Merge pull request #4332 from hardening/xrandr_and_fixes

Xrandr and fixes
This commit is contained in:
akallabeth 2018-01-08 09:20:56 +01:00 committed by GitHub
commit 4077d55a6c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 128 additions and 46 deletions

View File

@ -959,8 +959,8 @@ UINT rail_send_client_activate_order(railPlugin* rail, RAIL_ACTIVATE_ORDER* acti
{
wStream* s;
UINT error;
s = rail_pdu_init(RAIL_ACTIVATE_ORDER_LENGTH);
s = rail_pdu_init(RAIL_ACTIVATE_ORDER_LENGTH);
if (!s)
{
WLog_ERR(TAG, "rail_pdu_init failed!");

View File

@ -139,8 +139,8 @@ static UINT rdpgfx_decode_AVC420(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd
wStream* s;
RDPGFX_AVC420_BITMAP_STREAM h264;
RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface;
s = Stream_New(cmd->data, cmd->length);
s = Stream_New(cmd->data, cmd->length);
if (!s)
{
WLog_ERR(TAG, "Stream_New failed!");
@ -186,7 +186,6 @@ static UINT rdpgfx_decode_AVC444(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd
RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface;
s = Stream_New(cmd->data, cmd->length);
if (!s)
{
WLog_ERR(TAG, "Stream_New failed!");

View File

@ -198,8 +198,8 @@ static UINT rdpgfx_send_frame_acknowledge_pdu(RDPGFX_CHANNEL_CALLBACK* callback,
header.cmdId = RDPGFX_CMDID_FRAMEACKNOWLEDGE;
header.pduLength = RDPGFX_HEADER_SIZE + 12;
WLog_Print(gfx->log, WLOG_DEBUG, "SendFrameAcknowledgePdu: %"PRIu32"", pdu->frameId);
s = Stream_New(NULL, header.pduLength);
s = Stream_New(NULL, header.pduLength);
if (!s)
{
WLog_ERR(TAG, "Stream_New failed!");
@ -233,8 +233,8 @@ static UINT rdpgfx_send_qoe_frame_acknowledge_pdu(RDPGFX_CHANNEL_CALLBACK* callb
header.cmdId = RDPGFX_CMDID_QOEFRAMEACKNOWLEDGE;
header.pduLength = RDPGFX_HEADER_SIZE + 12;
WLog_Print(gfx->log, WLOG_DEBUG, "SendQoeFrameAcknowledgePdu: %"PRIu32"", pdu->frameId);
s = Stream_New(NULL, header.pduLength);
s = Stream_New(NULL, header.pduLength);
if (!s)
{
WLog_ERR(TAG, "Stream_New failed!");
@ -272,6 +272,7 @@ static UINT rdpgfx_recv_reset_graphics_pdu(RDPGFX_CHANNEL_CALLBACK* callback,
RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin;
RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface;
UINT error = CHANNEL_RC_OK;
GraphicsResetEventArgs graphicsReset;
if (Stream_GetRemainingLength(s) < 12)
{
@ -289,9 +290,7 @@ static UINT rdpgfx_recv_reset_graphics_pdu(RDPGFX_CHANNEL_CALLBACK* callback,
return ERROR_INVALID_DATA;
}
pdu.monitorDefArray = (MONITOR_DEF*) calloc(pdu.monitorCount,
sizeof(MONITOR_DEF));
pdu.monitorDefArray = (MONITOR_DEF*) calloc(pdu.monitorCount, sizeof(MONITOR_DEF));
if (!pdu.monitorDefArray)
{
WLog_Print(gfx->log, WLOG_ERROR, "calloc failed!");
@ -337,6 +336,12 @@ static UINT rdpgfx_recv_reset_graphics_pdu(RDPGFX_CHANNEL_CALLBACK* callback,
WLog_Print(gfx->log, WLOG_ERROR, "context->ResetGraphics failed with error %"PRIu32"", error);
}
/* some listeners may be interested (namely the display channel) */
EventArgsInit(&graphicsReset, "xfreerdp");
graphicsReset.width = pdu.width;
graphicsReset.height = pdu.height;
PubSub_OnGraphicsReset(gfx->rdpcontext->pubSub, gfx->rdpcontext, &graphicsReset);
free(pdu.monitorDefArray);
return error;
}
@ -403,7 +408,6 @@ static UINT rdpgfx_recv_cache_import_reply_pdu(RDPGFX_CHANNEL_CALLBACK* callback
}
pdu.cacheSlots = (UINT16*) calloc(pdu.importedEntriesCount, sizeof(UINT16));
if (!pdu.cacheSlots)
{
WLog_Print(gfx->log, WLOG_ERROR, "calloc failed!");
@ -815,8 +819,7 @@ static UINT rdpgfx_recv_solid_fill_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStrea
Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */
if ((error = rdpgfx_read_color32(s,
&(pdu.fillPixel)))) /* fillPixel (4 bytes) */
if ((error = rdpgfx_read_color32(s, &(pdu.fillPixel)))) /* fillPixel (4 bytes) */
{
WLog_Print(gfx->log, WLOG_ERROR, "rdpgfx_read_color32 failed with error %"PRIu32"!", error);
return error;
@ -831,7 +834,6 @@ static UINT rdpgfx_recv_solid_fill_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStrea
}
pdu.fillRects = (RECTANGLE_16*) calloc(pdu.fillRectCount, sizeof(RECTANGLE_16));
if (!pdu.fillRects)
{
WLog_Print(gfx->log, WLOG_ERROR, "calloc failed!");
@ -903,9 +905,7 @@ static UINT rdpgfx_recv_surface_to_surface_pdu(RDPGFX_CHANNEL_CALLBACK*
return ERROR_INVALID_DATA;
}
pdu.destPts = (RDPGFX_POINT16*) calloc(pdu.destPtsCount,
sizeof(RDPGFX_POINT16));
pdu.destPts = (RDPGFX_POINT16*) calloc(pdu.destPtsCount, sizeof(RDPGFX_POINT16));
if (!pdu.destPts)
{
WLog_Print(gfx->log, WLOG_ERROR, "calloc failed!");
@ -1151,11 +1151,9 @@ static UINT rdpgfx_recv_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s)
return error;
}
#if 1
WLog_Print(gfx->log, WLOG_DEBUG, "cmdId: %s (0x%04"PRIX16") flags: 0x%04"PRIX16" pduLength: %"PRIu32"",
rdpgfx_get_cmd_id_string(header.cmdId), header.cmdId, header.flags,
header.pduLength);
#endif
switch (header.cmdId)
{
@ -1308,8 +1306,8 @@ static UINT rdpgfx_on_data_received(IWTSVirtualChannelCallback*
RDPGFX_CHANNEL_CALLBACK* callback = (RDPGFX_CHANNEL_CALLBACK*) pChannelCallback;
RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin;
UINT error = CHANNEL_RC_OK;
status = zgfx_decompress(gfx->zgfx, Stream_Pointer(data),
Stream_GetRemainingLength(data), &pDstData, &DstSize, 0);
status = zgfx_decompress(gfx->zgfx, Stream_Pointer(data), Stream_GetRemainingLength(data),
&pDstData, &DstSize, 0);
if (status < 0)
{
@ -1318,7 +1316,6 @@ static UINT rdpgfx_on_data_received(IWTSVirtualChannelCallback*
}
s = Stream_New(pDstData, DstSize);
if (!s)
{
WLog_Print(gfx->log, WLOG_ERROR, "calloc failed!");
@ -1363,6 +1360,7 @@ static UINT rdpgfx_on_close(IWTSVirtualChannelCallback* pChannelCallback)
RDPGFX_CHANNEL_CALLBACK* callback = (RDPGFX_CHANNEL_CALLBACK*) pChannelCallback;
RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin;
RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface;
WLog_Print(gfx->log, WLOG_DEBUG, "OnClose");
free(callback);
gfx->UnacknowledgedFrames = 0;
@ -1422,11 +1420,9 @@ static UINT rdpgfx_on_new_channel_connection(IWTSListenerCallback*
IWTSVirtualChannelCallback** ppCallback)
{
RDPGFX_CHANNEL_CALLBACK* callback;
RDPGFX_LISTENER_CALLBACK* listener_callback = (RDPGFX_LISTENER_CALLBACK*)
pListenerCallback;
callback = (RDPGFX_CHANNEL_CALLBACK*) calloc(1,
sizeof(RDPGFX_CHANNEL_CALLBACK));
RDPGFX_LISTENER_CALLBACK* listener_callback = (RDPGFX_LISTENER_CALLBACK*)pListenerCallback;
callback = (RDPGFX_CHANNEL_CALLBACK*) calloc(1, sizeof(RDPGFX_CHANNEL_CALLBACK));
if (!callback)
{
WLog_ERR(TAG, "calloc failed!");
@ -1454,17 +1450,15 @@ static UINT rdpgfx_plugin_initialize(IWTSPlugin* pPlugin,
{
UINT error;
RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) pPlugin;
gfx->listener_callback = (RDPGFX_LISTENER_CALLBACK*) calloc(1,
sizeof(RDPGFX_LISTENER_CALLBACK));
gfx->listener_callback = (RDPGFX_LISTENER_CALLBACK*) calloc(1, sizeof(RDPGFX_LISTENER_CALLBACK));
if (!gfx->listener_callback)
{
WLog_Print(gfx->log, WLOG_ERROR, "calloc failed!");
return CHANNEL_RC_NO_MEMORY;
}
gfx->listener_callback->iface.OnNewChannelConnection =
rdpgfx_on_new_channel_connection;
gfx->listener_callback->iface.OnNewChannelConnection = rdpgfx_on_new_channel_connection;
gfx->listener_callback->plugin = pPlugin;
gfx->listener_callback->channel_mgr = pChannelMgr;
error = pChannelMgr->CreateListener(pChannelMgr, RDPGFX_DVC_CHANNEL_NAME, 0,
@ -1704,8 +1698,9 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
gfx->iface.Connected = NULL;
gfx->iface.Disconnected = NULL;
gfx->iface.Terminated = rdpgfx_plugin_terminated;
gfx->SurfaceTable = HashTable_New(TRUE);
gfx->rdpcontext = ((freerdp *)gfx->settings->instance)->context;
gfx->SurfaceTable = HashTable_New(TRUE);
if (!gfx->SurfaceTable)
{
free(gfx);
@ -1725,8 +1720,8 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
gfx->SmallCache = TRUE;
gfx->MaxCacheSlot = gfx->SmallCache ? 4096 : 25600;
context = (RdpgfxClientContext *)calloc(1, sizeof(RdpgfxClientContext));
context = (RdpgfxClientContext *)calloc(1, sizeof(RdpgfxClientContext));
if (!context)
{
free(gfx);

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;
@ -119,6 +120,32 @@ static void xf_disp_OnActivated(rdpContext* context, ActivatedEventArgs* e)
}
}
static void xf_disp_OnGraphicsReset(rdpContext* context, GraphicsResetEventArgs* e)
{
xfContext *xfc = (xfContext *)context;
xfDispContext *xfDisp = xfc->xfDisp;
rdpSettings *settings = context->settings;
xfDisp->waitingResize = FALSE;
if (xfDisp->activated && !settings->Fullscreen)
{
xf_disp_set_window_resizable(xfDisp);
/* if a resize has been done recently don't do anything and let the timer
* perform the resize */
if (GetTickCount64() - xfDisp->lastSentDate < RESIZE_MIN_DELAY)
return;
if ((xfDisp->lastSentWidth != xfDisp->targetWidth) || (xfDisp->lastSentHeight != xfDisp->targetHeight))
{
WLog_DBG(TAG, "performing delayed resize to %dx%d", xfDisp->targetWidth, xfDisp->targetHeight);
xf_disp_sendResize(xfDisp, xfDisp->targetWidth, xfDisp->targetHeight);
}
}
}
static void xf_disp_OnTimer(rdpContext* context, TimerEventArgs* e)
{
xfContext *xfc = (xfContext *)context;
@ -155,6 +182,7 @@ xfDispContext *xf_disp_new(xfContext* xfc)
ret->lastSentHeight = ret->targetHeight = xfc->context.settings->DesktopHeight;
PubSub_SubscribeActivated(xfc->context.pubSub, (pActivatedEventHandler)xf_disp_OnActivated);
PubSub_SubscribeGraphicsReset(xfc->context.pubSub, (pGraphicsResetEventHandler)xf_disp_OnGraphicsReset);
PubSub_SubscribeTimer(xfc->context.pubSub, (pTimerEventHandler)xf_disp_OnTimer);
return ret;
}
@ -171,6 +199,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 +214,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;
}

View File

@ -108,6 +108,11 @@ DEFINE_EVENT_BEGIN(Timer)
UINT64 now;
DEFINE_EVENT_END(Timer)
DEFINE_EVENT_BEGIN(GraphicsReset)
UINT32 width;
UINT32 height;
DEFINE_EVENT_END(GraphicsReset)
#ifdef __cplusplus
}
#endif

View File

@ -317,7 +317,10 @@ int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BY
{
int status = -1;
BYTE descriptor;
wStream* stream = Stream_New((BYTE*)pSrcData, SrcSize);
if (!stream)
return -1;
if (Stream_GetRemainingLength(stream) < 1)
goto fail;

View File

@ -606,6 +606,7 @@ static wEventType FreeRDP_Events[] =
DEFINE_EVENT_ENTRY(MouseEvent)
DEFINE_EVENT_ENTRY(Activated)
DEFINE_EVENT_ENTRY(Timer)
DEFINE_EVENT_ENTRY(GraphicsReset)
};
/** Allocator function for a rdp context.