1 /* $Id: winpos.c,v 1.5 2002/09/17 23:43:28 dwelch Exp $
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
6 * FILE: subsys/win32k/ntuser/window.c
7 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
9 * 06-06-2001 CSH Created
11 /* INCLUDES ******************************************************************/
13 #include <ddk/ntddk.h>
14 #include <win32k/win32k.h>
15 #include <include/object.h>
16 #include <include/guicheck.h>
17 #include <include/window.h>
18 #include <include/class.h>
19 #include <include/error.h>
20 #include <include/winsta.h>
22 #include <include/winpos.h>
23 #include <include/rect.h>
24 #include <include/callback.h>
25 #include <include/painting.h>
30 /* GLOBALS *******************************************************************/
32 #define MINMAX_NOSWP (0x00010000)
34 #define SWP_EX_PAINTSELF 0x0002
36 ATOM AtomInternalPos
= NULL
;
38 /* FUNCTIONS *****************************************************************/
40 #define HAS_DLGFRAME(Style, ExStyle) \
41 (((ExStyle) & WS_EX_DLGMODALFRAME) || \
42 (((Style) & WS_DLGFRAME) && !((Style) & WS_BORDER)))
44 #define HAS_THICKFRAME(Style, ExStyle) \
45 (((Style) & WS_THICKFRAME) && \
46 !((Style) & (WS_DLGFRAME | WS_BORDER)) == WS_DLGFRAME)
49 WinPosSetupInternalPos(VOID
)
51 AtomInternalPos
= NtAddAtom(L
"SysIP", (ATOM
*)(PULONG
)&AtomInternalPos
);
55 NtUserGetClientOrigin(HWND hWnd
, LPPOINT Point
)
57 PWINDOW_OBJECT WindowObject
;
59 WindowObject
= W32kGetWindowObject(hWnd
);
60 if (WindowObject
== NULL
)
64 Point
->x
= WindowObject
->ClientRect
.left
;
65 Point
->y
= WindowObject
->ClientRect
.right
;
70 WinPosActivateOtherWindow(PWINDOW_OBJECT Window
)
75 WinPosFindIconPos(HWND hWnd
, POINT Pos
)
80 WinPosCreateIconTitle(PWINDOW_OBJECT WindowObject
)
86 WinPosShowIconTitle(PWINDOW_OBJECT WindowObject
, BOOL Show
)
88 PINTERNALPOS InternalPos
= NtUserGetProp(WindowObject
->Self
,
90 PWINDOW_OBJECT IconWindow
;
95 HWND hWnd
= InternalPos
->IconTitle
;
99 hWnd
= WinPosCreateIconTitle(WindowObject
);
104 ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation
->
108 (PVOID
*)&IconWindow
);
109 if (NT_SUCCESS(Status
))
111 if (!(IconWindow
->Style
& WS_VISIBLE
))
113 NtUserSendMessage(hWnd
, WM_SHOWWINDOW
, TRUE
, 0);
114 WinPosSetWindowPos(hWnd
, 0, 0, 0, 0, 0, SWP_NOSIZE
|
115 SWP_NOMOVE
| SWP_NOACTIVATE
|
116 SWP_NOZORDER
| SWP_SHOWWINDOW
);
118 ObmDereferenceObject(IconWindow
);
123 WinPosShowWindow(hWnd
, SW_HIDE
);
130 WinPosInitInternalPos(PWINDOW_OBJECT WindowObject
, POINT pt
, PRECT RestoreRect
)
132 PINTERNALPOS InternalPos
= NtUserGetProp(WindowObject
->Self
,
134 if (InternalPos
== NULL
)
137 ExAllocatePool(NonPagedPool
, sizeof(INTERNALPOS
));
138 NtUserSetProp(WindowObject
->Self
, AtomInternalPos
, InternalPos
);
139 InternalPos
->IconTitle
= 0;
140 InternalPos
->NormalRect
= WindowObject
->WindowRect
;
141 InternalPos
->IconPos
.x
= InternalPos
->MaxPos
.x
= 0xFFFFFFFF;
142 InternalPos
->IconPos
.y
= InternalPos
->MaxPos
.y
= 0xFFFFFFFF;
144 if (WindowObject
->Style
& WS_MINIMIZE
)
146 InternalPos
->IconPos
= pt
;
148 else if (WindowObject
->Style
& WS_MAXIMIZE
)
150 InternalPos
->MaxPos
= pt
;
152 else if (RestoreRect
!= NULL
)
154 InternalPos
->NormalRect
= *RestoreRect
;
160 WinPosMinMaximize(PWINDOW_OBJECT WindowObject
, UINT ShowFlag
, RECT
* NewPos
)
163 PINTERNALPOS InternalPos
;
166 Size
.x
= WindowObject
->WindowRect
.left
;
167 Size
.y
= WindowObject
->WindowRect
.top
;
168 InternalPos
= WinPosInitInternalPos(WindowObject
, Size
,
169 &WindowObject
->WindowRect
);
173 if (WindowObject
->Style
& WS_MINIMIZE
)
175 if (!NtUserSendMessage(WindowObject
->Self
, WM_QUERYOPEN
, 0, 0))
177 return(SWP_NOSIZE
| SWP_NOMOVE
);
179 SwpFlags
|= SWP_NOCOPYBITS
;
185 if (WindowObject
->Style
& WS_MAXIMIZE
)
187 WindowObject
->Flags
|= WINDOWOBJECT_RESTOREMAX
;
188 WindowObject
->Style
&= ~WS_MAXIMIZE
;
192 WindowObject
->Style
&= ~WINDOWOBJECT_RESTOREMAX
;
194 WindowObject
->Style
|= WS_MINIMIZE
;
195 InternalPos
->IconPos
= WinPosFindIconPos(WindowObject
,
196 InternalPos
->IconPos
);
197 W32kSetRect(NewPos
, InternalPos
->IconPos
.x
, InternalPos
->IconPos
.y
,
198 NtUserGetSystemMetrics(SM_CXICON
),
199 NtUserGetSystemMetrics(SM_CYICON
));
200 SwpFlags
|= SWP_NOCOPYBITS
;
206 WinPosGetMinMaxInfo(WindowObject
, &Size
, &InternalPos
->MaxPos
,
208 if (WindowObject
->Style
& WS_MINIMIZE
)
210 WinPosShowIconTitle(WindowObject
, FALSE
);
211 WindowObject
->Style
&= ~WS_MINIMIZE
;
213 WindowObject
->Style
|= WS_MINIMIZE
;
214 W32kSetRect(NewPos
, InternalPos
->MaxPos
.x
, InternalPos
->MaxPos
.y
,
221 if (WindowObject
->Style
& WS_MINIMIZE
)
223 WindowObject
->Style
&= ~WS_MINIMIZE
;
224 WinPosShowIconTitle(WindowObject
, FALSE
);
225 if (WindowObject
->Flags
& WINDOWOBJECT_RESTOREMAX
)
227 WinPosGetMinMaxInfo(WindowObject
, &Size
,
228 &InternalPos
->MaxPos
, NULL
, NULL
);
229 WindowObject
->Style
|= WS_MAXIMIZE
;
230 W32kSetRect(NewPos
, InternalPos
->MaxPos
.x
,
231 InternalPos
->MaxPos
.y
, Size
.x
, Size
.y
);
237 if (!(WindowObject
->Style
& WS_MAXIMIZE
))
243 WindowObject
->Style
&= ~WS_MAXIMIZE
;
245 *NewPos
= InternalPos
->NormalRect
;
246 NewPos
->right
-= NewPos
->left
;
247 NewPos
->bottom
-= NewPos
->top
;
255 SwpFlags
|= SWP_NOSIZE
| SWP_NOMOVE
;
261 WinPosGetMinMaxInfo(PWINDOW_OBJECT Window
, POINT
* MaxSize
, POINT
* MaxPos
,
262 POINT
* MinTrack
, POINT
* MaxTrack
)
268 /* Get default values. */
269 MinMax
.ptMaxSize
.x
= NtUserGetSystemMetrics(SM_CXSCREEN
);
270 MinMax
.ptMaxSize
.y
= NtUserGetSystemMetrics(SM_CYSCREEN
);
271 MinMax
.ptMinTrackSize
.x
= NtUserGetSystemMetrics(SM_CXMINTRACK
);
272 MinMax
.ptMinTrackSize
.y
= NtUserGetSystemMetrics(SM_CYMINTRACK
);
273 MinMax
.ptMaxTrackSize
.x
= NtUserGetSystemMetrics(SM_CXSCREEN
);
274 MinMax
.ptMaxTrackSize
.y
= NtUserGetSystemMetrics(SM_CYSCREEN
);
276 if (HAS_DLGFRAME(Window
->Style
, Window
->ExStyle
))
278 XInc
= NtUserGetSystemMetrics(SM_CXDLGFRAME
);
279 YInc
= NtUserGetSystemMetrics(SM_CYDLGFRAME
);
284 if (HAS_THICKFRAME(Window
->Style
, Window
->ExStyle
))
286 XInc
+= NtUserGetSystemMetrics(SM_CXFRAME
);
287 YInc
+= NtUserGetSystemMetrics(SM_CYFRAME
);
289 if (Window
->Style
& WS_BORDER
)
291 XInc
+= NtUserGetSystemMetrics(SM_CXBORDER
);
292 YInc
+= NtUserGetSystemMetrics(SM_CYBORDER
);
295 MinMax
.ptMaxSize
.x
+= 2 * XInc
;
296 MinMax
.ptMaxSize
.y
+= 2 * YInc
;
298 Pos
= NtUserGetProp(Window
->Self
, AtomInternalPos
);
301 MinMax
.ptMaxPosition
= Pos
->MaxPos
;
305 MinMax
.ptMaxPosition
.x
-= XInc
;
306 MinMax
.ptMaxPosition
.y
-= YInc
;
309 W32kSendMessage(Window
->Self
, WM_GETMINMAXINFO
, 0, (LPARAM
)&MinMax
, TRUE
);
311 MinMax
.ptMaxTrackSize
.x
= max(MinMax
.ptMaxTrackSize
.x
,
312 MinMax
.ptMinTrackSize
.x
);
313 MinMax
.ptMaxTrackSize
.y
= max(MinMax
.ptMaxTrackSize
.y
,
314 MinMax
.ptMinTrackSize
.y
);
316 if (MaxSize
) *MaxSize
= MinMax
.ptMaxSize
;
317 if (MaxPos
) *MaxPos
= MinMax
.ptMaxPosition
;
318 if (MinTrack
) *MinTrack
= MinMax
.ptMinTrackSize
;
319 if (MaxTrack
) *MaxTrack
= MinMax
.ptMaxTrackSize
;
323 WinPosChangeActiveWindow(HWND Wnd
, BOOL MouseMsg
)
328 WinPosDoNCCALCSize(PWINDOW_OBJECT Window
, PWINDOWPOS WinPos
,
329 RECT
* WindowRect
, RECT
* ClientRect
)
334 WinPosDoWinPosChanging(PWINDOW_OBJECT WindowObject
,
339 if (!(WinPos
->flags
& SWP_NOSENDCHANGING
))
341 NtUserSendMessage(WindowObject
->Self
, WM_WINDOWPOSCHANGING
, 0,
345 *WindowRect
= WindowObject
->WindowRect
;
347 (WindowObject
->Style
& WS_MINIMIZE
) ? WindowObject
->WindowRect
:
348 WindowObject
->ClientRect
;
350 if (!(WinPos
->flags
& SWP_NOSIZE
))
352 WindowRect
->right
= WindowRect
->left
+ WinPos
->cx
;
353 WindowRect
->bottom
= WindowRect
->top
+ WinPos
->cy
;
356 if (!(WinPos
->flags
& SWP_NOMOVE
))
358 WindowRect
->left
= WinPos
->x
;
359 WindowRect
->top
= WinPos
->y
;
360 WindowRect
->right
+= WinPos
->x
- WindowObject
->WindowRect
.left
;
361 WindowRect
->bottom
+= WinPos
->y
- WindowObject
->WindowRect
.top
;
363 W32kOffsetRect(ClientRect
, WinPos
->x
- WindowObject
->WindowRect
.left
,
364 WinPos
->y
- WindowObject
->WindowRect
.top
);
367 WinPos
->flags
|= SWP_NOCLIENTMOVE
| SWP_NOCLIENTSIZE
;
372 WinPosSetWindowPos(HWND Wnd
, HWND WndInsertAfter
, INT x
, INT y
, INT cx
,
375 PWINDOW_OBJECT Window
;
383 /* FIXME: Get current active window from active queue. */
385 /* Check if the window is for a desktop. */
386 if (Wnd
== PsGetWin32Thread()->Desktop
->DesktopWindow
)
392 ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation
->HandleTable
,
396 if (!NT_SUCCESS(Status
))
401 /* Fix up the flags. */
402 if (Window
->Style
& WS_VISIBLE
)
404 flags
&= ~SWP_SHOWWINDOW
;
408 if (!(flags
& SWP_SHOWWINDOW
))
410 flags
|= SWP_NOREDRAW
;
412 flags
&= ~SWP_HIDEWINDOW
;
418 if ((Window
->WindowRect
.right
- Window
->WindowRect
.left
) == cx
&&
419 (Window
->WindowRect
.bottom
- Window
->WindowRect
.top
) == cy
)
423 if (Window
->WindowRect
.left
== x
&& Window
->WindowRect
.top
== y
)
427 if (FALSE
/* FIXME: Check if the window if already active. */)
429 flags
|= SWP_NOACTIVATE
;
431 else if ((Window
->Style
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)
433 if (!(flags
& SWP_NOACTIVATE
))
435 flags
&= ~SWP_NOZORDER
;
436 WndInsertAfter
= HWND_TOP
;
440 if (WndInsertAfter
== HWND_TOPMOST
|| WndInsertAfter
== HWND_NOTOPMOST
)
442 WndInsertAfter
= HWND_TOP
;
445 if (WndInsertAfter
!= HWND_TOP
&& WndInsertAfter
!= HWND_BOTTOM
)
447 /* FIXME: Find the window to insert after. */
451 WinPos
.hwndInsertAfter
= WndInsertAfter
;
456 WinPos
.flags
= flags
;
458 WinPosDoWinPosChanging(Window
, &WinPos
, &NewWindowRect
, &NewClientRect
);
460 if ((WinPos
.flags
& (SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) !=
463 /* FIXME: SWP_DoOwnedPopups. */
466 /* FIXME: Adjust flags based on WndInsertAfter */
468 if ((!(WinPos
.flags
& (SWP_NOREDRAW
| SWP_SHOWWINDOW
)) &&
469 WinPos
.flags
& (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
|
470 SWP_HIDEWINDOW
| SWP_FRAMECHANGED
)) !=
471 (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
))
473 if (Window
->Style
& WS_CLIPCHILDREN
)
475 VisRgn
= DceGetVisRgn(Wnd
, DCX_WINDOW
| DCX_CLIPSIBLINGS
, 0, 0);
479 VisRgn
= DceGetVisRgn(Wnd
, DCX_WINDOW
, 0, 0);
483 WvrFlags
= WinPosDoNCCALCSize(Window
, &WinPos
, &NewWindowRect
,
486 /* FIXME: Relink windows. */
488 /* FIXME: Reset active DCEs */
490 /* FIXME: Check for redrawing the whole client rect. */
492 if (WinPos
.flags
& SWP_SHOWWINDOW
)
494 Window
->Style
|= WS_VISIBLE
;
495 flags
|= SWP_EX_PAINTSELF
;
500 /* FIXME: Move the window bits */
503 if (WinPos
.flags
& SWP_HIDEWINDOW
)
505 Window
->Style
&= ~WS_VISIBLE
;
508 /* FIXME: Hide or show the claret */
512 if (!(WinPos
.flags
& SWP_NOREDRAW
))
514 if (flags
& SWP_EX_PAINTSELF
)
516 PaintRedrawWindow(Window
->Self
, NULL
,
517 (VisRgn
== 1) ? 0 : VisRgn
,
518 RDW_ERASE
| RDW_FRAME
| RDW_INVALIDATE
|
520 RDW_EX_XYWINDOW
| RDW_EX_USEHRGN
);
524 PaintRedrawWindow(Window
->Self
, NULL
,
525 (VisRgn
== 1) ? 0 : VisRgn
,
526 RDW_ERASE
| RDW_INVALIDATE
| RDW_ALLCHILDREN
,
529 /* FIXME: Redraw the window parent. */
531 /* FIXME: Delete VisRgn */
534 if (!(flags
& SWP_NOACTIVATE
))
536 WinPosChangeActiveWindow(WinPos
.hwnd
, FALSE
);
539 /* FIXME: Check some conditions before doing this. */
540 NtUserSendMessage(WinPos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
)&WinPos
);
542 ObmDereferenceObject(Window
);
547 WinPosGetNonClientSize(HWND Wnd
, RECT
* WindowRect
, RECT
* ClientRect
)
549 *ClientRect
= *WindowRect
;
550 return(W32kSendNCCALCSIZEMessage(Wnd
, FALSE
, ClientRect
, NULL
));
554 WinPosShowWindow(HWND Wnd
, INT Cmd
)
557 PWINDOW_OBJECT Window
;
564 ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation
->HandleTable
,
568 if (!NT_SUCCESS(Status
))
573 WasVisible
= (Window
->Style
& WS_VISIBLE
) != 0;
581 ObmDereferenceObject(Window
);
584 Swp
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
|
589 case SW_SHOWMINNOACTIVE
:
590 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
592 case SW_SHOWMINIMIZED
:
593 Swp
|= SWP_SHOWWINDOW
;
597 Swp
|= SWP_FRAMECHANGED
;
598 if (!(Window
->Style
& WS_MINIMIZE
))
600 Swp
|= WinPosMinMaximize(Window
, SW_MINIMIZE
, &NewPos
);
604 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
609 case SW_SHOWMAXIMIZED
:
611 Swp
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
612 if (!(Window
->Style
& WS_MAXIMIZE
))
614 Swp
|= WinPosMinMaximize(Window
, SW_MAXIMIZE
, &NewPos
);
618 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
624 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
627 Swp
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
628 /* Don't activate the topmost window. */
631 case SW_SHOWNOACTIVATE
:
637 Swp
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
638 if (Window
->Style
& (WS_MINIMIZE
| WS_MAXIMIZE
))
640 Swp
|= WinPosMinMaximize(Window
, SW_RESTORE
, &NewPos
);
644 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
649 ShowFlag
= (Cmd
!= SW_HIDE
);
650 if (ShowFlag
!= WasVisible
)
652 NtUserSendMessage(Wnd
, WM_SHOWWINDOW
, ShowFlag
, 0);
654 * FIXME: Need to check the window wasn't destroyed during the
659 if (Window
->Style
& WS_CHILD
&&
660 !W32kIsWindowVisible(Window
->Parent
->Self
) &&
661 (Swp
& (SWP_NOSIZE
| SWP_NOMOVE
)) == (SWP_NOSIZE
| SWP_NOMOVE
))
665 Window
->Style
&= ~WS_VISIBLE
;
669 Window
->Style
|= WS_VISIBLE
;
674 if (Window
->Style
& WS_CHILD
&&
675 !(Window
->ExStyle
& WS_EX_MDICHILD
))
677 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
679 if (!(Swp
& MINMAX_NOSWP
))
681 WinPosSetWindowPos(Wnd
, HWND_TOP
, NewPos
.left
, NewPos
.top
,
682 NewPos
.right
, NewPos
.bottom
, LOWORD(Swp
));
685 /* Hide the window. */
686 if (Wnd
== W32kGetActiveWindow())
688 WinPosActivateOtherWindow(Window
);
690 /* Revert focus to parent. */
691 if (Wnd
== W32kGetFocusWindow() ||
692 W32kIsChildWindow(Wnd
, W32kGetFocusWindow()))
694 W32kSetFocusWindow(Window
->Parent
->Self
);
698 /* FIXME: Check for window destruction. */
699 /* Show title for minimized windows. */
700 if (Window
->Style
& WS_MINIMIZE
)
702 WinPosShowIconTitle(Window
, TRUE
);
706 if (Window
->Flags
& WINDOWOBJECT_NEED_SIZE
)
708 WPARAM wParam
= SIZE_RESTORED
;
710 Window
->Flags
&= ~WINDOWOBJECT_NEED_SIZE
;
711 if (Window
->Style
& WS_MAXIMIZE
)
713 wParam
= SIZE_MAXIMIZED
;
715 else if (Window
->Style
& WS_MINIMIZE
)
717 wParam
= SIZE_MINIMIZED
;
720 NtUserSendMessage(Wnd
, WM_SIZE
, wParam
,
721 MAKELONG(Window
->ClientRect
.right
-
722 Window
->ClientRect
.left
,
723 Window
->ClientRect
.bottom
-
724 Window
->ClientRect
.top
));
725 NtUserSendMessage(Wnd
, WM_MOVE
, 0,
726 MAKELONG(Window
->ClientRect
.left
,
727 Window
->ClientRect
.top
));
729 ObmDereferenceObject(Window
);