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.
130 BOOL FASTCALL
can_activate_window( PWINDOW_OBJECT Wnd OPTIONAL
)
134 if (!Wnd
) return FALSE
;
136 if (!(style
& WS_VISIBLE
)) return FALSE
;
137 if ((style
& (WS_POPUP
|WS_CHILD
)) == WS_CHILD
) return FALSE
;
138 return !(style
& WS_DISABLED
);
142 /*******************************************************************
143 * WinPosActivateOtherWindow
145 * Activates window other than pWnd.
148 co_WinPosActivateOtherWindow(PWINDOW_OBJECT Window
)
150 PWINDOW_OBJECT WndTo
= NULL
;
152 USER_REFERENCE_ENTRY Ref
;
154 ASSERT_REFS_CO(Window
);
156 if (IntIsDesktopWindow(Window
))
158 IntSetFocusMessageQueue(NULL
);
162 /* If this is popup window, try to activate the owner first. */
163 if ((Window
->Style
& WS_POPUP
) && (WndTo
= IntGetOwner(Window
)))
165 WndTo
= UserGetAncestor( WndTo
, GA_ROOT
);
166 if (can_activate_window(WndTo
)) goto done
;
169 /* Pick a next top-level window. */
170 /* FIXME: Search for non-tooltip windows first. */
174 if (!(WndTo
= WndTo
->NextSibling
)) break;
175 if (can_activate_window( WndTo
)) break;
180 if (WndTo
) UserRefObjectCo(WndTo
, &Ref
);
182 Fg
= UserGetForegroundWindow();
183 if ((!Fg
|| Window
->hSelf
== Fg
) && WndTo
)//fixme: ok if WndTo is NULL??
185 /* fixme: wine can pass WndTo=NULL to co_IntSetForegroundWindow. hmm */
186 if (co_IntSetForegroundWindow(WndTo
))
188 UserDerefObjectCo(WndTo
);
193 if (!co_IntSetActiveWindow(WndTo
)) /* ok for WndTo to be NULL here */
194 co_IntSetActiveWindow(0);
196 if (WndTo
) UserDerefObjectCo(WndTo
);
202 co_WinPosArrangeIconicWindows(PWINDOW_OBJECT parent
)
205 INT i
, x
, y
, xspacing
, yspacing
;
206 HWND
*List
= IntWinListChildren(parent
);
208 ASSERT_REFS_CO(parent
);
210 IntGetClientRect( parent
, &rectParent
);
212 y
= rectParent
.bottom
;
214 xspacing
= UserGetSystemMetrics(SM_CXMINSPACING
);
215 yspacing
= UserGetSystemMetrics(SM_CYMINSPACING
);
217 DPRINT("X:%d Y:%d XS:%d YS:%d\n",x
,y
,xspacing
,yspacing
);
219 for( i
= 0; List
[i
]; i
++)
221 PWINDOW_OBJECT WndChild
;
223 if (!(WndChild
= UserGetWindowObject(List
[i
])))
226 if((WndChild
->Style
& WS_MINIMIZE
) != 0 )
228 USER_REFERENCE_ENTRY Ref
;
229 UserRefObjectCo(WndChild
, &Ref
);
231 co_WinPosSetWindowPos(WndChild
, 0, x
+ UserGetSystemMetrics(SM_CXBORDER
),
232 y
- yspacing
- UserGetSystemMetrics(SM_CYBORDER
)
233 , 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
235 UserDerefObjectCo(WndChild
);
237 if (x
<= rectParent
.right
- xspacing
)
252 WinPosFindIconPos(PWINDOW_OBJECT Window
, POINT
*Pos
)
257 PINTERNALPOS FASTCALL
258 WinPosInitInternalPos(PWINDOW_OBJECT Window
, POINT
*pt
, PRECT RestoreRect
)
260 PWINDOW_OBJECT Parent
;
263 if (Window
->InternalPos
== NULL
)
266 PDESKTOP_OBJECT Desktop
= PsGetWin32Thread()->Desktop
; /* Or rather get it from the window? */
268 Parent
= Window
->Parent
;
271 if(IntIsDesktopWindow(Parent
))
272 IntGetDesktopWorkArea(Desktop
, &WorkArea
);
274 WorkArea
= Parent
->ClientRect
;
277 IntGetDesktopWorkArea(Desktop
, &WorkArea
);
279 Window
->InternalPos
= ExAllocatePoolWithTag(PagedPool
, sizeof(INTERNALPOS
), TAG_WININTLIST
);
280 if(!Window
->InternalPos
)
282 DPRINT1("Failed to allocate INTERNALPOS structure for window 0x%x\n", Window
->hSelf
);
285 Window
->InternalPos
->NormalRect
= Window
->WindowRect
;
286 IntGetWindowBorderMeasures(Window
, &XInc
, &YInc
);
287 Window
->InternalPos
->MaxPos
.x
= WorkArea
.left
- XInc
;
288 Window
->InternalPos
->MaxPos
.y
= WorkArea
.top
- YInc
;
289 Window
->InternalPos
->IconPos
.x
= WorkArea
.left
;
290 Window
->InternalPos
->IconPos
.y
= WorkArea
.bottom
- UserGetSystemMetrics(SM_CYMINIMIZED
);
292 if (Window
->Style
& WS_MINIMIZE
)
294 Window
->InternalPos
->IconPos
= *pt
;
296 else if (Window
->Style
& WS_MAXIMIZE
)
298 Window
->InternalPos
->MaxPos
= *pt
;
300 else if (RestoreRect
!= NULL
)
302 Window
->InternalPos
->NormalRect
= *RestoreRect
;
304 return(Window
->InternalPos
);
308 co_WinPosMinMaximize(PWINDOW_OBJECT Window
, UINT ShowFlag
, RECT
* NewPos
)
311 PINTERNALPOS InternalPos
;
314 ASSERT_REFS_CO(Window
);
316 Size
.x
= Window
->WindowRect
.left
;
317 Size
.y
= Window
->WindowRect
.top
;
318 InternalPos
= WinPosInitInternalPos(Window
, &Size
, &Window
->WindowRect
);
322 if (Window
->Style
& WS_MINIMIZE
)
324 if (!co_IntSendMessage(Window
->hSelf
, WM_QUERYOPEN
, 0, 0))
326 return(SWP_NOSIZE
| SWP_NOMOVE
);
328 SwpFlags
|= SWP_NOCOPYBITS
;
334 if (Window
->Style
& WS_MAXIMIZE
)
336 Window
->Flags
|= WINDOWOBJECT_RESTOREMAX
;
337 Window
->Style
&= ~WS_MAXIMIZE
;
341 Window
->Flags
&= ~WINDOWOBJECT_RESTOREMAX
;
343 co_UserRedrawWindow(Window
, NULL
, 0, RDW_VALIDATE
| RDW_NOERASE
|
344 RDW_NOINTERNALPAINT
);
345 Window
->Style
|= WS_MINIMIZE
;
346 WinPosFindIconPos(Window
, &InternalPos
->IconPos
);
347 IntGdiSetRect(NewPos
, InternalPos
->IconPos
.x
, InternalPos
->IconPos
.y
,
348 UserGetSystemMetrics(SM_CXMINIMIZED
),
349 UserGetSystemMetrics(SM_CYMINIMIZED
));
350 SwpFlags
|= SWP_NOCOPYBITS
;
356 co_WinPosGetMinMaxInfo(Window
, &Size
, &InternalPos
->MaxPos
,
358 DPRINT("Maximize: %d,%d %dx%d\n",
359 InternalPos
->MaxPos
.x
, InternalPos
->MaxPos
.y
, Size
.x
, Size
.y
);
360 if (Window
->Style
& WS_MINIMIZE
)
362 Window
->Style
&= ~WS_MINIMIZE
;
364 Window
->Style
|= WS_MAXIMIZE
;
365 IntGdiSetRect(NewPos
, InternalPos
->MaxPos
.x
, InternalPos
->MaxPos
.y
,
372 if (Window
->Style
& WS_MINIMIZE
)
374 Window
->Style
&= ~WS_MINIMIZE
;
375 if (Window
->Flags
& WINDOWOBJECT_RESTOREMAX
)
377 co_WinPosGetMinMaxInfo(Window
, &Size
,
378 &InternalPos
->MaxPos
, NULL
, NULL
);
379 Window
->Style
|= WS_MAXIMIZE
;
380 IntGdiSetRect(NewPos
, InternalPos
->MaxPos
.x
,
381 InternalPos
->MaxPos
.y
, Size
.x
, Size
.y
);
386 *NewPos
= InternalPos
->NormalRect
;
387 NewPos
->right
-= NewPos
->left
;
388 NewPos
->bottom
-= NewPos
->top
;
394 if (!(Window
->Style
& WS_MAXIMIZE
))
398 Window
->Style
&= ~WS_MAXIMIZE
;
399 *NewPos
= InternalPos
->NormalRect
;
400 NewPos
->right
-= NewPos
->left
;
401 NewPos
->bottom
-= NewPos
->top
;
409 SwpFlags
|= SWP_NOSIZE
| SWP_NOMOVE
;
416 WinPosFillMinMaxInfoStruct(PWINDOW_OBJECT Window
, MINMAXINFO
*Info
)
420 PDESKTOP_OBJECT Desktop
= PsGetWin32Thread()->Desktop
; /* Or rather get it from the window? */
422 IntGetDesktopWorkArea(Desktop
, &WorkArea
);
424 /* Get default values. */
425 Info
->ptMinTrackSize
.x
= UserGetSystemMetrics(SM_CXMINTRACK
);
426 Info
->ptMinTrackSize
.y
= UserGetSystemMetrics(SM_CYMINTRACK
);
428 IntGetWindowBorderMeasures(Window
, &XInc
, &YInc
);
429 Info
->ptMaxSize
.x
= WorkArea
.right
- WorkArea
.left
+ 2 * XInc
;
430 Info
->ptMaxSize
.y
= WorkArea
.bottom
- WorkArea
.top
+ 2 * YInc
;
431 Info
->ptMaxTrackSize
.x
= Info
->ptMaxSize
.x
;
432 Info
->ptMaxTrackSize
.y
= Info
->ptMaxSize
.y
;
434 if (Window
->InternalPos
!= NULL
)
436 Info
->ptMaxPosition
= Window
->InternalPos
->MaxPos
;
440 Info
->ptMaxPosition
.x
= WorkArea
.left
- XInc
;
441 Info
->ptMaxPosition
.y
= WorkArea
.top
- YInc
;
446 co_WinPosGetMinMaxInfo(PWINDOW_OBJECT Window
, POINT
* MaxSize
, POINT
* MaxPos
,
447 POINT
* MinTrack
, POINT
* MaxTrack
)
451 ASSERT_REFS_CO(Window
);
453 WinPosFillMinMaxInfoStruct(Window
, &MinMax
);
455 co_IntSendMessage(Window
->hSelf
, WM_GETMINMAXINFO
, 0, (LPARAM
)&MinMax
);
457 MinMax
.ptMaxTrackSize
.x
= max(MinMax
.ptMaxTrackSize
.x
,
458 MinMax
.ptMinTrackSize
.x
);
459 MinMax
.ptMaxTrackSize
.y
= max(MinMax
.ptMaxTrackSize
.y
,
460 MinMax
.ptMinTrackSize
.y
);
463 *MaxSize
= MinMax
.ptMaxSize
;
465 *MaxPos
= MinMax
.ptMaxPosition
;
467 *MinTrack
= MinMax
.ptMinTrackSize
;
469 *MaxTrack
= MinMax
.ptMaxTrackSize
;
471 return 0; //FIXME: what does it return?
476 FixClientRect(PRECT ClientRect
, PRECT WindowRect
)
478 if (ClientRect
->left
< WindowRect
->left
)
480 ClientRect
->left
= WindowRect
->left
;
482 else if (WindowRect
->right
< ClientRect
->left
)
484 ClientRect
->left
= WindowRect
->right
;
486 if (ClientRect
->right
< WindowRect
->left
)
488 ClientRect
->right
= WindowRect
->left
;
490 else if (WindowRect
->right
< ClientRect
->right
)
492 ClientRect
->right
= WindowRect
->right
;
494 if (ClientRect
->top
< WindowRect
->top
)
496 ClientRect
->top
= WindowRect
->top
;
498 else if (WindowRect
->bottom
< ClientRect
->top
)
500 ClientRect
->top
= WindowRect
->bottom
;
502 if (ClientRect
->bottom
< WindowRect
->top
)
504 ClientRect
->bottom
= WindowRect
->top
;
506 else if (WindowRect
->bottom
< ClientRect
->bottom
)
508 ClientRect
->bottom
= WindowRect
->bottom
;
514 co_WinPosDoNCCALCSize(PWINDOW_OBJECT Window
, PWINDOWPOS WinPos
,
515 RECT
* WindowRect
, RECT
* ClientRect
)
517 PWINDOW_OBJECT Parent
;
520 ASSERT_REFS_CO(Window
);
522 /* Send WM_NCCALCSIZE message to get new client area */
523 if ((WinPos
->flags
& (SWP_FRAMECHANGED
| SWP_NOSIZE
)) != SWP_NOSIZE
)
525 NCCALCSIZE_PARAMS params
;
526 WINDOWPOS winposCopy
;
528 params
.rgrc
[0] = *WindowRect
;
529 params
.rgrc
[1] = Window
->WindowRect
;
530 params
.rgrc
[2] = Window
->ClientRect
;
531 Parent
= Window
->Parent
;
532 if (0 != (Window
->Style
& WS_CHILD
) && Parent
)
534 IntGdiOffsetRect(&(params
.rgrc
[0]), - Parent
->ClientRect
.left
,
535 - Parent
->ClientRect
.top
);
536 IntGdiOffsetRect(&(params
.rgrc
[1]), - Parent
->ClientRect
.left
,
537 - Parent
->ClientRect
.top
);
538 IntGdiOffsetRect(&(params
.rgrc
[2]), - Parent
->ClientRect
.left
,
539 - Parent
->ClientRect
.top
);
541 params
.lppos
= &winposCopy
;
542 winposCopy
= *WinPos
;
544 wvrFlags
= co_IntSendMessage(Window
->hSelf
, WM_NCCALCSIZE
, TRUE
, (LPARAM
) ¶ms
);
546 /* If the application send back garbage, ignore it */
547 if (params
.rgrc
[0].left
<= params
.rgrc
[0].right
&&
548 params
.rgrc
[0].top
<= params
.rgrc
[0].bottom
)
550 *ClientRect
= params
.rgrc
[0];
551 if ((Window
->Style
& WS_CHILD
) && Parent
)
553 IntGdiOffsetRect(ClientRect
, Parent
->ClientRect
.left
,
554 Parent
->ClientRect
.top
);
556 FixClientRect(ClientRect
, WindowRect
);
559 /* FIXME: WVR_ALIGNxxx */
561 if (ClientRect
->left
!= Window
->ClientRect
.left
||
562 ClientRect
->top
!= Window
->ClientRect
.top
)
564 WinPos
->flags
&= ~SWP_NOCLIENTMOVE
;
567 if ((ClientRect
->right
- ClientRect
->left
!=
568 Window
->ClientRect
.right
- Window
->ClientRect
.left
) ||
569 (ClientRect
->bottom
- ClientRect
->top
!=
570 Window
->ClientRect
.bottom
- Window
->ClientRect
.top
))
572 WinPos
->flags
&= ~SWP_NOCLIENTSIZE
;
577 if (! (WinPos
->flags
& SWP_NOMOVE
)
578 && (ClientRect
->left
!= Window
->ClientRect
.left
||
579 ClientRect
->top
!= Window
->ClientRect
.top
))
581 WinPos
->flags
&= ~SWP_NOCLIENTMOVE
;
590 co_WinPosDoWinPosChanging(PWINDOW_OBJECT Window
,
597 ASSERT_REFS_CO(Window
);
599 if (!(WinPos
->flags
& SWP_NOSENDCHANGING
))
601 co_IntPostOrSendMessage(Window
->hSelf
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
) WinPos
);
604 *WindowRect
= Window
->WindowRect
;
605 *ClientRect
= Window
->ClientRect
;
607 if (!(WinPos
->flags
& SWP_NOSIZE
))
609 WindowRect
->right
= WindowRect
->left
+ WinPos
->cx
;
610 WindowRect
->bottom
= WindowRect
->top
+ WinPos
->cy
;
613 if (!(WinPos
->flags
& SWP_NOMOVE
))
615 PWINDOW_OBJECT Parent
;
618 Parent
= Window
->Parent
;
619 if ((0 != (Window
->Style
& WS_CHILD
)) && Parent
)
621 X
+= Parent
->ClientRect
.left
;
622 Y
+= Parent
->ClientRect
.top
;
625 WindowRect
->left
= X
;
627 WindowRect
->right
+= X
- Window
->WindowRect
.left
;
628 WindowRect
->bottom
+= Y
- Window
->WindowRect
.top
;
629 IntGdiOffsetRect(ClientRect
,
630 X
- Window
->WindowRect
.left
,
631 Y
- Window
->WindowRect
.top
);
634 WinPos
->flags
|= SWP_NOCLIENTMOVE
| SWP_NOCLIENTSIZE
;
640 * Fix Z order taking into account owned popups -
641 * basically we need to maintain them above the window that owns them
645 WinPosDoOwnedPopups(HWND hWnd
, HWND hWndInsertAfter
)
648 HWND Owner
= UserGetWindow(hWnd
, GW_OWNER
);
649 LONG Style
= UserGetWindowLong(hWnd
, GWL_STYLE
, FALSE
);
650 PWINDOW_OBJECT DesktopWindow
, ChildObject
;
653 if ((Style
& WS_POPUP
) && Owner
)
655 /* Make sure this popup stays above the owner */
656 HWND hWndLocalPrev
= HWND_TOPMOST
;
658 if (hWndInsertAfter
!= HWND_TOPMOST
)
660 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
661 List
= IntWinListChildren(DesktopWindow
);
665 for (i
= 0; List
[i
]; i
++)
667 if (List
[i
] == Owner
)
669 if (HWND_TOP
== hWndInsertAfter
)
671 ChildObject
= UserGetWindowObject(List
[i
]);
672 if (NULL
!= ChildObject
)
674 if (0 == (ChildObject
->ExStyle
& WS_EX_TOPMOST
))
681 hWndLocalPrev
= List
[i
];
682 if (hWndLocalPrev
== hWndInsertAfter
)
685 hWndInsertAfter
= hWndLocalPrev
;
689 else if (Style
& WS_CHILD
)
691 return hWndInsertAfter
;
696 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
697 List
= IntWinListChildren(DesktopWindow
);
701 for (i
= 0; List
[i
]; i
++)
708 if (!(Wnd
= UserGetWindowObject(List
[i
])))
711 if ((Wnd
->Style
& WS_POPUP
) &&
712 UserGetWindow(List
[i
], GW_OWNER
) == hWnd
)
714 USER_REFERENCE_ENTRY Ref
;
715 UserRefObjectCo(Wnd
, &Ref
);
717 co_WinPosSetWindowPos(Wnd
, hWndInsertAfter
, 0, 0, 0, 0,
718 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOSENDCHANGING
);
720 UserDerefObjectCo(Wnd
);
722 hWndInsertAfter
= List
[i
];
728 return hWndInsertAfter
;
731 /***********************************************************************
732 * WinPosInternalMoveWindow
734 * Update WindowRect and ClientRect of Window and all of its children
735 * We keep both WindowRect and ClientRect in screen coordinates internally
739 WinPosInternalMoveWindow(PWINDOW_OBJECT Window
, INT MoveX
, INT MoveY
)
741 PWINDOW_OBJECT Child
;
743 Window
->WindowRect
.left
+= MoveX
;
744 Window
->WindowRect
.right
+= MoveX
;
745 Window
->WindowRect
.top
+= MoveY
;
746 Window
->WindowRect
.bottom
+= MoveY
;
748 Window
->ClientRect
.left
+= MoveX
;
749 Window
->ClientRect
.right
+= MoveX
;
750 Window
->ClientRect
.top
+= MoveY
;
751 Window
->ClientRect
.bottom
+= MoveY
;
753 for(Child
= Window
->FirstChild
; Child
; Child
= Child
->NextSibling
)
755 WinPosInternalMoveWindow(Child
, MoveX
, MoveY
);
760 * WinPosFixupSWPFlags
762 * Fix redundant flags and values in the WINDOWPOS structure.
766 WinPosFixupFlags(WINDOWPOS
*WinPos
, PWINDOW_OBJECT Window
)
768 if (Window
->Style
& WS_VISIBLE
)
770 WinPos
->flags
&= ~SWP_SHOWWINDOW
;
774 WinPos
->flags
&= ~SWP_HIDEWINDOW
;
775 if (!(WinPos
->flags
& SWP_SHOWWINDOW
))
776 WinPos
->flags
|= SWP_NOREDRAW
;
779 WinPos
->cx
= max(WinPos
->cx
, 0);
780 WinPos
->cy
= max(WinPos
->cy
, 0);
782 /* Check for right size */
783 if (Window
->WindowRect
.right
- Window
->WindowRect
.left
== WinPos
->cx
&&
784 Window
->WindowRect
.bottom
- Window
->WindowRect
.top
== WinPos
->cy
)
786 WinPos
->flags
|= SWP_NOSIZE
;
789 /* Check for right position */
790 if (Window
->WindowRect
.left
== WinPos
->x
&&
791 Window
->WindowRect
.top
== WinPos
->y
)
793 WinPos
->flags
|= SWP_NOMOVE
;
796 if (WinPos
->hwnd
== UserGetForegroundWindow())
798 WinPos
->flags
|= SWP_NOACTIVATE
; /* Already active */
801 if ((Window
->Style
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)
803 /* Bring to the top when activating */
804 if (!(WinPos
->flags
& SWP_NOACTIVATE
))
806 WinPos
->flags
&= ~SWP_NOZORDER
;
807 WinPos
->hwndInsertAfter
= (0 != (Window
->ExStyle
& WS_EX_TOPMOST
) ?
808 HWND_TOPMOST
: HWND_TOP
);
813 /* Check hwndInsertAfter */
814 if (!(WinPos
->flags
& SWP_NOZORDER
))
816 /* Fix sign extension */
817 if (WinPos
->hwndInsertAfter
== (HWND
)0xffff)
819 WinPos
->hwndInsertAfter
= HWND_TOPMOST
;
821 else if (WinPos
->hwndInsertAfter
== (HWND
)0xfffe)
823 WinPos
->hwndInsertAfter
= HWND_NOTOPMOST
;
826 if (WinPos
->hwndInsertAfter
== HWND_NOTOPMOST
)
828 WinPos
->hwndInsertAfter
= HWND_TOP
;
830 else if (HWND_TOP
== WinPos
->hwndInsertAfter
831 && 0 != (Window
->ExStyle
& WS_EX_TOPMOST
))
833 /* Keep it topmost when it's already topmost */
834 WinPos
->hwndInsertAfter
= HWND_TOPMOST
;
837 /* hwndInsertAfter must be a sibling of the window */
838 if (HWND_TOPMOST
!= WinPos
->hwndInsertAfter
839 && HWND_TOP
!= WinPos
->hwndInsertAfter
840 && HWND_NOTOPMOST
!= WinPos
->hwndInsertAfter
841 && HWND_BOTTOM
!= WinPos
->hwndInsertAfter
)
843 PWINDOW_OBJECT InsAfterWnd
, Parent
= Window
->Parent
;
845 InsAfterWnd
= UserGetWindowObject(WinPos
->hwndInsertAfter
);
847 if (InsAfterWnd
&& UserGetAncestor(InsAfterWnd
, GA_PARENT
) != Parent
)
854 * We don't need to change the Z order of hwnd if it's already
855 * inserted after hwndInsertAfter or when inserting hwnd after
858 if ((WinPos
->hwnd
== WinPos
->hwndInsertAfter
) ||
859 (WinPos
->hwnd
== UserGetWindow(WinPos
->hwndInsertAfter
, GW_HWNDNEXT
)))
861 WinPos
->flags
|= SWP_NOZORDER
;
870 /* x and y are always screen relative */
872 co_WinPosSetWindowPos(
873 PWINDOW_OBJECT Window
,
886 HRGN VisBefore
= NULL
;
887 HRGN VisAfter
= NULL
;
888 HRGN DirtyRgn
= NULL
;
889 HRGN ExposedRgn
= NULL
;
892 RECT OldWindowRect
, OldClientRect
;
898 ASSERT_REFS_CO(Window
);
900 /* FIXME: Get current active window from active queue. */
903 * Only allow CSRSS to mess with the desktop window
905 if (Window
->hSelf
== IntGetDesktopWindow() &&
906 Window
->OwnerThread
->ThreadsProcess
!= PsGetCurrentProcess())
911 WinPos
.hwnd
= Window
->hSelf
;
912 WinPos
.hwndInsertAfter
= WndInsertAfter
;
917 WinPos
.flags
= flags
;
919 co_WinPosDoWinPosChanging(Window
, &WinPos
, &NewWindowRect
, &NewClientRect
);
921 /* Fix up the flags. */
922 if (!WinPosFixupFlags(&WinPos
, Window
))
924 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
928 /* Does the window still exist? */
929 if (!IntIsWindow(WinPos
.hwnd
))
931 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
935 if ((WinPos
.flags
& (SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) !=
937 // UserGetAncestor(WinPos.hwnd, GA_PARENT) == IntGetDesktopWindow())
938 //faxme: is WinPos.hwnd constant?? (WinPos.hwnd = Window->hSelf above)
939 UserGetAncestor(Window
, GA_PARENT
)->hSelf
== IntGetDesktopWindow())
941 WinPos
.hwndInsertAfter
= WinPosDoOwnedPopups(WinPos
.hwnd
, WinPos
.hwndInsertAfter
);
944 if (!(WinPos
.flags
& SWP_NOREDRAW
))
946 /* Compute the visible region before the window position is changed */
947 if (!(WinPos
.flags
& (SWP_NOREDRAW
| SWP_SHOWWINDOW
)) &&
948 (WinPos
.flags
& (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
|
949 SWP_HIDEWINDOW
| SWP_FRAMECHANGED
)) !=
950 (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
))
952 VisBefore
= VIS_ComputeVisibleRegion(Window
, FALSE
, FALSE
, TRUE
);
955 if (VisBefore
!= NULL
&& (VisRgn
= (PROSRGNDATA
)RGNDATA_LockRgn(VisBefore
)) &&
956 UnsafeIntGetRgnBox(VisRgn
, &TempRect
) == NULLREGION
)
958 RGNDATA_UnlockRgn(VisRgn
);
959 NtGdiDeleteObject(VisBefore
);
964 RGNDATA_UnlockRgn(VisRgn
);
965 NtGdiOffsetRgn(VisBefore
, -Window
->WindowRect
.left
, -Window
->WindowRect
.top
);
970 WvrFlags
= co_WinPosDoNCCALCSize(Window
, &WinPos
, &NewWindowRect
, &NewClientRect
);
972 /* Relink windows. (also take into account shell window in hwndShellWindow) */
973 if (!(WinPos
.flags
& SWP_NOZORDER
) && WinPos
.hwnd
!= UserGetShellWindow())
975 PWINDOW_OBJECT ParentWindow
;
976 PWINDOW_OBJECT Sibling
;
977 PWINDOW_OBJECT InsertAfterWindow
;
979 if ((ParentWindow
= Window
->Parent
))
981 if (HWND_TOPMOST
== WinPos
.hwndInsertAfter
)
983 InsertAfterWindow
= NULL
;
985 else if (HWND_TOP
== WinPos
.hwndInsertAfter
986 || HWND_NOTOPMOST
== WinPos
.hwndInsertAfter
)
988 InsertAfterWindow
= NULL
;
989 Sibling
= ParentWindow
->FirstChild
;
990 while (NULL
!= Sibling
&& 0 != (Sibling
->ExStyle
& WS_EX_TOPMOST
))
992 InsertAfterWindow
= Sibling
;
993 Sibling
= Sibling
->NextSibling
;
995 if (NULL
!= InsertAfterWindow
)
997 UserRefObject(InsertAfterWindow
);
1000 else if (WinPos
.hwndInsertAfter
== HWND_BOTTOM
)
1002 if(ParentWindow
->LastChild
)
1004 UserRefObject(ParentWindow
->LastChild
);
1005 InsertAfterWindow
= ParentWindow
->LastChild
;
1008 InsertAfterWindow
= NULL
;
1011 InsertAfterWindow
= IntGetWindowObject(WinPos
.hwndInsertAfter
);
1012 /* Do nothing if hwndInsertAfter is HWND_BOTTOM and Window is already
1014 if (InsertAfterWindow
!= Window
)
1016 IntUnlinkWindow(Window
);
1017 IntLinkWindow(Window
, ParentWindow
, InsertAfterWindow
);
1019 if (InsertAfterWindow
!= NULL
)
1020 UserDerefObject(InsertAfterWindow
);
1021 if ((HWND_TOPMOST
== WinPos
.hwndInsertAfter
)
1022 || (0 != (Window
->ExStyle
& WS_EX_TOPMOST
)
1023 && NULL
!= Window
->PrevSibling
1024 && 0 != (Window
->PrevSibling
->ExStyle
& WS_EX_TOPMOST
))
1025 || (NULL
!= Window
->NextSibling
1026 && 0 != (Window
->NextSibling
->ExStyle
& WS_EX_TOPMOST
)))
1028 Window
->ExStyle
|= WS_EX_TOPMOST
;
1032 Window
->ExStyle
&= ~ WS_EX_TOPMOST
;
1038 OldWindowRect
= Window
->WindowRect
;
1039 OldClientRect
= Window
->ClientRect
;
1041 if (OldClientRect
.bottom
- OldClientRect
.top
==
1042 NewClientRect
.bottom
- NewClientRect
.top
)
1044 WvrFlags
&= ~WVR_VREDRAW
;
1047 if (OldClientRect
.right
- OldClientRect
.left
==
1048 NewClientRect
.right
- NewClientRect
.left
)
1050 WvrFlags
&= ~WVR_HREDRAW
;
1053 /* FIXME: Actually do something with WVR_VALIDRECTS */
1055 if (NewClientRect
.left
!= OldClientRect
.left
||
1056 NewClientRect
.top
!= OldClientRect
.top
)
1058 WinPosInternalMoveWindow(Window
,
1059 NewClientRect
.left
- OldClientRect
.left
,
1060 NewClientRect
.top
- OldClientRect
.top
);
1063 Window
->WindowRect
= NewWindowRect
;
1064 Window
->ClientRect
= NewClientRect
;
1066 if (!(WinPos
.flags
& SWP_SHOWWINDOW
) && (WinPos
.flags
& SWP_HIDEWINDOW
))
1068 /* Clear the update region */
1069 co_UserRedrawWindow(Window
, NULL
, 0, RDW_VALIDATE
| RDW_NOFRAME
|
1070 RDW_NOERASE
| RDW_NOINTERNALPAINT
| RDW_ALLCHILDREN
);
1071 if ((Window
->Style
& WS_VISIBLE
) &&
1072 Window
->Parent
== UserGetDesktopWindow())
1074 co_IntShellHookNotify(HSHELL_WINDOWDESTROYED
, (LPARAM
)Window
->hSelf
);
1076 Window
->Style
&= ~WS_VISIBLE
;
1078 else if (WinPos
.flags
& SWP_SHOWWINDOW
)
1080 if (!(Window
->Style
& WS_VISIBLE
) &&
1081 Window
->Parent
== UserGetDesktopWindow())
1083 co_IntShellHookNotify(HSHELL_WINDOWCREATED
, (LPARAM
)Window
->hSelf
);
1085 Window
->Style
|= WS_VISIBLE
;
1088 if (Window
->UpdateRegion
!= NULL
&& Window
->UpdateRegion
!= (HRGN
)1)
1090 NtGdiOffsetRgn(Window
->UpdateRegion
,
1091 NewWindowRect
.left
- OldWindowRect
.left
,
1092 NewWindowRect
.top
- OldWindowRect
.top
);
1095 DceResetActiveDCEs(Window
);
1097 if (!(WinPos
.flags
& SWP_NOREDRAW
))
1099 /* Determine the new visible region */
1100 VisAfter
= VIS_ComputeVisibleRegion(Window
, FALSE
, FALSE
, TRUE
);
1103 if (VisAfter
!= NULL
&& (VisRgn
= (PROSRGNDATA
)RGNDATA_LockRgn(VisAfter
)) &&
1104 UnsafeIntGetRgnBox(VisRgn
, &TempRect
) == NULLREGION
)
1106 RGNDATA_UnlockRgn(VisRgn
);
1107 NtGdiDeleteObject(VisAfter
);
1112 RGNDATA_UnlockRgn(VisRgn
);
1113 NtGdiOffsetRgn(VisAfter
, -Window
->WindowRect
.left
, -Window
->WindowRect
.top
);
1117 * Determine which pixels can be copied from the old window position
1118 * to the new. Those pixels must be visible in both the old and new
1119 * position. Also, check the class style to see if the windows of this
1120 * class need to be completely repainted on (horizontal/vertical) size
1123 if (VisBefore
!= NULL
&& VisAfter
!= NULL
&& !(WinPos
.flags
& SWP_NOCOPYBITS
) &&
1124 ((WinPos
.flags
& SWP_NOSIZE
) || !(WvrFlags
& WVR_REDRAW
)) &&
1125 !(Window
->ExStyle
& WS_EX_TRANSPARENT
))
1127 CopyRgn
= NtGdiCreateRectRgn(0, 0, 0, 0);
1128 RgnType
= NtGdiCombineRgn(CopyRgn
, VisAfter
, VisBefore
, RGN_AND
);
1131 * If this is (also) a window resize, the whole nonclient area
1132 * needs to be repainted. So we limit the copy to the client area,
1133 * 'cause there is no use in copying it (would possibly cause
1134 * "flashing" too). However, if the copy region is already empty,
1135 * we don't have to crop (can't take anything away from an empty
1138 if (!(WinPos
.flags
& SWP_NOSIZE
) && RgnType
!= ERROR
&&
1139 RgnType
!= NULLREGION
)
1141 RECT ORect
= OldClientRect
;
1142 RECT NRect
= NewClientRect
;
1143 IntGdiOffsetRect(&ORect
, - OldWindowRect
.left
, - OldWindowRect
.top
);
1144 IntGdiOffsetRect(&NRect
, - NewWindowRect
.left
, - NewWindowRect
.top
);
1145 IntGdiIntersectRect(&CopyRect
, &ORect
, &NRect
);
1146 REGION_CropRgn(CopyRgn
, CopyRgn
, &CopyRect
, NULL
);
1149 /* No use in copying bits which are in the update region. */
1150 if (Window
->UpdateRegion
!= NULL
)
1152 NtGdiOffsetRgn(CopyRgn
, NewWindowRect
.left
, NewWindowRect
.top
);
1153 NtGdiCombineRgn(CopyRgn
, CopyRgn
, Window
->UpdateRegion
, RGN_DIFF
);
1154 NtGdiOffsetRgn(CopyRgn
, -NewWindowRect
.left
, -NewWindowRect
.top
);
1158 * Now, get the bounding box of the copy region. If it's empty
1159 * there's nothing to copy. Also, it's no use copying bits onto
1162 if ((VisRgn
= (PROSRGNDATA
)RGNDATA_LockRgn(CopyRgn
)) &&
1163 UnsafeIntGetRgnBox(VisRgn
, &CopyRect
) == NULLREGION
)
1165 /* Nothing to copy, clean up */
1166 RGNDATA_UnlockRgn(VisRgn
);
1167 NtGdiDeleteObject(CopyRgn
);
1170 else if (OldWindowRect
.left
!= NewWindowRect
.left
||
1171 OldWindowRect
.top
!= NewWindowRect
.top
)
1175 RGNDATA_UnlockRgn(VisRgn
);
1179 * Small trick here: there is no function to bitblt a region. So
1180 * we set the region as the clipping region, take the bounding box
1181 * of the region and bitblt that. Since nothing outside the clipping
1182 * region is copied, this has the effect of bitblt'ing the region.
1184 * Since NtUserGetDCEx takes ownership of the clip region, we need
1185 * to create a copy of CopyRgn and pass that. We need CopyRgn later
1187 NtGdiOffsetRgn(CopyRgn
, NewWindowRect
.left
, NewWindowRect
.top
);
1188 Dc
= UserGetDCEx(Window
, CopyRgn
, DCX_WINDOW
| DCX_CACHE
|
1189 DCX_INTERSECTRGN
| DCX_CLIPSIBLINGS
|
1192 CopyRect
.left
, CopyRect
.top
, CopyRect
.right
- CopyRect
.left
,
1193 CopyRect
.bottom
- CopyRect
.top
, Dc
,
1194 CopyRect
.left
+ (OldWindowRect
.left
- NewWindowRect
.left
),
1195 CopyRect
.top
+ (OldWindowRect
.top
- NewWindowRect
.top
), SRCCOPY
);
1196 UserReleaseDC(Window
, Dc
, FALSE
);
1197 IntValidateParent(Window
, CopyRgn
);
1198 NtGdiOffsetRgn(CopyRgn
, -NewWindowRect
.left
, -NewWindowRect
.top
);
1202 RGNDATA_UnlockRgn(VisRgn
);
1210 /* We need to redraw what wasn't visible before */
1211 if (VisAfter
!= NULL
)
1213 DirtyRgn
= NtGdiCreateRectRgn(0, 0, 0, 0);
1214 if (CopyRgn
!= NULL
)
1216 RgnType
= NtGdiCombineRgn(DirtyRgn
, VisAfter
, CopyRgn
, RGN_DIFF
);
1220 RgnType
= NtGdiCombineRgn(DirtyRgn
, VisAfter
, 0, RGN_COPY
);
1222 if (RgnType
!= ERROR
&& RgnType
!= NULLREGION
)
1226 NtGdiOffsetRgn(DirtyRgn
,
1227 Window
->WindowRect
.left
- Window
->Parent
->ClientRect
.left
,
1228 Window
->WindowRect
.top
- Window
->Parent
->ClientRect
.top
);
1229 co_UserRedrawWindow(Window
->Parent
, NULL
, DirtyRgn
,
1230 RDW_ERASE
| RDW_FRAME
| RDW_INVALIDATE
| RDW_ALLCHILDREN
);
1234 NtGdiOffsetRgn(DirtyRgn
,
1235 Window
->WindowRect
.left
- Window
->ClientRect
.left
,
1236 Window
->WindowRect
.top
- Window
->ClientRect
.top
);
1237 co_UserRedrawWindow(Window
, NULL
, DirtyRgn
,
1238 RDW_ERASE
| RDW_FRAME
| RDW_INVALIDATE
| RDW_ALLCHILDREN
);
1241 NtGdiDeleteObject(DirtyRgn
);
1244 if (CopyRgn
!= NULL
)
1246 NtGdiDeleteObject(CopyRgn
);
1249 /* Expose what was covered before but not covered anymore */
1250 if (VisBefore
!= NULL
)
1252 ExposedRgn
= NtGdiCreateRectRgn(0, 0, 0, 0);
1253 NtGdiCombineRgn(ExposedRgn
, VisBefore
, NULL
, RGN_COPY
);
1254 NtGdiOffsetRgn(ExposedRgn
, OldWindowRect
.left
- NewWindowRect
.left
,
1255 OldWindowRect
.top
- NewWindowRect
.top
);
1256 if (VisAfter
!= NULL
)
1257 RgnType
= NtGdiCombineRgn(ExposedRgn
, ExposedRgn
, VisAfter
, RGN_DIFF
);
1259 RgnType
= SIMPLEREGION
;
1261 if (RgnType
!= ERROR
&& RgnType
!= NULLREGION
)
1263 co_VIS_WindowLayoutChanged(Window
, ExposedRgn
);
1265 NtGdiDeleteObject(ExposedRgn
);
1266 NtGdiDeleteObject(VisBefore
);
1269 if (VisAfter
!= NULL
)
1271 NtGdiDeleteObject(VisAfter
);
1274 if (!(WinPos
.flags
& SWP_NOACTIVATE
))
1276 if ((Window
->Style
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1278 co_IntSendMessage(WinPos
.hwnd
, WM_CHILDACTIVATE
, 0, 0);
1282 co_IntSetForegroundWindow(Window
);
1287 if ((WinPos
.flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOPOSCHANGE
)
1288 co_IntPostOrSendMessage(WinPos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
) &WinPos
);
1294 co_WinPosGetNonClientSize(PWINDOW_OBJECT Window
, RECT
* WindowRect
, RECT
* ClientRect
)
1298 ASSERT_REFS_CO(Window
);
1300 *ClientRect
= *WindowRect
;
1301 Result
= co_IntSendMessage(Window
->hSelf
, WM_NCCALCSIZE
, FALSE
, (LPARAM
) ClientRect
);
1303 FixClientRect(ClientRect
, WindowRect
);
1309 co_WinPosShowWindow(PWINDOW_OBJECT Window
, INT Cmd
)
1317 ASSERT_REFS_CO(Window
);
1319 WasVisible
= (Window
->Style
& WS_VISIBLE
) != 0;
1329 Swp
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
1330 if (Window
->hSelf
!= UserGetActiveWindow())
1331 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1335 case SW_SHOWMINNOACTIVE
:
1336 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1338 case SW_SHOWMINIMIZED
:
1339 Swp
|= SWP_SHOWWINDOW
;
1343 Swp
|= SWP_NOACTIVATE
;
1344 if (!(Window
->Style
& WS_MINIMIZE
))
1346 Swp
|= co_WinPosMinMaximize(Window
, SW_MINIMIZE
, &NewPos
) |
1351 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1354 Swp
|= SWP_FRAMECHANGED
;
1360 case SW_SHOWMAXIMIZED
:
1362 Swp
|= SWP_SHOWWINDOW
;
1363 if (!(Window
->Style
& WS_MAXIMIZE
))
1365 Swp
|= co_WinPosMinMaximize(Window
, SW_MAXIMIZE
, &NewPos
) |
1370 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1373 Swp
|= SWP_FRAMECHANGED
;
1380 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1383 Swp
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
1384 /* Don't activate the topmost window. */
1387 case SW_SHOWNOACTIVATE
:
1388 Swp
|= SWP_NOZORDER
;
1391 case SW_SHOWDEFAULT
:
1393 Swp
|= SWP_SHOWWINDOW
;
1394 if (Window
->Style
& (WS_MINIMIZE
| WS_MAXIMIZE
))
1396 Swp
|= co_WinPosMinMaximize(Window
, SW_RESTORE
, &NewPos
) |
1401 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1404 Swp
|= SWP_FRAMECHANGED
;
1410 ShowFlag
= (Cmd
!= SW_HIDE
);
1411 if (ShowFlag
!= WasVisible
)
1413 co_IntSendMessage(Window
->hSelf
, WM_SHOWWINDOW
, ShowFlag
, 0);
1416 /* We can't activate a child window */
1417 if ((Window
->Style
& WS_CHILD
) &&
1418 !(Window
->ExStyle
& WS_EX_MDICHILD
))
1420 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1423 co_WinPosSetWindowPos(Window
, 0 != (Window
->ExStyle
& WS_EX_TOPMOST
)
1424 ? HWND_TOPMOST
: HWND_TOP
,
1425 NewPos
.left
, NewPos
.top
, NewPos
.right
, NewPos
.bottom
, LOWORD(Swp
));
1429 PWINDOW_OBJECT ThreadFocusWindow
;
1431 /* FIXME: This will cause the window to be activated irrespective
1432 * of whether it is owned by the same thread. Has to be done
1436 if (Window
->hSelf
== UserGetActiveWindow())
1438 co_WinPosActivateOtherWindow(Window
);
1443 ThreadFocusWindow
= UserGetWindowObject(IntGetThreadFocusWindow());
1445 /* Revert focus to parent */
1446 if (ThreadFocusWindow
&& (Window
== ThreadFocusWindow
||
1447 IntIsChildWindow(Window
, ThreadFocusWindow
)))
1449 //faxme: as long as we have ref on Window, we also, indirectly, have ref on parent...
1450 co_UserSetFocus(Window
->Parent
);
1454 /* FIXME: Check for window destruction. */
1456 if ((Window
->Flags
& WINDOWOBJECT_NEED_SIZE
) &&
1457 !(Window
->Status
& WINDOWSTATUS_DESTROYING
))
1459 WPARAM wParam
= SIZE_RESTORED
;
1461 Window
->Flags
&= ~WINDOWOBJECT_NEED_SIZE
;
1462 if (Window
->Style
& WS_MAXIMIZE
)
1464 wParam
= SIZE_MAXIMIZED
;
1466 else if (Window
->Style
& WS_MINIMIZE
)
1468 wParam
= SIZE_MINIMIZED
;
1471 co_IntSendMessage(Window
->hSelf
, WM_SIZE
, wParam
,
1472 MAKELONG(Window
->ClientRect
.right
-
1473 Window
->ClientRect
.left
,
1474 Window
->ClientRect
.bottom
-
1475 Window
->ClientRect
.top
));
1476 co_IntSendMessage(Window
->hSelf
, WM_MOVE
, 0,
1477 MAKELONG(Window
->ClientRect
.left
,
1478 Window
->ClientRect
.top
));
1479 IntEngWindowChanged(Window
, WOC_RGN_CLIENT
);
1482 /* Activate the window if activation is not requested and the window is not minimized */
1484 if (!(Swp & (SWP_NOACTIVATE | SWP_HIDEWINDOW)) && !(Window->Style & WS_MINIMIZE))
1486 WinPosChangeActiveWindow(Wnd, FALSE);
1495 /* find child of 'parent' that contains the given point (in parent-relative coords) */
1496 PWINDOW_OBJECT
child_window_from_point(PWINDOW_OBJECT parent
, int x
, int y
)
1498 PWINDOW_OBJECT Wnd
;// = parent->FirstChild;
1500 // LIST_FOR_EACH_ENTRY( Wnd, &parent->children, struct window, entry )
1501 for (Wnd
= parent
->FirstChild
; Wnd
; Wnd
= Wnd
->NextSibling
)
1503 if (!IntPtInWindow( Wnd
, x
, y
)) continue; /* skip it */
1505 /* if window is minimized or disabled, return at once */
1506 if (Wnd
->Style
& (WS_MINIMIZE
|WS_DISABLED
)) return Wnd
;
1508 /* if point is not in client area, return at once */
1509 if (x
< Wnd
->ClientRect
.left
|| x
>= Wnd
->ClientRect
.right
||
1510 y
< Wnd
->ClientRect
.top
|| y
>= Wnd
->ClientRect
.bottom
)
1513 return child_window_from_point( Wnd
, x
- Wnd
->ClientRect
.left
, y
- Wnd
->ClientRect
.top
);
1515 return parent
; /* not found any child */
1519 /* wine server: child_window_from_point
1521 Caller must dereference the "returned" Window
1525 co_WinPosSearchChildren(
1526 PWINDOW_OBJECT ScopeWin
,
1527 PUSER_MESSAGE_QUEUE OnlyHitTests
,
1529 PWINDOW_OBJECT
* Window
,
1533 PWINDOW_OBJECT Current
;
1535 USER_REFERENCE_ENTRY Ref
;
1537 ASSERT_REFS_CO(ScopeWin
);
1539 if ((List
= IntWinListChildren(ScopeWin
)))
1541 for (phWnd
= List
; *phWnd
; ++phWnd
)
1543 if (!(Current
= UserGetWindowObject(*phWnd
)))
1546 if (!(Current
->Style
& WS_VISIBLE
))
1551 if ((Current
->Style
& (WS_POPUP
| WS_CHILD
| WS_DISABLED
)) ==
1552 (WS_CHILD
| WS_DISABLED
))
1557 if (!IntPtInWindow(Current
, Point
->x
, Point
->y
))
1562 if (*Window
) UserDerefObject(*Window
);
1564 UserRefObject(*Window
);
1566 if (Current
->Style
& WS_MINIMIZE
)
1568 *HitTest
= HTCAPTION
;
1572 if (Current
->Style
& WS_DISABLED
)
1578 UserRefObjectCo(Current
, &Ref
);
1580 if (OnlyHitTests
&& (Current
->MessageQueue
== OnlyHitTests
))
1582 *HitTest
= co_IntSendMessage(Current
->hSelf
, WM_NCHITTEST
, 0,
1583 MAKELONG(Point
->x
, Point
->y
));
1584 if ((*HitTest
) == (USHORT
)HTTRANSPARENT
)
1586 UserDerefObjectCo(Current
);
1591 *HitTest
= HTCLIENT
;
1593 if (Point
->x
>= Current
->ClientRect
.left
&&
1594 Point
->x
< Current
->ClientRect
.right
&&
1595 Point
->y
>= Current
->ClientRect
.top
&&
1596 Point
->y
< Current
->ClientRect
.bottom
)
1598 co_WinPosSearchChildren(Current
, OnlyHitTests
, Point
, Window
, HitTest
);
1601 UserDerefObjectCo(Current
);
1609 /* wine: WINPOS_WindowFromPoint */
1611 co_WinPosWindowFromPoint(PWINDOW_OBJECT ScopeWin
, PUSER_MESSAGE_QUEUE OnlyHitTests
, POINT
*WinPoint
,
1612 PWINDOW_OBJECT
* Window
)
1614 HWND DesktopWindowHandle
;
1615 PWINDOW_OBJECT DesktopWindow
;
1616 POINT Point
= *WinPoint
;
1619 ASSERT_REFS_CO(ScopeWin
);
1625 DPRINT1("WinPosWindowFromPoint(): ScopeWin == NULL!\n");
1629 if (ScopeWin
->Style
& WS_DISABLED
)
1634 /* Translate the point to the space of the scope window. */
1635 DesktopWindowHandle
= IntGetDesktopWindow();
1636 if((DesktopWindowHandle
!= ScopeWin
->hSelf
) &&
1637 (DesktopWindow
= UserGetWindowObject(DesktopWindowHandle
)))
1639 Point
.x
+= ScopeWin
->ClientRect
.left
- DesktopWindow
->ClientRect
.left
;
1640 Point
.y
+= ScopeWin
->ClientRect
.top
- DesktopWindow
->ClientRect
.top
;
1643 HitTest
= HTNOWHERE
;
1645 co_WinPosSearchChildren(ScopeWin
, OnlyHitTests
, &Point
, Window
, &HitTest
);
1647 return ((*Window
) ? HitTest
: HTNOWHERE
);
1652 NtUserGetMinMaxInfo(
1654 MINMAXINFO
*MinMaxInfo
,
1658 PINTERNALPOS InternalPos
;
1659 PWINDOW_OBJECT Window
= NULL
;
1660 MINMAXINFO SafeMinMax
;
1662 DECLARE_RETURN(BOOL
);
1663 USER_REFERENCE_ENTRY Ref
;
1665 DPRINT("Enter NtUserGetMinMaxInfo\n");
1666 UserEnterExclusive();
1668 if(!(Window
= UserGetWindowObject(hWnd
)))
1673 UserRefObjectCo(Window
, &Ref
);
1675 Size
.x
= Window
->WindowRect
.left
;
1676 Size
.y
= Window
->WindowRect
.top
;
1677 InternalPos
= WinPosInitInternalPos(Window
, &Size
,
1678 &Window
->WindowRect
);
1683 co_WinPosGetMinMaxInfo(Window
, &SafeMinMax
.ptMaxSize
, &SafeMinMax
.ptMaxPosition
,
1684 &SafeMinMax
.ptMinTrackSize
, &SafeMinMax
.ptMaxTrackSize
);
1688 WinPosFillMinMaxInfoStruct(Window
, &SafeMinMax
);
1690 Status
= MmCopyToCaller(MinMaxInfo
, &SafeMinMax
, sizeof(MINMAXINFO
));
1691 if(!NT_SUCCESS(Status
))
1693 SetLastNtError(Status
);
1703 if (Window
) UserDerefObjectCo(Window
);
1705 DPRINT("Leave NtUserGetMinMaxInfo, ret=%i\n",_ret_
);