2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
24 * FILE: subsys/win32k/ntuser/window.c
25 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
27 * 06-06-2001 CSH NtGdid
29 /* INCLUDES ******************************************************************/
31 #include <ddk/ntddk.h>
32 #include <win32k/win32k.h>
33 #include <include/object.h>
34 #include <include/guicheck.h>
35 #include <include/window.h>
36 #include <include/class.h>
37 #include <include/error.h>
38 #include <include/winsta.h>
40 #include <include/winpos.h>
41 #include <include/rect.h>
42 #include <include/callback.h>
43 #include <include/painting.h>
44 #include <include/dce.h>
45 #include <include/vis.h>
50 /* GLOBALS *******************************************************************/
52 #define MINMAX_NOSWP (0x00010000)
54 #define SWP_EX_NOCOPY 0x0001
55 #define SWP_EX_PAINTSELF 0x0002
57 #define SWP_AGG_NOGEOMETRYCHANGE \
58 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
59 #define SWP_AGG_NOPOSCHANGE \
60 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
61 #define SWP_AGG_STATUSFLAGS \
62 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
64 ATOM AtomInternalPos = (ATOM) NULL;
66 /* FUNCTIONS *****************************************************************/
68 #define HAS_DLGFRAME(Style, ExStyle) \
69 (((ExStyle) & WS_EX_DLGMODALFRAME) || \
70 (((Style) & WS_DLGFRAME) && !((Style) & WS_BORDER)))
72 #define HAS_THICKFRAME(Style, ExStyle) \
73 (((Style) & WS_THICKFRAME) && \
74 !((Style) & (WS_DLGFRAME | WS_BORDER)) == WS_DLGFRAME)
77 WinPosSetupInternalPos(VOID)
79 AtomInternalPos = NtAddAtom(L"SysIP", (ATOM*)(PULONG)&AtomInternalPos);
83 NtUserGetClientOrigin(HWND hWnd, LPPOINT Point)
85 PWINDOW_OBJECT WindowObject;
87 WindowObject = IntGetWindowObject(hWnd);
88 if (WindowObject == NULL)
90 Point->x = Point->y = 0;
93 Point->x = WindowObject->ClientRect.left;
94 Point->y = WindowObject->ClientRect.top;
99 WinPosActivateOtherWindow(PWINDOW_OBJECT Window)
104 POINT STATIC FASTCALL
105 WinPosFindIconPos(HWND hWnd, POINT Pos)
113 WinPosNtGdiIconTitle(PWINDOW_OBJECT WindowObject)
119 WinPosShowIconTitle(PWINDOW_OBJECT WindowObject, BOOL Show)
121 PINTERNALPOS InternalPos = (PINTERNALPOS)IntGetProp(WindowObject, AtomInternalPos);
122 PWINDOW_OBJECT IconWindow;
127 HWND hWnd = InternalPos->IconTitle;
131 hWnd = WinPosNtGdiIconTitle(WindowObject);
136 ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation->
140 (PVOID*)&IconWindow);
141 if (NT_SUCCESS(Status))
143 if (!(IconWindow->Style & WS_VISIBLE))
145 NtUserSendMessage(hWnd, WM_SHOWWINDOW, TRUE, 0);
146 WinPosSetWindowPos(hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE |
147 SWP_NOMOVE | SWP_NOACTIVATE |
148 SWP_NOZORDER | SWP_SHOWWINDOW);
150 ObmDereferenceObject(IconWindow);
155 WinPosShowWindow(hWnd, SW_HIDE);
161 PINTERNALPOS STATIC STDCALL
162 WinPosInitInternalPos(PWINDOW_OBJECT WindowObject, POINT pt, PRECT RestoreRect)
164 PINTERNALPOS InternalPos = (PINTERNALPOS)IntGetProp(WindowObject, AtomInternalPos);
165 if (InternalPos == NULL)
168 ExAllocatePool(NonPagedPool, sizeof(INTERNALPOS));
169 IntSetProp(WindowObject, AtomInternalPos, InternalPos);
170 InternalPos->IconTitle = 0;
171 InternalPos->NormalRect = WindowObject->WindowRect;
172 InternalPos->IconPos.x = InternalPos->MaxPos.x = 0xFFFFFFFF;
173 InternalPos->IconPos.y = InternalPos->MaxPos.y = 0xFFFFFFFF;
175 if (WindowObject->Style & WS_MINIMIZE)
177 InternalPos->IconPos = pt;
179 else if (WindowObject->Style & WS_MAXIMIZE)
181 InternalPos->MaxPos = pt;
183 else if (RestoreRect != NULL)
185 InternalPos->NormalRect = *RestoreRect;
191 WinPosMinMaximize(PWINDOW_OBJECT WindowObject, UINT ShowFlag, RECT* NewPos)
194 PINTERNALPOS InternalPos;
197 Size.x = WindowObject->WindowRect.left;
198 Size.y = WindowObject->WindowRect.top;
199 InternalPos = WinPosInitInternalPos(WindowObject, Size,
200 &WindowObject->WindowRect);
204 if (WindowObject->Style & WS_MINIMIZE)
206 if (!NtUserSendMessage(WindowObject->Self, WM_QUERYOPEN, 0, 0))
208 return(SWP_NOSIZE | SWP_NOMOVE);
210 SwpFlags |= SWP_NOCOPYBITS;
216 if (WindowObject->Style & WS_MAXIMIZE)
218 WindowObject->Flags |= WINDOWOBJECT_RESTOREMAX;
219 WindowObject->Style &= ~WS_MAXIMIZE;
223 WindowObject->Style &= ~WINDOWOBJECT_RESTOREMAX;
225 WindowObject->Style |= WS_MINIMIZE;
226 InternalPos->IconPos = WinPosFindIconPos(WindowObject,
227 InternalPos->IconPos);
228 NtGdiSetRect(NewPos, InternalPos->IconPos.x, InternalPos->IconPos.y,
229 NtUserGetSystemMetrics(SM_CXICON),
230 NtUserGetSystemMetrics(SM_CYICON));
231 SwpFlags |= SWP_NOCOPYBITS;
237 WinPosGetMinMaxInfo(WindowObject, &Size, &InternalPos->MaxPos,
239 if (WindowObject->Style & WS_MINIMIZE)
241 WinPosShowIconTitle(WindowObject, FALSE);
242 WindowObject->Style &= ~WS_MINIMIZE;
244 WindowObject->Style |= WS_MINIMIZE;
245 NtGdiSetRect(NewPos, InternalPos->MaxPos.x, InternalPos->MaxPos.y,
252 if (WindowObject->Style & WS_MINIMIZE)
254 WindowObject->Style &= ~WS_MINIMIZE;
255 WinPosShowIconTitle(WindowObject, FALSE);
256 if (WindowObject->Flags & WINDOWOBJECT_RESTOREMAX)
258 WinPosGetMinMaxInfo(WindowObject, &Size,
259 &InternalPos->MaxPos, NULL, NULL);
260 WindowObject->Style |= WS_MAXIMIZE;
261 NtGdiSetRect(NewPos, InternalPos->MaxPos.x,
262 InternalPos->MaxPos.y, Size.x, Size.y);
268 if (!(WindowObject->Style & WS_MAXIMIZE))
274 WindowObject->Style &= ~WS_MAXIMIZE;
276 *NewPos = InternalPos->NormalRect;
277 NewPos->right -= NewPos->left;
278 NewPos->bottom -= NewPos->top;
286 SwpFlags |= SWP_NOSIZE | SWP_NOMOVE;
292 WinPosGetMinMaxInfo(PWINDOW_OBJECT Window, POINT* MaxSize, POINT* MaxPos,
293 POINT* MinTrack, POINT* MaxTrack)
299 /* Get default values. */
300 MinMax.ptMaxSize.x = NtUserGetSystemMetrics(SM_CXSCREEN);
301 MinMax.ptMaxSize.y = NtUserGetSystemMetrics(SM_CYSCREEN);
302 MinMax.ptMinTrackSize.x = NtUserGetSystemMetrics(SM_CXMINTRACK);
303 MinMax.ptMinTrackSize.y = NtUserGetSystemMetrics(SM_CYMINTRACK);
304 MinMax.ptMaxTrackSize.x = NtUserGetSystemMetrics(SM_CXSCREEN);
305 MinMax.ptMaxTrackSize.y = NtUserGetSystemMetrics(SM_CYSCREEN);
307 if (HAS_DLGFRAME(Window->Style, Window->ExStyle))
309 XInc = NtUserGetSystemMetrics(SM_CXDLGFRAME);
310 YInc = NtUserGetSystemMetrics(SM_CYDLGFRAME);
315 if (HAS_THICKFRAME(Window->Style, Window->ExStyle))
317 XInc += NtUserGetSystemMetrics(SM_CXFRAME);
318 YInc += NtUserGetSystemMetrics(SM_CYFRAME);
320 if (Window->Style & WS_BORDER)
322 XInc += NtUserGetSystemMetrics(SM_CXBORDER);
323 YInc += NtUserGetSystemMetrics(SM_CYBORDER);
326 MinMax.ptMaxSize.x += 2 * XInc;
327 MinMax.ptMaxSize.y += 2 * YInc;
329 Pos = (PINTERNALPOS)IntGetProp(Window, AtomInternalPos);
332 MinMax.ptMaxPosition = Pos->MaxPos;
336 MinMax.ptMaxPosition.x -= XInc;
337 MinMax.ptMaxPosition.y -= YInc;
340 IntSendMessage(Window->Self, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax, TRUE);
342 MinMax.ptMaxTrackSize.x = max(MinMax.ptMaxTrackSize.x,
343 MinMax.ptMinTrackSize.x);
344 MinMax.ptMaxTrackSize.y = max(MinMax.ptMaxTrackSize.y,
345 MinMax.ptMinTrackSize.y);
347 if (MaxSize) *MaxSize = MinMax.ptMaxSize;
348 if (MaxPos) *MaxPos = MinMax.ptMaxPosition;
349 if (MinTrack) *MinTrack = MinMax.ptMinTrackSize;
350 if (MaxTrack) *MaxTrack = MinMax.ptMaxTrackSize;
352 return 0; //FIXME: what does it return?
356 WinPosChangeActiveWindow(HWND hWnd, BOOL MouseMsg)
358 PWINDOW_OBJECT WindowObject;
360 WindowObject = IntGetWindowObject(hWnd);
361 if (WindowObject == NULL)
366 NtUserSendMessage(hWnd,
368 MAKELONG(MouseMsg ? WA_CLICKACTIVE : WA_CLICKACTIVE,
369 (WindowObject->Style & WS_MINIMIZE) ? 1 : 0),
370 (LPARAM)IntGetDesktopWindow()); /* FIXME: Previous active window */
372 IntReleaseWindowObject(WindowObject);
378 WinPosDoNCCALCSize(PWINDOW_OBJECT Window, PWINDOWPOS WinPos,
379 RECT* WindowRect, RECT* ClientRect)
383 /* Send WM_NCCALCSIZE message to get new client area */
384 if ((WinPos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE)
386 NCCALCSIZE_PARAMS params;
387 WINDOWPOS winposCopy;
389 params.rgrc[0] = *WindowRect;
390 params.rgrc[1] = Window->WindowRect;
391 params.rgrc[2] = Window->ClientRect;
392 if (Window->Style & WS_CHILD)
394 NtGdiOffsetRect(&(params.rgrc[2]), - Window->Parent->ClientRect.left,
395 - Window->Parent->ClientRect.top);
397 params.lppos = &winposCopy;
398 winposCopy = *WinPos;
400 wvrFlags = IntSendNCCALCSIZEMessage(Window->Self, TRUE, NULL, ¶ms);
402 /* If the application send back garbage, ignore it */
403 if (params.rgrc[0].left <= params.rgrc[0].right &&
404 params.rgrc[0].top <= params.rgrc[0].bottom)
406 *ClientRect = params.rgrc[0];
407 if (Window->Style & WS_CHILD)
409 NtGdiOffsetRect(ClientRect, Window->Parent->ClientRect.left,
410 Window->Parent->ClientRect.top);
414 /* FIXME: WVR_ALIGNxxx */
416 if (ClientRect->left != Window->ClientRect.left ||
417 ClientRect->top != Window->ClientRect.top)
419 WinPos->flags &= ~SWP_NOCLIENTMOVE;
422 if ((ClientRect->right - ClientRect->left !=
423 Window->ClientRect.right - Window->ClientRect.left) ||
424 (ClientRect->bottom - ClientRect->top !=
425 Window->ClientRect.bottom - Window->ClientRect.top))
427 WinPos->flags &= ~SWP_NOCLIENTSIZE;
432 if (! (WinPos->flags & SWP_NOMOVE)
433 && (ClientRect->left != Window->ClientRect.left ||
434 ClientRect->top != Window->ClientRect.top))
436 WinPos->flags &= ~SWP_NOCLIENTMOVE;
444 WinPosDoWinPosChanging(PWINDOW_OBJECT WindowObject,
449 if (!(WinPos->flags & SWP_NOSENDCHANGING))
451 IntSendWINDOWPOSCHANGINGMessage(WindowObject->Self, WinPos);
454 *WindowRect = WindowObject->WindowRect;
456 (WindowObject->Style & WS_MINIMIZE) ? WindowObject->WindowRect :
457 WindowObject->ClientRect;
459 if (!(WinPos->flags & SWP_NOSIZE))
461 WindowRect->right = WindowRect->left + WinPos->cx;
462 WindowRect->bottom = WindowRect->top + WinPos->cy;
465 if (!(WinPos->flags & SWP_NOMOVE))
467 WindowRect->left = WinPos->x;
468 WindowRect->top = WinPos->y;
469 WindowRect->right += WinPos->x - WindowObject->WindowRect.left;
470 WindowRect->bottom += WinPos->y - WindowObject->WindowRect.top;
471 NtGdiOffsetRect(ClientRect,
472 WinPos->x - WindowObject->WindowRect.left,
473 WinPos->y - WindowObject->WindowRect.top);
476 WinPos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
481 /***********************************************************************
482 * WinPosInternalMoveWindow
484 * Update WindowRect and ClientRect of Window and all of its children
485 * We keep both WindowRect and ClientRect in screen coordinates internally
488 WinPosInternalMoveWindow(PWINDOW_OBJECT Window, INT MoveX, INT MoveY)
490 PWINDOW_OBJECT Child;
492 Window->WindowRect.left += MoveX;
493 Window->WindowRect.right += MoveX;
494 Window->WindowRect.top += MoveY;
495 Window->WindowRect.bottom += MoveY;
497 Window->ClientRect.left += MoveX;
498 Window->ClientRect.right += MoveX;
499 Window->ClientRect.top += MoveY;
500 Window->ClientRect.bottom += MoveY;
502 ExAcquireFastMutexUnsafe(&Window->ChildrenListLock);
503 Child = Window->FirstChild;
506 WinPosInternalMoveWindow(Child, MoveX, MoveY);
507 Child = Child->NextSibling;
509 ExReleaseFastMutexUnsafe(&Window->ChildrenListLock);
514 WinPosSetWindowPos(HWND Wnd, HWND WndInsertAfter, INT x, INT y, INT cx,
517 PWINDOW_OBJECT Window;
522 HRGN VisBefore = NULL;
523 HRGN VisAfter = NULL;
524 HRGN DirtyRgn = NULL;
525 HRGN ExposedRgn = NULL;
528 RECT OldWindowRect, OldClientRect;
535 /* FIXME: Get current active window from active queue. */
537 /* Check if the window is for a desktop. */
538 if (Wnd == PsGetWin32Thread()->Desktop->DesktopWindow)
544 ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation->HandleTable,
548 if (!NT_SUCCESS(Status))
553 /* Fix up the flags. */
554 if (Window->Style & WS_VISIBLE)
556 flags &= ~SWP_SHOWWINDOW;
560 if (!(flags & SWP_SHOWWINDOW))
562 flags |= SWP_NOREDRAW;
564 flags &= ~SWP_HIDEWINDOW;
570 if ((Window->WindowRect.right - Window->WindowRect.left) == cx &&
571 (Window->WindowRect.bottom - Window->WindowRect.top) == cy)
575 if (Window->WindowRect.left == x && Window->WindowRect.top == y)
579 if (Window->Style & WIN_NCACTIVATED)
581 flags |= SWP_NOACTIVATE;
583 else if ((Window->Style & (WS_POPUP | WS_CHILD)) != WS_CHILD)
585 if (!(flags & SWP_NOACTIVATE))
587 flags &= ~SWP_NOZORDER;
588 WndInsertAfter = HWND_TOP;
592 if (WndInsertAfter == HWND_TOPMOST || WndInsertAfter == HWND_NOTOPMOST)
594 WndInsertAfter = HWND_TOP;
597 if (WndInsertAfter != HWND_TOP && WndInsertAfter != HWND_BOTTOM)
599 /* FIXME: Find the window to insert after. */
603 WinPos.hwndInsertAfter = WndInsertAfter;
608 WinPos.flags = flags;
610 WinPosDoWinPosChanging(Window, &WinPos, &NewWindowRect, &NewClientRect);
612 if ((WinPos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) !=
615 /* FIXME: SWP_DoOwnedPopups. */
618 /* FIXME: Adjust flags based on WndInsertAfter */
620 /* Compute the visible region before the window position is changed */
621 if ((!(WinPos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) &&
622 WinPos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
623 SWP_HIDEWINDOW | SWP_FRAMECHANGED)) !=
624 (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER))
626 if (Window->Style & WS_CLIPCHILDREN)
628 VisBefore = VIS_ComputeVisibleRegion(PsGetWin32Thread()->Desktop,
629 Window, FALSE, FALSE, TRUE);
633 VisBefore = VIS_ComputeVisibleRegion(PsGetWin32Thread()->Desktop,
634 Window, FALSE, FALSE, FALSE);
636 if (NULLREGION == UnsafeIntGetRgnBox(VisBefore, &TempRect))
638 NtGdiDeleteObject(VisBefore);
643 WvrFlags = WinPosDoNCCALCSize(Window, &WinPos, &NewWindowRect,
646 /* FIXME: Relink windows. */
648 /* FIXME: Reset active DCEs */
650 OldWindowRect = Window->WindowRect;
651 OldClientRect = Window->ClientRect;
653 /* FIXME: Check for redrawing the whole client rect. */
655 if (! (WinPos.flags & SWP_NOMOVE))
657 WinPosInternalMoveWindow(Window,
658 NewWindowRect.left - OldWindowRect.left,
659 NewWindowRect.top - OldWindowRect.top);
661 Window->WindowRect = NewWindowRect;
662 Window->ClientRect = NewClientRect;
664 if (WinPos.flags & SWP_SHOWWINDOW)
666 Window->Style |= WS_VISIBLE;
667 FlagsEx |= SWP_EX_PAINTSELF;
669 else if (WinPos.flags & SWP_HIDEWINDOW)
671 Window->Style &= ~WS_VISIBLE;
674 if (!(WinPos.flags & SWP_NOREDRAW))
676 /* Determine the new visible region */
677 if (Window->Style & WS_CLIPCHILDREN)
679 VisAfter = VIS_ComputeVisibleRegion(PsGetWin32Thread()->Desktop,
680 Window, FALSE, FALSE, TRUE);
684 VisAfter = VIS_ComputeVisibleRegion(PsGetWin32Thread()->Desktop,
685 Window, FALSE, FALSE, FALSE);
687 if (NULLREGION == UnsafeIntGetRgnBox(VisAfter, &TempRect))
689 NtGdiDeleteObject(VisAfter);
693 /* Determine which pixels can be copied from the old window position
694 to the new. Those pixels must be visible in both the old and new
696 if (NULL != VisBefore && NULL != VisAfter && ! (WinPos.flags & SWP_NOCOPYBITS))
698 CopyRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
699 RgnType = NtGdiCombineRgn(CopyRgn, VisAfter, VisBefore, RGN_AND);
701 /* If this is (also) a window resize, the whole nonclient area
702 needs to be repainted. So we limit the copy to the client area,
703 'cause there is no use in copying it (would possibly cause
704 "flashing" too). However, if the copy region is already empty,
705 we don't have to crop (can't take anything away from an empty
707 if (! (WinPos.flags & SWP_NOSIZE)
708 && ERROR != RgnType && NULLREGION != RgnType)
710 RECT ORect = OldClientRect;
711 RECT NRect = NewClientRect;
712 NtGdiOffsetRect(&ORect, - OldWindowRect.left, - OldWindowRect.top);
713 NtGdiOffsetRect(&NRect, - NewWindowRect.left, - NewWindowRect.top);
714 NtGdiIntersectRect(&CopyRect, &ORect, &NRect);
715 REGION_CropRgn(CopyRgn, CopyRgn, &CopyRect, NULL);
718 /* No use in copying bits which are in the update region. */
719 if ((HRGN) 1 == Window->UpdateRegion)
721 /* The whole window is in the update region. No use
722 copying anything, so set the copy region empty */
723 NtGdiSetRectRgn(CopyRgn, 0, 0, 0, 0);
725 else if (1 < (DWORD) Window->UpdateRegion)
727 NtGdiCombineRgn(CopyRgn, CopyRgn, Window->UpdateRegion, RGN_DIFF);
731 /* Now, get the bounding box of the copy region. If it's empty
732 there's nothing to copy. Also, it's no use copying bits onto
734 UnsafeIntGetRgnBox(CopyRgn, &CopyRect);
735 if (NtGdiIsEmptyRect(&CopyRect))
737 /* Nothing to copy, clean up */
738 NtGdiDeleteObject(CopyRgn);
741 else if (OldWindowRect.left != NewWindowRect.left
742 || OldWindowRect.top != NewWindowRect.top)
744 /* Small trick here: there is no function to bitblt a region. So
745 we set the region as the clipping region, take the bounding box
746 of the region and bitblt that. Since nothing outside the clipping
747 region is copied, this has the effect of bitblt'ing the region.
749 Since NtUserGetDCEx takes ownership of the clip region, we need
750 to create a copy of CopyRgn and pass that. We need CopyRgn later */
751 HRGN ClipRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
752 NtGdiCombineRgn(ClipRgn, CopyRgn, NULL, RGN_COPY);
753 Dc = NtUserGetDCEx(Wnd, ClipRgn, DCX_WINDOW | DCX_CACHE |
754 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
755 NtGdiBitBlt(Dc, CopyRect.left, CopyRect.top, CopyRect.right - CopyRect.left,
756 CopyRect.bottom - CopyRect.top, Dc,
757 CopyRect.left + (OldWindowRect.left - NewWindowRect.left),
758 CopyRect.top + (OldWindowRect.top - NewWindowRect.top), SRCCOPY);
759 NtUserReleaseDC(Wnd, Dc);
767 /* We need to redraw what wasn't visible before */
768 if (NULL != VisAfter)
772 DirtyRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
773 RgnType = NtGdiCombineRgn(DirtyRgn, VisAfter, CopyRgn, RGN_DIFF);
774 if (ERROR != RgnType && NULLREGION != RgnType)
776 PaintRedrawWindow(Window, NULL, DirtyRgn,
777 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE |
778 RDW_ALLCHILDREN | RDW_ERASENOW,
779 RDW_EX_XYWINDOW | RDW_EX_USEHRGN);
781 NtGdiDeleteObject(DirtyRgn);
785 PaintRedrawWindow(Window, NULL, NULL,
786 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE |
787 RDW_ALLCHILDREN | RDW_ERASENOW,
788 RDW_EX_XYWINDOW | RDW_EX_USEHRGN);
794 NtGdiDeleteObject(CopyRgn);
798 /* Expose what was covered before but not covered anymore */
799 if (NULL != VisBefore)
801 ExposedRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
802 NtGdiCombineRgn(ExposedRgn, VisBefore, NULL, RGN_COPY);
803 NtGdiOffsetRgn(ExposedRgn, OldWindowRect.left - NewWindowRect.left,
804 OldWindowRect.top - NewWindowRect.top);
805 if (NULL != VisAfter)
807 RgnType = NtGdiCombineRgn(ExposedRgn, ExposedRgn, VisAfter, RGN_DIFF);
811 RgnType = SIMPLEREGION;
813 if (ERROR != RgnType && NULLREGION != RgnType)
815 VIS_WindowLayoutChanged(PsGetWin32Thread()->Desktop, Window, ExposedRgn);
817 NtGdiDeleteObject(ExposedRgn);
819 NtGdiDeleteObject(VisBefore);
822 if (NULL != VisAfter)
824 NtGdiDeleteObject(VisAfter);
827 /* FIXME: Hide or show the claret */
829 if (!(flags & SWP_NOACTIVATE))
831 WinPosChangeActiveWindow(WinPos.hwnd, FALSE);
834 /* FIXME: Check some conditions before doing this. */
835 IntSendWINDOWPOSCHANGEDMessage(WinPos.hwnd, &WinPos);
837 ObmDereferenceObject(Window);
842 WinPosGetNonClientSize(HWND Wnd, RECT* WindowRect, RECT* ClientRect)
844 *ClientRect = *WindowRect;
845 return(IntSendNCCALCSIZEMessage(Wnd, FALSE, ClientRect, NULL));
849 WinPosShowWindow(HWND Wnd, INT Cmd)
852 PWINDOW_OBJECT Window;
860 ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation->HandleTable,
864 if (!NT_SUCCESS(Status))
869 WasVisible = (Window->Style & WS_VISIBLE) != 0;
877 ObmDereferenceObject(Window);
880 Swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE |
885 case SW_SHOWMINNOACTIVE:
886 Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
888 case SW_SHOWMINIMIZED:
889 Swp |= SWP_SHOWWINDOW;
893 Swp |= SWP_FRAMECHANGED;
894 if (!(Window->Style & WS_MINIMIZE))
896 Swp |= WinPosMinMaximize(Window, SW_MINIMIZE, &NewPos);
900 Swp |= SWP_NOSIZE | SWP_NOMOVE;
905 case SW_SHOWMAXIMIZED:
907 Swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
908 if (!(Window->Style & WS_MAXIMIZE))
910 Swp |= WinPosMinMaximize(Window, SW_MAXIMIZE, &NewPos);
914 Swp |= SWP_NOSIZE | SWP_NOMOVE;
920 Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
923 Swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
924 /* Don't activate the topmost window. */
927 case SW_SHOWNOACTIVATE:
933 Swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
934 if (Window->Style & (WS_MINIMIZE | WS_MAXIMIZE))
936 Swp |= WinPosMinMaximize(Window, SW_RESTORE, &NewPos);
940 Swp |= SWP_NOSIZE | SWP_NOMOVE;
945 ShowFlag = (Cmd != SW_HIDE);
946 if (ShowFlag != WasVisible)
948 NtUserSendMessage(Wnd, WM_SHOWWINDOW, ShowFlag, 0);
950 * FIXME: Need to check the window wasn't destroyed during the
955 if (Window->Style & WS_CHILD &&
956 !IntIsWindowVisible(Window->Parent->Self) &&
957 (Swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE))
961 VisibleRgn = VIS_ComputeVisibleRegion(PsGetWin32Thread()->Desktop, Window,
962 FALSE, FALSE, FALSE);
963 Window->Style &= ~WS_VISIBLE;
964 VIS_WindowLayoutChanged(PsGetWin32Thread()->Desktop, Window, VisibleRgn);
965 NtGdiDeleteObject(VisibleRgn);
969 Window->Style |= WS_VISIBLE;
974 if (Window->Style & WS_CHILD &&
975 !(Window->ExStyle & WS_EX_MDICHILD))
977 Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
979 if (!(Swp & MINMAX_NOSWP))
981 WinPosSetWindowPos(Wnd, HWND_TOP, NewPos.left, NewPos.top,
982 NewPos.right, NewPos.bottom, LOWORD(Swp));
985 /* Hide the window. */
986 if (Wnd == IntGetActiveWindow())
988 WinPosActivateOtherWindow(Window);
990 /* Revert focus to parent. */
991 if (Wnd == IntGetFocusWindow() ||
992 IntIsChildWindow(Wnd, IntGetFocusWindow()))
994 IntSetFocusWindow(Window->Parent->Self);
998 /* FIXME: Check for window destruction. */
999 /* Show title for minimized windows. */
1000 if (Window->Style & WS_MINIMIZE)
1002 WinPosShowIconTitle(Window, TRUE);
1006 if (Window->Flags & WINDOWOBJECT_NEED_SIZE)
1008 WPARAM wParam = SIZE_RESTORED;
1010 Window->Flags &= ~WINDOWOBJECT_NEED_SIZE;
1011 if (Window->Style & WS_MAXIMIZE)
1013 wParam = SIZE_MAXIMIZED;
1015 else if (Window->Style & WS_MINIMIZE)
1017 wParam = SIZE_MINIMIZED;
1020 NtUserSendMessage(Wnd, WM_SIZE, wParam,
1021 MAKELONG(Window->ClientRect.right -
1022 Window->ClientRect.left,
1023 Window->ClientRect.bottom -
1024 Window->ClientRect.top));
1025 NtUserSendMessage(Wnd, WM_MOVE, 0,
1026 MAKELONG(Window->ClientRect.left,
1027 Window->ClientRect.top));
1030 /* Activate the window if activation is not requested and the window is not minimized */
1031 if (!(Swp & (SWP_NOACTIVATE | SWP_HIDEWINDOW)) && !(Window->Style & WS_MINIMIZE))
1033 WinPosChangeActiveWindow(Wnd, FALSE);
1036 ObmDereferenceObject(Window);
1040 BOOL STATIC FASTCALL
1041 WinPosPtInWindow(PWINDOW_OBJECT Window, POINT Point)
1043 return(Point.x >= Window->WindowRect.left &&
1044 Point.x < Window->WindowRect.right &&
1045 Point.y >= Window->WindowRect.top &&
1046 Point.y < Window->WindowRect.bottom);
1049 USHORT STATIC STDCALL
1050 WinPosSearchChildren(PWINDOW_OBJECT ScopeWin, POINT Point,
1051 PWINDOW_OBJECT* Window)
1053 PWINDOW_OBJECT Current;
1055 ExAcquireFastMutexUnsafe(&ScopeWin->ChildrenListLock);
1056 Current = ScopeWin->FirstChild;
1059 if (Current->Style & WS_VISIBLE &&
1060 ((!(Current->Style & WS_DISABLED)) ||
1061 (Current->Style & (WS_CHILD | WS_POPUP)) != WS_CHILD) &&
1062 WinPosPtInWindow(Current, Point))
1065 if (Current->Style & WS_DISABLED)
1067 ExReleaseFastMutexUnsafe(&ScopeWin->ChildrenListLock);
1070 if (Current->Style & WS_MINIMIZE)
1072 ExReleaseFastMutexUnsafe(&ScopeWin->ChildrenListLock);
1075 if (Point.x >= Current->ClientRect.left &&
1076 Point.x < Current->ClientRect.right &&
1077 Point.y >= Current->ClientRect.top &&
1078 Point.y < Current->ClientRect.bottom)
1081 ExReleaseFastMutexUnsafe(&ScopeWin->ChildrenListLock);
1082 return(WinPosSearchChildren(Current, Point, Window));
1085 ExReleaseFastMutexUnsafe(&ScopeWin->ChildrenListLock);
1088 Current = Current->NextSibling;
1091 ExReleaseFastMutexUnsafe(&ScopeWin->ChildrenListLock);
1096 WinPosWindowFromPoint(PWINDOW_OBJECT ScopeWin, POINT WinPoint,
1097 PWINDOW_OBJECT* Window)
1099 HWND DesktopWindowHandle;
1100 PWINDOW_OBJECT DesktopWindow;
1101 POINT Point = WinPoint;
1106 if (ScopeWin->Style & WS_DISABLED)
1111 /* Translate the point to the space of the scope window. */
1112 DesktopWindowHandle = IntGetDesktopWindow();
1113 DesktopWindow = IntGetWindowObject(DesktopWindowHandle);
1114 Point.x += ScopeWin->ClientRect.left - DesktopWindow->ClientRect.left;
1115 Point.y += ScopeWin->ClientRect.top - DesktopWindow->ClientRect.top;
1116 IntReleaseWindowObject(DesktopWindow);
1118 HitTest = WinPosSearchChildren(ScopeWin, Point, Window);
1124 if ((*Window) == NULL)
1128 if ((*Window)->MessageQueue == PsGetWin32Thread()->MessageQueue)
1130 HitTest = IntSendMessage((*Window)->Self, WM_NCHITTEST, 0,
1131 MAKELONG(Point.x, Point.y), FALSE);
1132 /* FIXME: Check for HTTRANSPARENT here. */
1143 WinPosSetActiveWindow(PWINDOW_OBJECT Window, BOOL Mouse, BOOL ChangeFocus)
1145 PUSER_MESSAGE_QUEUE ActiveQueue;
1148 ActiveQueue = IntGetFocusMessageQueue();
1149 if (ActiveQueue != NULL)
1151 PrevActive = ActiveQueue->ActiveWindow;
1158 if (Window->Self == IntGetActiveDesktop() || Window->Self == PrevActive)
1162 if (PrevActive != NULL)
1164 PWINDOW_OBJECT PrevActiveWindow = IntGetWindowObject(PrevActive);
1165 WORD Iconised = HIWORD(PrevActiveWindow->Style & WS_MINIMIZE);
1166 if (!IntSendMessage(PrevActive, WM_NCACTIVATE, FALSE, 0, TRUE))
1168 /* FIXME: Check if the new window is system modal. */
1171 IntSendMessage(PrevActive,
1173 MAKEWPARAM(WA_INACTIVE, Iconised),
1174 (LPARAM)Window->Self,
1176 /* FIXME: Check if anything changed while processing the message. */
1177 IntReleaseWindowObject(PrevActiveWindow);
1182 Window->MessageQueue->ActiveWindow = Window->Self;
1184 else if (ActiveQueue != NULL)
1186 ActiveQueue->ActiveWindow = NULL;
1188 /* FIXME: Unset this flag for inactive windows */
1189 //if ((Window->Style) & WS_CHILD) Window->Flags |= WIN_NCACTIVATED;
1191 /* FIXME: Send palette messages. */
1193 /* FIXME: Redraw icon title of previously active window. */
1195 /* FIXME: Bring the window to the top. */
1197 /* FIXME: Send WM_ACTIVATEAPP */
1199 IntSetFocusMessageQueue(Window->MessageQueue);
1201 /* FIXME: Send activate messages. */
1203 /* FIXME: Change focus. */
1205 /* FIXME: Redraw new window icon title. */
1211 NtUserGetActiveWindow(VOID)
1213 PUSER_MESSAGE_QUEUE ActiveQueue;
1215 ActiveQueue = IntGetFocusMessageQueue();
1216 if (ActiveQueue == NULL)
1220 return(ActiveQueue->ActiveWindow);
1224 NtUserSetActiveWindow(HWND hWnd)
1226 PWINDOW_OBJECT Window;
1227 PUSER_MESSAGE_QUEUE ThreadQueue;
1230 Window = IntGetWindowObject(hWnd);
1231 if (Window == NULL || (Window->Style & (WS_DISABLED | WS_CHILD)))
1233 IntReleaseWindowObject(Window);
1236 ThreadQueue = (PUSER_MESSAGE_QUEUE)PsGetWin32Thread()->MessageQueue;
1237 if (Window->MessageQueue != ThreadQueue)
1239 IntReleaseWindowObject(Window);
1242 Prev = Window->MessageQueue->ActiveWindow;
1243 WinPosSetActiveWindow(Window, FALSE, FALSE);
1244 IntReleaseWindowObject(Window);