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 ******************************************************************/
36 /* GLOBALS *******************************************************************/
38 #define MINMAX_NOSWP (0x00010000)
40 #define SWP_EX_NOCOPY 0x0001
41 #define SWP_EX_PAINTSELF 0x0002
43 #define SWP_AGG_NOGEOMETRYCHANGE \
44 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
45 #define SWP_AGG_NOPOSCHANGE \
46 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
47 #define SWP_AGG_STATUSFLAGS \
48 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
50 /* FUNCTIONS *****************************************************************/
53 IntGetClientOrigin(PWINDOW_OBJECT Window OPTIONAL
, LPPOINT Point
)
55 Window
= Window
? Window
: UserGetWindowObject(IntGetDesktopWindow());
58 Point
->x
= Point
->y
= 0;
61 Point
->x
= Window
->ClientRect
.left
;
62 Point
->y
= Window
->ClientRect
.top
;
71 UserGetClientOrigin(PWINDOW_OBJECT Window
, LPPOINT Point
)
79 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
83 Ret
= IntGetClientOrigin(Window
, &pt
);
87 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
91 Status
= MmCopyToCaller(Point
, &pt
, sizeof(POINT
));
92 if(!NT_SUCCESS(Status
))
94 SetLastNtError(Status
);
104 NtUserGetClientOrigin(HWND hWnd
, LPPOINT Point
)
106 DECLARE_RETURN(BOOL
);
107 PWINDOW_OBJECT Window
;
109 DPRINT("Enter NtUserGetClientOrigin\n");
112 if (!(Window
= UserGetWindowObject(hWnd
)))
115 RETURN(UserGetClientOrigin(Window
, Point
));
118 DPRINT("Leave NtUserGetClientOrigin, ret=%i\n",_ret_
);
124 /*******************************************************************
125 * can_activate_window
127 * Check if we can activate the specified window.
129 static BOOL FASTCALL
can_activate_window( PWINDOW_OBJECT Wnd
)
133 if (!Wnd
) return FALSE
;
135 if (!(style
& WS_VISIBLE
)) return FALSE
;
136 if ((style
& (WS_POPUP
|WS_CHILD
)) == WS_CHILD
) return FALSE
;
137 return !(style
& WS_DISABLED
);
141 /*******************************************************************
142 * WinPosActivateOtherWindow
144 * Activates window other than pWnd.
147 co_WinPosActivateOtherWindow(PWINDOW_OBJECT Window OPTIONAL
)
153 ASSERT_REFS_CO(Window
);
155 if (!Window
|| IntIsDesktopWindow(Window
))
157 IntSetFocusMessageQueue(NULL
);
161 /* If this is popup window, try to activate the owner first. */
162 if ((Window
->Style
& WS_POPUP
) && (Wnd
= IntGetOwner(Window
)))
164 Wnd
= UserGetAncestor( Wnd
, GA_ROOT
);
165 if (can_activate_window(Wnd
)) goto done
;
168 /* Pick a next top-level window. */
169 /* FIXME: Search for non-tooltip windows first. */
173 if (Wnd
->NextSibling
== NULL
)
179 Wnd
= Wnd
->NextSibling
;
181 if ((Wnd
->Style
& (WS_DISABLED
| WS_VISIBLE
)) == WS_VISIBLE
&&
182 (Wnd
->Style
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)
189 UserRefObjectCo(Wnd
);
191 Fg
= UserGetForegroundWindow();
192 if (Wnd
&& (!Fg
|| Window
->hSelf
== Fg
))
194 if (co_IntSetForegroundWindow(Wnd
))
196 UserDerefObjectCo(Wnd
);
201 if (!co_IntSetActiveWindow(Wnd
))
202 co_IntSetActiveWindow(0);
205 UserDerefObjectCo(Wnd
);
211 co_WinPosArrangeIconicWindows(PWINDOW_OBJECT parent
)
214 INT i
, x
, y
, xspacing
, yspacing
;
215 HWND
*List
= IntWinListChildren(parent
);
217 ASSERT_REFS_CO(parent
);
219 IntGetClientRect( parent
, &rectParent
);
221 y
= rectParent
.bottom
;
223 xspacing
= UserGetSystemMetrics(SM_CXMINSPACING
);
224 yspacing
= UserGetSystemMetrics(SM_CYMINSPACING
);
226 DPRINT("X:%d Y:%d XS:%d YS:%d\n",x
,y
,xspacing
,yspacing
);
228 for( i
= 0; List
[i
]; i
++)
230 PWINDOW_OBJECT WndChild
;
232 if (!(WndChild
= UserGetWindowObject(List
[i
])))
235 if((WndChild
->Style
& WS_MINIMIZE
) != 0 )
237 UserRefObjectCo(WndChild
);
239 co_WinPosSetWindowPos(WndChild
, 0, x
+ UserGetSystemMetrics(SM_CXBORDER
),
240 y
- yspacing
- UserGetSystemMetrics(SM_CYBORDER
)
241 , 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
243 UserDerefObjectCo(WndChild
);
245 if (x
<= rectParent
.right
- xspacing
)
260 WinPosFindIconPos(PWINDOW_OBJECT Window
, POINT
*Pos
)
265 PINTERNALPOS FASTCALL
266 WinPosInitInternalPos(PWINDOW_OBJECT Window
, POINT
*pt
, PRECT RestoreRect
)
268 PWINDOW_OBJECT Parent
;
271 if (Window
->InternalPos
== NULL
)
274 PDESKTOP_OBJECT Desktop
= PsGetWin32Thread()->Desktop
; /* Or rather get it from the window? */
276 Parent
= Window
->Parent
;
279 if(IntIsDesktopWindow(Parent
))
280 IntGetDesktopWorkArea(Desktop
, &WorkArea
);
282 WorkArea
= Parent
->ClientRect
;
285 IntGetDesktopWorkArea(Desktop
, &WorkArea
);
287 Window
->InternalPos
= ExAllocatePoolWithTag(PagedPool
, sizeof(INTERNALPOS
), TAG_WININTLIST
);
288 if(!Window
->InternalPos
)
290 DPRINT1("Failed to allocate INTERNALPOS structure for window 0x%x\n", Window
->hSelf
);
293 Window
->InternalPos
->NormalRect
= Window
->WindowRect
;
294 IntGetWindowBorderMeasures(Window
, &XInc
, &YInc
);
295 Window
->InternalPos
->MaxPos
.x
= WorkArea
.left
- XInc
;
296 Window
->InternalPos
->MaxPos
.y
= WorkArea
.top
- YInc
;
297 Window
->InternalPos
->IconPos
.x
= WorkArea
.left
;
298 Window
->InternalPos
->IconPos
.y
= WorkArea
.bottom
- UserGetSystemMetrics(SM_CYMINIMIZED
);
300 if (Window
->Style
& WS_MINIMIZE
)
302 Window
->InternalPos
->IconPos
= *pt
;
304 else if (Window
->Style
& WS_MAXIMIZE
)
306 Window
->InternalPos
->MaxPos
= *pt
;
308 else if (RestoreRect
!= NULL
)
310 Window
->InternalPos
->NormalRect
= *RestoreRect
;
312 return(Window
->InternalPos
);
316 co_WinPosMinMaximize(PWINDOW_OBJECT Window
, UINT ShowFlag
, RECT
* NewPos
)
319 PINTERNALPOS InternalPos
;
322 ASSERT_REFS_CO(Window
);
324 Size
.x
= Window
->WindowRect
.left
;
325 Size
.y
= Window
->WindowRect
.top
;
326 InternalPos
= WinPosInitInternalPos(Window
, &Size
, &Window
->WindowRect
);
330 if (Window
->Style
& WS_MINIMIZE
)
332 if (!co_IntSendMessage(Window
->hSelf
, WM_QUERYOPEN
, 0, 0))
334 return(SWP_NOSIZE
| SWP_NOMOVE
);
336 SwpFlags
|= SWP_NOCOPYBITS
;
342 if (Window
->Style
& WS_MAXIMIZE
)
344 Window
->Flags
|= WINDOWOBJECT_RESTOREMAX
;
345 Window
->Style
&= ~WS_MAXIMIZE
;
349 Window
->Flags
&= ~WINDOWOBJECT_RESTOREMAX
;
351 co_UserRedrawWindow(Window
, NULL
, 0, RDW_VALIDATE
| RDW_NOERASE
|
352 RDW_NOINTERNALPAINT
);
353 Window
->Style
|= WS_MINIMIZE
;
354 WinPosFindIconPos(Window
, &InternalPos
->IconPos
);
355 IntGdiSetRect(NewPos
, InternalPos
->IconPos
.x
, InternalPos
->IconPos
.y
,
356 UserGetSystemMetrics(SM_CXMINIMIZED
),
357 UserGetSystemMetrics(SM_CYMINIMIZED
));
358 SwpFlags
|= SWP_NOCOPYBITS
;
364 co_WinPosGetMinMaxInfo(Window
, &Size
, &InternalPos
->MaxPos
,
366 DPRINT("Maximize: %d,%d %dx%d\n",
367 InternalPos
->MaxPos
.x
, InternalPos
->MaxPos
.y
, Size
.x
, Size
.y
);
368 if (Window
->Style
& WS_MINIMIZE
)
370 Window
->Style
&= ~WS_MINIMIZE
;
372 Window
->Style
|= WS_MAXIMIZE
;
373 IntGdiSetRect(NewPos
, InternalPos
->MaxPos
.x
, InternalPos
->MaxPos
.y
,
380 if (Window
->Style
& WS_MINIMIZE
)
382 Window
->Style
&= ~WS_MINIMIZE
;
383 if (Window
->Flags
& WINDOWOBJECT_RESTOREMAX
)
385 co_WinPosGetMinMaxInfo(Window
, &Size
,
386 &InternalPos
->MaxPos
, NULL
, NULL
);
387 Window
->Style
|= WS_MAXIMIZE
;
388 IntGdiSetRect(NewPos
, InternalPos
->MaxPos
.x
,
389 InternalPos
->MaxPos
.y
, Size
.x
, Size
.y
);
394 *NewPos
= InternalPos
->NormalRect
;
395 NewPos
->right
-= NewPos
->left
;
396 NewPos
->bottom
-= NewPos
->top
;
402 if (!(Window
->Style
& WS_MAXIMIZE
))
406 Window
->Style
&= ~WS_MAXIMIZE
;
407 *NewPos
= InternalPos
->NormalRect
;
408 NewPos
->right
-= NewPos
->left
;
409 NewPos
->bottom
-= NewPos
->top
;
417 SwpFlags
|= SWP_NOSIZE
| SWP_NOMOVE
;
423 WinPosFillMinMaxInfoStruct(PWINDOW_OBJECT Window
, MINMAXINFO
*Info
)
427 PDESKTOP_OBJECT Desktop
= PsGetWin32Thread()->Desktop
; /* Or rather get it from the window? */
429 IntGetDesktopWorkArea(Desktop
, &WorkArea
);
431 /* Get default values. */
432 Info
->ptMaxSize
.x
= WorkArea
.right
- WorkArea
.left
;
433 Info
->ptMaxSize
.y
= WorkArea
.bottom
- WorkArea
.top
;
434 Info
->ptMinTrackSize
.x
= UserGetSystemMetrics(SM_CXMINTRACK
);
435 Info
->ptMinTrackSize
.y
= UserGetSystemMetrics(SM_CYMINTRACK
);
436 Info
->ptMaxTrackSize
.x
= Info
->ptMaxSize
.x
;
437 Info
->ptMaxTrackSize
.y
= Info
->ptMaxSize
.y
;
439 IntGetWindowBorderMeasures(Window
, &XInc
, &YInc
);
440 Info
->ptMaxSize
.x
+= 2 * XInc
;
441 Info
->ptMaxSize
.y
+= 2 * YInc
;
443 if (Window
->InternalPos
!= NULL
)
445 Info
->ptMaxPosition
= Window
->InternalPos
->MaxPos
;
449 Info
->ptMaxPosition
.x
-= WorkArea
.left
+ XInc
;
450 Info
->ptMaxPosition
.y
-= WorkArea
.top
+ YInc
;
455 co_WinPosGetMinMaxInfo(PWINDOW_OBJECT Window
, POINT
* MaxSize
, POINT
* MaxPos
,
456 POINT
* MinTrack
, POINT
* MaxTrack
)
460 ASSERT_REFS_CO(Window
);
462 WinPosFillMinMaxInfoStruct(Window
, &MinMax
);
464 co_IntSendMessage(Window
->hSelf
, WM_GETMINMAXINFO
, 0, (LPARAM
)&MinMax
);
466 MinMax
.ptMaxTrackSize
.x
= max(MinMax
.ptMaxTrackSize
.x
,
467 MinMax
.ptMinTrackSize
.x
);
468 MinMax
.ptMaxTrackSize
.y
= max(MinMax
.ptMaxTrackSize
.y
,
469 MinMax
.ptMinTrackSize
.y
);
472 *MaxSize
= MinMax
.ptMaxSize
;
474 *MaxPos
= MinMax
.ptMaxPosition
;
476 *MinTrack
= MinMax
.ptMinTrackSize
;
478 *MaxTrack
= MinMax
.ptMaxTrackSize
;
480 return 0; //FIXME: what does it return?
484 FixClientRect(PRECT ClientRect
, PRECT WindowRect
)
486 if (ClientRect
->left
< WindowRect
->left
)
488 ClientRect
->left
= WindowRect
->left
;
490 else if (WindowRect
->right
< ClientRect
->left
)
492 ClientRect
->left
= WindowRect
->right
;
494 if (ClientRect
->right
< WindowRect
->left
)
496 ClientRect
->right
= WindowRect
->left
;
498 else if (WindowRect
->right
< ClientRect
->right
)
500 ClientRect
->right
= WindowRect
->right
;
502 if (ClientRect
->top
< WindowRect
->top
)
504 ClientRect
->top
= WindowRect
->top
;
506 else if (WindowRect
->bottom
< ClientRect
->top
)
508 ClientRect
->top
= WindowRect
->bottom
;
510 if (ClientRect
->bottom
< WindowRect
->top
)
512 ClientRect
->bottom
= WindowRect
->top
;
514 else if (WindowRect
->bottom
< ClientRect
->bottom
)
516 ClientRect
->bottom
= WindowRect
->bottom
;
521 co_WinPosDoNCCALCSize(PWINDOW_OBJECT Window
, PWINDOWPOS WinPos
,
522 RECT
* WindowRect
, RECT
* ClientRect
)
524 PWINDOW_OBJECT Parent
;
527 ASSERT_REFS_CO(Window
);
529 /* Send WM_NCCALCSIZE message to get new client area */
530 if ((WinPos
->flags
& (SWP_FRAMECHANGED
| SWP_NOSIZE
)) != SWP_NOSIZE
)
532 NCCALCSIZE_PARAMS params
;
533 WINDOWPOS winposCopy
;
535 params
.rgrc
[0] = *WindowRect
;
536 params
.rgrc
[1] = Window
->WindowRect
;
537 params
.rgrc
[2] = Window
->ClientRect
;
538 Parent
= Window
->Parent
;
539 if (0 != (Window
->Style
& WS_CHILD
) && Parent
)
541 IntGdiOffsetRect(&(params
.rgrc
[0]), - Parent
->ClientRect
.left
,
542 - Parent
->ClientRect
.top
);
543 IntGdiOffsetRect(&(params
.rgrc
[1]), - Parent
->ClientRect
.left
,
544 - Parent
->ClientRect
.top
);
545 IntGdiOffsetRect(&(params
.rgrc
[2]), - Parent
->ClientRect
.left
,
546 - Parent
->ClientRect
.top
);
548 params
.lppos
= &winposCopy
;
549 winposCopy
= *WinPos
;
551 wvrFlags
= co_IntSendMessage(Window
->hSelf
, WM_NCCALCSIZE
, TRUE
, (LPARAM
) ¶ms
);
553 /* If the application send back garbage, ignore it */
554 if (params
.rgrc
[0].left
<= params
.rgrc
[0].right
&&
555 params
.rgrc
[0].top
<= params
.rgrc
[0].bottom
)
557 *ClientRect
= params
.rgrc
[0];
558 if ((Window
->Style
& WS_CHILD
) && Parent
)
560 IntGdiOffsetRect(ClientRect
, Parent
->ClientRect
.left
,
561 Parent
->ClientRect
.top
);
563 FixClientRect(ClientRect
, WindowRect
);
566 /* FIXME: WVR_ALIGNxxx */
568 if (ClientRect
->left
!= Window
->ClientRect
.left
||
569 ClientRect
->top
!= Window
->ClientRect
.top
)
571 WinPos
->flags
&= ~SWP_NOCLIENTMOVE
;
574 if ((ClientRect
->right
- ClientRect
->left
!=
575 Window
->ClientRect
.right
- Window
->ClientRect
.left
) ||
576 (ClientRect
->bottom
- ClientRect
->top
!=
577 Window
->ClientRect
.bottom
- Window
->ClientRect
.top
))
579 WinPos
->flags
&= ~SWP_NOCLIENTSIZE
;
584 if (! (WinPos
->flags
& SWP_NOMOVE
)
585 && (ClientRect
->left
!= Window
->ClientRect
.left
||
586 ClientRect
->top
!= Window
->ClientRect
.top
))
588 WinPos
->flags
&= ~SWP_NOCLIENTMOVE
;
596 co_WinPosDoWinPosChanging(PWINDOW_OBJECT Window
,
603 ASSERT_REFS_CO(Window
);
605 if (!(WinPos
->flags
& SWP_NOSENDCHANGING
))
607 co_IntSendMessage(Window
->hSelf
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
) WinPos
);
610 *WindowRect
= Window
->WindowRect
;
611 *ClientRect
= Window
->ClientRect
;
613 if (!(WinPos
->flags
& SWP_NOSIZE
))
615 WindowRect
->right
= WindowRect
->left
+ WinPos
->cx
;
616 WindowRect
->bottom
= WindowRect
->top
+ WinPos
->cy
;
619 if (!(WinPos
->flags
& SWP_NOMOVE
))
621 PWINDOW_OBJECT Parent
;
624 Parent
= Window
->Parent
;
625 if ((0 != (Window
->Style
& WS_CHILD
)) && Parent
)
627 X
+= Parent
->ClientRect
.left
;
628 Y
+= Parent
->ClientRect
.top
;
631 WindowRect
->left
= X
;
633 WindowRect
->right
+= X
- Window
->WindowRect
.left
;
634 WindowRect
->bottom
+= Y
- Window
->WindowRect
.top
;
635 IntGdiOffsetRect(ClientRect
,
636 X
- Window
->WindowRect
.left
,
637 Y
- Window
->WindowRect
.top
);
640 WinPos
->flags
|= SWP_NOCLIENTMOVE
| SWP_NOCLIENTSIZE
;
646 * Fix Z order taking into account owned popups -
647 * basically we need to maintain them above the window that owns them
650 WinPosDoOwnedPopups(HWND hWnd
, HWND hWndInsertAfter
)
653 HWND Owner
= UserGetWindow(hWnd
, GW_OWNER
);
654 LONG Style
= UserGetWindowLong(hWnd
, GWL_STYLE
, FALSE
);
655 PWINDOW_OBJECT DesktopWindow
, ChildObject
;
658 if ((Style
& WS_POPUP
) && Owner
)
660 /* Make sure this popup stays above the owner */
661 HWND hWndLocalPrev
= HWND_TOPMOST
;
663 if (hWndInsertAfter
!= HWND_TOPMOST
)
665 DesktopWindow
= IntGetWindowObject(IntGetDesktopWindow());
666 List
= IntWinListChildren(DesktopWindow
);
667 IntReleaseWindowObject(DesktopWindow
);
670 for (i
= 0; List
[i
]; i
++)
672 if (List
[i
] == Owner
)
674 if (HWND_TOP
== hWndInsertAfter
)
676 ChildObject
= IntGetWindowObject(List
[i
]);
677 if (NULL
!= ChildObject
)
679 if (0 == (ChildObject
->ExStyle
& WS_EX_TOPMOST
))
681 IntReleaseWindowObject(ChildObject
);
684 IntReleaseWindowObject(ChildObject
);
688 hWndLocalPrev
= List
[i
];
689 if (hWndLocalPrev
== hWndInsertAfter
)
692 hWndInsertAfter
= hWndLocalPrev
;
696 else if (Style
& WS_CHILD
)
698 return hWndInsertAfter
;
703 DesktopWindow
= IntGetWindowObject(IntGetDesktopWindow());
704 List
= IntWinListChildren(DesktopWindow
);
705 IntReleaseWindowObject(DesktopWindow
);
709 for (i
= 0; List
[i
]; i
++)
716 if (!(Wnd
= UserGetWindowObject(List
[i
])))
719 if ((Wnd
->Style
& WS_POPUP
) &&
720 UserGetWindow(List
[i
], GW_OWNER
) == hWnd
)
722 UserRefObjectCo(Wnd
);
724 co_WinPosSetWindowPos(Wnd
, hWndInsertAfter
, 0, 0, 0, 0,
725 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOSENDCHANGING
);
727 UserDerefObjectCo(Wnd
);
729 hWndInsertAfter
= List
[i
];
735 return hWndInsertAfter
;
738 /***********************************************************************
739 * WinPosInternalMoveWindow
741 * Update WindowRect and ClientRect of Window and all of its children
742 * We keep both WindowRect and ClientRect in screen coordinates internally
745 WinPosInternalMoveWindow(PWINDOW_OBJECT Window
, INT MoveX
, INT MoveY
)
747 PWINDOW_OBJECT Child
;
749 Window
->WindowRect
.left
+= MoveX
;
750 Window
->WindowRect
.right
+= MoveX
;
751 Window
->WindowRect
.top
+= MoveY
;
752 Window
->WindowRect
.bottom
+= MoveY
;
754 Window
->ClientRect
.left
+= MoveX
;
755 Window
->ClientRect
.right
+= MoveX
;
756 Window
->ClientRect
.top
+= MoveY
;
757 Window
->ClientRect
.bottom
+= MoveY
;
759 for(Child
= Window
->FirstChild
; Child
; Child
= Child
->NextSibling
)
761 WinPosInternalMoveWindow(Child
, MoveX
, MoveY
);
766 * WinPosFixupSWPFlags
768 * Fix redundant flags and values in the WINDOWPOS structure.
772 WinPosFixupFlags(WINDOWPOS
*WinPos
, PWINDOW_OBJECT Window
)
774 if (Window
->Style
& WS_VISIBLE
)
776 WinPos
->flags
&= ~SWP_SHOWWINDOW
;
780 WinPos
->flags
&= ~SWP_HIDEWINDOW
;
781 if (!(WinPos
->flags
& SWP_SHOWWINDOW
))
782 WinPos
->flags
|= SWP_NOREDRAW
;
785 WinPos
->cx
= max(WinPos
->cx
, 0);
786 WinPos
->cy
= max(WinPos
->cy
, 0);
788 /* Check for right size */
789 if (Window
->WindowRect
.right
- Window
->WindowRect
.left
== WinPos
->cx
&&
790 Window
->WindowRect
.bottom
- Window
->WindowRect
.top
== WinPos
->cy
)
792 WinPos
->flags
|= SWP_NOSIZE
;
795 /* Check for right position */
796 if (Window
->WindowRect
.left
== WinPos
->x
&&
797 Window
->WindowRect
.top
== WinPos
->y
)
799 WinPos
->flags
|= SWP_NOMOVE
;
802 if (WinPos
->hwnd
== UserGetForegroundWindow())
804 WinPos
->flags
|= SWP_NOACTIVATE
; /* Already active */
807 if ((Window
->Style
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)
809 /* Bring to the top when activating */
810 if (!(WinPos
->flags
& SWP_NOACTIVATE
))
812 WinPos
->flags
&= ~SWP_NOZORDER
;
813 WinPos
->hwndInsertAfter
= (0 != (Window
->ExStyle
& WS_EX_TOPMOST
) ?
814 HWND_TOPMOST
: HWND_TOP
);
819 /* Check hwndInsertAfter */
820 if (!(WinPos
->flags
& SWP_NOZORDER
))
822 /* Fix sign extension */
823 if (WinPos
->hwndInsertAfter
== (HWND
)0xffff)
825 WinPos
->hwndInsertAfter
= HWND_TOPMOST
;
827 else if (WinPos
->hwndInsertAfter
== (HWND
)0xfffe)
829 WinPos
->hwndInsertAfter
= HWND_NOTOPMOST
;
832 if (WinPos
->hwndInsertAfter
== HWND_NOTOPMOST
)
834 WinPos
->hwndInsertAfter
= HWND_TOP
;
836 else if (HWND_TOP
== WinPos
->hwndInsertAfter
837 && 0 != (Window
->ExStyle
& WS_EX_TOPMOST
))
839 /* Keep it topmost when it's already topmost */
840 WinPos
->hwndInsertAfter
= HWND_TOPMOST
;
843 /* hwndInsertAfter must be a sibling of the window */
844 if (HWND_TOPMOST
!= WinPos
->hwndInsertAfter
845 && HWND_TOP
!= WinPos
->hwndInsertAfter
846 && HWND_NOTOPMOST
!= WinPos
->hwndInsertAfter
847 && HWND_BOTTOM
!= WinPos
->hwndInsertAfter
)
849 PWINDOW_OBJECT InsAfterWnd
, Parent
= Window
->Parent
;
851 InsAfterWnd
= UserGetWindowObject(WinPos
->hwndInsertAfter
);
853 if (InsAfterWnd
&& UserGetAncestor(InsAfterWnd
, GA_PARENT
) != Parent
)
860 * We don't need to change the Z order of hwnd if it's already
861 * inserted after hwndInsertAfter or when inserting hwnd after
864 if ((WinPos
->hwnd
== WinPos
->hwndInsertAfter
) ||
865 (WinPos
->hwnd
== UserGetWindow(WinPos
->hwndInsertAfter
, GW_HWNDNEXT
)))
867 WinPos
->flags
|= SWP_NOZORDER
;
876 /* x and y are always screen relative */
878 co_WinPosSetWindowPos(
879 PWINDOW_OBJECT Window
,
892 HRGN VisBefore
= NULL
;
893 HRGN VisAfter
= NULL
;
894 HRGN DirtyRgn
= NULL
;
895 HRGN ExposedRgn
= NULL
;
898 RECT OldWindowRect
, OldClientRect
;
904 ASSERT_REFS_CO(Window
);
906 /* FIXME: Get current active window from active queue. */
909 * Only allow CSRSS to mess with the desktop window
911 if (Window
->hSelf
== IntGetDesktopWindow() &&
912 Window
->OwnerThread
->ThreadsProcess
!= PsGetCurrentProcess())
917 WinPos
.hwnd
= Window
->hSelf
;
918 WinPos
.hwndInsertAfter
= WndInsertAfter
;
923 WinPos
.flags
= flags
;
925 co_WinPosDoWinPosChanging(Window
, &WinPos
, &NewWindowRect
, &NewClientRect
);
927 /* Fix up the flags. */
928 if (!WinPosFixupFlags(&WinPos
, Window
))
930 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
934 /* Does the window still exist? */
935 if (!IntIsWindow(WinPos
.hwnd
))
937 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
941 if ((WinPos
.flags
& (SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) !=
943 // UserGetAncestor(WinPos.hwnd, GA_PARENT) == IntGetDesktopWindow())
944 //faxme: is WinPos.hwnd constant?? (WinPos.hwnd = Window->hSelf above)
945 UserGetAncestor(Window
, GA_PARENT
)->hSelf
== IntGetDesktopWindow())
947 WinPos
.hwndInsertAfter
= WinPosDoOwnedPopups(WinPos
.hwnd
, WinPos
.hwndInsertAfter
);
950 if (!(WinPos
.flags
& SWP_NOREDRAW
))
952 /* Compute the visible region before the window position is changed */
953 if (!(WinPos
.flags
& (SWP_NOREDRAW
| SWP_SHOWWINDOW
)) &&
954 (WinPos
.flags
& (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
|
955 SWP_HIDEWINDOW
| SWP_FRAMECHANGED
)) !=
956 (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
))
958 VisBefore
= VIS_ComputeVisibleRegion(Window
, FALSE
, FALSE
, TRUE
);
961 if (VisBefore
!= NULL
&& (VisRgn
= (PROSRGNDATA
)RGNDATA_LockRgn(VisBefore
)) &&
962 UnsafeIntGetRgnBox(VisRgn
, &TempRect
) == NULLREGION
)
964 RGNDATA_UnlockRgn(VisRgn
);
965 NtGdiDeleteObject(VisBefore
);
970 RGNDATA_UnlockRgn(VisRgn
);
975 WvrFlags
= co_WinPosDoNCCALCSize(Window
, &WinPos
, &NewWindowRect
, &NewClientRect
);
977 /* Relink windows. (also take into account shell window in hwndShellWindow) */
978 if (!(WinPos
.flags
& SWP_NOZORDER
) && WinPos
.hwnd
!= UserGetShellWindow())
980 PWINDOW_OBJECT ParentWindow
;
981 PWINDOW_OBJECT Sibling
;
982 PWINDOW_OBJECT InsertAfterWindow
;
984 if ((ParentWindow
= Window
->Parent
))
986 if (HWND_TOPMOST
== WinPos
.hwndInsertAfter
)
988 InsertAfterWindow
= NULL
;
990 else if (HWND_TOP
== WinPos
.hwndInsertAfter
991 || HWND_NOTOPMOST
== WinPos
.hwndInsertAfter
)
993 InsertAfterWindow
= NULL
;
994 Sibling
= ParentWindow
->FirstChild
;
995 while (NULL
!= Sibling
&& 0 != (Sibling
->ExStyle
& WS_EX_TOPMOST
))
997 InsertAfterWindow
= Sibling
;
998 Sibling
= Sibling
->NextSibling
;
1000 if (NULL
!= InsertAfterWindow
)
1002 IntReferenceWindowObject(InsertAfterWindow
);
1005 else if (WinPos
.hwndInsertAfter
== HWND_BOTTOM
)
1007 if(ParentWindow
->LastChild
)
1009 IntReferenceWindowObject(ParentWindow
->LastChild
);
1010 InsertAfterWindow
= ParentWindow
->LastChild
;
1013 InsertAfterWindow
= NULL
;
1016 InsertAfterWindow
= IntGetWindowObject(WinPos
.hwndInsertAfter
);
1017 /* Do nothing if hwndInsertAfter is HWND_BOTTOM and Window is already
1019 if (InsertAfterWindow
!= Window
)
1021 IntUnlinkWindow(Window
);
1022 IntLinkWindow(Window
, ParentWindow
, InsertAfterWindow
);
1024 if (InsertAfterWindow
!= NULL
)
1025 IntReleaseWindowObject(InsertAfterWindow
);
1026 if ((HWND_TOPMOST
== WinPos
.hwndInsertAfter
)
1027 || (0 != (Window
->ExStyle
& WS_EX_TOPMOST
)
1028 && NULL
!= Window
->PrevSibling
1029 && 0 != (Window
->PrevSibling
->ExStyle
& WS_EX_TOPMOST
))
1030 || (NULL
!= Window
->NextSibling
1031 && 0 != (Window
->NextSibling
->ExStyle
& WS_EX_TOPMOST
)))
1033 Window
->ExStyle
|= WS_EX_TOPMOST
;
1037 Window
->ExStyle
&= ~ WS_EX_TOPMOST
;
1043 OldWindowRect
= Window
->WindowRect
;
1044 OldClientRect
= Window
->ClientRect
;
1046 if (OldClientRect
.bottom
- OldClientRect
.top
==
1047 NewClientRect
.bottom
- NewClientRect
.top
)
1049 WvrFlags
&= ~WVR_VREDRAW
;
1052 if (OldClientRect
.right
- OldClientRect
.left
==
1053 NewClientRect
.right
- NewClientRect
.left
)
1055 WvrFlags
&= ~WVR_HREDRAW
;
1058 /* FIXME: Actually do something with WVR_VALIDRECTS */
1060 if (NewClientRect
.left
!= OldClientRect
.left
||
1061 NewClientRect
.top
!= OldClientRect
.top
)
1063 WinPosInternalMoveWindow(Window
,
1064 NewClientRect
.left
- OldClientRect
.left
,
1065 NewClientRect
.top
- OldClientRect
.top
);
1068 Window
->WindowRect
= NewWindowRect
;
1069 Window
->ClientRect
= NewClientRect
;
1071 if (!(WinPos
.flags
& SWP_SHOWWINDOW
) && (WinPos
.flags
& SWP_HIDEWINDOW
))
1073 /* Clear the update region */
1074 co_UserRedrawWindow(Window
, NULL
, 0, RDW_VALIDATE
| RDW_NOFRAME
|
1075 RDW_NOERASE
| RDW_NOINTERNALPAINT
| RDW_ALLCHILDREN
);
1076 Window
->Style
&= ~WS_VISIBLE
;
1078 else if (WinPos
.flags
& SWP_SHOWWINDOW
)
1080 Window
->Style
|= WS_VISIBLE
;
1083 DceResetActiveDCEs(Window
);
1085 if (!(WinPos
.flags
& SWP_NOREDRAW
))
1087 /* Determine the new visible region */
1088 VisAfter
= VIS_ComputeVisibleRegion(Window
, FALSE
, FALSE
, TRUE
);
1091 if (VisAfter
!= NULL
&& (VisRgn
= (PROSRGNDATA
)RGNDATA_LockRgn(VisAfter
)) &&
1092 UnsafeIntGetRgnBox(VisRgn
, &TempRect
) == NULLREGION
)
1094 RGNDATA_UnlockRgn(VisRgn
);
1095 NtGdiDeleteObject(VisAfter
);
1100 RGNDATA_UnlockRgn(VisRgn
);
1104 * Determine which pixels can be copied from the old window position
1105 * to the new. Those pixels must be visible in both the old and new
1106 * position. Also, check the class style to see if the windows of this
1107 * class need to be completely repainted on (horizontal/vertical) size
1110 if (VisBefore
!= NULL
&& VisAfter
!= NULL
&& !(WinPos
.flags
& SWP_NOCOPYBITS
) &&
1111 ((WinPos
.flags
& SWP_NOSIZE
) || !(WvrFlags
& WVR_REDRAW
)))
1113 CopyRgn
= NtGdiCreateRectRgn(0, 0, 0, 0);
1114 RgnType
= NtGdiCombineRgn(CopyRgn
, VisAfter
, VisBefore
, RGN_AND
);
1117 * If this is (also) a window resize, the whole nonclient area
1118 * needs to be repainted. So we limit the copy to the client area,
1119 * 'cause there is no use in copying it (would possibly cause
1120 * "flashing" too). However, if the copy region is already empty,
1121 * we don't have to crop (can't take anything away from an empty
1124 if (!(WinPos
.flags
& SWP_NOSIZE
) && RgnType
!= ERROR
&&
1125 RgnType
!= NULLREGION
)
1127 RECT ORect
= OldClientRect
;
1128 RECT NRect
= NewClientRect
;
1129 IntGdiOffsetRect(&ORect
, - OldWindowRect
.left
, - OldWindowRect
.top
);
1130 IntGdiOffsetRect(&NRect
, - NewWindowRect
.left
, - NewWindowRect
.top
);
1131 IntGdiIntersectRect(&CopyRect
, &ORect
, &NRect
);
1132 REGION_CropRgn(CopyRgn
, CopyRgn
, &CopyRect
, NULL
);
1135 /* No use in copying bits which are in the update region. */
1136 if (Window
->UpdateRegion
!= NULL
)
1138 NtGdiCombineRgn(CopyRgn
, CopyRgn
, Window
->UpdateRegion
, RGN_DIFF
);
1140 if (Window
->NCUpdateRegion
!= NULL
)
1142 NtGdiCombineRgn(CopyRgn
, CopyRgn
, Window
->NCUpdateRegion
, RGN_DIFF
);
1146 * Now, get the bounding box of the copy region. If it's empty
1147 * there's nothing to copy. Also, it's no use copying bits onto
1150 if ((VisRgn
= (PROSRGNDATA
)RGNDATA_LockRgn(CopyRgn
)) &&
1151 UnsafeIntGetRgnBox(VisRgn
, &CopyRect
) == NULLREGION
)
1153 /* Nothing to copy, clean up */
1154 RGNDATA_UnlockRgn(VisRgn
);
1155 NtGdiDeleteObject(CopyRgn
);
1158 else if (OldWindowRect
.left
!= NewWindowRect
.left
||
1159 OldWindowRect
.top
!= NewWindowRect
.top
)
1163 RGNDATA_UnlockRgn(VisRgn
);
1166 * Small trick here: there is no function to bitblt a region. So
1167 * we set the region as the clipping region, take the bounding box
1168 * of the region and bitblt that. Since nothing outside the clipping
1169 * region is copied, this has the effect of bitblt'ing the region.
1171 * Since NtUserGetDCEx takes ownership of the clip region, we need
1172 * to create a copy of CopyRgn and pass that. We need CopyRgn later
1174 HRGN ClipRgn
= NtGdiCreateRectRgn(0, 0, 0, 0);
1176 NtGdiCombineRgn(ClipRgn
, CopyRgn
, NULL
, RGN_COPY
);
1177 Dc
= UserGetDCEx(Window
, ClipRgn
, DCX_WINDOW
| DCX_CACHE
|
1178 DCX_INTERSECTRGN
| DCX_CLIPSIBLINGS
);
1180 CopyRect
.left
, CopyRect
.top
, CopyRect
.right
- CopyRect
.left
,
1181 CopyRect
.bottom
- CopyRect
.top
, Dc
,
1182 CopyRect
.left
+ (OldWindowRect
.left
- NewWindowRect
.left
),
1183 CopyRect
.top
+ (OldWindowRect
.top
- NewWindowRect
.top
), SRCCOPY
);
1184 UserReleaseDC(Window
, Dc
);
1185 IntValidateParent(Window
, CopyRgn
);
1189 RGNDATA_UnlockRgn(VisRgn
);
1197 /* We need to redraw what wasn't visible before */
1198 if (VisAfter
!= NULL
)
1200 DirtyRgn
= NtGdiCreateRectRgn(0, 0, 0, 0);
1201 if (CopyRgn
!= NULL
)
1203 RgnType
= NtGdiCombineRgn(DirtyRgn
, VisAfter
, CopyRgn
, RGN_DIFF
);
1207 RgnType
= NtGdiCombineRgn(DirtyRgn
, VisAfter
, 0, RGN_COPY
);
1209 if (RgnType
!= ERROR
&& RgnType
!= NULLREGION
)
1211 NtGdiOffsetRgn(DirtyRgn
,
1212 Window
->WindowRect
.left
- Window
->ClientRect
.left
,
1213 Window
->WindowRect
.top
- Window
->ClientRect
.top
);
1214 co_UserRedrawWindow(Window
, NULL
, DirtyRgn
,
1215 RDW_ERASE
| RDW_FRAME
| RDW_INVALIDATE
| RDW_ALLCHILDREN
);
1217 NtGdiDeleteObject(DirtyRgn
);
1220 if (CopyRgn
!= NULL
)
1222 NtGdiDeleteObject(CopyRgn
);
1225 /* Expose what was covered before but not covered anymore */
1226 if (VisBefore
!= NULL
)
1228 ExposedRgn
= NtGdiCreateRectRgn(0, 0, 0, 0);
1229 NtGdiCombineRgn(ExposedRgn
, VisBefore
, NULL
, RGN_COPY
);
1230 NtGdiOffsetRgn(ExposedRgn
, OldWindowRect
.left
- NewWindowRect
.left
,
1231 OldWindowRect
.top
- NewWindowRect
.top
);
1232 if (VisAfter
!= NULL
)
1233 RgnType
= NtGdiCombineRgn(ExposedRgn
, ExposedRgn
, VisAfter
, RGN_DIFF
);
1235 RgnType
= SIMPLEREGION
;
1237 if (RgnType
!= ERROR
&& RgnType
!= NULLREGION
)
1239 co_VIS_WindowLayoutChanged(Window
, ExposedRgn
);
1241 NtGdiDeleteObject(ExposedRgn
);
1242 NtGdiDeleteObject(VisBefore
);
1245 if (VisAfter
!= NULL
)
1247 NtGdiDeleteObject(VisAfter
);
1250 if (!(WinPos
.flags
& SWP_NOACTIVATE
))
1252 if ((Window
->Style
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1254 co_IntSendMessage(WinPos
.hwnd
, WM_CHILDACTIVATE
, 0, 0);
1258 co_IntSetForegroundWindow(Window
);
1263 if ((WinPos
.flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOPOSCHANGE
)
1264 co_IntSendMessage(WinPos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
) &WinPos
);
1270 co_WinPosGetNonClientSize(PWINDOW_OBJECT Window
, RECT
* WindowRect
, RECT
* ClientRect
)
1274 ASSERT_REFS_CO(Window
);
1276 *ClientRect
= *WindowRect
;
1277 Result
= co_IntSendMessage(Window
->hSelf
, WM_NCCALCSIZE
, FALSE
, (LPARAM
) ClientRect
);
1279 FixClientRect(ClientRect
, WindowRect
);
1285 co_WinPosShowWindow(PWINDOW_OBJECT Window
, INT Cmd
)
1293 ASSERT_REFS_CO(Window
);
1295 WasVisible
= (Window
->Style
& WS_VISIBLE
) != 0;
1305 Swp
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
1306 if (Window
->hSelf
!= UserGetActiveWindow())
1307 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1311 case SW_SHOWMINNOACTIVE
:
1312 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1314 case SW_SHOWMINIMIZED
:
1315 Swp
|= SWP_SHOWWINDOW
;
1319 Swp
|= SWP_FRAMECHANGED
| SWP_NOACTIVATE
;
1320 if (!(Window
->Style
& WS_MINIMIZE
))
1322 Swp
|= co_WinPosMinMaximize(Window
, SW_MINIMIZE
, &NewPos
);
1326 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1331 case SW_SHOWMAXIMIZED
:
1333 Swp
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
1334 if (!(Window
->Style
& WS_MAXIMIZE
))
1336 Swp
|= co_WinPosMinMaximize(Window
, SW_MAXIMIZE
, &NewPos
);
1340 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1346 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1349 Swp
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
1350 /* Don't activate the topmost window. */
1353 case SW_SHOWNOACTIVATE
:
1354 Swp
|= SWP_NOZORDER
;
1357 case SW_SHOWDEFAULT
:
1359 Swp
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
1360 if (Window
->Style
& (WS_MINIMIZE
| WS_MAXIMIZE
))
1362 Swp
|= co_WinPosMinMaximize(Window
, SW_RESTORE
, &NewPos
);
1366 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1371 ShowFlag
= (Cmd
!= SW_HIDE
);
1372 if (ShowFlag
!= WasVisible
)
1374 co_IntSendMessage(Window
->hSelf
, WM_SHOWWINDOW
, ShowFlag
, 0);
1376 * FIXME: Need to check the window wasn't destroyed during the
1379 if (!(Window
->Parent
))
1381 co_IntShellHookNotify(HSHELL_WINDOWCREATED
, (LPARAM
)Window
->hSelf
);
1385 /* We can't activate a child window */
1386 if ((Window
->Style
& WS_CHILD
) &&
1387 !(Window
->ExStyle
& WS_EX_MDICHILD
))
1389 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1392 co_WinPosSetWindowPos(Window
, 0 != (Window
->ExStyle
& WS_EX_TOPMOST
)
1393 ? HWND_TOPMOST
: HWND_TOP
,
1394 NewPos
.left
, NewPos
.top
, NewPos
.right
, NewPos
.bottom
, LOWORD(Swp
));
1398 /* FIXME: This will cause the window to be activated irrespective
1399 * of whether it is owned by the same thread. Has to be done
1403 if (Window
->hSelf
== UserGetActiveWindow())
1405 co_WinPosActivateOtherWindow(Window
);
1408 /* Revert focus to parent */
1409 if (Window
->hSelf
== IntGetThreadFocusWindow() ||
1410 IntIsChildWindow(Window
->hSelf
, IntGetThreadFocusWindow()))
1412 //faxme: as long as we have ref on Window, we also, indirectly, have ref on parent...
1413 co_UserSetFocus(Window
->Parent
);
1416 if (!(Window
->Parent
))
1418 co_IntShellHookNotify(HSHELL_WINDOWDESTROYED
, (LPARAM
)Window
->hSelf
);
1422 /* FIXME: Check for window destruction. */
1424 if ((Window
->Flags
& WINDOWOBJECT_NEED_SIZE
) &&
1425 !(Window
->Status
& WINDOWSTATUS_DESTROYING
))
1427 WPARAM wParam
= SIZE_RESTORED
;
1429 Window
->Flags
&= ~WINDOWOBJECT_NEED_SIZE
;
1430 if (Window
->Style
& WS_MAXIMIZE
)
1432 wParam
= SIZE_MAXIMIZED
;
1434 else if (Window
->Style
& WS_MINIMIZE
)
1436 wParam
= SIZE_MINIMIZED
;
1439 co_IntSendMessage(Window
->hSelf
, WM_SIZE
, wParam
,
1440 MAKELONG(Window
->ClientRect
.right
-
1441 Window
->ClientRect
.left
,
1442 Window
->ClientRect
.bottom
-
1443 Window
->ClientRect
.top
));
1444 co_IntSendMessage(Window
->hSelf
, WM_MOVE
, 0,
1445 MAKELONG(Window
->ClientRect
.left
,
1446 Window
->ClientRect
.top
));
1447 IntEngWindowChanged(Window
, WOC_RGN_CLIENT
);
1450 /* Activate the window if activation is not requested and the window is not minimized */
1452 if (!(Swp & (SWP_NOACTIVATE | SWP_HIDEWINDOW)) && !(Window->Style & WS_MINIMIZE))
1454 WinPosChangeActiveWindow(Wnd, FALSE);
1460 STATIC VOID FASTCALL
1461 co_WinPosSearchChildren(
1462 PWINDOW_OBJECT ScopeWin
, PUSER_MESSAGE_QUEUE OnlyHitTests
, POINT
*Point
,
1463 PWINDOW_OBJECT
* Window
, USHORT
*HitTest
)
1465 PWINDOW_OBJECT Current
;
1468 ASSERT_REFS_CO(ScopeWin
);
1470 if ((List
= IntWinListChildren(ScopeWin
)))
1472 for (phWnd
= List
; *phWnd
; ++phWnd
)
1474 if (!(Current
= IntGetWindowObject(*phWnd
)))
1477 if (!(Current
->Style
& WS_VISIBLE
))
1479 IntReleaseWindowObject(Current
);
1483 if ((Current
->Style
& (WS_POPUP
| WS_CHILD
| WS_DISABLED
)) ==
1484 (WS_CHILD
| WS_DISABLED
))
1486 IntReleaseWindowObject(Current
);
1490 if (!IntPtInWindow(Current
, Point
->x
, Point
->y
))
1492 IntReleaseWindowObject(Current
);
1497 IntReleaseWindowObject(*Window
);
1500 if (Current
->Style
& WS_MINIMIZE
)
1502 *HitTest
= HTCAPTION
;
1506 if (Current
->Style
& WS_DISABLED
)
1512 if (OnlyHitTests
&& (Current
->MessageQueue
== OnlyHitTests
))
1514 *HitTest
= co_IntSendMessage(Current
->hSelf
, WM_NCHITTEST
, 0,
1515 MAKELONG(Point
->x
, Point
->y
));
1516 if ((*HitTest
) == (USHORT
)HTTRANSPARENT
)
1520 *HitTest
= HTCLIENT
;
1522 if (Point
->x
>= Current
->ClientRect
.left
&&
1523 Point
->x
< Current
->ClientRect
.right
&&
1524 Point
->y
>= Current
->ClientRect
.top
&&
1525 Point
->y
< Current
->ClientRect
.bottom
)
1527 co_WinPosSearchChildren(Current
, OnlyHitTests
, Point
, Window
, HitTest
);
1537 co_WinPosWindowFromPoint(PWINDOW_OBJECT ScopeWin
, PUSER_MESSAGE_QUEUE OnlyHitTests
, POINT
*WinPoint
,
1538 PWINDOW_OBJECT
* Window
)
1540 HWND DesktopWindowHandle
;
1541 PWINDOW_OBJECT DesktopWindow
;
1542 POINT Point
= *WinPoint
;
1545 ASSERT_REFS_CO(ScopeWin
);
1551 DPRINT1("WinPosWindowFromPoint(): ScopeWin == NULL!\n");
1555 if (ScopeWin
->Style
& WS_DISABLED
)
1560 /* Translate the point to the space of the scope window. */
1561 DesktopWindowHandle
= IntGetDesktopWindow();
1562 if((DesktopWindowHandle
!= ScopeWin
->hSelf
) &&
1563 (DesktopWindow
= IntGetWindowObject(DesktopWindowHandle
)))
1565 Point
.x
+= ScopeWin
->ClientRect
.left
- DesktopWindow
->ClientRect
.left
;
1566 Point
.y
+= ScopeWin
->ClientRect
.top
- DesktopWindow
->ClientRect
.top
;
1567 IntReleaseWindowObject(DesktopWindow
);
1570 HitTest
= HTNOWHERE
;
1572 co_WinPosSearchChildren(ScopeWin
, OnlyHitTests
, &Point
, Window
, &HitTest
);
1574 return ((*Window
) ? HitTest
: HTNOWHERE
);
1579 NtUserGetMinMaxInfo(
1581 MINMAXINFO
*MinMaxInfo
,
1585 PINTERNALPOS InternalPos
;
1586 PWINDOW_OBJECT Window
= NULL
;
1587 MINMAXINFO SafeMinMax
;
1589 DECLARE_RETURN(BOOL
);
1591 DPRINT("Enter NtUserGetMinMaxInfo\n");
1592 UserEnterExclusive();
1594 if(!(Window
= UserGetWindowObject(hWnd
)))
1599 UserRefObjectCo(Window
);
1601 Size
.x
= Window
->WindowRect
.left
;
1602 Size
.y
= Window
->WindowRect
.top
;
1603 InternalPos
= WinPosInitInternalPos(Window
, &Size
,
1604 &Window
->WindowRect
);
1609 co_WinPosGetMinMaxInfo(Window
, &SafeMinMax
.ptMaxSize
, &SafeMinMax
.ptMaxPosition
,
1610 &SafeMinMax
.ptMinTrackSize
, &SafeMinMax
.ptMaxTrackSize
);
1614 WinPosFillMinMaxInfoStruct(Window
, &SafeMinMax
);
1616 Status
= MmCopyToCaller(MinMaxInfo
, &SafeMinMax
, sizeof(MINMAXINFO
));
1617 if(!NT_SUCCESS(Status
))
1619 SetLastNtError(Status
);
1630 UserDerefObjectCo(Window
);
1632 DPRINT("Leave NtUserGetMinMaxInfo, ret=%i\n",_ret_
);