2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
5 * FILE: subsystems/win32/win32k/ntuser/window.c
6 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
10 DBG_DEFAULT_CHANNEL(UserWinpos
);
12 /* GLOBALS *******************************************************************/
14 #define MINMAX_NOSWP (0x00010000)
16 #define SWP_EX_NOCOPY 0x0001
17 #define SWP_EX_PAINTSELF 0x0002
19 #define SWP_AGG_NOGEOMETRYCHANGE \
20 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
21 #define SWP_AGG_NOPOSCHANGE \
22 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
23 #define SWP_AGG_STATUSFLAGS \
24 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
26 #define EMPTYPOINT(pt) ((pt).x == -1 && (pt).y == -1)
27 #define PLACE_MIN 0x0001
28 #define PLACE_MAX 0x0002
29 #define PLACE_RECT 0x0004
31 /* FUNCTIONS *****************************************************************/
34 IntGetClientOrigin(PWND Window OPTIONAL
, LPPOINT Point
)
36 Window
= Window
? Window
: UserGetWindowObject(IntGetDesktopWindow());
39 Point
->x
= Point
->y
= 0;
42 Point
->x
= Window
->rcClient
.left
;
43 Point
->y
= Window
->rcClient
.top
;
49 /*******************************************************************
52 * Check if we can activate the specified window.
55 BOOL FASTCALL
can_activate_window( PWND Wnd OPTIONAL
)
59 if (!Wnd
) return FALSE
;
62 if (!(style
& WS_VISIBLE
) &&
63 Wnd
->head
.pti
->pEThread
->ThreadsProcess
!= CsrProcess
) return FALSE
;
64 if ((style
& WS_MINIMIZE
) &&
65 Wnd
->head
.pti
->pEThread
->ThreadsProcess
!= CsrProcess
) return FALSE
;
66 if ((style
& (WS_POPUP
|WS_CHILD
)) == WS_CHILD
) return FALSE
;
68 /* FIXME: This window could be disable because the child that closed
70 //return !(style & WS_DISABLED);
74 /*******************************************************************
75 * WinPosActivateOtherWindow
77 * Activates window other than pWnd.
80 co_WinPosActivateOtherWindow(PWND Wnd
)
84 USER_REFERENCE_ENTRY Ref
;
88 if (IntIsDesktopWindow(Wnd
))
90 IntSetFocusMessageQueue(NULL
);
94 /* If this is popup window, try to activate the owner first. */
95 if ((Wnd
->style
& WS_POPUP
) && (WndTo
= Wnd
->spwndOwner
))
97 WndTo
= UserGetAncestor( WndTo
, GA_ROOT
);
98 if (can_activate_window(WndTo
)) goto done
;
101 /* Pick a next top-level window. */
102 /* FIXME: Search for non-tooltip windows first. */
106 if (!(WndTo
= WndTo
->spwndNext
)) break;
107 if (can_activate_window( WndTo
)) break;
112 if (WndTo
) UserRefObjectCo(WndTo
, &Ref
);
114 Fg
= UserGetForegroundWindow();
115 if ((!Fg
|| Wnd
->head
.h
== Fg
) && WndTo
) // FIXME: Ok if WndTo is NULL??
117 /* FIXME: Wine can pass WndTo = NULL to co_IntSetForegroundWindow. Hmm... */
118 if (co_IntSetForegroundWindow(WndTo
))
120 UserDerefObjectCo(WndTo
);
125 if (!co_IntSetActiveWindow(WndTo
)) /* Ok for WndTo to be NULL here */
126 co_IntSetActiveWindow(0);
128 if (WndTo
) UserDerefObjectCo(WndTo
);
133 WinPosShowIconTitle( PWND pWnd
, BOOL bShow
)
136 if (!pWnd
->pcls
|| pWnd
->fnid
== FNID_DESKTOP
) return FALSE
;
137 hIcon
= pWnd
->pcls
->hIconSm
;
138 if (!hIcon
) hIcon
= pWnd
->pcls
->hIcon
;
139 if (!hIcon
) return FALSE
;
153 co_WinPosArrangeIconicWindows(PWND parent
)
156 INT i
, x
, y
, xspacing
, yspacing
, sx
, sy
;
157 HWND
*List
= IntWinListChildren(parent
);
159 ASSERT_REFS_CO(parent
);
161 /* Check if we found any children */
167 IntGetClientRect( parent
, &rectParent
);
169 y
= rectParent
.bottom
;
171 xspacing
= (UserGetSystemMetrics(SM_CXMINSPACING
)/2)+UserGetSystemMetrics(SM_CXBORDER
);
172 yspacing
= (UserGetSystemMetrics(SM_CYMINSPACING
)/2)+UserGetSystemMetrics(SM_CYBORDER
);
174 TRACE("X:%d Y:%d XS:%d YS:%d\n",x
,y
,xspacing
,yspacing
);
176 for(i
= 0; List
[i
]; i
++)
180 if (!(Child
= UserGetWindowObject(List
[i
])))
183 if((Child
->style
& WS_MINIMIZE
) != 0 )
185 USER_REFERENCE_ENTRY Ref
;
186 UserRefObjectCo(Child
, &Ref
);
188 sx
= x
+ UserGetSystemMetrics(SM_CXBORDER
);
189 sy
= y
- yspacing
- UserGetSystemMetrics(SM_CYBORDER
);
191 co_WinPosSetWindowPos( Child
, 0, sx
, sy
, 0, 0,
192 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
194 Child
->InternalPos
.IconPos
.x
= sx
;
195 Child
->InternalPos
.IconPos
.y
= sy
;
196 Child
->InternalPos
.flags
|= WPF_MININIT
;
198 UserDerefObjectCo(Child
);
200 if (x
<= (rectParent
.right
- UserGetSystemMetrics(SM_CXMINSPACING
)))
207 TRACE("X:%d Y:%d\n",x
,y
);
215 WinPosFindIconPos(PWND Window
, POINT
*Pos
)
217 RECT rect
, rectParent
;
218 PWND pwndChild
, pwndParent
;
220 int xspacing
, yspacing
;
222 pwndParent
= Window
->spwndParent
;
223 if (pwndParent
== UserGetDesktopWindow())
225 /* ReactOS doesn't support iconic minimize to desktop */
226 Pos
->x
= Pos
->y
= -32000;
230 IntGetClientRect( pwndParent
, &rectParent
);
231 if ((Pos
->x
>= rectParent
.left
) && ((Pos
->x
+ UserGetSystemMetrics(SM_CXICON
)) < rectParent
.right
) &&
232 (Pos
->y
>= rectParent
.top
) && ((Pos
->y
+ UserGetSystemMetrics(SM_CYICON
)) < rectParent
.bottom
))
233 return; /* The icon already has a suitable position */
235 xspacing
= UserGetSystemMetrics(SM_CXICONSPACING
);
236 yspacing
= UserGetSystemMetrics(SM_CYICONSPACING
);
238 /* Check if another icon already occupies this spot */
239 /* FIXME: this is completely inefficient */
241 hrgn
= IntSysCreateRectRgn( 0, 0, 0, 0 );
242 tmp
= IntSysCreateRectRgn( 0, 0, 0, 0 );
243 for (pwndChild
= pwndParent
->spwndChild
; pwndChild
; pwndChild
= pwndChild
->spwndNext
)
245 if (pwndChild
== Window
) continue;
246 if ((pwndChild
->style
& (WS_VISIBLE
|WS_MINIMIZE
)) != (WS_VISIBLE
|WS_MINIMIZE
))
248 if ( pwndChild
->spwndParent
)
250 PWND Parent
= pwndChild
->spwndParent
;
251 rect
.left
= rect
.top
= 0;
252 rect
.right
= Parent
->rcWindow
.right
- Parent
->rcWindow
.left
;
253 rect
.bottom
= Parent
->rcWindow
.bottom
- Parent
->rcWindow
.top
;
254 NtGdiSetRectRgn( tmp
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
255 NtGdiCombineRgn( hrgn
, hrgn
, tmp
, RGN_OR
);
258 GreDeleteObject( tmp
);
260 for (rect
.bottom
= rectParent
.bottom
; rect
.bottom
>= yspacing
; rect
.bottom
-= yspacing
)
262 for (rect
.left
= rectParent
.left
; rect
.left
<= rectParent
.right
- xspacing
; rect
.left
+= xspacing
)
264 rect
.right
= rect
.left
+ xspacing
;
265 rect
.top
= rect
.bottom
- yspacing
;
266 if (!IntRectInRegion( hrgn
, &rect
))
268 /* No window was found, so it's OK for us */
269 Pos
->x
= rect
.left
+ (xspacing
- UserGetSystemMetrics(SM_CXICON
)) / 2;
270 Pos
->y
= rect
.top
+ (yspacing
- UserGetSystemMetrics(SM_CYICON
)) / 2;
271 GreDeleteObject( hrgn
);
276 GreDeleteObject( hrgn
);
282 WinPosInitInternalPos(PWND Wnd
, RECTL
*RestoreRect
)
285 RECTL Rect
= *RestoreRect
;
287 if (Wnd
->spwndParent
!= UserGetDesktopWindow())
289 RECTL_vOffsetRect(&Rect
,
290 -Wnd
->spwndParent
->rcClient
.left
,
291 -Wnd
->spwndParent
->rcClient
.top
);
297 if (!Wnd
->InternalPosInitialized
)
299 // FIXME: Use check point Atom..
300 Wnd
->InternalPos
.flags
= 0;
301 Wnd
->InternalPos
.MaxPos
.x
= Wnd
->InternalPos
.MaxPos
.y
= -1;
302 Wnd
->InternalPos
.IconPos
.x
= Wnd
->InternalPos
.IconPos
.y
= -1;
303 Wnd
->InternalPos
.NormalRect
= Rect
;
304 Wnd
->InternalPosInitialized
= TRUE
;
307 if (Wnd
->style
& WS_MINIMIZE
)
309 Wnd
->InternalPos
.IconPos
= Size
;
310 Wnd
->InternalPos
.flags
|= WPF_MININIT
;
312 else if (Wnd
->style
& WS_MAXIMIZE
)
314 Wnd
->InternalPos
.flags
|= WPF_MAXINIT
;
316 if ( Wnd
->spwndParent
== Wnd
->head
.rpdesk
->pDeskInfo
->spwnd
)
318 if (Wnd
->state
& WNDS_MAXIMIZESTOMONITOR
)
320 Wnd
->InternalPos
.flags
&= ~WPF_MAXINIT
;
321 Wnd
->InternalPos
.MaxPos
.x
= Wnd
->InternalPos
.MaxPos
.y
= -1;
326 PMONITOR pmonitor
= UserMonitorFromRect(&Rect
, MONITOR_DEFAULTTOPRIMARY
);
328 // FIXME: support DPI aware, rcWorkDPI/Real etc..
329 if (!(Wnd
->style
& WS_MAXIMIZEBOX
) || (Wnd
->state
& WNDS_HASCAPTION
) || pmonitor
->cFullScreen
)
330 WorkArea
= pmonitor
->rcMonitor
;
332 WorkArea
= pmonitor
->rcWork
;
334 Wnd
->InternalPos
.MaxPos
.x
= Rect
.left
- WorkArea
.left
;
335 Wnd
->InternalPos
.MaxPos
.y
= Rect
.top
- WorkArea
.top
;
336 TRACE("WinPosIP 2 X %d Y %d\n",Wnd
->InternalPos
.MaxPos
.x
,Wnd
->InternalPos
.MaxPos
.y
);
340 Wnd
->InternalPos
.MaxPos
= Size
;
344 Wnd
->InternalPos
.NormalRect
= Rect
;
350 IntGetWindowPlacement(PWND Wnd
, WINDOWPLACEMENT
*lpwndpl
)
352 if (!Wnd
) return FALSE
;
354 if(lpwndpl
->length
!= sizeof(WINDOWPLACEMENT
))
361 WinPosInitInternalPos(Wnd
, &Wnd
->rcWindow
);
363 lpwndpl
->showCmd
= SW_HIDE
;
365 if ( Wnd
->style
& WS_MINIMIZE
)
366 lpwndpl
->showCmd
= SW_SHOWMINIMIZED
;
368 lpwndpl
->showCmd
= ( Wnd
->style
& WS_MAXIMIZE
) ? SW_SHOWMAXIMIZED
: SW_SHOWNORMAL
;
370 lpwndpl
->rcNormalPosition
= Wnd
->InternalPos
.NormalRect
;
372 if (Wnd
->InternalPos
.flags
& WPF_MININIT
) // Return if it was set!
374 lpwndpl
->ptMinPosition
.x
= Wnd
->InternalPos
.IconPos
.x
;
375 lpwndpl
->ptMinPosition
.y
= Wnd
->InternalPos
.IconPos
.y
;
378 lpwndpl
->ptMinPosition
.x
= lpwndpl
->ptMinPosition
.y
= -1;
380 if ( Wnd
->InternalPos
.flags
& WPF_MAXINIT
&& // Return if set and not maximized to monitor!
381 !(Wnd
->state
& WNDS_MAXIMIZESTOMONITOR
))
383 lpwndpl
->ptMaxPosition
.x
= Wnd
->InternalPos
.MaxPos
.x
;
384 lpwndpl
->ptMaxPosition
.y
= Wnd
->InternalPos
.MaxPos
.y
;
387 lpwndpl
->ptMaxPosition
.x
= lpwndpl
->ptMaxPosition
.y
= -1;
389 if ( Wnd
->spwndParent
== Wnd
->head
.rpdesk
->pDeskInfo
->spwnd
&&
390 !(Wnd
->ExStyle
& WS_EX_TOOLWINDOW
))
392 PMONITOR pmonitor
= UserMonitorFromRect(&lpwndpl
->rcNormalPosition
, MONITOR_DEFAULTTOPRIMARY
);
394 // FIXME: support DPI aware, rcWorkDPI/Real etc..
395 if (Wnd
->InternalPos
.flags
& WPF_MININIT
)
397 lpwndpl
->ptMinPosition
.x
-= (pmonitor
->rcWork
.left
- pmonitor
->rcMonitor
.left
);
398 lpwndpl
->ptMinPosition
.y
-= (pmonitor
->rcWork
.top
- pmonitor
->rcMonitor
.top
);
400 RECTL_vOffsetRect(&lpwndpl
->rcNormalPosition
,
401 pmonitor
->rcMonitor
.left
- pmonitor
->rcWork
.left
,
402 pmonitor
->rcMonitor
.top
- pmonitor
->rcWork
.top
);
405 if ( Wnd
->InternalPos
.flags
& WPF_RESTORETOMAXIMIZED
|| Wnd
->style
& WS_MAXIMIZE
)
406 lpwndpl
->flags
|= WPF_RESTORETOMAXIMIZED
;
408 if ( ((Wnd
->style
& (WS_CHILD
|WS_POPUP
)) == WS_CHILD
) && Wnd
->InternalPos
.flags
& WPF_SETMINPOSITION
)
409 lpwndpl
->flags
|= WPF_SETMINPOSITION
;
414 /* make sure the specified rect is visible on screen */
415 static void make_rect_onscreen( RECT
*rect
)
417 PMONITOR pmonitor
= UserMonitorFromRect( rect
, MONITOR_DEFAULTTONEAREST
); // Wine uses this.
419 // FIXME: support DPI aware, rcWorkDPI/Real etc..
420 if (!pmonitor
) return;
421 /* FIXME: map coordinates from rcWork to rcMonitor */
422 if (rect
->right
<= pmonitor
->rcWork
.left
)
424 rect
->right
+= pmonitor
->rcWork
.left
- rect
->left
;
425 rect
->left
= pmonitor
->rcWork
.left
;
427 else if (rect
->left
>= pmonitor
->rcWork
.right
)
429 rect
->left
+= pmonitor
->rcWork
.right
- rect
->right
;
430 rect
->right
= pmonitor
->rcWork
.right
;
432 if (rect
->bottom
<= pmonitor
->rcWork
.top
)
434 rect
->bottom
+= pmonitor
->rcWork
.top
- rect
->top
;
435 rect
->top
= pmonitor
->rcWork
.top
;
437 else if (rect
->top
>= pmonitor
->rcWork
.bottom
)
439 rect
->top
+= pmonitor
->rcWork
.bottom
- rect
->bottom
;
440 rect
->bottom
= pmonitor
->rcWork
.bottom
;
444 /* make sure the specified point is visible on screen */
445 static void make_point_onscreen( POINT
*pt
)
449 RECTL_vSetRect( &rect
, pt
->x
, pt
->y
, pt
->x
+ 1, pt
->y
+ 1 );
450 make_rect_onscreen( &rect
);
456 IntSetWindowPlacement(PWND Wnd
, WINDOWPLACEMENT
*wpl
, UINT Flags
)
461 if ( Flags
& PLACE_MIN
) make_point_onscreen( &wpl
->ptMinPosition
);
462 if ( Flags
& PLACE_MAX
) make_point_onscreen( &wpl
->ptMaxPosition
);
463 if ( Flags
& PLACE_RECT
) make_rect_onscreen( &wpl
->rcNormalPosition
);
465 if (!Wnd
|| Wnd
== Wnd
->head
.rpdesk
->pDeskInfo
->spwnd
) return FALSE
;
467 if ( Flags
& PLACE_MIN
) Wnd
->InternalPos
.IconPos
= wpl
->ptMinPosition
;
468 if ( Flags
& PLACE_MAX
) Wnd
->InternalPos
.MaxPos
= wpl
->ptMaxPosition
;
469 if ( Flags
& PLACE_RECT
) Wnd
->InternalPos
.NormalRect
= wpl
->rcNormalPosition
;
471 SWP_Flags
= SWP_NOZORDER
| SWP_NOACTIVATE
| ((wpl
->flags
& WPF_ASYNCWINDOWPLACEMENT
) ? SWP_ASYNCWINDOWPOS
: 0);
473 if (Wnd
->style
& WS_MINIMIZE
)
475 if (Flags
& PLACE_MIN
)
477 co_WinPosSetWindowPos(Wnd
, HWND_TOP
,
478 wpl
->ptMinPosition
.x
, wpl
->ptMinPosition
.y
, 0, 0,
479 SWP_NOSIZE
| SWP_Flags
);
480 Wnd
->InternalPos
.flags
|= WPF_MININIT
;
483 else if (Wnd
->style
& WS_MAXIMIZE
)
485 if (Flags
& PLACE_MAX
)
487 co_WinPosSetWindowPos(Wnd
, HWND_TOP
,
488 wpl
->ptMaxPosition
.x
, wpl
->ptMaxPosition
.y
, 0, 0,
489 SWP_NOSIZE
| SWP_Flags
);
490 Wnd
->InternalPos
.flags
|= WPF_MAXINIT
;
493 else if (Flags
& PLACE_RECT
)
495 co_WinPosSetWindowPos(Wnd
, HWND_TOP
,
496 wpl
->rcNormalPosition
.left
, wpl
->rcNormalPosition
.top
,
497 wpl
->rcNormalPosition
.right
- wpl
->rcNormalPosition
.left
,
498 wpl
->rcNormalPosition
.bottom
- wpl
->rcNormalPosition
.top
,
502 sAsync
= (Wnd
->head
.pti
->MessageQueue
!= gptiCurrent
->MessageQueue
&& wpl
->flags
& WPF_ASYNCWINDOWPLACEMENT
);
505 co_IntSendMessageNoWait( UserHMGetHandle(Wnd
), WM_ASYNC_SHOWWINDOW
, wpl
->showCmd
, 0 );
507 co_WinPosShowWindow(Wnd
, wpl
->showCmd
);
509 if ( Wnd
->style
& WS_MINIMIZE
&& !sAsync
)
511 if ( wpl
->flags
& WPF_SETMINPOSITION
)
512 Wnd
->InternalPos
.flags
|= WPF_SETMINPOSITION
;
514 if ( wpl
->flags
& WPF_RESTORETOMAXIMIZED
)
515 Wnd
->InternalPos
.flags
|= WPF_RESTORETOMAXIMIZED
;
521 co_WinPosMinMaximize(PWND Wnd
, UINT ShowFlag
, RECT
* NewPos
)
529 wpl
.length
= sizeof(wpl
);
530 IntGetWindowPlacement( Wnd
, &wpl
);
532 if (co_HOOK_CallHooks( WH_CBT
, HCBT_MINMAX
, (WPARAM
)Wnd
->head
.h
, ShowFlag
))
534 ERR("WinPosMinMaximize WH_CBT Call Hook return!\n");
535 return SWP_NOSIZE
| SWP_NOMOVE
;
537 if (Wnd
->style
& WS_MINIMIZE
)
539 if (ShowFlag
== SW_MINIMIZE
) return SWP_NOSIZE
| SWP_NOMOVE
;
541 if (!co_IntSendMessageNoWait(Wnd
->head
.h
, WM_QUERYOPEN
, 0, 0))
543 return(SWP_NOSIZE
| SWP_NOMOVE
);
545 SwpFlags
|= SWP_NOCOPYBITS
;
551 if (Wnd
->style
& WS_MAXIMIZE
)
553 Wnd
->InternalPos
.flags
|= WPF_RESTORETOMAXIMIZED
;
554 Wnd
->style
&= ~WS_MAXIMIZE
;
558 Wnd
->InternalPos
.flags
&= ~WPF_RESTORETOMAXIMIZED
;
560 co_UserRedrawWindow(Wnd
, NULL
, 0, RDW_VALIDATE
| RDW_NOERASE
|
561 RDW_NOINTERNALPAINT
);
562 Wnd
->style
|= WS_MINIMIZE
;
563 WinPosFindIconPos(Wnd
, &wpl
.ptMinPosition
);
564 RECTL_vSetRect(NewPos
, wpl
.ptMinPosition
.x
, wpl
.ptMinPosition
.y
,
565 UserGetSystemMetrics(SM_CXMINIMIZED
),
566 UserGetSystemMetrics(SM_CYMINIMIZED
));
567 SwpFlags
|= SWP_NOCOPYBITS
;
573 co_WinPosGetMinMaxInfo(Wnd
, &Size
, &wpl
.ptMaxPosition
, NULL
, NULL
);
575 TRACE("Maximize: %d,%d %dx%d\n",
576 wpl
.ptMaxPosition
.x
, wpl
.ptMaxPosition
.y
, Size
.x
, Size
.y
);
577 if (Wnd
->style
& WS_MINIMIZE
)
579 Wnd
->style
&= ~WS_MINIMIZE
;
581 Wnd
->style
|= WS_MAXIMIZE
;
582 RECTL_vSetRect(NewPos
, wpl
.ptMaxPosition
.x
, wpl
.ptMaxPosition
.y
, Size
.x
, Size
.y
);
588 if (Wnd
->style
& WS_MINIMIZE
)
590 Wnd
->style
&= ~WS_MINIMIZE
;
591 if (Wnd
->InternalPos
.flags
& WPF_RESTORETOMAXIMIZED
)
593 co_WinPosGetMinMaxInfo(Wnd
, &Size
, &wpl
.ptMaxPosition
, NULL
, NULL
);
595 Wnd
->style
|= WS_MAXIMIZE
;
596 RECTL_vSetRect(NewPos
, wpl
.ptMaxPosition
.x
, wpl
.ptMaxPosition
.y
, Size
.x
, Size
.y
);
601 *NewPos
= wpl
.rcNormalPosition
;
602 NewPos
->right
-= NewPos
->left
;
603 NewPos
->bottom
-= NewPos
->top
;
609 if (!(Wnd
->style
& WS_MAXIMIZE
))
613 Wnd
->style
&= ~WS_MAXIMIZE
;
614 Wnd
->InternalPos
.flags
&= ~WPF_RESTORETOMAXIMIZED
;
615 *NewPos
= wpl
.rcNormalPosition
;
616 NewPos
->right
-= NewPos
->left
;
617 NewPos
->bottom
-= NewPos
->top
;
626 UserHasWindowEdge(DWORD Style
, DWORD ExStyle
)
628 if (Style
& WS_MINIMIZE
)
630 if (ExStyle
& WS_EX_DLGMODALFRAME
)
632 if (ExStyle
& WS_EX_STATICEDGE
)
634 if (Style
& WS_THICKFRAME
)
637 if (Style
== WS_DLGFRAME
|| Style
== WS_CAPTION
)
643 UserGetWindowBorders(DWORD Style
, DWORD ExStyle
, SIZE
*Size
, BOOL WithClient
)
647 if (UserHasWindowEdge(Style
, ExStyle
))
649 else if (ExStyle
& WS_EX_STATICEDGE
)
651 if ((ExStyle
& WS_EX_CLIENTEDGE
) && WithClient
)
653 if (Style
& WS_CAPTION
|| ExStyle
& WS_EX_DLGMODALFRAME
)
655 Size
->cx
= Size
->cy
= Border
;
656 if ((Style
& WS_THICKFRAME
) && !(Style
& WS_MINIMIZE
))
658 Size
->cx
+= UserGetSystemMetrics(SM_CXFRAME
) - UserGetSystemMetrics(SM_CXDLGFRAME
);
659 Size
->cy
+= UserGetSystemMetrics(SM_CYFRAME
) - UserGetSystemMetrics(SM_CYDLGFRAME
);
661 Size
->cx
*= UserGetSystemMetrics(SM_CXBORDER
);
662 Size
->cy
*= UserGetSystemMetrics(SM_CYBORDER
);
666 UserAdjustWindowRectEx(LPRECT lpRect
,
675 lpRect
->top
-= UserGetSystemMetrics(SM_CYMENU
);
677 if ((dwStyle
& WS_CAPTION
) == WS_CAPTION
)
679 if (dwExStyle
& WS_EX_TOOLWINDOW
)
680 lpRect
->top
-= UserGetSystemMetrics(SM_CYSMCAPTION
);
682 lpRect
->top
-= UserGetSystemMetrics(SM_CYCAPTION
);
684 UserGetWindowBorders(dwStyle
, dwExStyle
, &BorderSize
, TRUE
);
694 co_WinPosGetMinMaxInfo(PWND Window
, POINT
* MaxSize
, POINT
* MaxPos
,
695 POINT
* MinTrack
, POINT
* MaxTrack
)
700 LONG style
= Window
->style
;
702 LONG exstyle
= Window
->ExStyle
;
705 ASSERT_REFS_CO(Window
);
707 /* Compute default values */
709 rc
= Window
->rcWindow
;
710 MinMax
.ptReserved
.x
= rc
.left
;
711 MinMax
.ptReserved
.y
= rc
.top
;
713 if ((style
& WS_CAPTION
) == WS_CAPTION
)
714 adjustedStyle
= style
& ~WS_BORDER
; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
716 adjustedStyle
= style
;
718 if(Window
->spwndParent
)
719 IntGetClientRect(Window
->spwndParent
, &rc
);
720 UserAdjustWindowRectEx(&rc
, adjustedStyle
, ((style
& WS_POPUP
) && Window
->IDMenu
), exstyle
);
725 MinMax
.ptMaxSize
.x
= rc
.right
- rc
.left
;
726 MinMax
.ptMaxSize
.y
= rc
.bottom
- rc
.top
;
727 if (style
& (WS_DLGFRAME
| WS_BORDER
))
729 MinMax
.ptMinTrackSize
.x
= UserGetSystemMetrics(SM_CXMINTRACK
);
730 MinMax
.ptMinTrackSize
.y
= UserGetSystemMetrics(SM_CYMINTRACK
);
734 MinMax
.ptMinTrackSize
.x
= 2 * xinc
;
735 MinMax
.ptMinTrackSize
.y
= 2 * yinc
;
737 MinMax
.ptMaxTrackSize
.x
= UserGetSystemMetrics(SM_CXMAXTRACK
);
738 MinMax
.ptMaxTrackSize
.y
= UserGetSystemMetrics(SM_CYMAXTRACK
);
739 MinMax
.ptMaxPosition
.x
= -xinc
;
740 MinMax
.ptMaxPosition
.y
= -yinc
;
742 if (!EMPTYPOINT(Window
->InternalPos
.MaxPos
)) MinMax
.ptMaxPosition
= Window
->InternalPos
.MaxPos
;
744 co_IntSendMessage(Window
->head
.h
, WM_GETMINMAXINFO
, 0, (LPARAM
)&MinMax
);
746 /* if the app didn't change the values, adapt them for the current monitor */
747 if ((monitor
= UserGetPrimaryMonitor()))
751 rc_work
= monitor
->rcMonitor
;
753 if (style
& WS_MAXIMIZEBOX
)
755 if ((style
& WS_CAPTION
) == WS_CAPTION
|| !(style
& (WS_CHILD
| WS_POPUP
)))
756 rc_work
= monitor
->rcWork
;
759 if (MinMax
.ptMaxSize
.x
== UserGetSystemMetrics(SM_CXSCREEN
) + 2 * xinc
&&
760 MinMax
.ptMaxSize
.y
== UserGetSystemMetrics(SM_CYSCREEN
) + 2 * yinc
)
762 MinMax
.ptMaxSize
.x
= (rc_work
.right
- rc_work
.left
) + 2 * xinc
;
763 MinMax
.ptMaxSize
.y
= (rc_work
.bottom
- rc_work
.top
) + 2 * yinc
;
765 if (MinMax
.ptMaxPosition
.x
== -xinc
&& MinMax
.ptMaxPosition
.y
== -yinc
)
767 MinMax
.ptMaxPosition
.x
= rc_work
.left
- xinc
;
768 MinMax
.ptMaxPosition
.y
= rc_work
.top
- yinc
;
773 MinMax
.ptMaxTrackSize
.x
= max(MinMax
.ptMaxTrackSize
.x
,
774 MinMax
.ptMinTrackSize
.x
);
775 MinMax
.ptMaxTrackSize
.y
= max(MinMax
.ptMaxTrackSize
.y
,
776 MinMax
.ptMinTrackSize
.y
);
779 *MaxSize
= MinMax
.ptMaxSize
;
781 *MaxPos
= MinMax
.ptMaxPosition
;
783 *MinTrack
= MinMax
.ptMinTrackSize
;
785 *MaxTrack
= MinMax
.ptMaxTrackSize
;
787 return 0; // FIXME: What does it return?
792 FixClientRect(PRECTL ClientRect
, PRECTL WindowRect
)
794 if (ClientRect
->left
< WindowRect
->left
)
796 ClientRect
->left
= WindowRect
->left
;
798 else if (WindowRect
->right
< ClientRect
->left
)
800 ClientRect
->left
= WindowRect
->right
;
802 if (ClientRect
->right
< WindowRect
->left
)
804 ClientRect
->right
= WindowRect
->left
;
806 else if (WindowRect
->right
< ClientRect
->right
)
808 ClientRect
->right
= WindowRect
->right
;
810 if (ClientRect
->top
< WindowRect
->top
)
812 ClientRect
->top
= WindowRect
->top
;
814 else if (WindowRect
->bottom
< ClientRect
->top
)
816 ClientRect
->top
= WindowRect
->bottom
;
818 if (ClientRect
->bottom
< WindowRect
->top
)
820 ClientRect
->bottom
= WindowRect
->top
;
822 else if (WindowRect
->bottom
< ClientRect
->bottom
)
824 ClientRect
->bottom
= WindowRect
->bottom
;
830 co_WinPosDoNCCALCSize(PWND Window
, PWINDOWPOS WinPos
,
831 RECT
* WindowRect
, RECT
* ClientRect
)
836 ASSERT_REFS_CO(Window
);
838 /* Send WM_NCCALCSIZE message to get new client area */
839 if ((WinPos
->flags
& (SWP_FRAMECHANGED
| SWP_NOSIZE
)) != SWP_NOSIZE
)
841 NCCALCSIZE_PARAMS params
;
842 WINDOWPOS winposCopy
;
844 params
.rgrc
[0] = *WindowRect
;
845 params
.rgrc
[1] = Window
->rcWindow
;
846 params
.rgrc
[2] = Window
->rcClient
;
847 Parent
= Window
->spwndParent
;
848 if (0 != (Window
->style
& WS_CHILD
) && Parent
)
850 RECTL_vOffsetRect(&(params
.rgrc
[0]), - Parent
->rcClient
.left
,
851 - Parent
->rcClient
.top
);
852 RECTL_vOffsetRect(&(params
.rgrc
[1]), - Parent
->rcClient
.left
,
853 - Parent
->rcClient
.top
);
854 RECTL_vOffsetRect(&(params
.rgrc
[2]), - Parent
->rcClient
.left
,
855 - Parent
->rcClient
.top
);
857 params
.lppos
= &winposCopy
;
858 winposCopy
= *WinPos
;
860 wvrFlags
= co_IntSendMessage(Window
->head
.h
, WM_NCCALCSIZE
, TRUE
, (LPARAM
) ¶ms
);
862 /* If the application send back garbage, ignore it */
863 if (params
.rgrc
[0].left
<= params
.rgrc
[0].right
&&
864 params
.rgrc
[0].top
<= params
.rgrc
[0].bottom
)
866 *ClientRect
= params
.rgrc
[0];
867 if ((Window
->style
& WS_CHILD
) && Parent
)
869 RECTL_vOffsetRect(ClientRect
, Parent
->rcClient
.left
,
870 Parent
->rcClient
.top
);
872 FixClientRect(ClientRect
, WindowRect
);
875 /* FIXME: WVR_ALIGNxxx */
877 if (ClientRect
->left
!= Window
->rcClient
.left
||
878 ClientRect
->top
!= Window
->rcClient
.top
)
880 WinPos
->flags
&= ~SWP_NOCLIENTMOVE
;
883 if ((ClientRect
->right
- ClientRect
->left
!=
884 Window
->rcClient
.right
- Window
->rcClient
.left
) ||
885 (ClientRect
->bottom
- ClientRect
->top
!=
886 Window
->rcClient
.bottom
- Window
->rcClient
.top
))
888 WinPos
->flags
&= ~SWP_NOCLIENTSIZE
;
893 if (! (WinPos
->flags
& SWP_NOMOVE
)
894 && (ClientRect
->left
!= Window
->rcClient
.left
||
895 ClientRect
->top
!= Window
->rcClient
.top
))
897 WinPos
->flags
&= ~SWP_NOCLIENTMOVE
;
906 co_WinPosDoWinPosChanging(PWND Window
,
913 ASSERT_REFS_CO(Window
);
915 if (!(WinPos
->flags
& SWP_NOSENDCHANGING
))
917 co_IntSendMessageNoWait(Window
->head
.h
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
) WinPos
);
920 *WindowRect
= Window
->rcWindow
;
921 *ClientRect
= Window
->rcClient
;
923 if (!(WinPos
->flags
& SWP_NOSIZE
))
925 WindowRect
->right
= WindowRect
->left
+ WinPos
->cx
;
926 WindowRect
->bottom
= WindowRect
->top
+ WinPos
->cy
;
929 if (!(WinPos
->flags
& SWP_NOMOVE
))
934 Parent
= Window
->spwndParent
;
935 if ((0 != (Window
->style
& WS_CHILD
)) && Parent
)
937 X
+= Parent
->rcClient
.left
;
938 Y
+= Parent
->rcClient
.top
;
941 WindowRect
->left
= X
;
943 WindowRect
->right
+= X
- Window
->rcWindow
.left
;
944 WindowRect
->bottom
+= Y
- Window
->rcWindow
.top
;
945 RECTL_vOffsetRect(ClientRect
,
946 X
- Window
->rcWindow
.left
,
947 Y
- Window
->rcWindow
.top
);
950 WinPos
->flags
|= SWP_NOCLIENTMOVE
| SWP_NOCLIENTSIZE
;
956 * Fix Z order taking into account owned popups -
957 * basically we need to maintain them above the window that owns them
961 WinPosDoOwnedPopups(PWND Window
, HWND hWndInsertAfter
)
966 PWND DesktopWindow
, ChildObject
;
969 Owner
= Window
->spwndOwner
? Window
->spwndOwner
->head
.h
: NULL
;
970 Style
= Window
->style
;
972 if ((Style
& WS_POPUP
) && Owner
)
974 /* Make sure this popup stays above the owner */
975 HWND hWndLocalPrev
= HWND_TOPMOST
;
977 if (hWndInsertAfter
!= HWND_TOPMOST
)
979 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
980 List
= IntWinListChildren(DesktopWindow
);
984 for (i
= 0; List
[i
]; i
++)
986 if (List
[i
] == Owner
)
988 if (HWND_TOP
== hWndInsertAfter
)
990 ChildObject
= UserGetWindowObject(List
[i
]);
991 if (NULL
!= ChildObject
)
993 if (0 == (ChildObject
->ExStyle
& WS_EX_TOPMOST
))
999 if (List
[i
] != Window
->head
.h
)
1000 hWndLocalPrev
= List
[i
];
1001 if (hWndLocalPrev
== hWndInsertAfter
)
1004 hWndInsertAfter
= hWndLocalPrev
;
1008 else if (Style
& WS_CHILD
)
1010 return hWndInsertAfter
;
1015 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1016 List
= IntWinListChildren(DesktopWindow
);
1020 for (i
= 0; List
[i
]; i
++)
1024 if (List
[i
] == Window
->head
.h
)
1027 if (!(Wnd
= UserGetWindowObject(List
[i
])))
1030 if (Wnd
->style
& WS_POPUP
&& Wnd
->spwndOwner
== Window
)
1032 USER_REFERENCE_ENTRY Ref
;
1033 UserRefObjectCo(Wnd
, &Ref
);
1035 co_WinPosSetWindowPos(Wnd
, hWndInsertAfter
, 0, 0, 0, 0,
1036 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOSENDCHANGING
);
1038 UserDerefObjectCo(Wnd
);
1040 hWndInsertAfter
= List
[i
];
1046 return hWndInsertAfter
;
1049 /***********************************************************************
1050 * WinPosInternalMoveWindow
1052 * Update WindowRect and ClientRect of Window and all of its children
1053 * We keep both WindowRect and ClientRect in screen coordinates internally
1057 WinPosInternalMoveWindow(PWND Window
, INT MoveX
, INT MoveY
)
1061 ASSERT(Window
!= Window
->spwndChild
);
1063 Window
->rcWindow
.left
+= MoveX
;
1064 Window
->rcWindow
.right
+= MoveX
;
1065 Window
->rcWindow
.top
+= MoveY
;
1066 Window
->rcWindow
.bottom
+= MoveY
;
1068 Window
->rcClient
.left
+= MoveX
;
1069 Window
->rcClient
.right
+= MoveX
;
1070 Window
->rcClient
.top
+= MoveY
;
1071 Window
->rcClient
.bottom
+= MoveY
;
1073 for(Child
= Window
->spwndChild
; Child
; Child
= Child
->spwndNext
)
1075 WinPosInternalMoveWindow(Child
, MoveX
, MoveY
);
1080 * WinPosFixupSWPFlags
1082 * Fix redundant flags and values in the WINDOWPOS structure.
1086 WinPosFixupFlags(WINDOWPOS
*WinPos
, PWND Wnd
)
1088 if (Wnd
->style
& WS_VISIBLE
)
1090 WinPos
->flags
&= ~SWP_SHOWWINDOW
;
1094 WinPos
->flags
&= ~SWP_HIDEWINDOW
;
1095 if (!(WinPos
->flags
& SWP_SHOWWINDOW
))
1096 WinPos
->flags
|= SWP_NOREDRAW
;
1099 WinPos
->cx
= max(WinPos
->cx
, 0);
1100 WinPos
->cy
= max(WinPos
->cy
, 0);
1102 /* Check for right size */
1103 if (Wnd
->rcWindow
.right
- Wnd
->rcWindow
.left
== WinPos
->cx
&&
1104 Wnd
->rcWindow
.bottom
- Wnd
->rcWindow
.top
== WinPos
->cy
)
1106 WinPos
->flags
|= SWP_NOSIZE
;
1109 /* Check for right position */
1110 if (Wnd
->rcWindow
.left
== WinPos
->x
&&
1111 Wnd
->rcWindow
.top
== WinPos
->y
)
1113 WinPos
->flags
|= SWP_NOMOVE
;
1116 if (WinPos
->hwnd
== UserGetForegroundWindow())
1118 WinPos
->flags
|= SWP_NOACTIVATE
; /* Already active */
1121 if ((Wnd
->style
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)
1123 /* Bring to the top when activating */
1124 if (!(WinPos
->flags
& SWP_NOACTIVATE
))
1126 WinPos
->flags
&= ~SWP_NOZORDER
;
1127 WinPos
->hwndInsertAfter
= (0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
) ?
1128 HWND_TOPMOST
: HWND_TOP
);
1133 /* Check hwndInsertAfter */
1134 if (!(WinPos
->flags
& SWP_NOZORDER
))
1136 /* Fix sign extension */
1137 if (WinPos
->hwndInsertAfter
== (HWND
)0xffff)
1139 WinPos
->hwndInsertAfter
= HWND_TOPMOST
;
1141 else if (WinPos
->hwndInsertAfter
== (HWND
)0xfffe)
1143 WinPos
->hwndInsertAfter
= HWND_NOTOPMOST
;
1146 if (WinPos
->hwndInsertAfter
== HWND_NOTOPMOST
)
1148 WinPos
->hwndInsertAfter
= HWND_TOP
;
1150 else if (HWND_TOP
== WinPos
->hwndInsertAfter
1151 && 0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
))
1153 /* Keep it topmost when it's already topmost */
1154 WinPos
->hwndInsertAfter
= HWND_TOPMOST
;
1157 /* hwndInsertAfter must be a sibling of the window */
1158 if (HWND_TOPMOST
!= WinPos
->hwndInsertAfter
1159 && HWND_TOP
!= WinPos
->hwndInsertAfter
1160 && HWND_NOTOPMOST
!= WinPos
->hwndInsertAfter
1161 && HWND_BOTTOM
!= WinPos
->hwndInsertAfter
)
1165 InsAfterWnd
= UserGetWindowObject(WinPos
->hwndInsertAfter
);
1171 if (InsAfterWnd
->spwndParent
!= Wnd
->spwndParent
)
1178 * We don't need to change the Z order of hwnd if it's already
1179 * inserted after hwndInsertAfter or when inserting hwnd after
1182 if ((WinPos
->hwnd
== WinPos
->hwndInsertAfter
) ||
1183 ((InsAfterWnd
->spwndNext
) && (WinPos
->hwnd
== InsAfterWnd
->spwndNext
->head
.h
)))
1185 WinPos
->flags
|= SWP_NOZORDER
;
1194 /* x and y are always screen relative */
1196 co_WinPosSetWindowPos(
1198 HWND WndInsertAfter
,
1207 RECTL NewWindowRect
;
1208 RECTL NewClientRect
;
1210 HRGN VisBefore
= NULL
;
1211 HRGN VisAfter
= NULL
;
1212 HRGN DirtyRgn
= NULL
;
1213 HRGN ExposedRgn
= NULL
;
1214 HRGN CopyRgn
= NULL
;
1216 RECTL OldWindowRect
, OldClientRect
;
1221 BOOL bPointerInWindow
;
1223 ASSERT_REFS_CO(Window
);
1225 /* FIXME: Get current active window from active queue. */
1227 * Only allow CSRSS to mess with the desktop window
1230 if ( Window
->head
.h
== IntGetDesktopWindow() &&
1231 Window
->head
.pti
->pEThread
->ThreadsProcess
!= PsGetCurrentProcess())
1233 ERR("Desktop Window...\n");
1236 bPointerInWindow
= IntPtInWindow(Window
, gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
);
1238 WinPos
.hwnd
= Window
->head
.h
;
1239 WinPos
.hwndInsertAfter
= WndInsertAfter
;
1244 WinPos
.flags
= flags
;
1246 co_WinPosDoWinPosChanging(Window
, &WinPos
, &NewWindowRect
, &NewClientRect
);
1248 /* Does the window still exist? */
1249 if (!IntIsWindow(WinPos
.hwnd
))
1251 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE
);
1255 /* Fix up the flags. */
1256 if (!WinPosFixupFlags(&WinPos
, Window
))
1258 EngSetLastError(ERROR_INVALID_PARAMETER
);
1262 Ancestor
= UserGetAncestor(Window
, GA_PARENT
);
1263 if ( (WinPos
.flags
& (SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) !=
1265 Ancestor
&& Ancestor
->head
.h
== IntGetDesktopWindow() )
1267 WinPos
.hwndInsertAfter
= WinPosDoOwnedPopups(Window
, WinPos
.hwndInsertAfter
);
1270 if (!(WinPos
.flags
& SWP_NOREDRAW
))
1272 /* Compute the visible region before the window position is changed */
1273 if (!(WinPos
.flags
& SWP_SHOWWINDOW
) &&
1274 (WinPos
.flags
& (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
|
1275 SWP_HIDEWINDOW
| SWP_FRAMECHANGED
)) !=
1276 (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
))
1278 VisBefore
= VIS_ComputeVisibleRegion(Window
, FALSE
, FALSE
,
1279 (Window
->style
& WS_CLIPSIBLINGS
) ? TRUE
: FALSE
);
1282 if ( VisBefore
!= NULL
&&
1283 (VisRgn
= (PROSRGNDATA
)RGNOBJAPI_Lock(VisBefore
, NULL
)) &&
1284 REGION_Complexity(VisRgn
) == NULLREGION
)
1286 RGNOBJAPI_Unlock(VisRgn
);
1287 GreDeleteObject(VisBefore
);
1292 RGNOBJAPI_Unlock(VisRgn
);
1293 NtGdiOffsetRgn(VisBefore
, -Window
->rcWindow
.left
, -Window
->rcWindow
.top
);
1298 WvrFlags
= co_WinPosDoNCCALCSize(Window
, &WinPos
, &NewWindowRect
, &NewClientRect
);
1300 TRACE("co_WinPosDoNCCALCSize returned %d\n", WvrFlags
);
1302 /* Relink windows. (also take into account shell window in hwndShellWindow) */
1303 if (!(WinPos
.flags
& SWP_NOZORDER
) && WinPos
.hwnd
!= UserGetShellWindow())
1305 IntLinkHwnd(Window
, WndInsertAfter
);
1308 OldWindowRect
= Window
->rcWindow
;
1309 OldClientRect
= Window
->rcClient
;
1311 if (OldClientRect
.bottom
- OldClientRect
.top
==
1312 NewClientRect
.bottom
- NewClientRect
.top
)
1314 WvrFlags
&= ~WVR_VREDRAW
;
1317 if (OldClientRect
.right
- OldClientRect
.left
==
1318 NewClientRect
.right
- NewClientRect
.left
)
1320 WvrFlags
&= ~WVR_HREDRAW
;
1323 /* FIXME: Actually do something with WVR_VALIDRECTS */
1325 if (NewClientRect
.left
!= OldClientRect
.left
||
1326 NewClientRect
.top
!= OldClientRect
.top
)
1328 WinPosInternalMoveWindow(Window
,
1329 NewClientRect
.left
- OldClientRect
.left
,
1330 NewClientRect
.top
- OldClientRect
.top
);
1333 Window
->rcWindow
= NewWindowRect
;
1334 Window
->rcClient
= NewClientRect
;
1336 if (WinPos
.flags
& SWP_HIDEWINDOW
)
1338 /* Clear the update region */
1339 co_UserRedrawWindow( Window
,
1342 RDW_VALIDATE
| RDW_NOFRAME
| RDW_NOERASE
| RDW_NOINTERNALPAINT
| RDW_ALLCHILDREN
);
1344 if (Window
->spwndParent
== UserGetDesktopWindow())
1345 co_IntShellHookNotify(HSHELL_WINDOWDESTROYED
, (LPARAM
)Window
->head
.h
);
1347 Window
->style
&= ~WS_VISIBLE
;
1349 else if (WinPos
.flags
& SWP_SHOWWINDOW
)
1351 if (Window
->spwndParent
== UserGetDesktopWindow())
1352 co_IntShellHookNotify(HSHELL_WINDOWCREATED
, (LPARAM
)Window
->head
.h
);
1354 Window
->style
|= WS_VISIBLE
;
1357 if (Window
->hrgnUpdate
!= NULL
&& Window
->hrgnUpdate
!= HRGN_WINDOW
)
1359 NtGdiOffsetRgn(Window
->hrgnUpdate
,
1360 NewWindowRect
.left
- OldWindowRect
.left
,
1361 NewWindowRect
.top
- OldWindowRect
.top
);
1364 DceResetActiveDCEs(Window
);
1366 if (!(WinPos
.flags
& SWP_NOREDRAW
))
1368 /* Determine the new visible region */
1369 VisAfter
= VIS_ComputeVisibleRegion(Window
, FALSE
, FALSE
,
1370 (Window
->style
& WS_CLIPSIBLINGS
) ? TRUE
: FALSE
);
1373 if ( VisAfter
!= NULL
&&
1374 (VisRgn
= (PROSRGNDATA
)RGNOBJAPI_Lock(VisAfter
, NULL
)) &&
1375 REGION_Complexity(VisRgn
) == NULLREGION
)
1377 RGNOBJAPI_Unlock(VisRgn
);
1378 GreDeleteObject(VisAfter
);
1383 RGNOBJAPI_Unlock(VisRgn
);
1384 NtGdiOffsetRgn(VisAfter
, -Window
->rcWindow
.left
, -Window
->rcWindow
.top
);
1388 * Determine which pixels can be copied from the old window position
1389 * to the new. Those pixels must be visible in both the old and new
1390 * position. Also, check the class style to see if the windows of this
1391 * class need to be completely repainted on (horizontal/vertical) size
1394 if ( VisBefore
!= NULL
&&
1396 !(WinPos
.flags
& SWP_NOCOPYBITS
) &&
1397 ((WinPos
.flags
& SWP_NOSIZE
) || !(WvrFlags
& WVR_REDRAW
)) &&
1398 !(Window
->ExStyle
& WS_EX_TRANSPARENT
) )
1400 CopyRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
1401 RgnType
= NtGdiCombineRgn(CopyRgn
, VisAfter
, VisBefore
, RGN_AND
);
1404 * If this is (also) a window resize, the whole nonclient area
1405 * needs to be repainted. So we limit the copy to the client area,
1406 * 'cause there is no use in copying it (would possibly cause
1407 * "flashing" too). However, if the copy region is already empty,
1408 * we don't have to crop (can't take anything away from an empty
1411 if (!(WinPos
.flags
& SWP_NOSIZE
) &&
1413 RgnType
!= NULLREGION
)
1415 PROSRGNDATA pCopyRgn
;
1416 RECTL ORect
= OldClientRect
;
1417 RECTL NRect
= NewClientRect
;
1418 RECTL_vOffsetRect(&ORect
, - OldWindowRect
.left
, - OldWindowRect
.top
);
1419 RECTL_vOffsetRect(&NRect
, - NewWindowRect
.left
, - NewWindowRect
.top
);
1420 RECTL_bIntersectRect(&CopyRect
, &ORect
, &NRect
);
1421 pCopyRgn
= RGNOBJAPI_Lock(CopyRgn
, NULL
);
1422 REGION_CropAndOffsetRegion(pCopyRgn
, pCopyRgn
, &CopyRect
, NULL
);
1423 RGNOBJAPI_Unlock(pCopyRgn
);
1426 /* No use in copying bits which are in the update region. */
1427 if (Window
->hrgnUpdate
!= NULL
)
1429 NtGdiOffsetRgn(CopyRgn
, NewWindowRect
.left
, NewWindowRect
.top
);
1430 NtGdiCombineRgn(CopyRgn
, CopyRgn
, Window
->hrgnUpdate
, RGN_DIFF
);
1431 NtGdiOffsetRgn(CopyRgn
, -NewWindowRect
.left
, -NewWindowRect
.top
);
1435 * Now, get the bounding box of the copy region. If it's empty
1436 * there's nothing to copy. Also, it's no use copying bits onto
1439 if ( (VisRgn
= (PROSRGNDATA
)RGNOBJAPI_Lock(CopyRgn
, NULL
)) &&
1440 REGION_GetRgnBox(VisRgn
, &CopyRect
) == NULLREGION
)
1442 /* Nothing to copy, clean up */
1443 RGNOBJAPI_Unlock(VisRgn
);
1444 GreDeleteObject(CopyRgn
);
1447 else if (OldWindowRect
.left
!= NewWindowRect
.left
||
1448 OldWindowRect
.top
!= NewWindowRect
.top
)
1452 RGNOBJAPI_Unlock(VisRgn
);
1456 * Small trick here: there is no function to bitblt a region. So
1457 * we set the region as the clipping region, take the bounding box
1458 * of the region and bitblt that. Since nothing outside the clipping
1459 * region is copied, this has the effect of bitblt'ing the region.
1461 * Since NtUserGetDCEx takes ownership of the clip region, we need
1462 * to create a copy of CopyRgn and pass that. We need CopyRgn later
1464 NtGdiOffsetRgn(CopyRgn
, NewWindowRect
.left
, NewWindowRect
.top
);
1465 Dc
= UserGetDCEx( Window
,
1467 DCX_WINDOW
|DCX_CACHE
|DCX_INTERSECTRGN
|DCX_CLIPSIBLINGS
|DCX_KEEPCLIPRGN
);
1469 CopyRect
.left
, CopyRect
.top
,
1470 CopyRect
.right
- CopyRect
.left
,
1471 CopyRect
.bottom
- CopyRect
.top
,
1473 CopyRect
.left
+ (OldWindowRect
.left
- NewWindowRect
.left
),
1474 CopyRect
.top
+ (OldWindowRect
.top
- NewWindowRect
.top
),
1479 UserReleaseDC(Window
, Dc
, FALSE
);
1480 IntValidateParent(Window
, CopyRgn
, FALSE
);
1481 NtGdiOffsetRgn(CopyRgn
, -NewWindowRect
.left
, -NewWindowRect
.top
);
1485 RGNOBJAPI_Unlock(VisRgn
);
1493 /* We need to redraw what wasn't visible before */
1494 if (VisAfter
!= NULL
)
1496 DirtyRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
1497 if (CopyRgn
!= NULL
)
1499 RgnType
= NtGdiCombineRgn(DirtyRgn
, VisAfter
, CopyRgn
, RGN_DIFF
);
1503 RgnType
= NtGdiCombineRgn(DirtyRgn
, VisAfter
, 0, RGN_COPY
);
1505 if (RgnType
!= ERROR
&& RgnType
!= NULLREGION
)
1508 NtGdiOffsetRgn(DirtyRgn, Window->rcWindow.left, Window->rcWindow.top);
1509 IntInvalidateWindows( Window,
1511 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
1513 GreDeleteObject(DirtyRgn);
1516 PWND Parent
= Window
->spwndParent
;
1518 NtGdiOffsetRgn( DirtyRgn
,
1519 Window
->rcWindow
.left
,
1520 Window
->rcWindow
.top
);
1521 if ( (Window
->style
& WS_CHILD
) &&
1523 !(Parent
->style
& WS_CLIPCHILDREN
))
1525 IntInvalidateWindows( Parent
,
1527 RDW_ERASE
| RDW_INVALIDATE
);
1528 co_IntPaintWindows(Parent
, RDW_ERASENOW
, FALSE
);
1532 IntInvalidateWindows( Window
,
1534 RDW_ERASE
| RDW_FRAME
| RDW_INVALIDATE
| RDW_ALLCHILDREN
);
1537 GreDeleteObject(DirtyRgn
);
1540 if (CopyRgn
!= NULL
)
1542 GreDeleteObject(CopyRgn
);
1545 /* Expose what was covered before but not covered anymore */
1546 if (VisBefore
!= NULL
)
1548 ExposedRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
1549 RgnType
= NtGdiCombineRgn(ExposedRgn
, VisBefore
, NULL
, RGN_COPY
);
1550 NtGdiOffsetRgn( ExposedRgn
,
1551 OldWindowRect
.left
- NewWindowRect
.left
,
1552 OldWindowRect
.top
- NewWindowRect
.top
);
1554 if (VisAfter
!= NULL
)
1555 RgnType
= NtGdiCombineRgn(ExposedRgn
, ExposedRgn
, VisAfter
, RGN_DIFF
);
1557 if (RgnType
!= ERROR
&& RgnType
!= NULLREGION
)
1559 co_VIS_WindowLayoutChanged(Window
, ExposedRgn
);
1561 GreDeleteObject(ExposedRgn
);
1562 GreDeleteObject(VisBefore
);
1565 if (VisAfter
!= NULL
)
1567 GreDeleteObject(VisAfter
);
1570 if (!(WinPos
.flags
& SWP_NOACTIVATE
))
1572 if ((Window
->style
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1574 co_IntSendMessageNoWait(WinPos
.hwnd
, WM_CHILDACTIVATE
, 0, 0);
1578 co_IntSetForegroundWindow(Window
);
1583 if ((WinPos
.flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOPOSCHANGE
)
1585 /* WM_WINDOWPOSCHANGED is sent even if SWP_NOSENDCHANGING is set
1586 and always contains final window position.
1588 WinPos
.x
= NewWindowRect
.left
;
1589 WinPos
.y
= NewWindowRect
.top
;
1590 WinPos
.cx
= NewWindowRect
.right
- NewWindowRect
.left
;
1591 WinPos
.cy
= NewWindowRect
.bottom
- NewWindowRect
.top
;
1592 co_IntSendMessageNoWait(WinPos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
) &WinPos
);
1595 if ( WinPos
.flags
& SWP_FRAMECHANGED
|| WinPos
.flags
& SWP_STATECHANGED
||
1596 !(WinPos
.flags
& SWP_NOCLIENTSIZE
) || !(WinPos
.flags
& SWP_NOCLIENTMOVE
) )
1598 PWND pWnd
= UserGetWindowObject(WinPos
.hwnd
);
1600 IntNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE
, pWnd
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
1603 if(bPointerInWindow
!= IntPtInWindow(Window
, gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
))
1605 /* Generate mouse move message */
1607 msg
.message
= WM_MOUSEMOVE
;
1608 msg
.wParam
= UserGetMouseButtonsState();
1609 msg
.lParam
= MAKELPARAM(gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
);
1610 msg
.pt
= gpsi
->ptCursor
;
1611 co_MsqInsertMouseMessage(&msg
, 0, 0, TRUE
);
1618 co_WinPosGetNonClientSize(PWND Window
, RECT
* WindowRect
, RECT
* ClientRect
)
1622 ASSERT_REFS_CO(Window
);
1624 *ClientRect
= *WindowRect
;
1625 Result
= co_IntSendMessage(Window
->head
.h
, WM_NCCALCSIZE
, FALSE
, (LPARAM
) ClientRect
);
1627 FixClientRect(ClientRect
, WindowRect
);
1633 co_WinPosSendSizeMove(PWND Wnd
)
1637 WPARAM wParam
= SIZE_RESTORED
;
1639 IntGetClientRect(Wnd
, &Rect
);
1641 Wnd
->state
&= ~WNDS_SENDSIZEMOVEMSGS
;
1642 if (Wnd
->style
& WS_MAXIMIZE
)
1644 wParam
= SIZE_MAXIMIZED
;
1646 else if (Wnd
->style
& WS_MINIMIZE
)
1648 wParam
= SIZE_MINIMIZED
;
1651 co_IntSendMessageNoWait(UserHMGetHandle(Wnd
), WM_SIZE
, wParam
, MAKELONG(Rect
.right
-Rect
.left
, Rect
.bottom
-Rect
.top
));
1653 if (Wnd
->spwndParent
== UserGetDesktopWindow()) // Wnd->spwndParent->fnid != FNID_DESKTOP )
1654 lParam
= MAKELONG(Wnd
->rcClient
.left
, Wnd
->rcClient
.top
);
1656 lParam
= MAKELONG(Wnd
->rcClient
.left
-Wnd
->spwndParent
->rcClient
.left
, Wnd
->rcClient
.top
-Wnd
->spwndParent
->rcClient
.top
);
1658 co_IntSendMessageNoWait(UserHMGetHandle(Wnd
), WM_MOVE
, 0, lParam
);
1659 IntEngWindowChanged(Wnd
, WOC_RGN_CLIENT
);
1663 co_WinPosShowWindow(PWND Wnd
, INT Cmd
)
1672 ASSERT_REFS_CO(Wnd
);
1674 WasVisible
= (Wnd
->style
& WS_VISIBLE
) != 0;
1685 Swp
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
1686 if (Wnd
->head
.h
!= UserGetActiveWindow())
1687 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1691 case SW_SHOWMINNOACTIVE
:
1692 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1694 case SW_SHOWMINIMIZED
:
1695 Swp
|= SWP_SHOWWINDOW
;
1699 Swp
|= SWP_NOACTIVATE
;
1700 if (!(style
& WS_MINIMIZE
))
1702 Swp
|= co_WinPosMinMaximize(Wnd
, SW_MINIMIZE
, &NewPos
) |
1707 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1710 Swp
|= SWP_FRAMECHANGED
;
1716 case SW_SHOWMAXIMIZED
:
1718 Swp
|= SWP_SHOWWINDOW
;
1719 if (!(style
& WS_MAXIMIZE
))
1721 Swp
|= co_WinPosMinMaximize(Wnd
, SW_MAXIMIZE
, &NewPos
) |
1726 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1729 Swp
|= SWP_FRAMECHANGED
;
1736 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1739 if (WasVisible
) return(TRUE
); // Nothing to do!
1740 Swp
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
1741 /* Don't activate the topmost window. */
1742 if (style
& WS_CHILD
) Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1745 case SW_SHOWNOACTIVATE
:
1746 Wnd
->InternalPos
.flags
&= ~WPF_RESTORETOMAXIMIZED
;
1747 //Swp |= SWP_NOZORDER;
1748 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1751 case SW_SHOWDEFAULT
:
1753 Swp
|= SWP_SHOWWINDOW
;
1754 if (style
& (WS_MINIMIZE
| WS_MAXIMIZE
))
1756 Swp
|= co_WinPosMinMaximize(Wnd
, SW_RESTORE
, &NewPos
) |
1761 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1764 Swp
|= SWP_FRAMECHANGED
;
1770 ShowFlag
= (Cmd
!= SW_HIDE
);
1772 if (ShowFlag
!= WasVisible
)
1774 co_IntSendMessageNoWait(Wnd
->head
.h
, WM_SHOWWINDOW
, ShowFlag
, 0);
1775 if (!(Wnd
->state2
& WNDS2_WIN31COMPAT
))
1776 co_IntSendMessageNoWait(Wnd
->head
.h
, WM_SETVISIBLE
, ShowFlag
, 0);
1779 /* We can't activate a child window */
1780 if ((Wnd
->style
& WS_CHILD
) &&
1781 !(Wnd
->ExStyle
& WS_EX_MDICHILD
))
1783 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1785 #if 0 // Explorer issues with common controls. Someone does not know how CS_SAVEBITS works.
1786 if ((Wnd
->style
& (WS_POPUP
|WS_CHILD
)) != WS_CHILD
&&
1787 Wnd
->pcls
->style
& CS_SAVEBITS
&&
1788 ((Cmd
== SW_SHOW
) || (Cmd
== SW_NORMAL
)))
1790 co_IntSetActiveWindow(Wnd
);
1791 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1794 co_WinPosSetWindowPos(Wnd
, 0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
)
1795 ? HWND_TOPMOST
: HWND_TOP
,
1796 NewPos
.left
, NewPos
.top
, NewPos
.right
, NewPos
.bottom
, LOWORD(Swp
));
1798 if ((Cmd
== SW_HIDE
) || (Cmd
== SW_MINIMIZE
))
1800 PWND ThreadFocusWindow
;
1802 /* FIXME: This will cause the window to be activated irrespective
1803 * of whether it is owned by the same thread. Has to be done
1807 if (Wnd
->head
.h
== UserGetActiveWindow())
1809 co_WinPosActivateOtherWindow(Wnd
);
1814 ThreadFocusWindow
= UserGetWindowObject(IntGetThreadFocusWindow());
1816 /* Revert focus to parent */
1817 /* if (ThreadFocusWindow && (Wnd == ThreadFocusWindow ||
1818 IntIsChildWindow(Wnd, ThreadFocusWindow)))
1820 if (Wnd
== ThreadFocusWindow
)
1822 // FIXME: As long as we have ref on Window, we also, indirectly, have ref on parent...
1823 co_UserSetFocus(Wnd
->spwndParent
);
1827 /* FIXME: Check for window destruction. */
1829 if ((Wnd
->state
& WNDS_SENDSIZEMOVEMSGS
) &&
1830 !(Wnd
->state2
& WNDS2_INDESTROY
))
1832 co_WinPosSendSizeMove(Wnd
);
1835 /* if previous state was minimized Windows sets focus to the window */
1836 if (style
& WS_MINIMIZE
) co_UserSetFocus(Wnd
);
1843 co_WinPosSearchChildren(
1852 if (!(ScopeWin
->style
& WS_VISIBLE
))
1857 if ((ScopeWin
->style
& WS_DISABLED
))
1862 if (!IntPtInWindow(ScopeWin
, Point
->x
, Point
->y
))
1867 UserReferenceObject(ScopeWin
);
1869 if (Point
->x
- ScopeWin
->rcClient
.left
< ScopeWin
->rcClient
.right
&&
1870 Point
->y
- ScopeWin
->rcClient
.top
< ScopeWin
->rcClient
.bottom
)
1872 List
= IntWinListChildren(ScopeWin
);
1875 for (phWnd
= List
; *phWnd
; ++phWnd
)
1877 if (!(pwndChild
= UserGetWindowObject(*phWnd
)))
1882 pwndChild
= co_WinPosSearchChildren(pwndChild
, Point
, HitTest
);
1884 if(pwndChild
!= NULL
)
1886 /* We found a window. Don't send any more WM_NCHITTEST messages */
1888 UserDereferenceObject(ScopeWin
);
1896 *HitTest
= (USHORT
)co_IntSendMessage(ScopeWin
->head
.h
, WM_NCHITTEST
, 0,
1897 MAKELONG(Point
->x
, Point
->y
));
1898 if ((*HitTest
) == (USHORT
)HTTRANSPARENT
)
1900 UserDereferenceObject(ScopeWin
);
1908 co_WinPosWindowFromPoint(PWND ScopeWin
, POINT
*WinPoint
, USHORT
* HitTest
)
1911 POINT Point
= *WinPoint
;
1912 USER_REFERENCE_ENTRY Ref
;
1914 if( ScopeWin
== NULL
)
1916 ScopeWin
= UserGetDesktopWindow();
1917 if(ScopeWin
== NULL
)
1921 *HitTest
= HTNOWHERE
;
1923 ASSERT_REFS_CO(ScopeWin
);
1924 UserRefObjectCo(ScopeWin
, &Ref
);
1926 Window
= co_WinPosSearchChildren(ScopeWin
, &Point
, HitTest
);
1928 UserDerefObjectCo(ScopeWin
);
1930 ASSERT_REFS_CO(Window
);
1931 ASSERT_REFS_CO(ScopeWin
);
1938 IntDeferWindowPos( HDWP hdwp
,
1949 HDWP retvalue
= hdwp
;
1951 TRACE("hdwp %p, hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
1952 hdwp
, hwnd
, hwndAfter
, x
, y
, cx
, cy
, flags
);
1954 if (flags
& ~(SWP_NOSIZE
| SWP_NOMOVE
|
1955 SWP_NOZORDER
| SWP_NOREDRAW
|
1956 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
1957 SWP_NOOWNERZORDER
|SWP_SHOWWINDOW
|
1958 SWP_HIDEWINDOW
| SWP_FRAMECHANGED
))
1960 EngSetLastError(ERROR_INVALID_PARAMETER
);
1964 if (!(pDWP
= (PSMWP
)UserGetObject(gHandleTable
, hdwp
, otSMWP
)))
1966 EngSetLastError(ERROR_INVALID_DWP_HANDLE
);
1970 for (i
= 0; i
< pDWP
->ccvr
; i
++)
1972 if (pDWP
->acvr
[i
].pos
.hwnd
== hwnd
)
1974 /* Merge with the other changes */
1975 if (!(flags
& SWP_NOZORDER
))
1977 pDWP
->acvr
[i
].pos
.hwndInsertAfter
= hwndAfter
;
1979 if (!(flags
& SWP_NOMOVE
))
1981 pDWP
->acvr
[i
].pos
.x
= x
;
1982 pDWP
->acvr
[i
].pos
.y
= y
;
1984 if (!(flags
& SWP_NOSIZE
))
1986 pDWP
->acvr
[i
].pos
.cx
= cx
;
1987 pDWP
->acvr
[i
].pos
.cy
= cy
;
1989 pDWP
->acvr
[i
].pos
.flags
&= flags
| ~(SWP_NOSIZE
| SWP_NOMOVE
|
1990 SWP_NOZORDER
| SWP_NOREDRAW
|
1991 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
1993 pDWP
->acvr
[i
].pos
.flags
|= flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
|
1998 if (pDWP
->ccvr
>= pDWP
->ccvrAlloc
)
2000 PCVR newpos
= ExAllocatePoolWithTag(PagedPool
, pDWP
->ccvrAlloc
* 2 * sizeof(CVR
), USERTAG_SWP
);
2006 RtlZeroMemory(newpos
, pDWP
->ccvrAlloc
* 2 * sizeof(CVR
));
2007 RtlCopyMemory(newpos
, pDWP
->acvr
, pDWP
->ccvrAlloc
* sizeof(CVR
));
2008 ExFreePoolWithTag(pDWP
->acvr
, USERTAG_SWP
);
2009 pDWP
->ccvrAlloc
*= 2;
2010 pDWP
->acvr
= newpos
;
2012 pDWP
->acvr
[pDWP
->ccvr
].pos
.hwnd
= hwnd
;
2013 pDWP
->acvr
[pDWP
->ccvr
].pos
.hwndInsertAfter
= hwndAfter
;
2014 pDWP
->acvr
[pDWP
->ccvr
].pos
.x
= x
;
2015 pDWP
->acvr
[pDWP
->ccvr
].pos
.y
= y
;
2016 pDWP
->acvr
[pDWP
->ccvr
].pos
.cx
= cx
;
2017 pDWP
->acvr
[pDWP
->ccvr
].pos
.cy
= cy
;
2018 pDWP
->acvr
[pDWP
->ccvr
].pos
.flags
= flags
;
2019 pDWP
->acvr
[pDWP
->ccvr
].hrgnClip
= NULL
;
2020 pDWP
->acvr
[pDWP
->ccvr
].hrgnInterMonitor
= NULL
;
2026 BOOL FASTCALL
IntEndDeferWindowPosEx( HDWP hdwp
, BOOL sAsync
)
2033 TRACE("%p\n", hdwp
);
2035 if (!(pDWP
= (PSMWP
)UserGetObject(gHandleTable
, hdwp
, otSMWP
)))
2037 EngSetLastError(ERROR_INVALID_DWP_HANDLE
);
2041 for (i
= 0, winpos
= pDWP
->acvr
; res
&& i
< pDWP
->ccvr
; i
++, winpos
++)
2044 USER_REFERENCE_ENTRY Ref
;
2046 TRACE("hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
2047 winpos
->pos
.hwnd
, winpos
->pos
.hwndInsertAfter
, winpos
->pos
.x
, winpos
->pos
.y
,
2048 winpos
->pos
.cx
, winpos
->pos
.cy
, winpos
->pos
.flags
);
2050 pwnd
= UserGetWindowObject(winpos
->pos
.hwnd
);
2054 UserRefObjectCo(pwnd
, &Ref
);
2059 PWINDOWPOS ppos
= ExAllocatePoolWithTag(PagedPool
, sizeof(WINDOWPOS
), USERTAG_SWP
);
2062 *ppos
= winpos
->pos
;
2063 /* Yes it's a pointer inside Win32k! */
2064 lRes
= co_IntSendMessageNoWait( winpos
->pos
.hwnd
, WM_ASYNC_SETWINDOWPOS
, 0, (LPARAM
)ppos
);
2065 /* We handle this the same way as Event Hooks and Hooks. */
2066 if ( -1 == (int) lRes
)
2068 ExFreePoolWithTag(ppos
, USERTAG_SWP
);
2073 res
= co_WinPosSetWindowPos( pwnd
,
2074 winpos
->pos
.hwndInsertAfter
,
2081 UserDerefObjectCo(pwnd
);
2083 ExFreePoolWithTag(pDWP
->acvr
, USERTAG_SWP
);
2084 UserDereferenceObject(pDWP
);
2085 UserDeleteObject(hdwp
, otSMWP
);
2094 NtUserChildWindowFromPointEx(HWND hwndParent
,
2104 if(!(Parent
= UserGetWindowObject(hwndParent
)))
2112 if(Parent
->head
.h
!= IntGetDesktopWindow())
2114 Pt
.x
+= Parent
->rcClient
.left
;
2115 Pt
.y
+= Parent
->rcClient
.top
;
2118 if(!IntPtInWindow(Parent
, Pt
.x
, Pt
.y
))
2123 Ret
= Parent
->head
.h
;
2124 if((List
= IntWinListChildren(Parent
)))
2126 for(phWnd
= List
; *phWnd
; phWnd
++)
2129 if((Child
= UserGetWindowObject(*phWnd
)))
2131 if(!(Child
->style
& WS_VISIBLE
) && (uiFlags
& CWP_SKIPINVISIBLE
))
2135 if((Child
->style
& WS_DISABLED
) && (uiFlags
& CWP_SKIPDISABLED
))
2139 if((Child
->ExStyle
& WS_EX_TRANSPARENT
) && (uiFlags
& CWP_SKIPTRANSPARENT
))
2143 if(IntPtInWindow(Child
, Pt
.x
, Pt
.y
))
2145 Ret
= Child
->head
.h
;
2160 NtUserEndDeferWindowPosEx(HDWP WinPosInfo
,
2164 TRACE("Enter NtUserEndDeferWindowPosEx\n");
2165 UserEnterExclusive();
2166 Ret
= IntEndDeferWindowPosEx(WinPosInfo
, (BOOL
)Unknown1
);
2167 TRACE("Leave NtUserEndDeferWindowPosEx, ret=%i\n", Ret
);
2176 NtUserDeferWindowPos(HDWP WinPosInfo
,
2178 HWND WndInsertAfter
,
2187 UINT Tmp
= ~(SWP_ASYNCWINDOWPOS
|SWP_DEFERERASE
|SWP_NOSENDCHANGING
|SWP_NOREPOSITION
|
2188 SWP_NOCOPYBITS
|SWP_HIDEWINDOW
|SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|
2189 SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_NOZORDER
|SWP_NOMOVE
|SWP_NOSIZE
);
2191 TRACE("Enter NtUserDeferWindowPos\n");
2192 UserEnterExclusive();
2196 EngSetLastError(ERROR_INVALID_FLAGS
);
2200 pWnd
= UserGetWindowObject(Wnd
);
2201 if ( !pWnd
|| // FIXME:
2202 pWnd
== IntGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
2203 pWnd
== IntGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
2208 if ( WndInsertAfter
&&
2209 WndInsertAfter
!= HWND_BOTTOM
&&
2210 WndInsertAfter
!= HWND_TOPMOST
&&
2211 WndInsertAfter
!= HWND_NOTOPMOST
)
2213 pWndIA
= UserGetWindowObject(WndInsertAfter
);
2215 pWndIA
== IntGetDesktopWindow() ||
2216 pWndIA
== IntGetMessageWindow() )
2222 Ret
= IntDeferWindowPos(WinPosInfo
, Wnd
, WndInsertAfter
, x
, y
, cx
, cy
, Flags
);
2225 TRACE("Leave NtUserDeferWindowPos, ret=%i\n", Ret
);
2234 NtUserGetInternalWindowPos( HWND hWnd
,
2241 WINDOWPLACEMENT wndpl
;
2245 if (!(Window
= UserGetWindowObject(hWnd
)))
2255 ProbeForWrite(rectWnd
,
2261 ProbeForWrite(ptIcon
,
2267 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2269 SetLastNtError(_SEH2_GetExceptionCode());
2274 wndpl
.length
= sizeof(WINDOWPLACEMENT
);
2276 if (IntGetWindowPlacement(Window
, &wndpl
) && !Hit
)
2282 RtlCopyMemory(rectWnd
, &wndpl
.rcNormalPosition
, sizeof(RECT
));
2286 RtlCopyMemory(ptIcon
, &wndpl
.ptMinPosition
, sizeof(POINT
));
2290 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2292 SetLastNtError(_SEH2_GetExceptionCode());
2297 if (!Hit
) Ret
= wndpl
.showCmd
;
2308 NtUserGetWindowPlacement(HWND hWnd
,
2309 WINDOWPLACEMENT
*lpwndpl
)
2312 WINDOWPLACEMENT Safepl
;
2314 DECLARE_RETURN(BOOL
);
2316 TRACE("Enter NtUserGetWindowPlacement\n");
2319 if (!(Wnd
= UserGetWindowObject(hWnd
)))
2324 Status
= MmCopyFromCaller(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
2325 if(!NT_SUCCESS(Status
))
2327 SetLastNtError(Status
);
2330 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
2335 IntGetWindowPlacement(Wnd
, &Safepl
);
2337 Status
= MmCopyToCaller(lpwndpl
, &Safepl
, sizeof(WINDOWPLACEMENT
));
2338 if(!NT_SUCCESS(Status
))
2340 SetLastNtError(Status
);
2347 TRACE("Leave NtUserGetWindowPlacement, ret=%i\n",_ret_
);
2356 UINT cmd
, // Wine SW_ commands
2363 TRACE("Enter NtUserMinMaximize\n");
2364 UserEnterExclusive();
2366 pWnd
= UserGetWindowObject(hWnd
);
2367 if ( !pWnd
|| // FIXME:
2368 pWnd
== IntGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
2369 pWnd
== IntGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
2374 if ( cmd
> SW_MAX
|| pWnd
->state2
& WNDS2_INDESTROY
)
2376 EngSetLastError(ERROR_INVALID_PARAMETER
);
2380 co_WinPosMinMaximize(pWnd
, cmd
, &NewPos
);
2382 SwFlags
= Hide
? SWP_NOACTIVATE
|SWP_NOZORDER
|SWP_FRAMECHANGED
: SWP_NOZORDER
|SWP_FRAMECHANGED
;
2384 co_WinPosSetWindowPos( pWnd
,
2392 co_WinPosShowWindow(pWnd
, cmd
);
2395 TRACE("Leave NtUserMinMaximize\n");
2397 return 0; // Always NULL?
2412 return NtUserSetWindowPos(hWnd
, 0, X
, Y
, nWidth
, nHeight
,
2413 (bRepaint
? SWP_NOZORDER
| SWP_NOACTIVATE
:
2414 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
));
2423 HWND hWndInsertAfter
,
2430 DECLARE_RETURN(BOOL
);
2431 PWND Window
, pWndIA
;
2433 USER_REFERENCE_ENTRY Ref
;
2435 TRACE("Enter NtUserSetWindowPos\n");
2436 UserEnterExclusive();
2438 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
2439 Window
== IntGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
2440 Window
== IntGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
2445 if ( hWndInsertAfter
&&
2446 hWndInsertAfter
!= HWND_BOTTOM
&&
2447 hWndInsertAfter
!= HWND_TOPMOST
&&
2448 hWndInsertAfter
!= HWND_NOTOPMOST
)
2450 pWndIA
= UserGetWindowObject(hWndInsertAfter
);
2452 pWndIA
== IntGetDesktopWindow() ||
2453 pWndIA
== IntGetMessageWindow() )
2459 /* First make sure that coordinates are valid for WM_WINDOWPOSCHANGING */
2460 if (!(uFlags
& SWP_NOMOVE
))
2462 if (X
< -32768) X
= -32768;
2463 else if (X
> 32767) X
= 32767;
2464 if (Y
< -32768) Y
= -32768;
2465 else if (Y
> 32767) Y
= 32767;
2467 if (!(uFlags
& SWP_NOSIZE
))
2470 else if (cx
> 32767) cx
= 32767;
2472 else if (cy
> 32767) cy
= 32767;
2475 UserRefObjectCo(Window
, &Ref
);
2476 ret
= co_WinPosSetWindowPos(Window
, hWndInsertAfter
, X
, Y
, cx
, cy
, uFlags
);
2477 UserDerefObjectCo(Window
);
2482 TRACE("Leave NtUserSetWindowPos, ret=%i\n",_ret_
);
2498 INT flags
= (SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
);
2499 BOOLEAN Ret
= FALSE
;
2500 DECLARE_RETURN(INT
);
2502 TRACE("Enter NtUserSetWindowRgn\n");
2503 UserEnterExclusive();
2505 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
2506 Window
== IntGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
2507 Window
== IntGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
2512 if (hRgn
) // The region will be deleted in user32.
2514 if (GreIsHandleValid(hRgn
))
2516 hrgnCopy
= IntSysCreateRectRgn(0, 0, 0, 0);
2517 /* The coordinates of a window's window region are relative to the
2518 upper-left corner of the window, not the client area of the window. */
2519 NtGdiCombineRgn( hrgnCopy
, hRgn
, 0, RGN_COPY
);
2529 if (Window
->hrgnClip
)
2531 /* Delete no longer needed region handle */
2532 IntGdiSetRegionOwner(Window
->hrgnClip
, GDI_OBJ_HMGR_POWNED
);
2533 GreDeleteObject(Window
->hrgnClip
);
2538 /* Set public ownership */
2539 IntGdiSetRegionOwner(hrgnCopy
, GDI_OBJ_HMGR_PUBLIC
);
2541 Window
->hrgnClip
= hrgnCopy
;
2543 Ret
= co_WinPosSetWindowPos(Window
, HWND_TOP
, 0, 0, 0, 0, bRedraw
? flags
: (flags
|SWP_NOREDRAW
) );
2548 TRACE("Leave NtUserSetWindowRgn, ret=%i\n",_ret_
);
2557 NtUserSetInternalWindowPos(
2563 WINDOWPLACEMENT wndpl
;
2568 DECLARE_RETURN(BOOL
);
2569 USER_REFERENCE_ENTRY Ref
;
2571 TRACE("Enter NtUserSetWindowPlacement\n");
2572 UserEnterExclusive();
2574 if (!(Wnd
= UserGetWindowObject(hwnd
)) || // FIXME:
2575 Wnd
== IntGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
2576 Wnd
== IntGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
2585 ProbeForRead(lppt
, sizeof(POINT
), 1);
2586 RtlCopyMemory(&pt
, lppt
, sizeof(POINT
));
2590 ProbeForRead(lprect
, sizeof(RECT
), 1);
2591 RtlCopyMemory(&rect
, lprect
, sizeof(RECT
));
2594 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2596 SetLastNtError(_SEH2_GetExceptionCode());
2597 _SEH2_YIELD(RETURN( FALSE
));
2601 wndpl
.length
= sizeof(wndpl
);
2602 wndpl
.showCmd
= showCmd
;
2603 wndpl
.flags
= flags
= 0;
2608 wndpl
.flags
|= WPF_SETMINPOSITION
;
2609 wndpl
.ptMinPosition
= pt
;
2613 flags
|= PLACE_RECT
;
2614 wndpl
.rcNormalPosition
= rect
;
2617 UserRefObjectCo(Wnd
, &Ref
);
2618 IntSetWindowPlacement(Wnd
, &wndpl
, flags
);
2619 UserDerefObjectCo(Wnd
);
2623 TRACE("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_
);
2632 NtUserSetWindowPlacement(HWND hWnd
,
2633 WINDOWPLACEMENT
*lpwndpl
)
2636 WINDOWPLACEMENT Safepl
;
2638 DECLARE_RETURN(BOOL
);
2639 USER_REFERENCE_ENTRY Ref
;
2641 TRACE("Enter NtUserSetWindowPlacement\n");
2642 UserEnterExclusive();
2644 if (!(Wnd
= UserGetWindowObject(hWnd
)) || // FIXME:
2645 Wnd
== IntGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
2646 Wnd
== IntGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
2653 ProbeForRead(lpwndpl
, sizeof(WINDOWPLACEMENT
), 1);
2654 RtlCopyMemory(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
2656 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2658 SetLastNtError(_SEH2_GetExceptionCode());
2659 _SEH2_YIELD(RETURN( FALSE
));
2663 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
2668 Flags
= PLACE_MAX
| PLACE_RECT
;
2669 if (Safepl
.flags
& WPF_SETMINPOSITION
) Flags
|= PLACE_MIN
;
2670 UserRefObjectCo(Wnd
, &Ref
);
2671 IntSetWindowPlacement(Wnd
, &Safepl
, Flags
);
2672 UserDerefObjectCo(Wnd
);
2676 TRACE("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_
);
2685 NtUserShowWindowAsync(HWND hWnd
, LONG nCmdShow
)
2689 DECLARE_RETURN(BOOL
);
2690 USER_REFERENCE_ENTRY Ref
;
2692 TRACE("Enter NtUserShowWindowAsync\n");
2693 UserEnterExclusive();
2695 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
2696 Window
== IntGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
2697 Window
== IntGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
2702 if ( nCmdShow
> SW_MAX
)
2704 EngSetLastError(ERROR_INVALID_PARAMETER
);
2708 UserRefObjectCo(Window
, &Ref
);
2709 ret
= co_IntSendMessageNoWait( hWnd
, WM_ASYNC_SHOWWINDOW
, nCmdShow
, 0 );
2710 UserDerefObjectCo(Window
);
2711 if (-1 == (int) ret
|| !ret
) ret
= FALSE
;
2716 TRACE("Leave NtUserShowWindowAsync, ret=%i\n",_ret_
);
2725 NtUserShowWindow(HWND hWnd
, LONG nCmdShow
)
2729 DECLARE_RETURN(BOOL
);
2730 USER_REFERENCE_ENTRY Ref
;
2732 TRACE("Enter NtUserShowWindow\n");
2733 UserEnterExclusive();
2735 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
2736 Window
== IntGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
2737 Window
== IntGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
2742 if ( nCmdShow
> SW_MAX
|| Window
->state2
& WNDS2_INDESTROY
)
2744 EngSetLastError(ERROR_INVALID_PARAMETER
);
2748 UserRefObjectCo(Window
, &Ref
);
2749 ret
= co_WinPosShowWindow(Window
, nCmdShow
);
2750 UserDerefObjectCo(Window
);
2755 TRACE("Leave NtUserShowWindow, ret=%i\n",_ret_
);
2765 NtUserWindowFromPoint(LONG X
, LONG Y
)
2769 PWND DesktopWindow
= NULL
, Window
= NULL
;
2771 DECLARE_RETURN(HWND
);
2772 USER_REFERENCE_ENTRY Ref
;
2774 TRACE("Enter NtUserWindowFromPoint\n");
2775 UserEnterExclusive();
2777 if ((DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow())))
2784 // Hmm... Threads live on desktops thus we have a reference on the desktop and indirectly the desktop window.
2785 // It is possible this referencing is useless, though it should not hurt...
2786 UserRefObjectCo(DesktopWindow
, &Ref
);
2788 //pti = PsGetCurrentThreadWin32Thread();
2789 Window
= co_WinPosWindowFromPoint(DesktopWindow
, &pt
, &hittest
);
2793 Ret
= Window
->head
.h
;
2802 if (Window
) UserDereferenceObject(Window
);
2803 if (DesktopWindow
) UserDerefObjectCo(DesktopWindow
);
2805 TRACE("Leave NtUserWindowFromPoint, ret=%i\n",_ret_
);