2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
5 * FILE: subsystems/win32/win32k/ntuser/window.c
6 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
10 DBG_DEFAULT_CHANNEL(UserWinpos
);
12 /* GLOBALS *******************************************************************/
14 #define MINMAX_NOSWP (0x00010000)
16 #define SWP_EX_NOCOPY 0x0001
17 #define SWP_EX_PAINTSELF 0x0002
19 #define SWP_AGG_NOGEOMETRYCHANGE \
20 (SWP_NOSIZE | SWP_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)
26 #define EMPTYPOINT(pt) ((pt).x == -1 && (pt).y == -1)
27 #define PLACE_MIN 0x0001
28 #define PLACE_MAX 0x0002
29 #define PLACE_RECT 0x0004
31 VOID FASTCALL
IntLinkWindow(PWND Wnd
,PWND WndInsertAfter
);
33 /* FUNCTIONS *****************************************************************/
36 IntGetClientOrigin(PWND Window OPTIONAL
, LPPOINT Point
)
38 Window
= Window
? Window
: UserGetDesktopWindow();
41 Point
->x
= Point
->y
= 0;
44 Point
->x
= Window
->rcClient
.left
;
45 Point
->y
= Window
->rcClient
.top
;
52 * Returns client window rectangle relative to the upper-left corner of client area.
54 * \note Does not check the validity of the parameters
57 IntGetClientRect(PWND Wnd
, RECTL
*Rect
)
61 if (Wnd
->style
& WS_MINIMIZED
)
63 Rect
->left
= Rect
->top
= 0;
64 Rect
->right
= UserGetSystemMetrics(SM_CXMINIMIZED
);
65 Rect
->bottom
= UserGetSystemMetrics(SM_CYMINIMIZED
);
68 if ( Wnd
!= UserGetDesktopWindow()) // Wnd->fnid != FNID_DESKTOP )
70 *Rect
= Wnd
->rcClient
;
71 RECTL_vOffsetRect(Rect
, -Wnd
->rcClient
.left
, -Wnd
->rcClient
.top
);
75 Rect
->left
= Rect
->top
= 0;
76 Rect
->right
= Wnd
->rcClient
.right
;
77 Rect
->bottom
= Wnd
->rcClient
.bottom
;
78 /* Do this until Init bug is fixed. This sets 640x480, see InitMetrics.
79 Rect->right = UserGetSystemMetrics(SM_CXSCREEN);
80 Rect->bottom = UserGetSystemMetrics(SM_CYSCREEN);
86 IntMapWindowPoints(PWND FromWnd
, PWND ToWnd
, LPPOINT lpPoints
, UINT cPoints
)
88 BOOL mirror_from
, mirror_to
;
93 /* Note: Desktop Top and Left is always 0! */
94 Delta
.x
= Delta
.y
= 0;
95 mirror_from
= mirror_to
= FALSE
;
97 if (FromWnd
&& FromWnd
!= UserGetDesktopWindow()) // FromWnd->fnid != FNID_DESKTOP)
99 if (FromWnd
->ExStyle
& WS_EX_LAYOUTRTL
)
103 Delta
.x
= -FromWnd
->rcClient
.right
;
106 Delta
.x
= FromWnd
->rcClient
.left
;
107 Delta
.y
= FromWnd
->rcClient
.top
;
110 if (ToWnd
&& ToWnd
!= UserGetDesktopWindow()) // ToWnd->fnid != FNID_DESKTOP)
112 if (ToWnd
->ExStyle
& WS_EX_LAYOUTRTL
)
116 Delta
.x
+= Change
* ToWnd
->rcClient
.right
;
119 Delta
.x
-= Change
* ToWnd
->rcClient
.left
;
120 Delta
.y
-= ToWnd
->rcClient
.top
;
123 for (i
= 0; i
!= cPoints
; i
++)
125 lpPoints
[i
].x
+= Delta
.x
;
126 lpPoints
[i
].x
*= Change
;
127 lpPoints
[i
].y
+= Delta
.y
;
130 if ((mirror_from
|| mirror_to
) && cPoints
== 2) /* special case for rectangle */
132 int tmp
= min(lpPoints
[0].x
, lpPoints
[1].x
);
133 lpPoints
[1].x
= max(lpPoints
[0].x
, lpPoints
[1].x
);
137 return MAKELONG(LOWORD(Delta
.x
), LOWORD(Delta
.y
));
141 IntClientToScreen(PWND Wnd
, LPPOINT lpPoint
)
143 if (Wnd
&& Wnd
->fnid
!= FNID_DESKTOP
)
145 if (Wnd
->ExStyle
& WS_EX_LAYOUTRTL
)
146 lpPoint
->x
= Wnd
->rcClient
.right
- lpPoint
->x
;
148 lpPoint
->x
+= Wnd
->rcClient
.left
;
149 lpPoint
->y
+= Wnd
->rcClient
.top
;
155 IntScreenToClient(PWND Wnd
, LPPOINT lpPoint
)
157 if (Wnd
&& Wnd
->fnid
!= FNID_DESKTOP
)
159 if (Wnd
->ExStyle
& WS_EX_LAYOUTRTL
)
160 lpPoint
->x
= Wnd
->rcClient
.right
- lpPoint
->x
;
162 lpPoint
->x
-= Wnd
->rcClient
.left
;
163 lpPoint
->y
-= Wnd
->rcClient
.top
;
168 BOOL FASTCALL
IsChildVisible(PWND pWnd
)
172 if ( (pWnd
->style
& (WS_POPUP
|WS_CHILD
)) != WS_CHILD
||
173 !(pWnd
= pWnd
->spwndParent
) )
176 while (pWnd
->style
& WS_VISIBLE
);
180 PWND FASTCALL
IntGetLastTopMostWindow(VOID
)
183 PDESKTOP rpdesk
= gptiCurrent
->rpdesk
;
186 (pWnd
= rpdesk
->pDeskInfo
->spwnd
->spwndChild
) &&
187 pWnd
->ExStyle
& WS_EX_TOPMOST
)
191 if (!pWnd
->spwndNext
) break;
192 if (!(pWnd
->spwndNext
->ExStyle
& WS_EX_TOPMOST
)) break;
193 pWnd
= pWnd
->spwndNext
;
201 // This helps with CORE-6129 forcing modal dialog active when another app is minimized or closed.
203 BOOL FASTCALL
ActivateOtherWindowMin(PWND Wnd
)
205 BOOL ActivePrev
, FindTopWnd
;
206 PWND pWndTopMost
, pWndChild
, pWndSetActive
, pWndTemp
, pWndDesk
;
207 USER_REFERENCE_ENTRY Ref
;
208 PTHREADINFO pti
= gptiCurrent
;
210 //ERR("AOWM 1 %p\n",Wnd->head.h);
211 ActivePrev
= (pti
->MessageQueue
->spwndActivePrev
!= NULL
);
214 if ((pWndTopMost
= IntGetLastTopMostWindow()))
215 pWndChild
= pWndTopMost
->spwndNext
;
217 pWndChild
= Wnd
->spwndParent
->spwndChild
;
222 pWndSetActive
= pti
->MessageQueue
->spwndActivePrev
;
224 pWndSetActive
= pWndChild
;
230 if ( VerifyWnd(pWndSetActive
) &&
231 !(pWndSetActive
->ExStyle
& WS_EX_NOACTIVATE
) &&
232 (pWndSetActive
->style
& (WS_VISIBLE
|WS_DISABLED
)) == WS_VISIBLE
&&
233 (!(pWndSetActive
->style
& WS_ICONIC
) /* FIXME MinMax pos? */ ) )
235 if (!(pWndSetActive
->ExStyle
& WS_EX_TOOLWINDOW
) )
237 UserRefObjectCo(pWndSetActive
, &Ref
);
238 //ERR("ActivateOtherWindowMin Set FG 1\n");
239 co_IntSetForegroundWindow(pWndSetActive
);
240 UserDerefObjectCo(pWndSetActive
);
241 //ERR("AOWM 2 Exit Good %p\n",pWndSetActive->head.h);
244 if (!pWndTemp
) pWndTemp
= pWndSetActive
;
249 pWndSetActive
= pWndChild
;
252 pWndSetActive
= pWndSetActive
->spwndNext
;
255 if ( !FindTopWnd
) break;
260 pWndChild
= pWndChild
->spwndParent
->spwndChild
;
264 if (!(pWndDesk
= IntGetThreadDesktopWindow(pti
)))
269 pWndChild
= pWndDesk
->spwndChild
;
272 if ((pWndSetActive
= pWndTemp
))
274 UserRefObjectCo(pWndSetActive
, &Ref
);
275 //ERR("ActivateOtherWindowMin Set FG 2\n");
276 co_IntSetForegroundWindow(pWndSetActive
);
277 UserDerefObjectCo(pWndSetActive
);
278 //ERR("AOWM 3 Exit Good %p\n",pWndSetActive->head.h);
281 //ERR("AOWM 4 Bad\n");
285 /*******************************************************************
286 * can_activate_window
288 * Check if we can activate the specified window.
291 BOOL FASTCALL
can_activate_window( PWND Wnd OPTIONAL
)
295 if (!Wnd
) return FALSE
;
298 if (!(style
& WS_VISIBLE
)) return FALSE
;
299 if (style
& WS_MINIMIZE
) return FALSE
;
300 if ((style
& (WS_POPUP
|WS_CHILD
)) == WS_CHILD
) return FALSE
;
302 /* FIXME: This window could be disable because the child that closed
304 //return !(style & WS_DISABLED);
308 /*******************************************************************
309 * WinPosActivateOtherWindow
311 * Activates window other than pWnd.
314 co_WinPosActivateOtherWindow(PWND Wnd
)
317 USER_REFERENCE_ENTRY Ref
;
321 if (IntIsDesktopWindow(Wnd
))
323 IntSetFocusMessageQueue(NULL
);
327 /* If this is popup window, try to activate the owner first. */
328 if ((Wnd
->style
& WS_POPUP
) && (WndTo
= Wnd
->spwndOwner
))
330 TRACE("WPAOW Popup with Owner\n");
331 WndTo
= UserGetAncestor( WndTo
, GA_ROOT
);
332 if (can_activate_window(WndTo
)) goto done
;
335 /* Pick a next top-level window. */
336 /* FIXME: Search for non-tooltip windows first. */
340 if (!(WndTo
= WndTo
->spwndNext
)) break;
341 if (can_activate_window( WndTo
)) goto done
;
345 Fixes wine win.c:test_SetParent last ShowWindow test after popup dies.
346 Check for previous active window to bring to top.
350 WndTo
= Wnd
->head
.pti
->MessageQueue
->spwndActivePrev
;
351 if (can_activate_window( WndTo
)) goto done
;
354 // Find any window to bring to top. Works Okay for wine since it does not see X11 windows.
355 WndTo
= UserGetDesktopWindow();
356 WndTo
= WndTo
->spwndChild
;
368 if (can_activate_window( WndTo
)) goto done
;
369 if (!(WndTo
= WndTo
->spwndNext
)) break;
373 if (WndTo
) UserRefObjectCo(WndTo
, &Ref
);
375 if (gpqForeground
&& (!gpqForeground
->spwndActive
|| Wnd
== gpqForeground
->spwndActive
))
377 /* ReactOS can pass WndTo = NULL to co_IntSetForegroundWindow and returns FALSE. */
378 //ERR("WinPosActivateOtherWindow Set FG 0x%p hWnd %p\n",WndTo, WndTo ? WndTo->head.h : 0);
379 if (co_IntSetForegroundWindow(WndTo
))
381 if (WndTo
) UserDerefObjectCo(WndTo
);
385 //ERR("WinPosActivateOtherWindow Set Active 0x%p\n",WndTo);
386 if (!co_IntSetActiveWindow(WndTo
,FALSE
,TRUE
,FALSE
)) /* Ok for WndTo to be NULL here */
388 //ERR("WPAOW SA 1\n");
389 co_IntSetActiveWindow(NULL
,FALSE
,TRUE
,FALSE
);
391 if (WndTo
) UserDerefObjectCo(WndTo
);
395 WinPosInitInternalPos(PWND Wnd
, RECTL
*RestoreRect
)
398 RECTL Rect
= *RestoreRect
;
400 if (Wnd
->spwndParent
&& Wnd
->spwndParent
!= UserGetDesktopWindow())
402 RECTL_vOffsetRect(&Rect
,
403 -Wnd
->spwndParent
->rcClient
.left
,
404 -Wnd
->spwndParent
->rcClient
.top
);
410 if (!Wnd
->InternalPosInitialized
)
412 // FIXME: Use check point Atom..
413 Wnd
->InternalPos
.flags
= 0;
414 Wnd
->InternalPos
.MaxPos
.x
= Wnd
->InternalPos
.MaxPos
.y
= -1;
415 Wnd
->InternalPos
.IconPos
.x
= Wnd
->InternalPos
.IconPos
.y
= -1;
416 Wnd
->InternalPos
.NormalRect
= Rect
;
417 Wnd
->InternalPosInitialized
= TRUE
;
420 if (Wnd
->style
& WS_MINIMIZE
)
422 Wnd
->InternalPos
.IconPos
= Size
;
423 Wnd
->InternalPos
.flags
|= WPF_MININIT
;
425 else if (Wnd
->style
& WS_MAXIMIZE
)
427 Wnd
->InternalPos
.flags
|= WPF_MAXINIT
;
429 if ( Wnd
->spwndParent
== Wnd
->head
.rpdesk
->pDeskInfo
->spwnd
)
431 if (Wnd
->state
& WNDS_MAXIMIZESTOMONITOR
)
433 Wnd
->InternalPos
.flags
&= ~WPF_MAXINIT
;
434 Wnd
->InternalPos
.MaxPos
.x
= Wnd
->InternalPos
.MaxPos
.y
= -1;
439 PMONITOR pmonitor
= UserMonitorFromRect(&Rect
, MONITOR_DEFAULTTOPRIMARY
);
440 // FIXME: support DPI aware, rcWorkDPI/Real etc..
441 WorkArea
= pmonitor
->rcMonitor
;
443 if (Wnd
->style
& WS_MAXIMIZEBOX
)
444 { // Support (Wnd->state & WNDS_HASCAPTION) || pmonitor->cFullScreen too.
445 if ((Wnd
->style
& WS_CAPTION
) == WS_CAPTION
|| !(Wnd
->style
& (WS_CHILD
| WS_POPUP
)))
447 WorkArea
= pmonitor
->rcWork
;
452 Wnd
->InternalPos
.MaxPos
.x
= Rect
.left
- WorkArea
.left
;
453 Wnd
->InternalPos
.MaxPos
.y
= Rect
.top
- WorkArea
.top
;
455 /*ERR("WinPosIP 2 X %d = R.l %d - W.l %d | Y %d = R.t %d - W.t %d\n",
456 Wnd->InternalPos.MaxPos.x,
457 Rect.left, WorkArea.left,
458 Wnd->InternalPos.MaxPos.y,
459 Rect.top, WorkArea.top);*/
463 Wnd
->InternalPos
.MaxPos
= Size
;
467 Wnd
->InternalPos
.NormalRect
= Rect
;
473 IntGetWindowPlacement(PWND Wnd
, WINDOWPLACEMENT
*lpwndpl
)
475 if (!Wnd
) return FALSE
;
477 if(lpwndpl
->length
!= sizeof(WINDOWPLACEMENT
))
484 WinPosInitInternalPos(Wnd
, &Wnd
->rcWindow
);
486 lpwndpl
->showCmd
= SW_HIDE
;
488 if ( Wnd
->style
& WS_MINIMIZE
)
489 lpwndpl
->showCmd
= SW_SHOWMINIMIZED
;
491 lpwndpl
->showCmd
= ( Wnd
->style
& WS_MAXIMIZE
) ? SW_SHOWMAXIMIZED
: SW_SHOWNORMAL
;
493 lpwndpl
->rcNormalPosition
= Wnd
->InternalPos
.NormalRect
;
495 if (Wnd
->InternalPos
.flags
& WPF_MININIT
) // Return if it was set!
497 lpwndpl
->ptMinPosition
.x
= Wnd
->InternalPos
.IconPos
.x
;
498 lpwndpl
->ptMinPosition
.y
= Wnd
->InternalPos
.IconPos
.y
;
501 lpwndpl
->ptMinPosition
.x
= lpwndpl
->ptMinPosition
.y
= -1;
503 if ( Wnd
->InternalPos
.flags
& WPF_MAXINIT
&& // Return if set and not maximized to monitor!
504 !(Wnd
->state
& WNDS_MAXIMIZESTOMONITOR
))
506 lpwndpl
->ptMaxPosition
.x
= Wnd
->InternalPos
.MaxPos
.x
;
507 lpwndpl
->ptMaxPosition
.y
= Wnd
->InternalPos
.MaxPos
.y
;
510 lpwndpl
->ptMaxPosition
.x
= lpwndpl
->ptMaxPosition
.y
= -1;
512 if ( Wnd
->spwndParent
== Wnd
->head
.rpdesk
->pDeskInfo
->spwnd
&&
513 !(Wnd
->ExStyle
& WS_EX_TOOLWINDOW
))
515 PMONITOR pmonitor
= UserMonitorFromRect(&lpwndpl
->rcNormalPosition
, MONITOR_DEFAULTTOPRIMARY
);
517 // FIXME: support DPI aware, rcWorkDPI/Real etc..
518 if (Wnd
->InternalPos
.flags
& WPF_MININIT
)
520 lpwndpl
->ptMinPosition
.x
-= (pmonitor
->rcWork
.left
- pmonitor
->rcMonitor
.left
);
521 lpwndpl
->ptMinPosition
.y
-= (pmonitor
->rcWork
.top
- pmonitor
->rcMonitor
.top
);
523 RECTL_vOffsetRect(&lpwndpl
->rcNormalPosition
,
524 pmonitor
->rcMonitor
.left
- pmonitor
->rcWork
.left
,
525 pmonitor
->rcMonitor
.top
- pmonitor
->rcWork
.top
);
528 if ( Wnd
->InternalPos
.flags
& WPF_RESTORETOMAXIMIZED
|| Wnd
->style
& WS_MAXIMIZE
)
529 lpwndpl
->flags
|= WPF_RESTORETOMAXIMIZED
;
531 if ( ((Wnd
->style
& (WS_CHILD
|WS_POPUP
)) == WS_CHILD
) && Wnd
->InternalPos
.flags
& WPF_SETMINPOSITION
)
532 lpwndpl
->flags
|= WPF_SETMINPOSITION
;
537 /* make sure the specified rect is visible on screen */
538 static void make_rect_onscreen( RECT
*rect
)
540 PMONITOR pmonitor
= UserMonitorFromRect( rect
, MONITOR_DEFAULTTONEAREST
); // Wine uses this.
542 // FIXME: support DPI aware, rcWorkDPI/Real etc..
543 if (!pmonitor
) return;
544 /* FIXME: map coordinates from rcWork to rcMonitor */
545 if (rect
->right
<= pmonitor
->rcWork
.left
)
547 rect
->right
+= pmonitor
->rcWork
.left
- rect
->left
;
548 rect
->left
= pmonitor
->rcWork
.left
;
550 else if (rect
->left
>= pmonitor
->rcWork
.right
)
552 rect
->left
+= pmonitor
->rcWork
.right
- rect
->right
;
553 rect
->right
= pmonitor
->rcWork
.right
;
555 if (rect
->bottom
<= pmonitor
->rcWork
.top
)
557 rect
->bottom
+= pmonitor
->rcWork
.top
- rect
->top
;
558 rect
->top
= pmonitor
->rcWork
.top
;
560 else if (rect
->top
>= pmonitor
->rcWork
.bottom
)
562 rect
->top
+= pmonitor
->rcWork
.bottom
- rect
->bottom
;
563 rect
->bottom
= pmonitor
->rcWork
.bottom
;
567 /* make sure the specified point is visible on screen */
568 static void make_point_onscreen( POINT
*pt
)
572 RECTL_vSetRect( &rect
, pt
->x
, pt
->y
, pt
->x
+ 1, pt
->y
+ 1 );
573 make_rect_onscreen( &rect
);
579 IntSetWindowPlacement(PWND Wnd
, WINDOWPLACEMENT
*wpl
, UINT Flags
)
584 if ( Flags
& PLACE_MIN
) make_point_onscreen( &wpl
->ptMinPosition
);
585 if ( Flags
& PLACE_MAX
) make_point_onscreen( &wpl
->ptMaxPosition
);
586 if ( Flags
& PLACE_RECT
) make_rect_onscreen( &wpl
->rcNormalPosition
);
588 if (!Wnd
|| Wnd
== Wnd
->head
.rpdesk
->pDeskInfo
->spwnd
) return FALSE
;
590 if ( Flags
& PLACE_MIN
) Wnd
->InternalPos
.IconPos
= wpl
->ptMinPosition
;
591 if ( Flags
& PLACE_MAX
) Wnd
->InternalPos
.MaxPos
= wpl
->ptMaxPosition
;
592 if ( Flags
& PLACE_RECT
) Wnd
->InternalPos
.NormalRect
= wpl
->rcNormalPosition
;
594 SWP_Flags
= SWP_NOZORDER
| SWP_NOACTIVATE
| ((wpl
->flags
& WPF_ASYNCWINDOWPLACEMENT
) ? SWP_ASYNCWINDOWPOS
: 0);
596 if (Wnd
->style
& WS_MINIMIZE
)
598 if (Flags
& PLACE_MIN
|| Wnd
->InternalPos
.flags
& WPF_SETMINPOSITION
)
600 co_WinPosSetWindowPos(Wnd
, HWND_TOP
,
601 wpl
->ptMinPosition
.x
, wpl
->ptMinPosition
.y
, 0, 0,
602 SWP_NOSIZE
| SWP_Flags
);
603 Wnd
->InternalPos
.flags
|= WPF_MININIT
;
606 else if (Wnd
->style
& WS_MAXIMIZE
)
608 if (Flags
& PLACE_MAX
)
610 co_WinPosSetWindowPos(Wnd
, HWND_TOP
,
611 wpl
->ptMaxPosition
.x
, wpl
->ptMaxPosition
.y
, 0, 0,
612 SWP_NOSIZE
| SWP_Flags
);
613 Wnd
->InternalPos
.flags
|= WPF_MAXINIT
;
616 else if (Flags
& PLACE_RECT
)
618 co_WinPosSetWindowPos(Wnd
, HWND_TOP
,
619 wpl
->rcNormalPosition
.left
, wpl
->rcNormalPosition
.top
,
620 wpl
->rcNormalPosition
.right
- wpl
->rcNormalPosition
.left
,
621 wpl
->rcNormalPosition
.bottom
- wpl
->rcNormalPosition
.top
,
625 sAsync
= (Wnd
->head
.pti
->MessageQueue
!= gptiCurrent
->MessageQueue
&& wpl
->flags
& WPF_ASYNCWINDOWPLACEMENT
);
628 co_IntSendMessageNoWait( UserHMGetHandle(Wnd
), WM_ASYNC_SHOWWINDOW
, wpl
->showCmd
, 0 );
630 co_WinPosShowWindow(Wnd
, wpl
->showCmd
);
632 if ( Wnd
->style
& WS_MINIMIZE
&& !sAsync
)
634 if ( wpl
->flags
& WPF_SETMINPOSITION
)
635 Wnd
->InternalPos
.flags
|= WPF_SETMINPOSITION
;
637 if ( wpl
->flags
& WPF_RESTORETOMAXIMIZED
)
638 Wnd
->InternalPos
.flags
|= WPF_RESTORETOMAXIMIZED
;
645 co_WinPosArrangeIconicWindows(PWND parent
)
649 INT x
, y
, xspacing
, yspacing
, sx
, sy
;
651 ASSERT_REFS_CO(parent
);
653 IntGetClientRect( parent
, &rectParent
);
654 // FIXME: Support Minimize Metrics gspv.mm.iArrange.
655 // Default: ARW_BOTTOMLEFT
657 y
= rectParent
.bottom
;
659 xspacing
= UserGetSystemMetrics(SM_CXMINIMIZED
);
660 yspacing
= UserGetSystemMetrics(SM_CYMINIMIZED
);
662 Child
= parent
->spwndChild
;
665 if((Child
->style
& WS_MINIMIZE
) != 0 )
667 USER_REFERENCE_ENTRY Ref
;
668 UserRefObjectCo(Child
, &Ref
);
670 sx
= x
+ UserGetSystemMetrics(SM_CXBORDER
);
671 sy
= y
- yspacing
- UserGetSystemMetrics(SM_CYBORDER
);
673 Child
->InternalPos
.IconPos
.x
= sx
;
674 Child
->InternalPos
.IconPos
.y
= sy
;
675 Child
->InternalPos
.flags
|= WPF_MININIT
;
677 co_WinPosSetWindowPos( Child
, 0, sx
, sy
, xspacing
, yspacing
, SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOCOPYBITS
| SWP_ASYNCWINDOWPOS
);
679 UserDerefObjectCo(Child
);
681 if (x
<= rectParent
.right
- xspacing
)
689 Child
= Child
->spwndNext
;
695 WinPosFindIconPos(PWND Window
, POINT
*Pos
)
698 PWND pwndChild
, pwndParent
;
699 int x
, y
, xspacing
, yspacing
;
701 pwndParent
= Window
->spwndParent
;
702 if (pwndParent
== UserGetDesktopWindow())
704 ERR("Parent is Desktop, Min off screen!\n");
705 /* ReactOS doesn't support iconic minimize to desktop */
706 Pos
->x
= Pos
->y
= -32000;
707 Window
->InternalPos
.flags
|= WPF_MININIT
;
708 Window
->InternalPos
.IconPos
.x
= Pos
->x
;
709 Window
->InternalPos
.IconPos
.y
= Pos
->y
;
713 IntGetClientRect( pwndParent
, &rectParent
);
714 // FIXME: Support Minimize Metrics gspv.mm.iArrange.
715 // Default: ARW_BOTTOMLEFT
717 y
= rectParent
.bottom
;
719 xspacing
= UserGetSystemMetrics(SM_CXMINIMIZED
);
720 yspacing
= UserGetSystemMetrics(SM_CYMINIMIZED
);
722 // Set to default position when minimized.
723 Pos
->x
= x
+ UserGetSystemMetrics(SM_CXBORDER
);
724 Pos
->y
= y
- yspacing
- UserGetSystemMetrics(SM_CYBORDER
);
726 for (pwndChild
= pwndParent
->spwndChild
; pwndChild
; pwndChild
= pwndChild
->spwndNext
)
728 if (pwndChild
== Window
) continue;
730 if ((pwndChild
->style
& (WS_VISIBLE
|WS_MINIMIZE
)) != (WS_VISIBLE
|WS_MINIMIZE
) )
735 if ( pwndChild
->InternalPos
.IconPos
.x
!= Pos
->x
&& pwndChild
->InternalPos
.IconPos
.y
!= Pos
->y
)
739 if (x
<= rectParent
.right
- xspacing
)
746 Pos
->x
= x
+ UserGetSystemMetrics(SM_CXBORDER
);
747 Pos
->y
= y
- yspacing
- UserGetSystemMetrics(SM_CYBORDER
);
750 Window
->InternalPos
.IconPos
.x
= Pos
->x
;
751 Window
->InternalPos
.IconPos
.y
= Pos
->y
;
752 Window
->InternalPos
.flags
|= WPF_MININIT
;
753 TRACE("Position is set! X:%d Y:%d\n",Pos
->x
,Pos
->y
);
758 co_WinPosMinMaximize(PWND Wnd
, UINT ShowFlag
, RECT
* NewPos
)
767 wpl
.length
= sizeof(wpl
);
768 IntGetWindowPlacement( Wnd
, &wpl
);
770 if (co_HOOK_CallHooks( WH_CBT
, HCBT_MINMAX
, (WPARAM
)Wnd
->head
.h
, ShowFlag
))
772 ERR("WinPosMinMaximize WH_CBT Call Hook return!\n");
773 return SWP_NOSIZE
| SWP_NOMOVE
;
775 if (Wnd
->style
& WS_MINIMIZE
)
780 case SW_SHOWMINNOACTIVE
:
781 case SW_SHOWMINIMIZED
:
782 case SW_FORCEMINIMIZE
:
783 return SWP_NOSIZE
| SWP_NOMOVE
;
785 if (!co_IntSendMessageNoWait(Wnd
->head
.h
, WM_QUERYOPEN
, 0, 0))
787 return(SWP_NOSIZE
| SWP_NOMOVE
);
789 SwpFlags
|= SWP_NOCOPYBITS
;
794 case SW_SHOWMINNOACTIVE
:
795 case SW_SHOWMINIMIZED
:
796 case SW_FORCEMINIMIZE
:
798 //ERR("MinMaximize Minimize\n");
799 if (Wnd
->style
& WS_MAXIMIZE
)
801 Wnd
->InternalPos
.flags
|= WPF_RESTORETOMAXIMIZED
;
805 Wnd
->InternalPos
.flags
&= ~WPF_RESTORETOMAXIMIZED
;
808 old_style
= IntSetStyle( Wnd
, WS_MINIMIZE
, WS_MAXIMIZE
);
810 co_UserRedrawWindow(Wnd
, NULL
, 0, RDW_VALIDATE
| RDW_NOERASE
| RDW_NOINTERNALPAINT
);
812 if (!(Wnd
->InternalPos
.flags
& WPF_SETMINPOSITION
))
813 Wnd
->InternalPos
.flags
&= ~WPF_MININIT
;
815 WinPosFindIconPos(Wnd
, &wpl
.ptMinPosition
);
817 /*if (!(old_style & WS_MINIMIZE))
819 SwpFlags |= SWP_STATECHANGED;
820 IntShowOwnedPopups(Wnd, FALSE);
823 RECTL_vSetRect(NewPos
, wpl
.ptMinPosition
.x
, wpl
.ptMinPosition
.y
,
824 wpl
.ptMinPosition
.x
+ UserGetSystemMetrics(SM_CXMINIMIZED
),
825 wpl
.ptMinPosition
.y
+ UserGetSystemMetrics(SM_CYMINIMIZED
));
826 SwpFlags
|= SWP_NOCOPYBITS
;
832 //ERR("MinMaximize Maximize\n");
833 if ((Wnd
->style
& WS_MAXIMIZE
) && (Wnd
->style
& WS_VISIBLE
))
835 SwpFlags
= SWP_NOSIZE
| SWP_NOMOVE
;
838 co_WinPosGetMinMaxInfo(Wnd
, &Size
, &wpl
.ptMaxPosition
, NULL
, NULL
);
840 /*ERR("Maximize: %d,%d %dx%d\n",
841 wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, Size.x, Size.y);
843 old_style
= IntSetStyle( Wnd
, WS_MAXIMIZE
, WS_MINIMIZE
);
844 /*if (old_style & WS_MINIMIZE)
846 IntShowOwnedPopups(Wnd, TRUE);
849 if (!(old_style
& WS_MAXIMIZE
)) SwpFlags
|= SWP_STATECHANGED
;
850 RECTL_vSetRect(NewPos
, wpl
.ptMaxPosition
.x
, wpl
.ptMaxPosition
.y
,
851 //wpl.ptMaxPosition.x + Size.x, wpl.ptMaxPosition.y + Size.y);
856 case SW_SHOWNOACTIVATE
:
857 Wnd
->InternalPos
.flags
&= ~WPF_RESTORETOMAXIMIZED
;
861 case SW_SHOWDEFAULT
: /* FIXME: should have its own handler */
863 //ERR("MinMaximize Restore\n");
864 old_style
= IntSetStyle( Wnd
, 0, WS_MINIMIZE
| WS_MAXIMIZE
);
865 if (old_style
& WS_MINIMIZE
)
867 //IntShowOwnedPopups(Wnd, TRUE);
869 if (Wnd
->InternalPos
.flags
& WPF_RESTORETOMAXIMIZED
)
871 co_WinPosGetMinMaxInfo(Wnd
, &Size
, &wpl
.ptMaxPosition
, NULL
, NULL
);
872 IntSetStyle( Wnd
, WS_MAXIMIZE
, 0 );
873 SwpFlags
|= SWP_STATECHANGED
;
874 RECTL_vSetRect(NewPos
, wpl
.ptMaxPosition
.x
, wpl
.ptMaxPosition
.y
,
875 wpl
.ptMaxPosition
.x
+ Size
.x
, wpl
.ptMaxPosition
.y
+ Size
.y
);
880 *NewPos
= wpl
.rcNormalPosition
;
881 NewPos
->right
-= NewPos
->left
;
882 NewPos
->bottom
-= NewPos
->top
;
888 if (!(old_style
& WS_MAXIMIZE
))
892 SwpFlags
|= SWP_STATECHANGED
;
893 Wnd
->InternalPos
.flags
&= ~WPF_RESTORETOMAXIMIZED
;
894 *NewPos
= wpl
.rcNormalPosition
;
895 NewPos
->right
-= NewPos
->left
;
896 NewPos
->bottom
-= NewPos
->top
;
905 UserHasWindowEdge(DWORD Style
, DWORD ExStyle
)
907 if (Style
& WS_MINIMIZE
)
909 if (ExStyle
& WS_EX_DLGMODALFRAME
)
911 if (ExStyle
& WS_EX_STATICEDGE
)
913 if (Style
& WS_THICKFRAME
)
916 if (Style
== WS_DLGFRAME
|| Style
== WS_CAPTION
)
922 IntGetWindowBorderMeasures(PWND Wnd
, UINT
*cx
, UINT
*cy
)
924 if(HAS_DLGFRAME(Wnd
->style
, Wnd
->ExStyle
) && !(Wnd
->style
& WS_MINIMIZE
))
926 *cx
= UserGetSystemMetrics(SM_CXDLGFRAME
);
927 *cy
= UserGetSystemMetrics(SM_CYDLGFRAME
);
931 if(HAS_THICKFRAME(Wnd
->style
, Wnd
->ExStyle
)&& !(Wnd
->style
& WS_MINIMIZE
))
933 *cx
= UserGetSystemMetrics(SM_CXFRAME
);
934 *cy
= UserGetSystemMetrics(SM_CYFRAME
);
936 else if(HAS_THINFRAME(Wnd
->style
, Wnd
->ExStyle
))
938 *cx
= UserGetSystemMetrics(SM_CXBORDER
);
939 *cy
= UserGetSystemMetrics(SM_CYBORDER
);
949 UserGetWindowBorders(DWORD Style
, DWORD ExStyle
, SIZE
*Size
, BOOL WithClient
)
953 if (UserHasWindowEdge(Style
, ExStyle
))
955 else if (ExStyle
& WS_EX_STATICEDGE
)
957 if ((ExStyle
& WS_EX_CLIENTEDGE
) && WithClient
)
959 if (Style
& WS_CAPTION
|| ExStyle
& WS_EX_DLGMODALFRAME
)
961 Size
->cx
= Size
->cy
= Border
;
962 if ((Style
& WS_THICKFRAME
) && !(Style
& WS_MINIMIZE
))
964 Size
->cx
+= UserGetSystemMetrics(SM_CXFRAME
) - UserGetSystemMetrics(SM_CXDLGFRAME
);
965 Size
->cy
+= UserGetSystemMetrics(SM_CYFRAME
) - UserGetSystemMetrics(SM_CYDLGFRAME
);
967 Size
->cx
*= UserGetSystemMetrics(SM_CXBORDER
);
968 Size
->cy
*= UserGetSystemMetrics(SM_CYBORDER
);
972 UserAdjustWindowRectEx(LPRECT lpRect
,
981 lpRect
->top
-= UserGetSystemMetrics(SM_CYMENU
);
983 if ((dwStyle
& WS_CAPTION
) == WS_CAPTION
)
985 if (dwExStyle
& WS_EX_TOOLWINDOW
)
986 lpRect
->top
-= UserGetSystemMetrics(SM_CYSMCAPTION
);
988 lpRect
->top
-= UserGetSystemMetrics(SM_CYCAPTION
);
990 UserGetWindowBorders(dwStyle
, dwExStyle
, &BorderSize
, TRUE
);
1000 co_WinPosGetMinMaxInfo(PWND Window
, POINT
* MaxSize
, POINT
* MaxPos
,
1001 POINT
* MinTrack
, POINT
* MaxTrack
)
1006 LONG style
= Window
->style
;
1008 LONG exstyle
= Window
->ExStyle
;
1011 ASSERT_REFS_CO(Window
);
1013 /* Compute default values */
1015 rc
= Window
->rcWindow
;
1016 MinMax
.ptReserved
.x
= rc
.left
;
1017 MinMax
.ptReserved
.y
= rc
.top
;
1019 if ((style
& WS_CAPTION
) == WS_CAPTION
)
1020 adjustedStyle
= style
& ~WS_BORDER
; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
1022 adjustedStyle
= style
;
1024 if(Window
->spwndParent
)
1025 IntGetClientRect(Window
->spwndParent
, &rc
);
1026 UserAdjustWindowRectEx(&rc
, adjustedStyle
, ((style
& WS_POPUP
) && Window
->IDMenu
), exstyle
);
1031 MinMax
.ptMaxSize
.x
= rc
.right
- rc
.left
;
1032 MinMax
.ptMaxSize
.y
= rc
.bottom
- rc
.top
;
1033 if (style
& (WS_DLGFRAME
| WS_BORDER
))
1035 MinMax
.ptMinTrackSize
.x
= UserGetSystemMetrics(SM_CXMINTRACK
);
1036 MinMax
.ptMinTrackSize
.y
= UserGetSystemMetrics(SM_CYMINTRACK
);
1040 MinMax
.ptMinTrackSize
.x
= 2 * xinc
;
1041 MinMax
.ptMinTrackSize
.y
= 2 * yinc
;
1043 MinMax
.ptMaxTrackSize
.x
= UserGetSystemMetrics(SM_CXMAXTRACK
);
1044 MinMax
.ptMaxTrackSize
.y
= UserGetSystemMetrics(SM_CYMAXTRACK
);
1045 MinMax
.ptMaxPosition
.x
= -xinc
;
1046 MinMax
.ptMaxPosition
.y
= -yinc
;
1048 if (!EMPTYPOINT(Window
->InternalPos
.MaxPos
)) MinMax
.ptMaxPosition
= Window
->InternalPos
.MaxPos
;
1050 co_IntSendMessage(Window
->head
.h
, WM_GETMINMAXINFO
, 0, (LPARAM
)&MinMax
);
1052 /* if the app didn't change the values, adapt them for the current monitor */
1053 if ((monitor
= UserGetPrimaryMonitor()))
1057 rc_work
= monitor
->rcMonitor
;
1059 if (style
& WS_MAXIMIZEBOX
)
1061 if ((style
& WS_CAPTION
) == WS_CAPTION
|| !(style
& (WS_CHILD
| WS_POPUP
)))
1062 rc_work
= monitor
->rcWork
;
1065 if (MinMax
.ptMaxSize
.x
== UserGetSystemMetrics(SM_CXSCREEN
) + 2 * xinc
&&
1066 MinMax
.ptMaxSize
.y
== UserGetSystemMetrics(SM_CYSCREEN
) + 2 * yinc
)
1068 MinMax
.ptMaxSize
.x
= (rc_work
.right
- rc_work
.left
) + 2 * xinc
;
1069 MinMax
.ptMaxSize
.y
= (rc_work
.bottom
- rc_work
.top
) + 2 * yinc
;
1071 if (MinMax
.ptMaxPosition
.x
== -xinc
&& MinMax
.ptMaxPosition
.y
== -yinc
)
1073 MinMax
.ptMaxPosition
.x
= rc_work
.left
- xinc
;
1074 MinMax
.ptMaxPosition
.y
= rc_work
.top
- yinc
;
1076 if (MinMax
.ptMaxSize
.x
>= (monitor
->rcMonitor
.right
- monitor
->rcMonitor
.left
) &&
1077 MinMax
.ptMaxSize
.y
>= (monitor
->rcMonitor
.bottom
- monitor
->rcMonitor
.top
) )
1078 Window
->state
|= WNDS_MAXIMIZESTOMONITOR
;
1080 Window
->state
&= ~WNDS_MAXIMIZESTOMONITOR
;
1084 MinMax
.ptMaxTrackSize
.x
= max(MinMax
.ptMaxTrackSize
.x
,
1085 MinMax
.ptMinTrackSize
.x
);
1086 MinMax
.ptMaxTrackSize
.y
= max(MinMax
.ptMaxTrackSize
.y
,
1087 MinMax
.ptMinTrackSize
.y
);
1090 *MaxSize
= MinMax
.ptMaxSize
;
1092 *MaxPos
= MinMax
.ptMaxPosition
;
1094 *MinTrack
= MinMax
.ptMinTrackSize
;
1096 *MaxTrack
= MinMax
.ptMaxTrackSize
;
1098 return 0; // FIXME: What does it return?
1103 FixClientRect(PRECTL ClientRect
, PRECTL WindowRect
)
1105 if (ClientRect
->left
< WindowRect
->left
)
1107 ClientRect
->left
= WindowRect
->left
;
1109 else if (WindowRect
->right
< ClientRect
->left
)
1111 ClientRect
->left
= WindowRect
->right
;
1113 if (ClientRect
->right
< WindowRect
->left
)
1115 ClientRect
->right
= WindowRect
->left
;
1117 else if (WindowRect
->right
< ClientRect
->right
)
1119 ClientRect
->right
= WindowRect
->right
;
1121 if (ClientRect
->top
< WindowRect
->top
)
1123 ClientRect
->top
= WindowRect
->top
;
1125 else if (WindowRect
->bottom
< ClientRect
->top
)
1127 ClientRect
->top
= WindowRect
->bottom
;
1129 if (ClientRect
->bottom
< WindowRect
->top
)
1131 ClientRect
->bottom
= WindowRect
->top
;
1133 else if (WindowRect
->bottom
< ClientRect
->bottom
)
1135 ClientRect
->bottom
= WindowRect
->bottom
;
1138 /***********************************************************************
1141 * Compute the valid rects from the old and new client rect and WVR_* flags.
1142 * Helper for WM_NCCALCSIZE handling.
1146 get_valid_rects( RECTL
*old_client
, RECTL
*new_client
, UINT flags
, RECTL
*valid
)
1150 if (flags
& WVR_REDRAW
)
1152 RECTL_vSetEmptyRect( &valid
[0] );
1153 RECTL_vSetEmptyRect( &valid
[1] );
1157 if (flags
& WVR_VALIDRECTS
)
1159 if (!RECTL_bIntersectRect( &valid
[0], &valid
[0], new_client
) ||
1160 !RECTL_bIntersectRect( &valid
[1], &valid
[1], old_client
))
1162 RECTL_vSetEmptyRect( &valid
[0] );
1163 RECTL_vSetEmptyRect( &valid
[1] );
1166 flags
= WVR_ALIGNLEFT
| WVR_ALIGNTOP
;
1170 valid
[0] = *new_client
;
1171 valid
[1] = *old_client
;
1174 /* make sure the rectangles have the same size */
1175 cx
= min( valid
[0].right
- valid
[0].left
, valid
[1].right
- valid
[1].left
);
1176 cy
= min( valid
[0].bottom
- valid
[0].top
, valid
[1].bottom
- valid
[1].top
);
1178 if (flags
& WVR_ALIGNBOTTOM
)
1180 valid
[0].top
= valid
[0].bottom
- cy
;
1181 valid
[1].top
= valid
[1].bottom
- cy
;
1185 valid
[0].bottom
= valid
[0].top
+ cy
;
1186 valid
[1].bottom
= valid
[1].top
+ cy
;
1188 if (flags
& WVR_ALIGNRIGHT
)
1190 valid
[0].left
= valid
[0].right
- cx
;
1191 valid
[1].left
= valid
[1].right
- cx
;
1195 valid
[0].right
= valid
[0].left
+ cx
;
1196 valid
[1].right
= valid
[1].left
+ cx
;
1202 co_WinPosDoNCCALCSize(PWND Window
, PWINDOWPOS WinPos
, RECTL
* WindowRect
, RECTL
* ClientRect
, RECTL
* validRects
)
1207 ASSERT_REFS_CO(Window
);
1209 /* Send WM_NCCALCSIZE message to get new client area */
1210 if ((WinPos
->flags
& (SWP_FRAMECHANGED
| SWP_NOSIZE
)) != SWP_NOSIZE
)
1212 NCCALCSIZE_PARAMS params
;
1213 WINDOWPOS winposCopy
;
1215 params
.rgrc
[0] = *WindowRect
; // new coordinates of a window that has been moved or resized
1216 params
.rgrc
[1] = Window
->rcWindow
; // window before it was moved or resized
1217 params
.rgrc
[2] = Window
->rcClient
; // client area before the window was moved or resized
1219 Parent
= Window
->spwndParent
;
1220 if (0 != (Window
->style
& WS_CHILD
) && Parent
)
1222 RECTL_vOffsetRect(&(params
.rgrc
[0]), - Parent
->rcClient
.left
, - Parent
->rcClient
.top
);
1223 RECTL_vOffsetRect(&(params
.rgrc
[1]), - Parent
->rcClient
.left
, - Parent
->rcClient
.top
);
1224 RECTL_vOffsetRect(&(params
.rgrc
[2]), - Parent
->rcClient
.left
, - Parent
->rcClient
.top
);
1227 params
.lppos
= &winposCopy
;
1228 winposCopy
= *WinPos
;
1230 wvrFlags
= co_IntSendMessage(Window
->head
.h
, WM_NCCALCSIZE
, TRUE
, (LPARAM
) ¶ms
);
1232 /* If the application send back garbage, ignore it */
1233 if (params
.rgrc
[0].left
<= params
.rgrc
[0].right
&&
1234 params
.rgrc
[0].top
<= params
.rgrc
[0].bottom
)
1236 *ClientRect
= params
.rgrc
[0]; // First rectangle contains the coordinates of the new client rectangle resulting from the move or resize
1237 if ((Window
->style
& WS_CHILD
) && Parent
)
1239 RECTL_vOffsetRect(ClientRect
, Parent
->rcClient
.left
, Parent
->rcClient
.top
);
1241 FixClientRect(ClientRect
, WindowRect
);
1244 if (ClientRect
->left
!= Window
->rcClient
.left
||
1245 ClientRect
->top
!= Window
->rcClient
.top
)
1247 WinPos
->flags
&= ~SWP_NOCLIENTMOVE
;
1250 if (ClientRect
->right
- ClientRect
->left
!= Window
->rcClient
.right
- Window
->rcClient
.left
)
1252 WinPos
->flags
&= ~SWP_NOCLIENTSIZE
;
1255 wvrFlags
&= ~WVR_HREDRAW
;
1257 if (ClientRect
->bottom
- ClientRect
->top
!= Window
->rcClient
.bottom
- Window
->rcClient
.top
)
1259 WinPos
->flags
&= ~SWP_NOCLIENTSIZE
;
1262 wvrFlags
&= ~WVR_VREDRAW
;
1264 validRects
[0] = params
.rgrc
[1]; // second rectangle contains the valid destination rectangle
1265 validRects
[1] = params
.rgrc
[2]; // third rectangle contains the valid source rectangle
1269 if (!(WinPos
->flags
& SWP_NOMOVE
) &&
1270 (ClientRect
->left
!= Window
->rcClient
.left
||
1271 ClientRect
->top
!= Window
->rcClient
.top
))
1273 WinPos
->flags
&= ~SWP_NOCLIENTMOVE
;
1277 if (WinPos
->flags
& (SWP_NOCOPYBITS
| SWP_NOREDRAW
| SWP_SHOWWINDOW
| SWP_HIDEWINDOW
))
1279 RECTL_vSetEmptyRect( &validRects
[0] );
1280 RECTL_vSetEmptyRect( &validRects
[1] );
1282 else get_valid_rects( &Window
->rcClient
, ClientRect
, wvrFlags
, validRects
);
1289 co_WinPosDoWinPosChanging(PWND Window
,
1294 ASSERT_REFS_CO(Window
);
1296 /* Send WM_WINDOWPOSCHANGING message */
1298 if (!(WinPos
->flags
& SWP_NOSENDCHANGING
))
1300 TRACE("Sending WM_WINDOWPOSCHANGING to hwnd %p flags %04x.\n", Window
->head
.h
,WinPos
->flags
);
1301 co_IntSendMessage(Window
->head
.h
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
) WinPos
);
1304 /* Calculate new position and size */
1306 *WindowRect
= Window
->rcWindow
;
1307 *ClientRect
= (Window
->style
& WS_MINIMIZE
) ? Window
->rcWindow
: Window
->rcClient
;
1309 if (!(WinPos
->flags
& SWP_NOSIZE
))
1311 if (Window
->style
& WS_MINIMIZE
)
1313 WindowRect
->right
= WindowRect
->left
+ UserGetSystemMetrics(SM_CXMINIMIZED
);
1314 WindowRect
->bottom
= WindowRect
->top
+ UserGetSystemMetrics(SM_CYMINIMIZED
);
1318 WindowRect
->right
= WindowRect
->left
+ WinPos
->cx
;
1319 WindowRect
->bottom
= WindowRect
->top
+ WinPos
->cy
;
1323 WinPos
->flags
|= SWP_NOCLIENTMOVE
| SWP_NOCLIENTSIZE
;
1325 if (!(WinPos
->flags
& SWP_NOMOVE
))
1332 Parent
= Window
->spwndParent
;
1334 // Fix wine msg test_SetParent:WmSetParentSeq_2:19 wParam bits.
1335 WinPos
->flags
&= ~SWP_NOCLIENTMOVE
;
1337 // Parent child position issue is in here. SetParent_W7 test CORE-6651.
1338 if (//((Window->style & WS_CHILD) != 0) && <- Fixes wine msg test_SetParent: "rects do not match", the last test.
1340 Parent
!= Window
->head
.rpdesk
->pDeskInfo
->spwnd
)
1342 TRACE("Not SWP_NOMOVE 1 Parent client offset X %d Y %d\n",X
,Y
);
1343 X
+= Parent
->rcClient
.left
;
1344 Y
+= Parent
->rcClient
.top
;
1345 TRACE("Not SWP_NOMOVE 2 Parent client offset X %d Y %d\n",X
,Y
);
1348 WindowRect
->left
= X
;
1349 WindowRect
->top
= Y
;
1350 WindowRect
->right
+= X
- Window
->rcWindow
.left
;
1351 WindowRect
->bottom
+= Y
- Window
->rcWindow
.top
;
1353 RECTL_vOffsetRect(ClientRect
, X
- Window
->rcWindow
.left
,
1354 Y
- Window
->rcWindow
.top
);
1357 TRACE( "hwnd %p, after %p, swp %d,%d %dx%d flags %08x\n",
1358 WinPos
->hwnd
, WinPos
->hwndInsertAfter
, WinPos
->x
, WinPos
->y
,
1359 WinPos
->cx
, WinPos
->cy
, WinPos
->flags
);
1360 TRACE("WindowRect: %d %d %d %d\n", WindowRect
->left
,WindowRect
->top
,WindowRect
->right
,WindowRect
->bottom
);
1361 TRACE("ClientRect: %d %d %d %d\n", ClientRect
->left
,ClientRect
->top
,ClientRect
->right
,ClientRect
->bottom
);
1367 * Fix Z order taking into account owned popups -
1368 * basically we need to maintain them above the window that owns them
1370 * FIXME: hide/show owned popups when owner visibility changes.
1372 * ReactOS: See bug CORE-6129 and CORE-6554.
1376 // Pass all the win:test_children/popup_zorder tests except "move hwnd_F and its popups down" which is if'ed out.
1377 // Side effect, breaks more of the DeferWindowPos api tests, but wine breaks more!!!!
1380 WinPosDoOwnedPopups(PWND Window
, HWND hWndInsertAfter
)
1385 PWND DesktopWindow
, ChildObject
;
1388 TRACE("(%p) hInsertAfter = %p\n", Window
, hWndInsertAfter
);
1390 Owner
= Window
->spwndOwner
? Window
->spwndOwner
->head
.h
: NULL
;
1391 Style
= Window
->style
;
1393 if (Style
& WS_CHILD
)
1395 TRACE("Window is child\n");
1396 return hWndInsertAfter
;
1401 /* Make sure this popup stays above the owner */
1403 if (hWndInsertAfter
!= HWND_TOPMOST
)
1405 DesktopWindow
= UserGetDesktopWindow();
1406 List
= IntWinListChildren(DesktopWindow
);
1410 for (i
= 0; List
[i
]; i
++)
1412 BOOL topmost
= FALSE
;
1414 ChildObject
= ValidateHwndNoErr(List
[i
]);
1417 topmost
= (ChildObject
->ExStyle
& WS_EX_TOPMOST
) != 0;
1420 if (List
[i
] == Owner
)
1422 if (i
> 0) hWndInsertAfter
= List
[i
-1];
1423 else hWndInsertAfter
= topmost
? HWND_TOPMOST
: HWND_TOP
;
1427 if (hWndInsertAfter
== HWND_TOP
|| hWndInsertAfter
== HWND_NOTOPMOST
)
1429 if (!topmost
) break;
1431 else if (List
[i
] == hWndInsertAfter
) break;
1435 return hWndInsertAfter
;
1439 if (hWndInsertAfter
== HWND_BOTTOM
)
1441 ERR("Window is HWND_BOTTOM\n");
1442 if (List
) ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1448 DesktopWindow
= UserGetDesktopWindow();
1449 List
= IntWinListChildren(DesktopWindow
);
1456 if (hWndInsertAfter
== HWND_TOP
|| hWndInsertAfter
== HWND_NOTOPMOST
)
1458 if (hWndInsertAfter
== HWND_NOTOPMOST
|| !(Window
->ExStyle
& WS_EX_TOPMOST
))
1460 TRACE("skip all the topmost windows\n");
1461 /* skip all the topmost windows */
1463 (ChildObject
= ValidateHwndNoErr(List
[i
])) &&
1464 (ChildObject
->ExStyle
& WS_EX_TOPMOST
)) i
++;
1467 else if (hWndInsertAfter
!= HWND_TOPMOST
)
1469 /* skip windows that are already placed correctly */
1470 for (i
= 0; List
[i
]; i
++)
1472 if (List
[i
] == hWndInsertAfter
) break;
1473 if (List
[i
] == UserHMGetHandle(Window
))
1475 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1476 goto done
; /* nothing to do if window is moving backwards in z-order */
1481 for (; List
[i
]; i
++)
1484 USER_REFERENCE_ENTRY Ref
;
1486 if (List
[i
] == UserHMGetHandle(Window
))
1489 if (!(Wnd
= ValidateHwndNoErr(List
[i
])))
1492 Owner
= Wnd
->spwndOwner
? Wnd
->spwndOwner
->head
.h
: NULL
;
1494 if (Owner
!= UserHMGetHandle(Window
)) continue;
1496 UserRefObjectCo(Wnd
, &Ref
);
1497 TRACE( "moving %p owned by %p after %p\n", List
[i
], UserHMGetHandle(Window
), hWndInsertAfter
);
1498 co_WinPosSetWindowPos(Wnd
, hWndInsertAfter
, 0, 0, 0, 0,
1499 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOSENDCHANGING
| SWP_DEFERERASE
);
1501 UserDerefObjectCo(Wnd
);
1502 hWndInsertAfter
= List
[i
];
1504 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1507 return hWndInsertAfter
;
1511 /***********************************************************************
1512 * WinPosInternalMoveWindow
1514 * Update WindowRect and ClientRect of Window and all of its children
1515 * We keep both WindowRect and ClientRect in screen coordinates internally
1519 WinPosInternalMoveWindow(PWND Window
, INT MoveX
, INT MoveY
)
1523 ASSERT(Window
!= Window
->spwndChild
);
1524 TRACE("InternalMoveWin X %d Y %d\n", MoveX
, MoveY
);
1526 Window
->rcWindow
.left
+= MoveX
;
1527 Window
->rcWindow
.right
+= MoveX
;
1528 Window
->rcWindow
.top
+= MoveY
;
1529 Window
->rcWindow
.bottom
+= MoveY
;
1531 Window
->rcClient
.left
+= MoveX
;
1532 Window
->rcClient
.right
+= MoveX
;
1533 Window
->rcClient
.top
+= MoveY
;
1534 Window
->rcClient
.bottom
+= MoveY
;
1536 for(Child
= Window
->spwndChild
; Child
; Child
= Child
->spwndNext
)
1538 WinPosInternalMoveWindow(Child
, MoveX
, MoveY
);
1543 * WinPosFixupSWPFlags
1545 * Fix redundant flags and values in the WINDOWPOS structure.
1549 WinPosFixupFlags(WINDOWPOS
*WinPos
, PWND Wnd
)
1554 /* Finally make sure that all coordinates are valid */
1555 if (WinPos
->x
< -32768) WinPos
->x
= -32768;
1556 else if (WinPos
->x
> 32767) WinPos
->x
= 32767;
1557 if (WinPos
->y
< -32768) WinPos
->y
= -32768;
1558 else if (WinPos
->y
> 32767) WinPos
->y
= 32767;
1560 WinPos
->cx
= max(WinPos
->cx
, 0);
1561 WinPos
->cy
= max(WinPos
->cy
, 0);
1563 Parent
= UserGetAncestor( Wnd
, GA_PARENT
);
1564 if (!IntIsWindowVisible( Parent
) &&
1565 /* Fix B : wine msg test_SetParent:WmSetParentSeq_2:25 wParam bits! */
1566 (WinPos
->flags
& SWP_AGG_STATUSFLAGS
) == SWP_AGG_NOPOSCHANGE
) WinPos
->flags
|= SWP_NOREDRAW
;
1568 if (Wnd
->style
& WS_VISIBLE
) WinPos
->flags
&= ~SWP_SHOWWINDOW
;
1571 WinPos
->flags
&= ~SWP_HIDEWINDOW
;
1572 if (!(WinPos
->flags
& SWP_SHOWWINDOW
)) WinPos
->flags
|= SWP_NOREDRAW
;
1575 /* Check for right size */
1576 if (Wnd
->rcWindow
.right
- Wnd
->rcWindow
.left
== WinPos
->cx
&&
1577 Wnd
->rcWindow
.bottom
- Wnd
->rcWindow
.top
== WinPos
->cy
)
1579 WinPos
->flags
|= SWP_NOSIZE
;
1584 IntClientToScreen( Parent
, &pt
);
1585 TRACE("WPFU C2S wpx %d wpy %d ptx %d pty %d\n",WinPos
->x
,WinPos
->y
,pt
.x
,pt
.y
);
1586 /* Check for right position */
1587 if (Wnd
->rcWindow
.left
== pt
.x
&& Wnd
->rcWindow
.top
== pt
.y
)
1589 //ERR("In right pos\n");
1590 WinPos
->flags
|= SWP_NOMOVE
;
1593 if ( WinPos
->hwnd
!= UserGetForegroundWindow() && (Wnd
->style
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)
1595 /* Bring to the top when activating */
1596 if (!(WinPos
->flags
& (SWP_NOACTIVATE
|SWP_HIDEWINDOW
)) &&
1597 (WinPos
->flags
& SWP_NOZORDER
||
1598 (WinPos
->hwndInsertAfter
!= HWND_TOPMOST
&& WinPos
->hwndInsertAfter
!= HWND_NOTOPMOST
)))
1600 WinPos
->flags
&= ~SWP_NOZORDER
;
1601 WinPos
->hwndInsertAfter
= (0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
) ? HWND_TOPMOST
: HWND_TOP
);
1605 /* Check hwndInsertAfter */
1606 if (!(WinPos
->flags
& SWP_NOZORDER
))
1608 /* Fix sign extension */
1609 if (WinPos
->hwndInsertAfter
== (HWND
)0xffff)
1611 WinPos
->hwndInsertAfter
= HWND_TOPMOST
;
1613 else if (WinPos
->hwndInsertAfter
== (HWND
)0xfffe)
1615 WinPos
->hwndInsertAfter
= HWND_NOTOPMOST
;
1618 if (WinPos
->hwndInsertAfter
== HWND_TOP
)
1620 /* Keep it topmost when it's already topmost */
1621 if ((Wnd
->ExStyle
& WS_EX_TOPMOST
) != 0)
1622 WinPos
->hwndInsertAfter
= HWND_TOPMOST
;
1624 if (IntGetWindow(WinPos
->hwnd
, GW_HWNDFIRST
) == WinPos
->hwnd
)
1626 WinPos
->flags
|= SWP_NOZORDER
;
1629 else if (WinPos
->hwndInsertAfter
== HWND_BOTTOM
)
1631 if (!(Wnd
->ExStyle
& WS_EX_TOPMOST
) && IntGetWindow(WinPos
->hwnd
, GW_HWNDLAST
) == WinPos
->hwnd
)
1632 WinPos
->flags
|= SWP_NOZORDER
;
1634 else if (WinPos
->hwndInsertAfter
== HWND_TOPMOST
)
1636 if ((Wnd
->ExStyle
& WS_EX_TOPMOST
) && IntGetWindow(WinPos
->hwnd
, GW_HWNDFIRST
) == WinPos
->hwnd
)
1637 WinPos
->flags
|= SWP_NOZORDER
;
1639 else if (WinPos
->hwndInsertAfter
== HWND_NOTOPMOST
)
1641 if (!(Wnd
->ExStyle
& WS_EX_TOPMOST
))
1642 WinPos
->flags
|= SWP_NOZORDER
;
1644 else /* hwndInsertAfter must be a sibling of the window */
1648 InsAfterWnd
= ValidateHwndNoErr(WinPos
->hwndInsertAfter
);
1654 if (InsAfterWnd
->spwndParent
!= Wnd
->spwndParent
)
1656 /* Note from wine User32 Win test_SetWindowPos:
1657 "Returns TRUE also for windows that are not siblings"
1658 "Does not seem to do anything even without passing flags, still returns TRUE"
1659 "Same thing the other way around."
1660 ".. and with these windows."
1667 * We don't need to change the Z order of hwnd if it's already
1668 * inserted after hwndInsertAfter or when inserting hwnd after
1671 if ((WinPos
->hwnd
== WinPos
->hwndInsertAfter
) ||
1672 ((InsAfterWnd
->spwndNext
) && (WinPos
->hwnd
== InsAfterWnd
->spwndNext
->head
.h
)))
1674 WinPos
->flags
|= SWP_NOZORDER
;
1683 /* x and y are always screen relative */
1685 co_WinPosSetWindowPos(
1687 HWND WndInsertAfter
,
1696 RECTL NewWindowRect
;
1697 RECTL NewClientRect
;
1698 RECTL valid_rects
[2];
1699 PREGION VisBefore
= NULL
;
1700 PREGION VisBeforeJustClient
= NULL
;
1701 PREGION VisAfter
= NULL
;
1702 PREGION CopyRgn
= NULL
;
1704 RECTL OldWindowRect
, OldClientRect
;
1709 BOOL bPointerInWindow
;
1710 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1712 ASSERT_REFS_CO(Window
);
1714 /* FIXME: Get current active window from active queue. Why? since r2915. */
1716 bPointerInWindow
= IntPtInWindow(Window
, gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
);
1718 WinPos
.hwnd
= Window
->head
.h
;
1719 WinPos
.hwndInsertAfter
= WndInsertAfter
;
1724 WinPos
.flags
= flags
;
1726 if ( flags
& SWP_ASYNCWINDOWPOS
)
1729 PWINDOWPOS ppos
= ExAllocatePoolWithTag(PagedPool
, sizeof(WINDOWPOS
), USERTAG_SWP
);
1732 WinPos
.flags
&= ~SWP_ASYNCWINDOWPOS
; // Clear flag.
1734 /* Yes it's a pointer inside Win32k! */
1735 lRes
= co_IntSendMessageNoWait( WinPos
.hwnd
, WM_ASYNC_SETWINDOWPOS
, 0, (LPARAM
)ppos
);
1736 /* We handle this the same way as Event Hooks and Hooks. */
1739 ExFreePoolWithTag(ppos
, USERTAG_SWP
);
1747 co_WinPosDoWinPosChanging(Window
, &WinPos
, &NewWindowRect
, &NewClientRect
);
1749 /* Does the window still exist? */
1750 if (!IntIsWindow(WinPos
.hwnd
))
1752 TRACE("WinPosSetWindowPos: Invalid handle 0x%p!\n",WinPos
.hwnd
);
1753 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE
);
1757 /* Fix up the flags. */
1758 if (!WinPosFixupFlags(&WinPos
, Window
))
1764 Ancestor
= UserGetAncestor(Window
, GA_PARENT
);
1765 if ( (WinPos
.flags
& (SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) != SWP_NOZORDER
&&
1766 Ancestor
&& Ancestor
->head
.h
== IntGetDesktopWindow() )
1768 WinPos
.hwndInsertAfter
= WinPosDoOwnedPopups(Window
, WinPos
.hwndInsertAfter
);
1771 if (!(WinPos
.flags
& SWP_NOREDRAW
))
1773 /* Compute the visible region before the window position is changed */
1774 if (!(WinPos
.flags
& SWP_SHOWWINDOW
) &&
1775 (WinPos
.flags
& (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
|
1776 SWP_HIDEWINDOW
| SWP_FRAMECHANGED
)) !=
1777 (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
))
1779 VisBefore
= VIS_ComputeVisibleRegion(Window
, FALSE
, FALSE
,
1780 (Window
->style
& WS_CLIPSIBLINGS
) ? TRUE
: FALSE
);
1782 if ( VisBefore
!= NULL
&&
1783 REGION_Complexity(VisBefore
) == NULLREGION
)
1785 REGION_Delete(VisBefore
);
1790 REGION_bOffsetRgn(VisBefore
, -Window
->rcWindow
.left
, -Window
->rcWindow
.top
);
1793 /* Calculate the non client area for resizes, as this is used in the copy region */
1794 if (!(WinPos
.flags
& SWP_NOSIZE
))
1796 VisBeforeJustClient
= VIS_ComputeVisibleRegion(Window
, TRUE
, FALSE
,
1797 (Window
->style
& WS_CLIPSIBLINGS
) ? TRUE
: FALSE
);
1799 if ( VisBeforeJustClient
!= NULL
&&
1800 REGION_Complexity(VisBeforeJustClient
) == NULLREGION
)
1802 REGION_Delete(VisBeforeJustClient
);
1803 VisBeforeJustClient
= NULL
;
1805 else if(VisBeforeJustClient
)
1807 REGION_bOffsetRgn(VisBeforeJustClient
, -Window
->rcWindow
.left
, -Window
->rcWindow
.top
);
1813 WvrFlags
= co_WinPosDoNCCALCSize(Window
, &WinPos
, &NewWindowRect
, &NewClientRect
, valid_rects
);
1815 // ERR("co_WinPosDoNCCALCSize returned 0x%x\n valid dest: %d %d %d %d\n valid src : %d %d %d %d\n", WvrFlags,
1816 // valid_rects[0].left,valid_rects[0].top,valid_rects[0].right,valid_rects[0].bottom,
1817 // valid_rects[1].left,valid_rects[1].top,valid_rects[1].right,valid_rects[1].bottom);
1819 /* Validate link windows. (also take into account shell window in hwndShellWindow) */
1820 if (!(WinPos
.flags
& SWP_NOZORDER
) && WinPos
.hwnd
!= UserGetShellWindow())
1822 IntLinkHwnd(Window
, WinPos
.hwndInsertAfter
);
1825 OldWindowRect
= Window
->rcWindow
;
1826 OldClientRect
= Window
->rcClient
;
1828 if (NewClientRect
.left
!= OldClientRect
.left
||
1829 NewClientRect
.top
!= OldClientRect
.top
)
1831 // Move child window if their parent is moved. Keep Child window relative to Parent...
1832 WinPosInternalMoveWindow(Window
,
1833 NewClientRect
.left
- OldClientRect
.left
,
1834 NewClientRect
.top
- OldClientRect
.top
);
1837 Window
->rcWindow
= NewWindowRect
;
1838 Window
->rcClient
= NewClientRect
;
1840 /* erase parent when hiding or resizing child */
1841 if (WinPos
.flags
& SWP_HIDEWINDOW
)
1843 /* Clear the update region */
1844 co_UserRedrawWindow( Window
,
1847 RDW_VALIDATE
| RDW_NOFRAME
| RDW_NOERASE
| RDW_NOINTERNALPAINT
| RDW_ALLCHILDREN
);
1849 if (Window
->spwndParent
== UserGetDesktopWindow())
1850 co_IntShellHookNotify(HSHELL_WINDOWDESTROYED
, (WPARAM
)Window
->head
.h
, 0);
1852 Window
->style
&= ~WS_VISIBLE
; //IntSetStyle( Window, 0, WS_VISIBLE );
1853 Window
->head
.pti
->cVisWindows
--;
1854 IntNotifyWinEvent(EVENT_OBJECT_HIDE
, Window
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
1856 else if (WinPos
.flags
& SWP_SHOWWINDOW
)
1858 if (Window
->spwndParent
== UserGetDesktopWindow() &&
1859 Window
->spwndOwner
== NULL
&&
1860 (!(Window
->ExStyle
& WS_EX_TOOLWINDOW
) ||
1861 (Window
->ExStyle
& WS_EX_APPWINDOW
)))
1862 co_IntShellHookNotify(HSHELL_WINDOWCREATED
, (WPARAM
)Window
->head
.h
, 0);
1864 Window
->style
|= WS_VISIBLE
; //IntSetStyle( Window, WS_VISIBLE, 0 );
1865 Window
->head
.pti
->cVisWindows
++;
1866 IntNotifyWinEvent(EVENT_OBJECT_SHOW
, Window
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
1869 if (Window
->hrgnUpdate
!= NULL
&& Window
->hrgnUpdate
!= HRGN_WINDOW
)
1871 NtGdiOffsetRgn(Window
->hrgnUpdate
,
1872 NewWindowRect
.left
- OldWindowRect
.left
,
1873 NewWindowRect
.top
- OldWindowRect
.top
);
1876 DceResetActiveDCEs(Window
); // For WS_VISIBLE changes.
1878 if (!(WinPos
.flags
& SWP_NOREDRAW
))
1880 /* Determine the new visible region */
1881 VisAfter
= VIS_ComputeVisibleRegion(Window
, FALSE
, FALSE
,
1882 (Window
->style
& WS_CLIPSIBLINGS
) ? TRUE
: FALSE
);
1884 if ( VisAfter
!= NULL
&&
1885 REGION_Complexity(VisAfter
) == NULLREGION
)
1887 REGION_Delete(VisAfter
);
1892 REGION_bOffsetRgn(VisAfter
, -Window
->rcWindow
.left
, -Window
->rcWindow
.top
);
1896 * Determine which pixels can be copied from the old window position
1897 * to the new. Those pixels must be visible in both the old and new
1898 * position. Also, check the class style to see if the windows of this
1899 * class need to be completely repainted on (horizontal/vertical) size
1902 if ( VisBefore
!= NULL
&&
1904 !(WinPos
.flags
& SWP_NOCOPYBITS
) &&
1905 ((WinPos
.flags
& SWP_NOSIZE
) || !(WvrFlags
& WVR_REDRAW
)) &&
1906 !(Window
->ExStyle
& WS_EX_TRANSPARENT
) )
1910 * If this is (also) a window resize, the whole nonclient area
1911 * needs to be repainted. So we limit the copy to the client area,
1912 * 'cause there is no use in copying it (would possibly cause
1913 * "flashing" too). However, if the copy region is already empty,
1914 * we don't have to crop (can't take anything away from an empty
1918 CopyRgn
= IntSysCreateRectpRgn(0, 0, 0, 0);
1919 if (WinPos
.flags
& SWP_NOSIZE
)
1920 RgnType
= IntGdiCombineRgn(CopyRgn
, VisAfter
, VisBefore
, RGN_AND
);
1921 else if (VisBeforeJustClient
!= NULL
)
1923 RgnType
= IntGdiCombineRgn(CopyRgn
, VisAfter
, VisBeforeJustClient
, RGN_AND
);
1924 REGION_Delete(VisBeforeJustClient
);
1927 /* No use in copying bits which are in the update region. */
1928 if (Window
->hrgnUpdate
!= NULL
)
1930 PREGION RgnUpdate
= REGION_LockRgn(Window
->hrgnUpdate
);
1933 REGION_bOffsetRgn(CopyRgn
, NewWindowRect
.left
, NewWindowRect
.top
);
1934 IntGdiCombineRgn(CopyRgn
, CopyRgn
, RgnUpdate
, RGN_DIFF
);
1935 REGION_bOffsetRgn(CopyRgn
, -NewWindowRect
.left
, -NewWindowRect
.top
);
1936 REGION_UnlockRgn(RgnUpdate
);
1941 * Now, get the bounding box of the copy region. If it's empty
1942 * there's nothing to copy. Also, it's no use copying bits onto
1945 if (REGION_GetRgnBox(CopyRgn
, &CopyRect
) == NULLREGION
)
1947 /* Nothing to copy, clean up */
1948 REGION_Delete(CopyRgn
);
1951 else if (OldWindowRect
.left
!= NewWindowRect
.left
||
1952 OldWindowRect
.top
!= NewWindowRect
.top
)
1954 HRGN DcRgn
= NtGdiCreateRectRgn(0, 0, 0, 0);
1955 PREGION DcRgnObj
= REGION_LockRgn(DcRgn
);
1958 * Small trick here: there is no function to bitblt a region. So
1959 * we set the region as the clipping region, take the bounding box
1960 * of the region and bitblt that. Since nothing outside the clipping
1961 * region is copied, this has the effect of bitblt'ing the region.
1963 * Since NtUserGetDCEx takes ownership of the clip region, we need
1964 * to create a copy of CopyRgn and pass that. We need CopyRgn later
1966 IntGdiCombineRgn(DcRgnObj
, CopyRgn
, NULL
, RGN_COPY
);
1967 REGION_bOffsetRgn(DcRgnObj
, NewWindowRect
.left
, NewWindowRect
.top
);
1968 REGION_UnlockRgn(DcRgnObj
);
1969 Dc
= UserGetDCEx( Window
,
1971 DCX_WINDOW
|DCX_CACHE
|DCX_INTERSECTRGN
|DCX_CLIPSIBLINGS
|DCX_KEEPCLIPRGN
);
1973 CopyRect
.left
, CopyRect
.top
,
1974 CopyRect
.right
- CopyRect
.left
,
1975 CopyRect
.bottom
- CopyRect
.top
,
1977 CopyRect
.left
+ (OldWindowRect
.left
- NewWindowRect
.left
),
1978 CopyRect
.top
+ (OldWindowRect
.top
- NewWindowRect
.top
),
1983 UserReleaseDC(Window
, Dc
, FALSE
);
1984 IntValidateParent(Window
, CopyRgn
, FALSE
);
1985 GreDeleteObject(DcRgn
);
1993 /* We need to redraw what wasn't visible before */
1994 if (VisAfter
!= NULL
)
1996 PREGION DirtyRgn
= IntSysCreateRectpRgn(0, 0, 0, 0);
1999 if (CopyRgn
!= NULL
)
2001 RgnType
= IntGdiCombineRgn(DirtyRgn
, VisAfter
, CopyRgn
, RGN_DIFF
);
2005 RgnType
= IntGdiCombineRgn(DirtyRgn
, VisAfter
, 0, RGN_COPY
);
2007 if (RgnType
!= ERROR
&& RgnType
!= NULLREGION
)
2010 NtGdiOffsetRgn(DirtyRgn, Window->rcWindow.left, Window->rcWindow.top);
2011 IntInvalidateWindows( Window,
2013 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
2015 GreDeleteObject(DirtyRgn);
2018 PWND Parent
= Window
->spwndParent
;
2020 REGION_bOffsetRgn( DirtyRgn
,
2021 Window
->rcWindow
.left
,
2022 Window
->rcWindow
.top
);
2023 if ( (Window
->style
& WS_CHILD
) &&
2025 !(Parent
->style
& WS_CLIPCHILDREN
))
2027 IntInvalidateWindows( Parent
,
2029 RDW_ERASE
| RDW_INVALIDATE
);
2030 co_IntPaintWindows(Parent
, RDW_ERASENOW
, FALSE
);
2034 IntInvalidateWindows( Window
,
2036 RDW_ERASE
| RDW_FRAME
| RDW_INVALIDATE
| RDW_ALLCHILDREN
);
2039 REGION_Delete(DirtyRgn
);
2043 if (CopyRgn
!= NULL
)
2045 REGION_Delete(CopyRgn
);
2048 /* Expose what was covered before but not covered anymore */
2049 if (VisBefore
!= NULL
)
2051 PREGION ExposedRgn
= IntSysCreateRectpRgn(0, 0, 0, 0);
2054 RgnType
= IntGdiCombineRgn(ExposedRgn
, VisBefore
, NULL
, RGN_COPY
);
2055 REGION_bOffsetRgn(ExposedRgn
,
2056 OldWindowRect
.left
- NewWindowRect
.left
,
2057 OldWindowRect
.top
- NewWindowRect
.top
);
2059 if (VisAfter
!= NULL
)
2060 RgnType
= IntGdiCombineRgn(ExposedRgn
, ExposedRgn
, VisAfter
, RGN_DIFF
);
2062 if (RgnType
!= ERROR
&& RgnType
!= NULLREGION
)
2064 co_VIS_WindowLayoutChanged(Window
, ExposedRgn
);
2066 REGION_Delete(ExposedRgn
);
2068 REGION_Delete(VisBefore
);
2071 if (VisAfter
!= NULL
)
2073 REGION_Delete(VisAfter
);
2077 if (!(WinPos
.flags
& (SWP_NOACTIVATE
|SWP_HIDEWINDOW
)))
2079 if ((Window
->style
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
2081 co_IntSendMessageNoWait(WinPos
.hwnd
, WM_CHILDACTIVATE
, 0, 0);
2083 /* Do not allow setting if already active.
2084 Fix A : wine msg test_SetParent:WmSetParentSeq_2:25 msg!
2085 Recursion broke the tests.
2087 else if ( pti
->MessageQueue
->spwndActive
!= Window
||
2088 pti
->MessageQueue
!= gpqForeground
) // This fixes the breakage at boot time caused by the above line!
2090 // Inside SAW? Fixes Api AttachThreadInput tests.
2091 TRACE("SetWindowPos Set FG Window! hWnd %p\n",WinPos
.hwnd
);
2092 if (!(Window
->state
& WNDS_BEINGACTIVATED
))
2094 TRACE("SetWindowPos Set FG Window!\n");
2095 // Fixes SW_HIDE issues. Wine win test_SetActiveWindow & test_SetForegroundWindow.
2096 co_IntSetForegroundWindow(Window
);
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 /* And last, send the WM_WINDOWPOSCHANGED message */
2113 TRACE("\tstatus hwnd %p flags = %04x\n",Window
?Window
->head
.h
:NULL
,WinPos
.flags
& SWP_AGG_STATUSFLAGS
);
2115 if ((WinPos
.flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOPOSCHANGE
)
2117 /* WM_WINDOWPOSCHANGED is sent even if SWP_NOSENDCHANGING is set
2118 and always contains final window position.
2120 WinPos
.x
= NewWindowRect
.left
;
2121 WinPos
.y
= NewWindowRect
.top
;
2122 WinPos
.cx
= NewWindowRect
.right
- NewWindowRect
.left
;
2123 WinPos
.cy
= NewWindowRect
.bottom
- NewWindowRect
.top
;
2124 TRACE("WM_WINDOWPOSCHANGED hwnd %p Flags %04x\n",WinPos
.hwnd
,WinPos
.flags
);
2125 co_IntSendMessageNoWait(WinPos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
) &WinPos
);
2128 if ( WinPos
.flags
& SWP_FRAMECHANGED
|| WinPos
.flags
& SWP_STATECHANGED
||
2129 !(WinPos
.flags
& SWP_NOCLIENTSIZE
) || !(WinPos
.flags
& SWP_NOCLIENTMOVE
) )
2131 PWND pWnd
= ValidateHwndNoErr(WinPos
.hwnd
);
2133 IntNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE
, pWnd
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
2136 if(bPointerInWindow
!= IntPtInWindow(Window
, gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
))
2138 /* Generate mouse move message */
2140 msg
.message
= WM_MOUSEMOVE
;
2141 msg
.wParam
= UserGetMouseButtonsState();
2142 msg
.lParam
= MAKELPARAM(gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
);
2143 msg
.pt
= gpsi
->ptCursor
;
2144 co_MsqInsertMouseMessage(&msg
, 0, 0, TRUE
);
2151 co_WinPosGetNonClientSize(PWND Window
, RECT
* WindowRect
, RECT
* ClientRect
)
2155 ASSERT_REFS_CO(Window
);
2157 *ClientRect
= *WindowRect
;
2158 Result
= co_IntSendMessageNoWait(Window
->head
.h
, WM_NCCALCSIZE
, FALSE
, (LPARAM
) ClientRect
);
2160 FixClientRect(ClientRect
, WindowRect
);
2166 co_WinPosSendSizeMove(PWND Wnd
)
2170 WPARAM wParam
= SIZE_RESTORED
;
2172 IntGetClientRect(Wnd
, &Rect
);
2173 lParam
= MAKELONG(Rect
.right
-Rect
.left
, Rect
.bottom
-Rect
.top
);
2175 Wnd
->state
&= ~WNDS_SENDSIZEMOVEMSGS
;
2177 if (Wnd
->style
& WS_MAXIMIZE
)
2179 wParam
= SIZE_MAXIMIZED
;
2181 else if (Wnd
->style
& WS_MINIMIZE
)
2183 wParam
= SIZE_MINIMIZED
;
2187 co_IntSendMessageNoWait(UserHMGetHandle(Wnd
), WM_SIZE
, wParam
, lParam
);
2189 if (Wnd
->spwndParent
== UserGetDesktopWindow()) // Wnd->spwndParent->fnid == FNID_DESKTOP )
2190 lParam
= MAKELONG(Wnd
->rcClient
.left
, Wnd
->rcClient
.top
);
2192 lParam
= MAKELONG(Wnd
->rcClient
.left
-Wnd
->spwndParent
->rcClient
.left
, Wnd
->rcClient
.top
-Wnd
->spwndParent
->rcClient
.top
);
2194 co_IntSendMessageNoWait(UserHMGetHandle(Wnd
), WM_MOVE
, 0, lParam
);
2196 IntEngWindowChanged(Wnd
, WOC_RGN_CLIENT
);
2200 ShowWindow does not set SWP_FRAMECHANGED!!! Fix wine msg test_SetParent:WmSetParentSeq_2:23 wParam bits!
2203 co_WinPosShowWindow(PWND Wnd
, INT Cmd
)
2206 UINT Swp
= 0, EventMsg
= 0;
2207 RECTL NewPos
= {0, 0, 0, 0};
2213 BOOL ShowOwned
= FALSE
;
2214 BOOL FirstTime
= FALSE
;
2215 ASSERT_REFS_CO(Wnd
);
2216 //KeRosDumpStackFrames(NULL, 20);
2217 pti
= PsGetCurrentThreadWin32Thread();
2218 WasVisible
= (Wnd
->style
& WS_VISIBLE
) != 0;
2221 TRACE("co_WinPosShowWindow START hwnd %p Cmd %d usicmd %u\n",
2222 Wnd
->head
.h
, Cmd
, pti
->ppi
->usi
.wShowWindow
);
2224 if ( pti
->ppi
->usi
.dwFlags
& STARTF_USESHOWWINDOW
)
2226 if ((Wnd
->style
& (WS_POPUP
|WS_CHILD
)) != WS_CHILD
)
2228 if ((Wnd
->style
& WS_CAPTION
) == WS_CAPTION
)
2230 if (Wnd
->spwndOwner
== NULL
)
2232 if ( Cmd
== SW_SHOWNORMAL
|| Cmd
== SW_SHOW
)
2234 Cmd
= SW_SHOWDEFAULT
;
2237 ERR("co_WPSW FT 1\n");
2243 if ( Cmd
== SW_SHOWDEFAULT
)
2245 if ( pti
->ppi
->usi
.dwFlags
& STARTF_USESHOWWINDOW
)
2247 Cmd
= pti
->ppi
->usi
.wShowWindow
;
2249 ERR("co_WPSW FT 2\n");
2255 pti
->ppi
->usi
.dwFlags
&= ~(STARTF_USEPOSITION
|STARTF_USESIZE
|STARTF_USESHOWWINDOW
);
2264 //ERR("co_WinPosShowWindow Exit Bad\n");
2267 Swp
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
2268 if (Wnd
!= pti
->MessageQueue
->spwndActive
)
2269 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2273 case SW_FORCEMINIMIZE
: /* FIXME: Does not work if thread is hung. */
2274 case SW_SHOWMINNOACTIVE
:
2275 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2277 case SW_SHOWMINIMIZED
:
2278 Swp
|= SWP_SHOWWINDOW
;
2282 Swp
|= SWP_NOACTIVATE
;
2283 if (!(style
& WS_MINIMIZE
))
2285 IntShowOwnedPopups(Wnd
, FALSE
);
2286 // Fix wine Win test_SetFocus todo #1 & #2,
2287 if (Cmd
== SW_SHOWMINIMIZED
)
2289 //ERR("co_WinPosShowWindow Set focus 1\n");
2290 if ((style
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
2291 co_UserSetFocus(Wnd
->spwndParent
);
2296 Swp
|= co_WinPosMinMaximize(Wnd
, Cmd
, &NewPos
);
2298 EventMsg
= EVENT_SYSTEM_MINIMIZESTART
;
2304 //ERR("co_WinPosShowWindow Exit Good\n");
2307 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
2312 case SW_SHOWMAXIMIZED
:
2314 Swp
|= SWP_SHOWWINDOW
;
2315 if (!(style
& WS_MAXIMIZE
))
2319 Swp
|= co_WinPosMinMaximize(Wnd
, SW_MAXIMIZE
, &NewPos
);
2321 EventMsg
= EVENT_SYSTEM_MINIMIZEEND
;
2327 //ERR("co_WinPosShowWindow Exit Good 1\n");
2330 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
2336 Swp
|= SWP_NOACTIVATE
| SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
2337 if (style
& WS_CHILD
&& !(Wnd
->ExStyle
& WS_EX_MDICHILD
)) Swp
|= SWP_NOZORDER
;
2340 if (WasVisible
) return(TRUE
); // Nothing to do!
2341 Swp
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
2342 /* Don't activate the topmost window. */
2343 if (style
& WS_CHILD
&& !(Wnd
->ExStyle
& WS_EX_MDICHILD
)) Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2346 case SW_SHOWNOACTIVATE
:
2347 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2350 case SW_SHOWDEFAULT
:
2352 if (!WasVisible
) Swp
|= SWP_SHOWWINDOW
;
2353 if (style
& (WS_MINIMIZE
| WS_MAXIMIZE
))
2355 Swp
|= co_WinPosMinMaximize(Wnd
, Cmd
, &NewPos
);
2356 if (style
& WS_MINIMIZE
) EventMsg
= EVENT_SYSTEM_MINIMIZEEND
;
2362 //ERR("co_WinPosShowWindow Exit Good 3\n");
2365 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
2367 if ( style
& WS_CHILD
&&
2368 !(Wnd
->ExStyle
& WS_EX_MDICHILD
) &&
2369 !(Swp
& SWP_STATECHANGED
))
2370 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2374 //ERR("co_WinPosShowWindow Exit Good 4\n");
2378 ShowFlag
= (Cmd
!= SW_HIDE
);
2380 if ((ShowFlag
!= WasVisible
|| Cmd
== SW_SHOWNA
) && Cmd
!= SW_SHOWMAXIMIZED
&& !(Swp
& SWP_STATECHANGED
))
2382 co_IntSendMessageNoWait(Wnd
->head
.h
, WM_SHOWWINDOW
, ShowFlag
, 0);
2383 #if 0 // Fix wine msg test_SetParent:WmSetParentSeq_1:2
2384 if (!(Wnd
->state2
& WNDS2_WIN31COMPAT
)) // <------------- XP sets this bit!
2385 co_IntSendMessageNoWait(Wnd
->head
.h
, WM_SETVISIBLE
, ShowFlag
, 0);
2387 if (!VerifyWnd(Wnd
)) return WasVisible
;
2390 /* We can't activate a child window */
2391 if ((Wnd
->style
& WS_CHILD
) &&
2392 !(Wnd
->ExStyle
& WS_EX_MDICHILD
) &&
2395 //ERR("SWP Child No active and ZOrder\n");
2396 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2399 #if 0 // Explorer issues with common controls? Someone does not know how CS_SAVEBITS works.
2400 // Breaks startup and shutdown active window...
2401 if ((Wnd
->style
& (WS_POPUP
|WS_CHILD
)) != WS_CHILD
&&
2402 Wnd
->pcls
->style
& CS_SAVEBITS
&&
2403 ((Cmd
== SW_SHOW
) || (Cmd
== SW_NORMAL
)))
2405 ERR("WinPosShowWindow Set active\n");
2406 UserSetActiveWindow(Wnd
);
2407 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2411 if (IsChildVisible(Wnd
) || Swp
& SWP_STATECHANGED
)
2413 TRACE("Child is Vis %s or State changed %s. ShowFlag %s Swp %04x\n",
2414 (IsChildVisible(Wnd
) ? "TRUE" : "FALSE"), (Swp
& SWP_STATECHANGED
? "TRUE" : "FALSE"),
2415 (ShowFlag
? "TRUE" : "FALSE"),LOWORD(Swp
));
2416 co_WinPosSetWindowPos( Wnd
,
2417 0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
) ? HWND_TOPMOST
: HWND_TOP
,
2420 NewPos
.right
, // NewPos.right - NewPos.left, when minimized and restore, the window becomes smaller.
2421 NewPos
.bottom
,// NewPos.bottom - NewPos.top,
2426 TRACE("Parent Vis?\n");
2427 /* if parent is not visible simply toggle WS_VISIBLE and return */
2428 if (ShowFlag
) IntSetStyle( Wnd
, WS_VISIBLE
, 0 );
2429 else IntSetStyle( Wnd
, 0, WS_VISIBLE
);
2432 if ( EventMsg
) IntNotifyWinEvent(EventMsg
, Wnd
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
2434 if ( ShowOwned
) IntShowOwnedPopups(Wnd
, TRUE
);
2436 if ((Cmd
== SW_HIDE
) || (Cmd
== SW_MINIMIZE
))
2438 if ( Wnd
== pti
->MessageQueue
->spwndActive
&& pti
->MessageQueue
== IntGetFocusMessageQueue() )
2440 if ( Wnd
->spwndParent
== UserGetDesktopWindow())
2442 if (!ActivateOtherWindowMin(Wnd
))
2444 co_WinPosActivateOtherWindow(Wnd
);
2449 co_WinPosActivateOtherWindow(Wnd
);
2453 /* Revert focus to parent */
2454 if (Wnd
== pti
->MessageQueue
->spwndFocus
)
2456 Parent
= Wnd
->spwndParent
;
2457 if (Wnd
->spwndParent
== UserGetDesktopWindow()) Parent
= 0;
2458 co_UserSetFocus(Parent
);
2460 // Hide, just return.
2461 if (Cmd
== SW_HIDE
) return WasVisible
;
2464 /* FIXME: Check for window destruction. */
2466 if ((Wnd
->state
& WNDS_SENDSIZEMOVEMSGS
) &&
2467 !(Wnd
->state2
& WNDS2_INDESTROY
))
2469 co_WinPosSendSizeMove(Wnd
);
2472 /* if previous state was minimized Windows sets focus to the window */
2473 if (style
& WS_MINIMIZE
)
2475 co_UserSetFocus(Wnd
);
2476 // Fix wine Win test_SetFocus todo #3,
2477 if (!(style
& WS_CHILD
)) co_IntSendMessageNoWait(UserHMGetHandle(Wnd
), WM_ACTIVATE
, WA_ACTIVE
, 0);
2479 //ERR("co_WinPosShowWindow EXIT\n");
2484 co_WinPosSearchChildren(
2487 IN OUT USHORT
*HitTest
,
2492 PWND pwndChild
= NULL
;
2495 if (!(ScopeWin
->style
& WS_VISIBLE
))
2500 /* not in window or in window region */
2501 if (!IntPtInWindow(ScopeWin
, Point
->x
, Point
->y
))
2507 if ((ScopeWin
->ExStyle
& (WS_EX_LAYERED
|WS_EX_TRANSPARENT
)) == (WS_EX_LAYERED
|WS_EX_TRANSPARENT
))
2512 if (!Ignore
&& (ScopeWin
->style
& WS_DISABLED
))
2513 { /* disabled child */
2514 if ((ScopeWin
->style
& (WS_POPUP
|WS_CHILD
)) == WS_CHILD
) return NULL
;
2515 /* process the hit error */
2520 /* not minimized and check if point is inside the window */
2521 if (!(ScopeWin
->style
& WS_MINIMIZE
) &&
2522 RECTL_bPointInRect(&ScopeWin
->rcClient
, Point
->x
, Point
->y
) )
2524 UserReferenceObject(ScopeWin
);
2526 List
= IntWinListChildren(ScopeWin
);
2529 for (phWnd
= List
; *phWnd
; ++phWnd
)
2531 if (!(pwndChild
= ValidateHwndNoErr(*phWnd
)))
2536 pwndChild
= co_WinPosSearchChildren(pwndChild
, Point
, HitTest
, Ignore
);
2538 if (pwndChild
!= NULL
)
2540 /* We found a window. Don't send any more WM_NCHITTEST messages */
2541 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2542 UserDereferenceObject(ScopeWin
);
2546 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2548 UserDereferenceObject(ScopeWin
);
2551 if (ScopeWin
->head
.pti
== PsGetCurrentThreadWin32Thread())
2553 *HitTest
= (USHORT
)co_IntSendMessage(ScopeWin
->head
.h
, WM_NCHITTEST
, 0, MAKELONG(Point
->x
, Point
->y
));
2555 if ((*HitTest
) == (USHORT
)HTTRANSPARENT
)
2562 if (*HitTest
== HTNOWHERE
&& pwndChild
== NULL
) *HitTest
= HTCLIENT
;
2569 co_WinPosWindowFromPoint(
2572 IN OUT USHORT
* HitTest
,
2576 POINT Point
= *WinPoint
;
2577 USER_REFERENCE_ENTRY Ref
;
2579 if( ScopeWin
== NULL
)
2581 ScopeWin
= UserGetDesktopWindow();
2582 if(ScopeWin
== NULL
)
2586 *HitTest
= HTNOWHERE
;
2588 ASSERT_REFS_CO(ScopeWin
);
2589 UserRefObjectCo(ScopeWin
, &Ref
);
2591 Window
= co_WinPosSearchChildren(ScopeWin
, &Point
, HitTest
, Ignore
);
2593 UserDerefObjectCo(ScopeWin
);
2595 ASSERT_REFS_CO(Window
);
2596 ASSERT_REFS_CO(ScopeWin
);
2602 IntRealChildWindowFromPoint(PWND Parent
, LONG x
, LONG y
)
2606 PWND pwndHit
= NULL
;
2611 if (Parent
!= UserGetDesktopWindow())
2613 Pt
.x
+= Parent
->rcClient
.left
;
2614 Pt
.y
+= Parent
->rcClient
.top
;
2617 if (!IntPtInWindow(Parent
, Pt
.x
, Pt
.y
)) return NULL
;
2619 if ((List
= IntWinListChildren(Parent
)))
2621 for (phWnd
= List
; *phWnd
; phWnd
++)
2624 if ((Child
= ValidateHwndNoErr(*phWnd
)))
2626 if ( Child
->style
& WS_VISIBLE
&& IntPtInWindow(Child
, Pt
.x
, Pt
.y
) )
2628 if ( Child
->pcls
->atomClassName
!= gpsi
->atomSysClass
[ICLS_BUTTON
] ||
2629 (Child
->style
& BS_TYPEMASK
) != BS_GROUPBOX
)
2631 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2638 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2640 return pwndHit
? pwndHit
: Parent
;
2644 IntChildWindowFromPointEx(PWND Parent
, LONG x
, LONG y
, UINT uiFlags
)
2648 PWND pwndHit
= NULL
;
2653 if (Parent
!= UserGetDesktopWindow())
2655 if (Parent
->ExStyle
& WS_EX_LAYOUTRTL
)
2656 Pt
.x
= Parent
->rcClient
.right
- Pt
.x
;
2658 Pt
.x
+= Parent
->rcClient
.left
;
2659 Pt
.y
+= Parent
->rcClient
.top
;
2662 if (!IntPtInWindow(Parent
, Pt
.x
, Pt
.y
)) return NULL
;
2664 if ((List
= IntWinListChildren(Parent
)))
2666 for (phWnd
= List
; *phWnd
; phWnd
++)
2669 if ((Child
= ValidateHwndNoErr(*phWnd
)))
2671 if (uiFlags
& (CWP_SKIPINVISIBLE
|CWP_SKIPDISABLED
))
2673 if (!(Child
->style
& WS_VISIBLE
) && (uiFlags
& CWP_SKIPINVISIBLE
)) continue;
2674 if ((Child
->style
& WS_DISABLED
) && (uiFlags
& CWP_SKIPDISABLED
)) continue;
2677 if (uiFlags
& CWP_SKIPTRANSPARENT
)
2679 if (Child
->ExStyle
& WS_EX_TRANSPARENT
) continue;
2682 if (IntPtInWindow(Child
, Pt
.x
, Pt
.y
))
2689 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2691 return pwndHit
? pwndHit
: Parent
;
2696 IntDeferWindowPos( HDWP hdwp
,
2707 HDWP retvalue
= hdwp
;
2709 TRACE("hdwp %p, hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
2710 hdwp
, hwnd
, hwndAfter
, x
, y
, cx
, cy
, flags
);
2712 if (flags
& ~(SWP_NOSIZE
| SWP_NOMOVE
|
2713 SWP_NOZORDER
| SWP_NOREDRAW
|
2714 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
2715 SWP_NOOWNERZORDER
|SWP_SHOWWINDOW
|
2716 SWP_HIDEWINDOW
| SWP_FRAMECHANGED
))
2718 EngSetLastError(ERROR_INVALID_PARAMETER
);
2722 if (!(pDWP
= (PSMWP
)UserGetObject(gHandleTable
, hdwp
, TYPE_SETWINDOWPOS
)))
2724 EngSetLastError(ERROR_INVALID_DWP_HANDLE
);
2728 for (i
= 0; i
< pDWP
->ccvr
; i
++)
2730 if (pDWP
->acvr
[i
].pos
.hwnd
== hwnd
)
2732 /* Merge with the other changes */
2733 if (!(flags
& SWP_NOZORDER
))
2735 pDWP
->acvr
[i
].pos
.hwndInsertAfter
= hwndAfter
;
2737 if (!(flags
& SWP_NOMOVE
))
2739 pDWP
->acvr
[i
].pos
.x
= x
;
2740 pDWP
->acvr
[i
].pos
.y
= y
;
2742 if (!(flags
& SWP_NOSIZE
))
2744 pDWP
->acvr
[i
].pos
.cx
= cx
;
2745 pDWP
->acvr
[i
].pos
.cy
= cy
;
2747 pDWP
->acvr
[i
].pos
.flags
&= flags
| ~(SWP_NOSIZE
| SWP_NOMOVE
|
2748 SWP_NOZORDER
| SWP_NOREDRAW
|
2749 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
2751 pDWP
->acvr
[i
].pos
.flags
|= flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
|
2756 if (pDWP
->ccvr
>= pDWP
->ccvrAlloc
)
2758 PCVR newpos
= ExAllocatePoolWithTag(PagedPool
, pDWP
->ccvrAlloc
* 2 * sizeof(CVR
), USERTAG_SWP
);
2764 RtlZeroMemory(newpos
, pDWP
->ccvrAlloc
* 2 * sizeof(CVR
));
2765 RtlCopyMemory(newpos
, pDWP
->acvr
, pDWP
->ccvrAlloc
* sizeof(CVR
));
2766 ExFreePoolWithTag(pDWP
->acvr
, USERTAG_SWP
);
2767 pDWP
->ccvrAlloc
*= 2;
2768 pDWP
->acvr
= newpos
;
2770 pDWP
->acvr
[pDWP
->ccvr
].pos
.hwnd
= hwnd
;
2771 pDWP
->acvr
[pDWP
->ccvr
].pos
.hwndInsertAfter
= hwndAfter
;
2772 pDWP
->acvr
[pDWP
->ccvr
].pos
.x
= x
;
2773 pDWP
->acvr
[pDWP
->ccvr
].pos
.y
= y
;
2774 pDWP
->acvr
[pDWP
->ccvr
].pos
.cx
= cx
;
2775 pDWP
->acvr
[pDWP
->ccvr
].pos
.cy
= cy
;
2776 pDWP
->acvr
[pDWP
->ccvr
].pos
.flags
= flags
;
2777 pDWP
->acvr
[pDWP
->ccvr
].hrgnClip
= NULL
;
2778 pDWP
->acvr
[pDWP
->ccvr
].hrgnInterMonitor
= NULL
;
2784 BOOL FASTCALL
IntEndDeferWindowPosEx( HDWP hdwp
, BOOL sAsync
)
2791 TRACE("%p\n", hdwp
);
2793 if (!(pDWP
= (PSMWP
)UserGetObject(gHandleTable
, hdwp
, TYPE_SETWINDOWPOS
)))
2795 EngSetLastError(ERROR_INVALID_DWP_HANDLE
);
2799 for (i
= 0, winpos
= pDWP
->acvr
; res
&& i
< pDWP
->ccvr
; i
++, winpos
++)
2802 USER_REFERENCE_ENTRY Ref
;
2804 TRACE("hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
2805 winpos
->pos
.hwnd
, winpos
->pos
.hwndInsertAfter
, winpos
->pos
.x
, winpos
->pos
.y
,
2806 winpos
->pos
.cx
, winpos
->pos
.cy
, winpos
->pos
.flags
);
2808 pwnd
= ValidateHwndNoErr(winpos
->pos
.hwnd
);
2812 UserRefObjectCo(pwnd
, &Ref
);
2817 PWINDOWPOS ppos
= ExAllocatePoolWithTag(PagedPool
, sizeof(WINDOWPOS
), USERTAG_SWP
);
2820 *ppos
= winpos
->pos
;
2821 /* Yes it's a pointer inside Win32k! */
2822 lRes
= co_IntSendMessageNoWait( winpos
->pos
.hwnd
, WM_ASYNC_SETWINDOWPOS
, 0, (LPARAM
)ppos
);
2823 /* We handle this the same way as Event Hooks and Hooks. */
2826 ExFreePoolWithTag(ppos
, USERTAG_SWP
);
2831 res
= co_WinPosSetWindowPos( pwnd
,
2832 winpos
->pos
.hwndInsertAfter
,
2839 // Hack to pass tests.... Must have some work to do so clear the error.
2840 if (res
&& (winpos
->pos
.flags
& (SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOZORDER
)) == SWP_NOZORDER
)
2841 EngSetLastError(ERROR_SUCCESS
);
2843 UserDerefObjectCo(pwnd
);
2845 ExFreePoolWithTag(pDWP
->acvr
, USERTAG_SWP
);
2846 UserDereferenceObject(pDWP
);
2847 UserDeleteObject(hdwp
, TYPE_SETWINDOWPOS
);
2855 NtUserChildWindowFromPointEx(HWND hwndParent
,
2861 TRACE("Enter NtUserChildWindowFromPointEx\n");
2862 UserEnterExclusive();
2863 if ((pwndParent
= UserGetWindowObject(hwndParent
)))
2865 pwndParent
= IntChildWindowFromPointEx(pwndParent
, x
, y
, uiFlags
);
2868 TRACE("Leave NtUserChildWindowFromPointEx\n");
2869 return pwndParent
? UserHMGetHandle(pwndParent
) : NULL
;
2876 NtUserEndDeferWindowPosEx(HDWP WinPosInfo
,
2880 TRACE("Enter NtUserEndDeferWindowPosEx\n");
2881 UserEnterExclusive();
2882 Ret
= IntEndDeferWindowPosEx(WinPosInfo
, (BOOL
)Unknown1
);
2883 TRACE("Leave NtUserEndDeferWindowPosEx, ret=%i\n", Ret
);
2892 NtUserDeferWindowPos(HDWP WinPosInfo
,
2894 HWND WndInsertAfter
,
2903 UINT Tmp
= ~(SWP_ASYNCWINDOWPOS
|SWP_DEFERERASE
|SWP_NOSENDCHANGING
|SWP_NOREPOSITION
|
2904 SWP_NOCOPYBITS
|SWP_HIDEWINDOW
|SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|
2905 SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_NOZORDER
|SWP_NOMOVE
|SWP_NOSIZE
);
2907 TRACE("Enter NtUserDeferWindowPos\n");
2908 UserEnterExclusive();
2912 EngSetLastError(ERROR_INVALID_FLAGS
);
2916 pWnd
= UserGetWindowObject(Wnd
);
2917 if ( !pWnd
|| // FIXME:
2918 pWnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
2919 pWnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
2924 if ( WndInsertAfter
&&
2925 WndInsertAfter
!= HWND_BOTTOM
&&
2926 WndInsertAfter
!= HWND_TOPMOST
&&
2927 WndInsertAfter
!= HWND_NOTOPMOST
)
2929 pWndIA
= UserGetWindowObject(WndInsertAfter
);
2931 pWndIA
== UserGetDesktopWindow() ||
2932 pWndIA
== UserGetMessageWindow() )
2938 Ret
= IntDeferWindowPos(WinPosInfo
, Wnd
, WndInsertAfter
, x
, y
, cx
, cy
, Flags
);
2941 TRACE("Leave NtUserDeferWindowPos, ret=%p\n", Ret
);
2950 NtUserGetInternalWindowPos( HWND hWnd
,
2957 WINDOWPLACEMENT wndpl
;
2961 if (!(Window
= UserGetWindowObject(hWnd
)))
2971 ProbeForWrite(rectWnd
,
2977 ProbeForWrite(ptIcon
,
2983 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2985 SetLastNtError(_SEH2_GetExceptionCode());
2990 wndpl
.length
= sizeof(WINDOWPLACEMENT
);
2992 if (IntGetWindowPlacement(Window
, &wndpl
) && !Hit
)
2998 RtlCopyMemory(rectWnd
, &wndpl
.rcNormalPosition
, sizeof(RECT
));
3002 RtlCopyMemory(ptIcon
, &wndpl
.ptMinPosition
, sizeof(POINT
));
3006 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3008 SetLastNtError(_SEH2_GetExceptionCode());
3013 if (!Hit
) Ret
= wndpl
.showCmd
;
3024 NtUserGetWindowPlacement(HWND hWnd
,
3025 WINDOWPLACEMENT
*lpwndpl
)
3028 WINDOWPLACEMENT Safepl
;
3030 DECLARE_RETURN(BOOL
);
3032 TRACE("Enter NtUserGetWindowPlacement\n");
3035 if (!(Wnd
= UserGetWindowObject(hWnd
)))
3040 Status
= MmCopyFromCaller(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
3041 if (!NT_SUCCESS(Status
))
3043 SetLastNtError(Status
);
3047 Safepl
.length
= sizeof(WINDOWPLACEMENT
);
3049 IntGetWindowPlacement(Wnd
, &Safepl
);
3051 Status
= MmCopyToCaller(lpwndpl
, &Safepl
, sizeof(WINDOWPLACEMENT
));
3052 if (!NT_SUCCESS(Status
))
3054 SetLastNtError(Status
);
3061 TRACE("Leave NtUserGetWindowPlacement, ret=%i\n",_ret_
);
3070 UINT cmd
, // Wine SW_ commands
3075 TRACE("Enter NtUserMinMaximize\n");
3076 UserEnterExclusive();
3078 pWnd
= UserGetWindowObject(hWnd
);
3079 if ( !pWnd
|| // FIXME:
3080 pWnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3081 pWnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3086 if ( cmd
> SW_MAX
|| pWnd
->state2
& WNDS2_INDESTROY
)
3088 EngSetLastError(ERROR_INVALID_PARAMETER
);
3092 cmd
|= Hide
? SW_HIDE
: 0;
3094 co_WinPosShowWindow(pWnd
, cmd
);
3097 TRACE("Leave NtUserMinMaximize\n");
3099 return 0; // Always NULL?
3114 return NtUserSetWindowPos(hWnd
, 0, X
, Y
, nWidth
, nHeight
,
3115 (bRepaint
? SWP_NOZORDER
| SWP_NOACTIVATE
:
3116 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
));
3123 NtUserRealChildWindowFromPoint(HWND Parent
,
3128 TRACE("Enter NtUserRealChildWindowFromPoint\n");
3130 if ((pwndParent
= UserGetWindowObject(Parent
)))
3132 pwndParent
= IntRealChildWindowFromPoint(pwndParent
, x
, y
);
3135 TRACE("Leave NtUserRealChildWindowFromPoint\n");
3136 return pwndParent
? UserHMGetHandle(pwndParent
) : NULL
;
3145 HWND hWndInsertAfter
,
3152 DECLARE_RETURN(BOOL
);
3153 PWND Window
, pWndIA
;
3155 USER_REFERENCE_ENTRY Ref
;
3157 TRACE("Enter NtUserSetWindowPos\n");
3158 UserEnterExclusive();
3160 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
3161 Window
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3162 Window
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3164 ERR("NtUserSetWindowPos bad window handle!\n");
3168 if ( hWndInsertAfter
&&
3169 hWndInsertAfter
!= HWND_BOTTOM
&&
3170 hWndInsertAfter
!= HWND_TOPMOST
&&
3171 hWndInsertAfter
!= HWND_NOTOPMOST
)
3173 if (!(pWndIA
= UserGetWindowObject(hWndInsertAfter
)) ||
3174 pWndIA
== UserGetDesktopWindow() ||
3175 pWndIA
== UserGetMessageWindow() )
3177 ERR("NtUserSetWindowPos bad insert window handle!\n");
3182 /* First make sure that coordinates are valid for WM_WINDOWPOSCHANGING */
3183 if (!(uFlags
& SWP_NOMOVE
))
3185 if (X
< -32768) X
= -32768;
3186 else if (X
> 32767) X
= 32767;
3187 if (Y
< -32768) Y
= -32768;
3188 else if (Y
> 32767) Y
= 32767;
3190 if (!(uFlags
& SWP_NOSIZE
))
3193 else if (cx
> 32767) cx
= 32767;
3195 else if (cy
> 32767) cy
= 32767;
3198 UserRefObjectCo(Window
, &Ref
);
3199 ret
= co_WinPosSetWindowPos(Window
, hWndInsertAfter
, X
, Y
, cx
, cy
, uFlags
);
3200 UserDerefObjectCo(Window
);
3205 TRACE("Leave NtUserSetWindowPos, ret=%i\n",_ret_
);
3219 HRGN hrgnCopy
= NULL
;
3221 INT flags
= (SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
);
3222 BOOLEAN Ret
= FALSE
;
3223 DECLARE_RETURN(INT
);
3225 TRACE("Enter NtUserSetWindowRgn\n");
3226 UserEnterExclusive();
3228 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
3229 Window
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3230 Window
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3235 if (hRgn
) // The region will be deleted in user32.
3237 if (GreIsHandleValid(hRgn
))
3239 hrgnCopy
= NtGdiCreateRectRgn(0, 0, 0, 0);
3240 /* The coordinates of a window's window region are relative to the
3241 upper-left corner of the window, not the client area of the window. */
3242 NtGdiCombineRgn( hrgnCopy
, hRgn
, 0, RGN_COPY
);
3248 if (Window
->hrgnClip
)
3250 /* Delete no longer needed region handle */
3251 IntGdiSetRegionOwner(Window
->hrgnClip
, GDI_OBJ_HMGR_POWNED
);
3252 GreDeleteObject(Window
->hrgnClip
);
3257 /* Set public ownership */
3258 IntGdiSetRegionOwner(hrgnCopy
, GDI_OBJ_HMGR_PUBLIC
);
3260 Window
->hrgnClip
= hrgnCopy
;
3262 Ret
= co_WinPosSetWindowPos(Window
, HWND_TOP
, 0, 0, 0, 0, bRedraw
? flags
: (flags
|SWP_NOREDRAW
) );
3267 TRACE("Leave NtUserSetWindowRgn, ret=%i\n",_ret_
);
3276 NtUserSetInternalWindowPos(
3282 WINDOWPLACEMENT wndpl
;
3287 DECLARE_RETURN(BOOL
);
3288 USER_REFERENCE_ENTRY Ref
;
3290 TRACE("Enter NtUserSetWindowPlacement\n");
3291 UserEnterExclusive();
3293 if (!(Wnd
= UserGetWindowObject(hwnd
)) || // FIXME:
3294 Wnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3295 Wnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3304 ProbeForRead(lppt
, sizeof(POINT
), 1);
3305 RtlCopyMemory(&pt
, lppt
, sizeof(POINT
));
3309 ProbeForRead(lprect
, sizeof(RECT
), 1);
3310 RtlCopyMemory(&rect
, lprect
, sizeof(RECT
));
3313 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3315 SetLastNtError(_SEH2_GetExceptionCode());
3316 _SEH2_YIELD(RETURN( FALSE
));
3320 wndpl
.length
= sizeof(wndpl
);
3321 wndpl
.showCmd
= showCmd
;
3322 wndpl
.flags
= flags
= 0;
3327 wndpl
.flags
|= WPF_SETMINPOSITION
;
3328 wndpl
.ptMinPosition
= pt
;
3332 flags
|= PLACE_RECT
;
3333 wndpl
.rcNormalPosition
= rect
;
3336 UserRefObjectCo(Wnd
, &Ref
);
3337 IntSetWindowPlacement(Wnd
, &wndpl
, flags
);
3338 UserDerefObjectCo(Wnd
);
3342 TRACE("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_
);
3351 NtUserSetWindowPlacement(HWND hWnd
,
3352 WINDOWPLACEMENT
*lpwndpl
)
3355 WINDOWPLACEMENT Safepl
;
3357 DECLARE_RETURN(BOOL
);
3358 USER_REFERENCE_ENTRY Ref
;
3360 TRACE("Enter NtUserSetWindowPlacement\n");
3361 UserEnterExclusive();
3363 if (!(Wnd
= UserGetWindowObject(hWnd
)) || // FIXME:
3364 Wnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3365 Wnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3372 ProbeForRead(lpwndpl
, sizeof(WINDOWPLACEMENT
), 1);
3373 RtlCopyMemory(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
3375 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3377 SetLastNtError(_SEH2_GetExceptionCode());
3378 _SEH2_YIELD(RETURN( FALSE
));
3382 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
3387 Flags
= PLACE_MAX
| PLACE_RECT
;
3388 if (Safepl
.flags
& WPF_SETMINPOSITION
) Flags
|= PLACE_MIN
;
3389 UserRefObjectCo(Wnd
, &Ref
);
3390 IntSetWindowPlacement(Wnd
, &Safepl
, Flags
);
3391 UserDerefObjectCo(Wnd
);
3395 TRACE("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_
);
3404 NtUserShowWindowAsync(HWND hWnd
, LONG nCmdShow
)
3408 DECLARE_RETURN(BOOL
);
3409 USER_REFERENCE_ENTRY Ref
;
3411 TRACE("Enter NtUserShowWindowAsync\n");
3412 UserEnterExclusive();
3414 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
3415 Window
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3416 Window
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3421 if ( nCmdShow
> SW_MAX
)
3423 EngSetLastError(ERROR_INVALID_PARAMETER
);
3427 UserRefObjectCo(Window
, &Ref
);
3428 ret
= co_IntSendMessageNoWait( hWnd
, WM_ASYNC_SHOWWINDOW
, nCmdShow
, 0 );
3429 UserDerefObjectCo(Window
);
3430 if (-1 == (int) ret
|| !ret
) ret
= FALSE
;
3435 TRACE("Leave NtUserShowWindowAsync, ret=%i\n",_ret_
);
3444 NtUserShowWindow(HWND hWnd
, LONG nCmdShow
)
3448 DECLARE_RETURN(BOOL
);
3449 USER_REFERENCE_ENTRY Ref
;
3451 TRACE("Enter NtUserShowWindow hWnd %p SW_ %d\n",hWnd
, nCmdShow
);
3452 UserEnterExclusive();
3454 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
3455 Window
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3456 Window
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3461 if ( nCmdShow
> SW_MAX
|| Window
->state2
& WNDS2_INDESTROY
)
3463 EngSetLastError(ERROR_INVALID_PARAMETER
);
3467 UserRefObjectCo(Window
, &Ref
);
3468 ret
= co_WinPosShowWindow(Window
, nCmdShow
);
3469 UserDerefObjectCo(Window
);
3474 TRACE("Leave NtUserShowWindow, ret=%i\n",_ret_
);
3484 NtUserWindowFromPoint(LONG X
, LONG Y
)
3488 PWND DesktopWindow
= NULL
, Window
= NULL
;
3490 DECLARE_RETURN(HWND
);
3491 USER_REFERENCE_ENTRY Ref
;
3493 TRACE("Enter NtUserWindowFromPoint\n");
3494 UserEnterExclusive();
3496 if ((DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow())))
3503 // Hmm... Threads live on desktops thus we have a reference on the desktop and indirectly the desktop window.
3504 // It is possible this referencing is useless, though it should not hurt...
3505 UserRefObjectCo(DesktopWindow
, &Ref
);
3507 //pti = PsGetCurrentThreadWin32Thread();
3508 Window
= co_WinPosWindowFromPoint(DesktopWindow
, &pt
, &hittest
, FALSE
);
3512 Ret
= UserHMGetHandle(Window
);
3521 if (DesktopWindow
) UserDerefObjectCo(DesktopWindow
);
3523 TRACE("Leave NtUserWindowFromPoint, ret=%p\n", _ret_
);