22 #include <freerdp/config.h>
28 #include <X11/Xutil.h>
30 #include <winpr/assert.h>
31 #include <winpr/crt.h>
33 #include <freerdp/log.h>
35 #define TAG CLIENT_TAG("x11")
38 #include <X11/extensions/Xinerama.h>
42 #include <X11/extensions/Xrandr.h>
43 #include <X11/extensions/randr.h>
45 #if (RANDR_MAJOR * 100 + RANDR_MINOR) >= 105
51 #include "xf_monitor.h"
56 int xf_list_monitors(xfContext* xfc)
58 Display* display = NULL;
62 display = XOpenDisplay(NULL);
66 WLog_ERR(TAG,
"failed to open X display");
70 #if defined(USABLE_XRANDR)
72 if (XRRQueryExtension(display, &major, &minor) &&
73 (XRRQueryVersion(display, &major, &minor) == True) && (major * 100 + minor >= 105))
75 XRRMonitorInfo* monitors =
76 XRRGetMonitors(display, DefaultRootWindow(display), 1, &nmonitors);
78 for (
int i = 0; i < nmonitors; i++)
80 printf(
" %s [%d] %dx%d\t+%d+%d\n", monitors[i].primary ?
"*" :
" ", i,
81 monitors[i].width, monitors[i].height, monitors[i].x, monitors[i].y);
84 XRRFreeMonitors(monitors);
89 if (XineramaQueryExtension(display, &major, &minor))
91 if (XineramaIsActive(display))
93 XineramaScreenInfo* screen = XineramaQueryScreens(display, &nmonitors);
95 for (
int i = 0; i < nmonitors; i++)
97 printf(
" %s [%d] %hdx%hd\t+%hd+%hd\n", (i == 0) ?
"*" :
" ", i,
98 screen[i].width, screen[i].height, screen[i].x_org, screen[i].y_org);
107 Screen* screen = ScreenOfDisplay(display, DefaultScreen(display));
108 printf(
" * [0] %dx%d\t+0+0\n", WidthOfScreen(screen), HeightOfScreen(screen));
112 XCloseDisplay(display);
116 static BOOL xf_is_monitor_id_active(xfContext* xfc, UINT32
id)
118 const rdpSettings* settings = NULL;
122 settings = xfc->common.context.settings;
123 WINPR_ASSERT(settings);
126 if (NumMonitorIds == 0)
129 for (UINT32 index = 0; index < NumMonitorIds; index++)
131 const UINT32* cur = freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorIds, index);
132 if (cur && (*cur ==
id))
139 BOOL xf_detect_monitors(xfContext* xfc, UINT32* pMaxWidth, UINT32* pMaxHeight)
142 UINT32 monitor_index = 0;
143 BOOL primaryMonitorFound = FALSE;
144 VIRTUAL_SCREEN* vscreen = NULL;
145 rdpSettings* settings = NULL;
150 UINT32 current_monitor = 0;
151 Screen* screen = NULL;
152 #if defined WITH_XINERAMA || defined WITH_XRANDR
156 #if defined(USABLE_XRANDR)
157 XRRMonitorInfo* rrmonitors = NULL;
158 BOOL useXRandr = FALSE;
161 if (!xfc || !pMaxWidth || !pMaxHeight || !xfc->common.context.settings)
164 settings = xfc->common.context.settings;
165 vscreen = &xfc->vscreen;
179 if (!XQueryPointer(xfc->display, DefaultRootWindow(xfc->display), &_dummy_w, &_dummy_w,
180 &mouse_x, &mouse_y, &_dummy_i, &_dummy_i, (
void*)&_dummy_i))
181 mouse_x = mouse_y = 0;
183 #if defined(USABLE_XRANDR)
185 if (XRRQueryExtension(xfc->display, &major, &minor) &&
186 (XRRQueryVersion(xfc->display, &major, &minor) == True) && (major * 100 + minor >= 105))
189 rrmonitors = XRRGetMonitors(xfc->display, DefaultRootWindow(xfc->display), 1, &nmonitors);
191 if ((nmonitors < 0) || (nmonitors > 16))
192 vscreen->nmonitors = 0;
194 vscreen->nmonitors = (UINT32)nmonitors;
196 if (vscreen->nmonitors)
198 for (UINT32 i = 0; i < vscreen->nmonitors; i++)
200 MONITOR_INFO* cur_vscreen = &vscreen->monitors[i];
201 const XRRMonitorInfo* cur_monitor = &rrmonitors[i];
202 cur_vscreen->area.left = cur_monitor->x;
203 cur_vscreen->area.top = cur_monitor->y;
204 cur_vscreen->area.right = cur_monitor->x + cur_monitor->width - 1;
205 cur_vscreen->area.bottom = cur_monitor->y + cur_monitor->height - 1;
206 cur_vscreen->primary = cur_monitor->primary > 0;
215 if (XineramaQueryExtension(xfc->display, &major, &minor) && XineramaIsActive(xfc->display))
218 XineramaScreenInfo* screenInfo = XineramaQueryScreens(xfc->display, &nmonitors);
220 if ((nmonitors < 0) || (nmonitors > 16))
221 vscreen->nmonitors = 0;
223 vscreen->nmonitors = (UINT32)nmonitors;
225 if (vscreen->nmonitors)
227 for (UINT32 i = 0; i < vscreen->nmonitors; i++)
229 MONITOR_INFO* monitor = &vscreen->monitors[i];
230 monitor->area.left = screenInfo[i].x_org;
231 monitor->area.top = screenInfo[i].y_org;
232 monitor->area.right = screenInfo[i].x_org + screenInfo[i].width - 1;
233 monitor->area.bottom = screenInfo[i].y_org + screenInfo[i].height - 1;
241 xfc->fullscreenMonitors.top = xfc->fullscreenMonitors.bottom = xfc->fullscreenMonitors.left =
242 xfc->fullscreenMonitors.right = 0;
245 if (vscreen->monitors)
247 for (UINT32 i = 0; i < vscreen->nmonitors; i++)
249 const MONITOR_INFO* monitor = &vscreen->monitors[i];
251 if ((mouse_x >= monitor->area.left) && (mouse_x <= monitor->area.right) &&
252 (mouse_y >= monitor->area.top) && (mouse_y <= monitor->area.bottom))
277 UINT32
id = current_monitor;
303 (vscreen->nmonitors > current_monitor))
305 MONITOR_INFO* monitor = vscreen->monitors + current_monitor;
310 xfc->workArea.x = monitor->area.left;
311 xfc->workArea.y = monitor->area.top;
312 xfc->workArea.width = monitor->area.right - monitor->area.left + 1;
313 xfc->workArea.height = monitor->area.bottom - monitor->area.top + 1;
319 xfc->workArea.width = WidthOfScreen(xfc->screen);
320 xfc->workArea.height = HeightOfScreen(xfc->screen);
326 *pMaxWidth = WidthOfScreen(xfc->screen);
327 *pMaxHeight = HeightOfScreen(xfc->screen);
331 *pMaxWidth = xfc->workArea.width;
332 *pMaxHeight = xfc->workArea.height;
339 if (vscreen->nmonitors > 0)
341 if (!vscreen->monitors)
344 const MONITOR_INFO* vmonitor = &vscreen->monitors[current_monitor];
347 *pMaxWidth = area->right - area->left + 1;
348 *pMaxHeight = area->bottom - area->top + 1;
351 *pMaxWidth = ((area->right - area->left + 1) *
356 *pMaxHeight = ((area->bottom - area->top + 1) *
362 *pMaxWidth = xfc->workArea.width;
363 *pMaxHeight = xfc->workArea.height;
366 *pMaxWidth = (xfc->workArea.width *
371 *pMaxHeight = (xfc->workArea.height *
394 for (UINT32 i = 0; i < vscreen->nmonitors; i++)
398 if (!xf_is_monitor_id_active(xfc, i))
401 if (!vscreen->monitors)
404 rdpMonitor* monitor = freerdp_settings_get_pointer_array_writable(
405 settings, FreeRDP_MonitorDefArray, nmonitors);
406 monitor->x = (vscreen->monitors[i].area.left *
411 monitor->y = (vscreen->monitors[i].area.top *
417 ((vscreen->monitors[i].area.right - vscreen->monitors[i].area.left + 1) *
423 ((vscreen->monitors[i].area.bottom - vscreen->monitors[i].area.top + 1) *
428 monitor->orig_screen = i;
431 if (useXRandr && rrmonitors)
435 attrs = &monitor->attributes;
436 attrs->physicalWidth = rrmonitors[i].mwidth;
437 attrs->physicalHeight = rrmonitors[i].mheight;
438 ret = XRRRotations(xfc->display, i, &rot);
439 attrs->orientation = ret;
446 monitor->is_primary = TRUE;
451 primaryMonitorFound = TRUE;
460 if (nmonitors == 0 && vscreen->nmonitors > 0)
462 if (!vscreen->monitors)
465 const MONITOR_INFO* vmonitor = &vscreen->monitors[current_monitor];
468 const INT32 width = area->right - area->left + 1;
469 const INT32 height = area->bottom - area->top + 1;
471 ((width < 0) || ((UINT32)width < *pMaxWidth)) ? width : (INT32)*pMaxWidth;
473 ((height < 0) || ((UINT32)height < *pMaxHeight)) ? width : (INT32)*pMaxHeight;
476 freerdp_settings_get_pointer_array_writable(settings, FreeRDP_MonitorDefArray, 0);
480 monitor->x = area->left;
481 monitor->y = area->top;
482 monitor->width = maxw;
483 monitor->height = maxh;
484 monitor->orig_screen = current_monitor;
495 freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorDefArray, 0);
500 int vX = cmonitor->x;
501 int vY = cmonitor->y;
502 int vR = vX + cmonitor->width;
503 int vB = vY + cmonitor->height;
504 xfc->fullscreenMonitors.top = xfc->fullscreenMonitors.bottom =
505 xfc->fullscreenMonitors.left = xfc->fullscreenMonitors.right = cmonitor->orig_screen;
513 freerdp_settings_get_pointer_array_writable(settings, FreeRDP_MonitorDefArray, i);
516 int destX = MIN(vX, monitor->x);
517 int destY = MIN(vY, monitor->y);
518 int destR = MAX(vR, monitor->x + monitor->width);
519 int destB = MAX(vB, monitor->y + monitor->height);
522 xfc->fullscreenMonitors.left = monitor->orig_screen;
525 xfc->fullscreenMonitors.top = monitor->orig_screen;
528 xfc->fullscreenMonitors.right = monitor->orig_screen;
531 xfc->fullscreenMonitors.bottom = monitor->orig_screen;
534 WINPR_ASSERT(ps <= 100);
540 vX = (destX * psuw) / 100;
541 vY = (destY * psuh) / 100;
542 vR = (destR * psuw) / 100;
543 vB = (destB * psuh) / 100;
546 vscreen->area.left = 0;
547 vscreen->area.right = vR - vX - 1;
548 vscreen->area.top = 0;
549 vscreen->area.bottom = vB - vY - 1;
553 vscreen->area.top = xfc->workArea.y;
554 vscreen->area.bottom = xfc->workArea.height + xfc->workArea.y - 1;
557 if (!primaryMonitorFound)
564 freerdp_settings_get_pointer_array_writable(settings, FreeRDP_MonitorIds, 0);
566 monitor_index = *ids;
574 screen = DefaultScreenOfDisplay(xfc->display);
575 monitor_index = XScreenNumberOfScreen(screen);
578 UINT32 j = monitor_index;
580 freerdp_settings_get_pointer_array_writable(settings, FreeRDP_MonitorDefArray, j);
583 if ((pmonitor->x != 0) || (pmonitor->y != 0))
585 pmonitor->is_primary = TRUE;
598 rdpMonitor* monitor = freerdp_settings_get_pointer_array_writable(
599 settings, FreeRDP_MonitorDefArray, i);
600 if (!primaryMonitorFound && monitor->x == 0 && monitor->y == 0)
602 monitor->is_primary = TRUE;
609 primaryMonitorFound = TRUE;
625 freerdp_settings_get_pointer_array_writable(settings, FreeRDP_MonitorDefArray, i);
634 *pMaxWidth = MIN(*pMaxWidth, (UINT32)vscreen->area.right - vscreen->area.left + 1);
635 *pMaxHeight = MIN(*pMaxHeight, (UINT32)vscreen->area.bottom - vscreen->area.top + 1);
652 XRRFreeMonitors(rrmonitors);
FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.
FREERDP_API const void * freerdp_settings_get_pointer(const rdpSettings *settings, FreeRDP_Settings_Keys_Pointer id)
Returns a immutable pointer settings value.
FREERDP_API UINT64 freerdp_settings_get_uint64(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt64 id)
Returns a UINT64 settings value.
FREERDP_API BOOL freerdp_settings_set_pointer_len(rdpSettings *settings, FreeRDP_Settings_Keys_Pointer id, const void *data, size_t len)
Set a pointer to value data.
FREERDP_API BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 param)
Sets a UINT32 settings value.
FREERDP_API BOOL freerdp_settings_set_bool(rdpSettings *settings, FreeRDP_Settings_Keys_Bool id, BOOL param)
Sets a BOOL settings value.