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 for (i
= 0; i
!= cPoints
; i
++)
125 lpPoints
[i
].x
+= Delta
.x
;
126 lpPoints
[i
].x
*= Change
;
127 lpPoints
[i
].y
+= Delta
.y
;
130 if ((mirror_from
|| mirror_to
) && cPoints
== 2) /* special case for rectangle */
132 int tmp
= min(lpPoints
[0].x
, lpPoints
[1].x
);
133 lpPoints
[1].x
= max(lpPoints
[0].x
, lpPoints
[1].x
);
137 return MAKELONG(LOWORD(Delta
.x
), LOWORD(Delta
.y
));
141 IntClientToScreen(PWND Wnd
, LPPOINT lpPoint
)
143 if (Wnd
&& Wnd
->fnid
!= FNID_DESKTOP
)
145 if (Wnd
->ExStyle
& WS_EX_LAYOUTRTL
)
146 lpPoint
->x
= Wnd
->rcClient
.right
- lpPoint
->x
;
148 lpPoint
->x
+= Wnd
->rcClient
.left
;
149 lpPoint
->y
+= Wnd
->rcClient
.top
;
155 IntScreenToClient(PWND Wnd
, LPPOINT lpPoint
)
157 if (Wnd
&& Wnd
->fnid
!= FNID_DESKTOP
)
159 if (Wnd
->ExStyle
& WS_EX_LAYOUTRTL
)
160 lpPoint
->x
= Wnd
->rcClient
.right
- lpPoint
->x
;
162 lpPoint
->x
-= Wnd
->rcClient
.left
;
163 lpPoint
->y
-= Wnd
->rcClient
.top
;
168 BOOL FASTCALL
IsChildVisible(PWND pWnd
)
172 if ( (pWnd
->style
& (WS_POPUP
|WS_CHILD
)) != WS_CHILD
||
173 !(pWnd
= pWnd
->spwndParent
) )
176 while (pWnd
->style
& WS_VISIBLE
);
180 PWND FASTCALL
IntGetLastTopMostWindow(VOID
)
183 PDESKTOP rpdesk
= gptiCurrent
->rpdesk
;
186 (pWnd
= rpdesk
->pDeskInfo
->spwnd
->spwndChild
) &&
187 pWnd
->ExStyle
& WS_EX_TOPMOST
)
191 if (!pWnd
->spwndNext
) break;
192 if (!(pWnd
->spwndNext
->ExStyle
& WS_EX_TOPMOST
)) break;
193 pWnd
= pWnd
->spwndNext
;
201 // This helps with bug 6751 forcing modal dialog active when another app is minimized or closed.
203 BOOL FASTCALL
ActivateOtherWindowMin(PWND Wnd
)
205 BOOL ActivePrev
, FindTopWnd
;
206 PWND pWndTopMost
, pWndChild
, pWndSetActive
, pWndTemp
, pWndDesk
;
207 USER_REFERENCE_ENTRY Ref
;
208 PTHREADINFO pti
= gptiCurrent
;
211 ActivePrev
= (pti
->MessageQueue
->spwndActivePrev
!= NULL
);
214 if ((pWndTopMost
= IntGetLastTopMostWindow()))
215 pWndChild
= pWndTopMost
->spwndNext
;
217 pWndChild
= Wnd
->spwndParent
->spwndChild
;
222 pWndSetActive
= pti
->MessageQueue
->spwndActivePrev
;
224 pWndSetActive
= pWndChild
;
230 if ( VerifyWnd(pWndSetActive
) &&
231 !(pWndSetActive
->ExStyle
& WS_EX_NOACTIVATE
) &&
232 (pWndSetActive
->style
& (WS_VISIBLE
|WS_DISABLED
)) == WS_VISIBLE
&&
233 (!(pWndSetActive
->style
& WS_ICONIC
) /* FIXME MinMax pos? */ ) )
235 if (!(pWndSetActive
->ExStyle
& WS_EX_TOOLWINDOW
) )
237 UserRefObjectCo(pWndSetActive
, &Ref
);
238 //ERR("ActivateOtherWindowMin Set FG 1\n");
239 co_IntSetForegroundWindow(pWndSetActive
);
240 UserDerefObjectCo(pWndSetActive
);
241 //ERR("AOWM 2 Exit Good\n");
244 if (!pWndTemp
) pWndTemp
= pWndSetActive
;
249 pWndSetActive
= pWndChild
;
252 pWndSetActive
= pWndSetActive
->spwndNext
;
255 if ( !FindTopWnd
) break;
260 pWndChild
= pWndChild
->spwndParent
->spwndChild
;
264 if (!(pWndDesk
= IntGetThreadDesktopWindow(pti
)))
269 pWndChild
= pWndDesk
->spwndChild
;
272 if ((pWndSetActive
= pWndTemp
))
274 UserRefObjectCo(pWndSetActive
, &Ref
);
275 //ERR("ActivateOtherWindowMin Set FG 2\n");
276 co_IntSetForegroundWindow(pWndSetActive
);
277 UserDerefObjectCo(pWndSetActive
);
278 //ERR("AOWM 3 Exit Good\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
)
317 USER_REFERENCE_ENTRY Ref
;
321 if (IntIsDesktopWindow(Wnd
))
323 IntSetFocusMessageQueue(NULL
);
327 /* If this is popup window, try to activate the owner first. */
328 if ((Wnd
->style
& WS_POPUP
) && (WndTo
= Wnd
->spwndOwner
))
330 WndTo
= UserGetAncestor( WndTo
, GA_ROOT
);
331 if (can_activate_window(WndTo
)) goto done
;
334 /* Pick a next top-level window. */
335 /* FIXME: Search for non-tooltip windows first. */
339 if (!(WndTo
= WndTo
->spwndNext
)) break;
340 if (can_activate_window( WndTo
)) break;
345 if (WndTo
) UserRefObjectCo(WndTo
, &Ref
);
347 if (!gpqForeground
|| Wnd
== gpqForeground
->spwndActive
)
349 /* ReactOS can pass WndTo = NULL to co_IntSetForegroundWindow and returns FALSE. */
350 //ERR("WinPosActivateOtherWindow Set FG 0x%p\n",WndTo);
351 if (co_IntSetForegroundWindow(WndTo
))
353 if (WndTo
) UserDerefObjectCo(WndTo
);
357 //ERR("WinPosActivateOtherWindow Set Active 0x%p\n",WndTo);
358 if (!co_IntSetActiveWindow(WndTo
,FALSE
,TRUE
,FALSE
)) /* Ok for WndTo to be NULL here */
360 co_IntSetActiveWindow(NULL
,FALSE
,TRUE
,FALSE
);
362 if (WndTo
) UserDerefObjectCo(WndTo
);
367 co_WinPosArrangeIconicWindows(PWND parent
)
370 INT i
, x
, y
, xspacing
, yspacing
, sx
, sy
;
371 HWND
*List
= IntWinListChildren(parent
);
373 ASSERT_REFS_CO(parent
);
375 /* Check if we found any children */
381 IntGetClientRect( parent
, &rectParent
);
382 // FIXME: Support gspv.mm.iArrange.
384 y
= rectParent
.bottom
;
386 xspacing
= (UserGetSystemMetrics(SM_CXMINSPACING
)/2)+UserGetSystemMetrics(SM_CXBORDER
);
387 yspacing
= (UserGetSystemMetrics(SM_CYMINSPACING
)/2)+UserGetSystemMetrics(SM_CYBORDER
);
389 //ERR("X:%d Y:%d XS:%d YS:%d\n",x,y,xspacing,yspacing);
391 for(i
= 0; List
[i
]; i
++)
395 if (!(Child
= ValidateHwndNoErr(List
[i
])))
398 if((Child
->style
& WS_MINIMIZE
) != 0 )
400 USER_REFERENCE_ENTRY Ref
;
401 UserRefObjectCo(Child
, &Ref
);
403 sx
= x
+ UserGetSystemMetrics(SM_CXBORDER
);
404 sy
= y
- yspacing
- UserGetSystemMetrics(SM_CYBORDER
);
406 co_WinPosSetWindowPos( Child
, 0, sx
, sy
, 0, 0,
407 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
409 Child
->InternalPos
.IconPos
.x
= sx
;
410 Child
->InternalPos
.IconPos
.y
= sy
;
411 Child
->InternalPos
.flags
|= WPF_MININIT
;
412 Child
->InternalPos
.flags
&= ~WPF_SETMINPOSITION
;
414 UserDerefObjectCo(Child
);
416 if (x
<= (rectParent
.right
- UserGetSystemMetrics(SM_CXMINSPACING
)))
423 //ERR("X:%d Y:%d\n",x,y);
426 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
431 WinPosFindIconPos(PWND Window
, POINT
*Pos
)
434 PWND pwndChild
, pwndParent
;
435 int x
, y
, xspacing
, yspacing
;
437 pwndParent
= Window
->spwndParent
;
438 if (pwndParent
== UserGetDesktopWindow())
440 //ERR("Parent is Desktop, Min off screen!\n");
441 /* ReactOS doesn't support iconic minimize to desktop */
442 Pos
->x
= Pos
->y
= -32000;
443 Window
->InternalPos
.flags
|= WPF_MININIT
;
444 Window
->InternalPos
.IconPos
.x
= Pos
->x
;
445 Window
->InternalPos
.IconPos
.y
= Pos
->y
;
449 IntGetClientRect( pwndParent
, &rectParent
);
450 // FIXME: Support gspv.mm.iArrange.
452 y
= rectParent
.bottom
;
454 xspacing
= (UserGetSystemMetrics(SM_CXMINSPACING
)/2)+UserGetSystemMetrics(SM_CXBORDER
);
455 yspacing
= (UserGetSystemMetrics(SM_CYMINSPACING
)/2)+UserGetSystemMetrics(SM_CYBORDER
);
457 //ERR("X:%d Y:%d XS:%d YS:%d\n",Pos->x,Pos->y,xspacing,yspacing);
459 // Set to default position when minimized.
460 Pos
->x
= x
+ UserGetSystemMetrics(SM_CXBORDER
);
461 Pos
->y
= y
- yspacing
- UserGetSystemMetrics(SM_CYBORDER
);
463 for (pwndChild
= pwndParent
->spwndChild
; pwndChild
; pwndChild
= pwndChild
->spwndNext
)
465 if (pwndChild
== Window
) continue;
467 if (pwndChild
->style
& WS_VISIBLE
)
472 //ERR("Pos Child X %d Y %d!\n", pwndChild->InternalPos.IconPos.x, pwndChild->InternalPos.IconPos.y);
473 if ( pwndChild
->InternalPos
.IconPos
.x
== Pos
->x
&&
474 pwndChild
->InternalPos
.IconPos
.y
== Pos
->y
)
476 if (x
<= rectParent
.right
- UserGetSystemMetrics(SM_CXMINSPACING
))
483 Pos
->x
= x
+ UserGetSystemMetrics(SM_CXBORDER
);
484 Pos
->y
= y
- yspacing
- UserGetSystemMetrics(SM_CYBORDER
);
487 Window
->InternalPos
.IconPos
.x
= Pos
->x
;
488 Window
->InternalPos
.IconPos
.y
= Pos
->y
;
489 Window
->InternalPos
.flags
|= WPF_MININIT
;
490 //ERR("Position is set! X:%d Y:%d\n",Pos->x,Pos->y);
495 WinPosInitInternalPos(PWND Wnd
, RECTL
*RestoreRect
)
498 RECTL Rect
= *RestoreRect
;
500 if (Wnd
->spwndParent
!= UserGetDesktopWindow())
502 RECTL_vOffsetRect(&Rect
,
503 -Wnd
->spwndParent
->rcClient
.left
,
504 -Wnd
->spwndParent
->rcClient
.top
);
510 if (!Wnd
->InternalPosInitialized
)
512 // FIXME: Use check point Atom..
513 Wnd
->InternalPos
.flags
= 0;
514 Wnd
->InternalPos
.MaxPos
.x
= Wnd
->InternalPos
.MaxPos
.y
= -1;
515 Wnd
->InternalPos
.IconPos
.x
= Wnd
->InternalPos
.IconPos
.y
= -1;
516 Wnd
->InternalPos
.NormalRect
= Rect
;
517 Wnd
->InternalPosInitialized
= TRUE
;
520 if (Wnd
->style
& WS_MINIMIZE
)
522 Wnd
->InternalPos
.IconPos
= Size
;
523 Wnd
->InternalPos
.flags
|= WPF_MININIT
;
525 else if (Wnd
->style
& WS_MAXIMIZE
)
527 Wnd
->InternalPos
.flags
|= WPF_MAXINIT
;
529 if ( Wnd
->spwndParent
== Wnd
->head
.rpdesk
->pDeskInfo
->spwnd
)
531 if (Wnd
->state
& WNDS_MAXIMIZESTOMONITOR
)
533 Wnd
->InternalPos
.flags
&= ~WPF_MAXINIT
;
534 Wnd
->InternalPos
.MaxPos
.x
= Wnd
->InternalPos
.MaxPos
.y
= -1;
539 PMONITOR pmonitor
= UserMonitorFromRect(&Rect
, MONITOR_DEFAULTTOPRIMARY
);
540 // FIXME: support DPI aware, rcWorkDPI/Real etc..
541 WorkArea
= pmonitor
->rcMonitor
;
543 if (Wnd
->style
& WS_MAXIMIZEBOX
)
544 { // Support (Wnd->state & WNDS_HASCAPTION) || pmonitor->cFullScreen too.
545 if ((Wnd
->style
& WS_CAPTION
) == WS_CAPTION
|| !(Wnd
->style
& (WS_CHILD
| WS_POPUP
)))
547 WorkArea
= pmonitor
->rcWork
;
552 Wnd
->InternalPos
.MaxPos
.x
= Rect
.left
- WorkArea
.left
;
553 Wnd
->InternalPos
.MaxPos
.y
= Rect
.top
- WorkArea
.top
;
555 /*ERR("WinPosIP 2 X %d = R.l %d - W.l %d | Y %d = R.t %d - W.t %d\n",
556 Wnd->InternalPos.MaxPos.x,
557 Rect.left, WorkArea.left,
558 Wnd->InternalPos.MaxPos.y,
559 Rect.top, WorkArea.top);*/
563 Wnd
->InternalPos
.MaxPos
= Size
;
567 Wnd
->InternalPos
.NormalRect
= Rect
;
573 IntGetWindowPlacement(PWND Wnd
, WINDOWPLACEMENT
*lpwndpl
)
575 if (!Wnd
) return FALSE
;
577 if(lpwndpl
->length
!= sizeof(WINDOWPLACEMENT
))
584 WinPosInitInternalPos(Wnd
, &Wnd
->rcWindow
);
586 lpwndpl
->showCmd
= SW_HIDE
;
588 if ( Wnd
->style
& WS_MINIMIZE
)
589 lpwndpl
->showCmd
= SW_SHOWMINIMIZED
;
591 lpwndpl
->showCmd
= ( Wnd
->style
& WS_MAXIMIZE
) ? SW_SHOWMAXIMIZED
: SW_SHOWNORMAL
;
593 lpwndpl
->rcNormalPosition
= Wnd
->InternalPos
.NormalRect
;
595 if (Wnd
->InternalPos
.flags
& WPF_MININIT
) // Return if it was set!
597 lpwndpl
->ptMinPosition
.x
= Wnd
->InternalPos
.IconPos
.x
;
598 lpwndpl
->ptMinPosition
.y
= Wnd
->InternalPos
.IconPos
.y
;
601 lpwndpl
->ptMinPosition
.x
= lpwndpl
->ptMinPosition
.y
= -1;
603 if ( Wnd
->InternalPos
.flags
& WPF_MAXINIT
&& // Return if set and not maximized to monitor!
604 !(Wnd
->state
& WNDS_MAXIMIZESTOMONITOR
))
606 lpwndpl
->ptMaxPosition
.x
= Wnd
->InternalPos
.MaxPos
.x
;
607 lpwndpl
->ptMaxPosition
.y
= Wnd
->InternalPos
.MaxPos
.y
;
610 lpwndpl
->ptMaxPosition
.x
= lpwndpl
->ptMaxPosition
.y
= -1;
612 if ( Wnd
->spwndParent
== Wnd
->head
.rpdesk
->pDeskInfo
->spwnd
&&
613 !(Wnd
->ExStyle
& WS_EX_TOOLWINDOW
))
615 PMONITOR pmonitor
= UserMonitorFromRect(&lpwndpl
->rcNormalPosition
, MONITOR_DEFAULTTOPRIMARY
);
617 // FIXME: support DPI aware, rcWorkDPI/Real etc..
618 if (Wnd
->InternalPos
.flags
& WPF_MININIT
)
620 lpwndpl
->ptMinPosition
.x
-= (pmonitor
->rcWork
.left
- pmonitor
->rcMonitor
.left
);
621 lpwndpl
->ptMinPosition
.y
-= (pmonitor
->rcWork
.top
- pmonitor
->rcMonitor
.top
);
623 RECTL_vOffsetRect(&lpwndpl
->rcNormalPosition
,
624 pmonitor
->rcMonitor
.left
- pmonitor
->rcWork
.left
,
625 pmonitor
->rcMonitor
.top
- pmonitor
->rcWork
.top
);
628 if ( Wnd
->InternalPos
.flags
& WPF_RESTORETOMAXIMIZED
|| Wnd
->style
& WS_MAXIMIZE
)
629 lpwndpl
->flags
|= WPF_RESTORETOMAXIMIZED
;
631 if ( ((Wnd
->style
& (WS_CHILD
|WS_POPUP
)) == WS_CHILD
) && Wnd
->InternalPos
.flags
& WPF_SETMINPOSITION
)
632 lpwndpl
->flags
|= WPF_SETMINPOSITION
;
637 /* make sure the specified rect is visible on screen */
638 static void make_rect_onscreen( RECT
*rect
)
640 PMONITOR pmonitor
= UserMonitorFromRect( rect
, MONITOR_DEFAULTTONEAREST
); // Wine uses this.
642 // FIXME: support DPI aware, rcWorkDPI/Real etc..
643 if (!pmonitor
) return;
644 /* FIXME: map coordinates from rcWork to rcMonitor */
645 if (rect
->right
<= pmonitor
->rcWork
.left
)
647 rect
->right
+= pmonitor
->rcWork
.left
- rect
->left
;
648 rect
->left
= pmonitor
->rcWork
.left
;
650 else if (rect
->left
>= pmonitor
->rcWork
.right
)
652 rect
->left
+= pmonitor
->rcWork
.right
- rect
->right
;
653 rect
->right
= pmonitor
->rcWork
.right
;
655 if (rect
->bottom
<= pmonitor
->rcWork
.top
)
657 rect
->bottom
+= pmonitor
->rcWork
.top
- rect
->top
;
658 rect
->top
= pmonitor
->rcWork
.top
;
660 else if (rect
->top
>= pmonitor
->rcWork
.bottom
)
662 rect
->top
+= pmonitor
->rcWork
.bottom
- rect
->bottom
;
663 rect
->bottom
= pmonitor
->rcWork
.bottom
;
667 /* make sure the specified point is visible on screen */
668 static void make_point_onscreen( POINT
*pt
)
672 RECTL_vSetRect( &rect
, pt
->x
, pt
->y
, pt
->x
+ 1, pt
->y
+ 1 );
673 make_rect_onscreen( &rect
);
679 IntSetWindowPlacement(PWND Wnd
, WINDOWPLACEMENT
*wpl
, UINT Flags
)
684 if ( Flags
& PLACE_MIN
) make_point_onscreen( &wpl
->ptMinPosition
);
685 if ( Flags
& PLACE_MAX
) make_point_onscreen( &wpl
->ptMaxPosition
);
686 if ( Flags
& PLACE_RECT
) make_rect_onscreen( &wpl
->rcNormalPosition
);
688 if (!Wnd
|| Wnd
== Wnd
->head
.rpdesk
->pDeskInfo
->spwnd
) return FALSE
;
690 if ( Flags
& PLACE_MIN
) Wnd
->InternalPos
.IconPos
= wpl
->ptMinPosition
;
691 if ( Flags
& PLACE_MAX
) Wnd
->InternalPos
.MaxPos
= wpl
->ptMaxPosition
;
692 if ( Flags
& PLACE_RECT
) Wnd
->InternalPos
.NormalRect
= wpl
->rcNormalPosition
;
694 SWP_Flags
= SWP_NOZORDER
| SWP_NOACTIVATE
| ((wpl
->flags
& WPF_ASYNCWINDOWPLACEMENT
) ? SWP_ASYNCWINDOWPOS
: 0);
696 if (Wnd
->style
& WS_MINIMIZE
)
698 if (Flags
& PLACE_MIN
|| Wnd
->InternalPos
.flags
& WPF_SETMINPOSITION
)
700 co_WinPosSetWindowPos(Wnd
, HWND_TOP
,
701 wpl
->ptMinPosition
.x
, wpl
->ptMinPosition
.y
, 0, 0,
702 SWP_NOSIZE
| SWP_Flags
);
703 Wnd
->InternalPos
.flags
|= WPF_MININIT
;
706 else if (Wnd
->style
& WS_MAXIMIZE
)
708 if (Flags
& PLACE_MAX
)
710 co_WinPosSetWindowPos(Wnd
, HWND_TOP
,
711 wpl
->ptMaxPosition
.x
, wpl
->ptMaxPosition
.y
, 0, 0,
712 SWP_NOSIZE
| SWP_Flags
);
713 Wnd
->InternalPos
.flags
|= WPF_MAXINIT
;
716 else if (Flags
& PLACE_RECT
)
718 co_WinPosSetWindowPos(Wnd
, HWND_TOP
,
719 wpl
->rcNormalPosition
.left
, wpl
->rcNormalPosition
.top
,
720 wpl
->rcNormalPosition
.right
- wpl
->rcNormalPosition
.left
,
721 wpl
->rcNormalPosition
.bottom
- wpl
->rcNormalPosition
.top
,
725 sAsync
= (Wnd
->head
.pti
->MessageQueue
!= gptiCurrent
->MessageQueue
&& wpl
->flags
& WPF_ASYNCWINDOWPLACEMENT
);
728 co_IntSendMessageNoWait( UserHMGetHandle(Wnd
), WM_ASYNC_SHOWWINDOW
, wpl
->showCmd
, 0 );
730 co_WinPosShowWindow(Wnd
, wpl
->showCmd
);
732 if ( Wnd
->style
& WS_MINIMIZE
&& !sAsync
)
734 if ( wpl
->flags
& WPF_SETMINPOSITION
)
735 Wnd
->InternalPos
.flags
|= WPF_SETMINPOSITION
;
737 if ( wpl
->flags
& WPF_RESTORETOMAXIMIZED
)
738 Wnd
->InternalPos
.flags
|= WPF_RESTORETOMAXIMIZED
;
744 co_WinPosMinMaximize(PWND Wnd
, UINT ShowFlag
, RECT
* NewPos
)
753 wpl
.length
= sizeof(wpl
);
754 IntGetWindowPlacement( Wnd
, &wpl
);
756 if (co_HOOK_CallHooks( WH_CBT
, HCBT_MINMAX
, (WPARAM
)Wnd
->head
.h
, ShowFlag
))
758 ERR("WinPosMinMaximize WH_CBT Call Hook return!\n");
759 return SWP_NOSIZE
| SWP_NOMOVE
;
761 if (Wnd
->style
& WS_MINIMIZE
)
765 case SW_SHOWMINNOACTIVE
:
766 case SW_SHOWMINIMIZED
:
767 case SW_FORCEMINIMIZE
:
769 return SWP_NOSIZE
| SWP_NOMOVE
;
771 if (!co_IntSendMessageNoWait(Wnd
->head
.h
, WM_QUERYOPEN
, 0, 0))
773 return(SWP_NOSIZE
| SWP_NOMOVE
);
775 SwpFlags
|= SWP_NOCOPYBITS
;
779 case SW_SHOWMINNOACTIVE
:
780 case SW_SHOWMINIMIZED
:
781 case SW_FORCEMINIMIZE
:
784 //ERR("MinMaximize Minimize\n");
785 if (Wnd
->style
& WS_MAXIMIZE
)
787 Wnd
->InternalPos
.flags
|= WPF_RESTORETOMAXIMIZED
;
791 Wnd
->InternalPos
.flags
&= ~WPF_RESTORETOMAXIMIZED
;
794 old_style
= IntSetStyle( Wnd
, WS_MINIMIZE
, WS_MAXIMIZE
);
796 co_UserRedrawWindow(Wnd
, NULL
, 0, RDW_VALIDATE
| RDW_NOERASE
|
797 RDW_NOINTERNALPAINT
);
799 if (!(Wnd
->InternalPos
.flags
& WPF_SETMINPOSITION
))
800 Wnd
->InternalPos
.flags
&= ~WPF_MININIT
;
802 WinPosFindIconPos(Wnd
, &wpl
.ptMinPosition
);
804 if (!(old_style
& WS_MINIMIZE
)) SwpFlags
|= SWP_STATECHANGED
;
806 /*ERR("Minimize: %d,%d %dx%d\n",
807 wpl.ptMinPosition.x, wpl.ptMinPosition.y, UserGetSystemMetrics(SM_CXMINIMIZED),
808 UserGetSystemMetrics(SM_CYMINIMIZED));
810 RECTL_vSetRect(NewPos
, wpl
.ptMinPosition
.x
, wpl
.ptMinPosition
.y
,
811 // wpl.ptMinPosition.x + UserGetSystemMetrics(SM_CXMINIMIZED),
812 // wpl.ptMinPosition.y + UserGetSystemMetrics(SM_CYMINIMIZED));
813 UserGetSystemMetrics(SM_CXMINIMIZED
),
814 UserGetSystemMetrics(SM_CYMINIMIZED
));
815 SwpFlags
|= SWP_NOCOPYBITS
;
821 //ERR("MinMaximize Maximize\n");
822 if ((Wnd
->style
& WS_MAXIMIZE
) && (Wnd
->style
& WS_VISIBLE
))
824 SwpFlags
= SWP_NOSIZE
| SWP_NOMOVE
;
827 co_WinPosGetMinMaxInfo(Wnd
, &Size
, &wpl
.ptMaxPosition
, NULL
, NULL
);
829 /*ERR("Maximize: %d,%d %dx%d\n",
830 wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, Size.x, Size.y);
832 old_style
= IntSetStyle( Wnd
, WS_MAXIMIZE
, WS_MINIMIZE
);
834 if (!(old_style
& WS_MAXIMIZE
)) SwpFlags
|= SWP_STATECHANGED
;
835 RECTL_vSetRect(NewPos
, wpl
.ptMaxPosition
.x
, wpl
.ptMaxPosition
.y
,
836 // wpl.ptMaxPosition.x + Size.x, wpl.ptMaxPosition.y + Size.y);
841 case SW_SHOWNOACTIVATE
:
842 Wnd
->InternalPos
.flags
&= ~WPF_RESTORETOMAXIMIZED
;
846 case SW_SHOWDEFAULT
: /* FIXME: should have its own handler */
848 //ERR("MinMaximize Restore\n");
849 old_style
= IntSetStyle( Wnd
, 0, WS_MINIMIZE
| WS_MAXIMIZE
);
850 if (old_style
& WS_MINIMIZE
)
852 if (Wnd
->InternalPos
.flags
& WPF_RESTORETOMAXIMIZED
)
854 co_WinPosGetMinMaxInfo(Wnd
, &Size
, &wpl
.ptMaxPosition
, NULL
, NULL
);
855 IntSetStyle( Wnd
, WS_MAXIMIZE
, 0 );
856 SwpFlags
|= SWP_STATECHANGED
;
857 /*ERR("Restore to Max: %d,%d %dx%d\n",
858 wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, Size.x, Size.y);
860 RECTL_vSetRect(NewPos
, wpl
.ptMaxPosition
.x
, wpl
.ptMaxPosition
.y
,
861 // wpl.ptMaxPosition.x + Size.x, wpl.ptMaxPosition.y + Size.y);
867 *NewPos
= wpl
.rcNormalPosition
;
868 /*ERR("Restore Max: %d,%d %dx%d\n",
869 NewPos->left, NewPos->top, NewPos->right - NewPos->left, NewPos->bottom - NewPos->top);
871 NewPos
->right
-= NewPos
->left
;
872 NewPos
->bottom
-= NewPos
->top
;
878 if (!(old_style
& WS_MAXIMIZE
))
882 SwpFlags
|= SWP_STATECHANGED
;
883 Wnd
->InternalPos
.flags
&= ~WPF_RESTORETOMAXIMIZED
;
884 *NewPos
= wpl
.rcNormalPosition
;
885 /*ERR("Restore Min: %d,%d %dx%d\n",
886 NewPos->left, NewPos->top, NewPos->right - NewPos->left, NewPos->bottom - NewPos->top);
888 NewPos
->right
-= NewPos
->left
;
889 NewPos
->bottom
-= NewPos
->top
;
898 UserHasWindowEdge(DWORD Style
, DWORD ExStyle
)
900 if (Style
& WS_MINIMIZE
)
902 if (ExStyle
& WS_EX_DLGMODALFRAME
)
904 if (ExStyle
& WS_EX_STATICEDGE
)
906 if (Style
& WS_THICKFRAME
)
909 if (Style
== WS_DLGFRAME
|| Style
== WS_CAPTION
)
915 IntGetWindowBorderMeasures(PWND Wnd
, UINT
*cx
, UINT
*cy
)
917 if(HAS_DLGFRAME(Wnd
->style
, Wnd
->ExStyle
) && !(Wnd
->style
& WS_MINIMIZE
))
919 *cx
= UserGetSystemMetrics(SM_CXDLGFRAME
);
920 *cy
= UserGetSystemMetrics(SM_CYDLGFRAME
);
924 if(HAS_THICKFRAME(Wnd
->style
, Wnd
->ExStyle
)&& !(Wnd
->style
& WS_MINIMIZE
))
926 *cx
= UserGetSystemMetrics(SM_CXFRAME
);
927 *cy
= UserGetSystemMetrics(SM_CYFRAME
);
929 else if(HAS_THINFRAME(Wnd
->style
, Wnd
->ExStyle
))
931 *cx
= UserGetSystemMetrics(SM_CXBORDER
);
932 *cy
= UserGetSystemMetrics(SM_CYBORDER
);
942 UserGetWindowBorders(DWORD Style
, DWORD ExStyle
, SIZE
*Size
, BOOL WithClient
)
946 if (UserHasWindowEdge(Style
, ExStyle
))
948 else if (ExStyle
& WS_EX_STATICEDGE
)
950 if ((ExStyle
& WS_EX_CLIENTEDGE
) && WithClient
)
952 if (Style
& WS_CAPTION
|| ExStyle
& WS_EX_DLGMODALFRAME
)
954 Size
->cx
= Size
->cy
= Border
;
955 if ((Style
& WS_THICKFRAME
) && !(Style
& WS_MINIMIZE
))
957 Size
->cx
+= UserGetSystemMetrics(SM_CXFRAME
) - UserGetSystemMetrics(SM_CXDLGFRAME
);
958 Size
->cy
+= UserGetSystemMetrics(SM_CYFRAME
) - UserGetSystemMetrics(SM_CYDLGFRAME
);
960 Size
->cx
*= UserGetSystemMetrics(SM_CXBORDER
);
961 Size
->cy
*= UserGetSystemMetrics(SM_CYBORDER
);
965 UserAdjustWindowRectEx(LPRECT lpRect
,
974 lpRect
->top
-= UserGetSystemMetrics(SM_CYMENU
);
976 if ((dwStyle
& WS_CAPTION
) == WS_CAPTION
)
978 if (dwExStyle
& WS_EX_TOOLWINDOW
)
979 lpRect
->top
-= UserGetSystemMetrics(SM_CYSMCAPTION
);
981 lpRect
->top
-= UserGetSystemMetrics(SM_CYCAPTION
);
983 UserGetWindowBorders(dwStyle
, dwExStyle
, &BorderSize
, TRUE
);
993 co_WinPosGetMinMaxInfo(PWND Window
, POINT
* MaxSize
, POINT
* MaxPos
,
994 POINT
* MinTrack
, POINT
* MaxTrack
)
999 LONG style
= Window
->style
;
1001 LONG exstyle
= Window
->ExStyle
;
1004 ASSERT_REFS_CO(Window
);
1006 /* Compute default values */
1008 rc
= Window
->rcWindow
;
1009 MinMax
.ptReserved
.x
= rc
.left
;
1010 MinMax
.ptReserved
.y
= rc
.top
;
1012 if ((style
& WS_CAPTION
) == WS_CAPTION
)
1013 adjustedStyle
= style
& ~WS_BORDER
; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
1015 adjustedStyle
= style
;
1017 if(Window
->spwndParent
)
1018 IntGetClientRect(Window
->spwndParent
, &rc
);
1019 UserAdjustWindowRectEx(&rc
, adjustedStyle
, ((style
& WS_POPUP
) && Window
->IDMenu
), exstyle
);
1024 MinMax
.ptMaxSize
.x
= rc
.right
- rc
.left
;
1025 MinMax
.ptMaxSize
.y
= rc
.bottom
- rc
.top
;
1026 if (style
& (WS_DLGFRAME
| WS_BORDER
))
1028 MinMax
.ptMinTrackSize
.x
= UserGetSystemMetrics(SM_CXMINTRACK
);
1029 MinMax
.ptMinTrackSize
.y
= UserGetSystemMetrics(SM_CYMINTRACK
);
1033 MinMax
.ptMinTrackSize
.x
= 2 * xinc
;
1034 MinMax
.ptMinTrackSize
.y
= 2 * yinc
;
1036 MinMax
.ptMaxTrackSize
.x
= UserGetSystemMetrics(SM_CXMAXTRACK
);
1037 MinMax
.ptMaxTrackSize
.y
= UserGetSystemMetrics(SM_CYMAXTRACK
);
1038 MinMax
.ptMaxPosition
.x
= -xinc
;
1039 MinMax
.ptMaxPosition
.y
= -yinc
;
1041 if (!EMPTYPOINT(Window
->InternalPos
.MaxPos
)) MinMax
.ptMaxPosition
= Window
->InternalPos
.MaxPos
;
1043 co_IntSendMessage(Window
->head
.h
, WM_GETMINMAXINFO
, 0, (LPARAM
)&MinMax
);
1045 /* if the app didn't change the values, adapt them for the current monitor */
1046 if ((monitor
= UserGetPrimaryMonitor()))
1050 rc_work
= monitor
->rcMonitor
;
1052 if (style
& WS_MAXIMIZEBOX
)
1054 if ((style
& WS_CAPTION
) == WS_CAPTION
|| !(style
& (WS_CHILD
| WS_POPUP
)))
1055 rc_work
= monitor
->rcWork
;
1058 if (MinMax
.ptMaxSize
.x
== UserGetSystemMetrics(SM_CXSCREEN
) + 2 * xinc
&&
1059 MinMax
.ptMaxSize
.y
== UserGetSystemMetrics(SM_CYSCREEN
) + 2 * yinc
)
1061 MinMax
.ptMaxSize
.x
= (rc_work
.right
- rc_work
.left
) + 2 * xinc
;
1062 MinMax
.ptMaxSize
.y
= (rc_work
.bottom
- rc_work
.top
) + 2 * yinc
;
1064 if (MinMax
.ptMaxPosition
.x
== -xinc
&& MinMax
.ptMaxPosition
.y
== -yinc
)
1066 MinMax
.ptMaxPosition
.x
= rc_work
.left
- xinc
;
1067 MinMax
.ptMaxPosition
.y
= rc_work
.top
- yinc
;
1069 if (MinMax
.ptMaxSize
.x
>= (monitor
->rcMonitor
.right
- monitor
->rcMonitor
.left
) &&
1070 MinMax
.ptMaxSize
.y
>= (monitor
->rcMonitor
.bottom
- monitor
->rcMonitor
.top
) )
1071 Window
->state
|= WNDS_MAXIMIZESTOMONITOR
;
1073 Window
->state
&= ~WNDS_MAXIMIZESTOMONITOR
;
1077 MinMax
.ptMaxTrackSize
.x
= max(MinMax
.ptMaxTrackSize
.x
,
1078 MinMax
.ptMinTrackSize
.x
);
1079 MinMax
.ptMaxTrackSize
.y
= max(MinMax
.ptMaxTrackSize
.y
,
1080 MinMax
.ptMinTrackSize
.y
);
1083 *MaxSize
= MinMax
.ptMaxSize
;
1085 *MaxPos
= MinMax
.ptMaxPosition
;
1087 *MinTrack
= MinMax
.ptMinTrackSize
;
1089 *MaxTrack
= MinMax
.ptMaxTrackSize
;
1091 return 0; // FIXME: What does it return?
1096 FixClientRect(PRECTL ClientRect
, PRECTL WindowRect
)
1098 if (ClientRect
->left
< WindowRect
->left
)
1100 ClientRect
->left
= WindowRect
->left
;
1102 else if (WindowRect
->right
< ClientRect
->left
)
1104 ClientRect
->left
= WindowRect
->right
;
1106 if (ClientRect
->right
< WindowRect
->left
)
1108 ClientRect
->right
= WindowRect
->left
;
1110 else if (WindowRect
->right
< ClientRect
->right
)
1112 ClientRect
->right
= WindowRect
->right
;
1114 if (ClientRect
->top
< WindowRect
->top
)
1116 ClientRect
->top
= WindowRect
->top
;
1118 else if (WindowRect
->bottom
< ClientRect
->top
)
1120 ClientRect
->top
= WindowRect
->bottom
;
1122 if (ClientRect
->bottom
< WindowRect
->top
)
1124 ClientRect
->bottom
= WindowRect
->top
;
1126 else if (WindowRect
->bottom
< ClientRect
->bottom
)
1128 ClientRect
->bottom
= WindowRect
->bottom
;
1131 /***********************************************************************
1134 * Compute the valid rects from the old and new client rect and WVR_* flags.
1135 * Helper for WM_NCCALCSIZE handling.
1139 get_valid_rects( RECTL
*old_client
, RECTL
*new_client
, UINT flags
, RECTL
*valid
)
1143 if (flags
& WVR_REDRAW
)
1145 RECTL_vSetEmptyRect( &valid
[0] );
1146 RECTL_vSetEmptyRect( &valid
[1] );
1150 if (flags
& WVR_VALIDRECTS
)
1152 if (!RECTL_bIntersectRect( &valid
[0], &valid
[0], new_client
) ||
1153 !RECTL_bIntersectRect( &valid
[1], &valid
[1], old_client
))
1155 RECTL_vSetEmptyRect( &valid
[0] );
1156 RECTL_vSetEmptyRect( &valid
[1] );
1159 flags
= WVR_ALIGNLEFT
| WVR_ALIGNTOP
;
1163 valid
[0] = *new_client
;
1164 valid
[1] = *old_client
;
1167 /* make sure the rectangles have the same size */
1168 cx
= min( valid
[0].right
- valid
[0].left
, valid
[1].right
- valid
[1].left
);
1169 cy
= min( valid
[0].bottom
- valid
[0].top
, valid
[1].bottom
- valid
[1].top
);
1171 if (flags
& WVR_ALIGNBOTTOM
)
1173 valid
[0].top
= valid
[0].bottom
- cy
;
1174 valid
[1].top
= valid
[1].bottom
- cy
;
1178 valid
[0].bottom
= valid
[0].top
+ cy
;
1179 valid
[1].bottom
= valid
[1].top
+ cy
;
1181 if (flags
& WVR_ALIGNRIGHT
)
1183 valid
[0].left
= valid
[0].right
- cx
;
1184 valid
[1].left
= valid
[1].right
- cx
;
1188 valid
[0].right
= valid
[0].left
+ cx
;
1189 valid
[1].right
= valid
[1].left
+ cx
;
1195 co_WinPosDoNCCALCSize(PWND Window
, PWINDOWPOS WinPos
, RECTL
* WindowRect
, RECTL
* ClientRect
, RECTL
* validRects
)
1200 ASSERT_REFS_CO(Window
);
1202 /* Send WM_NCCALCSIZE message to get new client area */
1203 if ((WinPos
->flags
& (SWP_FRAMECHANGED
| SWP_NOSIZE
)) != SWP_NOSIZE
)
1205 NCCALCSIZE_PARAMS params
;
1206 WINDOWPOS winposCopy
;
1208 params
.rgrc
[0] = *WindowRect
; // new coordinates of a window that has been moved or resized
1209 params
.rgrc
[1] = Window
->rcWindow
; // window before it was moved or resized
1210 params
.rgrc
[2] = Window
->rcClient
; // client area before the window was moved or resized
1212 Parent
= Window
->spwndParent
;
1213 if (0 != (Window
->style
& WS_CHILD
) && Parent
)
1215 RECTL_vOffsetRect(&(params
.rgrc
[0]), - Parent
->rcClient
.left
,
1216 - Parent
->rcClient
.top
);
1217 RECTL_vOffsetRect(&(params
.rgrc
[1]), - Parent
->rcClient
.left
,
1218 - Parent
->rcClient
.top
);
1219 RECTL_vOffsetRect(&(params
.rgrc
[2]), - Parent
->rcClient
.left
,
1220 - Parent
->rcClient
.top
);
1223 params
.lppos
= &winposCopy
;
1224 winposCopy
= *WinPos
;
1226 wvrFlags
= co_IntSendMessage(Window
->head
.h
, WM_NCCALCSIZE
, TRUE
, (LPARAM
) ¶ms
);
1228 /* If the application send back garbage, ignore it */
1229 if (params
.rgrc
[0].left
<= params
.rgrc
[0].right
&&
1230 params
.rgrc
[0].top
<= params
.rgrc
[0].bottom
)
1232 *ClientRect
= params
.rgrc
[0]; // First rectangle contains the coordinates of the new client rectangle resulting from the move or resize
1233 if ((Window
->style
& WS_CHILD
) && Parent
)
1235 RECTL_vOffsetRect(ClientRect
, Parent
->rcClient
.left
,
1236 Parent
->rcClient
.top
);
1238 FixClientRect(ClientRect
, WindowRect
);
1241 if (ClientRect
->left
!= Window
->rcClient
.left
||
1242 ClientRect
->top
!= Window
->rcClient
.top
)
1244 WinPos
->flags
&= ~SWP_NOCLIENTMOVE
;
1247 if (ClientRect
->right
- ClientRect
->left
!=
1248 Window
->rcClient
.right
- Window
->rcClient
.left
)
1250 WinPos
->flags
&= ~SWP_NOCLIENTSIZE
;
1253 wvrFlags
&= ~WVR_HREDRAW
;
1255 if (ClientRect
->bottom
- ClientRect
->top
!=
1256 Window
->rcClient
.bottom
- Window
->rcClient
.top
)
1258 WinPos
->flags
&= ~SWP_NOCLIENTSIZE
;
1261 wvrFlags
&= ~WVR_VREDRAW
;
1263 validRects
[0] = params
.rgrc
[1]; // second rectangle contains the valid destination rectangle
1264 validRects
[1] = params
.rgrc
[2]; // third rectangle contains the valid source rectangle
1268 if (!(WinPos
->flags
& SWP_NOMOVE
) &&
1269 (ClientRect
->left
!= Window
->rcClient
.left
||
1270 ClientRect
->top
!= Window
->rcClient
.top
))
1272 WinPos
->flags
&= ~SWP_NOCLIENTMOVE
;
1276 if (WinPos
->flags
& (SWP_NOCOPYBITS
| SWP_NOREDRAW
| SWP_SHOWWINDOW
| SWP_HIDEWINDOW
))
1278 RECTL_vSetEmptyRect( &validRects
[0] );
1279 RECTL_vSetEmptyRect( &validRects
[1] );
1281 else get_valid_rects( &Window
->rcClient
, ClientRect
, wvrFlags
, validRects
);
1288 co_WinPosDoWinPosChanging(PWND Window
,
1293 ASSERT_REFS_CO(Window
);
1295 /* Send WM_WINDOWPOSCHANGING message */
1297 if (!(WinPos
->flags
& SWP_NOSENDCHANGING
))
1299 co_IntSendMessageNoWait(Window
->head
.h
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
) WinPos
);
1302 /* Calculate new position and size */
1304 *WindowRect
= Window
->rcWindow
;
1305 *ClientRect
= (Window
->style
& WS_MINIMIZE
) ? Window
->rcWindow
: Window
->rcClient
;
1307 if (!(WinPos
->flags
& SWP_NOSIZE
))
1309 if (Window
->style
& WS_MINIMIZE
)
1311 WindowRect
->right
= WindowRect
->left
+ UserGetSystemMetrics(SM_CXICON
);
1312 WindowRect
->bottom
= WindowRect
->top
+ UserGetSystemMetrics(SM_CYICON
);
1316 WindowRect
->right
= WindowRect
->left
+ WinPos
->cx
;
1317 WindowRect
->bottom
= WindowRect
->top
+ WinPos
->cy
;
1321 if (!(WinPos
->flags
& SWP_NOMOVE
))
1323 WindowRect
->left
= WinPos
->x
;
1324 WindowRect
->top
= WinPos
->y
;
1325 WindowRect
->right
+= WinPos
->x
- Window
->rcWindow
.left
;
1326 WindowRect
->bottom
+= WinPos
->y
- Window
->rcWindow
.top
;
1327 RECTL_vOffsetRect(ClientRect
,
1328 WinPos
->x
- Window
->rcWindow
.left
,
1329 WinPos
->y
- Window
->rcWindow
.top
);
1333 *WindowRect
= Window
->rcWindow
;
1334 *ClientRect
= Window
->rcClient
;
1336 if (!(WinPos
->flags
& SWP_NOSIZE
))
1338 WindowRect
->right
= WindowRect
->left
+ WinPos
->cx
;
1339 WindowRect
->bottom
= WindowRect
->top
+ WinPos
->cy
;
1342 if (!(WinPos
->flags
& SWP_NOMOVE
))
1348 //ERR("Not SWP_NOMOVE\n");
1349 Parent
= Window
->spwndParent
;
1350 if (((Window
->style
& WS_CHILD
) != 0) &&
1352 Parent
!= Window
->head
.rpdesk
->pDeskInfo
->spwnd
)
1354 //ERR("Not SWP_NOMOVE 1 Parent client offset X %d Y %d\n",X,Y);
1355 X
+= Parent
->rcClient
.left
;
1356 Y
+= Parent
->rcClient
.top
;
1357 //ERR("Not SWP_NOMOVE 2 Parent client offset X %d Y %d\n",X,Y);
1360 WindowRect
->left
= X
;
1361 WindowRect
->top
= Y
;
1362 WindowRect
->right
+= X
- Window
->rcWindow
.left
;
1363 WindowRect
->bottom
+= Y
- Window
->rcWindow
.top
;
1365 RECTL_vOffsetRect(ClientRect
, X
- Window
->rcWindow
.left
,
1366 Y
- Window
->rcWindow
.top
);
1369 WinPos
->flags
|= SWP_NOCLIENTMOVE
| SWP_NOCLIENTSIZE
;
1371 TRACE( "hwnd %p, after %p, swp %d,%d %dx%d flags %08x\n",
1372 WinPos
->hwnd
, WinPos
->hwndInsertAfter
, WinPos
->x
, WinPos
->y
,
1373 WinPos
->cx
, WinPos
->cy
, WinPos
->flags
);
1379 * Fix Z order taking into account owned popups -
1380 * basically we need to maintain them above the window that owns them
1382 * FIXME: hide/show owned popups when owner visibility changes.
1384 * ReactOS: See bug CORE-6129 and CORE-6554.
1388 // Pass all the win:test_children/popup_zorder tests except "move hwnd_F and its popups down" which is if'ed out.
1389 // Side effect, breaks more of the DeferWindowPos api tests, but wine breaks more!!!!
1392 WinPosDoOwnedPopups(PWND Window
, HWND hWndInsertAfter
)
1397 PWND DesktopWindow
, ChildObject
;
1400 TRACE("(%p) hInsertAfter = %p\n", Window
, hWndInsertAfter
);
1402 Owner
= Window
->spwndOwner
? Window
->spwndOwner
->head
.h
: NULL
;
1403 Style
= Window
->style
;
1405 if (Style
& WS_CHILD
)
1407 TRACE("Window is child\n");
1408 return hWndInsertAfter
;
1413 /* Make sure this popup stays above the owner */
1415 if (hWndInsertAfter
!= HWND_TOPMOST
)
1417 DesktopWindow
= UserGetDesktopWindow();
1418 List
= IntWinListChildren(DesktopWindow
);
1422 for (i
= 0; List
[i
]; i
++)
1424 BOOL topmost
= FALSE
;
1426 ChildObject
= ValidateHwndNoErr(List
[i
]);
1429 topmost
= (ChildObject
->ExStyle
& WS_EX_TOPMOST
) != 0;
1432 if (List
[i
] == Owner
)
1434 if (i
> 0) hWndInsertAfter
= List
[i
-1];
1435 else hWndInsertAfter
= topmost
? HWND_TOPMOST
: HWND_TOP
;
1439 if (hWndInsertAfter
== HWND_TOP
|| hWndInsertAfter
== HWND_NOTOPMOST
)
1441 if (!topmost
) break;
1443 else if (List
[i
] == hWndInsertAfter
) break;
1447 return hWndInsertAfter
;
1451 if (hWndInsertAfter
== HWND_BOTTOM
)
1453 ERR("Window is HWND_BOTTOM\n");
1454 if (List
) ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1460 DesktopWindow
= UserGetDesktopWindow();
1461 List
= IntWinListChildren(DesktopWindow
);
1468 if (hWndInsertAfter
== HWND_TOP
|| hWndInsertAfter
== HWND_NOTOPMOST
)
1470 if (hWndInsertAfter
== HWND_NOTOPMOST
|| !(Window
->ExStyle
& WS_EX_TOPMOST
))
1472 TRACE("skip all the topmost windows\n");
1473 /* skip all the topmost windows */
1475 (ChildObject
= ValidateHwndNoErr(List
[i
])) &&
1476 (ChildObject
->ExStyle
& WS_EX_TOPMOST
)) i
++;
1479 else if (hWndInsertAfter
!= HWND_TOPMOST
)
1481 /* skip windows that are already placed correctly */
1482 for (i
= 0; List
[i
]; i
++)
1484 if (List
[i
] == hWndInsertAfter
) break;
1485 if (List
[i
] == UserHMGetHandle(Window
))
1487 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1488 goto done
; /* nothing to do if window is moving backwards in z-order */
1493 for (; List
[i
]; i
++)
1496 USER_REFERENCE_ENTRY Ref
;
1498 if (List
[i
] == UserHMGetHandle(Window
))
1501 if (!(Wnd
= ValidateHwndNoErr(List
[i
])))
1504 Owner
= Wnd
->spwndOwner
? Wnd
->spwndOwner
->head
.h
: NULL
;
1506 if (Owner
!= UserHMGetHandle(Window
)) continue;
1508 UserRefObjectCo(Wnd
, &Ref
);
1509 TRACE( "moving %p owned by %p after %p\n", List
[i
], UserHMGetHandle(Window
), hWndInsertAfter
);
1510 co_WinPosSetWindowPos(Wnd
, hWndInsertAfter
, 0, 0, 0, 0,
1511 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOSENDCHANGING
| SWP_DEFERERASE
);
1513 UserDerefObjectCo(Wnd
);
1514 hWndInsertAfter
= List
[i
];
1516 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1519 return hWndInsertAfter
;
1523 /***********************************************************************
1524 * WinPosInternalMoveWindow
1526 * Update WindowRect and ClientRect of Window and all of its children
1527 * We keep both WindowRect and ClientRect in screen coordinates internally
1531 WinPosInternalMoveWindow(PWND Window
, INT MoveX
, INT MoveY
)
1535 ASSERT(Window
!= Window
->spwndChild
);
1537 Window
->rcWindow
.left
+= MoveX
;
1538 Window
->rcWindow
.right
+= MoveX
;
1539 Window
->rcWindow
.top
+= MoveY
;
1540 Window
->rcWindow
.bottom
+= MoveY
;
1542 Window
->rcClient
.left
+= MoveX
;
1543 Window
->rcClient
.right
+= MoveX
;
1544 Window
->rcClient
.top
+= MoveY
;
1545 Window
->rcClient
.bottom
+= MoveY
;
1547 for(Child
= Window
->spwndChild
; Child
; Child
= Child
->spwndNext
)
1549 WinPosInternalMoveWindow(Child
, MoveX
, MoveY
);
1554 * WinPosFixupSWPFlags
1556 * Fix redundant flags and values in the WINDOWPOS structure.
1560 WinPosFixupFlags(WINDOWPOS
*WinPos
, PWND Wnd
)
1565 /* Finally make sure that all coordinates are valid */
1566 if (WinPos
->x
< -32768) WinPos
->x
= -32768;
1567 else if (WinPos
->x
> 32767) WinPos
->x
= 32767;
1568 if (WinPos
->y
< -32768) WinPos
->y
= -32768;
1569 else if (WinPos
->y
> 32767) WinPos
->y
= 32767;
1571 WinPos
->cx
= max(WinPos
->cx
, 0);
1572 WinPos
->cy
= max(WinPos
->cy
, 0);
1574 Parent
= UserGetAncestor( Wnd
, GA_PARENT
);
1575 if (!IntIsWindowVisible( Parent
)) WinPos
->flags
|= SWP_NOREDRAW
;
1577 if (Wnd
->style
& WS_VISIBLE
) WinPos
->flags
&= ~SWP_SHOWWINDOW
;
1580 WinPos
->flags
&= ~SWP_HIDEWINDOW
;
1581 if (!(WinPos
->flags
& SWP_SHOWWINDOW
)) WinPos
->flags
|= SWP_NOREDRAW
;
1584 /* Check for right size */
1585 if (Wnd
->rcWindow
.right
- Wnd
->rcWindow
.left
== WinPos
->cx
&&
1586 Wnd
->rcWindow
.bottom
- Wnd
->rcWindow
.top
== WinPos
->cy
)
1588 WinPos
->flags
|= SWP_NOSIZE
;
1593 IntClientToScreen( Parent
, &pt
);
1594 //ERR("WPFU C2S wpx %d wpy %d ptx %d pty %d\n",WinPos->x,WinPos->y,pt.x,pt.y);
1595 /* Check for right position */
1596 if (Wnd
->rcWindow
.left
== pt
.x
&& Wnd
->rcWindow
.top
== pt
.y
)
1598 //ERR("In right pos\n");
1599 WinPos
->flags
|= SWP_NOMOVE
;
1602 if (WinPos
->hwnd
== UserGetForegroundWindow())
1604 WinPos
->flags
|= SWP_NOACTIVATE
; /* Already active */
1607 if ((Wnd
->style
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)
1609 /* Bring to the top when activating */
1610 if (!(WinPos
->flags
& (SWP_NOACTIVATE
|SWP_HIDEWINDOW
)) &&
1611 (WinPos
->flags
& SWP_NOZORDER
||
1612 (WinPos
->hwndInsertAfter
!= HWND_TOPMOST
&& WinPos
->hwndInsertAfter
!= HWND_NOTOPMOST
)))
1614 WinPos
->flags
&= ~SWP_NOZORDER
;
1615 WinPos
->hwndInsertAfter
= (0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
) ? HWND_TOPMOST
: HWND_TOP
);
1619 /* Check hwndInsertAfter */
1620 if (!(WinPos
->flags
& SWP_NOZORDER
))
1622 /* Fix sign extension */
1623 if (WinPos
->hwndInsertAfter
== (HWND
)0xffff)
1625 WinPos
->hwndInsertAfter
= HWND_TOPMOST
;
1627 else if (WinPos
->hwndInsertAfter
== (HWND
)0xfffe)
1629 WinPos
->hwndInsertAfter
= HWND_NOTOPMOST
;
1632 if (WinPos
->hwndInsertAfter
== HWND_TOP
)
1634 /* Keep it topmost when it's already topmost */
1635 if ((Wnd
->ExStyle
& WS_EX_TOPMOST
) != 0)
1636 WinPos
->hwndInsertAfter
= HWND_TOPMOST
;
1638 if (IntGetWindow(WinPos
->hwnd
, GW_HWNDFIRST
) == WinPos
->hwnd
)
1639 WinPos
->flags
|= SWP_NOZORDER
;
1641 else if (WinPos
->hwndInsertAfter
== HWND_BOTTOM
)
1643 if (!(Wnd
->ExStyle
& WS_EX_TOPMOST
) && IntGetWindow(WinPos
->hwnd
, GW_HWNDLAST
) == WinPos
->hwnd
)
1644 WinPos
->flags
|= SWP_NOZORDER
;
1646 else if (WinPos
->hwndInsertAfter
== HWND_TOPMOST
)
1648 if ((Wnd
->ExStyle
& WS_EX_TOPMOST
) && IntGetWindow(WinPos
->hwnd
, GW_HWNDFIRST
) == WinPos
->hwnd
)
1649 WinPos
->flags
|= SWP_NOZORDER
;
1651 else if (WinPos
->hwndInsertAfter
== HWND_NOTOPMOST
)
1653 if (!(Wnd
->ExStyle
& WS_EX_TOPMOST
))
1654 WinPos
->flags
|= SWP_NOZORDER
;
1656 else /* hwndInsertAfter must be a sibling of the window */
1660 InsAfterWnd
= ValidateHwndNoErr(WinPos
->hwndInsertAfter
);
1666 if (InsAfterWnd
->spwndParent
!= Wnd
->spwndParent
)
1668 /* Note from wine User32 Win test_SetWindowPos:
1669 "Returns TRUE also for windows that are not siblings"
1670 "Does not seem to do anything even without passing flags, still returns TRUE"
1671 "Same thing the other way around."
1672 ".. and with these windows."
1679 * We don't need to change the Z order of hwnd if it's already
1680 * inserted after hwndInsertAfter or when inserting hwnd after
1683 if ((WinPos
->hwnd
== WinPos
->hwndInsertAfter
) ||
1684 ((InsAfterWnd
->spwndNext
) && (WinPos
->hwnd
== InsAfterWnd
->spwndNext
->head
.h
)))
1686 WinPos
->flags
|= SWP_NOZORDER
;
1695 /* x and y are always screen relative */
1697 co_WinPosSetWindowPos(
1699 HWND WndInsertAfter
,
1708 RECTL NewWindowRect
;
1709 RECTL NewClientRect
;
1710 RECTL valid_rects
[2];
1712 HRGN VisBefore
= NULL
;
1713 HRGN VisBeforeJustClient
= NULL
;
1714 HRGN VisAfter
= NULL
;
1715 HRGN DirtyRgn
= NULL
;
1716 HRGN ExposedRgn
= NULL
;
1717 HRGN CopyRgn
= NULL
;
1719 RECTL OldWindowRect
, OldClientRect
;
1724 BOOL bPointerInWindow
;
1726 ASSERT_REFS_CO(Window
);
1728 /* FIXME: Get current active window from active queue. Why? since r2915. */
1730 bPointerInWindow
= IntPtInWindow(Window
, gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
);
1732 WinPos
.hwnd
= Window
->head
.h
;
1733 WinPos
.hwndInsertAfter
= WndInsertAfter
;
1738 WinPos
.flags
= flags
;
1740 if ( flags
& SWP_ASYNCWINDOWPOS
)
1743 PWINDOWPOS ppos
= ExAllocatePoolWithTag(PagedPool
, sizeof(WINDOWPOS
), USERTAG_SWP
);
1746 WinPos
.flags
&= ~SWP_ASYNCWINDOWPOS
; // Clear flag.
1748 /* Yes it's a pointer inside Win32k! */
1749 lRes
= co_IntSendMessageNoWait( WinPos
.hwnd
, WM_ASYNC_SETWINDOWPOS
, 0, (LPARAM
)ppos
);
1750 /* We handle this the same way as Event Hooks and Hooks. */
1753 ExFreePoolWithTag(ppos
, USERTAG_SWP
);
1761 co_WinPosDoWinPosChanging(Window
, &WinPos
, &NewWindowRect
, &NewClientRect
);
1763 /* Does the window still exist? */
1764 if (!IntIsWindow(WinPos
.hwnd
))
1766 TRACE("WinPosSetWindowPos: Invalid handle 0x%p!\n",WinPos
.hwnd
);
1767 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE
);
1771 /* Fix up the flags. */
1772 if (!WinPosFixupFlags(&WinPos
, Window
))
1778 Ancestor
= UserGetAncestor(Window
, GA_PARENT
);
1779 if ( (WinPos
.flags
& (SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) != SWP_NOZORDER
&&
1780 Ancestor
&& Ancestor
->head
.h
== IntGetDesktopWindow() )
1782 WinPos
.hwndInsertAfter
= WinPosDoOwnedPopups(Window
, WinPos
.hwndInsertAfter
);
1785 if (!(WinPos
.flags
& SWP_NOREDRAW
))
1787 /* Compute the visible region before the window position is changed */
1788 if (!(WinPos
.flags
& SWP_SHOWWINDOW
) &&
1789 (WinPos
.flags
& (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
|
1790 SWP_HIDEWINDOW
| SWP_FRAMECHANGED
)) !=
1791 (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
))
1793 VisBefore
= VIS_ComputeVisibleRegion(Window
, FALSE
, FALSE
,
1794 (Window
->style
& WS_CLIPSIBLINGS
) ? TRUE
: FALSE
);
1797 if ( VisBefore
!= NULL
&&
1798 (VisRgn
= (PROSRGNDATA
)RGNOBJAPI_Lock(VisBefore
, NULL
)) &&
1799 REGION_Complexity(VisRgn
) == NULLREGION
)
1801 RGNOBJAPI_Unlock(VisRgn
);
1802 GreDeleteObject(VisBefore
);
1807 RGNOBJAPI_Unlock(VisRgn
);
1808 NtGdiOffsetRgn(VisBefore
, -Window
->rcWindow
.left
, -Window
->rcWindow
.top
);
1811 /* Calculate the non client area for resizes, as this is used in the copy region */
1812 if (!(WinPos
.flags
& SWP_NOSIZE
))
1814 VisBeforeJustClient
= VIS_ComputeVisibleRegion(Window
, TRUE
, FALSE
,
1815 (Window
->style
& WS_CLIPSIBLINGS
) ? TRUE
: FALSE
);
1818 if ( VisBeforeJustClient
!= NULL
&&
1819 (VisRgn
= (PROSRGNDATA
)RGNOBJAPI_Lock(VisBeforeJustClient
, NULL
)) &&
1820 REGION_Complexity(VisRgn
) == NULLREGION
)
1822 RGNOBJAPI_Unlock(VisRgn
);
1823 GreDeleteObject(VisBeforeJustClient
);
1824 VisBeforeJustClient
= NULL
;
1828 RGNOBJAPI_Unlock(VisRgn
);
1829 NtGdiOffsetRgn(VisBeforeJustClient
, -Window
->rcWindow
.left
, -Window
->rcWindow
.top
);
1835 WvrFlags
= co_WinPosDoNCCALCSize(Window
, &WinPos
, &NewWindowRect
, &NewClientRect
, valid_rects
);
1837 // ERR("co_WinPosDoNCCALCSize returned 0x%x\n valid dest: %d %d %d %d\n valid src : %d %d %d %d\n", WvrFlags,
1838 // valid_rects[0].left,valid_rects[0].top,valid_rects[0].right,valid_rects[0].bottom,
1839 // valid_rects[1].left,valid_rects[1].top,valid_rects[1].right,valid_rects[1].bottom);
1841 /* Validate link windows. (also take into account shell window in hwndShellWindow) */
1842 if (!(WinPos
.flags
& SWP_NOZORDER
) && WinPos
.hwnd
!= UserGetShellWindow())
1844 IntLinkHwnd(Window
, WinPos
.hwndInsertAfter
);
1847 OldWindowRect
= Window
->rcWindow
;
1848 OldClientRect
= Window
->rcClient
;
1849 //ERR("SetWindowPos OldWindowRect: %d %d %d %d\n", OldWindowRect.left,OldWindowRect.top,OldWindowRect.right,OldWindowRect.bottom);
1850 //ERR("SetWindowPos OldClientRect: %d %d %d %d\n", OldClientRect.left,OldClientRect.top,OldClientRect.right,OldClientRect.bottom);
1852 if (NewClientRect
.left
!= OldClientRect
.left
||
1853 NewClientRect
.top
!= OldClientRect
.top
)
1855 WinPosInternalMoveWindow(Window
,
1856 NewClientRect
.left
- OldClientRect
.left
,
1857 NewClientRect
.top
- OldClientRect
.top
);
1860 Window
->rcWindow
= NewWindowRect
;
1861 Window
->rcClient
= NewClientRect
;
1863 //ERR("SetWindowPos NewWindowRect: %d %d %d %d\n", NewWindowRect.left,NewWindowRect.top,NewWindowRect.right,NewWindowRect.bottom);
1864 //ERR("SetWindowPos NewClientRect: %d %d %d %d\n", NewClientRect.left,NewClientRect.top,NewClientRect.right,NewClientRect.bottom);
1866 /* erase parent when hiding or resizing child */
1867 if (WinPos
.flags
& SWP_HIDEWINDOW
)
1869 /* Clear the update region */
1870 co_UserRedrawWindow( Window
,
1873 RDW_VALIDATE
| RDW_NOFRAME
| RDW_NOERASE
| RDW_NOINTERNALPAINT
| RDW_ALLCHILDREN
);
1875 if (Window
->spwndParent
== UserGetDesktopWindow())
1876 co_IntShellHookNotify(HSHELL_WINDOWDESTROYED
, (WPARAM
)Window
->head
.h
, 0);
1878 Window
->style
&= ~WS_VISIBLE
; //IntSetStyle( Window, 0, WS_VISIBLE );
1879 Window
->head
.pti
->cVisWindows
--;
1880 IntNotifyWinEvent(EVENT_OBJECT_HIDE
, Window
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
1882 else if (WinPos
.flags
& SWP_SHOWWINDOW
)
1884 if (Window
->spwndParent
== UserGetDesktopWindow())
1885 co_IntShellHookNotify(HSHELL_WINDOWCREATED
, (WPARAM
)Window
->head
.h
, 0);
1887 Window
->style
|= WS_VISIBLE
; //IntSetStyle( Window, WS_VISIBLE, 0 );
1888 Window
->head
.pti
->cVisWindows
++;
1889 IntNotifyWinEvent(EVENT_OBJECT_SHOW
, Window
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
1892 if (Window
->hrgnUpdate
!= NULL
&& Window
->hrgnUpdate
!= HRGN_WINDOW
)
1894 NtGdiOffsetRgn(Window
->hrgnUpdate
,
1895 NewWindowRect
.left
- OldWindowRect
.left
,
1896 NewWindowRect
.top
- OldWindowRect
.top
);
1899 DceResetActiveDCEs(Window
); // For WS_VISIBLE changes.
1901 if (!(WinPos
.flags
& SWP_NOREDRAW
))
1903 /* Determine the new visible region */
1904 VisAfter
= VIS_ComputeVisibleRegion(Window
, FALSE
, FALSE
,
1905 (Window
->style
& WS_CLIPSIBLINGS
) ? TRUE
: FALSE
);
1908 if ( VisAfter
!= NULL
&&
1909 (VisRgn
= (PROSRGNDATA
)RGNOBJAPI_Lock(VisAfter
, NULL
)) &&
1910 REGION_Complexity(VisRgn
) == NULLREGION
)
1912 RGNOBJAPI_Unlock(VisRgn
);
1913 GreDeleteObject(VisAfter
);
1918 RGNOBJAPI_Unlock(VisRgn
);
1919 NtGdiOffsetRgn(VisAfter
, -Window
->rcWindow
.left
, -Window
->rcWindow
.top
);
1923 * Determine which pixels can be copied from the old window position
1924 * to the new. Those pixels must be visible in both the old and new
1925 * position. Also, check the class style to see if the windows of this
1926 * class need to be completely repainted on (horizontal/vertical) size
1929 if ( VisBefore
!= NULL
&&
1931 !(WinPos
.flags
& SWP_NOCOPYBITS
) &&
1932 ((WinPos
.flags
& SWP_NOSIZE
) || !(WvrFlags
& WVR_REDRAW
)) &&
1933 !(Window
->ExStyle
& WS_EX_TRANSPARENT
) )
1937 * If this is (also) a window resize, the whole nonclient area
1938 * needs to be repainted. So we limit the copy to the client area,
1939 * 'cause there is no use in copying it (would possibly cause
1940 * "flashing" too). However, if the copy region is already empty,
1941 * we don't have to crop (can't take anything away from an empty
1945 CopyRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
1946 if (WinPos
.flags
& SWP_NOSIZE
)
1947 RgnType
= NtGdiCombineRgn(CopyRgn
, VisAfter
, VisBefore
, RGN_AND
);
1948 else if (VisBeforeJustClient
!= NULL
)
1950 RgnType
= NtGdiCombineRgn(CopyRgn
, VisAfter
, VisBeforeJustClient
, RGN_AND
);
1951 GreDeleteObject(VisBeforeJustClient
);
1954 /* No use in copying bits which are in the update region. */
1955 if (Window
->hrgnUpdate
!= NULL
)
1957 NtGdiOffsetRgn(CopyRgn
, NewWindowRect
.left
, NewWindowRect
.top
);
1958 NtGdiCombineRgn(CopyRgn
, CopyRgn
, Window
->hrgnUpdate
, RGN_DIFF
);
1959 NtGdiOffsetRgn(CopyRgn
, -NewWindowRect
.left
, -NewWindowRect
.top
);
1963 * Now, get the bounding box of the copy region. If it's empty
1964 * there's nothing to copy. Also, it's no use copying bits onto
1967 if ( (VisRgn
= (PROSRGNDATA
)RGNOBJAPI_Lock(CopyRgn
, NULL
)) &&
1968 REGION_GetRgnBox(VisRgn
, &CopyRect
) == NULLREGION
)
1970 /* Nothing to copy, clean up */
1971 RGNOBJAPI_Unlock(VisRgn
);
1972 GreDeleteObject(CopyRgn
);
1975 else if (OldWindowRect
.left
!= NewWindowRect
.left
||
1976 OldWindowRect
.top
!= NewWindowRect
.top
)
1980 RGNOBJAPI_Unlock(VisRgn
);
1984 * Small trick here: there is no function to bitblt a region. So
1985 * we set the region as the clipping region, take the bounding box
1986 * of the region and bitblt that. Since nothing outside the clipping
1987 * region is copied, this has the effect of bitblt'ing the region.
1989 * Since NtUserGetDCEx takes ownership of the clip region, we need
1990 * to create a copy of CopyRgn and pass that. We need CopyRgn later
1992 NtGdiOffsetRgn(CopyRgn
, NewWindowRect
.left
, NewWindowRect
.top
);
1993 Dc
= UserGetDCEx( Window
,
1995 DCX_WINDOW
|DCX_CACHE
|DCX_INTERSECTRGN
|DCX_CLIPSIBLINGS
|DCX_KEEPCLIPRGN
);
1997 CopyRect
.left
, CopyRect
.top
,
1998 CopyRect
.right
- CopyRect
.left
,
1999 CopyRect
.bottom
- CopyRect
.top
,
2001 CopyRect
.left
+ (OldWindowRect
.left
- NewWindowRect
.left
),
2002 CopyRect
.top
+ (OldWindowRect
.top
- NewWindowRect
.top
),
2007 UserReleaseDC(Window
, Dc
, FALSE
);
2008 IntValidateParent(Window
, CopyRgn
, FALSE
);
2009 NtGdiOffsetRgn(CopyRgn
, -NewWindowRect
.left
, -NewWindowRect
.top
);
2013 RGNOBJAPI_Unlock(VisRgn
);
2021 /* We need to redraw what wasn't visible before */
2022 if (VisAfter
!= NULL
)
2024 DirtyRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
2025 if (CopyRgn
!= NULL
)
2027 RgnType
= NtGdiCombineRgn(DirtyRgn
, VisAfter
, CopyRgn
, RGN_DIFF
);
2031 RgnType
= NtGdiCombineRgn(DirtyRgn
, VisAfter
, 0, RGN_COPY
);
2033 if (RgnType
!= ERROR
&& RgnType
!= NULLREGION
)
2036 NtGdiOffsetRgn(DirtyRgn, Window->rcWindow.left, Window->rcWindow.top);
2037 IntInvalidateWindows( Window,
2039 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
2041 GreDeleteObject(DirtyRgn);
2044 PWND Parent
= Window
->spwndParent
;
2046 NtGdiOffsetRgn( DirtyRgn
,
2047 Window
->rcWindow
.left
,
2048 Window
->rcWindow
.top
);
2049 if ( (Window
->style
& WS_CHILD
) &&
2051 !(Parent
->style
& WS_CLIPCHILDREN
))
2053 IntInvalidateWindows( Parent
,
2055 RDW_ERASE
| RDW_INVALIDATE
);
2056 co_IntPaintWindows(Parent
, RDW_ERASENOW
, FALSE
);
2060 IntInvalidateWindows( Window
,
2062 RDW_ERASE
| RDW_FRAME
| RDW_INVALIDATE
| RDW_ALLCHILDREN
);
2065 GreDeleteObject(DirtyRgn
);
2068 if (CopyRgn
!= NULL
)
2070 GreDeleteObject(CopyRgn
);
2073 /* Expose what was covered before but not covered anymore */
2074 if (VisBefore
!= NULL
)
2076 ExposedRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
2077 RgnType
= NtGdiCombineRgn(ExposedRgn
, VisBefore
, NULL
, RGN_COPY
);
2078 NtGdiOffsetRgn( ExposedRgn
,
2079 OldWindowRect
.left
- NewWindowRect
.left
,
2080 OldWindowRect
.top
- NewWindowRect
.top
);
2082 if (VisAfter
!= NULL
)
2083 RgnType
= NtGdiCombineRgn(ExposedRgn
, ExposedRgn
, VisAfter
, RGN_DIFF
);
2085 if (RgnType
!= ERROR
&& RgnType
!= NULLREGION
)
2087 co_VIS_WindowLayoutChanged(Window
, ExposedRgn
);
2089 GreDeleteObject(ExposedRgn
);
2090 GreDeleteObject(VisBefore
);
2093 if (VisAfter
!= NULL
)
2095 GreDeleteObject(VisAfter
);
2099 if (!(WinPos
.flags
& (SWP_NOACTIVATE
|SWP_HIDEWINDOW
)))
2101 if ((Window
->style
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
2103 co_IntSendMessageNoWait(WinPos
.hwnd
, WM_CHILDACTIVATE
, 0, 0);
2107 //ERR("SetWindowPos Set FG Window!\n");
2108 if (Window
->state
& WNDS_BEINGACTIVATED
) // Inside SAW?
2109 co_IntSetActiveWindow(Window
, FALSE
, TRUE
, FALSE
); // Fixes Api AttachThreadInput tests.
2111 co_IntSetForegroundWindow(Window
); // Fixes SW_HIDE issues. Wine win test_SetActiveWindow & test_SetForegroundWindow.
2115 /* And last, send the WM_WINDOWPOSCHANGED message */
2117 TRACE("\tstatus flags = %04x\n", WinPos
.flags
& SWP_AGG_STATUSFLAGS
);
2119 if ((WinPos
.flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOPOSCHANGE
)
2121 /* WM_WINDOWPOSCHANGED is sent even if SWP_NOSENDCHANGING is set
2122 and always contains final window position.
2124 WinPos
.x
= NewWindowRect
.left
;
2125 WinPos
.y
= NewWindowRect
.top
;
2126 WinPos
.cx
= NewWindowRect
.right
- NewWindowRect
.left
;
2127 WinPos
.cy
= NewWindowRect
.bottom
- NewWindowRect
.top
;
2128 co_IntSendMessageNoWait(WinPos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
) &WinPos
);
2131 if ( WinPos
.flags
& SWP_FRAMECHANGED
|| WinPos
.flags
& SWP_STATECHANGED
||
2132 !(WinPos
.flags
& SWP_NOCLIENTSIZE
) || !(WinPos
.flags
& SWP_NOCLIENTMOVE
) )
2134 PWND pWnd
= ValidateHwndNoErr(WinPos
.hwnd
);
2136 IntNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE
, pWnd
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
2139 if(bPointerInWindow
!= IntPtInWindow(Window
, gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
))
2141 /* Generate mouse move message */
2143 msg
.message
= WM_MOUSEMOVE
;
2144 msg
.wParam
= UserGetMouseButtonsState();
2145 msg
.lParam
= MAKELPARAM(gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
);
2146 msg
.pt
= gpsi
->ptCursor
;
2147 co_MsqInsertMouseMessage(&msg
, 0, 0, TRUE
);
2154 co_WinPosGetNonClientSize(PWND Window
, RECT
* WindowRect
, RECT
* ClientRect
)
2158 ASSERT_REFS_CO(Window
);
2160 *ClientRect
= *WindowRect
;
2161 Result
= co_IntSendMessageNoWait(Window
->head
.h
, WM_NCCALCSIZE
, FALSE
, (LPARAM
) ClientRect
);
2163 FixClientRect(ClientRect
, WindowRect
);
2169 co_WinPosSendSizeMove(PWND Wnd
)
2173 WPARAM wParam
= SIZE_RESTORED
;
2175 IntGetClientRect(Wnd
, &Rect
);
2176 lParam
= MAKELONG(Rect
.right
-Rect
.left
, Rect
.bottom
-Rect
.top
);
2178 Wnd
->state
&= ~WNDS_SENDSIZEMOVEMSGS
;
2180 if (Wnd
->style
& WS_MAXIMIZE
)
2182 wParam
= SIZE_MAXIMIZED
;
2184 else if (Wnd
->style
& WS_MINIMIZE
)
2186 wParam
= SIZE_MINIMIZED
;
2190 co_IntSendMessageNoWait(UserHMGetHandle(Wnd
), WM_SIZE
, wParam
, lParam
);
2192 if (Wnd
->spwndParent
== UserGetDesktopWindow()) // Wnd->spwndParent->fnid == FNID_DESKTOP )
2193 lParam
= MAKELONG(Wnd
->rcClient
.left
, Wnd
->rcClient
.top
);
2195 lParam
= MAKELONG(Wnd
->rcClient
.left
-Wnd
->spwndParent
->rcClient
.left
, Wnd
->rcClient
.top
-Wnd
->spwndParent
->rcClient
.top
);
2197 co_IntSendMessageNoWait(UserHMGetHandle(Wnd
), WM_MOVE
, 0, lParam
);
2199 IntEngWindowChanged(Wnd
, WOC_RGN_CLIENT
);
2203 co_WinPosShowWindow(PWND Wnd
, INT Cmd
)
2206 UINT Swp
= 0, EventMsg
= 0;
2207 RECTL NewPos
= {0, 0, 0, 0};
2213 //ERR("co_WinPosShowWindow START\n");
2214 BOOL ShowOwned
= FALSE
;
2215 ASSERT_REFS_CO(Wnd
);
2217 pti
= PsGetCurrentThreadWin32Thread();
2218 WasVisible
= (Wnd
->style
& WS_VISIBLE
) != 0;
2227 //ERR("co_WinPosShowWindow Exit Bad\n");
2230 Swp
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
2231 if (Wnd
!= pti
->MessageQueue
->spwndActive
)
2232 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2236 case SW_FORCEMINIMIZE
: /* FIXME: Does not work if thread is hung. */
2237 case SW_SHOWMINNOACTIVE
:
2238 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2240 case SW_SHOWMINIMIZED
:
2241 Swp
|= SWP_SHOWWINDOW
;
2245 Swp
|= SWP_NOACTIVATE
;
2246 if (!(style
& WS_MINIMIZE
))
2248 IntShowOwnedPopups(Wnd
, FALSE
);
2250 // Fix wine Win test_SetFocus todo #1 & #2,
2251 if (Cmd
== SW_SHOWMINIMIZED
)
2253 //ERR("co_WinPosShowWindow Set focus 1\n");
2254 if ((style
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
2255 co_UserSetFocus(Wnd
->spwndParent
);
2260 Swp
|= co_WinPosMinMaximize(Wnd
, Cmd
, &NewPos
) |
2263 EventMsg
= EVENT_SYSTEM_MINIMIZESTART
;
2269 Swp
|= SWP_FRAMECHANGED
;
2273 //ERR("co_WinPosShowWindow Exit Good\n");
2276 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
2281 case SW_SHOWMAXIMIZED
:
2283 Swp
|= SWP_SHOWWINDOW
;
2284 if (!(style
& WS_MAXIMIZE
))
2288 Swp
|= co_WinPosMinMaximize(Wnd
, SW_MAXIMIZE
, &NewPos
) |
2291 EventMsg
= EVENT_SYSTEM_MINIMIZEEND
;
2297 Swp
|= SWP_FRAMECHANGED
;
2301 //ERR("co_WinPosShowWindow Exit Good 1\n");
2304 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
2310 Swp
|= SWP_NOACTIVATE
| SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
2311 if (style
& WS_CHILD
&& !(Wnd
->ExStyle
& WS_EX_MDICHILD
)) Swp
|= SWP_NOZORDER
;
2314 if (WasVisible
) return(TRUE
); // Nothing to do!
2315 Swp
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
2316 /* Don't activate the topmost window. */
2317 if (style
& WS_CHILD
&& !(Wnd
->ExStyle
& WS_EX_MDICHILD
)) Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2320 case SW_SHOWNOACTIVATE
:
2321 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2324 case SW_SHOWDEFAULT
:
2326 if (!WasVisible
) Swp
|= SWP_SHOWWINDOW
;
2327 if (style
& (WS_MINIMIZE
| WS_MAXIMIZE
))
2329 Swp
|= co_WinPosMinMaximize(Wnd
, Cmd
, &NewPos
) |
2332 if (style
& WS_MINIMIZE
) EventMsg
= EVENT_SYSTEM_MINIMIZEEND
;
2338 Swp
|= SWP_FRAMECHANGED
;
2342 //ERR("co_WinPosShowWindow Exit Good 3\n");
2345 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
2347 if ( style
& WS_CHILD
&&
2348 !(Wnd
->ExStyle
& WS_EX_MDICHILD
) &&
2349 !(Swp
& SWP_STATECHANGED
))
2350 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2354 //ERR("co_WinPosShowWindow Exit Good 4\n");
2358 ShowFlag
= (Cmd
!= SW_HIDE
);
2360 if ((ShowFlag
!= WasVisible
|| Cmd
== SW_SHOWNA
) && Cmd
!= SW_SHOWMAXIMIZED
&& !(Swp
& SWP_STATECHANGED
))
2362 co_IntSendMessageNoWait(Wnd
->head
.h
, WM_SHOWWINDOW
, ShowFlag
, 0);
2363 if (!(Wnd
->state2
& WNDS2_WIN31COMPAT
))
2364 co_IntSendMessageNoWait(Wnd
->head
.h
, WM_SETVISIBLE
, ShowFlag
, 0);
2365 if (!VerifyWnd(Wnd
)) return WasVisible
;
2368 /* We can't activate a child window */
2369 if ((Wnd
->style
& WS_CHILD
) &&
2370 !(Wnd
->ExStyle
& WS_EX_MDICHILD
) &&
2373 //ERR("SWP Child No active and ZOrder\n");
2374 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2377 #if 0 // Explorer issues with common controls. Someone does not know how CS_SAVEBITS works.
2378 if ((Wnd
->style
& (WS_POPUP
|WS_CHILD
)) != WS_CHILD
&&
2379 Wnd
->pcls
->style
& CS_SAVEBITS
&&
2380 ((Cmd
== SW_SHOW
) || (Cmd
== SW_NORMAL
)))
2382 ERR("WinPosShowWindow Set active\n");
2383 UserSetActiveWindow(Wnd
);
2384 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
2388 if (IsChildVisible(Wnd
) || Swp
& SWP_STATECHANGED
)
2390 TRACE("Child is Vis %s or State changed %s. ShowFlag %s\n",
2391 (IsChildVisible(Wnd
) ? "TRUE" : "FALSE"), (Swp
& SWP_STATECHANGED
? "TRUE" : "FALSE"),
2392 (ShowFlag
? "TRUE" : "FALSE"));
2393 co_WinPosSetWindowPos( Wnd
,
2394 0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
) ? HWND_TOPMOST
: HWND_TOP
,
2397 NewPos
.right
, //NewPos.right - NewPos.left,
2398 NewPos
.bottom
, //NewPos.bottom - NewPos.top,
2403 TRACE("Parent Vis?\n");
2404 /* if parent is not visible simply toggle WS_VISIBLE and return */
2405 if (ShowFlag
) IntSetStyle( Wnd
, WS_VISIBLE
, 0 );
2406 else IntSetStyle( Wnd
, 0, WS_VISIBLE
);
2409 if ( EventMsg
) IntNotifyWinEvent(EventMsg
, Wnd
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
2411 if ( ShowOwned
) IntShowOwnedPopups(Wnd
, TRUE
);
2413 if ((Cmd
== SW_HIDE
) || (Cmd
== SW_MINIMIZE
))
2415 if ( Wnd
== pti
->MessageQueue
->spwndActive
&& pti
->MessageQueue
== IntGetFocusMessageQueue() )
2417 if ( Wnd
->spwndParent
== UserGetDesktopWindow())
2419 if(!ActivateOtherWindowMin(Wnd
))
2420 co_WinPosActivateOtherWindow(Wnd
);
2423 co_WinPosActivateOtherWindow(Wnd
);
2426 /* Revert focus to parent */
2427 if (Wnd
== pti
->MessageQueue
->spwndFocus
)
2429 Parent
= Wnd
->spwndParent
;
2430 if (Wnd
->spwndParent
== UserGetDesktopWindow()) Parent
= 0;
2431 co_UserSetFocus(Parent
);
2435 /* FIXME: Check for window destruction. */
2437 if ((Wnd
->state
& WNDS_SENDSIZEMOVEMSGS
) &&
2438 !(Wnd
->state2
& WNDS2_INDESTROY
))
2440 co_WinPosSendSizeMove(Wnd
);
2443 /* if previous state was minimized Windows sets focus to the window */
2444 if (style
& WS_MINIMIZE
)
2446 co_UserSetFocus(Wnd
);
2447 // Fix wine Win test_SetFocus todo #3,
2448 if (!(style
& WS_CHILD
)) co_IntSendMessageNoWait(UserHMGetHandle(Wnd
), WM_ACTIVATE
, WA_ACTIVE
, 0);
2450 //ERR("co_WinPosShowWindow EXIT\n");
2456 co_WinPosSearchChildren(
2466 if (!(ScopeWin
->style
& WS_VISIBLE
))
2471 if (!Ignore
&& (ScopeWin
->style
& WS_DISABLED
))
2476 if (!IntPtInWindow(ScopeWin
, Point
->x
, Point
->y
))
2481 UserReferenceObject(ScopeWin
);
2483 if ( RECTL_bPointInRect(&ScopeWin
->rcClient
, Point
->x
, Point
->y
) )
2485 List
= IntWinListChildren(ScopeWin
);
2488 for (phWnd
= List
; *phWnd
; ++phWnd
)
2490 if (!(pwndChild
= ValidateHwndNoErr(*phWnd
)))
2495 pwndChild
= co_WinPosSearchChildren(pwndChild
, Point
, HitTest
, Ignore
);
2497 if(pwndChild
!= NULL
)
2499 /* We found a window. Don't send any more WM_NCHITTEST messages */
2500 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2501 UserDereferenceObject(ScopeWin
);
2505 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2509 if (ScopeWin
->head
.pti
== PsGetCurrentThreadWin32Thread())
2511 *HitTest
= (USHORT
)co_IntSendMessage(ScopeWin
->head
.h
, WM_NCHITTEST
, 0,
2512 MAKELONG(Point
->x
, Point
->y
));
2513 if ((*HitTest
) == (USHORT
)HTTRANSPARENT
)
2515 UserDereferenceObject(ScopeWin
);
2520 *HitTest
= HTCLIENT
;
2526 co_WinPosWindowFromPoint(PWND ScopeWin
, POINT
*WinPoint
, USHORT
* HitTest
, BOOL Ignore
)
2529 POINT Point
= *WinPoint
;
2530 USER_REFERENCE_ENTRY Ref
;
2532 if( ScopeWin
== NULL
)
2534 ScopeWin
= UserGetDesktopWindow();
2535 if(ScopeWin
== NULL
)
2539 *HitTest
= HTNOWHERE
;
2541 ASSERT_REFS_CO(ScopeWin
);
2542 UserRefObjectCo(ScopeWin
, &Ref
);
2544 Window
= co_WinPosSearchChildren(ScopeWin
, &Point
, HitTest
, Ignore
);
2546 UserDerefObjectCo(ScopeWin
);
2548 ASSERT_REFS_CO(Window
);
2549 ASSERT_REFS_CO(ScopeWin
);
2555 IntRealChildWindowFromPoint(PWND Parent
, LONG x
, LONG y
)
2559 PWND pwndHit
= NULL
;
2564 if (Parent
!= UserGetDesktopWindow())
2566 Pt
.x
+= Parent
->rcClient
.left
;
2567 Pt
.y
+= Parent
->rcClient
.top
;
2570 if (!IntPtInWindow(Parent
, Pt
.x
, Pt
.y
)) return NULL
;
2572 if ((List
= IntWinListChildren(Parent
)))
2574 for (phWnd
= List
; *phWnd
; phWnd
++)
2577 if ((Child
= ValidateHwndNoErr(*phWnd
)))
2579 if ( Child
->style
& WS_VISIBLE
&& IntPtInWindow(Child
, Pt
.x
, Pt
.y
) )
2581 if ( Child
->pcls
->atomClassName
!= gpsi
->atomSysClass
[ICLS_BUTTON
] ||
2582 (Child
->style
& BS_TYPEMASK
) != BS_GROUPBOX
)
2584 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2591 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2593 return pwndHit
? pwndHit
: Parent
;
2597 IntChildWindowFromPointEx(PWND Parent
, LONG x
, LONG y
, UINT uiFlags
)
2601 PWND pwndHit
= NULL
;
2606 if (Parent
!= UserGetDesktopWindow())
2608 if (Parent
->ExStyle
& WS_EX_LAYOUTRTL
)
2609 Pt
.x
= Parent
->rcClient
.right
- Pt
.x
;
2611 Pt
.x
+= Parent
->rcClient
.left
;
2612 Pt
.y
+= Parent
->rcClient
.top
;
2615 if (!IntPtInWindow(Parent
, Pt
.x
, Pt
.y
)) return NULL
;
2617 if ((List
= IntWinListChildren(Parent
)))
2619 for (phWnd
= List
; *phWnd
; phWnd
++)
2622 if ((Child
= ValidateHwndNoErr(*phWnd
)))
2624 if (uiFlags
& (CWP_SKIPINVISIBLE
|CWP_SKIPDISABLED
))
2626 if (!(Child
->style
& WS_VISIBLE
) && (uiFlags
& CWP_SKIPINVISIBLE
)) continue;
2627 if ((Child
->style
& WS_DISABLED
) && (uiFlags
& CWP_SKIPDISABLED
)) continue;
2630 if (uiFlags
& CWP_SKIPTRANSPARENT
)
2632 if (Child
->ExStyle
& WS_EX_TRANSPARENT
) continue;
2635 if (IntPtInWindow(Child
, Pt
.x
, Pt
.y
))
2642 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2644 return pwndHit
? pwndHit
: Parent
;
2649 IntDeferWindowPos( HDWP hdwp
,
2660 HDWP retvalue
= hdwp
;
2662 TRACE("hdwp %p, hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
2663 hdwp
, hwnd
, hwndAfter
, x
, y
, cx
, cy
, flags
);
2665 if (flags
& ~(SWP_NOSIZE
| SWP_NOMOVE
|
2666 SWP_NOZORDER
| SWP_NOREDRAW
|
2667 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
2668 SWP_NOOWNERZORDER
|SWP_SHOWWINDOW
|
2669 SWP_HIDEWINDOW
| SWP_FRAMECHANGED
))
2671 EngSetLastError(ERROR_INVALID_PARAMETER
);
2675 if (!(pDWP
= (PSMWP
)UserGetObject(gHandleTable
, hdwp
, TYPE_SETWINDOWPOS
)))
2677 EngSetLastError(ERROR_INVALID_DWP_HANDLE
);
2681 for (i
= 0; i
< pDWP
->ccvr
; i
++)
2683 if (pDWP
->acvr
[i
].pos
.hwnd
== hwnd
)
2685 /* Merge with the other changes */
2686 if (!(flags
& SWP_NOZORDER
))
2688 pDWP
->acvr
[i
].pos
.hwndInsertAfter
= hwndAfter
;
2690 if (!(flags
& SWP_NOMOVE
))
2692 pDWP
->acvr
[i
].pos
.x
= x
;
2693 pDWP
->acvr
[i
].pos
.y
= y
;
2695 if (!(flags
& SWP_NOSIZE
))
2697 pDWP
->acvr
[i
].pos
.cx
= cx
;
2698 pDWP
->acvr
[i
].pos
.cy
= cy
;
2700 pDWP
->acvr
[i
].pos
.flags
&= flags
| ~(SWP_NOSIZE
| SWP_NOMOVE
|
2701 SWP_NOZORDER
| SWP_NOREDRAW
|
2702 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
2704 pDWP
->acvr
[i
].pos
.flags
|= flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
|
2709 if (pDWP
->ccvr
>= pDWP
->ccvrAlloc
)
2711 PCVR newpos
= ExAllocatePoolWithTag(PagedPool
, pDWP
->ccvrAlloc
* 2 * sizeof(CVR
), USERTAG_SWP
);
2717 RtlZeroMemory(newpos
, pDWP
->ccvrAlloc
* 2 * sizeof(CVR
));
2718 RtlCopyMemory(newpos
, pDWP
->acvr
, pDWP
->ccvrAlloc
* sizeof(CVR
));
2719 ExFreePoolWithTag(pDWP
->acvr
, USERTAG_SWP
);
2720 pDWP
->ccvrAlloc
*= 2;
2721 pDWP
->acvr
= newpos
;
2723 pDWP
->acvr
[pDWP
->ccvr
].pos
.hwnd
= hwnd
;
2724 pDWP
->acvr
[pDWP
->ccvr
].pos
.hwndInsertAfter
= hwndAfter
;
2725 pDWP
->acvr
[pDWP
->ccvr
].pos
.x
= x
;
2726 pDWP
->acvr
[pDWP
->ccvr
].pos
.y
= y
;
2727 pDWP
->acvr
[pDWP
->ccvr
].pos
.cx
= cx
;
2728 pDWP
->acvr
[pDWP
->ccvr
].pos
.cy
= cy
;
2729 pDWP
->acvr
[pDWP
->ccvr
].pos
.flags
= flags
;
2730 pDWP
->acvr
[pDWP
->ccvr
].hrgnClip
= NULL
;
2731 pDWP
->acvr
[pDWP
->ccvr
].hrgnInterMonitor
= NULL
;
2737 BOOL FASTCALL
IntEndDeferWindowPosEx( HDWP hdwp
, BOOL sAsync
)
2744 TRACE("%p\n", hdwp
);
2746 if (!(pDWP
= (PSMWP
)UserGetObject(gHandleTable
, hdwp
, TYPE_SETWINDOWPOS
)))
2748 EngSetLastError(ERROR_INVALID_DWP_HANDLE
);
2752 for (i
= 0, winpos
= pDWP
->acvr
; res
&& i
< pDWP
->ccvr
; i
++, winpos
++)
2755 USER_REFERENCE_ENTRY Ref
;
2757 TRACE("hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
2758 winpos
->pos
.hwnd
, winpos
->pos
.hwndInsertAfter
, winpos
->pos
.x
, winpos
->pos
.y
,
2759 winpos
->pos
.cx
, winpos
->pos
.cy
, winpos
->pos
.flags
);
2761 pwnd
= ValidateHwndNoErr(winpos
->pos
.hwnd
);
2765 UserRefObjectCo(pwnd
, &Ref
);
2770 PWINDOWPOS ppos
= ExAllocatePoolWithTag(PagedPool
, sizeof(WINDOWPOS
), USERTAG_SWP
);
2773 *ppos
= winpos
->pos
;
2774 /* Yes it's a pointer inside Win32k! */
2775 lRes
= co_IntSendMessageNoWait( winpos
->pos
.hwnd
, WM_ASYNC_SETWINDOWPOS
, 0, (LPARAM
)ppos
);
2776 /* We handle this the same way as Event Hooks and Hooks. */
2779 ExFreePoolWithTag(ppos
, USERTAG_SWP
);
2784 res
= co_WinPosSetWindowPos( pwnd
,
2785 winpos
->pos
.hwndInsertAfter
,
2792 // Hack to pass tests.... Must have some work to do so clear the error.
2793 if (res
&& (winpos
->pos
.flags
& (SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOZORDER
)) == SWP_NOZORDER
)
2794 EngSetLastError(ERROR_SUCCESS
);
2796 UserDerefObjectCo(pwnd
);
2798 ExFreePoolWithTag(pDWP
->acvr
, USERTAG_SWP
);
2799 UserDereferenceObject(pDWP
);
2800 UserDeleteObject(hdwp
, TYPE_SETWINDOWPOS
);
2808 NtUserChildWindowFromPointEx(HWND hwndParent
,
2814 TRACE("Enter NtUserChildWindowFromPointEx\n");
2815 UserEnterExclusive();
2816 if ((pwndParent
= UserGetWindowObject(hwndParent
)))
2818 pwndParent
= IntChildWindowFromPointEx(pwndParent
, x
, y
, uiFlags
);
2821 TRACE("Leave NtUserChildWindowFromPointEx\n");
2822 return pwndParent
? UserHMGetHandle(pwndParent
) : NULL
;
2829 NtUserEndDeferWindowPosEx(HDWP WinPosInfo
,
2833 TRACE("Enter NtUserEndDeferWindowPosEx\n");
2834 UserEnterExclusive();
2835 Ret
= IntEndDeferWindowPosEx(WinPosInfo
, (BOOL
)Unknown1
);
2836 TRACE("Leave NtUserEndDeferWindowPosEx, ret=%i\n", Ret
);
2845 NtUserDeferWindowPos(HDWP WinPosInfo
,
2847 HWND WndInsertAfter
,
2856 UINT Tmp
= ~(SWP_ASYNCWINDOWPOS
|SWP_DEFERERASE
|SWP_NOSENDCHANGING
|SWP_NOREPOSITION
|
2857 SWP_NOCOPYBITS
|SWP_HIDEWINDOW
|SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|
2858 SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_NOZORDER
|SWP_NOMOVE
|SWP_NOSIZE
);
2860 TRACE("Enter NtUserDeferWindowPos\n");
2861 UserEnterExclusive();
2865 EngSetLastError(ERROR_INVALID_FLAGS
);
2869 pWnd
= UserGetWindowObject(Wnd
);
2870 if ( !pWnd
|| // FIXME:
2871 pWnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
2872 pWnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
2877 if ( WndInsertAfter
&&
2878 WndInsertAfter
!= HWND_BOTTOM
&&
2879 WndInsertAfter
!= HWND_TOPMOST
&&
2880 WndInsertAfter
!= HWND_NOTOPMOST
)
2882 pWndIA
= UserGetWindowObject(WndInsertAfter
);
2884 pWndIA
== UserGetDesktopWindow() ||
2885 pWndIA
== UserGetMessageWindow() )
2891 Ret
= IntDeferWindowPos(WinPosInfo
, Wnd
, WndInsertAfter
, x
, y
, cx
, cy
, Flags
);
2894 TRACE("Leave NtUserDeferWindowPos, ret=%p\n", Ret
);
2903 NtUserGetInternalWindowPos( HWND hWnd
,
2910 WINDOWPLACEMENT wndpl
;
2914 if (!(Window
= UserGetWindowObject(hWnd
)))
2924 ProbeForWrite(rectWnd
,
2930 ProbeForWrite(ptIcon
,
2936 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2938 SetLastNtError(_SEH2_GetExceptionCode());
2943 wndpl
.length
= sizeof(WINDOWPLACEMENT
);
2945 if (IntGetWindowPlacement(Window
, &wndpl
) && !Hit
)
2951 RtlCopyMemory(rectWnd
, &wndpl
.rcNormalPosition
, sizeof(RECT
));
2955 RtlCopyMemory(ptIcon
, &wndpl
.ptMinPosition
, sizeof(POINT
));
2959 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2961 SetLastNtError(_SEH2_GetExceptionCode());
2966 if (!Hit
) Ret
= wndpl
.showCmd
;
2977 NtUserGetWindowPlacement(HWND hWnd
,
2978 WINDOWPLACEMENT
*lpwndpl
)
2981 WINDOWPLACEMENT Safepl
;
2983 DECLARE_RETURN(BOOL
);
2985 TRACE("Enter NtUserGetWindowPlacement\n");
2988 if (!(Wnd
= UserGetWindowObject(hWnd
)))
2993 Status
= MmCopyFromCaller(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
2994 if(!NT_SUCCESS(Status
))
2996 SetLastNtError(Status
);
2999 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
3004 IntGetWindowPlacement(Wnd
, &Safepl
);
3006 Status
= MmCopyToCaller(lpwndpl
, &Safepl
, sizeof(WINDOWPLACEMENT
));
3007 if(!NT_SUCCESS(Status
))
3009 SetLastNtError(Status
);
3016 TRACE("Leave NtUserGetWindowPlacement, ret=%i\n",_ret_
);
3025 UINT cmd
, // Wine SW_ commands
3030 TRACE("Enter NtUserMinMaximize\n");
3031 UserEnterExclusive();
3033 pWnd
= UserGetWindowObject(hWnd
);
3034 if ( !pWnd
|| // FIXME:
3035 pWnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3036 pWnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3041 if ( cmd
> SW_MAX
|| pWnd
->state2
& WNDS2_INDESTROY
)
3043 EngSetLastError(ERROR_INVALID_PARAMETER
);
3047 cmd
|= Hide
? SW_HIDE
: 0;
3049 co_WinPosShowWindow(pWnd
, cmd
);
3052 TRACE("Leave NtUserMinMaximize\n");
3054 return 0; // Always NULL?
3069 return NtUserSetWindowPos(hWnd
, 0, X
, Y
, nWidth
, nHeight
,
3070 (bRepaint
? SWP_NOZORDER
| SWP_NOACTIVATE
:
3071 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
));
3078 NtUserRealChildWindowFromPoint(HWND Parent
,
3083 TRACE("Enter NtUserRealChildWindowFromPoint\n");
3085 if ((pwndParent
= UserGetWindowObject(Parent
)))
3087 pwndParent
= IntRealChildWindowFromPoint(pwndParent
, x
, y
);
3090 TRACE("Leave NtUserRealChildWindowFromPoint\n");
3091 return pwndParent
? UserHMGetHandle(pwndParent
) : NULL
;
3100 HWND hWndInsertAfter
,
3107 DECLARE_RETURN(BOOL
);
3108 PWND Window
, pWndIA
;
3110 USER_REFERENCE_ENTRY Ref
;
3112 TRACE("Enter NtUserSetWindowPos\n");
3113 UserEnterExclusive();
3115 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
3116 Window
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
3117 Window
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
3119 ERR("NtUserSetWindowPos bad window handle!\n");
3123 if ( hWndInsertAfter
&&
3124 hWndInsertAfter
!= HWND_BOTTOM
&&
3125 hWndInsertAfter
!= HWND_TOPMOST
&&
3126 hWndInsertAfter
!= HWND_NOTOPMOST
)
3128 if (!(pWndIA
= UserGetWindowObject(hWndInsertAfter
)) ||
3129 pWndIA
== UserGetDesktopWindow() ||
3130 pWndIA
== UserGetMessageWindow() )
3132 ERR("NtUserSetWindowPos bad insert window handle!\n");
3137 /* First make sure that coordinates are valid for WM_WINDOWPOSCHANGING */
3138 if (!(uFlags
& SWP_NOMOVE
))
3140 if (X
< -32768) X
= -32768;
3141 else if (X
> 32767) X
= 32767;
3142 if (Y
< -32768) Y
= -32768;
3143 else if (Y
> 32767) Y
= 32767;
3145 if (!(uFlags
& SWP_NOSIZE
))
3148 else if (cx
> 32767) cx
= 32767;
3150 else if (cy
> 32767) cy
= 32767;
3153 UserRefObjectCo(Window
, &Ref
);
3154 ret
= co_WinPosSetWindowPos(Window
, hWndInsertAfter
, X
, Y
, cx
, cy
, uFlags
);
3155 UserDerefObjectCo(Window
);
3160 TRACE("Leave NtUserSetWindowPos, ret=%i\n",_ret_
);
3176 INT flags
= (SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
);