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 VOID FASTCALL
IntLinkWindow(PWND Wnd
,PWND WndInsertAfter
);
35 /* FUNCTIONS *****************************************************************/
38 /***********************************************************************
41 static void dump_winpos_flags(UINT flags
)
43 static const DWORD dumped_flags
= (SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOREDRAW
|
44 SWP_NOACTIVATE
| SWP_FRAMECHANGED
| SWP_SHOWWINDOW
|
45 SWP_HIDEWINDOW
| SWP_NOCOPYBITS
| SWP_NOOWNERZORDER
|
46 SWP_NOSENDCHANGING
| SWP_DEFERERASE
| SWP_ASYNCWINDOWPOS
|
47 SWP_NOCLIENTSIZE
| SWP_NOCLIENTMOVE
| SWP_STATECHANGED
);
49 if(flags
& SWP_NOSIZE
) TRACE(" SWP_NOSIZE");
50 if(flags
& SWP_NOMOVE
) TRACE(" SWP_NOMOVE");
51 if(flags
& SWP_NOZORDER
) TRACE(" SWP_NOZORDER");
52 if(flags
& SWP_NOREDRAW
) TRACE(" SWP_NOREDRAW");
53 if(flags
& SWP_NOACTIVATE
) TRACE(" SWP_NOACTIVATE");
54 if(flags
& SWP_FRAMECHANGED
) TRACE(" SWP_FRAMECHANGED");
55 if(flags
& SWP_SHOWWINDOW
) TRACE(" SWP_SHOWWINDOW");
56 if(flags
& SWP_HIDEWINDOW
) TRACE(" SWP_HIDEWINDOW");
57 if(flags
& SWP_NOCOPYBITS
) TRACE(" SWP_NOCOPYBITS");
58 if(flags
& SWP_NOOWNERZORDER
) TRACE(" SWP_NOOWNERZORDER");
59 if(flags
& SWP_NOSENDCHANGING
) TRACE(" SWP_NOSENDCHANGING");
60 if(flags
& SWP_DEFERERASE
) TRACE(" SWP_DEFERERASE");
61 if(flags
& SWP_ASYNCWINDOWPOS
) TRACE(" SWP_ASYNCWINDOWPOS");
62 if(flags
& SWP_NOCLIENTSIZE
) TRACE(" SWP_NOCLIENTSIZE");
63 if(flags
& SWP_NOCLIENTMOVE
) TRACE(" SWP_NOCLIENTMOVE");
64 if(flags
& SWP_STATECHANGED
) TRACE(" SWP_STATECHANGED");
66 if(flags
& ~dumped_flags
) TRACE(" %08x", flags
& ~dumped_flags
);
72 IntGetClientOrigin(PWND Window OPTIONAL
, LPPOINT Point
)
74 Window
= Window
? Window
: UserGetDesktopWindow();
77 Point
->x
= Point
->y
= 0;
80 Point
->x
= Window
->rcClient
.left
;
81 Point
->y
= Window
->rcClient
.top
;
88 * Returns client window rectangle relative to the upper-left corner of client area.
90 * \note Does not check the validity of the parameters
93 IntGetClientRect(PWND Wnd
, RECTL
*Rect
)
97 if (Wnd
->style
& WS_MINIMIZED
)
99 Rect
->left
= Rect
->top
= 0;
100 Rect
->right
= UserGetSystemMetrics(SM_CXMINIMIZED
);
101 Rect
->bottom
= UserGetSystemMetrics(SM_CYMINIMIZED
);
104 if (!UserIsDesktopWindow(Wnd
))
106 *Rect
= Wnd
->rcClient
;
107 RECTL_vOffsetRect(Rect
, -Wnd
->rcClient
.left
, -Wnd
->rcClient
.top
);
111 Rect
->left
= Rect
->top
= 0;
112 Rect
->right
= Wnd
->rcClient
.right
;
113 Rect
->bottom
= Wnd
->rcClient
.bottom
;
114 /* Do this until Init bug is fixed. This sets 640x480, see InitMetrics.
115 Rect->right = UserGetSystemMetrics(SM_CXSCREEN);
116 Rect->bottom = UserGetSystemMetrics(SM_CYSCREEN);
122 IntGetWindowRect(PWND Wnd
, RECTL
*Rect
)
126 if (!Wnd
) return FALSE
;
127 if (!UserIsDesktopWindow(Wnd
))
129 *Rect
= Wnd
->rcWindow
;
133 Rect
->left
= Rect
->top
= 0;
134 Rect
->right
= Wnd
->rcWindow
.right
;
135 Rect
->bottom
= Wnd
->rcWindow
.bottom
;
136 /* Do this until Init bug is fixed. This sets 640x480, see InitMetrics.
137 Rect->right = GetSystemMetrics(SM_CXSCREEN);
138 Rect->bottom = GetSystemMetrics(SM_CYSCREEN);
145 IntMapWindowPoints(PWND FromWnd
, PWND ToWnd
, LPPOINT lpPoints
, UINT cPoints
)
147 BOOL mirror_from
, mirror_to
;
152 /* Note: Desktop Top and Left is always 0! */
153 Delta
.x
= Delta
.y
= 0;
154 mirror_from
= mirror_to
= FALSE
;
156 if (FromWnd
&& !UserIsDesktopWindow(FromWnd
))
158 if (FromWnd
->ExStyle
& WS_EX_LAYOUTRTL
)
162 Delta
.x
= -FromWnd
->rcClient
.right
;
165 Delta
.x
= FromWnd
->rcClient
.left
;
166 Delta
.y
= FromWnd
->rcClient
.top
;
169 if (ToWnd
&& !UserIsDesktopWindow(ToWnd
))
171 if (ToWnd
->ExStyle
& WS_EX_LAYOUTRTL
)
175 Delta
.x
+= Change
* ToWnd
->rcClient
.right
;
178 Delta
.x
-= Change
* ToWnd
->rcClient
.left
;
179 Delta
.y
-= ToWnd
->rcClient
.top
;
182 for (i
= 0; i
!= cPoints
; i
++)
184 lpPoints
[i
].x
+= Delta
.x
;
185 lpPoints
[i
].x
*= Change
;
186 lpPoints
[i
].y
+= Delta
.y
;
189 if ((mirror_from
|| mirror_to
) && cPoints
== 2) /* special case for rectangle */
191 int tmp
= min(lpPoints
[0].x
, lpPoints
[1].x
);
192 lpPoints
[1].x
= max(lpPoints
[0].x
, lpPoints
[1].x
);
196 return MAKELONG(LOWORD(Delta
.x
), LOWORD(Delta
.y
));
200 IntClientToScreen(PWND Wnd
, LPPOINT lpPoint
)
202 if (Wnd
&& Wnd
->fnid
!= FNID_DESKTOP
)
204 if (Wnd
->ExStyle
& WS_EX_LAYOUTRTL
)
205 lpPoint
->x
= Wnd
->rcClient
.right
- lpPoint
->x
;
207 lpPoint
->x
+= Wnd
->rcClient
.left
;
208 lpPoint
->y
+= Wnd
->rcClient
.top
;
214 IntScreenToClient(PWND Wnd
, LPPOINT lpPoint
)
216 if (Wnd
&& Wnd
->fnid
!= FNID_DESKTOP
)
218 if (Wnd
->ExStyle
& WS_EX_LAYOUTRTL
)
219 lpPoint
->x
= Wnd
->rcClient
.right
- lpPoint
->x
;
221 lpPoint
->x
-= Wnd
->rcClient
.left
;
222 lpPoint
->y
-= Wnd
->rcClient
.top
;
227 BOOL FASTCALL
IsChildVisible(PWND pWnd
)
231 if ( (pWnd
->style
& (WS_POPUP
|WS_CHILD
)) != WS_CHILD
||
232 !(pWnd
= pWnd
->spwndParent
) )
235 while (pWnd
->style
& WS_VISIBLE
);
239 PWND FASTCALL
IntGetLastTopMostWindow(VOID
)
242 PDESKTOP rpdesk
= gptiCurrent
->rpdesk
;
245 (pWnd
= rpdesk
->pDeskInfo
->spwnd
->spwndChild
) &&
246 pWnd
->ExStyle
& WS_EX_TOPMOST
)
250 if (!pWnd
->spwndNext
) break;
251 if (!(pWnd
->spwndNext
->ExStyle
& WS_EX_TOPMOST
)) break;
252 pWnd
= pWnd
->spwndNext
;
260 SelectWindowRgn(PWND Window
, HRGN hRgnClip
)
262 if (Window
->hrgnClip
)
264 /* Delete no longer needed region handle */
265 IntGdiSetRegionOwner(Window
->hrgnClip
, GDI_OBJ_HMGR_POWNED
);
266 GreDeleteObject(Window
->hrgnClip
);
267 Window
->hrgnClip
= NULL
;
270 if (hRgnClip
> HRGN_WINDOW
)
272 /*if (!UserIsDesktopWindow(Window))
274 NtGdiOffsetRgn(hRgnClip, Window->rcWindow.left, Window->rcWindow.top);
276 /* Set public ownership */
277 IntGdiSetRegionOwner(hRgnClip
, GDI_OBJ_HMGR_PUBLIC
);
279 Window
->hrgnClip
= hRgnClip
;
284 // This helps with CORE-6129 forcing modal dialog active when another app is minimized or closed.
286 BOOL FASTCALL
ActivateOtherWindowMin(PWND Wnd
)
288 BOOL ActivePrev
, FindTopWnd
;
289 PWND pWndTopMost
, pWndChild
, pWndSetActive
, pWndTemp
, pWndDesk
;
290 USER_REFERENCE_ENTRY Ref
;
291 PTHREADINFO pti
= gptiCurrent
;
293 //ERR("AOWM 1 %p\n",Wnd->head.h);
294 ActivePrev
= (pti
->MessageQueue
->spwndActivePrev
!= NULL
);
297 if ((pWndTopMost
= IntGetLastTopMostWindow()))
298 pWndChild
= pWndTopMost
->spwndNext
;
300 pWndChild
= Wnd
->spwndParent
->spwndChild
;
305 pWndSetActive
= pti
->MessageQueue
->spwndActivePrev
;
307 pWndSetActive
= pWndChild
;
313 if ( VerifyWnd(pWndSetActive
) &&
314 !(pWndSetActive
->ExStyle
& WS_EX_NOACTIVATE
) &&
315 (pWndSetActive
->style
& (WS_VISIBLE
|WS_DISABLED
)) == WS_VISIBLE
&&
316 (!(pWndSetActive
->style
& WS_ICONIC
) /* FIXME MinMax pos? */ ) )
318 if (!(pWndSetActive
->ExStyle
& WS_EX_TOOLWINDOW
) )
320 UserRefObjectCo(pWndSetActive
, &Ref
);
321 //ERR("ActivateOtherWindowMin Set FG 1\n");
322 co_IntSetForegroundWindow(pWndSetActive
);
323 UserDerefObjectCo(pWndSetActive
);
324 //ERR("AOWM 2 Exit Good %p\n",pWndSetActive->head.h);
327 if (!pWndTemp
) pWndTemp
= pWndSetActive
;
332 pWndSetActive
= pWndChild
;
335 pWndSetActive
= pWndSetActive
->spwndNext
;
338 if ( !FindTopWnd
) break;
343 pWndChild
= pWndChild
->spwndParent
->spwndChild
;
347 if (!(pWndDesk
= IntGetThreadDesktopWindow(pti
)))
352 pWndChild
= pWndDesk
->spwndChild
;
355 if ((pWndSetActive
= pWndTemp
))
357 UserRefObjectCo(pWndSetActive
, &Ref
);
358 //ERR("ActivateOtherWindowMin Set FG 2\n");
359 co_IntSetForegroundWindow(pWndSetActive
);
360 UserDerefObjectCo(pWndSetActive
);
361 //ERR("AOWM 3 Exit Good %p\n",pWndSetActive->head.h);
364 //ERR("AOWM 4 Bad\n");
368 /*******************************************************************
369 * can_activate_window
371 * Check if we can activate the specified window.
374 BOOL FASTCALL
can_activate_window( PWND Wnd OPTIONAL
)
378 if (!Wnd
) return FALSE
;
381 if (!(style
& WS_VISIBLE
)) return FALSE
;
382 if (style
& WS_MINIMIZE
) return FALSE
;
383 if ((style
& (WS_POPUP
|WS_CHILD
)) == WS_CHILD
) return FALSE
;
385 /* FIXME: This window could be disable because the child that closed
387 //return !(style & WS_DISABLED);
391 /*******************************************************************
392 * WinPosActivateOtherWindow
394 * Activates window other than pWnd.
397 co_WinPosActivateOtherWindow(PWND Wnd
)
400 USER_REFERENCE_ENTRY Ref
;
404 if (IntIsDesktopWindow(Wnd
))
406 //ERR("WinPosActivateOtherWindow Set Focus Msg Q No window!\n");
407 IntSetFocusMessageQueue(NULL
);
411 /* If this is popup window, try to activate the owner first. */
412 if ((Wnd
->style
& WS_POPUP
) && (WndTo
= Wnd
->spwndOwner
))
414 TRACE("WPAOW Popup with Owner\n");
415 WndTo
= UserGetAncestor( WndTo
, GA_ROOT
);
416 if (can_activate_window(WndTo
)) goto done
;
419 /* Pick a next top-level window. */
420 /* FIXME: Search for non-tooltip windows first. */
424 if (!(WndTo
= WndTo
->spwndNext
)) break;
425 if (can_activate_window( WndTo
)) goto done
;
429 Fixes wine win.c:test_SetParent last ShowWindow test after popup dies.
430 Check for previous active window to bring to top.
434 WndTo
= Wnd
->head
.pti
->MessageQueue
->spwndActivePrev
;
435 if (can_activate_window( WndTo
)) goto done
;
438 // Find any window to bring to top. Works Okay for wine since it does not see X11 windows.
439 WndTo
= UserGetDesktopWindow();
440 WndTo
= WndTo
->spwndChild
;
443 //ERR("WinPosActivateOtherWindow No window!\n");
453 if (can_activate_window( WndTo
)) goto done
;
454 if (!(WndTo
= WndTo
->spwndNext
)) break;
458 if (WndTo
) UserRefObjectCo(WndTo
, &Ref
);
460 if (gpqForeground
&& (!gpqForeground
->spwndActive
|| Wnd
== gpqForeground
->spwndActive
))
462 /* ReactOS can pass WndTo = NULL to co_IntSetForegroundWindow and returns FALSE. */
463 //ERR("WinPosActivateOtherWindow Set FG 0x%p hWnd %p\n",WndTo, WndTo ? WndTo->head.h : 0);
464 if (co_IntSetForegroundWindow(WndTo
))
466 if (WndTo
) UserDerefObjectCo(WndTo
);
470 //ERR("WinPosActivateOtherWindow Set Active 0x%p\n",WndTo);
471 if (!UserSetActiveWindow(WndTo
)) /* Ok for WndTo to be NULL here */
473 //ERR("WPAOW SA 1\n");
474 UserSetActiveWindow(NULL
);
476 if (WndTo
) UserDerefObjectCo(WndTo
);
480 WinPosInitInternalPos(PWND Wnd
, RECTL
*RestoreRect
)
483 RECTL Rect
= *RestoreRect
;
485 if (Wnd
->spwndParent
&& !UserIsDesktopWindow(Wnd
->spwndParent
))
487 RECTL_vOffsetRect(&Rect
,
488 -Wnd
->spwndParent
->rcClient
.left
,
489 -Wnd
->spwndParent
->rcClient
.top
);
495 if (!Wnd
->InternalPosInitialized
)
497 // FIXME: Use check point Atom..
498 Wnd
->InternalPos
.flags
= 0;
499 Wnd
->InternalPos
.MaxPos
.x
= Wnd
->InternalPos
.MaxPos
.y
= -1;
500 Wnd
->InternalPos
.IconPos
.x
= Wnd
->InternalPos
.IconPos
.y
= -1;
501 Wnd
->InternalPos
.NormalRect
= Rect
;
502 Wnd
->InternalPosInitialized
= TRUE
;
505 if (Wnd
->style
& WS_MINIMIZE
)
507 Wnd
->InternalPos
.IconPos
= Size
;
508 Wnd
->InternalPos
.flags
|= WPF_MININIT
;
510 else if (Wnd
->style
& WS_MAXIMIZE
)
512 Wnd
->InternalPos
.flags
|= WPF_MAXINIT
;
514 if ( Wnd
->spwndParent
== Wnd
->head
.rpdesk
->pDeskInfo
->spwnd
)
516 if (Wnd
->state
& WNDS_MAXIMIZESTOMONITOR
)
518 Wnd
->InternalPos
.flags
&= ~WPF_MAXINIT
;
519 Wnd
->InternalPos
.MaxPos
.x
= Wnd
->InternalPos
.MaxPos
.y
= -1;
524 PMONITOR pmonitor
= UserMonitorFromRect(&Rect
, MONITOR_DEFAULTTOPRIMARY
);
525 // FIXME: support DPI aware, rcWorkDPI/Real etc..
526 WorkArea
= pmonitor
->rcMonitor
;
528 if (Wnd
->style
& WS_MAXIMIZEBOX
)
529 { // Support (Wnd->state & WNDS_HASCAPTION) || pmonitor->cFullScreen too.
530 if ((Wnd
->style
& WS_CAPTION
) == WS_CAPTION
|| !(Wnd
->style
& (WS_CHILD
| WS_POPUP
)))
532 WorkArea
= pmonitor
->rcWork
;
537 Wnd
->InternalPos
.MaxPos
.x
= Rect
.left
- WorkArea
.left
;
538 Wnd
->InternalPos
.MaxPos
.y
= Rect
.top
- WorkArea
.top
;
540 /*ERR("WinPosIP 2 X %d = R.l %d - W.l %d | Y %d = R.t %d - W.t %d\n",
541 Wnd->InternalPos.MaxPos.x,
542 Rect.left, WorkArea.left,
543 Wnd->InternalPos.MaxPos.y,
544 Rect.top, WorkArea.top);*/
548 Wnd
->InternalPos
.MaxPos
= Size
;
552 Wnd
->InternalPos
.NormalRect
= Rect
;
558 IntGetWindowPlacement(PWND Wnd
, WINDOWPLACEMENT
*lpwndpl
)
560 if (!Wnd
) return FALSE
;
562 if(lpwndpl
->length
!= sizeof(WINDOWPLACEMENT
))
569 WinPosInitInternalPos(Wnd
, &Wnd
->rcWindow
);
571 lpwndpl
->showCmd
= SW_HIDE
;
573 if ( Wnd
->style
& WS_MINIMIZE
)
574 lpwndpl
->showCmd
= SW_SHOWMINIMIZED
;
576 lpwndpl
->showCmd
= ( Wnd
->style
& WS_MAXIMIZE
) ? SW_SHOWMAXIMIZED
: SW_SHOWNORMAL
;
578 lpwndpl
->rcNormalPosition
= Wnd
->InternalPos
.NormalRect
;
580 if (Wnd
->InternalPos
.flags
& WPF_MININIT
) // Return if it was set!
582 lpwndpl
->ptMinPosition
.x
= Wnd
->InternalPos
.IconPos
.x
;
583 lpwndpl
->ptMinPosition
.y
= Wnd
->InternalPos
.IconPos
.y
;
586 lpwndpl
->ptMinPosition
.x
= lpwndpl
->ptMinPosition
.y
= -1;
588 if ( Wnd
->InternalPos
.flags
& WPF_MAXINIT
&& // Return if set and not maximized to monitor!
589 !(Wnd
->state
& WNDS_MAXIMIZESTOMONITOR
))
591 lpwndpl
->ptMaxPosition
.x
= Wnd
->InternalPos
.MaxPos
.x
;
592 lpwndpl
->ptMaxPosition
.y
= Wnd
->InternalPos
.MaxPos
.y
;
595 lpwndpl
->ptMaxPosition
.x
= lpwndpl
->ptMaxPosition
.y
= -1;
597 if ( Wnd
->spwndParent
== Wnd
->head
.rpdesk
->pDeskInfo
->spwnd
&&
598 !(Wnd
->ExStyle
& WS_EX_TOOLWINDOW
))
600 PMONITOR pmonitor
= UserMonitorFromRect(&lpwndpl
->rcNormalPosition
, MONITOR_DEFAULTTOPRIMARY
);
602 // FIXME: support DPI aware, rcWorkDPI/Real etc..
603 if (Wnd
->InternalPos
.flags
& WPF_MININIT
)
605 lpwndpl
->ptMinPosition
.x
-= (pmonitor
->rcWork
.left
- pmonitor
->rcMonitor
.left
);
606 lpwndpl
->ptMinPosition
.y
-= (pmonitor
->rcWork
.top
- pmonitor
->rcMonitor
.top
);
608 RECTL_vOffsetRect(&lpwndpl
->rcNormalPosition
,
609 pmonitor
->rcMonitor
.left
- pmonitor
->rcWork
.left
,
610 pmonitor
->rcMonitor
.top
- pmonitor
->rcWork
.top
);
613 if ( Wnd
->InternalPos
.flags
& WPF_RESTORETOMAXIMIZED
|| Wnd
->style
& WS_MAXIMIZE
)
614 lpwndpl
->flags
|= WPF_RESTORETOMAXIMIZED
;
616 if ( ((Wnd
->style
& (WS_CHILD
|WS_POPUP
)) == WS_CHILD
) && Wnd
->InternalPos
.flags
& WPF_SETMINPOSITION
)
617 lpwndpl
->flags
|= WPF_SETMINPOSITION
;
622 /* make sure the specified rect is visible on screen */
623 static void make_rect_onscreen( RECT
*rect
)
625 PMONITOR pmonitor
= UserMonitorFromRect( rect
, MONITOR_DEFAULTTONEAREST
); // Wine uses this.
627 // FIXME: support DPI aware, rcWorkDPI/Real etc..
628 if (!pmonitor
) return;
629 /* FIXME: map coordinates from rcWork to rcMonitor */
630 if (rect
->right
<= pmonitor
->rcWork
.left
)
632 rect
->right
+= pmonitor
->rcWork
.left
- rect
->left
;
633 rect
->left
= pmonitor
->rcWork
.left
;
635 else if (rect
->left
>= pmonitor
->rcWork
.right
)
637 rect
->left
+= pmonitor
->rcWork
.right
- rect
->right
;
638 rect
->right
= pmonitor
->rcWork
.right
;
640 if (rect
->bottom
<= pmonitor
->rcWork
.top
)
642 rect
->bottom
+= pmonitor
->rcWork
.top
- rect
->top
;
643 rect
->top
= pmonitor
->rcWork
.top
;
645 else if (rect
->top
>= pmonitor
->rcWork
.bottom
)
647 rect
->top
+= pmonitor
->rcWork
.bottom
- rect
->bottom
;
648 rect
->bottom
= pmonitor
->rcWork
.bottom
;
652 /* make sure the specified point is visible on screen */
653 static void make_point_onscreen( POINT
*pt
)
657 RECTL_vSetRect( &rect
, pt
->x
, pt
->y
, pt
->x
+ 1, pt
->y
+ 1 );
658 make_rect_onscreen( &rect
);
664 IntSetWindowPlacement(PWND Wnd
, WINDOWPLACEMENT
*wpl
, UINT Flags
)
669 if ( Flags
& PLACE_MIN
) make_point_onscreen( &wpl
->ptMinPosition
);
670 if ( Flags
& PLACE_MAX
) make_point_onscreen( &wpl
->ptMaxPosition
);
671 if ( Flags
& PLACE_RECT
) make_rect_onscreen( &wpl
->rcNormalPosition
);
673 if (!Wnd
|| Wnd
== Wnd
->head
.rpdesk
->pDeskInfo
->spwnd
) return FALSE
;
675 if ( Flags
& PLACE_MIN
) Wnd
->InternalPos
.IconPos
= wpl
->ptMinPosition
;
676 if ( Flags
& PLACE_MAX
) Wnd
->InternalPos
.MaxPos
= wpl
->ptMaxPosition
;
677 if ( Flags
& PLACE_RECT
) Wnd
->InternalPos
.NormalRect
= wpl
->rcNormalPosition
;
679 SWP_Flags
= SWP_NOZORDER
| SWP_NOACTIVATE
| ((wpl
->flags
& WPF_ASYNCWINDOWPLACEMENT
) ? SWP_ASYNCWINDOWPOS
: 0);
681 if (Wnd
->style
& WS_MINIMIZE
)
683 if (Flags
& PLACE_MIN
|| Wnd
->InternalPos
.flags
& WPF_SETMINPOSITION
)
685 co_WinPosSetWindowPos(Wnd
, HWND_TOP
,
686 wpl
->ptMinPosition
.x
, wpl
->ptMinPosition
.y
, 0, 0,
687 SWP_NOSIZE
| SWP_Flags
);
688 Wnd
->InternalPos
.flags
|= WPF_MININIT
;
691 else if (Wnd
->style
& WS_MAXIMIZE
)
693 if (Flags
& PLACE_MAX
)
695 co_WinPosSetWindowPos(Wnd
, HWND_TOP
,
696 wpl
->ptMaxPosition
.x
, wpl
->ptMaxPosition
.y
, 0, 0,
697 SWP_NOSIZE
| SWP_Flags
);
698 Wnd
->InternalPos
.flags
|= WPF_MAXINIT
;
701 else if (Flags
& PLACE_RECT
)
703 co_WinPosSetWindowPos(Wnd
, HWND_TOP
,
704 wpl
->rcNormalPosition
.left
, wpl
->rcNormalPosition
.top
,
705 wpl
->rcNormalPosition
.right
- wpl
->rcNormalPosition
.left
,
706 wpl
->rcNormalPosition
.bottom
- wpl
->rcNormalPosition
.top
,
710 sAsync
= (Wnd
->head
.pti
->MessageQueue
!= gptiCurrent
->MessageQueue
&& wpl
->flags
& WPF_ASYNCWINDOWPLACEMENT
);
713 co_IntSendMessageNoWait( UserHMGetHandle(Wnd
), WM_ASYNC_SHOWWINDOW
, wpl
->showCmd
, 0 );
715 co_WinPosShowWindow(Wnd
, wpl
->showCmd
);
717 if ( Wnd
->style
& WS_MINIMIZE
&& !sAsync
)
719 if ( wpl
->flags
& WPF_SETMINPOSITION
)
720 Wnd
->InternalPos
.flags
|= WPF_SETMINPOSITION
;
722 if ( wpl
->flags
& WPF_RESTORETOMAXIMIZED
)
723 Wnd
->InternalPos
.flags
|= WPF_RESTORETOMAXIMIZED
;
730 co_WinPosArrangeIconicWindows(PWND parent
)
734 INT x
, y
, xspacing
, yspacing
, sx
, sy
;
736 ASSERT_REFS_CO(parent
);
738 IntGetClientRect( parent
, &rectParent
);
739 // FIXME: Support Minimize Metrics gspv.mm.iArrange.
740 // Default: ARW_BOTTOMLEFT
742 y
= rectParent
.bottom
;
744 xspacing
= UserGetSystemMetrics(SM_CXMINIMIZED
);
745 yspacing
= UserGetSystemMetrics(SM_CYMINIMIZED
);
747 Child
= parent
->spwndChild
;
750 if((Child
->style
& WS_MINIMIZE
) != 0 )
752 USER_REFERENCE_ENTRY Ref
;
753 UserRefObjectCo(Child
, &Ref
);
755 sx
= x
+ UserGetSystemMetrics(SM_CXBORDER
);
756 sy
= y
- yspacing
- UserGetSystemMetrics(SM_CYBORDER
);
758 Child
->InternalPos
.IconPos
.x
= sx
;
759 Child
->InternalPos
.IconPos
.y
= sy
;
760 Child
->InternalPos
.flags
|= WPF_MININIT
;
762 co_WinPosSetWindowPos( Child
, 0, sx
, sy
, xspacing
, yspacing
, SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOCOPYBITS
| SWP_ASYNCWINDOWPOS
);
764 UserDerefObjectCo(Child
);
766 if (x
<= rectParent
.right
- xspacing
)
774 Child
= Child
->spwndNext
;
780 WinPosFindIconPos(PWND Window
, POINT
*Pos
)
783 PWND pwndChild
, pwndParent
;
784 int x
, y
, xspacing
, yspacing
;
786 pwndParent
= Window
->spwndParent
;
787 if (UserIsDesktopWindow(pwndParent
))
789 ERR("FIXME: Parent is Desktop, Min off screen!\n");
790 /* FIXME: ReactOS doesn't support iconic minimize to desktop */
791 Pos
->x
= Pos
->y
= -32000;
792 Window
->InternalPos
.flags
|= WPF_MININIT
;
793 Window
->InternalPos
.IconPos
.x
= Pos
->x
;
794 Window
->InternalPos
.IconPos
.y
= Pos
->y
;
798 IntGetClientRect( pwndParent
, &rectParent
);
799 // FIXME: Support Minimize Metrics gspv.mm.iArrange.
800 // Default: ARW_BOTTOMLEFT
802 y
= rectParent
.bottom
;
804 xspacing
= UserGetSystemMetrics(SM_CXMINIMIZED
);
805 yspacing
= UserGetSystemMetrics(SM_CYMINIMIZED
);
807 // Set to default position when minimized.
808 Pos
->x
= x
+ UserGetSystemMetrics(SM_CXBORDER
);
809 Pos
->y
= y
- yspacing
- UserGetSystemMetrics(SM_CYBORDER
);
811 for (pwndChild
= pwndParent
->spwndChild
; pwndChild
; pwndChild
= pwndChild
->spwndNext
)
813 if (pwndChild
== Window
) continue;
815 if ((pwndChild
->style
& (WS_VISIBLE
|WS_MINIMIZE
)) != (WS_VISIBLE
|WS_MINIMIZE
) )
820 if ( pwndChild
->InternalPos
.IconPos
.x
!= Pos
->x
&& pwndChild
->InternalPos
.IconPos
.y
!= Pos
->y
)
824 if (x
<= rectParent
.right
- xspacing
)
831 Pos
->x
= x
+ UserGetSystemMetrics(SM_CXBORDER
);
832 Pos
->y
= y
- yspacing
- UserGetSystemMetrics(SM_CYBORDER
);
835 Window
->InternalPos
.IconPos
.x
= Pos
->x
;
836 Window
->InternalPos
.IconPos
.y
= Pos
->y
;
837 Window
->InternalPos
.flags
|= WPF_MININIT
;
838 TRACE("Position is set! X:%d Y:%d\n",Pos
->x
,Pos
->y
);
843 UserHasWindowEdge(DWORD Style
, DWORD ExStyle
)
845 if (Style
& WS_MINIMIZE
)
847 if (ExStyle
& WS_EX_DLGMODALFRAME
)
849 if (ExStyle
& WS_EX_STATICEDGE
)
851 if (Style
& WS_THICKFRAME
)
854 if (Style
== WS_DLGFRAME
|| Style
== WS_CAPTION
)
860 IntGetWindowBorderMeasures(PWND Wnd
, UINT
*cx
, UINT
*cy
)
862 if(HAS_DLGFRAME(Wnd
->style
, Wnd
->ExStyle
) && !(Wnd
->style
& WS_MINIMIZE
))
864 *cx
= UserGetSystemMetrics(SM_CXDLGFRAME
);
865 *cy
= UserGetSystemMetrics(SM_CYDLGFRAME
);
869 if(HAS_THICKFRAME(Wnd
->style
, Wnd
->ExStyle
)&& !(Wnd
->style
& WS_MINIMIZE
))
871 *cx
= UserGetSystemMetrics(SM_CXFRAME
);
872 *cy
= UserGetSystemMetrics(SM_CYFRAME
);
874 else if(HAS_THINFRAME(Wnd
->style
, Wnd
->ExStyle
))
876 *cx
= UserGetSystemMetrics(SM_CXBORDER
);
877 *cy
= UserGetSystemMetrics(SM_CYBORDER
);
887 UserGetWindowBorders(DWORD Style
, DWORD ExStyle
, SIZE
*Size
, BOOL WithClient
)
891 if (UserHasWindowEdge(Style
, ExStyle
))
893 else if (ExStyle
& WS_EX_STATICEDGE
)
895 if ((ExStyle
& WS_EX_CLIENTEDGE
) && WithClient
)
897 if (Style
& WS_CAPTION
|| ExStyle
& WS_EX_DLGMODALFRAME
)
899 Size
->cx
= Size
->cy
= Border
;
900 if ((Style
& WS_THICKFRAME
) && !(Style
& WS_MINIMIZE
))
902 Size
->cx
+= UserGetSystemMetrics(SM_CXFRAME
) - UserGetSystemMetrics(SM_CXDLGFRAME
);
903 Size
->cy
+= UserGetSystemMetrics(SM_CYFRAME
) - UserGetSystemMetrics(SM_CYDLGFRAME
);
905 Size
->cx
*= UserGetSystemMetrics(SM_CXBORDER
);
906 Size
->cy
*= UserGetSystemMetrics(SM_CYBORDER
);
910 UserAdjustWindowRectEx(LPRECT lpRect
,
919 lpRect
->top
-= UserGetSystemMetrics(SM_CYMENU
);
921 if ((dwStyle
& WS_CAPTION
) == WS_CAPTION
)
923 if (dwExStyle
& WS_EX_TOOLWINDOW
)
924 lpRect
->top
-= UserGetSystemMetrics(SM_CYSMCAPTION
);
926 lpRect
->top
-= UserGetSystemMetrics(SM_CYCAPTION
);
928 UserGetWindowBorders(dwStyle
, dwExStyle
, &BorderSize
, TRUE
);
938 co_WinPosGetMinMaxInfo(PWND Window
, POINT
* MaxSize
, POINT
* MaxPos
,
939 POINT
* MinTrack
, POINT
* MaxTrack
)
944 LONG style
= Window
->style
;
946 LONG exstyle
= Window
->ExStyle
;
949 ASSERT_REFS_CO(Window
);
951 /* Compute default values */
953 rc
= Window
->rcWindow
;
954 MinMax
.ptReserved
.x
= rc
.left
;
955 MinMax
.ptReserved
.y
= rc
.top
;
957 if ((style
& WS_CAPTION
) == WS_CAPTION
)
958 adjustedStyle
= style
& ~WS_BORDER
; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
960 adjustedStyle
= style
;
962 if(Window
->spwndParent
)
963 IntGetClientRect(Window
->spwndParent
, &rc
);
964 UserAdjustWindowRectEx(&rc
, adjustedStyle
, ((style
& WS_POPUP
) && Window
->IDMenu
), exstyle
);
969 MinMax
.ptMaxSize
.x
= rc
.right
- rc
.left
;
970 MinMax
.ptMaxSize
.y
= rc
.bottom
- rc
.top
;
971 if (style
& (WS_DLGFRAME
| WS_BORDER
))
973 MinMax
.ptMinTrackSize
.x
= UserGetSystemMetrics(SM_CXMINTRACK
);
974 MinMax
.ptMinTrackSize
.y
= UserGetSystemMetrics(SM_CYMINTRACK
);
978 MinMax
.ptMinTrackSize
.x
= 2 * xinc
;
979 MinMax
.ptMinTrackSize
.y
= 2 * yinc
;
981 MinMax
.ptMaxTrackSize
.x
= UserGetSystemMetrics(SM_CXMAXTRACK
);
982 MinMax
.ptMaxTrackSize
.y
= UserGetSystemMetrics(SM_CYMAXTRACK
);
983 MinMax
.ptMaxPosition
.x
= -xinc
;
984 MinMax
.ptMaxPosition
.y
= -yinc
;
986 if (!EMPTYPOINT(Window
->InternalPos
.MaxPos
)) MinMax
.ptMaxPosition
= Window
->InternalPos
.MaxPos
;
988 co_IntSendMessage(Window
->head
.h
, WM_GETMINMAXINFO
, 0, (LPARAM
)&MinMax
);
990 /* if the app didn't change the values, adapt them for the current monitor */
991 if ((monitor
= UserGetPrimaryMonitor()))
995 rc_work
= monitor
->rcMonitor
;
997 if (style
& WS_MAXIMIZEBOX
)
999 if ((style
& WS_CAPTION
) == WS_CAPTION
|| !(style
& (WS_CHILD
| WS_POPUP
)))
1000 rc_work
= monitor
->rcWork
;
1003 if (MinMax
.ptMaxSize
.x
== UserGetSystemMetrics(SM_CXSCREEN
) + 2 * xinc
&&
1004 MinMax
.ptMaxSize
.y
== UserGetSystemMetrics(SM_CYSCREEN
) + 2 * yinc
)
1006 MinMax
.ptMaxSize
.x
= (rc_work
.right
- rc_work
.left
) + 2 * xinc
;
1007 MinMax
.ptMaxSize
.y
= (rc_work
.bottom
- rc_work
.top
) + 2 * yinc
;
1009 if (MinMax
.ptMaxPosition
.x
== -xinc
&& MinMax
.ptMaxPosition
.y
== -yinc
)
1011 MinMax
.ptMaxPosition
.x
= rc_work
.left
- xinc
;
1012 MinMax
.ptMaxPosition
.y
= rc_work
.top
- yinc
;
1014 if (MinMax
.ptMaxSize
.x
>= (monitor
->rcMonitor
.right
- monitor
->rcMonitor
.left
) &&
1015 MinMax
.ptMaxSize
.y
>= (monitor
->rcMonitor
.bottom
- monitor
->rcMonitor
.top
) )
1016 Window
->state
|= WNDS_MAXIMIZESTOMONITOR
;
1018 Window
->state
&= ~WNDS_MAXIMIZESTOMONITOR
;
1022 MinMax
.ptMaxTrackSize
.x
= max(MinMax
.ptMaxTrackSize
.x
,
1023 MinMax
.ptMinTrackSize
.x
);
1024 MinMax
.ptMaxTrackSize
.y
= max(MinMax
.ptMaxTrackSize
.y
,
1025 MinMax
.ptMinTrackSize
.y
);
1028 *MaxSize
= MinMax
.ptMaxSize
;
1030 *MaxPos
= MinMax
.ptMaxPosition
;
1032 *MinTrack
= MinMax
.ptMinTrackSize
;
1034 *MaxTrack
= MinMax
.ptMaxTrackSize
;
1036 return 0; // FIXME: What does it return?
1041 IntValidateParent(PWND Child
, PREGION ValidateRgn
)
1043 PWND ParentWnd
= Child
;
1045 if (ParentWnd
->style
& WS_CHILD
)
1048 ParentWnd
= ParentWnd
->spwndParent
;
1049 while (ParentWnd
->style
& WS_CHILD
);
1052 ParentWnd
= Child
->spwndParent
;
1055 if (ParentWnd
->style
& WS_CLIPCHILDREN
)
1058 if (ParentWnd
->hrgnUpdate
!= 0)
1060 IntInvalidateWindows( ParentWnd
,
1062 RDW_VALIDATE
| RDW_NOCHILDREN
);
1065 ParentWnd
= ParentWnd
->spwndParent
;
1073 FixClientRect(PRECTL ClientRect
, PRECTL WindowRect
)
1075 if (ClientRect
->left
< WindowRect
->left
)
1077 ClientRect
->left
= WindowRect
->left
;
1079 else if (WindowRect
->right
< ClientRect
->left
)
1081 ClientRect
->left
= WindowRect
->right
;
1083 if (ClientRect
->right
< WindowRect
->left
)
1085 ClientRect
->right
= WindowRect
->left
;
1087 else if (WindowRect
->right
< ClientRect
->right
)
1089 ClientRect
->right
= WindowRect
->right
;
1091 if (ClientRect
->top
< WindowRect
->top
)
1093 ClientRect
->top
= WindowRect
->top
;
1095 else if (WindowRect
->bottom
< ClientRect
->top
)
1097 ClientRect
->top
= WindowRect
->bottom
;
1099 if (ClientRect
->bottom
< WindowRect
->top
)
1101 ClientRect
->bottom
= WindowRect
->top
;
1103 else if (WindowRect
->bottom
< ClientRect
->bottom
)
1105 ClientRect
->bottom
= WindowRect
->bottom
;
1108 /***********************************************************************
1111 * Compute the valid rects from the old and new client rect and WVR_* flags.
1112 * Helper for WM_NCCALCSIZE handling.
1116 get_valid_rects( RECTL
*old_client
, RECTL
*new_client
, UINT flags
, RECTL
*valid
)
1120 if (flags
& WVR_REDRAW
)
1122 RECTL_vSetEmptyRect( &valid
[0] );
1123 RECTL_vSetEmptyRect( &valid
[1] );
1127 if (flags
& WVR_VALIDRECTS
)
1129 if (!RECTL_bIntersectRect( &valid
[0], &valid
[0], new_client
) ||
1130 !RECTL_bIntersectRect( &valid
[1], &valid
[1], old_client
))
1132 RECTL_vSetEmptyRect( &valid
[0] );
1133 RECTL_vSetEmptyRect( &valid
[1] );
1136 flags
= WVR_ALIGNLEFT
| WVR_ALIGNTOP
;
1140 valid
[0] = *new_client
;
1141 valid
[1] = *old_client
;
1144 /* make sure the rectangles have the same size */
1145 cx
= min( valid
[0].right
- valid
[0].left
, valid
[1].right
- valid
[1].left
);
1146 cy
= min( valid
[0].bottom
- valid
[0].top
, valid
[1].bottom
- valid
[1].top
);
1148 if (flags
& WVR_ALIGNBOTTOM
)
1150 valid
[0].top
= valid
[0].bottom
- cy
;
1151 valid
[1].top
= valid
[1].bottom
- cy
;
1155 valid
[0].bottom
= valid
[0].top
+ cy
;
1156 valid
[1].bottom
= valid
[1].top
+ cy
;
1158 if (flags
& WVR_ALIGNRIGHT
)
1160 valid
[0].left
= valid
[0].right
- cx
;
1161 valid
[1].left
= valid
[1].right
- cx
;
1165 valid
[0].right
= valid
[0].left
+ cx
;
1166 valid
[1].right
= valid
[1].left
+ cx
;
1172 co_WinPosDoNCCALCSize(PWND Window
, PWINDOWPOS WinPos
, RECTL
* WindowRect
, RECTL
* ClientRect
, RECTL
* validRects
)
1177 ASSERT_REFS_CO(Window
);
1179 /* Send WM_NCCALCSIZE message to get new client area */
1180 if ((WinPos
->flags
& (SWP_FRAMECHANGED
| SWP_NOSIZE
)) != SWP_NOSIZE
)
1182 NCCALCSIZE_PARAMS params
;
1183 WINDOWPOS winposCopy
;
1185 params
.rgrc
[0] = *WindowRect
; // new coordinates of a window that has been moved or resized
1186 params
.rgrc
[1] = Window
->rcWindow
; // window before it was moved or resized
1187 params
.rgrc
[2] = Window
->rcClient
; // client area before the window was moved or resized
1189 Parent
= Window
->spwndParent
;
1190 if (0 != (Window
->style
& WS_CHILD
) && Parent
)
1192 RECTL_vOffsetRect(&(params
.rgrc
[0]), - Parent
->rcClient
.left
, - Parent
->rcClient
.top
);
1193 RECTL_vOffsetRect(&(params
.rgrc
[1]), - Parent
->rcClient
.left
, - Parent
->rcClient
.top
);
1194 RECTL_vOffsetRect(&(params
.rgrc
[2]), - Parent
->rcClient
.left
, - Parent
->rcClient
.top
);
1197 params
.lppos
= &winposCopy
;
1198 winposCopy
= *WinPos
;
1200 wvrFlags
= co_IntSendMessage(Window
->head
.h
, WM_NCCALCSIZE
, TRUE
, (LPARAM
) ¶ms
);
1202 /* If the application send back garbage, ignore it */
1203 if (params
.rgrc
[0].left
<= params
.rgrc
[0].right
&&
1204 params
.rgrc
[0].top
<= params
.rgrc
[0].bottom
)
1206 *ClientRect
= params
.rgrc
[0]; // First rectangle contains the coordinates of the new client rectangle resulting from the move or resize
1207 if ((Window
->style
& WS_CHILD
) && Parent
)
1209 RECTL_vOffsetRect(ClientRect
, Parent
->rcClient
.left
, Parent
->rcClient
.top
);
1211 FixClientRect(ClientRect
, WindowRect
);
1214 if (ClientRect
->left
!= Window
->rcClient
.left
||
1215 ClientRect
->top
!= Window
->rcClient
.top
)
1217 WinPos
->flags
&= ~SWP_NOCLIENTMOVE
;
1220 if (ClientRect
->right
- ClientRect
->left
!= Window
->rcClient
.right
- Window
->rcClient
.left
)
1222 WinPos
->flags
&= ~SWP_NOCLIENTSIZE
;
1225 wvrFlags
&= ~WVR_HREDRAW
;
1227 if (ClientRect
->bottom
- ClientRect
->top
!= Window
->rcClient
.bottom
- Window
->rcClient
.top
)
1229 WinPos
->flags
&= ~SWP_NOCLIENTSIZE
;
1232 wvrFlags
&= ~WVR_VREDRAW
;
1234 validRects
[0] = params
.rgrc
[1]; // second rectangle contains the valid destination rectangle
1235 validRects
[1] = params
.rgrc
[2]; // third rectangle contains the valid source rectangle
1239 if (!(WinPos
->flags
& SWP_NOMOVE
) &&
1240 (ClientRect
->left
!= Window
->rcClient
.left
||
1241 ClientRect
->top
!= Window
->rcClient
.top
))
1243 WinPos
->flags
&= ~SWP_NOCLIENTMOVE
;
1247 if (WinPos
->flags
& (SWP_NOCOPYBITS
| SWP_NOREDRAW
| SWP_SHOWWINDOW
| SWP_HIDEWINDOW
))
1249 RECTL_vSetEmptyRect( &validRects
[0] );
1250 RECTL_vSetEmptyRect( &validRects
[1] );
1252 else get_valid_rects( &Window
->rcClient
, ClientRect
, wvrFlags
, validRects
);
1259 co_WinPosDoWinPosChanging(PWND Window
,
1264 ASSERT_REFS_CO(Window
);
1266 /* Send WM_WINDOWPOSCHANGING message */
1268 if (!(WinPos
->flags
& SWP_NOSENDCHANGING
)
1269 && !((WinPos
->flags
& SWP_AGG_NOCLIENTCHANGE
) && (WinPos
->flags
& SWP_SHOWWINDOW
)))
1271 TRACE("Sending WM_WINDOWPOSCHANGING to hwnd %p flags %04x.\n", Window
->head
.h
,WinPos
->flags
);
1272 co_IntSendMessage(Window
->head
.h
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
) WinPos
);
1275 /* Calculate new position and size */
1277 *WindowRect
= Window
->rcWindow
;
1278 *ClientRect
= (Window
->style
& WS_MINIMIZE
) ? Window
->rcWindow
: Window
->rcClient
;
1280 if (!(WinPos
->flags
& SWP_NOSIZE
))
1282 if (Window
->style
& WS_MINIMIZE
)
1284 WindowRect
->right
= WindowRect
->left
+ UserGetSystemMetrics(SM_CXMINIMIZED
);
1285 WindowRect
->bottom
= WindowRect
->top
+ UserGetSystemMetrics(SM_CYMINIMIZED
);
1289 WindowRect
->right
= WindowRect
->left
+ WinPos
->cx
;
1290 WindowRect
->bottom
= WindowRect
->top
+ WinPos
->cy
;
1294 if (!(WinPos
->flags
& SWP_NOMOVE
))
1301 Parent
= Window
->spwndParent
;
1303 // Parent child position issue is in here. SetParent_W7 test CORE-6651.
1304 if (//((Window->style & WS_CHILD) != 0) && <- Fixes wine msg test_SetParent: "rects do not match", the last test.
1306 Parent
!= Window
->head
.rpdesk
->pDeskInfo
->spwnd
)
1308 TRACE("Not SWP_NOMOVE 1 Parent client offset X %d Y %d\n",X
,Y
);
1309 X
+= Parent
->rcClient
.left
;
1310 Y
+= Parent
->rcClient
.top
;
1311 TRACE("Not SWP_NOMOVE 2 Parent client offset X %d Y %d\n",X
,Y
);
1314 WindowRect
->left
= X
;
1315 WindowRect
->top
= Y
;
1316 WindowRect
->right
+= X
- Window
->rcWindow
.left
;
1317 WindowRect
->bottom
+= Y
- Window
->rcWindow
.top
;
1319 RECTL_vOffsetRect(ClientRect
, X
- Window
->rcWindow
.left
,
1320 Y
- Window
->rcWindow
.top
);
1322 WinPos
->flags
|= SWP_NOCLIENTMOVE
| SWP_NOCLIENTSIZE
;
1324 TRACE( "hwnd %p, after %p, swp %d,%d %dx%d flags %08x\n",
1325 WinPos
->hwnd
, WinPos
->hwndInsertAfter
, WinPos
->x
, WinPos
->y
,
1326 WinPos
->cx
, WinPos
->cy
, WinPos
->flags
);
1327 TRACE("WindowRect: %d %d %d %d\n", WindowRect
->left
,WindowRect
->top
,WindowRect
->right
,WindowRect
->bottom
);
1328 TRACE("ClientRect: %d %d %d %d\n", ClientRect
->left
,ClientRect
->top
,ClientRect
->right
,ClientRect
->bottom
);
1334 * Fix Z order taking into account owned popups -
1335 * basically we need to maintain them above the window that owns them
1337 * FIXME: hide/show owned popups when owner visibility changes.
1339 * ReactOS: See bug CORE-6129 and CORE-6554.
1343 // Pass all the win:test_children/popup_zorder tests except "move hwnd_F and its popups down" which is if'ed out.
1344 // Side effect, breaks more of the DeferWindowPos api tests, but wine breaks more!!!!
1347 WinPosDoOwnedPopups(PWND Window
, HWND hWndInsertAfter
)
1352 PWND DesktopWindow
, ChildObject
;
1355 TRACE("(%p) hInsertAfter = %p\n", Window
, hWndInsertAfter
);
1357 Style
= Window
->style
;
1359 if (Style
& WS_CHILD
)
1361 TRACE("Window is child\n");
1362 return hWndInsertAfter
;
1365 Owner
= Window
->spwndOwner
? Window
->spwndOwner
->head
.h
: NULL
;
1369 /* Make sure this popup stays above the owner */
1371 if (hWndInsertAfter
!= HWND_TOPMOST
)
1373 DesktopWindow
= UserGetDesktopWindow();
1374 List
= IntWinListChildren(DesktopWindow
);
1378 for (i
= 0; List
[i
]; i
++)
1380 BOOL topmost
= FALSE
;
1382 ChildObject
= ValidateHwndNoErr(List
[i
]);
1385 topmost
= (ChildObject
->ExStyle
& WS_EX_TOPMOST
) != 0;
1388 if (List
[i
] == Owner
)
1390 if (i
> 0) hWndInsertAfter
= List
[i
-1];
1391 else hWndInsertAfter
= topmost
? HWND_TOPMOST
: HWND_TOP
;
1395 if (hWndInsertAfter
== HWND_TOP
|| hWndInsertAfter
== HWND_NOTOPMOST
)
1397 if (!topmost
) break;
1399 else if (List
[i
] == hWndInsertAfter
) break;
1403 return hWndInsertAfter
;
1407 if (hWndInsertAfter
== HWND_BOTTOM
)
1409 ERR("Window is HWND_BOTTOM hwnd %p\n",hWndInsertAfter
);
1410 if (List
) ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1416 DesktopWindow
= UserGetDesktopWindow();
1417 List
= IntWinListChildren(DesktopWindow
);
1424 if (hWndInsertAfter
== HWND_TOP
|| hWndInsertAfter
== HWND_NOTOPMOST
)
1426 if (hWndInsertAfter
== HWND_NOTOPMOST
|| !(Window
->ExStyle
& WS_EX_TOPMOST
))
1428 TRACE("skip all the topmost windows\n");
1429 /* skip all the topmost windows */
1431 (ChildObject
= ValidateHwndNoErr(List
[i
])) &&
1432 (ChildObject
->ExStyle
& WS_EX_TOPMOST
)) i
++;
1435 else if (hWndInsertAfter
!= HWND_TOPMOST
)
1437 /* skip windows that are already placed correctly */
1438 for (i
= 0; List
[i
]; i
++)
1440 if (List
[i
] == hWndInsertAfter
) break;
1441 if (List
[i
] == UserHMGetHandle(Window
))
1443 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1444 goto done
; /* nothing to do if window is moving backwards in z-order */
1449 for (; List
[i
]; i
++)
1452 USER_REFERENCE_ENTRY Ref
;
1454 if (List
[i
] == UserHMGetHandle(Window
))
1457 if (!(Wnd
= ValidateHwndNoErr(List
[i
])))
1460 Owner
= Wnd
->spwndOwner
? Wnd
->spwndOwner
->head
.h
: NULL
;
1462 if (Owner
!= UserHMGetHandle(Window
)) continue;
1464 UserRefObjectCo(Wnd
, &Ref
);
1465 TRACE( "moving %p owned by %p after %p\n", List
[i
], UserHMGetHandle(Window
), hWndInsertAfter
);
1466 co_WinPosSetWindowPos(Wnd
, hWndInsertAfter
, 0, 0, 0, 0,
1467 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOSENDCHANGING
| SWP_DEFERERASE
);
1469 UserDerefObjectCo(Wnd
);
1470 hWndInsertAfter
= List
[i
];
1472 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1475 return hWndInsertAfter
;
1479 /***********************************************************************
1480 * WinPosInternalMoveWindow
1482 * Update WindowRect and ClientRect of Window and all of its children
1483 * We keep both WindowRect and ClientRect in screen coordinates internally
1487 WinPosInternalMoveWindow(PWND Window
, INT MoveX
, INT MoveY
)
1491 ASSERT(Window
!= Window
->spwndChild
);
1492 TRACE("InternalMoveWin X %d Y %d\n", MoveX
, MoveY
);
1494 Window
->rcWindow
.left
+= MoveX
;
1495 Window
->rcWindow
.right
+= MoveX
;
1496 Window
->rcWindow
.top
+= MoveY
;
1497 Window
->rcWindow
.bottom
+= MoveY
;
1499 Window
->rcClient
.left
+= MoveX
;
1500 Window
->rcClient
.right
+= MoveX
;
1501 Window
->rcClient
.top
+= MoveY
;
1502 Window
->rcClient
.bottom
+= MoveY
;
1504 for(Child
= Window
->spwndChild
; Child
; Child
= Child
->spwndNext
)
1506 WinPosInternalMoveWindow(Child
, MoveX
, MoveY
);
1511 * WinPosFixupSWPFlags
1513 * Fix redundant flags and values in the WINDOWPOS structure.
1517 WinPosFixupFlags(WINDOWPOS
*WinPos
, PWND Wnd
)
1522 /* Finally make sure that all coordinates are valid */
1523 if (WinPos
->x
< -32768) WinPos
->x
= -32768;
1524 else if (WinPos
->x
> 32767) WinPos
->x
= 32767;
1525 if (WinPos
->y
< -32768) WinPos
->y
= -32768;
1526 else if (WinPos
->y
> 32767) WinPos
->y
= 32767;
1528 WinPos
->cx
= max(WinPos
->cx
, 0);
1529 WinPos
->cy
= max(WinPos
->cy
, 0);
1531 Parent
= UserGetAncestor( Wnd
, GA_PARENT
);
1532 if (!IntIsWindowVisible( Parent
) &&
1533 /* Fix B : wine msg test_SetParent:WmSetParentSeq_2:25 wParam bits! */
1534 (WinPos
->flags
& SWP_AGG_STATUSFLAGS
) == SWP_AGG_NOPOSCHANGE
) WinPos
->flags
|= SWP_NOREDRAW
;
1536 if (Wnd
->style
& WS_VISIBLE
) WinPos
->flags
&= ~SWP_SHOWWINDOW
;
1539 WinPos
->flags
&= ~SWP_HIDEWINDOW
;
1540 if (!(WinPos
->flags
& SWP_SHOWWINDOW
)) WinPos
->flags
|= SWP_NOREDRAW
;
1543 /* Check for right size */
1544 if (Wnd
->rcWindow
.right
- Wnd
->rcWindow
.left
== WinPos
->cx
&&
1545 Wnd
->rcWindow
.bottom
- Wnd
->rcWindow
.top
== WinPos
->cy
)
1547 WinPos
->flags
|= SWP_NOSIZE
;
1552 IntClientToScreen( Parent
, &pt
);
1553 TRACE("WPFU C2S wpx %d wpy %d ptx %d pty %d\n",WinPos
->x
,WinPos
->y
,pt
.x
,pt
.y
);
1554 /* Check for right position */
1555 if (Wnd
->rcWindow
.left
== pt
.x
&& Wnd
->rcWindow
.top
== pt
.y
)
1557 //ERR("In right pos\n");
1558 WinPos
->flags
|= SWP_NOMOVE
;
1561 if ( WinPos
->hwnd
!= UserGetForegroundWindow() && (Wnd
->style
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)
1563 /* Bring to the top when activating */
1564 if (!(WinPos
->flags
& (SWP_NOACTIVATE
|SWP_HIDEWINDOW
)) &&
1565 (WinPos
->flags
& SWP_NOZORDER
||
1566 (WinPos
->hwndInsertAfter
!= HWND_TOPMOST
&& WinPos
->hwndInsertAfter
!= HWND_NOTOPMOST
)))
1568 WinPos
->flags
&= ~SWP_NOZORDER
;
1569 WinPos
->hwndInsertAfter
= (0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
) ? HWND_TOPMOST
: HWND_TOP
);
1573 /* Check hwndInsertAfter */
1574 if (!(WinPos
->flags
& SWP_NOZORDER
))
1576 /* Fix sign extension */
1577 if (WinPos
->hwndInsertAfter
== (HWND
)0xffff)
1579 WinPos
->hwndInsertAfter
= HWND_TOPMOST
;
1581 else if (WinPos
->hwndInsertAfter
== (HWND
)0xfffe)
1583 WinPos
->hwndInsertAfter
= HWND_NOTOPMOST
;
1586 if (WinPos
->hwndInsertAfter
== HWND_TOP
)
1588 /* Keep it topmost when it's already topmost */
1589 if ((Wnd
->ExStyle
& WS_EX_TOPMOST
) != 0)
1590 WinPos
->hwndInsertAfter
= HWND_TOPMOST
;
1592 if (IntGetWindow(WinPos
->hwnd
, GW_HWNDFIRST
) == WinPos
->hwnd
)
1594 WinPos
->flags
|= SWP_NOZORDER
;
1597 else if (WinPos
->hwndInsertAfter
== HWND_BOTTOM
)
1599 if (!(Wnd
->ExStyle
& WS_EX_TOPMOST
) && IntGetWindow(WinPos
->hwnd
, GW_HWNDLAST
) == WinPos
->hwnd
)
1600 WinPos
->flags
|= SWP_NOZORDER
;
1602 else if (WinPos
->hwndInsertAfter
== HWND_TOPMOST
)
1604 if ((Wnd
->ExStyle
& WS_EX_TOPMOST
) && IntGetWindow(WinPos
->hwnd
, GW_HWNDFIRST
) == WinPos
->hwnd
)
1605 WinPos
->flags
|= SWP_NOZORDER
;
1607 else if (WinPos
->hwndInsertAfter
== HWND_NOTOPMOST
)
1609 if (!(Wnd
->ExStyle
& WS_EX_TOPMOST
))
1610 WinPos
->flags
|= SWP_NOZORDER
;
1612 else /* hwndInsertAfter must be a sibling of the window */
1616 InsAfterWnd
= ValidateHwndNoErr(WinPos
->hwndInsertAfter
);
1622 if (InsAfterWnd
->spwndParent
!= Wnd
->spwndParent
)
1624 /* Note from wine User32 Win test_SetWindowPos:
1625 "Returns TRUE also for windows that are not siblings"
1626 "Does not seem to do anything even without passing flags, still returns TRUE"
1627 "Same thing the other way around."
1628 ".. and with these windows."
1635 * We don't need to change the Z order of hwnd if it's already
1636 * inserted after hwndInsertAfter or when inserting hwnd after
1639 if ((WinPos
->hwnd
== WinPos
->hwndInsertAfter
) ||
1640 ((InsAfterWnd
->spwndNext
) && (WinPos
->hwnd
== InsAfterWnd
->spwndNext
->head
.h
)))
1642 WinPos
->flags
|= SWP_NOZORDER
;
1651 /* x and y are always screen relative */
1653 co_WinPosSetWindowPos(
1655 HWND WndInsertAfter
,
1664 RECTL NewWindowRect
;
1665 RECTL NewClientRect
;
1666 RECTL valid_rects
[2];
1667 PREGION VisBefore
= NULL
;
1668 PREGION VisBeforeJustClient
= NULL
;
1669 PREGION VisAfter
= NULL
;
1670 PREGION CopyRgn
= NULL
;
1672 RECTL OldWindowRect
, OldClientRect
;
1677 BOOL bPointerInWindow
, PosChanged
= FALSE
;
1678 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1680 ASSERT_REFS_CO(Window
);
1682 TRACE("pwnd %p, after %p, %d,%d (%dx%d), flags %s",
1683 Window
, WndInsertAfter
, x
, y
, cx
, cy
, flags
);
1685 dump_winpos_flags(flags
);
1688 /* FIXME: Get current active window from active queue. Why? since r2915. */
1690 bPointerInWindow
= IntPtInWindow(Window
, gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
);
1692 WinPos
.hwnd
= Window
->head
.h
;
1693 WinPos
.hwndInsertAfter
= WndInsertAfter
;
1698 WinPos
.flags
= flags
;
1700 if ( flags
& SWP_ASYNCWINDOWPOS
)
1703 PWINDOWPOS ppos
= ExAllocatePoolWithTag(PagedPool
, sizeof(WINDOWPOS
), USERTAG_SWP
);
1706 WinPos
.flags
&= ~SWP_ASYNCWINDOWPOS
; // Clear flag.
1708 /* Yes it's a pointer inside Win32k! */
1709 lRes
= co_IntSendMessageNoWait( WinPos
.hwnd
, WM_ASYNC_SETWINDOWPOS
, 0, (LPARAM
)ppos
);
1710 /* We handle this the same way as Event Hooks and Hooks. */
1713 ExFreePoolWithTag(ppos
, USERTAG_SWP
);
1721 co_WinPosDoWinPosChanging(Window
, &WinPos
, &NewWindowRect
, &NewClientRect
);
1723 /* Does the window still exist? */
1724 if (!IntIsWindow(WinPos
.hwnd
))
1726 TRACE("WinPosSetWindowPos: Invalid handle 0x%p!\n",WinPos
.hwnd
);
1727 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE
);
1731 /* Fix up the flags. */
1732 if (!WinPosFixupFlags(&WinPos
, Window
))
1738 Ancestor
= UserGetAncestor(Window
, GA_PARENT
);
1739 if ( (WinPos
.flags
& (SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) != SWP_NOZORDER
&&
1740 Ancestor
&& Ancestor
->head
.h
== IntGetDesktopWindow() )
1742 WinPos
.hwndInsertAfter
= WinPosDoOwnedPopups(Window
, WinPos
.hwndInsertAfter
);
1745 if (!(WinPos
.flags
& SWP_NOREDRAW
))
1747 /* Compute the visible region before the window position is changed */
1748 if (!(WinPos
.flags
& SWP_SHOWWINDOW
) &&
1749 (WinPos
.flags
& (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
|
1750 SWP_HIDEWINDOW
| SWP_FRAMECHANGED
)) !=
1751 (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
))
1753 VisBefore
= VIS_ComputeVisibleRegion(Window
, FALSE
, FALSE
,
1754 (Window
->style
& WS_CLIPSIBLINGS
) ? TRUE
: FALSE
);
1756 if ( VisBefore
!= NULL
&&
1757 REGION_Complexity(VisBefore
) == NULLREGION
)
1759 REGION_Delete(VisBefore
);
1764 REGION_bOffsetRgn(VisBefore
, -Window
->rcWindow
.left
, -Window
->rcWindow
.top
);
1767 /* Calculate the non client area for resizes, as this is used in the copy region */
1768 if (!(WinPos
.flags
& SWP_NOSIZE
))
1770 VisBeforeJustClient
= VIS_ComputeVisibleRegion(Window
, TRUE
, FALSE
,
1771 (Window
->style
& WS_CLIPSIBLINGS
) ? TRUE
: FALSE
);
1773 if ( VisBeforeJustClient
!= NULL
&&
1774 REGION_Complexity(VisBeforeJustClient
) == NULLREGION
)
1776 REGION_Delete(VisBeforeJustClient
);
1777 VisBeforeJustClient
= NULL
;
1779 else if(VisBeforeJustClient
)
1781 REGION_bOffsetRgn(VisBeforeJustClient
, -Window
->rcWindow
.left
, -Window
->rcWindow
.top
);
1788 if (Window
->hrgnNewFrame
)
1790 SelectWindowRgn( Window
, Window
->hrgnNewFrame
); // Should be PSMWP->acvr->hrgnClip
1791 Window
->hrgnNewFrame
= NULL
;
1794 WvrFlags
= co_WinPosDoNCCALCSize(Window
, &WinPos
, &NewWindowRect
, &NewClientRect
, valid_rects
);
1796 // ERR("co_WinPosDoNCCALCSize returned 0x%x\n valid dest: %d %d %d %d\n valid src : %d %d %d %d\n", WvrFlags,
1797 // valid_rects[0].left,valid_rects[0].top,valid_rects[0].right,valid_rects[0].bottom,
1798 // valid_rects[1].left,valid_rects[1].top,valid_rects[1].right,valid_rects[1].bottom);
1800 /* Validate link windows. (also take into account shell window in hwndShellWindow) */
1801 if (!(WinPos
.flags
& SWP_NOZORDER
) && WinPos
.hwnd
!= UserGetShellWindow())
1803 IntLinkHwnd(Window
, WinPos
.hwndInsertAfter
);
1806 OldWindowRect
= Window
->rcWindow
;
1807 OldClientRect
= Window
->rcClient
;
1809 if (NewClientRect
.left
!= OldClientRect
.left
||
1810 NewClientRect
.top
!= OldClientRect
.top
)
1812 // Move child window if their parent is moved. Keep Child window relative to Parent...
1813 WinPosInternalMoveWindow(Window
,
1814 NewClientRect
.left
- OldClientRect
.left
,
1815 NewClientRect
.top
- OldClientRect
.top
);
1819 Window
->rcWindow
= NewWindowRect
;
1820 Window
->rcClient
= NewClientRect
;
1822 /* erase parent when hiding or resizing child */
1823 if (WinPos
.flags
& SWP_HIDEWINDOW
)
1825 /* Clear the update region */
1826 co_UserRedrawWindow( Window
,
1829 RDW_VALIDATE
| RDW_NOFRAME
| RDW_NOERASE
| RDW_NOINTERNALPAINT
| RDW_ALLCHILDREN
);
1831 if (UserIsDesktopWindow(Window
->spwndParent
))
1832 co_IntShellHookNotify(HSHELL_WINDOWDESTROYED
, (WPARAM
)Window
->head
.h
, 0);
1834 Window
->style
&= ~WS_VISIBLE
; //IntSetStyle( Window, 0, WS_VISIBLE );
1835 Window
->head
.pti
->cVisWindows
--;
1836 IntNotifyWinEvent(EVENT_OBJECT_HIDE
, Window
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
1838 else if (WinPos
.flags
& SWP_SHOWWINDOW
)
1840 if (UserIsDesktopWindow(Window
->spwndParent
) &&
1841 Window
->spwndOwner
== NULL
&&
1842 (!(Window
->ExStyle
& WS_EX_TOOLWINDOW
) ||
1843 (Window
->ExStyle
& WS_EX_APPWINDOW
)))
1844 co_IntShellHookNotify(HSHELL_WINDOWCREATED
, (WPARAM
)Window
->head
.h
, 0);
1846 Window
->style
|= WS_VISIBLE
; //IntSetStyle( Window, WS_VISIBLE, 0 );
1847 Window
->head
.pti
->cVisWindows
++;
1848 IntNotifyWinEvent(EVENT_OBJECT_SHOW
, Window
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
1851 if (Window
->hrgnUpdate
!= NULL
&& Window
->hrgnUpdate
!= HRGN_WINDOW
)
1853 NtGdiOffsetRgn(Window
->hrgnUpdate
,
1854 NewWindowRect
.left
- OldWindowRect
.left
,
1855 NewWindowRect
.top
- OldWindowRect
.top
);
1858 DceResetActiveDCEs(Window
); // For WS_VISIBLE changes.
1860 if (!(WinPos
.flags
& SWP_NOREDRAW
))
1862 /* Determine the new visible region */
1863 VisAfter
= VIS_ComputeVisibleRegion(Window
, FALSE
, FALSE
,
1864 (Window
->style
& WS_CLIPSIBLINGS
) ? TRUE
: FALSE
);
1866 if ( VisAfter
!= NULL
&&
1867 REGION_Complexity(VisAfter
) == NULLREGION
)
1869 REGION_Delete(VisAfter
);
1874 REGION_bOffsetRgn(VisAfter
, -Window
->rcWindow
.left
, -Window
->rcWindow
.top
);
1878 * Determine which pixels can be copied from the old window position
1879 * to the new. Those pixels must be visible in both the old and new
1880 * position. Also, check the class style to see if the windows of this
1881 * class need to be completely repainted on (horizontal/vertical) size
1884 if ( ( VisBefore
!= NULL
&&
1886 !(WinPos
.flags
& SWP_NOCOPYBITS
) &&
1887 ((WinPos
.flags
& SWP_NOSIZE
) || !(WvrFlags
& WVR_REDRAW
)) &&
1888 !(Window
->ExStyle
& WS_EX_TRANSPARENT
) ) ||
1889 ( !PosChanged
&& (WinPos
.flags
& SWP_FRAMECHANGED
) && VisBefore
) )
1893 * If this is (also) a window resize, the whole nonclient area
1894 * needs to be repainted. So we limit the copy to the client area,
1895 * 'cause there is no use in copying it (would possibly cause
1896 * "flashing" too). However, if the copy region is already empty,
1897 * we don't have to crop (can't take anything away from an empty
1901 CopyRgn
= IntSysCreateRectpRgn(0, 0, 0, 0);
1902 if (WinPos
.flags
& SWP_NOSIZE
)
1903 RgnType
= IntGdiCombineRgn(CopyRgn
, VisAfter
, VisBefore
, RGN_AND
);
1904 else if (VisBeforeJustClient
!= NULL
)
1906 RgnType
= IntGdiCombineRgn(CopyRgn
, VisAfter
, VisBeforeJustClient
, RGN_AND
);
1907 REGION_Delete(VisBeforeJustClient
);
1910 /* Now use in copying bits which are in the update region. */
1911 if (Window
->hrgnUpdate
!= NULL
)
1913 PREGION RgnUpdate
= REGION_LockRgn(Window
->hrgnUpdate
);
1916 REGION_bOffsetRgn(CopyRgn
, NewWindowRect
.left
, NewWindowRect
.top
);
1917 IntGdiCombineRgn(CopyRgn
, CopyRgn
, RgnUpdate
, RGN_DIFF
);
1918 REGION_bOffsetRgn(CopyRgn
, -NewWindowRect
.left
, -NewWindowRect
.top
);
1919 REGION_UnlockRgn(RgnUpdate
);
1924 * Now, get the bounding box of the copy region. If it's empty
1925 * there's nothing to copy. Also, it's no use copying bits onto
1928 if (REGION_GetRgnBox(CopyRgn
, &CopyRect
) == NULLREGION
)
1930 /* Nothing to copy, clean up */
1931 REGION_Delete(CopyRgn
);
1934 else if ( OldWindowRect
.left
!= NewWindowRect
.left
||
1935 OldWindowRect
.top
!= NewWindowRect
.top
||
1936 (WinPos
.flags
& SWP_FRAMECHANGED
) )
1938 HRGN DcRgn
= NtGdiCreateRectRgn(0, 0, 0, 0);
1939 PREGION DcRgnObj
= REGION_LockRgn(DcRgn
);
1942 * Small trick here: there is no function to bitblt a region. So
1943 * we set the region as the clipping region, take the bounding box
1944 * of the region and bitblt that. Since nothing outside the clipping
1945 * region is copied, this has the effect of bitblt'ing the region.
1947 * Since NtUserGetDCEx takes ownership of the clip region, we need
1948 * to create a copy of CopyRgn and pass that. We need CopyRgn later
1950 IntGdiCombineRgn(DcRgnObj
, CopyRgn
, NULL
, RGN_COPY
);
1951 REGION_bOffsetRgn(DcRgnObj
, NewWindowRect
.left
, NewWindowRect
.top
);
1952 REGION_UnlockRgn(DcRgnObj
);
1953 Dc
= UserGetDCEx( Window
,
1955 DCX_WINDOW
|DCX_CACHE
|DCX_INTERSECTRGN
|DCX_CLIPSIBLINGS
|DCX_KEEPCLIPRGN
);
1957 CopyRect
.left
, CopyRect
.top
,
1958 CopyRect
.right
- CopyRect
.left
,
1959 CopyRect
.bottom
- CopyRect
.top
,
1961 CopyRect
.left
+ (OldWindowRect
.left
- NewWindowRect
.left
),
1962 CopyRect
.top
+ (OldWindowRect
.top
- NewWindowRect
.top
),
1967 UserReleaseDC(Window
, Dc
, FALSE
);
1968 IntValidateParent(Window
, CopyRgn
);
1969 GreDeleteObject(DcRgn
);
1977 /////// Fixes NoPopup tests but breaks msg_paint tests.
1978 if ( !PosChanged
&& (WinPos
.flags
& SWP_FRAMECHANGED
) && VisBefore
)
1980 PWND Parent
= Window
->spwndParent
;
1981 ERR("SWP_FRAMECHANGED no chg\n");
1982 if ( !(Window
->style
& WS_CHILD
) && (Parent
) && (Parent
->style
& WS_CLIPCHILDREN
))
1984 ERR("SWP_FRAMECHANGED Parent WS_CLIPCHILDREN\n");
1985 //IntInvalidateWindows( Window, VisBefore, /*RDW_ERASE |*/ RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
1989 /* We need to redraw what wasn't visible before */
1990 if (VisAfter
!= NULL
)
1992 PREGION DirtyRgn
= IntSysCreateRectpRgn(0, 0, 0, 0);
1995 if (CopyRgn
!= NULL
)
1997 RgnType
= IntGdiCombineRgn(DirtyRgn
, VisAfter
, CopyRgn
, RGN_DIFF
);
2001 RgnType
= IntGdiCombineRgn(DirtyRgn
, VisAfter
, 0, RGN_COPY
);
2004 if (RgnType
!= ERROR
&& RgnType
!= NULLREGION
)
2007 NtGdiOffsetRgn(DirtyRgn, Window->rcWindow.left, Window->rcWindow.top);
2008 IntInvalidateWindows( Window,
2010 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
2012 GreDeleteObject(DirtyRgn);
2015 PWND Parent
= Window
->spwndParent
;
2017 REGION_bOffsetRgn( DirtyRgn
, Window
->rcWindow
.left
, Window
->rcWindow
.top
);
2019 if ( (Window
->style
& WS_CHILD
) && (Parent
) && !(Parent
->style
& WS_CLIPCHILDREN
))
2021 IntInvalidateWindows( Parent
, DirtyRgn
, RDW_ERASE
| RDW_INVALIDATE
);
2022 co_IntPaintWindows(Parent
, RDW_NOCHILDREN
, FALSE
);
2026 IntInvalidateWindows( Window
, DirtyRgn
, RDW_ERASE
| RDW_FRAME
| RDW_INVALIDATE
| RDW_ALLCHILDREN
);
2029 REGION_Delete(DirtyRgn
);
2033 if (CopyRgn
!= NULL
)
2035 REGION_Delete(CopyRgn
);
2038 /* Expose what was covered before but not covered anymore */
2039 if (VisBefore
!= NULL
)
2041 PREGION ExposedRgn
= IntSysCreateRectpRgn(0, 0, 0, 0);
2044 RgnType
= IntGdiCombineRgn(ExposedRgn
, VisBefore
, NULL
, RGN_COPY
);
2045 REGION_bOffsetRgn(ExposedRgn
,
2046 OldWindowRect
.left
- NewWindowRect
.left
,
2047 OldWindowRect
.top
- NewWindowRect
.top
);
2049 if (VisAfter
!= NULL
)
2050 RgnType
= IntGdiCombineRgn(ExposedRgn
, ExposedRgn
, VisAfter
, RGN_DIFF
);
2052 if (RgnType
!= ERROR
&& RgnType
!= NULLREGION
)
2054 co_VIS_WindowLayoutChanged(Window
, ExposedRgn
);
2056 REGION_Delete(ExposedRgn
);
2058 REGION_Delete(VisBefore
);
2061 if (VisAfter
!= NULL
)
2063 REGION_Delete(VisAfter
);
2067 if (!(WinPos
.flags
& (SWP_NOACTIVATE
|SWP_HIDEWINDOW
)))
2069 if ((Window
->style
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
2071 co_IntSendMessageNoWait(WinPos
.hwnd
, WM_CHILDACTIVATE
, 0, 0);
2075 //ERR("SetWindowPos Set FG Window!\n");
2076 if ( pti
->MessageQueue
->spwndActive
!= Window
||
2077 pti
->MessageQueue
!= gpqForeground
)
2079 //ERR("WPSWP : set active window\n");
2080 if (!(Window
->state
& WNDS_BEINGACTIVATED
)) // Inside SAW?
2082 co_IntSetForegroundWindow(Window
); // Fixes SW_HIDE issues. Wine win test_SetActiveWindow & test_SetForegroundWindow.
2089 (WinPos
.flags
& SWP_FRAMECHANGED
) &&
2090 !(WinPos
.flags
& SWP_DEFERERASE
) && // Prevent sending WM_SYNCPAINT message.
2093 PWND Parent
= Window
->spwndParent
;
2094 if ( !(Window
->style
& WS_CHILD
) && (Parent
) && (Parent
->style
& WS_CLIPCHILDREN
))
2096 TRACE("SWP_FRAMECHANGED Parent WS_CLIPCHILDREN\n");
2097 UserSyncAndPaintWindows( Parent
, RDW_CLIPCHILDREN
);
2101 // Fix wine msg test_SetFocus, prevents sending WM_WINDOWPOSCHANGED.
2102 if ( VisBefore
== NULL
&&
2103 VisBeforeJustClient
== NULL
&&
2104 !(Window
->ExStyle
& WS_EX_TOPMOST
) &&
2105 (WinPos
.flags
& SWP_AGG_STATUSFLAGS
) == (SWP_AGG_NOPOSCHANGE
& ~SWP_NOZORDER
))
2107 TRACE("No drawing, set no Z order and no redraw!\n");
2108 WinPos
.flags
|= SWP_NOZORDER
|SWP_NOREDRAW
;
2111 if(!(flags
& SWP_DEFERERASE
))
2113 /* erase parent when hiding or resizing child */
2114 if ((flags
& SWP_HIDEWINDOW
) ||
2115 (!(flags
& SWP_SHOWWINDOW
) &&
2116 (WinPos
.flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOGEOMETRYCHANGE
))
2118 PWND Parent
= Window
->spwndParent
;
2119 if (!Parent
|| UserIsDesktopWindow(Parent
)) Parent
= Window
;
2120 UserSyncAndPaintWindows( Parent
, RDW_ERASENOW
);
2123 /* Give newly shown windows a chance to redraw */
2124 if(((WinPos
.flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOPOSCHANGE
)
2125 && !(flags
& SWP_AGG_NOCLIENTCHANGE
) && (flags
& SWP_SHOWWINDOW
))
2127 UserSyncAndPaintWindows( Window
, RDW_ERASENOW
);
2131 /* And last, send the WM_WINDOWPOSCHANGED message */
2133 TRACE("\tstatus hwnd %p flags = %04x\n",Window
?Window
->head
.h
:NULL
,WinPos
.flags
& SWP_AGG_STATUSFLAGS
);
2135 if (((WinPos
.flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOPOSCHANGE
)
2136 && !((flags
& SWP_AGG_NOCLIENTCHANGE
) && (flags
& SWP_SHOWWINDOW
)))
2138 /* WM_WINDOWPOSCHANGED is sent even if SWP_NOSENDCHANGING is set
2139 and always contains final window position.
2141 WinPos
.x
= NewWindowRect
.left
;
2142 WinPos
.y
= NewWindowRect
.top
;
2143 WinPos
.cx
= NewWindowRect
.right
- NewWindowRect
.left
;
2144 WinPos
.cy
= NewWindowRect
.bottom
- NewWindowRect
.top
;
2145 TRACE("WM_WINDOWPOSCHANGED hwnd %p Flags %04x\n",WinPos
.hwnd
,WinPos
.flags
);
2146 co_IntSendMessageNoWait(WinPos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
) &WinPos
);
2149 if ( WinPos
.flags
& SWP_FRAMECHANGED
|| WinPos
.flags
& SWP_STATECHANGED
||
2150 !(WinPos
.flags
& SWP_NOCLIENTSIZE
) || !(WinPos
.flags
& SWP_NOCLIENTMOVE
) )
2152 PWND pWnd
= ValidateHwndNoErr(WinPos
.hwnd
);
2154 IntNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE
, pWnd
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
2157 if(bPointerInWindow
!= IntPtInWindow(Window
, gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
))
2159 /* Generate mouse move message */
2161 msg
.message
= WM_MOUSEMOVE
;
2162 msg
.wParam
= UserGetMouseButtonsState();
2163 msg
.lParam
= MAKELPARAM(gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
);
2164 msg
.pt
= gpsi
->ptCursor
;
2165 co_MsqInsertMouseMessage(&msg
, 0, 0, TRUE
);
2172 co_WinPosGetNonClientSize(PWND Window
, RECT
* WindowRect
, RECT
* ClientRect
)
2176 ASSERT_REFS_CO(Window
);
2178 *ClientRect
= *WindowRect
;
2179 Result
= co_IntSendMessageNoWait(Window
->head
.h
, WM_NCCALCSIZE
, FALSE
, (LPARAM
) ClientRect
);
2181 FixClientRect(ClientRect
, WindowRect
);
2187 co_WinPosSendSizeMove(PWND Wnd
)
2191 WPARAM wParam
= SIZE_RESTORED
;
2193 IntGetClientRect(Wnd
, &Rect
);
2194 lParam
= MAKELONG(Rect
.right
-Rect
.left
, Rect
.bottom
-Rect
.top
);
2196 Wnd
->state
&= ~WNDS_SENDSIZEMOVEMSGS
;
2198 if (Wnd
->style
& WS_MAXIMIZE
)
2200 wParam
= SIZE_MAXIMIZED
;
2202 else if (Wnd
->style
& WS_MINIMIZE
)
2204 wParam
= SIZE_MINIMIZED
;
2208 co_IntSendMessageNoWait(UserHMGetHandle(Wnd
), WM_SIZE
, wParam
, lParam
);
2210 if (UserIsDesktopWindow(Wnd
->spwndParent
))
2211 lParam
= MAKELONG(Wnd
->rcClient
.left
, Wnd
->rcClient
.top
);
2213 lParam
= MAKELONG(Wnd
->rcClient
.left
-Wnd
->spwndParent
->rcClient
.left
, Wnd
->rcClient
.top
-Wnd
->spwndParent
->rcClient
.top
);
2215 co_IntSendMessageNoWait(UserHMGetHandle(Wnd
), WM_MOVE
, 0, lParam
);
2217 IntEngWindowChanged(Wnd
, WOC_RGN_CLIENT
);
2221 co_WinPosMinMaximize(PWND Wnd
, UINT ShowFlag
, RECT
* NewPos
)
2224 WINDOWPLACEMENT wpl
;
2228 ASSERT_REFS_CO(Wnd
);
2230 wpl
.length
= sizeof(wpl
);
2231 IntGetWindowPlacement( Wnd
, &wpl
);
2233 if (co_HOOK_CallHooks( WH_CBT
, HCBT_MINMAX
, (WPARAM
)Wnd
->head
.h
, ShowFlag
))
2235 ERR("WinPosMinMaximize WH_CBT Call Hook return!\n");
2236 return SWP_NOSIZE
| SWP_NOMOVE
;
2238 if (Wnd
->style
& WS_MINIMIZE
)
2243 case SW_SHOWMINNOACTIVE
:
2244 case SW_SHOWMINIMIZED
:
2245 case SW_FORCEMINIMIZE
:
2246 return SWP_NOSIZE
| SWP_NOMOVE
;
2248 if (!co_IntSendMessageNoWait(Wnd
->head
.h
, WM_QUERYOPEN
, 0, 0))
2250 return(SWP_NOSIZE
| SWP_NOMOVE
);
2252 SwpFlags
|= SWP_NOCOPYBITS
;
2257 case SW_SHOWMINNOACTIVE
:
2258 case SW_SHOWMINIMIZED
:
2259 case SW_FORCEMINIMIZE
:
2261 //ERR("MinMaximize Minimize\n");
2262 if (Wnd
->style
& WS_MAXIMIZE
)
2264 Wnd
->InternalPos
.flags
|= WPF_RESTORETOMAXIMIZED
;
2268 Wnd
->InternalPos
.flags
&= ~WPF_RESTORETOMAXIMIZED
;
2271 old_style
= IntSetStyle( Wnd
, WS_MINIMIZE
, WS_MAXIMIZE
);
2273 co_UserRedrawWindow(Wnd
, NULL
, 0, RDW_VALIDATE
| RDW_NOERASE
| RDW_NOINTERNALPAINT
);
2275 if (!(Wnd
->InternalPos
.flags
& WPF_SETMINPOSITION
))
2276 Wnd
->InternalPos
.flags
&= ~WPF_MININIT
;
2278 WinPosFindIconPos(Wnd
, &wpl
.ptMinPosition
);
2280 /*if (!(old_style & WS_MINIMIZE))
2282 SwpFlags |= SWP_STATECHANGED;
2283 IntShowOwnedPopups(Wnd, FALSE);
2286 RECTL_vSetRect(NewPos
, wpl
.ptMinPosition
.x
, wpl
.ptMinPosition
.y
,
2287 wpl
.ptMinPosition
.x
+ UserGetSystemMetrics(SM_CXMINIMIZED
),
2288 wpl
.ptMinPosition
.y
+ UserGetSystemMetrics(SM_CYMINIMIZED
));
2289 SwpFlags
|= SWP_NOCOPYBITS
;
2295 //ERR("MinMaximize Maximize\n");
2296 if ((Wnd
->style
& WS_MAXIMIZE
) && (Wnd
->style
& WS_VISIBLE
))
2298 SwpFlags
= SWP_NOSIZE
| SWP_NOMOVE
;
2301 co_WinPosGetMinMaxInfo(Wnd
, &Size
, &wpl
.ptMaxPosition
, NULL
, NULL
);
2303 /*ERR("Maximize: %d,%d %dx%d\n",
2304 wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, Size.x, Size.y);
2306 old_style
= IntSetStyle( Wnd
, WS_MAXIMIZE
, WS_MINIMIZE
);
2307 /*if (old_style & WS_MINIMIZE)
2309 IntShowOwnedPopups(Wnd, TRUE);
2312 if (!(old_style
& WS_MAXIMIZE
)) SwpFlags
|= SWP_STATECHANGED
;
2313 RECTL_vSetRect(NewPos
, wpl
.ptMaxPosition
.x
, wpl
.ptMaxPosition
.y
,
2314 //wpl.ptMaxPosition.x + Size.x, wpl.ptMaxPosition.y + Size.y);
2319 case SW_SHOWNOACTIVATE
:
2320 Wnd
->InternalPos
.flags
&= ~WPF_RESTORETOMAXIMIZED
;
2324 case SW_SHOWDEFAULT
: /* FIXME: should have its own handler */
2326 //ERR("MinMaximize Restore\n");
2327 old_style
= IntSetStyle( Wnd
, 0, WS_MINIMIZE
| WS_MAXIMIZE
);
2328 if (old_style
& WS_MINIMIZE
)
2330 //IntShowOwnedPopups(Wnd, TRUE);
2332 if (Wnd
->InternalPos
.flags
& WPF_RESTORETOMAXIMIZED
)
2334 co_WinPosGetMinMaxInfo(Wnd
, &Size
, &wpl
.ptMaxPosition
, NULL
, NULL
);
2335 IntSetStyle( Wnd
, WS_MAXIMIZE
, 0 );
2336 SwpFlags
|= SWP_STATECHANGED
;
2337 RECTL_vSetRect(NewPos
, wpl
.ptMaxPosition
.x
, wpl
.ptMaxPosition
.y
,
2338 wpl
.ptMaxPosition
.x
+ Size
.x
, wpl
.ptMaxPosition
.y
+ Size
.y
);
2343 *NewPos
= wpl
.rcNormalPosition
;
2344 NewPos
->right
-= NewPos
->left
;
2345 NewPos
->bottom
-= NewPos
->top
;
2351 if (!(old_style
& WS_MAXIMIZE
))
2355 SwpFlags
|= SWP_STATECHANGED
;
2356 Wnd
->InternalPos
.flags
&= ~WPF_RESTORETOMAXIMIZED
;
2357 *NewPos
= wpl
.rcNormalPosition
;
2358 NewPos
->right
-= NewPos
->left
;
2359 NewPos
->bottom
-= NewPos
->top
;
2368 ShowWindow does not set SWP_FRAMECHANGED!!! Fix wine msg test_SetParent:WmSetParentSeq_2:23 wParam bits!
2371 co_WinPosShowWindow(PWND Wnd
, INT Cmd
)
2374 UINT Swp
= 0, EventMsg
= 0;
2375 RECTL NewPos
= {0, 0, 0, 0};
2381 BOOL ShowOwned
= FALSE
;
2382 BOOL FirstTime
= FALSE
;
2383 ASSERT_REFS_CO(Wnd
);
2384 //KeRosDumpStackFrames(NULL, 20);
2385 pti
= PsGetCurrentThreadWin32Thread();
2386 WasVisible
= (Wnd
->style
& WS_VISIBLE
) != 0;
2389 TRACE("co_WinPosShowWindow START hwnd %p Cmd %d usicmd %u\n",
2390 Wnd
->head
.h
, Cmd
, pti
->ppi
->usi
.wShowWindow
);
2392 if ( pti
->ppi
->usi
.dwFlags
& STARTF_USESHOWWINDOW
)
2394 if ((Wnd
->style
& (WS_POPUP
|WS_CHILD
)) != WS_CHILD
)
2396 if ((Wnd
->style
& WS_CAPTION
) == WS_CAPTION
)
2398 if (Wnd
->spwndOwner
== NULL
)
2400 if ( Cmd
== SW_SHOWNORMAL
|| Cmd
== SW_SHOW
)
2402 Cmd
= SW_SHOWDEFAULT
;
2405 TRACE("co_WPSW FT 1\n");
2411 if ( Cmd
== SW_SHOWDEFAULT
)
2413 if ( pti
->ppi
->usi
.dwFlags
& STARTF_USESHOWWINDOW
)
2415 Cmd
= pti
->ppi
->usi
.wShowWindow
;
2417 TRACE("co_WPSW FT 2\n");
2423 pti
->ppi
->usi
.dwFlags
&= ~(STARTF_USEPOSITION
|STARTF_USESIZE
|STARTF_USESHOWWINDOW
);
2432 //ERR("co_WinPosShowWindow Exit Bad\n");
2435 Swp
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
2436 if (Wnd
!= pti
->MessageQueue
->spwndActive
)
2437 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2441 case SW_FORCEMINIMIZE
: /* FIXME: Does not work if thread is hung. */
2442 case SW_SHOWMINNOACTIVE
:
2443 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2445 case SW_SHOWMINIMIZED
:
2446 Swp
|= SWP_SHOWWINDOW
;
2450 Swp
|= SWP_NOACTIVATE
;
2451 if (!(style
& WS_MINIMIZE
))
2453 IntShowOwnedPopups(Wnd
, FALSE
);
2454 // Fix wine Win test_SetFocus todo #1 & #2,
2455 if (Cmd
== SW_SHOWMINIMIZED
)
2457 //ERR("co_WinPosShowWindow Set focus 1\n");
2458 if ((style
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
2459 co_UserSetFocus(Wnd
->spwndParent
);
2464 Swp
|= co_WinPosMinMaximize(Wnd
, Cmd
, &NewPos
);
2466 EventMsg
= EVENT_SYSTEM_MINIMIZESTART
;
2472 //ERR("co_WinPosShowWindow Exit Good\n");
2475 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
2480 case SW_SHOWMAXIMIZED
:
2482 Swp
|= SWP_SHOWWINDOW
;
2483 if (!(style
& WS_MAXIMIZE
))
2487 Swp
|= co_WinPosMinMaximize(Wnd
, SW_MAXIMIZE
, &NewPos
);
2489 EventMsg
= EVENT_SYSTEM_MINIMIZEEND
;
2495 //ERR("co_WinPosShowWindow Exit Good 1\n");
2498 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
2504 Swp
|= SWP_NOACTIVATE
| SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
2505 if (style
& WS_CHILD
&& !(Wnd
->ExStyle
& WS_EX_MDICHILD
)) Swp
|= SWP_NOZORDER
;
2508 if (WasVisible
) return(TRUE
); // Nothing to do!
2509 Swp
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
2510 /* Don't activate the topmost window. */
2511 if (style
& WS_CHILD
&& !(Wnd
->ExStyle
& WS_EX_MDICHILD
)) Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2514 case SW_SHOWNOACTIVATE
:
2515 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2518 case SW_SHOWDEFAULT
:
2520 if (!WasVisible
) Swp
|= SWP_SHOWWINDOW
;
2521 if (style
& (WS_MINIMIZE
| WS_MAXIMIZE
))
2523 Swp
|= co_WinPosMinMaximize(Wnd
, Cmd
, &NewPos
);
2524 if (style
& WS_MINIMIZE
) EventMsg
= EVENT_SYSTEM_MINIMIZEEND
;
2530 //ERR("co_WinPosShowWindow Exit Good 3\n");
2533 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
2535 if ( style
& WS_CHILD
&&
2536 !(Wnd
->ExStyle
& WS_EX_MDICHILD
) &&
2537 !(Swp
& SWP_STATECHANGED
))
2538 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2542 //ERR("co_WinPosShowWindow Exit Good 4\n");
2546 ShowFlag
= (Cmd
!= SW_HIDE
);
2548 if ((ShowFlag
!= WasVisible
|| Cmd
== SW_SHOWNA
) && Cmd
!= SW_SHOWMAXIMIZED
&& !(Swp
& SWP_STATECHANGED
))
2550 co_IntSendMessageNoWait(Wnd
->head
.h
, WM_SHOWWINDOW
, ShowFlag
, 0);
2551 #if 0 // Fix wine msg test_SetParent:WmSetParentSeq_1:2
2552 if (!(Wnd
->state2
& WNDS2_WIN31COMPAT
)) // <------------- XP sets this bit!
2553 co_IntSendMessageNoWait(Wnd
->head
.h
, WM_SETVISIBLE
, ShowFlag
, 0);
2555 if (!VerifyWnd(Wnd
)) return WasVisible
;
2558 /* We can't activate a child window */
2559 if ((Wnd
->style
& WS_CHILD
) &&
2560 !(Wnd
->ExStyle
& WS_EX_MDICHILD
) &&
2563 //ERR("SWP Child No active and ZOrder\n");
2564 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2567 #if 0 // Explorer issues with common controls? Someone does not know how CS_SAVEBITS works.
2568 // Breaks startup and shutdown active window...
2569 if ((Wnd
->style
& (WS_POPUP
|WS_CHILD
)) != WS_CHILD
&&
2570 Wnd
->pcls
->style
& CS_SAVEBITS
&&
2571 ((Cmd
== SW_SHOW
) || (Cmd
== SW_NORMAL
)))
2573 ERR("WinPosShowWindow Set active\n");
2574 //UserSetActiveWindow(Wnd);
2575 co_IntSetForegroundWindow(Wnd
); // HACK
2576 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2580 if (IsChildVisible(Wnd
) || Swp
& SWP_STATECHANGED
)
2582 TRACE("Child is Vis %s or State changed %s. ShowFlag %s Swp %04x\n",
2583 (IsChildVisible(Wnd
) ? "TRUE" : "FALSE"), (Swp
& SWP_STATECHANGED
? "TRUE" : "FALSE"),
2584 (ShowFlag
? "TRUE" : "FALSE"),LOWORD(Swp
));
2585 co_WinPosSetWindowPos( Wnd
,
2586 0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
) ? HWND_TOPMOST
: HWND_TOP
,
2589 NewPos
.right
, // NewPos.right - NewPos.left, when minimized and restore, the window becomes smaller.
2590 NewPos
.bottom
,// NewPos.bottom - NewPos.top,
2595 TRACE("Parent Vis?\n");
2596 /* if parent is not visible simply toggle WS_VISIBLE and return */
2597 if (ShowFlag
) IntSetStyle( Wnd
, WS_VISIBLE
, 0 );
2598 else IntSetStyle( Wnd
, 0, WS_VISIBLE
);
2601 if ( EventMsg
) IntNotifyWinEvent(EventMsg
, Wnd
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
2603 if ( ShowOwned
) IntShowOwnedPopups(Wnd
, TRUE
);
2605 if ((Cmd
== SW_HIDE
) || (Cmd
== SW_MINIMIZE
))
2607 if ( Wnd
== pti
->MessageQueue
->spwndActive
&& pti
->MessageQueue
== IntGetFocusMessageQueue() )
2609 if (UserIsDesktopWindow(Wnd
->spwndParent
))
2611 if (!ActivateOtherWindowMin(Wnd
))
2613 co_WinPosActivateOtherWindow(Wnd
);
2618 co_WinPosActivateOtherWindow(Wnd
);
2622 /* Revert focus to parent */
2623 if (Wnd
== pti
->MessageQueue
->spwndFocus
)
2625 Parent
= Wnd
->spwndParent
;
2626 if (UserIsDesktopWindow(Wnd
->spwndParent
))
2628 co_UserSetFocus(Parent
);
2630 // Hide, just return.
2631 if (Cmd
== SW_HIDE
) return WasVisible
;
2634 /* FIXME: Check for window destruction. */
2636 if ((Wnd
->state
& WNDS_SENDSIZEMOVEMSGS
) &&
2637 !(Wnd
->state2
& WNDS2_INDESTROY
))
2639 co_WinPosSendSizeMove(Wnd
);
2642 /* if previous state was minimized Windows sets focus to the window */
2643 if (style
& WS_MINIMIZE
)
2645 co_UserSetFocus(Wnd
);
2646 // Fix wine Win test_SetFocus todo #3,
2647 if (!(style
& WS_CHILD
)) co_IntSendMessage(UserHMGetHandle(Wnd
), WM_ACTIVATE
, WA_ACTIVE
, 0);
2649 //ERR("co_WinPosShowWindow EXIT\n");
2654 co_WinPosSearchChildren(
2657 IN OUT USHORT
*HitTest
,
2662 PWND pwndChild
= NULL
;
2665 if (!(ScopeWin
->style
& WS_VISIBLE
))
2670 /* not in window or in window region */
2671 if (!IntPtInWindow(ScopeWin
, Point
->x
, Point
->y
))
2677 if ((ScopeWin
->ExStyle
& (WS_EX_LAYERED
|WS_EX_TRANSPARENT
)) == (WS_EX_LAYERED
|WS_EX_TRANSPARENT
))
2682 if (!Ignore
&& (ScopeWin
->style
& WS_DISABLED
))
2683 { /* disabled child */
2684 if ((ScopeWin
->style
& (WS_POPUP
|WS_CHILD
)) == WS_CHILD
) return NULL
;
2685 /* process the hit error */
2690 /* not minimized and check if point is inside the window */
2691 if (!(ScopeWin
->style
& WS_MINIMIZE
) &&
2692 RECTL_bPointInRect(&ScopeWin
->rcClient
, Point
->x
, Point
->y
) )
2694 UserReferenceObject(ScopeWin
);
2696 List
= IntWinListChildren(ScopeWin
);
2699 for (phWnd
= List
; *phWnd
; ++phWnd
)
2701 if (!(pwndChild
= ValidateHwndNoErr(*phWnd
)))
2706 pwndChild
= co_WinPosSearchChildren(pwndChild
, Point
, HitTest
, Ignore
);
2708 if (pwndChild
!= NULL
)
2710 /* We found a window. Don't send any more WM_NCHITTEST messages */
2711 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2712 UserDereferenceObject(ScopeWin
);
2716 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2718 UserDereferenceObject(ScopeWin
);
2721 if (ScopeWin
->head
.pti
== PsGetCurrentThreadWin32Thread())
2723 *HitTest
= (USHORT
)co_IntSendMessage(ScopeWin
->head
.h
, WM_NCHITTEST
, 0, MAKELONG(Point
->x
, Point
->y
));
2725 if ((*HitTest
) == (USHORT
)HTTRANSPARENT
)
2732 if (*HitTest
== HTNOWHERE
&& pwndChild
== NULL
) *HitTest
= HTCLIENT
;
2739 co_WinPosWindowFromPoint(
2742 IN OUT USHORT
* HitTest
,
2746 POINT Point
= *WinPoint
;
2747 USER_REFERENCE_ENTRY Ref
;
2749 if( ScopeWin
== NULL
)
2751 ScopeWin
= UserGetDesktopWindow();
2752 if(ScopeWin
== NULL
)
2756 *HitTest
= HTNOWHERE
;
2758 ASSERT_REFS_CO(ScopeWin
);
2759 UserRefObjectCo(ScopeWin
, &Ref
);
2761 Window
= co_WinPosSearchChildren(ScopeWin
, &Point
, HitTest
, Ignore
);
2763 UserDerefObjectCo(ScopeWin
);
2765 ASSERT_REFS_CO(Window
);
2766 ASSERT_REFS_CO(ScopeWin
);
2772 IntRealChildWindowFromPoint(PWND Parent
, LONG x
, LONG y
)
2776 PWND pwndHit
= NULL
;
2781 if (!UserIsDesktopWindow(Parent
))
2783 Pt
.x
+= Parent
->rcClient
.left
;
2784 Pt
.y
+= Parent
->rcClient
.top
;
2787 if (!IntPtInWindow(Parent
, Pt
.x
, Pt
.y
)) return NULL
;
2789 if ((List
= IntWinListChildren(Parent
)))
2791 for (phWnd
= List
; *phWnd
; phWnd
++)
2794 if ((Child
= ValidateHwndNoErr(*phWnd
)))
2796 if ( Child
->style
& WS_VISIBLE
&& IntPtInWindow(Child
, Pt
.x
, Pt
.y
) )
2798 if ( Child
->pcls
->atomClassName
!= gpsi
->atomSysClass
[ICLS_BUTTON
] ||
2799 (Child
->style
& BS_TYPEMASK
) != BS_GROUPBOX
)
2801 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2808 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2810 return pwndHit
? pwndHit
: Parent
;
2814 IntChildWindowFromPointEx(PWND Parent
, LONG x
, LONG y
, UINT uiFlags
)
2818 PWND pwndHit
= NULL
;
2823 if (!UserIsDesktopWindow(Parent
))
2825 if (Parent
->ExStyle
& WS_EX_LAYOUTRTL
)
2826 Pt
.x
= Parent
->rcClient
.right
- Pt
.x
;
2828 Pt
.x
+= Parent
->rcClient
.left
;
2829 Pt
.y
+= Parent
->rcClient
.top
;
2832 if (!IntPtInWindow(Parent
, Pt
.x
, Pt
.y
)) return NULL
;
2834 if ((List
= IntWinListChildren(Parent
)))
2836 for (phWnd
= List
; *phWnd
; phWnd
++)
2839 if ((Child
= ValidateHwndNoErr(*phWnd
)))
2841 if (uiFlags
& (CWP_SKIPINVISIBLE
|CWP_SKIPDISABLED
))
2843 if (!(Child
->style
& WS_VISIBLE
) && (uiFlags
& CWP_SKIPINVISIBLE
)) continue;
2844 if ((Child
->style
& WS_DISABLED
) && (uiFlags
& CWP_SKIPDISABLED
)) continue;
2847 if (uiFlags
& CWP_SKIPTRANSPARENT
)
2849 if (Child
->ExStyle
& WS_EX_TRANSPARENT
) continue;
2852 if (IntPtInWindow(Child
, Pt
.x
, Pt
.y
))
2859 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2861 return pwndHit
? pwndHit
: Parent
;
2866 IntDeferWindowPos( HDWP hdwp
,
2877 HDWP retvalue
= hdwp
;
2879 TRACE("hdwp %p, hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
2880 hdwp
, hwnd
, hwndAfter
, x
, y
, cx
, cy
, flags
);
2882 if (flags
& ~(SWP_NOSIZE
| SWP_NOMOVE
|
2883 SWP_NOZORDER
| SWP_NOREDRAW
|
2884 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
2885 SWP_NOOWNERZORDER
|SWP_SHOWWINDOW
|
2886 SWP_HIDEWINDOW
| SWP_FRAMECHANGED
))
2888 EngSetLastError(ERROR_INVALID_PARAMETER
);
2892 if (!(pDWP
= (PSMWP
)UserGetObject(gHandleTable
, hdwp
, TYPE_SETWINDOWPOS
)))
2894 EngSetLastError(ERROR_INVALID_DWP_HANDLE
);
2898 for (i
= 0; i
< pDWP
->ccvr
; i
++)
2900 if (pDWP
->acvr
[i
].pos
.hwnd
== hwnd
)
2902 /* Merge with the other changes */
2903 if (!(flags
& SWP_NOZORDER
))
2905 pDWP
->acvr
[i
].pos
.hwndInsertAfter
= hwndAfter
;
2907 if (!(flags
& SWP_NOMOVE
))
2909 pDWP
->acvr
[i
].pos
.x
= x
;
2910 pDWP
->acvr
[i
].pos
.y
= y
;
2912 if (!(flags
& SWP_NOSIZE
))
2914 pDWP
->acvr
[i
].pos
.cx
= cx
;
2915 pDWP
->acvr
[i
].pos
.cy
= cy
;
2917 pDWP
->acvr
[i
].pos
.flags
&= flags
| ~(SWP_NOSIZE
| SWP_NOMOVE
|
2918 SWP_NOZORDER
| SWP_NOREDRAW
|
2919 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
2921 pDWP
->acvr
[i
].pos
.flags
|= flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
|
2926 if (pDWP
->ccvr
>= pDWP
->ccvrAlloc
)
2928 PCVR newpos
= ExAllocatePoolWithTag(PagedPool
, pDWP
->ccvrAlloc
* 2 * sizeof(CVR
), USERTAG_SWP
);
2934 RtlZeroMemory(newpos
, pDWP
->ccvrAlloc
* 2 * sizeof(CVR
));
2935 RtlCopyMemory(newpos
, pDWP
->acvr
, pDWP
->ccvrAlloc
* sizeof(CVR
));
2936 ExFreePoolWithTag(pDWP
->acvr
, USERTAG_SWP
);
2937 pDWP
->ccvrAlloc
*= 2;
2938 pDWP
->acvr
= newpos
;
2940 pDWP
->acvr
[pDWP
->ccvr
].pos
.hwnd
= hwnd
;
2941 pDWP
->acvr
[pDWP
->ccvr
].pos
.hwndInsertAfter
= hwndAfter
;
2942 pDWP
->acvr
[pDWP
->ccvr
].pos
.x
= x
;
2943 pDWP
->acvr
[pDWP
->ccvr
].pos
.y
= y
;
2944 pDWP
->acvr
[pDWP
->ccvr
].pos
.cx
= cx
;
2945 pDWP
->acvr
[pDWP
->ccvr
].pos
.cy
= cy
;
2946 pDWP
->acvr
[pDWP
->ccvr
].pos
.flags
= flags
;
2947 pDWP
->acvr
[pDWP
->ccvr
].hrgnClip
= NULL
;
2948 pDWP
->acvr
[pDWP
->ccvr
].hrgnInterMonitor
= NULL
;
2954 BOOL FASTCALL
IntEndDeferWindowPosEx( HDWP hdwp
, BOOL sAsync
)
2961 TRACE("%p\n", hdwp
);
2963 if (!(pDWP
= (PSMWP
)UserGetObject(gHandleTable
, hdwp
, TYPE_SETWINDOWPOS
)))
2965 EngSetLastError(ERROR_INVALID_DWP_HANDLE
);
2969 for (i
= 0, winpos
= pDWP
->acvr
; res
&& i
< pDWP
->ccvr
; i
++, winpos
++)
2972 USER_REFERENCE_ENTRY Ref
;
2974 TRACE("hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
2975 winpos
->pos
.hwnd
, winpos
->pos
.hwndInsertAfter
, winpos
->pos
.x
, winpos
->pos
.y
,
2976 winpos
->pos
.cx
, winpos
->pos
.cy
, winpos
->pos
.flags
);
2978 pwnd
= ValidateHwndNoErr(winpos
->pos
.hwnd
);
2982 UserRefObjectCo(pwnd
, &Ref
);
2987 PWINDOWPOS ppos
= ExAllocatePoolWithTag(PagedPool
, sizeof(WINDOWPOS
), USERTAG_SWP
);
2990 *ppos
= winpos
->pos
;
2991 /* Yes it's a pointer inside Win32k! */
2992 lRes
= co_IntSendMessageNoWait( winpos
->pos
.hwnd
, WM_ASYNC_SETWINDOWPOS
, 0, (LPARAM
)ppos
);
2993 /* We handle this the same way as Event Hooks and Hooks. */
2996 ExFreePoolWithTag(ppos
, USERTAG_SWP
);
3001 res
= co_WinPosSetWindowPos( pwnd
,
3002 winpos
->pos
.hwndInsertAfter
,
3009 // Hack to pass tests.... Must have some work to do so clear the error.
3010 if (res
&& (winpos
->pos
.flags
& (SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOZORDER
)) == SWP_NOZORDER
)
3011 EngSetLastError(ERROR_SUCCESS
);
3013 UserDerefObjectCo(pwnd
);
3015 ExFreePoolWithTag(pDWP
->acvr
, USERTAG_SWP
);
3016 UserDereferenceObject(pDWP
);
3017 UserDeleteObject(hdwp
, TYPE_SETWINDOWPOS
);
3025 NtUserChildWindowFromPointEx(HWND hwndParent
,
3031 TRACE("Enter NtUserChildWindowFromPointEx\n");
3032 UserEnterExclusive();
3033 if ((pwndParent
= UserGetWindowObject(hwndParent
)))
3035 pwndParent
= IntChildWindowFromPointEx(pwndParent
, x
, y
, uiFlags
);
3038 TRACE("Leave NtUserChildWindowFromPointEx\n");
3039 return pwndParent
? UserHMGetHandle(pwndParent
) : NULL
;
3046 NtUserEndDeferWindowPosEx(HDWP WinPosInfo
,
3050 TRACE("Enter NtUserEndDeferWindowPosEx\n");
3051 UserEnterExclusive();
3052 Ret
= IntEndDeferWindowPosEx(WinPosInfo
, (BOOL
)Unknown1
);
3053 TRACE("Leave NtUserEndDeferWindowPosEx, ret=%i\n", Ret
);
3062 NtUserDeferWindowPos(HDWP WinPosInfo
,
3064 HWND WndInsertAfter
,
3073 UINT Tmp
= ~(SWP_ASYNCWINDOWPOS
|SWP_DEFERERASE
|SWP_NOSENDCHANGING
|SWP_NOREPOSITION
|
3074 SWP_NOCOPYBITS
|SWP_HIDEWINDOW
|SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|
3075 SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_NOZORDER
|SWP_NOMOVE
|SWP_NOSIZE
);
3077 TRACE("Enter NtUserDeferWindowPos\n");
3078 UserEnterExclusive();
3082 EngSetLastError(ERROR_INVALID_FLAGS
);
3086 pWnd
= UserGetWindowObject(Wnd
);
3087 if (!pWnd
|| UserIsDesktopWindow(pWnd
) || UserIsMessageWindow(pWnd
))
3092 if ( WndInsertAfter
&&
3093 WndInsertAfter
!= HWND_BOTTOM
&&
3094 WndInsertAfter
!= HWND_TOPMOST
&&
3095 WndInsertAfter
!= HWND_NOTOPMOST
)
3097 pWndIA
= UserGetWindowObject(WndInsertAfter
);
3098 if (!pWndIA
|| UserIsDesktopWindow(pWndIA
) || UserIsMessageWindow(pWndIA
))
3104 Ret
= IntDeferWindowPos(WinPosInfo
, Wnd
, WndInsertAfter
, x
, y
, cx
, cy
, Flags
);
3107 TRACE("Leave NtUserDeferWindowPos, ret=%p\n", Ret
);
3116 NtUserGetInternalWindowPos( HWND hWnd
,
3123 WINDOWPLACEMENT wndpl
;
3127 if (!(Window
= UserGetWindowObject(hWnd
)))
3137 ProbeForWrite(rectWnd
,
3143 ProbeForWrite(ptIcon
,
3149 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3151 SetLastNtError(_SEH2_GetExceptionCode());
3156 wndpl
.length
= sizeof(WINDOWPLACEMENT
);
3158 if (IntGetWindowPlacement(Window
, &wndpl
) && !Hit
)
3164 RtlCopyMemory(rectWnd
, &wndpl
.rcNormalPosition
, sizeof(RECT
));
3168 RtlCopyMemory(ptIcon
, &wndpl
.ptMinPosition
, sizeof(POINT
));
3172 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3174 SetLastNtError(_SEH2_GetExceptionCode());
3179 if (!Hit
) Ret
= wndpl
.showCmd
;
3190 NtUserGetWindowPlacement(HWND hWnd
,
3191 WINDOWPLACEMENT
*lpwndpl
)
3194 WINDOWPLACEMENT Safepl
;
3196 DECLARE_RETURN(BOOL
);
3198 TRACE("Enter NtUserGetWindowPlacement\n");
3201 if (!(Wnd
= UserGetWindowObject(hWnd
)))
3206 Status
= MmCopyFromCaller(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
3207 if (!NT_SUCCESS(Status
))
3209 SetLastNtError(Status
);
3213 Safepl
.length
= sizeof(WINDOWPLACEMENT
);
3215 IntGetWindowPlacement(Wnd
, &Safepl
);
3217 Status
= MmCopyToCaller(lpwndpl
, &Safepl
, sizeof(WINDOWPLACEMENT
));
3218 if (!NT_SUCCESS(Status
))
3220 SetLastNtError(Status
);
3227 TRACE("Leave NtUserGetWindowPlacement, ret=%i\n",_ret_
);
3236 UINT cmd
, // Wine SW_ commands
3241 TRACE("Enter NtUserMinMaximize\n");
3242 UserEnterExclusive();
3244 pWnd
= UserGetWindowObject(hWnd
);
3245 if (!pWnd
|| UserIsDesktopWindow(pWnd
) || UserIsMessageWindow(pWnd
))
3250 if ( cmd
> SW_MAX
|| pWnd
->state2
& WNDS2_INDESTROY
)
3252 EngSetLastError(ERROR_INVALID_PARAMETER
);
3256 cmd
|= Hide
? SW_HIDE
: 0;
3258 co_WinPosShowWindow(pWnd
, cmd
);
3261 TRACE("Leave NtUserMinMaximize\n");
3263 return 0; // Always NULL?
3278 return NtUserSetWindowPos(hWnd
, 0, X
, Y
, nWidth
, nHeight
,
3279 (bRepaint
? SWP_NOZORDER
| SWP_NOACTIVATE
:
3280 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
));
3287 NtUserRealChildWindowFromPoint(HWND Parent
,
3292 TRACE("Enter NtUserRealChildWindowFromPoint\n");
3294 if ((pwndParent
= UserGetWindowObject(Parent
)))
3296 pwndParent
= IntRealChildWindowFromPoint(pwndParent
, x
, y
);
3299 TRACE("Leave NtUserRealChildWindowFromPoint\n");
3300 return pwndParent
? UserHMGetHandle(pwndParent
) : NULL
;
3309 HWND hWndInsertAfter
,
3316 DECLARE_RETURN(BOOL
);
3317 PWND Window
, pWndIA
;
3319 USER_REFERENCE_ENTRY Ref
;
3321 TRACE("Enter NtUserSetWindowPos\n");
3322 UserEnterExclusive();
3324 if (!(Window
= UserGetWindowObject(hWnd
)) ||
3325 UserIsDesktopWindow(Window
) || UserIsMessageWindow(Window
))
3327 ERR("NtUserSetWindowPos bad window handle!\n");
3331 if ( hWndInsertAfter
&&
3332 hWndInsertAfter
!= HWND_BOTTOM
&&
3333 hWndInsertAfter
!= HWND_TOPMOST
&&
3334 hWndInsertAfter
!= HWND_NOTOPMOST
)
3336 if (!(pWndIA
= UserGetWindowObject(hWndInsertAfter
)) ||
3337 UserIsDesktopWindow(pWndIA
) || UserIsMessageWindow(pWndIA
))
3339 ERR("NtUserSetWindowPos bad insert window handle!\n");
3344 /* First make sure that coordinates are valid for WM_WINDOWPOSCHANGING */
3345 if (!(uFlags
& SWP_NOMOVE
))
3347 if (X
< -32768) X
= -32768;
3348 else if (X
> 32767) X
= 32767;
3349 if (Y
< -32768) Y
= -32768;
3350 else if (Y
> 32767) Y
= 32767;
3352 if (!(uFlags
& SWP_NOSIZE
))
3355 else if (cx
> 32767) cx
= 32767;
3357 else if (cy
> 32767) cy
= 32767;
3360 UserRefObjectCo(Window
, &Ref
);
3361 ret
= co_WinPosSetWindowPos(Window
, hWndInsertAfter
, X
, Y
, cx
, cy
, uFlags
);
3362 UserDerefObjectCo(Window
);
3367 TRACE("Leave NtUserSetWindowPos, ret=%i\n",_ret_
);
3381 HRGN hrgnCopy
= NULL
;
3383 INT flags
= (SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
);
3384 BOOLEAN Ret
= FALSE
;
3385 DECLARE_RETURN(INT
);
3387 TRACE("Enter NtUserSetWindowRgn\n");
3388 UserEnterExclusive();
3390 if (!(Window
= UserGetWindowObject(hWnd
)) ||
3391 UserIsDesktopWindow(Window
) || UserIsMessageWindow(Window
))
3396 if (hRgn
) // The region will be deleted in user32.
3398 if (GreIsHandleValid(hRgn
))
3400 hrgnCopy
= NtGdiCreateRectRgn(0, 0, 0, 0);
3401 /* The coordinates of a window's window region are relative to the
3402 upper-left corner of the window, not the client area of the window. */
3403 NtGdiCombineRgn( hrgnCopy
, hRgn
, 0, RGN_COPY
);
3409 //// HACK 1 : Work around the lack of supporting DeferWindowPos.
3412 Window
->hrgnNewFrame
= hrgnCopy
; // Should be PSMWP->acvr->hrgnClip
3416 Window
->hrgnNewFrame
= HRGN_WINDOW
;
3419 Ret
= co_WinPosSetWindowPos(Window
, HWND_TOP
, 0, 0, 0, 0, bRedraw
? flags
: (flags
|SWP_NOREDRAW
) );
3424 TRACE("Leave NtUserSetWindowRgn, ret=%i\n",_ret_
);
3433 NtUserSetInternalWindowPos(
3439 WINDOWPLACEMENT wndpl
;
3444 DECLARE_RETURN(BOOL
);
3445 USER_REFERENCE_ENTRY Ref
;
3447 TRACE("Enter NtUserSetWindowPlacement\n");
3448 UserEnterExclusive();
3450 if (!(Wnd
= UserGetWindowObject(hwnd
)) || // FIXME:
3451 UserIsDesktopWindow(Wnd
) || UserIsMessageWindow(Wnd
))
3460 ProbeForRead(lppt
, sizeof(POINT
), 1);
3461 RtlCopyMemory(&pt
, lppt
, sizeof(POINT
));
3465 ProbeForRead(lprect
, sizeof(RECT
), 1);
3466 RtlCopyMemory(&rect
, lprect
, sizeof(RECT
));
3469 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3471 SetLastNtError(_SEH2_GetExceptionCode());
3472 _SEH2_YIELD(RETURN( FALSE
));
3476 wndpl
.length
= sizeof(wndpl
);
3477 wndpl
.showCmd
= showCmd
;
3478 wndpl
.flags
= flags
= 0;
3483 wndpl
.flags
|= WPF_SETMINPOSITION
;
3484 wndpl
.ptMinPosition
= pt
;
3488 flags
|= PLACE_RECT
;
3489 wndpl
.rcNormalPosition
= rect
;
3492 UserRefObjectCo(Wnd
, &Ref
);
3493 IntSetWindowPlacement(Wnd
, &wndpl
, flags
);
3494 UserDerefObjectCo(Wnd
);
3498 TRACE("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_
);
3507 NtUserSetWindowPlacement(HWND hWnd
,
3508 WINDOWPLACEMENT
*lpwndpl
)
3511 WINDOWPLACEMENT Safepl
;
3513 DECLARE_RETURN(BOOL
);
3514 USER_REFERENCE_ENTRY Ref
;
3516 TRACE("Enter NtUserSetWindowPlacement\n");
3517 UserEnterExclusive();
3519 if (!(Wnd
= UserGetWindowObject(hWnd
)) ||
3520 UserIsDesktopWindow(Wnd
) || UserIsMessageWindow(Wnd
))
3527 ProbeForRead(lpwndpl
, sizeof(WINDOWPLACEMENT
), 1);
3528 RtlCopyMemory(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
3530 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3532 SetLastNtError(_SEH2_GetExceptionCode());
3533 _SEH2_YIELD(RETURN( FALSE
));
3537 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
3542 Flags
= PLACE_MAX
| PLACE_RECT
;
3543 if (Safepl
.flags
& WPF_SETMINPOSITION
) Flags
|= PLACE_MIN
;
3544 UserRefObjectCo(Wnd
, &Ref
);
3545 IntSetWindowPlacement(Wnd
, &Safepl
, Flags
);
3546 UserDerefObjectCo(Wnd
);
3550 TRACE("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_
);
3559 NtUserShowWindowAsync(HWND hWnd
, LONG nCmdShow
)
3563 DECLARE_RETURN(BOOL
);
3564 USER_REFERENCE_ENTRY Ref
;
3566 TRACE("Enter NtUserShowWindowAsync\n");
3567 UserEnterExclusive();
3569 if (!(Window
= UserGetWindowObject(hWnd
)) ||
3570 UserIsDesktopWindow(Window
) || UserIsMessageWindow(Window
))
3575 if ( nCmdShow
> SW_MAX
)
3577 EngSetLastError(ERROR_INVALID_PARAMETER
);
3581 UserRefObjectCo(Window
, &Ref
);
3582 ret
= co_IntSendMessageNoWait( hWnd
, WM_ASYNC_SHOWWINDOW
, nCmdShow
, 0 );
3583 UserDerefObjectCo(Window
);
3584 if (-1 == (int) ret
|| !ret
) ret
= FALSE
;
3589 TRACE("Leave NtUserShowWindowAsync, ret=%i\n",_ret_
);
3598 NtUserShowWindow(HWND hWnd
, LONG nCmdShow
)
3602 DECLARE_RETURN(BOOL
);
3603 USER_REFERENCE_ENTRY Ref
;
3605 TRACE("Enter NtUserShowWindow hWnd %p SW_ %d\n",hWnd
, nCmdShow
);
3606 UserEnterExclusive();
3608 if (!(Window
= UserGetWindowObject(hWnd
)) ||
3609 UserIsDesktopWindow(Window
) || UserIsMessageWindow(Window
))
3614 if ( nCmdShow
> SW_MAX
|| Window
->state2
& WNDS2_INDESTROY
)
3616 EngSetLastError(ERROR_INVALID_PARAMETER
);
3620 UserRefObjectCo(Window
, &Ref
);
3621 ret
= co_WinPosShowWindow(Window
, nCmdShow
);
3622 UserDerefObjectCo(Window
);
3627 TRACE("Leave NtUserShowWindow, ret=%i\n",_ret_
);
3637 NtUserWindowFromPoint(LONG X
, LONG Y
)
3641 PWND DesktopWindow
= NULL
, Window
= NULL
;
3643 DECLARE_RETURN(HWND
);
3644 USER_REFERENCE_ENTRY Ref
;
3646 TRACE("Enter NtUserWindowFromPoint\n");
3647 UserEnterExclusive();
3649 if ((DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow())))
3656 // Hmm... Threads live on desktops thus we have a reference on the desktop and indirectly the desktop window.
3657 // It is possible this referencing is useless, though it should not hurt...
3658 UserRefObjectCo(DesktopWindow
, &Ref
);
3660 //pti = PsGetCurrentThreadWin32Thread();
3661 Window
= co_WinPosWindowFromPoint(DesktopWindow
, &pt
, &hittest
, FALSE
);
3665 Ret
= UserHMGetHandle(Window
);
3674 if (DesktopWindow
) UserDerefObjectCo(DesktopWindow
);
3676 TRACE("Leave NtUserWindowFromPoint, ret=%p\n", _ret_
);