From 38d9b194e83b02f56d734da88396ac06ddb7af1f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gabriel=20Iv=C4=83ncescu?= <gabrielopcode@gmail.com>
Date: Mon, 24 Dec 2018 14:26:57 +0200
Subject: [PATCH] winex11.drv/window: Query the X server for the actual rect of
 the window before unmapping it
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Some applications control their own position when they are being moved. This
can become out of sync with the X server because certain WMs interfere with
this on purpose.

Thus we shouldn't just rely on our window rect when deciding whether to unmap
a window (if it's out of the screen), but query the X server in this case
as the last resort to make sure it really is outside and should be unmapped.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=15346
Signed-off-by: Gabriel Ivăncescu <gabrielopcode@gmail.com>
---
 dlls/winex11.drv/window.c | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c
index 97dee52..7f436ac 100644
--- a/dlls/winex11.drv/window.c
+++ b/dlls/winex11.drv/window.c
@@ -196,6 +196,25 @@ static BOOL has_owned_popups( HWND hwnd )
     return result.found;
 }
 
+static BOOL is_actual_window_rect_mapped(const struct x11drv_win_data *data)
+{
+    XWindowAttributes attr;
+    Window child;
+    RECT rect;
+    POINT pt;
+    int x, y;
+
+    /* Query the X server for the actual position of the window,
+       as some WMs tend to mess with it, so we need to make sure
+       we aren't unmapping the window wrongly with a bogus rect */
+    XTranslateCoordinates(data->display, data->whole_window, root_window, 0, 0, &x, &y, &child);
+    XGetWindowAttributes(data->display, data->whole_window, &attr);
+
+    pt = root_to_virtual_screen(x - attr.x, y - attr.y);
+    SetRect(&rect, pt.x, pt.y, pt.x + attr.width, pt.y + attr.height);
+    return is_window_rect_mapped(&rect);
+}
+
 
 /***********************************************************************
  *              alloc_win_data
@@ -2400,7 +2419,8 @@ void CDECL X11DRV_WindowPosChanged( HWND hwnd, HWND insert_after, UINT swp_flags
     {
         if (((swp_flags & SWP_HIDEWINDOW) && !(new_style & WS_VISIBLE)) ||
             (!event_type && !(new_style & WS_MINIMIZE) &&
-             !is_window_rect_mapped( rectWindow ) && is_window_rect_mapped( &old_window_rect )))
+             !is_window_rect_mapped( rectWindow ) && is_window_rect_mapped( &old_window_rect ) &&
+             !is_actual_window_rect_mapped( data )))
         {
             release_win_data( data );
             unmap_window( hwnd );
-- 
1.9.1

