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_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
21 #define SWP_AGG_NOPOSCHANGE \
22 (SWP_AGG_NOGEOMETRYCHANGE | 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 if (mirror_from
) Delta
.x
= -Delta
.x
;
125 for (i
= 0; i
!= cPoints
; i
++)
127 lpPoints
[i
].x
+= Delta
.x
;
128 lpPoints
[i
].x
*= Change
;
129 lpPoints
[i
].y
+= Delta
.y
;
132 if ((mirror_from
|| mirror_to
) && cPoints
== 2) /* special case for rectangle */
134 int tmp
= min(lpPoints
[0].x
, lpPoints
[1].x
);
135 lpPoints
[1].x
= max(lpPoints
[0].x
, lpPoints
[1].x
);
139 return MAKELONG(LOWORD(Delta
.x
), LOWORD(Delta
.y
));
142 BOOL FASTCALL
IsChildVisible(PWND pWnd
)
146 if ( (pWnd
->style
& (WS_POPUP
|WS_CHILD
)) != WS_CHILD
||
147 !(pWnd
= pWnd
->spwndParent
) )
150 while (pWnd
->style
& WS_VISIBLE
);
154 PWND FASTCALL
IntGetLastTopMostWindow(VOID
)
157 PDESKTOP rpdesk
= gptiCurrent
->rpdesk
;
160 (pWnd
= rpdesk
->pDeskInfo
->spwnd
->spwndChild
) &&
161 pWnd
->ExStyle
& WS_EX_TOPMOST
)
165 if (!pWnd
->spwndNext
) break;
166 if (!(pWnd
->spwndNext
->ExStyle
& WS_EX_TOPMOST
)) break;
167 pWnd
= pWnd
->spwndNext
;
175 // This helps with bug 6751 forcing modal dialog active when another app is minimized or closed.
177 BOOL FASTCALL
ActivateOtherWindowMin(PWND Wnd
)
179 BOOL ActivePrev
, FindTopWnd
;
180 PWND pWndTopMost
, pWndChild
, pWndSetActive
, pWndTemp
, pWndDesk
;
181 USER_REFERENCE_ENTRY Ref
;
182 PTHREADINFO pti
= gptiCurrent
;
185 ActivePrev
= (pti
->MessageQueue
->spwndActivePrev
!= NULL
);
188 if ((pWndTopMost
= IntGetLastTopMostWindow()))
189 pWndChild
= pWndTopMost
->spwndNext
;
191 pWndChild
= Wnd
->spwndParent
->spwndChild
;
196 pWndSetActive
= pti
->MessageQueue
->spwndActivePrev
;
198 pWndSetActive
= pWndChild
;
204 if ( VerifyWnd(pWndSetActive
) &&
205 !(pWndSetActive
->ExStyle
& WS_EX_NOACTIVATE
) &&
206 (pWndSetActive
->style
& (WS_VISIBLE
|WS_DISABLED
)) == WS_VISIBLE
&&
207 (!(pWndSetActive
->style
& WS_ICONIC
) /* FIXME MinMax pos? */ ) )
209 if (!(pWndSetActive
->ExStyle
& WS_EX_TOOLWINDOW
) )
211 UserRefObjectCo(pWndSetActive
, &Ref
);
212 co_IntSetForegroundWindow(pWndSetActive
);
213 UserDerefObjectCo(pWndSetActive
);
214 //ERR("AOWM 2 Exit Good\n");
217 if (!pWndTemp
) pWndTemp
= pWndSetActive
;
222 pWndSetActive
= pWndChild
;
225 pWndSetActive
= pWndSetActive
->spwndNext
;
228 if ( !FindTopWnd
) break;
233 pWndChild
= pWndChild
->spwndParent
->spwndChild
;
237 if (!(pWndDesk
= IntGetThreadDesktopWindow(pti
)))
242 pWndChild
= pWndDesk
->spwndChild
;
245 if ((pWndSetActive
= pWndTemp
))
247 UserRefObjectCo(pWndSetActive
, &Ref
);
248 co_IntSetForegroundWindow(pWndSetActive
);
249 UserDerefObjectCo(pWndSetActive
);
250 //ERR("AOWM 3 Exit Good\n");
253 //ERR("AOWM 4 Bad\n");
257 /*******************************************************************
258 * can_activate_window
260 * Check if we can activate the specified window.
263 BOOL FASTCALL
can_activate_window( PWND Wnd OPTIONAL
)
267 if (!Wnd
) return FALSE
;
270 if (!(style
& WS_VISIBLE
)) return FALSE
;
271 if (style
& WS_MINIMIZE
) return FALSE
;
272 if ((style
& (WS_POPUP
|WS_CHILD
)) == WS_CHILD
) return FALSE
;
274 /* FIXME: This window could be disable because the child that closed
276 //return !(style & WS_DISABLED);
280 /*******************************************************************
281 * WinPosActivateOtherWindow
283 * Activates window other than pWnd.
286 co_WinPosActivateOtherWindow(PWND Wnd
)
290 USER_REFERENCE_ENTRY Ref
;
294 if (IntIsDesktopWindow(Wnd
))
296 IntSetFocusMessageQueue(NULL
);
300 /* If this is popup window, try to activate the owner first. */
301 if ((Wnd
->style
& WS_POPUP
) && (WndTo
= Wnd
->spwndOwner
))
303 WndTo
= UserGetAncestor( WndTo
, GA_ROOT
);
304 if (can_activate_window(WndTo
)) goto done
;
307 /* Pick a next top-level window. */
308 /* FIXME: Search for non-tooltip windows first. */
312 if (!(WndTo
= WndTo
->spwndNext
)) break;
313 if (can_activate_window( WndTo
)) break;
318 if (WndTo
) UserRefObjectCo(WndTo
, &Ref
);
320 Fg
= UserGetForegroundWindow();
321 if ((!Fg
|| Wnd
->head
.h
== Fg
) && WndTo
) // FIXME: Ok if WndTo is NULL?? No, rule #4.
323 /* FIXME: Wine can pass WndTo = NULL to co_IntSetForegroundWindow. Hmm... */
324 if (co_IntSetForegroundWindow(WndTo
))
326 UserDerefObjectCo(WndTo
);
331 if (!co_IntSetActiveWindow(WndTo
,&previous
,FALSE
,TRUE
,FALSE
) || /* Ok for WndTo to be NULL here */
334 co_IntSetActiveWindow(0,NULL
,FALSE
,TRUE
,FALSE
);
336 if (WndTo
) UserDerefObjectCo(WndTo
);
342 co_WinPosArrangeIconicWindows(PWND parent
)
345 INT i
, x
, y
, xspacing
, yspacing
, sx
, sy
;
346 HWND
*List
= IntWinListChildren(parent
);
348 ASSERT_REFS_CO(parent
);
350 /* Check if we found any children */
356 IntGetClientRect( parent
, &rectParent
);
357 // FIXME: Support gspv.mm.iArrange.
359 y
= rectParent
.bottom
;
361 xspacing
= (UserGetSystemMetrics(SM_CXMINSPACING
)/2)+UserGetSystemMetrics(SM_CXBORDER
);
362 yspacing
= (UserGetSystemMetrics(SM_CYMINSPACING
)/2)+UserGetSystemMetrics(SM_CYBORDER
);
364 //ERR("X:%d Y:%d XS:%d YS:%d\n",x,y,xspacing,yspacing);
366 for(i
= 0; List
[i
]; i
++)
370 if (!(Child
= ValidateHwndNoErr(List
[i
])))
373 if((Child
->style
& WS_MINIMIZE
) != 0 )
375 USER_REFERENCE_ENTRY Ref
;
376 UserRefObjectCo(Child
, &Ref
);
378 sx
= x
+ UserGetSystemMetrics(SM_CXBORDER
);
379 sy
= y
- yspacing
- UserGetSystemMetrics(SM_CYBORDER
);
381 co_WinPosSetWindowPos( Child
, 0, sx
, sy
, 0, 0,
382 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
384 Child
->InternalPos
.IconPos
.x
= sx
;
385 Child
->InternalPos
.IconPos
.y
= sy
;
386 Child
->InternalPos
.flags
|= WPF_MININIT
;
387 Child
->InternalPos
.flags
&= ~WPF_SETMINPOSITION
;
389 UserDerefObjectCo(Child
);
391 if (x
<= (rectParent
.right
- UserGetSystemMetrics(SM_CXMINSPACING
)))
398 //ERR("X:%d Y:%d\n",x,y);
401 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
406 WinPosFindIconPos(PWND Window
, POINT
*Pos
)
409 PWND pwndChild
, pwndParent
;
410 int x
, y
, xspacing
, yspacing
;
412 pwndParent
= Window
->spwndParent
;
413 if (pwndParent
== UserGetDesktopWindow())
415 //ERR("Parent is Desktop, Min off screen!\n");
416 /* ReactOS doesn't support iconic minimize to desktop */
417 Pos
->x
= Pos
->y
= -32000;
418 Window
->InternalPos
.flags
|= WPF_MININIT
;
419 Window
->InternalPos
.IconPos
.x
= Pos
->x
;
420 Window
->InternalPos
.IconPos
.y
= Pos
->y
;
424 IntGetClientRect( pwndParent
, &rectParent
);
425 // FIXME: Support gspv.mm.iArrange.
427 y
= rectParent
.bottom
;
429 xspacing
= (UserGetSystemMetrics(SM_CXMINSPACING
)/2)+UserGetSystemMetrics(SM_CXBORDER
);
430 yspacing
= (UserGetSystemMetrics(SM_CYMINSPACING
)/2)+UserGetSystemMetrics(SM_CYBORDER
);
432 //ERR("X:%d Y:%d XS:%d YS:%d\n",Pos->x,Pos->y,xspacing,yspacing);
434 // Set to default position when minimized.
435 Pos
->x
= x
+ UserGetSystemMetrics(SM_CXBORDER
);
436 Pos
->y
= y
- yspacing
- UserGetSystemMetrics(SM_CYBORDER
);
438 for (pwndChild
= pwndParent
->spwndChild
; pwndChild
; pwndChild
= pwndChild
->spwndNext
)
440 if (pwndChild
== Window
) continue;
442 if (pwndChild
->style
& WS_VISIBLE
)
447 //ERR("Pos Child X %d Y %d!\n", pwndChild->InternalPos.IconPos.x, pwndChild->InternalPos.IconPos.y);
448 if ( pwndChild
->InternalPos
.IconPos
.x
== Pos
->x
&&
449 pwndChild
->InternalPos
.IconPos
.y
== Pos
->y
)
451 if (x
<= rectParent
.right
- UserGetSystemMetrics(SM_CXMINSPACING
))
458 Pos
->x
= x
+ UserGetSystemMetrics(SM_CXBORDER
);
459 Pos
->y
= y
- yspacing
- UserGetSystemMetrics(SM_CYBORDER
);
462 Window
->InternalPos
.IconPos
.x
= Pos
->x
;
463 Window
->InternalPos
.IconPos
.y
= Pos
->y
;
464 Window
->InternalPos
.flags
|= WPF_MININIT
;
465 //ERR("Position is set! X:%d Y:%d\n",Pos->x,Pos->y);
470 WinPosInitInternalPos(PWND Wnd
, RECTL
*RestoreRect
)
473 RECTL Rect
= *RestoreRect
;
475 if (Wnd
->spwndParent
!= UserGetDesktopWindow())
477 RECTL_vOffsetRect(&Rect
,
478 -Wnd
->spwndParent
->rcClient
.left
,
479 -Wnd
->spwndParent
->rcClient
.top
);
485 if (!Wnd
->InternalPosInitialized
)
487 // FIXME: Use check point Atom..
488 Wnd
->InternalPos
.flags
= 0;
489 Wnd
->InternalPos
.MaxPos
.x
= Wnd
->InternalPos
.MaxPos
.y
= -1;
490 Wnd
->InternalPos
.IconPos
.x
= Wnd
->InternalPos
.IconPos
.y
= -1;
491 Wnd
->InternalPos
.NormalRect
= Rect
;
492 Wnd
->InternalPosInitialized
= TRUE
;
495 if (Wnd
->style
& WS_MINIMIZE
)
497 Wnd
->InternalPos
.IconPos
= Size
;
498 Wnd
->InternalPos
.flags
|= WPF_MININIT
;
500 else if (Wnd
->style
& WS_MAXIMIZE
)
502 Wnd
->InternalPos
.flags
|= WPF_MAXINIT
;
504 if ( Wnd
->spwndParent
== Wnd
->head
.rpdesk
->pDeskInfo
->spwnd
)
506 if (Wnd
->state
& WNDS_MAXIMIZESTOMONITOR
)
508 Wnd
->InternalPos
.flags
&= ~WPF_MAXINIT
;
509 Wnd
->InternalPos
.MaxPos
.x
= Wnd
->InternalPos
.MaxPos
.y
= -1;
514 PMONITOR pmonitor
= UserMonitorFromRect(&Rect
, MONITOR_DEFAULTTOPRIMARY
);
515 // FIXME: support DPI aware, rcWorkDPI/Real etc..
516 WorkArea
= pmonitor
->rcMonitor
;
518 if (Wnd
->style
& WS_MAXIMIZEBOX
)
519 { // Support (Wnd->state & WNDS_HASCAPTION) || pmonitor->cFullScreen too.
520 if ((Wnd
->style
& WS_CAPTION
) == WS_CAPTION
|| !(Wnd
->style
& (WS_CHILD
| WS_POPUP
)))
522 WorkArea
= pmonitor
->rcWork
;
527 Wnd
->InternalPos
.MaxPos
.x
= Rect
.left
- WorkArea
.left
;
528 Wnd
->InternalPos
.MaxPos
.y
= Rect
.top
- WorkArea
.top
;
530 /*ERR("WinPosIP 2 X %d = R.l %d - W.l %d | Y %d = R.t %d - W.t %d\n",
531 Wnd->InternalPos.MaxPos.x,
532 Rect.left, WorkArea.left,
533 Wnd->InternalPos.MaxPos.y,
534 Rect.top, WorkArea.top);*/
538 Wnd
->InternalPos
.MaxPos
= Size
;
542 Wnd
->InternalPos
.NormalRect
= Rect
;
548 IntGetWindowPlacement(PWND Wnd
, WINDOWPLACEMENT
*lpwndpl
)
550 if (!Wnd
) return FALSE
;
552 if(lpwndpl
->length
!= sizeof(WINDOWPLACEMENT
))
559 WinPosInitInternalPos(Wnd
, &Wnd
->rcWindow
);
561 lpwndpl
->showCmd
= SW_HIDE
;
563 if ( Wnd
->style
& WS_MINIMIZE
)
564 lpwndpl
->showCmd
= SW_SHOWMINIMIZED
;
566 lpwndpl
->showCmd
= ( Wnd
->style
& WS_MAXIMIZE
) ? SW_SHOWMAXIMIZED
: SW_SHOWNORMAL
;
568 lpwndpl
->rcNormalPosition
= Wnd
->InternalPos
.NormalRect
;
570 if (Wnd
->InternalPos
.flags
& WPF_MININIT
) // Return if it was set!
572 lpwndpl
->ptMinPosition
.x
= Wnd
->InternalPos
.IconPos
.x
;
573 lpwndpl
->ptMinPosition
.y
= Wnd
->InternalPos
.IconPos
.y
;
576 lpwndpl
->ptMinPosition
.x
= lpwndpl
->ptMinPosition
.y
= -1;
578 if ( Wnd
->InternalPos
.flags
& WPF_MAXINIT
&& // Return if set and not maximized to monitor!
579 !(Wnd
->state
& WNDS_MAXIMIZESTOMONITOR
))
581 lpwndpl
->ptMaxPosition
.x
= Wnd
->InternalPos
.MaxPos
.x
;
582 lpwndpl
->ptMaxPosition
.y
= Wnd
->InternalPos
.MaxPos
.y
;
585 lpwndpl
->ptMaxPosition
.x
= lpwndpl
->ptMaxPosition
.y
= -1;
587 if ( Wnd
->spwndParent
== Wnd
->head
.rpdesk
->pDeskInfo
->spwnd
&&
588 !(Wnd
->ExStyle
& WS_EX_TOOLWINDOW
))
590 PMONITOR pmonitor
= UserMonitorFromRect(&lpwndpl
->rcNormalPosition
, MONITOR_DEFAULTTOPRIMARY
);
592 // FIXME: support DPI aware, rcWorkDPI/Real etc..
593 if (Wnd
->InternalPos
.flags
& WPF_MININIT
)
595 lpwndpl
->ptMinPosition
.x
-= (pmonitor
->rcWork
.left
- pmonitor
->rcMonitor
.left
);
596 lpwndpl
->ptMinPosition
.y
-= (pmonitor
->rcWork
.top
- pmonitor
->rcMonitor
.top
);
598 RECTL_vOffsetRect(&lpwndpl
->rcNormalPosition
,
599 pmonitor
->rcMonitor
.left
- pmonitor
->rcWork
.left
,
600 pmonitor
->rcMonitor
.top
- pmonitor
->rcWork
.top
);
603 if ( Wnd
->InternalPos
.flags
& WPF_RESTORETOMAXIMIZED
|| Wnd
->style
& WS_MAXIMIZE
)
604 lpwndpl
->flags
|= WPF_RESTORETOMAXIMIZED
;
606 if ( ((Wnd
->style
& (WS_CHILD
|WS_POPUP
)) == WS_CHILD
) && Wnd
->InternalPos
.flags
& WPF_SETMINPOSITION
)
607 lpwndpl
->flags
|= WPF_SETMINPOSITION
;
612 /* make sure the specified rect is visible on screen */
613 static void make_rect_onscreen( RECT
*rect
)
615 PMONITOR pmonitor
= UserMonitorFromRect( rect
, MONITOR_DEFAULTTONEAREST
); // Wine uses this.
617 // FIXME: support DPI aware, rcWorkDPI/Real etc..
618 if (!pmonitor
) return;
619 /* FIXME: map coordinates from rcWork to rcMonitor */
620 if (rect
->right
<= pmonitor
->rcWork
.left
)
622 rect
->right
+= pmonitor
->rcWork
.left
- rect
->left
;
623 rect
->left
= pmonitor
->rcWork
.left
;
625 else if (rect
->left
>= pmonitor
->rcWork
.right
)
627 rect
->left
+= pmonitor
->rcWork
.right
- rect
->right
;
628 rect
->right
= pmonitor
->rcWork
.right
;
630 if (rect
->bottom
<= pmonitor
->rcWork
.top
)
632 rect
->bottom
+= pmonitor
->rcWork
.top
- rect
->top
;
633 rect
->top
= pmonitor
->rcWork
.top
;
635 else if (rect
->top
>= pmonitor
->rcWork
.bottom
)
637 rect
->top
+= pmonitor
->rcWork
.bottom
- rect
->bottom
;
638 rect
->bottom
= pmonitor
->rcWork
.bottom
;
642 /* make sure the specified point is visible on screen */
643 static void make_point_onscreen( POINT
*pt
)
647 RECTL_vSetRect( &rect
, pt
->x
, pt
->y
, pt
->x
+ 1, pt
->y
+ 1 );
648 make_rect_onscreen( &rect
);
654 IntSetWindowPlacement(PWND Wnd
, WINDOWPLACEMENT
*wpl
, UINT Flags
)
659 if ( Flags
& PLACE_MIN
) make_point_onscreen( &wpl
->ptMinPosition
);
660 if ( Flags
& PLACE_MAX
) make_point_onscreen( &wpl
->ptMaxPosition
);
661 if ( Flags
& PLACE_RECT
) make_rect_onscreen( &wpl
->rcNormalPosition
);
663 if (!Wnd
|| Wnd
== Wnd
->head
.rpdesk
->pDeskInfo
->spwnd
) return FALSE
;
665 if ( Flags
& PLACE_MIN
) Wnd
->InternalPos
.IconPos
= wpl
->ptMinPosition
;
666 if ( Flags
& PLACE_MAX
) Wnd
->InternalPos
.MaxPos
= wpl
->ptMaxPosition
;
667 if ( Flags
& PLACE_RECT
) Wnd
->InternalPos
.NormalRect
= wpl
->rcNormalPosition
;
669 SWP_Flags
= SWP_NOZORDER
| SWP_NOACTIVATE
| ((wpl
->flags
& WPF_ASYNCWINDOWPLACEMENT
) ? SWP_ASYNCWINDOWPOS
: 0);
671 if (Wnd
->style
& WS_MINIMIZE
)
673 if (Flags
& PLACE_MIN
|| Wnd
->InternalPos
.flags
& WPF_SETMINPOSITION
)
675 co_WinPosSetWindowPos(Wnd
, HWND_TOP
,
676 wpl
->ptMinPosition
.x
, wpl
->ptMinPosition
.y
, 0, 0,
677 SWP_NOSIZE
| SWP_Flags
);
678 Wnd
->InternalPos
.flags
|= WPF_MININIT
;
681 else if (Wnd
->style
& WS_MAXIMIZE
)
683 if (Flags
& PLACE_MAX
)
685 co_WinPosSetWindowPos(Wnd
, HWND_TOP
,
686 wpl
->ptMaxPosition
.x
, wpl
->ptMaxPosition
.y
, 0, 0,
687 SWP_NOSIZE
| SWP_Flags
);
688 Wnd
->InternalPos
.flags
|= WPF_MAXINIT
;
691 else if (Flags
& PLACE_RECT
)
693 co_WinPosSetWindowPos(Wnd
, HWND_TOP
,
694 wpl
->rcNormalPosition
.left
, wpl
->rcNormalPosition
.top
,
695 wpl
->rcNormalPosition
.right
- wpl
->rcNormalPosition
.left
,
696 wpl
->rcNormalPosition
.bottom
- wpl
->rcNormalPosition
.top
,
700 sAsync
= (Wnd
->head
.pti
->MessageQueue
!= gptiCurrent
->MessageQueue
&& wpl
->flags
& WPF_ASYNCWINDOWPLACEMENT
);
703 co_IntSendMessageNoWait( UserHMGetHandle(Wnd
), WM_ASYNC_SHOWWINDOW
, wpl
->showCmd
, 0 );
705 co_WinPosShowWindow(Wnd
, wpl
->showCmd
);
707 if ( Wnd
->style
& WS_MINIMIZE
&& !sAsync
)
709 if ( wpl
->flags
& WPF_SETMINPOSITION
)
710 Wnd
->InternalPos
.flags
|= WPF_SETMINPOSITION
;
712 if ( wpl
->flags
& WPF_RESTORETOMAXIMIZED
)
713 Wnd
->InternalPos
.flags
|= WPF_RESTORETOMAXIMIZED
;
719 co_WinPosMinMaximize(PWND Wnd
, UINT ShowFlag
, RECT
* NewPos
)
728 wpl
.length
= sizeof(wpl
);
729 IntGetWindowPlacement( Wnd
, &wpl
);
731 if (co_HOOK_CallHooks( WH_CBT
, HCBT_MINMAX
, (WPARAM
)Wnd
->head
.h
, ShowFlag
))
733 ERR("WinPosMinMaximize WH_CBT Call Hook return!\n");
734 return SWP_NOSIZE
| SWP_NOMOVE
;
736 if (Wnd
->style
& WS_MINIMIZE
)
740 case SW_SHOWMINNOACTIVE
:
741 case SW_SHOWMINIMIZED
:
742 case SW_FORCEMINIMIZE
:
744 return SWP_NOSIZE
| SWP_NOMOVE
;
746 if (!co_IntSendMessageNoWait(Wnd
->head
.h
, WM_QUERYOPEN
, 0, 0))
748 return(SWP_NOSIZE
| SWP_NOMOVE
);
750 SwpFlags
|= SWP_NOCOPYBITS
;
754 case SW_SHOWMINNOACTIVE
:
755 case SW_SHOWMINIMIZED
:
756 case SW_FORCEMINIMIZE
:
759 //ERR("MinMaximize Minimize\n");
760 if (Wnd
->style
& WS_MAXIMIZE
)
762 Wnd
->InternalPos
.flags
|= WPF_RESTORETOMAXIMIZED
;
766 Wnd
->InternalPos
.flags
&= ~WPF_RESTORETOMAXIMIZED
;
769 old_style
= IntSetStyle( Wnd
, WS_MINIMIZE
, WS_MAXIMIZE
);
771 co_UserRedrawWindow(Wnd
, NULL
, 0, RDW_VALIDATE
| RDW_NOERASE
|
772 RDW_NOINTERNALPAINT
);
774 if (!(Wnd
->InternalPos
.flags
& WPF_SETMINPOSITION
))
775 Wnd
->InternalPos
.flags
&= ~WPF_MININIT
;
777 WinPosFindIconPos(Wnd
, &wpl
.ptMinPosition
);
779 if (!(old_style
& WS_MINIMIZE
)) SwpFlags
|= SWP_STATECHANGED
;
781 /*ERR("Minimize: %d,%d %dx%d\n",
782 wpl.ptMinPosition.x, wpl.ptMinPosition.y, UserGetSystemMetrics(SM_CXMINIMIZED),
783 UserGetSystemMetrics(SM_CYMINIMIZED));
785 RECTL_vSetRect(NewPos
, wpl
.ptMinPosition
.x
, wpl
.ptMinPosition
.y
,
786 // wpl.ptMinPosition.x + UserGetSystemMetrics(SM_CXMINIMIZED),
787 // wpl.ptMinPosition.y + UserGetSystemMetrics(SM_CYMINIMIZED));
788 UserGetSystemMetrics(SM_CXMINIMIZED
),
789 UserGetSystemMetrics(SM_CYMINIMIZED
));
790 SwpFlags
|= SWP_NOCOPYBITS
;
796 //ERR("MinMaximize Maximize\n");
797 if ((Wnd
->style
& WS_MAXIMIZE
) && (Wnd
->style
& WS_VISIBLE
))
799 SwpFlags
= SWP_NOSIZE
| SWP_NOMOVE
;
802 co_WinPosGetMinMaxInfo(Wnd
, &Size
, &wpl
.ptMaxPosition
, NULL
, NULL
);
804 /*ERR("Maximize: %d,%d %dx%d\n",
805 wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, Size.x, Size.y);
807 old_style
= IntSetStyle( Wnd
, WS_MAXIMIZE
, WS_MINIMIZE
);
809 if (!(old_style
& WS_MAXIMIZE
)) SwpFlags
|= SWP_STATECHANGED
;
810 RECTL_vSetRect(NewPos
, wpl
.ptMaxPosition
.x
, wpl
.ptMaxPosition
.y
,
811 // wpl.ptMaxPosition.x + Size.x, wpl.ptMaxPosition.y + Size.y);
816 case SW_SHOWNOACTIVATE
:
817 Wnd
->InternalPos
.flags
&= ~WPF_RESTORETOMAXIMIZED
;
821 case SW_SHOWDEFAULT
: /* FIXME: should have its own handler */
823 //ERR("MinMaximize Restore\n");
824 old_style
= IntSetStyle( Wnd
, 0, WS_MINIMIZE
| WS_MAXIMIZE
);
825 if (old_style
& WS_MINIMIZE
)
827 if (Wnd
->InternalPos
.flags
& WPF_RESTORETOMAXIMIZED
)
829 co_WinPosGetMinMaxInfo(Wnd
, &Size
, &wpl
.ptMaxPosition
, NULL
, NULL
);
830 IntSetStyle( Wnd
, WS_MAXIMIZE
, 0 );
831 SwpFlags
|= SWP_STATECHANGED
;
832 /*ERR("Restore to Max: %d,%d %dx%d\n",
833 wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, Size.x, Size.y);
835 RECTL_vSetRect(NewPos
, wpl
.ptMaxPosition
.x
, wpl
.ptMaxPosition
.y
,
836 // wpl.ptMaxPosition.x + Size.x, wpl.ptMaxPosition.y + Size.y);
842 *NewPos
= wpl
.rcNormalPosition
;
843 /*ERR("Restore Max: %d,%d %dx%d\n",
844 NewPos->left, NewPos->top, NewPos->right - NewPos->left, NewPos->bottom - NewPos->top);
846 NewPos
->right
-= NewPos
->left
;
847 NewPos
->bottom
-= NewPos
->top
;
853 if (!(old_style
& WS_MAXIMIZE
))
857 SwpFlags
|= SWP_STATECHANGED
;
858 Wnd
->InternalPos
.flags
&= ~WPF_RESTORETOMAXIMIZED
;
859 *NewPos
= wpl
.rcNormalPosition
;
860 /*ERR("Restore Min: %d,%d %dx%d\n",
861 NewPos->left, NewPos->top, NewPos->right - NewPos->left, NewPos->bottom - NewPos->top);
863 NewPos
->right
-= NewPos
->left
;
864 NewPos
->bottom
-= NewPos
->top
;
873 UserHasWindowEdge(DWORD Style
, DWORD ExStyle
)
875 if (Style
& WS_MINIMIZE
)
877 if (ExStyle
& WS_EX_DLGMODALFRAME
)
879 if (ExStyle
& WS_EX_STATICEDGE
)
881 if (Style
& WS_THICKFRAME
)
884 if (Style
== WS_DLGFRAME
|| Style
== WS_CAPTION
)
890 IntGetWindowBorderMeasures(PWND Wnd
, UINT
*cx
, UINT
*cy
)
892 if(HAS_DLGFRAME(Wnd
->style
, Wnd
->ExStyle
) && !(Wnd
->style
& WS_MINIMIZE
))
894 *cx
= UserGetSystemMetrics(SM_CXDLGFRAME
);
895 *cy
= UserGetSystemMetrics(SM_CYDLGFRAME
);
899 if(HAS_THICKFRAME(Wnd
->style
, Wnd
->ExStyle
)&& !(Wnd
->style
& WS_MINIMIZE
))
901 *cx
= UserGetSystemMetrics(SM_CXFRAME
);
902 *cy
= UserGetSystemMetrics(SM_CYFRAME
);
904 else if(HAS_THINFRAME(Wnd
->style
, Wnd
->ExStyle
))
906 *cx
= UserGetSystemMetrics(SM_CXBORDER
);
907 *cy
= UserGetSystemMetrics(SM_CYBORDER
);
917 UserGetWindowBorders(DWORD Style
, DWORD ExStyle
, SIZE
*Size
, BOOL WithClient
)
921 if (UserHasWindowEdge(Style
, ExStyle
))
923 else if (ExStyle
& WS_EX_STATICEDGE
)
925 if ((ExStyle
& WS_EX_CLIENTEDGE
) && WithClient
)
927 if (Style
& WS_CAPTION
|| ExStyle
& WS_EX_DLGMODALFRAME
)
929 Size
->cx
= Size
->cy
= Border
;
930 if ((Style
& WS_THICKFRAME
) && !(Style
& WS_MINIMIZE
))
932 Size
->cx
+= UserGetSystemMetrics(SM_CXFRAME
) - UserGetSystemMetrics(SM_CXDLGFRAME
);
933 Size
->cy
+= UserGetSystemMetrics(SM_CYFRAME
) - UserGetSystemMetrics(SM_CYDLGFRAME
);
935 Size
->cx
*= UserGetSystemMetrics(SM_CXBORDER
);
936 Size
->cy
*= UserGetSystemMetrics(SM_CYBORDER
);
940 UserAdjustWindowRectEx(LPRECT lpRect
,
949 lpRect
->top
-= UserGetSystemMetrics(SM_CYMENU
);
951 if ((dwStyle
& WS_CAPTION
) == WS_CAPTION
)
953 if (dwExStyle
& WS_EX_TOOLWINDOW
)
954 lpRect
->top
-= UserGetSystemMetrics(SM_CYSMCAPTION
);
956 lpRect
->top
-= UserGetSystemMetrics(SM_CYCAPTION
);
958 UserGetWindowBorders(dwStyle
, dwExStyle
, &BorderSize
, TRUE
);
968 co_WinPosGetMinMaxInfo(PWND Window
, POINT
* MaxSize
, POINT
* MaxPos
,
969 POINT
* MinTrack
, POINT
* MaxTrack
)
974 LONG style
= Window
->style
;
976 LONG exstyle
= Window
->ExStyle
;
979 ASSERT_REFS_CO(Window
);
981 /* Compute default values */
983 rc
= Window
->rcWindow
;
984 MinMax
.ptReserved
.x
= rc
.left
;
985 MinMax
.ptReserved
.y
= rc
.top
;
987 if ((style
& WS_CAPTION
) == WS_CAPTION
)
988 adjustedStyle
= style
& ~WS_BORDER
; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
990 adjustedStyle
= style
;
992 if(Window
->spwndParent
)
993 IntGetClientRect(Window
->spwndParent
, &rc
);
994 UserAdjustWindowRectEx(&rc
, adjustedStyle
, ((style
& WS_POPUP
) && Window
->IDMenu
), exstyle
);
999 MinMax
.ptMaxSize
.x
= rc
.right
- rc
.left
;
1000 MinMax
.ptMaxSize
.y
= rc
.bottom
- rc
.top
;
1001 if (style
& (WS_DLGFRAME
| WS_BORDER
))
1003 MinMax
.ptMinTrackSize
.x
= UserGetSystemMetrics(SM_CXMINTRACK
);
1004 MinMax
.ptMinTrackSize
.y
= UserGetSystemMetrics(SM_CYMINTRACK
);
1008 MinMax
.ptMinTrackSize
.x
= 2 * xinc
;
1009 MinMax
.ptMinTrackSize
.y
= 2 * yinc
;
1011 MinMax
.ptMaxTrackSize
.x
= UserGetSystemMetrics(SM_CXMAXTRACK
);
1012 MinMax
.ptMaxTrackSize
.y
= UserGetSystemMetrics(SM_CYMAXTRACK
);
1013 MinMax
.ptMaxPosition
.x
= -xinc
;
1014 MinMax
.ptMaxPosition
.y
= -yinc
;
1016 if (!EMPTYPOINT(Window
->InternalPos
.MaxPos
)) MinMax
.ptMaxPosition
= Window
->InternalPos
.MaxPos
;
1018 co_IntSendMessage(Window
->head
.h
, WM_GETMINMAXINFO
, 0, (LPARAM
)&MinMax
);
1020 /* if the app didn't change the values, adapt them for the current monitor */
1021 if ((monitor
= UserGetPrimaryMonitor()))
1025 rc_work
= monitor
->rcMonitor
;
1027 if (style
& WS_MAXIMIZEBOX
)
1029 if ((style
& WS_CAPTION
) == WS_CAPTION
|| !(style
& (WS_CHILD
| WS_POPUP
)))
1030 rc_work
= monitor
->rcWork
;
1033 if (MinMax
.ptMaxSize
.x
== UserGetSystemMetrics(SM_CXSCREEN
) + 2 * xinc
&&
1034 MinMax
.ptMaxSize
.y
== UserGetSystemMetrics(SM_CYSCREEN
) + 2 * yinc
)
1036 MinMax
.ptMaxSize
.x
= (rc_work
.right
- rc_work
.left
) + 2 * xinc
;
1037 MinMax
.ptMaxSize
.y
= (rc_work
.bottom
- rc_work
.top
) + 2 * yinc
;
1039 if (MinMax
.ptMaxPosition
.x
== -xinc
&& MinMax
.ptMaxPosition
.y
== -yinc
)
1041 MinMax
.ptMaxPosition
.x
= rc_work
.left
- xinc
;
1042 MinMax
.ptMaxPosition
.y
= rc_work
.top
- yinc
;
1044 if (MinMax
.ptMaxSize
.x
>= (monitor
->rcMonitor
.right
- monitor
->rcMonitor
.left
) &&
1045 MinMax
.ptMaxSize
.y
>= (monitor
->rcMonitor
.bottom
- monitor
->rcMonitor
.top
) )
1046 Window
->state
|= WNDS_MAXIMIZESTOMONITOR
;
1048 Window
->state
&= ~WNDS_MAXIMIZESTOMONITOR
;
1052 MinMax
.ptMaxTrackSize
.x
= max(MinMax
.ptMaxTrackSize
.x
,
1053 MinMax
.ptMinTrackSize
.x
);
1054 MinMax
.ptMaxTrackSize
.y
= max(MinMax
.ptMaxTrackSize
.y
,
1055 MinMax
.ptMinTrackSize
.y
);
1058 *MaxSize
= MinMax
.ptMaxSize
;
1060 *MaxPos
= MinMax
.ptMaxPosition
;
1062 *MinTrack
= MinMax
.ptMinTrackSize
;
1064 *MaxTrack
= MinMax
.ptMaxTrackSize
;
1066 return 0; // FIXME: What does it return?
1071 FixClientRect(PRECTL ClientRect
, PRECTL WindowRect
)
1073 if (ClientRect
->left
< WindowRect
->left
)
1075 ClientRect
->left
= WindowRect
->left
;
1077 else if (WindowRect
->right
< ClientRect
->left
)
1079 ClientRect
->left
= WindowRect
->right
;
1081 if (ClientRect
->right
< WindowRect
->left
)
1083 ClientRect
->right
= WindowRect
->left
;
1085 else if (WindowRect
->right
< ClientRect
->right
)
1087 ClientRect
->right
= WindowRect
->right
;
1089 if (ClientRect
->top
< WindowRect
->top
)
1091 ClientRect
->top
= WindowRect
->top
;
1093 else if (WindowRect
->bottom
< ClientRect
->top
)
1095 ClientRect
->top
= WindowRect
->bottom
;
1097 if (ClientRect
->bottom
< WindowRect
->top
)
1099 ClientRect
->bottom
= WindowRect
->top
;
1101 else if (WindowRect
->bottom
< ClientRect
->bottom
)
1103 ClientRect
->bottom
= WindowRect
->bottom
;
1109 co_WinPosDoNCCALCSize(PWND Window
, PWINDOWPOS WinPos
,
1110 RECT
* WindowRect
, RECT
* ClientRect
)
1115 ASSERT_REFS_CO(Window
);
1117 /* Send WM_NCCALCSIZE message to get new client area */
1118 if ((WinPos
->flags
& (SWP_FRAMECHANGED
| SWP_NOSIZE
)) != SWP_NOSIZE
)
1120 NCCALCSIZE_PARAMS params
;
1121 WINDOWPOS winposCopy
;
1123 params
.rgrc
[0] = *WindowRect
;
1124 params
.rgrc
[1] = Window
->rcWindow
;
1125 params
.rgrc
[2] = Window
->rcClient
;
1126 Parent
= Window
->spwndParent
;
1127 if (0 != (Window
->style
& WS_CHILD
) && Parent
)
1129 RECTL_vOffsetRect(&(params
.rgrc
[0]), - Parent
->rcClient
.left
,
1130 - Parent
->rcClient
.top
);
1131 RECTL_vOffsetRect(&(params
.rgrc
[1]), - Parent
->rcClient
.left
,
1132 - Parent
->rcClient
.top
);
1133 RECTL_vOffsetRect(&(params
.rgrc
[2]), - Parent
->rcClient
.left
,
1134 - Parent
->rcClient
.top
);
1136 params
.lppos
= &winposCopy
;
1137 winposCopy
= *WinPos
;
1139 wvrFlags
= co_IntSendMessage(Window
->head
.h
, WM_NCCALCSIZE
, TRUE
, (LPARAM
) ¶ms
);
1141 /* If the application send back garbage, ignore it */
1142 if (params
.rgrc
[0].left
<= params
.rgrc
[0].right
&&
1143 params
.rgrc
[0].top
<= params
.rgrc
[0].bottom
)
1145 *ClientRect
= params
.rgrc
[0];
1146 if ((Window
->style
& WS_CHILD
) && Parent
)
1148 RECTL_vOffsetRect(ClientRect
, Parent
->rcClient
.left
,
1149 Parent
->rcClient
.top
);
1151 FixClientRect(ClientRect
, WindowRect
);
1154 /* FIXME: WVR_ALIGNxxx */
1156 if (ClientRect
->left
!= Window
->rcClient
.left
||
1157 ClientRect
->top
!= Window
->rcClient
.top
)
1159 WinPos
->flags
&= ~SWP_NOCLIENTMOVE
;
1162 if ((ClientRect
->right
- ClientRect
->left
!=
1163 Window
->rcClient
.right
- Window
->rcClient
.left
) ||
1164 (ClientRect
->bottom
- ClientRect
->top
!=
1165 Window
->rcClient
.bottom
- Window
->rcClient
.top
))
1167 WinPos
->flags
&= ~SWP_NOCLIENTSIZE
;
1172 if (!(WinPos
->flags
& SWP_NOMOVE
) &&
1173 (ClientRect
->left
!= Window
->rcClient
.left
||
1174 ClientRect
->top
!= Window
->rcClient
.top
))
1176 WinPos
->flags
&= ~SWP_NOCLIENTMOVE
;
1185 co_WinPosDoWinPosChanging(PWND Window
,
1192 ASSERT_REFS_CO(Window
);
1194 if (!(WinPos
->flags
& SWP_NOSENDCHANGING
))
1196 co_IntSendMessageNoWait(Window
->head
.h
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
) WinPos
);
1199 *WindowRect
= Window
->rcWindow
;
1200 *ClientRect
= Window
->rcClient
;
1202 if (!(WinPos
->flags
& SWP_NOSIZE
))
1204 WindowRect
->right
= WindowRect
->left
+ WinPos
->cx
;
1205 WindowRect
->bottom
= WindowRect
->top
+ WinPos
->cy
;
1208 if (!(WinPos
->flags
& SWP_NOMOVE
))
1213 Parent
= Window
->spwndParent
;
1214 if ((0 != (Window
->style
& WS_CHILD
)) && Parent
)
1216 X
+= Parent
->rcClient
.left
;
1217 Y
+= Parent
->rcClient
.top
;
1220 WindowRect
->left
= X
;
1221 WindowRect
->top
= Y
;
1222 WindowRect
->right
+= X
- Window
->rcWindow
.left
;
1223 WindowRect
->bottom
+= Y
- Window
->rcWindow
.top
;
1224 RECTL_vOffsetRect(ClientRect
,
1225 X
- Window
->rcWindow
.left
,
1226 Y
- Window
->rcWindow
.top
);
1229 WinPos
->flags
|= SWP_NOCLIENTMOVE
| SWP_NOCLIENTSIZE
;
1235 * Fix Z order taking into account owned popups -
1236 * basically we need to maintain them above the window that owns them
1238 * FIXME: hide/show owned popups when owner visibility changes.
1240 * ReactOS: See bug 6751 and 7228.
1244 WinPosDoOwnedPopups(PWND Window
, HWND hWndInsertAfter
)
1249 PWND DesktopWindow
, ChildObject
;
1252 Owner
= Window
->spwndOwner
? Window
->spwndOwner
->head
.h
: NULL
;
1253 Style
= Window
->style
;
1255 if ((Style
& WS_POPUP
) && Owner
)
1257 /* Make sure this popup stays above the owner */
1258 HWND hWndLocalPrev
= HWND_TOPMOST
;
1260 if (hWndInsertAfter
!= HWND_TOPMOST
)
1262 DesktopWindow
= UserGetDesktopWindow();
1263 List
= IntWinListChildren(DesktopWindow
);
1267 for (i
= 0; List
[i
]; i
++)
1269 if (List
[i
] == Owner
)
1271 if (HWND_TOP
== hWndInsertAfter
)
1273 ChildObject
= ValidateHwndNoErr(List
[i
]);
1274 if (NULL
!= ChildObject
)
1276 if (0 == (ChildObject
->ExStyle
& WS_EX_TOPMOST
))
1282 if (List
[i
] != Window
->head
.h
)
1283 hWndLocalPrev
= List
[i
];
1284 if (hWndLocalPrev
== hWndInsertAfter
)
1287 hWndInsertAfter
= hWndLocalPrev
;
1291 else if (Style
& WS_CHILD
)
1293 return hWndInsertAfter
;
1298 DesktopWindow
= UserGetDesktopWindow();
1299 List
= IntWinListChildren(DesktopWindow
);
1303 for (i
= 0; List
[i
]; i
++)
1307 if (List
[i
] == UserHMGetHandle(Window
))
1310 if (!(Wnd
= ValidateHwndNoErr(List
[i
])))
1313 if (Wnd
->style
& WS_POPUP
&& Wnd
->spwndOwner
== Window
)
1315 USER_REFERENCE_ENTRY Ref
;
1316 UserRefObjectCo(Wnd
, &Ref
);
1318 co_WinPosSetWindowPos(Wnd
, hWndInsertAfter
, 0, 0, 0, 0,
1319 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOSENDCHANGING
| SWP_DEFERERASE
);
1321 UserDerefObjectCo(Wnd
);
1323 hWndInsertAfter
= List
[i
];
1326 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1329 return hWndInsertAfter
;
1332 /***********************************************************************
1333 * WinPosInternalMoveWindow
1335 * Update WindowRect and ClientRect of Window and all of its children
1336 * We keep both WindowRect and ClientRect in screen coordinates internally
1340 WinPosInternalMoveWindow(PWND Window
, INT MoveX
, INT MoveY
)
1344 ASSERT(Window
!= Window
->spwndChild
);
1346 Window
->rcWindow
.left
+= MoveX
;
1347 Window
->rcWindow
.right
+= MoveX
;
1348 Window
->rcWindow
.top
+= MoveY
;
1349 Window
->rcWindow
.bottom
+= MoveY
;
1351 Window
->rcClient
.left
+= MoveX
;
1352 Window
->rcClient
.right
+= MoveX
;
1353 Window
->rcClient
.top
+= MoveY
;
1354 Window
->rcClient
.bottom
+= MoveY
;
1356 for(Child
= Window
->spwndChild
; Child
; Child
= Child
->spwndNext
)
1358 WinPosInternalMoveWindow(Child
, MoveX
, MoveY
);
1363 * WinPosFixupSWPFlags
1365 * Fix redundant flags and values in the WINDOWPOS structure.
1369 WinPosFixupFlags(WINDOWPOS
*WinPos
, PWND Wnd
)
1371 if (Wnd
->style
& WS_VISIBLE
)
1373 WinPos
->flags
&= ~SWP_SHOWWINDOW
;
1377 WinPos
->flags
&= ~SWP_HIDEWINDOW
;
1378 if (!(WinPos
->flags
& SWP_SHOWWINDOW
))
1379 WinPos
->flags
|= SWP_NOREDRAW
;
1382 WinPos
->cx
= max(WinPos
->cx
, 0);
1383 WinPos
->cy
= max(WinPos
->cy
, 0);
1385 /* Check for right size */
1386 if (Wnd
->rcWindow
.right
- Wnd
->rcWindow
.left
== WinPos
->cx
&&
1387 Wnd
->rcWindow
.bottom
- Wnd
->rcWindow
.top
== WinPos
->cy
)
1389 WinPos
->flags
|= SWP_NOSIZE
;
1392 /* Check for right position */
1393 if (Wnd
->rcWindow
.left
== WinPos
->x
&&
1394 Wnd
->rcWindow
.top
== WinPos
->y
)
1396 WinPos
->flags
|= SWP_NOMOVE
;
1399 if (WinPos
->hwnd
== UserGetForegroundWindow())
1401 WinPos
->flags
|= SWP_NOACTIVATE
; /* Already active */
1404 if ((Wnd
->style
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)
1406 /* Bring to the top when activating */
1407 if (!(WinPos
->flags
& SWP_NOACTIVATE
))
1409 WinPos
->flags
&= ~SWP_NOZORDER
;
1410 WinPos
->hwndInsertAfter
= (0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
) ?
1411 HWND_TOPMOST
: HWND_TOP
);
1416 /* Check hwndInsertAfter */
1417 if (!(WinPos
->flags
& SWP_NOZORDER
))
1419 /* Fix sign extension */
1420 if (WinPos
->hwndInsertAfter
== (HWND
)0xffff)
1422 WinPos
->hwndInsertAfter
= HWND_TOPMOST
;
1424 else if (WinPos
->hwndInsertAfter
== (HWND
)0xfffe)
1426 WinPos
->hwndInsertAfter
= HWND_NOTOPMOST
;
1429 if (WinPos
->hwndInsertAfter
== HWND_NOTOPMOST
)
1431 if (!(Wnd
->ExStyle
& WS_EX_TOPMOST
))
1432 WinPos
->flags
|= SWP_NOZORDER
;
1434 WinPos
->hwndInsertAfter
= HWND_TOP
;
1436 else if (HWND_TOP
== WinPos
->hwndInsertAfter
1437 && 0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
))
1439 /* Keep it topmost when it's already topmost */
1440 WinPos
->hwndInsertAfter
= HWND_TOPMOST
;
1443 /* hwndInsertAfter must be a sibling of the window */
1444 if (HWND_TOPMOST
!= WinPos
->hwndInsertAfter
1445 && HWND_TOP
!= WinPos
->hwndInsertAfter
1446 && HWND_NOTOPMOST
!= WinPos
->hwndInsertAfter
1447 && HWND_BOTTOM
!= WinPos
->hwndInsertAfter
)
1451 InsAfterWnd
= ValidateHwndNoErr(WinPos
->hwndInsertAfter
);
1457 if (InsAfterWnd
->spwndParent
!= Wnd
->spwndParent
)
1459 /* Note from wine User32 Win test_SetWindowPos:
1460 "Returns TRUE also for windows that are not siblings"
1461 "Does not seem to do anything even without passing flags, still returns TRUE"
1462 "Same thing the other way around."
1463 ".. and with these windows."
1470 * We don't need to change the Z order of hwnd if it's already
1471 * inserted after hwndInsertAfter or when inserting hwnd after
1474 if ((WinPos
->hwnd
== WinPos
->hwndInsertAfter
) ||
1475 ((InsAfterWnd
->spwndNext
) && (WinPos
->hwnd
== InsAfterWnd
->spwndNext
->head
.h
)))
1477 WinPos
->flags
|= SWP_NOZORDER
;
1486 /* x and y are always screen relative */
1488 co_WinPosSetWindowPos(
1490 HWND WndInsertAfter
,
1499 RECTL NewWindowRect
;
1500 RECTL NewClientRect
;
1502 HRGN VisBefore
= NULL
;
1503 HRGN VisAfter
= NULL
;
1504 HRGN DirtyRgn
= NULL
;
1505 HRGN ExposedRgn
= NULL
;
1506 HRGN CopyRgn
= NULL
;
1508 RECTL OldWindowRect
, OldClientRect
;
1513 BOOL bPointerInWindow
;
1516 ASSERT_REFS_CO(Window
);
1518 /* FIXME: Get current active window from active queue. */
1520 bPointerInWindow
= IntPtInWindow(Window
, gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
);
1522 WinPos
.hwnd
= Window
->head
.h
;
1523 WinPos
.hwndInsertAfter
= WndInsertAfter
;
1528 WinPos
.flags
= flags
;
1530 co_WinPosDoWinPosChanging(Window
, &WinPos
, &NewWindowRect
, &NewClientRect
);
1532 // HWND_NOTOPMOST is redirected in WinPosFixupFlags.
1533 bNoTopMost
= WndInsertAfter
== HWND_NOTOPMOST
;
1535 /* Does the window still exist? */
1536 if (!IntIsWindow(WinPos
.hwnd
))
1538 TRACE("WinPosSetWindowPos: Invalid handle 0x%p!\n",WinPos
.hwnd
);
1539 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE
);
1543 /* Fix up the flags. */
1544 if (!WinPosFixupFlags(&WinPos
, Window
))
1550 Ancestor
= UserGetAncestor(Window
, GA_PARENT
);
1551 if ( (WinPos
.flags
& (SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) != SWP_NOZORDER
&&
1552 Ancestor
&& Ancestor
->head
.h
== IntGetDesktopWindow() )
1554 WinPos
.hwndInsertAfter
= WinPosDoOwnedPopups(Window
, WinPos
.hwndInsertAfter
);
1557 if (!(WinPos
.flags
& SWP_NOREDRAW
))
1559 /* Compute the visible region before the window position is changed */
1560 if (!(WinPos
.flags
& SWP_SHOWWINDOW
) &&
1561 (WinPos
.flags
& (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
|
1562 SWP_HIDEWINDOW
| SWP_FRAMECHANGED
)) !=
1563 (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
))
1565 VisBefore
= VIS_ComputeVisibleRegion(Window
, FALSE
, FALSE
,
1566 (Window
->style
& WS_CLIPSIBLINGS
) ? TRUE
: FALSE
);
1569 if ( VisBefore
!= NULL
&&
1570 (VisRgn
= (PROSRGNDATA
)RGNOBJAPI_Lock(VisBefore
, NULL
)) &&
1571 REGION_Complexity(VisRgn
) == NULLREGION
)
1573 RGNOBJAPI_Unlock(VisRgn
);
1574 GreDeleteObject(VisBefore
);
1579 RGNOBJAPI_Unlock(VisRgn
);
1580 NtGdiOffsetRgn(VisBefore
, -Window
->rcWindow
.left
, -Window
->rcWindow
.top
);
1585 WvrFlags
= co_WinPosDoNCCALCSize(Window
, &WinPos
, &NewWindowRect
, &NewClientRect
);
1587 TRACE("co_WinPosDoNCCALCSize returned %d\n", WvrFlags
);
1589 /* Validate link windows. (also take into account shell window in hwndShellWindow) */
1590 if (!(WinPos
.flags
& SWP_NOZORDER
) && WinPos
.hwnd
!= UserGetShellWindow())
1592 //// Fix bug 6751 & 7228 see WinPosDoOwnedPopups wine Fixme.
1595 PWND InsertAfterWindow
;
1597 if ((ParentWindow
= Window
->spwndParent
)) // Must have a Parent window!
1599 if (WinPos
.hwndInsertAfter
== HWND_TOPMOST
)
1601 InsertAfterWindow
= NULL
;
1603 else if ( WinPos
.hwndInsertAfter
== HWND_TOP
)
1605 InsertAfterWindow
= NULL
;
1607 Sibling
= ParentWindow
->spwndChild
;
1609 while ( Sibling
&& Sibling
->ExStyle
& WS_EX_TOPMOST
)
1611 InsertAfterWindow
= Sibling
;
1612 Sibling
= Sibling
->spwndNext
;
1615 else if (WinPos
.hwndInsertAfter
== HWND_BOTTOM
)
1617 if (ParentWindow
->spwndChild
)
1619 InsertAfterWindow
= ParentWindow
->spwndChild
;
1621 if(InsertAfterWindow
)
1623 while (InsertAfterWindow
->spwndNext
)
1624 InsertAfterWindow
= InsertAfterWindow
->spwndNext
;
1628 InsertAfterWindow
= NULL
;
1631 InsertAfterWindow
= IntGetWindowObject(WinPos
.hwndInsertAfter
);
1632 /* Do nothing if hwndInsertAfter is HWND_BOTTOM and Window is already
1634 if (InsertAfterWindow
!= Window
)
1636 IntUnlinkWindow(Window
);
1637 IntLinkWindow(Window
, InsertAfterWindow
);
1640 if ( ( WinPos
.hwndInsertAfter
== HWND_TOPMOST
||
1641 ( Window
->ExStyle
& WS_EX_TOPMOST
&& Window
->spwndPrev
&& Window
->spwndPrev
->ExStyle
& WS_EX_TOPMOST
) ||
1642 ( Window
->spwndNext
&& Window
->spwndNext
->ExStyle
& WS_EX_TOPMOST
) ) &&
1645 Window
->ExStyle
|= WS_EX_TOPMOST
;
1649 Window
->ExStyle
&= ~ WS_EX_TOPMOST
;
1655 OldWindowRect
= Window
->rcWindow
;
1656 OldClientRect
= Window
->rcClient
;
1658 if (OldClientRect
.bottom
- OldClientRect
.top
==
1659 NewClientRect
.bottom
- NewClientRect
.top
)
1661 WvrFlags
&= ~WVR_VREDRAW
;
1664 if (OldClientRect
.right
- OldClientRect
.left
==
1665 NewClientRect
.right
- NewClientRect
.left
)
1667 WvrFlags
&= ~WVR_HREDRAW
;
1670 /* FIXME: Actually do something with WVR_VALIDRECTS */
1672 if (NewClientRect
.left
!= OldClientRect
.left
||
1673 NewClientRect
.top
!= OldClientRect
.top
)
1675 WinPosInternalMoveWindow(Window
,
1676 NewClientRect
.left
- OldClientRect
.left
,
1677 NewClientRect
.top
- OldClientRect
.top
);
1680 Window
->rcWindow
= NewWindowRect
;
1681 Window
->rcClient
= NewClientRect
;
1683 /* erase parent when hiding or resizing child */
1684 if (WinPos
.flags
& SWP_HIDEWINDOW
)
1686 /* Clear the update region */
1687 co_UserRedrawWindow( Window
,
1690 RDW_VALIDATE
| RDW_NOFRAME
| RDW_NOERASE
| RDW_NOINTERNALPAINT
| RDW_ALLCHILDREN
);
1692 if (Window
->spwndParent
== UserGetDesktopWindow())
1693 co_IntShellHookNotify(HSHELL_WINDOWDESTROYED
, (WPARAM
)Window
->head
.h
, 0);
1695 Window
->style
&= ~WS_VISIBLE
; //IntSetStyle( Window, 0, WS_VISIBLE );
1696 IntNotifyWinEvent(EVENT_OBJECT_HIDE
, Window
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
1698 else if (WinPos
.flags
& SWP_SHOWWINDOW
)
1700 if (Window
->spwndParent
== UserGetDesktopWindow())
1701 co_IntShellHookNotify(HSHELL_WINDOWCREATED
, (WPARAM
)Window
->head
.h
, 0);
1703 Window
->style
|= WS_VISIBLE
; //IntSetStyle( Window, WS_VISIBLE, 0 );
1704 IntNotifyWinEvent(EVENT_OBJECT_SHOW
, Window
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
1707 if (Window
->hrgnUpdate
!= NULL
&& Window
->hrgnUpdate
!= HRGN_WINDOW
)
1709 NtGdiOffsetRgn(Window
->hrgnUpdate
,
1710 NewWindowRect
.left
- OldWindowRect
.left
,
1711 NewWindowRect
.top
- OldWindowRect
.top
);
1714 DceResetActiveDCEs(Window
); // For WS_VISIBLE changes.
1716 if (!(WinPos
.flags
& SWP_NOREDRAW
))
1718 /* Determine the new visible region */
1719 VisAfter
= VIS_ComputeVisibleRegion(Window
, FALSE
, FALSE
,
1720 (Window
->style
& WS_CLIPSIBLINGS
) ? TRUE
: FALSE
);
1723 if ( VisAfter
!= NULL
&&
1724 (VisRgn
= (PROSRGNDATA
)RGNOBJAPI_Lock(VisAfter
, NULL
)) &&
1725 REGION_Complexity(VisRgn
) == NULLREGION
)
1727 RGNOBJAPI_Unlock(VisRgn
);
1728 GreDeleteObject(VisAfter
);
1733 RGNOBJAPI_Unlock(VisRgn
);
1734 NtGdiOffsetRgn(VisAfter
, -Window
->rcWindow
.left
, -Window
->rcWindow
.top
);
1738 * Determine which pixels can be copied from the old window position
1739 * to the new. Those pixels must be visible in both the old and new
1740 * position. Also, check the class style to see if the windows of this
1741 * class need to be completely repainted on (horizontal/vertical) size
1744 if ( VisBefore
!= NULL
&&
1746 !(WinPos
.flags
& SWP_NOCOPYBITS
) &&
1747 ((WinPos
.flags
& SWP_NOSIZE
) || !(WvrFlags
& WVR_REDRAW
)) &&
1748 !(Window
->ExStyle
& WS_EX_TRANSPARENT
) )
1750 CopyRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
1751 RgnType
= NtGdiCombineRgn(CopyRgn
, VisAfter
, VisBefore
, RGN_AND
);
1754 * If this is (also) a window resize, the whole nonclient area
1755 * needs to be repainted. So we limit the copy to the client area,
1756 * 'cause there is no use in copying it (would possibly cause
1757 * "flashing" too). However, if the copy region is already empty,
1758 * we don't have to crop (can't take anything away from an empty
1761 if (!(WinPos
.flags
& SWP_NOSIZE
) &&
1763 RgnType
!= NULLREGION
)
1765 PROSRGNDATA pCopyRgn
;
1766 RECTL ORect
= OldClientRect
;
1767 RECTL NRect
= NewClientRect
;
1768 RECTL_vOffsetRect(&ORect
, - OldWindowRect
.left
, - OldWindowRect
.top
);
1769 RECTL_vOffsetRect(&NRect
, - NewWindowRect
.left
, - NewWindowRect
.top
);
1770 RECTL_bIntersectRect(&CopyRect
, &ORect
, &NRect
);
1771 pCopyRgn
= RGNOBJAPI_Lock(CopyRgn
, NULL
);
1772 REGION_CropAndOffsetRegion(pCopyRgn
, pCopyRgn
, &CopyRect
, NULL
);
1773 RGNOBJAPI_Unlock(pCopyRgn
);
1776 /* No use in copying bits which are in the update region. */
1777 if (Window
->hrgnUpdate
!= NULL
)
1779 NtGdiOffsetRgn(CopyRgn
, NewWindowRect
.left
, NewWindowRect
.top
);
1780 NtGdiCombineRgn(CopyRgn
, CopyRgn
, Window
->hrgnUpdate
, RGN_DIFF
);
1781 NtGdiOffsetRgn(CopyRgn
, -NewWindowRect
.left
, -NewWindowRect
.top
);
1785 * Now, get the bounding box of the copy region. If it's empty
1786 * there's nothing to copy. Also, it's no use copying bits onto
1789 if ( (VisRgn
= (PROSRGNDATA
)RGNOBJAPI_Lock(CopyRgn
, NULL
)) &&
1790 REGION_GetRgnBox(VisRgn
, &CopyRect
) == NULLREGION
)
1792 /* Nothing to copy, clean up */
1793 RGNOBJAPI_Unlock(VisRgn
);
1794 GreDeleteObject(CopyRgn
);
1797 else if (OldWindowRect
.left
!= NewWindowRect
.left
||
1798 OldWindowRect
.top
!= NewWindowRect
.top
)
1802 RGNOBJAPI_Unlock(VisRgn
);
1806 * Small trick here: there is no function to bitblt a region. So
1807 * we set the region as the clipping region, take the bounding box
1808 * of the region and bitblt that. Since nothing outside the clipping
1809 * region is copied, this has the effect of bitblt'ing the region.
1811 * Since NtUserGetDCEx takes ownership of the clip region, we need
1812 * to create a copy of CopyRgn and pass that. We need CopyRgn later
1814 NtGdiOffsetRgn(CopyRgn
, NewWindowRect
.left
, NewWindowRect
.top
);
1815 Dc
= UserGetDCEx( Window
,
1817 DCX_WINDOW
|DCX_CACHE
|DCX_INTERSECTRGN
|DCX_CLIPSIBLINGS
|DCX_KEEPCLIPRGN
);
1819 CopyRect
.left
, CopyRect
.top
,
1820 CopyRect
.right
- CopyRect
.left
,
1821 CopyRect
.bottom
- CopyRect
.top
,
1823 CopyRect
.left
+ (OldWindowRect
.left
- NewWindowRect
.left
),
1824 CopyRect
.top
+ (OldWindowRect
.top
- NewWindowRect
.top
),
1829 UserReleaseDC(Window
, Dc
, FALSE
);
1830 IntValidateParent(Window
, CopyRgn
, FALSE
);
1831 NtGdiOffsetRgn(CopyRgn
, -NewWindowRect
.left
, -NewWindowRect
.top
);
1835 RGNOBJAPI_Unlock(VisRgn
);
1843 /* We need to redraw what wasn't visible before */
1844 if (VisAfter
!= NULL
)
1846 DirtyRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
1847 if (CopyRgn
!= NULL
)
1849 RgnType
= NtGdiCombineRgn(DirtyRgn
, VisAfter
, CopyRgn
, RGN_DIFF
);
1853 RgnType
= NtGdiCombineRgn(DirtyRgn
, VisAfter
, 0, RGN_COPY
);
1855 if (RgnType
!= ERROR
&& RgnType
!= NULLREGION
)
1858 NtGdiOffsetRgn(DirtyRgn, Window->rcWindow.left, Window->rcWindow.top);
1859 IntInvalidateWindows( Window,
1861 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
1863 GreDeleteObject(DirtyRgn);
1866 PWND Parent
= Window
->spwndParent
;
1868 NtGdiOffsetRgn( DirtyRgn
,
1869 Window
->rcWindow
.left
,
1870 Window
->rcWindow
.top
);
1871 if ( (Window
->style
& WS_CHILD
) &&
1873 !(Parent
->style
& WS_CLIPCHILDREN
))
1875 IntInvalidateWindows( Parent
,
1877 RDW_ERASE
| RDW_INVALIDATE
);
1878 co_IntPaintWindows(Parent
, RDW_ERASENOW
, FALSE
);
1882 IntInvalidateWindows( Window
,
1884 RDW_ERASE
| RDW_FRAME
| RDW_INVALIDATE
| RDW_ALLCHILDREN
);
1887 GreDeleteObject(DirtyRgn
);
1890 if (CopyRgn
!= NULL
)
1892 GreDeleteObject(CopyRgn
);
1895 /* Expose what was covered before but not covered anymore */
1896 if (VisBefore
!= NULL
)
1898 ExposedRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
1899 RgnType
= NtGdiCombineRgn(ExposedRgn
, VisBefore
, NULL
, RGN_COPY
);
1900 NtGdiOffsetRgn( ExposedRgn
,
1901 OldWindowRect
.left
- NewWindowRect
.left
,
1902 OldWindowRect
.top
- NewWindowRect
.top
);
1904 if (VisAfter
!= NULL
)
1905 RgnType
= NtGdiCombineRgn(ExposedRgn
, ExposedRgn
, VisAfter
, RGN_DIFF
);
1907 if (RgnType
!= ERROR
&& RgnType
!= NULLREGION
)
1909 co_VIS_WindowLayoutChanged(Window
, ExposedRgn
);
1911 GreDeleteObject(ExposedRgn
);
1912 GreDeleteObject(VisBefore
);
1915 if (VisAfter
!= NULL
)
1917 GreDeleteObject(VisAfter
);
1921 if (!(WinPos
.flags
& (SWP_NOACTIVATE
|SWP_HIDEWINDOW
)))
1923 if ((Window
->style
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1925 co_IntSendMessageNoWait(WinPos
.hwnd
, WM_CHILDACTIVATE
, 0, 0);
1929 //ERR("SetWindowPos Set FG Window!\n");
1930 co_IntSetForegroundWindow(Window
);
1934 /* And last, send the WM_WINDOWPOSCHANGED message */
1936 TRACE("\tstatus flags = %04x\n", WinPos
.flags
& SWP_AGG_STATUSFLAGS
);
1938 if ((WinPos
.flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOPOSCHANGE
)
1940 /* WM_WINDOWPOSCHANGED is sent even if SWP_NOSENDCHANGING is set
1941 and always contains final window position.
1943 WinPos
.x
= NewWindowRect
.left
;
1944 WinPos
.y
= NewWindowRect
.top
;
1945 WinPos
.cx
= NewWindowRect
.right
- NewWindowRect
.left
;
1946 WinPos
.cy
= NewWindowRect
.bottom
- NewWindowRect
.top
;
1947 co_IntSendMessageNoWait(WinPos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
) &WinPos
);
1950 if ( WinPos
.flags
& SWP_FRAMECHANGED
|| WinPos
.flags
& SWP_STATECHANGED
||
1951 !(WinPos
.flags
& SWP_NOCLIENTSIZE
) || !(WinPos
.flags
& SWP_NOCLIENTMOVE
) )
1953 PWND pWnd
= ValidateHwndNoErr(WinPos
.hwnd
);
1955 IntNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE
, pWnd
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
1958 if(bPointerInWindow
!= IntPtInWindow(Window
, gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
))
1960 /* Generate mouse move message */
1962 msg
.message
= WM_MOUSEMOVE
;
1963 msg
.wParam
= UserGetMouseButtonsState();
1964 msg
.lParam
= MAKELPARAM(gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
);
1965 msg
.pt
= gpsi
->ptCursor
;
1966 co_MsqInsertMouseMessage(&msg
, 0, 0, TRUE
);
1973 co_WinPosGetNonClientSize(PWND Window
, RECT
* WindowRect
, RECT
* ClientRect
)
1977 ASSERT_REFS_CO(Window
);
1979 *ClientRect
= *WindowRect
;
1980 Result
= co_IntSendMessageNoWait(Window
->head
.h
, WM_NCCALCSIZE
, FALSE
, (LPARAM
) ClientRect
);
1982 FixClientRect(ClientRect
, WindowRect
);
1988 co_WinPosSendSizeMove(PWND Wnd
)
1992 WPARAM wParam
= SIZE_RESTORED
;
1994 IntGetClientRect(Wnd
, &Rect
);
1995 lParam
= MAKELONG(Rect
.right
-Rect
.left
, Rect
.bottom
-Rect
.top
);
1997 Wnd
->state
&= ~WNDS_SENDSIZEMOVEMSGS
;
1999 if (Wnd
->style
& WS_MAXIMIZE
)
2001 wParam
= SIZE_MAXIMIZED
;
2003 else if (Wnd
->style
& WS_MINIMIZE
)
2005 wParam
= SIZE_MINIMIZED
;
2009 co_IntSendMessageNoWait(UserHMGetHandle(Wnd
), WM_SIZE
, wParam
, lParam
);
2011 if (Wnd
->spwndParent
== UserGetDesktopWindow()) // Wnd->spwndParent->fnid != FNID_DESKTOP )
2012 lParam
= MAKELONG(Wnd
->rcClient
.left
, Wnd
->rcClient
.top
);
2014 lParam
= MAKELONG(Wnd
->rcClient
.left
-Wnd
->spwndParent
->rcClient
.left
, Wnd
->rcClient
.top
-Wnd
->spwndParent
->rcClient
.top
);
2016 co_IntSendMessageNoWait(UserHMGetHandle(Wnd
), WM_MOVE
, 0, lParam
);
2018 IntEngWindowChanged(Wnd
, WOC_RGN_CLIENT
);
2022 co_WinPosShowWindow(PWND Wnd
, INT Cmd
)
2025 UINT Swp
= 0, EventMsg
= 0;
2026 RECTL NewPos
= {0, 0, 0, 0};
2031 BOOL ShowOwned
= FALSE
;
2034 ASSERT_REFS_CO(Wnd
);
2036 pti
= PsGetCurrentThreadWin32Thread();
2037 WasVisible
= (Wnd
->style
& WS_VISIBLE
) != 0;
2048 Swp
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
2049 if (Wnd
!= pti
->MessageQueue
->spwndActive
)
2050 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2054 case SW_FORCEMINIMIZE
: /* FIXME: Does not work if thread is hung. */
2055 case SW_SHOWMINNOACTIVE
:
2056 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2058 case SW_SHOWMINIMIZED
:
2059 Swp
|= SWP_SHOWWINDOW
;
2063 Swp
|= SWP_NOACTIVATE
;
2064 if (!(style
& WS_MINIMIZE
))
2066 //IntShowOwnedPopups(Wnd, FALSE );
2068 // Fix wine Win test_SetFocus todo #1 & #2,
2069 if (Cmd
== SW_SHOWMINIMIZED
)
2071 if ((style
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
2072 co_UserSetFocus(Wnd
->spwndParent
);
2077 Swp
|= co_WinPosMinMaximize(Wnd
, Cmd
, &NewPos
) |
2080 EventMsg
= EVENT_SYSTEM_MINIMIZESTART
;
2086 Swp
|= SWP_FRAMECHANGED
;
2090 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
2095 case SW_SHOWMAXIMIZED
:
2097 Swp
|= SWP_SHOWWINDOW
;
2098 if (!(style
& WS_MAXIMIZE
))
2102 Swp
|= co_WinPosMinMaximize(Wnd
, SW_MAXIMIZE
, &NewPos
) |
2105 EventMsg
= EVENT_SYSTEM_MINIMIZEEND
;
2111 Swp
|= SWP_FRAMECHANGED
;
2115 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
2121 Swp
|= SWP_NOACTIVATE
| SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
2122 if (style
& WS_CHILD
&& !(Wnd
->ExStyle
& WS_EX_MDICHILD
)) Swp
|= SWP_NOZORDER
;
2125 if (WasVisible
) return(TRUE
); // Nothing to do!
2126 Swp
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
2127 /* Don't activate the topmost window. */
2128 if (style
& WS_CHILD
&& !(Wnd
->ExStyle
& WS_EX_MDICHILD
)) Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2131 case SW_SHOWNOACTIVATE
:
2132 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2135 case SW_SHOWDEFAULT
:
2137 if (!WasVisible
) Swp
|= SWP_SHOWWINDOW
;
2138 if (style
& (WS_MINIMIZE
| WS_MAXIMIZE
))
2140 Swp
|= co_WinPosMinMaximize(Wnd
, Cmd
, &NewPos
) |
2143 if (style
& WS_MINIMIZE
) EventMsg
= EVENT_SYSTEM_MINIMIZEEND
;
2149 Swp
|= SWP_FRAMECHANGED
;
2153 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
2155 if ( style
& WS_CHILD
&&
2156 !(Wnd
->ExStyle
& WS_EX_MDICHILD
) &&
2157 !(Swp
& SWP_STATECHANGED
))
2158 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2165 ShowFlag
= (Cmd
!= SW_HIDE
);
2167 if ((ShowFlag
!= WasVisible
|| Cmd
== SW_SHOWNA
) && Cmd
!= SW_SHOWMAXIMIZED
&& !(Swp
& SWP_STATECHANGED
))
2169 co_IntSendMessageNoWait(Wnd
->head
.h
, WM_SHOWWINDOW
, ShowFlag
, 0);
2170 if (!(Wnd
->state2
& WNDS2_WIN31COMPAT
))
2171 co_IntSendMessageNoWait(Wnd
->head
.h
, WM_SETVISIBLE
, ShowFlag
, 0);
2172 if (!VerifyWnd(Wnd
)) return WasVisible
;
2175 /* We can't activate a child window */
2176 if ((Wnd
->style
& WS_CHILD
) &&
2177 !(Wnd
->ExStyle
& WS_EX_MDICHILD
) &&
2180 //ERR("SWP Child No active and ZOrder\n");
2181 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2184 #if 0 // Explorer issues with common controls. Someone does not know how CS_SAVEBITS works.
2185 if ((Wnd
->style
& (WS_POPUP
|WS_CHILD
)) != WS_CHILD
&&
2186 Wnd
->pcls
->style
& CS_SAVEBITS
&&
2187 ((Cmd
== SW_SHOW
) || (Cmd
== SW_NORMAL
)))
2189 co_IntSetActiveWindow(Wnd
,NULL
,FALSE
,TRUE
,FALSE
);
2190 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2194 if (IsChildVisible(Wnd
) || Swp
& SWP_STATECHANGED
)
2196 TRACE("Child is Vis %s or State changed %s. ShowFlag %s\n",
2197 (IsChildVisible(Wnd
) ? "TRUE" : "FALSE"), (Swp
& SWP_STATECHANGED
? "TRUE" : "FALSE"),
2198 (ShowFlag
? "TRUE" : "FALSE"));
2199 co_WinPosSetWindowPos( Wnd
,
2200 0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
) ? HWND_TOPMOST
: HWND_TOP
,
2203 NewPos
.right
, //NewPos.right - NewPos.left,
2204 NewPos
.bottom
, //NewPos.bottom - NewPos.top,
2209 TRACE("Parent Vis?\n");
2210 /* if parent is not visible simply toggle WS_VISIBLE and return */
2211 if (ShowFlag
) IntSetStyle( Wnd
, WS_VISIBLE
, 0 );
2212 else IntSetStyle( Wnd
, 0, WS_VISIBLE
);
2215 if ( EventMsg
) IntNotifyWinEvent(EventMsg
, Wnd
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
2217 //if ( ShowOwned ) IntShowOwnedPopups(Wnd, TRUE );
2219 if ((Cmd
== SW_HIDE
) || (Cmd
== SW_MINIMIZE
))
2221 if ( Wnd
== pti
->MessageQueue
->spwndActive
&& pti
->MessageQueue
== IntGetFocusMessageQueue() )
2223 if ( Wnd
->spwndParent
== UserGetDesktopWindow())
2225 if(!ActivateOtherWindowMin(Wnd
))
2226 co_WinPosActivateOtherWindow(Wnd
);
2229 co_WinPosActivateOtherWindow(Wnd
);
2232 /* Revert focus to parent */
2233 if (Wnd
== pti
->MessageQueue
->spwndFocus
)
2235 Parent
= Wnd
->spwndParent
;
2236 if (Wnd
->spwndParent
== UserGetDesktopWindow()) Parent
= 0;
2237 co_UserSetFocus(Parent
);
2241 /* FIXME: Check for window destruction. */
2243 if ((Wnd
->state
& WNDS_SENDSIZEMOVEMSGS
) &&
2244 !(Wnd
->state2
& WNDS2_INDESTROY
))
2246 co_WinPosSendSizeMove(Wnd
);
2249 /* if previous state was minimized Windows sets focus to the window */
2250 if (style
& WS_MINIMIZE
)
2252 co_UserSetFocus(Wnd
);
2253 // Fix wine Win test_SetFocus todo #3,
2254 if (!(style
& WS_CHILD
)) co_IntSendMessageNoWait(UserHMGetHandle(Wnd
), WM_ACTIVATE
, WA_ACTIVE
, 0);
2261 co_WinPosSearchChildren(
2270 if (!(ScopeWin
->style
& WS_VISIBLE
))
2275 if ((ScopeWin
->style
& WS_DISABLED
))
2280 if (!IntPtInWindow(ScopeWin
, Point
->x
, Point
->y
))
2285 UserReferenceObject(ScopeWin
);
2287 if ( RECTL_bPointInRect(&ScopeWin
->rcClient
, Point
->x
, Point
->y
) )
2289 List
= IntWinListChildren(ScopeWin
);
2292 for (phWnd
= List
; *phWnd
; ++phWnd
)
2294 if (!(pwndChild
= ValidateHwndNoErr(*phWnd
)))
2299 pwndChild
= co_WinPosSearchChildren(pwndChild
, Point
, HitTest
);
2301 if(pwndChild
!= NULL
)
2303 /* We found a window. Don't send any more WM_NCHITTEST messages */
2304 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2305 UserDereferenceObject(ScopeWin
);
2309 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2313 if (ScopeWin
->head
.pti
== PsGetCurrentThreadWin32Thread())
2315 *HitTest
= (USHORT
)co_IntSendMessage(ScopeWin
->head
.h
, WM_NCHITTEST
, 0,
2316 MAKELONG(Point
->x
, Point
->y
));
2317 if ((*HitTest
) == (USHORT
)HTTRANSPARENT
)
2319 UserDereferenceObject(ScopeWin
);
2324 *HitTest
= HTCLIENT
;
2330 co_WinPosWindowFromPoint(PWND ScopeWin
, POINT
*WinPoint
, USHORT
* HitTest
)
2333 POINT Point
= *WinPoint
;
2334 USER_REFERENCE_ENTRY Ref
;
2336 if( ScopeWin
== NULL
)
2338 ScopeWin
= UserGetDesktopWindow();
2339 if(ScopeWin
== NULL
)
2343 *HitTest
= HTNOWHERE
;
2345 ASSERT_REFS_CO(ScopeWin
);
2346 UserRefObjectCo(ScopeWin
, &Ref
);
2348 Window
= co_WinPosSearchChildren(ScopeWin
, &Point
, HitTest
);
2350 UserDerefObjectCo(ScopeWin
);
2352 ASSERT_REFS_CO(Window
);
2353 ASSERT_REFS_CO(ScopeWin
);
2359 IntRealChildWindowFromPoint(PWND Parent
, LONG x
, LONG y
)
2363 PWND pwndHit
= NULL
;
2368 if (Parent
!= UserGetDesktopWindow())
2370 Pt
.x
+= Parent
->rcClient
.left
;
2371 Pt
.y
+= Parent
->rcClient
.top
;
2374 if (!IntPtInWindow(Parent
, Pt
.x
, Pt
.y
)) return NULL
;
2376 if ((List
= IntWinListChildren(Parent
)))
2378 for (phWnd
= List
; *phWnd
; phWnd
++)
2381 if ((Child
= ValidateHwndNoErr(*phWnd
)))
2383 if ( Child
->style
& WS_VISIBLE
&& IntPtInWindow(Child
, Pt
.x
, Pt
.y
) )
2385 if ( Child
->pcls
->atomClassName
!= gpsi
->atomSysClass
[ICLS_BUTTON
] ||
2386 (Child
->style
& BS_TYPEMASK
) != BS_GROUPBOX
)
2388 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2395 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2397 return pwndHit
? pwndHit
: Parent
;
2401 IntChildWindowFromPointEx(PWND Parent
, LONG x
, LONG y
, UINT uiFlags
)
2405 PWND pwndHit
= NULL
;
2410 if (Parent
!= UserGetDesktopWindow())
2412 if (Parent
->ExStyle
& WS_EX_LAYOUTRTL
)
2413 Pt
.x
= Parent
->rcClient
.right
- Pt
.x
;
2415 Pt
.x
+= Parent
->rcClient
.left
;
2416 Pt
.y
+= Parent
->rcClient
.top
;
2419 if (!IntPtInWindow(Parent
, Pt
.x
, Pt
.y
)) return NULL
;
2421 if ((List
= IntWinListChildren(Parent
)))
2423 for (phWnd
= List
; *phWnd
; phWnd
++)
2426 if ((Child
= ValidateHwndNoErr(*phWnd
)))
2428 if (uiFlags
& (CWP_SKIPINVISIBLE
|CWP_SKIPDISABLED
))
2430 if (!(Child
->style
& WS_VISIBLE
) && (uiFlags
& CWP_SKIPINVISIBLE
)) continue;
2431 if ((Child
->style
& WS_DISABLED
) && (uiFlags
& CWP_SKIPDISABLED
)) continue;
2434 if (uiFlags
& CWP_SKIPTRANSPARENT
)
2436 if (Child
->ExStyle
& WS_EX_TRANSPARENT
) continue;
2439 if (IntPtInWindow(Child
, Pt
.x
, Pt
.y
))
2446 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2448 return pwndHit
? pwndHit
: Parent
;
2453 IntDeferWindowPos( HDWP hdwp
,
2464 HDWP retvalue
= hdwp
;
2466 TRACE("hdwp %p, hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
2467 hdwp
, hwnd
, hwndAfter
, x
, y
, cx
, cy
, flags
);
2469 if (flags
& ~(SWP_NOSIZE
| SWP_NOMOVE
|
2470 SWP_NOZORDER
| SWP_NOREDRAW
|
2471 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
2472 SWP_NOOWNERZORDER
|SWP_SHOWWINDOW
|
2473 SWP_HIDEWINDOW
| SWP_FRAMECHANGED
))
2475 EngSetLastError(ERROR_INVALID_PARAMETER
);
2479 if (!(pDWP
= (PSMWP
)UserGetObject(gHandleTable
, hdwp
, TYPE_SETWINDOWPOS
)))
2481 EngSetLastError(ERROR_INVALID_DWP_HANDLE
);
2485 for (i
= 0; i
< pDWP
->ccvr
; i
++)
2487 if (pDWP
->acvr
[i
].pos
.hwnd
== hwnd
)
2489 /* Merge with the other changes */
2490 if (!(flags
& SWP_NOZORDER
))
2492 pDWP
->acvr
[i
].pos
.hwndInsertAfter
= hwndAfter
;
2494 if (!(flags
& SWP_NOMOVE
))
2496 pDWP
->acvr
[i
].pos
.x
= x
;
2497 pDWP
->acvr
[i
].pos
.y
= y
;
2499 if (!(flags
& SWP_NOSIZE
))
2501 pDWP
->acvr
[i
].pos
.cx
= cx
;
2502 pDWP
->acvr
[i
].pos
.cy
= cy
;
2504 pDWP
->acvr
[i
].pos
.flags
&= flags
| ~(SWP_NOSIZE
| SWP_NOMOVE
|
2505 SWP_NOZORDER
| SWP_NOREDRAW
|
2506 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
2508 pDWP
->acvr
[i
].pos
.flags
|= flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
|
2513 if (pDWP
->ccvr
>= pDWP
->ccvrAlloc
)
2515 PCVR newpos
= ExAllocatePoolWithTag(PagedPool
, pDWP
->ccvrAlloc
* 2 * sizeof(CVR
), USERTAG_SWP
);
2521 RtlZeroMemory(newpos
, pDWP
->ccvrAlloc
* 2 * sizeof(CVR
));
2522 RtlCopyMemory(newpos
, pDWP
->acvr
, pDWP
->ccvrAlloc
* sizeof(CVR
));
2523 ExFreePoolWithTag(pDWP
->acvr
, USERTAG_SWP
);
2524 pDWP
->ccvrAlloc
*= 2;
2525 pDWP
->acvr
= newpos
;
2527 pDWP
->acvr
[pDWP
->ccvr
].pos
.hwnd
= hwnd
;
2528 pDWP
->acvr
[pDWP
->ccvr
].pos
.hwndInsertAfter
= hwndAfter
;
2529 pDWP
->acvr
[pDWP
->ccvr
].pos
.x
= x
;
2530 pDWP
->acvr
[pDWP
->ccvr
].pos
.y
= y
;
2531 pDWP
->acvr
[pDWP
->ccvr
].pos
.cx
= cx
;
2532 pDWP
->acvr
[pDWP
->ccvr
].pos
.cy
= cy
;
2533 pDWP
->acvr
[pDWP
->ccvr
].pos
.flags
= flags
;
2534 pDWP
->acvr
[pDWP
->ccvr
].hrgnClip
= NULL
;
2535 pDWP
->acvr
[pDWP
->ccvr
].hrgnInterMonitor
= NULL
;
2541 BOOL FASTCALL
IntEndDeferWindowPosEx( HDWP hdwp
, BOOL sAsync
)
2548 TRACE("%p\n", hdwp
);
2550 if (!(pDWP
= (PSMWP
)UserGetObject(gHandleTable
, hdwp
, TYPE_SETWINDOWPOS
)))
2552 EngSetLastError(ERROR_INVALID_DWP_HANDLE
);
2556 for (i
= 0, winpos
= pDWP
->acvr
; res
&& i
< pDWP
->ccvr
; i
++, winpos
++)
2559 USER_REFERENCE_ENTRY Ref
;
2561 TRACE("hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
2562 winpos
->pos
.hwnd
, winpos
->pos
.hwndInsertAfter
, winpos
->pos
.x
, winpos
->pos
.y
,
2563 winpos
->pos
.cx
, winpos
->pos
.cy
, winpos
->pos
.flags
);
2565 pwnd
= ValidateHwndNoErr(winpos
->pos
.hwnd
);
2569 UserRefObjectCo(pwnd
, &Ref
);
2574 PWINDOWPOS ppos
= ExAllocatePoolWithTag(PagedPool
, sizeof(WINDOWPOS
), USERTAG_SWP
);
2577 *ppos
= winpos
->pos
;
2578 /* Yes it's a pointer inside Win32k! */
2579 lRes
= co_IntSendMessageNoWait( winpos
->pos
.hwnd
, WM_ASYNC_SETWINDOWPOS
, 0, (LPARAM
)ppos
);
2580 /* We handle this the same way as Event Hooks and Hooks. */
2583 ExFreePoolWithTag(ppos
, USERTAG_SWP
);
2588 res
= co_WinPosSetWindowPos( pwnd
,
2589 winpos
->pos
.hwndInsertAfter
,
2596 // Hack to pass tests.... Must have some work to do so clear the error.
2597 if (res
&& (winpos
->pos
.flags
& (SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOZORDER
)) == SWP_NOZORDER
)
2598 EngSetLastError(ERROR_SUCCESS
);
2600 UserDerefObjectCo(pwnd
);
2602 ExFreePoolWithTag(pDWP
->acvr
, USERTAG_SWP
);
2603 UserDereferenceObject(pDWP
);
2604 UserDeleteObject(hdwp
, TYPE_SETWINDOWPOS
);
2612 NtUserChildWindowFromPointEx(HWND hwndParent
,
2618 TRACE("Enter NtUserChildWindowFromPointEx\n");
2619 UserEnterExclusive();
2620 if ((pwndParent
= UserGetWindowObject(hwndParent
)))
2622 pwndParent
= IntChildWindowFromPointEx(pwndParent
, x
, y
, uiFlags
);
2625 TRACE("Leave NtUserChildWindowFromPointEx\n");
2626 return pwndParent
? UserHMGetHandle(pwndParent
) : NULL
;
2633 NtUserEndDeferWindowPosEx(HDWP WinPosInfo
,
2637 TRACE("Enter NtUserEndDeferWindowPosEx\n");
2638 UserEnterExclusive();
2639 Ret
= IntEndDeferWindowPosEx(WinPosInfo
, (BOOL
)Unknown1
);
2640 TRACE("Leave NtUserEndDeferWindowPosEx, ret=%i\n", Ret
);
2649 NtUserDeferWindowPos(HDWP WinPosInfo
,
2651 HWND WndInsertAfter
,
2660 UINT Tmp
= ~(SWP_ASYNCWINDOWPOS
|SWP_DEFERERASE
|SWP_NOSENDCHANGING
|SWP_NOREPOSITION
|
2661 SWP_NOCOPYBITS
|SWP_HIDEWINDOW
|SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|
2662 SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_NOZORDER
|SWP_NOMOVE
|SWP_NOSIZE
);
2664 TRACE("Enter NtUserDeferWindowPos\n");
2665 UserEnterExclusive();
2669 EngSetLastError(ERROR_INVALID_FLAGS
);
2673 pWnd
= UserGetWindowObject(Wnd
);
2674 if ( !pWnd
|| // FIXME:
2675 pWnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
2676 pWnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
2681 if ( WndInsertAfter
&&
2682 WndInsertAfter
!= HWND_BOTTOM
&&
2683 WndInsertAfter
!= HWND_TOPMOST
&&
2684 WndInsertAfter
!= HWND_NOTOPMOST
)
2686 pWndIA
= UserGetWindowObject(WndInsertAfter
);
2688 pWndIA
== UserGetDesktopWindow() ||
2689 pWndIA
== UserGetMessageWindow() )
2695 Ret
= IntDeferWindowPos(WinPosInfo
, Wnd
, WndInsertAfter
, x
, y
, cx
, cy
, Flags
);
2698 TRACE("Leave NtUserDeferWindowPos, ret=%i\n", Ret
);
2707 NtUserGetInternalWindowPos( HWND hWnd
,
2714 WINDOWPLACEMENT wndpl
;
2718 if (!(Window
= UserGetWindowObject(hWnd
)))
2728 ProbeForWrite(rectWnd
,
2734 ProbeForWrite(ptIcon
,
2740 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2742 SetLastNtError(_SEH2_GetExceptionCode());
2747 wndpl
.length
= sizeof(WINDOWPLACEMENT
);
2749 if (IntGetWindowPlacement(Window
, &wndpl
) && !Hit
)
2755 RtlCopyMemory(rectWnd
, &wndpl
.rcNormalPosition
, sizeof(RECT
));
2759 RtlCopyMemory(ptIcon
, &wndpl
.ptMinPosition
, sizeof(POINT
));
2763 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2765 SetLastNtError(_SEH2_GetExceptionCode());
2770 if (!Hit
) Ret
= wndpl
.showCmd
;
2781 NtUserGetWindowPlacement(HWND hWnd
,
2782 WINDOWPLACEMENT
*lpwndpl
)
2785 WINDOWPLACEMENT Safepl
;
2787 DECLARE_RETURN(BOOL
);
2789 TRACE("Enter NtUserGetWindowPlacement\n");
2792 if (!(Wnd
= UserGetWindowObject(hWnd
)))
2797 Status
= MmCopyFromCaller(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
2798 if(!NT_SUCCESS(Status
))
2800 SetLastNtError(Status
);
2803 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
2808 IntGetWindowPlacement(Wnd
, &Safepl
);
2810 Status
= MmCopyToCaller(lpwndpl
, &Safepl
, sizeof(WINDOWPLACEMENT
));
2811 if(!NT_SUCCESS(Status
))
2813 SetLastNtError(Status
);
2820 TRACE("Leave NtUserGetWindowPlacement, ret=%i\n",_ret_
);
2829 UINT cmd
, // Wine SW_ commands
2834 TRACE("Enter NtUserMinMaximize\n");
2835 UserEnterExclusive();
2837 pWnd
= UserGetWindowObject(hWnd
);
2838 if ( !pWnd
|| // FIXME:
2839 pWnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
2840 pWnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
2845 if ( cmd
> SW_MAX
|| pWnd
->state2
& WNDS2_INDESTROY
)
2847 EngSetLastError(ERROR_INVALID_PARAMETER
);
2851 cmd
|= Hide
? SW_HIDE
: 0;
2853 co_WinPosShowWindow(pWnd
, cmd
);
2856 TRACE("Leave NtUserMinMaximize\n");
2858 return 0; // Always NULL?
2873 return NtUserSetWindowPos(hWnd
, 0, X
, Y
, nWidth
, nHeight
,
2874 (bRepaint
? SWP_NOZORDER
| SWP_NOACTIVATE
:
2875 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
));
2882 NtUserRealChildWindowFromPoint(HWND Parent
,
2887 TRACE("Enter NtUserRealChildWindowFromPoint\n");
2889 if ((pwndParent
= UserGetWindowObject(Parent
)))
2891 pwndParent
= IntRealChildWindowFromPoint(pwndParent
, x
, y
);
2894 TRACE("Leave NtUserRealChildWindowFromPoint\n");
2895 return pwndParent
? UserHMGetHandle(pwndParent
) : NULL
;
2904 HWND hWndInsertAfter
,
2911 DECLARE_RETURN(BOOL
);
2912 PWND Window
, pWndIA
;
2914 USER_REFERENCE_ENTRY Ref
;
2916 TRACE("Enter NtUserSetWindowPos\n");
2917 UserEnterExclusive();
2919 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
2920 Window
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
2921 Window
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
2923 ERR("NtUserSetWindowPos bad window handle!\n");
2927 if ( hWndInsertAfter
&&
2928 hWndInsertAfter
!= HWND_BOTTOM
&&
2929 hWndInsertAfter
!= HWND_TOPMOST
&&
2930 hWndInsertAfter
!= HWND_NOTOPMOST
)
2932 if (!(pWndIA
= UserGetWindowObject(hWndInsertAfter
)) ||
2933 pWndIA
== UserGetDesktopWindow() ||
2934 pWndIA
== UserGetMessageWindow() )
2936 ERR("NtUserSetWindowPos bad insert window handle!\n");
2941 /* First make sure that coordinates are valid for WM_WINDOWPOSCHANGING */
2942 if (!(uFlags
& SWP_NOMOVE
))
2944 if (X
< -32768) X
= -32768;
2945 else if (X
> 32767) X
= 32767;
2946 if (Y
< -32768) Y
= -32768;
2947 else if (Y
> 32767) Y
= 32767;
2949 if (!(uFlags
& SWP_NOSIZE
))
2952 else if (cx
> 32767) cx
= 32767;
2954 else if (cy
> 32767) cy
= 32767;
2957 UserRefObjectCo(Window
, &Ref
);
2958 ret
= co_WinPosSetWindowPos(Window
, hWndInsertAfter
, X
, Y
, cx
, cy
, uFlags
);
2959 UserDerefObjectCo(Window
);
2964 TRACE("Leave NtUserSetWindowPos, ret=%i\n",_ret_
);
2980 INT flags
= (SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
);
2981 BOOLEAN Ret
= FALSE
;
2982 DECLARE_RETURN(INT
);
2984 TRACE("Enter NtUserSetWindowRgn\n");
2985 UserEnterExclusive();
2987 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
2988 Window
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
2989 Window
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
2994 if (hRgn
) // The region will be deleted in user32.
2996 if (GreIsHandleValid(hRgn
))
2998 hrgnCopy
= IntSysCreateRectRgn(0, 0, 0, 0);
2999 /* The coordinates of a window's window region are relative to the
3000 upper-left corner of the window, not the client area of the window. */
3001 NtGdiCombineRgn( hrgnCopy
, hRgn
, 0, RGN_COPY
);
3011 if (Window
->hrgnClip
)
3013 /* Delete no longer needed region handle */
3014 IntGdiSetRegionOwner(Window
->hrgnClip
, GDI_OBJ_HMGR_POWNED
);
3015 GreDeleteObject(Window
->hrgnClip
);
3020 /* Set public ownership */
3021 IntGdiSetRegionOwner(hrgnCopy
, GDI_OBJ_HMGR_PUBLIC
);
3023 Window
->hrgnClip
= hrgnCopy
;
3025 Ret
= co_WinPosSetWindowPos(Window
, HWND_TOP
, 0, 0, 0, 0, bRedraw
? flags
: (flags
|SWP_NOREDRAW
) );
3030 TRACE("Leave NtUserSetWindowRgn, ret=%i\n",_ret_
);
3039 NtUserSetInternalWindowPos(
3045 WINDOWPLACEMENT wndpl
;
3050 DECLARE_RETURN(BOOL
);
3051 USER_REFERENCE_ENTRY Ref
;
3053 TRACE("Enter NtUserSetWindowPlacement\n");
3054 UserEnterExclusive();
3056 if (!(Wnd
= UserGetWindowObject(hwnd
)) || // FIXME:
3057 Wnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3058 Wnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3067 ProbeForRead(lppt
, sizeof(POINT
), 1);
3068 RtlCopyMemory(&pt
, lppt
, sizeof(POINT
));
3072 ProbeForRead(lprect
, sizeof(RECT
), 1);
3073 RtlCopyMemory(&rect
, lprect
, sizeof(RECT
));
3076 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3078 SetLastNtError(_SEH2_GetExceptionCode());
3079 _SEH2_YIELD(RETURN( FALSE
));
3083 wndpl
.length
= sizeof(wndpl
);
3084 wndpl
.showCmd
= showCmd
;
3085 wndpl
.flags
= flags
= 0;
3090 wndpl
.flags
|= WPF_SETMINPOSITION
;
3091 wndpl
.ptMinPosition
= pt
;
3095 flags
|= PLACE_RECT
;
3096 wndpl
.rcNormalPosition
= rect
;
3099 UserRefObjectCo(Wnd
, &Ref
);
3100 IntSetWindowPlacement(Wnd
, &wndpl
, flags
);
3101 UserDerefObjectCo(Wnd
);
3105 TRACE("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_
);
3114 NtUserSetWindowPlacement(HWND hWnd
,
3115 WINDOWPLACEMENT
*lpwndpl
)
3118 WINDOWPLACEMENT Safepl
;
3120 DECLARE_RETURN(BOOL
);
3121 USER_REFERENCE_ENTRY Ref
;
3123 TRACE("Enter NtUserSetWindowPlacement\n");
3124 UserEnterExclusive();
3126 if (!(Wnd
= UserGetWindowObject(hWnd
)) || // FIXME:
3127 Wnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3128 Wnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3135 ProbeForRead(lpwndpl
, sizeof(WINDOWPLACEMENT
), 1);
3136 RtlCopyMemory(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
3138 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3140 SetLastNtError(_SEH2_GetExceptionCode());
3141 _SEH2_YIELD(RETURN( FALSE
));
3145 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
3150 Flags
= PLACE_MAX
| PLACE_RECT
;
3151 if (Safepl
.flags
& WPF_SETMINPOSITION
) Flags
|= PLACE_MIN
;
3152 UserRefObjectCo(Wnd
, &Ref
);
3153 IntSetWindowPlacement(Wnd
, &Safepl
, Flags
);
3154 UserDerefObjectCo(Wnd
);
3158 TRACE("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_
);
3167 NtUserShowWindowAsync(HWND hWnd
, LONG nCmdShow
)
3171 DECLARE_RETURN(BOOL
);
3172 USER_REFERENCE_ENTRY Ref
;
3174 TRACE("Enter NtUserShowWindowAsync\n");
3175 UserEnterExclusive();
3177 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
3178 Window
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3179 Window
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3184 if ( nCmdShow
> SW_MAX
)
3186 EngSetLastError(ERROR_INVALID_PARAMETER
);
3190 UserRefObjectCo(Window
, &Ref
);
3191 ret
= co_IntSendMessageNoWait( hWnd
, WM_ASYNC_SHOWWINDOW
, nCmdShow
, 0 );
3192 UserDerefObjectCo(Window
);
3193 if (-1 == (int) ret
|| !ret
) ret
= FALSE
;
3198 TRACE("Leave NtUserShowWindowAsync, ret=%i\n",_ret_
);
3207 NtUserShowWindow(HWND hWnd
, LONG nCmdShow
)
3211 DECLARE_RETURN(BOOL
);
3212 USER_REFERENCE_ENTRY Ref
;
3214 TRACE("Enter NtUserShowWindow\n");
3215 UserEnterExclusive();
3217 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
3218 Window
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3219 Window
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3224 if ( nCmdShow
> SW_MAX
|| Window
->state2
& WNDS2_INDESTROY
)
3226 EngSetLastError(ERROR_INVALID_PARAMETER
);
3230 UserRefObjectCo(Window
, &Ref
);
3231 ret
= co_WinPosShowWindow(Window
, nCmdShow
);
3232 UserDerefObjectCo(Window
);
3237 TRACE("Leave NtUserShowWindow, ret=%i\n",_ret_
);
3247 NtUserWindowFromPoint(LONG X
, LONG Y
)
3251 PWND DesktopWindow
= NULL
, Window
= NULL
;
3253 DECLARE_RETURN(HWND
);
3254 USER_REFERENCE_ENTRY Ref
;
3256 TRACE("Enter NtUserWindowFromPoint\n");
3257 UserEnterExclusive();
3259 if ((DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow())))
3266 // Hmm... Threads live on desktops thus we have a reference on the desktop and indirectly the desktop window.
3267 // It is possible this referencing is useless, though it should not hurt...
3268 UserRefObjectCo(DesktopWindow
, &Ref
);
3270 //pti = PsGetCurrentThreadWin32Thread();
3271 Window
= co_WinPosWindowFromPoint(DesktopWindow
, &pt
, &hittest
);
3275 Ret
= UserHMGetHandle(Window
);
3284 if (Window
) UserDereferenceObject(Window
);
3285 if (DesktopWindow
) UserDerefObjectCo(DesktopWindow
);
3287 TRACE("Leave NtUserWindowFromPoint, ret=%i\n",_ret_
);