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 /* FUNCTIONS *****************************************************************/
29 IntGetClientOrigin(PWND Window OPTIONAL
, LPPOINT Point
)
31 Window
= Window
? Window
: UserGetWindowObject(IntGetDesktopWindow());
34 Point
->x
= Point
->y
= 0;
37 Point
->x
= Window
->rcClient
.left
;
38 Point
->y
= Window
->rcClient
.top
;
44 /*******************************************************************
47 * Check if we can activate the specified window.
50 BOOL FASTCALL
can_activate_window( PWND Wnd OPTIONAL
)
54 if (!Wnd
) return FALSE
;
57 if (!(style
& WS_VISIBLE
) &&
58 Wnd
->head
.pti
->pEThread
->ThreadsProcess
!= CsrProcess
) return FALSE
;
59 if ((style
& WS_MINIMIZE
) &&
60 Wnd
->head
.pti
->pEThread
->ThreadsProcess
!= CsrProcess
) return FALSE
;
61 if ((style
& (WS_POPUP
|WS_CHILD
)) == WS_CHILD
) return FALSE
;
63 /* FIXME: This window could be disable because the child that closed
65 //return !(style & WS_DISABLED);
69 /*******************************************************************
70 * WinPosActivateOtherWindow
72 * Activates window other than pWnd.
75 co_WinPosActivateOtherWindow(PWND Wnd
)
79 USER_REFERENCE_ENTRY Ref
;
83 if (IntIsDesktopWindow(Wnd
))
85 IntSetFocusMessageQueue(NULL
);
89 /* If this is popup window, try to activate the owner first. */
90 if ((Wnd
->style
& WS_POPUP
) && (WndTo
= Wnd
->spwndOwner
))
92 WndTo
= UserGetAncestor( WndTo
, GA_ROOT
);
93 if (can_activate_window(WndTo
)) goto done
;
96 /* Pick a next top-level window. */
97 /* FIXME: Search for non-tooltip windows first. */
101 if (!(WndTo
= WndTo
->spwndNext
)) break;
102 if (can_activate_window( WndTo
)) break;
107 if (WndTo
) UserRefObjectCo(WndTo
, &Ref
);
109 Fg
= UserGetForegroundWindow();
110 if ((!Fg
|| Wnd
->head
.h
== Fg
) && WndTo
)//fixme: ok if WndTo is NULL??
112 /* fixme: wine can pass WndTo=NULL to co_IntSetForegroundWindow. hmm */
113 if (co_IntSetForegroundWindow(WndTo
))
115 UserDerefObjectCo(WndTo
);
120 if (!co_IntSetActiveWindow(WndTo
)) /* ok for WndTo to be NULL here */
121 co_IntSetActiveWindow(0);
123 if (WndTo
) UserDerefObjectCo(WndTo
);
129 co_WinPosArrangeIconicWindows(PWND parent
)
132 INT i
, x
, y
, xspacing
, yspacing
;
133 HWND
*List
= IntWinListChildren(parent
);
135 ASSERT_REFS_CO(parent
);
137 /* Check if we found any children */
143 IntGetClientRect( parent
, &rectParent
);
145 y
= rectParent
.bottom
;
147 xspacing
= UserGetSystemMetrics(SM_CXICONSPACING
);
148 yspacing
= UserGetSystemMetrics(SM_CYICONSPACING
);
150 TRACE("X:%d Y:%d XS:%d YS:%d\n",x
,y
,xspacing
,yspacing
);
152 for( i
= 0; List
[i
]; i
++)
156 if (!(Child
= UserGetWindowObject(List
[i
])))
159 if((Child
->style
& WS_MINIMIZE
) != 0 )
161 USER_REFERENCE_ENTRY Ref
;
162 UserRefObjectCo(Child
, &Ref
);
164 co_WinPosSetWindowPos(Child
, 0, x
+ (xspacing
- UserGetSystemMetrics(SM_CXICON
)) / 2,
165 y
- yspacing
- UserGetSystemMetrics(SM_CYICON
) / 2
166 , 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
168 UserDerefObjectCo(Child
);
170 if (x
<= rectParent
.right
- xspacing
)
185 WinPosFindIconPos(PWND Window
, POINT
*Pos
)
187 ERR("WinPosFindIconPos FIXME!\n");
191 WinPosInitInternalPos(PWND Wnd
, POINT
*pt
, RECTL
*RestoreRect
)
196 if (!Wnd
->InternalPosInitialized
)
200 Parent
= Wnd
->spwndParent
;
203 if(IntIsDesktopWindow(Parent
))
204 UserSystemParametersInfo(SPI_GETWORKAREA
, 0, &WorkArea
, 0);
206 WorkArea
= Parent
->rcClient
;
209 UserSystemParametersInfo(SPI_GETWORKAREA
, 0, &WorkArea
, 0);
211 Wnd
->InternalPos
.NormalRect
= Wnd
->rcWindow
;
212 IntGetWindowBorderMeasures(Wnd
, &XInc
, &YInc
);
213 Wnd
->InternalPos
.MaxPos
.x
= WorkArea
.left
- XInc
;
214 Wnd
->InternalPos
.MaxPos
.y
= WorkArea
.top
- YInc
;
215 Wnd
->InternalPos
.IconPos
.x
= WorkArea
.left
;
216 Wnd
->InternalPos
.IconPos
.y
= WorkArea
.bottom
- UserGetSystemMetrics(SM_CYMINIMIZED
);
218 Wnd
->InternalPosInitialized
= TRUE
;
220 if (Wnd
->style
& WS_MINIMIZE
)
222 Wnd
->InternalPos
.IconPos
= *pt
;
224 else if (Wnd
->style
& WS_MAXIMIZE
)
226 Wnd
->InternalPos
.MaxPos
= *pt
;
228 else if (RestoreRect
!= NULL
)
230 Wnd
->InternalPos
.NormalRect
= *RestoreRect
;
235 co_WinPosMinMaximize(PWND Wnd
, UINT ShowFlag
, RECT
* NewPos
)
242 Size
.x
= Wnd
->rcWindow
.left
;
243 Size
.y
= Wnd
->rcWindow
.top
;
244 WinPosInitInternalPos(Wnd
, &Size
, &Wnd
->rcWindow
);
246 if (co_HOOK_CallHooks( WH_CBT
, HCBT_MINMAX
, (WPARAM
)Wnd
->head
.h
, ShowFlag
))
248 ERR("WinPosMinMaximize WH_CBT Call Hook return!\n");
249 return SWP_NOSIZE
| SWP_NOMOVE
;
251 if (Wnd
->style
& WS_MINIMIZE
)
253 if (!co_IntSendMessageNoWait(Wnd
->head
.h
, WM_QUERYOPEN
, 0, 0))
255 return(SWP_NOSIZE
| SWP_NOMOVE
);
257 SwpFlags
|= SWP_NOCOPYBITS
;
263 if (Wnd
->style
& WS_MAXIMIZE
)
265 Wnd
->state2
|= WNDS2_MAXIMIZEBUTTONDOWN
;
266 Wnd
->style
&= ~WS_MAXIMIZE
;
270 Wnd
->state2
&= ~WNDS2_MAXIMIZEBUTTONDOWN
;
272 co_UserRedrawWindow(Wnd
, NULL
, 0, RDW_VALIDATE
| RDW_NOERASE
|
273 RDW_NOINTERNALPAINT
);
274 Wnd
->style
|= WS_MINIMIZE
;
275 WinPosFindIconPos(Wnd
, &Wnd
->InternalPos
.IconPos
);
276 RECTL_vSetRect(NewPos
, Wnd
->InternalPos
.IconPos
.x
, Wnd
->InternalPos
.IconPos
.y
,
277 UserGetSystemMetrics(SM_CXMINIMIZED
),
278 UserGetSystemMetrics(SM_CYMINIMIZED
));
279 SwpFlags
|= SWP_NOCOPYBITS
;
285 co_WinPosGetMinMaxInfo(Wnd
, &Size
, &Wnd
->InternalPos
.MaxPos
,
287 TRACE("Maximize: %d,%d %dx%d\n",
288 Wnd
->InternalPos
.MaxPos
.x
, Wnd
->InternalPos
.MaxPos
.y
, Size
.x
, Size
.y
);
289 if (Wnd
->style
& WS_MINIMIZE
)
291 Wnd
->style
&= ~WS_MINIMIZE
;
293 Wnd
->style
|= WS_MAXIMIZE
;
294 RECTL_vSetRect(NewPos
, Wnd
->InternalPos
.MaxPos
.x
, Wnd
->InternalPos
.MaxPos
.y
,
301 if (Wnd
->style
& WS_MINIMIZE
)
303 Wnd
->style
&= ~WS_MINIMIZE
;
304 if (Wnd
->state2
& WNDS2_MAXIMIZEBUTTONDOWN
)
306 co_WinPosGetMinMaxInfo(Wnd
, &Size
,
307 &Wnd
->InternalPos
.MaxPos
, NULL
, NULL
);
308 Wnd
->style
|= WS_MAXIMIZE
;
309 RECTL_vSetRect(NewPos
, Wnd
->InternalPos
.MaxPos
.x
,
310 Wnd
->InternalPos
.MaxPos
.y
, Size
.x
, Size
.y
);
315 *NewPos
= Wnd
->InternalPos
.NormalRect
;
316 NewPos
->right
-= NewPos
->left
;
317 NewPos
->bottom
-= NewPos
->top
;
323 if (!(Wnd
->style
& WS_MAXIMIZE
))
327 Wnd
->style
&= ~WS_MAXIMIZE
;
328 *NewPos
= Wnd
->InternalPos
.NormalRect
;
329 NewPos
->right
-= NewPos
->left
;
330 NewPos
->bottom
-= NewPos
->top
;
339 UserHasWindowEdge(DWORD Style
, DWORD ExStyle
)
341 if (Style
& WS_MINIMIZE
)
343 if (ExStyle
& WS_EX_DLGMODALFRAME
)
345 if (ExStyle
& WS_EX_STATICEDGE
)
347 if (Style
& WS_THICKFRAME
)
350 if (Style
== WS_DLGFRAME
|| Style
== WS_CAPTION
)
356 UserGetWindowBorders(DWORD Style
, DWORD ExStyle
, SIZE
*Size
, BOOL WithClient
)
360 if (UserHasWindowEdge(Style
, ExStyle
))
362 else if (ExStyle
& WS_EX_STATICEDGE
)
364 if ((ExStyle
& WS_EX_CLIENTEDGE
) && WithClient
)
366 if (Style
& WS_CAPTION
|| ExStyle
& WS_EX_DLGMODALFRAME
)
368 Size
->cx
= Size
->cy
= Border
;
369 if ((Style
& WS_THICKFRAME
) && !(Style
& WS_MINIMIZE
))
371 Size
->cx
+= UserGetSystemMetrics(SM_CXFRAME
) - UserGetSystemMetrics(SM_CXDLGFRAME
);
372 Size
->cy
+= UserGetSystemMetrics(SM_CYFRAME
) - UserGetSystemMetrics(SM_CYDLGFRAME
);
374 Size
->cx
*= UserGetSystemMetrics(SM_CXBORDER
);
375 Size
->cy
*= UserGetSystemMetrics(SM_CYBORDER
);
379 UserAdjustWindowRectEx(LPRECT lpRect
,
388 lpRect
->top
-= UserGetSystemMetrics(SM_CYMENU
);
390 if ((dwStyle
& WS_CAPTION
) == WS_CAPTION
)
392 if (dwExStyle
& WS_EX_TOOLWINDOW
)
393 lpRect
->top
-= UserGetSystemMetrics(SM_CYSMCAPTION
);
395 lpRect
->top
-= UserGetSystemMetrics(SM_CYCAPTION
);
397 UserGetWindowBorders(dwStyle
, dwExStyle
, &BorderSize
, TRUE
);
407 co_WinPosGetMinMaxInfo(PWND Window
, POINT
* MaxSize
, POINT
* MaxPos
,
408 POINT
* MinTrack
, POINT
* MaxTrack
)
413 LONG style
= Window
->style
;
415 LONG exstyle
= Window
->ExStyle
;
418 ASSERT_REFS_CO(Window
);
420 /* Compute default values */
422 rc
= Window
->rcWindow
;
423 MinMax
.ptReserved
.x
= rc
.left
;
424 MinMax
.ptReserved
.y
= rc
.top
;
426 if ((style
& WS_CAPTION
) == WS_CAPTION
)
427 adjustedStyle
= style
& ~WS_BORDER
; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
429 adjustedStyle
= style
;
431 if(Window
->spwndParent
)
432 IntGetClientRect(Window
->spwndParent
, &rc
);
433 UserAdjustWindowRectEx(&rc
, adjustedStyle
, ((style
& WS_POPUP
) && Window
->IDMenu
), exstyle
);
438 MinMax
.ptMaxSize
.x
= rc
.right
- rc
.left
;
439 MinMax
.ptMaxSize
.y
= rc
.bottom
- rc
.top
;
440 if (style
& (WS_DLGFRAME
| WS_BORDER
))
442 MinMax
.ptMinTrackSize
.x
= UserGetSystemMetrics(SM_CXMINTRACK
);
443 MinMax
.ptMinTrackSize
.y
= UserGetSystemMetrics(SM_CYMINTRACK
);
447 MinMax
.ptMinTrackSize
.x
= 2 * xinc
;
448 MinMax
.ptMinTrackSize
.y
= 2 * yinc
;
450 MinMax
.ptMaxTrackSize
.x
= UserGetSystemMetrics(SM_CXMAXTRACK
);
451 MinMax
.ptMaxTrackSize
.y
= UserGetSystemMetrics(SM_CYMAXTRACK
);
452 MinMax
.ptMaxPosition
.x
= -xinc
;
453 MinMax
.ptMaxPosition
.y
= -yinc
;
455 //if (!EMPTYPOINT(win->max_pos)) MinMax.ptMaxPosition = win->max_pos;
457 co_IntSendMessage(Window
->head
.h
, WM_GETMINMAXINFO
, 0, (LPARAM
)&MinMax
);
459 /* if the app didn't change the values, adapt them for the current monitor */
460 if ((monitor
= IntGetPrimaryMonitor()))
464 rc_work
= monitor
->rcMonitor
;
466 if (style
& WS_MAXIMIZEBOX
)
468 if ((style
& WS_CAPTION
) == WS_CAPTION
|| !(style
& (WS_CHILD
| WS_POPUP
)))
469 rc_work
= monitor
->rcWork
;
472 if (MinMax
.ptMaxSize
.x
== UserGetSystemMetrics(SM_CXSCREEN
) + 2 * xinc
&&
473 MinMax
.ptMaxSize
.y
== UserGetSystemMetrics(SM_CYSCREEN
) + 2 * yinc
)
475 MinMax
.ptMaxSize
.x
= (rc_work
.right
- rc_work
.left
) + 2 * xinc
;
476 MinMax
.ptMaxSize
.y
= (rc_work
.bottom
- rc_work
.top
) + 2 * yinc
;
478 if (MinMax
.ptMaxPosition
.x
== -xinc
&& MinMax
.ptMaxPosition
.y
== -yinc
)
480 MinMax
.ptMaxPosition
.x
= rc_work
.left
- xinc
;
481 MinMax
.ptMaxPosition
.y
= rc_work
.top
- yinc
;
486 MinMax
.ptMaxTrackSize
.x
= max(MinMax
.ptMaxTrackSize
.x
,
487 MinMax
.ptMinTrackSize
.x
);
488 MinMax
.ptMaxTrackSize
.y
= max(MinMax
.ptMaxTrackSize
.y
,
489 MinMax
.ptMinTrackSize
.y
);
492 *MaxSize
= MinMax
.ptMaxSize
;
494 *MaxPos
= MinMax
.ptMaxPosition
;
496 *MinTrack
= MinMax
.ptMinTrackSize
;
498 *MaxTrack
= MinMax
.ptMaxTrackSize
;
500 return 0; //FIXME: what does it return?
505 FixClientRect(PRECTL ClientRect
, PRECTL WindowRect
)
507 if (ClientRect
->left
< WindowRect
->left
)
509 ClientRect
->left
= WindowRect
->left
;
511 else if (WindowRect
->right
< ClientRect
->left
)
513 ClientRect
->left
= WindowRect
->right
;
515 if (ClientRect
->right
< WindowRect
->left
)
517 ClientRect
->right
= WindowRect
->left
;
519 else if (WindowRect
->right
< ClientRect
->right
)
521 ClientRect
->right
= WindowRect
->right
;
523 if (ClientRect
->top
< WindowRect
->top
)
525 ClientRect
->top
= WindowRect
->top
;
527 else if (WindowRect
->bottom
< ClientRect
->top
)
529 ClientRect
->top
= WindowRect
->bottom
;
531 if (ClientRect
->bottom
< WindowRect
->top
)
533 ClientRect
->bottom
= WindowRect
->top
;
535 else if (WindowRect
->bottom
< ClientRect
->bottom
)
537 ClientRect
->bottom
= WindowRect
->bottom
;
543 co_WinPosDoNCCALCSize(PWND Window
, PWINDOWPOS WinPos
,
544 RECT
* WindowRect
, RECT
* ClientRect
)
549 ASSERT_REFS_CO(Window
);
551 /* Send WM_NCCALCSIZE message to get new client area */
552 if ((WinPos
->flags
& (SWP_FRAMECHANGED
| SWP_NOSIZE
)) != SWP_NOSIZE
)
554 NCCALCSIZE_PARAMS params
;
555 WINDOWPOS winposCopy
;
557 params
.rgrc
[0] = *WindowRect
;
558 params
.rgrc
[1] = Window
->rcWindow
;
559 params
.rgrc
[2] = Window
->rcClient
;
560 Parent
= Window
->spwndParent
;
561 if (0 != (Window
->style
& WS_CHILD
) && Parent
)
563 RECTL_vOffsetRect(&(params
.rgrc
[0]), - Parent
->rcClient
.left
,
564 - Parent
->rcClient
.top
);
565 RECTL_vOffsetRect(&(params
.rgrc
[1]), - Parent
->rcClient
.left
,
566 - Parent
->rcClient
.top
);
567 RECTL_vOffsetRect(&(params
.rgrc
[2]), - Parent
->rcClient
.left
,
568 - Parent
->rcClient
.top
);
570 params
.lppos
= &winposCopy
;
571 winposCopy
= *WinPos
;
573 wvrFlags
= co_IntSendMessageNoWait(Window
->head
.h
, WM_NCCALCSIZE
, TRUE
, (LPARAM
) ¶ms
);
575 /* If the application send back garbage, ignore it */
576 if (params
.rgrc
[0].left
<= params
.rgrc
[0].right
&&
577 params
.rgrc
[0].top
<= params
.rgrc
[0].bottom
)
579 *ClientRect
= params
.rgrc
[0];
580 if ((Window
->style
& WS_CHILD
) && Parent
)
582 RECTL_vOffsetRect(ClientRect
, Parent
->rcClient
.left
,
583 Parent
->rcClient
.top
);
585 FixClientRect(ClientRect
, WindowRect
);
588 /* FIXME: WVR_ALIGNxxx */
590 if (ClientRect
->left
!= Window
->rcClient
.left
||
591 ClientRect
->top
!= Window
->rcClient
.top
)
593 WinPos
->flags
&= ~SWP_NOCLIENTMOVE
;
596 if ((ClientRect
->right
- ClientRect
->left
!=
597 Window
->rcClient
.right
- Window
->rcClient
.left
) ||
598 (ClientRect
->bottom
- ClientRect
->top
!=
599 Window
->rcClient
.bottom
- Window
->rcClient
.top
))
601 WinPos
->flags
&= ~SWP_NOCLIENTSIZE
;
606 if (! (WinPos
->flags
& SWP_NOMOVE
)
607 && (ClientRect
->left
!= Window
->rcClient
.left
||
608 ClientRect
->top
!= Window
->rcClient
.top
))
610 WinPos
->flags
&= ~SWP_NOCLIENTMOVE
;
619 co_WinPosDoWinPosChanging(PWND Window
,
626 ASSERT_REFS_CO(Window
);
628 if (!(WinPos
->flags
& SWP_NOSENDCHANGING
))
630 co_IntSendMessageNoWait(Window
->head
.h
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
) WinPos
);
633 *WindowRect
= Window
->rcWindow
;
634 *ClientRect
= Window
->rcClient
;
636 if (!(WinPos
->flags
& SWP_NOSIZE
))
638 WindowRect
->right
= WindowRect
->left
+ WinPos
->cx
;
639 WindowRect
->bottom
= WindowRect
->top
+ WinPos
->cy
;
642 if (!(WinPos
->flags
& SWP_NOMOVE
))
647 Parent
= Window
->spwndParent
;
648 if ((0 != (Window
->style
& WS_CHILD
)) && Parent
)
650 X
+= Parent
->rcClient
.left
;
651 Y
+= Parent
->rcClient
.top
;
654 WindowRect
->left
= X
;
656 WindowRect
->right
+= X
- Window
->rcWindow
.left
;
657 WindowRect
->bottom
+= Y
- Window
->rcWindow
.top
;
658 RECTL_vOffsetRect(ClientRect
,
659 X
- Window
->rcWindow
.left
,
660 Y
- Window
->rcWindow
.top
);
663 WinPos
->flags
|= SWP_NOCLIENTMOVE
| SWP_NOCLIENTSIZE
;
669 * Fix Z order taking into account owned popups -
670 * basically we need to maintain them above the window that owns them
674 WinPosDoOwnedPopups(PWND Window
, HWND hWndInsertAfter
)
679 PWND DesktopWindow
, ChildObject
;
682 Owner
= Window
->spwndOwner
? Window
->spwndOwner
->head
.h
: NULL
;
683 Style
= Window
->style
;
685 if ((Style
& WS_POPUP
) && Owner
)
687 /* Make sure this popup stays above the owner */
688 HWND hWndLocalPrev
= HWND_TOPMOST
;
690 if (hWndInsertAfter
!= HWND_TOPMOST
)
692 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
693 List
= IntWinListChildren(DesktopWindow
);
697 for (i
= 0; List
[i
]; i
++)
699 if (List
[i
] == Owner
)
701 if (HWND_TOP
== hWndInsertAfter
)
703 ChildObject
= UserGetWindowObject(List
[i
]);
704 if (NULL
!= ChildObject
)
706 if (0 == (ChildObject
->ExStyle
& WS_EX_TOPMOST
))
712 if (List
[i
] != Window
->head
.h
)
713 hWndLocalPrev
= List
[i
];
714 if (hWndLocalPrev
== hWndInsertAfter
)
717 hWndInsertAfter
= hWndLocalPrev
;
721 else if (Style
& WS_CHILD
)
723 return hWndInsertAfter
;
728 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
729 List
= IntWinListChildren(DesktopWindow
);
733 for (i
= 0; List
[i
]; i
++)
737 if (List
[i
] == Window
->head
.h
)
740 if (!(Wnd
= UserGetWindowObject(List
[i
])))
743 if (Wnd
->style
& WS_POPUP
&& Wnd
->spwndOwner
== Window
)
745 USER_REFERENCE_ENTRY Ref
;
746 UserRefObjectCo(Wnd
, &Ref
);
748 co_WinPosSetWindowPos(Wnd
, hWndInsertAfter
, 0, 0, 0, 0,
749 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOSENDCHANGING
);
751 UserDerefObjectCo(Wnd
);
753 hWndInsertAfter
= List
[i
];
759 return hWndInsertAfter
;
762 /***********************************************************************
763 * WinPosInternalMoveWindow
765 * Update WindowRect and ClientRect of Window and all of its children
766 * We keep both WindowRect and ClientRect in screen coordinates internally
770 WinPosInternalMoveWindow(PWND Window
, INT MoveX
, INT MoveY
)
774 ASSERT(Window
!= Window
->spwndChild
);
776 Window
->rcWindow
.left
+= MoveX
;
777 Window
->rcWindow
.right
+= MoveX
;
778 Window
->rcWindow
.top
+= MoveY
;
779 Window
->rcWindow
.bottom
+= MoveY
;
781 Window
->rcClient
.left
+= MoveX
;
782 Window
->rcClient
.right
+= MoveX
;
783 Window
->rcClient
.top
+= MoveY
;
784 Window
->rcClient
.bottom
+= MoveY
;
786 for(Child
= Window
->spwndChild
; Child
; Child
= Child
->spwndNext
)
788 WinPosInternalMoveWindow(Child
, MoveX
, MoveY
);
793 * WinPosFixupSWPFlags
795 * Fix redundant flags and values in the WINDOWPOS structure.
799 WinPosFixupFlags(WINDOWPOS
*WinPos
, PWND Wnd
)
801 if (Wnd
->style
& WS_VISIBLE
)
803 WinPos
->flags
&= ~SWP_SHOWWINDOW
;
807 WinPos
->flags
&= ~SWP_HIDEWINDOW
;
808 if (!(WinPos
->flags
& SWP_SHOWWINDOW
))
809 WinPos
->flags
|= SWP_NOREDRAW
;
812 WinPos
->cx
= max(WinPos
->cx
, 0);
813 WinPos
->cy
= max(WinPos
->cy
, 0);
815 /* Check for right size */
816 if (Wnd
->rcWindow
.right
- Wnd
->rcWindow
.left
== WinPos
->cx
&&
817 Wnd
->rcWindow
.bottom
- Wnd
->rcWindow
.top
== WinPos
->cy
)
819 WinPos
->flags
|= SWP_NOSIZE
;
822 /* Check for right position */
823 if (Wnd
->rcWindow
.left
== WinPos
->x
&&
824 Wnd
->rcWindow
.top
== WinPos
->y
)
826 WinPos
->flags
|= SWP_NOMOVE
;
829 if (WinPos
->hwnd
== UserGetForegroundWindow())
831 WinPos
->flags
|= SWP_NOACTIVATE
; /* Already active */
834 if ((Wnd
->style
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)
836 /* Bring to the top when activating */
837 if (!(WinPos
->flags
& SWP_NOACTIVATE
))
839 WinPos
->flags
&= ~SWP_NOZORDER
;
840 WinPos
->hwndInsertAfter
= (0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
) ?
841 HWND_TOPMOST
: HWND_TOP
);
846 /* Check hwndInsertAfter */
847 if (!(WinPos
->flags
& SWP_NOZORDER
))
849 /* Fix sign extension */
850 if (WinPos
->hwndInsertAfter
== (HWND
)0xffff)
852 WinPos
->hwndInsertAfter
= HWND_TOPMOST
;
854 else if (WinPos
->hwndInsertAfter
== (HWND
)0xfffe)
856 WinPos
->hwndInsertAfter
= HWND_NOTOPMOST
;
859 if (WinPos
->hwndInsertAfter
== HWND_NOTOPMOST
)
861 WinPos
->hwndInsertAfter
= HWND_TOP
;
863 else if (HWND_TOP
== WinPos
->hwndInsertAfter
864 && 0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
))
866 /* Keep it topmost when it's already topmost */
867 WinPos
->hwndInsertAfter
= HWND_TOPMOST
;
870 /* hwndInsertAfter must be a sibling of the window */
871 if (HWND_TOPMOST
!= WinPos
->hwndInsertAfter
872 && HWND_TOP
!= WinPos
->hwndInsertAfter
873 && HWND_NOTOPMOST
!= WinPos
->hwndInsertAfter
874 && HWND_BOTTOM
!= WinPos
->hwndInsertAfter
)
878 InsAfterWnd
= UserGetWindowObject(WinPos
->hwndInsertAfter
);
884 if (InsAfterWnd
->spwndParent
!= Wnd
->spwndParent
)
891 * We don't need to change the Z order of hwnd if it's already
892 * inserted after hwndInsertAfter or when inserting hwnd after
895 if ((WinPos
->hwnd
== WinPos
->hwndInsertAfter
) ||
896 ((InsAfterWnd
->spwndNext
) && (WinPos
->hwnd
== InsAfterWnd
->spwndNext
->head
.h
)))
898 WinPos
->flags
|= SWP_NOZORDER
;
907 /* x and y are always screen relative */
909 co_WinPosSetWindowPos(
923 HRGN VisBefore
= NULL
;
924 HRGN VisAfter
= NULL
;
925 HRGN DirtyRgn
= NULL
;
926 HRGN ExposedRgn
= NULL
;
929 RECTL OldWindowRect
, OldClientRect
;
934 BOOL bPointerInWindow
;
936 ASSERT_REFS_CO(Window
);
938 /* FIXME: Get current active window from active queue. */
940 * Only allow CSRSS to mess with the desktop window
943 if ( Window
->head
.h
== IntGetDesktopWindow() &&
944 Window
->head
.pti
->pEThread
->ThreadsProcess
!= PsGetCurrentProcess())
948 bPointerInWindow
= IntPtInWindow(Window
, gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
);
950 WinPos
.hwnd
= Window
->head
.h
;
951 WinPos
.hwndInsertAfter
= WndInsertAfter
;
956 WinPos
.flags
= flags
;
958 co_WinPosDoWinPosChanging(Window
, &WinPos
, &NewWindowRect
, &NewClientRect
);
960 /* Does the window still exist? */
961 if (!IntIsWindow(WinPos
.hwnd
))
963 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE
);
967 /* Fix up the flags. */
968 if (!WinPosFixupFlags(&WinPos
, Window
))
970 EngSetLastError(ERROR_INVALID_PARAMETER
);
974 Ancestor
= UserGetAncestor(Window
, GA_PARENT
);
975 if ( (WinPos
.flags
& (SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) !=
977 Ancestor
&& Ancestor
->head
.h
== IntGetDesktopWindow() )
979 WinPos
.hwndInsertAfter
= WinPosDoOwnedPopups(Window
, WinPos
.hwndInsertAfter
);
982 if (!(WinPos
.flags
& SWP_NOREDRAW
))
984 /* Compute the visible region before the window position is changed */
985 if (!(WinPos
.flags
& SWP_SHOWWINDOW
) &&
986 (WinPos
.flags
& (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
|
987 SWP_HIDEWINDOW
| SWP_FRAMECHANGED
)) !=
988 (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
))
990 VisBefore
= VIS_ComputeVisibleRegion(Window
, FALSE
, FALSE
,
991 (Window
->style
& WS_CLIPSIBLINGS
) ? TRUE
: FALSE
);
994 if ( VisBefore
!= NULL
&&
995 (VisRgn
= (PROSRGNDATA
)RGNOBJAPI_Lock(VisBefore
, NULL
)) &&
996 REGION_Complexity(VisRgn
) == NULLREGION
)
998 RGNOBJAPI_Unlock(VisRgn
);
999 GreDeleteObject(VisBefore
);
1004 RGNOBJAPI_Unlock(VisRgn
);
1005 NtGdiOffsetRgn(VisBefore
, -Window
->rcWindow
.left
, -Window
->rcWindow
.top
);
1010 WvrFlags
= co_WinPosDoNCCALCSize(Window
, &WinPos
, &NewWindowRect
, &NewClientRect
);
1012 TRACE("co_WinPosDoNCCALCSize returned %d\n", WvrFlags
);
1014 /* Relink windows. (also take into account shell window in hwndShellWindow) */
1015 if (!(WinPos
.flags
& SWP_NOZORDER
) && WinPos
.hwnd
!= UserGetShellWindow())
1017 IntLinkHwnd(Window
, WndInsertAfter
);
1020 OldWindowRect
= Window
->rcWindow
;
1021 OldClientRect
= Window
->rcClient
;
1023 if (OldClientRect
.bottom
- OldClientRect
.top
==
1024 NewClientRect
.bottom
- NewClientRect
.top
)
1026 WvrFlags
&= ~WVR_VREDRAW
;
1029 if (OldClientRect
.right
- OldClientRect
.left
==
1030 NewClientRect
.right
- NewClientRect
.left
)
1032 WvrFlags
&= ~WVR_HREDRAW
;
1035 /* FIXME: Actually do something with WVR_VALIDRECTS */
1037 if (NewClientRect
.left
!= OldClientRect
.left
||
1038 NewClientRect
.top
!= OldClientRect
.top
)
1040 WinPosInternalMoveWindow(Window
,
1041 NewClientRect
.left
- OldClientRect
.left
,
1042 NewClientRect
.top
- OldClientRect
.top
);
1045 Window
->rcWindow
= NewWindowRect
;
1046 Window
->rcClient
= NewClientRect
;
1048 if (WinPos
.flags
& SWP_HIDEWINDOW
)
1050 /* Clear the update region */
1051 co_UserRedrawWindow( Window
,
1054 RDW_VALIDATE
| RDW_NOFRAME
| RDW_NOERASE
| RDW_NOINTERNALPAINT
| RDW_ALLCHILDREN
);
1056 if (Window
->spwndParent
== UserGetDesktopWindow())
1057 co_IntShellHookNotify(HSHELL_WINDOWDESTROYED
, (LPARAM
)Window
->head
.h
);
1059 Window
->style
&= ~WS_VISIBLE
;
1061 else if (WinPos
.flags
& SWP_SHOWWINDOW
)
1063 if (Window
->spwndParent
== UserGetDesktopWindow())
1064 co_IntShellHookNotify(HSHELL_WINDOWCREATED
, (LPARAM
)Window
->head
.h
);
1066 Window
->style
|= WS_VISIBLE
;
1069 if (Window
->hrgnUpdate
!= NULL
&& Window
->hrgnUpdate
!= HRGN_WINDOW
)
1071 NtGdiOffsetRgn(Window
->hrgnUpdate
,
1072 NewWindowRect
.left
- OldWindowRect
.left
,
1073 NewWindowRect
.top
- OldWindowRect
.top
);
1076 DceResetActiveDCEs(Window
);
1078 if (!(WinPos
.flags
& SWP_NOREDRAW
))
1080 /* Determine the new visible region */
1081 VisAfter
= VIS_ComputeVisibleRegion(Window
, FALSE
, FALSE
,
1082 (Window
->style
& WS_CLIPSIBLINGS
) ? TRUE
: FALSE
);
1085 if ( VisAfter
!= NULL
&&
1086 (VisRgn
= (PROSRGNDATA
)RGNOBJAPI_Lock(VisAfter
, NULL
)) &&
1087 REGION_Complexity(VisRgn
) == NULLREGION
)
1089 RGNOBJAPI_Unlock(VisRgn
);
1090 GreDeleteObject(VisAfter
);
1095 RGNOBJAPI_Unlock(VisRgn
);
1096 NtGdiOffsetRgn(VisAfter
, -Window
->rcWindow
.left
, -Window
->rcWindow
.top
);
1100 * Determine which pixels can be copied from the old window position
1101 * to the new. Those pixels must be visible in both the old and new
1102 * position. Also, check the class style to see if the windows of this
1103 * class need to be completely repainted on (horizontal/vertical) size
1106 if ( VisBefore
!= NULL
&&
1108 !(WinPos
.flags
& SWP_NOCOPYBITS
) &&
1109 ((WinPos
.flags
& SWP_NOSIZE
) || !(WvrFlags
& WVR_REDRAW
)) &&
1110 !(Window
->ExStyle
& WS_EX_TRANSPARENT
) )
1112 CopyRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
1113 RgnType
= NtGdiCombineRgn(CopyRgn
, VisAfter
, VisBefore
, RGN_AND
);
1116 * If this is (also) a window resize, the whole nonclient area
1117 * needs to be repainted. So we limit the copy to the client area,
1118 * 'cause there is no use in copying it (would possibly cause
1119 * "flashing" too). However, if the copy region is already empty,
1120 * we don't have to crop (can't take anything away from an empty
1123 if (!(WinPos
.flags
& SWP_NOSIZE
) &&
1125 RgnType
!= NULLREGION
)
1127 PROSRGNDATA pCopyRgn
;
1128 RECTL ORect
= OldClientRect
;
1129 RECTL NRect
= NewClientRect
;
1130 RECTL_vOffsetRect(&ORect
, - OldWindowRect
.left
, - OldWindowRect
.top
);
1131 RECTL_vOffsetRect(&NRect
, - NewWindowRect
.left
, - NewWindowRect
.top
);
1132 RECTL_bIntersectRect(&CopyRect
, &ORect
, &NRect
);
1133 pCopyRgn
= RGNOBJAPI_Lock(CopyRgn
, NULL
);
1134 REGION_CropAndOffsetRegion(pCopyRgn
, pCopyRgn
, &CopyRect
, NULL
);
1135 RGNOBJAPI_Unlock(pCopyRgn
);
1138 /* No use in copying bits which are in the update region. */
1139 if (Window
->hrgnUpdate
!= NULL
)
1141 NtGdiOffsetRgn(CopyRgn
, NewWindowRect
.left
, NewWindowRect
.top
);
1142 NtGdiCombineRgn(CopyRgn
, CopyRgn
, Window
->hrgnUpdate
, RGN_DIFF
);
1143 NtGdiOffsetRgn(CopyRgn
, -NewWindowRect
.left
, -NewWindowRect
.top
);
1147 * Now, get the bounding box of the copy region. If it's empty
1148 * there's nothing to copy. Also, it's no use copying bits onto
1151 if ( (VisRgn
= (PROSRGNDATA
)RGNOBJAPI_Lock(CopyRgn
, NULL
)) &&
1152 REGION_GetRgnBox(VisRgn
, &CopyRect
) == NULLREGION
)
1154 /* Nothing to copy, clean up */
1155 RGNOBJAPI_Unlock(VisRgn
);
1156 GreDeleteObject(CopyRgn
);
1159 else if (OldWindowRect
.left
!= NewWindowRect
.left
||
1160 OldWindowRect
.top
!= NewWindowRect
.top
)
1164 RGNOBJAPI_Unlock(VisRgn
);
1168 * Small trick here: there is no function to bitblt a region. So
1169 * we set the region as the clipping region, take the bounding box
1170 * of the region and bitblt that. Since nothing outside the clipping
1171 * region is copied, this has the effect of bitblt'ing the region.
1173 * Since NtUserGetDCEx takes ownership of the clip region, we need
1174 * to create a copy of CopyRgn and pass that. We need CopyRgn later
1176 NtGdiOffsetRgn(CopyRgn
, NewWindowRect
.left
, NewWindowRect
.top
);
1177 Dc
= UserGetDCEx( Window
,
1179 DCX_WINDOW
|DCX_CACHE
|DCX_INTERSECTRGN
|DCX_CLIPSIBLINGS
|DCX_KEEPCLIPRGN
);
1181 CopyRect
.left
, CopyRect
.top
,
1182 CopyRect
.right
- CopyRect
.left
,
1183 CopyRect
.bottom
- CopyRect
.top
,
1185 CopyRect
.left
+ (OldWindowRect
.left
- NewWindowRect
.left
),
1186 CopyRect
.top
+ (OldWindowRect
.top
- NewWindowRect
.top
),
1191 UserReleaseDC(Window
, Dc
, FALSE
);
1192 IntValidateParent(Window
, CopyRgn
, FALSE
);
1193 NtGdiOffsetRgn(CopyRgn
, -NewWindowRect
.left
, -NewWindowRect
.top
);
1197 RGNOBJAPI_Unlock(VisRgn
);
1205 /* We need to redraw what wasn't visible before */
1206 if (VisAfter
!= NULL
)
1208 DirtyRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
1209 if (CopyRgn
!= NULL
)
1211 RgnType
= NtGdiCombineRgn(DirtyRgn
, VisAfter
, CopyRgn
, RGN_DIFF
);
1215 RgnType
= NtGdiCombineRgn(DirtyRgn
, VisAfter
, 0, RGN_COPY
);
1217 if (RgnType
!= ERROR
&& RgnType
!= NULLREGION
)
1220 NtGdiOffsetRgn(DirtyRgn, Window->rcWindow.left, Window->rcWindow.top);
1221 IntInvalidateWindows( Window,
1223 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
1225 GreDeleteObject(DirtyRgn);
1228 PWND Parent
= Window
->spwndParent
;
1230 NtGdiOffsetRgn( DirtyRgn
,
1231 Window
->rcWindow
.left
,
1232 Window
->rcWindow
.top
);
1233 if ( (Window
->style
& WS_CHILD
) &&
1235 !(Parent
->style
& WS_CLIPCHILDREN
))
1237 IntInvalidateWindows( Parent
,
1239 RDW_ERASE
| RDW_INVALIDATE
);
1240 co_IntPaintWindows(Parent
, RDW_ERASENOW
, FALSE
);
1244 IntInvalidateWindows( Window
,
1246 RDW_ERASE
| RDW_FRAME
| RDW_INVALIDATE
| RDW_ALLCHILDREN
);
1249 GreDeleteObject(DirtyRgn
);
1252 if (CopyRgn
!= NULL
)
1254 GreDeleteObject(CopyRgn
);
1257 /* Expose what was covered before but not covered anymore */
1258 if (VisBefore
!= NULL
)
1260 ExposedRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
1261 RgnType
= NtGdiCombineRgn(ExposedRgn
, VisBefore
, NULL
, RGN_COPY
);
1262 NtGdiOffsetRgn( ExposedRgn
,
1263 OldWindowRect
.left
- NewWindowRect
.left
,
1264 OldWindowRect
.top
- NewWindowRect
.top
);
1266 if (VisAfter
!= NULL
)
1267 RgnType
= NtGdiCombineRgn(ExposedRgn
, ExposedRgn
, VisAfter
, RGN_DIFF
);
1269 if (RgnType
!= ERROR
&& RgnType
!= NULLREGION
)
1271 co_VIS_WindowLayoutChanged(Window
, ExposedRgn
);
1273 GreDeleteObject(ExposedRgn
);
1274 GreDeleteObject(VisBefore
);
1277 if (VisAfter
!= NULL
)
1279 GreDeleteObject(VisAfter
);
1282 if (!(WinPos
.flags
& SWP_NOACTIVATE
))
1284 if ((Window
->style
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1286 co_IntSendMessageNoWait(WinPos
.hwnd
, WM_CHILDACTIVATE
, 0, 0);
1290 co_IntSetForegroundWindow(Window
);
1295 if ((WinPos
.flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOPOSCHANGE
)
1297 /* WM_WINDOWPOSCHANGED is sent even if SWP_NOSENDCHANGING is set
1298 and always contains final window position.
1300 WinPos
.x
= NewWindowRect
.left
;
1301 WinPos
.y
= NewWindowRect
.top
;
1302 WinPos
.cx
= NewWindowRect
.right
- NewWindowRect
.left
;
1303 WinPos
.cy
= NewWindowRect
.bottom
- NewWindowRect
.top
;
1304 co_IntSendMessageNoWait(WinPos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
) &WinPos
);
1307 if ( WinPos
.flags
& SWP_FRAMECHANGED
|| WinPos
.flags
& SWP_STATECHANGED
||
1308 !(WinPos
.flags
& SWP_NOCLIENTSIZE
) || !(WinPos
.flags
& SWP_NOCLIENTMOVE
) )
1310 PWND pWnd
= UserGetWindowObject(WinPos
.hwnd
);
1312 IntNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE
, pWnd
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
1315 if(bPointerInWindow
!= IntPtInWindow(Window
, gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
))
1317 /* Generate mouse move message */
1319 msg
.message
= WM_MOUSEMOVE
;
1320 msg
.wParam
= IntGetSysCursorInfo()->ButtonsDown
;
1321 msg
.lParam
= MAKELPARAM(gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
);
1322 msg
.pt
= gpsi
->ptCursor
;
1323 co_MsqInsertMouseMessage(&msg
, 0, 0, TRUE
);
1330 co_WinPosGetNonClientSize(PWND Window
, RECT
* WindowRect
, RECT
* ClientRect
)
1334 ASSERT_REFS_CO(Window
);
1336 *ClientRect
= *WindowRect
;
1337 Result
= co_IntSendMessageNoWait(Window
->head
.h
, WM_NCCALCSIZE
, FALSE
, (LPARAM
) ClientRect
);
1339 FixClientRect(ClientRect
, WindowRect
);
1345 co_WinPosSendSizeMove(PWND Wnd
)
1347 WPARAM wParam
= SIZE_RESTORED
;
1349 Wnd
->state
&= ~WNDS_SENDSIZEMOVEMSGS
;
1350 if (Wnd
->style
& WS_MAXIMIZE
)
1352 wParam
= SIZE_MAXIMIZED
;
1354 else if (Wnd
->style
& WS_MINIMIZE
)
1356 wParam
= SIZE_MINIMIZED
;
1359 co_IntSendMessageNoWait(Wnd
->head
.h
, WM_SIZE
, wParam
,
1360 MAKELONG(Wnd
->rcClient
.right
-
1362 Wnd
->rcClient
.bottom
-
1363 Wnd
->rcClient
.top
));
1364 co_IntSendMessageNoWait(Wnd
->head
.h
, WM_MOVE
, 0,
1365 MAKELONG(Wnd
->rcClient
.left
,
1366 Wnd
->rcClient
.top
));
1367 IntEngWindowChanged(Wnd
, WOC_RGN_CLIENT
);
1371 co_WinPosShowWindow(PWND Wnd
, INT Cmd
)
1379 ASSERT_REFS_CO(Wnd
);
1381 WasVisible
= (Wnd
->style
& WS_VISIBLE
) != 0;
1391 Swp
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
1392 if (Wnd
->head
.h
!= UserGetActiveWindow())
1393 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1397 case SW_SHOWMINNOACTIVE
:
1398 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1400 case SW_SHOWMINIMIZED
:
1401 Swp
|= SWP_SHOWWINDOW
;
1405 Swp
|= SWP_NOACTIVATE
;
1406 if (!(Wnd
->style
& WS_MINIMIZE
))
1408 Swp
|= co_WinPosMinMaximize(Wnd
, SW_MINIMIZE
, &NewPos
) |
1413 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1416 Swp
|= SWP_FRAMECHANGED
;
1422 case SW_SHOWMAXIMIZED
:
1424 Swp
|= SWP_SHOWWINDOW
;
1425 if (!(Wnd
->style
& WS_MAXIMIZE
))
1427 Swp
|= co_WinPosMinMaximize(Wnd
, SW_MAXIMIZE
, &NewPos
) |
1432 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1435 Swp
|= SWP_FRAMECHANGED
;
1442 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1445 if (WasVisible
) return(TRUE
); // Nothing to do!
1446 Swp
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
1447 /* Don't activate the topmost window. */
1450 case SW_SHOWNOACTIVATE
:
1451 //Swp |= SWP_NOZORDER;
1452 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1455 case SW_SHOWDEFAULT
:
1457 Swp
|= SWP_SHOWWINDOW
;
1458 if (Wnd
->style
& (WS_MINIMIZE
| WS_MAXIMIZE
))
1460 Swp
|= co_WinPosMinMaximize(Wnd
, SW_RESTORE
, &NewPos
) |
1465 Swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1468 Swp
|= SWP_FRAMECHANGED
;
1474 ShowFlag
= (Cmd
!= SW_HIDE
);
1476 if (ShowFlag
!= WasVisible
)
1478 co_IntSendMessageNoWait(Wnd
->head
.h
, WM_SHOWWINDOW
, ShowFlag
, 0);
1481 /* We can't activate a child window */
1482 if ((Wnd
->style
& WS_CHILD
) &&
1483 !(Wnd
->ExStyle
& WS_EX_MDICHILD
))
1485 Swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1488 co_WinPosSetWindowPos(Wnd
, 0 != (Wnd
->ExStyle
& WS_EX_TOPMOST
)
1489 ? HWND_TOPMOST
: HWND_TOP
,
1490 NewPos
.left
, NewPos
.top
, NewPos
.right
, NewPos
.bottom
, LOWORD(Swp
));
1492 if ((Cmd
== SW_HIDE
) || (Cmd
== SW_MINIMIZE
))
1494 PWND ThreadFocusWindow
;
1496 /* FIXME: This will cause the window to be activated irrespective
1497 * of whether it is owned by the same thread. Has to be done
1501 if (Wnd
->head
.h
== UserGetActiveWindow())
1503 co_WinPosActivateOtherWindow(Wnd
);
1508 ThreadFocusWindow
= UserGetWindowObject(IntGetThreadFocusWindow());
1510 /* Revert focus to parent */
1511 if (ThreadFocusWindow
&& (Wnd
== ThreadFocusWindow
||
1512 IntIsChildWindow(Wnd
, ThreadFocusWindow
)))
1514 //faxme: as long as we have ref on Window, we also, indirectly, have ref on parent...
1515 co_UserSetFocus(Wnd
->spwndParent
);
1519 /* FIXME: Check for window destruction. */
1521 if ((Wnd
->state
& WNDS_SENDSIZEMOVEMSGS
) &&
1522 !(Wnd
->state2
& WNDS2_INDESTROY
))
1524 co_WinPosSendSizeMove(Wnd
);
1527 /* Activate the window if activation is not requested and the window is not minimized */
1529 if (!(Swp & (SWP_NOACTIVATE | SWP_HIDEWINDOW)) && !(Window->style & WS_MINIMIZE))
1531 WinPosChangeActiveWindow(Wnd, FALSE);
1539 co_WinPosSearchChildren(
1548 if (!(ScopeWin
->style
& WS_VISIBLE
))
1553 if ((ScopeWin
->style
& WS_DISABLED
))
1558 if (!IntPtInWindow(ScopeWin
, Point
->x
, Point
->y
))
1563 UserReferenceObject(ScopeWin
);
1565 if (Point
->x
- ScopeWin
->rcClient
.left
< ScopeWin
->rcClient
.right
&&
1566 Point
->y
- ScopeWin
->rcClient
.top
< ScopeWin
->rcClient
.bottom
)
1568 List
= IntWinListChildren(ScopeWin
);
1571 for (phWnd
= List
; *phWnd
; ++phWnd
)
1573 if (!(pwndChild
= UserGetWindowObject(*phWnd
)))
1578 pwndChild
= co_WinPosSearchChildren(pwndChild
, Point
, HitTest
);
1580 if(pwndChild
!= NULL
)
1582 /* We found a window. Don't send any more WM_NCHITTEST messages */
1584 UserDereferenceObject(ScopeWin
);
1592 *HitTest
= co_IntSendMessage(ScopeWin
->head
.h
, WM_NCHITTEST
, 0,
1593 MAKELONG(Point
->x
, Point
->y
));
1594 if ((*HitTest
) == (USHORT
)HTTRANSPARENT
)
1596 UserDereferenceObject(ScopeWin
);
1604 co_WinPosWindowFromPoint(PWND ScopeWin
, POINT
*WinPoint
, USHORT
* HitTest
)
1607 POINT Point
= *WinPoint
;
1608 USER_REFERENCE_ENTRY Ref
;
1610 if( ScopeWin
== NULL
)
1612 ScopeWin
= UserGetDesktopWindow();
1613 if(ScopeWin
== NULL
)
1617 *HitTest
= HTNOWHERE
;
1619 ASSERT_REFS_CO(ScopeWin
);
1620 UserRefObjectCo(ScopeWin
, &Ref
);
1622 Window
= co_WinPosSearchChildren(ScopeWin
, &Point
, HitTest
);
1624 UserDerefObjectCo(ScopeWin
);
1626 ASSERT_REFS_CO(Window
);
1627 ASSERT_REFS_CO(ScopeWin
);
1634 IntDeferWindowPos( HDWP hdwp
,
1645 HDWP retvalue
= hdwp
;
1647 TRACE("hdwp %p, hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
1648 hdwp
, hwnd
, hwndAfter
, x
, y
, cx
, cy
, flags
);
1650 if (flags
& ~(SWP_NOSIZE
| SWP_NOMOVE
|
1651 SWP_NOZORDER
| SWP_NOREDRAW
|
1652 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
1653 SWP_NOOWNERZORDER
|SWP_SHOWWINDOW
|
1654 SWP_HIDEWINDOW
| SWP_FRAMECHANGED
))
1656 EngSetLastError(ERROR_INVALID_PARAMETER
);
1660 if (!(pDWP
= (PSMWP
)UserGetObject(gHandleTable
, hdwp
, otSMWP
)))
1662 EngSetLastError(ERROR_INVALID_DWP_HANDLE
);
1666 for (i
= 0; i
< pDWP
->ccvr
; i
++)
1668 if (pDWP
->acvr
[i
].pos
.hwnd
== hwnd
)
1670 /* Merge with the other changes */
1671 if (!(flags
& SWP_NOZORDER
))
1673 pDWP
->acvr
[i
].pos
.hwndInsertAfter
= hwndAfter
;
1675 if (!(flags
& SWP_NOMOVE
))
1677 pDWP
->acvr
[i
].pos
.x
= x
;
1678 pDWP
->acvr
[i
].pos
.y
= y
;
1680 if (!(flags
& SWP_NOSIZE
))
1682 pDWP
->acvr
[i
].pos
.cx
= cx
;
1683 pDWP
->acvr
[i
].pos
.cy
= cy
;
1685 pDWP
->acvr
[i
].pos
.flags
&= flags
| ~(SWP_NOSIZE
| SWP_NOMOVE
|
1686 SWP_NOZORDER
| SWP_NOREDRAW
|
1687 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
1689 pDWP
->acvr
[i
].pos
.flags
|= flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
|
1694 if (pDWP
->ccvr
>= pDWP
->ccvrAlloc
)
1696 PCVR newpos
= ExAllocatePoolWithTag(PagedPool
, pDWP
->ccvrAlloc
* 2 * sizeof(CVR
), USERTAG_SWP
);
1702 RtlZeroMemory(newpos
, pDWP
->ccvrAlloc
* 2 * sizeof(CVR
));
1703 RtlCopyMemory(newpos
, pDWP
->acvr
, pDWP
->ccvrAlloc
* sizeof(CVR
));
1704 ExFreePoolWithTag(pDWP
->acvr
, USERTAG_SWP
);
1705 pDWP
->ccvrAlloc
*= 2;
1706 pDWP
->acvr
= newpos
;
1708 pDWP
->acvr
[pDWP
->ccvr
].pos
.hwnd
= hwnd
;
1709 pDWP
->acvr
[pDWP
->ccvr
].pos
.hwndInsertAfter
= hwndAfter
;
1710 pDWP
->acvr
[pDWP
->ccvr
].pos
.x
= x
;
1711 pDWP
->acvr
[pDWP
->ccvr
].pos
.y
= y
;
1712 pDWP
->acvr
[pDWP
->ccvr
].pos
.cx
= cx
;
1713 pDWP
->acvr
[pDWP
->ccvr
].pos
.cy
= cy
;
1714 pDWP
->acvr
[pDWP
->ccvr
].pos
.flags
= flags
;
1715 pDWP
->acvr
[pDWP
->ccvr
].hrgnClip
= NULL
;
1716 pDWP
->acvr
[pDWP
->ccvr
].hrgnInterMonitor
= NULL
;
1722 BOOL FASTCALL
IntEndDeferWindowPosEx( HDWP hdwp
)
1729 TRACE("%p\n", hdwp
);
1731 if (!(pDWP
= (PSMWP
)UserGetObject(gHandleTable
, hdwp
, otSMWP
)))
1733 EngSetLastError(ERROR_INVALID_DWP_HANDLE
);
1737 for (i
= 0, winpos
= pDWP
->acvr
; res
&& i
< pDWP
->ccvr
; i
++, winpos
++)
1740 USER_REFERENCE_ENTRY Ref
;
1742 TRACE("hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
1743 winpos
->pos
.hwnd
, winpos
->pos
.hwndInsertAfter
, winpos
->pos
.x
, winpos
->pos
.y
,
1744 winpos
->pos
.cx
, winpos
->pos
.cy
, winpos
->pos
.flags
);
1746 pwnd
= UserGetWindowObject(winpos
->pos
.hwnd
);
1750 UserRefObjectCo(pwnd
, &Ref
);
1752 res
= co_WinPosSetWindowPos( pwnd
,
1753 winpos
->pos
.hwndInsertAfter
,
1760 UserDerefObjectCo(pwnd
);
1762 ExFreePoolWithTag(pDWP
->acvr
, USERTAG_SWP
);
1763 UserDereferenceObject(pDWP
);
1764 UserDeleteObject(hdwp
, otSMWP
);
1772 NtUserChildWindowFromPointEx(HWND hwndParent
,
1782 if(!(Parent
= UserGetWindowObject(hwndParent
)))
1790 if(Parent
->head
.h
!= IntGetDesktopWindow())
1792 Pt
.x
+= Parent
->rcClient
.left
;
1793 Pt
.y
+= Parent
->rcClient
.top
;
1796 if(!IntPtInWindow(Parent
, Pt
.x
, Pt
.y
))
1801 Ret
= Parent
->head
.h
;
1802 if((List
= IntWinListChildren(Parent
)))
1804 for(phWnd
= List
; *phWnd
; phWnd
++)
1807 if((Child
= UserGetWindowObject(*phWnd
)))
1809 if(!(Child
->style
& WS_VISIBLE
) && (uiFlags
& CWP_SKIPINVISIBLE
))
1813 if((Child
->style
& WS_DISABLED
) && (uiFlags
& CWP_SKIPDISABLED
))
1817 if((Child
->ExStyle
& WS_EX_TRANSPARENT
) && (uiFlags
& CWP_SKIPTRANSPARENT
))
1821 if(IntPtInWindow(Child
, Pt
.x
, Pt
.y
))
1823 Ret
= Child
->head
.h
;
1838 NtUserEndDeferWindowPosEx(HDWP WinPosInfo
,
1842 TRACE("Enter NtUserEndDeferWindowPosEx\n");
1843 UserEnterExclusive();
1844 Ret
= IntEndDeferWindowPosEx(WinPosInfo
);
1845 TRACE("Leave NtUserEndDeferWindowPosEx, ret=%i\n", Ret
);
1854 NtUserDeferWindowPos(HDWP WinPosInfo
,
1856 HWND WndInsertAfter
,
1865 UINT Tmp
= ~(SWP_ASYNCWINDOWPOS
|SWP_DEFERERASE
|SWP_NOSENDCHANGING
|SWP_NOREPOSITION
|
1866 SWP_NOCOPYBITS
|SWP_HIDEWINDOW
|SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|
1867 SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_NOZORDER
|SWP_NOMOVE
|SWP_NOSIZE
);
1869 TRACE("Enter NtUserDeferWindowPos\n");
1870 UserEnterExclusive();
1874 EngSetLastError(ERROR_INVALID_FLAGS
);
1878 pWnd
= UserGetWindowObject(Wnd
);
1879 if ( !pWnd
|| // FIXME:
1880 pWnd
== IntGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
1881 pWnd
== IntGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
1886 if ( WndInsertAfter
&&
1887 WndInsertAfter
!= HWND_BOTTOM
&&
1888 WndInsertAfter
!= HWND_TOPMOST
&&
1889 WndInsertAfter
!= HWND_NOTOPMOST
)
1891 pWndIA
= UserGetWindowObject(WndInsertAfter
);
1893 pWndIA
== IntGetDesktopWindow() ||
1894 pWndIA
== IntGetMessageWindow() )
1900 Ret
= IntDeferWindowPos(WinPosInfo
, Wnd
, WndInsertAfter
, x
, y
, cx
, cy
, Flags
);
1903 TRACE("Leave NtUserDeferWindowPos, ret=%i\n", Ret
);
1912 UINT cmd
, // Wine SW_ commands
1919 TRACE("Enter NtUserMinMaximize\n");
1920 UserEnterExclusive();
1922 pWnd
= UserGetWindowObject(hWnd
);
1923 if ( !pWnd
|| // FIXME:
1924 pWnd
== IntGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
1925 pWnd
== IntGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
1930 if ( cmd
> SW_MAX
|| pWnd
->state2
& WNDS2_INDESTROY
)
1932 EngSetLastError(ERROR_INVALID_PARAMETER
);
1936 co_WinPosMinMaximize(pWnd
, cmd
, &NewPos
);
1938 SwFlags
= Hide
? SWP_NOACTIVATE
|SWP_NOZORDER
|SWP_FRAMECHANGED
: SWP_NOZORDER
|SWP_FRAMECHANGED
;
1940 co_WinPosSetWindowPos( pWnd
,
1948 co_WinPosShowWindow(pWnd
, cmd
);
1951 TRACE("Leave NtUserMinMaximize\n");
1953 return 0; // Always NULL?
1968 return NtUserSetWindowPos(hWnd
, 0, X
, Y
, nWidth
, nHeight
,
1969 (bRepaint
? SWP_NOZORDER
| SWP_NOACTIVATE
:
1970 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
));
1979 HWND hWndInsertAfter
,
1986 DECLARE_RETURN(BOOL
);
1987 PWND Window
, pWndIA
;
1989 USER_REFERENCE_ENTRY Ref
;
1991 TRACE("Enter NtUserSetWindowPos\n");
1992 UserEnterExclusive();
1994 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
1995 Window
== IntGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
1996 Window
== IntGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
2001 if ( hWndInsertAfter
&&
2002 hWndInsertAfter
!= HWND_BOTTOM
&&
2003 hWndInsertAfter
!= HWND_TOPMOST
&&
2004 hWndInsertAfter
!= HWND_NOTOPMOST
)
2006 pWndIA
= UserGetWindowObject(hWndInsertAfter
);
2008 pWndIA
== IntGetDesktopWindow() ||
2009 pWndIA
== IntGetMessageWindow() )
2015 /* First make sure that coordinates are valid for WM_WINDOWPOSCHANGING */
2016 if (!(uFlags
& SWP_NOMOVE
))
2018 if (X
< -32768) X
= -32768;
2019 else if (X
> 32767) X
= 32767;
2020 if (Y
< -32768) Y
= -32768;
2021 else if (Y
> 32767) Y
= 32767;
2023 if (!(uFlags
& SWP_NOSIZE
))
2026 else if (cx
> 32767) cx
= 32767;
2028 else if (cy
> 32767) cy
= 32767;
2031 UserRefObjectCo(Window
, &Ref
);
2032 ret
= co_WinPosSetWindowPos(Window
, hWndInsertAfter
, X
, Y
, cx
, cy
, uFlags
);
2033 UserDerefObjectCo(Window
);
2038 TRACE("Leave NtUserSetWindowPos, ret=%i\n",_ret_
);
2054 INT flags
= (SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
);
2055 BOOLEAN Ret
= FALSE
;
2056 DECLARE_RETURN(INT
);
2058 TRACE("Enter NtUserSetWindowRgn\n");
2059 UserEnterExclusive();
2061 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
2062 Window
== IntGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
2063 Window
== IntGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
2068 if (hRgn
) // The region will be deleted in user32.
2070 if (GreIsHandleValid(hRgn
))
2072 hrgnCopy
= IntSysCreateRectRgn(0, 0, 0, 0);
2074 NtGdiCombineRgn(hrgnCopy
, hRgn
, 0, RGN_COPY
);
2084 /* Delete the region passed by the caller */
2085 GreDeleteObject(hRgn
);
2087 if (Window
->hrgnClip
)
2089 /* Delete no longer needed region handle */
2090 IntGdiSetRegionOwner(Window
->hrgnClip
, GDI_OBJ_HMGR_POWNED
);
2091 GreDeleteObject(Window
->hrgnClip
);
2096 /* Set public ownership */
2097 IntGdiSetRegionOwner(hrgnCopy
, GDI_OBJ_HMGR_PUBLIC
);
2099 Window
->hrgnClip
= hrgnCopy
;
2101 Ret
= co_WinPosSetWindowPos(Window
, HWND_TOP
, 0, 0, 0, 0, bRedraw
? flags
: (flags
|SWP_NOREDRAW
) );
2106 TRACE("Leave NtUserSetWindowRgn, ret=%i\n",_ret_
);
2115 NtUserSetWindowPlacement(HWND hWnd
,
2116 WINDOWPLACEMENT
*lpwndpl
)
2119 WINDOWPLACEMENT Safepl
;
2120 DECLARE_RETURN(BOOL
);
2121 USER_REFERENCE_ENTRY Ref
;
2123 TRACE("Enter NtUserSetWindowPlacement\n");
2124 UserEnterExclusive();
2126 if (!(Wnd
= UserGetWindowObject(hWnd
)) || // FIXME:
2127 Wnd
== IntGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
2128 Wnd
== IntGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
2135 ProbeForRead(lpwndpl
, sizeof(WINDOWPLACEMENT
), 1);
2136 RtlCopyMemory(&Safepl
, lpwndpl
, sizeof(WINDOWPLACEMENT
));
2138 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2140 SetLastNtError(_SEH2_GetExceptionCode());
2141 _SEH2_YIELD(RETURN( FALSE
));
2145 if(Safepl
.length
!= sizeof(WINDOWPLACEMENT
))
2150 UserRefObjectCo(Wnd
, &Ref
);
2152 if ((Wnd
->style
& (WS_MAXIMIZE
| WS_MINIMIZE
)) == 0)
2154 co_WinPosSetWindowPos(Wnd
, NULL
,
2155 Safepl
.rcNormalPosition
.left
, Safepl
.rcNormalPosition
.top
,
2156 Safepl
.rcNormalPosition
.right
- Safepl
.rcNormalPosition
.left
,
2157 Safepl
.rcNormalPosition
.bottom
- Safepl
.rcNormalPosition
.top
,
2158 SWP_NOZORDER
| SWP_NOACTIVATE
);
2161 /* FIXME - change window status */
2162 co_WinPosShowWindow(Wnd
, Safepl
.showCmd
);
2164 Wnd
->InternalPosInitialized
= TRUE
;
2165 Wnd
->InternalPos
.NormalRect
= Safepl
.rcNormalPosition
;
2166 Wnd
->InternalPos
.IconPos
= Safepl
.ptMinPosition
;
2167 Wnd
->InternalPos
.MaxPos
= Safepl
.ptMaxPosition
;
2169 UserDerefObjectCo(Wnd
);
2173 TRACE("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_
);
2182 NtUserShowWindowAsync(HWND hWnd
, LONG nCmdShow
)
2188 return NtUserShowWindow(hWnd
, nCmdShow
);
2196 NtUserShowWindow(HWND hWnd
, LONG nCmdShow
)
2200 DECLARE_RETURN(BOOL
);
2201 USER_REFERENCE_ENTRY Ref
;
2203 TRACE("Enter NtUserShowWindow\n");
2204 UserEnterExclusive();
2206 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
2207 Window
== IntGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
2208 Window
== IntGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
2213 if ( nCmdShow
> SW_MAX
|| Window
->state2
& WNDS2_INDESTROY
)
2215 EngSetLastError(ERROR_INVALID_PARAMETER
);
2219 UserRefObjectCo(Window
, &Ref
);
2220 ret
= co_WinPosShowWindow(Window
, nCmdShow
);
2221 UserDerefObjectCo(Window
);
2226 TRACE("Leave NtUserShowWindow, ret=%i\n",_ret_
);
2231 //// Ugly NtUser API ////
2234 NtUserGetMinMaxInfo(
2236 MINMAXINFO
*MinMaxInfo
,
2241 MINMAXINFO SafeMinMax
;
2244 USER_REFERENCE_ENTRY Ref
;
2246 TRACE("Enter NtUserGetMinMaxInfo\n");
2247 UserEnterExclusive();
2249 if(!(Window
= UserGetWindowObject(hWnd
)))
2255 UserRefObjectCo(Window
, &Ref
);
2257 Size
.x
= Window
->rcWindow
.left
;
2258 Size
.y
= Window
->rcWindow
.top
;
2259 WinPosInitInternalPos(Window
, &Size
,
2262 co_WinPosGetMinMaxInfo(Window
, &SafeMinMax
.ptMaxSize
, &SafeMinMax
.ptMaxPosition
,
2263 &SafeMinMax
.ptMinTrackSize
, &SafeMinMax
.ptMaxTrackSize
);
2265 Status
= MmCopyToCaller(MinMaxInfo
, &SafeMinMax
, sizeof(MINMAXINFO
));
2266 if(!NT_SUCCESS(Status
))
2268 SetLastNtError(Status
);
2276 if (Window
) UserDerefObjectCo(Window
);
2278 TRACE("Leave NtUserGetMinMaxInfo, ret=%i\n", ret
);