mirror of
https://github.com/morgan9e/FreeRDP
synced 2026-04-15 00:44:19 +09:00
Complete local move support. Use a state machine to keep track of XEvents to infer local move start and finish.
This commit is contained in:
@@ -554,71 +554,99 @@ boolean xf_event_PropertyNotify(xfInfo* xfi, XEvent* event, boolean app)
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean xf_event_process(freerdp* instance, XEvent* event)
|
||||
boolean xf_event_suppress_events(xfInfo *xfi, rdpWindow *window, XEvent*event)
|
||||
{
|
||||
boolean status = true;
|
||||
xfInfo* xfi = ((xfContext*) instance->context)->xfi;
|
||||
if (! xfi->remote_app)
|
||||
return false;
|
||||
|
||||
if (xfi->window && xfi->window->local_move.state == LMS_ACTIVE)
|
||||
switch (xfi->window->local_move.state)
|
||||
{
|
||||
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 LMS_NOT_ACTIVE:
|
||||
// No local move in progress, nothing to do
|
||||
break;
|
||||
case LMS_STARTING:
|
||||
// Local move initiated by RDP server, but we
|
||||
// have not yet seen any updates from the X server
|
||||
switch(event->type)
|
||||
{
|
||||
case ConfigureNotify:
|
||||
// Starting to see move events
|
||||
// from the X server. Local
|
||||
// move is now in progress.
|
||||
xfi->window->local_move.state = LMS_ACTIVE;
|
||||
|
||||
// Allow these events to be processed during move to keep
|
||||
// our state up to date.
|
||||
break;
|
||||
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.
|
||||
// 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_rail_end_local_move(xfi, window);
|
||||
break;
|
||||
case VisibilityNotify:
|
||||
case PropertyNotify:
|
||||
// Allow these events to pass
|
||||
return false;
|
||||
default:
|
||||
// Eat any other events
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case LMS_ACTIVE:
|
||||
// Local move is in progress
|
||||
switch(event->type)
|
||||
{
|
||||
case ConfigureNotify:
|
||||
case VisibilityNotify:
|
||||
case PropertyNotify:
|
||||
// Keep us up to date on position
|
||||
break;
|
||||
case Expose:
|
||||
return true;
|
||||
default:
|
||||
// Any other event terminates move
|
||||
xf_rail_end_local_move(xfi, window);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case LMS_TERMINATING:
|
||||
// Already sent RDP end move to sever
|
||||
// Allow events to pass.
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
boolean xf_event_process(freerdp* instance, XEvent* event)
|
||||
{
|
||||
boolean status = true;
|
||||
xfInfo* xfi = ((xfContext*) instance->context)->xfi;
|
||||
rdpRail* rail = ((rdpContext*) xfi->context)->rail;
|
||||
rdpWindow* window;
|
||||
|
||||
if (xfi->remote_app)
|
||||
{
|
||||
window = window_list_get_by_extra_id(
|
||||
rail->list, (void*) event->xexpose.window);
|
||||
if (window)
|
||||
{
|
||||
// Update "current" window for cursor change orders
|
||||
xfi->window = (xfWindow *) window->extra;
|
||||
|
||||
if (xf_event_suppress_events(xfi, window, event))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -715,10 +743,6 @@ boolean xf_event_process(freerdp* instance, XEvent* event)
|
||||
case PropertyNotify:
|
||||
status = xf_event_PropertyNotify(xfi, event, xfi->remote_app);
|
||||
break;
|
||||
|
||||
default:
|
||||
DEBUG_X11("xf_event_process unknown event %d", event->type);
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
|
||||
@@ -263,13 +263,12 @@ void xf_rail_adjust_position(xfInfo* xfi, rdpWindow *window)
|
||||
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",
|
||||
" RDP=0x%X rc={l=%d t=%d} w=%d h=%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);
|
||||
window->windowWidth, window->windowHeight);
|
||||
|
||||
// If current window position disagrees with RDP window position, send
|
||||
// update to RDP server
|
||||
|
||||
@@ -85,7 +85,7 @@ void xf_SendClientEvent(xfInfo *xfi, xfWindow* window, Atom atom, unsigned int n
|
||||
|
||||
xevent.xclient.type = ClientMessage;
|
||||
xevent.xclient.serial = 0;
|
||||
xevent.xclient.send_event = True;
|
||||
xevent.xclient.send_event = False;
|
||||
xevent.xclient.display = xfi->display;
|
||||
xevent.xclient.window = window->handle;
|
||||
xevent.xclient.message_type = atom;
|
||||
@@ -483,7 +483,7 @@ void xf_StartLocalMoveSize(xfInfo* xfi, xfWindow* window, int direction, int x,
|
||||
|
||||
window->local_move.root_x = x;
|
||||
window->local_move.root_y = y;
|
||||
window->local_move.state = LMS_ACTIVE;
|
||||
window->local_move.state = LMS_STARTING;
|
||||
|
||||
XTranslateCoordinates(xfi->display, DefaultRootWindow(xfi->display), window->handle,
|
||||
window->local_move.root_x,
|
||||
@@ -507,7 +507,7 @@ void xf_EndLocalMoveSize(xfInfo *xfi, xfWindow *window, boolean cancel)
|
||||
{
|
||||
rdpWindow* wnd = window->window;
|
||||
|
||||
DEBUG_X11_LMS("inProcess=%d cancel=%d window=0x%X rc={l=%d t=%d r=%d b=%d} w=%d h=%d "
|
||||
DEBUG_X11_LMS("state=%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,
|
||||
@@ -565,24 +565,10 @@ void xf_MoveWindow(xfInfo* xfi, xfWindow* window, int x, int y, int width, int h
|
||||
window->width = width;
|
||||
window->height = height;
|
||||
|
||||
if (window->is_transient)
|
||||
{
|
||||
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);
|
||||
}
|
||||
if (resize)
|
||||
XMoveResizeWindow(xfi->display, window->handle, x, y, width, height);
|
||||
else
|
||||
XMoveWindow(xfi->display, window->handle, x, y);
|
||||
}
|
||||
|
||||
void xf_ShowWindow(xfInfo* xfi, xfWindow* window, uint8 state)
|
||||
|
||||
@@ -46,6 +46,7 @@ typedef struct xf_window xfWindow;
|
||||
enum xf_localmove_state
|
||||
{
|
||||
LMS_NOT_ACTIVE,
|
||||
LMS_STARTING,
|
||||
LMS_ACTIVE,
|
||||
LMS_TERMINATING
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user