- 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
This commit is contained in:
James Tabor 2013-12-08 00:40:54 +00:00
parent e81e634203
commit 21d38eb786
3 changed files with 180 additions and 67 deletions

View file

@ -307,6 +307,64 @@ IntValidateOwnerDepth(PWND Wnd, PWND Owner)
return FALSE; 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 * IntSendDestroyMsg
*/ */
@ -3403,6 +3461,7 @@ NtUserSetShellWindowEx(HWND hwndShell, HWND hwndListView)
} }
UserRefObjectCo(WndShell, &Ref); UserRefObjectCo(WndShell, &Ref);
WndShell->state2 |= WNDS2_BOTTOMMOST;
co_WinPosSetWindowPos(WndShell, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE); co_WinPosSetWindowPos(WndShell, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
WinStaObject->ShellWindow = hwndShell; WinStaObject->ShellWindow = hwndShell;

View file

@ -61,5 +61,6 @@ ULONG FASTCALL IntSetStyle(PWND,ULONG,ULONG);
PWND FASTCALL VerifyWnd(PWND); PWND FASTCALL VerifyWnd(PWND);
PWND FASTCALL IntGetNonChildAncestor(PWND); PWND FASTCALL IntGetNonChildAncestor(PWND);
LONG FASTCALL co_UserSetWindowLong(HWND,DWORD,LONG,BOOL); LONG FASTCALL co_UserSetWindowLong(HWND,DWORD,LONG,BOOL);
HWND FASTCALL IntGetWindow(HWND,UINT);
/* EOF */ /* EOF */

View file

@ -1349,20 +1349,22 @@ co_WinPosDoWinPosChanging(PWND Window,
Y = WinPos->y; Y = WinPos->y;
//ERR("Not SWP_NOMOVE\n"); //ERR("Not SWP_NOMOVE\n");
Parent = Window->spwndParent; Parent = Window->spwndParent;
if ((0 != (Window->style & WS_CHILD)) && Parent && if (((Window->style & WS_CHILD) != 0) &&
Parent &&
Parent != Window->head.rpdesk->pDeskInfo->spwnd) 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; X += Parent->rcClient.left;
Y += Parent->rcClient.top; Y += Parent->rcClient.top;
//ERR("Not SWP_NOMOVE 2 Parent client offset X %d Y %d\n",X,Y);
} }
WindowRect->left = X; WindowRect->left = X;
WindowRect->top = Y; WindowRect->top = Y;
WindowRect->right += X - Window->rcWindow.left; WindowRect->right += X - Window->rcWindow.left;
WindowRect->bottom += Y - Window->rcWindow.top; WindowRect->bottom += Y - Window->rcWindow.top;
RECTL_vOffsetRect(ClientRect,
X - Window->rcWindow.left, RECTL_vOffsetRect(ClientRect, X - Window->rcWindow.left,
Y - Window->rcWindow.top); Y - Window->rcWindow.top);
} }
@ -1382,7 +1384,11 @@ co_WinPosDoWinPosChanging(PWND Window,
* FIXME: hide/show owned popups when owner visibility changes. * FIXME: hide/show owned popups when owner visibility changes.
* *
* ReactOS: See bug 6751 and 7228. * 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 static
HWND FASTCALL HWND FASTCALL
WinPosDoOwnedPopups(PWND Window, HWND hWndInsertAfter) WinPosDoOwnedPopups(PWND Window, HWND hWndInsertAfter)
@ -1393,13 +1399,20 @@ WinPosDoOwnedPopups(PWND Window, HWND hWndInsertAfter)
PWND DesktopWindow, ChildObject; PWND DesktopWindow, ChildObject;
int i; int i;
TRACE("(%p) hInsertAfter = %p\n", Window, hWndInsertAfter );
Owner = Window->spwndOwner ? Window->spwndOwner->head.h : NULL; Owner = Window->spwndOwner ? Window->spwndOwner->head.h : NULL;
Style = Window->style; 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 */ /* Make sure this popup stays above the owner */
HWND hWndLocalPrev = HWND_TOPMOST;
if (hWndInsertAfter != HWND_TOPMOST) if (hWndInsertAfter != HWND_TOPMOST)
{ {
@ -1410,43 +1423,79 @@ WinPosDoOwnedPopups(PWND Window, HWND hWndInsertAfter)
{ {
for (i = 0; List[i]; i++) for (i = 0; List[i]; i++)
{ {
if (List[i] == Owner) BOOL topmost = FALSE;
break;
if (HWND_TOP == hWndInsertAfter)
{
ChildObject = ValidateHwndNoErr(List[i]); ChildObject = ValidateHwndNoErr(List[i]);
if (NULL != ChildObject) if (ChildObject)
{ {
if (0 == (ChildObject->ExStyle & WS_EX_TOPMOST)) 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; break;
} }
}
} if (hWndInsertAfter == HWND_TOP || hWndInsertAfter == HWND_NOTOPMOST)
if (List[i] != Window->head.h)
hWndLocalPrev = List[i];
if (hWndLocalPrev == hWndInsertAfter)
break;
}
hWndInsertAfter = hWndLocalPrev;
}
}
}
else if (Style & WS_CHILD)
{ {
if (!topmost) break;
}
else if (List[i] == hWndInsertAfter) break;
}
}
else
return hWndInsertAfter; return hWndInsertAfter;
} }
}
if (hWndInsertAfter == HWND_BOTTOM)
{
TRACE("Window is HWND_BOTTOM\n");
if (List) ExFreePoolWithTag(List, USERTAG_WINDOWLIST);
goto done;
}
if (!List) if (!List)
{ {
DesktopWindow = UserGetDesktopWindow(); DesktopWindow = UserGetDesktopWindow();
List = IntWinListChildren(DesktopWindow); List = IntWinListChildren(DesktopWindow);
} }
if (List != NULL) if (List != NULL)
{ {
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++) 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; PWND Wnd;
USER_REFERENCE_ENTRY Ref;
if (List[i] == UserHMGetHandle(Window)) if (List[i] == UserHMGetHandle(Window))
break; break;
@ -1454,24 +1503,24 @@ WinPosDoOwnedPopups(PWND Window, HWND hWndInsertAfter)
if (!(Wnd = ValidateHwndNoErr(List[i]))) if (!(Wnd = ValidateHwndNoErr(List[i])))
continue; continue;
if (Wnd->style & WS_POPUP && Wnd->spwndOwner == Window) Owner = Wnd->spwndOwner ? Wnd->spwndOwner->head.h : NULL;
{
USER_REFERENCE_ENTRY Ref;
UserRefObjectCo(Wnd, &Ref);
if (Owner != UserHMGetHandle(Window)) continue;
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, co_WinPosSetWindowPos(Wnd, hWndInsertAfter, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING| SWP_DEFERERASE); SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING| SWP_DEFERERASE);
UserDerefObjectCo(Wnd); UserDerefObjectCo(Wnd);
hWndInsertAfter = List[i]; hWndInsertAfter = List[i];
} }
}
ExFreePoolWithTag(List, USERTAG_WINDOWLIST); ExFreePoolWithTag(List, USERTAG_WINDOWLIST);
} }
done:
return hWndInsertAfter; return hWndInsertAfter;
} }
////
/*********************************************************************** /***********************************************************************
* WinPosInternalMoveWindow * WinPosInternalMoveWindow
@ -1527,15 +1576,11 @@ WinPosFixupFlags(WINDOWPOS *WinPos, PWND Wnd)
Parent = UserGetAncestor( Wnd, GA_PARENT ); Parent = UserGetAncestor( Wnd, GA_PARENT );
if (!IntIsWindowVisible( Parent )) WinPos->flags |= SWP_NOREDRAW; if (!IntIsWindowVisible( Parent )) WinPos->flags |= SWP_NOREDRAW;
if (Wnd->style & WS_VISIBLE) if (Wnd->style & WS_VISIBLE) WinPos->flags &= ~SWP_SHOWWINDOW;
{
WinPos->flags &= ~SWP_SHOWWINDOW;
}
else else
{ {
WinPos->flags &= ~SWP_HIDEWINDOW; WinPos->flags &= ~SWP_HIDEWINDOW;
if (!(WinPos->flags & SWP_SHOWWINDOW)) if (!(WinPos->flags & SWP_SHOWWINDOW)) WinPos->flags |= SWP_NOREDRAW;
WinPos->flags |= SWP_NOREDRAW;
} }
/* Check for right size */ /* Check for right size */
@ -1548,12 +1593,11 @@ WinPosFixupFlags(WINDOWPOS *WinPos, PWND Wnd)
pt.x = WinPos->x; pt.x = WinPos->x;
pt.y = WinPos->y; pt.y = WinPos->y;
IntClientToScreen( Parent, &pt ); 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 */ /* Check for right position */
if (Wnd->rcWindow.left == pt.x && if (Wnd->rcWindow.left == pt.x && Wnd->rcWindow.top == pt.y)
Wnd->rcWindow.top == pt.y)
{ {
// ERR("In right pos\n"); //ERR("In right pos\n");
WinPos->flags |= SWP_NOMOVE; WinPos->flags |= SWP_NOMOVE;
} }
@ -1565,12 +1609,12 @@ WinPosFixupFlags(WINDOWPOS *WinPos, PWND Wnd)
if ((Wnd->style & (WS_POPUP | WS_CHILD)) != WS_CHILD) if ((Wnd->style & (WS_POPUP | WS_CHILD)) != WS_CHILD)
{ {
/* Bring to the top when activating */ /* 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->flags &= ~SWP_NOZORDER;
WinPos->hwndInsertAfter = (0 != (Wnd->ExStyle & WS_EX_TOPMOST) ? WinPos->hwndInsertAfter = (0 != (Wnd->ExStyle & WS_EX_TOPMOST) ? HWND_TOPMOST : HWND_TOP);
HWND_TOPMOST : HWND_TOP);
return TRUE;
} }
} }
@ -1587,25 +1631,31 @@ WinPosFixupFlags(WINDOWPOS *WinPos, PWND Wnd)
WinPos->hwndInsertAfter = HWND_NOTOPMOST; 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)) if (!(Wnd->ExStyle & WS_EX_TOPMOST))
WinPos->flags |= SWP_NOZORDER; WinPos->flags |= SWP_NOZORDER;
WinPos->hwndInsertAfter = HWND_TOP;
} }
else if (HWND_TOP == WinPos->hwndInsertAfter else /* hwndInsertAfter must be a sibling of the window */
&& 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)
{ {
PWND InsAfterWnd; PWND InsAfterWnd;
@ -1673,7 +1723,7 @@ co_WinPosSetWindowPos(
RECTL CopyRect; RECTL CopyRect;
PWND Ancestor; PWND Ancestor;
BOOL bPointerInWindow; BOOL bPointerInWindow;
BOOL bNoTopMost; //BOOL bNoTopMost;
ASSERT_REFS_CO(Window); ASSERT_REFS_CO(Window);
@ -1713,7 +1763,7 @@ co_WinPosSetWindowPos(
co_WinPosDoWinPosChanging(Window, &WinPos, &NewWindowRect, &NewClientRect); co_WinPosDoWinPosChanging(Window, &WinPos, &NewWindowRect, &NewClientRect);
// HWND_NOTOPMOST is redirected in WinPosFixupFlags. // HWND_NOTOPMOST is redirected in WinPosFixupFlags.
bNoTopMost = WndInsertAfter == HWND_NOTOPMOST; //bNoTopMost = WndInsertAfter == HWND_NOTOPMOST;
/* Does the window still exist? */ /* Does the window still exist? */
if (!IntIsWindow(WinPos.hwnd)) if (!IntIsWindow(WinPos.hwnd))
@ -1774,6 +1824,8 @@ co_WinPosSetWindowPos(
/* Validate link windows. (also take into account shell window in hwndShellWindow) */ /* Validate link windows. (also take into account shell window in hwndShellWindow) */
if (!(WinPos.flags & SWP_NOZORDER) && WinPos.hwnd != UserGetShellWindow()) if (!(WinPos.flags & SWP_NOZORDER) && WinPos.hwnd != UserGetShellWindow())
{ {
IntLinkHwnd(Window, WinPos.hwndInsertAfter);
#if 0
//// Fix bug 6751 & 7228 see WinPosDoOwnedPopups wine Fixme. //// Fix bug 6751 & 7228 see WinPosDoOwnedPopups wine Fixme.
PWND ParentWindow; PWND ParentWindow;
PWND Sibling; PWND Sibling;
@ -1836,6 +1888,7 @@ co_WinPosSetWindowPos(
} }
} }
//// ////
#endif
} }
OldWindowRect = Window->rcWindow; OldWindowRect = Window->rcWindow;