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(PWND Window
, ULONG Flags
, BOOL Recurse
);
39 IntValidateParent(PWND 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(PWND Window OPTIONAL
, LPPOINT Point
)
60 Window
= Window
? Window
: UserGetWindowObject(IntGetDesktopWindow());
63 Point
->x
= Point
->y
= 0;
66 Point
->x
= Window
->rcClient
.left
;
67 Point
->y
= Window
->rcClient
.top
;
73 UserGetClientOrigin(PWND Window
, LPPOINT Point
)
81 EngSetLastError(ERROR_INVALID_PARAMETER
);
85 Ret
= IntGetClientOrigin(Window
, &pt
);
89 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE
);
93 Status
= MmCopyToCaller(Point
, &pt
, sizeof(POINT
));
94 if(!NT_SUCCESS(Status
))
96 SetLastNtError(Status
);
105 /*******************************************************************
106 * can_activate_window
108 * Check if we can activate the specified window.
111 BOOL FASTCALL
can_activate_window( PWND Wnd OPTIONAL
)
115 if (!Wnd
) return FALSE
;
118 if (!(style
& WS_VISIBLE
) &&
119 Wnd
->head
.pti
->pEThread
->ThreadsProcess
!= CsrProcess
) return FALSE
;
120 if ((style
& WS_MINIMIZE
) &&
121 Wnd
->head
.pti
->pEThread
->ThreadsProcess
!= CsrProcess
) return FALSE
;
122 if ((style
& (WS_POPUP
|WS_CHILD
)) == WS_CHILD
) return FALSE
;
124 /* FIXME: This window could be disable because the child that closed
126 //return !(style & WS_DISABLED);
130 /*******************************************************************
131 * WinPosActivateOtherWindow
133 * Activates window other than pWnd.
136 co_WinPosActivateOtherWindow(PWND Wnd
)
140 USER_REFERENCE_ENTRY Ref
;
144 if (IntIsDesktopWindow(Wnd
))
146 IntSetFocusMessageQueue(NULL
);
150 /* If this is popup window, try to activate the owner first. */
151 if ((Wnd
->style
& WS_POPUP
) && (WndTo
= Wnd
->spwndOwner
))
153 WndTo
= UserGetAncestor( WndTo
, GA_ROOT
);
154 if (can_activate_window(WndTo
)) goto done
;
157 /* Pick a next top-level window. */
158 /* FIXME: Search for non-tooltip windows first. */
162 if (!(WndTo
= WndTo
->spwndNext
)) break;
163 if (can_activate_window( WndTo
)) break;
168 if (WndTo
) UserRefObjectCo(WndTo
, &Ref
);
170 Fg
= UserGetForegroundWindow();
171 if ((!Fg
|| Wnd
->head
.h
== Fg
) && WndTo
)//fixme: ok if WndTo is NULL??
173 /* fixme: wine can pass WndTo=NULL to co_IntSetForegroundWindow. hmm */
174 if (co_IntSetForegroundWindow(WndTo
))
176 UserDerefObjectCo(WndTo
);
181 if (!co_IntSetActiveWindow(WndTo
)) /* ok for WndTo to be NULL here */
182 co_IntSetActiveWindow(0);
184 if (WndTo
) UserDerefObjectCo(WndTo
);
190 co_WinPosArrangeIconicWindows(PWND parent
)
193 INT i
, x
, y
, xspacing
, yspacing
;
194 HWND
*List
= IntWinListChildren(parent
);
196 ASSERT_REFS_CO(parent
);
198 IntGetClientRect( parent
, &rectParent
);
200 y
= rectParent
.bottom
;
202 xspacing
= UserGetSystemMetrics(SM_CXMINSPACING
);
203 yspacing
= UserGetSystemMetrics(SM_CYMINSPACING
);
205 DPRINT("X:%d Y:%d XS:%d YS:%d\n",x
,y
,xspacing
,yspacing
);
207 for( i
= 0; List
[i
]; i
++)
211 if (!(Child
= UserGetWindowObject(List
[i
])))
214 if((Child
->style
& WS_MINIMIZE
) != 0 )
216 USER_REFERENCE_ENTRY Ref
;
217 UserRefObjectCo(Child
, &Ref
);
219 co_WinPosSetWindowPos(Child
, 0, x
+ UserGetSystemMetrics(SM_CXBORDER
),
220 y
- yspacing
- UserGetSystemMetrics(SM_CYBORDER
)
221 , 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
223 UserDerefObjectCo(Child
);
225 if (x
<= rectParent
.right
- xspacing
)
240 WinPosFindIconPos(PWND Window
, POINT
*Pos
)
246 WinPosInitInternalPos(PWND Wnd
, POINT
*pt
, RECTL
*RestoreRect
)
251 if (!Wnd
->InternalPosInitialized
)
255 Parent
= Wnd
->spwndParent
;
258 if(IntIsDesktopWindow(Parent
))
259 UserSystemParametersInfo(SPI_GETWORKAREA
, 0, &WorkArea
, 0);
261 WorkArea
= Parent
->rcClient
;
264 UserSystemParametersInfo(SPI_GETWORKAREA
, 0, &WorkArea
, 0);
266 Wnd
->InternalPos
.NormalRect
= Wnd
->rcWindow
;
267 IntGetWindowBorderMeasures(Wnd
, &XInc
, &YInc
);
268 Wnd
->InternalPos
.MaxPos
.x
= WorkArea
.left
- XInc
;
269 Wnd
->InternalPos
.MaxPos
.y
= WorkArea
.top
- YInc
;
270 Wnd
->InternalPos
.IconPos
.x
= WorkArea
.left
;
271 Wnd
->InternalPos
.IconPos
.y
= WorkArea
.bottom
- UserGetSystemMetrics(SM_CYMINIMIZED
);
273 Wnd
->InternalPosInitialized
= TRUE
;
275 if (Wnd
->style
& WS_MINIMIZE
)
277 Wnd
->InternalPos
.IconPos
= *pt
;
279 else if (Wnd
->style
& WS_MAXIMIZE
)
281 Wnd
->InternalPos
.MaxPos
= *pt
;
283 else if (RestoreRect
!= NULL
)
285 Wnd
->InternalPos
.NormalRect
= *RestoreRect
;
290 co_WinPosMinMaximize(PWND Wnd
, UINT ShowFlag
, RECT
* NewPos
)
297 Size
.x
= Wnd
->rcWindow
.left
;
298 Size
.y
= Wnd
->rcWindow
.top
;
299 WinPosInitInternalPos(Wnd
, &Size
, &Wnd
->rcWindow
);
301 if (co_HOOK_CallHooks( WH_CBT
, HCBT_MINMAX
, (WPARAM
)Wnd
->head
.h
, ShowFlag
))
303 DPRINT1("WinPosMinMaximize WH_CBT Call Hook return!\n");
304 return SWP_NOSIZE
| SWP_NOMOVE
;
306 if (Wnd
->style
& WS_MINIMIZE
)
308 if (!co_IntSendMessageNoWait(Wnd
->head
.h
, WM_QUERYOPEN
, 0, 0))
310 return(SWP_NOSIZE
| SWP_NOMOVE
);
312 SwpFlags
|= SWP_NOCOPYBITS
;
318 if (Wnd
->style
& WS_MAXIMIZE
)
320 Wnd
->state2
|= WNDS2_MAXIMIZEBUTTONDOWN
;
321 Wnd
->style
&= ~WS_MAXIMIZE
;
325 Wnd
->state2
&= ~WNDS2_MAXIMIZEBUTTONDOWN
;
327 co_UserRedrawWindow(Wnd
, NULL
, 0, RDW_VALIDATE
| RDW_NOERASE
|
328 RDW_NOINTERNALPAINT
);
329 Wnd
->style
|= WS_MINIMIZE
;
330 WinPosFindIconPos(Wnd
, &Wnd
->InternalPos
.IconPos
);
331 RECTL_vSetRect(NewPos
, Wnd
->InternalPos
.IconPos
.x
, Wnd
->InternalPos
.IconPos
.y
,
332 UserGetSystemMetrics(SM_CXMINIMIZED
),
333 UserGetSystemMetrics(SM_CYMINIMIZED
));
334 SwpFlags
|= SWP_NOCOPYBITS
;
340 co_WinPosGetMinMaxInfo(Wnd
, &Size
, &Wnd
->InternalPos
.MaxPos
,
342 DPRINT("Maximize: %d,%d %dx%d\n",
343 Wnd
->InternalPos
.MaxPos
.x
, Wnd
->InternalPos
.MaxPos
.y
, Size
.x
, Size
.y
);
344 if (Wnd
->style
& WS_MINIMIZE
)
346 Wnd
->style
&= ~WS_MINIMIZE
;
348 Wnd
->style
|= WS_MAXIMIZE
;
349 RECTL_vSetRect(NewPos
, Wnd
->InternalPos
.MaxPos
.x
, Wnd
->InternalPos
.MaxPos
.y
,
356 if (Wnd
->style
& WS_MINIMIZE
)
358 Wnd
->style
&= ~WS_MINIMIZE
;
359 if (Wnd
->state2
& WNDS2_MAXIMIZEBUTTONDOWN
)
361 co_WinPosGetMinMaxInfo(Wnd
, &Size
,
362 &Wnd
->InternalPos
.MaxPos
, NULL
, NULL
);
363 Wnd
->style
|= WS_MAXIMIZE
;
364 RECTL_vSetRect(NewPos
, Wnd
->InternalPos
.MaxPos
.x
,
365 Wnd
->InternalPos
.MaxPos
.y
, Size
.x
, Size
.y
);
370 *NewPos
= Wnd
->InternalPos
.NormalRect
;
371 NewPos
->right
-= NewPos
->left
;
372 NewPos
->bottom
-= NewPos
->top
;
378 if (!(Wnd
->style
& WS_MAXIMIZE
))
382 Wnd
->style
&= ~WS_MAXIMIZE
;
383 *NewPos
= Wnd
->InternalPos
.NormalRect
;
384 NewPos
->right
-= NewPos
->left
;
385 NewPos
->bottom
-= NewPos
->top
;
394 UserHasWindowEdge(DWORD Style
, DWORD ExStyle
)
396 if (Style
& WS_MINIMIZE
)
398 if (ExStyle
& WS_EX_DLGMODALFRAME
)
400 if (ExStyle
& WS_EX_STATICEDGE
)
402 if (Style
& WS_THICKFRAME
)
405 if (Style
== WS_DLGFRAME
|| Style
== WS_CAPTION
)
411 UserGetWindowBorders(DWORD Style
, DWORD ExStyle
, SIZE
*Size
, BOOL WithClient
)
415 if (UserHasWindowEdge(Style
, ExStyle
))
417 else if (ExStyle
& WS_EX_STATICEDGE
)
419 if ((ExStyle
& WS_EX_CLIENTEDGE
) && WithClient
)
421 if (Style
& WS_CAPTION
|| ExStyle
& WS_EX_DLGMODALFRAME
)
423 Size
->cx
= Size
->cy
= Border
;
424 if ((Style
& WS_THICKFRAME
) && !(Style
& WS_MINIMIZE
))
426 Size
->cx
+= UserGetSystemMetrics(SM_CXFRAME
) - UserGetSystemMetrics(SM_CXDLGFRAME
);
427 Size
->cy
+= UserGetSystemMetrics(SM_CYFRAME
) - UserGetSystemMetrics(SM_CYDLGFRAME
);
429 Size
->cx
*= UserGetSystemMetrics(SM_CXBORDER
);
430 Size
->cy
*= UserGetSystemMetrics(SM_CYBORDER
);
434 UserAdjustWindowRectEx(LPRECT lpRect
,
443 lpRect
->top
-= UserGetSystemMetrics(SM_CYMENU
);
445 if ((dwStyle
& WS_CAPTION
) == WS_CAPTION
)
447 if (dwExStyle
& WS_EX_TOOLWINDOW
)
448 lpRect
->top
-= UserGetSystemMetrics(SM_CYSMCAPTION
);
450 lpRect
->top
-= UserGetSystemMetrics(SM_CYCAPTION
);
452 UserGetWindowBorders(dwStyle
, dwExStyle
, &BorderSize
, TRUE
);
462 co_WinPosGetMinMaxInfo(PWND Window
, POINT
* MaxSize
, POINT
* MaxPos
,
463 POINT
* MinTrack
, POINT
* MaxTrack
)
468 LONG style
= Window
->style
;
470 LONG exstyle
= Window
->ExStyle
;
473 ASSERT_REFS_CO(Window
);
475 /* Compute default values */
477 rc
= Window
->rcWindow
;
478 MinMax
.ptReserved
.x
= rc
.left
;
479 MinMax
.ptReserved
.y
= rc
.top
;
481 if ((style
& WS_CAPTION
) == WS_CAPTION
)
482 adjustedStyle
= style
& ~WS_BORDER
; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
484 adjustedStyle
= style
;
486 if(Window
->spwndParent
)
487 IntGetClientRect(Window
->spwndParent
, &rc
);
488 UserAdjustWindowRectEx(&rc
, adjustedStyle
, ((style
& WS_POPUP
) && Window
->IDMenu
), exstyle
);
493 MinMax
.ptMaxSize
.x
= rc
.right
- rc
.left
;
494 MinMax
.ptMaxSize
.y
= rc
.bottom
- rc
.top
;
495 if (style
& (WS_DLGFRAME
| WS_BORDER
))
497 MinMax
.ptMinTrackSize
.x
= UserGetSystemMetrics(SM_CXMINTRACK
);
498 MinMax
.ptMinTrackSize
.y
= UserGetSystemMetrics(SM_CYMINTRACK
);
502 MinMax
.ptMinTrackSize
.x
= 2 * xinc
;
503 MinMax
.ptMinTrackSize
.y
= 2 * yinc
;
505 MinMax
.ptMaxTrackSize
.x
= UserGetSystemMetrics(SM_CXMAXTRACK
);
506 MinMax
.ptMaxTrackSize
.y
= UserGetSystemMetrics(SM_CYMAXTRACK
);
507 MinMax
.ptMaxPosition
.x
= -xinc
;
508 MinMax
.ptMaxPosition
.y
= -yinc
;
510 //if (!EMPTYPOINT(win->max_pos)) MinMax.ptMaxPosition = win->max_pos;
512 co_IntSendMessage(Window
->head
.h
, WM_GETMINMAXINFO
, 0, (LPARAM
)&MinMax
);
514 /* if the app didn't change the values, adapt them for the current monitor */
515 if ((monitor
= IntGetPrimaryMonitor()))
519 rc_work
= monitor
->rcMonitor
;
521 if (style
& WS_MAXIMIZEBOX
)
523 if ((style
& WS_CAPTION
) == WS_CAPTION
|| !(style
& (WS_CHILD
| WS_POPUP
)))
524 rc_work
= monitor
->rcWork
;
527 if (MinMax
.ptMaxSize
.x
== UserGetSystemMetrics(SM_CXSCREEN
) + 2 * xinc
&&
528 MinMax
.ptMaxSize
.y
== UserGetSystemMetrics(SM_CYSCREEN
) + 2 * yinc
)
530 MinMax
.ptMaxSize
.x
= (rc_work
.right
- rc_work
.left
) + 2 * xinc
;
531 MinMax
.ptMaxSize
.y
= (rc_work
.bottom
- rc_work
.top
) + 2 * yinc
;
533 if (MinMax
.ptMaxPosition
.x
== -xinc
&& MinMax
.ptMaxPosition
.y
== -yinc
)
535 MinMax
.ptMaxPosition
.x
= rc_work
.left
- xinc
;
536 MinMax
.ptMaxPosition
.y
= rc_work
.top
- yinc
;
541 MinMax
.ptMaxTrackSize
.x
= max(MinMax
.ptMaxTrackSize
.x
,
542 MinMax
.ptMinTrackSize
.x
);
543 MinMax
.ptMaxTrackSize
.y
= max(MinMax
.ptMaxTrackSize
.y
,
544 MinMax
.ptMinTrackSize
.y
);
547 *MaxSize
= MinMax
.ptMaxSize
;
549 *MaxPos
= MinMax
.ptMaxPosition
;
551 *MinTrack
= MinMax
.ptMinTrackSize
;
553 *MaxTrack
= MinMax
.ptMaxTrackSize
;
555 return 0; //FIXME: what does it return?
560 FixClientRect(PRECTL ClientRect
, PRECTL WindowRect
)
562 if (ClientRect
->left
< WindowRect
->left
)
564 ClientRect
->left
= WindowRect
->left
;
566 else if (WindowRect
->right
< ClientRect
->left
)
568 ClientRect
->left
= WindowRect
->right
;
570 if (ClientRect
->right
< WindowRect
->left
)
572 ClientRect
->right
= WindowRect
->left
;
574 else if (WindowRect
->right
< ClientRect
->right
)
576 ClientRect
->right
= WindowRect
->right
;
578 if (ClientRect
->top
< WindowRect
->top
)
580 ClientRect
->top
= WindowRect
->top
;
582 else if (WindowRect
->bottom
< ClientRect
->top
)
584 ClientRect
->top
= WindowRect
->bottom
;
586 if (ClientRect
->bottom
< WindowRect
->top
)
588 ClientRect
->bottom
= WindowRect
->top
;
590 else if (WindowRect
->bottom
< ClientRect
->bottom
)
592 ClientRect
->bottom
= WindowRect
->bottom
;
598 co_WinPosDoNCCALCSize(PWND Window
, PWINDOWPOS WinPos
,
599 RECT
* WindowRect
, RECT
* ClientRect
)
604 ASSERT_REFS_CO(Window
);
606 /* Send WM_NCCALCSIZE message to get new client area */
607 if ((WinPos
->flags
& (SWP_FRAMECHANGED
| SWP_NOSIZE
)) != SWP_NOSIZE
)
609 NCCALCSIZE_PARAMS params
;
610 WINDOWPOS winposCopy
;
612 params
.rgrc
[0] = *WindowRect
;
613 params
.rgrc
[1] = Window
->rcWindow
;
614 params
.rgrc
[2] = Window
->rcClient
;
615 Parent
= Window
->spwndParent
;
616 if (0 != (Window
->style
& WS_CHILD
) && Parent
)
618 RECTL_vOffsetRect(&(params
.rgrc
[0]), - Parent
->rcClient
.left
,
619 - Parent
->rcClient
.top
);
620 RECTL_vOffsetRect(&(params
.rgrc
[1]), - Parent
->rcClient
.left
,
621 - Parent
->rcClient
.top
);
622 RECTL_vOffsetRect(&(params
.rgrc
[2]), - Parent
->rcClient
.left
,
623 - Parent
->rcClient
.top
);
625 params
.lppos
= &winposCopy
;
626 winposCopy
= *WinPos
;
628 wvrFlags
= co_IntSendMessageNoWait(Window
->head
.h
, WM_NCCALCSIZE
, TRUE
, (LPARAM
) ¶ms
);
630 /* If the application send back garbage, ignore it */
631 if (params
.rgrc
[0].left
<= params
.rgrc
[0].right
&&
632 params
.rgrc
[0].top
<= params
.rgrc
[0].bottom
)
634 *ClientRect
= params
.rgrc
[0];
635 if ((Window
->style
& WS_CHILD
) && Parent
)
637 RECTL_vOffsetRect(ClientRect
, Parent
->rcClient
.left
,
638 Parent
->rcClient
.top
);
640 FixClientRect(ClientRect
, WindowRect
);
643 /* FIXME: WVR_ALIGNxxx */
645 if (ClientRect
->left
!= Window
->rcClient
.left
||
646 ClientRect
->top
!= Window
->rcClient
.top
)
648 WinPos
->flags
&= ~SWP_NOCLIENTMOVE
;
651 if ((ClientRect
->right
- ClientRect
->left
!=
652 Window
->rcClient
.right
- Window
->rcClient
.left
) ||
653 (ClientRect
->bottom
- ClientRect
->top
!=
654 Window
->rcClient
.bottom
- Window
->rcClient
.top
))
656 WinPos
->flags
&= ~SWP_NOCLIENTSIZE
;
661 if (! (WinPos
->flags
& SWP_NOMOVE
)
662 && (ClientRect
->left
!= Window
->rcClient
.left
||
663 ClientRect
->top
!= Window
->rcClient
.top
))
665 WinPos
->flags
&= ~SWP_NOCLIENTMOVE
;
674 co_WinPosDoWinPosChanging(PWND Window
,
681 ASSERT_REFS_CO(Window
);
683 if (!(WinPos
->flags
& SWP_NOSENDCHANGING
))
685 co_IntSendMessageNoWait(Window
->head
.h
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
) WinPos
);
688 *WindowRect
= Window
->rcWindow
;
689 *ClientRect
= Window
->rcClient
;
691 if (!(WinPos
->flags
& SWP_NOSIZE
))
693 WindowRect
->right
= WindowRect
->left
+ WinPos
->cx
;
694 WindowRect
->bottom
= WindowRect
->top
+ WinPos
->cy
;
697 if (!(WinPos
->flags
& SWP_NOMOVE
))
702 Parent
= Window
->spwndParent
;
703 if ((0 != (Window
->style
& WS_CHILD
)) && Parent
)
705 X
+= Parent
->rcClient
.left
;
706 Y
+= Parent
->rcClient
.top
;
709 WindowRect
->left
= X
;
711 WindowRect
->right
+= X
- Window
->rcWindow
.left
;
712 WindowRect
->bottom
+= Y
- Window
->rcWindow
.top
;
713 RECTL_vOffsetRect(ClientRect
,
714 X
- Window
->rcWindow
.left
,
715 Y
- Window
->rcWindow
.top
);
718 WinPos
->flags
|= SWP_NOCLIENTMOVE
| SWP_NOCLIENTSIZE
;
724 * Fix Z order taking into account owned popups -
725 * basically we need to maintain them above the window that owns them
729 WinPosDoOwnedPopups(HWND hWnd
, HWND hWndInsertAfter
)
734 PWND Window
,DesktopWindow
, ChildObject
;
737 Window
= UserGetWindowObject(hWnd
);
738 Owner
= Window
->spwndOwner
? Window
->spwndOwner
->head
.h
: NULL
;
739 Style
= Window
->style
;
741 if ((Style
& WS_POPUP
) && Owner
)
743 /* Make sure this popup stays above the owner */
744 HWND hWndLocalPrev
= HWND_TOPMOST
;
746 if (hWndInsertAfter
!= HWND_TOPMOST
)
748 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
749 List
= IntWinListChildren(DesktopWindow
);
753 for (i
= 0; List
[i
]; i
++)
755 if (List
[i
] == Owner
)
757 if (HWND_TOP
== hWndInsertAfter
)
759 ChildObject
= UserGetWindowObject(List
[i
]);
760 if (NULL
!= ChildObject
)
762 if (0 == (ChildObject
->ExStyle
& WS_EX_TOPMOST
))
769 hWndLocalPrev
= List
[i
];
770 if (hWndLocalPrev
== hWndInsertAfter
)
773 hWndInsertAfter
= hWndLocalPrev
;
777 else if (Style
& WS_CHILD
)
779 return hWndInsertAfter
;
784 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
785 List
= IntWinListChildren(DesktopWindow
);
789 for (i
= 0; List
[i
]; i
++)
796 if (!(Wnd
= UserGetWindowObject(List
[i
])))
799 if (Wnd
->style
& WS_POPUP
&& Wnd
->spwndOwner
== Window
)
801 USER_REFERENCE_ENTRY Ref
;
802 UserRefObjectCo(Wnd
, &Ref
);
804 co_WinPosSetWindowPos(Wnd
, hWndInsertAfter
, 0, 0, 0, 0,
805 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOSENDCHANGING
);
807 UserDerefObjectCo(Wnd
);
809 hWndInsertAfter
= List
[i
];
815 return hWndInsertAfter
;
818 /***********************************************************************
819 * WinPosInternalMoveWindow
821 * Update WindowRect and ClientRect of Window and all of its children
822 * We keep both WindowRect and ClientRect in screen coordinates internally
826 WinPosInternalMoveWindow(PWND Window
, INT MoveX
, INT MoveY
)
830 ASSERT(Window
!= Window
->spwndChild
);
832 Window
->rcWindow
.left
+= MoveX
;
833 Window
->rcWindow
.right
+= MoveX
;
834 Window
->rcWindow
.top
+= MoveY
;
835 Window
->rcWindow
.bottom
+= MoveY
;
837 Window
->rcClient
.left
+= MoveX
;
838 Window
->rcClient
.right
+= MoveX
;
839 Window
->rcClient
.top
+= MoveY
;
840 Window
->rcClient
.bottom
+= MoveY
;
842 for(Child
= Window
->spwndChild
; Child
; Child
= Child
->spwndNext
)
844 WinPosInternalMoveWindow(Child
, MoveX
, MoveY
);
849 * WinPosFixupSWPFlags
851 * Fix redundant flags and values in the WINDOWPOS structure.
855 WinPosFixupFlags(WINDOWPOS
*WinPos
, PWND Wnd
)
857 if (Wnd
->style
& WS_VISIBLE
)
859 WinPos
->flags
&= ~SWP_SHOWWINDOW
;
863 WinPos
->flags
&= ~SWP_HIDEWINDOW
;
864 if (!(WinPos
->flags
& SWP_SHOWWINDOW
))
865 WinPos
->flags
|= SWP_NOREDRAW
;
868 WinPos
->cx
= max(WinPos
->cx
, 0);
869 WinPos
->cy
= max(WinPos
->cy
, 0);
871 /* Check for right size */
872 if (Wnd
->rcWindow
.right
- Wnd
->rcWindow
.left
== WinPos
->cx
&&
873 Wnd
->rcWindow
.bottom
- Wnd
->rcWindow
.top
== WinPos
->cy
)
875 WinPos
->flags
|= SWP_NOSIZE
;
878 /* Check for right position */
879 if (Wnd
->rcWindow
.left
== WinPos
->x
&&
880 Wnd
->rcWindow
.top
== WinPos
->y
)
882 WinPos
->flags
|= SWP_NOMOVE
;
885 if (WinPos
->hwnd
== UserGetForegroundWindow())
887 WinPos
->flags
|= SWP_NOACTIVATE
; /* Already active */
890 if ((Wnd
->style
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)
892 /* Bring to the top when activating */
893 if (!(WinPos
->flags
& SWP_NOACTIVATE
))
895 WinPos
->flags
&= ~SWP_NOZORDER
;
896 WinPos
->hwndInsertAfter
= (0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
) ?
897 HWND_TOPMOST
: HWND_TOP
);
902 /* Check hwndInsertAfter */
903 if (!(WinPos
->flags
& SWP_NOZORDER
))
905 /* Fix sign extension */
906 if (WinPos
->hwndInsertAfter
== (HWND
)0xffff)
908 WinPos
->hwndInsertAfter
= HWND_TOPMOST
;
910 else if (WinPos
->hwndInsertAfter
== (HWND
)0xfffe)
912 WinPos
->hwndInsertAfter
= HWND_NOTOPMOST
;
915 if (WinPos
->hwndInsertAfter
== HWND_NOTOPMOST
)
917 WinPos
->hwndInsertAfter
= HWND_TOP
;
919 else if (HWND_TOP
== WinPos
->hwndInsertAfter
920 && 0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
))
922 /* Keep it topmost when it's already topmost */
923 WinPos
->hwndInsertAfter
= HWND_TOPMOST
;
926 /* hwndInsertAfter must be a sibling of the window */
927 if (HWND_TOPMOST
!= WinPos
->hwndInsertAfter
928 && HWND_TOP
!= WinPos
->hwndInsertAfter
929 && HWND_NOTOPMOST
!= WinPos
->hwndInsertAfter
930 && HWND_BOTTOM
!= WinPos
->hwndInsertAfter
)
932 PWND InsAfterWnd
, Parent
= Wnd
->spwndParent
;
934 InsAfterWnd
= UserGetWindowObject(WinPos
->hwndInsertAfter
);
936 if (InsAfterWnd
&& UserGetAncestor(InsAfterWnd
, GA_PARENT
) != Parent
)
943 * We don't need to change the Z order of hwnd if it's already
944 * inserted after hwndInsertAfter or when inserting hwnd after
947 if ((WinPos
->hwnd
== WinPos
->hwndInsertAfter
) ||
948 ((InsAfterWnd
->spwndNext
) && (WinPos
->hwnd
== InsAfterWnd
->spwndNext
->head
.h
)))
950 WinPos
->flags
|= SWP_NOZORDER
;
959 /* x and y are always screen relative */
961 co_WinPosSetWindowPos(
975 HRGN VisBefore
= NULL
;
976 HRGN VisAfter
= NULL
;
977 HRGN DirtyRgn
= NULL
;
978 HRGN ExposedRgn
= NULL
;
981 RECTL OldWindowRect
, OldClientRect
;
988 ASSERT_REFS_CO(Window
);
990 /* FIXME: Get current active window from active queue. */
992 * Only allow CSRSS to mess with the desktop window
995 if ( Window
->head
.h
== IntGetDesktopWindow() &&
996 Window
->head
.pti
->pEThread
->ThreadsProcess
!= PsGetCurrentProcess())
1001 WinPos
.hwnd
= Window
->head
.h
;
1002 WinPos
.hwndInsertAfter
= WndInsertAfter
;
1007 WinPos
.flags
= flags
;
1009 co_WinPosDoWinPosChanging(Window
, &WinPos
, &NewWindowRect
, &NewClientRect
);
1011 /* Fix up the flags. */
1012 if (!WinPosFixupFlags(&WinPos
, Window
))
1014 EngSetLastError(ERROR_INVALID_PARAMETER
);
1018 /* Does the window still exist? */
1019 if (!IntIsWindow(WinPos
.hwnd
))
1021 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE
);
1025 Ancestor
= UserGetAncestor(Window
, GA_PARENT
);
1026 if ( (WinPos
.flags
& (SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) !=
1028 Ancestor
&& Ancestor
->head
.h
== IntGetDesktopWindow() )
1030 WinPos
.hwndInsertAfter
= WinPosDoOwnedPopups(WinPos
.hwnd
, WinPos
.hwndInsertAfter
);
1033 if (!(WinPos
.flags
& SWP_NOREDRAW
))
1035 /* Compute the visible region before the window position is changed */
1036 if (!(WinPos
.flags
& (SWP_NOREDRAW
| SWP_SHOWWINDOW
)) &&
1037 (WinPos
.flags
& (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
|
1038 SWP_HIDEWINDOW
| SWP_FRAMECHANGED
)) !=
1039 (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
))
1041 VisBefore
= VIS_ComputeVisibleRegion(Window
, FALSE
, FALSE
, TRUE
);
1044 if ( VisBefore
!= NULL
&&
1045 (VisRgn
= (PROSRGNDATA
)RGNOBJAPI_Lock(VisBefore
, NULL
)) &&
1046 REGION_GetRgnBox(VisRgn
, &TempRect
) == NULLREGION
)
1048 RGNOBJAPI_Unlock(VisRgn
);
1049 GreDeleteObject(VisBefore
);
1054 RGNOBJAPI_Unlock(VisRgn
);
1055 NtGdiOffsetRgn(VisBefore
, -Window
->rcWindow
.left
, -Window
->rcWindow
.top
);
1060 WvrFlags
= co_WinPosDoNCCALCSize(Window
, &WinPos
, &NewWindowRect
, &NewClientRect
);
1062 //DPRINT1("co_WinPosDoNCCALCSize");
1064 /* Relink windows. (also take into account shell window in hwndShellWindow) */
1065 if (!(WinPos
.flags
& SWP_NOZORDER
) && WinPos
.hwnd
!= UserGetShellWindow())
1067 IntLinkHwnd(Window
, WndInsertAfter
);
1070 OldWindowRect
= Window
->rcWindow
;
1071 OldClientRect
= Window
->rcClient
;
1073 if (OldClientRect
.bottom
- OldClientRect
.top
==
1074 NewClientRect
.bottom
- NewClientRect
.top
)
1076 WvrFlags
&= ~WVR_VREDRAW
;
1079 if (OldClientRect
.right
- OldClientRect
.left
==
1080 NewClientRect
.right
- NewClientRect
.left
)
1082 WvrFlags
&= ~WVR_HREDRAW
;
1085 /* FIXME: Actually do something with WVR_VALIDRECTS */
1087 if ( NewClientRect
.left
!= OldClientRect
.left
||
1088 NewClientRect
.top
!= OldClientRect
.top
)
1090 WinPosInternalMoveWindow(Window
,
1091 NewClientRect
.left
- OldClientRect
.left
,
1092 NewClientRect
.top
- OldClientRect
.top
);
1095 Window
->rcWindow
= NewWindowRect
;
1096 Window
->rcClient
= NewClientRect
;
1098 if (!(WinPos
.flags
& SWP_SHOWWINDOW
) && (WinPos
.flags
& SWP_HIDEWINDOW
))
1100 /* Clear the update region */
1101 co_UserRedrawWindow( Window
,
1104 RDW_VALIDATE
| RDW_NOFRAME
| RDW_NOERASE
| RDW_NOINTERNALPAINT
| RDW_ALLCHILDREN
);
1106 if ((Window
->style
& WS_VISIBLE
) &&
1107 Window
->spwndParent
== UserGetDesktopWindow())
1109 co_IntShellHookNotify(HSHELL_WINDOWDESTROYED
, (LPARAM
)Window
->head
.h
);
1111 Window
->style
&= ~WS_VISIBLE
;
1113 else if (WinPos
.flags
& SWP_SHOWWINDOW
)
1115 if (!(Window
->style
& WS_VISIBLE
) &&
1116 Window
->spwndParent
== UserGetDesktopWindow() )
1118 co_IntShellHookNotify(HSHELL_WINDOWCREATED
, (LPARAM
)Window
->head
.h
);
1120 Window
->style
|= WS_VISIBLE
;
1123 if (Window
->hrgnUpdate
!= NULL
&& Window
->hrgnUpdate
!= HRGN_WINDOW
)
1125 NtGdiOffsetRgn(Window
->hrgnUpdate
,
1126 NewWindowRect
.left
- OldWindowRect
.left
,
1127 NewWindowRect
.top
- OldWindowRect
.top
);
1130 DceResetActiveDCEs(Window
);
1132 if (!(WinPos
.flags
& SWP_NOREDRAW
))
1134 /* Determine the new visible region */
1135 VisAfter
= VIS_ComputeVisibleRegion(Window
, FALSE
, FALSE
, TRUE
);
1138 if ( VisAfter
!= NULL
&&
1139 (VisRgn
= (PROSRGNDATA
)RGNOBJAPI_Lock(VisAfter
, NULL
)) &&
1140 REGION_GetRgnBox(VisRgn
, &TempRect
) == NULLREGION
)
1142 RGNOBJAPI_Unlock(VisRgn
);
1143 GreDeleteObject(VisAfter
);
1148 RGNOBJAPI_Unlock(VisRgn
);
1149 NtGdiOffsetRgn(VisAfter
, -Window
->rcWindow
.left
, -Window
->rcWindow
.top
);
1153 * Determine which pixels can be copied from the old window position
1154 * to the new. Those pixels must be visible in both the old and new
1155 * position. Also, check the class style to see if the windows of this
1156 * class need to be completely repainted on (horizontal/vertical) size
1159 if ( VisBefore
!= NULL
&&
1161 !(WinPos
.flags
& SWP_NOCOPYBITS
) &&
1162 ((WinPos
.flags
& SWP_NOSIZE
) || !(WvrFlags
& WVR_REDRAW
)) &&
1163 !(Window
->ExStyle
& WS_EX_TRANSPARENT
) )
1165 CopyRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
1166 RgnType
= NtGdiCombineRgn(CopyRgn
, VisAfter
, VisBefore
, RGN_AND
);
1169 * If this is (also) a window resize, the whole nonclient area
1170 * needs to be repainted. So we limit the copy to the client area,
1171 * 'cause there is no use in copying it (would possibly cause
1172 * "flashing" too). However, if the copy region is already empty,
1173 * we don't have to crop (can't take anything away from an empty
1176 if (!(WinPos
.flags
& SWP_NOSIZE
) &&
1178 RgnType
!= NULLREGION
)
1180 PROSRGNDATA pCopyRgn
;
1181 RECTL ORect
= OldClientRect
;
1182 RECTL NRect
= NewClientRect
;
1183 RECTL_vOffsetRect(&ORect
, - OldWindowRect
.left
, - OldWindowRect
.top
);
1184 RECTL_vOffsetRect(&NRect
, - NewWindowRect
.left
, - NewWindowRect
.top
);
1185 RECTL_bIntersectRect(&CopyRect
, &ORect
, &NRect
);
1186 pCopyRgn
= RGNOBJAPI_Lock(CopyRgn
, NULL
);
1187 REGION_CropAndOffsetRegion(pCopyRgn
, pCopyRgn
, &CopyRect
, NULL
);
1188 RGNOBJAPI_Unlock(pCopyRgn
);
1191 /* No use in copying bits which are in the update region. */
1192 if (Window
->hrgnUpdate
!= NULL
)
1194 NtGdiOffsetRgn(CopyRgn
, NewWindowRect
.left
, NewWindowRect
.top
);
1195 NtGdiCombineRgn(CopyRgn
, CopyRgn
, Window
->hrgnUpdate
, RGN_DIFF
);
1196 NtGdiOffsetRgn(CopyRgn
, -NewWindowRect
.left
, -NewWindowRect
.top
);
1200 * Now, get the bounding box of the copy region. If it's empty
1201 * there's nothing to copy. Also, it's no use copying bits onto
1204 if ( (VisRgn
= (PROSRGNDATA
)RGNOBJAPI_Lock(CopyRgn
, NULL
)) &&
1205 REGION_GetRgnBox(VisRgn
, &CopyRect
) == NULLREGION
)
1207 /* Nothing to copy, clean up */
1208 RGNOBJAPI_Unlock(VisRgn
);
1209 REGION_FreeRgnByHandle(CopyRgn
);
1212 else if (OldWindowRect
.left
!= NewWindowRect
.left
||
1213 OldWindowRect
.top
!= NewWindowRect
.top
)
1217 RGNOBJAPI_Unlock(VisRgn
);
1221 * Small trick here: there is no function to bitblt a region. So
1222 * we set the region as the clipping region, take the bounding box
1223 * of the region and bitblt that. Since nothing outside the clipping
1224 * region is copied, this has the effect of bitblt'ing the region.
1226 * Since NtUserGetDCEx takes ownership of the clip region, we need
1227 * to create a copy of CopyRgn and pass that. We need CopyRgn later
1229 NtGdiOffsetRgn(CopyRgn
, NewWindowRect
.left
, NewWindowRect
.top
);
1230 Dc
= UserGetDCEx( Window
,
1232 DCX_WINDOW
|DCX_CACHE
|DCX_INTERSECTRGN
|DCX_CLIPSIBLINGS
|DCX_KEEPCLIPRGN
);
1234 CopyRect
.left
, CopyRect
.top
,
1235 CopyRect
.right
- CopyRect
.left
,
1236 CopyRect
.bottom
- CopyRect
.top
,
1238 CopyRect
.left
+ (OldWindowRect
.left
- NewWindowRect
.left
),
1239 CopyRect
.top
+ (OldWindowRect
.top
- NewWindowRect
.top
),
1244 UserReleaseDC(Window
, Dc
, FALSE
);
1245 IntValidateParent(Window
, CopyRgn
, FALSE
);
1246 NtGdiOffsetRgn(CopyRgn
, -NewWindowRect
.left
, -NewWindowRect
.top
);
1250 RGNOBJAPI_Unlock(VisRgn
);
1258 /* We need to redraw what wasn't visible before */
1259 if (VisAfter
!= NULL
)
1261 DirtyRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
1262 if (CopyRgn
!= NULL
)
1264 RgnType
= NtGdiCombineRgn(DirtyRgn
, VisAfter
, CopyRgn
, RGN_DIFF
);
1268 RgnType
= NtGdiCombineRgn(DirtyRgn
, VisAfter
, 0, RGN_COPY
);
1270 if (RgnType
!= ERROR
&& RgnType
!= NULLREGION
)
1273 NtGdiOffsetRgn(DirtyRgn, Window->rcWindow.left, Window->rcWindow.top);
1274 IntInvalidateWindows( Window,
1276 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
1278 GreDeleteObject(DirtyRgn);
1281 PWND Parent
= Window
->spwndParent
;
1283 NtGdiOffsetRgn( DirtyRgn
,
1284 Window
->rcWindow
.left
,
1285 Window
->rcWindow
.top
);
1286 if ( (Window
->style
& WS_CHILD
) &&
1288 !(Parent
->style
& WS_CLIPCHILDREN
))
1290 IntInvalidateWindows( Parent
,
1292 RDW_ERASE
| RDW_INVALIDATE
);
1293 co_IntPaintWindows(Parent
, RDW_ERASENOW
, FALSE
);
1297 IntInvalidateWindows( Window
,
1299 RDW_ERASE
| RDW_FRAME
| RDW_INVALIDATE
| RDW_ALLCHILDREN
);
1302 REGION_FreeRgnByHandle(DirtyRgn
);
1305 if (CopyRgn
!= NULL
)
1307 REGION_FreeRgnByHandle(CopyRgn
);
1310 /* Expose what was covered before but not covered anymore */
1311 if (VisBefore
!= NULL
)
1313 ExposedRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
1314 NtGdiCombineRgn(ExposedRgn
, VisBefore
, NULL
, RGN_COPY
);
1315 NtGdiOffsetRgn( ExposedRgn
,
1316 OldWindowRect
.left
- NewWindowRect
.left
,
1317 OldWindowRect
.top
- NewWindowRect
.top
);
1319 if (VisAfter
!= NULL
)
1320 RgnType
= NtGdiCombineRgn(ExposedRgn
, ExposedRgn
, VisAfter
, RGN_DIFF
);
1322 RgnType
= SIMPLEREGION
;
1324 if (RgnType
!= ERROR
&& RgnType
!= NULLREGION
)
1326 co_VIS_WindowLayoutChanged(Window
, ExposedRgn
);
1328 REGION_FreeRgnByHandle(ExposedRgn
);
1329 REGION_FreeRgnByHandle(VisBefore
);
1332 if (VisAfter
!= NULL
)
1334 REGION_FreeRgnByHandle(VisAfter
);
1337 if (!(WinPos
.flags
& SWP_NOACTIVATE
))
1339 if ((Window
->style
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1341 co_IntSendMessageNoWait(WinPos
.hwnd
, WM_CHILDACTIVATE
, 0, 0);
1345 co_IntSetForegroundWindow(Window
);
1350 if ((WinPos
.flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOPOSCHANGE
)
1352 /* WM_WINDOWPOSCHANGED is sent even if SWP_NOSENDCHANGING is set
1353 and always contains final window position.
1355 WinPos
.x
= NewWindowRect
.left
;
1356 WinPos
.y
= NewWindowRect
.top
;
1357 WinPos
.cx
= NewWindowRect
.right
- NewWindowRect
.left
;
1358 WinPos
.cy
= NewWindowRect
.bottom
- NewWindowRect
.top
;
1359 co_IntSendMessageNoWait(WinPos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
) &WinPos
);
1362 if ( WinPos
.flags
& SWP_FRAMECHANGED
|| WinPos
.flags
& SWP_STATECHANGED
||
1363 !(WinPos
.flags
& SWP_NOCLIENTSIZE
) || !(WinPos
.flags
& SWP_NOCLIENTMOVE
) )
1365 PWND pWnd
= UserGetWindowObject(WinPos
.hwnd
);
1367 IntNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE
, pWnd
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
1374 co_WinPosGetNonClientSize(PWND Window
, RECT
* WindowRect
, RECT
* ClientRect
)
1378 ASSERT_REFS_CO(Window
);
1380 *ClientRect
= *WindowRect
;
1381 Result
= co_IntSendMessageNoWait(Window
->head
.h
, WM_NCCALCSIZE
, FALSE
, (LPARAM
) ClientRect
);
1383 FixClientRect(ClientRect
, WindowRect
);
1389 co_WinPosSendSizeMove(PWND Wnd
)
1391 WPARAM wParam
= SIZE_RESTORED
;
1393 Wnd
->state
&= ~WNDS_SENDSIZEMOVEMSGS
;
1394 if (Wnd
->style
& WS_MAXIMIZE
)
1396 wParam
= SIZE_MAXIMIZED
;
1398 else if (Wnd
->style
& WS_MINIMIZE
)
1400 wParam
= SIZE_MINIMIZED
;
1403 co_IntSendMessageNoWait(Wnd
->head
.h
, WM_SIZE
, wParam
,
1404 MAKELONG(Wnd
->rcClient
.right
-
1406 Wnd
->rcClient
.bottom
-
1407 Wnd
->rcClient
.top
));
1408 co_IntSendMessageNoWait(Wnd
->head
.h
, WM_MOVE
, 0,
1409 MAKELONG(Wnd
->rcClient
.left
,
1410 Wnd
->rcClient
.top
));
1411 IntEngWindowChanged(Wnd
, WOC_RGN_CLIENT
);
1415 co_WinPosShowWindow(PWND Wnd
, INT Cmd
)
1423 ASSERT_REFS_CO(Wnd
);
1425 WasVisible
= (Wnd
->style
& WS_VISIBLE
) != 0;
1435 Swp
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
1436 if (Wnd
->head
.h
!= UserGetActiveWindow())
1437 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1441 case SW_SHOWMINNOACTIVE
:
1442 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1444 case SW_SHOWMINIMIZED
:
1445 Swp
|= SWP_SHOWWINDOW
;
1449 Swp
|= SWP_NOACTIVATE
;
1450 if (!(Wnd
->style
& WS_MINIMIZE
))
1452 Swp
|= co_WinPosMinMaximize(Wnd
, SW_MINIMIZE
, &NewPos
) |
1457 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1460 Swp
|= SWP_FRAMECHANGED
;
1466 case SW_SHOWMAXIMIZED
:
1468 Swp
|= SWP_SHOWWINDOW
;
1469 if (!(Wnd
->style
& WS_MAXIMIZE
))
1471 Swp
|= co_WinPosMinMaximize(Wnd
, SW_MAXIMIZE
, &NewPos
) |
1476 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1479 Swp
|= SWP_FRAMECHANGED
;
1486 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1489 if (WasVisible
) return(TRUE
); // Nothing to do!
1490 Swp
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
1491 /* Don't activate the topmost window. */
1494 case SW_SHOWNOACTIVATE
:
1495 //Swp |= SWP_NOZORDER;
1496 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1499 case SW_SHOWDEFAULT
:
1501 Swp
|= SWP_SHOWWINDOW
;
1502 if (Wnd
->style
& (WS_MINIMIZE
| WS_MAXIMIZE
))
1504 Swp
|= co_WinPosMinMaximize(Wnd
, SW_RESTORE
, &NewPos
) |
1509 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1512 Swp
|= SWP_FRAMECHANGED
;
1518 ShowFlag
= (Cmd
!= SW_HIDE
);
1520 if (ShowFlag
!= WasVisible
)
1522 co_IntSendMessageNoWait(Wnd
->head
.h
, WM_SHOWWINDOW
, ShowFlag
, 0);
1525 /* We can't activate a child window */
1526 if ((Wnd
->style
& WS_CHILD
) &&
1527 !(Wnd
->ExStyle
& WS_EX_MDICHILD
))
1529 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1532 co_WinPosSetWindowPos(Wnd
, 0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
)
1533 ? HWND_TOPMOST
: HWND_TOP
,
1534 NewPos
.left
, NewPos
.top
, NewPos
.right
, NewPos
.bottom
, LOWORD(Swp
));
1536 if ((Cmd
== SW_HIDE
) || (Cmd
== SW_MINIMIZE
))
1538 PWND ThreadFocusWindow
;
1540 /* FIXME: This will cause the window to be activated irrespective
1541 * of whether it is owned by the same thread. Has to be done
1545 if (Wnd
->head
.h
== UserGetActiveWindow())
1547 co_WinPosActivateOtherWindow(Wnd
);
1552 ThreadFocusWindow
= UserGetWindowObject(IntGetThreadFocusWindow());
1554 /* Revert focus to parent */
1555 if (ThreadFocusWindow
&& (Wnd
== ThreadFocusWindow
||
1556 IntIsChildWindow(Wnd
, ThreadFocusWindow
)))
1558 //faxme: as long as we have ref on Window, we also, indirectly, have ref on parent...
1559 co_UserSetFocus(Wnd
->spwndParent
);
1563 /* FIXME: Check for window destruction. */
1565 if ((Wnd
->state
& WNDS_SENDSIZEMOVEMSGS
) &&
1566 !(Wnd
->state2
& WNDS2_INDESTROY
))
1568 co_WinPosSendSizeMove(Wnd
);
1571 /* Activate the window if activation is not requested and the window is not minimized */
1573 if (!(Swp & (SWP_NOACTIVATE | SWP_HIDEWINDOW)) && !(Window->style & WS_MINIMIZE))
1575 WinPosChangeActiveWindow(Wnd, FALSE);
1583 co_WinPosSearchChildren(
1592 if (!(ScopeWin
->style
& WS_VISIBLE
))
1597 if ((ScopeWin
->style
& WS_DISABLED
))
1602 if (!IntPtInWindow(ScopeWin
, Point
->x
, Point
->y
))
1607 UserReferenceObject(ScopeWin
);
1609 if (Point
->x
- ScopeWin
->rcClient
.left
< ScopeWin
->rcClient
.right
&&
1610 Point
->y
- ScopeWin
->rcClient
.top
< ScopeWin
->rcClient
.bottom
)
1612 List
= IntWinListChildren(ScopeWin
);
1615 for (phWnd
= List
; *phWnd
; ++phWnd
)
1617 if (!(pwndChild
= UserGetWindowObject(*phWnd
)))
1622 pwndChild
= co_WinPosSearchChildren(pwndChild
, Point
, HitTest
);
1624 if(pwndChild
!= NULL
)
1626 /* We found a window. Don't send any more WM_NCHITTEST messages */
1627 UserDereferenceObject(ScopeWin
);
1636 *HitTest
= co_IntSendMessage(ScopeWin
->head
.h
, WM_NCHITTEST
, 0,
1637 MAKELONG(Point
->x
, Point
->y
));
1638 if ((*HitTest
) == (USHORT
)HTTRANSPARENT
)
1640 UserDereferenceObject(ScopeWin
);
1648 co_WinPosWindowFromPoint(PWND ScopeWin
, POINT
*WinPoint
, USHORT
* HitTest
)
1651 POINT Point
= *WinPoint
;
1652 USER_REFERENCE_ENTRY Ref
;
1654 if( ScopeWin
== NULL
)
1656 ScopeWin
= UserGetDesktopWindow();
1657 if(ScopeWin
== NULL
)
1661 *HitTest
= HTNOWHERE
;
1663 ASSERT_REFS_CO(ScopeWin
);
1664 UserRefObjectCo(ScopeWin
, &Ref
);
1666 Window
= co_WinPosSearchChildren(ScopeWin
, &Point
, HitTest
);
1668 UserDerefObjectCo(ScopeWin
);
1670 ASSERT_REFS_CO(Window
);
1671 ASSERT_REFS_CO(ScopeWin
);
1678 NtUserGetMinMaxInfo(
1680 MINMAXINFO
*MinMaxInfo
,
1685 MINMAXINFO SafeMinMax
;
1688 USER_REFERENCE_ENTRY Ref
;
1690 DPRINT("Enter NtUserGetMinMaxInfo\n");
1691 UserEnterExclusive();
1693 if(!(Window
= UserGetWindowObject(hWnd
)))
1699 UserRefObjectCo(Window
, &Ref
);
1701 Size
.x
= Window
->rcWindow
.left
;
1702 Size
.y
= Window
->rcWindow
.top
;
1703 WinPosInitInternalPos(Window
, &Size
,
1706 co_WinPosGetMinMaxInfo(Window
, &SafeMinMax
.ptMaxSize
, &SafeMinMax
.ptMaxPosition
,
1707 &SafeMinMax
.ptMinTrackSize
, &SafeMinMax
.ptMaxTrackSize
);
1709 Status
= MmCopyToCaller(MinMaxInfo
, &SafeMinMax
, sizeof(MINMAXINFO
));
1710 if(!NT_SUCCESS(Status
))
1712 SetLastNtError(Status
);
1720 if (Window
) UserDerefObjectCo(Window
);
1722 DPRINT("Leave NtUserGetMinMaxInfo, ret=%i\n", ret
);