Programatically minimising window gets incorrect results.

Mike McCormack mike at codeweavers.com
Tue May 16 04:15:20 CDT 2006


Troy Rollo wrote:
> The attached C sample demonstrates two problems with using 
> ShowWindow(hwnd,SW_SHOWMINIMIZED) to minimise a top level window. The tests 
> were done in KDE, but the second problem has been confirmed in Gnome and I 
> suspect the first also occurs there.

The problem is that we should ask the Window manager to minimize us. 
There's a hack in CrossOver that "fixes" it, which I've attached.  If 
you're in a good mood, try getting it accepted into Wine. :)

I haven't tested that this patch works as is... however it should be 
complete, and at least compiles.

Mike
-------------- next part --------------
diff --git a/dlls/x11drv/winpos.c b/dlls/x11drv/winpos.c
index 5fdde83..33370df 100644
--- a/dlls/x11drv/winpos.c
+++ b/dlls/x11drv/winpos.c
@@ -923,12 +923,42 @@ UINT WINPOS_MinMaximize( HWND hwnd, UINT
     return swpFlags;
 }
 
+/***********************************************************************
+ *             X11DRV_WMMinimizeWindow
+ *
+ *  See the ICCCM section 4.1.4. Changing Window State for more details.
+ *  http://tronche.com/gui/x/icccm/sec-4.html#s-4.1.4
+ */
+static BOOL X11DRV_WMMinimizeWindow(HWND hwnd)
+{
+    XEvent xev;
+
+    TRACE("%p\n", hwnd);
+
+    wine_tsx11_lock();
+
+    xev.xclient.type = ClientMessage;
+    xev.xclient.window = X11DRV_get_whole_window( hwnd );
+    xev.xclient.message_type = x11drv_atom(WM_CHANGE_STATE);
+    xev.xclient.serial = 0;
+    xev.xclient.display = thread_display();
+    xev.xclient.send_event = True;
+    xev.xclient.format = 32;
+    xev.xclient.data.l[0] = IconicState;
+    xev.xclient.data.l[2] = 0;
+    XSendEvent(thread_display(), root_window, False, SubstructureNotifyMask, &xev);
+    
+    wine_tsx11_unlock();
+
+    return TRUE;
+}
 
 /***********************************************************************
  *              ShowWindow   (X11DRV.@)
  */
 BOOL X11DRV_ShowWindow( HWND hwnd, INT cmd )
 {
+    Display *display = thread_display();
     WND *wndPtr;
     HWND parent;
     LONG style = GetWindowLongW( hwnd, GWL_STYLE );
@@ -957,6 +987,19 @@ BOOL X11DRV_ShowWindow( HWND hwnd, INT c
             swp |= SWP_SHOWWINDOW;
             /* fall through */
 	case SW_MINIMIZE:
+
+            /* handle minimize a different way */
+            if ((root_window == DefaultRootWindow(display)) &&
+                 GetAncestor(hwnd,GA_PARENT) == GetDesktopWindow())
+            {
+                if( !(style & WS_MINIMIZE) )
+                {
+                    X11DRV_WMMinimizeWindow( hwnd );
+                    WIN_SetStyle( hwnd, WS_MAXIMIZE, WS_MINIMIZE );
+                }
+                return wasVisible;
+            }
+
             swp |= SWP_FRAMECHANGED;
             if( !(style & WS_MINIMIZE) )
 		 swp |= WINPOS_MinMaximize( hwnd, SW_MINIMIZE, &newPos );
diff --git a/dlls/x11drv/x11drv.h b/dlls/x11drv/x11drv.h
index d259c86..9e8c3d9 100644
--- a/dlls/x11drv/x11drv.h
+++ b/dlls/x11drv/x11drv.h
@@ -561,6 +561,7 @@ enum x11drv_atoms
     XATOM_WM_PROTOCOLS,
     XATOM_WM_DELETE_WINDOW,
     XATOM_WM_TAKE_FOCUS,
+    XATOM_WM_CHANGE_STATE,
     XATOM_KWM_DOCKWINDOW,
     XATOM_DndProtocol,
     XATOM_DndSelection,
diff --git a/dlls/x11drv/x11drv_main.c b/dlls/x11drv/x11drv_main.c
index f0269a9..322ffd7 100644
--- a/dlls/x11drv/x11drv_main.c
+++ b/dlls/x11drv/x11drv_main.c
@@ -123,6 +123,7 @@ static const char * const atom_names[NB_
     "WM_PROTOCOLS",
     "WM_DELETE_WINDOW",
     "WM_TAKE_FOCUS",
+    "WM_CHANGE_STATE",
     "KWM_DOCKWINDOW",
     "DndProtocol",
     "DndSelection",


More information about the wine-devel mailing list