2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
5 * FILE: subsystems/win32/win32k/ntuser/window.c
6 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
10 DBG_DEFAULT_CHANNEL(UserWinpos
);
12 /* GLOBALS *******************************************************************/
14 #define MINMAX_NOSWP (0x00010000)
16 #define SWP_EX_NOCOPY 0x0001
17 #define SWP_EX_PAINTSELF 0x0002
19 #define SWP_AGG_NOGEOMETRYCHANGE \
20 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
21 #define SWP_AGG_NOPOSCHANGE \
22 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
23 #define SWP_AGG_STATUSFLAGS \
24 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
26 #define EMPTYPOINT(pt) ((pt).x == -1 && (pt).y == -1)
27 #define PLACE_MIN 0x0001
28 #define PLACE_MAX 0x0002
29 #define PLACE_RECT 0x0004
31 VOID FASTCALL
IntLinkWindow(PWND Wnd
,PWND WndInsertAfter
);
33 /* FUNCTIONS *****************************************************************/
36 IntGetClientOrigin(PWND Window OPTIONAL
, LPPOINT Point
)
38 Window
= Window
? Window
: UserGetDesktopWindow();
41 Point
->x
= Point
->y
= 0;
44 Point
->x
= Window
->rcClient
.left
;
45 Point
->y
= Window
->rcClient
.top
;
52 * Returns client window rectangle relative to the upper-left corner of client area.
54 * \note Does not check the validity of the parameters
57 IntGetClientRect(PWND Wnd
, RECTL
*Rect
)
61 if (Wnd
->style
& WS_MINIMIZED
)
63 Rect
->left
= Rect
->top
= 0;
64 Rect
->right
= UserGetSystemMetrics(SM_CXMINIMIZED
);
65 Rect
->bottom
= UserGetSystemMetrics(SM_CYMINIMIZED
);
68 if ( Wnd
!= UserGetDesktopWindow()) // Wnd->fnid != FNID_DESKTOP )
70 *Rect
= Wnd
->rcClient
;
71 RECTL_vOffsetRect(Rect
, -Wnd
->rcClient
.left
, -Wnd
->rcClient
.top
);
75 Rect
->left
= Rect
->top
= 0;
76 Rect
->right
= Wnd
->rcClient
.right
;
77 Rect
->bottom
= Wnd
->rcClient
.bottom
;
78 /* Do this until Init bug is fixed. This sets 640x480, see InitMetrics.
79 Rect->right = UserGetSystemMetrics(SM_CXSCREEN);
80 Rect->bottom = UserGetSystemMetrics(SM_CYSCREEN);
86 IntMapWindowPoints(PWND FromWnd
, PWND ToWnd
, LPPOINT lpPoints
, UINT cPoints
)
88 BOOL mirror_from
, mirror_to
;
93 /* Note: Desktop Top and Left is always 0! */
94 Delta
.x
= Delta
.y
= 0;
95 mirror_from
= mirror_to
= FALSE
;
97 if (FromWnd
&& FromWnd
!= UserGetDesktopWindow()) // FromWnd->fnid != FNID_DESKTOP)
99 if (FromWnd
->ExStyle
& WS_EX_LAYOUTRTL
)
103 Delta
.x
= -FromWnd
->rcClient
.right
;
106 Delta
.x
= FromWnd
->rcClient
.left
;
107 Delta
.y
= FromWnd
->rcClient
.top
;
110 if (ToWnd
&& ToWnd
!= UserGetDesktopWindow()) // ToWnd->fnid != FNID_DESKTOP)
112 if (ToWnd
->ExStyle
& WS_EX_LAYOUTRTL
)
116 Delta
.x
+= Change
* ToWnd
->rcClient
.right
;
119 Delta
.x
-= Change
* ToWnd
->rcClient
.left
;
120 Delta
.y
-= ToWnd
->rcClient
.top
;
123 for (i
= 0; i
!= cPoints
; i
++)
125 lpPoints
[i
].x
+= Delta
.x
;
126 lpPoints
[i
].x
*= Change
;
127 lpPoints
[i
].y
+= Delta
.y
;
130 if ((mirror_from
|| mirror_to
) && cPoints
== 2) /* special case for rectangle */
132 int tmp
= min(lpPoints
[0].x
, lpPoints
[1].x
);
133 lpPoints
[1].x
= max(lpPoints
[0].x
, lpPoints
[1].x
);
137 return MAKELONG(LOWORD(Delta
.x
), LOWORD(Delta
.y
));
141 IntClientToScreen(PWND Wnd
, LPPOINT lpPoint
)
143 if (Wnd
&& Wnd
->fnid
!= FNID_DESKTOP
)
145 if (Wnd
->ExStyle
& WS_EX_LAYOUTRTL
)
146 lpPoint
->x
= Wnd
->rcClient
.right
- lpPoint
->x
;
148 lpPoint
->x
+= Wnd
->rcClient
.left
;
149 lpPoint
->y
+= Wnd
->rcClient
.top
;
155 IntScreenToClient(PWND Wnd
, LPPOINT lpPoint
)
157 if (Wnd
&& Wnd
->fnid
!= FNID_DESKTOP
)
159 if (Wnd
->ExStyle
& WS_EX_LAYOUTRTL
)
160 lpPoint
->x
= Wnd
->rcClient
.right
- lpPoint
->x
;
162 lpPoint
->x
-= Wnd
->rcClient
.left
;
163 lpPoint
->y
-= Wnd
->rcClient
.top
;
168 BOOL FASTCALL
IsChildVisible(PWND pWnd
)
172 if ( (pWnd
->style
& (WS_POPUP
|WS_CHILD
)) != WS_CHILD
||
173 !(pWnd
= pWnd
->spwndParent
) )
176 while (pWnd
->style
& WS_VISIBLE
);
180 PWND FASTCALL
IntGetLastTopMostWindow(VOID
)
183 PDESKTOP rpdesk
= gptiCurrent
->rpdesk
;
186 (pWnd
= rpdesk
->pDeskInfo
->spwnd
->spwndChild
) &&
187 pWnd
->ExStyle
& WS_EX_TOPMOST
)
191 if (!pWnd
->spwndNext
) break;
192 if (!(pWnd
->spwndNext
->ExStyle
& WS_EX_TOPMOST
)) break;
193 pWnd
= pWnd
->spwndNext
;
201 // This helps with CORE-6129 forcing modal dialog active when another app is minimized or closed.
203 BOOL FASTCALL
ActivateOtherWindowMin(PWND Wnd
)
205 BOOL ActivePrev
, FindTopWnd
;
206 PWND pWndTopMost
, pWndChild
, pWndSetActive
, pWndTemp
, pWndDesk
;
207 USER_REFERENCE_ENTRY Ref
;
208 PTHREADINFO pti
= gptiCurrent
;
211 ActivePrev
= (pti
->MessageQueue
->spwndActivePrev
!= NULL
);
214 if ((pWndTopMost
= IntGetLastTopMostWindow()))
215 pWndChild
= pWndTopMost
->spwndNext
;
217 pWndChild
= Wnd
->spwndParent
->spwndChild
;
222 pWndSetActive
= pti
->MessageQueue
->spwndActivePrev
;
224 pWndSetActive
= pWndChild
;
230 if ( VerifyWnd(pWndSetActive
) &&
231 !(pWndSetActive
->ExStyle
& WS_EX_NOACTIVATE
) &&
232 (pWndSetActive
->style
& (WS_VISIBLE
|WS_DISABLED
)) == WS_VISIBLE
&&
233 (!(pWndSetActive
->style
& WS_ICONIC
) /* FIXME MinMax pos? */ ) )
235 if (!(pWndSetActive
->ExStyle
& WS_EX_TOOLWINDOW
) )
237 UserRefObjectCo(pWndSetActive
, &Ref
);
238 //ERR("ActivateOtherWindowMin Set FG 1\n");
239 co_IntSetForegroundWindow(pWndSetActive
);
240 UserDerefObjectCo(pWndSetActive
);
241 //ERR("AOWM 2 Exit Good\n");
244 if (!pWndTemp
) pWndTemp
= pWndSetActive
;
249 pWndSetActive
= pWndChild
;
252 pWndSetActive
= pWndSetActive
->spwndNext
;
255 if ( !FindTopWnd
) break;
260 pWndChild
= pWndChild
->spwndParent
->spwndChild
;
264 if (!(pWndDesk
= IntGetThreadDesktopWindow(pti
)))
269 pWndChild
= pWndDesk
->spwndChild
;
272 if ((pWndSetActive
= pWndTemp
))
274 UserRefObjectCo(pWndSetActive
, &Ref
);
275 //ERR("ActivateOtherWindowMin Set FG 2\n");
276 co_IntSetForegroundWindow(pWndSetActive
);
277 UserDerefObjectCo(pWndSetActive
);
278 //ERR("AOWM 3 Exit Good\n");
281 //ERR("AOWM 4 Bad\n");
285 /*******************************************************************
286 * can_activate_window
288 * Check if we can activate the specified window.
291 BOOL FASTCALL
can_activate_window( PWND Wnd OPTIONAL
)
295 if (!Wnd
) return FALSE
;
298 if (!(style
& WS_VISIBLE
)) return FALSE
;
299 if (style
& WS_MINIMIZE
) return FALSE
;
300 if ((style
& (WS_POPUP
|WS_CHILD
)) == WS_CHILD
) return FALSE
;
302 /* FIXME: This window could be disable because the child that closed
304 //return !(style & WS_DISABLED);
308 /*******************************************************************
309 * WinPosActivateOtherWindow
311 * Activates window other than pWnd.
314 co_WinPosActivateOtherWindow(PWND Wnd
)
317 USER_REFERENCE_ENTRY Ref
;
321 if (IntIsDesktopWindow(Wnd
))
323 IntSetFocusMessageQueue(NULL
);
327 /* If this is popup window, try to activate the owner first. */
328 if ((Wnd
->style
& WS_POPUP
) && (WndTo
= Wnd
->spwndOwner
))
330 WndTo
= UserGetAncestor( WndTo
, GA_ROOT
);
331 if (can_activate_window(WndTo
)) goto done
;
334 /* Pick a next top-level window. */
335 /* FIXME: Search for non-tooltip windows first. */
339 if (!(WndTo
= WndTo
->spwndNext
)) break;
340 if (can_activate_window( WndTo
)) break;
345 if (WndTo
) UserRefObjectCo(WndTo
, &Ref
);
347 if (!gpqForeground
|| Wnd
== gpqForeground
->spwndActive
)
349 /* ReactOS can pass WndTo = NULL to co_IntSetForegroundWindow and returns FALSE. */
350 //ERR("WinPosActivateOtherWindow Set FG 0x%p\n",WndTo);
351 if (co_IntSetForegroundWindow(WndTo
))
353 if (WndTo
) UserDerefObjectCo(WndTo
);
357 //ERR("WinPosActivateOtherWindow Set Active 0x%p\n",WndTo);
358 if (!co_IntSetActiveWindow(WndTo
,FALSE
,TRUE
,FALSE
)) /* Ok for WndTo to be NULL here */
360 co_IntSetActiveWindow(NULL
,FALSE
,TRUE
,FALSE
);
362 if (WndTo
) UserDerefObjectCo(WndTo
);
366 WinPosInitInternalPos(PWND Wnd
, RECTL
*RestoreRect
)
369 RECTL Rect
= *RestoreRect
;
371 if (Wnd
->spwndParent
!= UserGetDesktopWindow())
373 RECTL_vOffsetRect(&Rect
,
374 -Wnd
->spwndParent
->rcClient
.left
,
375 -Wnd
->spwndParent
->rcClient
.top
);
381 if (!Wnd
->InternalPosInitialized
)
383 // FIXME: Use check point Atom..
384 Wnd
->InternalPos
.flags
= 0;
385 Wnd
->InternalPos
.MaxPos
.x
= Wnd
->InternalPos
.MaxPos
.y
= -1;
386 Wnd
->InternalPos
.IconPos
.x
= Wnd
->InternalPos
.IconPos
.y
= -1;
387 Wnd
->InternalPos
.NormalRect
= Rect
;
388 Wnd
->InternalPosInitialized
= TRUE
;
391 if (Wnd
->style
& WS_MINIMIZE
)
393 Wnd
->InternalPos
.IconPos
= Size
;
394 Wnd
->InternalPos
.flags
|= WPF_MININIT
;
396 else if (Wnd
->style
& WS_MAXIMIZE
)
398 Wnd
->InternalPos
.flags
|= WPF_MAXINIT
;
400 if ( Wnd
->spwndParent
== Wnd
->head
.rpdesk
->pDeskInfo
->spwnd
)
402 if (Wnd
->state
& WNDS_MAXIMIZESTOMONITOR
)
404 Wnd
->InternalPos
.flags
&= ~WPF_MAXINIT
;
405 Wnd
->InternalPos
.MaxPos
.x
= Wnd
->InternalPos
.MaxPos
.y
= -1;
410 PMONITOR pmonitor
= UserMonitorFromRect(&Rect
, MONITOR_DEFAULTTOPRIMARY
);
411 // FIXME: support DPI aware, rcWorkDPI/Real etc..
412 WorkArea
= pmonitor
->rcMonitor
;
414 if (Wnd
->style
& WS_MAXIMIZEBOX
)
415 { // Support (Wnd->state & WNDS_HASCAPTION) || pmonitor->cFullScreen too.
416 if ((Wnd
->style
& WS_CAPTION
) == WS_CAPTION
|| !(Wnd
->style
& (WS_CHILD
| WS_POPUP
)))
418 WorkArea
= pmonitor
->rcWork
;
423 Wnd
->InternalPos
.MaxPos
.x
= Rect
.left
- WorkArea
.left
;
424 Wnd
->InternalPos
.MaxPos
.y
= Rect
.top
- WorkArea
.top
;
426 /*ERR("WinPosIP 2 X %d = R.l %d - W.l %d | Y %d = R.t %d - W.t %d\n",
427 Wnd->InternalPos.MaxPos.x,
428 Rect.left, WorkArea.left,
429 Wnd->InternalPos.MaxPos.y,
430 Rect.top, WorkArea.top);*/
434 Wnd
->InternalPos
.MaxPos
= Size
;
438 Wnd
->InternalPos
.NormalRect
= Rect
;
444 IntGetWindowPlacement(PWND Wnd
, WINDOWPLACEMENT
*lpwndpl
)
446 if (!Wnd
) return FALSE
;
448 if(lpwndpl
->length
!= sizeof(WINDOWPLACEMENT
))
455 WinPosInitInternalPos(Wnd
, &Wnd
->rcWindow
);
457 lpwndpl
->showCmd
= SW_HIDE
;
459 if ( Wnd
->style
& WS_MINIMIZE
)
460 lpwndpl
->showCmd
= SW_SHOWMINIMIZED
;
462 lpwndpl
->showCmd
= ( Wnd
->style
& WS_MAXIMIZE
) ? SW_SHOWMAXIMIZED
: SW_SHOWNORMAL
;
464 lpwndpl
->rcNormalPosition
= Wnd
->InternalPos
.NormalRect
;
466 if (Wnd
->InternalPos
.flags
& WPF_MININIT
) // Return if it was set!
468 lpwndpl
->ptMinPosition
.x
= Wnd
->InternalPos
.IconPos
.x
;
469 lpwndpl
->ptMinPosition
.y
= Wnd
->InternalPos
.IconPos
.y
;
472 lpwndpl
->ptMinPosition
.x
= lpwndpl
->ptMinPosition
.y
= -1;
474 if ( Wnd
->InternalPos
.flags
& WPF_MAXINIT
&& // Return if set and not maximized to monitor!
475 !(Wnd
->state
& WNDS_MAXIMIZESTOMONITOR
))
477 lpwndpl
->ptMaxPosition
.x
= Wnd
->InternalPos
.MaxPos
.x
;
478 lpwndpl
->ptMaxPosition
.y
= Wnd
->InternalPos
.MaxPos
.y
;
481 lpwndpl
->ptMaxPosition
.x
= lpwndpl
->ptMaxPosition
.y
= -1;
483 if ( Wnd
->spwndParent
== Wnd
->head
.rpdesk
->pDeskInfo
->spwnd
&&
484 !(Wnd
->ExStyle
& WS_EX_TOOLWINDOW
))
486 PMONITOR pmonitor
= UserMonitorFromRect(&lpwndpl
->rcNormalPosition
, MONITOR_DEFAULTTOPRIMARY
);
488 // FIXME: support DPI aware, rcWorkDPI/Real etc..
489 if (Wnd
->InternalPos
.flags
& WPF_MININIT
)
491 lpwndpl
->ptMinPosition
.x
-= (pmonitor
->rcWork
.left
- pmonitor
->rcMonitor
.left
);
492 lpwndpl
->ptMinPosition
.y
-= (pmonitor
->rcWork
.top
- pmonitor
->rcMonitor
.top
);
494 RECTL_vOffsetRect(&lpwndpl
->rcNormalPosition
,
495 pmonitor
->rcMonitor
.left
- pmonitor
->rcWork
.left
,
496 pmonitor
->rcMonitor
.top
- pmonitor
->rcWork
.top
);
499 if ( Wnd
->InternalPos
.flags
& WPF_RESTORETOMAXIMIZED
|| Wnd
->style
& WS_MAXIMIZE
)
500 lpwndpl
->flags
|= WPF_RESTORETOMAXIMIZED
;
502 if ( ((Wnd
->style
& (WS_CHILD
|WS_POPUP
)) == WS_CHILD
) && Wnd
->InternalPos
.flags
& WPF_SETMINPOSITION
)
503 lpwndpl
->flags
|= WPF_SETMINPOSITION
;
508 /* make sure the specified rect is visible on screen */
509 static void make_rect_onscreen( RECT
*rect
)
511 PMONITOR pmonitor
= UserMonitorFromRect( rect
, MONITOR_DEFAULTTONEAREST
); // Wine uses this.
513 // FIXME: support DPI aware, rcWorkDPI/Real etc..
514 if (!pmonitor
) return;
515 /* FIXME: map coordinates from rcWork to rcMonitor */
516 if (rect
->right
<= pmonitor
->rcWork
.left
)
518 rect
->right
+= pmonitor
->rcWork
.left
- rect
->left
;
519 rect
->left
= pmonitor
->rcWork
.left
;
521 else if (rect
->left
>= pmonitor
->rcWork
.right
)
523 rect
->left
+= pmonitor
->rcWork
.right
- rect
->right
;
524 rect
->right
= pmonitor
->rcWork
.right
;
526 if (rect
->bottom
<= pmonitor
->rcWork
.top
)
528 rect
->bottom
+= pmonitor
->rcWork
.top
- rect
->top
;
529 rect
->top
= pmonitor
->rcWork
.top
;
531 else if (rect
->top
>= pmonitor
->rcWork
.bottom
)
533 rect
->top
+= pmonitor
->rcWork
.bottom
- rect
->bottom
;
534 rect
->bottom
= pmonitor
->rcWork
.bottom
;
538 /* make sure the specified point is visible on screen */
539 static void make_point_onscreen( POINT
*pt
)
543 RECTL_vSetRect( &rect
, pt
->x
, pt
->y
, pt
->x
+ 1, pt
->y
+ 1 );
544 make_rect_onscreen( &rect
);
550 IntSetWindowPlacement(PWND Wnd
, WINDOWPLACEMENT
*wpl
, UINT Flags
)
555 if ( Flags
& PLACE_MIN
) make_point_onscreen( &wpl
->ptMinPosition
);
556 if ( Flags
& PLACE_MAX
) make_point_onscreen( &wpl
->ptMaxPosition
);
557 if ( Flags
& PLACE_RECT
) make_rect_onscreen( &wpl
->rcNormalPosition
);
559 if (!Wnd
|| Wnd
== Wnd
->head
.rpdesk
->pDeskInfo
->spwnd
) return FALSE
;
561 if ( Flags
& PLACE_MIN
) Wnd
->InternalPos
.IconPos
= wpl
->ptMinPosition
;
562 if ( Flags
& PLACE_MAX
) Wnd
->InternalPos
.MaxPos
= wpl
->ptMaxPosition
;
563 if ( Flags
& PLACE_RECT
) Wnd
->InternalPos
.NormalRect
= wpl
->rcNormalPosition
;
565 SWP_Flags
= SWP_NOZORDER
| SWP_NOACTIVATE
| ((wpl
->flags
& WPF_ASYNCWINDOWPLACEMENT
) ? SWP_ASYNCWINDOWPOS
: 0);
567 if (Wnd
->style
& WS_MINIMIZE
)
569 if (Flags
& PLACE_MIN
|| Wnd
->InternalPos
.flags
& WPF_SETMINPOSITION
)
571 co_WinPosSetWindowPos(Wnd
, HWND_TOP
,
572 wpl
->ptMinPosition
.x
, wpl
->ptMinPosition
.y
, 0, 0,
573 SWP_NOSIZE
| SWP_Flags
);
574 Wnd
->InternalPos
.flags
|= WPF_MININIT
;
577 else if (Wnd
->style
& WS_MAXIMIZE
)
579 if (Flags
& PLACE_MAX
)
581 co_WinPosSetWindowPos(Wnd
, HWND_TOP
,
582 wpl
->ptMaxPosition
.x
, wpl
->ptMaxPosition
.y
, 0, 0,
583 SWP_NOSIZE
| SWP_Flags
);
584 Wnd
->InternalPos
.flags
|= WPF_MAXINIT
;
587 else if (Flags
& PLACE_RECT
)
589 co_WinPosSetWindowPos(Wnd
, HWND_TOP
,
590 wpl
->rcNormalPosition
.left
, wpl
->rcNormalPosition
.top
,
591 wpl
->rcNormalPosition
.right
- wpl
->rcNormalPosition
.left
,
592 wpl
->rcNormalPosition
.bottom
- wpl
->rcNormalPosition
.top
,
596 sAsync
= (Wnd
->head
.pti
->MessageQueue
!= gptiCurrent
->MessageQueue
&& wpl
->flags
& WPF_ASYNCWINDOWPLACEMENT
);
599 co_IntSendMessageNoWait( UserHMGetHandle(Wnd
), WM_ASYNC_SHOWWINDOW
, wpl
->showCmd
, 0 );
601 co_WinPosShowWindow(Wnd
, wpl
->showCmd
);
603 if ( Wnd
->style
& WS_MINIMIZE
&& !sAsync
)
605 if ( wpl
->flags
& WPF_SETMINPOSITION
)
606 Wnd
->InternalPos
.flags
|= WPF_SETMINPOSITION
;
608 if ( wpl
->flags
& WPF_RESTORETOMAXIMIZED
)
609 Wnd
->InternalPos
.flags
|= WPF_RESTORETOMAXIMIZED
;
616 co_WinPosArrangeIconicWindows(PWND parent
)
620 INT x
, y
, xspacing
, yspacing
, sx
, sy
;
622 ASSERT_REFS_CO(parent
);
624 IntGetClientRect( parent
, &rectParent
);
625 // FIXME: Support Minimize Metrics gspv.mm.iArrange.
626 // Default: ARW_BOTTOMLEFT
628 y
= rectParent
.bottom
;
630 xspacing
= UserGetSystemMetrics(SM_CXMINIMIZED
);
631 yspacing
= UserGetSystemMetrics(SM_CYMINIMIZED
);
633 Child
= parent
->spwndChild
;
636 if((Child
->style
& WS_MINIMIZE
) != 0 )
638 USER_REFERENCE_ENTRY Ref
;
639 UserRefObjectCo(Child
, &Ref
);
641 sx
= x
+ UserGetSystemMetrics(SM_CXBORDER
);
642 sy
= y
- yspacing
- UserGetSystemMetrics(SM_CYBORDER
);
644 Child
->InternalPos
.IconPos
.x
= sx
;
645 Child
->InternalPos
.IconPos
.y
= sy
;
646 Child
->InternalPos
.flags
|= WPF_MININIT
;
648 co_WinPosSetWindowPos( Child
, 0, sx
, sy
, xspacing
, yspacing
, SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOCOPYBITS
| SWP_ASYNCWINDOWPOS
);
650 UserDerefObjectCo(Child
);
652 if (x
<= rectParent
.right
- xspacing
)
660 Child
= Child
->spwndNext
;
666 WinPosFindIconPos(PWND Window
, POINT
*Pos
)
669 PWND pwndChild
, pwndParent
;
670 int x
, y
, xspacing
, yspacing
;
672 pwndParent
= Window
->spwndParent
;
673 if (pwndParent
== UserGetDesktopWindow())
675 //ERR("Parent is Desktop, Min off screen!\n");
676 /* ReactOS doesn't support iconic minimize to desktop */
677 Pos
->x
= Pos
->y
= -32000;
678 Window
->InternalPos
.flags
|= WPF_MININIT
;
679 Window
->InternalPos
.IconPos
.x
= Pos
->x
;
680 Window
->InternalPos
.IconPos
.y
= Pos
->y
;
684 IntGetClientRect( pwndParent
, &rectParent
);
685 // FIXME: Support Minimize Metrics gspv.mm.iArrange.
686 // Default: ARW_BOTTOMLEFT
688 y
= rectParent
.bottom
;
690 xspacing
= UserGetSystemMetrics(SM_CXMINIMIZED
);
691 yspacing
= UserGetSystemMetrics(SM_CYMINIMIZED
);
693 // Set to default position when minimized.
694 Pos
->x
= x
+ UserGetSystemMetrics(SM_CXBORDER
);
695 Pos
->y
= y
- yspacing
- UserGetSystemMetrics(SM_CYBORDER
);
697 for (pwndChild
= pwndParent
->spwndChild
; pwndChild
; pwndChild
= pwndChild
->spwndNext
)
699 if (pwndChild
== Window
) continue;
701 if ((pwndChild
->style
& (WS_VISIBLE
|WS_MINIMIZE
)) != (WS_VISIBLE
|WS_MINIMIZE
) )
706 if ( pwndChild
->InternalPos
.IconPos
.x
!= Pos
->x
&& pwndChild
->InternalPos
.IconPos
.y
!= Pos
->y
)
710 if (x
<= rectParent
.right
- xspacing
)
717 Pos
->x
= x
+ UserGetSystemMetrics(SM_CXBORDER
);
718 Pos
->y
= y
- yspacing
- UserGetSystemMetrics(SM_CYBORDER
);
721 Window
->InternalPos
.IconPos
.x
= Pos
->x
;
722 Window
->InternalPos
.IconPos
.y
= Pos
->y
;
723 Window
->InternalPos
.flags
|= WPF_MININIT
;
724 TRACE("Position is set! X:%d Y:%d\n",Pos
->x
,Pos
->y
);
729 co_WinPosMinMaximize(PWND Wnd
, UINT ShowFlag
, RECT
* NewPos
)
738 wpl
.length
= sizeof(wpl
);
739 IntGetWindowPlacement( Wnd
, &wpl
);
741 if (co_HOOK_CallHooks( WH_CBT
, HCBT_MINMAX
, (WPARAM
)Wnd
->head
.h
, ShowFlag
))
743 ERR("WinPosMinMaximize WH_CBT Call Hook return!\n");
744 return SWP_NOSIZE
| SWP_NOMOVE
;
746 if (Wnd
->style
& WS_MINIMIZE
)
750 case SW_SHOWMINNOACTIVE
:
751 case SW_SHOWMINIMIZED
:
752 case SW_FORCEMINIMIZE
:
754 return SWP_NOSIZE
| SWP_NOMOVE
;
756 if (!co_IntSendMessageNoWait(Wnd
->head
.h
, WM_QUERYOPEN
, 0, 0))
758 return(SWP_NOSIZE
| SWP_NOMOVE
);
760 SwpFlags
|= SWP_NOCOPYBITS
;
764 case SW_SHOWMINNOACTIVE
:
765 case SW_SHOWMINIMIZED
:
766 case SW_FORCEMINIMIZE
:
769 //ERR("MinMaximize Minimize\n");
770 if (Wnd
->style
& WS_MAXIMIZE
)
772 Wnd
->InternalPos
.flags
|= WPF_RESTORETOMAXIMIZED
;
776 Wnd
->InternalPos
.flags
&= ~WPF_RESTORETOMAXIMIZED
;
779 old_style
= IntSetStyle( Wnd
, WS_MINIMIZE
, WS_MAXIMIZE
);
781 co_UserRedrawWindow(Wnd
, NULL
, 0, RDW_VALIDATE
| RDW_NOERASE
| RDW_NOINTERNALPAINT
);
783 if (!(Wnd
->InternalPos
.flags
& WPF_SETMINPOSITION
))
784 Wnd
->InternalPos
.flags
&= ~WPF_MININIT
;
786 WinPosFindIconPos(Wnd
, &wpl
.ptMinPosition
);
788 if (!(old_style
& WS_MINIMIZE
)) SwpFlags
|= SWP_STATECHANGED
;
790 RECTL_vSetRect(NewPos
, wpl
.ptMinPosition
.x
, wpl
.ptMinPosition
.y
,
791 wpl
.ptMinPosition
.x
+ UserGetSystemMetrics(SM_CXMINIMIZED
),
792 wpl
.ptMinPosition
.y
+ UserGetSystemMetrics(SM_CYMINIMIZED
));
793 SwpFlags
|= SWP_NOCOPYBITS
;
799 //ERR("MinMaximize Maximize\n");
800 if ((Wnd
->style
& WS_MAXIMIZE
) && (Wnd
->style
& WS_VISIBLE
))
802 SwpFlags
= SWP_NOSIZE
| SWP_NOMOVE
;
805 co_WinPosGetMinMaxInfo(Wnd
, &Size
, &wpl
.ptMaxPosition
, NULL
, NULL
);
807 /*ERR("Maximize: %d,%d %dx%d\n",
808 wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, Size.x, Size.y);
810 old_style
= IntSetStyle( Wnd
, WS_MAXIMIZE
, WS_MINIMIZE
);
812 if (!(old_style
& WS_MAXIMIZE
)) SwpFlags
|= SWP_STATECHANGED
;
813 RECTL_vSetRect(NewPos
, wpl
.ptMaxPosition
.x
, wpl
.ptMaxPosition
.y
,
814 //wpl.ptMaxPosition.x + Size.x, wpl.ptMaxPosition.y + Size.y);
819 case SW_SHOWNOACTIVATE
:
820 Wnd
->InternalPos
.flags
&= ~WPF_RESTORETOMAXIMIZED
;
824 case SW_SHOWDEFAULT
: /* FIXME: should have its own handler */
826 //ERR("MinMaximize Restore\n");
827 old_style
= IntSetStyle( Wnd
, 0, WS_MINIMIZE
| WS_MAXIMIZE
);
828 if (old_style
& WS_MINIMIZE
)
830 if (Wnd
->InternalPos
.flags
& WPF_RESTORETOMAXIMIZED
)
832 co_WinPosGetMinMaxInfo(Wnd
, &Size
, &wpl
.ptMaxPosition
, NULL
, NULL
);
833 IntSetStyle( Wnd
, WS_MAXIMIZE
, 0 );
834 SwpFlags
|= SWP_STATECHANGED
;
835 RECTL_vSetRect(NewPos
, wpl
.ptMaxPosition
.x
, wpl
.ptMaxPosition
.y
,
836 wpl
.ptMaxPosition
.x
+ Size
.x
, wpl
.ptMaxPosition
.y
+ Size
.y
);
841 *NewPos
= wpl
.rcNormalPosition
;
842 NewPos
->right
-= NewPos
->left
;
843 NewPos
->bottom
-= NewPos
->top
;
849 if (!(old_style
& WS_MAXIMIZE
))
853 SwpFlags
|= SWP_STATECHANGED
;
854 Wnd
->InternalPos
.flags
&= ~WPF_RESTORETOMAXIMIZED
;
855 *NewPos
= wpl
.rcNormalPosition
;
856 NewPos
->right
-= NewPos
->left
;
857 NewPos
->bottom
-= NewPos
->top
;
866 UserHasWindowEdge(DWORD Style
, DWORD ExStyle
)
868 if (Style
& WS_MINIMIZE
)
870 if (ExStyle
& WS_EX_DLGMODALFRAME
)
872 if (ExStyle
& WS_EX_STATICEDGE
)
874 if (Style
& WS_THICKFRAME
)
877 if (Style
== WS_DLGFRAME
|| Style
== WS_CAPTION
)
883 IntGetWindowBorderMeasures(PWND Wnd
, UINT
*cx
, UINT
*cy
)
885 if(HAS_DLGFRAME(Wnd
->style
, Wnd
->ExStyle
) && !(Wnd
->style
& WS_MINIMIZE
))
887 *cx
= UserGetSystemMetrics(SM_CXDLGFRAME
);
888 *cy
= UserGetSystemMetrics(SM_CYDLGFRAME
);
892 if(HAS_THICKFRAME(Wnd
->style
, Wnd
->ExStyle
)&& !(Wnd
->style
& WS_MINIMIZE
))
894 *cx
= UserGetSystemMetrics(SM_CXFRAME
);
895 *cy
= UserGetSystemMetrics(SM_CYFRAME
);
897 else if(HAS_THINFRAME(Wnd
->style
, Wnd
->ExStyle
))
899 *cx
= UserGetSystemMetrics(SM_CXBORDER
);
900 *cy
= UserGetSystemMetrics(SM_CYBORDER
);
910 UserGetWindowBorders(DWORD Style
, DWORD ExStyle
, SIZE
*Size
, BOOL WithClient
)
914 if (UserHasWindowEdge(Style
, ExStyle
))
916 else if (ExStyle
& WS_EX_STATICEDGE
)
918 if ((ExStyle
& WS_EX_CLIENTEDGE
) && WithClient
)
920 if (Style
& WS_CAPTION
|| ExStyle
& WS_EX_DLGMODALFRAME
)
922 Size
->cx
= Size
->cy
= Border
;
923 if ((Style
& WS_THICKFRAME
) && !(Style
& WS_MINIMIZE
))
925 Size
->cx
+= UserGetSystemMetrics(SM_CXFRAME
) - UserGetSystemMetrics(SM_CXDLGFRAME
);
926 Size
->cy
+= UserGetSystemMetrics(SM_CYFRAME
) - UserGetSystemMetrics(SM_CYDLGFRAME
);
928 Size
->cx
*= UserGetSystemMetrics(SM_CXBORDER
);
929 Size
->cy
*= UserGetSystemMetrics(SM_CYBORDER
);
933 UserAdjustWindowRectEx(LPRECT lpRect
,
942 lpRect
->top
-= UserGetSystemMetrics(SM_CYMENU
);
944 if ((dwStyle
& WS_CAPTION
) == WS_CAPTION
)
946 if (dwExStyle
& WS_EX_TOOLWINDOW
)
947 lpRect
->top
-= UserGetSystemMetrics(SM_CYSMCAPTION
);
949 lpRect
->top
-= UserGetSystemMetrics(SM_CYCAPTION
);
951 UserGetWindowBorders(dwStyle
, dwExStyle
, &BorderSize
, TRUE
);
961 co_WinPosGetMinMaxInfo(PWND Window
, POINT
* MaxSize
, POINT
* MaxPos
,
962 POINT
* MinTrack
, POINT
* MaxTrack
)
967 LONG style
= Window
->style
;
969 LONG exstyle
= Window
->ExStyle
;
972 ASSERT_REFS_CO(Window
);
974 /* Compute default values */
976 rc
= Window
->rcWindow
;
977 MinMax
.ptReserved
.x
= rc
.left
;
978 MinMax
.ptReserved
.y
= rc
.top
;
980 if ((style
& WS_CAPTION
) == WS_CAPTION
)
981 adjustedStyle
= style
& ~WS_BORDER
; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
983 adjustedStyle
= style
;
985 if(Window
->spwndParent
)
986 IntGetClientRect(Window
->spwndParent
, &rc
);
987 UserAdjustWindowRectEx(&rc
, adjustedStyle
, ((style
& WS_POPUP
) && Window
->IDMenu
), exstyle
);
992 MinMax
.ptMaxSize
.x
= rc
.right
- rc
.left
;
993 MinMax
.ptMaxSize
.y
= rc
.bottom
- rc
.top
;
994 if (style
& (WS_DLGFRAME
| WS_BORDER
))
996 MinMax
.ptMinTrackSize
.x
= UserGetSystemMetrics(SM_CXMINTRACK
);
997 MinMax
.ptMinTrackSize
.y
= UserGetSystemMetrics(SM_CYMINTRACK
);
1001 MinMax
.ptMinTrackSize
.x
= 2 * xinc
;
1002 MinMax
.ptMinTrackSize
.y
= 2 * yinc
;
1004 MinMax
.ptMaxTrackSize
.x
= UserGetSystemMetrics(SM_CXMAXTRACK
);
1005 MinMax
.ptMaxTrackSize
.y
= UserGetSystemMetrics(SM_CYMAXTRACK
);
1006 MinMax
.ptMaxPosition
.x
= -xinc
;
1007 MinMax
.ptMaxPosition
.y
= -yinc
;
1009 if (!EMPTYPOINT(Window
->InternalPos
.MaxPos
)) MinMax
.ptMaxPosition
= Window
->InternalPos
.MaxPos
;
1011 co_IntSendMessage(Window
->head
.h
, WM_GETMINMAXINFO
, 0, (LPARAM
)&MinMax
);
1013 /* if the app didn't change the values, adapt them for the current monitor */
1014 if ((monitor
= UserGetPrimaryMonitor()))
1018 rc_work
= monitor
->rcMonitor
;
1020 if (style
& WS_MAXIMIZEBOX
)
1022 if ((style
& WS_CAPTION
) == WS_CAPTION
|| !(style
& (WS_CHILD
| WS_POPUP
)))
1023 rc_work
= monitor
->rcWork
;
1026 if (MinMax
.ptMaxSize
.x
== UserGetSystemMetrics(SM_CXSCREEN
) + 2 * xinc
&&
1027 MinMax
.ptMaxSize
.y
== UserGetSystemMetrics(SM_CYSCREEN
) + 2 * yinc
)
1029 MinMax
.ptMaxSize
.x
= (rc_work
.right
- rc_work
.left
) + 2 * xinc
;
1030 MinMax
.ptMaxSize
.y
= (rc_work
.bottom
- rc_work
.top
) + 2 * yinc
;
1032 if (MinMax
.ptMaxPosition
.x
== -xinc
&& MinMax
.ptMaxPosition
.y
== -yinc
)
1034 MinMax
.ptMaxPosition
.x
= rc_work
.left
- xinc
;
1035 MinMax
.ptMaxPosition
.y
= rc_work
.top
- yinc
;
1037 if (MinMax
.ptMaxSize
.x
>= (monitor
->rcMonitor
.right
- monitor
->rcMonitor
.left
) &&
1038 MinMax
.ptMaxSize
.y
>= (monitor
->rcMonitor
.bottom
- monitor
->rcMonitor
.top
) )
1039 Window
->state
|= WNDS_MAXIMIZESTOMONITOR
;
1041 Window
->state
&= ~WNDS_MAXIMIZESTOMONITOR
;
1045 MinMax
.ptMaxTrackSize
.x
= max(MinMax
.ptMaxTrackSize
.x
,
1046 MinMax
.ptMinTrackSize
.x
);
1047 MinMax
.ptMaxTrackSize
.y
= max(MinMax
.ptMaxTrackSize
.y
,
1048 MinMax
.ptMinTrackSize
.y
);
1051 *MaxSize
= MinMax
.ptMaxSize
;
1053 *MaxPos
= MinMax
.ptMaxPosition
;
1055 *MinTrack
= MinMax
.ptMinTrackSize
;
1057 *MaxTrack
= MinMax
.ptMaxTrackSize
;
1059 return 0; // FIXME: What does it return?
1064 FixClientRect(PRECTL ClientRect
, PRECTL WindowRect
)
1066 if (ClientRect
->left
< WindowRect
->left
)
1068 ClientRect
->left
= WindowRect
->left
;
1070 else if (WindowRect
->right
< ClientRect
->left
)
1072 ClientRect
->left
= WindowRect
->right
;
1074 if (ClientRect
->right
< WindowRect
->left
)
1076 ClientRect
->right
= WindowRect
->left
;
1078 else if (WindowRect
->right
< ClientRect
->right
)
1080 ClientRect
->right
= WindowRect
->right
;
1082 if (ClientRect
->top
< WindowRect
->top
)
1084 ClientRect
->top
= WindowRect
->top
;
1086 else if (WindowRect
->bottom
< ClientRect
->top
)
1088 ClientRect
->top
= WindowRect
->bottom
;
1090 if (ClientRect
->bottom
< WindowRect
->top
)
1092 ClientRect
->bottom
= WindowRect
->top
;
1094 else if (WindowRect
->bottom
< ClientRect
->bottom
)
1096 ClientRect
->bottom
= WindowRect
->bottom
;
1099 /***********************************************************************
1102 * Compute the valid rects from the old and new client rect and WVR_* flags.
1103 * Helper for WM_NCCALCSIZE handling.
1107 get_valid_rects( RECTL
*old_client
, RECTL
*new_client
, UINT flags
, RECTL
*valid
)
1111 if (flags
& WVR_REDRAW
)
1113 RECTL_vSetEmptyRect( &valid
[0] );
1114 RECTL_vSetEmptyRect( &valid
[1] );
1118 if (flags
& WVR_VALIDRECTS
)
1120 if (!RECTL_bIntersectRect( &valid
[0], &valid
[0], new_client
) ||
1121 !RECTL_bIntersectRect( &valid
[1], &valid
[1], old_client
))
1123 RECTL_vSetEmptyRect( &valid
[0] );
1124 RECTL_vSetEmptyRect( &valid
[1] );
1127 flags
= WVR_ALIGNLEFT
| WVR_ALIGNTOP
;
1131 valid
[0] = *new_client
;
1132 valid
[1] = *old_client
;
1135 /* make sure the rectangles have the same size */
1136 cx
= min( valid
[0].right
- valid
[0].left
, valid
[1].right
- valid
[1].left
);
1137 cy
= min( valid
[0].bottom
- valid
[0].top
, valid
[1].bottom
- valid
[1].top
);
1139 if (flags
& WVR_ALIGNBOTTOM
)
1141 valid
[0].top
= valid
[0].bottom
- cy
;
1142 valid
[1].top
= valid
[1].bottom
- cy
;
1146 valid
[0].bottom
= valid
[0].top
+ cy
;
1147 valid
[1].bottom
= valid
[1].top
+ cy
;
1149 if (flags
& WVR_ALIGNRIGHT
)
1151 valid
[0].left
= valid
[0].right
- cx
;
1152 valid
[1].left
= valid
[1].right
- cx
;
1156 valid
[0].right
= valid
[0].left
+ cx
;
1157 valid
[1].right
= valid
[1].left
+ cx
;
1163 co_WinPosDoNCCALCSize(PWND Window
, PWINDOWPOS WinPos
, RECTL
* WindowRect
, RECTL
* ClientRect
, RECTL
* validRects
)
1168 ASSERT_REFS_CO(Window
);
1170 /* Send WM_NCCALCSIZE message to get new client area */
1171 if ((WinPos
->flags
& (SWP_FRAMECHANGED
| SWP_NOSIZE
)) != SWP_NOSIZE
)
1173 NCCALCSIZE_PARAMS params
;
1174 WINDOWPOS winposCopy
;
1176 params
.rgrc
[0] = *WindowRect
; // new coordinates of a window that has been moved or resized
1177 params
.rgrc
[1] = Window
->rcWindow
; // window before it was moved or resized
1178 params
.rgrc
[2] = Window
->rcClient
; // client area before the window was moved or resized
1180 Parent
= Window
->spwndParent
;
1181 if (0 != (Window
->style
& WS_CHILD
) && Parent
)
1183 RECTL_vOffsetRect(&(params
.rgrc
[0]), - Parent
->rcClient
.left
, - Parent
->rcClient
.top
);
1184 RECTL_vOffsetRect(&(params
.rgrc
[1]), - Parent
->rcClient
.left
, - Parent
->rcClient
.top
);
1185 RECTL_vOffsetRect(&(params
.rgrc
[2]), - Parent
->rcClient
.left
, - Parent
->rcClient
.top
);
1188 params
.lppos
= &winposCopy
;
1189 winposCopy
= *WinPos
;
1191 wvrFlags
= co_IntSendMessage(Window
->head
.h
, WM_NCCALCSIZE
, TRUE
, (LPARAM
) ¶ms
);
1193 /* If the application send back garbage, ignore it */
1194 if (params
.rgrc
[0].left
<= params
.rgrc
[0].right
&&
1195 params
.rgrc
[0].top
<= params
.rgrc
[0].bottom
)
1197 *ClientRect
= params
.rgrc
[0]; // First rectangle contains the coordinates of the new client rectangle resulting from the move or resize
1198 if ((Window
->style
& WS_CHILD
) && Parent
)
1200 RECTL_vOffsetRect(ClientRect
, Parent
->rcClient
.left
, Parent
->rcClient
.top
);
1202 FixClientRect(ClientRect
, WindowRect
);
1205 if (ClientRect
->left
!= Window
->rcClient
.left
||
1206 ClientRect
->top
!= Window
->rcClient
.top
)
1208 WinPos
->flags
&= ~SWP_NOCLIENTMOVE
;
1211 if (ClientRect
->right
- ClientRect
->left
!= Window
->rcClient
.right
- Window
->rcClient
.left
)
1213 WinPos
->flags
&= ~SWP_NOCLIENTSIZE
;
1216 wvrFlags
&= ~WVR_HREDRAW
;
1218 if (ClientRect
->bottom
- ClientRect
->top
!= Window
->rcClient
.bottom
- Window
->rcClient
.top
)
1220 WinPos
->flags
&= ~SWP_NOCLIENTSIZE
;
1223 wvrFlags
&= ~WVR_VREDRAW
;
1225 validRects
[0] = params
.rgrc
[1]; // second rectangle contains the valid destination rectangle
1226 validRects
[1] = params
.rgrc
[2]; // third rectangle contains the valid source rectangle
1230 if (!(WinPos
->flags
& SWP_NOMOVE
) &&
1231 (ClientRect
->left
!= Window
->rcClient
.left
||
1232 ClientRect
->top
!= Window
->rcClient
.top
))
1234 WinPos
->flags
&= ~SWP_NOCLIENTMOVE
;
1238 if (WinPos
->flags
& (SWP_NOCOPYBITS
| SWP_NOREDRAW
| SWP_SHOWWINDOW
| SWP_HIDEWINDOW
))
1240 RECTL_vSetEmptyRect( &validRects
[0] );
1241 RECTL_vSetEmptyRect( &validRects
[1] );
1243 else get_valid_rects( &Window
->rcClient
, ClientRect
, wvrFlags
, validRects
);
1250 co_WinPosDoWinPosChanging(PWND Window
,
1255 ASSERT_REFS_CO(Window
);
1257 /* Send WM_WINDOWPOSCHANGING message */
1259 if (!(WinPos
->flags
& SWP_NOSENDCHANGING
))
1261 co_IntSendMessageNoWait(Window
->head
.h
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
) WinPos
);
1264 /* Calculate new position and size */
1266 *WindowRect
= Window
->rcWindow
;
1267 *ClientRect
= (Window
->style
& WS_MINIMIZE
) ? Window
->rcWindow
: Window
->rcClient
;
1269 if (!(WinPos
->flags
& SWP_NOSIZE
))
1271 if (Window
->style
& WS_MINIMIZE
)
1273 WindowRect
->right
= WindowRect
->left
+ UserGetSystemMetrics(SM_CXMINIMIZED
);
1274 WindowRect
->bottom
= WindowRect
->top
+ UserGetSystemMetrics(SM_CYMINIMIZED
);
1278 WindowRect
->right
= WindowRect
->left
+ WinPos
->cx
;
1279 WindowRect
->bottom
= WindowRect
->top
+ WinPos
->cy
;
1283 if (!(WinPos
->flags
& SWP_NOMOVE
))
1290 Parent
= Window
->spwndParent
;
1292 if (((Window
->style
& WS_CHILD
) != 0) &&
1294 Parent
!= Window
->head
.rpdesk
->pDeskInfo
->spwnd
)
1296 TRACE("Not SWP_NOMOVE 1 Parent client offset X %d Y %d\n",X
,Y
);
1297 X
+= Parent
->rcClient
.left
;
1298 Y
+= Parent
->rcClient
.top
;
1299 TRACE("Not SWP_NOMOVE 2 Parent client offset X %d Y %d\n",X
,Y
);
1302 WindowRect
->left
= X
;
1303 WindowRect
->top
= Y
;
1304 WindowRect
->right
+= X
- Window
->rcWindow
.left
;
1305 WindowRect
->bottom
+= Y
- Window
->rcWindow
.top
;
1307 RECTL_vOffsetRect(ClientRect
, X
- Window
->rcWindow
.left
,
1308 Y
- Window
->rcWindow
.top
);
1310 WinPos
->flags
|= SWP_NOCLIENTMOVE
| SWP_NOCLIENTSIZE
;
1312 TRACE( "hwnd %p, after %p, swp %d,%d %dx%d flags %08x\n",
1313 WinPos
->hwnd
, WinPos
->hwndInsertAfter
, WinPos
->x
, WinPos
->y
,
1314 WinPos
->cx
, WinPos
->cy
, WinPos
->flags
);
1315 TRACE("WindowRect: %d %d %d %d\n", WindowRect
->left
,WindowRect
->top
,WindowRect
->right
,WindowRect
->bottom
);
1316 TRACE("ClientRect: %d %d %d %d\n", ClientRect
->left
,ClientRect
->top
,ClientRect
->right
,ClientRect
->bottom
);
1322 * Fix Z order taking into account owned popups -
1323 * basically we need to maintain them above the window that owns them
1325 * FIXME: hide/show owned popups when owner visibility changes.
1327 * ReactOS: See bug CORE-6129 and CORE-6554.
1331 // Pass all the win:test_children/popup_zorder tests except "move hwnd_F and its popups down" which is if'ed out.
1332 // Side effect, breaks more of the DeferWindowPos api tests, but wine breaks more!!!!
1335 WinPosDoOwnedPopups(PWND Window
, HWND hWndInsertAfter
)
1340 PWND DesktopWindow
, ChildObject
;
1343 TRACE("(%p) hInsertAfter = %p\n", Window
, hWndInsertAfter
);
1345 Owner
= Window
->spwndOwner
? Window
->spwndOwner
->head
.h
: NULL
;
1346 Style
= Window
->style
;
1348 if (Style
& WS_CHILD
)
1350 TRACE("Window is child\n");
1351 return hWndInsertAfter
;
1356 /* Make sure this popup stays above the owner */
1358 if (hWndInsertAfter
!= HWND_TOPMOST
)
1360 DesktopWindow
= UserGetDesktopWindow();
1361 List
= IntWinListChildren(DesktopWindow
);
1365 for (i
= 0; List
[i
]; i
++)
1367 BOOL topmost
= FALSE
;
1369 ChildObject
= ValidateHwndNoErr(List
[i
]);
1372 topmost
= (ChildObject
->ExStyle
& WS_EX_TOPMOST
) != 0;
1375 if (List
[i
] == Owner
)
1377 if (i
> 0) hWndInsertAfter
= List
[i
-1];
1378 else hWndInsertAfter
= topmost
? HWND_TOPMOST
: HWND_TOP
;
1382 if (hWndInsertAfter
== HWND_TOP
|| hWndInsertAfter
== HWND_NOTOPMOST
)
1384 if (!topmost
) break;
1386 else if (List
[i
] == hWndInsertAfter
) break;
1390 return hWndInsertAfter
;
1394 if (hWndInsertAfter
== HWND_BOTTOM
)
1396 ERR("Window is HWND_BOTTOM\n");
1397 if (List
) ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1403 DesktopWindow
= UserGetDesktopWindow();
1404 List
= IntWinListChildren(DesktopWindow
);
1411 if (hWndInsertAfter
== HWND_TOP
|| hWndInsertAfter
== HWND_NOTOPMOST
)
1413 if (hWndInsertAfter
== HWND_NOTOPMOST
|| !(Window
->ExStyle
& WS_EX_TOPMOST
))
1415 TRACE("skip all the topmost windows\n");
1416 /* skip all the topmost windows */
1418 (ChildObject
= ValidateHwndNoErr(List
[i
])) &&
1419 (ChildObject
->ExStyle
& WS_EX_TOPMOST
)) i
++;
1422 else if (hWndInsertAfter
!= HWND_TOPMOST
)
1424 /* skip windows that are already placed correctly */
1425 for (i
= 0; List
[i
]; i
++)
1427 if (List
[i
] == hWndInsertAfter
) break;
1428 if (List
[i
] == UserHMGetHandle(Window
))
1430 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1431 goto done
; /* nothing to do if window is moving backwards in z-order */
1436 for (; List
[i
]; i
++)
1439 USER_REFERENCE_ENTRY Ref
;
1441 if (List
[i
] == UserHMGetHandle(Window
))
1444 if (!(Wnd
= ValidateHwndNoErr(List
[i
])))
1447 Owner
= Wnd
->spwndOwner
? Wnd
->spwndOwner
->head
.h
: NULL
;
1449 if (Owner
!= UserHMGetHandle(Window
)) continue;
1451 UserRefObjectCo(Wnd
, &Ref
);
1452 TRACE( "moving %p owned by %p after %p\n", List
[i
], UserHMGetHandle(Window
), hWndInsertAfter
);
1453 co_WinPosSetWindowPos(Wnd
, hWndInsertAfter
, 0, 0, 0, 0,
1454 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOSENDCHANGING
| SWP_DEFERERASE
);
1456 UserDerefObjectCo(Wnd
);
1457 hWndInsertAfter
= List
[i
];
1459 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1462 return hWndInsertAfter
;
1466 /***********************************************************************
1467 * WinPosInternalMoveWindow
1469 * Update WindowRect and ClientRect of Window and all of its children
1470 * We keep both WindowRect and ClientRect in screen coordinates internally
1474 WinPosInternalMoveWindow(PWND Window
, INT MoveX
, INT MoveY
)
1478 ASSERT(Window
!= Window
->spwndChild
);
1479 TRACE("InternalMoveWin X %d Y %d\n", MoveX
, MoveY
);
1481 Window
->rcWindow
.left
+= MoveX
;
1482 Window
->rcWindow
.right
+= MoveX
;
1483 Window
->rcWindow
.top
+= MoveY
;
1484 Window
->rcWindow
.bottom
+= MoveY
;
1486 Window
->rcClient
.left
+= MoveX
;
1487 Window
->rcClient
.right
+= MoveX
;
1488 Window
->rcClient
.top
+= MoveY
;
1489 Window
->rcClient
.bottom
+= MoveY
;
1491 for(Child
= Window
->spwndChild
; Child
; Child
= Child
->spwndNext
)
1493 WinPosInternalMoveWindow(Child
, MoveX
, MoveY
);
1498 * WinPosFixupSWPFlags
1500 * Fix redundant flags and values in the WINDOWPOS structure.
1504 WinPosFixupFlags(WINDOWPOS
*WinPos
, PWND Wnd
)
1509 /* Finally make sure that all coordinates are valid */
1510 if (WinPos
->x
< -32768) WinPos
->x
= -32768;
1511 else if (WinPos
->x
> 32767) WinPos
->x
= 32767;
1512 if (WinPos
->y
< -32768) WinPos
->y
= -32768;
1513 else if (WinPos
->y
> 32767) WinPos
->y
= 32767;
1515 WinPos
->cx
= max(WinPos
->cx
, 0);
1516 WinPos
->cy
= max(WinPos
->cy
, 0);
1518 Parent
= UserGetAncestor( Wnd
, GA_PARENT
);
1519 if (!IntIsWindowVisible( Parent
)) WinPos
->flags
|= SWP_NOREDRAW
;
1521 if (Wnd
->style
& WS_VISIBLE
) WinPos
->flags
&= ~SWP_SHOWWINDOW
;
1524 WinPos
->flags
&= ~SWP_HIDEWINDOW
;
1525 if (!(WinPos
->flags
& SWP_SHOWWINDOW
)) WinPos
->flags
|= SWP_NOREDRAW
;
1528 /* Check for right size */
1529 if (Wnd
->rcWindow
.right
- Wnd
->rcWindow
.left
== WinPos
->cx
&&
1530 Wnd
->rcWindow
.bottom
- Wnd
->rcWindow
.top
== WinPos
->cy
)
1532 WinPos
->flags
|= SWP_NOSIZE
;
1537 IntClientToScreen( Parent
, &pt
);
1538 TRACE("WPFU C2S wpx %d wpy %d ptx %d pty %d\n",WinPos
->x
,WinPos
->y
,pt
.x
,pt
.y
);
1539 /* Check for right position */
1540 if (Wnd
->rcWindow
.left
== pt
.x
&& Wnd
->rcWindow
.top
== pt
.y
)
1542 //ERR("In right pos\n");
1543 WinPos
->flags
|= SWP_NOMOVE
;
1546 if (WinPos
->hwnd
== UserGetForegroundWindow())
1548 WinPos
->flags
|= SWP_NOACTIVATE
; /* Already active */
1551 if ((Wnd
->style
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)
1553 /* Bring to the top when activating */
1554 if (!(WinPos
->flags
& (SWP_NOACTIVATE
|SWP_HIDEWINDOW
)) &&
1555 (WinPos
->flags
& SWP_NOZORDER
||
1556 (WinPos
->hwndInsertAfter
!= HWND_TOPMOST
&& WinPos
->hwndInsertAfter
!= HWND_NOTOPMOST
)))
1558 WinPos
->flags
&= ~SWP_NOZORDER
;
1559 WinPos
->hwndInsertAfter
= (0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
) ? HWND_TOPMOST
: HWND_TOP
);
1563 /* Check hwndInsertAfter */
1564 if (!(WinPos
->flags
& SWP_NOZORDER
))
1566 /* Fix sign extension */
1567 if (WinPos
->hwndInsertAfter
== (HWND
)0xffff)
1569 WinPos
->hwndInsertAfter
= HWND_TOPMOST
;
1571 else if (WinPos
->hwndInsertAfter
== (HWND
)0xfffe)
1573 WinPos
->hwndInsertAfter
= HWND_NOTOPMOST
;
1576 if (WinPos
->hwndInsertAfter
== HWND_TOP
)
1578 /* Keep it topmost when it's already topmost */
1579 if ((Wnd
->ExStyle
& WS_EX_TOPMOST
) != 0)
1580 WinPos
->hwndInsertAfter
= HWND_TOPMOST
;
1582 if (IntGetWindow(WinPos
->hwnd
, GW_HWNDFIRST
) == WinPos
->hwnd
)
1583 WinPos
->flags
|= SWP_NOZORDER
;
1585 else if (WinPos
->hwndInsertAfter
== HWND_BOTTOM
)
1587 if (!(Wnd
->ExStyle
& WS_EX_TOPMOST
) && IntGetWindow(WinPos
->hwnd
, GW_HWNDLAST
) == WinPos
->hwnd
)
1588 WinPos
->flags
|= SWP_NOZORDER
;
1590 else if (WinPos
->hwndInsertAfter
== HWND_TOPMOST
)
1592 if ((Wnd
->ExStyle
& WS_EX_TOPMOST
) && IntGetWindow(WinPos
->hwnd
, GW_HWNDFIRST
) == WinPos
->hwnd
)
1593 WinPos
->flags
|= SWP_NOZORDER
;
1595 else if (WinPos
->hwndInsertAfter
== HWND_NOTOPMOST
)
1597 if (!(Wnd
->ExStyle
& WS_EX_TOPMOST
))
1598 WinPos
->flags
|= SWP_NOZORDER
;
1600 else /* hwndInsertAfter must be a sibling of the window */
1604 InsAfterWnd
= ValidateHwndNoErr(WinPos
->hwndInsertAfter
);
1610 if (InsAfterWnd
->spwndParent
!= Wnd
->spwndParent
)
1612 /* Note from wine User32 Win test_SetWindowPos:
1613 "Returns TRUE also for windows that are not siblings"
1614 "Does not seem to do anything even without passing flags, still returns TRUE"
1615 "Same thing the other way around."
1616 ".. and with these windows."
1623 * We don't need to change the Z order of hwnd if it's already
1624 * inserted after hwndInsertAfter or when inserting hwnd after
1627 if ((WinPos
->hwnd
== WinPos
->hwndInsertAfter
) ||
1628 ((InsAfterWnd
->spwndNext
) && (WinPos
->hwnd
== InsAfterWnd
->spwndNext
->head
.h
)))
1630 WinPos
->flags
|= SWP_NOZORDER
;
1639 /* x and y are always screen relative */
1641 co_WinPosSetWindowPos(
1643 HWND WndInsertAfter
,
1652 RECTL NewWindowRect
;
1653 RECTL NewClientRect
;
1654 RECTL valid_rects
[2];
1656 HRGN VisBefore
= NULL
;
1657 HRGN VisBeforeJustClient
= NULL
;
1658 HRGN VisAfter
= NULL
;
1659 HRGN DirtyRgn
= NULL
;
1660 HRGN ExposedRgn
= NULL
;
1661 HRGN CopyRgn
= NULL
;
1663 RECTL OldWindowRect
, OldClientRect
;
1668 BOOL bPointerInWindow
;
1670 ASSERT_REFS_CO(Window
);
1672 /* FIXME: Get current active window from active queue. Why? since r2915. */
1674 bPointerInWindow
= IntPtInWindow(Window
, gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
);
1676 WinPos
.hwnd
= Window
->head
.h
;
1677 WinPos
.hwndInsertAfter
= WndInsertAfter
;
1682 WinPos
.flags
= flags
;
1684 if ( flags
& SWP_ASYNCWINDOWPOS
)
1687 PWINDOWPOS ppos
= ExAllocatePoolWithTag(PagedPool
, sizeof(WINDOWPOS
), USERTAG_SWP
);
1690 WinPos
.flags
&= ~SWP_ASYNCWINDOWPOS
; // Clear flag.
1692 /* Yes it's a pointer inside Win32k! */
1693 lRes
= co_IntSendMessageNoWait( WinPos
.hwnd
, WM_ASYNC_SETWINDOWPOS
, 0, (LPARAM
)ppos
);
1694 /* We handle this the same way as Event Hooks and Hooks. */
1697 ExFreePoolWithTag(ppos
, USERTAG_SWP
);
1705 co_WinPosDoWinPosChanging(Window
, &WinPos
, &NewWindowRect
, &NewClientRect
);
1707 /* Does the window still exist? */
1708 if (!IntIsWindow(WinPos
.hwnd
))
1710 TRACE("WinPosSetWindowPos: Invalid handle 0x%p!\n",WinPos
.hwnd
);
1711 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE
);
1715 /* Fix up the flags. */
1716 if (!WinPosFixupFlags(&WinPos
, Window
))
1722 Ancestor
= UserGetAncestor(Window
, GA_PARENT
);
1723 if ( (WinPos
.flags
& (SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) != SWP_NOZORDER
&&
1724 Ancestor
&& Ancestor
->head
.h
== IntGetDesktopWindow() )
1726 WinPos
.hwndInsertAfter
= WinPosDoOwnedPopups(Window
, WinPos
.hwndInsertAfter
);
1729 if (!(WinPos
.flags
& SWP_NOREDRAW
))
1731 /* Compute the visible region before the window position is changed */
1732 if (!(WinPos
.flags
& SWP_SHOWWINDOW
) &&
1733 (WinPos
.flags
& (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
|
1734 SWP_HIDEWINDOW
| SWP_FRAMECHANGED
)) !=
1735 (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
))
1737 VisBefore
= VIS_ComputeVisibleRegion(Window
, FALSE
, FALSE
,
1738 (Window
->style
& WS_CLIPSIBLINGS
) ? TRUE
: FALSE
);
1741 if ( VisBefore
!= NULL
&&
1742 (VisRgn
= (PROSRGNDATA
)RGNOBJAPI_Lock(VisBefore
, NULL
)) &&
1743 REGION_Complexity(VisRgn
) == NULLREGION
)
1745 RGNOBJAPI_Unlock(VisRgn
);
1746 GreDeleteObject(VisBefore
);
1751 RGNOBJAPI_Unlock(VisRgn
);
1752 NtGdiOffsetRgn(VisBefore
, -Window
->rcWindow
.left
, -Window
->rcWindow
.top
);
1755 /* Calculate the non client area for resizes, as this is used in the copy region */
1756 if (!(WinPos
.flags
& SWP_NOSIZE
))
1758 VisBeforeJustClient
= VIS_ComputeVisibleRegion(Window
, TRUE
, FALSE
,
1759 (Window
->style
& WS_CLIPSIBLINGS
) ? TRUE
: FALSE
);
1762 if ( VisBeforeJustClient
!= NULL
&&
1763 (VisRgn
= (PROSRGNDATA
)RGNOBJAPI_Lock(VisBeforeJustClient
, NULL
)) &&
1764 REGION_Complexity(VisRgn
) == NULLREGION
)
1766 RGNOBJAPI_Unlock(VisRgn
);
1767 GreDeleteObject(VisBeforeJustClient
);
1768 VisBeforeJustClient
= NULL
;
1772 RGNOBJAPI_Unlock(VisRgn
);
1773 NtGdiOffsetRgn(VisBeforeJustClient
, -Window
->rcWindow
.left
, -Window
->rcWindow
.top
);
1779 WvrFlags
= co_WinPosDoNCCALCSize(Window
, &WinPos
, &NewWindowRect
, &NewClientRect
, valid_rects
);
1781 // ERR("co_WinPosDoNCCALCSize returned 0x%x\n valid dest: %d %d %d %d\n valid src : %d %d %d %d\n", WvrFlags,
1782 // valid_rects[0].left,valid_rects[0].top,valid_rects[0].right,valid_rects[0].bottom,
1783 // valid_rects[1].left,valid_rects[1].top,valid_rects[1].right,valid_rects[1].bottom);
1785 /* Validate link windows. (also take into account shell window in hwndShellWindow) */
1786 if (!(WinPos
.flags
& SWP_NOZORDER
) && WinPos
.hwnd
!= UserGetShellWindow())
1788 IntLinkHwnd(Window
, WinPos
.hwndInsertAfter
);
1791 OldWindowRect
= Window
->rcWindow
;
1792 OldClientRect
= Window
->rcClient
;
1794 if (NewClientRect
.left
!= OldClientRect
.left
||
1795 NewClientRect
.top
!= OldClientRect
.top
)
1797 // Move child window if their parent is moved. Keep Child window relative to Parent...
1798 WinPosInternalMoveWindow(Window
,
1799 NewClientRect
.left
- OldClientRect
.left
,
1800 NewClientRect
.top
- OldClientRect
.top
);
1803 Window
->rcWindow
= NewWindowRect
;
1804 Window
->rcClient
= NewClientRect
;
1806 /* erase parent when hiding or resizing child */
1807 if (WinPos
.flags
& SWP_HIDEWINDOW
)
1809 /* Clear the update region */
1810 co_UserRedrawWindow( Window
,
1813 RDW_VALIDATE
| RDW_NOFRAME
| RDW_NOERASE
| RDW_NOINTERNALPAINT
| RDW_ALLCHILDREN
);
1815 if (Window
->spwndParent
== UserGetDesktopWindow())
1816 co_IntShellHookNotify(HSHELL_WINDOWDESTROYED
, (WPARAM
)Window
->head
.h
, 0);
1818 Window
->style
&= ~WS_VISIBLE
; //IntSetStyle( Window, 0, WS_VISIBLE );
1819 Window
->head
.pti
->cVisWindows
--;
1820 IntNotifyWinEvent(EVENT_OBJECT_HIDE
, Window
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
1822 else if (WinPos
.flags
& SWP_SHOWWINDOW
)
1824 if (Window
->spwndParent
== UserGetDesktopWindow())
1825 co_IntShellHookNotify(HSHELL_WINDOWCREATED
, (WPARAM
)Window
->head
.h
, 0);
1827 Window
->style
|= WS_VISIBLE
; //IntSetStyle( Window, WS_VISIBLE, 0 );
1828 Window
->head
.pti
->cVisWindows
++;
1829 IntNotifyWinEvent(EVENT_OBJECT_SHOW
, Window
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
1832 if (Window
->hrgnUpdate
!= NULL
&& Window
->hrgnUpdate
!= HRGN_WINDOW
)
1834 NtGdiOffsetRgn(Window
->hrgnUpdate
,
1835 NewWindowRect
.left
- OldWindowRect
.left
,
1836 NewWindowRect
.top
- OldWindowRect
.top
);
1839 DceResetActiveDCEs(Window
); // For WS_VISIBLE changes.
1841 if (!(WinPos
.flags
& SWP_NOREDRAW
))
1843 /* Determine the new visible region */
1844 VisAfter
= VIS_ComputeVisibleRegion(Window
, FALSE
, FALSE
,
1845 (Window
->style
& WS_CLIPSIBLINGS
) ? TRUE
: FALSE
);
1848 if ( VisAfter
!= NULL
&&
1849 (VisRgn
= (PROSRGNDATA
)RGNOBJAPI_Lock(VisAfter
, NULL
)) &&
1850 REGION_Complexity(VisRgn
) == NULLREGION
)
1852 RGNOBJAPI_Unlock(VisRgn
);
1853 GreDeleteObject(VisAfter
);
1858 RGNOBJAPI_Unlock(VisRgn
);
1859 NtGdiOffsetRgn(VisAfter
, -Window
->rcWindow
.left
, -Window
->rcWindow
.top
);
1863 * Determine which pixels can be copied from the old window position
1864 * to the new. Those pixels must be visible in both the old and new
1865 * position. Also, check the class style to see if the windows of this
1866 * class need to be completely repainted on (horizontal/vertical) size
1869 if ( VisBefore
!= NULL
&&
1871 !(WinPos
.flags
& SWP_NOCOPYBITS
) &&
1872 ((WinPos
.flags
& SWP_NOSIZE
) || !(WvrFlags
& WVR_REDRAW
)) &&
1873 !(Window
->ExStyle
& WS_EX_TRANSPARENT
) )
1877 * If this is (also) a window resize, the whole nonclient area
1878 * needs to be repainted. So we limit the copy to the client area,
1879 * 'cause there is no use in copying it (would possibly cause
1880 * "flashing" too). However, if the copy region is already empty,
1881 * we don't have to crop (can't take anything away from an empty
1885 CopyRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
1886 if (WinPos
.flags
& SWP_NOSIZE
)
1887 RgnType
= NtGdiCombineRgn(CopyRgn
, VisAfter
, VisBefore
, RGN_AND
);
1888 else if (VisBeforeJustClient
!= NULL
)
1890 RgnType
= NtGdiCombineRgn(CopyRgn
, VisAfter
, VisBeforeJustClient
, RGN_AND
);
1891 GreDeleteObject(VisBeforeJustClient
);
1894 /* No use in copying bits which are in the update region. */
1895 if (Window
->hrgnUpdate
!= NULL
)
1897 NtGdiOffsetRgn(CopyRgn
, NewWindowRect
.left
, NewWindowRect
.top
);
1898 NtGdiCombineRgn(CopyRgn
, CopyRgn
, Window
->hrgnUpdate
, RGN_DIFF
);
1899 NtGdiOffsetRgn(CopyRgn
, -NewWindowRect
.left
, -NewWindowRect
.top
);
1903 * Now, get the bounding box of the copy region. If it's empty
1904 * there's nothing to copy. Also, it's no use copying bits onto
1907 if ( (VisRgn
= (PROSRGNDATA
)RGNOBJAPI_Lock(CopyRgn
, NULL
)) &&
1908 REGION_GetRgnBox(VisRgn
, &CopyRect
) == NULLREGION
)
1910 /* Nothing to copy, clean up */
1911 RGNOBJAPI_Unlock(VisRgn
);
1912 GreDeleteObject(CopyRgn
);
1915 else if (OldWindowRect
.left
!= NewWindowRect
.left
||
1916 OldWindowRect
.top
!= NewWindowRect
.top
)
1920 RGNOBJAPI_Unlock(VisRgn
);
1924 * Small trick here: there is no function to bitblt a region. So
1925 * we set the region as the clipping region, take the bounding box
1926 * of the region and bitblt that. Since nothing outside the clipping
1927 * region is copied, this has the effect of bitblt'ing the region.
1929 * Since NtUserGetDCEx takes ownership of the clip region, we need
1930 * to create a copy of CopyRgn and pass that. We need CopyRgn later
1932 NtGdiOffsetRgn(CopyRgn
, NewWindowRect
.left
, NewWindowRect
.top
);
1933 Dc
= UserGetDCEx( Window
,
1935 DCX_WINDOW
|DCX_CACHE
|DCX_INTERSECTRGN
|DCX_CLIPSIBLINGS
|DCX_KEEPCLIPRGN
);
1937 CopyRect
.left
, CopyRect
.top
,
1938 CopyRect
.right
- CopyRect
.left
,
1939 CopyRect
.bottom
- CopyRect
.top
,
1941 CopyRect
.left
+ (OldWindowRect
.left
- NewWindowRect
.left
),
1942 CopyRect
.top
+ (OldWindowRect
.top
- NewWindowRect
.top
),
1947 UserReleaseDC(Window
, Dc
, FALSE
);
1948 IntValidateParent(Window
, CopyRgn
, FALSE
);
1949 NtGdiOffsetRgn(CopyRgn
, -NewWindowRect
.left
, -NewWindowRect
.top
);
1953 RGNOBJAPI_Unlock(VisRgn
);
1961 /* We need to redraw what wasn't visible before */
1962 if (VisAfter
!= NULL
)
1964 DirtyRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
1965 if (CopyRgn
!= NULL
)
1967 RgnType
= NtGdiCombineRgn(DirtyRgn
, VisAfter
, CopyRgn
, RGN_DIFF
);
1971 RgnType
= NtGdiCombineRgn(DirtyRgn
, VisAfter
, 0, RGN_COPY
);
1973 if (RgnType
!= ERROR
&& RgnType
!= NULLREGION
)
1976 NtGdiOffsetRgn(DirtyRgn, Window->rcWindow.left, Window->rcWindow.top);
1977 IntInvalidateWindows( Window,
1979 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
1981 GreDeleteObject(DirtyRgn);
1984 PWND Parent
= Window
->spwndParent
;
1986 NtGdiOffsetRgn( DirtyRgn
,
1987 Window
->rcWindow
.left
,
1988 Window
->rcWindow
.top
);
1989 if ( (Window
->style
& WS_CHILD
) &&
1991 !(Parent
->style
& WS_CLIPCHILDREN
))
1993 IntInvalidateWindows( Parent
,
1995 RDW_ERASE
| RDW_INVALIDATE
);
1996 co_IntPaintWindows(Parent
, RDW_ERASENOW
, FALSE
);
2000 IntInvalidateWindows( Window
,
2002 RDW_ERASE
| RDW_FRAME
| RDW_INVALIDATE
| RDW_ALLCHILDREN
);
2005 GreDeleteObject(DirtyRgn
);
2008 if (CopyRgn
!= NULL
)
2010 GreDeleteObject(CopyRgn
);
2013 /* Expose what was covered before but not covered anymore */
2014 if (VisBefore
!= NULL
)
2016 ExposedRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
2017 RgnType
= NtGdiCombineRgn(ExposedRgn
, VisBefore
, NULL
, RGN_COPY
);
2018 NtGdiOffsetRgn( ExposedRgn
,
2019 OldWindowRect
.left
- NewWindowRect
.left
,
2020 OldWindowRect
.top
- NewWindowRect
.top
);
2022 if (VisAfter
!= NULL
)
2023 RgnType
= NtGdiCombineRgn(ExposedRgn
, ExposedRgn
, VisAfter
, RGN_DIFF
);
2025 if (RgnType
!= ERROR
&& RgnType
!= NULLREGION
)
2027 co_VIS_WindowLayoutChanged(Window
, ExposedRgn
);
2029 GreDeleteObject(ExposedRgn
);
2030 GreDeleteObject(VisBefore
);
2033 if (VisAfter
!= NULL
)
2035 GreDeleteObject(VisAfter
);
2039 if (!(WinPos
.flags
& (SWP_NOACTIVATE
|SWP_HIDEWINDOW
)))
2041 if ((Window
->style
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
2043 co_IntSendMessageNoWait(WinPos
.hwnd
, WM_CHILDACTIVATE
, 0, 0);
2047 //ERR("SetWindowPos Set FG Window!\n");
2048 if (Window
->state
& WNDS_BEINGACTIVATED
) // Inside SAW?
2049 co_IntSetActiveWindow(Window
, FALSE
, TRUE
, FALSE
); // Fixes Api AttachThreadInput tests.
2051 co_IntSetForegroundWindow(Window
); // Fixes SW_HIDE issues. Wine win test_SetActiveWindow & test_SetForegroundWindow.
2055 /* And last, send the WM_WINDOWPOSCHANGED message */
2057 TRACE("\tstatus flags = %04x\n", WinPos
.flags
& SWP_AGG_STATUSFLAGS
);
2059 if ((WinPos
.flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOPOSCHANGE
)
2061 /* WM_WINDOWPOSCHANGED is sent even if SWP_NOSENDCHANGING is set
2062 and always contains final window position.
2064 WinPos
.x
= NewWindowRect
.left
;
2065 WinPos
.y
= NewWindowRect
.top
;
2066 WinPos
.cx
= NewWindowRect
.right
- NewWindowRect
.left
;
2067 WinPos
.cy
= NewWindowRect
.bottom
- NewWindowRect
.top
;
2068 co_IntSendMessageNoWait(WinPos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
) &WinPos
);
2071 if ( WinPos
.flags
& SWP_FRAMECHANGED
|| WinPos
.flags
& SWP_STATECHANGED
||
2072 !(WinPos
.flags
& SWP_NOCLIENTSIZE
) || !(WinPos
.flags
& SWP_NOCLIENTMOVE
) )
2074 PWND pWnd
= ValidateHwndNoErr(WinPos
.hwnd
);
2076 IntNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE
, pWnd
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
2079 if(bPointerInWindow
!= IntPtInWindow(Window
, gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
))
2081 /* Generate mouse move message */
2083 msg
.message
= WM_MOUSEMOVE
;
2084 msg
.wParam
= UserGetMouseButtonsState();
2085 msg
.lParam
= MAKELPARAM(gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
);
2086 msg
.pt
= gpsi
->ptCursor
;
2087 co_MsqInsertMouseMessage(&msg
, 0, 0, TRUE
);
2094 co_WinPosGetNonClientSize(PWND Window
, RECT
* WindowRect
, RECT
* ClientRect
)
2098 ASSERT_REFS_CO(Window
);
2100 *ClientRect
= *WindowRect
;
2101 Result
= co_IntSendMessageNoWait(Window
->head
.h
, WM_NCCALCSIZE
, FALSE
, (LPARAM
) ClientRect
);
2103 FixClientRect(ClientRect
, WindowRect
);
2109 co_WinPosSendSizeMove(PWND Wnd
)
2113 WPARAM wParam
= SIZE_RESTORED
;
2115 IntGetClientRect(Wnd
, &Rect
);
2116 lParam
= MAKELONG(Rect
.right
-Rect
.left
, Rect
.bottom
-Rect
.top
);
2118 Wnd
->state
&= ~WNDS_SENDSIZEMOVEMSGS
;
2120 if (Wnd
->style
& WS_MAXIMIZE
)
2122 wParam
= SIZE_MAXIMIZED
;
2124 else if (Wnd
->style
& WS_MINIMIZE
)
2126 wParam
= SIZE_MINIMIZED
;
2130 co_IntSendMessageNoWait(UserHMGetHandle(Wnd
), WM_SIZE
, wParam
, lParam
);
2132 if (Wnd
->spwndParent
== UserGetDesktopWindow()) // Wnd->spwndParent->fnid == FNID_DESKTOP )
2133 lParam
= MAKELONG(Wnd
->rcClient
.left
, Wnd
->rcClient
.top
);
2135 lParam
= MAKELONG(Wnd
->rcClient
.left
-Wnd
->spwndParent
->rcClient
.left
, Wnd
->rcClient
.top
-Wnd
->spwndParent
->rcClient
.top
);
2137 co_IntSendMessageNoWait(UserHMGetHandle(Wnd
), WM_MOVE
, 0, lParam
);
2139 IntEngWindowChanged(Wnd
, WOC_RGN_CLIENT
);
2143 co_WinPosShowWindow(PWND Wnd
, INT Cmd
)
2146 UINT Swp
= 0, EventMsg
= 0;
2147 RECTL NewPos
= {0, 0, 0, 0};
2153 BOOL ShowOwned
= FALSE
;
2154 ASSERT_REFS_CO(Wnd
);
2155 //ERR("co_WinPosShowWindow START\n");
2157 pti
= PsGetCurrentThreadWin32Thread();
2158 WasVisible
= (Wnd
->style
& WS_VISIBLE
) != 0;
2167 //ERR("co_WinPosShowWindow Exit Bad\n");
2170 Swp
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
2171 if (Wnd
!= pti
->MessageQueue
->spwndActive
)
2172 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2176 case SW_FORCEMINIMIZE
: /* FIXME: Does not work if thread is hung. */
2177 case SW_SHOWMINNOACTIVE
:
2178 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2180 case SW_SHOWMINIMIZED
:
2181 Swp
|= SWP_SHOWWINDOW
;
2185 Swp
|= SWP_NOACTIVATE
;
2186 if (!(style
& WS_MINIMIZE
))
2188 IntShowOwnedPopups(Wnd
, FALSE
);
2190 // Fix wine Win test_SetFocus todo #1 & #2,
2191 if (Cmd
== SW_SHOWMINIMIZED
)
2193 //ERR("co_WinPosShowWindow Set focus 1\n");
2194 if ((style
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
2195 co_UserSetFocus(Wnd
->spwndParent
);
2200 Swp
|= co_WinPosMinMaximize(Wnd
, Cmd
, &NewPos
) |
2203 EventMsg
= EVENT_SYSTEM_MINIMIZESTART
;
2209 Swp
|= SWP_FRAMECHANGED
;
2213 //ERR("co_WinPosShowWindow Exit Good\n");
2216 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
2221 case SW_SHOWMAXIMIZED
:
2223 Swp
|= SWP_SHOWWINDOW
;
2224 if (!(style
& WS_MAXIMIZE
))
2228 Swp
|= co_WinPosMinMaximize(Wnd
, SW_MAXIMIZE
, &NewPos
) |
2231 EventMsg
= EVENT_SYSTEM_MINIMIZEEND
;
2237 Swp
|= SWP_FRAMECHANGED
;
2241 //ERR("co_WinPosShowWindow Exit Good 1\n");
2244 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
2250 Swp
|= SWP_NOACTIVATE
| SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
2251 if (style
& WS_CHILD
&& !(Wnd
->ExStyle
& WS_EX_MDICHILD
)) Swp
|= SWP_NOZORDER
;
2254 if (WasVisible
) return(TRUE
); // Nothing to do!
2255 Swp
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
2256 /* Don't activate the topmost window. */
2257 if (style
& WS_CHILD
&& !(Wnd
->ExStyle
& WS_EX_MDICHILD
)) Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2260 case SW_SHOWNOACTIVATE
:
2261 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2264 case SW_SHOWDEFAULT
:
2266 if (!WasVisible
) Swp
|= SWP_SHOWWINDOW
;
2267 if (style
& (WS_MINIMIZE
| WS_MAXIMIZE
))
2269 Swp
|= co_WinPosMinMaximize(Wnd
, Cmd
, &NewPos
) |
2272 if (style
& WS_MINIMIZE
) EventMsg
= EVENT_SYSTEM_MINIMIZEEND
;
2278 Swp
|= SWP_FRAMECHANGED
;
2282 //ERR("co_WinPosShowWindow Exit Good 3\n");
2285 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
2287 if ( style
& WS_CHILD
&&
2288 !(Wnd
->ExStyle
& WS_EX_MDICHILD
) &&
2289 !(Swp
& SWP_STATECHANGED
))
2290 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2294 //ERR("co_WinPosShowWindow Exit Good 4\n");
2298 ShowFlag
= (Cmd
!= SW_HIDE
);
2300 if ((ShowFlag
!= WasVisible
|| Cmd
== SW_SHOWNA
) && Cmd
!= SW_SHOWMAXIMIZED
&& !(Swp
& SWP_STATECHANGED
))
2302 co_IntSendMessageNoWait(Wnd
->head
.h
, WM_SHOWWINDOW
, ShowFlag
, 0);
2303 if (!(Wnd
->state2
& WNDS2_WIN31COMPAT
))
2304 co_IntSendMessageNoWait(Wnd
->head
.h
, WM_SETVISIBLE
, ShowFlag
, 0);
2305 if (!VerifyWnd(Wnd
)) return WasVisible
;
2308 /* We can't activate a child window */
2309 if ((Wnd
->style
& WS_CHILD
) &&
2310 !(Wnd
->ExStyle
& WS_EX_MDICHILD
) &&
2313 //ERR("SWP Child No active and ZOrder\n");
2314 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2317 #if 0 // Explorer issues with common controls? Someone does not know how CS_SAVEBITS works.
2318 // Breaks startup and shutdown active window...
2319 if ((Wnd
->style
& (WS_POPUP
|WS_CHILD
)) != WS_CHILD
&&
2320 Wnd
->pcls
->style
& CS_SAVEBITS
&&
2321 ((Cmd
== SW_SHOW
) || (Cmd
== SW_NORMAL
)))
2323 ERR("WinPosShowWindow Set active\n");
2324 UserSetActiveWindow(Wnd
);
2325 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2329 if (IsChildVisible(Wnd
) || Swp
& SWP_STATECHANGED
)
2331 TRACE("Child is Vis %s or State changed %s. ShowFlag %s\n",
2332 (IsChildVisible(Wnd
) ? "TRUE" : "FALSE"), (Swp
& SWP_STATECHANGED
? "TRUE" : "FALSE"),
2333 (ShowFlag
? "TRUE" : "FALSE"));
2334 co_WinPosSetWindowPos( Wnd
,
2335 0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
) ? HWND_TOPMOST
: HWND_TOP
,
2338 NewPos
.right
, //NewPos.right - NewPos.left,
2339 NewPos
.bottom
, //NewPos.bottom - NewPos.top,
2344 TRACE("Parent Vis?\n");
2345 /* if parent is not visible simply toggle WS_VISIBLE and return */
2346 if (ShowFlag
) IntSetStyle( Wnd
, WS_VISIBLE
, 0 );
2347 else IntSetStyle( Wnd
, 0, WS_VISIBLE
);
2350 if ( EventMsg
) IntNotifyWinEvent(EventMsg
, Wnd
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
2352 if ( ShowOwned
) IntShowOwnedPopups(Wnd
, TRUE
);
2354 if ((Cmd
== SW_HIDE
) || (Cmd
== SW_MINIMIZE
))
2356 if ( Wnd
== pti
->MessageQueue
->spwndActive
&& pti
->MessageQueue
== IntGetFocusMessageQueue() )
2358 if ( Wnd
->spwndParent
== UserGetDesktopWindow())
2360 if(!ActivateOtherWindowMin(Wnd
))
2361 co_WinPosActivateOtherWindow(Wnd
);
2364 co_WinPosActivateOtherWindow(Wnd
);
2367 /* Revert focus to parent */
2368 if (Wnd
== pti
->MessageQueue
->spwndFocus
)
2370 Parent
= Wnd
->spwndParent
;
2371 if (Wnd
->spwndParent
== UserGetDesktopWindow()) Parent
= 0;
2372 co_UserSetFocus(Parent
);
2376 /* FIXME: Check for window destruction. */
2378 if ((Wnd
->state
& WNDS_SENDSIZEMOVEMSGS
) &&
2379 !(Wnd
->state2
& WNDS2_INDESTROY
))
2381 co_WinPosSendSizeMove(Wnd
);
2384 /* if previous state was minimized Windows sets focus to the window */
2385 if (style
& WS_MINIMIZE
)
2387 co_UserSetFocus(Wnd
);
2388 // Fix wine Win test_SetFocus todo #3,
2389 if (!(style
& WS_CHILD
)) co_IntSendMessageNoWait(UserHMGetHandle(Wnd
), WM_ACTIVATE
, WA_ACTIVE
, 0);
2391 //ERR("co_WinPosShowWindow EXIT\n");
2397 co_WinPosSearchChildren(
2407 if (!(ScopeWin
->style
& WS_VISIBLE
))
2412 if (!Ignore
&& (ScopeWin
->style
& WS_DISABLED
))
2417 if (!IntPtInWindow(ScopeWin
, Point
->x
, Point
->y
))
2422 UserReferenceObject(ScopeWin
);
2424 if ( RECTL_bPointInRect(&ScopeWin
->rcClient
, Point
->x
, Point
->y
) )
2426 List
= IntWinListChildren(ScopeWin
);
2429 for (phWnd
= List
; *phWnd
; ++phWnd
)
2431 if (!(pwndChild
= ValidateHwndNoErr(*phWnd
)))
2436 pwndChild
= co_WinPosSearchChildren(pwndChild
, Point
, HitTest
, Ignore
);
2438 if(pwndChild
!= NULL
)
2440 /* We found a window. Don't send any more WM_NCHITTEST messages */
2441 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2442 UserDereferenceObject(ScopeWin
);
2446 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2450 if (ScopeWin
->head
.pti
== PsGetCurrentThreadWin32Thread())
2452 *HitTest
= (USHORT
)co_IntSendMessage(ScopeWin
->head
.h
, WM_NCHITTEST
, 0,
2453 MAKELONG(Point
->x
, Point
->y
));
2454 if ((*HitTest
) == (USHORT
)HTTRANSPARENT
)
2456 UserDereferenceObject(ScopeWin
);
2461 *HitTest
= HTCLIENT
;
2467 co_WinPosWindowFromPoint(PWND ScopeWin
, POINT
*WinPoint
, USHORT
* HitTest
, BOOL Ignore
)
2470 POINT Point
= *WinPoint
;
2471 USER_REFERENCE_ENTRY Ref
;
2473 if( ScopeWin
== NULL
)
2475 ScopeWin
= UserGetDesktopWindow();
2476 if(ScopeWin
== NULL
)
2480 *HitTest
= HTNOWHERE
;
2482 ASSERT_REFS_CO(ScopeWin
);
2483 UserRefObjectCo(ScopeWin
, &Ref
);
2485 Window
= co_WinPosSearchChildren(ScopeWin
, &Point
, HitTest
, Ignore
);
2487 UserDerefObjectCo(ScopeWin
);
2489 ASSERT_REFS_CO(Window
);
2490 ASSERT_REFS_CO(ScopeWin
);
2496 IntRealChildWindowFromPoint(PWND Parent
, LONG x
, LONG y
)
2500 PWND pwndHit
= NULL
;
2505 if (Parent
!= UserGetDesktopWindow())
2507 Pt
.x
+= Parent
->rcClient
.left
;
2508 Pt
.y
+= Parent
->rcClient
.top
;
2511 if (!IntPtInWindow(Parent
, Pt
.x
, Pt
.y
)) return NULL
;
2513 if ((List
= IntWinListChildren(Parent
)))
2515 for (phWnd
= List
; *phWnd
; phWnd
++)
2518 if ((Child
= ValidateHwndNoErr(*phWnd
)))
2520 if ( Child
->style
& WS_VISIBLE
&& IntPtInWindow(Child
, Pt
.x
, Pt
.y
) )
2522 if ( Child
->pcls
->atomClassName
!= gpsi
->atomSysClass
[ICLS_BUTTON
] ||
2523 (Child
->style
& BS_TYPEMASK
) != BS_GROUPBOX
)
2525 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2532 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2534 return pwndHit
? pwndHit
: Parent
;
2538 IntChildWindowFromPointEx(PWND Parent
, LONG x
, LONG y
, UINT uiFlags
)
2542 PWND pwndHit
= NULL
;
2547 if (Parent
!= UserGetDesktopWindow())
2549 if (Parent
->ExStyle
& WS_EX_LAYOUTRTL
)
2550 Pt
.x
= Parent
->rcClient
.right
- Pt
.x
;
2552 Pt
.x
+= Parent
->rcClient
.left
;
2553 Pt
.y
+= Parent
->rcClient
.top
;
2556 if (!IntPtInWindow(Parent
, Pt
.x
, Pt
.y
)) return NULL
;
2558 if ((List
= IntWinListChildren(Parent
)))
2560 for (phWnd
= List
; *phWnd
; phWnd
++)
2563 if ((Child
= ValidateHwndNoErr(*phWnd
)))
2565 if (uiFlags
& (CWP_SKIPINVISIBLE
|CWP_SKIPDISABLED
))
2567 if (!(Child
->style
& WS_VISIBLE
) && (uiFlags
& CWP_SKIPINVISIBLE
)) continue;
2568 if ((Child
->style
& WS_DISABLED
) && (uiFlags
& CWP_SKIPDISABLED
)) continue;
2571 if (uiFlags
& CWP_SKIPTRANSPARENT
)
2573 if (Child
->ExStyle
& WS_EX_TRANSPARENT
) continue;
2576 if (IntPtInWindow(Child
, Pt
.x
, Pt
.y
))
2583 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2585 return pwndHit
? pwndHit
: Parent
;
2590 IntDeferWindowPos( HDWP hdwp
,
2601 HDWP retvalue
= hdwp
;
2603 TRACE("hdwp %p, hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
2604 hdwp
, hwnd
, hwndAfter
, x
, y
, cx
, cy
, flags
);
2606 if (flags
& ~(SWP_NOSIZE
| SWP_NOMOVE
|
2607 SWP_NOZORDER
| SWP_NOREDRAW
|
2608 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
2609 SWP_NOOWNERZORDER
|SWP_SHOWWINDOW
|
2610 SWP_HIDEWINDOW
| SWP_FRAMECHANGED
))
2612 EngSetLastError(ERROR_INVALID_PARAMETER
);
2616 if (!(pDWP
= (PSMWP
)UserGetObject(gHandleTable
, hdwp
, TYPE_SETWINDOWPOS
)))
2618 EngSetLastError(ERROR_INVALID_DWP_HANDLE
);
2622 for (i
= 0; i
< pDWP
->ccvr
; i
++)
2624 if (pDWP
->acvr
[i
].pos
.hwnd
== hwnd
)
2626 /* Merge with the other changes */
2627 if (!(flags
& SWP_NOZORDER
))
2629 pDWP
->acvr
[i
].pos
.hwndInsertAfter
= hwndAfter
;
2631 if (!(flags
& SWP_NOMOVE
))
2633 pDWP
->acvr
[i
].pos
.x
= x
;
2634 pDWP
->acvr
[i
].pos
.y
= y
;
2636 if (!(flags
& SWP_NOSIZE
))
2638 pDWP
->acvr
[i
].pos
.cx
= cx
;
2639 pDWP
->acvr
[i
].pos
.cy
= cy
;
2641 pDWP
->acvr
[i
].pos
.flags
&= flags
| ~(SWP_NOSIZE
| SWP_NOMOVE
|
2642 SWP_NOZORDER
| SWP_NOREDRAW
|
2643 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
2645 pDWP
->acvr
[i
].pos
.flags
|= flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
|
2650 if (pDWP
->ccvr
>= pDWP
->ccvrAlloc
)
2652 PCVR newpos
= ExAllocatePoolWithTag(PagedPool
, pDWP
->ccvrAlloc
* 2 * sizeof(CVR
), USERTAG_SWP
);
2658 RtlZeroMemory(newpos
, pDWP
->ccvrAlloc
* 2 * sizeof(CVR
));
2659 RtlCopyMemory(newpos
, pDWP
->acvr
, pDWP
->ccvrAlloc
* sizeof(CVR
));
2660 ExFreePoolWithTag(pDWP
->acvr
, USERTAG_SWP
);
2661 pDWP
->ccvrAlloc
*= 2;
2662 pDWP
->acvr
= newpos
;
2664 pDWP
->acvr
[pDWP
->ccvr
].pos
.hwnd
= hwnd
;
2665 pDWP
->acvr
[pDWP
->ccvr
].pos
.hwndInsertAfter
= hwndAfter
;
2666 pDWP
->acvr
[pDWP
->ccvr
].pos
.x
= x
;
2667 pDWP
->acvr
[pDWP
->ccvr
].pos
.y
= y
;
2668 pDWP
->acvr
[pDWP
->ccvr
].pos
.cx
= cx
;
2669 pDWP
->acvr
[pDWP
->ccvr
].pos
.cy
= cy
;
2670 pDWP
->acvr
[pDWP
->ccvr
].pos
.flags
= flags
;
2671 pDWP
->acvr
[pDWP
->ccvr
].hrgnClip
= NULL
;
2672 pDWP
->acvr
[pDWP
->ccvr
].hrgnInterMonitor
= NULL
;
2678 BOOL FASTCALL
IntEndDeferWindowPosEx( HDWP hdwp
, BOOL sAsync
)
2685 TRACE("%p\n", hdwp
);
2687 if (!(pDWP
= (PSMWP
)UserGetObject(gHandleTable
, hdwp
, TYPE_SETWINDOWPOS
)))
2689 EngSetLastError(ERROR_INVALID_DWP_HANDLE
);
2693 for (i
= 0, winpos
= pDWP
->acvr
; res
&& i
< pDWP
->ccvr
; i
++, winpos
++)
2696 USER_REFERENCE_ENTRY Ref
;
2698 TRACE("hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
2699 winpos
->pos
.hwnd
, winpos
->pos
.hwndInsertAfter
, winpos
->pos
.x
, winpos
->pos
.y
,
2700 winpos
->pos
.cx
, winpos
->pos
.cy
, winpos
->pos
.flags
);
2702 pwnd
= ValidateHwndNoErr(winpos
->pos
.hwnd
);
2706 UserRefObjectCo(pwnd
, &Ref
);
2711 PWINDOWPOS ppos
= ExAllocatePoolWithTag(PagedPool
, sizeof(WINDOWPOS
), USERTAG_SWP
);
2714 *ppos
= winpos
->pos
;
2715 /* Yes it's a pointer inside Win32k! */
2716 lRes
= co_IntSendMessageNoWait( winpos
->pos
.hwnd
, WM_ASYNC_SETWINDOWPOS
, 0, (LPARAM
)ppos
);
2717 /* We handle this the same way as Event Hooks and Hooks. */
2720 ExFreePoolWithTag(ppos
, USERTAG_SWP
);
2725 res
= co_WinPosSetWindowPos( pwnd
,
2726 winpos
->pos
.hwndInsertAfter
,
2733 // Hack to pass tests.... Must have some work to do so clear the error.
2734 if (res
&& (winpos
->pos
.flags
& (SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOZORDER
)) == SWP_NOZORDER
)
2735 EngSetLastError(ERROR_SUCCESS
);
2737 UserDerefObjectCo(pwnd
);
2739 ExFreePoolWithTag(pDWP
->acvr
, USERTAG_SWP
);
2740 UserDereferenceObject(pDWP
);
2741 UserDeleteObject(hdwp
, TYPE_SETWINDOWPOS
);
2749 NtUserChildWindowFromPointEx(HWND hwndParent
,
2755 TRACE("Enter NtUserChildWindowFromPointEx\n");
2756 UserEnterExclusive();
2757 if ((pwndParent
= UserGetWindowObject(hwndParent
)))
2759 pwndParent
= IntChildWindowFromPointEx(pwndParent
, x
, y
, uiFlags
);
2762 TRACE("Leave NtUserChildWindowFromPointEx\n");
2763 return pwndParent
? UserHMGetHandle(pwndParent
) : NULL
;
2770 NtUserEndDeferWindowPosEx(HDWP WinPosInfo
,
2774 TRACE("Enter NtUserEndDeferWindowPosEx\n");
2775 UserEnterExclusive();
2776 Ret
= IntEndDeferWindowPosEx(WinPosInfo
, (BOOL
)Unknown1
);
2777 TRACE("Leave NtUserEndDeferWindowPosEx, ret=%i\n", Ret
);
2786 NtUserDeferWindowPos(HDWP WinPosInfo
,
2788 HWND WndInsertAfter
,
2797 UINT Tmp
= ~(SWP_ASYNCWINDOWPOS
|SWP_DEFERERASE
|SWP_NOSENDCHANGING
|SWP_NOREPOSITION
|
2798 SWP_NOCOPYBITS
|SWP_HIDEWINDOW
|SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|
2799 SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_NOZORDER
|SWP_NOMOVE
|SWP_NOSIZE
);
2801 TRACE("Enter NtUserDeferWindowPos\n");
2802 UserEnterExclusive();
2806 EngSetLastError(ERROR_INVALID_FLAGS
);
2810 pWnd
= UserGetWindowObject(Wnd
);
2811 if ( !pWnd
|| // FIXME:
2812 pWnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
2813 pWnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
2818 if ( WndInsertAfter
&&
2819 WndInsertAfter
!= HWND_BOTTOM
&&
2820 WndInsertAfter
!= HWND_TOPMOST
&&
2821 WndInsertAfter
!= HWND_NOTOPMOST
)
2823 pWndIA
= UserGetWindowObject(WndInsertAfter
);
2825 pWndIA
== UserGetDesktopWindow() ||
2826 pWndIA
== UserGetMessageWindow() )
2832 Ret
= IntDeferWindowPos(WinPosInfo
, Wnd
, WndInsertAfter
, x
, y
, cx
, cy
, Flags
);
2835 TRACE("Leave NtUserDeferWindowPos, ret=%p\n", Ret
);
2844 NtUserGetInternalWindowPos( HWND hWnd
,
2851 WINDOWPLACEMENT wndpl
;
2855 if (!(Window
= UserGetWindowObject(hWnd
)))
2865 ProbeForWrite(rectWnd
,
2871 ProbeForWrite(ptIcon
,
2877 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2879 SetLastNtError(_SEH2_GetExceptionCode());
2884 wndpl
.length
= sizeof(WINDOWPLACEMENT
);
2886 if (IntGetWindowPlacement(Window
, &wndpl
) && !Hit
)
2892 RtlCopyMemory(rectWnd
, &wndpl
.rcNormalPosition
, sizeof(RECT
));
2896 RtlCopyMemory(ptIcon
, &wndpl
.ptMinPosition
, sizeof(POINT
));
2900 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2902 SetLastNtError(_SEH2_GetExceptionCode());
2907 if (!Hit
) Ret
= wndpl
.showCmd
;
2918 NtUserGetWindowPlacement(HWND hWnd
,
2919 WINDOWPLACEMENT
*lpwndpl
)
2922 WINDOWPLACEMENT Safepl
;
2924 DECLARE_RETURN(BOOL
);
2926 TRACE("Enter NtUserGetWindowPlacement\n");
2929 if (!(Wnd
= UserGetWindowObject(hWnd
)))
2934 Status
= MmCopyFromCaller(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
2935 if(!NT_SUCCESS(Status
))
2937 SetLastNtError(Status
);
2940 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
2945 IntGetWindowPlacement(Wnd
, &Safepl
);
2947 Status
= MmCopyToCaller(lpwndpl
, &Safepl
, sizeof(WINDOWPLACEMENT
));
2948 if(!NT_SUCCESS(Status
))
2950 SetLastNtError(Status
);
2957 TRACE("Leave NtUserGetWindowPlacement, ret=%i\n",_ret_
);
2966 UINT cmd
, // Wine SW_ commands
2971 TRACE("Enter NtUserMinMaximize\n");
2972 UserEnterExclusive();
2974 pWnd
= UserGetWindowObject(hWnd
);
2975 if ( !pWnd
|| // FIXME:
2976 pWnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
2977 pWnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
2982 if ( cmd
> SW_MAX
|| pWnd
->state2
& WNDS2_INDESTROY
)
2984 EngSetLastError(ERROR_INVALID_PARAMETER
);
2988 cmd
|= Hide
? SW_HIDE
: 0;
2990 co_WinPosShowWindow(pWnd
, cmd
);
2993 TRACE("Leave NtUserMinMaximize\n");
2995 return 0; // Always NULL?
3010 return NtUserSetWindowPos(hWnd
, 0, X
, Y
, nWidth
, nHeight
,
3011 (bRepaint
? SWP_NOZORDER
| SWP_NOACTIVATE
:
3012 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
));
3019 NtUserRealChildWindowFromPoint(HWND Parent
,
3024 TRACE("Enter NtUserRealChildWindowFromPoint\n");
3026 if ((pwndParent
= UserGetWindowObject(Parent
)))
3028 pwndParent
= IntRealChildWindowFromPoint(pwndParent
, x
, y
);
3031 TRACE("Leave NtUserRealChildWindowFromPoint\n");
3032 return pwndParent
? UserHMGetHandle(pwndParent
) : NULL
;
3041 HWND hWndInsertAfter
,
3048 DECLARE_RETURN(BOOL
);
3049 PWND Window
, pWndIA
;
3051 USER_REFERENCE_ENTRY Ref
;
3053 TRACE("Enter NtUserSetWindowPos\n");
3054 UserEnterExclusive();
3056 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
3057 Window
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3058 Window
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3060 ERR("NtUserSetWindowPos bad window handle!\n");
3064 if ( hWndInsertAfter
&&
3065 hWndInsertAfter
!= HWND_BOTTOM
&&
3066 hWndInsertAfter
!= HWND_TOPMOST
&&
3067 hWndInsertAfter
!= HWND_NOTOPMOST
)
3069 if (!(pWndIA
= UserGetWindowObject(hWndInsertAfter
)) ||
3070 pWndIA
== UserGetDesktopWindow() ||
3071 pWndIA
== UserGetMessageWindow() )
3073 ERR("NtUserSetWindowPos bad insert window handle!\n");
3078 /* First make sure that coordinates are valid for WM_WINDOWPOSCHANGING */
3079 if (!(uFlags
& SWP_NOMOVE
))
3081 if (X
< -32768) X
= -32768;
3082 else if (X
> 32767) X
= 32767;
3083 if (Y
< -32768) Y
= -32768;
3084 else if (Y
> 32767) Y
= 32767;
3086 if (!(uFlags
& SWP_NOSIZE
))
3089 else if (cx
> 32767) cx
= 32767;
3091 else if (cy
> 32767) cy
= 32767;
3094 UserRefObjectCo(Window
, &Ref
);
3095 ret
= co_WinPosSetWindowPos(Window
, hWndInsertAfter
, X
, Y
, cx
, cy
, uFlags
);
3096 UserDerefObjectCo(Window
);
3101 TRACE("Leave NtUserSetWindowPos, ret=%i\n",_ret_
);
3117 INT flags
= (SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
);
3118 BOOLEAN Ret
= FALSE
;
3119 DECLARE_RETURN(INT
);
3121 TRACE("Enter NtUserSetWindowRgn\n");
3122 UserEnterExclusive();
3124 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
3125 Window
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3126 Window
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3131 if (hRgn
) // The region will be deleted in user32.
3133 if (GreIsHandleValid(hRgn
))
3135 hrgnCopy
= IntSysCreateRectRgn(0, 0, 0, 0);
3136 /* The coordinates of a window's window region are relative to the
3137 upper-left corner of the window, not the client area of the window. */
3138 NtGdiCombineRgn( hrgnCopy
, hRgn
, 0, RGN_COPY
);
3148 if (Window
->hrgnClip
)
3150 /* Delete no longer needed region handle */
3151 IntGdiSetRegionOwner(Window
->hrgnClip
, GDI_OBJ_HMGR_POWNED
);
3152 GreDeleteObject(Window
->hrgnClip
);
3157 /* Set public ownership */
3158 IntGdiSetRegionOwner(hrgnCopy
, GDI_OBJ_HMGR_PUBLIC
);
3160 Window
->hrgnClip
= hrgnCopy
;
3162 Ret
= co_WinPosSetWindowPos(Window
, HWND_TOP
, 0, 0, 0, 0, bRedraw
? flags
: (flags
|SWP_NOREDRAW
) );
3167 TRACE("Leave NtUserSetWindowRgn, ret=%i\n",_ret_
);
3176 NtUserSetInternalWindowPos(
3182 WINDOWPLACEMENT wndpl
;
3187 DECLARE_RETURN(BOOL
);
3188 USER_REFERENCE_ENTRY Ref
;
3190 TRACE("Enter NtUserSetWindowPlacement\n");
3191 UserEnterExclusive();
3193 if (!(Wnd
= UserGetWindowObject(hwnd
)) || // FIXME:
3194 Wnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3195 Wnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3204 ProbeForRead(lppt
, sizeof(POINT
), 1);
3205 RtlCopyMemory(&pt
, lppt
, sizeof(POINT
));
3209 ProbeForRead(lprect
, sizeof(RECT
), 1);
3210 RtlCopyMemory(&rect
, lprect
, sizeof(RECT
));
3213 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3215 SetLastNtError(_SEH2_GetExceptionCode());
3216 _SEH2_YIELD(RETURN( FALSE
));
3220 wndpl
.length
= sizeof(wndpl
);
3221 wndpl
.showCmd
= showCmd
;
3222 wndpl
.flags
= flags
= 0;
3227 wndpl
.flags
|= WPF_SETMINPOSITION
;
3228 wndpl
.ptMinPosition
= pt
;
3232 flags
|= PLACE_RECT
;
3233 wndpl
.rcNormalPosition
= rect
;
3236 UserRefObjectCo(Wnd
, &Ref
);
3237 IntSetWindowPlacement(Wnd
, &wndpl
, flags
);
3238 UserDerefObjectCo(Wnd
);
3242 TRACE("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_
);
3251 NtUserSetWindowPlacement(HWND hWnd
,
3252 WINDOWPLACEMENT
*lpwndpl
)
3255 WINDOWPLACEMENT Safepl
;
3257 DECLARE_RETURN(BOOL
);
3258 USER_REFERENCE_ENTRY Ref
;
3260 TRACE("Enter NtUserSetWindowPlacement\n");
3261 UserEnterExclusive();
3263 if (!(Wnd
= UserGetWindowObject(hWnd
)) || // FIXME:
3264 Wnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3265 Wnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3272 ProbeForRead(lpwndpl
, sizeof(WINDOWPLACEMENT
), 1);
3273 RtlCopyMemory(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
3275 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3277 SetLastNtError(_SEH2_GetExceptionCode());
3278 _SEH2_YIELD(RETURN( FALSE
));
3282 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
3287 Flags
= PLACE_MAX
| PLACE_RECT
;
3288 if (Safepl
.flags
& WPF_SETMINPOSITION
) Flags
|= PLACE_MIN
;
3289 UserRefObjectCo(Wnd
, &Ref
);
3290 IntSetWindowPlacement(Wnd
, &Safepl
, Flags
);
3291 UserDerefObjectCo(Wnd
);
3295 TRACE("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_
);
3304 NtUserShowWindowAsync(HWND hWnd
, LONG nCmdShow
)
3308 DECLARE_RETURN(BOOL
);
3309 USER_REFERENCE_ENTRY Ref
;
3311 TRACE("Enter NtUserShowWindowAsync\n");
3312 UserEnterExclusive();
3314 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
3315 Window
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3316 Window
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3321 if ( nCmdShow
> SW_MAX
)
3323 EngSetLastError(ERROR_INVALID_PARAMETER
);
3327 UserRefObjectCo(Window
, &Ref
);
3328 ret
= co_IntSendMessageNoWait( hWnd
, WM_ASYNC_SHOWWINDOW
, nCmdShow
, 0 );
3329 UserDerefObjectCo(Window
);
3330 if (-1 == (int) ret
|| !ret
) ret
= FALSE
;
3335 TRACE("Leave NtUserShowWindowAsync, ret=%i\n",_ret_
);
3344 NtUserShowWindow(HWND hWnd
, LONG nCmdShow
)
3348 DECLARE_RETURN(BOOL
);
3349 USER_REFERENCE_ENTRY Ref
;
3351 TRACE("Enter NtUserShowWindow\n");
3352 UserEnterExclusive();
3354 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
3355 Window
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3356 Window
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3361 if ( nCmdShow
> SW_MAX
|| Window
->state2
& WNDS2_INDESTROY
)
3363 EngSetLastError(ERROR_INVALID_PARAMETER
);
3367 UserRefObjectCo(Window
, &Ref
);
3368 ret
= co_WinPosShowWindow(Window
, nCmdShow
);
3369 UserDerefObjectCo(Window
);
3374 TRACE("Leave NtUserShowWindow, ret=%i\n",_ret_
);
3384 NtUserWindowFromPoint(LONG X
, LONG Y
)
3388 PWND DesktopWindow
= NULL
, Window
= NULL
;
3390 DECLARE_RETURN(HWND
);
3391 USER_REFERENCE_ENTRY Ref
;
3393 TRACE("Enter NtUserWindowFromPoint\n");
3394 UserEnterExclusive();
3396 if ((DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow())))
3403 // Hmm... Threads live on desktops thus we have a reference on the desktop and indirectly the desktop window.
3404 // It is possible this referencing is useless, though it should not hurt...
3405 UserRefObjectCo(DesktopWindow
, &Ref
);
3407 //pti = PsGetCurrentThreadWin32Thread();
3408 Window
= co_WinPosWindowFromPoint(DesktopWindow
, &pt
, &hittest
, FALSE
);
3412 Ret
= UserHMGetHandle(Window
);
3421 if (Window
) UserDereferenceObject(Window
);
3422 if (DesktopWindow
) UserDerefObjectCo(DesktopWindow
);
3424 TRACE("Leave NtUserWindowFromPoint, ret=%p\n", _ret_
);