2 * Window position related functions.
4 * Copyright 1993, 1994, 1995 Alexandre Julliard
5 * 1995, 1996, 1999 Alex Korobka
12 #include "wine/winuser16.h"
25 #include "nonclient.h"
26 #include "debugtools.h"
31 DEFAULT_DEBUG_CHANNEL(win
)
33 #define HAS_DLGFRAME(style,exStyle) \
34 (((exStyle) & WS_EX_DLGMODALFRAME) || \
35 (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
37 #define HAS_THICKFRAME(style) \
38 (((style) & WS_THICKFRAME) && \
39 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
41 #define SWP_AGG_NOGEOMETRYCHANGE \
42 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
43 #define SWP_AGG_NOPOSCHANGE \
44 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
45 #define SWP_AGG_STATUSFLAGS \
46 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
48 #define EMPTYPOINT(pt) ((*(LONG*)&(pt)) == -1)
50 #define PLACE_MIN 0x0001
51 #define PLACE_MAX 0x0002
52 #define PLACE_RECT 0x0004
54 #define SWP_EX_NOCOPY 0x0001
55 #define SWP_EX_PAINTSELF 0x0002
56 #define SWP_EX_NONCLIENT 0x0004
58 #define MINMAX_NOSWP 0x00010000
60 /* ----- internal variables ----- */
62 static HWND hwndPrevActive
= 0; /* Previously active window */
63 static HWND hGlobalShellWindow
=0; /*the shell*/
64 static HWND hGlobalTaskmanWindow
=0;
65 static HWND hGlobalProgmanWindow
=0;
67 static LPCSTR atomInternalPos
;
69 extern HQUEUE16 hActiveQueue
;
71 /***********************************************************************
72 * WINPOS_CreateInternalPosAtom
74 BOOL
WINPOS_CreateInternalPosAtom()
77 atomInternalPos
= (LPCSTR
)(DWORD
)GlobalAddAtomA(str
);
78 return (atomInternalPos
) ? TRUE
: FALSE
;
81 /***********************************************************************
82 * WINPOS_CheckInternalPos
84 * Called when a window is destroyed.
86 void WINPOS_CheckInternalPos( WND
* wndPtr
)
89 MESSAGEQUEUE
*pMsgQ
= 0;
90 HWND hwnd
= wndPtr
->hwndSelf
;
92 lpPos
= (LPINTERNALPOS
) GetPropA( hwnd
, atomInternalPos
);
94 /* Retrieve the message queue associated with this window */
95 pMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( wndPtr
->hmemTaskQ
);
98 WARN("\tMessage queue not found. Exiting!\n" );
102 if( hwnd
== hwndPrevActive
) hwndPrevActive
= 0;
104 if( hwnd
== PERQDATA_GetActiveWnd( pMsgQ
->pQData
) )
106 PERQDATA_SetActiveWnd( pMsgQ
->pQData
, 0 );
107 WARN("\tattempt to activate destroyed window!\n");
112 if( IsWindow(lpPos
->hwndIconTitle
) )
113 DestroyWindow( lpPos
->hwndIconTitle
);
114 HeapFree( SystemHeap
, 0, lpPos
);
117 QUEUE_Unlock( pMsgQ
);
121 /***********************************************************************
124 * Find a suitable place for an iconic window.
126 static POINT16
WINPOS_FindIconPos( WND
* wndPtr
, POINT16 pt
)
129 short x
, y
, xspacing
, yspacing
;
131 GetClientRect16( wndPtr
->parent
->hwndSelf
, &rectParent
);
132 if ((pt
.x
>= rectParent
.left
) && (pt
.x
+ GetSystemMetrics(SM_CXICON
) < rectParent
.right
) &&
133 (pt
.y
>= rectParent
.top
) && (pt
.y
+ GetSystemMetrics(SM_CYICON
) < rectParent
.bottom
))
134 return pt
; /* The icon already has a suitable position */
136 xspacing
= GetSystemMetrics(SM_CXICONSPACING
);
137 yspacing
= GetSystemMetrics(SM_CYICONSPACING
);
139 y
= rectParent
.bottom
;
145 /* Check if another icon already occupies this spot */
146 WND
*childPtr
= WIN_LockWndPtr(wndPtr
->parent
->child
);
149 if ((childPtr
->dwStyle
& WS_MINIMIZE
) && (childPtr
!= wndPtr
))
151 if ((childPtr
->rectWindow
.left
< x
+ xspacing
) &&
152 (childPtr
->rectWindow
.right
>= x
) &&
153 (childPtr
->rectWindow
.top
<= y
) &&
154 (childPtr
->rectWindow
.bottom
> y
- yspacing
))
155 break; /* There's a window in there */
157 WIN_UpdateWndPtr(&childPtr
,childPtr
->next
);
159 WIN_ReleaseWndPtr(childPtr
);
160 if (!childPtr
) /* No window was found, so it's OK for us */
162 pt
.x
= x
+ (xspacing
- GetSystemMetrics(SM_CXICON
)) / 2;
163 pt
.y
= y
- (yspacing
+ GetSystemMetrics(SM_CYICON
)) / 2;
167 } while(x
<= rectParent
.right
-xspacing
);
173 /***********************************************************************
174 * ArrangeIconicWindows16 (USER.170)
176 UINT16 WINAPI
ArrangeIconicWindows16( HWND16 parent
)
178 return ArrangeIconicWindows(parent
);
180 /***********************************************************************
181 * ArrangeIconicWindows (USER32.7)
183 UINT WINAPI
ArrangeIconicWindows( HWND parent
)
187 INT x
, y
, xspacing
, yspacing
;
189 GetClientRect( parent
, &rectParent
);
191 y
= rectParent
.bottom
;
192 xspacing
= GetSystemMetrics(SM_CXICONSPACING
);
193 yspacing
= GetSystemMetrics(SM_CYICONSPACING
);
195 hwndChild
= GetWindow( parent
, GW_CHILD
);
198 if( IsIconic( hwndChild
) )
200 WND
*wndPtr
= WIN_FindWndPtr(hwndChild
);
202 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
204 SetWindowPos( hwndChild
, 0, x
+ (xspacing
- GetSystemMetrics(SM_CXICON
)) / 2,
205 y
- yspacing
- GetSystemMetrics(SM_CYICON
)/2, 0, 0,
206 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
207 if( IsWindow(hwndChild
) )
208 WINPOS_ShowIconTitle(wndPtr
, TRUE
);
209 WIN_ReleaseWndPtr(wndPtr
);
211 if (x
<= rectParent
.right
- xspacing
) x
+= xspacing
;
218 hwndChild
= GetWindow( hwndChild
, GW_HWNDNEXT
);
224 /***********************************************************************
225 * SwitchToThisWindow16 (USER.172)
227 void WINAPI
SwitchToThisWindow16( HWND16 hwnd
, BOOL16 restore
)
229 SwitchToThisWindow( hwnd
, restore
);
233 /***********************************************************************
234 * SwitchToThisWindow (USER32.539)
236 void WINAPI
SwitchToThisWindow( HWND hwnd
, BOOL restore
)
238 ShowWindow( hwnd
, restore
? SW_RESTORE
: SW_SHOWMINIMIZED
);
242 /***********************************************************************
243 * GetWindowRect16 (USER.32)
245 void WINAPI
GetWindowRect16( HWND16 hwnd
, LPRECT16 rect
)
247 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
250 CONV_RECT32TO16( &wndPtr
->rectWindow
, rect
);
251 if (wndPtr
->dwStyle
& WS_CHILD
)
252 MapWindowPoints16( wndPtr
->parent
->hwndSelf
, 0, (POINT16
*)rect
, 2 );
253 WIN_ReleaseWndPtr(wndPtr
);
257 /***********************************************************************
258 * GetWindowRect (USER32.308)
260 BOOL WINAPI
GetWindowRect( HWND hwnd
, LPRECT rect
)
262 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
263 if (!wndPtr
) return FALSE
;
265 *rect
= wndPtr
->rectWindow
;
266 if (wndPtr
->dwStyle
& WS_CHILD
)
267 MapWindowPoints( wndPtr
->parent
->hwndSelf
, 0, (POINT
*)rect
, 2 );
268 WIN_ReleaseWndPtr(wndPtr
);
273 /***********************************************************************
276 BOOL WINAPI
GetWindowRgn ( HWND hwnd
, HRGN hrgn
)
280 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
281 if (!wndPtr
) return (ERROR
);
283 FIXME("GetWindowRgn: doesn't really do regions\n");
285 memset (&rect
, 0, sizeof(rect
));
287 GetWindowRect ( hwnd
, &rect
);
289 FIXME("Check whether a valid region here\n");
291 SetRectRgn ( hrgn
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
293 WIN_ReleaseWndPtr(wndPtr
);
294 return (SIMPLEREGION
);
297 /***********************************************************************
300 INT WINAPI
SetWindowRgn( HWND hwnd
, HRGN hrgn
,BOOL bRedraw
)
304 FIXME("SetWindowRgn: stub\n");
308 /***********************************************************************
311 INT16 WINAPI
SetWindowRgn16( HWND16 hwnd
, HRGN16 hrgn
,BOOL16 bRedraw
)
315 FIXME("SetWindowRgn16: stub\n");
320 /***********************************************************************
321 * GetClientRect16 (USER.33)
323 void WINAPI
GetClientRect16( HWND16 hwnd
, LPRECT16 rect
)
325 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
327 rect
->left
= rect
->top
= rect
->right
= rect
->bottom
= 0;
330 rect
->right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
331 rect
->bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
333 WIN_ReleaseWndPtr(wndPtr
);
337 /***********************************************************************
338 * GetClientRect (USER.220)
340 BOOL WINAPI
GetClientRect( HWND hwnd
, LPRECT rect
)
342 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
344 rect
->left
= rect
->top
= rect
->right
= rect
->bottom
= 0;
345 if (!wndPtr
) return FALSE
;
346 rect
->right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
347 rect
->bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
349 WIN_ReleaseWndPtr(wndPtr
);
354 /*******************************************************************
355 * ClientToScreen16 (USER.28)
357 void WINAPI
ClientToScreen16( HWND16 hwnd
, LPPOINT16 lppnt
)
359 MapWindowPoints16( hwnd
, 0, lppnt
, 1 );
363 /*******************************************************************
364 * ClientToScreen (USER32.52)
366 BOOL WINAPI
ClientToScreen( HWND hwnd
, LPPOINT lppnt
)
368 MapWindowPoints( hwnd
, 0, lppnt
, 1 );
373 /*******************************************************************
374 * ScreenToClient16 (USER.29)
376 void WINAPI
ScreenToClient16( HWND16 hwnd
, LPPOINT16 lppnt
)
378 MapWindowPoints16( 0, hwnd
, lppnt
, 1 );
382 /*******************************************************************
383 * ScreenToClient (USER32.447)
385 BOOL WINAPI
ScreenToClient( HWND hwnd
, LPPOINT lppnt
)
387 MapWindowPoints( 0, hwnd
, lppnt
, 1 );
392 /***********************************************************************
393 * WINPOS_WindowFromPoint
395 * Find the window and hittest for a given point.
397 INT16
WINPOS_WindowFromPoint( WND
* wndScope
, POINT16 pt
, WND
**ppWnd
)
400 INT16 hittest
= HTERROR
;
405 wndPtr
= WIN_LockWndPtr(wndScope
->child
);
407 if( wndScope
->dwStyle
& WS_DISABLED
)
413 if( wndScope
->flags
& WIN_MANAGED
)
415 /* In managed mode we have to check wndScope first as it is also
416 * a window which received the mouse event. */
418 if( pt
.x
< wndScope
->rectClient
.left
|| pt
.x
>= wndScope
->rectClient
.right
||
419 pt
.y
< wndScope
->rectClient
.top
|| pt
.y
>= wndScope
->rectClient
.bottom
)
422 MapWindowPoints16( GetDesktopWindow16(), wndScope
->hwndSelf
, &xy
, 1 );
428 /* If point is in window, and window is visible, and it */
429 /* is enabled (or it's a top-level window), then explore */
430 /* its children. Otherwise, go to the next window. */
432 if ((wndPtr
->dwStyle
& WS_VISIBLE
) &&
433 (!(wndPtr
->dwStyle
& WS_DISABLED
) ||
434 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)) &&
435 (xy
.x
>= wndPtr
->rectWindow
.left
) &&
436 (xy
.x
< wndPtr
->rectWindow
.right
) &&
437 (xy
.y
>= wndPtr
->rectWindow
.top
) &&
438 (xy
.y
< wndPtr
->rectWindow
.bottom
))
440 *ppWnd
= wndPtr
; /* Got a suitable window */
442 /* If window is minimized or disabled, return at once */
443 if (wndPtr
->dwStyle
& WS_MINIMIZE
)
445 retvalue
= HTCAPTION
;
448 if (wndPtr
->dwStyle
& WS_DISABLED
)
454 /* If point is not in client area, ignore the children */
455 if ((xy
.x
< wndPtr
->rectClient
.left
) ||
456 (xy
.x
>= wndPtr
->rectClient
.right
) ||
457 (xy
.y
< wndPtr
->rectClient
.top
) ||
458 (xy
.y
>= wndPtr
->rectClient
.bottom
)) break;
460 xy
.x
-= wndPtr
->rectClient
.left
;
461 xy
.y
-= wndPtr
->rectClient
.top
;
462 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->child
);
466 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->next
);
471 /* If nothing found, try the scope window */
472 if (!*ppWnd
) *ppWnd
= wndScope
;
474 /* Send the WM_NCHITTEST message (only if to the same task) */
475 if ((*ppWnd
)->hmemTaskQ
== GetFastQueue16())
477 hittest
= (INT16
)SendMessage16( (*ppWnd
)->hwndSelf
, WM_NCHITTEST
,
478 0, MAKELONG( pt
.x
, pt
.y
) );
479 if (hittest
!= HTTRANSPARENT
)
481 retvalue
= hittest
; /* Found the window */
491 /* If no children found in last search, make point relative to parent */
494 xy
.x
+= (*ppWnd
)->rectClient
.left
;
495 xy
.y
+= (*ppWnd
)->rectClient
.top
;
498 /* Restart the search from the next sibling */
499 WIN_UpdateWndPtr(&wndPtr
,(*ppWnd
)->next
);
500 *ppWnd
= (*ppWnd
)->parent
;
504 WIN_ReleaseWndPtr(wndPtr
);
509 /*******************************************************************
510 * WindowFromPoint16 (USER.30)
512 HWND16 WINAPI
WindowFromPoint16( POINT16 pt
)
515 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt
, &pWnd
);
516 WIN_ReleaseDesktop();
517 return pWnd
->hwndSelf
;
521 /*******************************************************************
522 * WindowFromPoint (USER32.582)
524 HWND WINAPI
WindowFromPoint( POINT pt
)
528 CONV_POINT32TO16( &pt
, &pt16
);
529 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16
, &pWnd
);
530 WIN_ReleaseDesktop();
531 return (HWND
)pWnd
->hwndSelf
;
535 /*******************************************************************
536 * ChildWindowFromPoint16 (USER.191)
538 HWND16 WINAPI
ChildWindowFromPoint16( HWND16 hwndParent
, POINT16 pt
)
541 CONV_POINT16TO32( &pt
, &pt32
);
542 return (HWND16
)ChildWindowFromPoint( hwndParent
, pt32
);
546 /*******************************************************************
547 * ChildWindowFromPoint (USER32.49)
549 HWND WINAPI
ChildWindowFromPoint( HWND hwndParent
, POINT pt
)
551 /* pt is in the client coordinates */
553 WND
* wnd
= WIN_FindWndPtr(hwndParent
);
559 /* get client rect fast */
560 rect
.top
= rect
.left
= 0;
561 rect
.right
= wnd
->rectClient
.right
- wnd
->rectClient
.left
;
562 rect
.bottom
= wnd
->rectClient
.bottom
- wnd
->rectClient
.top
;
564 if (!PtInRect( &rect
, pt
))
569 WIN_UpdateWndPtr(&wnd
,wnd
->child
);
572 if (PtInRect( &wnd
->rectWindow
, pt
))
574 retvalue
= wnd
->hwndSelf
;
577 WIN_UpdateWndPtr(&wnd
,wnd
->next
);
579 retvalue
= hwndParent
;
581 WIN_ReleaseWndPtr(wnd
);
585 /*******************************************************************
586 * ChildWindowFromPointEx16 (USER.50)
588 HWND16 WINAPI
ChildWindowFromPointEx16( HWND16 hwndParent
, POINT16 pt
, UINT16 uFlags
)
591 CONV_POINT16TO32( &pt
, &pt32
);
592 return (HWND16
)ChildWindowFromPointEx( hwndParent
, pt32
, uFlags
);
596 /*******************************************************************
597 * ChildWindowFromPointEx (USER32.50)
599 HWND WINAPI
ChildWindowFromPointEx( HWND hwndParent
, POINT pt
,
602 /* pt is in the client coordinates */
604 WND
* wnd
= WIN_FindWndPtr(hwndParent
);
610 /* get client rect fast */
611 rect
.top
= rect
.left
= 0;
612 rect
.right
= wnd
->rectClient
.right
- wnd
->rectClient
.left
;
613 rect
.bottom
= wnd
->rectClient
.bottom
- wnd
->rectClient
.top
;
615 if (!PtInRect( &rect
, pt
))
620 WIN_UpdateWndPtr(&wnd
,wnd
->child
);
624 if (PtInRect( &wnd
->rectWindow
, pt
)) {
625 if ( (uFlags
& CWP_SKIPINVISIBLE
) &&
626 !(wnd
->dwStyle
& WS_VISIBLE
) );
627 else if ( (uFlags
& CWP_SKIPDISABLED
) &&
628 (wnd
->dwStyle
& WS_DISABLED
) );
629 else if ( (uFlags
& CWP_SKIPTRANSPARENT
) &&
630 (wnd
->dwExStyle
& WS_EX_TRANSPARENT
) );
633 retvalue
= wnd
->hwndSelf
;
638 WIN_UpdateWndPtr(&wnd
,wnd
->next
);
640 retvalue
= hwndParent
;
642 WIN_ReleaseWndPtr(wnd
);
647 /*******************************************************************
648 * WINPOS_GetWinOffset
650 * Calculate the offset between the origin of the two windows. Used
651 * to implement MapWindowPoints.
653 static void WINPOS_GetWinOffset( HWND hwndFrom
, HWND hwndTo
,
658 offset
->x
= offset
->y
= 0;
659 if (hwndFrom
== hwndTo
) return;
661 /* Translate source window origin to screen coords */
664 if (!(wndPtr
= WIN_FindWndPtr( hwndFrom
)))
666 ERR("bad hwndFrom = %04x\n",hwndFrom
);
669 while (wndPtr
->parent
)
671 offset
->x
+= wndPtr
->rectClient
.left
;
672 offset
->y
+= wndPtr
->rectClient
.top
;
673 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->parent
);
675 WIN_ReleaseWndPtr(wndPtr
);
678 /* Translate origin to destination window coords */
681 if (!(wndPtr
= WIN_FindWndPtr( hwndTo
)))
683 ERR("bad hwndTo = %04x\n", hwndTo
);
686 while (wndPtr
->parent
)
688 offset
->x
-= wndPtr
->rectClient
.left
;
689 offset
->y
-= wndPtr
->rectClient
.top
;
690 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->parent
);
692 WIN_ReleaseWndPtr(wndPtr
);
697 /*******************************************************************
698 * MapWindowPoints16 (USER.258)
700 void WINAPI
MapWindowPoints16( HWND16 hwndFrom
, HWND16 hwndTo
,
701 LPPOINT16 lppt
, UINT16 count
)
705 WINPOS_GetWinOffset( hwndFrom
, hwndTo
, &offset
);
715 /*******************************************************************
716 * MapWindowPoints (USER32.386)
718 INT WINAPI
MapWindowPoints( HWND hwndFrom
, HWND hwndTo
,
719 LPPOINT lppt
, UINT count
)
723 WINPOS_GetWinOffset( hwndFrom
, hwndTo
, &offset
);
730 return MAKELONG( LOWORD(offset
.x
), LOWORD(offset
.y
) );
734 /***********************************************************************
735 * IsIconic16 (USER.31)
737 BOOL16 WINAPI
IsIconic16(HWND16 hWnd
)
739 return IsIconic(hWnd
);
743 /***********************************************************************
744 * IsIconic (USER32.345)
746 BOOL WINAPI
IsIconic(HWND hWnd
)
749 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
750 if (wndPtr
== NULL
) return FALSE
;
751 retvalue
= (wndPtr
->dwStyle
& WS_MINIMIZE
) != 0;
752 WIN_ReleaseWndPtr(wndPtr
);
757 /***********************************************************************
758 * IsZoomed (USER.272)
760 BOOL16 WINAPI
IsZoomed16(HWND16 hWnd
)
762 return IsZoomed(hWnd
);
766 /***********************************************************************
767 * IsZoomed (USER.352)
769 BOOL WINAPI
IsZoomed(HWND hWnd
)
772 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
773 if (wndPtr
== NULL
) return FALSE
;
774 retvalue
= (wndPtr
->dwStyle
& WS_MAXIMIZE
) != 0;
775 WIN_ReleaseWndPtr(wndPtr
);
780 /*******************************************************************
781 * GetActiveWindow (USER.60)
783 HWND16 WINAPI
GetActiveWindow16(void)
785 return (HWND16
)GetActiveWindow();
788 /*******************************************************************
789 * GetActiveWindow (USER32.205)
791 HWND WINAPI
GetActiveWindow(void)
793 MESSAGEQUEUE
*pCurMsgQ
= 0;
796 /* Get the messageQ for the current thread */
797 if (!(pCurMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( GetFastQueue16() )))
799 WARN("\tCurrent message queue not found. Exiting!\n" );
803 /* Return the current active window from the perQ data of the current message Q */
804 hwndActive
= PERQDATA_GetActiveWnd( pCurMsgQ
->pQData
);
806 QUEUE_Unlock( pCurMsgQ
);
811 /*******************************************************************
814 static BOOL
WINPOS_CanActivate(WND
* pWnd
)
816 if( pWnd
&& ( (pWnd
->dwStyle
& (WS_DISABLED
| WS_VISIBLE
| WS_CHILD
))
817 == WS_VISIBLE
) ) return TRUE
;
822 /*******************************************************************
823 * SetActiveWindow16 (USER.59)
825 HWND16 WINAPI
SetActiveWindow16( HWND16 hwnd
)
827 return SetActiveWindow(hwnd
);
831 /*******************************************************************
832 * SetActiveWindow (USER32.463)
834 HWND WINAPI
SetActiveWindow( HWND hwnd
)
837 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
838 MESSAGEQUEUE
*pMsgQ
= 0, *pCurMsgQ
= 0;
840 if (!wndPtr
|| (wndPtr
->dwStyle
& (WS_DISABLED
| WS_CHILD
)))
846 /* Get the messageQ for the current thread */
847 if (!(pCurMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( GetFastQueue16() )))
849 WARN("\tCurrent message queue not found. Exiting!\n" );
853 /* Retrieve the message queue associated with this window */
854 pMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( wndPtr
->hmemTaskQ
);
857 WARN("\tWindow message queue not found. Exiting!\n" );
861 /* Make sure that the window is associated with the calling threads
862 * message queue. It must share the same perQ data.
865 if ( pCurMsgQ
->pQData
!= pMsgQ
->pQData
)
868 /* Save current active window */
869 prev
= PERQDATA_GetActiveWnd( pMsgQ
->pQData
);
871 WINPOS_SetActiveWindow( hwnd
, 0, 0 );
874 /* Unlock the queues before returning */
876 QUEUE_Unlock( pMsgQ
);
878 QUEUE_Unlock( pCurMsgQ
);
881 WIN_ReleaseWndPtr(wndPtr
);
886 /*******************************************************************
887 * GetForegroundWindow16 (USER.608)
889 HWND16 WINAPI
GetForegroundWindow16(void)
891 return (HWND16
)GetForegroundWindow();
895 /*******************************************************************
896 * SetForegroundWindow16 (USER.609)
898 BOOL16 WINAPI
SetForegroundWindow16( HWND16 hwnd
)
900 return SetForegroundWindow( hwnd
);
904 /*******************************************************************
905 * GetForegroundWindow (USER32.241)
907 HWND WINAPI
GetForegroundWindow(void)
911 /* Get the foreground window (active window of hActiveQueue) */
914 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
916 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
918 QUEUE_Unlock( pActiveQueue
);
924 /*******************************************************************
925 * SetForegroundWindow (USER32.482)
927 BOOL WINAPI
SetForegroundWindow( HWND hwnd
)
929 return WINPOS_ChangeActiveWindow( hwnd
, FALSE
);
933 /*******************************************************************
934 * GetShellWindow16 (USER.600)
936 HWND16 WINAPI
GetShellWindow16(void)
938 return GetShellWindow();
941 /*******************************************************************
942 * SetShellWindow (USER32.504)
944 HWND WINAPI
SetShellWindow(HWND hwndshell
)
945 { WARN("(hWnd=%08x) semi stub\n",hwndshell
);
947 hGlobalShellWindow
= hwndshell
;
948 return hGlobalShellWindow
;
952 /*******************************************************************
953 * GetShellWindow (USER32.287)
955 HWND WINAPI
GetShellWindow(void)
956 { WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow
);
958 return hGlobalShellWindow
;
962 /***********************************************************************
963 * BringWindowToTop16 (USER.45)
965 BOOL16 WINAPI
BringWindowToTop16( HWND16 hwnd
)
967 return BringWindowToTop(hwnd
);
971 /***********************************************************************
972 * BringWindowToTop (USER32.11)
974 BOOL WINAPI
BringWindowToTop( HWND hwnd
)
976 return SetWindowPos( hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
);
980 /***********************************************************************
981 * MoveWindow16 (USER.56)
983 BOOL16 WINAPI
MoveWindow16( HWND16 hwnd
, INT16 x
, INT16 y
, INT16 cx
, INT16 cy
,
986 return MoveWindow(hwnd
,x
,y
,cx
,cy
,repaint
);
990 /***********************************************************************
991 * MoveWindow (USER32.399)
993 BOOL WINAPI
MoveWindow( HWND hwnd
, INT x
, INT y
, INT cx
, INT cy
,
996 int flags
= SWP_NOZORDER
| SWP_NOACTIVATE
;
997 if (!repaint
) flags
|= SWP_NOREDRAW
;
998 TRACE("%04x %d,%d %dx%d %d\n",
999 hwnd
, x
, y
, cx
, cy
, repaint
);
1000 return SetWindowPos( hwnd
, 0, x
, y
, cx
, cy
, flags
);
1003 /***********************************************************************
1004 * WINPOS_InitInternalPos
1006 static LPINTERNALPOS
WINPOS_InitInternalPos( WND
* wnd
, POINT pt
,
1007 LPRECT restoreRect
)
1009 LPINTERNALPOS lpPos
= (LPINTERNALPOS
) GetPropA( wnd
->hwndSelf
,
1013 /* this happens when the window is minimized/maximized
1014 * for the first time (rectWindow is not adjusted yet) */
1016 lpPos
= HeapAlloc( SystemHeap
, 0, sizeof(INTERNALPOS
) );
1017 if( !lpPos
) return NULL
;
1019 SetPropA( wnd
->hwndSelf
, atomInternalPos
, (HANDLE
)lpPos
);
1020 lpPos
->hwndIconTitle
= 0; /* defer until needs to be shown */
1021 CONV_RECT32TO16( &wnd
->rectWindow
, &lpPos
->rectNormal
);
1022 *(UINT
*)&lpPos
->ptIconPos
= *(UINT
*)&lpPos
->ptMaxPos
= 0xFFFFFFFF;
1025 if( wnd
->dwStyle
& WS_MINIMIZE
)
1026 CONV_POINT32TO16( &pt
, &lpPos
->ptIconPos
);
1027 else if( wnd
->dwStyle
& WS_MAXIMIZE
)
1028 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1029 else if( restoreRect
)
1030 CONV_RECT32TO16( restoreRect
, &lpPos
->rectNormal
);
1035 /***********************************************************************
1036 * WINPOS_RedrawIconTitle
1038 BOOL
WINPOS_RedrawIconTitle( HWND hWnd
)
1040 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)GetPropA( hWnd
, atomInternalPos
);
1043 if( lpPos
->hwndIconTitle
)
1045 SendMessageA( lpPos
->hwndIconTitle
, WM_SHOWWINDOW
, TRUE
, 0);
1046 InvalidateRect( lpPos
->hwndIconTitle
, NULL
, TRUE
);
1053 /***********************************************************************
1054 * WINPOS_ShowIconTitle
1056 BOOL
WINPOS_ShowIconTitle( WND
* pWnd
, BOOL bShow
)
1058 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)GetPropA( pWnd
->hwndSelf
, atomInternalPos
);
1060 if( lpPos
&& !(pWnd
->flags
& WIN_MANAGED
))
1062 HWND16 hWnd
= lpPos
->hwndIconTitle
;
1064 TRACE("0x%04x %i\n", pWnd
->hwndSelf
, (bShow
!= 0) );
1067 lpPos
->hwndIconTitle
= hWnd
= ICONTITLE_Create( pWnd
);
1070 if( ( pWnd
= WIN_FindWndPtr(hWnd
) ) != NULL
)
1072 if( !(pWnd
->dwStyle
& WS_VISIBLE
) )
1074 SendMessageA( hWnd
, WM_SHOWWINDOW
, TRUE
, 0 );
1075 SetWindowPos( hWnd
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
1076 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_SHOWWINDOW
);
1078 WIN_ReleaseWndPtr(pWnd
);
1081 else ShowWindow( hWnd
, SW_HIDE
);
1086 /*******************************************************************
1087 * WINPOS_GetMinMaxInfo
1089 * Get the minimized and maximized information for a window.
1091 void WINPOS_GetMinMaxInfo( WND
*wndPtr
, POINT
*maxSize
, POINT
*maxPos
,
1092 POINT
*minTrack
, POINT
*maxTrack
)
1094 LPINTERNALPOS lpPos
;
1098 /* Compute default values */
1100 MinMax
.ptMaxSize
.x
= GetSystemMetrics(SM_CXSCREEN
);
1101 MinMax
.ptMaxSize
.y
= GetSystemMetrics(SM_CYSCREEN
);
1102 MinMax
.ptMinTrackSize
.x
= GetSystemMetrics(SM_CXMINTRACK
);
1103 MinMax
.ptMinTrackSize
.y
= GetSystemMetrics(SM_CYMINTRACK
);
1104 MinMax
.ptMaxTrackSize
.x
= GetSystemMetrics(SM_CXSCREEN
);
1105 MinMax
.ptMaxTrackSize
.y
= GetSystemMetrics(SM_CYSCREEN
);
1107 if (wndPtr
->flags
& WIN_MANAGED
) xinc
= yinc
= 0;
1108 else if (HAS_DLGFRAME( wndPtr
->dwStyle
, wndPtr
->dwExStyle
))
1110 xinc
= GetSystemMetrics(SM_CXDLGFRAME
);
1111 yinc
= GetSystemMetrics(SM_CYDLGFRAME
);
1116 if (HAS_THICKFRAME(wndPtr
->dwStyle
))
1118 xinc
+= GetSystemMetrics(SM_CXFRAME
);
1119 yinc
+= GetSystemMetrics(SM_CYFRAME
);
1121 if (wndPtr
->dwStyle
& WS_BORDER
)
1123 xinc
+= GetSystemMetrics(SM_CXBORDER
);
1124 yinc
+= GetSystemMetrics(SM_CYBORDER
);
1127 MinMax
.ptMaxSize
.x
+= 2 * xinc
;
1128 MinMax
.ptMaxSize
.y
+= 2 * yinc
;
1130 lpPos
= (LPINTERNALPOS
)GetPropA( wndPtr
->hwndSelf
, atomInternalPos
);
1131 if( lpPos
&& !EMPTYPOINT(lpPos
->ptMaxPos
) )
1132 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &MinMax
.ptMaxPosition
);
1135 MinMax
.ptMaxPosition
.x
= -xinc
;
1136 MinMax
.ptMaxPosition
.y
= -yinc
;
1139 SendMessageA( wndPtr
->hwndSelf
, WM_GETMINMAXINFO
, 0, (LPARAM
)&MinMax
);
1141 /* Some sanity checks */
1143 TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1144 MinMax
.ptMaxSize
.x
, MinMax
.ptMaxSize
.y
,
1145 MinMax
.ptMaxPosition
.x
, MinMax
.ptMaxPosition
.y
,
1146 MinMax
.ptMaxTrackSize
.x
, MinMax
.ptMaxTrackSize
.y
,
1147 MinMax
.ptMinTrackSize
.x
, MinMax
.ptMinTrackSize
.y
);
1148 MinMax
.ptMaxTrackSize
.x
= max( MinMax
.ptMaxTrackSize
.x
,
1149 MinMax
.ptMinTrackSize
.x
);
1150 MinMax
.ptMaxTrackSize
.y
= max( MinMax
.ptMaxTrackSize
.y
,
1151 MinMax
.ptMinTrackSize
.y
);
1153 if (maxSize
) *maxSize
= MinMax
.ptMaxSize
;
1154 if (maxPos
) *maxPos
= MinMax
.ptMaxPosition
;
1155 if (minTrack
) *minTrack
= MinMax
.ptMinTrackSize
;
1156 if (maxTrack
) *maxTrack
= MinMax
.ptMaxTrackSize
;
1159 /***********************************************************************
1160 * WINPOS_MinMaximize
1162 * Fill in lpRect and return additional flags to be used with SetWindowPos().
1163 * This function assumes that 'cmd' is different from the current window
1166 UINT
WINPOS_MinMaximize( WND
* wndPtr
, UINT16 cmd
, LPRECT16 lpRect
)
1170 LPINTERNALPOS lpPos
;
1172 TRACE("0x%04x %u\n", wndPtr
->hwndSelf
, cmd
);
1174 size
.x
= wndPtr
->rectWindow
.left
; size
.y
= wndPtr
->rectWindow
.top
;
1175 lpPos
= WINPOS_InitInternalPos( wndPtr
, size
, &wndPtr
->rectWindow
);
1177 if (lpPos
&& !HOOK_CallHooks16(WH_CBT
, HCBT_MINMAX
, wndPtr
->hwndSelf
, cmd
))
1179 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1181 if( !SendMessageA( wndPtr
->hwndSelf
, WM_QUERYOPEN
, 0, 0L ) )
1182 return (SWP_NOSIZE
| SWP_NOMOVE
);
1183 swpFlags
|= SWP_NOCOPYBITS
;
1188 if( wndPtr
->dwStyle
& WS_MAXIMIZE
)
1190 wndPtr
->flags
|= WIN_RESTORE_MAX
;
1191 wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
1194 wndPtr
->flags
&= ~WIN_RESTORE_MAX
;
1195 wndPtr
->dwStyle
|= WS_MINIMIZE
;
1197 if( wndPtr
->flags
& WIN_NATIVE
)
1198 if( wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, TRUE
) )
1199 swpFlags
|= MINMAX_NOSWP
;
1201 lpPos
->ptIconPos
= WINPOS_FindIconPos( wndPtr
, lpPos
->ptIconPos
);
1203 SetRect16( lpRect
, lpPos
->ptIconPos
.x
, lpPos
->ptIconPos
.y
,
1204 GetSystemMetrics(SM_CXICON
), GetSystemMetrics(SM_CYICON
) );
1205 swpFlags
|= SWP_NOCOPYBITS
;
1209 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &pt
);
1210 WINPOS_GetMinMaxInfo( wndPtr
, &size
, &pt
, NULL
, NULL
);
1211 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1213 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1215 if( wndPtr
->flags
& WIN_NATIVE
)
1216 if( wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, FALSE
) )
1217 swpFlags
|= MINMAX_NOSWP
;
1219 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
1220 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
1222 wndPtr
->dwStyle
|= WS_MAXIMIZE
;
1224 SetRect16( lpRect
, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
,
1229 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1231 if( wndPtr
->flags
& WIN_NATIVE
)
1232 if( wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, FALSE
) )
1233 swpFlags
|= MINMAX_NOSWP
;
1235 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
1236 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
1238 if( wndPtr
->flags
& WIN_RESTORE_MAX
)
1240 /* Restore to maximized position */
1241 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &pt
);
1242 WINPOS_GetMinMaxInfo( wndPtr
, &size
, &pt
, NULL
, NULL
);
1243 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1244 wndPtr
->dwStyle
|= WS_MAXIMIZE
;
1245 SetRect16( lpRect
, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
, size
.x
, size
.y
);
1250 if( !(wndPtr
->dwStyle
& WS_MAXIMIZE
) ) return (UINT16
)(-1);
1251 else wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
1253 /* Restore to normal position */
1255 *lpRect
= lpPos
->rectNormal
;
1256 lpRect
->right
-= lpRect
->left
;
1257 lpRect
->bottom
-= lpRect
->top
;
1261 } else swpFlags
|= SWP_NOSIZE
| SWP_NOMOVE
;
1265 /***********************************************************************
1266 * ShowWindowAsync (USER32.535)
1268 * doesn't wait; returns immediately.
1269 * used by threads to toggle windows in other (possibly hanging) threads
1271 BOOL WINAPI
ShowWindowAsync( HWND hwnd
, INT cmd
)
1273 /* FIXME: does ShowWindow() return immediately ? */
1274 return ShowWindow(hwnd
, cmd
);
1278 /***********************************************************************
1279 * ShowWindow16 (USER.42)
1281 BOOL16 WINAPI
ShowWindow16( HWND16 hwnd
, INT16 cmd
)
1283 return ShowWindow(hwnd
,cmd
);
1287 /***********************************************************************
1288 * ShowWindow (USER32.534)
1290 BOOL WINAPI
ShowWindow( HWND hwnd
, INT cmd
)
1292 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
1293 BOOL wasVisible
, showFlag
;
1294 RECT16 newPos
= {0, 0, 0, 0};
1297 if (!wndPtr
) return FALSE
;
1299 TRACE("hwnd=%04x, cmd=%d\n", hwnd
, cmd
);
1301 wasVisible
= (wndPtr
->dwStyle
& WS_VISIBLE
) != 0;
1306 if (!wasVisible
) goto END
;;
1307 swp
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
|
1308 SWP_NOACTIVATE
| SWP_NOZORDER
;
1311 case SW_SHOWMINNOACTIVE
:
1312 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1314 case SW_SHOWMINIMIZED
:
1315 swp
|= SWP_SHOWWINDOW
;
1318 swp
|= SWP_FRAMECHANGED
;
1319 if( !(wndPtr
->dwStyle
& WS_MINIMIZE
) )
1320 swp
|= WINPOS_MinMaximize( wndPtr
, SW_MINIMIZE
, &newPos
);
1321 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1324 case SW_SHOWMAXIMIZED
: /* same as SW_MAXIMIZE */
1325 swp
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
1326 if( !(wndPtr
->dwStyle
& WS_MAXIMIZE
) )
1327 swp
|= WINPOS_MinMaximize( wndPtr
, SW_MAXIMIZE
, &newPos
);
1328 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1332 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1335 swp
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
1338 * ShowWindow has a little peculiar behavior that if the
1339 * window is already the topmost window, it will not
1342 if (GetTopWindow((HWND
)0)==hwnd
&& (wasVisible
|| GetActiveWindow() == hwnd
))
1343 swp
|= SWP_NOACTIVATE
;
1347 case SW_SHOWNOACTIVATE
:
1348 swp
|= SWP_NOZORDER
;
1349 if (GetActiveWindow()) swp
|= SWP_NOACTIVATE
;
1351 case SW_SHOWNORMAL
: /* same as SW_NORMAL: */
1352 case SW_SHOWDEFAULT
: /* FIXME: should have its own handler */
1354 swp
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
1356 if( wndPtr
->dwStyle
& (WS_MINIMIZE
| WS_MAXIMIZE
) )
1357 swp
|= WINPOS_MinMaximize( wndPtr
, SW_RESTORE
, &newPos
);
1358 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1362 showFlag
= (cmd
!= SW_HIDE
);
1363 if (showFlag
!= wasVisible
)
1365 SendMessageA( hwnd
, WM_SHOWWINDOW
, showFlag
, 0 );
1366 if (!IsWindow( hwnd
)) goto END
;
1369 if ((wndPtr
->dwStyle
& WS_CHILD
) &&
1370 !IsWindowVisible( wndPtr
->parent
->hwndSelf
) &&
1371 (swp
& (SWP_NOSIZE
| SWP_NOMOVE
)) == (SWP_NOSIZE
| SWP_NOMOVE
) )
1373 /* Don't call SetWindowPos() on invisible child windows */
1374 if (cmd
== SW_HIDE
) wndPtr
->dwStyle
&= ~WS_VISIBLE
;
1375 else wndPtr
->dwStyle
|= WS_VISIBLE
;
1379 /* We can't activate a child window */
1380 if ((wndPtr
->dwStyle
& WS_CHILD
) &&
1381 !(wndPtr
->dwExStyle
& WS_EX_MDICHILD
))
1382 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1383 if (!(swp
& MINMAX_NOSWP
))
1385 SetWindowPos( hwnd
, HWND_TOP
, newPos
.left
, newPos
.top
,
1386 newPos
.right
, newPos
.bottom
, LOWORD(swp
) );
1389 /* FIXME: This will cause the window to be activated irrespective
1390 * of whether it is owned by the same thread. Has to be done
1394 if (hwnd
== GetActiveWindow())
1395 WINPOS_ActivateOtherWindow(wndPtr
);
1397 /* Revert focus to parent */
1398 if (hwnd
== GetFocus() || IsChild(hwnd
, GetFocus()))
1399 SetFocus( GetParent(hwnd
) );
1402 if (!IsWindow( hwnd
)) goto END
;
1403 else if( wndPtr
->dwStyle
& WS_MINIMIZE
) WINPOS_ShowIconTitle( wndPtr
, TRUE
);
1406 if (wndPtr
->flags
& WIN_NEED_SIZE
)
1408 /* should happen only in CreateWindowEx() */
1409 int wParam
= SIZE_RESTORED
;
1411 wndPtr
->flags
&= ~WIN_NEED_SIZE
;
1412 if (wndPtr
->dwStyle
& WS_MAXIMIZE
) wParam
= SIZE_MAXIMIZED
;
1413 else if (wndPtr
->dwStyle
& WS_MINIMIZE
) wParam
= SIZE_MINIMIZED
;
1414 SendMessageA( hwnd
, WM_SIZE
, wParam
,
1415 MAKELONG(wndPtr
->rectClient
.right
-wndPtr
->rectClient
.left
,
1416 wndPtr
->rectClient
.bottom
-wndPtr
->rectClient
.top
));
1417 SendMessageA( hwnd
, WM_MOVE
, 0,
1418 MAKELONG(wndPtr
->rectClient
.left
, wndPtr
->rectClient
.top
) );
1422 WIN_ReleaseWndPtr(wndPtr
);
1427 /***********************************************************************
1428 * GetInternalWindowPos16 (USER.460)
1430 UINT16 WINAPI
GetInternalWindowPos16( HWND16 hwnd
, LPRECT16 rectWnd
,
1433 WINDOWPLACEMENT16 wndpl
;
1434 if (GetWindowPlacement16( hwnd
, &wndpl
))
1436 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
1437 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
1438 return wndpl
.showCmd
;
1444 /***********************************************************************
1445 * GetInternalWindowPos (USER32.245)
1447 UINT WINAPI
GetInternalWindowPos( HWND hwnd
, LPRECT rectWnd
,
1450 WINDOWPLACEMENT wndpl
;
1451 if (GetWindowPlacement( hwnd
, &wndpl
))
1453 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
1454 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
1455 return wndpl
.showCmd
;
1460 /***********************************************************************
1461 * GetWindowPlacement16 (USER.370)
1463 BOOL16 WINAPI
GetWindowPlacement16( HWND16 hwnd
, WINDOWPLACEMENT16
*wndpl
)
1465 WND
*pWnd
= WIN_FindWndPtr( hwnd
);
1466 LPINTERNALPOS lpPos
;
1468 if(!pWnd
) return FALSE
;
1470 lpPos
= (LPINTERNALPOS
)WINPOS_InitInternalPos( pWnd
,
1471 *(LPPOINT
)&pWnd
->rectWindow
.left
, &pWnd
->rectWindow
);
1472 wndpl
->length
= sizeof(*wndpl
);
1473 if( pWnd
->dwStyle
& WS_MINIMIZE
)
1474 wndpl
->showCmd
= SW_SHOWMINIMIZED
;
1476 wndpl
->showCmd
= ( pWnd
->dwStyle
& WS_MAXIMIZE
)
1477 ? SW_SHOWMAXIMIZED
: SW_SHOWNORMAL
;
1478 if( pWnd
->flags
& WIN_RESTORE_MAX
)
1479 wndpl
->flags
= WPF_RESTORETOMAXIMIZED
;
1482 wndpl
->ptMinPosition
= lpPos
->ptIconPos
;
1483 wndpl
->ptMaxPosition
= lpPos
->ptMaxPos
;
1484 wndpl
->rcNormalPosition
= lpPos
->rectNormal
;
1486 WIN_ReleaseWndPtr(pWnd
);
1491 /***********************************************************************
1492 * GetWindowPlacement (USER32.307)
1495 * Fails if wndpl->length of Win95 (!) apps is invalid.
1497 BOOL WINAPI
GetWindowPlacement( HWND hwnd
, WINDOWPLACEMENT
*pwpl32
)
1501 WINDOWPLACEMENT16 wpl
;
1502 wpl
.length
= sizeof(wpl
);
1503 if( GetWindowPlacement16( hwnd
, &wpl
) )
1505 pwpl32
->length
= sizeof(*pwpl32
);
1506 pwpl32
->flags
= wpl
.flags
;
1507 pwpl32
->showCmd
= wpl
.showCmd
;
1508 CONV_POINT16TO32( &wpl
.ptMinPosition
, &pwpl32
->ptMinPosition
);
1509 CONV_POINT16TO32( &wpl
.ptMaxPosition
, &pwpl32
->ptMaxPosition
);
1510 CONV_RECT16TO32( &wpl
.rcNormalPosition
, &pwpl32
->rcNormalPosition
);
1518 /***********************************************************************
1519 * WINPOS_SetPlacement
1521 static BOOL
WINPOS_SetPlacement( HWND hwnd
, const WINDOWPLACEMENT16
*wndpl
,
1524 WND
*pWnd
= WIN_FindWndPtr( hwnd
);
1527 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)WINPOS_InitInternalPos( pWnd
,
1528 *(LPPOINT
)&pWnd
->rectWindow
.left
, &pWnd
->rectWindow
);
1530 if( flags
& PLACE_MIN
) lpPos
->ptIconPos
= wndpl
->ptMinPosition
;
1531 if( flags
& PLACE_MAX
) lpPos
->ptMaxPos
= wndpl
->ptMaxPosition
;
1532 if( flags
& PLACE_RECT
) lpPos
->rectNormal
= wndpl
->rcNormalPosition
;
1534 if( pWnd
->dwStyle
& WS_MINIMIZE
)
1536 WINPOS_ShowIconTitle( pWnd
, FALSE
);
1537 if( wndpl
->flags
& WPF_SETMINPOSITION
&& !EMPTYPOINT(lpPos
->ptIconPos
))
1538 SetWindowPos( hwnd
, 0, lpPos
->ptIconPos
.x
, lpPos
->ptIconPos
.y
,
1539 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1541 else if( pWnd
->dwStyle
& WS_MAXIMIZE
)
1543 if( !EMPTYPOINT(lpPos
->ptMaxPos
) )
1544 SetWindowPos( hwnd
, 0, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
,
1545 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1547 else if( flags
& PLACE_RECT
)
1548 SetWindowPos( hwnd
, 0, lpPos
->rectNormal
.left
, lpPos
->rectNormal
.top
,
1549 lpPos
->rectNormal
.right
- lpPos
->rectNormal
.left
,
1550 lpPos
->rectNormal
.bottom
- lpPos
->rectNormal
.top
,
1551 SWP_NOZORDER
| SWP_NOACTIVATE
);
1553 ShowWindow( hwnd
, wndpl
->showCmd
);
1554 if( IsWindow(hwnd
) && pWnd
->dwStyle
& WS_MINIMIZE
)
1556 if( pWnd
->dwStyle
& WS_VISIBLE
) WINPOS_ShowIconTitle( pWnd
, TRUE
);
1558 /* SDK: ...valid only the next time... */
1559 if( wndpl
->flags
& WPF_RESTORETOMAXIMIZED
) pWnd
->flags
|= WIN_RESTORE_MAX
;
1561 WIN_ReleaseWndPtr(pWnd
);
1568 /***********************************************************************
1569 * SetWindowPlacement16 (USER.371)
1571 BOOL16 WINAPI
SetWindowPlacement16(HWND16 hwnd
, const WINDOWPLACEMENT16
*wndpl
)
1573 return WINPOS_SetPlacement( hwnd
, wndpl
,
1574 PLACE_MIN
| PLACE_MAX
| PLACE_RECT
);
1577 /***********************************************************************
1578 * SetWindowPlacement (USER32.519)
1581 * Fails if wndpl->length of Win95 (!) apps is invalid.
1583 BOOL WINAPI
SetWindowPlacement( HWND hwnd
, const WINDOWPLACEMENT
*pwpl32
)
1587 WINDOWPLACEMENT16 wpl
;
1589 wpl
.length
= sizeof(WINDOWPLACEMENT16
);
1590 wpl
.flags
= pwpl32
->flags
;
1591 wpl
.showCmd
= pwpl32
->showCmd
;
1592 wpl
.ptMinPosition
.x
= pwpl32
->ptMinPosition
.x
;
1593 wpl
.ptMinPosition
.y
= pwpl32
->ptMinPosition
.y
;
1594 wpl
.ptMaxPosition
.x
= pwpl32
->ptMaxPosition
.x
;
1595 wpl
.ptMaxPosition
.y
= pwpl32
->ptMaxPosition
.y
;
1596 wpl
.rcNormalPosition
.left
= pwpl32
->rcNormalPosition
.left
;
1597 wpl
.rcNormalPosition
.top
= pwpl32
->rcNormalPosition
.top
;
1598 wpl
.rcNormalPosition
.right
= pwpl32
->rcNormalPosition
.right
;
1599 wpl
.rcNormalPosition
.bottom
= pwpl32
->rcNormalPosition
.bottom
;
1601 return WINPOS_SetPlacement( hwnd
, &wpl
, PLACE_MIN
| PLACE_MAX
| PLACE_RECT
);
1607 /***********************************************************************
1608 * SetInternalWindowPos16 (USER.461)
1610 void WINAPI
SetInternalWindowPos16( HWND16 hwnd
, UINT16 showCmd
,
1611 LPRECT16 rect
, LPPOINT16 pt
)
1613 if( IsWindow16(hwnd
) )
1615 WINDOWPLACEMENT16 wndpl
;
1618 wndpl
.length
= sizeof(wndpl
);
1619 wndpl
.showCmd
= showCmd
;
1620 wndpl
.flags
= flags
= 0;
1625 wndpl
.flags
|= WPF_SETMINPOSITION
;
1626 wndpl
.ptMinPosition
= *pt
;
1630 flags
|= PLACE_RECT
;
1631 wndpl
.rcNormalPosition
= *rect
;
1633 WINPOS_SetPlacement( hwnd
, &wndpl
, flags
);
1638 /***********************************************************************
1639 * SetInternalWindowPos (USER32.483)
1641 void WINAPI
SetInternalWindowPos( HWND hwnd
, UINT showCmd
,
1642 LPRECT rect
, LPPOINT pt
)
1644 if( IsWindow(hwnd
) )
1646 WINDOWPLACEMENT16 wndpl
;
1649 wndpl
.length
= sizeof(wndpl
);
1650 wndpl
.showCmd
= showCmd
;
1651 wndpl
.flags
= flags
= 0;
1656 wndpl
.flags
|= WPF_SETMINPOSITION
;
1657 CONV_POINT32TO16( pt
, &wndpl
.ptMinPosition
);
1661 flags
|= PLACE_RECT
;
1662 CONV_RECT32TO16( rect
, &wndpl
.rcNormalPosition
);
1664 WINPOS_SetPlacement( hwnd
, &wndpl
, flags
);
1668 /*******************************************************************
1669 * WINPOS_SetActiveWindow
1671 * SetActiveWindow() back-end. This is the only function that
1672 * can assign active status to a window. It must be called only
1673 * for the top level windows.
1675 BOOL
WINPOS_SetActiveWindow( HWND hWnd
, BOOL fMouse
, BOOL fChangeFocus
)
1677 CBTACTIVATESTRUCT16
* cbtStruct
;
1678 WND
* wndPtr
=0, *wndTemp
;
1679 HQUEUE16 hOldActiveQueue
, hNewActiveQueue
;
1680 MESSAGEQUEUE
*pOldActiveQueue
= 0, *pNewActiveQueue
= 0;
1682 HWND hwndActive
= 0;
1685 TRACE("(%04x, %d, %d)\n", hWnd
, fMouse
, fChangeFocus
);
1687 /* Get current active window from the active queue */
1690 pOldActiveQueue
= QUEUE_Lock( hActiveQueue
);
1691 if ( pOldActiveQueue
)
1692 hwndActive
= PERQDATA_GetActiveWnd( pOldActiveQueue
->pQData
);
1695 /* paranoid checks */
1696 if( hWnd
== GetDesktopWindow() || (bRet
= (hWnd
== hwndActive
)) )
1699 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1702 wndPtr
= WIN_FindWndPtr(hWnd
);
1703 hOldActiveQueue
= hActiveQueue
;
1705 if( (wndTemp
= WIN_FindWndPtr(hwndActive
)) )
1707 wIconized
= HIWORD(wndTemp
->dwStyle
& WS_MINIMIZE
);
1708 WIN_ReleaseWndPtr(wndTemp
);
1711 TRACE("no current active window.\n");
1713 /* call CBT hook chain */
1714 if ((cbtStruct
= SEGPTR_NEW(CBTACTIVATESTRUCT16
)))
1716 cbtStruct
->fMouse
= fMouse
;
1717 cbtStruct
->hWndActive
= hwndActive
;
1718 bRet
= (BOOL
)HOOK_CallHooks16( WH_CBT
, HCBT_ACTIVATE
, (WPARAM16
)hWnd
,
1719 (LPARAM
)SEGPTR_GET(cbtStruct
) );
1720 SEGPTR_FREE(cbtStruct
);
1721 if (bRet
) goto CLEANUP_END
;
1724 /* set prev active wnd to current active wnd and send notification */
1725 if ((hwndPrevActive
= hwndActive
) && IsWindow(hwndPrevActive
))
1727 MESSAGEQUEUE
*pTempActiveQueue
= 0;
1729 if (!SendMessageA( hwndPrevActive
, WM_NCACTIVATE
, FALSE
, 0 ))
1731 if (GetSysModalWindow16() != hWnd
)
1733 /* disregard refusal if hWnd is sysmodal */
1736 SendMessageA( hwndPrevActive
, WM_ACTIVATE
,
1737 MAKEWPARAM( WA_INACTIVE
, wIconized
),
1740 /* check if something happened during message processing
1741 * (global active queue may have changed)
1743 pTempActiveQueue
= QUEUE_Lock( hActiveQueue
);
1744 if(!pTempActiveQueue
)
1747 hwndActive
= PERQDATA_GetActiveWnd( pTempActiveQueue
->pQData
);
1748 QUEUE_Unlock( pTempActiveQueue
);
1749 if( hwndPrevActive
!= hwndActive
)
1753 /* Set new active window in the message queue */
1757 pNewActiveQueue
= QUEUE_Lock( wndPtr
->hmemTaskQ
);
1758 if ( pNewActiveQueue
)
1759 PERQDATA_SetActiveWnd( pNewActiveQueue
->pQData
, hwndActive
);
1761 else /* have to do this or MDI frame activation goes to hell */
1762 if( pOldActiveQueue
)
1763 PERQDATA_SetActiveWnd( pOldActiveQueue
->pQData
, 0 );
1765 /* send palette messages */
1766 if (hWnd
&& SendMessage16( hWnd
, WM_QUERYNEWPALETTE
, 0, 0L))
1767 SendMessage16((HWND16
)-1, WM_PALETTEISCHANGING
, (WPARAM16
)hWnd
, 0L );
1769 /* if prev wnd is minimized redraw icon title */
1770 if( IsIconic( hwndPrevActive
) ) WINPOS_RedrawIconTitle(hwndPrevActive
);
1772 /* managed windows will get ConfigureNotify event */
1773 if (wndPtr
&& !(wndPtr
->dwStyle
& WS_CHILD
) && !(wndPtr
->flags
& WIN_MANAGED
))
1775 /* check Z-order and bring hWnd to the top */
1776 for (wndTemp
= WIN_LockWndPtr(WIN_GetDesktop()->child
); wndTemp
; WIN_UpdateWndPtr(&wndTemp
,wndTemp
->next
))
1778 if (wndTemp
->dwStyle
& WS_VISIBLE
) break;
1780 WIN_ReleaseDesktop();
1781 WIN_ReleaseWndPtr(wndTemp
);
1783 if( wndTemp
!= wndPtr
)
1784 SetWindowPos(hWnd
, HWND_TOP
, 0,0,0,0,
1785 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
1786 if (!IsWindow(hWnd
))
1790 /* Get a handle to the new active queue */
1791 hNewActiveQueue
= wndPtr
? wndPtr
->hmemTaskQ
: 0;
1793 /* send WM_ACTIVATEAPP if necessary */
1794 if (hOldActiveQueue
!= hNewActiveQueue
)
1796 WND
**list
, **ppWnd
;
1797 WND
*pDesktop
= WIN_GetDesktop();
1799 if ((list
= WIN_BuildWinArray( pDesktop
, 0, NULL
)))
1801 for (ppWnd
= list
; *ppWnd
; ppWnd
++)
1803 if (!IsWindow( (*ppWnd
)->hwndSelf
)) continue;
1805 if ((*ppWnd
)->hmemTaskQ
== hOldActiveQueue
)
1806 SendMessage16( (*ppWnd
)->hwndSelf
, WM_ACTIVATEAPP
,
1807 0, QUEUE_GetQueueTask(hNewActiveQueue
) );
1809 WIN_ReleaseWinArray(list
);
1812 hActiveQueue
= hNewActiveQueue
;
1814 if ((list
= WIN_BuildWinArray(pDesktop
, 0, NULL
)))
1816 for (ppWnd
= list
; *ppWnd
; ppWnd
++)
1818 if (!IsWindow( (*ppWnd
)->hwndSelf
)) continue;
1820 if ((*ppWnd
)->hmemTaskQ
== hNewActiveQueue
)
1821 SendMessage16( (*ppWnd
)->hwndSelf
, WM_ACTIVATEAPP
,
1822 1, QUEUE_GetQueueTask( hOldActiveQueue
) );
1824 WIN_ReleaseWinArray(list
);
1826 WIN_ReleaseDesktop();
1828 if (hWnd
&& !IsWindow(hWnd
)) goto CLEANUP
;
1833 /* walk up to the first unowned window */
1834 wndTemp
= WIN_LockWndPtr(wndPtr
);
1835 while (wndTemp
->owner
)
1837 WIN_UpdateWndPtr(&wndTemp
,wndTemp
->owner
);
1839 /* and set last active owned popup */
1840 wndTemp
->hwndLastActive
= hWnd
;
1842 wIconized
= HIWORD(wndTemp
->dwStyle
& WS_MINIMIZE
);
1843 WIN_ReleaseWndPtr(wndTemp
);
1844 SendMessageA( hWnd
, WM_NCACTIVATE
, TRUE
, 0 );
1845 SendMessageA( hWnd
, WM_ACTIVATE
,
1846 MAKEWPARAM( (fMouse
) ? WA_CLICKACTIVE
: WA_ACTIVE
, wIconized
),
1847 (LPARAM
)hwndPrevActive
);
1848 if( !IsWindow(hWnd
) ) goto CLEANUP
;
1851 /* change focus if possible */
1854 if ( pNewActiveQueue
)
1856 HWND hOldFocus
= PERQDATA_GetFocusWnd( pNewActiveQueue
->pQData
);
1858 if ( hOldFocus
&& WIN_GetTopParent( hOldFocus
) != hwndActive
)
1859 FOCUS_SwitchFocus( pNewActiveQueue
, hOldFocus
,
1860 (wndPtr
&& (wndPtr
->dwStyle
& WS_MINIMIZE
))?
1864 if ( pOldActiveQueue
&&
1865 ( !pNewActiveQueue
||
1866 pNewActiveQueue
->pQData
!= pOldActiveQueue
->pQData
) )
1868 HWND hOldFocus
= PERQDATA_GetFocusWnd( pOldActiveQueue
->pQData
);
1870 FOCUS_SwitchFocus( pOldActiveQueue
, hOldFocus
, 0 );
1874 if( !hwndPrevActive
&& wndPtr
)
1875 (*wndPtr
->pDriver
->pForceWindowRaise
)(wndPtr
);
1877 /* if active wnd is minimized redraw icon title */
1878 if( IsIconic(hwndActive
) ) WINPOS_RedrawIconTitle(hwndActive
);
1880 bRet
= (hWnd
== hwndActive
); /* Success? */
1882 CLEANUP
: /* Unlock the message queues before returning */
1884 if ( pNewActiveQueue
)
1885 QUEUE_Unlock( pNewActiveQueue
);
1889 if ( pOldActiveQueue
)
1890 QUEUE_Unlock( pOldActiveQueue
);
1892 WIN_ReleaseWndPtr(wndPtr
);
1896 /*******************************************************************
1897 * WINPOS_ActivateOtherWindow
1899 * Activates window other than pWnd.
1901 BOOL
WINPOS_ActivateOtherWindow(WND
* pWnd
)
1905 HWND hwndActive
= 0;
1907 /* Get current active window from the active queue */
1910 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
1913 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
1914 QUEUE_Unlock( pActiveQueue
);
1918 if( pWnd
->hwndSelf
== hwndPrevActive
)
1921 if( hwndActive
!= pWnd
->hwndSelf
&&
1922 ( hwndActive
|| QUEUE_IsExitingQueue(pWnd
->hmemTaskQ
)) )
1925 if( !(pWnd
->dwStyle
& WS_POPUP
) || !(pWnd
->owner
) ||
1926 !WINPOS_CanActivate((pWndTo
= WIN_GetTopParentPtr(pWnd
->owner
))) )
1928 WND
* pWndPtr
= WIN_GetTopParentPtr(pWnd
);
1930 WIN_ReleaseWndPtr(pWndTo
);
1931 pWndTo
= WIN_FindWndPtr(hwndPrevActive
);
1933 while( !WINPOS_CanActivate(pWndTo
) )
1935 /* by now owned windows should've been taken care of */
1936 WIN_UpdateWndPtr(&pWndTo
,pWndPtr
->next
);
1937 WIN_UpdateWndPtr(&pWndPtr
,pWndTo
);
1938 if( !pWndTo
) break;
1940 WIN_ReleaseWndPtr(pWndPtr
);
1943 bRet
= WINPOS_SetActiveWindow( pWndTo
? pWndTo
->hwndSelf
: 0, FALSE
, TRUE
);
1945 /* switch desktop queue to current active */
1948 WIN_GetDesktop()->hmemTaskQ
= pWndTo
->hmemTaskQ
;
1949 WIN_ReleaseWndPtr(pWndTo
);
1950 WIN_ReleaseDesktop();
1957 /*******************************************************************
1958 * WINPOS_ChangeActiveWindow
1961 BOOL
WINPOS_ChangeActiveWindow( HWND hWnd
, BOOL mouseMsg
)
1963 WND
*wndPtr
, *wndTemp
;
1965 HWND hwndActive
= 0;
1967 /* Get current active window from the active queue */
1970 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
1973 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
1974 QUEUE_Unlock( pActiveQueue
);
1979 return WINPOS_SetActiveWindow( 0, mouseMsg
, TRUE
);
1981 wndPtr
= WIN_FindWndPtr(hWnd
);
1982 if( !wndPtr
) return FALSE
;
1984 /* child windows get WM_CHILDACTIVATE message */
1985 if( (wndPtr
->dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1987 retvalue
= SendMessageA(hWnd
, WM_CHILDACTIVATE
, 0, 0L);
1991 if( hWnd
== hwndActive
)
1997 if( !WINPOS_SetActiveWindow(hWnd
,mouseMsg
,TRUE
) )
2003 /* switch desktop queue to current active */
2004 wndTemp
= WIN_GetDesktop();
2005 if( wndPtr
->parent
== wndTemp
)
2006 wndTemp
->hmemTaskQ
= wndPtr
->hmemTaskQ
;
2007 WIN_ReleaseDesktop();
2011 WIN_ReleaseWndPtr(wndPtr
);
2016 /***********************************************************************
2017 * WINPOS_SendNCCalcSize
2019 * Send a WM_NCCALCSIZE message to a window.
2020 * All parameters are read-only except newClientRect.
2021 * oldWindowRect, oldClientRect and winpos must be non-NULL only
2022 * when calcValidRect is TRUE.
2024 LONG
WINPOS_SendNCCalcSize( HWND hwnd
, BOOL calcValidRect
,
2025 RECT
*newWindowRect
, RECT
*oldWindowRect
,
2026 RECT
*oldClientRect
, WINDOWPOS
*winpos
,
2027 RECT
*newClientRect
)
2029 NCCALCSIZE_PARAMS params
;
2030 WINDOWPOS winposCopy
;
2033 params
.rgrc
[0] = *newWindowRect
;
2036 winposCopy
= *winpos
;
2037 params
.rgrc
[1] = *oldWindowRect
;
2038 params
.rgrc
[2] = *oldClientRect
;
2039 params
.lppos
= &winposCopy
;
2041 result
= SendMessageA( hwnd
, WM_NCCALCSIZE
, calcValidRect
,
2043 TRACE("%d,%d-%d,%d\n",
2044 params
.rgrc
[0].left
, params
.rgrc
[0].top
,
2045 params
.rgrc
[0].right
, params
.rgrc
[0].bottom
);
2047 /* If the application send back garbage, ignore it */
2048 if (params
.rgrc
[0].left
<= params
.rgrc
[0].right
&& params
.rgrc
[0].top
<= params
.rgrc
[0].bottom
)
2049 *newClientRect
= params
.rgrc
[0];
2055 /***********************************************************************
2056 * WINPOS_HandleWindowPosChanging16
2058 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2060 LONG
WINPOS_HandleWindowPosChanging16( WND
*wndPtr
, WINDOWPOS16
*winpos
)
2062 POINT maxSize
, minTrack
;
2063 if (winpos
->flags
& SWP_NOSIZE
) return 0;
2064 if ((wndPtr
->dwStyle
& WS_THICKFRAME
) ||
2065 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) == 0))
2067 WINPOS_GetMinMaxInfo( wndPtr
, &maxSize
, NULL
, &minTrack
, NULL
);
2068 if (maxSize
.x
< winpos
->cx
) winpos
->cx
= maxSize
.x
;
2069 if (maxSize
.y
< winpos
->cy
) winpos
->cy
= maxSize
.y
;
2070 if (!(wndPtr
->dwStyle
& WS_MINIMIZE
))
2072 if (winpos
->cx
< minTrack
.x
) winpos
->cx
= minTrack
.x
;
2073 if (winpos
->cy
< minTrack
.y
) winpos
->cy
= minTrack
.y
;
2080 /***********************************************************************
2081 * WINPOS_HandleWindowPosChanging
2083 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2085 LONG
WINPOS_HandleWindowPosChanging( WND
*wndPtr
, WINDOWPOS
*winpos
)
2088 if (winpos
->flags
& SWP_NOSIZE
) return 0;
2089 if ((wndPtr
->dwStyle
& WS_THICKFRAME
) ||
2090 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) == 0))
2092 WINPOS_GetMinMaxInfo( wndPtr
, &maxSize
, NULL
, NULL
, NULL
);
2093 winpos
->cx
= min( winpos
->cx
, maxSize
.x
);
2094 winpos
->cy
= min( winpos
->cy
, maxSize
.y
);
2099 /***********************************************************************
2102 * fix Z order taking into account owned popups -
2103 * basically we need to maintain them above the window that owns them
2105 * FIXME: hide/show owned popups when owner visibility changes.
2107 static HWND
SWP_DoOwnedPopups(WND
* pDesktop
, WND
* wndPtr
, HWND hwndInsertAfter
, WORD flags
)
2109 WND
* w
= WIN_LockWndPtr(pDesktop
->child
);
2111 WARN("(%04x) hInsertAfter = %04x\n", wndPtr
->hwndSelf
, hwndInsertAfter
);
2113 if( (wndPtr
->dwStyle
& WS_POPUP
) && wndPtr
->owner
)
2115 /* make sure this popup stays above the owner */
2117 HWND hwndLocalPrev
= HWND_TOP
;
2119 if( hwndInsertAfter
!= HWND_TOP
)
2121 while( w
!= wndPtr
->owner
)
2123 if (w
!= wndPtr
) hwndLocalPrev
= w
->hwndSelf
;
2124 if( hwndLocalPrev
== hwndInsertAfter
) break;
2125 WIN_UpdateWndPtr(&w
,w
->next
);
2127 hwndInsertAfter
= hwndLocalPrev
;
2130 else if( wndPtr
->dwStyle
& WS_CHILD
)
2133 WIN_UpdateWndPtr(&w
, pDesktop
->child
);
2137 if( w
== wndPtr
) break;
2139 if( (w
->dwStyle
& WS_POPUP
) && w
->owner
== wndPtr
)
2141 SetWindowPos(w
->hwndSelf
, hwndInsertAfter
, 0, 0, 0, 0,
2142 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOSENDCHANGING
| SWP_DEFERERASE
);
2143 hwndInsertAfter
= w
->hwndSelf
;
2145 WIN_UpdateWndPtr(&w
, w
->next
);
2149 WIN_ReleaseWndPtr(w
);
2150 return hwndInsertAfter
;
2153 /***********************************************************************
2156 * Make window look nice without excessive repainting
2158 * visible and update regions are in window coordinates
2159 * client and window rectangles are in parent client coordinates
2161 * FIXME: SWP_EX_PAINTSELF in uFlags works only if both old and new
2162 * window rects have the same origin.
2164 * Returns: uFlags and a dirty region in *pVisRgn.
2166 static UINT
SWP_CopyValidBits( WND
* Wnd
, HRGN
* pVisRgn
,
2167 LPRECT lpOldWndRect
,
2168 LPRECT lpOldClientRect
, UINT uFlags
)
2171 HRGN newVisRgn
, dirtyRgn
;
2172 INT my
= COMPLEXREGION
;
2174 TRACE("\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2175 Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
,
2176 Wnd
->rectWindow
.right
, Wnd
->rectWindow
.bottom
,
2177 lpOldWndRect
->left
, lpOldWndRect
->top
,
2178 lpOldWndRect
->right
, lpOldWndRect
->bottom
, *pVisRgn
);
2179 TRACE("\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2180 Wnd
->rectClient
.left
, Wnd
->rectClient
.top
,
2181 Wnd
->rectClient
.right
, Wnd
->rectClient
.bottom
,
2182 lpOldClientRect
->left
, lpOldClientRect
->top
,
2183 lpOldClientRect
->right
,lpOldClientRect
->bottom
);
2185 if( Wnd
->hrgnUpdate
== 1 )
2186 uFlags
|= SWP_EX_NOCOPY
; /* whole window is invalid, nothing to copy */
2188 newVisRgn
= DCE_GetVisRgn( Wnd
->hwndSelf
, DCX_WINDOW
| DCX_CLIPSIBLINGS
, 0, 0);
2189 dirtyRgn
= CreateRectRgn( 0, 0, 0, 0 );
2191 if( !(uFlags
& SWP_EX_NOCOPY
) ) /* make sure dst region covers only valid bits */
2192 my
= CombineRgn( dirtyRgn
, newVisRgn
, *pVisRgn
, RGN_AND
);
2194 if( (my
== NULLREGION
) || (uFlags
& SWP_EX_NOCOPY
) )
2198 TRACE("\twon't copy anything!\n");
2200 /* set dirtyRgn to the sum of old and new visible regions
2201 * in parent client coordinates */
2203 OffsetRgn( newVisRgn
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2204 OffsetRgn( *pVisRgn
, lpOldWndRect
->left
, lpOldWndRect
->top
);
2206 CombineRgn(*pVisRgn
, *pVisRgn
, newVisRgn
, RGN_OR
);
2208 else /* copy valid bits to a new location */
2210 INT dx
, dy
, ow
, oh
, nw
, nh
, ocw
, ncw
, och
, nch
;
2211 HRGN hrgnValid
= dirtyRgn
; /* non-empty intersection of old and new visible rgns */
2213 /* subtract already invalid region inside Wnd from the dst region */
2215 if( Wnd
->hrgnUpdate
)
2216 if( CombineRgn( hrgnValid
, hrgnValid
, Wnd
->hrgnUpdate
, RGN_DIFF
) == NULLREGION
)
2219 /* check if entire window can be copied */
2221 ow
= lpOldWndRect
->right
- lpOldWndRect
->left
;
2222 oh
= lpOldWndRect
->bottom
- lpOldWndRect
->top
;
2223 nw
= Wnd
->rectWindow
.right
- Wnd
->rectWindow
.left
;
2224 nh
= Wnd
->rectWindow
.bottom
- Wnd
->rectWindow
.top
;
2226 ocw
= lpOldClientRect
->right
- lpOldClientRect
->left
;
2227 och
= lpOldClientRect
->bottom
- lpOldClientRect
->top
;
2228 ncw
= Wnd
->rectClient
.right
- Wnd
->rectClient
.left
;
2229 nch
= Wnd
->rectClient
.bottom
- Wnd
->rectClient
.top
;
2231 if( (ocw
!= ncw
) || (och
!= nch
) ||
2232 ( ow
!= nw
) || ( oh
!= nh
) ||
2233 ((lpOldClientRect
->top
- lpOldWndRect
->top
) !=
2234 (Wnd
->rectClient
.top
- Wnd
->rectWindow
.top
)) ||
2235 ((lpOldClientRect
->left
- lpOldWndRect
->left
) !=
2236 (Wnd
->rectClient
.left
- Wnd
->rectWindow
.left
)) )
2238 dx
= Wnd
->rectClient
.left
- lpOldClientRect
->left
;
2239 dy
= Wnd
->rectClient
.top
- lpOldClientRect
->top
;
2241 /* restrict valid bits to the common client rect */
2243 r
.left
= Wnd
->rectClient
.left
- Wnd
->rectWindow
.left
;
2244 r
.top
= Wnd
->rectClient
.top
- Wnd
->rectWindow
.top
;
2245 r
.right
= r
.left
+ min( ocw
, ncw
);
2246 r
.bottom
= r
.top
+ min( och
, nch
);
2248 REGION_CropRgn( hrgnValid
, hrgnValid
, &r
,
2249 (uFlags
& SWP_EX_PAINTSELF
) ? NULL
: (POINT
*)&(Wnd
->rectWindow
));
2250 GetRgnBox( hrgnValid
, &r
);
2251 if( IsRectEmpty( &r
) )
2253 r
= *lpOldClientRect
;
2257 dx
= Wnd
->rectWindow
.left
- lpOldWndRect
->left
;
2258 dy
= Wnd
->rectWindow
.top
- lpOldWndRect
->top
;
2259 if( !(uFlags
& SWP_EX_PAINTSELF
) )
2260 OffsetRgn( hrgnValid
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2264 if( !(uFlags
& SWP_EX_PAINTSELF
) )
2266 /* Move remaining regions to parent coordinates */
2267 OffsetRgn( newVisRgn
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2268 OffsetRgn( *pVisRgn
, lpOldWndRect
->left
, lpOldWndRect
->top
);
2271 OffsetRect( &r
, -lpOldWndRect
->left
, -lpOldWndRect
->top
);
2273 TRACE("\tcomputing dirty region!\n");
2275 /* Compute combined dirty region (old + new - valid) */
2276 CombineRgn( *pVisRgn
, *pVisRgn
, newVisRgn
, RGN_OR
);
2277 CombineRgn( *pVisRgn
, *pVisRgn
, hrgnValid
, RGN_DIFF
);
2279 /* Blt valid bits, r is the rect to copy */
2287 /* get DC and clip rect with drawable rect to avoid superfluous expose events
2288 from copying clipped areas */
2290 if( uFlags
& SWP_EX_PAINTSELF
)
2292 hDC
= GetDCEx( Wnd
->hwndSelf
, hrgnValid
, DCX_WINDOW
| DCX_CACHE
|
2293 DCX_KEEPCLIPRGN
| DCX_INTERSECTRGN
| DCX_CLIPSIBLINGS
);
2294 rClip
.right
= nw
; rClip
.bottom
= nh
;
2298 hDC
= GetDCEx( Wnd
->parent
->hwndSelf
, hrgnValid
, DCX_CACHE
|
2299 DCX_KEEPCLIPRGN
| DCX_INTERSECTRGN
| DCX_CLIPSIBLINGS
);
2300 rClip
.right
= Wnd
->parent
->rectClient
.right
- Wnd
->parent
->rectClient
.left
;
2301 rClip
.bottom
= Wnd
->parent
->rectClient
.bottom
- Wnd
->parent
->rectClient
.top
;
2303 rClip
.left
= rClip
.top
= 0;
2305 if( (dc
= (DC
*)GDI_GetObjPtr(hDC
, DC_MAGIC
)) )
2307 if( oh
> nh
) r
.bottom
= r
.top
+ nh
;
2308 if( ow
< nw
) r
.right
= r
.left
+ nw
;
2310 if( IntersectRect( &r
, &r
, &rClip
) )
2312 Wnd
->pDriver
->pSurfaceCopy( Wnd
->parent
, dc
, dx
, dy
, &r
, TRUE
);
2314 /* When you copy the bits without repainting, parent doesn't
2315 get validated appropriately. Therefore, we have to validate
2316 the parent with the windows' updated region when the
2317 parent's update region is not empty. */
2319 if (Wnd
->parent
->hrgnUpdate
!= 0 && !(Wnd
->parent
->dwStyle
& WS_CLIPCHILDREN
))
2321 OffsetRect(&r
, dx
, dy
);
2322 ValidateRect(Wnd
->parent
->hwndSelf
, &r
);
2326 GDI_HEAP_UNLOCK( hDC
);
2328 ReleaseDC( (uFlags
& SWP_EX_PAINTSELF
) ?
2329 Wnd
->hwndSelf
: Wnd
->parent
->hwndSelf
, hDC
);
2333 /* *pVisRgn now points to the invalidated region */
2335 DeleteObject(newVisRgn
);
2336 DeleteObject(dirtyRgn
);
2340 /***********************************************************************
2341 * SWP_DoSimpleFrameChanged
2343 * NOTE: old and new client rect origins are identical, only
2344 * extents may have changed. Window extents are the same.
2346 static void SWP_DoSimpleFrameChanged( WND
* wndPtr
, RECT
* pOldClientRect
, WORD swpFlags
, UINT uFlags
)
2352 if( !(swpFlags
& SWP_NOCLIENTSIZE
) )
2354 /* Client rect changed its position/size, most likely a scrollar
2355 * was added/removed.
2357 * FIXME: WVR alignment flags
2360 if( wndPtr
->rectClient
.right
> pOldClientRect
->right
) /* right edge */
2364 rect
.bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
2365 rect
.right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
2366 if(!(uFlags
& SWP_EX_NOCOPY
))
2367 rect
.left
= pOldClientRect
->right
- wndPtr
->rectClient
.left
;
2375 if( wndPtr
->rectClient
.bottom
> pOldClientRect
->bottom
) /* bottom edge */
2378 hrgn
= CreateRectRgnIndirect( &rect
);
2380 rect
.right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
2381 rect
.bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
2382 if(!(uFlags
& SWP_EX_NOCOPY
))
2383 rect
.top
= pOldClientRect
->bottom
- wndPtr
->rectClient
.top
;
2387 REGION_UnionRectWithRgn( hrgn
, &rect
);
2390 if( i
== 0 && (uFlags
& SWP_EX_NOCOPY
) ) /* force redraw anyway */
2392 rect
= wndPtr
->rectWindow
;
2393 OffsetRect( &rect
, wndPtr
->rectWindow
.left
- wndPtr
->rectClient
.left
,
2394 wndPtr
->rectWindow
.top
- wndPtr
->rectClient
.top
);
2402 PAINT_RedrawWindow( wndPtr
->hwndSelf
, &rect
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
|
2403 RDW_ERASENOW
| RDW_ALLCHILDREN
, RDW_EX_TOPFRAME
| RDW_EX_USEHRGN
);
2407 WIN_UpdateNCRgn(wndPtr
, 0, UNC_UPDATE
| UNC_ENTIRE
);
2411 DeleteObject( hrgn
);
2414 /***********************************************************************
2415 * SWP_DoWinPosChanging
2417 static BOOL
SWP_DoWinPosChanging( WND
* wndPtr
, WINDOWPOS
* pWinpos
,
2418 RECT
* pNewWindowRect
, RECT
* pNewClientRect
)
2420 /* Send WM_WINDOWPOSCHANGING message */
2422 if (!(pWinpos
->flags
& SWP_NOSENDCHANGING
))
2423 SendMessageA( wndPtr
->hwndSelf
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
)pWinpos
);
2425 /* Calculate new position and size */
2427 *pNewWindowRect
= wndPtr
->rectWindow
;
2428 *pNewClientRect
= (wndPtr
->dwStyle
& WS_MINIMIZE
) ? wndPtr
->rectWindow
2429 : wndPtr
->rectClient
;
2431 if (!(pWinpos
->flags
& SWP_NOSIZE
))
2433 pNewWindowRect
->right
= pNewWindowRect
->left
+ pWinpos
->cx
;
2434 pNewWindowRect
->bottom
= pNewWindowRect
->top
+ pWinpos
->cy
;
2436 if (!(pWinpos
->flags
& SWP_NOMOVE
))
2438 pNewWindowRect
->left
= pWinpos
->x
;
2439 pNewWindowRect
->top
= pWinpos
->y
;
2440 pNewWindowRect
->right
+= pWinpos
->x
- wndPtr
->rectWindow
.left
;
2441 pNewWindowRect
->bottom
+= pWinpos
->y
- wndPtr
->rectWindow
.top
;
2443 OffsetRect( pNewClientRect
, pWinpos
->x
- wndPtr
->rectWindow
.left
,
2444 pWinpos
->y
- wndPtr
->rectWindow
.top
);
2447 pWinpos
->flags
|= SWP_NOCLIENTMOVE
| SWP_NOCLIENTSIZE
;
2451 /***********************************************************************
2454 static UINT
SWP_DoNCCalcSize( WND
* wndPtr
, WINDOWPOS
* pWinpos
,
2455 RECT
* pNewWindowRect
, RECT
* pNewClientRect
, WORD f
)
2459 /* Send WM_NCCALCSIZE message to get new client area */
2460 if( (pWinpos
->flags
& (SWP_FRAMECHANGED
| SWP_NOSIZE
)) != SWP_NOSIZE
)
2462 wvrFlags
= WINPOS_SendNCCalcSize( pWinpos
->hwnd
, TRUE
, pNewWindowRect
,
2463 &wndPtr
->rectWindow
, &wndPtr
->rectClient
,
2464 pWinpos
, pNewClientRect
);
2466 /* FIXME: WVR_ALIGNxxx */
2468 if( pNewClientRect
->left
!= wndPtr
->rectClient
.left
||
2469 pNewClientRect
->top
!= wndPtr
->rectClient
.top
)
2470 pWinpos
->flags
&= ~SWP_NOCLIENTMOVE
;
2472 if( (pNewClientRect
->right
- pNewClientRect
->left
!=
2473 wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
) ||
2474 (pNewClientRect
->bottom
- pNewClientRect
->top
!=
2475 wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
) )
2476 pWinpos
->flags
&= ~SWP_NOCLIENTSIZE
;
2479 if( !(f
& SWP_NOMOVE
) && (pNewClientRect
->left
!= wndPtr
->rectClient
.left
||
2480 pNewClientRect
->top
!= wndPtr
->rectClient
.top
) )
2481 pWinpos
->flags
&= ~SWP_NOCLIENTMOVE
;
2485 /***********************************************************************
2486 * SetWindowPos (USER.2)
2488 BOOL16 WINAPI
SetWindowPos16( HWND16 hwnd
, HWND16 hwndInsertAfter
,
2489 INT16 x
, INT16 y
, INT16 cx
, INT16 cy
, WORD flags
)
2491 return SetWindowPos(hwnd
,(INT
)(INT16
)hwndInsertAfter
,x
,y
,cx
,cy
,flags
);
2494 /***********************************************************************
2495 * SetWindowPos (USER32.520)
2497 BOOL WINAPI
SetWindowPos( HWND hwnd
, HWND hwndInsertAfter
,
2498 INT x
, INT y
, INT cx
, INT cy
, UINT flags
)
2501 WND
* wndPtr
,*wndTemp
;
2502 RECT newWindowRect
, newClientRect
;
2503 RECT oldWindowRect
, oldClientRect
;
2505 UINT wvrFlags
= 0, uFlags
= 0;
2506 BOOL retvalue
, resync
= FALSE
, bChangePos
;
2507 HWND hwndActive
= 0;
2509 /* Get current active window from the active queue */
2512 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
2515 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
2516 QUEUE_Unlock( pActiveQueue
);
2520 TRACE("hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2521 hwnd
, x
, y
, x
+cx
, y
+cy
, flags
);
2523 bChangePos
= !(flags
& SWP_WINE_NOHOSTMOVE
);
2524 flags
&= ~SWP_WINE_NOHOSTMOVE
;
2527 /* ------------------------------------------------------------------------ CHECKS */
2529 /* Check window handle */
2531 if (hwnd
== GetDesktopWindow()) return FALSE
;
2532 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return FALSE
;
2534 TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr
->rectWindow
.left
, wndPtr
->rectWindow
.top
,
2535 wndPtr
->rectWindow
.right
, wndPtr
->rectWindow
.bottom
, (unsigned)wndPtr
->dwStyle
);
2537 /* Fix redundant flags */
2539 if(wndPtr
->dwStyle
& WS_VISIBLE
)
2540 flags
&= ~SWP_SHOWWINDOW
;
2543 if (!(flags
& SWP_SHOWWINDOW
))
2544 flags
|= SWP_NOREDRAW
;
2545 flags
&= ~SWP_HIDEWINDOW
;
2548 if ( cx
< 0 ) cx
= 0; if( cy
< 0 ) cy
= 0;
2550 if ((wndPtr
->rectWindow
.right
- wndPtr
->rectWindow
.left
== cx
) &&
2551 (wndPtr
->rectWindow
.bottom
- wndPtr
->rectWindow
.top
== cy
))
2552 flags
|= SWP_NOSIZE
; /* Already the right size */
2554 if ((wndPtr
->rectWindow
.left
== x
) && (wndPtr
->rectWindow
.top
== y
))
2555 flags
|= SWP_NOMOVE
; /* Already the right position */
2557 if (hwnd
== hwndActive
)
2558 flags
|= SWP_NOACTIVATE
; /* Already active */
2559 else if ( (wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)
2561 if(!(flags
& SWP_NOACTIVATE
)) /* Bring to the top when activating */
2563 flags
&= ~SWP_NOZORDER
;
2564 hwndInsertAfter
= HWND_TOP
;
2569 /* Check hwndInsertAfter */
2571 /* FIXME: TOPMOST not supported yet */
2572 if ((hwndInsertAfter
== HWND_TOPMOST
) ||
2573 (hwndInsertAfter
== HWND_NOTOPMOST
)) hwndInsertAfter
= HWND_TOP
;
2575 /* hwndInsertAfter must be a sibling of the window */
2576 if ((hwndInsertAfter
!= HWND_TOP
) && (hwndInsertAfter
!= HWND_BOTTOM
))
2578 WND
* wnd
= WIN_FindWndPtr(hwndInsertAfter
);
2581 if( wnd
->parent
!= wndPtr
->parent
)
2584 WIN_ReleaseWndPtr(wnd
);
2587 /* don't need to change the Zorder of hwnd if it's already inserted
2588 * after hwndInsertAfter or when inserting hwnd after itself.
2590 if(( wnd
->next
== wndPtr
) || (hwnd
== hwndInsertAfter
)) flags
|= SWP_NOZORDER
;
2592 WIN_ReleaseWndPtr(wnd
);
2595 Pos
: /* ------------------------------------------------------------------------ MAIN part */
2597 /* Fill the WINDOWPOS structure */
2600 winpos
.hwndInsertAfter
= hwndInsertAfter
;
2605 winpos
.flags
= flags
;
2607 SWP_DoWinPosChanging( wndPtr
, &winpos
, &newWindowRect
, &newClientRect
);
2609 if((winpos
.flags
& (SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) != SWP_NOZORDER
)
2611 if( wndPtr
->parent
== WIN_GetDesktop() )
2612 hwndInsertAfter
= SWP_DoOwnedPopups( wndPtr
->parent
, wndPtr
,
2613 hwndInsertAfter
, winpos
.flags
);
2614 WIN_ReleaseDesktop();
2617 if(!(wndPtr
->flags
& WIN_NATIVE
) )
2619 if( hwndInsertAfter
== HWND_TOP
)
2620 winpos
.flags
|= ( wndPtr
->parent
->child
== wndPtr
)? SWP_NOZORDER
: 0;
2622 if( hwndInsertAfter
== HWND_BOTTOM
)
2623 winpos
.flags
|= ( wndPtr
->next
)? 0: SWP_NOZORDER
;
2625 if( !(winpos
.flags
& SWP_NOZORDER
) )
2626 if( GetWindow(hwndInsertAfter
, GW_HWNDNEXT
) == wndPtr
->hwndSelf
)
2627 winpos
.flags
|= SWP_NOZORDER
;
2629 if( !(winpos
.flags
& (SWP_NOREDRAW
| SWP_SHOWWINDOW
)) &&
2630 ((winpos
.flags
& (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_FRAMECHANGED
))
2631 != (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
)) )
2633 /* get a previous visible region for SWP_CopyValidBits() */
2634 DWORD flags
= DCX_WINDOW
;
2636 if (wndPtr
->dwStyle
& WS_CLIPSIBLINGS
)
2637 flags
|= DCX_CLIPSIBLINGS
;
2639 visRgn
= DCE_GetVisRgn(hwnd
, flags
, 0, 0);
2643 /* Common operations */
2645 wvrFlags
= SWP_DoNCCalcSize( wndPtr
, &winpos
, &newWindowRect
, &newClientRect
, flags
);
2647 if(!(winpos
.flags
& SWP_NOZORDER
) && winpos
.hwnd
!= hwndInsertAfter
)
2649 if ( WIN_UnlinkWindow( winpos
.hwnd
) )
2650 WIN_LinkWindow( winpos
.hwnd
, hwndInsertAfter
);
2653 /* Reset active DCEs */
2655 if( (((winpos
.flags
& SWP_AGG_NOPOSCHANGE
) != SWP_AGG_NOPOSCHANGE
) &&
2656 wndPtr
->dwStyle
& WS_VISIBLE
) ||
2657 (flags
& (SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) )
2661 UnionRect(&rect
, &newWindowRect
, &wndPtr
->rectWindow
);
2662 DCE_InvalidateDCE(wndPtr
, &rect
);
2665 oldWindowRect
= wndPtr
->rectWindow
;
2666 oldClientRect
= wndPtr
->rectClient
;
2668 /* Find out if we have to redraw the whole client rect */
2670 if( oldClientRect
.bottom
- oldClientRect
.top
==
2671 newClientRect
.bottom
- newClientRect
.top
) wvrFlags
&= ~WVR_VREDRAW
;
2673 if( oldClientRect
.right
- oldClientRect
.left
==
2674 newClientRect
.right
- newClientRect
.left
) wvrFlags
&= ~WVR_HREDRAW
;
2676 if( (winpos
.flags
& SWP_NOCOPYBITS
) || (!(winpos
.flags
& SWP_NOCLIENTSIZE
) &&
2677 (wvrFlags
>= WVR_HREDRAW
) && (wvrFlags
< WVR_VALIDRECTS
)) )
2679 uFlags
|= SWP_EX_NOCOPY
;
2682 * Use this later in CopyValidBits()
2685 uFlags |= SWP_EX_NONCLIENT;
2688 /* FIXME: actually do something with WVR_VALIDRECTS */
2690 wndPtr
->rectWindow
= newWindowRect
;
2691 wndPtr
->rectClient
= newClientRect
;
2693 if (wndPtr
->flags
& WIN_NATIVE
) /* -------------------------------------------- hosted window */
2695 BOOL bCallDriver
= TRUE
;
2696 HWND tempInsertAfter
= winpos
.hwndInsertAfter
;
2698 winpos
.hwndInsertAfter
= hwndInsertAfter
;
2700 if( !(winpos
.flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
| SWP_NOREDRAW
)) )
2702 /* This is the only place where we need to force repainting of the contents
2703 of windows created by the host window system, all other cases go through the
2704 expose event handling */
2706 if( (winpos
.flags
& (SWP_NOSIZE
| SWP_FRAMECHANGED
)) == (SWP_NOSIZE
| SWP_FRAMECHANGED
) )
2708 cx
= newWindowRect
.right
- newWindowRect
.left
;
2709 cy
= newWindowRect
.bottom
- newWindowRect
.top
;
2711 wndPtr
->pDriver
->pSetWindowPos(wndPtr
, &winpos
, bChangePos
);
2712 winpos
.hwndInsertAfter
= tempInsertAfter
;
2713 bCallDriver
= FALSE
;
2715 if( winpos
.flags
& SWP_NOCLIENTMOVE
)
2716 SWP_DoSimpleFrameChanged(wndPtr
, &oldClientRect
, winpos
.flags
, uFlags
);
2719 /* client area moved but window extents remained the same, copy valid bits */
2721 visRgn
= CreateRectRgn( 0, 0, cx
, cy
);
2722 uFlags
= SWP_CopyValidBits( wndPtr
, &visRgn
, &oldWindowRect
, &oldClientRect
,
2723 uFlags
| SWP_EX_PAINTSELF
);
2730 if( !(winpos
.flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
| SWP_NOREDRAW
)) )
2732 if( (oldClientRect
.left
- oldWindowRect
.left
== newClientRect
.left
- newWindowRect
.left
) &&
2733 (oldClientRect
.top
- oldWindowRect
.top
== newClientRect
.top
- newWindowRect
.top
) &&
2734 !(uFlags
& SWP_EX_NOCOPY
) )
2736 /* The origin of the client rect didn't move so we can try to repaint
2737 * only the nonclient area by setting bit gravity hint for the host window system.
2740 if( !(wndPtr
->flags
& WIN_MANAGED
) )
2742 HRGN hrgn
= CreateRectRgn( 0, 0, newWindowRect
.right
- newWindowRect
.left
,
2743 newWindowRect
.bottom
- newWindowRect
.top
);
2744 RECT rcn
= newClientRect
;
2745 RECT rco
= oldClientRect
;
2747 OffsetRect( &rcn
, -newWindowRect
.left
, -newWindowRect
.top
);
2748 OffsetRect( &rco
, -oldWindowRect
.left
, -oldWindowRect
.top
);
2749 IntersectRect( &rcn
, &rcn
, &rco
);
2750 visRgn
= CreateRectRgnIndirect( &rcn
);
2751 CombineRgn( visRgn
, hrgn
, visRgn
, RGN_DIFF
);
2752 DeleteObject( hrgn
);
2753 uFlags
= SWP_EX_PAINTSELF
;
2755 wndPtr
->pDriver
->pSetHostAttr(wndPtr
, HAK_BITGRAVITY
, BGNorthWest
);
2758 wndPtr
->pDriver
->pSetHostAttr(wndPtr
, HAK_BITGRAVITY
, BGForget
);
2761 wndPtr
->pDriver
->pSetWindowPos(wndPtr
, &winpos
, bChangePos
);
2762 winpos
.hwndInsertAfter
= tempInsertAfter
;
2765 if( winpos
.flags
& SWP_SHOWWINDOW
)
2769 wndPtr
->dwStyle
|= WS_VISIBLE
;
2771 if (wndPtr
->flags
& WIN_MANAGED
) resync
= TRUE
;
2773 /* focus was set to unmapped window, reset host focus
2774 * since the window is now visible */
2776 focus
= curr
= GetFocus();
2781 WND
*pFocus
= WIN_FindWndPtr( focus
);
2783 pFocus
->pDriver
->pSetFocus(pFocus
);
2784 WIN_ReleaseWndPtr(pFocus
);
2787 curr
= GetParent(curr
);
2791 else /* -------------------------------------------- emulated window */
2793 if( winpos
.flags
& SWP_SHOWWINDOW
)
2795 wndPtr
->dwStyle
|= WS_VISIBLE
;
2796 uFlags
|= SWP_EX_PAINTSELF
;
2797 visRgn
= 1; /* redraw the whole window */
2799 else if( !(winpos
.flags
& SWP_NOREDRAW
) )
2801 if( winpos
.flags
& SWP_HIDEWINDOW
)
2803 if( visRgn
> 1 ) /* map to parent */
2804 OffsetRgn( visRgn
, oldWindowRect
.left
, oldWindowRect
.top
);
2810 if( (winpos
.flags
& SWP_AGG_NOPOSCHANGE
) != SWP_AGG_NOPOSCHANGE
)
2811 uFlags
= SWP_CopyValidBits(wndPtr
, &visRgn
, &oldWindowRect
,
2812 &oldClientRect
, uFlags
);
2815 /* nothing moved, redraw frame if needed */
2817 if( winpos
.flags
& SWP_FRAMECHANGED
)
2818 SWP_DoSimpleFrameChanged( wndPtr
, &oldClientRect
, winpos
.flags
, uFlags
);
2821 DeleteObject( visRgn
);
2829 if( winpos
.flags
& SWP_HIDEWINDOW
)
2831 wndPtr
->dwStyle
&= ~WS_VISIBLE
;
2833 if (hwnd
== CARET_GetHwnd()) DestroyCaret();
2836 /* ------------------------------------------------------------------------ FINAL */
2838 if (wndPtr
->flags
& WIN_NATIVE
)
2839 EVENT_Synchronize(); /* Synchronize with the host window system */
2841 if (!GetCapture() && ((wndPtr
->dwStyle
& WS_VISIBLE
) || (flags
& SWP_HIDEWINDOW
)))
2843 /* Simulate a mouse event to set the cursor */
2844 int iWndsLocks
= WIN_SuspendWndsLock();
2846 hardware_event( WM_MOUSEMOVE
, GET_KEYSTATE(), 0,
2847 PosX
, PosY
, GetTickCount(), 0 );
2849 WIN_RestoreWndsLock(iWndsLocks
);
2852 wndTemp
= WIN_GetDesktop();
2854 /* repaint invalidated region (if any)
2856 * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2857 * and force update after ChangeActiveWindow() to avoid painting frames twice.
2862 if( !(winpos
.flags
& SWP_NOREDRAW
) )
2865 /* Use PAINT_RedrawWindow to explicitly force an invalidation of the window,
2866 its parent and sibling and so on, and then erase the parent window
2867 back ground if the parent is either a top-level window or its parent's parent
2868 is top-level window. Rely on the system to repaint other affected
2869 windows later on. */
2870 if( uFlags
& SWP_EX_PAINTSELF
)
2872 PAINT_RedrawWindow( wndPtr
->hwndSelf
, NULL
, (visRgn
== 1) ? 0 : visRgn
,
2873 RDW_ERASE
| RDW_FRAME
| RDW_INVALIDATE
| RDW_ALLCHILDREN
,
2874 RDW_EX_XYWINDOW
| RDW_EX_USEHRGN
);
2878 PAINT_RedrawWindow( wndPtr
->parent
->hwndSelf
, NULL
, (visRgn
== 1) ? 0 : visRgn
,
2879 RDW_ERASE
| RDW_INVALIDATE
| RDW_ALLCHILDREN
,
2883 if(wndPtr
-> parent
== wndTemp
|| wndPtr
->parent
->parent
== wndTemp
)
2885 PAINT_RedrawWindow( wndPtr
->parent
->hwndSelf
, NULL
, 0,
2886 RDW_ERASENOW
| RDW_NOCHILDREN
, 0 );
2890 DeleteObject( visRgn
);
2893 WIN_ReleaseDesktop();
2895 if (!(flags
& SWP_NOACTIVATE
))
2896 WINPOS_ChangeActiveWindow( winpos
.hwnd
, FALSE
);
2898 /* And last, send the WM_WINDOWPOSCHANGED message */
2900 TRACE("\tstatus flags = %04x\n", winpos
.flags
& SWP_AGG_STATUSFLAGS
);
2903 (((winpos
.flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOPOSCHANGE
) &&
2904 !(winpos
.flags
& SWP_NOSENDCHANGING
)) )
2906 SendMessageA( winpos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
)&winpos
);
2907 if (resync
) EVENT_Synchronize();
2912 WIN_ReleaseWndPtr(wndPtr
);
2917 /***********************************************************************
2918 * BeginDeferWindowPos16 (USER.259)
2920 HDWP16 WINAPI
BeginDeferWindowPos16( INT16 count
)
2922 return BeginDeferWindowPos( count
);
2926 /***********************************************************************
2927 * BeginDeferWindowPos (USER32.9)
2929 HDWP WINAPI
BeginDeferWindowPos( INT count
)
2936 SetLastError(ERROR_INVALID_PARAMETER
);
2939 /* Windows allows zero count, in which case it allocates context for 8 moves */
2940 if (count
== 0) count
= 8;
2942 handle
= USER_HEAP_ALLOC( sizeof(DWP
) + (count
-1)*sizeof(WINDOWPOS
) );
2943 if (!handle
) return 0;
2944 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( handle
);
2945 pDWP
->actualCount
= 0;
2946 pDWP
->suggestedCount
= count
;
2948 pDWP
->wMagic
= DWP_MAGIC
;
2949 pDWP
->hwndParent
= 0;
2954 /***********************************************************************
2955 * DeferWindowPos16 (USER.260)
2957 HDWP16 WINAPI
DeferWindowPos16( HDWP16 hdwp
, HWND16 hwnd
, HWND16 hwndAfter
,
2958 INT16 x
, INT16 y
, INT16 cx
, INT16 cy
,
2961 return DeferWindowPos( hdwp
, hwnd
, (INT
)(INT16
)hwndAfter
,
2962 x
, y
, cx
, cy
, flags
);
2966 /***********************************************************************
2967 * DeferWindowPos (USER32.128)
2969 HDWP WINAPI
DeferWindowPos( HDWP hdwp
, HWND hwnd
, HWND hwndAfter
,
2970 INT x
, INT y
, INT cx
, INT cy
,
2975 HDWP newhdwp
= hdwp
,retvalue
;
2979 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
2980 if (!pDWP
) return 0;
2981 if (hwnd
== GetDesktopWindow()) return 0;
2983 if (!(pWnd
=WIN_FindWndPtr( hwnd
))) {
2984 USER_HEAP_FREE( hdwp
);
2988 /* Numega Bounds Checker Demo dislikes the following code.
2989 In fact, I've not been able to find any "same parent" requirement in any docu
2993 /* All the windows of a DeferWindowPos() must have the same parent */
2994 parent
= pWnd
->parent
->hwndSelf
;
2995 if (pDWP
->actualCount
== 0) pDWP
->hwndParent
= parent
;
2996 else if (parent
!= pDWP
->hwndParent
)
2998 USER_HEAP_FREE( hdwp
);
3004 for (i
= 0; i
< pDWP
->actualCount
; i
++)
3006 if (pDWP
->winPos
[i
].hwnd
== hwnd
)
3008 /* Merge with the other changes */
3009 if (!(flags
& SWP_NOZORDER
))
3011 pDWP
->winPos
[i
].hwndInsertAfter
= hwndAfter
;
3013 if (!(flags
& SWP_NOMOVE
))
3015 pDWP
->winPos
[i
].x
= x
;
3016 pDWP
->winPos
[i
].y
= y
;
3018 if (!(flags
& SWP_NOSIZE
))
3020 pDWP
->winPos
[i
].cx
= cx
;
3021 pDWP
->winPos
[i
].cy
= cy
;
3023 pDWP
->winPos
[i
].flags
&= flags
| ~(SWP_NOSIZE
| SWP_NOMOVE
|
3024 SWP_NOZORDER
| SWP_NOREDRAW
|
3025 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
3027 pDWP
->winPos
[i
].flags
|= flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
|
3033 if (pDWP
->actualCount
>= pDWP
->suggestedCount
)
3035 newhdwp
= USER_HEAP_REALLOC( hdwp
,
3036 sizeof(DWP
) + pDWP
->suggestedCount
*sizeof(WINDOWPOS
) );
3042 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( newhdwp
);
3043 pDWP
->suggestedCount
++;
3045 pDWP
->winPos
[pDWP
->actualCount
].hwnd
= hwnd
;
3046 pDWP
->winPos
[pDWP
->actualCount
].hwndInsertAfter
= hwndAfter
;
3047 pDWP
->winPos
[pDWP
->actualCount
].x
= x
;
3048 pDWP
->winPos
[pDWP
->actualCount
].y
= y
;
3049 pDWP
->winPos
[pDWP
->actualCount
].cx
= cx
;
3050 pDWP
->winPos
[pDWP
->actualCount
].cy
= cy
;
3051 pDWP
->winPos
[pDWP
->actualCount
].flags
= flags
;
3052 pDWP
->actualCount
++;
3055 WIN_ReleaseWndPtr(pWnd
);
3060 /***********************************************************************
3061 * EndDeferWindowPos16 (USER.261)
3063 BOOL16 WINAPI
EndDeferWindowPos16( HDWP16 hdwp
)
3065 return EndDeferWindowPos( hdwp
);
3069 /***********************************************************************
3070 * EndDeferWindowPos (USER32.173)
3072 BOOL WINAPI
EndDeferWindowPos( HDWP hdwp
)
3079 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
3080 if (!pDWP
) return FALSE
;
3081 for (i
= 0, winpos
= pDWP
->winPos
; i
< pDWP
->actualCount
; i
++, winpos
++)
3083 if (!(res
= SetWindowPos( winpos
->hwnd
, winpos
->hwndInsertAfter
,
3084 winpos
->x
, winpos
->y
, winpos
->cx
,
3085 winpos
->cy
, winpos
->flags
))) break;
3087 USER_HEAP_FREE( hdwp
);
3092 /***********************************************************************
3093 * TileChildWindows (USER.199)
3095 void WINAPI
TileChildWindows16( HWND16 parent
, WORD action
)
3097 FIXME("(%04x, %d): stub\n", parent
, action
);
3100 /***********************************************************************
3101 * CascadeChildWindows (USER.198)
3103 void WINAPI
CascadeChildWindows16( HWND16 parent
, WORD action
)
3105 FIXME("(%04x, %d): stub\n", parent
, action
);
3108 /***********************************************************************
3109 * SetProgmanWindow [USER32.522]
3111 HRESULT WINAPI
SetProgmanWindow ( HWND hwnd
)
3113 hGlobalProgmanWindow
= hwnd
;
3114 return hGlobalProgmanWindow
;
3117 /***********************************************************************
3118 * GetProgmanWindow [USER32.289]
3120 HRESULT WINAPI
GetProgmanWindow ( )
3122 return hGlobalProgmanWindow
;
3125 /***********************************************************************
3126 * SetShellWindowEx [USER32.531]
3127 * hwndProgman = Progman[Program Manager]
3128 * |-> SHELLDLL_DefView
3129 * hwndListView = | |-> SysListView32
3130 * | | |-> tooltips_class32
3136 HRESULT WINAPI
SetShellWindowEx ( HWND hwndProgman
, HWND hwndListView
)
3138 FIXME("0x%08x 0x%08x stub\n",hwndProgman
,hwndListView
);
3139 hGlobalShellWindow
= hwndProgman
;
3140 return hGlobalShellWindow
;
3144 /***********************************************************************
3145 * SetTaskmanWindow [USER32.537]
3147 * hwnd = MSTaskSwWClass
3148 * |-> SysTabControl32
3150 HRESULT WINAPI
SetTaskmanWindow ( HWND hwnd
)
3152 hGlobalTaskmanWindow
= hwnd
;
3153 return hGlobalTaskmanWindow
;
3156 /***********************************************************************
3157 * GetTaskmanWindow [USER32.304]
3159 HRESULT WINAPI
GetTaskmanWindow ( )
3161 return hGlobalTaskmanWindow
;