user32: Rewrite SWP_DoOwnedPopups to take into account topmost windows.
diff --git a/dlls/user32/winpos.c b/dlls/user32/winpos.c
index e6ab36c..4da5d28 100644
--- a/dlls/user32/winpos.c
+++ b/dlls/user32/winpos.c
@@ -1326,27 +1326,6 @@
}
}
-struct move_owned_info
-{
- HWND owner;
- HWND insert_after;
-};
-
-static BOOL CALLBACK move_owned_popups( HWND hwnd, LPARAM lparam )
-{
- struct move_owned_info *info = (struct move_owned_info *)lparam;
-
- if (hwnd == info->owner) return FALSE;
- if ((GetWindowLongW( hwnd, GWL_STYLE ) & WS_POPUP) &&
- GetWindow( hwnd, GW_OWNER ) == info->owner)
- {
- SetWindowPos( hwnd, info->insert_after, 0, 0, 0, 0,
- SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE |
- SWP_NOSENDCHANGING | SWP_DEFERERASE );
- info->insert_after = hwnd;
- }
- return TRUE;
-}
/***********************************************************************
* SWP_DoOwnedPopups
@@ -1358,36 +1337,75 @@
*/
static HWND SWP_DoOwnedPopups(HWND hwnd, HWND hwndInsertAfter)
{
- HWND owner = GetWindow( hwnd, GW_OWNER );
LONG style = GetWindowLongW( hwnd, GWL_STYLE );
- struct move_owned_info info;
+ HWND owner, *list = NULL;
+ unsigned int i;
TRACE("(%p) hInsertAfter = %p\n", hwnd, hwndInsertAfter );
- if ((style & WS_POPUP) && owner)
+ if ((style & WS_POPUP) && (owner = GetWindow( hwnd, GW_OWNER )))
{
/* make sure this popup stays above the owner */
if (hwndInsertAfter != HWND_TOP && hwndInsertAfter != HWND_TOPMOST)
{
- HWND hwndLocalPrev = HWND_TOP;
- HWND prev = GetWindow( owner, GW_HWNDPREV );
+ if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return hwndInsertAfter;
- while (prev && prev != hwndInsertAfter)
+ for (i = 0; list[i]; i++)
{
- if (hwndLocalPrev == HWND_TOP && GetWindowLongW( prev, GWL_STYLE ) & WS_VISIBLE)
- hwndLocalPrev = prev;
- prev = GetWindow( prev, GW_HWNDPREV );
+ if (list[i] == owner)
+ {
+ if (i > 0) hwndInsertAfter = list[i-1];
+ else hwndInsertAfter = HWND_TOP;
+ break;
+ }
+
+ if (hwndInsertAfter == HWND_NOTOPMOST)
+ {
+ if (!(GetWindowLongW( list[i], GWL_EXSTYLE ) & WS_EX_TOPMOST)) break;
+ }
+ else if (list[i] == hwndInsertAfter) break;
}
- if (!prev) hwndInsertAfter = hwndLocalPrev;
}
}
else if (style & WS_CHILD) return hwndInsertAfter;
- info.owner = hwnd;
- info.insert_after = hwndInsertAfter;
- EnumWindows( move_owned_popups, (LPARAM)&info );
- return info.insert_after;
+ if (hwndInsertAfter == HWND_BOTTOM) goto done;
+ if (!list && !(list = WIN_ListChildren( GetDesktopWindow() ))) goto done;
+
+ i = 0;
+ if (hwndInsertAfter == HWND_TOP || hwndInsertAfter == HWND_NOTOPMOST)
+ {
+ if (hwndInsertAfter == HWND_NOTOPMOST || !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOPMOST))
+ {
+ /* skip all the topmost windows */
+ while (list[i] && (GetWindowLongW( list[i], GWL_EXSTYLE ) & WS_EX_TOPMOST)) i++;
+ }
+ }
+ else if (hwndInsertAfter != HWND_TOPMOST)
+ {
+ /* skip windows that are already placed correctly */
+ for (i = 0; list[i]; i++)
+ {
+ if (list[i] == hwndInsertAfter) break;
+ if (list[i] == hwnd) goto done; /* nothing to do if window is moving backwards in z-order */
+ }
+ }
+
+ for ( ; list[i]; i++)
+ {
+ if (list[i] == hwnd) break;
+ if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_POPUP)) continue;
+ if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
+ TRACE( "moving %p owned by %p after %p\n", list[i], hwnd, hwndInsertAfter );
+ SetWindowPos( list[i], hwndInsertAfter, 0, 0, 0, 0,
+ SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE );
+ hwndInsertAfter = list[i];
+ }
+
+done:
+ HeapFree( GetProcessHeap(), 0, list );
+ return hwndInsertAfter;
}
/***********************************************************************