[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