Fixed #4679, #4753 dynamic resizing
authorArmin Novak <armin.novak@thincast.com>
Wed, 18 Jul 2018 07:31:04 +0000 (09:31 +0200)
committerArmin Novak <armin.novak@thincast.com>
Wed, 18 Jul 2018 07:48:19 +0000 (09:48 +0200)
Simplified resize logic, do not check before setting current resolution.

client/X11/xf_client.c
client/X11/xf_disp.c

index fba5b4a..7c880fd 100644 (file)
@@ -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)
                        {
index 49d9601..c8f9b21 100644 (file)
@@ -39,7 +39,7 @@
 
 struct _xfDispContext
 {
-       xfContext *xfc;
+       xfContextxfc;
        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;
+
+       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, int width, int height)
+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(xfDispContextxfDisp)
 {
-       XSizeHints *size_hints;
+       XSizeHintssize_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;
+       xfDispContextxfDisp = xfc->xfDisp;
+       rdpSettingssettings = 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)
+xfDispContextxf_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(xfDispContextdisp)
 {
        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_LAYOUTlayouts;
        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;
+       xfDispContextxfDisp = xfc->xfDisp;
+       rdpSettingssettings = xfc->context.settings;
        UINT32 maxWidth, maxHeight;
 
        if (!xfDisp->haveXRandr)
                return TRUE;
 
 #ifdef USABLE_XRANDR
+
        if (event->type != xfDisp->eventBase + RRScreenChangeNotify)
                return TRUE;
-#endif
 
+#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(xfContextxfc, 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, DispClientContextdisp)
 {
-       rdpSettings *settings = xfc->context.settings;
+       rdpSettingssettings = 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
        }