diff --git a/client/X11/xf_client.c b/client/X11/xf_client.c index fba5b4a1f..7c880fdcb 100644 --- a/client/X11/xf_client.c +++ b/client/X11/xf_client.c @@ -1536,12 +1536,9 @@ static DWORD WINAPI xf_client_thread(LPVOID param) goto disconnect; } - handles[0] = timer; - if (!settings->AsyncInput) { inputEvent = xfc->x11event; - handles[1] = inputEvent; } else { @@ -1555,6 +1552,12 @@ static DWORD WINAPI xf_client_thread(LPVOID param) while (!freerdp_shall_disconnect(instance)) { + nCount = 0; + handles[nCount++] = timer; + + if (!settings->AsyncInput) + handles[nCount++] = inputEvent; + /* * win8 and server 2k12 seem to have some timing issue/race condition * when a initial sync request is send to sync the keyboard indicators @@ -1566,11 +1569,9 @@ static DWORD WINAPI xf_client_thread(LPVOID param) xf_keyboard_focus_in(xfc); } - nCount = (settings->AsyncInput) ? 1 : 2; - if (!settings->AsyncTransport) { - DWORD tmp = freerdp_get_event_handles(context, &handles[nCount], 64 - nCount); + DWORD tmp = freerdp_get_event_handles(context, &handles[nCount], ARRAYSIZE(handles) - nCount); if (tmp == 0) { diff --git a/client/X11/xf_disp.c b/client/X11/xf_disp.c index 49d9601a0..c8f9b21b7 100644 --- a/client/X11/xf_disp.c +++ b/client/X11/xf_disp.c @@ -39,7 +39,7 @@ struct _xfDispContext { - xfContext *xfc; + xfContext* xfc; BOOL haveXRandr; int eventBase, errorBase; int lastSentWidth, lastSentHeight; @@ -47,37 +47,83 @@ struct _xfDispContext int targetWidth, targetHeight; BOOL activated; BOOL waitingResize; + UINT16 lastSentDesktopOrientation; + UINT32 lastSentDesktopScaleFactor; + UINT32 lastSentDeviceScaleFactor; }; +static BOOL xf_disp_settings_changed(xfDispContext* xfDisp) +{ + rdpSettings* settings; + settings = xfDisp->xfc->context.settings; -static BOOL xf_disp_sendResize(xfDispContext *xfDisp, int width, int height) + if (xfDisp->lastSentWidth != xfDisp->targetWidth) + return TRUE; + + if (xfDisp->lastSentHeight != xfDisp->targetHeight) + return TRUE; + + if (xfDisp->lastSentDesktopOrientation != settings->DesktopOrientation) + return TRUE; + + if (xfDisp->lastSentDesktopScaleFactor != settings->DesktopScaleFactor) + return TRUE; + + if (xfDisp->lastSentDeviceScaleFactor != settings->DeviceScaleFactor) + return TRUE; + + return FALSE; +} + +static BOOL xf_update_last_sent(xfDispContext* xfDisp) +{ + rdpSettings* settings = xfDisp->xfc->context.settings; + xfDisp->lastSentWidth = xfDisp->targetWidth; + xfDisp->lastSentHeight = xfDisp->targetHeight; + xfDisp->lastSentDesktopOrientation = settings->DesktopOrientation; + xfDisp->lastSentDesktopScaleFactor = settings->DesktopScaleFactor; + xfDisp->lastSentDeviceScaleFactor = settings->DeviceScaleFactor; + return TRUE; +} + +static BOOL xf_disp_sendResize(xfDispContext* xfDisp) { DISPLAY_CONTROL_MONITOR_LAYOUT layout; - xfContext *xfc = xfDisp->xfc; - rdpSettings *settings = xfc->context.settings; + xfContext* xfc = xfDisp->xfc; + rdpSettings* settings = xfc->context.settings; + + if (!xfDisp->activated) + return TRUE; + + if (GetTickCount64() - xfDisp->lastSentDate < RESIZE_MIN_DELAY) + return TRUE; xfDisp->lastSentDate = GetTickCount64(); - xfDisp->lastSentWidth = width; - xfDisp->lastSentHeight = height; - xfDisp->waitingResize = TRUE; + if (!xf_disp_settings_changed(xfDisp)) + return TRUE; + + xfDisp->waitingResize = TRUE; layout.Flags = DISPLAY_CONTROL_MONITOR_PRIMARY; layout.Top = layout.Left = 0; - layout.Width = width; - layout.Height = height; - layout.Orientation = ORIENTATION_LANDSCAPE; + layout.Width = xfDisp->targetWidth; + layout.Height = xfDisp->targetHeight; + layout.Orientation = settings->DesktopOrientation; layout.DesktopScaleFactor = settings->DesktopScaleFactor; layout.DeviceScaleFactor = settings->DeviceScaleFactor; - layout.PhysicalWidth = width; - layout.PhysicalHeight = height; + layout.PhysicalWidth = xfDisp->targetWidth; + layout.PhysicalHeight = xfDisp->targetHeight; - return xfc->disp->SendMonitorLayout(xfc->disp, 1, &layout) == CHANNEL_RC_OK; + if (xfc->disp->SendMonitorLayout(xfc->disp, 1, &layout) != CHANNEL_RC_OK) + return FALSE; + + return xf_update_last_sent(xfDisp); } -static BOOL xf_disp_set_window_resizable(xfDispContext *xfDisp) +static BOOL xf_disp_set_window_resizable(xfDispContext* xfDisp) { - XSizeHints *size_hints; + XSizeHints* size_hints; if (!(size_hints = XAllocSizeHints())) return FALSE; @@ -86,8 +132,10 @@ static BOOL xf_disp_set_window_resizable(xfDispContext *xfDisp) size_hints->win_gravity = NorthWestGravity; size_hints->min_width = size_hints->min_height = 320; size_hints->max_width = size_hints->max_height = 8192; + if (xfDisp->xfc->window) XSetWMNormalHints(xfDisp->xfc->display, xfDisp->xfc->window->handle, size_hints); + XFree(size_hints); return TRUE; } @@ -95,10 +143,9 @@ static BOOL xf_disp_set_window_resizable(xfDispContext *xfDisp) static void xf_disp_OnActivated(void* context, ActivatedEventArgs* e) { - xfContext *xfc = (xfContext *)context; - xfDispContext *xfDisp = xfc->xfDisp; - rdpSettings *settings = xfc->context.settings; - + xfContext* xfc = (xfContext*)context; + xfDispContext* xfDisp = xfc->xfDisp; + rdpSettings* settings = xfc->context.settings; xfDisp->waitingResize = FALSE; if (xfDisp->activated && !settings->Fullscreen) @@ -108,102 +155,77 @@ static void xf_disp_OnActivated(void* context, ActivatedEventArgs* e) if (e->firstActivation) return; - /* 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); - } + xf_disp_sendResize(xfDisp); } } static void xf_disp_OnGraphicsReset(void* context, GraphicsResetEventArgs* e) { - xfContext *xfc = (xfContext *)context; - xfDispContext *xfDisp = xfc->xfDisp; - rdpSettings *settings = xfc->context.settings; - + xfContext* xfc = (xfContext*)context; + xfDispContext* xfDisp = xfc->xfDisp; + rdpSettings* settings = xfc->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); - } + xf_disp_sendResize(xfDisp); } } static void xf_disp_OnTimer(void* context, TimerEventArgs* e) { - xfContext *xfc = (xfContext *)context; - xfDispContext *xfDisp = xfc->xfDisp; - rdpSettings *settings = xfc->context.settings; + xfContext* xfc = (xfContext*)context; + xfDispContext* xfDisp = xfc->xfDisp; + rdpSettings* settings = xfc->context.settings; if (!xfDisp->activated || settings->Fullscreen) return; - if (e->now - xfDisp->lastSentDate < RESIZE_MIN_DELAY) - return; - - if ((xfDisp->lastSentWidth != xfDisp->targetWidth) || (xfDisp->lastSentHeight != xfDisp->targetHeight)) - { - WLog_DBG(TAG, "timer performing delayed resize to %dx%d", xfDisp->targetWidth, xfDisp->targetHeight); - xf_disp_sendResize(xfDisp, xfDisp->targetWidth, xfDisp->targetHeight); - } + xf_disp_sendResize(xfDisp); } -xfDispContext *xf_disp_new(xfContext* xfc) +xfDispContext* xf_disp_new(xfContext* xfc) { - xfDispContext *ret = calloc(1, sizeof(xfDispContext)); + xfDispContext* ret = calloc(1, sizeof(xfDispContext)); + if (!ret) return NULL; ret->xfc = xfc; #ifdef USABLE_XRANDR + if (XRRQueryExtension(xfc->display, &ret->eventBase, &ret->errorBase)) { ret->haveXRandr = TRUE; } + #endif ret->lastSentWidth = ret->targetWidth = xfc->context.settings->DesktopWidth; ret->lastSentHeight = ret->targetHeight = xfc->context.settings->DesktopHeight; - PubSub_SubscribeActivated(xfc->context.pubSub, xf_disp_OnActivated); PubSub_SubscribeGraphicsReset(xfc->context.pubSub, xf_disp_OnGraphicsReset); PubSub_SubscribeTimer(xfc->context.pubSub, xf_disp_OnTimer); return ret; } -void xf_disp_free(xfDispContext *disp) +void xf_disp_free(xfDispContext* disp) { PubSub_UnsubscribeActivated(disp->xfc->context.pubSub, xf_disp_OnActivated); PubSub_UnsubscribeTimer(disp->xfc->context.pubSub, xf_disp_OnTimer); free(disp); } -static UINT xf_disp_sendLayout(DispClientContext *disp, rdpMonitor *monitors, int nmonitors) +static UINT xf_disp_sendLayout(DispClientContext* disp, rdpMonitor* monitors, int nmonitors) { UINT ret = CHANNEL_RC_OK; - DISPLAY_CONTROL_MONITOR_LAYOUT *layouts; + DISPLAY_CONTROL_MONITOR_LAYOUT* layouts; int i; - xfDispContext *xfDisp = (xfDispContext *)disp->custom; - rdpSettings *settings = xfDisp->xfc->context.settings; - + xfDispContext* xfDisp = (xfDispContext*)disp->custom; + rdpSettings* settings = xfDisp->xfc->context.settings; layouts = calloc(nmonitors, sizeof(DISPLAY_CONTROL_MONITOR_LAYOUT)); + if (!layouts) return CHANNEL_RC_NO_MEMORY; @@ -218,89 +240,81 @@ static UINT xf_disp_sendLayout(DispClientContext *disp, rdpMonitor *monitors, in layouts[i].PhysicalWidth = monitors[i].attributes.physicalWidth; layouts[i].PhysicalHeight = monitors[i].attributes.physicalHeight; - switch(monitors[i].attributes.orientation) + 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; + 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); - free(layouts); - return ret; } -BOOL xf_disp_handle_xevent(xfContext *xfc, XEvent *event) +BOOL xf_disp_handle_xevent(xfContext* xfc, XEvent* event) { - xfDispContext *xfDisp = xfc->xfDisp; - rdpSettings *settings = xfc->context.settings; + xfDispContext* xfDisp = xfc->xfDisp; + rdpSettings* settings = xfc->context.settings; UINT32 maxWidth, maxHeight; if (!xfDisp->haveXRandr) return TRUE; #ifdef USABLE_XRANDR + if (event->type != xfDisp->eventBase + RRScreenChangeNotify) return TRUE; + #endif - xf_detect_monitors(xfc, &maxWidth, &maxHeight); - return xf_disp_sendLayout(xfc->disp, settings->MonitorDefArray, settings->MonitorCount) == CHANNEL_RC_OK; + return xf_disp_sendLayout(xfc->disp, settings->MonitorDefArray, + settings->MonitorCount) == CHANNEL_RC_OK; } -BOOL xf_disp_handle_configureNotify(xfContext *xfc, int width, int height) +BOOL xf_disp_handle_configureNotify(xfContext* xfc, int width, int height) { - xfDispContext *xfDisp = xfc->xfDisp; - - if (xfDisp->lastSentWidth == width && xfDisp->lastSentHeight == height) - return TRUE; - - if (xfDisp->waitingResize || !xfDisp->activated || - (GetTickCount64() - xfDisp->lastSentDate < RESIZE_MIN_DELAY)) - { - WLog_DBG(TAG, "delaying resize to %dx%d", width, height); - xfDisp->targetWidth = width; - xfDisp->targetHeight = height; - return TRUE; - } - - WLog_DBG(TAG, "resizing on ConfigureNotify to %dx%d", width, height); - return xf_disp_sendResize(xfDisp, width, height); + xfDispContext* xfDisp = xfc->xfDisp; + xfDisp->targetWidth = width; + xfDisp->targetHeight = height; + return xf_disp_sendResize(xfDisp); } -UINT xf_DisplayControlCaps(DispClientContext *disp, UINT32 maxNumMonitors, UINT32 maxMonitorAreaFactorA, UINT32 maxMonitorAreaFactorB) +UINT xf_DisplayControlCaps(DispClientContext* disp, UINT32 maxNumMonitors, + UINT32 maxMonitorAreaFactorA, UINT32 maxMonitorAreaFactorB) { /* we're called only if dynamic resolution update is activated */ - xfDispContext *xfDisp = (xfDispContext *)disp->custom; - rdpSettings *settings = xfDisp->xfc->context.settings; - - WLog_DBG(TAG, "DisplayControlCapsPdu: MaxNumMonitors: %"PRIu32" MaxMonitorAreaFactorA: %"PRIu32" MaxMonitorAreaFactorB: %"PRIu32"", - maxNumMonitors, maxMonitorAreaFactorA, maxMonitorAreaFactorB); - + xfDispContext* xfDisp = (xfDispContext*)disp->custom; + rdpSettings* settings = xfDisp->xfc->context.settings; + WLog_DBG(TAG, + "DisplayControlCapsPdu: MaxNumMonitors: %"PRIu32" MaxMonitorAreaFactorA: %"PRIu32" MaxMonitorAreaFactorB: %"PRIu32"", + maxNumMonitors, maxMonitorAreaFactorA, maxMonitorAreaFactorB); xfDisp->activated = TRUE; if (settings->Fullscreen) @@ -310,9 +324,9 @@ UINT xf_DisplayControlCaps(DispClientContext *disp, UINT32 maxNumMonitors, UINT3 return xf_disp_set_window_resizable(xfDisp) ? CHANNEL_RC_OK : CHANNEL_RC_NO_MEMORY; } -BOOL xf_disp_init(xfContext* xfc, DispClientContext *disp) +BOOL xf_disp_init(xfContext* xfc, DispClientContext* disp) { - rdpSettings *settings = xfc->context.settings; + rdpSettings* settings = xfc->context.settings; xfc->disp = disp; disp->custom = (void*) xfc->xfDisp; @@ -320,11 +334,13 @@ BOOL xf_disp_init(xfContext* xfc, DispClientContext *disp) { disp->DisplayControlCaps = xf_DisplayControlCaps; #ifdef USABLE_XRANDR + if (settings->Fullscreen) { /* ask X11 to notify us of screen changes */ XRRSelectInput(xfc->display, DefaultRootWindow(xfc->display), RRScreenChangeNotifyMask); } + #endif }