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())
1549 WinPos
->flags
|= SWP_NOACTIVATE
; /* Already active */
1552 if ((Wnd
->style
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)
1554 /* Bring to the top when activating */
1555 if (!(WinPos
->flags
& (SWP_NOACTIVATE
|SWP_HIDEWINDOW
)) &&
1556 (WinPos
->flags
& SWP_NOZORDER
||
1557 (WinPos
->hwndInsertAfter
!= HWND_TOPMOST
&& WinPos
->hwndInsertAfter
!= HWND_NOTOPMOST
)))
1559 WinPos
->flags
&= ~SWP_NOZORDER
;
1560 WinPos
->hwndInsertAfter
= (0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
) ? HWND_TOPMOST
: HWND_TOP
);
1564 /* Check hwndInsertAfter */
1565 if (!(WinPos
->flags
& SWP_NOZORDER
))
1567 /* Fix sign extension */
1568 if (WinPos
->hwndInsertAfter
== (HWND
)0xffff)
1570 WinPos
->hwndInsertAfter
= HWND_TOPMOST
;
1572 else if (WinPos
->hwndInsertAfter
== (HWND
)0xfffe)
1574 WinPos
->hwndInsertAfter
= HWND_NOTOPMOST
;
1577 if (WinPos
->hwndInsertAfter
== HWND_TOP
)
1579 /* Keep it topmost when it's already topmost */
1580 if ((Wnd
->ExStyle
& WS_EX_TOPMOST
) != 0)
1581 WinPos
->hwndInsertAfter
= HWND_TOPMOST
;
1583 if (IntGetWindow(WinPos
->hwnd
, GW_HWNDFIRST
) == WinPos
->hwnd
)
1584 WinPos
->flags
|= SWP_NOZORDER
;
1586 else if (WinPos
->hwndInsertAfter
== HWND_BOTTOM
)
1588 if (!(Wnd
->ExStyle
& WS_EX_TOPMOST
) && IntGetWindow(WinPos
->hwnd
, GW_HWNDLAST
) == WinPos
->hwnd
)
1589 WinPos
->flags
|= SWP_NOZORDER
;
1591 else if (WinPos
->hwndInsertAfter
== HWND_TOPMOST
)
1593 if ((Wnd
->ExStyle
& WS_EX_TOPMOST
) && IntGetWindow(WinPos
->hwnd
, GW_HWNDFIRST
) == WinPos
->hwnd
)
1594 WinPos
->flags
|= SWP_NOZORDER
;
1596 else if (WinPos
->hwndInsertAfter
== HWND_NOTOPMOST
)
1598 if (!(Wnd
->ExStyle
& WS_EX_TOPMOST
))
1599 WinPos
->flags
|= SWP_NOZORDER
;
1601 else /* hwndInsertAfter must be a sibling of the window */
1605 InsAfterWnd
= ValidateHwndNoErr(WinPos
->hwndInsertAfter
);
1611 if (InsAfterWnd
->spwndParent
!= Wnd
->spwndParent
)
1613 /* Note from wine User32 Win test_SetWindowPos:
1614 "Returns TRUE also for windows that are not siblings"
1615 "Does not seem to do anything even without passing flags, still returns TRUE"
1616 "Same thing the other way around."
1617 ".. and with these windows."
1624 * We don't need to change the Z order of hwnd if it's already
1625 * inserted after hwndInsertAfter or when inserting hwnd after
1628 if ((WinPos
->hwnd
== WinPos
->hwndInsertAfter
) ||
1629 ((InsAfterWnd
->spwndNext
) && (WinPos
->hwnd
== InsAfterWnd
->spwndNext
->head
.h
)))
1631 WinPos
->flags
|= SWP_NOZORDER
;
1640 /* x and y are always screen relative */
1642 co_WinPosSetWindowPos(
1644 HWND WndInsertAfter
,
1653 RECTL NewWindowRect
;
1654 RECTL NewClientRect
;
1655 RECTL valid_rects
[2];
1656 PREGION VisBefore
= NULL
;
1657 PREGION VisBeforeJustClient
= NULL
;
1658 PREGION VisAfter
= NULL
;
1659 PREGION CopyRgn
= NULL
;
1661 RECTL OldWindowRect
, OldClientRect
;
1666 BOOL bPointerInWindow
;
1668 ASSERT_REFS_CO(Window
);
1670 /* FIXME: Get current active window from active queue. Why? since r2915. */
1672 bPointerInWindow
= IntPtInWindow(Window
, gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
);
1674 WinPos
.hwnd
= Window
->head
.h
;
1675 WinPos
.hwndInsertAfter
= WndInsertAfter
;
1680 WinPos
.flags
= flags
;
1682 if ( flags
& SWP_ASYNCWINDOWPOS
)
1685 PWINDOWPOS ppos
= ExAllocatePoolWithTag(PagedPool
, sizeof(WINDOWPOS
), USERTAG_SWP
);
1688 WinPos
.flags
&= ~SWP_ASYNCWINDOWPOS
; // Clear flag.
1690 /* Yes it's a pointer inside Win32k! */
1691 lRes
= co_IntSendMessageNoWait( WinPos
.hwnd
, WM_ASYNC_SETWINDOWPOS
, 0, (LPARAM
)ppos
);
1692 /* We handle this the same way as Event Hooks and Hooks. */
1695 ExFreePoolWithTag(ppos
, USERTAG_SWP
);
1703 co_WinPosDoWinPosChanging(Window
, &WinPos
, &NewWindowRect
, &NewClientRect
);
1705 /* Does the window still exist? */
1706 if (!IntIsWindow(WinPos
.hwnd
))
1708 TRACE("WinPosSetWindowPos: Invalid handle 0x%p!\n",WinPos
.hwnd
);
1709 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE
);
1713 /* Fix up the flags. */
1714 if (!WinPosFixupFlags(&WinPos
, Window
))
1720 Ancestor
= UserGetAncestor(Window
, GA_PARENT
);
1721 if ( (WinPos
.flags
& (SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) != SWP_NOZORDER
&&
1722 Ancestor
&& Ancestor
->head
.h
== IntGetDesktopWindow() )
1724 WinPos
.hwndInsertAfter
= WinPosDoOwnedPopups(Window
, WinPos
.hwndInsertAfter
);
1727 if (!(WinPos
.flags
& SWP_NOREDRAW
))
1729 /* Compute the visible region before the window position is changed */
1730 if (!(WinPos
.flags
& SWP_SHOWWINDOW
) &&
1731 (WinPos
.flags
& (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
|
1732 SWP_HIDEWINDOW
| SWP_FRAMECHANGED
)) !=
1733 (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
))
1735 VisBefore
= VIS_ComputeVisibleRegion(Window
, FALSE
, FALSE
,
1736 (Window
->style
& WS_CLIPSIBLINGS
) ? TRUE
: FALSE
);
1738 if ( VisBefore
!= NULL
&&
1739 REGION_Complexity(VisBefore
) == NULLREGION
)
1741 REGION_Delete(VisBefore
);
1746 IntGdiOffsetRgn(VisBefore
, -Window
->rcWindow
.left
, -Window
->rcWindow
.top
);
1749 /* Calculate the non client area for resizes, as this is used in the copy region */
1750 if (!(WinPos
.flags
& SWP_NOSIZE
))
1752 VisBeforeJustClient
= VIS_ComputeVisibleRegion(Window
, TRUE
, FALSE
,
1753 (Window
->style
& WS_CLIPSIBLINGS
) ? TRUE
: FALSE
);
1755 if ( VisBeforeJustClient
!= NULL
&&
1756 REGION_Complexity(VisBeforeJustClient
) == NULLREGION
)
1758 REGION_Delete(VisBeforeJustClient
);
1759 VisBeforeJustClient
= NULL
;
1761 else if(VisBeforeJustClient
)
1763 IntGdiOffsetRgn(VisBeforeJustClient
, -Window
->rcWindow
.left
, -Window
->rcWindow
.top
);
1769 WvrFlags
= co_WinPosDoNCCALCSize(Window
, &WinPos
, &NewWindowRect
, &NewClientRect
, valid_rects
);
1771 // ERR("co_WinPosDoNCCALCSize returned 0x%x\n valid dest: %d %d %d %d\n valid src : %d %d %d %d\n", WvrFlags,
1772 // valid_rects[0].left,valid_rects[0].top,valid_rects[0].right,valid_rects[0].bottom,
1773 // valid_rects[1].left,valid_rects[1].top,valid_rects[1].right,valid_rects[1].bottom);
1775 /* Validate link windows. (also take into account shell window in hwndShellWindow) */
1776 if (!(WinPos
.flags
& SWP_NOZORDER
) && WinPos
.hwnd
!= UserGetShellWindow())
1778 IntLinkHwnd(Window
, WinPos
.hwndInsertAfter
);
1781 OldWindowRect
= Window
->rcWindow
;
1782 OldClientRect
= Window
->rcClient
;
1784 if (NewClientRect
.left
!= OldClientRect
.left
||
1785 NewClientRect
.top
!= OldClientRect
.top
)
1787 // Move child window if their parent is moved. Keep Child window relative to Parent...
1788 WinPosInternalMoveWindow(Window
,
1789 NewClientRect
.left
- OldClientRect
.left
,
1790 NewClientRect
.top
- OldClientRect
.top
);
1793 Window
->rcWindow
= NewWindowRect
;
1794 Window
->rcClient
= NewClientRect
;
1796 /* erase parent when hiding or resizing child */
1797 if (WinPos
.flags
& SWP_HIDEWINDOW
)
1799 /* Clear the update region */
1800 co_UserRedrawWindow( Window
,
1803 RDW_VALIDATE
| RDW_NOFRAME
| RDW_NOERASE
| RDW_NOINTERNALPAINT
| RDW_ALLCHILDREN
);
1805 if (Window
->spwndParent
== UserGetDesktopWindow())
1806 co_IntShellHookNotify(HSHELL_WINDOWDESTROYED
, (WPARAM
)Window
->head
.h
, 0);
1808 Window
->style
&= ~WS_VISIBLE
; //IntSetStyle( Window, 0, WS_VISIBLE );
1809 Window
->head
.pti
->cVisWindows
--;
1810 IntNotifyWinEvent(EVENT_OBJECT_HIDE
, Window
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
1812 else if (WinPos
.flags
& SWP_SHOWWINDOW
)
1814 if (Window
->spwndParent
== UserGetDesktopWindow())
1815 co_IntShellHookNotify(HSHELL_WINDOWCREATED
, (WPARAM
)Window
->head
.h
, 0);
1817 Window
->style
|= WS_VISIBLE
; //IntSetStyle( Window, WS_VISIBLE, 0 );
1818 Window
->head
.pti
->cVisWindows
++;
1819 IntNotifyWinEvent(EVENT_OBJECT_SHOW
, Window
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
1822 if (Window
->hrgnUpdate
!= NULL
&& Window
->hrgnUpdate
!= HRGN_WINDOW
)
1824 NtGdiOffsetRgn(Window
->hrgnUpdate
,
1825 NewWindowRect
.left
- OldWindowRect
.left
,
1826 NewWindowRect
.top
- OldWindowRect
.top
);
1829 DceResetActiveDCEs(Window
); // For WS_VISIBLE changes.
1831 if (!(WinPos
.flags
& SWP_NOREDRAW
))
1833 /* Determine the new visible region */
1834 VisAfter
= VIS_ComputeVisibleRegion(Window
, FALSE
, FALSE
,
1835 (Window
->style
& WS_CLIPSIBLINGS
) ? TRUE
: FALSE
);
1837 if ( VisAfter
!= NULL
&&
1838 REGION_Complexity(VisAfter
) == NULLREGION
)
1840 REGION_Delete(VisAfter
);
1845 IntGdiOffsetRgn(VisAfter
, -Window
->rcWindow
.left
, -Window
->rcWindow
.top
);
1849 * Determine which pixels can be copied from the old window position
1850 * to the new. Those pixels must be visible in both the old and new
1851 * position. Also, check the class style to see if the windows of this
1852 * class need to be completely repainted on (horizontal/vertical) size
1855 if ( VisBefore
!= NULL
&&
1857 !(WinPos
.flags
& SWP_NOCOPYBITS
) &&
1858 ((WinPos
.flags
& SWP_NOSIZE
) || !(WvrFlags
& WVR_REDRAW
)) &&
1859 !(Window
->ExStyle
& WS_EX_TRANSPARENT
) )
1863 * If this is (also) a window resize, the whole nonclient area
1864 * needs to be repainted. So we limit the copy to the client area,
1865 * 'cause there is no use in copying it (would possibly cause
1866 * "flashing" too). However, if the copy region is already empty,
1867 * we don't have to crop (can't take anything away from an empty
1871 CopyRgn
= IntSysCreateRectpRgn(0, 0, 0, 0);
1872 if (WinPos
.flags
& SWP_NOSIZE
)
1873 RgnType
= IntGdiCombineRgn(CopyRgn
, VisAfter
, VisBefore
, RGN_AND
);
1874 else if (VisBeforeJustClient
!= NULL
)
1876 RgnType
= IntGdiCombineRgn(CopyRgn
, VisAfter
, VisBeforeJustClient
, RGN_AND
);
1877 REGION_Delete(VisBeforeJustClient
);
1880 /* No use in copying bits which are in the update region. */
1881 if (Window
->hrgnUpdate
!= NULL
)
1883 PREGION RgnUpdate
= RGNOBJAPI_Lock(Window
->hrgnUpdate
, NULL
);
1886 IntGdiOffsetRgn(CopyRgn
, NewWindowRect
.left
, NewWindowRect
.top
);
1887 IntGdiCombineRgn(CopyRgn
, CopyRgn
, RgnUpdate
, RGN_DIFF
);
1888 IntGdiOffsetRgn(CopyRgn
, -NewWindowRect
.left
, -NewWindowRect
.top
);
1889 RGNOBJAPI_Unlock(RgnUpdate
);
1894 * Now, get the bounding box of the copy region. If it's empty
1895 * there's nothing to copy. Also, it's no use copying bits onto
1898 if (REGION_GetRgnBox(CopyRgn
, &CopyRect
) == NULLREGION
)
1900 /* Nothing to copy, clean up */
1901 REGION_Delete(CopyRgn
);
1904 else if (OldWindowRect
.left
!= NewWindowRect
.left
||
1905 OldWindowRect
.top
!= NewWindowRect
.top
)
1907 HRGN DcRgn
= NtGdiCreateRectRgn(0, 0, 0, 0);
1908 PREGION DcRgnObj
= RGNOBJAPI_Lock(DcRgn
, NULL
);
1911 * Small trick here: there is no function to bitblt a region. So
1912 * we set the region as the clipping region, take the bounding box
1913 * of the region and bitblt that. Since nothing outside the clipping
1914 * region is copied, this has the effect of bitblt'ing the region.
1916 * Since NtUserGetDCEx takes ownership of the clip region, we need
1917 * to create a copy of CopyRgn and pass that. We need CopyRgn later
1919 IntGdiCombineRgn(DcRgnObj
, CopyRgn
, NULL
, RGN_COPY
);
1920 IntGdiOffsetRgn(DcRgnObj
, NewWindowRect
.left
, NewWindowRect
.top
);
1921 RGNOBJAPI_Unlock(DcRgnObj
);
1922 Dc
= UserGetDCEx( Window
,
1924 DCX_WINDOW
|DCX_CACHE
|DCX_INTERSECTRGN
|DCX_CLIPSIBLINGS
|DCX_KEEPCLIPRGN
);
1926 CopyRect
.left
, CopyRect
.top
,
1927 CopyRect
.right
- CopyRect
.left
,
1928 CopyRect
.bottom
- CopyRect
.top
,
1930 CopyRect
.left
+ (OldWindowRect
.left
- NewWindowRect
.left
),
1931 CopyRect
.top
+ (OldWindowRect
.top
- NewWindowRect
.top
),
1936 UserReleaseDC(Window
, Dc
, FALSE
);
1937 IntValidateParent(Window
, CopyRgn
, FALSE
);
1938 GreDeleteObject(DcRgn
);
1946 /* We need to redraw what wasn't visible before */
1947 if (VisAfter
!= NULL
)
1949 PREGION DirtyRgn
= IntSysCreateRectpRgn(0, 0, 0, 0);
1952 if (CopyRgn
!= NULL
)
1954 RgnType
= IntGdiCombineRgn(DirtyRgn
, VisAfter
, CopyRgn
, RGN_DIFF
);
1958 RgnType
= IntGdiCombineRgn(DirtyRgn
, VisAfter
, 0, RGN_COPY
);
1960 if (RgnType
!= ERROR
&& RgnType
!= NULLREGION
)
1963 NtGdiOffsetRgn(DirtyRgn, Window->rcWindow.left, Window->rcWindow.top);
1964 IntInvalidateWindows( Window,
1966 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
1968 GreDeleteObject(DirtyRgn);
1971 PWND Parent
= Window
->spwndParent
;
1973 IntGdiOffsetRgn( DirtyRgn
,
1974 Window
->rcWindow
.left
,
1975 Window
->rcWindow
.top
);
1976 if ( (Window
->style
& WS_CHILD
) &&
1978 !(Parent
->style
& WS_CLIPCHILDREN
))
1980 IntInvalidateWindows( Parent
,
1982 RDW_ERASE
| RDW_INVALIDATE
);
1983 co_IntPaintWindows(Parent
, RDW_ERASENOW
, FALSE
);
1987 IntInvalidateWindows( Window
,
1989 RDW_ERASE
| RDW_FRAME
| RDW_INVALIDATE
| RDW_ALLCHILDREN
);
1992 REGION_Delete(DirtyRgn
);
1996 if (CopyRgn
!= NULL
)
1998 REGION_Delete(CopyRgn
);
2001 /* Expose what was covered before but not covered anymore */
2002 if (VisBefore
!= NULL
)
2004 PREGION ExposedRgn
= IntSysCreateRectpRgn(0, 0, 0, 0);
2007 RgnType
= IntGdiCombineRgn(ExposedRgn
, VisBefore
, NULL
, RGN_COPY
);
2008 IntGdiOffsetRgn( ExposedRgn
,
2009 OldWindowRect
.left
- NewWindowRect
.left
,
2010 OldWindowRect
.top
- NewWindowRect
.top
);
2012 if (VisAfter
!= NULL
)
2013 RgnType
= IntGdiCombineRgn(ExposedRgn
, ExposedRgn
, VisAfter
, RGN_DIFF
);
2015 if (RgnType
!= ERROR
&& RgnType
!= NULLREGION
)
2017 co_VIS_WindowLayoutChanged(Window
, ExposedRgn
);
2019 REGION_Delete(ExposedRgn
);
2021 REGION_Delete(VisBefore
);
2024 if (VisAfter
!= NULL
)
2026 REGION_Delete(VisAfter
);
2030 if (!(WinPos
.flags
& (SWP_NOACTIVATE
|SWP_HIDEWINDOW
)))
2032 if ((Window
->style
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
2034 co_IntSendMessageNoWait(WinPos
.hwnd
, WM_CHILDACTIVATE
, 0, 0);
2038 //ERR("SetWindowPos Set FG Window!\n");
2039 if (Window
->state
& WNDS_BEINGACTIVATED
) // Inside SAW?
2040 co_IntSetActiveWindow(Window
, FALSE
, TRUE
, FALSE
); // Fixes Api AttachThreadInput tests.
2042 co_IntSetForegroundWindow(Window
); // Fixes SW_HIDE issues. Wine win test_SetActiveWindow & test_SetForegroundWindow.
2046 /* And last, send the WM_WINDOWPOSCHANGED message */
2048 TRACE("\tstatus flags = %04x\n", WinPos
.flags
& SWP_AGG_STATUSFLAGS
);
2050 if ((WinPos
.flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOPOSCHANGE
)
2052 /* WM_WINDOWPOSCHANGED is sent even if SWP_NOSENDCHANGING is set
2053 and always contains final window position.
2055 WinPos
.x
= NewWindowRect
.left
;
2056 WinPos
.y
= NewWindowRect
.top
;
2057 WinPos
.cx
= NewWindowRect
.right
- NewWindowRect
.left
;
2058 WinPos
.cy
= NewWindowRect
.bottom
- NewWindowRect
.top
;
2059 co_IntSendMessageNoWait(WinPos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
) &WinPos
);
2062 if ( WinPos
.flags
& SWP_FRAMECHANGED
|| WinPos
.flags
& SWP_STATECHANGED
||
2063 !(WinPos
.flags
& SWP_NOCLIENTSIZE
) || !(WinPos
.flags
& SWP_NOCLIENTMOVE
) )
2065 PWND pWnd
= ValidateHwndNoErr(WinPos
.hwnd
);
2067 IntNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE
, pWnd
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
2070 if(bPointerInWindow
!= IntPtInWindow(Window
, gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
))
2072 /* Generate mouse move message */
2074 msg
.message
= WM_MOUSEMOVE
;
2075 msg
.wParam
= UserGetMouseButtonsState();
2076 msg
.lParam
= MAKELPARAM(gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
);
2077 msg
.pt
= gpsi
->ptCursor
;
2078 co_MsqInsertMouseMessage(&msg
, 0, 0, TRUE
);
2085 co_WinPosGetNonClientSize(PWND Window
, RECT
* WindowRect
, RECT
* ClientRect
)
2089 ASSERT_REFS_CO(Window
);
2091 *ClientRect
= *WindowRect
;
2092 Result
= co_IntSendMessageNoWait(Window
->head
.h
, WM_NCCALCSIZE
, FALSE
, (LPARAM
) ClientRect
);
2094 FixClientRect(ClientRect
, WindowRect
);
2100 co_WinPosSendSizeMove(PWND Wnd
)
2104 WPARAM wParam
= SIZE_RESTORED
;
2106 IntGetClientRect(Wnd
, &Rect
);
2107 lParam
= MAKELONG(Rect
.right
-Rect
.left
, Rect
.bottom
-Rect
.top
);
2109 Wnd
->state
&= ~WNDS_SENDSIZEMOVEMSGS
;
2111 if (Wnd
->style
& WS_MAXIMIZE
)
2113 wParam
= SIZE_MAXIMIZED
;
2115 else if (Wnd
->style
& WS_MINIMIZE
)
2117 wParam
= SIZE_MINIMIZED
;
2121 co_IntSendMessageNoWait(UserHMGetHandle(Wnd
), WM_SIZE
, wParam
, lParam
);
2123 if (Wnd
->spwndParent
== UserGetDesktopWindow()) // Wnd->spwndParent->fnid == FNID_DESKTOP )
2124 lParam
= MAKELONG(Wnd
->rcClient
.left
, Wnd
->rcClient
.top
);
2126 lParam
= MAKELONG(Wnd
->rcClient
.left
-Wnd
->spwndParent
->rcClient
.left
, Wnd
->rcClient
.top
-Wnd
->spwndParent
->rcClient
.top
);
2128 co_IntSendMessageNoWait(UserHMGetHandle(Wnd
), WM_MOVE
, 0, lParam
);
2130 IntEngWindowChanged(Wnd
, WOC_RGN_CLIENT
);
2134 co_WinPosShowWindow(PWND Wnd
, INT Cmd
)
2137 UINT Swp
= 0, EventMsg
= 0;
2138 RECTL NewPos
= {0, 0, 0, 0};
2144 BOOL ShowOwned
= FALSE
;
2145 ASSERT_REFS_CO(Wnd
);
2146 //ERR("co_WinPosShowWindow START\n");
2148 pti
= PsGetCurrentThreadWin32Thread();
2149 WasVisible
= (Wnd
->style
& WS_VISIBLE
) != 0;
2158 //ERR("co_WinPosShowWindow Exit Bad\n");
2161 Swp
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
2162 if (Wnd
!= pti
->MessageQueue
->spwndActive
)
2163 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2167 case SW_FORCEMINIMIZE
: /* FIXME: Does not work if thread is hung. */
2168 case SW_SHOWMINNOACTIVE
:
2169 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2171 case SW_SHOWMINIMIZED
:
2172 Swp
|= SWP_SHOWWINDOW
;
2176 Swp
|= SWP_NOACTIVATE
;
2177 if (!(style
& WS_MINIMIZE
))
2179 IntShowOwnedPopups(Wnd
, FALSE
);
2181 // Fix wine Win test_SetFocus todo #1 & #2,
2182 if (Cmd
== SW_SHOWMINIMIZED
)
2184 //ERR("co_WinPosShowWindow Set focus 1\n");
2185 if ((style
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
2186 co_UserSetFocus(Wnd
->spwndParent
);
2191 Swp
|= co_WinPosMinMaximize(Wnd
, Cmd
, &NewPos
) |
2194 EventMsg
= EVENT_SYSTEM_MINIMIZESTART
;
2200 Swp
|= SWP_FRAMECHANGED
;
2204 //ERR("co_WinPosShowWindow Exit Good\n");
2207 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
2212 case SW_SHOWMAXIMIZED
:
2214 Swp
|= SWP_SHOWWINDOW
;
2215 if (!(style
& WS_MAXIMIZE
))
2219 Swp
|= co_WinPosMinMaximize(Wnd
, SW_MAXIMIZE
, &NewPos
) |
2222 EventMsg
= EVENT_SYSTEM_MINIMIZEEND
;
2228 Swp
|= SWP_FRAMECHANGED
;
2232 //ERR("co_WinPosShowWindow Exit Good 1\n");
2235 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
2241 Swp
|= SWP_NOACTIVATE
| SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
2242 if (style
& WS_CHILD
&& !(Wnd
->ExStyle
& WS_EX_MDICHILD
)) Swp
|= SWP_NOZORDER
;
2245 if (WasVisible
) return(TRUE
); // Nothing to do!
2246 Swp
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
2247 /* Don't activate the topmost window. */
2248 if (style
& WS_CHILD
&& !(Wnd
->ExStyle
& WS_EX_MDICHILD
)) Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2251 case SW_SHOWNOACTIVATE
:
2252 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2255 case SW_SHOWDEFAULT
:
2257 if (!WasVisible
) Swp
|= SWP_SHOWWINDOW
;
2258 if (style
& (WS_MINIMIZE
| WS_MAXIMIZE
))
2260 Swp
|= co_WinPosMinMaximize(Wnd
, Cmd
, &NewPos
) |
2263 if (style
& WS_MINIMIZE
) EventMsg
= EVENT_SYSTEM_MINIMIZEEND
;
2269 Swp
|= SWP_FRAMECHANGED
;
2273 //ERR("co_WinPosShowWindow Exit Good 3\n");
2276 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
2278 if ( style
& WS_CHILD
&&
2279 !(Wnd
->ExStyle
& WS_EX_MDICHILD
) &&
2280 !(Swp
& SWP_STATECHANGED
))
2281 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2285 //ERR("co_WinPosShowWindow Exit Good 4\n");
2289 ShowFlag
= (Cmd
!= SW_HIDE
);
2291 if ((ShowFlag
!= WasVisible
|| Cmd
== SW_SHOWNA
) && Cmd
!= SW_SHOWMAXIMIZED
&& !(Swp
& SWP_STATECHANGED
))
2293 co_IntSendMessageNoWait(Wnd
->head
.h
, WM_SHOWWINDOW
, ShowFlag
, 0);
2294 if (!(Wnd
->state2
& WNDS2_WIN31COMPAT
))
2295 co_IntSendMessageNoWait(Wnd
->head
.h
, WM_SETVISIBLE
, ShowFlag
, 0);
2296 if (!VerifyWnd(Wnd
)) return WasVisible
;
2299 /* We can't activate a child window */
2300 if ((Wnd
->style
& WS_CHILD
) &&
2301 !(Wnd
->ExStyle
& WS_EX_MDICHILD
) &&
2304 //ERR("SWP Child No active and ZOrder\n");
2305 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2308 #if 0 // Explorer issues with common controls? Someone does not know how CS_SAVEBITS works.
2309 // Breaks startup and shutdown active window...
2310 if ((Wnd
->style
& (WS_POPUP
|WS_CHILD
)) != WS_CHILD
&&
2311 Wnd
->pcls
->style
& CS_SAVEBITS
&&
2312 ((Cmd
== SW_SHOW
) || (Cmd
== SW_NORMAL
)))
2314 ERR("WinPosShowWindow Set active\n");
2315 UserSetActiveWindow(Wnd
);
2316 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2320 if (IsChildVisible(Wnd
) || Swp
& SWP_STATECHANGED
)
2322 TRACE("Child is Vis %s or State changed %s. ShowFlag %s\n",
2323 (IsChildVisible(Wnd
) ? "TRUE" : "FALSE"), (Swp
& SWP_STATECHANGED
? "TRUE" : "FALSE"),
2324 (ShowFlag
? "TRUE" : "FALSE"));
2325 co_WinPosSetWindowPos( Wnd
,
2326 0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
) ? HWND_TOPMOST
: HWND_TOP
,
2329 NewPos
.right
, //NewPos.right - NewPos.left,
2330 NewPos
.bottom
, //NewPos.bottom - NewPos.top,
2335 TRACE("Parent Vis?\n");
2336 /* if parent is not visible simply toggle WS_VISIBLE and return */
2337 if (ShowFlag
) IntSetStyle( Wnd
, WS_VISIBLE
, 0 );
2338 else IntSetStyle( Wnd
, 0, WS_VISIBLE
);
2341 if ( EventMsg
) IntNotifyWinEvent(EventMsg
, Wnd
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
2343 if ( ShowOwned
) IntShowOwnedPopups(Wnd
, TRUE
);
2345 if ((Cmd
== SW_HIDE
) || (Cmd
== SW_MINIMIZE
))
2347 if ( Wnd
== pti
->MessageQueue
->spwndActive
&& pti
->MessageQueue
== IntGetFocusMessageQueue() )
2349 if ( Wnd
->spwndParent
== UserGetDesktopWindow())
2351 if(!ActivateOtherWindowMin(Wnd
))
2352 co_WinPosActivateOtherWindow(Wnd
);
2355 co_WinPosActivateOtherWindow(Wnd
);
2358 /* Revert focus to parent */
2359 if (Wnd
== pti
->MessageQueue
->spwndFocus
)
2361 Parent
= Wnd
->spwndParent
;
2362 if (Wnd
->spwndParent
== UserGetDesktopWindow()) Parent
= 0;
2363 co_UserSetFocus(Parent
);
2367 /* FIXME: Check for window destruction. */
2369 if ((Wnd
->state
& WNDS_SENDSIZEMOVEMSGS
) &&
2370 !(Wnd
->state2
& WNDS2_INDESTROY
))
2372 co_WinPosSendSizeMove(Wnd
);
2375 /* if previous state was minimized Windows sets focus to the window */
2376 if (style
& WS_MINIMIZE
)
2378 co_UserSetFocus(Wnd
);
2379 // Fix wine Win test_SetFocus todo #3,
2380 if (!(style
& WS_CHILD
)) co_IntSendMessageNoWait(UserHMGetHandle(Wnd
), WM_ACTIVATE
, WA_ACTIVE
, 0);
2382 //ERR("co_WinPosShowWindow EXIT\n");
2388 co_WinPosSearchChildren(
2398 if (!(ScopeWin
->style
& WS_VISIBLE
))
2403 if (!Ignore
&& (ScopeWin
->style
& WS_DISABLED
))
2408 if (!IntPtInWindow(ScopeWin
, Point
->x
, Point
->y
))
2413 UserReferenceObject(ScopeWin
);
2415 if ( RECTL_bPointInRect(&ScopeWin
->rcClient
, Point
->x
, Point
->y
) )
2417 List
= IntWinListChildren(ScopeWin
);
2420 for (phWnd
= List
; *phWnd
; ++phWnd
)
2422 if (!(pwndChild
= ValidateHwndNoErr(*phWnd
)))
2427 pwndChild
= co_WinPosSearchChildren(pwndChild
, Point
, HitTest
, Ignore
);
2429 if(pwndChild
!= NULL
)
2431 /* We found a window. Don't send any more WM_NCHITTEST messages */
2432 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2433 UserDereferenceObject(ScopeWin
);
2437 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2441 if (ScopeWin
->head
.pti
== PsGetCurrentThreadWin32Thread())
2443 *HitTest
= (USHORT
)co_IntSendMessage(ScopeWin
->head
.h
, WM_NCHITTEST
, 0,
2444 MAKELONG(Point
->x
, Point
->y
));
2445 if ((*HitTest
) == (USHORT
)HTTRANSPARENT
)
2447 UserDereferenceObject(ScopeWin
);
2452 *HitTest
= HTCLIENT
;
2458 co_WinPosWindowFromPoint(PWND ScopeWin
, POINT
*WinPoint
, USHORT
* HitTest
, BOOL Ignore
)
2461 POINT Point
= *WinPoint
;
2462 USER_REFERENCE_ENTRY Ref
;
2464 if( ScopeWin
== NULL
)
2466 ScopeWin
= UserGetDesktopWindow();
2467 if(ScopeWin
== NULL
)
2471 *HitTest
= HTNOWHERE
;
2473 ASSERT_REFS_CO(ScopeWin
);
2474 UserRefObjectCo(ScopeWin
, &Ref
);
2476 Window
= co_WinPosSearchChildren(ScopeWin
, &Point
, HitTest
, Ignore
);
2478 UserDerefObjectCo(ScopeWin
);
2480 ASSERT_REFS_CO(Window
);
2481 ASSERT_REFS_CO(ScopeWin
);
2487 IntRealChildWindowFromPoint(PWND Parent
, LONG x
, LONG y
)
2491 PWND pwndHit
= NULL
;
2496 if (Parent
!= UserGetDesktopWindow())
2498 Pt
.x
+= Parent
->rcClient
.left
;
2499 Pt
.y
+= Parent
->rcClient
.top
;
2502 if (!IntPtInWindow(Parent
, Pt
.x
, Pt
.y
)) return NULL
;
2504 if ((List
= IntWinListChildren(Parent
)))
2506 for (phWnd
= List
; *phWnd
; phWnd
++)
2509 if ((Child
= ValidateHwndNoErr(*phWnd
)))
2511 if ( Child
->style
& WS_VISIBLE
&& IntPtInWindow(Child
, Pt
.x
, Pt
.y
) )
2513 if ( Child
->pcls
->atomClassName
!= gpsi
->atomSysClass
[ICLS_BUTTON
] ||
2514 (Child
->style
& BS_TYPEMASK
) != BS_GROUPBOX
)
2516 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2523 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2525 return pwndHit
? pwndHit
: Parent
;
2529 IntChildWindowFromPointEx(PWND Parent
, LONG x
, LONG y
, UINT uiFlags
)
2533 PWND pwndHit
= NULL
;
2538 if (Parent
!= UserGetDesktopWindow())
2540 if (Parent
->ExStyle
& WS_EX_LAYOUTRTL
)
2541 Pt
.x
= Parent
->rcClient
.right
- Pt
.x
;
2543 Pt
.x
+= Parent
->rcClient
.left
;
2544 Pt
.y
+= Parent
->rcClient
.top
;
2547 if (!IntPtInWindow(Parent
, Pt
.x
, Pt
.y
)) return NULL
;
2549 if ((List
= IntWinListChildren(Parent
)))
2551 for (phWnd
= List
; *phWnd
; phWnd
++)
2554 if ((Child
= ValidateHwndNoErr(*phWnd
)))
2556 if (uiFlags
& (CWP_SKIPINVISIBLE
|CWP_SKIPDISABLED
))
2558 if (!(Child
->style
& WS_VISIBLE
) && (uiFlags
& CWP_SKIPINVISIBLE
)) continue;
2559 if ((Child
->style
& WS_DISABLED
) && (uiFlags
& CWP_SKIPDISABLED
)) continue;
2562 if (uiFlags
& CWP_SKIPTRANSPARENT
)
2564 if (Child
->ExStyle
& WS_EX_TRANSPARENT
) continue;
2567 if (IntPtInWindow(Child
, Pt
.x
, Pt
.y
))
2574 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2576 return pwndHit
? pwndHit
: Parent
;
2581 IntDeferWindowPos( HDWP hdwp
,
2592 HDWP retvalue
= hdwp
;
2594 TRACE("hdwp %p, hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
2595 hdwp
, hwnd
, hwndAfter
, x
, y
, cx
, cy
, flags
);
2597 if (flags
& ~(SWP_NOSIZE
| SWP_NOMOVE
|
2598 SWP_NOZORDER
| SWP_NOREDRAW
|
2599 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
2600 SWP_NOOWNERZORDER
|SWP_SHOWWINDOW
|
2601 SWP_HIDEWINDOW
| SWP_FRAMECHANGED
))
2603 EngSetLastError(ERROR_INVALID_PARAMETER
);
2607 if (!(pDWP
= (PSMWP
)UserGetObject(gHandleTable
, hdwp
, TYPE_SETWINDOWPOS
)))
2609 EngSetLastError(ERROR_INVALID_DWP_HANDLE
);
2613 for (i
= 0; i
< pDWP
->ccvr
; i
++)
2615 if (pDWP
->acvr
[i
].pos
.hwnd
== hwnd
)
2617 /* Merge with the other changes */
2618 if (!(flags
& SWP_NOZORDER
))
2620 pDWP
->acvr
[i
].pos
.hwndInsertAfter
= hwndAfter
;
2622 if (!(flags
& SWP_NOMOVE
))
2624 pDWP
->acvr
[i
].pos
.x
= x
;
2625 pDWP
->acvr
[i
].pos
.y
= y
;
2627 if (!(flags
& SWP_NOSIZE
))
2629 pDWP
->acvr
[i
].pos
.cx
= cx
;
2630 pDWP
->acvr
[i
].pos
.cy
= cy
;
2632 pDWP
->acvr
[i
].pos
.flags
&= flags
| ~(SWP_NOSIZE
| SWP_NOMOVE
|
2633 SWP_NOZORDER
| SWP_NOREDRAW
|
2634 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
2636 pDWP
->acvr
[i
].pos
.flags
|= flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
|
2641 if (pDWP
->ccvr
>= pDWP
->ccvrAlloc
)
2643 PCVR newpos
= ExAllocatePoolWithTag(PagedPool
, pDWP
->ccvrAlloc
* 2 * sizeof(CVR
), USERTAG_SWP
);
2649 RtlZeroMemory(newpos
, pDWP
->ccvrAlloc
* 2 * sizeof(CVR
));
2650 RtlCopyMemory(newpos
, pDWP
->acvr
, pDWP
->ccvrAlloc
* sizeof(CVR
));
2651 ExFreePoolWithTag(pDWP
->acvr
, USERTAG_SWP
);
2652 pDWP
->ccvrAlloc
*= 2;
2653 pDWP
->acvr
= newpos
;
2655 pDWP
->acvr
[pDWP
->ccvr
].pos
.hwnd
= hwnd
;
2656 pDWP
->acvr
[pDWP
->ccvr
].pos
.hwndInsertAfter
= hwndAfter
;
2657 pDWP
->acvr
[pDWP
->ccvr
].pos
.x
= x
;
2658 pDWP
->acvr
[pDWP
->ccvr
].pos
.y
= y
;
2659 pDWP
->acvr
[pDWP
->ccvr
].pos
.cx
= cx
;
2660 pDWP
->acvr
[pDWP
->ccvr
].pos
.cy
= cy
;
2661 pDWP
->acvr
[pDWP
->ccvr
].pos
.flags
= flags
;
2662 pDWP
->acvr
[pDWP
->ccvr
].hrgnClip
= NULL
;
2663 pDWP
->acvr
[pDWP
->ccvr
].hrgnInterMonitor
= NULL
;
2669 BOOL FASTCALL
IntEndDeferWindowPosEx( HDWP hdwp
, BOOL sAsync
)
2676 TRACE("%p\n", hdwp
);
2678 if (!(pDWP
= (PSMWP
)UserGetObject(gHandleTable
, hdwp
, TYPE_SETWINDOWPOS
)))
2680 EngSetLastError(ERROR_INVALID_DWP_HANDLE
);
2684 for (i
= 0, winpos
= pDWP
->acvr
; res
&& i
< pDWP
->ccvr
; i
++, winpos
++)
2687 USER_REFERENCE_ENTRY Ref
;
2689 TRACE("hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
2690 winpos
->pos
.hwnd
, winpos
->pos
.hwndInsertAfter
, winpos
->pos
.x
, winpos
->pos
.y
,
2691 winpos
->pos
.cx
, winpos
->pos
.cy
, winpos
->pos
.flags
);
2693 pwnd
= ValidateHwndNoErr(winpos
->pos
.hwnd
);
2697 UserRefObjectCo(pwnd
, &Ref
);
2702 PWINDOWPOS ppos
= ExAllocatePoolWithTag(PagedPool
, sizeof(WINDOWPOS
), USERTAG_SWP
);
2705 *ppos
= winpos
->pos
;
2706 /* Yes it's a pointer inside Win32k! */
2707 lRes
= co_IntSendMessageNoWait( winpos
->pos
.hwnd
, WM_ASYNC_SETWINDOWPOS
, 0, (LPARAM
)ppos
);
2708 /* We handle this the same way as Event Hooks and Hooks. */
2711 ExFreePoolWithTag(ppos
, USERTAG_SWP
);
2716 res
= co_WinPosSetWindowPos( pwnd
,
2717 winpos
->pos
.hwndInsertAfter
,
2724 // Hack to pass tests.... Must have some work to do so clear the error.
2725 if (res
&& (winpos
->pos
.flags
& (SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOZORDER
)) == SWP_NOZORDER
)
2726 EngSetLastError(ERROR_SUCCESS
);
2728 UserDerefObjectCo(pwnd
);
2730 ExFreePoolWithTag(pDWP
->acvr
, USERTAG_SWP
);
2731 UserDereferenceObject(pDWP
);
2732 UserDeleteObject(hdwp
, TYPE_SETWINDOWPOS
);
2740 NtUserChildWindowFromPointEx(HWND hwndParent
,
2746 TRACE("Enter NtUserChildWindowFromPointEx\n");
2747 UserEnterExclusive();
2748 if ((pwndParent
= UserGetWindowObject(hwndParent
)))
2750 pwndParent
= IntChildWindowFromPointEx(pwndParent
, x
, y
, uiFlags
);
2753 TRACE("Leave NtUserChildWindowFromPointEx\n");
2754 return pwndParent
? UserHMGetHandle(pwndParent
) : NULL
;
2761 NtUserEndDeferWindowPosEx(HDWP WinPosInfo
,
2765 TRACE("Enter NtUserEndDeferWindowPosEx\n");
2766 UserEnterExclusive();
2767 Ret
= IntEndDeferWindowPosEx(WinPosInfo
, (BOOL
)Unknown1
);
2768 TRACE("Leave NtUserEndDeferWindowPosEx, ret=%i\n", Ret
);
2777 NtUserDeferWindowPos(HDWP WinPosInfo
,
2779 HWND WndInsertAfter
,
2788 UINT Tmp
= ~(SWP_ASYNCWINDOWPOS
|SWP_DEFERERASE
|SWP_NOSENDCHANGING
|SWP_NOREPOSITION
|
2789 SWP_NOCOPYBITS
|SWP_HIDEWINDOW
|SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|
2790 SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_NOZORDER
|SWP_NOMOVE
|SWP_NOSIZE
);
2792 TRACE("Enter NtUserDeferWindowPos\n");
2793 UserEnterExclusive();
2797 EngSetLastError(ERROR_INVALID_FLAGS
);
2801 pWnd
= UserGetWindowObject(Wnd
);
2802 if ( !pWnd
|| // FIXME:
2803 pWnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
2804 pWnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
2809 if ( WndInsertAfter
&&
2810 WndInsertAfter
!= HWND_BOTTOM
&&
2811 WndInsertAfter
!= HWND_TOPMOST
&&
2812 WndInsertAfter
!= HWND_NOTOPMOST
)
2814 pWndIA
= UserGetWindowObject(WndInsertAfter
);
2816 pWndIA
== UserGetDesktopWindow() ||
2817 pWndIA
== UserGetMessageWindow() )
2823 Ret
= IntDeferWindowPos(WinPosInfo
, Wnd
, WndInsertAfter
, x
, y
, cx
, cy
, Flags
);
2826 TRACE("Leave NtUserDeferWindowPos, ret=%p\n", Ret
);
2835 NtUserGetInternalWindowPos( HWND hWnd
,
2842 WINDOWPLACEMENT wndpl
;
2846 if (!(Window
= UserGetWindowObject(hWnd
)))
2856 ProbeForWrite(rectWnd
,
2862 ProbeForWrite(ptIcon
,
2868 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2870 SetLastNtError(_SEH2_GetExceptionCode());
2875 wndpl
.length
= sizeof(WINDOWPLACEMENT
);
2877 if (IntGetWindowPlacement(Window
, &wndpl
) && !Hit
)
2883 RtlCopyMemory(rectWnd
, &wndpl
.rcNormalPosition
, sizeof(RECT
));
2887 RtlCopyMemory(ptIcon
, &wndpl
.ptMinPosition
, sizeof(POINT
));
2891 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2893 SetLastNtError(_SEH2_GetExceptionCode());
2898 if (!Hit
) Ret
= wndpl
.showCmd
;
2909 NtUserGetWindowPlacement(HWND hWnd
,
2910 WINDOWPLACEMENT
*lpwndpl
)
2913 WINDOWPLACEMENT Safepl
;
2915 DECLARE_RETURN(BOOL
);
2917 TRACE("Enter NtUserGetWindowPlacement\n");
2920 if (!(Wnd
= UserGetWindowObject(hWnd
)))
2925 Status
= MmCopyFromCaller(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
2926 if(!NT_SUCCESS(Status
))
2928 SetLastNtError(Status
);
2931 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
2936 IntGetWindowPlacement(Wnd
, &Safepl
);
2938 Status
= MmCopyToCaller(lpwndpl
, &Safepl
, sizeof(WINDOWPLACEMENT
));
2939 if(!NT_SUCCESS(Status
))
2941 SetLastNtError(Status
);
2948 TRACE("Leave NtUserGetWindowPlacement, ret=%i\n",_ret_
);
2957 UINT cmd
, // Wine SW_ commands
2962 TRACE("Enter NtUserMinMaximize\n");
2963 UserEnterExclusive();
2965 pWnd
= UserGetWindowObject(hWnd
);
2966 if ( !pWnd
|| // FIXME:
2967 pWnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
2968 pWnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
2973 if ( cmd
> SW_MAX
|| pWnd
->state2
& WNDS2_INDESTROY
)
2975 EngSetLastError(ERROR_INVALID_PARAMETER
);
2979 cmd
|= Hide
? SW_HIDE
: 0;
2981 co_WinPosShowWindow(pWnd
, cmd
);
2984 TRACE("Leave NtUserMinMaximize\n");
2986 return 0; // Always NULL?
3001 return NtUserSetWindowPos(hWnd
, 0, X
, Y
, nWidth
, nHeight
,
3002 (bRepaint
? SWP_NOZORDER
| SWP_NOACTIVATE
:
3003 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
));
3010 NtUserRealChildWindowFromPoint(HWND Parent
,
3015 TRACE("Enter NtUserRealChildWindowFromPoint\n");
3017 if ((pwndParent
= UserGetWindowObject(Parent
)))
3019 pwndParent
= IntRealChildWindowFromPoint(pwndParent
, x
, y
);
3022 TRACE("Leave NtUserRealChildWindowFromPoint\n");
3023 return pwndParent
? UserHMGetHandle(pwndParent
) : NULL
;
3032 HWND hWndInsertAfter
,
3039 DECLARE_RETURN(BOOL
);
3040 PWND Window
, pWndIA
;
3042 USER_REFERENCE_ENTRY Ref
;
3044 TRACE("Enter NtUserSetWindowPos\n");
3045 UserEnterExclusive();
3047 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
3048 Window
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3049 Window
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3051 ERR("NtUserSetWindowPos bad window handle!\n");
3055 if ( hWndInsertAfter
&&
3056 hWndInsertAfter
!= HWND_BOTTOM
&&
3057 hWndInsertAfter
!= HWND_TOPMOST
&&
3058 hWndInsertAfter
!= HWND_NOTOPMOST
)
3060 if (!(pWndIA
= UserGetWindowObject(hWndInsertAfter
)) ||
3061 pWndIA
== UserGetDesktopWindow() ||
3062 pWndIA
== UserGetMessageWindow() )
3064 ERR("NtUserSetWindowPos bad insert window handle!\n");
3069 /* First make sure that coordinates are valid for WM_WINDOWPOSCHANGING */
3070 if (!(uFlags
& SWP_NOMOVE
))
3072 if (X
< -32768) X
= -32768;
3073 else if (X
> 32767) X
= 32767;
3074 if (Y
< -32768) Y
= -32768;
3075 else if (Y
> 32767) Y
= 32767;
3077 if (!(uFlags
& SWP_NOSIZE
))
3080 else if (cx
> 32767) cx
= 32767;
3082 else if (cy
> 32767) cy
= 32767;
3085 UserRefObjectCo(Window
, &Ref
);
3086 ret
= co_WinPosSetWindowPos(Window
, hWndInsertAfter
, X
, Y
, cx
, cy
, uFlags
);
3087 UserDerefObjectCo(Window
);
3092 TRACE("Leave NtUserSetWindowPos, ret=%i\n",_ret_
);
3106 HRGN hrgnCopy
= NULL
;
3108 INT flags
= (SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
);
3109 BOOLEAN Ret
= FALSE
;
3110 DECLARE_RETURN(INT
);
3112 TRACE("Enter NtUserSetWindowRgn\n");
3113 UserEnterExclusive();
3115 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
3116 Window
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3117 Window
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3122 if (hRgn
) // The region will be deleted in user32.
3124 if (GreIsHandleValid(hRgn
))
3126 hrgnCopy
= NtGdiCreateRectRgn(0, 0, 0, 0);
3127 /* The coordinates of a window's window region are relative to the
3128 upper-left corner of the window, not the client area of the window. */
3129 NtGdiCombineRgn( hrgnCopy
, hRgn
, 0, RGN_COPY
);
3135 if (Window
->hrgnClip
)
3137 /* Delete no longer needed region handle */
3138 IntGdiSetRegionOwner(Window
->hrgnClip
, GDI_OBJ_HMGR_POWNED
);
3139 GreDeleteObject(Window
->hrgnClip
);
3144 /* Set public ownership */
3145 IntGdiSetRegionOwner(hrgnCopy
, GDI_OBJ_HMGR_PUBLIC
);
3147 Window
->hrgnClip
= hrgnCopy
;
3149 Ret
= co_WinPosSetWindowPos(Window
, HWND_TOP
, 0, 0, 0, 0, bRedraw
? flags
: (flags
|SWP_NOREDRAW
) );
3154 TRACE("Leave NtUserSetWindowRgn, ret=%i\n",_ret_
);
3163 NtUserSetInternalWindowPos(
3169 WINDOWPLACEMENT wndpl
;