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_CHILD
)) ) return TRUE
;
814 /*******************************************************************
815 * SetActiveWindow16 (USER.59)
817 HWND16 WINAPI
SetActiveWindow16( HWND16 hwnd
)
819 return SetActiveWindow(hwnd
);
823 /*******************************************************************
824 * SetActiveWindow (USER32.463)
826 HWND WINAPI
SetActiveWindow( HWND hwnd
)
829 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
830 MESSAGEQUEUE
*pMsgQ
= 0, *pCurMsgQ
= 0;
832 if ( !WINPOS_CanActivate(wndPtr
) )
838 /* Get the messageQ for the current thread */
839 if (!(pCurMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( GetFastQueue16() )))
841 WARN("\tCurrent message queue not found. Exiting!\n" );
845 /* Retrieve the message queue associated with this window */
846 pMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( wndPtr
->hmemTaskQ
);
849 WARN("\tWindow message queue not found. Exiting!\n" );
853 /* Make sure that the window is associated with the calling threads
854 * message queue. It must share the same perQ data.
857 if ( pCurMsgQ
->pQData
!= pMsgQ
->pQData
)
860 /* Save current active window */
861 prev
= PERQDATA_GetActiveWnd( pMsgQ
->pQData
);
863 WINPOS_SetActiveWindow( hwnd
, 0, 0 );
866 /* Unlock the queues before returning */
868 QUEUE_Unlock( pMsgQ
);
870 QUEUE_Unlock( pCurMsgQ
);
873 WIN_ReleaseWndPtr(wndPtr
);
878 /*******************************************************************
879 * GetForegroundWindow16 (USER.608)
881 HWND16 WINAPI
GetForegroundWindow16(void)
883 return (HWND16
)GetForegroundWindow();
887 /*******************************************************************
888 * SetForegroundWindow16 (USER.609)
890 BOOL16 WINAPI
SetForegroundWindow16( HWND16 hwnd
)
892 return SetForegroundWindow( hwnd
);
896 /*******************************************************************
897 * GetForegroundWindow (USER32.241)
899 HWND WINAPI
GetForegroundWindow(void)
903 /* Get the foreground window (active window of hActiveQueue) */
906 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
908 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
910 QUEUE_Unlock( pActiveQueue
);
916 /*******************************************************************
917 * SetForegroundWindow (USER32.482)
919 BOOL WINAPI
SetForegroundWindow( HWND hwnd
)
921 return WINPOS_ChangeActiveWindow( hwnd
, FALSE
);
925 /*******************************************************************
926 * GetShellWindow16 (USER.600)
928 HWND16 WINAPI
GetShellWindow16(void)
930 return GetShellWindow();
933 /*******************************************************************
934 * SetShellWindow (USER32.504)
936 HWND WINAPI
SetShellWindow(HWND hwndshell
)
937 { WARN("(hWnd=%08x) semi stub\n",hwndshell
);
939 hGlobalShellWindow
= hwndshell
;
940 return hGlobalShellWindow
;
944 /*******************************************************************
945 * GetShellWindow (USER32.287)
947 HWND WINAPI
GetShellWindow(void)
948 { WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow
);
950 return hGlobalShellWindow
;
954 /***********************************************************************
955 * BringWindowToTop16 (USER.45)
957 BOOL16 WINAPI
BringWindowToTop16( HWND16 hwnd
)
959 return BringWindowToTop(hwnd
);
963 /***********************************************************************
964 * BringWindowToTop (USER32.11)
966 BOOL WINAPI
BringWindowToTop( HWND hwnd
)
968 return SetWindowPos( hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
);
972 /***********************************************************************
973 * MoveWindow16 (USER.56)
975 BOOL16 WINAPI
MoveWindow16( HWND16 hwnd
, INT16 x
, INT16 y
, INT16 cx
, INT16 cy
,
978 return MoveWindow(hwnd
,x
,y
,cx
,cy
,repaint
);
982 /***********************************************************************
983 * MoveWindow (USER32.399)
985 BOOL WINAPI
MoveWindow( HWND hwnd
, INT x
, INT y
, INT cx
, INT cy
,
988 int flags
= SWP_NOZORDER
| SWP_NOACTIVATE
;
989 if (!repaint
) flags
|= SWP_NOREDRAW
;
990 TRACE("%04x %d,%d %dx%d %d\n",
991 hwnd
, x
, y
, cx
, cy
, repaint
);
992 return SetWindowPos( hwnd
, 0, x
, y
, cx
, cy
, flags
);
995 /***********************************************************************
996 * WINPOS_InitInternalPos
998 static LPINTERNALPOS
WINPOS_InitInternalPos( WND
* wnd
, POINT pt
,
1001 LPINTERNALPOS lpPos
= (LPINTERNALPOS
) GetPropA( wnd
->hwndSelf
,
1005 /* this happens when the window is minimized/maximized
1006 * for the first time (rectWindow is not adjusted yet) */
1008 lpPos
= HeapAlloc( SystemHeap
, 0, sizeof(INTERNALPOS
) );
1009 if( !lpPos
) return NULL
;
1011 SetPropA( wnd
->hwndSelf
, atomInternalPos
, (HANDLE
)lpPos
);
1012 lpPos
->hwndIconTitle
= 0; /* defer until needs to be shown */
1013 CONV_RECT32TO16( &wnd
->rectWindow
, &lpPos
->rectNormal
);
1014 *(UINT
*)&lpPos
->ptIconPos
= *(UINT
*)&lpPos
->ptMaxPos
= 0xFFFFFFFF;
1017 if( wnd
->dwStyle
& WS_MINIMIZE
)
1018 CONV_POINT32TO16( &pt
, &lpPos
->ptIconPos
);
1019 else if( wnd
->dwStyle
& WS_MAXIMIZE
)
1020 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1021 else if( restoreRect
)
1022 CONV_RECT32TO16( restoreRect
, &lpPos
->rectNormal
);
1027 /***********************************************************************
1028 * WINPOS_RedrawIconTitle
1030 BOOL
WINPOS_RedrawIconTitle( HWND hWnd
)
1032 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)GetPropA( hWnd
, atomInternalPos
);
1035 if( lpPos
->hwndIconTitle
)
1037 SendMessageA( lpPos
->hwndIconTitle
, WM_SHOWWINDOW
, TRUE
, 0);
1038 InvalidateRect( lpPos
->hwndIconTitle
, NULL
, TRUE
);
1045 /***********************************************************************
1046 * WINPOS_ShowIconTitle
1048 BOOL
WINPOS_ShowIconTitle( WND
* pWnd
, BOOL bShow
)
1050 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)GetPropA( pWnd
->hwndSelf
, atomInternalPos
);
1052 if( lpPos
&& !(pWnd
->flags
& WIN_MANAGED
))
1054 HWND16 hWnd
= lpPos
->hwndIconTitle
;
1056 TRACE("0x%04x %i\n", pWnd
->hwndSelf
, (bShow
!= 0) );
1059 lpPos
->hwndIconTitle
= hWnd
= ICONTITLE_Create( pWnd
);
1062 if( ( pWnd
= WIN_FindWndPtr(hWnd
) ) != NULL
)
1064 if( !(pWnd
->dwStyle
& WS_VISIBLE
) )
1066 SendMessageA( hWnd
, WM_SHOWWINDOW
, TRUE
, 0 );
1067 SetWindowPos( hWnd
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
1068 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_SHOWWINDOW
);
1070 WIN_ReleaseWndPtr(pWnd
);
1073 else ShowWindow( hWnd
, SW_HIDE
);
1078 /*******************************************************************
1079 * WINPOS_GetMinMaxInfo
1081 * Get the minimized and maximized information for a window.
1083 void WINPOS_GetMinMaxInfo( WND
*wndPtr
, POINT
*maxSize
, POINT
*maxPos
,
1084 POINT
*minTrack
, POINT
*maxTrack
)
1086 LPINTERNALPOS lpPos
;
1090 /* Compute default values */
1092 MinMax
.ptMaxSize
.x
= GetSystemMetrics(SM_CXSCREEN
);
1093 MinMax
.ptMaxSize
.y
= GetSystemMetrics(SM_CYSCREEN
);
1094 MinMax
.ptMinTrackSize
.x
= GetSystemMetrics(SM_CXMINTRACK
);
1095 MinMax
.ptMinTrackSize
.y
= GetSystemMetrics(SM_CYMINTRACK
);
1096 MinMax
.ptMaxTrackSize
.x
= GetSystemMetrics(SM_CXSCREEN
);
1097 MinMax
.ptMaxTrackSize
.y
= GetSystemMetrics(SM_CYSCREEN
);
1099 if (wndPtr
->flags
& WIN_MANAGED
) xinc
= yinc
= 0;
1100 else if (HAS_DLGFRAME( wndPtr
->dwStyle
, wndPtr
->dwExStyle
))
1102 xinc
= GetSystemMetrics(SM_CXDLGFRAME
);
1103 yinc
= GetSystemMetrics(SM_CYDLGFRAME
);
1108 if (HAS_THICKFRAME(wndPtr
->dwStyle
))
1110 xinc
+= GetSystemMetrics(SM_CXFRAME
);
1111 yinc
+= GetSystemMetrics(SM_CYFRAME
);
1113 if (wndPtr
->dwStyle
& WS_BORDER
)
1115 xinc
+= GetSystemMetrics(SM_CXBORDER
);
1116 yinc
+= GetSystemMetrics(SM_CYBORDER
);
1119 MinMax
.ptMaxSize
.x
+= 2 * xinc
;
1120 MinMax
.ptMaxSize
.y
+= 2 * yinc
;
1122 lpPos
= (LPINTERNALPOS
)GetPropA( wndPtr
->hwndSelf
, atomInternalPos
);
1123 if( lpPos
&& !EMPTYPOINT(lpPos
->ptMaxPos
) )
1124 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &MinMax
.ptMaxPosition
);
1127 MinMax
.ptMaxPosition
.x
= -xinc
;
1128 MinMax
.ptMaxPosition
.y
= -yinc
;
1131 SendMessageA( wndPtr
->hwndSelf
, WM_GETMINMAXINFO
, 0, (LPARAM
)&MinMax
);
1133 /* Some sanity checks */
1135 TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1136 MinMax
.ptMaxSize
.x
, MinMax
.ptMaxSize
.y
,
1137 MinMax
.ptMaxPosition
.x
, MinMax
.ptMaxPosition
.y
,
1138 MinMax
.ptMaxTrackSize
.x
, MinMax
.ptMaxTrackSize
.y
,
1139 MinMax
.ptMinTrackSize
.x
, MinMax
.ptMinTrackSize
.y
);
1140 MinMax
.ptMaxTrackSize
.x
= MAX( MinMax
.ptMaxTrackSize
.x
,
1141 MinMax
.ptMinTrackSize
.x
);
1142 MinMax
.ptMaxTrackSize
.y
= MAX( MinMax
.ptMaxTrackSize
.y
,
1143 MinMax
.ptMinTrackSize
.y
);
1145 if (maxSize
) *maxSize
= MinMax
.ptMaxSize
;
1146 if (maxPos
) *maxPos
= MinMax
.ptMaxPosition
;
1147 if (minTrack
) *minTrack
= MinMax
.ptMinTrackSize
;
1148 if (maxTrack
) *maxTrack
= MinMax
.ptMaxTrackSize
;
1151 /***********************************************************************
1152 * WINPOS_MinMaximize
1154 * Fill in lpRect and return additional flags to be used with SetWindowPos().
1155 * This function assumes that 'cmd' is different from the current window
1158 UINT
WINPOS_MinMaximize( WND
* wndPtr
, UINT16 cmd
, LPRECT16 lpRect
)
1162 LPINTERNALPOS lpPos
;
1164 TRACE("0x%04x %u\n", wndPtr
->hwndSelf
, cmd
);
1166 size
.x
= wndPtr
->rectWindow
.left
; size
.y
= wndPtr
->rectWindow
.top
;
1167 lpPos
= WINPOS_InitInternalPos( wndPtr
, size
, &wndPtr
->rectWindow
);
1169 if (lpPos
&& !HOOK_CallHooks16(WH_CBT
, HCBT_MINMAX
, wndPtr
->hwndSelf
, cmd
))
1171 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1173 if( !SendMessageA( wndPtr
->hwndSelf
, WM_QUERYOPEN
, 0, 0L ) )
1174 return (SWP_NOSIZE
| SWP_NOMOVE
);
1175 swpFlags
|= SWP_NOCOPYBITS
;
1180 if( wndPtr
->dwStyle
& WS_MAXIMIZE
)
1182 wndPtr
->flags
|= WIN_RESTORE_MAX
;
1183 wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
1186 wndPtr
->flags
&= ~WIN_RESTORE_MAX
;
1187 wndPtr
->dwStyle
|= WS_MINIMIZE
;
1189 if( wndPtr
->flags
& WIN_NATIVE
)
1190 if( wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, TRUE
) )
1191 swpFlags
|= MINMAX_NOSWP
;
1193 lpPos
->ptIconPos
= WINPOS_FindIconPos( wndPtr
, lpPos
->ptIconPos
);
1195 SetRect16( lpRect
, lpPos
->ptIconPos
.x
, lpPos
->ptIconPos
.y
,
1196 GetSystemMetrics(SM_CXICON
), GetSystemMetrics(SM_CYICON
) );
1197 swpFlags
|= SWP_NOCOPYBITS
;
1201 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &pt
);
1202 WINPOS_GetMinMaxInfo( wndPtr
, &size
, &pt
, NULL
, NULL
);
1203 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1205 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1207 if( wndPtr
->flags
& WIN_NATIVE
)
1208 if( wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, FALSE
) )
1209 swpFlags
|= MINMAX_NOSWP
;
1211 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
1212 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
1214 wndPtr
->dwStyle
|= WS_MAXIMIZE
;
1216 SetRect16( lpRect
, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
,
1221 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1223 if( wndPtr
->flags
& WIN_NATIVE
)
1224 if( wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, FALSE
) )
1225 swpFlags
|= MINMAX_NOSWP
;
1227 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
1228 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
1230 if( wndPtr
->flags
& WIN_RESTORE_MAX
)
1232 /* Restore to maximized position */
1233 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &pt
);
1234 WINPOS_GetMinMaxInfo( wndPtr
, &size
, &pt
, NULL
, NULL
);
1235 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1236 wndPtr
->dwStyle
|= WS_MAXIMIZE
;
1237 SetRect16( lpRect
, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
, size
.x
, size
.y
);
1242 if( !(wndPtr
->dwStyle
& WS_MAXIMIZE
) ) return (UINT16
)(-1);
1243 else wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
1245 /* Restore to normal position */
1247 *lpRect
= lpPos
->rectNormal
;
1248 lpRect
->right
-= lpRect
->left
;
1249 lpRect
->bottom
-= lpRect
->top
;
1253 } else swpFlags
|= SWP_NOSIZE
| SWP_NOMOVE
;
1257 /***********************************************************************
1258 * ShowWindowAsync (USER32.535)
1260 * doesn't wait; returns immediately.
1261 * used by threads to toggle windows in other (possibly hanging) threads
1263 BOOL WINAPI
ShowWindowAsync( HWND hwnd
, INT cmd
)
1265 /* FIXME: does ShowWindow() return immediately ? */
1266 return ShowWindow(hwnd
, cmd
);
1270 /***********************************************************************
1271 * ShowWindow16 (USER.42)
1273 BOOL16 WINAPI
ShowWindow16( HWND16 hwnd
, INT16 cmd
)
1275 return ShowWindow(hwnd
,cmd
);
1279 /***********************************************************************
1280 * ShowWindow (USER32.534)
1282 BOOL WINAPI
ShowWindow( HWND hwnd
, INT cmd
)
1284 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
1285 BOOL wasVisible
, showFlag
;
1286 RECT16 newPos
= {0, 0, 0, 0};
1289 if (!wndPtr
) return FALSE
;
1291 TRACE("hwnd=%04x, cmd=%d\n", hwnd
, cmd
);
1293 wasVisible
= (wndPtr
->dwStyle
& WS_VISIBLE
) != 0;
1298 if (!wasVisible
) goto END
;;
1299 swp
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
|
1300 SWP_NOACTIVATE
| SWP_NOZORDER
;
1303 case SW_SHOWMINNOACTIVE
:
1304 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1306 case SW_SHOWMINIMIZED
:
1307 swp
|= SWP_SHOWWINDOW
;
1310 swp
|= SWP_FRAMECHANGED
;
1311 if( !(wndPtr
->dwStyle
& WS_MINIMIZE
) )
1312 swp
|= WINPOS_MinMaximize( wndPtr
, SW_MINIMIZE
, &newPos
);
1313 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1316 case SW_SHOWMAXIMIZED
: /* same as SW_MAXIMIZE */
1317 swp
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
1318 if( !(wndPtr
->dwStyle
& WS_MAXIMIZE
) )
1319 swp
|= WINPOS_MinMaximize( wndPtr
, SW_MAXIMIZE
, &newPos
);
1320 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1324 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1327 swp
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
1330 * ShowWindow has a little peculiar behavior that if the
1331 * window is already the topmost window, it will not
1334 if (GetTopWindow((HWND
)0)==hwnd
&& (wasVisible
|| GetActiveWindow() == hwnd
))
1335 swp
|= SWP_NOACTIVATE
;
1339 case SW_SHOWNOACTIVATE
:
1340 swp
|= SWP_NOZORDER
;
1341 if (GetActiveWindow()) swp
|= SWP_NOACTIVATE
;
1343 case SW_SHOWNORMAL
: /* same as SW_NORMAL: */
1344 case SW_SHOWDEFAULT
: /* FIXME: should have its own handler */
1346 swp
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
1348 if( wndPtr
->dwStyle
& (WS_MINIMIZE
| WS_MAXIMIZE
) )
1349 swp
|= WINPOS_MinMaximize( wndPtr
, SW_RESTORE
, &newPos
);
1350 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1354 showFlag
= (cmd
!= SW_HIDE
);
1355 if (showFlag
!= wasVisible
)
1357 SendMessageA( hwnd
, WM_SHOWWINDOW
, showFlag
, 0 );
1358 if (!IsWindow( hwnd
)) goto END
;
1361 if ((wndPtr
->dwStyle
& WS_CHILD
) &&
1362 !IsWindowVisible( wndPtr
->parent
->hwndSelf
) &&
1363 (swp
& (SWP_NOSIZE
| SWP_NOMOVE
)) == (SWP_NOSIZE
| SWP_NOMOVE
) )
1365 /* Don't call SetWindowPos() on invisible child windows */
1366 if (cmd
== SW_HIDE
) wndPtr
->dwStyle
&= ~WS_VISIBLE
;
1367 else wndPtr
->dwStyle
|= WS_VISIBLE
;
1371 /* We can't activate a child window */
1372 if ((wndPtr
->dwStyle
& WS_CHILD
) &&
1373 !(wndPtr
->dwExStyle
& WS_EX_MDICHILD
))
1374 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1375 if (!(swp
& MINMAX_NOSWP
))
1377 SetWindowPos( hwnd
, HWND_TOP
, newPos
.left
, newPos
.top
,
1378 newPos
.right
, newPos
.bottom
, LOWORD(swp
) );
1381 /* FIXME: This will cause the window to be activated irrespective
1382 * of whether it is owned by the same thread. Has to be done
1386 if (hwnd
== GetActiveWindow())
1387 WINPOS_ActivateOtherWindow(wndPtr
);
1389 /* Revert focus to parent */
1390 if (hwnd
== GetFocus() || IsChild(hwnd
, GetFocus()))
1391 SetFocus( GetParent(hwnd
) );
1394 if (!IsWindow( hwnd
)) goto END
;
1395 else if( wndPtr
->dwStyle
& WS_MINIMIZE
) WINPOS_ShowIconTitle( wndPtr
, TRUE
);
1398 if (wndPtr
->flags
& WIN_NEED_SIZE
)
1400 /* should happen only in CreateWindowEx() */
1401 int wParam
= SIZE_RESTORED
;
1403 wndPtr
->flags
&= ~WIN_NEED_SIZE
;
1404 if (wndPtr
->dwStyle
& WS_MAXIMIZE
) wParam
= SIZE_MAXIMIZED
;
1405 else if (wndPtr
->dwStyle
& WS_MINIMIZE
) wParam
= SIZE_MINIMIZED
;
1406 SendMessageA( hwnd
, WM_SIZE
, wParam
,
1407 MAKELONG(wndPtr
->rectClient
.right
-wndPtr
->rectClient
.left
,
1408 wndPtr
->rectClient
.bottom
-wndPtr
->rectClient
.top
));
1409 SendMessageA( hwnd
, WM_MOVE
, 0,
1410 MAKELONG(wndPtr
->rectClient
.left
, wndPtr
->rectClient
.top
) );
1414 WIN_ReleaseWndPtr(wndPtr
);
1419 /***********************************************************************
1420 * GetInternalWindowPos16 (USER.460)
1422 UINT16 WINAPI
GetInternalWindowPos16( HWND16 hwnd
, LPRECT16 rectWnd
,
1425 WINDOWPLACEMENT16 wndpl
;
1426 if (GetWindowPlacement16( hwnd
, &wndpl
))
1428 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
1429 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
1430 return wndpl
.showCmd
;
1436 /***********************************************************************
1437 * GetInternalWindowPos (USER32.245)
1439 UINT WINAPI
GetInternalWindowPos( HWND hwnd
, LPRECT rectWnd
,
1442 WINDOWPLACEMENT wndpl
;
1443 if (GetWindowPlacement( hwnd
, &wndpl
))
1445 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
1446 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
1447 return wndpl
.showCmd
;
1452 /***********************************************************************
1453 * GetWindowPlacement16 (USER.370)
1455 BOOL16 WINAPI
GetWindowPlacement16( HWND16 hwnd
, WINDOWPLACEMENT16
*wndpl
)
1457 WND
*pWnd
= WIN_FindWndPtr( hwnd
);
1458 LPINTERNALPOS lpPos
;
1460 if(!pWnd
) return FALSE
;
1462 lpPos
= (LPINTERNALPOS
)WINPOS_InitInternalPos( pWnd
,
1463 *(LPPOINT
)&pWnd
->rectWindow
.left
, &pWnd
->rectWindow
);
1464 wndpl
->length
= sizeof(*wndpl
);
1465 if( pWnd
->dwStyle
& WS_MINIMIZE
)
1466 wndpl
->showCmd
= SW_SHOWMINIMIZED
;
1468 wndpl
->showCmd
= ( pWnd
->dwStyle
& WS_MAXIMIZE
)
1469 ? SW_SHOWMAXIMIZED
: SW_SHOWNORMAL
;
1470 if( pWnd
->flags
& WIN_RESTORE_MAX
)
1471 wndpl
->flags
= WPF_RESTORETOMAXIMIZED
;
1474 wndpl
->ptMinPosition
= lpPos
->ptIconPos
;
1475 wndpl
->ptMaxPosition
= lpPos
->ptMaxPos
;
1476 wndpl
->rcNormalPosition
= lpPos
->rectNormal
;
1478 WIN_ReleaseWndPtr(pWnd
);
1483 /***********************************************************************
1484 * GetWindowPlacement (USER32.307)
1487 * Fails if wndpl->length of Win95 (!) apps is invalid.
1489 BOOL WINAPI
GetWindowPlacement( HWND hwnd
, WINDOWPLACEMENT
*pwpl32
)
1493 WINDOWPLACEMENT16 wpl
;
1494 wpl
.length
= sizeof(wpl
);
1495 if( GetWindowPlacement16( hwnd
, &wpl
) )
1497 pwpl32
->length
= sizeof(*pwpl32
);
1498 pwpl32
->flags
= wpl
.flags
;
1499 pwpl32
->showCmd
= wpl
.showCmd
;
1500 CONV_POINT16TO32( &wpl
.ptMinPosition
, &pwpl32
->ptMinPosition
);
1501 CONV_POINT16TO32( &wpl
.ptMaxPosition
, &pwpl32
->ptMaxPosition
);
1502 CONV_RECT16TO32( &wpl
.rcNormalPosition
, &pwpl32
->rcNormalPosition
);
1510 /***********************************************************************
1511 * WINPOS_SetPlacement
1513 static BOOL
WINPOS_SetPlacement( HWND hwnd
, const WINDOWPLACEMENT16
*wndpl
,
1516 WND
*pWnd
= WIN_FindWndPtr( hwnd
);
1519 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)WINPOS_InitInternalPos( pWnd
,
1520 *(LPPOINT
)&pWnd
->rectWindow
.left
, &pWnd
->rectWindow
);
1522 if( flags
& PLACE_MIN
) lpPos
->ptIconPos
= wndpl
->ptMinPosition
;
1523 if( flags
& PLACE_MAX
) lpPos
->ptMaxPos
= wndpl
->ptMaxPosition
;
1524 if( flags
& PLACE_RECT
) lpPos
->rectNormal
= wndpl
->rcNormalPosition
;
1526 if( pWnd
->dwStyle
& WS_MINIMIZE
)
1528 WINPOS_ShowIconTitle( pWnd
, FALSE
);
1529 if( wndpl
->flags
& WPF_SETMINPOSITION
&& !EMPTYPOINT(lpPos
->ptIconPos
))
1530 SetWindowPos( hwnd
, 0, lpPos
->ptIconPos
.x
, lpPos
->ptIconPos
.y
,
1531 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1533 else if( pWnd
->dwStyle
& WS_MAXIMIZE
)
1535 if( !EMPTYPOINT(lpPos
->ptMaxPos
) )
1536 SetWindowPos( hwnd
, 0, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
,
1537 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1539 else if( flags
& PLACE_RECT
)
1540 SetWindowPos( hwnd
, 0, lpPos
->rectNormal
.left
, lpPos
->rectNormal
.top
,
1541 lpPos
->rectNormal
.right
- lpPos
->rectNormal
.left
,
1542 lpPos
->rectNormal
.bottom
- lpPos
->rectNormal
.top
,
1543 SWP_NOZORDER
| SWP_NOACTIVATE
);
1545 ShowWindow( hwnd
, wndpl
->showCmd
);
1546 if( IsWindow(hwnd
) && pWnd
->dwStyle
& WS_MINIMIZE
)
1548 if( pWnd
->dwStyle
& WS_VISIBLE
) WINPOS_ShowIconTitle( pWnd
, TRUE
);
1550 /* SDK: ...valid only the next time... */
1551 if( wndpl
->flags
& WPF_RESTORETOMAXIMIZED
) pWnd
->flags
|= WIN_RESTORE_MAX
;
1553 WIN_ReleaseWndPtr(pWnd
);
1560 /***********************************************************************
1561 * SetWindowPlacement16 (USER.371)
1563 BOOL16 WINAPI
SetWindowPlacement16(HWND16 hwnd
, const WINDOWPLACEMENT16
*wndpl
)
1565 return WINPOS_SetPlacement( hwnd
, wndpl
,
1566 PLACE_MIN
| PLACE_MAX
| PLACE_RECT
);
1569 /***********************************************************************
1570 * SetWindowPlacement (USER32.519)
1573 * Fails if wndpl->length of Win95 (!) apps is invalid.
1575 BOOL WINAPI
SetWindowPlacement( HWND hwnd
, const WINDOWPLACEMENT
*pwpl32
)
1579 WINDOWPLACEMENT16 wpl
;
1581 wpl
.length
= sizeof(WINDOWPLACEMENT16
);
1582 wpl
.flags
= pwpl32
->flags
;
1583 wpl
.showCmd
= pwpl32
->showCmd
;
1584 wpl
.ptMinPosition
.x
= pwpl32
->ptMinPosition
.x
;
1585 wpl
.ptMinPosition
.y
= pwpl32
->ptMinPosition
.y
;
1586 wpl
.ptMaxPosition
.x
= pwpl32
->ptMaxPosition
.x
;
1587 wpl
.ptMaxPosition
.y
= pwpl32
->ptMaxPosition
.y
;
1588 wpl
.rcNormalPosition
.left
= pwpl32
->rcNormalPosition
.left
;
1589 wpl
.rcNormalPosition
.top
= pwpl32
->rcNormalPosition
.top
;
1590 wpl
.rcNormalPosition
.right
= pwpl32
->rcNormalPosition
.right
;
1591 wpl
.rcNormalPosition
.bottom
= pwpl32
->rcNormalPosition
.bottom
;
1593 return WINPOS_SetPlacement( hwnd
, &wpl
, PLACE_MIN
| PLACE_MAX
| PLACE_RECT
);
1599 /***********************************************************************
1600 * SetInternalWindowPos16 (USER.461)
1602 void WINAPI
SetInternalWindowPos16( HWND16 hwnd
, UINT16 showCmd
,
1603 LPRECT16 rect
, LPPOINT16 pt
)
1605 if( IsWindow16(hwnd
) )
1607 WINDOWPLACEMENT16 wndpl
;
1610 wndpl
.length
= sizeof(wndpl
);
1611 wndpl
.showCmd
= showCmd
;
1612 wndpl
.flags
= flags
= 0;
1617 wndpl
.flags
|= WPF_SETMINPOSITION
;
1618 wndpl
.ptMinPosition
= *pt
;
1622 flags
|= PLACE_RECT
;
1623 wndpl
.rcNormalPosition
= *rect
;
1625 WINPOS_SetPlacement( hwnd
, &wndpl
, flags
);
1630 /***********************************************************************
1631 * SetInternalWindowPos (USER32.483)
1633 void WINAPI
SetInternalWindowPos( HWND hwnd
, UINT showCmd
,
1634 LPRECT rect
, LPPOINT pt
)
1636 if( IsWindow(hwnd
) )
1638 WINDOWPLACEMENT16 wndpl
;
1641 wndpl
.length
= sizeof(wndpl
);
1642 wndpl
.showCmd
= showCmd
;
1643 wndpl
.flags
= flags
= 0;
1648 wndpl
.flags
|= WPF_SETMINPOSITION
;
1649 CONV_POINT32TO16( pt
, &wndpl
.ptMinPosition
);
1653 flags
|= PLACE_RECT
;
1654 CONV_RECT32TO16( rect
, &wndpl
.rcNormalPosition
);
1656 WINPOS_SetPlacement( hwnd
, &wndpl
, flags
);
1660 /*******************************************************************
1661 * WINPOS_SetActiveWindow
1663 * SetActiveWindow() back-end. This is the only function that
1664 * can assign active status to a window. It must be called only
1665 * for the top level windows.
1667 BOOL
WINPOS_SetActiveWindow( HWND hWnd
, BOOL fMouse
, BOOL fChangeFocus
)
1669 CBTACTIVATESTRUCT16
* cbtStruct
;
1670 WND
* wndPtr
=0, *wndTemp
;
1671 HQUEUE16 hOldActiveQueue
, hNewActiveQueue
;
1672 MESSAGEQUEUE
*pOldActiveQueue
= 0, *pNewActiveQueue
= 0;
1674 HWND hwndActive
= 0;
1677 TRACE("(%04x, %d, %d)\n", hWnd
, fMouse
, fChangeFocus
);
1679 /* Get current active window from the active queue */
1682 pOldActiveQueue
= QUEUE_Lock( hActiveQueue
);
1683 if ( pOldActiveQueue
)
1684 hwndActive
= PERQDATA_GetActiveWnd( pOldActiveQueue
->pQData
);
1687 /* paranoid checks */
1688 if( hWnd
== GetDesktopWindow() || (bRet
= (hWnd
== hwndActive
)) )
1691 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1694 wndPtr
= WIN_FindWndPtr(hWnd
);
1695 hOldActiveQueue
= hActiveQueue
;
1697 if( (wndTemp
= WIN_FindWndPtr(hwndActive
)) )
1699 wIconized
= HIWORD(wndTemp
->dwStyle
& WS_MINIMIZE
);
1700 WIN_ReleaseWndPtr(wndTemp
);
1703 TRACE("no current active window.\n");
1705 /* call CBT hook chain */
1706 if ((cbtStruct
= SEGPTR_NEW(CBTACTIVATESTRUCT16
)))
1708 cbtStruct
->fMouse
= fMouse
;
1709 cbtStruct
->hWndActive
= hwndActive
;
1710 bRet
= (BOOL
)HOOK_CallHooks16( WH_CBT
, HCBT_ACTIVATE
, (WPARAM16
)hWnd
,
1711 (LPARAM
)SEGPTR_GET(cbtStruct
) );
1712 SEGPTR_FREE(cbtStruct
);
1713 if (bRet
) goto CLEANUP_END
;
1716 /* set prev active wnd to current active wnd and send notification */
1717 if ((hwndPrevActive
= hwndActive
) && IsWindow(hwndPrevActive
))
1719 MESSAGEQUEUE
*pTempActiveQueue
= 0;
1721 if (!SendMessageA( hwndPrevActive
, WM_NCACTIVATE
, FALSE
, 0 ))
1723 if (GetSysModalWindow16() != hWnd
)
1725 /* disregard refusal if hWnd is sysmodal */
1728 SendMessageA( hwndPrevActive
, WM_ACTIVATE
,
1729 MAKEWPARAM( WA_INACTIVE
, wIconized
),
1732 /* check if something happened during message processing
1733 * (global active queue may have changed)
1735 pTempActiveQueue
= QUEUE_Lock( hActiveQueue
);
1736 if(!pTempActiveQueue
)
1739 hwndActive
= PERQDATA_GetActiveWnd( pTempActiveQueue
->pQData
);
1740 QUEUE_Unlock( pTempActiveQueue
);
1741 if( hwndPrevActive
!= hwndActive
)
1745 /* Set new active window in the message queue */
1749 pNewActiveQueue
= QUEUE_Lock( wndPtr
->hmemTaskQ
);
1750 if ( pNewActiveQueue
)
1751 PERQDATA_SetActiveWnd( pNewActiveQueue
->pQData
, hwndActive
);
1753 else /* have to do this or MDI frame activation goes to hell */
1754 if( pOldActiveQueue
)
1755 PERQDATA_SetActiveWnd( pOldActiveQueue
->pQData
, 0 );
1757 /* send palette messages */
1758 if (hWnd
&& SendMessage16( hWnd
, WM_QUERYNEWPALETTE
, 0, 0L))
1759 SendMessage16((HWND16
)-1, WM_PALETTEISCHANGING
, (WPARAM16
)hWnd
, 0L );
1761 /* if prev wnd is minimized redraw icon title */
1762 if( IsIconic( hwndPrevActive
) ) WINPOS_RedrawIconTitle(hwndPrevActive
);
1764 /* managed windows will get ConfigureNotify event */
1765 if (wndPtr
&& !(wndPtr
->dwStyle
& WS_CHILD
) && !(wndPtr
->flags
& WIN_MANAGED
))
1767 /* check Z-order and bring hWnd to the top */
1768 for (wndTemp
= WIN_LockWndPtr(WIN_GetDesktop()->child
); wndTemp
; WIN_UpdateWndPtr(&wndTemp
,wndTemp
->next
))
1770 if (wndTemp
->dwStyle
& WS_VISIBLE
) break;
1772 WIN_ReleaseDesktop();
1773 WIN_ReleaseWndPtr(wndTemp
);
1775 if( wndTemp
!= wndPtr
)
1776 SetWindowPos(hWnd
, HWND_TOP
, 0,0,0,0,
1777 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
1778 if (!IsWindow(hWnd
))
1782 /* Get a handle to the new active queue */
1783 hNewActiveQueue
= wndPtr
? wndPtr
->hmemTaskQ
: 0;
1785 /* send WM_ACTIVATEAPP if necessary */
1786 if (hOldActiveQueue
!= hNewActiveQueue
)
1788 WND
**list
, **ppWnd
;
1789 WND
*pDesktop
= WIN_GetDesktop();
1791 if ((list
= WIN_BuildWinArray( pDesktop
, 0, NULL
)))
1793 for (ppWnd
= list
; *ppWnd
; ppWnd
++)
1795 if (!IsWindow( (*ppWnd
)->hwndSelf
)) continue;
1797 if ((*ppWnd
)->hmemTaskQ
== hOldActiveQueue
)
1798 SendMessage16( (*ppWnd
)->hwndSelf
, WM_ACTIVATEAPP
,
1799 0, QUEUE_GetQueueTask(hNewActiveQueue
) );
1801 WIN_ReleaseWinArray(list
);
1804 hActiveQueue
= hNewActiveQueue
;
1806 if ((list
= WIN_BuildWinArray(pDesktop
, 0, NULL
)))
1808 for (ppWnd
= list
; *ppWnd
; ppWnd
++)
1810 if (!IsWindow( (*ppWnd
)->hwndSelf
)) continue;
1812 if ((*ppWnd
)->hmemTaskQ
== hNewActiveQueue
)
1813 SendMessage16( (*ppWnd
)->hwndSelf
, WM_ACTIVATEAPP
,
1814 1, QUEUE_GetQueueTask( hOldActiveQueue
) );
1816 WIN_ReleaseWinArray(list
);
1818 WIN_ReleaseDesktop();
1820 if (hWnd
&& !IsWindow(hWnd
)) goto CLEANUP
;
1825 /* walk up to the first unowned window */
1826 wndTemp
= WIN_LockWndPtr(wndPtr
);
1827 while (wndTemp
->owner
)
1829 WIN_UpdateWndPtr(&wndTemp
,wndTemp
->owner
);
1831 /* and set last active owned popup */
1832 wndTemp
->hwndLastActive
= hWnd
;
1834 wIconized
= HIWORD(wndTemp
->dwStyle
& WS_MINIMIZE
);
1835 WIN_ReleaseWndPtr(wndTemp
);
1836 SendMessageA( hWnd
, WM_NCACTIVATE
, TRUE
, 0 );
1837 SendMessageA( hWnd
, WM_ACTIVATE
,
1838 MAKEWPARAM( (fMouse
) ? WA_CLICKACTIVE
: WA_ACTIVE
, wIconized
),
1839 (LPARAM
)hwndPrevActive
);
1840 if( !IsWindow(hWnd
) ) goto CLEANUP
;
1843 /* change focus if possible */
1846 if ( pNewActiveQueue
)
1848 HWND hOldFocus
= PERQDATA_GetFocusWnd( pNewActiveQueue
->pQData
);
1850 if ( WIN_GetTopParent( hOldFocus
) != hwndActive
)
1851 FOCUS_SwitchFocus( pNewActiveQueue
, hOldFocus
,
1852 (wndPtr
&& (wndPtr
->dwStyle
& WS_MINIMIZE
))?
1856 if ( pOldActiveQueue
&&
1857 ( !pNewActiveQueue
||
1858 pNewActiveQueue
->pQData
!= pOldActiveQueue
->pQData
) )
1860 HWND hOldFocus
= PERQDATA_GetFocusWnd( pOldActiveQueue
->pQData
);
1862 FOCUS_SwitchFocus( pOldActiveQueue
, hOldFocus
, 0 );
1866 if( !hwndPrevActive
&& wndPtr
)
1867 (*wndPtr
->pDriver
->pForceWindowRaise
)(wndPtr
);
1869 /* if active wnd is minimized redraw icon title */
1870 if( IsIconic(hwndActive
) ) WINPOS_RedrawIconTitle(hwndActive
);
1872 bRet
= (hWnd
== hwndActive
); /* Success? */
1874 CLEANUP
: /* Unlock the message queues before returning */
1876 if ( pNewActiveQueue
)
1877 QUEUE_Unlock( pNewActiveQueue
);
1881 if ( pOldActiveQueue
)
1882 QUEUE_Unlock( pOldActiveQueue
);
1884 WIN_ReleaseWndPtr(wndPtr
);
1888 /*******************************************************************
1889 * WINPOS_ActivateOtherWindow
1891 * Activates window other than pWnd.
1893 BOOL
WINPOS_ActivateOtherWindow(WND
* pWnd
)
1897 HWND hwndActive
= 0;
1899 /* Get current active window from the active queue */
1902 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
1905 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
1906 QUEUE_Unlock( pActiveQueue
);
1910 if( pWnd
->hwndSelf
== hwndPrevActive
)
1913 if( hwndActive
!= pWnd
->hwndSelf
&&
1914 ( hwndActive
|| QUEUE_IsExitingQueue(pWnd
->hmemTaskQ
)) )
1917 if( !(pWnd
->dwStyle
& WS_POPUP
) || !(pWnd
->owner
) ||
1918 !WINPOS_CanActivate((pWndTo
= WIN_GetTopParentPtr(pWnd
->owner
))) )
1920 WND
* pWndPtr
= WIN_GetTopParentPtr(pWnd
);
1922 WIN_ReleaseWndPtr(pWndTo
);
1923 pWndTo
= WIN_FindWndPtr(hwndPrevActive
);
1925 while( !WINPOS_CanActivate(pWndTo
) )
1927 /* by now owned windows should've been taken care of */
1928 WIN_UpdateWndPtr(&pWndTo
,pWndPtr
->next
);
1929 WIN_UpdateWndPtr(&pWndPtr
,pWndTo
);
1930 if( !pWndTo
) break;
1932 WIN_ReleaseWndPtr(pWndPtr
);
1935 bRet
= WINPOS_SetActiveWindow( pWndTo
? pWndTo
->hwndSelf
: 0, FALSE
, TRUE
);
1937 /* switch desktop queue to current active */
1940 WIN_GetDesktop()->hmemTaskQ
= pWndTo
->hmemTaskQ
;
1941 WIN_ReleaseWndPtr(pWndTo
);
1942 WIN_ReleaseDesktop();
1949 /*******************************************************************
1950 * WINPOS_ChangeActiveWindow
1953 BOOL
WINPOS_ChangeActiveWindow( HWND hWnd
, BOOL mouseMsg
)
1955 WND
*wndPtr
, *wndTemp
;
1957 HWND hwndActive
= 0;
1959 /* Get current active window from the active queue */
1962 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
1965 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
1966 QUEUE_Unlock( pActiveQueue
);
1971 return WINPOS_SetActiveWindow( 0, mouseMsg
, TRUE
);
1973 wndPtr
= WIN_FindWndPtr(hWnd
);
1974 if( !wndPtr
) return FALSE
;
1976 /* child windows get WM_CHILDACTIVATE message */
1977 if( (wndPtr
->dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1979 retvalue
= SendMessageA(hWnd
, WM_CHILDACTIVATE
, 0, 0L);
1983 if( hWnd
== hwndActive
)
1989 if( !WINPOS_SetActiveWindow(hWnd
,mouseMsg
,TRUE
) )
1995 /* switch desktop queue to current active */
1996 wndTemp
= WIN_GetDesktop();
1997 if( wndPtr
->parent
== wndTemp
)
1998 wndTemp
->hmemTaskQ
= wndPtr
->hmemTaskQ
;
1999 WIN_ReleaseDesktop();
2003 WIN_ReleaseWndPtr(wndPtr
);
2008 /***********************************************************************
2009 * WINPOS_SendNCCalcSize
2011 * Send a WM_NCCALCSIZE message to a window.
2012 * All parameters are read-only except newClientRect.
2013 * oldWindowRect, oldClientRect and winpos must be non-NULL only
2014 * when calcValidRect is TRUE.
2016 LONG
WINPOS_SendNCCalcSize( HWND hwnd
, BOOL calcValidRect
,
2017 RECT
*newWindowRect
, RECT
*oldWindowRect
,
2018 RECT
*oldClientRect
, WINDOWPOS
*winpos
,
2019 RECT
*newClientRect
)
2021 NCCALCSIZE_PARAMS params
;
2022 WINDOWPOS winposCopy
;
2025 params
.rgrc
[0] = *newWindowRect
;
2028 winposCopy
= *winpos
;
2029 params
.rgrc
[1] = *oldWindowRect
;
2030 params
.rgrc
[2] = *oldClientRect
;
2031 params
.lppos
= &winposCopy
;
2033 result
= SendMessageA( hwnd
, WM_NCCALCSIZE
, calcValidRect
,
2035 TRACE("%d,%d-%d,%d\n",
2036 params
.rgrc
[0].left
, params
.rgrc
[0].top
,
2037 params
.rgrc
[0].right
, params
.rgrc
[0].bottom
);
2039 /* If the application send back garbage, ignore it */
2040 if (params
.rgrc
[0].left
<= params
.rgrc
[0].right
&& params
.rgrc
[0].top
<= params
.rgrc
[0].bottom
)
2041 *newClientRect
= params
.rgrc
[0];
2047 /***********************************************************************
2048 * WINPOS_HandleWindowPosChanging16
2050 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2052 LONG
WINPOS_HandleWindowPosChanging16( WND
*wndPtr
, WINDOWPOS16
*winpos
)
2054 POINT maxSize
, minTrack
;
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
, &minTrack
, NULL
);
2060 if (maxSize
.x
< winpos
->cx
) winpos
->cx
= maxSize
.x
;
2061 if (maxSize
.y
< winpos
->cy
) winpos
->cy
= maxSize
.y
;
2062 if (!(wndPtr
->dwStyle
& WS_MINIMIZE
))
2064 if (winpos
->cx
< minTrack
.x
) winpos
->cx
= minTrack
.x
;
2065 if (winpos
->cy
< minTrack
.y
) winpos
->cy
= minTrack
.y
;
2072 /***********************************************************************
2073 * WINPOS_HandleWindowPosChanging
2075 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2077 LONG
WINPOS_HandleWindowPosChanging( WND
*wndPtr
, WINDOWPOS
*winpos
)
2080 if (winpos
->flags
& SWP_NOSIZE
) return 0;
2081 if ((wndPtr
->dwStyle
& WS_THICKFRAME
) ||
2082 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) == 0))
2084 WINPOS_GetMinMaxInfo( wndPtr
, &maxSize
, NULL
, NULL
, NULL
);
2085 winpos
->cx
= MIN( winpos
->cx
, maxSize
.x
);
2086 winpos
->cy
= MIN( winpos
->cy
, maxSize
.y
);
2091 /***********************************************************************
2094 * fix Z order taking into account owned popups -
2095 * basically we need to maintain them above the window that owns them
2097 * FIXME: hide/show owned popups when owner visibility changes.
2099 static HWND
SWP_DoOwnedPopups(WND
* pDesktop
, WND
* wndPtr
, HWND hwndInsertAfter
, WORD flags
)
2101 WND
* w
= WIN_LockWndPtr(pDesktop
->child
);
2103 WARN("(%04x) hInsertAfter = %04x\n", wndPtr
->hwndSelf
, hwndInsertAfter
);
2105 if( (wndPtr
->dwStyle
& WS_POPUP
) && wndPtr
->owner
)
2107 /* make sure this popup stays above the owner */
2109 HWND hwndLocalPrev
= HWND_TOP
;
2111 if( hwndInsertAfter
!= HWND_TOP
)
2113 while( w
!= wndPtr
->owner
)
2115 if (w
!= wndPtr
) hwndLocalPrev
= w
->hwndSelf
;
2116 if( hwndLocalPrev
== hwndInsertAfter
) break;
2117 WIN_UpdateWndPtr(&w
,w
->next
);
2119 hwndInsertAfter
= hwndLocalPrev
;
2122 else if( wndPtr
->dwStyle
& WS_CHILD
)
2125 WIN_UpdateWndPtr(&w
, pDesktop
->child
);
2129 if( w
== wndPtr
) break;
2131 if( (w
->dwStyle
& WS_POPUP
) && w
->owner
== wndPtr
)
2133 SetWindowPos(w
->hwndSelf
, hwndInsertAfter
, 0, 0, 0, 0,
2134 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOSENDCHANGING
| SWP_DEFERERASE
);
2135 hwndInsertAfter
= w
->hwndSelf
;
2137 WIN_UpdateWndPtr(&w
, w
->next
);
2141 WIN_ReleaseWndPtr(w
);
2142 return hwndInsertAfter
;
2145 /***********************************************************************
2148 * Make window look nice without excessive repainting
2150 * visible and update regions are in window coordinates
2151 * client and window rectangles are in parent client coordinates
2153 * FIXME: SWP_EX_PAINTSELF in uFlags works only if both old and new
2154 * window rects have the same origin.
2156 * Returns: uFlags and a dirty region in *pVisRgn.
2158 static UINT
SWP_CopyValidBits( WND
* Wnd
, HRGN
* pVisRgn
,
2159 LPRECT lpOldWndRect
,
2160 LPRECT lpOldClientRect
, UINT uFlags
)
2163 HRGN newVisRgn
, dirtyRgn
;
2164 INT my
= COMPLEXREGION
;
2166 TRACE("\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2167 Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
,
2168 Wnd
->rectWindow
.right
, Wnd
->rectWindow
.bottom
,
2169 lpOldWndRect
->left
, lpOldWndRect
->top
,
2170 lpOldWndRect
->right
, lpOldWndRect
->bottom
, *pVisRgn
);
2171 TRACE("\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2172 Wnd
->rectClient
.left
, Wnd
->rectClient
.top
,
2173 Wnd
->rectClient
.right
, Wnd
->rectClient
.bottom
,
2174 lpOldClientRect
->left
, lpOldClientRect
->top
,
2175 lpOldClientRect
->right
,lpOldClientRect
->bottom
);
2177 if( Wnd
->hrgnUpdate
== 1 )
2178 uFlags
|= SWP_EX_NOCOPY
; /* whole window is invalid, nothing to copy */
2180 newVisRgn
= DCE_GetVisRgn( Wnd
->hwndSelf
, DCX_WINDOW
| DCX_CLIPSIBLINGS
, 0, 0);
2181 dirtyRgn
= CreateRectRgn( 0, 0, 0, 0 );
2183 if( !(uFlags
& SWP_EX_NOCOPY
) ) /* make sure dst region covers only valid bits */
2184 my
= CombineRgn( dirtyRgn
, newVisRgn
, *pVisRgn
, RGN_AND
);
2186 if( (my
== NULLREGION
) || (uFlags
& SWP_EX_NOCOPY
) )
2190 TRACE("\twon't copy anything!\n");
2192 /* set dirtyRgn to the sum of old and new visible regions
2193 * in parent client coordinates */
2195 OffsetRgn( newVisRgn
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2196 OffsetRgn( *pVisRgn
, lpOldWndRect
->left
, lpOldWndRect
->top
);
2198 CombineRgn(*pVisRgn
, *pVisRgn
, newVisRgn
, RGN_OR
);
2200 else /* copy valid bits to a new location */
2202 INT dx
, dy
, ow
, oh
, nw
, nh
, ocw
, ncw
, och
, nch
;
2203 HRGN hrgnValid
= dirtyRgn
; /* non-empty intersection of old and new visible rgns */
2205 /* subtract already invalid region inside Wnd from the dst region */
2207 if( Wnd
->hrgnUpdate
)
2208 if( CombineRgn( hrgnValid
, hrgnValid
, Wnd
->hrgnUpdate
, RGN_DIFF
) == NULLREGION
)
2211 /* check if entire window can be copied */
2213 ow
= lpOldWndRect
->right
- lpOldWndRect
->left
;
2214 oh
= lpOldWndRect
->bottom
- lpOldWndRect
->top
;
2215 nw
= Wnd
->rectWindow
.right
- Wnd
->rectWindow
.left
;
2216 nh
= Wnd
->rectWindow
.bottom
- Wnd
->rectWindow
.top
;
2218 ocw
= lpOldClientRect
->right
- lpOldClientRect
->left
;
2219 och
= lpOldClientRect
->bottom
- lpOldClientRect
->top
;
2220 ncw
= Wnd
->rectClient
.right
- Wnd
->rectClient
.left
;
2221 nch
= Wnd
->rectClient
.bottom
- Wnd
->rectClient
.top
;
2223 if( (ocw
!= ncw
) || (och
!= nch
) ||
2224 ( ow
!= nw
) || ( oh
!= nh
) ||
2225 ((lpOldClientRect
->top
- lpOldWndRect
->top
) !=
2226 (Wnd
->rectClient
.top
- Wnd
->rectWindow
.top
)) ||
2227 ((lpOldClientRect
->left
- lpOldWndRect
->left
) !=
2228 (Wnd
->rectClient
.left
- Wnd
->rectWindow
.left
)) )
2230 dx
= Wnd
->rectClient
.left
- lpOldClientRect
->left
;
2231 dy
= Wnd
->rectClient
.top
- lpOldClientRect
->top
;
2233 /* restrict valid bits to the common client rect */
2235 r
.left
= Wnd
->rectClient
.left
- Wnd
->rectWindow
.left
;
2236 r
.top
= Wnd
->rectClient
.top
- Wnd
->rectWindow
.top
;
2237 r
.right
= r
.left
+ MIN( ocw
, ncw
);
2238 r
.bottom
= r
.top
+ MIN( och
, nch
);
2240 REGION_CropRgn( hrgnValid
, hrgnValid
, &r
,
2241 (uFlags
& SWP_EX_PAINTSELF
) ? NULL
: (POINT
*)&(Wnd
->rectWindow
));
2242 GetRgnBox( hrgnValid
, &r
);
2243 if( IsRectEmpty( &r
) )
2245 r
= *lpOldClientRect
;
2249 dx
= Wnd
->rectWindow
.left
- lpOldWndRect
->left
;
2250 dy
= Wnd
->rectWindow
.top
- lpOldWndRect
->top
;
2251 if( !(uFlags
& SWP_EX_PAINTSELF
) )
2252 OffsetRgn( hrgnValid
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2256 if( !(uFlags
& SWP_EX_PAINTSELF
) )
2258 /* Move remaining regions to parent coordinates */
2259 OffsetRgn( newVisRgn
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2260 OffsetRgn( *pVisRgn
, lpOldWndRect
->left
, lpOldWndRect
->top
);
2263 OffsetRect( &r
, -lpOldWndRect
->left
, -lpOldWndRect
->top
);
2265 TRACE("\tcomputing dirty region!\n");
2267 /* Compute combined dirty region (old + new - valid) */
2268 CombineRgn( *pVisRgn
, *pVisRgn
, newVisRgn
, RGN_OR
);
2269 CombineRgn( *pVisRgn
, *pVisRgn
, hrgnValid
, RGN_DIFF
);
2271 /* Blt valid bits, r is the rect to copy */
2279 /* get DC and clip rect with drawable rect to avoid superfluous expose events
2280 from copying clipped areas */
2282 if( uFlags
& SWP_EX_PAINTSELF
)
2284 hDC
= GetDCEx( Wnd
->hwndSelf
, hrgnValid
, DCX_WINDOW
| DCX_CACHE
|
2285 DCX_KEEPCLIPRGN
| DCX_INTERSECTRGN
| DCX_CLIPSIBLINGS
);
2286 rClip
.right
= nw
; rClip
.bottom
= nh
;
2290 hDC
= GetDCEx( Wnd
->parent
->hwndSelf
, hrgnValid
, DCX_CACHE
|
2291 DCX_KEEPCLIPRGN
| DCX_INTERSECTRGN
| DCX_CLIPSIBLINGS
);
2292 rClip
.right
= Wnd
->parent
->rectClient
.right
- Wnd
->parent
->rectClient
.left
;
2293 rClip
.bottom
= Wnd
->parent
->rectClient
.bottom
- Wnd
->parent
->rectClient
.top
;
2295 rClip
.left
= rClip
.top
= 0;
2297 if( (dc
= (DC
*)GDI_GetObjPtr(hDC
, DC_MAGIC
)) )
2299 if( oh
> nh
) r
.bottom
= r
.top
+ nh
;
2300 if( ow
< nw
) r
.right
= r
.left
+ nw
;
2302 if( IntersectRect( &r
, &r
, &rClip
) )
2304 Wnd
->pDriver
->pSurfaceCopy( Wnd
->parent
, dc
, dx
, dy
, &r
, TRUE
);
2306 /* When you copy the bits without repainting, parent doesn't
2307 get validated appropriately. Therefore, we have to validate
2308 the parent with the windows' updated region when the
2309 parent's update region is not empty. */
2311 if (Wnd
->parent
->hrgnUpdate
!= 0 && !(Wnd
->parent
->dwStyle
& WS_CLIPCHILDREN
))
2313 OffsetRect(&r
, dx
, dy
);
2314 ValidateRect(Wnd
->parent
->hwndSelf
, &r
);
2318 GDI_HEAP_UNLOCK( hDC
);
2320 ReleaseDC( (uFlags
& SWP_EX_PAINTSELF
) ?
2321 Wnd
->hwndSelf
: Wnd
->parent
->hwndSelf
, hDC
);
2325 /* *pVisRgn now points to the invalidated region */
2327 DeleteObject(newVisRgn
);
2328 DeleteObject(dirtyRgn
);
2332 /***********************************************************************
2333 * SWP_DoSimpleFrameChanged
2335 * NOTE: old and new client rect origins are identical, only
2336 * extents may have changed. Window extents are the same.
2338 static void SWP_DoSimpleFrameChanged( WND
* wndPtr
, RECT
* pOldClientRect
, WORD swpFlags
, UINT uFlags
)
2344 if( !(swpFlags
& SWP_NOCLIENTSIZE
) )
2346 /* Client rect changed its position/size, most likely a scrollar
2347 * was added/removed.
2349 * FIXME: WVR alignment flags
2352 if( wndPtr
->rectClient
.right
> pOldClientRect
->right
) /* right edge */
2356 rect
.bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
2357 rect
.right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
2358 if(!(uFlags
& SWP_EX_NOCOPY
))
2359 rect
.left
= pOldClientRect
->right
- wndPtr
->rectClient
.left
;
2367 if( wndPtr
->rectClient
.bottom
> pOldClientRect
->bottom
) /* bottom edge */
2370 hrgn
= CreateRectRgnIndirect( &rect
);
2372 rect
.right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
2373 rect
.bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
2374 if(!(uFlags
& SWP_EX_NOCOPY
))
2375 rect
.top
= pOldClientRect
->bottom
- wndPtr
->rectClient
.top
;
2379 REGION_UnionRectWithRgn( hrgn
, &rect
);
2382 if( i
== 0 && (uFlags
& SWP_EX_NOCOPY
) ) /* force redraw anyway */
2384 rect
= wndPtr
->rectWindow
;
2385 OffsetRect( &rect
, wndPtr
->rectWindow
.left
- wndPtr
->rectClient
.left
,
2386 wndPtr
->rectWindow
.top
- wndPtr
->rectClient
.top
);
2394 PAINT_RedrawWindow( wndPtr
->hwndSelf
, &rect
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
|
2395 RDW_ERASENOW
| RDW_ALLCHILDREN
, RDW_EX_TOPFRAME
| RDW_EX_USEHRGN
);
2399 WIN_UpdateNCRgn(wndPtr
, 0, UNC_UPDATE
| UNC_ENTIRE
);
2403 DeleteObject( hrgn
);
2406 /***********************************************************************
2407 * SWP_DoWinPosChanging
2409 static BOOL
SWP_DoWinPosChanging( WND
* wndPtr
, WINDOWPOS
* pWinpos
,
2410 RECT
* pNewWindowRect
, RECT
* pNewClientRect
)
2412 /* Send WM_WINDOWPOSCHANGING message */
2414 if (!(pWinpos
->flags
& SWP_NOSENDCHANGING
))
2415 SendMessageA( wndPtr
->hwndSelf
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
)pWinpos
);
2417 /* Calculate new position and size */
2419 *pNewWindowRect
= wndPtr
->rectWindow
;
2420 *pNewClientRect
= (wndPtr
->dwStyle
& WS_MINIMIZE
) ? wndPtr
->rectWindow
2421 : wndPtr
->rectClient
;
2423 if (!(pWinpos
->flags
& SWP_NOSIZE
))
2425 pNewWindowRect
->right
= pNewWindowRect
->left
+ pWinpos
->cx
;
2426 pNewWindowRect
->bottom
= pNewWindowRect
->top
+ pWinpos
->cy
;
2428 if (!(pWinpos
->flags
& SWP_NOMOVE
))
2430 pNewWindowRect
->left
= pWinpos
->x
;
2431 pNewWindowRect
->top
= pWinpos
->y
;
2432 pNewWindowRect
->right
+= pWinpos
->x
- wndPtr
->rectWindow
.left
;
2433 pNewWindowRect
->bottom
+= pWinpos
->y
- wndPtr
->rectWindow
.top
;
2435 OffsetRect( pNewClientRect
, pWinpos
->x
- wndPtr
->rectWindow
.left
,
2436 pWinpos
->y
- wndPtr
->rectWindow
.top
);
2439 pWinpos
->flags
|= SWP_NOCLIENTMOVE
| SWP_NOCLIENTSIZE
;
2443 /***********************************************************************
2446 static UINT
SWP_DoNCCalcSize( WND
* wndPtr
, WINDOWPOS
* pWinpos
,
2447 RECT
* pNewWindowRect
, RECT
* pNewClientRect
, WORD f
)
2451 /* Send WM_NCCALCSIZE message to get new client area */
2452 if( (pWinpos
->flags
& (SWP_FRAMECHANGED
| SWP_NOSIZE
)) != SWP_NOSIZE
)
2454 wvrFlags
= WINPOS_SendNCCalcSize( pWinpos
->hwnd
, TRUE
, pNewWindowRect
,
2455 &wndPtr
->rectWindow
, &wndPtr
->rectClient
,
2456 pWinpos
, pNewClientRect
);
2458 /* FIXME: WVR_ALIGNxxx */
2460 if( pNewClientRect
->left
!= wndPtr
->rectClient
.left
||
2461 pNewClientRect
->top
!= wndPtr
->rectClient
.top
)
2462 pWinpos
->flags
&= ~SWP_NOCLIENTMOVE
;
2464 if( (pNewClientRect
->right
- pNewClientRect
->left
!=
2465 wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
) ||
2466 (pNewClientRect
->bottom
- pNewClientRect
->top
!=
2467 wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
) )
2468 pWinpos
->flags
&= ~SWP_NOCLIENTSIZE
;
2471 if( !(f
& SWP_NOMOVE
) && (pNewClientRect
->left
!= wndPtr
->rectClient
.left
||
2472 pNewClientRect
->top
!= wndPtr
->rectClient
.top
) )
2473 pWinpos
->flags
&= ~SWP_NOCLIENTMOVE
;
2477 /***********************************************************************
2478 * SetWindowPos (USER.2)
2480 BOOL16 WINAPI
SetWindowPos16( HWND16 hwnd
, HWND16 hwndInsertAfter
,
2481 INT16 x
, INT16 y
, INT16 cx
, INT16 cy
, WORD flags
)
2483 return SetWindowPos(hwnd
,(INT
)(INT16
)hwndInsertAfter
,x
,y
,cx
,cy
,flags
);
2486 /***********************************************************************
2487 * SetWindowPos (USER32.520)
2489 BOOL WINAPI
SetWindowPos( HWND hwnd
, HWND hwndInsertAfter
,
2490 INT x
, INT y
, INT cx
, INT cy
, UINT flags
)
2493 WND
* wndPtr
,*wndTemp
;
2494 RECT newWindowRect
, newClientRect
;
2495 RECT oldWindowRect
, oldClientRect
;
2497 UINT wvrFlags
= 0, uFlags
= 0;
2498 BOOL retvalue
, resync
= FALSE
, bChangePos
;
2499 HWND hwndActive
= 0;
2501 /* Get current active window from the active queue */
2504 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
2507 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
2508 QUEUE_Unlock( pActiveQueue
);
2512 TRACE("hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2513 hwnd
, x
, y
, x
+cx
, y
+cy
, flags
);
2515 bChangePos
= !(flags
& SWP_WINE_NOHOSTMOVE
);
2516 flags
&= ~SWP_WINE_NOHOSTMOVE
;
2519 /* ------------------------------------------------------------------------ CHECKS */
2521 /* Check window handle */
2523 if (hwnd
== GetDesktopWindow()) return FALSE
;
2524 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return FALSE
;
2526 TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr
->rectWindow
.left
, wndPtr
->rectWindow
.top
,
2527 wndPtr
->rectWindow
.right
, wndPtr
->rectWindow
.bottom
, (unsigned)wndPtr
->dwStyle
);
2529 /* Fix redundant flags */
2531 if(wndPtr
->dwStyle
& WS_VISIBLE
)
2532 flags
&= ~SWP_SHOWWINDOW
;
2535 if (!(flags
& SWP_SHOWWINDOW
))
2536 flags
|= SWP_NOREDRAW
;
2537 flags
&= ~SWP_HIDEWINDOW
;
2540 if ( cx
< 0 ) cx
= 0; if( cy
< 0 ) cy
= 0;
2542 if ((wndPtr
->rectWindow
.right
- wndPtr
->rectWindow
.left
== cx
) &&
2543 (wndPtr
->rectWindow
.bottom
- wndPtr
->rectWindow
.top
== cy
))
2544 flags
|= SWP_NOSIZE
; /* Already the right size */
2546 if ((wndPtr
->rectWindow
.left
== x
) && (wndPtr
->rectWindow
.top
== y
))
2547 flags
|= SWP_NOMOVE
; /* Already the right position */
2549 if (hwnd
== hwndActive
)
2550 flags
|= SWP_NOACTIVATE
; /* Already active */
2551 else if ( (wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)
2553 if(!(flags
& SWP_NOACTIVATE
)) /* Bring to the top when activating */
2555 flags
&= ~SWP_NOZORDER
;
2556 hwndInsertAfter
= HWND_TOP
;
2561 /* Check hwndInsertAfter */
2563 /* FIXME: TOPMOST not supported yet */
2564 if ((hwndInsertAfter
== HWND_TOPMOST
) ||
2565 (hwndInsertAfter
== HWND_NOTOPMOST
)) hwndInsertAfter
= HWND_TOP
;
2567 /* hwndInsertAfter must be a sibling of the window */
2568 if ((hwndInsertAfter
!= HWND_TOP
) && (hwndInsertAfter
!= HWND_BOTTOM
))
2570 WND
* wnd
= WIN_FindWndPtr(hwndInsertAfter
);
2573 if( wnd
->parent
!= wndPtr
->parent
)
2576 WIN_ReleaseWndPtr(wnd
);
2579 if( wnd
->next
== wndPtr
) flags
|= SWP_NOZORDER
;
2581 WIN_ReleaseWndPtr(wnd
);
2584 Pos
: /* ------------------------------------------------------------------------ MAIN part */
2586 /* Fill the WINDOWPOS structure */
2589 winpos
.hwndInsertAfter
= hwndInsertAfter
;
2594 winpos
.flags
= flags
;
2596 SWP_DoWinPosChanging( wndPtr
, &winpos
, &newWindowRect
, &newClientRect
);
2598 if((winpos
.flags
& (SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) != SWP_NOZORDER
)
2600 if( wndPtr
->parent
== WIN_GetDesktop() )
2601 hwndInsertAfter
= SWP_DoOwnedPopups( wndPtr
->parent
, wndPtr
,
2602 hwndInsertAfter
, winpos
.flags
);
2603 WIN_ReleaseDesktop();
2606 if(!(wndPtr
->flags
& WIN_NATIVE
) )
2608 if( hwndInsertAfter
== HWND_TOP
)
2609 winpos
.flags
|= ( wndPtr
->parent
->child
== wndPtr
)? SWP_NOZORDER
: 0;
2611 if( hwndInsertAfter
== HWND_BOTTOM
)
2612 winpos
.flags
|= ( wndPtr
->next
)? 0: SWP_NOZORDER
;
2614 if( !(winpos
.flags
& SWP_NOZORDER
) )
2615 if( GetWindow(hwndInsertAfter
, GW_HWNDNEXT
) == wndPtr
->hwndSelf
)
2616 winpos
.flags
|= SWP_NOZORDER
;
2618 if( !(winpos
.flags
& (SWP_NOREDRAW
| SWP_SHOWWINDOW
)) &&
2619 ((winpos
.flags
& (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_FRAMECHANGED
))
2620 != (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
)) )
2622 /* get a previous visible region for SWP_CopyValidBits() */
2623 DWORD flags
= DCX_WINDOW
;
2625 if (wndPtr
->dwStyle
& WS_CLIPSIBLINGS
)
2626 flags
|= DCX_CLIPSIBLINGS
;
2628 visRgn
= DCE_GetVisRgn(hwnd
, flags
, 0, 0);
2632 /* Common operations */
2634 wvrFlags
= SWP_DoNCCalcSize( wndPtr
, &winpos
, &newWindowRect
, &newClientRect
, flags
);
2636 if(!(winpos
.flags
& SWP_NOZORDER
))
2638 if ( WIN_UnlinkWindow( winpos
.hwnd
) )
2639 WIN_LinkWindow( winpos
.hwnd
, hwndInsertAfter
);
2642 /* Reset active DCEs */
2644 if( (((winpos
.flags
& SWP_AGG_NOPOSCHANGE
) != SWP_AGG_NOPOSCHANGE
) &&
2645 wndPtr
->dwStyle
& WS_VISIBLE
) ||
2646 (flags
& (SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) )
2650 UnionRect(&rect
, &newWindowRect
, &wndPtr
->rectWindow
);
2651 DCE_InvalidateDCE(wndPtr
, &rect
);
2654 oldWindowRect
= wndPtr
->rectWindow
;
2655 oldClientRect
= wndPtr
->rectClient
;
2657 /* Find out if we have to redraw the whole client rect */
2659 if( oldClientRect
.bottom
- oldClientRect
.top
==
2660 newClientRect
.bottom
- newClientRect
.top
) wvrFlags
&= ~WVR_VREDRAW
;
2662 if( oldClientRect
.right
- oldClientRect
.left
==
2663 newClientRect
.right
- newClientRect
.left
) wvrFlags
&= ~WVR_HREDRAW
;
2665 if( (winpos
.flags
& SWP_NOCOPYBITS
) || (!(winpos
.flags
& SWP_NOCLIENTSIZE
) &&
2666 (wvrFlags
>= WVR_HREDRAW
) && (wvrFlags
< WVR_VALIDRECTS
)) )
2668 uFlags
|= SWP_EX_NOCOPY
;
2671 * Use this later in CopyValidBits()
2674 uFlags |= SWP_EX_NONCLIENT;
2677 /* FIXME: actually do something with WVR_VALIDRECTS */
2679 wndPtr
->rectWindow
= newWindowRect
;
2680 wndPtr
->rectClient
= newClientRect
;
2682 if (wndPtr
->flags
& WIN_NATIVE
) /* -------------------------------------------- hosted window */
2684 BOOL bCallDriver
= TRUE
;
2685 HWND tempInsertAfter
= winpos
.hwndInsertAfter
;
2687 winpos
.hwndInsertAfter
= hwndInsertAfter
;
2689 if( !(winpos
.flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
| SWP_NOREDRAW
)) )
2691 /* This is the only place where we need to force repainting of the contents
2692 of windows created by the host window system, all other cases go through the
2693 expose event handling */
2695 if( (winpos
.flags
& (SWP_NOSIZE
| SWP_FRAMECHANGED
)) == (SWP_NOSIZE
| SWP_FRAMECHANGED
) )
2697 cx
= newWindowRect
.right
- newWindowRect
.left
;
2698 cy
= newWindowRect
.bottom
- newWindowRect
.top
;
2700 wndPtr
->pDriver
->pSetWindowPos(wndPtr
, &winpos
, bChangePos
);
2701 winpos
.hwndInsertAfter
= tempInsertAfter
;
2702 bCallDriver
= FALSE
;
2704 if( winpos
.flags
& SWP_NOCLIENTMOVE
)
2705 SWP_DoSimpleFrameChanged(wndPtr
, &oldClientRect
, winpos
.flags
, uFlags
);
2708 /* client area moved but window extents remained the same, copy valid bits */
2710 visRgn
= CreateRectRgn( 0, 0, cx
, cy
);
2711 uFlags
= SWP_CopyValidBits( wndPtr
, &visRgn
, &oldWindowRect
, &oldClientRect
,
2712 uFlags
| SWP_EX_PAINTSELF
);
2719 if( !(winpos
.flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
| SWP_NOREDRAW
)) )
2721 if( (oldClientRect
.left
- oldWindowRect
.left
== newClientRect
.left
- newWindowRect
.left
) &&
2722 (oldClientRect
.top
- oldWindowRect
.top
== newClientRect
.top
- newWindowRect
.top
) &&
2723 !(uFlags
& SWP_EX_NOCOPY
) )
2725 /* The origin of the client rect didn't move so we can try to repaint
2726 * only the nonclient area by setting bit gravity hint for the host window system.
2729 if( !(wndPtr
->flags
& WIN_MANAGED
) )
2731 HRGN hrgn
= CreateRectRgn( 0, 0, newWindowRect
.right
- newWindowRect
.left
,
2732 newWindowRect
.bottom
- newWindowRect
.top
);
2733 RECT rcn
= newClientRect
;
2734 RECT rco
= oldClientRect
;
2736 OffsetRect( &rcn
, -newWindowRect
.left
, -newWindowRect
.top
);
2737 OffsetRect( &rco
, -oldWindowRect
.left
, -oldWindowRect
.top
);
2738 IntersectRect( &rcn
, &rcn
, &rco
);
2739 visRgn
= CreateRectRgnIndirect( &rcn
);
2740 CombineRgn( visRgn
, hrgn
, visRgn
, RGN_DIFF
);
2741 DeleteObject( hrgn
);
2742 uFlags
= SWP_EX_PAINTSELF
;
2744 wndPtr
->pDriver
->pSetHostAttr(wndPtr
, HAK_BITGRAVITY
, BGNorthWest
);
2747 wndPtr
->pDriver
->pSetHostAttr(wndPtr
, HAK_BITGRAVITY
, BGForget
);
2750 wndPtr
->pDriver
->pSetWindowPos(wndPtr
, &winpos
, bChangePos
);
2751 winpos
.hwndInsertAfter
= tempInsertAfter
;
2754 if( winpos
.flags
& SWP_SHOWWINDOW
)
2758 wndPtr
->dwStyle
|= WS_VISIBLE
;
2760 if (wndPtr
->flags
& WIN_MANAGED
) resync
= TRUE
;
2762 /* focus was set to unmapped window, reset host focus
2763 * since the window is now visible */
2765 focus
= curr
= GetFocus();
2770 WND
*pFocus
= WIN_FindWndPtr( focus
);
2772 pFocus
->pDriver
->pSetFocus(pFocus
);
2773 WIN_ReleaseWndPtr(pFocus
);
2776 curr
= GetParent(curr
);
2780 else /* -------------------------------------------- emulated window */
2782 if( winpos
.flags
& SWP_SHOWWINDOW
)
2784 wndPtr
->dwStyle
|= WS_VISIBLE
;
2785 uFlags
|= SWP_EX_PAINTSELF
;
2786 visRgn
= 1; /* redraw the whole window */
2788 else if( !(winpos
.flags
& SWP_NOREDRAW
) )
2790 if( winpos
.flags
& SWP_HIDEWINDOW
)
2792 if( visRgn
> 1 ) /* map to parent */
2793 OffsetRgn( visRgn
, oldWindowRect
.left
, oldWindowRect
.top
);
2799 if( (winpos
.flags
& SWP_AGG_NOPOSCHANGE
) != SWP_AGG_NOPOSCHANGE
)
2800 uFlags
= SWP_CopyValidBits(wndPtr
, &visRgn
, &oldWindowRect
,
2801 &oldClientRect
, uFlags
);
2804 /* nothing moved, redraw frame if needed */
2806 if( winpos
.flags
& SWP_FRAMECHANGED
)
2807 SWP_DoSimpleFrameChanged( wndPtr
, &oldClientRect
, winpos
.flags
, uFlags
);
2810 DeleteObject( visRgn
);
2818 if( winpos
.flags
& SWP_HIDEWINDOW
)
2820 wndPtr
->dwStyle
&= ~WS_VISIBLE
;
2822 if (hwnd
== CARET_GetHwnd()) DestroyCaret();
2825 /* ------------------------------------------------------------------------ FINAL */
2827 if (wndPtr
->flags
& WIN_NATIVE
)
2828 EVENT_Synchronize(); /* Synchronize with the host window system */
2830 if (!GetCapture() && ((wndPtr
->dwStyle
& WS_VISIBLE
) || (flags
& SWP_HIDEWINDOW
)))
2832 /* Simulate a mouse event to set the cursor */
2833 DWORD posX
, posY
, keyState
;
2835 if ( EVENT_QueryPointer( &posX
, &posY
, &keyState
) )
2837 int iWndsLocks
= WIN_SuspendWndsLock();
2839 hardware_event( WM_MOUSEMOVE
, keyState
, 0,
2840 posX
, posY
, GetTickCount(), 0 );
2842 WIN_RestoreWndsLock(iWndsLocks
);
2846 wndTemp
= WIN_GetDesktop();
2848 /* repaint invalidated region (if any)
2850 * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2851 * and force update after ChangeActiveWindow() to avoid painting frames twice.
2856 if( !(winpos
.flags
& SWP_NOREDRAW
) )
2859 /* Use PAINT_RedrawWindow to explicitly force an invalidation of the window,
2860 its parent and sibling and so on, and then erase the parent window
2861 back ground if the parent is either a top-level window or its parent's parent
2862 is top-level window. Rely on the system to repaint other affected
2863 windows later on. */
2864 if( uFlags
& SWP_EX_PAINTSELF
)
2866 PAINT_RedrawWindow( wndPtr
->hwndSelf
, NULL
, (visRgn
== 1) ? 0 : visRgn
,
2867 RDW_ERASE
| RDW_FRAME
| RDW_INVALIDATE
| RDW_ALLCHILDREN
,
2868 RDW_EX_XYWINDOW
| RDW_EX_USEHRGN
);
2872 PAINT_RedrawWindow( wndPtr
->parent
->hwndSelf
, NULL
, (visRgn
== 1) ? 0 : visRgn
,
2873 RDW_ERASE
| RDW_INVALIDATE
| RDW_ALLCHILDREN
,
2877 if(wndPtr
-> parent
== wndTemp
|| wndPtr
->parent
->parent
== wndTemp
)
2879 PAINT_RedrawWindow( wndPtr
->parent
->hwndSelf
, NULL
, 0,
2880 RDW_ERASENOW
| RDW_NOCHILDREN
, 0 );
2884 DeleteObject( visRgn
);
2887 WIN_ReleaseDesktop();
2889 if (!(flags
& SWP_NOACTIVATE
))
2890 WINPOS_ChangeActiveWindow( winpos
.hwnd
, FALSE
);
2892 /* And last, send the WM_WINDOWPOSCHANGED message */
2894 TRACE("\tstatus flags = %04x\n", winpos
.flags
& SWP_AGG_STATUSFLAGS
);
2897 (((winpos
.flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOPOSCHANGE
) &&
2898 !(winpos
.flags
& SWP_NOSENDCHANGING
)) )
2900 SendMessageA( winpos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
)&winpos
);
2901 if (resync
) EVENT_Synchronize();
2906 WIN_ReleaseWndPtr(wndPtr
);
2911 /***********************************************************************
2912 * BeginDeferWindowPos16 (USER.259)
2914 HDWP16 WINAPI
BeginDeferWindowPos16( INT16 count
)
2916 return BeginDeferWindowPos( count
);
2920 /***********************************************************************
2921 * BeginDeferWindowPos (USER32.9)
2923 HDWP WINAPI
BeginDeferWindowPos( INT count
)
2928 if (count
<= 0) return 0;
2929 handle
= USER_HEAP_ALLOC( sizeof(DWP
) + (count
-1)*sizeof(WINDOWPOS
) );
2930 if (!handle
) return 0;
2931 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( handle
);
2932 pDWP
->actualCount
= 0;
2933 pDWP
->suggestedCount
= count
;
2935 pDWP
->wMagic
= DWP_MAGIC
;
2936 pDWP
->hwndParent
= 0;
2941 /***********************************************************************
2942 * DeferWindowPos16 (USER.260)
2944 HDWP16 WINAPI
DeferWindowPos16( HDWP16 hdwp
, HWND16 hwnd
, HWND16 hwndAfter
,
2945 INT16 x
, INT16 y
, INT16 cx
, INT16 cy
,
2948 return DeferWindowPos( hdwp
, hwnd
, (INT
)(INT16
)hwndAfter
,
2949 x
, y
, cx
, cy
, flags
);
2953 /***********************************************************************
2954 * DeferWindowPos (USER32.128)
2956 HDWP WINAPI
DeferWindowPos( HDWP hdwp
, HWND hwnd
, HWND hwndAfter
,
2957 INT x
, INT y
, INT cx
, INT cy
,
2962 HDWP newhdwp
= hdwp
,retvalue
;
2966 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
2967 if (!pDWP
) return 0;
2968 if (hwnd
== GetDesktopWindow()) return 0;
2970 if (!(pWnd
=WIN_FindWndPtr( hwnd
))) {
2971 USER_HEAP_FREE( hdwp
);
2975 /* Numega Bounds Checker Demo dislikes the following code.
2976 In fact, I've not been able to find any "same parent" requirement in any docu
2980 /* All the windows of a DeferWindowPos() must have the same parent */
2981 parent
= pWnd
->parent
->hwndSelf
;
2982 if (pDWP
->actualCount
== 0) pDWP
->hwndParent
= parent
;
2983 else if (parent
!= pDWP
->hwndParent
)
2985 USER_HEAP_FREE( hdwp
);
2991 for (i
= 0; i
< pDWP
->actualCount
; i
++)
2993 if (pDWP
->winPos
[i
].hwnd
== hwnd
)
2995 /* Merge with the other changes */
2996 if (!(flags
& SWP_NOZORDER
))
2998 pDWP
->winPos
[i
].hwndInsertAfter
= hwndAfter
;
3000 if (!(flags
& SWP_NOMOVE
))
3002 pDWP
->winPos
[i
].x
= x
;
3003 pDWP
->winPos
[i
].y
= y
;
3005 if (!(flags
& SWP_NOSIZE
))
3007 pDWP
->winPos
[i
].cx
= cx
;
3008 pDWP
->winPos
[i
].cy
= cy
;
3010 pDWP
->winPos
[i
].flags
&= flags
| ~(SWP_NOSIZE
| SWP_NOMOVE
|
3011 SWP_NOZORDER
| SWP_NOREDRAW
|
3012 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
3014 pDWP
->winPos
[i
].flags
|= flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
|
3020 if (pDWP
->actualCount
>= pDWP
->suggestedCount
)
3022 newhdwp
= USER_HEAP_REALLOC( hdwp
,
3023 sizeof(DWP
) + pDWP
->suggestedCount
*sizeof(WINDOWPOS
) );
3029 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( newhdwp
);
3030 pDWP
->suggestedCount
++;
3032 pDWP
->winPos
[pDWP
->actualCount
].hwnd
= hwnd
;
3033 pDWP
->winPos
[pDWP
->actualCount
].hwndInsertAfter
= hwndAfter
;
3034 pDWP
->winPos
[pDWP
->actualCount
].x
= x
;
3035 pDWP
->winPos
[pDWP
->actualCount
].y
= y
;
3036 pDWP
->winPos
[pDWP
->actualCount
].cx
= cx
;
3037 pDWP
->winPos
[pDWP
->actualCount
].cy
= cy
;
3038 pDWP
->winPos
[pDWP
->actualCount
].flags
= flags
;
3039 pDWP
->actualCount
++;
3042 WIN_ReleaseWndPtr(pWnd
);
3047 /***********************************************************************
3048 * EndDeferWindowPos16 (USER.261)
3050 BOOL16 WINAPI
EndDeferWindowPos16( HDWP16 hdwp
)
3052 return EndDeferWindowPos( hdwp
);
3056 /***********************************************************************
3057 * EndDeferWindowPos (USER32.173)
3059 BOOL WINAPI
EndDeferWindowPos( HDWP hdwp
)
3066 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
3067 if (!pDWP
) return FALSE
;
3068 for (i
= 0, winpos
= pDWP
->winPos
; i
< pDWP
->actualCount
; i
++, winpos
++)
3070 if (!(res
= SetWindowPos( winpos
->hwnd
, winpos
->hwndInsertAfter
,
3071 winpos
->x
, winpos
->y
, winpos
->cx
,
3072 winpos
->cy
, winpos
->flags
))) break;
3074 USER_HEAP_FREE( hdwp
);
3079 /***********************************************************************
3080 * TileChildWindows (USER.199)
3082 void WINAPI
TileChildWindows16( HWND16 parent
, WORD action
)
3084 FIXME("(%04x, %d): stub\n", parent
, action
);
3087 /***********************************************************************
3088 * CascageChildWindows (USER.198)
3090 void WINAPI
CascadeChildWindows16( HWND16 parent
, WORD action
)
3092 FIXME("(%04x, %d): stub\n", parent
, action
);
3095 /***********************************************************************
3096 * SetProgmanWindow [USER32.522]
3098 HRESULT WINAPI
SetProgmanWindow ( HWND hwnd
)
3100 hGlobalProgmanWindow
= hwnd
;
3101 return hGlobalProgmanWindow
;
3104 /***********************************************************************
3105 * GetProgmanWindow [USER32.289]
3107 HRESULT WINAPI
GetProgmanWindow ( )
3109 return hGlobalProgmanWindow
;
3112 /***********************************************************************
3113 * SetShellWindowEx [USER32.531]
3114 * hwndProgman = Progman[Program Manager]
3115 * |-> SHELLDLL_DefView
3116 * hwndListView = | |-> SysListView32
3117 * | | |-> tooltips_class32
3123 HRESULT WINAPI
SetShellWindowEx ( HWND hwndProgman
, HWND hwndListView
)
3125 FIXME("0x%08x 0x%08x stub\n",hwndProgman
,hwndListView
);
3126 hGlobalShellWindow
= hwndProgman
;
3127 return hGlobalShellWindow
;
3131 /***********************************************************************
3132 * SetTaskmanWindow [USER32.537]
3134 * hwnd = MSTaskSwWClass
3135 * |-> SysTabControl32
3137 HRESULT WINAPI
SetTaskmanWindow ( HWND hwnd
)
3139 hGlobalTaskmanWindow
= hwnd
;
3140 return hGlobalTaskmanWindow
;
3143 /***********************************************************************
3144 * GetTaskmanWindow [USER32.304]
3146 HRESULT WINAPI
GetTaskmanWindow ( )
3148 return hGlobalTaskmanWindow
;