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
));
143 IntClientToScreen(PWND Wnd
, LPPOINT lpPoint
)
145 if (Wnd
&& Wnd
->fnid
!= FNID_DESKTOP
)
147 if (Wnd
->ExStyle
& WS_EX_LAYOUTRTL
)
148 lpPoint
->x
= Wnd
->rcClient
.right
- lpPoint
->x
;
150 lpPoint
->x
+= Wnd
->rcClient
.left
;
151 lpPoint
->y
+= Wnd
->rcClient
.top
;
157 IntScreenToClient(PWND Wnd
, LPPOINT lpPoint
)
159 if (Wnd
&& Wnd
->fnid
!= FNID_DESKTOP
)
161 if (Wnd
->ExStyle
& WS_EX_LAYOUTRTL
)
162 lpPoint
->x
= Wnd
->rcClient
.right
- lpPoint
->x
;
164 lpPoint
->x
-= Wnd
->rcClient
.left
;
165 lpPoint
->y
-= Wnd
->rcClient
.top
;
170 BOOL FASTCALL
IsChildVisible(PWND pWnd
)
174 if ( (pWnd
->style
& (WS_POPUP
|WS_CHILD
)) != WS_CHILD
||
175 !(pWnd
= pWnd
->spwndParent
) )
178 while (pWnd
->style
& WS_VISIBLE
);
182 PWND FASTCALL
IntGetLastTopMostWindow(VOID
)
185 PDESKTOP rpdesk
= gptiCurrent
->rpdesk
;
188 (pWnd
= rpdesk
->pDeskInfo
->spwnd
->spwndChild
) &&
189 pWnd
->ExStyle
& WS_EX_TOPMOST
)
193 if (!pWnd
->spwndNext
) break;
194 if (!(pWnd
->spwndNext
->ExStyle
& WS_EX_TOPMOST
)) break;
195 pWnd
= pWnd
->spwndNext
;
203 // This helps with bug 6751 forcing modal dialog active when another app is minimized or closed.
205 BOOL FASTCALL
ActivateOtherWindowMin(PWND Wnd
)
207 BOOL ActivePrev
, FindTopWnd
;
208 PWND pWndTopMost
, pWndChild
, pWndSetActive
, pWndTemp
, pWndDesk
;
209 USER_REFERENCE_ENTRY Ref
;
210 PTHREADINFO pti
= gptiCurrent
;
213 ActivePrev
= (pti
->MessageQueue
->spwndActivePrev
!= NULL
);
216 if ((pWndTopMost
= IntGetLastTopMostWindow()))
217 pWndChild
= pWndTopMost
->spwndNext
;
219 pWndChild
= Wnd
->spwndParent
->spwndChild
;
224 pWndSetActive
= pti
->MessageQueue
->spwndActivePrev
;
226 pWndSetActive
= pWndChild
;
232 if ( VerifyWnd(pWndSetActive
) &&
233 !(pWndSetActive
->ExStyle
& WS_EX_NOACTIVATE
) &&
234 (pWndSetActive
->style
& (WS_VISIBLE
|WS_DISABLED
)) == WS_VISIBLE
&&
235 (!(pWndSetActive
->style
& WS_ICONIC
) /* FIXME MinMax pos? */ ) )
237 if (!(pWndSetActive
->ExStyle
& WS_EX_TOOLWINDOW
) )
239 UserRefObjectCo(pWndSetActive
, &Ref
);
240 co_IntSetForegroundWindow(pWndSetActive
);
241 UserDerefObjectCo(pWndSetActive
);
242 //ERR("AOWM 2 Exit Good\n");
245 if (!pWndTemp
) pWndTemp
= pWndSetActive
;
250 pWndSetActive
= pWndChild
;
253 pWndSetActive
= pWndSetActive
->spwndNext
;
256 if ( !FindTopWnd
) break;
261 pWndChild
= pWndChild
->spwndParent
->spwndChild
;
265 if (!(pWndDesk
= IntGetThreadDesktopWindow(pti
)))
270 pWndChild
= pWndDesk
->spwndChild
;
273 if ((pWndSetActive
= pWndTemp
))
275 UserRefObjectCo(pWndSetActive
, &Ref
);
276 co_IntSetForegroundWindow(pWndSetActive
);
277 UserDerefObjectCo(pWndSetActive
);
278 //ERR("AOWM 3 Exit Good\n");
281 //ERR("AOWM 4 Bad\n");
285 /*******************************************************************
286 * can_activate_window
288 * Check if we can activate the specified window.
291 BOOL FASTCALL
can_activate_window( PWND Wnd OPTIONAL
)
295 if (!Wnd
) return FALSE
;
298 if (!(style
& WS_VISIBLE
)) return FALSE
;
299 if (style
& WS_MINIMIZE
) return FALSE
;
300 if ((style
& (WS_POPUP
|WS_CHILD
)) == WS_CHILD
) return FALSE
;
302 /* FIXME: This window could be disable because the child that closed
304 //return !(style & WS_DISABLED);
308 /*******************************************************************
309 * WinPosActivateOtherWindow
311 * Activates window other than pWnd.
314 co_WinPosActivateOtherWindow(PWND Wnd
)
318 USER_REFERENCE_ENTRY Ref
;
322 if (IntIsDesktopWindow(Wnd
))
324 IntSetFocusMessageQueue(NULL
);
328 /* If this is popup window, try to activate the owner first. */
329 if ((Wnd
->style
& WS_POPUP
) && (WndTo
= Wnd
->spwndOwner
))
331 WndTo
= UserGetAncestor( WndTo
, GA_ROOT
);
332 if (can_activate_window(WndTo
)) goto done
;
335 /* Pick a next top-level window. */
336 /* FIXME: Search for non-tooltip windows first. */
340 if (!(WndTo
= WndTo
->spwndNext
)) break;
341 if (can_activate_window( WndTo
)) break;
346 if (WndTo
) UserRefObjectCo(WndTo
, &Ref
);
348 Fg
= UserGetForegroundWindow();
349 if ((!Fg
|| Wnd
->head
.h
== Fg
) && WndTo
) // FIXME: Ok if WndTo is NULL?? No, rule #4.
351 /* FIXME: Wine can pass WndTo = NULL to co_IntSetForegroundWindow. Hmm... */
352 if (co_IntSetForegroundWindow(WndTo
))
354 UserDerefObjectCo(WndTo
);
359 if (!co_IntSetActiveWindow(WndTo
,&previous
,FALSE
,TRUE
,FALSE
) || /* Ok for WndTo to be NULL here */
362 co_IntSetActiveWindow(0,NULL
,FALSE
,TRUE
,FALSE
);
364 if (WndTo
) UserDerefObjectCo(WndTo
);
370 co_WinPosArrangeIconicWindows(PWND parent
)
373 INT i
, x
, y
, xspacing
, yspacing
, sx
, sy
;
374 HWND
*List
= IntWinListChildren(parent
);
376 ASSERT_REFS_CO(parent
);
378 /* Check if we found any children */
384 IntGetClientRect( parent
, &rectParent
);
385 // FIXME: Support gspv.mm.iArrange.
387 y
= rectParent
.bottom
;
389 xspacing
= (UserGetSystemMetrics(SM_CXMINSPACING
)/2)+UserGetSystemMetrics(SM_CXBORDER
);
390 yspacing
= (UserGetSystemMetrics(SM_CYMINSPACING
)/2)+UserGetSystemMetrics(SM_CYBORDER
);
392 //ERR("X:%d Y:%d XS:%d YS:%d\n",x,y,xspacing,yspacing);
394 for(i
= 0; List
[i
]; i
++)
398 if (!(Child
= ValidateHwndNoErr(List
[i
])))
401 if((Child
->style
& WS_MINIMIZE
) != 0 )
403 USER_REFERENCE_ENTRY Ref
;
404 UserRefObjectCo(Child
, &Ref
);
406 sx
= x
+ UserGetSystemMetrics(SM_CXBORDER
);
407 sy
= y
- yspacing
- UserGetSystemMetrics(SM_CYBORDER
);
409 co_WinPosSetWindowPos( Child
, 0, sx
, sy
, 0, 0,
410 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
412 Child
->InternalPos
.IconPos
.x
= sx
;
413 Child
->InternalPos
.IconPos
.y
= sy
;
414 Child
->InternalPos
.flags
|= WPF_MININIT
;
415 Child
->InternalPos
.flags
&= ~WPF_SETMINPOSITION
;
417 UserDerefObjectCo(Child
);
419 if (x
<= (rectParent
.right
- UserGetSystemMetrics(SM_CXMINSPACING
)))
426 //ERR("X:%d Y:%d\n",x,y);
429 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
434 WinPosFindIconPos(PWND Window
, POINT
*Pos
)
437 PWND pwndChild
, pwndParent
;
438 int x
, y
, xspacing
, yspacing
;
440 pwndParent
= Window
->spwndParent
;
441 if (pwndParent
== UserGetDesktopWindow())
443 //ERR("Parent is Desktop, Min off screen!\n");
444 /* ReactOS doesn't support iconic minimize to desktop */
445 Pos
->x
= Pos
->y
= -32000;
446 Window
->InternalPos
.flags
|= WPF_MININIT
;
447 Window
->InternalPos
.IconPos
.x
= Pos
->x
;
448 Window
->InternalPos
.IconPos
.y
= Pos
->y
;
452 IntGetClientRect( pwndParent
, &rectParent
);
453 // FIXME: Support gspv.mm.iArrange.
455 y
= rectParent
.bottom
;
457 xspacing
= (UserGetSystemMetrics(SM_CXMINSPACING
)/2)+UserGetSystemMetrics(SM_CXBORDER
);
458 yspacing
= (UserGetSystemMetrics(SM_CYMINSPACING
)/2)+UserGetSystemMetrics(SM_CYBORDER
);
460 //ERR("X:%d Y:%d XS:%d YS:%d\n",Pos->x,Pos->y,xspacing,yspacing);
462 // Set to default position when minimized.
463 Pos
->x
= x
+ UserGetSystemMetrics(SM_CXBORDER
);
464 Pos
->y
= y
- yspacing
- UserGetSystemMetrics(SM_CYBORDER
);
466 for (pwndChild
= pwndParent
->spwndChild
; pwndChild
; pwndChild
= pwndChild
->spwndNext
)
468 if (pwndChild
== Window
) continue;
470 if (pwndChild
->style
& WS_VISIBLE
)
475 //ERR("Pos Child X %d Y %d!\n", pwndChild->InternalPos.IconPos.x, pwndChild->InternalPos.IconPos.y);
476 if ( pwndChild
->InternalPos
.IconPos
.x
== Pos
->x
&&
477 pwndChild
->InternalPos
.IconPos
.y
== Pos
->y
)
479 if (x
<= rectParent
.right
- UserGetSystemMetrics(SM_CXMINSPACING
))
486 Pos
->x
= x
+ UserGetSystemMetrics(SM_CXBORDER
);
487 Pos
->y
= y
- yspacing
- UserGetSystemMetrics(SM_CYBORDER
);
490 Window
->InternalPos
.IconPos
.x
= Pos
->x
;
491 Window
->InternalPos
.IconPos
.y
= Pos
->y
;
492 Window
->InternalPos
.flags
|= WPF_MININIT
;
493 //ERR("Position is set! X:%d Y:%d\n",Pos->x,Pos->y);
498 WinPosInitInternalPos(PWND Wnd
, RECTL
*RestoreRect
)
501 RECTL Rect
= *RestoreRect
;
503 if (Wnd
->spwndParent
!= UserGetDesktopWindow())
505 RECTL_vOffsetRect(&Rect
,
506 -Wnd
->spwndParent
->rcClient
.left
,
507 -Wnd
->spwndParent
->rcClient
.top
);
513 if (!Wnd
->InternalPosInitialized
)
515 // FIXME: Use check point Atom..
516 Wnd
->InternalPos
.flags
= 0;
517 Wnd
->InternalPos
.MaxPos
.x
= Wnd
->InternalPos
.MaxPos
.y
= -1;
518 Wnd
->InternalPos
.IconPos
.x
= Wnd
->InternalPos
.IconPos
.y
= -1;
519 Wnd
->InternalPos
.NormalRect
= Rect
;
520 Wnd
->InternalPosInitialized
= TRUE
;
523 if (Wnd
->style
& WS_MINIMIZE
)
525 Wnd
->InternalPos
.IconPos
= Size
;
526 Wnd
->InternalPos
.flags
|= WPF_MININIT
;
528 else if (Wnd
->style
& WS_MAXIMIZE
)
530 Wnd
->InternalPos
.flags
|= WPF_MAXINIT
;
532 if ( Wnd
->spwndParent
== Wnd
->head
.rpdesk
->pDeskInfo
->spwnd
)
534 if (Wnd
->state
& WNDS_MAXIMIZESTOMONITOR
)
536 Wnd
->InternalPos
.flags
&= ~WPF_MAXINIT
;
537 Wnd
->InternalPos
.MaxPos
.x
= Wnd
->InternalPos
.MaxPos
.y
= -1;
542 PMONITOR pmonitor
= UserMonitorFromRect(&Rect
, MONITOR_DEFAULTTOPRIMARY
);
543 // FIXME: support DPI aware, rcWorkDPI/Real etc..
544 WorkArea
= pmonitor
->rcMonitor
;
546 if (Wnd
->style
& WS_MAXIMIZEBOX
)
547 { // Support (Wnd->state & WNDS_HASCAPTION) || pmonitor->cFullScreen too.
548 if ((Wnd
->style
& WS_CAPTION
) == WS_CAPTION
|| !(Wnd
->style
& (WS_CHILD
| WS_POPUP
)))
550 WorkArea
= pmonitor
->rcWork
;
555 Wnd
->InternalPos
.MaxPos
.x
= Rect
.left
- WorkArea
.left
;
556 Wnd
->InternalPos
.MaxPos
.y
= Rect
.top
- WorkArea
.top
;
558 /*ERR("WinPosIP 2 X %d = R.l %d - W.l %d | Y %d = R.t %d - W.t %d\n",
559 Wnd->InternalPos.MaxPos.x,
560 Rect.left, WorkArea.left,
561 Wnd->InternalPos.MaxPos.y,
562 Rect.top, WorkArea.top);*/
566 Wnd
->InternalPos
.MaxPos
= Size
;
570 Wnd
->InternalPos
.NormalRect
= Rect
;
576 IntGetWindowPlacement(PWND Wnd
, WINDOWPLACEMENT
*lpwndpl
)
578 if (!Wnd
) return FALSE
;
580 if(lpwndpl
->length
!= sizeof(WINDOWPLACEMENT
))
587 WinPosInitInternalPos(Wnd
, &Wnd
->rcWindow
);
589 lpwndpl
->showCmd
= SW_HIDE
;
591 if ( Wnd
->style
& WS_MINIMIZE
)
592 lpwndpl
->showCmd
= SW_SHOWMINIMIZED
;
594 lpwndpl
->showCmd
= ( Wnd
->style
& WS_MAXIMIZE
) ? SW_SHOWMAXIMIZED
: SW_SHOWNORMAL
;
596 lpwndpl
->rcNormalPosition
= Wnd
->InternalPos
.NormalRect
;
598 if (Wnd
->InternalPos
.flags
& WPF_MININIT
) // Return if it was set!
600 lpwndpl
->ptMinPosition
.x
= Wnd
->InternalPos
.IconPos
.x
;
601 lpwndpl
->ptMinPosition
.y
= Wnd
->InternalPos
.IconPos
.y
;
604 lpwndpl
->ptMinPosition
.x
= lpwndpl
->ptMinPosition
.y
= -1;
606 if ( Wnd
->InternalPos
.flags
& WPF_MAXINIT
&& // Return if set and not maximized to monitor!
607 !(Wnd
->state
& WNDS_MAXIMIZESTOMONITOR
))
609 lpwndpl
->ptMaxPosition
.x
= Wnd
->InternalPos
.MaxPos
.x
;
610 lpwndpl
->ptMaxPosition
.y
= Wnd
->InternalPos
.MaxPos
.y
;
613 lpwndpl
->ptMaxPosition
.x
= lpwndpl
->ptMaxPosition
.y
= -1;
615 if ( Wnd
->spwndParent
== Wnd
->head
.rpdesk
->pDeskInfo
->spwnd
&&
616 !(Wnd
->ExStyle
& WS_EX_TOOLWINDOW
))
618 PMONITOR pmonitor
= UserMonitorFromRect(&lpwndpl
->rcNormalPosition
, MONITOR_DEFAULTTOPRIMARY
);
620 // FIXME: support DPI aware, rcWorkDPI/Real etc..
621 if (Wnd
->InternalPos
.flags
& WPF_MININIT
)
623 lpwndpl
->ptMinPosition
.x
-= (pmonitor
->rcWork
.left
- pmonitor
->rcMonitor
.left
);
624 lpwndpl
->ptMinPosition
.y
-= (pmonitor
->rcWork
.top
- pmonitor
->rcMonitor
.top
);
626 RECTL_vOffsetRect(&lpwndpl
->rcNormalPosition
,
627 pmonitor
->rcMonitor
.left
- pmonitor
->rcWork
.left
,
628 pmonitor
->rcMonitor
.top
- pmonitor
->rcWork
.top
);
631 if ( Wnd
->InternalPos
.flags
& WPF_RESTORETOMAXIMIZED
|| Wnd
->style
& WS_MAXIMIZE
)
632 lpwndpl
->flags
|= WPF_RESTORETOMAXIMIZED
;
634 if ( ((Wnd
->style
& (WS_CHILD
|WS_POPUP
)) == WS_CHILD
) && Wnd
->InternalPos
.flags
& WPF_SETMINPOSITION
)
635 lpwndpl
->flags
|= WPF_SETMINPOSITION
;
640 /* make sure the specified rect is visible on screen */
641 static void make_rect_onscreen( RECT
*rect
)
643 PMONITOR pmonitor
= UserMonitorFromRect( rect
, MONITOR_DEFAULTTONEAREST
); // Wine uses this.
645 // FIXME: support DPI aware, rcWorkDPI/Real etc..
646 if (!pmonitor
) return;
647 /* FIXME: map coordinates from rcWork to rcMonitor */
648 if (rect
->right
<= pmonitor
->rcWork
.left
)
650 rect
->right
+= pmonitor
->rcWork
.left
- rect
->left
;
651 rect
->left
= pmonitor
->rcWork
.left
;
653 else if (rect
->left
>= pmonitor
->rcWork
.right
)
655 rect
->left
+= pmonitor
->rcWork
.right
- rect
->right
;
656 rect
->right
= pmonitor
->rcWork
.right
;
658 if (rect
->bottom
<= pmonitor
->rcWork
.top
)
660 rect
->bottom
+= pmonitor
->rcWork
.top
- rect
->top
;
661 rect
->top
= pmonitor
->rcWork
.top
;
663 else if (rect
->top
>= pmonitor
->rcWork
.bottom
)
665 rect
->top
+= pmonitor
->rcWork
.bottom
- rect
->bottom
;
666 rect
->bottom
= pmonitor
->rcWork
.bottom
;
670 /* make sure the specified point is visible on screen */
671 static void make_point_onscreen( POINT
*pt
)
675 RECTL_vSetRect( &rect
, pt
->x
, pt
->y
, pt
->x
+ 1, pt
->y
+ 1 );
676 make_rect_onscreen( &rect
);
682 IntSetWindowPlacement(PWND Wnd
, WINDOWPLACEMENT
*wpl
, UINT Flags
)
687 if ( Flags
& PLACE_MIN
) make_point_onscreen( &wpl
->ptMinPosition
);
688 if ( Flags
& PLACE_MAX
) make_point_onscreen( &wpl
->ptMaxPosition
);
689 if ( Flags
& PLACE_RECT
) make_rect_onscreen( &wpl
->rcNormalPosition
);
691 if (!Wnd
|| Wnd
== Wnd
->head
.rpdesk
->pDeskInfo
->spwnd
) return FALSE
;
693 if ( Flags
& PLACE_MIN
) Wnd
->InternalPos
.IconPos
= wpl
->ptMinPosition
;
694 if ( Flags
& PLACE_MAX
) Wnd
->InternalPos
.MaxPos
= wpl
->ptMaxPosition
;
695 if ( Flags
& PLACE_RECT
) Wnd
->InternalPos
.NormalRect
= wpl
->rcNormalPosition
;
697 SWP_Flags
= SWP_NOZORDER
| SWP_NOACTIVATE
| ((wpl
->flags
& WPF_ASYNCWINDOWPLACEMENT
) ? SWP_ASYNCWINDOWPOS
: 0);
699 if (Wnd
->style
& WS_MINIMIZE
)
701 if (Flags
& PLACE_MIN
|| Wnd
->InternalPos
.flags
& WPF_SETMINPOSITION
)
703 co_WinPosSetWindowPos(Wnd
, HWND_TOP
,
704 wpl
->ptMinPosition
.x
, wpl
->ptMinPosition
.y
, 0, 0,
705 SWP_NOSIZE
| SWP_Flags
);
706 Wnd
->InternalPos
.flags
|= WPF_MININIT
;
709 else if (Wnd
->style
& WS_MAXIMIZE
)
711 if (Flags
& PLACE_MAX
)
713 co_WinPosSetWindowPos(Wnd
, HWND_TOP
,
714 wpl
->ptMaxPosition
.x
, wpl
->ptMaxPosition
.y
, 0, 0,
715 SWP_NOSIZE
| SWP_Flags
);
716 Wnd
->InternalPos
.flags
|= WPF_MAXINIT
;
719 else if (Flags
& PLACE_RECT
)
721 co_WinPosSetWindowPos(Wnd
, HWND_TOP
,
722 wpl
->rcNormalPosition
.left
, wpl
->rcNormalPosition
.top
,
723 wpl
->rcNormalPosition
.right
- wpl
->rcNormalPosition
.left
,
724 wpl
->rcNormalPosition
.bottom
- wpl
->rcNormalPosition
.top
,
728 sAsync
= (Wnd
->head
.pti
->MessageQueue
!= gptiCurrent
->MessageQueue
&& wpl
->flags
& WPF_ASYNCWINDOWPLACEMENT
);
731 co_IntSendMessageNoWait( UserHMGetHandle(Wnd
), WM_ASYNC_SHOWWINDOW
, wpl
->showCmd
, 0 );
733 co_WinPosShowWindow(Wnd
, wpl
->showCmd
);
735 if ( Wnd
->style
& WS_MINIMIZE
&& !sAsync
)
737 if ( wpl
->flags
& WPF_SETMINPOSITION
)
738 Wnd
->InternalPos
.flags
|= WPF_SETMINPOSITION
;
740 if ( wpl
->flags
& WPF_RESTORETOMAXIMIZED
)
741 Wnd
->InternalPos
.flags
|= WPF_RESTORETOMAXIMIZED
;
747 co_WinPosMinMaximize(PWND Wnd
, UINT ShowFlag
, RECT
* NewPos
)
756 wpl
.length
= sizeof(wpl
);
757 IntGetWindowPlacement( Wnd
, &wpl
);
759 if (co_HOOK_CallHooks( WH_CBT
, HCBT_MINMAX
, (WPARAM
)Wnd
->head
.h
, ShowFlag
))
761 ERR("WinPosMinMaximize WH_CBT Call Hook return!\n");
762 return SWP_NOSIZE
| SWP_NOMOVE
;
764 if (Wnd
->style
& WS_MINIMIZE
)
768 case SW_SHOWMINNOACTIVE
:
769 case SW_SHOWMINIMIZED
:
770 case SW_FORCEMINIMIZE
:
772 return SWP_NOSIZE
| SWP_NOMOVE
;
774 if (!co_IntSendMessageNoWait(Wnd
->head
.h
, WM_QUERYOPEN
, 0, 0))
776 return(SWP_NOSIZE
| SWP_NOMOVE
);
778 SwpFlags
|= SWP_NOCOPYBITS
;
782 case SW_SHOWMINNOACTIVE
:
783 case SW_SHOWMINIMIZED
:
784 case SW_FORCEMINIMIZE
:
787 //ERR("MinMaximize Minimize\n");
788 if (Wnd
->style
& WS_MAXIMIZE
)
790 Wnd
->InternalPos
.flags
|= WPF_RESTORETOMAXIMIZED
;
794 Wnd
->InternalPos
.flags
&= ~WPF_RESTORETOMAXIMIZED
;
797 old_style
= IntSetStyle( Wnd
, WS_MINIMIZE
, WS_MAXIMIZE
);
799 co_UserRedrawWindow(Wnd
, NULL
, 0, RDW_VALIDATE
| RDW_NOERASE
|
800 RDW_NOINTERNALPAINT
);
802 if (!(Wnd
->InternalPos
.flags
& WPF_SETMINPOSITION
))
803 Wnd
->InternalPos
.flags
&= ~WPF_MININIT
;
805 WinPosFindIconPos(Wnd
, &wpl
.ptMinPosition
);
807 if (!(old_style
& WS_MINIMIZE
)) SwpFlags
|= SWP_STATECHANGED
;
809 /*ERR("Minimize: %d,%d %dx%d\n",
810 wpl.ptMinPosition.x, wpl.ptMinPosition.y, UserGetSystemMetrics(SM_CXMINIMIZED),
811 UserGetSystemMetrics(SM_CYMINIMIZED));
813 RECTL_vSetRect(NewPos
, wpl
.ptMinPosition
.x
, wpl
.ptMinPosition
.y
,
814 // wpl.ptMinPosition.x + UserGetSystemMetrics(SM_CXMINIMIZED),
815 // wpl.ptMinPosition.y + UserGetSystemMetrics(SM_CYMINIMIZED));
816 UserGetSystemMetrics(SM_CXMINIMIZED
),
817 UserGetSystemMetrics(SM_CYMINIMIZED
));
818 SwpFlags
|= SWP_NOCOPYBITS
;
824 //ERR("MinMaximize Maximize\n");
825 if ((Wnd
->style
& WS_MAXIMIZE
) && (Wnd
->style
& WS_VISIBLE
))
827 SwpFlags
= SWP_NOSIZE
| SWP_NOMOVE
;
830 co_WinPosGetMinMaxInfo(Wnd
, &Size
, &wpl
.ptMaxPosition
, NULL
, NULL
);
832 /*ERR("Maximize: %d,%d %dx%d\n",
833 wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, Size.x, Size.y);
835 old_style
= IntSetStyle( Wnd
, WS_MAXIMIZE
, WS_MINIMIZE
);
837 if (!(old_style
& WS_MAXIMIZE
)) SwpFlags
|= SWP_STATECHANGED
;
838 RECTL_vSetRect(NewPos
, wpl
.ptMaxPosition
.x
, wpl
.ptMaxPosition
.y
,
839 // wpl.ptMaxPosition.x + Size.x, wpl.ptMaxPosition.y + Size.y);
844 case SW_SHOWNOACTIVATE
:
845 Wnd
->InternalPos
.flags
&= ~WPF_RESTORETOMAXIMIZED
;
849 case SW_SHOWDEFAULT
: /* FIXME: should have its own handler */
851 //ERR("MinMaximize Restore\n");
852 old_style
= IntSetStyle( Wnd
, 0, WS_MINIMIZE
| WS_MAXIMIZE
);
853 if (old_style
& WS_MINIMIZE
)
855 if (Wnd
->InternalPos
.flags
& WPF_RESTORETOMAXIMIZED
)
857 co_WinPosGetMinMaxInfo(Wnd
, &Size
, &wpl
.ptMaxPosition
, NULL
, NULL
);
858 IntSetStyle( Wnd
, WS_MAXIMIZE
, 0 );
859 SwpFlags
|= SWP_STATECHANGED
;
860 /*ERR("Restore to Max: %d,%d %dx%d\n",
861 wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, Size.x, Size.y);
863 RECTL_vSetRect(NewPos
, wpl
.ptMaxPosition
.x
, wpl
.ptMaxPosition
.y
,
864 // wpl.ptMaxPosition.x + Size.x, wpl.ptMaxPosition.y + Size.y);
870 *NewPos
= wpl
.rcNormalPosition
;
871 /*ERR("Restore Max: %d,%d %dx%d\n",
872 NewPos->left, NewPos->top, NewPos->right - NewPos->left, NewPos->bottom - NewPos->top);
874 NewPos
->right
-= NewPos
->left
;
875 NewPos
->bottom
-= NewPos
->top
;
881 if (!(old_style
& WS_MAXIMIZE
))
885 SwpFlags
|= SWP_STATECHANGED
;
886 Wnd
->InternalPos
.flags
&= ~WPF_RESTORETOMAXIMIZED
;
887 *NewPos
= wpl
.rcNormalPosition
;
888 /*ERR("Restore Min: %d,%d %dx%d\n",
889 NewPos->left, NewPos->top, NewPos->right - NewPos->left, NewPos->bottom - NewPos->top);
891 NewPos
->right
-= NewPos
->left
;
892 NewPos
->bottom
-= NewPos
->top
;
901 UserHasWindowEdge(DWORD Style
, DWORD ExStyle
)
903 if (Style
& WS_MINIMIZE
)
905 if (ExStyle
& WS_EX_DLGMODALFRAME
)
907 if (ExStyle
& WS_EX_STATICEDGE
)
909 if (Style
& WS_THICKFRAME
)
912 if (Style
== WS_DLGFRAME
|| Style
== WS_CAPTION
)
918 IntGetWindowBorderMeasures(PWND Wnd
, UINT
*cx
, UINT
*cy
)
920 if(HAS_DLGFRAME(Wnd
->style
, Wnd
->ExStyle
) && !(Wnd
->style
& WS_MINIMIZE
))
922 *cx
= UserGetSystemMetrics(SM_CXDLGFRAME
);
923 *cy
= UserGetSystemMetrics(SM_CYDLGFRAME
);
927 if(HAS_THICKFRAME(Wnd
->style
, Wnd
->ExStyle
)&& !(Wnd
->style
& WS_MINIMIZE
))
929 *cx
= UserGetSystemMetrics(SM_CXFRAME
);
930 *cy
= UserGetSystemMetrics(SM_CYFRAME
);
932 else if(HAS_THINFRAME(Wnd
->style
, Wnd
->ExStyle
))
934 *cx
= UserGetSystemMetrics(SM_CXBORDER
);
935 *cy
= UserGetSystemMetrics(SM_CYBORDER
);
945 UserGetWindowBorders(DWORD Style
, DWORD ExStyle
, SIZE
*Size
, BOOL WithClient
)
949 if (UserHasWindowEdge(Style
, ExStyle
))
951 else if (ExStyle
& WS_EX_STATICEDGE
)
953 if ((ExStyle
& WS_EX_CLIENTEDGE
) && WithClient
)
955 if (Style
& WS_CAPTION
|| ExStyle
& WS_EX_DLGMODALFRAME
)
957 Size
->cx
= Size
->cy
= Border
;
958 if ((Style
& WS_THICKFRAME
) && !(Style
& WS_MINIMIZE
))
960 Size
->cx
+= UserGetSystemMetrics(SM_CXFRAME
) - UserGetSystemMetrics(SM_CXDLGFRAME
);
961 Size
->cy
+= UserGetSystemMetrics(SM_CYFRAME
) - UserGetSystemMetrics(SM_CYDLGFRAME
);
963 Size
->cx
*= UserGetSystemMetrics(SM_CXBORDER
);
964 Size
->cy
*= UserGetSystemMetrics(SM_CYBORDER
);
968 UserAdjustWindowRectEx(LPRECT lpRect
,
977 lpRect
->top
-= UserGetSystemMetrics(SM_CYMENU
);
979 if ((dwStyle
& WS_CAPTION
) == WS_CAPTION
)
981 if (dwExStyle
& WS_EX_TOOLWINDOW
)
982 lpRect
->top
-= UserGetSystemMetrics(SM_CYSMCAPTION
);
984 lpRect
->top
-= UserGetSystemMetrics(SM_CYCAPTION
);
986 UserGetWindowBorders(dwStyle
, dwExStyle
, &BorderSize
, TRUE
);
996 co_WinPosGetMinMaxInfo(PWND Window
, POINT
* MaxSize
, POINT
* MaxPos
,
997 POINT
* MinTrack
, POINT
* MaxTrack
)
1002 LONG style
= Window
->style
;
1004 LONG exstyle
= Window
->ExStyle
;
1007 ASSERT_REFS_CO(Window
);
1009 /* Compute default values */
1011 rc
= Window
->rcWindow
;
1012 MinMax
.ptReserved
.x
= rc
.left
;
1013 MinMax
.ptReserved
.y
= rc
.top
;
1015 if ((style
& WS_CAPTION
) == WS_CAPTION
)
1016 adjustedStyle
= style
& ~WS_BORDER
; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
1018 adjustedStyle
= style
;
1020 if(Window
->spwndParent
)
1021 IntGetClientRect(Window
->spwndParent
, &rc
);
1022 UserAdjustWindowRectEx(&rc
, adjustedStyle
, ((style
& WS_POPUP
) && Window
->IDMenu
), exstyle
);
1027 MinMax
.ptMaxSize
.x
= rc
.right
- rc
.left
;
1028 MinMax
.ptMaxSize
.y
= rc
.bottom
- rc
.top
;
1029 if (style
& (WS_DLGFRAME
| WS_BORDER
))
1031 MinMax
.ptMinTrackSize
.x
= UserGetSystemMetrics(SM_CXMINTRACK
);
1032 MinMax
.ptMinTrackSize
.y
= UserGetSystemMetrics(SM_CYMINTRACK
);
1036 MinMax
.ptMinTrackSize
.x
= 2 * xinc
;
1037 MinMax
.ptMinTrackSize
.y
= 2 * yinc
;
1039 MinMax
.ptMaxTrackSize
.x
= UserGetSystemMetrics(SM_CXMAXTRACK
);
1040 MinMax
.ptMaxTrackSize
.y
= UserGetSystemMetrics(SM_CYMAXTRACK
);
1041 MinMax
.ptMaxPosition
.x
= -xinc
;
1042 MinMax
.ptMaxPosition
.y
= -yinc
;
1044 if (!EMPTYPOINT(Window
->InternalPos
.MaxPos
)) MinMax
.ptMaxPosition
= Window
->InternalPos
.MaxPos
;
1046 co_IntSendMessage(Window
->head
.h
, WM_GETMINMAXINFO
, 0, (LPARAM
)&MinMax
);
1048 /* if the app didn't change the values, adapt them for the current monitor */
1049 if ((monitor
= UserGetPrimaryMonitor()))
1053 rc_work
= monitor
->rcMonitor
;
1055 if (style
& WS_MAXIMIZEBOX
)
1057 if ((style
& WS_CAPTION
) == WS_CAPTION
|| !(style
& (WS_CHILD
| WS_POPUP
)))
1058 rc_work
= monitor
->rcWork
;
1061 if (MinMax
.ptMaxSize
.x
== UserGetSystemMetrics(SM_CXSCREEN
) + 2 * xinc
&&
1062 MinMax
.ptMaxSize
.y
== UserGetSystemMetrics(SM_CYSCREEN
) + 2 * yinc
)
1064 MinMax
.ptMaxSize
.x
= (rc_work
.right
- rc_work
.left
) + 2 * xinc
;
1065 MinMax
.ptMaxSize
.y
= (rc_work
.bottom
- rc_work
.top
) + 2 * yinc
;
1067 if (MinMax
.ptMaxPosition
.x
== -xinc
&& MinMax
.ptMaxPosition
.y
== -yinc
)
1069 MinMax
.ptMaxPosition
.x
= rc_work
.left
- xinc
;
1070 MinMax
.ptMaxPosition
.y
= rc_work
.top
- yinc
;
1072 if (MinMax
.ptMaxSize
.x
>= (monitor
->rcMonitor
.right
- monitor
->rcMonitor
.left
) &&
1073 MinMax
.ptMaxSize
.y
>= (monitor
->rcMonitor
.bottom
- monitor
->rcMonitor
.top
) )
1074 Window
->state
|= WNDS_MAXIMIZESTOMONITOR
;
1076 Window
->state
&= ~WNDS_MAXIMIZESTOMONITOR
;
1080 MinMax
.ptMaxTrackSize
.x
= max(MinMax
.ptMaxTrackSize
.x
,
1081 MinMax
.ptMinTrackSize
.x
);
1082 MinMax
.ptMaxTrackSize
.y
= max(MinMax
.ptMaxTrackSize
.y
,
1083 MinMax
.ptMinTrackSize
.y
);
1086 *MaxSize
= MinMax
.ptMaxSize
;
1088 *MaxPos
= MinMax
.ptMaxPosition
;
1090 *MinTrack
= MinMax
.ptMinTrackSize
;
1092 *MaxTrack
= MinMax
.ptMaxTrackSize
;
1094 return 0; // FIXME: What does it return?
1099 FixClientRect(PRECTL ClientRect
, PRECTL WindowRect
)
1101 if (ClientRect
->left
< WindowRect
->left
)
1103 ClientRect
->left
= WindowRect
->left
;
1105 else if (WindowRect
->right
< ClientRect
->left
)
1107 ClientRect
->left
= WindowRect
->right
;
1109 if (ClientRect
->right
< WindowRect
->left
)
1111 ClientRect
->right
= WindowRect
->left
;
1113 else if (WindowRect
->right
< ClientRect
->right
)
1115 ClientRect
->right
= WindowRect
->right
;
1117 if (ClientRect
->top
< WindowRect
->top
)
1119 ClientRect
->top
= WindowRect
->top
;
1121 else if (WindowRect
->bottom
< ClientRect
->top
)
1123 ClientRect
->top
= WindowRect
->bottom
;
1125 if (ClientRect
->bottom
< WindowRect
->top
)
1127 ClientRect
->bottom
= WindowRect
->top
;
1129 else if (WindowRect
->bottom
< ClientRect
->bottom
)
1131 ClientRect
->bottom
= WindowRect
->bottom
;
1137 co_WinPosDoNCCALCSize(PWND Window
, PWINDOWPOS WinPos
,
1138 RECT
* WindowRect
, RECT
* ClientRect
)
1143 ASSERT_REFS_CO(Window
);
1145 /* Send WM_NCCALCSIZE message to get new client area */
1146 if ((WinPos
->flags
& (SWP_FRAMECHANGED
| SWP_NOSIZE
)) != SWP_NOSIZE
)
1148 NCCALCSIZE_PARAMS params
;
1149 WINDOWPOS winposCopy
;
1151 params
.rgrc
[0] = *WindowRect
;
1152 params
.rgrc
[1] = Window
->rcWindow
;
1153 params
.rgrc
[2] = Window
->rcClient
;
1154 Parent
= Window
->spwndParent
;
1155 if (0 != (Window
->style
& WS_CHILD
) && Parent
)
1157 RECTL_vOffsetRect(&(params
.rgrc
[0]), - Parent
->rcClient
.left
,
1158 - Parent
->rcClient
.top
);
1159 RECTL_vOffsetRect(&(params
.rgrc
[1]), - Parent
->rcClient
.left
,
1160 - Parent
->rcClient
.top
);
1161 RECTL_vOffsetRect(&(params
.rgrc
[2]), - Parent
->rcClient
.left
,
1162 - Parent
->rcClient
.top
);
1164 params
.lppos
= &winposCopy
;
1165 winposCopy
= *WinPos
;
1167 wvrFlags
= co_IntSendMessage(Window
->head
.h
, WM_NCCALCSIZE
, TRUE
, (LPARAM
) ¶ms
);
1169 /* If the application send back garbage, ignore it */
1170 if (params
.rgrc
[0].left
<= params
.rgrc
[0].right
&&
1171 params
.rgrc
[0].top
<= params
.rgrc
[0].bottom
)
1173 *ClientRect
= params
.rgrc
[0];
1174 if ((Window
->style
& WS_CHILD
) && Parent
)
1176 RECTL_vOffsetRect(ClientRect
, Parent
->rcClient
.left
,
1177 Parent
->rcClient
.top
);
1179 FixClientRect(ClientRect
, WindowRect
);
1182 /* FIXME: WVR_ALIGNxxx */
1184 if (ClientRect
->left
!= Window
->rcClient
.left
||
1185 ClientRect
->top
!= Window
->rcClient
.top
)
1187 WinPos
->flags
&= ~SWP_NOCLIENTMOVE
;
1190 if ((ClientRect
->right
- ClientRect
->left
!=
1191 Window
->rcClient
.right
- Window
->rcClient
.left
) ||
1192 (ClientRect
->bottom
- ClientRect
->top
!=
1193 Window
->rcClient
.bottom
- Window
->rcClient
.top
))
1195 WinPos
->flags
&= ~SWP_NOCLIENTSIZE
;
1200 if (!(WinPos
->flags
& SWP_NOMOVE
) &&
1201 (ClientRect
->left
!= Window
->rcClient
.left
||
1202 ClientRect
->top
!= Window
->rcClient
.top
))
1204 WinPos
->flags
&= ~SWP_NOCLIENTMOVE
;
1213 co_WinPosDoWinPosChanging(PWND Window
,
1220 ASSERT_REFS_CO(Window
);
1222 if (!(WinPos
->flags
& SWP_NOSENDCHANGING
))
1224 co_IntSendMessageNoWait(Window
->head
.h
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
) WinPos
);
1227 *WindowRect
= Window
->rcWindow
;
1228 *ClientRect
= Window
->rcClient
;
1230 if (!(WinPos
->flags
& SWP_NOSIZE
))
1232 WindowRect
->right
= WindowRect
->left
+ WinPos
->cx
;
1233 WindowRect
->bottom
= WindowRect
->top
+ WinPos
->cy
;
1236 if (!(WinPos
->flags
& SWP_NOMOVE
))
1241 Parent
= Window
->spwndParent
;
1242 if ((0 != (Window
->style
& WS_CHILD
)) && Parent
)
1244 X
+= Parent
->rcClient
.left
;
1245 Y
+= Parent
->rcClient
.top
;
1248 WindowRect
->left
= X
;
1249 WindowRect
->top
= Y
;
1250 WindowRect
->right
+= X
- Window
->rcWindow
.left
;
1251 WindowRect
->bottom
+= Y
- Window
->rcWindow
.top
;
1252 RECTL_vOffsetRect(ClientRect
,
1253 X
- Window
->rcWindow
.left
,
1254 Y
- Window
->rcWindow
.top
);
1257 WinPos
->flags
|= SWP_NOCLIENTMOVE
| SWP_NOCLIENTSIZE
;
1263 * Fix Z order taking into account owned popups -
1264 * basically we need to maintain them above the window that owns them
1266 * FIXME: hide/show owned popups when owner visibility changes.
1268 * ReactOS: See bug 6751 and 7228.
1272 WinPosDoOwnedPopups(PWND Window
, HWND hWndInsertAfter
)
1277 PWND DesktopWindow
, ChildObject
;
1280 Owner
= Window
->spwndOwner
? Window
->spwndOwner
->head
.h
: NULL
;
1281 Style
= Window
->style
;
1283 if ((Style
& WS_POPUP
) && Owner
)
1285 /* Make sure this popup stays above the owner */
1286 HWND hWndLocalPrev
= HWND_TOPMOST
;
1288 if (hWndInsertAfter
!= HWND_TOPMOST
)
1290 DesktopWindow
= UserGetDesktopWindow();
1291 List
= IntWinListChildren(DesktopWindow
);
1295 for (i
= 0; List
[i
]; i
++)
1297 if (List
[i
] == Owner
)
1299 if (HWND_TOP
== hWndInsertAfter
)
1301 ChildObject
= ValidateHwndNoErr(List
[i
]);
1302 if (NULL
!= ChildObject
)
1304 if (0 == (ChildObject
->ExStyle
& WS_EX_TOPMOST
))
1310 if (List
[i
] != Window
->head
.h
)
1311 hWndLocalPrev
= List
[i
];
1312 if (hWndLocalPrev
== hWndInsertAfter
)
1315 hWndInsertAfter
= hWndLocalPrev
;
1319 else if (Style
& WS_CHILD
)
1321 return hWndInsertAfter
;
1326 DesktopWindow
= UserGetDesktopWindow();
1327 List
= IntWinListChildren(DesktopWindow
);
1331 for (i
= 0; List
[i
]; i
++)
1335 if (List
[i
] == UserHMGetHandle(Window
))
1338 if (!(Wnd
= ValidateHwndNoErr(List
[i
])))
1341 if (Wnd
->style
& WS_POPUP
&& Wnd
->spwndOwner
== Window
)
1343 USER_REFERENCE_ENTRY Ref
;
1344 UserRefObjectCo(Wnd
, &Ref
);
1346 co_WinPosSetWindowPos(Wnd
, hWndInsertAfter
, 0, 0, 0, 0,
1347 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOSENDCHANGING
| SWP_DEFERERASE
);
1349 UserDerefObjectCo(Wnd
);
1351 hWndInsertAfter
= List
[i
];
1354 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1357 return hWndInsertAfter
;
1360 /***********************************************************************
1361 * WinPosInternalMoveWindow
1363 * Update WindowRect and ClientRect of Window and all of its children
1364 * We keep both WindowRect and ClientRect in screen coordinates internally
1368 WinPosInternalMoveWindow(PWND Window
, INT MoveX
, INT MoveY
)
1372 ASSERT(Window
!= Window
->spwndChild
);
1374 Window
->rcWindow
.left
+= MoveX
;
1375 Window
->rcWindow
.right
+= MoveX
;
1376 Window
->rcWindow
.top
+= MoveY
;
1377 Window
->rcWindow
.bottom
+= MoveY
;
1379 Window
->rcClient
.left
+= MoveX
;
1380 Window
->rcClient
.right
+= MoveX
;
1381 Window
->rcClient
.top
+= MoveY
;
1382 Window
->rcClient
.bottom
+= MoveY
;
1384 for(Child
= Window
->spwndChild
; Child
; Child
= Child
->spwndNext
)
1386 WinPosInternalMoveWindow(Child
, MoveX
, MoveY
);
1391 * WinPosFixupSWPFlags
1393 * Fix redundant flags and values in the WINDOWPOS structure.
1397 WinPosFixupFlags(WINDOWPOS
*WinPos
, PWND Wnd
)
1399 if (Wnd
->style
& WS_VISIBLE
)
1401 WinPos
->flags
&= ~SWP_SHOWWINDOW
;
1405 WinPos
->flags
&= ~SWP_HIDEWINDOW
;
1406 if (!(WinPos
->flags
& SWP_SHOWWINDOW
))
1407 WinPos
->flags
|= SWP_NOREDRAW
;
1410 WinPos
->cx
= max(WinPos
->cx
, 0);
1411 WinPos
->cy
= max(WinPos
->cy
, 0);
1413 /* Check for right size */
1414 if (Wnd
->rcWindow
.right
- Wnd
->rcWindow
.left
== WinPos
->cx
&&
1415 Wnd
->rcWindow
.bottom
- Wnd
->rcWindow
.top
== WinPos
->cy
)
1417 WinPos
->flags
|= SWP_NOSIZE
;
1420 /* Check for right position */
1421 if (Wnd
->rcWindow
.left
== WinPos
->x
&&
1422 Wnd
->rcWindow
.top
== WinPos
->y
)
1424 WinPos
->flags
|= SWP_NOMOVE
;
1427 if (WinPos
->hwnd
== UserGetForegroundWindow())
1429 WinPos
->flags
|= SWP_NOACTIVATE
; /* Already active */
1432 if ((Wnd
->style
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)
1434 /* Bring to the top when activating */
1435 if (!(WinPos
->flags
& SWP_NOACTIVATE
))
1437 WinPos
->flags
&= ~SWP_NOZORDER
;
1438 WinPos
->hwndInsertAfter
= (0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
) ?
1439 HWND_TOPMOST
: HWND_TOP
);
1444 /* Check hwndInsertAfter */
1445 if (!(WinPos
->flags
& SWP_NOZORDER
))
1447 /* Fix sign extension */
1448 if (WinPos
->hwndInsertAfter
== (HWND
)0xffff)
1450 WinPos
->hwndInsertAfter
= HWND_TOPMOST
;
1452 else if (WinPos
->hwndInsertAfter
== (HWND
)0xfffe)
1454 WinPos
->hwndInsertAfter
= HWND_NOTOPMOST
;
1457 if (WinPos
->hwndInsertAfter
== HWND_NOTOPMOST
)
1459 if (!(Wnd
->ExStyle
& WS_EX_TOPMOST
))
1460 WinPos
->flags
|= SWP_NOZORDER
;
1462 WinPos
->hwndInsertAfter
= HWND_TOP
;
1464 else if (HWND_TOP
== WinPos
->hwndInsertAfter
1465 && 0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
))
1467 /* Keep it topmost when it's already topmost */
1468 WinPos
->hwndInsertAfter
= HWND_TOPMOST
;
1471 /* hwndInsertAfter must be a sibling of the window */
1472 if (HWND_TOPMOST
!= WinPos
->hwndInsertAfter
1473 && HWND_TOP
!= WinPos
->hwndInsertAfter
1474 && HWND_NOTOPMOST
!= WinPos
->hwndInsertAfter
1475 && HWND_BOTTOM
!= WinPos
->hwndInsertAfter
)
1479 InsAfterWnd
= ValidateHwndNoErr(WinPos
->hwndInsertAfter
);
1485 if (InsAfterWnd
->spwndParent
!= Wnd
->spwndParent
)
1487 /* Note from wine User32 Win test_SetWindowPos:
1488 "Returns TRUE also for windows that are not siblings"
1489 "Does not seem to do anything even without passing flags, still returns TRUE"
1490 "Same thing the other way around."
1491 ".. and with these windows."
1498 * We don't need to change the Z order of hwnd if it's already
1499 * inserted after hwndInsertAfter or when inserting hwnd after
1502 if ((WinPos
->hwnd
== WinPos
->hwndInsertAfter
) ||
1503 ((InsAfterWnd
->spwndNext
) && (WinPos
->hwnd
== InsAfterWnd
->spwndNext
->head
.h
)))
1505 WinPos
->flags
|= SWP_NOZORDER
;
1514 /* x and y are always screen relative */
1516 co_WinPosSetWindowPos(
1518 HWND WndInsertAfter
,
1527 RECTL NewWindowRect
;
1528 RECTL NewClientRect
;
1530 HRGN VisBefore
= NULL
;
1531 HRGN VisAfter
= NULL
;
1532 HRGN DirtyRgn
= NULL
;
1533 HRGN ExposedRgn
= NULL
;
1534 HRGN CopyRgn
= NULL
;
1536 RECTL OldWindowRect
, OldClientRect
;
1541 BOOL bPointerInWindow
;
1544 ASSERT_REFS_CO(Window
);
1546 /* FIXME: Get current active window from active queue. */
1548 bPointerInWindow
= IntPtInWindow(Window
, gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
);
1550 WinPos
.hwnd
= Window
->head
.h
;
1551 WinPos
.hwndInsertAfter
= WndInsertAfter
;
1556 WinPos
.flags
= flags
;
1558 co_WinPosDoWinPosChanging(Window
, &WinPos
, &NewWindowRect
, &NewClientRect
);
1560 // HWND_NOTOPMOST is redirected in WinPosFixupFlags.
1561 bNoTopMost
= WndInsertAfter
== HWND_NOTOPMOST
;
1563 /* Does the window still exist? */
1564 if (!IntIsWindow(WinPos
.hwnd
))
1566 TRACE("WinPosSetWindowPos: Invalid handle 0x%p!\n",WinPos
.hwnd
);
1567 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE
);
1571 /* Fix up the flags. */
1572 if (!WinPosFixupFlags(&WinPos
, Window
))
1578 Ancestor
= UserGetAncestor(Window
, GA_PARENT
);
1579 if ( (WinPos
.flags
& (SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) != SWP_NOZORDER
&&
1580 Ancestor
&& Ancestor
->head
.h
== IntGetDesktopWindow() )
1582 WinPos
.hwndInsertAfter
= WinPosDoOwnedPopups(Window
, WinPos
.hwndInsertAfter
);
1585 if (!(WinPos
.flags
& SWP_NOREDRAW
))
1587 /* Compute the visible region before the window position is changed */
1588 if (!(WinPos
.flags
& SWP_SHOWWINDOW
) &&
1589 (WinPos
.flags
& (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
|
1590 SWP_HIDEWINDOW
| SWP_FRAMECHANGED
)) !=
1591 (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
))
1593 VisBefore
= VIS_ComputeVisibleRegion(Window
, FALSE
, FALSE
,
1594 (Window
->style
& WS_CLIPSIBLINGS
) ? TRUE
: FALSE
);
1597 if ( VisBefore
!= NULL
&&
1598 (VisRgn
= (PROSRGNDATA
)RGNOBJAPI_Lock(VisBefore
, NULL
)) &&
1599 REGION_Complexity(VisRgn
) == NULLREGION
)
1601 RGNOBJAPI_Unlock(VisRgn
);
1602 GreDeleteObject(VisBefore
);
1607 RGNOBJAPI_Unlock(VisRgn
);
1608 NtGdiOffsetRgn(VisBefore
, -Window
->rcWindow
.left
, -Window
->rcWindow
.top
);
1613 WvrFlags
= co_WinPosDoNCCALCSize(Window
, &WinPos
, &NewWindowRect
, &NewClientRect
);
1615 TRACE("co_WinPosDoNCCALCSize returned %d\n", WvrFlags
);
1617 /* Validate link windows. (also take into account shell window in hwndShellWindow) */
1618 if (!(WinPos
.flags
& SWP_NOZORDER
) && WinPos
.hwnd
!= UserGetShellWindow())
1620 //// Fix bug 6751 & 7228 see WinPosDoOwnedPopups wine Fixme.
1623 PWND InsertAfterWindow
;
1625 if ((ParentWindow
= Window
->spwndParent
)) // Must have a Parent window!
1627 if (WinPos
.hwndInsertAfter
== HWND_TOPMOST
)
1629 InsertAfterWindow
= NULL
;
1631 else if ( WinPos
.hwndInsertAfter
== HWND_TOP
)
1633 InsertAfterWindow
= NULL
;
1635 Sibling
= ParentWindow
->spwndChild
;
1637 while ( Sibling
&& Sibling
->ExStyle
& WS_EX_TOPMOST
)
1639 InsertAfterWindow
= Sibling
;
1640 Sibling
= Sibling
->spwndNext
;
1643 else if (WinPos
.hwndInsertAfter
== HWND_BOTTOM
)
1645 if (ParentWindow
->spwndChild
)
1647 InsertAfterWindow
= ParentWindow
->spwndChild
;
1649 if(InsertAfterWindow
)
1651 while (InsertAfterWindow
->spwndNext
)
1652 InsertAfterWindow
= InsertAfterWindow
->spwndNext
;
1656 InsertAfterWindow
= NULL
;
1659 InsertAfterWindow
= IntGetWindowObject(WinPos
.hwndInsertAfter
);
1660 /* Do nothing if hwndInsertAfter is HWND_BOTTOM and Window is already
1662 if (InsertAfterWindow
!= Window
)
1664 IntUnlinkWindow(Window
);
1665 IntLinkWindow(Window
, InsertAfterWindow
);
1668 if ( ( WinPos
.hwndInsertAfter
== HWND_TOPMOST
||
1669 ( Window
->ExStyle
& WS_EX_TOPMOST
&& Window
->spwndPrev
&& Window
->spwndPrev
->ExStyle
& WS_EX_TOPMOST
) ||
1670 ( Window
->spwndNext
&& Window
->spwndNext
->ExStyle
& WS_EX_TOPMOST
) ) &&
1673 Window
->ExStyle
|= WS_EX_TOPMOST
;
1677 Window
->ExStyle
&= ~ WS_EX_TOPMOST
;
1683 OldWindowRect
= Window
->rcWindow
;
1684 OldClientRect
= Window
->rcClient
;
1686 if (OldClientRect
.bottom
- OldClientRect
.top
==
1687 NewClientRect
.bottom
- NewClientRect
.top
)
1689 WvrFlags
&= ~WVR_VREDRAW
;
1692 if (OldClientRect
.right
- OldClientRect
.left
==
1693 NewClientRect
.right
- NewClientRect
.left
)
1695 WvrFlags
&= ~WVR_HREDRAW
;
1698 /* FIXME: Actually do something with WVR_VALIDRECTS */
1700 if (NewClientRect
.left
!= OldClientRect
.left
||
1701 NewClientRect
.top
!= OldClientRect
.top
)
1703 WinPosInternalMoveWindow(Window
,
1704 NewClientRect
.left
- OldClientRect
.left
,
1705 NewClientRect
.top
- OldClientRect
.top
);
1708 Window
->rcWindow
= NewWindowRect
;
1709 Window
->rcClient
= NewClientRect
;
1711 /* erase parent when hiding or resizing child */
1712 if (WinPos
.flags
& SWP_HIDEWINDOW
)
1714 /* Clear the update region */
1715 co_UserRedrawWindow( Window
,
1718 RDW_VALIDATE
| RDW_NOFRAME
| RDW_NOERASE
| RDW_NOINTERNALPAINT
| RDW_ALLCHILDREN
);
1720 if (Window
->spwndParent
== UserGetDesktopWindow())
1721 co_IntShellHookNotify(HSHELL_WINDOWDESTROYED
, (WPARAM
)Window
->head
.h
, 0);
1723 Window
->style
&= ~WS_VISIBLE
; //IntSetStyle( Window, 0, WS_VISIBLE );
1724 IntNotifyWinEvent(EVENT_OBJECT_HIDE
, Window
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
1726 else if (WinPos
.flags
& SWP_SHOWWINDOW
)
1728 if (Window
->spwndParent
== UserGetDesktopWindow())
1729 co_IntShellHookNotify(HSHELL_WINDOWCREATED
, (WPARAM
)Window
->head
.h
, 0);
1731 Window
->style
|= WS_VISIBLE
; //IntSetStyle( Window, WS_VISIBLE, 0 );
1732 IntNotifyWinEvent(EVENT_OBJECT_SHOW
, Window
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
1735 if (Window
->hrgnUpdate
!= NULL
&& Window
->hrgnUpdate
!= HRGN_WINDOW
)
1737 NtGdiOffsetRgn(Window
->hrgnUpdate
,
1738 NewWindowRect
.left
- OldWindowRect
.left
,
1739 NewWindowRect
.top
- OldWindowRect
.top
);
1742 DceResetActiveDCEs(Window
); // For WS_VISIBLE changes.
1744 if (!(WinPos
.flags
& SWP_NOREDRAW
))
1746 /* Determine the new visible region */
1747 VisAfter
= VIS_ComputeVisibleRegion(Window
, FALSE
, FALSE
,
1748 (Window
->style
& WS_CLIPSIBLINGS
) ? TRUE
: FALSE
);
1751 if ( VisAfter
!= NULL
&&
1752 (VisRgn
= (PROSRGNDATA
)RGNOBJAPI_Lock(VisAfter
, NULL
)) &&
1753 REGION_Complexity(VisRgn
) == NULLREGION
)
1755 RGNOBJAPI_Unlock(VisRgn
);
1756 GreDeleteObject(VisAfter
);
1761 RGNOBJAPI_Unlock(VisRgn
);
1762 NtGdiOffsetRgn(VisAfter
, -Window
->rcWindow
.left
, -Window
->rcWindow
.top
);
1766 * Determine which pixels can be copied from the old window position
1767 * to the new. Those pixels must be visible in both the old and new
1768 * position. Also, check the class style to see if the windows of this
1769 * class need to be completely repainted on (horizontal/vertical) size
1772 if ( VisBefore
!= NULL
&&
1774 !(WinPos
.flags
& SWP_NOCOPYBITS
) &&
1775 ((WinPos
.flags
& SWP_NOSIZE
) || !(WvrFlags
& WVR_REDRAW
)) &&
1776 !(Window
->ExStyle
& WS_EX_TRANSPARENT
) )
1778 CopyRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
1779 RgnType
= NtGdiCombineRgn(CopyRgn
, VisAfter
, VisBefore
, RGN_AND
);
1782 * If this is (also) a window resize, the whole nonclient area
1783 * needs to be repainted. So we limit the copy to the client area,
1784 * 'cause there is no use in copying it (would possibly cause
1785 * "flashing" too). However, if the copy region is already empty,
1786 * we don't have to crop (can't take anything away from an empty
1789 if (!(WinPos
.flags
& SWP_NOSIZE
) &&
1791 RgnType
!= NULLREGION
)
1793 PROSRGNDATA pCopyRgn
;
1794 RECTL ORect
= OldClientRect
;
1795 RECTL NRect
= NewClientRect
;
1796 RECTL_vOffsetRect(&ORect
, - OldWindowRect
.left
, - OldWindowRect
.top
);
1797 RECTL_vOffsetRect(&NRect
, - NewWindowRect
.left
, - NewWindowRect
.top
);
1798 RECTL_bIntersectRect(&CopyRect
, &ORect
, &NRect
);
1799 pCopyRgn
= RGNOBJAPI_Lock(CopyRgn
, NULL
);
1800 REGION_CropAndOffsetRegion(pCopyRgn
, pCopyRgn
, &CopyRect
, NULL
);
1801 RGNOBJAPI_Unlock(pCopyRgn
);
1804 /* No use in copying bits which are in the update region. */
1805 if (Window
->hrgnUpdate
!= NULL
)
1807 NtGdiOffsetRgn(CopyRgn
, NewWindowRect
.left
, NewWindowRect
.top
);
1808 NtGdiCombineRgn(CopyRgn
, CopyRgn
, Window
->hrgnUpdate
, RGN_DIFF
);
1809 NtGdiOffsetRgn(CopyRgn
, -NewWindowRect
.left
, -NewWindowRect
.top
);
1813 * Now, get the bounding box of the copy region. If it's empty
1814 * there's nothing to copy. Also, it's no use copying bits onto
1817 if ( (VisRgn
= (PROSRGNDATA
)RGNOBJAPI_Lock(CopyRgn
, NULL
)) &&
1818 REGION_GetRgnBox(VisRgn
, &CopyRect
) == NULLREGION
)
1820 /* Nothing to copy, clean up */
1821 RGNOBJAPI_Unlock(VisRgn
);
1822 GreDeleteObject(CopyRgn
);
1825 else if (OldWindowRect
.left
!= NewWindowRect
.left
||
1826 OldWindowRect
.top
!= NewWindowRect
.top
)
1830 RGNOBJAPI_Unlock(VisRgn
);
1834 * Small trick here: there is no function to bitblt a region. So
1835 * we set the region as the clipping region, take the bounding box
1836 * of the region and bitblt that. Since nothing outside the clipping
1837 * region is copied, this has the effect of bitblt'ing the region.
1839 * Since NtUserGetDCEx takes ownership of the clip region, we need
1840 * to create a copy of CopyRgn and pass that. We need CopyRgn later
1842 NtGdiOffsetRgn(CopyRgn
, NewWindowRect
.left
, NewWindowRect
.top
);
1843 Dc
= UserGetDCEx( Window
,
1845 DCX_WINDOW
|DCX_CACHE
|DCX_INTERSECTRGN
|DCX_CLIPSIBLINGS
|DCX_KEEPCLIPRGN
);
1847 CopyRect
.left
, CopyRect
.top
,
1848 CopyRect
.right
- CopyRect
.left
,
1849 CopyRect
.bottom
- CopyRect
.top
,
1851 CopyRect
.left
+ (OldWindowRect
.left
- NewWindowRect
.left
),
1852 CopyRect
.top
+ (OldWindowRect
.top
- NewWindowRect
.top
),
1857 UserReleaseDC(Window
, Dc
, FALSE
);
1858 IntValidateParent(Window
, CopyRgn
, FALSE
);
1859 NtGdiOffsetRgn(CopyRgn
, -NewWindowRect
.left
, -NewWindowRect
.top
);
1863 RGNOBJAPI_Unlock(VisRgn
);
1871 /* We need to redraw what wasn't visible before */
1872 if (VisAfter
!= NULL
)
1874 DirtyRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
1875 if (CopyRgn
!= NULL
)
1877 RgnType
= NtGdiCombineRgn(DirtyRgn
, VisAfter
, CopyRgn
, RGN_DIFF
);
1881 RgnType
= NtGdiCombineRgn(DirtyRgn
, VisAfter
, 0, RGN_COPY
);
1883 if (RgnType
!= ERROR
&& RgnType
!= NULLREGION
)
1886 NtGdiOffsetRgn(DirtyRgn, Window->rcWindow.left, Window->rcWindow.top);
1887 IntInvalidateWindows( Window,
1889 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
1891 GreDeleteObject(DirtyRgn);
1894 PWND Parent
= Window
->spwndParent
;
1896 NtGdiOffsetRgn( DirtyRgn
,
1897 Window
->rcWindow
.left
,
1898 Window
->rcWindow
.top
);
1899 if ( (Window
->style
& WS_CHILD
) &&
1901 !(Parent
->style
& WS_CLIPCHILDREN
))
1903 IntInvalidateWindows( Parent
,
1905 RDW_ERASE
| RDW_INVALIDATE
);
1906 co_IntPaintWindows(Parent
, RDW_ERASENOW
, FALSE
);
1910 IntInvalidateWindows( Window
,
1912 RDW_ERASE
| RDW_FRAME
| RDW_INVALIDATE
| RDW_ALLCHILDREN
);
1915 GreDeleteObject(DirtyRgn
);
1918 if (CopyRgn
!= NULL
)
1920 GreDeleteObject(CopyRgn
);
1923 /* Expose what was covered before but not covered anymore */
1924 if (VisBefore
!= NULL
)
1926 ExposedRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
1927 RgnType
= NtGdiCombineRgn(ExposedRgn
, VisBefore
, NULL
, RGN_COPY
);
1928 NtGdiOffsetRgn( ExposedRgn
,
1929 OldWindowRect
.left
- NewWindowRect
.left
,
1930 OldWindowRect
.top
- NewWindowRect
.top
);
1932 if (VisAfter
!= NULL
)
1933 RgnType
= NtGdiCombineRgn(ExposedRgn
, ExposedRgn
, VisAfter
, RGN_DIFF
);
1935 if (RgnType
!= ERROR
&& RgnType
!= NULLREGION
)
1937 co_VIS_WindowLayoutChanged(Window
, ExposedRgn
);
1939 GreDeleteObject(ExposedRgn
);
1940 GreDeleteObject(VisBefore
);
1943 if (VisAfter
!= NULL
)
1945 GreDeleteObject(VisAfter
);
1949 if (!(WinPos
.flags
& (SWP_NOACTIVATE
|SWP_HIDEWINDOW
)))
1951 if ((Window
->style
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1953 co_IntSendMessageNoWait(WinPos
.hwnd
, WM_CHILDACTIVATE
, 0, 0);
1957 //ERR("SetWindowPos Set FG Window!\n");
1958 co_IntSetForegroundWindow(Window
);
1962 /* And last, send the WM_WINDOWPOSCHANGED message */
1964 TRACE("\tstatus flags = %04x\n", WinPos
.flags
& SWP_AGG_STATUSFLAGS
);
1966 if ((WinPos
.flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOPOSCHANGE
)
1968 /* WM_WINDOWPOSCHANGED is sent even if SWP_NOSENDCHANGING is set
1969 and always contains final window position.
1971 WinPos
.x
= NewWindowRect
.left
;
1972 WinPos
.y
= NewWindowRect
.top
;
1973 WinPos
.cx
= NewWindowRect
.right
- NewWindowRect
.left
;
1974 WinPos
.cy
= NewWindowRect
.bottom
- NewWindowRect
.top
;
1975 co_IntSendMessageNoWait(WinPos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
) &WinPos
);
1978 if ( WinPos
.flags
& SWP_FRAMECHANGED
|| WinPos
.flags
& SWP_STATECHANGED
||
1979 !(WinPos
.flags
& SWP_NOCLIENTSIZE
) || !(WinPos
.flags
& SWP_NOCLIENTMOVE
) )
1981 PWND pWnd
= ValidateHwndNoErr(WinPos
.hwnd
);
1983 IntNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE
, pWnd
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
1986 if(bPointerInWindow
!= IntPtInWindow(Window
, gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
))
1988 /* Generate mouse move message */
1990 msg
.message
= WM_MOUSEMOVE
;
1991 msg
.wParam
= UserGetMouseButtonsState();
1992 msg
.lParam
= MAKELPARAM(gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
);
1993 msg
.pt
= gpsi
->ptCursor
;
1994 co_MsqInsertMouseMessage(&msg
, 0, 0, TRUE
);
2001 co_WinPosGetNonClientSize(PWND Window
, RECT
* WindowRect
, RECT
* ClientRect
)
2005 ASSERT_REFS_CO(Window
);
2007 *ClientRect
= *WindowRect
;
2008 Result
= co_IntSendMessageNoWait(Window
->head
.h
, WM_NCCALCSIZE
, FALSE
, (LPARAM
) ClientRect
);
2010 FixClientRect(ClientRect
, WindowRect
);
2016 co_WinPosSendSizeMove(PWND Wnd
)
2020 WPARAM wParam
= SIZE_RESTORED
;
2022 IntGetClientRect(Wnd
, &Rect
);
2023 lParam
= MAKELONG(Rect
.right
-Rect
.left
, Rect
.bottom
-Rect
.top
);
2025 Wnd
->state
&= ~WNDS_SENDSIZEMOVEMSGS
;
2027 if (Wnd
->style
& WS_MAXIMIZE
)
2029 wParam
= SIZE_MAXIMIZED
;
2031 else if (Wnd
->style
& WS_MINIMIZE
)
2033 wParam
= SIZE_MINIMIZED
;
2037 co_IntSendMessageNoWait(UserHMGetHandle(Wnd
), WM_SIZE
, wParam
, lParam
);
2039 if (Wnd
->spwndParent
== UserGetDesktopWindow()) // Wnd->spwndParent->fnid != FNID_DESKTOP )
2040 lParam
= MAKELONG(Wnd
->rcClient
.left
, Wnd
->rcClient
.top
);
2042 lParam
= MAKELONG(Wnd
->rcClient
.left
-Wnd
->spwndParent
->rcClient
.left
, Wnd
->rcClient
.top
-Wnd
->spwndParent
->rcClient
.top
);
2044 co_IntSendMessageNoWait(UserHMGetHandle(Wnd
), WM_MOVE
, 0, lParam
);
2046 IntEngWindowChanged(Wnd
, WOC_RGN_CLIENT
);
2050 co_WinPosShowWindow(PWND Wnd
, INT Cmd
)
2053 UINT Swp
= 0, EventMsg
= 0;
2054 RECTL NewPos
= {0, 0, 0, 0};
2059 BOOL ShowOwned
= FALSE
;
2062 ASSERT_REFS_CO(Wnd
);
2064 pti
= PsGetCurrentThreadWin32Thread();
2065 WasVisible
= (Wnd
->style
& WS_VISIBLE
) != 0;
2076 Swp
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
2077 if (Wnd
!= pti
->MessageQueue
->spwndActive
)
2078 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2082 case SW_FORCEMINIMIZE
: /* FIXME: Does not work if thread is hung. */
2083 case SW_SHOWMINNOACTIVE
:
2084 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2086 case SW_SHOWMINIMIZED
:
2087 Swp
|= SWP_SHOWWINDOW
;
2091 Swp
|= SWP_NOACTIVATE
;
2092 if (!(style
& WS_MINIMIZE
))
2094 //IntShowOwnedPopups(Wnd, FALSE );
2096 // Fix wine Win test_SetFocus todo #1 & #2,
2097 if (Cmd
== SW_SHOWMINIMIZED
)
2099 if ((style
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
2100 co_UserSetFocus(Wnd
->spwndParent
);
2105 Swp
|= co_WinPosMinMaximize(Wnd
, Cmd
, &NewPos
) |
2108 EventMsg
= EVENT_SYSTEM_MINIMIZESTART
;
2114 Swp
|= SWP_FRAMECHANGED
;
2118 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
2123 case SW_SHOWMAXIMIZED
:
2125 Swp
|= SWP_SHOWWINDOW
;
2126 if (!(style
& WS_MAXIMIZE
))
2130 Swp
|= co_WinPosMinMaximize(Wnd
, SW_MAXIMIZE
, &NewPos
) |
2133 EventMsg
= EVENT_SYSTEM_MINIMIZEEND
;
2139 Swp
|= SWP_FRAMECHANGED
;
2143 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
2149 Swp
|= SWP_NOACTIVATE
| SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
2150 if (style
& WS_CHILD
&& !(Wnd
->ExStyle
& WS_EX_MDICHILD
)) Swp
|= SWP_NOZORDER
;
2153 if (WasVisible
) return(TRUE
); // Nothing to do!
2154 Swp
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
2155 /* Don't activate the topmost window. */
2156 if (style
& WS_CHILD
&& !(Wnd
->ExStyle
& WS_EX_MDICHILD
)) Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2159 case SW_SHOWNOACTIVATE
:
2160 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2163 case SW_SHOWDEFAULT
:
2165 if (!WasVisible
) Swp
|= SWP_SHOWWINDOW
;
2166 if (style
& (WS_MINIMIZE
| WS_MAXIMIZE
))
2168 Swp
|= co_WinPosMinMaximize(Wnd
, Cmd
, &NewPos
) |
2171 if (style
& WS_MINIMIZE
) EventMsg
= EVENT_SYSTEM_MINIMIZEEND
;
2177 Swp
|= SWP_FRAMECHANGED
;
2181 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
2183 if ( style
& WS_CHILD
&&
2184 !(Wnd
->ExStyle
& WS_EX_MDICHILD
) &&
2185 !(Swp
& SWP_STATECHANGED
))
2186 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2193 ShowFlag
= (Cmd
!= SW_HIDE
);
2195 if ((ShowFlag
!= WasVisible
|| Cmd
== SW_SHOWNA
) && Cmd
!= SW_SHOWMAXIMIZED
&& !(Swp
& SWP_STATECHANGED
))
2197 co_IntSendMessageNoWait(Wnd
->head
.h
, WM_SHOWWINDOW
, ShowFlag
, 0);
2198 if (!(Wnd
->state2
& WNDS2_WIN31COMPAT
))
2199 co_IntSendMessageNoWait(Wnd
->head
.h
, WM_SETVISIBLE
, ShowFlag
, 0);
2200 if (!VerifyWnd(Wnd
)) return WasVisible
;
2203 /* We can't activate a child window */
2204 if ((Wnd
->style
& WS_CHILD
) &&
2205 !(Wnd
->ExStyle
& WS_EX_MDICHILD
) &&
2208 //ERR("SWP Child No active and ZOrder\n");
2209 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2212 #if 0 // Explorer issues with common controls. Someone does not know how CS_SAVEBITS works.
2213 if ((Wnd
->style
& (WS_POPUP
|WS_CHILD
)) != WS_CHILD
&&
2214 Wnd
->pcls
->style
& CS_SAVEBITS
&&
2215 ((Cmd
== SW_SHOW
) || (Cmd
== SW_NORMAL
)))
2217 co_IntSetActiveWindow(Wnd
,NULL
,FALSE
,TRUE
,FALSE
);
2218 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2222 if (IsChildVisible(Wnd
) || Swp
& SWP_STATECHANGED
)
2224 TRACE("Child is Vis %s or State changed %s. ShowFlag %s\n",
2225 (IsChildVisible(Wnd
) ? "TRUE" : "FALSE"), (Swp
& SWP_STATECHANGED
? "TRUE" : "FALSE"),
2226 (ShowFlag
? "TRUE" : "FALSE"));
2227 co_WinPosSetWindowPos( Wnd
,
2228 0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
) ? HWND_TOPMOST
: HWND_TOP
,
2231 NewPos
.right
, //NewPos.right - NewPos.left,
2232 NewPos
.bottom
, //NewPos.bottom - NewPos.top,
2237 TRACE("Parent Vis?\n");
2238 /* if parent is not visible simply toggle WS_VISIBLE and return */
2239 if (ShowFlag
) IntSetStyle( Wnd
, WS_VISIBLE
, 0 );
2240 else IntSetStyle( Wnd
, 0, WS_VISIBLE
);
2243 if ( EventMsg
) IntNotifyWinEvent(EventMsg
, Wnd
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
2245 //if ( ShowOwned ) IntShowOwnedPopups(Wnd, TRUE );
2247 if ((Cmd
== SW_HIDE
) || (Cmd
== SW_MINIMIZE
))
2249 if ( Wnd
== pti
->MessageQueue
->spwndActive
&& pti
->MessageQueue
== IntGetFocusMessageQueue() )
2251 if ( Wnd
->spwndParent
== UserGetDesktopWindow())
2253 if(!ActivateOtherWindowMin(Wnd
))
2254 co_WinPosActivateOtherWindow(Wnd
);
2257 co_WinPosActivateOtherWindow(Wnd
);
2260 /* Revert focus to parent */
2261 if (Wnd
== pti
->MessageQueue
->spwndFocus
)
2263 Parent
= Wnd
->spwndParent
;
2264 if (Wnd
->spwndParent
== UserGetDesktopWindow()) Parent
= 0;
2265 co_UserSetFocus(Parent
);
2269 /* FIXME: Check for window destruction. */
2271 if ((Wnd
->state
& WNDS_SENDSIZEMOVEMSGS
) &&
2272 !(Wnd
->state2
& WNDS2_INDESTROY
))
2274 co_WinPosSendSizeMove(Wnd
);
2277 /* if previous state was minimized Windows sets focus to the window */
2278 if (style
& WS_MINIMIZE
)
2280 co_UserSetFocus(Wnd
);
2281 // Fix wine Win test_SetFocus todo #3,
2282 if (!(style
& WS_CHILD
)) co_IntSendMessageNoWait(UserHMGetHandle(Wnd
), WM_ACTIVATE
, WA_ACTIVE
, 0);
2289 co_WinPosSearchChildren(
2298 if (!(ScopeWin
->style
& WS_VISIBLE
))
2303 if ((ScopeWin
->style
& WS_DISABLED
))
2308 if (!IntPtInWindow(ScopeWin
, Point
->x
, Point
->y
))
2313 UserReferenceObject(ScopeWin
);
2315 if ( RECTL_bPointInRect(&ScopeWin
->rcClient
, Point
->x
, Point
->y
) )
2317 List
= IntWinListChildren(ScopeWin
);
2320 for (phWnd
= List
; *phWnd
; ++phWnd
)
2322 if (!(pwndChild
= ValidateHwndNoErr(*phWnd
)))
2327 pwndChild
= co_WinPosSearchChildren(pwndChild
, Point
, HitTest
);
2329 if(pwndChild
!= NULL
)
2331 /* We found a window. Don't send any more WM_NCHITTEST messages */
2332 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2333 UserDereferenceObject(ScopeWin
);
2337 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2341 if (ScopeWin
->head
.pti
== PsGetCurrentThreadWin32Thread())
2343 *HitTest
= (USHORT
)co_IntSendMessage(ScopeWin
->head
.h
, WM_NCHITTEST
, 0,
2344 MAKELONG(Point
->x
, Point
->y
));
2345 if ((*HitTest
) == (USHORT
)HTTRANSPARENT
)
2347 UserDereferenceObject(ScopeWin
);
2352 *HitTest
= HTCLIENT
;
2358 co_WinPosWindowFromPoint(PWND ScopeWin
, POINT
*WinPoint
, USHORT
* HitTest
)
2361 POINT Point
= *WinPoint
;
2362 USER_REFERENCE_ENTRY Ref
;
2364 if( ScopeWin
== NULL
)
2366 ScopeWin
= UserGetDesktopWindow();
2367 if(ScopeWin
== NULL
)
2371 *HitTest
= HTNOWHERE
;
2373 ASSERT_REFS_CO(ScopeWin
);
2374 UserRefObjectCo(ScopeWin
, &Ref
);
2376 Window
= co_WinPosSearchChildren(ScopeWin
, &Point
, HitTest
);
2378 UserDerefObjectCo(ScopeWin
);
2380 ASSERT_REFS_CO(Window
);
2381 ASSERT_REFS_CO(ScopeWin
);
2387 IntRealChildWindowFromPoint(PWND Parent
, LONG x
, LONG y
)
2391 PWND pwndHit
= NULL
;
2396 if (Parent
!= UserGetDesktopWindow())
2398 Pt
.x
+= Parent
->rcClient
.left
;
2399 Pt
.y
+= Parent
->rcClient
.top
;
2402 if (!IntPtInWindow(Parent
, Pt
.x
, Pt
.y
)) return NULL
;
2404 if ((List
= IntWinListChildren(Parent
)))
2406 for (phWnd
= List
; *phWnd
; phWnd
++)
2409 if ((Child
= ValidateHwndNoErr(*phWnd
)))
2411 if ( Child
->style
& WS_VISIBLE
&& IntPtInWindow(Child
, Pt
.x
, Pt
.y
) )
2413 if ( Child
->pcls
->atomClassName
!= gpsi
->atomSysClass
[ICLS_BUTTON
] ||
2414 (Child
->style
& BS_TYPEMASK
) != BS_GROUPBOX
)
2416 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2423 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2425 return pwndHit
? pwndHit
: Parent
;
2429 IntChildWindowFromPointEx(PWND Parent
, LONG x
, LONG y
, UINT uiFlags
)
2433 PWND pwndHit
= NULL
;
2438 if (Parent
!= UserGetDesktopWindow())
2440 if (Parent
->ExStyle
& WS_EX_LAYOUTRTL
)
2441 Pt
.x
= Parent
->rcClient
.right
- Pt
.x
;
2443 Pt
.x
+= Parent
->rcClient
.left
;
2444 Pt
.y
+= Parent
->rcClient
.top
;
2447 if (!IntPtInWindow(Parent
, Pt
.x
, Pt
.y
)) return NULL
;
2449 if ((List
= IntWinListChildren(Parent
)))
2451 for (phWnd
= List
; *phWnd
; phWnd
++)
2454 if ((Child
= ValidateHwndNoErr(*phWnd
)))
2456 if (uiFlags
& (CWP_SKIPINVISIBLE
|CWP_SKIPDISABLED
))
2458 if (!(Child
->style
& WS_VISIBLE
) && (uiFlags
& CWP_SKIPINVISIBLE
)) continue;
2459 if ((Child
->style
& WS_DISABLED
) && (uiFlags
& CWP_SKIPDISABLED
)) continue;
2462 if (uiFlags
& CWP_SKIPTRANSPARENT
)
2464 if (Child
->ExStyle
& WS_EX_TRANSPARENT
) continue;
2467 if (IntPtInWindow(Child
, Pt
.x
, Pt
.y
))
2474 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2476 return pwndHit
? pwndHit
: Parent
;
2481 IntDeferWindowPos( HDWP hdwp
,
2492 HDWP retvalue
= hdwp
;
2494 TRACE("hdwp %p, hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
2495 hdwp
, hwnd
, hwndAfter
, x
, y
, cx
, cy
, flags
);
2497 if (flags
& ~(SWP_NOSIZE
| SWP_NOMOVE
|
2498 SWP_NOZORDER
| SWP_NOREDRAW
|
2499 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
2500 SWP_NOOWNERZORDER
|SWP_SHOWWINDOW
|
2501 SWP_HIDEWINDOW
| SWP_FRAMECHANGED
))
2503 EngSetLastError(ERROR_INVALID_PARAMETER
);
2507 if (!(pDWP
= (PSMWP
)UserGetObject(gHandleTable
, hdwp
, TYPE_SETWINDOWPOS
)))
2509 EngSetLastError(ERROR_INVALID_DWP_HANDLE
);
2513 for (i
= 0; i
< pDWP
->ccvr
; i
++)
2515 if (pDWP
->acvr
[i
].pos
.hwnd
== hwnd
)
2517 /* Merge with the other changes */
2518 if (!(flags
& SWP_NOZORDER
))
2520 pDWP
->acvr
[i
].pos
.hwndInsertAfter
= hwndAfter
;
2522 if (!(flags
& SWP_NOMOVE
))
2524 pDWP
->acvr
[i
].pos
.x
= x
;
2525 pDWP
->acvr
[i
].pos
.y
= y
;
2527 if (!(flags
& SWP_NOSIZE
))
2529 pDWP
->acvr
[i
].pos
.cx
= cx
;
2530 pDWP
->acvr
[i
].pos
.cy
= cy
;
2532 pDWP
->acvr
[i
].pos
.flags
&= flags
| ~(SWP_NOSIZE
| SWP_NOMOVE
|
2533 SWP_NOZORDER
| SWP_NOREDRAW
|
2534 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
2536 pDWP
->acvr
[i
].pos
.flags
|= flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
|
2541 if (pDWP
->ccvr
>= pDWP
->ccvrAlloc
)
2543 PCVR newpos
= ExAllocatePoolWithTag(PagedPool
, pDWP
->ccvrAlloc
* 2 * sizeof(CVR
), USERTAG_SWP
);
2549 RtlZeroMemory(newpos
, pDWP
->ccvrAlloc
* 2 * sizeof(CVR
));
2550 RtlCopyMemory(newpos
, pDWP
->acvr
, pDWP
->ccvrAlloc
* sizeof(CVR
));
2551 ExFreePoolWithTag(pDWP
->acvr
, USERTAG_SWP
);
2552 pDWP
->ccvrAlloc
*= 2;
2553 pDWP
->acvr
= newpos
;
2555 pDWP
->acvr
[pDWP
->ccvr
].pos
.hwnd
= hwnd
;
2556 pDWP
->acvr
[pDWP
->ccvr
].pos
.hwndInsertAfter
= hwndAfter
;
2557 pDWP
->acvr
[pDWP
->ccvr
].pos
.x
= x
;
2558 pDWP
->acvr
[pDWP
->ccvr
].pos
.y
= y
;
2559 pDWP
->acvr
[pDWP
->ccvr
].pos
.cx
= cx
;
2560 pDWP
->acvr
[pDWP
->ccvr
].pos
.cy
= cy
;
2561 pDWP
->acvr
[pDWP
->ccvr
].pos
.flags
= flags
;
2562 pDWP
->acvr
[pDWP
->ccvr
].hrgnClip
= NULL
;
2563 pDWP
->acvr
[pDWP
->ccvr
].hrgnInterMonitor
= NULL
;
2569 BOOL FASTCALL
IntEndDeferWindowPosEx( HDWP hdwp
, BOOL sAsync
)
2576 TRACE("%p\n", hdwp
);
2578 if (!(pDWP
= (PSMWP
)UserGetObject(gHandleTable
, hdwp
, TYPE_SETWINDOWPOS
)))
2580 EngSetLastError(ERROR_INVALID_DWP_HANDLE
);
2584 for (i
= 0, winpos
= pDWP
->acvr
; res
&& i
< pDWP
->ccvr
; i
++, winpos
++)
2587 USER_REFERENCE_ENTRY Ref
;
2589 TRACE("hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
2590 winpos
->pos
.hwnd
, winpos
->pos
.hwndInsertAfter
, winpos
->pos
.x
, winpos
->pos
.y
,
2591 winpos
->pos
.cx
, winpos
->pos
.cy
, winpos
->pos
.flags
);
2593 pwnd
= ValidateHwndNoErr(winpos
->pos
.hwnd
);
2597 UserRefObjectCo(pwnd
, &Ref
);
2602 PWINDOWPOS ppos
= ExAllocatePoolWithTag(PagedPool
, sizeof(WINDOWPOS
), USERTAG_SWP
);
2605 *ppos
= winpos
->pos
;
2606 /* Yes it's a pointer inside Win32k! */
2607 lRes
= co_IntSendMessageNoWait( winpos
->pos
.hwnd
, WM_ASYNC_SETWINDOWPOS
, 0, (LPARAM
)ppos
);
2608 /* We handle this the same way as Event Hooks and Hooks. */
2611 ExFreePoolWithTag(ppos
, USERTAG_SWP
);
2616 res
= co_WinPosSetWindowPos( pwnd
,
2617 winpos
->pos
.hwndInsertAfter
,
2624 // Hack to pass tests.... Must have some work to do so clear the error.
2625 if (res
&& (winpos
->pos
.flags
& (SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOZORDER
)) == SWP_NOZORDER
)
2626 EngSetLastError(ERROR_SUCCESS
);
2628 UserDerefObjectCo(pwnd
);
2630 ExFreePoolWithTag(pDWP
->acvr
, USERTAG_SWP
);
2631 UserDereferenceObject(pDWP
);
2632 UserDeleteObject(hdwp
, TYPE_SETWINDOWPOS
);
2640 NtUserChildWindowFromPointEx(HWND hwndParent
,
2646 TRACE("Enter NtUserChildWindowFromPointEx\n");
2647 UserEnterExclusive();
2648 if ((pwndParent
= UserGetWindowObject(hwndParent
)))
2650 pwndParent
= IntChildWindowFromPointEx(pwndParent
, x
, y
, uiFlags
);
2653 TRACE("Leave NtUserChildWindowFromPointEx\n");
2654 return pwndParent
? UserHMGetHandle(pwndParent
) : NULL
;
2661 NtUserEndDeferWindowPosEx(HDWP WinPosInfo
,
2665 TRACE("Enter NtUserEndDeferWindowPosEx\n");
2666 UserEnterExclusive();
2667 Ret
= IntEndDeferWindowPosEx(WinPosInfo
, (BOOL
)Unknown1
);
2668 TRACE("Leave NtUserEndDeferWindowPosEx, ret=%i\n", Ret
);
2677 NtUserDeferWindowPos(HDWP WinPosInfo
,
2679 HWND WndInsertAfter
,
2688 UINT Tmp
= ~(SWP_ASYNCWINDOWPOS
|SWP_DEFERERASE
|SWP_NOSENDCHANGING
|SWP_NOREPOSITION
|
2689 SWP_NOCOPYBITS
|SWP_HIDEWINDOW
|SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|
2690 SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_NOZORDER
|SWP_NOMOVE
|SWP_NOSIZE
);
2692 TRACE("Enter NtUserDeferWindowPos\n");
2693 UserEnterExclusive();
2697 EngSetLastError(ERROR_INVALID_FLAGS
);
2701 pWnd
= UserGetWindowObject(Wnd
);
2702 if ( !pWnd
|| // FIXME:
2703 pWnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
2704 pWnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
2709 if ( WndInsertAfter
&&
2710 WndInsertAfter
!= HWND_BOTTOM
&&
2711 WndInsertAfter
!= HWND_TOPMOST
&&
2712 WndInsertAfter
!= HWND_NOTOPMOST
)
2714 pWndIA
= UserGetWindowObject(WndInsertAfter
);
2716 pWndIA
== UserGetDesktopWindow() ||
2717 pWndIA
== UserGetMessageWindow() )
2723 Ret
= IntDeferWindowPos(WinPosInfo
, Wnd
, WndInsertAfter
, x
, y
, cx
, cy
, Flags
);
2726 TRACE("Leave NtUserDeferWindowPos, ret=%i\n", Ret
);
2735 NtUserGetInternalWindowPos( HWND hWnd
,
2742 WINDOWPLACEMENT wndpl
;
2746 if (!(Window
= UserGetWindowObject(hWnd
)))
2756 ProbeForWrite(rectWnd
,
2762 ProbeForWrite(ptIcon
,
2768 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2770 SetLastNtError(_SEH2_GetExceptionCode());
2775 wndpl
.length
= sizeof(WINDOWPLACEMENT
);
2777 if (IntGetWindowPlacement(Window
, &wndpl
) && !Hit
)
2783 RtlCopyMemory(rectWnd
, &wndpl
.rcNormalPosition
, sizeof(RECT
));
2787 RtlCopyMemory(ptIcon
, &wndpl
.ptMinPosition
, sizeof(POINT
));
2791 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2793 SetLastNtError(_SEH2_GetExceptionCode());
2798 if (!Hit
) Ret
= wndpl
.showCmd
;
2809 NtUserGetWindowPlacement(HWND hWnd
,
2810 WINDOWPLACEMENT
*lpwndpl
)
2813 WINDOWPLACEMENT Safepl
;
2815 DECLARE_RETURN(BOOL
);
2817 TRACE("Enter NtUserGetWindowPlacement\n");
2820 if (!(Wnd
= UserGetWindowObject(hWnd
)))
2825 Status
= MmCopyFromCaller(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
2826 if(!NT_SUCCESS(Status
))
2828 SetLastNtError(Status
);
2831 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
2836 IntGetWindowPlacement(Wnd
, &Safepl
);
2838 Status
= MmCopyToCaller(lpwndpl
, &Safepl
, sizeof(WINDOWPLACEMENT
));
2839 if(!NT_SUCCESS(Status
))
2841 SetLastNtError(Status
);
2848 TRACE("Leave NtUserGetWindowPlacement, ret=%i\n",_ret_
);
2857 UINT cmd
, // Wine SW_ commands
2862 TRACE("Enter NtUserMinMaximize\n");
2863 UserEnterExclusive();
2865 pWnd
= UserGetWindowObject(hWnd
);
2866 if ( !pWnd
|| // FIXME:
2867 pWnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
2868 pWnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
2873 if ( cmd
> SW_MAX
|| pWnd
->state2
& WNDS2_INDESTROY
)
2875 EngSetLastError(ERROR_INVALID_PARAMETER
);
2879 cmd
|= Hide
? SW_HIDE
: 0;
2881 co_WinPosShowWindow(pWnd
, cmd
);
2884 TRACE("Leave NtUserMinMaximize\n");
2886 return 0; // Always NULL?
2901 return NtUserSetWindowPos(hWnd
, 0, X
, Y
, nWidth
, nHeight
,
2902 (bRepaint
? SWP_NOZORDER
| SWP_NOACTIVATE
:
2903 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
));
2910 NtUserRealChildWindowFromPoint(HWND Parent
,
2915 TRACE("Enter NtUserRealChildWindowFromPoint\n");
2917 if ((pwndParent
= UserGetWindowObject(Parent
)))
2919 pwndParent
= IntRealChildWindowFromPoint(pwndParent
, x
, y
);
2922 TRACE("Leave NtUserRealChildWindowFromPoint\n");
2923 return pwndParent
? UserHMGetHandle(pwndParent
) : NULL
;
2932 HWND hWndInsertAfter
,
2939 DECLARE_RETURN(BOOL
);
2940 PWND Window
, pWndIA
;
2942 USER_REFERENCE_ENTRY Ref
;
2944 TRACE("Enter NtUserSetWindowPos\n");
2945 UserEnterExclusive();
2947 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
2948 Window
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
2949 Window
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
2951 ERR("NtUserSetWindowPos bad window handle!\n");
2955 if ( hWndInsertAfter
&&
2956 hWndInsertAfter
!= HWND_BOTTOM
&&
2957 hWndInsertAfter
!= HWND_TOPMOST
&&
2958 hWndInsertAfter
!= HWND_NOTOPMOST
)
2960 if (!(pWndIA
= UserGetWindowObject(hWndInsertAfter
)) ||
2961 pWndIA
== UserGetDesktopWindow() ||
2962 pWndIA
== UserGetMessageWindow() )
2964 ERR("NtUserSetWindowPos bad insert window handle!\n");
2969 /* First make sure that coordinates are valid for WM_WINDOWPOSCHANGING */
2970 if (!(uFlags
& SWP_NOMOVE
))
2972 if (X
< -32768) X
= -32768;
2973 else if (X
> 32767) X
= 32767;
2974 if (Y
< -32768) Y
= -32768;
2975 else if (Y
> 32767) Y
= 32767;
2977 if (!(uFlags
& SWP_NOSIZE
))
2980 else if (cx
> 32767) cx
= 32767;
2982 else if (cy
> 32767) cy
= 32767;
2985 UserRefObjectCo(Window
, &Ref
);
2986 ret
= co_WinPosSetWindowPos(Window
, hWndInsertAfter
, X
, Y
, cx
, cy
, uFlags
);
2987 UserDerefObjectCo(Window
);
2992 TRACE("Leave NtUserSetWindowPos, ret=%i\n",_ret_
);
3008 INT flags
= (SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
);
3009 BOOLEAN Ret
= FALSE
;
3010 DECLARE_RETURN(INT
);
3012 TRACE("Enter NtUserSetWindowRgn\n");
3013 UserEnterExclusive();
3015 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
3016 Window
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3017 Window
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3022 if (hRgn
) // The region will be deleted in user32.
3024 if (GreIsHandleValid(hRgn
))
3026 hrgnCopy
= IntSysCreateRectRgn(0, 0, 0, 0);
3027 /* The coordinates of a window's window region are relative to the
3028 upper-left corner of the window, not the client area of the window. */
3029 NtGdiCombineRgn( hrgnCopy
, hRgn
, 0, RGN_COPY
);
3039 if (Window
->hrgnClip
)
3041 /* Delete no longer needed region handle */
3042 IntGdiSetRegionOwner(Window
->hrgnClip
, GDI_OBJ_HMGR_POWNED
);
3043 GreDeleteObject(Window
->hrgnClip
);
3048 /* Set public ownership */
3049 IntGdiSetRegionOwner(hrgnCopy
, GDI_OBJ_HMGR_PUBLIC
);
3051 Window
->hrgnClip
= hrgnCopy
;
3053 Ret
= co_WinPosSetWindowPos(Window
, HWND_TOP
, 0, 0, 0, 0, bRedraw
? flags
: (flags
|SWP_NOREDRAW
) );
3058 TRACE("Leave NtUserSetWindowRgn, ret=%i\n",_ret_
);
3067 NtUserSetInternalWindowPos(
3073 WINDOWPLACEMENT wndpl
;
3078 DECLARE_RETURN(BOOL
);
3079 USER_REFERENCE_ENTRY Ref
;
3081 TRACE("Enter NtUserSetWindowPlacement\n");
3082 UserEnterExclusive();
3084 if (!(Wnd
= UserGetWindowObject(hwnd
)) || // FIXME:
3085 Wnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3086 Wnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3095 ProbeForRead(lppt
, sizeof(POINT
), 1);
3096 RtlCopyMemory(&pt
, lppt
, sizeof(POINT
));
3100 ProbeForRead(lprect
, sizeof(RECT
), 1);
3101 RtlCopyMemory(&rect
, lprect
, sizeof(RECT
));
3104 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3106 SetLastNtError(_SEH2_GetExceptionCode());
3107 _SEH2_YIELD(RETURN( FALSE
));
3111 wndpl
.length
= sizeof(wndpl
);
3112 wndpl
.showCmd
= showCmd
;
3113 wndpl
.flags
= flags
= 0;
3118 wndpl
.flags
|= WPF_SETMINPOSITION
;
3119 wndpl
.ptMinPosition
= pt
;
3123 flags
|= PLACE_RECT
;
3124 wndpl
.rcNormalPosition
= rect
;
3127 UserRefObjectCo(Wnd
, &Ref
);
3128 IntSetWindowPlacement(Wnd
, &wndpl
, flags
);
3129 UserDerefObjectCo(Wnd
);
3133 TRACE("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_
);
3142 NtUserSetWindowPlacement(HWND hWnd
,
3143 WINDOWPLACEMENT
*lpwndpl
)
3146 WINDOWPLACEMENT Safepl
;
3148 DECLARE_RETURN(BOOL
);
3149 USER_REFERENCE_ENTRY Ref
;
3151 TRACE("Enter NtUserSetWindowPlacement\n");
3152 UserEnterExclusive();
3154 if (!(Wnd
= UserGetWindowObject(hWnd
)) || // FIXME:
3155 Wnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3156 Wnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3163 ProbeForRead(lpwndpl
, sizeof(WINDOWPLACEMENT
), 1);
3164 RtlCopyMemory(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
3166 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3168 SetLastNtError(_SEH2_GetExceptionCode());
3169 _SEH2_YIELD(RETURN( FALSE
));
3173 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
3178 Flags
= PLACE_MAX
| PLACE_RECT
;
3179 if (Safepl
.flags
& WPF_SETMINPOSITION
) Flags
|= PLACE_MIN
;
3180 UserRefObjectCo(Wnd
, &Ref
);
3181 IntSetWindowPlacement(Wnd
, &Safepl
, Flags
);
3182 UserDerefObjectCo(Wnd
);
3186 TRACE("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_
);
3195 NtUserShowWindowAsync(HWND hWnd
, LONG nCmdShow
)
3199 DECLARE_RETURN(BOOL
);
3200 USER_REFERENCE_ENTRY Ref
;
3202 TRACE("Enter NtUserShowWindowAsync\n");
3203 UserEnterExclusive();
3205 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
3206 Window
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3207 Window
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3212 if ( nCmdShow
> SW_MAX
)
3214 EngSetLastError(ERROR_INVALID_PARAMETER
);
3218 UserRefObjectCo(Window
, &Ref
);
3219 ret
= co_IntSendMessageNoWait( hWnd
, WM_ASYNC_SHOWWINDOW
, nCmdShow
, 0 );
3220 UserDerefObjectCo(Window
);
3221 if (-1 == (int) ret
|| !ret
) ret
= FALSE
;
3226 TRACE("Leave NtUserShowWindowAsync, ret=%i\n",_ret_
);
3235 NtUserShowWindow(HWND hWnd
, LONG nCmdShow
)
3239 DECLARE_RETURN(BOOL
);
3240 USER_REFERENCE_ENTRY Ref
;
3242 TRACE("Enter NtUserShowWindow\n");
3243 UserEnterExclusive();
3245 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
3246 Window
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3247 Window
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3252 if ( nCmdShow
> SW_MAX
|| Window
->state2
& WNDS2_INDESTROY
)
3254 EngSetLastError(ERROR_INVALID_PARAMETER
);
3258 UserRefObjectCo(Window
, &Ref
);
3259 ret
= co_WinPosShowWindow(Window
, nCmdShow
);
3260 UserDerefObjectCo(Window
);
3265 TRACE("Leave NtUserShowWindow, ret=%i\n",_ret_
);
3275 NtUserWindowFromPoint(LONG X
, LONG Y
)
3279 PWND DesktopWindow
= NULL
, Window
= NULL
;
3281 DECLARE_RETURN(HWND
);
3282 USER_REFERENCE_ENTRY Ref
;
3284 TRACE("Enter NtUserWindowFromPoint\n");
3285 UserEnterExclusive();
3287 if ((DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow())))
3294 // Hmm... Threads live on desktops thus we have a reference on the desktop and indirectly the desktop window.
3295 // It is possible this referencing is useless, though it should not hurt...
3296 UserRefObjectCo(DesktopWindow
, &Ref
);
3298 //pti = PsGetCurrentThreadWin32Thread();
3299 Window
= co_WinPosWindowFromPoint(DesktopWindow
, &pt
, &hittest
);
3303 Ret
= UserHMGetHandle(Window
);
3312 if (Window
) UserDereferenceObject(Window
);
3313 if (DesktopWindow
) UserDerefObjectCo(DesktopWindow
);
3315 TRACE("Leave NtUserWindowFromPoint, ret=%i\n",_ret_
);