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 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
85 Ret
= IntGetClientOrigin(Window
, &pt
);
89 SetLastWin32Error(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
))
302 return SWP_NOSIZE
| SWP_NOMOVE
;
304 if (Wnd
->style
& WS_MINIMIZE
)
306 if (!co_IntSendMessageNoWait(Wnd
->head
.h
, WM_QUERYOPEN
, 0, 0))
308 return(SWP_NOSIZE
| SWP_NOMOVE
);
310 SwpFlags
|= SWP_NOCOPYBITS
;
316 if (Wnd
->style
& WS_MAXIMIZE
)
318 Wnd
->state2
|= WNDS2_MAXIMIZEBUTTONDOWN
;
319 Wnd
->style
&= ~WS_MAXIMIZE
;
323 Wnd
->state2
&= ~WNDS2_MAXIMIZEBUTTONDOWN
;
325 co_UserRedrawWindow(Wnd
, NULL
, 0, RDW_VALIDATE
| RDW_NOERASE
|
326 RDW_NOINTERNALPAINT
);
327 Wnd
->style
|= WS_MINIMIZE
;
328 WinPosFindIconPos(Wnd
, &Wnd
->InternalPos
.IconPos
);
329 RECTL_vSetRect(NewPos
, Wnd
->InternalPos
.IconPos
.x
, Wnd
->InternalPos
.IconPos
.y
,
330 UserGetSystemMetrics(SM_CXMINIMIZED
),
331 UserGetSystemMetrics(SM_CYMINIMIZED
));
332 SwpFlags
|= SWP_NOCOPYBITS
;
338 co_WinPosGetMinMaxInfo(Wnd
, &Size
, &Wnd
->InternalPos
.MaxPos
,
340 DPRINT("Maximize: %d,%d %dx%d\n",
341 Wnd
->InternalPos
.MaxPos
.x
, Wnd
->InternalPos
.MaxPos
.y
, Size
.x
, Size
.y
);
342 if (Wnd
->style
& WS_MINIMIZE
)
344 Wnd
->style
&= ~WS_MINIMIZE
;
346 Wnd
->style
|= WS_MAXIMIZE
;
347 RECTL_vSetRect(NewPos
, Wnd
->InternalPos
.MaxPos
.x
, Wnd
->InternalPos
.MaxPos
.y
,
354 if (Wnd
->style
& WS_MINIMIZE
)
356 Wnd
->style
&= ~WS_MINIMIZE
;
357 if (Wnd
->state2
& WNDS2_MAXIMIZEBUTTONDOWN
)
359 co_WinPosGetMinMaxInfo(Wnd
, &Size
,
360 &Wnd
->InternalPos
.MaxPos
, NULL
, NULL
);
361 Wnd
->style
|= WS_MAXIMIZE
;
362 RECTL_vSetRect(NewPos
, Wnd
->InternalPos
.MaxPos
.x
,
363 Wnd
->InternalPos
.MaxPos
.y
, Size
.x
, Size
.y
);
368 *NewPos
= Wnd
->InternalPos
.NormalRect
;
369 NewPos
->right
-= NewPos
->left
;
370 NewPos
->bottom
-= NewPos
->top
;
376 if (!(Wnd
->style
& WS_MAXIMIZE
))
380 Wnd
->style
&= ~WS_MAXIMIZE
;
381 *NewPos
= Wnd
->InternalPos
.NormalRect
;
382 NewPos
->right
-= NewPos
->left
;
383 NewPos
->bottom
-= NewPos
->top
;
393 UserHasWindowEdge(DWORD Style
, DWORD ExStyle
)
395 if (Style
& WS_MINIMIZE
)
397 if (ExStyle
& WS_EX_DLGMODALFRAME
)
399 if (ExStyle
& WS_EX_STATICEDGE
)
401 if (Style
& WS_THICKFRAME
)
404 if (Style
== WS_DLGFRAME
|| Style
== WS_CAPTION
)
410 UserGetWindowBorders(DWORD Style
, DWORD ExStyle
, SIZE
*Size
, BOOL WithClient
)
414 if (UserHasWindowEdge(Style
, ExStyle
))
416 else if (ExStyle
& WS_EX_STATICEDGE
)
418 if ((ExStyle
& WS_EX_CLIENTEDGE
) && WithClient
)
420 if (Style
& WS_CAPTION
|| ExStyle
& WS_EX_DLGMODALFRAME
)
422 Size
->cx
= Size
->cy
= Border
;
423 if ((Style
& WS_THICKFRAME
) && !(Style
& WS_MINIMIZE
))
425 Size
->cx
+= UserGetSystemMetrics(SM_CXFRAME
) - UserGetSystemMetrics(SM_CXDLGFRAME
);
426 Size
->cy
+= UserGetSystemMetrics(SM_CYFRAME
) - UserGetSystemMetrics(SM_CYDLGFRAME
);
428 Size
->cx
*= UserGetSystemMetrics(SM_CXBORDER
);
429 Size
->cy
*= UserGetSystemMetrics(SM_CYBORDER
);
433 UserAdjustWindowRectEx(LPRECT lpRect
,
442 lpRect
->top
-= UserGetSystemMetrics(SM_CYMENU
);
444 if ((dwStyle
& WS_CAPTION
) == WS_CAPTION
)
446 if (dwExStyle
& WS_EX_TOOLWINDOW
)
447 lpRect
->top
-= UserGetSystemMetrics(SM_CYSMCAPTION
);
449 lpRect
->top
-= UserGetSystemMetrics(SM_CYCAPTION
);
451 UserGetWindowBorders(dwStyle
, dwExStyle
, &BorderSize
, TRUE
);
461 co_WinPosGetMinMaxInfo(PWND Window
, POINT
* MaxSize
, POINT
* MaxPos
,
462 POINT
* MinTrack
, POINT
* MaxTrack
)
467 LONG style
= Window
->style
;
469 LONG exstyle
= Window
->ExStyle
;
472 ASSERT_REFS_CO(Window
);
474 /* Compute default values */
476 rc
= Window
->rcWindow
;
477 MinMax
.ptReserved
.x
= rc
.left
;
478 MinMax
.ptReserved
.y
= rc
.top
;
480 if ((style
& WS_CAPTION
) == WS_CAPTION
)
481 adjustedStyle
= style
& ~WS_BORDER
; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
483 adjustedStyle
= style
;
485 if(Window
->spwndParent
)
486 IntGetClientRect(Window
->spwndParent
, &rc
);
487 UserAdjustWindowRectEx(&rc
, adjustedStyle
, ((style
& WS_POPUP
) && Window
->IDMenu
), exstyle
);
492 MinMax
.ptMaxSize
.x
= rc
.right
- rc
.left
;
493 MinMax
.ptMaxSize
.y
= rc
.bottom
- rc
.top
;
494 if (style
& (WS_DLGFRAME
| WS_BORDER
))
496 MinMax
.ptMinTrackSize
.x
= UserGetSystemMetrics(SM_CXMINTRACK
);
497 MinMax
.ptMinTrackSize
.y
= UserGetSystemMetrics(SM_CYMINTRACK
);
501 MinMax
.ptMinTrackSize
.x
= 2 * xinc
;
502 MinMax
.ptMinTrackSize
.y
= 2 * yinc
;
504 MinMax
.ptMaxTrackSize
.x
= UserGetSystemMetrics(SM_CXMAXTRACK
);
505 MinMax
.ptMaxTrackSize
.y
= UserGetSystemMetrics(SM_CYMAXTRACK
);
506 MinMax
.ptMaxPosition
.x
= -xinc
;
507 MinMax
.ptMaxPosition
.y
= -yinc
;
509 //if (!EMPTYPOINT(win->max_pos)) MinMax.ptMaxPosition = win->max_pos;
511 co_IntSendMessage(Window
->head
.h
, WM_GETMINMAXINFO
, 0, (LPARAM
)&MinMax
);
513 /* if the app didn't change the values, adapt them for the current monitor */
514 if ((monitor
= IntGetPrimaryMonitor()))
518 rc_work
= monitor
->rcMonitor
;
520 if (style
& WS_MAXIMIZEBOX
)
522 if ((style
& WS_CAPTION
) == WS_CAPTION
|| !(style
& (WS_CHILD
| WS_POPUP
)))
523 rc_work
= monitor
->rcWork
;
526 if (MinMax
.ptMaxSize
.x
== UserGetSystemMetrics(SM_CXSCREEN
) + 2 * xinc
&&
527 MinMax
.ptMaxSize
.y
== UserGetSystemMetrics(SM_CYSCREEN
) + 2 * yinc
)
529 MinMax
.ptMaxSize
.x
= (rc_work
.right
- rc_work
.left
) + 2 * xinc
;
530 MinMax
.ptMaxSize
.y
= (rc_work
.bottom
- rc_work
.top
) + 2 * yinc
;
532 if (MinMax
.ptMaxPosition
.x
== -xinc
&& MinMax
.ptMaxPosition
.y
== -yinc
)
534 MinMax
.ptMaxPosition
.x
= rc_work
.left
- xinc
;
535 MinMax
.ptMaxPosition
.y
= rc_work
.top
- yinc
;
540 MinMax
.ptMaxTrackSize
.x
= max(MinMax
.ptMaxTrackSize
.x
,
541 MinMax
.ptMinTrackSize
.x
);
542 MinMax
.ptMaxTrackSize
.y
= max(MinMax
.ptMaxTrackSize
.y
,
543 MinMax
.ptMinTrackSize
.y
);
546 *MaxSize
= MinMax
.ptMaxSize
;
548 *MaxPos
= MinMax
.ptMaxPosition
;
550 *MinTrack
= MinMax
.ptMinTrackSize
;
552 *MaxTrack
= MinMax
.ptMaxTrackSize
;
554 return 0; //FIXME: what does it return?
559 FixClientRect(PRECTL ClientRect
, PRECTL WindowRect
)
561 if (ClientRect
->left
< WindowRect
->left
)
563 ClientRect
->left
= WindowRect
->left
;
565 else if (WindowRect
->right
< ClientRect
->left
)
567 ClientRect
->left
= WindowRect
->right
;
569 if (ClientRect
->right
< WindowRect
->left
)
571 ClientRect
->right
= WindowRect
->left
;
573 else if (WindowRect
->right
< ClientRect
->right
)
575 ClientRect
->right
= WindowRect
->right
;
577 if (ClientRect
->top
< WindowRect
->top
)
579 ClientRect
->top
= WindowRect
->top
;
581 else if (WindowRect
->bottom
< ClientRect
->top
)
583 ClientRect
->top
= WindowRect
->bottom
;
585 if (ClientRect
->bottom
< WindowRect
->top
)
587 ClientRect
->bottom
= WindowRect
->top
;
589 else if (WindowRect
->bottom
< ClientRect
->bottom
)
591 ClientRect
->bottom
= WindowRect
->bottom
;
597 co_WinPosDoNCCALCSize(PWND Window
, PWINDOWPOS WinPos
,
598 RECT
* WindowRect
, RECT
* ClientRect
)
603 ASSERT_REFS_CO(Window
);
605 /* Send WM_NCCALCSIZE message to get new client area */
606 if ((WinPos
->flags
& (SWP_FRAMECHANGED
| SWP_NOSIZE
)) != SWP_NOSIZE
)
608 NCCALCSIZE_PARAMS params
;
609 WINDOWPOS winposCopy
;
611 params
.rgrc
[0] = *WindowRect
;
612 params
.rgrc
[1] = Window
->rcWindow
;
613 params
.rgrc
[2] = Window
->rcClient
;
614 Parent
= Window
->spwndParent
;
615 if (0 != (Window
->style
& WS_CHILD
) && Parent
)
617 RECTL_vOffsetRect(&(params
.rgrc
[0]), - Parent
->rcClient
.left
,
618 - Parent
->rcClient
.top
);
619 RECTL_vOffsetRect(&(params
.rgrc
[1]), - Parent
->rcClient
.left
,
620 - Parent
->rcClient
.top
);
621 RECTL_vOffsetRect(&(params
.rgrc
[2]), - Parent
->rcClient
.left
,
622 - Parent
->rcClient
.top
);
624 params
.lppos
= &winposCopy
;
625 winposCopy
= *WinPos
;
627 wvrFlags
= co_IntSendMessageNoWait(Window
->head
.h
, WM_NCCALCSIZE
, TRUE
, (LPARAM
) ¶ms
);
629 /* If the application send back garbage, ignore it */
630 if (params
.rgrc
[0].left
<= params
.rgrc
[0].right
&&
631 params
.rgrc
[0].top
<= params
.rgrc
[0].bottom
)
633 *ClientRect
= params
.rgrc
[0];
634 if ((Window
->style
& WS_CHILD
) && Parent
)
636 RECTL_vOffsetRect(ClientRect
, Parent
->rcClient
.left
,
637 Parent
->rcClient
.top
);
639 FixClientRect(ClientRect
, WindowRect
);
642 /* FIXME: WVR_ALIGNxxx */
644 if (ClientRect
->left
!= Window
->rcClient
.left
||
645 ClientRect
->top
!= Window
->rcClient
.top
)
647 WinPos
->flags
&= ~SWP_NOCLIENTMOVE
;
650 if ((ClientRect
->right
- ClientRect
->left
!=
651 Window
->rcClient
.right
- Window
->rcClient
.left
) ||
652 (ClientRect
->bottom
- ClientRect
->top
!=
653 Window
->rcClient
.bottom
- Window
->rcClient
.top
))
655 WinPos
->flags
&= ~SWP_NOCLIENTSIZE
;
660 if (! (WinPos
->flags
& SWP_NOMOVE
)
661 && (ClientRect
->left
!= Window
->rcClient
.left
||
662 ClientRect
->top
!= Window
->rcClient
.top
))
664 WinPos
->flags
&= ~SWP_NOCLIENTMOVE
;
673 co_WinPosDoWinPosChanging(PWND Window
,
680 ASSERT_REFS_CO(Window
);
682 if (!(WinPos
->flags
& SWP_NOSENDCHANGING
))
684 co_IntSendMessageNoWait(Window
->head
.h
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
) WinPos
);
687 *WindowRect
= Window
->rcWindow
;
688 *ClientRect
= Window
->rcClient
;
690 if (!(WinPos
->flags
& SWP_NOSIZE
))
692 WindowRect
->right
= WindowRect
->left
+ WinPos
->cx
;
693 WindowRect
->bottom
= WindowRect
->top
+ WinPos
->cy
;
696 if (!(WinPos
->flags
& SWP_NOMOVE
))
701 Parent
= Window
->spwndParent
;
702 if ((0 != (Window
->style
& WS_CHILD
)) && Parent
)
704 X
+= Parent
->rcClient
.left
;
705 Y
+= Parent
->rcClient
.top
;
708 WindowRect
->left
= X
;
710 WindowRect
->right
+= X
- Window
->rcWindow
.left
;
711 WindowRect
->bottom
+= Y
- Window
->rcWindow
.top
;
712 RECTL_vOffsetRect(ClientRect
,
713 X
- Window
->rcWindow
.left
,
714 Y
- Window
->rcWindow
.top
);
717 WinPos
->flags
|= SWP_NOCLIENTMOVE
| SWP_NOCLIENTSIZE
;
723 * Fix Z order taking into account owned popups -
724 * basically we need to maintain them above the window that owns them
728 WinPosDoOwnedPopups(HWND hWnd
, HWND hWndInsertAfter
)
733 PWND Window
,DesktopWindow
, ChildObject
;
736 Window
= UserGetWindowObject(hWnd
);
737 Owner
= Window
->spwndOwner
? Window
->spwndOwner
->head
.h
: NULL
;
738 Style
= Window
->style
;
740 if ((Style
& WS_POPUP
) && Owner
)
742 /* Make sure this popup stays above the owner */
743 HWND hWndLocalPrev
= HWND_TOPMOST
;
745 if (hWndInsertAfter
!= HWND_TOPMOST
)
747 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
748 List
= IntWinListChildren(DesktopWindow
);
752 for (i
= 0; List
[i
]; i
++)
754 if (List
[i
] == Owner
)
756 if (HWND_TOP
== hWndInsertAfter
)
758 ChildObject
= UserGetWindowObject(List
[i
]);
759 if (NULL
!= ChildObject
)
761 if (0 == (ChildObject
->ExStyle
& WS_EX_TOPMOST
))
768 hWndLocalPrev
= List
[i
];
769 if (hWndLocalPrev
== hWndInsertAfter
)
772 hWndInsertAfter
= hWndLocalPrev
;
776 else if (Style
& WS_CHILD
)
778 return hWndInsertAfter
;
783 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
784 List
= IntWinListChildren(DesktopWindow
);
788 for (i
= 0; List
[i
]; i
++)
795 if (!(Wnd
= UserGetWindowObject(List
[i
])))
798 if (Wnd
->style
& WS_POPUP
&& Wnd
->spwndOwner
== Window
)
800 USER_REFERENCE_ENTRY Ref
;
801 UserRefObjectCo(Wnd
, &Ref
);
803 co_WinPosSetWindowPos(Wnd
, hWndInsertAfter
, 0, 0, 0, 0,
804 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOSENDCHANGING
);
806 UserDerefObjectCo(Wnd
);
808 hWndInsertAfter
= List
[i
];
814 return hWndInsertAfter
;
817 /***********************************************************************
818 * WinPosInternalMoveWindow
820 * Update WindowRect and ClientRect of Window and all of its children
821 * We keep both WindowRect and ClientRect in screen coordinates internally
825 WinPosInternalMoveWindow(PWND Window
, INT MoveX
, INT MoveY
)
829 ASSERT(Window
!= Window
->spwndChild
);
831 Window
->rcWindow
.left
+= MoveX
;
832 Window
->rcWindow
.right
+= MoveX
;
833 Window
->rcWindow
.top
+= MoveY
;
834 Window
->rcWindow
.bottom
+= MoveY
;
836 Window
->rcClient
.left
+= MoveX
;
837 Window
->rcClient
.right
+= MoveX
;
838 Window
->rcClient
.top
+= MoveY
;
839 Window
->rcClient
.bottom
+= MoveY
;
841 for(Child
= Window
->spwndChild
; Child
; Child
= Child
->spwndNext
)
843 WinPosInternalMoveWindow(Child
, MoveX
, MoveY
);
848 * WinPosFixupSWPFlags
850 * Fix redundant flags and values in the WINDOWPOS structure.
854 WinPosFixupFlags(WINDOWPOS
*WinPos
, PWND Wnd
)
856 if (Wnd
->style
& WS_VISIBLE
)
858 WinPos
->flags
&= ~SWP_SHOWWINDOW
;
862 WinPos
->flags
&= ~SWP_HIDEWINDOW
;
863 if (!(WinPos
->flags
& SWP_SHOWWINDOW
))
864 WinPos
->flags
|= SWP_NOREDRAW
;
867 WinPos
->cx
= max(WinPos
->cx
, 0);
868 WinPos
->cy
= max(WinPos
->cy
, 0);
870 /* Check for right size */
871 if (Wnd
->rcWindow
.right
- Wnd
->rcWindow
.left
== WinPos
->cx
&&
872 Wnd
->rcWindow
.bottom
- Wnd
->rcWindow
.top
== WinPos
->cy
)
874 WinPos
->flags
|= SWP_NOSIZE
;
877 /* Check for right position */
878 if (Wnd
->rcWindow
.left
== WinPos
->x
&&
879 Wnd
->rcWindow
.top
== WinPos
->y
)
881 WinPos
->flags
|= SWP_NOMOVE
;
884 if (WinPos
->hwnd
== UserGetForegroundWindow())
886 WinPos
->flags
|= SWP_NOACTIVATE
; /* Already active */
889 if ((Wnd
->style
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)
891 /* Bring to the top when activating */
892 if (!(WinPos
->flags
& SWP_NOACTIVATE
))
894 WinPos
->flags
&= ~SWP_NOZORDER
;
895 WinPos
->hwndInsertAfter
= (0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
) ?
896 HWND_TOPMOST
: HWND_TOP
);
901 /* Check hwndInsertAfter */
902 if (!(WinPos
->flags
& SWP_NOZORDER
))
904 /* Fix sign extension */
905 if (WinPos
->hwndInsertAfter
== (HWND
)0xffff)
907 WinPos
->hwndInsertAfter
= HWND_TOPMOST
;
909 else if (WinPos
->hwndInsertAfter
== (HWND
)0xfffe)
911 WinPos
->hwndInsertAfter
= HWND_NOTOPMOST
;
914 if (WinPos
->hwndInsertAfter
== HWND_NOTOPMOST
)
916 WinPos
->hwndInsertAfter
= HWND_TOP
;
918 else if (HWND_TOP
== WinPos
->hwndInsertAfter
919 && 0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
))
921 /* Keep it topmost when it's already topmost */
922 WinPos
->hwndInsertAfter
= HWND_TOPMOST
;
925 /* hwndInsertAfter must be a sibling of the window */
926 if (HWND_TOPMOST
!= WinPos
->hwndInsertAfter
927 && HWND_TOP
!= WinPos
->hwndInsertAfter
928 && HWND_NOTOPMOST
!= WinPos
->hwndInsertAfter
929 && HWND_BOTTOM
!= WinPos
->hwndInsertAfter
)
931 PWND InsAfterWnd
, Parent
= Wnd
->spwndParent
;
933 InsAfterWnd
= UserGetWindowObject(WinPos
->hwndInsertAfter
);
935 if (InsAfterWnd
&& UserGetAncestor(InsAfterWnd
, GA_PARENT
) != Parent
)
942 * We don't need to change the Z order of hwnd if it's already
943 * inserted after hwndInsertAfter or when inserting hwnd after
946 if ((WinPos
->hwnd
== WinPos
->hwndInsertAfter
) ||
947 ((InsAfterWnd
->spwndNext
) && (WinPos
->hwnd
== InsAfterWnd
->spwndNext
->head
.h
)))
949 WinPos
->flags
|= SWP_NOZORDER
;
958 /* x and y are always screen relative */
960 co_WinPosSetWindowPos(
974 HRGN VisBefore
= NULL
;
975 HRGN VisAfter
= NULL
;
976 HRGN DirtyRgn
= NULL
;
977 HRGN ExposedRgn
= NULL
;
980 RECTL OldWindowRect
, OldClientRect
;
987 ASSERT_REFS_CO(Window
);
989 /* FIXME: Get current active window from active queue. */
991 * Only allow CSRSS to mess with the desktop window
994 if ( Window
->head
.h
== IntGetDesktopWindow() &&
995 Window
->head
.pti
->pEThread
->ThreadsProcess
!= PsGetCurrentProcess())
1000 WinPos
.hwnd
= Window
->head
.h
;
1001 WinPos
.hwndInsertAfter
= WndInsertAfter
;
1006 WinPos
.flags
= flags
;
1008 co_WinPosDoWinPosChanging(Window
, &WinPos
, &NewWindowRect
, &NewClientRect
);
1010 /* Fix up the flags. */
1011 if (!WinPosFixupFlags(&WinPos
, Window
))
1013 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1017 /* Does the window still exist? */
1018 if (!IntIsWindow(WinPos
.hwnd
))
1020 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1024 Ancestor
= UserGetAncestor(Window
, GA_PARENT
);
1025 if ( (WinPos
.flags
& (SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) !=
1027 Ancestor
&& Ancestor
->head
.h
== IntGetDesktopWindow() )
1029 WinPos
.hwndInsertAfter
= WinPosDoOwnedPopups(WinPos
.hwnd
, WinPos
.hwndInsertAfter
);
1032 if (!(WinPos
.flags
& SWP_NOREDRAW
))
1034 /* Compute the visible region before the window position is changed */
1035 if (!(WinPos
.flags
& (SWP_NOREDRAW
| SWP_SHOWWINDOW
)) &&
1036 (WinPos
.flags
& (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
|
1037 SWP_HIDEWINDOW
| SWP_FRAMECHANGED
)) !=
1038 (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
))
1040 VisBefore
= VIS_ComputeVisibleRegion(Window
, FALSE
, FALSE
, TRUE
);
1043 if ( VisBefore
!= NULL
&&
1044 (VisRgn
= (PROSRGNDATA
)RGNOBJAPI_Lock(VisBefore
, NULL
)) &&
1045 REGION_GetRgnBox(VisRgn
, &TempRect
) == NULLREGION
)
1047 RGNOBJAPI_Unlock(VisRgn
);
1048 GreDeleteObject(VisBefore
);
1053 RGNOBJAPI_Unlock(VisRgn
);
1054 NtGdiOffsetRgn(VisBefore
, -Window
->rcWindow
.left
, -Window
->rcWindow
.top
);
1059 WvrFlags
= co_WinPosDoNCCALCSize(Window
, &WinPos
, &NewWindowRect
, &NewClientRect
);
1061 //DPRINT1("co_WinPosDoNCCALCSize");
1063 /* Relink windows. (also take into account shell window in hwndShellWindow) */
1064 if (!(WinPos
.flags
& SWP_NOZORDER
) && WinPos
.hwnd
!= UserGetShellWindow())
1066 IntLinkHwnd(Window
, WndInsertAfter
);
1069 OldWindowRect
= Window
->rcWindow
;
1070 OldClientRect
= Window
->rcClient
;
1072 if (OldClientRect
.bottom
- OldClientRect
.top
==
1073 NewClientRect
.bottom
- NewClientRect
.top
)
1075 WvrFlags
&= ~WVR_VREDRAW
;
1078 if (OldClientRect
.right
- OldClientRect
.left
==
1079 NewClientRect
.right
- NewClientRect
.left
)
1081 WvrFlags
&= ~WVR_HREDRAW
;
1084 /* FIXME: Actually do something with WVR_VALIDRECTS */
1086 if ( NewClientRect
.left
!= OldClientRect
.left
||
1087 NewClientRect
.top
!= OldClientRect
.top
)
1089 WinPosInternalMoveWindow(Window
,
1090 NewClientRect
.left
- OldClientRect
.left
,
1091 NewClientRect
.top
- OldClientRect
.top
);
1094 Window
->rcWindow
= NewWindowRect
;
1095 Window
->rcClient
= NewClientRect
;
1097 if (!(WinPos
.flags
& SWP_SHOWWINDOW
) && (WinPos
.flags
& SWP_HIDEWINDOW
))
1099 /* Clear the update region */
1100 co_UserRedrawWindow( Window
,
1103 RDW_VALIDATE
| RDW_NOFRAME
| RDW_NOERASE
| RDW_NOINTERNALPAINT
| RDW_ALLCHILDREN
);
1105 if ((Window
->style
& WS_VISIBLE
) &&
1106 Window
->spwndParent
== UserGetDesktopWindow())
1108 co_IntShellHookNotify(HSHELL_WINDOWDESTROYED
, (LPARAM
)Window
->head
.h
);
1110 Window
->style
&= ~WS_VISIBLE
;
1112 else if (WinPos
.flags
& SWP_SHOWWINDOW
)
1114 if (!(Window
->style
& WS_VISIBLE
) &&
1115 Window
->spwndParent
== UserGetDesktopWindow() )
1117 co_IntShellHookNotify(HSHELL_WINDOWCREATED
, (LPARAM
)Window
->head
.h
);
1119 Window
->style
|= WS_VISIBLE
;
1122 if (Window
->hrgnUpdate
!= NULL
&& Window
->hrgnUpdate
!= (HRGN
)1)
1124 NtGdiOffsetRgn(Window
->hrgnUpdate
,
1125 NewWindowRect
.left
- OldWindowRect
.left
,
1126 NewWindowRect
.top
- OldWindowRect
.top
);
1129 DceResetActiveDCEs(Window
);
1131 if (!(WinPos
.flags
& SWP_NOREDRAW
))
1133 /* Determine the new visible region */
1134 VisAfter
= VIS_ComputeVisibleRegion(Window
, FALSE
, FALSE
, TRUE
);
1137 if ( VisAfter
!= NULL
&&
1138 (VisRgn
= (PROSRGNDATA
)RGNOBJAPI_Lock(VisAfter
, NULL
)) &&
1139 REGION_GetRgnBox(VisRgn
, &TempRect
) == NULLREGION
)
1141 RGNOBJAPI_Unlock(VisRgn
);
1142 GreDeleteObject(VisAfter
);
1147 RGNOBJAPI_Unlock(VisRgn
);
1148 NtGdiOffsetRgn(VisAfter
, -Window
->rcWindow
.left
, -Window
->rcWindow
.top
);
1152 * Determine which pixels can be copied from the old window position
1153 * to the new. Those pixels must be visible in both the old and new
1154 * position. Also, check the class style to see if the windows of this
1155 * class need to be completely repainted on (horizontal/vertical) size
1158 if ( VisBefore
!= NULL
&&
1160 !(WinPos
.flags
& SWP_NOCOPYBITS
) &&
1161 ((WinPos
.flags
& SWP_NOSIZE
) || !(WvrFlags
& WVR_REDRAW
)) &&
1162 !(Window
->ExStyle
& WS_EX_TRANSPARENT
) )
1164 CopyRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
1165 RgnType
= NtGdiCombineRgn(CopyRgn
, VisAfter
, VisBefore
, RGN_AND
);
1168 * If this is (also) a window resize, the whole nonclient area
1169 * needs to be repainted. So we limit the copy to the client area,
1170 * 'cause there is no use in copying it (would possibly cause
1171 * "flashing" too). However, if the copy region is already empty,
1172 * we don't have to crop (can't take anything away from an empty
1175 if (!(WinPos
.flags
& SWP_NOSIZE
) &&
1177 RgnType
!= NULLREGION
)
1179 PROSRGNDATA pCopyRgn
;
1180 RECTL ORect
= OldClientRect
;
1181 RECTL NRect
= NewClientRect
;
1182 RECTL_vOffsetRect(&ORect
, - OldWindowRect
.left
, - OldWindowRect
.top
);
1183 RECTL_vOffsetRect(&NRect
, - NewWindowRect
.left
, - NewWindowRect
.top
);
1184 RECTL_bIntersectRect(&CopyRect
, &ORect
, &NRect
);
1185 pCopyRgn
= RGNOBJAPI_Lock(CopyRgn
, NULL
);
1186 REGION_CropAndOffsetRegion(pCopyRgn
, pCopyRgn
, &CopyRect
, NULL
);
1187 RGNOBJAPI_Unlock(pCopyRgn
);
1190 /* No use in copying bits which are in the update region. */
1191 if (Window
->hrgnUpdate
!= NULL
)
1193 NtGdiOffsetRgn(CopyRgn
, NewWindowRect
.left
, NewWindowRect
.top
);
1194 NtGdiCombineRgn(CopyRgn
, CopyRgn
, Window
->hrgnUpdate
, RGN_DIFF
);
1195 NtGdiOffsetRgn(CopyRgn
, -NewWindowRect
.left
, -NewWindowRect
.top
);
1199 * Now, get the bounding box of the copy region. If it's empty
1200 * there's nothing to copy. Also, it's no use copying bits onto
1203 if ( (VisRgn
= (PROSRGNDATA
)RGNOBJAPI_Lock(CopyRgn
, NULL
)) &&
1204 REGION_GetRgnBox(VisRgn
, &CopyRect
) == NULLREGION
)
1206 /* Nothing to copy, clean up */
1207 RGNOBJAPI_Unlock(VisRgn
);
1208 REGION_FreeRgnByHandle(CopyRgn
);
1211 else if (OldWindowRect
.left
!= NewWindowRect
.left
||
1212 OldWindowRect
.top
!= NewWindowRect
.top
)
1216 RGNOBJAPI_Unlock(VisRgn
);
1220 * Small trick here: there is no function to bitblt a region. So
1221 * we set the region as the clipping region, take the bounding box
1222 * of the region and bitblt that. Since nothing outside the clipping
1223 * region is copied, this has the effect of bitblt'ing the region.
1225 * Since NtUserGetDCEx takes ownership of the clip region, we need
1226 * to create a copy of CopyRgn and pass that. We need CopyRgn later
1228 NtGdiOffsetRgn(CopyRgn
, NewWindowRect
.left
, NewWindowRect
.top
);
1229 Dc
= UserGetDCEx( Window
,
1231 DCX_WINDOW
|DCX_CACHE
|DCX_INTERSECTRGN
|DCX_CLIPSIBLINGS
|DCX_KEEPCLIPRGN
);
1233 CopyRect
.left
, CopyRect
.top
,
1234 CopyRect
.right
- CopyRect
.left
,
1235 CopyRect
.bottom
- CopyRect
.top
,
1237 CopyRect
.left
+ (OldWindowRect
.left
- NewWindowRect
.left
),
1238 CopyRect
.top
+ (OldWindowRect
.top
- NewWindowRect
.top
),
1243 UserReleaseDC(Window
, Dc
, FALSE
);
1244 IntValidateParent(Window
, CopyRgn
, FALSE
);
1245 NtGdiOffsetRgn(CopyRgn
, -NewWindowRect
.left
, -NewWindowRect
.top
);
1249 RGNOBJAPI_Unlock(VisRgn
);
1257 /* We need to redraw what wasn't visible before */
1258 if (VisAfter
!= NULL
)
1260 DirtyRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
1261 if (CopyRgn
!= NULL
)
1263 RgnType
= NtGdiCombineRgn(DirtyRgn
, VisAfter
, CopyRgn
, RGN_DIFF
);
1267 RgnType
= NtGdiCombineRgn(DirtyRgn
, VisAfter
, 0, RGN_COPY
);
1269 if (RgnType
!= ERROR
&& RgnType
!= NULLREGION
)
1272 NtGdiOffsetRgn(DirtyRgn, Window->rcWindow.left, Window->rcWindow.top);
1273 IntInvalidateWindows( Window,
1275 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
1277 GreDeleteObject(DirtyRgn);
1280 PWND Parent
= Window
->spwndParent
;
1282 NtGdiOffsetRgn( DirtyRgn
,
1283 Window
->rcWindow
.left
,
1284 Window
->rcWindow
.top
);
1285 if ( (Window
->style
& WS_CHILD
) &&
1287 !(Parent
->style
& WS_CLIPCHILDREN
))
1289 IntInvalidateWindows( Parent
,
1291 RDW_ERASE
| RDW_INVALIDATE
);
1292 co_IntPaintWindows(Parent
, RDW_ERASENOW
, FALSE
);
1296 IntInvalidateWindows( Window
,
1298 RDW_ERASE
| RDW_FRAME
| RDW_INVALIDATE
| RDW_ALLCHILDREN
);
1301 REGION_FreeRgnByHandle(DirtyRgn
);
1304 if (CopyRgn
!= NULL
)
1306 REGION_FreeRgnByHandle(CopyRgn
);
1309 /* Expose what was covered before but not covered anymore */
1310 if (VisBefore
!= NULL
)
1312 ExposedRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
1313 NtGdiCombineRgn(ExposedRgn
, VisBefore
, NULL
, RGN_COPY
);
1314 NtGdiOffsetRgn( ExposedRgn
,
1315 OldWindowRect
.left
- NewWindowRect
.left
,
1316 OldWindowRect
.top
- NewWindowRect
.top
);
1318 if (VisAfter
!= NULL
)
1319 RgnType
= NtGdiCombineRgn(ExposedRgn
, ExposedRgn
, VisAfter
, RGN_DIFF
);
1321 RgnType
= SIMPLEREGION
;
1323 if (RgnType
!= ERROR
&& RgnType
!= NULLREGION
)
1325 co_VIS_WindowLayoutChanged(Window
, ExposedRgn
);
1327 REGION_FreeRgnByHandle(ExposedRgn
);
1328 REGION_FreeRgnByHandle(VisBefore
);
1331 if (VisAfter
!= NULL
)
1333 REGION_FreeRgnByHandle(VisAfter
);
1336 if (!(WinPos
.flags
& SWP_NOACTIVATE
))
1338 if ((Window
->style
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1340 co_IntSendMessageNoWait(WinPos
.hwnd
, WM_CHILDACTIVATE
, 0, 0);
1344 co_IntSetForegroundWindow(Window
);
1349 if ((WinPos
.flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOPOSCHANGE
)
1351 /* WM_WINDOWPOSCHANGED is sent even if SWP_NOSENDCHANGING is set
1352 and always contains final window position.
1354 WinPos
.x
= NewWindowRect
.left
;
1355 WinPos
.y
= NewWindowRect
.top
;
1356 WinPos
.cx
= NewWindowRect
.right
- NewWindowRect
.left
;
1357 WinPos
.cy
= NewWindowRect
.bottom
- NewWindowRect
.top
;
1358 co_IntSendMessageNoWait(WinPos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
) &WinPos
);
1365 co_WinPosGetNonClientSize(PWND Window
, RECT
* WindowRect
, RECT
* ClientRect
)
1369 ASSERT_REFS_CO(Window
);
1371 *ClientRect
= *WindowRect
;
1372 Result
= co_IntSendMessageNoWait(Window
->head
.h
, WM_NCCALCSIZE
, FALSE
, (LPARAM
) ClientRect
);
1374 FixClientRect(ClientRect
, WindowRect
);
1380 co_WinPosSendSizeMove(PWND Wnd
)
1382 WPARAM wParam
= SIZE_RESTORED
;
1384 Wnd
->state
&= ~WNDS_SENDSIZEMOVEMSGS
;
1385 if (Wnd
->style
& WS_MAXIMIZE
)
1387 wParam
= SIZE_MAXIMIZED
;
1389 else if (Wnd
->style
& WS_MINIMIZE
)
1391 wParam
= SIZE_MINIMIZED
;
1394 co_IntSendMessageNoWait(Wnd
->head
.h
, WM_SIZE
, wParam
,
1395 MAKELONG(Wnd
->rcClient
.right
-
1397 Wnd
->rcClient
.bottom
-
1398 Wnd
->rcClient
.top
));
1399 co_IntSendMessageNoWait(Wnd
->head
.h
, WM_MOVE
, 0,
1400 MAKELONG(Wnd
->rcClient
.left
,
1401 Wnd
->rcClient
.top
));
1402 IntEngWindowChanged(Wnd
, WOC_RGN_CLIENT
);
1406 co_WinPosShowWindow(PWND Wnd
, INT Cmd
)
1414 ASSERT_REFS_CO(Wnd
);
1416 WasVisible
= (Wnd
->style
& WS_VISIBLE
) != 0;
1426 Swp
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
1427 if (Wnd
->head
.h
!= UserGetActiveWindow())
1428 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1432 case SW_SHOWMINNOACTIVE
:
1433 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1435 case SW_SHOWMINIMIZED
:
1436 Swp
|= SWP_SHOWWINDOW
;
1440 Swp
|= SWP_NOACTIVATE
;
1441 if (!(Wnd
->style
& WS_MINIMIZE
))
1443 Swp
|= co_WinPosMinMaximize(Wnd
, SW_MINIMIZE
, &NewPos
) |
1448 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1451 Swp
|= SWP_FRAMECHANGED
;
1457 case SW_SHOWMAXIMIZED
:
1459 Swp
|= SWP_SHOWWINDOW
;
1460 if (!(Wnd
->style
& WS_MAXIMIZE
))
1462 Swp
|= co_WinPosMinMaximize(Wnd
, SW_MAXIMIZE
, &NewPos
) |
1467 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1470 Swp
|= SWP_FRAMECHANGED
;
1477 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1480 if (WasVisible
) return(TRUE
); // Nothing to do!
1481 Swp
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
1482 /* Don't activate the topmost window. */
1485 case SW_SHOWNOACTIVATE
:
1486 //Swp |= SWP_NOZORDER;
1487 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1490 case SW_SHOWDEFAULT
:
1492 Swp
|= SWP_SHOWWINDOW
;
1493 if (Wnd
->style
& (WS_MINIMIZE
| WS_MAXIMIZE
))
1495 Swp
|= co_WinPosMinMaximize(Wnd
, SW_RESTORE
, &NewPos
) |
1500 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1503 Swp
|= SWP_FRAMECHANGED
;
1509 ShowFlag
= (Cmd
!= SW_HIDE
);
1511 if (ShowFlag
!= WasVisible
)
1513 co_IntSendMessageNoWait(Wnd
->head
.h
, WM_SHOWWINDOW
, ShowFlag
, 0);
1516 /* We can't activate a child window */
1517 if ((Wnd
->style
& WS_CHILD
) &&
1518 !(Wnd
->ExStyle
& WS_EX_MDICHILD
))
1520 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1523 co_WinPosSetWindowPos(Wnd
, 0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
)
1524 ? HWND_TOPMOST
: HWND_TOP
,
1525 NewPos
.left
, NewPos
.top
, NewPos
.right
, NewPos
.bottom
, LOWORD(Swp
));
1527 if ((Cmd
== SW_HIDE
) || (Cmd
== SW_MINIMIZE
))
1529 PWND ThreadFocusWindow
;
1531 /* FIXME: This will cause the window to be activated irrespective
1532 * of whether it is owned by the same thread. Has to be done
1536 if (Wnd
->head
.h
== UserGetActiveWindow())
1538 co_WinPosActivateOtherWindow(Wnd
);
1543 ThreadFocusWindow
= UserGetWindowObject(IntGetThreadFocusWindow());
1545 /* Revert focus to parent */
1546 if (ThreadFocusWindow
&& (Wnd
== ThreadFocusWindow
||
1547 IntIsChildWindow(Wnd
, ThreadFocusWindow
)))
1549 //faxme: as long as we have ref on Window, we also, indirectly, have ref on parent...
1550 co_UserSetFocus(Wnd
->spwndParent
);
1554 /* FIXME: Check for window destruction. */
1556 if ((Wnd
->state
& WNDS_SENDSIZEMOVEMSGS
) &&
1557 !(Wnd
->state2
& WNDS2_INDESTROY
))
1559 co_WinPosSendSizeMove(Wnd
);
1562 /* Activate the window if activation is not requested and the window is not minimized */
1564 if (!(Swp & (SWP_NOACTIVATE | SWP_HIDEWINDOW)) && !(Window->style & WS_MINIMIZE))
1566 WinPosChangeActiveWindow(Wnd, FALSE);
1575 /* find child of 'parent' that contains the given point (in parent-relative coords) */
1576 PWND
child_window_from_point(PWND parent
, int x
, int y
)
1578 PWND Wnd
;// = parent->spwndChild;
1580 // LIST_FOR_EACH_ENTRY( Wnd, &parent->children, struct window, entry )
1581 for (Wnd
= parent
->spwndChild
; Wnd
; Wnd
= Wnd
->spwndNext
)
1583 if (!IntPtInWindow( Wnd
, x
, y
)) continue; /* skip it */
1585 /* if window is minimized or disabled, return at once */
1586 if (Wnd
->style
& (WS_MINIMIZE
|WS_DISABLED
)) return Wnd
;
1588 /* if point is not in client area, return at once */
1589 if (x
< Wnd
->rcClient
.left
|| x
>= Wnd
->rcClient
.right
||
1590 y
< Wnd
->rcClient
.top
|| y
>= Wnd
->rcClient
.bottom
)
1593 return child_window_from_point( Wnd
, x
- Wnd
->rcClient
.left
, y
- Wnd
->rcClient
.top
);
1595 return parent
; /* not found any child */
1599 /* wine server: child_window_from_point
1601 Caller must dereference the "returned" Window
1605 co_WinPosSearchChildren(
1607 PUSER_MESSAGE_QUEUE OnlyHitTests
,
1615 USER_REFERENCE_ENTRY Ref
;
1617 ASSERT_REFS_CO(ScopeWin
);
1619 if ((List
= IntWinListChildren(ScopeWin
)))
1621 for (phWnd
= List
; *phWnd
; ++phWnd
)
1623 if (!(Current
= UserGetWindowObject(*phWnd
)))
1626 if (!(Current
->style
& WS_VISIBLE
))
1631 if ((Current
->style
& (WS_POPUP
| WS_CHILD
| WS_DISABLED
)) ==
1632 (WS_CHILD
| WS_DISABLED
))
1637 if (!IntPtInWindow(Current
, Point
->x
, Point
->y
))
1642 if (*Window
) UserDereferenceObject(*Window
);
1644 UserReferenceObject(*Window
);
1646 if (Current
->style
& WS_MINIMIZE
)
1648 *HitTest
= HTCAPTION
;
1652 if (Current
->style
& WS_DISABLED
)
1658 UserRefObjectCo(Current
, &Ref
);
1660 if (OnlyHitTests
&& (Current
->head
.pti
->MessageQueue
== OnlyHitTests
))
1662 *HitTest
= co_IntSendMessage(Current
->head
.h
, WM_NCHITTEST
, 0,
1663 MAKELONG(Point
->x
, Point
->y
));
1664 if ((*HitTest
) == (USHORT
)HTTRANSPARENT
)
1666 UserDerefObjectCo(Current
);
1671 *HitTest
= HTCLIENT
;
1673 if (Point
->x
>= Current
->rcClient
.left
&&
1674 Point
->x
< Current
->rcClient
.right
&&
1675 Point
->y
>= Current
->rcClient
.top
&&
1676 Point
->y
< Current
->rcClient
.bottom
)
1678 co_WinPosSearchChildren(Current
, OnlyHitTests
, Point
, Window
, HitTest
);
1681 UserDerefObjectCo(Current
);
1689 /* wine: WINPOS_WindowFromPoint */
1691 co_WinPosWindowFromPoint(PWND ScopeWin
, PUSER_MESSAGE_QUEUE OnlyHitTests
, POINT
*WinPoint
,
1694 HWND DesktopWindowHandle
;
1696 POINT Point
= *WinPoint
;
1699 ASSERT_REFS_CO(ScopeWin
);
1705 DPRINT1("WinPosWindowFromPoint(): ScopeWin == NULL!\n");
1709 if (ScopeWin
->style
& WS_DISABLED
)
1714 /* Translate the point to the space of the scope window. */
1715 DesktopWindowHandle
= IntGetDesktopWindow();
1716 if((DesktopWindowHandle
!= ScopeWin
->head
.h
) &&
1717 (DesktopWindow
= UserGetWindowObject(DesktopWindowHandle
)))
1719 Point
.x
+= ScopeWin
->rcClient
.left
- DesktopWindow
->rcClient
.left
;
1720 Point
.y
+= ScopeWin
->rcClient
.top
- DesktopWindow
->rcClient
.top
;
1723 HitTest
= HTNOWHERE
;
1725 co_WinPosSearchChildren(ScopeWin
, OnlyHitTests
, &Point
, Window
, &HitTest
);
1727 return ((*Window
) ? HitTest
: HTNOWHERE
);
1732 NtUserGetMinMaxInfo(
1734 MINMAXINFO
*MinMaxInfo
,
1739 MINMAXINFO SafeMinMax
;
1742 USER_REFERENCE_ENTRY Ref
;
1744 DPRINT("Enter NtUserGetMinMaxInfo\n");
1745 UserEnterExclusive();
1747 if(!(Window
= UserGetWindowObject(hWnd
)))
1753 UserRefObjectCo(Window
, &Ref
);
1755 Size
.x
= Window
->rcWindow
.left
;
1756 Size
.y
= Window
->rcWindow
.top
;
1757 WinPosInitInternalPos(Window
, &Size
,
1760 co_WinPosGetMinMaxInfo(Window
, &SafeMinMax
.ptMaxSize
, &SafeMinMax
.ptMaxPosition
,
1761 &SafeMinMax
.ptMinTrackSize
, &SafeMinMax
.ptMaxTrackSize
);
1763 Status
= MmCopyToCaller(MinMaxInfo
, &SafeMinMax
, sizeof(MINMAXINFO
));
1764 if(!NT_SUCCESS(Status
))
1766 SetLastNtError(Status
);
1774 if (Window
) UserDerefObjectCo(Window
);
1776 DPRINT("Leave NtUserGetMinMaxInfo, ret=%i\n", ret
);