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;
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
->spwndParent
== UserGetDesktopWindow() && !ActivateOtherWindowMin(Wnd
) ) ||
2223 ( Wnd
== pti
->MessageQueue
->spwndActive
&& pti
->MessageQueue
== IntGetFocusMessageQueue() ) )
2225 co_WinPosActivateOtherWindow(Wnd
);
2228 /* Revert focus to parent */
2229 if (Wnd
== pti
->MessageQueue
->spwndFocus
)
2231 Parent
= Wnd
->spwndParent
;
2232 if (Wnd
->spwndParent
== UserGetDesktopWindow()) Parent
= 0;
2233 co_UserSetFocus(Parent
);
2237 /* FIXME: Check for window destruction. */
2239 if ((Wnd
->state
& WNDS_SENDSIZEMOVEMSGS
) &&
2240 !(Wnd
->state2
& WNDS2_INDESTROY
))
2242 co_WinPosSendSizeMove(Wnd
);
2245 /* if previous state was minimized Windows sets focus to the window */
2246 if (style
& WS_MINIMIZE
)
2248 co_UserSetFocus(Wnd
);
2249 // Fix wine Win test_SetFocus todo #3,
2250 if (!(style
& WS_CHILD
)) co_IntSendMessageNoWait(UserHMGetHandle(Wnd
), WM_ACTIVATE
, WA_ACTIVE
, 0);
2257 co_WinPosSearchChildren(
2266 if (!(ScopeWin
->style
& WS_VISIBLE
))
2271 if ((ScopeWin
->style
& WS_DISABLED
))
2276 if (!IntPtInWindow(ScopeWin
, Point
->x
, Point
->y
))
2281 UserReferenceObject(ScopeWin
);
2283 if ( RECTL_bPointInRect(&ScopeWin
->rcClient
, Point
->x
, Point
->y
) )
2285 List
= IntWinListChildren(ScopeWin
);
2288 for (phWnd
= List
; *phWnd
; ++phWnd
)
2290 if (!(pwndChild
= ValidateHwndNoErr(*phWnd
)))
2295 pwndChild
= co_WinPosSearchChildren(pwndChild
, Point
, HitTest
);
2297 if(pwndChild
!= NULL
)
2299 /* We found a window. Don't send any more WM_NCHITTEST messages */
2300 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2301 UserDereferenceObject(ScopeWin
);
2305 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2309 if (ScopeWin
->head
.pti
== PsGetCurrentThreadWin32Thread())
2311 *HitTest
= (USHORT
)co_IntSendMessage(ScopeWin
->head
.h
, WM_NCHITTEST
, 0,
2312 MAKELONG(Point
->x
, Point
->y
));
2313 if ((*HitTest
) == (USHORT
)HTTRANSPARENT
)
2315 UserDereferenceObject(ScopeWin
);
2320 *HitTest
= HTCLIENT
;
2326 co_WinPosWindowFromPoint(PWND ScopeWin
, POINT
*WinPoint
, USHORT
* HitTest
)
2329 POINT Point
= *WinPoint
;
2330 USER_REFERENCE_ENTRY Ref
;
2332 if( ScopeWin
== NULL
)
2334 ScopeWin
= UserGetDesktopWindow();
2335 if(ScopeWin
== NULL
)
2339 *HitTest
= HTNOWHERE
;
2341 ASSERT_REFS_CO(ScopeWin
);
2342 UserRefObjectCo(ScopeWin
, &Ref
);
2344 Window
= co_WinPosSearchChildren(ScopeWin
, &Point
, HitTest
);
2346 UserDerefObjectCo(ScopeWin
);
2348 ASSERT_REFS_CO(Window
);
2349 ASSERT_REFS_CO(ScopeWin
);
2355 IntRealChildWindowFromPoint(PWND Parent
, LONG x
, LONG y
)
2359 PWND pwndHit
= NULL
;
2364 if (Parent
!= UserGetDesktopWindow())
2366 Pt
.x
+= Parent
->rcClient
.left
;
2367 Pt
.y
+= Parent
->rcClient
.top
;
2370 if (!IntPtInWindow(Parent
, Pt
.x
, Pt
.y
)) return NULL
;
2372 if ((List
= IntWinListChildren(Parent
)))
2374 for (phWnd
= List
; *phWnd
; phWnd
++)
2377 if ((Child
= ValidateHwndNoErr(*phWnd
)))
2379 if ( Child
->style
& WS_VISIBLE
&& IntPtInWindow(Child
, Pt
.x
, Pt
.y
) )
2381 if ( Child
->pcls
->atomClassName
!= gpsi
->atomSysClass
[ICLS_BUTTON
] ||
2382 (Child
->style
& BS_TYPEMASK
) != BS_GROUPBOX
)
2384 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2391 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2393 return pwndHit
? pwndHit
: Parent
;
2397 IntChildWindowFromPointEx(PWND Parent
, LONG x
, LONG y
, UINT uiFlags
)
2401 PWND pwndHit
= NULL
;
2406 if (Parent
!= UserGetDesktopWindow())
2408 if (Parent
->ExStyle
& WS_EX_LAYOUTRTL
)
2409 Pt
.x
= Parent
->rcClient
.right
- Pt
.x
;
2411 Pt
.x
+= Parent
->rcClient
.left
;
2412 Pt
.y
+= Parent
->rcClient
.top
;
2415 if (!IntPtInWindow(Parent
, Pt
.x
, Pt
.y
)) return NULL
;
2417 if ((List
= IntWinListChildren(Parent
)))
2419 for (phWnd
= List
; *phWnd
; phWnd
++)
2422 if ((Child
= ValidateHwndNoErr(*phWnd
)))
2424 if (uiFlags
& (CWP_SKIPINVISIBLE
|CWP_SKIPDISABLED
))
2426 if (!(Child
->style
& WS_VISIBLE
) && (uiFlags
& CWP_SKIPINVISIBLE
)) continue;
2427 if ((Child
->style
& WS_DISABLED
) && (uiFlags
& CWP_SKIPDISABLED
)) continue;
2430 if (uiFlags
& CWP_SKIPTRANSPARENT
)
2432 if (Child
->ExStyle
& WS_EX_TRANSPARENT
) continue;
2435 if (IntPtInWindow(Child
, Pt
.x
, Pt
.y
))
2442 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2444 return pwndHit
? pwndHit
: Parent
;
2449 IntDeferWindowPos( HDWP hdwp
,
2460 HDWP retvalue
= hdwp
;
2462 TRACE("hdwp %p, hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
2463 hdwp
, hwnd
, hwndAfter
, x
, y
, cx
, cy
, flags
);
2465 if (flags
& ~(SWP_NOSIZE
| SWP_NOMOVE
|
2466 SWP_NOZORDER
| SWP_NOREDRAW
|
2467 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
2468 SWP_NOOWNERZORDER
|SWP_SHOWWINDOW
|
2469 SWP_HIDEWINDOW
| SWP_FRAMECHANGED
))
2471 EngSetLastError(ERROR_INVALID_PARAMETER
);
2475 if (!(pDWP
= (PSMWP
)UserGetObject(gHandleTable
, hdwp
, TYPE_SETWINDOWPOS
)))
2477 EngSetLastError(ERROR_INVALID_DWP_HANDLE
);
2481 for (i
= 0; i
< pDWP
->ccvr
; i
++)
2483 if (pDWP
->acvr
[i
].pos
.hwnd
== hwnd
)
2485 /* Merge with the other changes */
2486 if (!(flags
& SWP_NOZORDER
))
2488 pDWP
->acvr
[i
].pos
.hwndInsertAfter
= hwndAfter
;
2490 if (!(flags
& SWP_NOMOVE
))
2492 pDWP
->acvr
[i
].pos
.x
= x
;
2493 pDWP
->acvr
[i
].pos
.y
= y
;
2495 if (!(flags
& SWP_NOSIZE
))
2497 pDWP
->acvr
[i
].pos
.cx
= cx
;
2498 pDWP
->acvr
[i
].pos
.cy
= cy
;
2500 pDWP
->acvr
[i
].pos
.flags
&= flags
| ~(SWP_NOSIZE
| SWP_NOMOVE
|
2501 SWP_NOZORDER
| SWP_NOREDRAW
|
2502 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
2504 pDWP
->acvr
[i
].pos
.flags
|= flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
|
2509 if (pDWP
->ccvr
>= pDWP
->ccvrAlloc
)
2511 PCVR newpos
= ExAllocatePoolWithTag(PagedPool
, pDWP
->ccvrAlloc
* 2 * sizeof(CVR
), USERTAG_SWP
);
2517 RtlZeroMemory(newpos
, pDWP
->ccvrAlloc
* 2 * sizeof(CVR
));
2518 RtlCopyMemory(newpos
, pDWP
->acvr
, pDWP
->ccvrAlloc
* sizeof(CVR
));
2519 ExFreePoolWithTag(pDWP
->acvr
, USERTAG_SWP
);
2520 pDWP
->ccvrAlloc
*= 2;
2521 pDWP
->acvr
= newpos
;
2523 pDWP
->acvr
[pDWP
->ccvr
].pos
.hwnd
= hwnd
;
2524 pDWP
->acvr
[pDWP
->ccvr
].pos
.hwndInsertAfter
= hwndAfter
;
2525 pDWP
->acvr
[pDWP
->ccvr
].pos
.x
= x
;
2526 pDWP
->acvr
[pDWP
->ccvr
].pos
.y
= y
;
2527 pDWP
->acvr
[pDWP
->ccvr
].pos
.cx
= cx
;
2528 pDWP
->acvr
[pDWP
->ccvr
].pos
.cy
= cy
;
2529 pDWP
->acvr
[pDWP
->ccvr
].pos
.flags
= flags
;
2530 pDWP
->acvr
[pDWP
->ccvr
].hrgnClip
= NULL
;
2531 pDWP
->acvr
[pDWP
->ccvr
].hrgnInterMonitor
= NULL
;
2537 BOOL FASTCALL
IntEndDeferWindowPosEx( HDWP hdwp
, BOOL sAsync
)
2544 TRACE("%p\n", hdwp
);
2546 if (!(pDWP
= (PSMWP
)UserGetObject(gHandleTable
, hdwp
, TYPE_SETWINDOWPOS
)))
2548 EngSetLastError(ERROR_INVALID_DWP_HANDLE
);
2552 for (i
= 0, winpos
= pDWP
->acvr
; res
&& i
< pDWP
->ccvr
; i
++, winpos
++)
2555 USER_REFERENCE_ENTRY Ref
;
2557 TRACE("hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
2558 winpos
->pos
.hwnd
, winpos
->pos
.hwndInsertAfter
, winpos
->pos
.x
, winpos
->pos
.y
,
2559 winpos
->pos
.cx
, winpos
->pos
.cy
, winpos
->pos
.flags
);
2561 pwnd
= ValidateHwndNoErr(winpos
->pos
.hwnd
);
2565 UserRefObjectCo(pwnd
, &Ref
);
2570 PWINDOWPOS ppos
= ExAllocatePoolWithTag(PagedPool
, sizeof(WINDOWPOS
), USERTAG_SWP
);
2573 *ppos
= winpos
->pos
;
2574 /* Yes it's a pointer inside Win32k! */
2575 lRes
= co_IntSendMessageNoWait( winpos
->pos
.hwnd
, WM_ASYNC_SETWINDOWPOS
, 0, (LPARAM
)ppos
);
2576 /* We handle this the same way as Event Hooks and Hooks. */
2579 ExFreePoolWithTag(ppos
, USERTAG_SWP
);
2584 res
= co_WinPosSetWindowPos( pwnd
,
2585 winpos
->pos
.hwndInsertAfter
,
2592 // Hack to pass tests.... Must have some work to do so clear the error.
2593 if (res
&& (winpos
->pos
.flags
& (SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOZORDER
)) == SWP_NOZORDER
)
2594 EngSetLastError(ERROR_SUCCESS
);
2596 UserDerefObjectCo(pwnd
);
2598 ExFreePoolWithTag(pDWP
->acvr
, USERTAG_SWP
);
2599 UserDereferenceObject(pDWP
);
2600 UserDeleteObject(hdwp
, TYPE_SETWINDOWPOS
);
2608 NtUserChildWindowFromPointEx(HWND hwndParent
,
2614 TRACE("Enter NtUserChildWindowFromPointEx\n");
2615 UserEnterExclusive();
2616 if ((pwndParent
= UserGetWindowObject(hwndParent
)))
2618 pwndParent
= IntChildWindowFromPointEx(pwndParent
, x
, y
, uiFlags
);
2621 TRACE("Leave NtUserChildWindowFromPointEx\n");
2622 return pwndParent
? UserHMGetHandle(pwndParent
) : NULL
;
2629 NtUserEndDeferWindowPosEx(HDWP WinPosInfo
,
2633 TRACE("Enter NtUserEndDeferWindowPosEx\n");
2634 UserEnterExclusive();
2635 Ret
= IntEndDeferWindowPosEx(WinPosInfo
, (BOOL
)Unknown1
);
2636 TRACE("Leave NtUserEndDeferWindowPosEx, ret=%i\n", Ret
);
2645 NtUserDeferWindowPos(HDWP WinPosInfo
,
2647 HWND WndInsertAfter
,
2656 UINT Tmp
= ~(SWP_ASYNCWINDOWPOS
|SWP_DEFERERASE
|SWP_NOSENDCHANGING
|SWP_NOREPOSITION
|
2657 SWP_NOCOPYBITS
|SWP_HIDEWINDOW
|SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|
2658 SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_NOZORDER
|SWP_NOMOVE
|SWP_NOSIZE
);
2660 TRACE("Enter NtUserDeferWindowPos\n");
2661 UserEnterExclusive();
2665 EngSetLastError(ERROR_INVALID_FLAGS
);
2669 pWnd
= UserGetWindowObject(Wnd
);
2670 if ( !pWnd
|| // FIXME:
2671 pWnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
2672 pWnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
2677 if ( WndInsertAfter
&&
2678 WndInsertAfter
!= HWND_BOTTOM
&&
2679 WndInsertAfter
!= HWND_TOPMOST
&&
2680 WndInsertAfter
!= HWND_NOTOPMOST
)
2682 pWndIA
= UserGetWindowObject(WndInsertAfter
);
2684 pWndIA
== UserGetDesktopWindow() ||
2685 pWndIA
== UserGetMessageWindow() )
2691 Ret
= IntDeferWindowPos(WinPosInfo
, Wnd
, WndInsertAfter
, x
, y
, cx
, cy
, Flags
);
2694 TRACE("Leave NtUserDeferWindowPos, ret=%i\n", Ret
);
2703 NtUserGetInternalWindowPos( HWND hWnd
,
2710 WINDOWPLACEMENT wndpl
;
2714 if (!(Window
= UserGetWindowObject(hWnd
)))
2724 ProbeForWrite(rectWnd
,
2730 ProbeForWrite(ptIcon
,
2736 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2738 SetLastNtError(_SEH2_GetExceptionCode());
2743 wndpl
.length
= sizeof(WINDOWPLACEMENT
);
2745 if (IntGetWindowPlacement(Window
, &wndpl
) && !Hit
)
2751 RtlCopyMemory(rectWnd
, &wndpl
.rcNormalPosition
, sizeof(RECT
));
2755 RtlCopyMemory(ptIcon
, &wndpl
.ptMinPosition
, sizeof(POINT
));
2759 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2761 SetLastNtError(_SEH2_GetExceptionCode());
2766 if (!Hit
) Ret
= wndpl
.showCmd
;
2777 NtUserGetWindowPlacement(HWND hWnd
,
2778 WINDOWPLACEMENT
*lpwndpl
)
2781 WINDOWPLACEMENT Safepl
;
2783 DECLARE_RETURN(BOOL
);
2785 TRACE("Enter NtUserGetWindowPlacement\n");
2788 if (!(Wnd
= UserGetWindowObject(hWnd
)))
2793 Status
= MmCopyFromCaller(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
2794 if(!NT_SUCCESS(Status
))
2796 SetLastNtError(Status
);
2799 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
2804 IntGetWindowPlacement(Wnd
, &Safepl
);
2806 Status
= MmCopyToCaller(lpwndpl
, &Safepl
, sizeof(WINDOWPLACEMENT
));
2807 if(!NT_SUCCESS(Status
))
2809 SetLastNtError(Status
);
2816 TRACE("Leave NtUserGetWindowPlacement, ret=%i\n",_ret_
);
2825 UINT cmd
, // Wine SW_ commands
2830 TRACE("Enter NtUserMinMaximize\n");
2831 UserEnterExclusive();
2833 pWnd
= UserGetWindowObject(hWnd
);
2834 if ( !pWnd
|| // FIXME:
2835 pWnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
2836 pWnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
2841 if ( cmd
> SW_MAX
|| pWnd
->state2
& WNDS2_INDESTROY
)
2843 EngSetLastError(ERROR_INVALID_PARAMETER
);
2847 cmd
|= Hide
? SW_HIDE
: 0;
2849 co_WinPosShowWindow(pWnd
, cmd
);
2852 TRACE("Leave NtUserMinMaximize\n");
2854 return 0; // Always NULL?
2869 return NtUserSetWindowPos(hWnd
, 0, X
, Y
, nWidth
, nHeight
,
2870 (bRepaint
? SWP_NOZORDER
| SWP_NOACTIVATE
:
2871 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
));
2878 NtUserRealChildWindowFromPoint(HWND Parent
,
2883 TRACE("Enter NtUserRealChildWindowFromPoint\n");
2885 if ((pwndParent
= UserGetWindowObject(Parent
)))
2887 pwndParent
= IntRealChildWindowFromPoint(pwndParent
, x
, y
);
2890 TRACE("Leave NtUserRealChildWindowFromPoint\n");
2891 return pwndParent
? UserHMGetHandle(pwndParent
) : NULL
;
2900 HWND hWndInsertAfter
,
2907 DECLARE_RETURN(BOOL
);
2908 PWND Window
, pWndIA
;
2910 USER_REFERENCE_ENTRY Ref
;
2912 TRACE("Enter NtUserSetWindowPos\n");
2913 UserEnterExclusive();
2915 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
2916 Window
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
2917 Window
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
2919 ERR("NtUserSetWindowPos bad window handle!\n");
2923 if ( hWndInsertAfter
&&
2924 hWndInsertAfter
!= HWND_BOTTOM
&&
2925 hWndInsertAfter
!= HWND_TOPMOST
&&
2926 hWndInsertAfter
!= HWND_NOTOPMOST
)
2928 if (!(pWndIA
= UserGetWindowObject(hWndInsertAfter
)) ||
2929 pWndIA
== UserGetDesktopWindow() ||
2930 pWndIA
== UserGetMessageWindow() )
2932 ERR("NtUserSetWindowPos bad insert window handle!\n");
2937 /* First make sure that coordinates are valid for WM_WINDOWPOSCHANGING */
2938 if (!(uFlags
& SWP_NOMOVE
))
2940 if (X
< -32768) X
= -32768;
2941 else if (X
> 32767) X
= 32767;
2942 if (Y
< -32768) Y
= -32768;
2943 else if (Y
> 32767) Y
= 32767;
2945 if (!(uFlags
& SWP_NOSIZE
))
2948 else if (cx
> 32767) cx
= 32767;
2950 else if (cy
> 32767) cy
= 32767;
2953 UserRefObjectCo(Window
, &Ref
);
2954 ret
= co_WinPosSetWindowPos(Window
, hWndInsertAfter
, X
, Y
, cx
, cy
, uFlags
);
2955 UserDerefObjectCo(Window
);
2960 TRACE("Leave NtUserSetWindowPos, ret=%i\n",_ret_
);
2976 INT flags
= (SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
);
2977 BOOLEAN Ret
= FALSE
;
2978 DECLARE_RETURN(INT
);
2980 TRACE("Enter NtUserSetWindowRgn\n");
2981 UserEnterExclusive();
2983 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
2984 Window
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
2985 Window
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
2990 if (hRgn
) // The region will be deleted in user32.
2992 if (GreIsHandleValid(hRgn
))
2994 hrgnCopy
= IntSysCreateRectRgn(0, 0, 0, 0);
2995 /* The coordinates of a window's window region are relative to the
2996 upper-left corner of the window, not the client area of the window. */
2997 NtGdiCombineRgn( hrgnCopy
, hRgn
, 0, RGN_COPY
);
3007 if (Window
->hrgnClip
)
3009 /* Delete no longer needed region handle */
3010 IntGdiSetRegionOwner(Window
->hrgnClip
, GDI_OBJ_HMGR_POWNED
);
3011 GreDeleteObject(Window
->hrgnClip
);
3016 /* Set public ownership */
3017 IntGdiSetRegionOwner(hrgnCopy
, GDI_OBJ_HMGR_PUBLIC
);
3019 Window
->hrgnClip
= hrgnCopy
;
3021 Ret
= co_WinPosSetWindowPos(Window
, HWND_TOP
, 0, 0, 0, 0, bRedraw
? flags
: (flags
|SWP_NOREDRAW
) );
3026 TRACE("Leave NtUserSetWindowRgn, ret=%i\n",_ret_
);
3035 NtUserSetInternalWindowPos(
3041 WINDOWPLACEMENT wndpl
;
3046 DECLARE_RETURN(BOOL
);
3047 USER_REFERENCE_ENTRY Ref
;
3049 TRACE("Enter NtUserSetWindowPlacement\n");
3050 UserEnterExclusive();
3052 if (!(Wnd
= UserGetWindowObject(hwnd
)) || // FIXME:
3053 Wnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3054 Wnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3063 ProbeForRead(lppt
, sizeof(POINT
), 1);
3064 RtlCopyMemory(&pt
, lppt
, sizeof(POINT
));
3068 ProbeForRead(lprect
, sizeof(RECT
), 1);
3069 RtlCopyMemory(&rect
, lprect
, sizeof(RECT
));
3072 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3074 SetLastNtError(_SEH2_GetExceptionCode());
3075 _SEH2_YIELD(RETURN( FALSE
));
3079 wndpl
.length
= sizeof(wndpl
);
3080 wndpl
.showCmd
= showCmd
;
3081 wndpl
.flags
= flags
= 0;
3086 wndpl
.flags
|= WPF_SETMINPOSITION
;
3087 wndpl
.ptMinPosition
= pt
;
3091 flags
|= PLACE_RECT
;
3092 wndpl
.rcNormalPosition
= rect
;
3095 UserRefObjectCo(Wnd
, &Ref
);
3096 IntSetWindowPlacement(Wnd
, &wndpl
, flags
);
3097 UserDerefObjectCo(Wnd
);
3101 TRACE("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_
);
3110 NtUserSetWindowPlacement(HWND hWnd
,
3111 WINDOWPLACEMENT
*lpwndpl
)
3114 WINDOWPLACEMENT Safepl
;
3116 DECLARE_RETURN(BOOL
);
3117 USER_REFERENCE_ENTRY Ref
;
3119 TRACE("Enter NtUserSetWindowPlacement\n");
3120 UserEnterExclusive();
3122 if (!(Wnd
= UserGetWindowObject(hWnd
)) || // FIXME:
3123 Wnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3124 Wnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3131 ProbeForRead(lpwndpl
, sizeof(WINDOWPLACEMENT
), 1);
3132 RtlCopyMemory(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
3134 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3136 SetLastNtError(_SEH2_GetExceptionCode());
3137 _SEH2_YIELD(RETURN( FALSE
));
3141 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
3146 Flags
= PLACE_MAX
| PLACE_RECT
;
3147 if (Safepl
.flags
& WPF_SETMINPOSITION
) Flags
|= PLACE_MIN
;
3148 UserRefObjectCo(Wnd
, &Ref
);
3149 IntSetWindowPlacement(Wnd
, &Safepl
, Flags
);
3150 UserDerefObjectCo(Wnd
);
3154 TRACE("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_
);
3163 NtUserShowWindowAsync(HWND hWnd
, LONG nCmdShow
)
3167 DECLARE_RETURN(BOOL
);
3168 USER_REFERENCE_ENTRY Ref
;
3170 TRACE("Enter NtUserShowWindowAsync\n");
3171 UserEnterExclusive();
3173 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
3174 Window
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3175 Window
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3180 if ( nCmdShow
> SW_MAX
)
3182 EngSetLastError(ERROR_INVALID_PARAMETER
);
3186 UserRefObjectCo(Window
, &Ref
);
3187 ret
= co_IntSendMessageNoWait( hWnd
, WM_ASYNC_SHOWWINDOW
, nCmdShow
, 0 );
3188 UserDerefObjectCo(Window
);
3189 if (-1 == (int) ret
|| !ret
) ret
= FALSE
;
3194 TRACE("Leave NtUserShowWindowAsync, ret=%i\n",_ret_
);
3203 NtUserShowWindow(HWND hWnd
, LONG nCmdShow
)
3207 DECLARE_RETURN(BOOL
);
3208 USER_REFERENCE_ENTRY Ref
;
3210 TRACE("Enter NtUserShowWindow\n");
3211 UserEnterExclusive();
3213 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME: