2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS kernel
23 * FILE: subsys/win32k/ntuser/window.c
24 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
26 * 06-06-2001 CSH NtGdid
28 /* INCLUDES ******************************************************************/
36 co_IntPaintWindows(PWINDOW_OBJECT Window
, ULONG Flags
, BOOL Recurse
);
39 IntValidateParent(PWINDOW_OBJECT Child
, HRGN hValidateRgn
, BOOL Recurse
);
41 /* GLOBALS *******************************************************************/
43 #define MINMAX_NOSWP (0x00010000)
45 #define SWP_EX_NOCOPY 0x0001
46 #define SWP_EX_PAINTSELF 0x0002
48 #define SWP_AGG_NOGEOMETRYCHANGE \
49 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
50 #define SWP_AGG_NOPOSCHANGE \
51 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
52 #define SWP_AGG_STATUSFLAGS \
53 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
55 /* FUNCTIONS *****************************************************************/
58 IntGetClientOrigin(PWINDOW_OBJECT Window OPTIONAL
, LPPOINT Point
)
60 Window
= Window
? Window
: UserGetWindowObject(IntGetDesktopWindow());
63 Point
->x
= Point
->y
= 0;
66 Point
->x
= Window
->Wnd
->rcClient
.left
;
67 Point
->y
= Window
->Wnd
->rcClient
.top
;
73 UserGetClientOrigin(PWINDOW_OBJECT 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( PWINDOW_OBJECT Wnd OPTIONAL
)
115 if (!Wnd
) return FALSE
;
116 if (!Wnd
->Wnd
) return FALSE
;
117 style
= Wnd
->Wnd
->style
;
118 if (!(style
& WS_VISIBLE
) &&
119 Wnd
->pti
->pEThread
->ThreadsProcess
!= CsrProcess
) return FALSE
;
120 if ((style
& WS_MINIMIZE
) &&
121 Wnd
->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(PWINDOW_OBJECT Window
)
138 PWINDOW_OBJECT WndTo
= NULL
;
140 USER_REFERENCE_ENTRY Ref
;
143 ASSERT_REFS_CO(Window
);
147 if (IntIsDesktopWindow(Window
))
149 IntSetFocusMessageQueue(NULL
);
153 /* If this is popup window, try to activate the owner first. */
154 if ((Wnd
->style
& WS_POPUP
) && (WndTo
= IntGetOwner(Window
)))
156 WndTo
= UserGetAncestor( WndTo
, GA_ROOT
);
157 if (can_activate_window(WndTo
)) goto done
;
160 /* Pick a next top-level window. */
161 /* FIXME: Search for non-tooltip windows first. */
165 if (!(WndTo
= WndTo
->spwndNext
)) break;
166 if (can_activate_window( WndTo
)) break;
171 if (WndTo
) UserRefObjectCo(WndTo
, &Ref
);
173 Fg
= UserGetForegroundWindow();
174 if ((!Fg
|| Window
->hSelf
== Fg
) && WndTo
)//fixme: ok if WndTo is NULL??
176 /* fixme: wine can pass WndTo=NULL to co_IntSetForegroundWindow. hmm */
177 if (co_IntSetForegroundWindow(WndTo
))
179 UserDerefObjectCo(WndTo
);
184 if (!co_IntSetActiveWindow(WndTo
)) /* ok for WndTo to be NULL here */
185 co_IntSetActiveWindow(0);
187 if (WndTo
) UserDerefObjectCo(WndTo
);
193 co_WinPosArrangeIconicWindows(PWINDOW_OBJECT parent
)
196 INT i
, x
, y
, xspacing
, yspacing
;
197 HWND
*List
= IntWinListChildren(parent
);
199 ASSERT_REFS_CO(parent
);
201 IntGetClientRect( parent
, &rectParent
);
203 y
= rectParent
.bottom
;
205 xspacing
= UserGetSystemMetrics(SM_CXMINSPACING
);
206 yspacing
= UserGetSystemMetrics(SM_CYMINSPACING
);
208 DPRINT("X:%d Y:%d XS:%d YS:%d\n",x
,y
,xspacing
,yspacing
);
210 for( i
= 0; List
[i
]; i
++)
212 PWINDOW_OBJECT WndChild
;
215 if (!(WndChild
= UserGetWindowObject(List
[i
])))
218 ChildWnd
= WndChild
->Wnd
;
220 if((ChildWnd
->style
& WS_MINIMIZE
) != 0 )
222 USER_REFERENCE_ENTRY Ref
;
223 UserRefObjectCo(WndChild
, &Ref
);
225 co_WinPosSetWindowPos(WndChild
, 0, x
+ UserGetSystemMetrics(SM_CXBORDER
),
226 y
- yspacing
- UserGetSystemMetrics(SM_CYBORDER
)
227 , 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
229 UserDerefObjectCo(WndChild
);
231 if (x
<= rectParent
.right
- xspacing
)
246 WinPosFindIconPos(PWINDOW_OBJECT Window
, POINT
*Pos
)
252 WinPosInitInternalPos(PWINDOW_OBJECT Window
, POINT
*pt
, RECTL
*RestoreRect
)
254 PWINDOW_OBJECT Parent
;
256 PWND Wnd
= Window
->Wnd
;
258 if (!Wnd
->InternalPosInitialized
)
262 Parent
= Window
->spwndParent
;
265 if(IntIsDesktopWindow(Parent
))
266 UserSystemParametersInfo(SPI_GETWORKAREA
, 0, &WorkArea
, 0);
268 WorkArea
= Parent
->Wnd
->rcClient
;
271 UserSystemParametersInfo(SPI_GETWORKAREA
, 0, &WorkArea
, 0);
273 Wnd
->InternalPos
.NormalRect
= Window
->Wnd
->rcWindow
;
274 IntGetWindowBorderMeasures(Window
, &XInc
, &YInc
);
275 Wnd
->InternalPos
.MaxPos
.x
= WorkArea
.left
- XInc
;
276 Wnd
->InternalPos
.MaxPos
.y
= WorkArea
.top
- YInc
;
277 Wnd
->InternalPos
.IconPos
.x
= WorkArea
.left
;
278 Wnd
->InternalPos
.IconPos
.y
= WorkArea
.bottom
- UserGetSystemMetrics(SM_CYMINIMIZED
);
280 Wnd
->InternalPosInitialized
= TRUE
;
282 if (Wnd
->style
& WS_MINIMIZE
)
284 Wnd
->InternalPos
.IconPos
= *pt
;
286 else if (Wnd
->style
& WS_MAXIMIZE
)
288 Wnd
->InternalPos
.MaxPos
= *pt
;
290 else if (RestoreRect
!= NULL
)
292 Wnd
->InternalPos
.NormalRect
= *RestoreRect
;
297 co_WinPosMinMaximize(PWINDOW_OBJECT Window
, UINT ShowFlag
, RECT
* NewPos
)
303 ASSERT_REFS_CO(Window
);
306 Size
.x
= Wnd
->rcWindow
.left
;
307 Size
.y
= Wnd
->rcWindow
.top
;
308 WinPosInitInternalPos(Window
, &Size
, &Wnd
->rcWindow
);
310 if (co_HOOK_CallHooks( WH_CBT
, HCBT_MINMAX
, (WPARAM
)Window
->hSelf
, ShowFlag
))
311 return SWP_NOSIZE
| SWP_NOMOVE
;
313 if (Wnd
->style
& WS_MINIMIZE
)
315 if (!co_IntSendMessageNoWait(Window
->hSelf
, WM_QUERYOPEN
, 0, 0))
317 return(SWP_NOSIZE
| SWP_NOMOVE
);
319 SwpFlags
|= SWP_NOCOPYBITS
;
325 if (Wnd
->style
& WS_MAXIMIZE
)
327 Window
->state
|= WINDOWOBJECT_RESTOREMAX
;
328 Wnd
->style
&= ~WS_MAXIMIZE
;
332 Window
->state
&= ~WINDOWOBJECT_RESTOREMAX
;
334 co_UserRedrawWindow(Window
, NULL
, 0, RDW_VALIDATE
| RDW_NOERASE
|
335 RDW_NOINTERNALPAINT
);
336 Wnd
->style
|= WS_MINIMIZE
;
337 WinPosFindIconPos(Window
, &Wnd
->InternalPos
.IconPos
);
338 RECTL_vSetRect(NewPos
, Wnd
->InternalPos
.IconPos
.x
, Wnd
->InternalPos
.IconPos
.y
,
339 UserGetSystemMetrics(SM_CXMINIMIZED
),
340 UserGetSystemMetrics(SM_CYMINIMIZED
));
341 SwpFlags
|= SWP_NOCOPYBITS
;
347 co_WinPosGetMinMaxInfo(Window
, &Size
, &Wnd
->InternalPos
.MaxPos
,
349 DPRINT("Maximize: %d,%d %dx%d\n",
350 Wnd
->InternalPos
.MaxPos
.x
, Wnd
->InternalPos
.MaxPos
.y
, Size
.x
, Size
.y
);
351 if (Wnd
->style
& WS_MINIMIZE
)
353 Wnd
->style
&= ~WS_MINIMIZE
;
355 Wnd
->style
|= WS_MAXIMIZE
;
356 RECTL_vSetRect(NewPos
, Wnd
->InternalPos
.MaxPos
.x
, Wnd
->InternalPos
.MaxPos
.y
,
363 if (Wnd
->style
& WS_MINIMIZE
)
365 Wnd
->style
&= ~WS_MINIMIZE
;
366 if (Window
->state
& WINDOWOBJECT_RESTOREMAX
)
368 co_WinPosGetMinMaxInfo(Window
, &Size
,
369 &Wnd
->InternalPos
.MaxPos
, NULL
, NULL
);
370 Wnd
->style
|= WS_MAXIMIZE
;
371 RECTL_vSetRect(NewPos
, Wnd
->InternalPos
.MaxPos
.x
,
372 Wnd
->InternalPos
.MaxPos
.y
, Size
.x
, Size
.y
);
377 *NewPos
= Wnd
->InternalPos
.NormalRect
;
378 NewPos
->right
-= NewPos
->left
;
379 NewPos
->bottom
-= NewPos
->top
;
385 if (!(Wnd
->style
& WS_MAXIMIZE
))
389 Wnd
->style
&= ~WS_MAXIMIZE
;
390 *NewPos
= Wnd
->InternalPos
.NormalRect
;
391 NewPos
->right
-= NewPos
->left
;
392 NewPos
->bottom
-= NewPos
->top
;
402 UserHasWindowEdge(DWORD Style
, DWORD ExStyle
)
404 if (Style
& WS_MINIMIZE
)
406 if (ExStyle
& WS_EX_DLGMODALFRAME
)
408 if (ExStyle
& WS_EX_STATICEDGE
)
410 if (Style
& WS_THICKFRAME
)
413 if (Style
== WS_DLGFRAME
|| Style
== WS_CAPTION
)
419 UserGetWindowBorders(DWORD Style
, DWORD ExStyle
, SIZE
*Size
, BOOL WithClient
)
423 if (UserHasWindowEdge(Style
, ExStyle
))
425 else if (ExStyle
& WS_EX_STATICEDGE
)
427 if ((ExStyle
& WS_EX_CLIENTEDGE
) && WithClient
)
429 if (Style
& WS_CAPTION
|| ExStyle
& WS_EX_DLGMODALFRAME
)
431 Size
->cx
= Size
->cy
= Border
;
432 if ((Style
& WS_THICKFRAME
) && !(Style
& WS_MINIMIZE
))
434 Size
->cx
+= UserGetSystemMetrics(SM_CXFRAME
) - UserGetSystemMetrics(SM_CXDLGFRAME
);
435 Size
->cy
+= UserGetSystemMetrics(SM_CYFRAME
) - UserGetSystemMetrics(SM_CYDLGFRAME
);
437 Size
->cx
*= UserGetSystemMetrics(SM_CXBORDER
);
438 Size
->cy
*= UserGetSystemMetrics(SM_CYBORDER
);
442 UserAdjustWindowRectEx(LPRECT lpRect
,
451 lpRect
->top
-= UserGetSystemMetrics(SM_CYMENU
);
453 if ((dwStyle
& WS_CAPTION
) == WS_CAPTION
)
455 if (dwExStyle
& WS_EX_TOOLWINDOW
)
456 lpRect
->top
-= UserGetSystemMetrics(SM_CYSMCAPTION
);
458 lpRect
->top
-= UserGetSystemMetrics(SM_CYCAPTION
);
460 UserGetWindowBorders(dwStyle
, dwExStyle
, &BorderSize
, TRUE
);
470 co_WinPosGetMinMaxInfo(PWINDOW_OBJECT Window
, POINT
* MaxSize
, POINT
* MaxPos
,
471 POINT
* MinTrack
, POINT
* MaxTrack
)
476 LONG style
= Window
->Wnd
->style
;
478 LONG exstyle
= Window
->Wnd
->ExStyle
;
481 ASSERT_REFS_CO(Window
);
483 /* Compute default values */
485 rc
= Window
->Wnd
->rcWindow
;
486 MinMax
.ptReserved
.x
= rc
.left
;
487 MinMax
.ptReserved
.y
= rc
.top
;
489 if ((style
& WS_CAPTION
) == WS_CAPTION
)
490 adjustedStyle
= style
& ~WS_BORDER
; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
492 adjustedStyle
= style
;
494 if(Window
->Wnd
->spwndParent
)
495 IntGetClientRect(Window
->spwndParent
, &rc
);
496 UserAdjustWindowRectEx(&rc
, adjustedStyle
, ((style
& WS_POPUP
) && Window
->Wnd
->IDMenu
), exstyle
);
501 MinMax
.ptMaxSize
.x
= rc
.right
- rc
.left
;
502 MinMax
.ptMaxSize
.y
= rc
.bottom
- rc
.top
;
503 if (style
& (WS_DLGFRAME
| WS_BORDER
))
505 MinMax
.ptMinTrackSize
.x
= UserGetSystemMetrics(SM_CXMINTRACK
);
506 MinMax
.ptMinTrackSize
.y
= UserGetSystemMetrics(SM_CYMINTRACK
);
510 MinMax
.ptMinTrackSize
.x
= 2 * xinc
;
511 MinMax
.ptMinTrackSize
.y
= 2 * yinc
;
513 MinMax
.ptMaxTrackSize
.x
= UserGetSystemMetrics(SM_CXMAXTRACK
);
514 MinMax
.ptMaxTrackSize
.y
= UserGetSystemMetrics(SM_CYMAXTRACK
);
515 MinMax
.ptMaxPosition
.x
= -xinc
;
516 MinMax
.ptMaxPosition
.y
= -yinc
;
518 //if (!EMPTYPOINT(win->max_pos)) MinMax.ptMaxPosition = win->max_pos;
520 co_IntSendMessage(Window
->hSelf
, WM_GETMINMAXINFO
, 0, (LPARAM
)&MinMax
);
522 /* if the app didn't change the values, adapt them for the current monitor */
523 if ((monitor
= IntGetPrimaryMonitor()))
527 rc_work
= monitor
->rcMonitor
;
529 if (style
& WS_MAXIMIZEBOX
)
531 if ((style
& WS_CAPTION
) == WS_CAPTION
|| !(style
& (WS_CHILD
| WS_POPUP
)))
532 rc_work
= monitor
->rcWork
;
535 if (MinMax
.ptMaxSize
.x
== UserGetSystemMetrics(SM_CXSCREEN
) + 2 * xinc
&&
536 MinMax
.ptMaxSize
.y
== UserGetSystemMetrics(SM_CYSCREEN
) + 2 * yinc
)
538 MinMax
.ptMaxSize
.x
= (rc_work
.right
- rc_work
.left
) + 2 * xinc
;
539 MinMax
.ptMaxSize
.y
= (rc_work
.bottom
- rc_work
.top
) + 2 * yinc
;
541 if (MinMax
.ptMaxPosition
.x
== -xinc
&& MinMax
.ptMaxPosition
.y
== -yinc
)
543 MinMax
.ptMaxPosition
.x
= rc_work
.left
- xinc
;
544 MinMax
.ptMaxPosition
.y
= rc_work
.top
- yinc
;
549 MinMax
.ptMaxTrackSize
.x
= max(MinMax
.ptMaxTrackSize
.x
,
550 MinMax
.ptMinTrackSize
.x
);
551 MinMax
.ptMaxTrackSize
.y
= max(MinMax
.ptMaxTrackSize
.y
,
552 MinMax
.ptMinTrackSize
.y
);
555 *MaxSize
= MinMax
.ptMaxSize
;
557 *MaxPos
= MinMax
.ptMaxPosition
;
559 *MinTrack
= MinMax
.ptMinTrackSize
;
561 *MaxTrack
= MinMax
.ptMaxTrackSize
;
563 return 0; //FIXME: what does it return?
568 FixClientRect(PRECTL ClientRect
, PRECTL WindowRect
)
570 if (ClientRect
->left
< WindowRect
->left
)
572 ClientRect
->left
= WindowRect
->left
;
574 else if (WindowRect
->right
< ClientRect
->left
)
576 ClientRect
->left
= WindowRect
->right
;
578 if (ClientRect
->right
< WindowRect
->left
)
580 ClientRect
->right
= WindowRect
->left
;
582 else if (WindowRect
->right
< ClientRect
->right
)
584 ClientRect
->right
= WindowRect
->right
;
586 if (ClientRect
->top
< WindowRect
->top
)
588 ClientRect
->top
= WindowRect
->top
;
590 else if (WindowRect
->bottom
< ClientRect
->top
)
592 ClientRect
->top
= WindowRect
->bottom
;
594 if (ClientRect
->bottom
< WindowRect
->top
)
596 ClientRect
->bottom
= WindowRect
->top
;
598 else if (WindowRect
->bottom
< ClientRect
->bottom
)
600 ClientRect
->bottom
= WindowRect
->bottom
;
606 co_WinPosDoNCCALCSize(PWINDOW_OBJECT Window
, PWINDOWPOS WinPos
,
607 RECT
* WindowRect
, RECT
* ClientRect
)
609 PWINDOW_OBJECT Parent
;
613 ASSERT_REFS_CO(Window
);
616 /* Send WM_NCCALCSIZE message to get new client area */
617 if ((WinPos
->flags
& (SWP_FRAMECHANGED
| SWP_NOSIZE
)) != SWP_NOSIZE
)
619 NCCALCSIZE_PARAMS params
;
620 WINDOWPOS winposCopy
;
622 params
.rgrc
[0] = *WindowRect
;
623 params
.rgrc
[1] = Window
->Wnd
->rcWindow
;
624 params
.rgrc
[2] = Window
->Wnd
->rcClient
;
625 Parent
= Window
->spwndParent
;
626 if (0 != (Wnd
->style
& WS_CHILD
) && Parent
)
628 RECTL_vOffsetRect(&(params
.rgrc
[0]), - Parent
->Wnd
->rcClient
.left
,
629 - Parent
->Wnd
->rcClient
.top
);
630 RECTL_vOffsetRect(&(params
.rgrc
[1]), - Parent
->Wnd
->rcClient
.left
,
631 - Parent
->Wnd
->rcClient
.top
);
632 RECTL_vOffsetRect(&(params
.rgrc
[2]), - Parent
->Wnd
->rcClient
.left
,
633 - Parent
->Wnd
->rcClient
.top
);
635 params
.lppos
= &winposCopy
;
636 winposCopy
= *WinPos
;
638 wvrFlags
= co_IntSendMessageNoWait(Window
->hSelf
, WM_NCCALCSIZE
, TRUE
, (LPARAM
) ¶ms
);
640 /* If the application send back garbage, ignore it */
641 if (params
.rgrc
[0].left
<= params
.rgrc
[0].right
&&
642 params
.rgrc
[0].top
<= params
.rgrc
[0].bottom
)
644 *ClientRect
= params
.rgrc
[0];
645 if ((Wnd
->style
& WS_CHILD
) && Parent
)
647 RECTL_vOffsetRect(ClientRect
, Parent
->Wnd
->rcClient
.left
,
648 Parent
->Wnd
->rcClient
.top
);
650 FixClientRect(ClientRect
, WindowRect
);
653 /* FIXME: WVR_ALIGNxxx */
655 if (ClientRect
->left
!= Wnd
->rcClient
.left
||
656 ClientRect
->top
!= Wnd
->rcClient
.top
)
658 WinPos
->flags
&= ~SWP_NOCLIENTMOVE
;
661 if ((ClientRect
->right
- ClientRect
->left
!=
662 Wnd
->rcClient
.right
- Wnd
->rcClient
.left
) ||
663 (ClientRect
->bottom
- ClientRect
->top
!=
664 Wnd
->rcClient
.bottom
- Wnd
->rcClient
.top
))
666 WinPos
->flags
&= ~SWP_NOCLIENTSIZE
;
671 if (! (WinPos
->flags
& SWP_NOMOVE
)
672 && (ClientRect
->left
!= Wnd
->rcClient
.left
||
673 ClientRect
->top
!= Wnd
->rcClient
.top
))
675 WinPos
->flags
&= ~SWP_NOCLIENTMOVE
;
684 co_WinPosDoWinPosChanging(PWINDOW_OBJECT Window
,
692 ASSERT_REFS_CO(Window
);
695 if (!(WinPos
->flags
& SWP_NOSENDCHANGING
))
697 co_IntSendMessageNoWait(Window
->hSelf
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
) WinPos
);
700 *WindowRect
= Wnd
->rcWindow
;
701 *ClientRect
= Wnd
->rcClient
;
703 if (!(WinPos
->flags
& SWP_NOSIZE
))
705 WindowRect
->right
= WindowRect
->left
+ WinPos
->cx
;
706 WindowRect
->bottom
= WindowRect
->top
+ WinPos
->cy
;
709 if (!(WinPos
->flags
& SWP_NOMOVE
))
711 PWINDOW_OBJECT Parent
;
714 Parent
= Window
->spwndParent
;
715 if ((0 != (Wnd
->style
& WS_CHILD
)) && Parent
)
717 X
+= Parent
->Wnd
->rcClient
.left
;
718 Y
+= Parent
->Wnd
->rcClient
.top
;
721 WindowRect
->left
= X
;
723 WindowRect
->right
+= X
- Wnd
->rcWindow
.left
;
724 WindowRect
->bottom
+= Y
- Wnd
->rcWindow
.top
;
725 RECTL_vOffsetRect(ClientRect
,
726 X
- Wnd
->rcWindow
.left
,
727 Y
- Wnd
->rcWindow
.top
);
730 WinPos
->flags
|= SWP_NOCLIENTMOVE
| SWP_NOCLIENTSIZE
;
736 * Fix Z order taking into account owned popups -
737 * basically we need to maintain them above the window that owns them
741 WinPosDoOwnedPopups(HWND hWnd
, HWND hWndInsertAfter
)
744 HWND Owner
= UserGetWindow(hWnd
, GW_OWNER
);
745 LONG Style
= UserGetWindowLong(hWnd
, GWL_STYLE
, FALSE
);
746 PWINDOW_OBJECT DesktopWindow
, ChildObject
;
749 if ((Style
& WS_POPUP
) && Owner
)
751 /* Make sure this popup stays above the owner */
752 HWND hWndLocalPrev
= HWND_TOPMOST
;
754 if (hWndInsertAfter
!= HWND_TOPMOST
)
756 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
757 List
= IntWinListChildren(DesktopWindow
);
761 for (i
= 0; List
[i
]; i
++)
763 if (List
[i
] == Owner
)
765 if (HWND_TOP
== hWndInsertAfter
)
767 ChildObject
= UserGetWindowObject(List
[i
]);
768 if (NULL
!= ChildObject
)
770 if (0 == (ChildObject
->Wnd
->ExStyle
& WS_EX_TOPMOST
))
777 hWndLocalPrev
= List
[i
];
778 if (hWndLocalPrev
== hWndInsertAfter
)
781 hWndInsertAfter
= hWndLocalPrev
;
785 else if (Style
& WS_CHILD
)
787 return hWndInsertAfter
;
792 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
793 List
= IntWinListChildren(DesktopWindow
);
797 for (i
= 0; List
[i
]; i
++)
804 if (!(Wnd
= UserGetWindowObject(List
[i
])))
807 if ((Wnd
->Wnd
->style
& WS_POPUP
) &&
808 UserGetWindow(List
[i
], GW_OWNER
) == hWnd
)
810 USER_REFERENCE_ENTRY Ref
;
811 UserRefObjectCo(Wnd
, &Ref
);
813 co_WinPosSetWindowPos(Wnd
, hWndInsertAfter
, 0, 0, 0, 0,
814 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOSENDCHANGING
);
816 UserDerefObjectCo(Wnd
);
818 hWndInsertAfter
= List
[i
];
824 return hWndInsertAfter
;
827 /***********************************************************************
828 * WinPosInternalMoveWindow
830 * Update WindowRect and ClientRect of Window and all of its children
831 * We keep both WindowRect and ClientRect in screen coordinates internally
835 WinPosInternalMoveWindow(PWINDOW_OBJECT Window
, INT MoveX
, INT MoveY
)
837 PWINDOW_OBJECT Child
;
839 ASSERT(Window
!= Window
->spwndChild
);
841 Window
->Wnd
->rcWindow
.left
+= MoveX
;
842 Window
->Wnd
->rcWindow
.right
+= MoveX
;
843 Window
->Wnd
->rcWindow
.top
+= MoveY
;
844 Window
->Wnd
->rcWindow
.bottom
+= MoveY
;
846 Window
->Wnd
->rcClient
.left
+= MoveX
;
847 Window
->Wnd
->rcClient
.right
+= MoveX
;
848 Window
->Wnd
->rcClient
.top
+= MoveY
;
849 Window
->Wnd
->rcClient
.bottom
+= MoveY
;
851 for(Child
= Window
->spwndChild
; Child
; Child
= Child
->spwndNext
)
853 WinPosInternalMoveWindow(Child
, MoveX
, MoveY
);
858 * WinPosFixupSWPFlags
860 * Fix redundant flags and values in the WINDOWPOS structure.
864 WinPosFixupFlags(WINDOWPOS
*WinPos
, PWINDOW_OBJECT Window
)
866 PWND Wnd
= Window
->Wnd
;
868 if (!Wnd
) return FALSE
;
870 if (Wnd
->style
& WS_VISIBLE
)
872 WinPos
->flags
&= ~SWP_SHOWWINDOW
;
876 WinPos
->flags
&= ~SWP_HIDEWINDOW
;
877 if (!(WinPos
->flags
& SWP_SHOWWINDOW
))
878 WinPos
->flags
|= SWP_NOREDRAW
;
881 WinPos
->cx
= max(WinPos
->cx
, 0);
882 WinPos
->cy
= max(WinPos
->cy
, 0);
884 /* Check for right size */
885 if (Wnd
->rcWindow
.right
- Wnd
->rcWindow
.left
== WinPos
->cx
&&
886 Wnd
->rcWindow
.bottom
- Wnd
->rcWindow
.top
== WinPos
->cy
)
888 WinPos
->flags
|= SWP_NOSIZE
;
891 /* Check for right position */
892 if (Wnd
->rcWindow
.left
== WinPos
->x
&&
893 Wnd
->rcWindow
.top
== WinPos
->y
)
895 WinPos
->flags
|= SWP_NOMOVE
;
898 if (WinPos
->hwnd
== UserGetForegroundWindow())
900 WinPos
->flags
|= SWP_NOACTIVATE
; /* Already active */
903 if ((Wnd
->style
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)
905 /* Bring to the top when activating */
906 if (!(WinPos
->flags
& SWP_NOACTIVATE
))
908 WinPos
->flags
&= ~SWP_NOZORDER
;
909 WinPos
->hwndInsertAfter
= (0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
) ?
910 HWND_TOPMOST
: HWND_TOP
);
915 /* Check hwndInsertAfter */
916 if (!(WinPos
->flags
& SWP_NOZORDER
))
918 /* Fix sign extension */
919 if (WinPos
->hwndInsertAfter
== (HWND
)0xffff)
921 WinPos
->hwndInsertAfter
= HWND_TOPMOST
;
923 else if (WinPos
->hwndInsertAfter
== (HWND
)0xfffe)
925 WinPos
->hwndInsertAfter
= HWND_NOTOPMOST
;
928 if (WinPos
->hwndInsertAfter
== HWND_NOTOPMOST
)
930 WinPos
->hwndInsertAfter
= HWND_TOP
;
932 else if (HWND_TOP
== WinPos
->hwndInsertAfter
933 && 0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
))
935 /* Keep it topmost when it's already topmost */
936 WinPos
->hwndInsertAfter
= HWND_TOPMOST
;
939 /* hwndInsertAfter must be a sibling of the window */
940 if (HWND_TOPMOST
!= WinPos
->hwndInsertAfter
941 && HWND_TOP
!= WinPos
->hwndInsertAfter
942 && HWND_NOTOPMOST
!= WinPos
->hwndInsertAfter
943 && HWND_BOTTOM
!= WinPos
->hwndInsertAfter
)
945 PWINDOW_OBJECT InsAfterWnd
, Parent
= Window
->spwndParent
;
947 InsAfterWnd
= UserGetWindowObject(WinPos
->hwndInsertAfter
);
949 if (InsAfterWnd
&& UserGetAncestor(InsAfterWnd
, GA_PARENT
) != Parent
)
956 * We don't need to change the Z order of hwnd if it's already
957 * inserted after hwndInsertAfter or when inserting hwnd after
960 if ((WinPos
->hwnd
== WinPos
->hwndInsertAfter
) ||
961 (WinPos
->hwnd
== UserGetWindow(WinPos
->hwndInsertAfter
, GW_HWNDNEXT
)))
963 WinPos
->flags
|= SWP_NOZORDER
;
972 /* x and y are always screen relative */
974 co_WinPosSetWindowPos(
975 PWINDOW_OBJECT Window
,
988 HRGN VisBefore
= NULL
;
989 HRGN VisAfter
= NULL
;
990 HRGN DirtyRgn
= NULL
;
991 HRGN ExposedRgn
= NULL
;
994 RECTL OldWindowRect
, OldClientRect
;
999 PWINDOW_OBJECT Ancestor
;
1001 ASSERT_REFS_CO(Window
);
1003 if (!Window
->Wnd
) return FALSE
;
1005 /* FIXME: Get current active window from active queue. */
1008 * Only allow CSRSS to mess with the desktop window
1010 if ( Window
->hSelf
== IntGetDesktopWindow() &&
1011 Window
->pti
->pEThread
->ThreadsProcess
!= PsGetCurrentProcess())
1016 WinPos
.hwnd
= Window
->hSelf
;
1017 WinPos
.hwndInsertAfter
= WndInsertAfter
;
1022 WinPos
.flags
= flags
;
1024 co_WinPosDoWinPosChanging(Window
, &WinPos
, &NewWindowRect
, &NewClientRect
);
1026 /* Fix up the flags. */
1027 if (!WinPosFixupFlags(&WinPos
, Window
))
1029 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1033 /* Does the window still exist? */
1034 if (!IntIsWindow(WinPos
.hwnd
))
1036 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1040 Ancestor
= UserGetAncestor(Window
, GA_PARENT
);
1041 if ( (WinPos
.flags
& (SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) !=
1043 Ancestor
&& Ancestor
->hSelf
== IntGetDesktopWindow() )
1045 WinPos
.hwndInsertAfter
= WinPosDoOwnedPopups(WinPos
.hwnd
, WinPos
.hwndInsertAfter
);
1048 if (!(WinPos
.flags
& SWP_NOREDRAW
))
1050 /* Compute the visible region before the window position is changed */
1051 if (!(WinPos
.flags
& (SWP_NOREDRAW
| SWP_SHOWWINDOW
)) &&
1052 (WinPos
.flags
& (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
|
1053 SWP_HIDEWINDOW
| SWP_FRAMECHANGED
)) !=
1054 (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
))
1056 VisBefore
= VIS_ComputeVisibleRegion(Window
, FALSE
, FALSE
, TRUE
);
1059 if ( VisBefore
!= NULL
&&
1060 (VisRgn
= (PROSRGNDATA
)RGNOBJAPI_Lock(VisBefore
, NULL
)) &&
1061 REGION_GetRgnBox(VisRgn
, &TempRect
) == NULLREGION
)
1063 RGNOBJAPI_Unlock(VisRgn
);
1064 GreDeleteObject(VisBefore
);
1069 RGNOBJAPI_Unlock(VisRgn
);
1070 NtGdiOffsetRgn(VisBefore
, -Window
->Wnd
->rcWindow
.left
, -Window
->Wnd
->rcWindow
.top
);
1075 WvrFlags
= co_WinPosDoNCCALCSize(Window
, &WinPos
, &NewWindowRect
, &NewClientRect
);
1077 //DPRINT1("co_WinPosDoNCCALCSize");
1079 /* Relink windows. (also take into account shell window in hwndShellWindow) */
1080 if (!(WinPos
.flags
& SWP_NOZORDER
) && WinPos
.hwnd
!= UserGetShellWindow())
1082 PWINDOW_OBJECT ParentWindow
;
1083 PWINDOW_OBJECT Sibling
;
1084 PWINDOW_OBJECT InsertAfterWindow
;
1086 if ((ParentWindow
= Window
->spwndParent
))
1088 if (HWND_TOPMOST
== WinPos
.hwndInsertAfter
)
1090 InsertAfterWindow
= NULL
;
1092 else if (HWND_TOP
== WinPos
.hwndInsertAfter
1093 || HWND_NOTOPMOST
== WinPos
.hwndInsertAfter
)
1095 InsertAfterWindow
= NULL
;
1096 Sibling
= ParentWindow
->spwndChild
;
1097 while ( NULL
!= Sibling
&&
1098 0 != (Sibling
->Wnd
->ExStyle
& WS_EX_TOPMOST
) )
1100 InsertAfterWindow
= Sibling
;
1101 Sibling
= Sibling
->spwndNext
;
1103 if (NULL
!= InsertAfterWindow
)
1105 UserReferenceObject(InsertAfterWindow
);
1108 else if (WinPos
.hwndInsertAfter
== HWND_BOTTOM
)
1110 if(ParentWindow
->spwndChild
)
1112 InsertAfterWindow
= ParentWindow
->spwndChild
;
1114 if(InsertAfterWindow
)
1116 while (InsertAfterWindow
->spwndNext
)
1117 InsertAfterWindow
= InsertAfterWindow
->spwndNext
;
1120 UserReferenceObject(InsertAfterWindow
);
1123 InsertAfterWindow
= NULL
;
1126 InsertAfterWindow
= IntGetWindowObject(WinPos
.hwndInsertAfter
);
1127 /* Do nothing if hwndInsertAfter is HWND_BOTTOM and Window is already
1129 if (InsertAfterWindow
!= Window
)
1131 IntUnlinkWindow(Window
);
1132 IntLinkWindow(Window
, ParentWindow
, InsertAfterWindow
);
1134 if (InsertAfterWindow
!= NULL
)
1135 UserDereferenceObject(InsertAfterWindow
);
1137 if ( (HWND_TOPMOST
== WinPos
.hwndInsertAfter
) ||
1138 (0 != (Window
->Wnd
->ExStyle
& WS_EX_TOPMOST
) &&
1139 NULL
!= Window
->spwndPrev
&&
1140 0 != (Window
->spwndPrev
->Wnd
->ExStyle
& WS_EX_TOPMOST
)) ||
1141 (NULL
!= Window
->spwndNext
&&
1142 0 != (Window
->spwndNext
->Wnd
->ExStyle
& WS_EX_TOPMOST
)) )
1144 Window
->Wnd
->ExStyle
|= WS_EX_TOPMOST
;
1148 Window
->Wnd
->ExStyle
&= ~ WS_EX_TOPMOST
;
1154 if (!Window
->Wnd
) return FALSE
;
1156 OldWindowRect
= Window
->Wnd
->rcWindow
;
1157 OldClientRect
= Window
->Wnd
->rcClient
;
1159 if (OldClientRect
.bottom
- OldClientRect
.top
==
1160 NewClientRect
.bottom
- NewClientRect
.top
)
1162 WvrFlags
&= ~WVR_VREDRAW
;
1165 if (OldClientRect
.right
- OldClientRect
.left
==
1166 NewClientRect
.right
- NewClientRect
.left
)
1168 WvrFlags
&= ~WVR_HREDRAW
;
1171 /* FIXME: Actually do something with WVR_VALIDRECTS */
1173 if ( NewClientRect
.left
!= OldClientRect
.left
||
1174 NewClientRect
.top
!= OldClientRect
.top
)
1176 WinPosInternalMoveWindow(Window
,
1177 NewClientRect
.left
- OldClientRect
.left
,
1178 NewClientRect
.top
- OldClientRect
.top
);
1181 Window
->Wnd
->rcWindow
= NewWindowRect
;
1182 Window
->Wnd
->rcClient
= NewClientRect
;
1184 if (!(WinPos
.flags
& SWP_SHOWWINDOW
) && (WinPos
.flags
& SWP_HIDEWINDOW
))
1186 /* Clear the update region */
1187 co_UserRedrawWindow( Window
,
1190 RDW_VALIDATE
| RDW_NOFRAME
| RDW_NOERASE
| RDW_NOINTERNALPAINT
| RDW_ALLCHILDREN
);
1192 if ((Window
->Wnd
->style
& WS_VISIBLE
) &&
1193 Window
->spwndParent
== UserGetDesktopWindow())
1195 co_IntShellHookNotify(HSHELL_WINDOWDESTROYED
, (LPARAM
)Window
->hSelf
);
1197 Window
->Wnd
->style
&= ~WS_VISIBLE
;
1199 else if (WinPos
.flags
& SWP_SHOWWINDOW
)
1201 if (!(Window
->Wnd
->style
& WS_VISIBLE
) &&
1202 Window
->spwndParent
== UserGetDesktopWindow() )
1204 co_IntShellHookNotify(HSHELL_WINDOWCREATED
, (LPARAM
)Window
->hSelf
);
1206 Window
->Wnd
->style
|= WS_VISIBLE
;
1209 if (Window
->hrgnUpdate
!= NULL
&& Window
->hrgnUpdate
!= (HRGN
)1)
1211 NtGdiOffsetRgn(Window
->hrgnUpdate
,
1212 NewWindowRect
.left
- OldWindowRect
.left
,
1213 NewWindowRect
.top
- OldWindowRect
.top
);
1216 DceResetActiveDCEs(Window
);
1218 if (!(WinPos
.flags
& SWP_NOREDRAW
))
1220 /* Determine the new visible region */
1221 VisAfter
= VIS_ComputeVisibleRegion(Window
, FALSE
, FALSE
, TRUE
);
1224 if ( VisAfter
!= NULL
&&
1225 (VisRgn
= (PROSRGNDATA
)RGNOBJAPI_Lock(VisAfter
, NULL
)) &&
1226 REGION_GetRgnBox(VisRgn
, &TempRect
) == NULLREGION
)
1228 RGNOBJAPI_Unlock(VisRgn
);
1229 GreDeleteObject(VisAfter
);
1234 RGNOBJAPI_Unlock(VisRgn
);
1235 NtGdiOffsetRgn(VisAfter
, -Window
->Wnd
->rcWindow
.left
, -Window
->Wnd
->rcWindow
.top
);
1239 * Determine which pixels can be copied from the old window position
1240 * to the new. Those pixels must be visible in both the old and new
1241 * position. Also, check the class style to see if the windows of this
1242 * class need to be completely repainted on (horizontal/vertical) size
1245 if ( VisBefore
!= NULL
&&
1247 !(WinPos
.flags
& SWP_NOCOPYBITS
) &&
1248 ((WinPos
.flags
& SWP_NOSIZE
) || !(WvrFlags
& WVR_REDRAW
)) &&
1249 !(Window
->Wnd
->ExStyle
& WS_EX_TRANSPARENT
) )
1251 CopyRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
1252 RgnType
= NtGdiCombineRgn(CopyRgn
, VisAfter
, VisBefore
, RGN_AND
);
1255 * If this is (also) a window resize, the whole nonclient area
1256 * needs to be repainted. So we limit the copy to the client area,
1257 * 'cause there is no use in copying it (would possibly cause
1258 * "flashing" too). However, if the copy region is already empty,
1259 * we don't have to crop (can't take anything away from an empty
1262 if (!(WinPos
.flags
& SWP_NOSIZE
) &&
1264 RgnType
!= NULLREGION
)
1266 PROSRGNDATA pCopyRgn
;
1267 RECTL ORect
= OldClientRect
;
1268 RECTL NRect
= NewClientRect
;
1269 RECTL_vOffsetRect(&ORect
, - OldWindowRect
.left
, - OldWindowRect
.top
);
1270 RECTL_vOffsetRect(&NRect
, - NewWindowRect
.left
, - NewWindowRect
.top
);
1271 RECTL_bIntersectRect(&CopyRect
, &ORect
, &NRect
);
1272 pCopyRgn
= RGNOBJAPI_Lock(CopyRgn
, NULL
);
1273 REGION_CropAndOffsetRegion(pCopyRgn
, pCopyRgn
, &CopyRect
, NULL
);
1274 RGNOBJAPI_Unlock(pCopyRgn
);
1277 /* No use in copying bits which are in the update region. */
1278 if (Window
->hrgnUpdate
!= NULL
)
1280 NtGdiOffsetRgn(CopyRgn
, NewWindowRect
.left
, NewWindowRect
.top
);
1281 NtGdiCombineRgn(CopyRgn
, CopyRgn
, Window
->hrgnUpdate
, RGN_DIFF
);
1282 NtGdiOffsetRgn(CopyRgn
, -NewWindowRect
.left
, -NewWindowRect
.top
);
1286 * Now, get the bounding box of the copy region. If it's empty
1287 * there's nothing to copy. Also, it's no use copying bits onto
1290 if ( (VisRgn
= (PROSRGNDATA
)RGNOBJAPI_Lock(CopyRgn
, NULL
)) &&
1291 REGION_GetRgnBox(VisRgn
, &CopyRect
) == NULLREGION
)
1293 /* Nothing to copy, clean up */
1294 RGNOBJAPI_Unlock(VisRgn
);
1295 REGION_FreeRgnByHandle(CopyRgn
);
1298 else if (OldWindowRect
.left
!= NewWindowRect
.left
||
1299 OldWindowRect
.top
!= NewWindowRect
.top
)
1303 RGNOBJAPI_Unlock(VisRgn
);
1307 * Small trick here: there is no function to bitblt a region. So
1308 * we set the region as the clipping region, take the bounding box
1309 * of the region and bitblt that. Since nothing outside the clipping
1310 * region is copied, this has the effect of bitblt'ing the region.
1312 * Since NtUserGetDCEx takes ownership of the clip region, we need
1313 * to create a copy of CopyRgn and pass that. We need CopyRgn later
1315 NtGdiOffsetRgn(CopyRgn
, NewWindowRect
.left
, NewWindowRect
.top
);
1316 Dc
= UserGetDCEx( Window
,
1318 DCX_WINDOW
|DCX_CACHE
|DCX_INTERSECTRGN
|DCX_CLIPSIBLINGS
|DCX_KEEPCLIPRGN
);
1320 CopyRect
.left
, CopyRect
.top
,
1321 CopyRect
.right
- CopyRect
.left
,
1322 CopyRect
.bottom
- CopyRect
.top
,
1324 CopyRect
.left
+ (OldWindowRect
.left
- NewWindowRect
.left
),
1325 CopyRect
.top
+ (OldWindowRect
.top
- NewWindowRect
.top
),
1330 UserReleaseDC(Window
, Dc
, FALSE
);
1331 IntValidateParent(Window
, CopyRgn
, FALSE
);
1332 NtGdiOffsetRgn(CopyRgn
, -NewWindowRect
.left
, -NewWindowRect
.top
);
1336 RGNOBJAPI_Unlock(VisRgn
);
1344 /* We need to redraw what wasn't visible before */
1345 if (VisAfter
!= NULL
)
1347 DirtyRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
1348 if (CopyRgn
!= NULL
)
1350 RgnType
= NtGdiCombineRgn(DirtyRgn
, VisAfter
, CopyRgn
, RGN_DIFF
);
1354 RgnType
= NtGdiCombineRgn(DirtyRgn
, VisAfter
, 0, RGN_COPY
);
1356 if (RgnType
!= ERROR
&& RgnType
!= NULLREGION
)
1359 NtGdiOffsetRgn(DirtyRgn, Window->rcWindow.left, Window->rcWindow.top);
1360 IntInvalidateWindows( Window,
1362 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
1364 GreDeleteObject(DirtyRgn);
1367 PWINDOW_OBJECT Parent
= Window
->spwndParent
;
1369 NtGdiOffsetRgn( DirtyRgn
,
1370 Window
->Wnd
->rcWindow
.left
,
1371 Window
->Wnd
->rcWindow
.top
);
1372 if ( (Window
->Wnd
->style
& WS_CHILD
) &&
1374 !(Parent
->Wnd
->style
& WS_CLIPCHILDREN
))
1376 IntInvalidateWindows( Parent
,
1378 RDW_ERASE
| RDW_INVALIDATE
);
1379 co_IntPaintWindows(Parent
, RDW_ERASENOW
, FALSE
);
1383 IntInvalidateWindows( Window
,
1385 RDW_ERASE
| RDW_FRAME
| RDW_INVALIDATE
| RDW_ALLCHILDREN
);
1388 REGION_FreeRgnByHandle(DirtyRgn
);
1391 if (CopyRgn
!= NULL
)
1393 REGION_FreeRgnByHandle(CopyRgn
);
1396 /* Expose what was covered before but not covered anymore */
1397 if (VisBefore
!= NULL
)
1399 ExposedRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
1400 NtGdiCombineRgn(ExposedRgn
, VisBefore
, NULL
, RGN_COPY
);
1401 NtGdiOffsetRgn( ExposedRgn
,
1402 OldWindowRect
.left
- NewWindowRect
.left
,
1403 OldWindowRect
.top
- NewWindowRect
.top
);
1405 if (VisAfter
!= NULL
)
1406 RgnType
= NtGdiCombineRgn(ExposedRgn
, ExposedRgn
, VisAfter
, RGN_DIFF
);
1408 RgnType
= SIMPLEREGION
;
1410 if (RgnType
!= ERROR
&& RgnType
!= NULLREGION
)
1412 co_VIS_WindowLayoutChanged(Window
, ExposedRgn
);
1414 REGION_FreeRgnByHandle(ExposedRgn
);
1415 REGION_FreeRgnByHandle(VisBefore
);
1418 if (VisAfter
!= NULL
)
1420 REGION_FreeRgnByHandle(VisAfter
);
1423 if (!(WinPos
.flags
& SWP_NOACTIVATE
))
1425 if ((Window
->Wnd
->style
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1427 co_IntSendMessageNoWait(WinPos
.hwnd
, WM_CHILDACTIVATE
, 0, 0);
1431 co_IntSetForegroundWindow(Window
);
1436 if ((WinPos
.flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOPOSCHANGE
)
1438 /* WM_WINDOWPOSCHANGED is sent even if SWP_NOSENDCHANGING is set
1439 and always contains final window position.
1441 WinPos
.x
= NewWindowRect
.left
;
1442 WinPos
.y
= NewWindowRect
.top
;
1443 WinPos
.cx
= NewWindowRect
.right
- NewWindowRect
.left
;
1444 WinPos
.cy
= NewWindowRect
.bottom
- NewWindowRect
.top
;
1445 co_IntSendMessageNoWait(WinPos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
) &WinPos
);
1452 co_WinPosGetNonClientSize(PWINDOW_OBJECT Window
, RECT
* WindowRect
, RECT
* ClientRect
)
1456 ASSERT_REFS_CO(Window
);
1458 *ClientRect
= *WindowRect
;
1459 Result
= co_IntSendMessageNoWait(Window
->hSelf
, WM_NCCALCSIZE
, FALSE
, (LPARAM
) ClientRect
);
1461 FixClientRect(ClientRect
, WindowRect
);
1467 co_WinPosShowWindow(PWINDOW_OBJECT Window
, INT Cmd
)
1476 ASSERT_REFS_CO(Window
);
1479 if (!Wnd
) return FALSE
;
1481 WasVisible
= (Wnd
->style
& WS_VISIBLE
) != 0;
1491 Swp
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
1492 if (Window
->hSelf
!= UserGetActiveWindow())
1493 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1497 case SW_SHOWMINNOACTIVE
:
1498 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1500 case SW_SHOWMINIMIZED
:
1501 Swp
|= SWP_SHOWWINDOW
;
1505 Swp
|= SWP_NOACTIVATE
;
1506 if (!(Wnd
->style
& WS_MINIMIZE
))
1508 Swp
|= co_WinPosMinMaximize(Window
, SW_MINIMIZE
, &NewPos
) |
1513 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1516 Swp
|= SWP_FRAMECHANGED
;
1522 case SW_SHOWMAXIMIZED
:
1524 Swp
|= SWP_SHOWWINDOW
;
1525 if (!(Wnd
->style
& WS_MAXIMIZE
))
1527 Swp
|= co_WinPosMinMaximize(Window
, SW_MAXIMIZE
, &NewPos
) |
1532 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1535 Swp
|= SWP_FRAMECHANGED
;
1542 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1545 if (WasVisible
) return(TRUE
); // Nothing to do!
1546 Swp
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
1547 /* Don't activate the topmost window. */
1550 case SW_SHOWNOACTIVATE
:
1551 //Swp |= SWP_NOZORDER;
1552 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1555 case SW_SHOWDEFAULT
:
1557 Swp
|= SWP_SHOWWINDOW
;
1558 if (Wnd
->style
& (WS_MINIMIZE
| WS_MAXIMIZE
))
1560 Swp
|= co_WinPosMinMaximize(Window
, SW_RESTORE
, &NewPos
) |
1565 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1568 Swp
|= SWP_FRAMECHANGED
;
1574 ShowFlag
= (Cmd
!= SW_HIDE
);
1576 if (ShowFlag
!= WasVisible
)
1578 co_IntSendMessageNoWait(Window
->hSelf
, WM_SHOWWINDOW
, ShowFlag
, 0);
1581 /* We can't activate a child window */
1582 if ((Wnd
->style
& WS_CHILD
) &&
1583 !(Wnd
->ExStyle
& WS_EX_MDICHILD
))
1585 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1588 co_WinPosSetWindowPos(Window
, 0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
)
1589 ? HWND_TOPMOST
: HWND_TOP
,
1590 NewPos
.left
, NewPos
.top
, NewPos
.right
, NewPos
.bottom
, LOWORD(Swp
));
1592 if ((Cmd
== SW_HIDE
) || (Cmd
== SW_MINIMIZE
))
1594 PWINDOW_OBJECT ThreadFocusWindow
;
1596 /* FIXME: This will cause the window to be activated irrespective
1597 * of whether it is owned by the same thread. Has to be done
1601 if (Window
->hSelf
== UserGetActiveWindow())
1603 co_WinPosActivateOtherWindow(Window
);
1608 ThreadFocusWindow
= UserGetWindowObject(IntGetThreadFocusWindow());
1610 /* Revert focus to parent */
1611 if (ThreadFocusWindow
&& (Window
== ThreadFocusWindow
||
1612 IntIsChildWindow(Window
, ThreadFocusWindow
)))
1614 //faxme: as long as we have ref on Window, we also, indirectly, have ref on parent...
1615 co_UserSetFocus(Window
->spwndParent
);
1619 /* FIXME: Check for window destruction. */
1621 if ((Window
->state
& WINDOWOBJECT_NEED_SIZE
) &&
1622 !(Window
->state
& WINDOWSTATUS_DESTROYING
))
1624 WPARAM wParam
= SIZE_RESTORED
;
1626 Window
->state
&= ~WINDOWOBJECT_NEED_SIZE
;
1627 if (Wnd
->style
& WS_MAXIMIZE
)
1629 wParam
= SIZE_MAXIMIZED
;
1631 else if (Wnd
->style
& WS_MINIMIZE
)
1633 wParam
= SIZE_MINIMIZED
;
1636 co_IntSendMessageNoWait(Window
->hSelf
, WM_SIZE
, wParam
,
1637 MAKELONG(Wnd
->rcClient
.right
-
1639 Wnd
->rcClient
.bottom
-
1640 Wnd
->rcClient
.top
));
1641 co_IntSendMessageNoWait(Window
->hSelf
, WM_MOVE
, 0,
1642 MAKELONG(Wnd
->rcClient
.left
,
1643 Wnd
->rcClient
.top
));
1644 IntEngWindowChanged(Window
, WOC_RGN_CLIENT
);
1648 /* Activate the window if activation is not requested and the window is not minimized */
1650 if (!(Swp & (SWP_NOACTIVATE | SWP_HIDEWINDOW)) && !(Window->style & WS_MINIMIZE))
1652 WinPosChangeActiveWindow(Wnd, FALSE);
1661 /* find child of 'parent' that contains the given point (in parent-relative coords) */
1662 PWINDOW_OBJECT
child_window_from_point(PWINDOW_OBJECT parent
, int x
, int y
)
1664 PWINDOW_OBJECT Wnd
;// = parent->spwndChild;
1666 // LIST_FOR_EACH_ENTRY( Wnd, &parent->children, struct window, entry )
1667 for (Wnd
= parent
->spwndChild
; Wnd
; Wnd
= Wnd
->spwndNext
)
1669 if (!IntPtInWindow( Wnd
, x
, y
)) continue; /* skip it */
1671 /* if window is minimized or disabled, return at once */
1672 if (Wnd
->style
& (WS_MINIMIZE
|WS_DISABLED
)) return Wnd
;
1674 /* if point is not in client area, return at once */
1675 if (x
< Wnd
->rcClient
.left
|| x
>= Wnd
->rcClient
.right
||
1676 y
< Wnd
->rcClient
.top
|| y
>= Wnd
->rcClient
.bottom
)
1679 return child_window_from_point( Wnd
, x
- Wnd
->rcClient
.left
, y
- Wnd
->rcClient
.top
);
1681 return parent
; /* not found any child */
1685 /* wine server: child_window_from_point
1687 Caller must dereference the "returned" Window
1691 co_WinPosSearchChildren(
1692 PWINDOW_OBJECT ScopeWin
,
1693 PUSER_MESSAGE_QUEUE OnlyHitTests
,
1695 PWINDOW_OBJECT
* Window
,
1699 PWINDOW_OBJECT Current
;
1702 USER_REFERENCE_ENTRY Ref
;
1704 ASSERT_REFS_CO(ScopeWin
);
1706 if ((List
= IntWinListChildren(ScopeWin
)))
1708 for (phWnd
= List
; *phWnd
; ++phWnd
)
1710 if (!(Current
= UserGetWindowObject(*phWnd
)))
1712 CurrentWnd
= Current
->Wnd
;
1714 if (!(CurrentWnd
->style
& WS_VISIBLE
))
1719 if ((CurrentWnd
->style
& (WS_POPUP
| WS_CHILD
| WS_DISABLED
)) ==
1720 (WS_CHILD
| WS_DISABLED
))
1725 if (!IntPtInWindow(Current
, Point
->x
, Point
->y
))
1730 if (*Window
) UserDereferenceObject(*Window
);
1732 UserReferenceObject(*Window
);
1734 if (CurrentWnd
->style
& WS_MINIMIZE
)
1736 *HitTest
= HTCAPTION
;
1740 if (CurrentWnd
->style
& WS_DISABLED
)
1746 UserRefObjectCo(Current
, &Ref
);
1748 if (OnlyHitTests
&& (Current
->pti
->MessageQueue
== OnlyHitTests
))
1750 *HitTest
= co_IntSendMessage(Current
->hSelf
, WM_NCHITTEST
, 0,
1751 MAKELONG(Point
->x
, Point
->y
));
1752 if ((*HitTest
) == (USHORT
)HTTRANSPARENT
)
1754 UserDerefObjectCo(Current
);
1759 *HitTest
= HTCLIENT
;
1761 if (Point
->x
>= CurrentWnd
->rcClient
.left
&&
1762 Point
->x
< CurrentWnd
->rcClient
.right
&&
1763 Point
->y
>= CurrentWnd
->rcClient
.top
&&
1764 Point
->y
< CurrentWnd
->rcClient
.bottom
)
1766 co_WinPosSearchChildren(Current
, OnlyHitTests
, Point
, Window
, HitTest
);
1769 UserDerefObjectCo(Current
);
1777 /* wine: WINPOS_WindowFromPoint */
1779 co_WinPosWindowFromPoint(PWINDOW_OBJECT ScopeWin
, PUSER_MESSAGE_QUEUE OnlyHitTests
, POINT
*WinPoint
,
1780 PWINDOW_OBJECT
* Window
)
1782 HWND DesktopWindowHandle
;
1783 PWINDOW_OBJECT DesktopWindow
;
1784 POINT Point
= *WinPoint
;
1787 ASSERT_REFS_CO(ScopeWin
);
1793 DPRINT1("WinPosWindowFromPoint(): ScopeWin == NULL!\n");
1797 if (ScopeWin
->Wnd
->style
& WS_DISABLED
)
1802 /* Translate the point to the space of the scope window. */
1803 DesktopWindowHandle
= IntGetDesktopWindow();
1804 if((DesktopWindowHandle
!= ScopeWin
->hSelf
) &&
1805 (DesktopWindow
= UserGetWindowObject(DesktopWindowHandle
)))
1807 Point
.x
+= ScopeWin
->Wnd
->rcClient
.left
- DesktopWindow
->Wnd
->rcClient
.left
;
1808 Point
.y
+= ScopeWin
->Wnd
->rcClient
.top
- DesktopWindow
->Wnd
->rcClient
.top
;
1811 HitTest
= HTNOWHERE
;
1813 co_WinPosSearchChildren(ScopeWin
, OnlyHitTests
, &Point
, Window
, &HitTest
);
1815 return ((*Window
) ? HitTest
: HTNOWHERE
);
1820 NtUserGetMinMaxInfo(
1822 MINMAXINFO
*MinMaxInfo
,
1826 PWINDOW_OBJECT Window
= NULL
;
1828 MINMAXINFO SafeMinMax
;
1831 USER_REFERENCE_ENTRY Ref
;
1833 DPRINT("Enter NtUserGetMinMaxInfo\n");
1834 UserEnterExclusive();
1836 if(!(Window
= UserGetWindowObject(hWnd
)))
1842 UserRefObjectCo(Window
, &Ref
);
1845 Size
.x
= Window
->Wnd
->rcWindow
.left
;
1846 Size
.y
= Window
->Wnd
->rcWindow
.top
;
1847 WinPosInitInternalPos(Window
, &Size
,
1850 co_WinPosGetMinMaxInfo(Window
, &SafeMinMax
.ptMaxSize
, &SafeMinMax
.ptMaxPosition
,
1851 &SafeMinMax
.ptMinTrackSize
, &SafeMinMax
.ptMaxTrackSize
);
1853 Status
= MmCopyToCaller(MinMaxInfo
, &SafeMinMax
, sizeof(MINMAXINFO
));
1854 if(!NT_SUCCESS(Status
))
1856 SetLastNtError(Status
);
1864 if (Window
) UserDerefObjectCo(Window
);
1866 DPRINT("Leave NtUserGetMinMaxInfo, ret=%i\n", ret
);