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
);
312 /* we'd like to set it back to 0 */
315 GetWindowRect(hwnd
, &tempRect
);
319 /* verify that region really exists */
320 if (GetRgnBox(hrgn
, &tempRect
) == ERROR
) goto done
;
324 /* Size the window to the rectangle of the new region
325 (if it isn't NULL) */
326 SetWindowPos( hwnd
, NULL
, tempRect
.left
, tempRect
.top
,
327 tempRect
.right
- tempRect
.left
, tempRect
.bottom
- tempRect
.top
,
328 SWP_NOSIZE
| SWP_FRAMECHANGED
| SWP_NOMOVE
|
329 SWP_NOZORDER
| (bRedraw
? 0 : SWP_NOREDRAW
) );
334 /* delete previous region */
335 DeleteObject(wndPtr
->hrgnWnd
);
338 else if (hrgn
== NULL
)
340 /* if there was no previous region (stored in wndPtr->hrgnWnd) and
341 the region to be set is also NULL, there is nothing more to do
347 /* valid region handle */
348 wndPtr
->hrgnWnd
= hrgn
;
349 wndPtr
->pDriver
->pSetWindowRgn(wndPtr
, hrgn
);
354 WIN_ReleaseWndPtr(wndPtr
);
358 /***********************************************************************
361 INT16 WINAPI
SetWindowRgn16( HWND16 hwnd
, HRGN16 hrgn
,BOOL16 bRedraw
)
365 FIXME("SetWindowRgn16: stub\n");
370 /***********************************************************************
371 * GetClientRect16 (USER.33)
373 void WINAPI
GetClientRect16( HWND16 hwnd
, LPRECT16 rect
)
375 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
377 rect
->left
= rect
->top
= rect
->right
= rect
->bottom
= 0;
380 rect
->right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
381 rect
->bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
383 WIN_ReleaseWndPtr(wndPtr
);
387 /***********************************************************************
388 * GetClientRect (USER.220)
390 BOOL WINAPI
GetClientRect( HWND hwnd
, LPRECT rect
)
392 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
394 rect
->left
= rect
->top
= rect
->right
= rect
->bottom
= 0;
395 if (!wndPtr
) return FALSE
;
396 rect
->right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
397 rect
->bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
399 WIN_ReleaseWndPtr(wndPtr
);
404 /*******************************************************************
405 * ClientToScreen16 (USER.28)
407 void WINAPI
ClientToScreen16( HWND16 hwnd
, LPPOINT16 lppnt
)
409 MapWindowPoints16( hwnd
, 0, lppnt
, 1 );
413 /*******************************************************************
414 * ClientToScreen (USER32.52)
416 BOOL WINAPI
ClientToScreen( HWND hwnd
, LPPOINT lppnt
)
418 MapWindowPoints( hwnd
, 0, lppnt
, 1 );
423 /*******************************************************************
424 * ScreenToClient16 (USER.29)
426 void WINAPI
ScreenToClient16( HWND16 hwnd
, LPPOINT16 lppnt
)
428 MapWindowPoints16( 0, hwnd
, lppnt
, 1 );
432 /*******************************************************************
433 * ScreenToClient (USER32.447)
435 BOOL WINAPI
ScreenToClient( HWND hwnd
, LPPOINT lppnt
)
437 MapWindowPoints( 0, hwnd
, lppnt
, 1 );
442 /***********************************************************************
443 * WINPOS_WindowFromPoint
445 * Find the window and hittest for a given point.
447 INT16
WINPOS_WindowFromPoint( WND
* wndScope
, POINT16 pt
, WND
**ppWnd
)
450 INT16 hittest
= HTERROR
;
454 TRACE("scope %04x %d,%d\n", wndScope
->hwndSelf
, pt
.x
, pt
.y
);
456 wndPtr
= WIN_LockWndPtr(wndScope
->child
);
458 if( wndScope
->dwStyle
& WS_DISABLED
)
464 if( wndScope
->dwExStyle
& WS_EX_MANAGED
)
466 /* In managed mode we have to check wndScope first as it is also
467 * a window which received the mouse event. */
469 if( pt
.x
< wndScope
->rectClient
.left
|| pt
.x
>= wndScope
->rectClient
.right
||
470 pt
.y
< wndScope
->rectClient
.top
|| pt
.y
>= wndScope
->rectClient
.bottom
)
473 MapWindowPoints16( GetDesktopWindow16(), wndScope
->hwndSelf
, &xy
, 1 );
479 /* If point is in window, and window is visible, and it */
480 /* is enabled (or it's a top-level window), then explore */
481 /* its children. Otherwise, go to the next window. */
483 if ((wndPtr
->dwStyle
& WS_VISIBLE
) &&
484 (!(wndPtr
->dwStyle
& WS_DISABLED
) ||
485 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)) &&
487 PtInRegion(wndPtr
->hrgnWnd
, xy
.x
- wndPtr
->rectWindow
.left
,
488 xy
.y
- wndPtr
->rectWindow
.top
) :
489 ((xy
.x
>= wndPtr
->rectWindow
.left
) &&
490 (xy
.x
< wndPtr
->rectWindow
.right
) &&
491 (xy
.y
>= wndPtr
->rectWindow
.top
) &&
492 (xy
.y
< wndPtr
->rectWindow
.bottom
))))
494 TRACE("%d,%d is inside %04x\n", xy
.x
, xy
.y
, wndPtr
->hwndSelf
);
495 *ppWnd
= wndPtr
; /* Got a suitable window */
497 /* If window is minimized or disabled, return at once */
498 if (wndPtr
->dwStyle
& WS_MINIMIZE
)
500 retvalue
= HTCAPTION
;
503 if (wndPtr
->dwStyle
& WS_DISABLED
)
509 /* If point is not in client area, ignore the children */
510 if ((xy
.x
< wndPtr
->rectClient
.left
) ||
511 (xy
.x
>= wndPtr
->rectClient
.right
) ||
512 (xy
.y
< wndPtr
->rectClient
.top
) ||
513 (xy
.y
>= wndPtr
->rectClient
.bottom
)) break;
515 xy
.x
-= wndPtr
->rectClient
.left
;
516 xy
.y
-= wndPtr
->rectClient
.top
;
517 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->child
);
521 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->next
);
526 /* If nothing found, try the scope window */
527 if (!*ppWnd
) *ppWnd
= wndScope
;
529 /* Send the WM_NCHITTEST message (only if to the same task) */
530 if ((*ppWnd
)->hmemTaskQ
== GetFastQueue16())
532 hittest
= (INT16
)SendMessage16( (*ppWnd
)->hwndSelf
, WM_NCHITTEST
,
533 0, MAKELONG( pt
.x
, pt
.y
) );
534 if (hittest
!= HTTRANSPARENT
)
536 retvalue
= hittest
; /* Found the window */
546 /* If no children found in last search, make point relative to parent */
549 xy
.x
+= (*ppWnd
)->rectClient
.left
;
550 xy
.y
+= (*ppWnd
)->rectClient
.top
;
553 /* Restart the search from the next sibling */
554 WIN_UpdateWndPtr(&wndPtr
,(*ppWnd
)->next
);
555 *ppWnd
= (*ppWnd
)->parent
;
559 WIN_ReleaseWndPtr(wndPtr
);
564 /*******************************************************************
565 * WindowFromPoint16 (USER.30)
567 HWND16 WINAPI
WindowFromPoint16( POINT16 pt
)
570 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt
, &pWnd
);
571 WIN_ReleaseDesktop();
572 return pWnd
->hwndSelf
;
576 /*******************************************************************
577 * WindowFromPoint (USER32.582)
579 HWND WINAPI
WindowFromPoint( POINT pt
)
583 CONV_POINT32TO16( &pt
, &pt16
);
584 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16
, &pWnd
);
585 WIN_ReleaseDesktop();
586 return (HWND
)pWnd
->hwndSelf
;
590 /*******************************************************************
591 * ChildWindowFromPoint16 (USER.191)
593 HWND16 WINAPI
ChildWindowFromPoint16( HWND16 hwndParent
, POINT16 pt
)
596 CONV_POINT16TO32( &pt
, &pt32
);
597 return (HWND16
)ChildWindowFromPoint( hwndParent
, pt32
);
601 /*******************************************************************
602 * ChildWindowFromPoint (USER32.49)
604 HWND WINAPI
ChildWindowFromPoint( HWND hwndParent
, POINT pt
)
606 /* pt is in the client coordinates */
608 WND
* wnd
= WIN_FindWndPtr(hwndParent
);
614 /* get client rect fast */
615 rect
.top
= rect
.left
= 0;
616 rect
.right
= wnd
->rectClient
.right
- wnd
->rectClient
.left
;
617 rect
.bottom
= wnd
->rectClient
.bottom
- wnd
->rectClient
.top
;
619 if (!PtInRect( &rect
, pt
))
624 WIN_UpdateWndPtr(&wnd
,wnd
->child
);
627 if (PtInRect( &wnd
->rectWindow
, pt
))
629 retvalue
= wnd
->hwndSelf
;
632 WIN_UpdateWndPtr(&wnd
,wnd
->next
);
634 retvalue
= hwndParent
;
636 WIN_ReleaseWndPtr(wnd
);
640 /*******************************************************************
641 * ChildWindowFromPointEx16 (USER.50)
643 HWND16 WINAPI
ChildWindowFromPointEx16( HWND16 hwndParent
, POINT16 pt
, UINT16 uFlags
)
646 CONV_POINT16TO32( &pt
, &pt32
);
647 return (HWND16
)ChildWindowFromPointEx( hwndParent
, pt32
, uFlags
);
651 /*******************************************************************
652 * ChildWindowFromPointEx (USER32.50)
654 HWND WINAPI
ChildWindowFromPointEx( HWND hwndParent
, POINT pt
,
657 /* pt is in the client coordinates */
659 WND
* wnd
= WIN_FindWndPtr(hwndParent
);
665 /* get client rect fast */
666 rect
.top
= rect
.left
= 0;
667 rect
.right
= wnd
->rectClient
.right
- wnd
->rectClient
.left
;
668 rect
.bottom
= wnd
->rectClient
.bottom
- wnd
->rectClient
.top
;
670 if (!PtInRect( &rect
, pt
))
675 WIN_UpdateWndPtr(&wnd
,wnd
->child
);
679 if (PtInRect( &wnd
->rectWindow
, pt
)) {
680 if ( (uFlags
& CWP_SKIPINVISIBLE
) &&
681 !(wnd
->dwStyle
& WS_VISIBLE
) );
682 else if ( (uFlags
& CWP_SKIPDISABLED
) &&
683 (wnd
->dwStyle
& WS_DISABLED
) );
684 else if ( (uFlags
& CWP_SKIPTRANSPARENT
) &&
685 (wnd
->dwExStyle
& WS_EX_TRANSPARENT
) );
688 retvalue
= wnd
->hwndSelf
;
693 WIN_UpdateWndPtr(&wnd
,wnd
->next
);
695 retvalue
= hwndParent
;
697 WIN_ReleaseWndPtr(wnd
);
702 /*******************************************************************
703 * WINPOS_GetWinOffset
705 * Calculate the offset between the origin of the two windows. Used
706 * to implement MapWindowPoints.
708 static void WINPOS_GetWinOffset( HWND hwndFrom
, HWND hwndTo
,
713 offset
->x
= offset
->y
= 0;
714 if (hwndFrom
== hwndTo
) return;
716 /* Translate source window origin to screen coords */
719 if (!(wndPtr
= WIN_FindWndPtr( hwndFrom
)))
721 ERR("bad hwndFrom = %04x\n",hwndFrom
);
724 while (wndPtr
->parent
)
726 offset
->x
+= wndPtr
->rectClient
.left
;
727 offset
->y
+= wndPtr
->rectClient
.top
;
728 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->parent
);
730 WIN_ReleaseWndPtr(wndPtr
);
733 /* Translate origin to destination window coords */
736 if (!(wndPtr
= WIN_FindWndPtr( hwndTo
)))
738 ERR("bad hwndTo = %04x\n", hwndTo
);
741 while (wndPtr
->parent
)
743 offset
->x
-= wndPtr
->rectClient
.left
;
744 offset
->y
-= wndPtr
->rectClient
.top
;
745 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->parent
);
747 WIN_ReleaseWndPtr(wndPtr
);
752 /*******************************************************************
753 * MapWindowPoints16 (USER.258)
755 void WINAPI
MapWindowPoints16( HWND16 hwndFrom
, HWND16 hwndTo
,
756 LPPOINT16 lppt
, UINT16 count
)
760 WINPOS_GetWinOffset( hwndFrom
, hwndTo
, &offset
);
770 /*******************************************************************
771 * MapWindowPoints (USER32.386)
773 INT WINAPI
MapWindowPoints( HWND hwndFrom
, HWND hwndTo
,
774 LPPOINT lppt
, UINT count
)
778 WINPOS_GetWinOffset( hwndFrom
, hwndTo
, &offset
);
785 return MAKELONG( LOWORD(offset
.x
), LOWORD(offset
.y
) );
789 /***********************************************************************
790 * IsIconic16 (USER.31)
792 BOOL16 WINAPI
IsIconic16(HWND16 hWnd
)
794 return IsIconic(hWnd
);
798 /***********************************************************************
799 * IsIconic (USER32.345)
801 BOOL WINAPI
IsIconic(HWND hWnd
)
804 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
805 if (wndPtr
== NULL
) return FALSE
;
806 retvalue
= (wndPtr
->dwStyle
& WS_MINIMIZE
) != 0;
807 WIN_ReleaseWndPtr(wndPtr
);
812 /***********************************************************************
813 * IsZoomed (USER.272)
815 BOOL16 WINAPI
IsZoomed16(HWND16 hWnd
)
817 return IsZoomed(hWnd
);
821 /***********************************************************************
822 * IsZoomed (USER.352)
824 BOOL WINAPI
IsZoomed(HWND hWnd
)
827 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
828 if (wndPtr
== NULL
) return FALSE
;
829 retvalue
= (wndPtr
->dwStyle
& WS_MAXIMIZE
) != 0;
830 WIN_ReleaseWndPtr(wndPtr
);
835 /*******************************************************************
836 * GetActiveWindow (USER.60)
838 HWND16 WINAPI
GetActiveWindow16(void)
840 return (HWND16
)GetActiveWindow();
843 /*******************************************************************
844 * GetActiveWindow (USER32.205)
846 HWND WINAPI
GetActiveWindow(void)
848 MESSAGEQUEUE
*pCurMsgQ
= 0;
851 /* Get the messageQ for the current thread */
852 if (!(pCurMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( GetFastQueue16() )))
854 WARN("\tCurrent message queue not found. Exiting!\n" );
858 /* Return the current active window from the perQ data of the current message Q */
859 hwndActive
= PERQDATA_GetActiveWnd( pCurMsgQ
->pQData
);
861 QUEUE_Unlock( pCurMsgQ
);
866 /*******************************************************************
869 static BOOL
WINPOS_CanActivate(WND
* pWnd
)
871 if( pWnd
&& ( (pWnd
->dwStyle
& (WS_DISABLED
| WS_VISIBLE
| WS_CHILD
))
872 == WS_VISIBLE
) ) return TRUE
;
877 /*******************************************************************
878 * SetActiveWindow16 (USER.59)
880 HWND16 WINAPI
SetActiveWindow16( HWND16 hwnd
)
882 return SetActiveWindow(hwnd
);
886 /*******************************************************************
887 * SetActiveWindow (USER32.463)
889 HWND WINAPI
SetActiveWindow( HWND hwnd
)
892 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
893 MESSAGEQUEUE
*pMsgQ
= 0, *pCurMsgQ
= 0;
895 if (!wndPtr
|| (wndPtr
->dwStyle
& (WS_DISABLED
| WS_CHILD
)))
901 /* Get the messageQ for the current thread */
902 if (!(pCurMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( GetFastQueue16() )))
904 WARN("\tCurrent message queue not found. Exiting!\n" );
908 /* Retrieve the message queue associated with this window */
909 pMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( wndPtr
->hmemTaskQ
);
912 WARN("\tWindow message queue not found. Exiting!\n" );
916 /* Make sure that the window is associated with the calling threads
917 * message queue. It must share the same perQ data.
920 if ( pCurMsgQ
->pQData
!= pMsgQ
->pQData
)
923 /* Save current active window */
924 prev
= PERQDATA_GetActiveWnd( pMsgQ
->pQData
);
926 WINPOS_SetActiveWindow( hwnd
, 0, 0 );
929 /* Unlock the queues before returning */
931 QUEUE_Unlock( pMsgQ
);
933 QUEUE_Unlock( pCurMsgQ
);
936 WIN_ReleaseWndPtr(wndPtr
);
941 /*******************************************************************
942 * GetForegroundWindow16 (USER.608)
944 HWND16 WINAPI
GetForegroundWindow16(void)
946 return (HWND16
)GetForegroundWindow();
950 /*******************************************************************
951 * SetForegroundWindow16 (USER.609)
953 BOOL16 WINAPI
SetForegroundWindow16( HWND16 hwnd
)
955 return SetForegroundWindow( hwnd
);
959 /*******************************************************************
960 * GetForegroundWindow (USER32.241)
962 HWND WINAPI
GetForegroundWindow(void)
966 /* Get the foreground window (active window of hActiveQueue) */
969 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
971 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
973 QUEUE_Unlock( pActiveQueue
);
979 /*******************************************************************
980 * SetForegroundWindow (USER32.482)
982 BOOL WINAPI
SetForegroundWindow( HWND hwnd
)
984 return WINPOS_ChangeActiveWindow( hwnd
, FALSE
);
988 /*******************************************************************
989 * GetShellWindow16 (USER.600)
991 HWND16 WINAPI
GetShellWindow16(void)
993 return GetShellWindow();
996 /*******************************************************************
997 * SetShellWindow (USER32.504)
999 HWND WINAPI
SetShellWindow(HWND hwndshell
)
1000 { WARN("(hWnd=%08x) semi stub\n",hwndshell
);
1002 hGlobalShellWindow
= hwndshell
;
1003 return hGlobalShellWindow
;
1007 /*******************************************************************
1008 * GetShellWindow (USER32.287)
1010 HWND WINAPI
GetShellWindow(void)
1011 { WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow
);
1013 return hGlobalShellWindow
;
1017 /***********************************************************************
1018 * BringWindowToTop16 (USER.45)
1020 BOOL16 WINAPI
BringWindowToTop16( HWND16 hwnd
)
1022 return BringWindowToTop(hwnd
);
1026 /***********************************************************************
1027 * BringWindowToTop (USER32.11)
1029 BOOL WINAPI
BringWindowToTop( HWND hwnd
)
1031 return SetWindowPos( hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
);
1035 /***********************************************************************
1036 * MoveWindow16 (USER.56)
1038 BOOL16 WINAPI
MoveWindow16( HWND16 hwnd
, INT16 x
, INT16 y
, INT16 cx
, INT16 cy
,
1041 return MoveWindow(hwnd
,x
,y
,cx
,cy
,repaint
);
1045 /***********************************************************************
1046 * MoveWindow (USER32.399)
1048 BOOL WINAPI
MoveWindow( HWND hwnd
, INT x
, INT y
, INT cx
, INT cy
,
1051 int flags
= SWP_NOZORDER
| SWP_NOACTIVATE
;
1052 if (!repaint
) flags
|= SWP_NOREDRAW
;
1053 TRACE("%04x %d,%d %dx%d %d\n",
1054 hwnd
, x
, y
, cx
, cy
, repaint
);
1055 return SetWindowPos( hwnd
, 0, x
, y
, cx
, cy
, flags
);
1058 /***********************************************************************
1059 * WINPOS_InitInternalPos
1061 static LPINTERNALPOS
WINPOS_InitInternalPos( WND
* wnd
, POINT pt
,
1062 LPRECT restoreRect
)
1064 LPINTERNALPOS lpPos
= (LPINTERNALPOS
) GetPropA( wnd
->hwndSelf
,
1068 /* this happens when the window is minimized/maximized
1069 * for the first time (rectWindow is not adjusted yet) */
1071 lpPos
= HeapAlloc( SystemHeap
, 0, sizeof(INTERNALPOS
) );
1072 if( !lpPos
) return NULL
;
1074 SetPropA( wnd
->hwndSelf
, atomInternalPos
, (HANDLE
)lpPos
);
1075 lpPos
->hwndIconTitle
= 0; /* defer until needs to be shown */
1076 CONV_RECT32TO16( &wnd
->rectWindow
, &lpPos
->rectNormal
);
1077 *(UINT
*)&lpPos
->ptIconPos
= *(UINT
*)&lpPos
->ptMaxPos
= 0xFFFFFFFF;
1080 if( wnd
->dwStyle
& WS_MINIMIZE
)
1081 CONV_POINT32TO16( &pt
, &lpPos
->ptIconPos
);
1082 else if( wnd
->dwStyle
& WS_MAXIMIZE
)
1083 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1084 else if( restoreRect
)
1085 CONV_RECT32TO16( restoreRect
, &lpPos
->rectNormal
);
1090 /***********************************************************************
1091 * WINPOS_RedrawIconTitle
1093 BOOL
WINPOS_RedrawIconTitle( HWND hWnd
)
1095 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)GetPropA( hWnd
, atomInternalPos
);
1098 if( lpPos
->hwndIconTitle
)
1100 SendMessageA( lpPos
->hwndIconTitle
, WM_SHOWWINDOW
, TRUE
, 0);
1101 InvalidateRect( lpPos
->hwndIconTitle
, NULL
, TRUE
);
1108 /***********************************************************************
1109 * WINPOS_ShowIconTitle
1111 BOOL
WINPOS_ShowIconTitle( WND
* pWnd
, BOOL bShow
)
1113 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)GetPropA( pWnd
->hwndSelf
, atomInternalPos
);
1115 if( lpPos
&& !(pWnd
->dwExStyle
& WS_EX_MANAGED
))
1117 HWND16 hWnd
= lpPos
->hwndIconTitle
;
1119 TRACE("0x%04x %i\n", pWnd
->hwndSelf
, (bShow
!= 0) );
1122 lpPos
->hwndIconTitle
= hWnd
= ICONTITLE_Create( pWnd
);
1125 if( ( pWnd
= WIN_FindWndPtr(hWnd
) ) != NULL
)
1127 if( !(pWnd
->dwStyle
& WS_VISIBLE
) )
1129 SendMessageA( hWnd
, WM_SHOWWINDOW
, TRUE
, 0 );
1130 SetWindowPos( hWnd
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
1131 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_SHOWWINDOW
);
1133 WIN_ReleaseWndPtr(pWnd
);
1136 else ShowWindow( hWnd
, SW_HIDE
);
1141 /*******************************************************************
1142 * WINPOS_GetMinMaxInfo
1144 * Get the minimized and maximized information for a window.
1146 void WINPOS_GetMinMaxInfo( WND
*wndPtr
, POINT
*maxSize
, POINT
*maxPos
,
1147 POINT
*minTrack
, POINT
*maxTrack
)
1149 LPINTERNALPOS lpPos
;
1153 /* Compute default values */
1155 MinMax
.ptMaxSize
.x
= GetSystemMetrics(SM_CXSCREEN
);
1156 MinMax
.ptMaxSize
.y
= GetSystemMetrics(SM_CYSCREEN
);
1157 MinMax
.ptMinTrackSize
.x
= GetSystemMetrics(SM_CXMINTRACK
);
1158 MinMax
.ptMinTrackSize
.y
= GetSystemMetrics(SM_CYMINTRACK
);
1159 MinMax
.ptMaxTrackSize
.x
= GetSystemMetrics(SM_CXSCREEN
);
1160 MinMax
.ptMaxTrackSize
.y
= GetSystemMetrics(SM_CYSCREEN
);
1162 if (wndPtr
->dwExStyle
& WS_EX_MANAGED
) xinc
= yinc
= 0;
1163 else if (HAS_DLGFRAME( wndPtr
->dwStyle
, wndPtr
->dwExStyle
))
1165 xinc
= GetSystemMetrics(SM_CXDLGFRAME
);
1166 yinc
= GetSystemMetrics(SM_CYDLGFRAME
);
1171 if (HAS_THICKFRAME(wndPtr
->dwStyle
))
1173 xinc
+= GetSystemMetrics(SM_CXFRAME
);
1174 yinc
+= GetSystemMetrics(SM_CYFRAME
);
1176 if (wndPtr
->dwStyle
& WS_BORDER
)
1178 xinc
+= GetSystemMetrics(SM_CXBORDER
);
1179 yinc
+= GetSystemMetrics(SM_CYBORDER
);
1182 MinMax
.ptMaxSize
.x
+= 2 * xinc
;
1183 MinMax
.ptMaxSize
.y
+= 2 * yinc
;
1185 lpPos
= (LPINTERNALPOS
)GetPropA( wndPtr
->hwndSelf
, atomInternalPos
);
1186 if( lpPos
&& !EMPTYPOINT(lpPos
->ptMaxPos
) )
1187 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &MinMax
.ptMaxPosition
);
1190 MinMax
.ptMaxPosition
.x
= -xinc
;
1191 MinMax
.ptMaxPosition
.y
= -yinc
;
1194 SendMessageA( wndPtr
->hwndSelf
, WM_GETMINMAXINFO
, 0, (LPARAM
)&MinMax
);
1196 /* Some sanity checks */
1198 TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1199 MinMax
.ptMaxSize
.x
, MinMax
.ptMaxSize
.y
,
1200 MinMax
.ptMaxPosition
.x
, MinMax
.ptMaxPosition
.y
,
1201 MinMax
.ptMaxTrackSize
.x
, MinMax
.ptMaxTrackSize
.y
,
1202 MinMax
.ptMinTrackSize
.x
, MinMax
.ptMinTrackSize
.y
);
1203 MinMax
.ptMaxTrackSize
.x
= max( MinMax
.ptMaxTrackSize
.x
,
1204 MinMax
.ptMinTrackSize
.x
);
1205 MinMax
.ptMaxTrackSize
.y
= max( MinMax
.ptMaxTrackSize
.y
,
1206 MinMax
.ptMinTrackSize
.y
);
1208 if (maxSize
) *maxSize
= MinMax
.ptMaxSize
;
1209 if (maxPos
) *maxPos
= MinMax
.ptMaxPosition
;
1210 if (minTrack
) *minTrack
= MinMax
.ptMinTrackSize
;
1211 if (maxTrack
) *maxTrack
= MinMax
.ptMaxTrackSize
;
1214 /***********************************************************************
1215 * WINPOS_MinMaximize
1217 * Fill in lpRect and return additional flags to be used with SetWindowPos().
1218 * This function assumes that 'cmd' is different from the current window
1221 UINT
WINPOS_MinMaximize( WND
* wndPtr
, UINT16 cmd
, LPRECT16 lpRect
)
1225 LPINTERNALPOS lpPos
;
1227 TRACE("0x%04x %u\n", wndPtr
->hwndSelf
, cmd
);
1229 size
.x
= wndPtr
->rectWindow
.left
; size
.y
= wndPtr
->rectWindow
.top
;
1230 lpPos
= WINPOS_InitInternalPos( wndPtr
, size
, &wndPtr
->rectWindow
);
1232 if (lpPos
&& !HOOK_CallHooks16(WH_CBT
, HCBT_MINMAX
, wndPtr
->hwndSelf
, cmd
))
1234 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1236 if( !SendMessageA( wndPtr
->hwndSelf
, WM_QUERYOPEN
, 0, 0L ) )
1237 return (SWP_NOSIZE
| SWP_NOMOVE
);
1238 swpFlags
|= SWP_NOCOPYBITS
;
1243 if( wndPtr
->dwStyle
& WS_MAXIMIZE
)
1245 wndPtr
->flags
|= WIN_RESTORE_MAX
;
1246 wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
1249 wndPtr
->flags
&= ~WIN_RESTORE_MAX
;
1250 wndPtr
->dwStyle
|= WS_MINIMIZE
;
1252 if( wndPtr
->flags
& WIN_NATIVE
)
1253 if( wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, TRUE
) )
1254 swpFlags
|= MINMAX_NOSWP
;
1256 lpPos
->ptIconPos
= WINPOS_FindIconPos( wndPtr
, lpPos
->ptIconPos
);
1258 SetRect16( lpRect
, lpPos
->ptIconPos
.x
, lpPos
->ptIconPos
.y
,
1259 GetSystemMetrics(SM_CXICON
), GetSystemMetrics(SM_CYICON
) );
1260 swpFlags
|= SWP_NOCOPYBITS
;
1264 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &pt
);
1265 WINPOS_GetMinMaxInfo( wndPtr
, &size
, &pt
, NULL
, NULL
);
1266 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1268 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1270 if( wndPtr
->flags
& WIN_NATIVE
)
1271 wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, FALSE
);
1273 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
1274 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
1276 wndPtr
->dwStyle
|= WS_MAXIMIZE
;
1278 SetRect16( lpRect
, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
,
1283 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1285 if( wndPtr
->flags
& WIN_NATIVE
)
1286 if( wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, FALSE
) )
1287 swpFlags
|= MINMAX_NOSWP
;
1289 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
1290 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
1292 if( wndPtr
->flags
& WIN_RESTORE_MAX
)
1294 /* Restore to maximized position */
1295 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &pt
);
1296 WINPOS_GetMinMaxInfo( wndPtr
, &size
, &pt
, NULL
, NULL
);
1297 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1298 wndPtr
->dwStyle
|= WS_MAXIMIZE
;
1299 SetRect16( lpRect
, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
, size
.x
, size
.y
);
1304 if( !(wndPtr
->dwStyle
& WS_MAXIMIZE
) ) return (UINT16
)(-1);
1305 else wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
1307 /* Restore to normal position */
1309 *lpRect
= lpPos
->rectNormal
;
1310 lpRect
->right
-= lpRect
->left
;
1311 lpRect
->bottom
-= lpRect
->top
;
1315 } else swpFlags
|= SWP_NOSIZE
| SWP_NOMOVE
;
1319 /***********************************************************************
1320 * ShowWindowAsync (USER32.535)
1322 * doesn't wait; returns immediately.
1323 * used by threads to toggle windows in other (possibly hanging) threads
1325 BOOL WINAPI
ShowWindowAsync( HWND hwnd
, INT cmd
)
1327 /* FIXME: does ShowWindow() return immediately ? */
1328 return ShowWindow(hwnd
, cmd
);
1332 /***********************************************************************
1333 * ShowWindow16 (USER.42)
1335 BOOL16 WINAPI
ShowWindow16( HWND16 hwnd
, INT16 cmd
)
1337 return ShowWindow(hwnd
,cmd
);
1341 /***********************************************************************
1342 * ShowWindow (USER32.534)
1344 BOOL WINAPI
ShowWindow( HWND hwnd
, INT cmd
)
1346 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
1347 BOOL wasVisible
, showFlag
;
1348 RECT16 newPos
= {0, 0, 0, 0};
1351 if (!wndPtr
) return FALSE
;
1353 TRACE("hwnd=%04x, cmd=%d\n", hwnd
, cmd
);
1355 wasVisible
= (wndPtr
->dwStyle
& WS_VISIBLE
) != 0;
1360 if (!wasVisible
) goto END
;;
1361 swp
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
|
1362 SWP_NOACTIVATE
| SWP_NOZORDER
;
1365 case SW_SHOWMINNOACTIVE
:
1366 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1368 case SW_SHOWMINIMIZED
:
1369 swp
|= SWP_SHOWWINDOW
;
1372 swp
|= SWP_FRAMECHANGED
;
1373 if( !(wndPtr
->dwStyle
& WS_MINIMIZE
) )
1374 swp
|= WINPOS_MinMaximize( wndPtr
, SW_MINIMIZE
, &newPos
);
1375 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1378 case SW_SHOWMAXIMIZED
: /* same as SW_MAXIMIZE */
1379 swp
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
1380 if( !(wndPtr
->dwStyle
& WS_MAXIMIZE
) )
1381 swp
|= WINPOS_MinMaximize( wndPtr
, SW_MAXIMIZE
, &newPos
);
1382 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1386 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1389 swp
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
1392 * ShowWindow has a little peculiar behavior that if the
1393 * window is already the topmost window, it will not
1396 if (GetTopWindow((HWND
)0)==hwnd
&& (wasVisible
|| GetActiveWindow() == hwnd
))
1397 swp
|= SWP_NOACTIVATE
;
1401 case SW_SHOWNOACTIVATE
:
1402 swp
|= SWP_NOZORDER
;
1403 if (GetActiveWindow()) swp
|= SWP_NOACTIVATE
;
1405 case SW_SHOWNORMAL
: /* same as SW_NORMAL: */
1406 case SW_SHOWDEFAULT
: /* FIXME: should have its own handler */
1408 swp
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
1410 if( wndPtr
->dwStyle
& (WS_MINIMIZE
| WS_MAXIMIZE
) )
1411 swp
|= WINPOS_MinMaximize( wndPtr
, SW_RESTORE
, &newPos
);
1412 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1416 showFlag
= (cmd
!= SW_HIDE
);
1417 if (showFlag
!= wasVisible
)
1419 SendMessageA( hwnd
, WM_SHOWWINDOW
, showFlag
, 0 );
1420 if (!IsWindow( hwnd
)) goto END
;
1423 if ((wndPtr
->dwStyle
& WS_CHILD
) &&
1424 !IsWindowVisible( wndPtr
->parent
->hwndSelf
) &&
1425 (swp
& (SWP_NOSIZE
| SWP_NOMOVE
)) == (SWP_NOSIZE
| SWP_NOMOVE
) )
1427 /* Don't call SetWindowPos() on invisible child windows */
1428 if (cmd
== SW_HIDE
) wndPtr
->dwStyle
&= ~WS_VISIBLE
;
1429 else wndPtr
->dwStyle
|= WS_VISIBLE
;
1433 /* We can't activate a child window */
1434 if ((wndPtr
->dwStyle
& WS_CHILD
) &&
1435 !(wndPtr
->dwExStyle
& WS_EX_MDICHILD
))
1436 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1437 if (!(swp
& MINMAX_NOSWP
))
1439 SetWindowPos( hwnd
, HWND_TOP
, newPos
.left
, newPos
.top
,
1440 newPos
.right
, newPos
.bottom
, LOWORD(swp
) );
1443 /* FIXME: This will cause the window to be activated irrespective
1444 * of whether it is owned by the same thread. Has to be done
1448 if (hwnd
== GetActiveWindow())
1449 WINPOS_ActivateOtherWindow(wndPtr
);
1451 /* Revert focus to parent */
1452 if (hwnd
== GetFocus() || IsChild(hwnd
, GetFocus()))
1453 SetFocus( GetParent(hwnd
) );
1456 if (!IsWindow( hwnd
)) goto END
;
1457 else if( wndPtr
->dwStyle
& WS_MINIMIZE
) WINPOS_ShowIconTitle( wndPtr
, TRUE
);
1460 if (wndPtr
->flags
& WIN_NEED_SIZE
)
1462 /* should happen only in CreateWindowEx() */
1463 int wParam
= SIZE_RESTORED
;
1465 wndPtr
->flags
&= ~WIN_NEED_SIZE
;
1466 if (wndPtr
->dwStyle
& WS_MAXIMIZE
) wParam
= SIZE_MAXIMIZED
;
1467 else if (wndPtr
->dwStyle
& WS_MINIMIZE
) wParam
= SIZE_MINIMIZED
;
1468 SendMessageA( hwnd
, WM_SIZE
, wParam
,
1469 MAKELONG(wndPtr
->rectClient
.right
-wndPtr
->rectClient
.left
,
1470 wndPtr
->rectClient
.bottom
-wndPtr
->rectClient
.top
));
1471 SendMessageA( hwnd
, WM_MOVE
, 0,
1472 MAKELONG(wndPtr
->rectClient
.left
, wndPtr
->rectClient
.top
) );
1476 WIN_ReleaseWndPtr(wndPtr
);
1481 /***********************************************************************
1482 * GetInternalWindowPos16 (USER.460)
1484 UINT16 WINAPI
GetInternalWindowPos16( HWND16 hwnd
, LPRECT16 rectWnd
,
1487 WINDOWPLACEMENT16 wndpl
;
1488 if (GetWindowPlacement16( hwnd
, &wndpl
))
1490 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
1491 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
1492 return wndpl
.showCmd
;
1498 /***********************************************************************
1499 * GetInternalWindowPos (USER32.245)
1501 UINT WINAPI
GetInternalWindowPos( HWND hwnd
, LPRECT rectWnd
,
1504 WINDOWPLACEMENT wndpl
;
1505 if (GetWindowPlacement( hwnd
, &wndpl
))
1507 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
1508 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
1509 return wndpl
.showCmd
;
1514 /***********************************************************************
1515 * GetWindowPlacement16 (USER.370)
1517 BOOL16 WINAPI
GetWindowPlacement16( HWND16 hwnd
, WINDOWPLACEMENT16
*wndpl
)
1519 WND
*pWnd
= WIN_FindWndPtr( hwnd
);
1520 LPINTERNALPOS lpPos
;
1522 if(!pWnd
) return FALSE
;
1524 lpPos
= (LPINTERNALPOS
)WINPOS_InitInternalPos( pWnd
,
1525 *(LPPOINT
)&pWnd
->rectWindow
.left
, &pWnd
->rectWindow
);
1526 wndpl
->length
= sizeof(*wndpl
);
1527 if( pWnd
->dwStyle
& WS_MINIMIZE
)
1528 wndpl
->showCmd
= SW_SHOWMINIMIZED
;
1530 wndpl
->showCmd
= ( pWnd
->dwStyle
& WS_MAXIMIZE
)
1531 ? SW_SHOWMAXIMIZED
: SW_SHOWNORMAL
;
1532 if( pWnd
->flags
& WIN_RESTORE_MAX
)
1533 wndpl
->flags
= WPF_RESTORETOMAXIMIZED
;
1536 wndpl
->ptMinPosition
= lpPos
->ptIconPos
;
1537 wndpl
->ptMaxPosition
= lpPos
->ptMaxPos
;
1538 wndpl
->rcNormalPosition
= lpPos
->rectNormal
;
1540 WIN_ReleaseWndPtr(pWnd
);
1545 /***********************************************************************
1546 * GetWindowPlacement (USER32.307)
1549 * Fails if wndpl->length of Win95 (!) apps is invalid.
1551 BOOL WINAPI
GetWindowPlacement( HWND hwnd
, WINDOWPLACEMENT
*pwpl32
)
1555 WINDOWPLACEMENT16 wpl
;
1556 wpl
.length
= sizeof(wpl
);
1557 if( GetWindowPlacement16( hwnd
, &wpl
) )
1559 pwpl32
->length
= sizeof(*pwpl32
);
1560 pwpl32
->flags
= wpl
.flags
;
1561 pwpl32
->showCmd
= wpl
.showCmd
;
1562 CONV_POINT16TO32( &wpl
.ptMinPosition
, &pwpl32
->ptMinPosition
);
1563 CONV_POINT16TO32( &wpl
.ptMaxPosition
, &pwpl32
->ptMaxPosition
);
1564 CONV_RECT16TO32( &wpl
.rcNormalPosition
, &pwpl32
->rcNormalPosition
);
1572 /***********************************************************************
1573 * WINPOS_SetPlacement
1575 static BOOL
WINPOS_SetPlacement( HWND hwnd
, const WINDOWPLACEMENT16
*wndpl
,
1578 WND
*pWnd
= WIN_FindWndPtr( hwnd
);
1581 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)WINPOS_InitInternalPos( pWnd
,
1582 *(LPPOINT
)&pWnd
->rectWindow
.left
, &pWnd
->rectWindow
);
1584 if( flags
& PLACE_MIN
) lpPos
->ptIconPos
= wndpl
->ptMinPosition
;
1585 if( flags
& PLACE_MAX
) lpPos
->ptMaxPos
= wndpl
->ptMaxPosition
;
1586 if( flags
& PLACE_RECT
) lpPos
->rectNormal
= wndpl
->rcNormalPosition
;
1588 if( pWnd
->dwStyle
& WS_MINIMIZE
)
1590 WINPOS_ShowIconTitle( pWnd
, FALSE
);
1591 if( wndpl
->flags
& WPF_SETMINPOSITION
&& !EMPTYPOINT(lpPos
->ptIconPos
))
1592 SetWindowPos( hwnd
, 0, lpPos
->ptIconPos
.x
, lpPos
->ptIconPos
.y
,
1593 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1595 else if( pWnd
->dwStyle
& WS_MAXIMIZE
)
1597 if( !EMPTYPOINT(lpPos
->ptMaxPos
) )
1598 SetWindowPos( hwnd
, 0, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
,
1599 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1601 else if( flags
& PLACE_RECT
)
1602 SetWindowPos( hwnd
, 0, lpPos
->rectNormal
.left
, lpPos
->rectNormal
.top
,
1603 lpPos
->rectNormal
.right
- lpPos
->rectNormal
.left
,
1604 lpPos
->rectNormal
.bottom
- lpPos
->rectNormal
.top
,
1605 SWP_NOZORDER
| SWP_NOACTIVATE
);
1607 ShowWindow( hwnd
, wndpl
->showCmd
);
1608 if( IsWindow(hwnd
) && pWnd
->dwStyle
& WS_MINIMIZE
)
1610 if( pWnd
->dwStyle
& WS_VISIBLE
) WINPOS_ShowIconTitle( pWnd
, TRUE
);
1612 /* SDK: ...valid only the next time... */
1613 if( wndpl
->flags
& WPF_RESTORETOMAXIMIZED
) pWnd
->flags
|= WIN_RESTORE_MAX
;
1615 WIN_ReleaseWndPtr(pWnd
);
1622 /***********************************************************************
1623 * SetWindowPlacement16 (USER.371)
1625 BOOL16 WINAPI
SetWindowPlacement16(HWND16 hwnd
, const WINDOWPLACEMENT16
*wndpl
)
1627 return WINPOS_SetPlacement( hwnd
, wndpl
,
1628 PLACE_MIN
| PLACE_MAX
| PLACE_RECT
);
1631 /***********************************************************************
1632 * SetWindowPlacement (USER32.519)
1635 * Fails if wndpl->length of Win95 (!) apps is invalid.
1637 BOOL WINAPI
SetWindowPlacement( HWND hwnd
, const WINDOWPLACEMENT
*pwpl32
)
1641 WINDOWPLACEMENT16 wpl
;
1643 wpl
.length
= sizeof(WINDOWPLACEMENT16
);
1644 wpl
.flags
= pwpl32
->flags
;
1645 wpl
.showCmd
= pwpl32
->showCmd
;
1646 wpl
.ptMinPosition
.x
= pwpl32
->ptMinPosition
.x
;
1647 wpl
.ptMinPosition
.y
= pwpl32
->ptMinPosition
.y
;
1648 wpl
.ptMaxPosition
.x
= pwpl32
->ptMaxPosition
.x
;
1649 wpl
.ptMaxPosition
.y
= pwpl32
->ptMaxPosition
.y
;
1650 wpl
.rcNormalPosition
.left
= pwpl32
->rcNormalPosition
.left
;
1651 wpl
.rcNormalPosition
.top
= pwpl32
->rcNormalPosition
.top
;
1652 wpl
.rcNormalPosition
.right
= pwpl32
->rcNormalPosition
.right
;
1653 wpl
.rcNormalPosition
.bottom
= pwpl32
->rcNormalPosition
.bottom
;
1655 return WINPOS_SetPlacement( hwnd
, &wpl
, PLACE_MIN
| PLACE_MAX
| PLACE_RECT
);
1661 /***********************************************************************
1662 * SetInternalWindowPos16 (USER.461)
1664 void WINAPI
SetInternalWindowPos16( HWND16 hwnd
, UINT16 showCmd
,
1665 LPRECT16 rect
, LPPOINT16 pt
)
1667 if( IsWindow16(hwnd
) )
1669 WINDOWPLACEMENT16 wndpl
;
1672 wndpl
.length
= sizeof(wndpl
);
1673 wndpl
.showCmd
= showCmd
;
1674 wndpl
.flags
= flags
= 0;
1679 wndpl
.flags
|= WPF_SETMINPOSITION
;
1680 wndpl
.ptMinPosition
= *pt
;
1684 flags
|= PLACE_RECT
;
1685 wndpl
.rcNormalPosition
= *rect
;
1687 WINPOS_SetPlacement( hwnd
, &wndpl
, flags
);
1692 /***********************************************************************
1693 * SetInternalWindowPos (USER32.483)
1695 void WINAPI
SetInternalWindowPos( HWND hwnd
, UINT showCmd
,
1696 LPRECT rect
, LPPOINT pt
)
1698 if( IsWindow(hwnd
) )
1700 WINDOWPLACEMENT16 wndpl
;
1703 wndpl
.length
= sizeof(wndpl
);
1704 wndpl
.showCmd
= showCmd
;
1705 wndpl
.flags
= flags
= 0;
1710 wndpl
.flags
|= WPF_SETMINPOSITION
;
1711 CONV_POINT32TO16( pt
, &wndpl
.ptMinPosition
);
1715 flags
|= PLACE_RECT
;
1716 CONV_RECT32TO16( rect
, &wndpl
.rcNormalPosition
);
1718 WINPOS_SetPlacement( hwnd
, &wndpl
, flags
);
1722 /*******************************************************************
1723 * WINPOS_SetActiveWindow
1725 * SetActiveWindow() back-end. This is the only function that
1726 * can assign active status to a window. It must be called only
1727 * for the top level windows.
1729 BOOL
WINPOS_SetActiveWindow( HWND hWnd
, BOOL fMouse
, BOOL fChangeFocus
)
1731 CBTACTIVATESTRUCT16
* cbtStruct
;
1732 WND
* wndPtr
=0, *wndTemp
;
1733 HQUEUE16 hOldActiveQueue
, hNewActiveQueue
;
1734 MESSAGEQUEUE
*pOldActiveQueue
= 0, *pNewActiveQueue
= 0;
1736 HWND hwndActive
= 0;
1739 TRACE("(%04x, %d, %d)\n", hWnd
, fMouse
, fChangeFocus
);
1741 /* Get current active window from the active queue */
1744 pOldActiveQueue
= QUEUE_Lock( hActiveQueue
);
1745 if ( pOldActiveQueue
)
1746 hwndActive
= PERQDATA_GetActiveWnd( pOldActiveQueue
->pQData
);
1749 /* paranoid checks */
1750 if( hWnd
== GetDesktopWindow() || (bRet
= (hWnd
== hwndActive
)) )
1753 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1756 wndPtr
= WIN_FindWndPtr(hWnd
);
1757 hOldActiveQueue
= hActiveQueue
;
1759 if( (wndTemp
= WIN_FindWndPtr(hwndActive
)) )
1761 wIconized
= HIWORD(wndTemp
->dwStyle
& WS_MINIMIZE
);
1762 WIN_ReleaseWndPtr(wndTemp
);
1765 TRACE("no current active window.\n");
1767 /* call CBT hook chain */
1768 if ((cbtStruct
= SEGPTR_NEW(CBTACTIVATESTRUCT16
)))
1770 cbtStruct
->fMouse
= fMouse
;
1771 cbtStruct
->hWndActive
= hwndActive
;
1772 bRet
= (BOOL
)HOOK_CallHooks16( WH_CBT
, HCBT_ACTIVATE
, (WPARAM16
)hWnd
,
1773 (LPARAM
)SEGPTR_GET(cbtStruct
) );
1774 SEGPTR_FREE(cbtStruct
);
1775 if (bRet
) goto CLEANUP_END
;
1778 /* set prev active wnd to current active wnd and send notification */
1779 if ((hwndPrevActive
= hwndActive
) && IsWindow(hwndPrevActive
))
1781 MESSAGEQUEUE
*pTempActiveQueue
= 0;
1783 if (!SendMessageA( hwndPrevActive
, WM_NCACTIVATE
, FALSE
, 0 ))
1785 if (GetSysModalWindow16() != hWnd
)
1787 /* disregard refusal if hWnd is sysmodal */
1790 SendMessageA( hwndPrevActive
, WM_ACTIVATE
,
1791 MAKEWPARAM( WA_INACTIVE
, wIconized
),
1794 /* check if something happened during message processing
1795 * (global active queue may have changed)
1797 pTempActiveQueue
= QUEUE_Lock( hActiveQueue
);
1798 if(!pTempActiveQueue
)
1801 hwndActive
= PERQDATA_GetActiveWnd( pTempActiveQueue
->pQData
);
1802 QUEUE_Unlock( pTempActiveQueue
);
1803 if( hwndPrevActive
!= hwndActive
)
1807 /* Set new active window in the message queue */
1811 pNewActiveQueue
= QUEUE_Lock( wndPtr
->hmemTaskQ
);
1812 if ( pNewActiveQueue
)
1813 PERQDATA_SetActiveWnd( pNewActiveQueue
->pQData
, hwndActive
);
1815 else /* have to do this or MDI frame activation goes to hell */
1816 if( pOldActiveQueue
)
1817 PERQDATA_SetActiveWnd( pOldActiveQueue
->pQData
, 0 );
1819 /* send palette messages */
1820 if (hWnd
&& SendMessage16( hWnd
, WM_QUERYNEWPALETTE
, 0, 0L))
1821 SendMessage16((HWND16
)-1, WM_PALETTEISCHANGING
, (WPARAM16
)hWnd
, 0L );
1823 /* if prev wnd is minimized redraw icon title */
1824 if( IsIconic( hwndPrevActive
) ) WINPOS_RedrawIconTitle(hwndPrevActive
);
1826 /* managed windows will get ConfigureNotify event */
1827 if (wndPtr
&& !(wndPtr
->dwStyle
& WS_CHILD
) && !(wndPtr
->dwExStyle
& WS_EX_MANAGED
))
1829 /* check Z-order and bring hWnd to the top */
1830 for (wndTemp
= WIN_LockWndPtr(WIN_GetDesktop()->child
); wndTemp
; WIN_UpdateWndPtr(&wndTemp
,wndTemp
->next
))
1832 if (wndTemp
->dwStyle
& WS_VISIBLE
) break;
1834 WIN_ReleaseDesktop();
1835 WIN_ReleaseWndPtr(wndTemp
);
1837 if( wndTemp
!= wndPtr
)
1838 SetWindowPos(hWnd
, HWND_TOP
, 0,0,0,0,
1839 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
1840 if (!IsWindow(hWnd
))
1844 /* Get a handle to the new active queue */
1845 hNewActiveQueue
= wndPtr
? wndPtr
->hmemTaskQ
: 0;
1847 /* send WM_ACTIVATEAPP if necessary */
1848 if (hOldActiveQueue
!= hNewActiveQueue
)
1850 WND
**list
, **ppWnd
;
1851 WND
*pDesktop
= WIN_GetDesktop();
1853 if ((list
= WIN_BuildWinArray( pDesktop
, 0, NULL
)))
1855 for (ppWnd
= list
; *ppWnd
; ppWnd
++)
1857 if (!IsWindow( (*ppWnd
)->hwndSelf
)) continue;
1859 if ((*ppWnd
)->hmemTaskQ
== hOldActiveQueue
)
1860 SendMessage16( (*ppWnd
)->hwndSelf
, WM_ACTIVATEAPP
,
1861 0, QUEUE_GetQueueTask(hNewActiveQueue
) );
1863 WIN_ReleaseWinArray(list
);
1866 hActiveQueue
= hNewActiveQueue
;
1868 if ((list
= WIN_BuildWinArray(pDesktop
, 0, NULL
)))
1870 for (ppWnd
= list
; *ppWnd
; ppWnd
++)
1872 if (!IsWindow( (*ppWnd
)->hwndSelf
)) continue;
1874 if ((*ppWnd
)->hmemTaskQ
== hNewActiveQueue
)
1875 SendMessage16( (*ppWnd
)->hwndSelf
, WM_ACTIVATEAPP
,
1876 1, QUEUE_GetQueueTask( hOldActiveQueue
) );
1878 WIN_ReleaseWinArray(list
);
1880 WIN_ReleaseDesktop();
1882 if (hWnd
&& !IsWindow(hWnd
)) goto CLEANUP
;
1887 /* walk up to the first unowned window */
1888 wndTemp
= WIN_LockWndPtr(wndPtr
);
1889 while (wndTemp
->owner
)
1891 WIN_UpdateWndPtr(&wndTemp
,wndTemp
->owner
);
1893 /* and set last active owned popup */
1894 wndTemp
->hwndLastActive
= hWnd
;
1896 wIconized
= HIWORD(wndTemp
->dwStyle
& WS_MINIMIZE
);
1897 WIN_ReleaseWndPtr(wndTemp
);
1898 SendMessageA( hWnd
, WM_NCACTIVATE
, TRUE
, 0 );
1899 SendMessageA( hWnd
, WM_ACTIVATE
,
1900 MAKEWPARAM( (fMouse
) ? WA_CLICKACTIVE
: WA_ACTIVE
, wIconized
),
1901 (LPARAM
)hwndPrevActive
);
1902 if( !IsWindow(hWnd
) ) goto CLEANUP
;
1905 /* change focus if possible */
1908 if ( pNewActiveQueue
)
1910 HWND hOldFocus
= PERQDATA_GetFocusWnd( pNewActiveQueue
->pQData
);
1912 if ( hOldFocus
&& WIN_GetTopParent( hOldFocus
) != hwndActive
)
1913 FOCUS_SwitchFocus( pNewActiveQueue
, hOldFocus
,
1914 (wndPtr
&& (wndPtr
->dwStyle
& WS_MINIMIZE
))?
1918 if ( pOldActiveQueue
&&
1919 ( !pNewActiveQueue
||
1920 pNewActiveQueue
->pQData
!= pOldActiveQueue
->pQData
) )
1922 HWND hOldFocus
= PERQDATA_GetFocusWnd( pOldActiveQueue
->pQData
);
1924 FOCUS_SwitchFocus( pOldActiveQueue
, hOldFocus
, 0 );
1928 if( !hwndPrevActive
&& wndPtr
)
1929 (*wndPtr
->pDriver
->pForceWindowRaise
)(wndPtr
);
1931 /* if active wnd is minimized redraw icon title */
1932 if( IsIconic(hwndActive
) ) WINPOS_RedrawIconTitle(hwndActive
);
1934 bRet
= (hWnd
== hwndActive
); /* Success? */
1936 CLEANUP
: /* Unlock the message queues before returning */
1938 if ( pNewActiveQueue
)
1939 QUEUE_Unlock( pNewActiveQueue
);
1943 if ( pOldActiveQueue
)
1944 QUEUE_Unlock( pOldActiveQueue
);
1946 WIN_ReleaseWndPtr(wndPtr
);
1950 /*******************************************************************
1951 * WINPOS_ActivateOtherWindow
1953 * Activates window other than pWnd.
1955 BOOL
WINPOS_ActivateOtherWindow(WND
* pWnd
)
1959 HWND hwndActive
= 0;
1961 /* Get current active window from the active queue */
1964 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
1967 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
1968 QUEUE_Unlock( pActiveQueue
);
1972 if( pWnd
->hwndSelf
== hwndPrevActive
)
1975 if( hwndActive
!= pWnd
->hwndSelf
&&
1976 ( hwndActive
|| QUEUE_IsExitingQueue(pWnd
->hmemTaskQ
)) )
1979 if( !(pWnd
->dwStyle
& WS_POPUP
) || !(pWnd
->owner
) ||
1980 !WINPOS_CanActivate((pWndTo
= WIN_GetTopParentPtr(pWnd
->owner
))) )
1982 WND
* pWndPtr
= WIN_GetTopParentPtr(pWnd
);
1984 WIN_ReleaseWndPtr(pWndTo
);
1985 pWndTo
= WIN_FindWndPtr(hwndPrevActive
);
1987 while( !WINPOS_CanActivate(pWndTo
) )
1989 /* by now owned windows should've been taken care of */
1990 WIN_UpdateWndPtr(&pWndTo
,pWndPtr
->next
);
1991 WIN_UpdateWndPtr(&pWndPtr
,pWndTo
);
1992 if( !pWndTo
) break;
1994 WIN_ReleaseWndPtr(pWndPtr
);
1997 bRet
= WINPOS_SetActiveWindow( pWndTo
? pWndTo
->hwndSelf
: 0, FALSE
, TRUE
);
1999 /* switch desktop queue to current active */
2002 WIN_GetDesktop()->hmemTaskQ
= pWndTo
->hmemTaskQ
;
2003 WIN_ReleaseWndPtr(pWndTo
);
2004 WIN_ReleaseDesktop();
2011 /*******************************************************************
2012 * WINPOS_ChangeActiveWindow
2015 BOOL
WINPOS_ChangeActiveWindow( HWND hWnd
, BOOL mouseMsg
)
2017 WND
*wndPtr
, *wndTemp
;
2019 HWND hwndActive
= 0;
2021 /* Get current active window from the active queue */
2024 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
2027 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
2028 QUEUE_Unlock( pActiveQueue
);
2033 return WINPOS_SetActiveWindow( 0, mouseMsg
, TRUE
);
2035 wndPtr
= WIN_FindWndPtr(hWnd
);
2036 if( !wndPtr
) return FALSE
;
2038 /* child windows get WM_CHILDACTIVATE message */
2039 if( (wndPtr
->dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
2041 retvalue
= SendMessageA(hWnd
, WM_CHILDACTIVATE
, 0, 0L);
2045 if( hWnd
== hwndActive
)
2051 if( !WINPOS_SetActiveWindow(hWnd
,mouseMsg
,TRUE
) )
2057 /* switch desktop queue to current active */
2058 wndTemp
= WIN_GetDesktop();
2059 if( wndPtr
->parent
== wndTemp
)
2060 wndTemp
->hmemTaskQ
= wndPtr
->hmemTaskQ
;
2061 WIN_ReleaseDesktop();
2065 WIN_ReleaseWndPtr(wndPtr
);
2070 /***********************************************************************
2071 * WINPOS_SendNCCalcSize
2073 * Send a WM_NCCALCSIZE message to a window.
2074 * All parameters are read-only except newClientRect.
2075 * oldWindowRect, oldClientRect and winpos must be non-NULL only
2076 * when calcValidRect is TRUE.
2078 LONG
WINPOS_SendNCCalcSize( HWND hwnd
, BOOL calcValidRect
,
2079 RECT
*newWindowRect
, RECT
*oldWindowRect
,
2080 RECT
*oldClientRect
, WINDOWPOS
*winpos
,
2081 RECT
*newClientRect
)
2083 NCCALCSIZE_PARAMS params
;
2084 WINDOWPOS winposCopy
;
2087 params
.rgrc
[0] = *newWindowRect
;
2090 winposCopy
= *winpos
;
2091 params
.rgrc
[1] = *oldWindowRect
;
2092 params
.rgrc
[2] = *oldClientRect
;
2093 params
.lppos
= &winposCopy
;
2095 result
= SendMessageA( hwnd
, WM_NCCALCSIZE
, calcValidRect
,
2097 TRACE("%d,%d-%d,%d\n",
2098 params
.rgrc
[0].left
, params
.rgrc
[0].top
,
2099 params
.rgrc
[0].right
, params
.rgrc
[0].bottom
);
2101 /* If the application send back garbage, ignore it */
2102 if (params
.rgrc
[0].left
<= params
.rgrc
[0].right
&& params
.rgrc
[0].top
<= params
.rgrc
[0].bottom
)
2103 *newClientRect
= params
.rgrc
[0];
2109 /***********************************************************************
2110 * WINPOS_HandleWindowPosChanging16
2112 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2114 LONG
WINPOS_HandleWindowPosChanging16( WND
*wndPtr
, WINDOWPOS16
*winpos
)
2116 POINT maxSize
, minTrack
;
2117 if (winpos
->flags
& SWP_NOSIZE
) return 0;
2118 if ((wndPtr
->dwStyle
& WS_THICKFRAME
) ||
2119 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) == 0))
2121 WINPOS_GetMinMaxInfo( wndPtr
, &maxSize
, NULL
, &minTrack
, NULL
);
2122 if (maxSize
.x
< winpos
->cx
) winpos
->cx
= maxSize
.x
;
2123 if (maxSize
.y
< winpos
->cy
) winpos
->cy
= maxSize
.y
;
2124 if (!(wndPtr
->dwStyle
& WS_MINIMIZE
))
2126 if (winpos
->cx
< minTrack
.x
) winpos
->cx
= minTrack
.x
;
2127 if (winpos
->cy
< minTrack
.y
) winpos
->cy
= minTrack
.y
;
2134 /***********************************************************************
2135 * WINPOS_HandleWindowPosChanging
2137 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2139 LONG
WINPOS_HandleWindowPosChanging( WND
*wndPtr
, WINDOWPOS
*winpos
)
2142 if (winpos
->flags
& SWP_NOSIZE
) return 0;
2143 if ((wndPtr
->dwStyle
& WS_THICKFRAME
) ||
2144 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) == 0))
2146 WINPOS_GetMinMaxInfo( wndPtr
, &maxSize
, NULL
, NULL
, NULL
);
2147 winpos
->cx
= min( winpos
->cx
, maxSize
.x
);
2148 winpos
->cy
= min( winpos
->cy
, maxSize
.y
);
2153 /***********************************************************************
2156 * fix Z order taking into account owned popups -
2157 * basically we need to maintain them above the window that owns them
2159 * FIXME: hide/show owned popups when owner visibility changes.
2161 static HWND
SWP_DoOwnedPopups(WND
* pDesktop
, WND
* wndPtr
, HWND hwndInsertAfter
, WORD flags
)
2163 WND
* w
= WIN_LockWndPtr(pDesktop
->child
);
2165 WARN("(%04x) hInsertAfter = %04x\n", wndPtr
->hwndSelf
, hwndInsertAfter
);
2167 if( (wndPtr
->dwStyle
& WS_POPUP
) && wndPtr
->owner
)
2169 /* make sure this popup stays above the owner */
2171 HWND hwndLocalPrev
= HWND_TOP
;
2173 if( hwndInsertAfter
!= HWND_TOP
)
2175 while( w
!= wndPtr
->owner
)
2177 if (w
!= wndPtr
) hwndLocalPrev
= w
->hwndSelf
;
2178 if( hwndLocalPrev
== hwndInsertAfter
) break;
2179 WIN_UpdateWndPtr(&w
,w
->next
);
2181 hwndInsertAfter
= hwndLocalPrev
;
2184 else if( wndPtr
->dwStyle
& WS_CHILD
)
2187 WIN_UpdateWndPtr(&w
, pDesktop
->child
);
2191 if( w
== wndPtr
) break;
2193 if( (w
->dwStyle
& WS_POPUP
) && w
->owner
== wndPtr
)
2195 SetWindowPos(w
->hwndSelf
, hwndInsertAfter
, 0, 0, 0, 0,
2196 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOSENDCHANGING
| SWP_DEFERERASE
);
2197 hwndInsertAfter
= w
->hwndSelf
;
2199 WIN_UpdateWndPtr(&w
, w
->next
);
2203 WIN_ReleaseWndPtr(w
);
2204 return hwndInsertAfter
;
2207 /***********************************************************************
2210 * Make window look nice without excessive repainting
2212 * visible and update regions are in window coordinates
2213 * client and window rectangles are in parent client coordinates
2215 * FIXME: SWP_EX_PAINTSELF in uFlags works only if both old and new
2216 * window rects have the same origin.
2218 * Returns: uFlags and a dirty region in *pVisRgn.
2220 static UINT
SWP_CopyValidBits( WND
* Wnd
, HRGN
* pVisRgn
,
2221 LPRECT lpOldWndRect
,
2222 LPRECT lpOldClientRect
, UINT uFlags
)
2225 HRGN newVisRgn
, dirtyRgn
;
2226 INT my
= COMPLEXREGION
;
2228 TRACE("\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2229 Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
,
2230 Wnd
->rectWindow
.right
, Wnd
->rectWindow
.bottom
,
2231 lpOldWndRect
->left
, lpOldWndRect
->top
,
2232 lpOldWndRect
->right
, lpOldWndRect
->bottom
, *pVisRgn
);
2233 TRACE("\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2234 Wnd
->rectClient
.left
, Wnd
->rectClient
.top
,
2235 Wnd
->rectClient
.right
, Wnd
->rectClient
.bottom
,
2236 lpOldClientRect
->left
, lpOldClientRect
->top
,
2237 lpOldClientRect
->right
,lpOldClientRect
->bottom
);
2239 if( Wnd
->hrgnUpdate
== 1 )
2240 uFlags
|= SWP_EX_NOCOPY
; /* whole window is invalid, nothing to copy */
2242 newVisRgn
= DCE_GetVisRgn( Wnd
->hwndSelf
, DCX_WINDOW
| DCX_CLIPSIBLINGS
, 0, 0);
2243 dirtyRgn
= CreateRectRgn( 0, 0, 0, 0 );
2245 if( !(uFlags
& SWP_EX_NOCOPY
) ) /* make sure dst region covers only valid bits */
2246 my
= CombineRgn( dirtyRgn
, newVisRgn
, *pVisRgn
, RGN_AND
);
2248 if( (my
== NULLREGION
) || (uFlags
& SWP_EX_NOCOPY
) )
2252 TRACE("\twon't copy anything!\n");
2254 /* set dirtyRgn to the sum of old and new visible regions
2255 * in parent client coordinates */
2257 OffsetRgn( newVisRgn
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2258 OffsetRgn( *pVisRgn
, lpOldWndRect
->left
, lpOldWndRect
->top
);
2260 CombineRgn(*pVisRgn
, *pVisRgn
, newVisRgn
, RGN_OR
);
2262 else /* copy valid bits to a new location */
2264 INT dx
, dy
, ow
, oh
, nw
, nh
, ocw
, ncw
, och
, nch
;
2265 HRGN hrgnValid
= dirtyRgn
; /* non-empty intersection of old and new visible rgns */
2267 /* subtract already invalid region inside Wnd from the dst region */
2269 if( Wnd
->hrgnUpdate
)
2270 if( CombineRgn( hrgnValid
, hrgnValid
, Wnd
->hrgnUpdate
, RGN_DIFF
) == NULLREGION
)
2273 /* check if entire window can be copied */
2275 ow
= lpOldWndRect
->right
- lpOldWndRect
->left
;
2276 oh
= lpOldWndRect
->bottom
- lpOldWndRect
->top
;
2277 nw
= Wnd
->rectWindow
.right
- Wnd
->rectWindow
.left
;
2278 nh
= Wnd
->rectWindow
.bottom
- Wnd
->rectWindow
.top
;
2280 ocw
= lpOldClientRect
->right
- lpOldClientRect
->left
;
2281 och
= lpOldClientRect
->bottom
- lpOldClientRect
->top
;
2282 ncw
= Wnd
->rectClient
.right
- Wnd
->rectClient
.left
;
2283 nch
= Wnd
->rectClient
.bottom
- Wnd
->rectClient
.top
;
2285 if( (ocw
!= ncw
) || (och
!= nch
) ||
2286 ( ow
!= nw
) || ( oh
!= nh
) ||
2287 ((lpOldClientRect
->top
- lpOldWndRect
->top
) !=
2288 (Wnd
->rectClient
.top
- Wnd
->rectWindow
.top
)) ||
2289 ((lpOldClientRect
->left
- lpOldWndRect
->left
) !=
2290 (Wnd
->rectClient
.left
- Wnd
->rectWindow
.left
)) )
2292 dx
= Wnd
->rectClient
.left
- lpOldClientRect
->left
;
2293 dy
= Wnd
->rectClient
.top
- lpOldClientRect
->top
;
2295 /* restrict valid bits to the common client rect */
2297 r
.left
= Wnd
->rectClient
.left
- Wnd
->rectWindow
.left
;
2298 r
.top
= Wnd
->rectClient
.top
- Wnd
->rectWindow
.top
;
2299 r
.right
= r
.left
+ min( ocw
, ncw
);
2300 r
.bottom
= r
.top
+ min( och
, nch
);
2302 REGION_CropRgn( hrgnValid
, hrgnValid
, &r
,
2303 (uFlags
& SWP_EX_PAINTSELF
) ? NULL
: (POINT
*)&(Wnd
->rectWindow
));
2304 GetRgnBox( hrgnValid
, &r
);
2305 if( IsRectEmpty( &r
) )
2307 r
= *lpOldClientRect
;
2311 dx
= Wnd
->rectWindow
.left
- lpOldWndRect
->left
;
2312 dy
= Wnd
->rectWindow
.top
- lpOldWndRect
->top
;
2313 if( !(uFlags
& SWP_EX_PAINTSELF
) )
2314 OffsetRgn( hrgnValid
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2318 if( !(uFlags
& SWP_EX_PAINTSELF
) )
2320 /* Move remaining regions to parent coordinates */
2321 OffsetRgn( newVisRgn
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2322 OffsetRgn( *pVisRgn
, lpOldWndRect
->left
, lpOldWndRect
->top
);
2325 OffsetRect( &r
, -lpOldWndRect
->left
, -lpOldWndRect
->top
);
2327 TRACE("\tcomputing dirty region!\n");
2329 /* Compute combined dirty region (old + new - valid) */
2330 CombineRgn( *pVisRgn
, *pVisRgn
, newVisRgn
, RGN_OR
);
2331 CombineRgn( *pVisRgn
, *pVisRgn
, hrgnValid
, RGN_DIFF
);
2333 /* Blt valid bits, r is the rect to copy */
2340 /* get DC and clip rect with drawable rect to avoid superfluous expose events
2341 from copying clipped areas */
2343 if( uFlags
& SWP_EX_PAINTSELF
)
2345 hDC
= GetDCEx( Wnd
->hwndSelf
, hrgnValid
, DCX_WINDOW
| DCX_CACHE
|
2346 DCX_KEEPCLIPRGN
| DCX_INTERSECTRGN
| DCX_CLIPSIBLINGS
);
2347 rClip
.right
= nw
; rClip
.bottom
= nh
;
2351 hDC
= GetDCEx( Wnd
->parent
->hwndSelf
, hrgnValid
, DCX_CACHE
|
2352 DCX_KEEPCLIPRGN
| DCX_INTERSECTRGN
| DCX_CLIPSIBLINGS
);
2353 rClip
.right
= Wnd
->parent
->rectClient
.right
- Wnd
->parent
->rectClient
.left
;
2354 rClip
.bottom
= Wnd
->parent
->rectClient
.bottom
- Wnd
->parent
->rectClient
.top
;
2356 rClip
.left
= rClip
.top
= 0;
2358 if( oh
> nh
) r
.bottom
= r
.top
+ nh
;
2359 if( ow
< nw
) r
.right
= r
.left
+ nw
;
2361 if( IntersectRect( &r
, &r
, &rClip
) )
2363 Wnd
->pDriver
->pSurfaceCopy( Wnd
->parent
, hDC
, dx
, dy
, &r
, TRUE
);
2365 /* When you copy the bits without repainting, parent doesn't
2366 get validated appropriately. Therefore, we have to validate
2367 the parent with the windows' updated region when the
2368 parent's update region is not empty. */
2370 if (Wnd
->parent
->hrgnUpdate
!= 0 && !(Wnd
->parent
->dwStyle
& WS_CLIPCHILDREN
))
2372 OffsetRect(&r
, dx
, dy
);
2373 ValidateRect(Wnd
->parent
->hwndSelf
, &r
);
2376 ReleaseDC( (uFlags
& SWP_EX_PAINTSELF
) ?
2377 Wnd
->hwndSelf
: Wnd
->parent
->hwndSelf
, hDC
);
2381 /* *pVisRgn now points to the invalidated region */
2383 DeleteObject(newVisRgn
);
2384 DeleteObject(dirtyRgn
);
2388 /***********************************************************************
2389 * SWP_DoSimpleFrameChanged
2391 * NOTE: old and new client rect origins are identical, only
2392 * extents may have changed. Window extents are the same.
2394 static void SWP_DoSimpleFrameChanged( WND
* wndPtr
, RECT
* pOldClientRect
, WORD swpFlags
, UINT uFlags
)
2400 if( !(swpFlags
& SWP_NOCLIENTSIZE
) )
2402 /* Client rect changed its position/size, most likely a scrollar
2403 * was added/removed.
2405 * FIXME: WVR alignment flags
2408 if( wndPtr
->rectClient
.right
> pOldClientRect
->right
) /* right edge */
2412 rect
.bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
2413 rect
.right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
2414 if(!(uFlags
& SWP_EX_NOCOPY
))
2415 rect
.left
= pOldClientRect
->right
- wndPtr
->rectClient
.left
;
2423 if( wndPtr
->rectClient
.bottom
> pOldClientRect
->bottom
) /* bottom edge */
2426 hrgn
= CreateRectRgnIndirect( &rect
);
2428 rect
.right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
2429 rect
.bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
2430 if(!(uFlags
& SWP_EX_NOCOPY
))
2431 rect
.top
= pOldClientRect
->bottom
- wndPtr
->rectClient
.top
;
2435 REGION_UnionRectWithRgn( hrgn
, &rect
);
2438 if( i
== 0 && (uFlags
& SWP_EX_NOCOPY
) ) /* force redraw anyway */
2440 rect
= wndPtr
->rectWindow
;
2441 OffsetRect( &rect
, wndPtr
->rectWindow
.left
- wndPtr
->rectClient
.left
,
2442 wndPtr
->rectWindow
.top
- wndPtr
->rectClient
.top
);
2450 PAINT_RedrawWindow( wndPtr
->hwndSelf
, &rect
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
|
2451 RDW_ERASENOW
| RDW_ALLCHILDREN
, RDW_EX_TOPFRAME
| RDW_EX_USEHRGN
);
2455 WIN_UpdateNCRgn(wndPtr
, 0, UNC_UPDATE
| UNC_ENTIRE
);
2459 DeleteObject( hrgn
);
2462 /***********************************************************************
2463 * SWP_DoWinPosChanging
2465 static BOOL
SWP_DoWinPosChanging( WND
* wndPtr
, WINDOWPOS
* pWinpos
,
2466 RECT
* pNewWindowRect
, RECT
* pNewClientRect
)
2468 /* Send WM_WINDOWPOSCHANGING message */
2470 if (!(pWinpos
->flags
& SWP_NOSENDCHANGING
))
2471 SendMessageA( wndPtr
->hwndSelf
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
)pWinpos
);
2473 /* Calculate new position and size */
2475 *pNewWindowRect
= wndPtr
->rectWindow
;
2476 *pNewClientRect
= (wndPtr
->dwStyle
& WS_MINIMIZE
) ? wndPtr
->rectWindow
2477 : wndPtr
->rectClient
;
2479 if (!(pWinpos
->flags
& SWP_NOSIZE
))
2481 pNewWindowRect
->right
= pNewWindowRect
->left
+ pWinpos
->cx
;
2482 pNewWindowRect
->bottom
= pNewWindowRect
->top
+ pWinpos
->cy
;
2484 if (!(pWinpos
->flags
& SWP_NOMOVE
))
2486 pNewWindowRect
->left
= pWinpos
->x
;
2487 pNewWindowRect
->top
= pWinpos
->y
;
2488 pNewWindowRect
->right
+= pWinpos
->x
- wndPtr
->rectWindow
.left
;
2489 pNewWindowRect
->bottom
+= pWinpos
->y
- wndPtr
->rectWindow
.top
;
2491 OffsetRect( pNewClientRect
, pWinpos
->x
- wndPtr
->rectWindow
.left
,
2492 pWinpos
->y
- wndPtr
->rectWindow
.top
);
2495 pWinpos
->flags
|= SWP_NOCLIENTMOVE
| SWP_NOCLIENTSIZE
;
2499 /***********************************************************************
2502 static UINT
SWP_DoNCCalcSize( WND
* wndPtr
, WINDOWPOS
* pWinpos
,
2503 RECT
* pNewWindowRect
, RECT
* pNewClientRect
, WORD f
)
2507 /* Send WM_NCCALCSIZE message to get new client area */
2508 if( (pWinpos
->flags
& (SWP_FRAMECHANGED
| SWP_NOSIZE
)) != SWP_NOSIZE
)
2510 wvrFlags
= WINPOS_SendNCCalcSize( pWinpos
->hwnd
, TRUE
, pNewWindowRect
,
2511 &wndPtr
->rectWindow
, &wndPtr
->rectClient
,
2512 pWinpos
, pNewClientRect
);
2514 /* FIXME: WVR_ALIGNxxx */
2516 if( pNewClientRect
->left
!= wndPtr
->rectClient
.left
||
2517 pNewClientRect
->top
!= wndPtr
->rectClient
.top
)
2518 pWinpos
->flags
&= ~SWP_NOCLIENTMOVE
;
2520 if( (pNewClientRect
->right
- pNewClientRect
->left
!=
2521 wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
) ||
2522 (pNewClientRect
->bottom
- pNewClientRect
->top
!=
2523 wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
) )
2524 pWinpos
->flags
&= ~SWP_NOCLIENTSIZE
;
2527 if( !(f
& SWP_NOMOVE
) && (pNewClientRect
->left
!= wndPtr
->rectClient
.left
||
2528 pNewClientRect
->top
!= wndPtr
->rectClient
.top
) )
2529 pWinpos
->flags
&= ~SWP_NOCLIENTMOVE
;
2533 /***********************************************************************
2534 * SetWindowPos (USER.2)
2536 BOOL16 WINAPI
SetWindowPos16( HWND16 hwnd
, HWND16 hwndInsertAfter
,
2537 INT16 x
, INT16 y
, INT16 cx
, INT16 cy
, WORD flags
)
2539 return SetWindowPos(hwnd
,(INT
)(INT16
)hwndInsertAfter
,x
,y
,cx
,cy
,flags
);
2542 /***********************************************************************
2543 * SetWindowPos (USER32.520)
2545 BOOL WINAPI
SetWindowPos( HWND hwnd
, HWND hwndInsertAfter
,
2546 INT x
, INT y
, INT cx
, INT cy
, UINT flags
)
2549 WND
* wndPtr
,*wndTemp
;
2550 RECT newWindowRect
, newClientRect
;
2551 RECT oldWindowRect
, oldClientRect
;
2553 UINT wvrFlags
= 0, uFlags
= 0;
2554 BOOL retvalue
, resync
= FALSE
, bChangePos
;
2555 HWND hwndActive
= 0;
2557 /* Get current active window from the active queue */
2560 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
2563 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
2564 QUEUE_Unlock( pActiveQueue
);
2568 TRACE("hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2569 hwnd
, x
, y
, x
+cx
, y
+cy
, flags
);
2571 bChangePos
= !(flags
& SWP_WINE_NOHOSTMOVE
);
2572 flags
&= ~SWP_WINE_NOHOSTMOVE
;
2575 /* ------------------------------------------------------------------------ CHECKS */
2577 /* Check window handle */
2579 if (hwnd
== GetDesktopWindow()) return FALSE
;
2580 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return FALSE
;
2582 TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr
->rectWindow
.left
, wndPtr
->rectWindow
.top
,
2583 wndPtr
->rectWindow
.right
, wndPtr
->rectWindow
.bottom
, (unsigned)wndPtr
->dwStyle
);
2585 /* Fix redundant flags */
2587 if(wndPtr
->dwStyle
& WS_VISIBLE
)
2588 flags
&= ~SWP_SHOWWINDOW
;
2591 if (!(flags
& SWP_SHOWWINDOW
))
2592 flags
|= SWP_NOREDRAW
;
2593 flags
&= ~SWP_HIDEWINDOW
;
2596 if ( cx
< 0 ) cx
= 0; if( cy
< 0 ) cy
= 0;
2598 if ((wndPtr
->rectWindow
.right
- wndPtr
->rectWindow
.left
== cx
) &&
2599 (wndPtr
->rectWindow
.bottom
- wndPtr
->rectWindow
.top
== cy
))
2600 flags
|= SWP_NOSIZE
; /* Already the right size */
2602 if ((wndPtr
->rectWindow
.left
== x
) && (wndPtr
->rectWindow
.top
== y
))
2603 flags
|= SWP_NOMOVE
; /* Already the right position */
2605 if (hwnd
== hwndActive
)
2606 flags
|= SWP_NOACTIVATE
; /* Already active */
2607 else if ( (wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)
2609 if(!(flags
& SWP_NOACTIVATE
)) /* Bring to the top when activating */
2611 flags
&= ~SWP_NOZORDER
;
2612 hwndInsertAfter
= HWND_TOP
;
2617 /* Check hwndInsertAfter */
2619 /* FIXME: TOPMOST not supported yet */
2620 if ((hwndInsertAfter
== HWND_TOPMOST
) ||
2621 (hwndInsertAfter
== HWND_NOTOPMOST
)) hwndInsertAfter
= HWND_TOP
;
2623 /* hwndInsertAfter must be a sibling of the window */
2624 if ((hwndInsertAfter
!= HWND_TOP
) && (hwndInsertAfter
!= HWND_BOTTOM
))
2626 WND
* wnd
= WIN_FindWndPtr(hwndInsertAfter
);
2629 if( wnd
->parent
!= wndPtr
->parent
)
2632 WIN_ReleaseWndPtr(wnd
);
2635 /* don't need to change the Zorder of hwnd if it's already inserted
2636 * after hwndInsertAfter or when inserting hwnd after itself.
2638 if(( wnd
->next
== wndPtr
) || (hwnd
== hwndInsertAfter
)) flags
|= SWP_NOZORDER
;
2640 WIN_ReleaseWndPtr(wnd
);
2643 Pos
: /* ------------------------------------------------------------------------ MAIN part */
2645 /* Fill the WINDOWPOS structure */
2648 winpos
.hwndInsertAfter
= hwndInsertAfter
;
2653 winpos
.flags
= flags
;
2655 SWP_DoWinPosChanging( wndPtr
, &winpos
, &newWindowRect
, &newClientRect
);
2657 if((winpos
.flags
& (SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) != SWP_NOZORDER
)
2659 if( wndPtr
->parent
== WIN_GetDesktop() )
2660 hwndInsertAfter
= SWP_DoOwnedPopups( wndPtr
->parent
, wndPtr
,
2661 hwndInsertAfter
, winpos
.flags
);
2662 WIN_ReleaseDesktop();
2665 if(!(wndPtr
->flags
& WIN_NATIVE
) )
2667 if( hwndInsertAfter
== HWND_TOP
)
2668 winpos
.flags
|= ( wndPtr
->parent
->child
== wndPtr
)? SWP_NOZORDER
: 0;
2670 if( hwndInsertAfter
== HWND_BOTTOM
)
2671 winpos
.flags
|= ( wndPtr
->next
)? 0: SWP_NOZORDER
;
2673 if( !(winpos
.flags
& SWP_NOZORDER
) )
2674 if( GetWindow(hwndInsertAfter
, GW_HWNDNEXT
) == wndPtr
->hwndSelf
)
2675 winpos
.flags
|= SWP_NOZORDER
;
2677 if( !(winpos
.flags
& (SWP_NOREDRAW
| SWP_SHOWWINDOW
)) &&
2678 ((winpos
.flags
& (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_FRAMECHANGED
))
2679 != (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
)) )
2681 /* get a previous visible region for SWP_CopyValidBits() */
2682 DWORD dflags
= DCX_WINDOW
;
2684 if (wndPtr
->dwStyle
& WS_CLIPSIBLINGS
)
2685 dflags
|= DCX_CLIPSIBLINGS
;
2687 visRgn
= DCE_GetVisRgn(hwnd
, dflags
, 0, 0);
2691 /* Common operations */
2693 wvrFlags
= SWP_DoNCCalcSize( wndPtr
, &winpos
, &newWindowRect
, &newClientRect
, flags
);
2695 if(!(winpos
.flags
& SWP_NOZORDER
) && winpos
.hwnd
!= hwndInsertAfter
)
2697 if ( WIN_UnlinkWindow( winpos
.hwnd
) )
2698 WIN_LinkWindow( winpos
.hwnd
, hwndInsertAfter
);
2701 /* Reset active DCEs */
2703 if( (((winpos
.flags
& SWP_AGG_NOPOSCHANGE
) != SWP_AGG_NOPOSCHANGE
) &&
2704 wndPtr
->dwStyle
& WS_VISIBLE
) ||
2705 (flags
& (SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) )
2709 UnionRect(&rect
, &newWindowRect
, &wndPtr
->rectWindow
);
2710 DCE_InvalidateDCE(wndPtr
, &rect
);
2713 oldWindowRect
= wndPtr
->rectWindow
;
2714 oldClientRect
= wndPtr
->rectClient
;
2716 /* Find out if we have to redraw the whole client rect */
2718 if( oldClientRect
.bottom
- oldClientRect
.top
==
2719 newClientRect
.bottom
- newClientRect
.top
) wvrFlags
&= ~WVR_VREDRAW
;
2721 if( oldClientRect
.right
- oldClientRect
.left
==
2722 newClientRect
.right
- newClientRect
.left
) wvrFlags
&= ~WVR_HREDRAW
;
2724 if( (winpos
.flags
& SWP_NOCOPYBITS
) || (!(winpos
.flags
& SWP_NOCLIENTSIZE
) &&
2725 (wvrFlags
>= WVR_HREDRAW
) && (wvrFlags
< WVR_VALIDRECTS
)) )
2727 uFlags
|= SWP_EX_NOCOPY
;
2730 * Use this later in CopyValidBits()
2733 uFlags |= SWP_EX_NONCLIENT;
2736 /* FIXME: actually do something with WVR_VALIDRECTS */
2738 wndPtr
->rectWindow
= newWindowRect
;
2739 wndPtr
->rectClient
= newClientRect
;
2741 if (wndPtr
->flags
& WIN_NATIVE
) /* -------------------------------------------- hosted window */
2743 BOOL bCallDriver
= TRUE
;
2744 HWND tempInsertAfter
= winpos
.hwndInsertAfter
;
2746 winpos
.hwndInsertAfter
= hwndInsertAfter
;
2748 if( !(winpos
.flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
| SWP_NOREDRAW
)) )
2750 /* This is the only place where we need to force repainting of the contents
2751 of windows created by the host window system, all other cases go through the
2752 expose event handling */
2754 if( (winpos
.flags
& (SWP_NOSIZE
| SWP_FRAMECHANGED
)) == (SWP_NOSIZE
| SWP_FRAMECHANGED
) )
2756 cx
= newWindowRect
.right
- newWindowRect
.left
;
2757 cy
= newWindowRect
.bottom
- newWindowRect
.top
;
2759 wndPtr
->pDriver
->pSetWindowPos(wndPtr
, &winpos
, bChangePos
);
2760 winpos
.hwndInsertAfter
= tempInsertAfter
;
2761 bCallDriver
= FALSE
;
2763 if( winpos
.flags
& SWP_NOCLIENTMOVE
)
2764 SWP_DoSimpleFrameChanged(wndPtr
, &oldClientRect
, winpos
.flags
, uFlags
);
2767 /* client area moved but window extents remained the same, copy valid bits */
2769 visRgn
= CreateRectRgn( 0, 0, cx
, cy
);
2770 uFlags
= SWP_CopyValidBits( wndPtr
, &visRgn
, &oldWindowRect
, &oldClientRect
,
2771 uFlags
| SWP_EX_PAINTSELF
);
2778 if( !(winpos
.flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
| SWP_NOREDRAW
)) )
2780 if( (oldClientRect
.left
- oldWindowRect
.left
== newClientRect
.left
- newWindowRect
.left
) &&
2781 (oldClientRect
.top
- oldWindowRect
.top
== newClientRect
.top
- newWindowRect
.top
) &&
2782 !(uFlags
& SWP_EX_NOCOPY
) )
2784 /* The origin of the client rect didn't move so we can try to repaint
2785 * only the nonclient area by setting bit gravity hint for the host window system.
2788 if( !(wndPtr
->dwExStyle
& WS_EX_MANAGED
) )
2790 HRGN hrgn
= CreateRectRgn( 0, 0, newWindowRect
.right
- newWindowRect
.left
,
2791 newWindowRect
.bottom
- newWindowRect
.top
);
2792 RECT rcn
= newClientRect
;
2793 RECT rco
= oldClientRect
;
2795 OffsetRect( &rcn
, -newWindowRect
.left
, -newWindowRect
.top
);
2796 OffsetRect( &rco
, -oldWindowRect
.left
, -oldWindowRect
.top
);
2797 IntersectRect( &rcn
, &rcn
, &rco
);
2798 visRgn
= CreateRectRgnIndirect( &rcn
);
2799 CombineRgn( visRgn
, hrgn
, visRgn
, RGN_DIFF
);
2800 DeleteObject( hrgn
);
2801 uFlags
= SWP_EX_PAINTSELF
;
2803 wndPtr
->pDriver
->pSetHostAttr(wndPtr
, HAK_BITGRAVITY
, BGNorthWest
);
2806 wndPtr
->pDriver
->pSetHostAttr(wndPtr
, HAK_BITGRAVITY
, BGForget
);
2809 wndPtr
->pDriver
->pSetWindowPos(wndPtr
, &winpos
, bChangePos
);
2810 winpos
.hwndInsertAfter
= tempInsertAfter
;
2813 if( winpos
.flags
& SWP_SHOWWINDOW
)
2817 wndPtr
->dwStyle
|= WS_VISIBLE
;
2819 if (wndPtr
->dwExStyle
& WS_EX_MANAGED
) resync
= TRUE
;
2821 /* focus was set to unmapped window, reset host focus
2822 * since the window is now visible */
2824 focus
= curr
= GetFocus();
2829 WND
*pFocus
= WIN_FindWndPtr( focus
);
2831 pFocus
->pDriver
->pSetFocus(pFocus
);
2832 WIN_ReleaseWndPtr(pFocus
);
2835 curr
= GetParent(curr
);
2839 else /* -------------------------------------------- emulated window */
2841 if( winpos
.flags
& SWP_SHOWWINDOW
)
2843 wndPtr
->dwStyle
|= WS_VISIBLE
;
2844 uFlags
|= SWP_EX_PAINTSELF
;
2845 visRgn
= 1; /* redraw the whole window */
2847 else if( !(winpos
.flags
& SWP_NOREDRAW
) )
2849 if( winpos
.flags
& SWP_HIDEWINDOW
)
2851 if( visRgn
> 1 ) /* map to parent */
2852 OffsetRgn( visRgn
, oldWindowRect
.left
, oldWindowRect
.top
);
2858 if( (winpos
.flags
& SWP_AGG_NOPOSCHANGE
) != SWP_AGG_NOPOSCHANGE
)
2860 /* if window was not resized and not moved try to repaint itself */
2861 if((winpos
.flags
& SWP_AGG_NOGEOMETRYCHANGE
) == SWP_AGG_NOGEOMETRYCHANGE
)
2862 uFlags
|= SWP_EX_PAINTSELF
;
2863 uFlags
= SWP_CopyValidBits(wndPtr
, &visRgn
, &oldWindowRect
,
2864 &oldClientRect
, uFlags
);
2868 /* nothing moved, redraw frame if needed */
2870 if( winpos
.flags
& SWP_FRAMECHANGED
)
2871 SWP_DoSimpleFrameChanged( wndPtr
, &oldClientRect
, winpos
.flags
, uFlags
);
2874 DeleteObject( visRgn
);
2882 if( winpos
.flags
& SWP_HIDEWINDOW
)
2884 wndPtr
->dwStyle
&= ~WS_VISIBLE
;
2887 if (hwnd
== CARET_GetHwnd())
2889 if( winpos
.flags
& SWP_HIDEWINDOW
)
2891 else if (winpos
.flags
& SWP_SHOWWINDOW
)
2895 /* ------------------------------------------------------------------------ FINAL */
2897 if (wndPtr
->flags
& WIN_NATIVE
)
2898 EVENT_Synchronize(); /* Synchronize with the host window system */
2900 if (!GetCapture() && ((wndPtr
->dwStyle
& WS_VISIBLE
) || (flags
& SWP_HIDEWINDOW
)))
2902 /* Simulate a mouse event to set the cursor */
2903 int iWndsLocks
= WIN_SuspendWndsLock();
2905 hardware_event( WM_MOUSEMOVE
, GET_KEYSTATE(), 0,
2906 PosX
, PosY
, GetTickCount(), 0 );
2908 WIN_RestoreWndsLock(iWndsLocks
);
2911 wndTemp
= WIN_GetDesktop();
2913 /* repaint invalidated region (if any)
2915 * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2916 * and force update after ChangeActiveWindow() to avoid painting frames twice.
2921 if( !(winpos
.flags
& SWP_NOREDRAW
) )
2924 /* Use PAINT_RedrawWindow to explicitly force an invalidation of the window,
2925 its parent and sibling and so on, and then erase the parent window
2926 back ground if the parent is either a top-level window or its parent's parent
2927 is top-level window. Rely on the system to repaint other affected
2928 windows later on. */
2929 if( uFlags
& SWP_EX_PAINTSELF
)
2931 PAINT_RedrawWindow( wndPtr
->hwndSelf
, NULL
, (visRgn
== 1) ? 0 : visRgn
,
2932 RDW_ERASE
| RDW_FRAME
| RDW_INVALIDATE
| RDW_ALLCHILDREN
,
2933 RDW_EX_XYWINDOW
| RDW_EX_USEHRGN
);
2937 PAINT_RedrawWindow( wndPtr
->parent
->hwndSelf
, NULL
, (visRgn
== 1) ? 0 : visRgn
,
2938 RDW_ERASE
| RDW_INVALIDATE
| RDW_ALLCHILDREN
,
2942 if(wndPtr
-> parent
== wndTemp
|| wndPtr
->parent
->parent
== wndTemp
)
2944 PAINT_RedrawWindow( wndPtr
->parent
->hwndSelf
, NULL
, 0,
2945 RDW_ERASENOW
| RDW_NOCHILDREN
, 0 );
2949 DeleteObject( visRgn
);
2952 WIN_ReleaseDesktop();
2954 if (!(flags
& SWP_NOACTIVATE
))
2955 WINPOS_ChangeActiveWindow( winpos
.hwnd
, FALSE
);
2957 /* And last, send the WM_WINDOWPOSCHANGED message */
2959 TRACE("\tstatus flags = %04x\n", winpos
.flags
& SWP_AGG_STATUSFLAGS
);
2962 (((winpos
.flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOPOSCHANGE
) &&
2963 !(winpos
.flags
& SWP_NOSENDCHANGING
)) )
2965 SendMessageA( winpos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
)&winpos
);
2966 if (resync
) EVENT_Synchronize();
2971 WIN_ReleaseWndPtr(wndPtr
);
2976 /***********************************************************************
2977 * BeginDeferWindowPos16 (USER.259)
2979 HDWP16 WINAPI
BeginDeferWindowPos16( INT16 count
)
2981 return BeginDeferWindowPos( count
);
2985 /***********************************************************************
2986 * BeginDeferWindowPos (USER32.9)
2988 HDWP WINAPI
BeginDeferWindowPos( INT count
)
2995 SetLastError(ERROR_INVALID_PARAMETER
);
2998 /* Windows allows zero count, in which case it allocates context for 8 moves */
2999 if (count
== 0) count
= 8;
3001 handle
= USER_HEAP_ALLOC( sizeof(DWP
) + (count
-1)*sizeof(WINDOWPOS
) );
3002 if (!handle
) return 0;
3003 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( handle
);
3004 pDWP
->actualCount
= 0;
3005 pDWP
->suggestedCount
= count
;
3007 pDWP
->wMagic
= DWP_MAGIC
;
3008 pDWP
->hwndParent
= 0;
3013 /***********************************************************************
3014 * DeferWindowPos16 (USER.260)
3016 HDWP16 WINAPI
DeferWindowPos16( HDWP16 hdwp
, HWND16 hwnd
, HWND16 hwndAfter
,
3017 INT16 x
, INT16 y
, INT16 cx
, INT16 cy
,
3020 return DeferWindowPos( hdwp
, hwnd
, (INT
)(INT16
)hwndAfter
,
3021 x
, y
, cx
, cy
, flags
);
3025 /***********************************************************************
3026 * DeferWindowPos (USER32.128)
3028 HDWP WINAPI
DeferWindowPos( HDWP hdwp
, HWND hwnd
, HWND hwndAfter
,
3029 INT x
, INT y
, INT cx
, INT cy
,
3034 HDWP newhdwp
= hdwp
,retvalue
;
3038 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
3039 if (!pDWP
) return 0;
3040 if (hwnd
== GetDesktopWindow()) return 0;
3042 if (!(pWnd
=WIN_FindWndPtr( hwnd
))) {
3043 USER_HEAP_FREE( hdwp
);
3047 /* Numega Bounds Checker Demo dislikes the following code.
3048 In fact, I've not been able to find any "same parent" requirement in any docu
3052 /* All the windows of a DeferWindowPos() must have the same parent */
3053 parent
= pWnd
->parent
->hwndSelf
;
3054 if (pDWP
->actualCount
== 0) pDWP
->hwndParent
= parent
;
3055 else if (parent
!= pDWP
->hwndParent
)
3057 USER_HEAP_FREE( hdwp
);
3063 for (i
= 0; i
< pDWP
->actualCount
; i
++)
3065 if (pDWP
->winPos
[i
].hwnd
== hwnd
)
3067 /* Merge with the other changes */
3068 if (!(flags
& SWP_NOZORDER
))
3070 pDWP
->winPos
[i
].hwndInsertAfter
= hwndAfter
;
3072 if (!(flags
& SWP_NOMOVE
))
3074 pDWP
->winPos
[i
].x
= x
;
3075 pDWP
->winPos
[i
].y
= y
;
3077 if (!(flags
& SWP_NOSIZE
))
3079 pDWP
->winPos
[i
].cx
= cx
;
3080 pDWP
->winPos
[i
].cy
= cy
;
3082 pDWP
->winPos
[i
].flags
&= flags
| ~(SWP_NOSIZE
| SWP_NOMOVE
|
3083 SWP_NOZORDER
| SWP_NOREDRAW
|
3084 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
3086 pDWP
->winPos
[i
].flags
|= flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
|
3092 if (pDWP
->actualCount
>= pDWP
->suggestedCount
)
3094 newhdwp
= USER_HEAP_REALLOC( hdwp
,
3095 sizeof(DWP
) + pDWP
->suggestedCount
*sizeof(WINDOWPOS
) );
3101 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( newhdwp
);
3102 pDWP
->suggestedCount
++;
3104 pDWP
->winPos
[pDWP
->actualCount
].hwnd
= hwnd
;
3105 pDWP
->winPos
[pDWP
->actualCount
].hwndInsertAfter
= hwndAfter
;
3106 pDWP
->winPos
[pDWP
->actualCount
].x
= x
;
3107 pDWP
->winPos
[pDWP
->actualCount
].y
= y
;
3108 pDWP
->winPos
[pDWP
->actualCount
].cx
= cx
;
3109 pDWP
->winPos
[pDWP
->actualCount
].cy
= cy
;
3110 pDWP
->winPos
[pDWP
->actualCount
].flags
= flags
;
3111 pDWP
->actualCount
++;
3114 WIN_ReleaseWndPtr(pWnd
);
3119 /***********************************************************************
3120 * EndDeferWindowPos16 (USER.261)
3122 BOOL16 WINAPI
EndDeferWindowPos16( HDWP16 hdwp
)
3124 return EndDeferWindowPos( hdwp
);
3128 /***********************************************************************
3129 * EndDeferWindowPos (USER32.173)
3131 BOOL WINAPI
EndDeferWindowPos( HDWP hdwp
)
3138 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
3139 if (!pDWP
) return FALSE
;
3140 for (i
= 0, winpos
= pDWP
->winPos
; i
< pDWP
->actualCount
; i
++, winpos
++)
3142 if (!(res
= SetWindowPos( winpos
->hwnd
, winpos
->hwndInsertAfter
,
3143 winpos
->x
, winpos
->y
, winpos
->cx
,
3144 winpos
->cy
, winpos
->flags
))) break;
3146 USER_HEAP_FREE( hdwp
);
3151 /***********************************************************************
3152 * TileChildWindows (USER.199)
3154 void WINAPI
TileChildWindows16( HWND16 parent
, WORD action
)
3156 FIXME("(%04x, %d): stub\n", parent
, action
);
3159 /***********************************************************************
3160 * CascadeChildWindows (USER.198)
3162 void WINAPI
CascadeChildWindows16( HWND16 parent
, WORD action
)
3164 FIXME("(%04x, %d): stub\n", parent
, action
);
3167 /***********************************************************************
3168 * SetProgmanWindow [USER32.522]
3170 HRESULT WINAPI
SetProgmanWindow ( HWND hwnd
)
3172 hGlobalProgmanWindow
= hwnd
;
3173 return hGlobalProgmanWindow
;
3176 /***********************************************************************
3177 * GetProgmanWindow [USER32.289]
3179 HRESULT WINAPI
GetProgmanWindow ( )
3181 return hGlobalProgmanWindow
;
3184 /***********************************************************************
3185 * SetShellWindowEx [USER32.531]
3186 * hwndProgman = Progman[Program Manager]
3187 * |-> SHELLDLL_DefView
3188 * hwndListView = | |-> SysListView32
3189 * | | |-> tooltips_class32
3195 HRESULT WINAPI
SetShellWindowEx ( HWND hwndProgman
, HWND hwndListView
)
3197 FIXME("0x%08x 0x%08x stub\n",hwndProgman
,hwndListView
);
3198 hGlobalShellWindow
= hwndProgman
;
3199 return hGlobalShellWindow
;
3203 /***********************************************************************
3204 * SetTaskmanWindow [USER32.537]
3206 * hwnd = MSTaskSwWClass
3207 * |-> SysTabControl32
3209 HRESULT WINAPI
SetTaskmanWindow ( HWND hwnd
)
3211 hGlobalTaskmanWindow
= hwnd
;
3212 return hGlobalTaskmanWindow
;
3215 /***********************************************************************
3216 * GetTaskmanWindow [USER32.304]
3218 HRESULT WINAPI
GetTaskmanWindow ( )
3220 return hGlobalTaskmanWindow
;