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 TRACE("Sending WM_WINDOWPOSCHANGING to hwnd %p.\n", Window
->head
.h
);
1262 co_IntSendMessageNoWait(Window
->head
.h
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
) WinPos
);
1265 /* Calculate new position and size */
1267 *WindowRect
= Window
->rcWindow
;
1268 *ClientRect
= (Window
->style
& WS_MINIMIZE
) ? Window
->rcWindow
: Window
->rcClient
;
1270 if (!(WinPos
->flags
& SWP_NOSIZE
))
1272 if (Window
->style
& WS_MINIMIZE
)
1274 WindowRect
->right
= WindowRect
->left
+ UserGetSystemMetrics(SM_CXMINIMIZED
);
1275 WindowRect
->bottom
= WindowRect
->top
+ UserGetSystemMetrics(SM_CYMINIMIZED
);
1279 WindowRect
->right
= WindowRect
->left
+ WinPos
->cx
;
1280 WindowRect
->bottom
= WindowRect
->top
+ WinPos
->cy
;
1284 if (!(WinPos
->flags
& SWP_NOMOVE
))
1291 Parent
= Window
->spwndParent
;
1293 if (((Window
->style
& WS_CHILD
) != 0) &&
1295 Parent
!= Window
->head
.rpdesk
->pDeskInfo
->spwnd
)
1297 TRACE("Not SWP_NOMOVE 1 Parent client offset X %d Y %d\n",X
,Y
);
1298 X
+= Parent
->rcClient
.left
;
1299 Y
+= Parent
->rcClient
.top
;
1300 TRACE("Not SWP_NOMOVE 2 Parent client offset X %d Y %d\n",X
,Y
);
1303 WindowRect
->left
= X
;
1304 WindowRect
->top
= Y
;
1305 WindowRect
->right
+= X
- Window
->rcWindow
.left
;
1306 WindowRect
->bottom
+= Y
- Window
->rcWindow
.top
;
1308 RECTL_vOffsetRect(ClientRect
, X
- Window
->rcWindow
.left
,
1309 Y
- Window
->rcWindow
.top
);
1311 WinPos
->flags
|= SWP_NOCLIENTMOVE
| SWP_NOCLIENTSIZE
;
1313 TRACE( "hwnd %p, after %p, swp %d,%d %dx%d flags %08x\n",
1314 WinPos
->hwnd
, WinPos
->hwndInsertAfter
, WinPos
->x
, WinPos
->y
,
1315 WinPos
->cx
, WinPos
->cy
, WinPos
->flags
);
1316 TRACE("WindowRect: %d %d %d %d\n", WindowRect
->left
,WindowRect
->top
,WindowRect
->right
,WindowRect
->bottom
);
1317 TRACE("ClientRect: %d %d %d %d\n", ClientRect
->left
,ClientRect
->top
,ClientRect
->right
,ClientRect
->bottom
);
1323 * Fix Z order taking into account owned popups -
1324 * basically we need to maintain them above the window that owns them
1326 * FIXME: hide/show owned popups when owner visibility changes.
1328 * ReactOS: See bug CORE-6129 and CORE-6554.
1332 // Pass all the win:test_children/popup_zorder tests except "move hwnd_F and its popups down" which is if'ed out.
1333 // Side effect, breaks more of the DeferWindowPos api tests, but wine breaks more!!!!
1336 WinPosDoOwnedPopups(PWND Window
, HWND hWndInsertAfter
)
1341 PWND DesktopWindow
, ChildObject
;
1344 TRACE("(%p) hInsertAfter = %p\n", Window
, hWndInsertAfter
);
1346 Owner
= Window
->spwndOwner
? Window
->spwndOwner
->head
.h
: NULL
;
1347 Style
= Window
->style
;
1349 if (Style
& WS_CHILD
)
1351 TRACE("Window is child\n");
1352 return hWndInsertAfter
;
1357 /* Make sure this popup stays above the owner */
1359 if (hWndInsertAfter
!= HWND_TOPMOST
)
1361 DesktopWindow
= UserGetDesktopWindow();
1362 List
= IntWinListChildren(DesktopWindow
);
1366 for (i
= 0; List
[i
]; i
++)
1368 BOOL topmost
= FALSE
;
1370 ChildObject
= ValidateHwndNoErr(List
[i
]);
1373 topmost
= (ChildObject
->ExStyle
& WS_EX_TOPMOST
) != 0;
1376 if (List
[i
] == Owner
)
1378 if (i
> 0) hWndInsertAfter
= List
[i
-1];
1379 else hWndInsertAfter
= topmost
? HWND_TOPMOST
: HWND_TOP
;
1383 if (hWndInsertAfter
== HWND_TOP
|| hWndInsertAfter
== HWND_NOTOPMOST
)
1385 if (!topmost
) break;
1387 else if (List
[i
] == hWndInsertAfter
) break;
1391 return hWndInsertAfter
;
1395 if (hWndInsertAfter
== HWND_BOTTOM
)
1397 ERR("Window is HWND_BOTTOM\n");
1398 if (List
) ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1404 DesktopWindow
= UserGetDesktopWindow();
1405 List
= IntWinListChildren(DesktopWindow
);
1412 if (hWndInsertAfter
== HWND_TOP
|| hWndInsertAfter
== HWND_NOTOPMOST
)
1414 if (hWndInsertAfter
== HWND_NOTOPMOST
|| !(Window
->ExStyle
& WS_EX_TOPMOST
))
1416 TRACE("skip all the topmost windows\n");
1417 /* skip all the topmost windows */
1419 (ChildObject
= ValidateHwndNoErr(List
[i
])) &&
1420 (ChildObject
->ExStyle
& WS_EX_TOPMOST
)) i
++;
1423 else if (hWndInsertAfter
!= HWND_TOPMOST
)
1425 /* skip windows that are already placed correctly */
1426 for (i
= 0; List
[i
]; i
++)
1428 if (List
[i
] == hWndInsertAfter
) break;
1429 if (List
[i
] == UserHMGetHandle(Window
))
1431 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1432 goto done
; /* nothing to do if window is moving backwards in z-order */
1437 for (; List
[i
]; i
++)
1440 USER_REFERENCE_ENTRY Ref
;
1442 if (List
[i
] == UserHMGetHandle(Window
))
1445 if (!(Wnd
= ValidateHwndNoErr(List
[i
])))
1448 Owner
= Wnd
->spwndOwner
? Wnd
->spwndOwner
->head
.h
: NULL
;
1450 if (Owner
!= UserHMGetHandle(Window
)) continue;
1452 UserRefObjectCo(Wnd
, &Ref
);
1453 TRACE( "moving %p owned by %p after %p\n", List
[i
], UserHMGetHandle(Window
), hWndInsertAfter
);
1454 co_WinPosSetWindowPos(Wnd
, hWndInsertAfter
, 0, 0, 0, 0,
1455 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOSENDCHANGING
| SWP_DEFERERASE
);
1457 UserDerefObjectCo(Wnd
);
1458 hWndInsertAfter
= List
[i
];
1460 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1463 return hWndInsertAfter
;
1467 /***********************************************************************
1468 * WinPosInternalMoveWindow
1470 * Update WindowRect and ClientRect of Window and all of its children
1471 * We keep both WindowRect and ClientRect in screen coordinates internally
1475 WinPosInternalMoveWindow(PWND Window
, INT MoveX
, INT MoveY
)
1479 ASSERT(Window
!= Window
->spwndChild
);
1480 TRACE("InternalMoveWin X %d Y %d\n", MoveX
, MoveY
);
1482 Window
->rcWindow
.left
+= MoveX
;
1483 Window
->rcWindow
.right
+= MoveX
;
1484 Window
->rcWindow
.top
+= MoveY
;
1485 Window
->rcWindow
.bottom
+= MoveY
;
1487 Window
->rcClient
.left
+= MoveX
;
1488 Window
->rcClient
.right
+= MoveX
;
1489 Window
->rcClient
.top
+= MoveY
;
1490 Window
->rcClient
.bottom
+= MoveY
;
1492 for(Child
= Window
->spwndChild
; Child
; Child
= Child
->spwndNext
)
1494 WinPosInternalMoveWindow(Child
, MoveX
, MoveY
);
1499 * WinPosFixupSWPFlags
1501 * Fix redundant flags and values in the WINDOWPOS structure.
1505 WinPosFixupFlags(WINDOWPOS
*WinPos
, PWND Wnd
)
1510 /* Finally make sure that all coordinates are valid */
1511 if (WinPos
->x
< -32768) WinPos
->x
= -32768;
1512 else if (WinPos
->x
> 32767) WinPos
->x
= 32767;
1513 if (WinPos
->y
< -32768) WinPos
->y
= -32768;
1514 else if (WinPos
->y
> 32767) WinPos
->y
= 32767;
1516 WinPos
->cx
= max(WinPos
->cx
, 0);
1517 WinPos
->cy
= max(WinPos
->cy
, 0);
1519 Parent
= UserGetAncestor( Wnd
, GA_PARENT
);
1520 if (!IntIsWindowVisible( Parent
)) WinPos
->flags
|= SWP_NOREDRAW
;
1522 if (Wnd
->style
& WS_VISIBLE
) WinPos
->flags
&= ~SWP_SHOWWINDOW
;
1525 WinPos
->flags
&= ~SWP_HIDEWINDOW
;
1526 if (!(WinPos
->flags
& SWP_SHOWWINDOW
)) WinPos
->flags
|= SWP_NOREDRAW
;
1529 /* Check for right size */
1530 if (Wnd
->rcWindow
.right
- Wnd
->rcWindow
.left
== WinPos
->cx
&&
1531 Wnd
->rcWindow
.bottom
- Wnd
->rcWindow
.top
== WinPos
->cy
)
1533 WinPos
->flags
|= SWP_NOSIZE
;
1538 IntClientToScreen( Parent
, &pt
);
1539 TRACE("WPFU C2S wpx %d wpy %d ptx %d pty %d\n",WinPos
->x
,WinPos
->y
,pt
.x
,pt
.y
);
1540 /* Check for right position */
1541 if (Wnd
->rcWindow
.left
== pt
.x
&& Wnd
->rcWindow
.top
== pt
.y
)
1543 //ERR("In right pos\n");
1544 WinPos
->flags
|= SWP_NOMOVE
;
1547 if (WinPos
->hwnd
!= UserGetForegroundWindow() && (Wnd
->style
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)
1549 /* Bring to the top when activating */
1550 if (!(WinPos
->flags
& (SWP_NOACTIVATE
|SWP_HIDEWINDOW
)) &&
1551 (WinPos
->flags
& SWP_NOZORDER
||
1552 (WinPos
->hwndInsertAfter
!= HWND_TOPMOST
&& WinPos
->hwndInsertAfter
!= HWND_NOTOPMOST
)))
1554 WinPos
->flags
&= ~SWP_NOZORDER
;
1555 WinPos
->hwndInsertAfter
= (0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
) ? HWND_TOPMOST
: HWND_TOP
);
1559 /* Check hwndInsertAfter */
1560 if (!(WinPos
->flags
& SWP_NOZORDER
))
1562 /* Fix sign extension */
1563 if (WinPos
->hwndInsertAfter
== (HWND
)0xffff)
1565 WinPos
->hwndInsertAfter
= HWND_TOPMOST
;
1567 else if (WinPos
->hwndInsertAfter
== (HWND
)0xfffe)
1569 WinPos
->hwndInsertAfter
= HWND_NOTOPMOST
;
1572 if (WinPos
->hwndInsertAfter
== HWND_TOP
)
1574 /* Keep it topmost when it's already topmost */
1575 if ((Wnd
->ExStyle
& WS_EX_TOPMOST
) != 0)
1576 WinPos
->hwndInsertAfter
= HWND_TOPMOST
;
1578 if (IntGetWindow(WinPos
->hwnd
, GW_HWNDFIRST
) == WinPos
->hwnd
)
1579 WinPos
->flags
|= SWP_NOZORDER
;
1581 else if (WinPos
->hwndInsertAfter
== HWND_BOTTOM
)
1583 if (!(Wnd
->ExStyle
& WS_EX_TOPMOST
) && IntGetWindow(WinPos
->hwnd
, GW_HWNDLAST
) == WinPos
->hwnd
)
1584 WinPos
->flags
|= SWP_NOZORDER
;
1586 else if (WinPos
->hwndInsertAfter
== HWND_TOPMOST
)
1588 if ((Wnd
->ExStyle
& WS_EX_TOPMOST
) && IntGetWindow(WinPos
->hwnd
, GW_HWNDFIRST
) == WinPos
->hwnd
)
1589 WinPos
->flags
|= SWP_NOZORDER
;
1591 else if (WinPos
->hwndInsertAfter
== HWND_NOTOPMOST
)
1593 if (!(Wnd
->ExStyle
& WS_EX_TOPMOST
))
1594 WinPos
->flags
|= SWP_NOZORDER
;
1596 else /* hwndInsertAfter must be a sibling of the window */
1600 InsAfterWnd
= ValidateHwndNoErr(WinPos
->hwndInsertAfter
);
1606 if (InsAfterWnd
->spwndParent
!= Wnd
->spwndParent
)
1608 /* Note from wine User32 Win test_SetWindowPos:
1609 "Returns TRUE also for windows that are not siblings"
1610 "Does not seem to do anything even without passing flags, still returns TRUE"
1611 "Same thing the other way around."
1612 ".. and with these windows."
1619 * We don't need to change the Z order of hwnd if it's already
1620 * inserted after hwndInsertAfter or when inserting hwnd after
1623 if ((WinPos
->hwnd
== WinPos
->hwndInsertAfter
) ||
1624 ((InsAfterWnd
->spwndNext
) && (WinPos
->hwnd
== InsAfterWnd
->spwndNext
->head
.h
)))
1626 WinPos
->flags
|= SWP_NOZORDER
;
1635 /* x and y are always screen relative */
1637 co_WinPosSetWindowPos(
1639 HWND WndInsertAfter
,
1648 RECTL NewWindowRect
;
1649 RECTL NewClientRect
;
1650 RECTL valid_rects
[2];
1651 PREGION VisBefore
= NULL
;
1652 PREGION VisBeforeJustClient
= NULL
;
1653 PREGION VisAfter
= NULL
;
1654 PREGION CopyRgn
= NULL
;
1656 RECTL OldWindowRect
, OldClientRect
;
1661 BOOL bPointerInWindow
;
1663 ASSERT_REFS_CO(Window
);
1665 /* FIXME: Get current active window from active queue. Why? since r2915. */
1667 bPointerInWindow
= IntPtInWindow(Window
, gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
);
1669 WinPos
.hwnd
= Window
->head
.h
;
1670 WinPos
.hwndInsertAfter
= WndInsertAfter
;
1675 WinPos
.flags
= flags
;
1677 if ( flags
& SWP_ASYNCWINDOWPOS
)
1680 PWINDOWPOS ppos
= ExAllocatePoolWithTag(PagedPool
, sizeof(WINDOWPOS
), USERTAG_SWP
);
1683 WinPos
.flags
&= ~SWP_ASYNCWINDOWPOS
; // Clear flag.
1685 /* Yes it's a pointer inside Win32k! */
1686 lRes
= co_IntSendMessageNoWait( WinPos
.hwnd
, WM_ASYNC_SETWINDOWPOS
, 0, (LPARAM
)ppos
);
1687 /* We handle this the same way as Event Hooks and Hooks. */
1690 ExFreePoolWithTag(ppos
, USERTAG_SWP
);
1698 co_WinPosDoWinPosChanging(Window
, &WinPos
, &NewWindowRect
, &NewClientRect
);
1700 /* Does the window still exist? */
1701 if (!IntIsWindow(WinPos
.hwnd
))
1703 TRACE("WinPosSetWindowPos: Invalid handle 0x%p!\n",WinPos
.hwnd
);
1704 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE
);
1708 /* Fix up the flags. */
1709 if (!WinPosFixupFlags(&WinPos
, Window
))
1715 Ancestor
= UserGetAncestor(Window
, GA_PARENT
);
1716 if ( (WinPos
.flags
& (SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) != SWP_NOZORDER
&&
1717 Ancestor
&& Ancestor
->head
.h
== IntGetDesktopWindow() )
1719 WinPos
.hwndInsertAfter
= WinPosDoOwnedPopups(Window
, WinPos
.hwndInsertAfter
);
1722 if (!(WinPos
.flags
& SWP_NOREDRAW
))
1724 /* Compute the visible region before the window position is changed */
1725 if (!(WinPos
.flags
& SWP_SHOWWINDOW
) &&
1726 (WinPos
.flags
& (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
|
1727 SWP_HIDEWINDOW
| SWP_FRAMECHANGED
)) !=
1728 (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
))
1730 VisBefore
= VIS_ComputeVisibleRegion(Window
, FALSE
, FALSE
,
1731 (Window
->style
& WS_CLIPSIBLINGS
) ? TRUE
: FALSE
);
1733 if ( VisBefore
!= NULL
&&
1734 REGION_Complexity(VisBefore
) == NULLREGION
)
1736 REGION_Delete(VisBefore
);
1741 IntGdiOffsetRgn(VisBefore
, -Window
->rcWindow
.left
, -Window
->rcWindow
.top
);
1744 /* Calculate the non client area for resizes, as this is used in the copy region */
1745 if (!(WinPos
.flags
& SWP_NOSIZE
))
1747 VisBeforeJustClient
= VIS_ComputeVisibleRegion(Window
, TRUE
, FALSE
,
1748 (Window
->style
& WS_CLIPSIBLINGS
) ? TRUE
: FALSE
);
1750 if ( VisBeforeJustClient
!= NULL
&&
1751 REGION_Complexity(VisBeforeJustClient
) == NULLREGION
)
1753 REGION_Delete(VisBeforeJustClient
);
1754 VisBeforeJustClient
= NULL
;
1756 else if(VisBeforeJustClient
)
1758 IntGdiOffsetRgn(VisBeforeJustClient
, -Window
->rcWindow
.left
, -Window
->rcWindow
.top
);
1764 WvrFlags
= co_WinPosDoNCCALCSize(Window
, &WinPos
, &NewWindowRect
, &NewClientRect
, valid_rects
);
1766 // ERR("co_WinPosDoNCCALCSize returned 0x%x\n valid dest: %d %d %d %d\n valid src : %d %d %d %d\n", WvrFlags,
1767 // valid_rects[0].left,valid_rects[0].top,valid_rects[0].right,valid_rects[0].bottom,
1768 // valid_rects[1].left,valid_rects[1].top,valid_rects[1].right,valid_rects[1].bottom);
1770 /* Validate link windows. (also take into account shell window in hwndShellWindow) */
1771 if (!(WinPos
.flags
& SWP_NOZORDER
) && WinPos
.hwnd
!= UserGetShellWindow())
1773 IntLinkHwnd(Window
, WinPos
.hwndInsertAfter
);
1776 OldWindowRect
= Window
->rcWindow
;
1777 OldClientRect
= Window
->rcClient
;
1779 if (NewClientRect
.left
!= OldClientRect
.left
||
1780 NewClientRect
.top
!= OldClientRect
.top
)
1782 // Move child window if their parent is moved. Keep Child window relative to Parent...
1783 WinPosInternalMoveWindow(Window
,
1784 NewClientRect
.left
- OldClientRect
.left
,
1785 NewClientRect
.top
- OldClientRect
.top
);
1788 Window
->rcWindow
= NewWindowRect
;
1789 Window
->rcClient
= NewClientRect
;
1791 /* erase parent when hiding or resizing child */
1792 if (WinPos
.flags
& SWP_HIDEWINDOW
)
1794 /* Clear the update region */
1795 co_UserRedrawWindow( Window
,
1798 RDW_VALIDATE
| RDW_NOFRAME
| RDW_NOERASE
| RDW_NOINTERNALPAINT
| RDW_ALLCHILDREN
);
1800 if (Window
->spwndParent
== UserGetDesktopWindow())
1801 co_IntShellHookNotify(HSHELL_WINDOWDESTROYED
, (WPARAM
)Window
->head
.h
, 0);
1803 Window
->style
&= ~WS_VISIBLE
; //IntSetStyle( Window, 0, WS_VISIBLE );
1804 Window
->head
.pti
->cVisWindows
--;
1805 IntNotifyWinEvent(EVENT_OBJECT_HIDE
, Window
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
1807 else if (WinPos
.flags
& SWP_SHOWWINDOW
)
1809 if (Window
->spwndParent
== UserGetDesktopWindow() &&
1810 Window
->spwndOwner
== NULL
&&
1811 (!(Window
->ExStyle
& WS_EX_TOOLWINDOW
) ||
1812 (Window
->ExStyle
& WS_EX_APPWINDOW
)))
1813 co_IntShellHookNotify(HSHELL_WINDOWCREATED
, (WPARAM
)Window
->head
.h
, 0);
1815 Window
->style
|= WS_VISIBLE
; //IntSetStyle( Window, WS_VISIBLE, 0 );
1816 Window
->head
.pti
->cVisWindows
++;
1817 IntNotifyWinEvent(EVENT_OBJECT_SHOW
, Window
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
1820 if (Window
->hrgnUpdate
!= NULL
&& Window
->hrgnUpdate
!= HRGN_WINDOW
)
1822 NtGdiOffsetRgn(Window
->hrgnUpdate
,
1823 NewWindowRect
.left
- OldWindowRect
.left
,
1824 NewWindowRect
.top
- OldWindowRect
.top
);
1827 DceResetActiveDCEs(Window
); // For WS_VISIBLE changes.
1829 if (!(WinPos
.flags
& SWP_NOREDRAW
))
1831 /* Determine the new visible region */
1832 VisAfter
= VIS_ComputeVisibleRegion(Window
, FALSE
, FALSE
,
1833 (Window
->style
& WS_CLIPSIBLINGS
) ? TRUE
: FALSE
);
1835 if ( VisAfter
!= NULL
&&
1836 REGION_Complexity(VisAfter
) == NULLREGION
)
1838 REGION_Delete(VisAfter
);
1843 IntGdiOffsetRgn(VisAfter
, -Window
->rcWindow
.left
, -Window
->rcWindow
.top
);
1847 * Determine which pixels can be copied from the old window position
1848 * to the new. Those pixels must be visible in both the old and new
1849 * position. Also, check the class style to see if the windows of this
1850 * class need to be completely repainted on (horizontal/vertical) size
1853 if ( VisBefore
!= NULL
&&
1855 !(WinPos
.flags
& SWP_NOCOPYBITS
) &&
1856 ((WinPos
.flags
& SWP_NOSIZE
) || !(WvrFlags
& WVR_REDRAW
)) &&
1857 !(Window
->ExStyle
& WS_EX_TRANSPARENT
) )
1861 * If this is (also) a window resize, the whole nonclient area
1862 * needs to be repainted. So we limit the copy to the client area,
1863 * 'cause there is no use in copying it (would possibly cause
1864 * "flashing" too). However, if the copy region is already empty,
1865 * we don't have to crop (can't take anything away from an empty
1869 CopyRgn
= IntSysCreateRectpRgn(0, 0, 0, 0);
1870 if (WinPos
.flags
& SWP_NOSIZE
)
1871 RgnType
= IntGdiCombineRgn(CopyRgn
, VisAfter
, VisBefore
, RGN_AND
);
1872 else if (VisBeforeJustClient
!= NULL
)
1874 RgnType
= IntGdiCombineRgn(CopyRgn
, VisAfter
, VisBeforeJustClient
, RGN_AND
);
1875 REGION_Delete(VisBeforeJustClient
);
1878 /* No use in copying bits which are in the update region. */
1879 if (Window
->hrgnUpdate
!= NULL
)
1881 PREGION RgnUpdate
= RGNOBJAPI_Lock(Window
->hrgnUpdate
, NULL
);
1884 IntGdiOffsetRgn(CopyRgn
, NewWindowRect
.left
, NewWindowRect
.top
);
1885 IntGdiCombineRgn(CopyRgn
, CopyRgn
, RgnUpdate
, RGN_DIFF
);
1886 IntGdiOffsetRgn(CopyRgn
, -NewWindowRect
.left
, -NewWindowRect
.top
);
1887 RGNOBJAPI_Unlock(RgnUpdate
);
1892 * Now, get the bounding box of the copy region. If it's empty
1893 * there's nothing to copy. Also, it's no use copying bits onto
1896 if (REGION_GetRgnBox(CopyRgn
, &CopyRect
) == NULLREGION
)
1898 /* Nothing to copy, clean up */
1899 REGION_Delete(CopyRgn
);
1902 else if (OldWindowRect
.left
!= NewWindowRect
.left
||
1903 OldWindowRect
.top
!= NewWindowRect
.top
)
1905 HRGN DcRgn
= NtGdiCreateRectRgn(0, 0, 0, 0);
1906 PREGION DcRgnObj
= RGNOBJAPI_Lock(DcRgn
, NULL
);
1909 * Small trick here: there is no function to bitblt a region. So
1910 * we set the region as the clipping region, take the bounding box
1911 * of the region and bitblt that. Since nothing outside the clipping
1912 * region is copied, this has the effect of bitblt'ing the region.
1914 * Since NtUserGetDCEx takes ownership of the clip region, we need
1915 * to create a copy of CopyRgn and pass that. We need CopyRgn later
1917 IntGdiCombineRgn(DcRgnObj
, CopyRgn
, NULL
, RGN_COPY
);
1918 IntGdiOffsetRgn(DcRgnObj
, NewWindowRect
.left
, NewWindowRect
.top
);
1919 RGNOBJAPI_Unlock(DcRgnObj
);
1920 Dc
= UserGetDCEx( Window
,
1922 DCX_WINDOW
|DCX_CACHE
|DCX_INTERSECTRGN
|DCX_CLIPSIBLINGS
|DCX_KEEPCLIPRGN
);
1924 CopyRect
.left
, CopyRect
.top
,
1925 CopyRect
.right
- CopyRect
.left
,
1926 CopyRect
.bottom
- CopyRect
.top
,
1928 CopyRect
.left
+ (OldWindowRect
.left
- NewWindowRect
.left
),
1929 CopyRect
.top
+ (OldWindowRect
.top
- NewWindowRect
.top
),
1934 UserReleaseDC(Window
, Dc
, FALSE
);
1935 IntValidateParent(Window
, CopyRgn
, FALSE
);
1936 GreDeleteObject(DcRgn
);
1944 /* We need to redraw what wasn't visible before */
1945 if (VisAfter
!= NULL
)
1947 PREGION DirtyRgn
= IntSysCreateRectpRgn(0, 0, 0, 0);
1950 if (CopyRgn
!= NULL
)
1952 RgnType
= IntGdiCombineRgn(DirtyRgn
, VisAfter
, CopyRgn
, RGN_DIFF
);
1956 RgnType
= IntGdiCombineRgn(DirtyRgn
, VisAfter
, 0, RGN_COPY
);
1958 if (RgnType
!= ERROR
&& RgnType
!= NULLREGION
)
1961 NtGdiOffsetRgn(DirtyRgn, Window->rcWindow.left, Window->rcWindow.top);
1962 IntInvalidateWindows( Window,
1964 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
1966 GreDeleteObject(DirtyRgn);
1969 PWND Parent
= Window
->spwndParent
;
1971 IntGdiOffsetRgn( DirtyRgn
,
1972 Window
->rcWindow
.left
,
1973 Window
->rcWindow
.top
);
1974 if ( (Window
->style
& WS_CHILD
) &&
1976 !(Parent
->style
& WS_CLIPCHILDREN
))
1978 IntInvalidateWindows( Parent
,
1980 RDW_ERASE
| RDW_INVALIDATE
);
1981 co_IntPaintWindows(Parent
, RDW_ERASENOW
, FALSE
);
1985 IntInvalidateWindows( Window
,
1987 RDW_ERASE
| RDW_FRAME
| RDW_INVALIDATE
| RDW_ALLCHILDREN
);
1990 REGION_Delete(DirtyRgn
);
1994 if (CopyRgn
!= NULL
)
1996 REGION_Delete(CopyRgn
);
1999 /* Expose what was covered before but not covered anymore */
2000 if (VisBefore
!= NULL
)
2002 PREGION ExposedRgn
= IntSysCreateRectpRgn(0, 0, 0, 0);
2005 RgnType
= IntGdiCombineRgn(ExposedRgn
, VisBefore
, NULL
, RGN_COPY
);
2006 IntGdiOffsetRgn( ExposedRgn
,
2007 OldWindowRect
.left
- NewWindowRect
.left
,
2008 OldWindowRect
.top
- NewWindowRect
.top
);
2010 if (VisAfter
!= NULL
)
2011 RgnType
= IntGdiCombineRgn(ExposedRgn
, ExposedRgn
, VisAfter
, RGN_DIFF
);
2013 if (RgnType
!= ERROR
&& RgnType
!= NULLREGION
)
2015 co_VIS_WindowLayoutChanged(Window
, ExposedRgn
);
2017 REGION_Delete(ExposedRgn
);
2019 REGION_Delete(VisBefore
);
2022 if (VisAfter
!= NULL
)
2024 REGION_Delete(VisAfter
);
2028 if (!(WinPos
.flags
& (SWP_NOACTIVATE
|SWP_HIDEWINDOW
)))
2030 if ((Window
->style
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
2032 co_IntSendMessageNoWait(WinPos
.hwnd
, WM_CHILDACTIVATE
, 0, 0);
2036 //ERR("SetWindowPos Set FG Window!\n");
2037 if (Window
->state
& WNDS_BEINGACTIVATED
) // Inside SAW?
2038 co_IntSetActiveWindow(Window
, FALSE
, TRUE
, FALSE
); // Fixes Api AttachThreadInput tests.
2040 co_IntSetForegroundWindow(Window
); // Fixes SW_HIDE issues. Wine win test_SetActiveWindow & test_SetForegroundWindow.
2044 /* And last, send the WM_WINDOWPOSCHANGED message */
2046 TRACE("\tstatus flags = %04x\n", WinPos
.flags
& SWP_AGG_STATUSFLAGS
);
2048 if ((WinPos
.flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOPOSCHANGE
)
2050 /* WM_WINDOWPOSCHANGED is sent even if SWP_NOSENDCHANGING is set
2051 and always contains final window position.
2053 WinPos
.x
= NewWindowRect
.left
;
2054 WinPos
.y
= NewWindowRect
.top
;
2055 WinPos
.cx
= NewWindowRect
.right
- NewWindowRect
.left
;
2056 WinPos
.cy
= NewWindowRect
.bottom
- NewWindowRect
.top
;
2057 co_IntSendMessageNoWait(WinPos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
) &WinPos
);
2060 if ( WinPos
.flags
& SWP_FRAMECHANGED
|| WinPos
.flags
& SWP_STATECHANGED
||
2061 !(WinPos
.flags
& SWP_NOCLIENTSIZE
) || !(WinPos
.flags
& SWP_NOCLIENTMOVE
) )
2063 PWND pWnd
= ValidateHwndNoErr(WinPos
.hwnd
);
2065 IntNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE
, pWnd
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
2068 if(bPointerInWindow
!= IntPtInWindow(Window
, gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
))
2070 /* Generate mouse move message */
2072 msg
.message
= WM_MOUSEMOVE
;
2073 msg
.wParam
= UserGetMouseButtonsState();
2074 msg
.lParam
= MAKELPARAM(gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
);
2075 msg
.pt
= gpsi
->ptCursor
;
2076 co_MsqInsertMouseMessage(&msg
, 0, 0, TRUE
);
2083 co_WinPosGetNonClientSize(PWND Window
, RECT
* WindowRect
, RECT
* ClientRect
)
2087 ASSERT_REFS_CO(Window
);
2089 *ClientRect
= *WindowRect
;
2090 Result
= co_IntSendMessageNoWait(Window
->head
.h
, WM_NCCALCSIZE
, FALSE
, (LPARAM
) ClientRect
);
2092 FixClientRect(ClientRect
, WindowRect
);
2098 co_WinPosSendSizeMove(PWND Wnd
)
2102 WPARAM wParam
= SIZE_RESTORED
;
2104 IntGetClientRect(Wnd
, &Rect
);
2105 lParam
= MAKELONG(Rect
.right
-Rect
.left
, Rect
.bottom
-Rect
.top
);
2107 Wnd
->state
&= ~WNDS_SENDSIZEMOVEMSGS
;
2109 if (Wnd
->style
& WS_MAXIMIZE
)
2111 wParam
= SIZE_MAXIMIZED
;
2113 else if (Wnd
->style
& WS_MINIMIZE
)
2115 wParam
= SIZE_MINIMIZED
;
2119 co_IntSendMessageNoWait(UserHMGetHandle(Wnd
), WM_SIZE
, wParam
, lParam
);
2121 if (Wnd
->spwndParent
== UserGetDesktopWindow()) // Wnd->spwndParent->fnid == FNID_DESKTOP )
2122 lParam
= MAKELONG(Wnd
->rcClient
.left
, Wnd
->rcClient
.top
);
2124 lParam
= MAKELONG(Wnd
->rcClient
.left
-Wnd
->spwndParent
->rcClient
.left
, Wnd
->rcClient
.top
-Wnd
->spwndParent
->rcClient
.top
);
2126 co_IntSendMessageNoWait(UserHMGetHandle(Wnd
), WM_MOVE
, 0, lParam
);
2128 IntEngWindowChanged(Wnd
, WOC_RGN_CLIENT
);
2132 co_WinPosShowWindow(PWND Wnd
, INT Cmd
)
2135 UINT Swp
= 0, EventMsg
= 0;
2136 RECTL NewPos
= {0, 0, 0, 0};
2142 BOOL ShowOwned
= FALSE
;
2143 ASSERT_REFS_CO(Wnd
);
2144 //ERR("co_WinPosShowWindow START\n");
2146 pti
= PsGetCurrentThreadWin32Thread();
2147 WasVisible
= (Wnd
->style
& WS_VISIBLE
) != 0;
2156 //ERR("co_WinPosShowWindow Exit Bad\n");
2159 Swp
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
2160 if (Wnd
!= pti
->MessageQueue
->spwndActive
)
2161 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2165 case SW_FORCEMINIMIZE
: /* FIXME: Does not work if thread is hung. */
2166 case SW_SHOWMINNOACTIVE
:
2167 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2169 case SW_SHOWMINIMIZED
:
2170 Swp
|= SWP_SHOWWINDOW
;
2174 Swp
|= SWP_NOACTIVATE
;
2175 if (!(style
& WS_MINIMIZE
))
2177 IntShowOwnedPopups(Wnd
, FALSE
);
2179 // Fix wine Win test_SetFocus todo #1 & #2,
2180 if (Cmd
== SW_SHOWMINIMIZED
)
2182 //ERR("co_WinPosShowWindow Set focus 1\n");
2183 if ((style
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
2184 co_UserSetFocus(Wnd
->spwndParent
);
2189 Swp
|= co_WinPosMinMaximize(Wnd
, Cmd
, &NewPos
) |
2192 EventMsg
= EVENT_SYSTEM_MINIMIZESTART
;
2198 Swp
|= SWP_FRAMECHANGED
;
2202 //ERR("co_WinPosShowWindow Exit Good\n");
2205 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
2210 case SW_SHOWMAXIMIZED
:
2212 Swp
|= SWP_SHOWWINDOW
;
2213 if (!(style
& WS_MAXIMIZE
))
2217 Swp
|= co_WinPosMinMaximize(Wnd
, SW_MAXIMIZE
, &NewPos
) |
2220 EventMsg
= EVENT_SYSTEM_MINIMIZEEND
;
2226 Swp
|= SWP_FRAMECHANGED
;
2230 //ERR("co_WinPosShowWindow Exit Good 1\n");
2233 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
2239 Swp
|= SWP_NOACTIVATE
| SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
2240 if (style
& WS_CHILD
&& !(Wnd
->ExStyle
& WS_EX_MDICHILD
)) Swp
|= SWP_NOZORDER
;
2243 if (WasVisible
) return(TRUE
); // Nothing to do!
2244 Swp
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
2245 /* Don't activate the topmost window. */
2246 if (style
& WS_CHILD
&& !(Wnd
->ExStyle
& WS_EX_MDICHILD
)) Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2249 case SW_SHOWNOACTIVATE
:
2250 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2253 case SW_SHOWDEFAULT
:
2255 if (!WasVisible
) Swp
|= SWP_SHOWWINDOW
;
2256 if (style
& (WS_MINIMIZE
| WS_MAXIMIZE
))
2258 Swp
|= co_WinPosMinMaximize(Wnd
, Cmd
, &NewPos
) |
2261 if (style
& WS_MINIMIZE
) EventMsg
= EVENT_SYSTEM_MINIMIZEEND
;
2267 Swp
|= SWP_FRAMECHANGED
;
2271 //ERR("co_WinPosShowWindow Exit Good 3\n");
2274 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
2276 if ( style
& WS_CHILD
&&
2277 !(Wnd
->ExStyle
& WS_EX_MDICHILD
) &&
2278 !(Swp
& SWP_STATECHANGED
))
2279 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2283 //ERR("co_WinPosShowWindow Exit Good 4\n");
2287 ShowFlag
= (Cmd
!= SW_HIDE
);
2289 if ((ShowFlag
!= WasVisible
|| Cmd
== SW_SHOWNA
) && Cmd
!= SW_SHOWMAXIMIZED
&& !(Swp
& SWP_STATECHANGED
))
2291 co_IntSendMessageNoWait(Wnd
->head
.h
, WM_SHOWWINDOW
, ShowFlag
, 0);
2292 if (!(Wnd
->state2
& WNDS2_WIN31COMPAT
))
2293 co_IntSendMessageNoWait(Wnd
->head
.h
, WM_SETVISIBLE
, ShowFlag
, 0);
2294 if (!VerifyWnd(Wnd
)) return WasVisible
;
2297 /* We can't activate a child window */
2298 if ((Wnd
->style
& WS_CHILD
) &&
2299 !(Wnd
->ExStyle
& WS_EX_MDICHILD
) &&
2302 //ERR("SWP Child No active and ZOrder\n");
2303 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2306 #if 0 // Explorer issues with common controls? Someone does not know how CS_SAVEBITS works.
2307 // Breaks startup and shutdown active window...
2308 if ((Wnd
->style
& (WS_POPUP
|WS_CHILD
)) != WS_CHILD
&&
2309 Wnd
->pcls
->style
& CS_SAVEBITS
&&
2310 ((Cmd
== SW_SHOW
) || (Cmd
== SW_NORMAL
)))
2312 ERR("WinPosShowWindow Set active\n");
2313 UserSetActiveWindow(Wnd
);
2314 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2318 if (IsChildVisible(Wnd
) || Swp
& SWP_STATECHANGED
)
2320 TRACE("Child is Vis %s or State changed %s. ShowFlag %s\n",
2321 (IsChildVisible(Wnd
) ? "TRUE" : "FALSE"), (Swp
& SWP_STATECHANGED
? "TRUE" : "FALSE"),
2322 (ShowFlag
? "TRUE" : "FALSE"));
2323 co_WinPosSetWindowPos( Wnd
,
2324 0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
) ? HWND_TOPMOST
: HWND_TOP
,
2327 NewPos
.right
, //NewPos.right - NewPos.left,
2328 NewPos
.bottom
, //NewPos.bottom - NewPos.top,
2333 TRACE("Parent Vis?\n");
2334 /* if parent is not visible simply toggle WS_VISIBLE and return */
2335 if (ShowFlag
) IntSetStyle( Wnd
, WS_VISIBLE
, 0 );
2336 else IntSetStyle( Wnd
, 0, WS_VISIBLE
);
2339 if ( EventMsg
) IntNotifyWinEvent(EventMsg
, Wnd
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
2341 if ( ShowOwned
) IntShowOwnedPopups(Wnd
, TRUE
);
2343 if ((Cmd
== SW_HIDE
) || (Cmd
== SW_MINIMIZE
))
2345 if ( Wnd
== pti
->MessageQueue
->spwndActive
&& pti
->MessageQueue
== IntGetFocusMessageQueue() )
2347 if ( Wnd
->spwndParent
== UserGetDesktopWindow())
2349 if(!ActivateOtherWindowMin(Wnd
))
2350 co_WinPosActivateOtherWindow(Wnd
);
2353 co_WinPosActivateOtherWindow(Wnd
);
2356 /* Revert focus to parent */
2357 if (Wnd
== pti
->MessageQueue
->spwndFocus
)
2359 Parent
= Wnd
->spwndParent
;
2360 if (Wnd
->spwndParent
== UserGetDesktopWindow()) Parent
= 0;
2361 co_UserSetFocus(Parent
);
2365 /* FIXME: Check for window destruction. */
2367 if ((Wnd
->state
& WNDS_SENDSIZEMOVEMSGS
) &&
2368 !(Wnd
->state2
& WNDS2_INDESTROY
))
2370 co_WinPosSendSizeMove(Wnd
);
2373 /* if previous state was minimized Windows sets focus to the window */
2374 if (style
& WS_MINIMIZE
)
2376 co_UserSetFocus(Wnd
);
2377 // Fix wine Win test_SetFocus todo #3,
2378 if (!(style
& WS_CHILD
)) co_IntSendMessageNoWait(UserHMGetHandle(Wnd
), WM_ACTIVATE
, WA_ACTIVE
, 0);
2380 //ERR("co_WinPosShowWindow EXIT\n");
2386 co_WinPosSearchChildren(
2396 if (!(ScopeWin
->style
& WS_VISIBLE
))
2401 if (!Ignore
&& (ScopeWin
->style
& WS_DISABLED
))
2406 if (!IntPtInWindow(ScopeWin
, Point
->x
, Point
->y
))
2411 UserReferenceObject(ScopeWin
);
2413 if ( RECTL_bPointInRect(&ScopeWin
->rcClient
, Point
->x
, Point
->y
) )
2415 List
= IntWinListChildren(ScopeWin
);
2418 for (phWnd
= List
; *phWnd
; ++phWnd
)
2420 if (!(pwndChild
= ValidateHwndNoErr(*phWnd
)))
2425 pwndChild
= co_WinPosSearchChildren(pwndChild
, Point
, HitTest
, Ignore
);
2427 if(pwndChild
!= NULL
)
2429 /* We found a window. Don't send any more WM_NCHITTEST messages */
2430 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2431 UserDereferenceObject(ScopeWin
);
2435 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2439 if (ScopeWin
->head
.pti
== PsGetCurrentThreadWin32Thread())
2441 *HitTest
= (USHORT
)co_IntSendMessage(ScopeWin
->head
.h
, WM_NCHITTEST
, 0,
2442 MAKELONG(Point
->x
, Point
->y
));
2443 if ((*HitTest
) == (USHORT
)HTTRANSPARENT
)
2445 UserDereferenceObject(ScopeWin
);
2450 *HitTest
= HTCLIENT
;
2456 co_WinPosWindowFromPoint(PWND ScopeWin
, POINT
*WinPoint
, USHORT
* HitTest
, BOOL Ignore
)
2459 POINT Point
= *WinPoint
;
2460 USER_REFERENCE_ENTRY Ref
;
2462 if( ScopeWin
== NULL
)
2464 ScopeWin
= UserGetDesktopWindow();
2465 if(ScopeWin
== NULL
)
2469 *HitTest
= HTNOWHERE
;
2471 ASSERT_REFS_CO(ScopeWin
);
2472 UserRefObjectCo(ScopeWin
, &Ref
);
2474 Window
= co_WinPosSearchChildren(ScopeWin
, &Point
, HitTest
, Ignore
);
2476 UserDerefObjectCo(ScopeWin
);
2478 ASSERT_REFS_CO(Window
);
2479 ASSERT_REFS_CO(ScopeWin
);
2485 IntRealChildWindowFromPoint(PWND Parent
, LONG x
, LONG y
)
2489 PWND pwndHit
= NULL
;
2494 if (Parent
!= UserGetDesktopWindow())
2496 Pt
.x
+= Parent
->rcClient
.left
;
2497 Pt
.y
+= Parent
->rcClient
.top
;
2500 if (!IntPtInWindow(Parent
, Pt
.x
, Pt
.y
)) return NULL
;
2502 if ((List
= IntWinListChildren(Parent
)))
2504 for (phWnd
= List
; *phWnd
; phWnd
++)
2507 if ((Child
= ValidateHwndNoErr(*phWnd
)))
2509 if ( Child
->style
& WS_VISIBLE
&& IntPtInWindow(Child
, Pt
.x
, Pt
.y
) )
2511 if ( Child
->pcls
->atomClassName
!= gpsi
->atomSysClass
[ICLS_BUTTON
] ||
2512 (Child
->style
& BS_TYPEMASK
) != BS_GROUPBOX
)
2514 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2521 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2523 return pwndHit
? pwndHit
: Parent
;
2527 IntChildWindowFromPointEx(PWND Parent
, LONG x
, LONG y
, UINT uiFlags
)
2531 PWND pwndHit
= NULL
;
2536 if (Parent
!= UserGetDesktopWindow())
2538 if (Parent
->ExStyle
& WS_EX_LAYOUTRTL
)
2539 Pt
.x
= Parent
->rcClient
.right
- Pt
.x
;
2541 Pt
.x
+= Parent
->rcClient
.left
;
2542 Pt
.y
+= Parent
->rcClient
.top
;
2545 if (!IntPtInWindow(Parent
, Pt
.x
, Pt
.y
)) return NULL
;
2547 if ((List
= IntWinListChildren(Parent
)))
2549 for (phWnd
= List
; *phWnd
; phWnd
++)
2552 if ((Child
= ValidateHwndNoErr(*phWnd
)))
2554 if (uiFlags
& (CWP_SKIPINVISIBLE
|CWP_SKIPDISABLED
))
2556 if (!(Child
->style
& WS_VISIBLE
) && (uiFlags
& CWP_SKIPINVISIBLE
)) continue;
2557 if ((Child
->style
& WS_DISABLED
) && (uiFlags
& CWP_SKIPDISABLED
)) continue;
2560 if (uiFlags
& CWP_SKIPTRANSPARENT
)
2562 if (Child
->ExStyle
& WS_EX_TRANSPARENT
) continue;
2565 if (IntPtInWindow(Child
, Pt
.x
, Pt
.y
))
2572 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2574 return pwndHit
? pwndHit
: Parent
;
2579 IntDeferWindowPos( HDWP hdwp
,
2590 HDWP retvalue
= hdwp
;
2592 TRACE("hdwp %p, hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
2593 hdwp
, hwnd
, hwndAfter
, x
, y
, cx
, cy
, flags
);
2595 if (flags
& ~(SWP_NOSIZE
| SWP_NOMOVE
|
2596 SWP_NOZORDER
| SWP_NOREDRAW
|
2597 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
2598 SWP_NOOWNERZORDER
|SWP_SHOWWINDOW
|
2599 SWP_HIDEWINDOW
| SWP_FRAMECHANGED
))
2601 EngSetLastError(ERROR_INVALID_PARAMETER
);
2605 if (!(pDWP
= (PSMWP
)UserGetObject(gHandleTable
, hdwp
, TYPE_SETWINDOWPOS
)))
2607 EngSetLastError(ERROR_INVALID_DWP_HANDLE
);
2611 for (i
= 0; i
< pDWP
->ccvr
; i
++)
2613 if (pDWP
->acvr
[i
].pos
.hwnd
== hwnd
)
2615 /* Merge with the other changes */
2616 if (!(flags
& SWP_NOZORDER
))
2618 pDWP
->acvr
[i
].pos
.hwndInsertAfter
= hwndAfter
;
2620 if (!(flags
& SWP_NOMOVE
))
2622 pDWP
->acvr
[i
].pos
.x
= x
;
2623 pDWP
->acvr
[i
].pos
.y
= y
;
2625 if (!(flags
& SWP_NOSIZE
))
2627 pDWP
->acvr
[i
].pos
.cx
= cx
;
2628 pDWP
->acvr
[i
].pos
.cy
= cy
;
2630 pDWP
->acvr
[i
].pos
.flags
&= flags
| ~(SWP_NOSIZE
| SWP_NOMOVE
|
2631 SWP_NOZORDER
| SWP_NOREDRAW
|
2632 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
2634 pDWP
->acvr
[i
].pos
.flags
|= flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
|
2639 if (pDWP
->ccvr
>= pDWP
->ccvrAlloc
)
2641 PCVR newpos
= ExAllocatePoolWithTag(PagedPool
, pDWP
->ccvrAlloc
* 2 * sizeof(CVR
), USERTAG_SWP
);
2647 RtlZeroMemory(newpos
, pDWP
->ccvrAlloc
* 2 * sizeof(CVR
));
2648 RtlCopyMemory(newpos
, pDWP
->acvr
, pDWP
->ccvrAlloc
* sizeof(CVR
));
2649 ExFreePoolWithTag(pDWP
->acvr
, USERTAG_SWP
);
2650 pDWP
->ccvrAlloc
*= 2;
2651 pDWP
->acvr
= newpos
;
2653 pDWP
->acvr
[pDWP
->ccvr
].pos
.hwnd
= hwnd
;
2654 pDWP
->acvr
[pDWP
->ccvr
].pos
.hwndInsertAfter
= hwndAfter
;
2655 pDWP
->acvr
[pDWP
->ccvr
].pos
.x
= x
;
2656 pDWP
->acvr
[pDWP
->ccvr
].pos
.y
= y
;
2657 pDWP
->acvr
[pDWP
->ccvr
].pos
.cx
= cx
;
2658 pDWP
->acvr
[pDWP
->ccvr
].pos
.cy
= cy
;
2659 pDWP
->acvr
[pDWP
->ccvr
].pos
.flags
= flags
;
2660 pDWP
->acvr
[pDWP
->ccvr
].hrgnClip
= NULL
;
2661 pDWP
->acvr
[pDWP
->ccvr
].hrgnInterMonitor
= NULL
;
2667 BOOL FASTCALL
IntEndDeferWindowPosEx( HDWP hdwp
, BOOL sAsync
)
2674 TRACE("%p\n", hdwp
);
2676 if (!(pDWP
= (PSMWP
)UserGetObject(gHandleTable
, hdwp
, TYPE_SETWINDOWPOS
)))
2678 EngSetLastError(ERROR_INVALID_DWP_HANDLE
);
2682 for (i
= 0, winpos
= pDWP
->acvr
; res
&& i
< pDWP
->ccvr
; i
++, winpos
++)
2685 USER_REFERENCE_ENTRY Ref
;
2687 TRACE("hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
2688 winpos
->pos
.hwnd
, winpos
->pos
.hwndInsertAfter
, winpos
->pos
.x
, winpos
->pos
.y
,
2689 winpos
->pos
.cx
, winpos
->pos
.cy
, winpos
->pos
.flags
);
2691 pwnd
= ValidateHwndNoErr(winpos
->pos
.hwnd
);
2695 UserRefObjectCo(pwnd
, &Ref
);
2700 PWINDOWPOS ppos
= ExAllocatePoolWithTag(PagedPool
, sizeof(WINDOWPOS
), USERTAG_SWP
);
2703 *ppos
= winpos
->pos
;
2704 /* Yes it's a pointer inside Win32k! */
2705 lRes
= co_IntSendMessageNoWait( winpos
->pos
.hwnd
, WM_ASYNC_SETWINDOWPOS
, 0, (LPARAM
)ppos
);
2706 /* We handle this the same way as Event Hooks and Hooks. */
2709 ExFreePoolWithTag(ppos
, USERTAG_SWP
);
2714 res
= co_WinPosSetWindowPos( pwnd
,
2715 winpos
->pos
.hwndInsertAfter
,
2722 // Hack to pass tests.... Must have some work to do so clear the error.
2723 if (res
&& (winpos
->pos
.flags
& (SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOZORDER
)) == SWP_NOZORDER
)
2724 EngSetLastError(ERROR_SUCCESS
);
2726 UserDerefObjectCo(pwnd
);
2728 ExFreePoolWithTag(pDWP
->acvr
, USERTAG_SWP
);
2729 UserDereferenceObject(pDWP
);
2730 UserDeleteObject(hdwp
, TYPE_SETWINDOWPOS
);
2738 NtUserChildWindowFromPointEx(HWND hwndParent
,
2744 TRACE("Enter NtUserChildWindowFromPointEx\n");
2745 UserEnterExclusive();
2746 if ((pwndParent
= UserGetWindowObject(hwndParent
)))
2748 pwndParent
= IntChildWindowFromPointEx(pwndParent
, x
, y
, uiFlags
);
2751 TRACE("Leave NtUserChildWindowFromPointEx\n");
2752 return pwndParent
? UserHMGetHandle(pwndParent
) : NULL
;
2759 NtUserEndDeferWindowPosEx(HDWP WinPosInfo
,
2763 TRACE("Enter NtUserEndDeferWindowPosEx\n");
2764 UserEnterExclusive();
2765 Ret
= IntEndDeferWindowPosEx(WinPosInfo
, (BOOL
)Unknown1
);
2766 TRACE("Leave NtUserEndDeferWindowPosEx, ret=%i\n", Ret
);
2775 NtUserDeferWindowPos(HDWP WinPosInfo
,
2777 HWND WndInsertAfter
,
2786 UINT Tmp
= ~(SWP_ASYNCWINDOWPOS
|SWP_DEFERERASE
|SWP_NOSENDCHANGING
|SWP_NOREPOSITION
|
2787 SWP_NOCOPYBITS
|SWP_HIDEWINDOW
|SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|
2788 SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_NOZORDER
|SWP_NOMOVE
|SWP_NOSIZE
);
2790 TRACE("Enter NtUserDeferWindowPos\n");
2791 UserEnterExclusive();
2795 EngSetLastError(ERROR_INVALID_FLAGS
);
2799 pWnd
= UserGetWindowObject(Wnd
);
2800 if ( !pWnd
|| // FIXME:
2801 pWnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
2802 pWnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
2807 if ( WndInsertAfter
&&
2808 WndInsertAfter
!= HWND_BOTTOM
&&
2809 WndInsertAfter
!= HWND_TOPMOST
&&
2810 WndInsertAfter
!= HWND_NOTOPMOST
)
2812 pWndIA
= UserGetWindowObject(WndInsertAfter
);
2814 pWndIA
== UserGetDesktopWindow() ||
2815 pWndIA
== UserGetMessageWindow() )
2821 Ret
= IntDeferWindowPos(WinPosInfo
, Wnd
, WndInsertAfter
, x
, y
, cx
, cy
, Flags
);
2824 TRACE("Leave NtUserDeferWindowPos, ret=%p\n", Ret
);
2833 NtUserGetInternalWindowPos( HWND hWnd
,
2840 WINDOWPLACEMENT wndpl
;
2844 if (!(Window
= UserGetWindowObject(hWnd
)))
2854 ProbeForWrite(rectWnd
,
2860 ProbeForWrite(ptIcon
,
2866 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2868 SetLastNtError(_SEH2_GetExceptionCode());
2873 wndpl
.length
= sizeof(WINDOWPLACEMENT
);
2875 if (IntGetWindowPlacement(Window
, &wndpl
) && !Hit
)
2881 RtlCopyMemory(rectWnd
, &wndpl
.rcNormalPosition
, sizeof(RECT
));
2885 RtlCopyMemory(ptIcon
, &wndpl
.ptMinPosition
, sizeof(POINT
));
2889 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2891 SetLastNtError(_SEH2_GetExceptionCode());
2896 if (!Hit
) Ret
= wndpl
.showCmd
;
2907 NtUserGetWindowPlacement(HWND hWnd
,
2908 WINDOWPLACEMENT
*lpwndpl
)
2911 WINDOWPLACEMENT Safepl
;
2913 DECLARE_RETURN(BOOL
);
2915 TRACE("Enter NtUserGetWindowPlacement\n");
2918 if (!(Wnd
= UserGetWindowObject(hWnd
)))
2923 Status
= MmCopyFromCaller(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
2924 if(!NT_SUCCESS(Status
))
2926 SetLastNtError(Status
);
2929 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
2934 IntGetWindowPlacement(Wnd
, &Safepl
);
2936 Status
= MmCopyToCaller(lpwndpl
, &Safepl
, sizeof(WINDOWPLACEMENT
));
2937 if(!NT_SUCCESS(Status
))
2939 SetLastNtError(Status
);
2946 TRACE("Leave NtUserGetWindowPlacement, ret=%i\n",_ret_
);
2955 UINT cmd
, // Wine SW_ commands
2960 TRACE("Enter NtUserMinMaximize\n");
2961 UserEnterExclusive();
2963 pWnd
= UserGetWindowObject(hWnd
);
2964 if ( !pWnd
|| // FIXME:
2965 pWnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
2966 pWnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
2971 if ( cmd
> SW_MAX
|| pWnd
->state2
& WNDS2_INDESTROY
)
2973 EngSetLastError(ERROR_INVALID_PARAMETER
);
2977 cmd
|= Hide
? SW_HIDE
: 0;
2979 co_WinPosShowWindow(pWnd
, cmd
);
2982 TRACE("Leave NtUserMinMaximize\n");
2984 return 0; // Always NULL?
2999 return NtUserSetWindowPos(hWnd
, 0, X
, Y
, nWidth
, nHeight
,
3000 (bRepaint
? SWP_NOZORDER
| SWP_NOACTIVATE
:
3001 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
));
3008 NtUserRealChildWindowFromPoint(HWND Parent
,
3013 TRACE("Enter NtUserRealChildWindowFromPoint\n");
3015 if ((pwndParent
= UserGetWindowObject(Parent
)))
3017 pwndParent
= IntRealChildWindowFromPoint(pwndParent
, x
, y
);
3020 TRACE("Leave NtUserRealChildWindowFromPoint\n");
3021 return pwndParent
? UserHMGetHandle(pwndParent
) : NULL
;
3030 HWND hWndInsertAfter
,
3037 DECLARE_RETURN(BOOL
);
3038 PWND Window
, pWndIA
;
3040 USER_REFERENCE_ENTRY Ref
;
3042 TRACE("Enter NtUserSetWindowPos\n");
3043 UserEnterExclusive();
3045 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
3046 Window
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3047 Window
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3049 ERR("NtUserSetWindowPos bad window handle!\n");
3053 if ( hWndInsertAfter
&&
3054 hWndInsertAfter
!= HWND_BOTTOM
&&
3055 hWndInsertAfter
!= HWND_TOPMOST
&&
3056 hWndInsertAfter
!= HWND_NOTOPMOST
)
3058 if (!(pWndIA
= UserGetWindowObject(hWndInsertAfter
)) ||
3059 pWndIA
== UserGetDesktopWindow() ||
3060 pWndIA
== UserGetMessageWindow() )
3062 ERR("NtUserSetWindowPos bad insert window handle!\n");
3067 /* First make sure that coordinates are valid for WM_WINDOWPOSCHANGING */
3068 if (!(uFlags
& SWP_NOMOVE
))
3070 if (X
< -32768) X
= -32768;
3071 else if (X
> 32767) X
= 32767;
3072 if (Y
< -32768) Y
= -32768;
3073 else if (Y
> 32767) Y
= 32767;
3075 if (!(uFlags
& SWP_NOSIZE
))
3078 else if (cx
> 32767) cx
= 32767;
3080 else if (cy
> 32767) cy
= 32767;
3083 UserRefObjectCo(Window
, &Ref
);
3084 ret
= co_WinPosSetWindowPos(Window
, hWndInsertAfter
, X
, Y
, cx
, cy
, uFlags
);
3085 UserDerefObjectCo(Window
);
3090 TRACE("Leave NtUserSetWindowPos, ret=%i\n",_ret_
);
3104 HRGN hrgnCopy
= NULL
;
3106 INT flags
= (SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
);
3107 BOOLEAN Ret
= FALSE
;
3108 DECLARE_RETURN(INT
);
3110 TRACE("Enter NtUserSetWindowRgn\n");
3111 UserEnterExclusive();
3113 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
3114 Window
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3115 Window
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3120 if (hRgn
) // The region will be deleted in user32.
3122 if (GreIsHandleValid(hRgn
))
3124 hrgnCopy
= NtGdiCreateRectRgn(0, 0, 0, 0);
3125 /* The coordinates of a window's window region are relative to the
3126 upper-left corner of the window, not the client area of the window. */
3127 NtGdiCombineRgn( hrgnCopy
, hRgn
, 0, RGN_COPY
);
3133 if (Window
->hrgnClip
)
3135 /* Delete no longer needed region handle */
3136 IntGdiSetRegionOwner(Window
->hrgnClip
, GDI_OBJ_HMGR_POWNED
);
3137 GreDeleteObject(Window
->hrgnClip
);
3142 /* Set public ownership */
3143 IntGdiSetRegionOwner(hrgnCopy
, GDI_OBJ_HMGR_PUBLIC
);
3145 Window
->hrgnClip
= hrgnCopy
;
3147 Ret
= co_WinPosSetWindowPos(Window
, HWND_TOP
, 0, 0, 0, 0, bRedraw
? flags
: (flags
|SWP_NOREDRAW
) );
3152 TRACE("Leave NtUserSetWindowRgn, ret=%i\n",_ret_
);
3161 NtUserSetInternalWindowPos(
3167 WINDOWPLACEMENT wndpl
;
3172 DECLARE_RETURN(BOOL
);
3173 USER_REFERENCE_ENTRY Ref
;
3175 TRACE("Enter NtUserSetWindowPlacement\n");
3176 UserEnterExclusive();
3178 if (!(Wnd
= UserGetWindowObject(hwnd
)) || // FIXME:
3179 Wnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3180 Wnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3189 ProbeForRead(lppt
, sizeof(POINT
), 1);
3190 RtlCopyMemory(&pt
, lppt
, sizeof(POINT
));
3194 ProbeForRead(lprect
, sizeof(RECT
), 1);
3195 RtlCopyMemory(&rect
, lprect
, sizeof(RECT
));
3198 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3200 SetLastNtError(_SEH2_GetExceptionCode());
3201 _SEH2_YIELD(RETURN( FALSE
));
3205 wndpl
.length
= sizeof(wndpl
);
3206 wndpl
.showCmd
= showCmd
;
3207 wndpl
.flags
= flags
= 0;
3212 wndpl
.flags
|= WPF_SETMINPOSITION
;
3213 wndpl
.ptMinPosition
= pt
;
3217 flags
|= PLACE_RECT
;
3218 wndpl
.rcNormalPosition
= rect
;
3221 UserRefObjectCo(Wnd
, &Ref
);
3222 IntSetWindowPlacement(Wnd
, &wndpl
, flags
);
3223 UserDerefObjectCo(Wnd
);
3227 TRACE("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_
);
3236 NtUserSetWindowPlacement(HWND hWnd
,
3237 WINDOWPLACEMENT
*lpwndpl
)
3240 WINDOWPLACEMENT Safepl
;
3242 DECLARE_RETURN(BOOL
);
3243 USER_REFERENCE_ENTRY Ref
;
3245 TRACE("Enter NtUserSetWindowPlacement\n");
3246 UserEnterExclusive();
3248 if (!(Wnd
= UserGetWindowObject(hWnd
)) || // FIXME:
3249 Wnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3250 Wnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3257 ProbeForRead(lpwndpl
, sizeof(WINDOWPLACEMENT
), 1);
3258 RtlCopyMemory(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
3260 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3262 SetLastNtError(_SEH2_GetExceptionCode());
3263 _SEH2_YIELD(RETURN( FALSE
));
3267 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
3272 Flags
= PLACE_MAX
| PLACE_RECT
;
3273 if (Safepl
.flags
& WPF_SETMINPOSITION
) Flags
|= PLACE_MIN
;
3274 UserRefObjectCo(Wnd
, &Ref
);
3275 IntSetWindowPlacement(Wnd
, &Safepl
, Flags
);
3276 UserDerefObjectCo(Wnd
);
3280 TRACE("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_
);
3289 NtUserShowWindowAsync(HWND hWnd
, LONG nCmdShow
)
3293 DECLARE_RETURN(BOOL
);
3294 USER_REFERENCE_ENTRY Ref
;
3296 TRACE("Enter NtUserShowWindowAsync\n");
3297 UserEnterExclusive();
3299 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
3300 Window
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3301 Window
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3306 if ( nCmdShow
> SW_MAX
)
3308 EngSetLastError(ERROR_INVALID_PARAMETER
);
3312 UserRefObjectCo(Window
, &Ref
);
3313 ret
= co_IntSendMessageNoWait( hWnd
, WM_ASYNC_SHOWWINDOW
, nCmdShow
, 0 );
3314 UserDerefObjectCo(Window
);
3315 if (-1 == (int) ret
|| !ret
) ret
= FALSE
;
3320 TRACE("Leave NtUserShowWindowAsync, ret=%i\n",_ret_
);
3329 NtUserShowWindow(HWND hWnd
, LONG nCmdShow
)
3333 DECLARE_RETURN(BOOL
);
3334 USER_REFERENCE_ENTRY Ref
;
3336 TRACE("Enter NtUserShowWindow\n");
3337 UserEnterExclusive();
3339 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
3340 Window
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3341 Window
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3346 if ( nCmdShow
> SW_MAX
|| Window
->state2
& WNDS2_INDESTROY
)
3348 EngSetLastError(ERROR_INVALID_PARAMETER
);
3352 UserRefObjectCo(Window
, &Ref
);
3353 ret
= co_WinPosShowWindow(Window
, nCmdShow
);
3354 UserDerefObjectCo(Window
);
3359 TRACE("Leave NtUserShowWindow, ret=%i\n",_ret_
);
3369 NtUserWindowFromPoint(LONG X
, LONG Y
)
3373 PWND DesktopWindow
= NULL
, Window
= NULL
;
3375 DECLARE_RETURN(HWND
);
3376 USER_REFERENCE_ENTRY Ref
;
3378 TRACE("Enter NtUserWindowFromPoint\n");
3379 UserEnterExclusive();
3381 if ((DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow())))
3388 // Hmm... Threads live on desktops thus we have a reference on the desktop and indirectly the desktop window.
3389 // It is possible this referencing is useless, though it should not hurt...
3390 UserRefObjectCo(DesktopWindow
, &Ref
);
3392 //pti = PsGetCurrentThreadWin32Thread();
3393 Window
= co_WinPosWindowFromPoint(DesktopWindow
, &pt
, &hittest
, FALSE
);
3397 Ret
= UserHMGetHandle(Window
);
3406 if (Window
) UserDereferenceObject(Window
);
3407 if (DesktopWindow
) UserDerefObjectCo(DesktopWindow
);
3409 TRACE("Leave NtUserWindowFromPoint, ret=%p\n", _ret_
);