From ee8d0a64405dbd13b1b83835c64e049fde18866b Mon Sep 17 00:00:00 2001 From: bjcollins Date: Wed, 11 Feb 2015 17:24:06 -0600 Subject: [PATCH] Fix remote app in xfreerdp. Remove use of the visibleOffset, this completely breaks the display of all windows except for the main application window. Instead, just maintain a local offset correction of the windowOffset. Apply workaround to determining the workArea for remote app mode. --- client/X11/xf_monitor.c | 7 +++- client/X11/xf_rail.c | 88 ++++++++++++++++++----------------------- client/X11/xf_window.c | 18 ++++++--- client/X11/xf_window.h | 3 ++ 4 files changed, 60 insertions(+), 56 deletions(-) diff --git a/client/X11/xf_monitor.c b/client/X11/xf_monitor.c index 65689e1c5..0afaafb33 100644 --- a/client/X11/xf_monitor.c +++ b/client/X11/xf_monitor.c @@ -163,7 +163,12 @@ BOOL xf_detect_monitors(xfContext* xfc) } #endif - if (!xf_GetWorkArea(xfc)) + /* WORKAROUND: With Remote Application Mode - using NET_WM_WORKAREA + * causes issues with the ability to fully size the window vertically + * (the bottom of the window area is never updated). So, we just set + * the workArea to match the full Screen width/height. + */ + if (settings->RemoteApplicationMode || !xf_GetWorkArea(xfc)) { xfc->workArea.x = 0; xfc->workArea.y = 0; diff --git a/client/X11/xf_rail.c b/client/X11/xf_rail.c index cad67bea5..8a6330b9c 100644 --- a/client/X11/xf_rail.c +++ b/client/X11/xf_rail.c @@ -113,43 +113,31 @@ void xf_rail_send_client_system_command(xfContext* xfc, UINT32 windowId, UINT16 */ void xf_rail_adjust_position(xfContext* xfc, xfAppWindow* appWindow) { - UINT32 offsetX = 0; - UINT32 offsetY = 0; RAIL_WINDOW_MOVE_ORDER windowMove; if (!appWindow->is_mapped || appWindow->local_move.state != LMS_NOT_ACTIVE) return; /* If current window position disagrees with RDP window position, send update to RDP server */ - if (appWindow->x != appWindow->visibleOffsetX || - appWindow->y != appWindow->visibleOffsetY || + if (appWindow->x != (appWindow->windowOffsetX - appWindow->localWindowOffsetCorrX) || + appWindow->y != (appWindow->windowOffsetY - appWindow->localWindowOffsetCorrY) || appWindow->width != appWindow->windowWidth || appWindow->height != appWindow->windowHeight) { - /* - * Although the rail server can give negative window coordinates when updating windowOffsetX and windowOffsetY, - * we can only send unsigned integers to the rail server. Therefore, we always bring negative coordinates up to 0 - * when attempting to adjust the rail window. - */ - - if (appWindow->windowOffsetX < 0) - offsetX = offsetX - appWindow->windowOffsetX; - - if (appWindow->windowOffsetY < 0) - offsetY = offsetY - appWindow->windowOffsetY; - /* * windowOffset corresponds to the window location on the rail server - * but our local window is based on the visibleOffset since using the windowOffset - * can result in blank areas for a maximized window + * 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 offsets for the rail server window - * Negative offset correction + rail server window offset + (difference in visibleOffset and new window local offset) + * 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 = offsetX + appWindow->windowOffsetX + (appWindow->x - appWindow->visibleOffsetX); - windowMove.top = offsetY + appWindow->windowOffsetY + (appWindow->y - appWindow->visibleOffsetY); + windowMove.left = appWindow->x + appWindow->localWindowOffsetCorrX; + windowMove.top = appWindow->y + appWindow->localWindowOffsetCorrY; windowMove.right = windowMove.left + appWindow->width; windowMove.bottom = windowMove.top + appWindow->height; @@ -162,37 +150,25 @@ void xf_rail_end_local_move(xfContext* xfc, xfAppWindow* appWindow) int x, y; int child_x; int child_y; - UINT32 offsetX = 0; - UINT32 offsetY = 0; unsigned int mask; Window root_window; Window child_window; RAIL_WINDOW_MOVE_ORDER windowMove; rdpInput* input = xfc->instance->input; - /* - * Although the rail server can give negative window coordinates when updating windowOffsetX and windowOffsetY, - * we can only send unsigned integers to the rail server. Therefore, we always bring negative coordinates up to 0 when - * attempting to adjust the rail window. - */ - - if (appWindow->windowOffsetX < 0) - offsetX = offsetX - appWindow->windowOffsetX; - - if (appWindow->windowOffsetY < 0) - offsetY = offsetY - appWindow->windowOffsetY; - /* * For keyboard moves send and explicit update to RDP server */ windowMove.windowId = appWindow->windowId; /* - * Calculate new offsets for the rail server window - * Negative offset correction + rail server window offset + (difference in visibleOffset and new window local offset) + * 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 = offsetX + appWindow->windowOffsetX + (appWindow->x - appWindow->visibleOffsetX); - windowMove.top = offsetY + appWindow->windowOffsetY + (appWindow->y - appWindow->visibleOffsetY); + windowMove.left = appWindow->x + appWindow->localWindowOffsetCorrX; + windowMove.top = appWindow->y + appWindow->localWindowOffsetCorrY; windowMove.right = windowMove.left + appWindow->width; /* In the update to RDP the position is one past the window */ windowMove.bottom = windowMove.top + appWindow->height; @@ -218,8 +194,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 = offsetX + appWindow->windowOffsetX + (appWindow->x - appWindow->visibleOffsetX); - appWindow->windowOffsetY = offsetY + appWindow->windowOffsetY + (appWindow->y - appWindow->visibleOffsetY); + appWindow->windowOffsetX = windowMove.left; + appWindow->windowOffsetY = windowMove.top; appWindow->windowWidth = appWindow->width; appWindow->windowHeight = appWindow->height; appWindow->local_move.state = LMS_TERMINATING; @@ -320,6 +296,9 @@ static void 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; + if (fieldFlags & WINDOW_ORDER_FIELD_TITLE) { char* title = NULL; @@ -358,6 +337,21 @@ static void xf_rail_window_common(rdpContext* context, WINDOW_ORDER_INFO* orderI { appWindow->windowOffsetX = windowState->windowOffsetX; appWindow->windowOffsetY = windowState->windowOffsetY; + + /* + * 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; + + if (appWindow->windowOffsetY < 0) + appWindow->localWindowOffsetCorrY = 0 - appWindow->windowOffsetY; + else + appWindow->localWindowOffsetCorrY = 0; } if (fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE) @@ -491,20 +485,16 @@ static void xf_rail_window_common(rdpContext* context, WINDOW_ORDER_INFO* orderI return; /* Do nothing if window is already in the correct position */ - if (appWindow->x == appWindow->visibleOffsetX && - appWindow->y == appWindow->visibleOffsetY && + if (appWindow->x == (appWindow->windowOffsetX - appWindow->localWindowOffsetCorrX) && + appWindow->y == (appWindow->windowOffsetY - appWindow->localWindowOffsetCorrY) && appWindow->width == appWindow->windowWidth && appWindow->height == appWindow->windowHeight) { - /* - * Just ensure entire window area is updated to handle cases where we - * have drawn locally before getting new bitmap from the server - */ xf_UpdateWindowArea(xfc, appWindow, 0, 0, appWindow->windowWidth, appWindow->windowHeight); return; } - xf_MoveWindow(xfc, appWindow, appWindow->visibleOffsetX, appWindow->visibleOffsetY, + xf_MoveWindow(xfc, appWindow, appWindow->windowOffsetX - appWindow->localWindowOffsetCorrX, appWindow->windowOffsetY - appWindow->localWindowOffsetCorrY, appWindow->windowWidth, appWindow->windowHeight); } diff --git a/client/X11/xf_window.c b/client/X11/xf_window.c index 38c32fabe..c04c979ff 100644 --- a/client/X11/xf_window.c +++ b/client/X11/xf_window.c @@ -886,14 +886,20 @@ 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; - ax = x + appWindow->visibleOffsetX; - ay = y + appWindow->visibleOffsetY; + /* Translate the server rail window offset to a local offset */ + translatedWindowOffsetX = (appWindow->windowOffsetX - appWindow->localWindowOffsetCorrX); + translatedWindowOffsetY = (appWindow->windowOffsetY - appWindow->localWindowOffsetCorrY); - if (ax + width > appWindow->visibleOffsetX + appWindow->width) - width = (appWindow->visibleOffsetX + appWindow->width - 1) - ax; - if (ay + height > appWindow->visibleOffsetY + appWindow->height) - height = (appWindow->visibleOffsetY + appWindow->height - 1) - ay; + ax = x + translatedWindowOffsetX; + ay = y + translatedWindowOffsetY; + + if (ax + width > translatedWindowOffsetX + appWindow->width) + width = (translatedWindowOffsetX + appWindow->width - 1) - ax; + if (ay + height > translatedWindowOffsetY + appWindow->height) + height = (translatedWindowOffsetY + appWindow->height - 1) - ay; xf_lock_x11(xfc, TRUE); diff --git a/client/X11/xf_window.h b/client/X11/xf_window.h index 990274483..70ae312ee 100644 --- a/client/X11/xf_window.h +++ b/client/X11/xf_window.h @@ -118,6 +118,9 @@ struct xf_app_window UINT32 numVisibilityRects; RECTANGLE_16* visibilityRects; + UINT32 localWindowOffsetCorrX; + UINT32 localWindowOffsetCorrY; + GC gc; int shmid; Window handle;