* 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.30 2003/09/09 09:39:21 gvg Exp $
+/* $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
/* 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 SWP_AGG_STATUSFLAGS \
(SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
-ATOM AtomInternalPos = (ATOM) NULL;
-
/* 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 FASTCALL
-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 = 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 FASTCALL
-WinPosActivateOtherWindow(PWINDOW_OBJECT Window)
+BOOL STDCALL
+NtUserGetClientOrigin(HWND hWnd, LPPOINT Point)
{
- return FALSE;
+ 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 FASTCALL
-WinPosFindIconPos(HWND hWnd, POINT Pos)
+/*******************************************************************
+ * WinPosActivateOtherWindow
+ *
+ * Activates window other than pWnd.
+ */
+VOID FASTCALL
+WinPosActivateOtherWindow(PWINDOW_OBJECT Window)
{
- POINT point;
- //FIXME
- return point;
+ 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 FASTCALL
-WinPosNtGdiIconTitle(PWINDOW_OBJECT WindowObject)
+VOID STATIC FASTCALL
+WinPosFindIconPos(HWND hWnd, POINT *Pos)
{
- return(NULL);
+ /* FIXME */
}
-BOOL STATIC FASTCALL
-WinPosShowIconTitle(PWINDOW_OBJECT WindowObject, BOOL Show)
+PINTERNALPOS FASTCALL
+WinPosInitInternalPos(PWINDOW_OBJECT WindowObject, POINT pt, PRECT RestoreRect)
{
- PINTERNALPOS InternalPos = (PINTERNALPOS)IntGetProp(WindowObject, AtomInternalPos);
- PWINDOW_OBJECT IconWindow;
- NTSTATUS Status;
-
- if (InternalPos)
+ INT XInc, YInc;
+
+ if (WindowObject->InternalPos == NULL)
{
- HWND hWnd = InternalPos->IconTitle;
-
- if (hWnd == NULL)
- {
- hWnd = WinPosNtGdiIconTitle(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 STDCALL
-WinPosInitInternalPos(PWINDOW_OBJECT WindowObject, POINT pt, PRECT RestoreRect)
-{
- PINTERNALPOS InternalPos = (PINTERNALPOS)IntGetProp(WindowObject, AtomInternalPos);
- if (InternalPos == NULL)
- {
- InternalPos =
- ExAllocatePool(NonPagedPool, sizeof(INTERNALPOS));
- IntSetProp(WindowObject, 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 STDCALL
+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);
+ WinPosFindIconPos(WindowObject, &InternalPos->IconPos);
NtGdiSetRect(NewPos, InternalPos->IconPos.x, InternalPos->IconPos.y,
- NtUserGetSystemMetrics(SM_CXICON),
- NtUserGetSystemMetrics(SM_CYICON));
+ 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;
+ 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.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 STDCALL
-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 = (PINTERNALPOS)IntGetProp(Window, 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;
}
+}
- IntSendMessage(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);
return 0; //FIXME: what does it return?
}
-BOOL STATIC FASTCALL
-WinPosChangeActiveWindow(HWND hWnd, BOOL MouseMsg)
-{
- PWINDOW_OBJECT WindowObject;
-
- WindowObject = IntGetWindowObject(hWnd);
- if (WindowObject == NULL)
- {
- return FALSE;
- }
-
- NtUserSendMessage(hWnd,
- WM_ACTIVATE,
- MAKELONG(MouseMsg ? WA_CLICKACTIVE : WA_CLICKACTIVE,
- (WindowObject->Style & WS_MINIMIZE) ? 1 : 0),
- (LPARAM)IntGetDesktopWindow()); /* FIXME: Previous active window */
-
- IntReleaseWindowObject(WindowObject);
-
- return TRUE;
-}
-
-LONG STATIC STDCALL
+LONG STATIC FASTCALL
WinPosDoNCCALCSize(PWINDOW_OBJECT Window, PWINDOWPOS WinPos,
RECT* WindowRect, RECT* ClientRect)
{
params.rgrc[0] = *WindowRect;
params.rgrc[1] = Window->WindowRect;
params.rgrc[2] = Window->ClientRect;
- if (Window->Style & WS_CHILD)
+ 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 = IntSendNCCALCSIZEMessage(Window->Self, TRUE, NULL, ¶ms);
+ 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 &&
return wvrFlags;
}
-BOOL STDCALL
+BOOL FASTCALL
WinPosDoWinPosChanging(PWINDOW_OBJECT WindowObject,
PWINDOWPOS WinPos,
PRECT WindowRect,
PRECT ClientRect)
{
+ INT X, Y;
+
if (!(WinPos->flags & SWP_NOSENDCHANGING))
{
- IntSendWINDOWPOSCHANGINGMessage(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;
+ 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,
- WinPos->x - WindowObject->WindowRect.left,
- WinPos->y - WindowObject->WindowRect.top);
+ X - WindowObject->WindowRect.left,
+ Y - WindowObject->WindowRect.top);
}
WinPos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
- return(TRUE);
+ return TRUE;
+}
+
+/*
+ * 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)
+{
+ 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);
+ }
+
+ return hWndInsertAfter;
}
/***********************************************************************
* Update WindowRect and ClientRect of Window and all of its children
* We keep both WindowRect and ClientRect in screen coordinates internally
*/
-static VOID
+VOID STATIC FASTCALL
WinPosInternalMoveWindow(PWINDOW_OBJECT Window, INT MoveX, INT MoveY)
{
PWINDOW_OBJECT Child;
ExReleaseFastMutexUnsafe(&Window->ChildrenListLock);
}
+/*
+ * WinPosFixupSWPFlags
+ *
+ * Fix redundant flags and values in the WINDOWPOS structure.
+ */
-BOOLEAN STDCALL
-WinPosSetWindowPos(HWND Wnd, HWND WndInsertAfter, INT x, INT y, INT cx,
- INT cy, UINT flags)
+BOOL FASTCALL
+WinPosFixupFlags(WINDOWPOS *WinPos, PWINDOW_OBJECT Window)
{
- PWINDOW_OBJECT Window;
- NTSTATUS Status;
- 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;
- UINT FlagsEx = 0;
- int RgnType;
- HDC Dc;
- RECT CopyRect;
- RECT TempRect;
-
- /* FIXME: Get current active window from active queue. */
-
- /* Check if the window is for a desktop. */
- if (Wnd == PsGetWin32Thread()->Desktop->DesktopWindow)
- {
- return(FALSE);
- }
+ 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;
+ }
+ }
- 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;
- }
+ /* 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;
+ }
- cx = max(cx, 0);
- cy = max(cy, 0);
+ /* FIXME: TOPMOST not supported yet */
+ if ((WinPos->hwndInsertAfter == HWND_TOPMOST) ||
+ (WinPos->hwndInsertAfter == HWND_NOTOPMOST))
+ {
+ WinPos->hwndInsertAfter = HWND_TOP;
+ }
- 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)
- {
- flags |= SWP_NOMOVE;
- }
- if (Window->Style & WIN_NCACTIVATED)
- {
- flags |= SWP_NOACTIVATE;
- }
- else if ((Window->Style & (WS_POPUP | WS_CHILD)) != WS_CHILD)
- {
- if (!(flags & SWP_NOACTIVATE))
- {
- flags &= ~SWP_NOZORDER;
- WndInsertAfter = HWND_TOP;
- }
- }
+ /* 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;
+ }
+ }
+ }
+ }
- if (WndInsertAfter == HWND_TOPMOST || WndInsertAfter == HWND_NOTOPMOST)
- {
- WndInsertAfter = HWND_TOP;
- }
+ return TRUE;
+}
- if (WndInsertAfter != HWND_TOP && WndInsertAfter != HWND_BOTTOM)
- {
- /* FIXME: Find the window to insert after. */
- }
+/* 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;
+ }
- WinPos.hwnd = Wnd;
- WinPos.hwndInsertAfter = WndInsertAfter;
- WinPos.x = x;
- WinPos.y = y;
- WinPos.cx = cx;
- WinPos.cy = cy;
- WinPos.flags = flags;
+ /* 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;
+ }
+ }
- WinPosDoWinPosChanging(Window, &WinPos, &NewWindowRect, &NewClientRect);
+ WvrFlags = WinPosDoNCCALCSize(Window, &WinPos, &NewWindowRect, &NewClientRect);
- if ((WinPos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) !=
- SWP_NOZORDER)
- {
- /* FIXME: SWP_DoOwnedPopups. */
- }
-
- /* FIXME: Adjust flags based on WndInsertAfter */
+ /* Relink windows. (also take into account shell window in hwndShellWindow) */
+ if (!(WinPos.flags & SWP_NOZORDER) && WinPos.hwnd != NtUserGetShellWindow())
+ {
+ PWINDOW_OBJECT ParentWindow;
+ PWINDOW_OBJECT InsertAfterWindow;
- /* 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))
- {
- if (Window->Style & WS_CLIPCHILDREN)
- {
- VisBefore = VIS_ComputeVisibleRegion(PsGetWin32Thread()->Desktop,
- Window, FALSE, FALSE, TRUE);
- }
- else
- {
- VisBefore = VIS_ComputeVisibleRegion(PsGetWin32Thread()->Desktop,
- Window, FALSE, FALSE, FALSE);
- }
- if (NULLREGION == UnsafeIntGetRgnBox(VisBefore, &TempRect))
- {
- NtGdiDeleteObject(VisBefore);
- VisBefore = NULL;
- }
- }
+ 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);
+ }
+ }
- WvrFlags = WinPosDoNCCALCSize(Window, &WinPos, &NewWindowRect,
- &NewClientRect);
+ /* FIXME: Reset active DCEs */
- /* FIXME: Relink windows. */
+ OldWindowRect = Window->WindowRect;
+ OldClientRect = Window->ClientRect;
- /* FIXME: Reset active DCEs */
+ if (OldClientRect.bottom - OldClientRect.top ==
+ NewClientRect.bottom - NewClientRect.top)
+ {
+ WvrFlags &= ~WVR_VREDRAW;
+ }
- OldWindowRect = Window->WindowRect;
- OldClientRect = Window->ClientRect;
+ if (OldClientRect.right - OldClientRect.left ==
+ NewClientRect.right - NewClientRect.left)
+ {
+ WvrFlags &= ~WVR_HREDRAW;
+ }
- /* FIXME: Check for redrawing the whole client rect. */
+ /* FIXME: Actually do something with WVR_VALIDRECTS */
- if (! (WinPos.flags & SWP_NOMOVE))
- {
+ 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)
- {
- Window->Style |= WS_VISIBLE;
- FlagsEx |= SWP_EX_PAINTSELF;
- }
- else if (WinPos.flags & SWP_HIDEWINDOW)
- {
+ 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;
+ }
- if (!(WinPos.flags & SWP_NOREDRAW))
- {
- /* Determine the new visible region */
- if (Window->Style & WS_CLIPCHILDREN)
- {
- VisAfter = VIS_ComputeVisibleRegion(PsGetWin32Thread()->Desktop,
- Window, FALSE, FALSE, TRUE);
- }
- else
- {
- VisAfter = VIS_ComputeVisibleRegion(PsGetWin32Thread()->Desktop,
- Window, FALSE, FALSE, FALSE);
- }
- if (NULLREGION == UnsafeIntGetRgnBox(VisAfter, &TempRect))
- {
- NtGdiDeleteObject(VisAfter);
- VisAfter = NULL;
- }
+ /* Determine the new visible region */
+ VisAfter = VIS_ComputeVisibleRegion(Window, FALSE, FALSE, TRUE);
- /* 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. */
- if (NULL != VisBefore && NULL != VisAfter && ! (WinPos.flags & SWP_NOCOPYBITS))
- {
- 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)
- && ERROR != RgnType && NULLREGION != RgnType)
- {
- 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);
- }
+ 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);
+ }
- /* No use in copying bits which are in the update region. */
- if ((HRGN) 1 == Window->UpdateRegion)
- {
- /* The whole window is in the update region. No use
- copying anything, so set the copy region empty */
- NtGdiSetRectRgn(CopyRgn, 0, 0, 0, 0);
- }
- else if (1 < (DWORD) Window->UpdateRegion)
- {
- NtGdiCombineRgn(CopyRgn, CopyRgn, Window->UpdateRegion, RGN_DIFF);
- }
+ /* 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 */
- UnsafeIntGetRgnBox(CopyRgn, &CopyRect);
- if (NtGdiIsEmptyRect(&CopyRect))
- {
- /* 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_KEEPCLIPRGN | 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);
- }
- }
+ /*
+ * 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
- {
- CopyRgn = NULL;
- }
-
- /* We need to redraw what wasn't visible before */
- if (NULL != VisAfter)
- {
- if (NULL != CopyRgn)
- {
- DirtyRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
- RgnType = NtGdiCombineRgn(DirtyRgn, VisAfter, CopyRgn, RGN_DIFF);
- if (ERROR != RgnType && NULLREGION != RgnType)
- {
- PaintRedrawWindow(Window, NULL, DirtyRgn,
- RDW_ERASE | RDW_FRAME | RDW_INVALIDATE |
- RDW_ALLCHILDREN | RDW_ERASENOW,
- RDW_EX_XYWINDOW | RDW_EX_USEHRGN);
- }
- NtGdiDeleteObject(DirtyRgn);
- }
- else
- {
- PaintRedrawWindow(Window, NULL, NULL,
- RDW_ERASE | RDW_FRAME | RDW_INVALIDATE |
- RDW_ALLCHILDREN | RDW_ERASENOW,
- RDW_EX_XYWINDOW | RDW_EX_USEHRGN);
- }
- }
+ {
+ 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 (NULL != CopyRgn)
- {
- NtGdiDeleteObject(CopyRgn);
- }
- }
+ if (CopyRgn != NULL)
+ {
+ NtGdiDeleteObject(CopyRgn);
+ }
- /* Expose what was covered before but not covered anymore */
- if (NULL != VisBefore)
- {
+ /* 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 (NULL != VisAfter)
- {
- RgnType = NtGdiCombineRgn(ExposedRgn, ExposedRgn, VisAfter, RGN_DIFF);
- }
+ if (VisAfter != NULL)
+ RgnType = NtGdiCombineRgn(ExposedRgn, ExposedRgn, VisAfter, RGN_DIFF);
else
- {
- RgnType = SIMPLEREGION;
- }
- if (ERROR != RgnType && NULLREGION != RgnType)
- {
- VIS_WindowLayoutChanged(PsGetWin32Thread()->Desktop, Window, ExposedRgn);
- }
- NtGdiDeleteObject(ExposedRgn);
+ RgnType = SIMPLEREGION;
+ if (RgnType != ERROR && RgnType != NULLREGION)
+ {
+ VIS_WindowLayoutChanged(Window, ExposedRgn);
+ }
+ NtGdiDeleteObject(ExposedRgn);
NtGdiDeleteObject(VisBefore);
- }
+ }
- if (NULL != VisAfter)
- {
+ if (VisAfter != NULL)
+ {
NtGdiDeleteObject(VisAfter);
- }
+ }
- /* FIXME: Hide or show the claret */
+ if (!(WinPos.flags & SWP_NOREDRAW))
+ {
+ IntRedrawWindow(Window, NULL, 0, RDW_ALLCHILDREN | RDW_ERASENOW);
+ }
- if (!(flags & SWP_NOACTIVATE))
- {
- WinPosChangeActiveWindow(WinPos.hwnd, FALSE);
- }
+ if (!(WinPos.flags & SWP_NOACTIVATE))
+ {
+ if ((Window->Style & (WS_CHILD | WS_POPUP)) == WS_CHILD)
+ {
+ IntSendMessage(WinPos.hwnd, WM_CHILDACTIVATE, 0, 0);
+ }
+ else
+ {
+ IntSetForegroundWindow(Window);
+ }
+ }
- /* FIXME: Check some conditions before doing this. */
- IntSendWINDOWPOSCHANGEDMessage(WinPos.hwnd, &WinPos);
+ if ((WinPos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE)
+ IntSendMessage(WinPos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM) &WinPos);
- ObmDereferenceObject(Window);
- return(TRUE);
+ IntReleaseWindowObject(Window);
+
+ return TRUE;
}
-LRESULT STDCALL
+LRESULT FASTCALL
WinPosGetNonClientSize(HWND Wnd, RECT* WindowRect, RECT* ClientRect)
{
*ClientRect = *WindowRect;
- return(IntSendNCCALCSIZEMessage(Wnd, FALSE, ClientRect, NULL));
+ return(IntSendMessage(Wnd, WM_NCCALCSIZE, FALSE, (LPARAM) ClientRect));
}
BOOLEAN FASTCALL
UINT Swp = 0;
RECT NewPos;
BOOLEAN ShowFlag;
- HRGN VisibleRgn;
+// 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 &&
- !IntIsWindowVisible(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)
- {
- VisibleRgn = VIS_ComputeVisibleRegion(PsGetWin32Thread()->Desktop, Window,
- FALSE, FALSE, FALSE);
- Window->Style &= ~WS_VISIBLE;
- VIS_WindowLayoutChanged(PsGetWin32Thread()->Desktop, Window, VisibleRgn);
- NtGdiDeleteObject(VisibleRgn);
- }
- 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 == IntGetActiveWindow())
- {
- WinPosActivateOtherWindow(Window);
- }
- /* Revert focus to parent. */
- if (Wnd == IntGetFocusWindow() ||
- IntIsChildWindow(Wnd, IntGetFocusWindow()))
- {
- IntSetFocusWindow(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);
Point.y < Window->WindowRect.bottom);
}
-USHORT STATIC STDCALL
+USHORT STATIC FASTCALL
WinPosSearchChildren(PWINDOW_OBJECT ScopeWin, POINT Point,
PWINDOW_OBJECT* Window)
{
(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)
- {
- ExReleaseFastMutexUnsafe(&ScopeWin->ChildrenListLock);
- return(HTCAPTION);
- }
if (Point.x >= Current->ClientRect.left &&
Point.x < Current->ClientRect.right &&
Point.y >= Current->ClientRect.top &&
return(0);
}
-USHORT STDCALL
+USHORT FASTCALL
WinPosWindowFromPoint(PWINDOW_OBJECT ScopeWin, POINT WinPoint,
PWINDOW_OBJECT* Window)
{
USHORT HitTest;
*Window = NULL;
+
+ if(!ScopeWin)
+ {
+ DPRINT1("WinPosWindowFromPoint(): ScopeWin == NULL!\n");
+ return(HTERROR);
+ }
if (ScopeWin->Style & WS_DISABLED)
{
if ((*Window)->MessageQueue == PsGetWin32Thread()->MessageQueue)
{
HitTest = IntSendMessage((*Window)->Self, WM_NCHITTEST, 0,
- MAKELONG(Point.x, Point.y), FALSE);
+ MAKELONG(Point.x, Point.y));
/* FIXME: Check for HTTRANSPARENT here. */
}
else
}
BOOL
-WinPosSetActiveWindow(PWINDOW_OBJECT Window, BOOL Mouse, BOOL ChangeFocus)
+STDCALL
+NtUserGetMinMaxInfo(
+ HWND hwnd,
+ MINMAXINFO *MinMaxInfo,
+ BOOL SendMessage)
{
- PUSER_MESSAGE_QUEUE ActiveQueue;
- HWND PrevActive;
-
- ActiveQueue = IntGetFocusMessageQueue();
- if (ActiveQueue != NULL)
- {
- PrevActive = ActiveQueue->ActiveWindow;
- }
- else
- {
- PrevActive = NULL;
- }
-
- if (Window->Self == IntGetActiveDesktop() || Window->Self == PrevActive)
- {
- return(FALSE);
- }
- if (PrevActive != NULL)
- {
- PWINDOW_OBJECT PrevActiveWindow = IntGetWindowObject(PrevActive);
- WORD Iconised = HIWORD(PrevActiveWindow->Style & WS_MINIMIZE);
- if (!IntSendMessage(PrevActive, WM_NCACTIVATE, FALSE, 0, TRUE))
- {
- /* FIXME: Check if the new window is system modal. */
- return(FALSE);
- }
- IntSendMessage(PrevActive,
- WM_ACTIVATE,
- MAKEWPARAM(WA_INACTIVE, Iconised),
- (LPARAM)Window->Self,
- TRUE);
- /* FIXME: Check if anything changed while processing the message. */
- IntReleaseWindowObject(PrevActiveWindow);
- }
-
- if (Window != NULL)
- {
- Window->MessageQueue->ActiveWindow = Window->Self;
- }
- else if (ActiveQueue != NULL)
- {
- ActiveQueue->ActiveWindow = NULL;
- }
- /* FIXME: Unset this flag for inactive windows */
- //if ((Window->Style) & WS_CHILD) Window->Flags |= WIN_NCACTIVATED;
-
- /* FIXME: Send palette messages. */
-
- /* FIXME: Redraw icon title of previously active window. */
-
- /* FIXME: Bring the window to the top. */
-
- /* FIXME: Send WM_ACTIVATEAPP */
+ POINT Size;
+ PINTERNALPOS InternalPos;
+ PWINDOW_OBJECT Window;
+ MINMAXINFO SafeMinMax;
+ NTSTATUS Status;
- IntSetFocusMessageQueue(Window->MessageQueue);
-
- /* FIXME: Send activate messages. */
-
- /* FIXME: Change focus. */
-
- /* FIXME: Redraw new window icon title. */
-
- return(TRUE);
-}
-
-HWND STDCALL
-NtUserGetActiveWindow(VOID)
-{
- PUSER_MESSAGE_QUEUE ActiveQueue;
-
- ActiveQueue = IntGetFocusMessageQueue();
- if (ActiveQueue == NULL)
+ 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)
{
- return(NULL);
+ WinPosGetMinMaxInfo(Window, &SafeMinMax.ptMaxSize, &SafeMinMax.ptMaxPosition,
+ &SafeMinMax.ptMinTrackSize, &SafeMinMax.ptMaxTrackSize);
}
- return(ActiveQueue->ActiveWindow);
-}
-
-HWND STDCALL
-NtUserSetActiveWindow(HWND hWnd)
-{
- PWINDOW_OBJECT Window;
- PUSER_MESSAGE_QUEUE ThreadQueue;
- HWND Prev;
-
- Window = IntGetWindowObject(hWnd);
- if (Window == NULL || (Window->Style & (WS_DISABLED | WS_CHILD)))
+ else
{
- IntReleaseWindowObject(Window);
- return(0);
+ WinPosFillMinMaxInfoStruct(Window, &SafeMinMax);
}
- ThreadQueue = (PUSER_MESSAGE_QUEUE)PsGetWin32Thread()->MessageQueue;
- if (Window->MessageQueue != ThreadQueue)
+ Status = MmCopyToCaller(MinMaxInfo, &SafeMinMax, sizeof(MINMAXINFO));
+ if(!NT_SUCCESS(Status))
{
IntReleaseWindowObject(Window);
- return(0);
+ SetLastNtError(Status);
+ return FALSE;
}
- Prev = Window->MessageQueue->ActiveWindow;
- WinPosSetActiveWindow(Window, FALSE, FALSE);
+ IntReleaseWindowObject(Window);
+ return TRUE;
+ }
+
IntReleaseWindowObject(Window);
- return(Prev);
+ return FALSE;
}
-
/* EOF */