-/* $Id: winpos.c,v 1.9 2003/05/18 07:51:41 gvg Exp $
+/*
+ * ReactOS W32 Subsystem
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id: winpos.c,v 1.83 2004/01/21 18:39:24 navaraf Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: subsys/win32k/ntuser/window.c
* PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
* REVISION HISTORY:
- * 06-06-2001 CSH Created
+ * 06-06-2001 CSH NtGdid
*/
/* INCLUDES ******************************************************************/
#include <ddk/ntddk.h>
+#include <internal/safe.h>
#include <win32k/win32k.h>
#include <include/object.h>
#include <include/guicheck.h>
#include <include/class.h>
#include <include/error.h>
#include <include/winsta.h>
-#include <windows.h>
+#include <include/desktop.h>
#include <include/winpos.h>
#include <include/rect.h>
#include <include/callback.h>
#include <include/painting.h>
+#include <include/dce.h>
+#include <include/vis.h>
+#include <include/focus.h>
#define NDEBUG
#include <debug.h>
#define MINMAX_NOSWP (0x00010000)
+#define SWP_EX_NOCOPY 0x0001
#define SWP_EX_PAINTSELF 0x0002
-ATOM AtomInternalPos = NULL;
+#define SWP_AGG_NOGEOMETRYCHANGE \
+ (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
+#define SWP_AGG_NOPOSCHANGE \
+ (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
+#define SWP_AGG_STATUSFLAGS \
+ (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
/* FUNCTIONS *****************************************************************/
#define HAS_DLGFRAME(Style, ExStyle) \
- (((ExStyle) & WS_EX_DLGMODALFRAME) || \
- (((Style) & WS_DLGFRAME) && !((Style) & WS_BORDER)))
+ (((ExStyle) & WS_EX_DLGMODALFRAME) || \
+ (((Style) & WS_DLGFRAME) && (!((Style) & WS_THICKFRAME))))
#define HAS_THICKFRAME(Style, ExStyle) \
- (((Style) & WS_THICKFRAME) && \
- !((Style) & (WS_DLGFRAME | WS_BORDER)) == WS_DLGFRAME)
+ (((Style) & WS_THICKFRAME) && \
+ (!(((Style) & (WS_DLGFRAME | WS_BORDER)) == WS_DLGFRAME)))
-VOID
-WinPosSetupInternalPos(VOID)
-{
- AtomInternalPos = NtAddAtom(L"SysIP", (ATOM*)(PULONG)&AtomInternalPos);
-}
+#define HAS_THINFRAME(Style, ExStyle) \
+ (((Style) & WS_BORDER) || (!((Style) & (WS_CHILD | WS_POPUP))))
-BOOL STDCALL
-NtUserGetClientOrigin(HWND hWnd, LPPOINT Point)
+BOOL FASTCALL
+IntGetClientOrigin(HWND hWnd, LPPOINT Point)
{
PWINDOW_OBJECT WindowObject;
-
- WindowObject = W32kGetWindowObject(hWnd);
+
+ WindowObject = IntGetWindowObject(hWnd);
if (WindowObject == NULL)
{
Point->x = Point->y = 0;
- return(TRUE);
+ return FALSE;
}
Point->x = WindowObject->ClientRect.left;
Point->y = WindowObject->ClientRect.top;
- return(TRUE);
+
+ IntReleaseWindowObject(WindowObject);
+ return TRUE;
}
-BOOL
-WinPosActivateOtherWindow(PWINDOW_OBJECT Window)
+BOOL STDCALL
+NtUserGetClientOrigin(HWND hWnd, LPPOINT Point)
{
+ BOOL Ret;
+ POINT pt;
+ NTSTATUS Status;
+
+ Ret = IntGetClientOrigin(hWnd, &pt);
+
+ Status = MmCopyToCaller(Point, &pt, sizeof(POINT));
+ if(!NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ return FALSE;
+ }
+
+ return Ret;
}
-POINT STATIC
-WinPosFindIconPos(HWND hWnd, POINT Pos)
+/*******************************************************************
+ * WinPosActivateOtherWindow
+ *
+ * Activates window other than pWnd.
+ */
+VOID FASTCALL
+WinPosActivateOtherWindow(PWINDOW_OBJECT Window)
{
+ PWINDOW_OBJECT Child;
+ PWINDOW_OBJECT TabooWindow = Window;
+
+ for (;;)
+ {
+ if (NULL == Window || IntIsDesktopWindow(Window))
+ {
+ IntSetFocusMessageQueue(NULL);
+ return;
+ }
+ Window = Window->Parent;
+ ExAcquireFastMutex(&(Window->ChildrenListLock));
+ Child = Window->FirstChild;
+ while (NULL != Child)
+ {
+ if (Child != TabooWindow)
+ {
+ ExReleaseFastMutex(&(Window->ChildrenListLock));
+ if (IntSetForegroundWindow(Child))
+ {
+ return;
+ }
+ ExAcquireFastMutex(&(Window->ChildrenListLock));
+ }
+ Child = Child->NextSibling;
+ }
+ ExReleaseFastMutex(&(Window->ChildrenListLock));
+ }
}
-HWND STATIC
-WinPosCreateIconTitle(PWINDOW_OBJECT WindowObject)
+VOID STATIC FASTCALL
+WinPosFindIconPos(HWND hWnd, POINT *Pos)
{
- return(NULL);
+ /* FIXME */
}
-BOOL STATIC
-WinPosShowIconTitle(PWINDOW_OBJECT WindowObject, BOOL Show)
+PINTERNALPOS FASTCALL
+WinPosInitInternalPos(PWINDOW_OBJECT WindowObject, POINT pt, PRECT RestoreRect)
{
- PINTERNALPOS InternalPos = NtUserGetProp(WindowObject->Self,
- AtomInternalPos);
- PWINDOW_OBJECT IconWindow;
- NTSTATUS Status;
-
- if (InternalPos)
+ INT XInc, YInc;
+
+ if (WindowObject->InternalPos == NULL)
{
- HWND hWnd = InternalPos->IconTitle;
-
- if (hWnd == NULL)
- {
- hWnd = WinPosCreateIconTitle(WindowObject);
- }
- if (Show)
- {
- Status =
- ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation->
- HandleTable,
- hWnd,
- otWindow,
- (PVOID*)&IconWindow);
- if (NT_SUCCESS(Status))
- {
- if (!(IconWindow->Style & WS_VISIBLE))
- {
- NtUserSendMessage(hWnd, WM_SHOWWINDOW, TRUE, 0);
- WinPosSetWindowPos(hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE |
- SWP_NOMOVE | SWP_NOACTIVATE |
- SWP_NOZORDER | SWP_SHOWWINDOW);
- }
- ObmDereferenceObject(IconWindow);
- }
- }
+ RECT WorkArea;
+ PDESKTOP_OBJECT Desktop = PsGetWin32Thread()->Desktop; /* Or rather get it from the window? */
+
+ if(IntIsDesktopWindow(WindowObject->Parent))
+ WorkArea = *IntGetDesktopWorkArea(Desktop);
else
+ WorkArea = WindowObject->Parent->ClientRect;
+
+ WindowObject->InternalPos = ExAllocatePool(NonPagedPool, sizeof(INTERNALPOS));
+ if(!WindowObject->InternalPos)
+ {
+ DPRINT1("Failed to allocate INTERNALPOS structure for window 0x%x\n", WindowObject->Self);
+ return NULL;
+ }
+ WindowObject->InternalPos->NormalRect = WindowObject->WindowRect;
+ if (HAS_DLGFRAME(WindowObject->Style, WindowObject->ExStyle) && !(WindowObject->Style & WS_MINIMIZE))
+ {
+ XInc = NtUserGetSystemMetrics(SM_CXDLGFRAME);
+ YInc = NtUserGetSystemMetrics(SM_CYDLGFRAME);
+ }
+ else
+ {
+ XInc = YInc = 0;
+ if (HAS_THICKFRAME(WindowObject->Style, WindowObject->ExStyle)&& !(WindowObject->Style & WS_MINIMIZE))
+ {
+ XInc += NtUserGetSystemMetrics(SM_CXFRAME);
+ YInc += NtUserGetSystemMetrics(SM_CYFRAME);
+ }
+ else if (HAS_THINFRAME(WindowObject->Style, WindowObject->ExStyle))
{
- WinPosShowWindow(hWnd, SW_HIDE);
+ XInc += NtUserGetSystemMetrics(SM_CXBORDER);
+ YInc += NtUserGetSystemMetrics(SM_CYBORDER);
}
- }
- return(FALSE);
-}
-
-PINTERNALPOS STATIC
-WinPosInitInternalPos(PWINDOW_OBJECT WindowObject, POINT pt, PRECT RestoreRect)
-{
- PINTERNALPOS InternalPos = NtUserGetProp(WindowObject->Self,
- AtomInternalPos);
- if (InternalPos == NULL)
- {
- InternalPos =
- ExAllocatePool(NonPagedPool, sizeof(INTERNALPOS));
- NtUserSetProp(WindowObject->Self, AtomInternalPos, InternalPos);
- InternalPos->IconTitle = 0;
- InternalPos->NormalRect = WindowObject->WindowRect;
- InternalPos->IconPos.x = InternalPos->MaxPos.x = 0xFFFFFFFF;
- InternalPos->IconPos.y = InternalPos->MaxPos.y = 0xFFFFFFFF;
+ }
+ WindowObject->InternalPos->MaxPos.x = WorkArea.left - XInc;
+ WindowObject->InternalPos->MaxPos.y = WorkArea.top - YInc;
+ WindowObject->InternalPos->IconPos.x = WorkArea.left;
+ WindowObject->InternalPos->IconPos.y = WorkArea.bottom - NtUserGetSystemMetrics(SM_CYMINIMIZED);
}
if (WindowObject->Style & WS_MINIMIZE)
{
- InternalPos->IconPos = pt;
+ WindowObject->InternalPos->IconPos = pt;
}
else if (WindowObject->Style & WS_MAXIMIZE)
{
- InternalPos->MaxPos = pt;
+ WindowObject->InternalPos->MaxPos = pt;
}
else if (RestoreRect != NULL)
{
- InternalPos->NormalRect = *RestoreRect;
+ WindowObject->InternalPos->NormalRect = *RestoreRect;
}
- return(InternalPos);
+ return(WindowObject->InternalPos);
}
-UINT
+UINT FASTCALL
WinPosMinMaximize(PWINDOW_OBJECT WindowObject, UINT ShowFlag, RECT* NewPos)
{
POINT Size;
{
if (WindowObject->Style & WS_MINIMIZE)
{
- if (!NtUserSendMessage(WindowObject->Self, WM_QUERYOPEN, 0, 0))
+ if (!IntSendMessage(WindowObject->Self, WM_QUERYOPEN, 0, 0))
{
return(SWP_NOSIZE | SWP_NOMOVE);
}
}
else
{
- WindowObject->Style &= ~WINDOWOBJECT_RESTOREMAX;
+ WindowObject->Flags &= ~WINDOWOBJECT_RESTOREMAX;
}
+ IntRedrawWindow(WindowObject, NULL, 0, RDW_VALIDATE | RDW_NOERASE |
+ RDW_NOINTERNALPAINT);
WindowObject->Style |= WS_MINIMIZE;
- InternalPos->IconPos = WinPosFindIconPos(WindowObject,
- InternalPos->IconPos);
- W32kSetRect(NewPos, InternalPos->IconPos.x, InternalPos->IconPos.y,
- NtUserGetSystemMetrics(SM_CXICON),
- NtUserGetSystemMetrics(SM_CYICON));
+ WinPosFindIconPos(WindowObject, &InternalPos->IconPos);
+ NtGdiSetRect(NewPos, InternalPos->IconPos.x, InternalPos->IconPos.y,
+ NtUserGetSystemMetrics(SM_CXMINIMIZED),
+ NtUserGetSystemMetrics(SM_CYMINIMIZED));
SwpFlags |= SWP_NOCOPYBITS;
break;
}
{
WinPosGetMinMaxInfo(WindowObject, &Size, &InternalPos->MaxPos,
NULL, NULL);
+ DPRINT1("Maximize: %d,%d %dx%d\n",
+ InternalPos->MaxPos.x, InternalPos->MaxPos.y, Size.x, Size.y);
if (WindowObject->Style & WS_MINIMIZE)
{
- WinPosShowIconTitle(WindowObject, FALSE);
WindowObject->Style &= ~WS_MINIMIZE;
}
- WindowObject->Style |= WS_MINIMIZE;
- W32kSetRect(NewPos, InternalPos->MaxPos.x, InternalPos->MaxPos.y,
+ WindowObject->Style |= WS_MAXIMIZE;
+ NtGdiSetRect(NewPos, InternalPos->MaxPos.x, InternalPos->MaxPos.y,
Size.x, Size.y);
break;
}
if (WindowObject->Style & WS_MINIMIZE)
{
WindowObject->Style &= ~WS_MINIMIZE;
- WinPosShowIconTitle(WindowObject, FALSE);
if (WindowObject->Flags & WINDOWOBJECT_RESTOREMAX)
{
WinPosGetMinMaxInfo(WindowObject, &Size,
&InternalPos->MaxPos, NULL, NULL);
WindowObject->Style |= WS_MAXIMIZE;
- W32kSetRect(NewPos, InternalPos->MaxPos.x,
+ NtGdiSetRect(NewPos, InternalPos->MaxPos.x,
InternalPos->MaxPos.y, Size.x, Size.y);
break;
}
+ else
+ {
+ *NewPos = InternalPos->NormalRect;
+ NewPos->right -= NewPos->left;
+ NewPos->bottom -= NewPos->top;
+ break;
+ }
}
else
{
if (!(WindowObject->Style & WS_MAXIMIZE))
{
- return(-1);
+ return 0;
}
- else
- {
- WindowObject->Style &= ~WS_MAXIMIZE;
- }
+ WindowObject->Style &= ~WS_MAXIMIZE;
*NewPos = InternalPos->NormalRect;
NewPos->right -= NewPos->left;
NewPos->bottom -= NewPos->top;
return(SwpFlags);
}
-UINT
-WinPosGetMinMaxInfo(PWINDOW_OBJECT Window, POINT* MaxSize, POINT* MaxPos,
- POINT* MinTrack, POINT* MaxTrack)
+VOID FASTCALL
+WinPosFillMinMaxInfoStruct(PWINDOW_OBJECT Window, MINMAXINFO *Info)
{
- MINMAXINFO MinMax;
INT XInc, YInc;
- INTERNALPOS* Pos;
-
+ RECT WorkArea;
+ PDESKTOP_OBJECT Desktop = PsGetWin32Thread()->Desktop; /* Or rather get it from the window? */
+
+ WorkArea = *IntGetDesktopWorkArea(Desktop);
+
/* Get default values. */
- MinMax.ptMaxSize.x = NtUserGetSystemMetrics(SM_CXSCREEN);
- MinMax.ptMaxSize.y = NtUserGetSystemMetrics(SM_CYSCREEN);
- MinMax.ptMinTrackSize.x = NtUserGetSystemMetrics(SM_CXMINTRACK);
- MinMax.ptMinTrackSize.y = NtUserGetSystemMetrics(SM_CYMINTRACK);
- MinMax.ptMaxTrackSize.x = NtUserGetSystemMetrics(SM_CXSCREEN);
- MinMax.ptMaxTrackSize.y = NtUserGetSystemMetrics(SM_CYSCREEN);
+ Info->ptMaxSize.x = WorkArea.right - WorkArea.left;
+ Info->ptMaxSize.y = WorkArea.bottom - WorkArea.top;
+ Info->ptMinTrackSize.x = NtUserGetSystemMetrics(SM_CXMINTRACK);
+ Info->ptMinTrackSize.y = NtUserGetSystemMetrics(SM_CYMINTRACK);
+ Info->ptMaxTrackSize.x = Info->ptMaxSize.x;
+ Info->ptMaxTrackSize.y = Info->ptMaxSize.y;
if (HAS_DLGFRAME(Window->Style, Window->ExStyle))
{
XInc += NtUserGetSystemMetrics(SM_CXFRAME);
YInc += NtUserGetSystemMetrics(SM_CYFRAME);
}
- if (Window->Style & WS_BORDER)
+ else if (HAS_THINFRAME(Window->Style, Window->ExStyle))
{
XInc += NtUserGetSystemMetrics(SM_CXBORDER);
YInc += NtUserGetSystemMetrics(SM_CYBORDER);
}
}
- MinMax.ptMaxSize.x += 2 * XInc;
- MinMax.ptMaxSize.y += 2 * YInc;
+ Info->ptMaxSize.x += 2 * XInc;
+ Info->ptMaxSize.y += 2 * YInc;
- Pos = NtUserGetProp(Window->Self, AtomInternalPos);
- if (Pos != NULL)
+ if (Window->InternalPos != NULL)
{
- MinMax.ptMaxPosition = Pos->MaxPos;
+ Info->ptMaxPosition = Window->InternalPos->MaxPos;
}
else
{
- MinMax.ptMaxPosition.x -= XInc;
- MinMax.ptMaxPosition.y -= YInc;
+ Info->ptMaxPosition.x -= WorkArea.left + XInc;
+ Info->ptMaxPosition.y -= WorkArea.top + YInc;
}
+}
- W32kSendMessage(Window->Self, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax, TRUE);
+UINT FASTCALL
+WinPosGetMinMaxInfo(PWINDOW_OBJECT Window, POINT* MaxSize, POINT* MaxPos,
+ POINT* MinTrack, POINT* MaxTrack)
+{
+ MINMAXINFO MinMax;
+
+ WinPosFillMinMaxInfoStruct(Window, &MinMax);
+
+ IntSendMessage(Window->Self, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax);
MinMax.ptMaxTrackSize.x = max(MinMax.ptMaxTrackSize.x,
MinMax.ptMinTrackSize.x);
if (MaxPos) *MaxPos = MinMax.ptMaxPosition;
if (MinTrack) *MinTrack = MinMax.ptMinTrackSize;
if (MaxTrack) *MaxTrack = MinMax.ptMaxTrackSize;
-}
-BOOL STATIC
-WinPosChangeActiveWindow(HWND Wnd, BOOL MouseMsg)
-{
+ return 0; //FIXME: what does it return?
}
-LONG STATIC
+LONG STATIC FASTCALL
WinPosDoNCCALCSize(PWINDOW_OBJECT Window, PWINDOWPOS WinPos,
RECT* WindowRect, RECT* ClientRect)
{
+ UINT wvrFlags = 0;
+
+ /* Send WM_NCCALCSIZE message to get new client area */
+ if ((WinPos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE)
+ {
+ NCCALCSIZE_PARAMS params;
+ WINDOWPOS winposCopy;
+
+ params.rgrc[0] = *WindowRect;
+ params.rgrc[1] = Window->WindowRect;
+ params.rgrc[2] = Window->ClientRect;
+ if (0 != (Window->Style & WS_CHILD))
+ {
+ NtGdiOffsetRect(&(params.rgrc[0]), - Window->Parent->ClientRect.left,
+ - Window->Parent->ClientRect.top);
+ NtGdiOffsetRect(&(params.rgrc[1]), - Window->Parent->ClientRect.left,
+ - Window->Parent->ClientRect.top);
+ NtGdiOffsetRect(&(params.rgrc[2]), - Window->Parent->ClientRect.left,
+ - Window->Parent->ClientRect.top);
+ }
+ params.lppos = &winposCopy;
+ winposCopy = *WinPos;
+
+ wvrFlags = IntSendMessage(Window->Self, WM_NCCALCSIZE, TRUE, (LPARAM) ¶ms);
+
+ /* If the application send back garbage, ignore it */
+ if (params.rgrc[0].left <= params.rgrc[0].right &&
+ params.rgrc[0].top <= params.rgrc[0].bottom)
+ {
+ *ClientRect = params.rgrc[0];
+ if (Window->Style & WS_CHILD)
+ {
+ NtGdiOffsetRect(ClientRect, Window->Parent->ClientRect.left,
+ Window->Parent->ClientRect.top);
+ }
+ }
+
+ /* FIXME: WVR_ALIGNxxx */
+
+ if (ClientRect->left != Window->ClientRect.left ||
+ ClientRect->top != Window->ClientRect.top)
+ {
+ WinPos->flags &= ~SWP_NOCLIENTMOVE;
+ }
+
+ if ((ClientRect->right - ClientRect->left !=
+ Window->ClientRect.right - Window->ClientRect.left) ||
+ (ClientRect->bottom - ClientRect->top !=
+ Window->ClientRect.bottom - Window->ClientRect.top))
+ {
+ WinPos->flags &= ~SWP_NOCLIENTSIZE;
+ }
+ }
+ else
+ {
+ if (! (WinPos->flags & SWP_NOMOVE)
+ && (ClientRect->left != Window->ClientRect.left ||
+ ClientRect->top != Window->ClientRect.top))
+ {
+ WinPos->flags &= ~SWP_NOCLIENTMOVE;
+ }
+ }
+
+ return wvrFlags;
}
-BOOL
+BOOL FASTCALL
WinPosDoWinPosChanging(PWINDOW_OBJECT WindowObject,
PWINDOWPOS WinPos,
PRECT WindowRect,
PRECT ClientRect)
{
+ INT X, Y;
+
if (!(WinPos->flags & SWP_NOSENDCHANGING))
{
- W32kSendWINDOWPOSCHANGINGMessage(WindowObject->Self, WinPos);
+ IntSendMessage(WindowObject->Self, WM_WINDOWPOSCHANGING, 0, (LPARAM) WinPos);
}
*WindowRect = WindowObject->WindowRect;
- *ClientRect =
- (WindowObject->Style & WS_MINIMIZE) ? WindowObject->WindowRect :
- WindowObject->ClientRect;
+ *ClientRect = WindowObject->ClientRect;
if (!(WinPos->flags & SWP_NOSIZE))
{
if (!(WinPos->flags & SWP_NOMOVE))
{
- WindowRect->left = WinPos->x;
- WindowRect->top = WinPos->y;
- WindowRect->right += WinPos->x - WindowObject->WindowRect.left;
- WindowRect->bottom += WinPos->y - WindowObject->WindowRect.top;
-
- W32kOffsetRect(ClientRect, WinPos->x - WindowObject->WindowRect.left,
- WinPos->y - WindowObject->WindowRect.top);
+ X = WinPos->x;
+ Y = WinPos->y;
+ if (0 != (WindowObject->Style & WS_CHILD))
+ {
+ X += WindowObject->Parent->ClientRect.left;
+ Y += WindowObject->Parent->ClientRect.top;
+ }
+ WindowRect->left = X;
+ WindowRect->top = Y;
+ WindowRect->right += X - WindowObject->WindowRect.left;
+ WindowRect->bottom += Y - WindowObject->WindowRect.top;
+ NtGdiOffsetRect(ClientRect,
+ X - WindowObject->WindowRect.left,
+ Y - WindowObject->WindowRect.top);
}
WinPos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
- return(TRUE);
+
+ return TRUE;
}
-BOOLEAN
-WinPosSetWindowPos(HWND Wnd, HWND WndInsertAfter, INT x, INT y, INT cx,
- INT cy, UINT flags)
+/*
+ * Fix Z order taking into account owned popups -
+ * basically we need to maintain them above the window that owns them
+ */
+HWND FASTCALL
+WinPosDoOwnedPopups(HWND hWnd, HWND hWndInsertAfter)
{
- PWINDOW_OBJECT Window;
- NTSTATUS Status;
- WINDOWPOS WinPos;
- RECT NewWindowRect;
- RECT NewClientRect;
- HRGN VisRgn = NULL;
- ULONG WvrFlags = 0;
+ HWND *List = NULL;
+ HWND Owner = NtUserGetWindow(hWnd, GW_OWNER);
+ LONG Style = NtUserGetWindowLong(hWnd, GWL_STYLE, FALSE);
+ PWINDOW_OBJECT DesktopWindow;
+ int i;
+
+ if ((Style & WS_POPUP) && Owner)
+ {
+ /* Make sure this popup stays above the owner */
+ HWND hWndLocalPrev = HWND_TOP;
+
+ if (hWndInsertAfter != HWND_TOP)
+ {
+ DesktopWindow = IntGetWindowObject(IntGetDesktopWindow());
+ List = IntWinListChildren(DesktopWindow);
+ IntReleaseWindowObject(DesktopWindow);
+ if (List != NULL)
+ {
+ for (i = 0; List[i]; i++)
+ {
+ if (List[i] == Owner) break;
+ if (List[i] != hWnd) hWndLocalPrev = List[i];
+ if (hWndLocalPrev == hWndInsertAfter) break;
+ }
+ hWndInsertAfter = hWndLocalPrev;
+ }
+ }
+ }
+ else if (Style & WS_CHILD)
+ {
+ return hWndInsertAfter;
+ }
+
+ if (!List)
+ {
+ DesktopWindow = IntGetWindowObject(IntGetDesktopWindow());
+ List = IntWinListChildren(DesktopWindow);
+ IntReleaseWindowObject(DesktopWindow);
+ }
+ if (List != NULL)
+ {
+ for (i = 0; List[i]; i++)
+ {
+ if (List[i] == hWnd)
+ break;
+ if ((NtUserGetWindowLong(List[i], GWL_STYLE, FALSE) & WS_POPUP) &&
+ NtUserGetWindow(List[i], GW_OWNER) == hWnd)
+ {
+ WinPosSetWindowPos(List[i], hWndInsertAfter, 0, 0, 0, 0,
+ SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING);
+ hWndInsertAfter = List[i];
+ }
+ }
+ ExFreePool(List);
+ }
- /* FIXME: Get current active window from active queue. */
+ return hWndInsertAfter;
+}
- /* Check if the window is for a desktop. */
- if (Wnd == PsGetWin32Thread()->Desktop->DesktopWindow)
- {
- return(FALSE);
- }
+/***********************************************************************
+ * WinPosInternalMoveWindow
+ *
+ * Update WindowRect and ClientRect of Window and all of its children
+ * We keep both WindowRect and ClientRect in screen coordinates internally
+ */
+VOID STATIC FASTCALL
+WinPosInternalMoveWindow(PWINDOW_OBJECT Window, INT MoveX, INT MoveY)
+{
+ PWINDOW_OBJECT Child;
- Status =
- ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation->HandleTable,
- Wnd,
- otWindow,
- (PVOID*)&Window);
- if (!NT_SUCCESS(Status))
- {
- return(FALSE);
- }
-
- /* Fix up the flags. */
- if (Window->Style & WS_VISIBLE)
- {
- flags &= ~SWP_SHOWWINDOW;
- }
- else
- {
- if (!(flags & SWP_SHOWWINDOW))
- {
- flags |= SWP_NOREDRAW;
- }
- flags &= ~SWP_HIDEWINDOW;
- }
+ Window->WindowRect.left += MoveX;
+ Window->WindowRect.right += MoveX;
+ Window->WindowRect.top += MoveY;
+ Window->WindowRect.bottom += MoveY;
- cx = max(cx, 0);
- cy = max(cy, 0);
+ Window->ClientRect.left += MoveX;
+ Window->ClientRect.right += MoveX;
+ Window->ClientRect.top += MoveY;
+ Window->ClientRect.bottom += MoveY;
- if ((Window->WindowRect.right - Window->WindowRect.left) == cx &&
- (Window->WindowRect.bottom - Window->WindowRect.top) == cy)
- {
- flags |= SWP_NOSIZE;
- }
- if (Window->WindowRect.left == x && Window->WindowRect.top == y)
+ ExAcquireFastMutexUnsafe(&Window->ChildrenListLock);
+ Child = Window->FirstChild;
+ while (Child)
{
- flags |= SWP_NOMOVE;
+ WinPosInternalMoveWindow(Child, MoveX, MoveY);
+ Child = Child->NextSibling;
}
- if (FALSE /* FIXME: Check if the window if already active. */)
- {
- flags |= SWP_NOACTIVATE;
- }
- else if ((Window->Style & (WS_POPUP | WS_CHILD)) != WS_CHILD)
- {
- if (!(flags & SWP_NOACTIVATE))
- {
- flags &= ~SWP_NOZORDER;
- WndInsertAfter = HWND_TOP;
- }
- }
-
- if (WndInsertAfter == HWND_TOPMOST || WndInsertAfter == HWND_NOTOPMOST)
- {
- WndInsertAfter = HWND_TOP;
- }
-
- if (WndInsertAfter != HWND_TOP && WndInsertAfter != HWND_BOTTOM)
- {
- /* FIXME: Find the window to insert after. */
- }
-
- WinPos.hwnd = Wnd;
- WinPos.hwndInsertAfter = WndInsertAfter;
- WinPos.x = x;
- WinPos.y = y;
- WinPos.cx = cx;
- WinPos.cy = cy;
- WinPos.flags = flags;
+ ExReleaseFastMutexUnsafe(&Window->ChildrenListLock);
+}
- WinPosDoWinPosChanging(Window, &WinPos, &NewWindowRect, &NewClientRect);
+/*
+ * WinPosFixupSWPFlags
+ *
+ * Fix redundant flags and values in the WINDOWPOS structure.
+ */
- if ((WinPos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) !=
- SWP_NOZORDER)
- {
- /* FIXME: SWP_DoOwnedPopups. */
- }
-
- /* FIXME: Adjust flags based on WndInsertAfter */
+BOOL FASTCALL
+WinPosFixupFlags(WINDOWPOS *WinPos, PWINDOW_OBJECT Window)
+{
+ if (Window->Style & WS_VISIBLE)
+ {
+ WinPos->flags &= ~SWP_SHOWWINDOW;
+ }
+ else
+ {
+ WinPos->flags &= ~SWP_HIDEWINDOW;
+ if (!(WinPos->flags & SWP_SHOWWINDOW))
+ WinPos->flags |= SWP_NOREDRAW;
+ }
+
+ WinPos->cx = max(WinPos->cx, 0);
+ WinPos->cy = max(WinPos->cy, 0);
+
+ /* Check for right size */
+ if (Window->WindowRect.right - Window->WindowRect.left == WinPos->cx &&
+ Window->WindowRect.bottom - Window->WindowRect.top == WinPos->cy)
+ {
+ WinPos->flags |= SWP_NOSIZE;
+ }
+
+ /* Check for right position */
+ if (Window->WindowRect.left == WinPos->x &&
+ Window->WindowRect.top == WinPos->y)
+ {
+ WinPos->flags |= SWP_NOMOVE;
+ }
+
+ if (WinPos->hwnd == NtUserGetForegroundWindow())
+ {
+ WinPos->flags |= SWP_NOACTIVATE; /* Already active */
+ }
+ else
+ if ((Window->Style & (WS_POPUP | WS_CHILD)) != WS_CHILD)
+ {
+ /* Bring to the top when activating */
+ if (!(WinPos->flags & SWP_NOACTIVATE))
+ {
+ WinPos->flags &= ~SWP_NOZORDER;
+ WinPos->hwndInsertAfter = HWND_TOP;
+ return TRUE;
+ }
+ }
- if ((!(WinPos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) &&
- WinPos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
- SWP_HIDEWINDOW | SWP_FRAMECHANGED)) !=
- (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER))
- {
- if (Window->Style & WS_CLIPCHILDREN)
- {
- VisRgn = DceGetVisRgn(Wnd, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
- }
- else
- {
- VisRgn = DceGetVisRgn(Wnd, DCX_WINDOW, 0, 0);
- }
- }
+ /* Check hwndInsertAfter */
+ if (!(WinPos->flags & SWP_NOZORDER))
+ {
+ /* Fix sign extension */
+ if (WinPos->hwndInsertAfter == (HWND)0xffff)
+ {
+ WinPos->hwndInsertAfter = HWND_TOPMOST;
+ }
+ else if (WinPos->hwndInsertAfter == (HWND)0xfffe)
+ {
+ WinPos->hwndInsertAfter = HWND_NOTOPMOST;
+ }
- WvrFlags = WinPosDoNCCALCSize(Window, &WinPos, &NewWindowRect,
- &NewClientRect);
+ /* FIXME: TOPMOST not supported yet */
+ if ((WinPos->hwndInsertAfter == HWND_TOPMOST) ||
+ (WinPos->hwndInsertAfter == HWND_NOTOPMOST))
+ {
+ WinPos->hwndInsertAfter = HWND_TOP;
+ }
- /* FIXME: Relink windows. */
+ /* hwndInsertAfter must be a sibling of the window */
+ if ((WinPos->hwndInsertAfter != HWND_TOP) &&
+ (WinPos->hwndInsertAfter != HWND_BOTTOM))
+ {
+ if (NtUserGetAncestor(WinPos->hwndInsertAfter, GA_PARENT) !=
+ Window->Parent->Self)
+ {
+ return FALSE;
+ }
+ else
+ {
+ /*
+ * We don't need to change the Z order of hwnd if it's already
+ * inserted after hwndInsertAfter or when inserting hwnd after
+ * itself.
+ */
+ if ((WinPos->hwnd == WinPos->hwndInsertAfter) ||
+ (WinPos->hwnd == NtUserGetWindow(WinPos->hwndInsertAfter, GW_HWNDNEXT)))
+ {
+ WinPos->flags |= SWP_NOZORDER;
+ }
+ }
+ }
+ }
- /* FIXME: Reset active DCEs */
+ return TRUE;
+}
- /* FIXME: Check for redrawing the whole client rect. */
+/* x and y are always screen relative */
+BOOLEAN FASTCALL
+WinPosSetWindowPos(HWND Wnd, HWND WndInsertAfter, INT x, INT y, INT cx,
+ INT cy, UINT flags)
+{
+ PWINDOW_OBJECT Window;
+ WINDOWPOS WinPos;
+ RECT NewWindowRect;
+ RECT NewClientRect;
+ HRGN VisBefore = NULL;
+ HRGN VisAfter = NULL;
+ HRGN DirtyRgn = NULL;
+ HRGN ExposedRgn = NULL;
+ HRGN CopyRgn = NULL;
+ ULONG WvrFlags = 0;
+ RECT OldWindowRect, OldClientRect;
+ int RgnType;
+ HDC Dc;
+ RECT CopyRect;
+ RECT TempRect;
+
+ /* FIXME: Get current active window from active queue. */
+
+ Window = IntGetWindowObject(Wnd);
+ if (!Window)
+ {
+ SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
+ return FALSE;
+ }
+
+ /*
+ * Only allow CSRSS to mess with the desktop window
+ */
+ if (Wnd == IntGetDesktopWindow() &&
+ Window->OwnerThread->ThreadsProcess != PsGetCurrentProcess())
+ {
+ return FALSE;
+ }
+
+ WinPos.hwnd = Wnd;
+ WinPos.hwndInsertAfter = WndInsertAfter;
+ WinPos.x = x;
+ WinPos.y = y;
+ WinPos.cx = cx;
+ WinPos.cy = cy;
+ WinPos.flags = flags;
+
+ WinPosDoWinPosChanging(Window, &WinPos, &NewWindowRect, &NewClientRect);
+
+ /* Fix up the flags. */
+ if (!WinPosFixupFlags(&WinPos, Window))
+ {
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ IntReleaseWindowObject(Window);
+ return FALSE;
+ }
+
+ /* Does the window still exist? */
+ if (!IntIsWindow(WinPos.hwnd))
+ {
+ SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
+ return FALSE;
+ }
+
+ if ((WinPos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) !=
+ SWP_NOZORDER &&
+ NtUserGetAncestor(WinPos.hwnd, GA_PARENT) == IntGetDesktopWindow())
+ {
+ WinPos.hwndInsertAfter = WinPosDoOwnedPopups(WinPos.hwnd, WinPos.hwndInsertAfter);
+ }
+
+ /* Compute the visible region before the window position is changed */
+ if (!(WinPos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) &&
+ (WinPos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
+ SWP_HIDEWINDOW | SWP_FRAMECHANGED)) !=
+ (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER))
+ {
+ VisBefore = VIS_ComputeVisibleRegion(Window, FALSE, FALSE, TRUE);
+
+ if (VisBefore != NULL &&
+ UnsafeIntGetRgnBox(VisBefore, &TempRect) == NULLREGION)
+ {
+ NtGdiDeleteObject(VisBefore);
+ VisBefore = NULL;
+ }
+ }
- if (WinPos.flags & SWP_SHOWWINDOW)
- {
- Window->Style |= WS_VISIBLE;
- flags |= SWP_EX_PAINTSELF;
- VisRgn = 1;
- }
- else
- {
- /* FIXME: Move the window bits */
- }
+ WvrFlags = WinPosDoNCCALCSize(Window, &WinPos, &NewWindowRect, &NewClientRect);
- Window->WindowRect = NewWindowRect;
- Window->ClientRect = NewClientRect;
+ /* Relink windows. (also take into account shell window in hwndShellWindow) */
+ if (!(WinPos.flags & SWP_NOZORDER) && WinPos.hwnd != NtUserGetShellWindow())
+ {
+ PWINDOW_OBJECT ParentWindow;
+ PWINDOW_OBJECT InsertAfterWindow;
- if (WinPos.flags & SWP_HIDEWINDOW)
- {
+ ParentWindow = Window->Parent;
+ if (ParentWindow)
+ {
+ if (WinPos.hwndInsertAfter == HWND_TOP)
+ InsertAfterWindow = NULL;
+ else if (WinPos.hwndInsertAfter == HWND_BOTTOM)
+ InsertAfterWindow = IntGetWindowObject(ParentWindow->LastChild->Self);
+ else
+ InsertAfterWindow = IntGetWindowObject(WinPos.hwndInsertAfter);
+ /* Do nothing if hwndInsertAfter is HWND_BOTTOM and Window is already
+ the last window */
+ if (InsertAfterWindow != Window)
+ {
+ ExAcquireFastMutexUnsafe(&ParentWindow->ChildrenListLock);
+ IntUnlinkWindow(Window);
+ IntLinkWindow(Window, ParentWindow, InsertAfterWindow);
+ ExReleaseFastMutexUnsafe(&ParentWindow->ChildrenListLock);
+ }
+ if (InsertAfterWindow != NULL)
+ IntReleaseWindowObject(InsertAfterWindow);
+ }
+ }
+
+ /* FIXME: Reset active DCEs */
+
+ OldWindowRect = Window->WindowRect;
+ OldClientRect = Window->ClientRect;
+
+ if (OldClientRect.bottom - OldClientRect.top ==
+ NewClientRect.bottom - NewClientRect.top)
+ {
+ WvrFlags &= ~WVR_VREDRAW;
+ }
+
+ if (OldClientRect.right - OldClientRect.left ==
+ NewClientRect.right - NewClientRect.left)
+ {
+ WvrFlags &= ~WVR_HREDRAW;
+ }
+
+ /* FIXME: Actually do something with WVR_VALIDRECTS */
+
+ if (! (WinPos.flags & SWP_NOMOVE)
+ && (NewWindowRect.left != OldWindowRect.left
+ || NewWindowRect.top != OldWindowRect.top))
+ {
+ WinPosInternalMoveWindow(Window,
+ NewWindowRect.left - OldWindowRect.left,
+ NewWindowRect.top - OldWindowRect.top);
+ }
+
+ Window->WindowRect = NewWindowRect;
+ Window->ClientRect = NewClientRect;
+
+ if (!(WinPos.flags & SWP_SHOWWINDOW) && (WinPos.flags & SWP_HIDEWINDOW))
+ {
+ /* Clear the update region */
+ IntRedrawWindow(Window, NULL, 0, RDW_VALIDATE | RDW_NOFRAME |
+ RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_ALLCHILDREN);
Window->Style &= ~WS_VISIBLE;
- }
+ }
+ else if (WinPos.flags & SWP_SHOWWINDOW)
+ {
+ Window->Style |= WS_VISIBLE;
+ }
+
+ /* Determine the new visible region */
+ VisAfter = VIS_ComputeVisibleRegion(Window, FALSE, FALSE, TRUE);
+
+ if (VisAfter != NULL &&
+ UnsafeIntGetRgnBox(VisAfter, &TempRect) == NULLREGION)
+ {
+ NtGdiDeleteObject(VisAfter);
+ VisAfter = NULL;
+ }
+
+ /*
+ * Determine which pixels can be copied from the old window position
+ * to the new. Those pixels must be visible in both the old and new
+ * position. Also, check the class style to see if the windows of this
+ * 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)))
+ {
+ CopyRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
+ RgnType = NtGdiCombineRgn(CopyRgn, VisAfter, VisBefore, RGN_AND);
+
+ /*
+ * If this is (also) a window resize, the whole nonclient area
+ * needs to be repainted. So we limit the copy to the client area,
+ * 'cause there is no use in copying it (would possibly cause
+ * "flashing" too). However, if the copy region is already empty,
+ * we don't have to crop (can't take anything away from an empty
+ * region...)
+ */
+ if (!(WinPos.flags & SWP_NOSIZE) && RgnType != ERROR &&
+ RgnType != NULLREGION)
+ {
+ RECT ORect = OldClientRect;
+ RECT NRect = NewClientRect;
+ NtGdiOffsetRect(&ORect, - OldWindowRect.left, - OldWindowRect.top);
+ NtGdiOffsetRect(&NRect, - NewWindowRect.left, - NewWindowRect.top);
+ NtGdiIntersectRect(&CopyRect, &ORect, &NRect);
+ REGION_CropRgn(CopyRgn, CopyRgn, &CopyRect, NULL);
+ }
- /* FIXME: Hide or show the claret */
+ /* No use in copying bits which are in the update region. */
+ if (Window->UpdateRegion != NULL)
+ {
+ NtGdiCombineRgn(CopyRgn, CopyRgn, Window->UpdateRegion, RGN_DIFF);
+ }
+ if (Window->NCUpdateRegion != NULL)
+ {
+ NtGdiCombineRgn(CopyRgn, CopyRgn, Window->NCUpdateRegion, RGN_DIFF);
+ }
+
+ /*
+ * Now, get the bounding box of the copy region. If it's empty
+ * there's nothing to copy. Also, it's no use copying bits onto
+ * themselves.
+ */
+ if (UnsafeIntGetRgnBox(CopyRgn, &CopyRect) == NULLREGION)
+ {
+ /* Nothing to copy, clean up */
+ NtGdiDeleteObject(CopyRgn);
+ CopyRgn = NULL;
+ }
+ else if (OldWindowRect.left != NewWindowRect.left ||
+ OldWindowRect.top != NewWindowRect.top)
+ {
+ /*
+ * Small trick here: there is no function to bitblt a region. So
+ * we set the region as the clipping region, take the bounding box
+ * of the region and bitblt that. Since nothing outside the clipping
+ * region is copied, this has the effect of bitblt'ing the region.
+ *
+ * Since NtUserGetDCEx takes ownership of the clip region, we need
+ * to create a copy of CopyRgn and pass that. We need CopyRgn later
+ */
+ HRGN ClipRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
+
+ NtGdiCombineRgn(ClipRgn, CopyRgn, NULL, RGN_COPY);
+ Dc = NtUserGetDCEx(Wnd, ClipRgn, DCX_WINDOW | DCX_CACHE |
+ DCX_INTERSECTRGN | DCX_CLIPSIBLINGS);
+ NtGdiBitBlt(Dc,
+ CopyRect.left, CopyRect.top, CopyRect.right - CopyRect.left,
+ CopyRect.bottom - CopyRect.top, Dc,
+ CopyRect.left + (OldWindowRect.left - NewWindowRect.left),
+ CopyRect.top + (OldWindowRect.top - NewWindowRect.top), SRCCOPY);
+ NtUserReleaseDC(Wnd, Dc);
+ IntValidateParent(Window, CopyRgn);
+ }
+ }
+ else
+ {
+ CopyRgn = NULL;
+ }
+
+ /* We need to redraw what wasn't visible before */
+ if (VisAfter != NULL)
+ {
+ DirtyRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
+ if (CopyRgn != NULL)
+ {
+ RgnType = NtGdiCombineRgn(DirtyRgn, VisAfter, CopyRgn, RGN_DIFF);
+ }
+ else
+ {
+ RgnType = NtGdiCombineRgn(DirtyRgn, VisAfter, 0, RGN_COPY);
+ }
+ if (RgnType != ERROR && RgnType != NULLREGION)
+ {
+ NtGdiOffsetRgn(DirtyRgn,
+ Window->WindowRect.left - Window->ClientRect.left,
+ Window->WindowRect.top - Window->ClientRect.top);
+ IntRedrawWindow(Window, NULL, DirtyRgn,
+ RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
+ }
+ NtGdiDeleteObject(DirtyRgn);
+ }
+
+ if (CopyRgn != NULL)
+ {
+ NtGdiDeleteObject(CopyRgn);
+ }
+
+ /* Expose what was covered before but not covered anymore */
+ if (VisBefore != NULL)
+ {
+ ExposedRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
+ NtGdiCombineRgn(ExposedRgn, VisBefore, NULL, RGN_COPY);
+ NtGdiOffsetRgn(ExposedRgn, OldWindowRect.left - NewWindowRect.left,
+ OldWindowRect.top - NewWindowRect.top);
+ if (VisAfter != NULL)
+ RgnType = NtGdiCombineRgn(ExposedRgn, ExposedRgn, VisAfter, RGN_DIFF);
+ else
+ RgnType = SIMPLEREGION;
- if (VisRgn)
- {
- if (!(WinPos.flags & SWP_NOREDRAW))
- {
- if (flags & SWP_EX_PAINTSELF)
- {
- PaintRedrawWindow(Window->Self, NULL,
- (VisRgn == 1) ? 0 : VisRgn,
- RDW_ERASE | RDW_FRAME | RDW_INVALIDATE |
- RDW_ALLCHILDREN,
- RDW_EX_XYWINDOW | RDW_EX_USEHRGN);
- }
- else
- {
- PaintRedrawWindow(Window->Self, NULL,
- (VisRgn == 1) ? 0 : VisRgn,
- RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN,
- RDW_EX_USEHRGN);
- }
- /* FIXME: Redraw the window parent. */
- }
- /* FIXME: Delete VisRgn */
- }
+ if (RgnType != ERROR && RgnType != NULLREGION)
+ {
+ VIS_WindowLayoutChanged(Window, ExposedRgn);
+ }
+ NtGdiDeleteObject(ExposedRgn);
+ NtGdiDeleteObject(VisBefore);
+ }
+
+ if (VisAfter != NULL)
+ {
+ NtGdiDeleteObject(VisAfter);
+ }
+
+ if (!(WinPos.flags & SWP_NOREDRAW))
+ {
+ IntRedrawWindow(Window, NULL, 0, RDW_ALLCHILDREN | RDW_ERASENOW);
+ }
+
+ if (!(WinPos.flags & SWP_NOACTIVATE))
+ {
+ if ((Window->Style & (WS_CHILD | WS_POPUP)) == WS_CHILD)
+ {
+ IntSendMessage(WinPos.hwnd, WM_CHILDACTIVATE, 0, 0);
+ }
+ else
+ {
+ IntSetForegroundWindow(Window);
+ }
+ }
- if (!(flags & SWP_NOACTIVATE))
- {
- WinPosChangeActiveWindow(WinPos.hwnd, FALSE);
- }
+ if ((WinPos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE)
+ IntSendMessage(WinPos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM) &WinPos);
- /* FIXME: Check some conditions before doing this. */
- W32kSendWINDOWPOSCHANGEDMessage(Window->Self, &WinPos);
+ IntReleaseWindowObject(Window);
- ObmDereferenceObject(Window);
- return(TRUE);
+ return TRUE;
}
-LRESULT
+LRESULT FASTCALL
WinPosGetNonClientSize(HWND Wnd, RECT* WindowRect, RECT* ClientRect)
{
*ClientRect = *WindowRect;
- return(W32kSendNCCALCSIZEMessage(Wnd, FALSE, ClientRect, NULL));
+ return(IntSendMessage(Wnd, WM_NCCALCSIZE, FALSE, (LPARAM) ClientRect));
}
-BOOLEAN
+BOOLEAN FASTCALL
WinPosShowWindow(HWND Wnd, INT Cmd)
{
BOOLEAN WasVisible;
UINT Swp = 0;
RECT NewPos;
BOOLEAN ShowFlag;
+// HRGN VisibleRgn;
Status =
ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation->HandleTable,
/* Fall through. */
case SW_MINIMIZE:
{
- Swp |= SWP_FRAMECHANGED;
+ Swp |= SWP_FRAMECHANGED | SWP_NOACTIVATE;
if (!(Window->Style & WS_MINIMIZE))
{
Swp |= WinPosMinMaximize(Window, SW_MINIMIZE, &NewPos);
ShowFlag = (Cmd != SW_HIDE);
if (ShowFlag != WasVisible)
{
- NtUserSendMessage(Wnd, WM_SHOWWINDOW, ShowFlag, 0);
+ IntSendMessage(Wnd, WM_SHOWWINDOW, ShowFlag, 0);
/*
* FIXME: Need to check the window wasn't destroyed during the
* window procedure.
*/
}
- if (Window->Style & WS_CHILD &&
- !W32kIsWindowVisible(Window->Parent->Self) &&
- (Swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE))
+ /* We can't activate a child window */
+ if ((Window->Style & WS_CHILD) &&
+ !(Window->ExStyle & WS_EX_MDICHILD))
{
- if (Cmd == SW_HIDE)
- {
- Window->Style &= ~WS_VISIBLE;
- }
- else
- {
- Window->Style |= WS_VISIBLE;
- }
+ Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
}
- else
+
+ WinPosSetWindowPos(Window->Self, HWND_TOP, NewPos.left, NewPos.top,
+ NewPos.right, NewPos.bottom, LOWORD(Swp));
+
+ if (Cmd == SW_HIDE)
{
- if (Window->Style & WS_CHILD &&
- !(Window->ExStyle & WS_EX_MDICHILD))
- {
- Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
- }
- if (!(Swp & MINMAX_NOSWP))
- {
- WinPosSetWindowPos(Wnd, HWND_TOP, NewPos.left, NewPos.top,
- NewPos.right, NewPos.bottom, LOWORD(Swp));
- if (Cmd == SW_HIDE)
- {
- /* Hide the window. */
- if (Wnd == W32kGetActiveWindow())
- {
- WinPosActivateOtherWindow(Window);
- }
- /* Revert focus to parent. */
- if (Wnd == W32kGetFocusWindow() ||
- W32kIsChildWindow(Wnd, W32kGetFocusWindow()))
- {
- W32kSetFocusWindow(Window->Parent->Self);
- }
- }
- }
- /* FIXME: Check for window destruction. */
- /* Show title for minimized windows. */
- if (Window->Style & WS_MINIMIZE)
- {
- WinPosShowIconTitle(Window, TRUE);
- }
+ /* FIXME: This will cause the window to be activated irrespective
+ * of whether it is owned by the same thread. Has to be done
+ * asynchronously.
+ */
+
+ if (Window->Self == NtUserGetActiveWindow())
+ {
+ WinPosActivateOtherWindow(Window);
+ }
+
+ /* Revert focus to parent */
+ if (Wnd == IntGetThreadFocusWindow() ||
+ IntIsChildWindow(Wnd, IntGetThreadFocusWindow()))
+ {
+ NtUserSetFocus(Window->Parent->Self);
+ }
}
+ /* FIXME: Check for window destruction. */
+
if (Window->Flags & WINDOWOBJECT_NEED_SIZE)
{
WPARAM wParam = SIZE_RESTORED;
wParam = SIZE_MINIMIZED;
}
- NtUserSendMessage(Wnd, WM_SIZE, wParam,
- MAKELONG(Window->ClientRect.right -
- Window->ClientRect.left,
- Window->ClientRect.bottom -
- Window->ClientRect.top));
- NtUserSendMessage(Wnd, WM_MOVE, 0,
- MAKELONG(Window->ClientRect.left,
- Window->ClientRect.top));
+ IntSendMessage(Wnd, WM_SIZE, wParam,
+ MAKELONG(Window->ClientRect.right -
+ Window->ClientRect.left,
+ Window->ClientRect.bottom -
+ Window->ClientRect.top));
+ IntSendMessage(Wnd, WM_MOVE, 0,
+ MAKELONG(Window->ClientRect.left,
+ Window->ClientRect.top));
+ }
+
+ /* Activate the window if activation is not requested and the window is not minimized */
+/*
+ if (!(Swp & (SWP_NOACTIVATE | SWP_HIDEWINDOW)) && !(Window->Style & WS_MINIMIZE))
+ {
+ WinPosChangeActiveWindow(Wnd, FALSE);
}
+*/
+
ObmDereferenceObject(Window);
return(WasVisible);
}
-BOOL STATIC
+BOOL STATIC FASTCALL
WinPosPtInWindow(PWINDOW_OBJECT Window, POINT Point)
{
return(Point.x >= Window->WindowRect.left &&
Point.y < Window->WindowRect.bottom);
}
-USHORT STATIC
+USHORT STATIC FASTCALL
WinPosSearchChildren(PWINDOW_OBJECT ScopeWin, POINT Point,
PWINDOW_OBJECT* Window)
{
- PLIST_ENTRY CurrentEntry;
PWINDOW_OBJECT Current;
- CurrentEntry = ScopeWin->ChildrenListHead.Flink;
- while (CurrentEntry != &ScopeWin->ChildrenListHead)
+ ExAcquireFastMutexUnsafe(&ScopeWin->ChildrenListLock);
+ Current = ScopeWin->FirstChild;
+ while (Current)
{
- Current =
- CONTAINING_RECORD(CurrentEntry, WINDOW_OBJECT, SiblingListEntry);
-
if (Current->Style & WS_VISIBLE &&
((!(Current->Style & WS_DISABLED)) ||
(Current->Style & (WS_CHILD | WS_POPUP)) != WS_CHILD) &&
WinPosPtInWindow(Current, Point))
{
+ if(*Window)
+ ObmDereferenceObject(*Window);
+ ObmReferenceObjectByPointer(Current, otWindow);
+
*Window = Current;
+
if (Current->Style & WS_DISABLED)
{
+ ExReleaseFastMutexUnsafe(&ScopeWin->ChildrenListLock);
return(HTERROR);
}
- if (Current->Style & WS_MINIMIZE)
- {
- return(HTCAPTION);
- }
if (Point.x >= Current->ClientRect.left &&
Point.x < Current->ClientRect.right &&
Point.y >= Current->ClientRect.top &&
Point.y < Current->ClientRect.bottom)
{
- Point.x -= Current->ClientRect.left;
- Point.y -= Current->ClientRect.top;
+ ExReleaseFastMutexUnsafe(&ScopeWin->ChildrenListLock);
return(WinPosSearchChildren(Current, Point, Window));
}
+
+ ExReleaseFastMutexUnsafe(&ScopeWin->ChildrenListLock);
return(0);
}
- CurrentEntry = CurrentEntry->Flink;
+ Current = Current->NextSibling;
}
+
+ ExReleaseFastMutexUnsafe(&ScopeWin->ChildrenListLock);
return(0);
}
-USHORT
+USHORT FASTCALL
WinPosWindowFromPoint(PWINDOW_OBJECT ScopeWin, POINT WinPoint,
PWINDOW_OBJECT* Window)
{
PWINDOW_OBJECT DesktopWindow;
POINT Point = WinPoint;
USHORT HitTest;
-
+
*Window = NULL;
+
+ if(!ScopeWin)
+ {
+ DPRINT1("WinPosWindowFromPoint(): ScopeWin == NULL!\n");
+ return(HTERROR);
+ }
if (ScopeWin->Style & WS_DISABLED)
{
}
/* Translate the point to the space of the scope window. */
- DesktopWindowHandle = W32kGetDesktopWindow();
- DesktopWindow = W32kGetWindowObject(DesktopWindowHandle);
+ DesktopWindowHandle = IntGetDesktopWindow();
+ DesktopWindow = IntGetWindowObject(DesktopWindowHandle);
Point.x += ScopeWin->ClientRect.left - DesktopWindow->ClientRect.left;
Point.y += ScopeWin->ClientRect.top - DesktopWindow->ClientRect.top;
- W32kReleaseWindowObject(DesktopWindow);
+ IntReleaseWindowObject(DesktopWindow);
HitTest = WinPosSearchChildren(ScopeWin, Point, Window);
if (HitTest != 0)
}
if ((*Window)->MessageQueue == PsGetWin32Thread()->MessageQueue)
{
- HitTest = W32kSendMessage((*Window)->Self, WM_NCHITTEST, 0,
- MAKELONG(Point.x, Point.y), FALSE);
+ HitTest = IntSendMessage((*Window)->Self, WM_NCHITTEST, 0,
+ MAKELONG(Point.x, Point.y));
/* FIXME: Check for HTTRANSPARENT here. */
}
else
return(HitTest);
}
+
+BOOL
+STDCALL
+NtUserGetMinMaxInfo(
+ HWND hwnd,
+ MINMAXINFO *MinMaxInfo,
+ BOOL SendMessage)
+{
+ POINT Size;
+ PINTERNALPOS InternalPos;
+ PWINDOW_OBJECT Window;
+ MINMAXINFO SafeMinMax;
+ NTSTATUS Status;
+
+ Window = IntGetWindowObject(hwnd);
+ if(!Window)
+ {
+ SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
+ return FALSE;
+ }
+
+ Size.x = Window->WindowRect.left;
+ Size.y = Window->WindowRect.top;
+ InternalPos = WinPosInitInternalPos(Window, Size,
+ &Window->WindowRect);
+ if(InternalPos)
+ {
+ if(SendMessage)
+ {
+ WinPosGetMinMaxInfo(Window, &SafeMinMax.ptMaxSize, &SafeMinMax.ptMaxPosition,
+ &SafeMinMax.ptMinTrackSize, &SafeMinMax.ptMaxTrackSize);
+ }
+ else
+ {
+ WinPosFillMinMaxInfoStruct(Window, &SafeMinMax);
+ }
+ Status = MmCopyToCaller(MinMaxInfo, &SafeMinMax, sizeof(MINMAXINFO));
+ if(!NT_SUCCESS(Status))
+ {
+ IntReleaseWindowObject(Window);
+ SetLastNtError(Status);
+ return FALSE;
+ }
+ IntReleaseWindowObject(Window);
+ return TRUE;
+ }
+
+ IntReleaseWindowObject(Window);
+ return FALSE;
+}
+
+/* EOF */