2 * Window position related functions.
4 * Copyright 1993, 1994, 1995 Alexandre Julliard
5 * 1995, 1996, 1999 Alex Korobka
13 #include "wine/winuser16.h"
26 #include "nonclient.h"
27 #include "debugtools.h"
32 DEFAULT_DEBUG_CHANNEL(win
)
34 #define HAS_DLGFRAME(style,exStyle) \
35 (((exStyle) & WS_EX_DLGMODALFRAME) || \
36 (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
38 #define HAS_THICKFRAME(style) \
39 (((style) & WS_THICKFRAME) && \
40 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
42 #define SWP_AGG_NOGEOMETRYCHANGE \
43 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
44 #define SWP_AGG_NOPOSCHANGE \
45 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
46 #define SWP_AGG_STATUSFLAGS \
47 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
49 #define EMPTYPOINT(pt) ((*(LONG*)&(pt)) == -1)
51 #define PLACE_MIN 0x0001
52 #define PLACE_MAX 0x0002
53 #define PLACE_RECT 0x0004
55 #define SWP_EX_NOCOPY 0x0001
56 #define SWP_EX_PAINTSELF 0x0002
57 #define SWP_EX_NONCLIENT 0x0004
59 #define MINMAX_NOSWP 0x00010000
61 /* ----- internal variables ----- */
63 static HWND hwndPrevActive
= 0; /* Previously active window */
64 static HWND hGlobalShellWindow
=0; /*the shell*/
65 static HWND hGlobalTaskmanWindow
=0;
66 static HWND hGlobalProgmanWindow
=0;
68 static LPCSTR atomInternalPos
;
70 extern HQUEUE16 hActiveQueue
;
72 /***********************************************************************
73 * WINPOS_CreateInternalPosAtom
75 BOOL
WINPOS_CreateInternalPosAtom()
78 atomInternalPos
= (LPCSTR
)(DWORD
)GlobalAddAtomA(str
);
79 return (atomInternalPos
) ? TRUE
: FALSE
;
82 /***********************************************************************
83 * WINPOS_CheckInternalPos
85 * Called when a window is destroyed.
87 void WINPOS_CheckInternalPos( WND
* wndPtr
)
90 MESSAGEQUEUE
*pMsgQ
= 0;
91 HWND hwnd
= wndPtr
->hwndSelf
;
93 lpPos
= (LPINTERNALPOS
) GetPropA( hwnd
, atomInternalPos
);
95 /* Retrieve the message queue associated with this window */
96 pMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( wndPtr
->hmemTaskQ
);
99 WARN("\tMessage queue not found. Exiting!\n" );
103 if( hwnd
== hwndPrevActive
) hwndPrevActive
= 0;
105 if( hwnd
== PERQDATA_GetActiveWnd( pMsgQ
->pQData
) )
107 PERQDATA_SetActiveWnd( pMsgQ
->pQData
, 0 );
108 WARN("\tattempt to activate destroyed window!\n");
113 if( IsWindow(lpPos
->hwndIconTitle
) )
114 DestroyWindow( lpPos
->hwndIconTitle
);
115 HeapFree( SystemHeap
, 0, lpPos
);
118 QUEUE_Unlock( pMsgQ
);
122 /***********************************************************************
125 * Find a suitable place for an iconic window.
127 static POINT16
WINPOS_FindIconPos( WND
* wndPtr
, POINT16 pt
)
130 short x
, y
, xspacing
, yspacing
;
132 GetClientRect16( wndPtr
->parent
->hwndSelf
, &rectParent
);
133 if ((pt
.x
>= rectParent
.left
) && (pt
.x
+ GetSystemMetrics(SM_CXICON
) < rectParent
.right
) &&
134 (pt
.y
>= rectParent
.top
) && (pt
.y
+ GetSystemMetrics(SM_CYICON
) < rectParent
.bottom
))
135 return pt
; /* The icon already has a suitable position */
137 xspacing
= GetSystemMetrics(SM_CXICONSPACING
);
138 yspacing
= GetSystemMetrics(SM_CYICONSPACING
);
140 y
= rectParent
.bottom
;
146 /* Check if another icon already occupies this spot */
147 WND
*childPtr
= WIN_LockWndPtr(wndPtr
->parent
->child
);
150 if ((childPtr
->dwStyle
& WS_MINIMIZE
) && (childPtr
!= wndPtr
))
152 if ((childPtr
->rectWindow
.left
< x
+ xspacing
) &&
153 (childPtr
->rectWindow
.right
>= x
) &&
154 (childPtr
->rectWindow
.top
<= y
) &&
155 (childPtr
->rectWindow
.bottom
> y
- yspacing
))
156 break; /* There's a window in there */
158 WIN_UpdateWndPtr(&childPtr
,childPtr
->next
);
160 WIN_ReleaseWndPtr(childPtr
);
161 if (!childPtr
) /* No window was found, so it's OK for us */
163 pt
.x
= x
+ (xspacing
- GetSystemMetrics(SM_CXICON
)) / 2;
164 pt
.y
= y
- (yspacing
+ GetSystemMetrics(SM_CYICON
)) / 2;
168 } while(x
<= rectParent
.right
-xspacing
);
174 /***********************************************************************
175 * ArrangeIconicWindows16 (USER.170)
177 UINT16 WINAPI
ArrangeIconicWindows16( HWND16 parent
)
179 return ArrangeIconicWindows(parent
);
181 /***********************************************************************
182 * ArrangeIconicWindows (USER32.7)
184 UINT WINAPI
ArrangeIconicWindows( HWND parent
)
188 INT x
, y
, xspacing
, yspacing
;
190 GetClientRect( parent
, &rectParent
);
192 y
= rectParent
.bottom
;
193 xspacing
= GetSystemMetrics(SM_CXICONSPACING
);
194 yspacing
= GetSystemMetrics(SM_CYICONSPACING
);
196 hwndChild
= GetWindow( parent
, GW_CHILD
);
199 if( IsIconic( hwndChild
) )
201 WND
*wndPtr
= WIN_FindWndPtr(hwndChild
);
203 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
205 SetWindowPos( hwndChild
, 0, x
+ (xspacing
- GetSystemMetrics(SM_CXICON
)) / 2,
206 y
- yspacing
- GetSystemMetrics(SM_CYICON
)/2, 0, 0,
207 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
208 if( IsWindow(hwndChild
) )
209 WINPOS_ShowIconTitle(wndPtr
, TRUE
);
210 WIN_ReleaseWndPtr(wndPtr
);
212 if (x
<= rectParent
.right
- xspacing
) x
+= xspacing
;
219 hwndChild
= GetWindow( hwndChild
, GW_HWNDNEXT
);
225 /***********************************************************************
226 * SwitchToThisWindow16 (USER.172)
228 void WINAPI
SwitchToThisWindow16( HWND16 hwnd
, BOOL16 restore
)
230 SwitchToThisWindow( hwnd
, restore
);
234 /***********************************************************************
235 * SwitchToThisWindow (USER32.539)
237 void WINAPI
SwitchToThisWindow( HWND hwnd
, BOOL restore
)
239 ShowWindow( hwnd
, restore
? SW_RESTORE
: SW_SHOWMINIMIZED
);
243 /***********************************************************************
244 * GetWindowRect16 (USER.32)
246 void WINAPI
GetWindowRect16( HWND16 hwnd
, LPRECT16 rect
)
248 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
251 CONV_RECT32TO16( &wndPtr
->rectWindow
, rect
);
252 if (wndPtr
->dwStyle
& WS_CHILD
)
253 MapWindowPoints16( wndPtr
->parent
->hwndSelf
, 0, (POINT16
*)rect
, 2 );
254 WIN_ReleaseWndPtr(wndPtr
);
258 /***********************************************************************
259 * GetWindowRect (USER32.308)
261 BOOL WINAPI
GetWindowRect( HWND hwnd
, LPRECT rect
)
263 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
264 if (!wndPtr
) return FALSE
;
266 *rect
= wndPtr
->rectWindow
;
267 if (wndPtr
->dwStyle
& WS_CHILD
)
268 MapWindowPoints( wndPtr
->parent
->hwndSelf
, 0, (POINT
*)rect
, 2 );
269 WIN_ReleaseWndPtr(wndPtr
);
274 /***********************************************************************
275 * GetWindowRgn (USER32)
277 int WINAPI
GetWindowRgn ( HWND hwnd
, HRGN hrgn
)
280 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
283 if (wndPtr
->hrgnWnd
) nRet
= CombineRgn( hrgn
, wndPtr
->hrgnWnd
, 0, RGN_COPY
);
284 WIN_ReleaseWndPtr(wndPtr
);
289 /***********************************************************************
290 * SetWindowRgn (USER32)
292 int WINAPI
SetWindowRgn( HWND hwnd
, HRGN hrgn
, BOOL bRedraw
)
297 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
299 if (!wndPtr
) return FALSE
;
301 /* a region exists for this window */
302 if (hrgn
!= 0 && hrgn
== wndPtr
->hrgnWnd
)
304 /* can't replace actual region with same region
305 since we're now owner of that region
307 SetLastError(ERROR_INVALID_HANDLE
);
313 /* delete previous region */
314 DeleteObject(wndPtr
->hrgnWnd
);
318 /* we'd like to set it back to 0 */
321 GetWindowRect(hwnd
, &tempRect
);
325 /* verify that region really exists */
326 if (GetRgnBox(hrgn
, &tempRect
) == ERROR
) goto done
;
329 /* valid region handle */
330 wndPtr
->hrgnWnd
= hrgn
;
331 SetWindowPos( hwnd
, NULL
, tempRect
.left
, tempRect
.top
,
332 tempRect
.right
- tempRect
.left
, tempRect
.bottom
- tempRect
.top
,
333 SWP_NOSIZE
| SWP_FRAMECHANGED
| SWP_NOMOVE
|
334 SWP_NOZORDER
| (bRedraw
? 0 : SWP_NOREDRAW
) );
336 wndPtr
->pDriver
->pSetWindowRgn(wndPtr
, hrgn
);
341 WIN_ReleaseWndPtr(wndPtr
);
345 /***********************************************************************
348 INT16 WINAPI
SetWindowRgn16( HWND16 hwnd
, HRGN16 hrgn
,BOOL16 bRedraw
)
352 FIXME("SetWindowRgn16: stub\n");
357 /***********************************************************************
358 * GetClientRect16 (USER.33)
360 void WINAPI
GetClientRect16( HWND16 hwnd
, LPRECT16 rect
)
362 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
364 rect
->left
= rect
->top
= rect
->right
= rect
->bottom
= 0;
367 rect
->right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
368 rect
->bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
370 WIN_ReleaseWndPtr(wndPtr
);
374 /***********************************************************************
375 * GetClientRect (USER.220)
377 BOOL WINAPI
GetClientRect( HWND hwnd
, LPRECT rect
)
379 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
381 rect
->left
= rect
->top
= rect
->right
= rect
->bottom
= 0;
382 if (!wndPtr
) return FALSE
;
383 rect
->right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
384 rect
->bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
386 WIN_ReleaseWndPtr(wndPtr
);
391 /*******************************************************************
392 * ClientToScreen16 (USER.28)
394 void WINAPI
ClientToScreen16( HWND16 hwnd
, LPPOINT16 lppnt
)
396 MapWindowPoints16( hwnd
, 0, lppnt
, 1 );
400 /*******************************************************************
401 * ClientToScreen (USER32.52)
403 BOOL WINAPI
ClientToScreen( HWND hwnd
, LPPOINT lppnt
)
405 MapWindowPoints( hwnd
, 0, lppnt
, 1 );
410 /*******************************************************************
411 * ScreenToClient16 (USER.29)
413 void WINAPI
ScreenToClient16( HWND16 hwnd
, LPPOINT16 lppnt
)
415 MapWindowPoints16( 0, hwnd
, lppnt
, 1 );
419 /*******************************************************************
420 * ScreenToClient (USER32.447)
422 BOOL WINAPI
ScreenToClient( HWND hwnd
, LPPOINT lppnt
)
424 MapWindowPoints( 0, hwnd
, lppnt
, 1 );
429 /***********************************************************************
430 * WINPOS_WindowFromPoint
432 * Find the window and hittest for a given point.
434 INT16
WINPOS_WindowFromPoint( WND
* wndScope
, POINT16 pt
, WND
**ppWnd
)
437 INT16 hittest
= HTERROR
;
442 wndPtr
= WIN_LockWndPtr(wndScope
->child
);
444 if( wndScope
->dwStyle
& WS_DISABLED
)
450 if( wndScope
->flags
& WIN_MANAGED
)
452 /* In managed mode we have to check wndScope first as it is also
453 * a window which received the mouse event. */
455 if( pt
.x
< wndScope
->rectClient
.left
|| pt
.x
>= wndScope
->rectClient
.right
||
456 pt
.y
< wndScope
->rectClient
.top
|| pt
.y
>= wndScope
->rectClient
.bottom
)
459 MapWindowPoints16( GetDesktopWindow16(), wndScope
->hwndSelf
, &xy
, 1 );
465 /* If point is in window, and window is visible, and it */
466 /* is enabled (or it's a top-level window), then explore */
467 /* its children. Otherwise, go to the next window. */
469 if ((wndPtr
->dwStyle
& WS_VISIBLE
) &&
470 (!(wndPtr
->dwStyle
& WS_DISABLED
) ||
471 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)) &&
472 (xy
.x
>= wndPtr
->rectWindow
.left
) &&
473 (xy
.x
< wndPtr
->rectWindow
.right
) &&
474 (xy
.y
>= wndPtr
->rectWindow
.top
) &&
475 (xy
.y
< wndPtr
->rectWindow
.bottom
))
477 *ppWnd
= wndPtr
; /* Got a suitable window */
479 /* If window is minimized or disabled, return at once */
480 if (wndPtr
->dwStyle
& WS_MINIMIZE
)
482 retvalue
= HTCAPTION
;
485 if (wndPtr
->dwStyle
& WS_DISABLED
)
491 /* If point is not in client area, ignore the children */
492 if ((xy
.x
< wndPtr
->rectClient
.left
) ||
493 (xy
.x
>= wndPtr
->rectClient
.right
) ||
494 (xy
.y
< wndPtr
->rectClient
.top
) ||
495 (xy
.y
>= wndPtr
->rectClient
.bottom
)) break;
497 xy
.x
-= wndPtr
->rectClient
.left
;
498 xy
.y
-= wndPtr
->rectClient
.top
;
499 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->child
);
503 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->next
);
508 /* If nothing found, try the scope window */
509 if (!*ppWnd
) *ppWnd
= wndScope
;
511 /* Send the WM_NCHITTEST message (only if to the same task) */
512 if ((*ppWnd
)->hmemTaskQ
== GetFastQueue16())
514 hittest
= (INT16
)SendMessage16( (*ppWnd
)->hwndSelf
, WM_NCHITTEST
,
515 0, MAKELONG( pt
.x
, pt
.y
) );
516 if (hittest
!= HTTRANSPARENT
)
518 retvalue
= hittest
; /* Found the window */
528 /* If no children found in last search, make point relative to parent */
531 xy
.x
+= (*ppWnd
)->rectClient
.left
;
532 xy
.y
+= (*ppWnd
)->rectClient
.top
;
535 /* Restart the search from the next sibling */
536 WIN_UpdateWndPtr(&wndPtr
,(*ppWnd
)->next
);
537 *ppWnd
= (*ppWnd
)->parent
;
541 WIN_ReleaseWndPtr(wndPtr
);
546 /*******************************************************************
547 * WindowFromPoint16 (USER.30)
549 HWND16 WINAPI
WindowFromPoint16( POINT16 pt
)
552 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt
, &pWnd
);
553 WIN_ReleaseDesktop();
554 return pWnd
->hwndSelf
;
558 /*******************************************************************
559 * WindowFromPoint (USER32.582)
561 HWND WINAPI
WindowFromPoint( POINT pt
)
565 CONV_POINT32TO16( &pt
, &pt16
);
566 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16
, &pWnd
);
567 WIN_ReleaseDesktop();
568 return (HWND
)pWnd
->hwndSelf
;
572 /*******************************************************************
573 * ChildWindowFromPoint16 (USER.191)
575 HWND16 WINAPI
ChildWindowFromPoint16( HWND16 hwndParent
, POINT16 pt
)
578 CONV_POINT16TO32( &pt
, &pt32
);
579 return (HWND16
)ChildWindowFromPoint( hwndParent
, pt32
);
583 /*******************************************************************
584 * ChildWindowFromPoint (USER32.49)
586 HWND WINAPI
ChildWindowFromPoint( HWND hwndParent
, POINT pt
)
588 /* pt is in the client coordinates */
590 WND
* wnd
= WIN_FindWndPtr(hwndParent
);
596 /* get client rect fast */
597 rect
.top
= rect
.left
= 0;
598 rect
.right
= wnd
->rectClient
.right
- wnd
->rectClient
.left
;
599 rect
.bottom
= wnd
->rectClient
.bottom
- wnd
->rectClient
.top
;
601 if (!PtInRect( &rect
, pt
))
606 WIN_UpdateWndPtr(&wnd
,wnd
->child
);
609 if (PtInRect( &wnd
->rectWindow
, pt
))
611 retvalue
= wnd
->hwndSelf
;
614 WIN_UpdateWndPtr(&wnd
,wnd
->next
);
616 retvalue
= hwndParent
;
618 WIN_ReleaseWndPtr(wnd
);
622 /*******************************************************************
623 * ChildWindowFromPointEx16 (USER.50)
625 HWND16 WINAPI
ChildWindowFromPointEx16( HWND16 hwndParent
, POINT16 pt
, UINT16 uFlags
)
628 CONV_POINT16TO32( &pt
, &pt32
);
629 return (HWND16
)ChildWindowFromPointEx( hwndParent
, pt32
, uFlags
);
633 /*******************************************************************
634 * ChildWindowFromPointEx (USER32.50)
636 HWND WINAPI
ChildWindowFromPointEx( HWND hwndParent
, POINT pt
,
639 /* pt is in the client coordinates */
641 WND
* wnd
= WIN_FindWndPtr(hwndParent
);
647 /* get client rect fast */
648 rect
.top
= rect
.left
= 0;
649 rect
.right
= wnd
->rectClient
.right
- wnd
->rectClient
.left
;
650 rect
.bottom
= wnd
->rectClient
.bottom
- wnd
->rectClient
.top
;
652 if (!PtInRect( &rect
, pt
))
657 WIN_UpdateWndPtr(&wnd
,wnd
->child
);
661 if (PtInRect( &wnd
->rectWindow
, pt
)) {
662 if ( (uFlags
& CWP_SKIPINVISIBLE
) &&
663 !(wnd
->dwStyle
& WS_VISIBLE
) );
664 else if ( (uFlags
& CWP_SKIPDISABLED
) &&
665 (wnd
->dwStyle
& WS_DISABLED
) );
666 else if ( (uFlags
& CWP_SKIPTRANSPARENT
) &&
667 (wnd
->dwExStyle
& WS_EX_TRANSPARENT
) );
670 retvalue
= wnd
->hwndSelf
;
675 WIN_UpdateWndPtr(&wnd
,wnd
->next
);
677 retvalue
= hwndParent
;
679 WIN_ReleaseWndPtr(wnd
);
684 /*******************************************************************
685 * WINPOS_GetWinOffset
687 * Calculate the offset between the origin of the two windows. Used
688 * to implement MapWindowPoints.
690 static void WINPOS_GetWinOffset( HWND hwndFrom
, HWND hwndTo
,
695 offset
->x
= offset
->y
= 0;
696 if (hwndFrom
== hwndTo
) return;
698 /* Translate source window origin to screen coords */
701 if (!(wndPtr
= WIN_FindWndPtr( hwndFrom
)))
703 ERR("bad hwndFrom = %04x\n",hwndFrom
);
706 while (wndPtr
->parent
)
708 offset
->x
+= wndPtr
->rectClient
.left
;
709 offset
->y
+= wndPtr
->rectClient
.top
;
710 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->parent
);
712 WIN_ReleaseWndPtr(wndPtr
);
715 /* Translate origin to destination window coords */
718 if (!(wndPtr
= WIN_FindWndPtr( hwndTo
)))
720 ERR("bad hwndTo = %04x\n", hwndTo
);
723 while (wndPtr
->parent
)
725 offset
->x
-= wndPtr
->rectClient
.left
;
726 offset
->y
-= wndPtr
->rectClient
.top
;
727 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->parent
);
729 WIN_ReleaseWndPtr(wndPtr
);
734 /*******************************************************************
735 * MapWindowPoints16 (USER.258)
737 void WINAPI
MapWindowPoints16( HWND16 hwndFrom
, HWND16 hwndTo
,
738 LPPOINT16 lppt
, UINT16 count
)
742 WINPOS_GetWinOffset( hwndFrom
, hwndTo
, &offset
);
752 /*******************************************************************
753 * MapWindowPoints (USER32.386)
755 INT WINAPI
MapWindowPoints( HWND hwndFrom
, HWND hwndTo
,
756 LPPOINT lppt
, UINT count
)
760 WINPOS_GetWinOffset( hwndFrom
, hwndTo
, &offset
);
767 return MAKELONG( LOWORD(offset
.x
), LOWORD(offset
.y
) );
771 /***********************************************************************
772 * IsIconic16 (USER.31)
774 BOOL16 WINAPI
IsIconic16(HWND16 hWnd
)
776 return IsIconic(hWnd
);
780 /***********************************************************************
781 * IsIconic (USER32.345)
783 BOOL WINAPI
IsIconic(HWND hWnd
)
786 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
787 if (wndPtr
== NULL
) return FALSE
;
788 retvalue
= (wndPtr
->dwStyle
& WS_MINIMIZE
) != 0;
789 WIN_ReleaseWndPtr(wndPtr
);
794 /***********************************************************************
795 * IsZoomed (USER.272)
797 BOOL16 WINAPI
IsZoomed16(HWND16 hWnd
)
799 return IsZoomed(hWnd
);
803 /***********************************************************************
804 * IsZoomed (USER.352)
806 BOOL WINAPI
IsZoomed(HWND hWnd
)
809 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
810 if (wndPtr
== NULL
) return FALSE
;
811 retvalue
= (wndPtr
->dwStyle
& WS_MAXIMIZE
) != 0;
812 WIN_ReleaseWndPtr(wndPtr
);
817 /*******************************************************************
818 * GetActiveWindow (USER.60)
820 HWND16 WINAPI
GetActiveWindow16(void)
822 return (HWND16
)GetActiveWindow();
825 /*******************************************************************
826 * GetActiveWindow (USER32.205)
828 HWND WINAPI
GetActiveWindow(void)
830 MESSAGEQUEUE
*pCurMsgQ
= 0;
833 /* Get the messageQ for the current thread */
834 if (!(pCurMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( GetFastQueue16() )))
836 WARN("\tCurrent message queue not found. Exiting!\n" );
840 /* Return the current active window from the perQ data of the current message Q */
841 hwndActive
= PERQDATA_GetActiveWnd( pCurMsgQ
->pQData
);
843 QUEUE_Unlock( pCurMsgQ
);
848 /*******************************************************************
851 static BOOL
WINPOS_CanActivate(WND
* pWnd
)
853 if( pWnd
&& ( (pWnd
->dwStyle
& (WS_DISABLED
| WS_VISIBLE
| WS_CHILD
))
854 == WS_VISIBLE
) ) return TRUE
;
859 /*******************************************************************
860 * SetActiveWindow16 (USER.59)
862 HWND16 WINAPI
SetActiveWindow16( HWND16 hwnd
)
864 return SetActiveWindow(hwnd
);
868 /*******************************************************************
869 * SetActiveWindow (USER32.463)
871 HWND WINAPI
SetActiveWindow( HWND hwnd
)
874 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
875 MESSAGEQUEUE
*pMsgQ
= 0, *pCurMsgQ
= 0;
877 if (!wndPtr
|| (wndPtr
->dwStyle
& (WS_DISABLED
| WS_CHILD
)))
883 /* Get the messageQ for the current thread */
884 if (!(pCurMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( GetFastQueue16() )))
886 WARN("\tCurrent message queue not found. Exiting!\n" );
890 /* Retrieve the message queue associated with this window */
891 pMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( wndPtr
->hmemTaskQ
);
894 WARN("\tWindow message queue not found. Exiting!\n" );
898 /* Make sure that the window is associated with the calling threads
899 * message queue. It must share the same perQ data.
902 if ( pCurMsgQ
->pQData
!= pMsgQ
->pQData
)
905 /* Save current active window */
906 prev
= PERQDATA_GetActiveWnd( pMsgQ
->pQData
);
908 WINPOS_SetActiveWindow( hwnd
, 0, 0 );
911 /* Unlock the queues before returning */
913 QUEUE_Unlock( pMsgQ
);
915 QUEUE_Unlock( pCurMsgQ
);
918 WIN_ReleaseWndPtr(wndPtr
);
923 /*******************************************************************
924 * GetForegroundWindow16 (USER.608)
926 HWND16 WINAPI
GetForegroundWindow16(void)
928 return (HWND16
)GetForegroundWindow();
932 /*******************************************************************
933 * SetForegroundWindow16 (USER.609)
935 BOOL16 WINAPI
SetForegroundWindow16( HWND16 hwnd
)
937 return SetForegroundWindow( hwnd
);
941 /*******************************************************************
942 * GetForegroundWindow (USER32.241)
944 HWND WINAPI
GetForegroundWindow(void)
948 /* Get the foreground window (active window of hActiveQueue) */
951 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
953 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
955 QUEUE_Unlock( pActiveQueue
);
961 /*******************************************************************
962 * SetForegroundWindow (USER32.482)
964 BOOL WINAPI
SetForegroundWindow( HWND hwnd
)
966 return WINPOS_ChangeActiveWindow( hwnd
, FALSE
);
970 /*******************************************************************
971 * GetShellWindow16 (USER.600)
973 HWND16 WINAPI
GetShellWindow16(void)
975 return GetShellWindow();
978 /*******************************************************************
979 * SetShellWindow (USER32.504)
981 HWND WINAPI
SetShellWindow(HWND hwndshell
)
982 { WARN("(hWnd=%08x) semi stub\n",hwndshell
);
984 hGlobalShellWindow
= hwndshell
;
985 return hGlobalShellWindow
;
989 /*******************************************************************
990 * GetShellWindow (USER32.287)
992 HWND WINAPI
GetShellWindow(void)
993 { WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow
);
995 return hGlobalShellWindow
;
999 /***********************************************************************
1000 * BringWindowToTop16 (USER.45)
1002 BOOL16 WINAPI
BringWindowToTop16( HWND16 hwnd
)
1004 return BringWindowToTop(hwnd
);
1008 /***********************************************************************
1009 * BringWindowToTop (USER32.11)
1011 BOOL WINAPI
BringWindowToTop( HWND hwnd
)
1013 return SetWindowPos( hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
);
1017 /***********************************************************************
1018 * MoveWindow16 (USER.56)
1020 BOOL16 WINAPI
MoveWindow16( HWND16 hwnd
, INT16 x
, INT16 y
, INT16 cx
, INT16 cy
,
1023 return MoveWindow(hwnd
,x
,y
,cx
,cy
,repaint
);
1027 /***********************************************************************
1028 * MoveWindow (USER32.399)
1030 BOOL WINAPI
MoveWindow( HWND hwnd
, INT x
, INT y
, INT cx
, INT cy
,
1033 int flags
= SWP_NOZORDER
| SWP_NOACTIVATE
;
1034 if (!repaint
) flags
|= SWP_NOREDRAW
;
1035 TRACE("%04x %d,%d %dx%d %d\n",
1036 hwnd
, x
, y
, cx
, cy
, repaint
);
1037 return SetWindowPos( hwnd
, 0, x
, y
, cx
, cy
, flags
);
1040 /***********************************************************************
1041 * WINPOS_InitInternalPos
1043 static LPINTERNALPOS
WINPOS_InitInternalPos( WND
* wnd
, POINT pt
,
1044 LPRECT restoreRect
)
1046 LPINTERNALPOS lpPos
= (LPINTERNALPOS
) GetPropA( wnd
->hwndSelf
,
1050 /* this happens when the window is minimized/maximized
1051 * for the first time (rectWindow is not adjusted yet) */
1053 lpPos
= HeapAlloc( SystemHeap
, 0, sizeof(INTERNALPOS
) );
1054 if( !lpPos
) return NULL
;
1056 SetPropA( wnd
->hwndSelf
, atomInternalPos
, (HANDLE
)lpPos
);
1057 lpPos
->hwndIconTitle
= 0; /* defer until needs to be shown */
1058 CONV_RECT32TO16( &wnd
->rectWindow
, &lpPos
->rectNormal
);
1059 *(UINT
*)&lpPos
->ptIconPos
= *(UINT
*)&lpPos
->ptMaxPos
= 0xFFFFFFFF;
1062 if( wnd
->dwStyle
& WS_MINIMIZE
)
1063 CONV_POINT32TO16( &pt
, &lpPos
->ptIconPos
);
1064 else if( wnd
->dwStyle
& WS_MAXIMIZE
)
1065 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1066 else if( restoreRect
)
1067 CONV_RECT32TO16( restoreRect
, &lpPos
->rectNormal
);
1072 /***********************************************************************
1073 * WINPOS_RedrawIconTitle
1075 BOOL
WINPOS_RedrawIconTitle( HWND hWnd
)
1077 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)GetPropA( hWnd
, atomInternalPos
);
1080 if( lpPos
->hwndIconTitle
)
1082 SendMessageA( lpPos
->hwndIconTitle
, WM_SHOWWINDOW
, TRUE
, 0);
1083 InvalidateRect( lpPos
->hwndIconTitle
, NULL
, TRUE
);
1090 /***********************************************************************
1091 * WINPOS_ShowIconTitle
1093 BOOL
WINPOS_ShowIconTitle( WND
* pWnd
, BOOL bShow
)
1095 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)GetPropA( pWnd
->hwndSelf
, atomInternalPos
);
1097 if( lpPos
&& !(pWnd
->flags
& WIN_MANAGED
))
1099 HWND16 hWnd
= lpPos
->hwndIconTitle
;
1101 TRACE("0x%04x %i\n", pWnd
->hwndSelf
, (bShow
!= 0) );
1104 lpPos
->hwndIconTitle
= hWnd
= ICONTITLE_Create( pWnd
);
1107 if( ( pWnd
= WIN_FindWndPtr(hWnd
) ) != NULL
)
1109 if( !(pWnd
->dwStyle
& WS_VISIBLE
) )
1111 SendMessageA( hWnd
, WM_SHOWWINDOW
, TRUE
, 0 );
1112 SetWindowPos( hWnd
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
1113 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_SHOWWINDOW
);
1115 WIN_ReleaseWndPtr(pWnd
);
1118 else ShowWindow( hWnd
, SW_HIDE
);
1123 /*******************************************************************
1124 * WINPOS_GetMinMaxInfo
1126 * Get the minimized and maximized information for a window.
1128 void WINPOS_GetMinMaxInfo( WND
*wndPtr
, POINT
*maxSize
, POINT
*maxPos
,
1129 POINT
*minTrack
, POINT
*maxTrack
)
1131 LPINTERNALPOS lpPos
;
1135 /* Compute default values */
1137 MinMax
.ptMaxSize
.x
= GetSystemMetrics(SM_CXSCREEN
);
1138 MinMax
.ptMaxSize
.y
= GetSystemMetrics(SM_CYSCREEN
);
1139 MinMax
.ptMinTrackSize
.x
= GetSystemMetrics(SM_CXMINTRACK
);
1140 MinMax
.ptMinTrackSize
.y
= GetSystemMetrics(SM_CYMINTRACK
);
1141 MinMax
.ptMaxTrackSize
.x
= GetSystemMetrics(SM_CXSCREEN
);
1142 MinMax
.ptMaxTrackSize
.y
= GetSystemMetrics(SM_CYSCREEN
);
1144 if (wndPtr
->flags
& WIN_MANAGED
) xinc
= yinc
= 0;
1145 else if (HAS_DLGFRAME( wndPtr
->dwStyle
, wndPtr
->dwExStyle
))
1147 xinc
= GetSystemMetrics(SM_CXDLGFRAME
);
1148 yinc
= GetSystemMetrics(SM_CYDLGFRAME
);
1153 if (HAS_THICKFRAME(wndPtr
->dwStyle
))
1155 xinc
+= GetSystemMetrics(SM_CXFRAME
);
1156 yinc
+= GetSystemMetrics(SM_CYFRAME
);
1158 if (wndPtr
->dwStyle
& WS_BORDER
)
1160 xinc
+= GetSystemMetrics(SM_CXBORDER
);
1161 yinc
+= GetSystemMetrics(SM_CYBORDER
);
1164 MinMax
.ptMaxSize
.x
+= 2 * xinc
;
1165 MinMax
.ptMaxSize
.y
+= 2 * yinc
;
1167 lpPos
= (LPINTERNALPOS
)GetPropA( wndPtr
->hwndSelf
, atomInternalPos
);
1168 if( lpPos
&& !EMPTYPOINT(lpPos
->ptMaxPos
) )
1169 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &MinMax
.ptMaxPosition
);
1172 MinMax
.ptMaxPosition
.x
= -xinc
;
1173 MinMax
.ptMaxPosition
.y
= -yinc
;
1176 SendMessageA( wndPtr
->hwndSelf
, WM_GETMINMAXINFO
, 0, (LPARAM
)&MinMax
);
1178 /* Some sanity checks */
1180 TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1181 MinMax
.ptMaxSize
.x
, MinMax
.ptMaxSize
.y
,
1182 MinMax
.ptMaxPosition
.x
, MinMax
.ptMaxPosition
.y
,
1183 MinMax
.ptMaxTrackSize
.x
, MinMax
.ptMaxTrackSize
.y
,
1184 MinMax
.ptMinTrackSize
.x
, MinMax
.ptMinTrackSize
.y
);
1185 MinMax
.ptMaxTrackSize
.x
= max( MinMax
.ptMaxTrackSize
.x
,
1186 MinMax
.ptMinTrackSize
.x
);
1187 MinMax
.ptMaxTrackSize
.y
= max( MinMax
.ptMaxTrackSize
.y
,
1188 MinMax
.ptMinTrackSize
.y
);
1190 if (maxSize
) *maxSize
= MinMax
.ptMaxSize
;
1191 if (maxPos
) *maxPos
= MinMax
.ptMaxPosition
;
1192 if (minTrack
) *minTrack
= MinMax
.ptMinTrackSize
;
1193 if (maxTrack
) *maxTrack
= MinMax
.ptMaxTrackSize
;
1196 /***********************************************************************
1197 * WINPOS_MinMaximize
1199 * Fill in lpRect and return additional flags to be used with SetWindowPos().
1200 * This function assumes that 'cmd' is different from the current window
1203 UINT
WINPOS_MinMaximize( WND
* wndPtr
, UINT16 cmd
, LPRECT16 lpRect
)
1207 LPINTERNALPOS lpPos
;
1209 TRACE("0x%04x %u\n", wndPtr
->hwndSelf
, cmd
);
1211 size
.x
= wndPtr
->rectWindow
.left
; size
.y
= wndPtr
->rectWindow
.top
;
1212 lpPos
= WINPOS_InitInternalPos( wndPtr
, size
, &wndPtr
->rectWindow
);
1214 if (lpPos
&& !HOOK_CallHooks16(WH_CBT
, HCBT_MINMAX
, wndPtr
->hwndSelf
, cmd
))
1216 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1218 if( !SendMessageA( wndPtr
->hwndSelf
, WM_QUERYOPEN
, 0, 0L ) )
1219 return (SWP_NOSIZE
| SWP_NOMOVE
);
1220 swpFlags
|= SWP_NOCOPYBITS
;
1225 if( wndPtr
->dwStyle
& WS_MAXIMIZE
)
1227 wndPtr
->flags
|= WIN_RESTORE_MAX
;
1228 wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
1231 wndPtr
->flags
&= ~WIN_RESTORE_MAX
;
1232 wndPtr
->dwStyle
|= WS_MINIMIZE
;
1234 if( wndPtr
->flags
& WIN_NATIVE
)
1235 if( wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, TRUE
) )
1236 swpFlags
|= MINMAX_NOSWP
;
1238 lpPos
->ptIconPos
= WINPOS_FindIconPos( wndPtr
, lpPos
->ptIconPos
);
1240 SetRect16( lpRect
, lpPos
->ptIconPos
.x
, lpPos
->ptIconPos
.y
,
1241 GetSystemMetrics(SM_CXICON
), GetSystemMetrics(SM_CYICON
) );
1242 swpFlags
|= SWP_NOCOPYBITS
;
1246 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &pt
);
1247 WINPOS_GetMinMaxInfo( wndPtr
, &size
, &pt
, NULL
, NULL
);
1248 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1250 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1252 if( wndPtr
->flags
& WIN_NATIVE
)
1253 if( wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, FALSE
) )
1254 swpFlags
|= MINMAX_NOSWP
;
1256 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
1257 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
1259 wndPtr
->dwStyle
|= WS_MAXIMIZE
;
1261 SetRect16( lpRect
, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
,
1266 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1268 if( wndPtr
->flags
& WIN_NATIVE
)
1269 if( wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, FALSE
) )
1270 swpFlags
|= MINMAX_NOSWP
;
1272 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
1273 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
1275 if( wndPtr
->flags
& WIN_RESTORE_MAX
)
1277 /* Restore to maximized position */
1278 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &pt
);
1279 WINPOS_GetMinMaxInfo( wndPtr
, &size
, &pt
, NULL
, NULL
);
1280 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1281 wndPtr
->dwStyle
|= WS_MAXIMIZE
;
1282 SetRect16( lpRect
, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
, size
.x
, size
.y
);
1287 if( !(wndPtr
->dwStyle
& WS_MAXIMIZE
) ) return (UINT16
)(-1);
1288 else wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
1290 /* Restore to normal position */
1292 *lpRect
= lpPos
->rectNormal
;
1293 lpRect
->right
-= lpRect
->left
;
1294 lpRect
->bottom
-= lpRect
->top
;
1298 } else swpFlags
|= SWP_NOSIZE
| SWP_NOMOVE
;
1302 /***********************************************************************
1303 * ShowWindowAsync (USER32.535)
1305 * doesn't wait; returns immediately.
1306 * used by threads to toggle windows in other (possibly hanging) threads
1308 BOOL WINAPI
ShowWindowAsync( HWND hwnd
, INT cmd
)
1310 /* FIXME: does ShowWindow() return immediately ? */
1311 return ShowWindow(hwnd
, cmd
);
1315 /***********************************************************************
1316 * ShowWindow16 (USER.42)
1318 BOOL16 WINAPI
ShowWindow16( HWND16 hwnd
, INT16 cmd
)
1320 return ShowWindow(hwnd
,cmd
);
1324 /***********************************************************************
1325 * ShowWindow (USER32.534)
1327 BOOL WINAPI
ShowWindow( HWND hwnd
, INT cmd
)
1329 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
1330 BOOL wasVisible
, showFlag
;
1331 RECT16 newPos
= {0, 0, 0, 0};
1334 if (!wndPtr
) return FALSE
;
1336 TRACE("hwnd=%04x, cmd=%d\n", hwnd
, cmd
);
1338 wasVisible
= (wndPtr
->dwStyle
& WS_VISIBLE
) != 0;
1343 if (!wasVisible
) goto END
;;
1344 swp
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
|
1345 SWP_NOACTIVATE
| SWP_NOZORDER
;
1348 case SW_SHOWMINNOACTIVE
:
1349 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1351 case SW_SHOWMINIMIZED
:
1352 swp
|= SWP_SHOWWINDOW
;
1355 swp
|= SWP_FRAMECHANGED
;
1356 if( !(wndPtr
->dwStyle
& WS_MINIMIZE
) )
1357 swp
|= WINPOS_MinMaximize( wndPtr
, SW_MINIMIZE
, &newPos
);
1358 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1361 case SW_SHOWMAXIMIZED
: /* same as SW_MAXIMIZE */
1362 swp
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
1363 if( !(wndPtr
->dwStyle
& WS_MAXIMIZE
) )
1364 swp
|= WINPOS_MinMaximize( wndPtr
, SW_MAXIMIZE
, &newPos
);
1365 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1369 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1372 swp
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
1375 * ShowWindow has a little peculiar behavior that if the
1376 * window is already the topmost window, it will not
1379 if (GetTopWindow((HWND
)0)==hwnd
&& (wasVisible
|| GetActiveWindow() == hwnd
))
1380 swp
|= SWP_NOACTIVATE
;
1384 case SW_SHOWNOACTIVATE
:
1385 swp
|= SWP_NOZORDER
;
1386 if (GetActiveWindow()) swp
|= SWP_NOACTIVATE
;
1388 case SW_SHOWNORMAL
: /* same as SW_NORMAL: */
1389 case SW_SHOWDEFAULT
: /* FIXME: should have its own handler */
1391 swp
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
1393 if( wndPtr
->dwStyle
& (WS_MINIMIZE
| WS_MAXIMIZE
) )
1394 swp
|= WINPOS_MinMaximize( wndPtr
, SW_RESTORE
, &newPos
);
1395 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1399 showFlag
= (cmd
!= SW_HIDE
);
1400 if (showFlag
!= wasVisible
)
1402 SendMessageA( hwnd
, WM_SHOWWINDOW
, showFlag
, 0 );
1403 if (!IsWindow( hwnd
)) goto END
;
1406 if ((wndPtr
->dwStyle
& WS_CHILD
) &&
1407 !IsWindowVisible( wndPtr
->parent
->hwndSelf
) &&
1408 (swp
& (SWP_NOSIZE
| SWP_NOMOVE
)) == (SWP_NOSIZE
| SWP_NOMOVE
) )
1410 /* Don't call SetWindowPos() on invisible child windows */
1411 if (cmd
== SW_HIDE
) wndPtr
->dwStyle
&= ~WS_VISIBLE
;
1412 else wndPtr
->dwStyle
|= WS_VISIBLE
;
1416 /* We can't activate a child window */
1417 if ((wndPtr
->dwStyle
& WS_CHILD
) &&
1418 !(wndPtr
->dwExStyle
& WS_EX_MDICHILD
))
1419 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1420 if (!(swp
& MINMAX_NOSWP
))
1422 SetWindowPos( hwnd
, HWND_TOP
, newPos
.left
, newPos
.top
,
1423 newPos
.right
, newPos
.bottom
, LOWORD(swp
) );
1426 /* FIXME: This will cause the window to be activated irrespective
1427 * of whether it is owned by the same thread. Has to be done
1431 if (hwnd
== GetActiveWindow())
1432 WINPOS_ActivateOtherWindow(wndPtr
);
1434 /* Revert focus to parent */
1435 if (hwnd
== GetFocus() || IsChild(hwnd
, GetFocus()))
1436 SetFocus( GetParent(hwnd
) );
1439 if (!IsWindow( hwnd
)) goto END
;
1440 else if( wndPtr
->dwStyle
& WS_MINIMIZE
) WINPOS_ShowIconTitle( wndPtr
, TRUE
);
1443 if (wndPtr
->flags
& WIN_NEED_SIZE
)
1445 /* should happen only in CreateWindowEx() */
1446 int wParam
= SIZE_RESTORED
;
1448 wndPtr
->flags
&= ~WIN_NEED_SIZE
;
1449 if (wndPtr
->dwStyle
& WS_MAXIMIZE
) wParam
= SIZE_MAXIMIZED
;
1450 else if (wndPtr
->dwStyle
& WS_MINIMIZE
) wParam
= SIZE_MINIMIZED
;
1451 SendMessageA( hwnd
, WM_SIZE
, wParam
,
1452 MAKELONG(wndPtr
->rectClient
.right
-wndPtr
->rectClient
.left
,
1453 wndPtr
->rectClient
.bottom
-wndPtr
->rectClient
.top
));
1454 SendMessageA( hwnd
, WM_MOVE
, 0,
1455 MAKELONG(wndPtr
->rectClient
.left
, wndPtr
->rectClient
.top
) );
1459 WIN_ReleaseWndPtr(wndPtr
);
1464 /***********************************************************************
1465 * GetInternalWindowPos16 (USER.460)
1467 UINT16 WINAPI
GetInternalWindowPos16( HWND16 hwnd
, LPRECT16 rectWnd
,
1470 WINDOWPLACEMENT16 wndpl
;
1471 if (GetWindowPlacement16( hwnd
, &wndpl
))
1473 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
1474 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
1475 return wndpl
.showCmd
;
1481 /***********************************************************************
1482 * GetInternalWindowPos (USER32.245)
1484 UINT WINAPI
GetInternalWindowPos( HWND hwnd
, LPRECT rectWnd
,
1487 WINDOWPLACEMENT wndpl
;
1488 if (GetWindowPlacement( hwnd
, &wndpl
))
1490 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
1491 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
1492 return wndpl
.showCmd
;
1497 /***********************************************************************
1498 * GetWindowPlacement16 (USER.370)
1500 BOOL16 WINAPI
GetWindowPlacement16( HWND16 hwnd
, WINDOWPLACEMENT16
*wndpl
)
1502 WND
*pWnd
= WIN_FindWndPtr( hwnd
);
1503 LPINTERNALPOS lpPos
;
1505 if(!pWnd
) return FALSE
;
1507 lpPos
= (LPINTERNALPOS
)WINPOS_InitInternalPos( pWnd
,
1508 *(LPPOINT
)&pWnd
->rectWindow
.left
, &pWnd
->rectWindow
);
1509 wndpl
->length
= sizeof(*wndpl
);
1510 if( pWnd
->dwStyle
& WS_MINIMIZE
)
1511 wndpl
->showCmd
= SW_SHOWMINIMIZED
;
1513 wndpl
->showCmd
= ( pWnd
->dwStyle
& WS_MAXIMIZE
)
1514 ? SW_SHOWMAXIMIZED
: SW_SHOWNORMAL
;
1515 if( pWnd
->flags
& WIN_RESTORE_MAX
)
1516 wndpl
->flags
= WPF_RESTORETOMAXIMIZED
;
1519 wndpl
->ptMinPosition
= lpPos
->ptIconPos
;
1520 wndpl
->ptMaxPosition
= lpPos
->ptMaxPos
;
1521 wndpl
->rcNormalPosition
= lpPos
->rectNormal
;
1523 WIN_ReleaseWndPtr(pWnd
);
1528 /***********************************************************************
1529 * GetWindowPlacement (USER32.307)
1532 * Fails if wndpl->length of Win95 (!) apps is invalid.
1534 BOOL WINAPI
GetWindowPlacement( HWND hwnd
, WINDOWPLACEMENT
*pwpl32
)
1538 WINDOWPLACEMENT16 wpl
;
1539 wpl
.length
= sizeof(wpl
);
1540 if( GetWindowPlacement16( hwnd
, &wpl
) )
1542 pwpl32
->length
= sizeof(*pwpl32
);
1543 pwpl32
->flags
= wpl
.flags
;
1544 pwpl32
->showCmd
= wpl
.showCmd
;
1545 CONV_POINT16TO32( &wpl
.ptMinPosition
, &pwpl32
->ptMinPosition
);
1546 CONV_POINT16TO32( &wpl
.ptMaxPosition
, &pwpl32
->ptMaxPosition
);
1547 CONV_RECT16TO32( &wpl
.rcNormalPosition
, &pwpl32
->rcNormalPosition
);
1555 /***********************************************************************
1556 * WINPOS_SetPlacement
1558 static BOOL
WINPOS_SetPlacement( HWND hwnd
, const WINDOWPLACEMENT16
*wndpl
,
1561 WND
*pWnd
= WIN_FindWndPtr( hwnd
);
1564 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)WINPOS_InitInternalPos( pWnd
,
1565 *(LPPOINT
)&pWnd
->rectWindow
.left
, &pWnd
->rectWindow
);
1567 if( flags
& PLACE_MIN
) lpPos
->ptIconPos
= wndpl
->ptMinPosition
;
1568 if( flags
& PLACE_MAX
) lpPos
->ptMaxPos
= wndpl
->ptMaxPosition
;
1569 if( flags
& PLACE_RECT
) lpPos
->rectNormal
= wndpl
->rcNormalPosition
;
1571 if( pWnd
->dwStyle
& WS_MINIMIZE
)
1573 WINPOS_ShowIconTitle( pWnd
, FALSE
);
1574 if( wndpl
->flags
& WPF_SETMINPOSITION
&& !EMPTYPOINT(lpPos
->ptIconPos
))
1575 SetWindowPos( hwnd
, 0, lpPos
->ptIconPos
.x
, lpPos
->ptIconPos
.y
,
1576 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1578 else if( pWnd
->dwStyle
& WS_MAXIMIZE
)
1580 if( !EMPTYPOINT(lpPos
->ptMaxPos
) )
1581 SetWindowPos( hwnd
, 0, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
,
1582 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1584 else if( flags
& PLACE_RECT
)
1585 SetWindowPos( hwnd
, 0, lpPos
->rectNormal
.left
, lpPos
->rectNormal
.top
,
1586 lpPos
->rectNormal
.right
- lpPos
->rectNormal
.left
,
1587 lpPos
->rectNormal
.bottom
- lpPos
->rectNormal
.top
,
1588 SWP_NOZORDER
| SWP_NOACTIVATE
);
1590 ShowWindow( hwnd
, wndpl
->showCmd
);
1591 if( IsWindow(hwnd
) && pWnd
->dwStyle
& WS_MINIMIZE
)
1593 if( pWnd
->dwStyle
& WS_VISIBLE
) WINPOS_ShowIconTitle( pWnd
, TRUE
);
1595 /* SDK: ...valid only the next time... */
1596 if( wndpl
->flags
& WPF_RESTORETOMAXIMIZED
) pWnd
->flags
|= WIN_RESTORE_MAX
;
1598 WIN_ReleaseWndPtr(pWnd
);
1605 /***********************************************************************
1606 * SetWindowPlacement16 (USER.371)
1608 BOOL16 WINAPI
SetWindowPlacement16(HWND16 hwnd
, const WINDOWPLACEMENT16
*wndpl
)
1610 return WINPOS_SetPlacement( hwnd
, wndpl
,
1611 PLACE_MIN
| PLACE_MAX
| PLACE_RECT
);
1614 /***********************************************************************
1615 * SetWindowPlacement (USER32.519)
1618 * Fails if wndpl->length of Win95 (!) apps is invalid.
1620 BOOL WINAPI
SetWindowPlacement( HWND hwnd
, const WINDOWPLACEMENT
*pwpl32
)
1624 WINDOWPLACEMENT16 wpl
;
1626 wpl
.length
= sizeof(WINDOWPLACEMENT16
);
1627 wpl
.flags
= pwpl32
->flags
;
1628 wpl
.showCmd
= pwpl32
->showCmd
;
1629 wpl
.ptMinPosition
.x
= pwpl32
->ptMinPosition
.x
;
1630 wpl
.ptMinPosition
.y
= pwpl32
->ptMinPosition
.y
;
1631 wpl
.ptMaxPosition
.x
= pwpl32
->ptMaxPosition
.x
;
1632 wpl
.ptMaxPosition
.y
= pwpl32
->ptMaxPosition
.y
;
1633 wpl
.rcNormalPosition
.left
= pwpl32
->rcNormalPosition
.left
;
1634 wpl
.rcNormalPosition
.top
= pwpl32
->rcNormalPosition
.top
;
1635 wpl
.rcNormalPosition
.right
= pwpl32
->rcNormalPosition
.right
;
1636 wpl
.rcNormalPosition
.bottom
= pwpl32
->rcNormalPosition
.bottom
;
1638 return WINPOS_SetPlacement( hwnd
, &wpl
, PLACE_MIN
| PLACE_MAX
| PLACE_RECT
);
1644 /***********************************************************************
1645 * SetInternalWindowPos16 (USER.461)
1647 void WINAPI
SetInternalWindowPos16( HWND16 hwnd
, UINT16 showCmd
,
1648 LPRECT16 rect
, LPPOINT16 pt
)
1650 if( IsWindow16(hwnd
) )
1652 WINDOWPLACEMENT16 wndpl
;
1655 wndpl
.length
= sizeof(wndpl
);
1656 wndpl
.showCmd
= showCmd
;
1657 wndpl
.flags
= flags
= 0;
1662 wndpl
.flags
|= WPF_SETMINPOSITION
;
1663 wndpl
.ptMinPosition
= *pt
;
1667 flags
|= PLACE_RECT
;
1668 wndpl
.rcNormalPosition
= *rect
;
1670 WINPOS_SetPlacement( hwnd
, &wndpl
, flags
);
1675 /***********************************************************************
1676 * SetInternalWindowPos (USER32.483)
1678 void WINAPI
SetInternalWindowPos( HWND hwnd
, UINT showCmd
,
1679 LPRECT rect
, LPPOINT pt
)
1681 if( IsWindow(hwnd
) )
1683 WINDOWPLACEMENT16 wndpl
;
1686 wndpl
.length
= sizeof(wndpl
);
1687 wndpl
.showCmd
= showCmd
;
1688 wndpl
.flags
= flags
= 0;
1693 wndpl
.flags
|= WPF_SETMINPOSITION
;
1694 CONV_POINT32TO16( pt
, &wndpl
.ptMinPosition
);
1698 flags
|= PLACE_RECT
;
1699 CONV_RECT32TO16( rect
, &wndpl
.rcNormalPosition
);
1701 WINPOS_SetPlacement( hwnd
, &wndpl
, flags
);
1705 /*******************************************************************
1706 * WINPOS_SetActiveWindow
1708 * SetActiveWindow() back-end. This is the only function that
1709 * can assign active status to a window. It must be called only
1710 * for the top level windows.
1712 BOOL
WINPOS_SetActiveWindow( HWND hWnd
, BOOL fMouse
, BOOL fChangeFocus
)
1714 CBTACTIVATESTRUCT16
* cbtStruct
;
1715 WND
* wndPtr
=0, *wndTemp
;
1716 HQUEUE16 hOldActiveQueue
, hNewActiveQueue
;
1717 MESSAGEQUEUE
*pOldActiveQueue
= 0, *pNewActiveQueue
= 0;
1719 HWND hwndActive
= 0;
1722 TRACE("(%04x, %d, %d)\n", hWnd
, fMouse
, fChangeFocus
);
1724 /* Get current active window from the active queue */
1727 pOldActiveQueue
= QUEUE_Lock( hActiveQueue
);
1728 if ( pOldActiveQueue
)
1729 hwndActive
= PERQDATA_GetActiveWnd( pOldActiveQueue
->pQData
);
1732 /* paranoid checks */
1733 if( hWnd
== GetDesktopWindow() || (bRet
= (hWnd
== hwndActive
)) )
1736 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1739 wndPtr
= WIN_FindWndPtr(hWnd
);
1740 hOldActiveQueue
= hActiveQueue
;
1742 if( (wndTemp
= WIN_FindWndPtr(hwndActive
)) )
1744 wIconized
= HIWORD(wndTemp
->dwStyle
& WS_MINIMIZE
);
1745 WIN_ReleaseWndPtr(wndTemp
);
1748 TRACE("no current active window.\n");
1750 /* call CBT hook chain */
1751 if ((cbtStruct
= SEGPTR_NEW(CBTACTIVATESTRUCT16
)))
1753 cbtStruct
->fMouse
= fMouse
;
1754 cbtStruct
->hWndActive
= hwndActive
;
1755 bRet
= (BOOL
)HOOK_CallHooks16( WH_CBT
, HCBT_ACTIVATE
, (WPARAM16
)hWnd
,
1756 (LPARAM
)SEGPTR_GET(cbtStruct
) );
1757 SEGPTR_FREE(cbtStruct
);
1758 if (bRet
) goto CLEANUP_END
;
1761 /* set prev active wnd to current active wnd and send notification */
1762 if ((hwndPrevActive
= hwndActive
) && IsWindow(hwndPrevActive
))
1764 MESSAGEQUEUE
*pTempActiveQueue
= 0;
1766 if (!SendMessageA( hwndPrevActive
, WM_NCACTIVATE
, FALSE
, 0 ))
1768 if (GetSysModalWindow16() != hWnd
)
1770 /* disregard refusal if hWnd is sysmodal */
1773 SendMessageA( hwndPrevActive
, WM_ACTIVATE
,
1774 MAKEWPARAM( WA_INACTIVE
, wIconized
),
1777 /* check if something happened during message processing
1778 * (global active queue may have changed)
1780 pTempActiveQueue
= QUEUE_Lock( hActiveQueue
);
1781 if(!pTempActiveQueue
)
1784 hwndActive
= PERQDATA_GetActiveWnd( pTempActiveQueue
->pQData
);
1785 QUEUE_Unlock( pTempActiveQueue
);
1786 if( hwndPrevActive
!= hwndActive
)
1790 /* Set new active window in the message queue */
1794 pNewActiveQueue
= QUEUE_Lock( wndPtr
->hmemTaskQ
);
1795 if ( pNewActiveQueue
)
1796 PERQDATA_SetActiveWnd( pNewActiveQueue
->pQData
, hwndActive
);
1798 else /* have to do this or MDI frame activation goes to hell */
1799 if( pOldActiveQueue
)
1800 PERQDATA_SetActiveWnd( pOldActiveQueue
->pQData
, 0 );
1802 /* send palette messages */
1803 if (hWnd
&& SendMessage16( hWnd
, WM_QUERYNEWPALETTE
, 0, 0L))
1804 SendMessage16((HWND16
)-1, WM_PALETTEISCHANGING
, (WPARAM16
)hWnd
, 0L );
1806 /* if prev wnd is minimized redraw icon title */
1807 if( IsIconic( hwndPrevActive
) ) WINPOS_RedrawIconTitle(hwndPrevActive
);
1809 /* managed windows will get ConfigureNotify event */
1810 if (wndPtr
&& !(wndPtr
->dwStyle
& WS_CHILD
) && !(wndPtr
->flags
& WIN_MANAGED
))
1812 /* check Z-order and bring hWnd to the top */
1813 for (wndTemp
= WIN_LockWndPtr(WIN_GetDesktop()->child
); wndTemp
; WIN_UpdateWndPtr(&wndTemp
,wndTemp
->next
))
1815 if (wndTemp
->dwStyle
& WS_VISIBLE
) break;
1817 WIN_ReleaseDesktop();
1818 WIN_ReleaseWndPtr(wndTemp
);
1820 if( wndTemp
!= wndPtr
)
1821 SetWindowPos(hWnd
, HWND_TOP
, 0,0,0,0,
1822 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
1823 if (!IsWindow(hWnd
))
1827 /* Get a handle to the new active queue */
1828 hNewActiveQueue
= wndPtr
? wndPtr
->hmemTaskQ
: 0;
1830 /* send WM_ACTIVATEAPP if necessary */
1831 if (hOldActiveQueue
!= hNewActiveQueue
)
1833 WND
**list
, **ppWnd
;
1834 WND
*pDesktop
= WIN_GetDesktop();
1836 if ((list
= WIN_BuildWinArray( pDesktop
, 0, NULL
)))
1838 for (ppWnd
= list
; *ppWnd
; ppWnd
++)
1840 if (!IsWindow( (*ppWnd
)->hwndSelf
)) continue;
1842 if ((*ppWnd
)->hmemTaskQ
== hOldActiveQueue
)
1843 SendMessage16( (*ppWnd
)->hwndSelf
, WM_ACTIVATEAPP
,
1844 0, QUEUE_GetQueueTask(hNewActiveQueue
) );
1846 WIN_ReleaseWinArray(list
);
1849 hActiveQueue
= hNewActiveQueue
;
1851 if ((list
= WIN_BuildWinArray(pDesktop
, 0, NULL
)))
1853 for (ppWnd
= list
; *ppWnd
; ppWnd
++)
1855 if (!IsWindow( (*ppWnd
)->hwndSelf
)) continue;
1857 if ((*ppWnd
)->hmemTaskQ
== hNewActiveQueue
)
1858 SendMessage16( (*ppWnd
)->hwndSelf
, WM_ACTIVATEAPP
,
1859 1, QUEUE_GetQueueTask( hOldActiveQueue
) );
1861 WIN_ReleaseWinArray(list
);
1863 WIN_ReleaseDesktop();
1865 if (hWnd
&& !IsWindow(hWnd
)) goto CLEANUP
;
1870 /* walk up to the first unowned window */
1871 wndTemp
= WIN_LockWndPtr(wndPtr
);
1872 while (wndTemp
->owner
)
1874 WIN_UpdateWndPtr(&wndTemp
,wndTemp
->owner
);
1876 /* and set last active owned popup */
1877 wndTemp
->hwndLastActive
= hWnd
;
1879 wIconized
= HIWORD(wndTemp
->dwStyle
& WS_MINIMIZE
);
1880 WIN_ReleaseWndPtr(wndTemp
);
1881 SendMessageA( hWnd
, WM_NCACTIVATE
, TRUE
, 0 );
1882 SendMessageA( hWnd
, WM_ACTIVATE
,
1883 MAKEWPARAM( (fMouse
) ? WA_CLICKACTIVE
: WA_ACTIVE
, wIconized
),
1884 (LPARAM
)hwndPrevActive
);
1885 if( !IsWindow(hWnd
) ) goto CLEANUP
;
1888 /* change focus if possible */
1891 if ( pNewActiveQueue
)
1893 HWND hOldFocus
= PERQDATA_GetFocusWnd( pNewActiveQueue
->pQData
);
1895 if ( hOldFocus
&& WIN_GetTopParent( hOldFocus
) != hwndActive
)
1896 FOCUS_SwitchFocus( pNewActiveQueue
, hOldFocus
,
1897 (wndPtr
&& (wndPtr
->dwStyle
& WS_MINIMIZE
))?
1901 if ( pOldActiveQueue
&&
1902 ( !pNewActiveQueue
||
1903 pNewActiveQueue
->pQData
!= pOldActiveQueue
->pQData
) )
1905 HWND hOldFocus
= PERQDATA_GetFocusWnd( pOldActiveQueue
->pQData
);
1907 FOCUS_SwitchFocus( pOldActiveQueue
, hOldFocus
, 0 );
1911 if( !hwndPrevActive
&& wndPtr
)
1912 (*wndPtr
->pDriver
->pForceWindowRaise
)(wndPtr
);
1914 /* if active wnd is minimized redraw icon title */
1915 if( IsIconic(hwndActive
) ) WINPOS_RedrawIconTitle(hwndActive
);
1917 bRet
= (hWnd
== hwndActive
); /* Success? */
1919 CLEANUP
: /* Unlock the message queues before returning */
1921 if ( pNewActiveQueue
)
1922 QUEUE_Unlock( pNewActiveQueue
);
1926 if ( pOldActiveQueue
)
1927 QUEUE_Unlock( pOldActiveQueue
);
1929 WIN_ReleaseWndPtr(wndPtr
);
1933 /*******************************************************************
1934 * WINPOS_ActivateOtherWindow
1936 * Activates window other than pWnd.
1938 BOOL
WINPOS_ActivateOtherWindow(WND
* pWnd
)
1942 HWND hwndActive
= 0;
1944 /* Get current active window from the active queue */
1947 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
1950 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
1951 QUEUE_Unlock( pActiveQueue
);
1955 if( pWnd
->hwndSelf
== hwndPrevActive
)
1958 if( hwndActive
!= pWnd
->hwndSelf
&&
1959 ( hwndActive
|| QUEUE_IsExitingQueue(pWnd
->hmemTaskQ
)) )
1962 if( !(pWnd
->dwStyle
& WS_POPUP
) || !(pWnd
->owner
) ||
1963 !WINPOS_CanActivate((pWndTo
= WIN_GetTopParentPtr(pWnd
->owner
))) )
1965 WND
* pWndPtr
= WIN_GetTopParentPtr(pWnd
);
1967 WIN_ReleaseWndPtr(pWndTo
);
1968 pWndTo
= WIN_FindWndPtr(hwndPrevActive
);
1970 while( !WINPOS_CanActivate(pWndTo
) )
1972 /* by now owned windows should've been taken care of */
1973 WIN_UpdateWndPtr(&pWndTo
,pWndPtr
->next
);
1974 WIN_UpdateWndPtr(&pWndPtr
,pWndTo
);
1975 if( !pWndTo
) break;
1977 WIN_ReleaseWndPtr(pWndPtr
);
1980 bRet
= WINPOS_SetActiveWindow( pWndTo
? pWndTo
->hwndSelf
: 0, FALSE
, TRUE
);
1982 /* switch desktop queue to current active */
1985 WIN_GetDesktop()->hmemTaskQ
= pWndTo
->hmemTaskQ
;
1986 WIN_ReleaseWndPtr(pWndTo
);
1987 WIN_ReleaseDesktop();
1994 /*******************************************************************
1995 * WINPOS_ChangeActiveWindow
1998 BOOL
WINPOS_ChangeActiveWindow( HWND hWnd
, BOOL mouseMsg
)
2000 WND
*wndPtr
, *wndTemp
;
2002 HWND hwndActive
= 0;
2004 /* Get current active window from the active queue */
2007 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
2010 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
2011 QUEUE_Unlock( pActiveQueue
);
2016 return WINPOS_SetActiveWindow( 0, mouseMsg
, TRUE
);
2018 wndPtr
= WIN_FindWndPtr(hWnd
);
2019 if( !wndPtr
) return FALSE
;
2021 /* child windows get WM_CHILDACTIVATE message */
2022 if( (wndPtr
->dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
2024 retvalue
= SendMessageA(hWnd
, WM_CHILDACTIVATE
, 0, 0L);
2028 if( hWnd
== hwndActive
)
2034 if( !WINPOS_SetActiveWindow(hWnd
,mouseMsg
,TRUE
) )
2040 /* switch desktop queue to current active */
2041 wndTemp
= WIN_GetDesktop();
2042 if( wndPtr
->parent
== wndTemp
)
2043 wndTemp
->hmemTaskQ
= wndPtr
->hmemTaskQ
;
2044 WIN_ReleaseDesktop();
2048 WIN_ReleaseWndPtr(wndPtr
);
2053 /***********************************************************************
2054 * WINPOS_SendNCCalcSize
2056 * Send a WM_NCCALCSIZE message to a window.
2057 * All parameters are read-only except newClientRect.
2058 * oldWindowRect, oldClientRect and winpos must be non-NULL only
2059 * when calcValidRect is TRUE.
2061 LONG
WINPOS_SendNCCalcSize( HWND hwnd
, BOOL calcValidRect
,
2062 RECT
*newWindowRect
, RECT
*oldWindowRect
,
2063 RECT
*oldClientRect
, WINDOWPOS
*winpos
,
2064 RECT
*newClientRect
)
2066 NCCALCSIZE_PARAMS params
;
2067 WINDOWPOS winposCopy
;
2070 params
.rgrc
[0] = *newWindowRect
;
2073 winposCopy
= *winpos
;
2074 params
.rgrc
[1] = *oldWindowRect
;
2075 params
.rgrc
[2] = *oldClientRect
;
2076 params
.lppos
= &winposCopy
;
2078 result
= SendMessageA( hwnd
, WM_NCCALCSIZE
, calcValidRect
,
2080 TRACE("%d,%d-%d,%d\n",
2081 params
.rgrc
[0].left
, params
.rgrc
[0].top
,
2082 params
.rgrc
[0].right
, params
.rgrc
[0].bottom
);
2084 /* If the application send back garbage, ignore it */
2085 if (params
.rgrc
[0].left
<= params
.rgrc
[0].right
&& params
.rgrc
[0].top
<= params
.rgrc
[0].bottom
)
2086 *newClientRect
= params
.rgrc
[0];
2092 /***********************************************************************
2093 * WINPOS_HandleWindowPosChanging16
2095 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2097 LONG
WINPOS_HandleWindowPosChanging16( WND
*wndPtr
, WINDOWPOS16
*winpos
)
2099 POINT maxSize
, minTrack
;
2100 if (winpos
->flags
& SWP_NOSIZE
) return 0;
2101 if ((wndPtr
->dwStyle
& WS_THICKFRAME
) ||
2102 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) == 0))
2104 WINPOS_GetMinMaxInfo( wndPtr
, &maxSize
, NULL
, &minTrack
, NULL
);
2105 if (maxSize
.x
< winpos
->cx
) winpos
->cx
= maxSize
.x
;
2106 if (maxSize
.y
< winpos
->cy
) winpos
->cy
= maxSize
.y
;
2107 if (!(wndPtr
->dwStyle
& WS_MINIMIZE
))
2109 if (winpos
->cx
< minTrack
.x
) winpos
->cx
= minTrack
.x
;
2110 if (winpos
->cy
< minTrack
.y
) winpos
->cy
= minTrack
.y
;
2117 /***********************************************************************
2118 * WINPOS_HandleWindowPosChanging
2120 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2122 LONG
WINPOS_HandleWindowPosChanging( WND
*wndPtr
, WINDOWPOS
*winpos
)
2125 if (winpos
->flags
& SWP_NOSIZE
) return 0;
2126 if ((wndPtr
->dwStyle
& WS_THICKFRAME
) ||
2127 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) == 0))
2129 WINPOS_GetMinMaxInfo( wndPtr
, &maxSize
, NULL
, NULL
, NULL
);
2130 winpos
->cx
= min( winpos
->cx
, maxSize
.x
);
2131 winpos
->cy
= min( winpos
->cy
, maxSize
.y
);
2136 /***********************************************************************
2139 * fix Z order taking into account owned popups -
2140 * basically we need to maintain them above the window that owns them
2142 * FIXME: hide/show owned popups when owner visibility changes.
2144 static HWND
SWP_DoOwnedPopups(WND
* pDesktop
, WND
* wndPtr
, HWND hwndInsertAfter
, WORD flags
)
2146 WND
* w
= WIN_LockWndPtr(pDesktop
->child
);
2148 WARN("(%04x) hInsertAfter = %04x\n", wndPtr
->hwndSelf
, hwndInsertAfter
);
2150 if( (wndPtr
->dwStyle
& WS_POPUP
) && wndPtr
->owner
)
2152 /* make sure this popup stays above the owner */
2154 HWND hwndLocalPrev
= HWND_TOP
;
2156 if( hwndInsertAfter
!= HWND_TOP
)
2158 while( w
!= wndPtr
->owner
)
2160 if (w
!= wndPtr
) hwndLocalPrev
= w
->hwndSelf
;
2161 if( hwndLocalPrev
== hwndInsertAfter
) break;
2162 WIN_UpdateWndPtr(&w
,w
->next
);
2164 hwndInsertAfter
= hwndLocalPrev
;
2167 else if( wndPtr
->dwStyle
& WS_CHILD
)
2170 WIN_UpdateWndPtr(&w
, pDesktop
->child
);
2174 if( w
== wndPtr
) break;
2176 if( (w
->dwStyle
& WS_POPUP
) && w
->owner
== wndPtr
)
2178 SetWindowPos(w
->hwndSelf
, hwndInsertAfter
, 0, 0, 0, 0,
2179 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOSENDCHANGING
| SWP_DEFERERASE
);
2180 hwndInsertAfter
= w
->hwndSelf
;
2182 WIN_UpdateWndPtr(&w
, w
->next
);
2186 WIN_ReleaseWndPtr(w
);
2187 return hwndInsertAfter
;
2190 /***********************************************************************
2193 * Make window look nice without excessive repainting
2195 * visible and update regions are in window coordinates
2196 * client and window rectangles are in parent client coordinates
2198 * FIXME: SWP_EX_PAINTSELF in uFlags works only if both old and new
2199 * window rects have the same origin.
2201 * Returns: uFlags and a dirty region in *pVisRgn.
2203 static UINT
SWP_CopyValidBits( WND
* Wnd
, HRGN
* pVisRgn
,
2204 LPRECT lpOldWndRect
,
2205 LPRECT lpOldClientRect
, UINT uFlags
)
2208 HRGN newVisRgn
, dirtyRgn
;
2209 INT my
= COMPLEXREGION
;
2211 TRACE("\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2212 Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
,
2213 Wnd
->rectWindow
.right
, Wnd
->rectWindow
.bottom
,
2214 lpOldWndRect
->left
, lpOldWndRect
->top
,
2215 lpOldWndRect
->right
, lpOldWndRect
->bottom
, *pVisRgn
);
2216 TRACE("\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2217 Wnd
->rectClient
.left
, Wnd
->rectClient
.top
,
2218 Wnd
->rectClient
.right
, Wnd
->rectClient
.bottom
,
2219 lpOldClientRect
->left
, lpOldClientRect
->top
,
2220 lpOldClientRect
->right
,lpOldClientRect
->bottom
);
2222 if( Wnd
->hrgnUpdate
== 1 )
2223 uFlags
|= SWP_EX_NOCOPY
; /* whole window is invalid, nothing to copy */
2225 newVisRgn
= DCE_GetVisRgn( Wnd
->hwndSelf
, DCX_WINDOW
| DCX_CLIPSIBLINGS
, 0, 0);
2226 dirtyRgn
= CreateRectRgn( 0, 0, 0, 0 );
2228 if( !(uFlags
& SWP_EX_NOCOPY
) ) /* make sure dst region covers only valid bits */
2229 my
= CombineRgn( dirtyRgn
, newVisRgn
, *pVisRgn
, RGN_AND
);
2231 if( (my
== NULLREGION
) || (uFlags
& SWP_EX_NOCOPY
) )
2235 TRACE("\twon't copy anything!\n");
2237 /* set dirtyRgn to the sum of old and new visible regions
2238 * in parent client coordinates */
2240 OffsetRgn( newVisRgn
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2241 OffsetRgn( *pVisRgn
, lpOldWndRect
->left
, lpOldWndRect
->top
);
2243 CombineRgn(*pVisRgn
, *pVisRgn
, newVisRgn
, RGN_OR
);
2245 else /* copy valid bits to a new location */
2247 INT dx
, dy
, ow
, oh
, nw
, nh
, ocw
, ncw
, och
, nch
;
2248 HRGN hrgnValid
= dirtyRgn
; /* non-empty intersection of old and new visible rgns */
2250 /* subtract already invalid region inside Wnd from the dst region */
2252 if( Wnd
->hrgnUpdate
)
2253 if( CombineRgn( hrgnValid
, hrgnValid
, Wnd
->hrgnUpdate
, RGN_DIFF
) == NULLREGION
)
2256 /* check if entire window can be copied */
2258 ow
= lpOldWndRect
->right
- lpOldWndRect
->left
;
2259 oh
= lpOldWndRect
->bottom
- lpOldWndRect
->top
;
2260 nw
= Wnd
->rectWindow
.right
- Wnd
->rectWindow
.left
;
2261 nh
= Wnd
->rectWindow
.bottom
- Wnd
->rectWindow
.top
;
2263 ocw
= lpOldClientRect
->right
- lpOldClientRect
->left
;
2264 och
= lpOldClientRect
->bottom
- lpOldClientRect
->top
;
2265 ncw
= Wnd
->rectClient
.right
- Wnd
->rectClient
.left
;
2266 nch
= Wnd
->rectClient
.bottom
- Wnd
->rectClient
.top
;
2268 if( (ocw
!= ncw
) || (och
!= nch
) ||
2269 ( ow
!= nw
) || ( oh
!= nh
) ||
2270 ((lpOldClientRect
->top
- lpOldWndRect
->top
) !=
2271 (Wnd
->rectClient
.top
- Wnd
->rectWindow
.top
)) ||
2272 ((lpOldClientRect
->left
- lpOldWndRect
->left
) !=
2273 (Wnd
->rectClient
.left
- Wnd
->rectWindow
.left
)) )
2275 dx
= Wnd
->rectClient
.left
- lpOldClientRect
->left
;
2276 dy
= Wnd
->rectClient
.top
- lpOldClientRect
->top
;
2278 /* restrict valid bits to the common client rect */
2280 r
.left
= Wnd
->rectClient
.left
- Wnd
->rectWindow
.left
;
2281 r
.top
= Wnd
->rectClient
.top
- Wnd
->rectWindow
.top
;
2282 r
.right
= r
.left
+ min( ocw
, ncw
);
2283 r
.bottom
= r
.top
+ min( och
, nch
);
2285 REGION_CropRgn( hrgnValid
, hrgnValid
, &r
,
2286 (uFlags
& SWP_EX_PAINTSELF
) ? NULL
: (POINT
*)&(Wnd
->rectWindow
));
2287 GetRgnBox( hrgnValid
, &r
);
2288 if( IsRectEmpty( &r
) )
2290 r
= *lpOldClientRect
;
2294 dx
= Wnd
->rectWindow
.left
- lpOldWndRect
->left
;
2295 dy
= Wnd
->rectWindow
.top
- lpOldWndRect
->top
;
2296 if( !(uFlags
& SWP_EX_PAINTSELF
) )
2297 OffsetRgn( hrgnValid
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2301 if( !(uFlags
& SWP_EX_PAINTSELF
) )
2303 /* Move remaining regions to parent coordinates */
2304 OffsetRgn( newVisRgn
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2305 OffsetRgn( *pVisRgn
, lpOldWndRect
->left
, lpOldWndRect
->top
);
2308 OffsetRect( &r
, -lpOldWndRect
->left
, -lpOldWndRect
->top
);
2310 TRACE("\tcomputing dirty region!\n");
2312 /* Compute combined dirty region (old + new - valid) */
2313 CombineRgn( *pVisRgn
, *pVisRgn
, newVisRgn
, RGN_OR
);
2314 CombineRgn( *pVisRgn
, *pVisRgn
, hrgnValid
, RGN_DIFF
);
2316 /* Blt valid bits, r is the rect to copy */
2324 /* get DC and clip rect with drawable rect to avoid superfluous expose events
2325 from copying clipped areas */
2327 if( uFlags
& SWP_EX_PAINTSELF
)
2329 hDC
= GetDCEx( Wnd
->hwndSelf
, hrgnValid
, DCX_WINDOW
| DCX_CACHE
|
2330 DCX_KEEPCLIPRGN
| DCX_INTERSECTRGN
| DCX_CLIPSIBLINGS
);
2331 rClip
.right
= nw
; rClip
.bottom
= nh
;
2335 hDC
= GetDCEx( Wnd
->parent
->hwndSelf
, hrgnValid
, DCX_CACHE
|
2336 DCX_KEEPCLIPRGN
| DCX_INTERSECTRGN
| DCX_CLIPSIBLINGS
);
2337 rClip
.right
= Wnd
->parent
->rectClient
.right
- Wnd
->parent
->rectClient
.left
;
2338 rClip
.bottom
= Wnd
->parent
->rectClient
.bottom
- Wnd
->parent
->rectClient
.top
;
2340 rClip
.left
= rClip
.top
= 0;
2342 if( (dc
= (DC
*)GDI_GetObjPtr(hDC
, DC_MAGIC
)) )
2344 if( oh
> nh
) r
.bottom
= r
.top
+ nh
;
2345 if( ow
< nw
) r
.right
= r
.left
+ nw
;
2347 if( IntersectRect( &r
, &r
, &rClip
) )
2349 Wnd
->pDriver
->pSurfaceCopy( Wnd
->parent
, dc
, dx
, dy
, &r
, TRUE
);
2351 /* When you copy the bits without repainting, parent doesn't
2352 get validated appropriately. Therefore, we have to validate
2353 the parent with the windows' updated region when the
2354 parent's update region is not empty. */
2356 if (Wnd
->parent
->hrgnUpdate
!= 0 && !(Wnd
->parent
->dwStyle
& WS_CLIPCHILDREN
))
2358 OffsetRect(&r
, dx
, dy
);
2359 ValidateRect(Wnd
->parent
->hwndSelf
, &r
);
2363 GDI_HEAP_UNLOCK( hDC
);
2365 ReleaseDC( (uFlags
& SWP_EX_PAINTSELF
) ?
2366 Wnd
->hwndSelf
: Wnd
->parent
->hwndSelf
, hDC
);
2370 /* *pVisRgn now points to the invalidated region */
2372 DeleteObject(newVisRgn
);
2373 DeleteObject(dirtyRgn
);
2377 /***********************************************************************
2378 * SWP_DoSimpleFrameChanged
2380 * NOTE: old and new client rect origins are identical, only
2381 * extents may have changed. Window extents are the same.
2383 static void SWP_DoSimpleFrameChanged( WND
* wndPtr
, RECT
* pOldClientRect
, WORD swpFlags
, UINT uFlags
)
2389 if( !(swpFlags
& SWP_NOCLIENTSIZE
) )
2391 /* Client rect changed its position/size, most likely a scrollar
2392 * was added/removed.
2394 * FIXME: WVR alignment flags
2397 if( wndPtr
->rectClient
.right
> pOldClientRect
->right
) /* right edge */
2401 rect
.bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
2402 rect
.right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
2403 if(!(uFlags
& SWP_EX_NOCOPY
))
2404 rect
.left
= pOldClientRect
->right
- wndPtr
->rectClient
.left
;
2412 if( wndPtr
->rectClient
.bottom
> pOldClientRect
->bottom
) /* bottom edge */
2415 hrgn
= CreateRectRgnIndirect( &rect
);
2417 rect
.right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
2418 rect
.bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
2419 if(!(uFlags
& SWP_EX_NOCOPY
))
2420 rect
.top
= pOldClientRect
->bottom
- wndPtr
->rectClient
.top
;
2424 REGION_UnionRectWithRgn( hrgn
, &rect
);
2427 if( i
== 0 && (uFlags
& SWP_EX_NOCOPY
) ) /* force redraw anyway */
2429 rect
= wndPtr
->rectWindow
;
2430 OffsetRect( &rect
, wndPtr
->rectWindow
.left
- wndPtr
->rectClient
.left
,
2431 wndPtr
->rectWindow
.top
- wndPtr
->rectClient
.top
);
2439 PAINT_RedrawWindow( wndPtr
->hwndSelf
, &rect
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
|
2440 RDW_ERASENOW
| RDW_ALLCHILDREN
, RDW_EX_TOPFRAME
| RDW_EX_USEHRGN
);
2444 WIN_UpdateNCRgn(wndPtr
, 0, UNC_UPDATE
| UNC_ENTIRE
);
2448 DeleteObject( hrgn
);
2451 /***********************************************************************
2452 * SWP_DoWinPosChanging
2454 static BOOL
SWP_DoWinPosChanging( WND
* wndPtr
, WINDOWPOS
* pWinpos
,
2455 RECT
* pNewWindowRect
, RECT
* pNewClientRect
)
2457 /* Send WM_WINDOWPOSCHANGING message */
2459 if (!(pWinpos
->flags
& SWP_NOSENDCHANGING
))
2460 SendMessageA( wndPtr
->hwndSelf
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
)pWinpos
);
2462 /* Calculate new position and size */
2464 *pNewWindowRect
= wndPtr
->rectWindow
;
2465 *pNewClientRect
= (wndPtr
->dwStyle
& WS_MINIMIZE
) ? wndPtr
->rectWindow
2466 : wndPtr
->rectClient
;
2468 if (!(pWinpos
->flags
& SWP_NOSIZE
))
2470 pNewWindowRect
->right
= pNewWindowRect
->left
+ pWinpos
->cx
;
2471 pNewWindowRect
->bottom
= pNewWindowRect
->top
+ pWinpos
->cy
;
2473 if (!(pWinpos
->flags
& SWP_NOMOVE
))
2475 pNewWindowRect
->left
= pWinpos
->x
;
2476 pNewWindowRect
->top
= pWinpos
->y
;
2477 pNewWindowRect
->right
+= pWinpos
->x
- wndPtr
->rectWindow
.left
;
2478 pNewWindowRect
->bottom
+= pWinpos
->y
- wndPtr
->rectWindow
.top
;
2480 OffsetRect( pNewClientRect
, pWinpos
->x
- wndPtr
->rectWindow
.left
,
2481 pWinpos
->y
- wndPtr
->rectWindow
.top
);
2484 pWinpos
->flags
|= SWP_NOCLIENTMOVE
| SWP_NOCLIENTSIZE
;
2488 /***********************************************************************
2491 static UINT
SWP_DoNCCalcSize( WND
* wndPtr
, WINDOWPOS
* pWinpos
,
2492 RECT
* pNewWindowRect
, RECT
* pNewClientRect
, WORD f
)
2496 /* Send WM_NCCALCSIZE message to get new client area */
2497 if( (pWinpos
->flags
& (SWP_FRAMECHANGED
| SWP_NOSIZE
)) != SWP_NOSIZE
)
2499 wvrFlags
= WINPOS_SendNCCalcSize( pWinpos
->hwnd
, TRUE
, pNewWindowRect
,
2500 &wndPtr
->rectWindow
, &wndPtr
->rectClient
,
2501 pWinpos
, pNewClientRect
);
2503 /* FIXME: WVR_ALIGNxxx */
2505 if( pNewClientRect
->left
!= wndPtr
->rectClient
.left
||
2506 pNewClientRect
->top
!= wndPtr
->rectClient
.top
)
2507 pWinpos
->flags
&= ~SWP_NOCLIENTMOVE
;
2509 if( (pNewClientRect
->right
- pNewClientRect
->left
!=
2510 wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
) ||
2511 (pNewClientRect
->bottom
- pNewClientRect
->top
!=
2512 wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
) )
2513 pWinpos
->flags
&= ~SWP_NOCLIENTSIZE
;
2516 if( !(f
& SWP_NOMOVE
) && (pNewClientRect
->left
!= wndPtr
->rectClient
.left
||
2517 pNewClientRect
->top
!= wndPtr
->rectClient
.top
) )
2518 pWinpos
->flags
&= ~SWP_NOCLIENTMOVE
;
2522 /***********************************************************************
2523 * SetWindowPos (USER.2)
2525 BOOL16 WINAPI
SetWindowPos16( HWND16 hwnd
, HWND16 hwndInsertAfter
,
2526 INT16 x
, INT16 y
, INT16 cx
, INT16 cy
, WORD flags
)
2528 return SetWindowPos(hwnd
,(INT
)(INT16
)hwndInsertAfter
,x
,y
,cx
,cy
,flags
);
2531 /***********************************************************************
2532 * SetWindowPos (USER32.520)
2534 BOOL WINAPI
SetWindowPos( HWND hwnd
, HWND hwndInsertAfter
,
2535 INT x
, INT y
, INT cx
, INT cy
, UINT flags
)
2538 WND
* wndPtr
,*wndTemp
;
2539 RECT newWindowRect
, newClientRect
;
2540 RECT oldWindowRect
, oldClientRect
;
2542 UINT wvrFlags
= 0, uFlags
= 0;
2543 BOOL retvalue
, resync
= FALSE
, bChangePos
;
2544 HWND hwndActive
= 0;
2546 /* Get current active window from the active queue */
2549 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
2552 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
2553 QUEUE_Unlock( pActiveQueue
);
2557 TRACE("hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2558 hwnd
, x
, y
, x
+cx
, y
+cy
, flags
);
2560 bChangePos
= !(flags
& SWP_WINE_NOHOSTMOVE
);
2561 flags
&= ~SWP_WINE_NOHOSTMOVE
;
2564 /* ------------------------------------------------------------------------ CHECKS */
2566 /* Check window handle */
2568 if (hwnd
== GetDesktopWindow()) return FALSE
;
2569 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return FALSE
;
2571 TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr
->rectWindow
.left
, wndPtr
->rectWindow
.top
,
2572 wndPtr
->rectWindow
.right
, wndPtr
->rectWindow
.bottom
, (unsigned)wndPtr
->dwStyle
);
2574 /* Fix redundant flags */
2576 if(wndPtr
->dwStyle
& WS_VISIBLE
)
2577 flags
&= ~SWP_SHOWWINDOW
;
2580 if (!(flags
& SWP_SHOWWINDOW
))
2581 flags
|= SWP_NOREDRAW
;
2582 flags
&= ~SWP_HIDEWINDOW
;
2585 if ( cx
< 0 ) cx
= 0; if( cy
< 0 ) cy
= 0;
2587 if ((wndPtr
->rectWindow
.right
- wndPtr
->rectWindow
.left
== cx
) &&
2588 (wndPtr
->rectWindow
.bottom
- wndPtr
->rectWindow
.top
== cy
))
2589 flags
|= SWP_NOSIZE
; /* Already the right size */
2591 if ((wndPtr
->rectWindow
.left
== x
) && (wndPtr
->rectWindow
.top
== y
))
2592 flags
|= SWP_NOMOVE
; /* Already the right position */
2594 if (hwnd
== hwndActive
)
2595 flags
|= SWP_NOACTIVATE
; /* Already active */
2596 else if ( (wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)
2598 if(!(flags
& SWP_NOACTIVATE
)) /* Bring to the top when activating */
2600 flags
&= ~SWP_NOZORDER
;
2601 hwndInsertAfter
= HWND_TOP
;
2606 /* Check hwndInsertAfter */
2608 /* FIXME: TOPMOST not supported yet */
2609 if ((hwndInsertAfter
== HWND_TOPMOST
) ||
2610 (hwndInsertAfter
== HWND_NOTOPMOST
)) hwndInsertAfter
= HWND_TOP
;
2612 /* hwndInsertAfter must be a sibling of the window */
2613 if ((hwndInsertAfter
!= HWND_TOP
) && (hwndInsertAfter
!= HWND_BOTTOM
))
2615 WND
* wnd
= WIN_FindWndPtr(hwndInsertAfter
);
2618 if( wnd
->parent
!= wndPtr
->parent
)
2621 WIN_ReleaseWndPtr(wnd
);
2624 /* don't need to change the Zorder of hwnd if it's already inserted
2625 * after hwndInsertAfter or when inserting hwnd after itself.
2627 if(( wnd
->next
== wndPtr
) || (hwnd
== hwndInsertAfter
)) flags
|= SWP_NOZORDER
;
2629 WIN_ReleaseWndPtr(wnd
);
2632 Pos
: /* ------------------------------------------------------------------------ MAIN part */
2634 /* Fill the WINDOWPOS structure */
2637 winpos
.hwndInsertAfter
= hwndInsertAfter
;
2642 winpos
.flags
= flags
;
2644 SWP_DoWinPosChanging( wndPtr
, &winpos
, &newWindowRect
, &newClientRect
);
2646 if((winpos
.flags
& (SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) != SWP_NOZORDER
)
2648 if( wndPtr
->parent
== WIN_GetDesktop() )
2649 hwndInsertAfter
= SWP_DoOwnedPopups( wndPtr
->parent
, wndPtr
,
2650 hwndInsertAfter
, winpos
.flags
);
2651 WIN_ReleaseDesktop();
2654 if(!(wndPtr
->flags
& WIN_NATIVE
) )
2656 if( hwndInsertAfter
== HWND_TOP
)
2657 winpos
.flags
|= ( wndPtr
->parent
->child
== wndPtr
)? SWP_NOZORDER
: 0;
2659 if( hwndInsertAfter
== HWND_BOTTOM
)
2660 winpos
.flags
|= ( wndPtr
->next
)? 0: SWP_NOZORDER
;
2662 if( !(winpos
.flags
& SWP_NOZORDER
) )
2663 if( GetWindow(hwndInsertAfter
, GW_HWNDNEXT
) == wndPtr
->hwndSelf
)
2664 winpos
.flags
|= SWP_NOZORDER
;
2666 if( !(winpos
.flags
& (SWP_NOREDRAW
| SWP_SHOWWINDOW
)) &&
2667 ((winpos
.flags
& (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_FRAMECHANGED
))
2668 != (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
)) )
2670 /* get a previous visible region for SWP_CopyValidBits() */
2671 DWORD flags
= DCX_WINDOW
;
2673 if (wndPtr
->dwStyle
& WS_CLIPSIBLINGS
)
2674 flags
|= DCX_CLIPSIBLINGS
;
2676 visRgn
= DCE_GetVisRgn(hwnd
, flags
, 0, 0);
2680 /* Common operations */
2682 wvrFlags
= SWP_DoNCCalcSize( wndPtr
, &winpos
, &newWindowRect
, &newClientRect
, flags
);
2684 if(!(winpos
.flags
& SWP_NOZORDER
) && winpos
.hwnd
!= hwndInsertAfter
)
2686 if ( WIN_UnlinkWindow( winpos
.hwnd
) )
2687 WIN_LinkWindow( winpos
.hwnd
, hwndInsertAfter
);
2690 /* Reset active DCEs */
2692 if( (((winpos
.flags
& SWP_AGG_NOPOSCHANGE
) != SWP_AGG_NOPOSCHANGE
) &&
2693 wndPtr
->dwStyle
& WS_VISIBLE
) ||
2694 (flags
& (SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) )
2698 UnionRect(&rect
, &newWindowRect
, &wndPtr
->rectWindow
);
2699 DCE_InvalidateDCE(wndPtr
, &rect
);
2702 oldWindowRect
= wndPtr
->rectWindow
;
2703 oldClientRect
= wndPtr
->rectClient
;
2705 /* Find out if we have to redraw the whole client rect */
2707 if( oldClientRect
.bottom
- oldClientRect
.top
==
2708 newClientRect
.bottom
- newClientRect
.top
) wvrFlags
&= ~WVR_VREDRAW
;
2710 if( oldClientRect
.right
- oldClientRect
.left
==
2711 newClientRect
.right
- newClientRect
.left
) wvrFlags
&= ~WVR_HREDRAW
;
2713 if( (winpos
.flags
& SWP_NOCOPYBITS
) || (!(winpos
.flags
& SWP_NOCLIENTSIZE
) &&
2714 (wvrFlags
>= WVR_HREDRAW
) && (wvrFlags
< WVR_VALIDRECTS
)) )
2716 uFlags
|= SWP_EX_NOCOPY
;
2719 * Use this later in CopyValidBits()
2722 uFlags |= SWP_EX_NONCLIENT;
2725 /* FIXME: actually do something with WVR_VALIDRECTS */
2727 wndPtr
->rectWindow
= newWindowRect
;
2728 wndPtr
->rectClient
= newClientRect
;
2730 if (wndPtr
->flags
& WIN_NATIVE
) /* -------------------------------------------- hosted window */
2732 BOOL bCallDriver
= TRUE
;
2733 HWND tempInsertAfter
= winpos
.hwndInsertAfter
;
2735 winpos
.hwndInsertAfter
= hwndInsertAfter
;
2737 if( !(winpos
.flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
| SWP_NOREDRAW
)) )
2739 /* This is the only place where we need to force repainting of the contents
2740 of windows created by the host window system, all other cases go through the
2741 expose event handling */
2743 if( (winpos
.flags
& (SWP_NOSIZE
| SWP_FRAMECHANGED
)) == (SWP_NOSIZE
| SWP_FRAMECHANGED
) )
2745 cx
= newWindowRect
.right
- newWindowRect
.left
;
2746 cy
= newWindowRect
.bottom
- newWindowRect
.top
;
2748 wndPtr
->pDriver
->pSetWindowPos(wndPtr
, &winpos
, bChangePos
);
2749 winpos
.hwndInsertAfter
= tempInsertAfter
;
2750 bCallDriver
= FALSE
;
2752 if( winpos
.flags
& SWP_NOCLIENTMOVE
)
2753 SWP_DoSimpleFrameChanged(wndPtr
, &oldClientRect
, winpos
.flags
, uFlags
);
2756 /* client area moved but window extents remained the same, copy valid bits */
2758 visRgn
= CreateRectRgn( 0, 0, cx
, cy
);
2759 uFlags
= SWP_CopyValidBits( wndPtr
, &visRgn
, &oldWindowRect
, &oldClientRect
,
2760 uFlags
| SWP_EX_PAINTSELF
);
2767 if( !(winpos
.flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
| SWP_NOREDRAW
)) )
2769 if( (oldClientRect
.left
- oldWindowRect
.left
== newClientRect
.left
- newWindowRect
.left
) &&
2770 (oldClientRect
.top
- oldWindowRect
.top
== newClientRect
.top
- newWindowRect
.top
) &&
2771 !(uFlags
& SWP_EX_NOCOPY
) )
2773 /* The origin of the client rect didn't move so we can try to repaint
2774 * only the nonclient area by setting bit gravity hint for the host window system.
2777 if( !(wndPtr
->flags
& WIN_MANAGED
) )
2779 HRGN hrgn
= CreateRectRgn( 0, 0, newWindowRect
.right
- newWindowRect
.left
,
2780 newWindowRect
.bottom
- newWindowRect
.top
);
2781 RECT rcn
= newClientRect
;
2782 RECT rco
= oldClientRect
;
2784 OffsetRect( &rcn
, -newWindowRect
.left
, -newWindowRect
.top
);
2785 OffsetRect( &rco
, -oldWindowRect
.left
, -oldWindowRect
.top
);
2786 IntersectRect( &rcn
, &rcn
, &rco
);
2787 visRgn
= CreateRectRgnIndirect( &rcn
);
2788 CombineRgn( visRgn
, hrgn
, visRgn
, RGN_DIFF
);
2789 DeleteObject( hrgn
);
2790 uFlags
= SWP_EX_PAINTSELF
;
2792 wndPtr
->pDriver
->pSetHostAttr(wndPtr
, HAK_BITGRAVITY
, BGNorthWest
);
2795 wndPtr
->pDriver
->pSetHostAttr(wndPtr
, HAK_BITGRAVITY
, BGForget
);
2798 wndPtr
->pDriver
->pSetWindowPos(wndPtr
, &winpos
, bChangePos
);
2799 winpos
.hwndInsertAfter
= tempInsertAfter
;
2802 if( winpos
.flags
& SWP_SHOWWINDOW
)
2806 wndPtr
->dwStyle
|= WS_VISIBLE
;
2808 if (wndPtr
->flags
& WIN_MANAGED
) resync
= TRUE
;
2810 /* focus was set to unmapped window, reset host focus
2811 * since the window is now visible */
2813 focus
= curr
= GetFocus();
2818 WND
*pFocus
= WIN_FindWndPtr( focus
);
2820 pFocus
->pDriver
->pSetFocus(pFocus
);
2821 WIN_ReleaseWndPtr(pFocus
);
2824 curr
= GetParent(curr
);
2828 else /* -------------------------------------------- emulated window */
2830 if( winpos
.flags
& SWP_SHOWWINDOW
)
2832 wndPtr
->dwStyle
|= WS_VISIBLE
;
2833 uFlags
|= SWP_EX_PAINTSELF
;
2834 visRgn
= 1; /* redraw the whole window */
2836 else if( !(winpos
.flags
& SWP_NOREDRAW
) )
2838 if( winpos
.flags
& SWP_HIDEWINDOW
)
2840 if( visRgn
> 1 ) /* map to parent */
2841 OffsetRgn( visRgn
, oldWindowRect
.left
, oldWindowRect
.top
);
2847 if( (winpos
.flags
& SWP_AGG_NOPOSCHANGE
) != SWP_AGG_NOPOSCHANGE
)
2848 uFlags
= SWP_CopyValidBits(wndPtr
, &visRgn
, &oldWindowRect
,
2849 &oldClientRect
, uFlags
);
2852 /* nothing moved, redraw frame if needed */
2854 if( winpos
.flags
& SWP_FRAMECHANGED
)
2855 SWP_DoSimpleFrameChanged( wndPtr
, &oldClientRect
, winpos
.flags
, uFlags
);
2858 DeleteObject( visRgn
);
2866 if( winpos
.flags
& SWP_HIDEWINDOW
)
2868 wndPtr
->dwStyle
&= ~WS_VISIBLE
;
2871 if (hwnd
== CARET_GetHwnd())
2873 if( winpos
.flags
& SWP_HIDEWINDOW
)
2875 else if (winpos
.flags
& SWP_SHOWWINDOW
)
2879 /* ------------------------------------------------------------------------ FINAL */
2881 if (wndPtr
->flags
& WIN_NATIVE
)
2882 EVENT_Synchronize(); /* Synchronize with the host window system */
2884 if (!GetCapture() && ((wndPtr
->dwStyle
& WS_VISIBLE
) || (flags
& SWP_HIDEWINDOW
)))
2886 /* Simulate a mouse event to set the cursor */
2887 int iWndsLocks
= WIN_SuspendWndsLock();
2889 hardware_event( WM_MOUSEMOVE
, GET_KEYSTATE(), 0,
2890 PosX
, PosY
, GetTickCount(), 0 );
2892 WIN_RestoreWndsLock(iWndsLocks
);
2895 wndTemp
= WIN_GetDesktop();
2897 /* repaint invalidated region (if any)
2899 * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2900 * and force update after ChangeActiveWindow() to avoid painting frames twice.
2905 if( !(winpos
.flags
& SWP_NOREDRAW
) )
2908 /* Use PAINT_RedrawWindow to explicitly force an invalidation of the window,
2909 its parent and sibling and so on, and then erase the parent window
2910 back ground if the parent is either a top-level window or its parent's parent
2911 is top-level window. Rely on the system to repaint other affected
2912 windows later on. */
2913 if( uFlags
& SWP_EX_PAINTSELF
)
2915 PAINT_RedrawWindow( wndPtr
->hwndSelf
, NULL
, (visRgn
== 1) ? 0 : visRgn
,
2916 RDW_ERASE
| RDW_FRAME
| RDW_INVALIDATE
| RDW_ALLCHILDREN
,
2917 RDW_EX_XYWINDOW
| RDW_EX_USEHRGN
);
2921 PAINT_RedrawWindow( wndPtr
->parent
->hwndSelf
, NULL
, (visRgn
== 1) ? 0 : visRgn
,
2922 RDW_ERASE
| RDW_INVALIDATE
| RDW_ALLCHILDREN
,
2926 if(wndPtr
-> parent
== wndTemp
|| wndPtr
->parent
->parent
== wndTemp
)
2928 PAINT_RedrawWindow( wndPtr
->parent
->hwndSelf
, NULL
, 0,
2929 RDW_ERASENOW
| RDW_NOCHILDREN
, 0 );
2933 DeleteObject( visRgn
);
2936 WIN_ReleaseDesktop();
2938 if (!(flags
& SWP_NOACTIVATE
))
2939 WINPOS_ChangeActiveWindow( winpos
.hwnd
, FALSE
);
2941 /* And last, send the WM_WINDOWPOSCHANGED message */
2943 TRACE("\tstatus flags = %04x\n", winpos
.flags
& SWP_AGG_STATUSFLAGS
);
2946 (((winpos
.flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOPOSCHANGE
) &&
2947 !(winpos
.flags
& SWP_NOSENDCHANGING
)) )
2949 SendMessageA( winpos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
)&winpos
);
2950 if (resync
) EVENT_Synchronize();
2955 WIN_ReleaseWndPtr(wndPtr
);
2960 /***********************************************************************
2961 * BeginDeferWindowPos16 (USER.259)
2963 HDWP16 WINAPI
BeginDeferWindowPos16( INT16 count
)
2965 return BeginDeferWindowPos( count
);
2969 /***********************************************************************
2970 * BeginDeferWindowPos (USER32.9)
2972 HDWP WINAPI
BeginDeferWindowPos( INT count
)
2979 SetLastError(ERROR_INVALID_PARAMETER
);
2982 /* Windows allows zero count, in which case it allocates context for 8 moves */
2983 if (count
== 0) count
= 8;
2985 handle
= USER_HEAP_ALLOC( sizeof(DWP
) + (count
-1)*sizeof(WINDOWPOS
) );
2986 if (!handle
) return 0;
2987 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( handle
);
2988 pDWP
->actualCount
= 0;
2989 pDWP
->suggestedCount
= count
;
2991 pDWP
->wMagic
= DWP_MAGIC
;
2992 pDWP
->hwndParent
= 0;
2997 /***********************************************************************
2998 * DeferWindowPos16 (USER.260)
3000 HDWP16 WINAPI
DeferWindowPos16( HDWP16 hdwp
, HWND16 hwnd
, HWND16 hwndAfter
,
3001 INT16 x
, INT16 y
, INT16 cx
, INT16 cy
,
3004 return DeferWindowPos( hdwp
, hwnd
, (INT
)(INT16
)hwndAfter
,
3005 x
, y
, cx
, cy
, flags
);
3009 /***********************************************************************
3010 * DeferWindowPos (USER32.128)
3012 HDWP WINAPI
DeferWindowPos( HDWP hdwp
, HWND hwnd
, HWND hwndAfter
,
3013 INT x
, INT y
, INT cx
, INT cy
,
3018 HDWP newhdwp
= hdwp
,retvalue
;
3022 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
3023 if (!pDWP
) return 0;
3024 if (hwnd
== GetDesktopWindow()) return 0;
3026 if (!(pWnd
=WIN_FindWndPtr( hwnd
))) {
3027 USER_HEAP_FREE( hdwp
);
3031 /* Numega Bounds Checker Demo dislikes the following code.
3032 In fact, I've not been able to find any "same parent" requirement in any docu
3036 /* All the windows of a DeferWindowPos() must have the same parent */
3037 parent
= pWnd
->parent
->hwndSelf
;
3038 if (pDWP
->actualCount
== 0) pDWP
->hwndParent
= parent
;
3039 else if (parent
!= pDWP
->hwndParent
)
3041 USER_HEAP_FREE( hdwp
);
3047 for (i
= 0; i
< pDWP
->actualCount
; i
++)
3049 if (pDWP
->winPos
[i
].hwnd
== hwnd
)
3051 /* Merge with the other changes */
3052 if (!(flags
& SWP_NOZORDER
))
3054 pDWP
->winPos
[i
].hwndInsertAfter
= hwndAfter
;
3056 if (!(flags
& SWP_NOMOVE
))
3058 pDWP
->winPos
[i
].x
= x
;
3059 pDWP
->winPos
[i
].y
= y
;
3061 if (!(flags
& SWP_NOSIZE
))
3063 pDWP
->winPos
[i
].cx
= cx
;
3064 pDWP
->winPos
[i
].cy
= cy
;
3066 pDWP
->winPos
[i
].flags
&= flags
| ~(SWP_NOSIZE
| SWP_NOMOVE
|
3067 SWP_NOZORDER
| SWP_NOREDRAW
|
3068 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
3070 pDWP
->winPos
[i
].flags
|= flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
|
3076 if (pDWP
->actualCount
>= pDWP
->suggestedCount
)
3078 newhdwp
= USER_HEAP_REALLOC( hdwp
,
3079 sizeof(DWP
) + pDWP
->suggestedCount
*sizeof(WINDOWPOS
) );
3085 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( newhdwp
);
3086 pDWP
->suggestedCount
++;
3088 pDWP
->winPos
[pDWP
->actualCount
].hwnd
= hwnd
;
3089 pDWP
->winPos
[pDWP
->actualCount
].hwndInsertAfter
= hwndAfter
;
3090 pDWP
->winPos
[pDWP
->actualCount
].x
= x
;
3091 pDWP
->winPos
[pDWP
->actualCount
].y
= y
;
3092 pDWP
->winPos
[pDWP
->actualCount
].cx
= cx
;
3093 pDWP
->winPos
[pDWP
->actualCount
].cy
= cy
;
3094 pDWP
->winPos
[pDWP
->actualCount
].flags
= flags
;
3095 pDWP
->actualCount
++;
3098 WIN_ReleaseWndPtr(pWnd
);
3103 /***********************************************************************
3104 * EndDeferWindowPos16 (USER.261)
3106 BOOL16 WINAPI
EndDeferWindowPos16( HDWP16 hdwp
)
3108 return EndDeferWindowPos( hdwp
);
3112 /***********************************************************************
3113 * EndDeferWindowPos (USER32.173)
3115 BOOL WINAPI
EndDeferWindowPos( HDWP hdwp
)
3122 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
3123 if (!pDWP
) return FALSE
;
3124 for (i
= 0, winpos
= pDWP
->winPos
; i
< pDWP
->actualCount
; i
++, winpos
++)
3126 if (!(res
= SetWindowPos( winpos
->hwnd
, winpos
->hwndInsertAfter
,
3127 winpos
->x
, winpos
->y
, winpos
->cx
,
3128 winpos
->cy
, winpos
->flags
))) break;
3130 USER_HEAP_FREE( hdwp
);
3135 /***********************************************************************
3136 * TileChildWindows (USER.199)
3138 void WINAPI
TileChildWindows16( HWND16 parent
, WORD action
)
3140 FIXME("(%04x, %d): stub\n", parent
, action
);
3143 /***********************************************************************
3144 * CascadeChildWindows (USER.198)
3146 void WINAPI
CascadeChildWindows16( HWND16 parent
, WORD action
)
3148 FIXME("(%04x, %d): stub\n", parent
, action
);
3151 /***********************************************************************
3152 * SetProgmanWindow [USER32.522]
3154 HRESULT WINAPI
SetProgmanWindow ( HWND hwnd
)
3156 hGlobalProgmanWindow
= hwnd
;
3157 return hGlobalProgmanWindow
;
3160 /***********************************************************************
3161 * GetProgmanWindow [USER32.289]
3163 HRESULT WINAPI
GetProgmanWindow ( )
3165 return hGlobalProgmanWindow
;
3168 /***********************************************************************
3169 * SetShellWindowEx [USER32.531]
3170 * hwndProgman = Progman[Program Manager]
3171 * |-> SHELLDLL_DefView
3172 * hwndListView = | |-> SysListView32
3173 * | | |-> tooltips_class32
3179 HRESULT WINAPI
SetShellWindowEx ( HWND hwndProgman
, HWND hwndListView
)
3181 FIXME("0x%08x 0x%08x stub\n",hwndProgman
,hwndListView
);
3182 hGlobalShellWindow
= hwndProgman
;
3183 return hGlobalShellWindow
;
3187 /***********************************************************************
3188 * SetTaskmanWindow [USER32.537]
3190 * hwnd = MSTaskSwWClass
3191 * |-> SysTabControl32
3193 HRESULT WINAPI
SetTaskmanWindow ( HWND hwnd
)
3195 hGlobalTaskmanWindow
= hwnd
;
3196 return hGlobalTaskmanWindow
;
3199 /***********************************************************************
3200 * GetTaskmanWindow [USER32.304]
3202 HRESULT WINAPI
GetTaskmanWindow ( )
3204 return hGlobalTaskmanWindow
;