Merge pull request #2926 from bjcollins/rail_fixes

Rail fixes
This commit is contained in:
Norbert Federa 2015-11-06 13:34:42 +01:00
commit 3eee70b164
7 changed files with 109 additions and 117 deletions

View File

@ -342,7 +342,7 @@ BOOL xf_sw_end_paint(rdpContext* context)
xf_lock_x11(xfc, FALSE);
xf_rail_paint(xfc, x, y, x + w - 1, y + h - 1);
xf_rail_paint(xfc, x, y, x + w, y + h);
xf_unlock_x11(xfc, FALSE);
}
@ -455,7 +455,7 @@ BOOL xf_hw_end_paint(rdpContext* context)
xf_lock_x11(xfc, FALSE);
xf_rail_paint(xfc, x, y, x + w - 1, y + h - 1);
xf_rail_paint(xfc, x, y, x + w, y + h);
xf_unlock_x11(xfc, FALSE);
}
@ -1852,7 +1852,11 @@ static BOOL xfreerdp_client_new(freerdp* instance, rdpContext* context)
xfc->_NET_WORKAREA = XInternAtom(xfc->display, "_NET_WORKAREA", False);
xfc->_NET_WM_STATE = XInternAtom(xfc->display, "_NET_WM_STATE", False);
xfc->_NET_WM_STATE_FULLSCREEN = XInternAtom(xfc->display, "_NET_WM_STATE_FULLSCREEN", False);
xfc->_NET_WM_STATE_MAXIMIZED_HORZ = XInternAtom(xfc->display, "_NET_WM_STATE_MAXIMIZED_HORZ", False);
xfc->_NET_WM_STATE_MAXIMIZED_VERT = XInternAtom(xfc->display, "_NET_WM_STATE_MAXIMIZED_VERT", False);
xfc->_NET_WM_FULLSCREEN_MONITORS = XInternAtom(xfc->display, "_NET_WM_FULLSCREEN_MONITORS", False);
xfc->_NET_WM_NAME = XInternAtom(xfc->display, "_NET_WM_NAME", False);
xfc->_NET_WM_PID = XInternAtom(xfc->display, "_NET_WM_PID", False);
xfc->_NET_WM_WINDOW_TYPE = XInternAtom(xfc->display, "_NET_WM_WINDOW_TYPE", False);
xfc->_NET_WM_WINDOW_TYPE_NORMAL = XInternAtom(xfc->display, "_NET_WM_WINDOW_TYPE_NORMAL", False);
xfc->_NET_WM_WINDOW_TYPE_DIALOG = XInternAtom(xfc->display, "_NET_WM_WINDOW_TYPE_DIALOG", False);
@ -1863,6 +1867,8 @@ 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);

View File

@ -466,7 +466,7 @@ BOOL xf_keyboard_handle_special_keys(xfContext* xfc, KeySym keysym)
return TRUE;
}
if(xfc->fullscreen_toggle)
if(!xfc->remote_app && xfc->fullscreen_toggle)
{
if (keysym == XK_Return)
{

View 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,7 @@ 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)
{
char* title = NULL;
@ -321,8 +308,6 @@ static BOOL xf_rail_window_common(rdpContext* context, WINDOW_ORDER_INFO* orderI
HashTable_Add(xfc->railWindows, (void*) (UINT_PTR) orderInfo->windowId, (void*) appWindow);
xf_AppWindowInit(xfc, appWindow);
return TRUE;
}
else
{
@ -333,37 +318,31 @@ static BOOL xf_rail_window_common(rdpContext* context, WINDOW_ORDER_INFO* orderI
if (!appWindow)
return FALSE;
/* 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_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))
{
position_or_size_updated = TRUE;
}
/* Update Parameters */
if ((fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET) ||
(fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE))
if (fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET)
{
if (fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET)
{
appWindow->windowOffsetX = windowState->windowOffsetX;
appWindow->windowOffsetY = windowState->windowOffsetY;
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)
{
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)
@ -479,41 +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)
{
xf_SetWindowRects(xfc, appWindow, appWindow->windowRects, appWindow->numWindowRects);
}
}*/
if (fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY)
{
xf_SetWindowVisibilityRects(xfc, appWindow, appWindow->visibilityRects, appWindow->numVisibilityRects);
}
return TRUE;
}

View File

@ -334,7 +334,7 @@ static void xf_SetWindowPID(xfContext* xfc, Window window, pid_t pid)
if (!pid)
pid = getpid();
am_wm_pid = XInternAtom(xfc->display, "_NET_WM_PID", False);
am_wm_pid = xfc->_NET_WM_PID;
XChangeProperty(xfc->display, window, am_wm_pid, XA_CARDINAL,
32, PropModeReplace, (BYTE*) &pid, 1);
@ -574,9 +574,11 @@ void xf_SetWindowStyle(xfContext* xfc, xfAppWindow* appWindow, UINT32 style, UIN
}
else
{
XChangeProperty(xfc->display, appWindow->handle, xfc->_NET_WM_WINDOW_TYPE,
XA_ATOM, 32, PropModeReplace, (BYTE*) &window_type, 1);
window_type = xfc->_NET_WM_WINDOW_TYPE_NORMAL;
}
XChangeProperty(xfc->display, appWindow->handle, xfc->_NET_WM_WINDOW_TYPE,
XA_ATOM, 32, PropModeReplace, (BYTE*) &window_type, 1);
}
void xf_SetWindowText(xfContext* xfc, xfAppWindow* appWindow, char* name)
@ -584,8 +586,8 @@ void xf_SetWindowText(xfContext* xfc, xfAppWindow* appWindow, char* name)
const size_t i = strlen(name);
XStoreName(xfc->display, appWindow->handle, name);
Atom wm_Name = XInternAtom(xfc->display, "_NET_WM_NAME", FALSE);
Atom utf8Str = XInternAtom(xfc->display, "UTF8_STRING", FALSE);
Atom wm_Name = xfc->_NET_WM_NAME;
Atom utf8Str = xfc->UTF8_STRING;
XChangeProperty(xfc->display, appWindow->handle, wm_Name, utf8Str, 8,
PropModeReplace, (unsigned char *)name, i);
@ -828,9 +830,10 @@ void xf_ShowWindow(xfContext* xfc, xfAppWindow* appWindow, BYTE state)
case WINDOW_SHOW_MAXIMIZED:
/* Set the window as maximized */
xf_SendClientEvent(xfc, appWindow->handle, xfc->_NET_WM_STATE, 4, 1,
XInternAtom(xfc->display, "_NET_WM_STATE_MAXIMIZED_VERT", False),
XInternAtom(xfc->display, "_NET_WM_STATE_MAXIMIZED_HORZ", False), 0);
xf_SendClientEvent(xfc, appWindow->handle, xfc->_NET_WM_STATE, 4,
_NET_WM_STATE_ADD,
xfc->_NET_WM_STATE_MAXIMIZED_VERT,
xfc->_NET_WM_STATE_MAXIMIZED_HORZ, 0);
/*
* This is a workaround for the case where the window is maximized locally before the rail server is told to maximize
* the window, this appears to be a race condition where the local window with incomplete data and once the window is
@ -845,9 +848,10 @@ void xf_ShowWindow(xfContext* xfc, xfAppWindow* appWindow, BYTE state)
case WINDOW_SHOW:
/* Ensure the window is not maximized */
xf_SendClientEvent(xfc, appWindow->handle, xfc->_NET_WM_STATE, 4, 0,
XInternAtom(xfc->display, "_NET_WM_STATE_MAXIMIZED_VERT", False),
XInternAtom(xfc->display, "_NET_WM_STATE_MAXIMIZED_HORZ", False), 0);
xf_SendClientEvent(xfc, appWindow->handle, xfc->_NET_WM_STATE, 4,
_NET_WM_STATE_REMOVE,
xfc->_NET_WM_STATE_MAXIMIZED_VERT,
xfc->_NET_WM_STATE_MAXIMIZED_HORZ, 0);
/*
* Ignore configure requests until both the Maximized properties have been processed
* to prevent condition where WM overrides size of request due to one or both of these properties
@ -930,7 +934,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;
@ -949,7 +953,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
@ -958,20 +962,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 + appWindow->windowOffsetX;
ay = y + appWindow->windowOffsetY;
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;
if (ax + width > appWindow->windowOffsetX + appWindow->width)
width = (appWindow->windowOffsetX + appWindow->width - 1) - ax;
if (ay + height > appWindow->windowOffsetY + appWindow->height)
height = (appWindow->windowOffsetY + appWindow->height - 1) - ay;
xf_lock_x11(xfc, TRUE);

View File

@ -102,22 +102,22 @@ struct xf_app_window
UINT32 dwExStyle;
UINT32 showState;
UINT32 clientOffsetX;
UINT32 clientOffsetY;
INT32 clientOffsetX;
INT32 clientOffsetY;
UINT32 clientAreaWidth;
UINT32 clientAreaHeight;
UINT32 windowOffsetX;
UINT32 windowOffsetY;
UINT32 windowClientDeltaX;
UINT32 windowClientDeltaY;
INT32 windowOffsetX;
INT32 windowOffsetY;
INT32 windowClientDeltaX;
INT32 windowClientDeltaY;
UINT32 windowWidth;
UINT32 windowHeight;
UINT32 numWindowRects;
RECTANGLE_16* windowRects;
UINT32 visibleOffsetX;
UINT32 visibleOffsetY;
INT32 visibleOffsetX;
INT32 visibleOffsetY;
UINT32 numVisibilityRects;
RECTANGLE_16* visibilityRects;
@ -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);

View File

@ -185,6 +185,8 @@ struct xf_context
xfClipboard* clipboard;
CliprdrClientContext* cliprdr;
Atom UTF8_STRING;
Atom _NET_WM_ICON;
Atom _MOTIF_WM_HINTS;
Atom _NET_CURRENT_DESKTOP;
@ -192,11 +194,16 @@ struct xf_context
Atom _NET_WM_STATE;
Atom _NET_WM_STATE_FULLSCREEN;
Atom _NET_WM_STATE_MAXIMIZED_HORZ;
Atom _NET_WM_STATE_MAXIMIZED_VERT;
Atom _NET_WM_STATE_SKIP_TASKBAR;
Atom _NET_WM_STATE_SKIP_PAGER;
Atom _NET_WM_FULLSCREEN_MONITORS;
Atom _NET_WM_NAME;
Atom _NET_WM_PID;
Atom _NET_WM_WINDOW_TYPE;
Atom _NET_WM_WINDOW_TYPE_NORMAL;
Atom _NET_WM_WINDOW_TYPE_DIALOG;

View File

@ -174,22 +174,22 @@ struct _WINDOW_STATE_ORDER
UINT32 extendedStyle;
UINT32 showState;
RAIL_UNICODE_STRING titleInfo;
UINT32 clientOffsetX;
UINT32 clientOffsetY;
INT32 clientOffsetX;
INT32 clientOffsetY;
UINT32 clientAreaWidth;
UINT32 clientAreaHeight;
UINT32 RPContent;
UINT32 rootParentHandle;
UINT32 windowOffsetX;
UINT32 windowOffsetY;
UINT32 windowClientDeltaX;
UINT32 windowClientDeltaY;
INT32 windowOffsetX;
INT32 windowOffsetY;
INT32 windowClientDeltaX;
INT32 windowClientDeltaY;
UINT32 windowWidth;
UINT32 windowHeight;
UINT32 numWindowRects;
RECTANGLE_16* windowRects;
UINT32 visibleOffsetX;
UINT32 visibleOffsetY;
INT32 visibleOffsetX;
INT32 visibleOffsetY;
UINT32 numVisibilityRects;
RECTANGLE_16* visibilityRects;
};