Module: wine Branch: master Commit: adf9dcd6a70ef2c125e154f4cd095a616e5505f8 URL: http://source.winehq.org/git/wine.git/?a=commit;h=adf9dcd6a70ef2c125e154f4cd...
Author: Alexandre Julliard julliard@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 ); }