2 * Window position related functions.
4 * Copyright 1993, 1994, 1995 Alexandre Julliard
5 * 1995, 1996, 1999 Alex Korobka
9 #include "sysmetrics.h"
22 #include "nonclient.h"
27 DEFAULT_DEBUG_CHANNEL(win
)
29 #define HAS_DLGFRAME(style,exStyle) \
30 (((exStyle) & WS_EX_DLGMODALFRAME) || \
31 (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
33 #define HAS_THICKFRAME(style) \
34 (((style) & WS_THICKFRAME) && \
35 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
37 #define SWP_AGG_NOGEOMETRYCHANGE \
38 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
39 #define SWP_AGG_NOPOSCHANGE \
40 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
41 #define SWP_AGG_STATUSFLAGS \
42 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
44 #define EMPTYPOINT(pt) ((*(LONG*)&(pt)) == -1)
46 #define PLACE_MIN 0x0001
47 #define PLACE_MAX 0x0002
48 #define PLACE_RECT 0x0004
50 #define SWP_EX_NOCOPY 0x0001
51 #define SWP_EX_PAINTSELF 0x0002
53 #define MINMAX_NOSWP 0x00010000
55 /* ----- internal variables ----- */
57 static HWND hwndPrevActive
= 0; /* Previously active window */
58 static HWND hGlobalShellWindow
=0; /*the shell*/
60 static LPCSTR atomInternalPos
;
62 extern HQUEUE16 hActiveQueue
;
64 /***********************************************************************
65 * WINPOS_CreateInternalPosAtom
67 BOOL
WINPOS_CreateInternalPosAtom()
70 atomInternalPos
= (LPCSTR
)(DWORD
)GlobalAddAtomA(str
);
71 return (atomInternalPos
) ? TRUE
: FALSE
;
74 /***********************************************************************
75 * WINPOS_CheckInternalPos
77 * Called when a window is destroyed.
79 void WINPOS_CheckInternalPos( WND
* wndPtr
)
82 MESSAGEQUEUE
*pMsgQ
= 0;
83 HWND hwnd
= wndPtr
->hwndSelf
;
85 lpPos
= (LPINTERNALPOS
) GetPropA( hwnd
, atomInternalPos
);
87 /* Retrieve the message queue associated with this window */
88 pMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( wndPtr
->hmemTaskQ
);
91 WARN( win
, "\tMessage queue not found. Exiting!\n" );
95 if( hwnd
== hwndPrevActive
) hwndPrevActive
= 0;
97 if( hwnd
== PERQDATA_GetActiveWnd( pMsgQ
->pQData
) )
99 PERQDATA_SetActiveWnd( pMsgQ
->pQData
, 0 );
100 WARN(win
, "\tattempt to activate destroyed window!\n");
105 if( IsWindow(lpPos
->hwndIconTitle
) )
106 DestroyWindow( lpPos
->hwndIconTitle
);
107 HeapFree( SystemHeap
, 0, lpPos
);
110 QUEUE_Unlock( pMsgQ
);
114 /***********************************************************************
117 * Find a suitable place for an iconic window.
119 static POINT16
WINPOS_FindIconPos( WND
* wndPtr
, POINT16 pt
)
122 short x
, y
, xspacing
, yspacing
;
124 GetClientRect16( wndPtr
->parent
->hwndSelf
, &rectParent
);
125 if ((pt
.x
>= rectParent
.left
) && (pt
.x
+ SYSMETRICS_CXICON
< rectParent
.right
) &&
126 (pt
.y
>= rectParent
.top
) && (pt
.y
+ SYSMETRICS_CYICON
< rectParent
.bottom
))
127 return pt
; /* The icon already has a suitable position */
129 xspacing
= SYSMETRICS_CXICONSPACING
;
130 yspacing
= SYSMETRICS_CYICONSPACING
;
132 y
= rectParent
.bottom
;
135 for (x
= rectParent
.left
; x
<= rectParent
.right
-xspacing
; x
+= xspacing
)
137 /* Check if another icon already occupies this spot */
138 WND
*childPtr
= WIN_LockWndPtr(wndPtr
->parent
->child
);
141 if ((childPtr
->dwStyle
& WS_MINIMIZE
) && (childPtr
!= wndPtr
))
143 if ((childPtr
->rectWindow
.left
< x
+ xspacing
) &&
144 (childPtr
->rectWindow
.right
>= x
) &&
145 (childPtr
->rectWindow
.top
<= y
) &&
146 (childPtr
->rectWindow
.bottom
> y
- yspacing
))
147 break; /* There's a window in there */
149 WIN_UpdateWndPtr(&childPtr
,childPtr
->next
);
151 WIN_ReleaseWndPtr(childPtr
);
152 if (!childPtr
) /* No window was found, so it's OK for us */
154 pt
.x
= x
+ (xspacing
- SYSMETRICS_CXICON
) / 2;
155 pt
.y
= y
- (yspacing
+ SYSMETRICS_CYICON
) / 2;
164 /***********************************************************************
165 * ArrangeIconicWindows16 (USER.170)
167 UINT16 WINAPI
ArrangeIconicWindows16( HWND16 parent
)
169 return ArrangeIconicWindows(parent
);
171 /***********************************************************************
172 * ArrangeIconicWindows (USER32.7)
174 UINT WINAPI
ArrangeIconicWindows( HWND parent
)
178 INT x
, y
, xspacing
, yspacing
;
180 GetClientRect( parent
, &rectParent
);
182 y
= rectParent
.bottom
;
183 xspacing
= SYSMETRICS_CXICONSPACING
;
184 yspacing
= SYSMETRICS_CYICONSPACING
;
186 hwndChild
= GetWindow( parent
, GW_CHILD
);
189 if( IsIconic( hwndChild
) )
191 WND
*wndPtr
= WIN_FindWndPtr(hwndChild
);
193 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
195 SetWindowPos( hwndChild
, 0, x
+ (xspacing
- SYSMETRICS_CXICON
) / 2,
196 y
- yspacing
- SYSMETRICS_CYICON
/2, 0, 0,
197 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
198 if( IsWindow(hwndChild
) )
199 WINPOS_ShowIconTitle(wndPtr
, TRUE
);
200 WIN_ReleaseWndPtr(wndPtr
);
202 if (x
<= rectParent
.right
- xspacing
) x
+= xspacing
;
209 hwndChild
= GetWindow( hwndChild
, GW_HWNDNEXT
);
215 /***********************************************************************
216 * SwitchToThisWindow16 (USER.172)
218 void WINAPI
SwitchToThisWindow16( HWND16 hwnd
, BOOL16 restore
)
220 SwitchToThisWindow( hwnd
, restore
);
224 /***********************************************************************
225 * SwitchToThisWindow (USER32.539)
227 void WINAPI
SwitchToThisWindow( HWND hwnd
, BOOL restore
)
229 ShowWindow( hwnd
, restore
? SW_RESTORE
: SW_SHOWMINIMIZED
);
233 /***********************************************************************
234 * GetWindowRect16 (USER.32)
236 void WINAPI
GetWindowRect16( HWND16 hwnd
, LPRECT16 rect
)
238 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
241 CONV_RECT32TO16( &wndPtr
->rectWindow
, rect
);
242 if (wndPtr
->dwStyle
& WS_CHILD
)
243 MapWindowPoints16( wndPtr
->parent
->hwndSelf
, 0, (POINT16
*)rect
, 2 );
244 WIN_ReleaseWndPtr(wndPtr
);
248 /***********************************************************************
249 * GetWindowRect (USER32.308)
251 BOOL WINAPI
GetWindowRect( HWND hwnd
, LPRECT rect
)
253 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
254 if (!wndPtr
) return FALSE
;
256 *rect
= wndPtr
->rectWindow
;
257 if (wndPtr
->dwStyle
& WS_CHILD
)
258 MapWindowPoints( wndPtr
->parent
->hwndSelf
, 0, (POINT
*)rect
, 2 );
259 WIN_ReleaseWndPtr(wndPtr
);
264 /***********************************************************************
267 BOOL WINAPI
GetWindowRgn ( HWND hwnd
, HRGN hrgn
)
271 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
272 if (!wndPtr
) return (ERROR
);
274 FIXME (win
, "GetWindowRgn: doesn't really do regions\n");
276 memset (&rect
, 0, sizeof(rect
));
278 GetWindowRect ( hwnd
, &rect
);
280 FIXME (win
, "Check whether a valid region here\n");
282 SetRectRgn ( hrgn
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
284 WIN_ReleaseWndPtr(wndPtr
);
285 return (SIMPLEREGION
);
288 /***********************************************************************
291 INT WINAPI
SetWindowRgn( HWND hwnd
, HRGN hrgn
,BOOL bRedraw
)
295 FIXME (win
, "SetWindowRgn: stub\n");
299 /***********************************************************************
302 INT16 WINAPI
SetWindowRgn16( HWND16 hwnd
, HRGN16 hrgn
,BOOL16 bRedraw
)
306 FIXME (win
, "SetWindowRgn16: stub\n");
311 /***********************************************************************
312 * GetClientRect16 (USER.33)
314 void WINAPI
GetClientRect16( HWND16 hwnd
, LPRECT16 rect
)
316 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
318 rect
->left
= rect
->top
= rect
->right
= rect
->bottom
= 0;
321 rect
->right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
322 rect
->bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
324 WIN_ReleaseWndPtr(wndPtr
);
328 /***********************************************************************
329 * GetClientRect (USER.220)
331 BOOL WINAPI
GetClientRect( HWND hwnd
, LPRECT rect
)
333 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
335 rect
->left
= rect
->top
= rect
->right
= rect
->bottom
= 0;
336 if (!wndPtr
) return FALSE
;
337 rect
->right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
338 rect
->bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
340 WIN_ReleaseWndPtr(wndPtr
);
345 /*******************************************************************
346 * ClientToScreen16 (USER.28)
348 void WINAPI
ClientToScreen16( HWND16 hwnd
, LPPOINT16 lppnt
)
350 MapWindowPoints16( hwnd
, 0, lppnt
, 1 );
354 /*******************************************************************
355 * ClientToScreen (USER32.52)
357 BOOL WINAPI
ClientToScreen( HWND hwnd
, LPPOINT lppnt
)
359 MapWindowPoints( hwnd
, 0, lppnt
, 1 );
364 /*******************************************************************
365 * ScreenToClient16 (USER.29)
367 void WINAPI
ScreenToClient16( HWND16 hwnd
, LPPOINT16 lppnt
)
369 MapWindowPoints16( 0, hwnd
, lppnt
, 1 );
373 /*******************************************************************
374 * ScreenToClient (USER32.447)
376 BOOL WINAPI
ScreenToClient( HWND hwnd
, LPPOINT lppnt
)
378 MapWindowPoints( 0, hwnd
, lppnt
, 1 );
383 /***********************************************************************
384 * WINPOS_WindowFromPoint
386 * Find the window and hittest for a given point.
388 INT16
WINPOS_WindowFromPoint( WND
* wndScope
, POINT16 pt
, WND
**ppWnd
)
391 INT16 hittest
= HTERROR
;
396 wndPtr
= WIN_LockWndPtr(wndScope
->child
);
398 if( wndScope
->flags
& WIN_MANAGED
)
400 /* In managed mode we have to check wndScope first as it is also
401 * a window which received the mouse event. */
403 if( wndScope
->dwStyle
& WS_DISABLED
)
408 if( pt
.x
< wndScope
->rectClient
.left
|| pt
.x
>= wndScope
->rectClient
.right
||
409 pt
.y
< wndScope
->rectClient
.top
|| pt
.y
>= wndScope
->rectClient
.bottom
)
412 MapWindowPoints16( GetDesktopWindow16(), wndScope
->hwndSelf
, &xy
, 1 );
418 /* If point is in window, and window is visible, and it */
419 /* is enabled (or it's a top-level window), then explore */
420 /* its children. Otherwise, go to the next window. */
422 if ((wndPtr
->dwStyle
& WS_VISIBLE
) &&
423 (!(wndPtr
->dwStyle
& WS_DISABLED
) ||
424 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)) &&
425 (xy
.x
>= wndPtr
->rectWindow
.left
) &&
426 (xy
.x
< wndPtr
->rectWindow
.right
) &&
427 (xy
.y
>= wndPtr
->rectWindow
.top
) &&
428 (xy
.y
< wndPtr
->rectWindow
.bottom
))
430 *ppWnd
= wndPtr
; /* Got a suitable window */
432 /* If window is minimized or disabled, return at once */
433 if (wndPtr
->dwStyle
& WS_MINIMIZE
)
435 retvalue
= HTCAPTION
;
438 if (wndPtr
->dwStyle
& WS_DISABLED
)
444 /* If point is not in client area, ignore the children */
445 if ((xy
.x
< wndPtr
->rectClient
.left
) ||
446 (xy
.x
>= wndPtr
->rectClient
.right
) ||
447 (xy
.y
< wndPtr
->rectClient
.top
) ||
448 (xy
.y
>= wndPtr
->rectClient
.bottom
)) break;
450 xy
.x
-= wndPtr
->rectClient
.left
;
451 xy
.y
-= wndPtr
->rectClient
.top
;
452 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->child
);
456 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->next
);
461 /* If nothing found, try the scope window */
462 if (!*ppWnd
) *ppWnd
= wndScope
;
464 /* Send the WM_NCHITTEST message (only if to the same task) */
465 if ((*ppWnd
)->hmemTaskQ
== GetFastQueue16())
467 hittest
= (INT16
)SendMessage16( (*ppWnd
)->hwndSelf
, WM_NCHITTEST
,
468 0, MAKELONG( pt
.x
, pt
.y
) );
469 if (hittest
!= HTTRANSPARENT
)
471 retvalue
= hittest
; /* Found the window */
481 /* If no children found in last search, make point relative to parent */
484 xy
.x
+= (*ppWnd
)->rectClient
.left
;
485 xy
.y
+= (*ppWnd
)->rectClient
.top
;
488 /* Restart the search from the next sibling */
489 WIN_UpdateWndPtr(&wndPtr
,(*ppWnd
)->next
);
490 *ppWnd
= (*ppWnd
)->parent
;
494 WIN_ReleaseWndPtr(wndPtr
);
499 /*******************************************************************
500 * WindowFromPoint16 (USER.30)
502 HWND16 WINAPI
WindowFromPoint16( POINT16 pt
)
505 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt
, &pWnd
);
506 WIN_ReleaseDesktop();
507 return pWnd
->hwndSelf
;
511 /*******************************************************************
512 * WindowFromPoint (USER32.582)
514 HWND WINAPI
WindowFromPoint( POINT pt
)
518 CONV_POINT32TO16( &pt
, &pt16
);
519 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16
, &pWnd
);
520 WIN_ReleaseDesktop();
521 return (HWND
)pWnd
->hwndSelf
;
525 /*******************************************************************
526 * ChildWindowFromPoint16 (USER.191)
528 HWND16 WINAPI
ChildWindowFromPoint16( HWND16 hwndParent
, POINT16 pt
)
531 CONV_POINT16TO32( &pt
, &pt32
);
532 return (HWND16
)ChildWindowFromPoint( hwndParent
, pt32
);
536 /*******************************************************************
537 * ChildWindowFromPoint (USER32.49)
539 HWND WINAPI
ChildWindowFromPoint( HWND hwndParent
, POINT pt
)
541 /* pt is in the client coordinates */
543 WND
* wnd
= WIN_FindWndPtr(hwndParent
);
549 /* get client rect fast */
550 rect
.top
= rect
.left
= 0;
551 rect
.right
= wnd
->rectClient
.right
- wnd
->rectClient
.left
;
552 rect
.bottom
= wnd
->rectClient
.bottom
- wnd
->rectClient
.top
;
554 if (!PtInRect( &rect
, pt
))
559 WIN_UpdateWndPtr(&wnd
,wnd
->child
);
562 if (PtInRect( &wnd
->rectWindow
, pt
))
564 retvalue
= wnd
->hwndSelf
;
567 WIN_UpdateWndPtr(&wnd
,wnd
->next
);
569 retvalue
= hwndParent
;
571 WIN_ReleaseWndPtr(wnd
);
575 /*******************************************************************
576 * ChildWindowFromPointEx16 (USER.50)
578 HWND16 WINAPI
ChildWindowFromPointEx16( HWND16 hwndParent
, POINT16 pt
, UINT16 uFlags
)
581 CONV_POINT16TO32( &pt
, &pt32
);
582 return (HWND16
)ChildWindowFromPointEx( hwndParent
, pt32
, uFlags
);
586 /*******************************************************************
587 * ChildWindowFromPointEx32 (USER32.50)
589 HWND WINAPI
ChildWindowFromPointEx( HWND hwndParent
, POINT pt
,
592 /* pt is in the client coordinates */
594 WND
* wnd
= WIN_FindWndPtr(hwndParent
);
600 /* get client rect fast */
601 rect
.top
= rect
.left
= 0;
602 rect
.right
= wnd
->rectClient
.right
- wnd
->rectClient
.left
;
603 rect
.bottom
= wnd
->rectClient
.bottom
- wnd
->rectClient
.top
;
605 if (!PtInRect( &rect
, pt
))
610 WIN_UpdateWndPtr(&wnd
,wnd
->child
);
614 if (PtInRect( &wnd
->rectWindow
, pt
)) {
615 if ( (uFlags
& CWP_SKIPINVISIBLE
) &&
616 !(wnd
->dwStyle
& WS_VISIBLE
) );
617 else if ( (uFlags
& CWP_SKIPDISABLED
) &&
618 (wnd
->dwStyle
& WS_DISABLED
) );
619 else if ( (uFlags
& CWP_SKIPTRANSPARENT
) &&
620 (wnd
->dwExStyle
& WS_EX_TRANSPARENT
) );
623 retvalue
= wnd
->hwndSelf
;
626 WIN_UpdateWndPtr(&wnd
,wnd
->next
);
630 retvalue
= hwndParent
;
632 WIN_ReleaseWndPtr(wnd
);
637 /*******************************************************************
638 * WINPOS_GetWinOffset
640 * Calculate the offset between the origin of the two windows. Used
641 * to implement MapWindowPoints.
643 static void WINPOS_GetWinOffset( HWND hwndFrom
, HWND hwndTo
,
648 offset
->x
= offset
->y
= 0;
649 if (hwndFrom
== hwndTo
) return;
651 /* Translate source window origin to screen coords */
654 if (!(wndPtr
= WIN_FindWndPtr( hwndFrom
)))
656 ERR(win
,"bad hwndFrom = %04x\n",hwndFrom
);
659 while (wndPtr
->parent
)
661 offset
->x
+= wndPtr
->rectClient
.left
;
662 offset
->y
+= wndPtr
->rectClient
.top
;
663 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->parent
);
665 WIN_ReleaseWndPtr(wndPtr
);
668 /* Translate origin to destination window coords */
671 if (!(wndPtr
= WIN_FindWndPtr( hwndTo
)))
673 ERR(win
,"bad hwndTo = %04x\n", hwndTo
);
676 while (wndPtr
->parent
)
678 offset
->x
-= wndPtr
->rectClient
.left
;
679 offset
->y
-= wndPtr
->rectClient
.top
;
680 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->parent
);
682 WIN_ReleaseWndPtr(wndPtr
);
687 /*******************************************************************
688 * MapWindowPoints16 (USER.258)
690 void WINAPI
MapWindowPoints16( HWND16 hwndFrom
, HWND16 hwndTo
,
691 LPPOINT16 lppt
, UINT16 count
)
695 WINPOS_GetWinOffset( hwndFrom
, hwndTo
, &offset
);
705 /*******************************************************************
706 * MapWindowPoints (USER32.386)
708 INT WINAPI
MapWindowPoints( HWND hwndFrom
, HWND hwndTo
,
709 LPPOINT lppt
, UINT count
)
713 WINPOS_GetWinOffset( hwndFrom
, hwndTo
, &offset
);
720 return MAKELONG( LOWORD(offset
.x
), LOWORD(offset
.y
) );
724 /***********************************************************************
725 * IsIconic16 (USER.31)
727 BOOL16 WINAPI
IsIconic16(HWND16 hWnd
)
729 return IsIconic(hWnd
);
733 /***********************************************************************
734 * IsIconic (USER32.345)
736 BOOL WINAPI
IsIconic(HWND hWnd
)
739 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
740 if (wndPtr
== NULL
) return FALSE
;
741 retvalue
= (wndPtr
->dwStyle
& WS_MINIMIZE
) != 0;
742 WIN_ReleaseWndPtr(wndPtr
);
747 /***********************************************************************
748 * IsZoomed (USER.272)
750 BOOL16 WINAPI
IsZoomed16(HWND16 hWnd
)
752 return IsZoomed(hWnd
);
756 /***********************************************************************
757 * IsZoomed (USER.352)
759 BOOL WINAPI
IsZoomed(HWND hWnd
)
762 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
763 if (wndPtr
== NULL
) return FALSE
;
764 retvalue
= (wndPtr
->dwStyle
& WS_MAXIMIZE
) != 0;
765 WIN_ReleaseWndPtr(wndPtr
);
770 /*******************************************************************
771 * GetActiveWindow (USER.60)
773 HWND16 WINAPI
GetActiveWindow16(void)
775 return (HWND16
)GetActiveWindow();
778 /*******************************************************************
779 * GetActiveWindow (USER32.205)
781 HWND WINAPI
GetActiveWindow(void)
783 MESSAGEQUEUE
*pCurMsgQ
= 0;
786 /* Get the messageQ for the current thread */
787 if (!(pCurMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( GetFastQueue16() )))
789 WARN( win
, "\tCurrent message queue not found. Exiting!\n" );
793 /* Return the current active window from the perQ data of the current message Q */
794 hwndActive
= PERQDATA_GetActiveWnd( pCurMsgQ
->pQData
);
796 QUEUE_Unlock( pCurMsgQ
);
801 /*******************************************************************
804 static BOOL
WINPOS_CanActivate(WND
* pWnd
)
806 if( pWnd
&& ((pWnd
->dwStyle
& (WS_DISABLED
| WS_VISIBLE
| WS_CHILD
))
807 == WS_VISIBLE
) ) return TRUE
;
812 /*******************************************************************
813 * SetActiveWindow16 (USER.59)
815 HWND16 WINAPI
SetActiveWindow16( HWND16 hwnd
)
817 return SetActiveWindow(hwnd
);
821 /*******************************************************************
822 * SetActiveWindow (USER32.463)
824 HWND WINAPI
SetActiveWindow( HWND hwnd
)
827 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
828 MESSAGEQUEUE
*pMsgQ
= 0, *pCurMsgQ
= 0;
830 if ( !WINPOS_CanActivate(wndPtr
) )
836 /* Get the messageQ for the current thread */
837 if (!(pCurMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( GetFastQueue16() )))
839 WARN( win
, "\tCurrent message queue not found. Exiting!\n" );
843 /* Retrieve the message queue associated with this window */
844 pMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( wndPtr
->hmemTaskQ
);
847 WARN( win
, "\tWindow message queue not found. Exiting!\n" );
851 /* Make sure that the window is associated with the calling threads
852 * message queue. It must share the same perQ data.
855 if ( pCurMsgQ
->pQData
!= pMsgQ
->pQData
)
858 /* Save current active window */
859 prev
= PERQDATA_GetActiveWnd( pMsgQ
->pQData
);
861 WINPOS_SetActiveWindow( hwnd
, 0, 0 );
864 /* Unlock the queues before returning */
866 QUEUE_Unlock( pMsgQ
);
868 QUEUE_Unlock( pCurMsgQ
);
871 WIN_ReleaseWndPtr(wndPtr
);
876 /*******************************************************************
877 * GetForegroundWindow16 (USER.608)
879 HWND16 WINAPI
GetForegroundWindow16(void)
881 return (HWND16
)GetForegroundWindow();
885 /*******************************************************************
886 * SetForegroundWindow16 (USER.609)
888 BOOL16 WINAPI
SetForegroundWindow16( HWND16 hwnd
)
890 return SetForegroundWindow( hwnd
);
894 /*******************************************************************
895 * GetForegroundWindow (USER32.241)
897 HWND WINAPI
GetForegroundWindow(void)
899 return GetActiveWindow();
903 /*******************************************************************
904 * SetForegroundWindow (USER32.482)
906 BOOL WINAPI
SetForegroundWindow( HWND hwnd
)
908 SetActiveWindow( hwnd
);
913 /*******************************************************************
914 * GetShellWindow16 (USER.600)
916 HWND16 WINAPI
GetShellWindow16(void)
918 return GetShellWindow();
921 /*******************************************************************
922 * SetShellWindow (USER32.504)
924 HWND WINAPI
SetShellWindow(HWND hwndshell
)
925 { WARN(win
, "(hWnd=%08x) semi stub\n",hwndshell
);
927 hGlobalShellWindow
= hwndshell
;
928 return hGlobalShellWindow
;
932 /*******************************************************************
933 * GetShellWindow (USER32.287)
935 HWND WINAPI
GetShellWindow(void)
936 { WARN(win
, "(hWnd=%x) semi stub\n",hGlobalShellWindow
);
938 return hGlobalShellWindow
;
942 /***********************************************************************
943 * BringWindowToTop16 (USER.45)
945 BOOL16 WINAPI
BringWindowToTop16( HWND16 hwnd
)
947 return BringWindowToTop(hwnd
);
951 /***********************************************************************
952 * BringWindowToTop (USER32.11)
954 BOOL WINAPI
BringWindowToTop( HWND hwnd
)
956 return SetWindowPos( hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
);
960 /***********************************************************************
961 * MoveWindow16 (USER.56)
963 BOOL16 WINAPI
MoveWindow16( HWND16 hwnd
, INT16 x
, INT16 y
, INT16 cx
, INT16 cy
,
966 return MoveWindow(hwnd
,x
,y
,cx
,cy
,repaint
);
970 /***********************************************************************
971 * MoveWindow (USER32.399)
973 BOOL WINAPI
MoveWindow( HWND hwnd
, INT x
, INT y
, INT cx
, INT cy
,
976 int flags
= SWP_NOZORDER
| SWP_NOACTIVATE
;
977 if (!repaint
) flags
|= SWP_NOREDRAW
;
978 TRACE(win
, "%04x %d,%d %dx%d %d\n",
979 hwnd
, x
, y
, cx
, cy
, repaint
);
980 return SetWindowPos( hwnd
, 0, x
, y
, cx
, cy
, flags
);
983 /***********************************************************************
984 * WINPOS_InitInternalPos
986 static LPINTERNALPOS
WINPOS_InitInternalPos( WND
* wnd
, POINT pt
,
989 LPINTERNALPOS lpPos
= (LPINTERNALPOS
) GetPropA( wnd
->hwndSelf
,
993 /* this happens when the window is minimized/maximized
994 * for the first time (rectWindow is not adjusted yet) */
996 lpPos
= HeapAlloc( SystemHeap
, 0, sizeof(INTERNALPOS
) );
997 if( !lpPos
) return NULL
;
999 SetPropA( wnd
->hwndSelf
, atomInternalPos
, (HANDLE
)lpPos
);
1000 lpPos
->hwndIconTitle
= 0; /* defer until needs to be shown */
1001 CONV_RECT32TO16( &wnd
->rectWindow
, &lpPos
->rectNormal
);
1002 *(UINT
*)&lpPos
->ptIconPos
= *(UINT
*)&lpPos
->ptMaxPos
= 0xFFFFFFFF;
1005 if( wnd
->dwStyle
& WS_MINIMIZE
)
1006 CONV_POINT32TO16( &pt
, &lpPos
->ptIconPos
);
1007 else if( wnd
->dwStyle
& WS_MAXIMIZE
)
1008 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1009 else if( restoreRect
)
1010 CONV_RECT32TO16( restoreRect
, &lpPos
->rectNormal
);
1015 /***********************************************************************
1016 * WINPOS_RedrawIconTitle
1018 BOOL
WINPOS_RedrawIconTitle( HWND hWnd
)
1020 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)GetPropA( hWnd
, atomInternalPos
);
1023 if( lpPos
->hwndIconTitle
)
1025 SendMessageA( lpPos
->hwndIconTitle
, WM_SHOWWINDOW
, TRUE
, 0);
1026 InvalidateRect( lpPos
->hwndIconTitle
, NULL
, TRUE
);
1033 /***********************************************************************
1034 * WINPOS_ShowIconTitle
1036 BOOL
WINPOS_ShowIconTitle( WND
* pWnd
, BOOL bShow
)
1038 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)GetPropA( pWnd
->hwndSelf
, atomInternalPos
);
1040 if( lpPos
&& !(pWnd
->flags
& WIN_MANAGED
))
1042 HWND16 hWnd
= lpPos
->hwndIconTitle
;
1044 TRACE(win
,"0x%04x %i\n", pWnd
->hwndSelf
, (bShow
!= 0) );
1047 lpPos
->hwndIconTitle
= hWnd
= ICONTITLE_Create( pWnd
);
1050 pWnd
= WIN_FindWndPtr(hWnd
);
1052 if( !(pWnd
->dwStyle
& WS_VISIBLE
) )
1054 SendMessageA( hWnd
, WM_SHOWWINDOW
, TRUE
, 0 );
1055 SetWindowPos( hWnd
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
1056 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_SHOWWINDOW
);
1058 WIN_ReleaseWndPtr(pWnd
);
1060 else ShowWindow( hWnd
, SW_HIDE
);
1065 /*******************************************************************
1066 * WINPOS_GetMinMaxInfo
1068 * Get the minimized and maximized information for a window.
1070 void WINPOS_GetMinMaxInfo( WND
*wndPtr
, POINT
*maxSize
, POINT
*maxPos
,
1071 POINT
*minTrack
, POINT
*maxTrack
)
1073 LPINTERNALPOS lpPos
;
1077 /* Compute default values */
1079 MinMax
.ptMaxSize
.x
= SYSMETRICS_CXSCREEN
;
1080 MinMax
.ptMaxSize
.y
= SYSMETRICS_CYSCREEN
;
1081 MinMax
.ptMinTrackSize
.x
= SYSMETRICS_CXMINTRACK
;
1082 MinMax
.ptMinTrackSize
.y
= SYSMETRICS_CYMINTRACK
;
1083 MinMax
.ptMaxTrackSize
.x
= SYSMETRICS_CXSCREEN
;
1084 MinMax
.ptMaxTrackSize
.y
= SYSMETRICS_CYSCREEN
;
1086 if (wndPtr
->flags
& WIN_MANAGED
) xinc
= yinc
= 0;
1087 else if (HAS_DLGFRAME( wndPtr
->dwStyle
, wndPtr
->dwExStyle
))
1089 xinc
= SYSMETRICS_CXDLGFRAME
;
1090 yinc
= SYSMETRICS_CYDLGFRAME
;
1095 if (HAS_THICKFRAME(wndPtr
->dwStyle
))
1097 xinc
+= SYSMETRICS_CXFRAME
;
1098 yinc
+= SYSMETRICS_CYFRAME
;
1100 if (wndPtr
->dwStyle
& WS_BORDER
)
1102 xinc
+= SYSMETRICS_CXBORDER
;
1103 yinc
+= SYSMETRICS_CYBORDER
;
1106 MinMax
.ptMaxSize
.x
+= 2 * xinc
;
1107 MinMax
.ptMaxSize
.y
+= 2 * yinc
;
1109 lpPos
= (LPINTERNALPOS
)GetPropA( wndPtr
->hwndSelf
, atomInternalPos
);
1110 if( lpPos
&& !EMPTYPOINT(lpPos
->ptMaxPos
) )
1111 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &MinMax
.ptMaxPosition
);
1114 MinMax
.ptMaxPosition
.x
= -xinc
;
1115 MinMax
.ptMaxPosition
.y
= -yinc
;
1118 SendMessageA( wndPtr
->hwndSelf
, WM_GETMINMAXINFO
, 0, (LPARAM
)&MinMax
);
1120 /* Some sanity checks */
1122 TRACE(win
,"%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1123 MinMax
.ptMaxSize
.x
, MinMax
.ptMaxSize
.y
,
1124 MinMax
.ptMaxPosition
.x
, MinMax
.ptMaxPosition
.y
,
1125 MinMax
.ptMaxTrackSize
.x
, MinMax
.ptMaxTrackSize
.y
,
1126 MinMax
.ptMinTrackSize
.x
, MinMax
.ptMinTrackSize
.y
);
1127 MinMax
.ptMaxTrackSize
.x
= MAX( MinMax
.ptMaxTrackSize
.x
,
1128 MinMax
.ptMinTrackSize
.x
);
1129 MinMax
.ptMaxTrackSize
.y
= MAX( MinMax
.ptMaxTrackSize
.y
,
1130 MinMax
.ptMinTrackSize
.y
);
1132 if (maxSize
) *maxSize
= MinMax
.ptMaxSize
;
1133 if (maxPos
) *maxPos
= MinMax
.ptMaxPosition
;
1134 if (minTrack
) *minTrack
= MinMax
.ptMinTrackSize
;
1135 if (maxTrack
) *maxTrack
= MinMax
.ptMaxTrackSize
;
1138 /***********************************************************************
1139 * WINPOS_MinMaximize
1141 * Fill in lpRect and return additional flags to be used with SetWindowPos().
1142 * This function assumes that 'cmd' is different from the current window
1145 UINT
WINPOS_MinMaximize( WND
* wndPtr
, UINT16 cmd
, LPRECT16 lpRect
)
1150 LPINTERNALPOS lpPos
;
1152 TRACE(win
,"0x%04x %u\n", wndPtr
->hwndSelf
, cmd
);
1154 size
.x
= wndPtr
->rectWindow
.left
;
1155 size
.y
= wndPtr
->rectWindow
.top
;
1157 lpPos
= WINPOS_InitInternalPos( wndPtr
, size
, &wndPtr
->rectWindow
);
1159 if (lpPos
&& !HOOK_CallHooks16(WH_CBT
, HCBT_MINMAX
, wndPtr
->hwndSelf
, cmd
))
1161 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1163 if( !SendMessageA( wndPtr
->hwndSelf
, WM_QUERYOPEN
, 0, 0L ) )
1164 return (SWP_NOSIZE
| SWP_NOMOVE
);
1165 swpFlags
|= SWP_NOCOPYBITS
;
1170 if( wndPtr
->dwStyle
& WS_MAXIMIZE
)
1172 wndPtr
->flags
|= WIN_RESTORE_MAX
;
1173 wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
1176 wndPtr
->flags
&= ~WIN_RESTORE_MAX
;
1177 wndPtr
->dwStyle
|= WS_MINIMIZE
;
1179 if( wndPtr
->flags
& WIN_NATIVE
)
1180 if( wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, TRUE
) )
1181 swpFlags
|= MINMAX_NOSWP
;
1183 lpPos
->ptIconPos
= WINPOS_FindIconPos( wndPtr
, lpPos
->ptIconPos
);
1185 SetRect16( lpRect
, lpPos
->ptIconPos
.x
, lpPos
->ptIconPos
.y
,
1186 SYSMETRICS_CXICON
, SYSMETRICS_CYICON
);
1187 swpFlags
|= SWP_NOCOPYBITS
;
1191 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &pt
);
1192 WINPOS_GetMinMaxInfo( wndPtr
, &size
, &pt
, NULL
, NULL
);
1193 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1195 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1197 if( wndPtr
->flags
& WIN_NATIVE
)
1198 if( wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, FALSE
) )
1199 swpFlags
|= MINMAX_NOSWP
;
1201 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
1202 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
1204 wndPtr
->dwStyle
|= WS_MAXIMIZE
;
1206 SetRect16( lpRect
, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
,
1211 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1213 if( wndPtr
->flags
& WIN_NATIVE
)
1214 if( wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, FALSE
) )
1215 swpFlags
|= MINMAX_NOSWP
;
1217 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
1218 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
1220 if( wndPtr
->flags
& WIN_RESTORE_MAX
)
1222 /* Restore to maximized position */
1223 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &pt
);
1224 WINPOS_GetMinMaxInfo( wndPtr
, &size
, &pt
, NULL
, NULL
);
1225 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1226 wndPtr
->dwStyle
|= WS_MAXIMIZE
;
1227 SetRect16( lpRect
, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
, size
.x
, size
.y
);
1232 if( !(wndPtr
->dwStyle
& WS_MAXIMIZE
) ) return (UINT16
)(-1);
1233 else wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
1235 /* Restore to normal position */
1237 *lpRect
= lpPos
->rectNormal
;
1238 lpRect
->right
-= lpRect
->left
;
1239 lpRect
->bottom
-= lpRect
->top
;
1243 } else swpFlags
|= SWP_NOSIZE
| SWP_NOMOVE
;
1247 /***********************************************************************
1248 * ShowWindowAsync (USER32.535)
1250 * doesn't wait; returns immediately.
1251 * used by threads to toggle windows in other (possibly hanging) threads
1253 BOOL WINAPI
ShowWindowAsync( HWND hwnd
, INT cmd
)
1255 /* FIXME: does ShowWindow() return immediately ? */
1256 return ShowWindow(hwnd
, cmd
);
1260 /***********************************************************************
1261 * ShowWindow16 (USER.42)
1263 BOOL16 WINAPI
ShowWindow16( HWND16 hwnd
, INT16 cmd
)
1265 return ShowWindow(hwnd
,cmd
);
1269 /***********************************************************************
1270 * ShowWindow (USER32.534)
1272 BOOL WINAPI
ShowWindow( HWND hwnd
, INT cmd
)
1274 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
1275 BOOL wasVisible
, showFlag
;
1276 RECT16 newPos
= {0, 0, 0, 0};
1279 if (!wndPtr
) return FALSE
;
1281 TRACE(win
,"hwnd=%04x, cmd=%d\n", hwnd
, cmd
);
1283 wasVisible
= (wndPtr
->dwStyle
& WS_VISIBLE
) != 0;
1288 if (!wasVisible
) goto END
;;
1289 swp
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
|
1290 SWP_NOACTIVATE
| SWP_NOZORDER
;
1291 if ((hwnd
== GetFocus()) || IsChild( hwnd
, GetFocus()))
1293 /* Revert focus to parent */
1294 SetFocus( GetParent(hwnd
) );
1298 case SW_SHOWMINNOACTIVE
:
1299 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1301 case SW_SHOWMINIMIZED
:
1302 swp
|= SWP_SHOWWINDOW
;
1305 swp
|= SWP_FRAMECHANGED
;
1306 if( !(wndPtr
->dwStyle
& WS_MINIMIZE
) )
1307 swp
|= WINPOS_MinMaximize( wndPtr
, SW_MINIMIZE
, &newPos
);
1308 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1311 case SW_SHOWMAXIMIZED
: /* same as SW_MAXIMIZE */
1312 swp
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
1313 if( !(wndPtr
->dwStyle
& WS_MAXIMIZE
) )
1314 swp
|= WINPOS_MinMaximize( wndPtr
, SW_MAXIMIZE
, &newPos
);
1315 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1319 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1322 swp
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
1325 case SW_SHOWNOACTIVATE
:
1326 swp
|= SWP_NOZORDER
;
1327 if (GetActiveWindow()) swp
|= SWP_NOACTIVATE
;
1329 case SW_SHOWNORMAL
: /* same as SW_NORMAL: */
1330 case SW_SHOWDEFAULT
: /* FIXME: should have its own handler */
1332 swp
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
1334 if( wndPtr
->dwStyle
& (WS_MINIMIZE
| WS_MAXIMIZE
) )
1335 swp
|= WINPOS_MinMaximize( wndPtr
, SW_RESTORE
, &newPos
);
1336 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1340 showFlag
= (cmd
!= SW_HIDE
);
1341 if (showFlag
!= wasVisible
)
1343 SendMessageA( hwnd
, WM_SHOWWINDOW
, showFlag
, 0 );
1344 if (!IsWindow( hwnd
)) goto END
;
1347 if ((wndPtr
->dwStyle
& WS_CHILD
) &&
1348 !IsWindowVisible( wndPtr
->parent
->hwndSelf
) &&
1349 (swp
& (SWP_NOSIZE
| SWP_NOMOVE
)) == (SWP_NOSIZE
| SWP_NOMOVE
) )
1351 /* Don't call SetWindowPos() on invisible child windows */
1352 if (cmd
== SW_HIDE
) wndPtr
->dwStyle
&= ~WS_VISIBLE
;
1353 else wndPtr
->dwStyle
|= WS_VISIBLE
;
1357 /* We can't activate a child window */
1358 if (wndPtr
->dwStyle
& WS_CHILD
) swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1359 if (!(swp
& MINMAX_NOSWP
))
1360 SetWindowPos( hwnd
, HWND_TOP
, newPos
.left
, newPos
.top
,
1361 newPos
.right
, newPos
.bottom
, LOWORD(swp
) );
1362 if (!IsWindow( hwnd
)) goto END
;
1363 else if( wndPtr
->dwStyle
& WS_MINIMIZE
) WINPOS_ShowIconTitle( wndPtr
, TRUE
);
1366 if (wndPtr
->flags
& WIN_NEED_SIZE
)
1368 /* should happen only in CreateWindowEx() */
1369 int wParam
= SIZE_RESTORED
;
1371 wndPtr
->flags
&= ~WIN_NEED_SIZE
;
1372 if (wndPtr
->dwStyle
& WS_MAXIMIZE
) wParam
= SIZE_MAXIMIZED
;
1373 else if (wndPtr
->dwStyle
& WS_MINIMIZE
) wParam
= SIZE_MINIMIZED
;
1374 SendMessageA( hwnd
, WM_SIZE
, wParam
,
1375 MAKELONG(wndPtr
->rectClient
.right
-wndPtr
->rectClient
.left
,
1376 wndPtr
->rectClient
.bottom
-wndPtr
->rectClient
.top
));
1377 SendMessageA( hwnd
, WM_MOVE
, 0,
1378 MAKELONG(wndPtr
->rectClient
.left
, wndPtr
->rectClient
.top
) );
1382 WIN_ReleaseWndPtr(wndPtr
);
1387 /***********************************************************************
1388 * GetInternalWindowPos16 (USER.460)
1390 UINT16 WINAPI
GetInternalWindowPos16( HWND16 hwnd
, LPRECT16 rectWnd
,
1393 WINDOWPLACEMENT16 wndpl
;
1394 if (GetWindowPlacement16( hwnd
, &wndpl
))
1396 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
1397 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
1398 return wndpl
.showCmd
;
1404 /***********************************************************************
1405 * GetInternalWindowPos (USER32.245)
1407 UINT WINAPI
GetInternalWindowPos( HWND hwnd
, LPRECT rectWnd
,
1410 WINDOWPLACEMENT wndpl
;
1411 if (GetWindowPlacement( hwnd
, &wndpl
))
1413 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
1414 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
1415 return wndpl
.showCmd
;
1420 /***********************************************************************
1421 * GetWindowPlacement16 (USER.370)
1423 BOOL16 WINAPI
GetWindowPlacement16( HWND16 hwnd
, WINDOWPLACEMENT16
*wndpl
)
1425 WND
*pWnd
= WIN_FindWndPtr( hwnd
);
1426 LPINTERNALPOS lpPos
;
1428 if(!pWnd
) return FALSE
;
1430 lpPos
= (LPINTERNALPOS
)WINPOS_InitInternalPos( pWnd
,
1431 *(LPPOINT
)&pWnd
->rectWindow
.left
, &pWnd
->rectWindow
);
1432 wndpl
->length
= sizeof(*wndpl
);
1433 if( pWnd
->dwStyle
& WS_MINIMIZE
)
1434 wndpl
->showCmd
= SW_SHOWMINIMIZED
;
1436 wndpl
->showCmd
= ( pWnd
->dwStyle
& WS_MAXIMIZE
)
1437 ? SW_SHOWMAXIMIZED
: SW_SHOWNORMAL
;
1438 if( pWnd
->flags
& WIN_RESTORE_MAX
)
1439 wndpl
->flags
= WPF_RESTORETOMAXIMIZED
;
1442 wndpl
->ptMinPosition
= lpPos
->ptIconPos
;
1443 wndpl
->ptMaxPosition
= lpPos
->ptMaxPos
;
1444 wndpl
->rcNormalPosition
= lpPos
->rectNormal
;
1446 WIN_ReleaseWndPtr(pWnd
);
1451 /***********************************************************************
1452 * GetWindowPlacement (USER32.307)
1455 * Fails if wndpl->length of Win95 (!) apps is invalid.
1457 BOOL WINAPI
GetWindowPlacement( HWND hwnd
, WINDOWPLACEMENT
*pwpl32
)
1461 WINDOWPLACEMENT16 wpl
;
1462 wpl
.length
= sizeof(wpl
);
1463 if( GetWindowPlacement16( hwnd
, &wpl
) )
1465 pwpl32
->length
= sizeof(*pwpl32
);
1466 pwpl32
->flags
= wpl
.flags
;
1467 pwpl32
->showCmd
= wpl
.showCmd
;
1468 CONV_POINT16TO32( &wpl
.ptMinPosition
, &pwpl32
->ptMinPosition
);
1469 CONV_POINT16TO32( &wpl
.ptMaxPosition
, &pwpl32
->ptMaxPosition
);
1470 CONV_RECT16TO32( &wpl
.rcNormalPosition
, &pwpl32
->rcNormalPosition
);
1478 /***********************************************************************
1479 * WINPOS_SetPlacement
1481 static BOOL
WINPOS_SetPlacement( HWND hwnd
, const WINDOWPLACEMENT16
*wndpl
,
1484 WND
*pWnd
= WIN_FindWndPtr( hwnd
);
1487 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)WINPOS_InitInternalPos( pWnd
,
1488 *(LPPOINT
)&pWnd
->rectWindow
.left
, &pWnd
->rectWindow
);
1490 if( flags
& PLACE_MIN
) lpPos
->ptIconPos
= wndpl
->ptMinPosition
;
1491 if( flags
& PLACE_MAX
) lpPos
->ptMaxPos
= wndpl
->ptMaxPosition
;
1492 if( flags
& PLACE_RECT
) lpPos
->rectNormal
= wndpl
->rcNormalPosition
;
1494 if( pWnd
->dwStyle
& WS_MINIMIZE
)
1496 WINPOS_ShowIconTitle( pWnd
, FALSE
);
1497 if( wndpl
->flags
& WPF_SETMINPOSITION
&& !EMPTYPOINT(lpPos
->ptIconPos
))
1498 SetWindowPos( hwnd
, 0, lpPos
->ptIconPos
.x
, lpPos
->ptIconPos
.y
,
1499 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1501 else if( pWnd
->dwStyle
& WS_MAXIMIZE
)
1503 if( !EMPTYPOINT(lpPos
->ptMaxPos
) )
1504 SetWindowPos( hwnd
, 0, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
,
1505 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1507 else if( flags
& PLACE_RECT
)
1508 SetWindowPos( hwnd
, 0, lpPos
->rectNormal
.left
, lpPos
->rectNormal
.top
,
1509 lpPos
->rectNormal
.right
- lpPos
->rectNormal
.left
,
1510 lpPos
->rectNormal
.bottom
- lpPos
->rectNormal
.top
,
1511 SWP_NOZORDER
| SWP_NOACTIVATE
);
1513 ShowWindow( hwnd
, wndpl
->showCmd
);
1514 if( IsWindow(hwnd
) && pWnd
->dwStyle
& WS_MINIMIZE
)
1516 if( pWnd
->dwStyle
& WS_VISIBLE
) WINPOS_ShowIconTitle( pWnd
, TRUE
);
1518 /* SDK: ...valid only the next time... */
1519 if( wndpl
->flags
& WPF_RESTORETOMAXIMIZED
) pWnd
->flags
|= WIN_RESTORE_MAX
;
1521 WIN_ReleaseWndPtr(pWnd
);
1528 /***********************************************************************
1529 * SetWindowPlacement16 (USER.371)
1531 BOOL16 WINAPI
SetWindowPlacement16(HWND16 hwnd
, const WINDOWPLACEMENT16
*wndpl
)
1533 return WINPOS_SetPlacement( hwnd
, wndpl
,
1534 PLACE_MIN
| PLACE_MAX
| PLACE_RECT
);
1537 /***********************************************************************
1538 * SetWindowPlacement (USER32.519)
1541 * Fails if wndpl->length of Win95 (!) apps is invalid.
1543 BOOL WINAPI
SetWindowPlacement( HWND hwnd
, const WINDOWPLACEMENT
*pwpl32
)
1547 WINDOWPLACEMENT16 wpl
;
1549 wpl
.length
= sizeof(WINDOWPLACEMENT16
);
1550 wpl
.flags
= pwpl32
->flags
;
1551 wpl
.showCmd
= pwpl32
->showCmd
;
1552 wpl
.ptMinPosition
.x
= pwpl32
->ptMinPosition
.x
;
1553 wpl
.ptMinPosition
.y
= pwpl32
->ptMinPosition
.y
;
1554 wpl
.ptMaxPosition
.x
= pwpl32
->ptMaxPosition
.x
;
1555 wpl
.ptMaxPosition
.y
= pwpl32
->ptMaxPosition
.y
;
1556 wpl
.rcNormalPosition
.left
= pwpl32
->rcNormalPosition
.left
;
1557 wpl
.rcNormalPosition
.top
= pwpl32
->rcNormalPosition
.top
;
1558 wpl
.rcNormalPosition
.right
= pwpl32
->rcNormalPosition
.right
;
1559 wpl
.rcNormalPosition
.bottom
= pwpl32
->rcNormalPosition
.bottom
;
1561 return WINPOS_SetPlacement( hwnd
, &wpl
, PLACE_MIN
| PLACE_MAX
| PLACE_RECT
);
1567 /***********************************************************************
1568 * SetInternalWindowPos16 (USER.461)
1570 void WINAPI
SetInternalWindowPos16( HWND16 hwnd
, UINT16 showCmd
,
1571 LPRECT16 rect
, LPPOINT16 pt
)
1573 if( IsWindow16(hwnd
) )
1575 WINDOWPLACEMENT16 wndpl
;
1578 wndpl
.length
= sizeof(wndpl
);
1579 wndpl
.showCmd
= showCmd
;
1580 wndpl
.flags
= flags
= 0;
1585 wndpl
.flags
|= WPF_SETMINPOSITION
;
1586 wndpl
.ptMinPosition
= *pt
;
1590 flags
|= PLACE_RECT
;
1591 wndpl
.rcNormalPosition
= *rect
;
1593 WINPOS_SetPlacement( hwnd
, &wndpl
, flags
);
1598 /***********************************************************************
1599 * SetInternalWindowPos (USER32.483)
1601 void WINAPI
SetInternalWindowPos( HWND hwnd
, UINT showCmd
,
1602 LPRECT rect
, LPPOINT pt
)
1604 if( IsWindow(hwnd
) )
1606 WINDOWPLACEMENT16 wndpl
;
1609 wndpl
.length
= sizeof(wndpl
);
1610 wndpl
.showCmd
= showCmd
;
1611 wndpl
.flags
= flags
= 0;
1616 wndpl
.flags
|= WPF_SETMINPOSITION
;
1617 CONV_POINT32TO16( pt
, &wndpl
.ptMinPosition
);
1621 flags
|= PLACE_RECT
;
1622 CONV_RECT32TO16( rect
, &wndpl
.rcNormalPosition
);
1624 WINPOS_SetPlacement( hwnd
, &wndpl
, flags
);
1628 /*******************************************************************
1629 * WINPOS_SetActiveWindow
1631 * SetActiveWindow() back-end. This is the only function that
1632 * can assign active status to a window. It must be called only
1633 * for the top level windows.
1635 BOOL
WINPOS_SetActiveWindow( HWND hWnd
, BOOL fMouse
, BOOL fChangeFocus
)
1637 CBTACTIVATESTRUCT16
* cbtStruct
;
1638 WND
* wndPtr
=0, *wndTemp
;
1639 HQUEUE16 hOldActiveQueue
, hNewActiveQueue
;
1640 MESSAGEQUEUE
*pOldActiveQueue
= 0, *pNewActiveQueue
= 0;
1642 HWND hwndActive
= 0;
1645 /* Get current active window from the active queue */
1648 pOldActiveQueue
= QUEUE_Lock( hActiveQueue
);
1649 if ( pOldActiveQueue
)
1650 hwndActive
= PERQDATA_GetActiveWnd( pOldActiveQueue
->pQData
);
1653 /* paranoid checks */
1654 if( hWnd
== GetDesktopWindow() || (bRet
= (hWnd
== hwndActive
)) )
1657 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1660 wndPtr
= WIN_FindWndPtr(hWnd
);
1661 hOldActiveQueue
= hActiveQueue
;
1663 if( (wndTemp
= WIN_FindWndPtr(hwndActive
)) )
1665 wIconized
= HIWORD(wndTemp
->dwStyle
& WS_MINIMIZE
);
1666 WIN_ReleaseWndPtr(wndTemp
);
1669 TRACE(win
,"no current active window.\n");
1671 /* call CBT hook chain */
1672 if ((cbtStruct
= SEGPTR_NEW(CBTACTIVATESTRUCT16
)))
1674 cbtStruct
->fMouse
= fMouse
;
1675 cbtStruct
->hWndActive
= hwndActive
;
1676 bRet
= (BOOL
)HOOK_CallHooks16( WH_CBT
, HCBT_ACTIVATE
, (WPARAM16
)hWnd
,
1677 (LPARAM
)SEGPTR_GET(cbtStruct
) );
1678 SEGPTR_FREE(cbtStruct
);
1679 if (bRet
) goto CLEANUP_END
;
1682 /* set prev active wnd to current active wnd and send notification */
1683 if ((hwndPrevActive
= hwndActive
) && IsWindow(hwndPrevActive
))
1685 MESSAGEQUEUE
*pTempActiveQueue
= 0;
1687 if (!SendMessageA( hwndPrevActive
, WM_NCACTIVATE
, FALSE
, 0 ))
1689 if (GetSysModalWindow16() != hWnd
)
1691 /* disregard refusal if hWnd is sysmodal */
1694 SendMessageA( hwndPrevActive
, WM_ACTIVATE
,
1695 MAKEWPARAM( WA_INACTIVE
, wIconized
),
1698 /* check if something happened during message processing
1699 * (global active queue may have changed)
1701 pTempActiveQueue
= QUEUE_Lock( hActiveQueue
);
1702 if(!pTempActiveQueue
)
1705 hwndActive
= PERQDATA_GetActiveWnd( pTempActiveQueue
->pQData
);
1706 QUEUE_Unlock( pTempActiveQueue
);
1707 if( hwndPrevActive
!= hwndActive
)
1711 /* Set new active window in the message queue */
1715 pNewActiveQueue
= QUEUE_Lock( wndPtr
->hmemTaskQ
);
1716 if ( pNewActiveQueue
)
1717 PERQDATA_SetActiveWnd( pNewActiveQueue
->pQData
, hwndActive
);
1719 else /* have to do this or MDI frame activation goes to hell */
1720 if( pOldActiveQueue
)
1721 PERQDATA_SetActiveWnd( pOldActiveQueue
->pQData
, 0 );
1723 /* send palette messages */
1724 if (hWnd
&& SendMessage16( hWnd
, WM_QUERYNEWPALETTE
, 0, 0L))
1725 SendMessage16((HWND16
)-1, WM_PALETTEISCHANGING
, (WPARAM16
)hWnd
, 0L );
1727 /* if prev wnd is minimized redraw icon title */
1728 if( IsIconic( hwndPrevActive
) ) WINPOS_RedrawIconTitle(hwndPrevActive
);
1730 /* managed windows will get ConfigureNotify event */
1731 if (wndPtr
&& !(wndPtr
->dwStyle
& WS_CHILD
) && !(wndPtr
->flags
& WIN_MANAGED
))
1733 /* check Z-order and bring hWnd to the top */
1734 for (wndTemp
= WIN_LockWndPtr(WIN_GetDesktop()->child
); wndTemp
; WIN_UpdateWndPtr(&wndTemp
,wndTemp
->next
))
1736 if (wndTemp
->dwStyle
& WS_VISIBLE
) break;
1738 WIN_ReleaseDesktop();
1739 WIN_ReleaseWndPtr(wndTemp
);
1741 if( wndTemp
!= wndPtr
)
1742 SetWindowPos(hWnd
, HWND_TOP
, 0,0,0,0,
1743 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
1744 if (!IsWindow(hWnd
))
1748 /* Get a handle to the new active queue */
1749 hNewActiveQueue
= wndPtr
? wndPtr
->hmemTaskQ
: 0;
1751 /* send WM_ACTIVATEAPP if necessary */
1752 if (hOldActiveQueue
!= hNewActiveQueue
)
1754 WND
**list
, **ppWnd
;
1755 WND
*pDesktop
= WIN_GetDesktop();
1757 if ((list
= WIN_BuildWinArray( pDesktop
, 0, NULL
)))
1759 for (ppWnd
= list
; *ppWnd
; ppWnd
++)
1761 if (!IsWindow( (*ppWnd
)->hwndSelf
)) continue;
1763 if ((*ppWnd
)->hmemTaskQ
== hOldActiveQueue
)
1764 SendMessage16( (*ppWnd
)->hwndSelf
, WM_ACTIVATEAPP
,
1765 0, QUEUE_GetQueueTask(hNewActiveQueue
) );
1767 WIN_ReleaseWinArray(list
);
1770 hActiveQueue
= hNewActiveQueue
;
1772 if ((list
= WIN_BuildWinArray(pDesktop
, 0, NULL
)))
1774 for (ppWnd
= list
; *ppWnd
; ppWnd
++)
1776 if (!IsWindow( (*ppWnd
)->hwndSelf
)) continue;
1778 if ((*ppWnd
)->hmemTaskQ
== hNewActiveQueue
)
1779 SendMessage16( (*ppWnd
)->hwndSelf
, WM_ACTIVATEAPP
,
1780 1, QUEUE_GetQueueTask( hOldActiveQueue
) );
1782 WIN_ReleaseWinArray(list
);
1784 WIN_ReleaseDesktop();
1786 if (!IsWindow(hWnd
)) goto CLEANUP
;
1791 /* walk up to the first unowned window */
1792 wndTemp
= WIN_LockWndPtr(wndPtr
);
1793 while (wndTemp
->owner
)
1795 WIN_UpdateWndPtr(&wndTemp
,wndTemp
->owner
);
1797 /* and set last active owned popup */
1798 wndTemp
->hwndLastActive
= hWnd
;
1800 wIconized
= HIWORD(wndTemp
->dwStyle
& WS_MINIMIZE
);
1801 WIN_ReleaseWndPtr(wndTemp
);
1802 SendMessageA( hWnd
, WM_NCACTIVATE
, TRUE
, 0 );
1803 SendMessageA( hWnd
, WM_ACTIVATE
,
1804 MAKEWPARAM( (fMouse
) ? WA_CLICKACTIVE
: WA_ACTIVE
, wIconized
),
1805 (LPARAM
)hwndPrevActive
);
1806 if( !IsWindow(hWnd
) ) goto CLEANUP
;
1809 /* change focus if possible */
1810 if( fChangeFocus
&& GetFocus() )
1811 if( WIN_GetTopParent(GetFocus()) != hwndActive
)
1812 FOCUS_SwitchFocus( pNewActiveQueue
, GetFocus(),
1813 (wndPtr
&& (wndPtr
->dwStyle
& WS_MINIMIZE
))?
1818 if( !hwndPrevActive
&& wndPtr
)
1819 (*wndPtr
->pDriver
->pForceWindowRaise
)(wndPtr
);
1821 /* if active wnd is minimized redraw icon title */
1822 if( IsIconic(hwndActive
) ) WINPOS_RedrawIconTitle(hwndActive
);
1824 bRet
= (hWnd
== hwndActive
); /* Success? */
1826 CLEANUP
: /* Unlock the message queues before returning */
1828 if ( pNewActiveQueue
)
1829 QUEUE_Unlock( pNewActiveQueue
);
1833 if ( pOldActiveQueue
)
1834 QUEUE_Unlock( pOldActiveQueue
);
1836 WIN_ReleaseWndPtr(wndPtr
);
1840 /*******************************************************************
1841 * WINPOS_ActivateOtherWindow
1843 * Activates window other than pWnd.
1845 BOOL
WINPOS_ActivateOtherWindow(WND
* pWnd
)
1849 HWND hwndActive
= 0;
1851 /* Get current active window from the active queue */
1854 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
1857 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
1858 QUEUE_Unlock( pActiveQueue
);
1862 if( pWnd
->hwndSelf
== hwndPrevActive
)
1865 if( hwndActive
!= pWnd
->hwndSelf
&&
1866 ( hwndActive
|| QUEUE_IsExitingQueue(pWnd
->hmemTaskQ
)) )
1869 if( !(pWnd
->dwStyle
& WS_POPUP
) || !(pWnd
->owner
) ||
1870 !WINPOS_CanActivate((pWndTo
= WIN_GetTopParentPtr(pWnd
->owner
))) )
1872 WND
* pWndPtr
= WIN_GetTopParentPtr(pWnd
);
1874 pWndTo
= WIN_FindWndPtr(hwndPrevActive
);
1876 while( !WINPOS_CanActivate(pWndTo
) )
1878 /* by now owned windows should've been taken care of */
1879 WIN_UpdateWndPtr(&pWndTo
,pWndPtr
->next
);
1880 WIN_UpdateWndPtr(&pWndPtr
,pWndTo
);
1881 if( !pWndTo
) break;
1883 WIN_ReleaseWndPtr(pWndPtr
);
1886 bRet
= WINPOS_SetActiveWindow( pWndTo
? pWndTo
->hwndSelf
: 0, FALSE
, TRUE
);
1888 /* switch desktop queue to current active */
1891 WIN_GetDesktop()->hmemTaskQ
= pWndTo
->hmemTaskQ
;
1892 WIN_ReleaseWndPtr(pWndTo
);
1893 WIN_ReleaseDesktop();
1900 /*******************************************************************
1901 * WINPOS_ChangeActiveWindow
1904 BOOL
WINPOS_ChangeActiveWindow( HWND hWnd
, BOOL mouseMsg
)
1906 WND
*wndPtr
, *wndTemp
;
1908 HWND hwndActive
= 0;
1910 /* Get current active window from the active queue */
1913 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
1916 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
1917 QUEUE_Unlock( pActiveQueue
);
1922 return WINPOS_SetActiveWindow( 0, mouseMsg
, TRUE
);
1924 wndPtr
= WIN_FindWndPtr(hWnd
);
1925 if( !wndPtr
) return FALSE
;
1927 /* child windows get WM_CHILDACTIVATE message */
1928 if( (wndPtr
->dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1930 retvalue
= SendMessageA(hWnd
, WM_CHILDACTIVATE
, 0, 0L);
1934 if( hWnd
== hwndActive
)
1940 if( !WINPOS_SetActiveWindow(hWnd
,mouseMsg
,TRUE
) )
1946 /* switch desktop queue to current active */
1947 wndTemp
= WIN_GetDesktop();
1948 if( wndPtr
->parent
== wndTemp
)
1949 wndTemp
->hmemTaskQ
= wndPtr
->hmemTaskQ
;
1950 WIN_ReleaseDesktop();
1954 WIN_ReleaseWndPtr(wndPtr
);
1959 /***********************************************************************
1960 * WINPOS_SendNCCalcSize
1962 * Send a WM_NCCALCSIZE message to a window.
1963 * All parameters are read-only except newClientRect.
1964 * oldWindowRect, oldClientRect and winpos must be non-NULL only
1965 * when calcValidRect is TRUE.
1967 LONG
WINPOS_SendNCCalcSize( HWND hwnd
, BOOL calcValidRect
,
1968 RECT
*newWindowRect
, RECT
*oldWindowRect
,
1969 RECT
*oldClientRect
, WINDOWPOS
*winpos
,
1970 RECT
*newClientRect
)
1972 NCCALCSIZE_PARAMS params
;
1973 WINDOWPOS winposCopy
;
1976 params
.rgrc
[0] = *newWindowRect
;
1979 winposCopy
= *winpos
;
1980 params
.rgrc
[1] = *oldWindowRect
;
1981 params
.rgrc
[2] = *oldClientRect
;
1982 params
.lppos
= &winposCopy
;
1984 result
= SendMessageA( hwnd
, WM_NCCALCSIZE
, calcValidRect
,
1986 TRACE(win
, "%d,%d-%d,%d\n",
1987 params
.rgrc
[0].left
, params
.rgrc
[0].top
,
1988 params
.rgrc
[0].right
, params
.rgrc
[0].bottom
);
1989 *newClientRect
= params
.rgrc
[0];
1994 /***********************************************************************
1995 * WINPOS_HandleWindowPosChanging16
1997 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
1999 LONG
WINPOS_HandleWindowPosChanging16( WND
*wndPtr
, WINDOWPOS16
*winpos
)
2001 POINT maxSize
, minTrack
;
2002 if (winpos
->flags
& SWP_NOSIZE
) return 0;
2003 if ((wndPtr
->dwStyle
& WS_THICKFRAME
) ||
2004 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) == 0))
2006 WINPOS_GetMinMaxInfo( wndPtr
, &maxSize
, NULL
, &minTrack
, NULL
);
2007 if (maxSize
.x
< winpos
->cx
) winpos
->cx
= maxSize
.x
;
2008 if (maxSize
.y
< winpos
->cy
) winpos
->cy
= maxSize
.y
;
2009 if (!(wndPtr
->dwStyle
& WS_MINIMIZE
))
2011 if (winpos
->cx
< minTrack
.x
) winpos
->cx
= minTrack
.x
;
2012 if (winpos
->cy
< minTrack
.y
) winpos
->cy
= minTrack
.y
;
2019 /***********************************************************************
2020 * WINPOS_HandleWindowPosChanging
2022 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2024 LONG
WINPOS_HandleWindowPosChanging( WND
*wndPtr
, WINDOWPOS
*winpos
)
2027 if (winpos
->flags
& SWP_NOSIZE
) return 0;
2028 if ((wndPtr
->dwStyle
& WS_THICKFRAME
) ||
2029 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) == 0))
2031 WINPOS_GetMinMaxInfo( wndPtr
, &maxSize
, NULL
, NULL
, NULL
);
2032 winpos
->cx
= MIN( winpos
->cx
, maxSize
.x
);
2033 winpos
->cy
= MIN( winpos
->cy
, maxSize
.y
);
2038 /***********************************************************************
2041 * fix Z order taking into account owned popups -
2042 * basically we need to maintain them above the window that owns them
2044 * FIXME: hide/show owned popups when owner visibility changes.
2046 static HWND
SWP_DoOwnedPopups(WND
* pDesktop
, WND
* wndPtr
, HWND hwndInsertAfter
, WORD flags
)
2048 WND
* w
= WIN_LockWndPtr(pDesktop
->child
);
2050 WARN(win
, "(%04x) hInsertAfter = %04x\n", wndPtr
->hwndSelf
, hwndInsertAfter
);
2052 if( (wndPtr
->dwStyle
& WS_POPUP
) && wndPtr
->owner
)
2054 /* make sure this popup stays above the owner */
2056 HWND hwndLocalPrev
= HWND_TOP
;
2058 if( hwndInsertAfter
!= HWND_TOP
)
2060 while( w
!= wndPtr
->owner
)
2062 if (w
!= wndPtr
) hwndLocalPrev
= w
->hwndSelf
;
2063 if( hwndLocalPrev
== hwndInsertAfter
) break;
2064 WIN_UpdateWndPtr(&w
,w
->next
);
2066 hwndInsertAfter
= hwndLocalPrev
;
2069 else if( wndPtr
->dwStyle
& WS_CHILD
)
2072 WIN_UpdateWndPtr(&w
, pDesktop
->child
);
2076 if( w
== wndPtr
) break;
2078 if( (w
->dwStyle
& WS_POPUP
) && w
->owner
== wndPtr
)
2080 SetWindowPos(w
->hwndSelf
, hwndInsertAfter
, 0, 0, 0, 0,
2081 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOSENDCHANGING
| SWP_DEFERERASE
);
2082 hwndInsertAfter
= w
->hwndSelf
;
2084 WIN_UpdateWndPtr(&w
, w
->next
);
2088 WIN_ReleaseWndPtr(w
);
2089 return hwndInsertAfter
;
2092 /***********************************************************************
2095 * Make window look nice without excessive repainting
2097 * visible and update regions are in window coordinates
2098 * client and window rectangles are in parent client coordinates
2100 * FIXME: SWP_EX_PAINTSELF in uFlags works only if both old and new
2101 * window rects have the same origin.
2103 * Returns: uFlags and a dirty region in *pVisRgn.
2105 static UINT
SWP_CopyValidBits( WND
* Wnd
, HRGN
* pVisRgn
,
2106 LPRECT lpOldWndRect
,
2107 LPRECT lpOldClientRect
, UINT uFlags
)
2110 HRGN newVisRgn
, dirtyRgn
;
2111 INT my
= COMPLEXREGION
;
2113 TRACE(win
,"\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2114 Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
,
2115 Wnd
->rectWindow
.right
, Wnd
->rectWindow
.bottom
,
2116 lpOldWndRect
->left
, lpOldWndRect
->top
,
2117 lpOldWndRect
->right
, lpOldWndRect
->bottom
, *pVisRgn
);
2118 TRACE(win
,"\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2119 Wnd
->rectClient
.left
, Wnd
->rectClient
.top
,
2120 Wnd
->rectClient
.right
, Wnd
->rectClient
.bottom
,
2121 lpOldClientRect
->left
, lpOldClientRect
->top
,
2122 lpOldClientRect
->right
,lpOldClientRect
->bottom
);
2124 if( Wnd
->hrgnUpdate
== 1 )
2125 uFlags
|= SWP_EX_NOCOPY
; /* whole window is invalid, nothing to copy */
2127 newVisRgn
= DCE_GetVisRgn( Wnd
->hwndSelf
, DCX_WINDOW
| DCX_CLIPSIBLINGS
, 0, 0);
2128 dirtyRgn
= CreateRectRgn( 0, 0, 0, 0 );
2130 if( !(uFlags
& SWP_EX_NOCOPY
) ) /* make sure dst region covers only valid bits */
2131 my
= CombineRgn( dirtyRgn
, newVisRgn
, *pVisRgn
, RGN_AND
);
2133 if( (my
== NULLREGION
) || (uFlags
& SWP_EX_NOCOPY
) )
2137 TRACE(win
,"\twon't copy anything!\n");
2139 /* set dirtyRgn to the sum of old and new visible regions
2140 * in parent client coordinates */
2142 OffsetRgn( newVisRgn
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2143 OffsetRgn( *pVisRgn
, lpOldWndRect
->left
, lpOldWndRect
->top
);
2145 CombineRgn(*pVisRgn
, *pVisRgn
, newVisRgn
, RGN_OR
);
2147 else /* copy valid bits to a new location */
2149 INT dx
, dy
, ow
, oh
, nw
, nh
, ocw
, ncw
, och
, nch
;
2150 HRGN hrgnValid
= dirtyRgn
; /* non-empty intersection of old and new visible rgns */
2152 /* subtract already invalid region inside Wnd from the dst region */
2154 if( Wnd
->hrgnUpdate
)
2155 if( CombineRgn( hrgnValid
, hrgnValid
, Wnd
->hrgnUpdate
, RGN_DIFF
) == NULLREGION
)
2158 /* check if entire window can be copied */
2160 ow
= lpOldWndRect
->right
- lpOldWndRect
->left
;
2161 oh
= lpOldWndRect
->bottom
- lpOldWndRect
->top
;
2162 nw
= Wnd
->rectWindow
.right
- Wnd
->rectWindow
.left
;
2163 nh
= Wnd
->rectWindow
.bottom
- Wnd
->rectWindow
.top
;
2165 ocw
= lpOldClientRect
->right
- lpOldClientRect
->left
;
2166 och
= lpOldClientRect
->bottom
- lpOldClientRect
->top
;
2167 ncw
= Wnd
->rectClient
.right
- Wnd
->rectClient
.left
;
2168 nch
= Wnd
->rectClient
.bottom
- Wnd
->rectClient
.top
;
2170 if( (ocw
!= ncw
) || (och
!= nch
) ||
2171 ( ow
!= nw
) || ( oh
!= nw
) ||
2172 ((lpOldClientRect
->top
- lpOldWndRect
->top
) !=
2173 (Wnd
->rectClient
.top
- Wnd
->rectWindow
.top
)) ||
2174 ((lpOldClientRect
->left
- lpOldWndRect
->left
) !=
2175 (Wnd
->rectClient
.left
- Wnd
->rectWindow
.left
)) )
2177 dx
= Wnd
->rectClient
.left
- lpOldClientRect
->left
;
2178 dy
= Wnd
->rectClient
.top
- lpOldClientRect
->top
;
2180 /* restrict valid bits to the common client rect */
2182 r
.left
= Wnd
->rectClient
.left
- Wnd
->rectWindow
.left
;
2183 r
.top
= Wnd
->rectClient
.top
- Wnd
->rectWindow
.top
;
2184 r
.right
= r
.left
+ MIN( ocw
, ncw
);
2185 r
.bottom
= r
.top
+ MIN( och
, nch
);
2187 REGION_CropRgn( hrgnValid
, hrgnValid
, &r
,
2188 (uFlags
& SWP_EX_PAINTSELF
) ? NULL
: (POINT
*)&(Wnd
->rectWindow
));
2189 GetRgnBox( hrgnValid
, &r
);
2190 if( IsRectEmpty( &r
) )
2192 r
= *lpOldClientRect
;
2196 dx
= Wnd
->rectWindow
.left
- lpOldWndRect
->left
;
2197 dy
= Wnd
->rectWindow
.top
- lpOldWndRect
->top
;
2198 if( !(uFlags
& SWP_EX_PAINTSELF
) )
2199 OffsetRgn( hrgnValid
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2203 if( !(uFlags
& SWP_EX_PAINTSELF
) )
2205 /* Move remaining regions to parent coordinates */
2206 OffsetRgn( newVisRgn
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2207 OffsetRgn( *pVisRgn
, lpOldWndRect
->left
, lpOldWndRect
->top
);
2210 OffsetRect( &r
, -lpOldWndRect
->left
, -lpOldWndRect
->top
);
2212 TRACE(win
,"\tcomputing dirty region!\n");
2214 /* Compute combined dirty region (old + new - valid) */
2215 CombineRgn( *pVisRgn
, *pVisRgn
, newVisRgn
, RGN_OR
);
2216 CombineRgn( *pVisRgn
, *pVisRgn
, hrgnValid
, RGN_DIFF
);
2218 /* Blt valid bits, r is the rect to copy */
2223 HDC hDC
= ( uFlags
& SWP_EX_PAINTSELF
)
2224 ? GetDCEx( Wnd
->hwndSelf
, hrgnValid
, DCX_WINDOW
| DCX_CACHE
|
2225 DCX_KEEPCLIPRGN
| DCX_INTERSECTRGN
| DCX_CLIPSIBLINGS
)
2226 : GetDCEx( Wnd
->parent
->hwndSelf
, hrgnValid
, DCX_CACHE
|
2227 DCX_KEEPCLIPRGN
| DCX_INTERSECTRGN
| DCX_CLIPSIBLINGS
);
2228 if( (dc
= (DC
*)GDI_GetObjPtr(hDC
, DC_MAGIC
)) )
2230 if( oh
> nh
) r
.bottom
= r
.top
+ nh
;
2231 if( ow
< nw
) r
.right
= r
.left
+ nw
;
2233 Wnd
->pDriver
->pSurfaceCopy( Wnd
->parent
, dc
, dx
, dy
, &r
, TRUE
);
2235 GDI_HEAP_UNLOCK( hDC
);
2237 ReleaseDC( (uFlags
& SWP_EX_PAINTSELF
) ?
2238 Wnd
->hwndSelf
: Wnd
->parent
->hwndSelf
, hDC
);
2242 /* *pVisRgn now points to the invalidated region */
2244 DeleteObject(newVisRgn
);
2245 DeleteObject(dirtyRgn
);
2249 /***********************************************************************
2250 * SWP_DoSimpleFrameChanged
2252 * NOTE: old and new client rect origins are identical, only
2253 * extents may have changed. Window extents are the same.
2255 static void SWP_DoSimpleFrameChanged( WND
* wndPtr
, RECT
* pOldClientRect
, WORD swpFlags
, UINT uFlags
)
2261 if( !(swpFlags
& SWP_NOCLIENTSIZE
) )
2263 /* FIXME: WVR alignment flags */
2265 if( wndPtr
->rectClient
.right
> pOldClientRect
->right
) /* right edge */
2269 rect
.bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
2270 rect
.right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
2271 if(!(uFlags
& SWP_EX_NOCOPY
))
2272 rect
.left
= pOldClientRect
->right
- wndPtr
->rectClient
.left
;
2280 if( wndPtr
->rectClient
.bottom
> pOldClientRect
->bottom
) /* bottom edge */
2283 hrgn
= CreateRectRgnIndirect( &rect
);
2285 rect
.right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
2286 rect
.bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
2287 if(!(uFlags
& SWP_EX_NOCOPY
))
2288 rect
.top
= pOldClientRect
->bottom
- wndPtr
->rectClient
.top
;
2292 REGION_UnionRectWithRgn( hrgn
, &rect
);
2295 if( i
== 0 && (uFlags
& SWP_EX_NOCOPY
) ) /* force redraw anyway */
2297 rect
= wndPtr
->rectWindow
;
2298 OffsetRect( &rect
, wndPtr
->rectWindow
.left
- wndPtr
->rectClient
.left
,
2299 wndPtr
->rectWindow
.top
- wndPtr
->rectClient
.top
);
2307 PAINT_RedrawWindow( wndPtr
->hwndSelf
, &rect
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
|
2308 RDW_ERASENOW
| RDW_ALLCHILDREN
, RDW_EX_TOPFRAME
| RDW_EX_USEHRGN
);
2311 hrgn
= WIN_UpdateNCRgn(wndPtr
, TRUE
, TRUE
);
2314 DeleteObject( hrgn
);
2317 /***********************************************************************
2318 * SWP_DoWinPosChanging
2320 static BOOL
SWP_DoWinPosChanging( WND
* wndPtr
, WINDOWPOS
* pWinpos
,
2321 RECT
* pNewWindowRect
, RECT
* pNewClientRect
)
2323 /* Send WM_WINDOWPOSCHANGING message */
2325 if (!(pWinpos
->flags
& SWP_NOSENDCHANGING
))
2326 SendMessageA( wndPtr
->hwndSelf
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
)pWinpos
);
2328 /* Calculate new position and size */
2330 *pNewWindowRect
= wndPtr
->rectWindow
;
2331 *pNewClientRect
= (wndPtr
->dwStyle
& WS_MINIMIZE
) ? wndPtr
->rectWindow
2332 : wndPtr
->rectClient
;
2334 if (!(pWinpos
->flags
& SWP_NOSIZE
))
2336 pNewWindowRect
->right
= pNewWindowRect
->left
+ pWinpos
->cx
;
2337 pNewWindowRect
->bottom
= pNewWindowRect
->top
+ pWinpos
->cy
;
2339 if (!(pWinpos
->flags
& SWP_NOMOVE
))
2341 pNewWindowRect
->left
= pWinpos
->x
;
2342 pNewWindowRect
->top
= pWinpos
->y
;
2343 pNewWindowRect
->right
+= pWinpos
->x
- wndPtr
->rectWindow
.left
;
2344 pNewWindowRect
->bottom
+= pWinpos
->y
- wndPtr
->rectWindow
.top
;
2346 OffsetRect( pNewClientRect
, pWinpos
->x
- wndPtr
->rectWindow
.left
,
2347 pWinpos
->y
- wndPtr
->rectWindow
.top
);
2350 pWinpos
->flags
|= SWP_NOCLIENTMOVE
| SWP_NOCLIENTSIZE
;
2354 /***********************************************************************
2357 static UINT
SWP_DoNCCalcSize( WND
* wndPtr
, WINDOWPOS
* pWinpos
,
2358 RECT
* pNewWindowRect
, RECT
* pNewClientRect
, WORD f
)
2362 /* Send WM_NCCALCSIZE message to get new client area */
2363 if( (pWinpos
->flags
& (SWP_FRAMECHANGED
| SWP_NOSIZE
)) != SWP_NOSIZE
)
2365 wvrFlags
= WINPOS_SendNCCalcSize( pWinpos
->hwnd
, TRUE
, pNewWindowRect
,
2366 &wndPtr
->rectWindow
, &wndPtr
->rectClient
,
2367 pWinpos
, pNewClientRect
);
2369 /* FIXME: WVR_ALIGNxxx */
2371 if( pNewClientRect
->left
!= wndPtr
->rectClient
.left
||
2372 pNewClientRect
->top
!= wndPtr
->rectClient
.top
)
2373 pWinpos
->flags
&= ~SWP_NOCLIENTMOVE
;
2375 if( (pNewClientRect
->right
- pNewClientRect
->left
!=
2376 wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
) ||
2377 (pNewClientRect
->bottom
- pNewClientRect
->top
!=
2378 wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
) )
2379 pWinpos
->flags
&= ~SWP_NOCLIENTSIZE
;
2382 if( !(f
& SWP_NOMOVE
) && (pNewClientRect
->left
!= wndPtr
->rectClient
.left
||
2383 pNewClientRect
->top
!= wndPtr
->rectClient
.top
) )
2384 pWinpos
->flags
&= ~SWP_NOCLIENTMOVE
;
2388 /***********************************************************************
2389 * SetWindowPos (USER.2)
2391 BOOL16 WINAPI
SetWindowPos16( HWND16 hwnd
, HWND16 hwndInsertAfter
,
2392 INT16 x
, INT16 y
, INT16 cx
, INT16 cy
, WORD flags
)
2394 return SetWindowPos(hwnd
,(INT
)(INT16
)hwndInsertAfter
,x
,y
,cx
,cy
,flags
);
2397 /***********************************************************************
2398 * SetWindowPos (USER32.520)
2400 BOOL WINAPI
SetWindowPos( HWND hwnd
, HWND hwndInsertAfter
,
2401 INT x
, INT y
, INT cx
, INT cy
, WORD flags
)
2404 WND
* wndPtr
,*wndTemp
;
2405 RECT newWindowRect
, newClientRect
;
2406 RECT oldWindowRect
, oldClientRect
;
2408 UINT wvrFlags
= 0, uFlags
= 0;
2409 BOOL retvalue
, resync
= FALSE
;
2410 HWND hwndActive
= 0;
2412 /* Get current active window from the active queue */
2415 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
2418 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
2419 QUEUE_Unlock( pActiveQueue
);
2423 TRACE(win
,"hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2424 hwnd
, x
, y
, x
+cx
, y
+cy
, flags
);
2426 /* ------------------------------------------------------------------------ CHECKS */
2428 /* Check window handle */
2430 if (hwnd
== GetDesktopWindow()) return FALSE
;
2431 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return FALSE
;
2433 TRACE(win
,"\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr
->rectWindow
.left
, wndPtr
->rectWindow
.top
,
2434 wndPtr
->rectWindow
.right
, wndPtr
->rectWindow
.bottom
, (unsigned)wndPtr
->dwStyle
);
2436 /* Fix redundant flags */
2438 if(wndPtr
->dwStyle
& WS_VISIBLE
)
2439 flags
&= ~SWP_SHOWWINDOW
;
2442 if (!(flags
& SWP_SHOWWINDOW
))
2443 flags
|= SWP_NOREDRAW
;
2444 flags
&= ~SWP_HIDEWINDOW
;
2447 if ( cx
< 0 ) cx
= 0; if( cy
< 0 ) cy
= 0;
2449 if ((wndPtr
->rectWindow
.right
- wndPtr
->rectWindow
.left
== cx
) &&
2450 (wndPtr
->rectWindow
.bottom
- wndPtr
->rectWindow
.top
== cy
))
2451 flags
|= SWP_NOSIZE
; /* Already the right size */
2453 if ((wndPtr
->rectWindow
.left
== x
) && (wndPtr
->rectWindow
.top
== y
))
2454 flags
|= SWP_NOMOVE
; /* Already the right position */
2456 if (hwnd
== hwndActive
)
2457 flags
|= SWP_NOACTIVATE
; /* Already active */
2460 if(!(flags
& SWP_NOACTIVATE
)) /* Bring to the top when activating */
2462 flags
&= ~SWP_NOZORDER
;
2463 hwndInsertAfter
= HWND_TOP
;
2468 /* Check hwndInsertAfter */
2470 /* FIXME: TOPMOST not supported yet */
2471 if ((hwndInsertAfter
== HWND_TOPMOST
) ||
2472 (hwndInsertAfter
== HWND_NOTOPMOST
)) hwndInsertAfter
= HWND_TOP
;
2474 /* hwndInsertAfter must be a sibling of the window */
2475 if ((hwndInsertAfter
!= HWND_TOP
) && (hwndInsertAfter
!= HWND_BOTTOM
))
2477 WND
* wnd
= WIN_FindWndPtr(hwndInsertAfter
);
2480 if( wnd
->parent
!= wndPtr
->parent
)
2483 WIN_ReleaseWndPtr(wnd
);
2486 if( wnd
->next
== wndPtr
) flags
|= SWP_NOZORDER
;
2488 WIN_ReleaseWndPtr(wnd
);
2491 Pos
: /* ------------------------------------------------------------------------ MAIN part */
2493 /* Fill the WINDOWPOS structure */
2496 winpos
.hwndInsertAfter
= hwndInsertAfter
;
2501 winpos
.flags
= flags
;
2503 SWP_DoWinPosChanging( wndPtr
, &winpos
, &newWindowRect
, &newClientRect
);
2505 if((winpos
.flags
& (SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) != SWP_NOZORDER
)
2507 if( wndPtr
->parent
== WIN_GetDesktop() )
2508 hwndInsertAfter
= SWP_DoOwnedPopups( wndPtr
->parent
, wndPtr
,
2509 hwndInsertAfter
, winpos
.flags
);
2510 WIN_ReleaseDesktop();
2513 if(!(wndPtr
->flags
& WIN_NATIVE
) )
2515 if( hwndInsertAfter
== HWND_TOP
)
2516 winpos
.flags
|= ( wndPtr
->parent
->child
== wndPtr
)? SWP_NOZORDER
: 0;
2518 if( hwndInsertAfter
== HWND_BOTTOM
)
2519 winpos
.flags
|= ( wndPtr
->next
)? 0: SWP_NOZORDER
;
2521 if( !(winpos
.flags
& SWP_NOZORDER
) )
2522 if( GetWindow(hwndInsertAfter
, GW_HWNDNEXT
) == wndPtr
->hwndSelf
)
2523 winpos
.flags
|= SWP_NOZORDER
;
2525 if( !(winpos
.flags
& SWP_NOREDRAW
) &&
2526 ((winpos
.flags
& (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_FRAMECHANGED
))
2527 != (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
)) )
2529 /* get a previous visible region for SWP_CopyValidBits() */
2531 visRgn
= DCE_GetVisRgn(hwnd
, DCX_WINDOW
| DCX_CLIPSIBLINGS
, 0, 0);
2535 /* Common operations */
2537 wvrFlags
= SWP_DoNCCalcSize( wndPtr
, &winpos
, &newWindowRect
, &newClientRect
, flags
);
2539 if(!(winpos
.flags
& SWP_NOZORDER
))
2541 /* upon window creation (while processing WM_NCCREATE), wndPtr->parent is set correctly
2542 * but wndPtr is not yet in wndPtr->parent->child list
2543 * in those cases (SetWindowPos called while processing WM_NCCREATE),
2544 * do not unlink/link winPtr in parent->child
2546 if ( WIN_UnlinkWindow( winpos
.hwnd
) )
2547 WIN_LinkWindow( winpos
.hwnd
, hwndInsertAfter
);
2550 /* Reset active DCEs */
2552 if( (((winpos
.flags
& SWP_AGG_NOPOSCHANGE
) != SWP_AGG_NOPOSCHANGE
) &&
2553 wndPtr
->dwStyle
& WS_VISIBLE
) ||
2554 (flags
& (SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) )
2558 UnionRect(&rect
, &newWindowRect
, &wndPtr
->rectWindow
);
2559 DCE_InvalidateDCE(wndPtr
, &rect
);
2562 oldWindowRect
= wndPtr
->rectWindow
;
2563 oldClientRect
= wndPtr
->rectClient
;
2565 /* Find out if we have to redraw the whole client rect */
2567 if( oldClientRect
.bottom
- oldClientRect
.top
==
2568 newClientRect
.bottom
- newClientRect
.top
) wvrFlags
&= ~WVR_VREDRAW
;
2570 if( oldClientRect
.right
- oldClientRect
.left
==
2571 newClientRect
.right
- newClientRect
.left
) wvrFlags
&= ~WVR_HREDRAW
;
2573 uFlags
|= ((winpos
.flags
& SWP_NOCOPYBITS
) ||
2574 (!(winpos
.flags
& SWP_NOCLIENTSIZE
) &&
2575 (wvrFlags
>= WVR_HREDRAW
) && (wvrFlags
< WVR_VALIDRECTS
))) ? SWP_EX_NOCOPY
: 0;
2577 /* FIXME: actually do something with WVR_VALIDRECTS */
2579 wndPtr
->rectWindow
= newWindowRect
;
2580 wndPtr
->rectClient
= newClientRect
;
2582 if (wndPtr
->flags
& WIN_NATIVE
) /* -------------------------------------------- hosted window */
2584 BOOL bCallDriver
= TRUE
;
2585 HWND tempInsertAfter
= winpos
.hwndInsertAfter
;
2587 winpos
.hwndInsertAfter
= hwndInsertAfter
;
2589 if( !(winpos
.flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
| SWP_NOREDRAW
)) )
2591 /* This is the only place where we need to force repainting of the contents
2592 of windows created by the host window system, all other cases go through the
2593 expose event handling */
2595 if( (winpos
.flags
& SWP_FRAMECHANGED
) )
2599 if( (x
= (newWindowRect
.right
- newWindowRect
.left
)) == (oldWindowRect
.right
- oldWindowRect
.left
) &&
2600 (y
= (newWindowRect
.bottom
- newWindowRect
.top
)) == (oldWindowRect
.bottom
- oldWindowRect
.top
) )
2603 wndPtr
->pDriver
->pSetWindowPos(wndPtr
, &winpos
, TRUE
);
2604 winpos
.hwndInsertAfter
= tempInsertAfter
;
2605 bCallDriver
= FALSE
;
2607 if( winpos
.flags
& SWP_NOCLIENTMOVE
)
2608 SWP_DoSimpleFrameChanged(wndPtr
, &oldClientRect
, winpos
.flags
, uFlags
);
2611 /* client area moved but window extents remained the same, copy valid bits */
2613 visRgn
= CreateRectRgn( 0, 0, x
, y
);
2614 uFlags
= SWP_CopyValidBits( wndPtr
, &visRgn
, &oldWindowRect
, &oldClientRect
,
2615 uFlags
| SWP_EX_PAINTSELF
);
2623 if( !(winpos
.flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
| SWP_NOREDRAW
)) )
2625 if( (oldClientRect
.left
- oldWindowRect
.left
== newClientRect
.left
- newWindowRect
.left
) &&
2626 (oldClientRect
.top
- oldWindowRect
.top
== newClientRect
.top
- newWindowRect
.top
) &&
2627 !(uFlags
& SWP_EX_NOCOPY
) )
2629 /* The origin of the client rect didn't move so we can try to repaint
2630 * only the nonclient area by setting bit gravity hint for the host window system.
2633 if( !(wndPtr
->flags
& WIN_MANAGED
) )
2635 HRGN hrgn
= CreateRectRgn( 0, 0, newWindowRect
.right
- newWindowRect
.left
,
2636 newWindowRect
.bottom
- newWindowRect
.top
);
2637 RECT rcn
= newClientRect
;
2638 RECT rco
= oldClientRect
;
2640 OffsetRect( &rcn
, -newWindowRect
.left
, -newWindowRect
.top
);
2641 OffsetRect( &rco
, -oldWindowRect
.left
, -oldWindowRect
.top
);
2642 IntersectRect( &rcn
, &rcn
, &rco
);
2643 visRgn
= CreateRectRgnIndirect( &rcn
);
2644 CombineRgn( visRgn
, hrgn
, visRgn
, RGN_DIFF
);
2645 DeleteObject( hrgn
);
2646 uFlags
= SWP_EX_PAINTSELF
;
2648 wndPtr
->pDriver
->pSetHostAttr(wndPtr
, HAK_BITGRAVITY
, BGNorthWest
);
2651 wndPtr
->pDriver
->pSetHostAttr(wndPtr
, HAK_BITGRAVITY
, BGForget
);
2653 wndPtr
->pDriver
->pSetWindowPos(wndPtr
, &winpos
, TRUE
);
2654 winpos
.hwndInsertAfter
= tempInsertAfter
;
2657 if( winpos
.flags
& SWP_SHOWWINDOW
)
2661 wndPtr
->dwStyle
|= WS_VISIBLE
;
2663 if (wndPtr
->flags
& WIN_MANAGED
) resync
= TRUE
;
2665 /* focus was set to unmapped window, reset host focus
2666 * since the window is now visible */
2668 focus
= curr
= GetFocus();
2673 WND
*pFocus
= WIN_FindWndPtr( focus
);
2675 pFocus
->pDriver
->pSetFocus(pFocus
);
2676 WIN_ReleaseWndPtr(pFocus
);
2679 curr
= GetParent(curr
);
2683 else /* -------------------------------------------- emulated window */
2685 if( winpos
.flags
& SWP_SHOWWINDOW
)
2687 wndPtr
->dwStyle
|= WS_VISIBLE
;
2688 uFlags
|= SWP_EX_PAINTSELF
;
2689 visRgn
= 1; /* redraw the whole window */
2691 else if( !(winpos
.flags
& SWP_NOREDRAW
) )
2693 if( winpos
.flags
& SWP_HIDEWINDOW
)
2695 if( visRgn
> 1 ) /* map to parent */
2696 OffsetRgn( visRgn
, oldWindowRect
.left
, oldWindowRect
.top
);
2702 if( (winpos
.flags
& SWP_AGG_NOPOSCHANGE
) != SWP_AGG_NOPOSCHANGE
)
2703 uFlags
= SWP_CopyValidBits(wndPtr
, &visRgn
, &oldWindowRect
,
2704 &oldClientRect
, uFlags
);
2707 /* nothing moved, redraw frame if needed */
2709 if( winpos
.flags
& SWP_FRAMECHANGED
)
2710 SWP_DoSimpleFrameChanged( wndPtr
, &oldClientRect
, winpos
.flags
, uFlags
);
2713 DeleteObject( visRgn
);
2721 if( winpos
.flags
& SWP_HIDEWINDOW
)
2723 wndPtr
->dwStyle
&= ~WS_VISIBLE
;
2725 if (hwnd
== CARET_GetHwnd()) DestroyCaret();
2727 /* FIXME: This will cause the window to be activated irrespective
2728 * of whether it is owned by the same thread. Has to be done
2732 if (winpos
.hwnd
== hwndActive
)
2733 WINPOS_ActivateOtherWindow( wndPtr
);
2736 /* ------------------------------------------------------------------------ FINAL */
2738 if (wndPtr
->flags
& WIN_NATIVE
)
2739 EVENT_Synchronize(); /* Synchronize with the host window system */
2741 if (!GetCapture() && ((wndPtr
->dwStyle
& WS_VISIBLE
) || (flags
& SWP_HIDEWINDOW
)))
2742 EVENT_DummyMotionNotify(); /* Simulate a mouse event to set the cursor */
2744 wndTemp
= WIN_GetDesktop();
2746 /* repaint invalidated region (if any)
2748 * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2749 * and force update after ChangeActiveWindow() to avoid painting frames twice.
2754 if( !(winpos
.flags
& SWP_NOREDRAW
) )
2756 if( uFlags
& SWP_EX_PAINTSELF
)
2758 PAINT_RedrawWindow( wndPtr
->hwndSelf
, NULL
, (visRgn
== 1) ? 0 : visRgn
, RDW_ERASE
| RDW_FRAME
|
2759 ((winpos
.flags
& SWP_DEFERERASE
) ? 0 : RDW_ERASENOW
) | RDW_INVALIDATE
|
2760 RDW_ALLCHILDREN
, RDW_EX_XYWINDOW
| RDW_EX_USEHRGN
);
2764 PAINT_RedrawWindow( wndPtr
->parent
->hwndSelf
, NULL
, (visRgn
== 1) ? 0 : visRgn
, RDW_ERASE
|
2765 ((winpos
.flags
& SWP_DEFERERASE
) ? 0 : RDW_ERASENOW
) | RDW_INVALIDATE
|
2766 RDW_ALLCHILDREN
, RDW_EX_USEHRGN
);
2770 DeleteObject( visRgn
);
2773 WIN_ReleaseDesktop();
2775 if (!(flags
& SWP_NOACTIVATE
))
2776 WINPOS_ChangeActiveWindow( winpos
.hwnd
, FALSE
);
2778 /* And last, send the WM_WINDOWPOSCHANGED message */
2780 TRACE(win
,"\tstatus flags = %04x\n", winpos
.flags
& SWP_AGG_STATUSFLAGS
);
2783 (((winpos
.flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOPOSCHANGE
) &&
2784 !(winpos
.flags
& SWP_NOSENDCHANGING
)) )
2786 SendMessageA( winpos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
)&winpos
);
2787 if (resync
) EVENT_Synchronize ();
2792 WIN_ReleaseWndPtr(wndPtr
);
2797 /***********************************************************************
2798 * BeginDeferWindowPos16 (USER.259)
2800 HDWP16 WINAPI
BeginDeferWindowPos16( INT16 count
)
2802 return BeginDeferWindowPos( count
);
2806 /***********************************************************************
2807 * BeginDeferWindowPos (USER32.9)
2809 HDWP WINAPI
BeginDeferWindowPos( INT count
)
2814 if (count
<= 0) return 0;
2815 handle
= USER_HEAP_ALLOC( sizeof(DWP
) + (count
-1)*sizeof(WINDOWPOS
) );
2816 if (!handle
) return 0;
2817 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( handle
);
2818 pDWP
->actualCount
= 0;
2819 pDWP
->suggestedCount
= count
;
2821 pDWP
->wMagic
= DWP_MAGIC
;
2822 pDWP
->hwndParent
= 0;
2827 /***********************************************************************
2828 * DeferWindowPos16 (USER.260)
2830 HDWP16 WINAPI
DeferWindowPos16( HDWP16 hdwp
, HWND16 hwnd
, HWND16 hwndAfter
,
2831 INT16 x
, INT16 y
, INT16 cx
, INT16 cy
,
2834 return DeferWindowPos( hdwp
, hwnd
, (INT
)(INT16
)hwndAfter
,
2835 x
, y
, cx
, cy
, flags
);
2839 /***********************************************************************
2840 * DeferWindowPos (USER32.128)
2842 HDWP WINAPI
DeferWindowPos( HDWP hdwp
, HWND hwnd
, HWND hwndAfter
,
2843 INT x
, INT y
, INT cx
, INT cy
,
2848 HDWP newhdwp
= hdwp
,retvalue
;
2852 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
2853 if (!pDWP
) return 0;
2854 if (hwnd
== GetDesktopWindow()) return 0;
2856 if (!(pWnd
=WIN_FindWndPtr( hwnd
))) {
2857 USER_HEAP_FREE( hdwp
);
2861 /* Numega Bounds Checker Demo dislikes the following code.
2862 In fact, I've not been able to find any "same parent" requirement in any docu
2866 /* All the windows of a DeferWindowPos() must have the same parent */
2867 parent
= pWnd
->parent
->hwndSelf
;
2868 if (pDWP
->actualCount
== 0) pDWP
->hwndParent
= parent
;
2869 else if (parent
!= pDWP
->hwndParent
)
2871 USER_HEAP_FREE( hdwp
);
2877 for (i
= 0; i
< pDWP
->actualCount
; i
++)
2879 if (pDWP
->winPos
[i
].hwnd
== hwnd
)
2881 /* Merge with the other changes */
2882 if (!(flags
& SWP_NOZORDER
))
2884 pDWP
->winPos
[i
].hwndInsertAfter
= hwndAfter
;
2886 if (!(flags
& SWP_NOMOVE
))
2888 pDWP
->winPos
[i
].x
= x
;
2889 pDWP
->winPos
[i
].y
= y
;
2891 if (!(flags
& SWP_NOSIZE
))
2893 pDWP
->winPos
[i
].cx
= cx
;
2894 pDWP
->winPos
[i
].cy
= cy
;
2896 pDWP
->winPos
[i
].flags
&= flags
| ~(SWP_NOSIZE
| SWP_NOMOVE
|
2897 SWP_NOZORDER
| SWP_NOREDRAW
|
2898 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
2900 pDWP
->winPos
[i
].flags
|= flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
|
2906 if (pDWP
->actualCount
>= pDWP
->suggestedCount
)
2908 newhdwp
= USER_HEAP_REALLOC( hdwp
,
2909 sizeof(DWP
) + pDWP
->suggestedCount
*sizeof(WINDOWPOS
) );
2915 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( newhdwp
);
2916 pDWP
->suggestedCount
++;
2918 pDWP
->winPos
[pDWP
->actualCount
].hwnd
= hwnd
;
2919 pDWP
->winPos
[pDWP
->actualCount
].hwndInsertAfter
= hwndAfter
;
2920 pDWP
->winPos
[pDWP
->actualCount
].x
= x
;
2921 pDWP
->winPos
[pDWP
->actualCount
].y
= y
;
2922 pDWP
->winPos
[pDWP
->actualCount
].cx
= cx
;
2923 pDWP
->winPos
[pDWP
->actualCount
].cy
= cy
;
2924 pDWP
->winPos
[pDWP
->actualCount
].flags
= flags
;
2925 pDWP
->actualCount
++;
2928 WIN_ReleaseWndPtr(pWnd
);
2933 /***********************************************************************
2934 * EndDeferWindowPos16 (USER.261)
2936 BOOL16 WINAPI
EndDeferWindowPos16( HDWP16 hdwp
)
2938 return EndDeferWindowPos( hdwp
);
2942 /***********************************************************************
2943 * EndDeferWindowPos (USER32.173)
2945 BOOL WINAPI
EndDeferWindowPos( HDWP hdwp
)
2952 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
2953 if (!pDWP
) return FALSE
;
2954 for (i
= 0, winpos
= pDWP
->winPos
; i
< pDWP
->actualCount
; i
++, winpos
++)
2956 if (!(res
= SetWindowPos( winpos
->hwnd
, winpos
->hwndInsertAfter
,
2957 winpos
->x
, winpos
->y
, winpos
->cx
,
2958 winpos
->cy
, winpos
->flags
))) break;
2960 USER_HEAP_FREE( hdwp
);
2965 /***********************************************************************
2966 * TileChildWindows (USER.199)
2968 void WINAPI
TileChildWindows16( HWND16 parent
, WORD action
)
2970 FIXME(win
, "(%04x, %d): stub\n", parent
, action
);
2973 /***********************************************************************
2974 * CascageChildWindows (USER.198)
2976 void WINAPI
CascadeChildWindows16( HWND16 parent
, WORD action
)
2978 FIXME(win
, "(%04x, %d): stub\n", parent
, action
);
2980 /***********************************************************************
2981 * GetProgmanWindow [USER32.289]
2983 HRESULT WINAPI
GetProgmanWindow ( )
2984 { FIXME(win
,"stub\n");
2987 /***********************************************************************
2988 * GetTaskmanWindow [USER32.304]
2990 HRESULT WINAPI
GetTaskmanWindow ( )
2991 { FIXME(win
,"stub\n");
2994 /***********************************************************************
2995 * SetProgmanWindow [USER32.522]
2997 HRESULT WINAPI
SetProgmanWindow ( DWORD x
)
2998 { FIXME(win
,"0x%08lx stub\n",x
);
3001 /***********************************************************************
3002 * SetShellWindowEx [USER32.531]
3004 HRESULT WINAPI
SetShellWindowEx ( DWORD x
, DWORD y
)
3005 { FIXME(win
,"0x%08lx 0x%08lx stub\n",x
,y
);
3008 /***********************************************************************
3009 * SetTaskmanWindow [USER32.537]
3011 HRESULT WINAPI
SetTaskmanWindow ( DWORD x
)
3012 { FIXME(win
,"0x%08lx stub\n",x
);