2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
5 * FILE: win32ss/user/ntuser/winpos.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_NOCLIENTSIZE | SWP_NOZORDER)
21 #define SWP_AGG_NOPOSCHANGE \
22 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE | SWP_NOZORDER)
23 #define SWP_AGG_STATUSFLAGS \
24 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
25 #define SWP_AGG_NOCLIENTCHANGE \
26 (SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
28 #define EMPTYPOINT(pt) ((pt).x == -1 && (pt).y == -1)
29 #define PLACE_MIN 0x0001
30 #define PLACE_MAX 0x0002
31 #define PLACE_RECT 0x0004
33 /* FUNCTIONS *****************************************************************/
36 /***********************************************************************
39 static void dump_winpos_flags(UINT flags
)
41 static const DWORD dumped_flags
= (SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOREDRAW
|
42 SWP_NOACTIVATE
| SWP_FRAMECHANGED
| SWP_SHOWWINDOW
|
43 SWP_HIDEWINDOW
| SWP_NOCOPYBITS
| SWP_NOOWNERZORDER
|
44 SWP_NOSENDCHANGING
| SWP_DEFERERASE
| SWP_ASYNCWINDOWPOS
|
45 SWP_NOCLIENTSIZE
| SWP_NOCLIENTMOVE
| SWP_STATECHANGED
);
47 if(flags
& SWP_NOSIZE
) TRACE(" SWP_NOSIZE");
48 if(flags
& SWP_NOMOVE
) TRACE(" SWP_NOMOVE");
49 if(flags
& SWP_NOZORDER
) TRACE(" SWP_NOZORDER");
50 if(flags
& SWP_NOREDRAW
) TRACE(" SWP_NOREDRAW");
51 if(flags
& SWP_NOACTIVATE
) TRACE(" SWP_NOACTIVATE");
52 if(flags
& SWP_FRAMECHANGED
) TRACE(" SWP_FRAMECHANGED");
53 if(flags
& SWP_SHOWWINDOW
) TRACE(" SWP_SHOWWINDOW");
54 if(flags
& SWP_HIDEWINDOW
) TRACE(" SWP_HIDEWINDOW");
55 if(flags
& SWP_NOCOPYBITS
) TRACE(" SWP_NOCOPYBITS");
56 if(flags
& SWP_NOOWNERZORDER
) TRACE(" SWP_NOOWNERZORDER");
57 if(flags
& SWP_NOSENDCHANGING
) TRACE(" SWP_NOSENDCHANGING");
58 if(flags
& SWP_DEFERERASE
) TRACE(" SWP_DEFERERASE");
59 if(flags
& SWP_ASYNCWINDOWPOS
) TRACE(" SWP_ASYNCWINDOWPOS");
60 if(flags
& SWP_NOCLIENTSIZE
) TRACE(" SWP_NOCLIENTSIZE");
61 if(flags
& SWP_NOCLIENTMOVE
) TRACE(" SWP_NOCLIENTMOVE");
62 if(flags
& SWP_STATECHANGED
) TRACE(" SWP_STATECHANGED");
64 if(flags
& ~dumped_flags
) TRACE(" %08x", flags
& ~dumped_flags
);
70 IntGetClientOrigin(PWND Window OPTIONAL
, LPPOINT Point
)
72 Window
= Window
? Window
: UserGetDesktopWindow();
75 Point
->x
= Point
->y
= 0;
78 Point
->x
= Window
->rcClient
.left
;
79 Point
->y
= Window
->rcClient
.top
;
86 * Returns client window rectangle relative to the upper-left corner of client area.
88 * \note Does not check the validity of the parameters
91 IntGetClientRect(PWND Wnd
, RECTL
*Rect
)
95 if (Wnd
->style
& WS_MINIMIZED
)
97 Rect
->left
= Rect
->top
= 0;
98 Rect
->right
= UserGetSystemMetrics(SM_CXMINIMIZED
);
99 Rect
->bottom
= UserGetSystemMetrics(SM_CYMINIMIZED
);
102 if (!UserIsDesktopWindow(Wnd
))
104 *Rect
= Wnd
->rcClient
;
105 RECTL_vOffsetRect(Rect
, -Wnd
->rcClient
.left
, -Wnd
->rcClient
.top
);
109 Rect
->left
= Rect
->top
= 0;
110 Rect
->right
= Wnd
->rcClient
.right
;
111 Rect
->bottom
= Wnd
->rcClient
.bottom
;
112 /* Do this until Init bug is fixed. This sets 640x480, see InitMetrics.
113 Rect->right = UserGetSystemMetrics(SM_CXSCREEN);
114 Rect->bottom = UserGetSystemMetrics(SM_CYSCREEN);
120 IntGetWindowRect(PWND Wnd
, RECTL
*Rect
)
124 if (!Wnd
) return FALSE
;
125 if (!UserIsDesktopWindow(Wnd
))
127 *Rect
= Wnd
->rcWindow
;
131 Rect
->left
= Rect
->top
= 0;
132 Rect
->right
= Wnd
->rcWindow
.right
;
133 Rect
->bottom
= Wnd
->rcWindow
.bottom
;
134 /* Do this until Init bug is fixed. This sets 640x480, see InitMetrics.
135 Rect->right = GetSystemMetrics(SM_CXSCREEN);
136 Rect->bottom = GetSystemMetrics(SM_CYSCREEN);
143 IntMapWindowPoints(PWND FromWnd
, PWND ToWnd
, LPPOINT lpPoints
, UINT cPoints
)
145 BOOL mirror_from
, mirror_to
;
150 /* Note: Desktop Top and Left is always 0! */
151 Delta
.x
= Delta
.y
= 0;
152 mirror_from
= mirror_to
= FALSE
;
154 if (FromWnd
&& !UserIsDesktopWindow(FromWnd
))
156 if (FromWnd
->ExStyle
& WS_EX_LAYOUTRTL
)
160 Delta
.x
= -FromWnd
->rcClient
.right
;
163 Delta
.x
= FromWnd
->rcClient
.left
;
164 Delta
.y
= FromWnd
->rcClient
.top
;
167 if (ToWnd
&& !UserIsDesktopWindow(ToWnd
))
169 if (ToWnd
->ExStyle
& WS_EX_LAYOUTRTL
)
173 Delta
.x
+= Change
* ToWnd
->rcClient
.right
;
176 Delta
.x
-= Change
* ToWnd
->rcClient
.left
;
177 Delta
.y
-= ToWnd
->rcClient
.top
;
180 for (i
= 0; i
!= cPoints
; i
++)
182 lpPoints
[i
].x
+= Delta
.x
;
183 lpPoints
[i
].x
*= Change
;
184 lpPoints
[i
].y
+= Delta
.y
;
187 if ((mirror_from
|| mirror_to
) && cPoints
== 2) /* special case for rectangle */
189 int tmp
= min(lpPoints
[0].x
, lpPoints
[1].x
);
190 lpPoints
[1].x
= max(lpPoints
[0].x
, lpPoints
[1].x
);
194 return MAKELONG(LOWORD(Delta
.x
), LOWORD(Delta
.y
));
198 IntClientToScreen(PWND Wnd
, LPPOINT lpPoint
)
200 if (Wnd
&& Wnd
->fnid
!= FNID_DESKTOP
)
202 if (Wnd
->ExStyle
& WS_EX_LAYOUTRTL
)
203 lpPoint
->x
= Wnd
->rcClient
.right
- lpPoint
->x
;
205 lpPoint
->x
+= Wnd
->rcClient
.left
;
206 lpPoint
->y
+= Wnd
->rcClient
.top
;
212 IntScreenToClient(PWND Wnd
, LPPOINT lpPoint
)
214 if (Wnd
&& Wnd
->fnid
!= FNID_DESKTOP
)
216 if (Wnd
->ExStyle
& WS_EX_LAYOUTRTL
)
217 lpPoint
->x
= Wnd
->rcClient
.right
- lpPoint
->x
;
219 lpPoint
->x
-= Wnd
->rcClient
.left
;
220 lpPoint
->y
-= Wnd
->rcClient
.top
;
225 BOOL FASTCALL
IsChildVisible(PWND pWnd
)
229 if ( (pWnd
->style
& (WS_POPUP
|WS_CHILD
)) != WS_CHILD
||
230 !(pWnd
= pWnd
->spwndParent
) )
233 while (pWnd
->style
& WS_VISIBLE
);
237 PWND FASTCALL
IntGetLastTopMostWindow(VOID
)
240 PDESKTOP rpdesk
= gptiCurrent
->rpdesk
;
243 (pWnd
= rpdesk
->pDeskInfo
->spwnd
->spwndChild
) &&
244 pWnd
->ExStyle
& WS_EX_TOPMOST
)
248 if (!pWnd
->spwndNext
) break;
249 if (!(pWnd
->spwndNext
->ExStyle
& WS_EX_TOPMOST
)) break;
250 pWnd
= pWnd
->spwndNext
;
258 SelectWindowRgn(PWND Window
, HRGN hRgnClip
)
260 if (Window
->hrgnClip
)
262 /* Delete no longer needed region handle */
263 IntGdiSetRegionOwner(Window
->hrgnClip
, GDI_OBJ_HMGR_POWNED
);
264 GreDeleteObject(Window
->hrgnClip
);
265 Window
->hrgnClip
= NULL
;
268 if (hRgnClip
> HRGN_WINDOW
)
270 /*if (!UserIsDesktopWindow(Window))
272 NtGdiOffsetRgn(hRgnClip, Window->rcWindow.left, Window->rcWindow.top);
274 /* Set public ownership */
275 IntGdiSetRegionOwner(hRgnClip
, GDI_OBJ_HMGR_PUBLIC
);
277 Window
->hrgnClip
= hRgnClip
;
282 // This helps with CORE-6129 forcing modal dialog active when another app is minimized or closed.
284 BOOL FASTCALL
ActivateOtherWindowMin(PWND Wnd
)
286 BOOL ActivePrev
, FindTopWnd
;
287 PWND pWndTopMost
, pWndChild
, pWndSetActive
, pWndTemp
, pWndDesk
;
288 USER_REFERENCE_ENTRY Ref
;
289 PTHREADINFO pti
= gptiCurrent
;
291 //ERR("AOWM 1 %p\n",Wnd->head.h);
292 ActivePrev
= (pti
->MessageQueue
->spwndActivePrev
!= NULL
);
295 if ((pWndTopMost
= IntGetLastTopMostWindow()))
296 pWndChild
= pWndTopMost
->spwndNext
;
298 pWndChild
= Wnd
->spwndParent
->spwndChild
;
303 pWndSetActive
= pti
->MessageQueue
->spwndActivePrev
;
305 pWndSetActive
= pWndChild
;
311 if ( VerifyWnd(pWndSetActive
) &&
312 !(pWndSetActive
->ExStyle
& WS_EX_NOACTIVATE
) &&
313 (pWndSetActive
->style
& (WS_VISIBLE
|WS_DISABLED
)) == WS_VISIBLE
&&
314 (!(pWndSetActive
->style
& WS_ICONIC
) /* FIXME MinMax pos? */ ) )
316 if (!(pWndSetActive
->ExStyle
& WS_EX_TOOLWINDOW
) )
318 UserRefObjectCo(pWndSetActive
, &Ref
);
319 //ERR("ActivateOtherWindowMin Set FG 1\n");
320 co_IntSetForegroundWindow(pWndSetActive
);
321 UserDerefObjectCo(pWndSetActive
);
322 //ERR("AOWM 2 Exit Good %p\n",pWndSetActive->head.h);
325 if (!pWndTemp
) pWndTemp
= pWndSetActive
;
330 pWndSetActive
= pWndChild
;
333 pWndSetActive
= pWndSetActive
->spwndNext
;
336 if ( !FindTopWnd
) break;
341 pWndChild
= pWndChild
->spwndParent
->spwndChild
;
345 if (!(pWndDesk
= IntGetThreadDesktopWindow(pti
)))
350 pWndChild
= pWndDesk
->spwndChild
;
353 if ((pWndSetActive
= pWndTemp
))
355 UserRefObjectCo(pWndSetActive
, &Ref
);
356 //ERR("ActivateOtherWindowMin Set FG 2\n");
357 co_IntSetForegroundWindow(pWndSetActive
);
358 UserDerefObjectCo(pWndSetActive
);
359 //ERR("AOWM 3 Exit Good %p\n",pWndSetActive->head.h);
362 //ERR("AOWM 4 Bad\n");
366 /*******************************************************************
367 * can_activate_window
369 * Check if we can activate the specified window.
372 BOOL FASTCALL
can_activate_window( PWND Wnd OPTIONAL
)
376 if (!Wnd
) return FALSE
;
379 if (!(style
& WS_VISIBLE
)) return FALSE
;
380 if (style
& WS_MINIMIZE
) return FALSE
;
381 if ((style
& (WS_POPUP
|WS_CHILD
)) == WS_CHILD
) return FALSE
;
383 /* FIXME: This window could be disable because the child that closed
385 //return !(style & WS_DISABLED);
389 /*******************************************************************
390 * WinPosActivateOtherWindow
392 * Activates window other than pWnd.
395 co_WinPosActivateOtherWindow(PWND Wnd
)
398 USER_REFERENCE_ENTRY Ref
;
402 if (IntIsDesktopWindow(Wnd
))
404 //ERR("WinPosActivateOtherWindow Set Focus Msg Q No window!\n");
405 IntSetFocusMessageQueue(NULL
);
409 /* If this is popup window, try to activate the owner first. */
410 if ((Wnd
->style
& WS_POPUP
) && (WndTo
= Wnd
->spwndOwner
))
412 TRACE("WPAOW Popup with Owner\n");
413 WndTo
= UserGetAncestor( WndTo
, GA_ROOT
);
414 if (can_activate_window(WndTo
)) goto done
;
417 /* Pick a next top-level window. */
418 /* FIXME: Search for non-tooltip windows first. */
422 if (!(WndTo
= WndTo
->spwndNext
)) break;
423 if (can_activate_window( WndTo
)) goto done
;
427 Fixes wine win.c:test_SetParent last ShowWindow test after popup dies.
428 Check for previous active window to bring to top.
432 WndTo
= Wnd
->head
.pti
->MessageQueue
->spwndActivePrev
;
433 if (can_activate_window( WndTo
)) goto done
;
436 // Find any window to bring to top. Works Okay for wine since it does not see X11 windows.
437 WndTo
= UserGetDesktopWindow();
438 WndTo
= WndTo
->spwndChild
;
441 //ERR("WinPosActivateOtherWindow No window!\n");
451 if (can_activate_window( WndTo
)) goto done
;
452 if (!(WndTo
= WndTo
->spwndNext
)) break;
456 if (WndTo
) UserRefObjectCo(WndTo
, &Ref
);
458 if (gpqForeground
&& (!gpqForeground
->spwndActive
|| Wnd
== gpqForeground
->spwndActive
))
460 /* ReactOS can pass WndTo = NULL to co_IntSetForegroundWindow and returns FALSE. */
461 //ERR("WinPosActivateOtherWindow Set FG 0x%p hWnd %p\n",WndTo, WndTo ? WndTo->head.h : 0);
462 if (co_IntSetForegroundWindow(WndTo
))
464 if (WndTo
) UserDerefObjectCo(WndTo
);
468 //ERR("WinPosActivateOtherWindow Set Active 0x%p\n",WndTo);
469 if (!UserSetActiveWindow(WndTo
)) /* Ok for WndTo to be NULL here */
471 //ERR("WPAOW SA 1\n");
472 UserSetActiveWindow(NULL
);
474 if (WndTo
) UserDerefObjectCo(WndTo
);
478 WinPosInitInternalPos(PWND Wnd
, RECTL
*RestoreRect
)
481 RECTL Rect
= *RestoreRect
;
483 if (Wnd
->spwndParent
&& !UserIsDesktopWindow(Wnd
->spwndParent
))
485 RECTL_vOffsetRect(&Rect
,
486 -Wnd
->spwndParent
->rcClient
.left
,
487 -Wnd
->spwndParent
->rcClient
.top
);
493 if (!Wnd
->InternalPosInitialized
)
495 // FIXME: Use check point Atom..
496 Wnd
->InternalPos
.flags
= 0;
497 Wnd
->InternalPos
.MaxPos
.x
= Wnd
->InternalPos
.MaxPos
.y
= -1;
498 Wnd
->InternalPos
.IconPos
.x
= Wnd
->InternalPos
.IconPos
.y
= -1;
499 Wnd
->InternalPos
.NormalRect
= Rect
;
500 Wnd
->InternalPosInitialized
= TRUE
;
503 if (Wnd
->style
& WS_MINIMIZE
)
505 Wnd
->InternalPos
.IconPos
= Size
;
506 Wnd
->InternalPos
.flags
|= WPF_MININIT
;
508 else if (Wnd
->style
& WS_MAXIMIZE
)
510 Wnd
->InternalPos
.flags
|= WPF_MAXINIT
;
512 if ( Wnd
->spwndParent
== Wnd
->head
.rpdesk
->pDeskInfo
->spwnd
)
514 if (Wnd
->state
& WNDS_MAXIMIZESTOMONITOR
)
516 Wnd
->InternalPos
.flags
&= ~WPF_MAXINIT
;
517 Wnd
->InternalPos
.MaxPos
.x
= Wnd
->InternalPos
.MaxPos
.y
= -1;
522 PMONITOR pmonitor
= UserMonitorFromRect(&Rect
, MONITOR_DEFAULTTOPRIMARY
);
523 // FIXME: support DPI aware, rcWorkDPI/Real etc..
524 WorkArea
= pmonitor
->rcMonitor
;
526 if (Wnd
->style
& WS_MAXIMIZEBOX
)
527 { // Support (Wnd->state & WNDS_HASCAPTION) || pmonitor->cFullScreen too.
528 if ((Wnd
->style
& WS_CAPTION
) == WS_CAPTION
|| !(Wnd
->style
& (WS_CHILD
| WS_POPUP
)))
530 WorkArea
= pmonitor
->rcWork
;
535 Wnd
->InternalPos
.MaxPos
.x
= Rect
.left
- WorkArea
.left
;
536 Wnd
->InternalPos
.MaxPos
.y
= Rect
.top
- WorkArea
.top
;
538 /*ERR("WinPosIP 2 X %d = R.l %d - W.l %d | Y %d = R.t %d - W.t %d\n",
539 Wnd->InternalPos.MaxPos.x,
540 Rect.left, WorkArea.left,
541 Wnd->InternalPos.MaxPos.y,
542 Rect.top, WorkArea.top);*/
546 Wnd
->InternalPos
.MaxPos
= Size
;
550 Wnd
->InternalPos
.NormalRect
= Rect
;
556 IntGetWindowPlacement(PWND Wnd
, WINDOWPLACEMENT
*lpwndpl
)
558 if (!Wnd
) return FALSE
;
560 if(lpwndpl
->length
!= sizeof(WINDOWPLACEMENT
))
567 WinPosInitInternalPos(Wnd
, &Wnd
->rcWindow
);
569 lpwndpl
->showCmd
= SW_HIDE
;
571 if ( Wnd
->style
& WS_MINIMIZE
)
572 lpwndpl
->showCmd
= SW_SHOWMINIMIZED
;
574 lpwndpl
->showCmd
= ( Wnd
->style
& WS_MAXIMIZE
) ? SW_SHOWMAXIMIZED
: SW_SHOWNORMAL
;
576 lpwndpl
->rcNormalPosition
= Wnd
->InternalPos
.NormalRect
;
578 if (Wnd
->InternalPos
.flags
& WPF_MININIT
) // Return if it was set!
580 lpwndpl
->ptMinPosition
.x
= Wnd
->InternalPos
.IconPos
.x
;
581 lpwndpl
->ptMinPosition
.y
= Wnd
->InternalPos
.IconPos
.y
;
584 lpwndpl
->ptMinPosition
.x
= lpwndpl
->ptMinPosition
.y
= -1;
586 if ( Wnd
->InternalPos
.flags
& WPF_MAXINIT
&& // Return if set and not maximized to monitor!
587 !(Wnd
->state
& WNDS_MAXIMIZESTOMONITOR
))
589 lpwndpl
->ptMaxPosition
.x
= Wnd
->InternalPos
.MaxPos
.x
;
590 lpwndpl
->ptMaxPosition
.y
= Wnd
->InternalPos
.MaxPos
.y
;
593 lpwndpl
->ptMaxPosition
.x
= lpwndpl
->ptMaxPosition
.y
= -1;
595 if ( Wnd
->spwndParent
== Wnd
->head
.rpdesk
->pDeskInfo
->spwnd
&&
596 !(Wnd
->ExStyle
& WS_EX_TOOLWINDOW
))
598 PMONITOR pmonitor
= UserMonitorFromRect(&lpwndpl
->rcNormalPosition
, MONITOR_DEFAULTTOPRIMARY
);
600 // FIXME: support DPI aware, rcWorkDPI/Real etc..
601 if (Wnd
->InternalPos
.flags
& WPF_MININIT
)
603 lpwndpl
->ptMinPosition
.x
-= (pmonitor
->rcWork
.left
- pmonitor
->rcMonitor
.left
);
604 lpwndpl
->ptMinPosition
.y
-= (pmonitor
->rcWork
.top
- pmonitor
->rcMonitor
.top
);
606 RECTL_vOffsetRect(&lpwndpl
->rcNormalPosition
,
607 pmonitor
->rcMonitor
.left
- pmonitor
->rcWork
.left
,
608 pmonitor
->rcMonitor
.top
- pmonitor
->rcWork
.top
);
611 if ( Wnd
->InternalPos
.flags
& WPF_RESTORETOMAXIMIZED
|| Wnd
->style
& WS_MAXIMIZE
)
612 lpwndpl
->flags
|= WPF_RESTORETOMAXIMIZED
;
614 if ( ((Wnd
->style
& (WS_CHILD
|WS_POPUP
)) == WS_CHILD
) && Wnd
->InternalPos
.flags
& WPF_SETMINPOSITION
)
615 lpwndpl
->flags
|= WPF_SETMINPOSITION
;
620 /* make sure the specified rect is visible on screen */
621 static void make_rect_onscreen( RECT
*rect
)
623 PMONITOR pmonitor
= UserMonitorFromRect( rect
, MONITOR_DEFAULTTONEAREST
); // Wine uses this.
625 // FIXME: support DPI aware, rcWorkDPI/Real etc..
626 if (!pmonitor
) return;
627 /* FIXME: map coordinates from rcWork to rcMonitor */
628 if (rect
->right
<= pmonitor
->rcWork
.left
)
630 rect
->right
+= pmonitor
->rcWork
.left
- rect
->left
;
631 rect
->left
= pmonitor
->rcWork
.left
;
633 else if (rect
->left
>= pmonitor
->rcWork
.right
)
635 rect
->left
+= pmonitor
->rcWork
.right
- rect
->right
;
636 rect
->right
= pmonitor
->rcWork
.right
;
638 if (rect
->bottom
<= pmonitor
->rcWork
.top
)
640 rect
->bottom
+= pmonitor
->rcWork
.top
- rect
->top
;
641 rect
->top
= pmonitor
->rcWork
.top
;
643 else if (rect
->top
>= pmonitor
->rcWork
.bottom
)
645 rect
->top
+= pmonitor
->rcWork
.bottom
- rect
->bottom
;
646 rect
->bottom
= pmonitor
->rcWork
.bottom
;
650 /* make sure the specified point is visible on screen */
651 static void make_point_onscreen( POINT
*pt
)
655 RECTL_vSetRect( &rect
, pt
->x
, pt
->y
, pt
->x
+ 1, pt
->y
+ 1 );
656 make_rect_onscreen( &rect
);
662 IntSetWindowPlacement(PWND Wnd
, WINDOWPLACEMENT
*wpl
, UINT Flags
)
667 if ( Flags
& PLACE_MIN
) make_point_onscreen( &wpl
->ptMinPosition
);
668 if ( Flags
& PLACE_MAX
) make_point_onscreen( &wpl
->ptMaxPosition
);
669 if ( Flags
& PLACE_RECT
) make_rect_onscreen( &wpl
->rcNormalPosition
);
671 if (!Wnd
|| Wnd
== Wnd
->head
.rpdesk
->pDeskInfo
->spwnd
) return FALSE
;
673 if ( Flags
& PLACE_MIN
) Wnd
->InternalPos
.IconPos
= wpl
->ptMinPosition
;
674 if ( Flags
& PLACE_MAX
) Wnd
->InternalPos
.MaxPos
= wpl
->ptMaxPosition
;
675 if ( Flags
& PLACE_RECT
) Wnd
->InternalPos
.NormalRect
= wpl
->rcNormalPosition
;
677 SWP_Flags
= SWP_NOZORDER
| SWP_NOACTIVATE
| ((wpl
->flags
& WPF_ASYNCWINDOWPLACEMENT
) ? SWP_ASYNCWINDOWPOS
: 0);
679 if (Wnd
->style
& WS_MINIMIZE
)
681 if (Flags
& PLACE_MIN
|| Wnd
->InternalPos
.flags
& WPF_SETMINPOSITION
)
683 co_WinPosSetWindowPos(Wnd
, HWND_TOP
,
684 wpl
->ptMinPosition
.x
, wpl
->ptMinPosition
.y
, 0, 0,
685 SWP_NOSIZE
| SWP_Flags
);
686 Wnd
->InternalPos
.flags
|= WPF_MININIT
;
689 else if (Wnd
->style
& WS_MAXIMIZE
)
691 if (Flags
& PLACE_MAX
)
693 co_WinPosSetWindowPos(Wnd
, HWND_TOP
,
694 wpl
->ptMaxPosition
.x
, wpl
->ptMaxPosition
.y
, 0, 0,
695 SWP_NOSIZE
| SWP_Flags
);
696 Wnd
->InternalPos
.flags
|= WPF_MAXINIT
;
699 else if (Flags
& PLACE_RECT
)
701 co_WinPosSetWindowPos(Wnd
, HWND_TOP
,
702 wpl
->rcNormalPosition
.left
, wpl
->rcNormalPosition
.top
,
703 wpl
->rcNormalPosition
.right
- wpl
->rcNormalPosition
.left
,
704 wpl
->rcNormalPosition
.bottom
- wpl
->rcNormalPosition
.top
,
708 sAsync
= (Wnd
->head
.pti
->MessageQueue
!= gptiCurrent
->MessageQueue
&& wpl
->flags
& WPF_ASYNCWINDOWPLACEMENT
);
711 co_IntSendMessageNoWait( UserHMGetHandle(Wnd
), WM_ASYNC_SHOWWINDOW
, wpl
->showCmd
, 0 );
713 co_WinPosShowWindow(Wnd
, wpl
->showCmd
);
715 if ( Wnd
->style
& WS_MINIMIZE
&& !sAsync
)
717 if ( wpl
->flags
& WPF_SETMINPOSITION
)
718 Wnd
->InternalPos
.flags
|= WPF_SETMINPOSITION
;
720 if ( wpl
->flags
& WPF_RESTORETOMAXIMIZED
)
721 Wnd
->InternalPos
.flags
|= WPF_RESTORETOMAXIMIZED
;
728 co_WinPosArrangeIconicWindows(PWND parent
)
732 INT x
, y
, xspacing
, yspacing
, sx
, sy
;
734 ASSERT_REFS_CO(parent
);
736 IntGetClientRect( parent
, &rectParent
);
737 // FIXME: Support Minimize Metrics gspv.mm.iArrange.
738 // Default: ARW_BOTTOMLEFT
740 y
= rectParent
.bottom
;
742 xspacing
= UserGetSystemMetrics(SM_CXMINIMIZED
);
743 yspacing
= UserGetSystemMetrics(SM_CYMINIMIZED
);
745 Child
= parent
->spwndChild
;
748 if((Child
->style
& WS_MINIMIZE
) != 0 )
750 USER_REFERENCE_ENTRY Ref
;
751 UserRefObjectCo(Child
, &Ref
);
753 sx
= x
+ UserGetSystemMetrics(SM_CXBORDER
);
754 sy
= y
- yspacing
- UserGetSystemMetrics(SM_CYBORDER
);
756 Child
->InternalPos
.IconPos
.x
= sx
;
757 Child
->InternalPos
.IconPos
.y
= sy
;
758 Child
->InternalPos
.flags
|= WPF_MININIT
;
760 co_WinPosSetWindowPos( Child
, 0, sx
, sy
, xspacing
, yspacing
, SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOCOPYBITS
| SWP_ASYNCWINDOWPOS
);
762 UserDerefObjectCo(Child
);
764 if (x
<= rectParent
.right
- xspacing
)
772 Child
= Child
->spwndNext
;
778 WinPosFindIconPos(PWND Window
, POINT
*Pos
)
781 PWND pwndChild
, pwndParent
;
782 int x
, y
, xspacing
, yspacing
;
784 pwndParent
= Window
->spwndParent
;
785 if (UserIsDesktopWindow(pwndParent
))
787 ERR("FIXME: Parent is Desktop, Min off screen!\n");
788 /* FIXME: ReactOS doesn't support iconic minimize to desktop */
789 Pos
->x
= Pos
->y
= -32000;
790 Window
->InternalPos
.flags
|= WPF_MININIT
;
791 Window
->InternalPos
.IconPos
.x
= Pos
->x
;
792 Window
->InternalPos
.IconPos
.y
= Pos
->y
;
796 IntGetClientRect( pwndParent
, &rectParent
);
797 // FIXME: Support Minimize Metrics gspv.mm.iArrange.
798 // Default: ARW_BOTTOMLEFT
800 y
= rectParent
.bottom
;
802 xspacing
= UserGetSystemMetrics(SM_CXMINIMIZED
);
803 yspacing
= UserGetSystemMetrics(SM_CYMINIMIZED
);
805 // Set to default position when minimized.
806 Pos
->x
= x
+ UserGetSystemMetrics(SM_CXBORDER
);
807 Pos
->y
= y
- yspacing
- UserGetSystemMetrics(SM_CYBORDER
);
809 for (pwndChild
= pwndParent
->spwndChild
; pwndChild
; pwndChild
= pwndChild
->spwndNext
)
811 if (pwndChild
== Window
) continue;
813 if ((pwndChild
->style
& (WS_VISIBLE
|WS_MINIMIZE
)) != (WS_VISIBLE
|WS_MINIMIZE
) )
818 if ( pwndChild
->InternalPos
.IconPos
.x
!= Pos
->x
&& pwndChild
->InternalPos
.IconPos
.y
!= Pos
->y
)
822 if (x
<= rectParent
.right
- xspacing
)
829 Pos
->x
= x
+ UserGetSystemMetrics(SM_CXBORDER
);
830 Pos
->y
= y
- yspacing
- UserGetSystemMetrics(SM_CYBORDER
);
833 Window
->InternalPos
.IconPos
.x
= Pos
->x
;
834 Window
->InternalPos
.IconPos
.y
= Pos
->y
;
835 Window
->InternalPos
.flags
|= WPF_MININIT
;
836 TRACE("Position is set! X:%d Y:%d\n",Pos
->x
,Pos
->y
);
841 UserHasWindowEdge(DWORD Style
, DWORD ExStyle
)
843 if (Style
& WS_MINIMIZE
)
845 if (ExStyle
& WS_EX_DLGMODALFRAME
)
847 if (ExStyle
& WS_EX_STATICEDGE
)
849 if (Style
& WS_THICKFRAME
)
852 if (Style
== WS_DLGFRAME
|| Style
== WS_CAPTION
)
858 IntGetWindowBorderMeasures(PWND Wnd
, UINT
*cx
, UINT
*cy
)
860 if(HAS_DLGFRAME(Wnd
->style
, Wnd
->ExStyle
) && !(Wnd
->style
& WS_MINIMIZE
))
862 *cx
= UserGetSystemMetrics(SM_CXDLGFRAME
);
863 *cy
= UserGetSystemMetrics(SM_CYDLGFRAME
);
867 if(HAS_THICKFRAME(Wnd
->style
, Wnd
->ExStyle
)&& !(Wnd
->style
& WS_MINIMIZE
))
869 *cx
= UserGetSystemMetrics(SM_CXFRAME
);
870 *cy
= UserGetSystemMetrics(SM_CYFRAME
);
872 else if(HAS_THINFRAME(Wnd
->style
, Wnd
->ExStyle
))
874 *cx
= UserGetSystemMetrics(SM_CXBORDER
);
875 *cy
= UserGetSystemMetrics(SM_CYBORDER
);
885 UserGetWindowBorders(DWORD Style
, DWORD ExStyle
, SIZE
*Size
, BOOL WithClient
)
889 if (UserHasWindowEdge(Style
, ExStyle
))
891 else if ((ExStyle
& (WS_EX_STATICEDGE
|WS_EX_DLGMODALFRAME
)) == WS_EX_STATICEDGE
)
892 Border
+= 1; /* for the outer frame always present */
893 if ((ExStyle
& WS_EX_CLIENTEDGE
) && WithClient
)
895 if (Style
& WS_CAPTION
|| ExStyle
& WS_EX_DLGMODALFRAME
)
896 Border
++; /* The other border */
897 Size
->cx
= Size
->cy
= Border
;
898 if ((Style
& WS_THICKFRAME
) && !(Style
& WS_MINIMIZE
)) /* The resize border */
900 Size
->cx
+= UserGetSystemMetrics(SM_CXFRAME
) - UserGetSystemMetrics(SM_CXDLGFRAME
);
901 Size
->cy
+= UserGetSystemMetrics(SM_CYFRAME
) - UserGetSystemMetrics(SM_CYDLGFRAME
);
903 Size
->cx
*= UserGetSystemMetrics(SM_CXBORDER
);
904 Size
->cy
*= UserGetSystemMetrics(SM_CYBORDER
);
909 // See winetests:user32:win.c:wine_AdjustWindowRectEx,
910 // Simplified version.
912 DWORD
IntGetWindowBorders(DWORD Style
, DWORD ExStyle
)
916 if ( ExStyle
& WS_EX_WINDOWEDGE
) // 1st
917 adjust
= 2; /* outer */
918 else if ( ExStyle
& WS_EX_STATICEDGE
) // 2nd
919 adjust
= 1; /* for the outer frame always present */
921 if (ExStyle
& WS_EX_CLIENTEDGE
)
924 if ( Style
& WS_CAPTION
|| ExStyle
& WS_EX_DLGMODALFRAME
)
925 adjust
++; /* The other border */
931 co_WinPosGetMinMaxInfo(PWND Window
, POINT
* MaxSize
, POINT
* MaxPos
,
932 POINT
* MinTrack
, POINT
* MaxTrack
)
937 LONG style
= Window
->style
;
939 LONG exstyle
= Window
->ExStyle
;
943 ASSERT_REFS_CO(Window
);
945 /* Compute default values */
947 rc
= Window
->rcWindow
;
948 MinMax
.ptReserved
.x
= rc
.left
;
949 MinMax
.ptReserved
.y
= rc
.top
;
951 if ((style
& WS_CAPTION
) == WS_CAPTION
)
952 adjustedStyle
= style
& ~WS_BORDER
; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
954 adjustedStyle
= style
;
956 if (Window
->spwndParent
)
957 IntGetClientRect(Window
->spwndParent
, &rc
);
959 adjust
= IntGetWindowBorders(adjustedStyle
, exstyle
);
961 // Handle special case while maximized. CORE-15893
962 if ((adjustedStyle
& WS_THICKFRAME
) && !(adjustedStyle
& WS_CHILD
) && !(adjustedStyle
& WS_MINIMIZE
))
965 xinc
= yinc
= adjust
;
967 if ((adjustedStyle
& WS_THICKFRAME
) && (adjustedStyle
& WS_CHILD
) && !(adjustedStyle
& WS_MINIMIZE
))
969 xinc
+= UserGetSystemMetrics(SM_CXFRAME
) - UserGetSystemMetrics(SM_CXDLGFRAME
);
970 yinc
+= UserGetSystemMetrics(SM_CYFRAME
) - UserGetSystemMetrics(SM_CYDLGFRAME
);
973 RECTL_vInflateRect( &rc
,
974 xinc
* UserGetSystemMetrics(SM_CXBORDER
),
975 yinc
* UserGetSystemMetrics(SM_CYBORDER
) );
980 MinMax
.ptMaxSize
.x
= rc
.right
- rc
.left
;
981 MinMax
.ptMaxSize
.y
= rc
.bottom
- rc
.top
;
982 if (style
& (WS_DLGFRAME
| WS_BORDER
))
984 MinMax
.ptMinTrackSize
.x
= UserGetSystemMetrics(SM_CXMINTRACK
);
985 MinMax
.ptMinTrackSize
.y
= UserGetSystemMetrics(SM_CYMINTRACK
);
989 MinMax
.ptMinTrackSize
.x
= 2 * xinc
;
990 MinMax
.ptMinTrackSize
.y
= 2 * yinc
;
992 MinMax
.ptMaxTrackSize
.x
= UserGetSystemMetrics(SM_CXMAXTRACK
);
993 MinMax
.ptMaxTrackSize
.y
= UserGetSystemMetrics(SM_CYMAXTRACK
);
994 MinMax
.ptMaxPosition
.x
= -xinc
;
995 MinMax
.ptMaxPosition
.y
= -yinc
;
997 if (!EMPTYPOINT(Window
->InternalPos
.MaxPos
)) MinMax
.ptMaxPosition
= Window
->InternalPos
.MaxPos
;
999 co_IntSendMessage(Window
->head
.h
, WM_GETMINMAXINFO
, 0, (LPARAM
)&MinMax
);
1001 /* if the app didn't change the values, adapt them for the current monitor */
1002 if ((monitor
= UserGetPrimaryMonitor()))
1006 rc_work
= monitor
->rcMonitor
;
1008 if (style
& WS_MAXIMIZEBOX
)
1010 if ((style
& WS_CAPTION
) == WS_CAPTION
|| !(style
& (WS_CHILD
| WS_POPUP
)))
1011 rc_work
= monitor
->rcWork
;
1014 if (MinMax
.ptMaxSize
.x
== UserGetSystemMetrics(SM_CXSCREEN
) + 2 * xinc
&&
1015 MinMax
.ptMaxSize
.y
== UserGetSystemMetrics(SM_CYSCREEN
) + 2 * yinc
)
1017 MinMax
.ptMaxSize
.x
= (rc_work
.right
- rc_work
.left
) + 2 * xinc
;
1018 MinMax
.ptMaxSize
.y
= (rc_work
.bottom
- rc_work
.top
) + 2 * yinc
;
1020 if (MinMax
.ptMaxPosition
.x
== -xinc
&& MinMax
.ptMaxPosition
.y
== -yinc
)
1022 MinMax
.ptMaxPosition
.x
= rc_work
.left
- xinc
;
1023 MinMax
.ptMaxPosition
.y
= rc_work
.top
- yinc
;
1025 if (MinMax
.ptMaxSize
.x
>= (monitor
->rcMonitor
.right
- monitor
->rcMonitor
.left
) &&
1026 MinMax
.ptMaxSize
.y
>= (monitor
->rcMonitor
.bottom
- monitor
->rcMonitor
.top
) )
1028 Window
->state
|= WNDS_MAXIMIZESTOMONITOR
;
1031 Window
->state
&= ~WNDS_MAXIMIZESTOMONITOR
;
1035 MinMax
.ptMaxTrackSize
.x
= max(MinMax
.ptMaxTrackSize
.x
,
1036 MinMax
.ptMinTrackSize
.x
);
1037 MinMax
.ptMaxTrackSize
.y
= max(MinMax
.ptMaxTrackSize
.y
,
1038 MinMax
.ptMinTrackSize
.y
);
1041 *MaxSize
= MinMax
.ptMaxSize
;
1043 *MaxPos
= MinMax
.ptMaxPosition
;
1045 *MinTrack
= MinMax
.ptMinTrackSize
;
1047 *MaxTrack
= MinMax
.ptMaxTrackSize
;
1049 return 0; // FIXME: What does it return? Wine returns MINMAXINFO.
1054 IntValidateParent(PWND Child
, PREGION ValidateRgn
)
1056 PWND ParentWnd
= Child
->spwndParent
;
1060 if (ParentWnd
->style
& WS_CLIPCHILDREN
)
1063 if (ParentWnd
->hrgnUpdate
!= 0)
1065 IntInvalidateWindows( ParentWnd
,
1067 RDW_VALIDATE
| RDW_NOCHILDREN
);
1070 ParentWnd
= ParentWnd
->spwndParent
;
1078 FixClientRect(PRECTL ClientRect
, PRECTL WindowRect
)
1080 if (ClientRect
->left
< WindowRect
->left
)
1082 ClientRect
->left
= WindowRect
->left
;
1084 else if (WindowRect
->right
< ClientRect
->left
)
1086 ClientRect
->left
= WindowRect
->right
;
1088 if (ClientRect
->right
< WindowRect
->left
)
1090 ClientRect
->right
= WindowRect
->left
;
1092 else if (WindowRect
->right
< ClientRect
->right
)
1094 ClientRect
->right
= WindowRect
->right
;
1096 if (ClientRect
->top
< WindowRect
->top
)
1098 ClientRect
->top
= WindowRect
->top
;
1100 else if (WindowRect
->bottom
< ClientRect
->top
)
1102 ClientRect
->top
= WindowRect
->bottom
;
1104 if (ClientRect
->bottom
< WindowRect
->top
)
1106 ClientRect
->bottom
= WindowRect
->top
;
1108 else if (WindowRect
->bottom
< ClientRect
->bottom
)
1110 ClientRect
->bottom
= WindowRect
->bottom
;
1113 /***********************************************************************
1116 * Compute the valid rects from the old and new client rect and WVR_* flags.
1117 * Helper for WM_NCCALCSIZE handling.
1121 get_valid_rects( RECTL
*old_client
, RECTL
*new_client
, UINT flags
, RECTL
*valid
)
1125 if (flags
& WVR_REDRAW
)
1127 RECTL_vSetEmptyRect( &valid
[0] );
1128 RECTL_vSetEmptyRect( &valid
[1] );
1132 if (flags
& WVR_VALIDRECTS
)
1134 if (!RECTL_bIntersectRect( &valid
[0], &valid
[0], new_client
) ||
1135 !RECTL_bIntersectRect( &valid
[1], &valid
[1], old_client
))
1137 RECTL_vSetEmptyRect( &valid
[0] );
1138 RECTL_vSetEmptyRect( &valid
[1] );
1141 flags
= WVR_ALIGNLEFT
| WVR_ALIGNTOP
;
1145 valid
[0] = *new_client
;
1146 valid
[1] = *old_client
;
1149 /* make sure the rectangles have the same size */
1150 cx
= min( valid
[0].right
- valid
[0].left
, valid
[1].right
- valid
[1].left
);
1151 cy
= min( valid
[0].bottom
- valid
[0].top
, valid
[1].bottom
- valid
[1].top
);
1153 if (flags
& WVR_ALIGNBOTTOM
)
1155 valid
[0].top
= valid
[0].bottom
- cy
;
1156 valid
[1].top
= valid
[1].bottom
- cy
;
1160 valid
[0].bottom
= valid
[0].top
+ cy
;
1161 valid
[1].bottom
= valid
[1].top
+ cy
;
1163 if (flags
& WVR_ALIGNRIGHT
)
1165 valid
[0].left
= valid
[0].right
- cx
;
1166 valid
[1].left
= valid
[1].right
- cx
;
1170 valid
[0].right
= valid
[0].left
+ cx
;
1171 valid
[1].right
= valid
[1].left
+ cx
;
1177 co_WinPosDoNCCALCSize(PWND Window
, PWINDOWPOS WinPos
, RECTL
* WindowRect
, RECTL
* ClientRect
, RECTL
* validRects
)
1182 ASSERT_REFS_CO(Window
);
1184 /* Send WM_NCCALCSIZE message to get new client area */
1185 if ((WinPos
->flags
& (SWP_FRAMECHANGED
| SWP_NOSIZE
)) != SWP_NOSIZE
)
1187 NCCALCSIZE_PARAMS params
;
1188 WINDOWPOS winposCopy
;
1190 params
.rgrc
[0] = *WindowRect
; // new coordinates of a window that has been moved or resized
1191 params
.rgrc
[1] = Window
->rcWindow
; // window before it was moved or resized
1192 params
.rgrc
[2] = Window
->rcClient
; // client area before the window was moved or resized
1194 Parent
= Window
->spwndParent
;
1195 if (0 != (Window
->style
& WS_CHILD
) && Parent
)
1197 RECTL_vOffsetRect(&(params
.rgrc
[0]), - Parent
->rcClient
.left
, - Parent
->rcClient
.top
);
1198 RECTL_vOffsetRect(&(params
.rgrc
[1]), - Parent
->rcClient
.left
, - Parent
->rcClient
.top
);
1199 RECTL_vOffsetRect(&(params
.rgrc
[2]), - Parent
->rcClient
.left
, - Parent
->rcClient
.top
);
1202 params
.lppos
= &winposCopy
;
1203 winposCopy
= *WinPos
;
1205 wvrFlags
= co_IntSendMessage(Window
->head
.h
, WM_NCCALCSIZE
, TRUE
, (LPARAM
) ¶ms
);
1207 /* If the application send back garbage, ignore it */
1208 if (params
.rgrc
[0].left
<= params
.rgrc
[0].right
&&
1209 params
.rgrc
[0].top
<= params
.rgrc
[0].bottom
)
1211 *ClientRect
= params
.rgrc
[0]; // First rectangle contains the coordinates of the new client rectangle resulting from the move or resize
1212 if ((Window
->style
& WS_CHILD
) && Parent
)
1214 RECTL_vOffsetRect(ClientRect
, Parent
->rcClient
.left
, Parent
->rcClient
.top
);
1216 FixClientRect(ClientRect
, WindowRect
);
1219 if (ClientRect
->left
!= Window
->rcClient
.left
||
1220 ClientRect
->top
!= Window
->rcClient
.top
)
1222 WinPos
->flags
&= ~SWP_NOCLIENTMOVE
;
1225 if (ClientRect
->right
- ClientRect
->left
!= Window
->rcClient
.right
- Window
->rcClient
.left
)
1227 WinPos
->flags
&= ~SWP_NOCLIENTSIZE
;
1230 wvrFlags
&= ~WVR_HREDRAW
;
1232 if (ClientRect
->bottom
- ClientRect
->top
!= Window
->rcClient
.bottom
- Window
->rcClient
.top
)
1234 WinPos
->flags
&= ~SWP_NOCLIENTSIZE
;
1237 wvrFlags
&= ~WVR_VREDRAW
;
1239 validRects
[0] = params
.rgrc
[1]; // second rectangle contains the valid destination rectangle
1240 validRects
[1] = params
.rgrc
[2]; // third rectangle contains the valid source rectangle
1244 if (!(WinPos
->flags
& SWP_NOMOVE
) &&
1245 (ClientRect
->left
!= Window
->rcClient
.left
||
1246 ClientRect
->top
!= Window
->rcClient
.top
))
1248 WinPos
->flags
&= ~SWP_NOCLIENTMOVE
;
1252 if (WinPos
->flags
& (SWP_NOCOPYBITS
| SWP_NOREDRAW
| SWP_SHOWWINDOW
| SWP_HIDEWINDOW
))
1254 RECTL_vSetEmptyRect( &validRects
[0] );
1255 RECTL_vSetEmptyRect( &validRects
[1] );
1257 else get_valid_rects( &Window
->rcClient
, ClientRect
, wvrFlags
, validRects
);
1264 co_WinPosDoWinPosChanging(PWND Window
,
1269 ASSERT_REFS_CO(Window
);
1271 /* Send WM_WINDOWPOSCHANGING message */
1273 if (!(WinPos
->flags
& SWP_NOSENDCHANGING
)
1274 && !((WinPos
->flags
& SWP_AGG_NOCLIENTCHANGE
) && (WinPos
->flags
& SWP_SHOWWINDOW
)))
1276 TRACE("Sending WM_WINDOWPOSCHANGING to hwnd %p flags %04x.\n", Window
->head
.h
,WinPos
->flags
);
1277 co_IntSendMessage(Window
->head
.h
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
) WinPos
);
1280 /* Calculate new position and size */
1282 *WindowRect
= Window
->rcWindow
;
1283 *ClientRect
= (Window
->style
& WS_MINIMIZE
) ? Window
->rcWindow
: Window
->rcClient
;
1285 if (!(WinPos
->flags
& SWP_NOSIZE
))
1287 if (Window
->style
& WS_MINIMIZE
)
1289 WindowRect
->right
= WindowRect
->left
+ UserGetSystemMetrics(SM_CXMINIMIZED
);
1290 WindowRect
->bottom
= WindowRect
->top
+ UserGetSystemMetrics(SM_CYMINIMIZED
);
1294 WindowRect
->right
= WindowRect
->left
+ WinPos
->cx
;
1295 WindowRect
->bottom
= WindowRect
->top
+ WinPos
->cy
;
1299 if (!(WinPos
->flags
& SWP_NOMOVE
))
1306 Parent
= Window
->spwndParent
;
1308 // Parent child position issue is in here. SetParent_W7 test CORE-6651.
1309 if (//((Window->style & WS_CHILD) != 0) && <- Fixes wine msg test_SetParent: "rects do not match", the last test.
1311 Parent
!= Window
->head
.rpdesk
->pDeskInfo
->spwnd
)
1313 TRACE("Not SWP_NOMOVE 1 Parent client offset X %d Y %d\n",X
,Y
);
1314 X
+= Parent
->rcClient
.left
;
1315 Y
+= Parent
->rcClient
.top
;
1316 TRACE("Not SWP_NOMOVE 2 Parent client offset X %d Y %d\n",X
,Y
);
1319 WindowRect
->left
= X
;
1320 WindowRect
->top
= Y
;
1321 WindowRect
->right
+= X
- Window
->rcWindow
.left
;
1322 WindowRect
->bottom
+= Y
- Window
->rcWindow
.top
;
1324 RECTL_vOffsetRect(ClientRect
, X
- Window
->rcWindow
.left
,
1325 Y
- Window
->rcWindow
.top
);
1327 WinPos
->flags
|= SWP_NOCLIENTMOVE
| SWP_NOCLIENTSIZE
;
1329 TRACE( "hwnd %p, after %p, swp %d,%d %dx%d flags %08x\n",
1330 WinPos
->hwnd
, WinPos
->hwndInsertAfter
, WinPos
->x
, WinPos
->y
,
1331 WinPos
->cx
, WinPos
->cy
, WinPos
->flags
);
1332 TRACE("WindowRect: %d %d %d %d\n", WindowRect
->left
,WindowRect
->top
,WindowRect
->right
,WindowRect
->bottom
);
1333 TRACE("ClientRect: %d %d %d %d\n", ClientRect
->left
,ClientRect
->top
,ClientRect
->right
,ClientRect
->bottom
);
1339 * Fix Z order taking into account owned popups -
1340 * basically we need to maintain them above the window that owns them
1342 * FIXME: hide/show owned popups when owner visibility changes.
1344 * ReactOS: See bug CORE-6129 and CORE-6554.
1348 // Pass all the win:test_children/popup_zorder tests except "move hwnd_F and its popups down" which is if'ed out.
1349 // Side effect, breaks more of the DeferWindowPos api tests, but wine breaks more!!!!
1352 WinPosDoOwnedPopups(PWND Window
, HWND hWndInsertAfter
)
1357 PWND DesktopWindow
, ChildObject
;
1360 TRACE("(%p) hInsertAfter = %p\n", Window
, hWndInsertAfter
);
1362 Style
= Window
->style
;
1364 if (Style
& WS_CHILD
)
1366 TRACE("Window is child\n");
1367 return hWndInsertAfter
;
1370 Owner
= Window
->spwndOwner
? Window
->spwndOwner
->head
.h
: NULL
;
1374 /* Make sure this popup stays above the owner */
1376 if (hWndInsertAfter
!= HWND_TOPMOST
)
1378 DesktopWindow
= UserGetDesktopWindow();
1379 List
= IntWinListChildren(DesktopWindow
);
1383 for (i
= 0; List
[i
]; i
++)
1385 BOOL topmost
= FALSE
;
1387 ChildObject
= ValidateHwndNoErr(List
[i
]);
1390 topmost
= (ChildObject
->ExStyle
& WS_EX_TOPMOST
) != 0;
1393 if (List
[i
] == Owner
)
1395 if (i
> 0) hWndInsertAfter
= List
[i
-1];
1396 else hWndInsertAfter
= topmost
? HWND_TOPMOST
: HWND_TOP
;
1400 if (hWndInsertAfter
== HWND_TOP
|| hWndInsertAfter
== HWND_NOTOPMOST
)
1402 if (!topmost
) break;
1404 else if (List
[i
] == hWndInsertAfter
) break;
1408 return hWndInsertAfter
;
1412 if (hWndInsertAfter
== HWND_BOTTOM
)
1414 ERR("Window is HWND_BOTTOM hwnd %p\n",hWndInsertAfter
);
1415 if (List
) ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1421 DesktopWindow
= UserGetDesktopWindow();
1422 List
= IntWinListChildren(DesktopWindow
);
1429 if (hWndInsertAfter
== HWND_TOP
|| hWndInsertAfter
== HWND_NOTOPMOST
)
1431 if (hWndInsertAfter
== HWND_NOTOPMOST
|| !(Window
->ExStyle
& WS_EX_TOPMOST
))
1433 TRACE("skip all the topmost windows\n");
1434 /* skip all the topmost windows */
1436 (ChildObject
= ValidateHwndNoErr(List
[i
])) &&
1437 (ChildObject
->ExStyle
& WS_EX_TOPMOST
)) i
++;
1440 else if (hWndInsertAfter
!= HWND_TOPMOST
)
1442 /* skip windows that are already placed correctly */
1443 for (i
= 0; List
[i
]; i
++)
1445 if (List
[i
] == hWndInsertAfter
) break;
1446 if (List
[i
] == UserHMGetHandle(Window
))
1448 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1449 goto done
; /* nothing to do if window is moving backwards in z-order */
1454 for (; List
[i
]; i
++)
1457 USER_REFERENCE_ENTRY Ref
;
1459 if (List
[i
] == UserHMGetHandle(Window
))
1462 if (!(Wnd
= ValidateHwndNoErr(List
[i
])))
1465 Owner
= Wnd
->spwndOwner
? Wnd
->spwndOwner
->head
.h
: NULL
;
1467 if (Owner
!= UserHMGetHandle(Window
)) continue;
1469 UserRefObjectCo(Wnd
, &Ref
);
1470 TRACE( "moving %p owned by %p after %p\n", List
[i
], UserHMGetHandle(Window
), hWndInsertAfter
);
1471 co_WinPosSetWindowPos(Wnd
, hWndInsertAfter
, 0, 0, 0, 0,
1472 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOSENDCHANGING
| SWP_DEFERERASE
);
1474 UserDerefObjectCo(Wnd
);
1475 hWndInsertAfter
= List
[i
];
1477 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1480 return hWndInsertAfter
;
1484 /***********************************************************************
1485 * WinPosInternalMoveWindow
1487 * Update WindowRect and ClientRect of Window and all of its children
1488 * We keep both WindowRect and ClientRect in screen coordinates internally
1492 WinPosInternalMoveWindow(PWND Window
, INT MoveX
, INT MoveY
)
1496 ASSERT(Window
!= Window
->spwndChild
);
1497 TRACE("InternalMoveWin X %d Y %d\n", MoveX
, MoveY
);
1499 Window
->rcWindow
.left
+= MoveX
;
1500 Window
->rcWindow
.right
+= MoveX
;
1501 Window
->rcWindow
.top
+= MoveY
;
1502 Window
->rcWindow
.bottom
+= MoveY
;
1504 Window
->rcClient
.left
+= MoveX
;
1505 Window
->rcClient
.right
+= MoveX
;
1506 Window
->rcClient
.top
+= MoveY
;
1507 Window
->rcClient
.bottom
+= MoveY
;
1509 for(Child
= Window
->spwndChild
; Child
; Child
= Child
->spwndNext
)
1511 WinPosInternalMoveWindow(Child
, MoveX
, MoveY
);
1516 * WinPosFixupSWPFlags
1518 * Fix redundant flags and values in the WINDOWPOS structure.
1522 WinPosFixupFlags(WINDOWPOS
*WinPos
, PWND Wnd
)
1527 /* Finally make sure that all coordinates are valid */
1528 if (WinPos
->x
< -32768) WinPos
->x
= -32768;
1529 else if (WinPos
->x
> 32767) WinPos
->x
= 32767;
1530 if (WinPos
->y
< -32768) WinPos
->y
= -32768;
1531 else if (WinPos
->y
> 32767) WinPos
->y
= 32767;
1533 WinPos
->cx
= max(WinPos
->cx
, 0);
1534 WinPos
->cy
= max(WinPos
->cy
, 0);
1536 Parent
= UserGetAncestor( Wnd
, GA_PARENT
);
1537 if (!IntIsWindowVisible( Parent
) &&
1538 /* Fix B : wine msg test_SetParent:WmSetParentSeq_2:25 wParam bits! */
1539 (WinPos
->flags
& SWP_AGG_STATUSFLAGS
) == SWP_AGG_NOPOSCHANGE
) WinPos
->flags
|= SWP_NOREDRAW
;
1541 if (Wnd
->style
& WS_VISIBLE
) WinPos
->flags
&= ~SWP_SHOWWINDOW
;
1544 WinPos
->flags
&= ~SWP_HIDEWINDOW
;
1545 if (!(WinPos
->flags
& SWP_SHOWWINDOW
)) WinPos
->flags
|= SWP_NOREDRAW
;
1548 /* Check for right size */
1549 if (Wnd
->rcWindow
.right
- Wnd
->rcWindow
.left
== WinPos
->cx
&&
1550 Wnd
->rcWindow
.bottom
- Wnd
->rcWindow
.top
== WinPos
->cy
)
1552 WinPos
->flags
|= SWP_NOSIZE
;
1557 IntClientToScreen( Parent
, &pt
);
1558 TRACE("WPFU C2S wpx %d wpy %d ptx %d pty %d\n",WinPos
->x
,WinPos
->y
,pt
.x
,pt
.y
);
1559 /* Check for right position */
1560 if (Wnd
->rcWindow
.left
== pt
.x
&& Wnd
->rcWindow
.top
== pt
.y
)
1562 //ERR("In right pos\n");
1563 WinPos
->flags
|= SWP_NOMOVE
;
1566 if ( WinPos
->hwnd
!= UserGetForegroundWindow() && (Wnd
->style
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)
1568 /* Bring to the top when activating */
1569 if (!(WinPos
->flags
& (SWP_NOACTIVATE
|SWP_HIDEWINDOW
)) &&
1570 (WinPos
->flags
& SWP_NOZORDER
||
1571 (WinPos
->hwndInsertAfter
!= HWND_TOPMOST
&& WinPos
->hwndInsertAfter
!= HWND_NOTOPMOST
)))
1573 WinPos
->flags
&= ~SWP_NOZORDER
;
1574 WinPos
->hwndInsertAfter
= (0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
) ? HWND_TOPMOST
: HWND_TOP
);
1578 /* Check hwndInsertAfter */
1579 if (!(WinPos
->flags
& SWP_NOZORDER
))
1581 /* Fix sign extension */
1582 if (WinPos
->hwndInsertAfter
== (HWND
)0xffff)
1584 WinPos
->hwndInsertAfter
= HWND_TOPMOST
;
1586 else if (WinPos
->hwndInsertAfter
== (HWND
)0xfffe)
1588 WinPos
->hwndInsertAfter
= HWND_NOTOPMOST
;
1591 if (WinPos
->hwndInsertAfter
== HWND_TOP
)
1593 /* Keep it topmost when it's already topmost */
1594 if ((Wnd
->ExStyle
& WS_EX_TOPMOST
) != 0)
1595 WinPos
->hwndInsertAfter
= HWND_TOPMOST
;
1597 if (IntGetWindow(WinPos
->hwnd
, GW_HWNDFIRST
) == WinPos
->hwnd
)
1599 WinPos
->flags
|= SWP_NOZORDER
;
1602 else if (WinPos
->hwndInsertAfter
== HWND_BOTTOM
)
1604 if (!(Wnd
->ExStyle
& WS_EX_TOPMOST
) && IntGetWindow(WinPos
->hwnd
, GW_HWNDLAST
) == WinPos
->hwnd
)
1605 WinPos
->flags
|= SWP_NOZORDER
;
1607 else if (WinPos
->hwndInsertAfter
== HWND_TOPMOST
)
1609 if ((Wnd
->ExStyle
& WS_EX_TOPMOST
) && IntGetWindow(WinPos
->hwnd
, GW_HWNDFIRST
) == WinPos
->hwnd
)
1610 WinPos
->flags
|= SWP_NOZORDER
;
1612 else if (WinPos
->hwndInsertAfter
== HWND_NOTOPMOST
)
1614 if (!(Wnd
->ExStyle
& WS_EX_TOPMOST
))
1615 WinPos
->flags
|= SWP_NOZORDER
;
1617 else /* hwndInsertAfter must be a sibling of the window */
1621 InsAfterWnd
= ValidateHwndNoErr(WinPos
->hwndInsertAfter
);
1627 if (InsAfterWnd
->spwndParent
!= Wnd
->spwndParent
)
1629 /* Note from wine User32 Win test_SetWindowPos:
1630 "Returns TRUE also for windows that are not siblings"
1631 "Does not seem to do anything even without passing flags, still returns TRUE"
1632 "Same thing the other way around."
1633 ".. and with these windows."
1640 * We don't need to change the Z order of hwnd if it's already
1641 * inserted after hwndInsertAfter or when inserting hwnd after
1644 if ((WinPos
->hwnd
== WinPos
->hwndInsertAfter
) ||
1645 ((InsAfterWnd
->spwndNext
) && (WinPos
->hwnd
== InsAfterWnd
->spwndNext
->head
.h
)))
1647 WinPos
->flags
|= SWP_NOZORDER
;
1657 // This is a NC HACK fix for forcing painting of non client areas.
1658 // Further troubleshooting in painting.c is required to remove this hack.
1659 // See CORE-7166 & CORE-15934
1662 ForceNCPaintErase(PWND Wnd
, HRGN hRgn
, PREGION pRgn
)
1667 BOOL Create
= FALSE
;
1669 if (Wnd
->hrgnUpdate
== NULL
)
1671 Wnd
->hrgnUpdate
= NtGdiCreateRectRgn(0, 0, 0, 0);
1672 IntGdiSetRegionOwner(Wnd
->hrgnUpdate
, GDI_OBJ_HMGR_PUBLIC
);
1676 if (Wnd
->hrgnUpdate
!= HRGN_WINDOW
)
1678 RgnUpdate
= REGION_LockRgn(Wnd
->hrgnUpdate
);
1681 RgnType
= IntGdiCombineRgn(RgnUpdate
, RgnUpdate
, pRgn
, RGN_OR
);
1682 REGION_UnlockRgn(RgnUpdate
);
1683 if (RgnType
== NULLREGION
)
1685 IntGdiSetRegionOwner(Wnd
->hrgnUpdate
, GDI_OBJ_HMGR_POWNED
);
1686 GreDeleteObject(Wnd
->hrgnUpdate
);
1687 Wnd
->hrgnUpdate
= NULL
;
1693 IntSendNCPaint( Wnd
, hRgn
); // Region can be deleted by the application.
1695 if (Wnd
->hrgnUpdate
)
1697 hDC
= UserGetDCEx( Wnd
,
1699 DCX_CACHE
|DCX_USESTYLE
|DCX_INTERSECTRGN
|DCX_KEEPCLIPRGN
);
1701 Wnd
->state
&= ~(WNDS_SENDERASEBACKGROUND
|WNDS_ERASEBACKGROUND
);
1702 // Kill the loop, so Clear before we send.
1703 if (!co_IntSendMessage(UserHMGetHandle(Wnd
), WM_ERASEBKGND
, (WPARAM
)hDC
, 0))
1705 Wnd
->state
|= (WNDS_SENDERASEBACKGROUND
|WNDS_ERASEBACKGROUND
);
1707 UserReleaseDC(Wnd
, hDC
, FALSE
);
1712 IntGdiSetRegionOwner(Wnd
->hrgnUpdate
, GDI_OBJ_HMGR_POWNED
);
1713 GreDeleteObject(Wnd
->hrgnUpdate
);
1714 Wnd
->hrgnUpdate
= NULL
;
1718 /* x and y are always screen relative */
1720 co_WinPosSetWindowPos(
1722 HWND WndInsertAfter
,
1731 RECTL NewWindowRect
;
1732 RECTL NewClientRect
;
1733 RECTL valid_rects
[2];
1734 PREGION VisBefore
= NULL
;
1735 PREGION VisBeforeJustClient
= NULL
;
1736 PREGION VisAfter
= NULL
;
1737 PREGION CopyRgn
= NULL
;
1739 RECTL OldWindowRect
, OldClientRect
;
1744 BOOL bPointerInWindow
, PosChanged
= FALSE
;
1745 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1747 ASSERT_REFS_CO(Window
);
1749 TRACE("pwnd %p, after %p, %d,%d (%dx%d), flags 0x%x",
1750 Window
, WndInsertAfter
, x
, y
, cx
, cy
, flags
);
1752 dump_winpos_flags(flags
);
1755 /* FIXME: Get current active window from active queue. Why? since r2915. */
1757 bPointerInWindow
= IntPtInWindow(Window
, gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
);
1759 WinPos
.hwnd
= Window
->head
.h
;
1760 WinPos
.hwndInsertAfter
= WndInsertAfter
;
1765 WinPos
.flags
= flags
;
1767 if ( flags
& SWP_ASYNCWINDOWPOS
)
1770 PWINDOWPOS ppos
= ExAllocatePoolWithTag(PagedPool
, sizeof(WINDOWPOS
), USERTAG_SWP
);
1773 WinPos
.flags
&= ~SWP_ASYNCWINDOWPOS
; // Clear flag.
1775 /* Yes it's a pointer inside Win32k! */
1776 lRes
= co_IntSendMessageNoWait( WinPos
.hwnd
, WM_ASYNC_SETWINDOWPOS
, 0, (LPARAM
)ppos
);
1777 /* We handle this the same way as Event Hooks and Hooks. */
1780 ExFreePoolWithTag(ppos
, USERTAG_SWP
);
1788 co_WinPosDoWinPosChanging(Window
, &WinPos
, &NewWindowRect
, &NewClientRect
);
1790 /* Does the window still exist? */
1791 if (!IntIsWindow(WinPos
.hwnd
))
1793 TRACE("WinPosSetWindowPos: Invalid handle 0x%p!\n",WinPos
.hwnd
);
1794 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE
);
1798 /* Fix up the flags. */
1799 if (!WinPosFixupFlags(&WinPos
, Window
))
1805 Ancestor
= UserGetAncestor(Window
, GA_PARENT
);
1806 if ( (WinPos
.flags
& (SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) != SWP_NOZORDER
&&
1807 Ancestor
&& Ancestor
->head
.h
== IntGetDesktopWindow() )
1809 WinPos
.hwndInsertAfter
= WinPosDoOwnedPopups(Window
, WinPos
.hwndInsertAfter
);
1812 if (!(WinPos
.flags
& SWP_NOREDRAW
))
1814 /* Compute the visible region before the window position is changed */
1815 if (!(WinPos
.flags
& SWP_SHOWWINDOW
) &&
1816 (WinPos
.flags
& (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
|
1817 SWP_HIDEWINDOW
| SWP_FRAMECHANGED
)) !=
1818 (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
))
1820 VisBefore
= VIS_ComputeVisibleRegion(Window
, FALSE
, FALSE
,
1821 (Window
->style
& WS_CLIPSIBLINGS
) ? TRUE
: FALSE
);
1823 if ( VisBefore
!= NULL
&&
1824 REGION_Complexity(VisBefore
) == NULLREGION
)
1826 REGION_Delete(VisBefore
);
1831 REGION_bOffsetRgn(VisBefore
, -Window
->rcWindow
.left
, -Window
->rcWindow
.top
);
1834 /* Calculate the non client area for resizes, as this is used in the copy region */
1835 if ((WinPos
.flags
& (SWP_NOSIZE
| SWP_FRAMECHANGED
)) != SWP_NOSIZE
)
1837 VisBeforeJustClient
= VIS_ComputeVisibleRegion(Window
, TRUE
, FALSE
,
1838 (Window
->style
& WS_CLIPSIBLINGS
) ? TRUE
: FALSE
);
1840 if ( VisBeforeJustClient
!= NULL
&&
1841 REGION_Complexity(VisBeforeJustClient
) == NULLREGION
)
1843 REGION_Delete(VisBeforeJustClient
);
1844 VisBeforeJustClient
= NULL
;
1846 else if(VisBeforeJustClient
)
1848 REGION_bOffsetRgn(VisBeforeJustClient
, -Window
->rcWindow
.left
, -Window
->rcWindow
.top
);
1855 if (Window
->hrgnNewFrame
)
1857 SelectWindowRgn( Window
, Window
->hrgnNewFrame
); // Should be PSMWP->acvr->hrgnClip
1858 Window
->hrgnNewFrame
= NULL
;
1861 WvrFlags
= co_WinPosDoNCCALCSize(Window
, &WinPos
, &NewWindowRect
, &NewClientRect
, valid_rects
);
1863 // ERR("co_WinPosDoNCCALCSize returned 0x%x\n valid dest: %d %d %d %d\n valid src : %d %d %d %d\n", WvrFlags,
1864 // valid_rects[0].left,valid_rects[0].top,valid_rects[0].right,valid_rects[0].bottom,
1865 // valid_rects[1].left,valid_rects[1].top,valid_rects[1].right,valid_rects[1].bottom);
1867 /* Validate link windows. (also take into account shell window in hwndShellWindow) */
1868 if (!(WinPos
.flags
& SWP_NOZORDER
) && WinPos
.hwnd
!= UserGetShellWindow())
1870 IntLinkHwnd(Window
, WinPos
.hwndInsertAfter
);
1873 OldWindowRect
= Window
->rcWindow
;
1874 OldClientRect
= Window
->rcClient
;
1876 if (NewClientRect
.left
!= OldClientRect
.left
||
1877 NewClientRect
.top
!= OldClientRect
.top
)
1879 // Move child window if their parent is moved. Keep Child window relative to Parent...
1880 WinPosInternalMoveWindow(Window
,
1881 NewClientRect
.left
- OldClientRect
.left
,
1882 NewClientRect
.top
- OldClientRect
.top
);
1886 Window
->rcWindow
= NewWindowRect
;
1887 Window
->rcClient
= NewClientRect
;
1889 /* erase parent when hiding or resizing child */
1890 if (WinPos
.flags
& SWP_HIDEWINDOW
)
1892 /* Clear the update region */
1893 co_UserRedrawWindow( Window
,
1896 RDW_VALIDATE
| RDW_NOFRAME
| RDW_NOERASE
| RDW_NOINTERNALPAINT
| RDW_ALLCHILDREN
);
1898 if (UserIsDesktopWindow(Window
->spwndParent
))
1899 co_IntShellHookNotify(HSHELL_WINDOWDESTROYED
, (WPARAM
)Window
->head
.h
, 0);
1901 Window
->style
&= ~WS_VISIBLE
; //IntSetStyle( Window, 0, WS_VISIBLE );
1902 Window
->head
.pti
->cVisWindows
--;
1903 IntNotifyWinEvent(EVENT_OBJECT_HIDE
, Window
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
1905 else if (WinPos
.flags
& SWP_SHOWWINDOW
)
1907 if ((Window
->ExStyle
& WS_EX_APPWINDOW
) ||
1908 (!(Window
->ExStyle
& WS_EX_TOOLWINDOW
) && !Window
->spwndOwner
&&
1909 (!Window
->spwndParent
|| UserIsDesktopWindow(Window
->spwndParent
))))
1911 co_IntShellHookNotify(HSHELL_WINDOWCREATED
, (WPARAM
)Window
->head
.h
, 0);
1912 if (!(WinPos
.flags
& SWP_NOACTIVATE
))
1913 UpdateShellHook(Window
);
1916 Window
->style
|= WS_VISIBLE
; //IntSetStyle( Window, WS_VISIBLE, 0 );
1917 Window
->head
.pti
->cVisWindows
++;
1918 IntNotifyWinEvent(EVENT_OBJECT_SHOW
, Window
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
1921 if (Window
->hrgnUpdate
!= NULL
&& Window
->hrgnUpdate
!= HRGN_WINDOW
)
1923 NtGdiOffsetRgn(Window
->hrgnUpdate
,
1924 NewWindowRect
.left
- OldWindowRect
.left
,
1925 NewWindowRect
.top
- OldWindowRect
.top
);
1928 DceResetActiveDCEs(Window
); // For WS_VISIBLE changes.
1930 // Change or update, set send non-client paint flag.
1931 if ( Window
->style
& WS_VISIBLE
&&
1932 (WinPos
.flags
& SWP_STATECHANGED
|| (!(Window
->state2
& WNDS2_WIN31COMPAT
) && WinPos
.flags
& SWP_NOREDRAW
) ) )
1934 TRACE("Set WNDS_SENDNCPAINT %p\n",Window
);
1935 Window
->state
|= WNDS_SENDNCPAINT
;
1938 if (!(WinPos
.flags
& SWP_NOREDRAW
))
1940 /* Determine the new visible region */
1941 VisAfter
= VIS_ComputeVisibleRegion(Window
, FALSE
, FALSE
,
1942 (Window
->style
& WS_CLIPSIBLINGS
) ? TRUE
: FALSE
);
1944 if ( VisAfter
!= NULL
&&
1945 REGION_Complexity(VisAfter
) == NULLREGION
)
1947 REGION_Delete(VisAfter
);
1952 REGION_bOffsetRgn(VisAfter
, -Window
->rcWindow
.left
, -Window
->rcWindow
.top
);
1956 * Determine which pixels can be copied from the old window position
1957 * to the new. Those pixels must be visible in both the old and new
1958 * position. Also, check the class style to see if the windows of this
1959 * class need to be completely repainted on (horizontal/vertical) size
1962 if ( ( VisBefore
!= NULL
&&
1964 !(WinPos
.flags
& SWP_NOCOPYBITS
) &&
1965 ((WinPos
.flags
& SWP_NOSIZE
) || !(WvrFlags
& WVR_REDRAW
)) &&
1966 !(Window
->ExStyle
& WS_EX_TRANSPARENT
) ) )
1970 * If this is (also) a window resize, the whole nonclient area
1971 * needs to be repainted. So we limit the copy to the client area,
1972 * 'cause there is no use in copying it (would possibly cause
1973 * "flashing" too). However, if the copy region is already empty,
1974 * we don't have to crop (can't take anything away from an empty
1978 CopyRgn
= IntSysCreateRectpRgn(0, 0, 0, 0);
1979 if ((WinPos
.flags
& SWP_NOSIZE
) && (WinPos
.flags
& SWP_NOCLIENTSIZE
))
1980 RgnType
= IntGdiCombineRgn(CopyRgn
, VisAfter
, VisBefore
, RGN_AND
);
1981 else if (VisBeforeJustClient
!= NULL
)
1983 RgnType
= IntGdiCombineRgn(CopyRgn
, VisAfter
, VisBeforeJustClient
, RGN_AND
);
1986 if (VisBeforeJustClient
!= NULL
)
1988 REGION_Delete(VisBeforeJustClient
);
1991 /* Now use in copying bits which are in the update region. */
1992 if (Window
->hrgnUpdate
!= NULL
)
1994 PREGION RgnUpdate
= REGION_LockRgn(Window
->hrgnUpdate
);
1997 REGION_bOffsetRgn(CopyRgn
, NewWindowRect
.left
, NewWindowRect
.top
);
1998 IntGdiCombineRgn(CopyRgn
, CopyRgn
, RgnUpdate
, RGN_DIFF
);
1999 REGION_bOffsetRgn(CopyRgn
, -NewWindowRect
.left
, -NewWindowRect
.top
);
2000 REGION_UnlockRgn(RgnUpdate
);
2005 * Now, get the bounding box of the copy region. If it's empty
2006 * there's nothing to copy. Also, it's no use copying bits onto
2009 if (REGION_GetRgnBox(CopyRgn
, &CopyRect
) == NULLREGION
)
2011 /* Nothing to copy, clean up */
2012 REGION_Delete(CopyRgn
);
2015 else if ( OldWindowRect
.left
!= NewWindowRect
.left
||
2016 OldWindowRect
.top
!= NewWindowRect
.top
||
2017 (WinPos
.flags
& SWP_FRAMECHANGED
) )
2019 HRGN DcRgn
= NtGdiCreateRectRgn(0, 0, 0, 0);
2020 PREGION DcRgnObj
= REGION_LockRgn(DcRgn
);
2023 * Small trick here: there is no function to bitblt a region. So
2024 * we set the region as the clipping region, take the bounding box
2025 * of the region and bitblt that. Since nothing outside the clipping
2026 * region is copied, this has the effect of bitblt'ing the region.
2028 * Since NtUserGetDCEx takes ownership of the clip region, we need
2029 * to create a copy of CopyRgn and pass that. We need CopyRgn later
2031 IntGdiCombineRgn(DcRgnObj
, CopyRgn
, NULL
, RGN_COPY
);
2032 REGION_bOffsetRgn(DcRgnObj
, NewWindowRect
.left
, NewWindowRect
.top
);
2033 REGION_UnlockRgn(DcRgnObj
);
2034 Dc
= UserGetDCEx( Window
,
2036 DCX_WINDOW
|DCX_CACHE
|DCX_INTERSECTRGN
|DCX_CLIPSIBLINGS
|DCX_KEEPCLIPRGN
); // DCX_WINDOW will set first, go read WinDC.c.
2038 CopyRect
.left
, CopyRect
.top
,
2039 CopyRect
.right
- CopyRect
.left
,
2040 CopyRect
.bottom
- CopyRect
.top
,
2042 CopyRect
.left
+ (OldWindowRect
.left
- NewWindowRect
.left
),
2043 CopyRect
.top
+ (OldWindowRect
.top
- NewWindowRect
.top
),
2048 UserReleaseDC(Window
, Dc
, FALSE
);
2049 IntValidateParent(Window
, CopyRgn
);
2050 GreDeleteObject(DcRgn
);
2058 /* We need to redraw what wasn't visible before or force a redraw */
2059 if (VisAfter
!= NULL
)
2061 PREGION DirtyRgn
= IntSysCreateRectpRgn(0, 0, 0, 0);
2064 if (CopyRgn
!= NULL
)
2066 RgnType
= IntGdiCombineRgn(DirtyRgn
, VisAfter
, CopyRgn
, RGN_DIFF
);
2070 RgnType
= IntGdiCombineRgn(DirtyRgn
, VisAfter
, 0, RGN_COPY
);
2073 if (RgnType
!= ERROR
&& RgnType
!= NULLREGION
) // Regions moved.
2076 NtGdiOffsetRgn(DirtyRgn, Window->rcWindow.left, Window->rcWindow.top);
2077 IntInvalidateWindows( Window,
2079 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
2081 GreDeleteObject(DirtyRgn);
2084 PWND Parent
= Window
->spwndParent
;
2086 REGION_bOffsetRgn( DirtyRgn
, Window
->rcWindow
.left
, Window
->rcWindow
.top
);
2088 if ( (Window
->style
& WS_CHILD
) && (Parent
) && !(Parent
->style
& WS_CLIPCHILDREN
))
2090 IntInvalidateWindows( Parent
, DirtyRgn
, RDW_ERASE
| RDW_INVALIDATE
);
2091 co_IntPaintWindows(Parent
, RDW_NOCHILDREN
, FALSE
);
2095 IntInvalidateWindows( Window
, DirtyRgn
, RDW_ERASE
| RDW_FRAME
| RDW_INVALIDATE
| RDW_ALLCHILDREN
);
2098 else if ( RgnType
!= ERROR
&& RgnType
== NULLREGION
) // Must be the same. See CORE-7166 & CORE-15934, NC HACK fix.
2101 !(WinPos
.flags
& SWP_DEFERERASE
) &&
2102 (WinPos
.flags
& SWP_FRAMECHANGED
) )
2105 PWND Parent
= Window
->spwndParent
;
2107 if ( pwnd
->style
& WS_CHILD
) // Fix ProgMan menu bar drawing.
2109 TRACE("SWP_FRAMECHANGED win child %p Parent %p\n",pwnd
,Parent
);
2110 pwnd
= Parent
? Parent
: pwnd
;
2113 if ( !(pwnd
->style
& WS_CHILD
) )
2115 HRGN DcRgn
= NtGdiCreateRectRgn(0, 0, 0, 0);
2116 PREGION DcRgnObj
= REGION_LockRgn(DcRgn
);
2117 TRACE("SWP_FRAMECHANGED win %p hRgn %p\n",pwnd
, DcRgn
);
2118 IntGdiCombineRgn(DcRgnObj
, VisBefore
, NULL
, RGN_COPY
);
2119 REGION_UnlockRgn(DcRgnObj
);
2120 ForceNCPaintErase(pwnd
, DcRgn
, DcRgnObj
);
2121 GreDeleteObject(DcRgn
);
2125 REGION_Delete(DirtyRgn
);
2129 if (CopyRgn
!= NULL
)
2131 REGION_Delete(CopyRgn
);
2134 /* Expose what was covered before but not covered anymore */
2135 if ( VisBefore
!= NULL
)
2137 PREGION ExposedRgn
= IntSysCreateRectpRgn(0, 0, 0, 0);
2140 RgnType
= IntGdiCombineRgn(ExposedRgn
, VisBefore
, NULL
, RGN_COPY
);
2141 REGION_bOffsetRgn(ExposedRgn
,
2142 OldWindowRect
.left
- NewWindowRect
.left
,
2143 OldWindowRect
.top
- NewWindowRect
.top
);
2145 if ( VisAfter
!= NULL
)
2146 RgnType
= IntGdiCombineRgn(ExposedRgn
, ExposedRgn
, VisAfter
, RGN_DIFF
);
2148 if (RgnType
!= ERROR
&& RgnType
!= NULLREGION
)
2150 co_VIS_WindowLayoutChanged(Window
, ExposedRgn
);
2152 REGION_Delete(ExposedRgn
);
2154 REGION_Delete(VisBefore
);
2157 if (VisAfter
!= NULL
)
2159 REGION_Delete(VisAfter
);
2163 if (!(WinPos
.flags
& (SWP_NOACTIVATE
|SWP_HIDEWINDOW
)))
2165 if ((Window
->style
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
2167 co_IntSendMessageNoWait(WinPos
.hwnd
, WM_CHILDACTIVATE
, 0, 0);
2171 //ERR("SetWindowPos Set FG Window!\n");
2172 if ( pti
->MessageQueue
->spwndActive
!= Window
||
2173 pti
->MessageQueue
!= gpqForeground
)
2175 //ERR("WPSWP : set active window\n");
2176 if (!(Window
->state
& WNDS_BEINGACTIVATED
)) // Inside SAW?
2178 co_IntSetForegroundWindow(Window
); // Fixes SW_HIDE issues. Wine win test_SetActiveWindow & test_SetForegroundWindow.
2185 (WinPos
.flags
& SWP_FRAMECHANGED
) &&
2186 !(WinPos
.flags
& SWP_DEFERERASE
) && // Prevent sending WM_SYNCPAINT message.
2189 PWND Parent
= Window
->spwndParent
;
2190 if ( !(Window
->style
& WS_CHILD
) && (Parent
) && (Parent
->style
& WS_CLIPCHILDREN
))
2192 TRACE("SWP_FRAMECHANGED Parent %p WS_CLIPCHILDREN %p\n",Parent
,Window
);
2193 UserSyncAndPaintWindows( Parent
, RDW_CLIPCHILDREN
); // NC should redraw here, see NC HACK fix.
2197 // Fix wine msg test_SetFocus, prevents sending WM_WINDOWPOSCHANGED.
2198 if ( VisBefore
== NULL
&&
2199 VisBeforeJustClient
== NULL
&&
2200 !(Window
->ExStyle
& WS_EX_TOPMOST
) &&
2201 (WinPos
.flags
& SWP_AGG_STATUSFLAGS
) == (SWP_AGG_NOPOSCHANGE
& ~SWP_NOZORDER
))
2203 TRACE("No drawing, set no Z order and no redraw!\n");
2204 WinPos
.flags
|= SWP_NOZORDER
|SWP_NOREDRAW
;
2207 if(!(flags
& SWP_DEFERERASE
))
2209 /* erase parent when hiding or resizing child */
2210 if ((flags
& SWP_HIDEWINDOW
) ||
2211 (!(flags
& SWP_SHOWWINDOW
) &&
2212 (WinPos
.flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOGEOMETRYCHANGE
))
2214 PWND Parent
= Window
->spwndParent
;
2215 if (!Parent
|| UserIsDesktopWindow(Parent
)) Parent
= Window
;
2216 UserSyncAndPaintWindows( Parent
, RDW_ERASENOW
);
2219 /* Give newly shown windows a chance to redraw */
2220 if(((WinPos
.flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOPOSCHANGE
)
2221 && !(flags
& SWP_AGG_NOCLIENTCHANGE
) && (flags
& SWP_SHOWWINDOW
))
2223 UserSyncAndPaintWindows( Window
, RDW_ERASENOW
);
2227 /* And last, send the WM_WINDOWPOSCHANGED message */
2229 TRACE("\tstatus hwnd %p flags = %04x\n",Window
?Window
->head
.h
:NULL
,WinPos
.flags
& SWP_AGG_STATUSFLAGS
);
2231 if (((WinPos
.flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOPOSCHANGE
)
2232 && !((flags
& SWP_AGG_NOCLIENTCHANGE
) && (flags
& SWP_SHOWWINDOW
)))
2234 /* WM_WINDOWPOSCHANGED is sent even if SWP_NOSENDCHANGING is set
2235 and always contains final window position.
2237 WinPos
.x
= NewWindowRect
.left
;
2238 WinPos
.y
= NewWindowRect
.top
;
2239 WinPos
.cx
= NewWindowRect
.right
- NewWindowRect
.left
;
2240 WinPos
.cy
= NewWindowRect
.bottom
- NewWindowRect
.top
;
2241 TRACE("WM_WINDOWPOSCHANGED hwnd %p Flags %04x\n",WinPos
.hwnd
,WinPos
.flags
);
2242 co_IntSendMessageNoWait(WinPos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
) &WinPos
);
2245 if ( WinPos
.flags
& SWP_FRAMECHANGED
|| WinPos
.flags
& SWP_STATECHANGED
||
2246 !(WinPos
.flags
& SWP_NOCLIENTSIZE
) || !(WinPos
.flags
& SWP_NOCLIENTMOVE
) )
2248 PWND pWnd
= ValidateHwndNoErr(WinPos
.hwnd
);
2250 IntNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE
, pWnd
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
2253 if(bPointerInWindow
!= IntPtInWindow(Window
, gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
))
2255 /* Generate mouse move message */
2257 msg
.message
= WM_MOUSEMOVE
;
2258 msg
.wParam
= UserGetMouseButtonsState();
2259 msg
.lParam
= MAKELPARAM(gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
);
2260 msg
.pt
= gpsi
->ptCursor
;
2261 co_MsqInsertMouseMessage(&msg
, 0, 0, TRUE
);
2268 co_WinPosGetNonClientSize(PWND Window
, RECT
* WindowRect
, RECT
* ClientRect
)
2272 ASSERT_REFS_CO(Window
);
2274 *ClientRect
= *WindowRect
;
2275 Result
= co_IntSendMessageNoWait(Window
->head
.h
, WM_NCCALCSIZE
, FALSE
, (LPARAM
) ClientRect
);
2277 FixClientRect(ClientRect
, WindowRect
);
2283 co_WinPosSendSizeMove(PWND Wnd
)
2287 WPARAM wParam
= SIZE_RESTORED
;
2289 IntGetClientRect(Wnd
, &Rect
);
2290 lParam
= MAKELONG(Rect
.right
-Rect
.left
, Rect
.bottom
-Rect
.top
);
2292 Wnd
->state
&= ~WNDS_SENDSIZEMOVEMSGS
;
2294 if (Wnd
->style
& WS_MAXIMIZE
)
2296 wParam
= SIZE_MAXIMIZED
;
2298 else if (Wnd
->style
& WS_MINIMIZE
)
2300 wParam
= SIZE_MINIMIZED
;
2304 co_IntSendMessageNoWait(UserHMGetHandle(Wnd
), WM_SIZE
, wParam
, lParam
);
2306 if (UserIsDesktopWindow(Wnd
->spwndParent
))
2307 lParam
= MAKELONG(Wnd
->rcClient
.left
, Wnd
->rcClient
.top
);
2309 lParam
= MAKELONG(Wnd
->rcClient
.left
-Wnd
->spwndParent
->rcClient
.left
, Wnd
->rcClient
.top
-Wnd
->spwndParent
->rcClient
.top
);
2311 co_IntSendMessageNoWait(UserHMGetHandle(Wnd
), WM_MOVE
, 0, lParam
);
2313 IntEngWindowChanged(Wnd
, WOC_RGN_CLIENT
);
2317 co_WinPosMinMaximize(PWND Wnd
, UINT ShowFlag
, RECT
* NewPos
)
2320 WINDOWPLACEMENT wpl
;
2324 ASSERT_REFS_CO(Wnd
);
2326 wpl
.length
= sizeof(wpl
);
2327 IntGetWindowPlacement( Wnd
, &wpl
);
2329 if (co_HOOK_CallHooks( WH_CBT
, HCBT_MINMAX
, (WPARAM
)Wnd
->head
.h
, ShowFlag
))
2331 ERR("WinPosMinMaximize WH_CBT Call Hook return!\n");
2332 return SWP_NOSIZE
| SWP_NOMOVE
;
2334 if (Wnd
->style
& WS_MINIMIZE
)
2339 case SW_SHOWMINNOACTIVE
:
2340 case SW_SHOWMINIMIZED
:
2341 case SW_FORCEMINIMIZE
:
2342 return SWP_NOSIZE
| SWP_NOMOVE
;
2344 if (!co_IntSendMessageNoWait(Wnd
->head
.h
, WM_QUERYOPEN
, 0, 0))
2346 return(SWP_NOSIZE
| SWP_NOMOVE
);
2348 SwpFlags
|= SWP_NOCOPYBITS
;
2353 case SW_SHOWMINNOACTIVE
:
2354 case SW_SHOWMINIMIZED
:
2355 case SW_FORCEMINIMIZE
:
2357 //ERR("MinMaximize Minimize\n");
2358 if (Wnd
->style
& WS_MAXIMIZE
)
2360 Wnd
->InternalPos
.flags
|= WPF_RESTORETOMAXIMIZED
;
2364 Wnd
->InternalPos
.flags
&= ~WPF_RESTORETOMAXIMIZED
;
2367 old_style
= IntSetStyle( Wnd
, WS_MINIMIZE
, WS_MAXIMIZE
);
2369 co_UserRedrawWindow(Wnd
, NULL
, 0, RDW_VALIDATE
| RDW_NOERASE
| RDW_NOINTERNALPAINT
);
2371 if (!(Wnd
->InternalPos
.flags
& WPF_SETMINPOSITION
))
2372 Wnd
->InternalPos
.flags
&= ~WPF_MININIT
;
2374 WinPosFindIconPos(Wnd
, &wpl
.ptMinPosition
);
2376 if (!(old_style
& WS_MINIMIZE
))
2378 SwpFlags
|= SWP_STATECHANGED
;
2379 IntShowOwnedPopups(Wnd
, FALSE
);
2382 RECTL_vSetRect(NewPos
, wpl
.ptMinPosition
.x
, wpl
.ptMinPosition
.y
,
2383 wpl
.ptMinPosition
.x
+ UserGetSystemMetrics(SM_CXMINIMIZED
),
2384 wpl
.ptMinPosition
.y
+ UserGetSystemMetrics(SM_CYMINIMIZED
));
2385 SwpFlags
|= SWP_NOCOPYBITS
;
2391 //ERR("MinMaximize Maximize\n");
2392 if ((Wnd
->style
& WS_MAXIMIZE
) && (Wnd
->style
& WS_VISIBLE
))
2394 SwpFlags
= SWP_NOSIZE
| SWP_NOMOVE
;
2397 co_WinPosGetMinMaxInfo(Wnd
, &Size
, &wpl
.ptMaxPosition
, NULL
, NULL
);
2399 /*ERR("Maximize: %d,%d %dx%d\n",
2400 wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, Size.x, Size.y);
2402 old_style
= IntSetStyle( Wnd
, WS_MAXIMIZE
, WS_MINIMIZE
);
2403 /*if (old_style & WS_MINIMIZE)
2405 IntShowOwnedPopups(Wnd, TRUE);
2408 if (!(old_style
& WS_MAXIMIZE
)) SwpFlags
|= SWP_STATECHANGED
;
2409 RECTL_vSetRect(NewPos
, wpl
.ptMaxPosition
.x
, wpl
.ptMaxPosition
.y
,
2410 //wpl.ptMaxPosition.x + Size.x, wpl.ptMaxPosition.y + Size.y);
2415 case SW_SHOWNOACTIVATE
:
2416 Wnd
->InternalPos
.flags
&= ~WPF_RESTORETOMAXIMIZED
;
2420 case SW_SHOWDEFAULT
: /* FIXME: should have its own handler */
2422 //ERR("MinMaximize Restore\n");
2423 old_style
= IntSetStyle( Wnd
, 0, WS_MINIMIZE
| WS_MAXIMIZE
);
2424 if (old_style
& WS_MINIMIZE
)
2426 IntShowOwnedPopups(Wnd
, TRUE
);
2428 if (Wnd
->InternalPos
.flags
& WPF_RESTORETOMAXIMIZED
)
2430 co_WinPosGetMinMaxInfo(Wnd
, &Size
, &wpl
.ptMaxPosition
, NULL
, NULL
);
2431 IntSetStyle( Wnd
, WS_MAXIMIZE
, 0 );
2432 SwpFlags
|= SWP_STATECHANGED
;
2433 RECTL_vSetRect(NewPos
, wpl
.ptMaxPosition
.x
, wpl
.ptMaxPosition
.y
,
2434 wpl
.ptMaxPosition
.x
+ Size
.x
, wpl
.ptMaxPosition
.y
+ Size
.y
);
2439 *NewPos
= wpl
.rcNormalPosition
;
2440 NewPos
->right
-= NewPos
->left
;
2441 NewPos
->bottom
-= NewPos
->top
;
2447 if (!(old_style
& WS_MAXIMIZE
))
2451 SwpFlags
|= SWP_STATECHANGED
;
2452 Wnd
->InternalPos
.flags
&= ~WPF_RESTORETOMAXIMIZED
;
2453 *NewPos
= wpl
.rcNormalPosition
;
2454 NewPos
->right
-= NewPos
->left
;
2455 NewPos
->bottom
-= NewPos
->top
;
2464 ShowWindow does not set SWP_FRAMECHANGED!!! Fix wine msg test_SetParent:WmSetParentSeq_2:23 wParam bits!
2467 co_WinPosShowWindow(PWND Wnd
, INT Cmd
)
2470 UINT Swp
= 0, EventMsg
= 0;
2471 RECTL NewPos
= {0, 0, 0, 0};
2477 BOOL ShowOwned
= FALSE
;
2478 BOOL FirstTime
= FALSE
;
2479 ASSERT_REFS_CO(Wnd
);
2480 //KeRosDumpStackFrames(NULL, 20);
2481 pti
= PsGetCurrentThreadWin32Thread();
2482 WasVisible
= (Wnd
->style
& WS_VISIBLE
) != 0;
2485 TRACE("co_WinPosShowWindow START hwnd %p Cmd %d usicmd %u\n",
2486 Wnd
->head
.h
, Cmd
, pti
->ppi
->usi
.wShowWindow
);
2488 if ( pti
->ppi
->usi
.dwFlags
& STARTF_USESHOWWINDOW
)
2490 if ((Wnd
->style
& (WS_POPUP
|WS_CHILD
)) != WS_CHILD
)
2492 if ((Wnd
->style
& WS_CAPTION
) == WS_CAPTION
)
2494 if (Wnd
->spwndOwner
== NULL
)
2496 if ( Cmd
== SW_SHOWNORMAL
|| Cmd
== SW_SHOW
)
2498 Cmd
= SW_SHOWDEFAULT
;
2501 TRACE("co_WPSW FT 1\n");
2507 if ( Cmd
== SW_SHOWDEFAULT
)
2509 if ( pti
->ppi
->usi
.dwFlags
& STARTF_USESHOWWINDOW
)
2511 Cmd
= pti
->ppi
->usi
.wShowWindow
;
2513 TRACE("co_WPSW FT 2\n");
2519 pti
->ppi
->usi
.dwFlags
&= ~(STARTF_USEPOSITION
|STARTF_USESIZE
|STARTF_USESHOWWINDOW
);
2528 //ERR("co_WinPosShowWindow Exit Bad\n");
2531 Swp
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
2532 if (Wnd
!= pti
->MessageQueue
->spwndActive
)
2533 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2537 case SW_FORCEMINIMIZE
: /* FIXME: Does not work if thread is hung. */
2538 case SW_SHOWMINNOACTIVE
:
2539 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2541 case SW_SHOWMINIMIZED
:
2542 Swp
|= SWP_SHOWWINDOW
;
2546 Swp
|= SWP_NOACTIVATE
;
2547 if (!(style
& WS_MINIMIZE
))
2549 IntShowOwnedPopups(Wnd
, FALSE
);
2550 // Fix wine Win test_SetFocus todo #1 & #2,
2551 if (Cmd
== SW_SHOWMINIMIZED
)
2553 //ERR("co_WinPosShowWindow Set focus 1\n");
2554 if ((style
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
2555 co_UserSetFocus(Wnd
->spwndParent
);
2560 Swp
|= co_WinPosMinMaximize(Wnd
, Cmd
, &NewPos
);
2562 EventMsg
= EVENT_SYSTEM_MINIMIZESTART
;
2568 //ERR("co_WinPosShowWindow Exit Good\n");
2571 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
2576 case SW_SHOWMAXIMIZED
:
2578 Swp
|= SWP_SHOWWINDOW
;
2579 if (!(style
& WS_MAXIMIZE
))
2583 Swp
|= co_WinPosMinMaximize(Wnd
, SW_MAXIMIZE
, &NewPos
);
2585 EventMsg
= EVENT_SYSTEM_MINIMIZEEND
;
2591 //ERR("co_WinPosShowWindow Exit Good 1\n");
2594 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
2600 Swp
|= SWP_NOACTIVATE
| SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
2601 if (style
& WS_CHILD
&& !(Wnd
->ExStyle
& WS_EX_MDICHILD
)) Swp
|= SWP_NOZORDER
;
2604 if (WasVisible
) return(TRUE
); // Nothing to do!
2605 Swp
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
2606 /* Don't activate the topmost window. */
2607 if (style
& WS_CHILD
&& !(Wnd
->ExStyle
& WS_EX_MDICHILD
)) Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2610 case SW_SHOWNOACTIVATE
:
2611 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2614 case SW_SHOWDEFAULT
:
2616 if (!WasVisible
) Swp
|= SWP_SHOWWINDOW
;
2617 if (style
& (WS_MINIMIZE
| WS_MAXIMIZE
))
2619 Swp
|= co_WinPosMinMaximize(Wnd
, Cmd
, &NewPos
);
2620 if (style
& WS_MINIMIZE
) EventMsg
= EVENT_SYSTEM_MINIMIZEEND
;
2626 //ERR("co_WinPosShowWindow Exit Good 3\n");
2629 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
2631 if ( style
& WS_CHILD
&&
2632 !(Wnd
->ExStyle
& WS_EX_MDICHILD
) &&
2633 !(Swp
& SWP_STATECHANGED
))
2634 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2638 //ERR("co_WinPosShowWindow Exit Good 4\n");
2642 ShowFlag
= (Cmd
!= SW_HIDE
);
2644 if ((ShowFlag
!= WasVisible
|| Cmd
== SW_SHOWNA
) && Cmd
!= SW_SHOWMAXIMIZED
&& !(Swp
& SWP_STATECHANGED
))
2646 co_IntSendMessageNoWait(Wnd
->head
.h
, WM_SHOWWINDOW
, ShowFlag
, 0);
2647 #if 0 // Fix wine msg test_SetParent:WmSetParentSeq_1:2
2648 if (!(Wnd
->state2
& WNDS2_WIN31COMPAT
)) // <------------- XP sets this bit!
2649 co_IntSendMessageNoWait(Wnd
->head
.h
, WM_SETVISIBLE
, ShowFlag
, 0);
2651 if (!VerifyWnd(Wnd
)) return WasVisible
;
2654 /* We can't activate a child window */
2655 if ((Wnd
->style
& WS_CHILD
) &&
2656 !(Wnd
->ExStyle
& WS_EX_MDICHILD
) &&
2659 //ERR("SWP Child No active and ZOrder\n");
2660 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2663 #if 0 // Explorer issues with common controls? Someone does not know how CS_SAVEBITS works.
2664 // Breaks startup and shutdown active window...
2665 if ((Wnd
->style
& (WS_POPUP
|WS_CHILD
)) != WS_CHILD
&&
2666 Wnd
->pcls
->style
& CS_SAVEBITS
&&
2667 ((Cmd
== SW_SHOW
) || (Cmd
== SW_NORMAL
)))
2669 ERR("WinPosShowWindow Set active\n");
2670 //UserSetActiveWindow(Wnd);
2671 co_IntSetForegroundWindow(Wnd
); // HACK
2672 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2676 if (IsChildVisible(Wnd
) || Swp
& SWP_STATECHANGED
)
2678 TRACE("Child is Vis %s or State changed %s. ShowFlag %s Swp %04x\n",
2679 (IsChildVisible(Wnd
) ? "TRUE" : "FALSE"), (Swp
& SWP_STATECHANGED
? "TRUE" : "FALSE"),
2680 (ShowFlag
? "TRUE" : "FALSE"),LOWORD(Swp
));
2681 co_WinPosSetWindowPos( Wnd
,
2682 0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
) ? HWND_TOPMOST
: HWND_TOP
,
2685 NewPos
.right
, // NewPos.right - NewPos.left, when minimized and restore, the window becomes smaller.
2686 NewPos
.bottom
,// NewPos.bottom - NewPos.top,
2691 TRACE("Parent Vis?\n");
2692 /* if parent is not visible simply toggle WS_VISIBLE and return */
2693 if (ShowFlag
) IntSetStyle( Wnd
, WS_VISIBLE
, 0 );
2694 else IntSetStyle( Wnd
, 0, WS_VISIBLE
);
2697 if ( EventMsg
) IntNotifyWinEvent(EventMsg
, Wnd
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
2699 if ( ShowOwned
) IntShowOwnedPopups(Wnd
, TRUE
);
2701 if ((Cmd
== SW_HIDE
) || (Cmd
== SW_MINIMIZE
))
2703 if ( Wnd
== pti
->MessageQueue
->spwndActive
&& pti
->MessageQueue
== IntGetFocusMessageQueue() )
2705 if (UserIsDesktopWindow(Wnd
->spwndParent
))
2707 if (!ActivateOtherWindowMin(Wnd
))
2709 co_WinPosActivateOtherWindow(Wnd
);
2714 co_WinPosActivateOtherWindow(Wnd
);
2718 /* Revert focus to parent */
2719 if (Wnd
== pti
->MessageQueue
->spwndFocus
)
2721 Parent
= Wnd
->spwndParent
;
2722 if (UserIsDesktopWindow(Wnd
->spwndParent
))
2724 co_UserSetFocus(Parent
);
2726 // Hide, just return.
2727 if (Cmd
== SW_HIDE
) return WasVisible
;
2730 /* FIXME: Check for window destruction. */
2732 if ((Wnd
->state
& WNDS_SENDSIZEMOVEMSGS
) &&
2733 !(Wnd
->state2
& WNDS2_INDESTROY
))
2735 co_WinPosSendSizeMove(Wnd
);
2738 /* if previous state was minimized Windows sets focus to the window */
2739 if (style
& WS_MINIMIZE
)
2741 co_UserSetFocus(Wnd
);
2742 // Fix wine Win test_SetFocus todo #3,
2743 if (!(style
& WS_CHILD
)) co_IntSendMessage(UserHMGetHandle(Wnd
), WM_ACTIVATE
, WA_ACTIVE
, 0);
2745 //ERR("co_WinPosShowWindow EXIT\n");
2750 co_WinPosSearchChildren(
2753 IN OUT USHORT
*HitTest
,
2758 PWND pwndChild
= NULL
;
2761 if (!(ScopeWin
->style
& WS_VISIBLE
))
2766 /* not in window or in window region */
2767 if (!IntPtInWindow(ScopeWin
, Point
->x
, Point
->y
))
2773 if ((ScopeWin
->ExStyle
& (WS_EX_LAYERED
|WS_EX_TRANSPARENT
)) == (WS_EX_LAYERED
|WS_EX_TRANSPARENT
))
2778 if (!Ignore
&& (ScopeWin
->style
& WS_DISABLED
))
2779 { /* disabled child */
2780 if ((ScopeWin
->style
& (WS_POPUP
|WS_CHILD
)) == WS_CHILD
) return NULL
;
2781 /* process the hit error */
2786 /* not minimized and check if point is inside the window */
2787 if (!(ScopeWin
->style
& WS_MINIMIZE
) &&
2788 RECTL_bPointInRect(&ScopeWin
->rcClient
, Point
->x
, Point
->y
) )
2790 UserReferenceObject(ScopeWin
);
2792 List
= IntWinListChildren(ScopeWin
);
2795 for (phWnd
= List
; *phWnd
; ++phWnd
)
2797 if (!(pwndChild
= ValidateHwndNoErr(*phWnd
)))
2802 pwndChild
= co_WinPosSearchChildren(pwndChild
, Point
, HitTest
, Ignore
);
2804 if (pwndChild
!= NULL
)
2806 /* We found a window. Don't send any more WM_NCHITTEST messages */
2807 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2808 UserDereferenceObject(ScopeWin
);
2812 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2814 UserDereferenceObject(ScopeWin
);
2817 if (ScopeWin
->head
.pti
== PsGetCurrentThreadWin32Thread())
2819 *HitTest
= (USHORT
)co_IntSendMessage(ScopeWin
->head
.h
, WM_NCHITTEST
, 0, MAKELONG(Point
->x
, Point
->y
));
2821 if ((*HitTest
) == (USHORT
)HTTRANSPARENT
)
2828 if (*HitTest
== HTNOWHERE
&& pwndChild
== NULL
) *HitTest
= HTCLIENT
;
2835 co_WinPosWindowFromPoint(
2838 IN OUT USHORT
* HitTest
,
2842 POINT Point
= *WinPoint
;
2843 USER_REFERENCE_ENTRY Ref
;
2845 if( ScopeWin
== NULL
)
2847 ScopeWin
= UserGetDesktopWindow();
2848 if(ScopeWin
== NULL
)
2852 *HitTest
= HTNOWHERE
;
2854 ASSERT_REFS_CO(ScopeWin
);
2855 UserRefObjectCo(ScopeWin
, &Ref
);
2857 Window
= co_WinPosSearchChildren(ScopeWin
, &Point
, HitTest
, Ignore
);
2859 UserDerefObjectCo(ScopeWin
);
2861 ASSERT_REFS_CO(Window
);
2862 ASSERT_REFS_CO(ScopeWin
);
2868 IntRealChildWindowFromPoint(PWND Parent
, LONG x
, LONG y
)
2872 PWND pwndHit
= NULL
;
2877 if (!UserIsDesktopWindow(Parent
))
2879 Pt
.x
+= Parent
->rcClient
.left
;
2880 Pt
.y
+= Parent
->rcClient
.top
;
2883 if (!IntPtInWindow(Parent
, Pt
.x
, Pt
.y
)) return NULL
;
2885 if ((List
= IntWinListChildren(Parent
)))
2887 for (phWnd
= List
; *phWnd
; phWnd
++)
2890 if ((Child
= ValidateHwndNoErr(*phWnd
)))
2892 if ( Child
->style
& WS_VISIBLE
&& IntPtInWindow(Child
, Pt
.x
, Pt
.y
) )
2894 if ( Child
->pcls
->atomClassName
!= gpsi
->atomSysClass
[ICLS_BUTTON
] ||
2895 (Child
->style
& BS_TYPEMASK
) != BS_GROUPBOX
)
2897 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2904 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2906 return pwndHit
? pwndHit
: Parent
;
2910 IntChildWindowFromPointEx(PWND Parent
, LONG x
, LONG y
, UINT uiFlags
)
2914 PWND pwndHit
= NULL
;
2919 if (!UserIsDesktopWindow(Parent
))
2921 if (Parent
->ExStyle
& WS_EX_LAYOUTRTL
)
2922 Pt
.x
= Parent
->rcClient
.right
- Pt
.x
;
2924 Pt
.x
+= Parent
->rcClient
.left
;
2925 Pt
.y
+= Parent
->rcClient
.top
;
2928 if (!IntPtInWindow(Parent
, Pt
.x
, Pt
.y
)) return NULL
;
2930 if ((List
= IntWinListChildren(Parent
)))
2932 for (phWnd
= List
; *phWnd
; phWnd
++)
2935 if ((Child
= ValidateHwndNoErr(*phWnd
)))
2937 if (uiFlags
& (CWP_SKIPINVISIBLE
|CWP_SKIPDISABLED
))
2939 if (!(Child
->style
& WS_VISIBLE
) && (uiFlags
& CWP_SKIPINVISIBLE
)) continue;
2940 if ((Child
->style
& WS_DISABLED
) && (uiFlags
& CWP_SKIPDISABLED
)) continue;
2943 if (uiFlags
& CWP_SKIPTRANSPARENT
)
2945 if (Child
->ExStyle
& WS_EX_TRANSPARENT
) continue;
2948 if (IntPtInWindow(Child
, Pt
.x
, Pt
.y
))
2955 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2957 return pwndHit
? pwndHit
: Parent
;
2962 IntDeferWindowPos( HDWP hdwp
,
2973 HDWP retvalue
= hdwp
;
2975 TRACE("hdwp %p, hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
2976 hdwp
, hwnd
, hwndAfter
, x
, y
, cx
, cy
, flags
);
2978 if (flags
& ~(SWP_NOSIZE
| SWP_NOMOVE
|
2979 SWP_NOZORDER
| SWP_NOREDRAW
|
2980 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
2981 SWP_NOOWNERZORDER
|SWP_SHOWWINDOW
|
2982 SWP_HIDEWINDOW
| SWP_FRAMECHANGED
))
2984 EngSetLastError(ERROR_INVALID_PARAMETER
);
2988 if (!(pDWP
= (PSMWP
)UserGetObject(gHandleTable
, hdwp
, TYPE_SETWINDOWPOS
)))
2990 EngSetLastError(ERROR_INVALID_DWP_HANDLE
);
2994 for (i
= 0; i
< pDWP
->ccvr
; i
++)
2996 if (pDWP
->acvr
[i
].pos
.hwnd
== hwnd
)
2998 /* Merge with the other changes */
2999 if (!(flags
& SWP_NOZORDER
))
3001 pDWP
->acvr
[i
].pos
.hwndInsertAfter
= hwndAfter
;
3003 if (!(flags
& SWP_NOMOVE
))
3005 pDWP
->acvr
[i
].pos
.x
= x
;
3006 pDWP
->acvr
[i
].pos
.y
= y
;
3008 if (!(flags
& SWP_NOSIZE
))
3010 pDWP
->acvr
[i
].pos
.cx
= cx
;
3011 pDWP
->acvr
[i
].pos
.cy
= cy
;
3013 pDWP
->acvr
[i
].pos
.flags
&= flags
| ~(SWP_NOSIZE
| SWP_NOMOVE
|
3014 SWP_NOZORDER
| SWP_NOREDRAW
|
3015 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
3017 pDWP
->acvr
[i
].pos
.flags
|= flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
|
3022 if (pDWP
->ccvr
>= pDWP
->ccvrAlloc
)
3024 PCVR newpos
= ExAllocatePoolWithTag(PagedPool
, pDWP
->ccvrAlloc
* 2 * sizeof(CVR
), USERTAG_SWP
);
3030 RtlZeroMemory(newpos
, pDWP
->ccvrAlloc
* 2 * sizeof(CVR
));
3031 RtlCopyMemory(newpos
, pDWP
->acvr
, pDWP
->ccvrAlloc
* sizeof(CVR
));
3032 ExFreePoolWithTag(pDWP
->acvr
, USERTAG_SWP
);
3033 pDWP
->ccvrAlloc
*= 2;
3034 pDWP
->acvr
= newpos
;
3036 pDWP
->acvr
[pDWP
->ccvr
].pos
.hwnd
= hwnd
;
3037 pDWP
->acvr
[pDWP
->ccvr
].pos
.hwndInsertAfter
= hwndAfter
;
3038 pDWP
->acvr
[pDWP
->ccvr
].pos
.x
= x
;
3039 pDWP
->acvr
[pDWP
->ccvr
].pos
.y
= y
;
3040 pDWP
->acvr
[pDWP
->ccvr
].pos
.cx
= cx
;
3041 pDWP
->acvr
[pDWP
->ccvr
].pos
.cy
= cy
;
3042 pDWP
->acvr
[pDWP
->ccvr
].pos
.flags
= flags
;
3043 pDWP
->acvr
[pDWP
->ccvr
].hrgnClip
= NULL
;
3044 pDWP
->acvr
[pDWP
->ccvr
].hrgnInterMonitor
= NULL
;
3050 BOOL FASTCALL
IntEndDeferWindowPosEx( HDWP hdwp
, BOOL sAsync
)
3057 TRACE("%p\n", hdwp
);
3059 if (!(pDWP
= (PSMWP
)UserGetObject(gHandleTable
, hdwp
, TYPE_SETWINDOWPOS
)))
3061 EngSetLastError(ERROR_INVALID_DWP_HANDLE
);
3065 for (i
= 0, winpos
= pDWP
->acvr
; res
&& i
< pDWP
->ccvr
; i
++, winpos
++)
3068 USER_REFERENCE_ENTRY Ref
;
3070 TRACE("hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
3071 winpos
->pos
.hwnd
, winpos
->pos
.hwndInsertAfter
, winpos
->pos
.x
, winpos
->pos
.y
,
3072 winpos
->pos
.cx
, winpos
->pos
.cy
, winpos
->pos
.flags
);
3074 pwnd
= ValidateHwndNoErr(winpos
->pos
.hwnd
);
3078 UserRefObjectCo(pwnd
, &Ref
);
3083 PWINDOWPOS ppos
= ExAllocatePoolWithTag(PagedPool
, sizeof(WINDOWPOS
), USERTAG_SWP
);
3086 *ppos
= winpos
->pos
;
3087 /* Yes it's a pointer inside Win32k! */
3088 lRes
= co_IntSendMessageNoWait( winpos
->pos
.hwnd
, WM_ASYNC_SETWINDOWPOS
, 0, (LPARAM
)ppos
);
3089 /* We handle this the same way as Event Hooks and Hooks. */
3092 ExFreePoolWithTag(ppos
, USERTAG_SWP
);
3097 res
= co_WinPosSetWindowPos( pwnd
,
3098 winpos
->pos
.hwndInsertAfter
,
3105 // Hack to pass tests.... Must have some work to do so clear the error.
3106 if (res
&& (winpos
->pos
.flags
& (SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOZORDER
)) == SWP_NOZORDER
)
3107 EngSetLastError(ERROR_SUCCESS
);
3109 UserDerefObjectCo(pwnd
);
3111 ExFreePoolWithTag(pDWP
->acvr
, USERTAG_SWP
);
3112 UserDereferenceObject(pDWP
);
3113 UserDeleteObject(hdwp
, TYPE_SETWINDOWPOS
);
3121 NtUserChildWindowFromPointEx(HWND hwndParent
,
3127 TRACE("Enter NtUserChildWindowFromPointEx\n");
3128 UserEnterExclusive();
3129 if ((pwndParent
= UserGetWindowObject(hwndParent
)))
3131 pwndParent
= IntChildWindowFromPointEx(pwndParent
, x
, y
, uiFlags
);
3134 TRACE("Leave NtUserChildWindowFromPointEx\n");
3135 return pwndParent
? UserHMGetHandle(pwndParent
) : NULL
;
3142 NtUserEndDeferWindowPosEx(HDWP WinPosInfo
,
3146 TRACE("Enter NtUserEndDeferWindowPosEx\n");
3147 UserEnterExclusive();
3148 Ret
= IntEndDeferWindowPosEx(WinPosInfo
, (BOOL
)Unknown1
);
3149 TRACE("Leave NtUserEndDeferWindowPosEx, ret=%i\n", Ret
);
3158 NtUserDeferWindowPos(HDWP WinPosInfo
,
3160 HWND WndInsertAfter
,
3169 UINT Tmp
= ~(SWP_ASYNCWINDOWPOS
|SWP_DEFERERASE
|SWP_NOSENDCHANGING
|SWP_NOREPOSITION
|
3170 SWP_NOCOPYBITS
|SWP_HIDEWINDOW
|SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|
3171 SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_NOZORDER
|SWP_NOMOVE
|SWP_NOSIZE
);
3173 TRACE("Enter NtUserDeferWindowPos\n");
3174 UserEnterExclusive();
3178 EngSetLastError(ERROR_INVALID_FLAGS
);
3182 pWnd
= UserGetWindowObject(Wnd
);
3183 if (!pWnd
|| UserIsDesktopWindow(pWnd
) || UserIsMessageWindow(pWnd
))
3188 if ( WndInsertAfter
&&
3189 WndInsertAfter
!= HWND_BOTTOM
&&
3190 WndInsertAfter
!= HWND_TOPMOST
&&
3191 WndInsertAfter
!= HWND_NOTOPMOST
)
3193 pWndIA
= UserGetWindowObject(WndInsertAfter
);
3194 if (!pWndIA
|| UserIsDesktopWindow(pWndIA
) || UserIsMessageWindow(pWndIA
))
3200 Ret
= IntDeferWindowPos(WinPosInfo
, Wnd
, WndInsertAfter
, x
, y
, cx
, cy
, Flags
);
3203 TRACE("Leave NtUserDeferWindowPos, ret=%p\n", Ret
);
3212 NtUserGetInternalWindowPos( HWND hWnd
,
3219 WINDOWPLACEMENT wndpl
;
3223 if (!(Window
= UserGetWindowObject(hWnd
)))
3233 ProbeForWrite(rectWnd
,
3239 ProbeForWrite(ptIcon
,
3245 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3247 SetLastNtError(_SEH2_GetExceptionCode());
3252 wndpl
.length
= sizeof(WINDOWPLACEMENT
);
3254 if (IntGetWindowPlacement(Window
, &wndpl
) && !Hit
)
3260 RtlCopyMemory(rectWnd
, &wndpl
.rcNormalPosition
, sizeof(RECT
));
3264 RtlCopyMemory(ptIcon
, &wndpl
.ptMinPosition
, sizeof(POINT
));
3268 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3270 SetLastNtError(_SEH2_GetExceptionCode());
3275 if (!Hit
) Ret
= wndpl
.showCmd
;
3286 NtUserGetWindowPlacement(HWND hWnd
,
3287 WINDOWPLACEMENT
*lpwndpl
)
3290 WINDOWPLACEMENT Safepl
;
3292 DECLARE_RETURN(BOOL
);
3294 TRACE("Enter NtUserGetWindowPlacement\n");
3297 if (!(Wnd
= UserGetWindowObject(hWnd
)))
3302 Status
= MmCopyFromCaller(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
3303 if (!NT_SUCCESS(Status
))
3305 SetLastNtError(Status
);
3309 Safepl
.length
= sizeof(WINDOWPLACEMENT
);
3311 IntGetWindowPlacement(Wnd
, &Safepl
);
3313 Status
= MmCopyToCaller(lpwndpl
, &Safepl
, sizeof(WINDOWPLACEMENT
));
3314 if (!NT_SUCCESS(Status
))
3316 SetLastNtError(Status
);
3323 TRACE("Leave NtUserGetWindowPlacement, ret=%i\n",_ret_
);
3332 UINT cmd
, // Wine SW_ commands
3337 TRACE("Enter NtUserMinMaximize\n");
3338 UserEnterExclusive();
3340 pWnd
= UserGetWindowObject(hWnd
);
3341 if (!pWnd
|| UserIsDesktopWindow(pWnd
) || UserIsMessageWindow(pWnd
))
3346 if ( cmd
> SW_MAX
|| pWnd
->state2
& WNDS2_INDESTROY
)
3348 EngSetLastError(ERROR_INVALID_PARAMETER
);
3352 cmd
|= Hide
? SW_HIDE
: 0;
3354 co_WinPosShowWindow(pWnd
, cmd
);
3357 TRACE("Leave NtUserMinMaximize\n");
3359 return 0; // Always NULL?
3374 return NtUserSetWindowPos(hWnd
, 0, X
, Y
, nWidth
, nHeight
,
3375 (bRepaint
? SWP_NOZORDER
| SWP_NOACTIVATE
:
3376 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
));
3383 NtUserRealChildWindowFromPoint(HWND Parent
,
3388 TRACE("Enter NtUserRealChildWindowFromPoint\n");
3390 if ((pwndParent
= UserGetWindowObject(Parent
)))
3392 pwndParent
= IntRealChildWindowFromPoint(pwndParent
, x
, y
);
3395 TRACE("Leave NtUserRealChildWindowFromPoint\n");
3396 return pwndParent
? UserHMGetHandle(pwndParent
) : NULL
;
3405 HWND hWndInsertAfter
,
3412 DECLARE_RETURN(BOOL
);
3413 PWND Window
, pWndIA
;
3415 USER_REFERENCE_ENTRY Ref
;
3417 TRACE("Enter NtUserSetWindowPos\n");
3418 UserEnterExclusive();
3420 if (!(Window
= UserGetWindowObject(hWnd
)) ||
3421 UserIsDesktopWindow(Window
) || UserIsMessageWindow(Window
))
3423 ERR("NtUserSetWindowPos bad window handle!\n");
3427 if ( hWndInsertAfter
!= HWND_TOP
&&
3428 hWndInsertAfter
!= HWND_BOTTOM
&&
3429 hWndInsertAfter
!= HWND_TOPMOST
&&
3430 hWndInsertAfter
!= HWND_NOTOPMOST
)
3432 if (!(pWndIA
= UserGetWindowObject(hWndInsertAfter
)) ||
3433 UserIsDesktopWindow(pWndIA
) || UserIsMessageWindow(pWndIA
))
3435 ERR("NtUserSetWindowPos bad insert window handle!\n");
3440 /* First make sure that coordinates are valid for WM_WINDOWPOSCHANGING */
3441 if (!(uFlags
& SWP_NOMOVE
))
3443 if (X
< -32768) X
= -32768;
3444 else if (X
> 32767) X
= 32767;
3445 if (Y
< -32768) Y
= -32768;
3446 else if (Y
> 32767) Y
= 32767;
3448 if (!(uFlags
& SWP_NOSIZE
))
3451 else if (cx
> 32767) cx
= 32767;
3453 else if (cy
> 32767) cy
= 32767;
3456 UserRefObjectCo(Window
, &Ref
);
3457 ret
= co_WinPosSetWindowPos(Window
, hWndInsertAfter
, X
, Y
, cx
, cy
, uFlags
);
3458 UserDerefObjectCo(Window
);
3463 TRACE("Leave NtUserSetWindowPos, ret=%i\n",_ret_
);
3477 HRGN hrgnCopy
= NULL
;
3479 INT flags
= (SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
);
3480 BOOLEAN Ret
= FALSE
;
3481 DECLARE_RETURN(INT
);
3483 TRACE("Enter NtUserSetWindowRgn\n");
3484 UserEnterExclusive();
3486 if (!(Window
= UserGetWindowObject(hWnd
)) ||
3487 UserIsDesktopWindow(Window
) || UserIsMessageWindow(Window
))
3492 if (hRgn
) // The region will be deleted in user32.
3494 if (GreIsHandleValid(hRgn
))
3496 hrgnCopy
= NtGdiCreateRectRgn(0, 0, 0, 0);
3497 /* The coordinates of a window's window region are relative to the
3498 upper-left corner of the window, not the client area of the window. */
3499 NtGdiCombineRgn( hrgnCopy
, hRgn
, 0, RGN_COPY
);
3505 //// HACK 1 : Work around the lack of supporting DeferWindowPos.
3508 Window
->hrgnNewFrame
= hrgnCopy
; // Should be PSMWP->acvr->hrgnClip
3512 Window
->hrgnNewFrame
= HRGN_WINDOW
;
3515 Ret
= co_WinPosSetWindowPos(Window
, HWND_TOP
, 0, 0, 0, 0, bRedraw
? flags
: (flags
|SWP_NOREDRAW
) );
3520 TRACE("Leave NtUserSetWindowRgn, ret=%i\n",_ret_
);
3529 NtUserSetInternalWindowPos(
3535 WINDOWPLACEMENT wndpl
;
3540 DECLARE_RETURN(BOOL
);
3541 USER_REFERENCE_ENTRY Ref
;
3543 TRACE("Enter NtUserSetWindowPlacement\n");
3544 UserEnterExclusive();
3546 if (!(Wnd
= UserGetWindowObject(hwnd
)) || // FIXME:
3547 UserIsDesktopWindow(Wnd
) || UserIsMessageWindow(Wnd
))
3556 ProbeForRead(lppt
, sizeof(POINT
), 1);
3557 RtlCopyMemory(&pt
, lppt
, sizeof(POINT
));
3561 ProbeForRead(lprect
, sizeof(RECT
), 1);
3562 RtlCopyMemory(&rect
, lprect
, sizeof(RECT
));
3565 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3567 SetLastNtError(_SEH2_GetExceptionCode());
3568 _SEH2_YIELD(RETURN( FALSE
));
3572 wndpl
.length
= sizeof(wndpl
);
3573 wndpl
.showCmd
= showCmd
;
3574 wndpl
.flags
= flags
= 0;
3579 wndpl
.flags
|= WPF_SETMINPOSITION
;
3580 wndpl
.ptMinPosition
= pt
;
3584 flags
|= PLACE_RECT
;
3585 wndpl
.rcNormalPosition
= rect
;
3588 UserRefObjectCo(Wnd
, &Ref
);
3589 IntSetWindowPlacement(Wnd
, &wndpl
, flags
);
3590 UserDerefObjectCo(Wnd
);
3594 TRACE("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_
);
3603 NtUserSetWindowPlacement(HWND hWnd
,
3604 WINDOWPLACEMENT
*lpwndpl
)
3607 WINDOWPLACEMENT Safepl
;
3609 DECLARE_RETURN(BOOL
);
3610 USER_REFERENCE_ENTRY Ref
;
3612 TRACE("Enter NtUserSetWindowPlacement\n");
3613 UserEnterExclusive();
3615 if (!(Wnd
= UserGetWindowObject(hWnd
)) ||
3616 UserIsDesktopWindow(Wnd
) || UserIsMessageWindow(Wnd
))
3623 ProbeForRead(lpwndpl
, sizeof(WINDOWPLACEMENT
), 1);
3624 RtlCopyMemory(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
3626 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3628 SetLastNtError(_SEH2_GetExceptionCode());
3629 _SEH2_YIELD(RETURN( FALSE
));
3633 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
3638 Flags
= PLACE_MAX
| PLACE_RECT
;
3639 if (Safepl
.flags
& WPF_SETMINPOSITION
) Flags
|= PLACE_MIN
;
3640 UserRefObjectCo(Wnd
, &Ref
);
3641 IntSetWindowPlacement(Wnd
, &Safepl
, Flags
);
3642 UserDerefObjectCo(Wnd
);
3646 TRACE("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_
);
3655 NtUserShowWindowAsync(HWND hWnd
, LONG nCmdShow
)
3659 DECLARE_RETURN(BOOL
);
3660 USER_REFERENCE_ENTRY Ref
;
3662 TRACE("Enter NtUserShowWindowAsync\n");
3663 UserEnterExclusive();
3665 if (!(Window
= UserGetWindowObject(hWnd
)) ||
3666 UserIsDesktopWindow(Window
) || UserIsMessageWindow(Window
))
3671 if ( nCmdShow
> SW_MAX
)
3673 EngSetLastError(ERROR_INVALID_PARAMETER
);
3677 UserRefObjectCo(Window
, &Ref
);
3678 ret
= co_IntSendMessageNoWait( hWnd
, WM_ASYNC_SHOWWINDOW
, nCmdShow
, 0 );
3679 UserDerefObjectCo(Window
);
3680 if (-1 == (int) ret
|| !ret
) ret
= FALSE
;
3685 TRACE("Leave NtUserShowWindowAsync, ret=%i\n",_ret_
);
3694 NtUserShowWindow(HWND hWnd
, LONG nCmdShow
)
3698 DECLARE_RETURN(BOOL
);
3699 USER_REFERENCE_ENTRY Ref
;
3701 TRACE("Enter NtUserShowWindow hWnd %p SW_ %d\n",hWnd
, nCmdShow
);
3702 UserEnterExclusive();
3704 if (!(Window
= UserGetWindowObject(hWnd
)) ||
3705 UserIsDesktopWindow(Window
) || UserIsMessageWindow(Window
))
3710 if ( nCmdShow
> SW_MAX
|| Window
->state2
& WNDS2_INDESTROY
)
3712 EngSetLastError(ERROR_INVALID_PARAMETER
);
3716 UserRefObjectCo(Window
, &Ref
);
3717 ret
= co_WinPosShowWindow(Window
, nCmdShow
);
3718 UserDerefObjectCo(Window
);
3723 TRACE("Leave NtUserShowWindow, ret=%i\n",_ret_
);
3733 NtUserWindowFromPoint(LONG X
, LONG Y
)
3737 PWND DesktopWindow
= NULL
, Window
= NULL
;
3739 DECLARE_RETURN(HWND
);
3740 USER_REFERENCE_ENTRY Ref
;
3742 TRACE("Enter NtUserWindowFromPoint\n");
3743 UserEnterExclusive();
3745 if ((DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow())))
3752 // Hmm... Threads live on desktops thus we have a reference on the desktop and indirectly the desktop window.
3753 // It is possible this referencing is useless, though it should not hurt...
3754 UserRefObjectCo(DesktopWindow
, &Ref
);
3756 //pti = PsGetCurrentThreadWin32Thread();
3757 Window
= co_WinPosWindowFromPoint(DesktopWindow
, &pt
, &hittest
, FALSE
);
3761 Ret
= UserHMGetHandle(Window
);
3770 if (DesktopWindow
) UserDerefObjectCo(DesktopWindow
);
3772 TRACE("Leave NtUserWindowFromPoint, ret=%p\n", _ret_
);