From 58b5573c82be8d2e16424c438ebe40b4c53a57ef Mon Sep 17 00:00:00 2001 From: David Fort Date: Sat, 23 Dec 2017 10:27:38 +0100 Subject: [PATCH] Use more xrandr attributes when available and preserve [desktop|device]ScaleFactor Fix a too restrictive detection of XRandr support. Set more monitor's attributes like physical size and orientation when XRandr is available. Set [desktop|device]ScaleFactor when it has been given on the command line, this should fix #4324. --- client/X11/xf_disp.c | 41 ++++++++++++++++++++++++++++++++------- client/X11/xf_monitor.c | 43 ++++++++++++++++++++++++++++++++--------- 2 files changed, 68 insertions(+), 16 deletions(-) diff --git a/client/X11/xf_disp.c b/client/X11/xf_disp.c index 7c7871701..a21e7f85c 100644 --- a/client/X11/xf_disp.c +++ b/client/X11/xf_disp.c @@ -24,7 +24,7 @@ #include #include -#if (RANDR_MAJOR * 100 + RANDR_MINOR) > 105 +#if (RANDR_MAJOR * 100 + RANDR_MINOR) >= 105 # define USABLE_XRANDR #endif @@ -54,6 +54,7 @@ static BOOL xf_disp_sendResize(xfDispContext *xfDisp, int width, int height) { DISPLAY_CONTROL_MONITOR_LAYOUT layout; xfContext *xfc = xfDisp->xfc; + rdpSettings *settings = xfc->context.settings; xfDisp->lastSentDate = GetTickCount64(); xfDisp->lastSentWidth = width; @@ -65,8 +66,8 @@ static BOOL xf_disp_sendResize(xfDispContext *xfDisp, int width, int height) layout.Width = width; layout.Height = height; layout.Orientation = ORIENTATION_LANDSCAPE; - layout.DesktopScaleFactor = 100; - layout.DeviceScaleFactor = 100; + layout.DesktopScaleFactor = settings->DesktopScaleFactor; + layout.DeviceScaleFactor = settings->DeviceScaleFactor; layout.PhysicalWidth = width; layout.PhysicalHeight = height; @@ -171,6 +172,8 @@ static UINT xf_disp_sendLayout(DispClientContext *disp, rdpMonitor *monitors, in UINT ret = CHANNEL_RC_OK; DISPLAY_CONTROL_MONITOR_LAYOUT *layouts; int i; + xfDispContext *xfDisp = (xfDispContext *)disp->custom; + rdpSettings *settings = xfDisp->xfc->context.settings; layouts = calloc(nmonitors, sizeof(DISPLAY_CONTROL_MONITOR_LAYOUT)); if (!layouts) @@ -184,10 +187,34 @@ static UINT xf_disp_sendLayout(DispClientContext *disp, rdpMonitor *monitors, in layouts[i].Width = monitors[i].width; layouts[i].Height = monitors[i].height; layouts[i].Orientation = ORIENTATION_LANDSCAPE; - layouts[i].PhysicalWidth = monitors[i].width; - layouts[i].PhysicalHeight = monitors[i].height; - layouts[i].DesktopScaleFactor = 100; - layouts[i].DeviceScaleFactor = 100; + layouts[i].PhysicalWidth = monitors[i].attributes.physicalWidth; + layouts[i].PhysicalHeight = monitors[i].attributes.physicalHeight; + + switch(monitors[i].attributes.orientation) + { + case 90: + layouts[i].Orientation = ORIENTATION_PORTRAIT; + break; + case 180: + layouts[i].Orientation = ORIENTATION_LANDSCAPE_FLIPPED; + break; + case 270: + layouts[i].Orientation = ORIENTATION_PORTRAIT_FLIPPED; + break; + case 0: + default: + /* MS-RDPEDISP - 2.2.2.2.1: + * Orientation (4 bytes): A 32-bit unsigned integer that specifies the + * orientation of the monitor in degrees. Valid values are 0, 90, 180 + * or 270 + * + * So we default to ORIENTATION_LANDSCAPE + */ + layouts[i].Orientation = ORIENTATION_LANDSCAPE; + break; + } + layouts[i].DesktopScaleFactor = settings->DesktopScaleFactor; + layouts[i].DeviceScaleFactor = settings->DeviceScaleFactor; } ret = disp->SendMonitorLayout(disp, nmonitors, layouts); diff --git a/client/X11/xf_monitor.c b/client/X11/xf_monitor.c index a14936bd3..9783b7072 100644 --- a/client/X11/xf_monitor.c +++ b/client/X11/xf_monitor.c @@ -42,7 +42,7 @@ #include #include -#if (RANDR_MAJOR * 100 + RANDR_MINOR) > 105 +#if (RANDR_MAJOR * 100 + RANDR_MINOR) >= 105 # define USABLE_XRANDR #endif @@ -144,6 +144,11 @@ BOOL xf_detect_monitors(xfContext* xfc, UINT32* pMaxWidth, UINT32* pMaxHeight) #if defined WITH_XINERAMA || defined WITH_XRANDR int major, minor; #endif +#if defined(USABLE_XRANDR) + XRRMonitorInfo *rrmonitors = NULL; + BOOL useXRandr = FALSE; +#endif + vscreen = &xfc->vscreen; *pMaxWidth = settings->DesktopWidth; *pMaxHeight = settings->DesktopHeight; @@ -158,7 +163,7 @@ BOOL xf_detect_monitors(xfContext* xfc, UINT32* pMaxWidth, UINT32* pMaxHeight) if (XRRQueryExtension(xfc->display, &major, &minor) && (XRRQueryVersion(xfc->display, &major, &minor) == True) && (major * 100 + minor >= 105)) { - XRRMonitorInfo *monitors = XRRGetMonitors(xfc->display, DefaultRootWindow(xfc->display), 1, &vscreen->nmonitors); + XRRMonitorInfo *rrmonitors = XRRGetMonitors(xfc->display, DefaultRootWindow(xfc->display), 1, &vscreen->nmonitors); if (vscreen->nmonitors > 16) vscreen->nmonitors = 0; @@ -167,14 +172,14 @@ BOOL xf_detect_monitors(xfContext* xfc, UINT32* pMaxWidth, UINT32* pMaxHeight) { for (i = 0; i < vscreen->nmonitors; i++) { - vscreen->monitors[i].area.left = monitors[i].x; - vscreen->monitors[i].area.top = monitors[i].y; - vscreen->monitors[i].area.right = monitors[i].x + monitors[i].width - 1; - vscreen->monitors[i].area.bottom = monitors[i].y + monitors[i].height - 1; - vscreen->monitors[i].primary = monitors[i].primary > 0; + vscreen->monitors[i].area.left = rrmonitors[i].x; + vscreen->monitors[i].area.top = rrmonitors[i].y; + vscreen->monitors[i].area.right = rrmonitors[i].x + rrmonitors[i].width - 1; + vscreen->monitors[i].area.bottom = rrmonitors[i].y + rrmonitors[i].height - 1; + vscreen->monitors[i].primary = rrmonitors[i].primary > 0; } } - XRRFreeMonitors(monitors); + useXRandr = TRUE; } else #endif @@ -270,7 +275,7 @@ BOOL xf_detect_monitors(xfContext* xfc, UINT32* pMaxWidth, UINT32* pMaxHeight) } if (!settings->Fullscreen && !settings->Workarea && !settings->UseMultimon) - return TRUE; + goto out; /* If single monitor fullscreen OR workarea without remote app */ if ((settings->Fullscreen && !settings->UseMultimon && !settings->SpanMonitors) || @@ -292,6 +297,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 */ for (i = 0; i < vscreen->nmonitors; i++) { + MONITOR_ATTRIBUTES *attrs; if (!xf_is_monitor_id_active(xfc, i)) continue; @@ -303,6 +309,20 @@ BOOL xf_detect_monitors(xfContext* xfc, UINT32* pMaxWidth, UINT32* pMaxHeight) MIN(vscreen->monitors[i].area.bottom - vscreen->monitors[i].area.top + 1, *pMaxHeight); settings->MonitorDefArray[nmonitors].orig_screen = i; +#ifdef USABLE_XRANDR + if (useXRandr && rrmonitors) + { + Rotation rot, ret; + + attrs = &settings->MonitorDefArray[nmonitors].attributes; + attrs->physicalWidth = rrmonitors[i].mwidth; + attrs->physicalHeight = rrmonitors[i].mheight; + + ret = XRRRotations(xfc->display, i, &rot); + attrs->orientation = rot; + } +#endif + if (i == settings->MonitorIds[0]) { settings->MonitorDefArray[nmonitors].is_primary = TRUE; @@ -455,5 +475,10 @@ BOOL xf_detect_monitors(xfContext* xfc, UINT32* pMaxWidth, UINT32* pMaxHeight) if (settings->MonitorCount) settings->SupportMonitorLayoutPdu = TRUE; +out: +#ifdef USABLE_XRANDR + if (rrmonitors) + XRRFreeMonitors(rrmonitors); +#endif return TRUE; }