2 * Window position related functions.
4 * Copyright 1993, 1994, 1995 Alexandre Julliard
5 * 1995, 1996, 1999 Alex Korobka
9 #include "wine/winuser16.h"
22 #include "nonclient.h"
23 #include "debugtools.h"
27 DEFAULT_DEBUG_CHANNEL(win
)
29 #define HAS_DLGFRAME(style,exStyle) \
30 (((exStyle) & WS_EX_DLGMODALFRAME) || \
31 (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
33 #define HAS_THICKFRAME(style) \
34 (((style) & WS_THICKFRAME) && \
35 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
37 #define SWP_AGG_NOGEOMETRYCHANGE \
38 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
39 #define SWP_AGG_NOPOSCHANGE \
40 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
41 #define SWP_AGG_STATUSFLAGS \
42 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
44 #define EMPTYPOINT(pt) ((*(LONG*)&(pt)) == -1)
46 #define PLACE_MIN 0x0001
47 #define PLACE_MAX 0x0002
48 #define PLACE_RECT 0x0004
50 #define SWP_EX_NOCOPY 0x0001
51 #define SWP_EX_PAINTSELF 0x0002
52 #define SWP_EX_NONCLIENT 0x0004
54 #define MINMAX_NOSWP 0x00010000
56 /* ----- internal variables ----- */
58 static HWND hwndPrevActive
= 0; /* Previously active window */
59 static HWND hGlobalShellWindow
=0; /*the shell*/
60 static HWND hGlobalTaskmanWindow
=0;
61 static HWND hGlobalProgmanWindow
=0;
63 static LPCSTR atomInternalPos
;
65 extern HQUEUE16 hActiveQueue
;
67 /***********************************************************************
68 * WINPOS_CreateInternalPosAtom
70 BOOL
WINPOS_CreateInternalPosAtom()
73 atomInternalPos
= (LPCSTR
)(DWORD
)GlobalAddAtomA(str
);
74 return (atomInternalPos
) ? TRUE
: FALSE
;
77 /***********************************************************************
78 * WINPOS_CheckInternalPos
80 * Called when a window is destroyed.
82 void WINPOS_CheckInternalPos( WND
* wndPtr
)
85 MESSAGEQUEUE
*pMsgQ
= 0;
86 HWND hwnd
= wndPtr
->hwndSelf
;
88 lpPos
= (LPINTERNALPOS
) GetPropA( hwnd
, atomInternalPos
);
90 /* Retrieve the message queue associated with this window */
91 pMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( wndPtr
->hmemTaskQ
);
94 WARN("\tMessage queue not found. Exiting!\n" );
98 if( hwnd
== hwndPrevActive
) hwndPrevActive
= 0;
100 if( hwnd
== PERQDATA_GetActiveWnd( pMsgQ
->pQData
) )
102 PERQDATA_SetActiveWnd( pMsgQ
->pQData
, 0 );
103 WARN("\tattempt to activate destroyed window!\n");
108 if( IsWindow(lpPos
->hwndIconTitle
) )
109 DestroyWindow( lpPos
->hwndIconTitle
);
110 HeapFree( SystemHeap
, 0, lpPos
);
113 QUEUE_Unlock( pMsgQ
);
117 /***********************************************************************
120 * Find a suitable place for an iconic window.
122 static POINT16
WINPOS_FindIconPos( WND
* wndPtr
, POINT16 pt
)
125 short x
, y
, xspacing
, yspacing
;
127 GetClientRect16( wndPtr
->parent
->hwndSelf
, &rectParent
);
128 if ((pt
.x
>= rectParent
.left
) && (pt
.x
+ GetSystemMetrics(SM_CXICON
) < rectParent
.right
) &&
129 (pt
.y
>= rectParent
.top
) && (pt
.y
+ GetSystemMetrics(SM_CYICON
) < rectParent
.bottom
))
130 return pt
; /* The icon already has a suitable position */
132 xspacing
= GetSystemMetrics(SM_CXICONSPACING
);
133 yspacing
= GetSystemMetrics(SM_CYICONSPACING
);
135 y
= rectParent
.bottom
;
138 for (x
= rectParent
.left
; x
<= rectParent
.right
-xspacing
; x
+= xspacing
)
140 /* Check if another icon already occupies this spot */
141 WND
*childPtr
= WIN_LockWndPtr(wndPtr
->parent
->child
);
144 if ((childPtr
->dwStyle
& WS_MINIMIZE
) && (childPtr
!= wndPtr
))
146 if ((childPtr
->rectWindow
.left
< x
+ xspacing
) &&
147 (childPtr
->rectWindow
.right
>= x
) &&
148 (childPtr
->rectWindow
.top
<= y
) &&
149 (childPtr
->rectWindow
.bottom
> y
- yspacing
))
150 break; /* There's a window in there */
152 WIN_UpdateWndPtr(&childPtr
,childPtr
->next
);
154 WIN_ReleaseWndPtr(childPtr
);
155 if (!childPtr
) /* No window was found, so it's OK for us */
157 pt
.x
= x
+ (xspacing
- GetSystemMetrics(SM_CXICON
)) / 2;
158 pt
.y
= y
- (yspacing
+ GetSystemMetrics(SM_CYICON
)) / 2;
167 /***********************************************************************
168 * ArrangeIconicWindows16 (USER.170)
170 UINT16 WINAPI
ArrangeIconicWindows16( HWND16 parent
)
172 return ArrangeIconicWindows(parent
);
174 /***********************************************************************
175 * ArrangeIconicWindows (USER32.7)
177 UINT WINAPI
ArrangeIconicWindows( HWND parent
)
181 INT x
, y
, xspacing
, yspacing
;
183 GetClientRect( parent
, &rectParent
);
185 y
= rectParent
.bottom
;
186 xspacing
= GetSystemMetrics(SM_CXICONSPACING
);
187 yspacing
= GetSystemMetrics(SM_CYICONSPACING
);
189 hwndChild
= GetWindow( parent
, GW_CHILD
);
192 if( IsIconic( hwndChild
) )
194 WND
*wndPtr
= WIN_FindWndPtr(hwndChild
);
196 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
198 SetWindowPos( hwndChild
, 0, x
+ (xspacing
- GetSystemMetrics(SM_CXICON
)) / 2,
199 y
- yspacing
- GetSystemMetrics(SM_CYICON
)/2, 0, 0,
200 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
201 if( IsWindow(hwndChild
) )
202 WINPOS_ShowIconTitle(wndPtr
, TRUE
);
203 WIN_ReleaseWndPtr(wndPtr
);
205 if (x
<= rectParent
.right
- xspacing
) x
+= xspacing
;
212 hwndChild
= GetWindow( hwndChild
, GW_HWNDNEXT
);
218 /***********************************************************************
219 * SwitchToThisWindow16 (USER.172)
221 void WINAPI
SwitchToThisWindow16( HWND16 hwnd
, BOOL16 restore
)
223 SwitchToThisWindow( hwnd
, restore
);
227 /***********************************************************************
228 * SwitchToThisWindow (USER32.539)
230 void WINAPI
SwitchToThisWindow( HWND hwnd
, BOOL restore
)
232 ShowWindow( hwnd
, restore
? SW_RESTORE
: SW_SHOWMINIMIZED
);
236 /***********************************************************************
237 * GetWindowRect16 (USER.32)
239 void WINAPI
GetWindowRect16( HWND16 hwnd
, LPRECT16 rect
)
241 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
244 CONV_RECT32TO16( &wndPtr
->rectWindow
, rect
);
245 if (wndPtr
->dwStyle
& WS_CHILD
)
246 MapWindowPoints16( wndPtr
->parent
->hwndSelf
, 0, (POINT16
*)rect
, 2 );
247 WIN_ReleaseWndPtr(wndPtr
);
251 /***********************************************************************
252 * GetWindowRect (USER32.308)
254 BOOL WINAPI
GetWindowRect( HWND hwnd
, LPRECT rect
)
256 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
257 if (!wndPtr
) return FALSE
;
259 *rect
= wndPtr
->rectWindow
;
260 if (wndPtr
->dwStyle
& WS_CHILD
)
261 MapWindowPoints( wndPtr
->parent
->hwndSelf
, 0, (POINT
*)rect
, 2 );
262 WIN_ReleaseWndPtr(wndPtr
);
267 /***********************************************************************
270 BOOL WINAPI
GetWindowRgn ( HWND hwnd
, HRGN hrgn
)
274 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
275 if (!wndPtr
) return (ERROR
);
277 FIXME("GetWindowRgn: doesn't really do regions\n");
279 memset (&rect
, 0, sizeof(rect
));
281 GetWindowRect ( hwnd
, &rect
);
283 FIXME("Check whether a valid region here\n");
285 SetRectRgn ( hrgn
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
287 WIN_ReleaseWndPtr(wndPtr
);
288 return (SIMPLEREGION
);
291 /***********************************************************************
294 INT WINAPI
SetWindowRgn( HWND hwnd
, HRGN hrgn
,BOOL bRedraw
)
298 FIXME("SetWindowRgn: stub\n");
302 /***********************************************************************
305 INT16 WINAPI
SetWindowRgn16( HWND16 hwnd
, HRGN16 hrgn
,BOOL16 bRedraw
)
309 FIXME("SetWindowRgn16: stub\n");
314 /***********************************************************************
315 * GetClientRect16 (USER.33)
317 void WINAPI
GetClientRect16( HWND16 hwnd
, LPRECT16 rect
)
319 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
321 rect
->left
= rect
->top
= rect
->right
= rect
->bottom
= 0;
324 rect
->right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
325 rect
->bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
327 WIN_ReleaseWndPtr(wndPtr
);
331 /***********************************************************************
332 * GetClientRect (USER.220)
334 BOOL WINAPI
GetClientRect( HWND hwnd
, LPRECT rect
)
336 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
338 rect
->left
= rect
->top
= rect
->right
= rect
->bottom
= 0;
339 if (!wndPtr
) return FALSE
;
340 rect
->right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
341 rect
->bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
343 WIN_ReleaseWndPtr(wndPtr
);
348 /*******************************************************************
349 * ClientToScreen16 (USER.28)
351 void WINAPI
ClientToScreen16( HWND16 hwnd
, LPPOINT16 lppnt
)
353 MapWindowPoints16( hwnd
, 0, lppnt
, 1 );
357 /*******************************************************************
358 * ClientToScreen (USER32.52)
360 BOOL WINAPI
ClientToScreen( HWND hwnd
, LPPOINT lppnt
)
362 MapWindowPoints( hwnd
, 0, lppnt
, 1 );
367 /*******************************************************************
368 * ScreenToClient16 (USER.29)
370 void WINAPI
ScreenToClient16( HWND16 hwnd
, LPPOINT16 lppnt
)
372 MapWindowPoints16( 0, hwnd
, lppnt
, 1 );
376 /*******************************************************************
377 * ScreenToClient (USER32.447)
379 BOOL WINAPI
ScreenToClient( HWND hwnd
, LPPOINT lppnt
)
381 MapWindowPoints( 0, hwnd
, lppnt
, 1 );
386 /***********************************************************************
387 * WINPOS_WindowFromPoint
389 * Find the window and hittest for a given point.
391 INT16
WINPOS_WindowFromPoint( WND
* wndScope
, POINT16 pt
, WND
**ppWnd
)
394 INT16 hittest
= HTERROR
;
399 wndPtr
= WIN_LockWndPtr(wndScope
->child
);
401 if( wndScope
->flags
& WIN_MANAGED
)
403 /* In managed mode we have to check wndScope first as it is also
404 * a window which received the mouse event. */
406 if( wndScope
->dwStyle
& WS_DISABLED
)
411 if( pt
.x
< wndScope
->rectClient
.left
|| pt
.x
>= wndScope
->rectClient
.right
||
412 pt
.y
< wndScope
->rectClient
.top
|| pt
.y
>= wndScope
->rectClient
.bottom
)
415 MapWindowPoints16( GetDesktopWindow16(), wndScope
->hwndSelf
, &xy
, 1 );
421 /* If point is in window, and window is visible, and it */
422 /* is enabled (or it's a top-level window), then explore */
423 /* its children. Otherwise, go to the next window. */
425 if ((wndPtr
->dwStyle
& WS_VISIBLE
) &&
426 (!(wndPtr
->dwStyle
& WS_DISABLED
) ||
427 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)) &&
428 (xy
.x
>= wndPtr
->rectWindow
.left
) &&
429 (xy
.x
< wndPtr
->rectWindow
.right
) &&
430 (xy
.y
>= wndPtr
->rectWindow
.top
) &&
431 (xy
.y
< wndPtr
->rectWindow
.bottom
))
433 *ppWnd
= wndPtr
; /* Got a suitable window */
435 /* If window is minimized or disabled, return at once */
436 if (wndPtr
->dwStyle
& WS_MINIMIZE
)
438 retvalue
= HTCAPTION
;
441 if (wndPtr
->dwStyle
& WS_DISABLED
)
447 /* If point is not in client area, ignore the children */
448 if ((xy
.x
< wndPtr
->rectClient
.left
) ||
449 (xy
.x
>= wndPtr
->rectClient
.right
) ||
450 (xy
.y
< wndPtr
->rectClient
.top
) ||
451 (xy
.y
>= wndPtr
->rectClient
.bottom
)) break;
453 xy
.x
-= wndPtr
->rectClient
.left
;
454 xy
.y
-= wndPtr
->rectClient
.top
;
455 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->child
);
459 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->next
);
464 /* If nothing found, try the scope window */
465 if (!*ppWnd
) *ppWnd
= wndScope
;
467 /* Send the WM_NCHITTEST message (only if to the same task) */
468 if ((*ppWnd
)->hmemTaskQ
== GetFastQueue16())
470 hittest
= (INT16
)SendMessage16( (*ppWnd
)->hwndSelf
, WM_NCHITTEST
,
471 0, MAKELONG( pt
.x
, pt
.y
) );
472 if (hittest
!= HTTRANSPARENT
)
474 retvalue
= hittest
; /* Found the window */
484 /* If no children found in last search, make point relative to parent */
487 xy
.x
+= (*ppWnd
)->rectClient
.left
;
488 xy
.y
+= (*ppWnd
)->rectClient
.top
;
491 /* Restart the search from the next sibling */
492 WIN_UpdateWndPtr(&wndPtr
,(*ppWnd
)->next
);
493 *ppWnd
= (*ppWnd
)->parent
;
497 WIN_ReleaseWndPtr(wndPtr
);
502 /*******************************************************************
503 * WindowFromPoint16 (USER.30)
505 HWND16 WINAPI
WindowFromPoint16( POINT16 pt
)
508 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt
, &pWnd
);
509 WIN_ReleaseDesktop();
510 return pWnd
->hwndSelf
;
514 /*******************************************************************
515 * WindowFromPoint (USER32.582)
517 HWND WINAPI
WindowFromPoint( POINT pt
)
521 CONV_POINT32TO16( &pt
, &pt16
);
522 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16
, &pWnd
);
523 WIN_ReleaseDesktop();
524 return (HWND
)pWnd
->hwndSelf
;
528 /*******************************************************************
529 * ChildWindowFromPoint16 (USER.191)
531 HWND16 WINAPI
ChildWindowFromPoint16( HWND16 hwndParent
, POINT16 pt
)
534 CONV_POINT16TO32( &pt
, &pt32
);
535 return (HWND16
)ChildWindowFromPoint( hwndParent
, pt32
);
539 /*******************************************************************
540 * ChildWindowFromPoint (USER32.49)
542 HWND WINAPI
ChildWindowFromPoint( HWND hwndParent
, POINT pt
)
544 /* pt is in the client coordinates */
546 WND
* wnd
= WIN_FindWndPtr(hwndParent
);
552 /* get client rect fast */
553 rect
.top
= rect
.left
= 0;
554 rect
.right
= wnd
->rectClient
.right
- wnd
->rectClient
.left
;
555 rect
.bottom
= wnd
->rectClient
.bottom
- wnd
->rectClient
.top
;
557 if (!PtInRect( &rect
, pt
))
562 WIN_UpdateWndPtr(&wnd
,wnd
->child
);
565 if (PtInRect( &wnd
->rectWindow
, pt
))
567 retvalue
= wnd
->hwndSelf
;
570 WIN_UpdateWndPtr(&wnd
,wnd
->next
);
572 retvalue
= hwndParent
;
574 WIN_ReleaseWndPtr(wnd
);
578 /*******************************************************************
579 * ChildWindowFromPointEx16 (USER.50)
581 HWND16 WINAPI
ChildWindowFromPointEx16( HWND16 hwndParent
, POINT16 pt
, UINT16 uFlags
)
584 CONV_POINT16TO32( &pt
, &pt32
);
585 return (HWND16
)ChildWindowFromPointEx( hwndParent
, pt32
, uFlags
);
589 /*******************************************************************
590 * ChildWindowFromPointEx32 (USER32.50)
592 HWND WINAPI
ChildWindowFromPointEx( HWND hwndParent
, POINT pt
,
595 /* pt is in the client coordinates */
597 WND
* wnd
= WIN_FindWndPtr(hwndParent
);
603 /* get client rect fast */
604 rect
.top
= rect
.left
= 0;
605 rect
.right
= wnd
->rectClient
.right
- wnd
->rectClient
.left
;
606 rect
.bottom
= wnd
->rectClient
.bottom
- wnd
->rectClient
.top
;
608 if (!PtInRect( &rect
, pt
))
613 WIN_UpdateWndPtr(&wnd
,wnd
->child
);
617 if (PtInRect( &wnd
->rectWindow
, pt
)) {
618 if ( (uFlags
& CWP_SKIPINVISIBLE
) &&
619 !(wnd
->dwStyle
& WS_VISIBLE
) );
620 else if ( (uFlags
& CWP_SKIPDISABLED
) &&
621 (wnd
->dwStyle
& WS_DISABLED
) );
622 else if ( (uFlags
& CWP_SKIPTRANSPARENT
) &&
623 (wnd
->dwExStyle
& WS_EX_TRANSPARENT
) );
626 retvalue
= wnd
->hwndSelf
;
631 WIN_UpdateWndPtr(&wnd
,wnd
->next
);
633 retvalue
= hwndParent
;
635 WIN_ReleaseWndPtr(wnd
);
640 /*******************************************************************
641 * WINPOS_GetWinOffset
643 * Calculate the offset between the origin of the two windows. Used
644 * to implement MapWindowPoints.
646 static void WINPOS_GetWinOffset( HWND hwndFrom
, HWND hwndTo
,
651 offset
->x
= offset
->y
= 0;
652 if (hwndFrom
== hwndTo
) return;
654 /* Translate source window origin to screen coords */
657 if (!(wndPtr
= WIN_FindWndPtr( hwndFrom
)))
659 ERR("bad hwndFrom = %04x\n",hwndFrom
);
662 while (wndPtr
->parent
)
664 offset
->x
+= wndPtr
->rectClient
.left
;
665 offset
->y
+= wndPtr
->rectClient
.top
;
666 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->parent
);
668 WIN_ReleaseWndPtr(wndPtr
);
671 /* Translate origin to destination window coords */
674 if (!(wndPtr
= WIN_FindWndPtr( hwndTo
)))
676 ERR("bad hwndTo = %04x\n", hwndTo
);
679 while (wndPtr
->parent
)
681 offset
->x
-= wndPtr
->rectClient
.left
;
682 offset
->y
-= wndPtr
->rectClient
.top
;
683 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->parent
);
685 WIN_ReleaseWndPtr(wndPtr
);
690 /*******************************************************************
691 * MapWindowPoints16 (USER.258)
693 void WINAPI
MapWindowPoints16( HWND16 hwndFrom
, HWND16 hwndTo
,
694 LPPOINT16 lppt
, UINT16 count
)
698 WINPOS_GetWinOffset( hwndFrom
, hwndTo
, &offset
);
708 /*******************************************************************
709 * MapWindowPoints (USER32.386)
711 INT WINAPI
MapWindowPoints( HWND hwndFrom
, HWND hwndTo
,
712 LPPOINT lppt
, UINT count
)
716 WINPOS_GetWinOffset( hwndFrom
, hwndTo
, &offset
);
723 return MAKELONG( LOWORD(offset
.x
), LOWORD(offset
.y
) );
727 /***********************************************************************
728 * IsIconic16 (USER.31)
730 BOOL16 WINAPI
IsIconic16(HWND16 hWnd
)
732 return IsIconic(hWnd
);
736 /***********************************************************************
737 * IsIconic (USER32.345)
739 BOOL WINAPI
IsIconic(HWND hWnd
)
742 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
743 if (wndPtr
== NULL
) return FALSE
;
744 retvalue
= (wndPtr
->dwStyle
& WS_MINIMIZE
) != 0;
745 WIN_ReleaseWndPtr(wndPtr
);
750 /***********************************************************************
751 * IsZoomed (USER.272)
753 BOOL16 WINAPI
IsZoomed16(HWND16 hWnd
)
755 return IsZoomed(hWnd
);
759 /***********************************************************************
760 * IsZoomed (USER.352)
762 BOOL WINAPI
IsZoomed(HWND hWnd
)
765 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
766 if (wndPtr
== NULL
) return FALSE
;
767 retvalue
= (wndPtr
->dwStyle
& WS_MAXIMIZE
) != 0;
768 WIN_ReleaseWndPtr(wndPtr
);
773 /*******************************************************************
774 * GetActiveWindow (USER.60)
776 HWND16 WINAPI
GetActiveWindow16(void)
778 return (HWND16
)GetActiveWindow();
781 /*******************************************************************
782 * GetActiveWindow (USER32.205)
784 HWND WINAPI
GetActiveWindow(void)
786 MESSAGEQUEUE
*pCurMsgQ
= 0;
789 /* Get the messageQ for the current thread */
790 if (!(pCurMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( GetFastQueue16() )))
792 WARN("\tCurrent message queue not found. Exiting!\n" );
796 /* Return the current active window from the perQ data of the current message Q */
797 hwndActive
= PERQDATA_GetActiveWnd( pCurMsgQ
->pQData
);
799 QUEUE_Unlock( pCurMsgQ
);
804 /*******************************************************************
807 static BOOL
WINPOS_CanActivate(WND
* pWnd
)
809 if( pWnd
&& ((pWnd
->dwStyle
& (WS_DISABLED
| WS_VISIBLE
| WS_CHILD
))
810 == WS_VISIBLE
) ) return TRUE
;
815 /*******************************************************************
816 * SetActiveWindow16 (USER.59)
818 HWND16 WINAPI
SetActiveWindow16( HWND16 hwnd
)
820 return SetActiveWindow(hwnd
);
824 /*******************************************************************
825 * SetActiveWindow (USER32.463)
827 HWND WINAPI
SetActiveWindow( HWND hwnd
)
830 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
831 MESSAGEQUEUE
*pMsgQ
= 0, *pCurMsgQ
= 0;
833 if ( !WINPOS_CanActivate(wndPtr
) )
839 /* Get the messageQ for the current thread */
840 if (!(pCurMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( GetFastQueue16() )))
842 WARN("\tCurrent message queue not found. Exiting!\n" );
846 /* Retrieve the message queue associated with this window */
847 pMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( wndPtr
->hmemTaskQ
);
850 WARN("\tWindow message queue not found. Exiting!\n" );
854 /* Make sure that the window is associated with the calling threads
855 * message queue. It must share the same perQ data.
858 if ( pCurMsgQ
->pQData
!= pMsgQ
->pQData
)
861 /* Save current active window */
862 prev
= PERQDATA_GetActiveWnd( pMsgQ
->pQData
);
864 WINPOS_SetActiveWindow( hwnd
, 0, 0 );
867 /* Unlock the queues before returning */
869 QUEUE_Unlock( pMsgQ
);
871 QUEUE_Unlock( pCurMsgQ
);
874 WIN_ReleaseWndPtr(wndPtr
);
879 /*******************************************************************
880 * GetForegroundWindow16 (USER.608)
882 HWND16 WINAPI
GetForegroundWindow16(void)
884 return (HWND16
)GetForegroundWindow();
888 /*******************************************************************
889 * SetForegroundWindow16 (USER.609)
891 BOOL16 WINAPI
SetForegroundWindow16( HWND16 hwnd
)
893 return SetForegroundWindow( hwnd
);
897 /*******************************************************************
898 * GetForegroundWindow (USER32.241)
900 HWND WINAPI
GetForegroundWindow(void)
904 /* Get the foreground window (active window of hActiveQueue) */
907 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
909 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
911 QUEUE_Unlock( pActiveQueue
);
917 /*******************************************************************
918 * SetForegroundWindow (USER32.482)
920 BOOL WINAPI
SetForegroundWindow( HWND hwnd
)
922 return WINPOS_ChangeActiveWindow( hwnd
, FALSE
);
926 /*******************************************************************
927 * GetShellWindow16 (USER.600)
929 HWND16 WINAPI
GetShellWindow16(void)
931 return GetShellWindow();
934 /*******************************************************************
935 * SetShellWindow (USER32.504)
937 HWND WINAPI
SetShellWindow(HWND hwndshell
)
938 { WARN("(hWnd=%08x) semi stub\n",hwndshell
);
940 hGlobalShellWindow
= hwndshell
;
941 return hGlobalShellWindow
;
945 /*******************************************************************
946 * GetShellWindow (USER32.287)
948 HWND WINAPI
GetShellWindow(void)
949 { WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow
);
951 return hGlobalShellWindow
;
955 /***********************************************************************
956 * BringWindowToTop16 (USER.45)
958 BOOL16 WINAPI
BringWindowToTop16( HWND16 hwnd
)
960 return BringWindowToTop(hwnd
);
964 /***********************************************************************
965 * BringWindowToTop (USER32.11)
967 BOOL WINAPI
BringWindowToTop( HWND hwnd
)
969 return SetWindowPos( hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
);
973 /***********************************************************************
974 * MoveWindow16 (USER.56)
976 BOOL16 WINAPI
MoveWindow16( HWND16 hwnd
, INT16 x
, INT16 y
, INT16 cx
, INT16 cy
,
979 return MoveWindow(hwnd
,x
,y
,cx
,cy
,repaint
);
983 /***********************************************************************
984 * MoveWindow (USER32.399)
986 BOOL WINAPI
MoveWindow( HWND hwnd
, INT x
, INT y
, INT cx
, INT cy
,
989 int flags
= SWP_NOZORDER
| SWP_NOACTIVATE
;
990 if (!repaint
) flags
|= SWP_NOREDRAW
;
991 TRACE("%04x %d,%d %dx%d %d\n",
992 hwnd
, x
, y
, cx
, cy
, repaint
);
993 return SetWindowPos( hwnd
, 0, x
, y
, cx
, cy
, flags
);
996 /***********************************************************************
997 * WINPOS_InitInternalPos
999 static LPINTERNALPOS
WINPOS_InitInternalPos( WND
* wnd
, POINT pt
,
1000 LPRECT restoreRect
)
1002 LPINTERNALPOS lpPos
= (LPINTERNALPOS
) GetPropA( wnd
->hwndSelf
,
1006 /* this happens when the window is minimized/maximized
1007 * for the first time (rectWindow is not adjusted yet) */
1009 lpPos
= HeapAlloc( SystemHeap
, 0, sizeof(INTERNALPOS
) );
1010 if( !lpPos
) return NULL
;
1012 SetPropA( wnd
->hwndSelf
, atomInternalPos
, (HANDLE
)lpPos
);
1013 lpPos
->hwndIconTitle
= 0; /* defer until needs to be shown */
1014 CONV_RECT32TO16( &wnd
->rectWindow
, &lpPos
->rectNormal
);
1015 *(UINT
*)&lpPos
->ptIconPos
= *(UINT
*)&lpPos
->ptMaxPos
= 0xFFFFFFFF;
1018 if( wnd
->dwStyle
& WS_MINIMIZE
)
1019 CONV_POINT32TO16( &pt
, &lpPos
->ptIconPos
);
1020 else if( wnd
->dwStyle
& WS_MAXIMIZE
)
1021 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1022 else if( restoreRect
)
1023 CONV_RECT32TO16( restoreRect
, &lpPos
->rectNormal
);
1028 /***********************************************************************
1029 * WINPOS_RedrawIconTitle
1031 BOOL
WINPOS_RedrawIconTitle( HWND hWnd
)
1033 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)GetPropA( hWnd
, atomInternalPos
);
1036 if( lpPos
->hwndIconTitle
)
1038 SendMessageA( lpPos
->hwndIconTitle
, WM_SHOWWINDOW
, TRUE
, 0);
1039 InvalidateRect( lpPos
->hwndIconTitle
, NULL
, TRUE
);
1046 /***********************************************************************
1047 * WINPOS_ShowIconTitle
1049 BOOL
WINPOS_ShowIconTitle( WND
* pWnd
, BOOL bShow
)
1051 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)GetPropA( pWnd
->hwndSelf
, atomInternalPos
);
1053 if( lpPos
&& !(pWnd
->flags
& WIN_MANAGED
))
1055 HWND16 hWnd
= lpPos
->hwndIconTitle
;
1057 TRACE("0x%04x %i\n", pWnd
->hwndSelf
, (bShow
!= 0) );
1060 lpPos
->hwndIconTitle
= hWnd
= ICONTITLE_Create( pWnd
);
1063 if( ( pWnd
= WIN_FindWndPtr(hWnd
) ) != NULL
)
1065 if( !(pWnd
->dwStyle
& WS_VISIBLE
) )
1067 SendMessageA( hWnd
, WM_SHOWWINDOW
, TRUE
, 0 );
1068 SetWindowPos( hWnd
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
1069 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_SHOWWINDOW
);
1071 WIN_ReleaseWndPtr(pWnd
);
1074 else ShowWindow( hWnd
, SW_HIDE
);
1079 /*******************************************************************
1080 * WINPOS_GetMinMaxInfo
1082 * Get the minimized and maximized information for a window.
1084 void WINPOS_GetMinMaxInfo( WND
*wndPtr
, POINT
*maxSize
, POINT
*maxPos
,
1085 POINT
*minTrack
, POINT
*maxTrack
)
1087 LPINTERNALPOS lpPos
;
1091 /* Compute default values */
1093 MinMax
.ptMaxSize
.x
= GetSystemMetrics(SM_CXSCREEN
);
1094 MinMax
.ptMaxSize
.y
= GetSystemMetrics(SM_CYSCREEN
);
1095 MinMax
.ptMinTrackSize
.x
= GetSystemMetrics(SM_CXMINTRACK
);
1096 MinMax
.ptMinTrackSize
.y
= GetSystemMetrics(SM_CYMINTRACK
);
1097 MinMax
.ptMaxTrackSize
.x
= GetSystemMetrics(SM_CXSCREEN
);
1098 MinMax
.ptMaxTrackSize
.y
= GetSystemMetrics(SM_CYSCREEN
);
1100 if (wndPtr
->flags
& WIN_MANAGED
) xinc
= yinc
= 0;
1101 else if (HAS_DLGFRAME( wndPtr
->dwStyle
, wndPtr
->dwExStyle
))
1103 xinc
= GetSystemMetrics(SM_CXDLGFRAME
);
1104 yinc
= GetSystemMetrics(SM_CYDLGFRAME
);
1109 if (HAS_THICKFRAME(wndPtr
->dwStyle
))
1111 xinc
+= GetSystemMetrics(SM_CXFRAME
);
1112 yinc
+= GetSystemMetrics(SM_CYFRAME
);
1114 if (wndPtr
->dwStyle
& WS_BORDER
)
1116 xinc
+= GetSystemMetrics(SM_CXBORDER
);
1117 yinc
+= GetSystemMetrics(SM_CYBORDER
);
1120 MinMax
.ptMaxSize
.x
+= 2 * xinc
;
1121 MinMax
.ptMaxSize
.y
+= 2 * yinc
;
1123 lpPos
= (LPINTERNALPOS
)GetPropA( wndPtr
->hwndSelf
, atomInternalPos
);
1124 if( lpPos
&& !EMPTYPOINT(lpPos
->ptMaxPos
) )
1125 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &MinMax
.ptMaxPosition
);
1128 MinMax
.ptMaxPosition
.x
= -xinc
;
1129 MinMax
.ptMaxPosition
.y
= -yinc
;
1132 SendMessageA( wndPtr
->hwndSelf
, WM_GETMINMAXINFO
, 0, (LPARAM
)&MinMax
);
1134 /* Some sanity checks */
1136 TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1137 MinMax
.ptMaxSize
.x
, MinMax
.ptMaxSize
.y
,
1138 MinMax
.ptMaxPosition
.x
, MinMax
.ptMaxPosition
.y
,
1139 MinMax
.ptMaxTrackSize
.x
, MinMax
.ptMaxTrackSize
.y
,
1140 MinMax
.ptMinTrackSize
.x
, MinMax
.ptMinTrackSize
.y
);
1141 MinMax
.ptMaxTrackSize
.x
= MAX( MinMax
.ptMaxTrackSize
.x
,
1142 MinMax
.ptMinTrackSize
.x
);
1143 MinMax
.ptMaxTrackSize
.y
= MAX( MinMax
.ptMaxTrackSize
.y
,
1144 MinMax
.ptMinTrackSize
.y
);
1146 if (maxSize
) *maxSize
= MinMax
.ptMaxSize
;
1147 if (maxPos
) *maxPos
= MinMax
.ptMaxPosition
;
1148 if (minTrack
) *minTrack
= MinMax
.ptMinTrackSize
;
1149 if (maxTrack
) *maxTrack
= MinMax
.ptMaxTrackSize
;
1152 /***********************************************************************
1153 * WINPOS_MinMaximize
1155 * Fill in lpRect and return additional flags to be used with SetWindowPos().
1156 * This function assumes that 'cmd' is different from the current window
1159 UINT
WINPOS_MinMaximize( WND
* wndPtr
, UINT16 cmd
, LPRECT16 lpRect
)
1163 LPINTERNALPOS lpPos
;
1165 TRACE("0x%04x %u\n", wndPtr
->hwndSelf
, cmd
);
1167 size
.x
= wndPtr
->rectWindow
.left
; size
.y
= wndPtr
->rectWindow
.top
;
1168 lpPos
= WINPOS_InitInternalPos( wndPtr
, size
, &wndPtr
->rectWindow
);
1170 if (lpPos
&& !HOOK_CallHooks16(WH_CBT
, HCBT_MINMAX
, wndPtr
->hwndSelf
, cmd
))
1172 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1174 if( !SendMessageA( wndPtr
->hwndSelf
, WM_QUERYOPEN
, 0, 0L ) )
1175 return (SWP_NOSIZE
| SWP_NOMOVE
);
1176 swpFlags
|= SWP_NOCOPYBITS
;
1181 if( wndPtr
->dwStyle
& WS_MAXIMIZE
)
1183 wndPtr
->flags
|= WIN_RESTORE_MAX
;
1184 wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
1187 wndPtr
->flags
&= ~WIN_RESTORE_MAX
;
1188 wndPtr
->dwStyle
|= WS_MINIMIZE
;
1190 if( wndPtr
->flags
& WIN_NATIVE
)
1191 if( wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, TRUE
) )
1192 swpFlags
|= MINMAX_NOSWP
;
1194 lpPos
->ptIconPos
= WINPOS_FindIconPos( wndPtr
, lpPos
->ptIconPos
);
1196 SetRect16( lpRect
, lpPos
->ptIconPos
.x
, lpPos
->ptIconPos
.y
,
1197 GetSystemMetrics(SM_CXICON
), GetSystemMetrics(SM_CYICON
) );
1198 swpFlags
|= SWP_NOCOPYBITS
;
1202 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &pt
);
1203 WINPOS_GetMinMaxInfo( wndPtr
, &size
, &pt
, NULL
, NULL
);
1204 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1206 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1208 if( wndPtr
->flags
& WIN_NATIVE
)
1209 if( wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, FALSE
) )
1210 swpFlags
|= MINMAX_NOSWP
;
1212 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
1213 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
1215 wndPtr
->dwStyle
|= WS_MAXIMIZE
;
1217 SetRect16( lpRect
, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
,
1222 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1224 if( wndPtr
->flags
& WIN_NATIVE
)
1225 if( wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, FALSE
) )
1226 swpFlags
|= MINMAX_NOSWP
;
1228 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
1229 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
1231 if( wndPtr
->flags
& WIN_RESTORE_MAX
)
1233 /* Restore to maximized position */
1234 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &pt
);
1235 WINPOS_GetMinMaxInfo( wndPtr
, &size
, &pt
, NULL
, NULL
);
1236 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1237 wndPtr
->dwStyle
|= WS_MAXIMIZE
;
1238 SetRect16( lpRect
, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
, size
.x
, size
.y
);
1243 if( !(wndPtr
->dwStyle
& WS_MAXIMIZE
) ) return (UINT16
)(-1);
1244 else wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
1246 /* Restore to normal position */
1248 *lpRect
= lpPos
->rectNormal
;
1249 lpRect
->right
-= lpRect
->left
;
1250 lpRect
->bottom
-= lpRect
->top
;
1254 } else swpFlags
|= SWP_NOSIZE
| SWP_NOMOVE
;
1258 /***********************************************************************
1259 * ShowWindowAsync (USER32.535)
1261 * doesn't wait; returns immediately.
1262 * used by threads to toggle windows in other (possibly hanging) threads
1264 BOOL WINAPI
ShowWindowAsync( HWND hwnd
, INT cmd
)
1266 /* FIXME: does ShowWindow() return immediately ? */
1267 return ShowWindow(hwnd
, cmd
);
1271 /***********************************************************************
1272 * ShowWindow16 (USER.42)
1274 BOOL16 WINAPI
ShowWindow16( HWND16 hwnd
, INT16 cmd
)
1276 return ShowWindow(hwnd
,cmd
);
1280 /***********************************************************************
1281 * ShowWindow (USER32.534)
1283 BOOL WINAPI
ShowWindow( HWND hwnd
, INT cmd
)
1285 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
1286 BOOL wasVisible
, showFlag
;
1287 RECT16 newPos
= {0, 0, 0, 0};
1290 if (!wndPtr
) return FALSE
;
1292 TRACE("hwnd=%04x, cmd=%d\n", hwnd
, cmd
);
1294 wasVisible
= (wndPtr
->dwStyle
& WS_VISIBLE
) != 0;
1299 if (!wasVisible
) goto END
;;
1300 swp
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
|
1301 SWP_NOACTIVATE
| SWP_NOZORDER
;
1302 if ((hwnd
== GetFocus()) || IsChild( hwnd
, GetFocus()))
1304 /* Revert focus to parent */
1305 SetFocus( GetParent(hwnd
) );
1309 case SW_SHOWMINNOACTIVE
:
1310 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1312 case SW_SHOWMINIMIZED
:
1313 swp
|= SWP_SHOWWINDOW
;
1316 swp
|= SWP_FRAMECHANGED
;
1317 if( !(wndPtr
->dwStyle
& WS_MINIMIZE
) )
1318 swp
|= WINPOS_MinMaximize( wndPtr
, SW_MINIMIZE
, &newPos
);
1319 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1322 case SW_SHOWMAXIMIZED
: /* same as SW_MAXIMIZE */
1323 swp
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
1324 if( !(wndPtr
->dwStyle
& WS_MAXIMIZE
) )
1325 swp
|= WINPOS_MinMaximize( wndPtr
, SW_MAXIMIZE
, &newPos
);
1326 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1330 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1333 swp
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
1336 case SW_SHOWNOACTIVATE
:
1337 swp
|= SWP_NOZORDER
;
1338 if (GetActiveWindow()) swp
|= SWP_NOACTIVATE
;
1340 case SW_SHOWNORMAL
: /* same as SW_NORMAL: */
1341 case SW_SHOWDEFAULT
: /* FIXME: should have its own handler */
1343 swp
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
1345 if( wndPtr
->dwStyle
& (WS_MINIMIZE
| WS_MAXIMIZE
) )
1346 swp
|= WINPOS_MinMaximize( wndPtr
, SW_RESTORE
, &newPos
);
1347 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1351 showFlag
= (cmd
!= SW_HIDE
);
1352 if (showFlag
!= wasVisible
)
1354 SendMessageA( hwnd
, WM_SHOWWINDOW
, showFlag
, 0 );
1355 if (!IsWindow( hwnd
)) goto END
;
1358 if ((wndPtr
->dwStyle
& WS_CHILD
) &&
1359 !IsWindowVisible( wndPtr
->parent
->hwndSelf
) &&
1360 (swp
& (SWP_NOSIZE
| SWP_NOMOVE
)) == (SWP_NOSIZE
| SWP_NOMOVE
) )
1362 /* Don't call SetWindowPos() on invisible child windows */
1363 if (cmd
== SW_HIDE
) wndPtr
->dwStyle
&= ~WS_VISIBLE
;
1364 else wndPtr
->dwStyle
|= WS_VISIBLE
;
1368 /* We can't activate a child window */
1369 if (wndPtr
->dwStyle
& WS_CHILD
) swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1370 if (!(swp
& MINMAX_NOSWP
))
1371 SetWindowPos( hwnd
, HWND_TOP
, newPos
.left
, newPos
.top
,
1372 newPos
.right
, newPos
.bottom
, LOWORD(swp
) );
1373 if (!IsWindow( hwnd
)) goto END
;
1374 else if( wndPtr
->dwStyle
& WS_MINIMIZE
) WINPOS_ShowIconTitle( wndPtr
, TRUE
);
1377 if (wndPtr
->flags
& WIN_NEED_SIZE
)
1379 /* should happen only in CreateWindowEx() */
1380 int wParam
= SIZE_RESTORED
;
1382 wndPtr
->flags
&= ~WIN_NEED_SIZE
;
1383 if (wndPtr
->dwStyle
& WS_MAXIMIZE
) wParam
= SIZE_MAXIMIZED
;
1384 else if (wndPtr
->dwStyle
& WS_MINIMIZE
) wParam
= SIZE_MINIMIZED
;
1385 SendMessageA( hwnd
, WM_SIZE
, wParam
,
1386 MAKELONG(wndPtr
->rectClient
.right
-wndPtr
->rectClient
.left
,
1387 wndPtr
->rectClient
.bottom
-wndPtr
->rectClient
.top
));
1388 SendMessageA( hwnd
, WM_MOVE
, 0,
1389 MAKELONG(wndPtr
->rectClient
.left
, wndPtr
->rectClient
.top
) );
1393 WIN_ReleaseWndPtr(wndPtr
);
1398 /***********************************************************************
1399 * GetInternalWindowPos16 (USER.460)
1401 UINT16 WINAPI
GetInternalWindowPos16( HWND16 hwnd
, LPRECT16 rectWnd
,
1404 WINDOWPLACEMENT16 wndpl
;
1405 if (GetWindowPlacement16( hwnd
, &wndpl
))
1407 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
1408 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
1409 return wndpl
.showCmd
;
1415 /***********************************************************************
1416 * GetInternalWindowPos (USER32.245)
1418 UINT WINAPI
GetInternalWindowPos( HWND hwnd
, LPRECT rectWnd
,
1421 WINDOWPLACEMENT wndpl
;
1422 if (GetWindowPlacement( hwnd
, &wndpl
))
1424 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
1425 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
1426 return wndpl
.showCmd
;
1431 /***********************************************************************
1432 * GetWindowPlacement16 (USER.370)
1434 BOOL16 WINAPI
GetWindowPlacement16( HWND16 hwnd
, WINDOWPLACEMENT16
*wndpl
)
1436 WND
*pWnd
= WIN_FindWndPtr( hwnd
);
1437 LPINTERNALPOS lpPos
;
1439 if(!pWnd
) return FALSE
;
1441 lpPos
= (LPINTERNALPOS
)WINPOS_InitInternalPos( pWnd
,
1442 *(LPPOINT
)&pWnd
->rectWindow
.left
, &pWnd
->rectWindow
);
1443 wndpl
->length
= sizeof(*wndpl
);
1444 if( pWnd
->dwStyle
& WS_MINIMIZE
)
1445 wndpl
->showCmd
= SW_SHOWMINIMIZED
;
1447 wndpl
->showCmd
= ( pWnd
->dwStyle
& WS_MAXIMIZE
)
1448 ? SW_SHOWMAXIMIZED
: SW_SHOWNORMAL
;
1449 if( pWnd
->flags
& WIN_RESTORE_MAX
)
1450 wndpl
->flags
= WPF_RESTORETOMAXIMIZED
;
1453 wndpl
->ptMinPosition
= lpPos
->ptIconPos
;
1454 wndpl
->ptMaxPosition
= lpPos
->ptMaxPos
;
1455 wndpl
->rcNormalPosition
= lpPos
->rectNormal
;
1457 WIN_ReleaseWndPtr(pWnd
);
1462 /***********************************************************************
1463 * GetWindowPlacement (USER32.307)
1466 * Fails if wndpl->length of Win95 (!) apps is invalid.
1468 BOOL WINAPI
GetWindowPlacement( HWND hwnd
, WINDOWPLACEMENT
*pwpl32
)
1472 WINDOWPLACEMENT16 wpl
;
1473 wpl
.length
= sizeof(wpl
);
1474 if( GetWindowPlacement16( hwnd
, &wpl
) )
1476 pwpl32
->length
= sizeof(*pwpl32
);
1477 pwpl32
->flags
= wpl
.flags
;
1478 pwpl32
->showCmd
= wpl
.showCmd
;
1479 CONV_POINT16TO32( &wpl
.ptMinPosition
, &pwpl32
->ptMinPosition
);
1480 CONV_POINT16TO32( &wpl
.ptMaxPosition
, &pwpl32
->ptMaxPosition
);
1481 CONV_RECT16TO32( &wpl
.rcNormalPosition
, &pwpl32
->rcNormalPosition
);
1489 /***********************************************************************
1490 * WINPOS_SetPlacement
1492 static BOOL
WINPOS_SetPlacement( HWND hwnd
, const WINDOWPLACEMENT16
*wndpl
,
1495 WND
*pWnd
= WIN_FindWndPtr( hwnd
);
1498 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)WINPOS_InitInternalPos( pWnd
,
1499 *(LPPOINT
)&pWnd
->rectWindow
.left
, &pWnd
->rectWindow
);
1501 if( flags
& PLACE_MIN
) lpPos
->ptIconPos
= wndpl
->ptMinPosition
;
1502 if( flags
& PLACE_MAX
) lpPos
->ptMaxPos
= wndpl
->ptMaxPosition
;
1503 if( flags
& PLACE_RECT
) lpPos
->rectNormal
= wndpl
->rcNormalPosition
;
1505 if( pWnd
->dwStyle
& WS_MINIMIZE
)
1507 WINPOS_ShowIconTitle( pWnd
, FALSE
);
1508 if( wndpl
->flags
& WPF_SETMINPOSITION
&& !EMPTYPOINT(lpPos
->ptIconPos
))
1509 SetWindowPos( hwnd
, 0, lpPos
->ptIconPos
.x
, lpPos
->ptIconPos
.y
,
1510 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1512 else if( pWnd
->dwStyle
& WS_MAXIMIZE
)
1514 if( !EMPTYPOINT(lpPos
->ptMaxPos
) )
1515 SetWindowPos( hwnd
, 0, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
,
1516 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1518 else if( flags
& PLACE_RECT
)
1519 SetWindowPos( hwnd
, 0, lpPos
->rectNormal
.left
, lpPos
->rectNormal
.top
,
1520 lpPos
->rectNormal
.right
- lpPos
->rectNormal
.left
,
1521 lpPos
->rectNormal
.bottom
- lpPos
->rectNormal
.top
,
1522 SWP_NOZORDER
| SWP_NOACTIVATE
);
1524 ShowWindow( hwnd
, wndpl
->showCmd
);
1525 if( IsWindow(hwnd
) && pWnd
->dwStyle
& WS_MINIMIZE
)
1527 if( pWnd
->dwStyle
& WS_VISIBLE
) WINPOS_ShowIconTitle( pWnd
, TRUE
);
1529 /* SDK: ...valid only the next time... */
1530 if( wndpl
->flags
& WPF_RESTORETOMAXIMIZED
) pWnd
->flags
|= WIN_RESTORE_MAX
;
1532 WIN_ReleaseWndPtr(pWnd
);
1539 /***********************************************************************
1540 * SetWindowPlacement16 (USER.371)
1542 BOOL16 WINAPI
SetWindowPlacement16(HWND16 hwnd
, const WINDOWPLACEMENT16
*wndpl
)
1544 return WINPOS_SetPlacement( hwnd
, wndpl
,
1545 PLACE_MIN
| PLACE_MAX
| PLACE_RECT
);
1548 /***********************************************************************
1549 * SetWindowPlacement (USER32.519)
1552 * Fails if wndpl->length of Win95 (!) apps is invalid.
1554 BOOL WINAPI
SetWindowPlacement( HWND hwnd
, const WINDOWPLACEMENT
*pwpl32
)
1558 WINDOWPLACEMENT16 wpl
;
1560 wpl
.length
= sizeof(WINDOWPLACEMENT16
);
1561 wpl
.flags
= pwpl32
->flags
;
1562 wpl
.showCmd
= pwpl32
->showCmd
;
1563 wpl
.ptMinPosition
.x
= pwpl32
->ptMinPosition
.x
;
1564 wpl
.ptMinPosition
.y
= pwpl32
->ptMinPosition
.y
;
1565 wpl
.ptMaxPosition
.x
= pwpl32
->ptMaxPosition
.x
;
1566 wpl
.ptMaxPosition
.y
= pwpl32
->ptMaxPosition
.y
;
1567 wpl
.rcNormalPosition
.left
= pwpl32
->rcNormalPosition
.left
;
1568 wpl
.rcNormalPosition
.top
= pwpl32
->rcNormalPosition
.top
;
1569 wpl
.rcNormalPosition
.right
= pwpl32
->rcNormalPosition
.right
;
1570 wpl
.rcNormalPosition
.bottom
= pwpl32
->rcNormalPosition
.bottom
;
1572 return WINPOS_SetPlacement( hwnd
, &wpl
, PLACE_MIN
| PLACE_MAX
| PLACE_RECT
);
1578 /***********************************************************************
1579 * SetInternalWindowPos16 (USER.461)
1581 void WINAPI
SetInternalWindowPos16( HWND16 hwnd
, UINT16 showCmd
,
1582 LPRECT16 rect
, LPPOINT16 pt
)
1584 if( IsWindow16(hwnd
) )
1586 WINDOWPLACEMENT16 wndpl
;
1589 wndpl
.length
= sizeof(wndpl
);
1590 wndpl
.showCmd
= showCmd
;
1591 wndpl
.flags
= flags
= 0;
1596 wndpl
.flags
|= WPF_SETMINPOSITION
;
1597 wndpl
.ptMinPosition
= *pt
;
1601 flags
|= PLACE_RECT
;
1602 wndpl
.rcNormalPosition
= *rect
;
1604 WINPOS_SetPlacement( hwnd
, &wndpl
, flags
);
1609 /***********************************************************************
1610 * SetInternalWindowPos (USER32.483)
1612 void WINAPI
SetInternalWindowPos( HWND hwnd
, UINT showCmd
,
1613 LPRECT rect
, LPPOINT pt
)
1615 if( IsWindow(hwnd
) )
1617 WINDOWPLACEMENT16 wndpl
;
1620 wndpl
.length
= sizeof(wndpl
);
1621 wndpl
.showCmd
= showCmd
;
1622 wndpl
.flags
= flags
= 0;
1627 wndpl
.flags
|= WPF_SETMINPOSITION
;
1628 CONV_POINT32TO16( pt
, &wndpl
.ptMinPosition
);
1632 flags
|= PLACE_RECT
;
1633 CONV_RECT32TO16( rect
, &wndpl
.rcNormalPosition
);
1635 WINPOS_SetPlacement( hwnd
, &wndpl
, flags
);
1639 /*******************************************************************
1640 * WINPOS_SetActiveWindow
1642 * SetActiveWindow() back-end. This is the only function that
1643 * can assign active status to a window. It must be called only
1644 * for the top level windows.
1646 BOOL
WINPOS_SetActiveWindow( HWND hWnd
, BOOL fMouse
, BOOL fChangeFocus
)
1648 CBTACTIVATESTRUCT16
* cbtStruct
;
1649 WND
* wndPtr
=0, *wndTemp
;
1650 HQUEUE16 hOldActiveQueue
, hNewActiveQueue
;
1651 MESSAGEQUEUE
*pOldActiveQueue
= 0, *pNewActiveQueue
= 0;
1653 HWND hwndActive
= 0;
1656 TRACE("(%04x, %d, %d)\n", hWnd
, fMouse
, fChangeFocus
);
1658 /* Get current active window from the active queue */
1661 pOldActiveQueue
= QUEUE_Lock( hActiveQueue
);
1662 if ( pOldActiveQueue
)
1663 hwndActive
= PERQDATA_GetActiveWnd( pOldActiveQueue
->pQData
);
1666 /* paranoid checks */
1667 if( hWnd
== GetDesktopWindow() || (bRet
= (hWnd
== hwndActive
)) )
1670 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1673 wndPtr
= WIN_FindWndPtr(hWnd
);
1674 hOldActiveQueue
= hActiveQueue
;
1676 if( (wndTemp
= WIN_FindWndPtr(hwndActive
)) )
1678 wIconized
= HIWORD(wndTemp
->dwStyle
& WS_MINIMIZE
);
1679 WIN_ReleaseWndPtr(wndTemp
);
1682 TRACE("no current active window.\n");
1684 /* call CBT hook chain */
1685 if ((cbtStruct
= SEGPTR_NEW(CBTACTIVATESTRUCT16
)))
1687 cbtStruct
->fMouse
= fMouse
;
1688 cbtStruct
->hWndActive
= hwndActive
;
1689 bRet
= (BOOL
)HOOK_CallHooks16( WH_CBT
, HCBT_ACTIVATE
, (WPARAM16
)hWnd
,
1690 (LPARAM
)SEGPTR_GET(cbtStruct
) );
1691 SEGPTR_FREE(cbtStruct
);
1692 if (bRet
) goto CLEANUP_END
;
1695 /* set prev active wnd to current active wnd and send notification */
1696 if ((hwndPrevActive
= hwndActive
) && IsWindow(hwndPrevActive
))
1698 MESSAGEQUEUE
*pTempActiveQueue
= 0;
1700 if (!SendMessageA( hwndPrevActive
, WM_NCACTIVATE
, FALSE
, 0 ))
1702 if (GetSysModalWindow16() != hWnd
)
1704 /* disregard refusal if hWnd is sysmodal */
1707 SendMessageA( hwndPrevActive
, WM_ACTIVATE
,
1708 MAKEWPARAM( WA_INACTIVE
, wIconized
),
1711 /* check if something happened during message processing
1712 * (global active queue may have changed)
1714 pTempActiveQueue
= QUEUE_Lock( hActiveQueue
);
1715 if(!pTempActiveQueue
)
1718 hwndActive
= PERQDATA_GetActiveWnd( pTempActiveQueue
->pQData
);
1719 QUEUE_Unlock( pTempActiveQueue
);
1720 if( hwndPrevActive
!= hwndActive
)
1724 /* Set new active window in the message queue */
1728 pNewActiveQueue
= QUEUE_Lock( wndPtr
->hmemTaskQ
);
1729 if ( pNewActiveQueue
)
1730 PERQDATA_SetActiveWnd( pNewActiveQueue
->pQData
, hwndActive
);
1732 else /* have to do this or MDI frame activation goes to hell */
1733 if( pOldActiveQueue
)
1734 PERQDATA_SetActiveWnd( pOldActiveQueue
->pQData
, 0 );
1736 /* send palette messages */
1737 if (hWnd
&& SendMessage16( hWnd
, WM_QUERYNEWPALETTE
, 0, 0L))
1738 SendMessage16((HWND16
)-1, WM_PALETTEISCHANGING
, (WPARAM16
)hWnd
, 0L );
1740 /* if prev wnd is minimized redraw icon title */
1741 if( IsIconic( hwndPrevActive
) ) WINPOS_RedrawIconTitle(hwndPrevActive
);
1743 /* managed windows will get ConfigureNotify event */
1744 if (wndPtr
&& !(wndPtr
->dwStyle
& WS_CHILD
) && !(wndPtr
->flags
& WIN_MANAGED
))
1746 /* check Z-order and bring hWnd to the top */
1747 for (wndTemp
= WIN_LockWndPtr(WIN_GetDesktop()->child
); wndTemp
; WIN_UpdateWndPtr(&wndTemp
,wndTemp
->next
))
1749 if (wndTemp
->dwStyle
& WS_VISIBLE
) break;
1751 WIN_ReleaseDesktop();
1752 WIN_ReleaseWndPtr(wndTemp
);
1754 if( wndTemp
!= wndPtr
)
1755 SetWindowPos(hWnd
, HWND_TOP
, 0,0,0,0,
1756 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
1757 if (!IsWindow(hWnd
))
1761 /* Get a handle to the new active queue */
1762 hNewActiveQueue
= wndPtr
? wndPtr
->hmemTaskQ
: 0;
1764 /* send WM_ACTIVATEAPP if necessary */
1765 if (hOldActiveQueue
!= hNewActiveQueue
)
1767 WND
**list
, **ppWnd
;
1768 WND
*pDesktop
= WIN_GetDesktop();
1770 if ((list
= WIN_BuildWinArray( pDesktop
, 0, NULL
)))
1772 for (ppWnd
= list
; *ppWnd
; ppWnd
++)
1774 if (!IsWindow( (*ppWnd
)->hwndSelf
)) continue;
1776 if ((*ppWnd
)->hmemTaskQ
== hOldActiveQueue
)
1777 SendMessage16( (*ppWnd
)->hwndSelf
, WM_ACTIVATEAPP
,
1778 0, QUEUE_GetQueueTask(hNewActiveQueue
) );
1780 WIN_ReleaseWinArray(list
);
1783 hActiveQueue
= hNewActiveQueue
;
1785 if ((list
= WIN_BuildWinArray(pDesktop
, 0, NULL
)))
1787 for (ppWnd
= list
; *ppWnd
; ppWnd
++)
1789 if (!IsWindow( (*ppWnd
)->hwndSelf
)) continue;
1791 if ((*ppWnd
)->hmemTaskQ
== hNewActiveQueue
)
1792 SendMessage16( (*ppWnd
)->hwndSelf
, WM_ACTIVATEAPP
,
1793 1, QUEUE_GetQueueTask( hOldActiveQueue
) );
1795 WIN_ReleaseWinArray(list
);
1797 WIN_ReleaseDesktop();
1799 if (hWnd
&& !IsWindow(hWnd
)) goto CLEANUP
;
1804 /* walk up to the first unowned window */
1805 wndTemp
= WIN_LockWndPtr(wndPtr
);
1806 while (wndTemp
->owner
)
1808 WIN_UpdateWndPtr(&wndTemp
,wndTemp
->owner
);
1810 /* and set last active owned popup */
1811 wndTemp
->hwndLastActive
= hWnd
;
1813 wIconized
= HIWORD(wndTemp
->dwStyle
& WS_MINIMIZE
);
1814 WIN_ReleaseWndPtr(wndTemp
);
1815 SendMessageA( hWnd
, WM_NCACTIVATE
, TRUE
, 0 );
1816 SendMessageA( hWnd
, WM_ACTIVATE
,
1817 MAKEWPARAM( (fMouse
) ? WA_CLICKACTIVE
: WA_ACTIVE
, wIconized
),
1818 (LPARAM
)hwndPrevActive
);
1819 if( !IsWindow(hWnd
) ) goto CLEANUP
;
1822 /* change focus if possible */
1825 if ( pNewActiveQueue
)
1827 HWND hOldFocus
= PERQDATA_GetFocusWnd( pNewActiveQueue
->pQData
);
1829 if ( WIN_GetTopParent( hOldFocus
) != hwndActive
)
1830 FOCUS_SwitchFocus( pNewActiveQueue
, hOldFocus
,
1831 (wndPtr
&& (wndPtr
->dwStyle
& WS_MINIMIZE
))?
1835 if ( pOldActiveQueue
&&
1836 ( !pNewActiveQueue
||
1837 pNewActiveQueue
->pQData
!= pOldActiveQueue
->pQData
) )
1839 HWND hOldFocus
= PERQDATA_GetFocusWnd( pOldActiveQueue
->pQData
);
1841 FOCUS_SwitchFocus( pOldActiveQueue
, hOldFocus
, 0 );
1845 if( !hwndPrevActive
&& wndPtr
)
1846 (*wndPtr
->pDriver
->pForceWindowRaise
)(wndPtr
);
1848 /* if active wnd is minimized redraw icon title */
1849 if( IsIconic(hwndActive
) ) WINPOS_RedrawIconTitle(hwndActive
);
1851 bRet
= (hWnd
== hwndActive
); /* Success? */
1853 CLEANUP
: /* Unlock the message queues before returning */
1855 if ( pNewActiveQueue
)
1856 QUEUE_Unlock( pNewActiveQueue
);
1860 if ( pOldActiveQueue
)
1861 QUEUE_Unlock( pOldActiveQueue
);
1863 WIN_ReleaseWndPtr(wndPtr
);
1867 /*******************************************************************
1868 * WINPOS_ActivateOtherWindow
1870 * Activates window other than pWnd.
1872 BOOL
WINPOS_ActivateOtherWindow(WND
* pWnd
)
1876 HWND hwndActive
= 0;
1878 /* Get current active window from the active queue */
1881 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
1884 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
1885 QUEUE_Unlock( pActiveQueue
);
1889 if( pWnd
->hwndSelf
== hwndPrevActive
)
1892 if( hwndActive
!= pWnd
->hwndSelf
&&
1893 ( hwndActive
|| QUEUE_IsExitingQueue(pWnd
->hmemTaskQ
)) )
1896 if( !(pWnd
->dwStyle
& WS_POPUP
) || !(pWnd
->owner
) ||
1897 !WINPOS_CanActivate((pWndTo
= WIN_GetTopParentPtr(pWnd
->owner
))) )
1899 WND
* pWndPtr
= WIN_GetTopParentPtr(pWnd
);
1901 WIN_ReleaseWndPtr(pWndTo
);
1902 pWndTo
= WIN_FindWndPtr(hwndPrevActive
);
1904 while( !WINPOS_CanActivate(pWndTo
) )
1906 /* by now owned windows should've been taken care of */
1907 WIN_UpdateWndPtr(&pWndTo
,pWndPtr
->next
);
1908 WIN_UpdateWndPtr(&pWndPtr
,pWndTo
);
1909 if( !pWndTo
) break;
1911 WIN_ReleaseWndPtr(pWndPtr
);
1914 bRet
= WINPOS_SetActiveWindow( pWndTo
? pWndTo
->hwndSelf
: 0, FALSE
, TRUE
);
1916 /* switch desktop queue to current active */
1919 WIN_GetDesktop()->hmemTaskQ
= pWndTo
->hmemTaskQ
;
1920 WIN_ReleaseWndPtr(pWndTo
);
1921 WIN_ReleaseDesktop();
1928 /*******************************************************************
1929 * WINPOS_ChangeActiveWindow
1932 BOOL
WINPOS_ChangeActiveWindow( HWND hWnd
, BOOL mouseMsg
)
1934 WND
*wndPtr
, *wndTemp
;
1936 HWND hwndActive
= 0;
1938 /* Get current active window from the active queue */
1941 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
1944 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
1945 QUEUE_Unlock( pActiveQueue
);
1950 return WINPOS_SetActiveWindow( 0, mouseMsg
, TRUE
);
1952 wndPtr
= WIN_FindWndPtr(hWnd
);
1953 if( !wndPtr
) return FALSE
;
1955 /* child windows get WM_CHILDACTIVATE message */
1956 if( (wndPtr
->dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1958 retvalue
= SendMessageA(hWnd
, WM_CHILDACTIVATE
, 0, 0L);
1962 if( hWnd
== hwndActive
)
1968 if( !WINPOS_SetActiveWindow(hWnd
,mouseMsg
,TRUE
) )
1974 /* switch desktop queue to current active */
1975 wndTemp
= WIN_GetDesktop();
1976 if( wndPtr
->parent
== wndTemp
)
1977 wndTemp
->hmemTaskQ
= wndPtr
->hmemTaskQ
;
1978 WIN_ReleaseDesktop();
1982 WIN_ReleaseWndPtr(wndPtr
);
1987 /***********************************************************************
1988 * WINPOS_SendNCCalcSize
1990 * Send a WM_NCCALCSIZE message to a window.
1991 * All parameters are read-only except newClientRect.
1992 * oldWindowRect, oldClientRect and winpos must be non-NULL only
1993 * when calcValidRect is TRUE.
1995 LONG
WINPOS_SendNCCalcSize( HWND hwnd
, BOOL calcValidRect
,
1996 RECT
*newWindowRect
, RECT
*oldWindowRect
,
1997 RECT
*oldClientRect
, WINDOWPOS
*winpos
,
1998 RECT
*newClientRect
)
2000 NCCALCSIZE_PARAMS params
;
2001 WINDOWPOS winposCopy
;
2004 params
.rgrc
[0] = *newWindowRect
;
2007 winposCopy
= *winpos
;
2008 params
.rgrc
[1] = *oldWindowRect
;
2009 params
.rgrc
[2] = *oldClientRect
;
2010 params
.lppos
= &winposCopy
;
2012 result
= SendMessageA( hwnd
, WM_NCCALCSIZE
, calcValidRect
,
2014 TRACE("%d,%d-%d,%d\n",
2015 params
.rgrc
[0].left
, params
.rgrc
[0].top
,
2016 params
.rgrc
[0].right
, params
.rgrc
[0].bottom
);
2017 *newClientRect
= params
.rgrc
[0];
2022 /***********************************************************************
2023 * WINPOS_HandleWindowPosChanging16
2025 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2027 LONG
WINPOS_HandleWindowPosChanging16( WND
*wndPtr
, WINDOWPOS16
*winpos
)
2029 POINT maxSize
, minTrack
;
2030 if (winpos
->flags
& SWP_NOSIZE
) return 0;
2031 if ((wndPtr
->dwStyle
& WS_THICKFRAME
) ||
2032 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) == 0))
2034 WINPOS_GetMinMaxInfo( wndPtr
, &maxSize
, NULL
, &minTrack
, NULL
);
2035 if (maxSize
.x
< winpos
->cx
) winpos
->cx
= maxSize
.x
;
2036 if (maxSize
.y
< winpos
->cy
) winpos
->cy
= maxSize
.y
;
2037 if (!(wndPtr
->dwStyle
& WS_MINIMIZE
))
2039 if (winpos
->cx
< minTrack
.x
) winpos
->cx
= minTrack
.x
;
2040 if (winpos
->cy
< minTrack
.y
) winpos
->cy
= minTrack
.y
;
2047 /***********************************************************************
2048 * WINPOS_HandleWindowPosChanging
2050 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2052 LONG
WINPOS_HandleWindowPosChanging( WND
*wndPtr
, WINDOWPOS
*winpos
)
2055 if (winpos
->flags
& SWP_NOSIZE
) return 0;
2056 if ((wndPtr
->dwStyle
& WS_THICKFRAME
) ||
2057 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) == 0))
2059 WINPOS_GetMinMaxInfo( wndPtr
, &maxSize
, NULL
, NULL
, NULL
);
2060 winpos
->cx
= MIN( winpos
->cx
, maxSize
.x
);
2061 winpos
->cy
= MIN( winpos
->cy
, maxSize
.y
);
2066 /***********************************************************************
2069 * fix Z order taking into account owned popups -
2070 * basically we need to maintain them above the window that owns them
2072 * FIXME: hide/show owned popups when owner visibility changes.
2074 static HWND
SWP_DoOwnedPopups(WND
* pDesktop
, WND
* wndPtr
, HWND hwndInsertAfter
, WORD flags
)
2076 WND
* w
= WIN_LockWndPtr(pDesktop
->child
);
2078 WARN("(%04x) hInsertAfter = %04x\n", wndPtr
->hwndSelf
, hwndInsertAfter
);
2080 if( (wndPtr
->dwStyle
& WS_POPUP
) && wndPtr
->owner
)
2082 /* make sure this popup stays above the owner */
2084 HWND hwndLocalPrev
= HWND_TOP
;
2086 if( hwndInsertAfter
!= HWND_TOP
)
2088 while( w
!= wndPtr
->owner
)
2090 if (w
!= wndPtr
) hwndLocalPrev
= w
->hwndSelf
;
2091 if( hwndLocalPrev
== hwndInsertAfter
) break;
2092 WIN_UpdateWndPtr(&w
,w
->next
);
2094 hwndInsertAfter
= hwndLocalPrev
;
2097 else if( wndPtr
->dwStyle
& WS_CHILD
)
2100 WIN_UpdateWndPtr(&w
, pDesktop
->child
);
2104 if( w
== wndPtr
) break;
2106 if( (w
->dwStyle
& WS_POPUP
) && w
->owner
== wndPtr
)
2108 SetWindowPos(w
->hwndSelf
, hwndInsertAfter
, 0, 0, 0, 0,
2109 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOSENDCHANGING
| SWP_DEFERERASE
);
2110 hwndInsertAfter
= w
->hwndSelf
;
2112 WIN_UpdateWndPtr(&w
, w
->next
);
2116 WIN_ReleaseWndPtr(w
);
2117 return hwndInsertAfter
;
2120 /***********************************************************************
2123 * Make window look nice without excessive repainting
2125 * visible and update regions are in window coordinates
2126 * client and window rectangles are in parent client coordinates
2128 * FIXME: SWP_EX_PAINTSELF in uFlags works only if both old and new
2129 * window rects have the same origin.
2131 * Returns: uFlags and a dirty region in *pVisRgn.
2133 static UINT
SWP_CopyValidBits( WND
* Wnd
, HRGN
* pVisRgn
,
2134 LPRECT lpOldWndRect
,
2135 LPRECT lpOldClientRect
, UINT uFlags
)
2138 HRGN newVisRgn
, dirtyRgn
;
2139 INT my
= COMPLEXREGION
;
2141 TRACE("\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2142 Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
,
2143 Wnd
->rectWindow
.right
, Wnd
->rectWindow
.bottom
,
2144 lpOldWndRect
->left
, lpOldWndRect
->top
,
2145 lpOldWndRect
->right
, lpOldWndRect
->bottom
, *pVisRgn
);
2146 TRACE("\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2147 Wnd
->rectClient
.left
, Wnd
->rectClient
.top
,
2148 Wnd
->rectClient
.right
, Wnd
->rectClient
.bottom
,
2149 lpOldClientRect
->left
, lpOldClientRect
->top
,
2150 lpOldClientRect
->right
,lpOldClientRect
->bottom
);
2152 if( Wnd
->hrgnUpdate
== 1 )
2153 uFlags
|= SWP_EX_NOCOPY
; /* whole window is invalid, nothing to copy */
2155 newVisRgn
= DCE_GetVisRgn( Wnd
->hwndSelf
, DCX_WINDOW
| DCX_CLIPSIBLINGS
, 0, 0);
2156 dirtyRgn
= CreateRectRgn( 0, 0, 0, 0 );
2158 if( !(uFlags
& SWP_EX_NOCOPY
) ) /* make sure dst region covers only valid bits */
2159 my
= CombineRgn( dirtyRgn
, newVisRgn
, *pVisRgn
, RGN_AND
);
2161 if( (my
== NULLREGION
) || (uFlags
& SWP_EX_NOCOPY
) )
2165 TRACE("\twon't copy anything!\n");
2167 /* set dirtyRgn to the sum of old and new visible regions
2168 * in parent client coordinates */
2170 OffsetRgn( newVisRgn
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2171 OffsetRgn( *pVisRgn
, lpOldWndRect
->left
, lpOldWndRect
->top
);
2173 CombineRgn(*pVisRgn
, *pVisRgn
, newVisRgn
, RGN_OR
);
2175 else /* copy valid bits to a new location */
2177 INT dx
, dy
, ow
, oh
, nw
, nh
, ocw
, ncw
, och
, nch
;
2178 HRGN hrgnValid
= dirtyRgn
; /* non-empty intersection of old and new visible rgns */
2180 /* subtract already invalid region inside Wnd from the dst region */
2182 if( Wnd
->hrgnUpdate
)
2183 if( CombineRgn( hrgnValid
, hrgnValid
, Wnd
->hrgnUpdate
, RGN_DIFF
) == NULLREGION
)
2186 /* check if entire window can be copied */
2188 ow
= lpOldWndRect
->right
- lpOldWndRect
->left
;
2189 oh
= lpOldWndRect
->bottom
- lpOldWndRect
->top
;
2190 nw
= Wnd
->rectWindow
.right
- Wnd
->rectWindow
.left
;
2191 nh
= Wnd
->rectWindow
.bottom
- Wnd
->rectWindow
.top
;
2193 ocw
= lpOldClientRect
->right
- lpOldClientRect
->left
;
2194 och
= lpOldClientRect
->bottom
- lpOldClientRect
->top
;
2195 ncw
= Wnd
->rectClient
.right
- Wnd
->rectClient
.left
;
2196 nch
= Wnd
->rectClient
.bottom
- Wnd
->rectClient
.top
;
2198 if( (ocw
!= ncw
) || (och
!= nch
) ||
2199 ( ow
!= nw
) || ( oh
!= nh
) ||
2200 ((lpOldClientRect
->top
- lpOldWndRect
->top
) !=
2201 (Wnd
->rectClient
.top
- Wnd
->rectWindow
.top
)) ||
2202 ((lpOldClientRect
->left
- lpOldWndRect
->left
) !=
2203 (Wnd
->rectClient
.left
- Wnd
->rectWindow
.left
)) )
2205 dx
= Wnd
->rectClient
.left
- lpOldClientRect
->left
;
2206 dy
= Wnd
->rectClient
.top
- lpOldClientRect
->top
;
2208 /* restrict valid bits to the common client rect */
2210 r
.left
= Wnd
->rectClient
.left
- Wnd
->rectWindow
.left
;
2211 r
.top
= Wnd
->rectClient
.top
- Wnd
->rectWindow
.top
;
2212 r
.right
= r
.left
+ MIN( ocw
, ncw
);
2213 r
.bottom
= r
.top
+ MIN( och
, nch
);
2215 REGION_CropRgn( hrgnValid
, hrgnValid
, &r
,
2216 (uFlags
& SWP_EX_PAINTSELF
) ? NULL
: (POINT
*)&(Wnd
->rectWindow
));
2217 GetRgnBox( hrgnValid
, &r
);
2218 if( IsRectEmpty( &r
) )
2220 r
= *lpOldClientRect
;
2224 dx
= Wnd
->rectWindow
.left
- lpOldWndRect
->left
;
2225 dy
= Wnd
->rectWindow
.top
- lpOldWndRect
->top
;
2226 if( !(uFlags
& SWP_EX_PAINTSELF
) )
2227 OffsetRgn( hrgnValid
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2231 if( !(uFlags
& SWP_EX_PAINTSELF
) )
2233 /* Move remaining regions to parent coordinates */
2234 OffsetRgn( newVisRgn
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2235 OffsetRgn( *pVisRgn
, lpOldWndRect
->left
, lpOldWndRect
->top
);
2238 OffsetRect( &r
, -lpOldWndRect
->left
, -lpOldWndRect
->top
);
2240 TRACE("\tcomputing dirty region!\n");
2242 /* Compute combined dirty region (old + new - valid) */
2243 CombineRgn( *pVisRgn
, *pVisRgn
, newVisRgn
, RGN_OR
);
2244 CombineRgn( *pVisRgn
, *pVisRgn
, hrgnValid
, RGN_DIFF
);
2246 /* Blt valid bits, r is the rect to copy */
2254 /* get DC and clip rect with drawable rect to avoid superfluous expose events
2255 from copying clipped areas */
2257 if( uFlags
& SWP_EX_PAINTSELF
)
2259 hDC
= GetDCEx( Wnd
->hwndSelf
, hrgnValid
, DCX_WINDOW
| DCX_CACHE
|
2260 DCX_KEEPCLIPRGN
| DCX_INTERSECTRGN
| DCX_CLIPSIBLINGS
);
2261 rClip
.right
= nw
; rClip
.bottom
= nh
;
2265 hDC
= GetDCEx( Wnd
->parent
->hwndSelf
, hrgnValid
, DCX_CACHE
|
2266 DCX_KEEPCLIPRGN
| DCX_INTERSECTRGN
| DCX_CLIPSIBLINGS
);
2267 rClip
.right
= Wnd
->parent
->rectClient
.right
- Wnd
->parent
->rectClient
.left
;
2268 rClip
.bottom
= Wnd
->parent
->rectClient
.bottom
- Wnd
->parent
->rectClient
.top
;
2270 rClip
.left
= rClip
.top
= 0;
2272 if( (dc
= (DC
*)GDI_GetObjPtr(hDC
, DC_MAGIC
)) )
2274 if( oh
> nh
) r
.bottom
= r
.top
+ nh
;
2275 if( ow
< nw
) r
.right
= r
.left
+ nw
;
2277 if( IntersectRect( &r
, &r
, &rClip
) )
2278 Wnd
->pDriver
->pSurfaceCopy( Wnd
->parent
, dc
, dx
, dy
, &r
, TRUE
);
2280 GDI_HEAP_UNLOCK( hDC
);
2282 ReleaseDC( (uFlags
& SWP_EX_PAINTSELF
) ?
2283 Wnd
->hwndSelf
: Wnd
->parent
->hwndSelf
, hDC
);
2287 /* *pVisRgn now points to the invalidated region */
2289 DeleteObject(newVisRgn
);
2290 DeleteObject(dirtyRgn
);
2294 /***********************************************************************
2295 * SWP_DoSimpleFrameChanged
2297 * NOTE: old and new client rect origins are identical, only
2298 * extents may have changed. Window extents are the same.
2300 static void SWP_DoSimpleFrameChanged( WND
* wndPtr
, RECT
* pOldClientRect
, WORD swpFlags
, UINT uFlags
)
2306 if( !(swpFlags
& SWP_NOCLIENTSIZE
) )
2308 /* Client rect changed its position/size, most likely a scrollar
2309 * was added/removed.
2311 * FIXME: WVR alignment flags
2314 if( wndPtr
->rectClient
.right
> pOldClientRect
->right
) /* right edge */
2318 rect
.bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
2319 rect
.right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
2320 if(!(uFlags
& SWP_EX_NOCOPY
))
2321 rect
.left
= pOldClientRect
->right
- wndPtr
->rectClient
.left
;
2329 if( wndPtr
->rectClient
.bottom
> pOldClientRect
->bottom
) /* bottom edge */
2332 hrgn
= CreateRectRgnIndirect( &rect
);
2334 rect
.right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
2335 rect
.bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
2336 if(!(uFlags
& SWP_EX_NOCOPY
))
2337 rect
.top
= pOldClientRect
->bottom
- wndPtr
->rectClient
.top
;
2341 REGION_UnionRectWithRgn( hrgn
, &rect
);
2344 if( i
== 0 && (uFlags
& SWP_EX_NOCOPY
) ) /* force redraw anyway */
2346 rect
= wndPtr
->rectWindow
;
2347 OffsetRect( &rect
, wndPtr
->rectWindow
.left
- wndPtr
->rectClient
.left
,
2348 wndPtr
->rectWindow
.top
- wndPtr
->rectClient
.top
);
2356 PAINT_RedrawWindow( wndPtr
->hwndSelf
, &rect
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
|
2357 RDW_ERASENOW
| RDW_ALLCHILDREN
, RDW_EX_TOPFRAME
| RDW_EX_USEHRGN
);
2361 WIN_UpdateNCRgn(wndPtr
, 0, UNC_UPDATE
| UNC_ENTIRE
);
2365 DeleteObject( hrgn
);
2368 /***********************************************************************
2369 * SWP_DoWinPosChanging
2371 static BOOL
SWP_DoWinPosChanging( WND
* wndPtr
, WINDOWPOS
* pWinpos
,
2372 RECT
* pNewWindowRect
, RECT
* pNewClientRect
)
2374 /* Send WM_WINDOWPOSCHANGING message */
2376 if (!(pWinpos
->flags
& SWP_NOSENDCHANGING
))
2377 SendMessageA( wndPtr
->hwndSelf
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
)pWinpos
);
2379 /* Calculate new position and size */
2381 *pNewWindowRect
= wndPtr
->rectWindow
;
2382 *pNewClientRect
= (wndPtr
->dwStyle
& WS_MINIMIZE
) ? wndPtr
->rectWindow
2383 : wndPtr
->rectClient
;
2385 if (!(pWinpos
->flags
& SWP_NOSIZE
))
2387 pNewWindowRect
->right
= pNewWindowRect
->left
+ pWinpos
->cx
;
2388 pNewWindowRect
->bottom
= pNewWindowRect
->top
+ pWinpos
->cy
;
2390 if (!(pWinpos
->flags
& SWP_NOMOVE
))
2392 pNewWindowRect
->left
= pWinpos
->x
;
2393 pNewWindowRect
->top
= pWinpos
->y
;
2394 pNewWindowRect
->right
+= pWinpos
->x
- wndPtr
->rectWindow
.left
;
2395 pNewWindowRect
->bottom
+= pWinpos
->y
- wndPtr
->rectWindow
.top
;
2397 OffsetRect( pNewClientRect
, pWinpos
->x
- wndPtr
->rectWindow
.left
,
2398 pWinpos
->y
- wndPtr
->rectWindow
.top
);
2401 pWinpos
->flags
|= SWP_NOCLIENTMOVE
| SWP_NOCLIENTSIZE
;
2405 /***********************************************************************
2408 static UINT
SWP_DoNCCalcSize( WND
* wndPtr
, WINDOWPOS
* pWinpos
,
2409 RECT
* pNewWindowRect
, RECT
* pNewClientRect
, WORD f
)
2413 /* Send WM_NCCALCSIZE message to get new client area */
2414 if( (pWinpos
->flags
& (SWP_FRAMECHANGED
| SWP_NOSIZE
)) != SWP_NOSIZE
)
2416 wvrFlags
= WINPOS_SendNCCalcSize( pWinpos
->hwnd
, TRUE
, pNewWindowRect
,
2417 &wndPtr
->rectWindow
, &wndPtr
->rectClient
,
2418 pWinpos
, pNewClientRect
);
2420 /* FIXME: WVR_ALIGNxxx */
2422 if( pNewClientRect
->left
!= wndPtr
->rectClient
.left
||
2423 pNewClientRect
->top
!= wndPtr
->rectClient
.top
)
2424 pWinpos
->flags
&= ~SWP_NOCLIENTMOVE
;
2426 if( (pNewClientRect
->right
- pNewClientRect
->left
!=
2427 wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
) ||
2428 (pNewClientRect
->bottom
- pNewClientRect
->top
!=
2429 wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
) )
2430 pWinpos
->flags
&= ~SWP_NOCLIENTSIZE
;
2433 if( !(f
& SWP_NOMOVE
) && (pNewClientRect
->left
!= wndPtr
->rectClient
.left
||
2434 pNewClientRect
->top
!= wndPtr
->rectClient
.top
) )
2435 pWinpos
->flags
&= ~SWP_NOCLIENTMOVE
;
2439 /***********************************************************************
2440 * SetWindowPos (USER.2)
2442 BOOL16 WINAPI
SetWindowPos16( HWND16 hwnd
, HWND16 hwndInsertAfter
,
2443 INT16 x
, INT16 y
, INT16 cx
, INT16 cy
, WORD flags
)
2445 return SetWindowPos(hwnd
,(INT
)(INT16
)hwndInsertAfter
,x
,y
,cx
,cy
,flags
);
2448 /***********************************************************************
2449 * SetWindowPos (USER32.520)
2451 BOOL WINAPI
SetWindowPos( HWND hwnd
, HWND hwndInsertAfter
,
2452 INT x
, INT y
, INT cx
, INT cy
, UINT flags
)
2455 WND
* wndPtr
,*wndTemp
;
2456 RECT newWindowRect
, newClientRect
;
2457 RECT oldWindowRect
, oldClientRect
;
2459 UINT wvrFlags
= 0, uFlags
= 0;
2460 BOOL retvalue
, resync
= FALSE
, bChangePos
;
2461 HWND hwndActive
= 0;
2463 /* Get current active window from the active queue */
2466 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
2469 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
2470 QUEUE_Unlock( pActiveQueue
);
2474 TRACE("hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2475 hwnd
, x
, y
, x
+cx
, y
+cy
, flags
);
2477 bChangePos
= !(flags
& SWP_WINE_NOHOSTMOVE
);
2478 flags
&= ~SWP_WINE_NOHOSTMOVE
;
2481 /* ------------------------------------------------------------------------ CHECKS */
2483 /* Check window handle */
2485 if (hwnd
== GetDesktopWindow()) return FALSE
;
2486 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return FALSE
;
2488 TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr
->rectWindow
.left
, wndPtr
->rectWindow
.top
,
2489 wndPtr
->rectWindow
.right
, wndPtr
->rectWindow
.bottom
, (unsigned)wndPtr
->dwStyle
);
2491 /* Fix redundant flags */
2493 if(wndPtr
->dwStyle
& WS_VISIBLE
)
2494 flags
&= ~SWP_SHOWWINDOW
;
2497 if (!(flags
& SWP_SHOWWINDOW
))
2498 flags
|= SWP_NOREDRAW
;
2499 flags
&= ~SWP_HIDEWINDOW
;
2502 if ( cx
< 0 ) cx
= 0; if( cy
< 0 ) cy
= 0;
2504 if ((wndPtr
->rectWindow
.right
- wndPtr
->rectWindow
.left
== cx
) &&
2505 (wndPtr
->rectWindow
.bottom
- wndPtr
->rectWindow
.top
== cy
))
2506 flags
|= SWP_NOSIZE
; /* Already the right size */
2508 if ((wndPtr
->rectWindow
.left
== x
) && (wndPtr
->rectWindow
.top
== y
))
2509 flags
|= SWP_NOMOVE
; /* Already the right position */
2511 if (hwnd
== hwndActive
)
2512 flags
|= SWP_NOACTIVATE
; /* Already active */
2513 else if ( (wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)
2515 if(!(flags
& SWP_NOACTIVATE
)) /* Bring to the top when activating */
2517 flags
&= ~SWP_NOZORDER
;
2518 hwndInsertAfter
= HWND_TOP
;
2523 /* Check hwndInsertAfter */
2525 /* FIXME: TOPMOST not supported yet */
2526 if ((hwndInsertAfter
== HWND_TOPMOST
) ||
2527 (hwndInsertAfter
== HWND_NOTOPMOST
)) hwndInsertAfter
= HWND_TOP
;
2529 /* hwndInsertAfter must be a sibling of the window */
2530 if ((hwndInsertAfter
!= HWND_TOP
) && (hwndInsertAfter
!= HWND_BOTTOM
))
2532 WND
* wnd
= WIN_FindWndPtr(hwndInsertAfter
);
2535 if( wnd
->parent
!= wndPtr
->parent
)
2538 WIN_ReleaseWndPtr(wnd
);
2541 if( wnd
->next
== wndPtr
) flags
|= SWP_NOZORDER
;
2543 WIN_ReleaseWndPtr(wnd
);
2546 Pos
: /* ------------------------------------------------------------------------ MAIN part */
2548 /* Fill the WINDOWPOS structure */
2551 winpos
.hwndInsertAfter
= hwndInsertAfter
;
2556 winpos
.flags
= flags
;
2558 SWP_DoWinPosChanging( wndPtr
, &winpos
, &newWindowRect
, &newClientRect
);
2560 if((winpos
.flags
& (SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) != SWP_NOZORDER
)
2562 if( wndPtr
->parent
== WIN_GetDesktop() )
2563 hwndInsertAfter
= SWP_DoOwnedPopups( wndPtr
->parent
, wndPtr
,
2564 hwndInsertAfter
, winpos
.flags
);
2565 WIN_ReleaseDesktop();
2568 if(!(wndPtr
->flags
& WIN_NATIVE
) )
2570 if( hwndInsertAfter
== HWND_TOP
)
2571 winpos
.flags
|= ( wndPtr
->parent
->child
== wndPtr
)? SWP_NOZORDER
: 0;
2573 if( hwndInsertAfter
== HWND_BOTTOM
)
2574 winpos
.flags
|= ( wndPtr
->next
)? 0: SWP_NOZORDER
;
2576 if( !(winpos
.flags
& SWP_NOZORDER
) )
2577 if( GetWindow(hwndInsertAfter
, GW_HWNDNEXT
) == wndPtr
->hwndSelf
)
2578 winpos
.flags
|= SWP_NOZORDER
;
2580 if( !(winpos
.flags
& (SWP_NOREDRAW
| SWP_SHOWWINDOW
)) &&
2581 ((winpos
.flags
& (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_FRAMECHANGED
))
2582 != (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
)) )
2584 /* get a previous visible region for SWP_CopyValidBits() */
2586 visRgn
= DCE_GetVisRgn(hwnd
, DCX_WINDOW
| DCX_CLIPSIBLINGS
, 0, 0);
2590 /* Common operations */
2592 wvrFlags
= SWP_DoNCCalcSize( wndPtr
, &winpos
, &newWindowRect
, &newClientRect
, flags
);
2594 if(!(winpos
.flags
& SWP_NOZORDER
))
2596 if ( WIN_UnlinkWindow( winpos
.hwnd
) )
2597 WIN_LinkWindow( winpos
.hwnd
, hwndInsertAfter
);
2600 /* Reset active DCEs */
2602 if( (((winpos
.flags
& SWP_AGG_NOPOSCHANGE
) != SWP_AGG_NOPOSCHANGE
) &&
2603 wndPtr
->dwStyle
& WS_VISIBLE
) ||
2604 (flags
& (SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) )
2608 UnionRect(&rect
, &newWindowRect
, &wndPtr
->rectWindow
);
2609 DCE_InvalidateDCE(wndPtr
, &rect
);
2612 oldWindowRect
= wndPtr
->rectWindow
;
2613 oldClientRect
= wndPtr
->rectClient
;
2615 /* Find out if we have to redraw the whole client rect */
2617 if( oldClientRect
.bottom
- oldClientRect
.top
==
2618 newClientRect
.bottom
- newClientRect
.top
) wvrFlags
&= ~WVR_VREDRAW
;
2620 if( oldClientRect
.right
- oldClientRect
.left
==
2621 newClientRect
.right
- newClientRect
.left
) wvrFlags
&= ~WVR_HREDRAW
;
2623 if( (winpos
.flags
& SWP_NOCOPYBITS
) || (!(winpos
.flags
& SWP_NOCLIENTSIZE
) &&
2624 (wvrFlags
>= WVR_HREDRAW
) && (wvrFlags
< WVR_VALIDRECTS
)) )
2626 uFlags
|= SWP_EX_NOCOPY
;
2629 * Use this later in CopyValidBits()
2632 uFlags |= SWP_EX_NONCLIENT;
2635 /* FIXME: actually do something with WVR_VALIDRECTS */
2637 wndPtr
->rectWindow
= newWindowRect
;
2638 wndPtr
->rectClient
= newClientRect
;
2640 if (wndPtr
->flags
& WIN_NATIVE
) /* -------------------------------------------- hosted window */
2642 BOOL bCallDriver
= TRUE
;
2643 HWND tempInsertAfter
= winpos
.hwndInsertAfter
;
2645 winpos
.hwndInsertAfter
= hwndInsertAfter
;
2647 if( !(winpos
.flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
| SWP_NOREDRAW
)) )
2649 /* This is the only place where we need to force repainting of the contents
2650 of windows created by the host window system, all other cases go through the
2651 expose event handling */
2653 if( (winpos
.flags
& (SWP_NOSIZE
| SWP_FRAMECHANGED
)) == (SWP_NOSIZE
| SWP_FRAMECHANGED
) )
2655 cx
= newWindowRect
.right
- newWindowRect
.left
;
2656 cy
= newWindowRect
.bottom
- newWindowRect
.top
;
2658 wndPtr
->pDriver
->pSetWindowPos(wndPtr
, &winpos
, bChangePos
);
2659 winpos
.hwndInsertAfter
= tempInsertAfter
;
2660 bCallDriver
= FALSE
;
2662 if( winpos
.flags
& SWP_NOCLIENTMOVE
)
2663 SWP_DoSimpleFrameChanged(wndPtr
, &oldClientRect
, winpos
.flags
, uFlags
);
2666 /* client area moved but window extents remained the same, copy valid bits */
2668 visRgn
= CreateRectRgn( 0, 0, cx
, cy
);
2669 uFlags
= SWP_CopyValidBits( wndPtr
, &visRgn
, &oldWindowRect
, &oldClientRect
,
2670 uFlags
| SWP_EX_PAINTSELF
);
2677 if( !(winpos
.flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
| SWP_NOREDRAW
)) )
2679 if( (oldClientRect
.left
- oldWindowRect
.left
== newClientRect
.left
- newWindowRect
.left
) &&
2680 (oldClientRect
.top
- oldWindowRect
.top
== newClientRect
.top
- newWindowRect
.top
) &&
2681 !(uFlags
& SWP_EX_NOCOPY
) )
2683 /* The origin of the client rect didn't move so we can try to repaint
2684 * only the nonclient area by setting bit gravity hint for the host window system.
2687 if( !(wndPtr
->flags
& WIN_MANAGED
) )
2689 HRGN hrgn
= CreateRectRgn( 0, 0, newWindowRect
.right
- newWindowRect
.left
,
2690 newWindowRect
.bottom
- newWindowRect
.top
);
2691 RECT rcn
= newClientRect
;
2692 RECT rco
= oldClientRect
;
2694 OffsetRect( &rcn
, -newWindowRect
.left
, -newWindowRect
.top
);
2695 OffsetRect( &rco
, -oldWindowRect
.left
, -oldWindowRect
.top
);
2696 IntersectRect( &rcn
, &rcn
, &rco
);
2697 visRgn
= CreateRectRgnIndirect( &rcn
);
2698 CombineRgn( visRgn
, hrgn
, visRgn
, RGN_DIFF
);
2699 DeleteObject( hrgn
);
2700 uFlags
= SWP_EX_PAINTSELF
;
2702 wndPtr
->pDriver
->pSetHostAttr(wndPtr
, HAK_BITGRAVITY
, BGNorthWest
);
2705 wndPtr
->pDriver
->pSetHostAttr(wndPtr
, HAK_BITGRAVITY
, BGForget
);
2708 wndPtr
->pDriver
->pSetWindowPos(wndPtr
, &winpos
, bChangePos
);
2709 winpos
.hwndInsertAfter
= tempInsertAfter
;
2712 if( winpos
.flags
& SWP_SHOWWINDOW
)
2716 wndPtr
->dwStyle
|= WS_VISIBLE
;
2718 if (wndPtr
->flags
& WIN_MANAGED
) resync
= TRUE
;
2720 /* focus was set to unmapped window, reset host focus
2721 * since the window is now visible */
2723 focus
= curr
= GetFocus();
2728 WND
*pFocus
= WIN_FindWndPtr( focus
);
2730 pFocus
->pDriver
->pSetFocus(pFocus
);
2731 WIN_ReleaseWndPtr(pFocus
);
2734 curr
= GetParent(curr
);
2738 else /* -------------------------------------------- emulated window */
2740 if( winpos
.flags
& SWP_SHOWWINDOW
)
2742 wndPtr
->dwStyle
|= WS_VISIBLE
;
2743 uFlags
|= SWP_EX_PAINTSELF
;
2744 visRgn
= 1; /* redraw the whole window */
2746 else if( !(winpos
.flags
& SWP_NOREDRAW
) )
2748 if( winpos
.flags
& SWP_HIDEWINDOW
)
2750 if( visRgn
> 1 ) /* map to parent */
2751 OffsetRgn( visRgn
, oldWindowRect
.left
, oldWindowRect
.top
);
2757 if( (winpos
.flags
& SWP_AGG_NOPOSCHANGE
) != SWP_AGG_NOPOSCHANGE
)
2758 uFlags
= SWP_CopyValidBits(wndPtr
, &visRgn
, &oldWindowRect
,
2759 &oldClientRect
, uFlags
);
2762 /* nothing moved, redraw frame if needed */
2764 if( winpos
.flags
& SWP_FRAMECHANGED
)
2765 SWP_DoSimpleFrameChanged( wndPtr
, &oldClientRect
, winpos
.flags
, uFlags
);
2768 DeleteObject( visRgn
);
2776 if( winpos
.flags
& SWP_HIDEWINDOW
)
2778 wndPtr
->dwStyle
&= ~WS_VISIBLE
;
2780 if (hwnd
== CARET_GetHwnd()) DestroyCaret();
2782 /* FIXME: This will cause the window to be activated irrespective
2783 * of whether it is owned by the same thread. Has to be done
2787 if (winpos
.hwnd
== hwndActive
)
2788 WINPOS_ActivateOtherWindow( wndPtr
);
2791 /* ------------------------------------------------------------------------ FINAL */
2793 if (wndPtr
->flags
& WIN_NATIVE
)
2794 EVENT_Synchronize(); /* Synchronize with the host window system */
2796 if (!GetCapture() && ((wndPtr
->dwStyle
& WS_VISIBLE
) || (flags
& SWP_HIDEWINDOW
)))
2798 /* Simulate a mouse event to set the cursor */
2799 DWORD posX
, posY
, keyState
;
2801 if ( EVENT_QueryPointer( &posX
, &posY
, &keyState
) )
2803 int iWndsLocks
= WIN_SuspendWndsLock();
2805 hardware_event( WM_MOUSEMOVE
, keyState
, 0,
2806 posX
, posY
, GetTickCount(), 0 );
2808 WIN_RestoreWndsLock(iWndsLocks
);
2812 wndTemp
= WIN_GetDesktop();
2814 /* repaint invalidated region (if any)
2816 * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2817 * and force update after ChangeActiveWindow() to avoid painting frames twice.
2822 if( !(winpos
.flags
& SWP_NOREDRAW
) )
2824 if (wndPtr
->parent
== wndTemp
)
2826 /* Desktop does not receive wm_paint message so we use RDW_ERASENOW to erase the
2827 the desktop window */
2829 if( uFlags
& SWP_EX_PAINTSELF
)
2831 PAINT_RedrawWindow( wndPtr
->hwndSelf
, NULL
, (visRgn
== 1) ? 0 : visRgn
, RDW_ERASE
| RDW_FRAME
|
2832 ((winpos
.flags
& SWP_DEFERERASE
) ? 0 : RDW_ERASENOW
) | RDW_INVALIDATE
|
2833 RDW_ALLCHILDREN
, RDW_EX_XYWINDOW
| RDW_EX_USEHRGN
);
2837 PAINT_RedrawWindow( wndPtr
->parent
->hwndSelf
, NULL
, (visRgn
== 1) ? 0 : visRgn
,
2838 RDW_ERASE
| RDW_ERASENOW
| RDW_INVALIDATE
| RDW_ALLCHILDREN
, RDW_EX_USEHRGN
);
2843 if( uFlags
& SWP_EX_PAINTSELF
)
2845 /* Use PAINT_RedrawWindow to explicitly force an invalidation of the window,
2846 its parent and sibling and so on, and then update the parent window,
2847 the non-top-level window. Rely on the system to repaint other affected
2848 windows later on. */
2850 PAINT_RedrawWindow( wndPtr
->hwndSelf
, NULL
, (visRgn
== 1) ? 0 : visRgn
, RDW_ERASE
|
2851 RDW_FRAME
| RDW_INVALIDATE
| RDW_ALLCHILDREN
, RDW_EX_XYWINDOW
| RDW_EX_USEHRGN
);
2855 PAINT_RedrawWindow( wndPtr
->parent
->hwndSelf
, NULL
, (visRgn
== 1) ? 0 : visRgn
,
2856 RDW_ERASE
| RDW_INVALIDATE
| RDW_ALLCHILDREN
, RDW_EX_USEHRGN
);
2858 UpdateWindow( wndPtr
->parent
->hwndSelf
);
2863 DeleteObject( visRgn
);
2866 WIN_ReleaseDesktop();
2868 if (!(flags
& SWP_NOACTIVATE
))
2869 WINPOS_ChangeActiveWindow( winpos
.hwnd
, FALSE
);
2871 /* And last, send the WM_WINDOWPOSCHANGED message */
2873 TRACE("\tstatus flags = %04x\n", winpos
.flags
& SWP_AGG_STATUSFLAGS
);
2876 (((winpos
.flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOPOSCHANGE
) &&
2877 !(winpos
.flags
& SWP_NOSENDCHANGING
)) )
2879 SendMessageA( winpos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
)&winpos
);
2880 if (resync
) EVENT_Synchronize();
2885 WIN_ReleaseWndPtr(wndPtr
);
2890 /***********************************************************************
2891 * BeginDeferWindowPos16 (USER.259)
2893 HDWP16 WINAPI
BeginDeferWindowPos16( INT16 count
)
2895 return BeginDeferWindowPos( count
);
2899 /***********************************************************************
2900 * BeginDeferWindowPos (USER32.9)
2902 HDWP WINAPI
BeginDeferWindowPos( INT count
)
2907 if (count
<= 0) return 0;
2908 handle
= USER_HEAP_ALLOC( sizeof(DWP
) + (count
-1)*sizeof(WINDOWPOS
) );
2909 if (!handle
) return 0;
2910 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( handle
);
2911 pDWP
->actualCount
= 0;
2912 pDWP
->suggestedCount
= count
;
2914 pDWP
->wMagic
= DWP_MAGIC
;
2915 pDWP
->hwndParent
= 0;
2920 /***********************************************************************
2921 * DeferWindowPos16 (USER.260)
2923 HDWP16 WINAPI
DeferWindowPos16( HDWP16 hdwp
, HWND16 hwnd
, HWND16 hwndAfter
,
2924 INT16 x
, INT16 y
, INT16 cx
, INT16 cy
,
2927 return DeferWindowPos( hdwp
, hwnd
, (INT
)(INT16
)hwndAfter
,
2928 x
, y
, cx
, cy
, flags
);
2932 /***********************************************************************
2933 * DeferWindowPos (USER32.128)
2935 HDWP WINAPI
DeferWindowPos( HDWP hdwp
, HWND hwnd
, HWND hwndAfter
,
2936 INT x
, INT y
, INT cx
, INT cy
,
2941 HDWP newhdwp
= hdwp
,retvalue
;
2945 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
2946 if (!pDWP
) return 0;
2947 if (hwnd
== GetDesktopWindow()) return 0;
2949 if (!(pWnd
=WIN_FindWndPtr( hwnd
))) {
2950 USER_HEAP_FREE( hdwp
);
2954 /* Numega Bounds Checker Demo dislikes the following code.
2955 In fact, I've not been able to find any "same parent" requirement in any docu
2959 /* All the windows of a DeferWindowPos() must have the same parent */
2960 parent
= pWnd
->parent
->hwndSelf
;
2961 if (pDWP
->actualCount
== 0) pDWP
->hwndParent
= parent
;
2962 else if (parent
!= pDWP
->hwndParent
)
2964 USER_HEAP_FREE( hdwp
);
2970 for (i
= 0; i
< pDWP
->actualCount
; i
++)
2972 if (pDWP
->winPos
[i
].hwnd
== hwnd
)
2974 /* Merge with the other changes */
2975 if (!(flags
& SWP_NOZORDER
))
2977 pDWP
->winPos
[i
].hwndInsertAfter
= hwndAfter
;
2979 if (!(flags
& SWP_NOMOVE
))
2981 pDWP
->winPos
[i
].x
= x
;
2982 pDWP
->winPos
[i
].y
= y
;
2984 if (!(flags
& SWP_NOSIZE
))
2986 pDWP
->winPos
[i
].cx
= cx
;
2987 pDWP
->winPos
[i
].cy
= cy
;
2989 pDWP
->winPos
[i
].flags
&= flags
| ~(SWP_NOSIZE
| SWP_NOMOVE
|
2990 SWP_NOZORDER
| SWP_NOREDRAW
|
2991 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
2993 pDWP
->winPos
[i
].flags
|= flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
|
2999 if (pDWP
->actualCount
>= pDWP
->suggestedCount
)
3001 newhdwp
= USER_HEAP_REALLOC( hdwp
,
3002 sizeof(DWP
) + pDWP
->suggestedCount
*sizeof(WINDOWPOS
) );
3008 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( newhdwp
);
3009 pDWP
->suggestedCount
++;
3011 pDWP
->winPos
[pDWP
->actualCount
].hwnd
= hwnd
;
3012 pDWP
->winPos
[pDWP
->actualCount
].hwndInsertAfter
= hwndAfter
;
3013 pDWP
->winPos
[pDWP
->actualCount
].x
= x
;
3014 pDWP
->winPos
[pDWP
->actualCount
].y
= y
;
3015 pDWP
->winPos
[pDWP
->actualCount
].cx
= cx
;
3016 pDWP
->winPos
[pDWP
->actualCount
].cy
= cy
;
3017 pDWP
->winPos
[pDWP
->actualCount
].flags
= flags
;
3018 pDWP
->actualCount
++;
3021 WIN_ReleaseWndPtr(pWnd
);
3026 /***********************************************************************
3027 * EndDeferWindowPos16 (USER.261)
3029 BOOL16 WINAPI
EndDeferWindowPos16( HDWP16 hdwp
)
3031 return EndDeferWindowPos( hdwp
);
3035 /***********************************************************************
3036 * EndDeferWindowPos (USER32.173)
3038 BOOL WINAPI
EndDeferWindowPos( HDWP hdwp
)
3045 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
3046 if (!pDWP
) return FALSE
;
3047 for (i
= 0, winpos
= pDWP
->winPos
; i
< pDWP
->actualCount
; i
++, winpos
++)
3049 if (!(res
= SetWindowPos( winpos
->hwnd
, winpos
->hwndInsertAfter
,
3050 winpos
->x
, winpos
->y
, winpos
->cx
,
3051 winpos
->cy
, winpos
->flags
))) break;
3053 USER_HEAP_FREE( hdwp
);
3058 /***********************************************************************
3059 * TileChildWindows (USER.199)
3061 void WINAPI
TileChildWindows16( HWND16 parent
, WORD action
)
3063 FIXME("(%04x, %d): stub\n", parent
, action
);
3066 /***********************************************************************
3067 * CascageChildWindows (USER.198)
3069 void WINAPI
CascadeChildWindows16( HWND16 parent
, WORD action
)
3071 FIXME("(%04x, %d): stub\n", parent
, action
);
3074 /***********************************************************************
3075 * SetProgmanWindow [USER32.522]
3077 HRESULT WINAPI
SetProgmanWindow ( HWND hwnd
)
3079 hGlobalProgmanWindow
= hwnd
;
3080 return hGlobalProgmanWindow
;
3083 /***********************************************************************
3084 * GetProgmanWindow [USER32.289]
3086 HRESULT WINAPI
GetProgmanWindow ( )
3088 return hGlobalProgmanWindow
;
3091 /***********************************************************************
3092 * SetShellWindowEx [USER32.531]
3093 * hwndProgman = Progman[Program Manager]
3094 * |-> SHELLDLL_DefView
3095 * hwndListView = | |-> SysListView32
3096 * | | |-> tooltips_class32
3102 HRESULT WINAPI
SetShellWindowEx ( HWND hwndProgman
, HWND hwndListView
)
3104 FIXME("0x%08x 0x%08x stub\n",hwndProgman
,hwndListView
);
3105 hGlobalShellWindow
= hwndProgman
;
3106 return hGlobalShellWindow
;
3110 /***********************************************************************
3111 * SetTaskmanWindow [USER32.537]
3113 * hwnd = MSTaskSwWClass
3114 * |-> SysTabControl32
3116 HRESULT WINAPI
SetTaskmanWindow ( HWND hwnd
)
3118 hGlobalTaskmanWindow
= hwnd
;
3119 return hGlobalTaskmanWindow
;
3122 /***********************************************************************
3123 * GetTaskmanWindow [USER32.304]
3125 HRESULT WINAPI
GetTaskmanWindow ( )
3127 return hGlobalTaskmanWindow
;