Add a function to synchronize the RDP server with the local window position and size when the window is moved locally.
Complete implementation for initiating RAIL local move support, however, this is still disabled until a method is found to tell when local moves complete on the X server.
This commit is contained in:
parent
354b00711b
commit
31cbac201d
@ -462,27 +462,8 @@ boolean xf_event_ConfigureNotify(xfInfo* xfi, XEvent* event, boolean app)
|
||||
xfw->bottom = xfw->top + xfw->height - 1;
|
||||
|
||||
if (app)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
xf_rail_send_windowmove(xfi, window->windowId,
|
||||
xfw->left, xfw->top, xfw->right, xfw->bottom);
|
||||
}
|
||||
}
|
||||
xf_rail_local_movesize(xfi, xfw);
|
||||
|
||||
DEBUG_X11_LMS("ConfigureNotify: send_event=%d eventWindow=0x%X window=0x%X above=0x%X rc={l=%d t=%d r=%d b=%d} "
|
||||
"w=%d h=%d override_redirect=%d",
|
||||
event->xconfigure.send_event,
|
||||
(uint32) event->xconfigure.event,
|
||||
(uint32) event->xconfigure.window,
|
||||
(uint32) event->xconfigure.above,
|
||||
xfw->left, xfw->top, xfw->right, xfw->bottom, xfw->width, xfw->height,
|
||||
event->xconfigure.override_redirect);
|
||||
}
|
||||
|
||||
return True;
|
||||
@ -502,6 +483,27 @@ boolean xf_event_MapNotify(xfInfo* xfi, XEvent* event, boolean app)
|
||||
{
|
||||
/* local restore event */
|
||||
xf_rail_send_client_system_command(xfi, window->windowId, SC_RESTORE);
|
||||
xfWindow *xfw = (xfWindow*) window->extra;
|
||||
xfw->isMapped = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean xf_event_UnmapNotify(xfInfo* xfi, XEvent* event, boolean app)
|
||||
{
|
||||
rdpWindow* window;
|
||||
rdpRail* rail = ((rdpContext*) xfi->context)->rail;
|
||||
|
||||
if (app != true)
|
||||
return true;
|
||||
|
||||
window = window_list_get_by_extra_id(rail->list, (void*) event->xany.window);
|
||||
|
||||
if (window != NULL)
|
||||
{
|
||||
xfWindow *xfw = (xfWindow*) window->extra;
|
||||
xfw->isMapped = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -631,6 +633,10 @@ boolean xf_event_process(freerdp* instance, XEvent* event)
|
||||
status = xf_event_MapNotify(xfi, event, app);
|
||||
break;
|
||||
|
||||
case UnmapNotify:
|
||||
status = xf_event_UnmapNotify(xfi, event, app);
|
||||
break;
|
||||
|
||||
case ReparentNotify:
|
||||
break;
|
||||
|
||||
|
@ -25,5 +25,6 @@
|
||||
#include "xfreerdp.h"
|
||||
|
||||
boolean xf_event_process(freerdp* instance, XEvent* event);
|
||||
void xf_event_SendClientEvent(xfInfo *xfi, xfWindow* window, Atom atom, unsigned int numArgs, ...);
|
||||
|
||||
#endif /* __XF_EVENT_H */
|
||||
|
@ -108,6 +108,39 @@ void xf_rail_MoveWindow(rdpRail* rail, rdpWindow* window)
|
||||
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;
|
||||
@ -364,6 +397,7 @@ void xf_process_rail_server_localmovesize_event(xfInfo* xfi, rdpChannels* channe
|
||||
rdpRail* rail;
|
||||
rdpWindow* rail_window = NULL;
|
||||
RAIL_LOCALMOVESIZE_ORDER* movesize = (RAIL_LOCALMOVESIZE_ORDER*) event->user_data;
|
||||
int direction = 0;
|
||||
|
||||
rail = ((rdpContext*) xfi->context)->rail;
|
||||
rail_window = window_list_get_by_id(rail->list, movesize->windowId);
|
||||
@ -377,12 +411,50 @@ void xf_process_rail_server_localmovesize_event(xfInfo* xfi, rdpChannels* channe
|
||||
movesize->windowId, movesize->isMoveSizeStart,
|
||||
movetype_names[movesize->moveSizeType], (sint16) movesize->posX, (sint16) movesize->posY);
|
||||
|
||||
if (movesize->isMoveSizeStart)
|
||||
xf_StartLocalMoveSize(xfi, window, movesize->moveSizeType, (int) movesize->posX, (int) movesize->posY);
|
||||
else
|
||||
xf_StopLocalMoveSize(xfi, window, movesize->moveSizeType, (int) movesize->posX, (int) movesize->posY);
|
||||
switch (movesize->moveSizeType)
|
||||
{
|
||||
case RAIL_WMSZ_LEFT: //0x1
|
||||
direction = _NET_WM_MOVERESIZE_SIZE_LEFT;
|
||||
break;
|
||||
case RAIL_WMSZ_RIGHT: //0x2
|
||||
direction = _NET_WM_MOVERESIZE_SIZE_RIGHT;
|
||||
break;
|
||||
case RAIL_WMSZ_TOP: //0x3
|
||||
direction = _NET_WM_MOVERESIZE_SIZE_TOP;
|
||||
break;
|
||||
case RAIL_WMSZ_TOPLEFT: //0x4
|
||||
direction = _NET_WM_MOVERESIZE_SIZE_TOPLEFT;
|
||||
break;
|
||||
case RAIL_WMSZ_TOPRIGHT: //0x5
|
||||
direction = _NET_WM_MOVERESIZE_SIZE_TOPRIGHT;
|
||||
break;
|
||||
case RAIL_WMSZ_BOTTOM: //0x6
|
||||
direction = _NET_WM_MOVERESIZE_SIZE_BOTTOM;
|
||||
break;
|
||||
case RAIL_WMSZ_BOTTOMLEFT: //0x7
|
||||
direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT;
|
||||
break;
|
||||
case RAIL_WMSZ_BOTTOMRIGHT: //0x8
|
||||
direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT;
|
||||
break;
|
||||
case RAIL_WMSZ_MOVE: //0x9
|
||||
direction = _NET_WM_MOVERESIZE_MOVE;
|
||||
break;
|
||||
case RAIL_WMSZ_KEYMOVE: //0xA
|
||||
direction = _NET_WM_MOVERESIZE_MOVE_KEYBOARD;
|
||||
break;
|
||||
case RAIL_WMSZ_KEYSIZE: //0xB
|
||||
direction = _NET_WM_MOVERESIZE_SIZE_KEYBOARD;
|
||||
break;
|
||||
}
|
||||
|
||||
if (movesize->isMoveSizeStart)
|
||||
{
|
||||
xf_StartLocalMoveSize(xfi, window, direction, movesize->posX, movesize->posY);
|
||||
} else {
|
||||
xf_EndLocalMoveSize(xfi, window, True);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void xf_process_rail_appid_resp_event(xfInfo* xfi, rdpChannels* channels, RDP_EVENT* event)
|
||||
|
@ -28,5 +28,6 @@ void xf_rail_send_client_system_command(xfInfo* xfi, uint32 windowId, uint16 com
|
||||
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);
|
||||
|
||||
#endif /* __XF_RAIL_H */
|
||||
|
@ -17,6 +17,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/Xatom.h>
|
||||
@ -49,22 +50,35 @@ struct _PropMotifWmHints
|
||||
};
|
||||
typedef struct _PropMotifWmHints PropMotifWmHints;
|
||||
|
||||
void xf_SendClientMessage(xfInfo* xfi, xfWindow* window, Atom atom, long msg, long d1, long d2, long d3)
|
||||
/**
|
||||
* Post an event from the client to the X server
|
||||
*/
|
||||
void xf_SendClientEvent(xfInfo *xfi, xfWindow* window, Atom atom, unsigned int numArgs, ...)
|
||||
{
|
||||
XEvent xevent;
|
||||
unsigned int i;
|
||||
va_list argp;
|
||||
|
||||
va_start(argp, numArgs);
|
||||
|
||||
xevent.xclient.type = ClientMessage;
|
||||
xevent.xclient.message_type = atom;
|
||||
xevent.xclient.serial = 0;
|
||||
xevent.xclient.send_event = True;
|
||||
xevent.xclient.display = xfi->display;
|
||||
xevent.xclient.window = window->handle;
|
||||
xevent.xclient.message_type = atom;
|
||||
xevent.xclient.format = 32;
|
||||
xevent.xclient.data.l[0] = CurrentTime;
|
||||
xevent.xclient.data.l[1] = msg;
|
||||
xevent.xclient.data.l[2] = d1;
|
||||
xevent.xclient.data.l[3] = d2;
|
||||
xevent.xclient.data.l[4] = d3;
|
||||
|
||||
XSendEvent(xfi->display, window->handle, false, NoEventMask, &xevent);
|
||||
XSync(xfi->display, false);
|
||||
for (i=0; i<numArgs; i++)
|
||||
{
|
||||
xevent.xclient.data.l[i] = va_arg(argp, int);
|
||||
}
|
||||
|
||||
DEBUG_X11("Send ClientMessage Event: wnd=0x%04X", (unsigned int) xevent.xclient.window);
|
||||
XSendEvent(xfi->display, window->handle, False, NoEventMask, &xevent);
|
||||
XSync(xfi->display, False);
|
||||
|
||||
va_end(argp);
|
||||
}
|
||||
|
||||
void xf_SetWindowFullscreen(xfInfo* xfi, xfWindow* window, boolean fullscreen)
|
||||
@ -221,6 +235,7 @@ xfWindow* xf_CreateDesktopWindow(xfInfo* xfi, char* name, int width, int height,
|
||||
window->height = height;
|
||||
window->fullscreen = false;
|
||||
window->decorations = decorations;
|
||||
window->isMapped = 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,
|
||||
@ -336,7 +351,8 @@ xfWindow* xf_CreateWindow(xfInfo* xfi, rdpWindow* wnd, int x, int y, int width,
|
||||
window->decorations = false;
|
||||
window->fullscreen = false;
|
||||
window->window = wnd;
|
||||
window->localMoveSize = false;
|
||||
window->localMove.inProgress = false;
|
||||
window->isMapped = false;
|
||||
|
||||
window->handle = XCreateWindow(xfi->display, RootWindowOfScreen(xfi->screen),
|
||||
x, y, window->width, window->height, 0, xfi->depth, InputOutput, xfi->visual,
|
||||
@ -403,41 +419,75 @@ void xf_SetWindowMinMaxInfo(xfInfo* xfi, xfWindow* window,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void xf_SendMoveResizeEvent(xfInfo* xfi, xfWindow* window, int direction, int x_root, int y_root)
|
||||
void xf_StartLocalMoveSize(xfInfo* xfi, xfWindow* window, int direction, int windowRelativeX, int windowRelativeY)
|
||||
{
|
||||
// TODO:
|
||||
// - how to receive movesize canceling event?
|
||||
// - how to produce correct RAIL movesize finish?
|
||||
// - how to receive move/size window coordinates in process of local move/size?
|
||||
window->localMove.windowRelativeX = windowRelativeX;
|
||||
window->localMove.windowRelativeY = windowRelativeY;
|
||||
|
||||
XEvent event;
|
||||
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);
|
||||
|
||||
event.xclient.type = ClientMessage;
|
||||
event.xclient.window = window->handle;
|
||||
event.xclient.message_type = xfi->_NET_WM_MOVERESIZE;
|
||||
event.xclient.serial = 0;
|
||||
event.xclient.display = xfi->display;
|
||||
event.xclient.send_event = true;
|
||||
event.xclient.format = 32;
|
||||
event.xclient.data.l[0] = x_root;
|
||||
event.xclient.data.l[1] = y_root;
|
||||
event.xclient.data.l[2] = direction;
|
||||
event.xclient.data.l[3] = 1; /* button 1 */
|
||||
event.xclient.data.l[4] = 0;
|
||||
// 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);
|
||||
|
||||
XUngrabPointer(xfi->display, CurrentTime);
|
||||
XSendEvent(xfi->display, RootWindowOfScreen(xfi->screen), false, SubstructureNotifyMask, &event);
|
||||
xf_SendClientEvent(xfi, window,
|
||||
xfi->_NET_WM_MOVERESIZE, // Request X window manager to initate a local move
|
||||
5, // 5 arguments to follow
|
||||
x, // x relative to root window
|
||||
y, // y relative to root window
|
||||
direction, // extended ICCM direction flag
|
||||
1, // simulated mouse button 1
|
||||
1);// 1 == application request per extended ICCM
|
||||
}
|
||||
|
||||
void xf_StartLocalMoveSize(xfInfo* xfi, xfWindow* window, uint16 moveSizeType, int posX, int posY)
|
||||
void xf_EndLocalMoveSize(xfInfo *xfi, xfWindow *window, boolean cancel)
|
||||
{
|
||||
window->localMoveSize = true;
|
||||
}
|
||||
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);
|
||||
|
||||
void xf_StopLocalMoveSize(xfInfo* xfi, xfWindow* window, uint16 moveSizeType, int posX, int posY)
|
||||
{
|
||||
window->localMoveSize = false;
|
||||
if (!window->localMove.inProgress)
|
||||
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
|
||||
5, // 5 arguments to follow
|
||||
x, // x relative to root window
|
||||
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;
|
||||
}
|
||||
|
||||
void xf_MoveWindow(xfInfo* xfi, xfWindow* window, int x, int y, int width, int height)
|
||||
@ -450,11 +500,6 @@ void xf_MoveWindow(xfInfo* xfi, xfWindow* window, int x, int y, int width, int h
|
||||
if ((window->width != width) || (window->height != height))
|
||||
resize = true;
|
||||
|
||||
if (resize)
|
||||
XMoveResizeWindow(xfi->display, window->handle, x, y, width, height);
|
||||
else
|
||||
XMoveWindow(xfi->display, window->handle, x, y);
|
||||
|
||||
window->left = x;
|
||||
window->top = y;
|
||||
window->right = x + width - 1;
|
||||
@ -462,7 +507,12 @@ void xf_MoveWindow(xfInfo* xfi, xfWindow* window, int x, int y, int width, int h
|
||||
window->width = width;
|
||||
window->height = height;
|
||||
|
||||
DEBUG_X11_LMS("xf_MoveWindow: window=0x%X rc={l=%d t=%d r=%d b=%d} w=%d h=%d",
|
||||
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);
|
||||
|
||||
@ -470,6 +520,7 @@ void xf_MoveWindow(xfInfo* xfi, xfWindow* window, int x, int y, int width, int h
|
||||
{
|
||||
xf_UpdateWindowArea(xfi, window, 0, 0, width, height);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void xf_ShowWindow(xfInfo* xfi, xfWindow* window, uint8 state)
|
||||
|
@ -24,10 +24,32 @@
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
|
||||
typedef struct xf_localmove xfLocalMove;
|
||||
typedef struct xf_window xfWindow;
|
||||
|
||||
#include "xfreerdp.h"
|
||||
|
||||
// Extended ICCM flags http://standards.freedesktop.org/wm-spec/wm-spec-latest.html
|
||||
#define _NET_WM_MOVERESIZE_SIZE_TOPLEFT 0
|
||||
#define _NET_WM_MOVERESIZE_SIZE_TOP 1
|
||||
#define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT 2
|
||||
#define _NET_WM_MOVERESIZE_SIZE_RIGHT 3
|
||||
#define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT 4
|
||||
#define _NET_WM_MOVERESIZE_SIZE_BOTTOM 5
|
||||
#define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT 6
|
||||
#define _NET_WM_MOVERESIZE_SIZE_LEFT 7
|
||||
#define _NET_WM_MOVERESIZE_MOVE 8 /* movement only */
|
||||
#define _NET_WM_MOVERESIZE_SIZE_KEYBOARD 9 /* size via keyboard */
|
||||
#define _NET_WM_MOVERESIZE_MOVE_KEYBOARD 10 /* move via keyboard */
|
||||
#define _NET_WM_MOVERESIZE_CANCEL 11 /* cancel operation */
|
||||
|
||||
struct xf_localmove
|
||||
{
|
||||
int windowRelativeX;
|
||||
int windowRelativeY;
|
||||
boolean inProgress;
|
||||
};
|
||||
|
||||
struct xf_window
|
||||
{
|
||||
GC gc;
|
||||
@ -41,7 +63,8 @@ struct xf_window
|
||||
boolean fullscreen;
|
||||
boolean decorations;
|
||||
rdpWindow* window;
|
||||
boolean localMoveSize;
|
||||
boolean isMapped;
|
||||
xfLocalMove localMove;
|
||||
};
|
||||
|
||||
void xf_ewmhints_init(xfInfo* xfi);
|
||||
@ -71,7 +94,8 @@ void xf_SetWindowMinMaxInfo(xfInfo* xfi, xfWindow* window, int maxWidth, int max
|
||||
int maxPosX, int maxPosY, int minTrackWidth, int minTrackHeight, int maxTrackWidth, int maxTrackHeight);
|
||||
|
||||
|
||||
void xf_StartLocalMoveSize(xfInfo* xfi, xfWindow* window, uint16 moveSizeType, int posX, int posY);
|
||||
void xf_StopLocalMoveSize(xfInfo* xfi, xfWindow* window, uint16 moveSizeType, int topLeftX, int topLeftY);
|
||||
void xf_StartLocalMoveSize(xfInfo* xfi, xfWindow* window, int direction, int windowRelativeX, int windowRelativeY);
|
||||
void xf_EndLocalMoveSize(xfInfo *xfi, xfWindow *window, boolean cancel);
|
||||
void xf_SendClientEvent(xfInfo *xfi, xfWindow* window, Atom atom, unsigned int numArgs, ...);
|
||||
|
||||
#endif /* __XF_WINDOW_H */
|
||||
|
Loading…
Reference in New Issue
Block a user