+/*
+ * 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$
*
* COPYRIGHT: See COPYING in the top level directory
* 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 <include/rect.h>
#include <include/callback.h>
#include <include/painting.h>
+#include <include/dce.h>
+#include <include/vis.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)
+
+ATOM AtomInternalPos = (ATOM) NULL;
/* FUNCTIONS *****************************************************************/
(((Style) & WS_THICKFRAME) && \
!((Style) & (WS_DLGFRAME | WS_BORDER)) == WS_DLGFRAME)
-VOID
+VOID FASTCALL
WinPosSetupInternalPos(VOID)
{
AtomInternalPos = NtAddAtom(L"SysIP", (ATOM*)(PULONG)&AtomInternalPos);
{
PWINDOW_OBJECT WindowObject;
- WindowObject = W32kGetWindowObject(hWnd);
+ WindowObject = IntGetWindowObject(hWnd);
if (WindowObject == NULL)
{
Point->x = Point->y = 0;
return(TRUE);
}
-BOOL
+BOOL FASTCALL
WinPosActivateOtherWindow(PWINDOW_OBJECT Window)
{
+ return FALSE;
}
-POINT STATIC
+POINT STATIC FASTCALL
WinPosFindIconPos(HWND hWnd, POINT Pos)
{
+ POINT point;
+ //FIXME
+ return point;
}
-HWND STATIC
-WinPosCreateIconTitle(PWINDOW_OBJECT WindowObject)
+HWND STATIC FASTCALL
+WinPosNtGdiIconTitle(PWINDOW_OBJECT WindowObject)
{
return(NULL);
}
-BOOL STATIC
+BOOL STATIC FASTCALL
WinPosShowIconTitle(PWINDOW_OBJECT WindowObject, BOOL Show)
{
- PINTERNALPOS InternalPos = NtUserGetProp(WindowObject->Self,
- AtomInternalPos);
+ PINTERNALPOS InternalPos = (PINTERNALPOS)IntGetProp(WindowObject, AtomInternalPos);
PWINDOW_OBJECT IconWindow;
NTSTATUS Status;
if (hWnd == NULL)
{
- hWnd = WinPosCreateIconTitle(WindowObject);
+ hWnd = WinPosNtGdiIconTitle(WindowObject);
}
if (Show)
{
return(FALSE);
}
-PINTERNALPOS STATIC
+PINTERNALPOS STATIC STDCALL
WinPosInitInternalPos(PWINDOW_OBJECT WindowObject, POINT pt, PRECT RestoreRect)
{
- PINTERNALPOS InternalPos = NtUserGetProp(WindowObject->Self,
- AtomInternalPos);
+ PINTERNALPOS InternalPos = (PINTERNALPOS)IntGetProp(WindowObject, AtomInternalPos);
if (InternalPos == NULL)
{
InternalPos =
ExAllocatePool(NonPagedPool, sizeof(INTERNALPOS));
- NtUserSetProp(WindowObject->Self, AtomInternalPos, InternalPos);
+ IntSetProp(WindowObject, AtomInternalPos, InternalPos);
InternalPos->IconTitle = 0;
InternalPos->NormalRect = WindowObject->WindowRect;
InternalPos->IconPos.x = InternalPos->MaxPos.x = 0xFFFFFFFF;
return(InternalPos);
}
-UINT
+UINT STDCALL
WinPosMinMaximize(PWINDOW_OBJECT WindowObject, UINT ShowFlag, RECT* NewPos)
{
POINT Size;
WindowObject->Style |= WS_MINIMIZE;
InternalPos->IconPos = WinPosFindIconPos(WindowObject,
InternalPos->IconPos);
- W32kSetRect(NewPos, InternalPos->IconPos.x, InternalPos->IconPos.y,
+ NtGdiSetRect(NewPos, InternalPos->IconPos.x, InternalPos->IconPos.y,
NtUserGetSystemMetrics(SM_CXICON),
NtUserGetSystemMetrics(SM_CYICON));
SwpFlags |= SWP_NOCOPYBITS;
WindowObject->Style &= ~WS_MINIMIZE;
}
WindowObject->Style |= WS_MINIMIZE;
- W32kSetRect(NewPos, InternalPos->MaxPos.x, InternalPos->MaxPos.y,
+ NtGdiSetRect(NewPos, InternalPos->MaxPos.x, InternalPos->MaxPos.y,
Size.x, Size.y);
break;
}
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;
}
return(SwpFlags);
}
-UINT
+UINT STDCALL
WinPosGetMinMaxInfo(PWINDOW_OBJECT Window, POINT* MaxSize, POINT* MaxPos,
POINT* MinTrack, POINT* MaxTrack)
{
MinMax.ptMaxSize.x += 2 * XInc;
MinMax.ptMaxSize.y += 2 * YInc;
- Pos = NtUserGetProp(Window->Self, AtomInternalPos);
+ Pos = (PINTERNALPOS)IntGetProp(Window, AtomInternalPos);
if (Pos != NULL)
{
MinMax.ptMaxPosition = Pos->MaxPos;
MinMax.ptMaxPosition.y -= YInc;
}
- W32kSendMessage(Window->Self, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax, TRUE);
+ IntSendMessage(Window->Self, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax, TRUE);
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;
+
+ return 0; //FIXME: what does it return?
}
-BOOL STATIC
-WinPosChangeActiveWindow(HWND Wnd, BOOL MouseMsg)
+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
+LONG STATIC STDCALL
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 (Window->Style & WS_CHILD)
+ {
+ NtGdiOffsetRect(&(params.rgrc[2]), - Window->Parent->ClientRect.left,
+ - Window->Parent->ClientRect.top);
+ }
+ params.lppos = &winposCopy;
+ winposCopy = *WinPos;
+
+ wvrFlags = IntSendNCCALCSIZEMessage(Window->Self, TRUE, NULL, ¶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 STDCALL
WinPosDoWinPosChanging(PWINDOW_OBJECT WindowObject,
PWINDOWPOS WinPos,
PRECT WindowRect,
{
if (!(WinPos->flags & SWP_NOSENDCHANGING))
{
- NtUserSendMessage(WindowObject->Self, WM_WINDOWPOSCHANGING, 0,
- (LPARAM)WinPos);
+ IntSendWINDOWPOSCHANGINGMessage(WindowObject->Self, WinPos);
}
*WindowRect = WindowObject->WindowRect;
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);
+ NtGdiOffsetRect(ClientRect,
+ WinPos->x - WindowObject->WindowRect.left,
+ WinPos->y - WindowObject->WindowRect.top);
}
WinPos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
+
return(TRUE);
}
-BOOLEAN
+/***********************************************************************
+ * WinPosInternalMoveWindow
+ *
+ * Update WindowRect and ClientRect of Window and all of its children
+ * We keep both WindowRect and ClientRect in screen coordinates internally
+ */
+static VOID
+WinPosInternalMoveWindow(PWINDOW_OBJECT Window, INT MoveX, INT MoveY)
+{
+ PWINDOW_OBJECT Child;
+
+ Window->WindowRect.left += MoveX;
+ Window->WindowRect.right += MoveX;
+ Window->WindowRect.top += MoveY;
+ Window->WindowRect.bottom += MoveY;
+
+ Window->ClientRect.left += MoveX;
+ Window->ClientRect.right += MoveX;
+ Window->ClientRect.top += MoveY;
+ Window->ClientRect.bottom += MoveY;
+
+ ExAcquireFastMutexUnsafe(&Window->ChildrenListLock);
+ Child = Window->FirstChild;
+ while (Child)
+ {
+ WinPosInternalMoveWindow(Child, MoveX, MoveY);
+ Child = Child->NextSibling;
+ }
+ ExReleaseFastMutexUnsafe(&Window->ChildrenListLock);
+}
+
+
+BOOLEAN STDCALL
WinPosSetWindowPos(HWND Wnd, HWND WndInsertAfter, INT x, INT y, INT cx,
INT cy, UINT flags)
{
WINDOWPOS WinPos;
RECT NewWindowRect;
RECT NewClientRect;
- HRGN VisRgn = NULL;
+ 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. */
{
flags |= SWP_NOMOVE;
}
- if (FALSE /* FIXME: Check if the window if already active. */)
+ if (Window->Style & WIN_NCACTIVATED)
{
flags |= SWP_NOACTIVATE;
}
/* FIXME: Adjust flags based on WndInsertAfter */
+ /* 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)) !=
{
if (Window->Style & WS_CLIPCHILDREN)
{
- VisRgn = DceGetVisRgn(Wnd, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
+ VisBefore = VIS_ComputeVisibleRegion(PsGetWin32Thread()->Desktop,
+ Window, FALSE, FALSE, TRUE);
}
else
{
- VisRgn = DceGetVisRgn(Wnd, DCX_WINDOW, 0, 0);
+ VisBefore = VIS_ComputeVisibleRegion(PsGetWin32Thread()->Desktop,
+ Window, FALSE, FALSE, FALSE);
+ }
+ if (NULLREGION == UnsafeIntGetRgnBox(VisBefore, &TempRect))
+ {
+ NtGdiDeleteObject(VisBefore);
+ VisBefore = NULL;
}
}
/* FIXME: Reset active DCEs */
+ OldWindowRect = Window->WindowRect;
+ OldClientRect = Window->ClientRect;
+
/* FIXME: Check for redrawing the whole client rect. */
+ if (! (WinPos.flags & SWP_NOMOVE))
+ {
+ 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;
- flags |= SWP_EX_PAINTSELF;
- VisRgn = 1;
+ FlagsEx |= SWP_EX_PAINTSELF;
}
- else
+ else if (WinPos.flags & SWP_HIDEWINDOW)
{
- /* FIXME: Move the window bits */
+ Window->Style &= ~WS_VISIBLE;
}
- if (WinPos.flags & SWP_HIDEWINDOW)
+ if (!(WinPos.flags & SWP_NOREDRAW))
{
- Window->Style &= ~WS_VISIBLE;
- }
+ /* 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;
+ }
- /* FIXME: Hide or show the claret */
+ /* 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 (VisRgn)
- {
- if (!(WinPos.flags & SWP_NOREDRAW))
+ /* 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);
+ }
+
+
+ /* 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);
+ }
+ }
+ else
{
- if (flags & SWP_EX_PAINTSELF)
+ CopyRgn = NULL;
+ }
+
+ /* We need to redraw what wasn't visible before */
+ if (NULL != VisAfter)
+ {
+ if (NULL != CopyRgn)
{
- PaintRedrawWindow(Window->Self, NULL,
- (VisRgn == 1) ? 0 : VisRgn,
- RDW_ERASE | RDW_FRAME | RDW_INVALIDATE |
- RDW_ALLCHILDREN,
- RDW_EX_XYWINDOW | RDW_EX_USEHRGN);
+ 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->Self, NULL,
- (VisRgn == 1) ? 0 : VisRgn,
- RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN,
- RDW_EX_USEHRGN);
+ PaintRedrawWindow(Window, NULL, NULL,
+ RDW_ERASE | RDW_FRAME | RDW_INVALIDATE |
+ RDW_ALLCHILDREN | RDW_ERASENOW,
+ RDW_EX_XYWINDOW | RDW_EX_USEHRGN);
}
- /* FIXME: Redraw the window parent. */
}
- /* FIXME: Delete VisRgn */
+
+ if (NULL != CopyRgn)
+ {
+ NtGdiDeleteObject(CopyRgn);
+ }
+ }
+
+ /* Expose what was covered before but not covered anymore */
+ if (NULL != VisBefore)
+ {
+ 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);
+ }
+ else
+ {
+ RgnType = SIMPLEREGION;
+ }
+ if (ERROR != RgnType && NULLREGION != RgnType)
+ {
+ VIS_WindowLayoutChanged(PsGetWin32Thread()->Desktop, Window, ExposedRgn);
+ }
+ NtGdiDeleteObject(ExposedRgn);
+
+ NtGdiDeleteObject(VisBefore);
}
+ if (NULL != VisAfter)
+ {
+ NtGdiDeleteObject(VisAfter);
+ }
+
+ /* FIXME: Hide or show the claret */
+
if (!(flags & SWP_NOACTIVATE))
{
WinPosChangeActiveWindow(WinPos.hwnd, FALSE);
}
/* FIXME: Check some conditions before doing this. */
- NtUserSendMessage(WinPos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&WinPos);
+ IntSendWINDOWPOSCHANGEDMessage(WinPos.hwnd, &WinPos);
ObmDereferenceObject(Window);
return(TRUE);
}
-LRESULT
+LRESULT STDCALL
WinPosGetNonClientSize(HWND Wnd, RECT* WindowRect, RECT* ClientRect)
{
*ClientRect = *WindowRect;
- return(W32kSendNCCALCSIZEMessage(Wnd, FALSE, ClientRect, NULL));
+ return(IntSendNCCALCSIZEMessage(Wnd, FALSE, ClientRect, NULL));
}
-BOOLEAN
+BOOLEAN FASTCALL
WinPosShowWindow(HWND Wnd, INT Cmd)
{
BOOLEAN WasVisible;
UINT Swp = 0;
RECT NewPos;
BOOLEAN ShowFlag;
+ HRGN VisibleRgn;
Status =
ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation->HandleTable,
}
if (Window->Style & WS_CHILD &&
- !W32kIsWindowVisible(Window->Parent->Self) &&
+ !IntIsWindowVisible(Window->Parent->Self) &&
(Swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE))
{
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
{
if (Cmd == SW_HIDE)
{
/* Hide the window. */
- if (Wnd == W32kGetActiveWindow())
+ if (Wnd == IntGetActiveWindow())
{
WinPosActivateOtherWindow(Window);
}
/* Revert focus to parent. */
- if (Wnd == W32kGetFocusWindow() ||
- W32kIsChildWindow(Wnd, W32kGetFocusWindow()))
+ if (Wnd == IntGetFocusWindow() ||
+ IntIsChildWindow(Wnd, IntGetFocusWindow()))
{
- W32kSetFocusWindow(Window->Parent->Self);
+ IntSetFocusWindow(Window->Parent->Self);
}
}
}
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 STDCALL
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) &&
*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.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 STDCALL
WinPosWindowFromPoint(PWINDOW_OBJECT ScopeWin, POINT WinPoint,
PWINDOW_OBJECT* Window)
{
PWINDOW_OBJECT DesktopWindow;
POINT Point = WinPoint;
USHORT HitTest;
-
+
*Window = NULL;
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,
+ HitTest = IntSendMessage((*Window)->Self, WM_NCHITTEST, 0,
MAKELONG(Point.x, Point.y), FALSE);
/* FIXME: Check for HTTRANSPARENT here. */
}
return(HitTest);
}
+
+BOOL
+WinPosSetActiveWindow(PWINDOW_OBJECT Window, BOOL Mouse, BOOL ChangeFocus)
+{
+ 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 */
+
+ 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)
+ {
+ return(NULL);
+ }
+ 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)))
+ {
+ IntReleaseWindowObject(Window);
+ return(0);
+ }
+ ThreadQueue = (PUSER_MESSAGE_QUEUE)PsGetWin32Thread()->MessageQueue;
+ if (Window->MessageQueue != ThreadQueue)
+ {
+ IntReleaseWindowObject(Window);
+ return(0);
+ }
+ Prev = Window->MessageQueue->ActiveWindow;
+ WinPosSetActiveWindow(Window, FALSE, FALSE);
+ IntReleaseWindowObject(Window);
+ return(Prev);
+}
+
+
+/* EOF */