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