RFC: Make X11 window rect empty for WS_EX_TRANSPARENT windows

Octavian Voicu octavian.voicu at gmail.com
Sun Oct 30 18:47:03 CDT 2011


Hi,

Attached patch fixes http://bugs.winehq.org/show_bug.cgi?id=28678.

The root problem is that X11 windows cannot be made transparent (allowing
other windows to draw over them). My approach I to make the X11 window with
WS_EX_TRANSPARENT extended style have an empty region.

Obviously, this is very hacky and except for very particular cases (like
the bug I'm trying to fix) it won't work at all, so this patch is more like
a proof-of-concept than a fix. For example, window decorations aren't drawn
and not even the window can paint itself. This becomes kind of a recursive
question -- how to draw the contents of the window-less window?

Can this approach ever work? Any comments or suggestions are welcome.

Octavian
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.winehq.org/pipermail/wine-devel/attachments/20111031/e2346885/attachment.html>
-------------- next part --------------
From bf558e09e148c7873d6a5c9138577fc953649cd4 Mon Sep 17 00:00:00 2001
From: Octavian Voicu <octavian.voicu at gmail.com>
Date: Mon, 31 Oct 2011 00:57:29 +0200
Subject: winex11.drv: Make X11 window rect empty for WS_EX_TRANSPARENT windows.
Reply-To: wine-devel <wine-devel at winehq.org>

--
Fixes http://bugs.winehq.org/show_bug.cgi?id=28678.
---
 dlls/winex11.drv/event.c  |    9 +++++++++
 dlls/winex11.drv/window.c |   26 ++++++++++++++++++++++++++
 2 files changed, 35 insertions(+), 0 deletions(-)

diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c
index 00915cf..8d660c2 100644
--- a/dlls/winex11.drv/event.c
+++ b/dlls/winex11.drv/event.c
@@ -978,6 +978,7 @@ void X11DRV_ConfigureNotify( HWND hwnd, XEvent *xev )
     HWND parent;
     BOOL root_coords;
     int cx, cy, x = event->x, y = event->y;
+    DWORD ex_style;
 
     if (!hwnd) return;
     if (!(data = X11DRV_get_win_data( hwnd ))) return;
@@ -1019,6 +1020,14 @@ void X11DRV_ConfigureNotify( HWND hwnd, XEvent *xev )
     X11DRV_X_to_window_rect( data, &rect );
     if (root_coords) MapWindowPoints( 0, parent, (POINT *)&rect, 2 );
 
+    ex_style = GetWindowLongW( hwnd, GWL_EXSTYLE );
+    if (ex_style & WS_EX_TRANSPARENT)
+    {
+        FIXME("transparent window, fixing window rect\n");
+        rect.right = rect.left;
+        rect.bottom = rect.top;
+    }
+
     /* Compare what has changed */
 
     x     = rect.left;
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c
index 6a87afc..6932342 100644
--- a/dlls/winex11.drv/window.c
+++ b/dlls/winex11.drv/window.c
@@ -2021,6 +2021,7 @@ struct x11drv_win_data *X11DRV_create_win_data( HWND hwnd )
     Display *display;
     struct x11drv_win_data *data;
     HWND parent;
+    DWORD ex_style;
 
     if (!(parent = GetAncestor( hwnd, GA_PARENT ))) return NULL;  /* desktop */
 
@@ -2032,9 +2033,21 @@ struct x11drv_win_data *X11DRV_create_win_data( HWND hwnd )
 
     GetWindowRect( hwnd, &data->window_rect );
     MapWindowPoints( 0, parent, (POINT *)&data->window_rect, 2 );
+    ex_style = GetWindowLongW( hwnd, GWL_EXSTYLE );
+    if (ex_style & WS_EX_TRANSPARENT)
+    {
+        FIXME("transparent window, fixing window rect\n");
+        data->window_rect.right = data->window_rect.left;
+        data->window_rect.bottom = data->window_rect.top;
+    }
     data->whole_rect = data->window_rect;
     GetClientRect( hwnd, &data->client_rect );
     MapWindowPoints( hwnd, parent, (POINT *)&data->client_rect, 2 );
+    if (ex_style & WS_EX_TRANSPARENT)
+    {
+        data->client_rect.right = data->client_rect.left;
+        data->client_rect.bottom = data->client_rect.top;
+    }
 
     if (parent == GetDesktopWindow())
     {
@@ -2456,6 +2469,7 @@ void CDECL X11DRV_WindowPosChanged( HWND hwnd, HWND insert_after, UINT swp_flags
     DWORD new_style = GetWindowLongW( hwnd, GWL_STYLE );
     RECT old_window_rect, old_whole_rect, old_client_rect;
     int event_type;
+    DWORD ex_style;
 
     if (!data) return;
 
@@ -2472,6 +2486,18 @@ void CDECL X11DRV_WindowPosChanged( HWND hwnd, HWND insert_after, UINT swp_flags
     TRACE( "win %p window %s client %s style %08x flags %08x\n",
            hwnd, wine_dbgstr_rect(rectWindow), wine_dbgstr_rect(rectClient), new_style, swp_flags );
 
+    ex_style = GetWindowLongW( hwnd, GWL_EXSTYLE );
+    if (ex_style & WS_EX_TRANSPARENT)
+    {
+        FIXME("transparent window, fixing window rect\n");
+        data->window_rect.right = data->window_rect.left;
+        data->window_rect.bottom = data->window_rect.top;
+        data->whole_rect.right = data->whole_rect.left;
+        data->whole_rect.bottom = data->whole_rect.top;
+        data->client_rect.right = data->client_rect.left;
+        data->client_rect.bottom = data->client_rect.top;
+    }
+
     if (!IsRectEmpty( &valid_rects[0] ))
     {
         int x_offset = old_whole_rect.left - data->whole_rect.left;
-- 
1.7.4.1


More information about the wine-devel mailing list