FreeRDP
xf_monitor.c
1 
22 #include <freerdp/config.h>
23 
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <X11/Xlib.h>
28 #include <X11/Xutil.h>
29 
30 #include <winpr/assert.h>
31 #include <winpr/crt.h>
32 
33 #include <freerdp/log.h>
34 
35 #define TAG CLIENT_TAG("x11")
36 
37 #ifdef WITH_XINERAMA
38 #include <X11/extensions/Xinerama.h>
39 #endif
40 
41 #ifdef WITH_XRANDR
42 #include <X11/extensions/Xrandr.h>
43 #include <X11/extensions/randr.h>
44 
45 #if (RANDR_MAJOR * 100 + RANDR_MINOR) >= 105
46 #define USABLE_XRANDR
47 #endif
48 
49 #endif
50 
51 #include "xf_monitor.h"
52 
53 /* See MSDN Section on Multiple Display Monitors: http://msdn.microsoft.com/en-us/library/dd145071
54  */
55 
56 int xf_list_monitors(xfContext* xfc)
57 {
58  Display* display = NULL;
59  int major = 0;
60  int minor = 0;
61  int nmonitors = 0;
62  display = XOpenDisplay(NULL);
63 
64  if (!display)
65  {
66  WLog_ERR(TAG, "failed to open X display");
67  return -1;
68  }
69 
70 #if defined(USABLE_XRANDR)
71 
72  if (XRRQueryExtension(display, &major, &minor) &&
73  (XRRQueryVersion(display, &major, &minor) == True) && (major * 100 + minor >= 105))
74  {
75  XRRMonitorInfo* monitors =
76  XRRGetMonitors(display, DefaultRootWindow(display), 1, &nmonitors);
77 
78  for (int i = 0; i < nmonitors; i++)
79  {
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);
82  }
83 
84  XRRFreeMonitors(monitors);
85  }
86  else
87 #endif
88 #ifdef WITH_XINERAMA
89  if (XineramaQueryExtension(display, &major, &minor))
90  {
91  if (XineramaIsActive(display))
92  {
93  XineramaScreenInfo* screen = XineramaQueryScreens(display, &nmonitors);
94 
95  for (int i = 0; i < nmonitors; i++)
96  {
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);
99  }
100 
101  XFree(screen);
102  }
103  }
104  else
105 #else
106  {
107  Screen* screen = ScreenOfDisplay(display, DefaultScreen(display));
108  printf(" * [0] %dx%d\t+0+0\n", WidthOfScreen(screen), HeightOfScreen(screen));
109  }
110 
111 #endif
112  XCloseDisplay(display);
113  return 0;
114 }
115 
116 static BOOL xf_is_monitor_id_active(xfContext* xfc, UINT32 id)
117 {
118  const rdpSettings* settings = NULL;
119 
120  WINPR_ASSERT(xfc);
121 
122  settings = xfc->common.context.settings;
123  WINPR_ASSERT(settings);
124 
125  const UINT32 NumMonitorIds = freerdp_settings_get_uint32(settings, FreeRDP_NumMonitorIds);
126  if (NumMonitorIds == 0)
127  return TRUE;
128 
129  for (UINT32 index = 0; index < NumMonitorIds; index++)
130  {
131  const UINT32* cur = freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorIds, index);
132  if (cur && (*cur == id))
133  return TRUE;
134  }
135 
136  return FALSE;
137 }
138 
139 BOOL xf_detect_monitors(xfContext* xfc, UINT32* pMaxWidth, UINT32* pMaxHeight)
140 {
141  BOOL rc = FALSE;
142  UINT32 monitor_index = 0;
143  BOOL primaryMonitorFound = FALSE;
144  VIRTUAL_SCREEN* vscreen = NULL;
145  rdpSettings* settings = NULL;
146  int mouse_x = 0;
147  int mouse_y = 0;
148  int _dummy_i = 0;
149  Window _dummy_w = 0;
150  UINT32 current_monitor = 0;
151  Screen* screen = NULL;
152 #if defined WITH_XINERAMA || defined WITH_XRANDR
153  int major = 0;
154  int minor = 0;
155 #endif
156 #if defined(USABLE_XRANDR)
157  XRRMonitorInfo* rrmonitors = NULL;
158  BOOL useXRandr = FALSE;
159 #endif
160 
161  if (!xfc || !pMaxWidth || !pMaxHeight || !xfc->common.context.settings)
162  return FALSE;
163 
164  settings = xfc->common.context.settings;
165  vscreen = &xfc->vscreen;
166  *pMaxWidth = freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth);
167  *pMaxHeight = freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight);
168 
169  if (freerdp_settings_get_uint64(settings, FreeRDP_ParentWindowId) > 0)
170  {
171  xfc->workArea.x = 0;
172  xfc->workArea.y = 0;
173  xfc->workArea.width = freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth);
174  xfc->workArea.height = freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight);
175  return TRUE;
176  }
177 
178  /* get mouse location */
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;
182 
183 #if defined(USABLE_XRANDR)
184 
185  if (XRRQueryExtension(xfc->display, &major, &minor) &&
186  (XRRQueryVersion(xfc->display, &major, &minor) == True) && (major * 100 + minor >= 105))
187  {
188  int nmonitors = 0;
189  rrmonitors = XRRGetMonitors(xfc->display, DefaultRootWindow(xfc->display), 1, &nmonitors);
190 
191  if ((nmonitors < 0) || (nmonitors > 16))
192  vscreen->nmonitors = 0;
193  else
194  vscreen->nmonitors = (UINT32)nmonitors;
195 
196  if (vscreen->nmonitors)
197  {
198  for (UINT32 i = 0; i < vscreen->nmonitors; i++)
199  {
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;
207  }
208  }
209 
210  useXRandr = TRUE;
211  }
212  else
213 #endif
214 #ifdef WITH_XINERAMA
215  if (XineramaQueryExtension(xfc->display, &major, &minor) && XineramaIsActive(xfc->display))
216  {
217  int nmonitors = 0;
218  XineramaScreenInfo* screenInfo = XineramaQueryScreens(xfc->display, &nmonitors);
219 
220  if ((nmonitors < 0) || (nmonitors > 16))
221  vscreen->nmonitors = 0;
222  else
223  vscreen->nmonitors = (UINT32)nmonitors;
224 
225  if (vscreen->nmonitors)
226  {
227  for (UINT32 i = 0; i < vscreen->nmonitors; i++)
228  {
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;
234  }
235  }
236 
237  XFree(screenInfo);
238  }
239 
240 #endif
241  xfc->fullscreenMonitors.top = xfc->fullscreenMonitors.bottom = xfc->fullscreenMonitors.left =
242  xfc->fullscreenMonitors.right = 0;
243 
244  /* Determine which monitor that the mouse cursor is on */
245  if (vscreen->monitors)
246  {
247  for (UINT32 i = 0; i < vscreen->nmonitors; i++)
248  {
249  const MONITOR_INFO* monitor = &vscreen->monitors[i];
250 
251  if ((mouse_x >= monitor->area.left) && (mouse_x <= monitor->area.right) &&
252  (mouse_y >= monitor->area.top) && (mouse_y <= monitor->area.bottom))
253  {
254  current_monitor = i;
255  break;
256  }
257  }
258  }
259 
260  /*
261  Even for a single monitor, we need to calculate the virtual screen to support
262  window managers that do not implement all X window state hints.
263 
264  If the user did not request multiple monitor or is using workarea
265  without remote app, we force the number of monitors be 1 so later
266  the rest of the client don't end up using more monitors than the user desires.
267  */
268  if ((!freerdp_settings_get_bool(settings, FreeRDP_UseMultimon) &&
269  !freerdp_settings_get_bool(settings, FreeRDP_SpanMonitors)) ||
270  (freerdp_settings_get_bool(settings, FreeRDP_Workarea) &&
271  !freerdp_settings_get_bool(settings, FreeRDP_RemoteApplicationMode)))
272  {
273  /* If no monitors were specified on the command-line then set the current monitor as active
274  */
275  if (freerdp_settings_get_uint32(settings, FreeRDP_NumMonitorIds) == 0)
276  {
277  UINT32 id = current_monitor;
278  if (!freerdp_settings_set_pointer_len(settings, FreeRDP_MonitorIds, &id, 1))
279  goto fail;
280  }
281 
282  /* Always sets number of monitors from command-line to just 1.
283  * If the monitor is invalid then we will default back to current monitor
284  * later as a fallback. So, there is no need to validate command-line entry here.
285  */
286  if (!freerdp_settings_set_uint32(settings, FreeRDP_NumMonitorIds, 1))
287  goto fail;
288  }
289 
290  /* WORKAROUND: With Remote Application Mode - using NET_WM_WORKAREA
291  * causes issues with the ability to fully size the window vertically
292  * (the bottom of the window area is never updated). So, we just set
293  * the workArea to match the full Screen width/height.
294  */
295  if (freerdp_settings_get_bool(settings, FreeRDP_RemoteApplicationMode) || !xf_GetWorkArea(xfc))
296  {
297  /*
298  if only 1 monitor is enabled, use monitor area
299  this is required in case of a screen composed of more than one monitor
300  but user did not enable multimonitor
301  */
302  if ((freerdp_settings_get_uint32(settings, FreeRDP_NumMonitorIds) == 1) &&
303  (vscreen->nmonitors > current_monitor))
304  {
305  MONITOR_INFO* monitor = vscreen->monitors + current_monitor;
306 
307  if (!monitor)
308  goto fail;
309 
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;
314  }
315  else
316  {
317  xfc->workArea.x = 0;
318  xfc->workArea.y = 0;
319  xfc->workArea.width = WidthOfScreen(xfc->screen);
320  xfc->workArea.height = HeightOfScreen(xfc->screen);
321  }
322  }
323 
324  if (freerdp_settings_get_bool(settings, FreeRDP_Fullscreen))
325  {
326  *pMaxWidth = WidthOfScreen(xfc->screen);
327  *pMaxHeight = HeightOfScreen(xfc->screen);
328  }
329  else if (freerdp_settings_get_bool(settings, FreeRDP_Workarea))
330  {
331  *pMaxWidth = xfc->workArea.width;
332  *pMaxHeight = xfc->workArea.height;
333  }
334  else if (freerdp_settings_get_uint32(settings, FreeRDP_PercentScreen))
335  {
336  /* If we have specific monitor information then limit the PercentScreen value
337  * to only affect the current monitor vs. the entire desktop
338  */
339  if (vscreen->nmonitors > 0)
340  {
341  if (!vscreen->monitors)
342  goto fail;
343 
344  const MONITOR_INFO* vmonitor = &vscreen->monitors[current_monitor];
345  const RECTANGLE_16* area = &vmonitor->area;
346 
347  *pMaxWidth = area->right - area->left + 1;
348  *pMaxHeight = area->bottom - area->top + 1;
349 
350  if (freerdp_settings_get_bool(settings, FreeRDP_PercentScreenUseWidth))
351  *pMaxWidth = ((area->right - area->left + 1) *
352  freerdp_settings_get_uint32(settings, FreeRDP_PercentScreen)) /
353  100;
354 
355  if (freerdp_settings_get_bool(settings, FreeRDP_PercentScreenUseHeight))
356  *pMaxHeight = ((area->bottom - area->top + 1) *
357  freerdp_settings_get_uint32(settings, FreeRDP_PercentScreen)) /
358  100;
359  }
360  else
361  {
362  *pMaxWidth = xfc->workArea.width;
363  *pMaxHeight = xfc->workArea.height;
364 
365  if (freerdp_settings_get_bool(settings, FreeRDP_PercentScreenUseWidth))
366  *pMaxWidth = (xfc->workArea.width *
367  freerdp_settings_get_uint32(settings, FreeRDP_PercentScreen)) /
368  100;
369 
370  if (freerdp_settings_get_bool(settings, FreeRDP_PercentScreenUseHeight))
371  *pMaxHeight = (xfc->workArea.height *
372  freerdp_settings_get_uint32(settings, FreeRDP_PercentScreen)) /
373  100;
374  }
375  }
376  else if (freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth) &&
377  freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight))
378  {
379  *pMaxWidth = freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth);
380  *pMaxHeight = freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight);
381  }
382 
383  /* Create array of all active monitors by taking into account monitors requested on the
384  * command-line */
385  int nmonitors = 0;
386  {
387  UINT32 nr = 0;
388 
389  {
390  const UINT32* ids = freerdp_settings_get_pointer(settings, FreeRDP_MonitorIds);
391  if (ids)
392  nr = *ids;
393  }
394  for (UINT32 i = 0; i < vscreen->nmonitors; i++)
395  {
396  MONITOR_ATTRIBUTES* attrs = NULL;
397 
398  if (!xf_is_monitor_id_active(xfc, i))
399  continue;
400 
401  if (!vscreen->monitors)
402  goto fail;
403 
404  rdpMonitor* monitor = freerdp_settings_get_pointer_array_writable(
405  settings, FreeRDP_MonitorDefArray, nmonitors);
406  monitor->x = (vscreen->monitors[i].area.left *
407  (freerdp_settings_get_bool(settings, FreeRDP_PercentScreenUseWidth)
408  ? freerdp_settings_get_uint32(settings, FreeRDP_PercentScreen)
409  : 100)) /
410  100;
411  monitor->y = (vscreen->monitors[i].area.top *
412  (freerdp_settings_get_bool(settings, FreeRDP_PercentScreenUseHeight)
413  ? freerdp_settings_get_uint32(settings, FreeRDP_PercentScreen)
414  : 100)) /
415  100;
416  monitor->width =
417  ((vscreen->monitors[i].area.right - vscreen->monitors[i].area.left + 1) *
418  (freerdp_settings_get_bool(settings, FreeRDP_PercentScreenUseWidth)
419  ? freerdp_settings_get_uint32(settings, FreeRDP_PercentScreen)
420  : 100)) /
421  100;
422  monitor->height =
423  ((vscreen->monitors[i].area.bottom - vscreen->monitors[i].area.top + 1) *
424  (freerdp_settings_get_bool(settings, FreeRDP_PercentScreenUseWidth)
425  ? freerdp_settings_get_uint32(settings, FreeRDP_PercentScreen)
426  : 100)) /
427  100;
428  monitor->orig_screen = i;
429 #ifdef USABLE_XRANDR
430 
431  if (useXRandr && rrmonitors)
432  {
433  Rotation rot = 0;
434  Rotation ret = 0;
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;
440  }
441 
442 #endif
443 
444  if (i == nr)
445  {
446  monitor->is_primary = TRUE;
447  if (!freerdp_settings_set_uint32(settings, FreeRDP_MonitorLocalShiftX, monitor->x))
448  goto fail;
449  if (!freerdp_settings_set_uint32(settings, FreeRDP_MonitorLocalShiftY, monitor->y))
450  goto fail;
451  primaryMonitorFound = TRUE;
452  }
453 
454  nmonitors++;
455  }
456  }
457 
458  /* If no monitor is active(bogus command-line monitor specification) - then lets try to fallback
459  * to go fullscreen on the current monitor only */
460  if (nmonitors == 0 && vscreen->nmonitors > 0)
461  {
462  if (!vscreen->monitors)
463  goto fail;
464 
465  const MONITOR_INFO* vmonitor = &vscreen->monitors[current_monitor];
466  const RECTANGLE_16* area = &vmonitor->area;
467 
468  const INT32 width = area->right - area->left + 1;
469  const INT32 height = area->bottom - area->top + 1;
470  const INT32 maxw =
471  ((width < 0) || ((UINT32)width < *pMaxWidth)) ? width : (INT32)*pMaxWidth;
472  const INT32 maxh =
473  ((height < 0) || ((UINT32)height < *pMaxHeight)) ? width : (INT32)*pMaxHeight;
474 
475  rdpMonitor* monitor =
476  freerdp_settings_get_pointer_array_writable(settings, FreeRDP_MonitorDefArray, 0);
477  if (!monitor)
478  goto fail;
479 
480  monitor->x = area->left;
481  monitor->y = area->top;
482  monitor->width = maxw;
483  monitor->height = maxh;
484  monitor->orig_screen = current_monitor;
485  nmonitors = 1;
486  }
487 
488  if (!freerdp_settings_set_uint32(settings, FreeRDP_MonitorCount, nmonitors))
489  goto fail;
490 
491  /* If we have specific monitor information */
492  if (freerdp_settings_get_uint32(settings, FreeRDP_MonitorCount) > 0)
493  {
494  const rdpMonitor* cmonitor =
495  freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorDefArray, 0);
496  if (!cmonitor)
497  goto fail;
498 
499  /* Initialize bounding rectangle for all monitors */
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;
506 
507  /* Calculate bounding rectangle around all monitors to be used AND
508  * also set the Xinerama indices which define left/top/right/bottom monitors.
509  */
510  for (UINT32 i = 0; i < freerdp_settings_get_uint32(settings, FreeRDP_MonitorCount); i++)
511  {
512  rdpMonitor* monitor =
513  freerdp_settings_get_pointer_array_writable(settings, FreeRDP_MonitorDefArray, i);
514 
515  /* does the same as gdk_rectangle_union */
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);
520 
521  if (vX != destX)
522  xfc->fullscreenMonitors.left = monitor->orig_screen;
523 
524  if (vY != destY)
525  xfc->fullscreenMonitors.top = monitor->orig_screen;
526 
527  if (vR != destR)
528  xfc->fullscreenMonitors.right = monitor->orig_screen;
529 
530  if (vB != destB)
531  xfc->fullscreenMonitors.bottom = monitor->orig_screen;
532 
533  const UINT32 ps = freerdp_settings_get_uint32(settings, FreeRDP_PercentScreen);
534  WINPR_ASSERT(ps <= 100);
535 
536  const int psuw =
537  freerdp_settings_get_bool(settings, FreeRDP_PercentScreenUseWidth) ? (int)ps : 100;
538  const int psuh =
539  freerdp_settings_get_bool(settings, FreeRDP_PercentScreenUseHeight) ? (int)ps : 100;
540  vX = (destX * psuw) / 100;
541  vY = (destY * psuh) / 100;
542  vR = (destR * psuw) / 100;
543  vB = (destB * psuh) / 100;
544  }
545 
546  vscreen->area.left = 0;
547  vscreen->area.right = vR - vX - 1;
548  vscreen->area.top = 0;
549  vscreen->area.bottom = vB - vY - 1;
550 
551  if (freerdp_settings_get_bool(settings, FreeRDP_Workarea))
552  {
553  vscreen->area.top = xfc->workArea.y;
554  vscreen->area.bottom = xfc->workArea.height + xfc->workArea.y - 1;
555  }
556 
557  if (!primaryMonitorFound)
558  {
559  /* If we have a command line setting we should use it */
560  if (freerdp_settings_get_uint32(settings, FreeRDP_NumMonitorIds) > 0)
561  {
562  /* The first monitor is the first in the setting which should be used */
563  UINT32* ids =
564  freerdp_settings_get_pointer_array_writable(settings, FreeRDP_MonitorIds, 0);
565  if (ids)
566  monitor_index = *ids;
567  }
568  else
569  {
570  /* This is the same as when we would trust the Xinerama results..
571  and set the monitor index to zero.
572  The monitor listed with /list:monitor on index zero is always the primary
573  */
574  screen = DefaultScreenOfDisplay(xfc->display);
575  monitor_index = XScreenNumberOfScreen(screen);
576  }
577 
578  UINT32 j = monitor_index;
579  rdpMonitor* pmonitor =
580  freerdp_settings_get_pointer_array_writable(settings, FreeRDP_MonitorDefArray, j);
581 
582  /* If the "default" monitor is not 0,0 use it */
583  if ((pmonitor->x != 0) || (pmonitor->y != 0))
584  {
585  pmonitor->is_primary = TRUE;
586  if (!freerdp_settings_set_uint32(settings, FreeRDP_MonitorLocalShiftX, pmonitor->x))
587  goto fail;
588  if (!freerdp_settings_set_uint32(settings, FreeRDP_MonitorLocalShiftY, pmonitor->y))
589  goto fail;
590  }
591  else
592  {
593  /* Lets try to see if there is a monitor with a 0,0 coordinate and use it as a
594  * fallback*/
595  for (UINT32 i = 0; i < freerdp_settings_get_uint32(settings, FreeRDP_MonitorCount);
596  i++)
597  {
598  rdpMonitor* monitor = freerdp_settings_get_pointer_array_writable(
599  settings, FreeRDP_MonitorDefArray, i);
600  if (!primaryMonitorFound && monitor->x == 0 && monitor->y == 0)
601  {
602  monitor->is_primary = TRUE;
603  if (!freerdp_settings_set_uint32(settings, FreeRDP_MonitorLocalShiftX,
604  monitor->x))
605  goto fail;
606  if (!freerdp_settings_set_uint32(settings, FreeRDP_MonitorLocalShiftY,
607  monitor->y))
608  goto fail;
609  primaryMonitorFound = TRUE;
610  }
611  }
612  }
613  }
614 
615  /* Subtract monitor shift from monitor variables for server-side use.
616  * We maintain monitor shift value as Window requires the primary monitor to have a
617  * coordinate of 0,0 In some X configurations, no monitor may have a coordinate of 0,0. This
618  * can also be happen if the user requests specific monitors from the command-line as well.
619  * So, we make sure to translate our primary monitor's upper-left corner to 0,0 on the
620  * server.
621  */
622  for (UINT32 i = 0; i < freerdp_settings_get_uint32(settings, FreeRDP_MonitorCount); i++)
623  {
624  rdpMonitor* monitor =
625  freerdp_settings_get_pointer_array_writable(settings, FreeRDP_MonitorDefArray, i);
626  monitor->x =
627  monitor->x - freerdp_settings_get_uint32(settings, FreeRDP_MonitorLocalShiftX);
628  monitor->y =
629  monitor->y - freerdp_settings_get_uint32(settings, FreeRDP_MonitorLocalShiftY);
630  }
631 
632  /* Set the desktop width and height according to the bounding rectangle around the active
633  * monitors */
634  *pMaxWidth = MIN(*pMaxWidth, (UINT32)vscreen->area.right - vscreen->area.left + 1);
635  *pMaxHeight = MIN(*pMaxHeight, (UINT32)vscreen->area.bottom - vscreen->area.top + 1);
636  }
637 
638  /* some 2008 server freeze at logon if we announce support for monitor layout PDU with
639  * #monitors < 2. So let's announce it only if we have more than 1 monitor.
640  */
641  if (freerdp_settings_get_uint32(settings, FreeRDP_MonitorCount) > 1)
642  {
643  if (!freerdp_settings_set_bool(settings, FreeRDP_SupportMonitorLayoutPdu, TRUE))
644  goto fail;
645  }
646 
647  rc = TRUE;
648 fail:
649 #ifdef USABLE_XRANDR
650 
651  if (rrmonitors)
652  XRRFreeMonitors(rrmonitors);
653 
654 #endif
655  return rc;
656 }
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.