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 along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS kernel
23 * FILE: subsys/win32k/ntuser/window.c
24 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
26 * 06-06-2001 CSH NtGdid
28 /* INCLUDES ******************************************************************/
36 co_IntPaintWindows(PWINDOW_OBJECT Window
, ULONG Flags
, BOOL Recurse
);
39 IntValidateParent(PWINDOW_OBJECT Child
, HRGN hValidateRgn
, BOOL Recurse
);
41 /* GLOBALS *******************************************************************/
43 #define MINMAX_NOSWP (0x00010000)
45 #define SWP_EX_NOCOPY 0x0001
46 #define SWP_EX_PAINTSELF 0x0002
48 #define SWP_AGG_NOGEOMETRYCHANGE \
49 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
50 #define SWP_AGG_NOPOSCHANGE \
51 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
52 #define SWP_AGG_STATUSFLAGS \
53 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
55 /* FUNCTIONS *****************************************************************/
58 IntGetClientOrigin(PWINDOW_OBJECT Window OPTIONAL
, LPPOINT Point
)
60 Window
= Window
? Window
: UserGetWindowObject(IntGetDesktopWindow());
63 Point
->x
= Point
->y
= 0;
66 Point
->x
= Window
->Wnd
->rcClient
.left
;
67 Point
->y
= Window
->Wnd
->rcClient
.top
;
76 UserGetClientOrigin(PWINDOW_OBJECT Window
, LPPOINT Point
)
84 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
88 Ret
= IntGetClientOrigin(Window
, &pt
);
92 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
96 Status
= MmCopyToCaller(Point
, &pt
, sizeof(POINT
));
97 if(!NT_SUCCESS(Status
))
99 SetLastNtError(Status
);
108 /*******************************************************************
109 * can_activate_window
111 * Check if we can activate the specified window.
114 BOOL FASTCALL
can_activate_window( PWINDOW_OBJECT Wnd OPTIONAL
)
118 if (!Wnd
) return FALSE
;
119 if (!Wnd
->Wnd
) return FALSE
;
120 style
= Wnd
->Wnd
->style
;
121 if (!(style
& WS_VISIBLE
) &&
122 Wnd
->pti
->pEThread
->ThreadsProcess
!= CsrProcess
) return FALSE
;
123 if ((style
& (WS_POPUP
|WS_CHILD
)) == WS_CHILD
) return FALSE
;
124 return !(style
& WS_DISABLED
);
128 /*******************************************************************
129 * WinPosActivateOtherWindow
131 * Activates window other than pWnd.
134 co_WinPosActivateOtherWindow(PWINDOW_OBJECT Window
)
136 PWINDOW_OBJECT WndTo
= NULL
;
138 USER_REFERENCE_ENTRY Ref
;
141 ASSERT_REFS_CO(Window
);
145 if (IntIsDesktopWindow(Window
))
147 IntSetFocusMessageQueue(NULL
);
151 /* If this is popup window, try to activate the owner first. */
152 if ((Wnd
->style
& WS_POPUP
) && (WndTo
= IntGetOwner(Window
)))
154 WndTo
= UserGetAncestor( WndTo
, GA_ROOT
);
155 if (can_activate_window(WndTo
)) goto done
;
158 /* Pick a next top-level window. */
159 /* FIXME: Search for non-tooltip windows first. */
163 if (!(WndTo
= WndTo
->spwndNext
)) break;
164 if (can_activate_window( WndTo
)) break;
169 if (WndTo
) UserRefObjectCo(WndTo
, &Ref
);
171 Fg
= UserGetForegroundWindow();
172 if ((!Fg
|| Window
->hSelf
== Fg
) && WndTo
)//fixme: ok if WndTo is NULL??
174 /* fixme: wine can pass WndTo=NULL to co_IntSetForegroundWindow. hmm */
175 if (co_IntSetForegroundWindow(WndTo
))
177 UserDerefObjectCo(WndTo
);
182 if (!co_IntSetActiveWindow(WndTo
)) /* ok for WndTo to be NULL here */
183 co_IntSetActiveWindow(0);
185 if (WndTo
) UserDerefObjectCo(WndTo
);
191 co_WinPosArrangeIconicWindows(PWINDOW_OBJECT parent
)
194 INT i
, x
, y
, xspacing
, yspacing
;
195 HWND
*List
= IntWinListChildren(parent
);
197 ASSERT_REFS_CO(parent
);
199 IntGetClientRect( parent
, &rectParent
);
201 y
= rectParent
.bottom
;
203 xspacing
= UserGetSystemMetrics(SM_CXMINSPACING
);
204 yspacing
= UserGetSystemMetrics(SM_CYMINSPACING
);
206 DPRINT("X:%d Y:%d XS:%d YS:%d\n",x
,y
,xspacing
,yspacing
);
208 for( i
= 0; List
[i
]; i
++)
210 PWINDOW_OBJECT WndChild
;
213 if (!(WndChild
= UserGetWindowObject(List
[i
])))
216 ChildWnd
= WndChild
->Wnd
;
218 if((ChildWnd
->style
& WS_MINIMIZE
) != 0 )
220 USER_REFERENCE_ENTRY Ref
;
221 UserRefObjectCo(WndChild
, &Ref
);
223 co_WinPosSetWindowPos(WndChild
, 0, x
+ UserGetSystemMetrics(SM_CXBORDER
),
224 y
- yspacing
- UserGetSystemMetrics(SM_CYBORDER
)
225 , 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
227 UserDerefObjectCo(WndChild
);
229 if (x
<= rectParent
.right
- xspacing
)
244 WinPosFindIconPos(PWINDOW_OBJECT Window
, POINT
*Pos
)
250 WinPosInitInternalPos(PWINDOW_OBJECT Window
, POINT
*pt
, RECTL
*RestoreRect
)
252 PWINDOW_OBJECT Parent
;
254 PWND Wnd
= Window
->Wnd
;
256 if (!Wnd
->InternalPosInitialized
)
259 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
260 PDESKTOP Desktop
= pti
->rpdesk
; /* Or rather get it from the window? */
262 Parent
= Window
->spwndParent
;
265 if(IntIsDesktopWindow(Parent
))
266 IntGetDesktopWorkArea(Desktop
, &WorkArea
);
268 WorkArea
= Parent
->Wnd
->rcClient
;
271 IntGetDesktopWorkArea(Desktop
, &WorkArea
);
273 Wnd
->InternalPos
.NormalRect
= Window
->Wnd
->rcWindow
;
274 IntGetWindowBorderMeasures(Window
, &XInc
, &YInc
);
275 Wnd
->InternalPos
.MaxPos
.x
= WorkArea
.left
- XInc
;
276 Wnd
->InternalPos
.MaxPos
.y
= WorkArea
.top
- YInc
;
277 Wnd
->InternalPos
.IconPos
.x
= WorkArea
.left
;
278 Wnd
->InternalPos
.IconPos
.y
= WorkArea
.bottom
- UserGetSystemMetrics(SM_CYMINIMIZED
);
280 Wnd
->InternalPosInitialized
= TRUE
;
282 if (Wnd
->style
& WS_MINIMIZE
)
284 Wnd
->InternalPos
.IconPos
= *pt
;
286 else if (Wnd
->style
& WS_MAXIMIZE
)
288 Wnd
->InternalPos
.MaxPos
= *pt
;
290 else if (RestoreRect
!= NULL
)
292 Wnd
->InternalPos
.NormalRect
= *RestoreRect
;
297 co_WinPosMinMaximize(PWINDOW_OBJECT Window
, UINT ShowFlag
, RECT
* NewPos
)
303 ASSERT_REFS_CO(Window
);
306 Size
.x
= Wnd
->rcWindow
.left
;
307 Size
.y
= Wnd
->rcWindow
.top
;
308 WinPosInitInternalPos(Window
, &Size
, &Wnd
->rcWindow
);
310 if (co_HOOK_CallHooks( WH_CBT
, HCBT_MINMAX
, (WPARAM
)Window
->hSelf
, ShowFlag
))
311 return SWP_NOSIZE
| SWP_NOMOVE
;
313 if (Wnd
->style
& WS_MINIMIZE
)
315 if (!co_IntSendMessage(Window
->hSelf
, WM_QUERYOPEN
, 0, 0))
317 return(SWP_NOSIZE
| SWP_NOMOVE
);
319 SwpFlags
|= SWP_NOCOPYBITS
;
325 if (Wnd
->style
& WS_MAXIMIZE
)
327 Window
->state
|= WINDOWOBJECT_RESTOREMAX
;
328 Wnd
->style
&= ~WS_MAXIMIZE
;
332 Window
->state
&= ~WINDOWOBJECT_RESTOREMAX
;
334 co_UserRedrawWindow(Window
, NULL
, 0, RDW_VALIDATE
| RDW_NOERASE
|
335 RDW_NOINTERNALPAINT
);
336 Wnd
->style
|= WS_MINIMIZE
;
337 WinPosFindIconPos(Window
, &Wnd
->InternalPos
.IconPos
);
338 RECTL_vSetRect(NewPos
, Wnd
->InternalPos
.IconPos
.x
, Wnd
->InternalPos
.IconPos
.y
,
339 UserGetSystemMetrics(SM_CXMINIMIZED
),
340 UserGetSystemMetrics(SM_CYMINIMIZED
));
341 SwpFlags
|= SWP_NOCOPYBITS
;
347 co_WinPosGetMinMaxInfo(Window
, &Size
, &Wnd
->InternalPos
.MaxPos
,
349 DPRINT("Maximize: %d,%d %dx%d\n",
350 Wnd
->InternalPos
.MaxPos
.x
, Wnd
->InternalPos
.MaxPos
.y
, Size
.x
, Size
.y
);
351 if (Wnd
->style
& WS_MINIMIZE
)
353 Wnd
->style
&= ~WS_MINIMIZE
;
355 Wnd
->style
|= WS_MAXIMIZE
;
356 RECTL_vSetRect(NewPos
, Wnd
->InternalPos
.MaxPos
.x
, Wnd
->InternalPos
.MaxPos
.y
,
363 if (Wnd
->style
& WS_MINIMIZE
)
365 Wnd
->style
&= ~WS_MINIMIZE
;
366 if (Window
->state
& WINDOWOBJECT_RESTOREMAX
)
368 co_WinPosGetMinMaxInfo(Window
, &Size
,
369 &Wnd
->InternalPos
.MaxPos
, NULL
, NULL
);
370 Wnd
->style
|= WS_MAXIMIZE
;
371 RECTL_vSetRect(NewPos
, Wnd
->InternalPos
.MaxPos
.x
,
372 Wnd
->InternalPos
.MaxPos
.y
, Size
.x
, Size
.y
);
377 *NewPos
= Wnd
->InternalPos
.NormalRect
;
378 NewPos
->right
-= NewPos
->left
;
379 NewPos
->bottom
-= NewPos
->top
;
385 if (!(Wnd
->style
& WS_MAXIMIZE
))
389 Wnd
->style
&= ~WS_MAXIMIZE
;
390 *NewPos
= Wnd
->InternalPos
.NormalRect
;
391 NewPos
->right
-= NewPos
->left
;
392 NewPos
->bottom
-= NewPos
->top
;
403 WinPosFillMinMaxInfoStruct(PWINDOW_OBJECT Window
, MINMAXINFO
*Info
)
407 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
408 PDESKTOP Desktop
= pti
->rpdesk
; /* Or rather get it from the window? */
410 IntGetDesktopWorkArea(Desktop
, &WorkArea
);
412 /* Get default values. */
413 Info
->ptMinTrackSize
.x
= UserGetSystemMetrics(SM_CXMINTRACK
);
414 Info
->ptMinTrackSize
.y
= UserGetSystemMetrics(SM_CYMINTRACK
);
416 IntGetWindowBorderMeasures(Window
, &XInc
, &YInc
);
417 Info
->ptMaxSize
.x
= WorkArea
.right
- WorkArea
.left
+ 2 * XInc
;
418 Info
->ptMaxSize
.y
= WorkArea
.bottom
- WorkArea
.top
+ 2 * YInc
;
419 Info
->ptMaxTrackSize
.x
= Info
->ptMaxSize
.x
;
420 Info
->ptMaxTrackSize
.y
= Info
->ptMaxSize
.y
;
422 if (Window
->Wnd
->InternalPosInitialized
)
424 Info
->ptMaxPosition
= Window
->Wnd
->InternalPos
.MaxPos
;
428 Info
->ptMaxPosition
.x
= WorkArea
.left
- XInc
;
429 Info
->ptMaxPosition
.y
= WorkArea
.top
- YInc
;
434 co_WinPosGetMinMaxInfo(PWINDOW_OBJECT Window
, POINT
* MaxSize
, POINT
* MaxPos
,
435 POINT
* MinTrack
, POINT
* MaxTrack
)
439 ASSERT_REFS_CO(Window
);
441 WinPosFillMinMaxInfoStruct(Window
, &MinMax
);
443 co_IntSendMessage(Window
->hSelf
, WM_GETMINMAXINFO
, 0, (LPARAM
)&MinMax
);
445 MinMax
.ptMaxTrackSize
.x
= max(MinMax
.ptMaxTrackSize
.x
,
446 MinMax
.ptMinTrackSize
.x
);
447 MinMax
.ptMaxTrackSize
.y
= max(MinMax
.ptMaxTrackSize
.y
,
448 MinMax
.ptMinTrackSize
.y
);
451 *MaxSize
= MinMax
.ptMaxSize
;
453 *MaxPos
= MinMax
.ptMaxPosition
;
455 *MinTrack
= MinMax
.ptMinTrackSize
;
457 *MaxTrack
= MinMax
.ptMaxTrackSize
;
459 return 0; //FIXME: what does it return?
464 FixClientRect(PRECTL ClientRect
, PRECTL WindowRect
)
466 if (ClientRect
->left
< WindowRect
->left
)
468 ClientRect
->left
= WindowRect
->left
;
470 else if (WindowRect
->right
< ClientRect
->left
)
472 ClientRect
->left
= WindowRect
->right
;
474 if (ClientRect
->right
< WindowRect
->left
)
476 ClientRect
->right
= WindowRect
->left
;
478 else if (WindowRect
->right
< ClientRect
->right
)
480 ClientRect
->right
= WindowRect
->right
;
482 if (ClientRect
->top
< WindowRect
->top
)
484 ClientRect
->top
= WindowRect
->top
;
486 else if (WindowRect
->bottom
< ClientRect
->top
)
488 ClientRect
->top
= WindowRect
->bottom
;
490 if (ClientRect
->bottom
< WindowRect
->top
)
492 ClientRect
->bottom
= WindowRect
->top
;
494 else if (WindowRect
->bottom
< ClientRect
->bottom
)
496 ClientRect
->bottom
= WindowRect
->bottom
;
502 co_WinPosDoNCCALCSize(PWINDOW_OBJECT Window
, PWINDOWPOS WinPos
,
503 RECT
* WindowRect
, RECT
* ClientRect
)
505 PWINDOW_OBJECT Parent
;
509 ASSERT_REFS_CO(Window
);
512 /* Send WM_NCCALCSIZE message to get new client area */
513 if ((WinPos
->flags
& (SWP_FRAMECHANGED
| SWP_NOSIZE
)) != SWP_NOSIZE
)
515 NCCALCSIZE_PARAMS params
;
516 WINDOWPOS winposCopy
;
518 params
.rgrc
[0] = *WindowRect
;
519 params
.rgrc
[1] = Window
->Wnd
->rcWindow
;
520 params
.rgrc
[2] = Window
->Wnd
->rcClient
;
521 Parent
= Window
->spwndParent
;
522 if (0 != (Wnd
->style
& WS_CHILD
) && Parent
)
524 RECTL_vOffsetRect(&(params
.rgrc
[0]), - Parent
->Wnd
->rcClient
.left
,
525 - Parent
->Wnd
->rcClient
.top
);
526 RECTL_vOffsetRect(&(params
.rgrc
[1]), - Parent
->Wnd
->rcClient
.left
,
527 - Parent
->Wnd
->rcClient
.top
);
528 RECTL_vOffsetRect(&(params
.rgrc
[2]), - Parent
->Wnd
->rcClient
.left
,
529 - Parent
->Wnd
->rcClient
.top
);
531 params
.lppos
= &winposCopy
;
532 winposCopy
= *WinPos
;
534 wvrFlags
= co_IntSendMessage(Window
->hSelf
, WM_NCCALCSIZE
, TRUE
, (LPARAM
) ¶ms
);
536 /* If the application send back garbage, ignore it */
537 if (params
.rgrc
[0].left
<= params
.rgrc
[0].right
&&
538 params
.rgrc
[0].top
<= params
.rgrc
[0].bottom
)
540 *ClientRect
= params
.rgrc
[0];
541 if ((Wnd
->style
& WS_CHILD
) && Parent
)
543 RECTL_vOffsetRect(ClientRect
, Parent
->Wnd
->rcClient
.left
,
544 Parent
->Wnd
->rcClient
.top
);
546 FixClientRect(ClientRect
, WindowRect
);
549 /* FIXME: WVR_ALIGNxxx */
551 if (ClientRect
->left
!= Wnd
->rcClient
.left
||
552 ClientRect
->top
!= Wnd
->rcClient
.top
)
554 WinPos
->flags
&= ~SWP_NOCLIENTMOVE
;
557 if ((ClientRect
->right
- ClientRect
->left
!=
558 Wnd
->rcClient
.right
- Wnd
->rcClient
.left
) ||
559 (ClientRect
->bottom
- ClientRect
->top
!=
560 Wnd
->rcClient
.bottom
- Wnd
->rcClient
.top
))
562 WinPos
->flags
&= ~SWP_NOCLIENTSIZE
;
567 if (! (WinPos
->flags
& SWP_NOMOVE
)
568 && (ClientRect
->left
!= Wnd
->rcClient
.left
||
569 ClientRect
->top
!= Wnd
->rcClient
.top
))
571 WinPos
->flags
&= ~SWP_NOCLIENTMOVE
;
580 co_WinPosDoWinPosChanging(PWINDOW_OBJECT Window
,
588 ASSERT_REFS_CO(Window
);
591 if (!(WinPos
->flags
& SWP_NOSENDCHANGING
))
593 co_IntPostOrSendMessage(Window
->hSelf
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
) WinPos
);
596 *WindowRect
= Wnd
->rcWindow
;
597 *ClientRect
= Wnd
->rcClient
;
599 if (!(WinPos
->flags
& SWP_NOSIZE
))
601 WindowRect
->right
= WindowRect
->left
+ WinPos
->cx
;
602 WindowRect
->bottom
= WindowRect
->top
+ WinPos
->cy
;
605 if (!(WinPos
->flags
& SWP_NOMOVE
))
607 PWINDOW_OBJECT Parent
;
610 Parent
= Window
->spwndParent
;
611 if ((0 != (Wnd
->style
& WS_CHILD
)) && Parent
)
613 X
+= Parent
->Wnd
->rcClient
.left
;
614 Y
+= Parent
->Wnd
->rcClient
.top
;
617 WindowRect
->left
= X
;
619 WindowRect
->right
+= X
- Wnd
->rcWindow
.left
;
620 WindowRect
->bottom
+= Y
- Wnd
->rcWindow
.top
;
621 RECTL_vOffsetRect(ClientRect
,
622 X
- Wnd
->rcWindow
.left
,
623 Y
- Wnd
->rcWindow
.top
);
626 WinPos
->flags
|= SWP_NOCLIENTMOVE
| SWP_NOCLIENTSIZE
;
632 * Fix Z order taking into account owned popups -
633 * basically we need to maintain them above the window that owns them
637 WinPosDoOwnedPopups(HWND hWnd
, HWND hWndInsertAfter
)
640 HWND Owner
= UserGetWindow(hWnd
, GW_OWNER
);
641 LONG Style
= UserGetWindowLong(hWnd
, GWL_STYLE
, FALSE
);
642 PWINDOW_OBJECT DesktopWindow
, ChildObject
;
645 if ((Style
& WS_POPUP
) && Owner
)
647 /* Make sure this popup stays above the owner */
648 HWND hWndLocalPrev
= HWND_TOPMOST
;
650 if (hWndInsertAfter
!= HWND_TOPMOST
)
652 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
653 List
= IntWinListChildren(DesktopWindow
);
657 for (i
= 0; List
[i
]; i
++)
659 if (List
[i
] == Owner
)
661 if (HWND_TOP
== hWndInsertAfter
)
663 ChildObject
= UserGetWindowObject(List
[i
]);
664 if (NULL
!= ChildObject
)
666 if (0 == (ChildObject
->Wnd
->ExStyle
& WS_EX_TOPMOST
))
673 hWndLocalPrev
= List
[i
];
674 if (hWndLocalPrev
== hWndInsertAfter
)
677 hWndInsertAfter
= hWndLocalPrev
;
681 else if (Style
& WS_CHILD
)
683 return hWndInsertAfter
;
688 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
689 List
= IntWinListChildren(DesktopWindow
);
693 for (i
= 0; List
[i
]; i
++)
700 if (!(Wnd
= UserGetWindowObject(List
[i
])))
703 if ((Wnd
->Wnd
->style
& WS_POPUP
) &&
704 UserGetWindow(List
[i
], GW_OWNER
) == hWnd
)
706 USER_REFERENCE_ENTRY Ref
;
707 UserRefObjectCo(Wnd
, &Ref
);
709 co_WinPosSetWindowPos(Wnd
, hWndInsertAfter
, 0, 0, 0, 0,
710 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOSENDCHANGING
);
712 UserDerefObjectCo(Wnd
);
714 hWndInsertAfter
= List
[i
];
720 return hWndInsertAfter
;
723 /***********************************************************************
724 * WinPosInternalMoveWindow
726 * Update WindowRect and ClientRect of Window and all of its children
727 * We keep both WindowRect and ClientRect in screen coordinates internally
731 WinPosInternalMoveWindow(PWINDOW_OBJECT Window
, INT MoveX
, INT MoveY
)
733 PWINDOW_OBJECT Child
;
735 ASSERT(Window
!= Window
->spwndChild
);
737 Window
->Wnd
->rcWindow
.left
+= MoveX
;
738 Window
->Wnd
->rcWindow
.right
+= MoveX
;
739 Window
->Wnd
->rcWindow
.top
+= MoveY
;
740 Window
->Wnd
->rcWindow
.bottom
+= MoveY
;
742 Window
->Wnd
->rcClient
.left
+= MoveX
;
743 Window
->Wnd
->rcClient
.right
+= MoveX
;
744 Window
->Wnd
->rcClient
.top
+= MoveY
;
745 Window
->Wnd
->rcClient
.bottom
+= MoveY
;
747 for(Child
= Window
->spwndChild
; Child
; Child
= Child
->spwndNext
)
749 WinPosInternalMoveWindow(Child
, MoveX
, MoveY
);
754 * WinPosFixupSWPFlags
756 * Fix redundant flags and values in the WINDOWPOS structure.
760 WinPosFixupFlags(WINDOWPOS
*WinPos
, PWINDOW_OBJECT Window
)
762 PWND Wnd
= Window
->Wnd
;
764 if (!Wnd
) return FALSE
;
766 if (Wnd
->style
& WS_VISIBLE
)
768 WinPos
->flags
&= ~SWP_SHOWWINDOW
;
772 WinPos
->flags
&= ~SWP_HIDEWINDOW
;
773 if (!(WinPos
->flags
& SWP_SHOWWINDOW
))
774 WinPos
->flags
|= SWP_NOREDRAW
;
777 WinPos
->cx
= max(WinPos
->cx
, 0);
778 WinPos
->cy
= max(WinPos
->cy
, 0);
780 /* Check for right size */
781 if (Wnd
->rcWindow
.right
- Wnd
->rcWindow
.left
== WinPos
->cx
&&
782 Wnd
->rcWindow
.bottom
- Wnd
->rcWindow
.top
== WinPos
->cy
)
784 WinPos
->flags
|= SWP_NOSIZE
;
787 /* Check for right position */
788 if (Wnd
->rcWindow
.left
== WinPos
->x
&&
789 Wnd
->rcWindow
.top
== WinPos
->y
)
791 WinPos
->flags
|= SWP_NOMOVE
;
794 if (WinPos
->hwnd
== UserGetForegroundWindow())
796 WinPos
->flags
|= SWP_NOACTIVATE
; /* Already active */
799 if ((Wnd
->style
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)
801 /* Bring to the top when activating */
802 if (!(WinPos
->flags
& SWP_NOACTIVATE
))
804 WinPos
->flags
&= ~SWP_NOZORDER
;
805 WinPos
->hwndInsertAfter
= (0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
) ?
806 HWND_TOPMOST
: HWND_TOP
);
811 /* Check hwndInsertAfter */
812 if (!(WinPos
->flags
& SWP_NOZORDER
))
814 /* Fix sign extension */
815 if (WinPos
->hwndInsertAfter
== (HWND
)0xffff)
817 WinPos
->hwndInsertAfter
= HWND_TOPMOST
;
819 else if (WinPos
->hwndInsertAfter
== (HWND
)0xfffe)
821 WinPos
->hwndInsertAfter
= HWND_NOTOPMOST
;
824 if (WinPos
->hwndInsertAfter
== HWND_NOTOPMOST
)
826 WinPos
->hwndInsertAfter
= HWND_TOP
;
828 else if (HWND_TOP
== WinPos
->hwndInsertAfter
829 && 0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
))
831 /* Keep it topmost when it's already topmost */
832 WinPos
->hwndInsertAfter
= HWND_TOPMOST
;
835 /* hwndInsertAfter must be a sibling of the window */
836 if (HWND_TOPMOST
!= WinPos
->hwndInsertAfter
837 && HWND_TOP
!= WinPos
->hwndInsertAfter
838 && HWND_NOTOPMOST
!= WinPos
->hwndInsertAfter
839 && HWND_BOTTOM
!= WinPos
->hwndInsertAfter
)
841 PWINDOW_OBJECT InsAfterWnd
, Parent
= Window
->spwndParent
;
843 InsAfterWnd
= UserGetWindowObject(WinPos
->hwndInsertAfter
);
845 if (InsAfterWnd
&& UserGetAncestor(InsAfterWnd
, GA_PARENT
) != Parent
)
852 * We don't need to change the Z order of hwnd if it's already
853 * inserted after hwndInsertAfter or when inserting hwnd after
856 if ((WinPos
->hwnd
== WinPos
->hwndInsertAfter
) ||
857 (WinPos
->hwnd
== UserGetWindow(WinPos
->hwndInsertAfter
, GW_HWNDNEXT
)))
859 WinPos
->flags
|= SWP_NOZORDER
;
868 /* x and y are always screen relative */
870 co_WinPosSetWindowPos(
871 PWINDOW_OBJECT Window
,
884 HRGN VisBefore
= NULL
;
885 HRGN VisAfter
= NULL
;
886 HRGN DirtyRgn
= NULL
;
887 HRGN ExposedRgn
= NULL
;
890 RECTL OldWindowRect
, OldClientRect
;
895 PWINDOW_OBJECT Ancestor
;
897 ASSERT_REFS_CO(Window
);
899 if (!Window
->Wnd
) return FALSE
;
901 /* FIXME: Get current active window from active queue. */
904 * Only allow CSRSS to mess with the desktop window
906 if ( Window
->hSelf
== IntGetDesktopWindow() &&
907 Window
->pti
->pEThread
->ThreadsProcess
!= PsGetCurrentProcess())
912 WinPos
.hwnd
= Window
->hSelf
;
913 WinPos
.hwndInsertAfter
= WndInsertAfter
;
918 WinPos
.flags
= flags
;
920 co_WinPosDoWinPosChanging(Window
, &WinPos
, &NewWindowRect
, &NewClientRect
);
922 /* Fix up the flags. */
923 if (!WinPosFixupFlags(&WinPos
, Window
))
925 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
929 /* Does the window still exist? */
930 if (!IntIsWindow(WinPos
.hwnd
))
932 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
936 Ancestor
= UserGetAncestor(Window
, GA_PARENT
);
937 if ( (WinPos
.flags
& (SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) !=
939 Ancestor
&& Ancestor
->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
&&
956 (VisRgn
= (PROSRGNDATA
)RGNOBJAPI_Lock(VisBefore
, NULL
)) &&
957 REGION_GetRgnBox(VisRgn
, &TempRect
) == NULLREGION
)
959 RGNOBJAPI_Unlock(VisRgn
);
960 GreDeleteObject(VisBefore
);
965 RGNOBJAPI_Unlock(VisRgn
);
966 NtGdiOffsetRgn(VisBefore
, -Window
->Wnd
->rcWindow
.left
, -Window
->Wnd
->rcWindow
.top
);
971 WvrFlags
= co_WinPosDoNCCALCSize(Window
, &WinPos
, &NewWindowRect
, &NewClientRect
);
973 //DPRINT1("co_WinPosDoNCCALCSize");
975 /* Relink windows. (also take into account shell window in hwndShellWindow) */
976 if (!(WinPos
.flags
& SWP_NOZORDER
) && WinPos
.hwnd
!= UserGetShellWindow())
978 PWINDOW_OBJECT ParentWindow
;
979 PWINDOW_OBJECT Sibling
;
980 PWINDOW_OBJECT InsertAfterWindow
;
982 if ((ParentWindow
= Window
->spwndParent
))
984 if (HWND_TOPMOST
== WinPos
.hwndInsertAfter
)
986 InsertAfterWindow
= NULL
;
988 else if (HWND_TOP
== WinPos
.hwndInsertAfter
989 || HWND_NOTOPMOST
== WinPos
.hwndInsertAfter
)
991 InsertAfterWindow
= NULL
;
992 Sibling
= ParentWindow
->spwndChild
;
993 while ( NULL
!= Sibling
&&
994 0 != (Sibling
->Wnd
->ExStyle
& WS_EX_TOPMOST
) )
996 InsertAfterWindow
= Sibling
;
997 Sibling
= Sibling
->spwndNext
;
999 if (NULL
!= InsertAfterWindow
)
1001 UserReferenceObject(InsertAfterWindow
);
1004 else if (WinPos
.hwndInsertAfter
== HWND_BOTTOM
)
1006 if(ParentWindow
->spwndChild
)
1008 InsertAfterWindow
= ParentWindow
->spwndChild
;
1010 if(InsertAfterWindow
)
1012 while (InsertAfterWindow
->spwndNext
)
1013 InsertAfterWindow
= InsertAfterWindow
->spwndNext
;
1016 UserReferenceObject(InsertAfterWindow
);
1019 InsertAfterWindow
= NULL
;
1022 InsertAfterWindow
= IntGetWindowObject(WinPos
.hwndInsertAfter
);
1023 /* Do nothing if hwndInsertAfter is HWND_BOTTOM and Window is already
1025 if (InsertAfterWindow
!= Window
)
1027 IntUnlinkWindow(Window
);
1028 IntLinkWindow(Window
, ParentWindow
, InsertAfterWindow
);
1030 if (InsertAfterWindow
!= NULL
)
1031 UserDereferenceObject(InsertAfterWindow
);
1033 if ( (HWND_TOPMOST
== WinPos
.hwndInsertAfter
) ||
1034 (0 != (Window
->Wnd
->ExStyle
& WS_EX_TOPMOST
) &&
1035 NULL
!= Window
->spwndPrev
&&
1036 0 != (Window
->spwndPrev
->Wnd
->ExStyle
& WS_EX_TOPMOST
)) ||
1037 (NULL
!= Window
->spwndNext
&&
1038 0 != (Window
->spwndNext
->Wnd
->ExStyle
& WS_EX_TOPMOST
)) )
1040 Window
->Wnd
->ExStyle
|= WS_EX_TOPMOST
;
1044 Window
->Wnd
->ExStyle
&= ~ WS_EX_TOPMOST
;
1050 if (!Window
->Wnd
) return FALSE
;
1052 OldWindowRect
= Window
->Wnd
->rcWindow
;
1053 OldClientRect
= Window
->Wnd
->rcClient
;
1055 if (OldClientRect
.bottom
- OldClientRect
.top
==
1056 NewClientRect
.bottom
- NewClientRect
.top
)
1058 WvrFlags
&= ~WVR_VREDRAW
;
1061 if (OldClientRect
.right
- OldClientRect
.left
==
1062 NewClientRect
.right
- NewClientRect
.left
)
1064 WvrFlags
&= ~WVR_HREDRAW
;
1067 /* FIXME: Actually do something with WVR_VALIDRECTS */
1069 if ( NewClientRect
.left
!= OldClientRect
.left
||
1070 NewClientRect
.top
!= OldClientRect
.top
)
1072 WinPosInternalMoveWindow(Window
,
1073 NewClientRect
.left
- OldClientRect
.left
,
1074 NewClientRect
.top
- OldClientRect
.top
);
1077 Window
->Wnd
->rcWindow
= NewWindowRect
;
1078 Window
->Wnd
->rcClient
= NewClientRect
;
1080 if (!(WinPos
.flags
& SWP_SHOWWINDOW
) && (WinPos
.flags
& SWP_HIDEWINDOW
))
1082 /* Clear the update region */
1083 co_UserRedrawWindow( Window
,
1086 RDW_VALIDATE
| RDW_NOFRAME
| RDW_NOERASE
| RDW_NOINTERNALPAINT
| RDW_ALLCHILDREN
);
1088 if ((Window
->Wnd
->style
& WS_VISIBLE
) &&
1089 Window
->spwndParent
== UserGetDesktopWindow())
1091 co_IntShellHookNotify(HSHELL_WINDOWDESTROYED
, (LPARAM
)Window
->hSelf
);
1093 Window
->Wnd
->style
&= ~WS_VISIBLE
;
1095 else if (WinPos
.flags
& SWP_SHOWWINDOW
)
1097 if (!(Window
->Wnd
->style
& WS_VISIBLE
) &&
1098 Window
->spwndParent
== UserGetDesktopWindow() )
1100 co_IntShellHookNotify(HSHELL_WINDOWCREATED
, (LPARAM
)Window
->hSelf
);
1102 Window
->Wnd
->style
|= WS_VISIBLE
;
1105 if (Window
->hrgnUpdate
!= NULL
&& Window
->hrgnUpdate
!= (HRGN
)1)
1107 NtGdiOffsetRgn(Window
->hrgnUpdate
,
1108 NewWindowRect
.left
- OldWindowRect
.left
,
1109 NewWindowRect
.top
- OldWindowRect
.top
);
1112 DceResetActiveDCEs(Window
);
1114 if (!(WinPos
.flags
& SWP_NOREDRAW
))
1116 /* Determine the new visible region */
1117 VisAfter
= VIS_ComputeVisibleRegion(Window
, FALSE
, FALSE
, TRUE
);
1120 if ( VisAfter
!= NULL
&&
1121 (VisRgn
= (PROSRGNDATA
)RGNOBJAPI_Lock(VisAfter
, NULL
)) &&
1122 REGION_GetRgnBox(VisRgn
, &TempRect
) == NULLREGION
)
1124 RGNOBJAPI_Unlock(VisRgn
);
1125 GreDeleteObject(VisAfter
);
1130 RGNOBJAPI_Unlock(VisRgn
);
1131 NtGdiOffsetRgn(VisAfter
, -Window
->Wnd
->rcWindow
.left
, -Window
->Wnd
->rcWindow
.top
);
1135 * Determine which pixels can be copied from the old window position
1136 * to the new. Those pixels must be visible in both the old and new
1137 * position. Also, check the class style to see if the windows of this
1138 * class need to be completely repainted on (horizontal/vertical) size
1141 if ( VisBefore
!= NULL
&&
1143 !(WinPos
.flags
& SWP_NOCOPYBITS
) &&
1144 ((WinPos
.flags
& SWP_NOSIZE
) || !(WvrFlags
& WVR_REDRAW
)) &&
1145 !(Window
->Wnd
->ExStyle
& WS_EX_TRANSPARENT
) )
1147 CopyRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
1148 RgnType
= NtGdiCombineRgn(CopyRgn
, VisAfter
, VisBefore
, RGN_AND
);
1151 * If this is (also) a window resize, the whole nonclient area
1152 * needs to be repainted. So we limit the copy to the client area,
1153 * 'cause there is no use in copying it (would possibly cause
1154 * "flashing" too). However, if the copy region is already empty,
1155 * we don't have to crop (can't take anything away from an empty
1158 if (!(WinPos
.flags
& SWP_NOSIZE
) &&
1160 RgnType
!= NULLREGION
)
1162 PROSRGNDATA pCopyRgn
;
1163 RECTL ORect
= OldClientRect
;
1164 RECTL NRect
= NewClientRect
;
1165 RECTL_vOffsetRect(&ORect
, - OldWindowRect
.left
, - OldWindowRect
.top
);
1166 RECTL_vOffsetRect(&NRect
, - NewWindowRect
.left
, - NewWindowRect
.top
);
1167 RECTL_bIntersectRect(&CopyRect
, &ORect
, &NRect
);
1168 pCopyRgn
= RGNOBJAPI_Lock(CopyRgn
, NULL
);
1169 REGION_CropAndOffsetRegion(pCopyRgn
, pCopyRgn
, &CopyRect
, NULL
);
1170 RGNOBJAPI_Unlock(pCopyRgn
);
1173 /* No use in copying bits which are in the update region. */
1174 if (Window
->hrgnUpdate
!= NULL
)
1176 NtGdiOffsetRgn(CopyRgn
, NewWindowRect
.left
, NewWindowRect
.top
);
1177 NtGdiCombineRgn(CopyRgn
, CopyRgn
, Window
->hrgnUpdate
, RGN_DIFF
);
1178 NtGdiOffsetRgn(CopyRgn
, -NewWindowRect
.left
, -NewWindowRect
.top
);
1182 * Now, get the bounding box of the copy region. If it's empty
1183 * there's nothing to copy. Also, it's no use copying bits onto
1186 if ( (VisRgn
= (PROSRGNDATA
)RGNOBJAPI_Lock(CopyRgn
, NULL
)) &&
1187 REGION_GetRgnBox(VisRgn
, &CopyRect
) == NULLREGION
)
1189 /* Nothing to copy, clean up */
1190 RGNOBJAPI_Unlock(VisRgn
);
1191 REGION_FreeRgnByHandle(CopyRgn
);
1194 else if (OldWindowRect
.left
!= NewWindowRect
.left
||
1195 OldWindowRect
.top
!= NewWindowRect
.top
)
1199 RGNOBJAPI_Unlock(VisRgn
);
1203 * Small trick here: there is no function to bitblt a region. So
1204 * we set the region as the clipping region, take the bounding box
1205 * of the region and bitblt that. Since nothing outside the clipping
1206 * region is copied, this has the effect of bitblt'ing the region.
1208 * Since NtUserGetDCEx takes ownership of the clip region, we need
1209 * to create a copy of CopyRgn and pass that. We need CopyRgn later
1211 NtGdiOffsetRgn(CopyRgn
, NewWindowRect
.left
, NewWindowRect
.top
);
1212 Dc
= UserGetDCEx( Window
,
1214 DCX_WINDOW
|DCX_CACHE
|DCX_INTERSECTRGN
|DCX_CLIPSIBLINGS
|DCX_KEEPCLIPRGN
);
1216 CopyRect
.left
, CopyRect
.top
,
1217 CopyRect
.right
- CopyRect
.left
,
1218 CopyRect
.bottom
- CopyRect
.top
,
1220 CopyRect
.left
+ (OldWindowRect
.left
- NewWindowRect
.left
),
1221 CopyRect
.top
+ (OldWindowRect
.top
- NewWindowRect
.top
),
1226 UserReleaseDC(Window
, Dc
, FALSE
);
1227 IntValidateParent(Window
, CopyRgn
, FALSE
);
1228 NtGdiOffsetRgn(CopyRgn
, -NewWindowRect
.left
, -NewWindowRect
.top
);
1232 RGNOBJAPI_Unlock(VisRgn
);
1240 /* We need to redraw what wasn't visible before */
1241 if (VisAfter
!= NULL
)
1243 DirtyRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
1244 if (CopyRgn
!= NULL
)
1246 RgnType
= NtGdiCombineRgn(DirtyRgn
, VisAfter
, CopyRgn
, RGN_DIFF
);
1250 RgnType
= NtGdiCombineRgn(DirtyRgn
, VisAfter
, 0, RGN_COPY
);
1252 if (RgnType
!= ERROR
&& RgnType
!= NULLREGION
)
1255 NtGdiOffsetRgn(DirtyRgn, Window->rcWindow.left, Window->rcWindow.top);
1256 IntInvalidateWindows( Window,
1258 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
1260 GreDeleteObject(DirtyRgn);
1263 PWINDOW_OBJECT Parent
= Window
->spwndParent
;
1265 NtGdiOffsetRgn( DirtyRgn
,
1266 Window
->Wnd
->rcWindow
.left
,
1267 Window
->Wnd
->rcWindow
.top
);
1268 if ( (Window
->Wnd
->style
& WS_CHILD
) &&
1270 !(Parent
->Wnd
->style
& WS_CLIPCHILDREN
))
1272 IntInvalidateWindows( Parent
,
1274 RDW_ERASE
| RDW_INVALIDATE
);
1275 co_IntPaintWindows(Parent
, RDW_ERASENOW
, FALSE
);
1279 IntInvalidateWindows( Window
,
1281 RDW_ERASE
| RDW_FRAME
| RDW_INVALIDATE
| RDW_ALLCHILDREN
);
1284 REGION_FreeRgnByHandle(DirtyRgn
);
1287 if (CopyRgn
!= NULL
)
1289 REGION_FreeRgnByHandle(CopyRgn
);
1292 /* Expose what was covered before but not covered anymore */
1293 if (VisBefore
!= NULL
)
1295 ExposedRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
1296 NtGdiCombineRgn(ExposedRgn
, VisBefore
, NULL
, RGN_COPY
);
1297 NtGdiOffsetRgn( ExposedRgn
,
1298 OldWindowRect
.left
- NewWindowRect
.left
,
1299 OldWindowRect
.top
- NewWindowRect
.top
);
1301 if (VisAfter
!= NULL
)
1302 RgnType
= NtGdiCombineRgn(ExposedRgn
, ExposedRgn
, VisAfter
, RGN_DIFF
);
1304 RgnType
= SIMPLEREGION
;
1306 if (RgnType
!= ERROR
&& RgnType
!= NULLREGION
)
1308 co_VIS_WindowLayoutChanged(Window
, ExposedRgn
);
1310 REGION_FreeRgnByHandle(ExposedRgn
);
1311 REGION_FreeRgnByHandle(VisBefore
);
1314 if (VisAfter
!= NULL
)
1316 REGION_FreeRgnByHandle(VisAfter
);
1319 if (!(WinPos
.flags
& SWP_NOACTIVATE
))
1321 if ((Window
->Wnd
->style
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1323 co_IntSendMessage(WinPos
.hwnd
, WM_CHILDACTIVATE
, 0, 0);
1327 co_IntSetForegroundWindow(Window
);
1332 if ((WinPos
.flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOPOSCHANGE
)
1333 co_IntPostOrSendMessage(WinPos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
) &WinPos
);
1339 co_WinPosGetNonClientSize(PWINDOW_OBJECT Window
, RECT
* WindowRect
, RECT
* ClientRect
)
1343 ASSERT_REFS_CO(Window
);
1345 *ClientRect
= *WindowRect
;
1346 Result
= co_IntSendMessage(Window
->hSelf
, WM_NCCALCSIZE
, FALSE
, (LPARAM
) ClientRect
);
1348 FixClientRect(ClientRect
, WindowRect
);
1354 co_WinPosShowWindow(PWINDOW_OBJECT Window
, INT Cmd
)
1363 ASSERT_REFS_CO(Window
);
1366 if (!Wnd
) return FALSE
;
1368 WasVisible
= (Wnd
->style
& WS_VISIBLE
) != 0;
1378 Swp
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
1379 if (Window
->hSelf
!= UserGetActiveWindow())
1380 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1384 case SW_SHOWMINNOACTIVE
:
1385 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1387 case SW_SHOWMINIMIZED
:
1388 Swp
|= SWP_SHOWWINDOW
;
1392 Swp
|= SWP_NOACTIVATE
;
1393 if (!(Wnd
->style
& WS_MINIMIZE
))
1395 Swp
|= co_WinPosMinMaximize(Window
, SW_MINIMIZE
, &NewPos
) |
1400 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1403 Swp
|= SWP_FRAMECHANGED
;
1409 case SW_SHOWMAXIMIZED
:
1411 Swp
|= SWP_SHOWWINDOW
;
1412 if (!(Wnd
->style
& WS_MAXIMIZE
))
1414 Swp
|= co_WinPosMinMaximize(Window
, SW_MAXIMIZE
, &NewPos
) |
1419 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1422 Swp
|= SWP_FRAMECHANGED
;
1429 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1432 if (WasVisible
) return(TRUE
); // Nothing to do!
1433 Swp
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
1434 /* Don't activate the topmost window. */
1437 case SW_SHOWNOACTIVATE
:
1438 //Swp |= SWP_NOZORDER;
1439 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1442 case SW_SHOWDEFAULT
:
1444 Swp
|= SWP_SHOWWINDOW
;
1445 if (Wnd
->style
& (WS_MINIMIZE
| WS_MAXIMIZE
))
1447 Swp
|= co_WinPosMinMaximize(Window
, SW_RESTORE
, &NewPos
) |
1452 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1455 Swp
|= SWP_FRAMECHANGED
;
1461 ShowFlag
= (Cmd
!= SW_HIDE
);
1463 if (ShowFlag
!= WasVisible
)
1465 co_IntSendMessage(Window
->hSelf
, WM_SHOWWINDOW
, ShowFlag
, 0);
1468 /* We can't activate a child window */
1469 if ((Wnd
->style
& WS_CHILD
) &&
1470 !(Wnd
->ExStyle
& WS_EX_MDICHILD
))
1472 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1475 co_WinPosSetWindowPos(Window
, 0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
)
1476 ? HWND_TOPMOST
: HWND_TOP
,
1477 NewPos
.left
, NewPos
.top
, NewPos
.right
, NewPos
.bottom
, LOWORD(Swp
));
1481 PWINDOW_OBJECT ThreadFocusWindow
;
1483 /* FIXME: This will cause the window to be activated irrespective
1484 * of whether it is owned by the same thread. Has to be done
1488 if (Window
->hSelf
== UserGetActiveWindow())
1490 co_WinPosActivateOtherWindow(Window
);
1495 ThreadFocusWindow
= UserGetWindowObject(IntGetThreadFocusWindow());
1497 /* Revert focus to parent */
1498 if (ThreadFocusWindow
&& (Window
== ThreadFocusWindow
||
1499 IntIsChildWindow(Window
, ThreadFocusWindow
)))
1501 //faxme: as long as we have ref on Window, we also, indirectly, have ref on parent...
1502 co_UserSetFocus(Window
->spwndParent
);
1506 /* FIXME: Check for window destruction. */
1508 if ((Window
->state
& WINDOWOBJECT_NEED_SIZE
) &&
1509 !(Window
->state
& WINDOWSTATUS_DESTROYING
))
1511 WPARAM wParam
= SIZE_RESTORED
;
1513 Window
->state
&= ~WINDOWOBJECT_NEED_SIZE
;
1514 if (Wnd
->style
& WS_MAXIMIZE
)
1516 wParam
= SIZE_MAXIMIZED
;
1518 else if (Wnd
->style
& WS_MINIMIZE
)
1520 wParam
= SIZE_MINIMIZED
;
1523 co_IntSendMessage(Window
->hSelf
, WM_SIZE
, wParam
,
1524 MAKELONG(Wnd
->rcClient
.right
-
1526 Wnd
->rcClient
.bottom
-
1527 Wnd
->rcClient
.top
));
1528 co_IntSendMessage(Window
->hSelf
, WM_MOVE
, 0,
1529 MAKELONG(Wnd
->rcClient
.left
,
1530 Wnd
->rcClient
.top
));
1531 IntEngWindowChanged(Window
, WOC_RGN_CLIENT
);
1535 /* Activate the window if activation is not requested and the window is not minimized */
1537 if (!(Swp & (SWP_NOACTIVATE | SWP_HIDEWINDOW)) && !(Window->style & WS_MINIMIZE))
1539 WinPosChangeActiveWindow(Wnd, FALSE);
1548 /* find child of 'parent' that contains the given point (in parent-relative coords) */
1549 PWINDOW_OBJECT
child_window_from_point(PWINDOW_OBJECT parent
, int x
, int y
)
1551 PWINDOW_OBJECT Wnd
;// = parent->spwndChild;
1553 // LIST_FOR_EACH_ENTRY( Wnd, &parent->children, struct window, entry )
1554 for (Wnd
= parent
->spwndChild
; Wnd
; Wnd
= Wnd
->spwndNext
)
1556 if (!IntPtInWindow( Wnd
, x
, y
)) continue; /* skip it */
1558 /* if window is minimized or disabled, return at once */
1559 if (Wnd
->style
& (WS_MINIMIZE
|WS_DISABLED
)) return Wnd
;
1561 /* if point is not in client area, return at once */
1562 if (x
< Wnd
->rcClient
.left
|| x
>= Wnd
->rcClient
.right
||
1563 y
< Wnd
->rcClient
.top
|| y
>= Wnd
->rcClient
.bottom
)
1566 return child_window_from_point( Wnd
, x
- Wnd
->rcClient
.left
, y
- Wnd
->rcClient
.top
);
1568 return parent
; /* not found any child */
1572 /* wine server: child_window_from_point
1574 Caller must dereference the "returned" Window
1578 co_WinPosSearchChildren(
1579 PWINDOW_OBJECT ScopeWin
,
1580 PUSER_MESSAGE_QUEUE OnlyHitTests
,
1582 PWINDOW_OBJECT
* Window
,
1586 PWINDOW_OBJECT Current
;
1589 USER_REFERENCE_ENTRY Ref
;
1591 ASSERT_REFS_CO(ScopeWin
);
1593 if ((List
= IntWinListChildren(ScopeWin
)))
1595 for (phWnd
= List
; *phWnd
; ++phWnd
)
1597 if (!(Current
= UserGetWindowObject(*phWnd
)))
1599 CurrentWnd
= Current
->Wnd
;
1601 if (!(CurrentWnd
->style
& WS_VISIBLE
))
1606 if ((CurrentWnd
->style
& (WS_POPUP
| WS_CHILD
| WS_DISABLED
)) ==
1607 (WS_CHILD
| WS_DISABLED
))
1612 if (!IntPtInWindow(Current
, Point
->x
, Point
->y
))
1617 if (*Window
) UserDereferenceObject(*Window
);
1619 UserReferenceObject(*Window
);
1621 if (CurrentWnd
->style
& WS_MINIMIZE
)
1623 *HitTest
= HTCAPTION
;
1627 if (CurrentWnd
->style
& WS_DISABLED
)
1633 UserRefObjectCo(Current
, &Ref
);
1635 if (OnlyHitTests
&& (Current
->pti
->MessageQueue
== OnlyHitTests
))
1637 *HitTest
= co_IntSendMessage(Current
->hSelf
, WM_NCHITTEST
, 0,
1638 MAKELONG(Point
->x
, Point
->y
));
1639 if ((*HitTest
) == (USHORT
)HTTRANSPARENT
)
1641 UserDerefObjectCo(Current
);
1646 *HitTest
= HTCLIENT
;
1648 if (Point
->x
>= CurrentWnd
->rcClient
.left
&&
1649 Point
->x
< CurrentWnd
->rcClient
.right
&&
1650 Point
->y
>= CurrentWnd
->rcClient
.top
&&
1651 Point
->y
< CurrentWnd
->rcClient
.bottom
)
1653 co_WinPosSearchChildren(Current
, OnlyHitTests
, Point
, Window
, HitTest
);
1656 UserDerefObjectCo(Current
);
1664 /* wine: WINPOS_WindowFromPoint */
1666 co_WinPosWindowFromPoint(PWINDOW_OBJECT ScopeWin
, PUSER_MESSAGE_QUEUE OnlyHitTests
, POINT
*WinPoint
,
1667 PWINDOW_OBJECT
* Window
)
1669 HWND DesktopWindowHandle
;
1670 PWINDOW_OBJECT DesktopWindow
;
1671 POINT Point
= *WinPoint
;
1674 ASSERT_REFS_CO(ScopeWin
);
1680 DPRINT1("WinPosWindowFromPoint(): ScopeWin == NULL!\n");
1684 if (ScopeWin
->Wnd
->style
& WS_DISABLED
)
1689 /* Translate the point to the space of the scope window. */
1690 DesktopWindowHandle
= IntGetDesktopWindow();
1691 if((DesktopWindowHandle
!= ScopeWin
->hSelf
) &&
1692 (DesktopWindow
= UserGetWindowObject(DesktopWindowHandle
)))
1694 Point
.x
+= ScopeWin
->Wnd
->rcClient
.left
- DesktopWindow
->Wnd
->rcClient
.left
;
1695 Point
.y
+= ScopeWin
->Wnd
->rcClient
.top
- DesktopWindow
->Wnd
->rcClient
.top
;
1698 HitTest
= HTNOWHERE
;
1700 co_WinPosSearchChildren(ScopeWin
, OnlyHitTests
, &Point
, Window
, &HitTest
);
1702 return ((*Window
) ? HitTest
: HTNOWHERE
);
1707 NtUserGetMinMaxInfo(
1709 MINMAXINFO
*MinMaxInfo
,
1713 PWINDOW_OBJECT Window
= NULL
;
1715 MINMAXINFO SafeMinMax
;
1718 USER_REFERENCE_ENTRY Ref
;
1720 DPRINT("Enter NtUserGetMinMaxInfo\n");
1721 UserEnterExclusive();
1723 if(!(Window
= UserGetWindowObject(hWnd
)))
1729 UserRefObjectCo(Window
, &Ref
);
1732 Size
.x
= Window
->Wnd
->rcWindow
.left
;
1733 Size
.y
= Window
->Wnd
->rcWindow
.top
;
1734 WinPosInitInternalPos(Window
, &Size
,
1739 co_WinPosGetMinMaxInfo(Window
, &SafeMinMax
.ptMaxSize
, &SafeMinMax
.ptMaxPosition
,
1740 &SafeMinMax
.ptMinTrackSize
, &SafeMinMax
.ptMaxTrackSize
);
1744 WinPosFillMinMaxInfoStruct(Window
, &SafeMinMax
);
1746 Status
= MmCopyToCaller(MinMaxInfo
, &SafeMinMax
, sizeof(MINMAXINFO
));
1747 if(!NT_SUCCESS(Status
))
1749 SetLastNtError(Status
);
1757 if (Window
) UserDerefObjectCo(Window
);
1759 DPRINT("Leave NtUserGetMinMaxInfo, ret=%i\n", ret
);