xfreerdp: add parent-child relationship for RAIL windows.

This commit is contained in:
roman-b 2011-08-25 00:16:57 +03:00
parent e5fb626d75
commit 6365db7be6
6 changed files with 161 additions and 43 deletions

View File

@ -458,7 +458,7 @@ boolean xf_event_process(freerdp* instance, XEvent* event)
#if 1
if (event->type != MotionNotify)
printf("X11 %s Event\n", X11_EVENT_STRINGS[event->type]);
printf("X11 %s Event: wnd=0x%X\n", X11_EVENT_STRINGS[event->type], (uint32)event->xany.window);
#endif
switch (event->type)

View File

@ -74,16 +74,37 @@ void xf_rail_CreateWindow(rdpRail* rail, rdpWindow* window)
{
xfInfo* xfi;
xfWindow* xfw;
xfWindow* xfparent;
xfi = (xfInfo*) rail->extra;
xfw = xf_CreateWindow((xfInfo*) rail->extra,
printf("xf_rail_CreateWindow: wid=0x%X own_wid=0x%X\n",
window->windowId, window->ownerWindowId);
// When ownerWindowId is equal to 0, it means that
// it is a main application window.
// For main application windows screen window is parent. (0 in Win32)
xfparent = NULL;
if (window->ownerWindowId != 0)
{
rdpWindow* p = NULL;
p = window_list_get_by_id(xfi->rail->list, window->ownerWindowId);
if (p != NULL)
xfparent = (xfWindow *)p->extra;
}
xfw = xf_CreateWindow((xfInfo*) rail->extra, xfparent,
window->windowOffsetX, window->windowOffsetY,
window->windowWidth, window->windowHeight,
window->windowId);
XStoreName(xfi->display, xfw->handle, window->title);
xf_SetWindowStyle(xfi, xfw, window->style, window->extendedStyle);
window->extra = (void*) xfw;
window->extraId = (void*) xfw->handle;
}
@ -276,7 +297,7 @@ void xf_process_rail_server_minmaxinfo_event(xfInfo* xfi, rdpChanMan* chanman, R
"maxWidth=%d maxHeight=%d maxPosX=%d maxPosY=%d "
"minTrackWidth=%d minTrackHeight=%d maxTrackWidth=%d maxTrackHeight=%d\n",
minmax->windowId, minmax->maxWidth, minmax->maxHeight,
minmax->maxPosX, minmax->maxPosY,
(sint16)minmax->maxPosX, (sint16)minmax->maxPosY,
minmax->minTrackWidth, minmax->minTrackHeight,
minmax->maxTrackWidth, minmax->maxTrackHeight);
}
@ -304,7 +325,7 @@ void xf_process_rail_server_localmovesize_event(xfInfo* xfi, rdpChanMan* chanman
printf("Server Local MoveSize PDU: windowId=0x%X "
"isMoveSizeStart=%d moveSizeType=%s PosX=%d PosY=%d\n",
movesize->windowId, movesize->isMoveSizeStart,
movetype_names[movesize->moveSizeType], movesize->posX, movesize->posY);
movetype_names[movesize->moveSizeType], (sint16)movesize->posX, (sint16)movesize->posY);
}
void xf_process_rail_appid_resp_event(xfInfo* xfi, rdpChanMan* chanman, RDP_EVENT* event)

View File

@ -41,6 +41,9 @@ struct _PropMotifWmHints
};
typedef struct _PropMotifWmHints PropMotifWmHints;
void xf_RefrenceWindow(xfInfo* xfi, xfWindow* window);
void xf_DerefrenceWindow(xfInfo* xfi, xfWindow* window);
void xf_SendClientMessage(xfInfo* xfi, xfWindow* window, Atom atom, long msg, long d1, long d2, long d3)
{
XEvent xevent;
@ -159,6 +162,43 @@ void xf_SetWindowDecorations(xfInfo* xfi, xfWindow* window, boolean show)
window->decorations = show;
}
void xf_SetWindowStyle(xfInfo* xfi, xfWindow* window, uint32 style, uint32 ex_style)
{
Atom window_type;
window_type = xfi->_NET_WM_WINDOW_TYPE_NORMAL;
if (((style & WS_POPUP) !=0) ||
((style & WS_DLGFRAME) != 0) ||
((ex_style & WS_EX_DLGMODALFRAME) != 0)
)
{
window_type = xfi->_NET_WM_WINDOW_TYPE_DIALOG;
}
else if ((ex_style & WS_EX_TOOLWINDOW) != 0)
{
window_type = xfi->_NET_WM_WINDOW_TYPE_UTILITY;
}
XChangeProperty(xfi->display, window->handle, xfi->_NET_WM_WINDOW_TYPE,
xfi->_NET_WM_WINDOW_TYPE, 32, PropModeReplace, (unsigned char*)&window_type, 1);
}
void xf_SetWindowChildState(xfInfo* xfi, xfWindow* window)
{
Atom window_state[2];
if (window->parent != NULL)
{
window_state[0] = xfi->_NET_WM_STATE_SKIP_PAGER;
window_state[1] = xfi->_NET_WM_STATE_SKIP_TASKBAR;
XChangeProperty(xfi->display, window->handle, xfi->_NET_WM_STATE,
xfi->_NET_WM_STATE, 32, PropModeReplace, (unsigned char*)&window_state, 2);
}
}
xfWindow* xf_CreateDesktopWindow(xfInfo* xfi, char* name, int width, int height)
{
xfWindow* window;
@ -232,7 +272,7 @@ void xf_FixWindowCoordinates(int* x, int* y, int* width, int* height)
char rail_window_class[] = "RAIL:00000000";
xfWindow* xf_CreateWindow(xfInfo* xfi, int x, int y, int width, int height, uint32 id)
xfWindow* xf_CreateWindow(xfInfo* xfi, xfWindow* parent, int x, int y, int width, int height, uint32 id)
{
xfWindow* window;
@ -254,18 +294,36 @@ xfWindow* xf_CreateWindow(xfInfo* xfi, int x, int y, int width, int height, uint
{
XGCValues gcv;
int input_mask;
XSizeHints* size_hints;
XClassHint* class_hints;
Window parent_handle;
int lx;
int ly;
window->ref_count = 0;
window->decorations = False;
window->fullscreen = False;
window->parent = parent;
window->handle = XCreateWindow(xfi->display, RootWindowOfScreen(xfi->screen),
x, y, window->width, window->height, 0, xfi->depth, InputOutput, xfi->visual,
lx = x;
ly = y;
parent_handle = RootWindowOfScreen(xfi->screen);
if (window->parent != NULL)
{
lx = x - window->parent->left;
ly = y - window->parent->top;
parent_handle = parent->handle;
}
window->handle = XCreateWindow(xfi->display, parent_handle,
lx, ly, window->width, window->height, 0, xfi->depth, InputOutput, xfi->visual,
CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
CWBorderPixel, &xfi->attribs);
xf_RefrenceWindow(xfi, window);
xf_RefrenceWindow(xfi, window->parent);
xf_SetWindowDecorations(xfi, window, window->decorations);
//xf_SetWindowChildState(xfi, window);
class_hints = XAllocClassHint();
@ -281,17 +339,6 @@ xfWindow* xf_CreateWindow(xfInfo* xfi, int x, int y, int width, int height, uint
xfree(class);
}
size_hints = XAllocSizeHints();
if (size_hints)
{
size_hints->flags = PMinSize | PMaxSize;
size_hints->min_width = size_hints->max_width = window->width;
size_hints->min_height = size_hints->max_height = window->height;
XSetWMNormalHints(xfi->display, window->handle, size_hints);
XFree(size_hints);
}
input_mask =
KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
VisibilityChangeMask | FocusChangeMask | StructureNotifyMask |
@ -304,6 +351,10 @@ xfWindow* xf_CreateWindow(xfInfo* xfi, int x, int y, int width, int height, uint
window->gc = XCreateGC(xfi->display, window->handle, GCGraphicsExposures, &gcv);
window->surface = XCreatePixmap(xfi->display, window->handle, window->width, window->height, xfi->depth);
printf("xf_CreateWindow: h=0x%X p=0x%X x=%d y=%d w=%d h=%d\n", (uint32)window->handle,
(window->parent != NULL) ? (uint32)window->parent->handle : 0,
x, y, width, height);
xf_MoveWindow(xfi, window, x, y, width, height);
}
@ -313,30 +364,32 @@ xfWindow* xf_CreateWindow(xfInfo* xfi, int x, int y, int width, int height, uint
void xf_MoveWindow(xfInfo* xfi, xfWindow* window, int x, int y, int width, int height)
{
Pixmap surface;
XSizeHints* size_hints;
int lx = x;
int ly = y;
if ((width * height) < 1)
return;
xf_FixWindowCoordinates(&x, &y, &width, &height);
printf("xf_MoveWindow: BEFORE correctness h=0x%X x=%d y=%d w=%d h=%d\n", (uint32)window->handle,
x, y, width, height);
size_hints = XAllocSizeHints();
xf_FixWindowCoordinates(&x, &y, &width, &height);
if (size_hints)
{
size_hints->flags = PMinSize | PMaxSize;
size_hints->min_width = size_hints->max_width = width;
size_hints->min_height = size_hints->max_height = height;
XSetWMNormalHints(xfi->display, window->handle, size_hints);
XFree(size_hints);
}
if (window->parent != NULL)
{
lx = x - window->parent->left;
ly = y - window->parent->top;
}
printf("xf_MoveWindow: AFTER correctness h=0x%X x=%d y=%d lx=%d ly=%d w=%d h=%d \n", (uint32)window->handle,
x, y, lx, ly, width, height);
if (window->width == width && window->height == height)
XMoveWindow(xfi->display, window->handle, x, y);
XMoveWindow(xfi->display, window->handle, lx, ly);
else if (window->left == x && window->top == y)
XResizeWindow(xfi->display, window->handle, width, height);
else
XMoveResizeWindow(xfi->display, window->handle, x, y, width, height);
XMoveResizeWindow(xfi->display, window->handle, lx, ly, width, height);
surface = XCreatePixmap(xfi->display, window->handle, width, height, xfi->depth);
XCopyArea(xfi->display, surface, window->surface, window->gc, 0, 0, window->width, window->height, 0, 0);
@ -432,16 +485,42 @@ void xf_SetWindowVisibilityRects(xfInfo* xfi, xfWindow* window, RECTANGLE_16* re
xfree(xrects);
}
void xf_RefrenceWindow(xfInfo* xfi, xfWindow* window)
{
if (window == NULL) return;
window->ref_count++;
}
void xf_DerefrenceWindow(xfInfo* xfi, xfWindow* window)
{
if (window == NULL) return;
window->ref_count--;
if (window->ref_count == 0)
{
printf("xf_DerefrenceWindow: destroying h=0x%X p=0x%X\n", (uint32)window->handle,
(window->parent != NULL) ? (uint32)window->parent->handle : 0);
if (window->gc)
XFreeGC(xfi->display, window->gc);
if (window->surface)
XFreePixmap(xfi->display, window->surface);
if (window->handle)
{
XUnmapWindow(xfi->display, window->handle);
XDestroyWindow(xfi->display, window->handle);
}
xfree(window);
}
}
void xf_DestroyWindow(xfInfo* xfi, xfWindow* window)
{
if (window->gc)
XFreeGC(xfi->display, window->gc);
if (window->surface)
XFreePixmap(xfi->display, window->surface);
if (window->handle)
{
XUnmapWindow(xfi->display, window->handle);
XDestroyWindow(xfi->display, window->handle);
}
xfree(window);
xfWindow* parent = window->parent;
printf("xf_DestroyWindow: h=0x%X p=0x%X\n", (uint32)window->handle,
(window->parent != NULL) ? (uint32)window->parent->handle : 0);
xf_DerefrenceWindow(xfi, window);
xf_DerefrenceWindow(xfi, parent);
}

View File

@ -41,6 +41,8 @@ struct xf_window
Pixmap surface;
boolean fullscreen;
boolean decorations;
xfWindow* parent;
size_t ref_count;
};
void xf_ewmhints_init(xfInfo* xfi);
@ -53,11 +55,12 @@ void xf_SetWindowDecorations(xfInfo* xfi, xfWindow* window, boolean show);
xfWindow* xf_CreateDesktopWindow(xfInfo* xfi, char* name, int width, int height);
xfWindow* xf_CreateWindow(xfInfo* xfi, int x, int y, int width, int height, uint32 id);
xfWindow* xf_CreateWindow(xfInfo* xfi, xfWindow* parent, int x, int y, int width, int height, uint32 id);
void xf_MoveWindow(xfInfo* xfi, xfWindow* window, int x, int y, int width, int height);
void xf_ShowWindow(xfInfo* xfi, xfWindow* window, uint8 state);
void xf_SetWindowIcon(xfInfo* xfi, xfWindow* window, rdpIcon* icon);
void xf_SetWindowVisibilityRects(xfInfo* xfi, xfWindow* window, RECTANGLE_16* rects, int nrects);
void xf_SetWindowStyle(xfInfo* xfi, xfWindow* window, uint32 style, uint32 ex_style);
void xf_DestroyWindow(xfInfo* xfi, xfWindow* window);
#endif /* __XF_WINDOW_H */

View File

@ -266,6 +266,13 @@ boolean xf_pre_connect(freerdp* instance)
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);
xf_kbd_init(xfi);

View File

@ -86,8 +86,16 @@ struct xf_info
Atom _MOTIF_WM_HINTS;
Atom _NET_CURRENT_DESKTOP;
Atom _NET_WORKAREA;
Atom _NET_WM_STATE;
Atom _NET_WM_STATE_FULLSCREEN;
Atom _NET_WM_STATE_SKIP_TASKBAR;
Atom _NET_WM_STATE_SKIP_PAGER;
Atom _NET_WM_WINDOW_TYPE;
Atom _NET_WM_WINDOW_TYPE_NORMAL;
Atom _NET_WM_WINDOW_TYPE_DIALOG;
Atom _NET_WM_WINDOW_TYPE_UTILITY;
};
void xf_toggle_fullscreen(xfInfo* xfi);