2 * Window position related functions.
4 * Copyright 1993, 1994, 1995 Alexandre Julliard
5 * 1995, 1996, 1999 Alex Korobka
9 #include "wine/winuser16.h"
10 #include "sysmetrics.h"
23 #include "nonclient.h"
28 DEFAULT_DEBUG_CHANNEL(win
)
30 #define HAS_DLGFRAME(style,exStyle) \
31 (((exStyle) & WS_EX_DLGMODALFRAME) || \
32 (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
34 #define HAS_THICKFRAME(style) \
35 (((style) & WS_THICKFRAME) && \
36 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
38 #define SWP_AGG_NOGEOMETRYCHANGE \
39 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
40 #define SWP_AGG_NOPOSCHANGE \
41 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
42 #define SWP_AGG_STATUSFLAGS \
43 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
45 #define EMPTYPOINT(pt) ((*(LONG*)&(pt)) == -1)
47 #define PLACE_MIN 0x0001
48 #define PLACE_MAX 0x0002
49 #define PLACE_RECT 0x0004
51 #define SWP_EX_NOCOPY 0x0001
52 #define SWP_EX_PAINTSELF 0x0002
53 #define SWP_EX_NONCLIENT 0x0004
55 #define MINMAX_NOSWP 0x00010000
57 /* ----- internal variables ----- */
59 static HWND hwndPrevActive
= 0; /* Previously active window */
60 static HWND hGlobalShellWindow
=0; /*the shell*/
61 static HWND hGlobalTaskmanWindow
=0;
62 static HWND hGlobalProgmanWindow
=0;
64 static LPCSTR atomInternalPos
;
66 extern HQUEUE16 hActiveQueue
;
68 /***********************************************************************
69 * WINPOS_CreateInternalPosAtom
71 BOOL
WINPOS_CreateInternalPosAtom()
74 atomInternalPos
= (LPCSTR
)(DWORD
)GlobalAddAtomA(str
);
75 return (atomInternalPos
) ? TRUE
: FALSE
;
78 /***********************************************************************
79 * WINPOS_CheckInternalPos
81 * Called when a window is destroyed.
83 void WINPOS_CheckInternalPos( WND
* wndPtr
)
86 MESSAGEQUEUE
*pMsgQ
= 0;
87 HWND hwnd
= wndPtr
->hwndSelf
;
89 lpPos
= (LPINTERNALPOS
) GetPropA( hwnd
, atomInternalPos
);
91 /* Retrieve the message queue associated with this window */
92 pMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( wndPtr
->hmemTaskQ
);
95 WARN( win
, "\tMessage queue not found. Exiting!\n" );
99 if( hwnd
== hwndPrevActive
) hwndPrevActive
= 0;
101 if( hwnd
== PERQDATA_GetActiveWnd( pMsgQ
->pQData
) )
103 PERQDATA_SetActiveWnd( pMsgQ
->pQData
, 0 );
104 WARN(win
, "\tattempt to activate destroyed window!\n");
109 if( IsWindow(lpPos
->hwndIconTitle
) )
110 DestroyWindow( lpPos
->hwndIconTitle
);
111 HeapFree( SystemHeap
, 0, lpPos
);
114 QUEUE_Unlock( pMsgQ
);
118 /***********************************************************************
121 * Find a suitable place for an iconic window.
123 static POINT16
WINPOS_FindIconPos( WND
* wndPtr
, POINT16 pt
)
126 short x
, y
, xspacing
, yspacing
;
128 GetClientRect16( wndPtr
->parent
->hwndSelf
, &rectParent
);
129 if ((pt
.x
>= rectParent
.left
) && (pt
.x
+ SYSMETRICS_CXICON
< rectParent
.right
) &&
130 (pt
.y
>= rectParent
.top
) && (pt
.y
+ SYSMETRICS_CYICON
< rectParent
.bottom
))
131 return pt
; /* The icon already has a suitable position */
133 xspacing
= SYSMETRICS_CXICONSPACING
;
134 yspacing
= SYSMETRICS_CYICONSPACING
;
136 y
= rectParent
.bottom
;
139 for (x
= rectParent
.left
; x
<= rectParent
.right
-xspacing
; x
+= xspacing
)
141 /* Check if another icon already occupies this spot */
142 WND
*childPtr
= WIN_LockWndPtr(wndPtr
->parent
->child
);
145 if ((childPtr
->dwStyle
& WS_MINIMIZE
) && (childPtr
!= wndPtr
))
147 if ((childPtr
->rectWindow
.left
< x
+ xspacing
) &&
148 (childPtr
->rectWindow
.right
>= x
) &&
149 (childPtr
->rectWindow
.top
<= y
) &&
150 (childPtr
->rectWindow
.bottom
> y
- yspacing
))
151 break; /* There's a window in there */
153 WIN_UpdateWndPtr(&childPtr
,childPtr
->next
);
155 WIN_ReleaseWndPtr(childPtr
);
156 if (!childPtr
) /* No window was found, so it's OK for us */
158 pt
.x
= x
+ (xspacing
- SYSMETRICS_CXICON
) / 2;
159 pt
.y
= y
- (yspacing
+ SYSMETRICS_CYICON
) / 2;
168 /***********************************************************************
169 * ArrangeIconicWindows16 (USER.170)
171 UINT16 WINAPI
ArrangeIconicWindows16( HWND16 parent
)
173 return ArrangeIconicWindows(parent
);
175 /***********************************************************************
176 * ArrangeIconicWindows (USER32.7)
178 UINT WINAPI
ArrangeIconicWindows( HWND parent
)
182 INT x
, y
, xspacing
, yspacing
;
184 GetClientRect( parent
, &rectParent
);
186 y
= rectParent
.bottom
;
187 xspacing
= SYSMETRICS_CXICONSPACING
;
188 yspacing
= SYSMETRICS_CYICONSPACING
;
190 hwndChild
= GetWindow( parent
, GW_CHILD
);
193 if( IsIconic( hwndChild
) )
195 WND
*wndPtr
= WIN_FindWndPtr(hwndChild
);
197 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
199 SetWindowPos( hwndChild
, 0, x
+ (xspacing
- SYSMETRICS_CXICON
) / 2,
200 y
- yspacing
- SYSMETRICS_CYICON
/2, 0, 0,
201 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
202 if( IsWindow(hwndChild
) )
203 WINPOS_ShowIconTitle(wndPtr
, TRUE
);
204 WIN_ReleaseWndPtr(wndPtr
);
206 if (x
<= rectParent
.right
- xspacing
) x
+= xspacing
;
213 hwndChild
= GetWindow( hwndChild
, GW_HWNDNEXT
);
219 /***********************************************************************
220 * SwitchToThisWindow16 (USER.172)
222 void WINAPI
SwitchToThisWindow16( HWND16 hwnd
, BOOL16 restore
)
224 SwitchToThisWindow( hwnd
, restore
);
228 /***********************************************************************
229 * SwitchToThisWindow (USER32.539)
231 void WINAPI
SwitchToThisWindow( HWND hwnd
, BOOL restore
)
233 ShowWindow( hwnd
, restore
? SW_RESTORE
: SW_SHOWMINIMIZED
);
237 /***********************************************************************
238 * GetWindowRect16 (USER.32)
240 void WINAPI
GetWindowRect16( HWND16 hwnd
, LPRECT16 rect
)
242 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
245 CONV_RECT32TO16( &wndPtr
->rectWindow
, rect
);
246 if (wndPtr
->dwStyle
& WS_CHILD
)
247 MapWindowPoints16( wndPtr
->parent
->hwndSelf
, 0, (POINT16
*)rect
, 2 );
248 WIN_ReleaseWndPtr(wndPtr
);
252 /***********************************************************************
253 * GetWindowRect (USER32.308)
255 BOOL WINAPI
GetWindowRect( HWND hwnd
, LPRECT rect
)
257 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
258 if (!wndPtr
) return FALSE
;
260 *rect
= wndPtr
->rectWindow
;
261 if (wndPtr
->dwStyle
& WS_CHILD
)
262 MapWindowPoints( wndPtr
->parent
->hwndSelf
, 0, (POINT
*)rect
, 2 );
263 WIN_ReleaseWndPtr(wndPtr
);
268 /***********************************************************************
271 BOOL WINAPI
GetWindowRgn ( HWND hwnd
, HRGN hrgn
)
275 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
276 if (!wndPtr
) return (ERROR
);
278 FIXME (win
, "GetWindowRgn: doesn't really do regions\n");
280 memset (&rect
, 0, sizeof(rect
));
282 GetWindowRect ( hwnd
, &rect
);
284 FIXME (win
, "Check whether a valid region here\n");
286 SetRectRgn ( hrgn
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
288 WIN_ReleaseWndPtr(wndPtr
);
289 return (SIMPLEREGION
);
292 /***********************************************************************
295 INT WINAPI
SetWindowRgn( HWND hwnd
, HRGN hrgn
,BOOL bRedraw
)
299 FIXME (win
, "SetWindowRgn: stub\n");
303 /***********************************************************************
306 INT16 WINAPI
SetWindowRgn16( HWND16 hwnd
, HRGN16 hrgn
,BOOL16 bRedraw
)
310 FIXME (win
, "SetWindowRgn16: stub\n");
315 /***********************************************************************
316 * GetClientRect16 (USER.33)
318 void WINAPI
GetClientRect16( HWND16 hwnd
, LPRECT16 rect
)
320 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
322 rect
->left
= rect
->top
= rect
->right
= rect
->bottom
= 0;
325 rect
->right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
326 rect
->bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
328 WIN_ReleaseWndPtr(wndPtr
);
332 /***********************************************************************
333 * GetClientRect (USER.220)
335 BOOL WINAPI
GetClientRect( HWND hwnd
, LPRECT rect
)
337 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
339 rect
->left
= rect
->top
= rect
->right
= rect
->bottom
= 0;
340 if (!wndPtr
) return FALSE
;
341 rect
->right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
342 rect
->bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
344 WIN_ReleaseWndPtr(wndPtr
);
349 /*******************************************************************
350 * ClientToScreen16 (USER.28)
352 void WINAPI
ClientToScreen16( HWND16 hwnd
, LPPOINT16 lppnt
)
354 MapWindowPoints16( hwnd
, 0, lppnt
, 1 );
358 /*******************************************************************
359 * ClientToScreen (USER32.52)
361 BOOL WINAPI
ClientToScreen( HWND hwnd
, LPPOINT lppnt
)
363 MapWindowPoints( hwnd
, 0, lppnt
, 1 );
368 /*******************************************************************
369 * ScreenToClient16 (USER.29)
371 void WINAPI
ScreenToClient16( HWND16 hwnd
, LPPOINT16 lppnt
)
373 MapWindowPoints16( 0, hwnd
, lppnt
, 1 );
377 /*******************************************************************
378 * ScreenToClient (USER32.447)
380 BOOL WINAPI
ScreenToClient( HWND hwnd
, LPPOINT lppnt
)
382 MapWindowPoints( 0, hwnd
, lppnt
, 1 );
387 /***********************************************************************
388 * WINPOS_WindowFromPoint
390 * Find the window and hittest for a given point.
392 INT16
WINPOS_WindowFromPoint( WND
* wndScope
, POINT16 pt
, WND
**ppWnd
)
395 INT16 hittest
= HTERROR
;
400 wndPtr
= WIN_LockWndPtr(wndScope
->child
);
402 if( wndScope
->flags
& WIN_MANAGED
)
404 /* In managed mode we have to check wndScope first as it is also
405 * a window which received the mouse event. */
407 if( wndScope
->dwStyle
& WS_DISABLED
)
412 if( pt
.x
< wndScope
->rectClient
.left
|| pt
.x
>= wndScope
->rectClient
.right
||
413 pt
.y
< wndScope
->rectClient
.top
|| pt
.y
>= wndScope
->rectClient
.bottom
)
416 MapWindowPoints16( GetDesktopWindow16(), wndScope
->hwndSelf
, &xy
, 1 );
422 /* If point is in window, and window is visible, and it */
423 /* is enabled (or it's a top-level window), then explore */
424 /* its children. Otherwise, go to the next window. */
426 if ((wndPtr
->dwStyle
& WS_VISIBLE
) &&
427 (!(wndPtr
->dwStyle
& WS_DISABLED
) ||
428 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)) &&
429 (xy
.x
>= wndPtr
->rectWindow
.left
) &&
430 (xy
.x
< wndPtr
->rectWindow
.right
) &&
431 (xy
.y
>= wndPtr
->rectWindow
.top
) &&
432 (xy
.y
< wndPtr
->rectWindow
.bottom
))
434 *ppWnd
= wndPtr
; /* Got a suitable window */
436 /* If window is minimized or disabled, return at once */
437 if (wndPtr
->dwStyle
& WS_MINIMIZE
)
439 retvalue
= HTCAPTION
;
442 if (wndPtr
->dwStyle
& WS_DISABLED
)
448 /* If point is not in client area, ignore the children */
449 if ((xy
.x
< wndPtr
->rectClient
.left
) ||
450 (xy
.x
>= wndPtr
->rectClient
.right
) ||
451 (xy
.y
< wndPtr
->rectClient
.top
) ||
452 (xy
.y
>= wndPtr
->rectClient
.bottom
)) break;
454 xy
.x
-= wndPtr
->rectClient
.left
;
455 xy
.y
-= wndPtr
->rectClient
.top
;
456 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->child
);
460 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->next
);
465 /* If nothing found, try the scope window */
466 if (!*ppWnd
) *ppWnd
= wndScope
;
468 /* Send the WM_NCHITTEST message (only if to the same task) */
469 if ((*ppWnd
)->hmemTaskQ
== GetFastQueue16())
471 hittest
= (INT16
)SendMessage16( (*ppWnd
)->hwndSelf
, WM_NCHITTEST
,
472 0, MAKELONG( pt
.x
, pt
.y
) );
473 if (hittest
!= HTTRANSPARENT
)
475 retvalue
= hittest
; /* Found the window */
485 /* If no children found in last search, make point relative to parent */
488 xy
.x
+= (*ppWnd
)->rectClient
.left
;
489 xy
.y
+= (*ppWnd
)->rectClient
.top
;
492 /* Restart the search from the next sibling */
493 WIN_UpdateWndPtr(&wndPtr
,(*ppWnd
)->next
);
494 *ppWnd
= (*ppWnd
)->parent
;
498 WIN_ReleaseWndPtr(wndPtr
);
503 /*******************************************************************
504 * WindowFromPoint16 (USER.30)
506 HWND16 WINAPI
WindowFromPoint16( POINT16 pt
)
509 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt
, &pWnd
);
510 WIN_ReleaseDesktop();
511 return pWnd
->hwndSelf
;
515 /*******************************************************************
516 * WindowFromPoint (USER32.582)
518 HWND WINAPI
WindowFromPoint( POINT pt
)
522 CONV_POINT32TO16( &pt
, &pt16
);
523 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16
, &pWnd
);
524 WIN_ReleaseDesktop();
525 return (HWND
)pWnd
->hwndSelf
;
529 /*******************************************************************
530 * ChildWindowFromPoint16 (USER.191)
532 HWND16 WINAPI
ChildWindowFromPoint16( HWND16 hwndParent
, POINT16 pt
)
535 CONV_POINT16TO32( &pt
, &pt32
);
536 return (HWND16
)ChildWindowFromPoint( hwndParent
, pt32
);
540 /*******************************************************************
541 * ChildWindowFromPoint (USER32.49)
543 HWND WINAPI
ChildWindowFromPoint( HWND hwndParent
, POINT pt
)
545 /* pt is in the client coordinates */
547 WND
* wnd
= WIN_FindWndPtr(hwndParent
);
553 /* get client rect fast */
554 rect
.top
= rect
.left
= 0;
555 rect
.right
= wnd
->rectClient
.right
- wnd
->rectClient
.left
;
556 rect
.bottom
= wnd
->rectClient
.bottom
- wnd
->rectClient
.top
;
558 if (!PtInRect( &rect
, pt
))
563 WIN_UpdateWndPtr(&wnd
,wnd
->child
);
566 if (PtInRect( &wnd
->rectWindow
, pt
))
568 retvalue
= wnd
->hwndSelf
;
571 WIN_UpdateWndPtr(&wnd
,wnd
->next
);
573 retvalue
= hwndParent
;
575 WIN_ReleaseWndPtr(wnd
);
579 /*******************************************************************
580 * ChildWindowFromPointEx16 (USER.50)
582 HWND16 WINAPI
ChildWindowFromPointEx16( HWND16 hwndParent
, POINT16 pt
, UINT16 uFlags
)
585 CONV_POINT16TO32( &pt
, &pt32
);
586 return (HWND16
)ChildWindowFromPointEx( hwndParent
, pt32
, uFlags
);
590 /*******************************************************************
591 * ChildWindowFromPointEx32 (USER32.50)
593 HWND WINAPI
ChildWindowFromPointEx( HWND hwndParent
, POINT pt
,
596 /* pt is in the client coordinates */
598 WND
* wnd
= WIN_FindWndPtr(hwndParent
);
604 /* get client rect fast */
605 rect
.top
= rect
.left
= 0;
606 rect
.right
= wnd
->rectClient
.right
- wnd
->rectClient
.left
;
607 rect
.bottom
= wnd
->rectClient
.bottom
- wnd
->rectClient
.top
;
609 if (!PtInRect( &rect
, pt
))
614 WIN_UpdateWndPtr(&wnd
,wnd
->child
);
618 if (PtInRect( &wnd
->rectWindow
, pt
)) {
619 if ( (uFlags
& CWP_SKIPINVISIBLE
) &&
620 !(wnd
->dwStyle
& WS_VISIBLE
) );
621 else if ( (uFlags
& CWP_SKIPDISABLED
) &&
622 (wnd
->dwStyle
& WS_DISABLED
) );
623 else if ( (uFlags
& CWP_SKIPTRANSPARENT
) &&
624 (wnd
->dwExStyle
& WS_EX_TRANSPARENT
) );
627 retvalue
= wnd
->hwndSelf
;
632 WIN_UpdateWndPtr(&wnd
,wnd
->next
);
634 retvalue
= hwndParent
;
636 WIN_ReleaseWndPtr(wnd
);
641 /*******************************************************************
642 * WINPOS_GetWinOffset
644 * Calculate the offset between the origin of the two windows. Used
645 * to implement MapWindowPoints.
647 static void WINPOS_GetWinOffset( HWND hwndFrom
, HWND hwndTo
,
652 offset
->x
= offset
->y
= 0;
653 if (hwndFrom
== hwndTo
) return;
655 /* Translate source window origin to screen coords */
658 if (!(wndPtr
= WIN_FindWndPtr( hwndFrom
)))
660 ERR(win
,"bad hwndFrom = %04x\n",hwndFrom
);
663 while (wndPtr
->parent
)
665 offset
->x
+= wndPtr
->rectClient
.left
;
666 offset
->y
+= wndPtr
->rectClient
.top
;
667 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->parent
);
669 WIN_ReleaseWndPtr(wndPtr
);
672 /* Translate origin to destination window coords */
675 if (!(wndPtr
= WIN_FindWndPtr( hwndTo
)))
677 ERR(win
,"bad hwndTo = %04x\n", hwndTo
);
680 while (wndPtr
->parent
)
682 offset
->x
-= wndPtr
->rectClient
.left
;
683 offset
->y
-= wndPtr
->rectClient
.top
;
684 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->parent
);
686 WIN_ReleaseWndPtr(wndPtr
);
691 /*******************************************************************
692 * MapWindowPoints16 (USER.258)
694 void WINAPI
MapWindowPoints16( HWND16 hwndFrom
, HWND16 hwndTo
,
695 LPPOINT16 lppt
, UINT16 count
)
699 WINPOS_GetWinOffset( hwndFrom
, hwndTo
, &offset
);
709 /*******************************************************************
710 * MapWindowPoints (USER32.386)
712 INT WINAPI
MapWindowPoints( HWND hwndFrom
, HWND hwndTo
,
713 LPPOINT lppt
, UINT count
)
717 WINPOS_GetWinOffset( hwndFrom
, hwndTo
, &offset
);
724 return MAKELONG( LOWORD(offset
.x
), LOWORD(offset
.y
) );
728 /***********************************************************************
729 * IsIconic16 (USER.31)
731 BOOL16 WINAPI
IsIconic16(HWND16 hWnd
)
733 return IsIconic(hWnd
);
737 /***********************************************************************
738 * IsIconic (USER32.345)
740 BOOL WINAPI
IsIconic(HWND hWnd
)
743 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
744 if (wndPtr
== NULL
) return FALSE
;
745 retvalue
= (wndPtr
->dwStyle
& WS_MINIMIZE
) != 0;
746 WIN_ReleaseWndPtr(wndPtr
);
751 /***********************************************************************
752 * IsZoomed (USER.272)
754 BOOL16 WINAPI
IsZoomed16(HWND16 hWnd
)
756 return IsZoomed(hWnd
);
760 /***********************************************************************
761 * IsZoomed (USER.352)
763 BOOL WINAPI
IsZoomed(HWND hWnd
)
766 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
767 if (wndPtr
== NULL
) return FALSE
;
768 retvalue
= (wndPtr
->dwStyle
& WS_MAXIMIZE
) != 0;
769 WIN_ReleaseWndPtr(wndPtr
);
774 /*******************************************************************
775 * GetActiveWindow (USER.60)
777 HWND16 WINAPI
GetActiveWindow16(void)
779 return (HWND16
)GetActiveWindow();
782 /*******************************************************************
783 * GetActiveWindow (USER32.205)
785 HWND WINAPI
GetActiveWindow(void)
787 MESSAGEQUEUE
*pCurMsgQ
= 0;
790 /* Get the messageQ for the current thread */
791 if (!(pCurMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( GetFastQueue16() )))
793 WARN( win
, "\tCurrent message queue not found. Exiting!\n" );
797 /* Return the current active window from the perQ data of the current message Q */
798 hwndActive
= PERQDATA_GetActiveWnd( pCurMsgQ
->pQData
);
800 QUEUE_Unlock( pCurMsgQ
);
805 /*******************************************************************
808 static BOOL
WINPOS_CanActivate(WND
* pWnd
)
810 if( pWnd
&& ((pWnd
->dwStyle
& (WS_DISABLED
| WS_VISIBLE
| WS_CHILD
))
811 == WS_VISIBLE
) ) return TRUE
;
816 /*******************************************************************
817 * SetActiveWindow16 (USER.59)
819 HWND16 WINAPI
SetActiveWindow16( HWND16 hwnd
)
821 return SetActiveWindow(hwnd
);
825 /*******************************************************************
826 * SetActiveWindow (USER32.463)
828 HWND WINAPI
SetActiveWindow( HWND hwnd
)
831 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
832 MESSAGEQUEUE
*pMsgQ
= 0, *pCurMsgQ
= 0;
834 if ( !WINPOS_CanActivate(wndPtr
) )
840 /* Get the messageQ for the current thread */
841 if (!(pCurMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( GetFastQueue16() )))
843 WARN( win
, "\tCurrent message queue not found. Exiting!\n" );
847 /* Retrieve the message queue associated with this window */
848 pMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( wndPtr
->hmemTaskQ
);
851 WARN( win
, "\tWindow message queue not found. Exiting!\n" );
855 /* Make sure that the window is associated with the calling threads
856 * message queue. It must share the same perQ data.
859 if ( pCurMsgQ
->pQData
!= pMsgQ
->pQData
)
862 /* Save current active window */
863 prev
= PERQDATA_GetActiveWnd( pMsgQ
->pQData
);
865 WINPOS_SetActiveWindow( hwnd
, 0, 0 );
868 /* Unlock the queues before returning */
870 QUEUE_Unlock( pMsgQ
);
872 QUEUE_Unlock( pCurMsgQ
);
875 WIN_ReleaseWndPtr(wndPtr
);
880 /*******************************************************************
881 * GetForegroundWindow16 (USER.608)
883 HWND16 WINAPI
GetForegroundWindow16(void)
885 return (HWND16
)GetForegroundWindow();
889 /*******************************************************************
890 * SetForegroundWindow16 (USER.609)
892 BOOL16 WINAPI
SetForegroundWindow16( HWND16 hwnd
)
894 return SetForegroundWindow( hwnd
);
898 /*******************************************************************
899 * GetForegroundWindow (USER32.241)
901 HWND WINAPI
GetForegroundWindow(void)
903 return GetActiveWindow();
907 /*******************************************************************
908 * SetForegroundWindow (USER32.482)
910 BOOL WINAPI
SetForegroundWindow( HWND hwnd
)
912 SetActiveWindow( hwnd
);
917 /*******************************************************************
918 * GetShellWindow16 (USER.600)
920 HWND16 WINAPI
GetShellWindow16(void)
922 return GetShellWindow();
925 /*******************************************************************
926 * SetShellWindow (USER32.504)
928 HWND WINAPI
SetShellWindow(HWND hwndshell
)
929 { WARN(win
, "(hWnd=%08x) semi stub\n",hwndshell
);
931 hGlobalShellWindow
= hwndshell
;
932 return hGlobalShellWindow
;
936 /*******************************************************************
937 * GetShellWindow (USER32.287)
939 HWND WINAPI
GetShellWindow(void)
940 { WARN(win
, "(hWnd=%x) semi stub\n",hGlobalShellWindow
);
942 return hGlobalShellWindow
;
946 /***********************************************************************
947 * BringWindowToTop16 (USER.45)
949 BOOL16 WINAPI
BringWindowToTop16( HWND16 hwnd
)
951 return BringWindowToTop(hwnd
);
955 /***********************************************************************
956 * BringWindowToTop (USER32.11)
958 BOOL WINAPI
BringWindowToTop( HWND hwnd
)
960 return SetWindowPos( hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
);
964 /***********************************************************************
965 * MoveWindow16 (USER.56)
967 BOOL16 WINAPI
MoveWindow16( HWND16 hwnd
, INT16 x
, INT16 y
, INT16 cx
, INT16 cy
,
970 return MoveWindow(hwnd
,x
,y
,cx
,cy
,repaint
);
974 /***********************************************************************
975 * MoveWindow (USER32.399)
977 BOOL WINAPI
MoveWindow( HWND hwnd
, INT x
, INT y
, INT cx
, INT cy
,
980 int flags
= SWP_NOZORDER
| SWP_NOACTIVATE
;
981 if (!repaint
) flags
|= SWP_NOREDRAW
;
982 TRACE(win
, "%04x %d,%d %dx%d %d\n",
983 hwnd
, x
, y
, cx
, cy
, repaint
);
984 return SetWindowPos( hwnd
, 0, x
, y
, cx
, cy
, flags
);
987 /***********************************************************************
988 * WINPOS_InitInternalPos
990 static LPINTERNALPOS
WINPOS_InitInternalPos( WND
* wnd
, POINT pt
,
993 LPINTERNALPOS lpPos
= (LPINTERNALPOS
) GetPropA( wnd
->hwndSelf
,
997 /* this happens when the window is minimized/maximized
998 * for the first time (rectWindow is not adjusted yet) */
1000 lpPos
= HeapAlloc( SystemHeap
, 0, sizeof(INTERNALPOS
) );
1001 if( !lpPos
) return NULL
;
1003 SetPropA( wnd
->hwndSelf
, atomInternalPos
, (HANDLE
)lpPos
);
1004 lpPos
->hwndIconTitle
= 0; /* defer until needs to be shown */
1005 CONV_RECT32TO16( &wnd
->rectWindow
, &lpPos
->rectNormal
);
1006 *(UINT
*)&lpPos
->ptIconPos
= *(UINT
*)&lpPos
->ptMaxPos
= 0xFFFFFFFF;
1009 if( wnd
->dwStyle
& WS_MINIMIZE
)
1010 CONV_POINT32TO16( &pt
, &lpPos
->ptIconPos
);
1011 else if( wnd
->dwStyle
& WS_MAXIMIZE
)
1012 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1013 else if( restoreRect
)
1014 CONV_RECT32TO16( restoreRect
, &lpPos
->rectNormal
);
1019 /***********************************************************************
1020 * WINPOS_RedrawIconTitle
1022 BOOL
WINPOS_RedrawIconTitle( HWND hWnd
)
1024 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)GetPropA( hWnd
, atomInternalPos
);
1027 if( lpPos
->hwndIconTitle
)
1029 SendMessageA( lpPos
->hwndIconTitle
, WM_SHOWWINDOW
, TRUE
, 0);
1030 InvalidateRect( lpPos
->hwndIconTitle
, NULL
, TRUE
);
1037 /***********************************************************************
1038 * WINPOS_ShowIconTitle
1040 BOOL
WINPOS_ShowIconTitle( WND
* pWnd
, BOOL bShow
)
1042 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)GetPropA( pWnd
->hwndSelf
, atomInternalPos
);
1044 if( lpPos
&& !(pWnd
->flags
& WIN_MANAGED
))
1046 HWND16 hWnd
= lpPos
->hwndIconTitle
;
1048 TRACE(win
,"0x%04x %i\n", pWnd
->hwndSelf
, (bShow
!= 0) );
1051 lpPos
->hwndIconTitle
= hWnd
= ICONTITLE_Create( pWnd
);
1054 pWnd
= WIN_FindWndPtr(hWnd
);
1056 if( !(pWnd
->dwStyle
& WS_VISIBLE
) )
1058 SendMessageA( hWnd
, WM_SHOWWINDOW
, TRUE
, 0 );
1059 SetWindowPos( hWnd
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
1060 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_SHOWWINDOW
);
1062 WIN_ReleaseWndPtr(pWnd
);
1064 else ShowWindow( hWnd
, SW_HIDE
);
1069 /*******************************************************************
1070 * WINPOS_GetMinMaxInfo
1072 * Get the minimized and maximized information for a window.
1074 void WINPOS_GetMinMaxInfo( WND
*wndPtr
, POINT
*maxSize
, POINT
*maxPos
,
1075 POINT
*minTrack
, POINT
*maxTrack
)
1077 LPINTERNALPOS lpPos
;
1081 /* Compute default values */
1083 MinMax
.ptMaxSize
.x
= SYSMETRICS_CXSCREEN
;
1084 MinMax
.ptMaxSize
.y
= SYSMETRICS_CYSCREEN
;
1085 MinMax
.ptMinTrackSize
.x
= SYSMETRICS_CXMINTRACK
;
1086 MinMax
.ptMinTrackSize
.y
= SYSMETRICS_CYMINTRACK
;
1087 MinMax
.ptMaxTrackSize
.x
= SYSMETRICS_CXSCREEN
;
1088 MinMax
.ptMaxTrackSize
.y
= SYSMETRICS_CYSCREEN
;
1090 if (wndPtr
->flags
& WIN_MANAGED
) xinc
= yinc
= 0;
1091 else if (HAS_DLGFRAME( wndPtr
->dwStyle
, wndPtr
->dwExStyle
))
1093 xinc
= SYSMETRICS_CXDLGFRAME
;
1094 yinc
= SYSMETRICS_CYDLGFRAME
;
1099 if (HAS_THICKFRAME(wndPtr
->dwStyle
))
1101 xinc
+= SYSMETRICS_CXFRAME
;
1102 yinc
+= SYSMETRICS_CYFRAME
;
1104 if (wndPtr
->dwStyle
& WS_BORDER
)
1106 xinc
+= SYSMETRICS_CXBORDER
;
1107 yinc
+= SYSMETRICS_CYBORDER
;
1110 MinMax
.ptMaxSize
.x
+= 2 * xinc
;
1111 MinMax
.ptMaxSize
.y
+= 2 * yinc
;
1113 lpPos
= (LPINTERNALPOS
)GetPropA( wndPtr
->hwndSelf
, atomInternalPos
);
1114 if( lpPos
&& !EMPTYPOINT(lpPos
->ptMaxPos
) )
1115 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &MinMax
.ptMaxPosition
);
1118 MinMax
.ptMaxPosition
.x
= -xinc
;
1119 MinMax
.ptMaxPosition
.y
= -yinc
;
1122 SendMessageA( wndPtr
->hwndSelf
, WM_GETMINMAXINFO
, 0, (LPARAM
)&MinMax
);
1124 /* Some sanity checks */
1126 TRACE(win
,"%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1127 MinMax
.ptMaxSize
.x
, MinMax
.ptMaxSize
.y
,
1128 MinMax
.ptMaxPosition
.x
, MinMax
.ptMaxPosition
.y
,
1129 MinMax
.ptMaxTrackSize
.x
, MinMax
.ptMaxTrackSize
.y
,
1130 MinMax
.ptMinTrackSize
.x
, MinMax
.ptMinTrackSize
.y
);
1131 MinMax
.ptMaxTrackSize
.x
= MAX( MinMax
.ptMaxTrackSize
.x
,
1132 MinMax
.ptMinTrackSize
.x
);
1133 MinMax
.ptMaxTrackSize
.y
= MAX( MinMax
.ptMaxTrackSize
.y
,
1134 MinMax
.ptMinTrackSize
.y
);
1136 if (maxSize
) *maxSize
= MinMax
.ptMaxSize
;
1137 if (maxPos
) *maxPos
= MinMax
.ptMaxPosition
;
1138 if (minTrack
) *minTrack
= MinMax
.ptMinTrackSize
;
1139 if (maxTrack
) *maxTrack
= MinMax
.ptMaxTrackSize
;
1142 /***********************************************************************
1143 * WINPOS_MinMaximize
1145 * Fill in lpRect and return additional flags to be used with SetWindowPos().
1146 * This function assumes that 'cmd' is different from the current window
1149 UINT
WINPOS_MinMaximize( WND
* wndPtr
, UINT16 cmd
, LPRECT16 lpRect
)
1153 LPINTERNALPOS lpPos
;
1155 TRACE(win
,"0x%04x %u\n", wndPtr
->hwndSelf
, cmd
);
1157 size
.x
= wndPtr
->rectWindow
.left
; size
.y
= wndPtr
->rectWindow
.top
;
1158 lpPos
= WINPOS_InitInternalPos( wndPtr
, size
, &wndPtr
->rectWindow
);
1160 if (lpPos
&& !HOOK_CallHooks16(WH_CBT
, HCBT_MINMAX
, wndPtr
->hwndSelf
, cmd
))
1162 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1164 if( !SendMessageA( wndPtr
->hwndSelf
, WM_QUERYOPEN
, 0, 0L ) )
1165 return (SWP_NOSIZE
| SWP_NOMOVE
);
1166 swpFlags
|= SWP_NOCOPYBITS
;
1171 if( wndPtr
->dwStyle
& WS_MAXIMIZE
)
1173 wndPtr
->flags
|= WIN_RESTORE_MAX
;
1174 wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
1177 wndPtr
->flags
&= ~WIN_RESTORE_MAX
;
1178 wndPtr
->dwStyle
|= WS_MINIMIZE
;
1180 if( wndPtr
->flags
& WIN_NATIVE
)
1181 if( wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, TRUE
) )
1182 swpFlags
|= MINMAX_NOSWP
;
1184 lpPos
->ptIconPos
= WINPOS_FindIconPos( wndPtr
, lpPos
->ptIconPos
);
1186 SetRect16( lpRect
, lpPos
->ptIconPos
.x
, lpPos
->ptIconPos
.y
,
1187 SYSMETRICS_CXICON
, SYSMETRICS_CYICON
);
1188 swpFlags
|= SWP_NOCOPYBITS
;
1192 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &pt
);
1193 WINPOS_GetMinMaxInfo( wndPtr
, &size
, &pt
, NULL
, NULL
);
1194 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1196 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1198 if( wndPtr
->flags
& WIN_NATIVE
)
1199 if( wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, FALSE
) )
1200 swpFlags
|= MINMAX_NOSWP
;
1202 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
1203 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
1205 wndPtr
->dwStyle
|= WS_MAXIMIZE
;
1207 SetRect16( lpRect
, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
,
1212 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1214 if( wndPtr
->flags
& WIN_NATIVE
)
1215 if( wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, FALSE
) )
1216 swpFlags
|= MINMAX_NOSWP
;
1218 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
1219 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
1221 if( wndPtr
->flags
& WIN_RESTORE_MAX
)
1223 /* Restore to maximized position */
1224 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &pt
);
1225 WINPOS_GetMinMaxInfo( wndPtr
, &size
, &pt
, NULL
, NULL
);
1226 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1227 wndPtr
->dwStyle
|= WS_MAXIMIZE
;
1228 SetRect16( lpRect
, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
, size
.x
, size
.y
);
1233 if( !(wndPtr
->dwStyle
& WS_MAXIMIZE
) ) return (UINT16
)(-1);
1234 else wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
1236 /* Restore to normal position */
1238 *lpRect
= lpPos
->rectNormal
;
1239 lpRect
->right
-= lpRect
->left
;
1240 lpRect
->bottom
-= lpRect
->top
;
1244 } else swpFlags
|= SWP_NOSIZE
| SWP_NOMOVE
;
1248 /***********************************************************************
1249 * ShowWindowAsync (USER32.535)
1251 * doesn't wait; returns immediately.
1252 * used by threads to toggle windows in other (possibly hanging) threads
1254 BOOL WINAPI
ShowWindowAsync( HWND hwnd
, INT cmd
)
1256 /* FIXME: does ShowWindow() return immediately ? */
1257 return ShowWindow(hwnd
, cmd
);
1261 /***********************************************************************
1262 * ShowWindow16 (USER.42)
1264 BOOL16 WINAPI
ShowWindow16( HWND16 hwnd
, INT16 cmd
)
1266 return ShowWindow(hwnd
,cmd
);
1270 /***********************************************************************
1271 * ShowWindow (USER32.534)
1273 BOOL WINAPI
ShowWindow( HWND hwnd
, INT cmd
)
1275 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
1276 BOOL wasVisible
, showFlag
;
1277 RECT16 newPos
= {0, 0, 0, 0};
1280 if (!wndPtr
) return FALSE
;
1282 TRACE(win
,"hwnd=%04x, cmd=%d\n", hwnd
, cmd
);
1284 wasVisible
= (wndPtr
->dwStyle
& WS_VISIBLE
) != 0;
1289 if (!wasVisible
) goto END
;;
1290 swp
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
|
1291 SWP_NOACTIVATE
| SWP_NOZORDER
;
1292 if ((hwnd
== GetFocus()) || IsChild( hwnd
, GetFocus()))
1294 /* Revert focus to parent */
1295 SetFocus( GetParent(hwnd
) );
1299 case SW_SHOWMINNOACTIVE
:
1300 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1302 case SW_SHOWMINIMIZED
:
1303 swp
|= SWP_SHOWWINDOW
;
1306 swp
|= SWP_FRAMECHANGED
;
1307 if( !(wndPtr
->dwStyle
& WS_MINIMIZE
) )
1308 swp
|= WINPOS_MinMaximize( wndPtr
, SW_MINIMIZE
, &newPos
);
1309 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1312 case SW_SHOWMAXIMIZED
: /* same as SW_MAXIMIZE */
1313 swp
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
1314 if( !(wndPtr
->dwStyle
& WS_MAXIMIZE
) )
1315 swp
|= WINPOS_MinMaximize( wndPtr
, SW_MAXIMIZE
, &newPos
);
1316 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1320 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1323 swp
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
1326 case SW_SHOWNOACTIVATE
:
1327 swp
|= SWP_NOZORDER
;
1328 if (GetActiveWindow()) swp
|= SWP_NOACTIVATE
;
1330 case SW_SHOWNORMAL
: /* same as SW_NORMAL: */
1331 case SW_SHOWDEFAULT
: /* FIXME: should have its own handler */
1333 swp
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
1335 if( wndPtr
->dwStyle
& (WS_MINIMIZE
| WS_MAXIMIZE
) )
1336 swp
|= WINPOS_MinMaximize( wndPtr
, SW_RESTORE
, &newPos
);
1337 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1341 showFlag
= (cmd
!= SW_HIDE
);
1342 if (showFlag
!= wasVisible
)
1344 SendMessageA( hwnd
, WM_SHOWWINDOW
, showFlag
, 0 );
1345 if (!IsWindow( hwnd
)) goto END
;
1348 if ((wndPtr
->dwStyle
& WS_CHILD
) &&
1349 !IsWindowVisible( wndPtr
->parent
->hwndSelf
) &&
1350 (swp
& (SWP_NOSIZE
| SWP_NOMOVE
)) == (SWP_NOSIZE
| SWP_NOMOVE
) )
1352 /* Don't call SetWindowPos() on invisible child windows */
1353 if (cmd
== SW_HIDE
) wndPtr
->dwStyle
&= ~WS_VISIBLE
;
1354 else wndPtr
->dwStyle
|= WS_VISIBLE
;
1358 /* We can't activate a child window */
1359 if (wndPtr
->dwStyle
& WS_CHILD
) swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1360 if (!(swp
& MINMAX_NOSWP
))
1361 SetWindowPos( hwnd
, HWND_TOP
, newPos
.left
, newPos
.top
,
1362 newPos
.right
, newPos
.bottom
, LOWORD(swp
) );
1363 if (!IsWindow( hwnd
)) goto END
;
1364 else if( wndPtr
->dwStyle
& WS_MINIMIZE
) WINPOS_ShowIconTitle( wndPtr
, TRUE
);
1367 if (wndPtr
->flags
& WIN_NEED_SIZE
)
1369 /* should happen only in CreateWindowEx() */
1370 int wParam
= SIZE_RESTORED
;
1372 wndPtr
->flags
&= ~WIN_NEED_SIZE
;
1373 if (wndPtr
->dwStyle
& WS_MAXIMIZE
) wParam
= SIZE_MAXIMIZED
;
1374 else if (wndPtr
->dwStyle
& WS_MINIMIZE
) wParam
= SIZE_MINIMIZED
;
1375 SendMessageA( hwnd
, WM_SIZE
, wParam
,
1376 MAKELONG(wndPtr
->rectClient
.right
-wndPtr
->rectClient
.left
,
1377 wndPtr
->rectClient
.bottom
-wndPtr
->rectClient
.top
));
1378 SendMessageA( hwnd
, WM_MOVE
, 0,
1379 MAKELONG(wndPtr
->rectClient
.left
, wndPtr
->rectClient
.top
) );
1383 WIN_ReleaseWndPtr(wndPtr
);
1388 /***********************************************************************
1389 * GetInternalWindowPos16 (USER.460)
1391 UINT16 WINAPI
GetInternalWindowPos16( HWND16 hwnd
, LPRECT16 rectWnd
,
1394 WINDOWPLACEMENT16 wndpl
;
1395 if (GetWindowPlacement16( hwnd
, &wndpl
))
1397 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
1398 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
1399 return wndpl
.showCmd
;
1405 /***********************************************************************
1406 * GetInternalWindowPos (USER32.245)
1408 UINT WINAPI
GetInternalWindowPos( HWND hwnd
, LPRECT rectWnd
,
1411 WINDOWPLACEMENT wndpl
;
1412 if (GetWindowPlacement( hwnd
, &wndpl
))
1414 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
1415 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
1416 return wndpl
.showCmd
;
1421 /***********************************************************************
1422 * GetWindowPlacement16 (USER.370)
1424 BOOL16 WINAPI
GetWindowPlacement16( HWND16 hwnd
, WINDOWPLACEMENT16
*wndpl
)
1426 WND
*pWnd
= WIN_FindWndPtr( hwnd
);
1427 LPINTERNALPOS lpPos
;
1429 if(!pWnd
) return FALSE
;
1431 lpPos
= (LPINTERNALPOS
)WINPOS_InitInternalPos( pWnd
,
1432 *(LPPOINT
)&pWnd
->rectWindow
.left
, &pWnd
->rectWindow
);
1433 wndpl
->length
= sizeof(*wndpl
);
1434 if( pWnd
->dwStyle
& WS_MINIMIZE
)
1435 wndpl
->showCmd
= SW_SHOWMINIMIZED
;
1437 wndpl
->showCmd
= ( pWnd
->dwStyle
& WS_MAXIMIZE
)
1438 ? SW_SHOWMAXIMIZED
: SW_SHOWNORMAL
;
1439 if( pWnd
->flags
& WIN_RESTORE_MAX
)
1440 wndpl
->flags
= WPF_RESTORETOMAXIMIZED
;
1443 wndpl
->ptMinPosition
= lpPos
->ptIconPos
;
1444 wndpl
->ptMaxPosition
= lpPos
->ptMaxPos
;
1445 wndpl
->rcNormalPosition
= lpPos
->rectNormal
;
1447 WIN_ReleaseWndPtr(pWnd
);
1452 /***********************************************************************
1453 * GetWindowPlacement (USER32.307)
1456 * Fails if wndpl->length of Win95 (!) apps is invalid.
1458 BOOL WINAPI
GetWindowPlacement( HWND hwnd
, WINDOWPLACEMENT
*pwpl32
)
1462 WINDOWPLACEMENT16 wpl
;
1463 wpl
.length
= sizeof(wpl
);
1464 if( GetWindowPlacement16( hwnd
, &wpl
) )
1466 pwpl32
->length
= sizeof(*pwpl32
);
1467 pwpl32
->flags
= wpl
.flags
;
1468 pwpl32
->showCmd
= wpl
.showCmd
;
1469 CONV_POINT16TO32( &wpl
.ptMinPosition
, &pwpl32
->ptMinPosition
);
1470 CONV_POINT16TO32( &wpl
.ptMaxPosition
, &pwpl32
->ptMaxPosition
);
1471 CONV_RECT16TO32( &wpl
.rcNormalPosition
, &pwpl32
->rcNormalPosition
);
1479 /***********************************************************************
1480 * WINPOS_SetPlacement
1482 static BOOL
WINPOS_SetPlacement( HWND hwnd
, const WINDOWPLACEMENT16
*wndpl
,
1485 WND
*pWnd
= WIN_FindWndPtr( hwnd
);
1488 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)WINPOS_InitInternalPos( pWnd
,
1489 *(LPPOINT
)&pWnd
->rectWindow
.left
, &pWnd
->rectWindow
);
1491 if( flags
& PLACE_MIN
) lpPos
->ptIconPos
= wndpl
->ptMinPosition
;
1492 if( flags
& PLACE_MAX
) lpPos
->ptMaxPos
= wndpl
->ptMaxPosition
;
1493 if( flags
& PLACE_RECT
) lpPos
->rectNormal
= wndpl
->rcNormalPosition
;
1495 if( pWnd
->dwStyle
& WS_MINIMIZE
)
1497 WINPOS_ShowIconTitle( pWnd
, FALSE
);
1498 if( wndpl
->flags
& WPF_SETMINPOSITION
&& !EMPTYPOINT(lpPos
->ptIconPos
))
1499 SetWindowPos( hwnd
, 0, lpPos
->ptIconPos
.x
, lpPos
->ptIconPos
.y
,
1500 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1502 else if( pWnd
->dwStyle
& WS_MAXIMIZE
)
1504 if( !EMPTYPOINT(lpPos
->ptMaxPos
) )
1505 SetWindowPos( hwnd
, 0, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
,
1506 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1508 else if( flags
& PLACE_RECT
)
1509 SetWindowPos( hwnd
, 0, lpPos
->rectNormal
.left
, lpPos
->rectNormal
.top
,
1510 lpPos
->rectNormal
.right
- lpPos
->rectNormal
.left
,
1511 lpPos
->rectNormal
.bottom
- lpPos
->rectNormal
.top
,
1512 SWP_NOZORDER
| SWP_NOACTIVATE
);
1514 ShowWindow( hwnd
, wndpl
->showCmd
);
1515 if( IsWindow(hwnd
) && pWnd
->dwStyle
& WS_MINIMIZE
)
1517 if( pWnd
->dwStyle
& WS_VISIBLE
) WINPOS_ShowIconTitle( pWnd
, TRUE
);
1519 /* SDK: ...valid only the next time... */
1520 if( wndpl
->flags
& WPF_RESTORETOMAXIMIZED
) pWnd
->flags
|= WIN_RESTORE_MAX
;
1522 WIN_ReleaseWndPtr(pWnd
);
1529 /***********************************************************************
1530 * SetWindowPlacement16 (USER.371)
1532 BOOL16 WINAPI
SetWindowPlacement16(HWND16 hwnd
, const WINDOWPLACEMENT16
*wndpl
)
1534 return WINPOS_SetPlacement( hwnd
, wndpl
,
1535 PLACE_MIN
| PLACE_MAX
| PLACE_RECT
);
1538 /***********************************************************************
1539 * SetWindowPlacement (USER32.519)
1542 * Fails if wndpl->length of Win95 (!) apps is invalid.
1544 BOOL WINAPI
SetWindowPlacement( HWND hwnd
, const WINDOWPLACEMENT
*pwpl32
)
1548 WINDOWPLACEMENT16 wpl
;
1550 wpl
.length
= sizeof(WINDOWPLACEMENT16
);
1551 wpl
.flags
= pwpl32
->flags
;
1552 wpl
.showCmd
= pwpl32
->showCmd
;
1553 wpl
.ptMinPosition
.x
= pwpl32
->ptMinPosition
.x
;
1554 wpl
.ptMinPosition
.y
= pwpl32
->ptMinPosition
.y
;
1555 wpl
.ptMaxPosition
.x
= pwpl32
->ptMaxPosition
.x
;
1556 wpl
.ptMaxPosition
.y
= pwpl32
->ptMaxPosition
.y
;
1557 wpl
.rcNormalPosition
.left
= pwpl32
->rcNormalPosition
.left
;
1558 wpl
.rcNormalPosition
.top
= pwpl32
->rcNormalPosition
.top
;
1559 wpl
.rcNormalPosition
.right
= pwpl32
->rcNormalPosition
.right
;
1560 wpl
.rcNormalPosition
.bottom
= pwpl32
->rcNormalPosition
.bottom
;
1562 return WINPOS_SetPlacement( hwnd
, &wpl
, PLACE_MIN
| PLACE_MAX
| PLACE_RECT
);
1568 /***********************************************************************
1569 * SetInternalWindowPos16 (USER.461)
1571 void WINAPI
SetInternalWindowPos16( HWND16 hwnd
, UINT16 showCmd
,
1572 LPRECT16 rect
, LPPOINT16 pt
)
1574 if( IsWindow16(hwnd
) )
1576 WINDOWPLACEMENT16 wndpl
;
1579 wndpl
.length
= sizeof(wndpl
);
1580 wndpl
.showCmd
= showCmd
;
1581 wndpl
.flags
= flags
= 0;
1586 wndpl
.flags
|= WPF_SETMINPOSITION
;
1587 wndpl
.ptMinPosition
= *pt
;
1591 flags
|= PLACE_RECT
;
1592 wndpl
.rcNormalPosition
= *rect
;
1594 WINPOS_SetPlacement( hwnd
, &wndpl
, flags
);
1599 /***********************************************************************
1600 * SetInternalWindowPos (USER32.483)
1602 void WINAPI
SetInternalWindowPos( HWND hwnd
, UINT showCmd
,
1603 LPRECT rect
, LPPOINT pt
)
1605 if( IsWindow(hwnd
) )
1607 WINDOWPLACEMENT16 wndpl
;
1610 wndpl
.length
= sizeof(wndpl
);
1611 wndpl
.showCmd
= showCmd
;
1612 wndpl
.flags
= flags
= 0;
1617 wndpl
.flags
|= WPF_SETMINPOSITION
;
1618 CONV_POINT32TO16( pt
, &wndpl
.ptMinPosition
);
1622 flags
|= PLACE_RECT
;
1623 CONV_RECT32TO16( rect
, &wndpl
.rcNormalPosition
);
1625 WINPOS_SetPlacement( hwnd
, &wndpl
, flags
);
1629 /*******************************************************************
1630 * WINPOS_SetActiveWindow
1632 * SetActiveWindow() back-end. This is the only function that
1633 * can assign active status to a window. It must be called only
1634 * for the top level windows.
1636 BOOL
WINPOS_SetActiveWindow( HWND hWnd
, BOOL fMouse
, BOOL fChangeFocus
)
1638 CBTACTIVATESTRUCT16
* cbtStruct
;
1639 WND
* wndPtr
=0, *wndTemp
;
1640 HQUEUE16 hOldActiveQueue
, hNewActiveQueue
;
1641 MESSAGEQUEUE
*pOldActiveQueue
= 0, *pNewActiveQueue
= 0;
1643 HWND hwndActive
= 0;
1646 /* Get current active window from the active queue */
1649 pOldActiveQueue
= QUEUE_Lock( hActiveQueue
);
1650 if ( pOldActiveQueue
)
1651 hwndActive
= PERQDATA_GetActiveWnd( pOldActiveQueue
->pQData
);
1654 /* paranoid checks */
1655 if( hWnd
== GetDesktopWindow() || (bRet
= (hWnd
== hwndActive
)) )
1658 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1661 wndPtr
= WIN_FindWndPtr(hWnd
);
1662 hOldActiveQueue
= hActiveQueue
;
1664 if( (wndTemp
= WIN_FindWndPtr(hwndActive
)) )
1666 wIconized
= HIWORD(wndTemp
->dwStyle
& WS_MINIMIZE
);
1667 WIN_ReleaseWndPtr(wndTemp
);
1670 TRACE(win
,"no current active window.\n");
1672 /* call CBT hook chain */
1673 if ((cbtStruct
= SEGPTR_NEW(CBTACTIVATESTRUCT16
)))
1675 cbtStruct
->fMouse
= fMouse
;
1676 cbtStruct
->hWndActive
= hwndActive
;
1677 bRet
= (BOOL
)HOOK_CallHooks16( WH_CBT
, HCBT_ACTIVATE
, (WPARAM16
)hWnd
,
1678 (LPARAM
)SEGPTR_GET(cbtStruct
) );
1679 SEGPTR_FREE(cbtStruct
);
1680 if (bRet
) goto CLEANUP_END
;
1683 /* set prev active wnd to current active wnd and send notification */
1684 if ((hwndPrevActive
= hwndActive
) && IsWindow(hwndPrevActive
))
1686 MESSAGEQUEUE
*pTempActiveQueue
= 0;
1688 if (!SendMessageA( hwndPrevActive
, WM_NCACTIVATE
, FALSE
, 0 ))
1690 if (GetSysModalWindow16() != hWnd
)
1692 /* disregard refusal if hWnd is sysmodal */
1695 SendMessageA( hwndPrevActive
, WM_ACTIVATE
,
1696 MAKEWPARAM( WA_INACTIVE
, wIconized
),
1699 /* check if something happened during message processing
1700 * (global active queue may have changed)
1702 pTempActiveQueue
= QUEUE_Lock( hActiveQueue
);
1703 if(!pTempActiveQueue
)
1706 hwndActive
= PERQDATA_GetActiveWnd( pTempActiveQueue
->pQData
);
1707 QUEUE_Unlock( pTempActiveQueue
);
1708 if( hwndPrevActive
!= hwndActive
)
1712 /* Set new active window in the message queue */
1716 pNewActiveQueue
= QUEUE_Lock( wndPtr
->hmemTaskQ
);
1717 if ( pNewActiveQueue
)
1718 PERQDATA_SetActiveWnd( pNewActiveQueue
->pQData
, hwndActive
);
1720 else /* have to do this or MDI frame activation goes to hell */
1721 if( pOldActiveQueue
)
1722 PERQDATA_SetActiveWnd( pOldActiveQueue
->pQData
, 0 );
1724 /* send palette messages */
1725 if (hWnd
&& SendMessage16( hWnd
, WM_QUERYNEWPALETTE
, 0, 0L))
1726 SendMessage16((HWND16
)-1, WM_PALETTEISCHANGING
, (WPARAM16
)hWnd
, 0L );
1728 /* if prev wnd is minimized redraw icon title */
1729 if( IsIconic( hwndPrevActive
) ) WINPOS_RedrawIconTitle(hwndPrevActive
);
1731 /* managed windows will get ConfigureNotify event */
1732 if (wndPtr
&& !(wndPtr
->dwStyle
& WS_CHILD
) && !(wndPtr
->flags
& WIN_MANAGED
))
1734 /* check Z-order and bring hWnd to the top */
1735 for (wndTemp
= WIN_LockWndPtr(WIN_GetDesktop()->child
); wndTemp
; WIN_UpdateWndPtr(&wndTemp
,wndTemp
->next
))
1737 if (wndTemp
->dwStyle
& WS_VISIBLE
) break;
1739 WIN_ReleaseDesktop();
1740 WIN_ReleaseWndPtr(wndTemp
);
1742 if( wndTemp
!= wndPtr
)
1743 SetWindowPos(hWnd
, HWND_TOP
, 0,0,0,0,
1744 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
1745 if (!IsWindow(hWnd
))
1749 /* Get a handle to the new active queue */
1750 hNewActiveQueue
= wndPtr
? wndPtr
->hmemTaskQ
: 0;
1752 /* send WM_ACTIVATEAPP if necessary */
1753 if (hOldActiveQueue
!= hNewActiveQueue
)
1755 WND
**list
, **ppWnd
;
1756 WND
*pDesktop
= WIN_GetDesktop();
1758 if ((list
= WIN_BuildWinArray( pDesktop
, 0, NULL
)))
1760 for (ppWnd
= list
; *ppWnd
; ppWnd
++)
1762 if (!IsWindow( (*ppWnd
)->hwndSelf
)) continue;
1764 if ((*ppWnd
)->hmemTaskQ
== hOldActiveQueue
)
1765 SendMessage16( (*ppWnd
)->hwndSelf
, WM_ACTIVATEAPP
,
1766 0, QUEUE_GetQueueTask(hNewActiveQueue
) );
1768 WIN_ReleaseWinArray(list
);
1771 hActiveQueue
= hNewActiveQueue
;
1773 if ((list
= WIN_BuildWinArray(pDesktop
, 0, NULL
)))
1775 for (ppWnd
= list
; *ppWnd
; ppWnd
++)
1777 if (!IsWindow( (*ppWnd
)->hwndSelf
)) continue;
1779 if ((*ppWnd
)->hmemTaskQ
== hNewActiveQueue
)
1780 SendMessage16( (*ppWnd
)->hwndSelf
, WM_ACTIVATEAPP
,
1781 1, QUEUE_GetQueueTask( hOldActiveQueue
) );
1783 WIN_ReleaseWinArray(list
);
1785 WIN_ReleaseDesktop();
1787 if (!IsWindow(hWnd
)) goto CLEANUP
;
1792 /* walk up to the first unowned window */
1793 wndTemp
= WIN_LockWndPtr(wndPtr
);
1794 while (wndTemp
->owner
)
1796 WIN_UpdateWndPtr(&wndTemp
,wndTemp
->owner
);
1798 /* and set last active owned popup */
1799 wndTemp
->hwndLastActive
= hWnd
;
1801 wIconized
= HIWORD(wndTemp
->dwStyle
& WS_MINIMIZE
);
1802 WIN_ReleaseWndPtr(wndTemp
);
1803 SendMessageA( hWnd
, WM_NCACTIVATE
, TRUE
, 0 );
1804 SendMessageA( hWnd
, WM_ACTIVATE
,
1805 MAKEWPARAM( (fMouse
) ? WA_CLICKACTIVE
: WA_ACTIVE
, wIconized
),
1806 (LPARAM
)hwndPrevActive
);
1807 if( !IsWindow(hWnd
) ) goto CLEANUP
;
1810 /* change focus if possible */
1811 if( fChangeFocus
&& GetFocus() )
1812 if( WIN_GetTopParent(GetFocus()) != hwndActive
)
1813 FOCUS_SwitchFocus( pNewActiveQueue
, GetFocus(),
1814 (wndPtr
&& (wndPtr
->dwStyle
& WS_MINIMIZE
))?
1819 if( !hwndPrevActive
&& wndPtr
)
1820 (*wndPtr
->pDriver
->pForceWindowRaise
)(wndPtr
);
1822 /* if active wnd is minimized redraw icon title */
1823 if( IsIconic(hwndActive
) ) WINPOS_RedrawIconTitle(hwndActive
);
1825 bRet
= (hWnd
== hwndActive
); /* Success? */
1827 CLEANUP
: /* Unlock the message queues before returning */
1829 if ( pNewActiveQueue
)
1830 QUEUE_Unlock( pNewActiveQueue
);
1834 if ( pOldActiveQueue
)
1835 QUEUE_Unlock( pOldActiveQueue
);
1837 WIN_ReleaseWndPtr(wndPtr
);
1841 /*******************************************************************
1842 * WINPOS_ActivateOtherWindow
1844 * Activates window other than pWnd.
1846 BOOL
WINPOS_ActivateOtherWindow(WND
* pWnd
)
1850 HWND hwndActive
= 0;
1852 /* Get current active window from the active queue */
1855 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
1858 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
1859 QUEUE_Unlock( pActiveQueue
);
1863 if( pWnd
->hwndSelf
== hwndPrevActive
)
1866 if( hwndActive
!= pWnd
->hwndSelf
&&
1867 ( hwndActive
|| QUEUE_IsExitingQueue(pWnd
->hmemTaskQ
)) )
1870 if( !(pWnd
->dwStyle
& WS_POPUP
) || !(pWnd
->owner
) ||
1871 !WINPOS_CanActivate((pWndTo
= WIN_GetTopParentPtr(pWnd
->owner
))) )
1873 WND
* pWndPtr
= WIN_GetTopParentPtr(pWnd
);
1875 WIN_ReleaseWndPtr(pWndTo
);
1876 pWndTo
= WIN_FindWndPtr(hwndPrevActive
);
1878 while( !WINPOS_CanActivate(pWndTo
) )
1880 /* by now owned windows should've been taken care of */
1881 WIN_UpdateWndPtr(&pWndTo
,pWndPtr
->next
);
1882 WIN_UpdateWndPtr(&pWndPtr
,pWndTo
);
1883 if( !pWndTo
) break;
1885 WIN_ReleaseWndPtr(pWndPtr
);
1888 bRet
= WINPOS_SetActiveWindow( pWndTo
? pWndTo
->hwndSelf
: 0, FALSE
, TRUE
);
1890 /* switch desktop queue to current active */
1893 WIN_GetDesktop()->hmemTaskQ
= pWndTo
->hmemTaskQ
;
1894 WIN_ReleaseWndPtr(pWndTo
);
1895 WIN_ReleaseDesktop();
1902 /*******************************************************************
1903 * WINPOS_ChangeActiveWindow
1906 BOOL
WINPOS_ChangeActiveWindow( HWND hWnd
, BOOL mouseMsg
)
1908 WND
*wndPtr
, *wndTemp
;
1910 HWND hwndActive
= 0;
1912 /* Get current active window from the active queue */
1915 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
1918 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
1919 QUEUE_Unlock( pActiveQueue
);
1924 return WINPOS_SetActiveWindow( 0, mouseMsg
, TRUE
);
1926 wndPtr
= WIN_FindWndPtr(hWnd
);
1927 if( !wndPtr
) return FALSE
;
1929 /* child windows get WM_CHILDACTIVATE message */
1930 if( (wndPtr
->dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1932 retvalue
= SendMessageA(hWnd
, WM_CHILDACTIVATE
, 0, 0L);
1936 if( hWnd
== hwndActive
)
1942 if( !WINPOS_SetActiveWindow(hWnd
,mouseMsg
,TRUE
) )
1948 /* switch desktop queue to current active */
1949 wndTemp
= WIN_GetDesktop();
1950 if( wndPtr
->parent
== wndTemp
)
1951 wndTemp
->hmemTaskQ
= wndPtr
->hmemTaskQ
;
1952 WIN_ReleaseDesktop();
1956 WIN_ReleaseWndPtr(wndPtr
);
1961 /***********************************************************************
1962 * WINPOS_SendNCCalcSize
1964 * Send a WM_NCCALCSIZE message to a window.
1965 * All parameters are read-only except newClientRect.
1966 * oldWindowRect, oldClientRect and winpos must be non-NULL only
1967 * when calcValidRect is TRUE.
1969 LONG
WINPOS_SendNCCalcSize( HWND hwnd
, BOOL calcValidRect
,
1970 RECT
*newWindowRect
, RECT
*oldWindowRect
,
1971 RECT
*oldClientRect
, WINDOWPOS
*winpos
,
1972 RECT
*newClientRect
)
1974 NCCALCSIZE_PARAMS params
;
1975 WINDOWPOS winposCopy
;
1978 params
.rgrc
[0] = *newWindowRect
;
1981 winposCopy
= *winpos
;
1982 params
.rgrc
[1] = *oldWindowRect
;
1983 params
.rgrc
[2] = *oldClientRect
;
1984 params
.lppos
= &winposCopy
;
1986 result
= SendMessageA( hwnd
, WM_NCCALCSIZE
, calcValidRect
,
1988 TRACE(win
, "%d,%d-%d,%d\n",
1989 params
.rgrc
[0].left
, params
.rgrc
[0].top
,
1990 params
.rgrc
[0].right
, params
.rgrc
[0].bottom
);
1991 *newClientRect
= params
.rgrc
[0];
1996 /***********************************************************************
1997 * WINPOS_HandleWindowPosChanging16
1999 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2001 LONG
WINPOS_HandleWindowPosChanging16( WND
*wndPtr
, WINDOWPOS16
*winpos
)
2003 POINT maxSize
, minTrack
;
2004 if (winpos
->flags
& SWP_NOSIZE
) return 0;
2005 if ((wndPtr
->dwStyle
& WS_THICKFRAME
) ||
2006 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) == 0))
2008 WINPOS_GetMinMaxInfo( wndPtr
, &maxSize
, NULL
, &minTrack
, NULL
);
2009 if (maxSize
.x
< winpos
->cx
) winpos
->cx
= maxSize
.x
;
2010 if (maxSize
.y
< winpos
->cy
) winpos
->cy
= maxSize
.y
;
2011 if (!(wndPtr
->dwStyle
& WS_MINIMIZE
))
2013 if (winpos
->cx
< minTrack
.x
) winpos
->cx
= minTrack
.x
;
2014 if (winpos
->cy
< minTrack
.y
) winpos
->cy
= minTrack
.y
;
2021 /***********************************************************************
2022 * WINPOS_HandleWindowPosChanging
2024 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2026 LONG
WINPOS_HandleWindowPosChanging( WND
*wndPtr
, WINDOWPOS
*winpos
)
2029 if (winpos
->flags
& SWP_NOSIZE
) return 0;
2030 if ((wndPtr
->dwStyle
& WS_THICKFRAME
) ||
2031 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) == 0))
2033 WINPOS_GetMinMaxInfo( wndPtr
, &maxSize
, NULL
, NULL
, NULL
);
2034 winpos
->cx
= MIN( winpos
->cx
, maxSize
.x
);
2035 winpos
->cy
= MIN( winpos
->cy
, maxSize
.y
);
2040 /***********************************************************************
2043 * fix Z order taking into account owned popups -
2044 * basically we need to maintain them above the window that owns them
2046 * FIXME: hide/show owned popups when owner visibility changes.
2048 static HWND
SWP_DoOwnedPopups(WND
* pDesktop
, WND
* wndPtr
, HWND hwndInsertAfter
, WORD flags
)
2050 WND
* w
= WIN_LockWndPtr(pDesktop
->child
);
2052 WARN(win
, "(%04x) hInsertAfter = %04x\n", wndPtr
->hwndSelf
, hwndInsertAfter
);
2054 if( (wndPtr
->dwStyle
& WS_POPUP
) && wndPtr
->owner
)
2056 /* make sure this popup stays above the owner */
2058 HWND hwndLocalPrev
= HWND_TOP
;
2060 if( hwndInsertAfter
!= HWND_TOP
)
2062 while( w
!= wndPtr
->owner
)
2064 if (w
!= wndPtr
) hwndLocalPrev
= w
->hwndSelf
;
2065 if( hwndLocalPrev
== hwndInsertAfter
) break;
2066 WIN_UpdateWndPtr(&w
,w
->next
);
2068 hwndInsertAfter
= hwndLocalPrev
;
2071 else if( wndPtr
->dwStyle
& WS_CHILD
)
2074 WIN_UpdateWndPtr(&w
, pDesktop
->child
);
2078 if( w
== wndPtr
) break;
2080 if( (w
->dwStyle
& WS_POPUP
) && w
->owner
== wndPtr
)
2082 SetWindowPos(w
->hwndSelf
, hwndInsertAfter
, 0, 0, 0, 0,
2083 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOSENDCHANGING
| SWP_DEFERERASE
);
2084 hwndInsertAfter
= w
->hwndSelf
;
2086 WIN_UpdateWndPtr(&w
, w
->next
);
2090 WIN_ReleaseWndPtr(w
);
2091 return hwndInsertAfter
;
2094 /***********************************************************************
2097 * Make window look nice without excessive repainting
2099 * visible and update regions are in window coordinates
2100 * client and window rectangles are in parent client coordinates
2102 * FIXME: SWP_EX_PAINTSELF in uFlags works only if both old and new
2103 * window rects have the same origin.
2105 * Returns: uFlags and a dirty region in *pVisRgn.
2107 static UINT
SWP_CopyValidBits( WND
* Wnd
, HRGN
* pVisRgn
,
2108 LPRECT lpOldWndRect
,
2109 LPRECT lpOldClientRect
, UINT uFlags
)
2112 HRGN newVisRgn
, dirtyRgn
;
2113 INT my
= COMPLEXREGION
;
2115 TRACE(win
,"\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2116 Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
,
2117 Wnd
->rectWindow
.right
, Wnd
->rectWindow
.bottom
,
2118 lpOldWndRect
->left
, lpOldWndRect
->top
,
2119 lpOldWndRect
->right
, lpOldWndRect
->bottom
, *pVisRgn
);
2120 TRACE(win
,"\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2121 Wnd
->rectClient
.left
, Wnd
->rectClient
.top
,
2122 Wnd
->rectClient
.right
, Wnd
->rectClient
.bottom
,
2123 lpOldClientRect
->left
, lpOldClientRect
->top
,
2124 lpOldClientRect
->right
,lpOldClientRect
->bottom
);
2126 if( Wnd
->hrgnUpdate
== 1 )
2127 uFlags
|= SWP_EX_NOCOPY
; /* whole window is invalid, nothing to copy */
2129 newVisRgn
= DCE_GetVisRgn( Wnd
->hwndSelf
, DCX_WINDOW
| DCX_CLIPSIBLINGS
, 0, 0);
2130 dirtyRgn
= CreateRectRgn( 0, 0, 0, 0 );
2132 if( !(uFlags
& SWP_EX_NOCOPY
) ) /* make sure dst region covers only valid bits */
2133 my
= CombineRgn( dirtyRgn
, newVisRgn
, *pVisRgn
, RGN_AND
);
2135 if( (my
== NULLREGION
) || (uFlags
& SWP_EX_NOCOPY
) )
2139 TRACE(win
,"\twon't copy anything!\n");
2141 /* set dirtyRgn to the sum of old and new visible regions
2142 * in parent client coordinates */
2144 OffsetRgn( newVisRgn
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2145 OffsetRgn( *pVisRgn
, lpOldWndRect
->left
, lpOldWndRect
->top
);
2147 CombineRgn(*pVisRgn
, *pVisRgn
, newVisRgn
, RGN_OR
);
2149 else /* copy valid bits to a new location */
2151 INT dx
, dy
, ow
, oh
, nw
, nh
, ocw
, ncw
, och
, nch
;
2152 HRGN hrgnValid
= dirtyRgn
; /* non-empty intersection of old and new visible rgns */
2154 /* subtract already invalid region inside Wnd from the dst region */
2156 if( Wnd
->hrgnUpdate
)
2157 if( CombineRgn( hrgnValid
, hrgnValid
, Wnd
->hrgnUpdate
, RGN_DIFF
) == NULLREGION
)
2160 /* check if entire window can be copied */
2162 ow
= lpOldWndRect
->right
- lpOldWndRect
->left
;
2163 oh
= lpOldWndRect
->bottom
- lpOldWndRect
->top
;
2164 nw
= Wnd
->rectWindow
.right
- Wnd
->rectWindow
.left
;
2165 nh
= Wnd
->rectWindow
.bottom
- Wnd
->rectWindow
.top
;
2167 ocw
= lpOldClientRect
->right
- lpOldClientRect
->left
;
2168 och
= lpOldClientRect
->bottom
- lpOldClientRect
->top
;
2169 ncw
= Wnd
->rectClient
.right
- Wnd
->rectClient
.left
;
2170 nch
= Wnd
->rectClient
.bottom
- Wnd
->rectClient
.top
;
2172 if( (ocw
!= ncw
) || (och
!= nch
) ||
2173 ( ow
!= nw
) || ( oh
!= nh
) ||
2174 ((lpOldClientRect
->top
- lpOldWndRect
->top
) !=
2175 (Wnd
->rectClient
.top
- Wnd
->rectWindow
.top
)) ||
2176 ((lpOldClientRect
->left
- lpOldWndRect
->left
) !=
2177 (Wnd
->rectClient
.left
- Wnd
->rectWindow
.left
)) )
2179 dx
= Wnd
->rectClient
.left
- lpOldClientRect
->left
;
2180 dy
= Wnd
->rectClient
.top
- lpOldClientRect
->top
;
2182 /* restrict valid bits to the common client rect */
2184 r
.left
= Wnd
->rectClient
.left
- Wnd
->rectWindow
.left
;
2185 r
.top
= Wnd
->rectClient
.top
- Wnd
->rectWindow
.top
;
2186 r
.right
= r
.left
+ MIN( ocw
, ncw
);
2187 r
.bottom
= r
.top
+ MIN( och
, nch
);
2189 REGION_CropRgn( hrgnValid
, hrgnValid
, &r
,
2190 (uFlags
& SWP_EX_PAINTSELF
) ? NULL
: (POINT
*)&(Wnd
->rectWindow
));
2191 GetRgnBox( hrgnValid
, &r
);
2192 if( IsRectEmpty( &r
) )
2194 r
= *lpOldClientRect
;
2198 dx
= Wnd
->rectWindow
.left
- lpOldWndRect
->left
;
2199 dy
= Wnd
->rectWindow
.top
- lpOldWndRect
->top
;
2200 if( !(uFlags
& SWP_EX_PAINTSELF
) )
2201 OffsetRgn( hrgnValid
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2205 if( !(uFlags
& SWP_EX_PAINTSELF
) )
2207 /* Move remaining regions to parent coordinates */
2208 OffsetRgn( newVisRgn
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2209 OffsetRgn( *pVisRgn
, lpOldWndRect
->left
, lpOldWndRect
->top
);
2212 OffsetRect( &r
, -lpOldWndRect
->left
, -lpOldWndRect
->top
);
2214 TRACE(win
,"\tcomputing dirty region!\n");
2216 /* Compute combined dirty region (old + new - valid) */
2217 CombineRgn( *pVisRgn
, *pVisRgn
, newVisRgn
, RGN_OR
);
2218 CombineRgn( *pVisRgn
, *pVisRgn
, hrgnValid
, RGN_DIFF
);
2220 /* Blt valid bits, r is the rect to copy */
2228 /* get DC and clip rect with drawable rect to avoid superfluous expose events
2229 from copying clipped areas */
2231 if( uFlags
& SWP_EX_PAINTSELF
)
2233 hDC
= GetDCEx( Wnd
->hwndSelf
, hrgnValid
, DCX_WINDOW
| DCX_CACHE
|
2234 DCX_KEEPCLIPRGN
| DCX_INTERSECTRGN
| DCX_CLIPSIBLINGS
);
2235 rClip
.right
= nw
; rClip
.bottom
= nh
;
2239 hDC
= GetDCEx( Wnd
->parent
->hwndSelf
, hrgnValid
, DCX_CACHE
|
2240 DCX_KEEPCLIPRGN
| DCX_INTERSECTRGN
| DCX_CLIPSIBLINGS
);
2241 rClip
.right
= Wnd
->parent
->rectClient
.right
- Wnd
->parent
->rectClient
.left
;
2242 rClip
.bottom
= Wnd
->parent
->rectClient
.bottom
- Wnd
->parent
->rectClient
.top
;
2244 rClip
.left
= rClip
.top
= 0;
2246 if( (dc
= (DC
*)GDI_GetObjPtr(hDC
, DC_MAGIC
)) )
2248 if( oh
> nh
) r
.bottom
= r
.top
+ nh
;
2249 if( ow
< nw
) r
.right
= r
.left
+ nw
;
2251 if( IntersectRect( &r
, &r
, &rClip
) )
2252 Wnd
->pDriver
->pSurfaceCopy( Wnd
->parent
, dc
, dx
, dy
, &r
, TRUE
);
2254 GDI_HEAP_UNLOCK( hDC
);
2256 ReleaseDC( (uFlags
& SWP_EX_PAINTSELF
) ?
2257 Wnd
->hwndSelf
: Wnd
->parent
->hwndSelf
, hDC
);
2261 /* *pVisRgn now points to the invalidated region */
2263 DeleteObject(newVisRgn
);
2264 DeleteObject(dirtyRgn
);
2268 /***********************************************************************
2269 * SWP_DoSimpleFrameChanged
2271 * NOTE: old and new client rect origins are identical, only
2272 * extents may have changed. Window extents are the same.
2274 static void SWP_DoSimpleFrameChanged( WND
* wndPtr
, RECT
* pOldClientRect
, WORD swpFlags
, UINT uFlags
)
2280 if( !(swpFlags
& SWP_NOCLIENTSIZE
) )
2282 /* Client rect changed its position/size, most likely a scrollar
2283 * was added/removed.
2285 * FIXME: WVR alignment flags
2288 if( wndPtr
->rectClient
.right
> pOldClientRect
->right
) /* right edge */
2292 rect
.bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
2293 rect
.right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
2294 if(!(uFlags
& SWP_EX_NOCOPY
))
2295 rect
.left
= pOldClientRect
->right
- wndPtr
->rectClient
.left
;
2303 if( wndPtr
->rectClient
.bottom
> pOldClientRect
->bottom
) /* bottom edge */
2306 hrgn
= CreateRectRgnIndirect( &rect
);
2308 rect
.right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
2309 rect
.bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
2310 if(!(uFlags
& SWP_EX_NOCOPY
))
2311 rect
.top
= pOldClientRect
->bottom
- wndPtr
->rectClient
.top
;
2315 REGION_UnionRectWithRgn( hrgn
, &rect
);
2318 if( i
== 0 && (uFlags
& SWP_EX_NOCOPY
) ) /* force redraw anyway */
2320 rect
= wndPtr
->rectWindow
;
2321 OffsetRect( &rect
, wndPtr
->rectWindow
.left
- wndPtr
->rectClient
.left
,
2322 wndPtr
->rectWindow
.top
- wndPtr
->rectClient
.top
);
2330 PAINT_RedrawWindow( wndPtr
->hwndSelf
, &rect
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
|
2331 RDW_ERASENOW
| RDW_ALLCHILDREN
, RDW_EX_TOPFRAME
| RDW_EX_USEHRGN
);
2335 WIN_UpdateNCRgn(wndPtr
, 0, UNC_UPDATE
| UNC_ENTIRE
);
2339 DeleteObject( hrgn
);
2342 /***********************************************************************
2343 * SWP_DoWinPosChanging
2345 static BOOL
SWP_DoWinPosChanging( WND
* wndPtr
, WINDOWPOS
* pWinpos
,
2346 RECT
* pNewWindowRect
, RECT
* pNewClientRect
)
2348 /* Send WM_WINDOWPOSCHANGING message */
2350 if (!(pWinpos
->flags
& SWP_NOSENDCHANGING
))
2351 SendMessageA( wndPtr
->hwndSelf
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
)pWinpos
);
2353 /* Calculate new position and size */
2355 *pNewWindowRect
= wndPtr
->rectWindow
;
2356 *pNewClientRect
= (wndPtr
->dwStyle
& WS_MINIMIZE
) ? wndPtr
->rectWindow
2357 : wndPtr
->rectClient
;
2359 if (!(pWinpos
->flags
& SWP_NOSIZE
))
2361 pNewWindowRect
->right
= pNewWindowRect
->left
+ pWinpos
->cx
;
2362 pNewWindowRect
->bottom
= pNewWindowRect
->top
+ pWinpos
->cy
;
2364 if (!(pWinpos
->flags
& SWP_NOMOVE
))
2366 pNewWindowRect
->left
= pWinpos
->x
;
2367 pNewWindowRect
->top
= pWinpos
->y
;
2368 pNewWindowRect
->right
+= pWinpos
->x
- wndPtr
->rectWindow
.left
;
2369 pNewWindowRect
->bottom
+= pWinpos
->y
- wndPtr
->rectWindow
.top
;
2371 OffsetRect( pNewClientRect
, pWinpos
->x
- wndPtr
->rectWindow
.left
,
2372 pWinpos
->y
- wndPtr
->rectWindow
.top
);
2375 pWinpos
->flags
|= SWP_NOCLIENTMOVE
| SWP_NOCLIENTSIZE
;
2379 /***********************************************************************
2382 static UINT
SWP_DoNCCalcSize( WND
* wndPtr
, WINDOWPOS
* pWinpos
,
2383 RECT
* pNewWindowRect
, RECT
* pNewClientRect
, WORD f
)
2387 /* Send WM_NCCALCSIZE message to get new client area */
2388 if( (pWinpos
->flags
& (SWP_FRAMECHANGED
| SWP_NOSIZE
)) != SWP_NOSIZE
)
2390 wvrFlags
= WINPOS_SendNCCalcSize( pWinpos
->hwnd
, TRUE
, pNewWindowRect
,
2391 &wndPtr
->rectWindow
, &wndPtr
->rectClient
,
2392 pWinpos
, pNewClientRect
);
2394 /* FIXME: WVR_ALIGNxxx */
2396 if( pNewClientRect
->left
!= wndPtr
->rectClient
.left
||
2397 pNewClientRect
->top
!= wndPtr
->rectClient
.top
)
2398 pWinpos
->flags
&= ~SWP_NOCLIENTMOVE
;
2400 if( (pNewClientRect
->right
- pNewClientRect
->left
!=
2401 wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
) ||
2402 (pNewClientRect
->bottom
- pNewClientRect
->top
!=
2403 wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
) )
2404 pWinpos
->flags
&= ~SWP_NOCLIENTSIZE
;
2407 if( !(f
& SWP_NOMOVE
) && (pNewClientRect
->left
!= wndPtr
->rectClient
.left
||
2408 pNewClientRect
->top
!= wndPtr
->rectClient
.top
) )
2409 pWinpos
->flags
&= ~SWP_NOCLIENTMOVE
;
2413 /***********************************************************************
2414 * SetWindowPos (USER.2)
2416 BOOL16 WINAPI
SetWindowPos16( HWND16 hwnd
, HWND16 hwndInsertAfter
,
2417 INT16 x
, INT16 y
, INT16 cx
, INT16 cy
, WORD flags
)
2419 return SetWindowPos(hwnd
,(INT
)(INT16
)hwndInsertAfter
,x
,y
,cx
,cy
,flags
);
2422 /***********************************************************************
2423 * SetWindowPos (USER32.520)
2425 BOOL WINAPI
SetWindowPos( HWND hwnd
, HWND hwndInsertAfter
,
2426 INT x
, INT y
, INT cx
, INT cy
, WORD flags
)
2429 WND
* wndPtr
,*wndTemp
;
2430 RECT newWindowRect
, newClientRect
;
2431 RECT oldWindowRect
, oldClientRect
;
2433 UINT wvrFlags
= 0, uFlags
= 0;
2434 BOOL retvalue
, resync
= FALSE
;
2435 HWND hwndActive
= 0;
2437 /* Get current active window from the active queue */
2440 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
2443 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
2444 QUEUE_Unlock( pActiveQueue
);
2448 TRACE(win
,"hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2449 hwnd
, x
, y
, x
+cx
, y
+cy
, flags
);
2451 /* ------------------------------------------------------------------------ CHECKS */
2453 /* Check window handle */
2455 if (hwnd
== GetDesktopWindow()) return FALSE
;
2456 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return FALSE
;
2458 TRACE(win
,"\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr
->rectWindow
.left
, wndPtr
->rectWindow
.top
,
2459 wndPtr
->rectWindow
.right
, wndPtr
->rectWindow
.bottom
, (unsigned)wndPtr
->dwStyle
);
2461 /* Fix redundant flags */
2463 if(wndPtr
->dwStyle
& WS_VISIBLE
)
2464 flags
&= ~SWP_SHOWWINDOW
;
2467 if (!(flags
& SWP_SHOWWINDOW
))
2468 flags
|= SWP_NOREDRAW
;
2469 flags
&= ~SWP_HIDEWINDOW
;
2472 if ( cx
< 0 ) cx
= 0; if( cy
< 0 ) cy
= 0;
2474 if ((wndPtr
->rectWindow
.right
- wndPtr
->rectWindow
.left
== cx
) &&
2475 (wndPtr
->rectWindow
.bottom
- wndPtr
->rectWindow
.top
== cy
))
2476 flags
|= SWP_NOSIZE
; /* Already the right size */
2478 if ((wndPtr
->rectWindow
.left
== x
) && (wndPtr
->rectWindow
.top
== y
))
2479 flags
|= SWP_NOMOVE
; /* Already the right position */
2481 if (hwnd
== hwndActive
)
2482 flags
|= SWP_NOACTIVATE
; /* Already active */
2485 if(!(flags
& SWP_NOACTIVATE
)) /* Bring to the top when activating */
2487 flags
&= ~SWP_NOZORDER
;
2488 hwndInsertAfter
= HWND_TOP
;
2493 /* Check hwndInsertAfter */
2495 /* FIXME: TOPMOST not supported yet */
2496 if ((hwndInsertAfter
== HWND_TOPMOST
) ||
2497 (hwndInsertAfter
== HWND_NOTOPMOST
)) hwndInsertAfter
= HWND_TOP
;
2499 /* hwndInsertAfter must be a sibling of the window */
2500 if ((hwndInsertAfter
!= HWND_TOP
) && (hwndInsertAfter
!= HWND_BOTTOM
))
2502 WND
* wnd
= WIN_FindWndPtr(hwndInsertAfter
);
2505 if( wnd
->parent
!= wndPtr
->parent
)
2508 WIN_ReleaseWndPtr(wnd
);
2511 if( wnd
->next
== wndPtr
) flags
|= SWP_NOZORDER
;
2513 WIN_ReleaseWndPtr(wnd
);
2516 Pos
: /* ------------------------------------------------------------------------ MAIN part */
2518 /* Fill the WINDOWPOS structure */
2521 winpos
.hwndInsertAfter
= hwndInsertAfter
;
2526 winpos
.flags
= flags
;
2528 SWP_DoWinPosChanging( wndPtr
, &winpos
, &newWindowRect
, &newClientRect
);
2530 if((winpos
.flags
& (SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) != SWP_NOZORDER
)
2532 if( wndPtr
->parent
== WIN_GetDesktop() )
2533 hwndInsertAfter
= SWP_DoOwnedPopups( wndPtr
->parent
, wndPtr
,
2534 hwndInsertAfter
, winpos
.flags
);
2535 WIN_ReleaseDesktop();
2538 if(!(wndPtr
->flags
& WIN_NATIVE
) )
2540 if( hwndInsertAfter
== HWND_TOP
)
2541 winpos
.flags
|= ( wndPtr
->parent
->child
== wndPtr
)? SWP_NOZORDER
: 0;
2543 if( hwndInsertAfter
== HWND_BOTTOM
)
2544 winpos
.flags
|= ( wndPtr
->next
)? 0: SWP_NOZORDER
;
2546 if( !(winpos
.flags
& SWP_NOZORDER
) )
2547 if( GetWindow(hwndInsertAfter
, GW_HWNDNEXT
) == wndPtr
->hwndSelf
)
2548 winpos
.flags
|= SWP_NOZORDER
;
2550 if( !(winpos
.flags
& (SWP_NOREDRAW
| SWP_SHOWWINDOW
)) &&
2551 ((winpos
.flags
& (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_FRAMECHANGED
))
2552 != (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
)) )
2554 /* get a previous visible region for SWP_CopyValidBits() */
2556 visRgn
= DCE_GetVisRgn(hwnd
, DCX_WINDOW
| DCX_CLIPSIBLINGS
, 0, 0);
2560 /* Common operations */
2562 wvrFlags
= SWP_DoNCCalcSize( wndPtr
, &winpos
, &newWindowRect
, &newClientRect
, flags
);
2564 if(!(winpos
.flags
& SWP_NOZORDER
))
2566 WIN_UnlinkWindow( winpos
.hwnd
);
2567 WIN_LinkWindow( winpos
.hwnd
, hwndInsertAfter
);
2570 /* Reset active DCEs */
2572 if( (((winpos
.flags
& SWP_AGG_NOPOSCHANGE
) != SWP_AGG_NOPOSCHANGE
) &&
2573 wndPtr
->dwStyle
& WS_VISIBLE
) ||
2574 (flags
& (SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) )
2578 UnionRect(&rect
, &newWindowRect
, &wndPtr
->rectWindow
);
2579 DCE_InvalidateDCE(wndPtr
, &rect
);
2582 oldWindowRect
= wndPtr
->rectWindow
;
2583 oldClientRect
= wndPtr
->rectClient
;
2585 /* Find out if we have to redraw the whole client rect */
2587 if( oldClientRect
.bottom
- oldClientRect
.top
==
2588 newClientRect
.bottom
- newClientRect
.top
) wvrFlags
&= ~WVR_VREDRAW
;
2590 if( oldClientRect
.right
- oldClientRect
.left
==
2591 newClientRect
.right
- newClientRect
.left
) wvrFlags
&= ~WVR_HREDRAW
;
2593 if( (winpos
.flags
& SWP_NOCOPYBITS
) || (!(winpos
.flags
& SWP_NOCLIENTSIZE
) &&
2594 (wvrFlags
>= WVR_HREDRAW
) && (wvrFlags
< WVR_VALIDRECTS
)) )
2596 uFlags
|= SWP_EX_NOCOPY
;
2599 * Use this later in CopyValidBits()
2602 uFlags |= SWP_EX_NONCLIENT;
2605 /* FIXME: actually do something with WVR_VALIDRECTS */
2607 wndPtr
->rectWindow
= newWindowRect
;
2608 wndPtr
->rectClient
= newClientRect
;
2610 if (wndPtr
->flags
& WIN_NATIVE
) /* -------------------------------------------- hosted window */
2612 BOOL bCallDriver
= TRUE
;
2613 HWND tempInsertAfter
= winpos
.hwndInsertAfter
;
2615 winpos
.hwndInsertAfter
= hwndInsertAfter
;
2617 if( !(winpos
.flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
| SWP_NOREDRAW
)) )
2619 /* This is the only place where we need to force repainting of the contents
2620 of windows created by the host window system, all other cases go through the
2621 expose event handling */
2623 if( (winpos
.flags
& (SWP_NOSIZE
| SWP_FRAMECHANGED
)) == (SWP_NOSIZE
| SWP_FRAMECHANGED
) )
2625 cx
= newWindowRect
.right
- newWindowRect
.left
;
2626 cy
= newWindowRect
.bottom
- newWindowRect
.top
;
2628 wndPtr
->pDriver
->pSetWindowPos(wndPtr
, &winpos
, TRUE
);
2629 winpos
.hwndInsertAfter
= tempInsertAfter
;
2630 bCallDriver
= FALSE
;
2632 if( winpos
.flags
& SWP_NOCLIENTMOVE
)
2633 SWP_DoSimpleFrameChanged(wndPtr
, &oldClientRect
, winpos
.flags
, uFlags
);
2636 /* client area moved but window extents remained the same, copy valid bits */
2638 visRgn
= CreateRectRgn( 0, 0, cx
, cy
);
2639 uFlags
= SWP_CopyValidBits( wndPtr
, &visRgn
, &oldWindowRect
, &oldClientRect
,
2640 uFlags
| SWP_EX_PAINTSELF
);
2647 if( !(winpos
.flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
| SWP_NOREDRAW
)) )
2649 if( (oldClientRect
.left
- oldWindowRect
.left
== newClientRect
.left
- newWindowRect
.left
) &&
2650 (oldClientRect
.top
- oldWindowRect
.top
== newClientRect
.top
- newWindowRect
.top
) &&
2651 !(uFlags
& SWP_EX_NOCOPY
) )
2653 /* The origin of the client rect didn't move so we can try to repaint
2654 * only the nonclient area by setting bit gravity hint for the host window system.
2657 if( !(wndPtr
->flags
& WIN_MANAGED
) )
2659 HRGN hrgn
= CreateRectRgn( 0, 0, newWindowRect
.right
- newWindowRect
.left
,
2660 newWindowRect
.bottom
- newWindowRect
.top
);
2661 RECT rcn
= newClientRect
;
2662 RECT rco
= oldClientRect
;
2664 OffsetRect( &rcn
, -newWindowRect
.left
, -newWindowRect
.top
);
2665 OffsetRect( &rco
, -oldWindowRect
.left
, -oldWindowRect
.top
);
2666 IntersectRect( &rcn
, &rcn
, &rco
);
2667 visRgn
= CreateRectRgnIndirect( &rcn
);
2668 CombineRgn( visRgn
, hrgn
, visRgn
, RGN_DIFF
);
2669 DeleteObject( hrgn
);
2670 uFlags
= SWP_EX_PAINTSELF
;
2672 wndPtr
->pDriver
->pSetHostAttr(wndPtr
, HAK_BITGRAVITY
, BGNorthWest
);
2675 wndPtr
->pDriver
->pSetHostAttr(wndPtr
, HAK_BITGRAVITY
, BGForget
);
2678 wndPtr
->pDriver
->pSetWindowPos(wndPtr
, &winpos
, TRUE
);
2679 winpos
.hwndInsertAfter
= tempInsertAfter
;
2682 if( winpos
.flags
& SWP_SHOWWINDOW
)
2686 wndPtr
->dwStyle
|= WS_VISIBLE
;
2688 if (wndPtr
->flags
& WIN_MANAGED
) resync
= TRUE
;
2690 /* focus was set to unmapped window, reset host focus
2691 * since the window is now visible */
2693 focus
= curr
= GetFocus();
2698 WND
*pFocus
= WIN_FindWndPtr( focus
);
2700 pFocus
->pDriver
->pSetFocus(pFocus
);
2701 WIN_ReleaseWndPtr(pFocus
);
2704 curr
= GetParent(curr
);
2708 else /* -------------------------------------------- emulated window */
2710 if( winpos
.flags
& SWP_SHOWWINDOW
)
2712 wndPtr
->dwStyle
|= WS_VISIBLE
;
2713 uFlags
|= SWP_EX_PAINTSELF
;
2714 visRgn
= 1; /* redraw the whole window */
2716 else if( !(winpos
.flags
& SWP_NOREDRAW
) )
2718 if( winpos
.flags
& SWP_HIDEWINDOW
)
2720 if( visRgn
> 1 ) /* map to parent */
2721 OffsetRgn( visRgn
, oldWindowRect
.left
, oldWindowRect
.top
);
2727 if( (winpos
.flags
& SWP_AGG_NOPOSCHANGE
) != SWP_AGG_NOPOSCHANGE
)
2728 uFlags
= SWP_CopyValidBits(wndPtr
, &visRgn
, &oldWindowRect
,
2729 &oldClientRect
, uFlags
);
2732 /* nothing moved, redraw frame if needed */
2734 if( winpos
.flags
& SWP_FRAMECHANGED
)
2735 SWP_DoSimpleFrameChanged( wndPtr
, &oldClientRect
, winpos
.flags
, uFlags
);
2738 DeleteObject( visRgn
);
2746 if( winpos
.flags
& SWP_HIDEWINDOW
)
2748 wndPtr
->dwStyle
&= ~WS_VISIBLE
;
2750 if (hwnd
== CARET_GetHwnd()) DestroyCaret();
2752 /* FIXME: This will cause the window to be activated irrespective
2753 * of whether it is owned by the same thread. Has to be done
2757 if (winpos
.hwnd
== hwndActive
)
2758 WINPOS_ActivateOtherWindow( wndPtr
);
2761 /* ------------------------------------------------------------------------ FINAL */
2763 if (wndPtr
->flags
& WIN_NATIVE
)
2764 EVENT_Synchronize(); /* Synchronize with the host window system */
2766 if (!GetCapture() && ((wndPtr
->dwStyle
& WS_VISIBLE
) || (flags
& SWP_HIDEWINDOW
)))
2767 EVENT_DummyMotionNotify(); /* Simulate a mouse event to set the cursor */
2769 wndTemp
= WIN_GetDesktop();
2771 /* repaint invalidated region (if any)
2773 * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2774 * and force update after ChangeActiveWindow() to avoid painting frames twice.
2779 if( !(winpos
.flags
& SWP_NOREDRAW
) )
2781 if( uFlags
& SWP_EX_PAINTSELF
)
2783 PAINT_RedrawWindow( wndPtr
->hwndSelf
, NULL
, (visRgn
== 1) ? 0 : visRgn
, RDW_ERASE
| RDW_FRAME
|
2784 ((winpos
.flags
& SWP_DEFERERASE
) ? 0 : RDW_ERASENOW
) | RDW_INVALIDATE
|
2785 RDW_ALLCHILDREN
, RDW_EX_XYWINDOW
| RDW_EX_USEHRGN
);
2789 PAINT_RedrawWindow( wndPtr
->parent
->hwndSelf
, NULL
, (visRgn
== 1) ? 0 : visRgn
, RDW_ERASE
|
2790 ((winpos
.flags
& SWP_DEFERERASE
) ? 0 : RDW_ERASENOW
) | RDW_INVALIDATE
|
2791 RDW_ALLCHILDREN
, RDW_EX_USEHRGN
);
2795 DeleteObject( visRgn
);
2798 WIN_ReleaseDesktop();
2800 if (!(flags
& SWP_NOACTIVATE
))
2801 WINPOS_ChangeActiveWindow( winpos
.hwnd
, FALSE
);
2803 /* And last, send the WM_WINDOWPOSCHANGED message */
2805 TRACE(win
,"\tstatus flags = %04x\n", winpos
.flags
& SWP_AGG_STATUSFLAGS
);
2808 (((winpos
.flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOPOSCHANGE
) &&
2809 !(winpos
.flags
& SWP_NOSENDCHANGING
)) )
2811 SendMessageA( winpos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
)&winpos
);
2812 if (resync
) EVENT_Synchronize ();
2817 WIN_ReleaseWndPtr(wndPtr
);
2822 /***********************************************************************
2823 * BeginDeferWindowPos16 (USER.259)
2825 HDWP16 WINAPI
BeginDeferWindowPos16( INT16 count
)
2827 return BeginDeferWindowPos( count
);
2831 /***********************************************************************
2832 * BeginDeferWindowPos (USER32.9)
2834 HDWP WINAPI
BeginDeferWindowPos( INT count
)
2839 if (count
<= 0) return 0;
2840 handle
= USER_HEAP_ALLOC( sizeof(DWP
) + (count
-1)*sizeof(WINDOWPOS
) );
2841 if (!handle
) return 0;
2842 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( handle
);
2843 pDWP
->actualCount
= 0;
2844 pDWP
->suggestedCount
= count
;
2846 pDWP
->wMagic
= DWP_MAGIC
;
2847 pDWP
->hwndParent
= 0;
2852 /***********************************************************************
2853 * DeferWindowPos16 (USER.260)
2855 HDWP16 WINAPI
DeferWindowPos16( HDWP16 hdwp
, HWND16 hwnd
, HWND16 hwndAfter
,
2856 INT16 x
, INT16 y
, INT16 cx
, INT16 cy
,
2859 return DeferWindowPos( hdwp
, hwnd
, (INT
)(INT16
)hwndAfter
,
2860 x
, y
, cx
, cy
, flags
);
2864 /***********************************************************************
2865 * DeferWindowPos (USER32.128)
2867 HDWP WINAPI
DeferWindowPos( HDWP hdwp
, HWND hwnd
, HWND hwndAfter
,
2868 INT x
, INT y
, INT cx
, INT cy
,
2873 HDWP newhdwp
= hdwp
,retvalue
;
2877 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
2878 if (!pDWP
) return 0;
2879 if (hwnd
== GetDesktopWindow()) return 0;
2881 if (!(pWnd
=WIN_FindWndPtr( hwnd
))) {
2882 USER_HEAP_FREE( hdwp
);
2886 /* Numega Bounds Checker Demo dislikes the following code.
2887 In fact, I've not been able to find any "same parent" requirement in any docu
2891 /* All the windows of a DeferWindowPos() must have the same parent */
2892 parent
= pWnd
->parent
->hwndSelf
;
2893 if (pDWP
->actualCount
== 0) pDWP
->hwndParent
= parent
;
2894 else if (parent
!= pDWP
->hwndParent
)
2896 USER_HEAP_FREE( hdwp
);
2902 for (i
= 0; i
< pDWP
->actualCount
; i
++)
2904 if (pDWP
->winPos
[i
].hwnd
== hwnd
)
2906 /* Merge with the other changes */
2907 if (!(flags
& SWP_NOZORDER
))
2909 pDWP
->winPos
[i
].hwndInsertAfter
= hwndAfter
;
2911 if (!(flags
& SWP_NOMOVE
))
2913 pDWP
->winPos
[i
].x
= x
;
2914 pDWP
->winPos
[i
].y
= y
;
2916 if (!(flags
& SWP_NOSIZE
))
2918 pDWP
->winPos
[i
].cx
= cx
;
2919 pDWP
->winPos
[i
].cy
= cy
;
2921 pDWP
->winPos
[i
].flags
&= flags
| ~(SWP_NOSIZE
| SWP_NOMOVE
|
2922 SWP_NOZORDER
| SWP_NOREDRAW
|
2923 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
2925 pDWP
->winPos
[i
].flags
|= flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
|
2931 if (pDWP
->actualCount
>= pDWP
->suggestedCount
)
2933 newhdwp
= USER_HEAP_REALLOC( hdwp
,
2934 sizeof(DWP
) + pDWP
->suggestedCount
*sizeof(WINDOWPOS
) );
2940 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( newhdwp
);
2941 pDWP
->suggestedCount
++;
2943 pDWP
->winPos
[pDWP
->actualCount
].hwnd
= hwnd
;
2944 pDWP
->winPos
[pDWP
->actualCount
].hwndInsertAfter
= hwndAfter
;
2945 pDWP
->winPos
[pDWP
->actualCount
].x
= x
;
2946 pDWP
->winPos
[pDWP
->actualCount
].y
= y
;
2947 pDWP
->winPos
[pDWP
->actualCount
].cx
= cx
;
2948 pDWP
->winPos
[pDWP
->actualCount
].cy
= cy
;
2949 pDWP
->winPos
[pDWP
->actualCount
].flags
= flags
;
2950 pDWP
->actualCount
++;
2953 WIN_ReleaseWndPtr(pWnd
);
2958 /***********************************************************************
2959 * EndDeferWindowPos16 (USER.261)
2961 BOOL16 WINAPI
EndDeferWindowPos16( HDWP16 hdwp
)
2963 return EndDeferWindowPos( hdwp
);
2967 /***********************************************************************
2968 * EndDeferWindowPos (USER32.173)
2970 BOOL WINAPI
EndDeferWindowPos( HDWP hdwp
)
2977 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
2978 if (!pDWP
) return FALSE
;
2979 for (i
= 0, winpos
= pDWP
->winPos
; i
< pDWP
->actualCount
; i
++, winpos
++)
2981 if (!(res
= SetWindowPos( winpos
->hwnd
, winpos
->hwndInsertAfter
,
2982 winpos
->x
, winpos
->y
, winpos
->cx
,
2983 winpos
->cy
, winpos
->flags
))) break;
2985 USER_HEAP_FREE( hdwp
);
2990 /***********************************************************************
2991 * TileChildWindows (USER.199)
2993 void WINAPI
TileChildWindows16( HWND16 parent
, WORD action
)
2995 FIXME(win
, "(%04x, %d): stub\n", parent
, action
);
2998 /***********************************************************************
2999 * CascageChildWindows (USER.198)
3001 void WINAPI
CascadeChildWindows16( HWND16 parent
, WORD action
)
3003 FIXME(win
, "(%04x, %d): stub\n", parent
, action
);
3006 /***********************************************************************
3007 * SetProgmanWindow [USER32.522]
3009 HRESULT WINAPI
SetProgmanWindow ( HWND hwnd
)
3011 hGlobalProgmanWindow
= hwnd
;
3012 return hGlobalProgmanWindow
;
3015 /***********************************************************************
3016 * GetProgmanWindow [USER32.289]
3018 HRESULT WINAPI
GetProgmanWindow ( )
3020 return hGlobalProgmanWindow
;
3023 /***********************************************************************
3024 * SetShellWindowEx [USER32.531]
3025 * hwndProgman = Progman[Program Manager]
3026 * |-> SHELLDLL_DefView
3027 * hwndListView = | |-> SysListView32
3028 * | | |-> tooltips_class32
3034 HRESULT WINAPI
SetShellWindowEx ( HWND hwndProgman
, HWND hwndListView
)
3036 FIXME(win
,"0x%08x 0x%08x stub\n",hwndProgman
,hwndListView
);
3037 hGlobalShellWindow
= hwndProgman
;
3038 return hGlobalShellWindow
;
3042 /***********************************************************************
3043 * SetTaskmanWindow [USER32.537]
3045 * hwnd = MSTaskSwWClass
3046 * |-> SysTabControl32
3048 HRESULT WINAPI
SetTaskmanWindow ( HWND hwnd
)
3050 hGlobalTaskmanWindow
= hwnd
;
3051 return hGlobalTaskmanWindow
;
3054 /***********************************************************************
3055 * GetTaskmanWindow [USER32.304]
3057 HRESULT WINAPI
GetTaskmanWindow ( )
3059 return hGlobalTaskmanWindow
;