2 * Window position related functions.
4 * Copyright 1993, 1994, 1995 Alexandre Julliard
5 * 1995, 1996, 1999 Alex Korobka
11 #include "sysmetrics.h"
24 #include "nonclient.h"
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 /* ----- internal variables ----- */
55 static HWND hwndPrevActive
= 0; /* Previously active window */
56 static HWND hGlobalShellWindow
=0; /*the shell*/
58 static LPCSTR atomInternalPos
;
60 extern HQUEUE16 hActiveQueue
;
62 /***********************************************************************
63 * WINPOS_CreateInternalPosAtom
65 BOOL
WINPOS_CreateInternalPosAtom()
68 atomInternalPos
= (LPCSTR
)(DWORD
)GlobalAddAtomA(str
);
69 return (atomInternalPos
) ? TRUE
: FALSE
;
72 /***********************************************************************
73 * WINPOS_CheckInternalPos
75 * Called when a window is destroyed.
77 void WINPOS_CheckInternalPos( WND
* wndPtr
)
80 MESSAGEQUEUE
*pMsgQ
= 0;
81 HWND hwnd
= wndPtr
->hwndSelf
;
83 lpPos
= (LPINTERNALPOS
) GetPropA( hwnd
, atomInternalPos
);
85 /* Retrieve the message queue associated with this window */
86 pMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( wndPtr
->hmemTaskQ
);
89 WARN( win
, "\tMessage queue not found. Exiting!\n" );
93 if( hwnd
== hwndPrevActive
) hwndPrevActive
= 0;
95 if( hwnd
== PERQDATA_GetActiveWnd( pMsgQ
->pQData
) )
97 PERQDATA_SetActiveWnd( pMsgQ
->pQData
, 0 );
98 WARN(win
, "\tattempt to activate destroyed window!\n");
103 if( IsWindow(lpPos
->hwndIconTitle
) )
104 DestroyWindow( lpPos
->hwndIconTitle
);
105 HeapFree( SystemHeap
, 0, lpPos
);
108 QUEUE_Unlock( pMsgQ
);
112 /***********************************************************************
115 * Find a suitable place for an iconic window.
117 static POINT16
WINPOS_FindIconPos( WND
* wndPtr
, POINT16 pt
)
120 short x
, y
, xspacing
, yspacing
;
122 GetClientRect16( wndPtr
->parent
->hwndSelf
, &rectParent
);
123 if ((pt
.x
>= rectParent
.left
) && (pt
.x
+ SYSMETRICS_CXICON
< rectParent
.right
) &&
124 (pt
.y
>= rectParent
.top
) && (pt
.y
+ SYSMETRICS_CYICON
< rectParent
.bottom
))
125 return pt
; /* The icon already has a suitable position */
127 xspacing
= SYSMETRICS_CXICONSPACING
;
128 yspacing
= SYSMETRICS_CYICONSPACING
;
130 y
= rectParent
.bottom
;
133 for (x
= rectParent
.left
; x
<= rectParent
.right
-xspacing
; x
+= xspacing
)
135 /* Check if another icon already occupies this spot */
136 WND
*childPtr
= WIN_LockWndPtr(wndPtr
->parent
->child
);
139 if ((childPtr
->dwStyle
& WS_MINIMIZE
) && (childPtr
!= wndPtr
))
141 if ((childPtr
->rectWindow
.left
< x
+ xspacing
) &&
142 (childPtr
->rectWindow
.right
>= x
) &&
143 (childPtr
->rectWindow
.top
<= y
) &&
144 (childPtr
->rectWindow
.bottom
> y
- yspacing
))
145 break; /* There's a window in there */
147 WIN_UpdateWndPtr(&childPtr
,childPtr
->next
);
149 WIN_ReleaseWndPtr(childPtr
);
150 if (!childPtr
) /* No window was found, so it's OK for us */
152 pt
.x
= x
+ (xspacing
- SYSMETRICS_CXICON
) / 2;
153 pt
.y
= y
- (yspacing
+ SYSMETRICS_CYICON
) / 2;
162 /***********************************************************************
163 * ArrangeIconicWindows16 (USER.170)
165 UINT16 WINAPI
ArrangeIconicWindows16( HWND16 parent
)
167 return ArrangeIconicWindows(parent
);
169 /***********************************************************************
170 * ArrangeIconicWindows (USER32.7)
172 UINT WINAPI
ArrangeIconicWindows( HWND parent
)
176 INT x
, y
, xspacing
, yspacing
;
178 GetClientRect( parent
, &rectParent
);
180 y
= rectParent
.bottom
;
181 xspacing
= SYSMETRICS_CXICONSPACING
;
182 yspacing
= SYSMETRICS_CYICONSPACING
;
184 hwndChild
= GetWindow( parent
, GW_CHILD
);
187 if( IsIconic( hwndChild
) )
189 WND
*wndPtr
= WIN_FindWndPtr(hwndChild
);
191 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
193 SetWindowPos( hwndChild
, 0, x
+ (xspacing
- SYSMETRICS_CXICON
) / 2,
194 y
- yspacing
- SYSMETRICS_CYICON
/2, 0, 0,
195 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
196 if( IsWindow(hwndChild
) )
197 WINPOS_ShowIconTitle(wndPtr
, TRUE
);
198 WIN_ReleaseWndPtr(wndPtr
);
200 if (x
<= rectParent
.right
- xspacing
) x
+= xspacing
;
207 hwndChild
= GetWindow( hwndChild
, GW_HWNDNEXT
);
213 /***********************************************************************
214 * SwitchToThisWindow16 (USER.172)
216 void WINAPI
SwitchToThisWindow16( HWND16 hwnd
, BOOL16 restore
)
218 SwitchToThisWindow( hwnd
, restore
);
222 /***********************************************************************
223 * SwitchToThisWindow (USER32.539)
225 void WINAPI
SwitchToThisWindow( HWND hwnd
, BOOL restore
)
227 ShowWindow( hwnd
, restore
? SW_RESTORE
: SW_SHOWMINIMIZED
);
231 /***********************************************************************
232 * GetWindowRect16 (USER.32)
234 void WINAPI
GetWindowRect16( HWND16 hwnd
, LPRECT16 rect
)
236 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
239 CONV_RECT32TO16( &wndPtr
->rectWindow
, rect
);
240 if (wndPtr
->dwStyle
& WS_CHILD
)
241 MapWindowPoints16( wndPtr
->parent
->hwndSelf
, 0, (POINT16
*)rect
, 2 );
242 WIN_ReleaseWndPtr(wndPtr
);
246 /***********************************************************************
247 * GetWindowRect (USER32.308)
249 BOOL WINAPI
GetWindowRect( HWND hwnd
, LPRECT rect
)
251 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
252 if (!wndPtr
) return FALSE
;
254 *rect
= wndPtr
->rectWindow
;
255 if (wndPtr
->dwStyle
& WS_CHILD
)
256 MapWindowPoints( wndPtr
->parent
->hwndSelf
, 0, (POINT
*)rect
, 2 );
257 WIN_ReleaseWndPtr(wndPtr
);
262 /***********************************************************************
265 BOOL WINAPI
GetWindowRgn ( HWND hwnd
, HRGN hrgn
)
269 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
270 if (!wndPtr
) return (ERROR
);
272 FIXME (win
, "GetWindowRgn: doesn't really do regions\n");
274 memset (&rect
, 0, sizeof(rect
));
276 GetWindowRect ( hwnd
, &rect
);
278 FIXME (win
, "Check whether a valid region here\n");
280 SetRectRgn ( hrgn
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
282 WIN_ReleaseWndPtr(wndPtr
);
283 return (SIMPLEREGION
);
286 /***********************************************************************
289 INT WINAPI
SetWindowRgn( HWND hwnd
, HRGN hrgn
,BOOL bRedraw
)
293 FIXME (win
, "SetWindowRgn: stub\n");
297 /***********************************************************************
300 INT16 WINAPI
SetWindowRgn16( HWND16 hwnd
, HRGN16 hrgn
,BOOL16 bRedraw
)
304 FIXME (win
, "SetWindowRgn16: stub\n");
309 /***********************************************************************
310 * GetClientRect16 (USER.33)
312 void WINAPI
GetClientRect16( HWND16 hwnd
, LPRECT16 rect
)
314 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
316 rect
->left
= rect
->top
= rect
->right
= rect
->bottom
= 0;
319 rect
->right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
320 rect
->bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
322 WIN_ReleaseWndPtr(wndPtr
);
326 /***********************************************************************
327 * GetClientRect (USER.220)
329 BOOL WINAPI
GetClientRect( HWND hwnd
, LPRECT rect
)
331 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
333 rect
->left
= rect
->top
= rect
->right
= rect
->bottom
= 0;
334 if (!wndPtr
) return FALSE
;
335 rect
->right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
336 rect
->bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
338 WIN_ReleaseWndPtr(wndPtr
);
343 /*******************************************************************
344 * ClientToScreen16 (USER.28)
346 void WINAPI
ClientToScreen16( HWND16 hwnd
, LPPOINT16 lppnt
)
348 MapWindowPoints16( hwnd
, 0, lppnt
, 1 );
352 /*******************************************************************
353 * ClientToScreen (USER32.52)
355 BOOL WINAPI
ClientToScreen( HWND hwnd
, LPPOINT lppnt
)
357 MapWindowPoints( hwnd
, 0, lppnt
, 1 );
362 /*******************************************************************
363 * ScreenToClient16 (USER.29)
365 void WINAPI
ScreenToClient16( HWND16 hwnd
, LPPOINT16 lppnt
)
367 MapWindowPoints16( 0, hwnd
, lppnt
, 1 );
371 /*******************************************************************
372 * ScreenToClient (USER32.447)
374 BOOL WINAPI
ScreenToClient( HWND hwnd
, LPPOINT lppnt
)
376 MapWindowPoints( 0, hwnd
, lppnt
, 1 );
381 /***********************************************************************
382 * WINPOS_WindowFromPoint
384 * Find the window and hittest for a given point.
386 INT16
WINPOS_WindowFromPoint( WND
* wndScope
, POINT16 pt
, WND
**ppWnd
)
389 INT16 hittest
= HTERROR
;
394 wndPtr
= WIN_LockWndPtr(wndScope
->child
);
396 if( wndScope
->flags
& WIN_MANAGED
)
398 /* In managed mode we have to check wndScope first as it is also
399 * a window which received the mouse event. */
401 if( wndScope
->dwStyle
& WS_DISABLED
)
406 if( pt
.x
< wndScope
->rectClient
.left
|| pt
.x
>= wndScope
->rectClient
.right
||
407 pt
.y
< wndScope
->rectClient
.top
|| pt
.y
>= wndScope
->rectClient
.bottom
)
410 MapWindowPoints16( GetDesktopWindow16(), wndScope
->hwndSelf
, &xy
, 1 );
416 /* If point is in window, and window is visible, and it */
417 /* is enabled (or it's a top-level window), then explore */
418 /* its children. Otherwise, go to the next window. */
420 if ((wndPtr
->dwStyle
& WS_VISIBLE
) &&
421 (!(wndPtr
->dwStyle
& WS_DISABLED
) ||
422 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)) &&
423 (xy
.x
>= wndPtr
->rectWindow
.left
) &&
424 (xy
.x
< wndPtr
->rectWindow
.right
) &&
425 (xy
.y
>= wndPtr
->rectWindow
.top
) &&
426 (xy
.y
< wndPtr
->rectWindow
.bottom
))
428 *ppWnd
= wndPtr
; /* Got a suitable window */
430 /* If window is minimized or disabled, return at once */
431 if (wndPtr
->dwStyle
& WS_MINIMIZE
)
433 retvalue
= HTCAPTION
;
436 if (wndPtr
->dwStyle
& WS_DISABLED
)
442 /* If point is not in client area, ignore the children */
443 if ((xy
.x
< wndPtr
->rectClient
.left
) ||
444 (xy
.x
>= wndPtr
->rectClient
.right
) ||
445 (xy
.y
< wndPtr
->rectClient
.top
) ||
446 (xy
.y
>= wndPtr
->rectClient
.bottom
)) break;
448 xy
.x
-= wndPtr
->rectClient
.left
;
449 xy
.y
-= wndPtr
->rectClient
.top
;
450 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->child
);
454 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->next
);
459 /* If nothing found, try the scope window */
460 if (!*ppWnd
) *ppWnd
= wndScope
;
462 /* Send the WM_NCHITTEST message (only if to the same task) */
463 if ((*ppWnd
)->hmemTaskQ
== GetFastQueue16())
465 hittest
= (INT16
)SendMessage16( (*ppWnd
)->hwndSelf
, WM_NCHITTEST
,
466 0, MAKELONG( pt
.x
, pt
.y
) );
467 if (hittest
!= HTTRANSPARENT
)
469 retvalue
= hittest
; /* Found the window */
479 /* If no children found in last search, make point relative to parent */
482 xy
.x
+= (*ppWnd
)->rectClient
.left
;
483 xy
.y
+= (*ppWnd
)->rectClient
.top
;
486 /* Restart the search from the next sibling */
487 WIN_UpdateWndPtr(&wndPtr
,(*ppWnd
)->next
);
488 *ppWnd
= (*ppWnd
)->parent
;
492 WIN_ReleaseWndPtr(wndPtr
);
497 /*******************************************************************
498 * WindowFromPoint16 (USER.30)
500 HWND16 WINAPI
WindowFromPoint16( POINT16 pt
)
503 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt
, &pWnd
);
504 WIN_ReleaseDesktop();
505 return pWnd
->hwndSelf
;
509 /*******************************************************************
510 * WindowFromPoint (USER32.582)
512 HWND WINAPI
WindowFromPoint( POINT pt
)
516 CONV_POINT32TO16( &pt
, &pt16
);
517 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16
, &pWnd
);
518 WIN_ReleaseDesktop();
519 return (HWND
)pWnd
->hwndSelf
;
523 /*******************************************************************
524 * ChildWindowFromPoint16 (USER.191)
526 HWND16 WINAPI
ChildWindowFromPoint16( HWND16 hwndParent
, POINT16 pt
)
529 CONV_POINT16TO32( &pt
, &pt32
);
530 return (HWND16
)ChildWindowFromPoint( hwndParent
, pt32
);
534 /*******************************************************************
535 * ChildWindowFromPoint (USER32.49)
537 HWND WINAPI
ChildWindowFromPoint( HWND hwndParent
, POINT pt
)
539 /* pt is in the client coordinates */
541 WND
* wnd
= WIN_FindWndPtr(hwndParent
);
547 /* get client rect fast */
548 rect
.top
= rect
.left
= 0;
549 rect
.right
= wnd
->rectClient
.right
- wnd
->rectClient
.left
;
550 rect
.bottom
= wnd
->rectClient
.bottom
- wnd
->rectClient
.top
;
552 if (!PtInRect( &rect
, pt
))
557 WIN_UpdateWndPtr(&wnd
,wnd
->child
);
560 if (PtInRect( &wnd
->rectWindow
, pt
))
562 retvalue
= wnd
->hwndSelf
;
565 WIN_UpdateWndPtr(&wnd
,wnd
->next
);
567 retvalue
= hwndParent
;
569 WIN_ReleaseWndPtr(wnd
);
573 /*******************************************************************
574 * ChildWindowFromPointEx16 (USER.50)
576 HWND16 WINAPI
ChildWindowFromPointEx16( HWND16 hwndParent
, POINT16 pt
, UINT16 uFlags
)
579 CONV_POINT16TO32( &pt
, &pt32
);
580 return (HWND16
)ChildWindowFromPointEx( hwndParent
, pt32
, uFlags
);
584 /*******************************************************************
585 * ChildWindowFromPointEx32 (USER32.50)
587 HWND WINAPI
ChildWindowFromPointEx( HWND hwndParent
, POINT pt
,
590 /* pt is in the client coordinates */
592 WND
* wnd
= WIN_FindWndPtr(hwndParent
);
598 /* get client rect fast */
599 rect
.top
= rect
.left
= 0;
600 rect
.right
= wnd
->rectClient
.right
- wnd
->rectClient
.left
;
601 rect
.bottom
= wnd
->rectClient
.bottom
- wnd
->rectClient
.top
;
603 if (!PtInRect( &rect
, pt
))
608 WIN_UpdateWndPtr(&wnd
,wnd
->child
);
612 if (PtInRect( &wnd
->rectWindow
, pt
)) {
613 if ( (uFlags
& CWP_SKIPINVISIBLE
) &&
614 !(wnd
->dwStyle
& WS_VISIBLE
) );
615 else if ( (uFlags
& CWP_SKIPDISABLED
) &&
616 (wnd
->dwStyle
& WS_DISABLED
) );
617 else if ( (uFlags
& CWP_SKIPTRANSPARENT
) &&
618 (wnd
->dwExStyle
& WS_EX_TRANSPARENT
) );
621 retvalue
= wnd
->hwndSelf
;
624 WIN_UpdateWndPtr(&wnd
,wnd
->next
);
628 retvalue
= hwndParent
;
630 WIN_ReleaseWndPtr(wnd
);
635 /*******************************************************************
636 * WINPOS_GetWinOffset
638 * Calculate the offset between the origin of the two windows. Used
639 * to implement MapWindowPoints.
641 static void WINPOS_GetWinOffset( HWND hwndFrom
, HWND hwndTo
,
646 offset
->x
= offset
->y
= 0;
647 if (hwndFrom
== hwndTo
) return;
649 /* Translate source window origin to screen coords */
652 if (!(wndPtr
= WIN_FindWndPtr( hwndFrom
)))
654 ERR(win
,"bad hwndFrom = %04x\n",hwndFrom
);
657 while (wndPtr
->parent
)
659 offset
->x
+= wndPtr
->rectClient
.left
;
660 offset
->y
+= wndPtr
->rectClient
.top
;
661 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->parent
);
663 WIN_ReleaseWndPtr(wndPtr
);
666 /* Translate origin to destination window coords */
669 if (!(wndPtr
= WIN_FindWndPtr( hwndTo
)))
671 ERR(win
,"bad hwndTo = %04x\n", hwndTo
);
674 while (wndPtr
->parent
)
676 offset
->x
-= wndPtr
->rectClient
.left
;
677 offset
->y
-= wndPtr
->rectClient
.top
;
678 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->parent
);
680 WIN_ReleaseWndPtr(wndPtr
);
685 /*******************************************************************
686 * MapWindowPoints16 (USER.258)
688 void WINAPI
MapWindowPoints16( HWND16 hwndFrom
, HWND16 hwndTo
,
689 LPPOINT16 lppt
, UINT16 count
)
693 WINPOS_GetWinOffset( hwndFrom
, hwndTo
, &offset
);
703 /*******************************************************************
704 * MapWindowPoints (USER32.386)
706 INT WINAPI
MapWindowPoints( HWND hwndFrom
, HWND hwndTo
,
707 LPPOINT lppt
, UINT count
)
711 WINPOS_GetWinOffset( hwndFrom
, hwndTo
, &offset
);
718 return MAKELONG( LOWORD(offset
.x
), LOWORD(offset
.y
) );
722 /***********************************************************************
723 * IsIconic16 (USER.31)
725 BOOL16 WINAPI
IsIconic16(HWND16 hWnd
)
727 return IsIconic(hWnd
);
731 /***********************************************************************
732 * IsIconic (USER32.345)
734 BOOL WINAPI
IsIconic(HWND hWnd
)
737 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
738 if (wndPtr
== NULL
) return FALSE
;
739 retvalue
= (wndPtr
->dwStyle
& WS_MINIMIZE
) != 0;
740 WIN_ReleaseWndPtr(wndPtr
);
745 /***********************************************************************
746 * IsZoomed (USER.272)
748 BOOL16 WINAPI
IsZoomed16(HWND16 hWnd
)
750 return IsZoomed(hWnd
);
754 /***********************************************************************
755 * IsZoomed (USER.352)
757 BOOL WINAPI
IsZoomed(HWND hWnd
)
760 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
761 if (wndPtr
== NULL
) return FALSE
;
762 retvalue
= (wndPtr
->dwStyle
& WS_MAXIMIZE
) != 0;
763 WIN_ReleaseWndPtr(wndPtr
);
768 /*******************************************************************
769 * GetActiveWindow (USER.60)
771 HWND16 WINAPI
GetActiveWindow16(void)
773 return (HWND16
)GetActiveWindow();
776 /*******************************************************************
777 * GetActiveWindow (USER32.205)
779 HWND WINAPI
GetActiveWindow(void)
781 MESSAGEQUEUE
*pCurMsgQ
= 0;
784 /* Get the messageQ for the current thread */
785 if (!(pCurMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( GetFastQueue16() )))
787 WARN( win
, "\tCurrent message queue not found. Exiting!\n" );
791 /* Return the current active window from the perQ data of the current message Q */
792 hwndActive
= PERQDATA_GetActiveWnd( pCurMsgQ
->pQData
);
794 QUEUE_Unlock( pCurMsgQ
);
799 /*******************************************************************
802 static BOOL
WINPOS_CanActivate(WND
* pWnd
)
804 if( pWnd
&& ((pWnd
->dwStyle
& (WS_DISABLED
| WS_VISIBLE
| WS_CHILD
))
805 == WS_VISIBLE
) ) return TRUE
;
810 /*******************************************************************
811 * SetActiveWindow16 (USER.59)
813 HWND16 WINAPI
SetActiveWindow16( HWND16 hwnd
)
815 return SetActiveWindow(hwnd
);
819 /*******************************************************************
820 * SetActiveWindow (USER32.463)
822 HWND WINAPI
SetActiveWindow( HWND hwnd
)
825 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
826 MESSAGEQUEUE
*pMsgQ
= 0, *pCurMsgQ
= 0;
828 if ( !WINPOS_CanActivate(wndPtr
) )
834 /* Get the messageQ for the current thread */
835 if (!(pCurMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( GetFastQueue16() )))
837 WARN( win
, "\tCurrent message queue not found. Exiting!\n" );
841 /* Retrieve the message queue associated with this window */
842 pMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( wndPtr
->hmemTaskQ
);
845 WARN( win
, "\tWindow message queue not found. Exiting!\n" );
849 /* Make sure that the window is associated with the calling threads
850 * message queue. It must share the same perQ data.
853 if ( pCurMsgQ
->pQData
!= pMsgQ
->pQData
)
856 /* Save current active window */
857 prev
= PERQDATA_GetActiveWnd( pMsgQ
->pQData
);
859 WINPOS_SetActiveWindow( hwnd
, 0, 0 );
862 /* Unlock the queues before returning */
864 QUEUE_Unlock( pMsgQ
);
866 QUEUE_Unlock( pCurMsgQ
);
869 WIN_ReleaseWndPtr(wndPtr
);
874 /*******************************************************************
875 * GetForegroundWindow16 (USER.608)
877 HWND16 WINAPI
GetForegroundWindow16(void)
879 return (HWND16
)GetForegroundWindow();
883 /*******************************************************************
884 * SetForegroundWindow16 (USER.609)
886 BOOL16 WINAPI
SetForegroundWindow16( HWND16 hwnd
)
888 return SetForegroundWindow( hwnd
);
892 /*******************************************************************
893 * GetForegroundWindow (USER32.241)
895 HWND WINAPI
GetForegroundWindow(void)
897 return GetActiveWindow();
901 /*******************************************************************
902 * SetForegroundWindow (USER32.482)
904 BOOL WINAPI
SetForegroundWindow( HWND hwnd
)
906 SetActiveWindow( hwnd
);
911 /*******************************************************************
912 * GetShellWindow16 (USER.600)
914 HWND16 WINAPI
GetShellWindow16(void)
916 return GetShellWindow();
919 /*******************************************************************
920 * SetShellWindow (USER32.504)
922 HWND WINAPI
SetShellWindow(HWND hwndshell
)
923 { WARN(win
, "(hWnd=%08x) semi stub\n",hwndshell
);
925 hGlobalShellWindow
= hwndshell
;
926 return hGlobalShellWindow
;
930 /*******************************************************************
931 * GetShellWindow (USER32.287)
933 HWND WINAPI
GetShellWindow(void)
934 { WARN(win
, "(hWnd=%x) semi stub\n",hGlobalShellWindow
);
936 return hGlobalShellWindow
;
940 /***********************************************************************
941 * BringWindowToTop16 (USER.45)
943 BOOL16 WINAPI
BringWindowToTop16( HWND16 hwnd
)
945 return BringWindowToTop(hwnd
);
949 /***********************************************************************
950 * BringWindowToTop (USER32.11)
952 BOOL WINAPI
BringWindowToTop( HWND hwnd
)
954 return SetWindowPos( hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
);
958 /***********************************************************************
959 * MoveWindow16 (USER.56)
961 BOOL16 WINAPI
MoveWindow16( HWND16 hwnd
, INT16 x
, INT16 y
, INT16 cx
, INT16 cy
,
964 return MoveWindow(hwnd
,x
,y
,cx
,cy
,repaint
);
968 /***********************************************************************
969 * MoveWindow (USER32.399)
971 BOOL WINAPI
MoveWindow( HWND hwnd
, INT x
, INT y
, INT cx
, INT cy
,
974 int flags
= SWP_NOZORDER
| SWP_NOACTIVATE
;
975 if (!repaint
) flags
|= SWP_NOREDRAW
;
976 TRACE(win
, "%04x %d,%d %dx%d %d\n",
977 hwnd
, x
, y
, cx
, cy
, repaint
);
978 return SetWindowPos( hwnd
, 0, x
, y
, cx
, cy
, flags
);
981 /***********************************************************************
982 * WINPOS_InitInternalPos
984 static LPINTERNALPOS
WINPOS_InitInternalPos( WND
* wnd
, POINT pt
,
987 LPINTERNALPOS lpPos
= (LPINTERNALPOS
) GetPropA( wnd
->hwndSelf
,
991 /* this happens when the window is minimized/maximized
992 * for the first time (rectWindow is not adjusted yet) */
994 lpPos
= HeapAlloc( SystemHeap
, 0, sizeof(INTERNALPOS
) );
995 if( !lpPos
) return NULL
;
997 SetPropA( wnd
->hwndSelf
, atomInternalPos
, (HANDLE
)lpPos
);
998 lpPos
->hwndIconTitle
= 0; /* defer until needs to be shown */
999 CONV_RECT32TO16( &wnd
->rectWindow
, &lpPos
->rectNormal
);
1000 *(UINT
*)&lpPos
->ptIconPos
= *(UINT
*)&lpPos
->ptMaxPos
= 0xFFFFFFFF;
1003 if( wnd
->dwStyle
& WS_MINIMIZE
)
1004 CONV_POINT32TO16( &pt
, &lpPos
->ptIconPos
);
1005 else if( wnd
->dwStyle
& WS_MAXIMIZE
)
1006 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1007 else if( restoreRect
)
1008 CONV_RECT32TO16( restoreRect
, &lpPos
->rectNormal
);
1013 /***********************************************************************
1014 * WINPOS_RedrawIconTitle
1016 BOOL
WINPOS_RedrawIconTitle( HWND hWnd
)
1018 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)GetPropA( hWnd
, atomInternalPos
);
1021 if( lpPos
->hwndIconTitle
)
1023 SendMessageA( lpPos
->hwndIconTitle
, WM_SHOWWINDOW
, TRUE
, 0);
1024 InvalidateRect( lpPos
->hwndIconTitle
, NULL
, TRUE
);
1031 /***********************************************************************
1032 * WINPOS_ShowIconTitle
1034 BOOL
WINPOS_ShowIconTitle( WND
* pWnd
, BOOL bShow
)
1036 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)GetPropA( pWnd
->hwndSelf
, atomInternalPos
);
1038 if( lpPos
&& !(pWnd
->flags
& WIN_MANAGED
))
1040 HWND16 hWnd
= lpPos
->hwndIconTitle
;
1042 TRACE(win
,"0x%04x %i\n", pWnd
->hwndSelf
, (bShow
!= 0) );
1045 lpPos
->hwndIconTitle
= hWnd
= ICONTITLE_Create( pWnd
);
1048 pWnd
= WIN_FindWndPtr(hWnd
);
1050 if( !(pWnd
->dwStyle
& WS_VISIBLE
) )
1052 SendMessageA( hWnd
, WM_SHOWWINDOW
, TRUE
, 0 );
1053 SetWindowPos( hWnd
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
1054 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_SHOWWINDOW
);
1056 WIN_ReleaseWndPtr(pWnd
);
1058 else ShowWindow( hWnd
, SW_HIDE
);
1063 /*******************************************************************
1064 * WINPOS_GetMinMaxInfo
1066 * Get the minimized and maximized information for a window.
1068 void WINPOS_GetMinMaxInfo( WND
*wndPtr
, POINT
*maxSize
, POINT
*maxPos
,
1069 POINT
*minTrack
, POINT
*maxTrack
)
1071 LPINTERNALPOS lpPos
;
1075 /* Compute default values */
1077 MinMax
.ptMaxSize
.x
= SYSMETRICS_CXSCREEN
;
1078 MinMax
.ptMaxSize
.y
= SYSMETRICS_CYSCREEN
;
1079 MinMax
.ptMinTrackSize
.x
= SYSMETRICS_CXMINTRACK
;
1080 MinMax
.ptMinTrackSize
.y
= SYSMETRICS_CYMINTRACK
;
1081 MinMax
.ptMaxTrackSize
.x
= SYSMETRICS_CXSCREEN
;
1082 MinMax
.ptMaxTrackSize
.y
= SYSMETRICS_CYSCREEN
;
1084 if (wndPtr
->flags
& WIN_MANAGED
) xinc
= yinc
= 0;
1085 else if (HAS_DLGFRAME( wndPtr
->dwStyle
, wndPtr
->dwExStyle
))
1087 xinc
= SYSMETRICS_CXDLGFRAME
;
1088 yinc
= SYSMETRICS_CYDLGFRAME
;
1093 if (HAS_THICKFRAME(wndPtr
->dwStyle
))
1095 xinc
+= SYSMETRICS_CXFRAME
;
1096 yinc
+= SYSMETRICS_CYFRAME
;
1098 if (wndPtr
->dwStyle
& WS_BORDER
)
1100 xinc
+= SYSMETRICS_CXBORDER
;
1101 yinc
+= SYSMETRICS_CYBORDER
;
1104 MinMax
.ptMaxSize
.x
+= 2 * xinc
;
1105 MinMax
.ptMaxSize
.y
+= 2 * yinc
;
1107 lpPos
= (LPINTERNALPOS
)GetPropA( wndPtr
->hwndSelf
, atomInternalPos
);
1108 if( lpPos
&& !EMPTYPOINT(lpPos
->ptMaxPos
) )
1109 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &MinMax
.ptMaxPosition
);
1112 MinMax
.ptMaxPosition
.x
= -xinc
;
1113 MinMax
.ptMaxPosition
.y
= -yinc
;
1116 SendMessageA( wndPtr
->hwndSelf
, WM_GETMINMAXINFO
, 0, (LPARAM
)&MinMax
);
1118 /* Some sanity checks */
1120 TRACE(win
,"%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1121 MinMax
.ptMaxSize
.x
, MinMax
.ptMaxSize
.y
,
1122 MinMax
.ptMaxPosition
.x
, MinMax
.ptMaxPosition
.y
,
1123 MinMax
.ptMaxTrackSize
.x
, MinMax
.ptMaxTrackSize
.y
,
1124 MinMax
.ptMinTrackSize
.x
, MinMax
.ptMinTrackSize
.y
);
1125 MinMax
.ptMaxTrackSize
.x
= MAX( MinMax
.ptMaxTrackSize
.x
,
1126 MinMax
.ptMinTrackSize
.x
);
1127 MinMax
.ptMaxTrackSize
.y
= MAX( MinMax
.ptMaxTrackSize
.y
,
1128 MinMax
.ptMinTrackSize
.y
);
1130 if (maxSize
) *maxSize
= MinMax
.ptMaxSize
;
1131 if (maxPos
) *maxPos
= MinMax
.ptMaxPosition
;
1132 if (minTrack
) *minTrack
= MinMax
.ptMinTrackSize
;
1133 if (maxTrack
) *maxTrack
= MinMax
.ptMaxTrackSize
;
1136 /***********************************************************************
1137 * WINPOS_MinMaximize
1139 * Fill in lpRect and return additional flags to be used with SetWindowPos().
1140 * This function assumes that 'cmd' is different from the current window
1143 UINT16
WINPOS_MinMaximize( WND
* wndPtr
, UINT16 cmd
, LPRECT16 lpRect
)
1145 UINT16 swpFlags
= 0;
1147 POINT size
= { wndPtr
->rectWindow
.left
, wndPtr
->rectWindow
.top
};
1148 LPINTERNALPOS lpPos
= WINPOS_InitInternalPos( wndPtr
, size
,
1149 &wndPtr
->rectWindow
);
1151 TRACE(win
,"0x%04x %u\n", wndPtr
->hwndSelf
, cmd
);
1153 if (lpPos
&& !HOOK_CallHooks16(WH_CBT
, HCBT_MINMAX
, wndPtr
->hwndSelf
, cmd
))
1155 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1157 if( !SendMessageA( wndPtr
->hwndSelf
, WM_QUERYOPEN
, 0, 0L ) )
1158 return (SWP_NOSIZE
| SWP_NOMOVE
);
1159 swpFlags
|= SWP_NOCOPYBITS
;
1164 if( wndPtr
->dwStyle
& WS_MAXIMIZE
)
1166 wndPtr
->flags
|= WIN_RESTORE_MAX
;
1167 wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
1170 wndPtr
->flags
&= ~WIN_RESTORE_MAX
;
1171 wndPtr
->dwStyle
|= WS_MINIMIZE
;
1173 lpPos
->ptIconPos
= WINPOS_FindIconPos( wndPtr
, lpPos
->ptIconPos
);
1175 SetRect16( lpRect
, lpPos
->ptIconPos
.x
, lpPos
->ptIconPos
.y
,
1176 SYSMETRICS_CXICON
, SYSMETRICS_CYICON
);
1177 swpFlags
|= SWP_NOCOPYBITS
;
1181 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &pt
);
1182 WINPOS_GetMinMaxInfo( wndPtr
, &size
, &pt
, NULL
, NULL
);
1183 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1185 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1187 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
1188 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
1190 wndPtr
->dwStyle
|= WS_MAXIMIZE
;
1192 SetRect16( lpRect
, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
,
1197 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1199 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
1200 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
1201 if( wndPtr
->flags
& WIN_RESTORE_MAX
)
1203 /* Restore to maximized position */
1204 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &pt
);
1205 WINPOS_GetMinMaxInfo( wndPtr
, &size
, &pt
, NULL
, NULL
);
1206 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1207 wndPtr
->dwStyle
|= WS_MAXIMIZE
;
1208 SetRect16( lpRect
, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
, size
.x
, size
.y
);
1213 if( !(wndPtr
->dwStyle
& WS_MAXIMIZE
) ) return (UINT16
)(-1);
1214 else wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
1216 /* Restore to normal position */
1218 *lpRect
= lpPos
->rectNormal
;
1219 lpRect
->right
-= lpRect
->left
;
1220 lpRect
->bottom
-= lpRect
->top
;
1224 } else swpFlags
|= SWP_NOSIZE
| SWP_NOMOVE
;
1228 /***********************************************************************
1229 * ShowWindowAsync (USER32.535)
1231 * doesn't wait; returns immediately.
1232 * used by threads to toggle windows in other (possibly hanging) threads
1234 BOOL WINAPI
ShowWindowAsync( HWND hwnd
, INT cmd
)
1236 /* FIXME: does ShowWindow() return immediately ? */
1237 return ShowWindow(hwnd
, cmd
);
1241 /***********************************************************************
1242 * ShowWindow16 (USER.42)
1244 BOOL16 WINAPI
ShowWindow16( HWND16 hwnd
, INT16 cmd
)
1246 return ShowWindow(hwnd
,cmd
);
1250 /***********************************************************************
1251 * ShowWindow (USER32.534)
1253 BOOL WINAPI
ShowWindow( HWND hwnd
, INT cmd
)
1255 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
1256 BOOL wasVisible
, showFlag
;
1257 RECT16 newPos
= {0, 0, 0, 0};
1260 if (!wndPtr
) return FALSE
;
1262 TRACE(win
,"hwnd=%04x, cmd=%d\n", hwnd
, cmd
);
1264 wasVisible
= (wndPtr
->dwStyle
& WS_VISIBLE
) != 0;
1269 if (!wasVisible
) goto END
;;
1270 swp
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
|
1271 SWP_NOACTIVATE
| SWP_NOZORDER
;
1272 if ((hwnd
== GetFocus()) || IsChild( hwnd
, GetFocus()))
1274 /* Revert focus to parent */
1275 SetFocus( GetParent(hwnd
) );
1279 case SW_SHOWMINNOACTIVE
:
1280 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1282 case SW_SHOWMINIMIZED
:
1283 swp
|= SWP_SHOWWINDOW
;
1286 swp
|= SWP_FRAMECHANGED
;
1287 if( !(wndPtr
->dwStyle
& WS_MINIMIZE
) )
1288 swp
|= WINPOS_MinMaximize( wndPtr
, SW_MINIMIZE
, &newPos
);
1289 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1292 case SW_SHOWMAXIMIZED
: /* same as SW_MAXIMIZE */
1293 swp
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
1294 if( !(wndPtr
->dwStyle
& WS_MAXIMIZE
) )
1295 swp
|= WINPOS_MinMaximize( wndPtr
, SW_MAXIMIZE
, &newPos
);
1296 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1300 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1303 swp
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
1306 case SW_SHOWNOACTIVATE
:
1307 swp
|= SWP_NOZORDER
;
1308 if (GetActiveWindow()) swp
|= SWP_NOACTIVATE
;
1310 case SW_SHOWNORMAL
: /* same as SW_NORMAL: */
1311 case SW_SHOWDEFAULT
: /* FIXME: should have its own handler */
1313 swp
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
1315 if( wndPtr
->dwStyle
& (WS_MINIMIZE
| WS_MAXIMIZE
) )
1316 swp
|= WINPOS_MinMaximize( wndPtr
, SW_RESTORE
, &newPos
);
1317 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1321 showFlag
= (cmd
!= SW_HIDE
);
1322 if (showFlag
!= wasVisible
)
1324 SendMessageA( hwnd
, WM_SHOWWINDOW
, showFlag
, 0 );
1325 if (!IsWindow( hwnd
)) goto END
;
1328 if ((wndPtr
->dwStyle
& WS_CHILD
) &&
1329 !IsWindowVisible( wndPtr
->parent
->hwndSelf
) &&
1330 (swp
& (SWP_NOSIZE
| SWP_NOMOVE
)) == (SWP_NOSIZE
| SWP_NOMOVE
) )
1332 /* Don't call SetWindowPos() on invisible child windows */
1333 if (cmd
== SW_HIDE
) wndPtr
->dwStyle
&= ~WS_VISIBLE
;
1334 else wndPtr
->dwStyle
|= WS_VISIBLE
;
1338 /* We can't activate a child window */
1339 if (wndPtr
->dwStyle
& WS_CHILD
) swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1340 SetWindowPos( hwnd
, HWND_TOP
,
1341 newPos
.left
, newPos
.top
, newPos
.right
, newPos
.bottom
, swp
);
1342 if (!IsWindow( hwnd
)) goto END
;
1343 else if( wndPtr
->dwStyle
& WS_MINIMIZE
) WINPOS_ShowIconTitle( wndPtr
, TRUE
);
1346 if (wndPtr
->flags
& WIN_NEED_SIZE
)
1348 /* should happen only in CreateWindowEx() */
1349 int wParam
= SIZE_RESTORED
;
1351 wndPtr
->flags
&= ~WIN_NEED_SIZE
;
1352 if (wndPtr
->dwStyle
& WS_MAXIMIZE
) wParam
= SIZE_MAXIMIZED
;
1353 else if (wndPtr
->dwStyle
& WS_MINIMIZE
) wParam
= SIZE_MINIMIZED
;
1354 SendMessageA( hwnd
, WM_SIZE
, wParam
,
1355 MAKELONG(wndPtr
->rectClient
.right
-wndPtr
->rectClient
.left
,
1356 wndPtr
->rectClient
.bottom
-wndPtr
->rectClient
.top
));
1357 SendMessageA( hwnd
, WM_MOVE
, 0,
1358 MAKELONG(wndPtr
->rectClient
.left
, wndPtr
->rectClient
.top
) );
1362 WIN_ReleaseWndPtr(wndPtr
);
1367 /***********************************************************************
1368 * GetInternalWindowPos16 (USER.460)
1370 UINT16 WINAPI
GetInternalWindowPos16( HWND16 hwnd
, LPRECT16 rectWnd
,
1373 WINDOWPLACEMENT16 wndpl
;
1374 if (GetWindowPlacement16( hwnd
, &wndpl
))
1376 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
1377 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
1378 return wndpl
.showCmd
;
1384 /***********************************************************************
1385 * GetInternalWindowPos (USER32.245)
1387 UINT WINAPI
GetInternalWindowPos( HWND hwnd
, LPRECT rectWnd
,
1390 WINDOWPLACEMENT wndpl
;
1391 if (GetWindowPlacement( hwnd
, &wndpl
))
1393 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
1394 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
1395 return wndpl
.showCmd
;
1400 /***********************************************************************
1401 * GetWindowPlacement16 (USER.370)
1403 BOOL16 WINAPI
GetWindowPlacement16( HWND16 hwnd
, WINDOWPLACEMENT16
*wndpl
)
1405 WND
*pWnd
= WIN_FindWndPtr( hwnd
);
1406 LPINTERNALPOS lpPos
;
1408 if(!pWnd
) return FALSE
;
1410 lpPos
= (LPINTERNALPOS
)WINPOS_InitInternalPos( pWnd
,
1411 *(LPPOINT
)&pWnd
->rectWindow
.left
, &pWnd
->rectWindow
);
1412 wndpl
->length
= sizeof(*wndpl
);
1413 if( pWnd
->dwStyle
& WS_MINIMIZE
)
1414 wndpl
->showCmd
= SW_SHOWMINIMIZED
;
1416 wndpl
->showCmd
= ( pWnd
->dwStyle
& WS_MAXIMIZE
)
1417 ? SW_SHOWMAXIMIZED
: SW_SHOWNORMAL
;
1418 if( pWnd
->flags
& WIN_RESTORE_MAX
)
1419 wndpl
->flags
= WPF_RESTORETOMAXIMIZED
;
1422 wndpl
->ptMinPosition
= lpPos
->ptIconPos
;
1423 wndpl
->ptMaxPosition
= lpPos
->ptMaxPos
;
1424 wndpl
->rcNormalPosition
= lpPos
->rectNormal
;
1426 WIN_ReleaseWndPtr(pWnd
);
1431 /***********************************************************************
1432 * GetWindowPlacement (USER32.307)
1435 * Fails if wndpl->length of Win95 (!) apps is invalid.
1437 BOOL WINAPI
GetWindowPlacement( HWND hwnd
, WINDOWPLACEMENT
*pwpl32
)
1441 WINDOWPLACEMENT16 wpl
;
1442 wpl
.length
= sizeof(wpl
);
1443 if( GetWindowPlacement16( hwnd
, &wpl
) )
1445 pwpl32
->length
= sizeof(*pwpl32
);
1446 pwpl32
->flags
= wpl
.flags
;
1447 pwpl32
->showCmd
= wpl
.showCmd
;
1448 CONV_POINT16TO32( &wpl
.ptMinPosition
, &pwpl32
->ptMinPosition
);
1449 CONV_POINT16TO32( &wpl
.ptMaxPosition
, &pwpl32
->ptMaxPosition
);
1450 CONV_RECT16TO32( &wpl
.rcNormalPosition
, &pwpl32
->rcNormalPosition
);
1458 /***********************************************************************
1459 * WINPOS_SetPlacement
1461 static BOOL
WINPOS_SetPlacement( HWND hwnd
, const WINDOWPLACEMENT16
*wndpl
,
1464 WND
*pWnd
= WIN_FindWndPtr( hwnd
);
1467 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)WINPOS_InitInternalPos( pWnd
,
1468 *(LPPOINT
)&pWnd
->rectWindow
.left
, &pWnd
->rectWindow
);
1470 if( flags
& PLACE_MIN
) lpPos
->ptIconPos
= wndpl
->ptMinPosition
;
1471 if( flags
& PLACE_MAX
) lpPos
->ptMaxPos
= wndpl
->ptMaxPosition
;
1472 if( flags
& PLACE_RECT
) lpPos
->rectNormal
= wndpl
->rcNormalPosition
;
1474 if( pWnd
->dwStyle
& WS_MINIMIZE
)
1476 WINPOS_ShowIconTitle( pWnd
, FALSE
);
1477 if( wndpl
->flags
& WPF_SETMINPOSITION
&& !EMPTYPOINT(lpPos
->ptIconPos
))
1478 SetWindowPos( hwnd
, 0, lpPos
->ptIconPos
.x
, lpPos
->ptIconPos
.y
,
1479 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1481 else if( pWnd
->dwStyle
& WS_MAXIMIZE
)
1483 if( !EMPTYPOINT(lpPos
->ptMaxPos
) )
1484 SetWindowPos( hwnd
, 0, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
,
1485 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1487 else if( flags
& PLACE_RECT
)
1488 SetWindowPos( hwnd
, 0, lpPos
->rectNormal
.left
, lpPos
->rectNormal
.top
,
1489 lpPos
->rectNormal
.right
- lpPos
->rectNormal
.left
,
1490 lpPos
->rectNormal
.bottom
- lpPos
->rectNormal
.top
,
1491 SWP_NOZORDER
| SWP_NOACTIVATE
);
1493 ShowWindow( hwnd
, wndpl
->showCmd
);
1494 if( IsWindow(hwnd
) && pWnd
->dwStyle
& WS_MINIMIZE
)
1496 if( pWnd
->dwStyle
& WS_VISIBLE
) WINPOS_ShowIconTitle( pWnd
, TRUE
);
1498 /* SDK: ...valid only the next time... */
1499 if( wndpl
->flags
& WPF_RESTORETOMAXIMIZED
) pWnd
->flags
|= WIN_RESTORE_MAX
;
1501 WIN_ReleaseWndPtr(pWnd
);
1508 /***********************************************************************
1509 * SetWindowPlacement16 (USER.371)
1511 BOOL16 WINAPI
SetWindowPlacement16(HWND16 hwnd
, const WINDOWPLACEMENT16
*wndpl
)
1513 return WINPOS_SetPlacement( hwnd
, wndpl
,
1514 PLACE_MIN
| PLACE_MAX
| PLACE_RECT
);
1517 /***********************************************************************
1518 * SetWindowPlacement (USER32.519)
1521 * Fails if wndpl->length of Win95 (!) apps is invalid.
1523 BOOL WINAPI
SetWindowPlacement( HWND hwnd
, const WINDOWPLACEMENT
*pwpl32
)
1527 WINDOWPLACEMENT16 wpl
= { sizeof(WINDOWPLACEMENT16
),
1528 pwpl32
->flags
, pwpl32
->showCmd
, { pwpl32
->ptMinPosition
.x
,
1529 pwpl32
->ptMinPosition
.y
}, { pwpl32
->ptMaxPosition
.x
,
1530 pwpl32
->ptMaxPosition
.y
}, { pwpl32
->rcNormalPosition
.left
,
1531 pwpl32
->rcNormalPosition
.top
, pwpl32
->rcNormalPosition
.right
,
1532 pwpl32
->rcNormalPosition
.bottom
} };
1534 return WINPOS_SetPlacement( hwnd
, &wpl
, PLACE_MIN
| PLACE_MAX
| PLACE_RECT
);
1540 /***********************************************************************
1541 * SetInternalWindowPos16 (USER.461)
1543 void WINAPI
SetInternalWindowPos16( HWND16 hwnd
, UINT16 showCmd
,
1544 LPRECT16 rect
, LPPOINT16 pt
)
1546 if( IsWindow16(hwnd
) )
1548 WINDOWPLACEMENT16 wndpl
;
1551 wndpl
.length
= sizeof(wndpl
);
1552 wndpl
.showCmd
= showCmd
;
1553 wndpl
.flags
= flags
= 0;
1558 wndpl
.flags
|= WPF_SETMINPOSITION
;
1559 wndpl
.ptMinPosition
= *pt
;
1563 flags
|= PLACE_RECT
;
1564 wndpl
.rcNormalPosition
= *rect
;
1566 WINPOS_SetPlacement( hwnd
, &wndpl
, flags
);
1571 /***********************************************************************
1572 * SetInternalWindowPos (USER32.483)
1574 void WINAPI
SetInternalWindowPos( HWND hwnd
, UINT showCmd
,
1575 LPRECT rect
, LPPOINT pt
)
1577 if( IsWindow(hwnd
) )
1579 WINDOWPLACEMENT16 wndpl
;
1582 wndpl
.length
= sizeof(wndpl
);
1583 wndpl
.showCmd
= showCmd
;
1584 wndpl
.flags
= flags
= 0;
1589 wndpl
.flags
|= WPF_SETMINPOSITION
;
1590 CONV_POINT32TO16( pt
, &wndpl
.ptMinPosition
);
1594 flags
|= PLACE_RECT
;
1595 CONV_RECT32TO16( rect
, &wndpl
.rcNormalPosition
);
1597 WINPOS_SetPlacement( hwnd
, &wndpl
, flags
);
1601 /*******************************************************************
1602 * WINPOS_SetActiveWindow
1604 * SetActiveWindow() back-end. This is the only function that
1605 * can assign active status to a window. It must be called only
1606 * for the top level windows.
1608 BOOL
WINPOS_SetActiveWindow( HWND hWnd
, BOOL fMouse
, BOOL fChangeFocus
)
1610 CBTACTIVATESTRUCT16
* cbtStruct
;
1611 WND
* wndPtr
=0, *wndTemp
;
1612 HQUEUE16 hOldActiveQueue
, hNewActiveQueue
;
1613 MESSAGEQUEUE
*pOldActiveQueue
= 0, *pNewActiveQueue
= 0;
1615 HWND hwndActive
= 0;
1618 /* Get current active window from the active queue */
1621 pOldActiveQueue
= QUEUE_Lock( hActiveQueue
);
1622 if ( pOldActiveQueue
)
1623 hwndActive
= PERQDATA_GetActiveWnd( pOldActiveQueue
->pQData
);
1626 /* paranoid checks */
1627 if( hWnd
== GetDesktopWindow() || hWnd
== hwndActive
) goto CLEANUP
;
1629 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1632 wndPtr
= WIN_FindWndPtr(hWnd
);
1633 hOldActiveQueue
= hActiveQueue
;
1635 if( (wndTemp
= WIN_FindWndPtr(hwndActive
)) )
1637 wIconized
= HIWORD(wndTemp
->dwStyle
& WS_MINIMIZE
);
1638 WIN_ReleaseWndPtr(wndTemp
);
1641 TRACE(win
,"no current active window.\n");
1643 /* call CBT hook chain */
1644 if ((cbtStruct
= SEGPTR_NEW(CBTACTIVATESTRUCT16
)))
1647 cbtStruct
->fMouse
= fMouse
;
1648 cbtStruct
->hWndActive
= hwndActive
;
1649 wRet
= HOOK_CallHooks16( WH_CBT
, HCBT_ACTIVATE
, (WPARAM16
)hWnd
,
1650 (LPARAM
)SEGPTR_GET(cbtStruct
) );
1651 SEGPTR_FREE(cbtStruct
);
1654 /* Unlock the active queue before returning */
1655 if ( pOldActiveQueue
)
1656 QUEUE_Unlock( pOldActiveQueue
);
1657 WIN_ReleaseWndPtr(wndPtr
);
1662 /* set prev active wnd to current active wnd and send notification */
1663 if ((hwndPrevActive
= hwndActive
) && IsWindow(hwndPrevActive
))
1665 MESSAGEQUEUE
*pTempActiveQueue
= 0;
1667 if (!SendMessageA( hwndPrevActive
, WM_NCACTIVATE
, FALSE
, 0 ))
1669 if (GetSysModalWindow16() != hWnd
) goto CLEANUP
;
1670 /* disregard refusal if hWnd is sysmodal */
1674 SendMessageA( hwndPrevActive
, WM_ACTIVATE
,
1675 MAKEWPARAM( WA_INACTIVE
, wIconized
),
1678 /* FIXME: must be SendMessage16() because A doesn't do
1679 * intertask at this time */
1680 SendMessage16( hwndPrevActive
, WM_ACTIVATE
, WA_INACTIVE
,
1681 MAKELPARAM( (HWND16
)hWnd
, wIconized
) );
1684 /* check if something happened during message processing
1685 * (global active queue may have changed)
1687 pTempActiveQueue
= QUEUE_Lock( hActiveQueue
);
1688 hwndActive
= PERQDATA_GetActiveWnd( pTempActiveQueue
->pQData
);
1689 QUEUE_Unlock( pTempActiveQueue
);
1690 if( hwndPrevActive
!= hwndActive
)
1694 /* Set new active window in the message queue */
1698 pNewActiveQueue
= QUEUE_Lock( wndPtr
->hmemTaskQ
);
1699 if ( pNewActiveQueue
)
1700 PERQDATA_SetActiveWnd( pNewActiveQueue
->pQData
, hwndActive
);
1702 else /* have to do this or MDI frame activation goes to hell */
1703 if( pOldActiveQueue
)
1704 PERQDATA_SetActiveWnd( pOldActiveQueue
->pQData
, 0 );
1706 /* send palette messages */
1707 if (hWnd
&& SendMessage16( hWnd
, WM_QUERYNEWPALETTE
, 0, 0L))
1708 SendMessage16((HWND16
)-1, WM_PALETTEISCHANGING
, (WPARAM16
)hWnd
, 0L );
1710 /* if prev wnd is minimized redraw icon title */
1711 if( IsIconic( hwndPrevActive
) ) WINPOS_RedrawIconTitle(hwndPrevActive
);
1713 /* managed windows will get ConfigureNotify event */
1714 if (wndPtr
&& !(wndPtr
->dwStyle
& WS_CHILD
) && !(wndPtr
->flags
& WIN_MANAGED
))
1716 /* check Z-order and bring hWnd to the top */
1717 for (wndTemp
= WIN_LockWndPtr(WIN_GetDesktop()->child
); wndTemp
; WIN_UpdateWndPtr(&wndTemp
,wndTemp
->next
))
1719 if (wndTemp
->dwStyle
& WS_VISIBLE
) break;
1721 WIN_ReleaseDesktop();
1722 WIN_ReleaseWndPtr(wndTemp
);
1724 if( wndTemp
!= wndPtr
)
1725 SetWindowPos(hWnd
, HWND_TOP
, 0,0,0,0,
1726 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
1727 if (!IsWindow(hWnd
)) goto CLEANUP
;
1730 /* Get a handle to the new active queue */
1731 hNewActiveQueue
= wndPtr
? wndPtr
->hmemTaskQ
: 0;
1733 /* send WM_ACTIVATEAPP if necessary */
1734 if (hOldActiveQueue
!= hNewActiveQueue
)
1736 WND
**list
, **ppWnd
;
1737 WND
*pDesktop
= WIN_GetDesktop();
1739 if ((list
= WIN_BuildWinArray( pDesktop
, 0, NULL
)))
1741 for (ppWnd
= list
; *ppWnd
; ppWnd
++)
1743 if (!IsWindow( (*ppWnd
)->hwndSelf
)) continue;
1745 if ((*ppWnd
)->hmemTaskQ
== hOldActiveQueue
)
1746 SendMessage16( (*ppWnd
)->hwndSelf
, WM_ACTIVATEAPP
,
1747 0, QUEUE_GetQueueTask(hNewActiveQueue
) );
1749 WIN_ReleaseWinArray(list
);
1752 hActiveQueue
= hNewActiveQueue
;
1754 if ((list
= WIN_BuildWinArray(pDesktop
, 0, NULL
)))
1756 for (ppWnd
= list
; *ppWnd
; ppWnd
++)
1758 if (!IsWindow( (*ppWnd
)->hwndSelf
)) continue;
1760 if ((*ppWnd
)->hmemTaskQ
== hNewActiveQueue
)
1761 SendMessage16( (*ppWnd
)->hwndSelf
, WM_ACTIVATEAPP
,
1762 1, QUEUE_GetQueueTask( hOldActiveQueue
) );
1764 WIN_ReleaseWinArray(list
);
1766 WIN_ReleaseDesktop();
1768 if (!IsWindow(hWnd
)) goto CLEANUP
;
1773 /* walk up to the first unowned window */
1774 wndTemp
= WIN_LockWndPtr(wndPtr
);
1775 while (wndTemp
->owner
)
1777 WIN_UpdateWndPtr(&wndTemp
,wndTemp
->owner
);
1779 /* and set last active owned popup */
1780 wndTemp
->hwndLastActive
= hWnd
;
1782 wIconized
= HIWORD(wndTemp
->dwStyle
& WS_MINIMIZE
);
1783 WIN_ReleaseWndPtr(wndTemp
);
1784 SendMessageA( hWnd
, WM_NCACTIVATE
, TRUE
, 0 );
1786 SendMessageA( hWnd
, WM_ACTIVATE
,
1787 MAKEWPARAM( (fMouse
) ? WA_CLICKACTIVE
: WA_ACTIVE
, wIconized
),
1788 (LPARAM
)hwndPrevActive
);
1790 SendMessage16(hWnd
, WM_ACTIVATE
, (fMouse
) ? WA_CLICKACTIVE
: WA_ACTIVE
,
1791 MAKELPARAM( (HWND16
)hwndPrevActive
, wIconized
) );
1794 if( !IsWindow(hWnd
) ) goto CLEANUP
;
1797 /* change focus if possible */
1798 if( fChangeFocus
&& GetFocus() )
1799 if( WIN_GetTopParent(GetFocus()) != hwndActive
)
1800 FOCUS_SwitchFocus( pNewActiveQueue
, GetFocus(),
1801 (wndPtr
&& (wndPtr
->dwStyle
& WS_MINIMIZE
))?
1806 if( !hwndPrevActive
&& wndPtr
)
1807 (*wndPtr
->pDriver
->pForceWindowRaise
)(wndPtr
);
1809 /* if active wnd is minimized redraw icon title */
1810 if( IsIconic(hwndActive
) ) WINPOS_RedrawIconTitle(hwndActive
);
1812 bRet
= 1; // Success
1816 /* Unlock the message queues before returning */
1817 if ( pOldActiveQueue
)
1818 QUEUE_Unlock( pOldActiveQueue
);
1819 if ( pNewActiveQueue
)
1820 QUEUE_Unlock( pNewActiveQueue
);
1821 WIN_ReleaseWndPtr(wndPtr
);
1822 return bRet
? (hWnd
== hwndActive
) : 0;
1825 /*******************************************************************
1826 * WINPOS_ActivateOtherWindow
1828 * Activates window other than pWnd.
1830 BOOL
WINPOS_ActivateOtherWindow(WND
* pWnd
)
1834 HWND hwndActive
= 0;
1836 /* Get current active window from the active queue */
1839 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
1842 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
1843 QUEUE_Unlock( pActiveQueue
);
1847 if( pWnd
->hwndSelf
== hwndPrevActive
)
1850 if( hwndActive
!= pWnd
->hwndSelf
&&
1851 ( hwndActive
|| QUEUE_IsExitingQueue(pWnd
->hmemTaskQ
)) )
1854 if( !(pWnd
->dwStyle
& WS_POPUP
) || !(pWnd
->owner
) ||
1855 !WINPOS_CanActivate((pWndTo
= WIN_GetTopParentPtr(pWnd
->owner
))) )
1857 WND
* pWndPtr
= WIN_GetTopParentPtr(pWnd
);
1859 pWndTo
= WIN_FindWndPtr(hwndPrevActive
);
1861 while( !WINPOS_CanActivate(pWndTo
) )
1863 /* by now owned windows should've been taken care of */
1864 WIN_UpdateWndPtr(&pWndTo
,pWndPtr
->next
);
1865 WIN_UpdateWndPtr(&pWndPtr
,pWndTo
);
1866 if( !pWndTo
) break;
1868 WIN_ReleaseWndPtr(pWndPtr
);
1871 bRet
= WINPOS_SetActiveWindow( pWndTo
? pWndTo
->hwndSelf
: 0, FALSE
, TRUE
);
1873 /* switch desktop queue to current active */
1876 WIN_GetDesktop()->hmemTaskQ
= pWndTo
->hmemTaskQ
;
1877 WIN_ReleaseWndPtr(pWndTo
);
1878 WIN_ReleaseDesktop();
1885 /*******************************************************************
1886 * WINPOS_ChangeActiveWindow
1889 BOOL
WINPOS_ChangeActiveWindow( HWND hWnd
, BOOL mouseMsg
)
1891 WND
*wndPtr
, *wndTemp
;
1893 HWND hwndActive
= 0;
1895 /* Get current active window from the active queue */
1898 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
1901 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
1902 QUEUE_Unlock( pActiveQueue
);
1907 return WINPOS_SetActiveWindow( 0, mouseMsg
, TRUE
);
1909 wndPtr
= WIN_FindWndPtr(hWnd
);
1910 if( !wndPtr
) return FALSE
;
1912 /* child windows get WM_CHILDACTIVATE message */
1913 if( (wndPtr
->dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1915 retvalue
= SendMessageA(hWnd
, WM_CHILDACTIVATE
, 0, 0L);
1919 if( hWnd
== hwndActive
)
1925 if( !WINPOS_SetActiveWindow(hWnd
,mouseMsg
,TRUE
) )
1931 /* switch desktop queue to current active */
1932 wndTemp
= WIN_GetDesktop();
1933 if( wndPtr
->parent
== wndTemp
)
1934 wndTemp
->hmemTaskQ
= wndPtr
->hmemTaskQ
;
1935 WIN_ReleaseDesktop();
1939 WIN_ReleaseWndPtr(wndPtr
);
1944 /***********************************************************************
1945 * WINPOS_SendNCCalcSize
1947 * Send a WM_NCCALCSIZE message to a window.
1948 * All parameters are read-only except newClientRect.
1949 * oldWindowRect, oldClientRect and winpos must be non-NULL only
1950 * when calcValidRect is TRUE.
1952 LONG
WINPOS_SendNCCalcSize( HWND hwnd
, BOOL calcValidRect
,
1953 RECT
*newWindowRect
, RECT
*oldWindowRect
,
1954 RECT
*oldClientRect
, WINDOWPOS
*winpos
,
1955 RECT
*newClientRect
)
1957 NCCALCSIZE_PARAMS params
;
1958 WINDOWPOS winposCopy
;
1961 params
.rgrc
[0] = *newWindowRect
;
1964 winposCopy
= *winpos
;
1965 params
.rgrc
[1] = *oldWindowRect
;
1966 params
.rgrc
[2] = *oldClientRect
;
1967 params
.lppos
= &winposCopy
;
1969 result
= SendMessageA( hwnd
, WM_NCCALCSIZE
, calcValidRect
,
1971 TRACE(win
, "%d,%d-%d,%d\n",
1972 params
.rgrc
[0].left
, params
.rgrc
[0].top
,
1973 params
.rgrc
[0].right
, params
.rgrc
[0].bottom
);
1974 *newClientRect
= params
.rgrc
[0];
1979 /***********************************************************************
1980 * WINPOS_HandleWindowPosChanging16
1982 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
1984 LONG
WINPOS_HandleWindowPosChanging16( WND
*wndPtr
, WINDOWPOS16
*winpos
)
1986 POINT maxSize
, minTrack
;
1987 if (winpos
->flags
& SWP_NOSIZE
) return 0;
1988 if ((wndPtr
->dwStyle
& WS_THICKFRAME
) ||
1989 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) == 0))
1991 WINPOS_GetMinMaxInfo( wndPtr
, &maxSize
, NULL
, &minTrack
, NULL
);
1992 if (maxSize
.x
< winpos
->cx
) winpos
->cx
= maxSize
.x
;
1993 if (maxSize
.y
< winpos
->cy
) winpos
->cy
= maxSize
.y
;
1994 if (!(wndPtr
->dwStyle
& WS_MINIMIZE
))
1996 if (winpos
->cx
< minTrack
.x
) winpos
->cx
= minTrack
.x
;
1997 if (winpos
->cy
< minTrack
.y
) winpos
->cy
= minTrack
.y
;
2004 /***********************************************************************
2005 * WINPOS_HandleWindowPosChanging
2007 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2009 LONG
WINPOS_HandleWindowPosChanging( WND
*wndPtr
, WINDOWPOS
*winpos
)
2012 if (winpos
->flags
& SWP_NOSIZE
) return 0;
2013 if ((wndPtr
->dwStyle
& WS_THICKFRAME
) ||
2014 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) == 0))
2016 WINPOS_GetMinMaxInfo( wndPtr
, &maxSize
, NULL
, NULL
, NULL
);
2017 winpos
->cx
= MIN( winpos
->cx
, maxSize
.x
);
2018 winpos
->cy
= MIN( winpos
->cy
, maxSize
.y
);
2023 /***********************************************************************
2026 * fix Z order taking into account owned popups -
2027 * basically we need to maintain them above the window that owns them
2029 * FIXME: hide/show owned popups when owner visibility changes.
2031 static HWND
SWP_DoOwnedPopups(WND
* pDesktop
, WND
* wndPtr
, HWND hwndInsertAfter
, WORD flags
)
2033 WND
* w
= WIN_LockWndPtr(pDesktop
->child
);
2035 WARN(win
, "(%04x) hInsertAfter = %04x\n", wndPtr
->hwndSelf
, hwndInsertAfter
);
2037 if( (wndPtr
->dwStyle
& WS_POPUP
) && wndPtr
->owner
)
2039 /* make sure this popup stays above the owner */
2041 HWND hwndLocalPrev
= HWND_TOP
;
2043 if( hwndInsertAfter
!= HWND_TOP
)
2045 while( w
!= wndPtr
->owner
)
2047 if (w
!= wndPtr
) hwndLocalPrev
= w
->hwndSelf
;
2048 if( hwndLocalPrev
== hwndInsertAfter
) break;
2049 WIN_UpdateWndPtr(&w
,w
->next
);
2051 hwndInsertAfter
= hwndLocalPrev
;
2054 else if( wndPtr
->dwStyle
& WS_CHILD
)
2057 WIN_UpdateWndPtr(&w
, pDesktop
->child
);
2061 if( w
== wndPtr
) break;
2063 if( (w
->dwStyle
& WS_POPUP
) && w
->owner
== wndPtr
)
2065 SetWindowPos(w
->hwndSelf
, hwndInsertAfter
, 0, 0, 0, 0,
2066 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOSENDCHANGING
| SWP_DEFERERASE
);
2067 hwndInsertAfter
= w
->hwndSelf
;
2069 WIN_UpdateWndPtr(&w
, w
->next
);
2073 WIN_ReleaseWndPtr(w
);
2074 return hwndInsertAfter
;
2077 /***********************************************************************
2080 * Make window look nice without excessive repainting
2082 * visible and update regions are in window coordinates
2083 * client and window rectangles are in parent client coordinates
2085 * FIXME: SWP_EX_PAINTSELF in uFlags works only if both old and new
2086 * window rects have the same origin.
2088 * Returns: uFlags and a dirty region in *pVisRgn.
2090 static UINT
SWP_CopyValidBits( WND
* Wnd
, HRGN
* pVisRgn
,
2091 LPRECT lpOldWndRect
,
2092 LPRECT lpOldClientRect
, UINT uFlags
)
2095 HRGN newVisRgn
, dirtyRgn
;
2096 INT my
= COMPLEXREGION
;
2098 TRACE(win
,"\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2099 Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
,
2100 Wnd
->rectWindow
.right
, Wnd
->rectWindow
.bottom
,
2101 lpOldWndRect
->left
, lpOldWndRect
->top
,
2102 lpOldWndRect
->right
, lpOldWndRect
->bottom
, *pVisRgn
);
2103 TRACE(win
,"\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2104 Wnd
->rectClient
.left
, Wnd
->rectClient
.top
,
2105 Wnd
->rectClient
.right
, Wnd
->rectClient
.bottom
,
2106 lpOldClientRect
->left
, lpOldClientRect
->top
,
2107 lpOldClientRect
->right
,lpOldClientRect
->bottom
);
2109 if( Wnd
->hrgnUpdate
== 1 )
2110 uFlags
|= SWP_EX_NOCOPY
; /* whole window is invalid, nothing to copy */
2112 newVisRgn
= DCE_GetVisRgn( Wnd
->hwndSelf
, DCX_WINDOW
| DCX_CLIPSIBLINGS
, 0, 0);
2113 dirtyRgn
= CreateRectRgn( 0, 0, 0, 0 );
2115 if( !(uFlags
& SWP_EX_NOCOPY
) ) /* make sure dst region covers only valid bits */
2116 my
= CombineRgn( dirtyRgn
, newVisRgn
, *pVisRgn
, RGN_AND
);
2118 if( (my
== NULLREGION
) || (uFlags
& SWP_EX_NOCOPY
) )
2122 TRACE(win
,"\twon't copy anything!\n");
2124 /* set dirtyRgn to the sum of old and new visible regions
2125 * in parent client coordinates */
2127 OffsetRgn( newVisRgn
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2128 OffsetRgn( *pVisRgn
, lpOldWndRect
->left
, lpOldWndRect
->top
);
2130 CombineRgn(*pVisRgn
, *pVisRgn
, newVisRgn
, RGN_OR
);
2132 else /* copy valid bits to a new location */
2134 INT dx
, dy
, ow
, oh
, nw
, nh
, ocw
, ncw
, och
, nch
;
2135 HRGN hrgnValid
= dirtyRgn
; /* non-empty intersection of old and new visible rgns */
2137 /* subtract already invalid region inside Wnd from the dst region */
2139 if( Wnd
->hrgnUpdate
)
2140 if( CombineRgn( hrgnValid
, hrgnValid
, Wnd
->hrgnUpdate
, RGN_DIFF
) == NULLREGION
)
2143 /* check if entire window can be copied */
2145 ow
= lpOldWndRect
->right
- lpOldWndRect
->left
;
2146 oh
= lpOldWndRect
->bottom
- lpOldWndRect
->top
;
2147 nw
= Wnd
->rectWindow
.right
- Wnd
->rectWindow
.left
;
2148 nh
= Wnd
->rectWindow
.bottom
- Wnd
->rectWindow
.top
;
2150 ocw
= lpOldClientRect
->right
- lpOldClientRect
->left
;
2151 och
= lpOldClientRect
->bottom
- lpOldClientRect
->top
;
2152 ncw
= Wnd
->rectClient
.right
- Wnd
->rectClient
.left
;
2153 nch
= Wnd
->rectClient
.bottom
- Wnd
->rectClient
.top
;
2155 if( (ocw
!= ncw
) || (och
!= nch
) ||
2156 ( ow
!= nw
) || ( oh
!= nw
) ||
2157 ((lpOldClientRect
->top
- lpOldWndRect
->top
) !=
2158 (Wnd
->rectClient
.top
- Wnd
->rectWindow
.top
)) ||
2159 ((lpOldClientRect
->left
- lpOldWndRect
->left
) !=
2160 (Wnd
->rectClient
.left
- Wnd
->rectWindow
.left
)) )
2162 dx
= Wnd
->rectClient
.left
- lpOldClientRect
->left
;
2163 dy
= Wnd
->rectClient
.top
- lpOldClientRect
->top
;
2165 /* restrict valid bits to the common client rect */
2167 r
.left
= Wnd
->rectClient
.left
- Wnd
->rectWindow
.left
;
2168 r
.top
= Wnd
->rectClient
.top
- Wnd
->rectWindow
.top
;
2169 r
.right
= r
.left
+ MIN( ocw
, ncw
);
2170 r
.bottom
= r
.top
+ MIN( och
, nch
);
2172 REGION_CropRgn( hrgnValid
, hrgnValid
, &r
,
2173 (uFlags
& SWP_EX_PAINTSELF
) ? NULL
: (POINT
*)&(Wnd
->rectWindow
));
2174 GetRgnBox( hrgnValid
, &r
);
2175 if( IsRectEmpty( &r
) )
2177 r
= *lpOldClientRect
;
2181 dx
= Wnd
->rectWindow
.left
- lpOldWndRect
->left
;
2182 dy
= Wnd
->rectWindow
.top
- lpOldWndRect
->top
;
2183 if( !(uFlags
& SWP_EX_PAINTSELF
) )
2184 OffsetRgn( hrgnValid
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2188 if( !(uFlags
& SWP_EX_PAINTSELF
) )
2190 /* Move remaining regions to parent coordinates */
2191 OffsetRgn( newVisRgn
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2192 OffsetRgn( *pVisRgn
, lpOldWndRect
->left
, lpOldWndRect
->top
);
2195 OffsetRect( &r
, -lpOldWndRect
->left
, -lpOldWndRect
->top
);
2197 TRACE(win
,"\tcomputing dirty region!\n");
2199 /* Compute combined dirty region (old + new - valid) */
2200 CombineRgn( *pVisRgn
, *pVisRgn
, newVisRgn
, RGN_OR
);
2201 CombineRgn( *pVisRgn
, *pVisRgn
, hrgnValid
, RGN_DIFF
);
2203 /* Blt valid bits, r is the rect to copy */
2208 HDC hDC
= ( uFlags
& SWP_EX_PAINTSELF
)
2209 ? GetDCEx( Wnd
->hwndSelf
, hrgnValid
, DCX_WINDOW
| DCX_CACHE
|
2210 DCX_KEEPCLIPRGN
| DCX_INTERSECTRGN
| DCX_CLIPSIBLINGS
)
2211 : GetDCEx( Wnd
->parent
->hwndSelf
, hrgnValid
, DCX_CACHE
|
2212 DCX_KEEPCLIPRGN
| DCX_INTERSECTRGN
| DCX_CLIPSIBLINGS
);
2213 if( (dc
= (DC
*)GDI_GetObjPtr(hDC
, DC_MAGIC
)) )
2215 if( oh
> nh
) r
.bottom
= r
.top
+ nh
;
2216 if( ow
< nw
) r
.right
= r
.left
+ nw
;
2218 Wnd
->pDriver
->pSurfaceCopy( Wnd
->parent
, dc
, dx
, dy
, &r
, TRUE
);
2220 GDI_HEAP_UNLOCK( hDC
);
2222 ReleaseDC( (uFlags
& SWP_EX_PAINTSELF
) ?
2223 Wnd
->hwndSelf
: Wnd
->parent
->hwndSelf
, hDC
);
2227 /* *pVisRgn now points to the invalidated region */
2229 DeleteObject(newVisRgn
);
2230 DeleteObject(dirtyRgn
);
2234 /***********************************************************************
2235 * SWP_DoSimpleFrameChanged
2237 static void SWP_DoSimpleFrameChanged( WND
* wndPtr
, RECT
* pNewClientRect
, RECT
* pOldClientRect
)
2242 if( pNewClientRect
->right
> pOldClientRect
->right
) /* redraw exposed client area on the right */
2244 rect
.top
= 0; rect
.bottom
= pNewClientRect
->bottom
- pNewClientRect
->top
;
2245 rect
.left
= pOldClientRect
->right
- pNewClientRect
->left
;
2246 rect
.right
= pNewClientRect
->right
- pNewClientRect
->left
;
2248 PAINT_RedrawWindow( wndPtr
->hwndSelf
, &rect
, 0, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
|
2249 RDW_ERASENOW
| RDW_ALLCHILDREN
, RDW_EX_TOPFRAME
);
2251 if( pNewClientRect
->bottom
> pOldClientRect
->bottom
) /* redraw exposed client area on the bottom */
2253 rect
.left
= 0; rect
.right
= ((wErase
)? pOldClientRect
->right
: pNewClientRect
->right
) - pNewClientRect
->left
;
2254 rect
.top
= pOldClientRect
->bottom
- pNewClientRect
->top
;
2255 rect
.bottom
= pNewClientRect
->bottom
- pNewClientRect
->top
;
2257 PAINT_RedrawWindow( wndPtr
->hwndSelf
, &rect
, 0, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
|
2258 RDW_ERASENOW
| RDW_ALLCHILDREN
, RDW_EX_TOPFRAME
);
2260 if( !wErase
) /* IMMEDIATELY update the nonclient area */
2263 if( (h
= WIN_UpdateNCRgn(wndPtr
, TRUE
, TRUE
)) > 1) DeleteObject( h
);
2267 /***********************************************************************
2268 * SWP_DoWinPosChanging
2270 static BOOL
SWP_DoWinPosChanging( WND
* wndPtr
, WINDOWPOS
* pWinpos
,
2271 RECT
* pNewWindowRect
, RECT
* pNewClientRect
)
2273 /* Send WM_WINDOWPOSCHANGING message */
2275 if (!(pWinpos
->flags
& SWP_NOSENDCHANGING
))
2276 SendMessageA( wndPtr
->hwndSelf
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
)pWinpos
);
2278 /* Calculate new position and size */
2280 *pNewWindowRect
= wndPtr
->rectWindow
;
2281 *pNewClientRect
= (wndPtr
->dwStyle
& WS_MINIMIZE
) ? wndPtr
->rectWindow
2282 : wndPtr
->rectClient
;
2284 if (!(pWinpos
->flags
& SWP_NOSIZE
))
2286 pNewWindowRect
->right
= pNewWindowRect
->left
+ pWinpos
->cx
;
2287 pNewWindowRect
->bottom
= pNewWindowRect
->top
+ pWinpos
->cy
;
2289 if (!(pWinpos
->flags
& SWP_NOMOVE
))
2291 pNewWindowRect
->left
= pWinpos
->x
;
2292 pNewWindowRect
->top
= pWinpos
->y
;
2293 pNewWindowRect
->right
+= pWinpos
->x
- wndPtr
->rectWindow
.left
;
2294 pNewWindowRect
->bottom
+= pWinpos
->y
- wndPtr
->rectWindow
.top
;
2296 OffsetRect( pNewClientRect
, pWinpos
->x
- wndPtr
->rectWindow
.left
,
2297 pWinpos
->y
- wndPtr
->rectWindow
.top
);
2300 pWinpos
->flags
|= SWP_NOCLIENTMOVE
| SWP_NOCLIENTSIZE
;
2304 /***********************************************************************
2307 static UINT
SWP_DoNCCalcSize( WND
* wndPtr
, WINDOWPOS
* pWinpos
,
2308 RECT
* pNewWindowRect
, RECT
* pNewClientRect
, WORD f
)
2312 /* Send WM_NCCALCSIZE message to get new client area */
2313 if( (pWinpos
->flags
& (SWP_FRAMECHANGED
| SWP_NOSIZE
)) != SWP_NOSIZE
)
2315 wvrFlags
= WINPOS_SendNCCalcSize( pWinpos
->hwnd
, TRUE
, pNewWindowRect
,
2316 &wndPtr
->rectWindow
, &wndPtr
->rectClient
,
2317 pWinpos
, pNewClientRect
);
2319 /* FIXME: WVR_ALIGNxxx */
2321 if( pNewClientRect
->left
!= wndPtr
->rectClient
.left
||
2322 pNewClientRect
->top
!= wndPtr
->rectClient
.top
)
2323 pWinpos
->flags
&= ~SWP_NOCLIENTMOVE
;
2325 if( (pNewClientRect
->right
- pNewClientRect
->left
!=
2326 wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
) ||
2327 (pNewClientRect
->bottom
- pNewClientRect
->top
!=
2328 wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
) )
2329 pWinpos
->flags
&= ~SWP_NOCLIENTSIZE
;
2332 if( !(f
& SWP_NOMOVE
) && (pNewClientRect
->left
!= wndPtr
->rectClient
.left
||
2333 pNewClientRect
->top
!= wndPtr
->rectClient
.top
) )
2334 pWinpos
->flags
&= ~SWP_NOCLIENTMOVE
;
2338 /***********************************************************************
2339 * SetWindowPos (USER.2)
2341 BOOL16 WINAPI
SetWindowPos16( HWND16 hwnd
, HWND16 hwndInsertAfter
,
2342 INT16 x
, INT16 y
, INT16 cx
, INT16 cy
, WORD flags
)
2344 return SetWindowPos(hwnd
,(INT
)(INT16
)hwndInsertAfter
,x
,y
,cx
,cy
,flags
);
2347 /***********************************************************************
2348 * SetWindowPos (USER32.520)
2350 BOOL WINAPI
SetWindowPos( HWND hwnd
, HWND hwndInsertAfter
,
2351 INT x
, INT y
, INT cx
, INT cy
, WORD flags
)
2354 WND
* wndPtr
,*wndTemp
;
2355 RECT newWindowRect
, newClientRect
;
2356 RECT oldWindowRect
, oldClientRect
;
2358 UINT wvrFlags
= 0, uFlags
= 0;
2359 BOOL retvalue
, resync
= FALSE
;
2360 HWND hwndActive
= 0;
2362 /* Get current active window from the active queue */
2365 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
2368 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
2369 QUEUE_Unlock( pActiveQueue
);
2373 TRACE(win
,"hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2374 hwnd
, x
, y
, x
+cx
, y
+cy
, flags
);
2376 /* ------------------------------------------------------------------------ CHECKS */
2378 /* Check window handle */
2380 if (hwnd
== GetDesktopWindow()) return FALSE
;
2381 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return FALSE
;
2383 TRACE(win
,"\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr
->rectWindow
.left
, wndPtr
->rectWindow
.top
,
2384 wndPtr
->rectWindow
.right
, wndPtr
->rectWindow
.bottom
, (unsigned)wndPtr
->dwStyle
);
2386 /* Fix redundant flags */
2388 if(wndPtr
->dwStyle
& WS_VISIBLE
)
2389 flags
&= ~SWP_SHOWWINDOW
;
2392 if (!(flags
& SWP_SHOWWINDOW
))
2393 flags
|= SWP_NOREDRAW
;
2394 flags
&= ~SWP_HIDEWINDOW
;
2397 if ( cx
< 0 ) cx
= 0; if( cy
< 0 ) cy
= 0;
2399 if ((wndPtr
->rectWindow
.right
- wndPtr
->rectWindow
.left
== cx
) &&
2400 (wndPtr
->rectWindow
.bottom
- wndPtr
->rectWindow
.top
== cy
))
2401 flags
|= SWP_NOSIZE
; /* Already the right size */
2403 if ((wndPtr
->rectWindow
.left
== x
) && (wndPtr
->rectWindow
.top
== y
))
2404 flags
|= SWP_NOMOVE
; /* Already the right position */
2406 if (hwnd
== hwndActive
)
2407 flags
|= SWP_NOACTIVATE
; /* Already active */
2410 if(!(flags
& SWP_NOACTIVATE
)) /* Bring to the top when activating */
2412 flags
&= ~SWP_NOZORDER
;
2413 hwndInsertAfter
= HWND_TOP
;
2418 /* Check hwndInsertAfter */
2420 /* FIXME: TOPMOST not supported yet */
2421 if ((hwndInsertAfter
== HWND_TOPMOST
) ||
2422 (hwndInsertAfter
== HWND_NOTOPMOST
)) hwndInsertAfter
= HWND_TOP
;
2424 /* hwndInsertAfter must be a sibling of the window */
2425 if ((hwndInsertAfter
!= HWND_TOP
) && (hwndInsertAfter
!= HWND_BOTTOM
))
2427 WND
* wnd
= WIN_FindWndPtr(hwndInsertAfter
);
2430 if( wnd
->parent
!= wndPtr
->parent
)
2433 WIN_ReleaseWndPtr(wnd
);
2436 if( wnd
->next
== wndPtr
) flags
|= SWP_NOZORDER
;
2438 WIN_ReleaseWndPtr(wnd
);
2441 Pos
: /* ------------------------------------------------------------------------ MAIN part */
2443 /* Fill the WINDOWPOS structure */
2446 winpos
.hwndInsertAfter
= hwndInsertAfter
;
2451 winpos
.flags
= flags
;
2453 SWP_DoWinPosChanging( wndPtr
, &winpos
, &newWindowRect
, &newClientRect
);
2455 if((winpos
.flags
& (SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) != SWP_NOZORDER
)
2457 if( wndPtr
->parent
== WIN_GetDesktop() )
2458 hwndInsertAfter
= SWP_DoOwnedPopups( wndPtr
->parent
, wndPtr
,
2459 hwndInsertAfter
, winpos
.flags
);
2460 WIN_ReleaseDesktop();
2463 if(!(wndPtr
->flags
& WIN_NATIVE
) )
2465 if( hwndInsertAfter
== HWND_TOP
)
2466 winpos
.flags
|= ( wndPtr
->parent
->child
== wndPtr
)? SWP_NOZORDER
: 0;
2468 if( hwndInsertAfter
== HWND_BOTTOM
)
2469 winpos
.flags
|= ( wndPtr
->next
)? 0: SWP_NOZORDER
;
2471 if( !(winpos
.flags
& SWP_NOZORDER
) )
2472 if( GetWindow(hwndInsertAfter
, GW_HWNDNEXT
) == wndPtr
->hwndSelf
)
2473 winpos
.flags
|= SWP_NOZORDER
;
2475 if( !(winpos
.flags
& SWP_NOREDRAW
) &&
2476 ((winpos
.flags
& (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_FRAMECHANGED
))
2477 != (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
)) )
2479 /* get a previous visible region for SWP_CopyValidBits() */
2481 visRgn
= DCE_GetVisRgn(hwnd
, DCX_WINDOW
| DCX_CLIPSIBLINGS
, 0, 0);
2485 /* Common operations */
2487 SWP_DoNCCalcSize( wndPtr
, &winpos
, &newWindowRect
, &newClientRect
, flags
);
2489 if(!(winpos
.flags
& SWP_NOZORDER
))
2491 WIN_UnlinkWindow( winpos
.hwnd
);
2492 WIN_LinkWindow( winpos
.hwnd
, hwndInsertAfter
);
2495 /* Reset active DCEs */
2497 if( (((winpos
.flags
& SWP_AGG_NOPOSCHANGE
) != SWP_AGG_NOPOSCHANGE
) &&
2498 wndPtr
->dwStyle
& WS_VISIBLE
) ||
2499 (flags
& (SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) )
2503 UnionRect(&rect
, &newWindowRect
, &wndPtr
->rectWindow
);
2504 DCE_InvalidateDCE(wndPtr
, &rect
);
2507 oldWindowRect
= wndPtr
->rectWindow
;
2508 oldClientRect
= wndPtr
->rectClient
;
2510 if (wndPtr
->flags
& WIN_NATIVE
) /* -------------------------------------------- hosted window */
2512 BOOL bCallDriver
= TRUE
;
2513 HWND tempInsertAfter
= winpos
.hwndInsertAfter
;
2515 winpos
.hwndInsertAfter
= hwndInsertAfter
;
2517 wndPtr
->rectWindow
= newWindowRect
;
2518 wndPtr
->rectClient
= newClientRect
;
2520 if( !(winpos
.flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
| SWP_NOREDRAW
)) )
2522 /* This is the only place where we need to force repainting of the contents
2523 of windows created by the host window system, all other cases go through the
2524 expose event handling */
2526 if( (winpos
.flags
& SWP_FRAMECHANGED
) )
2530 if( (x
= (newWindowRect
.right
- newWindowRect
.left
)) == (oldWindowRect
.right
- oldWindowRect
.left
) &&
2531 (y
= (newWindowRect
.bottom
- newWindowRect
.top
)) == (oldWindowRect
.bottom
- oldWindowRect
.top
) )
2534 wndPtr
->pDriver
->pSetWindowPos(wndPtr
, &winpos
, TRUE
);
2535 winpos
.hwndInsertAfter
= tempInsertAfter
;
2536 bCallDriver
= FALSE
;
2538 if( (oldClientRect
.left
- oldWindowRect
.left
== newClientRect
.left
- newWindowRect
.left
) &&
2539 (oldClientRect
.top
- oldWindowRect
.top
== newClientRect
.top
- newWindowRect
.top
) )
2540 SWP_DoSimpleFrameChanged(wndPtr
, &newClientRect
, &oldClientRect
);
2543 /* client area moved but window extents remained the same, copy valid bits */
2545 visRgn
= CreateRectRgn( 0, 0, x
, y
);
2546 uFlags
= SWP_CopyValidBits(wndPtr
, &visRgn
, &oldWindowRect
, &oldClientRect
, SWP_EX_PAINTSELF
);
2554 if( !(winpos
.flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
| SWP_NOREDRAW
)) )
2556 if( (oldClientRect
.left
- oldWindowRect
.left
== newClientRect
.left
- newWindowRect
.left
) &&
2557 (oldClientRect
.top
- oldWindowRect
.top
== newClientRect
.top
- newWindowRect
.top
) )
2559 if( !(wndPtr
->flags
& WIN_MANAGED
) ) /* force outer frame redraw */
2561 HRGN hrgn
= CreateRectRgn( 0, 0, newWindowRect
.right
- newWindowRect
.left
,
2562 newWindowRect
.bottom
- newWindowRect
.top
);
2563 RECT rcn
= newClientRect
;
2564 RECT rco
= oldClientRect
;
2566 OffsetRect( &rcn
, -newWindowRect
.left
, -newWindowRect
.top
);
2567 OffsetRect( &rco
, -oldWindowRect
.left
, -oldWindowRect
.top
);
2568 IntersectRect( &rcn
, &rcn
, &rco
);
2569 visRgn
= CreateRectRgnIndirect( &rcn
);
2570 CombineRgn( visRgn
, hrgn
, visRgn
, RGN_DIFF
);
2571 DeleteObject( hrgn
);
2572 uFlags
= SWP_EX_PAINTSELF
;
2574 wndPtr
->pDriver
->pSetHostAttr(wndPtr
, HAK_BITGRAVITY
, BGNorthWest
);
2577 wndPtr
->pDriver
->pSetHostAttr(wndPtr
, HAK_BITGRAVITY
, BGForget
);
2579 wndPtr
->pDriver
->pSetWindowPos(wndPtr
, &winpos
, TRUE
);
2580 winpos
.hwndInsertAfter
= tempInsertAfter
;
2583 if( winpos
.flags
& SWP_SHOWWINDOW
)
2587 wndPtr
->dwStyle
|= WS_VISIBLE
;
2589 if (wndPtr
->flags
& WIN_MANAGED
) resync
= TRUE
;
2591 /* focus was set to unmapped window, reset host focus
2592 * since the window is now visible */
2594 focus
= curr
= GetFocus();
2599 WND
*pFocus
= WIN_FindWndPtr( focus
);
2601 pFocus
->pDriver
->pSetFocus(pFocus
);
2602 WIN_ReleaseWndPtr(pFocus
);
2605 curr
= GetParent(curr
);
2609 else /* -------------------------------------------- emulated window */
2611 wndPtr
->rectWindow
= newWindowRect
;
2612 wndPtr
->rectClient
= newClientRect
;
2614 if( oldClientRect
.bottom
- oldClientRect
.top
==
2615 newClientRect
.bottom
- newClientRect
.top
) wvrFlags
&= ~WVR_VREDRAW
;
2617 if( oldClientRect
.right
- oldClientRect
.left
==
2618 newClientRect
.right
- newClientRect
.left
) wvrFlags
&= ~WVR_HREDRAW
;
2620 if( winpos
.flags
& SWP_SHOWWINDOW
)
2622 wndPtr
->dwStyle
|= WS_VISIBLE
;
2623 uFlags
|= SWP_EX_PAINTSELF
;
2626 else if( !(winpos
.flags
& SWP_NOREDRAW
) )
2628 if( winpos
.flags
& SWP_HIDEWINDOW
)
2630 if( visRgn
> 1 ) /* map to parent */
2631 OffsetRgn( visRgn
, oldWindowRect
.left
, oldWindowRect
.top
);
2637 uFlags
|= ((winpos
.flags
& SWP_NOCOPYBITS
) ||
2638 (wvrFlags
>= WVR_HREDRAW
&& wvrFlags
< WVR_VALIDRECTS
)) ? SWP_EX_NOCOPY
: 0;
2640 if( (winpos
.flags
& SWP_AGG_NOPOSCHANGE
) != SWP_AGG_NOPOSCHANGE
)
2641 uFlags
= SWP_CopyValidBits(wndPtr
, &visRgn
, &oldWindowRect
,
2642 &oldClientRect
, uFlags
);
2645 if( winpos
.flags
& SWP_FRAMECHANGED
)
2646 SWP_DoSimpleFrameChanged( wndPtr
, &newClientRect
, &oldClientRect
);
2649 DeleteObject( visRgn
);
2657 if( winpos
.flags
& SWP_HIDEWINDOW
)
2659 wndPtr
->dwStyle
&= ~WS_VISIBLE
;
2661 if (hwnd
== CARET_GetHwnd()) DestroyCaret();
2663 /* FIXME: This will cause the window to be activated irrespective
2664 * of whether it is owned by the same thread. Has to be done
2668 if (winpos
.hwnd
== hwndActive
)
2669 WINPOS_ActivateOtherWindow( wndPtr
);
2672 /* ------------------------------------------------------------------------ FINAL */
2674 /* Activate the window */
2676 if (!(flags
& SWP_NOACTIVATE
))
2677 WINPOS_ChangeActiveWindow( winpos
.hwnd
, FALSE
);
2679 if (wndPtr
->flags
& WIN_NATIVE
)
2680 EVENT_Synchronize(); /* Synchronize with the host window system */
2682 if (!GetCapture() && ((wndPtr
->dwStyle
& WS_VISIBLE
) || (flags
& SWP_HIDEWINDOW
)))
2683 EVENT_DummyMotionNotify(); /* Simulate a mouse event to set the cursor */
2685 wndTemp
= WIN_GetDesktop();
2687 /* repaint invalidated region (if any) */
2691 if( !(winpos
.flags
& SWP_NOREDRAW
) )
2693 if( uFlags
& SWP_EX_PAINTSELF
)
2695 PAINT_RedrawWindow( wndPtr
->hwndSelf
, NULL
, (visRgn
== 1) ? 0 : visRgn
, RDW_ERASE
| RDW_FRAME
|
2696 ((winpos
.flags
& SWP_DEFERERASE
) ? 0 : RDW_ERASENOW
) | RDW_INVALIDATE
|
2697 RDW_ALLCHILDREN
, RDW_EX_XYWINDOW
| RDW_EX_USEHRGN
);
2701 PAINT_RedrawWindow( wndPtr
->parent
->hwndSelf
, NULL
, (visRgn
== 1) ? 0 : visRgn
, RDW_ERASE
|
2702 ((winpos
.flags
& SWP_DEFERERASE
) ? 0 : RDW_ERASENOW
) | RDW_INVALIDATE
|
2703 RDW_ALLCHILDREN
, RDW_EX_USEHRGN
);
2707 DeleteObject( visRgn
);
2710 WIN_ReleaseDesktop();
2712 /* And last, send the WM_WINDOWPOSCHANGED message */
2714 TRACE(win
,"\tstatus flags = %04x\n", winpos
.flags
& SWP_AGG_STATUSFLAGS
);
2717 (((winpos
.flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOPOSCHANGE
) &&
2718 !(winpos
.flags
& SWP_NOSENDCHANGING
)) )
2720 SendMessageA( winpos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
)&winpos
);
2721 if (resync
) EVENT_Synchronize ();
2726 WIN_ReleaseWndPtr(wndPtr
);
2731 /***********************************************************************
2732 * BeginDeferWindowPos16 (USER.259)
2734 HDWP16 WINAPI
BeginDeferWindowPos16( INT16 count
)
2736 return BeginDeferWindowPos( count
);
2740 /***********************************************************************
2741 * BeginDeferWindowPos (USER32.9)
2743 HDWP WINAPI
BeginDeferWindowPos( INT count
)
2748 if (count
<= 0) return 0;
2749 handle
= USER_HEAP_ALLOC( sizeof(DWP
) + (count
-1)*sizeof(WINDOWPOS
) );
2750 if (!handle
) return 0;
2751 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( handle
);
2752 pDWP
->actualCount
= 0;
2753 pDWP
->suggestedCount
= count
;
2755 pDWP
->wMagic
= DWP_MAGIC
;
2756 pDWP
->hwndParent
= 0;
2761 /***********************************************************************
2762 * DeferWindowPos16 (USER.260)
2764 HDWP16 WINAPI
DeferWindowPos16( HDWP16 hdwp
, HWND16 hwnd
, HWND16 hwndAfter
,
2765 INT16 x
, INT16 y
, INT16 cx
, INT16 cy
,
2768 return DeferWindowPos( hdwp
, hwnd
, (INT
)(INT16
)hwndAfter
,
2769 x
, y
, cx
, cy
, flags
);
2773 /***********************************************************************
2774 * DeferWindowPos (USER32.128)
2776 HDWP WINAPI
DeferWindowPos( HDWP hdwp
, HWND hwnd
, HWND hwndAfter
,
2777 INT x
, INT y
, INT cx
, INT cy
,
2782 HDWP newhdwp
= hdwp
,retvalue
;
2786 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
2787 if (!pDWP
) return 0;
2788 if (hwnd
== GetDesktopWindow()) return 0;
2790 if (!(pWnd
=WIN_FindWndPtr( hwnd
))) {
2791 USER_HEAP_FREE( hdwp
);
2795 /* Numega Bounds Checker Demo dislikes the following code.
2796 In fact, I've not been able to find any "same parent" requirement in any docu
2800 /* All the windows of a DeferWindowPos() must have the same parent */
2801 parent
= pWnd
->parent
->hwndSelf
;
2802 if (pDWP
->actualCount
== 0) pDWP
->hwndParent
= parent
;
2803 else if (parent
!= pDWP
->hwndParent
)
2805 USER_HEAP_FREE( hdwp
);
2811 for (i
= 0; i
< pDWP
->actualCount
; i
++)
2813 if (pDWP
->winPos
[i
].hwnd
== hwnd
)
2815 /* Merge with the other changes */
2816 if (!(flags
& SWP_NOZORDER
))
2818 pDWP
->winPos
[i
].hwndInsertAfter
= hwndAfter
;
2820 if (!(flags
& SWP_NOMOVE
))
2822 pDWP
->winPos
[i
].x
= x
;
2823 pDWP
->winPos
[i
].y
= y
;
2825 if (!(flags
& SWP_NOSIZE
))
2827 pDWP
->winPos
[i
].cx
= cx
;
2828 pDWP
->winPos
[i
].cy
= cy
;
2830 pDWP
->winPos
[i
].flags
&= flags
| ~(SWP_NOSIZE
| SWP_NOMOVE
|
2831 SWP_NOZORDER
| SWP_NOREDRAW
|
2832 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
2834 pDWP
->winPos
[i
].flags
|= flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
|
2840 if (pDWP
->actualCount
>= pDWP
->suggestedCount
)
2842 newhdwp
= USER_HEAP_REALLOC( hdwp
,
2843 sizeof(DWP
) + pDWP
->suggestedCount
*sizeof(WINDOWPOS
) );
2849 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( newhdwp
);
2850 pDWP
->suggestedCount
++;
2852 pDWP
->winPos
[pDWP
->actualCount
].hwnd
= hwnd
;
2853 pDWP
->winPos
[pDWP
->actualCount
].hwndInsertAfter
= hwndAfter
;
2854 pDWP
->winPos
[pDWP
->actualCount
].x
= x
;
2855 pDWP
->winPos
[pDWP
->actualCount
].y
= y
;
2856 pDWP
->winPos
[pDWP
->actualCount
].cx
= cx
;
2857 pDWP
->winPos
[pDWP
->actualCount
].cy
= cy
;
2858 pDWP
->winPos
[pDWP
->actualCount
].flags
= flags
;
2859 pDWP
->actualCount
++;
2862 WIN_ReleaseWndPtr(pWnd
);
2867 /***********************************************************************
2868 * EndDeferWindowPos16 (USER.261)
2870 BOOL16 WINAPI
EndDeferWindowPos16( HDWP16 hdwp
)
2872 return EndDeferWindowPos( hdwp
);
2876 /***********************************************************************
2877 * EndDeferWindowPos (USER32.173)
2879 BOOL WINAPI
EndDeferWindowPos( HDWP hdwp
)
2886 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
2887 if (!pDWP
) return FALSE
;
2888 for (i
= 0, winpos
= pDWP
->winPos
; i
< pDWP
->actualCount
; i
++, winpos
++)
2890 if (!(res
= SetWindowPos( winpos
->hwnd
, winpos
->hwndInsertAfter
,
2891 winpos
->x
, winpos
->y
, winpos
->cx
,
2892 winpos
->cy
, winpos
->flags
))) break;
2894 USER_HEAP_FREE( hdwp
);
2899 /***********************************************************************
2900 * TileChildWindows (USER.199)
2902 void WINAPI
TileChildWindows16( HWND16 parent
, WORD action
)
2904 FIXME(win
, "(%04x, %d): stub\n", parent
, action
);
2907 /***********************************************************************
2908 * CascageChildWindows (USER.198)
2910 void WINAPI
CascadeChildWindows16( HWND16 parent
, WORD action
)
2912 FIXME(win
, "(%04x, %d): stub\n", parent
, action
);
2914 /***********************************************************************
2915 * GetProgmanWindow [USER32.289]
2917 HRESULT WINAPI
GetProgmanWindow ( )
2918 { FIXME(win
,"stub\n");
2921 /***********************************************************************
2922 * GetTaskmanWindow [USER32.304]
2924 HRESULT WINAPI
GetTaskmanWindow ( )
2925 { FIXME(win
,"stub\n");
2928 /***********************************************************************
2929 * SetProgmanWindow [USER32.522]
2931 HRESULT WINAPI
SetProgmanWindow ( DWORD x
)
2932 { FIXME(win
,"0x%08lx stub\n",x
);
2935 /***********************************************************************
2936 * SetShellWindowEx [USER32.531]
2938 HRESULT WINAPI
SetShellWindowEx ( DWORD x
, DWORD y
)
2939 { FIXME(win
,"0x%08lx 0x%08lx stub\n",x
,y
);
2942 /***********************************************************************
2943 * SetTaskmanWindow [USER32.537]
2945 HRESULT WINAPI
SetTaskmanWindow ( DWORD x
)
2946 { FIXME(win
,"0x%08lx stub\n",x
);