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 * ShowWindow has a little peculiar behavior that if the
1337 * window is already the topmost window, it will not
1340 if (GetTopWindow((HWND
)0)==hwnd
)
1341 swp
|= SWP_NOACTIVATE
;
1345 case SW_SHOWNOACTIVATE
:
1346 swp
|= SWP_NOZORDER
;
1347 if (GetActiveWindow()) swp
|= SWP_NOACTIVATE
;
1349 case SW_SHOWNORMAL
: /* same as SW_NORMAL: */
1350 case SW_SHOWDEFAULT
: /* FIXME: should have its own handler */
1352 swp
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
1354 if( wndPtr
->dwStyle
& (WS_MINIMIZE
| WS_MAXIMIZE
) )
1355 swp
|= WINPOS_MinMaximize( wndPtr
, SW_RESTORE
, &newPos
);
1356 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1360 showFlag
= (cmd
!= SW_HIDE
);
1361 if (showFlag
!= wasVisible
)
1363 SendMessageA( hwnd
, WM_SHOWWINDOW
, showFlag
, 0 );
1364 if (!IsWindow( hwnd
)) goto END
;
1367 if ((wndPtr
->dwStyle
& WS_CHILD
) &&
1368 !IsWindowVisible( wndPtr
->parent
->hwndSelf
) &&
1369 (swp
& (SWP_NOSIZE
| SWP_NOMOVE
)) == (SWP_NOSIZE
| SWP_NOMOVE
) )
1371 /* Don't call SetWindowPos() on invisible child windows */
1372 if (cmd
== SW_HIDE
) wndPtr
->dwStyle
&= ~WS_VISIBLE
;
1373 else wndPtr
->dwStyle
|= WS_VISIBLE
;
1377 /* We can't activate a child window */
1378 if (wndPtr
->dwStyle
& WS_CHILD
) swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1379 if (!(swp
& MINMAX_NOSWP
))
1380 SetWindowPos( hwnd
, HWND_TOP
, newPos
.left
, newPos
.top
,
1381 newPos
.right
, newPos
.bottom
, LOWORD(swp
) );
1382 if (!IsWindow( hwnd
)) goto END
;
1383 else if( wndPtr
->dwStyle
& WS_MINIMIZE
) WINPOS_ShowIconTitle( wndPtr
, TRUE
);
1386 if (wndPtr
->flags
& WIN_NEED_SIZE
)
1388 /* should happen only in CreateWindowEx() */
1389 int wParam
= SIZE_RESTORED
;
1391 wndPtr
->flags
&= ~WIN_NEED_SIZE
;
1392 if (wndPtr
->dwStyle
& WS_MAXIMIZE
) wParam
= SIZE_MAXIMIZED
;
1393 else if (wndPtr
->dwStyle
& WS_MINIMIZE
) wParam
= SIZE_MINIMIZED
;
1394 SendMessageA( hwnd
, WM_SIZE
, wParam
,
1395 MAKELONG(wndPtr
->rectClient
.right
-wndPtr
->rectClient
.left
,
1396 wndPtr
->rectClient
.bottom
-wndPtr
->rectClient
.top
));
1397 SendMessageA( hwnd
, WM_MOVE
, 0,
1398 MAKELONG(wndPtr
->rectClient
.left
, wndPtr
->rectClient
.top
) );
1402 WIN_ReleaseWndPtr(wndPtr
);
1407 /***********************************************************************
1408 * GetInternalWindowPos16 (USER.460)
1410 UINT16 WINAPI
GetInternalWindowPos16( HWND16 hwnd
, LPRECT16 rectWnd
,
1413 WINDOWPLACEMENT16 wndpl
;
1414 if (GetWindowPlacement16( hwnd
, &wndpl
))
1416 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
1417 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
1418 return wndpl
.showCmd
;
1424 /***********************************************************************
1425 * GetInternalWindowPos (USER32.245)
1427 UINT WINAPI
GetInternalWindowPos( HWND hwnd
, LPRECT rectWnd
,
1430 WINDOWPLACEMENT wndpl
;
1431 if (GetWindowPlacement( hwnd
, &wndpl
))
1433 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
1434 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
1435 return wndpl
.showCmd
;
1440 /***********************************************************************
1441 * GetWindowPlacement16 (USER.370)
1443 BOOL16 WINAPI
GetWindowPlacement16( HWND16 hwnd
, WINDOWPLACEMENT16
*wndpl
)
1445 WND
*pWnd
= WIN_FindWndPtr( hwnd
);
1446 LPINTERNALPOS lpPos
;
1448 if(!pWnd
) return FALSE
;
1450 lpPos
= (LPINTERNALPOS
)WINPOS_InitInternalPos( pWnd
,
1451 *(LPPOINT
)&pWnd
->rectWindow
.left
, &pWnd
->rectWindow
);
1452 wndpl
->length
= sizeof(*wndpl
);
1453 if( pWnd
->dwStyle
& WS_MINIMIZE
)
1454 wndpl
->showCmd
= SW_SHOWMINIMIZED
;
1456 wndpl
->showCmd
= ( pWnd
->dwStyle
& WS_MAXIMIZE
)
1457 ? SW_SHOWMAXIMIZED
: SW_SHOWNORMAL
;
1458 if( pWnd
->flags
& WIN_RESTORE_MAX
)
1459 wndpl
->flags
= WPF_RESTORETOMAXIMIZED
;
1462 wndpl
->ptMinPosition
= lpPos
->ptIconPos
;
1463 wndpl
->ptMaxPosition
= lpPos
->ptMaxPos
;
1464 wndpl
->rcNormalPosition
= lpPos
->rectNormal
;
1466 WIN_ReleaseWndPtr(pWnd
);
1471 /***********************************************************************
1472 * GetWindowPlacement (USER32.307)
1475 * Fails if wndpl->length of Win95 (!) apps is invalid.
1477 BOOL WINAPI
GetWindowPlacement( HWND hwnd
, WINDOWPLACEMENT
*pwpl32
)
1481 WINDOWPLACEMENT16 wpl
;
1482 wpl
.length
= sizeof(wpl
);
1483 if( GetWindowPlacement16( hwnd
, &wpl
) )
1485 pwpl32
->length
= sizeof(*pwpl32
);
1486 pwpl32
->flags
= wpl
.flags
;
1487 pwpl32
->showCmd
= wpl
.showCmd
;
1488 CONV_POINT16TO32( &wpl
.ptMinPosition
, &pwpl32
->ptMinPosition
);
1489 CONV_POINT16TO32( &wpl
.ptMaxPosition
, &pwpl32
->ptMaxPosition
);
1490 CONV_RECT16TO32( &wpl
.rcNormalPosition
, &pwpl32
->rcNormalPosition
);
1498 /***********************************************************************
1499 * WINPOS_SetPlacement
1501 static BOOL
WINPOS_SetPlacement( HWND hwnd
, const WINDOWPLACEMENT16
*wndpl
,
1504 WND
*pWnd
= WIN_FindWndPtr( hwnd
);
1507 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)WINPOS_InitInternalPos( pWnd
,
1508 *(LPPOINT
)&pWnd
->rectWindow
.left
, &pWnd
->rectWindow
);
1510 if( flags
& PLACE_MIN
) lpPos
->ptIconPos
= wndpl
->ptMinPosition
;
1511 if( flags
& PLACE_MAX
) lpPos
->ptMaxPos
= wndpl
->ptMaxPosition
;
1512 if( flags
& PLACE_RECT
) lpPos
->rectNormal
= wndpl
->rcNormalPosition
;
1514 if( pWnd
->dwStyle
& WS_MINIMIZE
)
1516 WINPOS_ShowIconTitle( pWnd
, FALSE
);
1517 if( wndpl
->flags
& WPF_SETMINPOSITION
&& !EMPTYPOINT(lpPos
->ptIconPos
))
1518 SetWindowPos( hwnd
, 0, lpPos
->ptIconPos
.x
, lpPos
->ptIconPos
.y
,
1519 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1521 else if( pWnd
->dwStyle
& WS_MAXIMIZE
)
1523 if( !EMPTYPOINT(lpPos
->ptMaxPos
) )
1524 SetWindowPos( hwnd
, 0, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
,
1525 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1527 else if( flags
& PLACE_RECT
)
1528 SetWindowPos( hwnd
, 0, lpPos
->rectNormal
.left
, lpPos
->rectNormal
.top
,
1529 lpPos
->rectNormal
.right
- lpPos
->rectNormal
.left
,
1530 lpPos
->rectNormal
.bottom
- lpPos
->rectNormal
.top
,
1531 SWP_NOZORDER
| SWP_NOACTIVATE
);
1533 ShowWindow( hwnd
, wndpl
->showCmd
);
1534 if( IsWindow(hwnd
) && pWnd
->dwStyle
& WS_MINIMIZE
)
1536 if( pWnd
->dwStyle
& WS_VISIBLE
) WINPOS_ShowIconTitle( pWnd
, TRUE
);
1538 /* SDK: ...valid only the next time... */
1539 if( wndpl
->flags
& WPF_RESTORETOMAXIMIZED
) pWnd
->flags
|= WIN_RESTORE_MAX
;
1541 WIN_ReleaseWndPtr(pWnd
);
1548 /***********************************************************************
1549 * SetWindowPlacement16 (USER.371)
1551 BOOL16 WINAPI
SetWindowPlacement16(HWND16 hwnd
, const WINDOWPLACEMENT16
*wndpl
)
1553 return WINPOS_SetPlacement( hwnd
, wndpl
,
1554 PLACE_MIN
| PLACE_MAX
| PLACE_RECT
);
1557 /***********************************************************************
1558 * SetWindowPlacement (USER32.519)
1561 * Fails if wndpl->length of Win95 (!) apps is invalid.
1563 BOOL WINAPI
SetWindowPlacement( HWND hwnd
, const WINDOWPLACEMENT
*pwpl32
)
1567 WINDOWPLACEMENT16 wpl
;
1569 wpl
.length
= sizeof(WINDOWPLACEMENT16
);
1570 wpl
.flags
= pwpl32
->flags
;
1571 wpl
.showCmd
= pwpl32
->showCmd
;
1572 wpl
.ptMinPosition
.x
= pwpl32
->ptMinPosition
.x
;
1573 wpl
.ptMinPosition
.y
= pwpl32
->ptMinPosition
.y
;
1574 wpl
.ptMaxPosition
.x
= pwpl32
->ptMaxPosition
.x
;
1575 wpl
.ptMaxPosition
.y
= pwpl32
->ptMaxPosition
.y
;
1576 wpl
.rcNormalPosition
.left
= pwpl32
->rcNormalPosition
.left
;
1577 wpl
.rcNormalPosition
.top
= pwpl32
->rcNormalPosition
.top
;
1578 wpl
.rcNormalPosition
.right
= pwpl32
->rcNormalPosition
.right
;
1579 wpl
.rcNormalPosition
.bottom
= pwpl32
->rcNormalPosition
.bottom
;
1581 return WINPOS_SetPlacement( hwnd
, &wpl
, PLACE_MIN
| PLACE_MAX
| PLACE_RECT
);
1587 /***********************************************************************
1588 * SetInternalWindowPos16 (USER.461)
1590 void WINAPI
SetInternalWindowPos16( HWND16 hwnd
, UINT16 showCmd
,
1591 LPRECT16 rect
, LPPOINT16 pt
)
1593 if( IsWindow16(hwnd
) )
1595 WINDOWPLACEMENT16 wndpl
;
1598 wndpl
.length
= sizeof(wndpl
);
1599 wndpl
.showCmd
= showCmd
;
1600 wndpl
.flags
= flags
= 0;
1605 wndpl
.flags
|= WPF_SETMINPOSITION
;
1606 wndpl
.ptMinPosition
= *pt
;
1610 flags
|= PLACE_RECT
;
1611 wndpl
.rcNormalPosition
= *rect
;
1613 WINPOS_SetPlacement( hwnd
, &wndpl
, flags
);
1618 /***********************************************************************
1619 * SetInternalWindowPos (USER32.483)
1621 void WINAPI
SetInternalWindowPos( HWND hwnd
, UINT showCmd
,
1622 LPRECT rect
, LPPOINT pt
)
1624 if( IsWindow(hwnd
) )
1626 WINDOWPLACEMENT16 wndpl
;
1629 wndpl
.length
= sizeof(wndpl
);
1630 wndpl
.showCmd
= showCmd
;
1631 wndpl
.flags
= flags
= 0;
1636 wndpl
.flags
|= WPF_SETMINPOSITION
;
1637 CONV_POINT32TO16( pt
, &wndpl
.ptMinPosition
);
1641 flags
|= PLACE_RECT
;
1642 CONV_RECT32TO16( rect
, &wndpl
.rcNormalPosition
);
1644 WINPOS_SetPlacement( hwnd
, &wndpl
, flags
);
1648 /*******************************************************************
1649 * WINPOS_SetActiveWindow
1651 * SetActiveWindow() back-end. This is the only function that
1652 * can assign active status to a window. It must be called only
1653 * for the top level windows.
1655 BOOL
WINPOS_SetActiveWindow( HWND hWnd
, BOOL fMouse
, BOOL fChangeFocus
)
1657 CBTACTIVATESTRUCT16
* cbtStruct
;
1658 WND
* wndPtr
=0, *wndTemp
;
1659 HQUEUE16 hOldActiveQueue
, hNewActiveQueue
;
1660 MESSAGEQUEUE
*pOldActiveQueue
= 0, *pNewActiveQueue
= 0;
1662 HWND hwndActive
= 0;
1665 TRACE("(%04x, %d, %d)\n", hWnd
, fMouse
, fChangeFocus
);
1667 /* Get current active window from the active queue */
1670 pOldActiveQueue
= QUEUE_Lock( hActiveQueue
);
1671 if ( pOldActiveQueue
)
1672 hwndActive
= PERQDATA_GetActiveWnd( pOldActiveQueue
->pQData
);
1675 /* paranoid checks */
1676 if( hWnd
== GetDesktopWindow() || (bRet
= (hWnd
== hwndActive
)) )
1679 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1682 wndPtr
= WIN_FindWndPtr(hWnd
);
1683 hOldActiveQueue
= hActiveQueue
;
1685 if( (wndTemp
= WIN_FindWndPtr(hwndActive
)) )
1687 wIconized
= HIWORD(wndTemp
->dwStyle
& WS_MINIMIZE
);
1688 WIN_ReleaseWndPtr(wndTemp
);
1691 TRACE("no current active window.\n");
1693 /* call CBT hook chain */
1694 if ((cbtStruct
= SEGPTR_NEW(CBTACTIVATESTRUCT16
)))
1696 cbtStruct
->fMouse
= fMouse
;
1697 cbtStruct
->hWndActive
= hwndActive
;
1698 bRet
= (BOOL
)HOOK_CallHooks16( WH_CBT
, HCBT_ACTIVATE
, (WPARAM16
)hWnd
,
1699 (LPARAM
)SEGPTR_GET(cbtStruct
) );
1700 SEGPTR_FREE(cbtStruct
);
1701 if (bRet
) goto CLEANUP_END
;
1704 /* set prev active wnd to current active wnd and send notification */
1705 if ((hwndPrevActive
= hwndActive
) && IsWindow(hwndPrevActive
))
1707 MESSAGEQUEUE
*pTempActiveQueue
= 0;
1709 if (!SendMessageA( hwndPrevActive
, WM_NCACTIVATE
, FALSE
, 0 ))
1711 if (GetSysModalWindow16() != hWnd
)
1713 /* disregard refusal if hWnd is sysmodal */
1716 SendMessageA( hwndPrevActive
, WM_ACTIVATE
,
1717 MAKEWPARAM( WA_INACTIVE
, wIconized
),
1720 /* check if something happened during message processing
1721 * (global active queue may have changed)
1723 pTempActiveQueue
= QUEUE_Lock( hActiveQueue
);
1724 if(!pTempActiveQueue
)
1727 hwndActive
= PERQDATA_GetActiveWnd( pTempActiveQueue
->pQData
);
1728 QUEUE_Unlock( pTempActiveQueue
);
1729 if( hwndPrevActive
!= hwndActive
)
1733 /* Set new active window in the message queue */
1737 pNewActiveQueue
= QUEUE_Lock( wndPtr
->hmemTaskQ
);
1738 if ( pNewActiveQueue
)
1739 PERQDATA_SetActiveWnd( pNewActiveQueue
->pQData
, hwndActive
);
1741 else /* have to do this or MDI frame activation goes to hell */
1742 if( pOldActiveQueue
)
1743 PERQDATA_SetActiveWnd( pOldActiveQueue
->pQData
, 0 );
1745 /* send palette messages */
1746 if (hWnd
&& SendMessage16( hWnd
, WM_QUERYNEWPALETTE
, 0, 0L))
1747 SendMessage16((HWND16
)-1, WM_PALETTEISCHANGING
, (WPARAM16
)hWnd
, 0L );
1749 /* if prev wnd is minimized redraw icon title */
1750 if( IsIconic( hwndPrevActive
) ) WINPOS_RedrawIconTitle(hwndPrevActive
);
1752 /* managed windows will get ConfigureNotify event */
1753 if (wndPtr
&& !(wndPtr
->dwStyle
& WS_CHILD
) && !(wndPtr
->flags
& WIN_MANAGED
))
1755 /* check Z-order and bring hWnd to the top */
1756 for (wndTemp
= WIN_LockWndPtr(WIN_GetDesktop()->child
); wndTemp
; WIN_UpdateWndPtr(&wndTemp
,wndTemp
->next
))
1758 if (wndTemp
->dwStyle
& WS_VISIBLE
) break;
1760 WIN_ReleaseDesktop();
1761 WIN_ReleaseWndPtr(wndTemp
);
1763 if( wndTemp
!= wndPtr
)
1764 SetWindowPos(hWnd
, HWND_TOP
, 0,0,0,0,
1765 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
1766 if (!IsWindow(hWnd
))
1770 /* Get a handle to the new active queue */
1771 hNewActiveQueue
= wndPtr
? wndPtr
->hmemTaskQ
: 0;
1773 /* send WM_ACTIVATEAPP if necessary */
1774 if (hOldActiveQueue
!= hNewActiveQueue
)
1776 WND
**list
, **ppWnd
;
1777 WND
*pDesktop
= WIN_GetDesktop();
1779 if ((list
= WIN_BuildWinArray( pDesktop
, 0, NULL
)))
1781 for (ppWnd
= list
; *ppWnd
; ppWnd
++)
1783 if (!IsWindow( (*ppWnd
)->hwndSelf
)) continue;
1785 if ((*ppWnd
)->hmemTaskQ
== hOldActiveQueue
)
1786 SendMessage16( (*ppWnd
)->hwndSelf
, WM_ACTIVATEAPP
,
1787 0, QUEUE_GetQueueTask(hNewActiveQueue
) );
1789 WIN_ReleaseWinArray(list
);
1792 hActiveQueue
= hNewActiveQueue
;
1794 if ((list
= WIN_BuildWinArray(pDesktop
, 0, NULL
)))
1796 for (ppWnd
= list
; *ppWnd
; ppWnd
++)
1798 if (!IsWindow( (*ppWnd
)->hwndSelf
)) continue;
1800 if ((*ppWnd
)->hmemTaskQ
== hNewActiveQueue
)
1801 SendMessage16( (*ppWnd
)->hwndSelf
, WM_ACTIVATEAPP
,
1802 1, QUEUE_GetQueueTask( hOldActiveQueue
) );
1804 WIN_ReleaseWinArray(list
);
1806 WIN_ReleaseDesktop();
1808 if (hWnd
&& !IsWindow(hWnd
)) goto CLEANUP
;
1813 /* walk up to the first unowned window */
1814 wndTemp
= WIN_LockWndPtr(wndPtr
);
1815 while (wndTemp
->owner
)
1817 WIN_UpdateWndPtr(&wndTemp
,wndTemp
->owner
);
1819 /* and set last active owned popup */
1820 wndTemp
->hwndLastActive
= hWnd
;
1822 wIconized
= HIWORD(wndTemp
->dwStyle
& WS_MINIMIZE
);
1823 WIN_ReleaseWndPtr(wndTemp
);
1824 SendMessageA( hWnd
, WM_NCACTIVATE
, TRUE
, 0 );
1825 SendMessageA( hWnd
, WM_ACTIVATE
,
1826 MAKEWPARAM( (fMouse
) ? WA_CLICKACTIVE
: WA_ACTIVE
, wIconized
),
1827 (LPARAM
)hwndPrevActive
);
1828 if( !IsWindow(hWnd
) ) goto CLEANUP
;
1831 /* change focus if possible */
1834 if ( pNewActiveQueue
)
1836 HWND hOldFocus
= PERQDATA_GetFocusWnd( pNewActiveQueue
->pQData
);
1838 if ( WIN_GetTopParent( hOldFocus
) != hwndActive
)
1839 FOCUS_SwitchFocus( pNewActiveQueue
, hOldFocus
,
1840 (wndPtr
&& (wndPtr
->dwStyle
& WS_MINIMIZE
))?
1844 if ( pOldActiveQueue
&&
1845 ( !pNewActiveQueue
||
1846 pNewActiveQueue
->pQData
!= pOldActiveQueue
->pQData
) )
1848 HWND hOldFocus
= PERQDATA_GetFocusWnd( pOldActiveQueue
->pQData
);
1850 FOCUS_SwitchFocus( pOldActiveQueue
, hOldFocus
, 0 );
1854 if( !hwndPrevActive
&& wndPtr
)
1855 (*wndPtr
->pDriver
->pForceWindowRaise
)(wndPtr
);
1857 /* if active wnd is minimized redraw icon title */
1858 if( IsIconic(hwndActive
) ) WINPOS_RedrawIconTitle(hwndActive
);
1860 bRet
= (hWnd
== hwndActive
); /* Success? */
1862 CLEANUP
: /* Unlock the message queues before returning */
1864 if ( pNewActiveQueue
)
1865 QUEUE_Unlock( pNewActiveQueue
);
1869 if ( pOldActiveQueue
)
1870 QUEUE_Unlock( pOldActiveQueue
);
1872 WIN_ReleaseWndPtr(wndPtr
);
1876 /*******************************************************************
1877 * WINPOS_ActivateOtherWindow
1879 * Activates window other than pWnd.
1881 BOOL
WINPOS_ActivateOtherWindow(WND
* pWnd
)
1885 HWND hwndActive
= 0;
1887 /* Get current active window from the active queue */
1890 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
1893 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
1894 QUEUE_Unlock( pActiveQueue
);
1898 if( pWnd
->hwndSelf
== hwndPrevActive
)
1901 if( hwndActive
!= pWnd
->hwndSelf
&&
1902 ( hwndActive
|| QUEUE_IsExitingQueue(pWnd
->hmemTaskQ
)) )
1905 if( !(pWnd
->dwStyle
& WS_POPUP
) || !(pWnd
->owner
) ||
1906 !WINPOS_CanActivate((pWndTo
= WIN_GetTopParentPtr(pWnd
->owner
))) )
1908 WND
* pWndPtr
= WIN_GetTopParentPtr(pWnd
);
1910 WIN_ReleaseWndPtr(pWndTo
);
1911 pWndTo
= WIN_FindWndPtr(hwndPrevActive
);
1913 while( !WINPOS_CanActivate(pWndTo
) )
1915 /* by now owned windows should've been taken care of */
1916 WIN_UpdateWndPtr(&pWndTo
,pWndPtr
->next
);
1917 WIN_UpdateWndPtr(&pWndPtr
,pWndTo
);
1918 if( !pWndTo
) break;
1920 WIN_ReleaseWndPtr(pWndPtr
);
1923 bRet
= WINPOS_SetActiveWindow( pWndTo
? pWndTo
->hwndSelf
: 0, FALSE
, TRUE
);
1925 /* switch desktop queue to current active */
1928 WIN_GetDesktop()->hmemTaskQ
= pWndTo
->hmemTaskQ
;
1929 WIN_ReleaseWndPtr(pWndTo
);
1930 WIN_ReleaseDesktop();
1937 /*******************************************************************
1938 * WINPOS_ChangeActiveWindow
1941 BOOL
WINPOS_ChangeActiveWindow( HWND hWnd
, BOOL mouseMsg
)
1943 WND
*wndPtr
, *wndTemp
;
1945 HWND hwndActive
= 0;
1947 /* Get current active window from the active queue */
1950 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
1953 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
1954 QUEUE_Unlock( pActiveQueue
);
1959 return WINPOS_SetActiveWindow( 0, mouseMsg
, TRUE
);
1961 wndPtr
= WIN_FindWndPtr(hWnd
);
1962 if( !wndPtr
) return FALSE
;
1964 /* child windows get WM_CHILDACTIVATE message */
1965 if( (wndPtr
->dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1967 retvalue
= SendMessageA(hWnd
, WM_CHILDACTIVATE
, 0, 0L);
1971 if( hWnd
== hwndActive
)
1977 if( !WINPOS_SetActiveWindow(hWnd
,mouseMsg
,TRUE
) )
1983 /* switch desktop queue to current active */
1984 wndTemp
= WIN_GetDesktop();
1985 if( wndPtr
->parent
== wndTemp
)
1986 wndTemp
->hmemTaskQ
= wndPtr
->hmemTaskQ
;
1987 WIN_ReleaseDesktop();
1991 WIN_ReleaseWndPtr(wndPtr
);
1996 /***********************************************************************
1997 * WINPOS_SendNCCalcSize
1999 * Send a WM_NCCALCSIZE message to a window.
2000 * All parameters are read-only except newClientRect.
2001 * oldWindowRect, oldClientRect and winpos must be non-NULL only
2002 * when calcValidRect is TRUE.
2004 LONG
WINPOS_SendNCCalcSize( HWND hwnd
, BOOL calcValidRect
,
2005 RECT
*newWindowRect
, RECT
*oldWindowRect
,
2006 RECT
*oldClientRect
, WINDOWPOS
*winpos
,
2007 RECT
*newClientRect
)
2009 NCCALCSIZE_PARAMS params
;
2010 WINDOWPOS winposCopy
;
2013 params
.rgrc
[0] = *newWindowRect
;
2016 winposCopy
= *winpos
;
2017 params
.rgrc
[1] = *oldWindowRect
;
2018 params
.rgrc
[2] = *oldClientRect
;
2019 params
.lppos
= &winposCopy
;
2021 result
= SendMessageA( hwnd
, WM_NCCALCSIZE
, calcValidRect
,
2023 TRACE("%d,%d-%d,%d\n",
2024 params
.rgrc
[0].left
, params
.rgrc
[0].top
,
2025 params
.rgrc
[0].right
, params
.rgrc
[0].bottom
);
2027 /* If the application send back garbage, ignore it */
2028 if (params
.rgrc
[0].left
<= params
.rgrc
[0].right
&& params
.rgrc
[0].top
<= params
.rgrc
[0].bottom
)
2029 *newClientRect
= params
.rgrc
[0];
2035 /***********************************************************************
2036 * WINPOS_HandleWindowPosChanging16
2038 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2040 LONG
WINPOS_HandleWindowPosChanging16( WND
*wndPtr
, WINDOWPOS16
*winpos
)
2042 POINT maxSize
, minTrack
;
2043 if (winpos
->flags
& SWP_NOSIZE
) return 0;
2044 if ((wndPtr
->dwStyle
& WS_THICKFRAME
) ||
2045 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) == 0))
2047 WINPOS_GetMinMaxInfo( wndPtr
, &maxSize
, NULL
, &minTrack
, NULL
);
2048 if (maxSize
.x
< winpos
->cx
) winpos
->cx
= maxSize
.x
;
2049 if (maxSize
.y
< winpos
->cy
) winpos
->cy
= maxSize
.y
;
2050 if (!(wndPtr
->dwStyle
& WS_MINIMIZE
))
2052 if (winpos
->cx
< minTrack
.x
) winpos
->cx
= minTrack
.x
;
2053 if (winpos
->cy
< minTrack
.y
) winpos
->cy
= minTrack
.y
;
2060 /***********************************************************************
2061 * WINPOS_HandleWindowPosChanging
2063 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2065 LONG
WINPOS_HandleWindowPosChanging( WND
*wndPtr
, WINDOWPOS
*winpos
)
2068 if (winpos
->flags
& SWP_NOSIZE
) return 0;
2069 if ((wndPtr
->dwStyle
& WS_THICKFRAME
) ||
2070 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) == 0))
2072 WINPOS_GetMinMaxInfo( wndPtr
, &maxSize
, NULL
, NULL
, NULL
);
2073 winpos
->cx
= MIN( winpos
->cx
, maxSize
.x
);
2074 winpos
->cy
= MIN( winpos
->cy
, maxSize
.y
);
2079 /***********************************************************************
2082 * fix Z order taking into account owned popups -
2083 * basically we need to maintain them above the window that owns them
2085 * FIXME: hide/show owned popups when owner visibility changes.
2087 static HWND
SWP_DoOwnedPopups(WND
* pDesktop
, WND
* wndPtr
, HWND hwndInsertAfter
, WORD flags
)
2089 WND
* w
= WIN_LockWndPtr(pDesktop
->child
);
2091 WARN("(%04x) hInsertAfter = %04x\n", wndPtr
->hwndSelf
, hwndInsertAfter
);
2093 if( (wndPtr
->dwStyle
& WS_POPUP
) && wndPtr
->owner
)
2095 /* make sure this popup stays above the owner */
2097 HWND hwndLocalPrev
= HWND_TOP
;
2099 if( hwndInsertAfter
!= HWND_TOP
)
2101 while( w
!= wndPtr
->owner
)
2103 if (w
!= wndPtr
) hwndLocalPrev
= w
->hwndSelf
;
2104 if( hwndLocalPrev
== hwndInsertAfter
) break;
2105 WIN_UpdateWndPtr(&w
,w
->next
);
2107 hwndInsertAfter
= hwndLocalPrev
;
2110 else if( wndPtr
->dwStyle
& WS_CHILD
)
2113 WIN_UpdateWndPtr(&w
, pDesktop
->child
);
2117 if( w
== wndPtr
) break;
2119 if( (w
->dwStyle
& WS_POPUP
) && w
->owner
== wndPtr
)
2121 SetWindowPos(w
->hwndSelf
, hwndInsertAfter
, 0, 0, 0, 0,
2122 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOSENDCHANGING
| SWP_DEFERERASE
);
2123 hwndInsertAfter
= w
->hwndSelf
;
2125 WIN_UpdateWndPtr(&w
, w
->next
);
2129 WIN_ReleaseWndPtr(w
);
2130 return hwndInsertAfter
;
2133 /***********************************************************************
2136 * Make window look nice without excessive repainting
2138 * visible and update regions are in window coordinates
2139 * client and window rectangles are in parent client coordinates
2141 * FIXME: SWP_EX_PAINTSELF in uFlags works only if both old and new
2142 * window rects have the same origin.
2144 * Returns: uFlags and a dirty region in *pVisRgn.
2146 static UINT
SWP_CopyValidBits( WND
* Wnd
, HRGN
* pVisRgn
,
2147 LPRECT lpOldWndRect
,
2148 LPRECT lpOldClientRect
, UINT uFlags
)
2151 HRGN newVisRgn
, dirtyRgn
;
2152 INT my
= COMPLEXREGION
;
2154 TRACE("\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2155 Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
,
2156 Wnd
->rectWindow
.right
, Wnd
->rectWindow
.bottom
,
2157 lpOldWndRect
->left
, lpOldWndRect
->top
,
2158 lpOldWndRect
->right
, lpOldWndRect
->bottom
, *pVisRgn
);
2159 TRACE("\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2160 Wnd
->rectClient
.left
, Wnd
->rectClient
.top
,
2161 Wnd
->rectClient
.right
, Wnd
->rectClient
.bottom
,
2162 lpOldClientRect
->left
, lpOldClientRect
->top
,
2163 lpOldClientRect
->right
,lpOldClientRect
->bottom
);
2165 if( Wnd
->hrgnUpdate
== 1 )
2166 uFlags
|= SWP_EX_NOCOPY
; /* whole window is invalid, nothing to copy */
2168 newVisRgn
= DCE_GetVisRgn( Wnd
->hwndSelf
, DCX_WINDOW
| DCX_CLIPSIBLINGS
, 0, 0);
2169 dirtyRgn
= CreateRectRgn( 0, 0, 0, 0 );
2171 if( !(uFlags
& SWP_EX_NOCOPY
) ) /* make sure dst region covers only valid bits */
2172 my
= CombineRgn( dirtyRgn
, newVisRgn
, *pVisRgn
, RGN_AND
);
2174 if( (my
== NULLREGION
) || (uFlags
& SWP_EX_NOCOPY
) )
2178 TRACE("\twon't copy anything!\n");
2180 /* set dirtyRgn to the sum of old and new visible regions
2181 * in parent client coordinates */
2183 OffsetRgn( newVisRgn
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2184 OffsetRgn( *pVisRgn
, lpOldWndRect
->left
, lpOldWndRect
->top
);
2186 CombineRgn(*pVisRgn
, *pVisRgn
, newVisRgn
, RGN_OR
);
2188 else /* copy valid bits to a new location */
2190 INT dx
, dy
, ow
, oh
, nw
, nh
, ocw
, ncw
, och
, nch
;
2191 HRGN hrgnValid
= dirtyRgn
; /* non-empty intersection of old and new visible rgns */
2193 /* subtract already invalid region inside Wnd from the dst region */
2195 if( Wnd
->hrgnUpdate
)
2196 if( CombineRgn( hrgnValid
, hrgnValid
, Wnd
->hrgnUpdate
, RGN_DIFF
) == NULLREGION
)
2199 /* check if entire window can be copied */
2201 ow
= lpOldWndRect
->right
- lpOldWndRect
->left
;
2202 oh
= lpOldWndRect
->bottom
- lpOldWndRect
->top
;
2203 nw
= Wnd
->rectWindow
.right
- Wnd
->rectWindow
.left
;
2204 nh
= Wnd
->rectWindow
.bottom
- Wnd
->rectWindow
.top
;
2206 ocw
= lpOldClientRect
->right
- lpOldClientRect
->left
;
2207 och
= lpOldClientRect
->bottom
- lpOldClientRect
->top
;
2208 ncw
= Wnd
->rectClient
.right
- Wnd
->rectClient
.left
;
2209 nch
= Wnd
->rectClient
.bottom
- Wnd
->rectClient
.top
;
2211 if( (ocw
!= ncw
) || (och
!= nch
) ||
2212 ( ow
!= nw
) || ( oh
!= nh
) ||
2213 ((lpOldClientRect
->top
- lpOldWndRect
->top
) !=
2214 (Wnd
->rectClient
.top
- Wnd
->rectWindow
.top
)) ||
2215 ((lpOldClientRect
->left
- lpOldWndRect
->left
) !=
2216 (Wnd
->rectClient
.left
- Wnd
->rectWindow
.left
)) )
2218 dx
= Wnd
->rectClient
.left
- lpOldClientRect
->left
;
2219 dy
= Wnd
->rectClient
.top
- lpOldClientRect
->top
;
2221 /* restrict valid bits to the common client rect */
2223 r
.left
= Wnd
->rectClient
.left
- Wnd
->rectWindow
.left
;
2224 r
.top
= Wnd
->rectClient
.top
- Wnd
->rectWindow
.top
;
2225 r
.right
= r
.left
+ MIN( ocw
, ncw
);
2226 r
.bottom
= r
.top
+ MIN( och
, nch
);
2228 REGION_CropRgn( hrgnValid
, hrgnValid
, &r
,
2229 (uFlags
& SWP_EX_PAINTSELF
) ? NULL
: (POINT
*)&(Wnd
->rectWindow
));
2230 GetRgnBox( hrgnValid
, &r
);
2231 if( IsRectEmpty( &r
) )
2233 r
= *lpOldClientRect
;
2237 dx
= Wnd
->rectWindow
.left
- lpOldWndRect
->left
;
2238 dy
= Wnd
->rectWindow
.top
- lpOldWndRect
->top
;
2239 if( !(uFlags
& SWP_EX_PAINTSELF
) )
2240 OffsetRgn( hrgnValid
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2244 if( !(uFlags
& SWP_EX_PAINTSELF
) )
2246 /* Move remaining regions to parent coordinates */
2247 OffsetRgn( newVisRgn
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2248 OffsetRgn( *pVisRgn
, lpOldWndRect
->left
, lpOldWndRect
->top
);
2251 OffsetRect( &r
, -lpOldWndRect
->left
, -lpOldWndRect
->top
);
2253 TRACE("\tcomputing dirty region!\n");
2255 /* Compute combined dirty region (old + new - valid) */
2256 CombineRgn( *pVisRgn
, *pVisRgn
, newVisRgn
, RGN_OR
);
2257 CombineRgn( *pVisRgn
, *pVisRgn
, hrgnValid
, RGN_DIFF
);
2259 /* Blt valid bits, r is the rect to copy */
2267 /* get DC and clip rect with drawable rect to avoid superfluous expose events
2268 from copying clipped areas */
2270 if( uFlags
& SWP_EX_PAINTSELF
)
2272 hDC
= GetDCEx( Wnd
->hwndSelf
, hrgnValid
, DCX_WINDOW
| DCX_CACHE
|
2273 DCX_KEEPCLIPRGN
| DCX_INTERSECTRGN
| DCX_CLIPSIBLINGS
);
2274 rClip
.right
= nw
; rClip
.bottom
= nh
;
2278 hDC
= GetDCEx( Wnd
->parent
->hwndSelf
, hrgnValid
, DCX_CACHE
|
2279 DCX_KEEPCLIPRGN
| DCX_INTERSECTRGN
| DCX_CLIPSIBLINGS
);
2280 rClip
.right
= Wnd
->parent
->rectClient
.right
- Wnd
->parent
->rectClient
.left
;
2281 rClip
.bottom
= Wnd
->parent
->rectClient
.bottom
- Wnd
->parent
->rectClient
.top
;
2283 rClip
.left
= rClip
.top
= 0;
2285 if( (dc
= (DC
*)GDI_GetObjPtr(hDC
, DC_MAGIC
)) )
2287 if( oh
> nh
) r
.bottom
= r
.top
+ nh
;
2288 if( ow
< nw
) r
.right
= r
.left
+ nw
;
2290 if( IntersectRect( &r
, &r
, &rClip
) )
2292 Wnd
->pDriver
->pSurfaceCopy( Wnd
->parent
, dc
, dx
, dy
, &r
, TRUE
);
2294 /* When you copy the bits without repainting, parent doesn't
2295 get validated appropriately. Therefore, we have to validate
2296 the parent with the windows' updated region when the
2297 parent's update region is not empty. */
2299 if (Wnd
->parent
->hrgnUpdate
!= 0 && !(Wnd
->parent
->dwStyle
& WS_CLIPCHILDREN
))
2301 OffsetRect(&r
, dx
, dy
);
2302 ValidateRect(Wnd
->parent
->hwndSelf
, &r
);
2306 GDI_HEAP_UNLOCK( hDC
);
2308 ReleaseDC( (uFlags
& SWP_EX_PAINTSELF
) ?
2309 Wnd
->hwndSelf
: Wnd
->parent
->hwndSelf
, hDC
);
2313 /* *pVisRgn now points to the invalidated region */
2315 DeleteObject(newVisRgn
);
2316 DeleteObject(dirtyRgn
);
2320 /***********************************************************************
2321 * SWP_DoSimpleFrameChanged
2323 * NOTE: old and new client rect origins are identical, only
2324 * extents may have changed. Window extents are the same.
2326 static void SWP_DoSimpleFrameChanged( WND
* wndPtr
, RECT
* pOldClientRect
, WORD swpFlags
, UINT uFlags
)
2332 if( !(swpFlags
& SWP_NOCLIENTSIZE
) )
2334 /* Client rect changed its position/size, most likely a scrollar
2335 * was added/removed.
2337 * FIXME: WVR alignment flags
2340 if( wndPtr
->rectClient
.right
> pOldClientRect
->right
) /* right edge */
2344 rect
.bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
2345 rect
.right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
2346 if(!(uFlags
& SWP_EX_NOCOPY
))
2347 rect
.left
= pOldClientRect
->right
- wndPtr
->rectClient
.left
;
2355 if( wndPtr
->rectClient
.bottom
> pOldClientRect
->bottom
) /* bottom edge */
2358 hrgn
= CreateRectRgnIndirect( &rect
);
2360 rect
.right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
2361 rect
.bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
2362 if(!(uFlags
& SWP_EX_NOCOPY
))
2363 rect
.top
= pOldClientRect
->bottom
- wndPtr
->rectClient
.top
;
2367 REGION_UnionRectWithRgn( hrgn
, &rect
);
2370 if( i
== 0 && (uFlags
& SWP_EX_NOCOPY
) ) /* force redraw anyway */
2372 rect
= wndPtr
->rectWindow
;
2373 OffsetRect( &rect
, wndPtr
->rectWindow
.left
- wndPtr
->rectClient
.left
,
2374 wndPtr
->rectWindow
.top
- wndPtr
->rectClient
.top
);
2382 PAINT_RedrawWindow( wndPtr
->hwndSelf
, &rect
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
|
2383 RDW_ERASENOW
| RDW_ALLCHILDREN
, RDW_EX_TOPFRAME
| RDW_EX_USEHRGN
);
2387 WIN_UpdateNCRgn(wndPtr
, 0, UNC_UPDATE
| UNC_ENTIRE
);
2391 DeleteObject( hrgn
);
2394 /***********************************************************************
2395 * SWP_DoWinPosChanging
2397 static BOOL
SWP_DoWinPosChanging( WND
* wndPtr
, WINDOWPOS
* pWinpos
,
2398 RECT
* pNewWindowRect
, RECT
* pNewClientRect
)
2400 /* Send WM_WINDOWPOSCHANGING message */
2402 if (!(pWinpos
->flags
& SWP_NOSENDCHANGING
))
2403 SendMessageA( wndPtr
->hwndSelf
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
)pWinpos
);
2405 /* Calculate new position and size */
2407 *pNewWindowRect
= wndPtr
->rectWindow
;
2408 *pNewClientRect
= (wndPtr
->dwStyle
& WS_MINIMIZE
) ? wndPtr
->rectWindow
2409 : wndPtr
->rectClient
;
2411 if (!(pWinpos
->flags
& SWP_NOSIZE
))
2413 pNewWindowRect
->right
= pNewWindowRect
->left
+ pWinpos
->cx
;
2414 pNewWindowRect
->bottom
= pNewWindowRect
->top
+ pWinpos
->cy
;
2416 if (!(pWinpos
->flags
& SWP_NOMOVE
))
2418 pNewWindowRect
->left
= pWinpos
->x
;
2419 pNewWindowRect
->top
= pWinpos
->y
;
2420 pNewWindowRect
->right
+= pWinpos
->x
- wndPtr
->rectWindow
.left
;
2421 pNewWindowRect
->bottom
+= pWinpos
->y
- wndPtr
->rectWindow
.top
;
2423 OffsetRect( pNewClientRect
, pWinpos
->x
- wndPtr
->rectWindow
.left
,
2424 pWinpos
->y
- wndPtr
->rectWindow
.top
);
2427 pWinpos
->flags
|= SWP_NOCLIENTMOVE
| SWP_NOCLIENTSIZE
;
2431 /***********************************************************************
2434 static UINT
SWP_DoNCCalcSize( WND
* wndPtr
, WINDOWPOS
* pWinpos
,
2435 RECT
* pNewWindowRect
, RECT
* pNewClientRect
, WORD f
)
2439 /* Send WM_NCCALCSIZE message to get new client area */
2440 if( (pWinpos
->flags
& (SWP_FRAMECHANGED
| SWP_NOSIZE
)) != SWP_NOSIZE
)
2442 wvrFlags
= WINPOS_SendNCCalcSize( pWinpos
->hwnd
, TRUE
, pNewWindowRect
,
2443 &wndPtr
->rectWindow
, &wndPtr
->rectClient
,
2444 pWinpos
, pNewClientRect
);
2446 /* FIXME: WVR_ALIGNxxx */
2448 if( pNewClientRect
->left
!= wndPtr
->rectClient
.left
||
2449 pNewClientRect
->top
!= wndPtr
->rectClient
.top
)
2450 pWinpos
->flags
&= ~SWP_NOCLIENTMOVE
;
2452 if( (pNewClientRect
->right
- pNewClientRect
->left
!=
2453 wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
) ||
2454 (pNewClientRect
->bottom
- pNewClientRect
->top
!=
2455 wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
) )
2456 pWinpos
->flags
&= ~SWP_NOCLIENTSIZE
;
2459 if( !(f
& SWP_NOMOVE
) && (pNewClientRect
->left
!= wndPtr
->rectClient
.left
||
2460 pNewClientRect
->top
!= wndPtr
->rectClient
.top
) )
2461 pWinpos
->flags
&= ~SWP_NOCLIENTMOVE
;
2465 /***********************************************************************
2466 * SetWindowPos (USER.2)
2468 BOOL16 WINAPI
SetWindowPos16( HWND16 hwnd
, HWND16 hwndInsertAfter
,
2469 INT16 x
, INT16 y
, INT16 cx
, INT16 cy
, WORD flags
)
2471 return SetWindowPos(hwnd
,(INT
)(INT16
)hwndInsertAfter
,x
,y
,cx
,cy
,flags
);
2474 /***********************************************************************
2475 * SetWindowPos (USER32.520)
2477 BOOL WINAPI
SetWindowPos( HWND hwnd
, HWND hwndInsertAfter
,
2478 INT x
, INT y
, INT cx
, INT cy
, UINT flags
)
2481 WND
* wndPtr
,*wndTemp
;
2482 RECT newWindowRect
, newClientRect
;
2483 RECT oldWindowRect
, oldClientRect
;
2485 UINT wvrFlags
= 0, uFlags
= 0;
2486 BOOL retvalue
, resync
= FALSE
, bChangePos
;
2487 HWND hwndActive
= 0;
2489 /* Get current active window from the active queue */
2492 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
2495 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
2496 QUEUE_Unlock( pActiveQueue
);
2500 TRACE("hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2501 hwnd
, x
, y
, x
+cx
, y
+cy
, flags
);
2503 bChangePos
= !(flags
& SWP_WINE_NOHOSTMOVE
);
2504 flags
&= ~SWP_WINE_NOHOSTMOVE
;
2507 /* ------------------------------------------------------------------------ CHECKS */
2509 /* Check window handle */
2511 if (hwnd
== GetDesktopWindow()) return FALSE
;
2512 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return FALSE
;
2514 TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr
->rectWindow
.left
, wndPtr
->rectWindow
.top
,
2515 wndPtr
->rectWindow
.right
, wndPtr
->rectWindow
.bottom
, (unsigned)wndPtr
->dwStyle
);
2517 /* Fix redundant flags */
2519 if(wndPtr
->dwStyle
& WS_VISIBLE
)
2520 flags
&= ~SWP_SHOWWINDOW
;
2523 if (!(flags
& SWP_SHOWWINDOW
))
2524 flags
|= SWP_NOREDRAW
;
2525 flags
&= ~SWP_HIDEWINDOW
;
2528 if ( cx
< 0 ) cx
= 0; if( cy
< 0 ) cy
= 0;
2530 if ((wndPtr
->rectWindow
.right
- wndPtr
->rectWindow
.left
== cx
) &&
2531 (wndPtr
->rectWindow
.bottom
- wndPtr
->rectWindow
.top
== cy
))
2532 flags
|= SWP_NOSIZE
; /* Already the right size */
2534 if ((wndPtr
->rectWindow
.left
== x
) && (wndPtr
->rectWindow
.top
== y
))
2535 flags
|= SWP_NOMOVE
; /* Already the right position */
2537 if (hwnd
== hwndActive
)
2538 flags
|= SWP_NOACTIVATE
; /* Already active */
2539 else if ( (wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)
2541 if(!(flags
& SWP_NOACTIVATE
)) /* Bring to the top when activating */
2543 flags
&= ~SWP_NOZORDER
;
2544 hwndInsertAfter
= HWND_TOP
;
2549 /* Check hwndInsertAfter */
2551 /* FIXME: TOPMOST not supported yet */
2552 if ((hwndInsertAfter
== HWND_TOPMOST
) ||
2553 (hwndInsertAfter
== HWND_NOTOPMOST
)) hwndInsertAfter
= HWND_TOP
;
2555 /* hwndInsertAfter must be a sibling of the window */
2556 if ((hwndInsertAfter
!= HWND_TOP
) && (hwndInsertAfter
!= HWND_BOTTOM
))
2558 WND
* wnd
= WIN_FindWndPtr(hwndInsertAfter
);
2561 if( wnd
->parent
!= wndPtr
->parent
)
2564 WIN_ReleaseWndPtr(wnd
);
2567 if( wnd
->next
== wndPtr
) flags
|= SWP_NOZORDER
;
2569 WIN_ReleaseWndPtr(wnd
);
2572 Pos
: /* ------------------------------------------------------------------------ MAIN part */
2574 /* Fill the WINDOWPOS structure */
2577 winpos
.hwndInsertAfter
= hwndInsertAfter
;
2582 winpos
.flags
= flags
;
2584 SWP_DoWinPosChanging( wndPtr
, &winpos
, &newWindowRect
, &newClientRect
);
2586 if((winpos
.flags
& (SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) != SWP_NOZORDER
)
2588 if( wndPtr
->parent
== WIN_GetDesktop() )
2589 hwndInsertAfter
= SWP_DoOwnedPopups( wndPtr
->parent
, wndPtr
,
2590 hwndInsertAfter
, winpos
.flags
);
2591 WIN_ReleaseDesktop();
2594 if(!(wndPtr
->flags
& WIN_NATIVE
) )
2596 if( hwndInsertAfter
== HWND_TOP
)
2597 winpos
.flags
|= ( wndPtr
->parent
->child
== wndPtr
)? SWP_NOZORDER
: 0;
2599 if( hwndInsertAfter
== HWND_BOTTOM
)
2600 winpos
.flags
|= ( wndPtr
->next
)? 0: SWP_NOZORDER
;
2602 if( !(winpos
.flags
& SWP_NOZORDER
) )
2603 if( GetWindow(hwndInsertAfter
, GW_HWNDNEXT
) == wndPtr
->hwndSelf
)
2604 winpos
.flags
|= SWP_NOZORDER
;
2606 if( !(winpos
.flags
& (SWP_NOREDRAW
| SWP_SHOWWINDOW
)) &&
2607 ((winpos
.flags
& (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_FRAMECHANGED
))
2608 != (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
)) )
2610 /* get a previous visible region for SWP_CopyValidBits() */
2611 DWORD flags
= DCX_WINDOW
;
2613 if (wndPtr
->dwStyle
& WS_CLIPSIBLINGS
)
2614 flags
|= DCX_CLIPSIBLINGS
;
2616 visRgn
= DCE_GetVisRgn(hwnd
, flags
, 0, 0);
2620 /* Common operations */
2622 wvrFlags
= SWP_DoNCCalcSize( wndPtr
, &winpos
, &newWindowRect
, &newClientRect
, flags
);
2624 if(!(winpos
.flags
& SWP_NOZORDER
))
2626 if ( WIN_UnlinkWindow( winpos
.hwnd
) )
2627 WIN_LinkWindow( winpos
.hwnd
, hwndInsertAfter
);
2630 /* Reset active DCEs */
2632 if( (((winpos
.flags
& SWP_AGG_NOPOSCHANGE
) != SWP_AGG_NOPOSCHANGE
) &&
2633 wndPtr
->dwStyle
& WS_VISIBLE
) ||
2634 (flags
& (SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) )
2638 UnionRect(&rect
, &newWindowRect
, &wndPtr
->rectWindow
);
2639 DCE_InvalidateDCE(wndPtr
, &rect
);
2642 oldWindowRect
= wndPtr
->rectWindow
;
2643 oldClientRect
= wndPtr
->rectClient
;
2645 /* Find out if we have to redraw the whole client rect */
2647 if( oldClientRect
.bottom
- oldClientRect
.top
==
2648 newClientRect
.bottom
- newClientRect
.top
) wvrFlags
&= ~WVR_VREDRAW
;
2650 if( oldClientRect
.right
- oldClientRect
.left
==
2651 newClientRect
.right
- newClientRect
.left
) wvrFlags
&= ~WVR_HREDRAW
;
2653 if( (winpos
.flags
& SWP_NOCOPYBITS
) || (!(winpos
.flags
& SWP_NOCLIENTSIZE
) &&
2654 (wvrFlags
>= WVR_HREDRAW
) && (wvrFlags
< WVR_VALIDRECTS
)) )
2656 uFlags
|= SWP_EX_NOCOPY
;
2659 * Use this later in CopyValidBits()
2662 uFlags |= SWP_EX_NONCLIENT;
2665 /* FIXME: actually do something with WVR_VALIDRECTS */
2667 wndPtr
->rectWindow
= newWindowRect
;
2668 wndPtr
->rectClient
= newClientRect
;
2670 if (wndPtr
->flags
& WIN_NATIVE
) /* -------------------------------------------- hosted window */
2672 BOOL bCallDriver
= TRUE
;
2673 HWND tempInsertAfter
= winpos
.hwndInsertAfter
;
2675 winpos
.hwndInsertAfter
= hwndInsertAfter
;
2677 if( !(winpos
.flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
| SWP_NOREDRAW
)) )
2679 /* This is the only place where we need to force repainting of the contents
2680 of windows created by the host window system, all other cases go through the
2681 expose event handling */
2683 if( (winpos
.flags
& (SWP_NOSIZE
| SWP_FRAMECHANGED
)) == (SWP_NOSIZE
| SWP_FRAMECHANGED
) )
2685 cx
= newWindowRect
.right
- newWindowRect
.left
;
2686 cy
= newWindowRect
.bottom
- newWindowRect
.top
;
2688 wndPtr
->pDriver
->pSetWindowPos(wndPtr
, &winpos
, bChangePos
);
2689 winpos
.hwndInsertAfter
= tempInsertAfter
;
2690 bCallDriver
= FALSE
;
2692 if( winpos
.flags
& SWP_NOCLIENTMOVE
)
2693 SWP_DoSimpleFrameChanged(wndPtr
, &oldClientRect
, winpos
.flags
, uFlags
);
2696 /* client area moved but window extents remained the same, copy valid bits */
2698 visRgn
= CreateRectRgn( 0, 0, cx
, cy
);
2699 uFlags
= SWP_CopyValidBits( wndPtr
, &visRgn
, &oldWindowRect
, &oldClientRect
,
2700 uFlags
| SWP_EX_PAINTSELF
);
2707 if( !(winpos
.flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
| SWP_NOREDRAW
)) )
2709 if( (oldClientRect
.left
- oldWindowRect
.left
== newClientRect
.left
- newWindowRect
.left
) &&
2710 (oldClientRect
.top
- oldWindowRect
.top
== newClientRect
.top
- newWindowRect
.top
) &&
2711 !(uFlags
& SWP_EX_NOCOPY
) )
2713 /* The origin of the client rect didn't move so we can try to repaint
2714 * only the nonclient area by setting bit gravity hint for the host window system.
2717 if( !(wndPtr
->flags
& WIN_MANAGED
) )
2719 HRGN hrgn
= CreateRectRgn( 0, 0, newWindowRect
.right
- newWindowRect
.left
,
2720 newWindowRect
.bottom
- newWindowRect
.top
);
2721 RECT rcn
= newClientRect
;
2722 RECT rco
= oldClientRect
;
2724 OffsetRect( &rcn
, -newWindowRect
.left
, -newWindowRect
.top
);
2725 OffsetRect( &rco
, -oldWindowRect
.left
, -oldWindowRect
.top
);
2726 IntersectRect( &rcn
, &rcn
, &rco
);
2727 visRgn
= CreateRectRgnIndirect( &rcn
);
2728 CombineRgn( visRgn
, hrgn
, visRgn
, RGN_DIFF
);
2729 DeleteObject( hrgn
);
2730 uFlags
= SWP_EX_PAINTSELF
;
2732 wndPtr
->pDriver
->pSetHostAttr(wndPtr
, HAK_BITGRAVITY
, BGNorthWest
);
2735 wndPtr
->pDriver
->pSetHostAttr(wndPtr
, HAK_BITGRAVITY
, BGForget
);
2738 wndPtr
->pDriver
->pSetWindowPos(wndPtr
, &winpos
, bChangePos
);
2739 winpos
.hwndInsertAfter
= tempInsertAfter
;
2742 if( winpos
.flags
& SWP_SHOWWINDOW
)
2746 wndPtr
->dwStyle
|= WS_VISIBLE
;
2748 if (wndPtr
->flags
& WIN_MANAGED
) resync
= TRUE
;
2750 /* focus was set to unmapped window, reset host focus
2751 * since the window is now visible */
2753 focus
= curr
= GetFocus();
2758 WND
*pFocus
= WIN_FindWndPtr( focus
);
2760 pFocus
->pDriver
->pSetFocus(pFocus
);
2761 WIN_ReleaseWndPtr(pFocus
);
2764 curr
= GetParent(curr
);
2768 else /* -------------------------------------------- emulated window */
2770 if( winpos
.flags
& SWP_SHOWWINDOW
)
2772 wndPtr
->dwStyle
|= WS_VISIBLE
;
2773 uFlags
|= SWP_EX_PAINTSELF
;
2774 visRgn
= 1; /* redraw the whole window */
2776 else if( !(winpos
.flags
& SWP_NOREDRAW
) )
2778 if( winpos
.flags
& SWP_HIDEWINDOW
)
2780 if( visRgn
> 1 ) /* map to parent */
2781 OffsetRgn( visRgn
, oldWindowRect
.left
, oldWindowRect
.top
);
2787 if( (winpos
.flags
& SWP_AGG_NOPOSCHANGE
) != SWP_AGG_NOPOSCHANGE
)
2788 uFlags
= SWP_CopyValidBits(wndPtr
, &visRgn
, &oldWindowRect
,
2789 &oldClientRect
, uFlags
);
2792 /* nothing moved, redraw frame if needed */
2794 if( winpos
.flags
& SWP_FRAMECHANGED
)
2795 SWP_DoSimpleFrameChanged( wndPtr
, &oldClientRect
, winpos
.flags
, uFlags
);
2798 DeleteObject( visRgn
);
2806 if( winpos
.flags
& SWP_HIDEWINDOW
)
2808 wndPtr
->dwStyle
&= ~WS_VISIBLE
;
2810 if (hwnd
== CARET_GetHwnd()) DestroyCaret();
2812 /* FIXME: This will cause the window to be activated irrespective
2813 * of whether it is owned by the same thread. Has to be done
2817 if (winpos
.hwnd
== hwndActive
)
2818 WINPOS_ActivateOtherWindow( wndPtr
);
2821 /* ------------------------------------------------------------------------ FINAL */
2823 if (wndPtr
->flags
& WIN_NATIVE
)
2824 EVENT_Synchronize(); /* Synchronize with the host window system */
2826 if (!GetCapture() && ((wndPtr
->dwStyle
& WS_VISIBLE
) || (flags
& SWP_HIDEWINDOW
)))
2828 /* Simulate a mouse event to set the cursor */
2829 DWORD posX
, posY
, keyState
;
2831 if ( EVENT_QueryPointer( &posX
, &posY
, &keyState
) )
2833 int iWndsLocks
= WIN_SuspendWndsLock();
2835 hardware_event( WM_MOUSEMOVE
, keyState
, 0,
2836 posX
, posY
, GetTickCount(), 0 );
2838 WIN_RestoreWndsLock(iWndsLocks
);
2842 wndTemp
= WIN_GetDesktop();
2844 /* repaint invalidated region (if any)
2846 * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2847 * and force update after ChangeActiveWindow() to avoid painting frames twice.
2852 if( !(winpos
.flags
& SWP_NOREDRAW
) )
2855 /* Use PAINT_RedrawWindow to explicitly force an invalidation of the window,
2856 its parent and sibling and so on, and then erase the parent window
2857 back ground if the parent is either a top-level window or its parent's parent
2858 is top-level window. Rely on the system to repaint other affected
2859 windows later on. */
2860 if( uFlags
& SWP_EX_PAINTSELF
)
2862 PAINT_RedrawWindow( wndPtr
->hwndSelf
, NULL
, (visRgn
== 1) ? 0 : visRgn
,
2863 RDW_ERASE
| RDW_FRAME
| RDW_INVALIDATE
| RDW_ALLCHILDREN
,
2864 RDW_EX_XYWINDOW
| RDW_EX_USEHRGN
);
2868 PAINT_RedrawWindow( wndPtr
->parent
->hwndSelf
, NULL
, (visRgn
== 1) ? 0 : visRgn
,
2869 RDW_ERASE
| RDW_INVALIDATE
| RDW_ALLCHILDREN
,
2873 if(wndPtr
-> parent
== wndTemp
|| wndPtr
->parent
->parent
== wndTemp
)
2875 PAINT_RedrawWindow( wndPtr
->parent
->hwndSelf
, NULL
, 0,
2876 RDW_ERASENOW
| RDW_NOCHILDREN
, 0 );
2880 DeleteObject( visRgn
);
2883 WIN_ReleaseDesktop();
2885 if (!(flags
& SWP_NOACTIVATE
))
2886 WINPOS_ChangeActiveWindow( winpos
.hwnd
, FALSE
);
2888 /* And last, send the WM_WINDOWPOSCHANGED message */
2890 TRACE("\tstatus flags = %04x\n", winpos
.flags
& SWP_AGG_STATUSFLAGS
);
2893 (((winpos
.flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOPOSCHANGE
) &&
2894 !(winpos
.flags
& SWP_NOSENDCHANGING
)) )
2896 SendMessageA( winpos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
)&winpos
);
2897 if (resync
) EVENT_Synchronize();
2902 WIN_ReleaseWndPtr(wndPtr
);
2907 /***********************************************************************
2908 * BeginDeferWindowPos16 (USER.259)
2910 HDWP16 WINAPI
BeginDeferWindowPos16( INT16 count
)
2912 return BeginDeferWindowPos( count
);
2916 /***********************************************************************
2917 * BeginDeferWindowPos (USER32.9)
2919 HDWP WINAPI
BeginDeferWindowPos( INT count
)
2924 if (count
<= 0) return 0;
2925 handle
= USER_HEAP_ALLOC( sizeof(DWP
) + (count
-1)*sizeof(WINDOWPOS
) );
2926 if (!handle
) return 0;
2927 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( handle
);
2928 pDWP
->actualCount
= 0;
2929 pDWP
->suggestedCount
= count
;
2931 pDWP
->wMagic
= DWP_MAGIC
;
2932 pDWP
->hwndParent
= 0;
2937 /***********************************************************************
2938 * DeferWindowPos16 (USER.260)
2940 HDWP16 WINAPI
DeferWindowPos16( HDWP16 hdwp
, HWND16 hwnd
, HWND16 hwndAfter
,
2941 INT16 x
, INT16 y
, INT16 cx
, INT16 cy
,
2944 return DeferWindowPos( hdwp
, hwnd
, (INT
)(INT16
)hwndAfter
,
2945 x
, y
, cx
, cy
, flags
);
2949 /***********************************************************************
2950 * DeferWindowPos (USER32.128)
2952 HDWP WINAPI
DeferWindowPos( HDWP hdwp
, HWND hwnd
, HWND hwndAfter
,
2953 INT x
, INT y
, INT cx
, INT cy
,
2958 HDWP newhdwp
= hdwp
,retvalue
;
2962 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
2963 if (!pDWP
) return 0;
2964 if (hwnd
== GetDesktopWindow()) return 0;
2966 if (!(pWnd
=WIN_FindWndPtr( hwnd
))) {
2967 USER_HEAP_FREE( hdwp
);
2971 /* Numega Bounds Checker Demo dislikes the following code.
2972 In fact, I've not been able to find any "same parent" requirement in any docu
2976 /* All the windows of a DeferWindowPos() must have the same parent */
2977 parent
= pWnd
->parent
->hwndSelf
;
2978 if (pDWP
->actualCount
== 0) pDWP
->hwndParent
= parent
;
2979 else if (parent
!= pDWP
->hwndParent
)
2981 USER_HEAP_FREE( hdwp
);
2987 for (i
= 0; i
< pDWP
->actualCount
; i
++)
2989 if (pDWP
->winPos
[i
].hwnd
== hwnd
)
2991 /* Merge with the other changes */
2992 if (!(flags
& SWP_NOZORDER
))
2994 pDWP
->winPos
[i
].hwndInsertAfter
= hwndAfter
;
2996 if (!(flags
& SWP_NOMOVE
))
2998 pDWP
->winPos
[i
].x
= x
;
2999 pDWP
->winPos
[i
].y
= y
;
3001 if (!(flags
& SWP_NOSIZE
))
3003 pDWP
->winPos
[i
].cx
= cx
;
3004 pDWP
->winPos
[i
].cy
= cy
;
3006 pDWP
->winPos
[i
].flags
&= flags
| ~(SWP_NOSIZE
| SWP_NOMOVE
|
3007 SWP_NOZORDER
| SWP_NOREDRAW
|
3008 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
3010 pDWP
->winPos
[i
].flags
|= flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
|
3016 if (pDWP
->actualCount
>= pDWP
->suggestedCount
)
3018 newhdwp
= USER_HEAP_REALLOC( hdwp
,
3019 sizeof(DWP
) + pDWP
->suggestedCount
*sizeof(WINDOWPOS
) );
3025 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( newhdwp
);
3026 pDWP
->suggestedCount
++;
3028 pDWP
->winPos
[pDWP
->actualCount
].hwnd
= hwnd
;
3029 pDWP
->winPos
[pDWP
->actualCount
].hwndInsertAfter
= hwndAfter
;
3030 pDWP
->winPos
[pDWP
->actualCount
].x
= x
;
3031 pDWP
->winPos
[pDWP
->actualCount
].y
= y
;
3032 pDWP
->winPos
[pDWP
->actualCount
].cx
= cx
;
3033 pDWP
->winPos
[pDWP
->actualCount
].cy
= cy
;
3034 pDWP
->winPos
[pDWP
->actualCount
].flags
= flags
;
3035 pDWP
->actualCount
++;
3038 WIN_ReleaseWndPtr(pWnd
);
3043 /***********************************************************************
3044 * EndDeferWindowPos16 (USER.261)
3046 BOOL16 WINAPI
EndDeferWindowPos16( HDWP16 hdwp
)
3048 return EndDeferWindowPos( hdwp
);
3052 /***********************************************************************
3053 * EndDeferWindowPos (USER32.173)
3055 BOOL WINAPI
EndDeferWindowPos( HDWP hdwp
)
3062 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
3063 if (!pDWP
) return FALSE
;
3064 for (i
= 0, winpos
= pDWP
->winPos
; i
< pDWP
->actualCount
; i
++, winpos
++)
3066 if (!(res
= SetWindowPos( winpos
->hwnd
, winpos
->hwndInsertAfter
,
3067 winpos
->x
, winpos
->y
, winpos
->cx
,
3068 winpos
->cy
, winpos
->flags
))) break;
3070 USER_HEAP_FREE( hdwp
);
3075 /***********************************************************************
3076 * TileChildWindows (USER.199)
3078 void WINAPI
TileChildWindows16( HWND16 parent
, WORD action
)
3080 FIXME("(%04x, %d): stub\n", parent
, action
);
3083 /***********************************************************************
3084 * CascageChildWindows (USER.198)
3086 void WINAPI
CascadeChildWindows16( HWND16 parent
, WORD action
)
3088 FIXME("(%04x, %d): stub\n", parent
, action
);
3091 /***********************************************************************
3092 * SetProgmanWindow [USER32.522]
3094 HRESULT WINAPI
SetProgmanWindow ( HWND hwnd
)
3096 hGlobalProgmanWindow
= hwnd
;
3097 return hGlobalProgmanWindow
;
3100 /***********************************************************************
3101 * GetProgmanWindow [USER32.289]
3103 HRESULT WINAPI
GetProgmanWindow ( )
3105 return hGlobalProgmanWindow
;
3108 /***********************************************************************
3109 * SetShellWindowEx [USER32.531]
3110 * hwndProgman = Progman[Program Manager]
3111 * |-> SHELLDLL_DefView
3112 * hwndListView = | |-> SysListView32
3113 * | | |-> tooltips_class32
3119 HRESULT WINAPI
SetShellWindowEx ( HWND hwndProgman
, HWND hwndListView
)
3121 FIXME("0x%08x 0x%08x stub\n",hwndProgman
,hwndListView
);
3122 hGlobalShellWindow
= hwndProgman
;
3123 return hGlobalShellWindow
;
3127 /***********************************************************************
3128 * SetTaskmanWindow [USER32.537]
3130 * hwnd = MSTaskSwWClass
3131 * |-> SysTabControl32
3133 HRESULT WINAPI
SetTaskmanWindow ( HWND hwnd
)
3135 hGlobalTaskmanWindow
= hwnd
;
3136 return hGlobalTaskmanWindow
;
3139 /***********************************************************************
3140 * GetTaskmanWindow [USER32.304]
3142 HRESULT WINAPI
GetTaskmanWindow ( )
3144 return hGlobalTaskmanWindow
;