Skip to content

Commit 567887f

Browse files
committed
[core,settings] Fix MONITOR_DEF settings
* Make FreeRDP_MonitorLocalShiftX and FreeRDP_MonitorLocalShiftY signed * Add function freerdp_settings_set_monitor_def_array_sorted to proplery align the MONITOR_DEF array according to RDP requirements
1 parent 1c7b291 commit 567887f

File tree

7 files changed

+174
-50
lines changed

7 files changed

+174
-50
lines changed

include/freerdp/settings.h

+21
Original file line numberDiff line numberDiff line change
@@ -752,6 +752,27 @@ extern "C"
752752
WINPR_ATTR_MALLOC(free, 1)
753753
FREERDP_API char* freerdp_settings_get_config_path(void);
754754

755+
/** @brief Sort monitor array according to:
756+
* 1. First monitor is at x/y 0/0 and is the primary monitor
757+
* 2. The primary monitor must be at 0/0, if not set
758+
* FreeRDP_MonitorLocalShiftX/FreeRDP_MonitorLocalShiftY
759+
*
760+
* The FreeRDP_MonitorLocalShiftX/FreeRDP_MonitorLocalShiftY is required to map the local
761+
* monitors / mouse / touch coordinates to the remote ones.
762+
*
763+
* @param settings The settings to set the monitors for
764+
* @param monitors The unsorted monitors array
765+
* @param count The number of monitors in the unsorted array
766+
*
767+
* @return \b TRUE if the configuration is valid (or could be corrected to a valid one), \b
768+
* FALSE otherwise.
769+
*
770+
* @version since 3.11.0
771+
*/
772+
FREERDP_API BOOL freerdp_settings_set_monitor_def_array_sorted(rdpSettings* settings,
773+
const rdpMonitor* monitors,
774+
size_t count);
775+
755776
#ifdef __cplusplus
756777
}
757778
#endif

include/freerdp/settings_types_private.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,8 @@ struct rdp_settings
160160
SETTINGS_DEPRECATED(ALIGN64 BOOL ListMonitors); /* 392 */
161161
SETTINGS_DEPRECATED(ALIGN64 UINT32* MonitorIds); /* 393 */
162162
SETTINGS_DEPRECATED(ALIGN64 UINT32 NumMonitorIds); /* 394 */
163-
SETTINGS_DEPRECATED(ALIGN64 UINT32 MonitorLocalShiftX); /*395 */
164-
SETTINGS_DEPRECATED(ALIGN64 UINT32 MonitorLocalShiftY); /* 396 */
163+
SETTINGS_DEPRECATED(ALIGN64 INT32 MonitorLocalShiftX); /*395 */
164+
SETTINGS_DEPRECATED(ALIGN64 INT32 MonitorLocalShiftY); /* 396 */
165165
SETTINGS_DEPRECATED(ALIGN64 BOOL HasMonitorAttributes); /* 397 */
166166
SETTINGS_DEPRECATED(ALIGN64 UINT32 MonitorFlags); /* 398 */
167167
SETTINGS_DEPRECATED(ALIGN64 UINT32 MonitorAttributeFlags); /* 399 */

libfreerdp/common/settings.c

+111
Original file line numberDiff line numberDiff line change
@@ -2257,3 +2257,114 @@ BOOL freerdp_settings_are_valid(const rdpSettings* settings)
22572257
{
22582258
return settings != NULL;
22592259
}
2260+
2261+
/* Function to sort rdpMonitor arrays:
2262+
* 1. first element is primary monitor
2263+
* 2. all others are sorted by coordinates of x/y
2264+
*/
2265+
static int sort_monitor_fn(const void* pva, const void* pvb)
2266+
{
2267+
const rdpMonitor* a = pva;
2268+
const rdpMonitor* b = pvb;
2269+
WINPR_ASSERT(a);
2270+
WINPR_ASSERT(b);
2271+
if (a->is_primary && b->is_primary)
2272+
return 0;
2273+
if (a->is_primary)
2274+
return -1;
2275+
if (b->is_primary)
2276+
return 1;
2277+
2278+
if (a->x != b->x)
2279+
return a->x - b->x;
2280+
if (a->y != b->y)
2281+
return a->y - b->y;
2282+
return 0;
2283+
}
2284+
2285+
BOOL freerdp_settings_set_monitor_def_array_sorted(rdpSettings* settings,
2286+
const rdpMonitor* monitors, size_t count)
2287+
{
2288+
WINPR_ASSERT(monitors || (count == 0));
2289+
if (count == 0)
2290+
{
2291+
if (!freerdp_settings_set_int32(settings, FreeRDP_MonitorLocalShiftX, 0))
2292+
return FALSE;
2293+
if (!freerdp_settings_set_int32(settings, FreeRDP_MonitorLocalShiftY, 0))
2294+
return FALSE;
2295+
if (!freerdp_settings_set_pointer_len(settings, FreeRDP_MonitorDefArray, NULL, 0))
2296+
return FALSE;
2297+
return freerdp_settings_set_uint32(settings, FreeRDP_MonitorCount, 0);
2298+
return TRUE;
2299+
}
2300+
2301+
// Find primary or alternatively the monitor at 0/0
2302+
const rdpMonitor* primary = NULL;
2303+
for (size_t x = 0; x < count; x++)
2304+
{
2305+
const rdpMonitor* cur = &monitors[x];
2306+
if (cur->is_primary)
2307+
{
2308+
primary = cur;
2309+
break;
2310+
}
2311+
}
2312+
if (!primary)
2313+
{
2314+
for (size_t x = 0; x < count; x++)
2315+
{
2316+
const rdpMonitor* cur = &monitors[x];
2317+
if ((cur->x == 0) && (cur->y == 0))
2318+
{
2319+
primary = cur;
2320+
break;
2321+
}
2322+
}
2323+
}
2324+
2325+
if (!primary)
2326+
{
2327+
WLog_ERR(TAG, "Could not find primary monitor, aborting");
2328+
return FALSE;
2329+
}
2330+
2331+
if (!freerdp_settings_set_pointer_len(settings, FreeRDP_MonitorDefArray, NULL, count))
2332+
return FALSE;
2333+
rdpMonitor* sorted = freerdp_settings_get_pointer_writable(settings, FreeRDP_MonitorDefArray);
2334+
WINPR_ASSERT(sorted);
2335+
2336+
size_t sortpos = 0;
2337+
2338+
/* Set primary. Ensure left/top is at 0/0 and flags contains MONITOR_PRIMARY */
2339+
sorted[sortpos] = *primary;
2340+
sorted[sortpos].x = 0;
2341+
sorted[sortpos].y = 0;
2342+
sorted[sortpos].is_primary = TRUE;
2343+
sortpos++;
2344+
2345+
/* Set monitor shift to original layout */
2346+
const INT32 offsetX = primary->x;
2347+
const INT32 offsetY = primary->y;
2348+
if (!freerdp_settings_set_int32(settings, FreeRDP_MonitorLocalShiftX, offsetX))
2349+
return FALSE;
2350+
if (!freerdp_settings_set_int32(settings, FreeRDP_MonitorLocalShiftY, offsetY))
2351+
return FALSE;
2352+
2353+
for (size_t x = 0; x < count; x++)
2354+
{
2355+
const rdpMonitor* cur = &monitors[x];
2356+
if (cur == primary)
2357+
continue;
2358+
2359+
rdpMonitor m = monitors[x];
2360+
m.x -= offsetX;
2361+
m.y -= offsetY;
2362+
sorted[sortpos++] = m;
2363+
}
2364+
2365+
// Sort remaining monitors by x/y ?
2366+
qsort(sorted, count, sizeof(rdpMonitor), sort_monitor_fn);
2367+
2368+
return freerdp_settings_set_uint32(settings, FreeRDP_MonitorCount,
2369+
WINPR_ASSERTING_INT_CAST(uint32_t, count));
2370+
}

libfreerdp/common/settings_getters.c

+14-14
Original file line numberDiff line numberDiff line change
@@ -1812,12 +1812,6 @@ UINT32 freerdp_settings_get_uint32(const rdpSettings* settings, FreeRDP_Settings
18121812
case FreeRDP_MonitorFlags:
18131813
return settings->MonitorFlags;
18141814

1815-
case FreeRDP_MonitorLocalShiftX:
1816-
return settings->MonitorLocalShiftX;
1817-
1818-
case FreeRDP_MonitorLocalShiftY:
1819-
return settings->MonitorLocalShiftY;
1820-
18211815
case FreeRDP_MultifragMaxRequestSize:
18221816
return settings->MultifragMaxRequestSize;
18231817

@@ -2277,14 +2271,6 @@ BOOL freerdp_settings_set_uint32(rdpSettings* settings, FreeRDP_Settings_Keys_UI
22772271
settings->MonitorFlags = cnv.c;
22782272
break;
22792273

2280-
case FreeRDP_MonitorLocalShiftX:
2281-
settings->MonitorLocalShiftX = cnv.c;
2282-
break;
2283-
2284-
case FreeRDP_MonitorLocalShiftY:
2285-
settings->MonitorLocalShiftY = cnv.c;
2286-
break;
2287-
22882274
case FreeRDP_MultifragMaxRequestSize:
22892275
settings->MultifragMaxRequestSize = cnv.c;
22902276
break;
@@ -2544,6 +2530,12 @@ INT32 freerdp_settings_get_int32(const rdpSettings* settings, FreeRDP_Settings_K
25442530

25452531
switch (id)
25462532
{
2533+
case FreeRDP_MonitorLocalShiftX:
2534+
return settings->MonitorLocalShiftX;
2535+
2536+
case FreeRDP_MonitorLocalShiftY:
2537+
return settings->MonitorLocalShiftY;
2538+
25472539
case FreeRDP_XPan:
25482540
return settings->XPan;
25492541

@@ -2574,6 +2566,14 @@ BOOL freerdp_settings_set_int32(rdpSettings* settings, FreeRDP_Settings_Keys_Int
25742566

25752567
switch (id)
25762568
{
2569+
case FreeRDP_MonitorLocalShiftX:
2570+
settings->MonitorLocalShiftX = cnv.c;
2571+
break;
2572+
2573+
case FreeRDP_MonitorLocalShiftY:
2574+
settings->MonitorLocalShiftY = cnv.c;
2575+
break;
2576+
25772577
case FreeRDP_XPan:
25782578
settings->XPan = cnv.c;
25792579
break;

libfreerdp/common/settings_str.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -362,8 +362,6 @@ static const struct settings_str_entry settings_map[] = {
362362
{ FreeRDP_MonitorCount, FREERDP_SETTINGS_TYPE_UINT32, "FreeRDP_MonitorCount" },
363363
{ FreeRDP_MonitorDefArraySize, FREERDP_SETTINGS_TYPE_UINT32, "FreeRDP_MonitorDefArraySize" },
364364
{ FreeRDP_MonitorFlags, FREERDP_SETTINGS_TYPE_UINT32, "FreeRDP_MonitorFlags" },
365-
{ FreeRDP_MonitorLocalShiftX, FREERDP_SETTINGS_TYPE_UINT32, "FreeRDP_MonitorLocalShiftX" },
366-
{ FreeRDP_MonitorLocalShiftY, FREERDP_SETTINGS_TYPE_UINT32, "FreeRDP_MonitorLocalShiftY" },
367365
{ FreeRDP_MultifragMaxRequestSize, FREERDP_SETTINGS_TYPE_UINT32,
368366
"FreeRDP_MultifragMaxRequestSize" },
369367
{ FreeRDP_MultitransportFlags, FREERDP_SETTINGS_TYPE_UINT32, "FreeRDP_MultitransportFlags" },
@@ -448,6 +446,8 @@ static const struct settings_str_entry settings_map[] = {
448446
{ FreeRDP_TlsSecLevel, FREERDP_SETTINGS_TYPE_UINT32, "FreeRDP_TlsSecLevel" },
449447
{ FreeRDP_VCChunkSize, FREERDP_SETTINGS_TYPE_UINT32, "FreeRDP_VCChunkSize" },
450448
{ FreeRDP_VCFlags, FREERDP_SETTINGS_TYPE_UINT32, "FreeRDP_VCFlags" },
449+
{ FreeRDP_MonitorLocalShiftX, FREERDP_SETTINGS_TYPE_INT32, "FreeRDP_MonitorLocalShiftX" },
450+
{ FreeRDP_MonitorLocalShiftY, FREERDP_SETTINGS_TYPE_INT32, "FreeRDP_MonitorLocalShiftY" },
451451
{ FreeRDP_XPan, FREERDP_SETTINGS_TYPE_INT32, "FreeRDP_XPan" },
452452
{ FreeRDP_YPan, FREERDP_SETTINGS_TYPE_INT32, "FreeRDP_YPan" },
453453
{ FreeRDP_ParentWindowId, FREERDP_SETTINGS_TYPE_UINT64, "FreeRDP_ParentWindowId" },

libfreerdp/core/settings.c

+22-30
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,7 @@ static BOOL freerdp_settings_client_monitors_check_primary_and_origin(const rdpS
606606
const UINT32 count = freerdp_settings_get_uint32(settings, FreeRDP_MonitorCount);
607607
BOOL havePrimary = FALSE;
608608
BOOL foundOrigin = FALSE;
609+
BOOL primaryIsOrigin = FALSE;
609610
BOOL rc = TRUE;
610611

611612
struct bounds_t bounds = { 0 };
@@ -644,6 +645,7 @@ static BOOL freerdp_settings_client_monitors_check_primary_and_origin(const rdpS
644645
rc = FALSE;
645646
}
646647
foundOrigin = TRUE;
648+
primaryIsOrigin = monitor->is_primary != 0;
647649
}
648650
}
649651

@@ -672,6 +674,11 @@ static BOOL freerdp_settings_client_monitors_check_primary_and_origin(const rdpS
672674
WLog_ERR(TAG, "Monitor configuration must start at 0/0 for first monitor!");
673675
rc = FALSE;
674676
}
677+
if (!primaryIsOrigin)
678+
{
679+
WLog_ERR(TAG, "Monitor configuration must start at 0/0 for primary monitor!");
680+
rc = FALSE;
681+
}
675682

676683
return rc;
677684
}
@@ -970,10 +977,10 @@ rdpSettings* freerdp_settings_new(DWORD flags)
970977
if (!freerdp_settings_set_pointer_len(settings, FreeRDP_MonitorDefArray, NULL, 32))
971978
goto out_fail;
972979

973-
if (!freerdp_settings_set_uint32(settings, FreeRDP_MonitorLocalShiftX, 0))
980+
if (!freerdp_settings_set_int32(settings, FreeRDP_MonitorLocalShiftX, 0))
974981
goto out_fail;
975982

976-
if (!freerdp_settings_set_uint32(settings, FreeRDP_MonitorLocalShiftY, 0))
983+
if (!freerdp_settings_set_int32(settings, FreeRDP_MonitorLocalShiftY, 0))
977984
goto out_fail;
978985

979986
if (!freerdp_settings_set_pointer_len(settings, FreeRDP_MonitorIds, NULL, 0))
@@ -1737,35 +1744,20 @@ BOOL freerdp_settings_enforce_monitor_exists(rdpSettings* settings)
17371744
if (!freerdp_settings_set_uint32(settings, FreeRDP_MonitorCount, 1))
17381745
return FALSE;
17391746

1740-
rdpMonitor* monitor =
1741-
freerdp_settings_get_pointer_array_writable(settings, FreeRDP_MonitorDefArray, 0);
1742-
if (!monitor)
1743-
return FALSE;
1744-
monitor->x = 0;
1745-
monitor->y = 0;
1746-
WINPR_ASSERT(width <= INT32_MAX);
1747-
monitor->width = (INT32)width;
1748-
WINPR_ASSERT(height <= INT32_MAX);
1749-
monitor->height = (INT32)height;
1750-
monitor->is_primary = TRUE;
1751-
monitor->orig_screen = 0;
1752-
monitor->attributes.physicalWidth = pwidth;
1753-
monitor->attributes.physicalHeight = pheight;
1754-
monitor->attributes.orientation = orientation;
1755-
monitor->attributes.desktopScaleFactor = desktopScaleFactor;
1756-
monitor->attributes.deviceScaleFactor = deviceScaleFactor;
1757-
}
1758-
else if (fullscreen || (multimon && (count == 1)))
1759-
{
1760-
/* not all platforms start primary monitor at 0/0, so enforce this to avoid issues with
1761-
* fullscreen mode */
1762-
rdpMonitor* monitor =
1763-
freerdp_settings_get_pointer_array_writable(settings, FreeRDP_MonitorDefArray, 0);
1764-
if (!monitor)
1747+
rdpMonitor monitor = { 0 };
1748+
monitor.x = 0;
1749+
monitor.y = 0;
1750+
monitor.width = WINPR_ASSERTING_INT_CAST(int32_t, width);
1751+
monitor.height = WINPR_ASSERTING_INT_CAST(int32_t, height);
1752+
monitor.is_primary = TRUE;
1753+
monitor.orig_screen = 0;
1754+
monitor.attributes.physicalWidth = pwidth;
1755+
monitor.attributes.physicalHeight = pheight;
1756+
monitor.attributes.orientation = orientation;
1757+
monitor.attributes.desktopScaleFactor = desktopScaleFactor;
1758+
monitor.attributes.deviceScaleFactor = deviceScaleFactor;
1759+
if (!freerdp_settings_set_monitor_def_array_sorted(settings, &monitor, 1))
17651760
return FALSE;
1766-
monitor->x = 0;
1767-
monitor->y = 0;
1768-
monitor->is_primary = TRUE;
17691761
}
17701762

17711763
return TRUE;

libfreerdp/core/test/settings_property_lists.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -281,8 +281,6 @@ static const size_t uint32_list_indices[] = {
281281
FreeRDP_MonitorCount,
282282
FreeRDP_MonitorDefArraySize,
283283
FreeRDP_MonitorFlags,
284-
FreeRDP_MonitorLocalShiftX,
285-
FreeRDP_MonitorLocalShiftY,
286284
FreeRDP_MultifragMaxRequestSize,
287285
FreeRDP_MultitransportFlags,
288286
FreeRDP_NSCodecColorLossLevel,
@@ -348,6 +346,8 @@ static const size_t uint32_list_indices[] = {
348346

349347
#define have_int32_list_indices
350348
static const size_t int32_list_indices[] = {
349+
FreeRDP_MonitorLocalShiftX,
350+
FreeRDP_MonitorLocalShiftY,
351351
FreeRDP_XPan,
352352
FreeRDP_YPan,
353353
};

0 commit comments

Comments
 (0)