xfreerdp: when available use xrandr to get display infos
authorDavid Fort <contact@hardening-consulting.com>
Fri, 24 Nov 2017 13:06:35 +0000 (14:06 +0100)
committerDavid Fort <contact@hardening-consulting.com>
Wed, 29 Nov 2017 09:38:48 +0000 (10:38 +0100)
client/X11/CMakeLists.txt
client/X11/xf_monitor.c

index bde78f7..fdd5e9d 100644 (file)
@@ -145,6 +145,10 @@ set(XRENDER_FEATURE_TYPE "RECOMMENDED")
 set(XRENDER_FEATURE_PURPOSE "rendering")
 set(XRENDER_FEATURE_DESCRIPTION "X11 render extension") 
 
+set(XRANDR_FEATURE_TYPE "RECOMMENDED")
+set(XRANDR_FEATURE_PURPOSE "tracking output configuration")
+set(XRANDR_FEATURE_DESCRIPTION "X11 randr extension")
+
 set(XFIXES_FEATURE_TYPE "RECOMMENDED")
 set(XFIXES_FEATURE_PURPOSE "X11 xfixes extension")
 set(XFIXES_FEATURE_DESCRIPTION "Useful additions to the X11 core protocol")
@@ -156,6 +160,7 @@ find_feature(Xcursor ${XCURSOR_FEATURE_TYPE} ${XCURSOR_FEATURE_PURPOSE} ${XCURSO
 find_feature(Xv ${XV_FEATURE_TYPE} ${XV_FEATURE_PURPOSE} ${XV_FEATURE_DESCRIPTION})
 find_feature(Xi ${XI_FEATURE_TYPE} ${XI_FEATURE_PURPOSE} ${XI_FEATURE_DESCRIPTION})
 find_feature(Xrender ${XRENDER_FEATURE_TYPE} ${XRENDER_FEATURE_PURPOSE} ${XRENDER_FEATURE_DESCRIPTION})
+find_feature(XRandR ${XRANDR_FEATURE_TYPE} ${XRANDR_FEATURE_PURPOSE} ${XRANDR_FEATURE_DESCRIPTION})
 find_feature(Xfixes ${XFIXES_FEATURE_TYPE} ${XFIXES_FEATURE_PURPOSE} ${XFIXES_FEATURE_DESCRIPTION})
 
 if(WITH_XINERAMA)
@@ -194,6 +199,12 @@ if(WITH_XRENDER)
        set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${XRENDER_LIBRARIES})
 endif()
 
+if(NOT APPLE AND WITH_XRANDR)
+       add_definitions(-DWITH_XRANDR)
+       include_directories(${XRANDR_INCLUDE_DIRS})
+       set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${XRANDR_LIBRARIES})
+endif()
+
 if(WITH_XFIXES)
        add_definitions(-DWITH_XFIXES)
        include_directories(${XFIXES_INCLUDE_DIRS})
index ee8b696..47715a4 100644 (file)
@@ -3,6 +3,7 @@
  * X11 Monitor Handling
  *
  * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ * Copyright 2017 David Fort <contact@hardening-consulting.com>
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #include <X11/extensions/Xinerama.h>
 #endif
 
+#ifdef WITH_XRANDR
+#include <X11/extensions/Xrandr.h>
+#include <X11/extensions/randr.h>
+#endif
+
 #include "xf_monitor.h"
 
 /* See MSDN Section on Multiple Display Monitors: http://msdn.microsoft.com/en-us/library/dd145071 */
 
 int xf_list_monitors(xfContext* xfc)
 {
-#ifdef WITH_XINERAMA
        Display* display;
        int major, minor;
        int i, nmonitors = 0;
-       XineramaScreenInfo* screen = NULL;
-       display = XOpenDisplay(NULL);
 
+       display = XOpenDisplay(NULL);
        if (!display)
        {
                WLog_ERR(TAG, "failed to open X display");
                return -1;
        }
 
+#ifdef WITH_XRANDR
+       if (XRRQueryExtension(xfc->display, &major, &minor))
+       {
+               XRRMonitorInfo *monitors = XRRGetMonitors(xfc->display, DefaultRootWindow(xfc->display), 1, &nmonitors);
+
+               for (i = 0; i < nmonitors; i++)
+               {
+                       printf("      %s [%d] %hdx%hd\t+%hd+%hd\n",
+                                  monitors[i].primary ? "*" : " ", i,
+                                  monitors[i].width, monitors[i].height,
+                                  monitors[i].x, monitors[i].y);
+               }
+               XRRFreeMonitors(monitors);
+       } else
+#endif
+
+#ifdef WITH_XINERAMA
        if (XineramaQueryExtension(display, &major, &minor))
        {
                if (XineramaIsActive(display))
                {
-                       screen = XineramaQueryScreens(display, &nmonitors);
+                       XineramaScreenInfo* screen = XineramaQueryScreens(display, &nmonitors);
 
                        for (i = 0; i < nmonitors; i++)
                        {
@@ -72,25 +93,16 @@ int xf_list_monitors(xfContext* xfc)
 
                        XFree(screen);
                }
-       }
+       } else
 
-       XCloseDisplay(display);
 #else
-       Screen* screen;
-       Display* display;
-       display = XOpenDisplay(NULL);
-
-       if (!display)
        {
-               WLog_ERR(TAG, "failed to open X display");
-               return -1;
+               Screen* screen = ScreenOfDisplay(display, DefaultScreen(display));
+               printf("      * [0] %dx%d\t+0+0\n", WidthOfScreen(screen), HeightOfScreen(screen));
        }
+#endif
 
-       screen = ScreenOfDisplay(display, DefaultScreen(display));
-       printf("      * [0] %dx%d\t+0+0\n", WidthOfScreen(screen),
-              HeightOfScreen(screen));
        XCloseDisplay(display);
-#endif
        return 0;
 }
 
@@ -123,9 +135,8 @@ BOOL xf_detect_monitors(xfContext* xfc, UINT32* pMaxWidth, UINT32* pMaxHeight)
        Window _dummy_w;
        int current_monitor = 0;
        Screen* screen;
-#ifdef WITH_XINERAMA
+#if defined WITH_XINERAMA || defined WITH_XRANDR
        int major, minor;
-       XineramaScreenInfo* screenInfo = NULL;
 #endif
        vscreen = &xfc->vscreen;
        *pMaxWidth = settings->DesktopWidth;
@@ -137,41 +148,59 @@ BOOL xf_detect_monitors(xfContext* xfc, UINT32* pMaxWidth, UINT32* pMaxHeight)
                           &_dummy_i, &_dummy_i, (void*) &_dummy_i))
                mouse_x = mouse_y = 0;
 
-#ifdef WITH_XINERAMA
-
-       if (XineramaQueryExtension(xfc->display, &major, &minor))
+#ifdef WITH_XRANDR
+       if (XRRQueryExtension(xfc->display, &major, &minor))
        {
-               if (XineramaIsActive(xfc->display))
-               {
-                       screenInfo = XineramaQueryScreens(xfc->display, &vscreen->nmonitors);
+               XRRMonitorInfo *monitors = XRRGetMonitors(xfc->display, DefaultRootWindow(xfc->display), 1, &vscreen->nmonitors);
 
-                       if (vscreen->nmonitors > 16)
-                               vscreen->nmonitors = 0;
+               if (vscreen->nmonitors > 16)
+                       vscreen->nmonitors = 0;
 
-                       if (vscreen->nmonitors)
+               if (vscreen->nmonitors)
+               {
+                       for (i = 0; i < vscreen->nmonitors; i++)
                        {
-                               for (i = 0; i < vscreen->nmonitors; i++)
-                               {
-                                       vscreen->monitors[i].area.left = screenInfo[i].x_org;
-                                       vscreen->monitors[i].area.top = screenInfo[i].y_org;
-                                       vscreen->monitors[i].area.right = screenInfo[i].x_org + screenInfo[i].width - 1;
-                                       vscreen->monitors[i].area.bottom = screenInfo[i].y_org + screenInfo[i].height -
-                                                                          1;
-
-                                       /* Determine which monitor that the mouse cursor is on */
-                                       if ((mouse_x >= vscreen->monitors[i].area.left) &&
-                                           (mouse_x <= vscreen->monitors[i].area.right) &&
-                                           (mouse_y >= vscreen->monitors[i].area.top) &&
-                                           (mouse_y <= vscreen->monitors[i].area.bottom))
-                                               current_monitor = i;
-                               }
+                               vscreen->monitors[i].area.left = monitors[i].x;
+                               vscreen->monitors[i].area.top = monitors[i].y;
+                               vscreen->monitors[i].area.right = monitors[i].x + monitors[i].width - 1;
+                               vscreen->monitors[i].area.bottom = monitors[i].y + monitors[i].height - 1;
+                               vscreen->monitors[i].primary = monitors[i].primary > 0;
                        }
+               }
+               XRRFreeMonitors(monitors);
+       } else
+#endif
 
-                       XFree(screenInfo);
+#ifdef WITH_XINERAMA
+       if (XineramaQueryExtension(xfc->display, &major, &minor) && XineramaIsActive(xfc->display))
+       {
+               XineramaScreenInfo* screenInfo = XineramaQueryScreens(xfc->display, &vscreen->nmonitors);
+
+               if (vscreen->nmonitors > 16)
+                       vscreen->nmonitors = 0;
+
+               if (vscreen->nmonitors)
+               {
+                       for (i = 0; i < vscreen->nmonitors; i++)
+                       {
+                               vscreen->monitors[i].area.left = screenInfo[i].x_org;
+                               vscreen->monitors[i].area.top = screenInfo[i].y_org;
+                               vscreen->monitors[i].area.right = screenInfo[i].x_org + screenInfo[i].width - 1;
+                               vscreen->monitors[i].area.bottom = screenInfo[i].y_org + screenInfo[i].height - 1;
+
+                               /* Determine which monitor that the mouse cursor is on */
+                               if ((mouse_x >= vscreen->monitors[i].area.left) &&
+                                       (mouse_x <= vscreen->monitors[i].area.right) &&
+                                       (mouse_y >= vscreen->monitors[i].area.top) &&
+                                       (mouse_y <= vscreen->monitors[i].area.bottom))
+                                       current_monitor = i;
+                       }
                }
-       }
 
+               XFree(screenInfo);
+       }
 #endif
+
        xfc->fullscreenMonitors.top = xfc->fullscreenMonitors.bottom =
                                          xfc->fullscreenMonitors.left = xfc->fullscreenMonitors.right = 0;