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
!= 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
);
3046 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
3051 IntGetWindowPlacement(Wnd
, &Safepl
);
3053 Status
= MmCopyToCaller(lpwndpl
, &Safepl
, sizeof(WINDOWPLACEMENT
));
3054 if(!NT_SUCCESS(Status
))
3056 SetLastNtError(Status
);
3063 TRACE("Leave NtUserGetWindowPlacement, ret=%i\n",_ret_
);
3072 UINT cmd
, // Wine SW_ commands
3077 TRACE("Enter NtUserMinMaximize\n");
3078 UserEnterExclusive();
3080 pWnd
= UserGetWindowObject(hWnd
);
3081 if ( !pWnd
|| // FIXME:
3082 pWnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3083 pWnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3088 if ( cmd
> SW_MAX
|| pWnd
->state2
& WNDS2_INDESTROY
)
3090 EngSetLastError(ERROR_INVALID_PARAMETER
);
3094 cmd
|= Hide
? SW_HIDE
: 0;
3096 co_WinPosShowWindow(pWnd
, cmd
);
3099 TRACE("Leave NtUserMinMaximize\n");
3101 return 0; // Always NULL?
3116 return NtUserSetWindowPos(hWnd
, 0, X
, Y
, nWidth
, nHeight
,
3117 (bRepaint
? SWP_NOZORDER
| SWP_NOACTIVATE
:
3118 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
));
3125 NtUserRealChildWindowFromPoint(HWND Parent
,
3130 TRACE("Enter NtUserRealChildWindowFromPoint\n");
3132 if ((pwndParent
= UserGetWindowObject(Parent
)))
3134 pwndParent
= IntRealChildWindowFromPoint(pwndParent
, x
, y
);
3137 TRACE("Leave NtUserRealChildWindowFromPoint\n");
3138 return pwndParent
? UserHMGetHandle(pwndParent
) : NULL
;
3147 HWND hWndInsertAfter
,
3154 DECLARE_RETURN(BOOL
);
3155 PWND Window
, pWndIA
;
3157 USER_REFERENCE_ENTRY Ref
;
3159 TRACE("Enter NtUserSetWindowPos\n");
3160 UserEnterExclusive();
3162 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
3163 Window
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3164 Window
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3166 ERR("NtUserSetWindowPos bad window handle!\n");
3170 if ( hWndInsertAfter
&&
3171 hWndInsertAfter
!= HWND_BOTTOM
&&
3172 hWndInsertAfter
!= HWND_TOPMOST
&&
3173 hWndInsertAfter
!= HWND_NOTOPMOST
)
3175 if (!(pWndIA
= UserGetWindowObject(hWndInsertAfter
)) ||
3176 pWndIA
== UserGetDesktopWindow() ||
3177 pWndIA
== UserGetMessageWindow() )
3179 ERR("NtUserSetWindowPos bad insert window handle!\n");
3184 /* First make sure that coordinates are valid for WM_WINDOWPOSCHANGING */
3185 if (!(uFlags
& SWP_NOMOVE
))
3187 if (X
< -32768) X
= -32768;
3188 else if (X
> 32767) X
= 32767;
3189 if (Y
< -32768) Y
= -32768;
3190 else if (Y
> 32767) Y
= 32767;
3192 if (!(uFlags
& SWP_NOSIZE
))
3195 else if (cx
> 32767) cx
= 32767;
3197 else if (cy
> 32767) cy
= 32767;
3200 UserRefObjectCo(Window
, &Ref
);
3201 ret
= co_WinPosSetWindowPos(Window
, hWndInsertAfter
, X
, Y
, cx
, cy
, uFlags
);
3202 UserDerefObjectCo(Window
);
3207 TRACE("Leave NtUserSetWindowPos, ret=%i\n",_ret_
);
3221 HRGN hrgnCopy
= NULL
;
3223 INT flags
= (SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
);
3224 BOOLEAN Ret
= FALSE
;
3225 DECLARE_RETURN(INT
);
3227 TRACE("Enter NtUserSetWindowRgn\n");
3228 UserEnterExclusive();
3230 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
3231 Window
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3232 Window
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3237 if (hRgn
) // The region will be deleted in user32.
3239 if (GreIsHandleValid(hRgn
))
3241 hrgnCopy
= NtGdiCreateRectRgn(0, 0, 0, 0);
3242 /* The coordinates of a window's window region are relative to the
3243 upper-left corner of the window, not the client area of the window. */
3244 NtGdiCombineRgn( hrgnCopy
, hRgn
, 0, RGN_COPY
);
3250 if (Window
->hrgnClip
)
3252 /* Delete no longer needed region handle */
3253 IntGdiSetRegionOwner(Window
->hrgnClip
, GDI_OBJ_HMGR_POWNED
);
3254 GreDeleteObject(Window
->hrgnClip
);
3259 /* Set public ownership */
3260 IntGdiSetRegionOwner(hrgnCopy
, GDI_OBJ_HMGR_PUBLIC
);
3262 Window
->hrgnClip
= hrgnCopy
;
3264 Ret
= co_WinPosSetWindowPos(Window
, HWND_TOP
, 0, 0, 0, 0, bRedraw
? flags
: (flags
|SWP_NOREDRAW
) );
3269 TRACE("Leave NtUserSetWindowRgn, ret=%i\n",_ret_
);
3278 NtUserSetInternalWindowPos(
3284 WINDOWPLACEMENT wndpl
;
3289 DECLARE_RETURN(BOOL
);
3290 USER_REFERENCE_ENTRY Ref
;
3292 TRACE("Enter NtUserSetWindowPlacement\n");
3293 UserEnterExclusive();
3295 if (!(Wnd
= UserGetWindowObject(hwnd
)) || // FIXME:
3296 Wnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3297 Wnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3306 ProbeForRead(lppt
, sizeof(POINT
), 1);
3307 RtlCopyMemory(&pt
, lppt
, sizeof(POINT
));
3311 ProbeForRead(lprect
, sizeof(RECT
), 1);
3312 RtlCopyMemory(&rect
, lprect
, sizeof(RECT
));
3315 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3317 SetLastNtError(_SEH2_GetExceptionCode());
3318 _SEH2_YIELD(RETURN( FALSE
));
3322 wndpl
.length
= sizeof(wndpl
);
3323 wndpl
.showCmd
= showCmd
;
3324 wndpl
.flags
= flags
= 0;
3329 wndpl
.flags
|= WPF_SETMINPOSITION
;
3330 wndpl
.ptMinPosition
= pt
;
3334 flags
|= PLACE_RECT
;
3335 wndpl
.rcNormalPosition
= rect
;
3338 UserRefObjectCo(Wnd
, &Ref
);
3339 IntSetWindowPlacement(Wnd
, &wndpl
, flags
);
3340 UserDerefObjectCo(Wnd
);
3344 TRACE("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_
);
3353 NtUserSetWindowPlacement(HWND hWnd
,
3354 WINDOWPLACEMENT
*lpwndpl
)
3357 WINDOWPLACEMENT Safepl
;
3359 DECLARE_RETURN(BOOL
);
3360 USER_REFERENCE_ENTRY Ref
;
3362 TRACE("Enter NtUserSetWindowPlacement\n");
3363 UserEnterExclusive();
3365 if (!(Wnd
= UserGetWindowObject(hWnd
)) || // FIXME:
3366 Wnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3367 Wnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3374 ProbeForRead(lpwndpl
, sizeof(WINDOWPLACEMENT
), 1);
3375 RtlCopyMemory(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
3377 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3379 SetLastNtError(_SEH2_GetExceptionCode());
3380 _SEH2_YIELD(RETURN( FALSE
));
3384 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
3389 Flags
= PLACE_MAX
| PLACE_RECT
;
3390 if (Safepl
.flags
& WPF_SETMINPOSITION
) Flags
|= PLACE_MIN
;
3391 UserRefObjectCo(Wnd
, &Ref
);
3392 IntSetWindowPlacement(Wnd
, &Safepl
, Flags
);
3393 UserDerefObjectCo(Wnd
);
3397 TRACE("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_
);
3406 NtUserShowWindowAsync(HWND hWnd
, LONG nCmdShow
)
3410 DECLARE_RETURN(BOOL
);
3411 USER_REFERENCE_ENTRY Ref
;
3413 TRACE("Enter NtUserShowWindowAsync\n");
3414 UserEnterExclusive();
3416 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
3417 Window
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3418 Window
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3423 if ( nCmdShow
> SW_MAX
)
3425 EngSetLastError(ERROR_INVALID_PARAMETER
);
3429 UserRefObjectCo(Window
, &Ref
);
3430 ret
= co_IntSendMessageNoWait( hWnd
, WM_ASYNC_SHOWWINDOW
, nCmdShow
, 0 );
3431 UserDerefObjectCo(Window
);
3432 if (-1 == (int) ret
|| !ret
) ret
= FALSE
;
3437 TRACE("Leave NtUserShowWindowAsync, ret=%i\n",_ret_
);
3446 NtUserShowWindow(HWND hWnd
, LONG nCmdShow
)
3450 DECLARE_RETURN(BOOL
);
3451 USER_REFERENCE_ENTRY Ref
;
3453 TRACE("Enter NtUserShowWindow hWnd %p SW_ %d\n",hWnd
, nCmdShow
);
3454 UserEnterExclusive();
3456 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
3457 Window
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3458 Window
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3463 if ( nCmdShow
> SW_MAX
|| Window
->state2
& WNDS2_INDESTROY
)
3465 EngSetLastError(ERROR_INVALID_PARAMETER
);
3469 UserRefObjectCo(Window
, &Ref
);
3470 ret
= co_WinPosShowWindow(Window
, nCmdShow
);
3471 UserDerefObjectCo(Window
);
3476 TRACE("Leave NtUserShowWindow, ret=%i\n",_ret_
);
3486 NtUserWindowFromPoint(LONG X
, LONG Y
)
3490 PWND DesktopWindow
= NULL
, Window
= NULL
;
3492 DECLARE_RETURN(HWND
);
3493 USER_REFERENCE_ENTRY Ref
;
3495 TRACE("Enter NtUserWindowFromPoint\n");
3496 UserEnterExclusive();
3498 if ((DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow())))
3505 // Hmm... Threads live on desktops thus we have a reference on the desktop and indirectly the desktop window.
3506 // It is possible this referencing is useless, though it should not hurt...
3507 UserRefObjectCo(DesktopWindow
, &Ref
);
3509 //pti = PsGetCurrentThreadWin32Thread();
3510 Window
= co_WinPosWindowFromPoint(DesktopWindow
, &pt
, &hittest
, FALSE
);
3514 Ret
= UserHMGetHandle(Window
);
3523 if (DesktopWindow
) UserDerefObjectCo(DesktopWindow
);
3525 TRACE("Leave NtUserWindowFromPoint, ret=%p\n", _ret_
);