[PATCH] Create an X11 window for the client area.
Roderick Colenbrander
thunderbird2k at gmx.net
Tue Dec 18 03:22:45 CST 2007
---
dlls/winex11.drv/dce.c | 9 +++-
dlls/winex11.drv/window.c | 111 ++++++++++++++++++++++++++++++++++++++++-----
dlls/winex11.drv/x11drv.h | 3 +-
server/window.c | 5 ++-
4 files changed, 113 insertions(+), 15 deletions(-)
diff --git a/dlls/winex11.drv/dce.c b/dlls/winex11.drv/dce.c
index 11d869e..b62e44f 100644
--- a/dlls/winex11.drv/dce.c
+++ b/dlls/winex11.drv/dce.c
@@ -154,9 +154,16 @@ static void update_visible_region( struct dce *dce )
escape.gl_drawable = 0;
escape.pixmap = 0;
}
- else
+ else if(top == dce->hwnd && (flags & DCX_WINDOW))
{
escape.drawable = X11DRV_get_whole_window( top );
+ escape.fbconfig_id = 0;
+ escape.gl_drawable = 0;
+ escape.pixmap = 0;
+ }
+ else
+ {
+ escape.drawable = X11DRV_get_client_window( top );
escape.fbconfig_id = X11DRV_get_fbconfig_id( dce->hwnd );
escape.gl_drawable = X11DRV_get_gl_drawable( dce->hwnd );
escape.pixmap = X11DRV_get_gl_pixmap( dce->hwnd );
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c
index 7348f2a..efc122e 100644
--- a/dlls/winex11.drv/window.c
+++ b/dlls/winex11.drv/window.c
@@ -54,13 +54,14 @@ XContext winContext = 0;
/* X context to associate a struct x11drv_win_data to an hwnd */
static XContext win_data_context;
-static const char whole_window_prop[] = "__wine_x11_whole_window";
-static const char icon_window_prop[] = "__wine_x11_icon_window";
-static const char fbconfig_id_prop[] = "__wine_x11_fbconfig_id";
-static const char gl_drawable_prop[] = "__wine_x11_gl_drawable";
-static const char pixmap_prop[] = "__wine_x11_pixmap";
-static const char managed_prop[] = "__wine_x11_managed";
-static const char visual_id_prop[] = "__wine_x11_visual_id";
+static const char whole_window_prop[] = "__wine_x11_whole_window";
+static const char client_window_prop[] = "__wine_x11_client_window";
+static const char icon_window_prop[] = "__wine_x11_icon_window";
+static const char fbconfig_id_prop[] = "__wine_x11_fbconfig_id";
+static const char gl_drawable_prop[] = "__wine_x11_gl_drawable";
+static const char pixmap_prop[] = "__wine_x11_pixmap";
+static const char managed_prop[] = "__wine_x11_managed";
+static const char visual_id_prop[] = "__wine_x11_visual_id";
/* for XDG systray icons */
#define SYSTEM_TRAY_REQUEST_DOCK 0
@@ -252,7 +253,7 @@ BOOL X11DRV_set_win_format( HWND hwnd, XID fbconfig_id )
wine_tsx11_unlock();
- parent = data->whole_window;
+ parent = data->client_window;
next_hwnd = hwnd;
while(!parent)
{
@@ -262,7 +263,7 @@ BOOL X11DRV_set_win_format( HWND hwnd, XID fbconfig_id )
ERR("Could not find parent HWND with a drawable!\n");
return FALSE;
}
- parent = X11DRV_get_whole_window(next_hwnd);
+ parent = X11DRV_get_client_window(next_hwnd);
}
w = data->client_rect.right - data->client_rect.left;
@@ -372,7 +373,7 @@ static void update_gl_drawable(Display *display, struct x11drv_win_data *data, c
}
#endif
- parent = data->whole_window;
+ parent = data->client_window;
next_hwnd = data->hwnd;
while(!parent)
{
@@ -382,7 +383,7 @@ static void update_gl_drawable(Display *display, struct x11drv_win_data *data, c
ERR("Could not find parent HWND with a drawable!\n");
return;
}
- parent = X11DRV_get_whole_window(next_hwnd);
+ parent = X11DRV_get_client_window(next_hwnd);
}
wine_tsx11_lock();
@@ -1015,8 +1016,51 @@ void X11DRV_sync_window_position( Display *display, struct x11drv_win_data *data
DefaultScreen(display), mask, &changes );
wine_tsx11_unlock();
}
+
+ if (data->client_window)
+ {
+ int w = data->client_rect.right - data->client_rect.left;
+ int h = data->client_rect.bottom - data->client_rect.top;
+
+ TRACE("Updating client window 0x%lx to %dx%x,%dx%d\n", data->client_window,
+ data->client_rect.left, data->client_rect.top, w, h);
+
+ if(w>0 && h>0)
+ {
+ wine_tsx11_lock();
+ XMoveResizeWindow(display, data->client_window, data->client_rect.left,
+ data->client_rect.top, w, h);
+ wine_tsx11_unlock();
+ }
+ }
}
+/**********************************************************************
+ * create_client_window
+ *
+ * Create the client window for a given window
+ */
+static Window create_client_window( Display *display, struct x11drv_win_data *data)
+{
+ XSetWindowAttributes attr;
+
+ attr.event_mask = ExposureMask;
+ attr.bit_gravity = NorthWestGravity;
+ attr.backing_store = NotUseful;
+
+ wine_tsx11_lock();
+ data->client_window = XCreateWindow( display, data->whole_window, 0, 0,
+ 1, 1, 0, screen_depth,
+ InputOutput, visual,
+ CWEventMask | CWBitGravity | CWBackingStore, &attr );
+
+ XSaveContext( display, data->client_window, winContext, (char *)data->hwnd );
+ XMapWindow( display, data->client_window );
+ wine_tsx11_unlock();
+
+ SetPropA( data->hwnd, client_window_prop, (HANDLE)data->client_window );
+ return data->client_window;
+}
/**********************************************************************
* create_whole_window
@@ -1069,6 +1113,23 @@ static Window create_whole_window( Display *display, struct x11drv_win_data *dat
return data->whole_window;
}
+/***********************************************************************
+ * destroy_client_window
+ */
+static void destroy_client_window( Display *display, struct x11drv_win_data *data )
+{
+ if (!data->client_window) return;
+
+ wine_tsx11_lock();
+
+ XDeleteContext( display, data->client_window, winContext );
+ XDestroyWindow( display, data->client_window );
+ data->client_window = 0;
+ XFlush(display);
+
+ wine_tsx11_unlock();
+ RemovePropA( data->hwnd, client_window_prop );
+}
/**********************************************************************
* destroy_whole_window
@@ -1202,6 +1263,7 @@ static struct x11drv_win_data *alloc_win_data( Display *display, HWND hwnd )
{
data->hwnd = hwnd;
data->whole_window = 0;
+ data->client_window = 0;
data->icon_window = 0;
data->fbconfig_id = 0;
data->gl_drawable = 0;
@@ -1244,6 +1306,7 @@ static void get_desktop_xwin( Display *display, struct x11drv_win_data *data )
}
SERVER_END_REQ;
data->whole_window = win;
+ data->client_window = win;
if (win != root_window) X11DRV_init_desktop( win, width, height );
}
else
@@ -1256,6 +1319,8 @@ static void get_desktop_xwin( Display *display, struct x11drv_win_data *data )
SetPropA( data->hwnd, whole_window_prop, (HANDLE)root_window );
SetPropA( data->hwnd, visual_id_prop, (HANDLE)visualid );
data->whole_window = root_window;
+ data->client_window = root_window;
+
X11DRV_SetWindowPos( data->hwnd, 0, &virtual_screen_rect, &virtual_screen_rect,
SWP_NOZORDER | SWP_NOACTIVATE, NULL );
if (root_window != DefaultRootWindow( display ))
@@ -1329,6 +1394,7 @@ BOOL X11DRV_CreateWindow( HWND hwnd, CREATESTRUCTA *cs, BOOL unicode )
if (GetAncestor( hwnd, GA_PARENT ) == GetDesktopWindow())
{
if (!create_whole_window( display, data, cs->style )) goto failed;
+ if (!create_client_window( display, data )) goto failed;
}
else if (hwnd == GetDesktopWindow())
{
@@ -1497,6 +1563,18 @@ Window X11DRV_get_whole_window( HWND hwnd )
return data->whole_window;
}
+/***********************************************************************
+ * X11DRV_get_client_window
+ *
+ * Return the X window associated with the client area of a window
+ */
+Window X11DRV_get_client_window( HWND hwnd )
+{
+ struct x11drv_win_data *data = X11DRV_get_win_data( hwnd );
+
+ if (!data) return (Window)GetPropA( hwnd, client_window_prop );
+ return data->client_window;
+}
/***********************************************************************
* X11DRV_get_fbconfig_id
@@ -1569,7 +1647,15 @@ void X11DRV_SetParent( HWND hwnd, HWND parent, HWND old_parent )
if (old_parent == GetDesktopWindow())
{
/* destroy the old X windows */
- destroy_whole_window( display, data );
+
+ /* Don't destroy the X11 window twice in order to prevent a BadWindow error, if the client window is the whole window */
+ if(data->whole_window == data->client_window)
+ destroy_whole_window( display, data );
+ else
+ {
+ destroy_client_window( display, data );
+ destroy_whole_window( display, data );
+ }
destroy_icon_window( display, data );
if (data->managed)
{
@@ -1582,6 +1668,7 @@ void X11DRV_SetParent( HWND hwnd, HWND parent, HWND old_parent )
{
/* FIXME: we ignore errors since we can't really recover anyway */
create_whole_window( display, data, GetWindowLongW( hwnd, GWL_STYLE ) );
+ create_client_window( display, data );
}
}
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index 3328981..ff80e26 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -531,7 +531,6 @@ extern Visual *visual;
extern Window root_window;
extern unsigned int screen_width;
extern unsigned int screen_height;
-extern unsigned int screen_bpp;
extern unsigned int screen_depth;
extern RECT virtual_screen_rect;
extern unsigned int text_caps;
@@ -662,6 +661,7 @@ struct x11drv_win_data
{
HWND hwnd; /* hwnd that this private data belongs to */
Window whole_window; /* X window for the complete window */
+ Window client_window; /* X window for the client area of the toplevel window */
Window icon_window; /* X window for the icon */
XID fbconfig_id; /* fbconfig id for the GL drawable this hwnd uses */
Drawable gl_drawable; /* Optional GL drawable for rendering the client area */
@@ -681,6 +681,7 @@ struct x11drv_win_data
extern struct x11drv_win_data *X11DRV_get_win_data( HWND hwnd );
extern Window X11DRV_get_whole_window( HWND hwnd );
+extern Window X11DRV_get_client_window( HWND hwnd );
extern XID X11DRV_get_fbconfig_id( HWND hwnd );
extern Drawable X11DRV_get_gl_drawable( HWND hwnd );
extern Pixmap X11DRV_get_gl_pixmap( HWND hwnd );
diff --git a/server/window.c b/server/window.c
index 8cf8001..a31a717 100644
--- a/server/window.c
+++ b/server/window.c
@@ -1997,7 +1997,10 @@ DECL_HANDLER(get_visible_region)
if (data) set_reply_data_ptr( data, reply->total_size );
}
reply->top_win = top->handle;
- reply->top_rect = top->visible_rect;
+ if(top == win && (req->flags&DCX_WINDOW))
+ reply->top_rect = top->visible_rect;
+ else
+ reply->top_rect = top->client_rect;
if (!is_desktop_window(win))
{
--
1.5.3.4
--========GMX133971197970737170732--
More information about the wine-patches
mailing list