Alexandre Julliard : user32: Fix Z-order handling of windows that have a top-most owner.

Alexandre Julliard julliard at winehq.org
Fri Feb 19 09:21:35 CST 2010


Module: wine
Branch: master
Commit: adf9dcd6a70ef2c125e154f4cd095a616e5505f8
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=adf9dcd6a70ef2c125e154f4cd095a616e5505f8

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Fri Feb 19 13:05:08 2010 +0100

user32: Fix Z-order handling of windows that have a top-most owner.

---

 dlls/user32/tests/win.c |   23 +++++++++++++++++++----
 dlls/user32/winpos.c    |   10 ++++++----
 server/window.c         |   12 ++++++++++--
 3 files changed, 35 insertions(+), 10 deletions(-)

diff --git a/dlls/user32/tests/win.c b/dlls/user32/tests/win.c
index 2799ec8..cd83749 100644
--- a/dlls/user32/tests/win.c
+++ b/dlls/user32/tests/win.c
@@ -2159,7 +2159,7 @@ static void check_z_order_debug(HWND hwnd, HWND next, HWND prev, HWND owner,
         /*trace("skipping next %p (%p)\n", test, UlongToHandle(GetWindowLongPtr(test, GWLP_HINSTANCE)));*/
         test = GetWindow(test, GW_HWNDNEXT);
     }
-    ok_(file, line)(next == test, "expected next %p, got %p\n", next, test);
+    ok_(file, line)(next == test, "%p: expected next %p, got %p\n", hwnd, next, test);
 
     test = GetWindow(hwnd, GW_HWNDPREV);
     /* skip foreign windows */
@@ -2171,13 +2171,14 @@ static void check_z_order_debug(HWND hwnd, HWND next, HWND prev, HWND owner,
         /*trace("skipping prev %p (%p)\n", test, UlongToHandle(GetWindowLongPtr(test, GWLP_HINSTANCE)));*/
         test = GetWindow(test, GW_HWNDPREV);
     }
-    ok_(file, line)(prev == test, "expected prev %p, got %p\n", prev, test);
+    ok_(file, line)(prev == test, "%p: expected prev %p, got %p\n", hwnd, prev, test);
 
     test = GetWindow(hwnd, GW_OWNER);
-    ok_(file, line)(owner == test, "expected owner %p, got %p\n", owner, test);
+    ok_(file, line)(owner == test, "%p: expected owner %p, got %p\n", hwnd, owner, test);
 
     ex_style = GetWindowLong(hwnd, GWL_EXSTYLE);
-    ok_(file, line)(!(ex_style & WS_EX_TOPMOST) == !topmost, "expected %stopmost\n", topmost ? "" : "NOT ");
+    ok_(file, line)(!(ex_style & WS_EX_TOPMOST) == !topmost, "%p: expected %stopmost\n",
+                    hwnd, topmost ? "" : "NOT ");
 }
 
 static void test_popup_zorder(HWND hwnd_D, HWND hwnd_E)
@@ -2258,6 +2259,20 @@ static void test_popup_zorder(HWND hwnd_D, HWND hwnd_E)
     check_z_order(hwnd_A, hwnd_D, 0, 0, TRUE);
 #endif
 
+    /* make hwnd_C owned by a topmost window */
+    DestroyWindow( hwnd_C );
+    hwnd_C = CreateWindowEx(0, "MainWindowClass", NULL,
+                            WS_POPUP,
+                            100, 100, 100, 100,
+                            hwnd_A, 0, GetModuleHandle(0), NULL);
+    trace("hwnd_C %p\n", hwnd_C);
+    check_z_order(hwnd_E, 0, hwnd_D, 0, FALSE);
+    check_z_order(hwnd_D, hwnd_E, hwnd_F, 0, FALSE);
+    check_z_order(hwnd_F, hwnd_D, hwnd_B, 0, FALSE);
+    check_z_order(hwnd_B, hwnd_F, hwnd_A, hwnd_F, TRUE);
+    check_z_order(hwnd_A, hwnd_B, hwnd_C, 0, TRUE);
+    check_z_order(hwnd_C, hwnd_A, 0, hwnd_A, TRUE);
+
     DestroyWindow(hwnd_A);
     DestroyWindow(hwnd_B);
     DestroyWindow(hwnd_C);
diff --git a/dlls/user32/winpos.c b/dlls/user32/winpos.c
index 65e9389..f8a3c41 100644
--- a/dlls/user32/winpos.c
+++ b/dlls/user32/winpos.c
@@ -1627,22 +1627,24 @@ static HWND SWP_DoOwnedPopups(HWND hwnd, HWND hwndInsertAfter)
     {
         /* make sure this popup stays above the owner */
 
-        if (hwndInsertAfter != HWND_TOP && hwndInsertAfter != HWND_TOPMOST)
+        if (hwndInsertAfter != HWND_TOPMOST)
         {
             if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return hwndInsertAfter;
 
             for (i = 0; list[i]; i++)
             {
+                BOOL topmost = (GetWindowLongW( list[i], GWL_EXSTYLE ) & WS_EX_TOPMOST) != 0;
+
                 if (list[i] == owner)
                 {
                     if (i > 0) hwndInsertAfter = list[i-1];
-                    else hwndInsertAfter = HWND_TOP;
+                    else hwndInsertAfter = topmost ? HWND_TOPMOST : HWND_TOP;
                     break;
                 }
 
-                if (hwndInsertAfter == HWND_NOTOPMOST)
+                if (hwndInsertAfter == HWND_TOP || hwndInsertAfter == HWND_NOTOPMOST)
                 {
-                    if (!(GetWindowLongW( list[i], GWL_EXSTYLE ) & WS_EX_TOPMOST)) break;
+                    if (!topmost) break;
                 }
                 else if (list[i] == hwndInsertAfter) break;
             }
diff --git a/server/window.c b/server/window.c
index a0e0788..5fd6f71 100644
--- a/server/window.c
+++ b/server/window.c
@@ -187,9 +187,17 @@ static void link_window( struct window *win, struct window *previous )
         struct list *entry = win->parent->children.next;
         if (!(win->ex_style & WS_EX_TOPMOST))  /* put it above the first non-topmost window */
         {
-            while (entry != &win->parent->children &&
-                   LIST_ENTRY( entry, struct window, entry )->ex_style & WS_EX_TOPMOST)
+            while (entry != &win->parent->children)
+            {
+                struct window *next = LIST_ENTRY( entry, struct window, entry );
+                if (!(next->ex_style & WS_EX_TOPMOST)) break;
+                if (next->handle == win->owner)  /* keep it above owner */
+                {
+                    win->ex_style |= WS_EX_TOPMOST;
+                    break;
+                }
                 entry = entry->next;
+            }
         }
         list_add_before( entry, &win->entry );
     }




More information about the wine-cvs mailing list