This fixes a number if issues on Ubuntu in particular.
#include <freerdp/kbd/vkcodes.h>
#include "xf_rail.h"
+#include "xf_window.h"
#include "xf_cliprdr.h"
#include "xf_event.h"
xf_rail_send_activate(xfi, event->xany.window, true);
xf_kbd_focus_in(xfi);
- if (xfi->remote_app != true)
+ if (app != true)
xf_cliprdr_check_owner(xfi);
return true;
xfw->bottom = xfw->top + xfw->height - 1;
if (app)
- xf_rail_local_movesize(xfi, xfw);
+ xf_rail_adjust_position(xfi, window);
}
/* local restore event */
xf_rail_send_client_system_command(xfi, window->windowId, SC_RESTORE);
xfWindow *xfw = (xfWindow*) window->extra;
- xfw->isMapped = true;
+ xfw->is_mapped = true;
}
return true;
if (window != NULL)
{
xfWindow *xfw = (xfWindow*) window->extra;
- xfw->isMapped = false;
+ xfw->is_mapped = false;
}
return true;
boolean xf_event_SelectionNotify(xfInfo* xfi, XEvent* event, boolean app)
{
- if (xfi->remote_app != true)
+ if (app != true)
{
if (xf_cliprdr_process_selection_notify(xfi, event))
return true;
boolean xf_event_SelectionRequest(xfInfo* xfi, XEvent* event, boolean app)
{
- if (xfi->remote_app != true)
+ if (app != true)
{
if (xf_cliprdr_process_selection_request(xfi, event))
return true;
boolean xf_event_SelectionClear(xfInfo* xfi, XEvent* event, boolean app)
{
- if (xfi->remote_app != true)
+ if (app != true)
{
if (xf_cliprdr_process_selection_clear(xfi, event))
return true;
boolean xf_event_PropertyNotify(xfInfo* xfi, XEvent* event, boolean app)
{
- if (xfi->remote_app != true)
+ if (app != true)
{
if (xf_cliprdr_process_property_notify(xfi, event))
return true;
boolean xf_event_process(freerdp* instance, XEvent* event)
{
- boolean app = false;
boolean status = true;
xfInfo* xfi = ((xfContext*) instance->context)->xfi;
- if (xfi->remote_app == true)
- {
- app = true;
- }
- else
+ if (xfi->window && xfi->window->local_move.state == LMS_ACTIVE)
{
- if (event->xany.window != xfi->window->handle)
- app = true;
- }
+ xfWindow* xfw;
+ rdpWindow* window;
+ rdpRail* rail = ((rdpContext*) xfi->context)->rail;
+ window = window_list_get_by_extra_id(rail->list, (void*) event->xexpose.window);
+ if (window != NULL)
+ {
+ xfw = (xfWindow*) window->extra;
+ xfi->window = xfw;
+ switch (event->type)
+ {
+ case ButtonPress:
+ case ButtonRelease:
+ case KeyPress:
+ case KeyRelease:
+ case UnmapNotify:
+ {
+ // A button release event means the X window server did not grab the
+ // mouse before the user released it. In this case we must cancel
+ // the local move. The event will be processed below as normal, below.
+ xf_EndLocalMoveSize(xfi, xfw, true);
+ }
+ break;
+
+ case FocusIn:
+ case FocusOut:
+ {
+ XFocusChangeEvent *focusEvent = (XFocusChangeEvent *)event;
+ if (focusEvent->mode == NotifyUngrab)
+ xf_rail_end_local_move(xfi, window);
+ else
+ return true;
+ }
+ break;
+ case EnterNotify:
+ case LeaveNotify:
+ {
+ XCrossingEvent *crossingEvent = (XCrossingEvent *)event;
+ if(crossingEvent->mode == NotifyUngrab)
+ xf_rail_end_local_move(xfi, window);
+ else
+ return true;
+ }
+ break;
+
+ case VisibilityNotify:
+ case ConfigureNotify:
+ case Expose:
+ case PropertyNotify:
+ // Allow these events to be processed during move to keep
+ // our state up to date.
+ break;
+ default:
+ // Any other event should signify the root no longer
+ // has the grap, so the move has finished.
+ xf_rail_end_local_move(xfi, window);
+ }
+
+ }
+ }
if (event->type != MotionNotify)
DEBUG_X11("%s Event: wnd=0x%04X", X11_EVENT_STRINGS[event->type], (uint32) event->xany.window);
switch (event->type)
{
case Expose:
- status = xf_event_Expose(xfi, event, app);
+ status = xf_event_Expose(xfi, event, xfi->remote_app);
break;
case VisibilityNotify:
- status = xf_event_VisibilityNotify(xfi, event, app);
+ status = xf_event_VisibilityNotify(xfi, event, xfi->remote_app);
break;
case MotionNotify:
- status = xf_event_MotionNotify(xfi, event, app);
+ status = xf_event_MotionNotify(xfi, event, xfi->remote_app);
break;
case ButtonPress:
- status = xf_event_ButtonPress(xfi, event, app);
+ status = xf_event_ButtonPress(xfi, event, xfi->remote_app);
break;
case ButtonRelease:
- status = xf_event_ButtonRelease(xfi, event, app);
+ status = xf_event_ButtonRelease(xfi, event, xfi->remote_app);
break;
case KeyPress:
- status = xf_event_KeyPress(xfi, event, app);
+ status = xf_event_KeyPress(xfi, event, xfi->remote_app);
break;
case KeyRelease:
- status = xf_event_KeyRelease(xfi, event, app);
+ status = xf_event_KeyRelease(xfi, event, xfi->remote_app);
break;
case FocusIn:
- status = xf_event_FocusIn(xfi, event, app);
+ status = xf_event_FocusIn(xfi, event, xfi->remote_app);
break;
case FocusOut:
- status = xf_event_FocusOut(xfi, event, app);
+ status = xf_event_FocusOut(xfi, event, xfi->remote_app);
break;
case EnterNotify:
- status = xf_event_EnterNotify(xfi, event, app);
+ status = xf_event_EnterNotify(xfi, event, xfi->remote_app);
break;
case LeaveNotify:
- status = xf_event_LeaveNotify(xfi, event, app);
+ status = xf_event_LeaveNotify(xfi, event, xfi->remote_app);
break;
case NoExpose:
break;
case ConfigureNotify:
- status = xf_event_ConfigureNotify(xfi, event, app);
+ status = xf_event_ConfigureNotify(xfi, event, xfi->remote_app);
break;
case MapNotify:
- status = xf_event_MapNotify(xfi, event, app);
+ status = xf_event_MapNotify(xfi, event, xfi->remote_app);
break;
case UnmapNotify:
- status = xf_event_UnmapNotify(xfi, event, app);
+ status = xf_event_UnmapNotify(xfi, event, xfi->remote_app);
break;
case ReparentNotify:
break;
case MappingNotify:
- status = xf_event_MappingNotify(xfi, event, app);
+ status = xf_event_MappingNotify(xfi, event, xfi->remote_app);
break;
case ClientMessage:
- status = xf_event_ClientMessage(xfi, event, app);
+ status = xf_event_ClientMessage(xfi, event, xfi->remote_app);
break;
case SelectionNotify:
- status = xf_event_SelectionNotify(xfi, event, app);
+ status = xf_event_SelectionNotify(xfi, event, xfi->remote_app);
break;
case SelectionRequest:
- status = xf_event_SelectionRequest(xfi, event, app);
+ status = xf_event_SelectionRequest(xfi, event, xfi->remote_app);
break;
case SelectionClear:
- status = xf_event_SelectionClear(xfi, event, app);
+ status = xf_event_SelectionClear(xfi, event, xfi->remote_app);
break;
case PropertyNotify:
- status = xf_event_PropertyNotify(xfi, event, app);
+ status = xf_event_PropertyNotify(xfi, event, xfi->remote_app);
break;
default:
window->windowWidth, window->windowHeight);
}
-/**
- * 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_local_movesize(xfInfo* xfi, xfWindow* window)
-{
- rdpWindow* wnd = window->window;
-
- if (window->isMapped)
- {
- // If current window position disagrees with RDP window position, send
- // update to RDP server
- if ( window->left != wnd->windowOffsetX ||
- window->top != wnd->windowOffsetY ||
- window->width != wnd->windowWidth ||
- window->height != wnd->windowHeight)
- {
- xf_rail_send_windowmove(xfi, wnd->windowId,
- window->left, window->top, window->right+1, window->bottom+1);
- }
-
- DEBUG_X11_LMS("window=0x%X rc={l=%d t=%d r=%d b=%d} w=%u h=%u"
- " RDP=0x%X rc={l=%d t=%d} w=%d h=%d",
- (uint32) window->handle, window->left, window->top,
- window->right, window->bottom, window->width, window->height,
- wnd->windowId,
- wnd->windowOffsetX, wnd->windowOffsetY,
- wnd->windowWidth, wnd->windowHeight);
- }
-}
-
void xf_rail_ShowWindow(rdpRail* rail, rdpWindow* window, uint8 state)
{
xfInfo* xfi;
}
}
-void xf_rail_send_windowmove(xfInfo* xfi, uint32 windowId, uint32 left, uint32 top, uint32 right, uint32 bottom)
-{
- rdpChannels* channels;
- RAIL_WINDOW_MOVE_ORDER window_move;
-
- channels = xfi->_context->channels;
-
- window_move.windowId = windowId;
- window_move.left = left;
- window_move.top = top;
- window_move.right = right;
- window_move.bottom = bottom;
-
- xf_send_rail_client_event(channels, RDP_EVENT_TYPE_RAIL_CLIENT_WINDOW_MOVE, &window_move);
-}
-
void xf_rail_send_activate(xfInfo* xfi, Window xwindow, boolean enabled)
{
rdpRail* rail;
xf_send_rail_client_event(channels, RDP_EVENT_TYPE_RAIL_CLIENT_SYSCOMMAND, &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(xfInfo* xfi, rdpWindow *window)
+{
+ xfWindow* xfw;
+ rdpChannels* channels;
+ RAIL_WINDOW_MOVE_ORDER window_move;
+
+ xfw = (xfWindow*) window->extra;
+ channels = xfi->_context->channels;
+
+ if (! xfw->is_mapped || xfw->local_move.state != LMS_NOT_ACTIVE)
+ return;
+
+ DEBUG_X11_LMS("window=0x%X rc={l=%d t=%d r=%d b=%d} w=%u h=%u"
+ " RDP=0x%X rc={l=%d t=%d} w=%d h=%d lms_state=%d mapped=%d",
+ (uint32) xfw->handle, xfw->left, xfw->top,
+ xfw->right, xfw->bottom, xfw->width, xfw->height,
+ window->windowId,
+ window->windowOffsetX, window->windowOffsetY,
+ window->windowWidth, window->windowHeight,
+ xfw->local_move.state, xfw->is_mapped);
+
+ // If current window position disagrees with RDP window position, send
+ // update to RDP server
+ if ( xfw->left != window->windowOffsetX ||
+ xfw->top != window->windowOffsetY ||
+ xfw->width != window->windowWidth ||
+ xfw->height != window->windowHeight)
+ {
+ window_move.windowId = window->windowId;
+ window_move.left = xfw->left;
+ window_move.top = xfw->top;
+ window_move.right = xfw->right;
+ window_move.bottom = xfw->bottom;
+
+ xf_send_rail_client_event(channels, RDP_EVENT_TYPE_RAIL_CLIENT_WINDOW_MOVE, &window_move);
+ }
+}
+
+void xf_rail_end_local_move(xfInfo* xfi, rdpWindow *window)
+{
+ xfWindow* xfw;
+ rdpChannels* channels;
+ RAIL_WINDOW_MOVE_ORDER window_move;
+ int x,y;
+ rdpInput* input = xfi->instance->input;
+
+ xfw = (xfWindow*) window->extra;
+ channels = xfi->_context->channels;
+
+ // Send RDP client event to inform RDP server
+
+ window_move.windowId = window->windowId;
+ window_move.left = xfw->left;
+ window_move.top = xfw->top;
+ window_move.right = xfw->right + 1; // In the update to RDP the position is one past the window
+ window_move.bottom = xfw->bottom + 1;
+
+ DEBUG_X11_LMS("ClientWindowMove: window=0x%X rc={l=%d t=%d r=%d b=%d}",
+ (uint32) xfw->handle, xfw->left, xfw->top, xfw->right, xfw->bottom);
+
+ xf_send_rail_client_event(channels, RDP_EVENT_TYPE_RAIL_CLIENT_WINDOW_MOVE, &window_move);
+
+ // Send synthetic button up event to the RDP server. This is per the RDP spec to
+ // indicate a local move has finished.
+
+ x = xfw->left + xfw->local_move.window_x;
+ y = xfw->top + xfw->local_move.window_y;
+ input->MouseEvent(input, PTR_FLAGS_BUTTON1, x, y);
+
+ xfw->local_move.state = LMS_TERMINATING;
+}
+
void xf_process_rail_get_sysparams_event(xfInfo* xfi, rdpChannels* channels, RDP_EVENT* event)
{
RAIL_SYSPARAM_ORDER* sysparam;
rdpWindow* rail_window = NULL;
RAIL_LOCALMOVESIZE_ORDER* movesize = (RAIL_LOCALMOVESIZE_ORDER*) event->user_data;
int direction = 0;
+ Window child_window;
+ int x,y;
rail = ((rdpContext*) xfi->context)->rail;
rail_window = window_list_get_by_id(rail->list, movesize->windowId);
if (rail_window != NULL)
{
- xfWindow* window = NULL;
- window = (xfWindow*) rail_window->extra;
+ xfWindow* xfw = NULL;
+ xfw = (xfWindow*) rail_window->extra;
DEBUG_X11_LMS("windowId=0x%X isMoveSizeStart=%d moveSizeType=%s PosX=%d PosY=%d",
movesize->windowId, movesize->isMoveSizeStart,
{
case RAIL_WMSZ_LEFT: //0x1
direction = _NET_WM_MOVERESIZE_SIZE_LEFT;
+ x = movesize->posX;
+ y = movesize->posY;
break;
case RAIL_WMSZ_RIGHT: //0x2
direction = _NET_WM_MOVERESIZE_SIZE_RIGHT;
+ x = movesize->posX;
+ y = movesize->posY;
break;
case RAIL_WMSZ_TOP: //0x3
direction = _NET_WM_MOVERESIZE_SIZE_TOP;
+ x = movesize->posX;
+ y = movesize->posY;
break;
case RAIL_WMSZ_TOPLEFT: //0x4
direction = _NET_WM_MOVERESIZE_SIZE_TOPLEFT;
+ x = movesize->posX;
+ y = movesize->posY;
break;
case RAIL_WMSZ_TOPRIGHT: //0x5
direction = _NET_WM_MOVERESIZE_SIZE_TOPRIGHT;
+ x = movesize->posX;
+ y = movesize->posY;
break;
case RAIL_WMSZ_BOTTOM: //0x6
direction = _NET_WM_MOVERESIZE_SIZE_BOTTOM;
+ x = movesize->posX;
+ y = movesize->posY;
break;
case RAIL_WMSZ_BOTTOMLEFT: //0x7
direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT;
+ x = movesize->posX;
+ y = movesize->posY;
break;
case RAIL_WMSZ_BOTTOMRIGHT: //0x8
direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT;
+ x = movesize->posX;
+ y = movesize->posY;
break;
case RAIL_WMSZ_MOVE: //0x9
direction = _NET_WM_MOVERESIZE_MOVE;
+ XTranslateCoordinates(xfi->display, xfw->handle, DefaultRootWindow(xfi->display),
+ movesize->posX, movesize->posY, &x, &y, &child_window);
break;
case RAIL_WMSZ_KEYMOVE: //0xA
direction = _NET_WM_MOVERESIZE_MOVE_KEYBOARD;
+ x = movesize->posX;
+ y = movesize->posY;
break;
case RAIL_WMSZ_KEYSIZE: //0xB
direction = _NET_WM_MOVERESIZE_SIZE_KEYBOARD;
+ x = movesize->posX;
+ y = movesize->posY;
break;
}
if (movesize->isMoveSizeStart)
{
- xf_StartLocalMoveSize(xfi, window, direction, movesize->posX, movesize->posY);
+ xf_StartLocalMoveSize(xfi, xfw, direction, x, y);
} else {
- xf_EndLocalMoveSize(xfi, window, True);
+ xf_MoveWindow(xfi, xfw, movesize->posX, movesize->posY,
+ xfw->width, xfw->height);
+ xf_EndLocalMoveSize(xfi, xfw, false);
}
}
}
void xf_rail_register_callbacks(xfInfo* xfi, rdpRail* rail);
void xf_rail_send_client_system_command(xfInfo* xfi, uint32 windowId, uint16 command);
void xf_rail_send_activate(xfInfo* xfi, Window xwindow, boolean enabled);
-void xf_rail_send_windowmove(xfInfo* xfi, uint32 windowId, uint32 left, uint32 top, uint32 right, uint32 bottom);
void xf_process_rail_event(xfInfo* xfi, rdpChannels* chanman, RDP_EVENT* event);
-void xf_rail_local_movesize(xfInfo* xfi, xfWindow* window);
+void xf_rail_adjust_position(xfInfo* xfi, rdpWindow *window);
+void xf_rail_end_local_move(xfInfo* xfi, rdpWindow *window);
#endif /* __XF_RAIL_H */
/* Extended Window Manager Hints: http://standards.freedesktop.org/wm-spec/wm-spec-1.3.html */
-#define MWM_HINTS_DECORATIONS (1L << 1)
+/* bit definitions for MwmHints.flags */
+#define MWM_HINTS_FUNCTIONS (1L << 0)
+#define MWM_HINTS_DECORATIONS (1L << 1)
+#define MWM_HINTS_INPUT_MODE (1L << 2)
+#define MWM_HINTS_STATUS (1L << 3)
+
+/* bit definitions for MwmHints.functions */
+#define MWM_FUNC_ALL (1L << 0)
+#define MWM_FUNC_RESIZE (1L << 1)
+#define MWM_FUNC_MOVE (1L << 2)
+#define MWM_FUNC_MINIMIZE (1L << 3)
+#define MWM_FUNC_MAXIMIZE (1L << 4)
+#define MWM_FUNC_CLOSE (1L << 5)
+
+/* bit definitions for MwmHints.decorations */
+#define MWM_DECOR_ALL (1L << 0)
+#define MWM_DECOR_BORDER (1L << 1)
+#define MWM_DECOR_RESIZEH (1L << 2)
+#define MWM_DECOR_TITLE (1L << 3)
+#define MWM_DECOR_MENU (1L << 4)
+#define MWM_DECOR_MINIMIZE (1L << 5)
+#define MWM_DECOR_MAXIMIZE (1L << 6)
+
#define PROP_MOTIF_WM_HINTS_ELEMENTS 5
struct _PropMotifWmHints
}
DEBUG_X11("Send ClientMessage Event: wnd=0x%04X", (unsigned int) xevent.xclient.window);
- XSendEvent(xfi->display, window->handle, False, NoEventMask, &xevent);
+ XSendEvent(xfi->display, DefaultRootWindow(xfi->display), False,
+ SubstructureRedirectMask | SubstructureNotifyMask, &xevent);
XSync(xfi->display, False);
va_end(argp);
{
PropMotifWmHints hints;
- hints.decorations = show;
- hints.flags = MWM_HINTS_DECORATIONS;
+ hints.decorations = (show) ? MWM_DECOR_ALL : 0;
+ hints.functions = MWM_FUNC_ALL ;
+ hints.flags = MWM_HINTS_DECORATIONS | MWM_HINTS_FUNCTIONS;
XChangeProperty(xfi->display, window->handle, xfi->_MOTIF_WM_HINTS, xfi->_MOTIF_WM_HINTS, 32,
PropModeReplace, (uint8*) &hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
{
Atom window_type;
- window_type = xfi->_NET_WM_WINDOW_TYPE_NORMAL;
-
- if ((style & WS_POPUP) || (style & WS_DLGFRAME) || (ex_style & WS_EX_DLGMODALFRAME))
+ if (style & WS_POPUP)
{
- window_type = xfi->_NET_WM_WINDOW_TYPE_DIALOG;
+ // WS_POPUP includes tool tips, dropdown menus, etc. These won't work
+ // correctly if the local window manager resizes or moves them. Set
+ // override redirect to prevent this from occurring.
+
+ XSetWindowAttributes attrs;
+ attrs.override_redirect = True;
+ XChangeWindowAttributes(xfi->display, window->handle, CWOverrideRedirect, &attrs);
+ window->is_transient = true;
+
+ window_type = xfi->_NET_WM_WINDOW_TYPE_POPUP;
}
-
- if (ex_style & WS_EX_TOOLWINDOW)
+ else
{
- xf_SetWindowUnlisted(xfi, window);
- window_type = xfi->_NET_WM_WINDOW_TYPE_UTILITY;
+ window_type = xfi->_NET_WM_WINDOW_TYPE_NORMAL;
}
XChangeProperty(xfi->display, window->handle, xfi->_NET_WM_WINDOW_TYPE,
XA_ATOM, 32, PropModeReplace, (uint8*) &window_type, 1);
+
}
xfWindow* xf_CreateDesktopWindow(xfInfo* xfi, char* name, int width, int height, boolean decorations)
window->height = height;
window->fullscreen = false;
window->decorations = decorations;
- window->isMapped = false;
+ window->local_move.state = LMS_NOT_ACTIVE;
+ window->is_mapped = false;
+ window->is_transient = false;
window->handle = XCreateWindow(xfi->display, RootWindowOfScreen(xfi->screen),
xfi->workArea.x, xfi->workArea.y, xfi->width, xfi->height, 0, xfi->depth, InputOutput, xfi->visual,
- CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
- CWBorderPixel, &xfi->attribs);
+ CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
+ CWBorderPixel | CWWinGravity | CWBitGravity, &xfi->attribs);
class_hints = XAllocClassHint();
window->height = height;
XGCValues gcv;
- int input_mask;
XClassHint* class_hints;
+ int input_mask;
window->decorations = false;
window->fullscreen = false;
window->window = wnd;
- window->localMove.inProgress = false;
- window->isMapped = false;
+ window->local_move.state = LMS_NOT_ACTIVE;
+ window->is_mapped = false;
+ window->is_transient = false;
+
+ // Proper behavior of tooltips, dropdown menus, etc, depend on the local window
+ // manager not modify them. Set override_redirect on these windows. RDP window
+ // styles don't map 1 to 1 to X window styles, but the presence of WM_POPUP
+ // appears to be sufficient for setting override_redirect.
window->handle = XCreateWindow(xfi->display, RootWindowOfScreen(xfi->screen),
x, y, window->width, window->height, 0, xfi->depth, InputOutput, xfi->visual,
- CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
- CWBorderPixel, &xfi->attribs);
+ CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
+ CWBorderPixel | CWWinGravity | CWBitGravity, &xfi->attribs);
+
+ DEBUG_X11_LMS("Create window=0x%X rc={l=%d t=%d r=%d b=%d} w=%d h=%d rdp=0x%X",
+ (uint32) window->handle, window->left, window->top, window->right, window->bottom,
+ window->width, window->height, wnd->windowId);
xf_SetWindowDecorations(xfi, window, window->decorations);
+ xf_SetWindowStyle(xfi, window, wnd->style, wnd->extendedStyle);
class_hints = XAllocClassHint();
XSetWMProtocols(xfi->display, window->handle, &(xfi->WM_DELETE_WINDOW), 1);
- input_mask =
- KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
- VisibilityChangeMask | FocusChangeMask | StructureNotifyMask |
- PointerMotionMask | ExposureMask | EnterWindowMask;
+ input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask |
+ ButtonReleaseMask | EnterWindowMask | LeaveWindowMask |
+ PointerMotionMask | Button1MotionMask | Button2MotionMask |
+ Button3MotionMask | Button4MotionMask | Button5MotionMask |
+ ButtonMotionMask | KeymapStateMask | ExposureMask |
+ VisibilityChangeMask | StructureNotifyMask | SubstructureNotifyMask |
+ SubstructureRedirectMask | FocusChangeMask | PropertyChangeMask |
+ ColormapChangeMask | OwnerGrabButtonMask;
XSelectInput(xfi->display, window->handle, input_mask);
XMapWindow(xfi->display, window->handle);
}
}
-void xf_StartLocalMoveSize(xfInfo* xfi, xfWindow* window, int direction, int windowRelativeX, int windowRelativeY)
+void xf_StartLocalMoveSize(xfInfo* xfi, xfWindow* window, int direction, int x, int y)
{
- window->localMove.windowRelativeX = windowRelativeX;
- window->localMove.windowRelativeY = windowRelativeY;
-
- DEBUG_X11_LMS("direction=%d coords=%d,%d window=0x%X rc={l=%d t=%d r=%d b=%d} w=%d h=%d",
- direction, windowRelativeX, windowRelativeY,
- (uint32) window->handle, window->left, window->top, window->right, window->bottom,
- window->width, window->height);
-
- // FIXME: There does not appear a way to tell when the local window manager completes
- // a window move or resize. The client will receive a number of ConfigureNotify events
- // but nothing indicates when the user has completed the move gesture (keyboard or mouse).
- //
- return;
-
- // X Server _WM_MOVERESIZE coordinates are expressed relative to the root window.
- // RDP coordinates are expressed relative to the local window.
- // Translate these to root window coordinates.
-
- window->localMove.inProgress = True;
- Window childWindow;
- int x,y;
-
- XTranslateCoordinates(xfi->display, window->handle, DefaultRootWindow(xfi->display),
- windowRelativeX, windowRelativeY, &x, &y, &childWindow);
+ rdpWindow* wnd = window->window;
+ Window child_window;
+
+ DEBUG_X11_LMS("direction=%d window=0x%X rc={l=%d t=%d r=%d b=%d} w=%d h=%d "
+ "RDP=0x%X rc={l=%d t=%d} w=%d h=%d mouse_x=%d mouse_y=%d",
+ direction, (uint32) window->handle,
+ window->left, window->top, window->right, window->bottom,
+ window->width, window->height,
+ wnd->windowId,
+ wnd->windowOffsetX, wnd->windowOffsetY,
+ wnd->windowWidth, wnd->windowHeight,
+ x, y);
+
+ window->local_move.root_x = x;
+ window->local_move.root_y = y;
+ window->local_move.state = LMS_ACTIVE;
+
+ XTranslateCoordinates(xfi->display, DefaultRootWindow(xfi->display), window->handle,
+ window->local_move.root_x,
+ window->local_move.root_y,
+ &window->local_move.window_x,
+ &window->local_move.window_y,
+ &child_window);
XUngrabPointer(xfi->display, CurrentTime);
xf_SendClientEvent(xfi, window,
void xf_EndLocalMoveSize(xfInfo *xfi, xfWindow *window, boolean cancel)
{
- DEBUG_X11_LMS("inProcess=%d cancel=%d window=0x%X rc={l=%d t=%d r=%d b=%d} w=%d h=%d",
- window->localMove.inProgress, cancel,
- (uint32) window->handle, window->left, window->top, window->right, window->bottom,
- window->width, window->height);
+ rdpWindow* wnd = window->window;
- if (!window->localMove.inProgress)
+ DEBUG_X11_LMS("inProcess=%d cancel=%d window=0x%X rc={l=%d t=%d r=%d b=%d} w=%d h=%d "
+ "RDP=0x%X rc={l=%d t=%d} w=%d h=%d",
+ window->local_move.state, cancel,
+ (uint32) window->handle, window->left, window->top, window->right, window->bottom,
+ window->width, window->height,
+ wnd->windowId,
+ wnd->windowOffsetX, wnd->windowOffsetY,
+ wnd->windowWidth, wnd->windowHeight);
+
+ if (window->local_move.state == LMS_NOT_ACTIVE)
return;
if (cancel)
{
// Per ICCM, the X client can ask to cancel an active move. Do this if we
// receive a local move stop from RDP while a local move is in progress
- Window childWindow;
- int x,y;
-
- XTranslateCoordinates(xfi->display, window->handle, DefaultRootWindow(xfi->display),
- window->localMove.windowRelativeX, window->localMove.windowRelativeY, &x, &y, &childWindow);
xf_SendClientEvent(xfi, window,
- xfi->_NET_WM_MOVERESIZE, // Request X window manager to initate a local move
+ xfi->_NET_WM_MOVERESIZE, // Request X window manager to abort a local move
5, // 5 arguments to follow
- x, // x relative to root window
- y, // y relative to root window
+ window->local_move.root_x, // x relative to root window
+ window->local_move.root_y, // y relative to root window
_NET_WM_MOVERESIZE_CANCEL, // extended ICCM direction flag
1, // simulated mouse button 1
1);// 1 == application request per extended ICCM
}
- window->localMove.inProgress = False;
+ window->local_move.state = LMS_NOT_ACTIVE;
}
void xf_MoveWindow(xfInfo* xfi, xfWindow* window, int x, int y, int width, int height)
{
boolean resize = false;
+ rdpWindow* wnd = window->window;
if ((width * height) < 1)
return;
if ((window->width != width) || (window->height != height))
resize = true;
+ DEBUG_X11_LMS("window=0x%X current rc={l=%d t=%d r=%d b=%d} w=%u h=%u "
+ "new rc={l=%d t=%d r=%d b=%d} w=%u h=%u"
+ " RDP=0x%X rc={l=%d t=%d} w=%d h=%d",
+ (uint32) window->handle, window->left, window->top,
+ window->right, window->bottom, window->width, window->height,
+ x, y, x + width -1, y + height -1, width, height,
+ wnd->windowId,
+ wnd->windowOffsetX, wnd->windowOffsetY,
+ wnd->windowWidth, wnd->windowHeight);
+
window->left = x;
window->top = y;
window->right = x + width - 1;
window->width = width;
window->height = height;
- if (resize)
- XMoveResizeWindow(xfi->display, window->handle, x, y, width, height);
- else
- XMoveWindow(xfi->display, window->handle, x, y);
-
- DEBUG_X11_LMS("window=0x%X rc={l=%d t=%d r=%d b=%d} w=%d h=%d",
- (uint32) window->handle, window->left, window->top, window->right, window->bottom,
- window->width, window->height);
-
- if (resize)
+ if (window->is_transient)
{
- xf_UpdateWindowArea(xfi, window, 0, 0, width, height);
+ if (resize)
+ XMoveResizeWindow(xfi->display, window->handle, x, y, width, height);
+ else
+ XMoveWindow(xfi->display, window->handle, x, y);
+ } else {
+ // Sending a client event preserves
+ // window gravity
+ xf_SendClientEvent(xfi, window,
+ xfi->_NET_MOVERESIZE_WINDOW, // Request X window manager to move window
+ 5, // 5 arguments to follow
+ 0x1F0A, // STATIC gravity
+ x, // x relative to root window
+ y, // y relative to root window
+ width,
+ height);
}
-
}
void xf_ShowWindow(xfInfo* xfi, xfWindow* window, uint8 state)
{
int ax, ay;
rdpWindow* wnd;
-
wnd = window->window;
+
ax = x + wnd->windowOffsetX;
ay = y + wnd->windowOffsetY;
#define _NET_WM_MOVERESIZE_MOVE_KEYBOARD 10 /* move via keyboard */
#define _NET_WM_MOVERESIZE_CANCEL 11 /* cancel operation */
+enum xf_localmove_state
+{
+ LMS_NOT_ACTIVE,
+ LMS_ACTIVE,
+ LMS_TERMINATING
+};
+
struct xf_localmove
{
- int windowRelativeX;
- int windowRelativeY;
- boolean inProgress;
+ int root_x; // relative to root
+ int root_y;
+ int window_x; // relative to window
+ int window_y;
+ enum xf_localmove_state state;
};
struct xf_window
boolean fullscreen;
boolean decorations;
rdpWindow* window;
- boolean isMapped;
- xfLocalMove localMove;
+ boolean is_mapped;
+ boolean is_transient;
+ xfLocalMove local_move;
};
void xf_ewmhints_init(xfInfo* xfi);
int maxPosX, int maxPosY, int minTrackWidth, int minTrackHeight, int maxTrackWidth, int maxTrackHeight);
-void xf_StartLocalMoveSize(xfInfo* xfi, xfWindow* window, int direction, int windowRelativeX, int windowRelativeY);
+void xf_StartLocalMoveSize(xfInfo* xfi, xfWindow* window, int direction, int x, int y);
void xf_EndLocalMoveSize(xfInfo *xfi, xfWindow *window, boolean cancel);
void xf_SendClientEvent(xfInfo *xfi, xfWindow* window, Atom atom, unsigned int numArgs, ...);
xfi->attribs.backing_store = xfi->primary ? NotUseful : Always;
xfi->attribs.override_redirect = xfi->fullscreen;
xfi->attribs.colormap = xfi->colormap;
+ xfi->attribs.bit_gravity = ForgetGravity;
+ xfi->attribs.win_gravity = StaticGravity;
if (xfi->remote_app != true)
{
return false;
}
- xfi->_NET_WM_ICON = XInternAtom(xfi->display, "_NET_WM_ICON", false);
- xfi->_MOTIF_WM_HINTS = XInternAtom(xfi->display, "_MOTIF_WM_HINTS", false);
- xfi->_NET_CURRENT_DESKTOP = XInternAtom(xfi->display, "_NET_CURRENT_DESKTOP", false);
- xfi->_NET_WORKAREA = XInternAtom(xfi->display, "_NET_WORKAREA", false);
- xfi->_NET_WM_STATE = XInternAtom(xfi->display, "_NET_WM_STATE", false);
- xfi->_NET_WM_STATE_FULLSCREEN = XInternAtom(xfi->display, "_NET_WM_STATE_FULLSCREEN", false);
- xfi->_NET_WM_WINDOW_TYPE = XInternAtom(xfi->display, "_NET_WM_WINDOW_TYPE", false);
-
- xfi->_NET_WM_WINDOW_TYPE_NORMAL = XInternAtom(xfi->display, "_NET_WM_WINDOW_TYPE_NORMAL", false);
- xfi->_NET_WM_WINDOW_TYPE_DIALOG = XInternAtom(xfi->display, "_NET_WM_WINDOW_TYPE_DIALOG", false);
- xfi->_NET_WM_WINDOW_TYPE_UTILITY = XInternAtom(xfi->display, "_NET_WM_WINDOW_TYPE_UTILITY", false);
- xfi->_NET_WM_STATE_SKIP_TASKBAR = XInternAtom(xfi->display, "_NET_WM_STATE_SKIP_TASKBAR", false);
- xfi->_NET_WM_STATE_SKIP_PAGER = XInternAtom(xfi->display, "_NET_WM_STATE_SKIP_PAGER", false);
-
- xfi->_NET_WM_MOVERESIZE = XInternAtom(xfi->display, "_NET_WM_MOVERESIZE", false);
-
- xfi->WM_PROTOCOLS = XInternAtom(xfi->display, "WM_PROTOCOLS", false);
- xfi->WM_DELETE_WINDOW = XInternAtom(xfi->display, "WM_DELETE_WINDOW", false);
+ xfi->_NET_WM_ICON = XInternAtom(xfi->display, "_NET_WM_ICON", True);
+ xfi->_MOTIF_WM_HINTS = XInternAtom(xfi->display, "_MOTIF_WM_HINTS", True);
+ xfi->_NET_CURRENT_DESKTOP = XInternAtom(xfi->display, "_NET_CURRENT_DESKTOP", True);
+ xfi->_NET_WORKAREA = XInternAtom(xfi->display, "_NET_WORKAREA", True);
+ xfi->_NET_WM_STATE = XInternAtom(xfi->display, "_NET_WM_STATE", True);
+ xfi->_NET_WM_STATE_FULLSCREEN = XInternAtom(xfi->display, "_NET_WM_STATE_FULLSCREEN", True);
+ xfi->_NET_WM_WINDOW_TYPE = XInternAtom(xfi->display, "_NET_WM_WINDOW_TYPE", True);
+
+ xfi->_NET_WM_WINDOW_TYPE_NORMAL = XInternAtom(xfi->display, "_NET_WM_WINDOW_TYPE_NORMAL", True);
+ xfi->_NET_WM_WINDOW_TYPE_DIALOG = XInternAtom(xfi->display, "_NET_WM_WINDOW_TYPE_DIALOG", True);
+ xfi->_NET_WM_WINDOW_TYPE_POPUP= XInternAtom(xfi->display, "_NET_WM_WINDOW_TYPE_POPUP", True);
+ xfi->_NET_WM_WINDOW_TYPE_UTILITY = XInternAtom(xfi->display, "_NET_WM_WINDOW_TYPE_UTILITY", True);
+ xfi->_NET_WM_WINDOW_TYPE_DROPDOWN_MENU = XInternAtom(xfi->display, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU", True);
+ xfi->_NET_WM_STATE_SKIP_TASKBAR = XInternAtom(xfi->display, "_NET_WM_STATE_SKIP_TASKBAR", True);
+ xfi->_NET_WM_STATE_SKIP_PAGER = XInternAtom(xfi->display, "_NET_WM_STATE_SKIP_PAGER", True);
+ xfi->_NET_WM_MOVERESIZE = XInternAtom(xfi->display, "_NET_WM_MOVERESIZE", True);
+ xfi->_NET_MOVERESIZE_WINDOW = XInternAtom(xfi->display, "_NET_MOVERESIZE_WINDOW", True);
+
+ xfi->WM_PROTOCOLS = XInternAtom(xfi->display, "WM_PROTOCOLS", True);
+ xfi->WM_DELETE_WINDOW = XInternAtom(xfi->display, "WM_DELETE_WINDOW", True);
xf_kbd_init(xfi);
Atom _NET_WM_WINDOW_TYPE_NORMAL;
Atom _NET_WM_WINDOW_TYPE_DIALOG;
Atom _NET_WM_WINDOW_TYPE_UTILITY;
+ Atom _NET_WM_WINDOW_TYPE_POPUP;
+ Atom _NET_WM_WINDOW_TYPE_DROPDOWN_MENU;
Atom _NET_WM_MOVERESIZE;
+ Atom _NET_MOVERESIZE_WINDOW;
Atom WM_PROTOCOLS;
Atom WM_DELETE_WINDOW;