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 * ChildWindowFromPointEx32 (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_CHILD
)) ) return TRUE
;
819 /*******************************************************************
820 * SetActiveWindow16 (USER.59)
822 HWND16 WINAPI
SetActiveWindow16( HWND16 hwnd
)
824 return SetActiveWindow(hwnd
);
828 /*******************************************************************
829 * SetActiveWindow (USER32.463)
831 HWND WINAPI
SetActiveWindow( HWND hwnd
)
834 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
835 MESSAGEQUEUE
*pMsgQ
= 0, *pCurMsgQ
= 0;
837 if ( !WINPOS_CanActivate(wndPtr
) )
843 /* Get the messageQ for the current thread */
844 if (!(pCurMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( GetFastQueue16() )))
846 WARN("\tCurrent message queue not found. Exiting!\n" );
850 /* Retrieve the message queue associated with this window */
851 pMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( wndPtr
->hmemTaskQ
);
854 WARN("\tWindow message queue not found. Exiting!\n" );
858 /* Make sure that the window is associated with the calling threads
859 * message queue. It must share the same perQ data.
862 if ( pCurMsgQ
->pQData
!= pMsgQ
->pQData
)
865 /* Save current active window */
866 prev
= PERQDATA_GetActiveWnd( pMsgQ
->pQData
);
868 WINPOS_SetActiveWindow( hwnd
, 0, 0 );
871 /* Unlock the queues before returning */
873 QUEUE_Unlock( pMsgQ
);
875 QUEUE_Unlock( pCurMsgQ
);
878 WIN_ReleaseWndPtr(wndPtr
);
883 /*******************************************************************
884 * GetForegroundWindow16 (USER.608)
886 HWND16 WINAPI
GetForegroundWindow16(void)
888 return (HWND16
)GetForegroundWindow();
892 /*******************************************************************
893 * SetForegroundWindow16 (USER.609)
895 BOOL16 WINAPI
SetForegroundWindow16( HWND16 hwnd
)
897 return SetForegroundWindow( hwnd
);
901 /*******************************************************************
902 * GetForegroundWindow (USER32.241)
904 HWND WINAPI
GetForegroundWindow(void)
908 /* Get the foreground window (active window of hActiveQueue) */
911 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
913 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
915 QUEUE_Unlock( pActiveQueue
);
921 /*******************************************************************
922 * SetForegroundWindow (USER32.482)
924 BOOL WINAPI
SetForegroundWindow( HWND hwnd
)
926 return WINPOS_ChangeActiveWindow( hwnd
, FALSE
);
930 /*******************************************************************
931 * GetShellWindow16 (USER.600)
933 HWND16 WINAPI
GetShellWindow16(void)
935 return GetShellWindow();
938 /*******************************************************************
939 * SetShellWindow (USER32.504)
941 HWND WINAPI
SetShellWindow(HWND hwndshell
)
942 { WARN("(hWnd=%08x) semi stub\n",hwndshell
);
944 hGlobalShellWindow
= hwndshell
;
945 return hGlobalShellWindow
;
949 /*******************************************************************
950 * GetShellWindow (USER32.287)
952 HWND WINAPI
GetShellWindow(void)
953 { WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow
);
955 return hGlobalShellWindow
;
959 /***********************************************************************
960 * BringWindowToTop16 (USER.45)
962 BOOL16 WINAPI
BringWindowToTop16( HWND16 hwnd
)
964 return BringWindowToTop(hwnd
);
968 /***********************************************************************
969 * BringWindowToTop (USER32.11)
971 BOOL WINAPI
BringWindowToTop( HWND hwnd
)
973 return SetWindowPos( hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
);
977 /***********************************************************************
978 * MoveWindow16 (USER.56)
980 BOOL16 WINAPI
MoveWindow16( HWND16 hwnd
, INT16 x
, INT16 y
, INT16 cx
, INT16 cy
,
983 return MoveWindow(hwnd
,x
,y
,cx
,cy
,repaint
);
987 /***********************************************************************
988 * MoveWindow (USER32.399)
990 BOOL WINAPI
MoveWindow( HWND hwnd
, INT x
, INT y
, INT cx
, INT cy
,
993 int flags
= SWP_NOZORDER
| SWP_NOACTIVATE
;
994 if (!repaint
) flags
|= SWP_NOREDRAW
;
995 TRACE("%04x %d,%d %dx%d %d\n",
996 hwnd
, x
, y
, cx
, cy
, repaint
);
997 return SetWindowPos( hwnd
, 0, x
, y
, cx
, cy
, flags
);
1000 /***********************************************************************
1001 * WINPOS_InitInternalPos
1003 static LPINTERNALPOS
WINPOS_InitInternalPos( WND
* wnd
, POINT pt
,
1004 LPRECT restoreRect
)
1006 LPINTERNALPOS lpPos
= (LPINTERNALPOS
) GetPropA( wnd
->hwndSelf
,
1010 /* this happens when the window is minimized/maximized
1011 * for the first time (rectWindow is not adjusted yet) */
1013 lpPos
= HeapAlloc( SystemHeap
, 0, sizeof(INTERNALPOS
) );
1014 if( !lpPos
) return NULL
;
1016 SetPropA( wnd
->hwndSelf
, atomInternalPos
, (HANDLE
)lpPos
);
1017 lpPos
->hwndIconTitle
= 0; /* defer until needs to be shown */
1018 CONV_RECT32TO16( &wnd
->rectWindow
, &lpPos
->rectNormal
);
1019 *(UINT
*)&lpPos
->ptIconPos
= *(UINT
*)&lpPos
->ptMaxPos
= 0xFFFFFFFF;
1022 if( wnd
->dwStyle
& WS_MINIMIZE
)
1023 CONV_POINT32TO16( &pt
, &lpPos
->ptIconPos
);
1024 else if( wnd
->dwStyle
& WS_MAXIMIZE
)
1025 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1026 else if( restoreRect
)
1027 CONV_RECT32TO16( restoreRect
, &lpPos
->rectNormal
);
1032 /***********************************************************************
1033 * WINPOS_RedrawIconTitle
1035 BOOL
WINPOS_RedrawIconTitle( HWND hWnd
)
1037 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)GetPropA( hWnd
, atomInternalPos
);
1040 if( lpPos
->hwndIconTitle
)
1042 SendMessageA( lpPos
->hwndIconTitle
, WM_SHOWWINDOW
, TRUE
, 0);
1043 InvalidateRect( lpPos
->hwndIconTitle
, NULL
, TRUE
);
1050 /***********************************************************************
1051 * WINPOS_ShowIconTitle
1053 BOOL
WINPOS_ShowIconTitle( WND
* pWnd
, BOOL bShow
)
1055 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)GetPropA( pWnd
->hwndSelf
, atomInternalPos
);
1057 if( lpPos
&& !(pWnd
->flags
& WIN_MANAGED
))
1059 HWND16 hWnd
= lpPos
->hwndIconTitle
;
1061 TRACE("0x%04x %i\n", pWnd
->hwndSelf
, (bShow
!= 0) );
1064 lpPos
->hwndIconTitle
= hWnd
= ICONTITLE_Create( pWnd
);
1067 if( ( pWnd
= WIN_FindWndPtr(hWnd
) ) != NULL
)
1069 if( !(pWnd
->dwStyle
& WS_VISIBLE
) )
1071 SendMessageA( hWnd
, WM_SHOWWINDOW
, TRUE
, 0 );
1072 SetWindowPos( hWnd
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
1073 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_SHOWWINDOW
);
1075 WIN_ReleaseWndPtr(pWnd
);
1078 else ShowWindow( hWnd
, SW_HIDE
);
1083 /*******************************************************************
1084 * WINPOS_GetMinMaxInfo
1086 * Get the minimized and maximized information for a window.
1088 void WINPOS_GetMinMaxInfo( WND
*wndPtr
, POINT
*maxSize
, POINT
*maxPos
,
1089 POINT
*minTrack
, POINT
*maxTrack
)
1091 LPINTERNALPOS lpPos
;
1095 /* Compute default values */
1097 MinMax
.ptMaxSize
.x
= GetSystemMetrics(SM_CXSCREEN
);
1098 MinMax
.ptMaxSize
.y
= GetSystemMetrics(SM_CYSCREEN
);
1099 MinMax
.ptMinTrackSize
.x
= GetSystemMetrics(SM_CXMINTRACK
);
1100 MinMax
.ptMinTrackSize
.y
= GetSystemMetrics(SM_CYMINTRACK
);
1101 MinMax
.ptMaxTrackSize
.x
= GetSystemMetrics(SM_CXSCREEN
);
1102 MinMax
.ptMaxTrackSize
.y
= GetSystemMetrics(SM_CYSCREEN
);
1104 if (wndPtr
->flags
& WIN_MANAGED
) xinc
= yinc
= 0;
1105 else if (HAS_DLGFRAME( wndPtr
->dwStyle
, wndPtr
->dwExStyle
))
1107 xinc
= GetSystemMetrics(SM_CXDLGFRAME
);
1108 yinc
= GetSystemMetrics(SM_CYDLGFRAME
);
1113 if (HAS_THICKFRAME(wndPtr
->dwStyle
))
1115 xinc
+= GetSystemMetrics(SM_CXFRAME
);
1116 yinc
+= GetSystemMetrics(SM_CYFRAME
);
1118 if (wndPtr
->dwStyle
& WS_BORDER
)
1120 xinc
+= GetSystemMetrics(SM_CXBORDER
);
1121 yinc
+= GetSystemMetrics(SM_CYBORDER
);
1124 MinMax
.ptMaxSize
.x
+= 2 * xinc
;
1125 MinMax
.ptMaxSize
.y
+= 2 * yinc
;
1127 lpPos
= (LPINTERNALPOS
)GetPropA( wndPtr
->hwndSelf
, atomInternalPos
);
1128 if( lpPos
&& !EMPTYPOINT(lpPos
->ptMaxPos
) )
1129 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &MinMax
.ptMaxPosition
);
1132 MinMax
.ptMaxPosition
.x
= -xinc
;
1133 MinMax
.ptMaxPosition
.y
= -yinc
;
1136 SendMessageA( wndPtr
->hwndSelf
, WM_GETMINMAXINFO
, 0, (LPARAM
)&MinMax
);
1138 /* Some sanity checks */
1140 TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1141 MinMax
.ptMaxSize
.x
, MinMax
.ptMaxSize
.y
,
1142 MinMax
.ptMaxPosition
.x
, MinMax
.ptMaxPosition
.y
,
1143 MinMax
.ptMaxTrackSize
.x
, MinMax
.ptMaxTrackSize
.y
,
1144 MinMax
.ptMinTrackSize
.x
, MinMax
.ptMinTrackSize
.y
);
1145 MinMax
.ptMaxTrackSize
.x
= MAX( MinMax
.ptMaxTrackSize
.x
,
1146 MinMax
.ptMinTrackSize
.x
);
1147 MinMax
.ptMaxTrackSize
.y
= MAX( MinMax
.ptMaxTrackSize
.y
,
1148 MinMax
.ptMinTrackSize
.y
);
1150 if (maxSize
) *maxSize
= MinMax
.ptMaxSize
;
1151 if (maxPos
) *maxPos
= MinMax
.ptMaxPosition
;
1152 if (minTrack
) *minTrack
= MinMax
.ptMinTrackSize
;
1153 if (maxTrack
) *maxTrack
= MinMax
.ptMaxTrackSize
;
1156 /***********************************************************************
1157 * WINPOS_MinMaximize
1159 * Fill in lpRect and return additional flags to be used with SetWindowPos().
1160 * This function assumes that 'cmd' is different from the current window
1163 UINT
WINPOS_MinMaximize( WND
* wndPtr
, UINT16 cmd
, LPRECT16 lpRect
)
1167 LPINTERNALPOS lpPos
;
1169 TRACE("0x%04x %u\n", wndPtr
->hwndSelf
, cmd
);
1171 size
.x
= wndPtr
->rectWindow
.left
; size
.y
= wndPtr
->rectWindow
.top
;
1172 lpPos
= WINPOS_InitInternalPos( wndPtr
, size
, &wndPtr
->rectWindow
);
1174 if (lpPos
&& !HOOK_CallHooks16(WH_CBT
, HCBT_MINMAX
, wndPtr
->hwndSelf
, cmd
))
1176 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1178 if( !SendMessageA( wndPtr
->hwndSelf
, WM_QUERYOPEN
, 0, 0L ) )
1179 return (SWP_NOSIZE
| SWP_NOMOVE
);
1180 swpFlags
|= SWP_NOCOPYBITS
;
1185 if( wndPtr
->dwStyle
& WS_MAXIMIZE
)
1187 wndPtr
->flags
|= WIN_RESTORE_MAX
;
1188 wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
1191 wndPtr
->flags
&= ~WIN_RESTORE_MAX
;
1192 wndPtr
->dwStyle
|= WS_MINIMIZE
;
1194 if( wndPtr
->flags
& WIN_NATIVE
)
1195 if( wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, TRUE
) )
1196 swpFlags
|= MINMAX_NOSWP
;
1198 lpPos
->ptIconPos
= WINPOS_FindIconPos( wndPtr
, lpPos
->ptIconPos
);
1200 SetRect16( lpRect
, lpPos
->ptIconPos
.x
, lpPos
->ptIconPos
.y
,
1201 GetSystemMetrics(SM_CXICON
), GetSystemMetrics(SM_CYICON
) );
1202 swpFlags
|= SWP_NOCOPYBITS
;
1206 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &pt
);
1207 WINPOS_GetMinMaxInfo( wndPtr
, &size
, &pt
, NULL
, NULL
);
1208 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1210 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1212 if( wndPtr
->flags
& WIN_NATIVE
)
1213 if( wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, FALSE
) )
1214 swpFlags
|= MINMAX_NOSWP
;
1216 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
1217 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
1219 wndPtr
->dwStyle
|= WS_MAXIMIZE
;
1221 SetRect16( lpRect
, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
,
1226 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1228 if( wndPtr
->flags
& WIN_NATIVE
)
1229 if( wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, FALSE
) )
1230 swpFlags
|= MINMAX_NOSWP
;
1232 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
1233 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
1235 if( wndPtr
->flags
& WIN_RESTORE_MAX
)
1237 /* Restore to maximized position */
1238 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &pt
);
1239 WINPOS_GetMinMaxInfo( wndPtr
, &size
, &pt
, NULL
, NULL
);
1240 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1241 wndPtr
->dwStyle
|= WS_MAXIMIZE
;
1242 SetRect16( lpRect
, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
, size
.x
, size
.y
);
1247 if( !(wndPtr
->dwStyle
& WS_MAXIMIZE
) ) return (UINT16
)(-1);
1248 else wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
1250 /* Restore to normal position */
1252 *lpRect
= lpPos
->rectNormal
;
1253 lpRect
->right
-= lpRect
->left
;
1254 lpRect
->bottom
-= lpRect
->top
;
1258 } else swpFlags
|= SWP_NOSIZE
| SWP_NOMOVE
;
1262 /***********************************************************************
1263 * ShowWindowAsync (USER32.535)
1265 * doesn't wait; returns immediately.
1266 * used by threads to toggle windows in other (possibly hanging) threads
1268 BOOL WINAPI
ShowWindowAsync( HWND hwnd
, INT cmd
)
1270 /* FIXME: does ShowWindow() return immediately ? */
1271 return ShowWindow(hwnd
, cmd
);
1275 /***********************************************************************
1276 * ShowWindow16 (USER.42)
1278 BOOL16 WINAPI
ShowWindow16( HWND16 hwnd
, INT16 cmd
)
1280 return ShowWindow(hwnd
,cmd
);
1284 /***********************************************************************
1285 * ShowWindow (USER32.534)
1287 BOOL WINAPI
ShowWindow( HWND hwnd
, INT cmd
)
1289 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
1290 BOOL wasVisible
, showFlag
;
1291 RECT16 newPos
= {0, 0, 0, 0};
1294 if (!wndPtr
) return FALSE
;
1296 TRACE("hwnd=%04x, cmd=%d\n", hwnd
, cmd
);
1298 wasVisible
= (wndPtr
->dwStyle
& WS_VISIBLE
) != 0;
1303 if (!wasVisible
) goto END
;;
1304 swp
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
|
1305 SWP_NOACTIVATE
| SWP_NOZORDER
;
1308 case SW_SHOWMINNOACTIVE
:
1309 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1311 case SW_SHOWMINIMIZED
:
1312 swp
|= SWP_SHOWWINDOW
;
1315 swp
|= SWP_FRAMECHANGED
;
1316 if( !(wndPtr
->dwStyle
& WS_MINIMIZE
) )
1317 swp
|= WINPOS_MinMaximize( wndPtr
, SW_MINIMIZE
, &newPos
);
1318 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1321 case SW_SHOWMAXIMIZED
: /* same as SW_MAXIMIZE */
1322 swp
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
1323 if( !(wndPtr
->dwStyle
& WS_MAXIMIZE
) )
1324 swp
|= WINPOS_MinMaximize( wndPtr
, SW_MAXIMIZE
, &newPos
);
1325 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1329 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1332 swp
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
1335 * ShowWindow has a little peculiar behavior that if the
1336 * window is already the topmost window, it will not
1339 if (GetTopWindow((HWND
)0)==hwnd
&& (wasVisible
|| GetActiveWindow() == hwnd
))
1340 swp
|= SWP_NOACTIVATE
;
1344 case SW_SHOWNOACTIVATE
:
1345 swp
|= SWP_NOZORDER
;
1346 if (GetActiveWindow()) swp
|= SWP_NOACTIVATE
;
1348 case SW_SHOWNORMAL
: /* same as SW_NORMAL: */
1349 case SW_SHOWDEFAULT
: /* FIXME: should have its own handler */
1351 swp
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
1353 if( wndPtr
->dwStyle
& (WS_MINIMIZE
| WS_MAXIMIZE
) )
1354 swp
|= WINPOS_MinMaximize( wndPtr
, SW_RESTORE
, &newPos
);
1355 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1359 showFlag
= (cmd
!= SW_HIDE
);
1360 if (showFlag
!= wasVisible
)
1362 SendMessageA( hwnd
, WM_SHOWWINDOW
, showFlag
, 0 );
1363 if (!IsWindow( hwnd
)) goto END
;
1366 if ((wndPtr
->dwStyle
& WS_CHILD
) &&
1367 !IsWindowVisible( wndPtr
->parent
->hwndSelf
) &&
1368 (swp
& (SWP_NOSIZE
| SWP_NOMOVE
)) == (SWP_NOSIZE
| SWP_NOMOVE
) )
1370 /* Don't call SetWindowPos() on invisible child windows */
1371 if (cmd
== SW_HIDE
) wndPtr
->dwStyle
&= ~WS_VISIBLE
;
1372 else wndPtr
->dwStyle
|= WS_VISIBLE
;
1376 /* We can't activate a child window */
1377 if ((wndPtr
->dwStyle
& WS_CHILD
) &&
1378 !(wndPtr
->dwExStyle
& WS_EX_MDICHILD
))
1379 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1380 if (!(swp
& MINMAX_NOSWP
))
1382 SetWindowPos( hwnd
, HWND_TOP
, newPos
.left
, newPos
.top
,
1383 newPos
.right
, newPos
.bottom
, LOWORD(swp
) );
1386 /* FIXME: This will cause the window to be activated irrespective
1387 * of whether it is owned by the same thread. Has to be done
1391 if (hwnd
== GetActiveWindow())
1392 WINPOS_ActivateOtherWindow(wndPtr
);
1394 /* Revert focus to parent */
1395 if (hwnd
== GetFocus() || IsChild(hwnd
, GetFocus()))
1396 SetFocus( GetParent(hwnd
) );
1399 if (!IsWindow( hwnd
)) goto END
;
1400 else if( wndPtr
->dwStyle
& WS_MINIMIZE
) WINPOS_ShowIconTitle( wndPtr
, TRUE
);
1403 if (wndPtr
->flags
& WIN_NEED_SIZE
)
1405 /* should happen only in CreateWindowEx() */
1406 int wParam
= SIZE_RESTORED
;
1408 wndPtr
->flags
&= ~WIN_NEED_SIZE
;
1409 if (wndPtr
->dwStyle
& WS_MAXIMIZE
) wParam
= SIZE_MAXIMIZED
;
1410 else if (wndPtr
->dwStyle
& WS_MINIMIZE
) wParam
= SIZE_MINIMIZED
;
1411 SendMessageA( hwnd
, WM_SIZE
, wParam
,
1412 MAKELONG(wndPtr
->rectClient
.right
-wndPtr
->rectClient
.left
,
1413 wndPtr
->rectClient
.bottom
-wndPtr
->rectClient
.top
));
1414 SendMessageA( hwnd
, WM_MOVE
, 0,
1415 MAKELONG(wndPtr
->rectClient
.left
, wndPtr
->rectClient
.top
) );
1419 WIN_ReleaseWndPtr(wndPtr
);
1424 /***********************************************************************
1425 * GetInternalWindowPos16 (USER.460)
1427 UINT16 WINAPI
GetInternalWindowPos16( HWND16 hwnd
, LPRECT16 rectWnd
,
1430 WINDOWPLACEMENT16 wndpl
;
1431 if (GetWindowPlacement16( hwnd
, &wndpl
))
1433 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
1434 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
1435 return wndpl
.showCmd
;
1441 /***********************************************************************
1442 * GetInternalWindowPos (USER32.245)
1444 UINT WINAPI
GetInternalWindowPos( HWND hwnd
, LPRECT rectWnd
,
1447 WINDOWPLACEMENT wndpl
;
1448 if (GetWindowPlacement( hwnd
, &wndpl
))
1450 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
1451 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
1452 return wndpl
.showCmd
;
1457 /***********************************************************************
1458 * GetWindowPlacement16 (USER.370)
1460 BOOL16 WINAPI
GetWindowPlacement16( HWND16 hwnd
, WINDOWPLACEMENT16
*wndpl
)
1462 WND
*pWnd
= WIN_FindWndPtr( hwnd
);
1463 LPINTERNALPOS lpPos
;
1465 if(!pWnd
) return FALSE
;
1467 lpPos
= (LPINTERNALPOS
)WINPOS_InitInternalPos( pWnd
,
1468 *(LPPOINT
)&pWnd
->rectWindow
.left
, &pWnd
->rectWindow
);
1469 wndpl
->length
= sizeof(*wndpl
);
1470 if( pWnd
->dwStyle
& WS_MINIMIZE
)
1471 wndpl
->showCmd
= SW_SHOWMINIMIZED
;
1473 wndpl
->showCmd
= ( pWnd
->dwStyle
& WS_MAXIMIZE
)
1474 ? SW_SHOWMAXIMIZED
: SW_SHOWNORMAL
;
1475 if( pWnd
->flags
& WIN_RESTORE_MAX
)
1476 wndpl
->flags
= WPF_RESTORETOMAXIMIZED
;
1479 wndpl
->ptMinPosition
= lpPos
->ptIconPos
;
1480 wndpl
->ptMaxPosition
= lpPos
->ptMaxPos
;
1481 wndpl
->rcNormalPosition
= lpPos
->rectNormal
;
1483 WIN_ReleaseWndPtr(pWnd
);
1488 /***********************************************************************
1489 * GetWindowPlacement (USER32.307)
1492 * Fails if wndpl->length of Win95 (!) apps is invalid.
1494 BOOL WINAPI
GetWindowPlacement( HWND hwnd
, WINDOWPLACEMENT
*pwpl32
)
1498 WINDOWPLACEMENT16 wpl
;
1499 wpl
.length
= sizeof(wpl
);
1500 if( GetWindowPlacement16( hwnd
, &wpl
) )
1502 pwpl32
->length
= sizeof(*pwpl32
);
1503 pwpl32
->flags
= wpl
.flags
;
1504 pwpl32
->showCmd
= wpl
.showCmd
;
1505 CONV_POINT16TO32( &wpl
.ptMinPosition
, &pwpl32
->ptMinPosition
);
1506 CONV_POINT16TO32( &wpl
.ptMaxPosition
, &pwpl32
->ptMaxPosition
);
1507 CONV_RECT16TO32( &wpl
.rcNormalPosition
, &pwpl32
->rcNormalPosition
);
1515 /***********************************************************************
1516 * WINPOS_SetPlacement
1518 static BOOL
WINPOS_SetPlacement( HWND hwnd
, const WINDOWPLACEMENT16
*wndpl
,
1521 WND
*pWnd
= WIN_FindWndPtr( hwnd
);
1524 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)WINPOS_InitInternalPos( pWnd
,
1525 *(LPPOINT
)&pWnd
->rectWindow
.left
, &pWnd
->rectWindow
);
1527 if( flags
& PLACE_MIN
) lpPos
->ptIconPos
= wndpl
->ptMinPosition
;
1528 if( flags
& PLACE_MAX
) lpPos
->ptMaxPos
= wndpl
->ptMaxPosition
;
1529 if( flags
& PLACE_RECT
) lpPos
->rectNormal
= wndpl
->rcNormalPosition
;
1531 if( pWnd
->dwStyle
& WS_MINIMIZE
)
1533 WINPOS_ShowIconTitle( pWnd
, FALSE
);
1534 if( wndpl
->flags
& WPF_SETMINPOSITION
&& !EMPTYPOINT(lpPos
->ptIconPos
))
1535 SetWindowPos( hwnd
, 0, lpPos
->ptIconPos
.x
, lpPos
->ptIconPos
.y
,
1536 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1538 else if( pWnd
->dwStyle
& WS_MAXIMIZE
)
1540 if( !EMPTYPOINT(lpPos
->ptMaxPos
) )
1541 SetWindowPos( hwnd
, 0, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
,
1542 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1544 else if( flags
& PLACE_RECT
)
1545 SetWindowPos( hwnd
, 0, lpPos
->rectNormal
.left
, lpPos
->rectNormal
.top
,
1546 lpPos
->rectNormal
.right
- lpPos
->rectNormal
.left
,
1547 lpPos
->rectNormal
.bottom
- lpPos
->rectNormal
.top
,
1548 SWP_NOZORDER
| SWP_NOACTIVATE
);
1550 ShowWindow( hwnd
, wndpl
->showCmd
);
1551 if( IsWindow(hwnd
) && pWnd
->dwStyle
& WS_MINIMIZE
)
1553 if( pWnd
->dwStyle
& WS_VISIBLE
) WINPOS_ShowIconTitle( pWnd
, TRUE
);
1555 /* SDK: ...valid only the next time... */
1556 if( wndpl
->flags
& WPF_RESTORETOMAXIMIZED
) pWnd
->flags
|= WIN_RESTORE_MAX
;
1558 WIN_ReleaseWndPtr(pWnd
);
1565 /***********************************************************************
1566 * SetWindowPlacement16 (USER.371)
1568 BOOL16 WINAPI
SetWindowPlacement16(HWND16 hwnd
, const WINDOWPLACEMENT16
*wndpl
)
1570 return WINPOS_SetPlacement( hwnd
, wndpl
,
1571 PLACE_MIN
| PLACE_MAX
| PLACE_RECT
);
1574 /***********************************************************************
1575 * SetWindowPlacement (USER32.519)
1578 * Fails if wndpl->length of Win95 (!) apps is invalid.
1580 BOOL WINAPI
SetWindowPlacement( HWND hwnd
, const WINDOWPLACEMENT
*pwpl32
)
1584 WINDOWPLACEMENT16 wpl
;
1586 wpl
.length
= sizeof(WINDOWPLACEMENT16
);
1587 wpl
.flags
= pwpl32
->flags
;
1588 wpl
.showCmd
= pwpl32
->showCmd
;
1589 wpl
.ptMinPosition
.x
= pwpl32
->ptMinPosition
.x
;
1590 wpl
.ptMinPosition
.y
= pwpl32
->ptMinPosition
.y
;
1591 wpl
.ptMaxPosition
.x
= pwpl32
->ptMaxPosition
.x
;
1592 wpl
.ptMaxPosition
.y
= pwpl32
->ptMaxPosition
.y
;
1593 wpl
.rcNormalPosition
.left
= pwpl32
->rcNormalPosition
.left
;
1594 wpl
.rcNormalPosition
.top
= pwpl32
->rcNormalPosition
.top
;
1595 wpl
.rcNormalPosition
.right
= pwpl32
->rcNormalPosition
.right
;
1596 wpl
.rcNormalPosition
.bottom
= pwpl32
->rcNormalPosition
.bottom
;
1598 return WINPOS_SetPlacement( hwnd
, &wpl
, PLACE_MIN
| PLACE_MAX
| PLACE_RECT
);
1604 /***********************************************************************
1605 * SetInternalWindowPos16 (USER.461)
1607 void WINAPI
SetInternalWindowPos16( HWND16 hwnd
, UINT16 showCmd
,
1608 LPRECT16 rect
, LPPOINT16 pt
)
1610 if( IsWindow16(hwnd
) )
1612 WINDOWPLACEMENT16 wndpl
;
1615 wndpl
.length
= sizeof(wndpl
);
1616 wndpl
.showCmd
= showCmd
;
1617 wndpl
.flags
= flags
= 0;
1622 wndpl
.flags
|= WPF_SETMINPOSITION
;
1623 wndpl
.ptMinPosition
= *pt
;
1627 flags
|= PLACE_RECT
;
1628 wndpl
.rcNormalPosition
= *rect
;
1630 WINPOS_SetPlacement( hwnd
, &wndpl
, flags
);
1635 /***********************************************************************
1636 * SetInternalWindowPos (USER32.483)
1638 void WINAPI
SetInternalWindowPos( HWND hwnd
, UINT showCmd
,
1639 LPRECT rect
, LPPOINT pt
)
1641 if( IsWindow(hwnd
) )
1643 WINDOWPLACEMENT16 wndpl
;
1646 wndpl
.length
= sizeof(wndpl
);
1647 wndpl
.showCmd
= showCmd
;
1648 wndpl
.flags
= flags
= 0;
1653 wndpl
.flags
|= WPF_SETMINPOSITION
;
1654 CONV_POINT32TO16( pt
, &wndpl
.ptMinPosition
);
1658 flags
|= PLACE_RECT
;
1659 CONV_RECT32TO16( rect
, &wndpl
.rcNormalPosition
);
1661 WINPOS_SetPlacement( hwnd
, &wndpl
, flags
);
1665 /*******************************************************************
1666 * WINPOS_SetActiveWindow
1668 * SetActiveWindow() back-end. This is the only function that
1669 * can assign active status to a window. It must be called only
1670 * for the top level windows.
1672 BOOL
WINPOS_SetActiveWindow( HWND hWnd
, BOOL fMouse
, BOOL fChangeFocus
)
1674 CBTACTIVATESTRUCT16
* cbtStruct
;
1675 WND
* wndPtr
=0, *wndTemp
;
1676 HQUEUE16 hOldActiveQueue
, hNewActiveQueue
;
1677 MESSAGEQUEUE
*pOldActiveQueue
= 0, *pNewActiveQueue
= 0;
1679 HWND hwndActive
= 0;
1682 TRACE("(%04x, %d, %d)\n", hWnd
, fMouse
, fChangeFocus
);
1684 /* Get current active window from the active queue */
1687 pOldActiveQueue
= QUEUE_Lock( hActiveQueue
);
1688 if ( pOldActiveQueue
)
1689 hwndActive
= PERQDATA_GetActiveWnd( pOldActiveQueue
->pQData
);
1692 /* paranoid checks */
1693 if( hWnd
== GetDesktopWindow() || (bRet
= (hWnd
== hwndActive
)) )
1696 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1699 wndPtr
= WIN_FindWndPtr(hWnd
);
1700 hOldActiveQueue
= hActiveQueue
;
1702 if( (wndTemp
= WIN_FindWndPtr(hwndActive
)) )
1704 wIconized
= HIWORD(wndTemp
->dwStyle
& WS_MINIMIZE
);
1705 WIN_ReleaseWndPtr(wndTemp
);
1708 TRACE("no current active window.\n");
1710 /* call CBT hook chain */
1711 if ((cbtStruct
= SEGPTR_NEW(CBTACTIVATESTRUCT16
)))
1713 cbtStruct
->fMouse
= fMouse
;
1714 cbtStruct
->hWndActive
= hwndActive
;
1715 bRet
= (BOOL
)HOOK_CallHooks16( WH_CBT
, HCBT_ACTIVATE
, (WPARAM16
)hWnd
,
1716 (LPARAM
)SEGPTR_GET(cbtStruct
) );
1717 SEGPTR_FREE(cbtStruct
);
1718 if (bRet
) goto CLEANUP_END
;
1721 /* set prev active wnd to current active wnd and send notification */
1722 if ((hwndPrevActive
= hwndActive
) && IsWindow(hwndPrevActive
))
1724 MESSAGEQUEUE
*pTempActiveQueue
= 0;
1726 if (!SendMessageA( hwndPrevActive
, WM_NCACTIVATE
, FALSE
, 0 ))
1728 if (GetSysModalWindow16() != hWnd
)
1730 /* disregard refusal if hWnd is sysmodal */
1733 SendMessageA( hwndPrevActive
, WM_ACTIVATE
,
1734 MAKEWPARAM( WA_INACTIVE
, wIconized
),
1737 /* check if something happened during message processing
1738 * (global active queue may have changed)
1740 pTempActiveQueue
= QUEUE_Lock( hActiveQueue
);
1741 if(!pTempActiveQueue
)
1744 hwndActive
= PERQDATA_GetActiveWnd( pTempActiveQueue
->pQData
);
1745 QUEUE_Unlock( pTempActiveQueue
);
1746 if( hwndPrevActive
!= hwndActive
)
1750 /* Set new active window in the message queue */
1754 pNewActiveQueue
= QUEUE_Lock( wndPtr
->hmemTaskQ
);
1755 if ( pNewActiveQueue
)
1756 PERQDATA_SetActiveWnd( pNewActiveQueue
->pQData
, hwndActive
);
1758 else /* have to do this or MDI frame activation goes to hell */
1759 if( pOldActiveQueue
)
1760 PERQDATA_SetActiveWnd( pOldActiveQueue
->pQData
, 0 );
1762 /* send palette messages */
1763 if (hWnd
&& SendMessage16( hWnd
, WM_QUERYNEWPALETTE
, 0, 0L))
1764 SendMessage16((HWND16
)-1, WM_PALETTEISCHANGING
, (WPARAM16
)hWnd
, 0L );
1766 /* if prev wnd is minimized redraw icon title */
1767 if( IsIconic( hwndPrevActive
) ) WINPOS_RedrawIconTitle(hwndPrevActive
);
1769 /* managed windows will get ConfigureNotify event */
1770 if (wndPtr
&& !(wndPtr
->dwStyle
& WS_CHILD
) && !(wndPtr
->flags
& WIN_MANAGED
))
1772 /* check Z-order and bring hWnd to the top */
1773 for (wndTemp
= WIN_LockWndPtr(WIN_GetDesktop()->child
); wndTemp
; WIN_UpdateWndPtr(&wndTemp
,wndTemp
->next
))
1775 if (wndTemp
->dwStyle
& WS_VISIBLE
) break;
1777 WIN_ReleaseDesktop();
1778 WIN_ReleaseWndPtr(wndTemp
);
1780 if( wndTemp
!= wndPtr
)
1781 SetWindowPos(hWnd
, HWND_TOP
, 0,0,0,0,
1782 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
1783 if (!IsWindow(hWnd
))
1787 /* Get a handle to the new active queue */
1788 hNewActiveQueue
= wndPtr
? wndPtr
->hmemTaskQ
: 0;
1790 /* send WM_ACTIVATEAPP if necessary */
1791 if (hOldActiveQueue
!= hNewActiveQueue
)
1793 WND
**list
, **ppWnd
;
1794 WND
*pDesktop
= WIN_GetDesktop();
1796 if ((list
= WIN_BuildWinArray( pDesktop
, 0, NULL
)))
1798 for (ppWnd
= list
; *ppWnd
; ppWnd
++)
1800 if (!IsWindow( (*ppWnd
)->hwndSelf
)) continue;
1802 if ((*ppWnd
)->hmemTaskQ
== hOldActiveQueue
)
1803 SendMessage16( (*ppWnd
)->hwndSelf
, WM_ACTIVATEAPP
,
1804 0, QUEUE_GetQueueTask(hNewActiveQueue
) );
1806 WIN_ReleaseWinArray(list
);
1809 hActiveQueue
= hNewActiveQueue
;
1811 if ((list
= WIN_BuildWinArray(pDesktop
, 0, NULL
)))
1813 for (ppWnd
= list
; *ppWnd
; ppWnd
++)
1815 if (!IsWindow( (*ppWnd
)->hwndSelf
)) continue;
1817 if ((*ppWnd
)->hmemTaskQ
== hNewActiveQueue
)
1818 SendMessage16( (*ppWnd
)->hwndSelf
, WM_ACTIVATEAPP
,
1819 1, QUEUE_GetQueueTask( hOldActiveQueue
) );
1821 WIN_ReleaseWinArray(list
);
1823 WIN_ReleaseDesktop();
1825 if (hWnd
&& !IsWindow(hWnd
)) goto CLEANUP
;
1830 /* walk up to the first unowned window */
1831 wndTemp
= WIN_LockWndPtr(wndPtr
);
1832 while (wndTemp
->owner
)
1834 WIN_UpdateWndPtr(&wndTemp
,wndTemp
->owner
);
1836 /* and set last active owned popup */
1837 wndTemp
->hwndLastActive
= hWnd
;
1839 wIconized
= HIWORD(wndTemp
->dwStyle
& WS_MINIMIZE
);
1840 WIN_ReleaseWndPtr(wndTemp
);
1841 SendMessageA( hWnd
, WM_NCACTIVATE
, TRUE
, 0 );
1842 SendMessageA( hWnd
, WM_ACTIVATE
,
1843 MAKEWPARAM( (fMouse
) ? WA_CLICKACTIVE
: WA_ACTIVE
, wIconized
),
1844 (LPARAM
)hwndPrevActive
);
1845 if( !IsWindow(hWnd
) ) goto CLEANUP
;
1848 /* change focus if possible */
1851 if ( pNewActiveQueue
)
1853 HWND hOldFocus
= PERQDATA_GetFocusWnd( pNewActiveQueue
->pQData
);
1855 if ( WIN_GetTopParent( hOldFocus
) != hwndActive
)
1856 FOCUS_SwitchFocus( pNewActiveQueue
, hOldFocus
,
1857 (wndPtr
&& (wndPtr
->dwStyle
& WS_MINIMIZE
))?
1861 if ( pOldActiveQueue
&&
1862 ( !pNewActiveQueue
||
1863 pNewActiveQueue
->pQData
!= pOldActiveQueue
->pQData
) )
1865 HWND hOldFocus
= PERQDATA_GetFocusWnd( pOldActiveQueue
->pQData
);
1867 FOCUS_SwitchFocus( pOldActiveQueue
, hOldFocus
, 0 );
1871 if( !hwndPrevActive
&& wndPtr
)
1872 (*wndPtr
->pDriver
->pForceWindowRaise
)(wndPtr
);
1874 /* if active wnd is minimized redraw icon title */
1875 if( IsIconic(hwndActive
) ) WINPOS_RedrawIconTitle(hwndActive
);
1877 bRet
= (hWnd
== hwndActive
); /* Success? */
1879 CLEANUP
: /* Unlock the message queues before returning */
1881 if ( pNewActiveQueue
)
1882 QUEUE_Unlock( pNewActiveQueue
);
1886 if ( pOldActiveQueue
)
1887 QUEUE_Unlock( pOldActiveQueue
);
1889 WIN_ReleaseWndPtr(wndPtr
);
1893 /*******************************************************************
1894 * WINPOS_ActivateOtherWindow
1896 * Activates window other than pWnd.
1898 BOOL
WINPOS_ActivateOtherWindow(WND
* pWnd
)
1902 HWND hwndActive
= 0;
1904 /* Get current active window from the active queue */
1907 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
1910 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
1911 QUEUE_Unlock( pActiveQueue
);
1915 if( pWnd
->hwndSelf
== hwndPrevActive
)
1918 if( hwndActive
!= pWnd
->hwndSelf
&&
1919 ( hwndActive
|| QUEUE_IsExitingQueue(pWnd
->hmemTaskQ
)) )
1922 if( !(pWnd
->dwStyle
& WS_POPUP
) || !(pWnd
->owner
) ||
1923 !WINPOS_CanActivate((pWndTo
= WIN_GetTopParentPtr(pWnd
->owner
))) )
1925 WND
* pWndPtr
= WIN_GetTopParentPtr(pWnd
);
1927 WIN_ReleaseWndPtr(pWndTo
);
1928 pWndTo
= WIN_FindWndPtr(hwndPrevActive
);
1930 while( !WINPOS_CanActivate(pWndTo
) )
1932 /* by now owned windows should've been taken care of */
1933 WIN_UpdateWndPtr(&pWndTo
,pWndPtr
->next
);
1934 WIN_UpdateWndPtr(&pWndPtr
,pWndTo
);
1935 if( !pWndTo
) break;
1937 WIN_ReleaseWndPtr(pWndPtr
);
1940 bRet
= WINPOS_SetActiveWindow( pWndTo
? pWndTo
->hwndSelf
: 0, FALSE
, TRUE
);
1942 /* switch desktop queue to current active */
1945 WIN_GetDesktop()->hmemTaskQ
= pWndTo
->hmemTaskQ
;
1946 WIN_ReleaseWndPtr(pWndTo
);
1947 WIN_ReleaseDesktop();
1954 /*******************************************************************
1955 * WINPOS_ChangeActiveWindow
1958 BOOL
WINPOS_ChangeActiveWindow( HWND hWnd
, BOOL mouseMsg
)
1960 WND
*wndPtr
, *wndTemp
;
1962 HWND hwndActive
= 0;
1964 /* Get current active window from the active queue */
1967 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
1970 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
1971 QUEUE_Unlock( pActiveQueue
);
1976 return WINPOS_SetActiveWindow( 0, mouseMsg
, TRUE
);
1978 wndPtr
= WIN_FindWndPtr(hWnd
);
1979 if( !wndPtr
) return FALSE
;
1981 /* child windows get WM_CHILDACTIVATE message */
1982 if( (wndPtr
->dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1984 retvalue
= SendMessageA(hWnd
, WM_CHILDACTIVATE
, 0, 0L);
1988 if( hWnd
== hwndActive
)
1994 if( !WINPOS_SetActiveWindow(hWnd
,mouseMsg
,TRUE
) )
2000 /* switch desktop queue to current active */
2001 wndTemp
= WIN_GetDesktop();
2002 if( wndPtr
->parent
== wndTemp
)
2003 wndTemp
->hmemTaskQ
= wndPtr
->hmemTaskQ
;
2004 WIN_ReleaseDesktop();
2008 WIN_ReleaseWndPtr(wndPtr
);
2013 /***********************************************************************
2014 * WINPOS_SendNCCalcSize
2016 * Send a WM_NCCALCSIZE message to a window.
2017 * All parameters are read-only except newClientRect.
2018 * oldWindowRect, oldClientRect and winpos must be non-NULL only
2019 * when calcValidRect is TRUE.
2021 LONG
WINPOS_SendNCCalcSize( HWND hwnd
, BOOL calcValidRect
,
2022 RECT
*newWindowRect
, RECT
*oldWindowRect
,
2023 RECT
*oldClientRect
, WINDOWPOS
*winpos
,
2024 RECT
*newClientRect
)
2026 NCCALCSIZE_PARAMS params
;
2027 WINDOWPOS winposCopy
;
2030 params
.rgrc
[0] = *newWindowRect
;
2033 winposCopy
= *winpos
;
2034 params
.rgrc
[1] = *oldWindowRect
;
2035 params
.rgrc
[2] = *oldClientRect
;
2036 params
.lppos
= &winposCopy
;
2038 result
= SendMessageA( hwnd
, WM_NCCALCSIZE
, calcValidRect
,
2040 TRACE("%d,%d-%d,%d\n",
2041 params
.rgrc
[0].left
, params
.rgrc
[0].top
,
2042 params
.rgrc
[0].right
, params
.rgrc
[0].bottom
);
2044 /* If the application send back garbage, ignore it */
2045 if (params
.rgrc
[0].left
<= params
.rgrc
[0].right
&& params
.rgrc
[0].top
<= params
.rgrc
[0].bottom
)
2046 *newClientRect
= params
.rgrc
[0];
2052 /***********************************************************************
2053 * WINPOS_HandleWindowPosChanging16
2055 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2057 LONG
WINPOS_HandleWindowPosChanging16( WND
*wndPtr
, WINDOWPOS16
*winpos
)
2059 POINT maxSize
, minTrack
;
2060 if (winpos
->flags
& SWP_NOSIZE
) return 0;
2061 if ((wndPtr
->dwStyle
& WS_THICKFRAME
) ||
2062 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) == 0))
2064 WINPOS_GetMinMaxInfo( wndPtr
, &maxSize
, NULL
, &minTrack
, NULL
);
2065 if (maxSize
.x
< winpos
->cx
) winpos
->cx
= maxSize
.x
;
2066 if (maxSize
.y
< winpos
->cy
) winpos
->cy
= maxSize
.y
;
2067 if (!(wndPtr
->dwStyle
& WS_MINIMIZE
))
2069 if (winpos
->cx
< minTrack
.x
) winpos
->cx
= minTrack
.x
;
2070 if (winpos
->cy
< minTrack
.y
) winpos
->cy
= minTrack
.y
;
2077 /***********************************************************************
2078 * WINPOS_HandleWindowPosChanging
2080 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2082 LONG
WINPOS_HandleWindowPosChanging( WND
*wndPtr
, WINDOWPOS
*winpos
)
2085 if (winpos
->flags
& SWP_NOSIZE
) return 0;
2086 if ((wndPtr
->dwStyle
& WS_THICKFRAME
) ||
2087 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) == 0))
2089 WINPOS_GetMinMaxInfo( wndPtr
, &maxSize
, NULL
, NULL
, NULL
);
2090 winpos
->cx
= MIN( winpos
->cx
, maxSize
.x
);
2091 winpos
->cy
= MIN( winpos
->cy
, maxSize
.y
);
2096 /***********************************************************************
2099 * fix Z order taking into account owned popups -
2100 * basically we need to maintain them above the window that owns them
2102 * FIXME: hide/show owned popups when owner visibility changes.
2104 static HWND
SWP_DoOwnedPopups(WND
* pDesktop
, WND
* wndPtr
, HWND hwndInsertAfter
, WORD flags
)
2106 WND
* w
= WIN_LockWndPtr(pDesktop
->child
);
2108 WARN("(%04x) hInsertAfter = %04x\n", wndPtr
->hwndSelf
, hwndInsertAfter
);
2110 if( (wndPtr
->dwStyle
& WS_POPUP
) && wndPtr
->owner
)
2112 /* make sure this popup stays above the owner */
2114 HWND hwndLocalPrev
= HWND_TOP
;
2116 if( hwndInsertAfter
!= HWND_TOP
)
2118 while( w
!= wndPtr
->owner
)
2120 if (w
!= wndPtr
) hwndLocalPrev
= w
->hwndSelf
;
2121 if( hwndLocalPrev
== hwndInsertAfter
) break;
2122 WIN_UpdateWndPtr(&w
,w
->next
);
2124 hwndInsertAfter
= hwndLocalPrev
;
2127 else if( wndPtr
->dwStyle
& WS_CHILD
)
2130 WIN_UpdateWndPtr(&w
, pDesktop
->child
);
2134 if( w
== wndPtr
) break;
2136 if( (w
->dwStyle
& WS_POPUP
) && w
->owner
== wndPtr
)
2138 SetWindowPos(w
->hwndSelf
, hwndInsertAfter
, 0, 0, 0, 0,
2139 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOSENDCHANGING
| SWP_DEFERERASE
);
2140 hwndInsertAfter
= w
->hwndSelf
;
2142 WIN_UpdateWndPtr(&w
, w
->next
);
2146 WIN_ReleaseWndPtr(w
);
2147 return hwndInsertAfter
;
2150 /***********************************************************************
2153 * Make window look nice without excessive repainting
2155 * visible and update regions are in window coordinates
2156 * client and window rectangles are in parent client coordinates
2158 * FIXME: SWP_EX_PAINTSELF in uFlags works only if both old and new
2159 * window rects have the same origin.
2161 * Returns: uFlags and a dirty region in *pVisRgn.
2163 static UINT
SWP_CopyValidBits( WND
* Wnd
, HRGN
* pVisRgn
,
2164 LPRECT lpOldWndRect
,
2165 LPRECT lpOldClientRect
, UINT uFlags
)
2168 HRGN newVisRgn
, dirtyRgn
;
2169 INT my
= COMPLEXREGION
;
2171 TRACE("\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2172 Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
,
2173 Wnd
->rectWindow
.right
, Wnd
->rectWindow
.bottom
,
2174 lpOldWndRect
->left
, lpOldWndRect
->top
,
2175 lpOldWndRect
->right
, lpOldWndRect
->bottom
, *pVisRgn
);
2176 TRACE("\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2177 Wnd
->rectClient
.left
, Wnd
->rectClient
.top
,
2178 Wnd
->rectClient
.right
, Wnd
->rectClient
.bottom
,
2179 lpOldClientRect
->left
, lpOldClientRect
->top
,
2180 lpOldClientRect
->right
,lpOldClientRect
->bottom
);
2182 if( Wnd
->hrgnUpdate
== 1 )
2183 uFlags
|= SWP_EX_NOCOPY
; /* whole window is invalid, nothing to copy */
2185 newVisRgn
= DCE_GetVisRgn( Wnd
->hwndSelf
, DCX_WINDOW
| DCX_CLIPSIBLINGS
, 0, 0);
2186 dirtyRgn
= CreateRectRgn( 0, 0, 0, 0 );
2188 if( !(uFlags
& SWP_EX_NOCOPY
) ) /* make sure dst region covers only valid bits */
2189 my
= CombineRgn( dirtyRgn
, newVisRgn
, *pVisRgn
, RGN_AND
);
2191 if( (my
== NULLREGION
) || (uFlags
& SWP_EX_NOCOPY
) )
2195 TRACE("\twon't copy anything!\n");
2197 /* set dirtyRgn to the sum of old and new visible regions
2198 * in parent client coordinates */
2200 OffsetRgn( newVisRgn
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2201 OffsetRgn( *pVisRgn
, lpOldWndRect
->left
, lpOldWndRect
->top
);
2203 CombineRgn(*pVisRgn
, *pVisRgn
, newVisRgn
, RGN_OR
);
2205 else /* copy valid bits to a new location */
2207 INT dx
, dy
, ow
, oh
, nw
, nh
, ocw
, ncw
, och
, nch
;
2208 HRGN hrgnValid
= dirtyRgn
; /* non-empty intersection of old and new visible rgns */
2210 /* subtract already invalid region inside Wnd from the dst region */
2212 if( Wnd
->hrgnUpdate
)
2213 if( CombineRgn( hrgnValid
, hrgnValid
, Wnd
->hrgnUpdate
, RGN_DIFF
) == NULLREGION
)
2216 /* check if entire window can be copied */
2218 ow
= lpOldWndRect
->right
- lpOldWndRect
->left
;
2219 oh
= lpOldWndRect
->bottom
- lpOldWndRect
->top
;
2220 nw
= Wnd
->rectWindow
.right
- Wnd
->rectWindow
.left
;
2221 nh
= Wnd
->rectWindow
.bottom
- Wnd
->rectWindow
.top
;
2223 ocw
= lpOldClientRect
->right
- lpOldClientRect
->left
;
2224 och
= lpOldClientRect
->bottom
- lpOldClientRect
->top
;
2225 ncw
= Wnd
->rectClient
.right
- Wnd
->rectClient
.left
;
2226 nch
= Wnd
->rectClient
.bottom
- Wnd
->rectClient
.top
;
2228 if( (ocw
!= ncw
) || (och
!= nch
) ||
2229 ( ow
!= nw
) || ( oh
!= nh
) ||
2230 ((lpOldClientRect
->top
- lpOldWndRect
->top
) !=
2231 (Wnd
->rectClient
.top
- Wnd
->rectWindow
.top
)) ||
2232 ((lpOldClientRect
->left
- lpOldWndRect
->left
) !=
2233 (Wnd
->rectClient
.left
- Wnd
->rectWindow
.left
)) )
2235 dx
= Wnd
->rectClient
.left
- lpOldClientRect
->left
;
2236 dy
= Wnd
->rectClient
.top
- lpOldClientRect
->top
;
2238 /* restrict valid bits to the common client rect */
2240 r
.left
= Wnd
->rectClient
.left
- Wnd
->rectWindow
.left
;
2241 r
.top
= Wnd
->rectClient
.top
- Wnd
->rectWindow
.top
;
2242 r
.right
= r
.left
+ MIN( ocw
, ncw
);
2243 r
.bottom
= r
.top
+ MIN( och
, nch
);
2245 REGION_CropRgn( hrgnValid
, hrgnValid
, &r
,
2246 (uFlags
& SWP_EX_PAINTSELF
) ? NULL
: (POINT
*)&(Wnd
->rectWindow
));
2247 GetRgnBox( hrgnValid
, &r
);
2248 if( IsRectEmpty( &r
) )
2250 r
= *lpOldClientRect
;
2254 dx
= Wnd
->rectWindow
.left
- lpOldWndRect
->left
;
2255 dy
= Wnd
->rectWindow
.top
- lpOldWndRect
->top
;
2256 if( !(uFlags
& SWP_EX_PAINTSELF
) )
2257 OffsetRgn( hrgnValid
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2261 if( !(uFlags
& SWP_EX_PAINTSELF
) )
2263 /* Move remaining regions to parent coordinates */
2264 OffsetRgn( newVisRgn
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2265 OffsetRgn( *pVisRgn
, lpOldWndRect
->left
, lpOldWndRect
->top
);
2268 OffsetRect( &r
, -lpOldWndRect
->left
, -lpOldWndRect
->top
);
2270 TRACE("\tcomputing dirty region!\n");
2272 /* Compute combined dirty region (old + new - valid) */
2273 CombineRgn( *pVisRgn
, *pVisRgn
, newVisRgn
, RGN_OR
);
2274 CombineRgn( *pVisRgn
, *pVisRgn
, hrgnValid
, RGN_DIFF
);
2276 /* Blt valid bits, r is the rect to copy */
2284 /* get DC and clip rect with drawable rect to avoid superfluous expose events
2285 from copying clipped areas */
2287 if( uFlags
& SWP_EX_PAINTSELF
)
2289 hDC
= GetDCEx( Wnd
->hwndSelf
, hrgnValid
, DCX_WINDOW
| DCX_CACHE
|
2290 DCX_KEEPCLIPRGN
| DCX_INTERSECTRGN
| DCX_CLIPSIBLINGS
);
2291 rClip
.right
= nw
; rClip
.bottom
= nh
;
2295 hDC
= GetDCEx( Wnd
->parent
->hwndSelf
, hrgnValid
, DCX_CACHE
|
2296 DCX_KEEPCLIPRGN
| DCX_INTERSECTRGN
| DCX_CLIPSIBLINGS
);
2297 rClip
.right
= Wnd
->parent
->rectClient
.right
- Wnd
->parent
->rectClient
.left
;
2298 rClip
.bottom
= Wnd
->parent
->rectClient
.bottom
- Wnd
->parent
->rectClient
.top
;
2300 rClip
.left
= rClip
.top
= 0;
2302 if( (dc
= (DC
*)GDI_GetObjPtr(hDC
, DC_MAGIC
)) )
2304 if( oh
> nh
) r
.bottom
= r
.top
+ nh
;
2305 if( ow
< nw
) r
.right
= r
.left
+ nw
;
2307 if( IntersectRect( &r
, &r
, &rClip
) )
2309 Wnd
->pDriver
->pSurfaceCopy( Wnd
->parent
, dc
, dx
, dy
, &r
, TRUE
);
2311 /* When you copy the bits without repainting, parent doesn't
2312 get validated appropriately. Therefore, we have to validate
2313 the parent with the windows' updated region when the
2314 parent's update region is not empty. */
2316 if (Wnd
->parent
->hrgnUpdate
!= 0 && !(Wnd
->parent
->dwStyle
& WS_CLIPCHILDREN
))
2318 OffsetRect(&r
, dx
, dy
);
2319 ValidateRect(Wnd
->parent
->hwndSelf
, &r
);
2323 GDI_HEAP_UNLOCK( hDC
);
2325 ReleaseDC( (uFlags
& SWP_EX_PAINTSELF
) ?
2326 Wnd
->hwndSelf
: Wnd
->parent
->hwndSelf
, hDC
);
2330 /* *pVisRgn now points to the invalidated region */
2332 DeleteObject(newVisRgn
);
2333 DeleteObject(dirtyRgn
);
2337 /***********************************************************************
2338 * SWP_DoSimpleFrameChanged
2340 * NOTE: old and new client rect origins are identical, only
2341 * extents may have changed. Window extents are the same.
2343 static void SWP_DoSimpleFrameChanged( WND
* wndPtr
, RECT
* pOldClientRect
, WORD swpFlags
, UINT uFlags
)
2349 if( !(swpFlags
& SWP_NOCLIENTSIZE
) )
2351 /* Client rect changed its position/size, most likely a scrollar
2352 * was added/removed.
2354 * FIXME: WVR alignment flags
2357 if( wndPtr
->rectClient
.right
> pOldClientRect
->right
) /* right edge */
2361 rect
.bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
2362 rect
.right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
2363 if(!(uFlags
& SWP_EX_NOCOPY
))
2364 rect
.left
= pOldClientRect
->right
- wndPtr
->rectClient
.left
;
2372 if( wndPtr
->rectClient
.bottom
> pOldClientRect
->bottom
) /* bottom edge */
2375 hrgn
= CreateRectRgnIndirect( &rect
);
2377 rect
.right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
2378 rect
.bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
2379 if(!(uFlags
& SWP_EX_NOCOPY
))
2380 rect
.top
= pOldClientRect
->bottom
- wndPtr
->rectClient
.top
;
2384 REGION_UnionRectWithRgn( hrgn
, &rect
);
2387 if( i
== 0 && (uFlags
& SWP_EX_NOCOPY
) ) /* force redraw anyway */
2389 rect
= wndPtr
->rectWindow
;
2390 OffsetRect( &rect
, wndPtr
->rectWindow
.left
- wndPtr
->rectClient
.left
,
2391 wndPtr
->rectWindow
.top
- wndPtr
->rectClient
.top
);
2399 PAINT_RedrawWindow( wndPtr
->hwndSelf
, &rect
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
|
2400 RDW_ERASENOW
| RDW_ALLCHILDREN
, RDW_EX_TOPFRAME
| RDW_EX_USEHRGN
);
2404 WIN_UpdateNCRgn(wndPtr
, 0, UNC_UPDATE
| UNC_ENTIRE
);
2408 DeleteObject( hrgn
);
2411 /***********************************************************************
2412 * SWP_DoWinPosChanging
2414 static BOOL
SWP_DoWinPosChanging( WND
* wndPtr
, WINDOWPOS
* pWinpos
,
2415 RECT
* pNewWindowRect
, RECT
* pNewClientRect
)
2417 /* Send WM_WINDOWPOSCHANGING message */
2419 if (!(pWinpos
->flags
& SWP_NOSENDCHANGING
))
2420 SendMessageA( wndPtr
->hwndSelf
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
)pWinpos
);
2422 /* Calculate new position and size */
2424 *pNewWindowRect
= wndPtr
->rectWindow
;
2425 *pNewClientRect
= (wndPtr
->dwStyle
& WS_MINIMIZE
) ? wndPtr
->rectWindow
2426 : wndPtr
->rectClient
;
2428 if (!(pWinpos
->flags
& SWP_NOSIZE
))
2430 pNewWindowRect
->right
= pNewWindowRect
->left
+ pWinpos
->cx
;
2431 pNewWindowRect
->bottom
= pNewWindowRect
->top
+ pWinpos
->cy
;
2433 if (!(pWinpos
->flags
& SWP_NOMOVE
))
2435 pNewWindowRect
->left
= pWinpos
->x
;
2436 pNewWindowRect
->top
= pWinpos
->y
;
2437 pNewWindowRect
->right
+= pWinpos
->x
- wndPtr
->rectWindow
.left
;
2438 pNewWindowRect
->bottom
+= pWinpos
->y
- wndPtr
->rectWindow
.top
;
2440 OffsetRect( pNewClientRect
, pWinpos
->x
- wndPtr
->rectWindow
.left
,
2441 pWinpos
->y
- wndPtr
->rectWindow
.top
);
2444 pWinpos
->flags
|= SWP_NOCLIENTMOVE
| SWP_NOCLIENTSIZE
;
2448 /***********************************************************************
2451 static UINT
SWP_DoNCCalcSize( WND
* wndPtr
, WINDOWPOS
* pWinpos
,
2452 RECT
* pNewWindowRect
, RECT
* pNewClientRect
, WORD f
)
2456 /* Send WM_NCCALCSIZE message to get new client area */
2457 if( (pWinpos
->flags
& (SWP_FRAMECHANGED
| SWP_NOSIZE
)) != SWP_NOSIZE
)
2459 wvrFlags
= WINPOS_SendNCCalcSize( pWinpos
->hwnd
, TRUE
, pNewWindowRect
,
2460 &wndPtr
->rectWindow
, &wndPtr
->rectClient
,
2461 pWinpos
, pNewClientRect
);
2463 /* FIXME: WVR_ALIGNxxx */
2465 if( pNewClientRect
->left
!= wndPtr
->rectClient
.left
||
2466 pNewClientRect
->top
!= wndPtr
->rectClient
.top
)
2467 pWinpos
->flags
&= ~SWP_NOCLIENTMOVE
;
2469 if( (pNewClientRect
->right
- pNewClientRect
->left
!=
2470 wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
) ||
2471 (pNewClientRect
->bottom
- pNewClientRect
->top
!=
2472 wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
) )
2473 pWinpos
->flags
&= ~SWP_NOCLIENTSIZE
;
2476 if( !(f
& SWP_NOMOVE
) && (pNewClientRect
->left
!= wndPtr
->rectClient
.left
||
2477 pNewClientRect
->top
!= wndPtr
->rectClient
.top
) )
2478 pWinpos
->flags
&= ~SWP_NOCLIENTMOVE
;
2482 /***********************************************************************
2483 * SetWindowPos (USER.2)
2485 BOOL16 WINAPI
SetWindowPos16( HWND16 hwnd
, HWND16 hwndInsertAfter
,
2486 INT16 x
, INT16 y
, INT16 cx
, INT16 cy
, WORD flags
)
2488 return SetWindowPos(hwnd
,(INT
)(INT16
)hwndInsertAfter
,x
,y
,cx
,cy
,flags
);
2491 /***********************************************************************
2492 * SetWindowPos (USER32.520)
2494 BOOL WINAPI
SetWindowPos( HWND hwnd
, HWND hwndInsertAfter
,
2495 INT x
, INT y
, INT cx
, INT cy
, UINT flags
)
2498 WND
* wndPtr
,*wndTemp
;
2499 RECT newWindowRect
, newClientRect
;
2500 RECT oldWindowRect
, oldClientRect
;
2502 UINT wvrFlags
= 0, uFlags
= 0;
2503 BOOL retvalue
, resync
= FALSE
, bChangePos
;
2504 HWND hwndActive
= 0;
2506 /* Get current active window from the active queue */
2509 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
2512 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
2513 QUEUE_Unlock( pActiveQueue
);
2517 TRACE("hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2518 hwnd
, x
, y
, x
+cx
, y
+cy
, flags
);
2520 bChangePos
= !(flags
& SWP_WINE_NOHOSTMOVE
);
2521 flags
&= ~SWP_WINE_NOHOSTMOVE
;
2524 /* ------------------------------------------------------------------------ CHECKS */
2526 /* Check window handle */
2528 if (hwnd
== GetDesktopWindow()) return FALSE
;
2529 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return FALSE
;
2531 TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr
->rectWindow
.left
, wndPtr
->rectWindow
.top
,
2532 wndPtr
->rectWindow
.right
, wndPtr
->rectWindow
.bottom
, (unsigned)wndPtr
->dwStyle
);
2534 /* Fix redundant flags */
2536 if(wndPtr
->dwStyle
& WS_VISIBLE
)
2537 flags
&= ~SWP_SHOWWINDOW
;
2540 if (!(flags
& SWP_SHOWWINDOW
))
2541 flags
|= SWP_NOREDRAW
;
2542 flags
&= ~SWP_HIDEWINDOW
;
2545 if ( cx
< 0 ) cx
= 0; if( cy
< 0 ) cy
= 0;
2547 if ((wndPtr
->rectWindow
.right
- wndPtr
->rectWindow
.left
== cx
) &&
2548 (wndPtr
->rectWindow
.bottom
- wndPtr
->rectWindow
.top
== cy
))
2549 flags
|= SWP_NOSIZE
; /* Already the right size */
2551 if ((wndPtr
->rectWindow
.left
== x
) && (wndPtr
->rectWindow
.top
== y
))
2552 flags
|= SWP_NOMOVE
; /* Already the right position */
2554 if (hwnd
== hwndActive
)
2555 flags
|= SWP_NOACTIVATE
; /* Already active */
2556 else if ( (wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)
2558 if(!(flags
& SWP_NOACTIVATE
)) /* Bring to the top when activating */
2560 flags
&= ~SWP_NOZORDER
;
2561 hwndInsertAfter
= HWND_TOP
;
2566 /* Check hwndInsertAfter */
2568 /* FIXME: TOPMOST not supported yet */
2569 if ((hwndInsertAfter
== HWND_TOPMOST
) ||
2570 (hwndInsertAfter
== HWND_NOTOPMOST
)) hwndInsertAfter
= HWND_TOP
;
2572 /* hwndInsertAfter must be a sibling of the window */
2573 if ((hwndInsertAfter
!= HWND_TOP
) && (hwndInsertAfter
!= HWND_BOTTOM
))
2575 WND
* wnd
= WIN_FindWndPtr(hwndInsertAfter
);
2578 if( wnd
->parent
!= wndPtr
->parent
)
2581 WIN_ReleaseWndPtr(wnd
);
2584 if( wnd
->next
== wndPtr
) flags
|= SWP_NOZORDER
;
2586 WIN_ReleaseWndPtr(wnd
);
2589 Pos
: /* ------------------------------------------------------------------------ MAIN part */
2591 /* Fill the WINDOWPOS structure */
2594 winpos
.hwndInsertAfter
= hwndInsertAfter
;
2599 winpos
.flags
= flags
;
2601 SWP_DoWinPosChanging( wndPtr
, &winpos
, &newWindowRect
, &newClientRect
);
2603 if((winpos
.flags
& (SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) != SWP_NOZORDER
)
2605 if( wndPtr
->parent
== WIN_GetDesktop() )
2606 hwndInsertAfter
= SWP_DoOwnedPopups( wndPtr
->parent
, wndPtr
,
2607 hwndInsertAfter
, winpos
.flags
);
2608 WIN_ReleaseDesktop();
2611 if(!(wndPtr
->flags
& WIN_NATIVE
) )
2613 if( hwndInsertAfter
== HWND_TOP
)
2614 winpos
.flags
|= ( wndPtr
->parent
->child
== wndPtr
)? SWP_NOZORDER
: 0;
2616 if( hwndInsertAfter
== HWND_BOTTOM
)
2617 winpos
.flags
|= ( wndPtr
->next
)? 0: SWP_NOZORDER
;
2619 if( !(winpos
.flags
& SWP_NOZORDER
) )
2620 if( GetWindow(hwndInsertAfter
, GW_HWNDNEXT
) == wndPtr
->hwndSelf
)
2621 winpos
.flags
|= SWP_NOZORDER
;
2623 if( !(winpos
.flags
& (SWP_NOREDRAW
| SWP_SHOWWINDOW
)) &&
2624 ((winpos
.flags
& (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_FRAMECHANGED
))
2625 != (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
)) )
2627 /* get a previous visible region for SWP_CopyValidBits() */
2628 DWORD flags
= DCX_WINDOW
;
2630 if (wndPtr
->dwStyle
& WS_CLIPSIBLINGS
)
2631 flags
|= DCX_CLIPSIBLINGS
;
2633 visRgn
= DCE_GetVisRgn(hwnd
, flags
, 0, 0);
2637 /* Common operations */
2639 wvrFlags
= SWP_DoNCCalcSize( wndPtr
, &winpos
, &newWindowRect
, &newClientRect
, flags
);
2641 if(!(winpos
.flags
& SWP_NOZORDER
) && winpos
.hwnd
!= hwndInsertAfter
)
2643 if ( WIN_UnlinkWindow( winpos
.hwnd
) )
2644 WIN_LinkWindow( winpos
.hwnd
, hwndInsertAfter
);
2647 /* Reset active DCEs */
2649 if( (((winpos
.flags
& SWP_AGG_NOPOSCHANGE
) != SWP_AGG_NOPOSCHANGE
) &&
2650 wndPtr
->dwStyle
& WS_VISIBLE
) ||
2651 (flags
& (SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) )
2655 UnionRect(&rect
, &newWindowRect
, &wndPtr
->rectWindow
);
2656 DCE_InvalidateDCE(wndPtr
, &rect
);
2659 oldWindowRect
= wndPtr
->rectWindow
;
2660 oldClientRect
= wndPtr
->rectClient
;
2662 /* Find out if we have to redraw the whole client rect */
2664 if( oldClientRect
.bottom
- oldClientRect
.top
==
2665 newClientRect
.bottom
- newClientRect
.top
) wvrFlags
&= ~WVR_VREDRAW
;
2667 if( oldClientRect
.right
- oldClientRect
.left
==
2668 newClientRect
.right
- newClientRect
.left
) wvrFlags
&= ~WVR_HREDRAW
;
2670 if( (winpos
.flags
& SWP_NOCOPYBITS
) || (!(winpos
.flags
& SWP_NOCLIENTSIZE
) &&
2671 (wvrFlags
>= WVR_HREDRAW
) && (wvrFlags
< WVR_VALIDRECTS
)) )
2673 uFlags
|= SWP_EX_NOCOPY
;
2676 * Use this later in CopyValidBits()
2679 uFlags |= SWP_EX_NONCLIENT;
2682 /* FIXME: actually do something with WVR_VALIDRECTS */
2684 wndPtr
->rectWindow
= newWindowRect
;
2685 wndPtr
->rectClient
= newClientRect
;
2687 if (wndPtr
->flags
& WIN_NATIVE
) /* -------------------------------------------- hosted window */
2689 BOOL bCallDriver
= TRUE
;
2690 HWND tempInsertAfter
= winpos
.hwndInsertAfter
;
2692 winpos
.hwndInsertAfter
= hwndInsertAfter
;
2694 if( !(winpos
.flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
| SWP_NOREDRAW
)) )
2696 /* This is the only place where we need to force repainting of the contents
2697 of windows created by the host window system, all other cases go through the
2698 expose event handling */
2700 if( (winpos
.flags
& (SWP_NOSIZE
| SWP_FRAMECHANGED
)) == (SWP_NOSIZE
| SWP_FRAMECHANGED
) )
2702 cx
= newWindowRect
.right
- newWindowRect
.left
;
2703 cy
= newWindowRect
.bottom
- newWindowRect
.top
;
2705 wndPtr
->pDriver
->pSetWindowPos(wndPtr
, &winpos
, bChangePos
);
2706 winpos
.hwndInsertAfter
= tempInsertAfter
;
2707 bCallDriver
= FALSE
;
2709 if( winpos
.flags
& SWP_NOCLIENTMOVE
)
2710 SWP_DoSimpleFrameChanged(wndPtr
, &oldClientRect
, winpos
.flags
, uFlags
);
2713 /* client area moved but window extents remained the same, copy valid bits */
2715 visRgn
= CreateRectRgn( 0, 0, cx
, cy
);
2716 uFlags
= SWP_CopyValidBits( wndPtr
, &visRgn
, &oldWindowRect
, &oldClientRect
,
2717 uFlags
| SWP_EX_PAINTSELF
);
2724 if( !(winpos
.flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
| SWP_NOREDRAW
)) )
2726 if( (oldClientRect
.left
- oldWindowRect
.left
== newClientRect
.left
- newWindowRect
.left
) &&
2727 (oldClientRect
.top
- oldWindowRect
.top
== newClientRect
.top
- newWindowRect
.top
) &&
2728 !(uFlags
& SWP_EX_NOCOPY
) )
2730 /* The origin of the client rect didn't move so we can try to repaint
2731 * only the nonclient area by setting bit gravity hint for the host window system.
2734 if( !(wndPtr
->flags
& WIN_MANAGED
) )
2736 HRGN hrgn
= CreateRectRgn( 0, 0, newWindowRect
.right
- newWindowRect
.left
,
2737 newWindowRect
.bottom
- newWindowRect
.top
);
2738 RECT rcn
= newClientRect
;
2739 RECT rco
= oldClientRect
;
2741 OffsetRect( &rcn
, -newWindowRect
.left
, -newWindowRect
.top
);
2742 OffsetRect( &rco
, -oldWindowRect
.left
, -oldWindowRect
.top
);
2743 IntersectRect( &rcn
, &rcn
, &rco
);
2744 visRgn
= CreateRectRgnIndirect( &rcn
);
2745 CombineRgn( visRgn
, hrgn
, visRgn
, RGN_DIFF
);
2746 DeleteObject( hrgn
);
2747 uFlags
= SWP_EX_PAINTSELF
;
2749 wndPtr
->pDriver
->pSetHostAttr(wndPtr
, HAK_BITGRAVITY
, BGNorthWest
);
2752 wndPtr
->pDriver
->pSetHostAttr(wndPtr
, HAK_BITGRAVITY
, BGForget
);
2755 wndPtr
->pDriver
->pSetWindowPos(wndPtr
, &winpos
, bChangePos
);
2756 winpos
.hwndInsertAfter
= tempInsertAfter
;
2759 if( winpos
.flags
& SWP_SHOWWINDOW
)
2763 wndPtr
->dwStyle
|= WS_VISIBLE
;
2765 if (wndPtr
->flags
& WIN_MANAGED
) resync
= TRUE
;
2767 /* focus was set to unmapped window, reset host focus
2768 * since the window is now visible */
2770 focus
= curr
= GetFocus();
2775 WND
*pFocus
= WIN_FindWndPtr( focus
);
2777 pFocus
->pDriver
->pSetFocus(pFocus
);
2778 WIN_ReleaseWndPtr(pFocus
);
2781 curr
= GetParent(curr
);
2785 else /* -------------------------------------------- emulated window */
2787 if( winpos
.flags
& SWP_SHOWWINDOW
)
2789 wndPtr
->dwStyle
|= WS_VISIBLE
;
2790 uFlags
|= SWP_EX_PAINTSELF
;
2791 visRgn
= 1; /* redraw the whole window */
2793 else if( !(winpos
.flags
& SWP_NOREDRAW
) )
2795 if( winpos
.flags
& SWP_HIDEWINDOW
)
2797 if( visRgn
> 1 ) /* map to parent */
2798 OffsetRgn( visRgn
, oldWindowRect
.left
, oldWindowRect
.top
);
2804 if( (winpos
.flags
& SWP_AGG_NOPOSCHANGE
) != SWP_AGG_NOPOSCHANGE
)
2805 uFlags
= SWP_CopyValidBits(wndPtr
, &visRgn
, &oldWindowRect
,
2806 &oldClientRect
, uFlags
);
2809 /* nothing moved, redraw frame if needed */
2811 if( winpos
.flags
& SWP_FRAMECHANGED
)
2812 SWP_DoSimpleFrameChanged( wndPtr
, &oldClientRect
, winpos
.flags
, uFlags
);
2815 DeleteObject( visRgn
);
2823 if( winpos
.flags
& SWP_HIDEWINDOW
)
2825 wndPtr
->dwStyle
&= ~WS_VISIBLE
;
2827 if (hwnd
== CARET_GetHwnd()) DestroyCaret();
2830 /* ------------------------------------------------------------------------ FINAL */
2832 if (wndPtr
->flags
& WIN_NATIVE
)
2833 EVENT_Synchronize(); /* Synchronize with the host window system */
2835 if (!GetCapture() && ((wndPtr
->dwStyle
& WS_VISIBLE
) || (flags
& SWP_HIDEWINDOW
)))
2837 /* Simulate a mouse event to set the cursor */
2838 int iWndsLocks
= WIN_SuspendWndsLock();
2840 hardware_event( WM_MOUSEMOVE
, GET_KEYSTATE(), 0,
2841 PosX
, PosY
, GetTickCount(), 0 );
2843 WIN_RestoreWndsLock(iWndsLocks
);
2846 wndTemp
= WIN_GetDesktop();
2848 /* repaint invalidated region (if any)
2850 * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2851 * and force update after ChangeActiveWindow() to avoid painting frames twice.
2856 if( !(winpos
.flags
& SWP_NOREDRAW
) )
2859 /* Use PAINT_RedrawWindow to explicitly force an invalidation of the window,
2860 its parent and sibling and so on, and then erase the parent window
2861 back ground if the parent is either a top-level window or its parent's parent
2862 is top-level window. Rely on the system to repaint other affected
2863 windows later on. */
2864 if( uFlags
& SWP_EX_PAINTSELF
)
2866 PAINT_RedrawWindow( wndPtr
->hwndSelf
, NULL
, (visRgn
== 1) ? 0 : visRgn
,
2867 RDW_ERASE
| RDW_FRAME
| RDW_INVALIDATE
| RDW_ALLCHILDREN
,
2868 RDW_EX_XYWINDOW
| RDW_EX_USEHRGN
);
2872 PAINT_RedrawWindow( wndPtr
->parent
->hwndSelf
, NULL
, (visRgn
== 1) ? 0 : visRgn
,
2873 RDW_ERASE
| RDW_INVALIDATE
| RDW_ALLCHILDREN
,
2877 if(wndPtr
-> parent
== wndTemp
|| wndPtr
->parent
->parent
== wndTemp
)
2879 PAINT_RedrawWindow( wndPtr
->parent
->hwndSelf
, NULL
, 0,
2880 RDW_ERASENOW
| RDW_NOCHILDREN
, 0 );
2884 DeleteObject( visRgn
);
2887 WIN_ReleaseDesktop();
2889 if (!(flags
& SWP_NOACTIVATE
))
2890 WINPOS_ChangeActiveWindow( winpos
.hwnd
, FALSE
);
2892 /* And last, send the WM_WINDOWPOSCHANGED message */
2894 TRACE("\tstatus flags = %04x\n", winpos
.flags
& SWP_AGG_STATUSFLAGS
);
2897 (((winpos
.flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOPOSCHANGE
) &&
2898 !(winpos
.flags
& SWP_NOSENDCHANGING
)) )
2900 SendMessageA( winpos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
)&winpos
);
2901 if (resync
) EVENT_Synchronize();
2906 WIN_ReleaseWndPtr(wndPtr
);
2911 /***********************************************************************
2912 * BeginDeferWindowPos16 (USER.259)
2914 HDWP16 WINAPI
BeginDeferWindowPos16( INT16 count
)
2916 return BeginDeferWindowPos( count
);
2920 /***********************************************************************
2921 * BeginDeferWindowPos (USER32.9)
2923 HDWP WINAPI
BeginDeferWindowPos( INT count
)
2928 if (count
<= 0) return 0;
2929 handle
= USER_HEAP_ALLOC( sizeof(DWP
) + (count
-1)*sizeof(WINDOWPOS
) );
2930 if (!handle
) return 0;
2931 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( handle
);
2932 pDWP
->actualCount
= 0;
2933 pDWP
->suggestedCount
= count
;
2935 pDWP
->wMagic
= DWP_MAGIC
;
2936 pDWP
->hwndParent
= 0;
2941 /***********************************************************************
2942 * DeferWindowPos16 (USER.260)
2944 HDWP16 WINAPI
DeferWindowPos16( HDWP16 hdwp
, HWND16 hwnd
, HWND16 hwndAfter
,
2945 INT16 x
, INT16 y
, INT16 cx
, INT16 cy
,
2948 return DeferWindowPos( hdwp
, hwnd
, (INT
)(INT16
)hwndAfter
,
2949 x
, y
, cx
, cy
, flags
);
2953 /***********************************************************************
2954 * DeferWindowPos (USER32.128)
2956 HDWP WINAPI
DeferWindowPos( HDWP hdwp
, HWND hwnd
, HWND hwndAfter
,
2957 INT x
, INT y
, INT cx
, INT cy
,
2962 HDWP newhdwp
= hdwp
,retvalue
;
2966 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
2967 if (!pDWP
) return 0;
2968 if (hwnd
== GetDesktopWindow()) return 0;
2970 if (!(pWnd
=WIN_FindWndPtr( hwnd
))) {
2971 USER_HEAP_FREE( hdwp
);
2975 /* Numega Bounds Checker Demo dislikes the following code.
2976 In fact, I've not been able to find any "same parent" requirement in any docu
2980 /* All the windows of a DeferWindowPos() must have the same parent */
2981 parent
= pWnd
->parent
->hwndSelf
;
2982 if (pDWP
->actualCount
== 0) pDWP
->hwndParent
= parent
;
2983 else if (parent
!= pDWP
->hwndParent
)
2985 USER_HEAP_FREE( hdwp
);
2991 for (i
= 0; i
< pDWP
->actualCount
; i
++)
2993 if (pDWP
->winPos
[i
].hwnd
== hwnd
)
2995 /* Merge with the other changes */
2996 if (!(flags
& SWP_NOZORDER
))
2998 pDWP
->winPos
[i
].hwndInsertAfter
= hwndAfter
;
3000 if (!(flags
& SWP_NOMOVE
))
3002 pDWP
->winPos
[i
].x
= x
;
3003 pDWP
->winPos
[i
].y
= y
;
3005 if (!(flags
& SWP_NOSIZE
))
3007 pDWP
->winPos
[i
].cx
= cx
;
3008 pDWP
->winPos
[i
].cy
= cy
;
3010 pDWP
->winPos
[i
].flags
&= flags
| ~(SWP_NOSIZE
| SWP_NOMOVE
|
3011 SWP_NOZORDER
| SWP_NOREDRAW
|
3012 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
3014 pDWP
->winPos
[i
].flags
|= flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
|
3020 if (pDWP
->actualCount
>= pDWP
->suggestedCount
)
3022 newhdwp
= USER_HEAP_REALLOC( hdwp
,
3023 sizeof(DWP
) + pDWP
->suggestedCount
*sizeof(WINDOWPOS
) );
3029 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( newhdwp
);
3030 pDWP
->suggestedCount
++;
3032 pDWP
->winPos
[pDWP
->actualCount
].hwnd
= hwnd
;
3033 pDWP
->winPos
[pDWP
->actualCount
].hwndInsertAfter
= hwndAfter
;
3034 pDWP
->winPos
[pDWP
->actualCount
].x
= x
;
3035 pDWP
->winPos
[pDWP
->actualCount
].y
= y
;
3036 pDWP
->winPos
[pDWP
->actualCount
].cx
= cx
;
3037 pDWP
->winPos
[pDWP
->actualCount
].cy
= cy
;
3038 pDWP
->winPos
[pDWP
->actualCount
].flags
= flags
;
3039 pDWP
->actualCount
++;
3042 WIN_ReleaseWndPtr(pWnd
);
3047 /***********************************************************************
3048 * EndDeferWindowPos16 (USER.261)
3050 BOOL16 WINAPI
EndDeferWindowPos16( HDWP16 hdwp
)
3052 return EndDeferWindowPos( hdwp
);
3056 /***********************************************************************
3057 * EndDeferWindowPos (USER32.173)
3059 BOOL WINAPI
EndDeferWindowPos( HDWP hdwp
)
3066 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
3067 if (!pDWP
) return FALSE
;
3068 for (i
= 0, winpos
= pDWP
->winPos
; i
< pDWP
->actualCount
; i
++, winpos
++)
3070 if (!(res
= SetWindowPos( winpos
->hwnd
, winpos
->hwndInsertAfter
,
3071 winpos
->x
, winpos
->y
, winpos
->cx
,
3072 winpos
->cy
, winpos
->flags
))) break;
3074 USER_HEAP_FREE( hdwp
);
3079 /***********************************************************************
3080 * TileChildWindows (USER.199)
3082 void WINAPI
TileChildWindows16( HWND16 parent
, WORD action
)
3084 FIXME("(%04x, %d): stub\n", parent
, action
);
3087 /***********************************************************************
3088 * CascageChildWindows (USER.198)
3090 void WINAPI
CascadeChildWindows16( HWND16 parent
, WORD action
)
3092 FIXME("(%04x, %d): stub\n", parent
, action
);
3095 /***********************************************************************
3096 * SetProgmanWindow [USER32.522]
3098 HRESULT WINAPI
SetProgmanWindow ( HWND hwnd
)
3100 hGlobalProgmanWindow
= hwnd
;
3101 return hGlobalProgmanWindow
;
3104 /***********************************************************************
3105 * GetProgmanWindow [USER32.289]
3107 HRESULT WINAPI
GetProgmanWindow ( )
3109 return hGlobalProgmanWindow
;
3112 /***********************************************************************
3113 * SetShellWindowEx [USER32.531]
3114 * hwndProgman = Progman[Program Manager]
3115 * |-> SHELLDLL_DefView
3116 * hwndListView = | |-> SysListView32
3117 * | | |-> tooltips_class32
3123 HRESULT WINAPI
SetShellWindowEx ( HWND hwndProgman
, HWND hwndListView
)
3125 FIXME("0x%08x 0x%08x stub\n",hwndProgman
,hwndListView
);
3126 hGlobalShellWindow
= hwndProgman
;
3127 return hGlobalShellWindow
;
3131 /***********************************************************************
3132 * SetTaskmanWindow [USER32.537]
3134 * hwnd = MSTaskSwWClass
3135 * |-> SysTabControl32
3137 HRESULT WINAPI
SetTaskmanWindow ( HWND hwnd
)
3139 hGlobalTaskmanWindow
= hwnd
;
3140 return hGlobalTaskmanWindow
;
3143 /***********************************************************************
3144 * GetTaskmanWindow [USER32.304]
3146 HRESULT WINAPI
GetTaskmanWindow ( )
3148 return hGlobalTaskmanWindow
;