2 * Window position related functions.
4 * Copyright 1993, 1994, 1995 Alexandre Julliard
5 * 1995, 1996, 1999 Alex Korobka
13 #include "wine/winuser16.h"
26 #include "nonclient.h"
27 #include "debugtools.h"
30 DEFAULT_DEBUG_CHANNEL(win
);
32 #define HAS_DLGFRAME(style,exStyle) \
33 (((exStyle) & WS_EX_DLGMODALFRAME) || \
34 (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
36 #define HAS_THICKFRAME(style) \
37 (((style) & WS_THICKFRAME) && \
38 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
40 #define SWP_AGG_NOGEOMETRYCHANGE \
41 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
42 #define SWP_AGG_NOPOSCHANGE \
43 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
44 #define SWP_AGG_STATUSFLAGS \
45 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
47 #define EMPTYPOINT(pt) ((*(LONG*)&(pt)) == -1)
49 #define PLACE_MIN 0x0001
50 #define PLACE_MAX 0x0002
51 #define PLACE_RECT 0x0004
53 #define SWP_EX_NOCOPY 0x0001
54 #define SWP_EX_PAINTSELF 0x0002
55 #define SWP_EX_NONCLIENT 0x0004
57 #define MINMAX_NOSWP 0x00010000
59 /* ----- internal variables ----- */
61 static HWND hwndPrevActive
= 0; /* Previously active window */
62 static HWND hGlobalShellWindow
=0; /*the shell*/
63 static HWND hGlobalTaskmanWindow
=0;
64 static HWND hGlobalProgmanWindow
=0;
66 static LPCSTR atomInternalPos
;
68 extern HQUEUE16 hActiveQueue
;
70 /***********************************************************************
71 * WINPOS_CreateInternalPosAtom
73 BOOL
WINPOS_CreateInternalPosAtom()
76 atomInternalPos
= (LPCSTR
)(DWORD
)GlobalAddAtomA(str
);
77 return (atomInternalPos
) ? TRUE
: FALSE
;
80 /***********************************************************************
81 * WINPOS_CheckInternalPos
83 * Called when a window is destroyed.
85 void WINPOS_CheckInternalPos( WND
* wndPtr
)
88 MESSAGEQUEUE
*pMsgQ
= 0;
89 HWND hwnd
= wndPtr
->hwndSelf
;
91 lpPos
= (LPINTERNALPOS
) GetPropA( hwnd
, atomInternalPos
);
93 /* Retrieve the message queue associated with this window */
94 pMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( wndPtr
->hmemTaskQ
);
97 WARN("\tMessage queue not found. Exiting!\n" );
101 if( hwnd
== hwndPrevActive
) hwndPrevActive
= 0;
103 if( hwnd
== PERQDATA_GetActiveWnd( pMsgQ
->pQData
) )
105 PERQDATA_SetActiveWnd( pMsgQ
->pQData
, 0 );
106 WARN("\tattempt to activate destroyed window!\n");
111 if( IsWindow(lpPos
->hwndIconTitle
) )
112 DestroyWindow( lpPos
->hwndIconTitle
);
113 HeapFree( SystemHeap
, 0, lpPos
);
116 QUEUE_Unlock( pMsgQ
);
120 /***********************************************************************
123 * Find a suitable place for an iconic window.
125 static POINT16
WINPOS_FindIconPos( WND
* wndPtr
, POINT16 pt
)
128 short x
, y
, xspacing
, yspacing
;
130 GetClientRect16( wndPtr
->parent
->hwndSelf
, &rectParent
);
131 if ((pt
.x
>= rectParent
.left
) && (pt
.x
+ GetSystemMetrics(SM_CXICON
) < rectParent
.right
) &&
132 (pt
.y
>= rectParent
.top
) && (pt
.y
+ GetSystemMetrics(SM_CYICON
) < rectParent
.bottom
))
133 return pt
; /* The icon already has a suitable position */
135 xspacing
= GetSystemMetrics(SM_CXICONSPACING
);
136 yspacing
= GetSystemMetrics(SM_CYICONSPACING
);
138 y
= rectParent
.bottom
;
144 /* Check if another icon already occupies this spot */
145 WND
*childPtr
= WIN_LockWndPtr(wndPtr
->parent
->child
);
148 if ((childPtr
->dwStyle
& WS_MINIMIZE
) && (childPtr
!= wndPtr
))
150 if ((childPtr
->rectWindow
.left
< x
+ xspacing
) &&
151 (childPtr
->rectWindow
.right
>= x
) &&
152 (childPtr
->rectWindow
.top
<= y
) &&
153 (childPtr
->rectWindow
.bottom
> y
- yspacing
))
154 break; /* There's a window in there */
156 WIN_UpdateWndPtr(&childPtr
,childPtr
->next
);
158 WIN_ReleaseWndPtr(childPtr
);
159 if (!childPtr
) /* No window was found, so it's OK for us */
161 pt
.x
= x
+ (xspacing
- GetSystemMetrics(SM_CXICON
)) / 2;
162 pt
.y
= y
- (yspacing
+ GetSystemMetrics(SM_CYICON
)) / 2;
166 } while(x
<= rectParent
.right
-xspacing
);
172 /***********************************************************************
173 * ArrangeIconicWindows16 (USER.170)
175 UINT16 WINAPI
ArrangeIconicWindows16( HWND16 parent
)
177 return ArrangeIconicWindows(parent
);
179 /***********************************************************************
180 * ArrangeIconicWindows (USER32.7)
182 UINT WINAPI
ArrangeIconicWindows( HWND parent
)
186 INT x
, y
, xspacing
, yspacing
;
188 GetClientRect( parent
, &rectParent
);
190 y
= rectParent
.bottom
;
191 xspacing
= GetSystemMetrics(SM_CXICONSPACING
);
192 yspacing
= GetSystemMetrics(SM_CYICONSPACING
);
194 hwndChild
= GetWindow( parent
, GW_CHILD
);
197 if( IsIconic( hwndChild
) )
199 WND
*wndPtr
= WIN_FindWndPtr(hwndChild
);
201 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
203 SetWindowPos( hwndChild
, 0, x
+ (xspacing
- GetSystemMetrics(SM_CXICON
)) / 2,
204 y
- yspacing
- GetSystemMetrics(SM_CYICON
)/2, 0, 0,
205 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
206 if( IsWindow(hwndChild
) )
207 WINPOS_ShowIconTitle(wndPtr
, TRUE
);
208 WIN_ReleaseWndPtr(wndPtr
);
210 if (x
<= rectParent
.right
- xspacing
) x
+= xspacing
;
217 hwndChild
= GetWindow( hwndChild
, GW_HWNDNEXT
);
223 /***********************************************************************
224 * SwitchToThisWindow16 (USER.172)
226 void WINAPI
SwitchToThisWindow16( HWND16 hwnd
, BOOL16 restore
)
228 SwitchToThisWindow( hwnd
, restore
);
232 /***********************************************************************
233 * SwitchToThisWindow (USER32.539)
235 void WINAPI
SwitchToThisWindow( HWND hwnd
, BOOL restore
)
237 ShowWindow( hwnd
, restore
? SW_RESTORE
: SW_SHOWMINIMIZED
);
241 /***********************************************************************
242 * GetWindowRect16 (USER.32)
244 void WINAPI
GetWindowRect16( HWND16 hwnd
, LPRECT16 rect
)
246 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
249 CONV_RECT32TO16( &wndPtr
->rectWindow
, rect
);
250 if (wndPtr
->dwStyle
& WS_CHILD
)
251 MapWindowPoints16( wndPtr
->parent
->hwndSelf
, 0, (POINT16
*)rect
, 2 );
252 WIN_ReleaseWndPtr(wndPtr
);
256 /***********************************************************************
257 * GetWindowRect (USER32.308)
259 BOOL WINAPI
GetWindowRect( HWND hwnd
, LPRECT rect
)
261 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
262 if (!wndPtr
) return FALSE
;
264 *rect
= wndPtr
->rectWindow
;
265 if (wndPtr
->dwStyle
& WS_CHILD
)
266 MapWindowPoints( wndPtr
->parent
->hwndSelf
, 0, (POINT
*)rect
, 2 );
267 WIN_ReleaseWndPtr(wndPtr
);
272 /***********************************************************************
273 * GetWindowRgn (USER32)
275 int WINAPI
GetWindowRgn ( HWND hwnd
, HRGN hrgn
)
278 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
281 if (wndPtr
->hrgnWnd
) nRet
= CombineRgn( hrgn
, wndPtr
->hrgnWnd
, 0, RGN_COPY
);
282 WIN_ReleaseWndPtr(wndPtr
);
287 /***********************************************************************
288 * SetWindowRgn (USER32)
290 int WINAPI
SetWindowRgn( HWND hwnd
, HRGN hrgn
, BOOL bRedraw
)
295 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
297 if (!wndPtr
) return FALSE
;
299 /* a region exists for this window */
300 if (hrgn
!= 0 && hrgn
== wndPtr
->hrgnWnd
)
302 /* can't replace actual region with same region
303 since we're now owner of that region
305 SetLastError(ERROR_INVALID_HANDLE
);
310 /* we'd like to set it back to 0 */
313 GetWindowRect(hwnd
, &tempRect
);
317 /* verify that region really exists */
318 if (GetRgnBox(hrgn
, &tempRect
) == ERROR
) goto done
;
322 /* Size the window to the rectangle of the new region
323 (if it isn't NULL) */
324 SetWindowPos( hwnd
, 0, tempRect
.left
, tempRect
.top
,
325 tempRect
.right
- tempRect
.left
, tempRect
.bottom
- tempRect
.top
,
326 SWP_NOSIZE
| SWP_FRAMECHANGED
| SWP_NOMOVE
|
327 SWP_NOZORDER
| (bRedraw
? 0 : SWP_NOREDRAW
) );
332 /* delete previous region */
333 DeleteObject(wndPtr
->hrgnWnd
);
338 /* if there was no previous region (stored in wndPtr->hrgnWnd) and
339 the region to be set is also NULL, there is nothing more to do
345 /* valid region handle */
346 wndPtr
->hrgnWnd
= hrgn
;
347 wndPtr
->pDriver
->pSetWindowRgn(wndPtr
, hrgn
);
352 WIN_ReleaseWndPtr(wndPtr
);
356 /***********************************************************************
359 INT16 WINAPI
SetWindowRgn16( HWND16 hwnd
, HRGN16 hrgn
,BOOL16 bRedraw
)
363 FIXME("SetWindowRgn16: stub\n");
368 /***********************************************************************
369 * GetClientRect16 (USER.33)
371 void WINAPI
GetClientRect16( HWND16 hwnd
, LPRECT16 rect
)
373 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
375 rect
->left
= rect
->top
= rect
->right
= rect
->bottom
= 0;
378 rect
->right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
379 rect
->bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
381 WIN_ReleaseWndPtr(wndPtr
);
385 /***********************************************************************
386 * GetClientRect (USER.220)
388 BOOL WINAPI
GetClientRect( HWND hwnd
, LPRECT rect
)
390 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
392 rect
->left
= rect
->top
= rect
->right
= rect
->bottom
= 0;
393 if (!wndPtr
) return FALSE
;
394 rect
->right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
395 rect
->bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
397 WIN_ReleaseWndPtr(wndPtr
);
402 /*******************************************************************
403 * ClientToScreen16 (USER.28)
405 void WINAPI
ClientToScreen16( HWND16 hwnd
, LPPOINT16 lppnt
)
407 MapWindowPoints16( hwnd
, 0, lppnt
, 1 );
411 /*******************************************************************
412 * ClientToScreen (USER32.52)
414 BOOL WINAPI
ClientToScreen( HWND hwnd
, LPPOINT lppnt
)
416 MapWindowPoints( hwnd
, 0, lppnt
, 1 );
421 /*******************************************************************
422 * ScreenToClient16 (USER.29)
424 void WINAPI
ScreenToClient16( HWND16 hwnd
, LPPOINT16 lppnt
)
426 MapWindowPoints16( 0, hwnd
, lppnt
, 1 );
430 /*******************************************************************
431 * ScreenToClient (USER32.447)
433 BOOL WINAPI
ScreenToClient( HWND hwnd
, LPPOINT lppnt
)
435 MapWindowPoints( 0, hwnd
, lppnt
, 1 );
440 /***********************************************************************
441 * WINPOS_WindowFromPoint
443 * Find the window and hittest for a given point.
445 INT16
WINPOS_WindowFromPoint( WND
* wndScope
, POINT16 pt
, WND
**ppWnd
)
448 INT16 hittest
= HTERROR
;
452 TRACE("scope %04x %d,%d\n", wndScope
->hwndSelf
, pt
.x
, pt
.y
);
454 wndPtr
= WIN_LockWndPtr(wndScope
->child
);
456 if( wndScope
->dwStyle
& WS_DISABLED
)
462 if( wndScope
->dwExStyle
& WS_EX_MANAGED
)
464 /* In managed mode we have to check wndScope first as it is also
465 * a window which received the mouse event. */
467 if( pt
.x
< wndScope
->rectClient
.left
|| pt
.x
>= wndScope
->rectClient
.right
||
468 pt
.y
< wndScope
->rectClient
.top
|| pt
.y
>= wndScope
->rectClient
.bottom
)
471 MapWindowPoints16( GetDesktopWindow16(), wndScope
->hwndSelf
, &xy
, 1 );
477 /* If point is in window, and window is visible, and it */
478 /* is enabled (or it's a top-level window), then explore */
479 /* its children. Otherwise, go to the next window. */
481 if ((wndPtr
->dwStyle
& WS_VISIBLE
) &&
482 (!(wndPtr
->dwStyle
& WS_DISABLED
) ||
483 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)) &&
485 PtInRegion(wndPtr
->hrgnWnd
, xy
.x
- wndPtr
->rectWindow
.left
,
486 xy
.y
- wndPtr
->rectWindow
.top
) :
487 ((xy
.x
>= wndPtr
->rectWindow
.left
) &&
488 (xy
.x
< wndPtr
->rectWindow
.right
) &&
489 (xy
.y
>= wndPtr
->rectWindow
.top
) &&
490 (xy
.y
< wndPtr
->rectWindow
.bottom
))))
492 TRACE("%d,%d is inside %04x\n", xy
.x
, xy
.y
, wndPtr
->hwndSelf
);
493 *ppWnd
= wndPtr
; /* Got a suitable window */
495 /* If window is minimized or disabled, return at once */
496 if (wndPtr
->dwStyle
& WS_MINIMIZE
)
498 retvalue
= HTCAPTION
;
501 if (wndPtr
->dwStyle
& WS_DISABLED
)
507 /* If point is not in client area, ignore the children */
508 if ((xy
.x
< wndPtr
->rectClient
.left
) ||
509 (xy
.x
>= wndPtr
->rectClient
.right
) ||
510 (xy
.y
< wndPtr
->rectClient
.top
) ||
511 (xy
.y
>= wndPtr
->rectClient
.bottom
)) break;
513 xy
.x
-= wndPtr
->rectClient
.left
;
514 xy
.y
-= wndPtr
->rectClient
.top
;
515 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->child
);
519 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->next
);
524 /* If nothing found, try the scope window */
525 if (!*ppWnd
) *ppWnd
= wndScope
;
527 /* Send the WM_NCHITTEST message (only if to the same task) */
528 if ((*ppWnd
)->hmemTaskQ
== GetFastQueue16())
530 hittest
= (INT16
)SendMessage16( (*ppWnd
)->hwndSelf
, WM_NCHITTEST
,
531 0, MAKELONG( pt
.x
, pt
.y
) );
532 if (hittest
!= HTTRANSPARENT
)
534 retvalue
= hittest
; /* Found the window */
544 /* If no children found in last search, make point relative to parent */
547 xy
.x
+= (*ppWnd
)->rectClient
.left
;
548 xy
.y
+= (*ppWnd
)->rectClient
.top
;
551 /* Restart the search from the next sibling */
552 WIN_UpdateWndPtr(&wndPtr
,(*ppWnd
)->next
);
553 *ppWnd
= (*ppWnd
)->parent
;
557 WIN_ReleaseWndPtr(wndPtr
);
562 /*******************************************************************
563 * WindowFromPoint16 (USER.30)
565 HWND16 WINAPI
WindowFromPoint16( POINT16 pt
)
568 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt
, &pWnd
);
569 WIN_ReleaseDesktop();
570 return pWnd
->hwndSelf
;
574 /*******************************************************************
575 * WindowFromPoint (USER32.582)
577 HWND WINAPI
WindowFromPoint( POINT pt
)
581 CONV_POINT32TO16( &pt
, &pt16
);
582 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16
, &pWnd
);
583 WIN_ReleaseDesktop();
584 return (HWND
)pWnd
->hwndSelf
;
588 /*******************************************************************
589 * ChildWindowFromPoint16 (USER.191)
591 HWND16 WINAPI
ChildWindowFromPoint16( HWND16 hwndParent
, POINT16 pt
)
594 CONV_POINT16TO32( &pt
, &pt32
);
595 return (HWND16
)ChildWindowFromPoint( hwndParent
, pt32
);
599 /*******************************************************************
600 * ChildWindowFromPoint (USER32.49)
602 HWND WINAPI
ChildWindowFromPoint( HWND hwndParent
, POINT pt
)
604 /* pt is in the client coordinates */
606 WND
* wnd
= WIN_FindWndPtr(hwndParent
);
612 /* get client rect fast */
613 rect
.top
= rect
.left
= 0;
614 rect
.right
= wnd
->rectClient
.right
- wnd
->rectClient
.left
;
615 rect
.bottom
= wnd
->rectClient
.bottom
- wnd
->rectClient
.top
;
617 if (!PtInRect( &rect
, pt
))
622 WIN_UpdateWndPtr(&wnd
,wnd
->child
);
625 if (PtInRect( &wnd
->rectWindow
, pt
))
627 retvalue
= wnd
->hwndSelf
;
630 WIN_UpdateWndPtr(&wnd
,wnd
->next
);
632 retvalue
= hwndParent
;
634 WIN_ReleaseWndPtr(wnd
);
638 /*******************************************************************
639 * ChildWindowFromPointEx16 (USER.50)
641 HWND16 WINAPI
ChildWindowFromPointEx16( HWND16 hwndParent
, POINT16 pt
, UINT16 uFlags
)
644 CONV_POINT16TO32( &pt
, &pt32
);
645 return (HWND16
)ChildWindowFromPointEx( hwndParent
, pt32
, uFlags
);
649 /*******************************************************************
650 * ChildWindowFromPointEx (USER32.50)
652 HWND WINAPI
ChildWindowFromPointEx( HWND hwndParent
, POINT pt
,
655 /* pt is in the client coordinates */
657 WND
* wnd
= WIN_FindWndPtr(hwndParent
);
663 /* get client rect fast */
664 rect
.top
= rect
.left
= 0;
665 rect
.right
= wnd
->rectClient
.right
- wnd
->rectClient
.left
;
666 rect
.bottom
= wnd
->rectClient
.bottom
- wnd
->rectClient
.top
;
668 if (!PtInRect( &rect
, pt
))
673 WIN_UpdateWndPtr(&wnd
,wnd
->child
);
677 if (PtInRect( &wnd
->rectWindow
, pt
)) {
678 if ( (uFlags
& CWP_SKIPINVISIBLE
) &&
679 !(wnd
->dwStyle
& WS_VISIBLE
) );
680 else if ( (uFlags
& CWP_SKIPDISABLED
) &&
681 (wnd
->dwStyle
& WS_DISABLED
) );
682 else if ( (uFlags
& CWP_SKIPTRANSPARENT
) &&
683 (wnd
->dwExStyle
& WS_EX_TRANSPARENT
) );
686 retvalue
= wnd
->hwndSelf
;
691 WIN_UpdateWndPtr(&wnd
,wnd
->next
);
693 retvalue
= hwndParent
;
695 WIN_ReleaseWndPtr(wnd
);
700 /*******************************************************************
701 * WINPOS_GetWinOffset
703 * Calculate the offset between the origin of the two windows. Used
704 * to implement MapWindowPoints.
706 static void WINPOS_GetWinOffset( HWND hwndFrom
, HWND hwndTo
,
711 offset
->x
= offset
->y
= 0;
712 if (hwndFrom
== hwndTo
) return;
714 /* Translate source window origin to screen coords */
717 if (!(wndPtr
= WIN_FindWndPtr( hwndFrom
)))
719 ERR("bad hwndFrom = %04x\n",hwndFrom
);
722 while (wndPtr
->parent
)
724 offset
->x
+= wndPtr
->rectClient
.left
;
725 offset
->y
+= wndPtr
->rectClient
.top
;
726 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->parent
);
728 WIN_ReleaseWndPtr(wndPtr
);
731 /* Translate origin to destination window coords */
734 if (!(wndPtr
= WIN_FindWndPtr( hwndTo
)))
736 ERR("bad hwndTo = %04x\n", hwndTo
);
739 while (wndPtr
->parent
)
741 offset
->x
-= wndPtr
->rectClient
.left
;
742 offset
->y
-= wndPtr
->rectClient
.top
;
743 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->parent
);
745 WIN_ReleaseWndPtr(wndPtr
);
750 /*******************************************************************
751 * MapWindowPoints16 (USER.258)
753 void WINAPI
MapWindowPoints16( HWND16 hwndFrom
, HWND16 hwndTo
,
754 LPPOINT16 lppt
, UINT16 count
)
758 WINPOS_GetWinOffset( hwndFrom
, hwndTo
, &offset
);
768 /*******************************************************************
769 * MapWindowPoints (USER32.386)
771 INT WINAPI
MapWindowPoints( HWND hwndFrom
, HWND hwndTo
,
772 LPPOINT lppt
, UINT count
)
776 WINPOS_GetWinOffset( hwndFrom
, hwndTo
, &offset
);
783 return MAKELONG( LOWORD(offset
.x
), LOWORD(offset
.y
) );
787 /***********************************************************************
788 * IsIconic16 (USER.31)
790 BOOL16 WINAPI
IsIconic16(HWND16 hWnd
)
792 return IsIconic(hWnd
);
796 /***********************************************************************
797 * IsIconic (USER32.345)
799 BOOL WINAPI
IsIconic(HWND hWnd
)
802 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
803 if (wndPtr
== NULL
) return FALSE
;
804 retvalue
= (wndPtr
->dwStyle
& WS_MINIMIZE
) != 0;
805 WIN_ReleaseWndPtr(wndPtr
);
810 /***********************************************************************
811 * IsZoomed (USER.272)
813 BOOL16 WINAPI
IsZoomed16(HWND16 hWnd
)
815 return IsZoomed(hWnd
);
819 /***********************************************************************
820 * IsZoomed (USER.352)
822 BOOL WINAPI
IsZoomed(HWND hWnd
)
825 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
826 if (wndPtr
== NULL
) return FALSE
;
827 retvalue
= (wndPtr
->dwStyle
& WS_MAXIMIZE
) != 0;
828 WIN_ReleaseWndPtr(wndPtr
);
833 /*******************************************************************
834 * GetActiveWindow (USER.60)
836 HWND16 WINAPI
GetActiveWindow16(void)
838 return (HWND16
)GetActiveWindow();
841 /*******************************************************************
842 * GetActiveWindow (USER32.205)
844 HWND WINAPI
GetActiveWindow(void)
846 MESSAGEQUEUE
*pCurMsgQ
= 0;
849 /* Get the messageQ for the current thread */
850 if (!(pCurMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( GetFastQueue16() )))
852 WARN("\tCurrent message queue not found. Exiting!\n" );
856 /* Return the current active window from the perQ data of the current message Q */
857 hwndActive
= PERQDATA_GetActiveWnd( pCurMsgQ
->pQData
);
859 QUEUE_Unlock( pCurMsgQ
);
864 /*******************************************************************
867 static BOOL
WINPOS_CanActivate(WND
* pWnd
)
869 if( pWnd
&& ( (pWnd
->dwStyle
& (WS_DISABLED
| WS_VISIBLE
| WS_CHILD
))
870 == WS_VISIBLE
) ) return TRUE
;
875 /*******************************************************************
876 * SetActiveWindow16 (USER.59)
878 HWND16 WINAPI
SetActiveWindow16( HWND16 hwnd
)
880 return SetActiveWindow(hwnd
);
884 /*******************************************************************
885 * SetActiveWindow (USER32.463)
887 HWND WINAPI
SetActiveWindow( HWND hwnd
)
890 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
891 MESSAGEQUEUE
*pMsgQ
= 0, *pCurMsgQ
= 0;
893 if (!wndPtr
|| (wndPtr
->dwStyle
& (WS_DISABLED
| WS_CHILD
)))
899 /* Get the messageQ for the current thread */
900 if (!(pCurMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( GetFastQueue16() )))
902 WARN("\tCurrent message queue not found. Exiting!\n" );
906 /* Retrieve the message queue associated with this window */
907 pMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( wndPtr
->hmemTaskQ
);
910 WARN("\tWindow message queue not found. Exiting!\n" );
914 /* Make sure that the window is associated with the calling threads
915 * message queue. It must share the same perQ data.
918 if ( pCurMsgQ
->pQData
!= pMsgQ
->pQData
)
921 /* Save current active window */
922 prev
= PERQDATA_GetActiveWnd( pMsgQ
->pQData
);
924 WINPOS_SetActiveWindow( hwnd
, 0, 0 );
927 /* Unlock the queues before returning */
929 QUEUE_Unlock( pMsgQ
);
931 QUEUE_Unlock( pCurMsgQ
);
934 WIN_ReleaseWndPtr(wndPtr
);
939 /*******************************************************************
940 * GetForegroundWindow16 (USER.608)
942 HWND16 WINAPI
GetForegroundWindow16(void)
944 return (HWND16
)GetForegroundWindow();
948 /*******************************************************************
949 * SetForegroundWindow16 (USER.609)
951 BOOL16 WINAPI
SetForegroundWindow16( HWND16 hwnd
)
953 return SetForegroundWindow( hwnd
);
957 /*******************************************************************
958 * GetForegroundWindow (USER32.241)
960 HWND WINAPI
GetForegroundWindow(void)
964 /* Get the foreground window (active window of hActiveQueue) */
967 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
969 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
971 QUEUE_Unlock( pActiveQueue
);
977 /*******************************************************************
978 * SetForegroundWindow (USER32.482)
980 BOOL WINAPI
SetForegroundWindow( HWND hwnd
)
982 return WINPOS_ChangeActiveWindow( hwnd
, FALSE
);
986 /*******************************************************************
987 * AllowSetForegroundWindow (USER32)
989 BOOL WINAPI
AllowSetForegroundWindow( DWORD procid
)
991 /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
992 * implemented, then fix this function. */
997 /*******************************************************************
998 * LockSetForegroundWindow (USER32)
1000 BOOL WINAPI
LockSetForegroundWindow( UINT lockcode
)
1002 /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
1003 * implemented, then fix this function. */
1008 /*******************************************************************
1009 * GetShellWindow16 (USER.600)
1011 HWND16 WINAPI
GetShellWindow16(void)
1013 return GetShellWindow();
1016 /*******************************************************************
1017 * SetShellWindow (USER32.504)
1019 HWND WINAPI
SetShellWindow(HWND hwndshell
)
1020 { WARN("(hWnd=%08x) semi stub\n",hwndshell
);
1022 hGlobalShellWindow
= hwndshell
;
1023 return hGlobalShellWindow
;
1027 /*******************************************************************
1028 * GetShellWindow (USER32.287)
1030 HWND WINAPI
GetShellWindow(void)
1031 { WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow
);
1033 return hGlobalShellWindow
;
1037 /***********************************************************************
1038 * BringWindowToTop16 (USER.45)
1040 BOOL16 WINAPI
BringWindowToTop16( HWND16 hwnd
)
1042 return BringWindowToTop(hwnd
);
1046 /***********************************************************************
1047 * BringWindowToTop (USER32.11)
1049 BOOL WINAPI
BringWindowToTop( HWND hwnd
)
1051 return SetWindowPos( hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
);
1055 /***********************************************************************
1056 * MoveWindow16 (USER.56)
1058 BOOL16 WINAPI
MoveWindow16( HWND16 hwnd
, INT16 x
, INT16 y
, INT16 cx
, INT16 cy
,
1061 return MoveWindow(hwnd
,x
,y
,cx
,cy
,repaint
);
1065 /***********************************************************************
1066 * MoveWindow (USER32.399)
1068 BOOL WINAPI
MoveWindow( HWND hwnd
, INT x
, INT y
, INT cx
, INT cy
,
1071 int flags
= SWP_NOZORDER
| SWP_NOACTIVATE
;
1072 if (!repaint
) flags
|= SWP_NOREDRAW
;
1073 TRACE("%04x %d,%d %dx%d %d\n",
1074 hwnd
, x
, y
, cx
, cy
, repaint
);
1075 return SetWindowPos( hwnd
, 0, x
, y
, cx
, cy
, flags
);
1078 /***********************************************************************
1079 * WINPOS_InitInternalPos
1081 static LPINTERNALPOS
WINPOS_InitInternalPos( WND
* wnd
, POINT pt
,
1082 LPRECT restoreRect
)
1084 LPINTERNALPOS lpPos
= (LPINTERNALPOS
) GetPropA( wnd
->hwndSelf
,
1088 /* this happens when the window is minimized/maximized
1089 * for the first time (rectWindow is not adjusted yet) */
1091 lpPos
= HeapAlloc( SystemHeap
, 0, sizeof(INTERNALPOS
) );
1092 if( !lpPos
) return NULL
;
1094 SetPropA( wnd
->hwndSelf
, atomInternalPos
, (HANDLE
)lpPos
);
1095 lpPos
->hwndIconTitle
= 0; /* defer until needs to be shown */
1096 CONV_RECT32TO16( &wnd
->rectWindow
, &lpPos
->rectNormal
);
1097 *(UINT
*)&lpPos
->ptIconPos
= *(UINT
*)&lpPos
->ptMaxPos
= 0xFFFFFFFF;
1100 if( wnd
->dwStyle
& WS_MINIMIZE
)
1101 CONV_POINT32TO16( &pt
, &lpPos
->ptIconPos
);
1102 else if( wnd
->dwStyle
& WS_MAXIMIZE
)
1103 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1104 else if( restoreRect
)
1105 CONV_RECT32TO16( restoreRect
, &lpPos
->rectNormal
);
1110 /***********************************************************************
1111 * WINPOS_RedrawIconTitle
1113 BOOL
WINPOS_RedrawIconTitle( HWND hWnd
)
1115 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)GetPropA( hWnd
, atomInternalPos
);
1118 if( lpPos
->hwndIconTitle
)
1120 SendMessageA( lpPos
->hwndIconTitle
, WM_SHOWWINDOW
, TRUE
, 0);
1121 InvalidateRect( lpPos
->hwndIconTitle
, NULL
, TRUE
);
1128 /***********************************************************************
1129 * WINPOS_ShowIconTitle
1131 BOOL
WINPOS_ShowIconTitle( WND
* pWnd
, BOOL bShow
)
1133 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)GetPropA( pWnd
->hwndSelf
, atomInternalPos
);
1135 if( lpPos
&& !(pWnd
->dwExStyle
& WS_EX_MANAGED
))
1137 HWND16 hWnd
= lpPos
->hwndIconTitle
;
1139 TRACE("0x%04x %i\n", pWnd
->hwndSelf
, (bShow
!= 0) );
1142 lpPos
->hwndIconTitle
= hWnd
= ICONTITLE_Create( pWnd
);
1145 if( ( pWnd
= WIN_FindWndPtr(hWnd
) ) != NULL
)
1147 if( !(pWnd
->dwStyle
& WS_VISIBLE
) )
1149 SendMessageA( hWnd
, WM_SHOWWINDOW
, TRUE
, 0 );
1150 SetWindowPos( hWnd
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
1151 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_SHOWWINDOW
);
1153 WIN_ReleaseWndPtr(pWnd
);
1156 else ShowWindow( hWnd
, SW_HIDE
);
1161 /*******************************************************************
1162 * WINPOS_GetMinMaxInfo
1164 * Get the minimized and maximized information for a window.
1166 void WINPOS_GetMinMaxInfo( WND
*wndPtr
, POINT
*maxSize
, POINT
*maxPos
,
1167 POINT
*minTrack
, POINT
*maxTrack
)
1169 LPINTERNALPOS lpPos
;
1173 /* Compute default values */
1175 MinMax
.ptMaxSize
.x
= GetSystemMetrics(SM_CXSCREEN
);
1176 MinMax
.ptMaxSize
.y
= GetSystemMetrics(SM_CYSCREEN
);
1177 MinMax
.ptMinTrackSize
.x
= GetSystemMetrics(SM_CXMINTRACK
);
1178 MinMax
.ptMinTrackSize
.y
= GetSystemMetrics(SM_CYMINTRACK
);
1179 MinMax
.ptMaxTrackSize
.x
= GetSystemMetrics(SM_CXSCREEN
);
1180 MinMax
.ptMaxTrackSize
.y
= GetSystemMetrics(SM_CYSCREEN
);
1182 if (wndPtr
->dwExStyle
& WS_EX_MANAGED
) xinc
= yinc
= 0;
1183 else if (HAS_DLGFRAME( wndPtr
->dwStyle
, wndPtr
->dwExStyle
))
1185 xinc
= GetSystemMetrics(SM_CXDLGFRAME
);
1186 yinc
= GetSystemMetrics(SM_CYDLGFRAME
);
1191 if (HAS_THICKFRAME(wndPtr
->dwStyle
))
1193 xinc
+= GetSystemMetrics(SM_CXFRAME
);
1194 yinc
+= GetSystemMetrics(SM_CYFRAME
);
1196 if (wndPtr
->dwStyle
& WS_BORDER
)
1198 xinc
+= GetSystemMetrics(SM_CXBORDER
);
1199 yinc
+= GetSystemMetrics(SM_CYBORDER
);
1202 MinMax
.ptMaxSize
.x
+= 2 * xinc
;
1203 MinMax
.ptMaxSize
.y
+= 2 * yinc
;
1205 lpPos
= (LPINTERNALPOS
)GetPropA( wndPtr
->hwndSelf
, atomInternalPos
);
1206 if( lpPos
&& !EMPTYPOINT(lpPos
->ptMaxPos
) )
1207 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &MinMax
.ptMaxPosition
);
1210 MinMax
.ptMaxPosition
.x
= -xinc
;
1211 MinMax
.ptMaxPosition
.y
= -yinc
;
1214 SendMessageA( wndPtr
->hwndSelf
, WM_GETMINMAXINFO
, 0, (LPARAM
)&MinMax
);
1216 /* Some sanity checks */
1218 TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1219 MinMax
.ptMaxSize
.x
, MinMax
.ptMaxSize
.y
,
1220 MinMax
.ptMaxPosition
.x
, MinMax
.ptMaxPosition
.y
,
1221 MinMax
.ptMaxTrackSize
.x
, MinMax
.ptMaxTrackSize
.y
,
1222 MinMax
.ptMinTrackSize
.x
, MinMax
.ptMinTrackSize
.y
);
1223 MinMax
.ptMaxTrackSize
.x
= max( MinMax
.ptMaxTrackSize
.x
,
1224 MinMax
.ptMinTrackSize
.x
);
1225 MinMax
.ptMaxTrackSize
.y
= max( MinMax
.ptMaxTrackSize
.y
,
1226 MinMax
.ptMinTrackSize
.y
);
1228 if (maxSize
) *maxSize
= MinMax
.ptMaxSize
;
1229 if (maxPos
) *maxPos
= MinMax
.ptMaxPosition
;
1230 if (minTrack
) *minTrack
= MinMax
.ptMinTrackSize
;
1231 if (maxTrack
) *maxTrack
= MinMax
.ptMaxTrackSize
;
1234 /***********************************************************************
1235 * WINPOS_MinMaximize
1237 * Fill in lpRect and return additional flags to be used with SetWindowPos().
1238 * This function assumes that 'cmd' is different from the current window
1241 UINT
WINPOS_MinMaximize( WND
* wndPtr
, UINT16 cmd
, LPRECT16 lpRect
)
1245 LPINTERNALPOS lpPos
;
1247 TRACE("0x%04x %u\n", wndPtr
->hwndSelf
, cmd
);
1249 size
.x
= wndPtr
->rectWindow
.left
; size
.y
= wndPtr
->rectWindow
.top
;
1250 lpPos
= WINPOS_InitInternalPos( wndPtr
, size
, &wndPtr
->rectWindow
);
1252 if (lpPos
&& !HOOK_CallHooks16(WH_CBT
, HCBT_MINMAX
, wndPtr
->hwndSelf
, cmd
))
1254 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1256 if( !SendMessageA( wndPtr
->hwndSelf
, WM_QUERYOPEN
, 0, 0L ) )
1257 return (SWP_NOSIZE
| SWP_NOMOVE
);
1258 swpFlags
|= SWP_NOCOPYBITS
;
1263 if( wndPtr
->dwStyle
& WS_MAXIMIZE
)
1265 wndPtr
->flags
|= WIN_RESTORE_MAX
;
1266 wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
1269 wndPtr
->flags
&= ~WIN_RESTORE_MAX
;
1270 wndPtr
->dwStyle
|= WS_MINIMIZE
;
1272 if( wndPtr
->flags
& WIN_NATIVE
)
1273 if( wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, TRUE
) )
1274 swpFlags
|= MINMAX_NOSWP
;
1276 lpPos
->ptIconPos
= WINPOS_FindIconPos( wndPtr
, lpPos
->ptIconPos
);
1278 SetRect16( lpRect
, lpPos
->ptIconPos
.x
, lpPos
->ptIconPos
.y
,
1279 GetSystemMetrics(SM_CXICON
), GetSystemMetrics(SM_CYICON
) );
1280 swpFlags
|= SWP_NOCOPYBITS
;
1284 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &pt
);
1285 WINPOS_GetMinMaxInfo( wndPtr
, &size
, &pt
, NULL
, NULL
);
1286 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1288 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1290 if( wndPtr
->flags
& WIN_NATIVE
)
1291 wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, FALSE
);
1293 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
1294 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
1296 wndPtr
->dwStyle
|= WS_MAXIMIZE
;
1298 SetRect16( lpRect
, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
,
1303 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1305 if( wndPtr
->flags
& WIN_NATIVE
)
1306 if( wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, FALSE
) )
1307 swpFlags
|= MINMAX_NOSWP
;
1309 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
1310 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
1312 if( wndPtr
->flags
& WIN_RESTORE_MAX
)
1314 /* Restore to maximized position */
1315 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &pt
);
1316 WINPOS_GetMinMaxInfo( wndPtr
, &size
, &pt
, NULL
, NULL
);
1317 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1318 wndPtr
->dwStyle
|= WS_MAXIMIZE
;
1319 SetRect16( lpRect
, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
, size
.x
, size
.y
);
1324 if( !(wndPtr
->dwStyle
& WS_MAXIMIZE
) ) return (UINT16
)(-1);
1325 else wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
1327 /* Restore to normal position */
1329 *lpRect
= lpPos
->rectNormal
;
1330 lpRect
->right
-= lpRect
->left
;
1331 lpRect
->bottom
-= lpRect
->top
;
1335 } else swpFlags
|= SWP_NOSIZE
| SWP_NOMOVE
;
1339 /***********************************************************************
1340 * ShowWindowAsync (USER32.535)
1342 * doesn't wait; returns immediately.
1343 * used by threads to toggle windows in other (possibly hanging) threads
1345 BOOL WINAPI
ShowWindowAsync( HWND hwnd
, INT cmd
)
1347 /* FIXME: does ShowWindow() return immediately ? */
1348 return ShowWindow(hwnd
, cmd
);
1352 /***********************************************************************
1353 * ShowWindow16 (USER.42)
1355 BOOL16 WINAPI
ShowWindow16( HWND16 hwnd
, INT16 cmd
)
1357 return ShowWindow(hwnd
,cmd
);
1361 /***********************************************************************
1362 * ShowWindow (USER32.534)
1364 BOOL WINAPI
ShowWindow( HWND hwnd
, INT cmd
)
1366 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
1367 BOOL wasVisible
, showFlag
;
1368 RECT16 newPos
= {0, 0, 0, 0};
1371 if (!wndPtr
) return FALSE
;
1373 TRACE("hwnd=%04x, cmd=%d\n", hwnd
, cmd
);
1375 wasVisible
= (wndPtr
->dwStyle
& WS_VISIBLE
) != 0;
1380 if (!wasVisible
) goto END
;;
1381 swp
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
|
1382 SWP_NOACTIVATE
| SWP_NOZORDER
;
1385 case SW_SHOWMINNOACTIVE
:
1386 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1388 case SW_SHOWMINIMIZED
:
1389 swp
|= SWP_SHOWWINDOW
;
1392 swp
|= SWP_FRAMECHANGED
;
1393 if( !(wndPtr
->dwStyle
& WS_MINIMIZE
) )
1394 swp
|= WINPOS_MinMaximize( wndPtr
, SW_MINIMIZE
, &newPos
);
1395 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1398 case SW_SHOWMAXIMIZED
: /* same as SW_MAXIMIZE */
1399 swp
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
1400 if( !(wndPtr
->dwStyle
& WS_MAXIMIZE
) )
1401 swp
|= WINPOS_MinMaximize( wndPtr
, SW_MAXIMIZE
, &newPos
);
1402 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1406 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1409 swp
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
1412 * ShowWindow has a little peculiar behavior that if the
1413 * window is already the topmost window, it will not
1416 if (GetTopWindow((HWND
)0)==hwnd
&& (wasVisible
|| GetActiveWindow() == hwnd
))
1417 swp
|= SWP_NOACTIVATE
;
1421 case SW_SHOWNOACTIVATE
:
1422 swp
|= SWP_NOZORDER
;
1423 if (GetActiveWindow()) swp
|= SWP_NOACTIVATE
;
1425 case SW_SHOWNORMAL
: /* same as SW_NORMAL: */
1426 case SW_SHOWDEFAULT
: /* FIXME: should have its own handler */
1428 swp
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
1430 if( wndPtr
->dwStyle
& (WS_MINIMIZE
| WS_MAXIMIZE
) )
1431 swp
|= WINPOS_MinMaximize( wndPtr
, SW_RESTORE
, &newPos
);
1432 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1436 showFlag
= (cmd
!= SW_HIDE
);
1437 if (showFlag
!= wasVisible
)
1439 SendMessageA( hwnd
, WM_SHOWWINDOW
, showFlag
, 0 );
1440 if (!IsWindow( hwnd
)) goto END
;
1443 if ((wndPtr
->dwStyle
& WS_CHILD
) &&
1444 !IsWindowVisible( wndPtr
->parent
->hwndSelf
) &&
1445 (swp
& (SWP_NOSIZE
| SWP_NOMOVE
)) == (SWP_NOSIZE
| SWP_NOMOVE
) )
1447 /* Don't call SetWindowPos() on invisible child windows */
1448 if (cmd
== SW_HIDE
) wndPtr
->dwStyle
&= ~WS_VISIBLE
;
1449 else wndPtr
->dwStyle
|= WS_VISIBLE
;
1453 /* We can't activate a child window */
1454 if ((wndPtr
->dwStyle
& WS_CHILD
) &&
1455 !(wndPtr
->dwExStyle
& WS_EX_MDICHILD
))
1456 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1457 if (!(swp
& MINMAX_NOSWP
))
1459 SetWindowPos( hwnd
, HWND_TOP
, newPos
.left
, newPos
.top
,
1460 newPos
.right
, newPos
.bottom
, LOWORD(swp
) );
1463 /* FIXME: This will cause the window to be activated irrespective
1464 * of whether it is owned by the same thread. Has to be done
1468 if (hwnd
== GetActiveWindow())
1469 WINPOS_ActivateOtherWindow(wndPtr
);
1471 /* Revert focus to parent */
1472 if (hwnd
== GetFocus() || IsChild(hwnd
, GetFocus()))
1473 SetFocus( GetParent(hwnd
) );
1476 if (!IsWindow( hwnd
)) goto END
;
1477 else if( wndPtr
->dwStyle
& WS_MINIMIZE
) WINPOS_ShowIconTitle( wndPtr
, TRUE
);
1480 if (wndPtr
->flags
& WIN_NEED_SIZE
)
1482 /* should happen only in CreateWindowEx() */
1483 int wParam
= SIZE_RESTORED
;
1485 wndPtr
->flags
&= ~WIN_NEED_SIZE
;
1486 if (wndPtr
->dwStyle
& WS_MAXIMIZE
) wParam
= SIZE_MAXIMIZED
;
1487 else if (wndPtr
->dwStyle
& WS_MINIMIZE
) wParam
= SIZE_MINIMIZED
;
1488 SendMessageA( hwnd
, WM_SIZE
, wParam
,
1489 MAKELONG(wndPtr
->rectClient
.right
-wndPtr
->rectClient
.left
,
1490 wndPtr
->rectClient
.bottom
-wndPtr
->rectClient
.top
));
1491 SendMessageA( hwnd
, WM_MOVE
, 0,
1492 MAKELONG(wndPtr
->rectClient
.left
, wndPtr
->rectClient
.top
) );
1496 WIN_ReleaseWndPtr(wndPtr
);
1501 /***********************************************************************
1502 * GetInternalWindowPos16 (USER.460)
1504 UINT16 WINAPI
GetInternalWindowPos16( HWND16 hwnd
, LPRECT16 rectWnd
,
1507 WINDOWPLACEMENT16 wndpl
;
1508 if (GetWindowPlacement16( hwnd
, &wndpl
))
1510 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
1511 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
1512 return wndpl
.showCmd
;
1518 /***********************************************************************
1519 * GetInternalWindowPos (USER32.245)
1521 UINT WINAPI
GetInternalWindowPos( HWND hwnd
, LPRECT rectWnd
,
1524 WINDOWPLACEMENT wndpl
;
1525 if (GetWindowPlacement( hwnd
, &wndpl
))
1527 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
1528 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
1529 return wndpl
.showCmd
;
1534 /***********************************************************************
1535 * GetWindowPlacement16 (USER.370)
1537 BOOL16 WINAPI
GetWindowPlacement16( HWND16 hwnd
, WINDOWPLACEMENT16
*wndpl
)
1539 WND
*pWnd
= WIN_FindWndPtr( hwnd
);
1540 LPINTERNALPOS lpPos
;
1542 if(!pWnd
) return FALSE
;
1544 lpPos
= (LPINTERNALPOS
)WINPOS_InitInternalPos( pWnd
,
1545 *(LPPOINT
)&pWnd
->rectWindow
.left
, &pWnd
->rectWindow
);
1546 wndpl
->length
= sizeof(*wndpl
);
1547 if( pWnd
->dwStyle
& WS_MINIMIZE
)
1548 wndpl
->showCmd
= SW_SHOWMINIMIZED
;
1550 wndpl
->showCmd
= ( pWnd
->dwStyle
& WS_MAXIMIZE
)
1551 ? SW_SHOWMAXIMIZED
: SW_SHOWNORMAL
;
1552 if( pWnd
->flags
& WIN_RESTORE_MAX
)
1553 wndpl
->flags
= WPF_RESTORETOMAXIMIZED
;
1556 wndpl
->ptMinPosition
= lpPos
->ptIconPos
;
1557 wndpl
->ptMaxPosition
= lpPos
->ptMaxPos
;
1558 wndpl
->rcNormalPosition
= lpPos
->rectNormal
;
1560 WIN_ReleaseWndPtr(pWnd
);
1565 /***********************************************************************
1566 * GetWindowPlacement (USER32.307)
1569 * Fails if wndpl->length of Win95 (!) apps is invalid.
1571 BOOL WINAPI
GetWindowPlacement( HWND hwnd
, WINDOWPLACEMENT
*pwpl32
)
1575 WINDOWPLACEMENT16 wpl
;
1576 wpl
.length
= sizeof(wpl
);
1577 if( GetWindowPlacement16( hwnd
, &wpl
) )
1579 pwpl32
->length
= sizeof(*pwpl32
);
1580 pwpl32
->flags
= wpl
.flags
;
1581 pwpl32
->showCmd
= wpl
.showCmd
;
1582 CONV_POINT16TO32( &wpl
.ptMinPosition
, &pwpl32
->ptMinPosition
);
1583 CONV_POINT16TO32( &wpl
.ptMaxPosition
, &pwpl32
->ptMaxPosition
);
1584 CONV_RECT16TO32( &wpl
.rcNormalPosition
, &pwpl32
->rcNormalPosition
);
1592 /***********************************************************************
1593 * WINPOS_SetPlacement
1595 static BOOL
WINPOS_SetPlacement( HWND hwnd
, const WINDOWPLACEMENT16
*wndpl
,
1598 WND
*pWnd
= WIN_FindWndPtr( hwnd
);
1601 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)WINPOS_InitInternalPos( pWnd
,
1602 *(LPPOINT
)&pWnd
->rectWindow
.left
, &pWnd
->rectWindow
);
1604 if( flags
& PLACE_MIN
) lpPos
->ptIconPos
= wndpl
->ptMinPosition
;
1605 if( flags
& PLACE_MAX
) lpPos
->ptMaxPos
= wndpl
->ptMaxPosition
;
1606 if( flags
& PLACE_RECT
) lpPos
->rectNormal
= wndpl
->rcNormalPosition
;
1608 if( pWnd
->dwStyle
& WS_MINIMIZE
)
1610 WINPOS_ShowIconTitle( pWnd
, FALSE
);
1611 if( wndpl
->flags
& WPF_SETMINPOSITION
&& !EMPTYPOINT(lpPos
->ptIconPos
))
1612 SetWindowPos( hwnd
, 0, lpPos
->ptIconPos
.x
, lpPos
->ptIconPos
.y
,
1613 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1615 else if( pWnd
->dwStyle
& WS_MAXIMIZE
)
1617 if( !EMPTYPOINT(lpPos
->ptMaxPos
) )
1618 SetWindowPos( hwnd
, 0, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
,
1619 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1621 else if( flags
& PLACE_RECT
)
1622 SetWindowPos( hwnd
, 0, lpPos
->rectNormal
.left
, lpPos
->rectNormal
.top
,
1623 lpPos
->rectNormal
.right
- lpPos
->rectNormal
.left
,
1624 lpPos
->rectNormal
.bottom
- lpPos
->rectNormal
.top
,
1625 SWP_NOZORDER
| SWP_NOACTIVATE
);
1627 ShowWindow( hwnd
, wndpl
->showCmd
);
1628 if( IsWindow(hwnd
) && pWnd
->dwStyle
& WS_MINIMIZE
)
1630 if( pWnd
->dwStyle
& WS_VISIBLE
) WINPOS_ShowIconTitle( pWnd
, TRUE
);
1632 /* SDK: ...valid only the next time... */
1633 if( wndpl
->flags
& WPF_RESTORETOMAXIMIZED
) pWnd
->flags
|= WIN_RESTORE_MAX
;
1635 WIN_ReleaseWndPtr(pWnd
);
1642 /***********************************************************************
1643 * SetWindowPlacement16 (USER.371)
1645 BOOL16 WINAPI
SetWindowPlacement16(HWND16 hwnd
, const WINDOWPLACEMENT16
*wndpl
)
1647 return WINPOS_SetPlacement( hwnd
, wndpl
,
1648 PLACE_MIN
| PLACE_MAX
| PLACE_RECT
);
1651 /***********************************************************************
1652 * SetWindowPlacement (USER32.519)
1655 * Fails if wndpl->length of Win95 (!) apps is invalid.
1657 BOOL WINAPI
SetWindowPlacement( HWND hwnd
, const WINDOWPLACEMENT
*pwpl32
)
1661 WINDOWPLACEMENT16 wpl
;
1663 wpl
.length
= sizeof(WINDOWPLACEMENT16
);
1664 wpl
.flags
= pwpl32
->flags
;
1665 wpl
.showCmd
= pwpl32
->showCmd
;
1666 wpl
.ptMinPosition
.x
= pwpl32
->ptMinPosition
.x
;
1667 wpl
.ptMinPosition
.y
= pwpl32
->ptMinPosition
.y
;
1668 wpl
.ptMaxPosition
.x
= pwpl32
->ptMaxPosition
.x
;
1669 wpl
.ptMaxPosition
.y
= pwpl32
->ptMaxPosition
.y
;
1670 wpl
.rcNormalPosition
.left
= pwpl32
->rcNormalPosition
.left
;
1671 wpl
.rcNormalPosition
.top
= pwpl32
->rcNormalPosition
.top
;
1672 wpl
.rcNormalPosition
.right
= pwpl32
->rcNormalPosition
.right
;
1673 wpl
.rcNormalPosition
.bottom
= pwpl32
->rcNormalPosition
.bottom
;
1675 return WINPOS_SetPlacement( hwnd
, &wpl
, PLACE_MIN
| PLACE_MAX
| PLACE_RECT
);
1681 /***********************************************************************
1682 * SetInternalWindowPos16 (USER.461)
1684 void WINAPI
SetInternalWindowPos16( HWND16 hwnd
, UINT16 showCmd
,
1685 LPRECT16 rect
, LPPOINT16 pt
)
1687 if( IsWindow16(hwnd
) )
1689 WINDOWPLACEMENT16 wndpl
;
1692 wndpl
.length
= sizeof(wndpl
);
1693 wndpl
.showCmd
= showCmd
;
1694 wndpl
.flags
= flags
= 0;
1699 wndpl
.flags
|= WPF_SETMINPOSITION
;
1700 wndpl
.ptMinPosition
= *pt
;
1704 flags
|= PLACE_RECT
;
1705 wndpl
.rcNormalPosition
= *rect
;
1707 WINPOS_SetPlacement( hwnd
, &wndpl
, flags
);
1712 /***********************************************************************
1713 * SetInternalWindowPos (USER32.483)
1715 void WINAPI
SetInternalWindowPos( HWND hwnd
, UINT showCmd
,
1716 LPRECT rect
, LPPOINT pt
)
1718 if( IsWindow(hwnd
) )
1720 WINDOWPLACEMENT16 wndpl
;
1723 wndpl
.length
= sizeof(wndpl
);
1724 wndpl
.showCmd
= showCmd
;
1725 wndpl
.flags
= flags
= 0;
1730 wndpl
.flags
|= WPF_SETMINPOSITION
;
1731 CONV_POINT32TO16( pt
, &wndpl
.ptMinPosition
);
1735 flags
|= PLACE_RECT
;
1736 CONV_RECT32TO16( rect
, &wndpl
.rcNormalPosition
);
1738 WINPOS_SetPlacement( hwnd
, &wndpl
, flags
);
1742 /*******************************************************************
1743 * WINPOS_SetActiveWindow
1745 * SetActiveWindow() back-end. This is the only function that
1746 * can assign active status to a window. It must be called only
1747 * for the top level windows.
1749 BOOL
WINPOS_SetActiveWindow( HWND hWnd
, BOOL fMouse
, BOOL fChangeFocus
)
1751 CBTACTIVATESTRUCT16
* cbtStruct
;
1752 WND
* wndPtr
=0, *wndTemp
;
1753 HQUEUE16 hOldActiveQueue
, hNewActiveQueue
;
1754 MESSAGEQUEUE
*pOldActiveQueue
= 0, *pNewActiveQueue
= 0;
1756 HWND hwndActive
= 0;
1759 TRACE("(%04x, %d, %d)\n", hWnd
, fMouse
, fChangeFocus
);
1761 /* Get current active window from the active queue */
1764 pOldActiveQueue
= QUEUE_Lock( hActiveQueue
);
1765 if ( pOldActiveQueue
)
1766 hwndActive
= PERQDATA_GetActiveWnd( pOldActiveQueue
->pQData
);
1769 /* paranoid checks */
1770 if( hWnd
== GetDesktopWindow() || (bRet
= (hWnd
== hwndActive
)) )
1773 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1776 wndPtr
= WIN_FindWndPtr(hWnd
);
1777 hOldActiveQueue
= hActiveQueue
;
1779 if( (wndTemp
= WIN_FindWndPtr(hwndActive
)) )
1781 wIconized
= HIWORD(wndTemp
->dwStyle
& WS_MINIMIZE
);
1782 WIN_ReleaseWndPtr(wndTemp
);
1785 TRACE("no current active window.\n");
1787 /* call CBT hook chain */
1788 if ((cbtStruct
= SEGPTR_NEW(CBTACTIVATESTRUCT16
)))
1790 cbtStruct
->fMouse
= fMouse
;
1791 cbtStruct
->hWndActive
= hwndActive
;
1792 bRet
= (BOOL
)HOOK_CallHooks16( WH_CBT
, HCBT_ACTIVATE
, (WPARAM16
)hWnd
,
1793 (LPARAM
)SEGPTR_GET(cbtStruct
) );
1794 SEGPTR_FREE(cbtStruct
);
1795 if (bRet
) goto CLEANUP_END
;
1798 /* set prev active wnd to current active wnd and send notification */
1799 if ((hwndPrevActive
= hwndActive
) && IsWindow(hwndPrevActive
))
1801 MESSAGEQUEUE
*pTempActiveQueue
= 0;
1803 if (!SendMessageA( hwndPrevActive
, WM_NCACTIVATE
, FALSE
, 0 ))
1805 if (GetSysModalWindow16() != hWnd
)
1807 /* disregard refusal if hWnd is sysmodal */
1810 SendMessageA( hwndPrevActive
, WM_ACTIVATE
,
1811 MAKEWPARAM( WA_INACTIVE
, wIconized
),
1814 /* check if something happened during message processing
1815 * (global active queue may have changed)
1817 pTempActiveQueue
= QUEUE_Lock( hActiveQueue
);
1818 if(!pTempActiveQueue
)
1821 hwndActive
= PERQDATA_GetActiveWnd( pTempActiveQueue
->pQData
);
1822 QUEUE_Unlock( pTempActiveQueue
);
1823 if( hwndPrevActive
!= hwndActive
)
1827 /* Set new active window in the message queue */
1831 pNewActiveQueue
= QUEUE_Lock( wndPtr
->hmemTaskQ
);
1832 if ( pNewActiveQueue
)
1833 PERQDATA_SetActiveWnd( pNewActiveQueue
->pQData
, hwndActive
);
1835 else /* have to do this or MDI frame activation goes to hell */
1836 if( pOldActiveQueue
)
1837 PERQDATA_SetActiveWnd( pOldActiveQueue
->pQData
, 0 );
1839 /* send palette messages */
1840 if (hWnd
&& SendMessage16( hWnd
, WM_QUERYNEWPALETTE
, 0, 0L))
1841 SendMessage16((HWND16
)-1, WM_PALETTEISCHANGING
, (WPARAM16
)hWnd
, 0L );
1843 /* if prev wnd is minimized redraw icon title */
1844 if( IsIconic( hwndPrevActive
) ) WINPOS_RedrawIconTitle(hwndPrevActive
);
1846 /* managed windows will get ConfigureNotify event */
1847 if (wndPtr
&& !(wndPtr
->dwStyle
& WS_CHILD
) && !(wndPtr
->dwExStyle
& WS_EX_MANAGED
))
1849 /* check Z-order and bring hWnd to the top */
1850 for (wndTemp
= WIN_LockWndPtr(WIN_GetDesktop()->child
); wndTemp
; WIN_UpdateWndPtr(&wndTemp
,wndTemp
->next
))
1852 if (wndTemp
->dwStyle
& WS_VISIBLE
) break;
1854 WIN_ReleaseDesktop();
1855 WIN_ReleaseWndPtr(wndTemp
);
1857 if( wndTemp
!= wndPtr
)
1858 SetWindowPos(hWnd
, HWND_TOP
, 0,0,0,0,
1859 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
1860 if (!IsWindow(hWnd
))
1864 /* Get a handle to the new active queue */
1865 hNewActiveQueue
= wndPtr
? wndPtr
->hmemTaskQ
: 0;
1867 /* send WM_ACTIVATEAPP if necessary */
1868 if (hOldActiveQueue
!= hNewActiveQueue
)
1870 WND
**list
, **ppWnd
;
1871 WND
*pDesktop
= WIN_GetDesktop();
1873 if ((list
= WIN_BuildWinArray( pDesktop
, 0, NULL
)))
1875 for (ppWnd
= list
; *ppWnd
; ppWnd
++)
1877 if (!IsWindow( (*ppWnd
)->hwndSelf
)) continue;
1879 if ((*ppWnd
)->hmemTaskQ
== hOldActiveQueue
)
1880 SendMessage16( (*ppWnd
)->hwndSelf
, WM_ACTIVATEAPP
,
1881 0, QUEUE_GetQueueTask(hNewActiveQueue
) );
1883 WIN_ReleaseWinArray(list
);
1886 hActiveQueue
= hNewActiveQueue
;
1888 if ((list
= WIN_BuildWinArray(pDesktop
, 0, NULL
)))
1890 for (ppWnd
= list
; *ppWnd
; ppWnd
++)
1892 if (!IsWindow( (*ppWnd
)->hwndSelf
)) continue;
1894 if ((*ppWnd
)->hmemTaskQ
== hNewActiveQueue
)
1895 SendMessage16( (*ppWnd
)->hwndSelf
, WM_ACTIVATEAPP
,
1896 1, QUEUE_GetQueueTask( hOldActiveQueue
) );
1898 WIN_ReleaseWinArray(list
);
1900 WIN_ReleaseDesktop();
1902 if (hWnd
&& !IsWindow(hWnd
)) goto CLEANUP
;
1907 /* walk up to the first unowned window */
1908 wndTemp
= WIN_LockWndPtr(wndPtr
);
1909 while (wndTemp
->owner
)
1911 WIN_UpdateWndPtr(&wndTemp
,wndTemp
->owner
);
1913 /* and set last active owned popup */
1914 wndTemp
->hwndLastActive
= hWnd
;
1916 wIconized
= HIWORD(wndTemp
->dwStyle
& WS_MINIMIZE
);
1917 WIN_ReleaseWndPtr(wndTemp
);
1918 SendMessageA( hWnd
, WM_NCACTIVATE
, TRUE
, 0 );
1919 SendMessageA( hWnd
, WM_ACTIVATE
,
1920 MAKEWPARAM( (fMouse
) ? WA_CLICKACTIVE
: WA_ACTIVE
, wIconized
),
1921 (LPARAM
)hwndPrevActive
);
1922 if( !IsWindow(hWnd
) ) goto CLEANUP
;
1925 /* change focus if possible */
1928 if ( pNewActiveQueue
)
1930 HWND hOldFocus
= PERQDATA_GetFocusWnd( pNewActiveQueue
->pQData
);
1932 if ( hOldFocus
&& WIN_GetTopParent( hOldFocus
) != hwndActive
)
1933 FOCUS_SwitchFocus( pNewActiveQueue
, hOldFocus
,
1934 (wndPtr
&& (wndPtr
->dwStyle
& WS_MINIMIZE
))?
1938 if ( pOldActiveQueue
&&
1939 ( !pNewActiveQueue
||
1940 pNewActiveQueue
->pQData
!= pOldActiveQueue
->pQData
) )
1942 HWND hOldFocus
= PERQDATA_GetFocusWnd( pOldActiveQueue
->pQData
);
1944 FOCUS_SwitchFocus( pOldActiveQueue
, hOldFocus
, 0 );
1948 if( !hwndPrevActive
&& wndPtr
)
1949 (*wndPtr
->pDriver
->pForceWindowRaise
)(wndPtr
);
1951 /* if active wnd is minimized redraw icon title */
1952 if( IsIconic(hwndActive
) ) WINPOS_RedrawIconTitle(hwndActive
);
1954 bRet
= (hWnd
== hwndActive
); /* Success? */
1956 CLEANUP
: /* Unlock the message queues before returning */
1958 if ( pNewActiveQueue
)
1959 QUEUE_Unlock( pNewActiveQueue
);
1963 if ( pOldActiveQueue
)
1964 QUEUE_Unlock( pOldActiveQueue
);
1966 WIN_ReleaseWndPtr(wndPtr
);
1970 /*******************************************************************
1971 * WINPOS_ActivateOtherWindow
1973 * Activates window other than pWnd.
1975 BOOL
WINPOS_ActivateOtherWindow(WND
* pWnd
)
1979 HWND hwndActive
= 0;
1981 /* Get current active window from the active queue */
1984 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
1987 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
1988 QUEUE_Unlock( pActiveQueue
);
1992 if( pWnd
->hwndSelf
== hwndPrevActive
)
1995 if( hwndActive
!= pWnd
->hwndSelf
&&
1996 ( hwndActive
|| QUEUE_IsExitingQueue(pWnd
->hmemTaskQ
)) )
1999 if( !(pWnd
->dwStyle
& WS_POPUP
) || !(pWnd
->owner
) ||
2000 !WINPOS_CanActivate((pWndTo
= WIN_GetTopParentPtr(pWnd
->owner
))) )
2002 WND
* pWndPtr
= WIN_GetTopParentPtr(pWnd
);
2004 WIN_ReleaseWndPtr(pWndTo
);
2005 pWndTo
= WIN_FindWndPtr(hwndPrevActive
);
2007 while( !WINPOS_CanActivate(pWndTo
) )
2009 /* by now owned windows should've been taken care of */
2010 WIN_UpdateWndPtr(&pWndTo
,pWndPtr
->next
);
2011 WIN_UpdateWndPtr(&pWndPtr
,pWndTo
);
2012 if( !pWndTo
) break;
2014 WIN_ReleaseWndPtr(pWndPtr
);
2017 bRet
= WINPOS_SetActiveWindow( pWndTo
? pWndTo
->hwndSelf
: 0, FALSE
, TRUE
);
2019 /* switch desktop queue to current active */
2022 WIN_GetDesktop()->hmemTaskQ
= pWndTo
->hmemTaskQ
;
2023 WIN_ReleaseWndPtr(pWndTo
);
2024 WIN_ReleaseDesktop();
2031 /*******************************************************************
2032 * WINPOS_ChangeActiveWindow
2035 BOOL
WINPOS_ChangeActiveWindow( HWND hWnd
, BOOL mouseMsg
)
2037 WND
*wndPtr
, *wndTemp
;
2039 HWND hwndActive
= 0;
2041 /* Get current active window from the active queue */
2044 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
2047 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
2048 QUEUE_Unlock( pActiveQueue
);
2053 return WINPOS_SetActiveWindow( 0, mouseMsg
, TRUE
);
2055 wndPtr
= WIN_FindWndPtr(hWnd
);
2056 if( !wndPtr
) return FALSE
;
2058 /* child windows get WM_CHILDACTIVATE message */
2059 if( (wndPtr
->dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
2061 retvalue
= SendMessageA(hWnd
, WM_CHILDACTIVATE
, 0, 0L);
2065 if( hWnd
== hwndActive
)
2071 if( !WINPOS_SetActiveWindow(hWnd
,mouseMsg
,TRUE
) )
2077 /* switch desktop queue to current active */
2078 wndTemp
= WIN_GetDesktop();
2079 if( wndPtr
->parent
== wndTemp
)
2080 wndTemp
->hmemTaskQ
= wndPtr
->hmemTaskQ
;
2081 WIN_ReleaseDesktop();
2085 WIN_ReleaseWndPtr(wndPtr
);
2090 /***********************************************************************
2091 * WINPOS_SendNCCalcSize
2093 * Send a WM_NCCALCSIZE message to a window.
2094 * All parameters are read-only except newClientRect.
2095 * oldWindowRect, oldClientRect and winpos must be non-NULL only
2096 * when calcValidRect is TRUE.
2098 LONG
WINPOS_SendNCCalcSize( HWND hwnd
, BOOL calcValidRect
,
2099 RECT
*newWindowRect
, RECT
*oldWindowRect
,
2100 RECT
*oldClientRect
, WINDOWPOS
*winpos
,
2101 RECT
*newClientRect
)
2103 NCCALCSIZE_PARAMS params
;
2104 WINDOWPOS winposCopy
;
2107 params
.rgrc
[0] = *newWindowRect
;
2110 winposCopy
= *winpos
;
2111 params
.rgrc
[1] = *oldWindowRect
;
2112 params
.rgrc
[2] = *oldClientRect
;
2113 params
.lppos
= &winposCopy
;
2115 result
= SendMessageA( hwnd
, WM_NCCALCSIZE
, calcValidRect
,
2117 TRACE("%d,%d-%d,%d\n",
2118 params
.rgrc
[0].left
, params
.rgrc
[0].top
,
2119 params
.rgrc
[0].right
, params
.rgrc
[0].bottom
);
2121 /* If the application send back garbage, ignore it */
2122 if (params
.rgrc
[0].left
<= params
.rgrc
[0].right
&& params
.rgrc
[0].top
<= params
.rgrc
[0].bottom
)
2123 *newClientRect
= params
.rgrc
[0];
2129 /***********************************************************************
2130 * WINPOS_HandleWindowPosChanging16
2132 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2134 LONG
WINPOS_HandleWindowPosChanging16( WND
*wndPtr
, WINDOWPOS16
*winpos
)
2136 POINT maxSize
, minTrack
;
2137 if (winpos
->flags
& SWP_NOSIZE
) return 0;
2138 if ((wndPtr
->dwStyle
& WS_THICKFRAME
) ||
2139 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) == 0))
2141 WINPOS_GetMinMaxInfo( wndPtr
, &maxSize
, NULL
, &minTrack
, NULL
);
2142 if (maxSize
.x
< winpos
->cx
) winpos
->cx
= maxSize
.x
;
2143 if (maxSize
.y
< winpos
->cy
) winpos
->cy
= maxSize
.y
;
2144 if (!(wndPtr
->dwStyle
& WS_MINIMIZE
))
2146 if (winpos
->cx
< minTrack
.x
) winpos
->cx
= minTrack
.x
;
2147 if (winpos
->cy
< minTrack
.y
) winpos
->cy
= minTrack
.y
;
2154 /***********************************************************************
2155 * WINPOS_HandleWindowPosChanging
2157 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2159 LONG
WINPOS_HandleWindowPosChanging( WND
*wndPtr
, WINDOWPOS
*winpos
)
2162 if (winpos
->flags
& SWP_NOSIZE
) return 0;
2163 if ((wndPtr
->dwStyle
& WS_THICKFRAME
) ||
2164 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) == 0))
2166 WINPOS_GetMinMaxInfo( wndPtr
, &maxSize
, NULL
, NULL
, NULL
);
2167 winpos
->cx
= min( winpos
->cx
, maxSize
.x
);
2168 winpos
->cy
= min( winpos
->cy
, maxSize
.y
);
2173 /***********************************************************************
2176 * fix Z order taking into account owned popups -
2177 * basically we need to maintain them above the window that owns them
2179 * FIXME: hide/show owned popups when owner visibility changes.
2181 static HWND
SWP_DoOwnedPopups(WND
* pDesktop
, WND
* wndPtr
, HWND hwndInsertAfter
, WORD flags
)
2183 WND
* w
= WIN_LockWndPtr(pDesktop
->child
);
2185 WARN("(%04x) hInsertAfter = %04x\n", wndPtr
->hwndSelf
, hwndInsertAfter
);
2187 if( (wndPtr
->dwStyle
& WS_POPUP
) && wndPtr
->owner
)
2189 /* make sure this popup stays above the owner */
2191 HWND hwndLocalPrev
= HWND_TOP
;
2193 if( hwndInsertAfter
!= HWND_TOP
)
2195 while( w
!= wndPtr
->owner
)
2197 if (w
!= wndPtr
) hwndLocalPrev
= w
->hwndSelf
;
2198 if( hwndLocalPrev
== hwndInsertAfter
) break;
2199 WIN_UpdateWndPtr(&w
,w
->next
);
2201 hwndInsertAfter
= hwndLocalPrev
;
2204 else if( wndPtr
->dwStyle
& WS_CHILD
)
2207 WIN_UpdateWndPtr(&w
, pDesktop
->child
);
2211 if( w
== wndPtr
) break;
2213 if( (w
->dwStyle
& WS_POPUP
) && w
->owner
== wndPtr
)
2215 SetWindowPos(w
->hwndSelf
, hwndInsertAfter
, 0, 0, 0, 0,
2216 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOSENDCHANGING
| SWP_DEFERERASE
);
2217 hwndInsertAfter
= w
->hwndSelf
;
2219 WIN_UpdateWndPtr(&w
, w
->next
);
2223 WIN_ReleaseWndPtr(w
);
2224 return hwndInsertAfter
;
2227 /***********************************************************************
2230 * Make window look nice without excessive repainting
2232 * visible and update regions are in window coordinates
2233 * client and window rectangles are in parent client coordinates
2235 * Returns: uFlags and a dirty region in *pVisRgn.
2237 static UINT
SWP_CopyValidBits( WND
* Wnd
, HRGN
* pVisRgn
,
2238 LPRECT lpOldWndRect
,
2239 LPRECT lpOldClientRect
, UINT uFlags
)
2242 HRGN newVisRgn
, dirtyRgn
;
2243 INT my
= COMPLEXREGION
;
2245 TRACE("\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2246 Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
,
2247 Wnd
->rectWindow
.right
, Wnd
->rectWindow
.bottom
,
2248 lpOldWndRect
->left
, lpOldWndRect
->top
,
2249 lpOldWndRect
->right
, lpOldWndRect
->bottom
, *pVisRgn
);
2250 TRACE("\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2251 Wnd
->rectClient
.left
, Wnd
->rectClient
.top
,
2252 Wnd
->rectClient
.right
, Wnd
->rectClient
.bottom
,
2253 lpOldClientRect
->left
, lpOldClientRect
->top
,
2254 lpOldClientRect
->right
,lpOldClientRect
->bottom
);
2256 if( Wnd
->hrgnUpdate
== 1 )
2257 uFlags
|= SWP_EX_NOCOPY
; /* whole window is invalid, nothing to copy */
2259 newVisRgn
= DCE_GetVisRgn( Wnd
->hwndSelf
, DCX_WINDOW
| DCX_CLIPSIBLINGS
, 0, 0);
2260 dirtyRgn
= CreateRectRgn( 0, 0, 0, 0 );
2262 if( !(uFlags
& SWP_EX_NOCOPY
) ) /* make sure dst region covers only valid bits */
2263 my
= CombineRgn( dirtyRgn
, newVisRgn
, *pVisRgn
, RGN_AND
);
2265 if( (my
== NULLREGION
) || (uFlags
& SWP_EX_NOCOPY
) )
2269 TRACE("\twon't copy anything!\n");
2271 /* set dirtyRgn to the sum of old and new visible regions
2272 * in parent client coordinates */
2274 OffsetRgn( newVisRgn
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2275 OffsetRgn( *pVisRgn
, lpOldWndRect
->left
, lpOldWndRect
->top
);
2277 CombineRgn(*pVisRgn
, *pVisRgn
, newVisRgn
, RGN_OR
);
2279 else /* copy valid bits to a new location */
2281 INT dx
, dy
, ow
, oh
, nw
, nh
, ocw
, ncw
, och
, nch
;
2282 HRGN hrgnValid
= dirtyRgn
; /* non-empty intersection of old and new visible rgns */
2284 /* subtract already invalid region inside Wnd from the dst region */
2286 if( Wnd
->hrgnUpdate
)
2287 if( CombineRgn( hrgnValid
, hrgnValid
, Wnd
->hrgnUpdate
, RGN_DIFF
) == NULLREGION
)
2290 /* check if entire window can be copied */
2292 ow
= lpOldWndRect
->right
- lpOldWndRect
->left
;
2293 oh
= lpOldWndRect
->bottom
- lpOldWndRect
->top
;
2294 nw
= Wnd
->rectWindow
.right
- Wnd
->rectWindow
.left
;
2295 nh
= Wnd
->rectWindow
.bottom
- Wnd
->rectWindow
.top
;
2297 ocw
= lpOldClientRect
->right
- lpOldClientRect
->left
;
2298 och
= lpOldClientRect
->bottom
- lpOldClientRect
->top
;
2299 ncw
= Wnd
->rectClient
.right
- Wnd
->rectClient
.left
;
2300 nch
= Wnd
->rectClient
.bottom
- Wnd
->rectClient
.top
;
2302 if( (ocw
!= ncw
) || (och
!= nch
) ||
2303 ( ow
!= nw
) || ( oh
!= nh
) ||
2304 ((lpOldClientRect
->top
- lpOldWndRect
->top
) !=
2305 (Wnd
->rectClient
.top
- Wnd
->rectWindow
.top
)) ||
2306 ((lpOldClientRect
->left
- lpOldWndRect
->left
) !=
2307 (Wnd
->rectClient
.left
- Wnd
->rectWindow
.left
)) )
2309 if(uFlags
& SWP_EX_PAINTSELF
)
2311 /* movement relative to the window itself */
2312 dx
= (Wnd
->rectClient
.left
- Wnd
->rectWindow
.left
) -
2313 (lpOldClientRect
->left
- lpOldWndRect
->left
) ;
2314 dy
= (Wnd
->rectClient
.top
- Wnd
->rectWindow
.top
) -
2315 (lpOldClientRect
->top
- lpOldWndRect
->top
) ;
2319 /* movement relative to the parent's client area */
2320 dx
= Wnd
->rectClient
.left
- lpOldClientRect
->left
;
2321 dy
= Wnd
->rectClient
.top
- lpOldClientRect
->top
;
2324 /* restrict valid bits to the common client rect */
2326 r
.left
= Wnd
->rectClient
.left
- Wnd
->rectWindow
.left
;
2327 r
.top
= Wnd
->rectClient
.top
- Wnd
->rectWindow
.top
;
2328 r
.right
= r
.left
+ min( ocw
, ncw
);
2329 r
.bottom
= r
.top
+ min( och
, nch
);
2331 REGION_CropRgn( hrgnValid
, hrgnValid
, &r
,
2332 (uFlags
& SWP_EX_PAINTSELF
) ? NULL
: (POINT
*)&(Wnd
->rectWindow
));
2333 GetRgnBox( hrgnValid
, &r
);
2334 if( IsRectEmpty( &r
) )
2336 r
= *lpOldClientRect
;
2340 if(uFlags
& SWP_EX_PAINTSELF
) {
2342 * with SWP_EX_PAINTSELF, the window repaints itself. Since a window can't move
2343 * relative to itself, only the client area can change.
2344 * if the client rect didn't change, there's nothing to do.
2351 dx
= Wnd
->rectWindow
.left
- lpOldWndRect
->left
;
2352 dy
= Wnd
->rectWindow
.top
- lpOldWndRect
->top
;
2353 OffsetRgn( hrgnValid
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2358 if( !(uFlags
& SWP_EX_PAINTSELF
) )
2360 /* Move remaining regions to parent coordinates */
2361 OffsetRgn( newVisRgn
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2362 OffsetRgn( *pVisRgn
, lpOldWndRect
->left
, lpOldWndRect
->top
);
2365 OffsetRect( &r
, -lpOldWndRect
->left
, -lpOldWndRect
->top
);
2367 TRACE("\tcomputing dirty region!\n");
2369 /* Compute combined dirty region (old + new - valid) */
2370 CombineRgn( *pVisRgn
, *pVisRgn
, newVisRgn
, RGN_OR
);
2371 CombineRgn( *pVisRgn
, *pVisRgn
, hrgnValid
, RGN_DIFF
);
2373 /* Blt valid bits, r is the rect to copy */
2380 /* get DC and clip rect with drawable rect to avoid superfluous expose events
2381 from copying clipped areas */
2383 if( uFlags
& SWP_EX_PAINTSELF
)
2385 hDC
= GetDCEx( Wnd
->hwndSelf
, hrgnValid
, DCX_WINDOW
| DCX_CACHE
|
2386 DCX_KEEPCLIPRGN
| DCX_INTERSECTRGN
| DCX_CLIPSIBLINGS
);
2387 rClip
.right
= nw
; rClip
.bottom
= nh
;
2391 hDC
= GetDCEx( Wnd
->parent
->hwndSelf
, hrgnValid
, DCX_CACHE
|
2392 DCX_KEEPCLIPRGN
| DCX_INTERSECTRGN
| DCX_CLIPSIBLINGS
);
2393 rClip
.right
= Wnd
->parent
->rectClient
.right
- Wnd
->parent
->rectClient
.left
;
2394 rClip
.bottom
= Wnd
->parent
->rectClient
.bottom
- Wnd
->parent
->rectClient
.top
;
2396 rClip
.left
= rClip
.top
= 0;
2398 if( oh
> nh
) r
.bottom
= r
.top
+ nh
;
2399 if( ow
< nw
) r
.right
= r
.left
+ nw
;
2401 if( IntersectRect( &r
, &r
, &rClip
) )
2403 Wnd
->pDriver
->pSurfaceCopy( Wnd
->parent
, hDC
, dx
, dy
, &r
, TRUE
);
2405 /* When you copy the bits without repainting, parent doesn't
2406 get validated appropriately. Therefore, we have to validate
2407 the parent with the windows' updated region when the
2408 parent's update region is not empty. */
2410 if (Wnd
->parent
->hrgnUpdate
!= 0 && !(Wnd
->parent
->dwStyle
& WS_CLIPCHILDREN
))
2412 OffsetRect(&r
, dx
, dy
);
2413 ValidateRect(Wnd
->parent
->hwndSelf
, &r
);
2416 ReleaseDC( (uFlags
& SWP_EX_PAINTSELF
) ?
2417 Wnd
->hwndSelf
: Wnd
->parent
->hwndSelf
, hDC
);
2421 /* *pVisRgn now points to the invalidated region */
2423 DeleteObject(newVisRgn
);
2424 DeleteObject(dirtyRgn
);
2428 /***********************************************************************
2429 * SWP_DoSimpleFrameChanged
2431 * NOTE: old and new client rect origins are identical, only
2432 * extents may have changed. Window extents are the same.
2434 static void SWP_DoSimpleFrameChanged( WND
* wndPtr
, RECT
* pOldClientRect
, WORD swpFlags
, UINT uFlags
)
2440 if( !(swpFlags
& SWP_NOCLIENTSIZE
) )
2442 /* Client rect changed its position/size, most likely a scrollar
2443 * was added/removed.
2445 * FIXME: WVR alignment flags
2448 if( wndPtr
->rectClient
.right
> pOldClientRect
->right
) /* right edge */
2452 rect
.bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
2453 rect
.right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
2454 if(!(uFlags
& SWP_EX_NOCOPY
))
2455 rect
.left
= pOldClientRect
->right
- wndPtr
->rectClient
.left
;
2463 if( wndPtr
->rectClient
.bottom
> pOldClientRect
->bottom
) /* bottom edge */
2466 hrgn
= CreateRectRgnIndirect( &rect
);
2468 rect
.right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
2469 rect
.bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
2470 if(!(uFlags
& SWP_EX_NOCOPY
))
2471 rect
.top
= pOldClientRect
->bottom
- wndPtr
->rectClient
.top
;
2475 REGION_UnionRectWithRgn( hrgn
, &rect
);
2478 if( i
== 0 && (uFlags
& SWP_EX_NOCOPY
) ) /* force redraw anyway */
2480 rect
= wndPtr
->rectWindow
;
2481 OffsetRect( &rect
, wndPtr
->rectWindow
.left
- wndPtr
->rectClient
.left
,
2482 wndPtr
->rectWindow
.top
- wndPtr
->rectClient
.top
);
2490 PAINT_RedrawWindow( wndPtr
->hwndSelf
, &rect
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
|
2491 RDW_ERASENOW
| RDW_ALLCHILDREN
, RDW_EX_TOPFRAME
| RDW_EX_USEHRGN
);
2495 WIN_UpdateNCRgn(wndPtr
, 0, UNC_UPDATE
| UNC_ENTIRE
);
2499 DeleteObject( hrgn
);
2502 /***********************************************************************
2503 * SWP_DoWinPosChanging
2505 static BOOL
SWP_DoWinPosChanging( WND
* wndPtr
, WINDOWPOS
* pWinpos
,
2506 RECT
* pNewWindowRect
, RECT
* pNewClientRect
)
2508 /* Send WM_WINDOWPOSCHANGING message */
2510 if (!(pWinpos
->flags
& SWP_NOSENDCHANGING
))
2511 SendMessageA( wndPtr
->hwndSelf
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
)pWinpos
);
2513 /* Calculate new position and size */
2515 *pNewWindowRect
= wndPtr
->rectWindow
;
2516 *pNewClientRect
= (wndPtr
->dwStyle
& WS_MINIMIZE
) ? wndPtr
->rectWindow
2517 : wndPtr
->rectClient
;
2519 if (!(pWinpos
->flags
& SWP_NOSIZE
))
2521 pNewWindowRect
->right
= pNewWindowRect
->left
+ pWinpos
->cx
;
2522 pNewWindowRect
->bottom
= pNewWindowRect
->top
+ pWinpos
->cy
;
2524 if (!(pWinpos
->flags
& SWP_NOMOVE
))
2526 pNewWindowRect
->left
= pWinpos
->x
;
2527 pNewWindowRect
->top
= pWinpos
->y
;
2528 pNewWindowRect
->right
+= pWinpos
->x
- wndPtr
->rectWindow
.left
;
2529 pNewWindowRect
->bottom
+= pWinpos
->y
- wndPtr
->rectWindow
.top
;
2531 OffsetRect( pNewClientRect
, pWinpos
->x
- wndPtr
->rectWindow
.left
,
2532 pWinpos
->y
- wndPtr
->rectWindow
.top
);
2535 pWinpos
->flags
|= SWP_NOCLIENTMOVE
| SWP_NOCLIENTSIZE
;
2539 /***********************************************************************
2542 static UINT
SWP_DoNCCalcSize( WND
* wndPtr
, WINDOWPOS
* pWinpos
,
2543 RECT
* pNewWindowRect
, RECT
* pNewClientRect
, WORD f
)
2547 /* Send WM_NCCALCSIZE message to get new client area */
2548 if( (pWinpos
->flags
& (SWP_FRAMECHANGED
| SWP_NOSIZE
)) != SWP_NOSIZE
)
2550 wvrFlags
= WINPOS_SendNCCalcSize( pWinpos
->hwnd
, TRUE
, pNewWindowRect
,
2551 &wndPtr
->rectWindow
, &wndPtr
->rectClient
,
2552 pWinpos
, pNewClientRect
);
2554 /* FIXME: WVR_ALIGNxxx */
2556 if( pNewClientRect
->left
!= wndPtr
->rectClient
.left
||
2557 pNewClientRect
->top
!= wndPtr
->rectClient
.top
)
2558 pWinpos
->flags
&= ~SWP_NOCLIENTMOVE
;
2560 if( (pNewClientRect
->right
- pNewClientRect
->left
!=
2561 wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
) ||
2562 (pNewClientRect
->bottom
- pNewClientRect
->top
!=
2563 wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
) )
2564 pWinpos
->flags
&= ~SWP_NOCLIENTSIZE
;
2567 if( !(f
& SWP_NOMOVE
) && (pNewClientRect
->left
!= wndPtr
->rectClient
.left
||
2568 pNewClientRect
->top
!= wndPtr
->rectClient
.top
) )
2569 pWinpos
->flags
&= ~SWP_NOCLIENTMOVE
;
2573 /***********************************************************************
2574 * SetWindowPos (USER.2)
2576 BOOL16 WINAPI
SetWindowPos16( HWND16 hwnd
, HWND16 hwndInsertAfter
,
2577 INT16 x
, INT16 y
, INT16 cx
, INT16 cy
, WORD flags
)
2579 return SetWindowPos(hwnd
,(INT
)(INT16
)hwndInsertAfter
,x
,y
,cx
,cy
,flags
);
2582 /***********************************************************************
2583 * SetWindowPos (USER32.520)
2585 BOOL WINAPI
SetWindowPos( HWND hwnd
, HWND hwndInsertAfter
,
2586 INT x
, INT y
, INT cx
, INT cy
, UINT flags
)
2589 WND
* wndPtr
,*wndTemp
;
2590 RECT newWindowRect
, newClientRect
;
2591 RECT oldWindowRect
, oldClientRect
;
2593 UINT wvrFlags
= 0, uFlags
= 0;
2594 BOOL retvalue
, resync
= FALSE
, bChangePos
;
2595 HWND hwndActive
= 0;
2597 /* Get current active window from the active queue */
2600 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
2603 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
2604 QUEUE_Unlock( pActiveQueue
);
2608 TRACE("hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2609 hwnd
, x
, y
, x
+cx
, y
+cy
, flags
);
2611 bChangePos
= !(flags
& SWP_WINE_NOHOSTMOVE
);
2612 flags
&= ~SWP_WINE_NOHOSTMOVE
;
2615 /* ------------------------------------------------------------------------ CHECKS */
2617 /* Check window handle */
2619 if (hwnd
== GetDesktopWindow()) return FALSE
;
2620 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return FALSE
;
2622 TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr
->rectWindow
.left
, wndPtr
->rectWindow
.top
,
2623 wndPtr
->rectWindow
.right
, wndPtr
->rectWindow
.bottom
, (unsigned)wndPtr
->dwStyle
);
2625 /* Fix redundant flags */
2627 if(wndPtr
->dwStyle
& WS_VISIBLE
)
2628 flags
&= ~SWP_SHOWWINDOW
;
2631 if (!(flags
& SWP_SHOWWINDOW
))
2632 flags
|= SWP_NOREDRAW
;
2633 flags
&= ~SWP_HIDEWINDOW
;
2636 if ( cx
< 0 ) cx
= 0; if( cy
< 0 ) cy
= 0;
2638 if ((wndPtr
->rectWindow
.right
- wndPtr
->rectWindow
.left
== cx
) &&
2639 (wndPtr
->rectWindow
.bottom
- wndPtr
->rectWindow
.top
== cy
))
2640 flags
|= SWP_NOSIZE
; /* Already the right size */
2642 if ((wndPtr
->rectWindow
.left
== x
) && (wndPtr
->rectWindow
.top
== y
))
2643 flags
|= SWP_NOMOVE
; /* Already the right position */
2645 if (hwnd
== hwndActive
)
2646 flags
|= SWP_NOACTIVATE
; /* Already active */
2647 else if ( (wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)
2649 if(!(flags
& SWP_NOACTIVATE
)) /* Bring to the top when activating */
2651 flags
&= ~SWP_NOZORDER
;
2652 hwndInsertAfter
= HWND_TOP
;
2657 /* Check hwndInsertAfter */
2659 /* FIXME: TOPMOST not supported yet */
2660 if ((hwndInsertAfter
== HWND_TOPMOST
) ||
2661 (hwndInsertAfter
== HWND_NOTOPMOST
)) hwndInsertAfter
= HWND_TOP
;
2663 /* hwndInsertAfter must be a sibling of the window */
2664 if ((hwndInsertAfter
!= HWND_TOP
) && (hwndInsertAfter
!= HWND_BOTTOM
))
2666 WND
* wnd
= WIN_FindWndPtr(hwndInsertAfter
);
2669 if( wnd
->parent
!= wndPtr
->parent
)
2672 WIN_ReleaseWndPtr(wnd
);
2675 /* don't need to change the Zorder of hwnd if it's already inserted
2676 * after hwndInsertAfter or when inserting hwnd after itself.
2678 if(( wnd
->next
== wndPtr
) || (hwnd
== hwndInsertAfter
)) flags
|= SWP_NOZORDER
;
2680 WIN_ReleaseWndPtr(wnd
);
2683 Pos
: /* ------------------------------------------------------------------------ MAIN part */
2685 /* Fill the WINDOWPOS structure */
2688 winpos
.hwndInsertAfter
= hwndInsertAfter
;
2693 winpos
.flags
= flags
;
2695 SWP_DoWinPosChanging( wndPtr
, &winpos
, &newWindowRect
, &newClientRect
);
2697 if((winpos
.flags
& (SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) != SWP_NOZORDER
)
2699 if( wndPtr
->parent
== WIN_GetDesktop() )
2700 hwndInsertAfter
= SWP_DoOwnedPopups( wndPtr
->parent
, wndPtr
,
2701 hwndInsertAfter
, winpos
.flags
);
2702 WIN_ReleaseDesktop();
2705 if(!(wndPtr
->flags
& WIN_NATIVE
) )
2707 if( hwndInsertAfter
== HWND_TOP
)
2708 winpos
.flags
|= ( wndPtr
->parent
->child
== wndPtr
)? SWP_NOZORDER
: 0;
2710 if( hwndInsertAfter
== HWND_BOTTOM
)
2711 winpos
.flags
|= ( wndPtr
->next
)? 0: SWP_NOZORDER
;
2713 if( !(winpos
.flags
& SWP_NOZORDER
) )
2714 if( GetWindow(hwndInsertAfter
, GW_HWNDNEXT
) == wndPtr
->hwndSelf
)
2715 winpos
.flags
|= SWP_NOZORDER
;
2717 if( !(winpos
.flags
& (SWP_NOREDRAW
| SWP_SHOWWINDOW
)) &&
2718 ((winpos
.flags
& (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_FRAMECHANGED
))
2719 != (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
)) )
2721 /* get a previous visible region for SWP_CopyValidBits() */
2722 DWORD dflags
= DCX_WINDOW
;
2724 if (wndPtr
->dwStyle
& WS_CLIPSIBLINGS
)
2725 dflags
|= DCX_CLIPSIBLINGS
;
2727 visRgn
= DCE_GetVisRgn(hwnd
, dflags
, 0, 0);
2731 /* Common operations */
2733 wvrFlags
= SWP_DoNCCalcSize( wndPtr
, &winpos
, &newWindowRect
, &newClientRect
, flags
);
2735 if(!(winpos
.flags
& SWP_NOZORDER
) && winpos
.hwnd
!= hwndInsertAfter
)
2737 if ( WIN_UnlinkWindow( winpos
.hwnd
) )
2738 WIN_LinkWindow( winpos
.hwnd
, hwndInsertAfter
);
2741 /* Reset active DCEs */
2743 if( (((winpos
.flags
& SWP_AGG_NOPOSCHANGE
) != SWP_AGG_NOPOSCHANGE
) &&
2744 wndPtr
->dwStyle
& WS_VISIBLE
) ||
2745 (flags
& (SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) )
2749 UnionRect(&rect
, &newWindowRect
, &wndPtr
->rectWindow
);
2750 DCE_InvalidateDCE(wndPtr
, &rect
);
2753 oldWindowRect
= wndPtr
->rectWindow
;
2754 oldClientRect
= wndPtr
->rectClient
;
2756 /* Find out if we have to redraw the whole client rect */
2758 if( oldClientRect
.bottom
- oldClientRect
.top
==
2759 newClientRect
.bottom
- newClientRect
.top
) wvrFlags
&= ~WVR_VREDRAW
;
2761 if( oldClientRect
.right
- oldClientRect
.left
==
2762 newClientRect
.right
- newClientRect
.left
) wvrFlags
&= ~WVR_HREDRAW
;
2764 if( (winpos
.flags
& SWP_NOCOPYBITS
) || (!(winpos
.flags
& SWP_NOCLIENTSIZE
) &&
2765 (wvrFlags
>= WVR_HREDRAW
) && (wvrFlags
< WVR_VALIDRECTS
)) )
2767 uFlags
|= SWP_EX_NOCOPY
;
2770 * Use this later in CopyValidBits()
2773 uFlags |= SWP_EX_NONCLIENT;
2776 /* FIXME: actually do something with WVR_VALIDRECTS */
2778 wndPtr
->rectWindow
= newWindowRect
;
2779 wndPtr
->rectClient
= newClientRect
;
2781 if (wndPtr
->flags
& WIN_NATIVE
) /* -------------------------------------------- hosted window */
2783 BOOL bCallDriver
= TRUE
;
2784 HWND tempInsertAfter
= winpos
.hwndInsertAfter
;
2786 winpos
.hwndInsertAfter
= hwndInsertAfter
;
2788 if( !(winpos
.flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
| SWP_NOREDRAW
)) )
2790 /* This is the only place where we need to force repainting of the contents
2791 of windows created by the host window system, all other cases go through the
2792 expose event handling */
2794 if( (winpos
.flags
& (SWP_NOSIZE
| SWP_FRAMECHANGED
)) == (SWP_NOSIZE
| SWP_FRAMECHANGED
) )
2796 cx
= newWindowRect
.right
- newWindowRect
.left
;
2797 cy
= newWindowRect
.bottom
- newWindowRect
.top
;
2799 wndPtr
->pDriver
->pSetWindowPos(wndPtr
, &winpos
, bChangePos
);
2800 winpos
.hwndInsertAfter
= tempInsertAfter
;
2801 bCallDriver
= FALSE
;
2803 if( winpos
.flags
& SWP_NOCLIENTMOVE
)
2804 SWP_DoSimpleFrameChanged(wndPtr
, &oldClientRect
, winpos
.flags
, uFlags
);
2807 /* client area moved but window extents remained the same, copy valid bits */
2809 visRgn
= CreateRectRgn( 0, 0, cx
, cy
);
2810 uFlags
= SWP_CopyValidBits( wndPtr
, &visRgn
, &oldWindowRect
, &oldClientRect
,
2811 uFlags
| SWP_EX_PAINTSELF
);
2818 if( !(winpos
.flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
| SWP_NOREDRAW
)) )
2820 if( (oldClientRect
.left
- oldWindowRect
.left
== newClientRect
.left
- newWindowRect
.left
) &&
2821 (oldClientRect
.top
- oldWindowRect
.top
== newClientRect
.top
- newWindowRect
.top
) &&
2822 !(uFlags
& SWP_EX_NOCOPY
) )
2824 /* The origin of the client rect didn't move so we can try to repaint
2825 * only the nonclient area by setting bit gravity hint for the host window system.
2828 if( !(wndPtr
->dwExStyle
& WS_EX_MANAGED
) )
2830 HRGN hrgn
= CreateRectRgn( 0, 0, newWindowRect
.right
- newWindowRect
.left
,
2831 newWindowRect
.bottom
- newWindowRect
.top
);
2832 RECT rcn
= newClientRect
;
2833 RECT rco
= oldClientRect
;
2835 OffsetRect( &rcn
, -newWindowRect
.left
, -newWindowRect
.top
);
2836 OffsetRect( &rco
, -oldWindowRect
.left
, -oldWindowRect
.top
);
2837 IntersectRect( &rcn
, &rcn
, &rco
);
2838 visRgn
= CreateRectRgnIndirect( &rcn
);
2839 CombineRgn( visRgn
, hrgn
, visRgn
, RGN_DIFF
);
2840 DeleteObject( hrgn
);
2841 uFlags
= SWP_EX_PAINTSELF
;
2843 wndPtr
->pDriver
->pSetHostAttr(wndPtr
, HAK_BITGRAVITY
, BGNorthWest
);
2846 wndPtr
->pDriver
->pSetHostAttr(wndPtr
, HAK_BITGRAVITY
, BGForget
);
2849 wndPtr
->pDriver
->pSetWindowPos(wndPtr
, &winpos
, bChangePos
);
2850 winpos
.hwndInsertAfter
= tempInsertAfter
;
2853 if( winpos
.flags
& SWP_SHOWWINDOW
)
2857 wndPtr
->dwStyle
|= WS_VISIBLE
;
2859 if (wndPtr
->dwExStyle
& WS_EX_MANAGED
) resync
= TRUE
;
2861 /* focus was set to unmapped window, reset host focus
2862 * since the window is now visible */
2864 focus
= curr
= GetFocus();
2869 WND
*pFocus
= WIN_FindWndPtr( focus
);
2871 pFocus
->pDriver
->pSetFocus(pFocus
);
2872 WIN_ReleaseWndPtr(pFocus
);
2875 curr
= GetParent(curr
);
2879 else /* -------------------------------------------- emulated window */
2881 if( winpos
.flags
& SWP_SHOWWINDOW
)
2883 wndPtr
->dwStyle
|= WS_VISIBLE
;
2884 uFlags
|= SWP_EX_PAINTSELF
;
2885 visRgn
= 1; /* redraw the whole window */
2887 else if( !(winpos
.flags
& SWP_NOREDRAW
) )
2889 if( winpos
.flags
& SWP_HIDEWINDOW
)
2891 if( visRgn
> 1 ) /* map to parent */
2892 OffsetRgn( visRgn
, oldWindowRect
.left
, oldWindowRect
.top
);
2898 if( (winpos
.flags
& SWP_AGG_NOPOSCHANGE
) != SWP_AGG_NOPOSCHANGE
)
2900 /* if window was not resized and not moved try to repaint itself */
2901 if((winpos
.flags
& SWP_AGG_NOGEOMETRYCHANGE
) == SWP_AGG_NOGEOMETRYCHANGE
)
2902 uFlags
|= SWP_EX_PAINTSELF
;
2903 uFlags
= SWP_CopyValidBits(wndPtr
, &visRgn
, &oldWindowRect
,
2904 &oldClientRect
, uFlags
);
2908 /* nothing moved, redraw frame if needed */
2910 if( winpos
.flags
& SWP_FRAMECHANGED
)
2911 SWP_DoSimpleFrameChanged( wndPtr
, &oldClientRect
, winpos
.flags
, uFlags
);
2914 DeleteObject( visRgn
);
2922 if( winpos
.flags
& SWP_HIDEWINDOW
)
2924 wndPtr
->dwStyle
&= ~WS_VISIBLE
;
2927 if (hwnd
== CARET_GetHwnd())
2929 if( winpos
.flags
& SWP_HIDEWINDOW
)
2931 else if (winpos
.flags
& SWP_SHOWWINDOW
)
2935 /* ------------------------------------------------------------------------ FINAL */
2937 if (wndPtr
->flags
& WIN_NATIVE
)
2938 EVENT_Synchronize(); /* Synchronize with the host window system */
2940 if (!GetCapture() && ((wndPtr
->dwStyle
& WS_VISIBLE
) || (flags
& SWP_HIDEWINDOW
)))
2942 /* Simulate a mouse event to set the cursor */
2943 int iWndsLocks
= WIN_SuspendWndsLock();
2945 hardware_event( WM_MOUSEMOVE
, GET_KEYSTATE(), 0,
2946 PosX
, PosY
, GetTickCount(), 0 );
2948 WIN_RestoreWndsLock(iWndsLocks
);
2951 wndTemp
= WIN_GetDesktop();
2953 /* repaint invalidated region (if any)
2955 * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2956 * and force update after ChangeActiveWindow() to avoid painting frames twice.
2961 if( !(winpos
.flags
& SWP_NOREDRAW
) )
2964 /* Use PAINT_RedrawWindow to explicitly force an invalidation of the window,
2965 its parent and sibling and so on, and then erase the parent window
2966 back ground if the parent is either a top-level window or its parent's parent
2967 is top-level window. Rely on the system to repaint other affected
2968 windows later on. */
2969 if( uFlags
& SWP_EX_PAINTSELF
)
2971 PAINT_RedrawWindow( wndPtr
->hwndSelf
, NULL
, (visRgn
== 1) ? 0 : visRgn
,
2972 RDW_ERASE
| RDW_FRAME
| RDW_INVALIDATE
| RDW_ALLCHILDREN
,
2973 RDW_EX_XYWINDOW
| RDW_EX_USEHRGN
);
2977 PAINT_RedrawWindow( wndPtr
->parent
->hwndSelf
, NULL
, (visRgn
== 1) ? 0 : visRgn
,
2978 RDW_ERASE
| RDW_INVALIDATE
| RDW_ALLCHILDREN
,
2982 if(wndPtr
-> parent
== wndTemp
|| wndPtr
->parent
->parent
== wndTemp
)
2984 PAINT_RedrawWindow( wndPtr
->parent
->hwndSelf
, NULL
, 0,
2985 RDW_ERASENOW
| RDW_NOCHILDREN
, 0 );
2989 DeleteObject( visRgn
);
2992 WIN_ReleaseDesktop();
2994 if (!(flags
& SWP_NOACTIVATE
))
2995 WINPOS_ChangeActiveWindow( winpos
.hwnd
, FALSE
);
2997 /* And last, send the WM_WINDOWPOSCHANGED message */
2999 TRACE("\tstatus flags = %04x\n", winpos
.flags
& SWP_AGG_STATUSFLAGS
);
3002 (((winpos
.flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOPOSCHANGE
) &&
3003 !(winpos
.flags
& SWP_NOSENDCHANGING
)) )
3005 SendMessageA( winpos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
)&winpos
);
3006 if (resync
) EVENT_Synchronize();
3011 WIN_ReleaseWndPtr(wndPtr
);
3016 /***********************************************************************
3017 * BeginDeferWindowPos16 (USER.259)
3019 HDWP16 WINAPI
BeginDeferWindowPos16( INT16 count
)
3021 return BeginDeferWindowPos( count
);
3025 /***********************************************************************
3026 * BeginDeferWindowPos (USER32.9)
3028 HDWP WINAPI
BeginDeferWindowPos( INT count
)
3035 SetLastError(ERROR_INVALID_PARAMETER
);
3038 /* Windows allows zero count, in which case it allocates context for 8 moves */
3039 if (count
== 0) count
= 8;
3041 handle
= USER_HEAP_ALLOC( sizeof(DWP
) + (count
-1)*sizeof(WINDOWPOS
) );
3042 if (!handle
) return 0;
3043 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( handle
);
3044 pDWP
->actualCount
= 0;
3045 pDWP
->suggestedCount
= count
;
3047 pDWP
->wMagic
= DWP_MAGIC
;
3048 pDWP
->hwndParent
= 0;
3053 /***********************************************************************
3054 * DeferWindowPos16 (USER.260)
3056 HDWP16 WINAPI
DeferWindowPos16( HDWP16 hdwp
, HWND16 hwnd
, HWND16 hwndAfter
,
3057 INT16 x
, INT16 y
, INT16 cx
, INT16 cy
,
3060 return DeferWindowPos( hdwp
, hwnd
, (INT
)(INT16
)hwndAfter
,
3061 x
, y
, cx
, cy
, flags
);
3065 /***********************************************************************
3066 * DeferWindowPos (USER32.128)
3068 HDWP WINAPI
DeferWindowPos( HDWP hdwp
, HWND hwnd
, HWND hwndAfter
,
3069 INT x
, INT y
, INT cx
, INT cy
,
3074 HDWP newhdwp
= hdwp
,retvalue
;
3078 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
3079 if (!pDWP
) return 0;
3080 if (hwnd
== GetDesktopWindow()) return 0;
3082 if (!(pWnd
=WIN_FindWndPtr( hwnd
))) {
3083 USER_HEAP_FREE( hdwp
);
3087 /* Numega Bounds Checker Demo dislikes the following code.
3088 In fact, I've not been able to find any "same parent" requirement in any docu
3092 /* All the windows of a DeferWindowPos() must have the same parent */
3093 parent
= pWnd
->parent
->hwndSelf
;
3094 if (pDWP
->actualCount
== 0) pDWP
->hwndParent
= parent
;
3095 else if (parent
!= pDWP
->hwndParent
)
3097 USER_HEAP_FREE( hdwp
);
3103 for (i
= 0; i
< pDWP
->actualCount
; i
++)
3105 if (pDWP
->winPos
[i
].hwnd
== hwnd
)
3107 /* Merge with the other changes */
3108 if (!(flags
& SWP_NOZORDER
))
3110 pDWP
->winPos
[i
].hwndInsertAfter
= hwndAfter
;
3112 if (!(flags
& SWP_NOMOVE
))
3114 pDWP
->winPos
[i
].x
= x
;
3115 pDWP
->winPos
[i
].y
= y
;
3117 if (!(flags
& SWP_NOSIZE
))
3119 pDWP
->winPos
[i
].cx
= cx
;
3120 pDWP
->winPos
[i
].cy
= cy
;
3122 pDWP
->winPos
[i
].flags
&= flags
| ~(SWP_NOSIZE
| SWP_NOMOVE
|
3123 SWP_NOZORDER
| SWP_NOREDRAW
|
3124 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
3126 pDWP
->winPos
[i
].flags
|= flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
|
3132 if (pDWP
->actualCount
>= pDWP
->suggestedCount
)
3134 newhdwp
= USER_HEAP_REALLOC( hdwp
,
3135 sizeof(DWP
) + pDWP
->suggestedCount
*sizeof(WINDOWPOS
) );
3141 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( newhdwp
);
3142 pDWP
->suggestedCount
++;
3144 pDWP
->winPos
[pDWP
->actualCount
].hwnd
= hwnd
;
3145 pDWP
->winPos
[pDWP
->actualCount
].hwndInsertAfter
= hwndAfter
;
3146 pDWP
->winPos
[pDWP
->actualCount
].x
= x
;
3147 pDWP
->winPos
[pDWP
->actualCount
].y
= y
;
3148 pDWP
->winPos
[pDWP
->actualCount
].cx
= cx
;
3149 pDWP
->winPos
[pDWP
->actualCount
].cy
= cy
;
3150 pDWP
->winPos
[pDWP
->actualCount
].flags
= flags
;
3151 pDWP
->actualCount
++;
3154 WIN_ReleaseWndPtr(pWnd
);
3159 /***********************************************************************
3160 * EndDeferWindowPos16 (USER.261)
3162 BOOL16 WINAPI
EndDeferWindowPos16( HDWP16 hdwp
)
3164 return EndDeferWindowPos( hdwp
);
3168 /***********************************************************************
3169 * EndDeferWindowPos (USER32.173)
3171 BOOL WINAPI
EndDeferWindowPos( HDWP hdwp
)
3178 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
3179 if (!pDWP
) return FALSE
;
3180 for (i
= 0, winpos
= pDWP
->winPos
; i
< pDWP
->actualCount
; i
++, winpos
++)
3182 if (!(res
= SetWindowPos( winpos
->hwnd
, winpos
->hwndInsertAfter
,
3183 winpos
->x
, winpos
->y
, winpos
->cx
,
3184 winpos
->cy
, winpos
->flags
))) break;
3186 USER_HEAP_FREE( hdwp
);
3191 /***********************************************************************
3192 * TileChildWindows (USER.199)
3194 void WINAPI
TileChildWindows16( HWND16 parent
, WORD action
)
3196 FIXME("(%04x, %d): stub\n", parent
, action
);
3199 /***********************************************************************
3200 * CascadeChildWindows (USER.198)
3202 void WINAPI
CascadeChildWindows16( HWND16 parent
, WORD action
)
3204 FIXME("(%04x, %d): stub\n", parent
, action
);
3207 /***********************************************************************
3208 * SetProgmanWindow [USER32.522]
3210 HRESULT WINAPI
SetProgmanWindow ( HWND hwnd
)
3212 hGlobalProgmanWindow
= hwnd
;
3213 return hGlobalProgmanWindow
;
3216 /***********************************************************************
3217 * GetProgmanWindow [USER32.289]
3219 HRESULT WINAPI
GetProgmanWindow ( )
3221 return hGlobalProgmanWindow
;
3224 /***********************************************************************
3225 * SetShellWindowEx [USER32.531]
3226 * hwndProgman = Progman[Program Manager]
3227 * |-> SHELLDLL_DefView
3228 * hwndListView = | |-> SysListView32
3229 * | | |-> tooltips_class32
3235 HRESULT WINAPI
SetShellWindowEx ( HWND hwndProgman
, HWND hwndListView
)
3237 FIXME("0x%08x 0x%08x stub\n",hwndProgman
,hwndListView
);
3238 hGlobalShellWindow
= hwndProgman
;
3239 return hGlobalShellWindow
;
3243 /***********************************************************************
3244 * SetTaskmanWindow [USER32.537]
3246 * hwnd = MSTaskSwWClass
3247 * |-> SysTabControl32
3249 HRESULT WINAPI
SetTaskmanWindow ( HWND hwnd
)
3251 hGlobalTaskmanWindow
= hwnd
;
3252 return hGlobalTaskmanWindow
;
3255 /***********************************************************************
3256 * GetTaskmanWindow [USER32.304]
3258 HRESULT WINAPI
GetTaskmanWindow ( )
3260 return hGlobalTaskmanWindow
;