diff --git a/channels/rdpgfx/client/rdpgfx_main.c b/channels/rdpgfx/client/rdpgfx_main.c index 288b583dc..553a2fc0e 100644 --- a/channels/rdpgfx/client/rdpgfx_main.c +++ b/channels/rdpgfx/client/rdpgfx_main.c @@ -508,7 +508,6 @@ fail: */ static UINT rdpgfx_recv_reset_graphics_pdu(GENERIC_CHANNEL_CALLBACK* callback, wStream* s) { - MONITOR_DEF* monitor = NULL; RDPGFX_RESET_GRAPHICS_PDU pdu = { 0 }; WINPR_ASSERT(callback); @@ -540,7 +539,7 @@ static UINT rdpgfx_recv_reset_graphics_pdu(GENERIC_CHANNEL_CALLBACK* callback, w for (UINT32 index = 0; index < pdu.monitorCount; index++) { - monitor = &(pdu.monitorDefArray[index]); + MONITOR_DEF* monitor = &(pdu.monitorDefArray[index]); Stream_Read_INT32(s, monitor->left); /* left (4 bytes) */ Stream_Read_INT32(s, monitor->top); /* top (4 bytes) */ Stream_Read_INT32(s, monitor->right); /* right (4 bytes) */ @@ -570,7 +569,7 @@ static UINT rdpgfx_recv_reset_graphics_pdu(GENERIC_CHANNEL_CALLBACK* callback, w #if defined(WITH_DEBUG_RDPGFX) for (UINT32 index = 0; index < pdu.monitorCount; index++) { - monitor = &(pdu.monitorDefArray[index]); + MONITOR_DEF* monitor = &(pdu.monitorDefArray[index]); DEBUG_RDPGFX(gfx->log, "RecvResetGraphicsPdu: monitor left:%" PRIi32 " top:%" PRIi32 " right:%" PRIi32 " bottom:%" PRIi32 " flags:0x%" PRIx32 "", diff --git a/client/SDL/SDL2/sdl_monitor.cpp b/client/SDL/SDL2/sdl_monitor.cpp index e60edd82f..57d598153 100644 --- a/client/SDL/SDL2/sdl_monitor.cpp +++ b/client/SDL/SDL2/sdl_monitor.cpp @@ -196,10 +196,7 @@ static BOOL sdl_apply_display_properties(SdlContext* sdl) return TRUE; const UINT32 numIds = freerdp_settings_get_uint32(settings, FreeRDP_NumMonitorIds); - if (!freerdp_settings_set_pointer_len(settings, FreeRDP_MonitorDefArray, nullptr, numIds)) - return FALSE; - if (!freerdp_settings_set_uint32(settings, FreeRDP_MonitorCount, numIds)) - return FALSE; + std::vector monitors; for (UINT32 x = 0; x < numIds; x++) { @@ -265,26 +262,25 @@ static BOOL sdl_apply_display_properties(SdlContext* sdl) const UINT32 rdp_orientation = ORIENTATION_LANDSCAPE; #endif - auto monitor = static_cast( - freerdp_settings_get_pointer_array_writable(settings, FreeRDP_MonitorDefArray, x)); - WINPR_ASSERT(monitor); + rdpMonitor monitor = {}; /* windows uses 96 dpi as 'default' and the scale factors are in percent. */ const auto factor = ddpi / 96.0f * 100.0f; - monitor->orig_screen = x; - monitor->x = rect.x; - monitor->y = rect.y; - monitor->width = rect.w; - monitor->height = rect.h; - monitor->is_primary = x == 0; - monitor->attributes.desktopScaleFactor = static_cast(factor); - monitor->attributes.deviceScaleFactor = 100; - monitor->attributes.orientation = rdp_orientation; - monitor->attributes.physicalWidth = scale(WINPR_ASSERTING_INT_CAST(uint32_t, rect.w), hdpi); - monitor->attributes.physicalHeight = - scale(WINPR_ASSERTING_INT_CAST(uint32_t, rect.h), vdpi); + monitor.orig_screen = x; + monitor.x = rect.x; + monitor.y = rect.y; + monitor.width = rect.w; + monitor.height = rect.h; + monitor.is_primary = x == 0; + monitor.attributes.desktopScaleFactor = static_cast(factor); + monitor.attributes.deviceScaleFactor = 100; + monitor.attributes.orientation = rdp_orientation; + monitor.attributes.physicalWidth = scale(WINPR_ASSERTING_INT_CAST(uint32_t, rect.w), hdpi); + monitor.attributes.physicalHeight = scale(WINPR_ASSERTING_INT_CAST(uint32_t, rect.h), vdpi); + monitors.emplace_back(monitor); } - return TRUE; + return freerdp_settings_set_monitor_def_array_sorted(settings, monitors.data(), + monitors.size()); } static BOOL sdl_detect_single_window(SdlContext* sdl, UINT32* pMaxWidth, UINT32* pMaxHeight) diff --git a/client/SDL/SDL3/sdl_monitor.cpp b/client/SDL/SDL3/sdl_monitor.cpp index 41da479c7..8ca830553 100644 --- a/client/SDL/SDL3/sdl_monitor.cpp +++ b/client/SDL/SDL3/sdl_monitor.cpp @@ -196,10 +196,7 @@ static BOOL sdl_apply_display_properties(SdlContext* sdl) return TRUE; const UINT32 numIds = freerdp_settings_get_uint32(settings, FreeRDP_NumMonitorIds); - if (!freerdp_settings_set_pointer_len(settings, FreeRDP_MonitorDefArray, nullptr, numIds)) - return FALSE; - if (!freerdp_settings_set_uint32(settings, FreeRDP_MonitorCount, numIds)) - return FALSE; + std::vector monitors; for (UINT32 x = 0; x < numIds; x++) { @@ -260,26 +257,25 @@ static BOOL sdl_apply_display_properties(SdlContext* sdl) SDL_GetCurrentDisplayOrientation(WINPR_ASSERTING_INT_CAST(uint32_t, *id)); const UINT32 rdp_orientation = sdl_orientaion_to_rdp(orientation); - auto monitor = static_cast( - freerdp_settings_get_pointer_array_writable(settings, FreeRDP_MonitorDefArray, x)); - WINPR_ASSERT(monitor); + rdpMonitor monitor = {}; /* windows uses 96 dpi as 'default' and the scale factors are in percent. */ const auto factor = dpi / 96.0f * 100.0f; - monitor->orig_screen = x; - monitor->x = rect.x; - monitor->y = rect.y; - monitor->width = rect.w; - monitor->height = rect.h; - monitor->is_primary = x == 0; - monitor->attributes.desktopScaleFactor = static_cast(factor); - monitor->attributes.deviceScaleFactor = 100; - monitor->attributes.orientation = rdp_orientation; - monitor->attributes.physicalWidth = scale(WINPR_ASSERTING_INT_CAST(uint32_t, rect.w), hdpi); - monitor->attributes.physicalHeight = - scale(WINPR_ASSERTING_INT_CAST(uint32_t, rect.h), vdpi); + monitor.orig_screen = x; + monitor.x = rect.x; + monitor.y = rect.y; + monitor.width = rect.w; + monitor.height = rect.h; + monitor.is_primary = x == 0; + monitor.attributes.desktopScaleFactor = static_cast(factor); + monitor.attributes.deviceScaleFactor = 100; + monitor.attributes.orientation = rdp_orientation; + monitor.attributes.physicalWidth = scale(WINPR_ASSERTING_INT_CAST(uint32_t, rect.w), hdpi); + monitor.attributes.physicalHeight = scale(WINPR_ASSERTING_INT_CAST(uint32_t, rect.h), vdpi); + monitors.emplace_back(monitor); } - return TRUE; + return freerdp_settings_set_monitor_def_array_sorted(settings, monitors.data(), + monitors.size()); } static BOOL sdl_detect_single_window(SdlContext* sdl, UINT32* pMaxWidth, UINT32* pMaxHeight) diff --git a/client/X11/xf_monitor.c b/client/X11/xf_monitor.c index db647f534..1ee14d7fc 100644 --- a/client/X11/xf_monitor.c +++ b/client/X11/xf_monitor.c @@ -56,11 +56,12 @@ int xf_list_monitors(xfContext* xfc) { - Display* display = NULL; + WINPR_UNUSED(xfc); + int major = 0; int minor = 0; int nmonitors = 0; - display = XOpenDisplay(NULL); + Display* display = XOpenDisplay(NULL); if (!display) { @@ -142,8 +143,6 @@ BOOL xf_detect_monitors(xfContext* xfc, UINT32* pMaxWidth, UINT32* pMaxHeight) BOOL rc = FALSE; UINT32 monitor_index = 0; BOOL primaryMonitorFound = FALSE; - VIRTUAL_SCREEN* vscreen = NULL; - rdpSettings* settings = NULL; int mouse_x = 0; int mouse_y = 0; int _dummy_i = 0; @@ -162,8 +161,9 @@ BOOL xf_detect_monitors(xfContext* xfc, UINT32* pMaxWidth, UINT32* pMaxHeight) if (!xfc || !pMaxWidth || !pMaxHeight || !xfc->common.context.settings) return FALSE; - settings = xfc->common.context.settings; - vscreen = &xfc->vscreen; + rdpSettings* settings = xfc->common.context.settings; + VIRTUAL_SCREEN* vscreen = &xfc->vscreen; + *pMaxWidth = freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth); *pMaxHeight = freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight); @@ -244,8 +244,15 @@ BOOL xf_detect_monitors(xfContext* xfc, UINT32* pMaxWidth, UINT32* pMaxHeight) } #endif - xfc->fullscreenMonitors.top = xfc->fullscreenMonitors.bottom = xfc->fullscreenMonitors.left = - xfc->fullscreenMonitors.right = 0; + + rdpMonitor* rdpmonitors = calloc(vscreen->nmonitors + 1, sizeof(rdpMonitor)); + if (!rdpmonitors) + goto fail; + + xfc->fullscreenMonitors.top = 0; + xfc->fullscreenMonitors.bottom = 0; + xfc->fullscreenMonitors.left = 0; + xfc->fullscreenMonitors.right = 0; /* Determine which monitor that the mouse cursor is on */ if (vscreen->monitors) @@ -388,7 +395,7 @@ BOOL xf_detect_monitors(xfContext* xfc, UINT32* pMaxWidth, UINT32* pMaxHeight) /* Create array of all active monitors by taking into account monitors requested on the * command-line */ - int nmonitors = 0; + size_t nmonitors = 0; { UINT32 nr = 0; @@ -407,8 +414,7 @@ BOOL xf_detect_monitors(xfContext* xfc, UINT32* pMaxWidth, UINT32* pMaxHeight) if (!vscreen->monitors) goto fail; - rdpMonitor* monitor = freerdp_settings_get_pointer_array_writable( - settings, FreeRDP_MonitorDefArray, WINPR_ASSERTING_INT_CAST(size_t, nmonitors)); + rdpMonitor* monitor = &rdpmonitors[nmonitors]; monitor->x = WINPR_ASSERTING_INT_CAST( int32_t, vscreen->monitors[i].area.left*( @@ -458,12 +464,6 @@ BOOL xf_detect_monitors(xfContext* xfc, UINT32* pMaxWidth, UINT32* pMaxHeight) if (i == nr) { monitor->is_primary = TRUE; - if (!freerdp_settings_set_uint32(settings, FreeRDP_MonitorLocalShiftX, - WINPR_ASSERTING_INT_CAST(uint32_t, monitor->x))) - goto fail; - if (!freerdp_settings_set_uint32(settings, FreeRDP_MonitorLocalShiftY, - WINPR_ASSERTING_INT_CAST(uint32_t, monitor->y))) - goto fail; primaryMonitorFound = TRUE; } @@ -473,7 +473,7 @@ BOOL xf_detect_monitors(xfContext* xfc, UINT32* pMaxWidth, UINT32* pMaxHeight) /* If no monitor is active(bogus command-line monitor specification) - then lets try to fallback * to go fullscreen on the current monitor only */ - if (nmonitors == 0 && vscreen->nmonitors > 0) + if ((nmonitors == 0) && (vscreen->nmonitors > 0)) { if (!vscreen->monitors) goto fail; @@ -488,8 +488,7 @@ BOOL xf_detect_monitors(xfContext* xfc, UINT32* pMaxWidth, UINT32* pMaxHeight) const INT32 maxh = ((height < 0) || ((UINT32)height < *pMaxHeight)) ? width : (INT32)*pMaxHeight; - rdpMonitor* monitor = - freerdp_settings_get_pointer_array_writable(settings, FreeRDP_MonitorDefArray, 0); + rdpMonitor* monitor = &rdpmonitors[0]; if (!monitor) goto fail; @@ -508,8 +507,7 @@ BOOL xf_detect_monitors(xfContext* xfc, UINT32* pMaxWidth, UINT32* pMaxHeight) /* If we have specific monitor information */ if (freerdp_settings_get_uint32(settings, FreeRDP_MonitorCount) > 0) { - const rdpMonitor* cmonitor = - freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorDefArray, 0); + const rdpMonitor* cmonitor = &rdpmonitors[0]; if (!cmonitor) goto fail; @@ -518,34 +516,37 @@ BOOL xf_detect_monitors(xfContext* xfc, UINT32* pMaxWidth, UINT32* pMaxHeight) int vY = cmonitor->y; int vR = vX + cmonitor->width; int vB = vY + cmonitor->height; - xfc->fullscreenMonitors.top = xfc->fullscreenMonitors.bottom = - xfc->fullscreenMonitors.left = xfc->fullscreenMonitors.right = cmonitor->orig_screen; + const int32_t corig = WINPR_ASSERTING_INT_CAST(int32_t, cmonitor->orig_screen); + xfc->fullscreenMonitors.top = corig; + xfc->fullscreenMonitors.bottom = corig; + xfc->fullscreenMonitors.left = corig; + xfc->fullscreenMonitors.right = corig; /* Calculate bounding rectangle around all monitors to be used AND * also set the Xinerama indices which define left/top/right/bottom monitors. */ for (UINT32 i = 0; i < freerdp_settings_get_uint32(settings, FreeRDP_MonitorCount); i++) { - rdpMonitor* monitor = - freerdp_settings_get_pointer_array_writable(settings, FreeRDP_MonitorDefArray, i); + rdpMonitor* monitor = &rdpmonitors[i]; /* does the same as gdk_rectangle_union */ - int destX = MIN(vX, monitor->x); - int destY = MIN(vY, monitor->y); - int destR = MAX(vR, monitor->x + monitor->width); - int destB = MAX(vB, monitor->y + monitor->height); + const int destX = MIN(vX, monitor->x); + const int destY = MIN(vY, monitor->y); + const int destR = MAX(vR, monitor->x + monitor->width); + const int destB = MAX(vB, monitor->y + monitor->height); + const int32_t orig = WINPR_ASSERTING_INT_CAST(int32_t, monitor->orig_screen); if (vX != destX) - xfc->fullscreenMonitors.left = monitor->orig_screen; + xfc->fullscreenMonitors.left = orig; if (vY != destY) - xfc->fullscreenMonitors.top = monitor->orig_screen; + xfc->fullscreenMonitors.top = orig; if (vR != destR) - xfc->fullscreenMonitors.right = monitor->orig_screen; + xfc->fullscreenMonitors.right = orig; if (vB != destB) - xfc->fullscreenMonitors.bottom = monitor->orig_screen; + xfc->fullscreenMonitors.bottom = orig; const UINT32 ps = freerdp_settings_get_uint32(settings, FreeRDP_PercentScreen); WINPR_ASSERT(ps <= 100); @@ -596,19 +597,12 @@ BOOL xf_detect_monitors(xfContext* xfc, UINT32* pMaxWidth, UINT32* pMaxHeight) } UINT32 j = monitor_index; - rdpMonitor* pmonitor = - freerdp_settings_get_pointer_array_writable(settings, FreeRDP_MonitorDefArray, j); + rdpMonitor* pmonitor = &rdpmonitors[j]; /* If the "default" monitor is not 0,0 use it */ if ((pmonitor->x != 0) || (pmonitor->y != 0)) { pmonitor->is_primary = TRUE; - if (!freerdp_settings_set_uint32(settings, FreeRDP_MonitorLocalShiftX, - WINPR_ASSERTING_INT_CAST(uint32_t, pmonitor->x))) - goto fail; - if (!freerdp_settings_set_uint32(settings, FreeRDP_MonitorLocalShiftY, - WINPR_ASSERTING_INT_CAST(uint32_t, pmonitor->y))) - goto fail; } else { @@ -617,46 +611,16 @@ BOOL xf_detect_monitors(xfContext* xfc, UINT32* pMaxWidth, UINT32* pMaxHeight) for (UINT32 i = 0; i < freerdp_settings_get_uint32(settings, FreeRDP_MonitorCount); i++) { - rdpMonitor* monitor = freerdp_settings_get_pointer_array_writable( - settings, FreeRDP_MonitorDefArray, i); + rdpMonitor* monitor = &rdpmonitors[i]; if (!primaryMonitorFound && monitor->x == 0 && monitor->y == 0) { monitor->is_primary = TRUE; - if (!freerdp_settings_set_uint32( - settings, FreeRDP_MonitorLocalShiftX, - WINPR_ASSERTING_INT_CAST(uint32_t, monitor->x))) - goto fail; - if (!freerdp_settings_set_uint32( - settings, FreeRDP_MonitorLocalShiftY, - WINPR_ASSERTING_INT_CAST(uint32_t, monitor->y))) - goto fail; primaryMonitorFound = TRUE; } } } } - /* Subtract monitor shift from monitor variables for server-side use. - * We maintain monitor shift value as Window requires the primary monitor to have a - * coordinate of 0,0 In some X configurations, no monitor may have a coordinate of 0,0. This - * can also be happen if the user requests specific monitors from the command-line as well. - * So, we make sure to translate our primary monitor's upper-left corner to 0,0 on the - * server. - */ - for (UINT32 i = 0; i < freerdp_settings_get_uint32(settings, FreeRDP_MonitorCount); i++) - { - rdpMonitor* monitor = - freerdp_settings_get_pointer_array_writable(settings, FreeRDP_MonitorDefArray, i); - monitor->x = - monitor->x - - WINPR_ASSERTING_INT_CAST( - int32_t, freerdp_settings_get_uint32(settings, FreeRDP_MonitorLocalShiftX)); - monitor->y = - monitor->y - - WINPR_ASSERTING_INT_CAST( - int32_t, freerdp_settings_get_uint32(settings, FreeRDP_MonitorLocalShiftY)); - } - /* Set the desktop width and height according to the bounding rectangle around the active * monitors */ *pMaxWidth = MIN(*pMaxWidth, (UINT32)vscreen->area.right - vscreen->area.left + 1); @@ -666,13 +630,15 @@ BOOL xf_detect_monitors(xfContext* xfc, UINT32* pMaxWidth, UINT32* pMaxHeight) /* some 2008 server freeze at logon if we announce support for monitor layout PDU with * #monitors < 2. So let's announce it only if we have more than 1 monitor. */ - if (freerdp_settings_get_uint32(settings, FreeRDP_MonitorCount) > 1) + nmonitors = freerdp_settings_get_uint32(settings, FreeRDP_MonitorCount); + if (nmonitors > 1) { if (!freerdp_settings_set_bool(settings, FreeRDP_SupportMonitorLayoutPdu, TRUE)) goto fail; } - rc = TRUE; + rc = freerdp_settings_set_monitor_def_array_sorted(settings, rdpmonitors, nmonitors); + fail: #ifdef USABLE_XRANDR @@ -680,5 +646,6 @@ fail: XRRFreeMonitors(rrmonitors); #endif + free(rdpmonitors); return rc; } diff --git a/client/X11/xf_window.c b/client/X11/xf_window.c index 31b1239ef..03400b96c 100644 --- a/client/X11/xf_window.c +++ b/client/X11/xf_window.c @@ -334,10 +334,8 @@ void xf_SetWindowFullscreen(xfContext* xfc, xfWindow* window, BOOL fullscreen) /* Lastly apply any monitor shift(translation from remote to local coordinate system) * to startX and startY values */ - startX += WINPR_ASSERTING_INT_CAST( - int, freerdp_settings_get_uint32(settings, FreeRDP_MonitorLocalShiftX)); - startY += WINPR_ASSERTING_INT_CAST( - int, freerdp_settings_get_uint32(settings, FreeRDP_MonitorLocalShiftY)); + startX += freerdp_settings_get_int32(settings, FreeRDP_MonitorLocalShiftX); + startY += freerdp_settings_get_int32(settings, FreeRDP_MonitorLocalShiftY); } /* @@ -395,7 +393,7 @@ void xf_SetWindowFullscreen(xfContext* xfc, xfWindow* window, BOOL fullscreen) } else { - XSetWindowAttributes xswa; + XSetWindowAttributes xswa = { 0 }; xswa.override_redirect = True; XChangeWindowAttributes(xfc->display, window->handle, CWOverrideRedirect, &xswa); XRaiseWindow(xfc->display, window->handle); @@ -576,8 +574,8 @@ static BOOL xf_GetWorkArea_NET_WORKAREA(xfContext* xfc, Window root) if ((xfc->current_desktop * 4 + 3) >= (INT64)nitems) goto fail; - xfc->workArea.x = (UINT32)MIN(UINT32_MAX, prop[xfc->current_desktop * 4 + 0]); - xfc->workArea.y = (UINT32)MIN(UINT32_MAX, prop[xfc->current_desktop * 4 + 1]); + xfc->workArea.x = (INT32)MIN(INT32_MAX, prop[xfc->current_desktop * 4 + 0]); + xfc->workArea.y = (INT32)MIN(INT32_MAX, prop[xfc->current_desktop * 4 + 1]); xfc->workArea.width = (UINT32)MIN(UINT32_MAX, prop[xfc->current_desktop * 4 + 2]); xfc->workArea.height = (UINT32)MIN(UINT32_MAX, prop[xfc->current_desktop * 4 + 3]); diff --git a/client/X11/xfreerdp.h b/client/X11/xfreerdp.h index 000ba566e..bd7824c8c 100644 --- a/client/X11/xfreerdp.h +++ b/client/X11/xfreerdp.h @@ -64,17 +64,17 @@ typedef XcursorUInt XcursorPixel; struct xf_FullscreenMonitors { - UINT32 top; - UINT32 bottom; - UINT32 left; - UINT32 right; + INT32 top; + INT32 bottom; + INT32 left; + INT32 right; }; typedef struct xf_FullscreenMonitors xfFullscreenMonitors; struct xf_WorkArea { - UINT32 x; - UINT32 y; + INT32 x; + INT32 y; UINT32 width; UINT32 height; }; diff --git a/include/freerdp/settings.h b/include/freerdp/settings.h index 6b883840f..54fe7d0a1 100644 --- a/include/freerdp/settings.h +++ b/include/freerdp/settings.h @@ -752,6 +752,27 @@ extern "C" WINPR_ATTR_MALLOC(free, 1) FREERDP_API char* freerdp_settings_get_config_path(void); + /** @brief Sort monitor array according to: + * 1. First monitor is at x/y 0/0 and is the primary monitor + * 2. The primary monitor must be at 0/0, if not set + * FreeRDP_MonitorLocalShiftX/FreeRDP_MonitorLocalShiftY + * + * The FreeRDP_MonitorLocalShiftX/FreeRDP_MonitorLocalShiftY is required to map the local + * monitors / mouse / touch coordinates to the remote ones. + * + * @param settings The settings to set the monitors for + * @param monitors The unsorted monitors array + * @param count The number of monitors in the unsorted array + * + * @return \b TRUE if the configuration is valid (or could be corrected to a valid one), \b + * FALSE otherwise. + * + * @version since 3.11.0 + */ + FREERDP_API BOOL freerdp_settings_set_monitor_def_array_sorted(rdpSettings* settings, + const rdpMonitor* monitors, + size_t count); + #ifdef __cplusplus } #endif diff --git a/include/freerdp/settings_types_private.h b/include/freerdp/settings_types_private.h index b47e788a1..fa0cd1b9b 100644 --- a/include/freerdp/settings_types_private.h +++ b/include/freerdp/settings_types_private.h @@ -160,8 +160,8 @@ struct rdp_settings SETTINGS_DEPRECATED(ALIGN64 BOOL ListMonitors); /* 392 */ SETTINGS_DEPRECATED(ALIGN64 UINT32* MonitorIds); /* 393 */ SETTINGS_DEPRECATED(ALIGN64 UINT32 NumMonitorIds); /* 394 */ - SETTINGS_DEPRECATED(ALIGN64 UINT32 MonitorLocalShiftX); /*395 */ - SETTINGS_DEPRECATED(ALIGN64 UINT32 MonitorLocalShiftY); /* 396 */ + SETTINGS_DEPRECATED(ALIGN64 INT32 MonitorLocalShiftX); /*395 */ + SETTINGS_DEPRECATED(ALIGN64 INT32 MonitorLocalShiftY); /* 396 */ SETTINGS_DEPRECATED(ALIGN64 BOOL HasMonitorAttributes); /* 397 */ SETTINGS_DEPRECATED(ALIGN64 UINT32 MonitorFlags); /* 398 */ SETTINGS_DEPRECATED(ALIGN64 UINT32 MonitorAttributeFlags); /* 399 */ diff --git a/libfreerdp/codec/h264.h b/libfreerdp/codec/h264.h index 4b62b9030..dc758a8b6 100644 --- a/libfreerdp/codec/h264.h +++ b/libfreerdp/codec/h264.h @@ -62,7 +62,7 @@ extern "C" UINT32 FrameRate; UINT32 QP; UINT32 UsageType; - BOOL hwAccel; + UINT32 hwAccel; UINT32 NumberOfThreads; UINT32 iStride[3]; diff --git a/libfreerdp/common/settings.c b/libfreerdp/common/settings.c index 13478b057..d56850b9e 100644 --- a/libfreerdp/common/settings.c +++ b/libfreerdp/common/settings.c @@ -2257,3 +2257,114 @@ BOOL freerdp_settings_are_valid(const rdpSettings* settings) { return settings != NULL; } + +/* Function to sort rdpMonitor arrays: + * 1. first element is primary monitor + * 2. all others are sorted by coordinates of x/y + */ +static int sort_monitor_fn(const void* pva, const void* pvb) +{ + const rdpMonitor* a = pva; + const rdpMonitor* b = pvb; + WINPR_ASSERT(a); + WINPR_ASSERT(b); + if (a->is_primary && b->is_primary) + return 0; + if (a->is_primary) + return -1; + if (b->is_primary) + return 1; + + if (a->x != b->x) + return a->x - b->x; + if (a->y != b->y) + return a->y - b->y; + return 0; +} + +BOOL freerdp_settings_set_monitor_def_array_sorted(rdpSettings* settings, + const rdpMonitor* monitors, size_t count) +{ + WINPR_ASSERT(monitors || (count == 0)); + if (count == 0) + { + if (!freerdp_settings_set_int32(settings, FreeRDP_MonitorLocalShiftX, 0)) + return FALSE; + if (!freerdp_settings_set_int32(settings, FreeRDP_MonitorLocalShiftY, 0)) + return FALSE; + if (!freerdp_settings_set_pointer_len(settings, FreeRDP_MonitorDefArray, NULL, 0)) + return FALSE; + return freerdp_settings_set_uint32(settings, FreeRDP_MonitorCount, 0); + return TRUE; + } + + // Find primary or alternatively the monitor at 0/0 + const rdpMonitor* primary = NULL; + for (size_t x = 0; x < count; x++) + { + const rdpMonitor* cur = &monitors[x]; + if (cur->is_primary) + { + primary = cur; + break; + } + } + if (!primary) + { + for (size_t x = 0; x < count; x++) + { + const rdpMonitor* cur = &monitors[x]; + if ((cur->x == 0) && (cur->y == 0)) + { + primary = cur; + break; + } + } + } + + if (!primary) + { + WLog_ERR(TAG, "Could not find primary monitor, aborting"); + return FALSE; + } + + if (!freerdp_settings_set_pointer_len(settings, FreeRDP_MonitorDefArray, NULL, count)) + return FALSE; + rdpMonitor* sorted = freerdp_settings_get_pointer_writable(settings, FreeRDP_MonitorDefArray); + WINPR_ASSERT(sorted); + + size_t sortpos = 0; + + /* Set primary. Ensure left/top is at 0/0 and flags contains MONITOR_PRIMARY */ + sorted[sortpos] = *primary; + sorted[sortpos].x = 0; + sorted[sortpos].y = 0; + sorted[sortpos].is_primary = TRUE; + sortpos++; + + /* Set monitor shift to original layout */ + const INT32 offsetX = primary->x; + const INT32 offsetY = primary->y; + if (!freerdp_settings_set_int32(settings, FreeRDP_MonitorLocalShiftX, offsetX)) + return FALSE; + if (!freerdp_settings_set_int32(settings, FreeRDP_MonitorLocalShiftY, offsetY)) + return FALSE; + + for (size_t x = 0; x < count; x++) + { + const rdpMonitor* cur = &monitors[x]; + if (cur == primary) + continue; + + rdpMonitor m = monitors[x]; + m.x -= offsetX; + m.y -= offsetY; + sorted[sortpos++] = m; + } + + // Sort remaining monitors by x/y ? + qsort(sorted, count, sizeof(rdpMonitor), sort_monitor_fn); + + return freerdp_settings_set_uint32(settings, FreeRDP_MonitorCount, + WINPR_ASSERTING_INT_CAST(uint32_t, count)); +} diff --git a/libfreerdp/common/settings_getters.c b/libfreerdp/common/settings_getters.c index c0845ec3a..ddde63489 100644 --- a/libfreerdp/common/settings_getters.c +++ b/libfreerdp/common/settings_getters.c @@ -2544,6 +2544,12 @@ INT32 freerdp_settings_get_int32(const rdpSettings* settings, FreeRDP_Settings_K switch (id) { + case FreeRDP_MonitorLocalShiftX: + return settings->MonitorLocalShiftX; + + case FreeRDP_MonitorLocalShiftY: + return settings->MonitorLocalShiftY; + case FreeRDP_XPan: return settings->XPan; @@ -2574,6 +2580,14 @@ BOOL freerdp_settings_set_int32(rdpSettings* settings, FreeRDP_Settings_Keys_Int switch (id) { + case FreeRDP_MonitorLocalShiftX: + settings->MonitorLocalShiftX = cnv.c; + break; + + case FreeRDP_MonitorLocalShiftY: + settings->MonitorLocalShiftY = cnv.c; + break; + case FreeRDP_XPan: settings->XPan = cnv.c; break; diff --git a/libfreerdp/common/settings_str.h b/libfreerdp/common/settings_str.h index 093df8361..9691e7e89 100644 --- a/libfreerdp/common/settings_str.h +++ b/libfreerdp/common/settings_str.h @@ -448,6 +448,8 @@ static const struct settings_str_entry settings_map[] = { { FreeRDP_TlsSecLevel, FREERDP_SETTINGS_TYPE_UINT32, "FreeRDP_TlsSecLevel" }, { FreeRDP_VCChunkSize, FREERDP_SETTINGS_TYPE_UINT32, "FreeRDP_VCChunkSize" }, { FreeRDP_VCFlags, FREERDP_SETTINGS_TYPE_UINT32, "FreeRDP_VCFlags" }, + { FreeRDP_MonitorLocalShiftX, FREERDP_SETTINGS_TYPE_INT32, "FreeRDP_MonitorLocalShiftX" }, + { FreeRDP_MonitorLocalShiftY, FREERDP_SETTINGS_TYPE_INT32, "FreeRDP_MonitorLocalShiftY" }, { FreeRDP_XPan, FREERDP_SETTINGS_TYPE_INT32, "FreeRDP_XPan" }, { FreeRDP_YPan, FREERDP_SETTINGS_TYPE_INT32, "FreeRDP_YPan" }, { FreeRDP_ParentWindowId, FREERDP_SETTINGS_TYPE_UINT64, "FreeRDP_ParentWindowId" }, diff --git a/libfreerdp/core/gcc.c b/libfreerdp/core/gcc.c index 319e2e5fa..55d3edfe8 100644 --- a/libfreerdp/core/gcc.c +++ b/libfreerdp/core/gcc.c @@ -2138,18 +2138,13 @@ BOOL gcc_read_client_monitor_data(wStream* s, rdpMcs* mcs) for (UINT32 index = 0; index < monitorCount; index++) { - INT32 left = 0; - INT32 top = 0; - INT32 right = 0; - INT32 bottom = 0; - INT32 flags = 0; rdpMonitor* current = &settings->MonitorDefArray[index]; - Stream_Read_INT32(s, left); /* left */ - Stream_Read_INT32(s, top); /* top */ - Stream_Read_INT32(s, right); /* right */ - Stream_Read_INT32(s, bottom); /* bottom */ - Stream_Read_INT32(s, flags); /* flags */ + const INT32 left = Stream_Get_INT32(s); /* left */ + const INT32 top = Stream_Get_INT32(s); /* top */ + const INT32 right = Stream_Get_INT32(s); /* right */ + const INT32 bottom = Stream_Get_INT32(s); /* bottom */ + const UINT32 flags = Stream_Get_UINT32(s); /* flags */ current->x = left; current->y = top; current->width = right - left + 1; @@ -2205,19 +2200,19 @@ BOOL gcc_write_client_monitor_data(wStream* s, const rdpMcs* mcs) for (UINT32 i = 0; i < settings->MonitorCount; i++) { const rdpMonitor* current = &settings->MonitorDefArray[i]; - const UINT32 left = WINPR_ASSERTING_INT_CAST(uint32_t, current->x - baseX); - const UINT32 top = WINPR_ASSERTING_INT_CAST(uint32_t, current->y - baseY); - const UINT32 right = left + WINPR_ASSERTING_INT_CAST(uint32_t, current->width - 1); - const UINT32 bottom = top + WINPR_ASSERTING_INT_CAST(uint32_t, current->height - 1); + const INT32 left = current->x - baseX; + const INT32 top = current->y - baseY; + const INT32 right = left + current->width - 1; + const INT32 bottom = top + current->height - 1; const UINT32 flags = current->is_primary ? MONITOR_PRIMARY : 0; WLog_DBG(TAG, - "Monitor[%" PRIu32 "]: top=%" PRIu32 ", left=%" PRIu32 ", bottom=%" PRIu32 - ", right=%" PRIu32 ", flags=%" PRIu32, + "Monitor[%" PRIu32 "]: top=%" PRId32 ", left=%" PRId32 ", bottom=%" PRId32 + ", right=%" PRId32 ", flags=%" PRIu32, i, top, left, bottom, right, flags); - Stream_Write_UINT32(s, left); /* left */ - Stream_Write_UINT32(s, top); /* top */ - Stream_Write_UINT32(s, right); /* right */ - Stream_Write_UINT32(s, bottom); /* bottom */ + Stream_Write_INT32(s, left); /* left */ + Stream_Write_INT32(s, top); /* top */ + Stream_Write_INT32(s, right); /* right */ + Stream_Write_INT32(s, bottom); /* bottom */ Stream_Write_UINT32(s, flags); /* flags */ } } diff --git a/libfreerdp/core/settings.c b/libfreerdp/core/settings.c index 99bee2d37..d01f57aff 100644 --- a/libfreerdp/core/settings.c +++ b/libfreerdp/core/settings.c @@ -606,6 +606,7 @@ static BOOL freerdp_settings_client_monitors_check_primary_and_origin(const rdpS const UINT32 count = freerdp_settings_get_uint32(settings, FreeRDP_MonitorCount); BOOL havePrimary = FALSE; BOOL foundOrigin = FALSE; + BOOL primaryIsOrigin = FALSE; BOOL rc = TRUE; struct bounds_t bounds = { 0 }; @@ -644,6 +645,7 @@ static BOOL freerdp_settings_client_monitors_check_primary_and_origin(const rdpS rc = FALSE; } foundOrigin = TRUE; + primaryIsOrigin = monitor->is_primary != 0; } } @@ -672,6 +674,11 @@ static BOOL freerdp_settings_client_monitors_check_primary_and_origin(const rdpS WLog_ERR(TAG, "Monitor configuration must start at 0/0 for first monitor!"); rc = FALSE; } + if (!primaryIsOrigin) + { + WLog_ERR(TAG, "Monitor configuration must start at 0/0 for primary monitor!"); + rc = FALSE; + } return rc; } @@ -970,10 +977,10 @@ rdpSettings* freerdp_settings_new(DWORD flags) if (!freerdp_settings_set_pointer_len(settings, FreeRDP_MonitorDefArray, NULL, 32)) goto out_fail; - if (!freerdp_settings_set_uint32(settings, FreeRDP_MonitorLocalShiftX, 0)) + if (!freerdp_settings_set_int32(settings, FreeRDP_MonitorLocalShiftX, 0)) goto out_fail; - if (!freerdp_settings_set_uint32(settings, FreeRDP_MonitorLocalShiftY, 0)) + if (!freerdp_settings_set_int32(settings, FreeRDP_MonitorLocalShiftY, 0)) goto out_fail; if (!freerdp_settings_set_pointer_len(settings, FreeRDP_MonitorIds, NULL, 0)) @@ -1737,35 +1744,20 @@ BOOL freerdp_settings_enforce_monitor_exists(rdpSettings* settings) if (!freerdp_settings_set_uint32(settings, FreeRDP_MonitorCount, 1)) return FALSE; - rdpMonitor* monitor = - freerdp_settings_get_pointer_array_writable(settings, FreeRDP_MonitorDefArray, 0); - if (!monitor) + rdpMonitor monitor = { 0 }; + monitor.x = 0; + monitor.y = 0; + monitor.width = WINPR_ASSERTING_INT_CAST(int32_t, width); + monitor.height = WINPR_ASSERTING_INT_CAST(int32_t, height); + monitor.is_primary = TRUE; + monitor.orig_screen = 0; + monitor.attributes.physicalWidth = pwidth; + monitor.attributes.physicalHeight = pheight; + monitor.attributes.orientation = orientation; + monitor.attributes.desktopScaleFactor = desktopScaleFactor; + monitor.attributes.deviceScaleFactor = deviceScaleFactor; + if (!freerdp_settings_set_monitor_def_array_sorted(settings, &monitor, 1)) return FALSE; - monitor->x = 0; - monitor->y = 0; - WINPR_ASSERT(width <= INT32_MAX); - monitor->width = (INT32)width; - WINPR_ASSERT(height <= INT32_MAX); - monitor->height = (INT32)height; - monitor->is_primary = TRUE; - monitor->orig_screen = 0; - monitor->attributes.physicalWidth = pwidth; - monitor->attributes.physicalHeight = pheight; - monitor->attributes.orientation = orientation; - monitor->attributes.desktopScaleFactor = desktopScaleFactor; - monitor->attributes.deviceScaleFactor = deviceScaleFactor; - } - else if (fullscreen || (multimon && (count == 1))) - { - /* not all platforms start primary monitor at 0/0, so enforce this to avoid issues with - * fullscreen mode */ - rdpMonitor* monitor = - freerdp_settings_get_pointer_array_writable(settings, FreeRDP_MonitorDefArray, 0); - if (!monitor) - return FALSE; - monitor->x = 0; - monitor->y = 0; - monitor->is_primary = TRUE; } return TRUE; diff --git a/libfreerdp/core/test/TestSettings.c b/libfreerdp/core/test/TestSettings.c index c19d5df8a..342600002 100644 --- a/libfreerdp/core/test/TestSettings.c +++ b/libfreerdp/core/test/TestSettings.c @@ -950,20 +950,52 @@ static BOOL prepare_monitor_array(rdpSettings* settings, const struct validity_t WINPR_ASSERT(settings); WINPR_ASSERT(testcase); - const size_t count = freerdp_settings_get_uint32(settings, FreeRDP_MonitorDefArraySize); - if (count < testcase->count) + return freerdp_settings_set_monitor_def_array_sorted(settings, testcase->monitors, + testcase->count); +} + +static BOOL check_primary_offset(const rdpSettings* settings, const rdpMonitor* monitors, + size_t count) +{ + const rdpMonitor* cprimary = NULL; + for (size_t x = 0; x < count; x++) { - (void)fprintf(stderr, "MonitorDefArraySize=%" PRIuz ", but testcase requires %" PRIuz "\n", - count, testcase->count); - return FALSE; + const rdpMonitor* cur = &monitors[x]; + if (cur->is_primary) + cprimary = cur; } - for (size_t x = 0; x < testcase->count; x++) + if (!cprimary) { - const rdpMonitor* monitor = &testcase->monitors[x]; - if (!freerdp_settings_set_pointer_array(settings, FreeRDP_MonitorDefArray, x, monitor)) + for (size_t x = 0; x < count; x++) + { + const rdpMonitor* cur = &monitors[x]; + if ((cur->x == 0) && (cur->y == 0)) + cprimary = cur; + } + } + const rdpMonitor* sprimary = NULL; + for (size_t x = 0; x < count; x++) + { + const rdpMonitor* cur = + freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorDefArray, x); + if (!cur) return FALSE; + if (cur->is_primary) + sprimary = cur; } - return freerdp_settings_set_uint32(settings, FreeRDP_MonitorCount, testcase->count); + + if (!sprimary || !cprimary) + return FALSE; + + const INT32 xoff = cprimary->x; + const INT32 yoff = cprimary->y; + const INT32 sxoff = freerdp_settings_get_int32(settings, FreeRDP_MonitorLocalShiftX); + const INT32 syoff = freerdp_settings_get_int32(settings, FreeRDP_MonitorLocalShiftY); + if (xoff != sxoff) + return FALSE; + if (yoff != syoff) + return FALSE; + return TRUE; } static BOOL test_validity_check(void) @@ -1348,7 +1380,7 @@ static BOOL test_validity_check(void) { FALSE, ARRAYSIZE(single_monitor_invalid_3), single_monitor_invalid_3 }, { FALSE, ARRAYSIZE(single_monitor_invalid_4), single_monitor_invalid_4 }, { TRUE, ARRAYSIZE(multi_monitor_valid), multi_monitor_valid }, - { FALSE, ARRAYSIZE(multi_monitor_invalid_1), multi_monitor_invalid_1 }, + { TRUE, ARRAYSIZE(multi_monitor_invalid_1), multi_monitor_invalid_1 }, { FALSE, ARRAYSIZE(multi_monitor_invalid_2), multi_monitor_invalid_2 }, { FALSE, ARRAYSIZE(multi_monitor_invalid_3), multi_monitor_invalid_3 }, { FALSE, ARRAYSIZE(multi_monitor_invalid_4), multi_monitor_invalid_4 }, @@ -1370,7 +1402,9 @@ static BOOL test_validity_check(void) #else const BOOL res = cur->expected; #endif - if (res != cur->expected) + + if ((res != cur->expected) || + !check_primary_offset(settings, cur->monitors, cur->count)) { rc = log_result_case(FALSE, __func__, x); } diff --git a/libfreerdp/core/test/settings_property_lists.h b/libfreerdp/core/test/settings_property_lists.h index 5ba8f0060..f9df959df 100644 --- a/libfreerdp/core/test/settings_property_lists.h +++ b/libfreerdp/core/test/settings_property_lists.h @@ -348,6 +348,8 @@ static const size_t uint32_list_indices[] = { #define have_int32_list_indices static const size_t int32_list_indices[] = { + FreeRDP_MonitorLocalShiftX, + FreeRDP_MonitorLocalShiftY, FreeRDP_XPan, FreeRDP_YPan, }; diff --git a/scripts/abi-suppr.txt b/scripts/abi-suppr.txt index 3995607d2..b53162493 100644 --- a/scripts/abi-suppr.txt +++ b/scripts/abi-suppr.txt @@ -32,3 +32,13 @@ name = smartcard_irp_device_control_call [suppress_function] change_kind = function-subtype-change name = freerdp_passphrase_read + +# freerdp_settings_get_uint32 subtype change (delete MonitorLocalShift[XY] +[suppress_function] +change_kind = function-subtype-change +name = freerdp_settings_get_uint32 + +# freerdp_settings_set_uint32 subtype change (delete MonitorLocalShift[XY] +[suppress_function] +change_kind = function-subtype-change +name = freerdp_settings_set_uint32 diff --git a/tools/update-settings-tests b/tools/update-settings-tests index 14d6d04bd..582c88e40 100755 --- a/tools/update-settings-tests +++ b/tools/update-settings-tests @@ -324,6 +324,9 @@ try: getter_list = dict(type_list) setter_list = dict(type_list) setter_list2 = dict(type_list) + # Compatibility with older 3.x releases where the value was wrongly an unsigned type + getter_list['UINT32'].append('MonitorLocalShiftX') + getter_list['UINT32'].append('MonitorLocalShiftY') write_getter(f, getter_list, 'BOOL', 'bool', '') write_setter(f, setter_list, 'BOOL', 'bool', '') write_getter(f, getter_list, 'UINT16', 'uint16', '')