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 VOID FASTCALL
IntLinkWindow(PWND Wnd
,PWND WndInsertAfter
);
33 /* FUNCTIONS *****************************************************************/
36 IntGetClientOrigin(PWND Window OPTIONAL
, LPPOINT Point
)
38 Window
= Window
? Window
: UserGetDesktopWindow();
41 Point
->x
= Point
->y
= 0;
44 Point
->x
= Window
->rcClient
.left
;
45 Point
->y
= Window
->rcClient
.top
;
52 * Returns client window rectangle relative to the upper-left corner of client area.
54 * \note Does not check the validity of the parameters
57 IntGetClientRect(PWND Wnd
, RECTL
*Rect
)
61 if (Wnd
->style
& WS_MINIMIZED
)
63 Rect
->left
= Rect
->top
= 0;
64 Rect
->right
= UserGetSystemMetrics(SM_CXMINIMIZED
);
65 Rect
->bottom
= UserGetSystemMetrics(SM_CYMINIMIZED
);
68 if ( Wnd
!= UserGetDesktopWindow()) // Wnd->fnid != FNID_DESKTOP )
70 *Rect
= Wnd
->rcClient
;
71 RECTL_vOffsetRect(Rect
, -Wnd
->rcClient
.left
, -Wnd
->rcClient
.top
);
75 Rect
->left
= Rect
->top
= 0;
76 Rect
->right
= Wnd
->rcClient
.right
;
77 Rect
->bottom
= Wnd
->rcClient
.bottom
;
78 /* Do this until Init bug is fixed. This sets 640x480, see InitMetrics.
79 Rect->right = UserGetSystemMetrics(SM_CXSCREEN);
80 Rect->bottom = UserGetSystemMetrics(SM_CYSCREEN);
86 IntMapWindowPoints(PWND FromWnd
, PWND ToWnd
, LPPOINT lpPoints
, UINT cPoints
)
88 BOOL mirror_from
, mirror_to
;
93 /* Note: Desktop Top and Left is always 0! */
94 Delta
.x
= Delta
.y
= 0;
95 mirror_from
= mirror_to
= FALSE
;
97 if (FromWnd
&& FromWnd
!= UserGetDesktopWindow()) // FromWnd->fnid != FNID_DESKTOP)
99 if (FromWnd
->ExStyle
& WS_EX_LAYOUTRTL
)
103 Delta
.x
= -FromWnd
->rcClient
.right
;
106 Delta
.x
= FromWnd
->rcClient
.left
;
107 Delta
.y
= FromWnd
->rcClient
.top
;
110 if (ToWnd
&& ToWnd
!= UserGetDesktopWindow()) // ToWnd->fnid != FNID_DESKTOP)
112 if (ToWnd
->ExStyle
& WS_EX_LAYOUTRTL
)
116 Delta
.x
+= Change
* ToWnd
->rcClient
.right
;
119 Delta
.x
-= Change
* ToWnd
->rcClient
.left
;
120 Delta
.y
-= ToWnd
->rcClient
.top
;
123 for (i
= 0; i
!= cPoints
; i
++)
125 lpPoints
[i
].x
+= Delta
.x
;
126 lpPoints
[i
].x
*= Change
;
127 lpPoints
[i
].y
+= Delta
.y
;
130 if ((mirror_from
|| mirror_to
) && cPoints
== 2) /* special case for rectangle */
132 int tmp
= min(lpPoints
[0].x
, lpPoints
[1].x
);
133 lpPoints
[1].x
= max(lpPoints
[0].x
, lpPoints
[1].x
);
137 return MAKELONG(LOWORD(Delta
.x
), LOWORD(Delta
.y
));
141 IntClientToScreen(PWND Wnd
, LPPOINT lpPoint
)
143 if (Wnd
&& Wnd
->fnid
!= FNID_DESKTOP
)
145 if (Wnd
->ExStyle
& WS_EX_LAYOUTRTL
)
146 lpPoint
->x
= Wnd
->rcClient
.right
- lpPoint
->x
;
148 lpPoint
->x
+= Wnd
->rcClient
.left
;
149 lpPoint
->y
+= Wnd
->rcClient
.top
;
155 IntScreenToClient(PWND Wnd
, LPPOINT lpPoint
)
157 if (Wnd
&& Wnd
->fnid
!= FNID_DESKTOP
)
159 if (Wnd
->ExStyle
& WS_EX_LAYOUTRTL
)
160 lpPoint
->x
= Wnd
->rcClient
.right
- lpPoint
->x
;
162 lpPoint
->x
-= Wnd
->rcClient
.left
;
163 lpPoint
->y
-= Wnd
->rcClient
.top
;
168 BOOL FASTCALL
IsChildVisible(PWND pWnd
)
172 if ( (pWnd
->style
& (WS_POPUP
|WS_CHILD
)) != WS_CHILD
||
173 !(pWnd
= pWnd
->spwndParent
) )
176 while (pWnd
->style
& WS_VISIBLE
);
180 PWND FASTCALL
IntGetLastTopMostWindow(VOID
)
183 PDESKTOP rpdesk
= gptiCurrent
->rpdesk
;
186 (pWnd
= rpdesk
->pDeskInfo
->spwnd
->spwndChild
) &&
187 pWnd
->ExStyle
& WS_EX_TOPMOST
)
191 if (!pWnd
->spwndNext
) break;
192 if (!(pWnd
->spwndNext
->ExStyle
& WS_EX_TOPMOST
)) break;
193 pWnd
= pWnd
->spwndNext
;
201 // This helps with CORE-6129 forcing modal dialog active when another app is minimized or closed.
203 BOOL FASTCALL
ActivateOtherWindowMin(PWND Wnd
)
205 BOOL ActivePrev
, FindTopWnd
;
206 PWND pWndTopMost
, pWndChild
, pWndSetActive
, pWndTemp
, pWndDesk
;
207 USER_REFERENCE_ENTRY Ref
;
208 PTHREADINFO pti
= gptiCurrent
;
211 ActivePrev
= (pti
->MessageQueue
->spwndActivePrev
!= NULL
);
214 if ((pWndTopMost
= IntGetLastTopMostWindow()))
215 pWndChild
= pWndTopMost
->spwndNext
;
217 pWndChild
= Wnd
->spwndParent
->spwndChild
;
222 pWndSetActive
= pti
->MessageQueue
->spwndActivePrev
;
224 pWndSetActive
= pWndChild
;
230 if ( VerifyWnd(pWndSetActive
) &&
231 !(pWndSetActive
->ExStyle
& WS_EX_NOACTIVATE
) &&
232 (pWndSetActive
->style
& (WS_VISIBLE
|WS_DISABLED
)) == WS_VISIBLE
&&
233 (!(pWndSetActive
->style
& WS_ICONIC
) /* FIXME MinMax pos? */ ) )
235 if (!(pWndSetActive
->ExStyle
& WS_EX_TOOLWINDOW
) )
237 UserRefObjectCo(pWndSetActive
, &Ref
);
238 //ERR("ActivateOtherWindowMin Set FG 1\n");
239 co_IntSetForegroundWindow(pWndSetActive
);
240 UserDerefObjectCo(pWndSetActive
);
241 //ERR("AOWM 2 Exit Good\n");
244 if (!pWndTemp
) pWndTemp
= pWndSetActive
;
249 pWndSetActive
= pWndChild
;
252 pWndSetActive
= pWndSetActive
->spwndNext
;
255 if ( !FindTopWnd
) break;
260 pWndChild
= pWndChild
->spwndParent
->spwndChild
;
264 if (!(pWndDesk
= IntGetThreadDesktopWindow(pti
)))
269 pWndChild
= pWndDesk
->spwndChild
;
272 if ((pWndSetActive
= pWndTemp
))
274 UserRefObjectCo(pWndSetActive
, &Ref
);
275 //ERR("ActivateOtherWindowMin Set FG 2\n");
276 co_IntSetForegroundWindow(pWndSetActive
);
277 UserDerefObjectCo(pWndSetActive
);
278 //ERR("AOWM 3 Exit Good\n");
281 //ERR("AOWM 4 Bad\n");
285 /*******************************************************************
286 * can_activate_window
288 * Check if we can activate the specified window.
291 BOOL FASTCALL
can_activate_window( PWND Wnd OPTIONAL
)
295 if (!Wnd
) return FALSE
;
298 if (!(style
& WS_VISIBLE
)) return FALSE
;
299 if (style
& WS_MINIMIZE
) return FALSE
;
300 if ((style
& (WS_POPUP
|WS_CHILD
)) == WS_CHILD
) return FALSE
;
302 /* FIXME: This window could be disable because the child that closed
304 //return !(style & WS_DISABLED);
308 /*******************************************************************
309 * WinPosActivateOtherWindow
311 * Activates window other than pWnd.
314 co_WinPosActivateOtherWindow(PWND Wnd
)
317 USER_REFERENCE_ENTRY Ref
;
321 if (IntIsDesktopWindow(Wnd
))
323 IntSetFocusMessageQueue(NULL
);
327 /* If this is popup window, try to activate the owner first. */
328 if ((Wnd
->style
& WS_POPUP
) && (WndTo
= Wnd
->spwndOwner
))
330 WndTo
= UserGetAncestor( WndTo
, GA_ROOT
);
331 if (can_activate_window(WndTo
)) goto done
;
334 /* Pick a next top-level window. */
335 /* FIXME: Search for non-tooltip windows first. */
339 if (!(WndTo
= WndTo
->spwndNext
)) break;
340 if (can_activate_window( WndTo
)) break;
345 if (WndTo
) UserRefObjectCo(WndTo
, &Ref
);
347 if (!gpqForeground
|| Wnd
== gpqForeground
->spwndActive
)
349 /* ReactOS can pass WndTo = NULL to co_IntSetForegroundWindow and returns FALSE. */
350 //ERR("WinPosActivateOtherWindow Set FG 0x%p\n",WndTo);
351 if (co_IntSetForegroundWindow(WndTo
))
353 if (WndTo
) UserDerefObjectCo(WndTo
);
357 //ERR("WinPosActivateOtherWindow Set Active 0x%p\n",WndTo);
358 if (!co_IntSetActiveWindow(WndTo
,FALSE
,TRUE
,FALSE
)) /* Ok for WndTo to be NULL here */
360 co_IntSetActiveWindow(NULL
,FALSE
,TRUE
,FALSE
);
362 if (WndTo
) UserDerefObjectCo(WndTo
);
366 WinPosInitInternalPos(PWND Wnd
, RECTL
*RestoreRect
)
369 RECTL Rect
= *RestoreRect
;
371 if (Wnd
->spwndParent
!= UserGetDesktopWindow())
373 RECTL_vOffsetRect(&Rect
,
374 -Wnd
->spwndParent
->rcClient
.left
,
375 -Wnd
->spwndParent
->rcClient
.top
);
381 if (!Wnd
->InternalPosInitialized
)
383 // FIXME: Use check point Atom..
384 Wnd
->InternalPos
.flags
= 0;
385 Wnd
->InternalPos
.MaxPos
.x
= Wnd
->InternalPos
.MaxPos
.y
= -1;
386 Wnd
->InternalPos
.IconPos
.x
= Wnd
->InternalPos
.IconPos
.y
= -1;
387 Wnd
->InternalPos
.NormalRect
= Rect
;
388 Wnd
->InternalPosInitialized
= TRUE
;
391 if (Wnd
->style
& WS_MINIMIZE
)
393 Wnd
->InternalPos
.IconPos
= Size
;
394 Wnd
->InternalPos
.flags
|= WPF_MININIT
;
396 else if (Wnd
->style
& WS_MAXIMIZE
)
398 Wnd
->InternalPos
.flags
|= WPF_MAXINIT
;
400 if ( Wnd
->spwndParent
== Wnd
->head
.rpdesk
->pDeskInfo
->spwnd
)
402 if (Wnd
->state
& WNDS_MAXIMIZESTOMONITOR
)
404 Wnd
->InternalPos
.flags
&= ~WPF_MAXINIT
;
405 Wnd
->InternalPos
.MaxPos
.x
= Wnd
->InternalPos
.MaxPos
.y
= -1;
410 PMONITOR pmonitor
= UserMonitorFromRect(&Rect
, MONITOR_DEFAULTTOPRIMARY
);
411 // FIXME: support DPI aware, rcWorkDPI/Real etc..
412 WorkArea
= pmonitor
->rcMonitor
;
414 if (Wnd
->style
& WS_MAXIMIZEBOX
)
415 { // Support (Wnd->state & WNDS_HASCAPTION) || pmonitor->cFullScreen too.
416 if ((Wnd
->style
& WS_CAPTION
) == WS_CAPTION
|| !(Wnd
->style
& (WS_CHILD
| WS_POPUP
)))
418 WorkArea
= pmonitor
->rcWork
;
423 Wnd
->InternalPos
.MaxPos
.x
= Rect
.left
- WorkArea
.left
;
424 Wnd
->InternalPos
.MaxPos
.y
= Rect
.top
- WorkArea
.top
;
426 /*ERR("WinPosIP 2 X %d = R.l %d - W.l %d | Y %d = R.t %d - W.t %d\n",
427 Wnd->InternalPos.MaxPos.x,
428 Rect.left, WorkArea.left,
429 Wnd->InternalPos.MaxPos.y,
430 Rect.top, WorkArea.top);*/
434 Wnd
->InternalPos
.MaxPos
= Size
;
438 Wnd
->InternalPos
.NormalRect
= Rect
;
444 IntGetWindowPlacement(PWND Wnd
, WINDOWPLACEMENT
*lpwndpl
)
446 if (!Wnd
) return FALSE
;
448 if(lpwndpl
->length
!= sizeof(WINDOWPLACEMENT
))
455 WinPosInitInternalPos(Wnd
, &Wnd
->rcWindow
);
457 lpwndpl
->showCmd
= SW_HIDE
;
459 if ( Wnd
->style
& WS_MINIMIZE
)
460 lpwndpl
->showCmd
= SW_SHOWMINIMIZED
;
462 lpwndpl
->showCmd
= ( Wnd
->style
& WS_MAXIMIZE
) ? SW_SHOWMAXIMIZED
: SW_SHOWNORMAL
;
464 lpwndpl
->rcNormalPosition
= Wnd
->InternalPos
.NormalRect
;
466 if (Wnd
->InternalPos
.flags
& WPF_MININIT
) // Return if it was set!
468 lpwndpl
->ptMinPosition
.x
= Wnd
->InternalPos
.IconPos
.x
;
469 lpwndpl
->ptMinPosition
.y
= Wnd
->InternalPos
.IconPos
.y
;
472 lpwndpl
->ptMinPosition
.x
= lpwndpl
->ptMinPosition
.y
= -1;
474 if ( Wnd
->InternalPos
.flags
& WPF_MAXINIT
&& // Return if set and not maximized to monitor!
475 !(Wnd
->state
& WNDS_MAXIMIZESTOMONITOR
))
477 lpwndpl
->ptMaxPosition
.x
= Wnd
->InternalPos
.MaxPos
.x
;
478 lpwndpl
->ptMaxPosition
.y
= Wnd
->InternalPos
.MaxPos
.y
;
481 lpwndpl
->ptMaxPosition
.x
= lpwndpl
->ptMaxPosition
.y
= -1;
483 if ( Wnd
->spwndParent
== Wnd
->head
.rpdesk
->pDeskInfo
->spwnd
&&
484 !(Wnd
->ExStyle
& WS_EX_TOOLWINDOW
))
486 PMONITOR pmonitor
= UserMonitorFromRect(&lpwndpl
->rcNormalPosition
, MONITOR_DEFAULTTOPRIMARY
);
488 // FIXME: support DPI aware, rcWorkDPI/Real etc..
489 if (Wnd
->InternalPos
.flags
& WPF_MININIT
)
491 lpwndpl
->ptMinPosition
.x
-= (pmonitor
->rcWork
.left
- pmonitor
->rcMonitor
.left
);
492 lpwndpl
->ptMinPosition
.y
-= (pmonitor
->rcWork
.top
- pmonitor
->rcMonitor
.top
);
494 RECTL_vOffsetRect(&lpwndpl
->rcNormalPosition
,
495 pmonitor
->rcMonitor
.left
- pmonitor
->rcWork
.left
,
496 pmonitor
->rcMonitor
.top
- pmonitor
->rcWork
.top
);
499 if ( Wnd
->InternalPos
.flags
& WPF_RESTORETOMAXIMIZED
|| Wnd
->style
& WS_MAXIMIZE
)
500 lpwndpl
->flags
|= WPF_RESTORETOMAXIMIZED
;
502 if ( ((Wnd
->style
& (WS_CHILD
|WS_POPUP
)) == WS_CHILD
) && Wnd
->InternalPos
.flags
& WPF_SETMINPOSITION
)
503 lpwndpl
->flags
|= WPF_SETMINPOSITION
;
508 /* make sure the specified rect is visible on screen */
509 static void make_rect_onscreen( RECT
*rect
)
511 PMONITOR pmonitor
= UserMonitorFromRect( rect
, MONITOR_DEFAULTTONEAREST
); // Wine uses this.
513 // FIXME: support DPI aware, rcWorkDPI/Real etc..
514 if (!pmonitor
) return;
515 /* FIXME: map coordinates from rcWork to rcMonitor */
516 if (rect
->right
<= pmonitor
->rcWork
.left
)
518 rect
->right
+= pmonitor
->rcWork
.left
- rect
->left
;
519 rect
->left
= pmonitor
->rcWork
.left
;
521 else if (rect
->left
>= pmonitor
->rcWork
.right
)
523 rect
->left
+= pmonitor
->rcWork
.right
- rect
->right
;
524 rect
->right
= pmonitor
->rcWork
.right
;
526 if (rect
->bottom
<= pmonitor
->rcWork
.top
)
528 rect
->bottom
+= pmonitor
->rcWork
.top
- rect
->top
;
529 rect
->top
= pmonitor
->rcWork
.top
;
531 else if (rect
->top
>= pmonitor
->rcWork
.bottom
)
533 rect
->top
+= pmonitor
->rcWork
.bottom
- rect
->bottom
;
534 rect
->bottom
= pmonitor
->rcWork
.bottom
;
538 /* make sure the specified point is visible on screen */
539 static void make_point_onscreen( POINT
*pt
)
543 RECTL_vSetRect( &rect
, pt
->x
, pt
->y
, pt
->x
+ 1, pt
->y
+ 1 );
544 make_rect_onscreen( &rect
);
550 IntSetWindowPlacement(PWND Wnd
, WINDOWPLACEMENT
*wpl
, UINT Flags
)
555 if ( Flags
& PLACE_MIN
) make_point_onscreen( &wpl
->ptMinPosition
);
556 if ( Flags
& PLACE_MAX
) make_point_onscreen( &wpl
->ptMaxPosition
);
557 if ( Flags
& PLACE_RECT
) make_rect_onscreen( &wpl
->rcNormalPosition
);
559 if (!Wnd
|| Wnd
== Wnd
->head
.rpdesk
->pDeskInfo
->spwnd
) return FALSE
;
561 if ( Flags
& PLACE_MIN
) Wnd
->InternalPos
.IconPos
= wpl
->ptMinPosition
;
562 if ( Flags
& PLACE_MAX
) Wnd
->InternalPos
.MaxPos
= wpl
->ptMaxPosition
;
563 if ( Flags
& PLACE_RECT
) Wnd
->InternalPos
.NormalRect
= wpl
->rcNormalPosition
;
565 SWP_Flags
= SWP_NOZORDER
| SWP_NOACTIVATE
| ((wpl
->flags
& WPF_ASYNCWINDOWPLACEMENT
) ? SWP_ASYNCWINDOWPOS
: 0);
567 if (Wnd
->style
& WS_MINIMIZE
)
569 if (Flags
& PLACE_MIN
|| Wnd
->InternalPos
.flags
& WPF_SETMINPOSITION
)
571 co_WinPosSetWindowPos(Wnd
, HWND_TOP
,
572 wpl
->ptMinPosition
.x
, wpl
->ptMinPosition
.y
, 0, 0,
573 SWP_NOSIZE
| SWP_Flags
);
574 Wnd
->InternalPos
.flags
|= WPF_MININIT
;
577 else if (Wnd
->style
& WS_MAXIMIZE
)
579 if (Flags
& PLACE_MAX
)
581 co_WinPosSetWindowPos(Wnd
, HWND_TOP
,
582 wpl
->ptMaxPosition
.x
, wpl
->ptMaxPosition
.y
, 0, 0,
583 SWP_NOSIZE
| SWP_Flags
);
584 Wnd
->InternalPos
.flags
|= WPF_MAXINIT
;
587 else if (Flags
& PLACE_RECT
)
589 co_WinPosSetWindowPos(Wnd
, HWND_TOP
,
590 wpl
->rcNormalPosition
.left
, wpl
->rcNormalPosition
.top
,
591 wpl
->rcNormalPosition
.right
- wpl
->rcNormalPosition
.left
,
592 wpl
->rcNormalPosition
.bottom
- wpl
->rcNormalPosition
.top
,
596 sAsync
= (Wnd
->head
.pti
->MessageQueue
!= gptiCurrent
->MessageQueue
&& wpl
->flags
& WPF_ASYNCWINDOWPLACEMENT
);
599 co_IntSendMessageNoWait( UserHMGetHandle(Wnd
), WM_ASYNC_SHOWWINDOW
, wpl
->showCmd
, 0 );
601 co_WinPosShowWindow(Wnd
, wpl
->showCmd
);
603 if ( Wnd
->style
& WS_MINIMIZE
&& !sAsync
)
605 if ( wpl
->flags
& WPF_SETMINPOSITION
)
606 Wnd
->InternalPos
.flags
|= WPF_SETMINPOSITION
;
608 if ( wpl
->flags
& WPF_RESTORETOMAXIMIZED
)
609 Wnd
->InternalPos
.flags
|= WPF_RESTORETOMAXIMIZED
;
616 co_WinPosArrangeIconicWindows(PWND parent
)
620 INT x
, y
, xspacing
, yspacing
, sx
, sy
;
622 ASSERT_REFS_CO(parent
);
624 IntGetClientRect( parent
, &rectParent
);
625 // FIXME: Support Minimize Metrics gspv.mm.iArrange.
626 // Default: ARW_BOTTOMLEFT
628 y
= rectParent
.bottom
;
630 xspacing
= UserGetSystemMetrics(SM_CXMINIMIZED
);
631 yspacing
= UserGetSystemMetrics(SM_CYMINIMIZED
);
633 Child
= parent
->spwndChild
;
636 if((Child
->style
& WS_MINIMIZE
) != 0 )
638 USER_REFERENCE_ENTRY Ref
;
639 UserRefObjectCo(Child
, &Ref
);
641 sx
= x
+ UserGetSystemMetrics(SM_CXBORDER
);
642 sy
= y
- yspacing
- UserGetSystemMetrics(SM_CYBORDER
);
644 Child
->InternalPos
.IconPos
.x
= sx
;
645 Child
->InternalPos
.IconPos
.y
= sy
;
646 Child
->InternalPos
.flags
|= WPF_MININIT
;
648 co_WinPosSetWindowPos( Child
, 0, sx
, sy
, xspacing
, yspacing
, SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOCOPYBITS
| SWP_ASYNCWINDOWPOS
);
650 UserDerefObjectCo(Child
);
652 if (x
<= rectParent
.right
- xspacing
)
660 Child
= Child
->spwndNext
;
666 WinPosFindIconPos(PWND Window
, POINT
*Pos
)
669 PWND pwndChild
, pwndParent
;
670 int x
, y
, xspacing
, yspacing
;
672 pwndParent
= Window
->spwndParent
;
673 if (pwndParent
== UserGetDesktopWindow())
675 //ERR("Parent is Desktop, Min off screen!\n");
676 /* ReactOS doesn't support iconic minimize to desktop */
677 Pos
->x
= Pos
->y
= -32000;
678 Window
->InternalPos
.flags
|= WPF_MININIT
;
679 Window
->InternalPos
.IconPos
.x
= Pos
->x
;
680 Window
->InternalPos
.IconPos
.y
= Pos
->y
;
684 IntGetClientRect( pwndParent
, &rectParent
);
685 // FIXME: Support Minimize Metrics gspv.mm.iArrange.
686 // Default: ARW_BOTTOMLEFT
688 y
= rectParent
.bottom
;
690 xspacing
= UserGetSystemMetrics(SM_CXMINIMIZED
);
691 yspacing
= UserGetSystemMetrics(SM_CYMINIMIZED
);
693 // Set to default position when minimized.
694 Pos
->x
= x
+ UserGetSystemMetrics(SM_CXBORDER
);
695 Pos
->y
= y
- yspacing
- UserGetSystemMetrics(SM_CYBORDER
);
697 for (pwndChild
= pwndParent
->spwndChild
; pwndChild
; pwndChild
= pwndChild
->spwndNext
)
699 if (pwndChild
== Window
) continue;
701 if ((pwndChild
->style
& (WS_VISIBLE
|WS_MINIMIZE
)) != (WS_VISIBLE
|WS_MINIMIZE
) )
706 if ( pwndChild
->InternalPos
.IconPos
.x
!= Pos
->x
&& pwndChild
->InternalPos
.IconPos
.y
!= Pos
->y
)
710 if (x
<= rectParent
.right
- xspacing
)
717 Pos
->x
= x
+ UserGetSystemMetrics(SM_CXBORDER
);
718 Pos
->y
= y
- yspacing
- UserGetSystemMetrics(SM_CYBORDER
);
721 Window
->InternalPos
.IconPos
.x
= Pos
->x
;
722 Window
->InternalPos
.IconPos
.y
= Pos
->y
;
723 Window
->InternalPos
.flags
|= WPF_MININIT
;
724 TRACE("Position is set! X:%d Y:%d\n",Pos
->x
,Pos
->y
);
729 co_WinPosMinMaximize(PWND Wnd
, UINT ShowFlag
, RECT
* NewPos
)
738 wpl
.length
= sizeof(wpl
);
739 IntGetWindowPlacement( Wnd
, &wpl
);
741 if (co_HOOK_CallHooks( WH_CBT
, HCBT_MINMAX
, (WPARAM
)Wnd
->head
.h
, ShowFlag
))
743 ERR("WinPosMinMaximize WH_CBT Call Hook return!\n");
744 return SWP_NOSIZE
| SWP_NOMOVE
;
746 if (Wnd
->style
& WS_MINIMIZE
)
750 case SW_SHOWMINNOACTIVE
:
751 case SW_SHOWMINIMIZED
:
752 case SW_FORCEMINIMIZE
:
754 return SWP_NOSIZE
| SWP_NOMOVE
;
756 if (!co_IntSendMessageNoWait(Wnd
->head
.h
, WM_QUERYOPEN
, 0, 0))
758 return(SWP_NOSIZE
| SWP_NOMOVE
);
760 SwpFlags
|= SWP_NOCOPYBITS
;
764 case SW_SHOWMINNOACTIVE
:
765 case SW_SHOWMINIMIZED
:
766 case SW_FORCEMINIMIZE
:
769 //ERR("MinMaximize Minimize\n");
770 if (Wnd
->style
& WS_MAXIMIZE
)
772 Wnd
->InternalPos
.flags
|= WPF_RESTORETOMAXIMIZED
;
776 Wnd
->InternalPos
.flags
&= ~WPF_RESTORETOMAXIMIZED
;
779 old_style
= IntSetStyle( Wnd
, WS_MINIMIZE
, WS_MAXIMIZE
);
781 co_UserRedrawWindow(Wnd
, NULL
, 0, RDW_VALIDATE
| RDW_NOERASE
| RDW_NOINTERNALPAINT
);
783 if (!(Wnd
->InternalPos
.flags
& WPF_SETMINPOSITION
))
784 Wnd
->InternalPos
.flags
&= ~WPF_MININIT
;
786 WinPosFindIconPos(Wnd
, &wpl
.ptMinPosition
);
788 if (!(old_style
& WS_MINIMIZE
)) SwpFlags
|= SWP_STATECHANGED
;
790 RECTL_vSetRect(NewPos
, wpl
.ptMinPosition
.x
, wpl
.ptMinPosition
.y
,
791 wpl
.ptMinPosition
.x
+ UserGetSystemMetrics(SM_CXMINIMIZED
),
792 wpl
.ptMinPosition
.y
+ UserGetSystemMetrics(SM_CYMINIMIZED
));
793 SwpFlags
|= SWP_NOCOPYBITS
;
799 //ERR("MinMaximize Maximize\n");
800 if ((Wnd
->style
& WS_MAXIMIZE
) && (Wnd
->style
& WS_VISIBLE
))
802 SwpFlags
= SWP_NOSIZE
| SWP_NOMOVE
;
805 co_WinPosGetMinMaxInfo(Wnd
, &Size
, &wpl
.ptMaxPosition
, NULL
, NULL
);
807 /*ERR("Maximize: %d,%d %dx%d\n",
808 wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, Size.x, Size.y);
810 old_style
= IntSetStyle( Wnd
, WS_MAXIMIZE
, WS_MINIMIZE
);
812 if (!(old_style
& WS_MAXIMIZE
)) SwpFlags
|= SWP_STATECHANGED
;
813 RECTL_vSetRect(NewPos
, wpl
.ptMaxPosition
.x
, wpl
.ptMaxPosition
.y
,
814 //wpl.ptMaxPosition.x + Size.x, wpl.ptMaxPosition.y + Size.y);
819 case SW_SHOWNOACTIVATE
:
820 Wnd
->InternalPos
.flags
&= ~WPF_RESTORETOMAXIMIZED
;
824 case SW_SHOWDEFAULT
: /* FIXME: should have its own handler */
826 //ERR("MinMaximize Restore\n");
827 old_style
= IntSetStyle( Wnd
, 0, WS_MINIMIZE
| WS_MAXIMIZE
);
828 if (old_style
& WS_MINIMIZE
)
830 if (Wnd
->InternalPos
.flags
& WPF_RESTORETOMAXIMIZED
)
832 co_WinPosGetMinMaxInfo(Wnd
, &Size
, &wpl
.ptMaxPosition
, NULL
, NULL
);
833 IntSetStyle( Wnd
, WS_MAXIMIZE
, 0 );
834 SwpFlags
|= SWP_STATECHANGED
;
835 RECTL_vSetRect(NewPos
, wpl
.ptMaxPosition
.x
, wpl
.ptMaxPosition
.y
,
836 wpl
.ptMaxPosition
.x
+ Size
.x
, wpl
.ptMaxPosition
.y
+ Size
.y
);
841 *NewPos
= wpl
.rcNormalPosition
;
842 NewPos
->right
-= NewPos
->left
;
843 NewPos
->bottom
-= NewPos
->top
;
849 if (!(old_style
& WS_MAXIMIZE
))
853 SwpFlags
|= SWP_STATECHANGED
;
854 Wnd
->InternalPos
.flags
&= ~WPF_RESTORETOMAXIMIZED
;
855 *NewPos
= wpl
.rcNormalPosition
;
856 NewPos
->right
-= NewPos
->left
;
857 NewPos
->bottom
-= NewPos
->top
;
866 UserHasWindowEdge(DWORD Style
, DWORD ExStyle
)
868 if (Style
& WS_MINIMIZE
)
870 if (ExStyle
& WS_EX_DLGMODALFRAME
)
872 if (ExStyle
& WS_EX_STATICEDGE
)
874 if (Style
& WS_THICKFRAME
)
877 if (Style
== WS_DLGFRAME
|| Style
== WS_CAPTION
)
883 IntGetWindowBorderMeasures(PWND Wnd
, UINT
*cx
, UINT
*cy
)
885 if(HAS_DLGFRAME(Wnd
->style
, Wnd
->ExStyle
) && !(Wnd
->style
& WS_MINIMIZE
))
887 *cx
= UserGetSystemMetrics(SM_CXDLGFRAME
);
888 *cy
= UserGetSystemMetrics(SM_CYDLGFRAME
);
892 if(HAS_THICKFRAME(Wnd
->style
, Wnd
->ExStyle
)&& !(Wnd
->style
& WS_MINIMIZE
))
894 *cx
= UserGetSystemMetrics(SM_CXFRAME
);
895 *cy
= UserGetSystemMetrics(SM_CYFRAME
);
897 else if(HAS_THINFRAME(Wnd
->style
, Wnd
->ExStyle
))
899 *cx
= UserGetSystemMetrics(SM_CXBORDER
);
900 *cy
= UserGetSystemMetrics(SM_CYBORDER
);
910 UserGetWindowBorders(DWORD Style
, DWORD ExStyle
, SIZE
*Size
, BOOL WithClient
)
914 if (UserHasWindowEdge(Style
, ExStyle
))
916 else if (ExStyle
& WS_EX_STATICEDGE
)
918 if ((ExStyle
& WS_EX_CLIENTEDGE
) && WithClient
)
920 if (Style
& WS_CAPTION
|| ExStyle
& WS_EX_DLGMODALFRAME
)
922 Size
->cx
= Size
->cy
= Border
;
923 if ((Style
& WS_THICKFRAME
) && !(Style
& WS_MINIMIZE
))
925 Size
->cx
+= UserGetSystemMetrics(SM_CXFRAME
) - UserGetSystemMetrics(SM_CXDLGFRAME
);
926 Size
->cy
+= UserGetSystemMetrics(SM_CYFRAME
) - UserGetSystemMetrics(SM_CYDLGFRAME
);
928 Size
->cx
*= UserGetSystemMetrics(SM_CXBORDER
);
929 Size
->cy
*= UserGetSystemMetrics(SM_CYBORDER
);
933 UserAdjustWindowRectEx(LPRECT lpRect
,
942 lpRect
->top
-= UserGetSystemMetrics(SM_CYMENU
);
944 if ((dwStyle
& WS_CAPTION
) == WS_CAPTION
)
946 if (dwExStyle
& WS_EX_TOOLWINDOW
)
947 lpRect
->top
-= UserGetSystemMetrics(SM_CYSMCAPTION
);
949 lpRect
->top
-= UserGetSystemMetrics(SM_CYCAPTION
);
951 UserGetWindowBorders(dwStyle
, dwExStyle
, &BorderSize
, TRUE
);
961 co_WinPosGetMinMaxInfo(PWND Window
, POINT
* MaxSize
, POINT
* MaxPos
,
962 POINT
* MinTrack
, POINT
* MaxTrack
)
967 LONG style
= Window
->style
;
969 LONG exstyle
= Window
->ExStyle
;
972 ASSERT_REFS_CO(Window
);
974 /* Compute default values */
976 rc
= Window
->rcWindow
;
977 MinMax
.ptReserved
.x
= rc
.left
;
978 MinMax
.ptReserved
.y
= rc
.top
;
980 if ((style
& WS_CAPTION
) == WS_CAPTION
)
981 adjustedStyle
= style
& ~WS_BORDER
; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
983 adjustedStyle
= style
;
985 if(Window
->spwndParent
)
986 IntGetClientRect(Window
->spwndParent
, &rc
);
987 UserAdjustWindowRectEx(&rc
, adjustedStyle
, ((style
& WS_POPUP
) && Window
->IDMenu
), exstyle
);
992 MinMax
.ptMaxSize
.x
= rc
.right
- rc
.left
;
993 MinMax
.ptMaxSize
.y
= rc
.bottom
- rc
.top
;
994 if (style
& (WS_DLGFRAME
| WS_BORDER
))
996 MinMax
.ptMinTrackSize
.x
= UserGetSystemMetrics(SM_CXMINTRACK
);
997 MinMax
.ptMinTrackSize
.y
= UserGetSystemMetrics(SM_CYMINTRACK
);
1001 MinMax
.ptMinTrackSize
.x
= 2 * xinc
;
1002 MinMax
.ptMinTrackSize
.y
= 2 * yinc
;
1004 MinMax
.ptMaxTrackSize
.x
= UserGetSystemMetrics(SM_CXMAXTRACK
);
1005 MinMax
.ptMaxTrackSize
.y
= UserGetSystemMetrics(SM_CYMAXTRACK
);
1006 MinMax
.ptMaxPosition
.x
= -xinc
;
1007 MinMax
.ptMaxPosition
.y
= -yinc
;
1009 if (!EMPTYPOINT(Window
->InternalPos
.MaxPos
)) MinMax
.ptMaxPosition
= Window
->InternalPos
.MaxPos
;
1011 co_IntSendMessage(Window
->head
.h
, WM_GETMINMAXINFO
, 0, (LPARAM
)&MinMax
);
1013 /* if the app didn't change the values, adapt them for the current monitor */
1014 if ((monitor
= UserGetPrimaryMonitor()))
1018 rc_work
= monitor
->rcMonitor
;
1020 if (style
& WS_MAXIMIZEBOX
)
1022 if ((style
& WS_CAPTION
) == WS_CAPTION
|| !(style
& (WS_CHILD
| WS_POPUP
)))
1023 rc_work
= monitor
->rcWork
;
1026 if (MinMax
.ptMaxSize
.x
== UserGetSystemMetrics(SM_CXSCREEN
) + 2 * xinc
&&
1027 MinMax
.ptMaxSize
.y
== UserGetSystemMetrics(SM_CYSCREEN
) + 2 * yinc
)
1029 MinMax
.ptMaxSize
.x
= (rc_work
.right
- rc_work
.left
) + 2 * xinc
;
1030 MinMax
.ptMaxSize
.y
= (rc_work
.bottom
- rc_work
.top
) + 2 * yinc
;
1032 if (MinMax
.ptMaxPosition
.x
== -xinc
&& MinMax
.ptMaxPosition
.y
== -yinc
)
1034 MinMax
.ptMaxPosition
.x
= rc_work
.left
- xinc
;
1035 MinMax
.ptMaxPosition
.y
= rc_work
.top
- yinc
;
1037 if (MinMax
.ptMaxSize
.x
>= (monitor
->rcMonitor
.right
- monitor
->rcMonitor
.left
) &&
1038 MinMax
.ptMaxSize
.y
>= (monitor
->rcMonitor
.bottom
- monitor
->rcMonitor
.top
) )
1039 Window
->state
|= WNDS_MAXIMIZESTOMONITOR
;
1041 Window
->state
&= ~WNDS_MAXIMIZESTOMONITOR
;
1045 MinMax
.ptMaxTrackSize
.x
= max(MinMax
.ptMaxTrackSize
.x
,
1046 MinMax
.ptMinTrackSize
.x
);
1047 MinMax
.ptMaxTrackSize
.y
= max(MinMax
.ptMaxTrackSize
.y
,
1048 MinMax
.ptMinTrackSize
.y
);
1051 *MaxSize
= MinMax
.ptMaxSize
;
1053 *MaxPos
= MinMax
.ptMaxPosition
;
1055 *MinTrack
= MinMax
.ptMinTrackSize
;
1057 *MaxTrack
= MinMax
.ptMaxTrackSize
;
1059 return 0; // FIXME: What does it return?
1064 FixClientRect(PRECTL ClientRect
, PRECTL WindowRect
)
1066 if (ClientRect
->left
< WindowRect
->left
)
1068 ClientRect
->left
= WindowRect
->left
;
1070 else if (WindowRect
->right
< ClientRect
->left
)
1072 ClientRect
->left
= WindowRect
->right
;
1074 if (ClientRect
->right
< WindowRect
->left
)
1076 ClientRect
->right
= WindowRect
->left
;
1078 else if (WindowRect
->right
< ClientRect
->right
)
1080 ClientRect
->right
= WindowRect
->right
;
1082 if (ClientRect
->top
< WindowRect
->top
)
1084 ClientRect
->top
= WindowRect
->top
;
1086 else if (WindowRect
->bottom
< ClientRect
->top
)
1088 ClientRect
->top
= WindowRect
->bottom
;
1090 if (ClientRect
->bottom
< WindowRect
->top
)
1092 ClientRect
->bottom
= WindowRect
->top
;
1094 else if (WindowRect
->bottom
< ClientRect
->bottom
)
1096 ClientRect
->bottom
= WindowRect
->bottom
;
1099 /***********************************************************************
1102 * Compute the valid rects from the old and new client rect and WVR_* flags.
1103 * Helper for WM_NCCALCSIZE handling.
1107 get_valid_rects( RECTL
*old_client
, RECTL
*new_client
, UINT flags
, RECTL
*valid
)
1111 if (flags
& WVR_REDRAW
)
1113 RECTL_vSetEmptyRect( &valid
[0] );
1114 RECTL_vSetEmptyRect( &valid
[1] );
1118 if (flags
& WVR_VALIDRECTS
)
1120 if (!RECTL_bIntersectRect( &valid
[0], &valid
[0], new_client
) ||
1121 !RECTL_bIntersectRect( &valid
[1], &valid
[1], old_client
))
1123 RECTL_vSetEmptyRect( &valid
[0] );
1124 RECTL_vSetEmptyRect( &valid
[1] );
1127 flags
= WVR_ALIGNLEFT
| WVR_ALIGNTOP
;
1131 valid
[0] = *new_client
;
1132 valid
[1] = *old_client
;
1135 /* make sure the rectangles have the same size */
1136 cx
= min( valid
[0].right
- valid
[0].left
, valid
[1].right
- valid
[1].left
);
1137 cy
= min( valid
[0].bottom
- valid
[0].top
, valid
[1].bottom
- valid
[1].top
);
1139 if (flags
& WVR_ALIGNBOTTOM
)
1141 valid
[0].top
= valid
[0].bottom
- cy
;
1142 valid
[1].top
= valid
[1].bottom
- cy
;
1146 valid
[0].bottom
= valid
[0].top
+ cy
;
1147 valid
[1].bottom
= valid
[1].top
+ cy
;
1149 if (flags
& WVR_ALIGNRIGHT
)
1151 valid
[0].left
= valid
[0].right
- cx
;
1152 valid
[1].left
= valid
[1].right
- cx
;
1156 valid
[0].right
= valid
[0].left
+ cx
;
1157 valid
[1].right
= valid
[1].left
+ cx
;
1163 co_WinPosDoNCCALCSize(PWND Window
, PWINDOWPOS WinPos
, RECTL
* WindowRect
, RECTL
* ClientRect
, RECTL
* validRects
)
1168 ASSERT_REFS_CO(Window
);
1170 /* Send WM_NCCALCSIZE message to get new client area */
1171 if ((WinPos
->flags
& (SWP_FRAMECHANGED
| SWP_NOSIZE
)) != SWP_NOSIZE
)
1173 NCCALCSIZE_PARAMS params
;
1174 WINDOWPOS winposCopy
;
1176 params
.rgrc
[0] = *WindowRect
; // new coordinates of a window that has been moved or resized
1177 params
.rgrc
[1] = Window
->rcWindow
; // window before it was moved or resized
1178 params
.rgrc
[2] = Window
->rcClient
; // client area before the window was moved or resized
1180 Parent
= Window
->spwndParent
;
1181 if (0 != (Window
->style
& WS_CHILD
) && Parent
)
1183 RECTL_vOffsetRect(&(params
.rgrc
[0]), - Parent
->rcClient
.left
, - Parent
->rcClient
.top
);
1184 RECTL_vOffsetRect(&(params
.rgrc
[1]), - Parent
->rcClient
.left
, - Parent
->rcClient
.top
);
1185 RECTL_vOffsetRect(&(params
.rgrc
[2]), - Parent
->rcClient
.left
, - Parent
->rcClient
.top
);
1188 params
.lppos
= &winposCopy
;
1189 winposCopy
= *WinPos
;
1191 wvrFlags
= co_IntSendMessage(Window
->head
.h
, WM_NCCALCSIZE
, TRUE
, (LPARAM
) ¶ms
);
1193 /* If the application send back garbage, ignore it */
1194 if (params
.rgrc
[0].left
<= params
.rgrc
[0].right
&&
1195 params
.rgrc
[0].top
<= params
.rgrc
[0].bottom
)
1197 *ClientRect
= params
.rgrc
[0]; // First rectangle contains the coordinates of the new client rectangle resulting from the move or resize
1198 if ((Window
->style
& WS_CHILD
) && Parent
)
1200 RECTL_vOffsetRect(ClientRect
, Parent
->rcClient
.left
, Parent
->rcClient
.top
);
1202 FixClientRect(ClientRect
, WindowRect
);
1205 if (ClientRect
->left
!= Window
->rcClient
.left
||
1206 ClientRect
->top
!= Window
->rcClient
.top
)
1208 WinPos
->flags
&= ~SWP_NOCLIENTMOVE
;
1211 if (ClientRect
->right
- ClientRect
->left
!= Window
->rcClient
.right
- Window
->rcClient
.left
)
1213 WinPos
->flags
&= ~SWP_NOCLIENTSIZE
;
1216 wvrFlags
&= ~WVR_HREDRAW
;
1218 if (ClientRect
->bottom
- ClientRect
->top
!= Window
->rcClient
.bottom
- Window
->rcClient
.top
)
1220 WinPos
->flags
&= ~SWP_NOCLIENTSIZE
;
1223 wvrFlags
&= ~WVR_VREDRAW
;
1225 validRects
[0] = params
.rgrc
[1]; // second rectangle contains the valid destination rectangle
1226 validRects
[1] = params
.rgrc
[2]; // third rectangle contains the valid source rectangle
1230 if (!(WinPos
->flags
& SWP_NOMOVE
) &&
1231 (ClientRect
->left
!= Window
->rcClient
.left
||
1232 ClientRect
->top
!= Window
->rcClient
.top
))
1234 WinPos
->flags
&= ~SWP_NOCLIENTMOVE
;
1238 if (WinPos
->flags
& (SWP_NOCOPYBITS
| SWP_NOREDRAW
| SWP_SHOWWINDOW
| SWP_HIDEWINDOW
))
1240 RECTL_vSetEmptyRect( &validRects
[0] );
1241 RECTL_vSetEmptyRect( &validRects
[1] );
1243 else get_valid_rects( &Window
->rcClient
, ClientRect
, wvrFlags
, validRects
);
1250 co_WinPosDoWinPosChanging(PWND Window
,
1255 ASSERT_REFS_CO(Window
);
1257 /* Send WM_WINDOWPOSCHANGING message */
1259 if (!(WinPos
->flags
& SWP_NOSENDCHANGING
))
1261 co_IntSendMessageNoWait(Window
->head
.h
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
) WinPos
);
1264 /* Calculate new position and size */
1266 *WindowRect
= Window
->rcWindow
;
1267 *ClientRect
= (Window
->style
& WS_MINIMIZE
) ? Window
->rcWindow
: Window
->rcClient
;
1269 if (!(WinPos
->flags
& SWP_NOSIZE
))
1271 if (Window
->style
& WS_MINIMIZE
)
1273 WindowRect
->right
= WindowRect
->left
+ UserGetSystemMetrics(SM_CXMINIMIZED
);
1274 WindowRect
->bottom
= WindowRect
->top
+ UserGetSystemMetrics(SM_CYMINIMIZED
);
1278 WindowRect
->right
= WindowRect
->left
+ WinPos
->cx
;
1279 WindowRect
->bottom
= WindowRect
->top
+ WinPos
->cy
;
1283 if (!(WinPos
->flags
& SWP_NOMOVE
))
1290 Parent
= Window
->spwndParent
;
1292 if (((Window
->style
& WS_CHILD
) != 0) &&
1294 Parent
!= Window
->head
.rpdesk
->pDeskInfo
->spwnd
)
1296 TRACE("Not SWP_NOMOVE 1 Parent client offset X %d Y %d\n",X
,Y
);
1297 X
+= Parent
->rcClient
.left
;
1298 Y
+= Parent
->rcClient
.top
;
1299 TRACE("Not SWP_NOMOVE 2 Parent client offset X %d Y %d\n",X
,Y
);
1302 WindowRect
->left
= X
;
1303 WindowRect
->top
= Y
;
1304 WindowRect
->right
+= X
- Window
->rcWindow
.left
;
1305 WindowRect
->bottom
+= Y
- Window
->rcWindow
.top
;
1307 RECTL_vOffsetRect(ClientRect
, X
- Window
->rcWindow
.left
,
1308 Y
- Window
->rcWindow
.top
);
1310 WinPos
->flags
|= SWP_NOCLIENTMOVE
| SWP_NOCLIENTSIZE
;
1312 TRACE( "hwnd %p, after %p, swp %d,%d %dx%d flags %08x\n",
1313 WinPos
->hwnd
, WinPos
->hwndInsertAfter
, WinPos
->x
, WinPos
->y
,
1314 WinPos
->cx
, WinPos
->cy
, WinPos
->flags
);
1315 TRACE("WindowRect: %d %d %d %d\n", WindowRect
->left
,WindowRect
->top
,WindowRect
->right
,WindowRect
->bottom
);
1316 TRACE("ClientRect: %d %d %d %d\n", ClientRect
->left
,ClientRect
->top
,ClientRect
->right
,ClientRect
->bottom
);
1322 * Fix Z order taking into account owned popups -
1323 * basically we need to maintain them above the window that owns them
1325 * FIXME: hide/show owned popups when owner visibility changes.
1327 * ReactOS: See bug CORE-6129 and CORE-6554.
1331 // Pass all the win:test_children/popup_zorder tests except "move hwnd_F and its popups down" which is if'ed out.
1332 // Side effect, breaks more of the DeferWindowPos api tests, but wine breaks more!!!!
1335 WinPosDoOwnedPopups(PWND Window
, HWND hWndInsertAfter
)
1340 PWND DesktopWindow
, ChildObject
;
1343 TRACE("(%p) hInsertAfter = %p\n", Window
, hWndInsertAfter
);
1345 Owner
= Window
->spwndOwner
? Window
->spwndOwner
->head
.h
: NULL
;
1346 Style
= Window
->style
;
1348 if (Style
& WS_CHILD
)
1350 TRACE("Window is child\n");
1351 return hWndInsertAfter
;
1356 /* Make sure this popup stays above the owner */
1358 if (hWndInsertAfter
!= HWND_TOPMOST
)
1360 DesktopWindow
= UserGetDesktopWindow();
1361 List
= IntWinListChildren(DesktopWindow
);
1365 for (i
= 0; List
[i
]; i
++)
1367 BOOL topmost
= FALSE
;
1369 ChildObject
= ValidateHwndNoErr(List
[i
]);
1372 topmost
= (ChildObject
->ExStyle
& WS_EX_TOPMOST
) != 0;
1375 if (List
[i
] == Owner
)
1377 if (i
> 0) hWndInsertAfter
= List
[i
-1];
1378 else hWndInsertAfter
= topmost
? HWND_TOPMOST
: HWND_TOP
;
1382 if (hWndInsertAfter
== HWND_TOP
|| hWndInsertAfter
== HWND_NOTOPMOST
)
1384 if (!topmost
) break;
1386 else if (List
[i
] == hWndInsertAfter
) break;
1390 return hWndInsertAfter
;
1394 if (hWndInsertAfter
== HWND_BOTTOM
)
1396 ERR("Window is HWND_BOTTOM\n");
1397 if (List
) ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1403 DesktopWindow
= UserGetDesktopWindow();
1404 List
= IntWinListChildren(DesktopWindow
);
1411 if (hWndInsertAfter
== HWND_TOP
|| hWndInsertAfter
== HWND_NOTOPMOST
)
1413 if (hWndInsertAfter
== HWND_NOTOPMOST
|| !(Window
->ExStyle
& WS_EX_TOPMOST
))
1415 TRACE("skip all the topmost windows\n");
1416 /* skip all the topmost windows */
1418 (ChildObject
= ValidateHwndNoErr(List
[i
])) &&
1419 (ChildObject
->ExStyle
& WS_EX_TOPMOST
)) i
++;
1422 else if (hWndInsertAfter
!= HWND_TOPMOST
)
1424 /* skip windows that are already placed correctly */
1425 for (i
= 0; List
[i
]; i
++)
1427 if (List
[i
] == hWndInsertAfter
) break;
1428 if (List
[i
] == UserHMGetHandle(Window
))
1430 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1431 goto done
; /* nothing to do if window is moving backwards in z-order */
1436 for (; List
[i
]; i
++)
1439 USER_REFERENCE_ENTRY Ref
;
1441 if (List
[i
] == UserHMGetHandle(Window
))
1444 if (!(Wnd
= ValidateHwndNoErr(List
[i
])))
1447 Owner
= Wnd
->spwndOwner
? Wnd
->spwndOwner
->head
.h
: NULL
;
1449 if (Owner
!= UserHMGetHandle(Window
)) continue;
1451 UserRefObjectCo(Wnd
, &Ref
);
1452 TRACE( "moving %p owned by %p after %p\n", List
[i
], UserHMGetHandle(Window
), hWndInsertAfter
);
1453 co_WinPosSetWindowPos(Wnd
, hWndInsertAfter
, 0, 0, 0, 0,
1454 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOSENDCHANGING
| SWP_DEFERERASE
);
1456 UserDerefObjectCo(Wnd
);
1457 hWndInsertAfter
= List
[i
];
1459 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1462 return hWndInsertAfter
;
1466 /***********************************************************************
1467 * WinPosInternalMoveWindow
1469 * Update WindowRect and ClientRect of Window and all of its children
1470 * We keep both WindowRect and ClientRect in screen coordinates internally
1474 WinPosInternalMoveWindow(PWND Window
, INT MoveX
, INT MoveY
)
1478 ASSERT(Window
!= Window
->spwndChild
);
1479 TRACE("InternalMoveWin X %d Y %d\n", MoveX
, MoveY
);
1481 Window
->rcWindow
.left
+= MoveX
;
1482 Window
->rcWindow
.right
+= MoveX
;
1483 Window
->rcWindow
.top
+= MoveY
;
1484 Window
->rcWindow
.bottom
+= MoveY
;
1486 Window
->rcClient
.left
+= MoveX
;
1487 Window
->rcClient
.right
+= MoveX
;
1488 Window
->rcClient
.top
+= MoveY
;
1489 Window
->rcClient
.bottom
+= MoveY
;
1491 for(Child
= Window
->spwndChild
; Child
; Child
= Child
->spwndNext
)
1493 WinPosInternalMoveWindow(Child
, MoveX
, MoveY
);
1498 * WinPosFixupSWPFlags
1500 * Fix redundant flags and values in the WINDOWPOS structure.
1504 WinPosFixupFlags(WINDOWPOS
*WinPos
, PWND Wnd
)
1509 /* Finally make sure that all coordinates are valid */
1510 if (WinPos
->x
< -32768) WinPos
->x
= -32768;
1511 else if (WinPos
->x
> 32767) WinPos
->x
= 32767;
1512 if (WinPos
->y
< -32768) WinPos
->y
= -32768;
1513 else if (WinPos
->y
> 32767) WinPos
->y
= 32767;
1515 WinPos
->cx
= max(WinPos
->cx
, 0);
1516 WinPos
->cy
= max(WinPos
->cy
, 0);
1518 Parent
= UserGetAncestor( Wnd
, GA_PARENT
);
1519 if (!IntIsWindowVisible( Parent
)) WinPos
->flags
|= SWP_NOREDRAW
;
1521 if (Wnd
->style
& WS_VISIBLE
) WinPos
->flags
&= ~SWP_SHOWWINDOW
;
1524 WinPos
->flags
&= ~SWP_HIDEWINDOW
;
1525 if (!(WinPos
->flags
& SWP_SHOWWINDOW
)) WinPos
->flags
|= SWP_NOREDRAW
;
1528 /* Check for right size */
1529 if (Wnd
->rcWindow
.right
- Wnd
->rcWindow
.left
== WinPos
->cx
&&
1530 Wnd
->rcWindow
.bottom
- Wnd
->rcWindow
.top
== WinPos
->cy
)
1532 WinPos
->flags
|= SWP_NOSIZE
;
1537 IntClientToScreen( Parent
, &pt
);
1538 TRACE("WPFU C2S wpx %d wpy %d ptx %d pty %d\n",WinPos
->x
,WinPos
->y
,pt
.x
,pt
.y
);
1539 /* Check for right position */
1540 if (Wnd
->rcWindow
.left
== pt
.x
&& Wnd
->rcWindow
.top
== pt
.y
)
1542 //ERR("In right pos\n");
1543 WinPos
->flags
|= SWP_NOMOVE
;
1546 if (WinPos
->hwnd
== UserGetForegroundWindow())
1548 WinPos
->flags
|= SWP_NOACTIVATE
; /* Already active */
1551 if ((Wnd
->style
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)
1553 /* Bring to the top when activating */
1554 if (!(WinPos
->flags
& (SWP_NOACTIVATE
|SWP_HIDEWINDOW
)) &&
1555 (WinPos
->flags
& SWP_NOZORDER
||
1556 (WinPos
->hwndInsertAfter
!= HWND_TOPMOST
&& WinPos
->hwndInsertAfter
!= HWND_NOTOPMOST
)))
1558 WinPos
->flags
&= ~SWP_NOZORDER
;
1559 WinPos
->hwndInsertAfter
= (0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
) ? HWND_TOPMOST
: HWND_TOP
);
1563 /* Check hwndInsertAfter */
1564 if (!(WinPos
->flags
& SWP_NOZORDER
))
1566 /* Fix sign extension */
1567 if (WinPos
->hwndInsertAfter
== (HWND
)0xffff)
1569 WinPos
->hwndInsertAfter
= HWND_TOPMOST
;
1571 else if (WinPos
->hwndInsertAfter
== (HWND
)0xfffe)
1573 WinPos
->hwndInsertAfter
= HWND_NOTOPMOST
;
1576 if (WinPos
->hwndInsertAfter
== HWND_TOP
)
1578 /* Keep it topmost when it's already topmost */
1579 if ((Wnd
->ExStyle
& WS_EX_TOPMOST
) != 0)
1580 WinPos
->hwndInsertAfter
= HWND_TOPMOST
;
1582 if (IntGetWindow(WinPos
->hwnd
, GW_HWNDFIRST
) == WinPos
->hwnd
)
1583 WinPos
->flags
|= SWP_NOZORDER
;
1585 else if (WinPos
->hwndInsertAfter
== HWND_BOTTOM
)
1587 if (!(Wnd
->ExStyle
& WS_EX_TOPMOST
) && IntGetWindow(WinPos
->hwnd
, GW_HWNDLAST
) == WinPos
->hwnd
)
1588 WinPos
->flags
|= SWP_NOZORDER
;
1590 else if (WinPos
->hwndInsertAfter
== HWND_TOPMOST
)
1592 if ((Wnd
->ExStyle
& WS_EX_TOPMOST
) && IntGetWindow(WinPos
->hwnd
, GW_HWNDFIRST
) == WinPos
->hwnd
)
1593 WinPos
->flags
|= SWP_NOZORDER
;
1595 else if (WinPos
->hwndInsertAfter
== HWND_NOTOPMOST
)
1597 if (!(Wnd
->ExStyle
& WS_EX_TOPMOST
))
1598 WinPos
->flags
|= SWP_NOZORDER
;
1600 else /* hwndInsertAfter must be a sibling of the window */
1604 InsAfterWnd
= ValidateHwndNoErr(WinPos
->hwndInsertAfter
);
1610 if (InsAfterWnd
->spwndParent
!= Wnd
->spwndParent
)
1612 /* Note from wine User32 Win test_SetWindowPos:
1613 "Returns TRUE also for windows that are not siblings"
1614 "Does not seem to do anything even without passing flags, still returns TRUE"
1615 "Same thing the other way around."
1616 ".. and with these windows."
1623 * We don't need to change the Z order of hwnd if it's already
1624 * inserted after hwndInsertAfter or when inserting hwnd after
1627 if ((WinPos
->hwnd
== WinPos
->hwndInsertAfter
) ||
1628 ((InsAfterWnd
->spwndNext
) && (WinPos
->hwnd
== InsAfterWnd
->spwndNext
->head
.h
)))
1630 WinPos
->flags
|= SWP_NOZORDER
;
1639 /* x and y are always screen relative */
1641 co_WinPosSetWindowPos(
1643 HWND WndInsertAfter
,
1652 RECTL NewWindowRect
;
1653 RECTL NewClientRect
;
1654 RECTL valid_rects
[2];
1655 PREGION VisBefore
= NULL
;
1656 PREGION VisBeforeJustClient
= NULL
;
1657 PREGION VisAfter
= NULL
;
1658 PREGION CopyRgn
= NULL
;
1660 RECTL OldWindowRect
, OldClientRect
;
1665 BOOL bPointerInWindow
;
1667 ASSERT_REFS_CO(Window
);
1669 /* FIXME: Get current active window from active queue. Why? since r2915. */
1671 bPointerInWindow
= IntPtInWindow(Window
, gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
);
1673 WinPos
.hwnd
= Window
->head
.h
;
1674 WinPos
.hwndInsertAfter
= WndInsertAfter
;
1679 WinPos
.flags
= flags
;
1681 if ( flags
& SWP_ASYNCWINDOWPOS
)
1684 PWINDOWPOS ppos
= ExAllocatePoolWithTag(PagedPool
, sizeof(WINDOWPOS
), USERTAG_SWP
);
1687 WinPos
.flags
&= ~SWP_ASYNCWINDOWPOS
; // Clear flag.
1689 /* Yes it's a pointer inside Win32k! */
1690 lRes
= co_IntSendMessageNoWait( WinPos
.hwnd
, WM_ASYNC_SETWINDOWPOS
, 0, (LPARAM
)ppos
);
1691 /* We handle this the same way as Event Hooks and Hooks. */
1694 ExFreePoolWithTag(ppos
, USERTAG_SWP
);
1702 co_WinPosDoWinPosChanging(Window
, &WinPos
, &NewWindowRect
, &NewClientRect
);
1704 /* Does the window still exist? */
1705 if (!IntIsWindow(WinPos
.hwnd
))
1707 TRACE("WinPosSetWindowPos: Invalid handle 0x%p!\n",WinPos
.hwnd
);
1708 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE
);
1712 /* Fix up the flags. */
1713 if (!WinPosFixupFlags(&WinPos
, Window
))
1719 Ancestor
= UserGetAncestor(Window
, GA_PARENT
);
1720 if ( (WinPos
.flags
& (SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) != SWP_NOZORDER
&&
1721 Ancestor
&& Ancestor
->head
.h
== IntGetDesktopWindow() )
1723 WinPos
.hwndInsertAfter
= WinPosDoOwnedPopups(Window
, WinPos
.hwndInsertAfter
);
1726 if (!(WinPos
.flags
& SWP_NOREDRAW
))
1728 /* Compute the visible region before the window position is changed */
1729 if (!(WinPos
.flags
& SWP_SHOWWINDOW
) &&
1730 (WinPos
.flags
& (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
|
1731 SWP_HIDEWINDOW
| SWP_FRAMECHANGED
)) !=
1732 (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
))
1734 VisBefore
= VIS_ComputeVisibleRegion(Window
, FALSE
, FALSE
,
1735 (Window
->style
& WS_CLIPSIBLINGS
) ? TRUE
: FALSE
);
1737 if ( VisBefore
!= NULL
&&
1738 REGION_Complexity(VisBefore
) == NULLREGION
)
1740 REGION_Delete(VisBefore
);
1745 IntGdiOffsetRgn(VisBefore
, -Window
->rcWindow
.left
, -Window
->rcWindow
.top
);
1748 /* Calculate the non client area for resizes, as this is used in the copy region */
1749 if (!(WinPos
.flags
& SWP_NOSIZE
))
1751 VisBeforeJustClient
= VIS_ComputeVisibleRegion(Window
, TRUE
, FALSE
,
1752 (Window
->style
& WS_CLIPSIBLINGS
) ? TRUE
: FALSE
);
1754 if ( VisBeforeJustClient
!= NULL
&&
1755 REGION_Complexity(VisBeforeJustClient
) == NULLREGION
)
1757 REGION_Delete(VisBeforeJustClient
);
1758 VisBeforeJustClient
= NULL
;
1760 else if(VisBeforeJustClient
)
1762 IntGdiOffsetRgn(VisBeforeJustClient
, -Window
->rcWindow
.left
, -Window
->rcWindow
.top
);
1768 WvrFlags
= co_WinPosDoNCCALCSize(Window
, &WinPos
, &NewWindowRect
, &NewClientRect
, valid_rects
);
1770 // ERR("co_WinPosDoNCCALCSize returned 0x%x\n valid dest: %d %d %d %d\n valid src : %d %d %d %d\n", WvrFlags,
1771 // valid_rects[0].left,valid_rects[0].top,valid_rects[0].right,valid_rects[0].bottom,
1772 // valid_rects[1].left,valid_rects[1].top,valid_rects[1].right,valid_rects[1].bottom);
1774 /* Validate link windows. (also take into account shell window in hwndShellWindow) */
1775 if (!(WinPos
.flags
& SWP_NOZORDER
) && WinPos
.hwnd
!= UserGetShellWindow())
1777 IntLinkHwnd(Window
, WinPos
.hwndInsertAfter
);
1780 OldWindowRect
= Window
->rcWindow
;
1781 OldClientRect
= Window
->rcClient
;
1783 if (NewClientRect
.left
!= OldClientRect
.left
||
1784 NewClientRect
.top
!= OldClientRect
.top
)
1786 // Move child window if their parent is moved. Keep Child window relative to Parent...
1787 WinPosInternalMoveWindow(Window
,
1788 NewClientRect
.left
- OldClientRect
.left
,
1789 NewClientRect
.top
- OldClientRect
.top
);
1792 Window
->rcWindow
= NewWindowRect
;
1793 Window
->rcClient
= NewClientRect
;
1795 /* erase parent when hiding or resizing child */
1796 if (WinPos
.flags
& SWP_HIDEWINDOW
)
1798 /* Clear the update region */
1799 co_UserRedrawWindow( Window
,
1802 RDW_VALIDATE
| RDW_NOFRAME
| RDW_NOERASE
| RDW_NOINTERNALPAINT
| RDW_ALLCHILDREN
);
1804 if (Window
->spwndParent
== UserGetDesktopWindow())
1805 co_IntShellHookNotify(HSHELL_WINDOWDESTROYED
, (WPARAM
)Window
->head
.h
, 0);
1807 Window
->style
&= ~WS_VISIBLE
; //IntSetStyle( Window, 0, WS_VISIBLE );
1808 Window
->head
.pti
->cVisWindows
--;
1809 IntNotifyWinEvent(EVENT_OBJECT_HIDE
, Window
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
1811 else if (WinPos
.flags
& SWP_SHOWWINDOW
)
1813 if (Window
->spwndParent
== UserGetDesktopWindow())
1814 co_IntShellHookNotify(HSHELL_WINDOWCREATED
, (WPARAM
)Window
->head
.h
, 0);
1816 Window
->style
|= WS_VISIBLE
; //IntSetStyle( Window, WS_VISIBLE, 0 );
1817 Window
->head
.pti
->cVisWindows
++;
1818 IntNotifyWinEvent(EVENT_OBJECT_SHOW
, Window
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
1821 if (Window
->hrgnUpdate
!= NULL
&& Window
->hrgnUpdate
!= HRGN_WINDOW
)
1823 NtGdiOffsetRgn(Window
->hrgnUpdate
,
1824 NewWindowRect
.left
- OldWindowRect
.left
,
1825 NewWindowRect
.top
- OldWindowRect
.top
);
1828 DceResetActiveDCEs(Window
); // For WS_VISIBLE changes.
1830 if (!(WinPos
.flags
& SWP_NOREDRAW
))
1832 /* Determine the new visible region */
1833 VisAfter
= VIS_ComputeVisibleRegion(Window
, FALSE
, FALSE
,
1834 (Window
->style
& WS_CLIPSIBLINGS
) ? TRUE
: FALSE
);
1836 if ( VisAfter
!= NULL
&&
1837 REGION_Complexity(VisAfter
) == NULLREGION
)
1839 REGION_Delete(VisAfter
);
1844 IntGdiOffsetRgn(VisAfter
, -Window
->rcWindow
.left
, -Window
->rcWindow
.top
);
1848 * Determine which pixels can be copied from the old window position
1849 * to the new. Those pixels must be visible in both the old and new
1850 * position. Also, check the class style to see if the windows of this
1851 * class need to be completely repainted on (horizontal/vertical) size
1854 if ( VisBefore
!= NULL
&&
1856 !(WinPos
.flags
& SWP_NOCOPYBITS
) &&
1857 ((WinPos
.flags
& SWP_NOSIZE
) || !(WvrFlags
& WVR_REDRAW
)) &&
1858 !(Window
->ExStyle
& WS_EX_TRANSPARENT
) )
1862 * If this is (also) a window resize, the whole nonclient area
1863 * needs to be repainted. So we limit the copy to the client area,
1864 * 'cause there is no use in copying it (would possibly cause
1865 * "flashing" too). However, if the copy region is already empty,
1866 * we don't have to crop (can't take anything away from an empty
1870 CopyRgn
= IntSysCreateRectpRgn(0, 0, 0, 0);
1871 if (WinPos
.flags
& SWP_NOSIZE
)
1872 RgnType
= IntGdiCombineRgn(CopyRgn
, VisAfter
, VisBefore
, RGN_AND
);
1873 else if (VisBeforeJustClient
!= NULL
)
1875 RgnType
= IntGdiCombineRgn(CopyRgn
, VisAfter
, VisBeforeJustClient
, RGN_AND
);
1876 REGION_Delete(VisBeforeJustClient
);
1879 /* No use in copying bits which are in the update region. */
1880 if (Window
->hrgnUpdate
!= NULL
)
1882 PREGION RgnUpdate
= RGNOBJAPI_Lock(Window
->hrgnUpdate
, NULL
);
1885 IntGdiOffsetRgn(CopyRgn
, NewWindowRect
.left
, NewWindowRect
.top
);
1886 IntGdiCombineRgn(CopyRgn
, CopyRgn
, RgnUpdate
, RGN_DIFF
);
1887 IntGdiOffsetRgn(CopyRgn
, -NewWindowRect
.left
, -NewWindowRect
.top
);
1888 RGNOBJAPI_Unlock(RgnUpdate
);
1893 * Now, get the bounding box of the copy region. If it's empty
1894 * there's nothing to copy. Also, it's no use copying bits onto
1897 if (REGION_GetRgnBox(CopyRgn
, &CopyRect
) == NULLREGION
)
1899 /* Nothing to copy, clean up */
1900 REGION_Delete(CopyRgn
);
1903 else if (OldWindowRect
.left
!= NewWindowRect
.left
||
1904 OldWindowRect
.top
!= NewWindowRect
.top
)
1906 HRGN DcRgn
= NtGdiCreateRectRgn(0, 0, 0, 0);
1907 PREGION DcRgnObj
= RGNOBJAPI_Lock(DcRgn
, NULL
);
1910 * Small trick here: there is no function to bitblt a region. So
1911 * we set the region as the clipping region, take the bounding box
1912 * of the region and bitblt that. Since nothing outside the clipping
1913 * region is copied, this has the effect of bitblt'ing the region.
1915 * Since NtUserGetDCEx takes ownership of the clip region, we need
1916 * to create a copy of CopyRgn and pass that. We need CopyRgn later
1918 IntGdiCombineRgn(DcRgnObj
, CopyRgn
, NULL
, RGN_COPY
);
1919 IntGdiOffsetRgn(DcRgnObj
, NewWindowRect
.left
, NewWindowRect
.top
);
1920 RGNOBJAPI_Unlock(DcRgnObj
);
1921 Dc
= UserGetDCEx( Window
,
1923 DCX_WINDOW
|DCX_CACHE
|DCX_INTERSECTRGN
|DCX_CLIPSIBLINGS
|DCX_KEEPCLIPRGN
);
1925 CopyRect
.left
, CopyRect
.top
,
1926 CopyRect
.right
- CopyRect
.left
,
1927 CopyRect
.bottom
- CopyRect
.top
,
1929 CopyRect
.left
+ (OldWindowRect
.left
- NewWindowRect
.left
),
1930 CopyRect
.top
+ (OldWindowRect
.top
- NewWindowRect
.top
),
1935 UserReleaseDC(Window
, Dc
, FALSE
);
1936 IntValidateParent(Window
, CopyRgn
, FALSE
);
1937 GreDeleteObject(DcRgn
);
1945 /* We need to redraw what wasn't visible before */
1946 if (VisAfter
!= NULL
)
1948 PREGION DirtyRgn
= IntSysCreateRectpRgn(0, 0, 0, 0);
1951 if (CopyRgn
!= NULL
)
1953 RgnType
= IntGdiCombineRgn(DirtyRgn
, VisAfter
, CopyRgn
, RGN_DIFF
);
1957 RgnType
= IntGdiCombineRgn(DirtyRgn
, VisAfter
, 0, RGN_COPY
);
1959 if (RgnType
!= ERROR
&& RgnType
!= NULLREGION
)
1962 NtGdiOffsetRgn(DirtyRgn, Window->rcWindow.left, Window->rcWindow.top);
1963 IntInvalidateWindows( Window,
1965 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
1967 GreDeleteObject(DirtyRgn);
1970 PWND Parent
= Window
->spwndParent
;
1972 IntGdiOffsetRgn( DirtyRgn
,
1973 Window
->rcWindow
.left
,
1974 Window
->rcWindow
.top
);
1975 if ( (Window
->style
& WS_CHILD
) &&
1977 !(Parent
->style
& WS_CLIPCHILDREN
))
1979 IntInvalidateWindows( Parent
,
1981 RDW_ERASE
| RDW_INVALIDATE
);
1982 co_IntPaintWindows(Parent
, RDW_ERASENOW
, FALSE
);
1986 IntInvalidateWindows( Window
,
1988 RDW_ERASE
| RDW_FRAME
| RDW_INVALIDATE
| RDW_ALLCHILDREN
);
1991 REGION_Delete(DirtyRgn
);
1995 if (CopyRgn
!= NULL
)
1997 REGION_Delete(CopyRgn
);
2000 /* Expose what was covered before but not covered anymore */
2001 if (VisBefore
!= NULL
)
2003 PREGION ExposedRgn
= IntSysCreateRectpRgn(0, 0, 0, 0);
2006 RgnType
= IntGdiCombineRgn(ExposedRgn
, VisBefore
, NULL
, RGN_COPY
);
2007 IntGdiOffsetRgn( ExposedRgn
,
2008 OldWindowRect
.left
- NewWindowRect
.left
,
2009 OldWindowRect
.top
- NewWindowRect
.top
);
2011 if (VisAfter
!= NULL
)
2012 RgnType
= IntGdiCombineRgn(ExposedRgn
, ExposedRgn
, VisAfter
, RGN_DIFF
);
2014 if (RgnType
!= ERROR
&& RgnType
!= NULLREGION
)
2016 co_VIS_WindowLayoutChanged(Window
, ExposedRgn
);
2018 REGION_Delete(ExposedRgn
);
2020 REGION_Delete(VisBefore
);
2023 if (VisAfter
!= NULL
)
2025 REGION_Delete(VisAfter
);
2029 if (!(WinPos
.flags
& (SWP_NOACTIVATE
|SWP_HIDEWINDOW
)))
2031 if ((Window
->style
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
2033 co_IntSendMessageNoWait(WinPos
.hwnd
, WM_CHILDACTIVATE
, 0, 0);
2037 //ERR("SetWindowPos Set FG Window!\n");
2038 if (Window
->state
& WNDS_BEINGACTIVATED
) // Inside SAW?
2039 co_IntSetActiveWindow(Window
, FALSE
, TRUE
, FALSE
); // Fixes Api AttachThreadInput tests.
2041 co_IntSetForegroundWindow(Window
); // Fixes SW_HIDE issues. Wine win test_SetActiveWindow & test_SetForegroundWindow.
2045 /* And last, send the WM_WINDOWPOSCHANGED message */
2047 TRACE("\tstatus flags = %04x\n", WinPos
.flags
& SWP_AGG_STATUSFLAGS
);
2049 if ((WinPos
.flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOPOSCHANGE
)
2051 /* WM_WINDOWPOSCHANGED is sent even if SWP_NOSENDCHANGING is set
2052 and always contains final window position.
2054 WinPos
.x
= NewWindowRect
.left
;
2055 WinPos
.y
= NewWindowRect
.top
;
2056 WinPos
.cx
= NewWindowRect
.right
- NewWindowRect
.left
;
2057 WinPos
.cy
= NewWindowRect
.bottom
- NewWindowRect
.top
;
2058 co_IntSendMessageNoWait(WinPos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
) &WinPos
);
2061 if ( WinPos
.flags
& SWP_FRAMECHANGED
|| WinPos
.flags
& SWP_STATECHANGED
||
2062 !(WinPos
.flags
& SWP_NOCLIENTSIZE
) || !(WinPos
.flags
& SWP_NOCLIENTMOVE
) )
2064 PWND pWnd
= ValidateHwndNoErr(WinPos
.hwnd
);
2066 IntNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE
, pWnd
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
2069 if(bPointerInWindow
!= IntPtInWindow(Window
, gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
))
2071 /* Generate mouse move message */
2073 msg
.message
= WM_MOUSEMOVE
;
2074 msg
.wParam
= UserGetMouseButtonsState();
2075 msg
.lParam
= MAKELPARAM(gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
);
2076 msg
.pt
= gpsi
->ptCursor
;
2077 co_MsqInsertMouseMessage(&msg
, 0, 0, TRUE
);
2084 co_WinPosGetNonClientSize(PWND Window
, RECT
* WindowRect
, RECT
* ClientRect
)
2088 ASSERT_REFS_CO(Window
);
2090 *ClientRect
= *WindowRect
;
2091 Result
= co_IntSendMessageNoWait(Window
->head
.h
, WM_NCCALCSIZE
, FALSE
, (LPARAM
) ClientRect
);
2093 FixClientRect(ClientRect
, WindowRect
);
2099 co_WinPosSendSizeMove(PWND Wnd
)
2103 WPARAM wParam
= SIZE_RESTORED
;
2105 IntGetClientRect(Wnd
, &Rect
);
2106 lParam
= MAKELONG(Rect
.right
-Rect
.left
, Rect
.bottom
-Rect
.top
);
2108 Wnd
->state
&= ~WNDS_SENDSIZEMOVEMSGS
;
2110 if (Wnd
->style
& WS_MAXIMIZE
)
2112 wParam
= SIZE_MAXIMIZED
;
2114 else if (Wnd
->style
& WS_MINIMIZE
)
2116 wParam
= SIZE_MINIMIZED
;
2120 co_IntSendMessageNoWait(UserHMGetHandle(Wnd
), WM_SIZE
, wParam
, lParam
);
2122 if (Wnd
->spwndParent
== UserGetDesktopWindow()) // Wnd->spwndParent->fnid == FNID_DESKTOP )
2123 lParam
= MAKELONG(Wnd
->rcClient
.left
, Wnd
->rcClient
.top
);
2125 lParam
= MAKELONG(Wnd
->rcClient
.left
-Wnd
->spwndParent
->rcClient
.left
, Wnd
->rcClient
.top
-Wnd
->spwndParent
->rcClient
.top
);
2127 co_IntSendMessageNoWait(UserHMGetHandle(Wnd
), WM_MOVE
, 0, lParam
);
2129 IntEngWindowChanged(Wnd
, WOC_RGN_CLIENT
);
2133 co_WinPosShowWindow(PWND Wnd
, INT Cmd
)
2136 UINT Swp
= 0, EventMsg
= 0;
2137 RECTL NewPos
= {0, 0, 0, 0};
2143 BOOL ShowOwned
= FALSE
;
2144 ASSERT_REFS_CO(Wnd
);
2145 //ERR("co_WinPosShowWindow START\n");
2147 pti
= PsGetCurrentThreadWin32Thread();
2148 WasVisible
= (Wnd
->style
& WS_VISIBLE
) != 0;
2157 //ERR("co_WinPosShowWindow Exit Bad\n");
2160 Swp
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
2161 if (Wnd
!= pti
->MessageQueue
->spwndActive
)
2162 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2166 case SW_FORCEMINIMIZE
: /* FIXME: Does not work if thread is hung. */
2167 case SW_SHOWMINNOACTIVE
:
2168 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2170 case SW_SHOWMINIMIZED
:
2171 Swp
|= SWP_SHOWWINDOW
;
2175 Swp
|= SWP_NOACTIVATE
;
2176 if (!(style
& WS_MINIMIZE
))
2178 IntShowOwnedPopups(Wnd
, FALSE
);
2180 // Fix wine Win test_SetFocus todo #1 & #2,
2181 if (Cmd
== SW_SHOWMINIMIZED
)
2183 //ERR("co_WinPosShowWindow Set focus 1\n");
2184 if ((style
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
2185 co_UserSetFocus(Wnd
->spwndParent
);
2190 Swp
|= co_WinPosMinMaximize(Wnd
, Cmd
, &NewPos
) |
2193 EventMsg
= EVENT_SYSTEM_MINIMIZESTART
;
2199 Swp
|= SWP_FRAMECHANGED
;
2203 //ERR("co_WinPosShowWindow Exit Good\n");
2206 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
2211 case SW_SHOWMAXIMIZED
:
2213 Swp
|= SWP_SHOWWINDOW
;
2214 if (!(style
& WS_MAXIMIZE
))
2218 Swp
|= co_WinPosMinMaximize(Wnd
, SW_MAXIMIZE
, &NewPos
) |
2221 EventMsg
= EVENT_SYSTEM_MINIMIZEEND
;
2227 Swp
|= SWP_FRAMECHANGED
;
2231 //ERR("co_WinPosShowWindow Exit Good 1\n");
2234 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
2240 Swp
|= SWP_NOACTIVATE
| SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
2241 if (style
& WS_CHILD
&& !(Wnd
->ExStyle
& WS_EX_MDICHILD
)) Swp
|= SWP_NOZORDER
;
2244 if (WasVisible
) return(TRUE
); // Nothing to do!
2245 Swp
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
2246 /* Don't activate the topmost window. */
2247 if (style
& WS_CHILD
&& !(Wnd
->ExStyle
& WS_EX_MDICHILD
)) Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2250 case SW_SHOWNOACTIVATE
:
2251 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2254 case SW_SHOWDEFAULT
:
2256 if (!WasVisible
) Swp
|= SWP_SHOWWINDOW
;
2257 if (style
& (WS_MINIMIZE
| WS_MAXIMIZE
))
2259 Swp
|= co_WinPosMinMaximize(Wnd
, Cmd
, &NewPos
) |
2262 if (style
& WS_MINIMIZE
) EventMsg
= EVENT_SYSTEM_MINIMIZEEND
;
2268 Swp
|= SWP_FRAMECHANGED
;
2272 //ERR("co_WinPosShowWindow Exit Good 3\n");
2275 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
2277 if ( style
& WS_CHILD
&&
2278 !(Wnd
->ExStyle
& WS_EX_MDICHILD
) &&
2279 !(Swp
& SWP_STATECHANGED
))
2280 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2284 //ERR("co_WinPosShowWindow Exit Good 4\n");
2288 ShowFlag
= (Cmd
!= SW_HIDE
);
2290 if ((ShowFlag
!= WasVisible
|| Cmd
== SW_SHOWNA
) && Cmd
!= SW_SHOWMAXIMIZED
&& !(Swp
& SWP_STATECHANGED
))
2292 co_IntSendMessageNoWait(Wnd
->head
.h
, WM_SHOWWINDOW
, ShowFlag
, 0);
2293 if (!(Wnd
->state2
& WNDS2_WIN31COMPAT
))
2294 co_IntSendMessageNoWait(Wnd
->head
.h
, WM_SETVISIBLE
, ShowFlag
, 0);
2295 if (!VerifyWnd(Wnd
)) return WasVisible
;
2298 /* We can't activate a child window */
2299 if ((Wnd
->style
& WS_CHILD
) &&
2300 !(Wnd
->ExStyle
& WS_EX_MDICHILD
) &&
2303 //ERR("SWP Child No active and ZOrder\n");
2304 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2307 #if 0 // Explorer issues with common controls? Someone does not know how CS_SAVEBITS works.
2308 // Breaks startup and shutdown active window...
2309 if ((Wnd
->style
& (WS_POPUP
|WS_CHILD
)) != WS_CHILD
&&
2310 Wnd
->pcls
->style
& CS_SAVEBITS
&&
2311 ((Cmd
== SW_SHOW
) || (Cmd
== SW_NORMAL
)))
2313 ERR("WinPosShowWindow Set active\n");
2314 UserSetActiveWindow(Wnd
);
2315 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2319 if (IsChildVisible(Wnd
) || Swp
& SWP_STATECHANGED
)
2321 TRACE("Child is Vis %s or State changed %s. ShowFlag %s\n",
2322 (IsChildVisible(Wnd
) ? "TRUE" : "FALSE"), (Swp
& SWP_STATECHANGED
? "TRUE" : "FALSE"),
2323 (ShowFlag
? "TRUE" : "FALSE"));
2324 co_WinPosSetWindowPos( Wnd
,
2325 0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
) ? HWND_TOPMOST
: HWND_TOP
,
2328 NewPos
.right
, //NewPos.right - NewPos.left,
2329 NewPos
.bottom
, //NewPos.bottom - NewPos.top,
2334 TRACE("Parent Vis?\n");
2335 /* if parent is not visible simply toggle WS_VISIBLE and return */
2336 if (ShowFlag
) IntSetStyle( Wnd
, WS_VISIBLE
, 0 );
2337 else IntSetStyle( Wnd
, 0, WS_VISIBLE
);
2340 if ( EventMsg
) IntNotifyWinEvent(EventMsg
, Wnd
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
2342 if ( ShowOwned
) IntShowOwnedPopups(Wnd
, TRUE
);
2344 if ((Cmd
== SW_HIDE
) || (Cmd
== SW_MINIMIZE
))
2346 if ( Wnd
== pti
->MessageQueue
->spwndActive
&& pti
->MessageQueue
== IntGetFocusMessageQueue() )
2348 if ( Wnd
->spwndParent
== UserGetDesktopWindow())
2350 if(!ActivateOtherWindowMin(Wnd
))
2351 co_WinPosActivateOtherWindow(Wnd
);
2354 co_WinPosActivateOtherWindow(Wnd
);
2357 /* Revert focus to parent */
2358 if (Wnd
== pti
->MessageQueue
->spwndFocus
)
2360 Parent
= Wnd
->spwndParent
;
2361 if (Wnd
->spwndParent
== UserGetDesktopWindow()) Parent
= 0;
2362 co_UserSetFocus(Parent
);
2366 /* FIXME: Check for window destruction. */
2368 if ((Wnd
->state
& WNDS_SENDSIZEMOVEMSGS
) &&
2369 !(Wnd
->state2
& WNDS2_INDESTROY
))
2371 co_WinPosSendSizeMove(Wnd
);
2374 /* if previous state was minimized Windows sets focus to the window */
2375 if (style
& WS_MINIMIZE
)
2377 co_UserSetFocus(Wnd
);
2378 // Fix wine Win test_SetFocus todo #3,
2379 if (!(style
& WS_CHILD
)) co_IntSendMessageNoWait(UserHMGetHandle(Wnd
), WM_ACTIVATE
, WA_ACTIVE
, 0);
2381 //ERR("co_WinPosShowWindow EXIT\n");
2387 co_WinPosSearchChildren(
2397 if (!(ScopeWin
->style
& WS_VISIBLE
))
2402 if (!Ignore
&& (ScopeWin
->style
& WS_DISABLED
))
2407 if (!IntPtInWindow(ScopeWin
, Point
->x
, Point
->y
))
2412 UserReferenceObject(ScopeWin
);
2414 if ( RECTL_bPointInRect(&ScopeWin
->rcClient
, Point
->x
, Point
->y
) )
2416 List
= IntWinListChildren(ScopeWin
);
2419 for (phWnd
= List
; *phWnd
; ++phWnd
)
2421 if (!(pwndChild
= ValidateHwndNoErr(*phWnd
)))
2426 pwndChild
= co_WinPosSearchChildren(pwndChild
, Point
, HitTest
, Ignore
);
2428 if(pwndChild
!= NULL
)
2430 /* We found a window. Don't send any more WM_NCHITTEST messages */
2431 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2432 UserDereferenceObject(ScopeWin
);
2436 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2440 if (ScopeWin
->head
.pti
== PsGetCurrentThreadWin32Thread())
2442 *HitTest
= (USHORT
)co_IntSendMessage(ScopeWin
->head
.h
, WM_NCHITTEST
, 0,
2443 MAKELONG(Point
->x
, Point
->y
));
2444 if ((*HitTest
) == (USHORT
)HTTRANSPARENT
)
2446 UserDereferenceObject(ScopeWin
);
2451 *HitTest
= HTCLIENT
;
2457 co_WinPosWindowFromPoint(PWND ScopeWin
, POINT
*WinPoint
, USHORT
* HitTest
, BOOL Ignore
)
2460 POINT Point
= *WinPoint
;
2461 USER_REFERENCE_ENTRY Ref
;
2463 if( ScopeWin
== NULL
)
2465 ScopeWin
= UserGetDesktopWindow();
2466 if(ScopeWin
== NULL
)
2470 *HitTest
= HTNOWHERE
;
2472 ASSERT_REFS_CO(ScopeWin
);
2473 UserRefObjectCo(ScopeWin
, &Ref
);
2475 Window
= co_WinPosSearchChildren(ScopeWin
, &Point
, HitTest
, Ignore
);
2477 UserDerefObjectCo(ScopeWin
);
2479 ASSERT_REFS_CO(Window
);
2480 ASSERT_REFS_CO(ScopeWin
);
2486 IntRealChildWindowFromPoint(PWND Parent
, LONG x
, LONG y
)
2490 PWND pwndHit
= NULL
;
2495 if (Parent
!= UserGetDesktopWindow())
2497 Pt
.x
+= Parent
->rcClient
.left
;
2498 Pt
.y
+= Parent
->rcClient
.top
;
2501 if (!IntPtInWindow(Parent
, Pt
.x
, Pt
.y
)) return NULL
;
2503 if ((List
= IntWinListChildren(Parent
)))
2505 for (phWnd
= List
; *phWnd
; phWnd
++)
2508 if ((Child
= ValidateHwndNoErr(*phWnd
)))
2510 if ( Child
->style
& WS_VISIBLE
&& IntPtInWindow(Child
, Pt
.x
, Pt
.y
) )
2512 if ( Child
->pcls
->atomClassName
!= gpsi
->atomSysClass
[ICLS_BUTTON
] ||
2513 (Child
->style
& BS_TYPEMASK
) != BS_GROUPBOX
)
2515 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2522 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2524 return pwndHit
? pwndHit
: Parent
;
2528 IntChildWindowFromPointEx(PWND Parent
, LONG x
, LONG y
, UINT uiFlags
)
2532 PWND pwndHit
= NULL
;
2537 if (Parent
!= UserGetDesktopWindow())
2539 if (Parent
->ExStyle
& WS_EX_LAYOUTRTL
)
2540 Pt
.x
= Parent
->rcClient
.right
- Pt
.x
;
2542 Pt
.x
+= Parent
->rcClient
.left
;
2543 Pt
.y
+= Parent
->rcClient
.top
;
2546 if (!IntPtInWindow(Parent
, Pt
.x
, Pt
.y
)) return NULL
;
2548 if ((List
= IntWinListChildren(Parent
)))
2550 for (phWnd
= List
; *phWnd
; phWnd
++)
2553 if ((Child
= ValidateHwndNoErr(*phWnd
)))
2555 if (uiFlags
& (CWP_SKIPINVISIBLE
|CWP_SKIPDISABLED
))
2557 if (!(Child
->style
& WS_VISIBLE
) && (uiFlags
& CWP_SKIPINVISIBLE
)) continue;
2558 if ((Child
->style
& WS_DISABLED
) && (uiFlags
& CWP_SKIPDISABLED
)) continue;
2561 if (uiFlags
& CWP_SKIPTRANSPARENT
)
2563 if (Child
->ExStyle
& WS_EX_TRANSPARENT
) continue;
2566 if (IntPtInWindow(Child
, Pt
.x
, Pt
.y
))
2573 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2575 return pwndHit
? pwndHit
: Parent
;
2580 IntDeferWindowPos( HDWP hdwp
,
2591 HDWP retvalue
= hdwp
;
2593 TRACE("hdwp %p, hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
2594 hdwp
, hwnd
, hwndAfter
, x
, y
, cx
, cy
, flags
);
2596 if (flags
& ~(SWP_NOSIZE
| SWP_NOMOVE
|
2597 SWP_NOZORDER
| SWP_NOREDRAW
|
2598 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
2599 SWP_NOOWNERZORDER
|SWP_SHOWWINDOW
|
2600 SWP_HIDEWINDOW
| SWP_FRAMECHANGED
))
2602 EngSetLastError(ERROR_INVALID_PARAMETER
);
2606 if (!(pDWP
= (PSMWP
)UserGetObject(gHandleTable
, hdwp
, TYPE_SETWINDOWPOS
)))
2608 EngSetLastError(ERROR_INVALID_DWP_HANDLE
);
2612 for (i
= 0; i
< pDWP
->ccvr
; i
++)
2614 if (pDWP
->acvr
[i
].pos
.hwnd
== hwnd
)
2616 /* Merge with the other changes */
2617 if (!(flags
& SWP_NOZORDER
))
2619 pDWP
->acvr
[i
].pos
.hwndInsertAfter
= hwndAfter
;
2621 if (!(flags
& SWP_NOMOVE
))
2623 pDWP
->acvr
[i
].pos
.x
= x
;
2624 pDWP
->acvr
[i
].pos
.y
= y
;
2626 if (!(flags
& SWP_NOSIZE
))
2628 pDWP
->acvr
[i
].pos
.cx
= cx
;
2629 pDWP
->acvr
[i
].pos
.cy
= cy
;
2631 pDWP
->acvr
[i
].pos
.flags
&= flags
| ~(SWP_NOSIZE
| SWP_NOMOVE
|
2632 SWP_NOZORDER
| SWP_NOREDRAW
|
2633 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
2635 pDWP
->acvr
[i
].pos
.flags
|= flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
|
2640 if (pDWP
->ccvr
>= pDWP
->ccvrAlloc
)
2642 PCVR newpos
= ExAllocatePoolWithTag(PagedPool
, pDWP
->ccvrAlloc
* 2 * sizeof(CVR
), USERTAG_SWP
);
2648 RtlZeroMemory(newpos
, pDWP
->ccvrAlloc
* 2 * sizeof(CVR
));
2649 RtlCopyMemory(newpos
, pDWP
->acvr
, pDWP
->ccvrAlloc
* sizeof(CVR
));
2650 ExFreePoolWithTag(pDWP
->acvr
, USERTAG_SWP
);
2651 pDWP
->ccvrAlloc
*= 2;
2652 pDWP
->acvr
= newpos
;
2654 pDWP
->acvr
[pDWP
->ccvr
].pos
.hwnd
= hwnd
;
2655 pDWP
->acvr
[pDWP
->ccvr
].pos
.hwndInsertAfter
= hwndAfter
;
2656 pDWP
->acvr
[pDWP
->ccvr
].pos
.x
= x
;
2657 pDWP
->acvr
[pDWP
->ccvr
].pos
.y
= y
;
2658 pDWP
->acvr
[pDWP
->ccvr
].pos
.cx
= cx
;
2659 pDWP
->acvr
[pDWP
->ccvr
].pos
.cy
= cy
;
2660 pDWP
->acvr
[pDWP
->ccvr
].pos
.flags
= flags
;
2661 pDWP
->acvr
[pDWP
->ccvr
].hrgnClip
= NULL
;
2662 pDWP
->acvr
[pDWP
->ccvr
].hrgnInterMonitor
= NULL
;
2668 BOOL FASTCALL
IntEndDeferWindowPosEx( HDWP hdwp
, BOOL sAsync
)
2675 TRACE("%p\n", hdwp
);
2677 if (!(pDWP
= (PSMWP
)UserGetObject(gHandleTable
, hdwp
, TYPE_SETWINDOWPOS
)))
2679 EngSetLastError(ERROR_INVALID_DWP_HANDLE
);
2683 for (i
= 0, winpos
= pDWP
->acvr
; res
&& i
< pDWP
->ccvr
; i
++, winpos
++)
2686 USER_REFERENCE_ENTRY Ref
;
2688 TRACE("hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
2689 winpos
->pos
.hwnd
, winpos
->pos
.hwndInsertAfter
, winpos
->pos
.x
, winpos
->pos
.y
,
2690 winpos
->pos
.cx
, winpos
->pos
.cy
, winpos
->pos
.flags
);
2692 pwnd
= ValidateHwndNoErr(winpos
->pos
.hwnd
);
2696 UserRefObjectCo(pwnd
, &Ref
);
2701 PWINDOWPOS ppos
= ExAllocatePoolWithTag(PagedPool
, sizeof(WINDOWPOS
), USERTAG_SWP
);
2704 *ppos
= winpos
->pos
;
2705 /* Yes it's a pointer inside Win32k! */
2706 lRes
= co_IntSendMessageNoWait( winpos
->pos
.hwnd
, WM_ASYNC_SETWINDOWPOS
, 0, (LPARAM
)ppos
);
2707 /* We handle this the same way as Event Hooks and Hooks. */
2710 ExFreePoolWithTag(ppos
, USERTAG_SWP
);
2715 res
= co_WinPosSetWindowPos( pwnd
,
2716 winpos
->pos
.hwndInsertAfter
,
2723 // Hack to pass tests.... Must have some work to do so clear the error.
2724 if (res
&& (winpos
->pos
.flags
& (SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOZORDER
)) == SWP_NOZORDER
)
2725 EngSetLastError(ERROR_SUCCESS
);
2727 UserDerefObjectCo(pwnd
);
2729 ExFreePoolWithTag(pDWP
->acvr
, USERTAG_SWP
);
2730 UserDereferenceObject(pDWP
);
2731 UserDeleteObject(hdwp
, TYPE_SETWINDOWPOS
);
2739 NtUserChildWindowFromPointEx(HWND hwndParent
,
2745 TRACE("Enter NtUserChildWindowFromPointEx\n");
2746 UserEnterExclusive();
2747 if ((pwndParent
= UserGetWindowObject(hwndParent
)))
2749 pwndParent
= IntChildWindowFromPointEx(pwndParent
, x
, y
, uiFlags
);
2752 TRACE("Leave NtUserChildWindowFromPointEx\n");
2753 return pwndParent
? UserHMGetHandle(pwndParent
) : NULL
;
2760 NtUserEndDeferWindowPosEx(HDWP WinPosInfo
,
2764 TRACE("Enter NtUserEndDeferWindowPosEx\n");
2765 UserEnterExclusive();
2766 Ret
= IntEndDeferWindowPosEx(WinPosInfo
, (BOOL
)Unknown1
);
2767 TRACE("Leave NtUserEndDeferWindowPosEx, ret=%i\n", Ret
);
2776 NtUserDeferWindowPos(HDWP WinPosInfo
,
2778 HWND WndInsertAfter
,
2787 UINT Tmp
= ~(SWP_ASYNCWINDOWPOS
|SWP_DEFERERASE
|SWP_NOSENDCHANGING
|SWP_NOREPOSITION
|
2788 SWP_NOCOPYBITS
|SWP_HIDEWINDOW
|SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|
2789 SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_NOZORDER
|SWP_NOMOVE
|SWP_NOSIZE
);
2791 TRACE("Enter NtUserDeferWindowPos\n");
2792 UserEnterExclusive();
2796 EngSetLastError(ERROR_INVALID_FLAGS
);
2800 pWnd
= UserGetWindowObject(Wnd
);
2801 if ( !pWnd
|| // FIXME:
2802 pWnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
2803 pWnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
2808 if ( WndInsertAfter
&&
2809 WndInsertAfter
!= HWND_BOTTOM
&&
2810 WndInsertAfter
!= HWND_TOPMOST
&&
2811 WndInsertAfter
!= HWND_NOTOPMOST
)
2813 pWndIA
= UserGetWindowObject(WndInsertAfter
);
2815 pWndIA
== UserGetDesktopWindow() ||
2816 pWndIA
== UserGetMessageWindow() )
2822 Ret
= IntDeferWindowPos(WinPosInfo
, Wnd
, WndInsertAfter
, x
, y
, cx
, cy
, Flags
);
2825 TRACE("Leave NtUserDeferWindowPos, ret=%p\n", Ret
);
2834 NtUserGetInternalWindowPos( HWND hWnd
,
2841 WINDOWPLACEMENT wndpl
;
2845 if (!(Window
= UserGetWindowObject(hWnd
)))
2855 ProbeForWrite(rectWnd
,
2861 ProbeForWrite(ptIcon
,
2867 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2869 SetLastNtError(_SEH2_GetExceptionCode());
2874 wndpl
.length
= sizeof(WINDOWPLACEMENT
);
2876 if (IntGetWindowPlacement(Window
, &wndpl
) && !Hit
)
2882 RtlCopyMemory(rectWnd
, &wndpl
.rcNormalPosition
, sizeof(RECT
));
2886 RtlCopyMemory(ptIcon
, &wndpl
.ptMinPosition
, sizeof(POINT
));
2890 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2892 SetLastNtError(_SEH2_GetExceptionCode());
2897 if (!Hit
) Ret
= wndpl
.showCmd
;
2908 NtUserGetWindowPlacement(HWND hWnd
,
2909 WINDOWPLACEMENT
*lpwndpl
)
2912 WINDOWPLACEMENT Safepl
;
2914 DECLARE_RETURN(BOOL
);
2916 TRACE("Enter NtUserGetWindowPlacement\n");
2919 if (!(Wnd
= UserGetWindowObject(hWnd
)))
2924 Status
= MmCopyFromCaller(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
2925 if(!NT_SUCCESS(Status
))
2927 SetLastNtError(Status
);
2930 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
2935 IntGetWindowPlacement(Wnd
, &Safepl
);
2937 Status
= MmCopyToCaller(lpwndpl
, &Safepl
, sizeof(WINDOWPLACEMENT
));
2938 if(!NT_SUCCESS(Status
))
2940 SetLastNtError(Status
);
2947 TRACE("Leave NtUserGetWindowPlacement, ret=%i\n",_ret_
);
2956 UINT cmd
, // Wine SW_ commands
2961 TRACE("Enter NtUserMinMaximize\n");
2962 UserEnterExclusive();
2964 pWnd
= UserGetWindowObject(hWnd
);
2965 if ( !pWnd
|| // FIXME:
2966 pWnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
2967 pWnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
2972 if ( cmd
> SW_MAX
|| pWnd
->state2
& WNDS2_INDESTROY
)
2974 EngSetLastError(ERROR_INVALID_PARAMETER
);
2978 cmd
|= Hide
? SW_HIDE
: 0;
2980 co_WinPosShowWindow(pWnd
, cmd
);
2983 TRACE("Leave NtUserMinMaximize\n");
2985 return 0; // Always NULL?
3000 return NtUserSetWindowPos(hWnd
, 0, X
, Y
, nWidth
, nHeight
,
3001 (bRepaint
? SWP_NOZORDER
| SWP_NOACTIVATE
:
3002 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
));
3009 NtUserRealChildWindowFromPoint(HWND Parent
,
3014 TRACE("Enter NtUserRealChildWindowFromPoint\n");
3016 if ((pwndParent
= UserGetWindowObject(Parent
)))
3018 pwndParent
= IntRealChildWindowFromPoint(pwndParent
, x
, y
);
3021 TRACE("Leave NtUserRealChildWindowFromPoint\n");
3022 return pwndParent
? UserHMGetHandle(pwndParent
) : NULL
;
3031 HWND hWndInsertAfter
,
3038 DECLARE_RETURN(BOOL
);
3039 PWND Window
, pWndIA
;
3041 USER_REFERENCE_ENTRY Ref
;
3043 TRACE("Enter NtUserSetWindowPos\n");
3044 UserEnterExclusive();
3046 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
3047 Window
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3048 Window
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3050 ERR("NtUserSetWindowPos bad window handle!\n");
3054 if ( hWndInsertAfter
&&
3055 hWndInsertAfter
!= HWND_BOTTOM
&&
3056 hWndInsertAfter
!= HWND_TOPMOST
&&
3057 hWndInsertAfter
!= HWND_NOTOPMOST
)
3059 if (!(pWndIA
= UserGetWindowObject(hWndInsertAfter
)) ||
3060 pWndIA
== UserGetDesktopWindow() ||
3061 pWndIA
== UserGetMessageWindow() )
3063 ERR("NtUserSetWindowPos bad insert window handle!\n");
3068 /* First make sure that coordinates are valid for WM_WINDOWPOSCHANGING */
3069 if (!(uFlags
& SWP_NOMOVE
))
3071 if (X
< -32768) X
= -32768;
3072 else if (X
> 32767) X
= 32767;
3073 if (Y
< -32768) Y
= -32768;
3074 else if (Y
> 32767) Y
= 32767;
3076 if (!(uFlags
& SWP_NOSIZE
))
3079 else if (cx
> 32767) cx
= 32767;
3081 else if (cy
> 32767) cy
= 32767;
3084 UserRefObjectCo(Window
, &Ref
);
3085 ret
= co_WinPosSetWindowPos(Window
, hWndInsertAfter
, X
, Y
, cx
, cy
, uFlags
);
3086 UserDerefObjectCo(Window
);
3091 TRACE("Leave NtUserSetWindowPos, ret=%i\n",_ret_
);
3105 HRGN hrgnCopy
= NULL
;
3107 INT flags
= (SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
);
3108 BOOLEAN Ret
= FALSE
;
3109 DECLARE_RETURN(INT
);
3111 TRACE("Enter NtUserSetWindowRgn\n");
3112 UserEnterExclusive();
3114 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
3115 Window
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3116 Window
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3121 if (hRgn
) // The region will be deleted in user32.
3123 if (GreIsHandleValid(hRgn
))
3125 hrgnCopy
= NtGdiCreateRectRgn(0, 0, 0, 0);
3126 /* The coordinates of a window's window region are relative to the
3127 upper-left corner of the window, not the client area of the window. */
3128 NtGdiCombineRgn( hrgnCopy
, hRgn
, 0, RGN_COPY
);
3134 if (Window
->hrgnClip
)
3136 /* Delete no longer needed region handle */
3137 IntGdiSetRegionOwner(Window
->hrgnClip
, GDI_OBJ_HMGR_POWNED
);
3138 GreDeleteObject(Window
->hrgnClip
);
3143 /* Set public ownership */
3144 IntGdiSetRegionOwner(hrgnCopy
, GDI_OBJ_HMGR_PUBLIC
);
3146 Window
->hrgnClip
= hrgnCopy
;
3148 Ret
= co_WinPosSetWindowPos(Window
, HWND_TOP
, 0, 0, 0, 0, bRedraw
? flags
: (flags
|SWP_NOREDRAW
) );
3153 TRACE("Leave NtUserSetWindowRgn, ret=%i\n",_ret_
);
3162 NtUserSetInternalWindowPos(
3168 WINDOWPLACEMENT wndpl
;
3173 DECLARE_RETURN(BOOL
);
3174 USER_REFERENCE_ENTRY Ref
;
3176 TRACE("Enter NtUserSetWindowPlacement\n");
3177 UserEnterExclusive();
3179 if (!(Wnd
= UserGetWindowObject(hwnd
)) || // FIXME:
3180 Wnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3181 Wnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3190 ProbeForRead(lppt
, sizeof(POINT
), 1);
3191 RtlCopyMemory(&pt
, lppt
, sizeof(POINT
));
3195 ProbeForRead(lprect
, sizeof(RECT
), 1);
3196 RtlCopyMemory(&rect
, lprect
, sizeof(RECT
));
3199 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3201 SetLastNtError(_SEH2_GetExceptionCode());
3202 _SEH2_YIELD(RETURN( FALSE
));
3206 wndpl
.length
= sizeof(wndpl
);
3207 wndpl
.showCmd
= showCmd
;
3208 wndpl
.flags
= flags
= 0;
3213 wndpl
.flags
|= WPF_SETMINPOSITION
;
3214 wndpl
.ptMinPosition
= pt
;
3218 flags
|= PLACE_RECT
;
3219 wndpl
.rcNormalPosition
= rect
;
3222 UserRefObjectCo(Wnd
, &Ref
);
3223 IntSetWindowPlacement(Wnd
, &wndpl
, flags
);
3224 UserDerefObjectCo(Wnd
);
3228 TRACE("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_
);
3237 NtUserSetWindowPlacement(HWND hWnd
,
3238 WINDOWPLACEMENT
*lpwndpl
)
3241 WINDOWPLACEMENT Safepl
;
3243 DECLARE_RETURN(BOOL
);
3244 USER_REFERENCE_ENTRY Ref
;
3246 TRACE("Enter NtUserSetWindowPlacement\n");
3247 UserEnterExclusive();
3249 if (!(Wnd
= UserGetWindowObject(hWnd
)) || // FIXME:
3250 Wnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3251 Wnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3258 ProbeForRead(lpwndpl
, sizeof(WINDOWPLACEMENT
), 1);
3259 RtlCopyMemory(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
3261 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3263 SetLastNtError(_SEH2_GetExceptionCode());
3264 _SEH2_YIELD(RETURN( FALSE
));
3268 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
3273 Flags
= PLACE_MAX
| PLACE_RECT
;
3274 if (Safepl
.flags
& WPF_SETMINPOSITION
) Flags
|= PLACE_MIN
;
3275 UserRefObjectCo(Wnd
, &Ref
);
3276 IntSetWindowPlacement(Wnd
, &Safepl
, Flags
);
3277 UserDerefObjectCo(Wnd
);
3281 TRACE("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_
);
3290 NtUserShowWindowAsync(HWND hWnd
, LONG nCmdShow
)
3294 DECLARE_RETURN(BOOL
);
3295 USER_REFERENCE_ENTRY Ref
;
3297 TRACE("Enter NtUserShowWindowAsync\n");
3298 UserEnterExclusive();
3300 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
3301 Window
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3302 Window
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3307 if ( nCmdShow
> SW_MAX
)
3309 EngSetLastError(ERROR_INVALID_PARAMETER
);
3313 UserRefObjectCo(Window
, &Ref
);
3314 ret
= co_IntSendMessageNoWait( hWnd
, WM_ASYNC_SHOWWINDOW
, nCmdShow
, 0 );
3315 UserDerefObjectCo(Window
);
3316 if (-1 == (int) ret
|| !ret
) ret
= FALSE
;
3321 TRACE("Leave NtUserShowWindowAsync, ret=%i\n",_ret_
);
3330 NtUserShowWindow(HWND hWnd
, LONG nCmdShow
)
3334 DECLARE_RETURN(BOOL
);
3335 USER_REFERENCE_ENTRY Ref
;
3337 TRACE("Enter NtUserShowWindow\n");
3338 UserEnterExclusive();
3340 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
3341 Window
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3342 Window
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3347 if ( nCmdShow
> SW_MAX
|| Window
->state2
& WNDS2_INDESTROY
)
3349 EngSetLastError(ERROR_INVALID_PARAMETER
);
3353 UserRefObjectCo(Window
, &Ref
);
3354 ret
= co_WinPosShowWindow(Window
, nCmdShow
);
3355 UserDerefObjectCo(Window
);
3360 TRACE("Leave NtUserShowWindow, ret=%i\n",_ret_
);
3370 NtUserWindowFromPoint(LONG X
, LONG Y
)
3374 PWND DesktopWindow
= NULL
, Window
= NULL
;
3376 DECLARE_RETURN(HWND
);
3377 USER_REFERENCE_ENTRY Ref
;
3379 TRACE("Enter NtUserWindowFromPoint\n");
3380 UserEnterExclusive();
3382 if ((DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow())))
3389 // Hmm... Threads live on desktops thus we have a reference on the desktop and indirectly the desktop window.
3390 // It is possible this referencing is useless, though it should not hurt...
3391 UserRefObjectCo(DesktopWindow
, &Ref
);
3393 //pti = PsGetCurrentThreadWin32Thread();
3394 Window
= co_WinPosWindowFromPoint(DesktopWindow
, &pt
, &hittest
, FALSE
);
3398 Ret
= UserHMGetHandle(Window
);
3407 if (Window
) UserDereferenceObject(Window
);
3408 if (DesktopWindow
) UserDerefObjectCo(DesktopWindow
);
3410 TRACE("Leave NtUserWindowFromPoint, ret=%p\n", _ret_
);