2 * Window position related functions.
4 * Copyright 1993, 1994, 1995 Alexandre Julliard
5 * 1995, 1996, 1999 Alex Korobka
9 #include "sysmetrics.h"
22 #include "nonclient.h"
27 #define HAS_DLGFRAME(style,exStyle) \
28 (((exStyle) & WS_EX_DLGMODALFRAME) || \
29 (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
31 #define HAS_THICKFRAME(style) \
32 (((style) & WS_THICKFRAME) && \
33 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
35 #define SWP_AGG_NOGEOMETRYCHANGE \
36 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
37 #define SWP_AGG_NOPOSCHANGE \
38 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
39 #define SWP_AGG_STATUSFLAGS \
40 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
42 #define EMPTYPOINT(pt) ((*(LONG*)&(pt)) == -1)
44 #define PLACE_MIN 0x0001
45 #define PLACE_MAX 0x0002
46 #define PLACE_RECT 0x0004
48 #define SWP_EX_NOCOPY 0x0001
49 #define SWP_EX_PAINTSELF 0x0002
51 #define MINMAX_NOSWP 0x00010000
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 UINT
WINPOS_MinMaximize( WND
* wndPtr
, UINT16 cmd
, LPRECT16 lpRect
)
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 if( wndPtr
->flags
& WIN_NATIVE
)
1174 if( wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, TRUE
) )
1175 swpFlags
|= MINMAX_NOSWP
;
1177 lpPos
->ptIconPos
= WINPOS_FindIconPos( wndPtr
, lpPos
->ptIconPos
);
1179 SetRect16( lpRect
, lpPos
->ptIconPos
.x
, lpPos
->ptIconPos
.y
,
1180 SYSMETRICS_CXICON
, SYSMETRICS_CYICON
);
1181 swpFlags
|= SWP_NOCOPYBITS
;
1185 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &pt
);
1186 WINPOS_GetMinMaxInfo( wndPtr
, &size
, &pt
, NULL
, NULL
);
1187 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1189 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1191 if( wndPtr
->flags
& WIN_NATIVE
)
1192 if( wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, FALSE
) )
1193 swpFlags
|= MINMAX_NOSWP
;
1195 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
1196 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
1198 wndPtr
->dwStyle
|= WS_MAXIMIZE
;
1200 SetRect16( lpRect
, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
,
1205 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1207 if( wndPtr
->flags
& WIN_NATIVE
)
1208 if( wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, FALSE
) )
1209 swpFlags
|= MINMAX_NOSWP
;
1211 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
1212 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
1214 if( wndPtr
->flags
& WIN_RESTORE_MAX
)
1216 /* Restore to maximized position */
1217 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &pt
);
1218 WINPOS_GetMinMaxInfo( wndPtr
, &size
, &pt
, NULL
, NULL
);
1219 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1220 wndPtr
->dwStyle
|= WS_MAXIMIZE
;
1221 SetRect16( lpRect
, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
, size
.x
, size
.y
);
1226 if( !(wndPtr
->dwStyle
& WS_MAXIMIZE
) ) return (UINT16
)(-1);
1227 else wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
1229 /* Restore to normal position */
1231 *lpRect
= lpPos
->rectNormal
;
1232 lpRect
->right
-= lpRect
->left
;
1233 lpRect
->bottom
-= lpRect
->top
;
1237 } else swpFlags
|= SWP_NOSIZE
| SWP_NOMOVE
;
1241 /***********************************************************************
1242 * ShowWindowAsync (USER32.535)
1244 * doesn't wait; returns immediately.
1245 * used by threads to toggle windows in other (possibly hanging) threads
1247 BOOL WINAPI
ShowWindowAsync( HWND hwnd
, INT cmd
)
1249 /* FIXME: does ShowWindow() return immediately ? */
1250 return ShowWindow(hwnd
, cmd
);
1254 /***********************************************************************
1255 * ShowWindow16 (USER.42)
1257 BOOL16 WINAPI
ShowWindow16( HWND16 hwnd
, INT16 cmd
)
1259 return ShowWindow(hwnd
,cmd
);
1263 /***********************************************************************
1264 * ShowWindow (USER32.534)
1266 BOOL WINAPI
ShowWindow( HWND hwnd
, INT cmd
)
1268 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
1269 BOOL wasVisible
, showFlag
;
1270 RECT16 newPos
= {0, 0, 0, 0};
1273 if (!wndPtr
) return FALSE
;
1275 TRACE(win
,"hwnd=%04x, cmd=%d\n", hwnd
, cmd
);
1277 wasVisible
= (wndPtr
->dwStyle
& WS_VISIBLE
) != 0;
1282 if (!wasVisible
) goto END
;;
1283 swp
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
|
1284 SWP_NOACTIVATE
| SWP_NOZORDER
;
1285 if ((hwnd
== GetFocus()) || IsChild( hwnd
, GetFocus()))
1287 /* Revert focus to parent */
1288 SetFocus( GetParent(hwnd
) );
1292 case SW_SHOWMINNOACTIVE
:
1293 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1295 case SW_SHOWMINIMIZED
:
1296 swp
|= SWP_SHOWWINDOW
;
1299 swp
|= SWP_FRAMECHANGED
;
1300 if( !(wndPtr
->dwStyle
& WS_MINIMIZE
) )
1301 swp
|= WINPOS_MinMaximize( wndPtr
, SW_MINIMIZE
, &newPos
);
1302 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1305 case SW_SHOWMAXIMIZED
: /* same as SW_MAXIMIZE */
1306 swp
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
1307 if( !(wndPtr
->dwStyle
& WS_MAXIMIZE
) )
1308 swp
|= WINPOS_MinMaximize( wndPtr
, SW_MAXIMIZE
, &newPos
);
1309 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1313 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1316 swp
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
1319 case SW_SHOWNOACTIVATE
:
1320 swp
|= SWP_NOZORDER
;
1321 if (GetActiveWindow()) swp
|= SWP_NOACTIVATE
;
1323 case SW_SHOWNORMAL
: /* same as SW_NORMAL: */
1324 case SW_SHOWDEFAULT
: /* FIXME: should have its own handler */
1326 swp
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
1328 if( wndPtr
->dwStyle
& (WS_MINIMIZE
| WS_MAXIMIZE
) )
1329 swp
|= WINPOS_MinMaximize( wndPtr
, SW_RESTORE
, &newPos
);
1330 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1334 showFlag
= (cmd
!= SW_HIDE
);
1335 if (showFlag
!= wasVisible
)
1337 SendMessageA( hwnd
, WM_SHOWWINDOW
, showFlag
, 0 );
1338 if (!IsWindow( hwnd
)) goto END
;
1341 if ((wndPtr
->dwStyle
& WS_CHILD
) &&
1342 !IsWindowVisible( wndPtr
->parent
->hwndSelf
) &&
1343 (swp
& (SWP_NOSIZE
| SWP_NOMOVE
)) == (SWP_NOSIZE
| SWP_NOMOVE
) )
1345 /* Don't call SetWindowPos() on invisible child windows */
1346 if (cmd
== SW_HIDE
) wndPtr
->dwStyle
&= ~WS_VISIBLE
;
1347 else wndPtr
->dwStyle
|= WS_VISIBLE
;
1351 /* We can't activate a child window */
1352 if (wndPtr
->dwStyle
& WS_CHILD
) swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1353 if (!(swp
& MINMAX_NOSWP
))
1354 SetWindowPos( hwnd
, HWND_TOP
, newPos
.left
, newPos
.top
,
1355 newPos
.right
, newPos
.bottom
, LOWORD(swp
) );
1356 if (!IsWindow( hwnd
)) goto END
;
1357 else if( wndPtr
->dwStyle
& WS_MINIMIZE
) WINPOS_ShowIconTitle( wndPtr
, TRUE
);
1360 if (wndPtr
->flags
& WIN_NEED_SIZE
)
1362 /* should happen only in CreateWindowEx() */
1363 int wParam
= SIZE_RESTORED
;
1365 wndPtr
->flags
&= ~WIN_NEED_SIZE
;
1366 if (wndPtr
->dwStyle
& WS_MAXIMIZE
) wParam
= SIZE_MAXIMIZED
;
1367 else if (wndPtr
->dwStyle
& WS_MINIMIZE
) wParam
= SIZE_MINIMIZED
;
1368 SendMessageA( hwnd
, WM_SIZE
, wParam
,
1369 MAKELONG(wndPtr
->rectClient
.right
-wndPtr
->rectClient
.left
,
1370 wndPtr
->rectClient
.bottom
-wndPtr
->rectClient
.top
));
1371 SendMessageA( hwnd
, WM_MOVE
, 0,
1372 MAKELONG(wndPtr
->rectClient
.left
, wndPtr
->rectClient
.top
) );
1376 WIN_ReleaseWndPtr(wndPtr
);
1381 /***********************************************************************
1382 * GetInternalWindowPos16 (USER.460)
1384 UINT16 WINAPI
GetInternalWindowPos16( HWND16 hwnd
, LPRECT16 rectWnd
,
1387 WINDOWPLACEMENT16 wndpl
;
1388 if (GetWindowPlacement16( hwnd
, &wndpl
))
1390 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
1391 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
1392 return wndpl
.showCmd
;
1398 /***********************************************************************
1399 * GetInternalWindowPos (USER32.245)
1401 UINT WINAPI
GetInternalWindowPos( HWND hwnd
, LPRECT rectWnd
,
1404 WINDOWPLACEMENT wndpl
;
1405 if (GetWindowPlacement( hwnd
, &wndpl
))
1407 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
1408 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
1409 return wndpl
.showCmd
;
1414 /***********************************************************************
1415 * GetWindowPlacement16 (USER.370)
1417 BOOL16 WINAPI
GetWindowPlacement16( HWND16 hwnd
, WINDOWPLACEMENT16
*wndpl
)
1419 WND
*pWnd
= WIN_FindWndPtr( hwnd
);
1420 LPINTERNALPOS lpPos
;
1422 if(!pWnd
) return FALSE
;
1424 lpPos
= (LPINTERNALPOS
)WINPOS_InitInternalPos( pWnd
,
1425 *(LPPOINT
)&pWnd
->rectWindow
.left
, &pWnd
->rectWindow
);
1426 wndpl
->length
= sizeof(*wndpl
);
1427 if( pWnd
->dwStyle
& WS_MINIMIZE
)
1428 wndpl
->showCmd
= SW_SHOWMINIMIZED
;
1430 wndpl
->showCmd
= ( pWnd
->dwStyle
& WS_MAXIMIZE
)
1431 ? SW_SHOWMAXIMIZED
: SW_SHOWNORMAL
;
1432 if( pWnd
->flags
& WIN_RESTORE_MAX
)
1433 wndpl
->flags
= WPF_RESTORETOMAXIMIZED
;
1436 wndpl
->ptMinPosition
= lpPos
->ptIconPos
;
1437 wndpl
->ptMaxPosition
= lpPos
->ptMaxPos
;
1438 wndpl
->rcNormalPosition
= lpPos
->rectNormal
;
1440 WIN_ReleaseWndPtr(pWnd
);
1445 /***********************************************************************
1446 * GetWindowPlacement (USER32.307)
1449 * Fails if wndpl->length of Win95 (!) apps is invalid.
1451 BOOL WINAPI
GetWindowPlacement( HWND hwnd
, WINDOWPLACEMENT
*pwpl32
)
1455 WINDOWPLACEMENT16 wpl
;
1456 wpl
.length
= sizeof(wpl
);
1457 if( GetWindowPlacement16( hwnd
, &wpl
) )
1459 pwpl32
->length
= sizeof(*pwpl32
);
1460 pwpl32
->flags
= wpl
.flags
;
1461 pwpl32
->showCmd
= wpl
.showCmd
;
1462 CONV_POINT16TO32( &wpl
.ptMinPosition
, &pwpl32
->ptMinPosition
);
1463 CONV_POINT16TO32( &wpl
.ptMaxPosition
, &pwpl32
->ptMaxPosition
);
1464 CONV_RECT16TO32( &wpl
.rcNormalPosition
, &pwpl32
->rcNormalPosition
);
1472 /***********************************************************************
1473 * WINPOS_SetPlacement
1475 static BOOL
WINPOS_SetPlacement( HWND hwnd
, const WINDOWPLACEMENT16
*wndpl
,
1478 WND
*pWnd
= WIN_FindWndPtr( hwnd
);
1481 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)WINPOS_InitInternalPos( pWnd
,
1482 *(LPPOINT
)&pWnd
->rectWindow
.left
, &pWnd
->rectWindow
);
1484 if( flags
& PLACE_MIN
) lpPos
->ptIconPos
= wndpl
->ptMinPosition
;
1485 if( flags
& PLACE_MAX
) lpPos
->ptMaxPos
= wndpl
->ptMaxPosition
;
1486 if( flags
& PLACE_RECT
) lpPos
->rectNormal
= wndpl
->rcNormalPosition
;
1488 if( pWnd
->dwStyle
& WS_MINIMIZE
)
1490 WINPOS_ShowIconTitle( pWnd
, FALSE
);
1491 if( wndpl
->flags
& WPF_SETMINPOSITION
&& !EMPTYPOINT(lpPos
->ptIconPos
))
1492 SetWindowPos( hwnd
, 0, lpPos
->ptIconPos
.x
, lpPos
->ptIconPos
.y
,
1493 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1495 else if( pWnd
->dwStyle
& WS_MAXIMIZE
)
1497 if( !EMPTYPOINT(lpPos
->ptMaxPos
) )
1498 SetWindowPos( hwnd
, 0, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
,
1499 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1501 else if( flags
& PLACE_RECT
)
1502 SetWindowPos( hwnd
, 0, lpPos
->rectNormal
.left
, lpPos
->rectNormal
.top
,
1503 lpPos
->rectNormal
.right
- lpPos
->rectNormal
.left
,
1504 lpPos
->rectNormal
.bottom
- lpPos
->rectNormal
.top
,
1505 SWP_NOZORDER
| SWP_NOACTIVATE
);
1507 ShowWindow( hwnd
, wndpl
->showCmd
);
1508 if( IsWindow(hwnd
) && pWnd
->dwStyle
& WS_MINIMIZE
)
1510 if( pWnd
->dwStyle
& WS_VISIBLE
) WINPOS_ShowIconTitle( pWnd
, TRUE
);
1512 /* SDK: ...valid only the next time... */
1513 if( wndpl
->flags
& WPF_RESTORETOMAXIMIZED
) pWnd
->flags
|= WIN_RESTORE_MAX
;
1515 WIN_ReleaseWndPtr(pWnd
);
1522 /***********************************************************************
1523 * SetWindowPlacement16 (USER.371)
1525 BOOL16 WINAPI
SetWindowPlacement16(HWND16 hwnd
, const WINDOWPLACEMENT16
*wndpl
)
1527 return WINPOS_SetPlacement( hwnd
, wndpl
,
1528 PLACE_MIN
| PLACE_MAX
| PLACE_RECT
);
1531 /***********************************************************************
1532 * SetWindowPlacement (USER32.519)
1535 * Fails if wndpl->length of Win95 (!) apps is invalid.
1537 BOOL WINAPI
SetWindowPlacement( HWND hwnd
, const WINDOWPLACEMENT
*pwpl32
)
1541 WINDOWPLACEMENT16 wpl
= { sizeof(WINDOWPLACEMENT16
),
1542 pwpl32
->flags
, pwpl32
->showCmd
, { pwpl32
->ptMinPosition
.x
,
1543 pwpl32
->ptMinPosition
.y
}, { pwpl32
->ptMaxPosition
.x
,
1544 pwpl32
->ptMaxPosition
.y
}, { pwpl32
->rcNormalPosition
.left
,
1545 pwpl32
->rcNormalPosition
.top
, pwpl32
->rcNormalPosition
.right
,
1546 pwpl32
->rcNormalPosition
.bottom
} };
1548 return WINPOS_SetPlacement( hwnd
, &wpl
, PLACE_MIN
| PLACE_MAX
| PLACE_RECT
);
1554 /***********************************************************************
1555 * SetInternalWindowPos16 (USER.461)
1557 void WINAPI
SetInternalWindowPos16( HWND16 hwnd
, UINT16 showCmd
,
1558 LPRECT16 rect
, LPPOINT16 pt
)
1560 if( IsWindow16(hwnd
) )
1562 WINDOWPLACEMENT16 wndpl
;
1565 wndpl
.length
= sizeof(wndpl
);
1566 wndpl
.showCmd
= showCmd
;
1567 wndpl
.flags
= flags
= 0;
1572 wndpl
.flags
|= WPF_SETMINPOSITION
;
1573 wndpl
.ptMinPosition
= *pt
;
1577 flags
|= PLACE_RECT
;
1578 wndpl
.rcNormalPosition
= *rect
;
1580 WINPOS_SetPlacement( hwnd
, &wndpl
, flags
);
1585 /***********************************************************************
1586 * SetInternalWindowPos (USER32.483)
1588 void WINAPI
SetInternalWindowPos( HWND hwnd
, UINT showCmd
,
1589 LPRECT rect
, LPPOINT pt
)
1591 if( IsWindow(hwnd
) )
1593 WINDOWPLACEMENT16 wndpl
;
1596 wndpl
.length
= sizeof(wndpl
);
1597 wndpl
.showCmd
= showCmd
;
1598 wndpl
.flags
= flags
= 0;
1603 wndpl
.flags
|= WPF_SETMINPOSITION
;
1604 CONV_POINT32TO16( pt
, &wndpl
.ptMinPosition
);
1608 flags
|= PLACE_RECT
;
1609 CONV_RECT32TO16( rect
, &wndpl
.rcNormalPosition
);
1611 WINPOS_SetPlacement( hwnd
, &wndpl
, flags
);
1615 /*******************************************************************
1616 * WINPOS_SetActiveWindow
1618 * SetActiveWindow() back-end. This is the only function that
1619 * can assign active status to a window. It must be called only
1620 * for the top level windows.
1622 BOOL
WINPOS_SetActiveWindow( HWND hWnd
, BOOL fMouse
, BOOL fChangeFocus
)
1624 CBTACTIVATESTRUCT16
* cbtStruct
;
1625 WND
* wndPtr
=0, *wndTemp
;
1626 HQUEUE16 hOldActiveQueue
, hNewActiveQueue
;
1627 MESSAGEQUEUE
*pOldActiveQueue
= 0, *pNewActiveQueue
= 0;
1629 HWND hwndActive
= 0;
1632 /* Get current active window from the active queue */
1635 pOldActiveQueue
= QUEUE_Lock( hActiveQueue
);
1636 if ( pOldActiveQueue
)
1637 hwndActive
= PERQDATA_GetActiveWnd( pOldActiveQueue
->pQData
);
1640 /* paranoid checks */
1641 if( hWnd
== GetDesktopWindow() || (bRet
= (hWnd
== hwndActive
)) )
1644 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1647 wndPtr
= WIN_FindWndPtr(hWnd
);
1648 hOldActiveQueue
= hActiveQueue
;
1650 if( (wndTemp
= WIN_FindWndPtr(hwndActive
)) )
1652 wIconized
= HIWORD(wndTemp
->dwStyle
& WS_MINIMIZE
);
1653 WIN_ReleaseWndPtr(wndTemp
);
1656 TRACE(win
,"no current active window.\n");
1658 /* call CBT hook chain */
1659 if ((cbtStruct
= SEGPTR_NEW(CBTACTIVATESTRUCT16
)))
1661 cbtStruct
->fMouse
= fMouse
;
1662 cbtStruct
->hWndActive
= hwndActive
;
1663 bRet
= (BOOL
)HOOK_CallHooks16( WH_CBT
, HCBT_ACTIVATE
, (WPARAM16
)hWnd
,
1664 (LPARAM
)SEGPTR_GET(cbtStruct
) );
1665 SEGPTR_FREE(cbtStruct
);
1666 if (bRet
) goto CLEANUP_END
;
1669 /* set prev active wnd to current active wnd and send notification */
1670 if ((hwndPrevActive
= hwndActive
) && IsWindow(hwndPrevActive
))
1672 MESSAGEQUEUE
*pTempActiveQueue
= 0;
1674 if (!SendMessageA( hwndPrevActive
, WM_NCACTIVATE
, FALSE
, 0 ))
1676 if (GetSysModalWindow16() != hWnd
)
1678 /* disregard refusal if hWnd is sysmodal */
1681 SendMessageA( hwndPrevActive
, WM_ACTIVATE
,
1682 MAKEWPARAM( WA_INACTIVE
, wIconized
),
1685 /* check if something happened during message processing
1686 * (global active queue may have changed)
1688 pTempActiveQueue
= QUEUE_Lock( hActiveQueue
);
1689 if(!pTempActiveQueue
)
1692 hwndActive
= PERQDATA_GetActiveWnd( pTempActiveQueue
->pQData
);
1693 QUEUE_Unlock( pTempActiveQueue
);
1694 if( hwndPrevActive
!= hwndActive
)
1698 /* Set new active window in the message queue */
1702 pNewActiveQueue
= QUEUE_Lock( wndPtr
->hmemTaskQ
);
1703 if ( pNewActiveQueue
)
1704 PERQDATA_SetActiveWnd( pNewActiveQueue
->pQData
, hwndActive
);
1706 else /* have to do this or MDI frame activation goes to hell */
1707 if( pOldActiveQueue
)
1708 PERQDATA_SetActiveWnd( pOldActiveQueue
->pQData
, 0 );
1710 /* send palette messages */
1711 if (hWnd
&& SendMessage16( hWnd
, WM_QUERYNEWPALETTE
, 0, 0L))
1712 SendMessage16((HWND16
)-1, WM_PALETTEISCHANGING
, (WPARAM16
)hWnd
, 0L );
1714 /* if prev wnd is minimized redraw icon title */
1715 if( IsIconic( hwndPrevActive
) ) WINPOS_RedrawIconTitle(hwndPrevActive
);
1717 /* managed windows will get ConfigureNotify event */
1718 if (wndPtr
&& !(wndPtr
->dwStyle
& WS_CHILD
) && !(wndPtr
->flags
& WIN_MANAGED
))
1720 /* check Z-order and bring hWnd to the top */
1721 for (wndTemp
= WIN_LockWndPtr(WIN_GetDesktop()->child
); wndTemp
; WIN_UpdateWndPtr(&wndTemp
,wndTemp
->next
))
1723 if (wndTemp
->dwStyle
& WS_VISIBLE
) break;
1725 WIN_ReleaseDesktop();
1726 WIN_ReleaseWndPtr(wndTemp
);
1728 if( wndTemp
!= wndPtr
)
1729 SetWindowPos(hWnd
, HWND_TOP
, 0,0,0,0,
1730 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
1731 if (!IsWindow(hWnd
))
1735 /* Get a handle to the new active queue */
1736 hNewActiveQueue
= wndPtr
? wndPtr
->hmemTaskQ
: 0;
1738 /* send WM_ACTIVATEAPP if necessary */
1739 if (hOldActiveQueue
!= hNewActiveQueue
)
1741 WND
**list
, **ppWnd
;
1742 WND
*pDesktop
= WIN_GetDesktop();
1744 if ((list
= WIN_BuildWinArray( pDesktop
, 0, NULL
)))
1746 for (ppWnd
= list
; *ppWnd
; ppWnd
++)
1748 if (!IsWindow( (*ppWnd
)->hwndSelf
)) continue;
1750 if ((*ppWnd
)->hmemTaskQ
== hOldActiveQueue
)
1751 SendMessage16( (*ppWnd
)->hwndSelf
, WM_ACTIVATEAPP
,
1752 0, QUEUE_GetQueueTask(hNewActiveQueue
) );
1754 WIN_ReleaseWinArray(list
);
1757 hActiveQueue
= hNewActiveQueue
;
1759 if ((list
= WIN_BuildWinArray(pDesktop
, 0, NULL
)))
1761 for (ppWnd
= list
; *ppWnd
; ppWnd
++)
1763 if (!IsWindow( (*ppWnd
)->hwndSelf
)) continue;
1765 if ((*ppWnd
)->hmemTaskQ
== hNewActiveQueue
)
1766 SendMessage16( (*ppWnd
)->hwndSelf
, WM_ACTIVATEAPP
,
1767 1, QUEUE_GetQueueTask( hOldActiveQueue
) );
1769 WIN_ReleaseWinArray(list
);
1771 WIN_ReleaseDesktop();
1773 if (!IsWindow(hWnd
)) goto CLEANUP
;
1778 /* walk up to the first unowned window */
1779 wndTemp
= WIN_LockWndPtr(wndPtr
);
1780 while (wndTemp
->owner
)
1782 WIN_UpdateWndPtr(&wndTemp
,wndTemp
->owner
);
1784 /* and set last active owned popup */
1785 wndTemp
->hwndLastActive
= hWnd
;
1787 wIconized
= HIWORD(wndTemp
->dwStyle
& WS_MINIMIZE
);
1788 WIN_ReleaseWndPtr(wndTemp
);
1789 SendMessageA( hWnd
, WM_NCACTIVATE
, TRUE
, 0 );
1790 SendMessageA( hWnd
, WM_ACTIVATE
,
1791 MAKEWPARAM( (fMouse
) ? WA_CLICKACTIVE
: WA_ACTIVE
, wIconized
),
1792 (LPARAM
)hwndPrevActive
);
1793 if( !IsWindow(hWnd
) ) goto CLEANUP
;
1796 /* change focus if possible */
1797 if( fChangeFocus
&& GetFocus() )
1798 if( WIN_GetTopParent(GetFocus()) != hwndActive
)
1799 FOCUS_SwitchFocus( pNewActiveQueue
, GetFocus(),
1800 (wndPtr
&& (wndPtr
->dwStyle
& WS_MINIMIZE
))?
1805 if( !hwndPrevActive
&& wndPtr
)
1806 (*wndPtr
->pDriver
->pForceWindowRaise
)(wndPtr
);
1808 /* if active wnd is minimized redraw icon title */
1809 if( IsIconic(hwndActive
) ) WINPOS_RedrawIconTitle(hwndActive
);
1811 bRet
= (hWnd
== hwndActive
); /* Success? */
1813 CLEANUP
: /* Unlock the message queues before returning */
1815 if ( pNewActiveQueue
)
1816 QUEUE_Unlock( pNewActiveQueue
);
1820 if ( pOldActiveQueue
)
1821 QUEUE_Unlock( pOldActiveQueue
);
1823 WIN_ReleaseWndPtr(wndPtr
);
1827 /*******************************************************************
1828 * WINPOS_ActivateOtherWindow
1830 * Activates window other than pWnd.
1832 BOOL
WINPOS_ActivateOtherWindow(WND
* pWnd
)
1836 HWND hwndActive
= 0;
1838 /* Get current active window from the active queue */
1841 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
1844 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
1845 QUEUE_Unlock( pActiveQueue
);
1849 if( pWnd
->hwndSelf
== hwndPrevActive
)
1852 if( hwndActive
!= pWnd
->hwndSelf
&&
1853 ( hwndActive
|| QUEUE_IsExitingQueue(pWnd
->hmemTaskQ
)) )
1856 if( !(pWnd
->dwStyle
& WS_POPUP
) || !(pWnd
->owner
) ||
1857 !WINPOS_CanActivate((pWndTo
= WIN_GetTopParentPtr(pWnd
->owner
))) )
1859 WND
* pWndPtr
= WIN_GetTopParentPtr(pWnd
);
1861 pWndTo
= WIN_FindWndPtr(hwndPrevActive
);
1863 while( !WINPOS_CanActivate(pWndTo
) )
1865 /* by now owned windows should've been taken care of */
1866 WIN_UpdateWndPtr(&pWndTo
,pWndPtr
->next
);
1867 WIN_UpdateWndPtr(&pWndPtr
,pWndTo
);
1868 if( !pWndTo
) break;
1870 WIN_ReleaseWndPtr(pWndPtr
);
1873 bRet
= WINPOS_SetActiveWindow( pWndTo
? pWndTo
->hwndSelf
: 0, FALSE
, TRUE
);
1875 /* switch desktop queue to current active */
1878 WIN_GetDesktop()->hmemTaskQ
= pWndTo
->hmemTaskQ
;
1879 WIN_ReleaseWndPtr(pWndTo
);
1880 WIN_ReleaseDesktop();
1887 /*******************************************************************
1888 * WINPOS_ChangeActiveWindow
1891 BOOL
WINPOS_ChangeActiveWindow( HWND hWnd
, BOOL mouseMsg
)
1893 WND
*wndPtr
, *wndTemp
;
1895 HWND hwndActive
= 0;
1897 /* Get current active window from the active queue */
1900 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
1903 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
1904 QUEUE_Unlock( pActiveQueue
);
1909 return WINPOS_SetActiveWindow( 0, mouseMsg
, TRUE
);
1911 wndPtr
= WIN_FindWndPtr(hWnd
);
1912 if( !wndPtr
) return FALSE
;
1914 /* child windows get WM_CHILDACTIVATE message */
1915 if( (wndPtr
->dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1917 retvalue
= SendMessageA(hWnd
, WM_CHILDACTIVATE
, 0, 0L);
1921 if( hWnd
== hwndActive
)
1927 if( !WINPOS_SetActiveWindow(hWnd
,mouseMsg
,TRUE
) )
1933 /* switch desktop queue to current active */
1934 wndTemp
= WIN_GetDesktop();
1935 if( wndPtr
->parent
== wndTemp
)
1936 wndTemp
->hmemTaskQ
= wndPtr
->hmemTaskQ
;
1937 WIN_ReleaseDesktop();
1941 WIN_ReleaseWndPtr(wndPtr
);
1946 /***********************************************************************
1947 * WINPOS_SendNCCalcSize
1949 * Send a WM_NCCALCSIZE message to a window.
1950 * All parameters are read-only except newClientRect.
1951 * oldWindowRect, oldClientRect and winpos must be non-NULL only
1952 * when calcValidRect is TRUE.
1954 LONG
WINPOS_SendNCCalcSize( HWND hwnd
, BOOL calcValidRect
,
1955 RECT
*newWindowRect
, RECT
*oldWindowRect
,
1956 RECT
*oldClientRect
, WINDOWPOS
*winpos
,
1957 RECT
*newClientRect
)
1959 NCCALCSIZE_PARAMS params
;
1960 WINDOWPOS winposCopy
;
1963 params
.rgrc
[0] = *newWindowRect
;
1966 winposCopy
= *winpos
;
1967 params
.rgrc
[1] = *oldWindowRect
;
1968 params
.rgrc
[2] = *oldClientRect
;
1969 params
.lppos
= &winposCopy
;
1971 result
= SendMessageA( hwnd
, WM_NCCALCSIZE
, calcValidRect
,
1973 TRACE(win
, "%d,%d-%d,%d\n",
1974 params
.rgrc
[0].left
, params
.rgrc
[0].top
,
1975 params
.rgrc
[0].right
, params
.rgrc
[0].bottom
);
1976 *newClientRect
= params
.rgrc
[0];
1981 /***********************************************************************
1982 * WINPOS_HandleWindowPosChanging16
1984 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
1986 LONG
WINPOS_HandleWindowPosChanging16( WND
*wndPtr
, WINDOWPOS16
*winpos
)
1988 POINT maxSize
, minTrack
;
1989 if (winpos
->flags
& SWP_NOSIZE
) return 0;
1990 if ((wndPtr
->dwStyle
& WS_THICKFRAME
) ||
1991 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) == 0))
1993 WINPOS_GetMinMaxInfo( wndPtr
, &maxSize
, NULL
, &minTrack
, NULL
);
1994 if (maxSize
.x
< winpos
->cx
) winpos
->cx
= maxSize
.x
;
1995 if (maxSize
.y
< winpos
->cy
) winpos
->cy
= maxSize
.y
;
1996 if (!(wndPtr
->dwStyle
& WS_MINIMIZE
))
1998 if (winpos
->cx
< minTrack
.x
) winpos
->cx
= minTrack
.x
;
1999 if (winpos
->cy
< minTrack
.y
) winpos
->cy
= minTrack
.y
;
2006 /***********************************************************************
2007 * WINPOS_HandleWindowPosChanging
2009 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2011 LONG
WINPOS_HandleWindowPosChanging( WND
*wndPtr
, WINDOWPOS
*winpos
)
2014 if (winpos
->flags
& SWP_NOSIZE
) return 0;
2015 if ((wndPtr
->dwStyle
& WS_THICKFRAME
) ||
2016 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) == 0))
2018 WINPOS_GetMinMaxInfo( wndPtr
, &maxSize
, NULL
, NULL
, NULL
);
2019 winpos
->cx
= MIN( winpos
->cx
, maxSize
.x
);
2020 winpos
->cy
= MIN( winpos
->cy
, maxSize
.y
);
2025 /***********************************************************************
2028 * fix Z order taking into account owned popups -
2029 * basically we need to maintain them above the window that owns them
2031 * FIXME: hide/show owned popups when owner visibility changes.
2033 static HWND
SWP_DoOwnedPopups(WND
* pDesktop
, WND
* wndPtr
, HWND hwndInsertAfter
, WORD flags
)
2035 WND
* w
= WIN_LockWndPtr(pDesktop
->child
);
2037 WARN(win
, "(%04x) hInsertAfter = %04x\n", wndPtr
->hwndSelf
, hwndInsertAfter
);
2039 if( (wndPtr
->dwStyle
& WS_POPUP
) && wndPtr
->owner
)
2041 /* make sure this popup stays above the owner */
2043 HWND hwndLocalPrev
= HWND_TOP
;
2045 if( hwndInsertAfter
!= HWND_TOP
)
2047 while( w
!= wndPtr
->owner
)
2049 if (w
!= wndPtr
) hwndLocalPrev
= w
->hwndSelf
;
2050 if( hwndLocalPrev
== hwndInsertAfter
) break;
2051 WIN_UpdateWndPtr(&w
,w
->next
);
2053 hwndInsertAfter
= hwndLocalPrev
;
2056 else if( wndPtr
->dwStyle
& WS_CHILD
)
2059 WIN_UpdateWndPtr(&w
, pDesktop
->child
);
2063 if( w
== wndPtr
) break;
2065 if( (w
->dwStyle
& WS_POPUP
) && w
->owner
== wndPtr
)
2067 SetWindowPos(w
->hwndSelf
, hwndInsertAfter
, 0, 0, 0, 0,
2068 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOSENDCHANGING
| SWP_DEFERERASE
);
2069 hwndInsertAfter
= w
->hwndSelf
;
2071 WIN_UpdateWndPtr(&w
, w
->next
);
2075 WIN_ReleaseWndPtr(w
);
2076 return hwndInsertAfter
;
2079 /***********************************************************************
2082 * Make window look nice without excessive repainting
2084 * visible and update regions are in window coordinates
2085 * client and window rectangles are in parent client coordinates
2087 * FIXME: SWP_EX_PAINTSELF in uFlags works only if both old and new
2088 * window rects have the same origin.
2090 * Returns: uFlags and a dirty region in *pVisRgn.
2092 static UINT
SWP_CopyValidBits( WND
* Wnd
, HRGN
* pVisRgn
,
2093 LPRECT lpOldWndRect
,
2094 LPRECT lpOldClientRect
, UINT uFlags
)
2097 HRGN newVisRgn
, dirtyRgn
;
2098 INT my
= COMPLEXREGION
;
2100 TRACE(win
,"\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2101 Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
,
2102 Wnd
->rectWindow
.right
, Wnd
->rectWindow
.bottom
,
2103 lpOldWndRect
->left
, lpOldWndRect
->top
,
2104 lpOldWndRect
->right
, lpOldWndRect
->bottom
, *pVisRgn
);
2105 TRACE(win
,"\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2106 Wnd
->rectClient
.left
, Wnd
->rectClient
.top
,
2107 Wnd
->rectClient
.right
, Wnd
->rectClient
.bottom
,
2108 lpOldClientRect
->left
, lpOldClientRect
->top
,
2109 lpOldClientRect
->right
,lpOldClientRect
->bottom
);
2111 if( Wnd
->hrgnUpdate
== 1 )
2112 uFlags
|= SWP_EX_NOCOPY
; /* whole window is invalid, nothing to copy */
2114 newVisRgn
= DCE_GetVisRgn( Wnd
->hwndSelf
, DCX_WINDOW
| DCX_CLIPSIBLINGS
, 0, 0);
2115 dirtyRgn
= CreateRectRgn( 0, 0, 0, 0 );
2117 if( !(uFlags
& SWP_EX_NOCOPY
) ) /* make sure dst region covers only valid bits */
2118 my
= CombineRgn( dirtyRgn
, newVisRgn
, *pVisRgn
, RGN_AND
);
2120 if( (my
== NULLREGION
) || (uFlags
& SWP_EX_NOCOPY
) )
2124 TRACE(win
,"\twon't copy anything!\n");
2126 /* set dirtyRgn to the sum of old and new visible regions
2127 * in parent client coordinates */
2129 OffsetRgn( newVisRgn
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2130 OffsetRgn( *pVisRgn
, lpOldWndRect
->left
, lpOldWndRect
->top
);
2132 CombineRgn(*pVisRgn
, *pVisRgn
, newVisRgn
, RGN_OR
);
2134 else /* copy valid bits to a new location */
2136 INT dx
, dy
, ow
, oh
, nw
, nh
, ocw
, ncw
, och
, nch
;
2137 HRGN hrgnValid
= dirtyRgn
; /* non-empty intersection of old and new visible rgns */
2139 /* subtract already invalid region inside Wnd from the dst region */
2141 if( Wnd
->hrgnUpdate
)
2142 if( CombineRgn( hrgnValid
, hrgnValid
, Wnd
->hrgnUpdate
, RGN_DIFF
) == NULLREGION
)
2145 /* check if entire window can be copied */
2147 ow
= lpOldWndRect
->right
- lpOldWndRect
->left
;
2148 oh
= lpOldWndRect
->bottom
- lpOldWndRect
->top
;
2149 nw
= Wnd
->rectWindow
.right
- Wnd
->rectWindow
.left
;
2150 nh
= Wnd
->rectWindow
.bottom
- Wnd
->rectWindow
.top
;
2152 ocw
= lpOldClientRect
->right
- lpOldClientRect
->left
;
2153 och
= lpOldClientRect
->bottom
- lpOldClientRect
->top
;
2154 ncw
= Wnd
->rectClient
.right
- Wnd
->rectClient
.left
;
2155 nch
= Wnd
->rectClient
.bottom
- Wnd
->rectClient
.top
;
2157 if( (ocw
!= ncw
) || (och
!= nch
) ||
2158 ( ow
!= nw
) || ( oh
!= nw
) ||
2159 ((lpOldClientRect
->top
- lpOldWndRect
->top
) !=
2160 (Wnd
->rectClient
.top
- Wnd
->rectWindow
.top
)) ||
2161 ((lpOldClientRect
->left
- lpOldWndRect
->left
) !=
2162 (Wnd
->rectClient
.left
- Wnd
->rectWindow
.left
)) )
2164 dx
= Wnd
->rectClient
.left
- lpOldClientRect
->left
;
2165 dy
= Wnd
->rectClient
.top
- lpOldClientRect
->top
;
2167 /* restrict valid bits to the common client rect */
2169 r
.left
= Wnd
->rectClient
.left
- Wnd
->rectWindow
.left
;
2170 r
.top
= Wnd
->rectClient
.top
- Wnd
->rectWindow
.top
;
2171 r
.right
= r
.left
+ MIN( ocw
, ncw
);
2172 r
.bottom
= r
.top
+ MIN( och
, nch
);
2174 REGION_CropRgn( hrgnValid
, hrgnValid
, &r
,
2175 (uFlags
& SWP_EX_PAINTSELF
) ? NULL
: (POINT
*)&(Wnd
->rectWindow
));
2176 GetRgnBox( hrgnValid
, &r
);
2177 if( IsRectEmpty( &r
) )
2179 r
= *lpOldClientRect
;
2183 dx
= Wnd
->rectWindow
.left
- lpOldWndRect
->left
;
2184 dy
= Wnd
->rectWindow
.top
- lpOldWndRect
->top
;
2185 if( !(uFlags
& SWP_EX_PAINTSELF
) )
2186 OffsetRgn( hrgnValid
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2190 if( !(uFlags
& SWP_EX_PAINTSELF
) )
2192 /* Move remaining regions to parent coordinates */
2193 OffsetRgn( newVisRgn
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2194 OffsetRgn( *pVisRgn
, lpOldWndRect
->left
, lpOldWndRect
->top
);
2197 OffsetRect( &r
, -lpOldWndRect
->left
, -lpOldWndRect
->top
);
2199 TRACE(win
,"\tcomputing dirty region!\n");
2201 /* Compute combined dirty region (old + new - valid) */
2202 CombineRgn( *pVisRgn
, *pVisRgn
, newVisRgn
, RGN_OR
);
2203 CombineRgn( *pVisRgn
, *pVisRgn
, hrgnValid
, RGN_DIFF
);
2205 /* Blt valid bits, r is the rect to copy */
2210 HDC hDC
= ( uFlags
& SWP_EX_PAINTSELF
)
2211 ? GetDCEx( Wnd
->hwndSelf
, hrgnValid
, DCX_WINDOW
| DCX_CACHE
|
2212 DCX_KEEPCLIPRGN
| DCX_INTERSECTRGN
| DCX_CLIPSIBLINGS
)
2213 : GetDCEx( Wnd
->parent
->hwndSelf
, hrgnValid
, DCX_CACHE
|
2214 DCX_KEEPCLIPRGN
| DCX_INTERSECTRGN
| DCX_CLIPSIBLINGS
);
2215 if( (dc
= (DC
*)GDI_GetObjPtr(hDC
, DC_MAGIC
)) )
2217 if( oh
> nh
) r
.bottom
= r
.top
+ nh
;
2218 if( ow
< nw
) r
.right
= r
.left
+ nw
;
2220 Wnd
->pDriver
->pSurfaceCopy( Wnd
->parent
, dc
, dx
, dy
, &r
, TRUE
);
2222 GDI_HEAP_UNLOCK( hDC
);
2224 ReleaseDC( (uFlags
& SWP_EX_PAINTSELF
) ?
2225 Wnd
->hwndSelf
: Wnd
->parent
->hwndSelf
, hDC
);
2229 /* *pVisRgn now points to the invalidated region */
2231 DeleteObject(newVisRgn
);
2232 DeleteObject(dirtyRgn
);
2236 /***********************************************************************
2237 * SWP_DoSimpleFrameChanged
2239 * NOTE: old and new client rect origins are identical, only
2240 * extents may have changed. Window extents are the same.
2242 static void SWP_DoSimpleFrameChanged( WND
* wndPtr
, RECT
* pOldClientRect
, WORD swpFlags
, UINT uFlags
)
2248 if( !(swpFlags
& SWP_NOCLIENTSIZE
) )
2250 /* FIXME: WVR alignment flags */
2252 if( wndPtr
->rectClient
.right
> pOldClientRect
->right
) /* right edge */
2256 rect
.bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
2257 rect
.right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
2258 if(!(uFlags
& SWP_EX_NOCOPY
))
2259 rect
.left
= pOldClientRect
->right
- wndPtr
->rectClient
.left
;
2267 if( wndPtr
->rectClient
.bottom
> pOldClientRect
->bottom
) /* bottom edge */
2270 hrgn
= CreateRectRgnIndirect( &rect
);
2272 rect
.right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
2273 rect
.bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
2274 if(!(uFlags
& SWP_EX_NOCOPY
))
2275 rect
.top
= pOldClientRect
->bottom
- wndPtr
->rectClient
.top
;
2279 REGION_UnionRectWithRgn( hrgn
, &rect
);
2282 if( i
== 0 && (uFlags
& SWP_EX_NOCOPY
) ) /* force redraw anyway */
2284 rect
= wndPtr
->rectWindow
;
2285 OffsetRect( &rect
, wndPtr
->rectWindow
.left
- wndPtr
->rectClient
.left
,
2286 wndPtr
->rectWindow
.top
- wndPtr
->rectClient
.top
);
2294 PAINT_RedrawWindow( wndPtr
->hwndSelf
, &rect
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
|
2295 RDW_ERASENOW
| RDW_ALLCHILDREN
, RDW_EX_TOPFRAME
| RDW_EX_USEHRGN
);
2298 hrgn
= WIN_UpdateNCRgn(wndPtr
, TRUE
, TRUE
);
2301 DeleteObject( hrgn
);
2304 /***********************************************************************
2305 * SWP_DoWinPosChanging
2307 static BOOL
SWP_DoWinPosChanging( WND
* wndPtr
, WINDOWPOS
* pWinpos
,
2308 RECT
* pNewWindowRect
, RECT
* pNewClientRect
)
2310 /* Send WM_WINDOWPOSCHANGING message */
2312 if (!(pWinpos
->flags
& SWP_NOSENDCHANGING
))
2313 SendMessageA( wndPtr
->hwndSelf
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
)pWinpos
);
2315 /* Calculate new position and size */
2317 *pNewWindowRect
= wndPtr
->rectWindow
;
2318 *pNewClientRect
= (wndPtr
->dwStyle
& WS_MINIMIZE
) ? wndPtr
->rectWindow
2319 : wndPtr
->rectClient
;
2321 if (!(pWinpos
->flags
& SWP_NOSIZE
))
2323 pNewWindowRect
->right
= pNewWindowRect
->left
+ pWinpos
->cx
;
2324 pNewWindowRect
->bottom
= pNewWindowRect
->top
+ pWinpos
->cy
;
2326 if (!(pWinpos
->flags
& SWP_NOMOVE
))
2328 pNewWindowRect
->left
= pWinpos
->x
;
2329 pNewWindowRect
->top
= pWinpos
->y
;
2330 pNewWindowRect
->right
+= pWinpos
->x
- wndPtr
->rectWindow
.left
;
2331 pNewWindowRect
->bottom
+= pWinpos
->y
- wndPtr
->rectWindow
.top
;
2333 OffsetRect( pNewClientRect
, pWinpos
->x
- wndPtr
->rectWindow
.left
,
2334 pWinpos
->y
- wndPtr
->rectWindow
.top
);
2337 pWinpos
->flags
|= SWP_NOCLIENTMOVE
| SWP_NOCLIENTSIZE
;
2341 /***********************************************************************
2344 static UINT
SWP_DoNCCalcSize( WND
* wndPtr
, WINDOWPOS
* pWinpos
,
2345 RECT
* pNewWindowRect
, RECT
* pNewClientRect
, WORD f
)
2349 /* Send WM_NCCALCSIZE message to get new client area */
2350 if( (pWinpos
->flags
& (SWP_FRAMECHANGED
| SWP_NOSIZE
)) != SWP_NOSIZE
)
2352 wvrFlags
= WINPOS_SendNCCalcSize( pWinpos
->hwnd
, TRUE
, pNewWindowRect
,
2353 &wndPtr
->rectWindow
, &wndPtr
->rectClient
,
2354 pWinpos
, pNewClientRect
);
2356 /* FIXME: WVR_ALIGNxxx */
2358 if( pNewClientRect
->left
!= wndPtr
->rectClient
.left
||
2359 pNewClientRect
->top
!= wndPtr
->rectClient
.top
)
2360 pWinpos
->flags
&= ~SWP_NOCLIENTMOVE
;
2362 if( (pNewClientRect
->right
- pNewClientRect
->left
!=
2363 wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
) ||
2364 (pNewClientRect
->bottom
- pNewClientRect
->top
!=
2365 wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
) )
2366 pWinpos
->flags
&= ~SWP_NOCLIENTSIZE
;
2369 if( !(f
& SWP_NOMOVE
) && (pNewClientRect
->left
!= wndPtr
->rectClient
.left
||
2370 pNewClientRect
->top
!= wndPtr
->rectClient
.top
) )
2371 pWinpos
->flags
&= ~SWP_NOCLIENTMOVE
;
2375 /***********************************************************************
2376 * SetWindowPos (USER.2)
2378 BOOL16 WINAPI
SetWindowPos16( HWND16 hwnd
, HWND16 hwndInsertAfter
,
2379 INT16 x
, INT16 y
, INT16 cx
, INT16 cy
, WORD flags
)
2381 return SetWindowPos(hwnd
,(INT
)(INT16
)hwndInsertAfter
,x
,y
,cx
,cy
,flags
);
2384 /***********************************************************************
2385 * SetWindowPos (USER32.520)
2387 BOOL WINAPI
SetWindowPos( HWND hwnd
, HWND hwndInsertAfter
,
2388 INT x
, INT y
, INT cx
, INT cy
, WORD flags
)
2391 WND
* wndPtr
,*wndTemp
;
2392 RECT newWindowRect
, newClientRect
;
2393 RECT oldWindowRect
, oldClientRect
;
2395 UINT wvrFlags
= 0, uFlags
= 0;
2396 BOOL retvalue
, resync
= FALSE
;
2397 HWND hwndActive
= 0;
2399 /* Get current active window from the active queue */
2402 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
2405 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
2406 QUEUE_Unlock( pActiveQueue
);
2410 TRACE(win
,"hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2411 hwnd
, x
, y
, x
+cx
, y
+cy
, flags
);
2413 /* ------------------------------------------------------------------------ CHECKS */
2415 /* Check window handle */
2417 if (hwnd
== GetDesktopWindow()) return FALSE
;
2418 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return FALSE
;
2420 TRACE(win
,"\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr
->rectWindow
.left
, wndPtr
->rectWindow
.top
,
2421 wndPtr
->rectWindow
.right
, wndPtr
->rectWindow
.bottom
, (unsigned)wndPtr
->dwStyle
);
2423 /* Fix redundant flags */
2425 if(wndPtr
->dwStyle
& WS_VISIBLE
)
2426 flags
&= ~SWP_SHOWWINDOW
;
2429 if (!(flags
& SWP_SHOWWINDOW
))
2430 flags
|= SWP_NOREDRAW
;
2431 flags
&= ~SWP_HIDEWINDOW
;
2434 if ( cx
< 0 ) cx
= 0; if( cy
< 0 ) cy
= 0;
2436 if ((wndPtr
->rectWindow
.right
- wndPtr
->rectWindow
.left
== cx
) &&
2437 (wndPtr
->rectWindow
.bottom
- wndPtr
->rectWindow
.top
== cy
))
2438 flags
|= SWP_NOSIZE
; /* Already the right size */
2440 if ((wndPtr
->rectWindow
.left
== x
) && (wndPtr
->rectWindow
.top
== y
))
2441 flags
|= SWP_NOMOVE
; /* Already the right position */
2443 if (hwnd
== hwndActive
)
2444 flags
|= SWP_NOACTIVATE
; /* Already active */
2447 if(!(flags
& SWP_NOACTIVATE
)) /* Bring to the top when activating */
2449 flags
&= ~SWP_NOZORDER
;
2450 hwndInsertAfter
= HWND_TOP
;
2455 /* Check hwndInsertAfter */
2457 /* FIXME: TOPMOST not supported yet */
2458 if ((hwndInsertAfter
== HWND_TOPMOST
) ||
2459 (hwndInsertAfter
== HWND_NOTOPMOST
)) hwndInsertAfter
= HWND_TOP
;
2461 /* hwndInsertAfter must be a sibling of the window */
2462 if ((hwndInsertAfter
!= HWND_TOP
) && (hwndInsertAfter
!= HWND_BOTTOM
))
2464 WND
* wnd
= WIN_FindWndPtr(hwndInsertAfter
);
2467 if( wnd
->parent
!= wndPtr
->parent
)
2470 WIN_ReleaseWndPtr(wnd
);
2473 if( wnd
->next
== wndPtr
) flags
|= SWP_NOZORDER
;
2475 WIN_ReleaseWndPtr(wnd
);
2478 Pos
: /* ------------------------------------------------------------------------ MAIN part */
2480 /* Fill the WINDOWPOS structure */
2483 winpos
.hwndInsertAfter
= hwndInsertAfter
;
2488 winpos
.flags
= flags
;
2490 SWP_DoWinPosChanging( wndPtr
, &winpos
, &newWindowRect
, &newClientRect
);
2492 if((winpos
.flags
& (SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) != SWP_NOZORDER
)
2494 if( wndPtr
->parent
== WIN_GetDesktop() )
2495 hwndInsertAfter
= SWP_DoOwnedPopups( wndPtr
->parent
, wndPtr
,
2496 hwndInsertAfter
, winpos
.flags
);
2497 WIN_ReleaseDesktop();
2500 if(!(wndPtr
->flags
& WIN_NATIVE
) )
2502 if( hwndInsertAfter
== HWND_TOP
)
2503 winpos
.flags
|= ( wndPtr
->parent
->child
== wndPtr
)? SWP_NOZORDER
: 0;
2505 if( hwndInsertAfter
== HWND_BOTTOM
)
2506 winpos
.flags
|= ( wndPtr
->next
)? 0: SWP_NOZORDER
;
2508 if( !(winpos
.flags
& SWP_NOZORDER
) )
2509 if( GetWindow(hwndInsertAfter
, GW_HWNDNEXT
) == wndPtr
->hwndSelf
)
2510 winpos
.flags
|= SWP_NOZORDER
;
2512 if( !(winpos
.flags
& SWP_NOREDRAW
) &&
2513 ((winpos
.flags
& (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_FRAMECHANGED
))
2514 != (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
)) )
2516 /* get a previous visible region for SWP_CopyValidBits() */
2518 visRgn
= DCE_GetVisRgn(hwnd
, DCX_WINDOW
| DCX_CLIPSIBLINGS
, 0, 0);
2522 /* Common operations */
2524 wvrFlags
= SWP_DoNCCalcSize( wndPtr
, &winpos
, &newWindowRect
, &newClientRect
, flags
);
2526 if(!(winpos
.flags
& SWP_NOZORDER
))
2528 /* upon window creation (while processing WM_NCCREATE), wndPtr->parent is set correctly
2529 * but wndPtr is not yet in wndPtr->parent->child list
2530 * in those cases (SetWindowPos called while processing WM_NCCREATE),
2531 * do not unlink/link winPtr in parent->child
2533 if ( WIN_UnlinkWindow( winpos
.hwnd
) )
2534 WIN_LinkWindow( winpos
.hwnd
, hwndInsertAfter
);
2537 /* Reset active DCEs */
2539 if( (((winpos
.flags
& SWP_AGG_NOPOSCHANGE
) != SWP_AGG_NOPOSCHANGE
) &&
2540 wndPtr
->dwStyle
& WS_VISIBLE
) ||
2541 (flags
& (SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) )
2545 UnionRect(&rect
, &newWindowRect
, &wndPtr
->rectWindow
);
2546 DCE_InvalidateDCE(wndPtr
, &rect
);
2549 oldWindowRect
= wndPtr
->rectWindow
;
2550 oldClientRect
= wndPtr
->rectClient
;
2552 /* Find out if we have to redraw the whole client rect */
2554 if( oldClientRect
.bottom
- oldClientRect
.top
==
2555 newClientRect
.bottom
- newClientRect
.top
) wvrFlags
&= ~WVR_VREDRAW
;
2557 if( oldClientRect
.right
- oldClientRect
.left
==
2558 newClientRect
.right
- newClientRect
.left
) wvrFlags
&= ~WVR_HREDRAW
;
2560 uFlags
|= ((winpos
.flags
& SWP_NOCOPYBITS
) ||
2561 (!(winpos
.flags
& SWP_NOCLIENTSIZE
) &&
2562 (wvrFlags
>= WVR_HREDRAW
) && (wvrFlags
< WVR_VALIDRECTS
))) ? SWP_EX_NOCOPY
: 0;
2564 /* FIXME: actually do something with WVR_VALIDRECTS */
2566 wndPtr
->rectWindow
= newWindowRect
;
2567 wndPtr
->rectClient
= newClientRect
;
2569 if (wndPtr
->flags
& WIN_NATIVE
) /* -------------------------------------------- hosted window */
2571 BOOL bCallDriver
= TRUE
;
2572 HWND tempInsertAfter
= winpos
.hwndInsertAfter
;
2574 winpos
.hwndInsertAfter
= hwndInsertAfter
;
2576 if( !(winpos
.flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
| SWP_NOREDRAW
)) )
2578 /* This is the only place where we need to force repainting of the contents
2579 of windows created by the host window system, all other cases go through the
2580 expose event handling */
2582 if( (winpos
.flags
& SWP_FRAMECHANGED
) )
2586 if( (x
= (newWindowRect
.right
- newWindowRect
.left
)) == (oldWindowRect
.right
- oldWindowRect
.left
) &&
2587 (y
= (newWindowRect
.bottom
- newWindowRect
.top
)) == (oldWindowRect
.bottom
- oldWindowRect
.top
) )
2590 wndPtr
->pDriver
->pSetWindowPos(wndPtr
, &winpos
, TRUE
);
2591 winpos
.hwndInsertAfter
= tempInsertAfter
;
2592 bCallDriver
= FALSE
;
2594 if( winpos
.flags
& SWP_NOCLIENTMOVE
)
2595 SWP_DoSimpleFrameChanged(wndPtr
, &oldClientRect
, winpos
.flags
, uFlags
);
2598 /* client area moved but window extents remained the same, copy valid bits */
2600 visRgn
= CreateRectRgn( 0, 0, x
, y
);
2601 uFlags
= SWP_CopyValidBits( wndPtr
, &visRgn
, &oldWindowRect
, &oldClientRect
,
2602 uFlags
| SWP_EX_PAINTSELF
);
2610 if( !(winpos
.flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
| SWP_NOREDRAW
)) )
2612 if( (oldClientRect
.left
- oldWindowRect
.left
== newClientRect
.left
- newWindowRect
.left
) &&
2613 (oldClientRect
.top
- oldWindowRect
.top
== newClientRect
.top
- newWindowRect
.top
) &&
2614 !(uFlags
& SWP_EX_NOCOPY
) )
2616 /* The origin of the client rect didn't move so we can try to repaint
2617 * only the nonclient area by setting bit gravity hint for the host window system.
2620 if( !(wndPtr
->flags
& WIN_MANAGED
) )
2622 HRGN hrgn
= CreateRectRgn( 0, 0, newWindowRect
.right
- newWindowRect
.left
,
2623 newWindowRect
.bottom
- newWindowRect
.top
);
2624 RECT rcn
= newClientRect
;
2625 RECT rco
= oldClientRect
;
2627 OffsetRect( &rcn
, -newWindowRect
.left
, -newWindowRect
.top
);
2628 OffsetRect( &rco
, -oldWindowRect
.left
, -oldWindowRect
.top
);
2629 IntersectRect( &rcn
, &rcn
, &rco
);
2630 visRgn
= CreateRectRgnIndirect( &rcn
);
2631 CombineRgn( visRgn
, hrgn
, visRgn
, RGN_DIFF
);
2632 DeleteObject( hrgn
);
2633 uFlags
= SWP_EX_PAINTSELF
;
2635 wndPtr
->pDriver
->pSetHostAttr(wndPtr
, HAK_BITGRAVITY
, BGNorthWest
);
2638 wndPtr
->pDriver
->pSetHostAttr(wndPtr
, HAK_BITGRAVITY
, BGForget
);
2640 wndPtr
->pDriver
->pSetWindowPos(wndPtr
, &winpos
, TRUE
);
2641 winpos
.hwndInsertAfter
= tempInsertAfter
;
2644 if( winpos
.flags
& SWP_SHOWWINDOW
)
2648 wndPtr
->dwStyle
|= WS_VISIBLE
;
2650 if (wndPtr
->flags
& WIN_MANAGED
) resync
= TRUE
;
2652 /* focus was set to unmapped window, reset host focus
2653 * since the window is now visible */
2655 focus
= curr
= GetFocus();
2660 WND
*pFocus
= WIN_FindWndPtr( focus
);
2662 pFocus
->pDriver
->pSetFocus(pFocus
);
2663 WIN_ReleaseWndPtr(pFocus
);
2666 curr
= GetParent(curr
);
2670 else /* -------------------------------------------- emulated window */
2672 if( winpos
.flags
& SWP_SHOWWINDOW
)
2674 wndPtr
->dwStyle
|= WS_VISIBLE
;
2675 uFlags
|= SWP_EX_PAINTSELF
;
2676 visRgn
= 1; /* redraw the whole window */
2678 else if( !(winpos
.flags
& SWP_NOREDRAW
) )
2680 if( winpos
.flags
& SWP_HIDEWINDOW
)
2682 if( visRgn
> 1 ) /* map to parent */
2683 OffsetRgn( visRgn
, oldWindowRect
.left
, oldWindowRect
.top
);
2689 if( (winpos
.flags
& SWP_AGG_NOPOSCHANGE
) != SWP_AGG_NOPOSCHANGE
)
2690 uFlags
= SWP_CopyValidBits(wndPtr
, &visRgn
, &oldWindowRect
,
2691 &oldClientRect
, uFlags
);
2694 /* nothing moved, redraw frame if needed */
2696 if( winpos
.flags
& SWP_FRAMECHANGED
)
2697 SWP_DoSimpleFrameChanged( wndPtr
, &oldClientRect
, winpos
.flags
, uFlags
);
2700 DeleteObject( visRgn
);
2708 if( winpos
.flags
& SWP_HIDEWINDOW
)
2710 wndPtr
->dwStyle
&= ~WS_VISIBLE
;
2712 if (hwnd
== CARET_GetHwnd()) DestroyCaret();
2714 /* FIXME: This will cause the window to be activated irrespective
2715 * of whether it is owned by the same thread. Has to be done
2719 if (winpos
.hwnd
== hwndActive
)
2720 WINPOS_ActivateOtherWindow( wndPtr
);
2723 /* ------------------------------------------------------------------------ FINAL */
2725 if (wndPtr
->flags
& WIN_NATIVE
)
2726 EVENT_Synchronize(); /* Synchronize with the host window system */
2728 if (!GetCapture() && ((wndPtr
->dwStyle
& WS_VISIBLE
) || (flags
& SWP_HIDEWINDOW
)))
2729 EVENT_DummyMotionNotify(); /* Simulate a mouse event to set the cursor */
2731 wndTemp
= WIN_GetDesktop();
2733 /* repaint invalidated region (if any)
2735 * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2736 * and force update after ChangeActiveWindow() to avoid painting frames twice.
2741 if( !(winpos
.flags
& SWP_NOREDRAW
) )
2743 if( uFlags
& SWP_EX_PAINTSELF
)
2745 PAINT_RedrawWindow( wndPtr
->hwndSelf
, NULL
, (visRgn
== 1) ? 0 : visRgn
, RDW_ERASE
| RDW_FRAME
|
2746 ((winpos
.flags
& SWP_DEFERERASE
) ? 0 : RDW_ERASENOW
) | RDW_INVALIDATE
|
2747 RDW_ALLCHILDREN
, RDW_EX_XYWINDOW
| RDW_EX_USEHRGN
);
2751 PAINT_RedrawWindow( wndPtr
->parent
->hwndSelf
, NULL
, (visRgn
== 1) ? 0 : visRgn
, RDW_ERASE
|
2752 ((winpos
.flags
& SWP_DEFERERASE
) ? 0 : RDW_ERASENOW
) | RDW_INVALIDATE
|
2753 RDW_ALLCHILDREN
, RDW_EX_USEHRGN
);
2757 DeleteObject( visRgn
);
2760 WIN_ReleaseDesktop();
2762 if (!(flags
& SWP_NOACTIVATE
))
2763 WINPOS_ChangeActiveWindow( winpos
.hwnd
, FALSE
);
2765 /* And last, send the WM_WINDOWPOSCHANGED message */
2767 TRACE(win
,"\tstatus flags = %04x\n", winpos
.flags
& SWP_AGG_STATUSFLAGS
);
2770 (((winpos
.flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOPOSCHANGE
) &&
2771 !(winpos
.flags
& SWP_NOSENDCHANGING
)) )
2773 SendMessageA( winpos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
)&winpos
);
2774 if (resync
) EVENT_Synchronize ();
2779 WIN_ReleaseWndPtr(wndPtr
);
2784 /***********************************************************************
2785 * BeginDeferWindowPos16 (USER.259)
2787 HDWP16 WINAPI
BeginDeferWindowPos16( INT16 count
)
2789 return BeginDeferWindowPos( count
);
2793 /***********************************************************************
2794 * BeginDeferWindowPos (USER32.9)
2796 HDWP WINAPI
BeginDeferWindowPos( INT count
)
2801 if (count
<= 0) return 0;
2802 handle
= USER_HEAP_ALLOC( sizeof(DWP
) + (count
-1)*sizeof(WINDOWPOS
) );
2803 if (!handle
) return 0;
2804 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( handle
);
2805 pDWP
->actualCount
= 0;
2806 pDWP
->suggestedCount
= count
;
2808 pDWP
->wMagic
= DWP_MAGIC
;
2809 pDWP
->hwndParent
= 0;
2814 /***********************************************************************
2815 * DeferWindowPos16 (USER.260)
2817 HDWP16 WINAPI
DeferWindowPos16( HDWP16 hdwp
, HWND16 hwnd
, HWND16 hwndAfter
,
2818 INT16 x
, INT16 y
, INT16 cx
, INT16 cy
,
2821 return DeferWindowPos( hdwp
, hwnd
, (INT
)(INT16
)hwndAfter
,
2822 x
, y
, cx
, cy
, flags
);
2826 /***********************************************************************
2827 * DeferWindowPos (USER32.128)
2829 HDWP WINAPI
DeferWindowPos( HDWP hdwp
, HWND hwnd
, HWND hwndAfter
,
2830 INT x
, INT y
, INT cx
, INT cy
,
2835 HDWP newhdwp
= hdwp
,retvalue
;
2839 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
2840 if (!pDWP
) return 0;
2841 if (hwnd
== GetDesktopWindow()) return 0;
2843 if (!(pWnd
=WIN_FindWndPtr( hwnd
))) {
2844 USER_HEAP_FREE( hdwp
);
2848 /* Numega Bounds Checker Demo dislikes the following code.
2849 In fact, I've not been able to find any "same parent" requirement in any docu
2853 /* All the windows of a DeferWindowPos() must have the same parent */
2854 parent
= pWnd
->parent
->hwndSelf
;
2855 if (pDWP
->actualCount
== 0) pDWP
->hwndParent
= parent
;
2856 else if (parent
!= pDWP
->hwndParent
)
2858 USER_HEAP_FREE( hdwp
);
2864 for (i
= 0; i
< pDWP
->actualCount
; i
++)
2866 if (pDWP
->winPos
[i
].hwnd
== hwnd
)
2868 /* Merge with the other changes */
2869 if (!(flags
& SWP_NOZORDER
))
2871 pDWP
->winPos
[i
].hwndInsertAfter
= hwndAfter
;
2873 if (!(flags
& SWP_NOMOVE
))
2875 pDWP
->winPos
[i
].x
= x
;
2876 pDWP
->winPos
[i
].y
= y
;
2878 if (!(flags
& SWP_NOSIZE
))
2880 pDWP
->winPos
[i
].cx
= cx
;
2881 pDWP
->winPos
[i
].cy
= cy
;
2883 pDWP
->winPos
[i
].flags
&= flags
| ~(SWP_NOSIZE
| SWP_NOMOVE
|
2884 SWP_NOZORDER
| SWP_NOREDRAW
|
2885 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
2887 pDWP
->winPos
[i
].flags
|= flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
|
2893 if (pDWP
->actualCount
>= pDWP
->suggestedCount
)
2895 newhdwp
= USER_HEAP_REALLOC( hdwp
,
2896 sizeof(DWP
) + pDWP
->suggestedCount
*sizeof(WINDOWPOS
) );
2902 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( newhdwp
);
2903 pDWP
->suggestedCount
++;
2905 pDWP
->winPos
[pDWP
->actualCount
].hwnd
= hwnd
;
2906 pDWP
->winPos
[pDWP
->actualCount
].hwndInsertAfter
= hwndAfter
;
2907 pDWP
->winPos
[pDWP
->actualCount
].x
= x
;
2908 pDWP
->winPos
[pDWP
->actualCount
].y
= y
;
2909 pDWP
->winPos
[pDWP
->actualCount
].cx
= cx
;
2910 pDWP
->winPos
[pDWP
->actualCount
].cy
= cy
;
2911 pDWP
->winPos
[pDWP
->actualCount
].flags
= flags
;
2912 pDWP
->actualCount
++;
2915 WIN_ReleaseWndPtr(pWnd
);
2920 /***********************************************************************
2921 * EndDeferWindowPos16 (USER.261)
2923 BOOL16 WINAPI
EndDeferWindowPos16( HDWP16 hdwp
)
2925 return EndDeferWindowPos( hdwp
);
2929 /***********************************************************************
2930 * EndDeferWindowPos (USER32.173)
2932 BOOL WINAPI
EndDeferWindowPos( HDWP hdwp
)
2939 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
2940 if (!pDWP
) return FALSE
;
2941 for (i
= 0, winpos
= pDWP
->winPos
; i
< pDWP
->actualCount
; i
++, winpos
++)
2943 if (!(res
= SetWindowPos( winpos
->hwnd
, winpos
->hwndInsertAfter
,
2944 winpos
->x
, winpos
->y
, winpos
->cx
,
2945 winpos
->cy
, winpos
->flags
))) break;
2947 USER_HEAP_FREE( hdwp
);
2952 /***********************************************************************
2953 * TileChildWindows (USER.199)
2955 void WINAPI
TileChildWindows16( HWND16 parent
, WORD action
)
2957 FIXME(win
, "(%04x, %d): stub\n", parent
, action
);
2960 /***********************************************************************
2961 * CascageChildWindows (USER.198)
2963 void WINAPI
CascadeChildWindows16( HWND16 parent
, WORD action
)
2965 FIXME(win
, "(%04x, %d): stub\n", parent
, action
);
2967 /***********************************************************************
2968 * GetProgmanWindow [USER32.289]
2970 HRESULT WINAPI
GetProgmanWindow ( )
2971 { FIXME(win
,"stub\n");
2974 /***********************************************************************
2975 * GetTaskmanWindow [USER32.304]
2977 HRESULT WINAPI
GetTaskmanWindow ( )
2978 { FIXME(win
,"stub\n");
2981 /***********************************************************************
2982 * SetProgmanWindow [USER32.522]
2984 HRESULT WINAPI
SetProgmanWindow ( DWORD x
)
2985 { FIXME(win
,"0x%08lx stub\n",x
);
2988 /***********************************************************************
2989 * SetShellWindowEx [USER32.531]
2991 HRESULT WINAPI
SetShellWindowEx ( DWORD x
, DWORD y
)
2992 { FIXME(win
,"0x%08lx 0x%08lx stub\n",x
,y
);
2995 /***********************************************************************
2996 * SetTaskmanWindow [USER32.537]
2998 HRESULT WINAPI
SetTaskmanWindow ( DWORD x
)
2999 { FIXME(win
,"0x%08lx stub\n",x
);