diff --git a/reactos/subsystems/win32/win32k/include/window.h b/reactos/subsystems/win32/win32k/include/window.h index 79a8df2d003..617e3e50848 100644 --- a/reactos/subsystems/win32/win32k/include/window.h +++ b/reactos/subsystems/win32/win32k/include/window.h @@ -114,7 +114,10 @@ VOID FASTCALL IntUnlinkWindow(PWINDOW_OBJECT Wnd); VOID FASTCALL -IntLinkWindow(PWINDOW_OBJECT Wnd, PWINDOW_OBJECT WndParent, PWINDOW_OBJECT WndPrevSibling); +IntLinkWindow(PWINDOW_OBJECT Wnd, PWINDOW_OBJECT WndPrevSibling); + +VOID FASTCALL +IntLinkHwnd(PWINDOW_OBJECT Wnd, HWND hWndPrev); PWINDOW_OBJECT FASTCALL IntGetAncestor(PWINDOW_OBJECT Wnd, UINT Type); diff --git a/reactos/subsystems/win32/win32k/ntuser/window.c b/reactos/subsystems/win32/win32k/ntuser/window.c index 1e71a1cee3a..ecd152f77bf 100644 --- a/reactos/subsystems/win32/win32k/ntuser/window.c +++ b/reactos/subsystems/win32/win32k/ntuser/window.c @@ -997,17 +997,16 @@ IntIsWindowVisible(PWINDOW_OBJECT BaseWindow) return FALSE; } -VOID FASTCALL + +static VOID FASTCALL IntLinkWnd( PWND Wnd, - PWND WndParent, - PWND WndPrevSibling) /* set to NULL if top sibling */ + PWND WndInsertAfter) /* set to NULL if top sibling */ { - Wnd->spwndParent = WndParent; - if ((Wnd->spwndPrev = WndPrevSibling)) + if ((Wnd->spwndPrev = WndInsertAfter)) { - /* link after WndPrevSibling */ - if ((Wnd->spwndNext = WndPrevSibling->spwndNext)) + /* link after WndInsertAfter */ + if ((Wnd->spwndNext = WndInsertAfter->spwndNext)) Wnd->spwndNext->spwndPrev = Wnd; Wnd->spwndPrev->spwndNext = Wnd; @@ -1015,53 +1014,129 @@ IntLinkWnd( else { /* link at top */ - if ((Wnd->spwndNext = WndParent->spwndChild)) + if ((Wnd->spwndNext = Wnd->spwndParent->spwndChild)) Wnd->spwndNext->spwndPrev = Wnd; - - WndParent->spwndChild = Wnd; - } + Wnd->spwndParent->spwndChild = Wnd; + } } -/* link the window into siblings and parent. children are kept in place. */ +/* + link the window into siblings list + children and parent are kept in place. +*/ VOID FASTCALL IntLinkWindow( PWINDOW_OBJECT Wnd, - PWINDOW_OBJECT WndParent, - PWINDOW_OBJECT WndPrevSibling /* set to NULL if top sibling */ + PWINDOW_OBJECT WndInsertAfter /* set to NULL if top sibling */ ) { - PWINDOW_OBJECT Parent; - IntLinkWnd(Wnd->Wnd, - WndParent->Wnd, - WndPrevSibling ? WndPrevSibling->Wnd : NULL); + WndInsertAfter ? WndInsertAfter->Wnd : NULL); - Wnd->spwndParent = WndParent; - if ((Wnd->spwndPrev = WndPrevSibling)) + if ((Wnd->spwndPrev = WndInsertAfter)) { - /* link after WndPrevSibling */ - if ((Wnd->spwndNext = WndPrevSibling->spwndNext)) + /* link after WndInsertAfter */ + if ((Wnd->spwndNext = WndInsertAfter->spwndNext)) Wnd->spwndNext->spwndPrev = Wnd; + Wnd->spwndPrev->spwndNext = Wnd; } else { /* link at top */ - Parent = Wnd->spwndParent; - if ((Wnd->spwndNext = WndParent->spwndChild)) + if ((Wnd->spwndNext = Wnd->spwndParent->spwndChild)) Wnd->spwndNext->spwndPrev = Wnd; - else if (Parent) - { - Parent->spwndChild = Wnd; - return; - } - if(Parent) - { - Parent->spwndChild = Wnd; - } - } + Wnd->spwndParent->spwndChild = Wnd; + } +} + + +VOID FASTCALL IntLinkHwnd(PWINDOW_OBJECT Wnd, HWND hWndPrev) +{ + if (hWndPrev == HWND_NOTOPMOST) + { + if (!(Wnd->Wnd->ExStyle & WS_EX_TOPMOST) && + (Wnd->Wnd->ExStyle2 & WS_EX2_LINKED)) return; /* nothing to do */ + Wnd->Wnd->ExStyle &= ~WS_EX_TOPMOST; + hWndPrev = HWND_TOP; /* fallback to the HWND_TOP case */ + } + + IntUnlinkWindow(Wnd); /* unlink it from the previous location */ + + if (hWndPrev == HWND_BOTTOM) + { + /* Link in the bottom of the list */ + PWINDOW_OBJECT WndInsertAfter; + + WndInsertAfter = Wnd->spwndParent->spwndChild; + while( WndInsertAfter && WndInsertAfter->spwndNext) + WndInsertAfter = WndInsertAfter->spwndNext; + + IntLinkWindow(Wnd, WndInsertAfter); + Wnd->Wnd->ExStyle &= ~WS_EX_TOPMOST; + } + else if (hWndPrev == HWND_TOPMOST) + { + /* Link in the top of the list */ + IntLinkWindow(Wnd, NULL); + + Wnd->Wnd->ExStyle |= WS_EX_TOPMOST; + } + else if (hWndPrev == HWND_TOP) + { + /* Link it after the last topmost window */ + PWINDOW_OBJECT WndInsertBefore; + + WndInsertBefore = Wnd->spwndParent->spwndChild; + + if (!(Wnd->Wnd->ExStyle & WS_EX_TOPMOST)) /* put it above the first non-topmost window */ + { + while (WndInsertBefore != NULL && WndInsertBefore->spwndNext != NULL) + { + if (!(WndInsertBefore->Wnd->ExStyle & WS_EX_TOPMOST)) break; + if (WndInsertBefore == Wnd->spwndOwner) /* keep it above owner */ + { + Wnd->Wnd->ExStyle |= WS_EX_TOPMOST; + break; + } + WndInsertBefore = WndInsertBefore->spwndNext; + } + } + + IntLinkWindow(Wnd, WndInsertBefore ? WndInsertBefore->spwndPrev : NULL); + } + else + { + /* Link it after hWndPrev */ + PWINDOW_OBJECT WndInsertAfter; + + WndInsertAfter = UserGetWindowObject(hWndPrev); + /* Are we called with an erroneous handle */ + if(WndInsertAfter == NULL) + { + /* Link in a default position */ + IntLinkHwnd(Wnd, HWND_TOP); + return; + } + + IntLinkWindow(Wnd, WndInsertAfter); + + /* Fix the WS_EX_TOPMOST flag */ + if (!(WndInsertAfter->Wnd->ExStyle & WS_EX_TOPMOST)) + { + Wnd->Wnd->ExStyle &= ~WS_EX_TOPMOST; + } + else + { + if(WndInsertAfter->spwndNext && + WndInsertAfter->spwndNext->Wnd->ExStyle & WS_EX_TOPMOST) + { + Wnd->Wnd->ExStyle |= WS_EX_TOPMOST; + } + } + } } HWND FASTCALL @@ -1096,8 +1171,7 @@ IntSetOwner(HWND hWnd, HWND hWndNewOwner) PWINDOW_OBJECT FASTCALL co_IntSetParent(PWINDOW_OBJECT Wnd, PWINDOW_OBJECT WndNewParent) { - PWINDOW_OBJECT WndOldParent, Sibling, InsertAfter; -// HWND hWnd, hWndNewParent; + PWINDOW_OBJECT WndOldParent; BOOL WasVisible; ASSERT(Wnd); @@ -1105,9 +1179,6 @@ co_IntSetParent(PWINDOW_OBJECT Wnd, PWINDOW_OBJECT WndNewParent) ASSERT_REFS_CO(Wnd); ASSERT_REFS_CO(WndNewParent); -// hWnd = Wnd->hSelf; -// hWndNewParent = WndNewParent->hSelf; - /* Some applications try to set a child as a parent */ if (IntIsChildWindow(Wnd, WndNewParent)) { @@ -1121,10 +1192,6 @@ co_IntSetParent(PWINDOW_OBJECT Wnd, PWINDOW_OBJECT WndNewParent) */ WasVisible = co_WinPosShowWindow(Wnd, SW_HIDE); -// /* Validate that window and parent still exist */ -// if (!IntIsWindow(hWnd) || !IntIsWindow(hWndNewParent)) -// return NULL; - /* Window must belong to current process */ if (Wnd->pti->pEThread->ThreadsProcess != PsGetCurrentProcess()) return NULL; @@ -1135,28 +1202,16 @@ co_IntSetParent(PWINDOW_OBJECT Wnd, PWINDOW_OBJECT WndNewParent) if (WndNewParent != WndOldParent) { + /* Unlink the window from the siblings list */ IntUnlinkWindow(Wnd); - InsertAfter = NULL; - if (0 == (Wnd->Wnd->ExStyle & WS_EX_TOPMOST)) - { - /* Not a TOPMOST window, put after TOPMOSTs of new parent */ - Sibling = WndNewParent->spwndChild; - while (NULL != Sibling && 0 != (Sibling->Wnd->ExStyle & WS_EX_TOPMOST)) - { - InsertAfter = Sibling; - Sibling = Sibling->spwndNext; - } - } - if (NULL == InsertAfter) - { - IntLinkWindow(Wnd, WndNewParent, InsertAfter /*prev sibling*/); - } - else - { -// UserReferenceObject(InsertAfter); - IntLinkWindow(Wnd, WndNewParent, InsertAfter /*prev sibling*/); -// UserDereferenceObject(InsertAfter); - } + + /* Set the new parent */ + Wnd->spwndParent = WndNewParent; + Wnd->Wnd->spwndParent = WndNewParent->Wnd; + + /* Link the window with its new siblings*/ + IntLinkHwnd(Wnd, HWND_TOP); + } /* @@ -1173,24 +1228,7 @@ co_IntSetParent(PWINDOW_OBJECT Wnd, PWINDOW_OBJECT WndNewParent) * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */ - /* - * Validate that the old parent still exist, since it migth have been - * destroyed during the last callbacks to user-mode - */ -// if(WndOldParent) -// { -// if(!IntIsWindow(WndOldParent->hSelf)) -// { -// UserDereferenceObject(WndOldParent); -// return NULL; -// } - - /* don't dereference the window object here, it must be done by the caller - of IntSetParent() */ -// return WndOldParent; -// } - - return WndOldParent;//NULL; + return WndOldParent; } BOOL FASTCALL @@ -1219,7 +1257,7 @@ IntSetSystemMenu(PWINDOW_OBJECT Window, PMENU_OBJECT Menu) return TRUE; } -/* unlink the window from siblings and parent. children are kept in place. */ +/* unlink the window from siblings. children and parent are kept in place. */ VOID FASTCALL IntUnlinkWnd(PWND Wnd) { @@ -1232,27 +1270,27 @@ IntUnlinkWnd(PWND Wnd) if (Wnd->spwndParent && Wnd->spwndParent->spwndChild == Wnd) Wnd->spwndParent->spwndChild = Wnd->spwndNext; - Wnd->spwndPrev = Wnd->spwndNext = Wnd->spwndParent = NULL; + Wnd->spwndPrev = Wnd->spwndNext = NULL; } -/* unlink the window from siblings and parent. children are kept in place. */ +/* unlink the window from siblings. children and parent are kept in place. */ VOID FASTCALL IntUnlinkWindow(PWINDOW_OBJECT Wnd) { - PWINDOW_OBJECT WndParent = Wnd->spwndParent; - IntUnlinkWnd(Wnd->Wnd); + IntUnlinkWnd(Wnd->Wnd); - if (Wnd->spwndNext) - Wnd->spwndNext->spwndPrev = Wnd->spwndPrev; + if (Wnd->spwndNext) + Wnd->spwndNext->spwndPrev = Wnd->spwndPrev; + + if (Wnd->spwndPrev) + Wnd->spwndPrev->spwndNext = Wnd->spwndNext; - if (Wnd->spwndPrev) - Wnd->spwndPrev->spwndNext = Wnd->spwndNext; - else if (WndParent && WndParent->spwndChild == Wnd) - WndParent->spwndChild = Wnd->spwndNext; - - Wnd->spwndPrev = Wnd->spwndNext = Wnd->spwndParent = NULL; + if (Wnd->spwndParent && Wnd->spwndParent->spwndChild == Wnd) + Wnd->spwndParent->spwndChild = Wnd->spwndNext; + + Wnd->spwndPrev = Wnd->spwndNext = NULL; } BOOL FASTCALL @@ -2037,43 +2075,11 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs, /* Link the window*/ if (NULL != ParentWindow) { - /* link the window into the parent's child list */ + /* link the window into the siblings list */ if ((dwStyle & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD) - { - PWINDOW_OBJECT PrevSibling; - - PrevSibling = ParentWindow->spwndChild; - - if(PrevSibling) - { - while (PrevSibling->spwndNext) - PrevSibling = PrevSibling->spwndNext; - } - - /* link window as bottom sibling */ - IntLinkWindow(Window, ParentWindow, PrevSibling /*prev sibling*/); - } + IntLinkHwnd(Window, HWND_BOTTOM); else - { - /* link window as top sibling (but after topmost siblings) */ - PWINDOW_OBJECT InsertAfter, Sibling; - if (!(Cs->dwExStyle & WS_EX_TOPMOST)) - { - InsertAfter = NULL; - Sibling = ParentWindow->spwndChild; - while (Sibling && (Sibling->Wnd->ExStyle & WS_EX_TOPMOST)) - { - InsertAfter = Sibling; - Sibling = Sibling->spwndNext; - } - } - else - { - InsertAfter = NULL; - } - - IntLinkWindow(Window, ParentWindow, InsertAfter /* prev sibling */); - } + IntLinkHwnd(Window, HWND_TOP); } /* Send the NCCREATE message */ @@ -2099,7 +2105,6 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs, if (Result == (LRESULT)-1) { DPRINT1("co_UserCreateWindowEx(): WM_CREATE message failed\n"); - IntUnlinkWindow(Window); RETURN((PWND)0); } diff --git a/reactos/subsystems/win32/win32k/ntuser/winpos.c b/reactos/subsystems/win32/win32k/ntuser/winpos.c index cef431fc039..2d1f77fe9c3 100644 --- a/reactos/subsystems/win32/win32k/ntuser/winpos.c +++ b/reactos/subsystems/win32/win32k/ntuser/winpos.c @@ -1082,80 +1082,9 @@ co_WinPosSetWindowPos( /* Relink windows. (also take into account shell window in hwndShellWindow) */ if (!(WinPos.flags & SWP_NOZORDER) && WinPos.hwnd != UserGetShellWindow()) { - PWINDOW_OBJECT ParentWindow; - PWINDOW_OBJECT Sibling; - PWINDOW_OBJECT InsertAfterWindow; - - if ((ParentWindow = Window->spwndParent)) - { - if (HWND_TOPMOST == WinPos.hwndInsertAfter) - { - InsertAfterWindow = NULL; - } - else if (HWND_TOP == WinPos.hwndInsertAfter - || HWND_NOTOPMOST == WinPos.hwndInsertAfter) - { - InsertAfterWindow = NULL; - Sibling = ParentWindow->spwndChild; - while ( NULL != Sibling && - 0 != (Sibling->Wnd->ExStyle & WS_EX_TOPMOST) ) - { - InsertAfterWindow = Sibling; - Sibling = Sibling->spwndNext; - } - if (NULL != InsertAfterWindow) - { - UserReferenceObject(InsertAfterWindow); - } - } - else if (WinPos.hwndInsertAfter == HWND_BOTTOM) - { - if(ParentWindow->spwndChild) - { - InsertAfterWindow = ParentWindow->spwndChild; - - if(InsertAfterWindow) - { - while (InsertAfterWindow->spwndNext) - InsertAfterWindow = InsertAfterWindow->spwndNext; - } - - UserReferenceObject(InsertAfterWindow); - } - else - InsertAfterWindow = NULL; - } - else - InsertAfterWindow = IntGetWindowObject(WinPos.hwndInsertAfter); - /* Do nothing if hwndInsertAfter is HWND_BOTTOM and Window is already - the last window */ - if (InsertAfterWindow != Window) - { - IntUnlinkWindow(Window); - IntLinkWindow(Window, ParentWindow, InsertAfterWindow); - } - if (InsertAfterWindow != NULL) - UserDereferenceObject(InsertAfterWindow); - - if ( (HWND_TOPMOST == WinPos.hwndInsertAfter) || - (0 != (Window->Wnd->ExStyle & WS_EX_TOPMOST) && - NULL != Window->spwndPrev && - 0 != (Window->spwndPrev->Wnd->ExStyle & WS_EX_TOPMOST)) || - (NULL != Window->spwndNext && - 0 != (Window->spwndNext->Wnd->ExStyle & WS_EX_TOPMOST)) ) - { - Window->Wnd->ExStyle |= WS_EX_TOPMOST; - } - else - { - Window->Wnd->ExStyle &= ~ WS_EX_TOPMOST; - } - - } + IntLinkHwnd(Window, WndInsertAfter); } - if (!Window->Wnd) return FALSE; - OldWindowRect = Window->Wnd->rcWindow; OldClientRect = Window->Wnd->rcClient;