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
->spwndNext
)) 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
->spwndParent
;
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
->state
|= WINDOWOBJECT_RESTOREMAX
;
329 Wnd
->style
&= ~WS_MAXIMIZE
;
333 Window
->state
&= ~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
->state
& 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
->spwndParent
;
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
->spwndParent
;
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
->spwndChild
);
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
->spwndChild
; Child
; Child
= Child
->spwndNext
)
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
->spwndParent
;
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
)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
&& 0 != (Sibling
->Wnd
->ExStyle
& WS_EX_TOPMOST
))
995 InsertAfterWindow
= Sibling
;
996 Sibling
= Sibling
->spwndNext
;
998 if (NULL
!= InsertAfterWindow
)
1000 UserReferenceObject(InsertAfterWindow
);
1003 else if (WinPos
.hwndInsertAfter
== HWND_BOTTOM
)
1005 if(ParentWindow
->spwndChild
)
1007 InsertAfterWindow
= ParentWindow
->spwndChild
;
1009 if(InsertAfterWindow
)
1011 while (InsertAfterWindow
->spwndNext
)
1012 InsertAfterWindow
= InsertAfterWindow
->spwndNext
;
1015 UserReferenceObject(InsertAfterWindow
);
1018 InsertAfterWindow
= NULL
;
1021 InsertAfterWindow
= IntGetWindowObject(WinPos
.hwndInsertAfter
);
1022 /* Do nothing if hwndInsertAfter is HWND_BOTTOM and Window is already
1024 if (InsertAfterWindow
!= Window
)
1026 IntUnlinkWindow(Window
);
1027 IntLinkWindow(Window
, ParentWindow
, InsertAfterWindow
);
1029 if (InsertAfterWindow
!= NULL
)
1030 UserDereferenceObject(InsertAfterWindow
);
1031 if ((HWND_TOPMOST
== WinPos
.hwndInsertAfter
)
1032 || (0 != (Window
->Wnd
->ExStyle
& WS_EX_TOPMOST
)
1033 && NULL
!= Window
->spwndPrev
1034 && 0 != (Window
->spwndPrev
->Wnd
->ExStyle
& WS_EX_TOPMOST
))
1035 || (NULL
!= Window
->spwndNext
1036 && 0 != (Window
->spwndNext
->Wnd
->ExStyle
& WS_EX_TOPMOST
)))
1038 Window
->Wnd
->ExStyle
|= WS_EX_TOPMOST
;
1042 Window
->Wnd
->ExStyle
&= ~ WS_EX_TOPMOST
;
1048 if (!Window
->Wnd
) return FALSE
;
1050 OldWindowRect
= Window
->Wnd
->rcWindow
;
1051 OldClientRect
= Window
->Wnd
->rcClient
;
1053 if (OldClientRect
.bottom
- OldClientRect
.top
==
1054 NewClientRect
.bottom
- NewClientRect
.top
)
1056 WvrFlags
&= ~WVR_VREDRAW
;
1059 if (OldClientRect
.right
- OldClientRect
.left
==
1060 NewClientRect
.right
- NewClientRect
.left
)
1062 WvrFlags
&= ~WVR_HREDRAW
;
1065 /* FIXME: Actually do something with WVR_VALIDRECTS */
1067 if (NewClientRect
.left
!= OldClientRect
.left
||
1068 NewClientRect
.top
!= OldClientRect
.top
)
1070 WinPosInternalMoveWindow(Window
,
1071 NewClientRect
.left
- OldClientRect
.left
,
1072 NewClientRect
.top
- OldClientRect
.top
);
1075 Window
->Wnd
->rcWindow
= NewWindowRect
;
1076 Window
->Wnd
->rcClient
= NewClientRect
;
1078 if (!(WinPos
.flags
& SWP_SHOWWINDOW
) && (WinPos
.flags
& SWP_HIDEWINDOW
))
1080 /* Clear the update region */
1081 co_UserRedrawWindow(Window
, NULL
, 0, RDW_VALIDATE
| RDW_NOFRAME
|
1082 RDW_NOERASE
| RDW_NOINTERNALPAINT
| RDW_ALLCHILDREN
);
1083 if ((Window
->Wnd
->style
& WS_VISIBLE
) &&
1084 Window
->spwndParent
== UserGetDesktopWindow())
1086 co_IntShellHookNotify(HSHELL_WINDOWDESTROYED
, (LPARAM
)Window
->hSelf
);
1088 Window
->Wnd
->style
&= ~WS_VISIBLE
;
1090 else if (WinPos
.flags
& SWP_SHOWWINDOW
)
1092 if (!(Window
->Wnd
->style
& WS_VISIBLE
) &&
1093 Window
->spwndParent
== UserGetDesktopWindow())
1095 co_IntShellHookNotify(HSHELL_WINDOWCREATED
, (LPARAM
)Window
->hSelf
);
1097 Window
->Wnd
->style
|= WS_VISIBLE
;
1100 if (Window
->UpdateRegion
!= NULL
&& Window
->UpdateRegion
!= (HRGN
)1)
1102 NtGdiOffsetRgn(Window
->UpdateRegion
,
1103 NewWindowRect
.left
- OldWindowRect
.left
,
1104 NewWindowRect
.top
- OldWindowRect
.top
);
1107 DceResetActiveDCEs(Window
);
1109 if (!(WinPos
.flags
& SWP_NOREDRAW
))
1111 /* Determine the new visible region */
1112 VisAfter
= VIS_ComputeVisibleRegion(Window
, FALSE
, FALSE
, TRUE
);
1115 if (VisAfter
!= NULL
&& (VisRgn
= (PROSRGNDATA
)RGNOBJAPI_Lock(VisAfter
, NULL
)) &&
1116 REGION_GetRgnBox(VisRgn
, &TempRect
) == NULLREGION
)
1118 RGNOBJAPI_Unlock(VisRgn
);
1119 GreDeleteObject(VisAfter
);
1124 RGNOBJAPI_Unlock(VisRgn
);
1125 NtGdiOffsetRgn(VisAfter
, -Window
->Wnd
->rcWindow
.left
, -Window
->Wnd
->rcWindow
.top
);
1129 * Determine which pixels can be copied from the old window position
1130 * to the new. Those pixels must be visible in both the old and new
1131 * position. Also, check the class style to see if the windows of this
1132 * class need to be completely repainted on (horizontal/vertical) size
1135 if (VisBefore
!= NULL
&& VisAfter
!= NULL
&& !(WinPos
.flags
& SWP_NOCOPYBITS
) &&
1136 ((WinPos
.flags
& SWP_NOSIZE
) || !(WvrFlags
& WVR_REDRAW
)) &&
1137 !(Window
->Wnd
->ExStyle
& WS_EX_TRANSPARENT
))
1139 CopyRgn
= NtGdiCreateRectRgn(0, 0, 0, 0);
1140 RgnType
= NtGdiCombineRgn(CopyRgn
, VisAfter
, VisBefore
, RGN_AND
);
1143 * If this is (also) a window resize, the whole nonclient area
1144 * needs to be repainted. So we limit the copy to the client area,
1145 * 'cause there is no use in copying it (would possibly cause
1146 * "flashing" too). However, if the copy region is already empty,
1147 * we don't have to crop (can't take anything away from an empty
1150 if (!(WinPos
.flags
& SWP_NOSIZE
) && RgnType
!= ERROR
&&
1151 RgnType
!= NULLREGION
)
1153 PROSRGNDATA pCopyRgn
;
1154 RECTL ORect
= OldClientRect
;
1155 RECTL NRect
= NewClientRect
;
1156 RECTL_vOffsetRect(&ORect
, - OldWindowRect
.left
, - OldWindowRect
.top
);
1157 RECTL_vOffsetRect(&NRect
, - NewWindowRect
.left
, - NewWindowRect
.top
);
1158 RECTL_bIntersectRect(&CopyRect
, &ORect
, &NRect
);
1159 pCopyRgn
= RGNOBJAPI_Lock(CopyRgn
, NULL
);
1160 REGION_CropAndOffsetRegion(pCopyRgn
, pCopyRgn
, &CopyRect
, NULL
);
1161 RGNOBJAPI_Unlock(pCopyRgn
);
1164 /* No use in copying bits which are in the update region. */
1165 if (Window
->UpdateRegion
!= NULL
)
1167 NtGdiOffsetRgn(CopyRgn
, NewWindowRect
.left
, NewWindowRect
.top
);
1168 NtGdiCombineRgn(CopyRgn
, CopyRgn
, Window
->UpdateRegion
, RGN_DIFF
);
1169 NtGdiOffsetRgn(CopyRgn
, -NewWindowRect
.left
, -NewWindowRect
.top
);
1173 * Now, get the bounding box of the copy region. If it's empty
1174 * there's nothing to copy. Also, it's no use copying bits onto
1177 if ((VisRgn
= (PROSRGNDATA
)RGNOBJAPI_Lock(CopyRgn
, NULL
)) &&
1178 REGION_GetRgnBox(VisRgn
, &CopyRect
) == NULLREGION
)
1180 /* Nothing to copy, clean up */
1181 RGNOBJAPI_Unlock(VisRgn
);
1182 GreDeleteObject(CopyRgn
);
1185 else if (OldWindowRect
.left
!= NewWindowRect
.left
||
1186 OldWindowRect
.top
!= NewWindowRect
.top
)
1190 RGNOBJAPI_Unlock(VisRgn
);
1194 * Small trick here: there is no function to bitblt a region. So
1195 * we set the region as the clipping region, take the bounding box
1196 * of the region and bitblt that. Since nothing outside the clipping
1197 * region is copied, this has the effect of bitblt'ing the region.
1199 * Since NtUserGetDCEx takes ownership of the clip region, we need
1200 * to create a copy of CopyRgn and pass that. We need CopyRgn later
1202 NtGdiOffsetRgn(CopyRgn
, NewWindowRect
.left
, NewWindowRect
.top
);
1203 Dc
= UserGetDCEx(Window
, CopyRgn
, DCX_WINDOW
| DCX_CACHE
|
1204 DCX_INTERSECTRGN
| DCX_CLIPSIBLINGS
|
1207 CopyRect
.left
, CopyRect
.top
, CopyRect
.right
- CopyRect
.left
,
1208 CopyRect
.bottom
- CopyRect
.top
, Dc
,
1209 CopyRect
.left
+ (OldWindowRect
.left
- NewWindowRect
.left
),
1210 CopyRect
.top
+ (OldWindowRect
.top
- NewWindowRect
.top
), SRCCOPY
, 0, 0);
1211 UserReleaseDC(Window
, Dc
, FALSE
);
1212 IntValidateParent(Window
, CopyRgn
, FALSE
);
1213 NtGdiOffsetRgn(CopyRgn
, -NewWindowRect
.left
, -NewWindowRect
.top
);
1217 RGNOBJAPI_Unlock(VisRgn
);
1225 /* We need to redraw what wasn't visible before */
1226 if (VisAfter
!= NULL
)
1228 DirtyRgn
= NtGdiCreateRectRgn(0, 0, 0, 0);
1229 if (CopyRgn
!= NULL
)
1231 RgnType
= NtGdiCombineRgn(DirtyRgn
, VisAfter
, CopyRgn
, RGN_DIFF
);
1235 RgnType
= NtGdiCombineRgn(DirtyRgn
, VisAfter
, 0, RGN_COPY
);
1237 if (RgnType
!= ERROR
&& RgnType
!= NULLREGION
)
1240 NtGdiOffsetRgn(DirtyRgn, Window->rcWindow.left, Window->rcWindow.top);
1241 IntInvalidateWindows(Window, DirtyRgn,
1242 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
1244 GreDeleteObject(DirtyRgn);
1247 PWINDOW_OBJECT Parent
= Window
->spwndParent
;
1249 NtGdiOffsetRgn(DirtyRgn
,
1250 Window
->Wnd
->rcWindow
.left
,
1251 Window
->Wnd
->rcWindow
.top
);
1252 if ((Window
->Wnd
->style
& WS_CHILD
) &&
1254 !(Parent
->Wnd
->style
& WS_CLIPCHILDREN
))
1256 IntInvalidateWindows(Parent
, DirtyRgn
,
1257 RDW_ERASE
| RDW_INVALIDATE
);
1258 co_IntPaintWindows(Parent
, RDW_ERASENOW
, FALSE
);
1262 IntInvalidateWindows(Window
, DirtyRgn
,
1263 RDW_ERASE
| RDW_FRAME
| RDW_INVALIDATE
| RDW_ALLCHILDREN
);
1266 GreDeleteObject(DirtyRgn
);
1269 if (CopyRgn
!= NULL
)
1271 GreDeleteObject(CopyRgn
);
1274 /* Expose what was covered before but not covered anymore */
1275 if (VisBefore
!= NULL
)
1277 ExposedRgn
= NtGdiCreateRectRgn(0, 0, 0, 0);
1278 NtGdiCombineRgn(ExposedRgn
, VisBefore
, NULL
, RGN_COPY
);
1279 NtGdiOffsetRgn(ExposedRgn
, OldWindowRect
.left
- NewWindowRect
.left
,
1280 OldWindowRect
.top
- NewWindowRect
.top
);
1281 if (VisAfter
!= NULL
)
1282 RgnType
= NtGdiCombineRgn(ExposedRgn
, ExposedRgn
, VisAfter
, RGN_DIFF
);
1284 RgnType
= SIMPLEREGION
;
1286 if (RgnType
!= ERROR
&& RgnType
!= NULLREGION
)
1288 co_VIS_WindowLayoutChanged(Window
, ExposedRgn
);
1290 GreDeleteObject(ExposedRgn
);
1291 GreDeleteObject(VisBefore
);
1294 if (VisAfter
!= NULL
)
1296 GreDeleteObject(VisAfter
);
1299 if (!(WinPos
.flags
& SWP_NOACTIVATE
))
1301 if ((Window
->Wnd
->style
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1303 co_IntSendMessage(WinPos
.hwnd
, WM_CHILDACTIVATE
, 0, 0);
1307 co_IntSetForegroundWindow(Window
);
1312 if ((WinPos
.flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOPOSCHANGE
)
1313 co_IntPostOrSendMessage(WinPos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
) &WinPos
);
1319 co_WinPosGetNonClientSize(PWINDOW_OBJECT Window
, RECT
* WindowRect
, RECT
* ClientRect
)
1323 ASSERT_REFS_CO(Window
);
1325 *ClientRect
= *WindowRect
;
1326 Result
= co_IntSendMessage(Window
->hSelf
, WM_NCCALCSIZE
, FALSE
, (LPARAM
) ClientRect
);
1328 FixClientRect(ClientRect
, WindowRect
);
1334 co_WinPosShowWindow(PWINDOW_OBJECT Window
, INT Cmd
)
1343 ASSERT_REFS_CO(Window
);
1346 if (!Wnd
) return FALSE
;
1348 WasVisible
= (Wnd
->style
& WS_VISIBLE
) != 0;
1358 Swp
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
1359 if (Window
->hSelf
!= UserGetActiveWindow())
1360 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1364 case SW_SHOWMINNOACTIVE
:
1365 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1367 case SW_SHOWMINIMIZED
:
1368 Swp
|= SWP_SHOWWINDOW
;
1372 Swp
|= SWP_NOACTIVATE
;
1373 if (!(Wnd
->style
& WS_MINIMIZE
))
1375 Swp
|= co_WinPosMinMaximize(Window
, SW_MINIMIZE
, &NewPos
) |
1380 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1383 Swp
|= SWP_FRAMECHANGED
;
1389 case SW_SHOWMAXIMIZED
:
1391 Swp
|= SWP_SHOWWINDOW
;
1392 if (!(Wnd
->style
& WS_MAXIMIZE
))
1394 Swp
|= co_WinPosMinMaximize(Window
, SW_MAXIMIZE
, &NewPos
) |
1399 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1402 Swp
|= SWP_FRAMECHANGED
;
1409 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1412 if (WasVisible
) return(TRUE
); // Nothing to do!
1413 Swp
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
1414 /* Don't activate the topmost window. */
1417 case SW_SHOWNOACTIVATE
:
1418 //Swp |= SWP_NOZORDER;
1419 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1422 case SW_SHOWDEFAULT
:
1424 Swp
|= SWP_SHOWWINDOW
;
1425 if (Wnd
->style
& (WS_MINIMIZE
| WS_MAXIMIZE
))
1427 Swp
|= co_WinPosMinMaximize(Window
, SW_RESTORE
, &NewPos
) |
1432 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1435 Swp
|= SWP_FRAMECHANGED
;
1441 ShowFlag
= (Cmd
!= SW_HIDE
);
1443 if (ShowFlag
!= WasVisible
)
1445 co_IntSendMessage(Window
->hSelf
, WM_SHOWWINDOW
, ShowFlag
, 0);
1448 /* We can't activate a child window */
1449 if ((Wnd
->style
& WS_CHILD
) &&
1450 !(Wnd
->ExStyle
& WS_EX_MDICHILD
))
1452 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1455 co_WinPosSetWindowPos(Window
, 0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
)
1456 ? HWND_TOPMOST
: HWND_TOP
,
1457 NewPos
.left
, NewPos
.top
, NewPos
.right
, NewPos
.bottom
, LOWORD(Swp
));
1461 PWINDOW_OBJECT ThreadFocusWindow
;
1463 /* FIXME: This will cause the window to be activated irrespective
1464 * of whether it is owned by the same thread. Has to be done
1468 if (Window
->hSelf
== UserGetActiveWindow())
1470 co_WinPosActivateOtherWindow(Window
);
1475 ThreadFocusWindow
= UserGetWindowObject(IntGetThreadFocusWindow());
1477 /* Revert focus to parent */
1478 if (ThreadFocusWindow
&& (Window
== ThreadFocusWindow
||
1479 IntIsChildWindow(Window
, ThreadFocusWindow
)))
1481 //faxme: as long as we have ref on Window, we also, indirectly, have ref on parent...
1482 co_UserSetFocus(Window
->spwndParent
);
1486 /* FIXME: Check for window destruction. */
1488 if ((Window
->state
& WINDOWOBJECT_NEED_SIZE
) &&
1489 !(Window
->state
& WINDOWSTATUS_DESTROYING
))
1491 WPARAM wParam
= SIZE_RESTORED
;
1493 Window
->state
&= ~WINDOWOBJECT_NEED_SIZE
;
1494 if (Wnd
->style
& WS_MAXIMIZE
)
1496 wParam
= SIZE_MAXIMIZED
;
1498 else if (Wnd
->style
& WS_MINIMIZE
)
1500 wParam
= SIZE_MINIMIZED
;
1503 co_IntSendMessage(Window
->hSelf
, WM_SIZE
, wParam
,
1504 MAKELONG(Wnd
->rcClient
.right
-
1506 Wnd
->rcClient
.bottom
-
1507 Wnd
->rcClient
.top
));
1508 co_IntSendMessage(Window
->hSelf
, WM_MOVE
, 0,
1509 MAKELONG(Wnd
->rcClient
.left
,
1510 Wnd
->rcClient
.top
));
1511 IntEngWindowChanged(Window
, WOC_RGN_CLIENT
);
1515 /* Activate the window if activation is not requested and the window is not minimized */
1517 if (!(Swp & (SWP_NOACTIVATE | SWP_HIDEWINDOW)) && !(Window->style & WS_MINIMIZE))
1519 WinPosChangeActiveWindow(Wnd, FALSE);
1528 /* find child of 'parent' that contains the given point (in parent-relative coords) */
1529 PWINDOW_OBJECT
child_window_from_point(PWINDOW_OBJECT parent
, int x
, int y
)
1531 PWINDOW_OBJECT Wnd
;// = parent->spwndChild;
1533 // LIST_FOR_EACH_ENTRY( Wnd, &parent->children, struct window, entry )
1534 for (Wnd
= parent
->spwndChild
; Wnd
; Wnd
= Wnd
->spwndNext
)
1536 if (!IntPtInWindow( Wnd
, x
, y
)) continue; /* skip it */
1538 /* if window is minimized or disabled, return at once */
1539 if (Wnd
->style
& (WS_MINIMIZE
|WS_DISABLED
)) return Wnd
;
1541 /* if point is not in client area, return at once */
1542 if (x
< Wnd
->rcClient
.left
|| x
>= Wnd
->rcClient
.right
||
1543 y
< Wnd
->rcClient
.top
|| y
>= Wnd
->rcClient
.bottom
)
1546 return child_window_from_point( Wnd
, x
- Wnd
->rcClient
.left
, y
- Wnd
->rcClient
.top
);
1548 return parent
; /* not found any child */
1552 /* wine server: child_window_from_point
1554 Caller must dereference the "returned" Window
1558 co_WinPosSearchChildren(
1559 PWINDOW_OBJECT ScopeWin
,
1560 PUSER_MESSAGE_QUEUE OnlyHitTests
,
1562 PWINDOW_OBJECT
* Window
,
1566 PWINDOW_OBJECT Current
;
1569 USER_REFERENCE_ENTRY Ref
;
1571 ASSERT_REFS_CO(ScopeWin
);
1573 if ((List
= IntWinListChildren(ScopeWin
)))
1575 for (phWnd
= List
; *phWnd
; ++phWnd
)
1577 if (!(Current
= UserGetWindowObject(*phWnd
)))
1579 CurrentWnd
= Current
->Wnd
;
1581 if (!(CurrentWnd
->style
& WS_VISIBLE
))
1586 if ((CurrentWnd
->style
& (WS_POPUP
| WS_CHILD
| WS_DISABLED
)) ==
1587 (WS_CHILD
| WS_DISABLED
))
1592 if (!IntPtInWindow(Current
, Point
->x
, Point
->y
))
1597 if (*Window
) UserDereferenceObject(*Window
);
1599 UserReferenceObject(*Window
);
1601 if (CurrentWnd
->style
& WS_MINIMIZE
)
1603 *HitTest
= HTCAPTION
;
1607 if (CurrentWnd
->style
& WS_DISABLED
)
1613 UserRefObjectCo(Current
, &Ref
);
1615 if (OnlyHitTests
&& (Current
->MessageQueue
== OnlyHitTests
))
1617 *HitTest
= co_IntSendMessage(Current
->hSelf
, WM_NCHITTEST
, 0,
1618 MAKELONG(Point
->x
, Point
->y
));
1619 if ((*HitTest
) == (USHORT
)HTTRANSPARENT
)
1621 UserDerefObjectCo(Current
);
1626 *HitTest
= HTCLIENT
;
1628 if (Point
->x
>= CurrentWnd
->rcClient
.left
&&
1629 Point
->x
< CurrentWnd
->rcClient
.right
&&
1630 Point
->y
>= CurrentWnd
->rcClient
.top
&&
1631 Point
->y
< CurrentWnd
->rcClient
.bottom
)
1633 co_WinPosSearchChildren(Current
, OnlyHitTests
, Point
, Window
, HitTest
);
1636 UserDerefObjectCo(Current
);
1644 /* wine: WINPOS_WindowFromPoint */
1646 co_WinPosWindowFromPoint(PWINDOW_OBJECT ScopeWin
, PUSER_MESSAGE_QUEUE OnlyHitTests
, POINT
*WinPoint
,
1647 PWINDOW_OBJECT
* Window
)
1649 HWND DesktopWindowHandle
;
1650 PWINDOW_OBJECT DesktopWindow
;
1651 POINT Point
= *WinPoint
;
1654 ASSERT_REFS_CO(ScopeWin
);
1660 DPRINT1("WinPosWindowFromPoint(): ScopeWin == NULL!\n");
1664 if (ScopeWin
->Wnd
->style
& WS_DISABLED
)
1669 /* Translate the point to the space of the scope window. */
1670 DesktopWindowHandle
= IntGetDesktopWindow();
1671 if((DesktopWindowHandle
!= ScopeWin
->hSelf
) &&
1672 (DesktopWindow
= UserGetWindowObject(DesktopWindowHandle
)))
1674 Point
.x
+= ScopeWin
->Wnd
->rcClient
.left
- DesktopWindow
->Wnd
->rcClient
.left
;
1675 Point
.y
+= ScopeWin
->Wnd
->rcClient
.top
- DesktopWindow
->Wnd
->rcClient
.top
;
1678 HitTest
= HTNOWHERE
;
1680 co_WinPosSearchChildren(ScopeWin
, OnlyHitTests
, &Point
, Window
, &HitTest
);
1682 return ((*Window
) ? HitTest
: HTNOWHERE
);
1687 NtUserGetMinMaxInfo(
1689 MINMAXINFO
*MinMaxInfo
,
1693 PWINDOW_OBJECT Window
= NULL
;
1695 MINMAXINFO SafeMinMax
;
1698 USER_REFERENCE_ENTRY Ref
;
1700 DPRINT("Enter NtUserGetMinMaxInfo\n");
1701 UserEnterExclusive();
1703 if(!(Window
= UserGetWindowObject(hWnd
)))
1709 UserRefObjectCo(Window
, &Ref
);
1712 Size
.x
= Window
->Wnd
->rcWindow
.left
;
1713 Size
.y
= Window
->Wnd
->rcWindow
.top
;
1714 WinPosInitInternalPos(Window
, &Size
,
1719 co_WinPosGetMinMaxInfo(Window
, &SafeMinMax
.ptMaxSize
, &SafeMinMax
.ptMaxPosition
,
1720 &SafeMinMax
.ptMinTrackSize
, &SafeMinMax
.ptMaxTrackSize
);
1724 WinPosFillMinMaxInfoStruct(Window
, &SafeMinMax
);
1726 Status
= MmCopyToCaller(MinMaxInfo
, &SafeMinMax
, sizeof(MINMAXINFO
));
1727 if(!NT_SUCCESS(Status
))
1729 SetLastNtError(Status
);
1737 if (Window
) UserDerefObjectCo(Window
);
1739 DPRINT("Leave NtUserGetMinMaxInfo, ret=%i\n", ret
);