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 ERR("WPAOW Popup with Owner\n");
331 WndTo
= UserGetAncestor( WndTo
, GA_ROOT
);
332 if (can_activate_window(WndTo
)) goto done
;
335 /* Pick a next top-level window. */
336 /* FIXME: Search for non-tooltip windows first. */
340 if (!(WndTo
= WndTo
->spwndNext
)) break;
341 if (can_activate_window( WndTo
)) goto done
;
345 Fixes wine win.c:test_SetParent last ShowWindow test after popup dies.
346 Check for previous active window to bring to top.
350 WndTo
= Wnd
->head
.pti
->MessageQueue
->spwndActivePrev
;
351 if (can_activate_window( WndTo
)) goto done
;
354 // Find any window to bring to top. Works Okay for wine.
355 WndTo
= UserGetDesktopWindow();
356 WndTo
= WndTo
->spwndChild
;
364 if (can_activate_window( WndTo
)) goto done
;
365 if (!(WndTo
= WndTo
->spwndNext
)) break;
369 if (WndTo
) UserRefObjectCo(WndTo
, &Ref
);
371 if ((gpqForeground
&& !gpqForeground
->spwndActive
) || Wnd
== gpqForeground
->spwndActive
)
373 /* ReactOS can pass WndTo = NULL to co_IntSetForegroundWindow and returns FALSE. */
374 //ERR("WinPosActivateOtherWindow Set FG 0x%p hWnd %p\n",WndTo, WndTo ? WndTo->head.h : 0);
375 if (co_IntSetForegroundWindow(WndTo
))
377 if (WndTo
) UserDerefObjectCo(WndTo
);
381 //ERR("WinPosActivateOtherWindow Set Active 0x%p\n",WndTo);
382 if (!co_IntSetActiveWindow(WndTo
,FALSE
,TRUE
,FALSE
)) /* Ok for WndTo to be NULL here */
384 co_IntSetActiveWindow(NULL
,FALSE
,TRUE
,FALSE
);
386 if (WndTo
) UserDerefObjectCo(WndTo
);
390 WinPosInitInternalPos(PWND Wnd
, RECTL
*RestoreRect
)
393 RECTL Rect
= *RestoreRect
;
395 if (Wnd
->spwndParent
!= UserGetDesktopWindow())
397 RECTL_vOffsetRect(&Rect
,
398 -Wnd
->spwndParent
->rcClient
.left
,
399 -Wnd
->spwndParent
->rcClient
.top
);
405 if (!Wnd
->InternalPosInitialized
)
407 // FIXME: Use check point Atom..
408 Wnd
->InternalPos
.flags
= 0;
409 Wnd
->InternalPos
.MaxPos
.x
= Wnd
->InternalPos
.MaxPos
.y
= -1;
410 Wnd
->InternalPos
.IconPos
.x
= Wnd
->InternalPos
.IconPos
.y
= -1;
411 Wnd
->InternalPos
.NormalRect
= Rect
;
412 Wnd
->InternalPosInitialized
= TRUE
;
415 if (Wnd
->style
& WS_MINIMIZE
)
417 Wnd
->InternalPos
.IconPos
= Size
;
418 Wnd
->InternalPos
.flags
|= WPF_MININIT
;
420 else if (Wnd
->style
& WS_MAXIMIZE
)
422 Wnd
->InternalPos
.flags
|= WPF_MAXINIT
;
424 if ( Wnd
->spwndParent
== Wnd
->head
.rpdesk
->pDeskInfo
->spwnd
)
426 if (Wnd
->state
& WNDS_MAXIMIZESTOMONITOR
)
428 Wnd
->InternalPos
.flags
&= ~WPF_MAXINIT
;
429 Wnd
->InternalPos
.MaxPos
.x
= Wnd
->InternalPos
.MaxPos
.y
= -1;
434 PMONITOR pmonitor
= UserMonitorFromRect(&Rect
, MONITOR_DEFAULTTOPRIMARY
);
435 // FIXME: support DPI aware, rcWorkDPI/Real etc..
436 WorkArea
= pmonitor
->rcMonitor
;
438 if (Wnd
->style
& WS_MAXIMIZEBOX
)
439 { // Support (Wnd->state & WNDS_HASCAPTION) || pmonitor->cFullScreen too.
440 if ((Wnd
->style
& WS_CAPTION
) == WS_CAPTION
|| !(Wnd
->style
& (WS_CHILD
| WS_POPUP
)))
442 WorkArea
= pmonitor
->rcWork
;
447 Wnd
->InternalPos
.MaxPos
.x
= Rect
.left
- WorkArea
.left
;
448 Wnd
->InternalPos
.MaxPos
.y
= Rect
.top
- WorkArea
.top
;
450 /*ERR("WinPosIP 2 X %d = R.l %d - W.l %d | Y %d = R.t %d - W.t %d\n",
451 Wnd->InternalPos.MaxPos.x,
452 Rect.left, WorkArea.left,
453 Wnd->InternalPos.MaxPos.y,
454 Rect.top, WorkArea.top);*/
458 Wnd
->InternalPos
.MaxPos
= Size
;
462 Wnd
->InternalPos
.NormalRect
= Rect
;
468 IntGetWindowPlacement(PWND Wnd
, WINDOWPLACEMENT
*lpwndpl
)
470 if (!Wnd
) return FALSE
;
472 if(lpwndpl
->length
!= sizeof(WINDOWPLACEMENT
))
479 WinPosInitInternalPos(Wnd
, &Wnd
->rcWindow
);
481 lpwndpl
->showCmd
= SW_HIDE
;
483 if ( Wnd
->style
& WS_MINIMIZE
)
484 lpwndpl
->showCmd
= SW_SHOWMINIMIZED
;
486 lpwndpl
->showCmd
= ( Wnd
->style
& WS_MAXIMIZE
) ? SW_SHOWMAXIMIZED
: SW_SHOWNORMAL
;
488 lpwndpl
->rcNormalPosition
= Wnd
->InternalPos
.NormalRect
;
490 if (Wnd
->InternalPos
.flags
& WPF_MININIT
) // Return if it was set!
492 lpwndpl
->ptMinPosition
.x
= Wnd
->InternalPos
.IconPos
.x
;
493 lpwndpl
->ptMinPosition
.y
= Wnd
->InternalPos
.IconPos
.y
;
496 lpwndpl
->ptMinPosition
.x
= lpwndpl
->ptMinPosition
.y
= -1;
498 if ( Wnd
->InternalPos
.flags
& WPF_MAXINIT
&& // Return if set and not maximized to monitor!
499 !(Wnd
->state
& WNDS_MAXIMIZESTOMONITOR
))
501 lpwndpl
->ptMaxPosition
.x
= Wnd
->InternalPos
.MaxPos
.x
;
502 lpwndpl
->ptMaxPosition
.y
= Wnd
->InternalPos
.MaxPos
.y
;
505 lpwndpl
->ptMaxPosition
.x
= lpwndpl
->ptMaxPosition
.y
= -1;
507 if ( Wnd
->spwndParent
== Wnd
->head
.rpdesk
->pDeskInfo
->spwnd
&&
508 !(Wnd
->ExStyle
& WS_EX_TOOLWINDOW
))
510 PMONITOR pmonitor
= UserMonitorFromRect(&lpwndpl
->rcNormalPosition
, MONITOR_DEFAULTTOPRIMARY
);
512 // FIXME: support DPI aware, rcWorkDPI/Real etc..
513 if (Wnd
->InternalPos
.flags
& WPF_MININIT
)
515 lpwndpl
->ptMinPosition
.x
-= (pmonitor
->rcWork
.left
- pmonitor
->rcMonitor
.left
);
516 lpwndpl
->ptMinPosition
.y
-= (pmonitor
->rcWork
.top
- pmonitor
->rcMonitor
.top
);
518 RECTL_vOffsetRect(&lpwndpl
->rcNormalPosition
,
519 pmonitor
->rcMonitor
.left
- pmonitor
->rcWork
.left
,
520 pmonitor
->rcMonitor
.top
- pmonitor
->rcWork
.top
);
523 if ( Wnd
->InternalPos
.flags
& WPF_RESTORETOMAXIMIZED
|| Wnd
->style
& WS_MAXIMIZE
)
524 lpwndpl
->flags
|= WPF_RESTORETOMAXIMIZED
;
526 if ( ((Wnd
->style
& (WS_CHILD
|WS_POPUP
)) == WS_CHILD
) && Wnd
->InternalPos
.flags
& WPF_SETMINPOSITION
)
527 lpwndpl
->flags
|= WPF_SETMINPOSITION
;
532 /* make sure the specified rect is visible on screen */
533 static void make_rect_onscreen( RECT
*rect
)
535 PMONITOR pmonitor
= UserMonitorFromRect( rect
, MONITOR_DEFAULTTONEAREST
); // Wine uses this.
537 // FIXME: support DPI aware, rcWorkDPI/Real etc..
538 if (!pmonitor
) return;
539 /* FIXME: map coordinates from rcWork to rcMonitor */
540 if (rect
->right
<= pmonitor
->rcWork
.left
)
542 rect
->right
+= pmonitor
->rcWork
.left
- rect
->left
;
543 rect
->left
= pmonitor
->rcWork
.left
;
545 else if (rect
->left
>= pmonitor
->rcWork
.right
)
547 rect
->left
+= pmonitor
->rcWork
.right
- rect
->right
;
548 rect
->right
= pmonitor
->rcWork
.right
;
550 if (rect
->bottom
<= pmonitor
->rcWork
.top
)
552 rect
->bottom
+= pmonitor
->rcWork
.top
- rect
->top
;
553 rect
->top
= pmonitor
->rcWork
.top
;
555 else if (rect
->top
>= pmonitor
->rcWork
.bottom
)
557 rect
->top
+= pmonitor
->rcWork
.bottom
- rect
->bottom
;
558 rect
->bottom
= pmonitor
->rcWork
.bottom
;
562 /* make sure the specified point is visible on screen */
563 static void make_point_onscreen( POINT
*pt
)
567 RECTL_vSetRect( &rect
, pt
->x
, pt
->y
, pt
->x
+ 1, pt
->y
+ 1 );
568 make_rect_onscreen( &rect
);
574 IntSetWindowPlacement(PWND Wnd
, WINDOWPLACEMENT
*wpl
, UINT Flags
)
579 if ( Flags
& PLACE_MIN
) make_point_onscreen( &wpl
->ptMinPosition
);
580 if ( Flags
& PLACE_MAX
) make_point_onscreen( &wpl
->ptMaxPosition
);
581 if ( Flags
& PLACE_RECT
) make_rect_onscreen( &wpl
->rcNormalPosition
);
583 if (!Wnd
|| Wnd
== Wnd
->head
.rpdesk
->pDeskInfo
->spwnd
) return FALSE
;
585 if ( Flags
& PLACE_MIN
) Wnd
->InternalPos
.IconPos
= wpl
->ptMinPosition
;
586 if ( Flags
& PLACE_MAX
) Wnd
->InternalPos
.MaxPos
= wpl
->ptMaxPosition
;
587 if ( Flags
& PLACE_RECT
) Wnd
->InternalPos
.NormalRect
= wpl
->rcNormalPosition
;
589 SWP_Flags
= SWP_NOZORDER
| SWP_NOACTIVATE
| ((wpl
->flags
& WPF_ASYNCWINDOWPLACEMENT
) ? SWP_ASYNCWINDOWPOS
: 0);
591 if (Wnd
->style
& WS_MINIMIZE
)
593 if (Flags
& PLACE_MIN
|| Wnd
->InternalPos
.flags
& WPF_SETMINPOSITION
)
595 co_WinPosSetWindowPos(Wnd
, HWND_TOP
,
596 wpl
->ptMinPosition
.x
, wpl
->ptMinPosition
.y
, 0, 0,
597 SWP_NOSIZE
| SWP_Flags
);
598 Wnd
->InternalPos
.flags
|= WPF_MININIT
;
601 else if (Wnd
->style
& WS_MAXIMIZE
)
603 if (Flags
& PLACE_MAX
)
605 co_WinPosSetWindowPos(Wnd
, HWND_TOP
,
606 wpl
->ptMaxPosition
.x
, wpl
->ptMaxPosition
.y
, 0, 0,
607 SWP_NOSIZE
| SWP_Flags
);
608 Wnd
->InternalPos
.flags
|= WPF_MAXINIT
;
611 else if (Flags
& PLACE_RECT
)
613 co_WinPosSetWindowPos(Wnd
, HWND_TOP
,
614 wpl
->rcNormalPosition
.left
, wpl
->rcNormalPosition
.top
,
615 wpl
->rcNormalPosition
.right
- wpl
->rcNormalPosition
.left
,
616 wpl
->rcNormalPosition
.bottom
- wpl
->rcNormalPosition
.top
,
620 sAsync
= (Wnd
->head
.pti
->MessageQueue
!= gptiCurrent
->MessageQueue
&& wpl
->flags
& WPF_ASYNCWINDOWPLACEMENT
);
623 co_IntSendMessageNoWait( UserHMGetHandle(Wnd
), WM_ASYNC_SHOWWINDOW
, wpl
->showCmd
, 0 );
625 co_WinPosShowWindow(Wnd
, wpl
->showCmd
);
627 if ( Wnd
->style
& WS_MINIMIZE
&& !sAsync
)
629 if ( wpl
->flags
& WPF_SETMINPOSITION
)
630 Wnd
->InternalPos
.flags
|= WPF_SETMINPOSITION
;
632 if ( wpl
->flags
& WPF_RESTORETOMAXIMIZED
)
633 Wnd
->InternalPos
.flags
|= WPF_RESTORETOMAXIMIZED
;
640 co_WinPosArrangeIconicWindows(PWND parent
)
644 INT x
, y
, xspacing
, yspacing
, sx
, sy
;
646 ASSERT_REFS_CO(parent
);
648 IntGetClientRect( parent
, &rectParent
);
649 // FIXME: Support Minimize Metrics gspv.mm.iArrange.
650 // Default: ARW_BOTTOMLEFT
652 y
= rectParent
.bottom
;
654 xspacing
= UserGetSystemMetrics(SM_CXMINIMIZED
);
655 yspacing
= UserGetSystemMetrics(SM_CYMINIMIZED
);
657 Child
= parent
->spwndChild
;
660 if((Child
->style
& WS_MINIMIZE
) != 0 )
662 USER_REFERENCE_ENTRY Ref
;
663 UserRefObjectCo(Child
, &Ref
);
665 sx
= x
+ UserGetSystemMetrics(SM_CXBORDER
);
666 sy
= y
- yspacing
- UserGetSystemMetrics(SM_CYBORDER
);
668 Child
->InternalPos
.IconPos
.x
= sx
;
669 Child
->InternalPos
.IconPos
.y
= sy
;
670 Child
->InternalPos
.flags
|= WPF_MININIT
;
672 co_WinPosSetWindowPos( Child
, 0, sx
, sy
, xspacing
, yspacing
, SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOCOPYBITS
| SWP_ASYNCWINDOWPOS
);
674 UserDerefObjectCo(Child
);
676 if (x
<= rectParent
.right
- xspacing
)
684 Child
= Child
->spwndNext
;
690 WinPosFindIconPos(PWND Window
, POINT
*Pos
)
693 PWND pwndChild
, pwndParent
;
694 int x
, y
, xspacing
, yspacing
;
696 pwndParent
= Window
->spwndParent
;
697 if (pwndParent
== UserGetDesktopWindow())
699 //ERR("Parent is Desktop, Min off screen!\n");
700 /* ReactOS doesn't support iconic minimize to desktop */
701 Pos
->x
= Pos
->y
= -32000;
702 Window
->InternalPos
.flags
|= WPF_MININIT
;
703 Window
->InternalPos
.IconPos
.x
= Pos
->x
;
704 Window
->InternalPos
.IconPos
.y
= Pos
->y
;
708 IntGetClientRect( pwndParent
, &rectParent
);
709 // FIXME: Support Minimize Metrics gspv.mm.iArrange.
710 // Default: ARW_BOTTOMLEFT
712 y
= rectParent
.bottom
;
714 xspacing
= UserGetSystemMetrics(SM_CXMINIMIZED
);
715 yspacing
= UserGetSystemMetrics(SM_CYMINIMIZED
);
717 // Set to default position when minimized.
718 Pos
->x
= x
+ UserGetSystemMetrics(SM_CXBORDER
);
719 Pos
->y
= y
- yspacing
- UserGetSystemMetrics(SM_CYBORDER
);
721 for (pwndChild
= pwndParent
->spwndChild
; pwndChild
; pwndChild
= pwndChild
->spwndNext
)
723 if (pwndChild
== Window
) continue;
725 if ((pwndChild
->style
& (WS_VISIBLE
|WS_MINIMIZE
)) != (WS_VISIBLE
|WS_MINIMIZE
) )
730 if ( pwndChild
->InternalPos
.IconPos
.x
!= Pos
->x
&& pwndChild
->InternalPos
.IconPos
.y
!= Pos
->y
)
734 if (x
<= rectParent
.right
- xspacing
)
741 Pos
->x
= x
+ UserGetSystemMetrics(SM_CXBORDER
);
742 Pos
->y
= y
- yspacing
- UserGetSystemMetrics(SM_CYBORDER
);
745 Window
->InternalPos
.IconPos
.x
= Pos
->x
;
746 Window
->InternalPos
.IconPos
.y
= Pos
->y
;
747 Window
->InternalPos
.flags
|= WPF_MININIT
;
748 TRACE("Position is set! X:%d Y:%d\n",Pos
->x
,Pos
->y
);
753 co_WinPosMinMaximize(PWND Wnd
, UINT ShowFlag
, RECT
* NewPos
)
762 wpl
.length
= sizeof(wpl
);
763 IntGetWindowPlacement( Wnd
, &wpl
);
765 if (co_HOOK_CallHooks( WH_CBT
, HCBT_MINMAX
, (WPARAM
)Wnd
->head
.h
, ShowFlag
))
767 ERR("WinPosMinMaximize WH_CBT Call Hook return!\n");
768 return SWP_NOSIZE
| SWP_NOMOVE
;
770 if (Wnd
->style
& WS_MINIMIZE
)
774 case SW_SHOWMINNOACTIVE
:
775 case SW_SHOWMINIMIZED
:
776 case SW_FORCEMINIMIZE
:
778 return SWP_NOSIZE
| SWP_NOMOVE
;
780 if (!co_IntSendMessageNoWait(Wnd
->head
.h
, WM_QUERYOPEN
, 0, 0))
782 return(SWP_NOSIZE
| SWP_NOMOVE
);
784 SwpFlags
|= SWP_NOCOPYBITS
;
788 case SW_SHOWMINNOACTIVE
:
789 case SW_SHOWMINIMIZED
:
790 case SW_FORCEMINIMIZE
:
793 //ERR("MinMaximize Minimize\n");
794 if (Wnd
->style
& WS_MAXIMIZE
)
796 Wnd
->InternalPos
.flags
|= WPF_RESTORETOMAXIMIZED
;
800 Wnd
->InternalPos
.flags
&= ~WPF_RESTORETOMAXIMIZED
;
803 old_style
= IntSetStyle( Wnd
, WS_MINIMIZE
, WS_MAXIMIZE
);
805 co_UserRedrawWindow(Wnd
, NULL
, 0, RDW_VALIDATE
| RDW_NOERASE
| RDW_NOINTERNALPAINT
);
807 if (!(Wnd
->InternalPos
.flags
& WPF_SETMINPOSITION
))
808 Wnd
->InternalPos
.flags
&= ~WPF_MININIT
;
810 WinPosFindIconPos(Wnd
, &wpl
.ptMinPosition
);
812 if (!(old_style
& WS_MINIMIZE
)) SwpFlags
|= SWP_STATECHANGED
;
814 RECTL_vSetRect(NewPos
, wpl
.ptMinPosition
.x
, wpl
.ptMinPosition
.y
,
815 wpl
.ptMinPosition
.x
+ UserGetSystemMetrics(SM_CXMINIMIZED
),
816 wpl
.ptMinPosition
.y
+ UserGetSystemMetrics(SM_CYMINIMIZED
));
817 SwpFlags
|= SWP_NOCOPYBITS
;
823 //ERR("MinMaximize Maximize\n");
824 if ((Wnd
->style
& WS_MAXIMIZE
) && (Wnd
->style
& WS_VISIBLE
))
826 SwpFlags
= SWP_NOSIZE
| SWP_NOMOVE
;
829 co_WinPosGetMinMaxInfo(Wnd
, &Size
, &wpl
.ptMaxPosition
, NULL
, NULL
);
831 /*ERR("Maximize: %d,%d %dx%d\n",
832 wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, Size.x, Size.y);
834 old_style
= IntSetStyle( Wnd
, WS_MAXIMIZE
, WS_MINIMIZE
);
836 if (!(old_style
& WS_MAXIMIZE
)) SwpFlags
|= SWP_STATECHANGED
;
837 RECTL_vSetRect(NewPos
, wpl
.ptMaxPosition
.x
, wpl
.ptMaxPosition
.y
,
838 //wpl.ptMaxPosition.x + Size.x, wpl.ptMaxPosition.y + Size.y);
843 case SW_SHOWNOACTIVATE
:
844 Wnd
->InternalPos
.flags
&= ~WPF_RESTORETOMAXIMIZED
;
848 case SW_SHOWDEFAULT
: /* FIXME: should have its own handler */
850 //ERR("MinMaximize Restore\n");
851 old_style
= IntSetStyle( Wnd
, 0, WS_MINIMIZE
| WS_MAXIMIZE
);
852 if (old_style
& WS_MINIMIZE
)
854 if (Wnd
->InternalPos
.flags
& WPF_RESTORETOMAXIMIZED
)
856 co_WinPosGetMinMaxInfo(Wnd
, &Size
, &wpl
.ptMaxPosition
, NULL
, NULL
);
857 IntSetStyle( Wnd
, WS_MAXIMIZE
, 0 );
858 SwpFlags
|= SWP_STATECHANGED
;
859 RECTL_vSetRect(NewPos
, wpl
.ptMaxPosition
.x
, wpl
.ptMaxPosition
.y
,
860 wpl
.ptMaxPosition
.x
+ Size
.x
, wpl
.ptMaxPosition
.y
+ Size
.y
);
865 *NewPos
= wpl
.rcNormalPosition
;
866 NewPos
->right
-= NewPos
->left
;
867 NewPos
->bottom
-= NewPos
->top
;
873 if (!(old_style
& WS_MAXIMIZE
))
877 SwpFlags
|= SWP_STATECHANGED
;
878 Wnd
->InternalPos
.flags
&= ~WPF_RESTORETOMAXIMIZED
;
879 *NewPos
= wpl
.rcNormalPosition
;
880 NewPos
->right
-= NewPos
->left
;
881 NewPos
->bottom
-= NewPos
->top
;
890 UserHasWindowEdge(DWORD Style
, DWORD ExStyle
)
892 if (Style
& WS_MINIMIZE
)
894 if (ExStyle
& WS_EX_DLGMODALFRAME
)
896 if (ExStyle
& WS_EX_STATICEDGE
)
898 if (Style
& WS_THICKFRAME
)
901 if (Style
== WS_DLGFRAME
|| Style
== WS_CAPTION
)
907 IntGetWindowBorderMeasures(PWND Wnd
, UINT
*cx
, UINT
*cy
)
909 if(HAS_DLGFRAME(Wnd
->style
, Wnd
->ExStyle
) && !(Wnd
->style
& WS_MINIMIZE
))
911 *cx
= UserGetSystemMetrics(SM_CXDLGFRAME
);
912 *cy
= UserGetSystemMetrics(SM_CYDLGFRAME
);
916 if(HAS_THICKFRAME(Wnd
->style
, Wnd
->ExStyle
)&& !(Wnd
->style
& WS_MINIMIZE
))
918 *cx
= UserGetSystemMetrics(SM_CXFRAME
);
919 *cy
= UserGetSystemMetrics(SM_CYFRAME
);
921 else if(HAS_THINFRAME(Wnd
->style
, Wnd
->ExStyle
))
923 *cx
= UserGetSystemMetrics(SM_CXBORDER
);
924 *cy
= UserGetSystemMetrics(SM_CYBORDER
);
934 UserGetWindowBorders(DWORD Style
, DWORD ExStyle
, SIZE
*Size
, BOOL WithClient
)
938 if (UserHasWindowEdge(Style
, ExStyle
))
940 else if (ExStyle
& WS_EX_STATICEDGE
)
942 if ((ExStyle
& WS_EX_CLIENTEDGE
) && WithClient
)
944 if (Style
& WS_CAPTION
|| ExStyle
& WS_EX_DLGMODALFRAME
)
946 Size
->cx
= Size
->cy
= Border
;
947 if ((Style
& WS_THICKFRAME
) && !(Style
& WS_MINIMIZE
))
949 Size
->cx
+= UserGetSystemMetrics(SM_CXFRAME
) - UserGetSystemMetrics(SM_CXDLGFRAME
);
950 Size
->cy
+= UserGetSystemMetrics(SM_CYFRAME
) - UserGetSystemMetrics(SM_CYDLGFRAME
);
952 Size
->cx
*= UserGetSystemMetrics(SM_CXBORDER
);
953 Size
->cy
*= UserGetSystemMetrics(SM_CYBORDER
);
957 UserAdjustWindowRectEx(LPRECT lpRect
,
966 lpRect
->top
-= UserGetSystemMetrics(SM_CYMENU
);
968 if ((dwStyle
& WS_CAPTION
) == WS_CAPTION
)
970 if (dwExStyle
& WS_EX_TOOLWINDOW
)
971 lpRect
->top
-= UserGetSystemMetrics(SM_CYSMCAPTION
);
973 lpRect
->top
-= UserGetSystemMetrics(SM_CYCAPTION
);
975 UserGetWindowBorders(dwStyle
, dwExStyle
, &BorderSize
, TRUE
);
985 co_WinPosGetMinMaxInfo(PWND Window
, POINT
* MaxSize
, POINT
* MaxPos
,
986 POINT
* MinTrack
, POINT
* MaxTrack
)
991 LONG style
= Window
->style
;
993 LONG exstyle
= Window
->ExStyle
;
996 ASSERT_REFS_CO(Window
);
998 /* Compute default values */
1000 rc
= Window
->rcWindow
;
1001 MinMax
.ptReserved
.x
= rc
.left
;
1002 MinMax
.ptReserved
.y
= rc
.top
;
1004 if ((style
& WS_CAPTION
) == WS_CAPTION
)
1005 adjustedStyle
= style
& ~WS_BORDER
; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
1007 adjustedStyle
= style
;
1009 if(Window
->spwndParent
)
1010 IntGetClientRect(Window
->spwndParent
, &rc
);
1011 UserAdjustWindowRectEx(&rc
, adjustedStyle
, ((style
& WS_POPUP
) && Window
->IDMenu
), exstyle
);
1016 MinMax
.ptMaxSize
.x
= rc
.right
- rc
.left
;
1017 MinMax
.ptMaxSize
.y
= rc
.bottom
- rc
.top
;
1018 if (style
& (WS_DLGFRAME
| WS_BORDER
))
1020 MinMax
.ptMinTrackSize
.x
= UserGetSystemMetrics(SM_CXMINTRACK
);
1021 MinMax
.ptMinTrackSize
.y
= UserGetSystemMetrics(SM_CYMINTRACK
);
1025 MinMax
.ptMinTrackSize
.x
= 2 * xinc
;
1026 MinMax
.ptMinTrackSize
.y
= 2 * yinc
;
1028 MinMax
.ptMaxTrackSize
.x
= UserGetSystemMetrics(SM_CXMAXTRACK
);
1029 MinMax
.ptMaxTrackSize
.y
= UserGetSystemMetrics(SM_CYMAXTRACK
);
1030 MinMax
.ptMaxPosition
.x
= -xinc
;
1031 MinMax
.ptMaxPosition
.y
= -yinc
;
1033 if (!EMPTYPOINT(Window
->InternalPos
.MaxPos
)) MinMax
.ptMaxPosition
= Window
->InternalPos
.MaxPos
;
1035 co_IntSendMessage(Window
->head
.h
, WM_GETMINMAXINFO
, 0, (LPARAM
)&MinMax
);
1037 /* if the app didn't change the values, adapt them for the current monitor */
1038 if ((monitor
= UserGetPrimaryMonitor()))
1042 rc_work
= monitor
->rcMonitor
;
1044 if (style
& WS_MAXIMIZEBOX
)
1046 if ((style
& WS_CAPTION
) == WS_CAPTION
|| !(style
& (WS_CHILD
| WS_POPUP
)))
1047 rc_work
= monitor
->rcWork
;
1050 if (MinMax
.ptMaxSize
.x
== UserGetSystemMetrics(SM_CXSCREEN
) + 2 * xinc
&&
1051 MinMax
.ptMaxSize
.y
== UserGetSystemMetrics(SM_CYSCREEN
) + 2 * yinc
)
1053 MinMax
.ptMaxSize
.x
= (rc_work
.right
- rc_work
.left
) + 2 * xinc
;
1054 MinMax
.ptMaxSize
.y
= (rc_work
.bottom
- rc_work
.top
) + 2 * yinc
;
1056 if (MinMax
.ptMaxPosition
.x
== -xinc
&& MinMax
.ptMaxPosition
.y
== -yinc
)
1058 MinMax
.ptMaxPosition
.x
= rc_work
.left
- xinc
;
1059 MinMax
.ptMaxPosition
.y
= rc_work
.top
- yinc
;
1061 if (MinMax
.ptMaxSize
.x
>= (monitor
->rcMonitor
.right
- monitor
->rcMonitor
.left
) &&
1062 MinMax
.ptMaxSize
.y
>= (monitor
->rcMonitor
.bottom
- monitor
->rcMonitor
.top
) )
1063 Window
->state
|= WNDS_MAXIMIZESTOMONITOR
;
1065 Window
->state
&= ~WNDS_MAXIMIZESTOMONITOR
;
1069 MinMax
.ptMaxTrackSize
.x
= max(MinMax
.ptMaxTrackSize
.x
,
1070 MinMax
.ptMinTrackSize
.x
);
1071 MinMax
.ptMaxTrackSize
.y
= max(MinMax
.ptMaxTrackSize
.y
,
1072 MinMax
.ptMinTrackSize
.y
);
1075 *MaxSize
= MinMax
.ptMaxSize
;
1077 *MaxPos
= MinMax
.ptMaxPosition
;
1079 *MinTrack
= MinMax
.ptMinTrackSize
;
1081 *MaxTrack
= MinMax
.ptMaxTrackSize
;
1083 return 0; // FIXME: What does it return?
1088 FixClientRect(PRECTL ClientRect
, PRECTL WindowRect
)
1090 if (ClientRect
->left
< WindowRect
->left
)
1092 ClientRect
->left
= WindowRect
->left
;
1094 else if (WindowRect
->right
< ClientRect
->left
)
1096 ClientRect
->left
= WindowRect
->right
;
1098 if (ClientRect
->right
< WindowRect
->left
)
1100 ClientRect
->right
= WindowRect
->left
;
1102 else if (WindowRect
->right
< ClientRect
->right
)
1104 ClientRect
->right
= WindowRect
->right
;
1106 if (ClientRect
->top
< WindowRect
->top
)
1108 ClientRect
->top
= WindowRect
->top
;
1110 else if (WindowRect
->bottom
< ClientRect
->top
)
1112 ClientRect
->top
= WindowRect
->bottom
;
1114 if (ClientRect
->bottom
< WindowRect
->top
)
1116 ClientRect
->bottom
= WindowRect
->top
;
1118 else if (WindowRect
->bottom
< ClientRect
->bottom
)
1120 ClientRect
->bottom
= WindowRect
->bottom
;
1123 /***********************************************************************
1126 * Compute the valid rects from the old and new client rect and WVR_* flags.
1127 * Helper for WM_NCCALCSIZE handling.
1131 get_valid_rects( RECTL
*old_client
, RECTL
*new_client
, UINT flags
, RECTL
*valid
)
1135 if (flags
& WVR_REDRAW
)
1137 RECTL_vSetEmptyRect( &valid
[0] );
1138 RECTL_vSetEmptyRect( &valid
[1] );
1142 if (flags
& WVR_VALIDRECTS
)
1144 if (!RECTL_bIntersectRect( &valid
[0], &valid
[0], new_client
) ||
1145 !RECTL_bIntersectRect( &valid
[1], &valid
[1], old_client
))
1147 RECTL_vSetEmptyRect( &valid
[0] );
1148 RECTL_vSetEmptyRect( &valid
[1] );
1151 flags
= WVR_ALIGNLEFT
| WVR_ALIGNTOP
;
1155 valid
[0] = *new_client
;
1156 valid
[1] = *old_client
;
1159 /* make sure the rectangles have the same size */
1160 cx
= min( valid
[0].right
- valid
[0].left
, valid
[1].right
- valid
[1].left
);
1161 cy
= min( valid
[0].bottom
- valid
[0].top
, valid
[1].bottom
- valid
[1].top
);
1163 if (flags
& WVR_ALIGNBOTTOM
)
1165 valid
[0].top
= valid
[0].bottom
- cy
;
1166 valid
[1].top
= valid
[1].bottom
- cy
;
1170 valid
[0].bottom
= valid
[0].top
+ cy
;
1171 valid
[1].bottom
= valid
[1].top
+ cy
;
1173 if (flags
& WVR_ALIGNRIGHT
)
1175 valid
[0].left
= valid
[0].right
- cx
;
1176 valid
[1].left
= valid
[1].right
- cx
;
1180 valid
[0].right
= valid
[0].left
+ cx
;
1181 valid
[1].right
= valid
[1].left
+ cx
;
1187 co_WinPosDoNCCALCSize(PWND Window
, PWINDOWPOS WinPos
, RECTL
* WindowRect
, RECTL
* ClientRect
, RECTL
* validRects
)
1192 ASSERT_REFS_CO(Window
);
1194 /* Send WM_NCCALCSIZE message to get new client area */
1195 if ((WinPos
->flags
& (SWP_FRAMECHANGED
| SWP_NOSIZE
)) != SWP_NOSIZE
)
1197 NCCALCSIZE_PARAMS params
;
1198 WINDOWPOS winposCopy
;
1200 params
.rgrc
[0] = *WindowRect
; // new coordinates of a window that has been moved or resized
1201 params
.rgrc
[1] = Window
->rcWindow
; // window before it was moved or resized
1202 params
.rgrc
[2] = Window
->rcClient
; // client area before the window was moved or resized
1204 Parent
= Window
->spwndParent
;
1205 if (0 != (Window
->style
& WS_CHILD
) && Parent
)
1207 RECTL_vOffsetRect(&(params
.rgrc
[0]), - Parent
->rcClient
.left
, - Parent
->rcClient
.top
);
1208 RECTL_vOffsetRect(&(params
.rgrc
[1]), - Parent
->rcClient
.left
, - Parent
->rcClient
.top
);
1209 RECTL_vOffsetRect(&(params
.rgrc
[2]), - Parent
->rcClient
.left
, - Parent
->rcClient
.top
);
1212 params
.lppos
= &winposCopy
;
1213 winposCopy
= *WinPos
;
1215 wvrFlags
= co_IntSendMessage(Window
->head
.h
, WM_NCCALCSIZE
, TRUE
, (LPARAM
) ¶ms
);
1217 /* If the application send back garbage, ignore it */
1218 if (params
.rgrc
[0].left
<= params
.rgrc
[0].right
&&
1219 params
.rgrc
[0].top
<= params
.rgrc
[0].bottom
)
1221 *ClientRect
= params
.rgrc
[0]; // First rectangle contains the coordinates of the new client rectangle resulting from the move or resize
1222 if ((Window
->style
& WS_CHILD
) && Parent
)
1224 RECTL_vOffsetRect(ClientRect
, Parent
->rcClient
.left
, Parent
->rcClient
.top
);
1226 FixClientRect(ClientRect
, WindowRect
);
1229 if (ClientRect
->left
!= Window
->rcClient
.left
||
1230 ClientRect
->top
!= Window
->rcClient
.top
)
1232 WinPos
->flags
&= ~SWP_NOCLIENTMOVE
;
1235 if (ClientRect
->right
- ClientRect
->left
!= Window
->rcClient
.right
- Window
->rcClient
.left
)
1237 WinPos
->flags
&= ~SWP_NOCLIENTSIZE
;
1240 wvrFlags
&= ~WVR_HREDRAW
;
1242 if (ClientRect
->bottom
- ClientRect
->top
!= Window
->rcClient
.bottom
- Window
->rcClient
.top
)
1244 WinPos
->flags
&= ~SWP_NOCLIENTSIZE
;
1247 wvrFlags
&= ~WVR_VREDRAW
;
1249 validRects
[0] = params
.rgrc
[1]; // second rectangle contains the valid destination rectangle
1250 validRects
[1] = params
.rgrc
[2]; // third rectangle contains the valid source rectangle
1254 if (!(WinPos
->flags
& SWP_NOMOVE
) &&
1255 (ClientRect
->left
!= Window
->rcClient
.left
||
1256 ClientRect
->top
!= Window
->rcClient
.top
))
1258 WinPos
->flags
&= ~SWP_NOCLIENTMOVE
;
1262 if (WinPos
->flags
& (SWP_NOCOPYBITS
| SWP_NOREDRAW
| SWP_SHOWWINDOW
| SWP_HIDEWINDOW
))
1264 RECTL_vSetEmptyRect( &validRects
[0] );
1265 RECTL_vSetEmptyRect( &validRects
[1] );
1267 else get_valid_rects( &Window
->rcClient
, ClientRect
, wvrFlags
, validRects
);
1274 co_WinPosDoWinPosChanging(PWND Window
,
1279 ASSERT_REFS_CO(Window
);
1281 /* Send WM_WINDOWPOSCHANGING message */
1283 if (!(WinPos
->flags
& SWP_NOSENDCHANGING
))
1285 TRACE("Sending WM_WINDOWPOSCHANGING to hwnd %p.\n", Window
->head
.h
);
1286 co_IntSendMessageNoWait(Window
->head
.h
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
) WinPos
);
1289 /* Calculate new position and size */
1291 *WindowRect
= Window
->rcWindow
;
1292 *ClientRect
= (Window
->style
& WS_MINIMIZE
) ? Window
->rcWindow
: Window
->rcClient
;
1294 if (!(WinPos
->flags
& SWP_NOSIZE
))
1296 if (Window
->style
& WS_MINIMIZE
)
1298 WindowRect
->right
= WindowRect
->left
+ UserGetSystemMetrics(SM_CXMINIMIZED
);
1299 WindowRect
->bottom
= WindowRect
->top
+ UserGetSystemMetrics(SM_CYMINIMIZED
);
1303 WindowRect
->right
= WindowRect
->left
+ WinPos
->cx
;
1304 WindowRect
->bottom
= WindowRect
->top
+ WinPos
->cy
;
1308 if (!(WinPos
->flags
& SWP_NOMOVE
))
1315 Parent
= Window
->spwndParent
;
1317 if (((Window
->style
& WS_CHILD
) != 0) &&
1319 Parent
!= Window
->head
.rpdesk
->pDeskInfo
->spwnd
)
1321 TRACE("Not SWP_NOMOVE 1 Parent client offset X %d Y %d\n",X
,Y
);
1322 X
+= Parent
->rcClient
.left
;
1323 Y
+= Parent
->rcClient
.top
;
1324 TRACE("Not SWP_NOMOVE 2 Parent client offset X %d Y %d\n",X
,Y
);
1327 WindowRect
->left
= X
;
1328 WindowRect
->top
= Y
;
1329 WindowRect
->right
+= X
- Window
->rcWindow
.left
;
1330 WindowRect
->bottom
+= Y
- Window
->rcWindow
.top
;
1332 RECTL_vOffsetRect(ClientRect
, X
- Window
->rcWindow
.left
,
1333 Y
- Window
->rcWindow
.top
);
1335 WinPos
->flags
|= SWP_NOCLIENTMOVE
| SWP_NOCLIENTSIZE
;
1337 TRACE( "hwnd %p, after %p, swp %d,%d %dx%d flags %08x\n",
1338 WinPos
->hwnd
, WinPos
->hwndInsertAfter
, WinPos
->x
, WinPos
->y
,
1339 WinPos
->cx
, WinPos
->cy
, WinPos
->flags
);
1340 TRACE("WindowRect: %d %d %d %d\n", WindowRect
->left
,WindowRect
->top
,WindowRect
->right
,WindowRect
->bottom
);
1341 TRACE("ClientRect: %d %d %d %d\n", ClientRect
->left
,ClientRect
->top
,ClientRect
->right
,ClientRect
->bottom
);
1347 * Fix Z order taking into account owned popups -
1348 * basically we need to maintain them above the window that owns them
1350 * FIXME: hide/show owned popups when owner visibility changes.
1352 * ReactOS: See bug CORE-6129 and CORE-6554.
1356 // Pass all the win:test_children/popup_zorder tests except "move hwnd_F and its popups down" which is if'ed out.
1357 // Side effect, breaks more of the DeferWindowPos api tests, but wine breaks more!!!!
1360 WinPosDoOwnedPopups(PWND Window
, HWND hWndInsertAfter
)
1365 PWND DesktopWindow
, ChildObject
;
1368 TRACE("(%p) hInsertAfter = %p\n", Window
, hWndInsertAfter
);
1370 Owner
= Window
->spwndOwner
? Window
->spwndOwner
->head
.h
: NULL
;
1371 Style
= Window
->style
;
1373 if (Style
& WS_CHILD
)
1375 TRACE("Window is child\n");
1376 return hWndInsertAfter
;
1381 /* Make sure this popup stays above the owner */
1383 if (hWndInsertAfter
!= HWND_TOPMOST
)
1385 DesktopWindow
= UserGetDesktopWindow();
1386 List
= IntWinListChildren(DesktopWindow
);
1390 for (i
= 0; List
[i
]; i
++)
1392 BOOL topmost
= FALSE
;
1394 ChildObject
= ValidateHwndNoErr(List
[i
]);
1397 topmost
= (ChildObject
->ExStyle
& WS_EX_TOPMOST
) != 0;
1400 if (List
[i
] == Owner
)
1402 if (i
> 0) hWndInsertAfter
= List
[i
-1];
1403 else hWndInsertAfter
= topmost
? HWND_TOPMOST
: HWND_TOP
;
1407 if (hWndInsertAfter
== HWND_TOP
|| hWndInsertAfter
== HWND_NOTOPMOST
)
1409 if (!topmost
) break;
1411 else if (List
[i
] == hWndInsertAfter
) break;
1415 return hWndInsertAfter
;
1419 if (hWndInsertAfter
== HWND_BOTTOM
)
1421 ERR("Window is HWND_BOTTOM\n");
1422 if (List
) ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1428 DesktopWindow
= UserGetDesktopWindow();
1429 List
= IntWinListChildren(DesktopWindow
);
1436 if (hWndInsertAfter
== HWND_TOP
|| hWndInsertAfter
== HWND_NOTOPMOST
)
1438 if (hWndInsertAfter
== HWND_NOTOPMOST
|| !(Window
->ExStyle
& WS_EX_TOPMOST
))
1440 TRACE("skip all the topmost windows\n");
1441 /* skip all the topmost windows */
1443 (ChildObject
= ValidateHwndNoErr(List
[i
])) &&
1444 (ChildObject
->ExStyle
& WS_EX_TOPMOST
)) i
++;
1447 else if (hWndInsertAfter
!= HWND_TOPMOST
)
1449 /* skip windows that are already placed correctly */
1450 for (i
= 0; List
[i
]; i
++)
1452 if (List
[i
] == hWndInsertAfter
) break;
1453 if (List
[i
] == UserHMGetHandle(Window
))
1455 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1456 goto done
; /* nothing to do if window is moving backwards in z-order */
1461 for (; List
[i
]; i
++)
1464 USER_REFERENCE_ENTRY Ref
;
1466 if (List
[i
] == UserHMGetHandle(Window
))
1469 if (!(Wnd
= ValidateHwndNoErr(List
[i
])))
1472 Owner
= Wnd
->spwndOwner
? Wnd
->spwndOwner
->head
.h
: NULL
;
1474 if (Owner
!= UserHMGetHandle(Window
)) continue;
1476 UserRefObjectCo(Wnd
, &Ref
);
1477 TRACE( "moving %p owned by %p after %p\n", List
[i
], UserHMGetHandle(Window
), hWndInsertAfter
);
1478 co_WinPosSetWindowPos(Wnd
, hWndInsertAfter
, 0, 0, 0, 0,
1479 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOSENDCHANGING
| SWP_DEFERERASE
);
1481 UserDerefObjectCo(Wnd
);
1482 hWndInsertAfter
= List
[i
];
1484 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1487 return hWndInsertAfter
;
1491 /***********************************************************************
1492 * WinPosInternalMoveWindow
1494 * Update WindowRect and ClientRect of Window and all of its children
1495 * We keep both WindowRect and ClientRect in screen coordinates internally
1499 WinPosInternalMoveWindow(PWND Window
, INT MoveX
, INT MoveY
)
1503 ASSERT(Window
!= Window
->spwndChild
);
1504 TRACE("InternalMoveWin X %d Y %d\n", MoveX
, MoveY
);
1506 Window
->rcWindow
.left
+= MoveX
;
1507 Window
->rcWindow
.right
+= MoveX
;
1508 Window
->rcWindow
.top
+= MoveY
;
1509 Window
->rcWindow
.bottom
+= MoveY
;
1511 Window
->rcClient
.left
+= MoveX
;
1512 Window
->rcClient
.right
+= MoveX
;
1513 Window
->rcClient
.top
+= MoveY
;
1514 Window
->rcClient
.bottom
+= MoveY
;
1516 for(Child
= Window
->spwndChild
; Child
; Child
= Child
->spwndNext
)
1518 WinPosInternalMoveWindow(Child
, MoveX
, MoveY
);
1523 * WinPosFixupSWPFlags
1525 * Fix redundant flags and values in the WINDOWPOS structure.
1529 WinPosFixupFlags(WINDOWPOS
*WinPos
, PWND Wnd
)
1534 /* Finally make sure that all coordinates are valid */
1535 if (WinPos
->x
< -32768) WinPos
->x
= -32768;
1536 else if (WinPos
->x
> 32767) WinPos
->x
= 32767;
1537 if (WinPos
->y
< -32768) WinPos
->y
= -32768;
1538 else if (WinPos
->y
> 32767) WinPos
->y
= 32767;
1540 WinPos
->cx
= max(WinPos
->cx
, 0);
1541 WinPos
->cy
= max(WinPos
->cy
, 0);
1543 Parent
= UserGetAncestor( Wnd
, GA_PARENT
);
1544 if (!IntIsWindowVisible( Parent
)) WinPos
->flags
|= SWP_NOREDRAW
;
1546 if (Wnd
->style
& WS_VISIBLE
) WinPos
->flags
&= ~SWP_SHOWWINDOW
;
1549 WinPos
->flags
&= ~SWP_HIDEWINDOW
;
1550 if (!(WinPos
->flags
& SWP_SHOWWINDOW
)) WinPos
->flags
|= SWP_NOREDRAW
;
1553 /* Check for right size */
1554 if (Wnd
->rcWindow
.right
- Wnd
->rcWindow
.left
== WinPos
->cx
&&
1555 Wnd
->rcWindow
.bottom
- Wnd
->rcWindow
.top
== WinPos
->cy
)
1557 WinPos
->flags
|= SWP_NOSIZE
;
1562 IntClientToScreen( Parent
, &pt
);
1563 TRACE("WPFU C2S wpx %d wpy %d ptx %d pty %d\n",WinPos
->x
,WinPos
->y
,pt
.x
,pt
.y
);
1564 /* Check for right position */
1565 if (Wnd
->rcWindow
.left
== pt
.x
&& Wnd
->rcWindow
.top
== pt
.y
)
1567 //ERR("In right pos\n");
1568 WinPos
->flags
|= SWP_NOMOVE
;
1571 if (WinPos
->hwnd
!= UserGetForegroundWindow() && (Wnd
->style
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)
1573 /* Bring to the top when activating */
1574 if (!(WinPos
->flags
& (SWP_NOACTIVATE
|SWP_HIDEWINDOW
)) &&
1575 (WinPos
->flags
& SWP_NOZORDER
||
1576 (WinPos
->hwndInsertAfter
!= HWND_TOPMOST
&& WinPos
->hwndInsertAfter
!= HWND_NOTOPMOST
)))
1578 WinPos
->flags
&= ~SWP_NOZORDER
;
1579 WinPos
->hwndInsertAfter
= (0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
) ? HWND_TOPMOST
: HWND_TOP
);
1583 /* Check hwndInsertAfter */
1584 if (!(WinPos
->flags
& SWP_NOZORDER
))
1586 /* Fix sign extension */
1587 if (WinPos
->hwndInsertAfter
== (HWND
)0xffff)
1589 WinPos
->hwndInsertAfter
= HWND_TOPMOST
;
1591 else if (WinPos
->hwndInsertAfter
== (HWND
)0xfffe)
1593 WinPos
->hwndInsertAfter
= HWND_NOTOPMOST
;
1596 if (WinPos
->hwndInsertAfter
== HWND_TOP
)
1598 /* Keep it topmost when it's already topmost */
1599 if ((Wnd
->ExStyle
& WS_EX_TOPMOST
) != 0)
1600 WinPos
->hwndInsertAfter
= HWND_TOPMOST
;
1602 if (IntGetWindow(WinPos
->hwnd
, GW_HWNDFIRST
) == WinPos
->hwnd
)
1603 WinPos
->flags
|= SWP_NOZORDER
;
1605 else if (WinPos
->hwndInsertAfter
== HWND_BOTTOM
)
1607 if (!(Wnd
->ExStyle
& WS_EX_TOPMOST
) && IntGetWindow(WinPos
->hwnd
, GW_HWNDLAST
) == WinPos
->hwnd
)
1608 WinPos
->flags
|= SWP_NOZORDER
;
1610 else if (WinPos
->hwndInsertAfter
== HWND_TOPMOST
)
1612 if ((Wnd
->ExStyle
& WS_EX_TOPMOST
) && IntGetWindow(WinPos
->hwnd
, GW_HWNDFIRST
) == WinPos
->hwnd
)
1613 WinPos
->flags
|= SWP_NOZORDER
;
1615 else if (WinPos
->hwndInsertAfter
== HWND_NOTOPMOST
)
1617 if (!(Wnd
->ExStyle
& WS_EX_TOPMOST
))
1618 WinPos
->flags
|= SWP_NOZORDER
;
1620 else /* hwndInsertAfter must be a sibling of the window */
1624 InsAfterWnd
= ValidateHwndNoErr(WinPos
->hwndInsertAfter
);
1630 if (InsAfterWnd
->spwndParent
!= Wnd
->spwndParent
)
1632 /* Note from wine User32 Win test_SetWindowPos:
1633 "Returns TRUE also for windows that are not siblings"
1634 "Does not seem to do anything even without passing flags, still returns TRUE"
1635 "Same thing the other way around."
1636 ".. and with these windows."
1643 * We don't need to change the Z order of hwnd if it's already
1644 * inserted after hwndInsertAfter or when inserting hwnd after
1647 if ((WinPos
->hwnd
== WinPos
->hwndInsertAfter
) ||
1648 ((InsAfterWnd
->spwndNext
) && (WinPos
->hwnd
== InsAfterWnd
->spwndNext
->head
.h
)))
1650 WinPos
->flags
|= SWP_NOZORDER
;
1659 /* x and y are always screen relative */
1661 co_WinPosSetWindowPos(
1663 HWND WndInsertAfter
,
1672 RECTL NewWindowRect
;
1673 RECTL NewClientRect
;
1674 RECTL valid_rects
[2];
1675 PREGION VisBefore
= NULL
;
1676 PREGION VisBeforeJustClient
= NULL
;
1677 PREGION VisAfter
= NULL
;
1678 PREGION CopyRgn
= NULL
;
1680 RECTL OldWindowRect
, OldClientRect
;
1685 BOOL bPointerInWindow
;
1687 ASSERT_REFS_CO(Window
);
1689 /* FIXME: Get current active window from active queue. Why? since r2915. */
1691 bPointerInWindow
= IntPtInWindow(Window
, gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
);
1693 WinPos
.hwnd
= Window
->head
.h
;
1694 WinPos
.hwndInsertAfter
= WndInsertAfter
;
1699 WinPos
.flags
= flags
;
1701 if ( flags
& SWP_ASYNCWINDOWPOS
)
1704 PWINDOWPOS ppos
= ExAllocatePoolWithTag(PagedPool
, sizeof(WINDOWPOS
), USERTAG_SWP
);
1707 WinPos
.flags
&= ~SWP_ASYNCWINDOWPOS
; // Clear flag.
1709 /* Yes it's a pointer inside Win32k! */
1710 lRes
= co_IntSendMessageNoWait( WinPos
.hwnd
, WM_ASYNC_SETWINDOWPOS
, 0, (LPARAM
)ppos
);
1711 /* We handle this the same way as Event Hooks and Hooks. */
1714 ExFreePoolWithTag(ppos
, USERTAG_SWP
);
1722 co_WinPosDoWinPosChanging(Window
, &WinPos
, &NewWindowRect
, &NewClientRect
);
1724 /* Does the window still exist? */
1725 if (!IntIsWindow(WinPos
.hwnd
))
1727 TRACE("WinPosSetWindowPos: Invalid handle 0x%p!\n",WinPos
.hwnd
);
1728 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE
);
1732 /* Fix up the flags. */
1733 if (!WinPosFixupFlags(&WinPos
, Window
))
1739 Ancestor
= UserGetAncestor(Window
, GA_PARENT
);
1740 if ( (WinPos
.flags
& (SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) != SWP_NOZORDER
&&
1741 Ancestor
&& Ancestor
->head
.h
== IntGetDesktopWindow() )
1743 WinPos
.hwndInsertAfter
= WinPosDoOwnedPopups(Window
, WinPos
.hwndInsertAfter
);
1746 if (!(WinPos
.flags
& SWP_NOREDRAW
))
1748 /* Compute the visible region before the window position is changed */
1749 if (!(WinPos
.flags
& SWP_SHOWWINDOW
) &&
1750 (WinPos
.flags
& (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
|
1751 SWP_HIDEWINDOW
| SWP_FRAMECHANGED
)) !=
1752 (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
))
1754 VisBefore
= VIS_ComputeVisibleRegion(Window
, FALSE
, FALSE
,
1755 (Window
->style
& WS_CLIPSIBLINGS
) ? TRUE
: FALSE
);
1757 if ( VisBefore
!= NULL
&&
1758 REGION_Complexity(VisBefore
) == NULLREGION
)
1760 REGION_Delete(VisBefore
);
1765 IntGdiOffsetRgn(VisBefore
, -Window
->rcWindow
.left
, -Window
->rcWindow
.top
);
1768 /* Calculate the non client area for resizes, as this is used in the copy region */
1769 if (!(WinPos
.flags
& SWP_NOSIZE
))
1771 VisBeforeJustClient
= VIS_ComputeVisibleRegion(Window
, TRUE
, FALSE
,
1772 (Window
->style
& WS_CLIPSIBLINGS
) ? TRUE
: FALSE
);
1774 if ( VisBeforeJustClient
!= NULL
&&
1775 REGION_Complexity(VisBeforeJustClient
) == NULLREGION
)
1777 REGION_Delete(VisBeforeJustClient
);
1778 VisBeforeJustClient
= NULL
;
1780 else if(VisBeforeJustClient
)
1782 IntGdiOffsetRgn(VisBeforeJustClient
, -Window
->rcWindow
.left
, -Window
->rcWindow
.top
);
1788 WvrFlags
= co_WinPosDoNCCALCSize(Window
, &WinPos
, &NewWindowRect
, &NewClientRect
, valid_rects
);
1790 // ERR("co_WinPosDoNCCALCSize returned 0x%x\n valid dest: %d %d %d %d\n valid src : %d %d %d %d\n", WvrFlags,
1791 // valid_rects[0].left,valid_rects[0].top,valid_rects[0].right,valid_rects[0].bottom,
1792 // valid_rects[1].left,valid_rects[1].top,valid_rects[1].right,valid_rects[1].bottom);
1794 /* Validate link windows. (also take into account shell window in hwndShellWindow) */
1795 if (!(WinPos
.flags
& SWP_NOZORDER
) && WinPos
.hwnd
!= UserGetShellWindow())
1797 IntLinkHwnd(Window
, WinPos
.hwndInsertAfter
);
1800 OldWindowRect
= Window
->rcWindow
;
1801 OldClientRect
= Window
->rcClient
;
1803 if (NewClientRect
.left
!= OldClientRect
.left
||
1804 NewClientRect
.top
!= OldClientRect
.top
)
1806 // Move child window if their parent is moved. Keep Child window relative to Parent...
1807 WinPosInternalMoveWindow(Window
,
1808 NewClientRect
.left
- OldClientRect
.left
,
1809 NewClientRect
.top
- OldClientRect
.top
);
1812 Window
->rcWindow
= NewWindowRect
;
1813 Window
->rcClient
= NewClientRect
;
1815 /* erase parent when hiding or resizing child */
1816 if (WinPos
.flags
& SWP_HIDEWINDOW
)
1818 /* Clear the update region */
1819 co_UserRedrawWindow( Window
,
1822 RDW_VALIDATE
| RDW_NOFRAME
| RDW_NOERASE
| RDW_NOINTERNALPAINT
| RDW_ALLCHILDREN
);
1824 if (Window
->spwndParent
== UserGetDesktopWindow())
1825 co_IntShellHookNotify(HSHELL_WINDOWDESTROYED
, (WPARAM
)Window
->head
.h
, 0);
1827 Window
->style
&= ~WS_VISIBLE
; //IntSetStyle( Window, 0, WS_VISIBLE );
1828 Window
->head
.pti
->cVisWindows
--;
1829 IntNotifyWinEvent(EVENT_OBJECT_HIDE
, Window
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
1831 else if (WinPos
.flags
& SWP_SHOWWINDOW
)
1833 if (Window
->spwndParent
== UserGetDesktopWindow() &&
1834 Window
->spwndOwner
== NULL
&&
1835 (!(Window
->ExStyle
& WS_EX_TOOLWINDOW
) ||
1836 (Window
->ExStyle
& WS_EX_APPWINDOW
)))
1837 co_IntShellHookNotify(HSHELL_WINDOWCREATED
, (WPARAM
)Window
->head
.h
, 0);
1839 Window
->style
|= WS_VISIBLE
; //IntSetStyle( Window, WS_VISIBLE, 0 );
1840 Window
->head
.pti
->cVisWindows
++;
1841 IntNotifyWinEvent(EVENT_OBJECT_SHOW
, Window
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
1844 if (Window
->hrgnUpdate
!= NULL
&& Window
->hrgnUpdate
!= HRGN_WINDOW
)
1846 NtGdiOffsetRgn(Window
->hrgnUpdate
,
1847 NewWindowRect
.left
- OldWindowRect
.left
,
1848 NewWindowRect
.top
- OldWindowRect
.top
);
1851 DceResetActiveDCEs(Window
); // For WS_VISIBLE changes.
1853 if (!(WinPos
.flags
& SWP_NOREDRAW
))
1855 /* Determine the new visible region */
1856 VisAfter
= VIS_ComputeVisibleRegion(Window
, FALSE
, FALSE
,
1857 (Window
->style
& WS_CLIPSIBLINGS
) ? TRUE
: FALSE
);
1859 if ( VisAfter
!= NULL
&&
1860 REGION_Complexity(VisAfter
) == NULLREGION
)
1862 REGION_Delete(VisAfter
);
1867 IntGdiOffsetRgn(VisAfter
, -Window
->rcWindow
.left
, -Window
->rcWindow
.top
);
1871 * Determine which pixels can be copied from the old window position
1872 * to the new. Those pixels must be visible in both the old and new
1873 * position. Also, check the class style to see if the windows of this
1874 * class need to be completely repainted on (horizontal/vertical) size
1877 if ( VisBefore
!= NULL
&&
1879 !(WinPos
.flags
& SWP_NOCOPYBITS
) &&
1880 ((WinPos
.flags
& SWP_NOSIZE
) || !(WvrFlags
& WVR_REDRAW
)) &&
1881 !(Window
->ExStyle
& WS_EX_TRANSPARENT
) )
1885 * If this is (also) a window resize, the whole nonclient area
1886 * needs to be repainted. So we limit the copy to the client area,
1887 * 'cause there is no use in copying it (would possibly cause
1888 * "flashing" too). However, if the copy region is already empty,
1889 * we don't have to crop (can't take anything away from an empty
1893 CopyRgn
= IntSysCreateRectpRgn(0, 0, 0, 0);
1894 if (WinPos
.flags
& SWP_NOSIZE
)
1895 RgnType
= IntGdiCombineRgn(CopyRgn
, VisAfter
, VisBefore
, RGN_AND
);
1896 else if (VisBeforeJustClient
!= NULL
)
1898 RgnType
= IntGdiCombineRgn(CopyRgn
, VisAfter
, VisBeforeJustClient
, RGN_AND
);
1899 REGION_Delete(VisBeforeJustClient
);
1902 /* No use in copying bits which are in the update region. */
1903 if (Window
->hrgnUpdate
!= NULL
)
1905 PREGION RgnUpdate
= RGNOBJAPI_Lock(Window
->hrgnUpdate
, NULL
);
1908 IntGdiOffsetRgn(CopyRgn
, NewWindowRect
.left
, NewWindowRect
.top
);
1909 IntGdiCombineRgn(CopyRgn
, CopyRgn
, RgnUpdate
, RGN_DIFF
);
1910 IntGdiOffsetRgn(CopyRgn
, -NewWindowRect
.left
, -NewWindowRect
.top
);
1911 RGNOBJAPI_Unlock(RgnUpdate
);
1916 * Now, get the bounding box of the copy region. If it's empty
1917 * there's nothing to copy. Also, it's no use copying bits onto
1920 if (REGION_GetRgnBox(CopyRgn
, &CopyRect
) == NULLREGION
)
1922 /* Nothing to copy, clean up */
1923 REGION_Delete(CopyRgn
);
1926 else if (OldWindowRect
.left
!= NewWindowRect
.left
||
1927 OldWindowRect
.top
!= NewWindowRect
.top
)
1929 HRGN DcRgn
= NtGdiCreateRectRgn(0, 0, 0, 0);
1930 PREGION DcRgnObj
= RGNOBJAPI_Lock(DcRgn
, NULL
);
1933 * Small trick here: there is no function to bitblt a region. So
1934 * we set the region as the clipping region, take the bounding box
1935 * of the region and bitblt that. Since nothing outside the clipping
1936 * region is copied, this has the effect of bitblt'ing the region.
1938 * Since NtUserGetDCEx takes ownership of the clip region, we need
1939 * to create a copy of CopyRgn and pass that. We need CopyRgn later
1941 IntGdiCombineRgn(DcRgnObj
, CopyRgn
, NULL
, RGN_COPY
);
1942 IntGdiOffsetRgn(DcRgnObj
, NewWindowRect
.left
, NewWindowRect
.top
);
1943 RGNOBJAPI_Unlock(DcRgnObj
);
1944 Dc
= UserGetDCEx( Window
,
1946 DCX_WINDOW
|DCX_CACHE
|DCX_INTERSECTRGN
|DCX_CLIPSIBLINGS
|DCX_KEEPCLIPRGN
);
1948 CopyRect
.left
, CopyRect
.top
,
1949 CopyRect
.right
- CopyRect
.left
,
1950 CopyRect
.bottom
- CopyRect
.top
,
1952 CopyRect
.left
+ (OldWindowRect
.left
- NewWindowRect
.left
),
1953 CopyRect
.top
+ (OldWindowRect
.top
- NewWindowRect
.top
),
1958 UserReleaseDC(Window
, Dc
, FALSE
);
1959 IntValidateParent(Window
, CopyRgn
, FALSE
);
1960 GreDeleteObject(DcRgn
);
1968 /* We need to redraw what wasn't visible before */
1969 if (VisAfter
!= NULL
)
1971 PREGION DirtyRgn
= IntSysCreateRectpRgn(0, 0, 0, 0);
1974 if (CopyRgn
!= NULL
)
1976 RgnType
= IntGdiCombineRgn(DirtyRgn
, VisAfter
, CopyRgn
, RGN_DIFF
);
1980 RgnType
= IntGdiCombineRgn(DirtyRgn
, VisAfter
, 0, RGN_COPY
);
1982 if (RgnType
!= ERROR
&& RgnType
!= NULLREGION
)
1985 NtGdiOffsetRgn(DirtyRgn, Window->rcWindow.left, Window->rcWindow.top);
1986 IntInvalidateWindows( Window,
1988 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
1990 GreDeleteObject(DirtyRgn);
1993 PWND Parent
= Window
->spwndParent
;
1995 IntGdiOffsetRgn( DirtyRgn
,
1996 Window
->rcWindow
.left
,
1997 Window
->rcWindow
.top
);
1998 if ( (Window
->style
& WS_CHILD
) &&
2000 !(Parent
->style
& WS_CLIPCHILDREN
))
2002 IntInvalidateWindows( Parent
,
2004 RDW_ERASE
| RDW_INVALIDATE
);
2005 co_IntPaintWindows(Parent
, RDW_ERASENOW
, FALSE
);
2009 IntInvalidateWindows( Window
,
2011 RDW_ERASE
| RDW_FRAME
| RDW_INVALIDATE
| RDW_ALLCHILDREN
);
2014 REGION_Delete(DirtyRgn
);
2018 if (CopyRgn
!= NULL
)
2020 REGION_Delete(CopyRgn
);
2023 /* Expose what was covered before but not covered anymore */
2024 if (VisBefore
!= NULL
)
2026 PREGION ExposedRgn
= IntSysCreateRectpRgn(0, 0, 0, 0);
2029 RgnType
= IntGdiCombineRgn(ExposedRgn
, VisBefore
, NULL
, RGN_COPY
);
2030 IntGdiOffsetRgn( ExposedRgn
,
2031 OldWindowRect
.left
- NewWindowRect
.left
,
2032 OldWindowRect
.top
- NewWindowRect
.top
);
2034 if (VisAfter
!= NULL
)
2035 RgnType
= IntGdiCombineRgn(ExposedRgn
, ExposedRgn
, VisAfter
, RGN_DIFF
);
2037 if (RgnType
!= ERROR
&& RgnType
!= NULLREGION
)
2039 co_VIS_WindowLayoutChanged(Window
, ExposedRgn
);
2041 REGION_Delete(ExposedRgn
);
2043 REGION_Delete(VisBefore
);
2046 if (VisAfter
!= NULL
)
2048 REGION_Delete(VisAfter
);
2052 if (!(WinPos
.flags
& (SWP_NOACTIVATE
|SWP_HIDEWINDOW
)))
2054 if ((Window
->style
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
2056 co_IntSendMessageNoWait(WinPos
.hwnd
, WM_CHILDACTIVATE
, 0, 0);
2060 //ERR("SetWindowPos Set FG Window!\n");
2061 if (Window
->state
& WNDS_BEINGACTIVATED
) // Inside SAW?
2062 co_IntSetActiveWindow(Window
, FALSE
, TRUE
, FALSE
); // Fixes Api AttachThreadInput tests.
2064 co_IntSetForegroundWindow(Window
); // Fixes SW_HIDE issues. Wine win test_SetActiveWindow & test_SetForegroundWindow.
2068 /* And last, send the WM_WINDOWPOSCHANGED message */
2070 TRACE("\tstatus flags = %04x\n", WinPos
.flags
& SWP_AGG_STATUSFLAGS
);
2072 if ((WinPos
.flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOPOSCHANGE
)
2074 /* WM_WINDOWPOSCHANGED is sent even if SWP_NOSENDCHANGING is set
2075 and always contains final window position.
2077 WinPos
.x
= NewWindowRect
.left
;
2078 WinPos
.y
= NewWindowRect
.top
;
2079 WinPos
.cx
= NewWindowRect
.right
- NewWindowRect
.left
;
2080 WinPos
.cy
= NewWindowRect
.bottom
- NewWindowRect
.top
;
2081 co_IntSendMessageNoWait(WinPos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
) &WinPos
);
2084 if ( WinPos
.flags
& SWP_FRAMECHANGED
|| WinPos
.flags
& SWP_STATECHANGED
||
2085 !(WinPos
.flags
& SWP_NOCLIENTSIZE
) || !(WinPos
.flags
& SWP_NOCLIENTMOVE
) )
2087 PWND pWnd
= ValidateHwndNoErr(WinPos
.hwnd
);
2089 IntNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE
, pWnd
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
2092 if(bPointerInWindow
!= IntPtInWindow(Window
, gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
))
2094 /* Generate mouse move message */
2096 msg
.message
= WM_MOUSEMOVE
;
2097 msg
.wParam
= UserGetMouseButtonsState();
2098 msg
.lParam
= MAKELPARAM(gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
);
2099 msg
.pt
= gpsi
->ptCursor
;
2100 co_MsqInsertMouseMessage(&msg
, 0, 0, TRUE
);
2107 co_WinPosGetNonClientSize(PWND Window
, RECT
* WindowRect
, RECT
* ClientRect
)
2111 ASSERT_REFS_CO(Window
);
2113 *ClientRect
= *WindowRect
;
2114 Result
= co_IntSendMessageNoWait(Window
->head
.h
, WM_NCCALCSIZE
, FALSE
, (LPARAM
) ClientRect
);
2116 FixClientRect(ClientRect
, WindowRect
);
2122 co_WinPosSendSizeMove(PWND Wnd
)
2126 WPARAM wParam
= SIZE_RESTORED
;
2128 IntGetClientRect(Wnd
, &Rect
);
2129 lParam
= MAKELONG(Rect
.right
-Rect
.left
, Rect
.bottom
-Rect
.top
);
2131 Wnd
->state
&= ~WNDS_SENDSIZEMOVEMSGS
;
2133 if (Wnd
->style
& WS_MAXIMIZE
)
2135 wParam
= SIZE_MAXIMIZED
;
2137 else if (Wnd
->style
& WS_MINIMIZE
)
2139 wParam
= SIZE_MINIMIZED
;
2143 co_IntSendMessageNoWait(UserHMGetHandle(Wnd
), WM_SIZE
, wParam
, lParam
);
2145 if (Wnd
->spwndParent
== UserGetDesktopWindow()) // Wnd->spwndParent->fnid == FNID_DESKTOP )
2146 lParam
= MAKELONG(Wnd
->rcClient
.left
, Wnd
->rcClient
.top
);
2148 lParam
= MAKELONG(Wnd
->rcClient
.left
-Wnd
->spwndParent
->rcClient
.left
, Wnd
->rcClient
.top
-Wnd
->spwndParent
->rcClient
.top
);
2150 co_IntSendMessageNoWait(UserHMGetHandle(Wnd
), WM_MOVE
, 0, lParam
);
2152 IntEngWindowChanged(Wnd
, WOC_RGN_CLIENT
);
2156 co_WinPosShowWindow(PWND Wnd
, INT Cmd
)
2159 UINT Swp
= 0, EventMsg
= 0;
2160 RECTL NewPos
= {0, 0, 0, 0};
2166 BOOL ShowOwned
= FALSE
;
2167 ASSERT_REFS_CO(Wnd
);
2168 //ERR("co_WinPosShowWindow START\n");
2170 pti
= PsGetCurrentThreadWin32Thread();
2171 WasVisible
= (Wnd
->style
& WS_VISIBLE
) != 0;
2180 //ERR("co_WinPosShowWindow Exit Bad\n");
2183 Swp
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
2184 if (Wnd
!= pti
->MessageQueue
->spwndActive
)
2185 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2189 case SW_FORCEMINIMIZE
: /* FIXME: Does not work if thread is hung. */
2190 case SW_SHOWMINNOACTIVE
:
2191 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2193 case SW_SHOWMINIMIZED
:
2194 Swp
|= SWP_SHOWWINDOW
;
2198 Swp
|= SWP_NOACTIVATE
;
2199 if (!(style
& WS_MINIMIZE
))
2201 IntShowOwnedPopups(Wnd
, FALSE
);
2203 // Fix wine Win test_SetFocus todo #1 & #2,
2204 if (Cmd
== SW_SHOWMINIMIZED
)
2206 //ERR("co_WinPosShowWindow Set focus 1\n");
2207 if ((style
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
2208 co_UserSetFocus(Wnd
->spwndParent
);
2213 Swp
|= co_WinPosMinMaximize(Wnd
, Cmd
, &NewPos
) |
2216 EventMsg
= EVENT_SYSTEM_MINIMIZESTART
;
2222 Swp
|= SWP_FRAMECHANGED
;
2226 //ERR("co_WinPosShowWindow Exit Good\n");
2229 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
2234 case SW_SHOWMAXIMIZED
:
2236 Swp
|= SWP_SHOWWINDOW
;
2237 if (!(style
& WS_MAXIMIZE
))
2241 Swp
|= co_WinPosMinMaximize(Wnd
, SW_MAXIMIZE
, &NewPos
) |
2244 EventMsg
= EVENT_SYSTEM_MINIMIZEEND
;
2250 Swp
|= SWP_FRAMECHANGED
;
2254 //ERR("co_WinPosShowWindow Exit Good 1\n");
2257 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
2263 Swp
|= SWP_NOACTIVATE
| SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
2264 if (style
& WS_CHILD
&& !(Wnd
->ExStyle
& WS_EX_MDICHILD
)) Swp
|= SWP_NOZORDER
;
2267 if (WasVisible
) return(TRUE
); // Nothing to do!
2268 Swp
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
2269 /* Don't activate the topmost window. */
2270 if (style
& WS_CHILD
&& !(Wnd
->ExStyle
& WS_EX_MDICHILD
)) Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2273 case SW_SHOWNOACTIVATE
:
2274 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2277 case SW_SHOWDEFAULT
:
2279 if (!WasVisible
) Swp
|= SWP_SHOWWINDOW
;
2280 if (style
& (WS_MINIMIZE
| WS_MAXIMIZE
))
2282 Swp
|= co_WinPosMinMaximize(Wnd
, Cmd
, &NewPos
) |
2285 if (style
& WS_MINIMIZE
) EventMsg
= EVENT_SYSTEM_MINIMIZEEND
;
2291 Swp
|= SWP_FRAMECHANGED
;
2295 //ERR("co_WinPosShowWindow Exit Good 3\n");
2298 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
2300 if ( style
& WS_CHILD
&&
2301 !(Wnd
->ExStyle
& WS_EX_MDICHILD
) &&
2302 !(Swp
& SWP_STATECHANGED
))
2303 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2307 //ERR("co_WinPosShowWindow Exit Good 4\n");
2311 ShowFlag
= (Cmd
!= SW_HIDE
);
2313 if ((ShowFlag
!= WasVisible
|| Cmd
== SW_SHOWNA
) && Cmd
!= SW_SHOWMAXIMIZED
&& !(Swp
& SWP_STATECHANGED
))
2315 co_IntSendMessageNoWait(Wnd
->head
.h
, WM_SHOWWINDOW
, ShowFlag
, 0);
2316 if (!(Wnd
->state2
& WNDS2_WIN31COMPAT
))
2317 co_IntSendMessageNoWait(Wnd
->head
.h
, WM_SETVISIBLE
, ShowFlag
, 0);
2318 if (!VerifyWnd(Wnd
)) return WasVisible
;
2321 /* We can't activate a child window */
2322 if ((Wnd
->style
& WS_CHILD
) &&
2323 !(Wnd
->ExStyle
& WS_EX_MDICHILD
) &&
2326 //ERR("SWP Child No active and ZOrder\n");
2327 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2330 #if 0 // Explorer issues with common controls? Someone does not know how CS_SAVEBITS works.
2331 // Breaks startup and shutdown active window...
2332 if ((Wnd
->style
& (WS_POPUP
|WS_CHILD
)) != WS_CHILD
&&
2333 Wnd
->pcls
->style
& CS_SAVEBITS
&&
2334 ((Cmd
== SW_SHOW
) || (Cmd
== SW_NORMAL
)))
2336 ERR("WinPosShowWindow Set active\n");
2337 UserSetActiveWindow(Wnd
);
2338 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2342 if (IsChildVisible(Wnd
) || Swp
& SWP_STATECHANGED
)
2344 TRACE("Child is Vis %s or State changed %s. ShowFlag %s\n",
2345 (IsChildVisible(Wnd
) ? "TRUE" : "FALSE"), (Swp
& SWP_STATECHANGED
? "TRUE" : "FALSE"),
2346 (ShowFlag
? "TRUE" : "FALSE"));
2347 co_WinPosSetWindowPos( Wnd
,
2348 0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
) ? HWND_TOPMOST
: HWND_TOP
,
2351 NewPos
.right
, //NewPos.right - NewPos.left,
2352 NewPos
.bottom
, //NewPos.bottom - NewPos.top,
2357 TRACE("Parent Vis?\n");
2358 /* if parent is not visible simply toggle WS_VISIBLE and return */
2359 if (ShowFlag
) IntSetStyle( Wnd
, WS_VISIBLE
, 0 );
2360 else IntSetStyle( Wnd
, 0, WS_VISIBLE
);
2363 if ( EventMsg
) IntNotifyWinEvent(EventMsg
, Wnd
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
2365 if ( ShowOwned
) IntShowOwnedPopups(Wnd
, TRUE
);
2367 if ((Cmd
== SW_HIDE
) || (Cmd
== SW_MINIMIZE
))
2369 if ( Wnd
== pti
->MessageQueue
->spwndActive
&& pti
->MessageQueue
== IntGetFocusMessageQueue() )
2371 if ( Wnd
->spwndParent
== UserGetDesktopWindow())
2373 if(!ActivateOtherWindowMin(Wnd
))
2374 co_WinPosActivateOtherWindow(Wnd
);
2377 co_WinPosActivateOtherWindow(Wnd
);
2380 /* Revert focus to parent */
2381 if (Wnd
== pti
->MessageQueue
->spwndFocus
)
2383 Parent
= Wnd
->spwndParent
;
2384 if (Wnd
->spwndParent
== UserGetDesktopWindow()) Parent
= 0;
2385 co_UserSetFocus(Parent
);
2389 /* FIXME: Check for window destruction. */
2391 if ((Wnd
->state
& WNDS_SENDSIZEMOVEMSGS
) &&
2392 !(Wnd
->state2
& WNDS2_INDESTROY
))
2394 co_WinPosSendSizeMove(Wnd
);
2397 /* if previous state was minimized Windows sets focus to the window */
2398 if (style
& WS_MINIMIZE
)
2400 co_UserSetFocus(Wnd
);
2401 // Fix wine Win test_SetFocus todo #3,
2402 if (!(style
& WS_CHILD
)) co_IntSendMessageNoWait(UserHMGetHandle(Wnd
), WM_ACTIVATE
, WA_ACTIVE
, 0);
2404 //ERR("co_WinPosShowWindow EXIT\n");
2410 co_WinPosSearchChildren(
2420 if (!(ScopeWin
->style
& WS_VISIBLE
))
2425 if (!Ignore
&& (ScopeWin
->style
& WS_DISABLED
))
2430 if (!IntPtInWindow(ScopeWin
, Point
->x
, Point
->y
))
2435 UserReferenceObject(ScopeWin
);
2437 if ( RECTL_bPointInRect(&ScopeWin
->rcClient
, Point
->x
, Point
->y
) )
2439 List
= IntWinListChildren(ScopeWin
);
2442 for (phWnd
= List
; *phWnd
; ++phWnd
)
2444 if (!(pwndChild
= ValidateHwndNoErr(*phWnd
)))
2449 pwndChild
= co_WinPosSearchChildren(pwndChild
, Point
, HitTest
, Ignore
);
2451 if(pwndChild
!= NULL
)
2453 /* We found a window. Don't send any more WM_NCHITTEST messages */
2454 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2455 UserDereferenceObject(ScopeWin
);
2459 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2463 if (ScopeWin
->head
.pti
== PsGetCurrentThreadWin32Thread())
2465 *HitTest
= (USHORT
)co_IntSendMessage(ScopeWin
->head
.h
, WM_NCHITTEST
, 0,
2466 MAKELONG(Point
->x
, Point
->y
));
2467 if ((*HitTest
) == (USHORT
)HTTRANSPARENT
)
2469 UserDereferenceObject(ScopeWin
);
2474 *HitTest
= HTCLIENT
;
2480 co_WinPosWindowFromPoint(PWND ScopeWin
, POINT
*WinPoint
, USHORT
* HitTest
, BOOL Ignore
)
2483 POINT Point
= *WinPoint
;
2484 USER_REFERENCE_ENTRY Ref
;
2486 if( ScopeWin
== NULL
)
2488 ScopeWin
= UserGetDesktopWindow();
2489 if(ScopeWin
== NULL
)
2493 *HitTest
= HTNOWHERE
;
2495 ASSERT_REFS_CO(ScopeWin
);
2496 UserRefObjectCo(ScopeWin
, &Ref
);
2498 Window
= co_WinPosSearchChildren(ScopeWin
, &Point
, HitTest
, Ignore
);
2500 UserDerefObjectCo(ScopeWin
);
2502 ASSERT_REFS_CO(Window
);
2503 ASSERT_REFS_CO(ScopeWin
);
2509 IntRealChildWindowFromPoint(PWND Parent
, LONG x
, LONG y
)
2513 PWND pwndHit
= NULL
;
2518 if (Parent
!= UserGetDesktopWindow())
2520 Pt
.x
+= Parent
->rcClient
.left
;
2521 Pt
.y
+= Parent
->rcClient
.top
;
2524 if (!IntPtInWindow(Parent
, Pt
.x
, Pt
.y
)) return NULL
;
2526 if ((List
= IntWinListChildren(Parent
)))
2528 for (phWnd
= List
; *phWnd
; phWnd
++)
2531 if ((Child
= ValidateHwndNoErr(*phWnd
)))
2533 if ( Child
->style
& WS_VISIBLE
&& IntPtInWindow(Child
, Pt
.x
, Pt
.y
) )
2535 if ( Child
->pcls
->atomClassName
!= gpsi
->atomSysClass
[ICLS_BUTTON
] ||
2536 (Child
->style
& BS_TYPEMASK
) != BS_GROUPBOX
)
2538 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2545 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2547 return pwndHit
? pwndHit
: Parent
;
2551 IntChildWindowFromPointEx(PWND Parent
, LONG x
, LONG y
, UINT uiFlags
)
2555 PWND pwndHit
= NULL
;
2560 if (Parent
!= UserGetDesktopWindow())
2562 if (Parent
->ExStyle
& WS_EX_LAYOUTRTL
)
2563 Pt
.x
= Parent
->rcClient
.right
- Pt
.x
;
2565 Pt
.x
+= Parent
->rcClient
.left
;
2566 Pt
.y
+= Parent
->rcClient
.top
;
2569 if (!IntPtInWindow(Parent
, Pt
.x
, Pt
.y
)) return NULL
;
2571 if ((List
= IntWinListChildren(Parent
)))
2573 for (phWnd
= List
; *phWnd
; phWnd
++)
2576 if ((Child
= ValidateHwndNoErr(*phWnd
)))
2578 if (uiFlags
& (CWP_SKIPINVISIBLE
|CWP_SKIPDISABLED
))
2580 if (!(Child
->style
& WS_VISIBLE
) && (uiFlags
& CWP_SKIPINVISIBLE
)) continue;
2581 if ((Child
->style
& WS_DISABLED
) && (uiFlags
& CWP_SKIPDISABLED
)) continue;
2584 if (uiFlags
& CWP_SKIPTRANSPARENT
)
2586 if (Child
->ExStyle
& WS_EX_TRANSPARENT
) continue;
2589 if (IntPtInWindow(Child
, Pt
.x
, Pt
.y
))
2596 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2598 return pwndHit
? pwndHit
: Parent
;
2603 IntDeferWindowPos( HDWP hdwp
,
2614 HDWP retvalue
= hdwp
;
2616 TRACE("hdwp %p, hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
2617 hdwp
, hwnd
, hwndAfter
, x
, y
, cx
, cy
, flags
);
2619 if (flags
& ~(SWP_NOSIZE
| SWP_NOMOVE
|
2620 SWP_NOZORDER
| SWP_NOREDRAW
|
2621 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
2622 SWP_NOOWNERZORDER
|SWP_SHOWWINDOW
|
2623 SWP_HIDEWINDOW
| SWP_FRAMECHANGED
))
2625 EngSetLastError(ERROR_INVALID_PARAMETER
);
2629 if (!(pDWP
= (PSMWP
)UserGetObject(gHandleTable
, hdwp
, TYPE_SETWINDOWPOS
)))
2631 EngSetLastError(ERROR_INVALID_DWP_HANDLE
);
2635 for (i
= 0; i
< pDWP
->ccvr
; i
++)
2637 if (pDWP
->acvr
[i
].pos
.hwnd
== hwnd
)
2639 /* Merge with the other changes */
2640 if (!(flags
& SWP_NOZORDER
))
2642 pDWP
->acvr
[i
].pos
.hwndInsertAfter
= hwndAfter
;
2644 if (!(flags
& SWP_NOMOVE
))
2646 pDWP
->acvr
[i
].pos
.x
= x
;
2647 pDWP
->acvr
[i
].pos
.y
= y
;
2649 if (!(flags
& SWP_NOSIZE
))
2651 pDWP
->acvr
[i
].pos
.cx
= cx
;
2652 pDWP
->acvr
[i
].pos
.cy
= cy
;
2654 pDWP
->acvr
[i
].pos
.flags
&= flags
| ~(SWP_NOSIZE
| SWP_NOMOVE
|
2655 SWP_NOZORDER
| SWP_NOREDRAW
|
2656 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
2658 pDWP
->acvr
[i
].pos
.flags
|= flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
|
2663 if (pDWP
->ccvr
>= pDWP
->ccvrAlloc
)
2665 PCVR newpos
= ExAllocatePoolWithTag(PagedPool
, pDWP
->ccvrAlloc
* 2 * sizeof(CVR
), USERTAG_SWP
);
2671 RtlZeroMemory(newpos
, pDWP
->ccvrAlloc
* 2 * sizeof(CVR
));
2672 RtlCopyMemory(newpos
, pDWP
->acvr
, pDWP
->ccvrAlloc
* sizeof(CVR
));
2673 ExFreePoolWithTag(pDWP
->acvr
, USERTAG_SWP
);
2674 pDWP
->ccvrAlloc
*= 2;
2675 pDWP
->acvr
= newpos
;
2677 pDWP
->acvr
[pDWP
->ccvr
].pos
.hwnd
= hwnd
;
2678 pDWP
->acvr
[pDWP
->ccvr
].pos
.hwndInsertAfter
= hwndAfter
;
2679 pDWP
->acvr
[pDWP
->ccvr
].pos
.x
= x
;
2680 pDWP
->acvr
[pDWP
->ccvr
].pos
.y
= y
;
2681 pDWP
->acvr
[pDWP
->ccvr
].pos
.cx
= cx
;
2682 pDWP
->acvr
[pDWP
->ccvr
].pos
.cy
= cy
;
2683 pDWP
->acvr
[pDWP
->ccvr
].pos
.flags
= flags
;
2684 pDWP
->acvr
[pDWP
->ccvr
].hrgnClip
= NULL
;
2685 pDWP
->acvr
[pDWP
->ccvr
].hrgnInterMonitor
= NULL
;
2691 BOOL FASTCALL
IntEndDeferWindowPosEx( HDWP hdwp
, BOOL sAsync
)
2698 TRACE("%p\n", hdwp
);
2700 if (!(pDWP
= (PSMWP
)UserGetObject(gHandleTable
, hdwp
, TYPE_SETWINDOWPOS
)))
2702 EngSetLastError(ERROR_INVALID_DWP_HANDLE
);
2706 for (i
= 0, winpos
= pDWP
->acvr
; res
&& i
< pDWP
->ccvr
; i
++, winpos
++)
2709 USER_REFERENCE_ENTRY Ref
;
2711 TRACE("hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
2712 winpos
->pos
.hwnd
, winpos
->pos
.hwndInsertAfter
, winpos
->pos
.x
, winpos
->pos
.y
,
2713 winpos
->pos
.cx
, winpos
->pos
.cy
, winpos
->pos
.flags
);
2715 pwnd
= ValidateHwndNoErr(winpos
->pos
.hwnd
);
2719 UserRefObjectCo(pwnd
, &Ref
);
2724 PWINDOWPOS ppos
= ExAllocatePoolWithTag(PagedPool
, sizeof(WINDOWPOS
), USERTAG_SWP
);
2727 *ppos
= winpos
->pos
;
2728 /* Yes it's a pointer inside Win32k! */
2729 lRes
= co_IntSendMessageNoWait( winpos
->pos
.hwnd
, WM_ASYNC_SETWINDOWPOS
, 0, (LPARAM
)ppos
);
2730 /* We handle this the same way as Event Hooks and Hooks. */
2733 ExFreePoolWithTag(ppos
, USERTAG_SWP
);
2738 res
= co_WinPosSetWindowPos( pwnd
,
2739 winpos
->pos
.hwndInsertAfter
,
2746 // Hack to pass tests.... Must have some work to do so clear the error.
2747 if (res
&& (winpos
->pos
.flags
& (SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOZORDER
)) == SWP_NOZORDER
)
2748 EngSetLastError(ERROR_SUCCESS
);
2750 UserDerefObjectCo(pwnd
);
2752 ExFreePoolWithTag(pDWP
->acvr
, USERTAG_SWP
);
2753 UserDereferenceObject(pDWP
);
2754 UserDeleteObject(hdwp
, TYPE_SETWINDOWPOS
);
2762 NtUserChildWindowFromPointEx(HWND hwndParent
,
2768 TRACE("Enter NtUserChildWindowFromPointEx\n");
2769 UserEnterExclusive();
2770 if ((pwndParent
= UserGetWindowObject(hwndParent
)))
2772 pwndParent
= IntChildWindowFromPointEx(pwndParent
, x
, y
, uiFlags
);
2775 TRACE("Leave NtUserChildWindowFromPointEx\n");
2776 return pwndParent
? UserHMGetHandle(pwndParent
) : NULL
;
2783 NtUserEndDeferWindowPosEx(HDWP WinPosInfo
,
2787 TRACE("Enter NtUserEndDeferWindowPosEx\n");
2788 UserEnterExclusive();
2789 Ret
= IntEndDeferWindowPosEx(WinPosInfo
, (BOOL
)Unknown1
);
2790 TRACE("Leave NtUserEndDeferWindowPosEx, ret=%i\n", Ret
);
2799 NtUserDeferWindowPos(HDWP WinPosInfo
,
2801 HWND WndInsertAfter
,
2810 UINT Tmp
= ~(SWP_ASYNCWINDOWPOS
|SWP_DEFERERASE
|SWP_NOSENDCHANGING
|SWP_NOREPOSITION
|
2811 SWP_NOCOPYBITS
|SWP_HIDEWINDOW
|SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|
2812 SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_NOZORDER
|SWP_NOMOVE
|SWP_NOSIZE
);
2814 TRACE("Enter NtUserDeferWindowPos\n");
2815 UserEnterExclusive();
2819 EngSetLastError(ERROR_INVALID_FLAGS
);
2823 pWnd
= UserGetWindowObject(Wnd
);
2824 if ( !pWnd
|| // FIXME:
2825 pWnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
2826 pWnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
2831 if ( WndInsertAfter
&&
2832 WndInsertAfter
!= HWND_BOTTOM
&&
2833 WndInsertAfter
!= HWND_TOPMOST
&&
2834 WndInsertAfter
!= HWND_NOTOPMOST
)
2836 pWndIA
= UserGetWindowObject(WndInsertAfter
);
2838 pWndIA
== UserGetDesktopWindow() ||
2839 pWndIA
== UserGetMessageWindow() )
2845 Ret
= IntDeferWindowPos(WinPosInfo
, Wnd
, WndInsertAfter
, x
, y
, cx
, cy
, Flags
);
2848 TRACE("Leave NtUserDeferWindowPos, ret=%p\n", Ret
);
2857 NtUserGetInternalWindowPos( HWND hWnd
,
2864 WINDOWPLACEMENT wndpl
;
2868 if (!(Window
= UserGetWindowObject(hWnd
)))
2878 ProbeForWrite(rectWnd
,
2884 ProbeForWrite(ptIcon
,
2890 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2892 SetLastNtError(_SEH2_GetExceptionCode());
2897 wndpl
.length
= sizeof(WINDOWPLACEMENT
);
2899 if (IntGetWindowPlacement(Window
, &wndpl
) && !Hit
)
2905 RtlCopyMemory(rectWnd
, &wndpl
.rcNormalPosition
, sizeof(RECT
));
2909 RtlCopyMemory(ptIcon
, &wndpl
.ptMinPosition
, sizeof(POINT
));
2913 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2915 SetLastNtError(_SEH2_GetExceptionCode());
2920 if (!Hit
) Ret
= wndpl
.showCmd
;
2931 NtUserGetWindowPlacement(HWND hWnd
,
2932 WINDOWPLACEMENT
*lpwndpl
)
2935 WINDOWPLACEMENT Safepl
;
2937 DECLARE_RETURN(BOOL
);
2939 TRACE("Enter NtUserGetWindowPlacement\n");
2942 if (!(Wnd
= UserGetWindowObject(hWnd
)))
2947 Status
= MmCopyFromCaller(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
2948 if(!NT_SUCCESS(Status
))
2950 SetLastNtError(Status
);
2953 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
2958 IntGetWindowPlacement(Wnd
, &Safepl
);
2960 Status
= MmCopyToCaller(lpwndpl
, &Safepl
, sizeof(WINDOWPLACEMENT
));
2961 if(!NT_SUCCESS(Status
))
2963 SetLastNtError(Status
);
2970 TRACE("Leave NtUserGetWindowPlacement, ret=%i\n",_ret_
);
2979 UINT cmd
, // Wine SW_ commands
2984 TRACE("Enter NtUserMinMaximize\n");
2985 UserEnterExclusive();
2987 pWnd
= UserGetWindowObject(hWnd
);
2988 if ( !pWnd
|| // FIXME:
2989 pWnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
2990 pWnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
2995 if ( cmd
> SW_MAX
|| pWnd
->state2
& WNDS2_INDESTROY
)
2997 EngSetLastError(ERROR_INVALID_PARAMETER
);
3001 cmd
|= Hide
? SW_HIDE
: 0;
3003 co_WinPosShowWindow(pWnd
, cmd
);
3006 TRACE("Leave NtUserMinMaximize\n");
3008 return 0; // Always NULL?
3023 return NtUserSetWindowPos(hWnd
, 0, X
, Y
, nWidth
, nHeight
,
3024 (bRepaint
? SWP_NOZORDER
| SWP_NOACTIVATE
:
3025 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
));
3032 NtUserRealChildWindowFromPoint(HWND Parent
,
3037 TRACE("Enter NtUserRealChildWindowFromPoint\n");
3039 if ((pwndParent
= UserGetWindowObject(Parent
)))
3041 pwndParent
= IntRealChildWindowFromPoint(pwndParent
, x
, y
);
3044 TRACE("Leave NtUserRealChildWindowFromPoint\n");
3045 return pwndParent
? UserHMGetHandle(pwndParent
) : NULL
;
3054 HWND hWndInsertAfter
,
3061 DECLARE_RETURN(BOOL
);
3062 PWND Window
, pWndIA
;
3064 USER_REFERENCE_ENTRY Ref
;
3066 TRACE("Enter NtUserSetWindowPos\n");
3067 UserEnterExclusive();
3069 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
3070 Window
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3071 Window
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3073 ERR("NtUserSetWindowPos bad window handle!\n");
3077 if ( hWndInsertAfter
&&
3078 hWndInsertAfter
!= HWND_BOTTOM
&&
3079 hWndInsertAfter
!= HWND_TOPMOST
&&
3080 hWndInsertAfter
!= HWND_NOTOPMOST
)
3082 if (!(pWndIA
= UserGetWindowObject(hWndInsertAfter
)) ||
3083 pWndIA
== UserGetDesktopWindow() ||
3084 pWndIA
== UserGetMessageWindow() )
3086 ERR("NtUserSetWindowPos bad insert window handle!\n");
3091 /* First make sure that coordinates are valid for WM_WINDOWPOSCHANGING */
3092 if (!(uFlags
& SWP_NOMOVE
))
3094 if (X
< -32768) X
= -32768;
3095 else if (X
> 32767) X
= 32767;
3096 if (Y
< -32768) Y
= -32768;
3097 else if (Y
> 32767) Y
= 32767;
3099 if (!(uFlags
& SWP_NOSIZE
))
3102 else if (cx
> 32767) cx
= 32767;
3104 else if (cy
> 32767) cy
= 32767;
3107 UserRefObjectCo(Window
, &Ref
);
3108 ret
= co_WinPosSetWindowPos(Window
, hWndInsertAfter
, X
, Y
, cx
, cy
, uFlags
);
3109 UserDerefObjectCo(Window
);
3114 TRACE("Leave NtUserSetWindowPos, ret=%i\n",_ret_
);
3128 HRGN hrgnCopy
= NULL
;
3130 INT flags
= (SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
);
3131 BOOLEAN Ret
= FALSE
;
3132 DECLARE_RETURN(INT
);
3134 TRACE("Enter NtUserSetWindowRgn\n");
3135 UserEnterExclusive();
3137 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
3138 Window
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3139 Window
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3144 if (hRgn
) // The region will be deleted in user32.
3146 if (GreIsHandleValid(hRgn
))
3148 hrgnCopy
= NtGdiCreateRectRgn(0, 0, 0, 0);
3149 /* The coordinates of a window's window region are relative to the
3150 upper-left corner of the window, not the client area of the window. */
3151 NtGdiCombineRgn( hrgnCopy
, hRgn
, 0, RGN_COPY
);
3157 if (Window
->hrgnClip
)
3159 /* Delete no longer needed region handle */
3160 IntGdiSetRegionOwner(Window
->hrgnClip
, GDI_OBJ_HMGR_POWNED
);
3161 GreDeleteObject(Window
->hrgnClip
);
3166 /* Set public ownership */
3167 IntGdiSetRegionOwner(hrgnCopy
, GDI_OBJ_HMGR_PUBLIC
);
3169 Window
->hrgnClip
= hrgnCopy
;
3171 Ret
= co_WinPosSetWindowPos(Window
, HWND_TOP
, 0, 0, 0, 0, bRedraw
? flags
: (flags
|SWP_NOREDRAW
) );
3176 TRACE("Leave NtUserSetWindowRgn, ret=%i\n",_ret_
);
3185 NtUserSetInternalWindowPos(
3191 WINDOWPLACEMENT wndpl
;
3196 DECLARE_RETURN(BOOL
);
3197 USER_REFERENCE_ENTRY Ref
;
3199 TRACE("Enter NtUserSetWindowPlacement\n");
3200 UserEnterExclusive();
3202 if (!(Wnd
= UserGetWindowObject(hwnd
)) || // FIXME:
3203 Wnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3204 Wnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3213 ProbeForRead(lppt
, sizeof(POINT
), 1);
3214 RtlCopyMemory(&pt
, lppt
, sizeof(POINT
));
3218 ProbeForRead(lprect
, sizeof(RECT
), 1);
3219 RtlCopyMemory(&rect
, lprect
, sizeof(RECT
));
3222 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3224 SetLastNtError(_SEH2_GetExceptionCode());
3225 _SEH2_YIELD(RETURN( FALSE
));
3229 wndpl
.length
= sizeof(wndpl
);
3230 wndpl
.showCmd
= showCmd
;
3231 wndpl
.flags
= flags
= 0;
3236 wndpl
.flags
|= WPF_SETMINPOSITION
;
3237 wndpl
.ptMinPosition
= pt
;
3241 flags
|= PLACE_RECT
;
3242 wndpl
.rcNormalPosition
= rect
;
3245 UserRefObjectCo(Wnd
, &Ref
);
3246 IntSetWindowPlacement(Wnd
, &wndpl
, flags
);
3247 UserDerefObjectCo(Wnd
);
3251 TRACE("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_
);
3260 NtUserSetWindowPlacement(HWND hWnd
,
3261 WINDOWPLACEMENT
*lpwndpl
)
3264 WINDOWPLACEMENT Safepl
;
3266 DECLARE_RETURN(BOOL
);
3267 USER_REFERENCE_ENTRY Ref
;
3269 TRACE("Enter NtUserSetWindowPlacement\n");
3270 UserEnterExclusive();
3272 if (!(Wnd
= UserGetWindowObject(hWnd
)) || // FIXME:
3273 Wnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3274 Wnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3281 ProbeForRead(lpwndpl
, sizeof(WINDOWPLACEMENT
), 1);
3282 RtlCopyMemory(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
3284 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3286 SetLastNtError(_SEH2_GetExceptionCode());
3287 _SEH2_YIELD(RETURN( FALSE
));
3291 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
3296 Flags
= PLACE_MAX
| PLACE_RECT
;
3297 if (Safepl
.flags
& WPF_SETMINPOSITION
) Flags
|= PLACE_MIN
;
3298 UserRefObjectCo(Wnd
, &Ref
);
3299 IntSetWindowPlacement(Wnd
, &Safepl
, Flags
);
3300 UserDerefObjectCo(Wnd
);
3304 TRACE("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_
);
3313 NtUserShowWindowAsync(HWND hWnd
, LONG nCmdShow
)
3317 DECLARE_RETURN(BOOL
);
3318 USER_REFERENCE_ENTRY Ref
;
3320 TRACE("Enter NtUserShowWindowAsync\n");
3321 UserEnterExclusive();
3323 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
3324 Window
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3325 Window
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3330 if ( nCmdShow
> SW_MAX
)
3332 EngSetLastError(ERROR_INVALID_PARAMETER
);
3336 UserRefObjectCo(Window
, &Ref
);
3337 ret
= co_IntSendMessageNoWait( hWnd
, WM_ASYNC_SHOWWINDOW
, nCmdShow
, 0 );
3338 UserDerefObjectCo(Window
);
3339 if (-1 == (int) ret
|| !ret
) ret
= FALSE
;
3344 TRACE("Leave NtUserShowWindowAsync, ret=%i\n",_ret_
);
3353 NtUserShowWindow(HWND hWnd
, LONG nCmdShow
)
3357 DECLARE_RETURN(BOOL
);
3358 USER_REFERENCE_ENTRY Ref
;
3360 TRACE("Enter NtUserShowWindow\n");
3361 UserEnterExclusive();
3363 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
3364 Window
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3365 Window
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3370 if ( nCmdShow
> SW_MAX
|| Window
->state2
& WNDS2_INDESTROY
)
3372 EngSetLastError(ERROR_INVALID_PARAMETER
);
3376 UserRefObjectCo(Window
, &Ref
);
3377 ret
= co_WinPosShowWindow(Window
, nCmdShow
);
3378 UserDerefObjectCo(Window
);
3383 TRACE("Leave NtUserShowWindow, ret=%i\n",_ret_
);
3393 NtUserWindowFromPoint(LONG X
, LONG Y
)
3397 PWND DesktopWindow
= NULL
, Window
= NULL
;
3399 DECLARE_RETURN(HWND
);
3400 USER_REFERENCE_ENTRY Ref
;
3402 TRACE("Enter NtUserWindowFromPoint\n");
3403 UserEnterExclusive();
3405 if ((DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow())))
3412 // Hmm... Threads live on desktops thus we have a reference on the desktop and indirectly the desktop window.
3413 // It is possible this referencing is useless, though it should not hurt...
3414 UserRefObjectCo(DesktopWindow
, &Ref
);
3416 //pti = PsGetCurrentThreadWin32Thread();
3417 Window
= co_WinPosWindowFromPoint(DesktopWindow
, &pt
, &hittest
, FALSE
);
3421 Ret
= UserHMGetHandle(Window
);
3430 if (Window
) UserDereferenceObject(Window
);
3431 if (DesktopWindow
) UserDerefObjectCo(DesktopWindow
);
3433 TRACE("Leave NtUserWindowFromPoint, ret=%p\n", _ret_
);