From: James Tabor Date: Sun, 8 Dec 2013 00:40:54 +0000 (+0000) Subject: [Win32k] X-Git-Tag: ReactOS-0.3.16~569 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=21d38eb78667f99c06c6fada28ae7158861ef291 [Win32k] - Restore code from revision 48982 by Giannis Adamopoulos. See CORE-6554. - Port sync wine winpos code. Fixes all the wine win:test_children/popup_zorder tests except "move hwnd_F and its popups down" that is if'ed out. Side effect, ReactOS regressed from 29 to 48 failures for the DeferWindowPos API test. That is not bad compared to wine ran 347 tests and 52 failures, ReactOS ran 385 tests. - Keeping code if'ed out for now and added a flag to set most bottom window. svn path=/trunk/; revision=61244 --- 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++) { + BOOL topmost = FALSE; + + ChildObject = ValidateHwndNoErr(List[i]); + if (ChildObject) + { + topmost = (ChildObject->ExStyle & WS_EX_TOPMOST) != 0; + } + if (List[i] == Owner) + { + if (i > 0) hWndInsertAfter = List[i-1]; + else hWndInsertAfter = topmost ? HWND_TOPMOST : HWND_TOP; break; - if (HWND_TOP == hWndInsertAfter) + } + + if (hWndInsertAfter == HWND_TOP || hWndInsertAfter == HWND_NOTOPMOST) { - ChildObject = ValidateHwndNoErr(List[i]); - if (NULL != ChildObject) - { - if (0 == (ChildObject->ExStyle & WS_EX_TOPMOST)) - { - break; - } - } + if (!topmost) break; } - if (List[i] != Window->head.h) - hWndLocalPrev = List[i]; - if (hWndLocalPrev == hWndInsertAfter) - 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) { - if (!(Wnd->ExStyle & WS_EX_TOPMOST)) - WinPos->flags |= SWP_NOZORDER; + /* Keep it topmost when it's already topmost */ + if ((Wnd->ExStyle & WS_EX_TOPMOST) != 0) + WinPos->hwndInsertAfter = HWND_TOPMOST; - WinPos->hwndInsertAfter = HWND_TOP; + if (IntGetWindow(WinPos->hwnd, GW_HWNDFIRST) == WinPos->hwnd) + WinPos->flags |= SWP_NOZORDER; } - else if (HWND_TOP == WinPos->hwndInsertAfter - && 0 != (Wnd->ExStyle & WS_EX_TOPMOST)) + else if (WinPos->hwndInsertAfter == HWND_BOTTOM) { - /* Keep it topmost when it's already topmost */ - WinPos->hwndInsertAfter = HWND_TOPMOST; + if (!(Wnd->ExStyle & WS_EX_TOPMOST) && IntGetWindow(WinPos->hwnd, GW_HWNDLAST) == WinPos->hwnd) + WinPos->flags |= SWP_NOZORDER; } - - /* 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 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; + } + 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;