(X11 Series 2/3) Fix handling of non-default visuals

Michael Karcher wine at mkarcher.dialup.fu-berlin.de
Sun Mar 16 15:08:33 CDT 2008


This patch fixes wine with respect to a non-default visual for Wine
windows. The issue is that for an X11 window depth, colormap and visual
have to match, otherwise a BadMatch error is raised. Furthermore, GCs
are specific to one depth, so a GC created for the root window does not
work with windows of a different depth. This is the reason for the
template window I create on non-default visuals. Of course, the Windows
concept of having one GC that works everywhere on the screen breaks in
the case of non-default visuals. I don't see any way to prevent that.

This patch has not yet been thoroughly tested. But it makes wine
applications start if I force ScreenDepth to 32 (thus using a ARGB
visual instead of the 24 bit RGB visual). Using the ARGB visual, I
encountered another bug, namely invisible text. The next patch in this
series fixes it.

>From d6e88b4e9981b5ae6bb6b2f33530b8bea88745e1 Mon Sep 17 00:00:00 2001
From: Michael Karcher <wine at mkarcher.dialup.fu-berlin.de>
Date: Sun, 16 Mar 2008 20:41:57 +0100
Subject: [PATCH] Fixed handling of non-default visuals, to prevent BadMatch
 errors from X. This code is more like patched-to-work-at-least-a-bit
 than complete worked through. Be careful!

---
 dlls/winex11.drv/clipboard.c |    2 +-
 dlls/winex11.drv/init.c      |   28 +++++++++++++++++++++++++++-
 dlls/winex11.drv/window.c    |   12 +++++++++---
 dlls/winex11.drv/x11drv.h    |    2 ++
 4 files changed, 39 insertions(+), 5 deletions(-)

diff --git a/dlls/winex11.drv/clipboard.c b/dlls/winex11.drv/clipboard.c
index 5e85998..6b719a6 100644
--- a/dlls/winex11.drv/clipboard.c
+++ b/dlls/winex11.drv/clipboard.c
@@ -326,7 +326,7 @@ static Window thread_selection_wnd(void)
                        ButtonPressMask | ButtonReleaseMask | EnterWindowMask);
 
         wine_tsx11_lock();
-        w = XCreateWindow(thread_display(), root_window, 0, 0, 1, 1, 0, screen_depth,
+        w = XCreateWindow(thread_display(), root_window, 0, 0, 1, 1, 0, CopyFromParent,
                           InputOutput, CopyFromParent, CWEventMask, &attr);
         wine_tsx11_unlock();
 
diff --git a/dlls/winex11.drv/init.c b/dlls/winex11.drv/init.c
index 5e549b9..6c49284 100644
--- a/dlls/winex11.drv/init.c
+++ b/dlls/winex11.drv/init.c
@@ -33,6 +33,7 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
 
+Window template_window;
 Display *gdi_display;  /* display to use for all GDI functions */
 
 /* a few dynamic device caps */
@@ -77,6 +78,29 @@ static DWORD get_dpi( void )
     return dpi;
 }
 
+static void init_template_window(void)
+{
+    if( screen_depth != DefaultDepthOfScreen( screen ))
+    {
+        XSetWindowAttributes att;
+        att.colormap = X11DRV_PALETTE_PaletteXColormap;
+        att.border_pixel = BlackPixel( gdi_display, XScreenNumberOfScreen(screen) );
+        template_window = XCreateWindow( gdi_display, root_window, 0, 0, 1, 1, 0, 
+                                         screen_depth, InputOutput, visual, 
+                                         CWColormap | CWBorderPixel, &att );
+   }
+   else
+   {
+        template_window = root_window;
+   }
+}
+
+static void remove_template_window(void)
+{
+    if(template_window != root_window)
+        XDestroyWindow( gdi_display, template_window );
+}
+
 /**********************************************************************
  *	     device_init
  *
@@ -94,6 +118,7 @@ static void device_init(void)
 
     palette_size = X11DRV_PALETTE_Init();
 
+    init_template_window();  
     X11DRV_BITMAP_Init();
 
     /* Initialize device caps */
@@ -110,6 +135,7 @@ static void device_init(void)
  */
 void X11DRV_GDI_Finalize(void)
 {
+    remove_template_window();
     X11DRV_PALETTE_Cleanup();
     /* don't bother to close the display, it often triggers X bugs */
     /* XCloseDisplay( gdi_display ); */
@@ -144,7 +170,7 @@ BOOL X11DRV_CreateDC( HDC hdc, X11DRV_PDEVICE **pdev, LPCWSTR driver, LPCWSTR de
     else
     {
         physDev->bitmap    = NULL;
-        physDev->drawable  = root_window;
+        physDev->drawable  = template_window;
         physDev->depth     = screen_depth;
         physDev->drawable_rect = virtual_screen_rect;
         SetRect( &physDev->dc_rect, 0, 0, virtual_screen_rect.right - virtual_screen_rect.left,
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c
index 2d94455..ef526e1 100644
--- a/dlls/winex11.drv/window.c
+++ b/dlls/winex11.drv/window.c
@@ -590,6 +590,7 @@ static Window create_icon_window( Display *display, struct x11drv_win_data *data
     attr.bit_gravity = NorthWestGravity;
     attr.backing_store = NotUseful/*WhenMapped*/;
     attr.colormap      = X11DRV_PALETTE_PaletteXColormap; /* Needed due to our visual */
+    attr.border_pixel  = BlackPixel ( display, XScreenNumberOfScreen(screen) ); /* Needed due to our visual */
 
     wine_tsx11_lock();
     data->icon_window = XCreateWindow( display, root_window, 0, 0,
@@ -597,7 +598,7 @@ static Window create_icon_window( Display *display, struct x11drv_win_data *data
                                        GetSystemMetrics( SM_CYICON ),
                                        0, screen_depth,
                                        InputOutput, visual,
-                                       CWEventMask | CWBitGravity | CWBackingStore | CWColormap, &attr );
+                                       CWEventMask | CWBitGravity | CWBackingStore | CWColormap | CWBorderPixel, &attr );
     XSaveContext( display, data->icon_window, winContext, (char *)data->hwnd );
     wine_tsx11_unlock();
 
@@ -1155,11 +1156,16 @@ static Window create_whole_window( Display *display, struct x11drv_win_data *dat
     wine_tsx11_lock();
 
     data->whole_rect = data->window_rect;
+    /* HACK: Set CWBorderPixel to prevent a BadMatch on the BorderPixmap
+       when creating windows in a different visual than the root window.
+       
+       As the border width is zero, the border itself is never used */
+    attr.border_pixel = BlackPixel( display, DefaultScreen(display) );
     data->whole_window = XCreateWindow( display, root_window,
                                         data->window_rect.left - virtual_screen_rect.left,
                                         data->window_rect.top - virtual_screen_rect.top,
                                         cx, cy, 0, screen_depth, InputOutput,
-                                        visual, mask, &attr );
+                                        visual, mask | CWBorderPixel, &attr );
 
     if (data->whole_window) XSaveContext( display, data->whole_window, winContext, (char *)data->hwnd );
     wine_tsx11_unlock();
@@ -1555,7 +1561,7 @@ void X11DRV_ReleaseDC( HWND hwnd, HDC hdc )
     struct x11drv_escape_set_drawable escape;
 
     escape.code = X11DRV_SET_DRAWABLE;
-    escape.drawable = root_window;
+    escape.drawable = template_window;
     escape.mode = IncludeInferiors;
     escape.drawable_rect = virtual_screen_rect;
     SetRect( &escape.dc_rect, 0, 0, virtual_screen_rect.right - virtual_screen_rect.left,
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index 52670e8..04da1c9 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -520,8 +520,10 @@ static inline struct x11drv_thread_data *x11drv_thread_data(void)
 
 static inline Display *thread_display(void) { return x11drv_thread_data()->display; }
 
+extern Screen *screen;
 extern Visual *visual;
 extern Window root_window;
+extern Window template_window;
 extern unsigned int screen_width;
 extern unsigned int screen_height;
 extern unsigned int screen_bpp;
-- 
1.5.4.3





More information about the wine-patches mailing list