2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
5 * FILE: win32ss/user/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 IntGetWindowRect(PWND Wnd
, RECTL
*Rect
)
90 if (!Wnd
) return FALSE
;
91 if ( Wnd
!= UserGetDesktopWindow()) // Wnd->fnid != FNID_DESKTOP )
93 *Rect
= Wnd
->rcWindow
;
97 Rect
->left
= Rect
->top
= 0;
98 Rect
->right
= Wnd
->rcWindow
.right
;
99 Rect
->bottom
= Wnd
->rcWindow
.bottom
;
100 /* Do this until Init bug is fixed. This sets 640x480, see InitMetrics.
101 Rect->right = GetSystemMetrics(SM_CXSCREEN);
102 Rect->bottom = GetSystemMetrics(SM_CYSCREEN);
109 IntMapWindowPoints(PWND FromWnd
, PWND ToWnd
, LPPOINT lpPoints
, UINT cPoints
)
111 BOOL mirror_from
, mirror_to
;
116 /* Note: Desktop Top and Left is always 0! */
117 Delta
.x
= Delta
.y
= 0;
118 mirror_from
= mirror_to
= FALSE
;
120 if (FromWnd
&& FromWnd
!= UserGetDesktopWindow()) // FromWnd->fnid != FNID_DESKTOP)
122 if (FromWnd
->ExStyle
& WS_EX_LAYOUTRTL
)
126 Delta
.x
= -FromWnd
->rcClient
.right
;
129 Delta
.x
= FromWnd
->rcClient
.left
;
130 Delta
.y
= FromWnd
->rcClient
.top
;
133 if (ToWnd
&& ToWnd
!= UserGetDesktopWindow()) // ToWnd->fnid != FNID_DESKTOP)
135 if (ToWnd
->ExStyle
& WS_EX_LAYOUTRTL
)
139 Delta
.x
+= Change
* ToWnd
->rcClient
.right
;
142 Delta
.x
-= Change
* ToWnd
->rcClient
.left
;
143 Delta
.y
-= ToWnd
->rcClient
.top
;
146 for (i
= 0; i
!= cPoints
; i
++)
148 lpPoints
[i
].x
+= Delta
.x
;
149 lpPoints
[i
].x
*= Change
;
150 lpPoints
[i
].y
+= Delta
.y
;
153 if ((mirror_from
|| mirror_to
) && cPoints
== 2) /* special case for rectangle */
155 int tmp
= min(lpPoints
[0].x
, lpPoints
[1].x
);
156 lpPoints
[1].x
= max(lpPoints
[0].x
, lpPoints
[1].x
);
160 return MAKELONG(LOWORD(Delta
.x
), LOWORD(Delta
.y
));
164 IntClientToScreen(PWND Wnd
, LPPOINT lpPoint
)
166 if (Wnd
&& Wnd
->fnid
!= FNID_DESKTOP
)
168 if (Wnd
->ExStyle
& WS_EX_LAYOUTRTL
)
169 lpPoint
->x
= Wnd
->rcClient
.right
- lpPoint
->x
;
171 lpPoint
->x
+= Wnd
->rcClient
.left
;
172 lpPoint
->y
+= Wnd
->rcClient
.top
;
178 IntScreenToClient(PWND Wnd
, LPPOINT lpPoint
)
180 if (Wnd
&& Wnd
->fnid
!= FNID_DESKTOP
)
182 if (Wnd
->ExStyle
& WS_EX_LAYOUTRTL
)
183 lpPoint
->x
= Wnd
->rcClient
.right
- lpPoint
->x
;
185 lpPoint
->x
-= Wnd
->rcClient
.left
;
186 lpPoint
->y
-= Wnd
->rcClient
.top
;
191 BOOL FASTCALL
IsChildVisible(PWND pWnd
)
195 if ( (pWnd
->style
& (WS_POPUP
|WS_CHILD
)) != WS_CHILD
||
196 !(pWnd
= pWnd
->spwndParent
) )
199 while (pWnd
->style
& WS_VISIBLE
);
203 PWND FASTCALL
IntGetLastTopMostWindow(VOID
)
206 PDESKTOP rpdesk
= gptiCurrent
->rpdesk
;
209 (pWnd
= rpdesk
->pDeskInfo
->spwnd
->spwndChild
) &&
210 pWnd
->ExStyle
& WS_EX_TOPMOST
)
214 if (!pWnd
->spwndNext
) break;
215 if (!(pWnd
->spwndNext
->ExStyle
& WS_EX_TOPMOST
)) break;
216 pWnd
= pWnd
->spwndNext
;
224 // This helps with CORE-6129 forcing modal dialog active when another app is minimized or closed.
226 BOOL FASTCALL
ActivateOtherWindowMin(PWND Wnd
)
228 BOOL ActivePrev
, FindTopWnd
;
229 PWND pWndTopMost
, pWndChild
, pWndSetActive
, pWndTemp
, pWndDesk
;
230 USER_REFERENCE_ENTRY Ref
;
231 PTHREADINFO pti
= gptiCurrent
;
233 //ERR("AOWM 1 %p\n",Wnd->head.h);
234 ActivePrev
= (pti
->MessageQueue
->spwndActivePrev
!= NULL
);
237 if ((pWndTopMost
= IntGetLastTopMostWindow()))
238 pWndChild
= pWndTopMost
->spwndNext
;
240 pWndChild
= Wnd
->spwndParent
->spwndChild
;
245 pWndSetActive
= pti
->MessageQueue
->spwndActivePrev
;
247 pWndSetActive
= pWndChild
;
253 if ( VerifyWnd(pWndSetActive
) &&
254 !(pWndSetActive
->ExStyle
& WS_EX_NOACTIVATE
) &&
255 (pWndSetActive
->style
& (WS_VISIBLE
|WS_DISABLED
)) == WS_VISIBLE
&&
256 (!(pWndSetActive
->style
& WS_ICONIC
) /* FIXME MinMax pos? */ ) )
258 if (!(pWndSetActive
->ExStyle
& WS_EX_TOOLWINDOW
) )
260 UserRefObjectCo(pWndSetActive
, &Ref
);
261 //ERR("ActivateOtherWindowMin Set FG 1\n");
262 co_IntSetForegroundWindow(pWndSetActive
);
263 UserDerefObjectCo(pWndSetActive
);
264 //ERR("AOWM 2 Exit Good %p\n",pWndSetActive->head.h);
267 if (!pWndTemp
) pWndTemp
= pWndSetActive
;
272 pWndSetActive
= pWndChild
;
275 pWndSetActive
= pWndSetActive
->spwndNext
;
278 if ( !FindTopWnd
) break;
283 pWndChild
= pWndChild
->spwndParent
->spwndChild
;
287 if (!(pWndDesk
= IntGetThreadDesktopWindow(pti
)))
292 pWndChild
= pWndDesk
->spwndChild
;
295 if ((pWndSetActive
= pWndTemp
))
297 UserRefObjectCo(pWndSetActive
, &Ref
);
298 //ERR("ActivateOtherWindowMin Set FG 2\n");
299 co_IntSetForegroundWindow(pWndSetActive
);
300 UserDerefObjectCo(pWndSetActive
);
301 //ERR("AOWM 3 Exit Good %p\n",pWndSetActive->head.h);
304 //ERR("AOWM 4 Bad\n");
308 /*******************************************************************
309 * can_activate_window
311 * Check if we can activate the specified window.
314 BOOL FASTCALL
can_activate_window( PWND Wnd OPTIONAL
)
318 if (!Wnd
) return FALSE
;
321 if (!(style
& WS_VISIBLE
)) return FALSE
;
322 if (style
& WS_MINIMIZE
) return FALSE
;
323 if ((style
& (WS_POPUP
|WS_CHILD
)) == WS_CHILD
) return FALSE
;
325 /* FIXME: This window could be disable because the child that closed
327 //return !(style & WS_DISABLED);
331 /*******************************************************************
332 * WinPosActivateOtherWindow
334 * Activates window other than pWnd.
337 co_WinPosActivateOtherWindow(PWND Wnd
)
340 USER_REFERENCE_ENTRY Ref
;
344 if (IntIsDesktopWindow(Wnd
))
346 IntSetFocusMessageQueue(NULL
);
350 /* If this is popup window, try to activate the owner first. */
351 if ((Wnd
->style
& WS_POPUP
) && (WndTo
= Wnd
->spwndOwner
))
353 TRACE("WPAOW Popup with Owner\n");
354 WndTo
= UserGetAncestor( WndTo
, GA_ROOT
);
355 if (can_activate_window(WndTo
)) goto done
;
358 /* Pick a next top-level window. */
359 /* FIXME: Search for non-tooltip windows first. */
363 if (!(WndTo
= WndTo
->spwndNext
)) break;
364 if (can_activate_window( WndTo
)) goto done
;
368 Fixes wine win.c:test_SetParent last ShowWindow test after popup dies.
369 Check for previous active window to bring to top.
373 WndTo
= Wnd
->head
.pti
->MessageQueue
->spwndActivePrev
;
374 if (can_activate_window( WndTo
)) goto done
;
377 // Find any window to bring to top. Works Okay for wine since it does not see X11 windows.
378 WndTo
= UserGetDesktopWindow();
379 WndTo
= WndTo
->spwndChild
;
391 if (can_activate_window( WndTo
)) goto done
;
392 if (!(WndTo
= WndTo
->spwndNext
)) break;
396 if (WndTo
) UserRefObjectCo(WndTo
, &Ref
);
398 if (gpqForeground
&& (!gpqForeground
->spwndActive
|| Wnd
== gpqForeground
->spwndActive
))
400 /* ReactOS can pass WndTo = NULL to co_IntSetForegroundWindow and returns FALSE. */
401 //ERR("WinPosActivateOtherWindow Set FG 0x%p hWnd %p\n",WndTo, WndTo ? WndTo->head.h : 0);
402 if (co_IntSetForegroundWindow(WndTo
))
404 if (WndTo
) UserDerefObjectCo(WndTo
);
408 //ERR("WinPosActivateOtherWindow Set Active 0x%p\n",WndTo);
409 if (!co_IntSetActiveWindow(WndTo
,FALSE
,TRUE
,FALSE
)) /* Ok for WndTo to be NULL here */
411 //ERR("WPAOW SA 1\n");
412 co_IntSetActiveWindow(NULL
,FALSE
,TRUE
,FALSE
);
414 if (WndTo
) UserDerefObjectCo(WndTo
);
418 WinPosInitInternalPos(PWND Wnd
, RECTL
*RestoreRect
)
421 RECTL Rect
= *RestoreRect
;
423 if (Wnd
->spwndParent
&& Wnd
->spwndParent
!= UserGetDesktopWindow())
425 RECTL_vOffsetRect(&Rect
,
426 -Wnd
->spwndParent
->rcClient
.left
,
427 -Wnd
->spwndParent
->rcClient
.top
);
433 if (!Wnd
->InternalPosInitialized
)
435 // FIXME: Use check point Atom..
436 Wnd
->InternalPos
.flags
= 0;
437 Wnd
->InternalPos
.MaxPos
.x
= Wnd
->InternalPos
.MaxPos
.y
= -1;
438 Wnd
->InternalPos
.IconPos
.x
= Wnd
->InternalPos
.IconPos
.y
= -1;
439 Wnd
->InternalPos
.NormalRect
= Rect
;
440 Wnd
->InternalPosInitialized
= TRUE
;
443 if (Wnd
->style
& WS_MINIMIZE
)
445 Wnd
->InternalPos
.IconPos
= Size
;
446 Wnd
->InternalPos
.flags
|= WPF_MININIT
;
448 else if (Wnd
->style
& WS_MAXIMIZE
)
450 Wnd
->InternalPos
.flags
|= WPF_MAXINIT
;
452 if ( Wnd
->spwndParent
== Wnd
->head
.rpdesk
->pDeskInfo
->spwnd
)
454 if (Wnd
->state
& WNDS_MAXIMIZESTOMONITOR
)
456 Wnd
->InternalPos
.flags
&= ~WPF_MAXINIT
;
457 Wnd
->InternalPos
.MaxPos
.x
= Wnd
->InternalPos
.MaxPos
.y
= -1;
462 PMONITOR pmonitor
= UserMonitorFromRect(&Rect
, MONITOR_DEFAULTTOPRIMARY
);
463 // FIXME: support DPI aware, rcWorkDPI/Real etc..
464 WorkArea
= pmonitor
->rcMonitor
;
466 if (Wnd
->style
& WS_MAXIMIZEBOX
)
467 { // Support (Wnd->state & WNDS_HASCAPTION) || pmonitor->cFullScreen too.
468 if ((Wnd
->style
& WS_CAPTION
) == WS_CAPTION
|| !(Wnd
->style
& (WS_CHILD
| WS_POPUP
)))
470 WorkArea
= pmonitor
->rcWork
;
475 Wnd
->InternalPos
.MaxPos
.x
= Rect
.left
- WorkArea
.left
;
476 Wnd
->InternalPos
.MaxPos
.y
= Rect
.top
- WorkArea
.top
;
478 /*ERR("WinPosIP 2 X %d = R.l %d - W.l %d | Y %d = R.t %d - W.t %d\n",
479 Wnd->InternalPos.MaxPos.x,
480 Rect.left, WorkArea.left,
481 Wnd->InternalPos.MaxPos.y,
482 Rect.top, WorkArea.top);*/
486 Wnd
->InternalPos
.MaxPos
= Size
;
490 Wnd
->InternalPos
.NormalRect
= Rect
;
496 IntGetWindowPlacement(PWND Wnd
, WINDOWPLACEMENT
*lpwndpl
)
498 if (!Wnd
) return FALSE
;
500 if(lpwndpl
->length
!= sizeof(WINDOWPLACEMENT
))
507 WinPosInitInternalPos(Wnd
, &Wnd
->rcWindow
);
509 lpwndpl
->showCmd
= SW_HIDE
;
511 if ( Wnd
->style
& WS_MINIMIZE
)
512 lpwndpl
->showCmd
= SW_SHOWMINIMIZED
;
514 lpwndpl
->showCmd
= ( Wnd
->style
& WS_MAXIMIZE
) ? SW_SHOWMAXIMIZED
: SW_SHOWNORMAL
;
516 lpwndpl
->rcNormalPosition
= Wnd
->InternalPos
.NormalRect
;
518 if (Wnd
->InternalPos
.flags
& WPF_MININIT
) // Return if it was set!
520 lpwndpl
->ptMinPosition
.x
= Wnd
->InternalPos
.IconPos
.x
;
521 lpwndpl
->ptMinPosition
.y
= Wnd
->InternalPos
.IconPos
.y
;
524 lpwndpl
->ptMinPosition
.x
= lpwndpl
->ptMinPosition
.y
= -1;
526 if ( Wnd
->InternalPos
.flags
& WPF_MAXINIT
&& // Return if set and not maximized to monitor!
527 !(Wnd
->state
& WNDS_MAXIMIZESTOMONITOR
))
529 lpwndpl
->ptMaxPosition
.x
= Wnd
->InternalPos
.MaxPos
.x
;
530 lpwndpl
->ptMaxPosition
.y
= Wnd
->InternalPos
.MaxPos
.y
;
533 lpwndpl
->ptMaxPosition
.x
= lpwndpl
->ptMaxPosition
.y
= -1;
535 if ( Wnd
->spwndParent
== Wnd
->head
.rpdesk
->pDeskInfo
->spwnd
&&
536 !(Wnd
->ExStyle
& WS_EX_TOOLWINDOW
))
538 PMONITOR pmonitor
= UserMonitorFromRect(&lpwndpl
->rcNormalPosition
, MONITOR_DEFAULTTOPRIMARY
);
540 // FIXME: support DPI aware, rcWorkDPI/Real etc..
541 if (Wnd
->InternalPos
.flags
& WPF_MININIT
)
543 lpwndpl
->ptMinPosition
.x
-= (pmonitor
->rcWork
.left
- pmonitor
->rcMonitor
.left
);
544 lpwndpl
->ptMinPosition
.y
-= (pmonitor
->rcWork
.top
- pmonitor
->rcMonitor
.top
);
546 RECTL_vOffsetRect(&lpwndpl
->rcNormalPosition
,
547 pmonitor
->rcMonitor
.left
- pmonitor
->rcWork
.left
,
548 pmonitor
->rcMonitor
.top
- pmonitor
->rcWork
.top
);
551 if ( Wnd
->InternalPos
.flags
& WPF_RESTORETOMAXIMIZED
|| Wnd
->style
& WS_MAXIMIZE
)
552 lpwndpl
->flags
|= WPF_RESTORETOMAXIMIZED
;
554 if ( ((Wnd
->style
& (WS_CHILD
|WS_POPUP
)) == WS_CHILD
) && Wnd
->InternalPos
.flags
& WPF_SETMINPOSITION
)
555 lpwndpl
->flags
|= WPF_SETMINPOSITION
;
560 /* make sure the specified rect is visible on screen */
561 static void make_rect_onscreen( RECT
*rect
)
563 PMONITOR pmonitor
= UserMonitorFromRect( rect
, MONITOR_DEFAULTTONEAREST
); // Wine uses this.
565 // FIXME: support DPI aware, rcWorkDPI/Real etc..
566 if (!pmonitor
) return;
567 /* FIXME: map coordinates from rcWork to rcMonitor */
568 if (rect
->right
<= pmonitor
->rcWork
.left
)
570 rect
->right
+= pmonitor
->rcWork
.left
- rect
->left
;
571 rect
->left
= pmonitor
->rcWork
.left
;
573 else if (rect
->left
>= pmonitor
->rcWork
.right
)
575 rect
->left
+= pmonitor
->rcWork
.right
- rect
->right
;
576 rect
->right
= pmonitor
->rcWork
.right
;
578 if (rect
->bottom
<= pmonitor
->rcWork
.top
)
580 rect
->bottom
+= pmonitor
->rcWork
.top
- rect
->top
;
581 rect
->top
= pmonitor
->rcWork
.top
;
583 else if (rect
->top
>= pmonitor
->rcWork
.bottom
)
585 rect
->top
+= pmonitor
->rcWork
.bottom
- rect
->bottom
;
586 rect
->bottom
= pmonitor
->rcWork
.bottom
;
590 /* make sure the specified point is visible on screen */
591 static void make_point_onscreen( POINT
*pt
)
595 RECTL_vSetRect( &rect
, pt
->x
, pt
->y
, pt
->x
+ 1, pt
->y
+ 1 );
596 make_rect_onscreen( &rect
);
602 IntSetWindowPlacement(PWND Wnd
, WINDOWPLACEMENT
*wpl
, UINT Flags
)
607 if ( Flags
& PLACE_MIN
) make_point_onscreen( &wpl
->ptMinPosition
);
608 if ( Flags
& PLACE_MAX
) make_point_onscreen( &wpl
->ptMaxPosition
);
609 if ( Flags
& PLACE_RECT
) make_rect_onscreen( &wpl
->rcNormalPosition
);
611 if (!Wnd
|| Wnd
== Wnd
->head
.rpdesk
->pDeskInfo
->spwnd
) return FALSE
;
613 if ( Flags
& PLACE_MIN
) Wnd
->InternalPos
.IconPos
= wpl
->ptMinPosition
;
614 if ( Flags
& PLACE_MAX
) Wnd
->InternalPos
.MaxPos
= wpl
->ptMaxPosition
;
615 if ( Flags
& PLACE_RECT
) Wnd
->InternalPos
.NormalRect
= wpl
->rcNormalPosition
;
617 SWP_Flags
= SWP_NOZORDER
| SWP_NOACTIVATE
| ((wpl
->flags
& WPF_ASYNCWINDOWPLACEMENT
) ? SWP_ASYNCWINDOWPOS
: 0);
619 if (Wnd
->style
& WS_MINIMIZE
)
621 if (Flags
& PLACE_MIN
|| Wnd
->InternalPos
.flags
& WPF_SETMINPOSITION
)
623 co_WinPosSetWindowPos(Wnd
, HWND_TOP
,
624 wpl
->ptMinPosition
.x
, wpl
->ptMinPosition
.y
, 0, 0,
625 SWP_NOSIZE
| SWP_Flags
);
626 Wnd
->InternalPos
.flags
|= WPF_MININIT
;
629 else if (Wnd
->style
& WS_MAXIMIZE
)
631 if (Flags
& PLACE_MAX
)
633 co_WinPosSetWindowPos(Wnd
, HWND_TOP
,
634 wpl
->ptMaxPosition
.x
, wpl
->ptMaxPosition
.y
, 0, 0,
635 SWP_NOSIZE
| SWP_Flags
);
636 Wnd
->InternalPos
.flags
|= WPF_MAXINIT
;
639 else if (Flags
& PLACE_RECT
)
641 co_WinPosSetWindowPos(Wnd
, HWND_TOP
,
642 wpl
->rcNormalPosition
.left
, wpl
->rcNormalPosition
.top
,
643 wpl
->rcNormalPosition
.right
- wpl
->rcNormalPosition
.left
,
644 wpl
->rcNormalPosition
.bottom
- wpl
->rcNormalPosition
.top
,
648 sAsync
= (Wnd
->head
.pti
->MessageQueue
!= gptiCurrent
->MessageQueue
&& wpl
->flags
& WPF_ASYNCWINDOWPLACEMENT
);
651 co_IntSendMessageNoWait( UserHMGetHandle(Wnd
), WM_ASYNC_SHOWWINDOW
, wpl
->showCmd
, 0 );
653 co_WinPosShowWindow(Wnd
, wpl
->showCmd
);
655 if ( Wnd
->style
& WS_MINIMIZE
&& !sAsync
)
657 if ( wpl
->flags
& WPF_SETMINPOSITION
)
658 Wnd
->InternalPos
.flags
|= WPF_SETMINPOSITION
;
660 if ( wpl
->flags
& WPF_RESTORETOMAXIMIZED
)
661 Wnd
->InternalPos
.flags
|= WPF_RESTORETOMAXIMIZED
;
668 co_WinPosArrangeIconicWindows(PWND parent
)
672 INT x
, y
, xspacing
, yspacing
, sx
, sy
;
674 ASSERT_REFS_CO(parent
);
676 IntGetClientRect( parent
, &rectParent
);
677 // FIXME: Support Minimize Metrics gspv.mm.iArrange.
678 // Default: ARW_BOTTOMLEFT
680 y
= rectParent
.bottom
;
682 xspacing
= UserGetSystemMetrics(SM_CXMINIMIZED
);
683 yspacing
= UserGetSystemMetrics(SM_CYMINIMIZED
);
685 Child
= parent
->spwndChild
;
688 if((Child
->style
& WS_MINIMIZE
) != 0 )
690 USER_REFERENCE_ENTRY Ref
;
691 UserRefObjectCo(Child
, &Ref
);
693 sx
= x
+ UserGetSystemMetrics(SM_CXBORDER
);
694 sy
= y
- yspacing
- UserGetSystemMetrics(SM_CYBORDER
);
696 Child
->InternalPos
.IconPos
.x
= sx
;
697 Child
->InternalPos
.IconPos
.y
= sy
;
698 Child
->InternalPos
.flags
|= WPF_MININIT
;
700 co_WinPosSetWindowPos( Child
, 0, sx
, sy
, xspacing
, yspacing
, SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOCOPYBITS
| SWP_ASYNCWINDOWPOS
);
702 UserDerefObjectCo(Child
);
704 if (x
<= rectParent
.right
- xspacing
)
712 Child
= Child
->spwndNext
;
718 WinPosFindIconPos(PWND Window
, POINT
*Pos
)
721 PWND pwndChild
, pwndParent
;
722 int x
, y
, xspacing
, yspacing
;
724 pwndParent
= Window
->spwndParent
;
725 if (pwndParent
== UserGetDesktopWindow())
727 ERR("Parent is Desktop, Min off screen!\n");
728 /* ReactOS doesn't support iconic minimize to desktop */
729 Pos
->x
= Pos
->y
= -32000;
730 Window
->InternalPos
.flags
|= WPF_MININIT
;
731 Window
->InternalPos
.IconPos
.x
= Pos
->x
;
732 Window
->InternalPos
.IconPos
.y
= Pos
->y
;
736 IntGetClientRect( pwndParent
, &rectParent
);
737 // FIXME: Support Minimize Metrics gspv.mm.iArrange.
738 // Default: ARW_BOTTOMLEFT
740 y
= rectParent
.bottom
;
742 xspacing
= UserGetSystemMetrics(SM_CXMINIMIZED
);
743 yspacing
= UserGetSystemMetrics(SM_CYMINIMIZED
);
745 // Set to default position when minimized.
746 Pos
->x
= x
+ UserGetSystemMetrics(SM_CXBORDER
);
747 Pos
->y
= y
- yspacing
- UserGetSystemMetrics(SM_CYBORDER
);
749 for (pwndChild
= pwndParent
->spwndChild
; pwndChild
; pwndChild
= pwndChild
->spwndNext
)
751 if (pwndChild
== Window
) continue;
753 if ((pwndChild
->style
& (WS_VISIBLE
|WS_MINIMIZE
)) != (WS_VISIBLE
|WS_MINIMIZE
) )
758 if ( pwndChild
->InternalPos
.IconPos
.x
!= Pos
->x
&& pwndChild
->InternalPos
.IconPos
.y
!= Pos
->y
)
762 if (x
<= rectParent
.right
- xspacing
)
769 Pos
->x
= x
+ UserGetSystemMetrics(SM_CXBORDER
);
770 Pos
->y
= y
- yspacing
- UserGetSystemMetrics(SM_CYBORDER
);
773 Window
->InternalPos
.IconPos
.x
= Pos
->x
;
774 Window
->InternalPos
.IconPos
.y
= Pos
->y
;
775 Window
->InternalPos
.flags
|= WPF_MININIT
;
776 TRACE("Position is set! X:%d Y:%d\n",Pos
->x
,Pos
->y
);
781 co_WinPosMinMaximize(PWND Wnd
, UINT ShowFlag
, RECT
* NewPos
)
790 wpl
.length
= sizeof(wpl
);
791 IntGetWindowPlacement( Wnd
, &wpl
);
793 if (co_HOOK_CallHooks( WH_CBT
, HCBT_MINMAX
, (WPARAM
)Wnd
->head
.h
, ShowFlag
))
795 ERR("WinPosMinMaximize WH_CBT Call Hook return!\n");
796 return SWP_NOSIZE
| SWP_NOMOVE
;
798 if (Wnd
->style
& WS_MINIMIZE
)
803 case SW_SHOWMINNOACTIVE
:
804 case SW_SHOWMINIMIZED
:
805 case SW_FORCEMINIMIZE
:
806 return SWP_NOSIZE
| SWP_NOMOVE
;
808 if (!co_IntSendMessageNoWait(Wnd
->head
.h
, WM_QUERYOPEN
, 0, 0))
810 return(SWP_NOSIZE
| SWP_NOMOVE
);
812 SwpFlags
|= SWP_NOCOPYBITS
;
817 case SW_SHOWMINNOACTIVE
:
818 case SW_SHOWMINIMIZED
:
819 case SW_FORCEMINIMIZE
:
821 //ERR("MinMaximize Minimize\n");
822 if (Wnd
->style
& WS_MAXIMIZE
)
824 Wnd
->InternalPos
.flags
|= WPF_RESTORETOMAXIMIZED
;
828 Wnd
->InternalPos
.flags
&= ~WPF_RESTORETOMAXIMIZED
;
831 old_style
= IntSetStyle( Wnd
, WS_MINIMIZE
, WS_MAXIMIZE
);
833 co_UserRedrawWindow(Wnd
, NULL
, 0, RDW_VALIDATE
| RDW_NOERASE
| RDW_NOINTERNALPAINT
);
835 if (!(Wnd
->InternalPos
.flags
& WPF_SETMINPOSITION
))
836 Wnd
->InternalPos
.flags
&= ~WPF_MININIT
;
838 WinPosFindIconPos(Wnd
, &wpl
.ptMinPosition
);
840 /*if (!(old_style & WS_MINIMIZE))
842 SwpFlags |= SWP_STATECHANGED;
843 IntShowOwnedPopups(Wnd, FALSE);
846 RECTL_vSetRect(NewPos
, wpl
.ptMinPosition
.x
, wpl
.ptMinPosition
.y
,
847 wpl
.ptMinPosition
.x
+ UserGetSystemMetrics(SM_CXMINIMIZED
),
848 wpl
.ptMinPosition
.y
+ UserGetSystemMetrics(SM_CYMINIMIZED
));
849 SwpFlags
|= SWP_NOCOPYBITS
;
855 //ERR("MinMaximize Maximize\n");
856 if ((Wnd
->style
& WS_MAXIMIZE
) && (Wnd
->style
& WS_VISIBLE
))
858 SwpFlags
= SWP_NOSIZE
| SWP_NOMOVE
;
861 co_WinPosGetMinMaxInfo(Wnd
, &Size
, &wpl
.ptMaxPosition
, NULL
, NULL
);
863 /*ERR("Maximize: %d,%d %dx%d\n",
864 wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, Size.x, Size.y);
866 old_style
= IntSetStyle( Wnd
, WS_MAXIMIZE
, WS_MINIMIZE
);
867 /*if (old_style & WS_MINIMIZE)
869 IntShowOwnedPopups(Wnd, TRUE);
872 if (!(old_style
& WS_MAXIMIZE
)) SwpFlags
|= SWP_STATECHANGED
;
873 RECTL_vSetRect(NewPos
, wpl
.ptMaxPosition
.x
, wpl
.ptMaxPosition
.y
,
874 //wpl.ptMaxPosition.x + Size.x, wpl.ptMaxPosition.y + Size.y);
879 case SW_SHOWNOACTIVATE
:
880 Wnd
->InternalPos
.flags
&= ~WPF_RESTORETOMAXIMIZED
;
884 case SW_SHOWDEFAULT
: /* FIXME: should have its own handler */
886 //ERR("MinMaximize Restore\n");
887 old_style
= IntSetStyle( Wnd
, 0, WS_MINIMIZE
| WS_MAXIMIZE
);
888 if (old_style
& WS_MINIMIZE
)
890 //IntShowOwnedPopups(Wnd, TRUE);
892 if (Wnd
->InternalPos
.flags
& WPF_RESTORETOMAXIMIZED
)
894 co_WinPosGetMinMaxInfo(Wnd
, &Size
, &wpl
.ptMaxPosition
, NULL
, NULL
);
895 IntSetStyle( Wnd
, WS_MAXIMIZE
, 0 );
896 SwpFlags
|= SWP_STATECHANGED
;
897 RECTL_vSetRect(NewPos
, wpl
.ptMaxPosition
.x
, wpl
.ptMaxPosition
.y
,
898 wpl
.ptMaxPosition
.x
+ Size
.x
, wpl
.ptMaxPosition
.y
+ Size
.y
);
903 *NewPos
= wpl
.rcNormalPosition
;
904 NewPos
->right
-= NewPos
->left
;
905 NewPos
->bottom
-= NewPos
->top
;
911 if (!(old_style
& WS_MAXIMIZE
))
915 SwpFlags
|= SWP_STATECHANGED
;
916 Wnd
->InternalPos
.flags
&= ~WPF_RESTORETOMAXIMIZED
;
917 *NewPos
= wpl
.rcNormalPosition
;
918 NewPos
->right
-= NewPos
->left
;
919 NewPos
->bottom
-= NewPos
->top
;
928 UserHasWindowEdge(DWORD Style
, DWORD ExStyle
)
930 if (Style
& WS_MINIMIZE
)
932 if (ExStyle
& WS_EX_DLGMODALFRAME
)
934 if (ExStyle
& WS_EX_STATICEDGE
)
936 if (Style
& WS_THICKFRAME
)
939 if (Style
== WS_DLGFRAME
|| Style
== WS_CAPTION
)
945 IntGetWindowBorderMeasures(PWND Wnd
, UINT
*cx
, UINT
*cy
)
947 if(HAS_DLGFRAME(Wnd
->style
, Wnd
->ExStyle
) && !(Wnd
->style
& WS_MINIMIZE
))
949 *cx
= UserGetSystemMetrics(SM_CXDLGFRAME
);
950 *cy
= UserGetSystemMetrics(SM_CYDLGFRAME
);
954 if(HAS_THICKFRAME(Wnd
->style
, Wnd
->ExStyle
)&& !(Wnd
->style
& WS_MINIMIZE
))
956 *cx
= UserGetSystemMetrics(SM_CXFRAME
);
957 *cy
= UserGetSystemMetrics(SM_CYFRAME
);
959 else if(HAS_THINFRAME(Wnd
->style
, Wnd
->ExStyle
))
961 *cx
= UserGetSystemMetrics(SM_CXBORDER
);
962 *cy
= UserGetSystemMetrics(SM_CYBORDER
);
972 UserGetWindowBorders(DWORD Style
, DWORD ExStyle
, SIZE
*Size
, BOOL WithClient
)
976 if (UserHasWindowEdge(Style
, ExStyle
))
978 else if (ExStyle
& WS_EX_STATICEDGE
)
980 if ((ExStyle
& WS_EX_CLIENTEDGE
) && WithClient
)
982 if (Style
& WS_CAPTION
|| ExStyle
& WS_EX_DLGMODALFRAME
)
984 Size
->cx
= Size
->cy
= Border
;
985 if ((Style
& WS_THICKFRAME
) && !(Style
& WS_MINIMIZE
))
987 Size
->cx
+= UserGetSystemMetrics(SM_CXFRAME
) - UserGetSystemMetrics(SM_CXDLGFRAME
);
988 Size
->cy
+= UserGetSystemMetrics(SM_CYFRAME
) - UserGetSystemMetrics(SM_CYDLGFRAME
);
990 Size
->cx
*= UserGetSystemMetrics(SM_CXBORDER
);
991 Size
->cy
*= UserGetSystemMetrics(SM_CYBORDER
);
995 UserAdjustWindowRectEx(LPRECT lpRect
,
1004 lpRect
->top
-= UserGetSystemMetrics(SM_CYMENU
);
1006 if ((dwStyle
& WS_CAPTION
) == WS_CAPTION
)
1008 if (dwExStyle
& WS_EX_TOOLWINDOW
)
1009 lpRect
->top
-= UserGetSystemMetrics(SM_CYSMCAPTION
);
1011 lpRect
->top
-= UserGetSystemMetrics(SM_CYCAPTION
);
1013 UserGetWindowBorders(dwStyle
, dwExStyle
, &BorderSize
, TRUE
);
1023 co_WinPosGetMinMaxInfo(PWND Window
, POINT
* MaxSize
, POINT
* MaxPos
,
1024 POINT
* MinTrack
, POINT
* MaxTrack
)
1029 LONG style
= Window
->style
;
1031 LONG exstyle
= Window
->ExStyle
;
1034 ASSERT_REFS_CO(Window
);
1036 /* Compute default values */
1038 rc
= Window
->rcWindow
;
1039 MinMax
.ptReserved
.x
= rc
.left
;
1040 MinMax
.ptReserved
.y
= rc
.top
;
1042 if ((style
& WS_CAPTION
) == WS_CAPTION
)
1043 adjustedStyle
= style
& ~WS_BORDER
; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
1045 adjustedStyle
= style
;
1047 if(Window
->spwndParent
)
1048 IntGetClientRect(Window
->spwndParent
, &rc
);
1049 UserAdjustWindowRectEx(&rc
, adjustedStyle
, ((style
& WS_POPUP
) && Window
->IDMenu
), exstyle
);
1054 MinMax
.ptMaxSize
.x
= rc
.right
- rc
.left
;
1055 MinMax
.ptMaxSize
.y
= rc
.bottom
- rc
.top
;
1056 if (style
& (WS_DLGFRAME
| WS_BORDER
))
1058 MinMax
.ptMinTrackSize
.x
= UserGetSystemMetrics(SM_CXMINTRACK
);
1059 MinMax
.ptMinTrackSize
.y
= UserGetSystemMetrics(SM_CYMINTRACK
);
1063 MinMax
.ptMinTrackSize
.x
= 2 * xinc
;
1064 MinMax
.ptMinTrackSize
.y
= 2 * yinc
;
1066 MinMax
.ptMaxTrackSize
.x
= UserGetSystemMetrics(SM_CXMAXTRACK
);
1067 MinMax
.ptMaxTrackSize
.y
= UserGetSystemMetrics(SM_CYMAXTRACK
);
1068 MinMax
.ptMaxPosition
.x
= -xinc
;
1069 MinMax
.ptMaxPosition
.y
= -yinc
;
1071 if (!EMPTYPOINT(Window
->InternalPos
.MaxPos
)) MinMax
.ptMaxPosition
= Window
->InternalPos
.MaxPos
;
1073 co_IntSendMessage(Window
->head
.h
, WM_GETMINMAXINFO
, 0, (LPARAM
)&MinMax
);
1075 /* if the app didn't change the values, adapt them for the current monitor */
1076 if ((monitor
= UserGetPrimaryMonitor()))
1080 rc_work
= monitor
->rcMonitor
;
1082 if (style
& WS_MAXIMIZEBOX
)
1084 if ((style
& WS_CAPTION
) == WS_CAPTION
|| !(style
& (WS_CHILD
| WS_POPUP
)))
1085 rc_work
= monitor
->rcWork
;
1088 if (MinMax
.ptMaxSize
.x
== UserGetSystemMetrics(SM_CXSCREEN
) + 2 * xinc
&&
1089 MinMax
.ptMaxSize
.y
== UserGetSystemMetrics(SM_CYSCREEN
) + 2 * yinc
)
1091 MinMax
.ptMaxSize
.x
= (rc_work
.right
- rc_work
.left
) + 2 * xinc
;
1092 MinMax
.ptMaxSize
.y
= (rc_work
.bottom
- rc_work
.top
) + 2 * yinc
;
1094 if (MinMax
.ptMaxPosition
.x
== -xinc
&& MinMax
.ptMaxPosition
.y
== -yinc
)
1096 MinMax
.ptMaxPosition
.x
= rc_work
.left
- xinc
;
1097 MinMax
.ptMaxPosition
.y
= rc_work
.top
- yinc
;
1099 if (MinMax
.ptMaxSize
.x
>= (monitor
->rcMonitor
.right
- monitor
->rcMonitor
.left
) &&
1100 MinMax
.ptMaxSize
.y
>= (monitor
->rcMonitor
.bottom
- monitor
->rcMonitor
.top
) )
1101 Window
->state
|= WNDS_MAXIMIZESTOMONITOR
;
1103 Window
->state
&= ~WNDS_MAXIMIZESTOMONITOR
;
1107 MinMax
.ptMaxTrackSize
.x
= max(MinMax
.ptMaxTrackSize
.x
,
1108 MinMax
.ptMinTrackSize
.x
);
1109 MinMax
.ptMaxTrackSize
.y
= max(MinMax
.ptMaxTrackSize
.y
,
1110 MinMax
.ptMinTrackSize
.y
);
1113 *MaxSize
= MinMax
.ptMaxSize
;
1115 *MaxPos
= MinMax
.ptMaxPosition
;
1117 *MinTrack
= MinMax
.ptMinTrackSize
;
1119 *MaxTrack
= MinMax
.ptMaxTrackSize
;
1121 return 0; // FIXME: What does it return?
1126 IntValidateParent(PWND Child
, PREGION ValidateRgn
)
1128 PWND ParentWnd
= Child
;
1130 if (ParentWnd
->style
& WS_CHILD
)
1133 ParentWnd
= ParentWnd
->spwndParent
;
1134 while (ParentWnd
->style
& WS_CHILD
);
1137 ParentWnd
= Child
->spwndParent
;
1140 if (ParentWnd
->style
& WS_CLIPCHILDREN
)
1143 if (ParentWnd
->hrgnUpdate
!= 0)
1145 IntInvalidateWindows( ParentWnd
,
1147 RDW_VALIDATE
| RDW_NOCHILDREN
);
1150 ParentWnd
= ParentWnd
->spwndParent
;
1158 FixClientRect(PRECTL ClientRect
, PRECTL WindowRect
)
1160 if (ClientRect
->left
< WindowRect
->left
)
1162 ClientRect
->left
= WindowRect
->left
;
1164 else if (WindowRect
->right
< ClientRect
->left
)
1166 ClientRect
->left
= WindowRect
->right
;
1168 if (ClientRect
->right
< WindowRect
->left
)
1170 ClientRect
->right
= WindowRect
->left
;
1172 else if (WindowRect
->right
< ClientRect
->right
)
1174 ClientRect
->right
= WindowRect
->right
;
1176 if (ClientRect
->top
< WindowRect
->top
)
1178 ClientRect
->top
= WindowRect
->top
;
1180 else if (WindowRect
->bottom
< ClientRect
->top
)
1182 ClientRect
->top
= WindowRect
->bottom
;
1184 if (ClientRect
->bottom
< WindowRect
->top
)
1186 ClientRect
->bottom
= WindowRect
->top
;
1188 else if (WindowRect
->bottom
< ClientRect
->bottom
)
1190 ClientRect
->bottom
= WindowRect
->bottom
;
1193 /***********************************************************************
1196 * Compute the valid rects from the old and new client rect and WVR_* flags.
1197 * Helper for WM_NCCALCSIZE handling.
1201 get_valid_rects( RECTL
*old_client
, RECTL
*new_client
, UINT flags
, RECTL
*valid
)
1205 if (flags
& WVR_REDRAW
)
1207 RECTL_vSetEmptyRect( &valid
[0] );
1208 RECTL_vSetEmptyRect( &valid
[1] );
1212 if (flags
& WVR_VALIDRECTS
)
1214 if (!RECTL_bIntersectRect( &valid
[0], &valid
[0], new_client
) ||
1215 !RECTL_bIntersectRect( &valid
[1], &valid
[1], old_client
))
1217 RECTL_vSetEmptyRect( &valid
[0] );
1218 RECTL_vSetEmptyRect( &valid
[1] );
1221 flags
= WVR_ALIGNLEFT
| WVR_ALIGNTOP
;
1225 valid
[0] = *new_client
;
1226 valid
[1] = *old_client
;
1229 /* make sure the rectangles have the same size */
1230 cx
= min( valid
[0].right
- valid
[0].left
, valid
[1].right
- valid
[1].left
);
1231 cy
= min( valid
[0].bottom
- valid
[0].top
, valid
[1].bottom
- valid
[1].top
);
1233 if (flags
& WVR_ALIGNBOTTOM
)
1235 valid
[0].top
= valid
[0].bottom
- cy
;
1236 valid
[1].top
= valid
[1].bottom
- cy
;
1240 valid
[0].bottom
= valid
[0].top
+ cy
;
1241 valid
[1].bottom
= valid
[1].top
+ cy
;
1243 if (flags
& WVR_ALIGNRIGHT
)
1245 valid
[0].left
= valid
[0].right
- cx
;
1246 valid
[1].left
= valid
[1].right
- cx
;
1250 valid
[0].right
= valid
[0].left
+ cx
;
1251 valid
[1].right
= valid
[1].left
+ cx
;
1257 co_WinPosDoNCCALCSize(PWND Window
, PWINDOWPOS WinPos
, RECTL
* WindowRect
, RECTL
* ClientRect
, RECTL
* validRects
)
1262 ASSERT_REFS_CO(Window
);
1264 /* Send WM_NCCALCSIZE message to get new client area */
1265 if ((WinPos
->flags
& (SWP_FRAMECHANGED
| SWP_NOSIZE
)) != SWP_NOSIZE
)
1267 NCCALCSIZE_PARAMS params
;
1268 WINDOWPOS winposCopy
;
1270 params
.rgrc
[0] = *WindowRect
; // new coordinates of a window that has been moved or resized
1271 params
.rgrc
[1] = Window
->rcWindow
; // window before it was moved or resized
1272 params
.rgrc
[2] = Window
->rcClient
; // client area before the window was moved or resized
1274 Parent
= Window
->spwndParent
;
1275 if (0 != (Window
->style
& WS_CHILD
) && Parent
)
1277 RECTL_vOffsetRect(&(params
.rgrc
[0]), - Parent
->rcClient
.left
, - Parent
->rcClient
.top
);
1278 RECTL_vOffsetRect(&(params
.rgrc
[1]), - Parent
->rcClient
.left
, - Parent
->rcClient
.top
);
1279 RECTL_vOffsetRect(&(params
.rgrc
[2]), - Parent
->rcClient
.left
, - Parent
->rcClient
.top
);
1282 params
.lppos
= &winposCopy
;
1283 winposCopy
= *WinPos
;
1285 wvrFlags
= co_IntSendMessage(Window
->head
.h
, WM_NCCALCSIZE
, TRUE
, (LPARAM
) ¶ms
);
1287 /* If the application send back garbage, ignore it */
1288 if (params
.rgrc
[0].left
<= params
.rgrc
[0].right
&&
1289 params
.rgrc
[0].top
<= params
.rgrc
[0].bottom
)
1291 *ClientRect
= params
.rgrc
[0]; // First rectangle contains the coordinates of the new client rectangle resulting from the move or resize
1292 if ((Window
->style
& WS_CHILD
) && Parent
)
1294 RECTL_vOffsetRect(ClientRect
, Parent
->rcClient
.left
, Parent
->rcClient
.top
);
1296 FixClientRect(ClientRect
, WindowRect
);
1299 if (ClientRect
->left
!= Window
->rcClient
.left
||
1300 ClientRect
->top
!= Window
->rcClient
.top
)
1302 WinPos
->flags
&= ~SWP_NOCLIENTMOVE
;
1305 if (ClientRect
->right
- ClientRect
->left
!= Window
->rcClient
.right
- Window
->rcClient
.left
)
1307 WinPos
->flags
&= ~SWP_NOCLIENTSIZE
;
1310 wvrFlags
&= ~WVR_HREDRAW
;
1312 if (ClientRect
->bottom
- ClientRect
->top
!= Window
->rcClient
.bottom
- Window
->rcClient
.top
)
1314 WinPos
->flags
&= ~SWP_NOCLIENTSIZE
;
1317 wvrFlags
&= ~WVR_VREDRAW
;
1319 validRects
[0] = params
.rgrc
[1]; // second rectangle contains the valid destination rectangle
1320 validRects
[1] = params
.rgrc
[2]; // third rectangle contains the valid source rectangle
1324 if (!(WinPos
->flags
& SWP_NOMOVE
) &&
1325 (ClientRect
->left
!= Window
->rcClient
.left
||
1326 ClientRect
->top
!= Window
->rcClient
.top
))
1328 WinPos
->flags
&= ~SWP_NOCLIENTMOVE
;
1332 if (WinPos
->flags
& (SWP_NOCOPYBITS
| SWP_NOREDRAW
| SWP_SHOWWINDOW
| SWP_HIDEWINDOW
))
1334 RECTL_vSetEmptyRect( &validRects
[0] );
1335 RECTL_vSetEmptyRect( &validRects
[1] );
1337 else get_valid_rects( &Window
->rcClient
, ClientRect
, wvrFlags
, validRects
);
1344 co_WinPosDoWinPosChanging(PWND Window
,
1349 ASSERT_REFS_CO(Window
);
1351 /* Send WM_WINDOWPOSCHANGING message */
1353 if (!(WinPos
->flags
& SWP_NOSENDCHANGING
))
1355 TRACE("Sending WM_WINDOWPOSCHANGING to hwnd %p flags %04x.\n", Window
->head
.h
,WinPos
->flags
);
1356 co_IntSendMessage(Window
->head
.h
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
) WinPos
);
1359 /* Calculate new position and size */
1361 *WindowRect
= Window
->rcWindow
;
1362 *ClientRect
= (Window
->style
& WS_MINIMIZE
) ? Window
->rcWindow
: Window
->rcClient
;
1364 if (!(WinPos
->flags
& SWP_NOSIZE
))
1366 if (Window
->style
& WS_MINIMIZE
)
1368 WindowRect
->right
= WindowRect
->left
+ UserGetSystemMetrics(SM_CXMINIMIZED
);
1369 WindowRect
->bottom
= WindowRect
->top
+ UserGetSystemMetrics(SM_CYMINIMIZED
);
1373 WindowRect
->right
= WindowRect
->left
+ WinPos
->cx
;
1374 WindowRect
->bottom
= WindowRect
->top
+ WinPos
->cy
;
1378 if (!(WinPos
->flags
& SWP_NOMOVE
))
1385 Parent
= Window
->spwndParent
;
1387 // Parent child position issue is in here. SetParent_W7 test CORE-6651.
1388 if (//((Window->style & WS_CHILD) != 0) && <- Fixes wine msg test_SetParent: "rects do not match", the last test.
1390 Parent
!= Window
->head
.rpdesk
->pDeskInfo
->spwnd
)
1392 TRACE("Not SWP_NOMOVE 1 Parent client offset X %d Y %d\n",X
,Y
);
1393 X
+= Parent
->rcClient
.left
;
1394 Y
+= Parent
->rcClient
.top
;
1395 TRACE("Not SWP_NOMOVE 2 Parent client offset X %d Y %d\n",X
,Y
);
1398 WindowRect
->left
= X
;
1399 WindowRect
->top
= Y
;
1400 WindowRect
->right
+= X
- Window
->rcWindow
.left
;
1401 WindowRect
->bottom
+= Y
- Window
->rcWindow
.top
;
1403 RECTL_vOffsetRect(ClientRect
, X
- Window
->rcWindow
.left
,
1404 Y
- Window
->rcWindow
.top
);
1406 WinPos
->flags
|= SWP_NOCLIENTMOVE
| SWP_NOCLIENTSIZE
;
1408 TRACE( "hwnd %p, after %p, swp %d,%d %dx%d flags %08x\n",
1409 WinPos
->hwnd
, WinPos
->hwndInsertAfter
, WinPos
->x
, WinPos
->y
,
1410 WinPos
->cx
, WinPos
->cy
, WinPos
->flags
);
1411 TRACE("WindowRect: %d %d %d %d\n", WindowRect
->left
,WindowRect
->top
,WindowRect
->right
,WindowRect
->bottom
);
1412 TRACE("ClientRect: %d %d %d %d\n", ClientRect
->left
,ClientRect
->top
,ClientRect
->right
,ClientRect
->bottom
);
1418 * Fix Z order taking into account owned popups -
1419 * basically we need to maintain them above the window that owns them
1421 * FIXME: hide/show owned popups when owner visibility changes.
1423 * ReactOS: See bug CORE-6129 and CORE-6554.
1427 // Pass all the win:test_children/popup_zorder tests except "move hwnd_F and its popups down" which is if'ed out.
1428 // Side effect, breaks more of the DeferWindowPos api tests, but wine breaks more!!!!
1431 WinPosDoOwnedPopups(PWND Window
, HWND hWndInsertAfter
)
1436 PWND DesktopWindow
, ChildObject
;
1439 TRACE("(%p) hInsertAfter = %p\n", Window
, hWndInsertAfter
);
1441 Style
= Window
->style
;
1443 if (Style
& WS_CHILD
)
1445 TRACE("Window is child\n");
1446 return hWndInsertAfter
;
1449 Owner
= Window
->spwndOwner
? Window
->spwndOwner
->head
.h
: NULL
;
1453 /* Make sure this popup stays above the owner */
1455 if (hWndInsertAfter
!= HWND_TOPMOST
)
1457 DesktopWindow
= UserGetDesktopWindow();
1458 List
= IntWinListChildren(DesktopWindow
);
1462 for (i
= 0; List
[i
]; i
++)
1464 BOOL topmost
= FALSE
;
1466 ChildObject
= ValidateHwndNoErr(List
[i
]);
1469 topmost
= (ChildObject
->ExStyle
& WS_EX_TOPMOST
) != 0;
1472 if (List
[i
] == Owner
)
1474 if (i
> 0) hWndInsertAfter
= List
[i
-1];
1475 else hWndInsertAfter
= topmost
? HWND_TOPMOST
: HWND_TOP
;
1479 if (hWndInsertAfter
== HWND_TOP
|| hWndInsertAfter
== HWND_NOTOPMOST
)
1481 if (!topmost
) break;
1483 else if (List
[i
] == hWndInsertAfter
) break;
1487 return hWndInsertAfter
;
1491 if (hWndInsertAfter
== HWND_BOTTOM
)
1493 ERR("Window is HWND_BOTTOM hwnd %p\n",hWndInsertAfter
);
1494 if (List
) ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1500 DesktopWindow
= UserGetDesktopWindow();
1501 List
= IntWinListChildren(DesktopWindow
);
1508 if (hWndInsertAfter
== HWND_TOP
|| hWndInsertAfter
== HWND_NOTOPMOST
)
1510 if (hWndInsertAfter
== HWND_NOTOPMOST
|| !(Window
->ExStyle
& WS_EX_TOPMOST
))
1512 TRACE("skip all the topmost windows\n");
1513 /* skip all the topmost windows */
1515 (ChildObject
= ValidateHwndNoErr(List
[i
])) &&
1516 (ChildObject
->ExStyle
& WS_EX_TOPMOST
)) i
++;
1519 else if (hWndInsertAfter
!= HWND_TOPMOST
)
1521 /* skip windows that are already placed correctly */
1522 for (i
= 0; List
[i
]; i
++)
1524 if (List
[i
] == hWndInsertAfter
) break;
1525 if (List
[i
] == UserHMGetHandle(Window
))
1527 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1528 goto done
; /* nothing to do if window is moving backwards in z-order */
1533 for (; List
[i
]; i
++)
1536 USER_REFERENCE_ENTRY Ref
;
1538 if (List
[i
] == UserHMGetHandle(Window
))
1541 if (!(Wnd
= ValidateHwndNoErr(List
[i
])))
1544 Owner
= Wnd
->spwndOwner
? Wnd
->spwndOwner
->head
.h
: NULL
;
1546 if (Owner
!= UserHMGetHandle(Window
)) continue;
1548 UserRefObjectCo(Wnd
, &Ref
);
1549 TRACE( "moving %p owned by %p after %p\n", List
[i
], UserHMGetHandle(Window
), hWndInsertAfter
);
1550 co_WinPosSetWindowPos(Wnd
, hWndInsertAfter
, 0, 0, 0, 0,
1551 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOSENDCHANGING
| SWP_DEFERERASE
);
1553 UserDerefObjectCo(Wnd
);
1554 hWndInsertAfter
= List
[i
];
1556 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1559 return hWndInsertAfter
;
1563 /***********************************************************************
1564 * WinPosInternalMoveWindow
1566 * Update WindowRect and ClientRect of Window and all of its children
1567 * We keep both WindowRect and ClientRect in screen coordinates internally
1571 WinPosInternalMoveWindow(PWND Window
, INT MoveX
, INT MoveY
)
1575 ASSERT(Window
!= Window
->spwndChild
);
1576 TRACE("InternalMoveWin X %d Y %d\n", MoveX
, MoveY
);
1578 Window
->rcWindow
.left
+= MoveX
;
1579 Window
->rcWindow
.right
+= MoveX
;
1580 Window
->rcWindow
.top
+= MoveY
;
1581 Window
->rcWindow
.bottom
+= MoveY
;
1583 Window
->rcClient
.left
+= MoveX
;
1584 Window
->rcClient
.right
+= MoveX
;
1585 Window
->rcClient
.top
+= MoveY
;
1586 Window
->rcClient
.bottom
+= MoveY
;
1588 for(Child
= Window
->spwndChild
; Child
; Child
= Child
->spwndNext
)
1590 WinPosInternalMoveWindow(Child
, MoveX
, MoveY
);
1595 * WinPosFixupSWPFlags
1597 * Fix redundant flags and values in the WINDOWPOS structure.
1601 WinPosFixupFlags(WINDOWPOS
*WinPos
, PWND Wnd
)
1606 /* Finally make sure that all coordinates are valid */
1607 if (WinPos
->x
< -32768) WinPos
->x
= -32768;
1608 else if (WinPos
->x
> 32767) WinPos
->x
= 32767;
1609 if (WinPos
->y
< -32768) WinPos
->y
= -32768;
1610 else if (WinPos
->y
> 32767) WinPos
->y
= 32767;
1612 WinPos
->cx
= max(WinPos
->cx
, 0);
1613 WinPos
->cy
= max(WinPos
->cy
, 0);
1615 Parent
= UserGetAncestor( Wnd
, GA_PARENT
);
1616 if (!IntIsWindowVisible( Parent
) &&
1617 /* Fix B : wine msg test_SetParent:WmSetParentSeq_2:25 wParam bits! */
1618 (WinPos
->flags
& SWP_AGG_STATUSFLAGS
) == SWP_AGG_NOPOSCHANGE
) WinPos
->flags
|= SWP_NOREDRAW
;
1620 if (Wnd
->style
& WS_VISIBLE
) WinPos
->flags
&= ~SWP_SHOWWINDOW
;
1623 WinPos
->flags
&= ~SWP_HIDEWINDOW
;
1624 if (!(WinPos
->flags
& SWP_SHOWWINDOW
)) WinPos
->flags
|= SWP_NOREDRAW
;
1627 /* Check for right size */
1628 if (Wnd
->rcWindow
.right
- Wnd
->rcWindow
.left
== WinPos
->cx
&&
1629 Wnd
->rcWindow
.bottom
- Wnd
->rcWindow
.top
== WinPos
->cy
)
1631 WinPos
->flags
|= SWP_NOSIZE
;
1636 IntClientToScreen( Parent
, &pt
);
1637 TRACE("WPFU C2S wpx %d wpy %d ptx %d pty %d\n",WinPos
->x
,WinPos
->y
,pt
.x
,pt
.y
);
1638 /* Check for right position */
1639 if (Wnd
->rcWindow
.left
== pt
.x
&& Wnd
->rcWindow
.top
== pt
.y
)
1641 //ERR("In right pos\n");
1642 WinPos
->flags
|= SWP_NOMOVE
;
1645 if ( WinPos
->hwnd
!= UserGetForegroundWindow() && (Wnd
->style
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)
1647 /* Bring to the top when activating */
1648 if (!(WinPos
->flags
& (SWP_NOACTIVATE
|SWP_HIDEWINDOW
)) &&
1649 (WinPos
->flags
& SWP_NOZORDER
||
1650 (WinPos
->hwndInsertAfter
!= HWND_TOPMOST
&& WinPos
->hwndInsertAfter
!= HWND_NOTOPMOST
)))
1652 WinPos
->flags
&= ~SWP_NOZORDER
;
1653 WinPos
->hwndInsertAfter
= (0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
) ? HWND_TOPMOST
: HWND_TOP
);
1657 /* Check hwndInsertAfter */
1658 if (!(WinPos
->flags
& SWP_NOZORDER
))
1660 /* Fix sign extension */
1661 if (WinPos
->hwndInsertAfter
== (HWND
)0xffff)
1663 WinPos
->hwndInsertAfter
= HWND_TOPMOST
;
1665 else if (WinPos
->hwndInsertAfter
== (HWND
)0xfffe)
1667 WinPos
->hwndInsertAfter
= HWND_NOTOPMOST
;
1670 if (WinPos
->hwndInsertAfter
== HWND_TOP
)
1672 /* Keep it topmost when it's already topmost */
1673 if ((Wnd
->ExStyle
& WS_EX_TOPMOST
) != 0)
1674 WinPos
->hwndInsertAfter
= HWND_TOPMOST
;
1676 if (IntGetWindow(WinPos
->hwnd
, GW_HWNDFIRST
) == WinPos
->hwnd
)
1678 WinPos
->flags
|= SWP_NOZORDER
;
1681 else if (WinPos
->hwndInsertAfter
== HWND_BOTTOM
)
1683 if (!(Wnd
->ExStyle
& WS_EX_TOPMOST
) && IntGetWindow(WinPos
->hwnd
, GW_HWNDLAST
) == WinPos
->hwnd
)
1684 WinPos
->flags
|= SWP_NOZORDER
;
1686 else if (WinPos
->hwndInsertAfter
== HWND_TOPMOST
)
1688 if ((Wnd
->ExStyle
& WS_EX_TOPMOST
) && IntGetWindow(WinPos
->hwnd
, GW_HWNDFIRST
) == WinPos
->hwnd
)
1689 WinPos
->flags
|= SWP_NOZORDER
;
1691 else if (WinPos
->hwndInsertAfter
== HWND_NOTOPMOST
)
1693 if (!(Wnd
->ExStyle
& WS_EX_TOPMOST
))
1694 WinPos
->flags
|= SWP_NOZORDER
;
1696 else /* hwndInsertAfter must be a sibling of the window */
1700 InsAfterWnd
= ValidateHwndNoErr(WinPos
->hwndInsertAfter
);
1706 if (InsAfterWnd
->spwndParent
!= Wnd
->spwndParent
)
1708 /* Note from wine User32 Win test_SetWindowPos:
1709 "Returns TRUE also for windows that are not siblings"
1710 "Does not seem to do anything even without passing flags, still returns TRUE"
1711 "Same thing the other way around."
1712 ".. and with these windows."
1719 * We don't need to change the Z order of hwnd if it's already
1720 * inserted after hwndInsertAfter or when inserting hwnd after
1723 if ((WinPos
->hwnd
== WinPos
->hwndInsertAfter
) ||
1724 ((InsAfterWnd
->spwndNext
) && (WinPos
->hwnd
== InsAfterWnd
->spwndNext
->head
.h
)))
1726 WinPos
->flags
|= SWP_NOZORDER
;
1735 /* x and y are always screen relative */
1737 co_WinPosSetWindowPos(
1739 HWND WndInsertAfter
,
1748 RECTL NewWindowRect
;
1749 RECTL NewClientRect
;
1750 RECTL valid_rects
[2];
1751 PREGION VisBefore
= NULL
;
1752 PREGION VisBeforeJustClient
= NULL
;
1753 PREGION VisAfter
= NULL
;
1754 PREGION CopyRgn
= NULL
;
1756 RECTL OldWindowRect
, OldClientRect
;
1761 BOOL bPointerInWindow
;
1762 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1764 ASSERT_REFS_CO(Window
);
1766 /* FIXME: Get current active window from active queue. Why? since r2915. */
1768 bPointerInWindow
= IntPtInWindow(Window
, gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
);
1770 WinPos
.hwnd
= Window
->head
.h
;
1771 WinPos
.hwndInsertAfter
= WndInsertAfter
;
1776 WinPos
.flags
= flags
;
1778 if ( flags
& SWP_ASYNCWINDOWPOS
)
1781 PWINDOWPOS ppos
= ExAllocatePoolWithTag(PagedPool
, sizeof(WINDOWPOS
), USERTAG_SWP
);
1784 WinPos
.flags
&= ~SWP_ASYNCWINDOWPOS
; // Clear flag.
1786 /* Yes it's a pointer inside Win32k! */
1787 lRes
= co_IntSendMessageNoWait( WinPos
.hwnd
, WM_ASYNC_SETWINDOWPOS
, 0, (LPARAM
)ppos
);
1788 /* We handle this the same way as Event Hooks and Hooks. */
1791 ExFreePoolWithTag(ppos
, USERTAG_SWP
);
1799 co_WinPosDoWinPosChanging(Window
, &WinPos
, &NewWindowRect
, &NewClientRect
);
1801 /* Does the window still exist? */
1802 if (!IntIsWindow(WinPos
.hwnd
))
1804 TRACE("WinPosSetWindowPos: Invalid handle 0x%p!\n",WinPos
.hwnd
);
1805 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE
);
1809 /* Fix up the flags. */
1810 if (!WinPosFixupFlags(&WinPos
, Window
))
1816 Ancestor
= UserGetAncestor(Window
, GA_PARENT
);
1817 if ( (WinPos
.flags
& (SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) != SWP_NOZORDER
&&
1818 Ancestor
&& Ancestor
->head
.h
== IntGetDesktopWindow() )
1820 WinPos
.hwndInsertAfter
= WinPosDoOwnedPopups(Window
, WinPos
.hwndInsertAfter
);
1823 if (!(WinPos
.flags
& SWP_NOREDRAW
))
1825 /* Compute the visible region before the window position is changed */
1826 if (!(WinPos
.flags
& SWP_SHOWWINDOW
) &&
1827 (WinPos
.flags
& (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
|
1828 SWP_HIDEWINDOW
| SWP_FRAMECHANGED
)) !=
1829 (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
))
1831 VisBefore
= VIS_ComputeVisibleRegion(Window
, FALSE
, FALSE
,
1832 (Window
->style
& WS_CLIPSIBLINGS
) ? TRUE
: FALSE
);
1834 if ( VisBefore
!= NULL
&&
1835 REGION_Complexity(VisBefore
) == NULLREGION
)
1837 REGION_Delete(VisBefore
);
1842 REGION_bOffsetRgn(VisBefore
, -Window
->rcWindow
.left
, -Window
->rcWindow
.top
);
1845 /* Calculate the non client area for resizes, as this is used in the copy region */
1846 if (!(WinPos
.flags
& SWP_NOSIZE
))
1848 VisBeforeJustClient
= VIS_ComputeVisibleRegion(Window
, TRUE
, FALSE
,
1849 (Window
->style
& WS_CLIPSIBLINGS
) ? TRUE
: FALSE
);
1851 if ( VisBeforeJustClient
!= NULL
&&
1852 REGION_Complexity(VisBeforeJustClient
) == NULLREGION
)
1854 REGION_Delete(VisBeforeJustClient
);
1855 VisBeforeJustClient
= NULL
;
1857 else if(VisBeforeJustClient
)
1859 REGION_bOffsetRgn(VisBeforeJustClient
, -Window
->rcWindow
.left
, -Window
->rcWindow
.top
);
1865 WvrFlags
= co_WinPosDoNCCALCSize(Window
, &WinPos
, &NewWindowRect
, &NewClientRect
, valid_rects
);
1867 // ERR("co_WinPosDoNCCALCSize returned 0x%x\n valid dest: %d %d %d %d\n valid src : %d %d %d %d\n", WvrFlags,
1868 // valid_rects[0].left,valid_rects[0].top,valid_rects[0].right,valid_rects[0].bottom,
1869 // valid_rects[1].left,valid_rects[1].top,valid_rects[1].right,valid_rects[1].bottom);
1871 /* Validate link windows. (also take into account shell window in hwndShellWindow) */
1872 if (!(WinPos
.flags
& SWP_NOZORDER
) && WinPos
.hwnd
!= UserGetShellWindow())
1874 IntLinkHwnd(Window
, WinPos
.hwndInsertAfter
);
1877 OldWindowRect
= Window
->rcWindow
;
1878 OldClientRect
= Window
->rcClient
;
1880 if (NewClientRect
.left
!= OldClientRect
.left
||
1881 NewClientRect
.top
!= OldClientRect
.top
)
1883 // Move child window if their parent is moved. Keep Child window relative to Parent...
1884 WinPosInternalMoveWindow(Window
,
1885 NewClientRect
.left
- OldClientRect
.left
,
1886 NewClientRect
.top
- OldClientRect
.top
);
1889 Window
->rcWindow
= NewWindowRect
;
1890 Window
->rcClient
= NewClientRect
;
1892 /* erase parent when hiding or resizing child */
1893 if (WinPos
.flags
& SWP_HIDEWINDOW
)
1895 /* Clear the update region */
1896 co_UserRedrawWindow( Window
,
1899 RDW_VALIDATE
| RDW_NOFRAME
| RDW_NOERASE
| RDW_NOINTERNALPAINT
| RDW_ALLCHILDREN
);
1901 if (Window
->spwndParent
== UserGetDesktopWindow())
1902 co_IntShellHookNotify(HSHELL_WINDOWDESTROYED
, (WPARAM
)Window
->head
.h
, 0);
1904 Window
->style
&= ~WS_VISIBLE
; //IntSetStyle( Window, 0, WS_VISIBLE );
1905 Window
->head
.pti
->cVisWindows
--;
1906 IntNotifyWinEvent(EVENT_OBJECT_HIDE
, Window
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
1908 else if (WinPos
.flags
& SWP_SHOWWINDOW
)
1910 if (Window
->spwndParent
== UserGetDesktopWindow() &&
1911 Window
->spwndOwner
== NULL
&&
1912 (!(Window
->ExStyle
& WS_EX_TOOLWINDOW
) ||
1913 (Window
->ExStyle
& WS_EX_APPWINDOW
)))
1914 co_IntShellHookNotify(HSHELL_WINDOWCREATED
, (WPARAM
)Window
->head
.h
, 0);
1916 Window
->style
|= WS_VISIBLE
; //IntSetStyle( Window, WS_VISIBLE, 0 );
1917 Window
->head
.pti
->cVisWindows
++;
1918 IntNotifyWinEvent(EVENT_OBJECT_SHOW
, Window
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
1921 if (Window
->hrgnUpdate
!= NULL
&& Window
->hrgnUpdate
!= HRGN_WINDOW
)
1923 NtGdiOffsetRgn(Window
->hrgnUpdate
,
1924 NewWindowRect
.left
- OldWindowRect
.left
,
1925 NewWindowRect
.top
- OldWindowRect
.top
);
1928 DceResetActiveDCEs(Window
); // For WS_VISIBLE changes.
1930 if (!(WinPos
.flags
& SWP_NOREDRAW
))
1932 /* Determine the new visible region */
1933 VisAfter
= VIS_ComputeVisibleRegion(Window
, FALSE
, FALSE
,
1934 (Window
->style
& WS_CLIPSIBLINGS
) ? TRUE
: FALSE
);
1936 if ( VisAfter
!= NULL
&&
1937 REGION_Complexity(VisAfter
) == NULLREGION
)
1939 REGION_Delete(VisAfter
);
1944 REGION_bOffsetRgn(VisAfter
, -Window
->rcWindow
.left
, -Window
->rcWindow
.top
);
1948 * Determine which pixels can be copied from the old window position
1949 * to the new. Those pixels must be visible in both the old and new
1950 * position. Also, check the class style to see if the windows of this
1951 * class need to be completely repainted on (horizontal/vertical) size
1954 if ( VisBefore
!= NULL
&&
1956 !(WinPos
.flags
& SWP_NOCOPYBITS
) &&
1957 ((WinPos
.flags
& SWP_NOSIZE
) || !(WvrFlags
& WVR_REDRAW
)) &&
1958 !(Window
->ExStyle
& WS_EX_TRANSPARENT
) )
1962 * If this is (also) a window resize, the whole nonclient area
1963 * needs to be repainted. So we limit the copy to the client area,
1964 * 'cause there is no use in copying it (would possibly cause
1965 * "flashing" too). However, if the copy region is already empty,
1966 * we don't have to crop (can't take anything away from an empty
1970 CopyRgn
= IntSysCreateRectpRgn(0, 0, 0, 0);
1971 if (WinPos
.flags
& SWP_NOSIZE
)
1972 RgnType
= IntGdiCombineRgn(CopyRgn
, VisAfter
, VisBefore
, RGN_AND
);
1973 else if (VisBeforeJustClient
!= NULL
)
1975 RgnType
= IntGdiCombineRgn(CopyRgn
, VisAfter
, VisBeforeJustClient
, RGN_AND
);
1976 REGION_Delete(VisBeforeJustClient
);
1979 /* No use in copying bits which are in the update region. */
1980 if (Window
->hrgnUpdate
!= NULL
)
1982 PREGION RgnUpdate
= REGION_LockRgn(Window
->hrgnUpdate
);
1985 REGION_bOffsetRgn(CopyRgn
, NewWindowRect
.left
, NewWindowRect
.top
);
1986 IntGdiCombineRgn(CopyRgn
, CopyRgn
, RgnUpdate
, RGN_DIFF
);
1987 REGION_bOffsetRgn(CopyRgn
, -NewWindowRect
.left
, -NewWindowRect
.top
);
1988 REGION_UnlockRgn(RgnUpdate
);
1993 * Now, get the bounding box of the copy region. If it's empty
1994 * there's nothing to copy. Also, it's no use copying bits onto
1997 if (REGION_GetRgnBox(CopyRgn
, &CopyRect
) == NULLREGION
)
1999 /* Nothing to copy, clean up */
2000 REGION_Delete(CopyRgn
);
2003 else if (OldWindowRect
.left
!= NewWindowRect
.left
||
2004 OldWindowRect
.top
!= NewWindowRect
.top
)
2006 HRGN DcRgn
= NtGdiCreateRectRgn(0, 0, 0, 0);
2007 PREGION DcRgnObj
= REGION_LockRgn(DcRgn
);
2010 * Small trick here: there is no function to bitblt a region. So
2011 * we set the region as the clipping region, take the bounding box
2012 * of the region and bitblt that. Since nothing outside the clipping
2013 * region is copied, this has the effect of bitblt'ing the region.
2015 * Since NtUserGetDCEx takes ownership of the clip region, we need
2016 * to create a copy of CopyRgn and pass that. We need CopyRgn later
2018 IntGdiCombineRgn(DcRgnObj
, CopyRgn
, NULL
, RGN_COPY
);
2019 REGION_bOffsetRgn(DcRgnObj
, NewWindowRect
.left
, NewWindowRect
.top
);
2020 REGION_UnlockRgn(DcRgnObj
);
2021 Dc
= UserGetDCEx( Window
,
2023 DCX_WINDOW
|DCX_CACHE
|DCX_INTERSECTRGN
|DCX_CLIPSIBLINGS
|DCX_KEEPCLIPRGN
);
2025 CopyRect
.left
, CopyRect
.top
,
2026 CopyRect
.right
- CopyRect
.left
,
2027 CopyRect
.bottom
- CopyRect
.top
,
2029 CopyRect
.left
+ (OldWindowRect
.left
- NewWindowRect
.left
),
2030 CopyRect
.top
+ (OldWindowRect
.top
- NewWindowRect
.top
),
2035 UserReleaseDC(Window
, Dc
, FALSE
);
2036 IntValidateParent(Window
, CopyRgn
);
2037 GreDeleteObject(DcRgn
);
2045 /* We need to redraw what wasn't visible before */
2046 if (VisAfter
!= NULL
)
2048 PREGION DirtyRgn
= IntSysCreateRectpRgn(0, 0, 0, 0);
2051 if (CopyRgn
!= NULL
)
2053 RgnType
= IntGdiCombineRgn(DirtyRgn
, VisAfter
, CopyRgn
, RGN_DIFF
);
2057 RgnType
= IntGdiCombineRgn(DirtyRgn
, VisAfter
, 0, RGN_COPY
);
2060 if (RgnType
!= ERROR
&& RgnType
!= NULLREGION
)
2063 NtGdiOffsetRgn(DirtyRgn, Window->rcWindow.left, Window->rcWindow.top);
2064 IntInvalidateWindows( Window,
2066 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
2068 GreDeleteObject(DirtyRgn);
2071 PWND Parent
= Window
->spwndParent
;
2073 REGION_bOffsetRgn( DirtyRgn
, Window
->rcWindow
.left
, Window
->rcWindow
.top
);
2075 if ( (Window
->style
& WS_CHILD
) && (Parent
) && !(Parent
->style
& WS_CLIPCHILDREN
))
2077 IntInvalidateWindows( Parent
, DirtyRgn
, RDW_ERASE
| RDW_INVALIDATE
);
2078 co_IntPaintWindows(Parent
, RDW_NOCHILDREN
, FALSE
);
2082 IntInvalidateWindows( Window
, DirtyRgn
, RDW_ERASE
| RDW_FRAME
| RDW_INVALIDATE
| RDW_ALLCHILDREN
);
2085 REGION_Delete(DirtyRgn
);
2089 if (CopyRgn
!= NULL
)
2091 REGION_Delete(CopyRgn
);
2094 /* Expose what was covered before but not covered anymore */
2095 if (VisBefore
!= NULL
)
2097 PREGION ExposedRgn
= IntSysCreateRectpRgn(0, 0, 0, 0);
2100 RgnType
= IntGdiCombineRgn(ExposedRgn
, VisBefore
, NULL
, RGN_COPY
);
2101 REGION_bOffsetRgn(ExposedRgn
,
2102 OldWindowRect
.left
- NewWindowRect
.left
,
2103 OldWindowRect
.top
- NewWindowRect
.top
);
2105 if (VisAfter
!= NULL
)
2106 RgnType
= IntGdiCombineRgn(ExposedRgn
, ExposedRgn
, VisAfter
, RGN_DIFF
);
2108 if (RgnType
!= ERROR
&& RgnType
!= NULLREGION
)
2110 co_VIS_WindowLayoutChanged(Window
, ExposedRgn
);
2112 REGION_Delete(ExposedRgn
);
2114 REGION_Delete(VisBefore
);
2117 if (VisAfter
!= NULL
)
2119 REGION_Delete(VisAfter
);
2123 if (!(WinPos
.flags
& (SWP_NOACTIVATE
|SWP_HIDEWINDOW
)))
2125 if ((Window
->style
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
2127 co_IntSendMessageNoWait(WinPos
.hwnd
, WM_CHILDACTIVATE
, 0, 0);
2129 /* Do not allow setting if already active.
2130 Fix A : wine msg test_SetParent:WmSetParentSeq_2:25 msg!
2131 Recursion broke the tests.
2133 else if ( pti
->MessageQueue
->spwndActive
!= Window
||
2134 pti
->MessageQueue
!= gpqForeground
) // This fixes the breakage at boot time caused by the above line!
2136 // Inside SAW? Fixes Api AttachThreadInput tests.
2137 TRACE("SetWindowPos Set FG Window! hWnd %p\n",WinPos
.hwnd
);
2138 if (!(Window
->state
& WNDS_BEINGACTIVATED
))
2140 TRACE("SetWindowPos Set FG Window!\n");
2141 // Fixes SW_HIDE issues. Wine win test_SetActiveWindow & test_SetForegroundWindow.
2142 co_IntSetForegroundWindow(Window
);
2147 // Fix wine msg test_SetFocus, prevents sending WM_WINDOWPOSCHANGED.
2148 if ( VisBefore
== NULL
&&
2149 VisBeforeJustClient
== NULL
&&
2150 !(Window
->ExStyle
& WS_EX_TOPMOST
) &&
2151 (WinPos
.flags
& SWP_AGG_STATUSFLAGS
) == (SWP_AGG_NOPOSCHANGE
& ~SWP_NOZORDER
))
2153 TRACE("No drawing, set no Z order and no redraw!\n");
2154 WinPos
.flags
|= SWP_NOZORDER
|SWP_NOREDRAW
;
2157 /* And last, send the WM_WINDOWPOSCHANGED message */
2159 TRACE("\tstatus hwnd %p flags = %04x\n",Window
?Window
->head
.h
:NULL
,WinPos
.flags
& SWP_AGG_STATUSFLAGS
);
2161 if ((WinPos
.flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOPOSCHANGE
)
2163 /* WM_WINDOWPOSCHANGED is sent even if SWP_NOSENDCHANGING is set
2164 and always contains final window position.
2166 WinPos
.x
= NewWindowRect
.left
;
2167 WinPos
.y
= NewWindowRect
.top
;
2168 WinPos
.cx
= NewWindowRect
.right
- NewWindowRect
.left
;
2169 WinPos
.cy
= NewWindowRect
.bottom
- NewWindowRect
.top
;
2170 TRACE("WM_WINDOWPOSCHANGED hwnd %p Flags %04x\n",WinPos
.hwnd
,WinPos
.flags
);
2171 co_IntSendMessageNoWait(WinPos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
) &WinPos
);
2174 if ( WinPos
.flags
& SWP_FRAMECHANGED
|| WinPos
.flags
& SWP_STATECHANGED
||
2175 !(WinPos
.flags
& SWP_NOCLIENTSIZE
) || !(WinPos
.flags
& SWP_NOCLIENTMOVE
) )
2177 PWND pWnd
= ValidateHwndNoErr(WinPos
.hwnd
);
2179 IntNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE
, pWnd
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
2182 if(bPointerInWindow
!= IntPtInWindow(Window
, gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
))
2184 /* Generate mouse move message */
2186 msg
.message
= WM_MOUSEMOVE
;
2187 msg
.wParam
= UserGetMouseButtonsState();
2188 msg
.lParam
= MAKELPARAM(gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
);
2189 msg
.pt
= gpsi
->ptCursor
;
2190 co_MsqInsertMouseMessage(&msg
, 0, 0, TRUE
);
2197 co_WinPosGetNonClientSize(PWND Window
, RECT
* WindowRect
, RECT
* ClientRect
)
2201 ASSERT_REFS_CO(Window
);
2203 *ClientRect
= *WindowRect
;
2204 Result
= co_IntSendMessageNoWait(Window
->head
.h
, WM_NCCALCSIZE
, FALSE
, (LPARAM
) ClientRect
);
2206 FixClientRect(ClientRect
, WindowRect
);
2212 co_WinPosSendSizeMove(PWND Wnd
)
2216 WPARAM wParam
= SIZE_RESTORED
;
2218 IntGetClientRect(Wnd
, &Rect
);
2219 lParam
= MAKELONG(Rect
.right
-Rect
.left
, Rect
.bottom
-Rect
.top
);
2221 Wnd
->state
&= ~WNDS_SENDSIZEMOVEMSGS
;
2223 if (Wnd
->style
& WS_MAXIMIZE
)
2225 wParam
= SIZE_MAXIMIZED
;
2227 else if (Wnd
->style
& WS_MINIMIZE
)
2229 wParam
= SIZE_MINIMIZED
;
2233 co_IntSendMessageNoWait(UserHMGetHandle(Wnd
), WM_SIZE
, wParam
, lParam
);
2235 if (Wnd
->spwndParent
== UserGetDesktopWindow()) // Wnd->spwndParent->fnid == FNID_DESKTOP )
2236 lParam
= MAKELONG(Wnd
->rcClient
.left
, Wnd
->rcClient
.top
);
2238 lParam
= MAKELONG(Wnd
->rcClient
.left
-Wnd
->spwndParent
->rcClient
.left
, Wnd
->rcClient
.top
-Wnd
->spwndParent
->rcClient
.top
);
2240 co_IntSendMessageNoWait(UserHMGetHandle(Wnd
), WM_MOVE
, 0, lParam
);
2242 IntEngWindowChanged(Wnd
, WOC_RGN_CLIENT
);
2246 ShowWindow does not set SWP_FRAMECHANGED!!! Fix wine msg test_SetParent:WmSetParentSeq_2:23 wParam bits!
2249 co_WinPosShowWindow(PWND Wnd
, INT Cmd
)
2252 UINT Swp
= 0, EventMsg
= 0;
2253 RECTL NewPos
= {0, 0, 0, 0};
2259 BOOL ShowOwned
= FALSE
;
2260 BOOL FirstTime
= FALSE
;
2261 ASSERT_REFS_CO(Wnd
);
2262 //KeRosDumpStackFrames(NULL, 20);
2263 pti
= PsGetCurrentThreadWin32Thread();
2264 WasVisible
= (Wnd
->style
& WS_VISIBLE
) != 0;
2267 TRACE("co_WinPosShowWindow START hwnd %p Cmd %d usicmd %u\n",
2268 Wnd
->head
.h
, Cmd
, pti
->ppi
->usi
.wShowWindow
);
2270 if ( pti
->ppi
->usi
.dwFlags
& STARTF_USESHOWWINDOW
)
2272 if ((Wnd
->style
& (WS_POPUP
|WS_CHILD
)) != WS_CHILD
)
2274 if ((Wnd
->style
& WS_CAPTION
) == WS_CAPTION
)
2276 if (Wnd
->spwndOwner
== NULL
)
2278 if ( Cmd
== SW_SHOWNORMAL
|| Cmd
== SW_SHOW
)
2280 Cmd
= SW_SHOWDEFAULT
;
2283 TRACE("co_WPSW FT 1\n");
2289 if ( Cmd
== SW_SHOWDEFAULT
)
2291 if ( pti
->ppi
->usi
.dwFlags
& STARTF_USESHOWWINDOW
)
2293 Cmd
= pti
->ppi
->usi
.wShowWindow
;
2295 TRACE("co_WPSW FT 2\n");
2301 pti
->ppi
->usi
.dwFlags
&= ~(STARTF_USEPOSITION
|STARTF_USESIZE
|STARTF_USESHOWWINDOW
);
2310 //ERR("co_WinPosShowWindow Exit Bad\n");
2313 Swp
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
2314 if (Wnd
!= pti
->MessageQueue
->spwndActive
)
2315 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2319 case SW_FORCEMINIMIZE
: /* FIXME: Does not work if thread is hung. */
2320 case SW_SHOWMINNOACTIVE
:
2321 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2323 case SW_SHOWMINIMIZED
:
2324 Swp
|= SWP_SHOWWINDOW
;
2328 Swp
|= SWP_NOACTIVATE
;
2329 if (!(style
& WS_MINIMIZE
))
2331 IntShowOwnedPopups(Wnd
, FALSE
);
2332 // Fix wine Win test_SetFocus todo #1 & #2,
2333 if (Cmd
== SW_SHOWMINIMIZED
)
2335 //ERR("co_WinPosShowWindow Set focus 1\n");
2336 if ((style
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
2337 co_UserSetFocus(Wnd
->spwndParent
);
2342 Swp
|= co_WinPosMinMaximize(Wnd
, Cmd
, &NewPos
);
2344 EventMsg
= EVENT_SYSTEM_MINIMIZESTART
;
2350 //ERR("co_WinPosShowWindow Exit Good\n");
2353 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
2358 case SW_SHOWMAXIMIZED
:
2360 Swp
|= SWP_SHOWWINDOW
;
2361 if (!(style
& WS_MAXIMIZE
))
2365 Swp
|= co_WinPosMinMaximize(Wnd
, SW_MAXIMIZE
, &NewPos
);
2367 EventMsg
= EVENT_SYSTEM_MINIMIZEEND
;
2373 //ERR("co_WinPosShowWindow Exit Good 1\n");
2376 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
2382 Swp
|= SWP_NOACTIVATE
| SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
2383 if (style
& WS_CHILD
&& !(Wnd
->ExStyle
& WS_EX_MDICHILD
)) Swp
|= SWP_NOZORDER
;
2386 if (WasVisible
) return(TRUE
); // Nothing to do!
2387 Swp
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
2388 /* Don't activate the topmost window. */
2389 if (style
& WS_CHILD
&& !(Wnd
->ExStyle
& WS_EX_MDICHILD
)) Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2392 case SW_SHOWNOACTIVATE
:
2393 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2396 case SW_SHOWDEFAULT
:
2398 if (!WasVisible
) Swp
|= SWP_SHOWWINDOW
;
2399 if (style
& (WS_MINIMIZE
| WS_MAXIMIZE
))
2401 Swp
|= co_WinPosMinMaximize(Wnd
, Cmd
, &NewPos
);
2402 if (style
& WS_MINIMIZE
) EventMsg
= EVENT_SYSTEM_MINIMIZEEND
;
2408 //ERR("co_WinPosShowWindow Exit Good 3\n");
2411 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
2413 if ( style
& WS_CHILD
&&
2414 !(Wnd
->ExStyle
& WS_EX_MDICHILD
) &&
2415 !(Swp
& SWP_STATECHANGED
))
2416 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2420 //ERR("co_WinPosShowWindow Exit Good 4\n");
2424 ShowFlag
= (Cmd
!= SW_HIDE
);
2426 if ((ShowFlag
!= WasVisible
|| Cmd
== SW_SHOWNA
) && Cmd
!= SW_SHOWMAXIMIZED
&& !(Swp
& SWP_STATECHANGED
))
2428 co_IntSendMessageNoWait(Wnd
->head
.h
, WM_SHOWWINDOW
, ShowFlag
, 0);
2429 #if 0 // Fix wine msg test_SetParent:WmSetParentSeq_1:2
2430 if (!(Wnd
->state2
& WNDS2_WIN31COMPAT
)) // <------------- XP sets this bit!
2431 co_IntSendMessageNoWait(Wnd
->head
.h
, WM_SETVISIBLE
, ShowFlag
, 0);
2433 if (!VerifyWnd(Wnd
)) return WasVisible
;
2436 /* We can't activate a child window */
2437 if ((Wnd
->style
& WS_CHILD
) &&
2438 !(Wnd
->ExStyle
& WS_EX_MDICHILD
) &&
2441 //ERR("SWP Child No active and ZOrder\n");
2442 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2445 #if 0 // Explorer issues with common controls? Someone does not know how CS_SAVEBITS works.
2446 // Breaks startup and shutdown active window...
2447 if ((Wnd
->style
& (WS_POPUP
|WS_CHILD
)) != WS_CHILD
&&
2448 Wnd
->pcls
->style
& CS_SAVEBITS
&&
2449 ((Cmd
== SW_SHOW
) || (Cmd
== SW_NORMAL
)))
2451 ERR("WinPosShowWindow Set active\n");
2452 UserSetActiveWindow(Wnd
);
2453 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2457 if (IsChildVisible(Wnd
) || Swp
& SWP_STATECHANGED
)
2459 TRACE("Child is Vis %s or State changed %s. ShowFlag %s Swp %04x\n",
2460 (IsChildVisible(Wnd
) ? "TRUE" : "FALSE"), (Swp
& SWP_STATECHANGED
? "TRUE" : "FALSE"),
2461 (ShowFlag
? "TRUE" : "FALSE"),LOWORD(Swp
));
2462 co_WinPosSetWindowPos( Wnd
,
2463 0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
) ? HWND_TOPMOST
: HWND_TOP
,
2466 NewPos
.right
, // NewPos.right - NewPos.left, when minimized and restore, the window becomes smaller.
2467 NewPos
.bottom
,// NewPos.bottom - NewPos.top,
2472 TRACE("Parent Vis?\n");
2473 /* if parent is not visible simply toggle WS_VISIBLE and return */
2474 if (ShowFlag
) IntSetStyle( Wnd
, WS_VISIBLE
, 0 );
2475 else IntSetStyle( Wnd
, 0, WS_VISIBLE
);
2478 if ( EventMsg
) IntNotifyWinEvent(EventMsg
, Wnd
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
2480 if ( ShowOwned
) IntShowOwnedPopups(Wnd
, TRUE
);
2482 if ((Cmd
== SW_HIDE
) || (Cmd
== SW_MINIMIZE
))
2484 if ( Wnd
== pti
->MessageQueue
->spwndActive
&& pti
->MessageQueue
== IntGetFocusMessageQueue() )
2486 if ( Wnd
->spwndParent
== UserGetDesktopWindow())
2488 if (!ActivateOtherWindowMin(Wnd
))
2490 co_WinPosActivateOtherWindow(Wnd
);
2495 co_WinPosActivateOtherWindow(Wnd
);
2499 /* Revert focus to parent */
2500 if (Wnd
== pti
->MessageQueue
->spwndFocus
)
2502 Parent
= Wnd
->spwndParent
;
2503 if (Wnd
->spwndParent
== UserGetDesktopWindow()) Parent
= 0;
2504 co_UserSetFocus(Parent
);
2506 // Hide, just return.
2507 if (Cmd
== SW_HIDE
) return WasVisible
;
2510 /* FIXME: Check for window destruction. */
2512 if ((Wnd
->state
& WNDS_SENDSIZEMOVEMSGS
) &&
2513 !(Wnd
->state2
& WNDS2_INDESTROY
))
2515 co_WinPosSendSizeMove(Wnd
);
2518 /* if previous state was minimized Windows sets focus to the window */
2519 if (style
& WS_MINIMIZE
)
2521 co_UserSetFocus(Wnd
);
2522 // Fix wine Win test_SetFocus todo #3,
2523 if (!(style
& WS_CHILD
)) co_IntSendMessageNoWait(UserHMGetHandle(Wnd
), WM_ACTIVATE
, WA_ACTIVE
, 0);
2525 //ERR("co_WinPosShowWindow EXIT\n");
2530 co_WinPosSearchChildren(
2533 IN OUT USHORT
*HitTest
,
2538 PWND pwndChild
= NULL
;
2541 if (!(ScopeWin
->style
& WS_VISIBLE
))
2546 /* not in window or in window region */
2547 if (!IntPtInWindow(ScopeWin
, Point
->x
, Point
->y
))
2553 if ((ScopeWin
->ExStyle
& (WS_EX_LAYERED
|WS_EX_TRANSPARENT
)) == (WS_EX_LAYERED
|WS_EX_TRANSPARENT
))
2558 if (!Ignore
&& (ScopeWin
->style
& WS_DISABLED
))
2559 { /* disabled child */
2560 if ((ScopeWin
->style
& (WS_POPUP
|WS_CHILD
)) == WS_CHILD
) return NULL
;
2561 /* process the hit error */
2566 /* not minimized and check if point is inside the window */
2567 if (!(ScopeWin
->style
& WS_MINIMIZE
) &&
2568 RECTL_bPointInRect(&ScopeWin
->rcClient
, Point
->x
, Point
->y
) )
2570 UserReferenceObject(ScopeWin
);
2572 List
= IntWinListChildren(ScopeWin
);
2575 for (phWnd
= List
; *phWnd
; ++phWnd
)
2577 if (!(pwndChild
= ValidateHwndNoErr(*phWnd
)))
2582 pwndChild
= co_WinPosSearchChildren(pwndChild
, Point
, HitTest
, Ignore
);
2584 if (pwndChild
!= NULL
)
2586 /* We found a window. Don't send any more WM_NCHITTEST messages */
2587 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2588 UserDereferenceObject(ScopeWin
);
2592 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2594 UserDereferenceObject(ScopeWin
);
2597 if (ScopeWin
->head
.pti
== PsGetCurrentThreadWin32Thread())
2599 *HitTest
= (USHORT
)co_IntSendMessage(ScopeWin
->head
.h
, WM_NCHITTEST
, 0, MAKELONG(Point
->x
, Point
->y
));
2601 if ((*HitTest
) == (USHORT
)HTTRANSPARENT
)
2608 if (*HitTest
== HTNOWHERE
&& pwndChild
== NULL
) *HitTest
= HTCLIENT
;
2615 co_WinPosWindowFromPoint(
2618 IN OUT USHORT
* HitTest
,
2622 POINT Point
= *WinPoint
;
2623 USER_REFERENCE_ENTRY Ref
;
2625 if( ScopeWin
== NULL
)
2627 ScopeWin
= UserGetDesktopWindow();
2628 if(ScopeWin
== NULL
)
2632 *HitTest
= HTNOWHERE
;
2634 ASSERT_REFS_CO(ScopeWin
);
2635 UserRefObjectCo(ScopeWin
, &Ref
);
2637 Window
= co_WinPosSearchChildren(ScopeWin
, &Point
, HitTest
, Ignore
);
2639 UserDerefObjectCo(ScopeWin
);
2641 ASSERT_REFS_CO(Window
);
2642 ASSERT_REFS_CO(ScopeWin
);
2648 IntRealChildWindowFromPoint(PWND Parent
, LONG x
, LONG y
)
2652 PWND pwndHit
= NULL
;
2657 if (Parent
!= UserGetDesktopWindow())
2659 Pt
.x
+= Parent
->rcClient
.left
;
2660 Pt
.y
+= Parent
->rcClient
.top
;
2663 if (!IntPtInWindow(Parent
, Pt
.x
, Pt
.y
)) return NULL
;
2665 if ((List
= IntWinListChildren(Parent
)))
2667 for (phWnd
= List
; *phWnd
; phWnd
++)
2670 if ((Child
= ValidateHwndNoErr(*phWnd
)))
2672 if ( Child
->style
& WS_VISIBLE
&& IntPtInWindow(Child
, Pt
.x
, Pt
.y
) )
2674 if ( Child
->pcls
->atomClassName
!= gpsi
->atomSysClass
[ICLS_BUTTON
] ||
2675 (Child
->style
& BS_TYPEMASK
) != BS_GROUPBOX
)
2677 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2684 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2686 return pwndHit
? pwndHit
: Parent
;
2690 IntChildWindowFromPointEx(PWND Parent
, LONG x
, LONG y
, UINT uiFlags
)
2694 PWND pwndHit
= NULL
;
2699 if (Parent
!= UserGetDesktopWindow())
2701 if (Parent
->ExStyle
& WS_EX_LAYOUTRTL
)
2702 Pt
.x
= Parent
->rcClient
.right
- Pt
.x
;
2704 Pt
.x
+= Parent
->rcClient
.left
;
2705 Pt
.y
+= Parent
->rcClient
.top
;
2708 if (!IntPtInWindow(Parent
, Pt
.x
, Pt
.y
)) return NULL
;
2710 if ((List
= IntWinListChildren(Parent
)))
2712 for (phWnd
= List
; *phWnd
; phWnd
++)
2715 if ((Child
= ValidateHwndNoErr(*phWnd
)))
2717 if (uiFlags
& (CWP_SKIPINVISIBLE
|CWP_SKIPDISABLED
))
2719 if (!(Child
->style
& WS_VISIBLE
) && (uiFlags
& CWP_SKIPINVISIBLE
)) continue;
2720 if ((Child
->style
& WS_DISABLED
) && (uiFlags
& CWP_SKIPDISABLED
)) continue;
2723 if (uiFlags
& CWP_SKIPTRANSPARENT
)
2725 if (Child
->ExStyle
& WS_EX_TRANSPARENT
) continue;
2728 if (IntPtInWindow(Child
, Pt
.x
, Pt
.y
))
2735 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2737 return pwndHit
? pwndHit
: Parent
;
2742 IntDeferWindowPos( HDWP hdwp
,
2753 HDWP retvalue
= hdwp
;
2755 TRACE("hdwp %p, hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
2756 hdwp
, hwnd
, hwndAfter
, x
, y
, cx
, cy
, flags
);
2758 if (flags
& ~(SWP_NOSIZE
| SWP_NOMOVE
|
2759 SWP_NOZORDER
| SWP_NOREDRAW
|
2760 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
2761 SWP_NOOWNERZORDER
|SWP_SHOWWINDOW
|
2762 SWP_HIDEWINDOW
| SWP_FRAMECHANGED
))
2764 EngSetLastError(ERROR_INVALID_PARAMETER
);
2768 if (!(pDWP
= (PSMWP
)UserGetObject(gHandleTable
, hdwp
, TYPE_SETWINDOWPOS
)))
2770 EngSetLastError(ERROR_INVALID_DWP_HANDLE
);
2774 for (i
= 0; i
< pDWP
->ccvr
; i
++)
2776 if (pDWP
->acvr
[i
].pos
.hwnd
== hwnd
)
2778 /* Merge with the other changes */
2779 if (!(flags
& SWP_NOZORDER
))
2781 pDWP
->acvr
[i
].pos
.hwndInsertAfter
= hwndAfter
;
2783 if (!(flags
& SWP_NOMOVE
))
2785 pDWP
->acvr
[i
].pos
.x
= x
;
2786 pDWP
->acvr
[i
].pos
.y
= y
;
2788 if (!(flags
& SWP_NOSIZE
))
2790 pDWP
->acvr
[i
].pos
.cx
= cx
;
2791 pDWP
->acvr
[i
].pos
.cy
= cy
;
2793 pDWP
->acvr
[i
].pos
.flags
&= flags
| ~(SWP_NOSIZE
| SWP_NOMOVE
|
2794 SWP_NOZORDER
| SWP_NOREDRAW
|
2795 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
2797 pDWP
->acvr
[i
].pos
.flags
|= flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
|
2802 if (pDWP
->ccvr
>= pDWP
->ccvrAlloc
)
2804 PCVR newpos
= ExAllocatePoolWithTag(PagedPool
, pDWP
->ccvrAlloc
* 2 * sizeof(CVR
), USERTAG_SWP
);
2810 RtlZeroMemory(newpos
, pDWP
->ccvrAlloc
* 2 * sizeof(CVR
));
2811 RtlCopyMemory(newpos
, pDWP
->acvr
, pDWP
->ccvrAlloc
* sizeof(CVR
));
2812 ExFreePoolWithTag(pDWP
->acvr
, USERTAG_SWP
);
2813 pDWP
->ccvrAlloc
*= 2;
2814 pDWP
->acvr
= newpos
;
2816 pDWP
->acvr
[pDWP
->ccvr
].pos
.hwnd
= hwnd
;
2817 pDWP
->acvr
[pDWP
->ccvr
].pos
.hwndInsertAfter
= hwndAfter
;
2818 pDWP
->acvr
[pDWP
->ccvr
].pos
.x
= x
;
2819 pDWP
->acvr
[pDWP
->ccvr
].pos
.y
= y
;
2820 pDWP
->acvr
[pDWP
->ccvr
].pos
.cx
= cx
;
2821 pDWP
->acvr
[pDWP
->ccvr
].pos
.cy
= cy
;
2822 pDWP
->acvr
[pDWP
->ccvr
].pos
.flags
= flags
;
2823 pDWP
->acvr
[pDWP
->ccvr
].hrgnClip
= NULL
;
2824 pDWP
->acvr
[pDWP
->ccvr
].hrgnInterMonitor
= NULL
;
2830 BOOL FASTCALL
IntEndDeferWindowPosEx( HDWP hdwp
, BOOL sAsync
)
2837 TRACE("%p\n", hdwp
);
2839 if (!(pDWP
= (PSMWP
)UserGetObject(gHandleTable
, hdwp
, TYPE_SETWINDOWPOS
)))
2841 EngSetLastError(ERROR_INVALID_DWP_HANDLE
);
2845 for (i
= 0, winpos
= pDWP
->acvr
; res
&& i
< pDWP
->ccvr
; i
++, winpos
++)
2848 USER_REFERENCE_ENTRY Ref
;
2850 TRACE("hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
2851 winpos
->pos
.hwnd
, winpos
->pos
.hwndInsertAfter
, winpos
->pos
.x
, winpos
->pos
.y
,
2852 winpos
->pos
.cx
, winpos
->pos
.cy
, winpos
->pos
.flags
);
2854 pwnd
= ValidateHwndNoErr(winpos
->pos
.hwnd
);
2858 UserRefObjectCo(pwnd
, &Ref
);
2863 PWINDOWPOS ppos
= ExAllocatePoolWithTag(PagedPool
, sizeof(WINDOWPOS
), USERTAG_SWP
);
2866 *ppos
= winpos
->pos
;
2867 /* Yes it's a pointer inside Win32k! */
2868 lRes
= co_IntSendMessageNoWait( winpos
->pos
.hwnd
, WM_ASYNC_SETWINDOWPOS
, 0, (LPARAM
)ppos
);
2869 /* We handle this the same way as Event Hooks and Hooks. */
2872 ExFreePoolWithTag(ppos
, USERTAG_SWP
);
2877 res
= co_WinPosSetWindowPos( pwnd
,
2878 winpos
->pos
.hwndInsertAfter
,
2885 // Hack to pass tests.... Must have some work to do so clear the error.
2886 if (res
&& (winpos
->pos
.flags
& (SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOZORDER
)) == SWP_NOZORDER
)
2887 EngSetLastError(ERROR_SUCCESS
);
2889 UserDerefObjectCo(pwnd
);
2891 ExFreePoolWithTag(pDWP
->acvr
, USERTAG_SWP
);
2892 UserDereferenceObject(pDWP
);
2893 UserDeleteObject(hdwp
, TYPE_SETWINDOWPOS
);
2901 NtUserChildWindowFromPointEx(HWND hwndParent
,
2907 TRACE("Enter NtUserChildWindowFromPointEx\n");
2908 UserEnterExclusive();
2909 if ((pwndParent
= UserGetWindowObject(hwndParent
)))
2911 pwndParent
= IntChildWindowFromPointEx(pwndParent
, x
, y
, uiFlags
);
2914 TRACE("Leave NtUserChildWindowFromPointEx\n");
2915 return pwndParent
? UserHMGetHandle(pwndParent
) : NULL
;
2922 NtUserEndDeferWindowPosEx(HDWP WinPosInfo
,
2926 TRACE("Enter NtUserEndDeferWindowPosEx\n");
2927 UserEnterExclusive();
2928 Ret
= IntEndDeferWindowPosEx(WinPosInfo
, (BOOL
)Unknown1
);
2929 TRACE("Leave NtUserEndDeferWindowPosEx, ret=%i\n", Ret
);
2938 NtUserDeferWindowPos(HDWP WinPosInfo
,
2940 HWND WndInsertAfter
,
2949 UINT Tmp
= ~(SWP_ASYNCWINDOWPOS
|SWP_DEFERERASE
|SWP_NOSENDCHANGING
|SWP_NOREPOSITION
|
2950 SWP_NOCOPYBITS
|SWP_HIDEWINDOW
|SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|
2951 SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_NOZORDER
|SWP_NOMOVE
|SWP_NOSIZE
);
2953 TRACE("Enter NtUserDeferWindowPos\n");
2954 UserEnterExclusive();
2958 EngSetLastError(ERROR_INVALID_FLAGS
);
2962 pWnd
= UserGetWindowObject(Wnd
);
2963 if ( !pWnd
|| // FIXME:
2964 pWnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
2965 pWnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
2970 if ( WndInsertAfter
&&
2971 WndInsertAfter
!= HWND_BOTTOM
&&
2972 WndInsertAfter
!= HWND_TOPMOST
&&
2973 WndInsertAfter
!= HWND_NOTOPMOST
)
2975 pWndIA
= UserGetWindowObject(WndInsertAfter
);
2977 pWndIA
== UserGetDesktopWindow() ||
2978 pWndIA
== UserGetMessageWindow() )
2984 Ret
= IntDeferWindowPos(WinPosInfo
, Wnd
, WndInsertAfter
, x
, y
, cx
, cy
, Flags
);
2987 TRACE("Leave NtUserDeferWindowPos, ret=%p\n", Ret
);
2996 NtUserGetInternalWindowPos( HWND hWnd
,
3003 WINDOWPLACEMENT wndpl
;
3007 if (!(Window
= UserGetWindowObject(hWnd
)))
3017 ProbeForWrite(rectWnd
,
3023 ProbeForWrite(ptIcon
,
3029 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3031 SetLastNtError(_SEH2_GetExceptionCode());
3036 wndpl
.length
= sizeof(WINDOWPLACEMENT
);
3038 if (IntGetWindowPlacement(Window
, &wndpl
) && !Hit
)
3044 RtlCopyMemory(rectWnd
, &wndpl
.rcNormalPosition
, sizeof(RECT
));
3048 RtlCopyMemory(ptIcon
, &wndpl
.ptMinPosition
, sizeof(POINT
));
3052 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3054 SetLastNtError(_SEH2_GetExceptionCode());
3059 if (!Hit
) Ret
= wndpl
.showCmd
;
3070 NtUserGetWindowPlacement(HWND hWnd
,
3071 WINDOWPLACEMENT
*lpwndpl
)
3074 WINDOWPLACEMENT Safepl
;
3076 DECLARE_RETURN(BOOL
);
3078 TRACE("Enter NtUserGetWindowPlacement\n");
3081 if (!(Wnd
= UserGetWindowObject(hWnd
)))
3086 Status
= MmCopyFromCaller(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
3087 if (!NT_SUCCESS(Status
))
3089 SetLastNtError(Status
);
3093 Safepl
.length
= sizeof(WINDOWPLACEMENT
);
3095 IntGetWindowPlacement(Wnd
, &Safepl
);
3097 Status
= MmCopyToCaller(lpwndpl
, &Safepl
, sizeof(WINDOWPLACEMENT
));
3098 if (!NT_SUCCESS(Status
))
3100 SetLastNtError(Status
);
3107 TRACE("Leave NtUserGetWindowPlacement, ret=%i\n",_ret_
);
3116 UINT cmd
, // Wine SW_ commands
3121 TRACE("Enter NtUserMinMaximize\n");
3122 UserEnterExclusive();
3124 pWnd
= UserGetWindowObject(hWnd
);
3125 if ( !pWnd
|| // FIXME:
3126 pWnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3127 pWnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3132 if ( cmd
> SW_MAX
|| pWnd
->state2
& WNDS2_INDESTROY
)
3134 EngSetLastError(ERROR_INVALID_PARAMETER
);
3138 cmd
|= Hide
? SW_HIDE
: 0;
3140 co_WinPosShowWindow(pWnd
, cmd
);
3143 TRACE("Leave NtUserMinMaximize\n");
3145 return 0; // Always NULL?
3160 return NtUserSetWindowPos(hWnd
, 0, X
, Y
, nWidth
, nHeight
,
3161 (bRepaint
? SWP_NOZORDER
| SWP_NOACTIVATE
:
3162 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
));
3169 NtUserRealChildWindowFromPoint(HWND Parent
,
3174 TRACE("Enter NtUserRealChildWindowFromPoint\n");
3176 if ((pwndParent
= UserGetWindowObject(Parent
)))
3178 pwndParent
= IntRealChildWindowFromPoint(pwndParent
, x
, y
);
3181 TRACE("Leave NtUserRealChildWindowFromPoint\n");
3182 return pwndParent
? UserHMGetHandle(pwndParent
) : NULL
;
3191 HWND hWndInsertAfter
,
3198 DECLARE_RETURN(BOOL
);
3199 PWND Window
, pWndIA
;
3201 USER_REFERENCE_ENTRY Ref
;
3203 TRACE("Enter NtUserSetWindowPos\n");
3204 UserEnterExclusive();
3206 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
3207 Window
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3208 Window
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3210 ERR("NtUserSetWindowPos bad window handle!\n");
3214 if ( hWndInsertAfter
&&
3215 hWndInsertAfter
!= HWND_BOTTOM
&&
3216 hWndInsertAfter
!= HWND_TOPMOST
&&
3217 hWndInsertAfter
!= HWND_NOTOPMOST
)
3219 if (!(pWndIA
= UserGetWindowObject(hWndInsertAfter
)) ||
3220 pWndIA
== UserGetDesktopWindow() ||
3221 pWndIA
== UserGetMessageWindow() )
3223 ERR("NtUserSetWindowPos bad insert window handle!\n");
3228 /* First make sure that coordinates are valid for WM_WINDOWPOSCHANGING */
3229 if (!(uFlags
& SWP_NOMOVE
))
3231 if (X
< -32768) X
= -32768;
3232 else if (X
> 32767) X
= 32767;
3233 if (Y
< -32768) Y
= -32768;
3234 else if (Y
> 32767) Y
= 32767;
3236 if (!(uFlags
& SWP_NOSIZE
))
3239 else if (cx
> 32767) cx
= 32767;
3241 else if (cy
> 32767) cy
= 32767;
3244 UserRefObjectCo(Window
, &Ref
);
3245 ret
= co_WinPosSetWindowPos(Window
, hWndInsertAfter
, X
, Y
, cx
, cy
, uFlags
);
3246 UserDerefObjectCo(Window
);
3251 TRACE("Leave NtUserSetWindowPos, ret=%i\n",_ret_
);
3265 HRGN hrgnCopy
= NULL
;
3267 INT flags
= (SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
);
3268 BOOLEAN Ret
= FALSE
;
3269 DECLARE_RETURN(INT
);
3271 TRACE("Enter NtUserSetWindowRgn\n");
3272 UserEnterExclusive();
3274 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
3275 Window
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3276 Window
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3281 if (hRgn
) // The region will be deleted in user32.
3283 if (GreIsHandleValid(hRgn
))
3285 hrgnCopy
= NtGdiCreateRectRgn(0, 0, 0, 0);
3286 /* The coordinates of a window's window region are relative to the
3287 upper-left corner of the window, not the client area of the window. */
3288 NtGdiCombineRgn( hrgnCopy
, hRgn
, 0, RGN_COPY
);
3294 if (Window
->hrgnClip
)
3296 /* Delete no longer needed region handle */
3297 IntGdiSetRegionOwner(Window
->hrgnClip
, GDI_OBJ_HMGR_POWNED
);
3298 GreDeleteObject(Window
->hrgnClip
);
3303 /* Set public ownership */
3304 IntGdiSetRegionOwner(hrgnCopy
, GDI_OBJ_HMGR_PUBLIC
);
3306 Window
->hrgnClip
= hrgnCopy
;
3308 Ret
= co_WinPosSetWindowPos(Window
, HWND_TOP
, 0, 0, 0, 0, bRedraw
? flags
: (flags
|SWP_NOREDRAW
) );
3313 TRACE("Leave NtUserSetWindowRgn, ret=%i\n",_ret_
);
3322 NtUserSetInternalWindowPos(
3328 WINDOWPLACEMENT wndpl
;
3333 DECLARE_RETURN(BOOL
);
3334 USER_REFERENCE_ENTRY Ref
;
3336 TRACE("Enter NtUserSetWindowPlacement\n");
3337 UserEnterExclusive();
3339 if (!(Wnd
= UserGetWindowObject(hwnd
)) || // FIXME:
3340 Wnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3341 Wnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3350 ProbeForRead(lppt
, sizeof(POINT
), 1);
3351 RtlCopyMemory(&pt
, lppt
, sizeof(POINT
));
3355 ProbeForRead(lprect
, sizeof(RECT
), 1);
3356 RtlCopyMemory(&rect
, lprect
, sizeof(RECT
));
3359 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3361 SetLastNtError(_SEH2_GetExceptionCode());
3362 _SEH2_YIELD(RETURN( FALSE
));
3366 wndpl
.length
= sizeof(wndpl
);
3367 wndpl
.showCmd
= showCmd
;
3368 wndpl
.flags
= flags
= 0;
3373 wndpl
.flags
|= WPF_SETMINPOSITION
;
3374 wndpl
.ptMinPosition
= pt
;
3378 flags
|= PLACE_RECT
;
3379 wndpl
.rcNormalPosition
= rect
;
3382 UserRefObjectCo(Wnd
, &Ref
);
3383 IntSetWindowPlacement(Wnd
, &wndpl
, flags
);
3384 UserDerefObjectCo(Wnd
);
3388 TRACE("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_
);
3397 NtUserSetWindowPlacement(HWND hWnd
,
3398 WINDOWPLACEMENT
*lpwndpl
)
3401 WINDOWPLACEMENT Safepl
;
3403 DECLARE_RETURN(BOOL
);
3404 USER_REFERENCE_ENTRY Ref
;
3406 TRACE("Enter NtUserSetWindowPlacement\n");
3407 UserEnterExclusive();
3409 if (!(Wnd
= UserGetWindowObject(hWnd
)) || // FIXME:
3410 Wnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3411 Wnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3418 ProbeForRead(lpwndpl
, sizeof(WINDOWPLACEMENT
), 1);
3419 RtlCopyMemory(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
3421 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3423 SetLastNtError(_SEH2_GetExceptionCode());
3424 _SEH2_YIELD(RETURN( FALSE
));
3428 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
3433 Flags
= PLACE_MAX
| PLACE_RECT
;
3434 if (Safepl
.flags
& WPF_SETMINPOSITION
) Flags
|= PLACE_MIN
;
3435 UserRefObjectCo(Wnd
, &Ref
);
3436 IntSetWindowPlacement(Wnd
, &Safepl
, Flags
);
3437 UserDerefObjectCo(Wnd
);
3441 TRACE("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_
);
3450 NtUserShowWindowAsync(HWND hWnd
, LONG nCmdShow
)
3454 DECLARE_RETURN(BOOL
);
3455 USER_REFERENCE_ENTRY Ref
;
3457 TRACE("Enter NtUserShowWindowAsync\n");
3458 UserEnterExclusive();
3460 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
3461 Window
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3462 Window
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3467 if ( nCmdShow
> SW_MAX
)
3469 EngSetLastError(ERROR_INVALID_PARAMETER
);
3473 UserRefObjectCo(Window
, &Ref
);
3474 ret
= co_IntSendMessageNoWait( hWnd
, WM_ASYNC_SHOWWINDOW
, nCmdShow
, 0 );
3475 UserDerefObjectCo(Window
);
3476 if (-1 == (int) ret
|| !ret
) ret
= FALSE
;
3481 TRACE("Leave NtUserShowWindowAsync, ret=%i\n",_ret_
);
3490 NtUserShowWindow(HWND hWnd
, LONG nCmdShow
)
3494 DECLARE_RETURN(BOOL
);
3495 USER_REFERENCE_ENTRY Ref
;
3497 TRACE("Enter NtUserShowWindow hWnd %p SW_ %d\n",hWnd
, nCmdShow
);
3498 UserEnterExclusive();
3500 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
3501 Window
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3502 Window
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3507 if ( nCmdShow
> SW_MAX
|| Window
->state2
& WNDS2_INDESTROY
)
3509 EngSetLastError(ERROR_INVALID_PARAMETER
);
3513 UserRefObjectCo(Window
, &Ref
);
3514 ret
= co_WinPosShowWindow(Window
, nCmdShow
);
3515 UserDerefObjectCo(Window
);
3520 TRACE("Leave NtUserShowWindow, ret=%i\n",_ret_
);
3530 NtUserWindowFromPoint(LONG X
, LONG Y
)
3534 PWND DesktopWindow
= NULL
, Window
= NULL
;
3536 DECLARE_RETURN(HWND
);
3537 USER_REFERENCE_ENTRY Ref
;
3539 TRACE("Enter NtUserWindowFromPoint\n");
3540 UserEnterExclusive();
3542 if ((DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow())))
3549 // Hmm... Threads live on desktops thus we have a reference on the desktop and indirectly the desktop window.
3550 // It is possible this referencing is useless, though it should not hurt...
3551 UserRefObjectCo(DesktopWindow
, &Ref
);
3553 //pti = PsGetCurrentThreadWin32Thread();
3554 Window
= co_WinPosWindowFromPoint(DesktopWindow
, &pt
, &hittest
, FALSE
);
3558 Ret
= UserHMGetHandle(Window
);
3567 if (DesktopWindow
) UserDerefObjectCo(DesktopWindow
);
3569 TRACE("Leave NtUserWindowFromPoint, ret=%p\n", _ret_
);