2 * Window position related functions.
4 * Copyright 1993, 1994, 1995 Alexandre Julliard
5 * 1995, 1996, 1999 Alex Korobka
9 #include "wine/winuser16.h"
22 #include "nonclient.h"
23 #include "debugtools.h"
28 DEFAULT_DEBUG_CHANNEL(win
)
30 #define HAS_DLGFRAME(style,exStyle) \
31 (((exStyle) & WS_EX_DLGMODALFRAME) || \
32 (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
34 #define HAS_THICKFRAME(style) \
35 (((style) & WS_THICKFRAME) && \
36 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
38 #define SWP_AGG_NOGEOMETRYCHANGE \
39 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
40 #define SWP_AGG_NOPOSCHANGE \
41 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
42 #define SWP_AGG_STATUSFLAGS \
43 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
45 #define EMPTYPOINT(pt) ((*(LONG*)&(pt)) == -1)
47 #define PLACE_MIN 0x0001
48 #define PLACE_MAX 0x0002
49 #define PLACE_RECT 0x0004
51 #define SWP_EX_NOCOPY 0x0001
52 #define SWP_EX_PAINTSELF 0x0002
53 #define SWP_EX_NONCLIENT 0x0004
55 #define MINMAX_NOSWP 0x00010000
57 /* ----- internal variables ----- */
59 static HWND hwndPrevActive
= 0; /* Previously active window */
60 static HWND hGlobalShellWindow
=0; /*the shell*/
61 static HWND hGlobalTaskmanWindow
=0;
62 static HWND hGlobalProgmanWindow
=0;
64 static LPCSTR atomInternalPos
;
66 extern HQUEUE16 hActiveQueue
;
68 /***********************************************************************
69 * WINPOS_CreateInternalPosAtom
71 BOOL
WINPOS_CreateInternalPosAtom()
74 atomInternalPos
= (LPCSTR
)(DWORD
)GlobalAddAtomA(str
);
75 return (atomInternalPos
) ? TRUE
: FALSE
;
78 /***********************************************************************
79 * WINPOS_CheckInternalPos
81 * Called when a window is destroyed.
83 void WINPOS_CheckInternalPos( WND
* wndPtr
)
86 MESSAGEQUEUE
*pMsgQ
= 0;
87 HWND hwnd
= wndPtr
->hwndSelf
;
89 lpPos
= (LPINTERNALPOS
) GetPropA( hwnd
, atomInternalPos
);
91 /* Retrieve the message queue associated with this window */
92 pMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( wndPtr
->hmemTaskQ
);
95 WARN("\tMessage queue not found. Exiting!\n" );
99 if( hwnd
== hwndPrevActive
) hwndPrevActive
= 0;
101 if( hwnd
== PERQDATA_GetActiveWnd( pMsgQ
->pQData
) )
103 PERQDATA_SetActiveWnd( pMsgQ
->pQData
, 0 );
104 WARN("\tattempt to activate destroyed window!\n");
109 if( IsWindow(lpPos
->hwndIconTitle
) )
110 DestroyWindow( lpPos
->hwndIconTitle
);
111 HeapFree( SystemHeap
, 0, lpPos
);
114 QUEUE_Unlock( pMsgQ
);
118 /***********************************************************************
121 * Find a suitable place for an iconic window.
123 static POINT16
WINPOS_FindIconPos( WND
* wndPtr
, POINT16 pt
)
126 short x
, y
, xspacing
, yspacing
;
128 GetClientRect16( wndPtr
->parent
->hwndSelf
, &rectParent
);
129 if ((pt
.x
>= rectParent
.left
) && (pt
.x
+ GetSystemMetrics(SM_CXICON
) < rectParent
.right
) &&
130 (pt
.y
>= rectParent
.top
) && (pt
.y
+ GetSystemMetrics(SM_CYICON
) < rectParent
.bottom
))
131 return pt
; /* The icon already has a suitable position */
133 xspacing
= GetSystemMetrics(SM_CXICONSPACING
);
134 yspacing
= GetSystemMetrics(SM_CYICONSPACING
);
136 y
= rectParent
.bottom
;
139 for (x
= rectParent
.left
; x
<= rectParent
.right
-xspacing
; x
+= xspacing
)
141 /* Check if another icon already occupies this spot */
142 WND
*childPtr
= WIN_LockWndPtr(wndPtr
->parent
->child
);
145 if ((childPtr
->dwStyle
& WS_MINIMIZE
) && (childPtr
!= wndPtr
))
147 if ((childPtr
->rectWindow
.left
< x
+ xspacing
) &&
148 (childPtr
->rectWindow
.right
>= x
) &&
149 (childPtr
->rectWindow
.top
<= y
) &&
150 (childPtr
->rectWindow
.bottom
> y
- yspacing
))
151 break; /* There's a window in there */
153 WIN_UpdateWndPtr(&childPtr
,childPtr
->next
);
155 WIN_ReleaseWndPtr(childPtr
);
156 if (!childPtr
) /* No window was found, so it's OK for us */
158 pt
.x
= x
+ (xspacing
- GetSystemMetrics(SM_CXICON
)) / 2;
159 pt
.y
= y
- (yspacing
+ GetSystemMetrics(SM_CYICON
)) / 2;
168 /***********************************************************************
169 * ArrangeIconicWindows16 (USER.170)
171 UINT16 WINAPI
ArrangeIconicWindows16( HWND16 parent
)
173 return ArrangeIconicWindows(parent
);
175 /***********************************************************************
176 * ArrangeIconicWindows (USER32.7)
178 UINT WINAPI
ArrangeIconicWindows( HWND parent
)
182 INT x
, y
, xspacing
, yspacing
;
184 GetClientRect( parent
, &rectParent
);
186 y
= rectParent
.bottom
;
187 xspacing
= GetSystemMetrics(SM_CXICONSPACING
);
188 yspacing
= GetSystemMetrics(SM_CYICONSPACING
);
190 hwndChild
= GetWindow( parent
, GW_CHILD
);
193 if( IsIconic( hwndChild
) )
195 WND
*wndPtr
= WIN_FindWndPtr(hwndChild
);
197 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
199 SetWindowPos( hwndChild
, 0, x
+ (xspacing
- GetSystemMetrics(SM_CXICON
)) / 2,
200 y
- yspacing
- GetSystemMetrics(SM_CYICON
)/2, 0, 0,
201 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
202 if( IsWindow(hwndChild
) )
203 WINPOS_ShowIconTitle(wndPtr
, TRUE
);
204 WIN_ReleaseWndPtr(wndPtr
);
206 if (x
<= rectParent
.right
- xspacing
) x
+= xspacing
;
213 hwndChild
= GetWindow( hwndChild
, GW_HWNDNEXT
);
219 /***********************************************************************
220 * SwitchToThisWindow16 (USER.172)
222 void WINAPI
SwitchToThisWindow16( HWND16 hwnd
, BOOL16 restore
)
224 SwitchToThisWindow( hwnd
, restore
);
228 /***********************************************************************
229 * SwitchToThisWindow (USER32.539)
231 void WINAPI
SwitchToThisWindow( HWND hwnd
, BOOL restore
)
233 ShowWindow( hwnd
, restore
? SW_RESTORE
: SW_SHOWMINIMIZED
);
237 /***********************************************************************
238 * GetWindowRect16 (USER.32)
240 void WINAPI
GetWindowRect16( HWND16 hwnd
, LPRECT16 rect
)
242 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
245 CONV_RECT32TO16( &wndPtr
->rectWindow
, rect
);
246 if (wndPtr
->dwStyle
& WS_CHILD
)
247 MapWindowPoints16( wndPtr
->parent
->hwndSelf
, 0, (POINT16
*)rect
, 2 );
248 WIN_ReleaseWndPtr(wndPtr
);
252 /***********************************************************************
253 * GetWindowRect (USER32.308)
255 BOOL WINAPI
GetWindowRect( HWND hwnd
, LPRECT rect
)
257 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
258 if (!wndPtr
) return FALSE
;
260 *rect
= wndPtr
->rectWindow
;
261 if (wndPtr
->dwStyle
& WS_CHILD
)
262 MapWindowPoints( wndPtr
->parent
->hwndSelf
, 0, (POINT
*)rect
, 2 );
263 WIN_ReleaseWndPtr(wndPtr
);
268 /***********************************************************************
271 BOOL WINAPI
GetWindowRgn ( HWND hwnd
, HRGN hrgn
)
275 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
276 if (!wndPtr
) return (ERROR
);
278 FIXME("GetWindowRgn: doesn't really do regions\n");
280 memset (&rect
, 0, sizeof(rect
));
282 GetWindowRect ( hwnd
, &rect
);
284 FIXME("Check whether a valid region here\n");
286 SetRectRgn ( hrgn
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
288 WIN_ReleaseWndPtr(wndPtr
);
289 return (SIMPLEREGION
);
292 /***********************************************************************
295 INT WINAPI
SetWindowRgn( HWND hwnd
, HRGN hrgn
,BOOL bRedraw
)
299 FIXME("SetWindowRgn: stub\n");
303 /***********************************************************************
306 INT16 WINAPI
SetWindowRgn16( HWND16 hwnd
, HRGN16 hrgn
,BOOL16 bRedraw
)
310 FIXME("SetWindowRgn16: stub\n");
315 /***********************************************************************
316 * GetClientRect16 (USER.33)
318 void WINAPI
GetClientRect16( HWND16 hwnd
, LPRECT16 rect
)
320 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
322 rect
->left
= rect
->top
= rect
->right
= rect
->bottom
= 0;
325 rect
->right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
326 rect
->bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
328 WIN_ReleaseWndPtr(wndPtr
);
332 /***********************************************************************
333 * GetClientRect (USER.220)
335 BOOL WINAPI
GetClientRect( HWND hwnd
, LPRECT rect
)
337 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
339 rect
->left
= rect
->top
= rect
->right
= rect
->bottom
= 0;
340 if (!wndPtr
) return FALSE
;
341 rect
->right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
342 rect
->bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
344 WIN_ReleaseWndPtr(wndPtr
);
349 /*******************************************************************
350 * ClientToScreen16 (USER.28)
352 void WINAPI
ClientToScreen16( HWND16 hwnd
, LPPOINT16 lppnt
)
354 MapWindowPoints16( hwnd
, 0, lppnt
, 1 );
358 /*******************************************************************
359 * ClientToScreen (USER32.52)
361 BOOL WINAPI
ClientToScreen( HWND hwnd
, LPPOINT lppnt
)
363 MapWindowPoints( hwnd
, 0, lppnt
, 1 );
368 /*******************************************************************
369 * ScreenToClient16 (USER.29)
371 void WINAPI
ScreenToClient16( HWND16 hwnd
, LPPOINT16 lppnt
)
373 MapWindowPoints16( 0, hwnd
, lppnt
, 1 );
377 /*******************************************************************
378 * ScreenToClient (USER32.447)
380 BOOL WINAPI
ScreenToClient( HWND hwnd
, LPPOINT lppnt
)
382 MapWindowPoints( 0, hwnd
, lppnt
, 1 );
387 /***********************************************************************
388 * WINPOS_WindowFromPoint
390 * Find the window and hittest for a given point.
392 INT16
WINPOS_WindowFromPoint( WND
* wndScope
, POINT16 pt
, WND
**ppWnd
)
395 INT16 hittest
= HTERROR
;
400 wndPtr
= WIN_LockWndPtr(wndScope
->child
);
402 if( wndScope
->flags
& WIN_MANAGED
)
404 /* In managed mode we have to check wndScope first as it is also
405 * a window which received the mouse event. */
407 if( wndScope
->dwStyle
& WS_DISABLED
)
412 if( pt
.x
< wndScope
->rectClient
.left
|| pt
.x
>= wndScope
->rectClient
.right
||
413 pt
.y
< wndScope
->rectClient
.top
|| pt
.y
>= wndScope
->rectClient
.bottom
)
416 MapWindowPoints16( GetDesktopWindow16(), wndScope
->hwndSelf
, &xy
, 1 );
422 /* If point is in window, and window is visible, and it */
423 /* is enabled (or it's a top-level window), then explore */
424 /* its children. Otherwise, go to the next window. */
426 if ((wndPtr
->dwStyle
& WS_VISIBLE
) &&
427 (!(wndPtr
->dwStyle
& WS_DISABLED
) ||
428 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)) &&
429 (xy
.x
>= wndPtr
->rectWindow
.left
) &&
430 (xy
.x
< wndPtr
->rectWindow
.right
) &&
431 (xy
.y
>= wndPtr
->rectWindow
.top
) &&
432 (xy
.y
< wndPtr
->rectWindow
.bottom
))
434 *ppWnd
= wndPtr
; /* Got a suitable window */
436 /* If window is minimized or disabled, return at once */
437 if (wndPtr
->dwStyle
& WS_MINIMIZE
)
439 retvalue
= HTCAPTION
;
442 if (wndPtr
->dwStyle
& WS_DISABLED
)
448 /* If point is not in client area, ignore the children */
449 if ((xy
.x
< wndPtr
->rectClient
.left
) ||
450 (xy
.x
>= wndPtr
->rectClient
.right
) ||
451 (xy
.y
< wndPtr
->rectClient
.top
) ||
452 (xy
.y
>= wndPtr
->rectClient
.bottom
)) break;
454 xy
.x
-= wndPtr
->rectClient
.left
;
455 xy
.y
-= wndPtr
->rectClient
.top
;
456 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->child
);
460 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->next
);
465 /* If nothing found, try the scope window */
466 if (!*ppWnd
) *ppWnd
= wndScope
;
468 /* Send the WM_NCHITTEST message (only if to the same task) */
469 if ((*ppWnd
)->hmemTaskQ
== GetFastQueue16())
471 hittest
= (INT16
)SendMessage16( (*ppWnd
)->hwndSelf
, WM_NCHITTEST
,
472 0, MAKELONG( pt
.x
, pt
.y
) );
473 if (hittest
!= HTTRANSPARENT
)
475 retvalue
= hittest
; /* Found the window */
485 /* If no children found in last search, make point relative to parent */
488 xy
.x
+= (*ppWnd
)->rectClient
.left
;
489 xy
.y
+= (*ppWnd
)->rectClient
.top
;
492 /* Restart the search from the next sibling */
493 WIN_UpdateWndPtr(&wndPtr
,(*ppWnd
)->next
);
494 *ppWnd
= (*ppWnd
)->parent
;
498 WIN_ReleaseWndPtr(wndPtr
);
503 /*******************************************************************
504 * WindowFromPoint16 (USER.30)
506 HWND16 WINAPI
WindowFromPoint16( POINT16 pt
)
509 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt
, &pWnd
);
510 WIN_ReleaseDesktop();
511 return pWnd
->hwndSelf
;
515 /*******************************************************************
516 * WindowFromPoint (USER32.582)
518 HWND WINAPI
WindowFromPoint( POINT pt
)
522 CONV_POINT32TO16( &pt
, &pt16
);
523 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16
, &pWnd
);
524 WIN_ReleaseDesktop();
525 return (HWND
)pWnd
->hwndSelf
;
529 /*******************************************************************
530 * ChildWindowFromPoint16 (USER.191)
532 HWND16 WINAPI
ChildWindowFromPoint16( HWND16 hwndParent
, POINT16 pt
)
535 CONV_POINT16TO32( &pt
, &pt32
);
536 return (HWND16
)ChildWindowFromPoint( hwndParent
, pt32
);
540 /*******************************************************************
541 * ChildWindowFromPoint (USER32.49)
543 HWND WINAPI
ChildWindowFromPoint( HWND hwndParent
, POINT pt
)
545 /* pt is in the client coordinates */
547 WND
* wnd
= WIN_FindWndPtr(hwndParent
);
553 /* get client rect fast */
554 rect
.top
= rect
.left
= 0;
555 rect
.right
= wnd
->rectClient
.right
- wnd
->rectClient
.left
;
556 rect
.bottom
= wnd
->rectClient
.bottom
- wnd
->rectClient
.top
;
558 if (!PtInRect( &rect
, pt
))
563 WIN_UpdateWndPtr(&wnd
,wnd
->child
);
566 if (PtInRect( &wnd
->rectWindow
, pt
))
568 retvalue
= wnd
->hwndSelf
;
571 WIN_UpdateWndPtr(&wnd
,wnd
->next
);
573 retvalue
= hwndParent
;
575 WIN_ReleaseWndPtr(wnd
);
579 /*******************************************************************
580 * ChildWindowFromPointEx16 (USER.50)
582 HWND16 WINAPI
ChildWindowFromPointEx16( HWND16 hwndParent
, POINT16 pt
, UINT16 uFlags
)
585 CONV_POINT16TO32( &pt
, &pt32
);
586 return (HWND16
)ChildWindowFromPointEx( hwndParent
, pt32
, uFlags
);
590 /*******************************************************************
591 * ChildWindowFromPointEx32 (USER32.50)
593 HWND WINAPI
ChildWindowFromPointEx( HWND hwndParent
, POINT pt
,
596 /* pt is in the client coordinates */
598 WND
* wnd
= WIN_FindWndPtr(hwndParent
);
604 /* get client rect fast */
605 rect
.top
= rect
.left
= 0;
606 rect
.right
= wnd
->rectClient
.right
- wnd
->rectClient
.left
;
607 rect
.bottom
= wnd
->rectClient
.bottom
- wnd
->rectClient
.top
;
609 if (!PtInRect( &rect
, pt
))
614 WIN_UpdateWndPtr(&wnd
,wnd
->child
);
618 if (PtInRect( &wnd
->rectWindow
, pt
)) {
619 if ( (uFlags
& CWP_SKIPINVISIBLE
) &&
620 !(wnd
->dwStyle
& WS_VISIBLE
) );
621 else if ( (uFlags
& CWP_SKIPDISABLED
) &&
622 (wnd
->dwStyle
& WS_DISABLED
) );
623 else if ( (uFlags
& CWP_SKIPTRANSPARENT
) &&
624 (wnd
->dwExStyle
& WS_EX_TRANSPARENT
) );
627 retvalue
= wnd
->hwndSelf
;
632 WIN_UpdateWndPtr(&wnd
,wnd
->next
);
634 retvalue
= hwndParent
;
636 WIN_ReleaseWndPtr(wnd
);
641 /*******************************************************************
642 * WINPOS_GetWinOffset
644 * Calculate the offset between the origin of the two windows. Used
645 * to implement MapWindowPoints.
647 static void WINPOS_GetWinOffset( HWND hwndFrom
, HWND hwndTo
,
652 offset
->x
= offset
->y
= 0;
653 if (hwndFrom
== hwndTo
) return;
655 /* Translate source window origin to screen coords */
658 if (!(wndPtr
= WIN_FindWndPtr( hwndFrom
)))
660 ERR("bad hwndFrom = %04x\n",hwndFrom
);
663 while (wndPtr
->parent
)
665 offset
->x
+= wndPtr
->rectClient
.left
;
666 offset
->y
+= wndPtr
->rectClient
.top
;
667 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->parent
);
669 WIN_ReleaseWndPtr(wndPtr
);
672 /* Translate origin to destination window coords */
675 if (!(wndPtr
= WIN_FindWndPtr( hwndTo
)))
677 ERR("bad hwndTo = %04x\n", hwndTo
);
680 while (wndPtr
->parent
)
682 offset
->x
-= wndPtr
->rectClient
.left
;
683 offset
->y
-= wndPtr
->rectClient
.top
;
684 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->parent
);
686 WIN_ReleaseWndPtr(wndPtr
);
691 /*******************************************************************
692 * MapWindowPoints16 (USER.258)
694 void WINAPI
MapWindowPoints16( HWND16 hwndFrom
, HWND16 hwndTo
,
695 LPPOINT16 lppt
, UINT16 count
)
699 WINPOS_GetWinOffset( hwndFrom
, hwndTo
, &offset
);
709 /*******************************************************************
710 * MapWindowPoints (USER32.386)
712 INT WINAPI
MapWindowPoints( HWND hwndFrom
, HWND hwndTo
,
713 LPPOINT lppt
, UINT count
)
717 WINPOS_GetWinOffset( hwndFrom
, hwndTo
, &offset
);
724 return MAKELONG( LOWORD(offset
.x
), LOWORD(offset
.y
) );
728 /***********************************************************************
729 * IsIconic16 (USER.31)
731 BOOL16 WINAPI
IsIconic16(HWND16 hWnd
)
733 return IsIconic(hWnd
);
737 /***********************************************************************
738 * IsIconic (USER32.345)
740 BOOL WINAPI
IsIconic(HWND hWnd
)
743 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
744 if (wndPtr
== NULL
) return FALSE
;
745 retvalue
= (wndPtr
->dwStyle
& WS_MINIMIZE
) != 0;
746 WIN_ReleaseWndPtr(wndPtr
);
751 /***********************************************************************
752 * IsZoomed (USER.272)
754 BOOL16 WINAPI
IsZoomed16(HWND16 hWnd
)
756 return IsZoomed(hWnd
);
760 /***********************************************************************
761 * IsZoomed (USER.352)
763 BOOL WINAPI
IsZoomed(HWND hWnd
)
766 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
767 if (wndPtr
== NULL
) return FALSE
;
768 retvalue
= (wndPtr
->dwStyle
& WS_MAXIMIZE
) != 0;
769 WIN_ReleaseWndPtr(wndPtr
);
774 /*******************************************************************
775 * GetActiveWindow (USER.60)
777 HWND16 WINAPI
GetActiveWindow16(void)
779 return (HWND16
)GetActiveWindow();
782 /*******************************************************************
783 * GetActiveWindow (USER32.205)
785 HWND WINAPI
GetActiveWindow(void)
787 MESSAGEQUEUE
*pCurMsgQ
= 0;
790 /* Get the messageQ for the current thread */
791 if (!(pCurMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( GetFastQueue16() )))
793 WARN("\tCurrent message queue not found. Exiting!\n" );
797 /* Return the current active window from the perQ data of the current message Q */
798 hwndActive
= PERQDATA_GetActiveWnd( pCurMsgQ
->pQData
);
800 QUEUE_Unlock( pCurMsgQ
);
805 /*******************************************************************
808 static BOOL
WINPOS_CanActivate(WND
* pWnd
)
810 if( pWnd
&& !(pWnd
->dwStyle
& (WS_DISABLED
| WS_CHILD
)) ) return TRUE
;
815 /*******************************************************************
816 * SetActiveWindow16 (USER.59)
818 HWND16 WINAPI
SetActiveWindow16( HWND16 hwnd
)
820 return SetActiveWindow(hwnd
);
824 /*******************************************************************
825 * SetActiveWindow (USER32.463)
827 HWND WINAPI
SetActiveWindow( HWND hwnd
)
830 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
831 MESSAGEQUEUE
*pMsgQ
= 0, *pCurMsgQ
= 0;
833 if ( !WINPOS_CanActivate(wndPtr
) )
839 /* Get the messageQ for the current thread */
840 if (!(pCurMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( GetFastQueue16() )))
842 WARN("\tCurrent message queue not found. Exiting!\n" );
846 /* Retrieve the message queue associated with this window */
847 pMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( wndPtr
->hmemTaskQ
);
850 WARN("\tWindow message queue not found. Exiting!\n" );
854 /* Make sure that the window is associated with the calling threads
855 * message queue. It must share the same perQ data.
858 if ( pCurMsgQ
->pQData
!= pMsgQ
->pQData
)
861 /* Save current active window */
862 prev
= PERQDATA_GetActiveWnd( pMsgQ
->pQData
);
864 WINPOS_SetActiveWindow( hwnd
, 0, 0 );
867 /* Unlock the queues before returning */
869 QUEUE_Unlock( pMsgQ
);
871 QUEUE_Unlock( pCurMsgQ
);
874 WIN_ReleaseWndPtr(wndPtr
);
879 /*******************************************************************
880 * GetForegroundWindow16 (USER.608)
882 HWND16 WINAPI
GetForegroundWindow16(void)
884 return (HWND16
)GetForegroundWindow();
888 /*******************************************************************
889 * SetForegroundWindow16 (USER.609)
891 BOOL16 WINAPI
SetForegroundWindow16( HWND16 hwnd
)
893 return SetForegroundWindow( hwnd
);
897 /*******************************************************************
898 * GetForegroundWindow (USER32.241)
900 HWND WINAPI
GetForegroundWindow(void)
904 /* Get the foreground window (active window of hActiveQueue) */
907 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
909 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
911 QUEUE_Unlock( pActiveQueue
);
917 /*******************************************************************
918 * SetForegroundWindow (USER32.482)
920 BOOL WINAPI
SetForegroundWindow( HWND hwnd
)
922 return WINPOS_ChangeActiveWindow( hwnd
, FALSE
);
926 /*******************************************************************
927 * GetShellWindow16 (USER.600)
929 HWND16 WINAPI
GetShellWindow16(void)
931 return GetShellWindow();
934 /*******************************************************************
935 * SetShellWindow (USER32.504)
937 HWND WINAPI
SetShellWindow(HWND hwndshell
)
938 { WARN("(hWnd=%08x) semi stub\n",hwndshell
);
940 hGlobalShellWindow
= hwndshell
;
941 return hGlobalShellWindow
;
945 /*******************************************************************
946 * GetShellWindow (USER32.287)
948 HWND WINAPI
GetShellWindow(void)
949 { WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow
);
951 return hGlobalShellWindow
;
955 /***********************************************************************
956 * BringWindowToTop16 (USER.45)
958 BOOL16 WINAPI
BringWindowToTop16( HWND16 hwnd
)
960 return BringWindowToTop(hwnd
);
964 /***********************************************************************
965 * BringWindowToTop (USER32.11)
967 BOOL WINAPI
BringWindowToTop( HWND hwnd
)
969 return SetWindowPos( hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
);
973 /***********************************************************************
974 * MoveWindow16 (USER.56)
976 BOOL16 WINAPI
MoveWindow16( HWND16 hwnd
, INT16 x
, INT16 y
, INT16 cx
, INT16 cy
,
979 return MoveWindow(hwnd
,x
,y
,cx
,cy
,repaint
);
983 /***********************************************************************
984 * MoveWindow (USER32.399)
986 BOOL WINAPI
MoveWindow( HWND hwnd
, INT x
, INT y
, INT cx
, INT cy
,
989 int flags
= SWP_NOZORDER
| SWP_NOACTIVATE
;
990 if (!repaint
) flags
|= SWP_NOREDRAW
;
991 TRACE("%04x %d,%d %dx%d %d\n",
992 hwnd
, x
, y
, cx
, cy
, repaint
);
993 return SetWindowPos( hwnd
, 0, x
, y
, cx
, cy
, flags
);
996 /***********************************************************************
997 * WINPOS_InitInternalPos
999 static LPINTERNALPOS
WINPOS_InitInternalPos( WND
* wnd
, POINT pt
,
1000 LPRECT restoreRect
)
1002 LPINTERNALPOS lpPos
= (LPINTERNALPOS
) GetPropA( wnd
->hwndSelf
,
1006 /* this happens when the window is minimized/maximized
1007 * for the first time (rectWindow is not adjusted yet) */
1009 lpPos
= HeapAlloc( SystemHeap
, 0, sizeof(INTERNALPOS
) );
1010 if( !lpPos
) return NULL
;
1012 SetPropA( wnd
->hwndSelf
, atomInternalPos
, (HANDLE
)lpPos
);
1013 lpPos
->hwndIconTitle
= 0; /* defer until needs to be shown */
1014 CONV_RECT32TO16( &wnd
->rectWindow
, &lpPos
->rectNormal
);
1015 *(UINT
*)&lpPos
->ptIconPos
= *(UINT
*)&lpPos
->ptMaxPos
= 0xFFFFFFFF;
1018 if( wnd
->dwStyle
& WS_MINIMIZE
)
1019 CONV_POINT32TO16( &pt
, &lpPos
->ptIconPos
);
1020 else if( wnd
->dwStyle
& WS_MAXIMIZE
)
1021 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1022 else if( restoreRect
)
1023 CONV_RECT32TO16( restoreRect
, &lpPos
->rectNormal
);
1028 /***********************************************************************
1029 * WINPOS_RedrawIconTitle
1031 BOOL
WINPOS_RedrawIconTitle( HWND hWnd
)
1033 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)GetPropA( hWnd
, atomInternalPos
);
1036 if( lpPos
->hwndIconTitle
)
1038 SendMessageA( lpPos
->hwndIconTitle
, WM_SHOWWINDOW
, TRUE
, 0);
1039 InvalidateRect( lpPos
->hwndIconTitle
, NULL
, TRUE
);
1046 /***********************************************************************
1047 * WINPOS_ShowIconTitle
1049 BOOL
WINPOS_ShowIconTitle( WND
* pWnd
, BOOL bShow
)
1051 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)GetPropA( pWnd
->hwndSelf
, atomInternalPos
);
1053 if( lpPos
&& !(pWnd
->flags
& WIN_MANAGED
))
1055 HWND16 hWnd
= lpPos
->hwndIconTitle
;
1057 TRACE("0x%04x %i\n", pWnd
->hwndSelf
, (bShow
!= 0) );
1060 lpPos
->hwndIconTitle
= hWnd
= ICONTITLE_Create( pWnd
);
1063 if( ( pWnd
= WIN_FindWndPtr(hWnd
) ) != NULL
)
1065 if( !(pWnd
->dwStyle
& WS_VISIBLE
) )
1067 SendMessageA( hWnd
, WM_SHOWWINDOW
, TRUE
, 0 );
1068 SetWindowPos( hWnd
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
1069 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_SHOWWINDOW
);
1071 WIN_ReleaseWndPtr(pWnd
);
1074 else ShowWindow( hWnd
, SW_HIDE
);
1079 /*******************************************************************
1080 * WINPOS_GetMinMaxInfo
1082 * Get the minimized and maximized information for a window.
1084 void WINPOS_GetMinMaxInfo( WND
*wndPtr
, POINT
*maxSize
, POINT
*maxPos
,
1085 POINT
*minTrack
, POINT
*maxTrack
)
1087 LPINTERNALPOS lpPos
;
1091 /* Compute default values */
1093 MinMax
.ptMaxSize
.x
= GetSystemMetrics(SM_CXSCREEN
);
1094 MinMax
.ptMaxSize
.y
= GetSystemMetrics(SM_CYSCREEN
);
1095 MinMax
.ptMinTrackSize
.x
= GetSystemMetrics(SM_CXMINTRACK
);
1096 MinMax
.ptMinTrackSize
.y
= GetSystemMetrics(SM_CYMINTRACK
);
1097 MinMax
.ptMaxTrackSize
.x
= GetSystemMetrics(SM_CXSCREEN
);
1098 MinMax
.ptMaxTrackSize
.y
= GetSystemMetrics(SM_CYSCREEN
);
1100 if (wndPtr
->flags
& WIN_MANAGED
) xinc
= yinc
= 0;
1101 else if (HAS_DLGFRAME( wndPtr
->dwStyle
, wndPtr
->dwExStyle
))
1103 xinc
= GetSystemMetrics(SM_CXDLGFRAME
);
1104 yinc
= GetSystemMetrics(SM_CYDLGFRAME
);
1109 if (HAS_THICKFRAME(wndPtr
->dwStyle
))
1111 xinc
+= GetSystemMetrics(SM_CXFRAME
);
1112 yinc
+= GetSystemMetrics(SM_CYFRAME
);
1114 if (wndPtr
->dwStyle
& WS_BORDER
)
1116 xinc
+= GetSystemMetrics(SM_CXBORDER
);
1117 yinc
+= GetSystemMetrics(SM_CYBORDER
);
1120 MinMax
.ptMaxSize
.x
+= 2 * xinc
;
1121 MinMax
.ptMaxSize
.y
+= 2 * yinc
;
1123 lpPos
= (LPINTERNALPOS
)GetPropA( wndPtr
->hwndSelf
, atomInternalPos
);
1124 if( lpPos
&& !EMPTYPOINT(lpPos
->ptMaxPos
) )
1125 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &MinMax
.ptMaxPosition
);
1128 MinMax
.ptMaxPosition
.x
= -xinc
;
1129 MinMax
.ptMaxPosition
.y
= -yinc
;
1132 SendMessageA( wndPtr
->hwndSelf
, WM_GETMINMAXINFO
, 0, (LPARAM
)&MinMax
);
1134 /* Some sanity checks */
1136 TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1137 MinMax
.ptMaxSize
.x
, MinMax
.ptMaxSize
.y
,
1138 MinMax
.ptMaxPosition
.x
, MinMax
.ptMaxPosition
.y
,
1139 MinMax
.ptMaxTrackSize
.x
, MinMax
.ptMaxTrackSize
.y
,
1140 MinMax
.ptMinTrackSize
.x
, MinMax
.ptMinTrackSize
.y
);
1141 MinMax
.ptMaxTrackSize
.x
= MAX( MinMax
.ptMaxTrackSize
.x
,
1142 MinMax
.ptMinTrackSize
.x
);
1143 MinMax
.ptMaxTrackSize
.y
= MAX( MinMax
.ptMaxTrackSize
.y
,
1144 MinMax
.ptMinTrackSize
.y
);
1146 if (maxSize
) *maxSize
= MinMax
.ptMaxSize
;
1147 if (maxPos
) *maxPos
= MinMax
.ptMaxPosition
;
1148 if (minTrack
) *minTrack
= MinMax
.ptMinTrackSize
;
1149 if (maxTrack
) *maxTrack
= MinMax
.ptMaxTrackSize
;
1152 /***********************************************************************
1153 * WINPOS_MinMaximize
1155 * Fill in lpRect and return additional flags to be used with SetWindowPos().
1156 * This function assumes that 'cmd' is different from the current window
1159 UINT
WINPOS_MinMaximize( WND
* wndPtr
, UINT16 cmd
, LPRECT16 lpRect
)
1163 LPINTERNALPOS lpPos
;
1165 TRACE("0x%04x %u\n", wndPtr
->hwndSelf
, cmd
);
1167 size
.x
= wndPtr
->rectWindow
.left
; size
.y
= wndPtr
->rectWindow
.top
;
1168 lpPos
= WINPOS_InitInternalPos( wndPtr
, size
, &wndPtr
->rectWindow
);
1170 if (lpPos
&& !HOOK_CallHooks16(WH_CBT
, HCBT_MINMAX
, wndPtr
->hwndSelf
, cmd
))
1172 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1174 if( !SendMessageA( wndPtr
->hwndSelf
, WM_QUERYOPEN
, 0, 0L ) )
1175 return (SWP_NOSIZE
| SWP_NOMOVE
);
1176 swpFlags
|= SWP_NOCOPYBITS
;
1181 if( wndPtr
->dwStyle
& WS_MAXIMIZE
)
1183 wndPtr
->flags
|= WIN_RESTORE_MAX
;
1184 wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
1187 wndPtr
->flags
&= ~WIN_RESTORE_MAX
;
1188 wndPtr
->dwStyle
|= WS_MINIMIZE
;
1190 if( wndPtr
->flags
& WIN_NATIVE
)
1191 if( wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, TRUE
) )
1192 swpFlags
|= MINMAX_NOSWP
;
1194 lpPos
->ptIconPos
= WINPOS_FindIconPos( wndPtr
, lpPos
->ptIconPos
);
1196 SetRect16( lpRect
, lpPos
->ptIconPos
.x
, lpPos
->ptIconPos
.y
,
1197 GetSystemMetrics(SM_CXICON
), GetSystemMetrics(SM_CYICON
) );
1198 swpFlags
|= SWP_NOCOPYBITS
;
1202 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &pt
);
1203 WINPOS_GetMinMaxInfo( wndPtr
, &size
, &pt
, NULL
, NULL
);
1204 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1206 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1208 if( wndPtr
->flags
& WIN_NATIVE
)
1209 if( wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, FALSE
) )
1210 swpFlags
|= MINMAX_NOSWP
;
1212 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
1213 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
1215 wndPtr
->dwStyle
|= WS_MAXIMIZE
;
1217 SetRect16( lpRect
, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
,
1222 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1224 if( wndPtr
->flags
& WIN_NATIVE
)
1225 if( wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, FALSE
) )
1226 swpFlags
|= MINMAX_NOSWP
;
1228 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
1229 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
1231 if( wndPtr
->flags
& WIN_RESTORE_MAX
)
1233 /* Restore to maximized position */
1234 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &pt
);
1235 WINPOS_GetMinMaxInfo( wndPtr
, &size
, &pt
, NULL
, NULL
);
1236 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1237 wndPtr
->dwStyle
|= WS_MAXIMIZE
;
1238 SetRect16( lpRect
, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
, size
.x
, size
.y
);
1243 if( !(wndPtr
->dwStyle
& WS_MAXIMIZE
) ) return (UINT16
)(-1);
1244 else wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
1246 /* Restore to normal position */
1248 *lpRect
= lpPos
->rectNormal
;
1249 lpRect
->right
-= lpRect
->left
;
1250 lpRect
->bottom
-= lpRect
->top
;
1254 } else swpFlags
|= SWP_NOSIZE
| SWP_NOMOVE
;
1258 /***********************************************************************
1259 * ShowWindowAsync (USER32.535)
1261 * doesn't wait; returns immediately.
1262 * used by threads to toggle windows in other (possibly hanging) threads
1264 BOOL WINAPI
ShowWindowAsync( HWND hwnd
, INT cmd
)
1266 /* FIXME: does ShowWindow() return immediately ? */
1267 return ShowWindow(hwnd
, cmd
);
1271 /***********************************************************************
1272 * ShowWindow16 (USER.42)
1274 BOOL16 WINAPI
ShowWindow16( HWND16 hwnd
, INT16 cmd
)
1276 return ShowWindow(hwnd
,cmd
);
1280 /***********************************************************************
1281 * ShowWindow (USER32.534)
1283 BOOL WINAPI
ShowWindow( HWND hwnd
, INT cmd
)
1285 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
1286 BOOL wasVisible
, showFlag
;
1287 RECT16 newPos
= {0, 0, 0, 0};
1290 if (!wndPtr
) return FALSE
;
1292 TRACE("hwnd=%04x, cmd=%d\n", hwnd
, cmd
);
1294 wasVisible
= (wndPtr
->dwStyle
& WS_VISIBLE
) != 0;
1299 if (!wasVisible
) goto END
;;
1300 swp
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
|
1301 SWP_NOACTIVATE
| SWP_NOZORDER
;
1304 case SW_SHOWMINNOACTIVE
:
1305 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1307 case SW_SHOWMINIMIZED
:
1308 swp
|= SWP_SHOWWINDOW
;
1311 swp
|= SWP_FRAMECHANGED
;
1312 if( !(wndPtr
->dwStyle
& WS_MINIMIZE
) )
1313 swp
|= WINPOS_MinMaximize( wndPtr
, SW_MINIMIZE
, &newPos
);
1314 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1317 case SW_SHOWMAXIMIZED
: /* same as SW_MAXIMIZE */
1318 swp
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
1319 if( !(wndPtr
->dwStyle
& WS_MAXIMIZE
) )
1320 swp
|= WINPOS_MinMaximize( wndPtr
, SW_MAXIMIZE
, &newPos
);
1321 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1325 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1328 swp
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
1331 * ShowWindow has a little peculiar behavior that if the
1332 * window is already the topmost window, it will not
1335 if (GetTopWindow((HWND
)0)==hwnd
&& (wasVisible
|| GetActiveWindow() == hwnd
))
1336 swp
|= SWP_NOACTIVATE
;
1340 case SW_SHOWNOACTIVATE
:
1341 swp
|= SWP_NOZORDER
;
1342 if (GetActiveWindow()) swp
|= SWP_NOACTIVATE
;
1344 case SW_SHOWNORMAL
: /* same as SW_NORMAL: */
1345 case SW_SHOWDEFAULT
: /* FIXME: should have its own handler */
1347 swp
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
1349 if( wndPtr
->dwStyle
& (WS_MINIMIZE
| WS_MAXIMIZE
) )
1350 swp
|= WINPOS_MinMaximize( wndPtr
, SW_RESTORE
, &newPos
);
1351 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1355 showFlag
= (cmd
!= SW_HIDE
);
1356 if (showFlag
!= wasVisible
)
1358 SendMessageA( hwnd
, WM_SHOWWINDOW
, showFlag
, 0 );
1359 if (!IsWindow( hwnd
)) goto END
;
1362 if ((wndPtr
->dwStyle
& WS_CHILD
) &&
1363 !IsWindowVisible( wndPtr
->parent
->hwndSelf
) &&
1364 (swp
& (SWP_NOSIZE
| SWP_NOMOVE
)) == (SWP_NOSIZE
| SWP_NOMOVE
) )
1366 /* Don't call SetWindowPos() on invisible child windows */
1367 if (cmd
== SW_HIDE
) wndPtr
->dwStyle
&= ~WS_VISIBLE
;
1368 else wndPtr
->dwStyle
|= WS_VISIBLE
;
1372 /* We can't activate a child window */
1373 if ((wndPtr
->dwStyle
& WS_CHILD
) &&
1374 !(wndPtr
->dwExStyle
& WS_EX_MDICHILD
))
1375 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1376 if (!(swp
& MINMAX_NOSWP
))
1378 SetWindowPos( hwnd
, HWND_TOP
, newPos
.left
, newPos
.top
,
1379 newPos
.right
, newPos
.bottom
, LOWORD(swp
) );
1382 /* FIXME: This will cause the window to be activated irrespective
1383 * of whether it is owned by the same thread. Has to be done
1387 if (hwnd
== GetActiveWindow())
1388 WINPOS_ActivateOtherWindow(wndPtr
);
1390 /* Revert focus to parent */
1391 if (hwnd
== GetFocus() || IsChild(hwnd
, GetFocus()))
1392 SetFocus( GetParent(hwnd
) );
1395 if (!IsWindow( hwnd
)) goto END
;
1396 else if( wndPtr
->dwStyle
& WS_MINIMIZE
) WINPOS_ShowIconTitle( wndPtr
, TRUE
);
1399 if (wndPtr
->flags
& WIN_NEED_SIZE
)
1401 /* should happen only in CreateWindowEx() */
1402 int wParam
= SIZE_RESTORED
;
1404 wndPtr
->flags
&= ~WIN_NEED_SIZE
;
1405 if (wndPtr
->dwStyle
& WS_MAXIMIZE
) wParam
= SIZE_MAXIMIZED
;
1406 else if (wndPtr
->dwStyle
& WS_MINIMIZE
) wParam
= SIZE_MINIMIZED
;
1407 SendMessageA( hwnd
, WM_SIZE
, wParam
,
1408 MAKELONG(wndPtr
->rectClient
.right
-wndPtr
->rectClient
.left
,
1409 wndPtr
->rectClient
.bottom
-wndPtr
->rectClient
.top
));
1410 SendMessageA( hwnd
, WM_MOVE
, 0,
1411 MAKELONG(wndPtr
->rectClient
.left
, wndPtr
->rectClient
.top
) );
1415 WIN_ReleaseWndPtr(wndPtr
);
1420 /***********************************************************************
1421 * GetInternalWindowPos16 (USER.460)
1423 UINT16 WINAPI
GetInternalWindowPos16( HWND16 hwnd
, LPRECT16 rectWnd
,
1426 WINDOWPLACEMENT16 wndpl
;
1427 if (GetWindowPlacement16( hwnd
, &wndpl
))
1429 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
1430 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
1431 return wndpl
.showCmd
;
1437 /***********************************************************************
1438 * GetInternalWindowPos (USER32.245)
1440 UINT WINAPI
GetInternalWindowPos( HWND hwnd
, LPRECT rectWnd
,
1443 WINDOWPLACEMENT wndpl
;
1444 if (GetWindowPlacement( hwnd
, &wndpl
))
1446 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
1447 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
1448 return wndpl
.showCmd
;
1453 /***********************************************************************
1454 * GetWindowPlacement16 (USER.370)
1456 BOOL16 WINAPI
GetWindowPlacement16( HWND16 hwnd
, WINDOWPLACEMENT16
*wndpl
)
1458 WND
*pWnd
= WIN_FindWndPtr( hwnd
);
1459 LPINTERNALPOS lpPos
;
1461 if(!pWnd
) return FALSE
;
1463 lpPos
= (LPINTERNALPOS
)WINPOS_InitInternalPos( pWnd
,
1464 *(LPPOINT
)&pWnd
->rectWindow
.left
, &pWnd
->rectWindow
);
1465 wndpl
->length
= sizeof(*wndpl
);
1466 if( pWnd
->dwStyle
& WS_MINIMIZE
)
1467 wndpl
->showCmd
= SW_SHOWMINIMIZED
;
1469 wndpl
->showCmd
= ( pWnd
->dwStyle
& WS_MAXIMIZE
)
1470 ? SW_SHOWMAXIMIZED
: SW_SHOWNORMAL
;
1471 if( pWnd
->flags
& WIN_RESTORE_MAX
)
1472 wndpl
->flags
= WPF_RESTORETOMAXIMIZED
;
1475 wndpl
->ptMinPosition
= lpPos
->ptIconPos
;
1476 wndpl
->ptMaxPosition
= lpPos
->ptMaxPos
;
1477 wndpl
->rcNormalPosition
= lpPos
->rectNormal
;
1479 WIN_ReleaseWndPtr(pWnd
);
1484 /***********************************************************************
1485 * GetWindowPlacement (USER32.307)
1488 * Fails if wndpl->length of Win95 (!) apps is invalid.
1490 BOOL WINAPI
GetWindowPlacement( HWND hwnd
, WINDOWPLACEMENT
*pwpl32
)
1494 WINDOWPLACEMENT16 wpl
;
1495 wpl
.length
= sizeof(wpl
);
1496 if( GetWindowPlacement16( hwnd
, &wpl
) )
1498 pwpl32
->length
= sizeof(*pwpl32
);
1499 pwpl32
->flags
= wpl
.flags
;
1500 pwpl32
->showCmd
= wpl
.showCmd
;
1501 CONV_POINT16TO32( &wpl
.ptMinPosition
, &pwpl32
->ptMinPosition
);
1502 CONV_POINT16TO32( &wpl
.ptMaxPosition
, &pwpl32
->ptMaxPosition
);
1503 CONV_RECT16TO32( &wpl
.rcNormalPosition
, &pwpl32
->rcNormalPosition
);
1511 /***********************************************************************
1512 * WINPOS_SetPlacement
1514 static BOOL
WINPOS_SetPlacement( HWND hwnd
, const WINDOWPLACEMENT16
*wndpl
,
1517 WND
*pWnd
= WIN_FindWndPtr( hwnd
);
1520 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)WINPOS_InitInternalPos( pWnd
,
1521 *(LPPOINT
)&pWnd
->rectWindow
.left
, &pWnd
->rectWindow
);
1523 if( flags
& PLACE_MIN
) lpPos
->ptIconPos
= wndpl
->ptMinPosition
;
1524 if( flags
& PLACE_MAX
) lpPos
->ptMaxPos
= wndpl
->ptMaxPosition
;
1525 if( flags
& PLACE_RECT
) lpPos
->rectNormal
= wndpl
->rcNormalPosition
;
1527 if( pWnd
->dwStyle
& WS_MINIMIZE
)
1529 WINPOS_ShowIconTitle( pWnd
, FALSE
);
1530 if( wndpl
->flags
& WPF_SETMINPOSITION
&& !EMPTYPOINT(lpPos
->ptIconPos
))
1531 SetWindowPos( hwnd
, 0, lpPos
->ptIconPos
.x
, lpPos
->ptIconPos
.y
,
1532 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1534 else if( pWnd
->dwStyle
& WS_MAXIMIZE
)
1536 if( !EMPTYPOINT(lpPos
->ptMaxPos
) )
1537 SetWindowPos( hwnd
, 0, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
,
1538 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1540 else if( flags
& PLACE_RECT
)
1541 SetWindowPos( hwnd
, 0, lpPos
->rectNormal
.left
, lpPos
->rectNormal
.top
,
1542 lpPos
->rectNormal
.right
- lpPos
->rectNormal
.left
,
1543 lpPos
->rectNormal
.bottom
- lpPos
->rectNormal
.top
,
1544 SWP_NOZORDER
| SWP_NOACTIVATE
);
1546 ShowWindow( hwnd
, wndpl
->showCmd
);
1547 if( IsWindow(hwnd
) && pWnd
->dwStyle
& WS_MINIMIZE
)
1549 if( pWnd
->dwStyle
& WS_VISIBLE
) WINPOS_ShowIconTitle( pWnd
, TRUE
);
1551 /* SDK: ...valid only the next time... */
1552 if( wndpl
->flags
& WPF_RESTORETOMAXIMIZED
) pWnd
->flags
|= WIN_RESTORE_MAX
;
1554 WIN_ReleaseWndPtr(pWnd
);
1561 /***********************************************************************
1562 * SetWindowPlacement16 (USER.371)
1564 BOOL16 WINAPI
SetWindowPlacement16(HWND16 hwnd
, const WINDOWPLACEMENT16
*wndpl
)
1566 return WINPOS_SetPlacement( hwnd
, wndpl
,
1567 PLACE_MIN
| PLACE_MAX
| PLACE_RECT
);
1570 /***********************************************************************
1571 * SetWindowPlacement (USER32.519)
1574 * Fails if wndpl->length of Win95 (!) apps is invalid.
1576 BOOL WINAPI
SetWindowPlacement( HWND hwnd
, const WINDOWPLACEMENT
*pwpl32
)
1580 WINDOWPLACEMENT16 wpl
;
1582 wpl
.length
= sizeof(WINDOWPLACEMENT16
);
1583 wpl
.flags
= pwpl32
->flags
;
1584 wpl
.showCmd
= pwpl32
->showCmd
;
1585 wpl
.ptMinPosition
.x
= pwpl32
->ptMinPosition
.x
;
1586 wpl
.ptMinPosition
.y
= pwpl32
->ptMinPosition
.y
;
1587 wpl
.ptMaxPosition
.x
= pwpl32
->ptMaxPosition
.x
;
1588 wpl
.ptMaxPosition
.y
= pwpl32
->ptMaxPosition
.y
;
1589 wpl
.rcNormalPosition
.left
= pwpl32
->rcNormalPosition
.left
;
1590 wpl
.rcNormalPosition
.top
= pwpl32
->rcNormalPosition
.top
;
1591 wpl
.rcNormalPosition
.right
= pwpl32
->rcNormalPosition
.right
;
1592 wpl
.rcNormalPosition
.bottom
= pwpl32
->rcNormalPosition
.bottom
;
1594 return WINPOS_SetPlacement( hwnd
, &wpl
, PLACE_MIN
| PLACE_MAX
| PLACE_RECT
);
1600 /***********************************************************************
1601 * SetInternalWindowPos16 (USER.461)
1603 void WINAPI
SetInternalWindowPos16( HWND16 hwnd
, UINT16 showCmd
,
1604 LPRECT16 rect
, LPPOINT16 pt
)
1606 if( IsWindow16(hwnd
) )
1608 WINDOWPLACEMENT16 wndpl
;
1611 wndpl
.length
= sizeof(wndpl
);
1612 wndpl
.showCmd
= showCmd
;
1613 wndpl
.flags
= flags
= 0;
1618 wndpl
.flags
|= WPF_SETMINPOSITION
;
1619 wndpl
.ptMinPosition
= *pt
;
1623 flags
|= PLACE_RECT
;
1624 wndpl
.rcNormalPosition
= *rect
;
1626 WINPOS_SetPlacement( hwnd
, &wndpl
, flags
);
1631 /***********************************************************************
1632 * SetInternalWindowPos (USER32.483)
1634 void WINAPI
SetInternalWindowPos( HWND hwnd
, UINT showCmd
,
1635 LPRECT rect
, LPPOINT pt
)
1637 if( IsWindow(hwnd
) )
1639 WINDOWPLACEMENT16 wndpl
;
1642 wndpl
.length
= sizeof(wndpl
);
1643 wndpl
.showCmd
= showCmd
;
1644 wndpl
.flags
= flags
= 0;
1649 wndpl
.flags
|= WPF_SETMINPOSITION
;
1650 CONV_POINT32TO16( pt
, &wndpl
.ptMinPosition
);
1654 flags
|= PLACE_RECT
;
1655 CONV_RECT32TO16( rect
, &wndpl
.rcNormalPosition
);
1657 WINPOS_SetPlacement( hwnd
, &wndpl
, flags
);
1661 /*******************************************************************
1662 * WINPOS_SetActiveWindow
1664 * SetActiveWindow() back-end. This is the only function that
1665 * can assign active status to a window. It must be called only
1666 * for the top level windows.
1668 BOOL
WINPOS_SetActiveWindow( HWND hWnd
, BOOL fMouse
, BOOL fChangeFocus
)
1670 CBTACTIVATESTRUCT16
* cbtStruct
;
1671 WND
* wndPtr
=0, *wndTemp
;
1672 HQUEUE16 hOldActiveQueue
, hNewActiveQueue
;
1673 MESSAGEQUEUE
*pOldActiveQueue
= 0, *pNewActiveQueue
= 0;
1675 HWND hwndActive
= 0;
1678 TRACE("(%04x, %d, %d)\n", hWnd
, fMouse
, fChangeFocus
);
1680 /* Get current active window from the active queue */
1683 pOldActiveQueue
= QUEUE_Lock( hActiveQueue
);
1684 if ( pOldActiveQueue
)
1685 hwndActive
= PERQDATA_GetActiveWnd( pOldActiveQueue
->pQData
);
1688 /* paranoid checks */
1689 if( hWnd
== GetDesktopWindow() || (bRet
= (hWnd
== hwndActive
)) )
1692 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1695 wndPtr
= WIN_FindWndPtr(hWnd
);
1696 hOldActiveQueue
= hActiveQueue
;
1698 if( (wndTemp
= WIN_FindWndPtr(hwndActive
)) )
1700 wIconized
= HIWORD(wndTemp
->dwStyle
& WS_MINIMIZE
);
1701 WIN_ReleaseWndPtr(wndTemp
);
1704 TRACE("no current active window.\n");
1706 /* call CBT hook chain */
1707 if ((cbtStruct
= SEGPTR_NEW(CBTACTIVATESTRUCT16
)))
1709 cbtStruct
->fMouse
= fMouse
;
1710 cbtStruct
->hWndActive
= hwndActive
;
1711 bRet
= (BOOL
)HOOK_CallHooks16( WH_CBT
, HCBT_ACTIVATE
, (WPARAM16
)hWnd
,
1712 (LPARAM
)SEGPTR_GET(cbtStruct
) );
1713 SEGPTR_FREE(cbtStruct
);
1714 if (bRet
) goto CLEANUP_END
;
1717 /* set prev active wnd to current active wnd and send notification */
1718 if ((hwndPrevActive
= hwndActive
) && IsWindow(hwndPrevActive
))
1720 MESSAGEQUEUE
*pTempActiveQueue
= 0;
1722 if (!SendMessageA( hwndPrevActive
, WM_NCACTIVATE
, FALSE
, 0 ))
1724 if (GetSysModalWindow16() != hWnd
)
1726 /* disregard refusal if hWnd is sysmodal */
1729 SendMessageA( hwndPrevActive
, WM_ACTIVATE
,
1730 MAKEWPARAM( WA_INACTIVE
, wIconized
),
1733 /* check if something happened during message processing
1734 * (global active queue may have changed)
1736 pTempActiveQueue
= QUEUE_Lock( hActiveQueue
);
1737 if(!pTempActiveQueue
)
1740 hwndActive
= PERQDATA_GetActiveWnd( pTempActiveQueue
->pQData
);
1741 QUEUE_Unlock( pTempActiveQueue
);
1742 if( hwndPrevActive
!= hwndActive
)
1746 /* Set new active window in the message queue */
1750 pNewActiveQueue
= QUEUE_Lock( wndPtr
->hmemTaskQ
);
1751 if ( pNewActiveQueue
)
1752 PERQDATA_SetActiveWnd( pNewActiveQueue
->pQData
, hwndActive
);
1754 else /* have to do this or MDI frame activation goes to hell */
1755 if( pOldActiveQueue
)
1756 PERQDATA_SetActiveWnd( pOldActiveQueue
->pQData
, 0 );
1758 /* send palette messages */
1759 if (hWnd
&& SendMessage16( hWnd
, WM_QUERYNEWPALETTE
, 0, 0L))
1760 SendMessage16((HWND16
)-1, WM_PALETTEISCHANGING
, (WPARAM16
)hWnd
, 0L );
1762 /* if prev wnd is minimized redraw icon title */
1763 if( IsIconic( hwndPrevActive
) ) WINPOS_RedrawIconTitle(hwndPrevActive
);
1765 /* managed windows will get ConfigureNotify event */
1766 if (wndPtr
&& !(wndPtr
->dwStyle
& WS_CHILD
) && !(wndPtr
->flags
& WIN_MANAGED
))
1768 /* check Z-order and bring hWnd to the top */
1769 for (wndTemp
= WIN_LockWndPtr(WIN_GetDesktop()->child
); wndTemp
; WIN_UpdateWndPtr(&wndTemp
,wndTemp
->next
))
1771 if (wndTemp
->dwStyle
& WS_VISIBLE
) break;
1773 WIN_ReleaseDesktop();
1774 WIN_ReleaseWndPtr(wndTemp
);
1776 if( wndTemp
!= wndPtr
)
1777 SetWindowPos(hWnd
, HWND_TOP
, 0,0,0,0,
1778 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
1779 if (!IsWindow(hWnd
))
1783 /* Get a handle to the new active queue */
1784 hNewActiveQueue
= wndPtr
? wndPtr
->hmemTaskQ
: 0;
1786 /* send WM_ACTIVATEAPP if necessary */
1787 if (hOldActiveQueue
!= hNewActiveQueue
)
1789 WND
**list
, **ppWnd
;
1790 WND
*pDesktop
= WIN_GetDesktop();
1792 if ((list
= WIN_BuildWinArray( pDesktop
, 0, NULL
)))
1794 for (ppWnd
= list
; *ppWnd
; ppWnd
++)
1796 if (!IsWindow( (*ppWnd
)->hwndSelf
)) continue;
1798 if ((*ppWnd
)->hmemTaskQ
== hOldActiveQueue
)
1799 SendMessage16( (*ppWnd
)->hwndSelf
, WM_ACTIVATEAPP
,
1800 0, QUEUE_GetQueueTask(hNewActiveQueue
) );
1802 WIN_ReleaseWinArray(list
);
1805 hActiveQueue
= hNewActiveQueue
;
1807 if ((list
= WIN_BuildWinArray(pDesktop
, 0, NULL
)))
1809 for (ppWnd
= list
; *ppWnd
; ppWnd
++)
1811 if (!IsWindow( (*ppWnd
)->hwndSelf
)) continue;
1813 if ((*ppWnd
)->hmemTaskQ
== hNewActiveQueue
)
1814 SendMessage16( (*ppWnd
)->hwndSelf
, WM_ACTIVATEAPP
,
1815 1, QUEUE_GetQueueTask( hOldActiveQueue
) );
1817 WIN_ReleaseWinArray(list
);
1819 WIN_ReleaseDesktop();
1821 if (hWnd
&& !IsWindow(hWnd
)) goto CLEANUP
;
1826 /* walk up to the first unowned window */
1827 wndTemp
= WIN_LockWndPtr(wndPtr
);
1828 while (wndTemp
->owner
)
1830 WIN_UpdateWndPtr(&wndTemp
,wndTemp
->owner
);
1832 /* and set last active owned popup */
1833 wndTemp
->hwndLastActive
= hWnd
;
1835 wIconized
= HIWORD(wndTemp
->dwStyle
& WS_MINIMIZE
);
1836 WIN_ReleaseWndPtr(wndTemp
);
1837 SendMessageA( hWnd
, WM_NCACTIVATE
, TRUE
, 0 );
1838 SendMessageA( hWnd
, WM_ACTIVATE
,
1839 MAKEWPARAM( (fMouse
) ? WA_CLICKACTIVE
: WA_ACTIVE
, wIconized
),
1840 (LPARAM
)hwndPrevActive
);
1841 if( !IsWindow(hWnd
) ) goto CLEANUP
;
1844 /* change focus if possible */
1847 if ( pNewActiveQueue
)
1849 HWND hOldFocus
= PERQDATA_GetFocusWnd( pNewActiveQueue
->pQData
);
1851 if ( WIN_GetTopParent( hOldFocus
) != hwndActive
)
1852 FOCUS_SwitchFocus( pNewActiveQueue
, hOldFocus
,
1853 (wndPtr
&& (wndPtr
->dwStyle
& WS_MINIMIZE
))?
1857 if ( pOldActiveQueue
&&
1858 ( !pNewActiveQueue
||
1859 pNewActiveQueue
->pQData
!= pOldActiveQueue
->pQData
) )
1861 HWND hOldFocus
= PERQDATA_GetFocusWnd( pOldActiveQueue
->pQData
);
1863 FOCUS_SwitchFocus( pOldActiveQueue
, hOldFocus
, 0 );
1867 if( !hwndPrevActive
&& wndPtr
)
1868 (*wndPtr
->pDriver
->pForceWindowRaise
)(wndPtr
);
1870 /* if active wnd is minimized redraw icon title */
1871 if( IsIconic(hwndActive
) ) WINPOS_RedrawIconTitle(hwndActive
);
1873 bRet
= (hWnd
== hwndActive
); /* Success? */
1875 CLEANUP
: /* Unlock the message queues before returning */
1877 if ( pNewActiveQueue
)
1878 QUEUE_Unlock( pNewActiveQueue
);
1882 if ( pOldActiveQueue
)
1883 QUEUE_Unlock( pOldActiveQueue
);
1885 WIN_ReleaseWndPtr(wndPtr
);
1889 /*******************************************************************
1890 * WINPOS_ActivateOtherWindow
1892 * Activates window other than pWnd.
1894 BOOL
WINPOS_ActivateOtherWindow(WND
* pWnd
)
1898 HWND hwndActive
= 0;
1900 /* Get current active window from the active queue */
1903 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
1906 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
1907 QUEUE_Unlock( pActiveQueue
);
1911 if( pWnd
->hwndSelf
== hwndPrevActive
)
1914 if( hwndActive
!= pWnd
->hwndSelf
&&
1915 ( hwndActive
|| QUEUE_IsExitingQueue(pWnd
->hmemTaskQ
)) )
1918 if( !(pWnd
->dwStyle
& WS_POPUP
) || !(pWnd
->owner
) ||
1919 !WINPOS_CanActivate((pWndTo
= WIN_GetTopParentPtr(pWnd
->owner
))) )
1921 WND
* pWndPtr
= WIN_GetTopParentPtr(pWnd
);
1923 WIN_ReleaseWndPtr(pWndTo
);
1924 pWndTo
= WIN_FindWndPtr(hwndPrevActive
);
1926 while( !WINPOS_CanActivate(pWndTo
) )
1928 /* by now owned windows should've been taken care of */
1929 WIN_UpdateWndPtr(&pWndTo
,pWndPtr
->next
);
1930 WIN_UpdateWndPtr(&pWndPtr
,pWndTo
);
1931 if( !pWndTo
) break;
1933 WIN_ReleaseWndPtr(pWndPtr
);
1936 bRet
= WINPOS_SetActiveWindow( pWndTo
? pWndTo
->hwndSelf
: 0, FALSE
, TRUE
);
1938 /* switch desktop queue to current active */
1941 WIN_GetDesktop()->hmemTaskQ
= pWndTo
->hmemTaskQ
;
1942 WIN_ReleaseWndPtr(pWndTo
);
1943 WIN_ReleaseDesktop();
1950 /*******************************************************************
1951 * WINPOS_ChangeActiveWindow
1954 BOOL
WINPOS_ChangeActiveWindow( HWND hWnd
, BOOL mouseMsg
)
1956 WND
*wndPtr
, *wndTemp
;
1958 HWND hwndActive
= 0;
1960 /* Get current active window from the active queue */
1963 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
1966 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
1967 QUEUE_Unlock( pActiveQueue
);
1972 return WINPOS_SetActiveWindow( 0, mouseMsg
, TRUE
);
1974 wndPtr
= WIN_FindWndPtr(hWnd
);
1975 if( !wndPtr
) return FALSE
;
1977 /* child windows get WM_CHILDACTIVATE message */
1978 if( (wndPtr
->dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1980 retvalue
= SendMessageA(hWnd
, WM_CHILDACTIVATE
, 0, 0L);
1984 if( hWnd
== hwndActive
)
1990 if( !WINPOS_SetActiveWindow(hWnd
,mouseMsg
,TRUE
) )
1996 /* switch desktop queue to current active */
1997 wndTemp
= WIN_GetDesktop();
1998 if( wndPtr
->parent
== wndTemp
)
1999 wndTemp
->hmemTaskQ
= wndPtr
->hmemTaskQ
;
2000 WIN_ReleaseDesktop();
2004 WIN_ReleaseWndPtr(wndPtr
);
2009 /***********************************************************************
2010 * WINPOS_SendNCCalcSize
2012 * Send a WM_NCCALCSIZE message to a window.
2013 * All parameters are read-only except newClientRect.
2014 * oldWindowRect, oldClientRect and winpos must be non-NULL only
2015 * when calcValidRect is TRUE.
2017 LONG
WINPOS_SendNCCalcSize( HWND hwnd
, BOOL calcValidRect
,
2018 RECT
*newWindowRect
, RECT
*oldWindowRect
,
2019 RECT
*oldClientRect
, WINDOWPOS
*winpos
,
2020 RECT
*newClientRect
)
2022 NCCALCSIZE_PARAMS params
;
2023 WINDOWPOS winposCopy
;
2026 params
.rgrc
[0] = *newWindowRect
;
2029 winposCopy
= *winpos
;
2030 params
.rgrc
[1] = *oldWindowRect
;
2031 params
.rgrc
[2] = *oldClientRect
;
2032 params
.lppos
= &winposCopy
;
2034 result
= SendMessageA( hwnd
, WM_NCCALCSIZE
, calcValidRect
,
2036 TRACE("%d,%d-%d,%d\n",
2037 params
.rgrc
[0].left
, params
.rgrc
[0].top
,
2038 params
.rgrc
[0].right
, params
.rgrc
[0].bottom
);
2040 /* If the application send back garbage, ignore it */
2041 if (params
.rgrc
[0].left
<= params
.rgrc
[0].right
&& params
.rgrc
[0].top
<= params
.rgrc
[0].bottom
)
2042 *newClientRect
= params
.rgrc
[0];
2048 /***********************************************************************
2049 * WINPOS_HandleWindowPosChanging16
2051 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2053 LONG
WINPOS_HandleWindowPosChanging16( WND
*wndPtr
, WINDOWPOS16
*winpos
)
2055 POINT maxSize
, minTrack
;
2056 if (winpos
->flags
& SWP_NOSIZE
) return 0;
2057 if ((wndPtr
->dwStyle
& WS_THICKFRAME
) ||
2058 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) == 0))
2060 WINPOS_GetMinMaxInfo( wndPtr
, &maxSize
, NULL
, &minTrack
, NULL
);
2061 if (maxSize
.x
< winpos
->cx
) winpos
->cx
= maxSize
.x
;
2062 if (maxSize
.y
< winpos
->cy
) winpos
->cy
= maxSize
.y
;
2063 if (!(wndPtr
->dwStyle
& WS_MINIMIZE
))
2065 if (winpos
->cx
< minTrack
.x
) winpos
->cx
= minTrack
.x
;
2066 if (winpos
->cy
< minTrack
.y
) winpos
->cy
= minTrack
.y
;
2073 /***********************************************************************
2074 * WINPOS_HandleWindowPosChanging
2076 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2078 LONG
WINPOS_HandleWindowPosChanging( WND
*wndPtr
, WINDOWPOS
*winpos
)
2081 if (winpos
->flags
& SWP_NOSIZE
) return 0;
2082 if ((wndPtr
->dwStyle
& WS_THICKFRAME
) ||
2083 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) == 0))
2085 WINPOS_GetMinMaxInfo( wndPtr
, &maxSize
, NULL
, NULL
, NULL
);
2086 winpos
->cx
= MIN( winpos
->cx
, maxSize
.x
);
2087 winpos
->cy
= MIN( winpos
->cy
, maxSize
.y
);
2092 /***********************************************************************
2095 * fix Z order taking into account owned popups -
2096 * basically we need to maintain them above the window that owns them
2098 * FIXME: hide/show owned popups when owner visibility changes.
2100 static HWND
SWP_DoOwnedPopups(WND
* pDesktop
, WND
* wndPtr
, HWND hwndInsertAfter
, WORD flags
)
2102 WND
* w
= WIN_LockWndPtr(pDesktop
->child
);
2104 WARN("(%04x) hInsertAfter = %04x\n", wndPtr
->hwndSelf
, hwndInsertAfter
);
2106 if( (wndPtr
->dwStyle
& WS_POPUP
) && wndPtr
->owner
)
2108 /* make sure this popup stays above the owner */
2110 HWND hwndLocalPrev
= HWND_TOP
;
2112 if( hwndInsertAfter
!= HWND_TOP
)
2114 while( w
!= wndPtr
->owner
)
2116 if (w
!= wndPtr
) hwndLocalPrev
= w
->hwndSelf
;
2117 if( hwndLocalPrev
== hwndInsertAfter
) break;
2118 WIN_UpdateWndPtr(&w
,w
->next
);
2120 hwndInsertAfter
= hwndLocalPrev
;
2123 else if( wndPtr
->dwStyle
& WS_CHILD
)
2126 WIN_UpdateWndPtr(&w
, pDesktop
->child
);
2130 if( w
== wndPtr
) break;
2132 if( (w
->dwStyle
& WS_POPUP
) && w
->owner
== wndPtr
)
2134 SetWindowPos(w
->hwndSelf
, hwndInsertAfter
, 0, 0, 0, 0,
2135 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOSENDCHANGING
| SWP_DEFERERASE
);
2136 hwndInsertAfter
= w
->hwndSelf
;
2138 WIN_UpdateWndPtr(&w
, w
->next
);
2142 WIN_ReleaseWndPtr(w
);
2143 return hwndInsertAfter
;
2146 /***********************************************************************
2149 * Make window look nice without excessive repainting
2151 * visible and update regions are in window coordinates
2152 * client and window rectangles are in parent client coordinates
2154 * FIXME: SWP_EX_PAINTSELF in uFlags works only if both old and new
2155 * window rects have the same origin.
2157 * Returns: uFlags and a dirty region in *pVisRgn.
2159 static UINT
SWP_CopyValidBits( WND
* Wnd
, HRGN
* pVisRgn
,
2160 LPRECT lpOldWndRect
,
2161 LPRECT lpOldClientRect
, UINT uFlags
)
2164 HRGN newVisRgn
, dirtyRgn
;
2165 INT my
= COMPLEXREGION
;
2167 TRACE("\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2168 Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
,
2169 Wnd
->rectWindow
.right
, Wnd
->rectWindow
.bottom
,
2170 lpOldWndRect
->left
, lpOldWndRect
->top
,
2171 lpOldWndRect
->right
, lpOldWndRect
->bottom
, *pVisRgn
);
2172 TRACE("\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2173 Wnd
->rectClient
.left
, Wnd
->rectClient
.top
,
2174 Wnd
->rectClient
.right
, Wnd
->rectClient
.bottom
,
2175 lpOldClientRect
->left
, lpOldClientRect
->top
,
2176 lpOldClientRect
->right
,lpOldClientRect
->bottom
);
2178 if( Wnd
->hrgnUpdate
== 1 )
2179 uFlags
|= SWP_EX_NOCOPY
; /* whole window is invalid, nothing to copy */
2181 newVisRgn
= DCE_GetVisRgn( Wnd
->hwndSelf
, DCX_WINDOW
| DCX_CLIPSIBLINGS
, 0, 0);
2182 dirtyRgn
= CreateRectRgn( 0, 0, 0, 0 );
2184 if( !(uFlags
& SWP_EX_NOCOPY
) ) /* make sure dst region covers only valid bits */
2185 my
= CombineRgn( dirtyRgn
, newVisRgn
, *pVisRgn
, RGN_AND
);
2187 if( (my
== NULLREGION
) || (uFlags
& SWP_EX_NOCOPY
) )
2191 TRACE("\twon't copy anything!\n");
2193 /* set dirtyRgn to the sum of old and new visible regions
2194 * in parent client coordinates */
2196 OffsetRgn( newVisRgn
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2197 OffsetRgn( *pVisRgn
, lpOldWndRect
->left
, lpOldWndRect
->top
);
2199 CombineRgn(*pVisRgn
, *pVisRgn
, newVisRgn
, RGN_OR
);
2201 else /* copy valid bits to a new location */
2203 INT dx
, dy
, ow
, oh
, nw
, nh
, ocw
, ncw
, och
, nch
;
2204 HRGN hrgnValid
= dirtyRgn
; /* non-empty intersection of old and new visible rgns */
2206 /* subtract already invalid region inside Wnd from the dst region */
2208 if( Wnd
->hrgnUpdate
)
2209 if( CombineRgn( hrgnValid
, hrgnValid
, Wnd
->hrgnUpdate
, RGN_DIFF
) == NULLREGION
)
2212 /* check if entire window can be copied */
2214 ow
= lpOldWndRect
->right
- lpOldWndRect
->left
;
2215 oh
= lpOldWndRect
->bottom
- lpOldWndRect
->top
;
2216 nw
= Wnd
->rectWindow
.right
- Wnd
->rectWindow
.left
;
2217 nh
= Wnd
->rectWindow
.bottom
- Wnd
->rectWindow
.top
;
2219 ocw
= lpOldClientRect
->right
- lpOldClientRect
->left
;
2220 och
= lpOldClientRect
->bottom
- lpOldClientRect
->top
;
2221 ncw
= Wnd
->rectClient
.right
- Wnd
->rectClient
.left
;
2222 nch
= Wnd
->rectClient
.bottom
- Wnd
->rectClient
.top
;
2224 if( (ocw
!= ncw
) || (och
!= nch
) ||
2225 ( ow
!= nw
) || ( oh
!= nh
) ||
2226 ((lpOldClientRect
->top
- lpOldWndRect
->top
) !=
2227 (Wnd
->rectClient
.top
- Wnd
->rectWindow
.top
)) ||
2228 ((lpOldClientRect
->left
- lpOldWndRect
->left
) !=
2229 (Wnd
->rectClient
.left
- Wnd
->rectWindow
.left
)) )
2231 dx
= Wnd
->rectClient
.left
- lpOldClientRect
->left
;
2232 dy
= Wnd
->rectClient
.top
- lpOldClientRect
->top
;
2234 /* restrict valid bits to the common client rect */
2236 r
.left
= Wnd
->rectClient
.left
- Wnd
->rectWindow
.left
;
2237 r
.top
= Wnd
->rectClient
.top
- Wnd
->rectWindow
.top
;
2238 r
.right
= r
.left
+ MIN( ocw
, ncw
);
2239 r
.bottom
= r
.top
+ MIN( och
, nch
);
2241 REGION_CropRgn( hrgnValid
, hrgnValid
, &r
,
2242 (uFlags
& SWP_EX_PAINTSELF
) ? NULL
: (POINT
*)&(Wnd
->rectWindow
));
2243 GetRgnBox( hrgnValid
, &r
);
2244 if( IsRectEmpty( &r
) )
2246 r
= *lpOldClientRect
;
2250 dx
= Wnd
->rectWindow
.left
- lpOldWndRect
->left
;
2251 dy
= Wnd
->rectWindow
.top
- lpOldWndRect
->top
;
2252 if( !(uFlags
& SWP_EX_PAINTSELF
) )
2253 OffsetRgn( hrgnValid
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2257 if( !(uFlags
& SWP_EX_PAINTSELF
) )
2259 /* Move remaining regions to parent coordinates */
2260 OffsetRgn( newVisRgn
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2261 OffsetRgn( *pVisRgn
, lpOldWndRect
->left
, lpOldWndRect
->top
);
2264 OffsetRect( &r
, -lpOldWndRect
->left
, -lpOldWndRect
->top
);
2266 TRACE("\tcomputing dirty region!\n");
2268 /* Compute combined dirty region (old + new - valid) */
2269 CombineRgn( *pVisRgn
, *pVisRgn
, newVisRgn
, RGN_OR
);
2270 CombineRgn( *pVisRgn
, *pVisRgn
, hrgnValid
, RGN_DIFF
);
2272 /* Blt valid bits, r is the rect to copy */
2280 /* get DC and clip rect with drawable rect to avoid superfluous expose events
2281 from copying clipped areas */
2283 if( uFlags
& SWP_EX_PAINTSELF
)
2285 hDC
= GetDCEx( Wnd
->hwndSelf
, hrgnValid
, DCX_WINDOW
| DCX_CACHE
|
2286 DCX_KEEPCLIPRGN
| DCX_INTERSECTRGN
| DCX_CLIPSIBLINGS
);
2287 rClip
.right
= nw
; rClip
.bottom
= nh
;
2291 hDC
= GetDCEx( Wnd
->parent
->hwndSelf
, hrgnValid
, DCX_CACHE
|
2292 DCX_KEEPCLIPRGN
| DCX_INTERSECTRGN
| DCX_CLIPSIBLINGS
);
2293 rClip
.right
= Wnd
->parent
->rectClient
.right
- Wnd
->parent
->rectClient
.left
;
2294 rClip
.bottom
= Wnd
->parent
->rectClient
.bottom
- Wnd
->parent
->rectClient
.top
;
2296 rClip
.left
= rClip
.top
= 0;
2298 if( (dc
= (DC
*)GDI_GetObjPtr(hDC
, DC_MAGIC
)) )
2300 if( oh
> nh
) r
.bottom
= r
.top
+ nh
;
2301 if( ow
< nw
) r
.right
= r
.left
+ nw
;
2303 if( IntersectRect( &r
, &r
, &rClip
) )
2305 Wnd
->pDriver
->pSurfaceCopy( Wnd
->parent
, dc
, dx
, dy
, &r
, TRUE
);
2307 /* When you copy the bits without repainting, parent doesn't
2308 get validated appropriately. Therefore, we have to validate
2309 the parent with the windows' updated region when the
2310 parent's update region is not empty. */
2312 if (Wnd
->parent
->hrgnUpdate
!= 0 && !(Wnd
->parent
->dwStyle
& WS_CLIPCHILDREN
))
2314 OffsetRect(&r
, dx
, dy
);
2315 ValidateRect(Wnd
->parent
->hwndSelf
, &r
);
2319 GDI_HEAP_UNLOCK( hDC
);
2321 ReleaseDC( (uFlags
& SWP_EX_PAINTSELF
) ?
2322 Wnd
->hwndSelf
: Wnd
->parent
->hwndSelf
, hDC
);
2326 /* *pVisRgn now points to the invalidated region */
2328 DeleteObject(newVisRgn
);
2329 DeleteObject(dirtyRgn
);
2333 /***********************************************************************
2334 * SWP_DoSimpleFrameChanged
2336 * NOTE: old and new client rect origins are identical, only
2337 * extents may have changed. Window extents are the same.
2339 static void SWP_DoSimpleFrameChanged( WND
* wndPtr
, RECT
* pOldClientRect
, WORD swpFlags
, UINT uFlags
)
2345 if( !(swpFlags
& SWP_NOCLIENTSIZE
) )
2347 /* Client rect changed its position/size, most likely a scrollar
2348 * was added/removed.
2350 * FIXME: WVR alignment flags
2353 if( wndPtr
->rectClient
.right
> pOldClientRect
->right
) /* right edge */
2357 rect
.bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
2358 rect
.right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
2359 if(!(uFlags
& SWP_EX_NOCOPY
))
2360 rect
.left
= pOldClientRect
->right
- wndPtr
->rectClient
.left
;
2368 if( wndPtr
->rectClient
.bottom
> pOldClientRect
->bottom
) /* bottom edge */
2371 hrgn
= CreateRectRgnIndirect( &rect
);
2373 rect
.right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
2374 rect
.bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
2375 if(!(uFlags
& SWP_EX_NOCOPY
))
2376 rect
.top
= pOldClientRect
->bottom
- wndPtr
->rectClient
.top
;
2380 REGION_UnionRectWithRgn( hrgn
, &rect
);
2383 if( i
== 0 && (uFlags
& SWP_EX_NOCOPY
) ) /* force redraw anyway */
2385 rect
= wndPtr
->rectWindow
;
2386 OffsetRect( &rect
, wndPtr
->rectWindow
.left
- wndPtr
->rectClient
.left
,
2387 wndPtr
->rectWindow
.top
- wndPtr
->rectClient
.top
);
2395 PAINT_RedrawWindow( wndPtr
->hwndSelf
, &rect
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
|
2396 RDW_ERASENOW
| RDW_ALLCHILDREN
, RDW_EX_TOPFRAME
| RDW_EX_USEHRGN
);
2400 WIN_UpdateNCRgn(wndPtr
, 0, UNC_UPDATE
| UNC_ENTIRE
);
2404 DeleteObject( hrgn
);
2407 /***********************************************************************
2408 * SWP_DoWinPosChanging
2410 static BOOL
SWP_DoWinPosChanging( WND
* wndPtr
, WINDOWPOS
* pWinpos
,
2411 RECT
* pNewWindowRect
, RECT
* pNewClientRect
)
2413 /* Send WM_WINDOWPOSCHANGING message */
2415 if (!(pWinpos
->flags
& SWP_NOSENDCHANGING
))
2416 SendMessageA( wndPtr
->hwndSelf
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
)pWinpos
);
2418 /* Calculate new position and size */
2420 *pNewWindowRect
= wndPtr
->rectWindow
;
2421 *pNewClientRect
= (wndPtr
->dwStyle
& WS_MINIMIZE
) ? wndPtr
->rectWindow
2422 : wndPtr
->rectClient
;
2424 if (!(pWinpos
->flags
& SWP_NOSIZE
))
2426 pNewWindowRect
->right
= pNewWindowRect
->left
+ pWinpos
->cx
;
2427 pNewWindowRect
->bottom
= pNewWindowRect
->top
+ pWinpos
->cy
;
2429 if (!(pWinpos
->flags
& SWP_NOMOVE
))
2431 pNewWindowRect
->left
= pWinpos
->x
;
2432 pNewWindowRect
->top
= pWinpos
->y
;
2433 pNewWindowRect
->right
+= pWinpos
->x
- wndPtr
->rectWindow
.left
;
2434 pNewWindowRect
->bottom
+= pWinpos
->y
- wndPtr
->rectWindow
.top
;
2436 OffsetRect( pNewClientRect
, pWinpos
->x
- wndPtr
->rectWindow
.left
,
2437 pWinpos
->y
- wndPtr
->rectWindow
.top
);
2440 pWinpos
->flags
|= SWP_NOCLIENTMOVE
| SWP_NOCLIENTSIZE
;
2444 /***********************************************************************
2447 static UINT
SWP_DoNCCalcSize( WND
* wndPtr
, WINDOWPOS
* pWinpos
,
2448 RECT
* pNewWindowRect
, RECT
* pNewClientRect
, WORD f
)
2452 /* Send WM_NCCALCSIZE message to get new client area */
2453 if( (pWinpos
->flags
& (SWP_FRAMECHANGED
| SWP_NOSIZE
)) != SWP_NOSIZE
)
2455 wvrFlags
= WINPOS_SendNCCalcSize( pWinpos
->hwnd
, TRUE
, pNewWindowRect
,
2456 &wndPtr
->rectWindow
, &wndPtr
->rectClient
,
2457 pWinpos
, pNewClientRect
);
2459 /* FIXME: WVR_ALIGNxxx */
2461 if( pNewClientRect
->left
!= wndPtr
->rectClient
.left
||
2462 pNewClientRect
->top
!= wndPtr
->rectClient
.top
)
2463 pWinpos
->flags
&= ~SWP_NOCLIENTMOVE
;
2465 if( (pNewClientRect
->right
- pNewClientRect
->left
!=
2466 wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
) ||
2467 (pNewClientRect
->bottom
- pNewClientRect
->top
!=
2468 wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
) )
2469 pWinpos
->flags
&= ~SWP_NOCLIENTSIZE
;
2472 if( !(f
& SWP_NOMOVE
) && (pNewClientRect
->left
!= wndPtr
->rectClient
.left
||
2473 pNewClientRect
->top
!= wndPtr
->rectClient
.top
) )
2474 pWinpos
->flags
&= ~SWP_NOCLIENTMOVE
;
2478 /***********************************************************************
2479 * SetWindowPos (USER.2)
2481 BOOL16 WINAPI
SetWindowPos16( HWND16 hwnd
, HWND16 hwndInsertAfter
,
2482 INT16 x
, INT16 y
, INT16 cx
, INT16 cy
, WORD flags
)
2484 return SetWindowPos(hwnd
,(INT
)(INT16
)hwndInsertAfter
,x
,y
,cx
,cy
,flags
);
2487 /***********************************************************************
2488 * SetWindowPos (USER32.520)
2490 BOOL WINAPI
SetWindowPos( HWND hwnd
, HWND hwndInsertAfter
,
2491 INT x
, INT y
, INT cx
, INT cy
, UINT flags
)
2494 WND
* wndPtr
,*wndTemp
;
2495 RECT newWindowRect
, newClientRect
;
2496 RECT oldWindowRect
, oldClientRect
;
2498 UINT wvrFlags
= 0, uFlags
= 0;
2499 BOOL retvalue
, resync
= FALSE
, bChangePos
;
2500 HWND hwndActive
= 0;
2502 /* Get current active window from the active queue */
2505 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
2508 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
2509 QUEUE_Unlock( pActiveQueue
);
2513 TRACE("hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2514 hwnd
, x
, y
, x
+cx
, y
+cy
, flags
);
2516 bChangePos
= !(flags
& SWP_WINE_NOHOSTMOVE
);
2517 flags
&= ~SWP_WINE_NOHOSTMOVE
;
2520 /* ------------------------------------------------------------------------ CHECKS */
2522 /* Check window handle */
2524 if (hwnd
== GetDesktopWindow()) return FALSE
;
2525 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return FALSE
;
2527 TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr
->rectWindow
.left
, wndPtr
->rectWindow
.top
,
2528 wndPtr
->rectWindow
.right
, wndPtr
->rectWindow
.bottom
, (unsigned)wndPtr
->dwStyle
);
2530 /* Fix redundant flags */
2532 if(wndPtr
->dwStyle
& WS_VISIBLE
)
2533 flags
&= ~SWP_SHOWWINDOW
;
2536 if (!(flags
& SWP_SHOWWINDOW
))
2537 flags
|= SWP_NOREDRAW
;
2538 flags
&= ~SWP_HIDEWINDOW
;
2541 if ( cx
< 0 ) cx
= 0; if( cy
< 0 ) cy
= 0;
2543 if ((wndPtr
->rectWindow
.right
- wndPtr
->rectWindow
.left
== cx
) &&
2544 (wndPtr
->rectWindow
.bottom
- wndPtr
->rectWindow
.top
== cy
))
2545 flags
|= SWP_NOSIZE
; /* Already the right size */
2547 if ((wndPtr
->rectWindow
.left
== x
) && (wndPtr
->rectWindow
.top
== y
))
2548 flags
|= SWP_NOMOVE
; /* Already the right position */
2550 if (hwnd
== hwndActive
)
2551 flags
|= SWP_NOACTIVATE
; /* Already active */
2552 else if ( (wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)
2554 if(!(flags
& SWP_NOACTIVATE
)) /* Bring to the top when activating */
2556 flags
&= ~SWP_NOZORDER
;
2557 hwndInsertAfter
= HWND_TOP
;
2562 /* Check hwndInsertAfter */
2564 /* FIXME: TOPMOST not supported yet */
2565 if ((hwndInsertAfter
== HWND_TOPMOST
) ||
2566 (hwndInsertAfter
== HWND_NOTOPMOST
)) hwndInsertAfter
= HWND_TOP
;
2568 /* hwndInsertAfter must be a sibling of the window */
2569 if ((hwndInsertAfter
!= HWND_TOP
) && (hwndInsertAfter
!= HWND_BOTTOM
))
2571 WND
* wnd
= WIN_FindWndPtr(hwndInsertAfter
);
2574 if( wnd
->parent
!= wndPtr
->parent
)
2577 WIN_ReleaseWndPtr(wnd
);
2580 if( wnd
->next
== wndPtr
) flags
|= SWP_NOZORDER
;
2582 WIN_ReleaseWndPtr(wnd
);
2585 Pos
: /* ------------------------------------------------------------------------ MAIN part */
2587 /* Fill the WINDOWPOS structure */
2590 winpos
.hwndInsertAfter
= hwndInsertAfter
;
2595 winpos
.flags
= flags
;
2597 SWP_DoWinPosChanging( wndPtr
, &winpos
, &newWindowRect
, &newClientRect
);
2599 if((winpos
.flags
& (SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) != SWP_NOZORDER
)
2601 if( wndPtr
->parent
== WIN_GetDesktop() )
2602 hwndInsertAfter
= SWP_DoOwnedPopups( wndPtr
->parent
, wndPtr
,
2603 hwndInsertAfter
, winpos
.flags
);
2604 WIN_ReleaseDesktop();
2607 if(!(wndPtr
->flags
& WIN_NATIVE
) )
2609 if( hwndInsertAfter
== HWND_TOP
)
2610 winpos
.flags
|= ( wndPtr
->parent
->child
== wndPtr
)? SWP_NOZORDER
: 0;
2612 if( hwndInsertAfter
== HWND_BOTTOM
)
2613 winpos
.flags
|= ( wndPtr
->next
)? 0: SWP_NOZORDER
;
2615 if( !(winpos
.flags
& SWP_NOZORDER
) )
2616 if( GetWindow(hwndInsertAfter
, GW_HWNDNEXT
) == wndPtr
->hwndSelf
)
2617 winpos
.flags
|= SWP_NOZORDER
;
2619 if( !(winpos
.flags
& (SWP_NOREDRAW
| SWP_SHOWWINDOW
)) &&
2620 ((winpos
.flags
& (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_FRAMECHANGED
))
2621 != (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
)) )
2623 /* get a previous visible region for SWP_CopyValidBits() */
2624 DWORD flags
= DCX_WINDOW
;
2626 if (wndPtr
->dwStyle
& WS_CLIPSIBLINGS
)
2627 flags
|= DCX_CLIPSIBLINGS
;
2629 visRgn
= DCE_GetVisRgn(hwnd
, flags
, 0, 0);
2633 /* Common operations */
2635 wvrFlags
= SWP_DoNCCalcSize( wndPtr
, &winpos
, &newWindowRect
, &newClientRect
, flags
);
2637 if(!(winpos
.flags
& SWP_NOZORDER
))
2639 if ( WIN_UnlinkWindow( winpos
.hwnd
) )
2640 WIN_LinkWindow( winpos
.hwnd
, hwndInsertAfter
);
2643 /* Reset active DCEs */
2645 if( (((winpos
.flags
& SWP_AGG_NOPOSCHANGE
) != SWP_AGG_NOPOSCHANGE
) &&
2646 wndPtr
->dwStyle
& WS_VISIBLE
) ||
2647 (flags
& (SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) )
2651 UnionRect(&rect
, &newWindowRect
, &wndPtr
->rectWindow
);
2652 DCE_InvalidateDCE(wndPtr
, &rect
);
2655 oldWindowRect
= wndPtr
->rectWindow
;
2656 oldClientRect
= wndPtr
->rectClient
;
2658 /* Find out if we have to redraw the whole client rect */
2660 if( oldClientRect
.bottom
- oldClientRect
.top
==
2661 newClientRect
.bottom
- newClientRect
.top
) wvrFlags
&= ~WVR_VREDRAW
;
2663 if( oldClientRect
.right
- oldClientRect
.left
==
2664 newClientRect
.right
- newClientRect
.left
) wvrFlags
&= ~WVR_HREDRAW
;
2666 if( (winpos
.flags
& SWP_NOCOPYBITS
) || (!(winpos
.flags
& SWP_NOCLIENTSIZE
) &&
2667 (wvrFlags
>= WVR_HREDRAW
) && (wvrFlags
< WVR_VALIDRECTS
)) )
2669 uFlags
|= SWP_EX_NOCOPY
;
2672 * Use this later in CopyValidBits()
2675 uFlags |= SWP_EX_NONCLIENT;
2678 /* FIXME: actually do something with WVR_VALIDRECTS */
2680 wndPtr
->rectWindow
= newWindowRect
;
2681 wndPtr
->rectClient
= newClientRect
;
2683 if (wndPtr
->flags
& WIN_NATIVE
) /* -------------------------------------------- hosted window */
2685 BOOL bCallDriver
= TRUE
;
2686 HWND tempInsertAfter
= winpos
.hwndInsertAfter
;
2688 winpos
.hwndInsertAfter
= hwndInsertAfter
;
2690 if( !(winpos
.flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
| SWP_NOREDRAW
)) )
2692 /* This is the only place where we need to force repainting of the contents
2693 of windows created by the host window system, all other cases go through the
2694 expose event handling */
2696 if( (winpos
.flags
& (SWP_NOSIZE
| SWP_FRAMECHANGED
)) == (SWP_NOSIZE
| SWP_FRAMECHANGED
) )
2698 cx
= newWindowRect
.right
- newWindowRect
.left
;
2699 cy
= newWindowRect
.bottom
- newWindowRect
.top
;
2701 wndPtr
->pDriver
->pSetWindowPos(wndPtr
, &winpos
, bChangePos
);
2702 winpos
.hwndInsertAfter
= tempInsertAfter
;
2703 bCallDriver
= FALSE
;
2705 if( winpos
.flags
& SWP_NOCLIENTMOVE
)
2706 SWP_DoSimpleFrameChanged(wndPtr
, &oldClientRect
, winpos
.flags
, uFlags
);
2709 /* client area moved but window extents remained the same, copy valid bits */
2711 visRgn
= CreateRectRgn( 0, 0, cx
, cy
);
2712 uFlags
= SWP_CopyValidBits( wndPtr
, &visRgn
, &oldWindowRect
, &oldClientRect
,
2713 uFlags
| SWP_EX_PAINTSELF
);
2720 if( !(winpos
.flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
| SWP_NOREDRAW
)) )
2722 if( (oldClientRect
.left
- oldWindowRect
.left
== newClientRect
.left
- newWindowRect
.left
) &&
2723 (oldClientRect
.top
- oldWindowRect
.top
== newClientRect
.top
- newWindowRect
.top
) &&
2724 !(uFlags
& SWP_EX_NOCOPY
) )
2726 /* The origin of the client rect didn't move so we can try to repaint
2727 * only the nonclient area by setting bit gravity hint for the host window system.
2730 if( !(wndPtr
->flags
& WIN_MANAGED
) )
2732 HRGN hrgn
= CreateRectRgn( 0, 0, newWindowRect
.right
- newWindowRect
.left
,
2733 newWindowRect
.bottom
- newWindowRect
.top
);
2734 RECT rcn
= newClientRect
;
2735 RECT rco
= oldClientRect
;
2737 OffsetRect( &rcn
, -newWindowRect
.left
, -newWindowRect
.top
);
2738 OffsetRect( &rco
, -oldWindowRect
.left
, -oldWindowRect
.top
);
2739 IntersectRect( &rcn
, &rcn
, &rco
);
2740 visRgn
= CreateRectRgnIndirect( &rcn
);
2741 CombineRgn( visRgn
, hrgn
, visRgn
, RGN_DIFF
);
2742 DeleteObject( hrgn
);
2743 uFlags
= SWP_EX_PAINTSELF
;
2745 wndPtr
->pDriver
->pSetHostAttr(wndPtr
, HAK_BITGRAVITY
, BGNorthWest
);
2748 wndPtr
->pDriver
->pSetHostAttr(wndPtr
, HAK_BITGRAVITY
, BGForget
);
2751 wndPtr
->pDriver
->pSetWindowPos(wndPtr
, &winpos
, bChangePos
);
2752 winpos
.hwndInsertAfter
= tempInsertAfter
;
2755 if( winpos
.flags
& SWP_SHOWWINDOW
)
2759 wndPtr
->dwStyle
|= WS_VISIBLE
;
2761 if (wndPtr
->flags
& WIN_MANAGED
) resync
= TRUE
;
2763 /* focus was set to unmapped window, reset host focus
2764 * since the window is now visible */
2766 focus
= curr
= GetFocus();
2771 WND
*pFocus
= WIN_FindWndPtr( focus
);
2773 pFocus
->pDriver
->pSetFocus(pFocus
);
2774 WIN_ReleaseWndPtr(pFocus
);
2777 curr
= GetParent(curr
);
2781 else /* -------------------------------------------- emulated window */
2783 if( winpos
.flags
& SWP_SHOWWINDOW
)
2785 wndPtr
->dwStyle
|= WS_VISIBLE
;
2786 uFlags
|= SWP_EX_PAINTSELF
;
2787 visRgn
= 1; /* redraw the whole window */
2789 else if( !(winpos
.flags
& SWP_NOREDRAW
) )
2791 if( winpos
.flags
& SWP_HIDEWINDOW
)
2793 if( visRgn
> 1 ) /* map to parent */
2794 OffsetRgn( visRgn
, oldWindowRect
.left
, oldWindowRect
.top
);
2800 if( (winpos
.flags
& SWP_AGG_NOPOSCHANGE
) != SWP_AGG_NOPOSCHANGE
)
2801 uFlags
= SWP_CopyValidBits(wndPtr
, &visRgn
, &oldWindowRect
,
2802 &oldClientRect
, uFlags
);
2805 /* nothing moved, redraw frame if needed */
2807 if( winpos
.flags
& SWP_FRAMECHANGED
)
2808 SWP_DoSimpleFrameChanged( wndPtr
, &oldClientRect
, winpos
.flags
, uFlags
);
2811 DeleteObject( visRgn
);
2819 if( winpos
.flags
& SWP_HIDEWINDOW
)
2821 wndPtr
->dwStyle
&= ~WS_VISIBLE
;
2823 if (hwnd
== CARET_GetHwnd()) DestroyCaret();
2826 /* ------------------------------------------------------------------------ FINAL */
2828 if (wndPtr
->flags
& WIN_NATIVE
)
2829 EVENT_Synchronize(); /* Synchronize with the host window system */
2831 if (!GetCapture() && ((wndPtr
->dwStyle
& WS_VISIBLE
) || (flags
& SWP_HIDEWINDOW
)))
2833 /* Simulate a mouse event to set the cursor */
2834 int iWndsLocks
= WIN_SuspendWndsLock();
2836 hardware_event( WM_MOUSEMOVE
, GET_KEYSTATE(), 0,
2837 PosX
, PosY
, GetTickCount(), 0 );
2839 WIN_RestoreWndsLock(iWndsLocks
);
2842 wndTemp
= WIN_GetDesktop();
2844 /* repaint invalidated region (if any)
2846 * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2847 * and force update after ChangeActiveWindow() to avoid painting frames twice.
2852 if( !(winpos
.flags
& SWP_NOREDRAW
) )
2855 /* Use PAINT_RedrawWindow to explicitly force an invalidation of the window,
2856 its parent and sibling and so on, and then erase the parent window
2857 back ground if the parent is either a top-level window or its parent's parent
2858 is top-level window. Rely on the system to repaint other affected
2859 windows later on. */
2860 if( uFlags
& SWP_EX_PAINTSELF
)
2862 PAINT_RedrawWindow( wndPtr
->hwndSelf
, NULL
, (visRgn
== 1) ? 0 : visRgn
,
2863 RDW_ERASE
| RDW_FRAME
| RDW_INVALIDATE
| RDW_ALLCHILDREN
,
2864 RDW_EX_XYWINDOW
| RDW_EX_USEHRGN
);
2868 PAINT_RedrawWindow( wndPtr
->parent
->hwndSelf
, NULL
, (visRgn
== 1) ? 0 : visRgn
,
2869 RDW_ERASE
| RDW_INVALIDATE
| RDW_ALLCHILDREN
,
2873 if(wndPtr
-> parent
== wndTemp
|| wndPtr
->parent
->parent
== wndTemp
)
2875 PAINT_RedrawWindow( wndPtr
->parent
->hwndSelf
, NULL
, 0,
2876 RDW_ERASENOW
| RDW_NOCHILDREN
, 0 );
2880 DeleteObject( visRgn
);
2883 WIN_ReleaseDesktop();
2885 if (!(flags
& SWP_NOACTIVATE
))
2886 WINPOS_ChangeActiveWindow( winpos
.hwnd
, FALSE
);
2888 /* And last, send the WM_WINDOWPOSCHANGED message */
2890 TRACE("\tstatus flags = %04x\n", winpos
.flags
& SWP_AGG_STATUSFLAGS
);
2893 (((winpos
.flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOPOSCHANGE
) &&
2894 !(winpos
.flags
& SWP_NOSENDCHANGING
)) )
2896 SendMessageA( winpos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
)&winpos
);
2897 if (resync
) EVENT_Synchronize();
2902 WIN_ReleaseWndPtr(wndPtr
);
2907 /***********************************************************************
2908 * BeginDeferWindowPos16 (USER.259)
2910 HDWP16 WINAPI
BeginDeferWindowPos16( INT16 count
)
2912 return BeginDeferWindowPos( count
);
2916 /***********************************************************************
2917 * BeginDeferWindowPos (USER32.9)
2919 HDWP WINAPI
BeginDeferWindowPos( INT count
)
2924 if (count
<= 0) return 0;
2925 handle
= USER_HEAP_ALLOC( sizeof(DWP
) + (count
-1)*sizeof(WINDOWPOS
) );
2926 if (!handle
) return 0;
2927 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( handle
);
2928 pDWP
->actualCount
= 0;
2929 pDWP
->suggestedCount
= count
;
2931 pDWP
->wMagic
= DWP_MAGIC
;
2932 pDWP
->hwndParent
= 0;
2937 /***********************************************************************
2938 * DeferWindowPos16 (USER.260)
2940 HDWP16 WINAPI
DeferWindowPos16( HDWP16 hdwp
, HWND16 hwnd
, HWND16 hwndAfter
,
2941 INT16 x
, INT16 y
, INT16 cx
, INT16 cy
,
2944 return DeferWindowPos( hdwp
, hwnd
, (INT
)(INT16
)hwndAfter
,
2945 x
, y
, cx
, cy
, flags
);
2949 /***********************************************************************
2950 * DeferWindowPos (USER32.128)
2952 HDWP WINAPI
DeferWindowPos( HDWP hdwp
, HWND hwnd
, HWND hwndAfter
,
2953 INT x
, INT y
, INT cx
, INT cy
,
2958 HDWP newhdwp
= hdwp
,retvalue
;
2962 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
2963 if (!pDWP
) return 0;
2964 if (hwnd
== GetDesktopWindow()) return 0;
2966 if (!(pWnd
=WIN_FindWndPtr( hwnd
))) {
2967 USER_HEAP_FREE( hdwp
);
2971 /* Numega Bounds Checker Demo dislikes the following code.
2972 In fact, I've not been able to find any "same parent" requirement in any docu
2976 /* All the windows of a DeferWindowPos() must have the same parent */
2977 parent
= pWnd
->parent
->hwndSelf
;
2978 if (pDWP
->actualCount
== 0) pDWP
->hwndParent
= parent
;
2979 else if (parent
!= pDWP
->hwndParent
)
2981 USER_HEAP_FREE( hdwp
);
2987 for (i
= 0; i
< pDWP
->actualCount
; i
++)
2989 if (pDWP
->winPos
[i
].hwnd
== hwnd
)
2991 /* Merge with the other changes */
2992 if (!(flags
& SWP_NOZORDER
))
2994 pDWP
->winPos
[i
].hwndInsertAfter
= hwndAfter
;
2996 if (!(flags
& SWP_NOMOVE
))
2998 pDWP
->winPos
[i
].x
= x
;
2999 pDWP
->winPos
[i
].y
= y
;
3001 if (!(flags
& SWP_NOSIZE
))
3003 pDWP
->winPos
[i
].cx
= cx
;
3004 pDWP
->winPos
[i
].cy
= cy
;
3006 pDWP
->winPos
[i
].flags
&= flags
| ~(SWP_NOSIZE
| SWP_NOMOVE
|
3007 SWP_NOZORDER
| SWP_NOREDRAW
|
3008 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
3010 pDWP
->winPos
[i
].flags
|= flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
|
3016 if (pDWP
->actualCount
>= pDWP
->suggestedCount
)
3018 newhdwp
= USER_HEAP_REALLOC( hdwp
,
3019 sizeof(DWP
) + pDWP
->suggestedCount
*sizeof(WINDOWPOS
) );
3025 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( newhdwp
);
3026 pDWP
->suggestedCount
++;
3028 pDWP
->winPos
[pDWP
->actualCount
].hwnd
= hwnd
;
3029 pDWP
->winPos
[pDWP
->actualCount
].hwndInsertAfter
= hwndAfter
;
3030 pDWP
->winPos
[pDWP
->actualCount
].x
= x
;
3031 pDWP
->winPos
[pDWP
->actualCount
].y
= y
;
3032 pDWP
->winPos
[pDWP
->actualCount
].cx
= cx
;
3033 pDWP
->winPos
[pDWP
->actualCount
].cy
= cy
;
3034 pDWP
->winPos
[pDWP
->actualCount
].flags
= flags
;
3035 pDWP
->actualCount
++;
3038 WIN_ReleaseWndPtr(pWnd
);
3043 /***********************************************************************
3044 * EndDeferWindowPos16 (USER.261)
3046 BOOL16 WINAPI
EndDeferWindowPos16( HDWP16 hdwp
)
3048 return EndDeferWindowPos( hdwp
);
3052 /***********************************************************************
3053 * EndDeferWindowPos (USER32.173)
3055 BOOL WINAPI
EndDeferWindowPos( HDWP hdwp
)
3062 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
3063 if (!pDWP
) return FALSE
;
3064 for (i
= 0, winpos
= pDWP
->winPos
; i
< pDWP
->actualCount
; i
++, winpos
++)
3066 if (!(res
= SetWindowPos( winpos
->hwnd
, winpos
->hwndInsertAfter
,
3067 winpos
->x
, winpos
->y
, winpos
->cx
,
3068 winpos
->cy
, winpos
->flags
))) break;
3070 USER_HEAP_FREE( hdwp
);
3075 /***********************************************************************
3076 * TileChildWindows (USER.199)
3078 void WINAPI
TileChildWindows16( HWND16 parent
, WORD action
)
3080 FIXME("(%04x, %d): stub\n", parent
, action
);
3083 /***********************************************************************
3084 * CascageChildWindows (USER.198)
3086 void WINAPI
CascadeChildWindows16( HWND16 parent
, WORD action
)
3088 FIXME("(%04x, %d): stub\n", parent
, action
);
3091 /***********************************************************************
3092 * SetProgmanWindow [USER32.522]
3094 HRESULT WINAPI
SetProgmanWindow ( HWND hwnd
)
3096 hGlobalProgmanWindow
= hwnd
;
3097 return hGlobalProgmanWindow
;
3100 /***********************************************************************
3101 * GetProgmanWindow [USER32.289]
3103 HRESULT WINAPI
GetProgmanWindow ( )
3105 return hGlobalProgmanWindow
;
3108 /***********************************************************************
3109 * SetShellWindowEx [USER32.531]
3110 * hwndProgman = Progman[Program Manager]
3111 * |-> SHELLDLL_DefView
3112 * hwndListView = | |-> SysListView32
3113 * | | |-> tooltips_class32
3119 HRESULT WINAPI
SetShellWindowEx ( HWND hwndProgman
, HWND hwndListView
)
3121 FIXME("0x%08x 0x%08x stub\n",hwndProgman
,hwndListView
);
3122 hGlobalShellWindow
= hwndProgman
;
3123 return hGlobalShellWindow
;
3127 /***********************************************************************
3128 * SetTaskmanWindow [USER32.537]
3130 * hwnd = MSTaskSwWClass
3131 * |-> SysTabControl32
3133 HRESULT WINAPI
SetTaskmanWindow ( HWND hwnd
)
3135 hGlobalTaskmanWindow
= hwnd
;
3136 return hGlobalTaskmanWindow
;
3139 /***********************************************************************
3140 * GetTaskmanWindow [USER32.304]
3142 HRESULT WINAPI
GetTaskmanWindow ( )
3144 return hGlobalTaskmanWindow
;