Do not remove focus from a hidden window, remove it in DestroyWindow()

Dmitry Timoshkov dmitry at baikal.ru
Sat May 1 09:42:20 CDT 2004


Hello,

I was researching why a maximized window sometimes has wrong extents
in its WND structure while X dimensions are slightly different. An idea
was that at the maximization time a window doesn't receive WM_NCCALCSIZE
message. While looking at it I decided to fix some problems preventing
my further progress.

Recent tests confirm that a hidden window can have an input focus, and
the message test shows that a focus should be moved out of a window
being destroyed.

This patch and a following one reduce number of message test failures
under Wine from 38 to 29.

Changelog:
    Dmitry Timoshkov <dmitry at codeweavers.com>
    Do not remove focus from a hidden window, remove it in DestroyWindow().
    It's a SetWindowPos responsibility to activate another window if
    a window is being hidden.

diff -u cvs/hq/wine/dlls/user/tests/msg.c wine/dlls/user/tests/msg.c
--- cvs/hq/wine/dlls/user/tests/msg.c	2004-05-01 18:19:05.000000000 +0900
+++ wine/dlls/user/tests/msg.c	2004-05-01 22:55:37.000000000 +0900
@@ -88,7 +88,7 @@ static const struct message WmShowOverla
     { WM_MOVE, sent },
     { 0 }
 };
-/* DestroyWindow (for overlapped window) (32) */
+/* DestroyWindow (for visible overlapped window) (32) */
 static const struct message WmDestroyOverlappedSeq[] = {
     { HCBT_DESTROYWND, hook },
     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
@@ -190,7 +190,7 @@ static const struct message WmShowChildS
     { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
     { 0 }
 };
-/* DestroyWindow (for child window) */
+/* DestroyWindow (for visible child window) */
 static const struct message WmDestroyChildSeq[] = {
     { HCBT_DESTROYWND, hook },
     { WM_PARENTNOTIFY, sent|parent|wparam, WM_DESTROY },
@@ -596,6 +596,8 @@ static void test_messages(void)
     /* test WM_SETREDRAW on a visible top level window */
     test_WM_SETREDRAW(hwnd);
 
+    ok(IsWindowVisible(hwnd), "overlapped window should be visible at this point\n");
+
     DestroyWindow(hwnd);
     ok_sequence(WmDestroyOverlappedSeq, "DestroyWindow:overlapped");
 
@@ -640,6 +642,8 @@ static void test_messages(void)
     MoveWindow(hchild, 10, 10, 20, 20, TRUE);
     ok_sequence(WmResizingChildWithMoveWindowSeq, "MoveWindow:child");
 
+    ok(IsWindowVisible(hchild), "child should be visible at this point\n");
+
     DestroyWindow(hchild);
     ok_sequence(WmDestroyChildSeq, "DestroyWindow:child");
     DestroyWindow(hchild2);
diff -u cvs/hq/wine/dlls/x11drv/winpos.c wine/dlls/x11drv/winpos.c
--- cvs/hq/wine/dlls/x11drv/winpos.c	2004-05-01 18:19:06.000000000 +0900
+++ wine/dlls/x11drv/winpos.c	2004-05-01 22:58:56.000000000 +0900
@@ -1099,6 +1099,16 @@ BOOL X11DRV_SetWindowPos( WINDOWPOS *win
         SendMessageA( winpos->hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)winpos );
         /* WM_WINDOWPOSCHANGED is send even if SWP_NOSENDCHANGING is set */
 
+    if (winpos->flags & SWP_HIDEWINDOW)
+    {
+        /* FIXME: This will cause the window to be activated irrespective
+         * of whether it is owned by the same thread. Has to be done
+         * asynchronously.
+         */
+        if (winpos->hwnd == GetActiveWindow())
+            WINPOS_ActivateOtherWindow(winpos->hwnd);
+    }
+
     return TRUE;
 }
 
@@ -1278,7 +1288,7 @@ BOOL X11DRV_ShowWindow( HWND hwnd, INT c
 
     TRACE("hwnd=%p, cmd=%d\n", hwnd, cmd);
 
-    wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
+    wasVisible = IsWindowVisible(hwnd);
 
     switch(cmd)
     {
@@ -1352,27 +1362,7 @@ BOOL X11DRV_ShowWindow( HWND hwnd, INT c
 
     SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top,
                   newPos.right, newPos.bottom, LOWORD(swp) );
-    if (cmd == SW_HIDE)
-    {
-        HWND hFocus;
 
-        /* FIXME: This will cause the window to be activated irrespective
-         * of whether it is owned by the same thread. Has to be done
-         * asynchronously.
-         */
-
-        if (hwnd == GetActiveWindow())
-            WINPOS_ActivateOtherWindow(hwnd);
-
-        /* Revert focus to parent */
-        hFocus = GetFocus();
-        if (hwnd == hFocus || IsChild(hwnd, hFocus))
-        {
-            HWND parent = GetAncestor(hwnd, GA_PARENT);
-            if (parent == GetDesktopWindow()) parent = 0;
-            SetFocus(parent);
-        }
-    }
     if (!IsWindow( hwnd )) goto END;
     else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( hwnd, TRUE );
 
diff -u cvs/hq/wine/windows/win.c wine/windows/win.c
--- cvs/hq/wine/windows/win.c	2004-04-03 12:30:57.000000000 +0900
+++ wine/windows/win.c	2004-05-01 23:14:52.000000000 +0900
@@ -1468,6 +1468,7 @@ static void WIN_SendDestroyMsg( HWND hwn
  */
 BOOL WINAPI DestroyWindow( HWND hwnd )
 {
+    HWND hFocus;
     BOOL is_child;
 
     if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
@@ -1505,10 +1506,6 @@ BOOL WINAPI DestroyWindow( HWND hwnd )
 
       /* Hide the window */
 
-    if (!ShowWindow( hwnd, SW_HIDE ))
-    {
-        if (hwnd == GetActiveWindow()) WINPOS_ActivateOtherWindow( hwnd );
-    }
     if (!IsWindow(hwnd)) return TRUE;
 
       /* Recursively destroy owned windows */
@@ -1538,6 +1535,15 @@ BOOL WINAPI DestroyWindow( HWND hwnd )
         }
     }
 
+    /* Revert focus to parent */
+    hFocus = GetFocus();
+    if (hwnd == hFocus || IsChild(hwnd, hFocus))
+    {
+        HWND parent = GetAncestor(hwnd, GA_PARENT);
+        if (parent == GetDesktopWindow()) parent = 0;
+        SetFocus(parent);
+    }
+
       /* Send destroy messages */
 
     WIN_SendDestroyMsg( hwnd );






More information about the wine-patches mailing list