X-Git-Url: https://git.reactos.org/?p=reactos.git;a=blobdiff_plain;f=win32ss%2Fuser%2Fntuser%2Fwinpos.c;h=66f3530460611ba4f7d2d59367dc73c8b9c7bd9f;hp=62e9708df3bf6534d4558f69ae2188910991f918;hb=68df5a50e6a4d821ad8cf927907a955140500e39;hpb=66000022832126b73fcc375138769070bea818ac diff --git a/win32ss/user/ntuser/winpos.c b/win32ss/user/ntuser/winpos.c index 62e9708df3b..66f35304606 100644 --- a/win32ss/user/ntuser/winpos.c +++ b/win32ss/user/ntuser/winpos.c @@ -2,7 +2,7 @@ * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * PURPOSE: Windows - * FILE: subsystems/win32/win32k/ntuser/window.c + * FILE: win32ss/user/ntuser/winpos.c * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) */ @@ -17,21 +17,55 @@ DBG_DEFAULT_CHANNEL(UserWinpos); #define SWP_EX_PAINTSELF 0x0002 #define SWP_AGG_NOGEOMETRYCHANGE \ - (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE) + (SWP_NOSIZE | SWP_NOCLIENTSIZE | SWP_NOZORDER) #define SWP_AGG_NOPOSCHANGE \ - (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER) + (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE | SWP_NOZORDER) #define SWP_AGG_STATUSFLAGS \ (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW) +#define SWP_AGG_NOCLIENTCHANGE \ + (SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE) #define EMPTYPOINT(pt) ((pt).x == -1 && (pt).y == -1) #define PLACE_MIN 0x0001 #define PLACE_MAX 0x0002 #define PLACE_RECT 0x0004 -VOID FASTCALL IntLinkWindow(PWND Wnd,PWND WndInsertAfter); - /* FUNCTIONS *****************************************************************/ +#if DBG +/*********************************************************************** + * dump_winpos_flags + */ +static void dump_winpos_flags(UINT flags) +{ + static const DWORD dumped_flags = (SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOREDRAW | + SWP_NOACTIVATE | SWP_FRAMECHANGED | SWP_SHOWWINDOW | + SWP_HIDEWINDOW | SWP_NOCOPYBITS | SWP_NOOWNERZORDER | + SWP_NOSENDCHANGING | SWP_DEFERERASE | SWP_ASYNCWINDOWPOS | + SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE | SWP_STATECHANGED); + TRACE("flags:"); + if(flags & SWP_NOSIZE) TRACE(" SWP_NOSIZE"); + if(flags & SWP_NOMOVE) TRACE(" SWP_NOMOVE"); + if(flags & SWP_NOZORDER) TRACE(" SWP_NOZORDER"); + if(flags & SWP_NOREDRAW) TRACE(" SWP_NOREDRAW"); + if(flags & SWP_NOACTIVATE) TRACE(" SWP_NOACTIVATE"); + if(flags & SWP_FRAMECHANGED) TRACE(" SWP_FRAMECHANGED"); + if(flags & SWP_SHOWWINDOW) TRACE(" SWP_SHOWWINDOW"); + if(flags & SWP_HIDEWINDOW) TRACE(" SWP_HIDEWINDOW"); + if(flags & SWP_NOCOPYBITS) TRACE(" SWP_NOCOPYBITS"); + if(flags & SWP_NOOWNERZORDER) TRACE(" SWP_NOOWNERZORDER"); + if(flags & SWP_NOSENDCHANGING) TRACE(" SWP_NOSENDCHANGING"); + if(flags & SWP_DEFERERASE) TRACE(" SWP_DEFERERASE"); + if(flags & SWP_ASYNCWINDOWPOS) TRACE(" SWP_ASYNCWINDOWPOS"); + if(flags & SWP_NOCLIENTSIZE) TRACE(" SWP_NOCLIENTSIZE"); + if(flags & SWP_NOCLIENTMOVE) TRACE(" SWP_NOCLIENTMOVE"); + if(flags & SWP_STATECHANGED) TRACE(" SWP_STATECHANGED"); + + if(flags & ~dumped_flags) TRACE(" %08x", flags & ~dumped_flags); + TRACE("\n"); +} +#endif + BOOL FASTCALL IntGetClientOrigin(PWND Window OPTIONAL, LPPOINT Point) { @@ -65,7 +99,7 @@ IntGetClientRect(PWND Wnd, RECTL *Rect) Rect->bottom = UserGetSystemMetrics(SM_CYMINIMIZED); return; } - if ( Wnd != UserGetDesktopWindow()) // Wnd->fnid != FNID_DESKTOP ) + if (!UserIsDesktopWindow(Wnd)) { *Rect = Wnd->rcClient; RECTL_vOffsetRect(Rect, -Wnd->rcClient.left, -Wnd->rcClient.top); @@ -82,6 +116,29 @@ IntGetClientRect(PWND Wnd, RECTL *Rect) } } +BOOL FASTCALL +IntGetWindowRect(PWND Wnd, RECTL *Rect) +{ + ASSERT( Wnd ); + ASSERT( Rect ); + if (!Wnd) return FALSE; + if (!UserIsDesktopWindow(Wnd)) + { + *Rect = Wnd->rcWindow; + } + else + { + Rect->left = Rect->top = 0; + Rect->right = Wnd->rcWindow.right; + Rect->bottom = Wnd->rcWindow.bottom; +/* Do this until Init bug is fixed. This sets 640x480, see InitMetrics. + Rect->right = GetSystemMetrics(SM_CXSCREEN); + Rect->bottom = GetSystemMetrics(SM_CYSCREEN); +*/ } + return TRUE; +} + + INT FASTCALL IntMapWindowPoints(PWND FromWnd, PWND ToWnd, LPPOINT lpPoints, UINT cPoints) { @@ -94,7 +151,7 @@ IntMapWindowPoints(PWND FromWnd, PWND ToWnd, LPPOINT lpPoints, UINT cPoints) Delta.x = Delta.y = 0; mirror_from = mirror_to = FALSE; - if (FromWnd && FromWnd != UserGetDesktopWindow()) // FromWnd->fnid != FNID_DESKTOP) + if (FromWnd && !UserIsDesktopWindow(FromWnd)) { if (FromWnd->ExStyle & WS_EX_LAYOUTRTL) { @@ -107,7 +164,7 @@ IntMapWindowPoints(PWND FromWnd, PWND ToWnd, LPPOINT lpPoints, UINT cPoints) Delta.y = FromWnd->rcClient.top; } - if (ToWnd && ToWnd != UserGetDesktopWindow()) // ToWnd->fnid != FNID_DESKTOP) + if (ToWnd && !UserIsDesktopWindow(ToWnd)) { if (ToWnd->ExStyle & WS_EX_LAYOUTRTL) { @@ -197,8 +254,32 @@ PWND FASTCALL IntGetLastTopMostWindow(VOID) return NULL; } +VOID +SelectWindowRgn(PWND Window, HRGN hRgnClip) +{ + if (Window->hrgnClip) + { + /* Delete no longer needed region handle */ + IntGdiSetRegionOwner(Window->hrgnClip, GDI_OBJ_HMGR_POWNED); + GreDeleteObject(Window->hrgnClip); + Window->hrgnClip = NULL; + } + + if (hRgnClip > HRGN_WINDOW) + { + /*if (!UserIsDesktopWindow(Window)) + { + NtGdiOffsetRgn(hRgnClip, Window->rcWindow.left, Window->rcWindow.top); + }*/ + /* Set public ownership */ + IntGdiSetRegionOwner(hRgnClip, GDI_OBJ_HMGR_PUBLIC); + + Window->hrgnClip = hRgnClip; + } +} + // -// This helps with bug 6751 forcing modal dialog active when another app is minimized or closed. +// This helps with CORE-6129 forcing modal dialog active when another app is minimized or closed. // BOOL FASTCALL ActivateOtherWindowMin(PWND Wnd) { @@ -207,7 +288,7 @@ BOOL FASTCALL ActivateOtherWindowMin(PWND Wnd) USER_REFERENCE_ENTRY Ref; PTHREADINFO pti = gptiCurrent; - //ERR("AOWM 1\n"); + //ERR("AOWM 1 %p\n",Wnd->head.h); ActivePrev = (pti->MessageQueue->spwndActivePrev != NULL); FindTopWnd = TRUE; @@ -238,7 +319,7 @@ BOOL FASTCALL ActivateOtherWindowMin(PWND Wnd) //ERR("ActivateOtherWindowMin Set FG 1\n"); co_IntSetForegroundWindow(pWndSetActive); UserDerefObjectCo(pWndSetActive); - //ERR("AOWM 2 Exit Good\n"); + //ERR("AOWM 2 Exit Good %p\n",pWndSetActive->head.h); return TRUE; } if (!pWndTemp ) pWndTemp = pWndSetActive; @@ -275,7 +356,7 @@ BOOL FASTCALL ActivateOtherWindowMin(PWND Wnd) //ERR("ActivateOtherWindowMin Set FG 2\n"); co_IntSetForegroundWindow(pWndSetActive); UserDerefObjectCo(pWndSetActive); - //ERR("AOWM 3 Exit Good\n"); + //ERR("AOWM 3 Exit Good %p\n",pWndSetActive->head.h); return TRUE; } //ERR("AOWM 4 Bad\n"); @@ -320,6 +401,7 @@ co_WinPosActivateOtherWindow(PWND Wnd) if (IntIsDesktopWindow(Wnd)) { + //ERR("WinPosActivateOtherWindow Set Focus Msg Q No window!\n"); IntSetFocusMessageQueue(NULL); return; } @@ -327,6 +409,7 @@ co_WinPosActivateOtherWindow(PWND Wnd) /* If this is popup window, try to activate the owner first. */ if ((Wnd->style & WS_POPUP) && (WndTo = Wnd->spwndOwner)) { + TRACE("WPAOW Popup with Owner\n"); WndTo = UserGetAncestor( WndTo, GA_ROOT ); if (can_activate_window(WndTo)) goto done; } @@ -336,159 +419,59 @@ co_WinPosActivateOtherWindow(PWND Wnd) WndTo = Wnd; for (;;) { - if (!(WndTo = WndTo->spwndNext)) break; - if (can_activate_window( WndTo )) break; + if (!(WndTo = WndTo->spwndNext)) break; + if (can_activate_window( WndTo )) goto done; } -done: - - if (WndTo) UserRefObjectCo(WndTo, &Ref); - - if (!gpqForeground || Wnd == gpqForeground->spwndActive) - { - /* ReactOS can pass WndTo = NULL to co_IntSetForegroundWindow and returns FALSE. */ - //ERR("WinPosActivateOtherWindow Set FG 0x%p\n",WndTo); - if (co_IntSetForegroundWindow(WndTo)) - { - if (WndTo) UserDerefObjectCo(WndTo); - return; - } - } - //ERR("WinPosActivateOtherWindow Set Active 0x%p\n",WndTo); - if (!co_IntSetActiveWindow(WndTo,FALSE,TRUE,FALSE)) /* Ok for WndTo to be NULL here */ + /* + Fixes wine win.c:test_SetParent last ShowWindow test after popup dies. + Check for previous active window to bring to top. + */ + if (Wnd) { - co_IntSetActiveWindow(NULL,FALSE,TRUE,FALSE); + WndTo = Wnd->head.pti->MessageQueue->spwndActivePrev; + if (can_activate_window( WndTo )) goto done; } - if (WndTo) UserDerefObjectCo(WndTo); -} -UINT -FASTCALL -co_WinPosArrangeIconicWindows(PWND parent) -{ - RECTL rectParent; - INT i, x, y, xspacing, yspacing, sx, sy; - HWND *List = IntWinListChildren(parent); - - ASSERT_REFS_CO(parent); - - /* Check if we found any children */ - if(List == NULL) + // Find any window to bring to top. Works Okay for wine since it does not see X11 windows. + WndTo = UserGetDesktopWindow(); + WndTo = WndTo->spwndChild; + if ( WndTo == NULL ) { - return 0; + //ERR("WinPosActivateOtherWindow No window!\n"); + return; } - - IntGetClientRect( parent, &rectParent ); - // FIXME: Support gspv.mm.iArrange. - x = rectParent.left; - y = rectParent.bottom; - - xspacing = (UserGetSystemMetrics(SM_CXMINSPACING)/2)+UserGetSystemMetrics(SM_CXBORDER); - yspacing = (UserGetSystemMetrics(SM_CYMINSPACING)/2)+UserGetSystemMetrics(SM_CYBORDER); - - //ERR("X:%d Y:%d XS:%d YS:%d\n",x,y,xspacing,yspacing); - - for(i = 0; List[i]; i++) + for (;;) { - PWND Child; - - if (!(Child = ValidateHwndNoErr(List[i]))) - continue; - - if((Child->style & WS_MINIMIZE) != 0 ) + if (WndTo == Wnd) { - USER_REFERENCE_ENTRY Ref; - UserRefObjectCo(Child, &Ref); - - sx = x + UserGetSystemMetrics(SM_CXBORDER); - sy = y - yspacing - UserGetSystemMetrics(SM_CYBORDER); - - co_WinPosSetWindowPos( Child, 0, sx, sy, 0, 0, - SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE ); - - Child->InternalPos.IconPos.x = sx; - Child->InternalPos.IconPos.y = sy; - Child->InternalPos.flags |= WPF_MININIT; - Child->InternalPos.flags &= ~WPF_SETMINPOSITION; - - UserDerefObjectCo(Child); - - if (x <= (rectParent.right - UserGetSystemMetrics(SM_CXMINSPACING))) - x += xspacing; - else - { - x = rectParent.left; - y -= yspacing; - } - //ERR("X:%d Y:%d\n",x,y); + WndTo = NULL; + break; } + if (can_activate_window( WndTo )) goto done; + if (!(WndTo = WndTo->spwndNext)) break; } - ExFreePoolWithTag(List, USERTAG_WINDOWLIST); - return yspacing; -} -static VOID FASTCALL -WinPosFindIconPos(PWND Window, POINT *Pos) -{ - RECT rectParent; - PWND pwndChild, pwndParent; - int x, y, xspacing, yspacing; +done: + if (WndTo) UserRefObjectCo(WndTo, &Ref); - pwndParent = Window->spwndParent; - if (pwndParent == UserGetDesktopWindow()) + if (gpqForeground && (!gpqForeground->spwndActive || Wnd == gpqForeground->spwndActive)) { - //ERR("Parent is Desktop, Min off screen!\n"); - /* ReactOS doesn't support iconic minimize to desktop */ - Pos->x = Pos->y = -32000; - Window->InternalPos.flags |= WPF_MININIT; - Window->InternalPos.IconPos.x = Pos->x; - Window->InternalPos.IconPos.y = Pos->y; - return; + /* ReactOS can pass WndTo = NULL to co_IntSetForegroundWindow and returns FALSE. */ + //ERR("WinPosActivateOtherWindow Set FG 0x%p hWnd %p\n",WndTo, WndTo ? WndTo->head.h : 0); + if (co_IntSetForegroundWindow(WndTo)) + { + if (WndTo) UserDerefObjectCo(WndTo); + return; + } } - - IntGetClientRect( pwndParent, &rectParent ); - // FIXME: Support gspv.mm.iArrange. - x = rectParent.left; - y = rectParent.bottom; - - xspacing = (UserGetSystemMetrics(SM_CXMINSPACING)/2)+UserGetSystemMetrics(SM_CXBORDER); - yspacing = (UserGetSystemMetrics(SM_CYMINSPACING)/2)+UserGetSystemMetrics(SM_CYBORDER); - - //ERR("X:%d Y:%d XS:%d YS:%d\n",Pos->x,Pos->y,xspacing,yspacing); - - // Set to default position when minimized. - Pos->x = x + UserGetSystemMetrics(SM_CXBORDER); - Pos->y = y - yspacing - UserGetSystemMetrics(SM_CYBORDER); - - for (pwndChild = pwndParent->spwndChild; pwndChild; pwndChild = pwndChild->spwndNext) + //ERR("WinPosActivateOtherWindow Set Active 0x%p\n",WndTo); + if (!UserSetActiveWindow(WndTo)) /* Ok for WndTo to be NULL here */ { - if (pwndChild == Window) continue; - - if (pwndChild->style & WS_VISIBLE) - { - //ERR("Loop!\n"); - continue; - } - //ERR("Pos Child X %d Y %d!\n", pwndChild->InternalPos.IconPos.x, pwndChild->InternalPos.IconPos.y); - if ( pwndChild->InternalPos.IconPos.x == Pos->x && - pwndChild->InternalPos.IconPos.y == Pos->y ) - { - if (x <= rectParent.right - UserGetSystemMetrics(SM_CXMINSPACING)) - x += xspacing; - else - { - x = rectParent.left; - y -= yspacing; - } - Pos->x = x + UserGetSystemMetrics(SM_CXBORDER); - Pos->y = y - yspacing - UserGetSystemMetrics(SM_CYBORDER); - } + //ERR("WPAOW SA 1\n"); + UserSetActiveWindow(NULL); } - Window->InternalPos.IconPos.x = Pos->x; - Window->InternalPos.IconPos.y = Pos->y; - Window->InternalPos.flags |= WPF_MININIT; - //ERR("Position is set! X:%d Y:%d\n",Pos->x,Pos->y); - return; + if (WndTo) UserDerefObjectCo(WndTo); } VOID FASTCALL @@ -497,7 +480,7 @@ WinPosInitInternalPos(PWND Wnd, RECTL *RestoreRect) POINT Size; RECTL Rect = *RestoreRect; - if (Wnd->spwndParent != UserGetDesktopWindow()) + if (Wnd->spwndParent && !UserIsDesktopWindow(Wnd->spwndParent)) { RECTL_vOffsetRect(&Rect, -Wnd->spwndParent->rcClient.left, @@ -740,158 +723,118 @@ IntSetWindowPlacement(PWND Wnd, WINDOWPLACEMENT *wpl, UINT Flags) return TRUE; } -UINT FASTCALL -co_WinPosMinMaximize(PWND Wnd, UINT ShowFlag, RECT* NewPos) +UINT +FASTCALL +co_WinPosArrangeIconicWindows(PWND parent) { - POINT Size; - WINDOWPLACEMENT wpl; - LONG old_style; - UINT SwpFlags = 0; + RECTL rectParent; + PWND Child; + INT x, y, xspacing, yspacing, sx, sy; - ASSERT_REFS_CO(Wnd); + ASSERT_REFS_CO(parent); - wpl.length = sizeof(wpl); - IntGetWindowPlacement( Wnd, &wpl ); + IntGetClientRect( parent, &rectParent ); + // FIXME: Support Minimize Metrics gspv.mm.iArrange. + // Default: ARW_BOTTOMLEFT + x = rectParent.left; + y = rectParent.bottom; - if (co_HOOK_CallHooks( WH_CBT, HCBT_MINMAX, (WPARAM)Wnd->head.h, ShowFlag)) + xspacing = UserGetSystemMetrics(SM_CXMINIMIZED); + yspacing = UserGetSystemMetrics(SM_CYMINIMIZED); + + Child = parent->spwndChild; + while(Child) { - ERR("WinPosMinMaximize WH_CBT Call Hook return!\n"); - return SWP_NOSIZE | SWP_NOMOVE; - } - if (Wnd->style & WS_MINIMIZE) + if((Child->style & WS_MINIMIZE) != 0 ) { - switch (ShowFlag) - { - case SW_SHOWMINNOACTIVE: - case SW_SHOWMINIMIZED: - case SW_FORCEMINIMIZE: - case SW_MINIMIZE: - return SWP_NOSIZE | SWP_NOMOVE; - } - if (!co_IntSendMessageNoWait(Wnd->head.h, WM_QUERYOPEN, 0, 0)) + USER_REFERENCE_ENTRY Ref; + UserRefObjectCo(Child, &Ref); + + sx = x + UserGetSystemMetrics(SM_CXBORDER); + sy = y - yspacing - UserGetSystemMetrics(SM_CYBORDER); + + Child->InternalPos.IconPos.x = sx; + Child->InternalPos.IconPos.y = sy; + Child->InternalPos.flags |= WPF_MININIT; + + co_WinPosSetWindowPos( Child, 0, sx, sy, xspacing, yspacing, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_ASYNCWINDOWPOS); + + UserDerefObjectCo(Child); + + if (x <= rectParent.right - xspacing) + x += xspacing; + else { - return(SWP_NOSIZE | SWP_NOMOVE); + x = rectParent.left; + y -= yspacing; } - SwpFlags |= SWP_NOCOPYBITS; } - switch (ShowFlag) - { - case SW_SHOWMINNOACTIVE: - case SW_SHOWMINIMIZED: - case SW_FORCEMINIMIZE: - case SW_MINIMIZE: - { - //ERR("MinMaximize Minimize\n"); - if (Wnd->style & WS_MAXIMIZE) - { - Wnd->InternalPos.flags |= WPF_RESTORETOMAXIMIZED; - } - else - { - Wnd->InternalPos.flags &= ~WPF_RESTORETOMAXIMIZED; - } - - old_style = IntSetStyle( Wnd, WS_MINIMIZE, WS_MAXIMIZE ); + Child = Child->spwndNext; + } + return yspacing; +} - co_UserRedrawWindow(Wnd, NULL, 0, RDW_VALIDATE | RDW_NOERASE | - RDW_NOINTERNALPAINT); +static VOID FASTCALL +WinPosFindIconPos(PWND Window, POINT *Pos) +{ + RECT rectParent; + PWND pwndChild, pwndParent; + int x, y, xspacing, yspacing; - if (!(Wnd->InternalPos.flags & WPF_SETMINPOSITION)) - Wnd->InternalPos.flags &= ~WPF_MININIT; + pwndParent = Window->spwndParent; + if (UserIsDesktopWindow(pwndParent)) + { + ERR("FIXME: Parent is Desktop, Min off screen!\n"); + /* FIXME: ReactOS doesn't support iconic minimize to desktop */ + Pos->x = Pos->y = -32000; + Window->InternalPos.flags |= WPF_MININIT; + Window->InternalPos.IconPos.x = Pos->x; + Window->InternalPos.IconPos.y = Pos->y; + return; + } - WinPosFindIconPos(Wnd, &wpl.ptMinPosition); + IntGetClientRect( pwndParent, &rectParent ); + // FIXME: Support Minimize Metrics gspv.mm.iArrange. + // Default: ARW_BOTTOMLEFT + x = rectParent.left; + y = rectParent.bottom; - if (!(old_style & WS_MINIMIZE)) SwpFlags |= SWP_STATECHANGED; + xspacing = UserGetSystemMetrics(SM_CXMINIMIZED); + yspacing = UserGetSystemMetrics(SM_CYMINIMIZED); - /*ERR("Minimize: %d,%d %dx%d\n", - wpl.ptMinPosition.x, wpl.ptMinPosition.y, UserGetSystemMetrics(SM_CXMINIMIZED), - UserGetSystemMetrics(SM_CYMINIMIZED)); - */ - RECTL_vSetRect(NewPos, wpl.ptMinPosition.x, wpl.ptMinPosition.y, -// wpl.ptMinPosition.x + UserGetSystemMetrics(SM_CXMINIMIZED), -// wpl.ptMinPosition.y + UserGetSystemMetrics(SM_CYMINIMIZED)); - UserGetSystemMetrics(SM_CXMINIMIZED), - UserGetSystemMetrics(SM_CYMINIMIZED)); - SwpFlags |= SWP_NOCOPYBITS; - break; - } + // Set to default position when minimized. + Pos->x = x + UserGetSystemMetrics(SM_CXBORDER); + Pos->y = y - yspacing - UserGetSystemMetrics(SM_CYBORDER); - case SW_MAXIMIZE: - { - //ERR("MinMaximize Maximize\n"); - if ((Wnd->style & WS_MAXIMIZE) && (Wnd->style & WS_VISIBLE)) - { - SwpFlags = SWP_NOSIZE | SWP_NOMOVE; - break; - } - co_WinPosGetMinMaxInfo(Wnd, &Size, &wpl.ptMaxPosition, NULL, NULL); + for (pwndChild = pwndParent->spwndChild; pwndChild; pwndChild = pwndChild->spwndNext) + { + if (pwndChild == Window) continue; - /*ERR("Maximize: %d,%d %dx%d\n", - wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, Size.x, Size.y); - */ - old_style = IntSetStyle( Wnd, WS_MAXIMIZE, WS_MINIMIZE ); + if ((pwndChild->style & (WS_VISIBLE|WS_MINIMIZE)) != (WS_VISIBLE|WS_MINIMIZE) ) + { + continue; + } - if (!(old_style & WS_MAXIMIZE)) SwpFlags |= SWP_STATECHANGED; - RECTL_vSetRect(NewPos, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, -// wpl.ptMaxPosition.x + Size.x, wpl.ptMaxPosition.y + Size.y); - Size.x, Size.y); - break; - } + if ( pwndChild->InternalPos.IconPos.x != Pos->x && pwndChild->InternalPos.IconPos.y != Pos->y ) + { + break; + } + if (x <= rectParent.right - xspacing) + x += xspacing; + else + { + x = rectParent.left; + y -= yspacing; + } + Pos->x = x + UserGetSystemMetrics(SM_CXBORDER); + Pos->y = y - yspacing - UserGetSystemMetrics(SM_CYBORDER); + } - case SW_SHOWNOACTIVATE: - Wnd->InternalPos.flags &= ~WPF_RESTORETOMAXIMIZED; - /* fall through */ - case SW_SHOWNORMAL: - case SW_RESTORE: - case SW_SHOWDEFAULT: /* FIXME: should have its own handler */ - { - //ERR("MinMaximize Restore\n"); - old_style = IntSetStyle( Wnd, 0, WS_MINIMIZE | WS_MAXIMIZE ); - if (old_style & WS_MINIMIZE) - { - if (Wnd->InternalPos.flags & WPF_RESTORETOMAXIMIZED) - { - co_WinPosGetMinMaxInfo(Wnd, &Size, &wpl.ptMaxPosition, NULL, NULL); - IntSetStyle( Wnd, WS_MAXIMIZE, 0 ); - SwpFlags |= SWP_STATECHANGED; - /*ERR("Restore to Max: %d,%d %dx%d\n", - wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, Size.x, Size.y); - */ - RECTL_vSetRect(NewPos, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, -// wpl.ptMaxPosition.x + Size.x, wpl.ptMaxPosition.y + Size.y); - Size.x, Size.y); - break; - } - else - { - *NewPos = wpl.rcNormalPosition; - /*ERR("Restore Max: %d,%d %dx%d\n", - NewPos->left, NewPos->top, NewPos->right - NewPos->left, NewPos->bottom - NewPos->top); - */ - NewPos->right -= NewPos->left; - NewPos->bottom -= NewPos->top; - break; - } - } - else - { - if (!(old_style & WS_MAXIMIZE)) - { - break; - } - SwpFlags |= SWP_STATECHANGED; - Wnd->InternalPos.flags &= ~WPF_RESTORETOMAXIMIZED; - *NewPos = wpl.rcNormalPosition; - /*ERR("Restore Min: %d,%d %dx%d\n", - NewPos->left, NewPos->top, NewPos->right - NewPos->left, NewPos->bottom - NewPos->top); - */ - NewPos->right -= NewPos->left; - NewPos->bottom -= NewPos->top; - break; - } - } - } - return SwpFlags; + Window->InternalPos.IconPos.x = Pos->x; + Window->InternalPos.IconPos.y = Pos->y; + Window->InternalPos.flags |= WPF_MININIT; + TRACE("Position is set! X:%d Y:%d\n",Pos->x,Pos->y); + return; } BOOL @@ -1091,6 +1034,38 @@ co_WinPosGetMinMaxInfo(PWND Window, POINT* MaxSize, POINT* MaxPos, return 0; // FIXME: What does it return? } +static +BOOL +IntValidateParent(PWND Child, PREGION ValidateRgn) +{ + PWND ParentWnd = Child; + + if (ParentWnd->style & WS_CHILD) + { + do + ParentWnd = ParentWnd->spwndParent; + while (ParentWnd->style & WS_CHILD); + } + + ParentWnd = Child->spwndParent; + while (ParentWnd) + { + if (ParentWnd->style & WS_CLIPCHILDREN) + break; + + if (ParentWnd->hrgnUpdate != 0) + { + IntInvalidateWindows( ParentWnd, + ValidateRgn, + RDW_VALIDATE | RDW_NOCHILDREN); + } + + ParentWnd = ParentWnd->spwndParent; + } + + return TRUE; +} + static VOID FASTCALL FixClientRect(PRECTL ClientRect, PRECTL WindowRect) @@ -1212,12 +1187,9 @@ co_WinPosDoNCCALCSize(PWND Window, PWINDOWPOS WinPos, RECTL* WindowRect, RECTL* Parent = Window->spwndParent; if (0 != (Window->style & WS_CHILD) && Parent) { - RECTL_vOffsetRect(&(params.rgrc[0]), - Parent->rcClient.left, - - Parent->rcClient.top); - RECTL_vOffsetRect(&(params.rgrc[1]), - Parent->rcClient.left, - - Parent->rcClient.top); - RECTL_vOffsetRect(&(params.rgrc[2]), - Parent->rcClient.left, - - Parent->rcClient.top); + RECTL_vOffsetRect(&(params.rgrc[0]), - Parent->rcClient.left, - Parent->rcClient.top); + RECTL_vOffsetRect(&(params.rgrc[1]), - Parent->rcClient.left, - Parent->rcClient.top); + RECTL_vOffsetRect(&(params.rgrc[2]), - Parent->rcClient.left, - Parent->rcClient.top); } params.lppos = &winposCopy; @@ -1232,8 +1204,7 @@ co_WinPosDoNCCALCSize(PWND Window, PWINDOWPOS WinPos, RECTL* WindowRect, RECTL* *ClientRect = params.rgrc[0]; // First rectangle contains the coordinates of the new client rectangle resulting from the move or resize if ((Window->style & WS_CHILD) && Parent) { - RECTL_vOffsetRect(ClientRect, Parent->rcClient.left, - Parent->rcClient.top); + RECTL_vOffsetRect(ClientRect, Parent->rcClient.left, Parent->rcClient.top); } FixClientRect(ClientRect, WindowRect); } @@ -1244,16 +1215,14 @@ co_WinPosDoNCCALCSize(PWND Window, PWINDOWPOS WinPos, RECTL* WindowRect, RECTL* WinPos->flags &= ~SWP_NOCLIENTMOVE; } - if (ClientRect->right - ClientRect->left != - Window->rcClient.right - Window->rcClient.left) + if (ClientRect->right - ClientRect->left != Window->rcClient.right - Window->rcClient.left) { WinPos->flags &= ~SWP_NOCLIENTSIZE; } else wvrFlags &= ~WVR_HREDRAW; - if (ClientRect->bottom - ClientRect->top != - Window->rcClient.bottom - Window->rcClient.top) + if (ClientRect->bottom - ClientRect->top != Window->rcClient.bottom - Window->rcClient.top) { WinPos->flags &= ~SWP_NOCLIENTSIZE; } @@ -1294,9 +1263,11 @@ co_WinPosDoWinPosChanging(PWND Window, /* Send WM_WINDOWPOSCHANGING message */ - if (!(WinPos->flags & SWP_NOSENDCHANGING)) + if (!(WinPos->flags & SWP_NOSENDCHANGING) + && !((WinPos->flags & SWP_AGG_NOCLIENTCHANGE) && (WinPos->flags & SWP_SHOWWINDOW))) { - co_IntSendMessageNoWait(Window->head.h, WM_WINDOWPOSCHANGING, 0, (LPARAM) WinPos); + TRACE("Sending WM_WINDOWPOSCHANGING to hwnd %p flags %04x.\n", Window->head.h,WinPos->flags); + co_IntSendMessage(Window->head.h, WM_WINDOWPOSCHANGING, 0, (LPARAM) WinPos); } /* Calculate new position and size */ @@ -1308,8 +1279,8 @@ co_WinPosDoWinPosChanging(PWND Window, { if (Window->style & WS_MINIMIZE) { - WindowRect->right = WindowRect->left + UserGetSystemMetrics(SM_CXICON); - WindowRect->bottom = WindowRect->top + UserGetSystemMetrics(SM_CYICON); + WindowRect->right = WindowRect->left + UserGetSystemMetrics(SM_CXMINIMIZED); + WindowRect->bottom = WindowRect->top + UserGetSystemMetrics(SM_CYMINIMIZED); } else { @@ -1317,44 +1288,25 @@ co_WinPosDoWinPosChanging(PWND Window, WindowRect->bottom = WindowRect->top + WinPos->cy; } } -#if 0 - if (!(WinPos->flags & SWP_NOMOVE)) - { - WindowRect->left = WinPos->x; - WindowRect->top = WinPos->y; - WindowRect->right += WinPos->x - Window->rcWindow.left; - WindowRect->bottom += WinPos->y - Window->rcWindow.top; - RECTL_vOffsetRect(ClientRect, - WinPos->x - Window->rcWindow.left, - WinPos->y - Window->rcWindow.top); - - } - *WindowRect = Window->rcWindow; - *ClientRect = Window->rcClient; - - if (!(WinPos->flags & SWP_NOSIZE)) - { - WindowRect->right = WindowRect->left + WinPos->cx; - WindowRect->bottom = WindowRect->top + WinPos->cy; - } -#endif if (!(WinPos->flags & SWP_NOMOVE)) { INT X, Y; PWND Parent; X = WinPos->x; Y = WinPos->y; - //ERR("Not SWP_NOMOVE\n"); + Parent = Window->spwndParent; - if (((Window->style & WS_CHILD) != 0) && + + // Parent child position issue is in here. SetParent_W7 test CORE-6651. + if (//((Window->style & WS_CHILD) != 0) && <- Fixes wine msg test_SetParent: "rects do not match", the last test. Parent && Parent != Window->head.rpdesk->pDeskInfo->spwnd) { - //ERR("Not SWP_NOMOVE 1 Parent client offset X %d Y %d\n",X,Y); + TRACE("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); + TRACE("Not SWP_NOMOVE 2 Parent client offset X %d Y %d\n",X,Y); } WindowRect->left = X; @@ -1365,12 +1317,13 @@ co_WinPosDoWinPosChanging(PWND Window, RECTL_vOffsetRect(ClientRect, X - Window->rcWindow.left, Y - Window->rcWindow.top); } - WinPos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE; TRACE( "hwnd %p, after %p, swp %d,%d %dx%d flags %08x\n", WinPos->hwnd, WinPos->hwndInsertAfter, WinPos->x, WinPos->y, WinPos->cx, WinPos->cy, WinPos->flags ); + TRACE("WindowRect: %d %d %d %d\n", WindowRect->left,WindowRect->top,WindowRect->right,WindowRect->bottom); + TRACE("ClientRect: %d %d %d %d\n", ClientRect->left,ClientRect->top,ClientRect->right,ClientRect->bottom); return TRUE; } @@ -1399,7 +1352,6 @@ WinPosDoOwnedPopups(PWND Window, HWND hWndInsertAfter) TRACE("(%p) hInsertAfter = %p\n", Window, hWndInsertAfter ); - Owner = Window->spwndOwner ? Window->spwndOwner->head.h : NULL; Style = Window->style; if (Style & WS_CHILD) @@ -1408,6 +1360,8 @@ WinPosDoOwnedPopups(PWND Window, HWND hWndInsertAfter) return hWndInsertAfter; } + Owner = Window->spwndOwner ? Window->spwndOwner->head.h : NULL; + if (Owner) { /* Make sure this popup stays above the owner */ @@ -1450,7 +1404,7 @@ WinPosDoOwnedPopups(PWND Window, HWND hWndInsertAfter) if (hWndInsertAfter == HWND_BOTTOM) { - ERR("Window is HWND_BOTTOM\n"); + ERR("Window is HWND_BOTTOM hwnd %p\n",hWndInsertAfter); if (List) ExFreePoolWithTag(List, USERTAG_WINDOWLIST); goto done; } @@ -1472,7 +1426,7 @@ WinPosDoOwnedPopups(PWND Window, HWND hWndInsertAfter) TRACE("skip all the topmost windows\n"); /* skip all the topmost windows */ while (List[i] && - (ChildObject = ValidateHwndNoErr(List[i])) && + (ChildObject = ValidateHwndNoErr(List[i])) && (ChildObject->ExStyle & WS_EX_TOPMOST)) i++; } } @@ -1533,6 +1487,7 @@ WinPosInternalMoveWindow(PWND Window, INT MoveX, INT MoveY) PWND Child; ASSERT(Window != Window->spwndChild); + TRACE("InternalMoveWin X %d Y %d\n", MoveX, MoveY); Window->rcWindow.left += MoveX; Window->rcWindow.right += MoveX; @@ -1563,16 +1518,18 @@ WinPosFixupFlags(WINDOWPOS *WinPos, PWND Wnd) POINT pt; /* Finally make sure that all coordinates are valid */ - if (WinPos->x < -32768) WinPos->x = -32768; + if (WinPos->x < -32768) WinPos->x = -32768; else if (WinPos->x > 32767) WinPos->x = 32767; - if (WinPos->y < -32768) WinPos->y = -32768; + if (WinPos->y < -32768) WinPos->y = -32768; else if (WinPos->y > 32767) WinPos->y = 32767; WinPos->cx = max(WinPos->cx, 0); WinPos->cy = max(WinPos->cy, 0); Parent = UserGetAncestor( Wnd, GA_PARENT ); - if (!IntIsWindowVisible( Parent )) WinPos->flags |= SWP_NOREDRAW; + if (!IntIsWindowVisible( Parent ) && + /* Fix B : wine msg test_SetParent:WmSetParentSeq_2:25 wParam bits! */ + (WinPos->flags & SWP_AGG_STATUSFLAGS) == SWP_AGG_NOPOSCHANGE) WinPos->flags |= SWP_NOREDRAW; if (Wnd->style & WS_VISIBLE) WinPos->flags &= ~SWP_SHOWWINDOW; else @@ -1591,7 +1548,7 @@ 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); + TRACE("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) { @@ -1599,22 +1556,17 @@ WinPosFixupFlags(WINDOWPOS *WinPos, PWND Wnd) WinPos->flags |= SWP_NOMOVE; } - if (WinPos->hwnd == UserGetForegroundWindow()) + if ( WinPos->hwnd != UserGetForegroundWindow() && (Wnd->style & (WS_POPUP | WS_CHILD)) != WS_CHILD) { - WinPos->flags |= SWP_NOACTIVATE; /* Already active */ - } - else - if ((Wnd->style & (WS_POPUP | WS_CHILD)) != WS_CHILD) + /* Bring to the top when activating */ + if (!(WinPos->flags & (SWP_NOACTIVATE|SWP_HIDEWINDOW)) && + (WinPos->flags & SWP_NOZORDER || + (WinPos->hwndInsertAfter != HWND_TOPMOST && WinPos->hwndInsertAfter != HWND_NOTOPMOST))) { - /* Bring to the top when activating */ - 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); - } + WinPos->flags &= ~SWP_NOZORDER; + WinPos->hwndInsertAfter = (0 != (Wnd->ExStyle & WS_EX_TOPMOST) ? HWND_TOPMOST : HWND_TOP); } + } /* Check hwndInsertAfter */ if (!(WinPos->flags & SWP_NOZORDER)) @@ -1636,7 +1588,9 @@ WinPosFixupFlags(WINDOWPOS *WinPos, PWND Wnd) WinPos->hwndInsertAfter = HWND_TOPMOST; if (IntGetWindow(WinPos->hwnd, GW_HWNDFIRST) == WinPos->hwnd) + { WinPos->flags |= SWP_NOZORDER; + } } else if (WinPos->hwndInsertAfter == HWND_BOTTOM) { @@ -1708,23 +1662,27 @@ co_WinPosSetWindowPos( RECTL NewWindowRect; RECTL NewClientRect; RECTL valid_rects[2]; - PROSRGNDATA VisRgn; - HRGN VisBefore = NULL; - HRGN VisBeforeJustClient = NULL; - HRGN VisAfter = NULL; - HRGN DirtyRgn = NULL; - HRGN ExposedRgn = NULL; - HRGN CopyRgn = NULL; + PREGION VisBefore = NULL; + PREGION VisBeforeJustClient = NULL; + PREGION VisAfter = NULL; + PREGION CopyRgn = NULL; ULONG WvrFlags = 0; RECTL OldWindowRect, OldClientRect; int RgnType; HDC Dc; RECTL CopyRect; PWND Ancestor; - BOOL bPointerInWindow; + BOOL bPointerInWindow, PosChanged = FALSE; + PTHREADINFO pti = PsGetCurrentThreadWin32Thread(); ASSERT_REFS_CO(Window); + TRACE("pwnd %p, after %p, %d,%d (%dx%d), flags %s", + Window, WndInsertAfter, x, y, cx, cy, flags); +#if DBG + dump_winpos_flags(flags); +#endif + /* FIXME: Get current active window from active queue. Why? since r2915. */ bPointerInWindow = IntPtInWindow(Window, gpsi->ptCursor.x, gpsi->ptCursor.y); @@ -1792,46 +1750,45 @@ co_WinPosSetWindowPos( { VisBefore = VIS_ComputeVisibleRegion(Window, FALSE, FALSE, (Window->style & WS_CLIPSIBLINGS) ? TRUE : FALSE); - VisRgn = NULL; if ( VisBefore != NULL && - (VisRgn = (PROSRGNDATA)RGNOBJAPI_Lock(VisBefore, NULL)) && - REGION_Complexity(VisRgn) == NULLREGION ) + REGION_Complexity(VisBefore) == NULLREGION ) { - RGNOBJAPI_Unlock(VisRgn); - GreDeleteObject(VisBefore); + REGION_Delete(VisBefore); VisBefore = NULL; } - else if(VisRgn) + else if(VisBefore) { - RGNOBJAPI_Unlock(VisRgn); - NtGdiOffsetRgn(VisBefore, -Window->rcWindow.left, -Window->rcWindow.top); + REGION_bOffsetRgn(VisBefore, -Window->rcWindow.left, -Window->rcWindow.top); } - /* Calculate the non client area for resizes, as this is used in the copy region */ + /* Calculate the non client area for resizes, as this is used in the copy region */ if (!(WinPos.flags & SWP_NOSIZE)) { VisBeforeJustClient = VIS_ComputeVisibleRegion(Window, TRUE, FALSE, (Window->style & WS_CLIPSIBLINGS) ? TRUE : FALSE); - VisRgn = NULL; if ( VisBeforeJustClient != NULL && - (VisRgn = (PROSRGNDATA)RGNOBJAPI_Lock(VisBeforeJustClient, NULL)) && - REGION_Complexity(VisRgn) == NULLREGION ) + REGION_Complexity(VisBeforeJustClient) == NULLREGION ) { - RGNOBJAPI_Unlock(VisRgn); - GreDeleteObject(VisBeforeJustClient); + REGION_Delete(VisBeforeJustClient); VisBeforeJustClient = NULL; } - else if(VisRgn) + else if(VisBeforeJustClient) { - RGNOBJAPI_Unlock(VisRgn); - NtGdiOffsetRgn(VisBeforeJustClient, -Window->rcWindow.left, -Window->rcWindow.top); + REGION_bOffsetRgn(VisBeforeJustClient, -Window->rcWindow.left, -Window->rcWindow.top); } } } } + //// HACK 3 + if (Window->hrgnNewFrame) + { + SelectWindowRgn( Window, Window->hrgnNewFrame ); // Should be PSMWP->acvr->hrgnClip + Window->hrgnNewFrame = NULL; + } + WvrFlags = co_WinPosDoNCCALCSize(Window, &WinPos, &NewWindowRect, &NewClientRect, valid_rects); // ERR("co_WinPosDoNCCALCSize returned 0x%x\n valid dest: %d %d %d %d\n valid src : %d %d %d %d\n", WvrFlags, @@ -1846,23 +1803,20 @@ co_WinPosSetWindowPos( OldWindowRect = Window->rcWindow; OldClientRect = Window->rcClient; - //ERR("SetWindowPos OldWindowRect: %d %d %d %d\n", OldWindowRect.left,OldWindowRect.top,OldWindowRect.right,OldWindowRect.bottom); - //ERR("SetWindowPos OldClientRect: %d %d %d %d\n", OldClientRect.left,OldClientRect.top,OldClientRect.right,OldClientRect.bottom); if (NewClientRect.left != OldClientRect.left || NewClientRect.top != OldClientRect.top) { + // Move child window if their parent is moved. Keep Child window relative to Parent... WinPosInternalMoveWindow(Window, NewClientRect.left - OldClientRect.left, NewClientRect.top - OldClientRect.top); + PosChanged = TRUE; } Window->rcWindow = NewWindowRect; Window->rcClient = NewClientRect; - //ERR("SetWindowPos NewWindowRect: %d %d %d %d\n", NewWindowRect.left,NewWindowRect.top,NewWindowRect.right,NewWindowRect.bottom); - //ERR("SetWindowPos NewClientRect: %d %d %d %d\n", NewClientRect.left,NewClientRect.top,NewClientRect.right,NewClientRect.bottom); - /* erase parent when hiding or resizing child */ if (WinPos.flags & SWP_HIDEWINDOW) { @@ -1872,7 +1826,7 @@ co_WinPosSetWindowPos( 0, RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_ALLCHILDREN); - if (Window->spwndParent == UserGetDesktopWindow()) + if (UserIsDesktopWindow(Window->spwndParent)) co_IntShellHookNotify(HSHELL_WINDOWDESTROYED, (WPARAM)Window->head.h, 0); Window->style &= ~WS_VISIBLE; //IntSetStyle( Window, 0, WS_VISIBLE ); @@ -1881,7 +1835,7 @@ co_WinPosSetWindowPos( } else if (WinPos.flags & SWP_SHOWWINDOW) { - if (Window->spwndParent == UserGetDesktopWindow() && + if (UserIsDesktopWindow(Window->spwndParent) && Window->spwndOwner == NULL && (!(Window->ExStyle & WS_EX_TOOLWINDOW) || (Window->ExStyle & WS_EX_APPWINDOW))) @@ -1906,20 +1860,16 @@ co_WinPosSetWindowPos( /* Determine the new visible region */ VisAfter = VIS_ComputeVisibleRegion(Window, FALSE, FALSE, (Window->style & WS_CLIPSIBLINGS) ? TRUE : FALSE); - VisRgn = NULL; if ( VisAfter != NULL && - (VisRgn = (PROSRGNDATA)RGNOBJAPI_Lock(VisAfter, NULL)) && - REGION_Complexity(VisRgn) == NULLREGION ) + REGION_Complexity(VisAfter) == NULLREGION ) { - RGNOBJAPI_Unlock(VisRgn); - GreDeleteObject(VisAfter); + REGION_Delete(VisAfter); VisAfter = NULL; } - else if(VisRgn) + else if(VisAfter) { - RGNOBJAPI_Unlock(VisRgn); - NtGdiOffsetRgn(VisAfter, -Window->rcWindow.left, -Window->rcWindow.top); + REGION_bOffsetRgn(VisAfter, -Window->rcWindow.left, -Window->rcWindow.top); } /* @@ -1929,11 +1879,12 @@ co_WinPosSetWindowPos( * class need to be completely repainted on (horizontal/vertical) size * change. */ - if ( VisBefore != NULL && - VisAfter != NULL && - !(WinPos.flags & SWP_NOCOPYBITS) && - ((WinPos.flags & SWP_NOSIZE) || !(WvrFlags & WVR_REDRAW)) && - !(Window->ExStyle & WS_EX_TRANSPARENT) ) + if ( ( VisBefore != NULL && + VisAfter != NULL && + !(WinPos.flags & SWP_NOCOPYBITS) && + ((WinPos.flags & SWP_NOSIZE) || !(WvrFlags & WVR_REDRAW)) && + !(Window->ExStyle & WS_EX_TRANSPARENT) ) || + ( !PosChanged && (WinPos.flags & SWP_FRAMECHANGED) && VisBefore) ) { /* @@ -1945,21 +1896,26 @@ co_WinPosSetWindowPos( * region...) */ - CopyRgn = IntSysCreateRectRgn(0, 0, 0, 0); + CopyRgn = IntSysCreateRectpRgn(0, 0, 0, 0); if (WinPos.flags & SWP_NOSIZE) - RgnType = NtGdiCombineRgn(CopyRgn, VisAfter, VisBefore, RGN_AND); + RgnType = IntGdiCombineRgn(CopyRgn, VisAfter, VisBefore, RGN_AND); else if (VisBeforeJustClient != NULL) { - RgnType = NtGdiCombineRgn(CopyRgn, VisAfter, VisBeforeJustClient, RGN_AND); - GreDeleteObject(VisBeforeJustClient); + RgnType = IntGdiCombineRgn(CopyRgn, VisAfter, VisBeforeJustClient, RGN_AND); + REGION_Delete(VisBeforeJustClient); } - /* No use in copying bits which are in the update region. */ + /* Now use in copying bits which are in the update region. */ if (Window->hrgnUpdate != NULL) { - NtGdiOffsetRgn(CopyRgn, NewWindowRect.left, NewWindowRect.top); - NtGdiCombineRgn(CopyRgn, CopyRgn, Window->hrgnUpdate, RGN_DIFF); - NtGdiOffsetRgn(CopyRgn, -NewWindowRect.left, -NewWindowRect.top); + PREGION RgnUpdate = REGION_LockRgn(Window->hrgnUpdate); + if (RgnUpdate) + { + REGION_bOffsetRgn(CopyRgn, NewWindowRect.left, NewWindowRect.top); + IntGdiCombineRgn(CopyRgn, CopyRgn, RgnUpdate, RGN_DIFF); + REGION_bOffsetRgn(CopyRgn, -NewWindowRect.left, -NewWindowRect.top); + REGION_UnlockRgn(RgnUpdate); + } } /* @@ -1967,21 +1923,18 @@ co_WinPosSetWindowPos( * there's nothing to copy. Also, it's no use copying bits onto * themselves. */ - if ( (VisRgn = (PROSRGNDATA)RGNOBJAPI_Lock(CopyRgn, NULL)) && - REGION_GetRgnBox(VisRgn, &CopyRect) == NULLREGION) + if (REGION_GetRgnBox(CopyRgn, &CopyRect) == NULLREGION) { /* Nothing to copy, clean up */ - RGNOBJAPI_Unlock(VisRgn); - GreDeleteObject(CopyRgn); + REGION_Delete(CopyRgn); CopyRgn = NULL; } - else if (OldWindowRect.left != NewWindowRect.left || - OldWindowRect.top != NewWindowRect.top) + else if ( OldWindowRect.left != NewWindowRect.left || + OldWindowRect.top != NewWindowRect.top || + (WinPos.flags & SWP_FRAMECHANGED) ) { - if(VisRgn) - { - RGNOBJAPI_Unlock(VisRgn); - } + HRGN DcRgn = NtGdiCreateRectRgn(0, 0, 0, 0); + PREGION DcRgnObj = REGION_LockRgn(DcRgn); /* * Small trick here: there is no function to bitblt a region. So @@ -1992,10 +1945,12 @@ co_WinPosSetWindowPos( * Since NtUserGetDCEx takes ownership of the clip region, we need * to create a copy of CopyRgn and pass that. We need CopyRgn later */ - NtGdiOffsetRgn(CopyRgn, NewWindowRect.left, NewWindowRect.top); + IntGdiCombineRgn(DcRgnObj, CopyRgn, NULL, RGN_COPY); + REGION_bOffsetRgn(DcRgnObj, NewWindowRect.left, NewWindowRect.top); + REGION_UnlockRgn(DcRgnObj); Dc = UserGetDCEx( Window, - CopyRgn, - DCX_WINDOW|DCX_CACHE|DCX_INTERSECTRGN|DCX_CLIPSIBLINGS|DCX_KEEPCLIPRGN); + DcRgn, + DCX_WINDOW|DCX_CACHE|DCX_INTERSECTRGN|DCX_CLIPSIBLINGS|DCX_KEEPCLIPRGN); // DCX_WINDOW will set first, go read WinDC.c. NtGdiBitBlt( Dc, CopyRect.left, CopyRect.top, CopyRect.right - CopyRect.left, @@ -2008,94 +1963,126 @@ co_WinPosSetWindowPos( 0); UserReleaseDC(Window, Dc, FALSE); - IntValidateParent(Window, CopyRgn, FALSE); - NtGdiOffsetRgn(CopyRgn, -NewWindowRect.left, -NewWindowRect.top); + IntValidateParent(Window, CopyRgn); + GreDeleteObject(DcRgn); + } + } + else + { + CopyRgn = NULL; + } + + if ( !PosChanged && (WinPos.flags & SWP_FRAMECHANGED) && VisBefore ) + { + PWND pwnd = Window; + PWND Parent = pwnd->spwndParent; + + TRACE("SWP_FRAMECHANGED no chg\n"); + + if ( pwnd->style & WS_CHILD ) // Fix ProgMan menu bar drawing. + { + TRACE("SWP_FRAMECHANGED win child %p Parent %p\n",pwnd,Parent); + pwnd = Parent ? Parent : pwnd; } - else if(VisRgn) + + if ( !(pwnd->style & WS_CHILD) ) { - RGNOBJAPI_Unlock(VisRgn); + HDC hdc; + HRGN DcRgn = NtGdiCreateRectRgn(0, 0, 0, 0); + PREGION DcRgnObj = REGION_LockRgn(DcRgn); + + TRACE("SWP_FRAMECHANGED Draw\n"); + + IntGdiCombineRgn(DcRgnObj, VisBefore, NULL, RGN_COPY); + REGION_UnlockRgn(DcRgnObj); + + hdc = UserGetDCEx( pwnd, + DcRgn, + DCX_WINDOW|DCX_CACHE|DCX_INTERSECTRGN|DCX_CLIPSIBLINGS|DCX_KEEPCLIPRGN); // DCX_WINDOW, see note above.... + + NC_DoNCPaint(pwnd, hdc, -1); // Force full redraw of nonclient area. + + UserReleaseDC(pwnd, hdc, FALSE); + IntValidateParent(pwnd, DcRgnObj); + GreDeleteObject(DcRgn); } } - else - { - CopyRgn = NULL; - } /* We need to redraw what wasn't visible before */ if (VisAfter != NULL) { - DirtyRgn = IntSysCreateRectRgn(0, 0, 0, 0); - if (CopyRgn != NULL) - { - RgnType = NtGdiCombineRgn(DirtyRgn, VisAfter, CopyRgn, RGN_DIFF); - } - else + PREGION DirtyRgn = IntSysCreateRectpRgn(0, 0, 0, 0); + if (DirtyRgn) { - RgnType = NtGdiCombineRgn(DirtyRgn, VisAfter, 0, RGN_COPY); - } - if (RgnType != ERROR && RgnType != NULLREGION) - { - /* old code - NtGdiOffsetRgn(DirtyRgn, Window->rcWindow.left, Window->rcWindow.top); - IntInvalidateWindows( Window, - DirtyRgn, - RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN); - } - GreDeleteObject(DirtyRgn); - */ - - PWND Parent = Window->spwndParent; + if (CopyRgn != NULL) + { + RgnType = IntGdiCombineRgn(DirtyRgn, VisAfter, CopyRgn, RGN_DIFF); + } + else + { + RgnType = IntGdiCombineRgn(DirtyRgn, VisAfter, 0, RGN_COPY); + } - NtGdiOffsetRgn( DirtyRgn, - Window->rcWindow.left, - Window->rcWindow.top); - if ( (Window->style & WS_CHILD) && - (Parent) && - !(Parent->style & WS_CLIPCHILDREN)) - { - IntInvalidateWindows( Parent, - DirtyRgn, - RDW_ERASE | RDW_INVALIDATE); - co_IntPaintWindows(Parent, RDW_ERASENOW, FALSE); - } - else - { + if (RgnType != ERROR && RgnType != NULLREGION) + { + /* old code + NtGdiOffsetRgn(DirtyRgn, Window->rcWindow.left, Window->rcWindow.top); IntInvalidateWindows( Window, DirtyRgn, - RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN); - } + RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN); + } + GreDeleteObject(DirtyRgn); + */ + + PWND Parent = Window->spwndParent; + + REGION_bOffsetRgn( DirtyRgn, Window->rcWindow.left, Window->rcWindow.top); + + if ( (Window->style & WS_CHILD) && (Parent) && !(Parent->style & WS_CLIPCHILDREN)) + { + IntInvalidateWindows( Parent, DirtyRgn, RDW_ERASE | RDW_INVALIDATE); + co_IntPaintWindows(Parent, RDW_NOCHILDREN, FALSE); + } + else + { + IntInvalidateWindows( Window, DirtyRgn, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN); + } + } + REGION_Delete(DirtyRgn); } - GreDeleteObject(DirtyRgn); } if (CopyRgn != NULL) { - GreDeleteObject(CopyRgn); + REGION_Delete(CopyRgn); } /* Expose what was covered before but not covered anymore */ if (VisBefore != NULL) { - ExposedRgn = IntSysCreateRectRgn(0, 0, 0, 0); - RgnType = NtGdiCombineRgn(ExposedRgn, VisBefore, NULL, RGN_COPY); - NtGdiOffsetRgn( ExposedRgn, - OldWindowRect.left - NewWindowRect.left, - OldWindowRect.top - NewWindowRect.top); + PREGION ExposedRgn = IntSysCreateRectpRgn(0, 0, 0, 0); + if (ExposedRgn) + { + RgnType = IntGdiCombineRgn(ExposedRgn, VisBefore, NULL, RGN_COPY); + REGION_bOffsetRgn(ExposedRgn, + OldWindowRect.left - NewWindowRect.left, + OldWindowRect.top - NewWindowRect.top); - if (VisAfter != NULL) - RgnType = NtGdiCombineRgn(ExposedRgn, ExposedRgn, VisAfter, RGN_DIFF); + if (VisAfter != NULL) + RgnType = IntGdiCombineRgn(ExposedRgn, ExposedRgn, VisAfter, RGN_DIFF); - if (RgnType != ERROR && RgnType != NULLREGION) - { - co_VIS_WindowLayoutChanged(Window, ExposedRgn); + if (RgnType != ERROR && RgnType != NULLREGION) + { + co_VIS_WindowLayoutChanged(Window, ExposedRgn); + } + REGION_Delete(ExposedRgn); } - GreDeleteObject(ExposedRgn); - GreDeleteObject(VisBefore); + REGION_Delete(VisBefore); } if (VisAfter != NULL) { - GreDeleteObject(VisAfter); + REGION_Delete(VisAfter); } } @@ -2108,18 +2095,67 @@ co_WinPosSetWindowPos( else { //ERR("SetWindowPos Set FG Window!\n"); - if (Window->state & WNDS_BEINGACTIVATED) // Inside SAW? - co_IntSetActiveWindow(Window, FALSE, TRUE, FALSE); // Fixes Api AttachThreadInput tests. - else - co_IntSetForegroundWindow(Window); // Fixes SW_HIDE issues. Wine win test_SetActiveWindow & test_SetForegroundWindow. + if ( pti->MessageQueue->spwndActive != Window || + pti->MessageQueue != gpqForeground ) + { + //ERR("WPSWP : set active window\n"); + if (!(Window->state & WNDS_BEINGACTIVATED)) // Inside SAW? + { + co_IntSetForegroundWindow(Window); // Fixes SW_HIDE issues. Wine win test_SetActiveWindow & test_SetForegroundWindow. + } + } } } + if ( !PosChanged && + (WinPos.flags & SWP_FRAMECHANGED) && + !(WinPos.flags & SWP_DEFERERASE) && // Prevent sending WM_SYNCPAINT message. + VisAfter ) + { + PWND Parent = Window->spwndParent; + if ( !(Window->style & WS_CHILD) && (Parent) && (Parent->style & WS_CLIPCHILDREN)) + { + TRACE("SWP_FRAMECHANGED Parent WS_CLIPCHILDREN\n"); + UserSyncAndPaintWindows( Parent, RDW_CLIPCHILDREN); + } + } + + // Fix wine msg test_SetFocus, prevents sending WM_WINDOWPOSCHANGED. + if ( VisBefore == NULL && + VisBeforeJustClient == NULL && + !(Window->ExStyle & WS_EX_TOPMOST) && + (WinPos.flags & SWP_AGG_STATUSFLAGS) == (SWP_AGG_NOPOSCHANGE & ~SWP_NOZORDER)) + { + TRACE("No drawing, set no Z order and no redraw!\n"); + WinPos.flags |= SWP_NOZORDER|SWP_NOREDRAW; + } + + if(!(flags & SWP_DEFERERASE)) + { + /* erase parent when hiding or resizing child */ + if ((flags & SWP_HIDEWINDOW) || + (!(flags & SWP_SHOWWINDOW) && + (WinPos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOGEOMETRYCHANGE)) + { + PWND Parent = Window->spwndParent; + if (!Parent || UserIsDesktopWindow(Parent)) Parent = Window; + UserSyncAndPaintWindows( Parent, RDW_ERASENOW); + } + + /* Give newly shown windows a chance to redraw */ + if(((WinPos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) + && !(flags & SWP_AGG_NOCLIENTCHANGE) && (flags & SWP_SHOWWINDOW)) + { + UserSyncAndPaintWindows( Window, RDW_ERASENOW); + } + } + /* And last, send the WM_WINDOWPOSCHANGED message */ - TRACE("\tstatus flags = %04x\n", WinPos.flags & SWP_AGG_STATUSFLAGS); + TRACE("\tstatus hwnd %p flags = %04x\n",Window?Window->head.h:NULL,WinPos.flags & SWP_AGG_STATUSFLAGS); - if ((WinPos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) + if (((WinPos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) + && !((flags & SWP_AGG_NOCLIENTCHANGE) && (flags & SWP_SHOWWINDOW))) { /* WM_WINDOWPOSCHANGED is sent even if SWP_NOSENDCHANGING is set and always contains final window position. @@ -2128,6 +2164,7 @@ co_WinPosSetWindowPos( WinPos.y = NewWindowRect.top; WinPos.cx = NewWindowRect.right - NewWindowRect.left; WinPos.cy = NewWindowRect.bottom - NewWindowRect.top; + TRACE("WM_WINDOWPOSCHANGED hwnd %p Flags %04x\n",WinPos.hwnd,WinPos.flags); co_IntSendMessageNoWait(WinPos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM) &WinPos); } @@ -2192,7 +2229,7 @@ co_WinPosSendSizeMove(PWND Wnd) co_IntSendMessageNoWait(UserHMGetHandle(Wnd), WM_SIZE, wParam, lParam); - if (Wnd->spwndParent == UserGetDesktopWindow()) // Wnd->spwndParent->fnid == FNID_DESKTOP ) + if (UserIsDesktopWindow(Wnd->spwndParent)) lParam = MAKELONG(Wnd->rcClient.left, Wnd->rcClient.top); else lParam = MAKELONG(Wnd->rcClient.left-Wnd->spwndParent->rcClient.left, Wnd->rcClient.top-Wnd->spwndParent->rcClient.top); @@ -2202,6 +2239,156 @@ co_WinPosSendSizeMove(PWND Wnd) IntEngWindowChanged(Wnd, WOC_RGN_CLIENT); } +UINT FASTCALL +co_WinPosMinMaximize(PWND Wnd, UINT ShowFlag, RECT* NewPos) +{ + POINT Size; + WINDOWPLACEMENT wpl; + LONG old_style; + UINT SwpFlags = 0; + + ASSERT_REFS_CO(Wnd); + + wpl.length = sizeof(wpl); + IntGetWindowPlacement( Wnd, &wpl ); + + if (co_HOOK_CallHooks( WH_CBT, HCBT_MINMAX, (WPARAM)Wnd->head.h, ShowFlag)) + { + ERR("WinPosMinMaximize WH_CBT Call Hook return!\n"); + return SWP_NOSIZE | SWP_NOMOVE; + } + if (Wnd->style & WS_MINIMIZE) + { + switch (ShowFlag) + { + case SW_MINIMIZE: + case SW_SHOWMINNOACTIVE: + case SW_SHOWMINIMIZED: + case SW_FORCEMINIMIZE: + return SWP_NOSIZE | SWP_NOMOVE; + } + if (!co_IntSendMessageNoWait(Wnd->head.h, WM_QUERYOPEN, 0, 0)) + { + return(SWP_NOSIZE | SWP_NOMOVE); + } + SwpFlags |= SWP_NOCOPYBITS; + } + switch (ShowFlag) + { + case SW_MINIMIZE: + case SW_SHOWMINNOACTIVE: + case SW_SHOWMINIMIZED: + case SW_FORCEMINIMIZE: + { + //ERR("MinMaximize Minimize\n"); + if (Wnd->style & WS_MAXIMIZE) + { + Wnd->InternalPos.flags |= WPF_RESTORETOMAXIMIZED; + } + else + { + Wnd->InternalPos.flags &= ~WPF_RESTORETOMAXIMIZED; + } + + old_style = IntSetStyle( Wnd, WS_MINIMIZE, WS_MAXIMIZE ); + + co_UserRedrawWindow(Wnd, NULL, 0, RDW_VALIDATE | RDW_NOERASE | RDW_NOINTERNALPAINT); + + if (!(Wnd->InternalPos.flags & WPF_SETMINPOSITION)) + Wnd->InternalPos.flags &= ~WPF_MININIT; + + WinPosFindIconPos(Wnd, &wpl.ptMinPosition); + + if (!(old_style & WS_MINIMIZE)) + { + SwpFlags |= SWP_STATECHANGED; + IntShowOwnedPopups(Wnd, FALSE); + } + + RECTL_vSetRect(NewPos, wpl.ptMinPosition.x, wpl.ptMinPosition.y, + wpl.ptMinPosition.x + UserGetSystemMetrics(SM_CXMINIMIZED), + wpl.ptMinPosition.y + UserGetSystemMetrics(SM_CYMINIMIZED)); + SwpFlags |= SWP_NOCOPYBITS; + break; + } + + case SW_MAXIMIZE: + { + //ERR("MinMaximize Maximize\n"); + if ((Wnd->style & WS_MAXIMIZE) && (Wnd->style & WS_VISIBLE)) + { + SwpFlags = SWP_NOSIZE | SWP_NOMOVE; + break; + } + co_WinPosGetMinMaxInfo(Wnd, &Size, &wpl.ptMaxPosition, NULL, NULL); + + /*ERR("Maximize: %d,%d %dx%d\n", + wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, Size.x, Size.y); + */ + old_style = IntSetStyle( Wnd, WS_MAXIMIZE, WS_MINIMIZE ); + /*if (old_style & WS_MINIMIZE) + { + IntShowOwnedPopups(Wnd, TRUE); + }*/ + + if (!(old_style & WS_MAXIMIZE)) SwpFlags |= SWP_STATECHANGED; + RECTL_vSetRect(NewPos, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, + //wpl.ptMaxPosition.x + Size.x, wpl.ptMaxPosition.y + Size.y); + Size.x, Size.y); + break; + } + + case SW_SHOWNOACTIVATE: + Wnd->InternalPos.flags &= ~WPF_RESTORETOMAXIMIZED; + /* fall through */ + case SW_SHOWNORMAL: + case SW_RESTORE: + case SW_SHOWDEFAULT: /* FIXME: should have its own handler */ + { + //ERR("MinMaximize Restore\n"); + old_style = IntSetStyle( Wnd, 0, WS_MINIMIZE | WS_MAXIMIZE ); + if (old_style & WS_MINIMIZE) + { + IntShowOwnedPopups(Wnd, TRUE); + + if (Wnd->InternalPos.flags & WPF_RESTORETOMAXIMIZED) + { + co_WinPosGetMinMaxInfo(Wnd, &Size, &wpl.ptMaxPosition, NULL, NULL); + IntSetStyle( Wnd, WS_MAXIMIZE, 0 ); + SwpFlags |= SWP_STATECHANGED; + RECTL_vSetRect(NewPos, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, + wpl.ptMaxPosition.x + Size.x, wpl.ptMaxPosition.y + Size.y); + break; + } + else + { + *NewPos = wpl.rcNormalPosition; + NewPos->right -= NewPos->left; + NewPos->bottom -= NewPos->top; + break; + } + } + else + { + if (!(old_style & WS_MAXIMIZE)) + { + break; + } + SwpFlags |= SWP_STATECHANGED; + Wnd->InternalPos.flags &= ~WPF_RESTORETOMAXIMIZED; + *NewPos = wpl.rcNormalPosition; + NewPos->right -= NewPos->left; + NewPos->bottom -= NewPos->top; + break; + } + } + } + return SwpFlags; +} + +/* + ShowWindow does not set SWP_FRAMECHANGED!!! Fix wine msg test_SetParent:WmSetParentSeq_2:23 wParam bits! + */ BOOLEAN FASTCALL co_WinPosShowWindow(PWND Wnd, INT Cmd) { @@ -2212,15 +2399,52 @@ co_WinPosShowWindow(PWND Wnd, INT Cmd) LONG style; PWND Parent; PTHREADINFO pti; - // HRGN VisibleRgn; - //ERR("co_WinPosShowWindow START\n"); + //HRGN VisibleRgn; BOOL ShowOwned = FALSE; + BOOL FirstTime = FALSE; ASSERT_REFS_CO(Wnd); - + //KeRosDumpStackFrames(NULL, 20); pti = PsGetCurrentThreadWin32Thread(); WasVisible = (Wnd->style & WS_VISIBLE) != 0; style = Wnd->style; + TRACE("co_WinPosShowWindow START hwnd %p Cmd %d usicmd %u\n", + Wnd->head.h, Cmd, pti->ppi->usi.wShowWindow); + + if ( pti->ppi->usi.dwFlags & STARTF_USESHOWWINDOW ) + { + if ((Wnd->style & (WS_POPUP|WS_CHILD)) != WS_CHILD) + { + if ((Wnd->style & WS_CAPTION) == WS_CAPTION) + { + if (Wnd->spwndOwner == NULL) + { + if ( Cmd == SW_SHOWNORMAL || Cmd == SW_SHOW) + { + Cmd = SW_SHOWDEFAULT; + } + FirstTime = TRUE; + TRACE("co_WPSW FT 1\n"); + } + } + } + } + + if ( Cmd == SW_SHOWDEFAULT ) + { + if ( pti->ppi->usi.dwFlags & STARTF_USESHOWWINDOW ) + { + Cmd = pti->ppi->usi.wShowWindow; + FirstTime = TRUE; + TRACE("co_WPSW FT 2\n"); + } + } + + if (FirstTime) + { + pti->ppi->usi.dwFlags &= ~(STARTF_USEPOSITION|STARTF_USESIZE|STARTF_USESHOWWINDOW); + } + switch (Cmd) { case SW_HIDE: @@ -2228,7 +2452,7 @@ co_WinPosShowWindow(PWND Wnd, INT Cmd) if (!WasVisible) { //ERR("co_WinPosShowWindow Exit Bad\n"); - return(FALSE); + return FALSE; } Swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE; if (Wnd != pti->MessageQueue->spwndActive) @@ -2249,7 +2473,6 @@ co_WinPosShowWindow(PWND Wnd, INT Cmd) if (!(style & WS_MINIMIZE)) { IntShowOwnedPopups(Wnd, FALSE ); - // Fix wine Win test_SetFocus todo #1 & #2, if (Cmd == SW_SHOWMINIMIZED) { @@ -2260,18 +2483,13 @@ co_WinPosShowWindow(PWND Wnd, INT Cmd) co_UserSetFocus(0); } - Swp |= co_WinPosMinMaximize(Wnd, Cmd, &NewPos) | - SWP_FRAMECHANGED; + Swp |= co_WinPosMinMaximize(Wnd, Cmd, &NewPos); EventMsg = EVENT_SYSTEM_MINIMIZESTART; } else { - if (!WasVisible) - { - Swp |= SWP_FRAMECHANGED; - } - else //// + if (WasVisible) { //ERR("co_WinPosShowWindow Exit Good\n"); return TRUE; @@ -2288,18 +2506,13 @@ co_WinPosShowWindow(PWND Wnd, INT Cmd) { ShowOwned = TRUE; - Swp |= co_WinPosMinMaximize(Wnd, SW_MAXIMIZE, &NewPos) | - SWP_FRAMECHANGED; + Swp |= co_WinPosMinMaximize(Wnd, SW_MAXIMIZE, &NewPos); EventMsg = EVENT_SYSTEM_MINIMIZEEND; } else { - if (!WasVisible) - { - Swp |= SWP_FRAMECHANGED; - } - else //// + if (WasVisible) { //ERR("co_WinPosShowWindow Exit Good 1\n"); return TRUE; @@ -2329,18 +2542,12 @@ co_WinPosShowWindow(PWND Wnd, INT Cmd) if (!WasVisible) Swp |= SWP_SHOWWINDOW; if (style & (WS_MINIMIZE | WS_MAXIMIZE)) { - Swp |= co_WinPosMinMaximize(Wnd, Cmd, &NewPos) | - SWP_FRAMECHANGED; - + Swp |= co_WinPosMinMaximize(Wnd, Cmd, &NewPos); if (style & WS_MINIMIZE) EventMsg = EVENT_SYSTEM_MINIMIZEEND; } else { - if (!WasVisible) - { - Swp |= SWP_FRAMECHANGED; - } - else //// + if (WasVisible) { //ERR("co_WinPosShowWindow Exit Good 3\n"); return TRUE; @@ -2363,8 +2570,10 @@ co_WinPosShowWindow(PWND Wnd, INT Cmd) if ((ShowFlag != WasVisible || Cmd == SW_SHOWNA) && Cmd != SW_SHOWMAXIMIZED && !(Swp & SWP_STATECHANGED)) { co_IntSendMessageNoWait(Wnd->head.h, WM_SHOWWINDOW, ShowFlag, 0); - if (!(Wnd->state2 & WNDS2_WIN31COMPAT)) +#if 0 // Fix wine msg test_SetParent:WmSetParentSeq_1:2 + if (!(Wnd->state2 & WNDS2_WIN31COMPAT)) // <------------- XP sets this bit! co_IntSendMessageNoWait(Wnd->head.h, WM_SETVISIBLE, ShowFlag, 0); +#endif if (!VerifyWnd(Wnd)) return WasVisible; } @@ -2377,28 +2586,30 @@ co_WinPosShowWindow(PWND Wnd, INT Cmd) Swp |= SWP_NOACTIVATE | SWP_NOZORDER; } -#if 0 // Explorer issues with common controls. Someone does not know how CS_SAVEBITS works. +#if 0 // Explorer issues with common controls? Someone does not know how CS_SAVEBITS works. + // Breaks startup and shutdown active window... if ((Wnd->style & (WS_POPUP|WS_CHILD)) != WS_CHILD && Wnd->pcls->style & CS_SAVEBITS && ((Cmd == SW_SHOW) || (Cmd == SW_NORMAL))) { ERR("WinPosShowWindow Set active\n"); - UserSetActiveWindow(Wnd); + //UserSetActiveWindow(Wnd); + co_IntSetForegroundWindow(Wnd); // HACK Swp |= SWP_NOACTIVATE | SWP_NOZORDER; } #endif if (IsChildVisible(Wnd) || Swp & SWP_STATECHANGED) { - TRACE("Child is Vis %s or State changed %s. ShowFlag %s\n", + TRACE("Child is Vis %s or State changed %s. ShowFlag %s Swp %04x\n", (IsChildVisible(Wnd) ? "TRUE" : "FALSE"), (Swp & SWP_STATECHANGED ? "TRUE" : "FALSE"), - (ShowFlag ? "TRUE" : "FALSE")); + (ShowFlag ? "TRUE" : "FALSE"),LOWORD(Swp)); co_WinPosSetWindowPos( Wnd, 0 != (Wnd->ExStyle & WS_EX_TOPMOST) ? HWND_TOPMOST : HWND_TOP, NewPos.left, NewPos.top, - NewPos.right, //NewPos.right - NewPos.left, - NewPos.bottom, //NewPos.bottom - NewPos.top, + NewPos.right, // NewPos.right - NewPos.left, when minimized and restore, the window becomes smaller. + NewPos.bottom,// NewPos.bottom - NewPos.top, LOWORD(Swp)); } else @@ -2417,22 +2628,29 @@ co_WinPosShowWindow(PWND Wnd, INT Cmd) { if ( Wnd == pti->MessageQueue->spwndActive && pti->MessageQueue == IntGetFocusMessageQueue() ) { - if ( Wnd->spwndParent == UserGetDesktopWindow()) + if (UserIsDesktopWindow(Wnd->spwndParent)) { - if(!ActivateOtherWindowMin(Wnd)) + if (!ActivateOtherWindowMin(Wnd)) + { co_WinPosActivateOtherWindow(Wnd); + } } else + { co_WinPosActivateOtherWindow(Wnd); + } } /* Revert focus to parent */ if (Wnd == pti->MessageQueue->spwndFocus) { Parent = Wnd->spwndParent; - if (Wnd->spwndParent == UserGetDesktopWindow()) Parent = 0; + if (UserIsDesktopWindow(Wnd->spwndParent)) + Parent = 0; co_UserSetFocus(Parent); } + // Hide, just return. + if (Cmd == SW_HIDE) return WasVisible; } /* FIXME: Check for window destruction. */ @@ -2448,45 +2666,57 @@ co_WinPosShowWindow(PWND Wnd, INT Cmd) { co_UserSetFocus(Wnd); // Fix wine Win test_SetFocus todo #3, - if (!(style & WS_CHILD)) co_IntSendMessageNoWait(UserHMGetHandle(Wnd), WM_ACTIVATE, WA_ACTIVE, 0); + if (!(style & WS_CHILD)) co_IntSendMessage(UserHMGetHandle(Wnd), WM_ACTIVATE, WA_ACTIVE, 0); } //ERR("co_WinPosShowWindow EXIT\n"); - return(WasVisible); + return WasVisible; } -static -PWND FASTCALL +static PWND co_WinPosSearchChildren( - PWND ScopeWin, - POINT *Point, - USHORT *HitTest, - BOOL Ignore + IN PWND ScopeWin, + IN POINT *Point, + IN OUT USHORT *HitTest, + IN BOOL Ignore ) { - PWND pwndChild; HWND *List, *phWnd; + PWND pwndChild = NULL; + /* not visible */ if (!(ScopeWin->style & WS_VISIBLE)) { return NULL; } - if (!Ignore && (ScopeWin->style & WS_DISABLED)) + /* not in window or in window region */ + if (!IntPtInWindow(ScopeWin, Point->x, Point->y)) { return NULL; } - if (!IntPtInWindow(ScopeWin, Point->x, Point->y)) + /* transparent */ + if ((ScopeWin->ExStyle & (WS_EX_LAYERED|WS_EX_TRANSPARENT)) == (WS_EX_LAYERED|WS_EX_TRANSPARENT)) { return NULL; } - UserReferenceObject(ScopeWin); + if (!Ignore && (ScopeWin->style & WS_DISABLED)) + { /* disabled child */ + if ((ScopeWin->style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return NULL; + /* process the hit error */ + *HitTest = HTERROR; + return ScopeWin; + } - if ( RECTL_bPointInRect(&ScopeWin->rcClient, Point->x, Point->y) ) + /* not minimized and check if point is inside the window */ + if (!(ScopeWin->style & WS_MINIMIZE) && + RECTL_bPointInRect(&ScopeWin->rcClient, Point->x, Point->y) ) { + UserReferenceObject(ScopeWin); + List = IntWinListChildren(ScopeWin); - if(List) + if (List) { for (phWnd = List; *phWnd; ++phWnd) { @@ -2497,7 +2727,7 @@ co_WinPosSearchChildren( pwndChild = co_WinPosSearchChildren(pwndChild, Point, HitTest, Ignore); - if(pwndChild != NULL) + if (pwndChild != NULL) { /* We found a window. Don't send any more WM_NCHITTEST messages */ ExFreePoolWithTag(List, USERTAG_WINDOWLIST); @@ -2507,26 +2737,32 @@ co_WinPosSearchChildren( } ExFreePoolWithTag(List, USERTAG_WINDOWLIST); } + UserDereferenceObject(ScopeWin); } if (ScopeWin->head.pti == PsGetCurrentThreadWin32Thread()) { - *HitTest = (USHORT)co_IntSendMessage(ScopeWin->head.h, WM_NCHITTEST, 0, - MAKELONG(Point->x, Point->y)); + *HitTest = (USHORT)co_IntSendMessage(ScopeWin->head.h, WM_NCHITTEST, 0, MAKELONG(Point->x, Point->y)); + if ((*HitTest) == (USHORT)HTTRANSPARENT) { - UserDereferenceObject(ScopeWin); return NULL; } } else - *HitTest = HTCLIENT; + { + if (*HitTest == HTNOWHERE && pwndChild == NULL) *HitTest = HTCLIENT; + } return ScopeWin; } -PWND FASTCALL -co_WinPosWindowFromPoint(PWND ScopeWin, POINT *WinPoint, USHORT* HitTest, BOOL Ignore) +PWND APIENTRY +co_WinPosWindowFromPoint( + IN PWND ScopeWin, + IN POINT *WinPoint, + IN OUT USHORT* HitTest, + IN BOOL Ignore) { PWND Window; POINT Point = *WinPoint; @@ -2564,7 +2800,7 @@ IntRealChildWindowFromPoint(PWND Parent, LONG x, LONG y) Pt.x = x; Pt.y = y; - if (Parent != UserGetDesktopWindow()) + if (!UserIsDesktopWindow(Parent)) { Pt.x += Parent->rcClient.left; Pt.y += Parent->rcClient.top; @@ -2606,7 +2842,7 @@ IntChildWindowFromPointEx(PWND Parent, LONG x, LONG y, UINT uiFlags) Pt.x = x; Pt.y = y; - if (Parent != UserGetDesktopWindow()) + if (!UserIsDesktopWindow(Parent)) { if (Parent->ExStyle & WS_EX_LAYOUTRTL) Pt.x = Parent->rcClient.right - Pt.x; @@ -2870,9 +3106,7 @@ NtUserDeferWindowPos(HDWP WinPosInfo, } pWnd = UserGetWindowObject(Wnd); - if ( !pWnd || // FIXME: - pWnd == UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP - pWnd == UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND + if (!pWnd || UserIsDesktopWindow(pWnd) || UserIsMessageWindow(pWnd)) { goto Exit; } @@ -2883,9 +3117,7 @@ NtUserDeferWindowPos(HDWP WinPosInfo, WndInsertAfter != HWND_NOTOPMOST ) { pWndIA = UserGetWindowObject(WndInsertAfter); - if ( !pWndIA || - pWndIA == UserGetDesktopWindow() || - pWndIA == UserGetMessageWindow() ) + if (!pWndIA || UserIsDesktopWindow(pWndIA) || UserIsMessageWindow(pWndIA)) { goto Exit; } @@ -2994,20 +3226,18 @@ NtUserGetWindowPlacement(HWND hWnd, } Status = MmCopyFromCaller(&Safepl, lpwndpl, sizeof(WINDOWPLACEMENT)); - if(!NT_SUCCESS(Status)) + if (!NT_SUCCESS(Status)) { SetLastNtError(Status); RETURN( FALSE); } - if(Safepl.length != sizeof(WINDOWPLACEMENT)) - { - RETURN( FALSE); - } + + Safepl.length = sizeof(WINDOWPLACEMENT); IntGetWindowPlacement(Wnd, &Safepl); Status = MmCopyToCaller(lpwndpl, &Safepl, sizeof(WINDOWPLACEMENT)); - if(!NT_SUCCESS(Status)) + if (!NT_SUCCESS(Status)) { SetLastNtError(Status); RETURN( FALSE); @@ -3034,9 +3264,7 @@ NtUserMinMaximize( UserEnterExclusive(); pWnd = UserGetWindowObject(hWnd); - if ( !pWnd || // FIXME: - pWnd == UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP - pWnd == UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND + if (!pWnd || UserIsDesktopWindow(pWnd) || UserIsMessageWindow(pWnd)) { goto Exit; } @@ -3115,22 +3343,20 @@ NtUserSetWindowPos( TRACE("Enter NtUserSetWindowPos\n"); UserEnterExclusive(); - if (!(Window = UserGetWindowObject(hWnd)) || // FIXME: - Window == UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP - Window == UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND + if (!(Window = UserGetWindowObject(hWnd)) || + UserIsDesktopWindow(Window) || UserIsMessageWindow(Window)) { ERR("NtUserSetWindowPos bad window handle!\n"); RETURN(FALSE); } - if ( hWndInsertAfter && + if ( hWndInsertAfter != HWND_TOP && hWndInsertAfter != HWND_BOTTOM && hWndInsertAfter != HWND_TOPMOST && hWndInsertAfter != HWND_NOTOPMOST ) { if (!(pWndIA = UserGetWindowObject(hWndInsertAfter)) || - pWndIA == UserGetDesktopWindow() || - pWndIA == UserGetMessageWindow() ) + UserIsDesktopWindow(pWndIA) || UserIsMessageWindow(pWndIA)) { ERR("NtUserSetWindowPos bad insert window handle!\n"); RETURN(FALSE); @@ -3174,7 +3400,7 @@ NtUserSetWindowRgn( HRGN hRgn, BOOL bRedraw) { - HRGN hrgnCopy; + HRGN hrgnCopy = NULL; PWND Window; INT flags = (SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE); BOOLEAN Ret = FALSE; @@ -3183,9 +3409,8 @@ NtUserSetWindowRgn( TRACE("Enter NtUserSetWindowRgn\n"); UserEnterExclusive(); - if (!(Window = UserGetWindowObject(hWnd)) || // FIXME: - Window == UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP - Window == UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND + if (!(Window = UserGetWindowObject(hWnd)) || + UserIsDesktopWindow(Window) || UserIsMessageWindow(Window)) { RETURN( 0); } @@ -3194,7 +3419,7 @@ NtUserSetWindowRgn( { if (GreIsHandleValid(hRgn)) { - hrgnCopy = IntSysCreateRectRgn(0, 0, 0, 0); + hrgnCopy = NtGdiCreateRectRgn(0, 0, 0, 0); /* The coordinates of a window's window region are relative to the upper-left corner of the window, not the client area of the window. */ NtGdiCombineRgn( hrgnCopy, hRgn, 0, RGN_COPY); @@ -3202,25 +3427,17 @@ NtUserSetWindowRgn( else RETURN( 0); } - else - { - hrgnCopy = NULL; - } - if (Window->hrgnClip) + //// HACK 1 : Work around the lack of supporting DeferWindowPos. + if (hrgnCopy) { - /* Delete no longer needed region handle */ - IntGdiSetRegionOwner(Window->hrgnClip, GDI_OBJ_HMGR_POWNED); - GreDeleteObject(Window->hrgnClip); + Window->hrgnNewFrame = hrgnCopy; // Should be PSMWP->acvr->hrgnClip } - - if (hrgnCopy) + else { - /* Set public ownership */ - IntGdiSetRegionOwner(hrgnCopy, GDI_OBJ_HMGR_PUBLIC); + Window->hrgnNewFrame = HRGN_WINDOW; } - Window->hrgnClip = hrgnCopy; - + //// HACK 2 Ret = co_WinPosSetWindowPos(Window, HWND_TOP, 0, 0, 0, 0, bRedraw ? flags : (flags|SWP_NOREDRAW) ); RETURN( (INT)Ret); @@ -3253,8 +3470,7 @@ NtUserSetInternalWindowPos( UserEnterExclusive(); if (!(Wnd = UserGetWindowObject(hwnd)) || // FIXME: - Wnd == UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP - Wnd == UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND + UserIsDesktopWindow(Wnd) || UserIsMessageWindow(Wnd)) { RETURN( FALSE); } @@ -3322,9 +3538,8 @@ NtUserSetWindowPlacement(HWND hWnd, TRACE("Enter NtUserSetWindowPlacement\n"); UserEnterExclusive(); - if (!(Wnd = UserGetWindowObject(hWnd)) || // FIXME: - Wnd == UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP - Wnd == UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND + if (!(Wnd = UserGetWindowObject(hWnd)) || + UserIsDesktopWindow(Wnd) || UserIsMessageWindow(Wnd)) { RETURN( FALSE); } @@ -3373,9 +3588,8 @@ NtUserShowWindowAsync(HWND hWnd, LONG nCmdShow) TRACE("Enter NtUserShowWindowAsync\n"); UserEnterExclusive(); - if (!(Window = UserGetWindowObject(hWnd)) || // FIXME: - Window == UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP - Window == UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND + if (!(Window = UserGetWindowObject(hWnd)) || + UserIsDesktopWindow(Window) || UserIsMessageWindow(Window)) { RETURN(FALSE); } @@ -3410,12 +3624,11 @@ NtUserShowWindow(HWND hWnd, LONG nCmdShow) DECLARE_RETURN(BOOL); USER_REFERENCE_ENTRY Ref; - TRACE("Enter NtUserShowWindow\n"); + TRACE("Enter NtUserShowWindow hWnd %p SW_ %d\n",hWnd, nCmdShow); UserEnterExclusive(); - if (!(Window = UserGetWindowObject(hWnd)) || // FIXME: - Window == UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP - Window == UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND + if (!(Window = UserGetWindowObject(hWnd)) || + UserIsDesktopWindow(Window) || UserIsMessageWindow(Window)) { RETURN(FALSE); } @@ -3480,7 +3693,6 @@ NtUserWindowFromPoint(LONG X, LONG Y) RETURN( NULL); CLEANUP: - if (Window) UserDereferenceObject(Window); if (DesktopWindow) UserDerefObjectCo(DesktopWindow); TRACE("Leave NtUserWindowFromPoint, ret=%p\n", _ret_);