RemoteApp Support
authorbjcollins <bcollins@trustedcs.com>
Thu, 15 Oct 2015 23:41:55 +0000 (18:41 -0500)
committerbjcollins <bcollins@trustedcs.com>
Thu, 15 Oct 2015 23:41:55 +0000 (18:41 -0500)
1. Remove all uses of "localWindowOffsetCorr" variables, they added an extra layer of complexity and they are not actually needed to handle coordination of window position/size between
the local coordinate system and the remote one. This logic was causing issues in the case where the window was moved off the left side of the screen.

2. Update the xf_setWindowVisibilityRects function to offset the visibility rects as necessary when the window is hanging off the left side of the screen.

3. Stop sending mouse events when doing keyboard moves/sizes(as desired), and stop sending two mouse events for non-keyboard moves/sizes

4. Move location of new UTF8_STRING variable from previous commit

5. Refresh window and window shape for any window position/size updates, this helps keep the local and server windows in sync and works around some race conditions

client/X11/xf_client.c
client/X11/xf_event.c
client/X11/xf_rail.c
client/X11/xf_window.c
client/X11/xf_window.h

index 49684cb..a7afe4b 100644 (file)
@@ -1865,11 +1865,12 @@ static BOOL xfreerdp_client_new(freerdp* instance, rdpContext* context)
        xfc->_NET_WM_STATE_SKIP_PAGER = XInternAtom(xfc->display, "_NET_WM_STATE_SKIP_PAGER", False);
        xfc->_NET_WM_MOVERESIZE = XInternAtom(xfc->display, "_NET_WM_MOVERESIZE", False);
        xfc->_NET_MOVERESIZE_WINDOW = XInternAtom(xfc->display, "_NET_MOVERESIZE_WINDOW", False);
+
+       xfc->UTF8_STRING = XInternAtom(xfc->display, "UTF8_STRING", FALSE);
        xfc->WM_PROTOCOLS = XInternAtom(xfc->display, "WM_PROTOCOLS", False);
        xfc->WM_DELETE_WINDOW = XInternAtom(xfc->display, "WM_DELETE_WINDOW", False);
        xfc->WM_STATE = XInternAtom(xfc->display, "WM_STATE", False);
 
-       xfc->UTF8_STRING = XInternAtom(xfc->display, "UTF8_STRING", FALSE);
        xfc->xfds = ConnectionNumber(xfc->display);
        xfc->screen_number = DefaultScreen(xfc->display);
        xfc->screen = ScreenOfDisplay(xfc->display, xfc->screen_number);
index 5f13d50..18328f3 100644 (file)
@@ -278,7 +278,8 @@ BOOL xf_generic_MotionNotify(xfContext* xfc, int x, int y, int state, Window win
 
        xf_event_adjust_coordinates(xfc, &x, &y);
 
-       input->MouseEvent(input, PTR_FLAGS_MOVE, x, y);
+       if (!app || xf_AppWindowFromX11Window(xfc,window)->local_move.direction != RAIL_WMSZ_KEYSIZE)
+               input->MouseEvent(input, PTR_FLAGS_MOVE, x, y);
 
        if (xfc->fullscreen && !app)
        {
index d5e9495..22a941c 100644 (file)
@@ -119,25 +119,17 @@ void xf_rail_adjust_position(xfContext* xfc, xfAppWindow* appWindow)
                return;
 
        /* If current window position disagrees with RDP window position, send update to RDP server */
-       if (appWindow->x != (appWindow->windowOffsetX - appWindow->localWindowOffsetCorrX) ||
-                       appWindow->y != (appWindow->windowOffsetY - appWindow->localWindowOffsetCorrY) ||
+       if (appWindow->x != appWindow->windowOffsetX ||
+                       appWindow->y != appWindow->windowOffsetY ||
                        appWindow->width != appWindow->windowWidth ||
                        appWindow->height != appWindow->windowHeight)
        {
-               /*
-                * windowOffset corresponds to the window location on the rail server
-                * but our local window is based uses a local offset since the windowOffset
-                * can be negative and but X does not support negative values. Not using an 
-                * offset can result in blank areas for a maximized window
-                */
                windowMove.windowId = appWindow->windowId;
                /*
                 * Calculate new size/position for the rail window(new values for windowOffsetX/windowOffsetY/windowWidth/windowHeight) on the server
-                * New position is based on: Current local rail window offset +
-                * Local offset correction(current correction value to translate the local window offset to the server rail window offset)
                 */
-               windowMove.left = appWindow->x + appWindow->localWindowOffsetCorrX;
-               windowMove.top = appWindow->y + appWindow->localWindowOffsetCorrY;
+               windowMove.left = appWindow->x;
+               windowMove.top = appWindow->y;
                windowMove.right = windowMove.left + appWindow->width;
                windowMove.bottom = windowMove.top + appWindow->height;
 
@@ -163,12 +155,10 @@ void xf_rail_end_local_move(xfContext* xfc, xfAppWindow* appWindow)
 
        /*
         * Calculate new size/position for the rail window(new values for windowOffsetX/windowOffsetY/windowWidth/windowHeight) on the server
-        * New position is based on: Current local rail window offset +
-        * Local offset correction(current correction value to translate the local window offset to the server rail window offset)
         *
         */
-       windowMove.left = appWindow->x + appWindow->localWindowOffsetCorrX;
-       windowMove.top = appWindow->y + appWindow->localWindowOffsetCorrY;
+       windowMove.left = appWindow->x;
+       windowMove.top = appWindow->y;
        windowMove.right = windowMove.left + appWindow->width; /* In the update to RDP the position is one past the window */
        windowMove.bottom = windowMove.top + appWindow->height;
 
@@ -180,8 +170,6 @@ void xf_rail_end_local_move(xfContext* xfc, xfAppWindow* appWindow)
        XQueryPointer(xfc->display, appWindow->handle,
                        &root_window, &child_window, &x, &y, &child_x, &child_y, &mask);
 
-       input->MouseEvent(input, PTR_FLAGS_BUTTON1, x, y);
-
        /* only send the mouse coordinates if not a keyboard move or size */
        if ((appWindow->local_move.direction != _NET_WM_MOVERESIZE_MOVE_KEYBOARD) &&
                        (appWindow->local_move.direction != _NET_WM_MOVERESIZE_SIZE_KEYBOARD))
@@ -194,8 +182,8 @@ void xf_rail_end_local_move(xfContext* xfc, xfAppWindow* appWindow)
         * we can start to receive GDI orders for the new window dimensions before we
         * receive the RAIL ORDER for the new window size.  This avoids that race condition.
         */
-       appWindow->windowOffsetX = windowMove.left;
-       appWindow->windowOffsetY = windowMove.top;
+       appWindow->windowOffsetX = appWindow->x;
+       appWindow->windowOffsetY = appWindow->y;
        appWindow->windowWidth = appWindow->width;
        appWindow->windowHeight = appWindow->height;
        appWindow->local_move.state = LMS_TERMINATING;
@@ -277,6 +265,7 @@ static BOOL xf_rail_window_common(rdpContext* context, WINDOW_ORDER_INFO* orderI
        xfAppWindow* appWindow = NULL;
        xfContext* xfc = (xfContext*) context;
        UINT32 fieldFlags = orderInfo->fieldFlags;
+       BOOL position_or_size_updated = FALSE;
 
        if (fieldFlags & WINDOW_ORDER_STATE_NEW)
        {
@@ -296,9 +285,6 @@ static BOOL xf_rail_window_common(rdpContext* context, WINDOW_ORDER_INFO* orderI
                appWindow->width = appWindow->windowWidth = windowState->windowWidth;
                appWindow->height = appWindow->windowHeight = windowState->windowHeight;
 
-               appWindow->localWindowOffsetCorrX = 0;
-               appWindow->localWindowOffsetCorrY = 0;
-
                /* Ensure window always gets a window title */
                if (fieldFlags & WINDOW_ORDER_FIELD_TITLE)
                {
@@ -332,37 +318,31 @@ static BOOL xf_rail_window_common(rdpContext* context, WINDOW_ORDER_INFO* orderI
        if (!appWindow)
                return FALSE;
 
-       /* Update Parameters */
-
+       /* Keep track of any position/size update so that we can force a refresh of the window */
        if ((fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET) ||
-               (fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE))
+               (fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE)   ||
+               (fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET) ||
+               (fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE) ||
+               (fieldFlags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA) ||
+               (fieldFlags & WINDOW_ORDER_FIELD_VIS_OFFSET) ||
+               (fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY))
        {
-               if (fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET)
-               {
-                       appWindow->windowOffsetX = windowState->windowOffsetX;
-                       appWindow->windowOffsetY = windowState->windowOffsetY;
+               position_or_size_updated = TRUE;
+       }                               
 
-                       /*
-                        * The rail server can give negative window coordinates when updating windowOffsetX and windowOffsetY,
-                        * but we can only send unsigned integers to the rail server. Therefore, we maintain a local offset.
-                        */
 
-                       if (appWindow->windowOffsetX < 0)
-                               appWindow->localWindowOffsetCorrX = 0 - appWindow->windowOffsetX;
-                       else
-                               appWindow->localWindowOffsetCorrX = 0;
+       /* Update Parameters */
 
-                       if (appWindow->windowOffsetY < 0)
-                               appWindow->localWindowOffsetCorrY = 0 - appWindow->windowOffsetY;
-                       else
-                               appWindow->localWindowOffsetCorrY = 0;
-               }
+       if (fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET)
+       {
+               appWindow->windowOffsetX = windowState->windowOffsetX;
+               appWindow->windowOffsetY = windowState->windowOffsetY;
+       }
 
-               if (fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE)
-               {
-                       appWindow->windowWidth = windowState->windowWidth;
-                       appWindow->windowHeight = windowState->windowHeight;
-               }
+       if (fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE)
+       {
+               appWindow->windowWidth = windowState->windowWidth;
+               appWindow->windowHeight = windowState->windowHeight;
        }
 
        if (fieldFlags & WINDOW_ORDER_FIELD_OWNER)
@@ -478,42 +458,43 @@ static BOOL xf_rail_window_common(rdpContext* context, WINDOW_ORDER_INFO* orderI
                        xf_SetWindowText(xfc, appWindow, appWindow->title);
        }
 
-       if ((fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET) ||
-                       (fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE))
+       if (position_or_size_updated)
        {
+               UINT32 visibilityRectsOffsetX = (appWindow->visibleOffsetX - (appWindow->clientOffsetX - appWindow->windowClientDeltaX));
+               UINT32 visibilityRectsOffsetY = (appWindow->visibleOffsetY - (appWindow->clientOffsetY - appWindow->windowClientDeltaY));
+
                /*
                 * The rail server like to set the window to a small size when it is minimized even though it is hidden
                 * in some cases this can cause the window not to restore back to its original size. Therefore we don't
                 * update our local window when that rail window state is minimized
                 */
-               if (appWindow->rail_state == WINDOW_SHOW_MINIMIZED)
-                       return TRUE;
+               if (appWindow->rail_state != WINDOW_SHOW_MINIMIZED)
+               {
 
-               /* Do nothing if window is already in the correct position */
-               if (appWindow->x == (appWindow->windowOffsetX - appWindow->localWindowOffsetCorrX) &&
-                               appWindow->y == (appWindow->windowOffsetY - appWindow->localWindowOffsetCorrY) &&
+                       /* Redraw window area if already in the correct position */
+                       if (appWindow->x == appWindow->windowOffsetX &&
+                               appWindow->y == appWindow->windowOffsetY &&
                                appWindow->width == appWindow->windowWidth &&
                                appWindow->height == appWindow->windowHeight)
-               {
-                       xf_UpdateWindowArea(xfc, appWindow, 0, 0, appWindow->windowWidth, appWindow->windowHeight);
-               }
-               else
-               {
-                       xf_MoveWindow(xfc, appWindow, appWindow->windowOffsetX - appWindow->localWindowOffsetCorrX, appWindow->windowOffsetY - appWindow->localWindowOffsetCorrY,
-                               appWindow->windowWidth, appWindow->windowHeight);
+                       {
+                               xf_UpdateWindowArea(xfc, appWindow, 0, 0, appWindow->windowWidth, appWindow->windowHeight);
+                       }
+                       else
+                       {
+                               xf_MoveWindow(xfc, appWindow, appWindow->windowOffsetX, appWindow->windowOffsetY,
+                                       appWindow->windowWidth, appWindow->windowHeight);
+                       }
+
+                       xf_SetWindowVisibilityRects(xfc, appWindow, visibilityRectsOffsetX, visibilityRectsOffsetY, appWindow->visibilityRects, appWindow->numVisibilityRects);
                }
        }
 
-       if (fieldFlags & WINDOW_ORDER_FIELD_WND_RECTS)
+       /* We should only be using the visibility rects for shaping the window */
+       /*if (fieldFlags & WINDOW_ORDER_FIELD_WND_RECTS)
        {
-               /* We should only be using the visibility rects for shaping the window */
-               //xf_SetWindowRects(xfc, appWindow, appWindow->windowRects, appWindow->numWindowRects);
-       }
+               xf_SetWindowRects(xfc, appWindow, appWindow->windowRects, appWindow->numWindowRects);
+       }*/
 
-       if (fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY)
-       {
-               xf_SetWindowVisibilityRects(xfc, appWindow, appWindow->visibilityRects, appWindow->numVisibilityRects);
-       }
        return TRUE;
 }
 
index b9810e5..f4c832b 100644 (file)
@@ -927,7 +927,7 @@ void xf_SetWindowRects(xfContext* xfc, xfAppWindow* appWindow, RECTANGLE_16* rec
 
 }
 
-void xf_SetWindowVisibilityRects(xfContext* xfc, xfAppWindow* appWindow, RECTANGLE_16* rects, int nrects)
+void xf_SetWindowVisibilityRects(xfContext* xfc, xfAppWindow* appWindow, UINT32 rectsOffsetX, UINT32 rectsOffsetY, RECTANGLE_16* rects, int nrects)
 {
        int i;
        XRectangle* xrects;
@@ -946,7 +946,7 @@ void xf_SetWindowVisibilityRects(xfContext* xfc, xfAppWindow* appWindow, RECTANG
                xrects[i].height = rects[i].bottom - rects[i].top;
        }
 
-       XShapeCombineRectangles(xfc->display, appWindow->handle, ShapeBounding, 0, 0, xrects, nrects, ShapeSet, 0);
+       XShapeCombineRectangles(xfc->display, appWindow->handle, ShapeBounding, rectsOffsetX, rectsOffsetY, xrects, nrects, ShapeSet, 0);
        free(xrects);
 #endif
 
@@ -955,20 +955,14 @@ void xf_SetWindowVisibilityRects(xfContext* xfc, xfAppWindow* appWindow, RECTANG
 void xf_UpdateWindowArea(xfContext* xfc, xfAppWindow* appWindow, int x, int y, int width, int height)
 {
        int ax, ay;
-       UINT32 translatedWindowOffsetX;
-       UINT32 translatedWindowOffsetY;
-
-       /* Translate the server rail window offset to a local offset */
-       translatedWindowOffsetX = (appWindow->windowOffsetX - appWindow->localWindowOffsetCorrX);
-       translatedWindowOffsetY = (appWindow->windowOffsetY - appWindow->localWindowOffsetCorrY);
 
-       ax = x + translatedWindowOffsetX;
-       ay = y + translatedWindowOffsetY;
+       ax = x + appWindow->windowOffsetX;
+       ay = y + appWindow->windowOffsetY;
 
-       if (ax + width > translatedWindowOffsetX + appWindow->width)
-               width = (translatedWindowOffsetX + appWindow->width - 1) - ax;
-       if (ay + height > translatedWindowOffsetY + appWindow->height)
-               height = (translatedWindowOffsetY + appWindow->height - 1) - ay;
+       if (ax + width > appWindow->windowOffsetX + appWindow->windowWidth)
+               width = (appWindow->windowOffsetX + appWindow->windowWidth - 1) - ax;
+       if (ay + height > appWindow->windowOffsetY + appWindow->windowHeight)
+               height = (appWindow->windowOffsetY + appWindow->windowHeight - 1) - ay;
 
        xf_lock_x11(xfc, TRUE);
 
index 2fd9de2..0a41c79 100644 (file)
@@ -160,7 +160,7 @@ void xf_MoveWindow(xfContext* xfc, xfAppWindow* appWindow, int x, int y, int wid
 void xf_ShowWindow(xfContext* xfc, xfAppWindow* appWindow, BYTE state);
 //void xf_SetWindowIcon(xfContext* xfc, xfAppWindow* appWindow, rdpIcon* icon);
 void xf_SetWindowRects(xfContext* xfc, xfAppWindow* appWindow, RECTANGLE_16* rects, int nrects);
-void xf_SetWindowVisibilityRects(xfContext* xfc, xfAppWindow* appWindow, RECTANGLE_16* rects, int nrects);
+void xf_SetWindowVisibilityRects(xfContext* xfc, xfAppWindow* appWindow, UINT32 rectsOffsetX, UINT32 rectsOffsetY, RECTANGLE_16* rects, int nrects);
 void xf_SetWindowStyle(xfContext* xfc, xfAppWindow* appWindow, UINT32 style, UINT32 ex_style);
 void xf_UpdateWindowArea(xfContext* xfc, xfAppWindow* appWindow, int x, int y, int width, int height);
 void xf_DestroyWindow(xfContext* xfc, xfAppWindow* appWindow);