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.
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 ******************************************************************/
37 co_IntPaintWindows(PWINDOW_OBJECT Window
, ULONG Flags
, BOOL Recurse
);
40 IntValidateParent(PWINDOW_OBJECT Child
, HRGN hValidateRgn
, BOOL Recurse
);
42 /* GLOBALS *******************************************************************/
44 #define MINMAX_NOSWP (0x00010000)
46 #define SWP_EX_NOCOPY 0x0001
47 #define SWP_EX_PAINTSELF 0x0002
49 #define SWP_AGG_NOGEOMETRYCHANGE \
50 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
51 #define SWP_AGG_NOPOSCHANGE \
52 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
53 #define SWP_AGG_STATUSFLAGS \
54 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
56 /* FUNCTIONS *****************************************************************/
59 IntGetClientOrigin(PWINDOW_OBJECT Window OPTIONAL
, LPPOINT Point
)
61 Window
= Window
? Window
: UserGetWindowObject(IntGetDesktopWindow());
64 Point
->x
= Point
->y
= 0;
67 Point
->x
= Window
->Wnd
->rcClient
.left
;
68 Point
->y
= Window
->Wnd
->rcClient
.top
;
77 UserGetClientOrigin(PWINDOW_OBJECT Window
, LPPOINT Point
)
85 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
89 Ret
= IntGetClientOrigin(Window
, &pt
);
93 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
97 Status
= MmCopyToCaller(Point
, &pt
, sizeof(POINT
));
98 if(!NT_SUCCESS(Status
))
100 SetLastNtError(Status
);
109 /*******************************************************************
110 * can_activate_window
112 * Check if we can activate the specified window.
115 BOOL FASTCALL
can_activate_window( PWINDOW_OBJECT Wnd OPTIONAL
)
119 if (!Wnd
) return FALSE
;
120 if (!Wnd
->Wnd
) return FALSE
;
121 style
= Wnd
->Wnd
->style
;
122 if (!(style
& WS_VISIBLE
) &&
123 Wnd
->OwnerThread
->ThreadsProcess
!= CsrProcess
) return FALSE
;
124 if ((style
& (WS_POPUP
|WS_CHILD
)) == WS_CHILD
) return FALSE
;
125 return !(style
& WS_DISABLED
);
129 /*******************************************************************
130 * WinPosActivateOtherWindow
132 * Activates window other than pWnd.
135 co_WinPosActivateOtherWindow(PWINDOW_OBJECT Window
)
137 PWINDOW_OBJECT WndTo
= NULL
;
139 USER_REFERENCE_ENTRY Ref
;
142 ASSERT_REFS_CO(Window
);
146 if (IntIsDesktopWindow(Window
))
148 IntSetFocusMessageQueue(NULL
);
152 /* If this is popup window, try to activate the owner first. */
153 if ((Wnd
->style
& WS_POPUP
) && (WndTo
= IntGetOwner(Window
)))
155 WndTo
= UserGetAncestor( WndTo
, GA_ROOT
);
156 if (can_activate_window(WndTo
)) goto done
;
159 /* Pick a next top-level window. */
160 /* FIXME: Search for non-tooltip windows first. */
164 if (!(WndTo
= WndTo
->NextSibling
)) break;
165 if (can_activate_window( WndTo
)) break;
170 if (WndTo
) UserRefObjectCo(WndTo
, &Ref
);
172 Fg
= UserGetForegroundWindow();
173 if ((!Fg
|| Window
->hSelf
== Fg
) && WndTo
)//fixme: ok if WndTo is NULL??
175 /* fixme: wine can pass WndTo=NULL to co_IntSetForegroundWindow. hmm */
176 if (co_IntSetForegroundWindow(WndTo
))
178 UserDerefObjectCo(WndTo
);
183 if (!co_IntSetActiveWindow(WndTo
)) /* ok for WndTo to be NULL here */
184 co_IntSetActiveWindow(0);
186 if (WndTo
) UserDerefObjectCo(WndTo
);
192 co_WinPosArrangeIconicWindows(PWINDOW_OBJECT parent
)
195 INT i
, x
, y
, xspacing
, yspacing
;
196 HWND
*List
= IntWinListChildren(parent
);
198 ASSERT_REFS_CO(parent
);
200 IntGetClientRect( parent
, &rectParent
);
202 y
= rectParent
.bottom
;
204 xspacing
= UserGetSystemMetrics(SM_CXMINSPACING
);
205 yspacing
= UserGetSystemMetrics(SM_CYMINSPACING
);
207 DPRINT("X:%d Y:%d XS:%d YS:%d\n",x
,y
,xspacing
,yspacing
);
209 for( i
= 0; List
[i
]; i
++)
211 PWINDOW_OBJECT WndChild
;
214 if (!(WndChild
= UserGetWindowObject(List
[i
])))
217 ChildWnd
= WndChild
->Wnd
;
219 if((ChildWnd
->style
& WS_MINIMIZE
) != 0 )
221 USER_REFERENCE_ENTRY Ref
;
222 UserRefObjectCo(WndChild
, &Ref
);
224 co_WinPosSetWindowPos(WndChild
, 0, x
+ UserGetSystemMetrics(SM_CXBORDER
),
225 y
- yspacing
- UserGetSystemMetrics(SM_CYBORDER
)
226 , 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
228 UserDerefObjectCo(WndChild
);
230 if (x
<= rectParent
.right
- xspacing
)
245 WinPosFindIconPos(PWINDOW_OBJECT Window
, POINT
*Pos
)
251 WinPosInitInternalPos(PWINDOW_OBJECT Window
, POINT
*pt
, RECTL
*RestoreRect
)
253 PWINDOW_OBJECT Parent
;
255 PWND Wnd
= Window
->Wnd
;
257 if (!Wnd
->InternalPosInitialized
)
260 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
261 PDESKTOP Desktop
= pti
->Desktop
; /* Or rather get it from the window? */
263 Parent
= Window
->Parent
;
266 if(IntIsDesktopWindow(Parent
))
267 IntGetDesktopWorkArea(Desktop
, &WorkArea
);
269 WorkArea
= Parent
->Wnd
->rcClient
;
272 IntGetDesktopWorkArea(Desktop
, &WorkArea
);
274 Wnd
->InternalPos
.NormalRect
= Window
->Wnd
->rcWindow
;
275 IntGetWindowBorderMeasures(Window
, &XInc
, &YInc
);
276 Wnd
->InternalPos
.MaxPos
.x
= WorkArea
.left
- XInc
;
277 Wnd
->InternalPos
.MaxPos
.y
= WorkArea
.top
- YInc
;
278 Wnd
->InternalPos
.IconPos
.x
= WorkArea
.left
;
279 Wnd
->InternalPos
.IconPos
.y
= WorkArea
.bottom
- UserGetSystemMetrics(SM_CYMINIMIZED
);
281 Wnd
->InternalPosInitialized
= TRUE
;
283 if (Wnd
->style
& WS_MINIMIZE
)
285 Wnd
->InternalPos
.IconPos
= *pt
;
287 else if (Wnd
->style
& WS_MAXIMIZE
)
289 Wnd
->InternalPos
.MaxPos
= *pt
;
291 else if (RestoreRect
!= NULL
)
293 Wnd
->InternalPos
.NormalRect
= *RestoreRect
;
298 co_WinPosMinMaximize(PWINDOW_OBJECT Window
, UINT ShowFlag
, RECT
* NewPos
)
304 ASSERT_REFS_CO(Window
);
307 Size
.x
= Wnd
->rcWindow
.left
;
308 Size
.y
= Wnd
->rcWindow
.top
;
309 WinPosInitInternalPos(Window
, &Size
, &Wnd
->rcWindow
);
311 if (co_HOOK_CallHooks( WH_CBT
, HCBT_MINMAX
, (WPARAM
)Window
->hSelf
, ShowFlag
))
312 return SWP_NOSIZE
| SWP_NOMOVE
;
314 if (Wnd
->style
& WS_MINIMIZE
)
316 if (!co_IntSendMessage(Window
->hSelf
, WM_QUERYOPEN
, 0, 0))
318 return(SWP_NOSIZE
| SWP_NOMOVE
);
320 SwpFlags
|= SWP_NOCOPYBITS
;
326 if (Wnd
->style
& WS_MAXIMIZE
)
328 Window
->Flags
|= WINDOWOBJECT_RESTOREMAX
;
329 Wnd
->style
&= ~WS_MAXIMIZE
;
333 Window
->Flags
&= ~WINDOWOBJECT_RESTOREMAX
;
335 co_UserRedrawWindow(Window
, NULL
, 0, RDW_VALIDATE
| RDW_NOERASE
|
336 RDW_NOINTERNALPAINT
);
337 Wnd
->style
|= WS_MINIMIZE
;
338 WinPosFindIconPos(Window
, &Wnd
->InternalPos
.IconPos
);
339 RECTL_vSetRect(NewPos
, Wnd
->InternalPos
.IconPos
.x
, Wnd
->InternalPos
.IconPos
.y
,
340 UserGetSystemMetrics(SM_CXMINIMIZED
),
341 UserGetSystemMetrics(SM_CYMINIMIZED
));
342 SwpFlags
|= SWP_NOCOPYBITS
;
348 co_WinPosGetMinMaxInfo(Window
, &Size
, &Wnd
->InternalPos
.MaxPos
,
350 DPRINT("Maximize: %d,%d %dx%d\n",
351 Wnd
->InternalPos
.MaxPos
.x
, Wnd
->InternalPos
.MaxPos
.y
, Size
.x
, Size
.y
);
352 if (Wnd
->style
& WS_MINIMIZE
)
354 Wnd
->style
&= ~WS_MINIMIZE
;
356 Wnd
->style
|= WS_MAXIMIZE
;
357 RECTL_vSetRect(NewPos
, Wnd
->InternalPos
.MaxPos
.x
, Wnd
->InternalPos
.MaxPos
.y
,
364 if (Wnd
->style
& WS_MINIMIZE
)
366 Wnd
->style
&= ~WS_MINIMIZE
;
367 if (Window
->Flags
& WINDOWOBJECT_RESTOREMAX
)
369 co_WinPosGetMinMaxInfo(Window
, &Size
,
370 &Wnd
->InternalPos
.MaxPos
, NULL
, NULL
);
371 Wnd
->style
|= WS_MAXIMIZE
;
372 RECTL_vSetRect(NewPos
, Wnd
->InternalPos
.MaxPos
.x
,
373 Wnd
->InternalPos
.MaxPos
.y
, Size
.x
, Size
.y
);
378 *NewPos
= Wnd
->InternalPos
.NormalRect
;
379 NewPos
->right
-= NewPos
->left
;
380 NewPos
->bottom
-= NewPos
->top
;
386 if (!(Wnd
->style
& WS_MAXIMIZE
))
390 Wnd
->style
&= ~WS_MAXIMIZE
;
391 *NewPos
= Wnd
->InternalPos
.NormalRect
;
392 NewPos
->right
-= NewPos
->left
;
393 NewPos
->bottom
-= NewPos
->top
;
404 WinPosFillMinMaxInfoStruct(PWINDOW_OBJECT Window
, MINMAXINFO
*Info
)
408 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
409 PDESKTOP Desktop
= pti
->Desktop
; /* Or rather get it from the window? */
411 IntGetDesktopWorkArea(Desktop
, &WorkArea
);
413 /* Get default values. */
414 Info
->ptMinTrackSize
.x
= UserGetSystemMetrics(SM_CXMINTRACK
);
415 Info
->ptMinTrackSize
.y
= UserGetSystemMetrics(SM_CYMINTRACK
);
417 IntGetWindowBorderMeasures(Window
, &XInc
, &YInc
);
418 Info
->ptMaxSize
.x
= WorkArea
.right
- WorkArea
.left
+ 2 * XInc
;
419 Info
->ptMaxSize
.y
= WorkArea
.bottom
- WorkArea
.top
+ 2 * YInc
;
420 Info
->ptMaxTrackSize
.x
= Info
->ptMaxSize
.x
;
421 Info
->ptMaxTrackSize
.y
= Info
->ptMaxSize
.y
;
423 if (Window
->Wnd
->InternalPosInitialized
)
425 Info
->ptMaxPosition
= Window
->Wnd
->InternalPos
.MaxPos
;
429 Info
->ptMaxPosition
.x
= WorkArea
.left
- XInc
;
430 Info
->ptMaxPosition
.y
= WorkArea
.top
- YInc
;
435 co_WinPosGetMinMaxInfo(PWINDOW_OBJECT Window
, POINT
* MaxSize
, POINT
* MaxPos
,
436 POINT
* MinTrack
, POINT
* MaxTrack
)
440 ASSERT_REFS_CO(Window
);
442 WinPosFillMinMaxInfoStruct(Window
, &MinMax
);
444 co_IntSendMessage(Window
->hSelf
, WM_GETMINMAXINFO
, 0, (LPARAM
)&MinMax
);
446 MinMax
.ptMaxTrackSize
.x
= max(MinMax
.ptMaxTrackSize
.x
,
447 MinMax
.ptMinTrackSize
.x
);
448 MinMax
.ptMaxTrackSize
.y
= max(MinMax
.ptMaxTrackSize
.y
,
449 MinMax
.ptMinTrackSize
.y
);
452 *MaxSize
= MinMax
.ptMaxSize
;
454 *MaxPos
= MinMax
.ptMaxPosition
;
456 *MinTrack
= MinMax
.ptMinTrackSize
;
458 *MaxTrack
= MinMax
.ptMaxTrackSize
;
460 return 0; //FIXME: what does it return?
465 FixClientRect(PRECTL ClientRect
, PRECTL WindowRect
)
467 if (ClientRect
->left
< WindowRect
->left
)
469 ClientRect
->left
= WindowRect
->left
;
471 else if (WindowRect
->right
< ClientRect
->left
)
473 ClientRect
->left
= WindowRect
->right
;
475 if (ClientRect
->right
< WindowRect
->left
)
477 ClientRect
->right
= WindowRect
->left
;
479 else if (WindowRect
->right
< ClientRect
->right
)
481 ClientRect
->right
= WindowRect
->right
;
483 if (ClientRect
->top
< WindowRect
->top
)
485 ClientRect
->top
= WindowRect
->top
;
487 else if (WindowRect
->bottom
< ClientRect
->top
)
489 ClientRect
->top
= WindowRect
->bottom
;
491 if (ClientRect
->bottom
< WindowRect
->top
)
493 ClientRect
->bottom
= WindowRect
->top
;
495 else if (WindowRect
->bottom
< ClientRect
->bottom
)
497 ClientRect
->bottom
= WindowRect
->bottom
;
503 co_WinPosDoNCCALCSize(PWINDOW_OBJECT Window
, PWINDOWPOS WinPos
,
504 RECT
* WindowRect
, RECT
* ClientRect
)
506 PWINDOW_OBJECT Parent
;
510 ASSERT_REFS_CO(Window
);
513 /* Send WM_NCCALCSIZE message to get new client area */
514 if ((WinPos
->flags
& (SWP_FRAMECHANGED
| SWP_NOSIZE
)) != SWP_NOSIZE
)
516 NCCALCSIZE_PARAMS params
;
517 WINDOWPOS winposCopy
;
519 params
.rgrc
[0] = *WindowRect
;
520 params
.rgrc
[1] = Window
->Wnd
->rcWindow
;
521 params
.rgrc
[2] = Window
->Wnd
->rcClient
;
522 Parent
= Window
->Parent
;
523 if (0 != (Wnd
->style
& WS_CHILD
) && Parent
)
525 RECTL_vOffsetRect(&(params
.rgrc
[0]), - Parent
->Wnd
->rcClient
.left
,
526 - Parent
->Wnd
->rcClient
.top
);
527 RECTL_vOffsetRect(&(params
.rgrc
[1]), - Parent
->Wnd
->rcClient
.left
,
528 - Parent
->Wnd
->rcClient
.top
);
529 RECTL_vOffsetRect(&(params
.rgrc
[2]), - Parent
->Wnd
->rcClient
.left
,
530 - Parent
->Wnd
->rcClient
.top
);
532 params
.lppos
= &winposCopy
;
533 winposCopy
= *WinPos
;
535 wvrFlags
= co_IntSendMessage(Window
->hSelf
, WM_NCCALCSIZE
, TRUE
, (LPARAM
) ¶ms
);
537 /* If the application send back garbage, ignore it */
538 if (params
.rgrc
[0].left
<= params
.rgrc
[0].right
&&
539 params
.rgrc
[0].top
<= params
.rgrc
[0].bottom
)
541 *ClientRect
= params
.rgrc
[0];
542 if ((Wnd
->style
& WS_CHILD
) && Parent
)
544 RECTL_vOffsetRect(ClientRect
, Parent
->Wnd
->rcClient
.left
,
545 Parent
->Wnd
->rcClient
.top
);
547 FixClientRect(ClientRect
, WindowRect
);
550 /* FIXME: WVR_ALIGNxxx */
552 if (ClientRect
->left
!= Wnd
->rcClient
.left
||
553 ClientRect
->top
!= Wnd
->rcClient
.top
)
555 WinPos
->flags
&= ~SWP_NOCLIENTMOVE
;
558 if ((ClientRect
->right
- ClientRect
->left
!=
559 Wnd
->rcClient
.right
- Wnd
->rcClient
.left
) ||
560 (ClientRect
->bottom
- ClientRect
->top
!=
561 Wnd
->rcClient
.bottom
- Wnd
->rcClient
.top
))
563 WinPos
->flags
&= ~SWP_NOCLIENTSIZE
;
568 if (! (WinPos
->flags
& SWP_NOMOVE
)
569 && (ClientRect
->left
!= Wnd
->rcClient
.left
||
570 ClientRect
->top
!= Wnd
->rcClient
.top
))
572 WinPos
->flags
&= ~SWP_NOCLIENTMOVE
;
581 co_WinPosDoWinPosChanging(PWINDOW_OBJECT Window
,
589 ASSERT_REFS_CO(Window
);
592 if (!(WinPos
->flags
& SWP_NOSENDCHANGING
))
594 co_IntPostOrSendMessage(Window
->hSelf
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
) WinPos
);
597 *WindowRect
= Wnd
->rcWindow
;
598 *ClientRect
= Wnd
->rcClient
;
600 if (!(WinPos
->flags
& SWP_NOSIZE
))
602 WindowRect
->right
= WindowRect
->left
+ WinPos
->cx
;
603 WindowRect
->bottom
= WindowRect
->top
+ WinPos
->cy
;
606 if (!(WinPos
->flags
& SWP_NOMOVE
))
608 PWINDOW_OBJECT Parent
;
611 Parent
= Window
->Parent
;
612 if ((0 != (Wnd
->style
& WS_CHILD
)) && Parent
)
614 X
+= Parent
->Wnd
->rcClient
.left
;
615 Y
+= Parent
->Wnd
->rcClient
.top
;
618 WindowRect
->left
= X
;
620 WindowRect
->right
+= X
- Wnd
->rcWindow
.left
;
621 WindowRect
->bottom
+= Y
- Wnd
->rcWindow
.top
;
622 RECTL_vOffsetRect(ClientRect
,
623 X
- Wnd
->rcWindow
.left
,
624 Y
- Wnd
->rcWindow
.top
);
627 WinPos
->flags
|= SWP_NOCLIENTMOVE
| SWP_NOCLIENTSIZE
;
633 * Fix Z order taking into account owned popups -
634 * basically we need to maintain them above the window that owns them
638 WinPosDoOwnedPopups(HWND hWnd
, HWND hWndInsertAfter
)
641 HWND Owner
= UserGetWindow(hWnd
, GW_OWNER
);
642 LONG Style
= UserGetWindowLong(hWnd
, GWL_STYLE
, FALSE
);
643 PWINDOW_OBJECT DesktopWindow
, ChildObject
;
646 if ((Style
& WS_POPUP
) && Owner
)
648 /* Make sure this popup stays above the owner */
649 HWND hWndLocalPrev
= HWND_TOPMOST
;
651 if (hWndInsertAfter
!= HWND_TOPMOST
)
653 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
654 List
= IntWinListChildren(DesktopWindow
);
658 for (i
= 0; List
[i
]; i
++)
660 if (List
[i
] == Owner
)
662 if (HWND_TOP
== hWndInsertAfter
)
664 ChildObject
= UserGetWindowObject(List
[i
]);
665 if (NULL
!= ChildObject
)
667 if (0 == (ChildObject
->Wnd
->ExStyle
& WS_EX_TOPMOST
))
674 hWndLocalPrev
= List
[i
];
675 if (hWndLocalPrev
== hWndInsertAfter
)
678 hWndInsertAfter
= hWndLocalPrev
;
682 else if (Style
& WS_CHILD
)
684 return hWndInsertAfter
;
689 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
690 List
= IntWinListChildren(DesktopWindow
);
694 for (i
= 0; List
[i
]; i
++)
701 if (!(Wnd
= UserGetWindowObject(List
[i
])))
704 if ((Wnd
->Wnd
->style
& WS_POPUP
) &&
705 UserGetWindow(List
[i
], GW_OWNER
) == hWnd
)
707 USER_REFERENCE_ENTRY Ref
;
708 UserRefObjectCo(Wnd
, &Ref
);
710 co_WinPosSetWindowPos(Wnd
, hWndInsertAfter
, 0, 0, 0, 0,
711 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOSENDCHANGING
);
713 UserDerefObjectCo(Wnd
);
715 hWndInsertAfter
= List
[i
];
721 return hWndInsertAfter
;
724 /***********************************************************************
725 * WinPosInternalMoveWindow
727 * Update WindowRect and ClientRect of Window and all of its children
728 * We keep both WindowRect and ClientRect in screen coordinates internally
732 WinPosInternalMoveWindow(PWINDOW_OBJECT Window
, INT MoveX
, INT MoveY
)
734 PWINDOW_OBJECT Child
;
736 ASSERT(Window
!= Window
->FirstChild
);
738 Window
->Wnd
->rcWindow
.left
+= MoveX
;
739 Window
->Wnd
->rcWindow
.right
+= MoveX
;
740 Window
->Wnd
->rcWindow
.top
+= MoveY
;
741 Window
->Wnd
->rcWindow
.bottom
+= MoveY
;
743 Window
->Wnd
->rcClient
.left
+= MoveX
;
744 Window
->Wnd
->rcClient
.right
+= MoveX
;
745 Window
->Wnd
->rcClient
.top
+= MoveY
;
746 Window
->Wnd
->rcClient
.bottom
+= MoveY
;
748 for(Child
= Window
->FirstChild
; Child
; Child
= Child
->NextSibling
)
750 WinPosInternalMoveWindow(Child
, MoveX
, MoveY
);
755 * WinPosFixupSWPFlags
757 * Fix redundant flags and values in the WINDOWPOS structure.
761 WinPosFixupFlags(WINDOWPOS
*WinPos
, PWINDOW_OBJECT Window
)
763 PWND Wnd
= Window
->Wnd
;
765 if (!Wnd
) return FALSE
;
767 if (Wnd
->style
& WS_VISIBLE
)
769 WinPos
->flags
&= ~SWP_SHOWWINDOW
;
773 WinPos
->flags
&= ~SWP_HIDEWINDOW
;
774 if (!(WinPos
->flags
& SWP_SHOWWINDOW
))
775 WinPos
->flags
|= SWP_NOREDRAW
;
778 WinPos
->cx
= max(WinPos
->cx
, 0);
779 WinPos
->cy
= max(WinPos
->cy
, 0);
781 /* Check for right size */
782 if (Wnd
->rcWindow
.right
- Wnd
->rcWindow
.left
== WinPos
->cx
&&
783 Wnd
->rcWindow
.bottom
- Wnd
->rcWindow
.top
== WinPos
->cy
)
785 WinPos
->flags
|= SWP_NOSIZE
;
788 /* Check for right position */
789 if (Wnd
->rcWindow
.left
== WinPos
->x
&&
790 Wnd
->rcWindow
.top
== WinPos
->y
)
792 WinPos
->flags
|= SWP_NOMOVE
;
795 if (WinPos
->hwnd
== UserGetForegroundWindow())
797 WinPos
->flags
|= SWP_NOACTIVATE
; /* Already active */
800 if ((Wnd
->style
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)
802 /* Bring to the top when activating */
803 if (!(WinPos
->flags
& SWP_NOACTIVATE
))
805 WinPos
->flags
&= ~SWP_NOZORDER
;
806 WinPos
->hwndInsertAfter
= (0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
) ?
807 HWND_TOPMOST
: HWND_TOP
);
812 /* Check hwndInsertAfter */
813 if (!(WinPos
->flags
& SWP_NOZORDER
))
815 /* Fix sign extension */
816 if (WinPos
->hwndInsertAfter
== (HWND
)0xffff)
818 WinPos
->hwndInsertAfter
= HWND_TOPMOST
;
820 else if (WinPos
->hwndInsertAfter
== (HWND
)0xfffe)
822 WinPos
->hwndInsertAfter
= HWND_NOTOPMOST
;
825 if (WinPos
->hwndInsertAfter
== HWND_NOTOPMOST
)
827 WinPos
->hwndInsertAfter
= HWND_TOP
;
829 else if (HWND_TOP
== WinPos
->hwndInsertAfter
830 && 0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
))
832 /* Keep it topmost when it's already topmost */
833 WinPos
->hwndInsertAfter
= HWND_TOPMOST
;
836 /* hwndInsertAfter must be a sibling of the window */
837 if (HWND_TOPMOST
!= WinPos
->hwndInsertAfter
838 && HWND_TOP
!= WinPos
->hwndInsertAfter
839 && HWND_NOTOPMOST
!= WinPos
->hwndInsertAfter
840 && HWND_BOTTOM
!= WinPos
->hwndInsertAfter
)
842 PWINDOW_OBJECT InsAfterWnd
, Parent
= Window
->Parent
;
844 InsAfterWnd
= UserGetWindowObject(WinPos
->hwndInsertAfter
);
846 if (InsAfterWnd
&& UserGetAncestor(InsAfterWnd
, GA_PARENT
) != Parent
)
853 * We don't need to change the Z order of hwnd if it's already
854 * inserted after hwndInsertAfter or when inserting hwnd after
857 if ((WinPos
->hwnd
== WinPos
->hwndInsertAfter
) ||
858 (WinPos
->hwnd
== UserGetWindow(WinPos
->hwndInsertAfter
, GW_HWNDNEXT
)))
860 WinPos
->flags
|= SWP_NOZORDER
;
869 /* x and y are always screen relative */
871 co_WinPosSetWindowPos(
872 PWINDOW_OBJECT Window
,
885 HRGN VisBefore
= NULL
;
886 HRGN VisAfter
= NULL
;
887 HRGN DirtyRgn
= NULL
;
888 HRGN ExposedRgn
= NULL
;
891 RECTL OldWindowRect
, OldClientRect
;
896 PWINDOW_OBJECT Ancestor
;
898 ASSERT_REFS_CO(Window
);
900 if (!Window
->Wnd
) return FALSE
;
902 /* FIXME: Get current active window from active queue. */
905 * Only allow CSRSS to mess with the desktop window
907 if (Window
->hSelf
== IntGetDesktopWindow() &&
908 Window
->OwnerThread
->ThreadsProcess
!= PsGetCurrentProcess())
913 WinPos
.hwnd
= Window
->hSelf
;
914 WinPos
.hwndInsertAfter
= WndInsertAfter
;
919 WinPos
.flags
= flags
;
921 co_WinPosDoWinPosChanging(Window
, &WinPos
, &NewWindowRect
, &NewClientRect
);
923 /* Fix up the flags. */
924 if (!WinPosFixupFlags(&WinPos
, Window
))
926 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
930 /* Does the window still exist? */
931 if (!IntIsWindow(WinPos
.hwnd
))
933 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
937 Ancestor
= UserGetAncestor(Window
, GA_PARENT
);
938 if ((WinPos
.flags
& (SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) !=
940 Ancestor
&& Ancestor
->hSelf
== IntGetDesktopWindow())
942 WinPos
.hwndInsertAfter
= WinPosDoOwnedPopups(WinPos
.hwnd
, WinPos
.hwndInsertAfter
);
945 if (!(WinPos
.flags
& SWP_NOREDRAW
))
947 /* Compute the visible region before the window position is changed */
948 if (!(WinPos
.flags
& (SWP_NOREDRAW
| SWP_SHOWWINDOW
)) &&
949 (WinPos
.flags
& (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
|
950 SWP_HIDEWINDOW
| SWP_FRAMECHANGED
)) !=
951 (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
))
953 VisBefore
= VIS_ComputeVisibleRegion(Window
, FALSE
, FALSE
, TRUE
);
956 if (VisBefore
!= NULL
&& (VisRgn
= (PROSRGNDATA
)REGION_LockRgn(VisBefore
)) &&
957 REGION_GetRgnBox(VisRgn
, &TempRect
) == NULLREGION
)
959 REGION_UnlockRgn(VisRgn
);
960 GreDeleteObject(VisBefore
);
965 REGION_UnlockRgn(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
->Parent
))
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
->FirstChild
;
993 while (NULL
!= Sibling
&& 0 != (Sibling
->Wnd
->ExStyle
& WS_EX_TOPMOST
))
995 InsertAfterWindow
= Sibling
;
996 Sibling
= Sibling
->NextSibling
;
998 if (NULL
!= InsertAfterWindow
)
1000 UserReferenceObject(InsertAfterWindow
);
1003 else if (WinPos
.hwndInsertAfter
== HWND_BOTTOM
)
1005 if(ParentWindow
->LastChild
)
1007 UserReferenceObject(ParentWindow
->LastChild
);
1008 InsertAfterWindow
= ParentWindow
->LastChild
;
1011 InsertAfterWindow
= NULL
;
1014 InsertAfterWindow
= IntGetWindowObject(WinPos
.hwndInsertAfter
);
1015 /* Do nothing if hwndInsertAfter is HWND_BOTTOM and Window is already
1017 if (InsertAfterWindow
!= Window
)
1019 IntUnlinkWindow(Window
);
1020 IntLinkWindow(Window
, ParentWindow
, InsertAfterWindow
);
1022 if (InsertAfterWindow
!= NULL
)
1023 UserDereferenceObject(InsertAfterWindow
);
1024 if ((HWND_TOPMOST
== WinPos
.hwndInsertAfter
)
1025 || (0 != (Window
->Wnd
->ExStyle
& WS_EX_TOPMOST
)
1026 && NULL
!= Window
->PrevSibling
1027 && 0 != (Window
->PrevSibling
->Wnd
->ExStyle
& WS_EX_TOPMOST
))
1028 || (NULL
!= Window
->NextSibling
1029 && 0 != (Window
->NextSibling
->Wnd
->ExStyle
& WS_EX_TOPMOST
)))
1031 Window
->Wnd
->ExStyle
|= WS_EX_TOPMOST
;
1035 Window
->Wnd
->ExStyle
&= ~ WS_EX_TOPMOST
;
1041 if (!Window
->Wnd
) return FALSE
;
1043 OldWindowRect
= Window
->Wnd
->rcWindow
;
1044 OldClientRect
= Window
->Wnd
->rcClient
;
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
->Wnd
->rcWindow
= NewWindowRect
;
1069 Window
->Wnd
->rcClient
= 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 if ((Window
->Wnd
->style
& WS_VISIBLE
) &&
1077 Window
->Parent
== UserGetDesktopWindow())
1079 co_IntShellHookNotify(HSHELL_WINDOWDESTROYED
, (LPARAM
)Window
->hSelf
);
1081 Window
->Wnd
->style
&= ~WS_VISIBLE
;
1083 else if (WinPos
.flags
& SWP_SHOWWINDOW
)
1085 if (!(Window
->Wnd
->style
& WS_VISIBLE
) &&
1086 Window
->Parent
== UserGetDesktopWindow())
1088 co_IntShellHookNotify(HSHELL_WINDOWCREATED
, (LPARAM
)Window
->hSelf
);
1090 Window
->Wnd
->style
|= WS_VISIBLE
;
1093 if (Window
->UpdateRegion
!= NULL
&& Window
->UpdateRegion
!= (HRGN
)1)
1095 NtGdiOffsetRgn(Window
->UpdateRegion
,
1096 NewWindowRect
.left
- OldWindowRect
.left
,
1097 NewWindowRect
.top
- OldWindowRect
.top
);
1100 DceResetActiveDCEs(Window
);
1102 if (!(WinPos
.flags
& SWP_NOREDRAW
))
1104 /* Determine the new visible region */
1105 VisAfter
= VIS_ComputeVisibleRegion(Window
, FALSE
, FALSE
, TRUE
);
1108 if (VisAfter
!= NULL
&& (VisRgn
= (PROSRGNDATA
)REGION_LockRgn(VisAfter
)) &&
1109 REGION_GetRgnBox(VisRgn
, &TempRect
) == NULLREGION
)
1111 REGION_UnlockRgn(VisRgn
);
1112 GreDeleteObject(VisAfter
);
1117 REGION_UnlockRgn(VisRgn
);
1118 NtGdiOffsetRgn(VisAfter
, -Window
->Wnd
->rcWindow
.left
, -Window
->Wnd
->rcWindow
.top
);
1122 * Determine which pixels can be copied from the old window position
1123 * to the new. Those pixels must be visible in both the old and new
1124 * position. Also, check the class style to see if the windows of this
1125 * class need to be completely repainted on (horizontal/vertical) size
1128 if (VisBefore
!= NULL
&& VisAfter
!= NULL
&& !(WinPos
.flags
& SWP_NOCOPYBITS
) &&
1129 ((WinPos
.flags
& SWP_NOSIZE
) || !(WvrFlags
& WVR_REDRAW
)) &&
1130 !(Window
->Wnd
->ExStyle
& WS_EX_TRANSPARENT
))
1132 CopyRgn
= NtGdiCreateRectRgn(0, 0, 0, 0);
1133 RgnType
= NtGdiCombineRgn(CopyRgn
, VisAfter
, VisBefore
, RGN_AND
);
1136 * If this is (also) a window resize, the whole nonclient area
1137 * needs to be repainted. So we limit the copy to the client area,
1138 * 'cause there is no use in copying it (would possibly cause
1139 * "flashing" too). However, if the copy region is already empty,
1140 * we don't have to crop (can't take anything away from an empty
1143 if (!(WinPos
.flags
& SWP_NOSIZE
) && RgnType
!= ERROR
&&
1144 RgnType
!= NULLREGION
)
1146 PROSRGNDATA pCopyRgn
;
1147 RECTL ORect
= OldClientRect
;
1148 RECTL NRect
= NewClientRect
;
1149 RECTL_vOffsetRect(&ORect
, - OldWindowRect
.left
, - OldWindowRect
.top
);
1150 RECTL_vOffsetRect(&NRect
, - NewWindowRect
.left
, - NewWindowRect
.top
);
1151 RECTL_bIntersectRect(&CopyRect
, &ORect
, &NRect
);
1152 pCopyRgn
= REGION_LockRgn(CopyRgn
);
1153 REGION_CropAndOffsetRegion(pCopyRgn
, pCopyRgn
, &CopyRect
, NULL
);
1154 REGION_UnlockRgn(pCopyRgn
);
1157 /* No use in copying bits which are in the update region. */
1158 if (Window
->UpdateRegion
!= NULL
)
1160 NtGdiOffsetRgn(CopyRgn
, NewWindowRect
.left
, NewWindowRect
.top
);
1161 NtGdiCombineRgn(CopyRgn
, CopyRgn
, Window
->UpdateRegion
, RGN_DIFF
);
1162 NtGdiOffsetRgn(CopyRgn
, -NewWindowRect
.left
, -NewWindowRect
.top
);
1166 * Now, get the bounding box of the copy region. If it's empty
1167 * there's nothing to copy. Also, it's no use copying bits onto
1170 if ((VisRgn
= (PROSRGNDATA
)REGION_LockRgn(CopyRgn
)) &&
1171 REGION_GetRgnBox(VisRgn
, &CopyRect
) == NULLREGION
)
1173 /* Nothing to copy, clean up */
1174 REGION_UnlockRgn(VisRgn
);
1175 GreDeleteObject(CopyRgn
);
1178 else if (OldWindowRect
.left
!= NewWindowRect
.left
||
1179 OldWindowRect
.top
!= NewWindowRect
.top
)
1183 REGION_UnlockRgn(VisRgn
);
1187 * Small trick here: there is no function to bitblt a region. So
1188 * we set the region as the clipping region, take the bounding box
1189 * of the region and bitblt that. Since nothing outside the clipping
1190 * region is copied, this has the effect of bitblt'ing the region.
1192 * Since NtUserGetDCEx takes ownership of the clip region, we need
1193 * to create a copy of CopyRgn and pass that. We need CopyRgn later
1195 NtGdiOffsetRgn(CopyRgn
, NewWindowRect
.left
, NewWindowRect
.top
);
1196 Dc
= UserGetDCEx(Window
, CopyRgn
, DCX_WINDOW
| DCX_CACHE
|
1197 DCX_INTERSECTRGN
| DCX_CLIPSIBLINGS
|
1200 CopyRect
.left
, CopyRect
.top
, CopyRect
.right
- CopyRect
.left
,
1201 CopyRect
.bottom
- CopyRect
.top
, Dc
,
1202 CopyRect
.left
+ (OldWindowRect
.left
- NewWindowRect
.left
),
1203 CopyRect
.top
+ (OldWindowRect
.top
- NewWindowRect
.top
), SRCCOPY
, 0, 0);
1204 UserReleaseDC(Window
, Dc
, FALSE
);
1205 IntValidateParent(Window
, CopyRgn
, FALSE
);
1206 NtGdiOffsetRgn(CopyRgn
, -NewWindowRect
.left
, -NewWindowRect
.top
);
1210 REGION_UnlockRgn(VisRgn
);
1218 /* We need to redraw what wasn't visible before */
1219 if (VisAfter
!= NULL
)
1221 DirtyRgn
= NtGdiCreateRectRgn(0, 0, 0, 0);
1222 if (CopyRgn
!= NULL
)
1224 RgnType
= NtGdiCombineRgn(DirtyRgn
, VisAfter
, CopyRgn
, RGN_DIFF
);
1228 RgnType
= NtGdiCombineRgn(DirtyRgn
, VisAfter
, 0, RGN_COPY
);
1230 if (RgnType
!= ERROR
&& RgnType
!= NULLREGION
)
1233 NtGdiOffsetRgn(DirtyRgn, Window->rcWindow.left, Window->rcWindow.top);
1234 IntInvalidateWindows(Window, DirtyRgn,
1235 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
1237 GreDeleteObject(DirtyRgn);
1240 PWINDOW_OBJECT Parent
= Window
->Parent
;
1242 NtGdiOffsetRgn(DirtyRgn
,
1243 Window
->Wnd
->rcWindow
.left
,
1244 Window
->Wnd
->rcWindow
.top
);
1245 if ((Window
->Wnd
->style
& WS_CHILD
) &&
1247 !(Parent
->Wnd
->style
& WS_CLIPCHILDREN
))
1249 IntInvalidateWindows(Parent
, DirtyRgn
,
1250 RDW_ERASE
| RDW_INVALIDATE
);
1251 co_IntPaintWindows(Parent
, RDW_ERASENOW
, FALSE
);
1255 IntInvalidateWindows(Window
, DirtyRgn
,
1256 RDW_ERASE
| RDW_FRAME
| RDW_INVALIDATE
| RDW_ALLCHILDREN
);
1259 GreDeleteObject(DirtyRgn
);
1262 if (CopyRgn
!= NULL
)
1264 GreDeleteObject(CopyRgn
);
1267 /* Expose what was covered before but not covered anymore */
1268 if (VisBefore
!= NULL
)
1270 ExposedRgn
= NtGdiCreateRectRgn(0, 0, 0, 0);
1271 NtGdiCombineRgn(ExposedRgn
, VisBefore
, NULL
, RGN_COPY
);
1272 NtGdiOffsetRgn(ExposedRgn
, OldWindowRect
.left
- NewWindowRect
.left
,
1273 OldWindowRect
.top
- NewWindowRect
.top
);
1274 if (VisAfter
!= NULL
)
1275 RgnType
= NtGdiCombineRgn(ExposedRgn
, ExposedRgn
, VisAfter
, RGN_DIFF
);
1277 RgnType
= SIMPLEREGION
;
1279 if (RgnType
!= ERROR
&& RgnType
!= NULLREGION
)
1281 co_VIS_WindowLayoutChanged(Window
, ExposedRgn
);
1283 GreDeleteObject(ExposedRgn
);
1284 GreDeleteObject(VisBefore
);
1287 if (VisAfter
!= NULL
)
1289 GreDeleteObject(VisAfter
);
1292 if (!(WinPos
.flags
& SWP_NOACTIVATE
))
1294 if ((Window
->Wnd
->style
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1296 co_IntSendMessage(WinPos
.hwnd
, WM_CHILDACTIVATE
, 0, 0);
1300 co_IntSetForegroundWindow(Window
);
1305 if ((WinPos
.flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOPOSCHANGE
)
1306 co_IntPostOrSendMessage(WinPos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
) &WinPos
);
1312 co_WinPosGetNonClientSize(PWINDOW_OBJECT Window
, RECT
* WindowRect
, RECT
* ClientRect
)
1316 ASSERT_REFS_CO(Window
);
1318 *ClientRect
= *WindowRect
;
1319 Result
= co_IntSendMessage(Window
->hSelf
, WM_NCCALCSIZE
, FALSE
, (LPARAM
) ClientRect
);
1321 FixClientRect(ClientRect
, WindowRect
);
1327 co_WinPosShowWindow(PWINDOW_OBJECT Window
, INT Cmd
)
1336 ASSERT_REFS_CO(Window
);
1339 if (!Wnd
) return FALSE
;
1341 WasVisible
= (Wnd
->style
& WS_VISIBLE
) != 0;
1351 Swp
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
1352 if (Window
->hSelf
!= UserGetActiveWindow())
1353 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1357 case SW_SHOWMINNOACTIVE
:
1358 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1360 case SW_SHOWMINIMIZED
:
1361 Swp
|= SWP_SHOWWINDOW
;
1365 Swp
|= SWP_NOACTIVATE
;
1366 if (!(Wnd
->style
& WS_MINIMIZE
))
1368 Swp
|= co_WinPosMinMaximize(Window
, SW_MINIMIZE
, &NewPos
) |
1373 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1376 Swp
|= SWP_FRAMECHANGED
;
1382 case SW_SHOWMAXIMIZED
:
1384 Swp
|= SWP_SHOWWINDOW
;
1385 if (!(Wnd
->style
& WS_MAXIMIZE
))
1387 Swp
|= co_WinPosMinMaximize(Window
, SW_MAXIMIZE
, &NewPos
) |
1392 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1395 Swp
|= SWP_FRAMECHANGED
;
1402 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1405 if (WasVisible
) return(TRUE
); // Nothing to do!
1406 Swp
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
1407 /* Don't activate the topmost window. */
1410 case SW_SHOWNOACTIVATE
:
1411 //Swp |= SWP_NOZORDER;
1412 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1415 case SW_SHOWDEFAULT
:
1417 Swp
|= SWP_SHOWWINDOW
;
1418 if (Wnd
->style
& (WS_MINIMIZE
| WS_MAXIMIZE
))
1420 Swp
|= co_WinPosMinMaximize(Window
, SW_RESTORE
, &NewPos
) |
1425 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1428 Swp
|= SWP_FRAMECHANGED
;
1434 ShowFlag
= (Cmd
!= SW_HIDE
);
1436 if (ShowFlag
!= WasVisible
)
1438 co_IntSendMessage(Window
->hSelf
, WM_SHOWWINDOW
, ShowFlag
, 0);
1441 /* We can't activate a child window */
1442 if ((Wnd
->style
& WS_CHILD
) &&
1443 !(Wnd
->ExStyle
& WS_EX_MDICHILD
))
1445 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1448 co_WinPosSetWindowPos(Window
, 0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
)
1449 ? HWND_TOPMOST
: HWND_TOP
,
1450 NewPos
.left
, NewPos
.top
, NewPos
.right
, NewPos
.bottom
, LOWORD(Swp
));
1454 PWINDOW_OBJECT ThreadFocusWindow
;
1456 /* FIXME: This will cause the window to be activated irrespective
1457 * of whether it is owned by the same thread. Has to be done
1461 if (Window
->hSelf
== UserGetActiveWindow())
1463 co_WinPosActivateOtherWindow(Window
);
1468 ThreadFocusWindow
= UserGetWindowObject(IntGetThreadFocusWindow());
1470 /* Revert focus to parent */
1471 if (ThreadFocusWindow
&& (Window
== ThreadFocusWindow
||
1472 IntIsChildWindow(Window
, ThreadFocusWindow
)))
1474 //faxme: as long as we have ref on Window, we also, indirectly, have ref on parent...
1475 co_UserSetFocus(Window
->Parent
);
1479 /* FIXME: Check for window destruction. */
1481 if ((Window
->Flags
& WINDOWOBJECT_NEED_SIZE
) &&
1482 !(Window
->Status
& WINDOWSTATUS_DESTROYING
))
1484 WPARAM wParam
= SIZE_RESTORED
;
1486 Window
->Flags
&= ~WINDOWOBJECT_NEED_SIZE
;
1487 if (Wnd
->style
& WS_MAXIMIZE
)
1489 wParam
= SIZE_MAXIMIZED
;
1491 else if (Wnd
->style
& WS_MINIMIZE
)
1493 wParam
= SIZE_MINIMIZED
;
1496 co_IntSendMessage(Window
->hSelf
, WM_SIZE
, wParam
,
1497 MAKELONG(Wnd
->rcClient
.right
-
1499 Wnd
->rcClient
.bottom
-
1500 Wnd
->rcClient
.top
));
1501 co_IntSendMessage(Window
->hSelf
, WM_MOVE
, 0,
1502 MAKELONG(Wnd
->rcClient
.left
,
1503 Wnd
->rcClient
.top
));
1504 IntEngWindowChanged(Window
, WOC_RGN_CLIENT
);
1508 /* Activate the window if activation is not requested and the window is not minimized */
1510 if (!(Swp & (SWP_NOACTIVATE | SWP_HIDEWINDOW)) && !(Window->style & WS_MINIMIZE))
1512 WinPosChangeActiveWindow(Wnd, FALSE);
1521 /* find child of 'parent' that contains the given point (in parent-relative coords) */
1522 PWINDOW_OBJECT
child_window_from_point(PWINDOW_OBJECT parent
, int x
, int y
)
1524 PWINDOW_OBJECT Wnd
;// = parent->FirstChild;
1526 // LIST_FOR_EACH_ENTRY( Wnd, &parent->children, struct window, entry )
1527 for (Wnd
= parent
->FirstChild
; Wnd
; Wnd
= Wnd
->NextSibling
)
1529 if (!IntPtInWindow( Wnd
, x
, y
)) continue; /* skip it */
1531 /* if window is minimized or disabled, return at once */
1532 if (Wnd
->style
& (WS_MINIMIZE
|WS_DISABLED
)) return Wnd
;
1534 /* if point is not in client area, return at once */
1535 if (x
< Wnd
->rcClient
.left
|| x
>= Wnd
->rcClient
.right
||
1536 y
< Wnd
->rcClient
.top
|| y
>= Wnd
->rcClient
.bottom
)
1539 return child_window_from_point( Wnd
, x
- Wnd
->rcClient
.left
, y
- Wnd
->rcClient
.top
);
1541 return parent
; /* not found any child */
1545 /* wine server: child_window_from_point
1547 Caller must dereference the "returned" Window
1551 co_WinPosSearchChildren(
1552 PWINDOW_OBJECT ScopeWin
,
1553 PUSER_MESSAGE_QUEUE OnlyHitTests
,
1555 PWINDOW_OBJECT
* Window
,
1559 PWINDOW_OBJECT Current
;
1562 USER_REFERENCE_ENTRY Ref
;
1564 ASSERT_REFS_CO(ScopeWin
);
1566 if ((List
= IntWinListChildren(ScopeWin
)))
1568 for (phWnd
= List
; *phWnd
; ++phWnd
)
1570 if (!(Current
= UserGetWindowObject(*phWnd
)))
1572 CurrentWnd
= Current
->Wnd
;
1574 if (!(CurrentWnd
->style
& WS_VISIBLE
))
1579 if ((CurrentWnd
->style
& (WS_POPUP
| WS_CHILD
| WS_DISABLED
)) ==
1580 (WS_CHILD
| WS_DISABLED
))
1585 if (!IntPtInWindow(Current
, Point
->x
, Point
->y
))
1590 if (*Window
) UserDereferenceObject(*Window
);
1592 UserReferenceObject(*Window
);
1594 if (CurrentWnd
->style
& WS_MINIMIZE
)
1596 *HitTest
= HTCAPTION
;
1600 if (CurrentWnd
->style
& WS_DISABLED
)
1606 UserRefObjectCo(Current
, &Ref
);
1608 if (OnlyHitTests
&& (Current
->MessageQueue
== OnlyHitTests
))
1610 *HitTest
= co_IntSendMessage(Current
->hSelf
, WM_NCHITTEST
, 0,
1611 MAKELONG(Point
->x
, Point
->y
));
1612 if ((*HitTest
) == (USHORT
)HTTRANSPARENT
)
1614 UserDerefObjectCo(Current
);
1619 *HitTest
= HTCLIENT
;
1621 if (Point
->x
>= CurrentWnd
->rcClient
.left
&&
1622 Point
->x
< CurrentWnd
->rcClient
.right
&&
1623 Point
->y
>= CurrentWnd
->rcClient
.top
&&
1624 Point
->y
< CurrentWnd
->rcClient
.bottom
)
1626 co_WinPosSearchChildren(Current
, OnlyHitTests
, Point
, Window
, HitTest
);
1629 UserDerefObjectCo(Current
);
1637 /* wine: WINPOS_WindowFromPoint */
1639 co_WinPosWindowFromPoint(PWINDOW_OBJECT ScopeWin
, PUSER_MESSAGE_QUEUE OnlyHitTests
, POINT
*WinPoint
,
1640 PWINDOW_OBJECT
* Window
)
1642 HWND DesktopWindowHandle
;
1643 PWINDOW_OBJECT DesktopWindow
;
1644 POINT Point
= *WinPoint
;
1647 ASSERT_REFS_CO(ScopeWin
);
1653 DPRINT1("WinPosWindowFromPoint(): ScopeWin == NULL!\n");
1657 if (ScopeWin
->Wnd
->style
& WS_DISABLED
)
1662 /* Translate the point to the space of the scope window. */
1663 DesktopWindowHandle
= IntGetDesktopWindow();
1664 if((DesktopWindowHandle
!= ScopeWin
->hSelf
) &&
1665 (DesktopWindow
= UserGetWindowObject(DesktopWindowHandle
)))
1667 Point
.x
+= ScopeWin
->Wnd
->rcClient
.left
- DesktopWindow
->Wnd
->rcClient
.left
;
1668 Point
.y
+= ScopeWin
->Wnd
->rcClient
.top
- DesktopWindow
->Wnd
->rcClient
.top
;
1671 HitTest
= HTNOWHERE
;
1673 co_WinPosSearchChildren(ScopeWin
, OnlyHitTests
, &Point
, Window
, &HitTest
);
1675 return ((*Window
) ? HitTest
: HTNOWHERE
);
1680 NtUserGetMinMaxInfo(
1682 MINMAXINFO
*MinMaxInfo
,
1686 PWINDOW_OBJECT Window
= NULL
;
1688 MINMAXINFO SafeMinMax
;
1691 USER_REFERENCE_ENTRY Ref
;
1693 DPRINT("Enter NtUserGetMinMaxInfo\n");
1694 UserEnterExclusive();
1696 if(!(Window
= UserGetWindowObject(hWnd
)))
1702 UserRefObjectCo(Window
, &Ref
);
1705 Size
.x
= Window
->Wnd
->rcWindow
.left
;
1706 Size
.y
= Window
->Wnd
->rcWindow
.top
;
1707 WinPosInitInternalPos(Window
, &Size
,
1712 co_WinPosGetMinMaxInfo(Window
, &SafeMinMax
.ptMaxSize
, &SafeMinMax
.ptMaxPosition
,
1713 &SafeMinMax
.ptMinTrackSize
, &SafeMinMax
.ptMaxTrackSize
);
1717 WinPosFillMinMaxInfoStruct(Window
, &SafeMinMax
);
1719 Status
= MmCopyToCaller(MinMaxInfo
, &SafeMinMax
, sizeof(MINMAXINFO
));
1720 if(!NT_SUCCESS(Status
))
1722 SetLastNtError(Status
);
1730 if (Window
) UserDerefObjectCo(Window
);
1732 DPRINT("Leave NtUserGetMinMaxInfo, ret=%i\n", ret
);