From abf6d4f71ea901e31ee2d1b4625fa805af6b0cc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 12 Nov 2014 16:42:32 -0500 Subject: [PATCH] xfreerdp: prepare RAIL migration away from libfreerdp-rail --- client/X11/xf_event.c | 123 ++++---- client/X11/xf_rail.c | 662 +++++++++++++++++++++++++++-------------- client/X11/xf_window.c | 131 ++++++-- client/X11/xf_window.h | 33 +- client/X11/xfreerdp.h | 2 + 5 files changed, 625 insertions(+), 326 deletions(-) diff --git a/client/X11/xf_event.c b/client/X11/xf_event.c index ff9705f4f..8b83c1a99 100644 --- a/client/X11/xf_event.c +++ b/client/X11/xf_event.c @@ -208,15 +208,12 @@ static BOOL xf_event_Expose(xfContext* xfc, XEvent* event, BOOL app) } else { - rdpWindow* window; xfAppWindow* appWindow; - rdpRail* rail = ((rdpContext*) xfc)->rail; - window = window_list_get_by_extra_id(rail->list, (void*) event->xexpose.window); + appWindow = xf_AppWindowFromX11Window(xfc, event->xany.window); - if (window) + if (appWindow) { - appWindow = (xfAppWindow*) window->extra; xf_UpdateWindowArea(xfc, appWindow, x, y, w, h); } } @@ -246,7 +243,7 @@ BOOL xf_generic_MotionNotify(xfContext* xfc, int x, int y, int state, Window win if (app) { /* make sure window exists */ - if (!xf_rdpWindowFromWindow(xfc, window)) + if (!xf_AppWindowFromX11Window(xfc, window)) return TRUE; /* Translate to desktop coordinates */ @@ -351,7 +348,7 @@ BOOL xf_generic_ButtonPress(xfContext* xfc, int x, int y, int button, Window win if (app) { /* make sure window exists */ - if (!xf_rdpWindowFromWindow(xfc, window)) + if (!xf_AppWindowFromX11Window(xfc, window)) return TRUE; /* Translate to desktop coordinates */ @@ -398,7 +395,6 @@ BOOL xf_generic_ButtonRelease(xfContext* xfc, int x, int y, int button, Window w rdpInput* input; Window childWindow; - flags = 0; wheel = FALSE; extended = FALSE; @@ -442,7 +438,7 @@ BOOL xf_generic_ButtonRelease(xfContext* xfc, int x, int y, int button, Window w if (app) { /* make sure window exists */ - if (!xf_rdpWindowFromWindow(xfc, window)) + if (!xf_AppWindowFromX11Window(xfc, window)) return TRUE; /* Translate to desktop coordinates */ @@ -523,18 +519,15 @@ static BOOL xf_event_FocusIn(xfContext* xfc, XEvent* event, BOOL app) if (app) { - rdpWindow* window; xfAppWindow* appWindow; - rdpRail* rail = ((rdpContext*) xfc)->rail; xf_rail_send_activate(xfc, event->xany.window, TRUE); - window = window_list_get_by_extra_id(rail->list, (void*) event->xany.window); + appWindow = xf_AppWindowFromX11Window(xfc, event->xany.window); /* Update the server with any window changes that occurred while the window was not focused. */ - if (window) + if (appWindow) { - appWindow = (xfAppWindow*) window->extra; xf_rail_adjust_position(xfc, appWindow); } } @@ -582,15 +575,13 @@ static BOOL xf_event_ClientMessage(xfContext* xfc, XEvent* event, BOOL app) { if (app) { - DEBUG_X11("RAIL window closed"); - rdpWindow* window; - rdpRail* rail = ((rdpContext*) xfc)->rail; + xfAppWindow* appWindow; - window = window_list_get_by_extra_id(rail->list, (void*) event->xclient.window); + appWindow = xf_AppWindowFromX11Window(xfc, event->xany.window); - if (window) + if (appWindow) { - xf_rail_send_client_system_command(xfc, window->windowId, SC_CLOSE); + xf_rail_send_client_system_command(xfc, appWindow->windowId, SC_CLOSE); } return TRUE; @@ -619,17 +610,14 @@ static BOOL xf_event_EnterNotify(xfContext* xfc, XEvent* event, BOOL app) } else { + xfAppWindow* appWindow; + + appWindow = xf_AppWindowFromX11Window(xfc, event->xany.window); + /* keep track of which window has focus so that we can apply pointer updates */ - rdpWindow* window; - xfAppWindow* appWindow; - rdpRail* rail = ((rdpContext*) xfc)->rail; - - window = window_list_get_by_extra_id(rail->list, (void*) event->xexpose.window); - - if (window) + if (appWindow) { - appWindow = (xfAppWindow*) window->extra; xfc->appWindow = appWindow; } } @@ -650,21 +638,16 @@ static BOOL xf_event_LeaveNotify(xfContext* xfc, XEvent* event, BOOL app) static BOOL xf_event_ConfigureNotify(xfContext* xfc, XEvent* event, BOOL app) { - rdpWindow* window; - rdpRail* rail = ((rdpContext*) xfc)->rail; + Window childWindow; + xfAppWindow* appWindow; - if (!app || !rail) + if (!app) return TRUE; - window = window_list_get_by_extra_id(rail->list, (void*) event->xconfigure.window); + appWindow = xf_AppWindowFromX11Window(xfc, event->xany.window); - if (window) + if (appWindow) { - Window childWindow; - xfAppWindow* appWindow; - - appWindow = (xfAppWindow*) window->extra; - /* * ConfigureNotify coordinates are expressed relative to the window parent. * Translate these to root window coordinates. @@ -689,12 +672,18 @@ static BOOL xf_event_ConfigureNotify(xfContext* xfc, XEvent* event, BOOL app) xf_rail_adjust_position(xfc, appWindow); - window->windowOffsetX = appWindow->x; - window->visibleOffsetX = window->windowOffsetX; - window->windowOffsetY = appWindow->y; - window->visibleOffsetY = window->windowOffsetY; - window->windowWidth = appWindow->width; - window->windowHeight = appWindow->height; +#ifdef OLD_X11_RAIL + { + rdpWindow* window = appWindow->window; + + window->windowOffsetX = appWindow->x; + window->visibleOffsetX = window->windowOffsetX; + window->windowOffsetY = appWindow->y; + window->visibleOffsetY = window->windowOffsetY; + window->windowWidth = appWindow->width; + window->windowHeight = appWindow->height; + } +#endif } else { @@ -711,9 +700,8 @@ static BOOL xf_event_ConfigureNotify(xfContext* xfc, XEvent* event, BOOL app) static BOOL xf_event_MapNotify(xfContext* xfc, XEvent* event, BOOL app) { RECTANGLE_16 rect; - rdpWindow* window; + xfAppWindow* appWindow; rdpUpdate* update = xfc->instance->update; - rdpRail* rail = ((rdpContext*) xfc)->rail; if (!app) { @@ -726,9 +714,9 @@ static BOOL xf_event_MapNotify(xfContext* xfc, XEvent* event, BOOL app) } else { - window = window_list_get_by_extra_id(rail->list, (void*) event->xany.window); + appWindow = xf_AppWindowFromX11Window(xfc, event->xany.window); - if (window) + if (appWindow) { /* local restore event */ @@ -737,8 +725,7 @@ static BOOL xf_event_MapNotify(xfContext* xfc, XEvent* event, BOOL app) * that is minimized back to the maximized state */ - //xf_rail_send_client_system_command(xfc, window->windowId, SC_RESTORE); - xfAppWindow* appWindow = (xfAppWindow*) window->extra; + //xf_rail_send_client_system_command(xfc, appWindow->windowId, SC_RESTORE); appWindow->is_mapped = TRUE; } } @@ -748,9 +735,8 @@ static BOOL xf_event_MapNotify(xfContext* xfc, XEvent* event, BOOL app) static BOOL xf_event_UnmapNotify(xfContext* xfc, XEvent* event, BOOL app) { - rdpWindow* window; + xfAppWindow* appWindow; rdpUpdate* update = xfc->instance->update; - rdpRail* rail = ((rdpContext*) xfc)->rail; xf_keyboard_release_all_keypress(xfc); @@ -760,11 +746,10 @@ static BOOL xf_event_UnmapNotify(xfContext* xfc, XEvent* event, BOOL app) } else { - window = window_list_get_by_extra_id(rail->list, (void*) event->xany.window); + appWindow = xf_AppWindowFromX11Window(xfc, event->xany.window); - if (window) + if (appWindow) { - xfAppWindow* appWindow = (xfAppWindow*) window->extra; appWindow->is_mapped = FALSE; } } @@ -782,15 +767,12 @@ static BOOL xf_event_PropertyNotify(xfContext* xfc, XEvent* event, BOOL app) if (app) { - rdpWindow* window; xfAppWindow* appWindow; - window = xf_rdpWindowFromWindow(xfc, event->xproperty.window); + appWindow = xf_AppWindowFromX11Window(xfc, event->xany.window); - if (!window) + if (!appWindow) return TRUE; - - appWindow = (xfAppWindow*) window->extra; if ((((Atom) event->xproperty.atom == xfc->_NET_WM_STATE) && (event->xproperty.state != PropertyDelete)) || (((Atom) event->xproperty.atom == xfc->WM_STATE) && (event->xproperty.state != PropertyDelete))) @@ -830,7 +812,8 @@ static BOOL xf_event_PropertyNotify(xfContext* xfc, XEvent* event, BOOL app) if ((Atom) event->xproperty.atom == xfc->WM_STATE) { - status = xf_GetWindowProperty(xfc, event->xproperty.window, xfc->WM_STATE, 1, &nitems, &bytes, &prop); + status = xf_GetWindowProperty(xfc, event->xproperty.window, + xfc->WM_STATE, 1, &nitems, &bytes, &prop); if (status) { @@ -843,22 +826,21 @@ static BOOL xf_event_PropertyNotify(xfContext* xfc, XEvent* event, BOOL app) XFree(prop); } } - if (maxVert && maxHorz && !minimized && (appWindow->rail_state != WINDOW_SHOW_MAXIMIZED)) { appWindow->rail_state = WINDOW_SHOW_MAXIMIZED; - xf_rail_send_client_system_command(xfc, window->windowId, SC_MAXIMIZE); + xf_rail_send_client_system_command(xfc, appWindow->windowId, SC_MAXIMIZE); } else if (minimized && (appWindow->rail_state != WINDOW_SHOW_MINIMIZED)) { appWindow->rail_state = WINDOW_SHOW_MINIMIZED; - xf_rail_send_client_system_command(xfc, window->windowId, SC_MINIMIZE); + xf_rail_send_client_system_command(xfc, appWindow->windowId, SC_MINIMIZE); } else if (!minimized && !maxVert && !maxHorz && (appWindow->rail_state != WINDOW_SHOW)) { appWindow->rail_state = WINDOW_SHOW; - xf_rail_send_client_system_command(xfc, window->windowId, SC_RESTORE); + xf_rail_send_client_system_command(xfc, appWindow->windowId, SC_RESTORE); } } } @@ -948,20 +930,19 @@ static BOOL xf_event_suppress_events(xfContext* xfc, xfAppWindow* appWindow, XEv BOOL xf_event_process(freerdp* instance, XEvent* event) { BOOL status = TRUE; - rdpWindow* window; + xfAppWindow* appWindow; xfContext* xfc = (xfContext*) instance->context; - rdpRail* rail = ((rdpContext*) xfc)->rail; if (xfc->remote_app) { - window = window_list_get_by_extra_id(rail->list, (void*) event->xexpose.window); + appWindow = xf_AppWindowFromX11Window(xfc, event->xany.window); - if (window) + if (appWindow) { /* Update "current" window for cursor change orders */ - xfc->appWindow = (xfAppWindow*) window->extra; + xfc->appWindow = appWindow; - if (xf_event_suppress_events(xfc, xfc->appWindow, event)) + if (xf_event_suppress_events(xfc, appWindow, event)) return TRUE; } } diff --git a/client/X11/xf_rail.c b/client/X11/xf_rail.c index a7b94de11..f8aa9548f 100644 --- a/client/X11/xf_rail.c +++ b/client/X11/xf_rail.c @@ -81,6 +81,272 @@ void xf_rail_disable_remoteapp_mode(xfContext* xfc) } } +void xf_rail_send_activate(xfContext* xfc, Window xwindow, BOOL enabled) +{ + rdpRail* rail; + rdpWindow* rail_window; + RAIL_ACTIVATE_ORDER activate; + + rail = ((rdpContext*) xfc)->rail; + rail_window = window_list_get_by_extra_id(rail->list, (void*) xwindow); + + if (!rail_window) + return; + + activate.windowId = rail_window->windowId; + activate.enabled = enabled; + + xfc->rail->ClientActivate(xfc->rail, &activate); +} + +void xf_rail_send_client_system_command(xfContext* xfc, UINT32 windowId, UINT16 command) +{ + RAIL_SYSCOMMAND_ORDER syscommand; + + syscommand.windowId = windowId; + syscommand.command = command; + + xfc->rail->ClientSystemCommand(xfc->rail, &syscommand); +} + +/** + * The position of the X window can become out of sync with the RDP window + * if the X window is moved locally by the window manager. In this event + * send an update to the RDP server informing it of the new window position + * and size. + */ +void xf_rail_adjust_position(xfContext* xfc, xfAppWindow* appWindow) +{ +#ifdef OLD_X11_RAIL + rdpWindow* window; + RAIL_WINDOW_MOVE_ORDER windowMove; + + window = appWindow->window; + + 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 != window->visibleOffsetX || + appWindow->y != window->visibleOffsetY || + appWindow->width != window->windowWidth || + appWindow->height != window->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. + */ + UINT32 offsetX = 0; + UINT32 offsetY = 0; + + if (window->windowOffsetX < 0) + offsetX = offsetX - window->windowOffsetX; + + if (window->windowOffsetY < 0) + offsetY = offsetY - window->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 + */ + windowMove.windowId = window->windowId; + /* + * Calculate new offsets for the rail server window + * Negative offset correction + rail server window offset + (difference in visibleOffset and new window local offset) + */ + windowMove.left = offsetX + window->windowOffsetX + (appWindow->x - window->visibleOffsetX); + windowMove.top = offsetY + window->windowOffsetY + (appWindow->y - window->visibleOffsetY); + windowMove.right = windowMove.left + appWindow->width; + windowMove.bottom = windowMove.top + appWindow->height; + + xfc->rail->ClientWindowMove(xfc->rail, &windowMove); + } +#else + 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 || + 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 + */ + 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) + */ + windowMove.left = offsetX + appWindow->windowOffsetX + (appWindow->x - appWindow->visibleOffsetX); + windowMove.top = offsetY + appWindow->windowOffsetY + (appWindow->y - appWindow->visibleOffsetY); + windowMove.right = windowMove.left + appWindow->width; + windowMove.bottom = windowMove.top + appWindow->height; + + xfc->rail->ClientWindowMove(xfc->rail, &windowMove); + } +#endif +} + +void xf_rail_end_local_move(xfContext* xfc, xfAppWindow* appWindow) +{ +#ifdef OLD_X11_RAIL + int x, y; + int child_x; + int child_y; + rdpWindow* window; + unsigned int mask; + Window root_window; + Window child_window; + RAIL_WINDOW_MOVE_ORDER windowMove; + rdpInput* input = xfc->instance->input; + + window = appWindow->window; + + /* + * 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. + */ + UINT32 offsetX = 0; + UINT32 offsetY = 0; + + if (window->windowOffsetX < 0) + offsetX = offsetX - window->windowOffsetX; + + if (window->windowOffsetY < 0) + offsetY = offsetY - window->windowOffsetY; + + /* + * For keyboard moves send and explicit update to RDP server + */ + windowMove.windowId = window->windowId; + + /* + * Calculate new offsets for the rail server window + * Negative offset correction + rail server window offset + (difference in visibleOffset and new window local offset) + */ + windowMove.left = offsetX + window->windowOffsetX + (appWindow->x - window->visibleOffsetX); + windowMove.top = offsetY + window->windowOffsetY + (appWindow->y - window->visibleOffsetY); + windowMove.right = windowMove.left + appWindow->width; /* In the update to RDP the position is one past the window */ + windowMove.bottom = windowMove.top + appWindow->height; + + xfc->rail->ClientWindowMove(xfc->rail, &windowMove); + + /* + * Simulate button up at new position to end the local move (per RDP spec) + */ + 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)) + { + input->MouseEvent(input, PTR_FLAGS_BUTTON1, x, y); + } + + /* + * Proactively update the RAIL window dimensions. There is a race condition where + * 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. + */ + window->windowOffsetX = offsetX + window->windowOffsetX + (appWindow->x - window->visibleOffsetX); + window->windowOffsetY = offsetY + window->windowOffsetY + (appWindow->y - window->visibleOffsetY); + window->windowWidth = appWindow->width; + window->windowHeight = appWindow->height; + appWindow->local_move.state = LMS_TERMINATING; +#else + 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) + */ + windowMove.left = offsetX + appWindow->windowOffsetX + (appWindow->x - appWindow->visibleOffsetX); + windowMove.top = offsetY + appWindow->windowOffsetY + (appWindow->y - appWindow->visibleOffsetY); + windowMove.right = windowMove.left + appWindow->width; /* In the update to RDP the position is one past the window */ + windowMove.bottom = windowMove.top + appWindow->height; + + xfc->rail->ClientWindowMove(xfc->rail, &windowMove); + + /* + * Simulate button up at new position to end the local move (per RDP spec) + */ + 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)) + { + input->MouseEvent(input, PTR_FLAGS_BUTTON1, x, y); + } + + /* + * Proactively update the RAIL window dimensions. There is a race condition where + * 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->windowWidth = appWindow->width; + appWindow->windowHeight = appWindow->height; + appWindow->local_move.state = LMS_TERMINATING; +#endif +} + void xf_rail_invalidate_region(xfContext* xfc, REGION16* invalidRegion) { int index; @@ -134,6 +400,22 @@ void xf_rail_invalidate_region(xfContext* xfc, REGION16* invalidRegion) void xf_rail_paint(xfContext* xfc, INT32 uleft, INT32 utop, UINT32 uright, UINT32 ubottom) { +#ifndef OLD_X11_RAIL + REGION16 invalidRegion; + RECTANGLE_16 invalidRect; + + invalidRect.left = uleft; + invalidRect.top = utop; + invalidRect.right = uright; + invalidRect.bottom = ubottom; + + region16_init(&invalidRegion); + region16_union_rect(&invalidRegion, &invalidRegion, &invalidRect); + + xf_rail_invalidate_region(xfc, &invalidRegion); + + region16_uninit(&invalidRegion); +#else rdpRail* rail; rdpWindow* window; xfAppWindow* appWindow; @@ -144,26 +426,6 @@ void xf_rail_paint(xfContext* xfc, INT32 uleft, INT32 utop, UINT32 uright, UINT3 INT32 wleft, wtop; UINT32 wright, wbottom; - if (0) - { - REGION16 invalidRegion; - RECTANGLE_16 invalidRect; - - invalidRect.left = uleft; - invalidRect.top = utop; - invalidRect.right = uright; - invalidRect.bottom = ubottom; - - region16_init(&invalidRegion); - region16_union_rect(&invalidRegion, &invalidRegion, &invalidRect); - - xf_rail_invalidate_region(xfc, &invalidRegion); - - region16_uninit(&invalidRegion); - - return; - } - rail = ((rdpContext*) xfc)->rail; window_list_rewind(rail->list); @@ -197,9 +459,10 @@ void xf_rail_paint(xfContext* xfc, INT32 uleft, INT32 utop, UINT32 uright, UINT3 xf_UpdateWindowArea(xfc, appWindow, ileft - wleft, itop - wtop, iwidth, iheight); } } +#endif } -#if 1 +#ifdef OLD_X11_RAIL static void xf_rail_CreateWindow(rdpRail* rail, rdpWindow* window) { @@ -343,189 +606,33 @@ void xf_rail_register_callbacks(xfContext* xfc, rdpRail* rail) rail->rail_DesktopNonMonitored = xf_rail_DesktopNonMonitored; } -#endif - -void xf_rail_send_activate(xfContext* xfc, Window xwindow, BOOL enabled) -{ - rdpRail* rail; - rdpWindow* rail_window; - RAIL_ACTIVATE_ORDER activate; - - rail = ((rdpContext*) xfc)->rail; - rail_window = window_list_get_by_extra_id(rail->list, (void*) xwindow); - - if (!rail_window) - return; - - activate.windowId = rail_window->windowId; - activate.enabled = enabled; - - xfc->rail->ClientActivate(xfc->rail, &activate); -} - -void xf_rail_send_client_system_command(xfContext* xfc, UINT32 windowId, UINT16 command) -{ - RAIL_SYSCOMMAND_ORDER syscommand; - - syscommand.windowId = windowId; - syscommand.command = command; - - xfc->rail->ClientSystemCommand(xfc->rail, &syscommand); -} - -/** - * The position of the X window can become out of sync with the RDP window - * if the X window is moved locally by the window manager. In this event - * send an update to the RDP server informing it of the new window position - * and size. - */ -void xf_rail_adjust_position(xfContext* xfc, xfAppWindow* appWindow) -{ - rdpWindow* window; - RAIL_WINDOW_MOVE_ORDER windowMove; - - window = appWindow->window; - - 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 != window->visibleOffsetX || - appWindow->y != window->visibleOffsetY || - appWindow->width != window->windowWidth || - appWindow->height != window->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. - */ - UINT32 offsetX = 0; - UINT32 offsetY = 0; - - if (window->windowOffsetX < 0) - offsetX = offsetX - window->windowOffsetX; - - if (window->windowOffsetY < 0) - offsetY = offsetY - window->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 - */ - windowMove.windowId = window->windowId; - /* - * Calculate new offsets for the rail server window - * Negative offset correction + rail server window offset + (difference in visibleOffset and new window local offset) - */ - windowMove.left = offsetX + window->windowOffsetX + (appWindow->x - window->visibleOffsetX); - windowMove.top = offsetY + window->windowOffsetY + (appWindow->y - window->visibleOffsetY); - windowMove.right = windowMove.left + appWindow->width; - windowMove.bottom = windowMove.top + appWindow->height; - - xfc->rail->ClientWindowMove(xfc->rail, &windowMove); - } -} - -void xf_rail_end_local_move(xfContext* xfc, xfAppWindow* appWindow) -{ - int x, y; - int child_x; - int child_y; - rdpWindow* window; - unsigned int mask; - Window root_window; - Window child_window; - RAIL_WINDOW_MOVE_ORDER windowMove; - rdpInput* input = xfc->instance->input; - - window = appWindow->window; - - /* - * 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. - */ - UINT32 offsetX = 0; - UINT32 offsetY = 0; - - if (window->windowOffsetX < 0) - offsetX = offsetX - window->windowOffsetX; - - if (window->windowOffsetY < 0) - offsetY = offsetY - window->windowOffsetY; - - /* - * For keyboard moves send and explicit update to RDP server - */ - windowMove.windowId = window->windowId; - - /* - * Calculate new offsets for the rail server window - * Negative offset correction + rail server window offset + (difference in visibleOffset and new window local offset) - */ - windowMove.left = offsetX + window->windowOffsetX + (appWindow->x - window->visibleOffsetX); - windowMove.top = offsetY + window->windowOffsetY + (appWindow->y - window->visibleOffsetY); - windowMove.right = windowMove.left + appWindow->width; /* In the update to RDP the position is one past the window */ - windowMove.bottom = windowMove.top + appWindow->height; - - xfc->rail->ClientWindowMove(xfc->rail, &windowMove); - - /* - * Simulate button up at new position to end the local move (per RDP spec) - */ - 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)) - { - input->MouseEvent(input, PTR_FLAGS_BUTTON1, x, y); - } - - /* - * Proactively update the RAIL window dimensions. There is a race condition where - * 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. - */ - window->windowOffsetX = offsetX + window->windowOffsetX + (appWindow->x - window->visibleOffsetX); - window->windowOffsetY = offsetY + window->windowOffsetY + (appWindow->y - window->visibleOffsetY); - window->windowWidth = appWindow->width; - window->windowHeight = appWindow->height; - appWindow->local_move.state = LMS_TERMINATING; -} - -#if 0 +#else /* RemoteApp Core Protocol Extension */ static void xf_rail_window_common(rdpContext* context, WINDOW_ORDER_INFO* orderInfo, WINDOW_STATE_ORDER* windowState) { - xfAppWindow* railWindow = NULL; + xfAppWindow* appWindow = NULL; xfContext* xfc = (xfContext*) context; UINT32 fieldFlags = orderInfo->fieldFlags; if (fieldFlags & WINDOW_ORDER_STATE_NEW) { - railWindow = (xfAppWindow*) calloc(1, sizeof(xfAppWindow)); + appWindow = (xfAppWindow*) calloc(1, sizeof(xfAppWindow)); - if (!railWindow) + if (!appWindow) return; - railWindow->xfc = xfc; + appWindow->xfc = xfc; - railWindow->id = orderInfo->windowId; - railWindow->dwStyle = windowState->style; - railWindow->dwExStyle = windowState->extendedStyle; + appWindow->windowId = orderInfo->windowId; + appWindow->dwStyle = windowState->style; + appWindow->dwExStyle = windowState->extendedStyle; - railWindow->x = windowState->windowOffsetX; - railWindow->y = windowState->windowOffsetY; - railWindow->width = windowState->windowWidth; - railWindow->height = windowState->windowHeight; + appWindow->x = appWindow->windowOffsetX = windowState->windowOffsetX; + appWindow->y = appWindow->windowOffsetY = windowState->windowOffsetY; + appWindow->width = appWindow->windowWidth = windowState->windowWidth; + appWindow->height = appWindow->windowHeight = windowState->windowHeight; if (fieldFlags & WINDOW_ORDER_FIELD_TITLE) { @@ -534,59 +641,60 @@ static void xf_rail_window_common(rdpContext* context, WINDOW_ORDER_INFO* orderI ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) windowState->titleInfo.string, windowState->titleInfo.length / 2, &title, 0, NULL, NULL); - railWindow->title = title; + appWindow->title = title; } else { - railWindow->title = _strdup("RdpRailWindow"); + appWindow->title = _strdup("RdpRailWindow"); } - railWindow->xfw = xf_CreateWindow(xfc, railWindow, railWindow->x, railWindow->y, - railWindow->width, railWindow->height, railWindow->id); + xf_AppWindowInit(xfc, appWindow); - HashTable_Add(xfc->railWindows, (void*) (UINT_PTR) orderInfo->windowId, (void*) railWindow); + HashTable_Add(xfc->railWindows, (void*) (UINT_PTR) orderInfo->windowId, (void*) appWindow); return; } else { - railWindow = (xfAppWindow*) HashTable_GetItemValue(xfc->railWindows, + appWindow = (xfAppWindow*) HashTable_GetItemValue(xfc->railWindows, (void*) (UINT_PTR) orderInfo->windowId); } - if (!railWindow) + if (!appWindow) return; + /* Update Parameters */ + if ((fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET) || (fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE)) { if (fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET) { - railWindow->x = windowState->windowOffsetX; - railWindow->y = windowState->windowOffsetY; + appWindow->x = appWindow->windowOffsetX = windowState->windowOffsetX; + appWindow->y = appWindow->windowOffsetY = windowState->windowOffsetY; } if (fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE) { - railWindow->width = windowState->windowWidth; - railWindow->height = windowState->windowHeight; + appWindow->width = appWindow->windowWidth = windowState->windowWidth; + appWindow->height = appWindow->windowHeight = windowState->windowHeight; } } if (fieldFlags & WINDOW_ORDER_FIELD_OWNER) { - + appWindow->ownerWindowId = windowState->ownerWindowId; } if (fieldFlags & WINDOW_ORDER_FIELD_STYLE) { - railWindow->dwStyle = windowState->style; - railWindow->dwExStyle = windowState->extendedStyle; + appWindow->dwStyle = windowState->style; + appWindow->dwExStyle = windowState->extendedStyle; } if (fieldFlags & WINDOW_ORDER_FIELD_SHOW) { - + appWindow->showState = windowState->showState; } if (fieldFlags & WINDOW_ORDER_FIELD_TITLE) @@ -596,65 +704,155 @@ static void xf_rail_window_common(rdpContext* context, WINDOW_ORDER_INFO* orderI ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) windowState->titleInfo.string, windowState->titleInfo.length / 2, &title, 0, NULL, NULL); - free(railWindow->title); - railWindow->title = title; + free(appWindow->title); + appWindow->title = title; } if (fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET) { - + appWindow->clientOffsetX = windowState->clientOffsetX; + appWindow->clientOffsetY = windowState->clientOffsetY; } if (fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE) { - + appWindow->clientAreaWidth = windowState->clientAreaWidth; + appWindow->clientAreaHeight = windowState->clientAreaHeight; } if (fieldFlags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA) { - - } - - if (fieldFlags & WINDOW_ORDER_FIELD_RP_CONTENT) - { - - } - - if (fieldFlags & WINDOW_ORDER_FIELD_ROOT_PARENT) - { - + appWindow->windowClientDeltaX = windowState->windowClientDeltaX; + appWindow->windowClientDeltaY = windowState->windowClientDeltaY; } if (fieldFlags & WINDOW_ORDER_FIELD_WND_RECTS) { + if (appWindow->windowRects) + { + free(appWindow->windowRects); + appWindow->windowRects = NULL; + } + appWindow->numWindowRects = windowState->numWindowRects; + + if (appWindow->numWindowRects) + { + appWindow->windowRects = (RECTANGLE_16*) calloc(appWindow->numWindowRects, sizeof(RECTANGLE_16)); + + if (!appWindow->windowRects) + return; + + CopyMemory(appWindow->windowRects, windowState->windowRects, + appWindow->numWindowRects * sizeof(RECTANGLE_16)); + } } if (fieldFlags & WINDOW_ORDER_FIELD_VIS_OFFSET) { - + appWindow->visibleOffsetX = windowState->visibleOffsetX; + appWindow->visibleOffsetY = windowState->visibleOffsetY; } if (fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY) { + if (appWindow->visibilityRects) + { + free(appWindow->visibilityRects); + appWindow->visibilityRects = NULL; + } + appWindow->numVisibilityRects = windowState->numVisibilityRects; + + if (appWindow->numVisibilityRects) + { + appWindow->visibilityRects = (RECTANGLE_16*) calloc(appWindow->numVisibilityRects, sizeof(RECTANGLE_16)); + + if (!appWindow->visibilityRects) + return; + + CopyMemory(appWindow->visibilityRects, windowState->visibilityRects, + appWindow->numVisibilityRects * sizeof(RECTANGLE_16)); + } + } + + /* Update Window */ + + if (fieldFlags & WINDOW_ORDER_FIELD_STYLE) + { + + } + + if (fieldFlags & WINDOW_ORDER_FIELD_SHOW) + { + xf_ShowWindow(xfc, appWindow, appWindow->showState); + } + + if (fieldFlags & WINDOW_ORDER_FIELD_TITLE) + { + xf_SetWindowText(xfc, appWindow, appWindow->title); + } + + if ((fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET) || + (fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE)) + { + /* + * 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; + + /* Do nothing if window is already in the correct position */ + if (appWindow->x == appWindow->visibleOffsetX && + appWindow->y == appWindow->visibleOffsetY && + 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, + appWindow->windowWidth, appWindow->windowHeight); + } + + 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); } } static void xf_rail_window_delete(rdpContext* context, WINDOW_ORDER_INFO* orderInfo) { - xfAppWindow* railWindow = NULL; + xfAppWindow* appWindow = NULL; xfContext* xfc = (xfContext*) context; - railWindow = (xfAppWindow*) HashTable_GetItemValue(xfc->railWindows, + appWindow = (xfAppWindow*) HashTable_GetItemValue(xfc->railWindows, (void*) (UINT_PTR) orderInfo->windowId); - if (!railWindow) + if (!appWindow) return; HashTable_Remove(xfc->railWindows, (void*) (UINT_PTR) orderInfo->windowId); - free(railWindow); + xf_DestroyWindow(xfc, appWindow); + + free(appWindow->title); + free(appWindow->windowRects); + free(appWindow->visibilityRects); + + free(appWindow); } static void xf_rail_window_icon(rdpContext* context, WINDOW_ORDER_INFO* orderInfo, WINDOW_ICON_ORDER* windowIcon) @@ -701,7 +899,7 @@ static void xf_rail_notify_icon_common(rdpContext* context, WINDOW_ORDER_INFO* o if (orderInfo->fieldFlags & WINDOW_ORDER_ICON) { - //ICON_INFO* iconInfo = &(notifyIconState->icon); + } if (orderInfo->fieldFlags & WINDOW_ORDER_CACHED_ICON) @@ -997,9 +1195,11 @@ int xf_rail_init(xfContext* xfc, RailClientContext* rail) context->rail = rail_new(context->settings); rail_register_update_callbacks(context->rail, context->update); +#ifdef OLD_X11_RAIL xf_rail_register_callbacks(xfc, context->rail); - - //xf_rail_register_update_callbacks(context->update); +#else + xf_rail_register_update_callbacks(context->update); +#endif rail->custom = (void*) xfc; @@ -1012,6 +1212,8 @@ int xf_rail_init(xfContext* xfc, RailClientContext* rail) rail->ServerLanguageBarInfo = xf_rail_server_language_bar_info; rail->ServerGetAppIdResponse = xf_rail_server_get_appid_response; + xfc->railWindows = HashTable_New(TRUE); + return 1; } @@ -1031,5 +1233,11 @@ int xf_rail_uninit(xfContext* xfc, RailClientContext* rail) context->rail = NULL; } + if (xfc->railWindows) + { + HashTable_Free(xfc->railWindows); + xfc->railWindows = NULL; + } + return 1; } diff --git a/client/X11/xf_window.c b/client/X11/xf_window.c index 5ac35d65d..0d06b6ca5 100644 --- a/client/X11/xf_window.c +++ b/client/X11/xf_window.c @@ -49,6 +49,7 @@ #include "xf_input.h" #endif +#include "xf_rail.h" #include "xf_input.h" #define TAG CLIENT_TAG("x11") @@ -536,33 +537,17 @@ void xf_FixWindowCoordinates(xfContext* xfc, int* x, int* y, int* width, int* he } } -xfAppWindow* xf_CreateWindow(xfContext* xfc, rdpWindow* wnd, int x, int y, int width, int height, UINT32 id) +int xf_AppWindowInit(xfContext* xfc, xfAppWindow* appWindow) { XGCValues gcv; int input_mask; - xfAppWindow* appWindow; XWMHints* InputModeHint; XClassHint* class_hints; - appWindow = (xfAppWindow*) calloc(1, sizeof(xfAppWindow)); + xf_FixWindowCoordinates(xfc, &appWindow->x, &appWindow->y, &appWindow->width, &appWindow->height); - if (!appWindow) - return NULL; - - xf_FixWindowCoordinates(xfc, &x, &y, &width, &height); - - appWindow->x = x; - appWindow->y = y; - appWindow->width = width; - appWindow->height = height; - - /* - * WS_EX_DECORATIONS is used by XRDP and instructs - * the client to use local window decorations - */ - appWindow->decorations = (wnd->extendedStyle & WS_EX_DECORATIONS) ? TRUE : FALSE; + appWindow->decorations = FALSE; appWindow->fullscreen = FALSE; - appWindow->window = wnd; appWindow->local_move.state = LMS_NOT_ACTIVE; appWindow->is_mapped = FALSE; appWindow->is_transient = FALSE; @@ -570,11 +555,11 @@ xfAppWindow* xf_CreateWindow(xfContext* xfc, rdpWindow* wnd, int x, int y, int w appWindow->rail_ignore_configure = FALSE; appWindow->handle = XCreateWindow(xfc->display, RootWindowOfScreen(xfc->screen), - x, y, appWindow->width, appWindow->height, 0, xfc->depth, - InputOutput, xfc->visual, 0, &xfc->attribs); + appWindow->x, appWindow->y, appWindow->width, appWindow->height, + 0, xfc->depth, InputOutput, xfc->visual, 0, &xfc->attribs); if (!appWindow->handle) - return NULL; + return -1; ZeroMemory(&gcv, sizeof(gcv)); appWindow->gc = XCreateGC(xfc->display, appWindow->handle, GCGraphicsExposures, &gcv); @@ -592,7 +577,7 @@ xfAppWindow* xf_CreateWindow(xfContext* xfc, rdpWindow* wnd, int x, int y, int w else { class = malloc(sizeof("RAIL:00000000")); - snprintf(class, sizeof("RAIL:00000000"), "RAIL:%08X", id); + snprintf(class, sizeof("RAIL:00000000"), "RAIL:%08X", appWindow->windowId); class_hints->res_class = class; } @@ -626,7 +611,7 @@ xfAppWindow* xf_CreateWindow(xfContext* xfc, rdpWindow* wnd, int x, int y, int w XSelectInput(xfc->display, appWindow->handle, input_mask); xf_SetWindowDecorations(xfc, appWindow->handle, appWindow->decorations); - xf_SetWindowStyle(xfc, appWindow, wnd->style, wnd->extendedStyle); + xf_SetWindowStyle(xfc, appWindow, appWindow->dwStyle, appWindow->dwExStyle); xf_SetWindowPID(xfc, appWindow->handle, 0); xf_ShowWindow(xfc, appWindow, WINDOW_SHOW); @@ -634,7 +619,35 @@ xfAppWindow* xf_CreateWindow(xfContext* xfc, rdpWindow* wnd, int x, int y, int w XMapWindow(xfc->display, appWindow->handle); /* Move doesn't seem to work until window is mapped. */ - xf_MoveWindow(xfc, appWindow, x, y, width, height); + xf_MoveWindow(xfc, appWindow, appWindow->x, appWindow->y, appWindow->width, appWindow->height); + + return 1; +} + +xfAppWindow* xf_CreateWindow(xfContext* xfc, rdpWindow* wnd, int x, int y, int width, int height, UINT32 id) +{ + xfAppWindow* appWindow; + + appWindow = (xfAppWindow*) calloc(1, sizeof(xfAppWindow)); + + if (!appWindow) + return NULL; + +#ifdef OLD_X11_RAIL + appWindow->window = wnd; +#endif + + appWindow->windowId = id; + + appWindow->dwStyle = wnd->style; + appWindow->dwExStyle = wnd->extendedStyle; + + appWindow->x = x; + appWindow->y = y; + appWindow->width = width; + appWindow->height = height; + + xf_AppWindowInit(xfc, appWindow); return appWindow; } @@ -763,7 +776,13 @@ void xf_ShowWindow(xfContext* xfc, xfAppWindow* appWindow, BYTE state) * the entire window once the rail server notifies us that the window is now maximized. */ if (appWindow->rail_state == WINDOW_SHOW_MAXIMIZED) + { +#ifdef OLD_X11_RAIL xf_UpdateWindowArea(xfc, appWindow, 0, 0, appWindow->window->windowWidth, appWindow->window->windowHeight); +#else + xf_UpdateWindowArea(xfc, appWindow, 0, 0, appWindow->width, appWindow->height); +#endif + } break; case WINDOW_SHOW: @@ -878,6 +897,7 @@ void xf_SetWindowVisibilityRects(xfContext* xfc, xfAppWindow* appWindow, RECTANG void xf_UpdateWindowArea(xfContext* xfc, xfAppWindow* appWindow, int x, int y, int width, int height) { +#ifdef OLD_X11_RAIL int ax, ay; rdpWindow* wnd; @@ -905,6 +925,32 @@ void xf_UpdateWindowArea(xfContext* xfc, xfAppWindow* appWindow, int x, int y, i XFlush(xfc->display); xf_unlock_x11(xfc, TRUE); +#else + int ax, ay; + + ax = x + appWindow->visibleOffsetX; + ay = y + appWindow->visibleOffsetY; + + 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; + + xf_lock_x11(xfc, TRUE); + + if (xfc->settings->SoftwareGdi) + { + XPutImage(xfc->display, xfc->primary, appWindow->gc, xfc->image, + ax, ay, ax, ay, width, height); + } + + XCopyArea(xfc->display, xfc->primary, appWindow->handle, appWindow->gc, + ax, ay, width, height, x, y); + + XFlush(xfc->display); + + xf_unlock_x11(xfc, TRUE); +#endif } void xf_DestroyWindow(xfContext* xfc, xfAppWindow* appWindow) @@ -935,8 +981,9 @@ void xf_DestroyWindow(xfContext* xfc, xfAppWindow* appWindow) free(appWindow); } -rdpWindow* xf_rdpWindowFromWindow(xfContext* xfc, Window wnd) +xfAppWindow* xf_AppWindowFromX11Window(xfContext* xfc, Window wnd) { +#ifdef OLD_X11_RAIL rdpRail* rail; if (xfc) @@ -946,9 +993,39 @@ rdpWindow* xf_rdpWindowFromWindow(xfContext* xfc, Window wnd) rail = ((rdpContext*) xfc)->rail; if (rail) - return window_list_get_by_extra_id(rail->list, (void*) (long) wnd); + { + rdpWindow* window; + + window = (rdpWindow*) window_list_get_by_extra_id(rail->list, (void*) (long) wnd); + + if (!window) + return NULL; + + return (xfAppWindow*) window->extra; + } + } + } +#else + int index; + int count; + ULONG_PTR* pKeys = NULL; + xfAppWindow* appWindow; + + count = HashTable_GetKeys(xfc->railWindows, &pKeys); + + for (index = 0; index < count; index++) + { + appWindow = (xfAppWindow*) HashTable_GetItemValue(xfc->railWindows, (void*) pKeys[index]); + + if (appWindow->handle == wnd) + { + free(pKeys); + return appWindow; } } + free(pKeys); +#endif + return NULL; } diff --git a/client/X11/xf_window.h b/client/X11/xf_window.h index fb93098a2..0c07a875f 100644 --- a/client/X11/xf_window.h +++ b/client/X11/xf_window.h @@ -86,12 +86,42 @@ struct xf_window struct xf_app_window { xfContext* xfc; + +#ifdef OLD_X11_RAIL rdpWindow* window; +#endif int x; int y; int width; int height; + char* title; + + UINT32 windowId; + UINT32 ownerWindowId; + + UINT32 dwStyle; + UINT32 dwExStyle; + UINT32 showState; + + UINT32 clientOffsetX; + UINT32 clientOffsetY; + UINT32 clientAreaWidth; + UINT32 clientAreaHeight; + + UINT32 windowOffsetX; + UINT32 windowOffsetY; + UINT32 windowClientDeltaX; + UINT32 windowClientDeltaY; + UINT32 windowWidth; + UINT32 windowHeight; + UINT32 numWindowRects; + RECTANGLE_16* windowRects; + + UINT32 visibleOffsetX; + UINT32 visibleOffsetY; + UINT32 numVisibilityRects; + RECTANGLE_16* visibilityRects; GC gc; int shmid; @@ -123,6 +153,7 @@ BOOL xf_GetWindowProperty(xfContext* xfc, Window window, Atom property, int leng unsigned long* nitems, unsigned long* bytes, BYTE** prop); void xf_SendClientEvent(xfContext* xfc, Window window, Atom atom, unsigned int numArgs, ...); +int xf_AppWindowInit(xfContext* xfc, xfAppWindow* appWindow); xfAppWindow* xf_CreateWindow(xfContext* xfc, rdpWindow* wnd, int x, int y, int width, int height, UINT32 id); void xf_SetWindowText(xfContext* xfc, xfAppWindow* appWindow, char* name); void xf_MoveWindow(xfContext* xfc, xfAppWindow* appWindow, int x, int y, int width, int height); @@ -138,6 +169,6 @@ void xf_SetWindowMinMaxInfo(xfContext* xfc, xfAppWindow* appWindow, int minTrackWidth, int minTrackHeight, int maxTrackWidth, int maxTrackHeight); void xf_StartLocalMoveSize(xfContext* xfc, xfAppWindow* appWindow, int direction, int x, int y); void xf_EndLocalMoveSize(xfContext* xfc, xfAppWindow* appWindow); -rdpWindow* xf_rdpWindowFromWindow(xfContext* xfc, Window wnd); +xfAppWindow* xf_AppWindowFromX11Window(xfContext* xfc, Window wnd); #endif /* __XF_WINDOW_H */ diff --git a/client/X11/xfreerdp.h b/client/X11/xfreerdp.h index cda774e97..75ce368c6 100644 --- a/client/X11/xfreerdp.h +++ b/client/X11/xfreerdp.h @@ -24,6 +24,8 @@ typedef struct xf_context xfContext; #include +#define OLD_X11_RAIL 1 + #include "xf_window.h" #include "xf_monitor.h" #include "xf_channels.h"