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.
This commit is contained in:
David Fort 2017-12-23 10:27:38 +01:00
parent 158840429d
commit 58b5573c82
2 changed files with 68 additions and 16 deletions

View File

@ -24,7 +24,7 @@
#include <X11/extensions/Xrandr.h>
#include <X11/extensions/randr.h>
#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);

View File

@ -42,7 +42,7 @@
#include <X11/extensions/Xrandr.h>
#include <X11/extensions/randr.h>
#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;
}