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