2 * Window position related functions.
4 * Copyright 1993, 1994, 1995 Alexandre Julliard
5 * 1995, 1996, 1999 Alex Korobka
11 #include "wine/winuser16.h"
24 #include "nonclient.h"
25 #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 /***********************************************************************
275 BOOL WINAPI
GetWindowRgn ( HWND hwnd
, HRGN hrgn
)
279 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
280 if (!wndPtr
) return (ERROR
);
282 FIXME("GetWindowRgn: doesn't really do regions\n");
284 memset (&rect
, 0, sizeof(rect
));
286 GetWindowRect ( hwnd
, &rect
);
288 FIXME("Check whether a valid region here\n");
290 SetRectRgn ( hrgn
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
292 WIN_ReleaseWndPtr(wndPtr
);
293 return (SIMPLEREGION
);
296 /***********************************************************************
299 INT WINAPI
SetWindowRgn( HWND hwnd
, HRGN hrgn
,BOOL bRedraw
)
303 FIXME("SetWindowRgn: stub\n");
307 /***********************************************************************
310 INT16 WINAPI
SetWindowRgn16( HWND16 hwnd
, HRGN16 hrgn
,BOOL16 bRedraw
)
314 FIXME("SetWindowRgn16: stub\n");
319 /***********************************************************************
320 * GetClientRect16 (USER.33)
322 void WINAPI
GetClientRect16( HWND16 hwnd
, LPRECT16 rect
)
324 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
326 rect
->left
= rect
->top
= rect
->right
= rect
->bottom
= 0;
329 rect
->right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
330 rect
->bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
332 WIN_ReleaseWndPtr(wndPtr
);
336 /***********************************************************************
337 * GetClientRect (USER.220)
339 BOOL WINAPI
GetClientRect( HWND hwnd
, LPRECT rect
)
341 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
343 rect
->left
= rect
->top
= rect
->right
= rect
->bottom
= 0;
344 if (!wndPtr
) return FALSE
;
345 rect
->right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
346 rect
->bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
348 WIN_ReleaseWndPtr(wndPtr
);
353 /*******************************************************************
354 * ClientToScreen16 (USER.28)
356 void WINAPI
ClientToScreen16( HWND16 hwnd
, LPPOINT16 lppnt
)
358 MapWindowPoints16( hwnd
, 0, lppnt
, 1 );
362 /*******************************************************************
363 * ClientToScreen (USER32.52)
365 BOOL WINAPI
ClientToScreen( HWND hwnd
, LPPOINT lppnt
)
367 MapWindowPoints( hwnd
, 0, lppnt
, 1 );
372 /*******************************************************************
373 * ScreenToClient16 (USER.29)
375 void WINAPI
ScreenToClient16( HWND16 hwnd
, LPPOINT16 lppnt
)
377 MapWindowPoints16( 0, hwnd
, lppnt
, 1 );
381 /*******************************************************************
382 * ScreenToClient (USER32.447)
384 BOOL WINAPI
ScreenToClient( HWND hwnd
, LPPOINT lppnt
)
386 MapWindowPoints( 0, hwnd
, lppnt
, 1 );
391 /***********************************************************************
392 * WINPOS_WindowFromPoint
394 * Find the window and hittest for a given point.
396 INT16
WINPOS_WindowFromPoint( WND
* wndScope
, POINT16 pt
, WND
**ppWnd
)
399 INT16 hittest
= HTERROR
;
404 wndPtr
= WIN_LockWndPtr(wndScope
->child
);
406 if( wndScope
->flags
& WIN_MANAGED
)
408 /* In managed mode we have to check wndScope first as it is also
409 * a window which received the mouse event. */
411 if( wndScope
->dwStyle
& WS_DISABLED
)
416 if( pt
.x
< wndScope
->rectClient
.left
|| pt
.x
>= wndScope
->rectClient
.right
||
417 pt
.y
< wndScope
->rectClient
.top
|| pt
.y
>= wndScope
->rectClient
.bottom
)
420 MapWindowPoints16( GetDesktopWindow16(), wndScope
->hwndSelf
, &xy
, 1 );
426 /* If point is in window, and window is visible, and it */
427 /* is enabled (or it's a top-level window), then explore */
428 /* its children. Otherwise, go to the next window. */
430 if ((wndPtr
->dwStyle
& WS_VISIBLE
) &&
431 (!(wndPtr
->dwStyle
& WS_DISABLED
) ||
432 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)) &&
433 (xy
.x
>= wndPtr
->rectWindow
.left
) &&
434 (xy
.x
< wndPtr
->rectWindow
.right
) &&
435 (xy
.y
>= wndPtr
->rectWindow
.top
) &&
436 (xy
.y
< wndPtr
->rectWindow
.bottom
))
438 *ppWnd
= wndPtr
; /* Got a suitable window */
440 /* If window is minimized or disabled, return at once */
441 if (wndPtr
->dwStyle
& WS_MINIMIZE
)
443 retvalue
= HTCAPTION
;
446 if (wndPtr
->dwStyle
& WS_DISABLED
)
452 /* If point is not in client area, ignore the children */
453 if ((xy
.x
< wndPtr
->rectClient
.left
) ||
454 (xy
.x
>= wndPtr
->rectClient
.right
) ||
455 (xy
.y
< wndPtr
->rectClient
.top
) ||
456 (xy
.y
>= wndPtr
->rectClient
.bottom
)) break;
458 xy
.x
-= wndPtr
->rectClient
.left
;
459 xy
.y
-= wndPtr
->rectClient
.top
;
460 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->child
);
464 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->next
);
469 /* If nothing found, try the scope window */
470 if (!*ppWnd
) *ppWnd
= wndScope
;
472 /* Send the WM_NCHITTEST message (only if to the same task) */
473 if ((*ppWnd
)->hmemTaskQ
== GetFastQueue16())
475 hittest
= (INT16
)SendMessage16( (*ppWnd
)->hwndSelf
, WM_NCHITTEST
,
476 0, MAKELONG( pt
.x
, pt
.y
) );
477 if (hittest
!= HTTRANSPARENT
)
479 retvalue
= hittest
; /* Found the window */
489 /* If no children found in last search, make point relative to parent */
492 xy
.x
+= (*ppWnd
)->rectClient
.left
;
493 xy
.y
+= (*ppWnd
)->rectClient
.top
;
496 /* Restart the search from the next sibling */
497 WIN_UpdateWndPtr(&wndPtr
,(*ppWnd
)->next
);
498 *ppWnd
= (*ppWnd
)->parent
;
502 WIN_ReleaseWndPtr(wndPtr
);
507 /*******************************************************************
508 * WindowFromPoint16 (USER.30)
510 HWND16 WINAPI
WindowFromPoint16( POINT16 pt
)
513 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt
, &pWnd
);
514 WIN_ReleaseDesktop();
515 return pWnd
->hwndSelf
;
519 /*******************************************************************
520 * WindowFromPoint (USER32.582)
522 HWND WINAPI
WindowFromPoint( POINT pt
)
526 CONV_POINT32TO16( &pt
, &pt16
);
527 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16
, &pWnd
);
528 WIN_ReleaseDesktop();
529 return (HWND
)pWnd
->hwndSelf
;
533 /*******************************************************************
534 * ChildWindowFromPoint16 (USER.191)
536 HWND16 WINAPI
ChildWindowFromPoint16( HWND16 hwndParent
, POINT16 pt
)
539 CONV_POINT16TO32( &pt
, &pt32
);
540 return (HWND16
)ChildWindowFromPoint( hwndParent
, pt32
);
544 /*******************************************************************
545 * ChildWindowFromPoint (USER32.49)
547 HWND WINAPI
ChildWindowFromPoint( HWND hwndParent
, POINT pt
)
549 /* pt is in the client coordinates */
551 WND
* wnd
= WIN_FindWndPtr(hwndParent
);
557 /* get client rect fast */
558 rect
.top
= rect
.left
= 0;
559 rect
.right
= wnd
->rectClient
.right
- wnd
->rectClient
.left
;
560 rect
.bottom
= wnd
->rectClient
.bottom
- wnd
->rectClient
.top
;
562 if (!PtInRect( &rect
, pt
))
567 WIN_UpdateWndPtr(&wnd
,wnd
->child
);
570 if (PtInRect( &wnd
->rectWindow
, pt
))
572 retvalue
= wnd
->hwndSelf
;
575 WIN_UpdateWndPtr(&wnd
,wnd
->next
);
577 retvalue
= hwndParent
;
579 WIN_ReleaseWndPtr(wnd
);
583 /*******************************************************************
584 * ChildWindowFromPointEx16 (USER.50)
586 HWND16 WINAPI
ChildWindowFromPointEx16( HWND16 hwndParent
, POINT16 pt
, UINT16 uFlags
)
589 CONV_POINT16TO32( &pt
, &pt32
);
590 return (HWND16
)ChildWindowFromPointEx( hwndParent
, pt32
, uFlags
);
594 /*******************************************************************
595 * ChildWindowFromPointEx (USER32.50)
597 HWND WINAPI
ChildWindowFromPointEx( HWND hwndParent
, POINT pt
,
600 /* pt is in the client coordinates */
602 WND
* wnd
= WIN_FindWndPtr(hwndParent
);
608 /* get client rect fast */
609 rect
.top
= rect
.left
= 0;
610 rect
.right
= wnd
->rectClient
.right
- wnd
->rectClient
.left
;
611 rect
.bottom
= wnd
->rectClient
.bottom
- wnd
->rectClient
.top
;
613 if (!PtInRect( &rect
, pt
))
618 WIN_UpdateWndPtr(&wnd
,wnd
->child
);
622 if (PtInRect( &wnd
->rectWindow
, pt
)) {
623 if ( (uFlags
& CWP_SKIPINVISIBLE
) &&
624 !(wnd
->dwStyle
& WS_VISIBLE
) );
625 else if ( (uFlags
& CWP_SKIPDISABLED
) &&
626 (wnd
->dwStyle
& WS_DISABLED
) );
627 else if ( (uFlags
& CWP_SKIPTRANSPARENT
) &&
628 (wnd
->dwExStyle
& WS_EX_TRANSPARENT
) );
631 retvalue
= wnd
->hwndSelf
;
636 WIN_UpdateWndPtr(&wnd
,wnd
->next
);
638 retvalue
= hwndParent
;
640 WIN_ReleaseWndPtr(wnd
);
645 /*******************************************************************
646 * WINPOS_GetWinOffset
648 * Calculate the offset between the origin of the two windows. Used
649 * to implement MapWindowPoints.
651 static void WINPOS_GetWinOffset( HWND hwndFrom
, HWND hwndTo
,
656 offset
->x
= offset
->y
= 0;
657 if (hwndFrom
== hwndTo
) return;
659 /* Translate source window origin to screen coords */
662 if (!(wndPtr
= WIN_FindWndPtr( hwndFrom
)))
664 ERR("bad hwndFrom = %04x\n",hwndFrom
);
667 while (wndPtr
->parent
)
669 offset
->x
+= wndPtr
->rectClient
.left
;
670 offset
->y
+= wndPtr
->rectClient
.top
;
671 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->parent
);
673 WIN_ReleaseWndPtr(wndPtr
);
676 /* Translate origin to destination window coords */
679 if (!(wndPtr
= WIN_FindWndPtr( hwndTo
)))
681 ERR("bad hwndTo = %04x\n", hwndTo
);
684 while (wndPtr
->parent
)
686 offset
->x
-= wndPtr
->rectClient
.left
;
687 offset
->y
-= wndPtr
->rectClient
.top
;
688 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->parent
);
690 WIN_ReleaseWndPtr(wndPtr
);
695 /*******************************************************************
696 * MapWindowPoints16 (USER.258)
698 void WINAPI
MapWindowPoints16( HWND16 hwndFrom
, HWND16 hwndTo
,
699 LPPOINT16 lppt
, UINT16 count
)
703 WINPOS_GetWinOffset( hwndFrom
, hwndTo
, &offset
);
713 /*******************************************************************
714 * MapWindowPoints (USER32.386)
716 INT WINAPI
MapWindowPoints( HWND hwndFrom
, HWND hwndTo
,
717 LPPOINT lppt
, UINT count
)
721 WINPOS_GetWinOffset( hwndFrom
, hwndTo
, &offset
);
728 return MAKELONG( LOWORD(offset
.x
), LOWORD(offset
.y
) );
732 /***********************************************************************
733 * IsIconic16 (USER.31)
735 BOOL16 WINAPI
IsIconic16(HWND16 hWnd
)
737 return IsIconic(hWnd
);
741 /***********************************************************************
742 * IsIconic (USER32.345)
744 BOOL WINAPI
IsIconic(HWND hWnd
)
747 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
748 if (wndPtr
== NULL
) return FALSE
;
749 retvalue
= (wndPtr
->dwStyle
& WS_MINIMIZE
) != 0;
750 WIN_ReleaseWndPtr(wndPtr
);
755 /***********************************************************************
756 * IsZoomed (USER.272)
758 BOOL16 WINAPI
IsZoomed16(HWND16 hWnd
)
760 return IsZoomed(hWnd
);
764 /***********************************************************************
765 * IsZoomed (USER.352)
767 BOOL WINAPI
IsZoomed(HWND hWnd
)
770 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
771 if (wndPtr
== NULL
) return FALSE
;
772 retvalue
= (wndPtr
->dwStyle
& WS_MAXIMIZE
) != 0;
773 WIN_ReleaseWndPtr(wndPtr
);
778 /*******************************************************************
779 * GetActiveWindow (USER.60)
781 HWND16 WINAPI
GetActiveWindow16(void)
783 return (HWND16
)GetActiveWindow();
786 /*******************************************************************
787 * GetActiveWindow (USER32.205)
789 HWND WINAPI
GetActiveWindow(void)
791 MESSAGEQUEUE
*pCurMsgQ
= 0;
794 /* Get the messageQ for the current thread */
795 if (!(pCurMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( GetFastQueue16() )))
797 WARN("\tCurrent message queue not found. Exiting!\n" );
801 /* Return the current active window from the perQ data of the current message Q */
802 hwndActive
= PERQDATA_GetActiveWnd( pCurMsgQ
->pQData
);
804 QUEUE_Unlock( pCurMsgQ
);
809 /*******************************************************************
812 static BOOL
WINPOS_CanActivate(WND
* pWnd
)
814 if( pWnd
&& ( (pWnd
->dwStyle
& (WS_DISABLED
| WS_VISIBLE
| WS_CHILD
))
815 == WS_VISIBLE
) ) return TRUE
;
820 /*******************************************************************
821 * SetActiveWindow16 (USER.59)
823 HWND16 WINAPI
SetActiveWindow16( HWND16 hwnd
)
825 return SetActiveWindow(hwnd
);
829 /*******************************************************************
830 * SetActiveWindow (USER32.463)
832 HWND WINAPI
SetActiveWindow( HWND hwnd
)
835 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
836 MESSAGEQUEUE
*pMsgQ
= 0, *pCurMsgQ
= 0;
838 if (!wndPtr
|| (wndPtr
->dwStyle
& (WS_DISABLED
| WS_CHILD
)))
844 /* Get the messageQ for the current thread */
845 if (!(pCurMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( GetFastQueue16() )))
847 WARN("\tCurrent message queue not found. Exiting!\n" );
851 /* Retrieve the message queue associated with this window */
852 pMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( wndPtr
->hmemTaskQ
);
855 WARN("\tWindow message queue not found. Exiting!\n" );
859 /* Make sure that the window is associated with the calling threads
860 * message queue. It must share the same perQ data.
863 if ( pCurMsgQ
->pQData
!= pMsgQ
->pQData
)
866 /* Save current active window */
867 prev
= PERQDATA_GetActiveWnd( pMsgQ
->pQData
);
869 WINPOS_SetActiveWindow( hwnd
, 0, 0 );
872 /* Unlock the queues before returning */
874 QUEUE_Unlock( pMsgQ
);
876 QUEUE_Unlock( pCurMsgQ
);
879 WIN_ReleaseWndPtr(wndPtr
);
884 /*******************************************************************
885 * GetForegroundWindow16 (USER.608)
887 HWND16 WINAPI
GetForegroundWindow16(void)
889 return (HWND16
)GetForegroundWindow();
893 /*******************************************************************
894 * SetForegroundWindow16 (USER.609)
896 BOOL16 WINAPI
SetForegroundWindow16( HWND16 hwnd
)
898 return SetForegroundWindow( hwnd
);
902 /*******************************************************************
903 * GetForegroundWindow (USER32.241)
905 HWND WINAPI
GetForegroundWindow(void)
909 /* Get the foreground window (active window of hActiveQueue) */
912 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
914 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
916 QUEUE_Unlock( pActiveQueue
);
922 /*******************************************************************
923 * SetForegroundWindow (USER32.482)
925 BOOL WINAPI
SetForegroundWindow( HWND hwnd
)
927 return WINPOS_ChangeActiveWindow( hwnd
, FALSE
);
931 /*******************************************************************
932 * GetShellWindow16 (USER.600)
934 HWND16 WINAPI
GetShellWindow16(void)
936 return GetShellWindow();
939 /*******************************************************************
940 * SetShellWindow (USER32.504)
942 HWND WINAPI
SetShellWindow(HWND hwndshell
)
943 { WARN("(hWnd=%08x) semi stub\n",hwndshell
);
945 hGlobalShellWindow
= hwndshell
;
946 return hGlobalShellWindow
;
950 /*******************************************************************
951 * GetShellWindow (USER32.287)
953 HWND WINAPI
GetShellWindow(void)
954 { WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow
);
956 return hGlobalShellWindow
;
960 /***********************************************************************
961 * BringWindowToTop16 (USER.45)
963 BOOL16 WINAPI
BringWindowToTop16( HWND16 hwnd
)
965 return BringWindowToTop(hwnd
);
969 /***********************************************************************
970 * BringWindowToTop (USER32.11)
972 BOOL WINAPI
BringWindowToTop( HWND hwnd
)
974 return SetWindowPos( hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
);
978 /***********************************************************************
979 * MoveWindow16 (USER.56)
981 BOOL16 WINAPI
MoveWindow16( HWND16 hwnd
, INT16 x
, INT16 y
, INT16 cx
, INT16 cy
,
984 return MoveWindow(hwnd
,x
,y
,cx
,cy
,repaint
);
988 /***********************************************************************
989 * MoveWindow (USER32.399)
991 BOOL WINAPI
MoveWindow( HWND hwnd
, INT x
, INT y
, INT cx
, INT cy
,
994 int flags
= SWP_NOZORDER
| SWP_NOACTIVATE
;
995 if (!repaint
) flags
|= SWP_NOREDRAW
;
996 TRACE("%04x %d,%d %dx%d %d\n",
997 hwnd
, x
, y
, cx
, cy
, repaint
);
998 return SetWindowPos( hwnd
, 0, x
, y
, cx
, cy
, flags
);
1001 /***********************************************************************
1002 * WINPOS_InitInternalPos
1004 static LPINTERNALPOS
WINPOS_InitInternalPos( WND
* wnd
, POINT pt
,
1005 LPRECT restoreRect
)
1007 LPINTERNALPOS lpPos
= (LPINTERNALPOS
) GetPropA( wnd
->hwndSelf
,
1011 /* this happens when the window is minimized/maximized
1012 * for the first time (rectWindow is not adjusted yet) */
1014 lpPos
= HeapAlloc( SystemHeap
, 0, sizeof(INTERNALPOS
) );
1015 if( !lpPos
) return NULL
;
1017 SetPropA( wnd
->hwndSelf
, atomInternalPos
, (HANDLE
)lpPos
);
1018 lpPos
->hwndIconTitle
= 0; /* defer until needs to be shown */
1019 CONV_RECT32TO16( &wnd
->rectWindow
, &lpPos
->rectNormal
);
1020 *(UINT
*)&lpPos
->ptIconPos
= *(UINT
*)&lpPos
->ptMaxPos
= 0xFFFFFFFF;
1023 if( wnd
->dwStyle
& WS_MINIMIZE
)
1024 CONV_POINT32TO16( &pt
, &lpPos
->ptIconPos
);
1025 else if( wnd
->dwStyle
& WS_MAXIMIZE
)
1026 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1027 else if( restoreRect
)
1028 CONV_RECT32TO16( restoreRect
, &lpPos
->rectNormal
);
1033 /***********************************************************************
1034 * WINPOS_RedrawIconTitle
1036 BOOL
WINPOS_RedrawIconTitle( HWND hWnd
)
1038 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)GetPropA( hWnd
, atomInternalPos
);
1041 if( lpPos
->hwndIconTitle
)
1043 SendMessageA( lpPos
->hwndIconTitle
, WM_SHOWWINDOW
, TRUE
, 0);
1044 InvalidateRect( lpPos
->hwndIconTitle
, NULL
, TRUE
);
1051 /***********************************************************************
1052 * WINPOS_ShowIconTitle
1054 BOOL
WINPOS_ShowIconTitle( WND
* pWnd
, BOOL bShow
)
1056 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)GetPropA( pWnd
->hwndSelf
, atomInternalPos
);
1058 if( lpPos
&& !(pWnd
->flags
& WIN_MANAGED
))
1060 HWND16 hWnd
= lpPos
->hwndIconTitle
;
1062 TRACE("0x%04x %i\n", pWnd
->hwndSelf
, (bShow
!= 0) );
1065 lpPos
->hwndIconTitle
= hWnd
= ICONTITLE_Create( pWnd
);
1068 if( ( pWnd
= WIN_FindWndPtr(hWnd
) ) != NULL
)
1070 if( !(pWnd
->dwStyle
& WS_VISIBLE
) )
1072 SendMessageA( hWnd
, WM_SHOWWINDOW
, TRUE
, 0 );
1073 SetWindowPos( hWnd
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
1074 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_SHOWWINDOW
);
1076 WIN_ReleaseWndPtr(pWnd
);
1079 else ShowWindow( hWnd
, SW_HIDE
);
1084 /*******************************************************************
1085 * WINPOS_GetMinMaxInfo
1087 * Get the minimized and maximized information for a window.
1089 void WINPOS_GetMinMaxInfo( WND
*wndPtr
, POINT
*maxSize
, POINT
*maxPos
,
1090 POINT
*minTrack
, POINT
*maxTrack
)
1092 LPINTERNALPOS lpPos
;
1096 /* Compute default values */
1098 MinMax
.ptMaxSize
.x
= GetSystemMetrics(SM_CXSCREEN
);
1099 MinMax
.ptMaxSize
.y
= GetSystemMetrics(SM_CYSCREEN
);
1100 MinMax
.ptMinTrackSize
.x
= GetSystemMetrics(SM_CXMINTRACK
);
1101 MinMax
.ptMinTrackSize
.y
= GetSystemMetrics(SM_CYMINTRACK
);
1102 MinMax
.ptMaxTrackSize
.x
= GetSystemMetrics(SM_CXSCREEN
);
1103 MinMax
.ptMaxTrackSize
.y
= GetSystemMetrics(SM_CYSCREEN
);
1105 if (wndPtr
->flags
& WIN_MANAGED
) xinc
= yinc
= 0;
1106 else if (HAS_DLGFRAME( wndPtr
->dwStyle
, wndPtr
->dwExStyle
))
1108 xinc
= GetSystemMetrics(SM_CXDLGFRAME
);
1109 yinc
= GetSystemMetrics(SM_CYDLGFRAME
);
1114 if (HAS_THICKFRAME(wndPtr
->dwStyle
))
1116 xinc
+= GetSystemMetrics(SM_CXFRAME
);
1117 yinc
+= GetSystemMetrics(SM_CYFRAME
);
1119 if (wndPtr
->dwStyle
& WS_BORDER
)
1121 xinc
+= GetSystemMetrics(SM_CXBORDER
);
1122 yinc
+= GetSystemMetrics(SM_CYBORDER
);
1125 MinMax
.ptMaxSize
.x
+= 2 * xinc
;
1126 MinMax
.ptMaxSize
.y
+= 2 * yinc
;
1128 lpPos
= (LPINTERNALPOS
)GetPropA( wndPtr
->hwndSelf
, atomInternalPos
);
1129 if( lpPos
&& !EMPTYPOINT(lpPos
->ptMaxPos
) )
1130 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &MinMax
.ptMaxPosition
);
1133 MinMax
.ptMaxPosition
.x
= -xinc
;
1134 MinMax
.ptMaxPosition
.y
= -yinc
;
1137 SendMessageA( wndPtr
->hwndSelf
, WM_GETMINMAXINFO
, 0, (LPARAM
)&MinMax
);
1139 /* Some sanity checks */
1141 TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1142 MinMax
.ptMaxSize
.x
, MinMax
.ptMaxSize
.y
,
1143 MinMax
.ptMaxPosition
.x
, MinMax
.ptMaxPosition
.y
,
1144 MinMax
.ptMaxTrackSize
.x
, MinMax
.ptMaxTrackSize
.y
,
1145 MinMax
.ptMinTrackSize
.x
, MinMax
.ptMinTrackSize
.y
);
1146 MinMax
.ptMaxTrackSize
.x
= max( MinMax
.ptMaxTrackSize
.x
,
1147 MinMax
.ptMinTrackSize
.x
);
1148 MinMax
.ptMaxTrackSize
.y
= max( MinMax
.ptMaxTrackSize
.y
,
1149 MinMax
.ptMinTrackSize
.y
);
1151 if (maxSize
) *maxSize
= MinMax
.ptMaxSize
;
1152 if (maxPos
) *maxPos
= MinMax
.ptMaxPosition
;
1153 if (minTrack
) *minTrack
= MinMax
.ptMinTrackSize
;
1154 if (maxTrack
) *maxTrack
= MinMax
.ptMaxTrackSize
;
1157 /***********************************************************************
1158 * WINPOS_MinMaximize
1160 * Fill in lpRect and return additional flags to be used with SetWindowPos().
1161 * This function assumes that 'cmd' is different from the current window
1164 UINT
WINPOS_MinMaximize( WND
* wndPtr
, UINT16 cmd
, LPRECT16 lpRect
)
1168 LPINTERNALPOS lpPos
;
1170 TRACE("0x%04x %u\n", wndPtr
->hwndSelf
, cmd
);
1172 size
.x
= wndPtr
->rectWindow
.left
; size
.y
= wndPtr
->rectWindow
.top
;
1173 lpPos
= WINPOS_InitInternalPos( wndPtr
, size
, &wndPtr
->rectWindow
);
1175 if (lpPos
&& !HOOK_CallHooks16(WH_CBT
, HCBT_MINMAX
, wndPtr
->hwndSelf
, cmd
))
1177 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1179 if( !SendMessageA( wndPtr
->hwndSelf
, WM_QUERYOPEN
, 0, 0L ) )
1180 return (SWP_NOSIZE
| SWP_NOMOVE
);
1181 swpFlags
|= SWP_NOCOPYBITS
;
1186 if( wndPtr
->dwStyle
& WS_MAXIMIZE
)
1188 wndPtr
->flags
|= WIN_RESTORE_MAX
;
1189 wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
1192 wndPtr
->flags
&= ~WIN_RESTORE_MAX
;
1193 wndPtr
->dwStyle
|= WS_MINIMIZE
;
1195 if( wndPtr
->flags
& WIN_NATIVE
)
1196 if( wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, TRUE
) )
1197 swpFlags
|= MINMAX_NOSWP
;
1199 lpPos
->ptIconPos
= WINPOS_FindIconPos( wndPtr
, lpPos
->ptIconPos
);
1201 SetRect16( lpRect
, lpPos
->ptIconPos
.x
, lpPos
->ptIconPos
.y
,
1202 GetSystemMetrics(SM_CXICON
), GetSystemMetrics(SM_CYICON
) );
1203 swpFlags
|= SWP_NOCOPYBITS
;
1207 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &pt
);
1208 WINPOS_GetMinMaxInfo( wndPtr
, &size
, &pt
, NULL
, NULL
);
1209 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1211 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1213 if( wndPtr
->flags
& WIN_NATIVE
)
1214 if( wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, FALSE
) )
1215 swpFlags
|= MINMAX_NOSWP
;
1217 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
1218 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
1220 wndPtr
->dwStyle
|= WS_MAXIMIZE
;
1222 SetRect16( lpRect
, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
,
1227 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1229 if( wndPtr
->flags
& WIN_NATIVE
)
1230 if( wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, FALSE
) )
1231 swpFlags
|= MINMAX_NOSWP
;
1233 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
1234 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
1236 if( wndPtr
->flags
& WIN_RESTORE_MAX
)
1238 /* Restore to maximized position */
1239 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &pt
);
1240 WINPOS_GetMinMaxInfo( wndPtr
, &size
, &pt
, NULL
, NULL
);
1241 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1242 wndPtr
->dwStyle
|= WS_MAXIMIZE
;
1243 SetRect16( lpRect
, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
, size
.x
, size
.y
);
1248 if( !(wndPtr
->dwStyle
& WS_MAXIMIZE
) ) return (UINT16
)(-1);
1249 else wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
1251 /* Restore to normal position */
1253 *lpRect
= lpPos
->rectNormal
;
1254 lpRect
->right
-= lpRect
->left
;
1255 lpRect
->bottom
-= lpRect
->top
;
1259 } else swpFlags
|= SWP_NOSIZE
| SWP_NOMOVE
;
1263 /***********************************************************************
1264 * ShowWindowAsync (USER32.535)
1266 * doesn't wait; returns immediately.
1267 * used by threads to toggle windows in other (possibly hanging) threads
1269 BOOL WINAPI
ShowWindowAsync( HWND hwnd
, INT cmd
)
1271 /* FIXME: does ShowWindow() return immediately ? */
1272 return ShowWindow(hwnd
, cmd
);
1276 /***********************************************************************
1277 * ShowWindow16 (USER.42)
1279 BOOL16 WINAPI
ShowWindow16( HWND16 hwnd
, INT16 cmd
)
1281 return ShowWindow(hwnd
,cmd
);
1285 /***********************************************************************
1286 * ShowWindow (USER32.534)
1288 BOOL WINAPI
ShowWindow( HWND hwnd
, INT cmd
)
1290 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
1291 BOOL wasVisible
, showFlag
;
1292 RECT16 newPos
= {0, 0, 0, 0};
1295 if (!wndPtr
) return FALSE
;
1297 TRACE("hwnd=%04x, cmd=%d\n", hwnd
, cmd
);
1299 wasVisible
= (wndPtr
->dwStyle
& WS_VISIBLE
) != 0;
1304 if (!wasVisible
) goto END
;;
1305 swp
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
|
1306 SWP_NOACTIVATE
| SWP_NOZORDER
;
1309 case SW_SHOWMINNOACTIVE
:
1310 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1312 case SW_SHOWMINIMIZED
:
1313 swp
|= SWP_SHOWWINDOW
;
1316 swp
|= SWP_FRAMECHANGED
;
1317 if( !(wndPtr
->dwStyle
& WS_MINIMIZE
) )
1318 swp
|= WINPOS_MinMaximize( wndPtr
, SW_MINIMIZE
, &newPos
);
1319 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1322 case SW_SHOWMAXIMIZED
: /* same as SW_MAXIMIZE */
1323 swp
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
1324 if( !(wndPtr
->dwStyle
& WS_MAXIMIZE
) )
1325 swp
|= WINPOS_MinMaximize( wndPtr
, SW_MAXIMIZE
, &newPos
);
1326 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1330 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1333 swp
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
1336 * ShowWindow has a little peculiar behavior that if the
1337 * window is already the topmost window, it will not
1340 if (GetTopWindow((HWND
)0)==hwnd
&& (wasVisible
|| GetActiveWindow() == hwnd
))
1341 swp
|= SWP_NOACTIVATE
;
1345 case SW_SHOWNOACTIVATE
:
1346 swp
|= SWP_NOZORDER
;
1347 if (GetActiveWindow()) swp
|= SWP_NOACTIVATE
;
1349 case SW_SHOWNORMAL
: /* same as SW_NORMAL: */
1350 case SW_SHOWDEFAULT
: /* FIXME: should have its own handler */
1352 swp
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
1354 if( wndPtr
->dwStyle
& (WS_MINIMIZE
| WS_MAXIMIZE
) )
1355 swp
|= WINPOS_MinMaximize( wndPtr
, SW_RESTORE
, &newPos
);
1356 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1360 showFlag
= (cmd
!= SW_HIDE
);
1361 if (showFlag
!= wasVisible
)
1363 SendMessageA( hwnd
, WM_SHOWWINDOW
, showFlag
, 0 );
1364 if (!IsWindow( hwnd
)) goto END
;
1367 if ((wndPtr
->dwStyle
& WS_CHILD
) &&
1368 !IsWindowVisible( wndPtr
->parent
->hwndSelf
) &&
1369 (swp
& (SWP_NOSIZE
| SWP_NOMOVE
)) == (SWP_NOSIZE
| SWP_NOMOVE
) )
1371 /* Don't call SetWindowPos() on invisible child windows */
1372 if (cmd
== SW_HIDE
) wndPtr
->dwStyle
&= ~WS_VISIBLE
;
1373 else wndPtr
->dwStyle
|= WS_VISIBLE
;
1377 /* We can't activate a child window */
1378 if ((wndPtr
->dwStyle
& WS_CHILD
) &&
1379 !(wndPtr
->dwExStyle
& WS_EX_MDICHILD
))
1380 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1381 if (!(swp
& MINMAX_NOSWP
))
1383 SetWindowPos( hwnd
, HWND_TOP
, newPos
.left
, newPos
.top
,
1384 newPos
.right
, newPos
.bottom
, LOWORD(swp
) );
1387 /* FIXME: This will cause the window to be activated irrespective
1388 * of whether it is owned by the same thread. Has to be done
1392 if (hwnd
== GetActiveWindow())
1393 WINPOS_ActivateOtherWindow(wndPtr
);
1395 /* Revert focus to parent */
1396 if (hwnd
== GetFocus() || IsChild(hwnd
, GetFocus()))
1397 SetFocus( GetParent(hwnd
) );
1400 if (!IsWindow( hwnd
)) goto END
;
1401 else if( wndPtr
->dwStyle
& WS_MINIMIZE
) WINPOS_ShowIconTitle( wndPtr
, TRUE
);
1404 if (wndPtr
->flags
& WIN_NEED_SIZE
)
1406 /* should happen only in CreateWindowEx() */
1407 int wParam
= SIZE_RESTORED
;
1409 wndPtr
->flags
&= ~WIN_NEED_SIZE
;
1410 if (wndPtr
->dwStyle
& WS_MAXIMIZE
) wParam
= SIZE_MAXIMIZED
;
1411 else if (wndPtr
->dwStyle
& WS_MINIMIZE
) wParam
= SIZE_MINIMIZED
;
1412 SendMessageA( hwnd
, WM_SIZE
, wParam
,
1413 MAKELONG(wndPtr
->rectClient
.right
-wndPtr
->rectClient
.left
,
1414 wndPtr
->rectClient
.bottom
-wndPtr
->rectClient
.top
));
1415 SendMessageA( hwnd
, WM_MOVE
, 0,
1416 MAKELONG(wndPtr
->rectClient
.left
, wndPtr
->rectClient
.top
) );
1420 WIN_ReleaseWndPtr(wndPtr
);
1425 /***********************************************************************
1426 * GetInternalWindowPos16 (USER.460)
1428 UINT16 WINAPI
GetInternalWindowPos16( HWND16 hwnd
, LPRECT16 rectWnd
,
1431 WINDOWPLACEMENT16 wndpl
;
1432 if (GetWindowPlacement16( hwnd
, &wndpl
))
1434 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
1435 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
1436 return wndpl
.showCmd
;
1442 /***********************************************************************
1443 * GetInternalWindowPos (USER32.245)
1445 UINT WINAPI
GetInternalWindowPos( HWND hwnd
, LPRECT rectWnd
,
1448 WINDOWPLACEMENT wndpl
;
1449 if (GetWindowPlacement( hwnd
, &wndpl
))
1451 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
1452 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
1453 return wndpl
.showCmd
;
1458 /***********************************************************************
1459 * GetWindowPlacement16 (USER.370)
1461 BOOL16 WINAPI
GetWindowPlacement16( HWND16 hwnd
, WINDOWPLACEMENT16
*wndpl
)
1463 WND
*pWnd
= WIN_FindWndPtr( hwnd
);
1464 LPINTERNALPOS lpPos
;
1466 if(!pWnd
) return FALSE
;
1468 lpPos
= (LPINTERNALPOS
)WINPOS_InitInternalPos( pWnd
,
1469 *(LPPOINT
)&pWnd
->rectWindow
.left
, &pWnd
->rectWindow
);
1470 wndpl
->length
= sizeof(*wndpl
);
1471 if( pWnd
->dwStyle
& WS_MINIMIZE
)
1472 wndpl
->showCmd
= SW_SHOWMINIMIZED
;
1474 wndpl
->showCmd
= ( pWnd
->dwStyle
& WS_MAXIMIZE
)
1475 ? SW_SHOWMAXIMIZED
: SW_SHOWNORMAL
;
1476 if( pWnd
->flags
& WIN_RESTORE_MAX
)
1477 wndpl
->flags
= WPF_RESTORETOMAXIMIZED
;
1480 wndpl
->ptMinPosition
= lpPos
->ptIconPos
;
1481 wndpl
->ptMaxPosition
= lpPos
->ptMaxPos
;
1482 wndpl
->rcNormalPosition
= lpPos
->rectNormal
;
1484 WIN_ReleaseWndPtr(pWnd
);
1489 /***********************************************************************
1490 * GetWindowPlacement (USER32.307)
1493 * Fails if wndpl->length of Win95 (!) apps is invalid.
1495 BOOL WINAPI
GetWindowPlacement( HWND hwnd
, WINDOWPLACEMENT
*pwpl32
)
1499 WINDOWPLACEMENT16 wpl
;
1500 wpl
.length
= sizeof(wpl
);
1501 if( GetWindowPlacement16( hwnd
, &wpl
) )
1503 pwpl32
->length
= sizeof(*pwpl32
);
1504 pwpl32
->flags
= wpl
.flags
;
1505 pwpl32
->showCmd
= wpl
.showCmd
;
1506 CONV_POINT16TO32( &wpl
.ptMinPosition
, &pwpl32
->ptMinPosition
);
1507 CONV_POINT16TO32( &wpl
.ptMaxPosition
, &pwpl32
->ptMaxPosition
);
1508 CONV_RECT16TO32( &wpl
.rcNormalPosition
, &pwpl32
->rcNormalPosition
);
1516 /***********************************************************************
1517 * WINPOS_SetPlacement
1519 static BOOL
WINPOS_SetPlacement( HWND hwnd
, const WINDOWPLACEMENT16
*wndpl
,
1522 WND
*pWnd
= WIN_FindWndPtr( hwnd
);
1525 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)WINPOS_InitInternalPos( pWnd
,
1526 *(LPPOINT
)&pWnd
->rectWindow
.left
, &pWnd
->rectWindow
);
1528 if( flags
& PLACE_MIN
) lpPos
->ptIconPos
= wndpl
->ptMinPosition
;
1529 if( flags
& PLACE_MAX
) lpPos
->ptMaxPos
= wndpl
->ptMaxPosition
;
1530 if( flags
& PLACE_RECT
) lpPos
->rectNormal
= wndpl
->rcNormalPosition
;
1532 if( pWnd
->dwStyle
& WS_MINIMIZE
)
1534 WINPOS_ShowIconTitle( pWnd
, FALSE
);
1535 if( wndpl
->flags
& WPF_SETMINPOSITION
&& !EMPTYPOINT(lpPos
->ptIconPos
))
1536 SetWindowPos( hwnd
, 0, lpPos
->ptIconPos
.x
, lpPos
->ptIconPos
.y
,
1537 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1539 else if( pWnd
->dwStyle
& WS_MAXIMIZE
)
1541 if( !EMPTYPOINT(lpPos
->ptMaxPos
) )
1542 SetWindowPos( hwnd
, 0, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
,
1543 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1545 else if( flags
& PLACE_RECT
)
1546 SetWindowPos( hwnd
, 0, lpPos
->rectNormal
.left
, lpPos
->rectNormal
.top
,
1547 lpPos
->rectNormal
.right
- lpPos
->rectNormal
.left
,
1548 lpPos
->rectNormal
.bottom
- lpPos
->rectNormal
.top
,
1549 SWP_NOZORDER
| SWP_NOACTIVATE
);
1551 ShowWindow( hwnd
, wndpl
->showCmd
);
1552 if( IsWindow(hwnd
) && pWnd
->dwStyle
& WS_MINIMIZE
)
1554 if( pWnd
->dwStyle
& WS_VISIBLE
) WINPOS_ShowIconTitle( pWnd
, TRUE
);
1556 /* SDK: ...valid only the next time... */
1557 if( wndpl
->flags
& WPF_RESTORETOMAXIMIZED
) pWnd
->flags
|= WIN_RESTORE_MAX
;
1559 WIN_ReleaseWndPtr(pWnd
);
1566 /***********************************************************************
1567 * SetWindowPlacement16 (USER.371)
1569 BOOL16 WINAPI
SetWindowPlacement16(HWND16 hwnd
, const WINDOWPLACEMENT16
*wndpl
)
1571 return WINPOS_SetPlacement( hwnd
, wndpl
,
1572 PLACE_MIN
| PLACE_MAX
| PLACE_RECT
);
1575 /***********************************************************************
1576 * SetWindowPlacement (USER32.519)
1579 * Fails if wndpl->length of Win95 (!) apps is invalid.
1581 BOOL WINAPI
SetWindowPlacement( HWND hwnd
, const WINDOWPLACEMENT
*pwpl32
)
1585 WINDOWPLACEMENT16 wpl
;
1587 wpl
.length
= sizeof(WINDOWPLACEMENT16
);
1588 wpl
.flags
= pwpl32
->flags
;
1589 wpl
.showCmd
= pwpl32
->showCmd
;
1590 wpl
.ptMinPosition
.x
= pwpl32
->ptMinPosition
.x
;
1591 wpl
.ptMinPosition
.y
= pwpl32
->ptMinPosition
.y
;
1592 wpl
.ptMaxPosition
.x
= pwpl32
->ptMaxPosition
.x
;
1593 wpl
.ptMaxPosition
.y
= pwpl32
->ptMaxPosition
.y
;
1594 wpl
.rcNormalPosition
.left
= pwpl32
->rcNormalPosition
.left
;
1595 wpl
.rcNormalPosition
.top
= pwpl32
->rcNormalPosition
.top
;
1596 wpl
.rcNormalPosition
.right
= pwpl32
->rcNormalPosition
.right
;
1597 wpl
.rcNormalPosition
.bottom
= pwpl32
->rcNormalPosition
.bottom
;
1599 return WINPOS_SetPlacement( hwnd
, &wpl
, PLACE_MIN
| PLACE_MAX
| PLACE_RECT
);
1605 /***********************************************************************
1606 * SetInternalWindowPos16 (USER.461)
1608 void WINAPI
SetInternalWindowPos16( HWND16 hwnd
, UINT16 showCmd
,
1609 LPRECT16 rect
, LPPOINT16 pt
)
1611 if( IsWindow16(hwnd
) )
1613 WINDOWPLACEMENT16 wndpl
;
1616 wndpl
.length
= sizeof(wndpl
);
1617 wndpl
.showCmd
= showCmd
;
1618 wndpl
.flags
= flags
= 0;
1623 wndpl
.flags
|= WPF_SETMINPOSITION
;
1624 wndpl
.ptMinPosition
= *pt
;
1628 flags
|= PLACE_RECT
;
1629 wndpl
.rcNormalPosition
= *rect
;
1631 WINPOS_SetPlacement( hwnd
, &wndpl
, flags
);
1636 /***********************************************************************
1637 * SetInternalWindowPos (USER32.483)
1639 void WINAPI
SetInternalWindowPos( HWND hwnd
, UINT showCmd
,
1640 LPRECT rect
, LPPOINT pt
)
1642 if( IsWindow(hwnd
) )
1644 WINDOWPLACEMENT16 wndpl
;
1647 wndpl
.length
= sizeof(wndpl
);
1648 wndpl
.showCmd
= showCmd
;
1649 wndpl
.flags
= flags
= 0;
1654 wndpl
.flags
|= WPF_SETMINPOSITION
;
1655 CONV_POINT32TO16( pt
, &wndpl
.ptMinPosition
);
1659 flags
|= PLACE_RECT
;
1660 CONV_RECT32TO16( rect
, &wndpl
.rcNormalPosition
);
1662 WINPOS_SetPlacement( hwnd
, &wndpl
, flags
);
1666 /*******************************************************************
1667 * WINPOS_SetActiveWindow
1669 * SetActiveWindow() back-end. This is the only function that
1670 * can assign active status to a window. It must be called only
1671 * for the top level windows.
1673 BOOL
WINPOS_SetActiveWindow( HWND hWnd
, BOOL fMouse
, BOOL fChangeFocus
)
1675 CBTACTIVATESTRUCT16
* cbtStruct
;
1676 WND
* wndPtr
=0, *wndTemp
;
1677 HQUEUE16 hOldActiveQueue
, hNewActiveQueue
;
1678 MESSAGEQUEUE
*pOldActiveQueue
= 0, *pNewActiveQueue
= 0;
1680 HWND hwndActive
= 0;
1683 TRACE("(%04x, %d, %d)\n", hWnd
, fMouse
, fChangeFocus
);
1685 /* Get current active window from the active queue */
1688 pOldActiveQueue
= QUEUE_Lock( hActiveQueue
);
1689 if ( pOldActiveQueue
)
1690 hwndActive
= PERQDATA_GetActiveWnd( pOldActiveQueue
->pQData
);
1693 /* paranoid checks */
1694 if( hWnd
== GetDesktopWindow() || (bRet
= (hWnd
== hwndActive
)) )
1697 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1700 wndPtr
= WIN_FindWndPtr(hWnd
);
1701 hOldActiveQueue
= hActiveQueue
;
1703 if( (wndTemp
= WIN_FindWndPtr(hwndActive
)) )
1705 wIconized
= HIWORD(wndTemp
->dwStyle
& WS_MINIMIZE
);
1706 WIN_ReleaseWndPtr(wndTemp
);
1709 TRACE("no current active window.\n");
1711 /* call CBT hook chain */
1712 if ((cbtStruct
= SEGPTR_NEW(CBTACTIVATESTRUCT16
)))
1714 cbtStruct
->fMouse
= fMouse
;
1715 cbtStruct
->hWndActive
= hwndActive
;
1716 bRet
= (BOOL
)HOOK_CallHooks16( WH_CBT
, HCBT_ACTIVATE
, (WPARAM16
)hWnd
,
1717 (LPARAM
)SEGPTR_GET(cbtStruct
) );
1718 SEGPTR_FREE(cbtStruct
);
1719 if (bRet
) goto CLEANUP_END
;
1722 /* set prev active wnd to current active wnd and send notification */
1723 if ((hwndPrevActive
= hwndActive
) && IsWindow(hwndPrevActive
))
1725 MESSAGEQUEUE
*pTempActiveQueue
= 0;
1727 if (!SendMessageA( hwndPrevActive
, WM_NCACTIVATE
, FALSE
, 0 ))
1729 if (GetSysModalWindow16() != hWnd
)
1731 /* disregard refusal if hWnd is sysmodal */
1734 SendMessageA( hwndPrevActive
, WM_ACTIVATE
,
1735 MAKEWPARAM( WA_INACTIVE
, wIconized
),
1738 /* check if something happened during message processing
1739 * (global active queue may have changed)
1741 pTempActiveQueue
= QUEUE_Lock( hActiveQueue
);
1742 if(!pTempActiveQueue
)
1745 hwndActive
= PERQDATA_GetActiveWnd( pTempActiveQueue
->pQData
);
1746 QUEUE_Unlock( pTempActiveQueue
);
1747 if( hwndPrevActive
!= hwndActive
)
1751 /* Set new active window in the message queue */
1755 pNewActiveQueue
= QUEUE_Lock( wndPtr
->hmemTaskQ
);
1756 if ( pNewActiveQueue
)
1757 PERQDATA_SetActiveWnd( pNewActiveQueue
->pQData
, hwndActive
);
1759 else /* have to do this or MDI frame activation goes to hell */
1760 if( pOldActiveQueue
)
1761 PERQDATA_SetActiveWnd( pOldActiveQueue
->pQData
, 0 );
1763 /* send palette messages */
1764 if (hWnd
&& SendMessage16( hWnd
, WM_QUERYNEWPALETTE
, 0, 0L))
1765 SendMessage16((HWND16
)-1, WM_PALETTEISCHANGING
, (WPARAM16
)hWnd
, 0L );
1767 /* if prev wnd is minimized redraw icon title */
1768 if( IsIconic( hwndPrevActive
) ) WINPOS_RedrawIconTitle(hwndPrevActive
);
1770 /* managed windows will get ConfigureNotify event */
1771 if (wndPtr
&& !(wndPtr
->dwStyle
& WS_CHILD
) && !(wndPtr
->flags
& WIN_MANAGED
))
1773 /* check Z-order and bring hWnd to the top */
1774 for (wndTemp
= WIN_LockWndPtr(WIN_GetDesktop()->child
); wndTemp
; WIN_UpdateWndPtr(&wndTemp
,wndTemp
->next
))
1776 if (wndTemp
->dwStyle
& WS_VISIBLE
) break;
1778 WIN_ReleaseDesktop();
1779 WIN_ReleaseWndPtr(wndTemp
);
1781 if( wndTemp
!= wndPtr
)
1782 SetWindowPos(hWnd
, HWND_TOP
, 0,0,0,0,
1783 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
1784 if (!IsWindow(hWnd
))
1788 /* Get a handle to the new active queue */
1789 hNewActiveQueue
= wndPtr
? wndPtr
->hmemTaskQ
: 0;
1791 /* send WM_ACTIVATEAPP if necessary */
1792 if (hOldActiveQueue
!= hNewActiveQueue
)
1794 WND
**list
, **ppWnd
;
1795 WND
*pDesktop
= WIN_GetDesktop();
1797 if ((list
= WIN_BuildWinArray( pDesktop
, 0, NULL
)))
1799 for (ppWnd
= list
; *ppWnd
; ppWnd
++)
1801 if (!IsWindow( (*ppWnd
)->hwndSelf
)) continue;
1803 if ((*ppWnd
)->hmemTaskQ
== hOldActiveQueue
)
1804 SendMessage16( (*ppWnd
)->hwndSelf
, WM_ACTIVATEAPP
,
1805 0, QUEUE_GetQueueTask(hNewActiveQueue
) );
1807 WIN_ReleaseWinArray(list
);
1810 hActiveQueue
= hNewActiveQueue
;
1812 if ((list
= WIN_BuildWinArray(pDesktop
, 0, NULL
)))
1814 for (ppWnd
= list
; *ppWnd
; ppWnd
++)
1816 if (!IsWindow( (*ppWnd
)->hwndSelf
)) continue;
1818 if ((*ppWnd
)->hmemTaskQ
== hNewActiveQueue
)
1819 SendMessage16( (*ppWnd
)->hwndSelf
, WM_ACTIVATEAPP
,
1820 1, QUEUE_GetQueueTask( hOldActiveQueue
) );
1822 WIN_ReleaseWinArray(list
);
1824 WIN_ReleaseDesktop();
1826 if (hWnd
&& !IsWindow(hWnd
)) goto CLEANUP
;
1831 /* walk up to the first unowned window */
1832 wndTemp
= WIN_LockWndPtr(wndPtr
);
1833 while (wndTemp
->owner
)
1835 WIN_UpdateWndPtr(&wndTemp
,wndTemp
->owner
);
1837 /* and set last active owned popup */
1838 wndTemp
->hwndLastActive
= hWnd
;
1840 wIconized
= HIWORD(wndTemp
->dwStyle
& WS_MINIMIZE
);
1841 WIN_ReleaseWndPtr(wndTemp
);
1842 SendMessageA( hWnd
, WM_NCACTIVATE
, TRUE
, 0 );
1843 SendMessageA( hWnd
, WM_ACTIVATE
,
1844 MAKEWPARAM( (fMouse
) ? WA_CLICKACTIVE
: WA_ACTIVE
, wIconized
),
1845 (LPARAM
)hwndPrevActive
);
1846 if( !IsWindow(hWnd
) ) goto CLEANUP
;
1849 /* change focus if possible */
1852 if ( pNewActiveQueue
)
1854 HWND hOldFocus
= PERQDATA_GetFocusWnd( pNewActiveQueue
->pQData
);
1856 if ( WIN_GetTopParent( hOldFocus
) != hwndActive
)
1857 FOCUS_SwitchFocus( pNewActiveQueue
, hOldFocus
,
1858 (wndPtr
&& (wndPtr
->dwStyle
& WS_MINIMIZE
))?
1862 if ( pOldActiveQueue
&&
1863 ( !pNewActiveQueue
||
1864 pNewActiveQueue
->pQData
!= pOldActiveQueue
->pQData
) )
1866 HWND hOldFocus
= PERQDATA_GetFocusWnd( pOldActiveQueue
->pQData
);
1868 FOCUS_SwitchFocus( pOldActiveQueue
, hOldFocus
, 0 );
1872 if( !hwndPrevActive
&& wndPtr
)
1873 (*wndPtr
->pDriver
->pForceWindowRaise
)(wndPtr
);
1875 /* if active wnd is minimized redraw icon title */
1876 if( IsIconic(hwndActive
) ) WINPOS_RedrawIconTitle(hwndActive
);
1878 bRet
= (hWnd
== hwndActive
); /* Success? */
1880 CLEANUP
: /* Unlock the message queues before returning */
1882 if ( pNewActiveQueue
)
1883 QUEUE_Unlock( pNewActiveQueue
);
1887 if ( pOldActiveQueue
)
1888 QUEUE_Unlock( pOldActiveQueue
);
1890 WIN_ReleaseWndPtr(wndPtr
);
1894 /*******************************************************************
1895 * WINPOS_ActivateOtherWindow
1897 * Activates window other than pWnd.
1899 BOOL
WINPOS_ActivateOtherWindow(WND
* pWnd
)
1903 HWND hwndActive
= 0;
1905 /* Get current active window from the active queue */
1908 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
1911 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
1912 QUEUE_Unlock( pActiveQueue
);
1916 if( pWnd
->hwndSelf
== hwndPrevActive
)
1919 if( hwndActive
!= pWnd
->hwndSelf
&&
1920 ( hwndActive
|| QUEUE_IsExitingQueue(pWnd
->hmemTaskQ
)) )
1923 if( !(pWnd
->dwStyle
& WS_POPUP
) || !(pWnd
->owner
) ||
1924 !WINPOS_CanActivate((pWndTo
= WIN_GetTopParentPtr(pWnd
->owner
))) )
1926 WND
* pWndPtr
= WIN_GetTopParentPtr(pWnd
);
1928 WIN_ReleaseWndPtr(pWndTo
);
1929 pWndTo
= WIN_FindWndPtr(hwndPrevActive
);
1931 while( !WINPOS_CanActivate(pWndTo
) )
1933 /* by now owned windows should've been taken care of */
1934 WIN_UpdateWndPtr(&pWndTo
,pWndPtr
->next
);
1935 WIN_UpdateWndPtr(&pWndPtr
,pWndTo
);
1936 if( !pWndTo
) break;
1938 WIN_ReleaseWndPtr(pWndPtr
);
1941 bRet
= WINPOS_SetActiveWindow( pWndTo
? pWndTo
->hwndSelf
: 0, FALSE
, TRUE
);
1943 /* switch desktop queue to current active */
1946 WIN_GetDesktop()->hmemTaskQ
= pWndTo
->hmemTaskQ
;
1947 WIN_ReleaseWndPtr(pWndTo
);
1948 WIN_ReleaseDesktop();
1955 /*******************************************************************
1956 * WINPOS_ChangeActiveWindow
1959 BOOL
WINPOS_ChangeActiveWindow( HWND hWnd
, BOOL mouseMsg
)
1961 WND
*wndPtr
, *wndTemp
;
1963 HWND hwndActive
= 0;
1965 /* Get current active window from the active queue */
1968 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
1971 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
1972 QUEUE_Unlock( pActiveQueue
);
1977 return WINPOS_SetActiveWindow( 0, mouseMsg
, TRUE
);
1979 wndPtr
= WIN_FindWndPtr(hWnd
);
1980 if( !wndPtr
) return FALSE
;
1982 /* child windows get WM_CHILDACTIVATE message */
1983 if( (wndPtr
->dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1985 retvalue
= SendMessageA(hWnd
, WM_CHILDACTIVATE
, 0, 0L);
1989 if( hWnd
== hwndActive
)
1995 if( !WINPOS_SetActiveWindow(hWnd
,mouseMsg
,TRUE
) )
2001 /* switch desktop queue to current active */
2002 wndTemp
= WIN_GetDesktop();
2003 if( wndPtr
->parent
== wndTemp
)
2004 wndTemp
->hmemTaskQ
= wndPtr
->hmemTaskQ
;
2005 WIN_ReleaseDesktop();
2009 WIN_ReleaseWndPtr(wndPtr
);
2014 /***********************************************************************
2015 * WINPOS_SendNCCalcSize
2017 * Send a WM_NCCALCSIZE message to a window.
2018 * All parameters are read-only except newClientRect.
2019 * oldWindowRect, oldClientRect and winpos must be non-NULL only
2020 * when calcValidRect is TRUE.
2022 LONG
WINPOS_SendNCCalcSize( HWND hwnd
, BOOL calcValidRect
,
2023 RECT
*newWindowRect
, RECT
*oldWindowRect
,
2024 RECT
*oldClientRect
, WINDOWPOS
*winpos
,
2025 RECT
*newClientRect
)
2027 NCCALCSIZE_PARAMS params
;
2028 WINDOWPOS winposCopy
;
2031 params
.rgrc
[0] = *newWindowRect
;
2034 winposCopy
= *winpos
;
2035 params
.rgrc
[1] = *oldWindowRect
;
2036 params
.rgrc
[2] = *oldClientRect
;
2037 params
.lppos
= &winposCopy
;
2039 result
= SendMessageA( hwnd
, WM_NCCALCSIZE
, calcValidRect
,
2041 TRACE("%d,%d-%d,%d\n",
2042 params
.rgrc
[0].left
, params
.rgrc
[0].top
,
2043 params
.rgrc
[0].right
, params
.rgrc
[0].bottom
);
2045 /* If the application send back garbage, ignore it */
2046 if (params
.rgrc
[0].left
<= params
.rgrc
[0].right
&& params
.rgrc
[0].top
<= params
.rgrc
[0].bottom
)
2047 *newClientRect
= params
.rgrc
[0];
2053 /***********************************************************************
2054 * WINPOS_HandleWindowPosChanging16
2056 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2058 LONG
WINPOS_HandleWindowPosChanging16( WND
*wndPtr
, WINDOWPOS16
*winpos
)
2060 POINT maxSize
, minTrack
;
2061 if (winpos
->flags
& SWP_NOSIZE
) return 0;
2062 if ((wndPtr
->dwStyle
& WS_THICKFRAME
) ||
2063 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) == 0))
2065 WINPOS_GetMinMaxInfo( wndPtr
, &maxSize
, NULL
, &minTrack
, NULL
);
2066 if (maxSize
.x
< winpos
->cx
) winpos
->cx
= maxSize
.x
;
2067 if (maxSize
.y
< winpos
->cy
) winpos
->cy
= maxSize
.y
;
2068 if (!(wndPtr
->dwStyle
& WS_MINIMIZE
))
2070 if (winpos
->cx
< minTrack
.x
) winpos
->cx
= minTrack
.x
;
2071 if (winpos
->cy
< minTrack
.y
) winpos
->cy
= minTrack
.y
;
2078 /***********************************************************************
2079 * WINPOS_HandleWindowPosChanging
2081 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2083 LONG
WINPOS_HandleWindowPosChanging( WND
*wndPtr
, WINDOWPOS
*winpos
)
2086 if (winpos
->flags
& SWP_NOSIZE
) return 0;
2087 if ((wndPtr
->dwStyle
& WS_THICKFRAME
) ||
2088 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) == 0))
2090 WINPOS_GetMinMaxInfo( wndPtr
, &maxSize
, NULL
, NULL
, NULL
);
2091 winpos
->cx
= min( winpos
->cx
, maxSize
.x
);
2092 winpos
->cy
= min( winpos
->cy
, maxSize
.y
);
2097 /***********************************************************************
2100 * fix Z order taking into account owned popups -
2101 * basically we need to maintain them above the window that owns them
2103 * FIXME: hide/show owned popups when owner visibility changes.
2105 static HWND
SWP_DoOwnedPopups(WND
* pDesktop
, WND
* wndPtr
, HWND hwndInsertAfter
, WORD flags
)
2107 WND
* w
= WIN_LockWndPtr(pDesktop
->child
);
2109 WARN("(%04x) hInsertAfter = %04x\n", wndPtr
->hwndSelf
, hwndInsertAfter
);
2111 if( (wndPtr
->dwStyle
& WS_POPUP
) && wndPtr
->owner
)
2113 /* make sure this popup stays above the owner */
2115 HWND hwndLocalPrev
= HWND_TOP
;
2117 if( hwndInsertAfter
!= HWND_TOP
)
2119 while( w
!= wndPtr
->owner
)
2121 if (w
!= wndPtr
) hwndLocalPrev
= w
->hwndSelf
;
2122 if( hwndLocalPrev
== hwndInsertAfter
) break;
2123 WIN_UpdateWndPtr(&w
,w
->next
);
2125 hwndInsertAfter
= hwndLocalPrev
;
2128 else if( wndPtr
->dwStyle
& WS_CHILD
)
2131 WIN_UpdateWndPtr(&w
, pDesktop
->child
);
2135 if( w
== wndPtr
) break;
2137 if( (w
->dwStyle
& WS_POPUP
) && w
->owner
== wndPtr
)
2139 SetWindowPos(w
->hwndSelf
, hwndInsertAfter
, 0, 0, 0, 0,
2140 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOSENDCHANGING
| SWP_DEFERERASE
);
2141 hwndInsertAfter
= w
->hwndSelf
;
2143 WIN_UpdateWndPtr(&w
, w
->next
);
2147 WIN_ReleaseWndPtr(w
);
2148 return hwndInsertAfter
;
2151 /***********************************************************************
2154 * Make window look nice without excessive repainting
2156 * visible and update regions are in window coordinates
2157 * client and window rectangles are in parent client coordinates
2159 * FIXME: SWP_EX_PAINTSELF in uFlags works only if both old and new
2160 * window rects have the same origin.
2162 * Returns: uFlags and a dirty region in *pVisRgn.
2164 static UINT
SWP_CopyValidBits( WND
* Wnd
, HRGN
* pVisRgn
,
2165 LPRECT lpOldWndRect
,
2166 LPRECT lpOldClientRect
, UINT uFlags
)
2169 HRGN newVisRgn
, dirtyRgn
;
2170 INT my
= COMPLEXREGION
;
2172 TRACE("\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2173 Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
,
2174 Wnd
->rectWindow
.right
, Wnd
->rectWindow
.bottom
,
2175 lpOldWndRect
->left
, lpOldWndRect
->top
,
2176 lpOldWndRect
->right
, lpOldWndRect
->bottom
, *pVisRgn
);
2177 TRACE("\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2178 Wnd
->rectClient
.left
, Wnd
->rectClient
.top
,
2179 Wnd
->rectClient
.right
, Wnd
->rectClient
.bottom
,
2180 lpOldClientRect
->left
, lpOldClientRect
->top
,
2181 lpOldClientRect
->right
,lpOldClientRect
->bottom
);
2183 if( Wnd
->hrgnUpdate
== 1 )
2184 uFlags
|= SWP_EX_NOCOPY
; /* whole window is invalid, nothing to copy */
2186 newVisRgn
= DCE_GetVisRgn( Wnd
->hwndSelf
, DCX_WINDOW
| DCX_CLIPSIBLINGS
, 0, 0);
2187 dirtyRgn
= CreateRectRgn( 0, 0, 0, 0 );
2189 if( !(uFlags
& SWP_EX_NOCOPY
) ) /* make sure dst region covers only valid bits */
2190 my
= CombineRgn( dirtyRgn
, newVisRgn
, *pVisRgn
, RGN_AND
);
2192 if( (my
== NULLREGION
) || (uFlags
& SWP_EX_NOCOPY
) )
2196 TRACE("\twon't copy anything!\n");
2198 /* set dirtyRgn to the sum of old and new visible regions
2199 * in parent client coordinates */
2201 OffsetRgn( newVisRgn
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2202 OffsetRgn( *pVisRgn
, lpOldWndRect
->left
, lpOldWndRect
->top
);
2204 CombineRgn(*pVisRgn
, *pVisRgn
, newVisRgn
, RGN_OR
);
2206 else /* copy valid bits to a new location */
2208 INT dx
, dy
, ow
, oh
, nw
, nh
, ocw
, ncw
, och
, nch
;
2209 HRGN hrgnValid
= dirtyRgn
; /* non-empty intersection of old and new visible rgns */
2211 /* subtract already invalid region inside Wnd from the dst region */
2213 if( Wnd
->hrgnUpdate
)
2214 if( CombineRgn( hrgnValid
, hrgnValid
, Wnd
->hrgnUpdate
, RGN_DIFF
) == NULLREGION
)
2217 /* check if entire window can be copied */
2219 ow
= lpOldWndRect
->right
- lpOldWndRect
->left
;
2220 oh
= lpOldWndRect
->bottom
- lpOldWndRect
->top
;
2221 nw
= Wnd
->rectWindow
.right
- Wnd
->rectWindow
.left
;
2222 nh
= Wnd
->rectWindow
.bottom
- Wnd
->rectWindow
.top
;
2224 ocw
= lpOldClientRect
->right
- lpOldClientRect
->left
;
2225 och
= lpOldClientRect
->bottom
- lpOldClientRect
->top
;
2226 ncw
= Wnd
->rectClient
.right
- Wnd
->rectClient
.left
;
2227 nch
= Wnd
->rectClient
.bottom
- Wnd
->rectClient
.top
;
2229 if( (ocw
!= ncw
) || (och
!= nch
) ||
2230 ( ow
!= nw
) || ( oh
!= nh
) ||
2231 ((lpOldClientRect
->top
- lpOldWndRect
->top
) !=
2232 (Wnd
->rectClient
.top
- Wnd
->rectWindow
.top
)) ||
2233 ((lpOldClientRect
->left
- lpOldWndRect
->left
) !=
2234 (Wnd
->rectClient
.left
- Wnd
->rectWindow
.left
)) )
2236 dx
= Wnd
->rectClient
.left
- lpOldClientRect
->left
;
2237 dy
= Wnd
->rectClient
.top
- lpOldClientRect
->top
;
2239 /* restrict valid bits to the common client rect */
2241 r
.left
= Wnd
->rectClient
.left
- Wnd
->rectWindow
.left
;
2242 r
.top
= Wnd
->rectClient
.top
- Wnd
->rectWindow
.top
;
2243 r
.right
= r
.left
+ min( ocw
, ncw
);
2244 r
.bottom
= r
.top
+ min( och
, nch
);
2246 REGION_CropRgn( hrgnValid
, hrgnValid
, &r
,
2247 (uFlags
& SWP_EX_PAINTSELF
) ? NULL
: (POINT
*)&(Wnd
->rectWindow
));
2248 GetRgnBox( hrgnValid
, &r
);
2249 if( IsRectEmpty( &r
) )
2251 r
= *lpOldClientRect
;
2255 dx
= Wnd
->rectWindow
.left
- lpOldWndRect
->left
;
2256 dy
= Wnd
->rectWindow
.top
- lpOldWndRect
->top
;
2257 if( !(uFlags
& SWP_EX_PAINTSELF
) )
2258 OffsetRgn( hrgnValid
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2262 if( !(uFlags
& SWP_EX_PAINTSELF
) )
2264 /* Move remaining regions to parent coordinates */
2265 OffsetRgn( newVisRgn
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2266 OffsetRgn( *pVisRgn
, lpOldWndRect
->left
, lpOldWndRect
->top
);
2269 OffsetRect( &r
, -lpOldWndRect
->left
, -lpOldWndRect
->top
);
2271 TRACE("\tcomputing dirty region!\n");
2273 /* Compute combined dirty region (old + new - valid) */
2274 CombineRgn( *pVisRgn
, *pVisRgn
, newVisRgn
, RGN_OR
);
2275 CombineRgn( *pVisRgn
, *pVisRgn
, hrgnValid
, RGN_DIFF
);
2277 /* Blt valid bits, r is the rect to copy */
2285 /* get DC and clip rect with drawable rect to avoid superfluous expose events
2286 from copying clipped areas */
2288 if( uFlags
& SWP_EX_PAINTSELF
)
2290 hDC
= GetDCEx( Wnd
->hwndSelf
, hrgnValid
, DCX_WINDOW
| DCX_CACHE
|
2291 DCX_KEEPCLIPRGN
| DCX_INTERSECTRGN
| DCX_CLIPSIBLINGS
);
2292 rClip
.right
= nw
; rClip
.bottom
= nh
;
2296 hDC
= GetDCEx( Wnd
->parent
->hwndSelf
, hrgnValid
, DCX_CACHE
|
2297 DCX_KEEPCLIPRGN
| DCX_INTERSECTRGN
| DCX_CLIPSIBLINGS
);
2298 rClip
.right
= Wnd
->parent
->rectClient
.right
- Wnd
->parent
->rectClient
.left
;
2299 rClip
.bottom
= Wnd
->parent
->rectClient
.bottom
- Wnd
->parent
->rectClient
.top
;
2301 rClip
.left
= rClip
.top
= 0;
2303 if( (dc
= (DC
*)GDI_GetObjPtr(hDC
, DC_MAGIC
)) )
2305 if( oh
> nh
) r
.bottom
= r
.top
+ nh
;
2306 if( ow
< nw
) r
.right
= r
.left
+ nw
;
2308 if( IntersectRect( &r
, &r
, &rClip
) )
2310 Wnd
->pDriver
->pSurfaceCopy( Wnd
->parent
, dc
, dx
, dy
, &r
, TRUE
);
2312 /* When you copy the bits without repainting, parent doesn't
2313 get validated appropriately. Therefore, we have to validate
2314 the parent with the windows' updated region when the
2315 parent's update region is not empty. */
2317 if (Wnd
->parent
->hrgnUpdate
!= 0 && !(Wnd
->parent
->dwStyle
& WS_CLIPCHILDREN
))
2319 OffsetRect(&r
, dx
, dy
);
2320 ValidateRect(Wnd
->parent
->hwndSelf
, &r
);
2324 GDI_HEAP_UNLOCK( hDC
);
2326 ReleaseDC( (uFlags
& SWP_EX_PAINTSELF
) ?
2327 Wnd
->hwndSelf
: Wnd
->parent
->hwndSelf
, hDC
);
2331 /* *pVisRgn now points to the invalidated region */
2333 DeleteObject(newVisRgn
);
2334 DeleteObject(dirtyRgn
);
2338 /***********************************************************************
2339 * SWP_DoSimpleFrameChanged
2341 * NOTE: old and new client rect origins are identical, only
2342 * extents may have changed. Window extents are the same.
2344 static void SWP_DoSimpleFrameChanged( WND
* wndPtr
, RECT
* pOldClientRect
, WORD swpFlags
, UINT uFlags
)
2350 if( !(swpFlags
& SWP_NOCLIENTSIZE
) )
2352 /* Client rect changed its position/size, most likely a scrollar
2353 * was added/removed.
2355 * FIXME: WVR alignment flags
2358 if( wndPtr
->rectClient
.right
> pOldClientRect
->right
) /* right edge */
2362 rect
.bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
2363 rect
.right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
2364 if(!(uFlags
& SWP_EX_NOCOPY
))
2365 rect
.left
= pOldClientRect
->right
- wndPtr
->rectClient
.left
;
2373 if( wndPtr
->rectClient
.bottom
> pOldClientRect
->bottom
) /* bottom edge */
2376 hrgn
= CreateRectRgnIndirect( &rect
);
2378 rect
.right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
2379 rect
.bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
2380 if(!(uFlags
& SWP_EX_NOCOPY
))
2381 rect
.top
= pOldClientRect
->bottom
- wndPtr
->rectClient
.top
;
2385 REGION_UnionRectWithRgn( hrgn
, &rect
);
2388 if( i
== 0 && (uFlags
& SWP_EX_NOCOPY
) ) /* force redraw anyway */
2390 rect
= wndPtr
->rectWindow
;
2391 OffsetRect( &rect
, wndPtr
->rectWindow
.left
- wndPtr
->rectClient
.left
,
2392 wndPtr
->rectWindow
.top
- wndPtr
->rectClient
.top
);
2400 PAINT_RedrawWindow( wndPtr
->hwndSelf
, &rect
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
|
2401 RDW_ERASENOW
| RDW_ALLCHILDREN
, RDW_EX_TOPFRAME
| RDW_EX_USEHRGN
);
2405 WIN_UpdateNCRgn(wndPtr
, 0, UNC_UPDATE
| UNC_ENTIRE
);
2409 DeleteObject( hrgn
);
2412 /***********************************************************************
2413 * SWP_DoWinPosChanging
2415 static BOOL
SWP_DoWinPosChanging( WND
* wndPtr
, WINDOWPOS
* pWinpos
,
2416 RECT
* pNewWindowRect
, RECT
* pNewClientRect
)
2418 /* Send WM_WINDOWPOSCHANGING message */
2420 if (!(pWinpos
->flags
& SWP_NOSENDCHANGING
))
2421 SendMessageA( wndPtr
->hwndSelf
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
)pWinpos
);
2423 /* Calculate new position and size */
2425 *pNewWindowRect
= wndPtr
->rectWindow
;
2426 *pNewClientRect
= (wndPtr
->dwStyle
& WS_MINIMIZE
) ? wndPtr
->rectWindow
2427 : wndPtr
->rectClient
;
2429 if (!(pWinpos
->flags
& SWP_NOSIZE
))
2431 pNewWindowRect
->right
= pNewWindowRect
->left
+ pWinpos
->cx
;
2432 pNewWindowRect
->bottom
= pNewWindowRect
->top
+ pWinpos
->cy
;
2434 if (!(pWinpos
->flags
& SWP_NOMOVE
))
2436 pNewWindowRect
->left
= pWinpos
->x
;
2437 pNewWindowRect
->top
= pWinpos
->y
;
2438 pNewWindowRect
->right
+= pWinpos
->x
- wndPtr
->rectWindow
.left
;
2439 pNewWindowRect
->bottom
+= pWinpos
->y
- wndPtr
->rectWindow
.top
;
2441 OffsetRect( pNewClientRect
, pWinpos
->x
- wndPtr
->rectWindow
.left
,
2442 pWinpos
->y
- wndPtr
->rectWindow
.top
);
2445 pWinpos
->flags
|= SWP_NOCLIENTMOVE
| SWP_NOCLIENTSIZE
;
2449 /***********************************************************************
2452 static UINT
SWP_DoNCCalcSize( WND
* wndPtr
, WINDOWPOS
* pWinpos
,
2453 RECT
* pNewWindowRect
, RECT
* pNewClientRect
, WORD f
)
2457 /* Send WM_NCCALCSIZE message to get new client area */
2458 if( (pWinpos
->flags
& (SWP_FRAMECHANGED
| SWP_NOSIZE
)) != SWP_NOSIZE
)
2460 wvrFlags
= WINPOS_SendNCCalcSize( pWinpos
->hwnd
, TRUE
, pNewWindowRect
,
2461 &wndPtr
->rectWindow
, &wndPtr
->rectClient
,
2462 pWinpos
, pNewClientRect
);
2464 /* FIXME: WVR_ALIGNxxx */
2466 if( pNewClientRect
->left
!= wndPtr
->rectClient
.left
||
2467 pNewClientRect
->top
!= wndPtr
->rectClient
.top
)
2468 pWinpos
->flags
&= ~SWP_NOCLIENTMOVE
;
2470 if( (pNewClientRect
->right
- pNewClientRect
->left
!=
2471 wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
) ||
2472 (pNewClientRect
->bottom
- pNewClientRect
->top
!=
2473 wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
) )
2474 pWinpos
->flags
&= ~SWP_NOCLIENTSIZE
;
2477 if( !(f
& SWP_NOMOVE
) && (pNewClientRect
->left
!= wndPtr
->rectClient
.left
||
2478 pNewClientRect
->top
!= wndPtr
->rectClient
.top
) )
2479 pWinpos
->flags
&= ~SWP_NOCLIENTMOVE
;
2483 /***********************************************************************
2484 * SetWindowPos (USER.2)
2486 BOOL16 WINAPI
SetWindowPos16( HWND16 hwnd
, HWND16 hwndInsertAfter
,
2487 INT16 x
, INT16 y
, INT16 cx
, INT16 cy
, WORD flags
)
2489 return SetWindowPos(hwnd
,(INT
)(INT16
)hwndInsertAfter
,x
,y
,cx
,cy
,flags
);
2492 /***********************************************************************
2493 * SetWindowPos (USER32.520)
2495 BOOL WINAPI
SetWindowPos( HWND hwnd
, HWND hwndInsertAfter
,
2496 INT x
, INT y
, INT cx
, INT cy
, UINT flags
)
2499 WND
* wndPtr
,*wndTemp
;
2500 RECT newWindowRect
, newClientRect
;
2501 RECT oldWindowRect
, oldClientRect
;
2503 UINT wvrFlags
= 0, uFlags
= 0;
2504 BOOL retvalue
, resync
= FALSE
, bChangePos
;
2505 HWND hwndActive
= 0;
2507 /* Get current active window from the active queue */
2510 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
2513 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
2514 QUEUE_Unlock( pActiveQueue
);
2518 TRACE("hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2519 hwnd
, x
, y
, x
+cx
, y
+cy
, flags
);
2521 bChangePos
= !(flags
& SWP_WINE_NOHOSTMOVE
);
2522 flags
&= ~SWP_WINE_NOHOSTMOVE
;
2525 /* ------------------------------------------------------------------------ CHECKS */
2527 /* Check window handle */
2529 if (hwnd
== GetDesktopWindow()) return FALSE
;
2530 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return FALSE
;
2532 TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr
->rectWindow
.left
, wndPtr
->rectWindow
.top
,
2533 wndPtr
->rectWindow
.right
, wndPtr
->rectWindow
.bottom
, (unsigned)wndPtr
->dwStyle
);
2535 /* Fix redundant flags */
2537 if(wndPtr
->dwStyle
& WS_VISIBLE
)
2538 flags
&= ~SWP_SHOWWINDOW
;
2541 if (!(flags
& SWP_SHOWWINDOW
))
2542 flags
|= SWP_NOREDRAW
;
2543 flags
&= ~SWP_HIDEWINDOW
;
2546 if ( cx
< 0 ) cx
= 0; if( cy
< 0 ) cy
= 0;
2548 if ((wndPtr
->rectWindow
.right
- wndPtr
->rectWindow
.left
== cx
) &&
2549 (wndPtr
->rectWindow
.bottom
- wndPtr
->rectWindow
.top
== cy
))
2550 flags
|= SWP_NOSIZE
; /* Already the right size */
2552 if ((wndPtr
->rectWindow
.left
== x
) && (wndPtr
->rectWindow
.top
== y
))
2553 flags
|= SWP_NOMOVE
; /* Already the right position */
2555 if (hwnd
== hwndActive
)
2556 flags
|= SWP_NOACTIVATE
; /* Already active */
2557 else if ( (wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)
2559 if(!(flags
& SWP_NOACTIVATE
)) /* Bring to the top when activating */
2561 flags
&= ~SWP_NOZORDER
;
2562 hwndInsertAfter
= HWND_TOP
;
2567 /* Check hwndInsertAfter */
2569 /* FIXME: TOPMOST not supported yet */
2570 if ((hwndInsertAfter
== HWND_TOPMOST
) ||
2571 (hwndInsertAfter
== HWND_NOTOPMOST
)) hwndInsertAfter
= HWND_TOP
;
2573 /* hwndInsertAfter must be a sibling of the window */
2574 if ((hwndInsertAfter
!= HWND_TOP
) && (hwndInsertAfter
!= HWND_BOTTOM
))
2576 WND
* wnd
= WIN_FindWndPtr(hwndInsertAfter
);
2579 if( wnd
->parent
!= wndPtr
->parent
)
2582 WIN_ReleaseWndPtr(wnd
);
2585 if( wnd
->next
== wndPtr
) flags
|= SWP_NOZORDER
;
2587 WIN_ReleaseWndPtr(wnd
);
2590 Pos
: /* ------------------------------------------------------------------------ MAIN part */
2592 /* Fill the WINDOWPOS structure */
2595 winpos
.hwndInsertAfter
= hwndInsertAfter
;
2600 winpos
.flags
= flags
;
2602 SWP_DoWinPosChanging( wndPtr
, &winpos
, &newWindowRect
, &newClientRect
);
2604 if((winpos
.flags
& (SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) != SWP_NOZORDER
)
2606 if( wndPtr
->parent
== WIN_GetDesktop() )
2607 hwndInsertAfter
= SWP_DoOwnedPopups( wndPtr
->parent
, wndPtr
,
2608 hwndInsertAfter
, winpos
.flags
);
2609 WIN_ReleaseDesktop();
2612 if(!(wndPtr
->flags
& WIN_NATIVE
) )
2614 if( hwndInsertAfter
== HWND_TOP
)
2615 winpos
.flags
|= ( wndPtr
->parent
->child
== wndPtr
)? SWP_NOZORDER
: 0;
2617 if( hwndInsertAfter
== HWND_BOTTOM
)
2618 winpos
.flags
|= ( wndPtr
->next
)? 0: SWP_NOZORDER
;
2620 if( !(winpos
.flags
& SWP_NOZORDER
) )
2621 if( GetWindow(hwndInsertAfter
, GW_HWNDNEXT
) == wndPtr
->hwndSelf
)
2622 winpos
.flags
|= SWP_NOZORDER
;
2624 if( !(winpos
.flags
& (SWP_NOREDRAW
| SWP_SHOWWINDOW
)) &&
2625 ((winpos
.flags
& (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_FRAMECHANGED
))
2626 != (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
)) )
2628 /* get a previous visible region for SWP_CopyValidBits() */
2629 DWORD flags
= DCX_WINDOW
;
2631 if (wndPtr
->dwStyle
& WS_CLIPSIBLINGS
)
2632 flags
|= DCX_CLIPSIBLINGS
;
2634 visRgn
= DCE_GetVisRgn(hwnd
, flags
, 0, 0);
2638 /* Common operations */
2640 wvrFlags
= SWP_DoNCCalcSize( wndPtr
, &winpos
, &newWindowRect
, &newClientRect
, flags
);
2642 if(!(winpos
.flags
& SWP_NOZORDER
) && winpos
.hwnd
!= hwndInsertAfter
)
2644 if ( WIN_UnlinkWindow( winpos
.hwnd
) )
2645 WIN_LinkWindow( winpos
.hwnd
, hwndInsertAfter
);
2648 /* Reset active DCEs */
2650 if( (((winpos
.flags
& SWP_AGG_NOPOSCHANGE
) != SWP_AGG_NOPOSCHANGE
) &&
2651 wndPtr
->dwStyle
& WS_VISIBLE
) ||
2652 (flags
& (SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) )
2656 UnionRect(&rect
, &newWindowRect
, &wndPtr
->rectWindow
);
2657 DCE_InvalidateDCE(wndPtr
, &rect
);
2660 oldWindowRect
= wndPtr
->rectWindow
;
2661 oldClientRect
= wndPtr
->rectClient
;
2663 /* Find out if we have to redraw the whole client rect */
2665 if( oldClientRect
.bottom
- oldClientRect
.top
==
2666 newClientRect
.bottom
- newClientRect
.top
) wvrFlags
&= ~WVR_VREDRAW
;
2668 if( oldClientRect
.right
- oldClientRect
.left
==
2669 newClientRect
.right
- newClientRect
.left
) wvrFlags
&= ~WVR_HREDRAW
;
2671 if( (winpos
.flags
& SWP_NOCOPYBITS
) || (!(winpos
.flags
& SWP_NOCLIENTSIZE
) &&
2672 (wvrFlags
>= WVR_HREDRAW
) && (wvrFlags
< WVR_VALIDRECTS
)) )
2674 uFlags
|= SWP_EX_NOCOPY
;
2677 * Use this later in CopyValidBits()
2680 uFlags |= SWP_EX_NONCLIENT;
2683 /* FIXME: actually do something with WVR_VALIDRECTS */
2685 wndPtr
->rectWindow
= newWindowRect
;
2686 wndPtr
->rectClient
= newClientRect
;
2688 if (wndPtr
->flags
& WIN_NATIVE
) /* -------------------------------------------- hosted window */
2690 BOOL bCallDriver
= TRUE
;
2691 HWND tempInsertAfter
= winpos
.hwndInsertAfter
;
2693 winpos
.hwndInsertAfter
= hwndInsertAfter
;
2695 if( !(winpos
.flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
| SWP_NOREDRAW
)) )
2697 /* This is the only place where we need to force repainting of the contents
2698 of windows created by the host window system, all other cases go through the
2699 expose event handling */
2701 if( (winpos
.flags
& (SWP_NOSIZE
| SWP_FRAMECHANGED
)) == (SWP_NOSIZE
| SWP_FRAMECHANGED
) )
2703 cx
= newWindowRect
.right
- newWindowRect
.left
;
2704 cy
= newWindowRect
.bottom
- newWindowRect
.top
;
2706 wndPtr
->pDriver
->pSetWindowPos(wndPtr
, &winpos
, bChangePos
);
2707 winpos
.hwndInsertAfter
= tempInsertAfter
;
2708 bCallDriver
= FALSE
;
2710 if( winpos
.flags
& SWP_NOCLIENTMOVE
)
2711 SWP_DoSimpleFrameChanged(wndPtr
, &oldClientRect
, winpos
.flags
, uFlags
);
2714 /* client area moved but window extents remained the same, copy valid bits */
2716 visRgn
= CreateRectRgn( 0, 0, cx
, cy
);
2717 uFlags
= SWP_CopyValidBits( wndPtr
, &visRgn
, &oldWindowRect
, &oldClientRect
,
2718 uFlags
| SWP_EX_PAINTSELF
);
2725 if( !(winpos
.flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
| SWP_NOREDRAW
)) )
2727 if( (oldClientRect
.left
- oldWindowRect
.left
== newClientRect
.left
- newWindowRect
.left
) &&
2728 (oldClientRect
.top
- oldWindowRect
.top
== newClientRect
.top
- newWindowRect
.top
) &&
2729 !(uFlags
& SWP_EX_NOCOPY
) )
2731 /* The origin of the client rect didn't move so we can try to repaint
2732 * only the nonclient area by setting bit gravity hint for the host window system.
2735 if( !(wndPtr
->flags
& WIN_MANAGED
) )
2737 HRGN hrgn
= CreateRectRgn( 0, 0, newWindowRect
.right
- newWindowRect
.left
,
2738 newWindowRect
.bottom
- newWindowRect
.top
);
2739 RECT rcn
= newClientRect
;
2740 RECT rco
= oldClientRect
;
2742 OffsetRect( &rcn
, -newWindowRect
.left
, -newWindowRect
.top
);
2743 OffsetRect( &rco
, -oldWindowRect
.left
, -oldWindowRect
.top
);
2744 IntersectRect( &rcn
, &rcn
, &rco
);
2745 visRgn
= CreateRectRgnIndirect( &rcn
);
2746 CombineRgn( visRgn
, hrgn
, visRgn
, RGN_DIFF
);
2747 DeleteObject( hrgn
);
2748 uFlags
= SWP_EX_PAINTSELF
;
2750 wndPtr
->pDriver
->pSetHostAttr(wndPtr
, HAK_BITGRAVITY
, BGNorthWest
);
2753 wndPtr
->pDriver
->pSetHostAttr(wndPtr
, HAK_BITGRAVITY
, BGForget
);
2756 wndPtr
->pDriver
->pSetWindowPos(wndPtr
, &winpos
, bChangePos
);
2757 winpos
.hwndInsertAfter
= tempInsertAfter
;
2760 if( winpos
.flags
& SWP_SHOWWINDOW
)
2764 wndPtr
->dwStyle
|= WS_VISIBLE
;
2766 if (wndPtr
->flags
& WIN_MANAGED
) resync
= TRUE
;
2768 /* focus was set to unmapped window, reset host focus
2769 * since the window is now visible */
2771 focus
= curr
= GetFocus();
2776 WND
*pFocus
= WIN_FindWndPtr( focus
);
2778 pFocus
->pDriver
->pSetFocus(pFocus
);
2779 WIN_ReleaseWndPtr(pFocus
);
2782 curr
= GetParent(curr
);
2786 else /* -------------------------------------------- emulated window */
2788 if( winpos
.flags
& SWP_SHOWWINDOW
)
2790 wndPtr
->dwStyle
|= WS_VISIBLE
;
2791 uFlags
|= SWP_EX_PAINTSELF
;
2792 visRgn
= 1; /* redraw the whole window */
2794 else if( !(winpos
.flags
& SWP_NOREDRAW
) )
2796 if( winpos
.flags
& SWP_HIDEWINDOW
)
2798 if( visRgn
> 1 ) /* map to parent */
2799 OffsetRgn( visRgn
, oldWindowRect
.left
, oldWindowRect
.top
);
2805 if( (winpos
.flags
& SWP_AGG_NOPOSCHANGE
) != SWP_AGG_NOPOSCHANGE
)
2806 uFlags
= SWP_CopyValidBits(wndPtr
, &visRgn
, &oldWindowRect
,
2807 &oldClientRect
, uFlags
);
2810 /* nothing moved, redraw frame if needed */
2812 if( winpos
.flags
& SWP_FRAMECHANGED
)
2813 SWP_DoSimpleFrameChanged( wndPtr
, &oldClientRect
, winpos
.flags
, uFlags
);
2816 DeleteObject( visRgn
);
2824 if( winpos
.flags
& SWP_HIDEWINDOW
)
2826 wndPtr
->dwStyle
&= ~WS_VISIBLE
;
2828 if (hwnd
== CARET_GetHwnd()) DestroyCaret();
2831 /* ------------------------------------------------------------------------ FINAL */
2833 if (wndPtr
->flags
& WIN_NATIVE
)
2834 EVENT_Synchronize(); /* Synchronize with the host window system */
2836 if (!GetCapture() && ((wndPtr
->dwStyle
& WS_VISIBLE
) || (flags
& SWP_HIDEWINDOW
)))
2838 /* Simulate a mouse event to set the cursor */
2839 int iWndsLocks
= WIN_SuspendWndsLock();
2841 hardware_event( WM_MOUSEMOVE
, GET_KEYSTATE(), 0,
2842 PosX
, PosY
, GetTickCount(), 0 );
2844 WIN_RestoreWndsLock(iWndsLocks
);
2847 wndTemp
= WIN_GetDesktop();
2849 /* repaint invalidated region (if any)
2851 * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2852 * and force update after ChangeActiveWindow() to avoid painting frames twice.
2857 if( !(winpos
.flags
& SWP_NOREDRAW
) )
2860 /* Use PAINT_RedrawWindow to explicitly force an invalidation of the window,
2861 its parent and sibling and so on, and then erase the parent window
2862 back ground if the parent is either a top-level window or its parent's parent
2863 is top-level window. Rely on the system to repaint other affected
2864 windows later on. */
2865 if( uFlags
& SWP_EX_PAINTSELF
)
2867 PAINT_RedrawWindow( wndPtr
->hwndSelf
, NULL
, (visRgn
== 1) ? 0 : visRgn
,
2868 RDW_ERASE
| RDW_FRAME
| RDW_INVALIDATE
| RDW_ALLCHILDREN
,
2869 RDW_EX_XYWINDOW
| RDW_EX_USEHRGN
);
2873 PAINT_RedrawWindow( wndPtr
->parent
->hwndSelf
, NULL
, (visRgn
== 1) ? 0 : visRgn
,
2874 RDW_ERASE
| RDW_INVALIDATE
| RDW_ALLCHILDREN
,
2878 if(wndPtr
-> parent
== wndTemp
|| wndPtr
->parent
->parent
== wndTemp
)
2880 PAINT_RedrawWindow( wndPtr
->parent
->hwndSelf
, NULL
, 0,
2881 RDW_ERASENOW
| RDW_NOCHILDREN
, 0 );
2885 DeleteObject( visRgn
);
2888 WIN_ReleaseDesktop();
2890 if (!(flags
& SWP_NOACTIVATE
))
2891 WINPOS_ChangeActiveWindow( winpos
.hwnd
, FALSE
);
2893 /* And last, send the WM_WINDOWPOSCHANGED message */
2895 TRACE("\tstatus flags = %04x\n", winpos
.flags
& SWP_AGG_STATUSFLAGS
);
2898 (((winpos
.flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOPOSCHANGE
) &&
2899 !(winpos
.flags
& SWP_NOSENDCHANGING
)) )
2901 SendMessageA( winpos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
)&winpos
);
2902 if (resync
) EVENT_Synchronize();
2907 WIN_ReleaseWndPtr(wndPtr
);
2912 /***********************************************************************
2913 * BeginDeferWindowPos16 (USER.259)
2915 HDWP16 WINAPI
BeginDeferWindowPos16( INT16 count
)
2917 return BeginDeferWindowPos( count
);
2921 /***********************************************************************
2922 * BeginDeferWindowPos (USER32.9)
2924 HDWP WINAPI
BeginDeferWindowPos( INT count
)
2929 if (count
<= 0) return 0;
2930 handle
= USER_HEAP_ALLOC( sizeof(DWP
) + (count
-1)*sizeof(WINDOWPOS
) );
2931 if (!handle
) return 0;
2932 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( handle
);
2933 pDWP
->actualCount
= 0;
2934 pDWP
->suggestedCount
= count
;
2936 pDWP
->wMagic
= DWP_MAGIC
;
2937 pDWP
->hwndParent
= 0;
2942 /***********************************************************************
2943 * DeferWindowPos16 (USER.260)
2945 HDWP16 WINAPI
DeferWindowPos16( HDWP16 hdwp
, HWND16 hwnd
, HWND16 hwndAfter
,
2946 INT16 x
, INT16 y
, INT16 cx
, INT16 cy
,
2949 return DeferWindowPos( hdwp
, hwnd
, (INT
)(INT16
)hwndAfter
,
2950 x
, y
, cx
, cy
, flags
);
2954 /***********************************************************************
2955 * DeferWindowPos (USER32.128)
2957 HDWP WINAPI
DeferWindowPos( HDWP hdwp
, HWND hwnd
, HWND hwndAfter
,
2958 INT x
, INT y
, INT cx
, INT cy
,
2963 HDWP newhdwp
= hdwp
,retvalue
;
2967 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
2968 if (!pDWP
) return 0;
2969 if (hwnd
== GetDesktopWindow()) return 0;
2971 if (!(pWnd
=WIN_FindWndPtr( hwnd
))) {
2972 USER_HEAP_FREE( hdwp
);
2976 /* Numega Bounds Checker Demo dislikes the following code.
2977 In fact, I've not been able to find any "same parent" requirement in any docu
2981 /* All the windows of a DeferWindowPos() must have the same parent */
2982 parent
= pWnd
->parent
->hwndSelf
;
2983 if (pDWP
->actualCount
== 0) pDWP
->hwndParent
= parent
;
2984 else if (parent
!= pDWP
->hwndParent
)
2986 USER_HEAP_FREE( hdwp
);
2992 for (i
= 0; i
< pDWP
->actualCount
; i
++)
2994 if (pDWP
->winPos
[i
].hwnd
== hwnd
)
2996 /* Merge with the other changes */
2997 if (!(flags
& SWP_NOZORDER
))
2999 pDWP
->winPos
[i
].hwndInsertAfter
= hwndAfter
;
3001 if (!(flags
& SWP_NOMOVE
))
3003 pDWP
->winPos
[i
].x
= x
;
3004 pDWP
->winPos
[i
].y
= y
;
3006 if (!(flags
& SWP_NOSIZE
))
3008 pDWP
->winPos
[i
].cx
= cx
;
3009 pDWP
->winPos
[i
].cy
= cy
;
3011 pDWP
->winPos
[i
].flags
&= flags
| ~(SWP_NOSIZE
| SWP_NOMOVE
|
3012 SWP_NOZORDER
| SWP_NOREDRAW
|
3013 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
3015 pDWP
->winPos
[i
].flags
|= flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
|
3021 if (pDWP
->actualCount
>= pDWP
->suggestedCount
)
3023 newhdwp
= USER_HEAP_REALLOC( hdwp
,
3024 sizeof(DWP
) + pDWP
->suggestedCount
*sizeof(WINDOWPOS
) );
3030 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( newhdwp
);
3031 pDWP
->suggestedCount
++;
3033 pDWP
->winPos
[pDWP
->actualCount
].hwnd
= hwnd
;
3034 pDWP
->winPos
[pDWP
->actualCount
].hwndInsertAfter
= hwndAfter
;
3035 pDWP
->winPos
[pDWP
->actualCount
].x
= x
;
3036 pDWP
->winPos
[pDWP
->actualCount
].y
= y
;
3037 pDWP
->winPos
[pDWP
->actualCount
].cx
= cx
;
3038 pDWP
->winPos
[pDWP
->actualCount
].cy
= cy
;
3039 pDWP
->winPos
[pDWP
->actualCount
].flags
= flags
;
3040 pDWP
->actualCount
++;
3043 WIN_ReleaseWndPtr(pWnd
);
3048 /***********************************************************************
3049 * EndDeferWindowPos16 (USER.261)
3051 BOOL16 WINAPI
EndDeferWindowPos16( HDWP16 hdwp
)
3053 return EndDeferWindowPos( hdwp
);
3057 /***********************************************************************
3058 * EndDeferWindowPos (USER32.173)
3060 BOOL WINAPI
EndDeferWindowPos( HDWP hdwp
)
3067 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
3068 if (!pDWP
) return FALSE
;
3069 for (i
= 0, winpos
= pDWP
->winPos
; i
< pDWP
->actualCount
; i
++, winpos
++)
3071 if (!(res
= SetWindowPos( winpos
->hwnd
, winpos
->hwndInsertAfter
,
3072 winpos
->x
, winpos
->y
, winpos
->cx
,
3073 winpos
->cy
, winpos
->flags
))) break;
3075 USER_HEAP_FREE( hdwp
);
3080 /***********************************************************************
3081 * TileChildWindows (USER.199)
3083 void WINAPI
TileChildWindows16( HWND16 parent
, WORD action
)
3085 FIXME("(%04x, %d): stub\n", parent
, action
);
3088 /***********************************************************************
3089 * CascadeChildWindows (USER.198)
3091 void WINAPI
CascadeChildWindows16( HWND16 parent
, WORD action
)
3093 FIXME("(%04x, %d): stub\n", parent
, action
);
3096 /***********************************************************************
3097 * SetProgmanWindow [USER32.522]
3099 HRESULT WINAPI
SetProgmanWindow ( HWND hwnd
)
3101 hGlobalProgmanWindow
= hwnd
;
3102 return hGlobalProgmanWindow
;
3105 /***********************************************************************
3106 * GetProgmanWindow [USER32.289]
3108 HRESULT WINAPI
GetProgmanWindow ( )
3110 return hGlobalProgmanWindow
;
3113 /***********************************************************************
3114 * SetShellWindowEx [USER32.531]
3115 * hwndProgman = Progman[Program Manager]
3116 * |-> SHELLDLL_DefView
3117 * hwndListView = | |-> SysListView32
3118 * | | |-> tooltips_class32
3124 HRESULT WINAPI
SetShellWindowEx ( HWND hwndProgman
, HWND hwndListView
)
3126 FIXME("0x%08x 0x%08x stub\n",hwndProgman
,hwndListView
);
3127 hGlobalShellWindow
= hwndProgman
;
3128 return hGlobalShellWindow
;
3132 /***********************************************************************
3133 * SetTaskmanWindow [USER32.537]
3135 * hwnd = MSTaskSwWClass
3136 * |-> SysTabControl32
3138 HRESULT WINAPI
SetTaskmanWindow ( HWND hwnd
)
3140 hGlobalTaskmanWindow
= hwnd
;
3141 return hGlobalTaskmanWindow
;
3144 /***********************************************************************
3145 * GetTaskmanWindow [USER32.304]
3147 HRESULT WINAPI
GetTaskmanWindow ( )
3149 return hGlobalTaskmanWindow
;