From c764210731d4d4b6fda53bf27e2150b704e09ac8 Mon Sep 17 00:00:00 2001 From: David Hedberg Date: Tue, 22 Mar 2011 02:40:46 +0100 Subject: [PATCH] user32: Fix return value when passing a non-sibling preceding window to SetWindowPos. Acrobat Reader relies on SetWindowPos, with hwndInsertAfter set to a non-sibling window and no SWP_NOZORDER passed, to return true. --- dlls/user32/tests/win.c | 22 +++++++++------------ dlls/user32/winpos.c | 43 +++++++++++++++++++++++++---------------- 2 files changed, 35 insertions(+), 30 deletions(-) diff --git a/dlls/user32/tests/win.c b/dlls/user32/tests/win.c index 67601b14044..278a2828440 100644 --- a/dlls/user32/tests/win.c +++ b/dlls/user32/tests/win.c @@ -2064,7 +2064,7 @@ static void test_SetWindowPos(HWND hwnd, HWND hwnd2) /* Returns TRUE also for windows that are not siblings */ ret = SetWindowPos(hwnd_child, hwnd2, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); - todo_wine ok(ret, "Got %d\n", ret); + ok(ret, "Got %d\n", ret); check_active_state(hwnd2, hwnd2, hwnd2); ret = SetWindowPos(hwnd2, hwnd_child, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); @@ -2074,7 +2074,7 @@ static void test_SetWindowPos(HWND hwnd, HWND hwnd2) /* Does not seem to do anything even without passing flags, still returns TRUE */ GetWindowRect(hwnd_child, &rc1); ret = SetWindowPos(hwnd_child, hwnd2 , 1, 2, 3, 4, 0); - todo_wine ok(ret, "Got %d\n", ret); + ok(ret, "Got %d\n", ret); GetWindowRect(hwnd_child, &rc2); ok(rc1.left == rc2.left && rc1.top == rc2.top && rc1.right == rc2.right && rc1.bottom == rc2.bottom, @@ -2087,20 +2087,16 @@ static void test_SetWindowPos(HWND hwnd, HWND hwnd2) ret = SetWindowPos(hwnd2, hwnd_child, 1, 2, 3, 4, 0); ok(ret, "Got %d\n", ret); GetWindowRect(hwnd2, &rc2); - todo_wine - ok(rc1.left == rc2.left && rc1.top == rc2.top && - rc1.right == rc2.right && rc1.bottom == rc2.bottom, - "(%d, %d, %d, %d) != (%d, %d, %d, %d)\n", - rc1.left, rc1.top, rc1.right, rc1.bottom, rc2.left, rc2.top, rc2.right, rc2.bottom); + ok(rc1.left == rc2.left && rc1.top == rc2.top && + rc1.right == rc2.right && rc1.bottom == rc2.bottom, + "(%d, %d, %d, %d) != (%d, %d, %d, %d)\n", + rc1.left, rc1.top, rc1.right, rc1.bottom, rc2.left, rc2.top, rc2.right, rc2.bottom); check_active_state(hwnd2, hwnd2, hwnd2); - /* Restore window */ - SetWindowPos(hwnd2, HWND_TOP, rc1.left, rc1.top, rc1.right-rc1.left, rc1.bottom-rc1.top, 0); - /* .. and with these windows. */ GetWindowRect(hwnd_grandchild, &rc1); ret = SetWindowPos(hwnd_grandchild, hwnd_child2, 1, 2, 3, 4, 0); - todo_wine ok(ret, "Got %d\n", ret); + ok(ret, "Got %d\n", ret); GetWindowRect(hwnd_grandchild, &rc2); ok(rc1.left == rc2.left && rc1.top == rc2.top && rc1.right == rc2.right && rc1.bottom == rc2.bottom, @@ -2154,8 +2150,8 @@ static void test_SetWindowPos(HWND hwnd, HWND hwnd2) check_active_state(hwnd2, hwnd2, hwnd2); ret = SetWindowPos(hwnd, hwnd_desktop, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); - todo_wine ok(!ret, "Got %d\n", ret); - todo_wine check_active_state(hwnd2, hwnd2, hwnd2); + ok(!ret, "Got %d\n", ret); + check_active_state(hwnd2, hwnd2, hwnd2); DestroyWindow(hwnd_grandchild); DestroyWindow(hwnd_child); diff --git a/dlls/user32/winpos.c b/dlls/user32/winpos.c index 789238f02f9..57ccb81797b 100644 --- a/dlls/user32/winpos.c +++ b/dlls/user32/winpos.c @@ -1902,11 +1902,6 @@ static BOOL fixup_flags( WINDOWPOS *winpos ) /* Check hwndInsertAfter */ if (winpos->flags & SWP_NOZORDER) goto done; - /* fix sign extension */ - if (winpos->hwndInsertAfter == (HWND)0xffff) winpos->hwndInsertAfter = HWND_TOPMOST; - else if (winpos->hwndInsertAfter == (HWND)0xfffe) winpos->hwndInsertAfter = HWND_NOTOPMOST; - - /* hwndInsertAfter must be a sibling of the window */ if (winpos->hwndInsertAfter == HWND_TOP) { if (GetWindow(winpos->hwnd, GW_HWNDFIRST) == winpos->hwnd) @@ -1929,16 +1924,9 @@ static BOOL fixup_flags( WINDOWPOS *winpos ) } else { - if (GetAncestor( winpos->hwndInsertAfter, GA_PARENT ) != parent) ret = FALSE; - else - { - /* don't need to change the Zorder of hwnd if it's already inserted - * after hwndInsertAfter or when inserting hwnd after itself. - */ - if ((winpos->hwnd == winpos->hwndInsertAfter) || - (winpos->hwnd == GetWindow( winpos->hwndInsertAfter, GW_HWNDNEXT ))) - winpos->flags |= SWP_NOZORDER; - } + if ((winpos->hwnd == winpos->hwndInsertAfter) || + (winpos->hwnd == GetWindow( winpos->hwndInsertAfter, GW_HWNDNEXT ))) + winpos->flags |= SWP_NOZORDER; } done: WIN_ReleasePtr( wndPtr ); @@ -2033,8 +2021,29 @@ BOOL USER_SetWindowPos( WINDOWPOS * winpos ) UINT orig_flags; orig_flags = winpos->flags; - - /* First make sure that coordinates are valid for WM_WINDOWPOSCHANGING */ + + /* First, check z-order arguments. */ + if (!(winpos->flags & SWP_NOZORDER)) + { + /* fix sign extension */ + if (winpos->hwndInsertAfter == (HWND)0xffff) winpos->hwndInsertAfter = HWND_TOPMOST; + else if (winpos->hwndInsertAfter == (HWND)0xfffe) winpos->hwndInsertAfter = HWND_NOTOPMOST; + + if (!(winpos->hwndInsertAfter == HWND_TOP || + winpos->hwndInsertAfter == HWND_BOTTOM || + winpos->hwndInsertAfter == HWND_TOPMOST || + winpos->hwndInsertAfter == HWND_NOTOPMOST)) + { + HWND parent = GetAncestor( winpos->hwnd, GA_PARENT ); + HWND insertafter_parent = GetAncestor( winpos->hwndInsertAfter, GA_PARENT ); + + /* hwndInsertAfter must be a sibling of the window */ + if (!insertafter_parent) return FALSE; + if (insertafter_parent != parent) return TRUE; + } + } + + /* Make sure that coordinates are valid for WM_WINDOWPOSCHANGING */ if (!(winpos->flags & SWP_NOMOVE)) { if (winpos->x < -32768) winpos->x = -32768;