diff --git a/reactos/win32ss/user/ntuser/window.c b/reactos/win32ss/user/ntuser/window.c index 25a1b0a7633..67664313819 100644 --- a/reactos/win32ss/user/ntuser/window.c +++ b/reactos/win32ss/user/ntuser/window.c @@ -307,6 +307,64 @@ IntValidateOwnerDepth(PWND Wnd, PWND Owner) return FALSE; } +HWND FASTCALL +IntGetWindow(HWND hWnd, + UINT uCmd) +{ + PWND Wnd, FoundWnd; + HWND Ret = NULL; + + Wnd = ValidateHwndNoErr(hWnd); + if (!Wnd) + return NULL; + + FoundWnd = NULL; + switch (uCmd) + { + case GW_OWNER: + if (Wnd->spwndOwner != NULL) + FoundWnd = Wnd->spwndOwner; + break; + + case GW_HWNDFIRST: + if(Wnd->spwndParent != NULL) + { + FoundWnd = Wnd->spwndParent; + if (FoundWnd->spwndChild != NULL) + FoundWnd = FoundWnd->spwndChild; + } + break; + case GW_HWNDNEXT: + if (Wnd->spwndNext != NULL) + FoundWnd = Wnd->spwndNext; + break; + + case GW_HWNDPREV: + if (Wnd->spwndPrev != NULL) + FoundWnd = Wnd->spwndPrev; + break; + + case GW_CHILD: + if (Wnd->spwndChild != NULL) + FoundWnd = Wnd->spwndChild; + break; + + case GW_HWNDLAST: + FoundWnd = Wnd; + while ( FoundWnd->spwndNext != NULL) + FoundWnd = FoundWnd->spwndNext; + break; + + default: + Wnd = NULL; + break; + } + + if (FoundWnd != NULL) + Ret = UserHMGetHandle(FoundWnd); + return Ret; +} + /*********************************************************************** * IntSendDestroyMsg */ @@ -3403,6 +3461,7 @@ NtUserSetShellWindowEx(HWND hwndShell, HWND hwndListView) } UserRefObjectCo(WndShell, &Ref); + WndShell->state2 |= WNDS2_BOTTOMMOST; co_WinPosSetWindowPos(WndShell, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE); WinStaObject->ShellWindow = hwndShell; diff --git a/reactos/win32ss/user/ntuser/window.h b/reactos/win32ss/user/ntuser/window.h index e9c10305342..776fa840fd7 100644 --- a/reactos/win32ss/user/ntuser/window.h +++ b/reactos/win32ss/user/ntuser/window.h @@ -61,5 +61,6 @@ ULONG FASTCALL IntSetStyle(PWND,ULONG,ULONG); PWND FASTCALL VerifyWnd(PWND); PWND FASTCALL IntGetNonChildAncestor(PWND); LONG FASTCALL co_UserSetWindowLong(HWND,DWORD,LONG,BOOL); +HWND FASTCALL IntGetWindow(HWND,UINT); /* EOF */ diff --git a/reactos/win32ss/user/ntuser/winpos.c b/reactos/win32ss/user/ntuser/winpos.c index 1b630e12893..ab2c722b92c 100644 --- a/reactos/win32ss/user/ntuser/winpos.c +++ b/reactos/win32ss/user/ntuser/winpos.c @@ -1349,21 +1349,23 @@ co_WinPosDoWinPosChanging(PWND Window, Y = WinPos->y; //ERR("Not SWP_NOMOVE\n"); Parent = Window->spwndParent; - if ((0 != (Window->style & WS_CHILD)) && Parent && - Parent != Window->head.rpdesk->pDeskInfo->spwnd) + if (((Window->style & WS_CHILD) != 0) && + Parent && + Parent != Window->head.rpdesk->pDeskInfo->spwnd) { - //ERR("Not SWP_NOMOVE Parent client offset\n"); + //ERR("Not SWP_NOMOVE 1 Parent client offset X %d Y %d\n",X,Y); X += Parent->rcClient.left; Y += Parent->rcClient.top; + //ERR("Not SWP_NOMOVE 2 Parent client offset X %d Y %d\n",X,Y); } WindowRect->left = X; WindowRect->top = Y; WindowRect->right += X - Window->rcWindow.left; WindowRect->bottom += Y - Window->rcWindow.top; - RECTL_vOffsetRect(ClientRect, - X - Window->rcWindow.left, - Y - Window->rcWindow.top); + + RECTL_vOffsetRect(ClientRect, X - Window->rcWindow.left, + Y - Window->rcWindow.top); } WinPos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE; @@ -1382,7 +1384,11 @@ co_WinPosDoWinPosChanging(PWND Window, * FIXME: hide/show owned popups when owner visibility changes. * * ReactOS: See bug 6751 and 7228. + * */ + //// + // Pass all the win:test_children/popup_zorder tests except "move hwnd_F and its popups down" which is if'ed out. + // Side effect, breaks more of the DeferWindowPos api tests, but wine breaks more!!!! static HWND FASTCALL WinPosDoOwnedPopups(PWND Window, HWND hWndInsertAfter) @@ -1393,13 +1399,20 @@ WinPosDoOwnedPopups(PWND Window, HWND hWndInsertAfter) PWND DesktopWindow, ChildObject; int i; + TRACE("(%p) hInsertAfter = %p\n", Window, hWndInsertAfter ); + Owner = Window->spwndOwner ? Window->spwndOwner->head.h : NULL; Style = Window->style; - if ((Style & WS_POPUP) && Owner) + if (Style & WS_CHILD) + { + TRACE("Window is child\n"); + return hWndInsertAfter; + } + + if (Owner) { /* Make sure this popup stays above the owner */ - HWND hWndLocalPrev = HWND_TOPMOST; if (hWndInsertAfter != HWND_TOPMOST) { @@ -1410,31 +1423,38 @@ WinPosDoOwnedPopups(PWND Window, HWND hWndInsertAfter) { for (i = 0; List[i]; i++) { - if (List[i] == Owner) - break; - if (HWND_TOP == hWndInsertAfter) + BOOL topmost = FALSE; + + ChildObject = ValidateHwndNoErr(List[i]); + if (ChildObject) { - ChildObject = ValidateHwndNoErr(List[i]); - if (NULL != ChildObject) - { - if (0 == (ChildObject->ExStyle & WS_EX_TOPMOST)) - { - break; - } - } + topmost = (ChildObject->ExStyle & WS_EX_TOPMOST) != 0; } - if (List[i] != Window->head.h) - hWndLocalPrev = List[i]; - if (hWndLocalPrev == hWndInsertAfter) + + if (List[i] == Owner) + { + if (i > 0) hWndInsertAfter = List[i-1]; + else hWndInsertAfter = topmost ? HWND_TOPMOST : HWND_TOP; break; + } + + if (hWndInsertAfter == HWND_TOP || hWndInsertAfter == HWND_NOTOPMOST) + { + if (!topmost) break; + } + else if (List[i] == hWndInsertAfter) break; } - hWndInsertAfter = hWndLocalPrev; } + else + return hWndInsertAfter; } } - else if (Style & WS_CHILD) + + if (hWndInsertAfter == HWND_BOTTOM) { - return hWndInsertAfter; + TRACE("Window is HWND_BOTTOM\n"); + if (List) ExFreePoolWithTag(List, USERTAG_WINDOWLIST); + goto done; } if (!List) @@ -1442,11 +1462,40 @@ WinPosDoOwnedPopups(PWND Window, HWND hWndInsertAfter) DesktopWindow = UserGetDesktopWindow(); List = IntWinListChildren(DesktopWindow); } + if (List != NULL) { - for (i = 0; List[i]; i++) + i = 0; + + if (hWndInsertAfter == HWND_TOP || hWndInsertAfter == HWND_NOTOPMOST) + { + if (hWndInsertAfter == HWND_NOTOPMOST || !(Window->ExStyle & WS_EX_TOPMOST)) + { + TRACE("skip all the topmost windows\n"); + /* skip all the topmost windows */ + while (List[i] && + (ChildObject = ValidateHwndNoErr(List[i])) && + (ChildObject->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] == UserHMGetHandle(Window)) + { + ExFreePoolWithTag(List, USERTAG_WINDOWLIST); + goto done; /* nothing to do if window is moving backwards in z-order */ + } + } + } + + for (; List[i]; i++) { PWND Wnd; + USER_REFERENCE_ENTRY Ref; if (List[i] == UserHMGetHandle(Window)) break; @@ -1454,24 +1503,24 @@ WinPosDoOwnedPopups(PWND Window, HWND hWndInsertAfter) if (!(Wnd = ValidateHwndNoErr(List[i]))) continue; - if (Wnd->style & WS_POPUP && Wnd->spwndOwner == Window) - { - USER_REFERENCE_ENTRY Ref; - UserRefObjectCo(Wnd, &Ref); + Owner = Wnd->spwndOwner ? Wnd->spwndOwner->head.h : NULL; - co_WinPosSetWindowPos(Wnd, hWndInsertAfter, 0, 0, 0, 0, - SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING| SWP_DEFERERASE); + if (Owner != UserHMGetHandle(Window)) continue; - UserDerefObjectCo(Wnd); + UserRefObjectCo(Wnd, &Ref); + TRACE( "moving %p owned by %p after %p\n", List[i], UserHMGetHandle(Window), hWndInsertAfter ); + co_WinPosSetWindowPos(Wnd, hWndInsertAfter, 0, 0, 0, 0, + SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING| SWP_DEFERERASE); - hWndInsertAfter = List[i]; - } + UserDerefObjectCo(Wnd); + hWndInsertAfter = List[i]; } ExFreePoolWithTag(List, USERTAG_WINDOWLIST); } - +done: return hWndInsertAfter; } +//// /*********************************************************************** * WinPosInternalMoveWindow @@ -1527,15 +1576,11 @@ WinPosFixupFlags(WINDOWPOS *WinPos, PWND Wnd) Parent = UserGetAncestor( Wnd, GA_PARENT ); if (!IntIsWindowVisible( Parent )) WinPos->flags |= SWP_NOREDRAW; - if (Wnd->style & WS_VISIBLE) - { - WinPos->flags &= ~SWP_SHOWWINDOW; - } + if (Wnd->style & WS_VISIBLE) WinPos->flags &= ~SWP_SHOWWINDOW; else { WinPos->flags &= ~SWP_HIDEWINDOW; - if (!(WinPos->flags & SWP_SHOWWINDOW)) - WinPos->flags |= SWP_NOREDRAW; + if (!(WinPos->flags & SWP_SHOWWINDOW)) WinPos->flags |= SWP_NOREDRAW; } /* Check for right size */ @@ -1548,12 +1593,11 @@ WinPosFixupFlags(WINDOWPOS *WinPos, PWND Wnd) pt.x = WinPos->x; pt.y = WinPos->y; IntClientToScreen( Parent, &pt ); -// ERR("WPFU C2S wpx %d wpy %d ptx %d pty %d\n",WinPos->x,WinPos->y,pt.x,pt.y); + //ERR("WPFU C2S wpx %d wpy %d ptx %d pty %d\n",WinPos->x,WinPos->y,pt.x,pt.y); /* Check for right position */ - if (Wnd->rcWindow.left == pt.x && - Wnd->rcWindow.top == pt.y) + if (Wnd->rcWindow.left == pt.x && Wnd->rcWindow.top == pt.y) { -// ERR("In right pos\n"); + //ERR("In right pos\n"); WinPos->flags |= SWP_NOMOVE; } @@ -1565,12 +1609,12 @@ WinPosFixupFlags(WINDOWPOS *WinPos, PWND Wnd) if ((Wnd->style & (WS_POPUP | WS_CHILD)) != WS_CHILD) { /* Bring to the top when activating */ - if (!(WinPos->flags & SWP_NOACTIVATE)) + if (!(WinPos->flags & (SWP_NOACTIVATE|SWP_HIDEWINDOW)) && + (WinPos->flags & SWP_NOZORDER || + (WinPos->hwndInsertAfter != HWND_TOPMOST && WinPos->hwndInsertAfter != HWND_NOTOPMOST))) { WinPos->flags &= ~SWP_NOZORDER; - WinPos->hwndInsertAfter = (0 != (Wnd->ExStyle & WS_EX_TOPMOST) ? - HWND_TOPMOST : HWND_TOP); - return TRUE; + WinPos->hwndInsertAfter = (0 != (Wnd->ExStyle & WS_EX_TOPMOST) ? HWND_TOPMOST : HWND_TOP); } } @@ -1587,25 +1631,31 @@ WinPosFixupFlags(WINDOWPOS *WinPos, PWND Wnd) WinPos->hwndInsertAfter = HWND_NOTOPMOST; } - if (WinPos->hwndInsertAfter == HWND_NOTOPMOST) + if (WinPos->hwndInsertAfter == HWND_TOP) + { + /* Keep it topmost when it's already topmost */ + if ((Wnd->ExStyle & WS_EX_TOPMOST) != 0) + WinPos->hwndInsertAfter = HWND_TOPMOST; + + if (IntGetWindow(WinPos->hwnd, GW_HWNDFIRST) == WinPos->hwnd) + WinPos->flags |= SWP_NOZORDER; + } + else if (WinPos->hwndInsertAfter == HWND_BOTTOM) + { + if (!(Wnd->ExStyle & WS_EX_TOPMOST) && IntGetWindow(WinPos->hwnd, GW_HWNDLAST) == WinPos->hwnd) + WinPos->flags |= SWP_NOZORDER; + } + else if (WinPos->hwndInsertAfter == HWND_TOPMOST) + { + if ((Wnd->ExStyle & WS_EX_TOPMOST) && IntGetWindow(WinPos->hwnd, GW_HWNDFIRST) == WinPos->hwnd) + WinPos->flags |= SWP_NOZORDER; + } + else if (WinPos->hwndInsertAfter == HWND_NOTOPMOST) { if (!(Wnd->ExStyle & WS_EX_TOPMOST)) WinPos->flags |= SWP_NOZORDER; - - WinPos->hwndInsertAfter = HWND_TOP; } - else if (HWND_TOP == WinPos->hwndInsertAfter - && 0 != (Wnd->ExStyle & WS_EX_TOPMOST)) - { - /* Keep it topmost when it's already topmost */ - WinPos->hwndInsertAfter = HWND_TOPMOST; - } - - /* hwndInsertAfter must be a sibling of the window */ - if (HWND_TOPMOST != WinPos->hwndInsertAfter - && HWND_TOP != WinPos->hwndInsertAfter - && HWND_NOTOPMOST != WinPos->hwndInsertAfter - && HWND_BOTTOM != WinPos->hwndInsertAfter) + else /* hwndInsertAfter must be a sibling of the window */ { PWND InsAfterWnd; @@ -1673,7 +1723,7 @@ co_WinPosSetWindowPos( RECTL CopyRect; PWND Ancestor; BOOL bPointerInWindow; - BOOL bNoTopMost; + //BOOL bNoTopMost; ASSERT_REFS_CO(Window); @@ -1713,7 +1763,7 @@ co_WinPosSetWindowPos( co_WinPosDoWinPosChanging(Window, &WinPos, &NewWindowRect, &NewClientRect); // HWND_NOTOPMOST is redirected in WinPosFixupFlags. - bNoTopMost = WndInsertAfter == HWND_NOTOPMOST; + //bNoTopMost = WndInsertAfter == HWND_NOTOPMOST; /* Does the window still exist? */ if (!IntIsWindow(WinPos.hwnd)) @@ -1774,6 +1824,8 @@ co_WinPosSetWindowPos( /* Validate link windows. (also take into account shell window in hwndShellWindow) */ if (!(WinPos.flags & SWP_NOZORDER) && WinPos.hwnd != UserGetShellWindow()) { + IntLinkHwnd(Window, WinPos.hwndInsertAfter); +#if 0 //// Fix bug 6751 & 7228 see WinPosDoOwnedPopups wine Fixme. PWND ParentWindow; PWND Sibling; @@ -1836,6 +1888,7 @@ co_WinPosSetWindowPos( } } //// +#endif } OldWindowRect = Window->rcWindow;