2 * Window position related functions.
4 * Copyright 1993, 1994, 1995 Alexandre Julliard
5 * 1995, 1996, 1999 Alex Korobka
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include "wine/winuser16.h"
28 #include "wine/server.h"
37 #include "nonclient.h"
38 #include "wine/debug.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(win
);
43 #define HAS_DLGFRAME(style,exStyle) \
44 (((exStyle) & WS_EX_DLGMODALFRAME) || \
45 (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
47 #define HAS_THICKFRAME(style) \
48 (((style) & WS_THICKFRAME) && \
49 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
51 #define EMPTYPOINT(pt) ((*(LONG*)&(pt)) == -1)
53 #define PLACE_MIN 0x0001
54 #define PLACE_MAX 0x0002
55 #define PLACE_RECT 0x0004
58 #define DWP_MAGIC ((INT)('W' | ('P' << 8) | ('O' << 16) | ('S' << 24)))
70 /* ----- internal variables ----- */
72 static HWND hwndPrevActive
= 0; /* Previously active window */
73 static HWND hGlobalShellWindow
=0; /*the shell*/
74 static HWND hGlobalTaskmanWindow
=0;
75 static HWND hGlobalProgmanWindow
=0;
77 static LPCSTR atomInternalPos
;
79 extern HQUEUE16 hActiveQueue
;
81 /***********************************************************************
82 * WINPOS_CreateInternalPosAtom
84 BOOL
WINPOS_CreateInternalPosAtom()
87 atomInternalPos
= (LPCSTR
)(DWORD
)GlobalAddAtomA(str
);
88 return (atomInternalPos
) ? TRUE
: FALSE
;
91 /***********************************************************************
92 * WINPOS_CheckInternalPos
94 * Called when a window is destroyed.
96 void WINPOS_CheckInternalPos( HWND hwnd
)
99 MESSAGEQUEUE
*pMsgQ
= 0;
100 WND
*wndPtr
= WIN_GetPtr( hwnd
);
102 if (!wndPtr
|| wndPtr
== WND_OTHER_PROCESS
) return;
104 lpPos
= (LPINTERNALPOS
) GetPropA( hwnd
, atomInternalPos
);
106 /* Retrieve the message queue associated with this window */
107 pMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( wndPtr
->hmemTaskQ
);
110 WARN("\tMessage queue not found. Exiting!\n" );
111 WIN_ReleasePtr( wndPtr
);
115 if( hwnd
== hwndPrevActive
) hwndPrevActive
= 0;
117 if( hwnd
== PERQDATA_GetActiveWnd( pMsgQ
->pQData
) )
119 PERQDATA_SetActiveWnd( pMsgQ
->pQData
, 0 );
120 WARN("\tattempt to activate destroyed window!\n");
125 if( IsWindow(lpPos
->hwndIconTitle
) )
126 DestroyWindow( lpPos
->hwndIconTitle
);
127 HeapFree( GetProcessHeap(), 0, lpPos
);
130 QUEUE_Unlock( pMsgQ
);
131 WIN_ReleasePtr( wndPtr
);
134 /***********************************************************************
135 * ArrangeIconicWindows (USER32.@)
137 UINT WINAPI
ArrangeIconicWindows( HWND parent
)
141 INT x
, y
, xspacing
, yspacing
;
143 GetClientRect( parent
, &rectParent
);
145 y
= rectParent
.bottom
;
146 xspacing
= GetSystemMetrics(SM_CXICONSPACING
);
147 yspacing
= GetSystemMetrics(SM_CYICONSPACING
);
149 hwndChild
= GetWindow( parent
, GW_CHILD
);
152 if( IsIconic( hwndChild
) )
154 WINPOS_ShowIconTitle( hwndChild
, FALSE
);
156 SetWindowPos( hwndChild
, 0, x
+ (xspacing
- GetSystemMetrics(SM_CXICON
)) / 2,
157 y
- yspacing
- GetSystemMetrics(SM_CYICON
)/2, 0, 0,
158 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
159 if( IsWindow(hwndChild
) )
160 WINPOS_ShowIconTitle(hwndChild
, TRUE
);
162 if (x
<= rectParent
.right
- xspacing
) x
+= xspacing
;
169 hwndChild
= GetWindow( hwndChild
, GW_HWNDNEXT
);
175 /***********************************************************************
176 * SwitchToThisWindow (USER32.@)
178 void WINAPI
SwitchToThisWindow( HWND hwnd
, BOOL restore
)
180 ShowWindow( hwnd
, restore
? SW_RESTORE
: SW_SHOWMINIMIZED
);
184 /***********************************************************************
185 * GetWindowRect (USER32.@)
187 BOOL WINAPI
GetWindowRect( HWND hwnd
, LPRECT rect
)
189 BOOL ret
= WIN_GetRectangles( hwnd
, rect
, NULL
);
192 MapWindowPoints( GetAncestor( hwnd
, GA_PARENT
), 0, (POINT
*)rect
, 2 );
193 TRACE( "hwnd %04x (%d,%d)-(%d,%d)\n",
194 hwnd
, rect
->left
, rect
->top
, rect
->right
, rect
->bottom
);
200 /***********************************************************************
201 * GetWindowRgn (USER32.@)
203 int WINAPI
GetWindowRgn ( HWND hwnd
, HRGN hrgn
)
206 WND
*wndPtr
= WIN_GetPtr( hwnd
);
208 if (wndPtr
== WND_OTHER_PROCESS
)
210 if (IsWindow( hwnd
))
211 FIXME( "not supported on other process window %x\n", hwnd
);
216 SetLastError( ERROR_INVALID_WINDOW_HANDLE
);
219 if (wndPtr
->hrgnWnd
) nRet
= CombineRgn( hrgn
, wndPtr
->hrgnWnd
, 0, RGN_COPY
);
220 WIN_ReleasePtr( wndPtr
);
225 /***********************************************************************
226 * SetWindowRgn (USER32.@)
228 int WINAPI
SetWindowRgn( HWND hwnd
, HRGN hrgn
, BOOL bRedraw
)
233 if (hrgn
) /* verify that region really exists */
235 if (GetRgnBox( hrgn
, &rect
) == ERROR
) return FALSE
;
238 if (USER_Driver
.pSetWindowRgn
)
239 return USER_Driver
.pSetWindowRgn( hwnd
, hrgn
, bRedraw
);
241 if ((wndPtr
= WIN_GetPtr( hwnd
)) == WND_OTHER_PROCESS
)
243 if (IsWindow( hwnd
))
244 FIXME( "not supported on other process window %x\n", hwnd
);
249 SetLastError( ERROR_INVALID_WINDOW_HANDLE
);
253 if (wndPtr
->hrgnWnd
== hrgn
)
255 WIN_ReleasePtr( wndPtr
);
261 /* delete previous region */
262 DeleteObject(wndPtr
->hrgnWnd
);
265 wndPtr
->hrgnWnd
= hrgn
;
266 WIN_ReleasePtr( wndPtr
);
268 /* Size the window to the rectangle of the new region (if it isn't NULL) */
269 if (hrgn
) SetWindowPos( hwnd
, 0, rect
.left
, rect
.top
,
270 rect
.right
- rect
.left
, rect
.bottom
- rect
.top
,
271 SWP_NOSIZE
| SWP_FRAMECHANGED
| SWP_NOMOVE
| SWP_NOACTIVATE
|
272 SWP_NOZORDER
| (bRedraw
? 0 : SWP_NOREDRAW
) );
277 /***********************************************************************
278 * GetClientRect (USER32.@)
280 BOOL WINAPI
GetClientRect( HWND hwnd
, LPRECT rect
)
284 rect
->right
= rect
->bottom
= 0;
285 if ((ret
= WIN_GetRectangles( hwnd
, NULL
, rect
)))
287 rect
->right
-= rect
->left
;
288 rect
->bottom
-= rect
->top
;
290 rect
->left
= rect
->top
= 0;
295 /*******************************************************************
296 * ClientToScreen (USER32.@)
298 BOOL WINAPI
ClientToScreen( HWND hwnd
, LPPOINT lppnt
)
300 MapWindowPoints( hwnd
, 0, lppnt
, 1 );
305 /*******************************************************************
306 * ScreenToClient (USER32.@)
308 BOOL WINAPI
ScreenToClient( HWND hwnd
, LPPOINT lppnt
)
310 MapWindowPoints( 0, hwnd
, lppnt
, 1 );
315 /***********************************************************************
316 * find_child_from_point
318 * Find the child that contains pt. Helper for WindowFromPoint.
319 * pt is in parent client coordinates.
320 * lparam is the param to pass in the WM_NCHITTEST message.
322 static HWND
find_child_from_point( HWND parent
, POINT pt
, INT
*hittest
, LPARAM lparam
)
326 RECT rectWindow
, rectClient
;
328 HWND
*list
= WIN_ListChildren( parent
);
331 for (i
= 0; list
[i
]; i
++)
333 /* If point is in window, and window is visible, and it */
334 /* is enabled (or it's a top-level window), then explore */
335 /* its children. Otherwise, go to the next window. */
337 style
= GetWindowLongW( list
[i
], GWL_STYLE
);
338 if (!(style
& WS_VISIBLE
)) continue; /* not visible -> skip */
339 if ((style
& (WS_POPUP
| WS_CHILD
| WS_DISABLED
)) == (WS_CHILD
| WS_DISABLED
))
340 continue; /* disabled child -> skip */
341 exstyle
= GetWindowLongW( list
[i
], GWL_EXSTYLE
);
342 if ((exstyle
& (WS_EX_LAYERED
| WS_EX_TRANSPARENT
)) == (WS_EX_LAYERED
| WS_EX_TRANSPARENT
))
343 continue; /* transparent -> skip */
345 if (!WIN_GetRectangles( list
[i
], &rectWindow
, &rectClient
)) continue;
346 if (!PtInRect( &rectWindow
, pt
)) continue; /* not in window -> skip */
348 /* FIXME: check window region for other processes too */
349 if ((wndPtr
= WIN_GetPtr( list
[i
] )) && wndPtr
!= WND_OTHER_PROCESS
)
351 if (wndPtr
->hrgnWnd
&& !PtInRegion( wndPtr
->hrgnWnd
,
352 pt
.x
- rectWindow
.left
, pt
.y
- rectWindow
.top
))
354 WIN_ReleasePtr( wndPtr
);
355 continue; /* point outside window region -> skip */
357 WIN_ReleasePtr( wndPtr
);
360 /* If window is minimized or disabled, return at once */
361 if (style
& WS_MINIMIZE
)
363 *hittest
= HTCAPTION
;
366 if (style
& WS_DISABLED
)
372 /* If point is in client area, explore children */
373 if (PtInRect( &rectClient
, pt
))
378 new_pt
.x
= pt
.x
- rectClient
.left
;
379 new_pt
.y
= pt
.y
- rectClient
.top
;
380 if ((ret
= find_child_from_point( list
[i
], new_pt
, hittest
, lparam
)))
384 /* Now it's inside window, send WM_NCCHITTEST (if same thread) */
385 if (!WIN_IsCurrentThread( list
[i
] ))
390 if ((res
= SendMessageA( list
[i
], WM_NCHITTEST
, 0, lparam
)) != HTTRANSPARENT
)
392 *hittest
= res
; /* Found the window */
395 /* continue search with next sibling */
401 /***********************************************************************
402 * WINPOS_WindowFromPoint
404 * Find the window and hittest for a given point.
406 HWND
WINPOS_WindowFromPoint( HWND hwndScope
, POINT pt
, INT
*hittest
)
412 TRACE("scope %04x %ld,%ld\n", hwndScope
, pt
.x
, pt
.y
);
414 if (!hwndScope
) hwndScope
= GetDesktopWindow();
415 style
= GetWindowLongW( hwndScope
, GWL_STYLE
);
418 if (style
& WS_DISABLED
) return 0;
420 MapWindowPoints( GetDesktopWindow(), GetAncestor( hwndScope
, GA_PARENT
), &xy
, 1 );
422 if (!(style
& WS_MINIMIZE
))
425 if (WIN_GetRectangles( hwndScope
, NULL
, &rectClient
) && PtInRect( &rectClient
, xy
))
429 xy
.x
-= rectClient
.left
;
430 xy
.y
-= rectClient
.top
;
431 if ((ret
= find_child_from_point( hwndScope
, xy
, hittest
, MAKELONG( pt
.x
, pt
.y
) )))
433 TRACE( "found child %x\n", ret
);
439 /* If nothing found, try the scope window */
440 if (!WIN_IsCurrentThread( hwndScope
))
443 TRACE( "returning %x\n", hwndScope
);
446 res
= SendMessageA( hwndScope
, WM_NCHITTEST
, 0, MAKELONG( pt
.x
, pt
.y
) );
447 if (res
!= HTTRANSPARENT
)
449 *hittest
= res
; /* Found the window */
450 TRACE( "returning %x\n", hwndScope
);
453 *hittest
= HTNOWHERE
;
454 TRACE( "nothing found\n" );
459 /*******************************************************************
460 * WindowFromPoint (USER32.@)
462 HWND WINAPI
WindowFromPoint( POINT pt
)
465 return WINPOS_WindowFromPoint( 0, pt
, &hittest
);
469 /*******************************************************************
470 * ChildWindowFromPoint (USER32.@)
472 HWND WINAPI
ChildWindowFromPoint( HWND hwndParent
, POINT pt
)
474 return ChildWindowFromPointEx( hwndParent
, pt
, CWP_ALL
);
477 /*******************************************************************
478 * ChildWindowFromPointEx (USER32.@)
480 HWND WINAPI
ChildWindowFromPointEx( HWND hwndParent
, POINT pt
, UINT uFlags
)
482 /* pt is in the client coordinates */
488 GetClientRect( hwndParent
, &rect
);
489 if (!PtInRect( &rect
, pt
)) return 0;
490 if (!(list
= WIN_ListChildren( hwndParent
))) return 0;
492 for (i
= 0; list
[i
]; i
++)
494 if (!WIN_GetRectangles( list
[i
], &rect
, NULL
)) continue;
495 if (!PtInRect( &rect
, pt
)) continue;
496 if (uFlags
& (CWP_SKIPINVISIBLE
|CWP_SKIPDISABLED
))
498 LONG style
= GetWindowLongW( list
[i
], GWL_STYLE
);
499 if ((uFlags
& CWP_SKIPINVISIBLE
) && !(style
& WS_VISIBLE
)) continue;
500 if ((uFlags
& CWP_SKIPDISABLED
) && (style
& WS_DISABLED
)) continue;
502 if (uFlags
& CWP_SKIPTRANSPARENT
)
504 if (GetWindowLongW( list
[i
], GWL_EXSTYLE
) & WS_EX_TRANSPARENT
) continue;
509 HeapFree( GetProcessHeap(), 0, list
);
510 if (!retvalue
) retvalue
= hwndParent
;
515 /*******************************************************************
516 * WINPOS_GetWinOffset
518 * Calculate the offset between the origin of the two windows. Used
519 * to implement MapWindowPoints.
521 static void WINPOS_GetWinOffset( HWND hwndFrom
, HWND hwndTo
, POINT
*offset
)
525 offset
->x
= offset
->y
= 0;
527 /* Translate source window origin to screen coords */
530 HWND hwnd
= hwndFrom
;
534 if (hwnd
== hwndTo
) return;
535 if (!(wndPtr
= WIN_GetPtr( hwnd
)))
537 ERR( "bad hwndFrom = %04x\n", hwnd
);
540 if (wndPtr
== WND_OTHER_PROCESS
) goto other_process
;
541 offset
->x
+= wndPtr
->rectClient
.left
;
542 offset
->y
+= wndPtr
->rectClient
.top
;
543 hwnd
= wndPtr
->parent
;
544 WIN_ReleasePtr( wndPtr
);
548 /* Translate origin to destination window coords */
555 if (!(wndPtr
= WIN_GetPtr( hwnd
)))
557 ERR( "bad hwndTo = %04x\n", hwnd
);
560 if (wndPtr
== WND_OTHER_PROCESS
) goto other_process
;
561 offset
->x
-= wndPtr
->rectClient
.left
;
562 offset
->y
-= wndPtr
->rectClient
.top
;
563 hwnd
= wndPtr
->parent
;
564 WIN_ReleasePtr( wndPtr
);
569 other_process
: /* one of the parents may belong to another process, do it the hard way */
570 offset
->x
= offset
->y
= 0;
571 SERVER_START_REQ( get_windows_offset
)
573 req
->from
= hwndFrom
;
575 if (!wine_server_call( req
))
577 offset
->x
= reply
->x
;
578 offset
->y
= reply
->y
;
585 /*******************************************************************
586 * MapWindowPoints (USER.258)
588 void WINAPI
MapWindowPoints16( HWND16 hwndFrom
, HWND16 hwndTo
,
589 LPPOINT16 lppt
, UINT16 count
)
593 WINPOS_GetWinOffset( WIN_Handle32(hwndFrom
), WIN_Handle32(hwndTo
), &offset
);
603 /*******************************************************************
604 * MapWindowPoints (USER32.@)
606 INT WINAPI
MapWindowPoints( HWND hwndFrom
, HWND hwndTo
, LPPOINT lppt
, UINT count
)
610 WINPOS_GetWinOffset( hwndFrom
, hwndTo
, &offset
);
617 return MAKELONG( LOWORD(offset
.x
), LOWORD(offset
.y
) );
621 /***********************************************************************
622 * IsIconic (USER32.@)
624 BOOL WINAPI
IsIconic(HWND hWnd
)
626 return (GetWindowLongW( hWnd
, GWL_STYLE
) & WS_MINIMIZE
) != 0;
630 /***********************************************************************
631 * IsZoomed (USER32.@)
633 BOOL WINAPI
IsZoomed(HWND hWnd
)
635 return (GetWindowLongW( hWnd
, GWL_STYLE
) & WS_MAXIMIZE
) != 0;
639 /*******************************************************************
640 * GetActiveWindow (USER32.@)
642 HWND WINAPI
GetActiveWindow(void)
644 MESSAGEQUEUE
*pCurMsgQ
= 0;
646 /* Get the messageQ for the current thread */
647 if (!(pCurMsgQ
= QUEUE_Current()))
649 WARN("\tCurrent message queue not found. Exiting!\n" );
653 /* Return the current active window from the perQ data of the current message Q */
654 return PERQDATA_GetActiveWnd( pCurMsgQ
->pQData
);
658 /*******************************************************************
661 static BOOL
WINPOS_CanActivate(HWND hwnd
)
663 if (!hwnd
) return FALSE
;
664 return ((GetWindowLongW( hwnd
, GWL_STYLE
) & (WS_DISABLED
|WS_CHILD
)) == 0);
667 /*******************************************************************
670 static BOOL
WINPOS_IsVisible(HWND hwnd
)
672 if (!hwnd
) return FALSE
;
673 return ((GetWindowLongW( hwnd
, GWL_STYLE
) & WS_VISIBLE
) == WS_VISIBLE
);
677 /*******************************************************************
678 * SetActiveWindow (USER32.@)
680 HWND WINAPI
SetActiveWindow( HWND hwnd
)
683 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
684 MESSAGEQUEUE
*pMsgQ
= 0, *pCurMsgQ
= 0;
686 if (!wndPtr
) return 0;
688 if (wndPtr
->dwStyle
& (WS_DISABLED
| WS_CHILD
)) goto error
;
690 /* Get the messageQ for the current thread */
691 if (!(pCurMsgQ
= QUEUE_Current()))
693 WARN("\tCurrent message queue not found. Exiting!\n" );
697 /* Retrieve the message queue associated with this window */
698 pMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( wndPtr
->hmemTaskQ
);
701 WARN("\tWindow message queue not found. Exiting!\n" );
705 /* Make sure that the window is associated with the calling threads
706 * message queue. It must share the same perQ data.
708 if ( pCurMsgQ
->pQData
!= pMsgQ
->pQData
)
710 QUEUE_Unlock( pMsgQ
);
714 /* Save current active window */
715 prev
= PERQDATA_GetActiveWnd( pMsgQ
->pQData
);
716 QUEUE_Unlock( pMsgQ
);
717 WIN_ReleaseWndPtr(wndPtr
);
718 WINPOS_SetActiveWindow( hwnd
, FALSE
, TRUE
);
722 WIN_ReleaseWndPtr(wndPtr
);
727 /*******************************************************************
728 * GetForegroundWindow (USER32.@)
730 HWND WINAPI
GetForegroundWindow(void)
734 /* Get the foreground window (active window of hActiveQueue) */
737 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
739 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
741 QUEUE_Unlock( pActiveQueue
);
747 /*******************************************************************
748 * SetForegroundWindow (USER32.@)
750 BOOL WINAPI
SetForegroundWindow( HWND hwnd
)
752 if (!hwnd
) return WINPOS_SetActiveWindow( 0, FALSE
, TRUE
);
754 /* child windows get WM_CHILDACTIVATE message */
755 if ((GetWindowLongW( hwnd
, GWL_STYLE
) & (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
756 return SendMessageA( hwnd
, WM_CHILDACTIVATE
, 0, 0 );
758 hwnd
= WIN_GetFullHandle( hwnd
);
759 if( hwnd
== GetForegroundWindow() ) return FALSE
;
761 return WINPOS_SetActiveWindow( hwnd
, FALSE
, TRUE
);
765 /*******************************************************************
766 * AllowSetForegroundWindow (USER32.@)
768 BOOL WINAPI
AllowSetForegroundWindow( DWORD procid
)
770 /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
771 * implemented, then fix this function. */
776 /*******************************************************************
777 * LockSetForegroundWindow (USER32.@)
779 BOOL WINAPI
LockSetForegroundWindow( UINT lockcode
)
781 /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
782 * implemented, then fix this function. */
787 /*******************************************************************
788 * SetShellWindow (USER32.@)
790 HWND WINAPI
SetShellWindow(HWND hwndshell
)
791 { WARN("(hWnd=%08x) semi stub\n",hwndshell
);
793 hGlobalShellWindow
= WIN_GetFullHandle( hwndshell
);
794 return hGlobalShellWindow
;
798 /*******************************************************************
799 * GetShellWindow (USER32.@)
801 HWND WINAPI
GetShellWindow(void)
802 { WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow
);
804 return hGlobalShellWindow
;
808 /***********************************************************************
809 * BringWindowToTop (USER32.@)
811 BOOL WINAPI
BringWindowToTop( HWND hwnd
)
813 return SetWindowPos( hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
);
817 /***********************************************************************
818 * MoveWindow (USER32.@)
820 BOOL WINAPI
MoveWindow( HWND hwnd
, INT x
, INT y
, INT cx
, INT cy
,
823 int flags
= SWP_NOZORDER
| SWP_NOACTIVATE
;
824 if (!repaint
) flags
|= SWP_NOREDRAW
;
825 TRACE("%04x %d,%d %dx%d %d\n",
826 hwnd
, x
, y
, cx
, cy
, repaint
);
827 return SetWindowPos( hwnd
, 0, x
, y
, cx
, cy
, flags
);
830 /***********************************************************************
831 * WINPOS_InitInternalPos
833 static LPINTERNALPOS
WINPOS_InitInternalPos( WND
* wnd
, POINT pt
, const RECT
*restoreRect
)
835 LPINTERNALPOS lpPos
= (LPINTERNALPOS
) GetPropA( wnd
->hwndSelf
,
839 /* this happens when the window is minimized/maximized
840 * for the first time (rectWindow is not adjusted yet) */
842 lpPos
= HeapAlloc( GetProcessHeap(), 0, sizeof(INTERNALPOS
) );
843 if( !lpPos
) return NULL
;
845 SetPropA( wnd
->hwndSelf
, atomInternalPos
, (HANDLE
)lpPos
);
846 lpPos
->hwndIconTitle
= 0; /* defer until needs to be shown */
847 CONV_RECT32TO16( &wnd
->rectWindow
, &lpPos
->rectNormal
);
848 *(UINT
*)&lpPos
->ptIconPos
= *(UINT
*)&lpPos
->ptMaxPos
= 0xFFFFFFFF;
851 if( wnd
->dwStyle
& WS_MINIMIZE
)
852 CONV_POINT32TO16( &pt
, &lpPos
->ptIconPos
);
853 else if( wnd
->dwStyle
& WS_MAXIMIZE
)
854 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
855 else if( restoreRect
)
856 CONV_RECT32TO16( restoreRect
, &lpPos
->rectNormal
);
861 /***********************************************************************
862 * WINPOS_RedrawIconTitle
864 BOOL
WINPOS_RedrawIconTitle( HWND hWnd
)
866 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)GetPropA( hWnd
, atomInternalPos
);
869 if( lpPos
->hwndIconTitle
)
871 SendMessageA( lpPos
->hwndIconTitle
, WM_SHOWWINDOW
, TRUE
, 0);
872 InvalidateRect( lpPos
->hwndIconTitle
, NULL
, TRUE
);
879 /***********************************************************************
880 * WINPOS_ShowIconTitle
882 BOOL
WINPOS_ShowIconTitle( HWND hwnd
, BOOL bShow
)
884 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)GetPropA( hwnd
, atomInternalPos
);
886 if( lpPos
&& !(GetWindowLongA( hwnd
, GWL_EXSTYLE
) & WS_EX_MANAGED
))
888 HWND title
= lpPos
->hwndIconTitle
;
890 TRACE("0x%04x %i\n", hwnd
, (bShow
!= 0) );
893 lpPos
->hwndIconTitle
= title
= ICONTITLE_Create( hwnd
);
896 if (!IsWindowVisible(title
))
898 SendMessageA( title
, WM_SHOWWINDOW
, TRUE
, 0 );
899 SetWindowPos( title
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
900 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_SHOWWINDOW
);
903 else ShowWindow( title
, SW_HIDE
);
908 /*******************************************************************
909 * WINPOS_GetMinMaxInfo
911 * Get the minimized and maximized information for a window.
913 void WINPOS_GetMinMaxInfo( HWND hwnd
, POINT
*maxSize
, POINT
*maxPos
,
914 POINT
*minTrack
, POINT
*maxTrack
)
919 LONG style
= GetWindowLongA( hwnd
, GWL_STYLE
);
920 LONG exstyle
= GetWindowLongA( hwnd
, GWL_EXSTYLE
);
922 /* Compute default values */
924 MinMax
.ptMaxSize
.x
= GetSystemMetrics(SM_CXSCREEN
);
925 MinMax
.ptMaxSize
.y
= GetSystemMetrics(SM_CYSCREEN
);
926 MinMax
.ptMinTrackSize
.x
= GetSystemMetrics(SM_CXMINTRACK
);
927 MinMax
.ptMinTrackSize
.y
= GetSystemMetrics(SM_CYMINTRACK
);
928 MinMax
.ptMaxTrackSize
.x
= GetSystemMetrics(SM_CXSCREEN
);
929 MinMax
.ptMaxTrackSize
.y
= GetSystemMetrics(SM_CYSCREEN
);
931 if (HAS_DLGFRAME( style
, exstyle
))
933 xinc
= GetSystemMetrics(SM_CXDLGFRAME
);
934 yinc
= GetSystemMetrics(SM_CYDLGFRAME
);
939 if (HAS_THICKFRAME(style
))
941 xinc
+= GetSystemMetrics(SM_CXFRAME
);
942 yinc
+= GetSystemMetrics(SM_CYFRAME
);
944 if (style
& WS_BORDER
)
946 xinc
+= GetSystemMetrics(SM_CXBORDER
);
947 yinc
+= GetSystemMetrics(SM_CYBORDER
);
950 MinMax
.ptMaxSize
.x
+= 2 * xinc
;
951 MinMax
.ptMaxSize
.y
+= 2 * yinc
;
953 lpPos
= (LPINTERNALPOS
)GetPropA( hwnd
, atomInternalPos
);
954 if( lpPos
&& !EMPTYPOINT(lpPos
->ptMaxPos
) )
955 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &MinMax
.ptMaxPosition
);
958 MinMax
.ptMaxPosition
.x
= -xinc
;
959 MinMax
.ptMaxPosition
.y
= -yinc
;
962 SendMessageA( hwnd
, WM_GETMINMAXINFO
, 0, (LPARAM
)&MinMax
);
964 /* Some sanity checks */
966 TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
967 MinMax
.ptMaxSize
.x
, MinMax
.ptMaxSize
.y
,
968 MinMax
.ptMaxPosition
.x
, MinMax
.ptMaxPosition
.y
,
969 MinMax
.ptMaxTrackSize
.x
, MinMax
.ptMaxTrackSize
.y
,
970 MinMax
.ptMinTrackSize
.x
, MinMax
.ptMinTrackSize
.y
);
971 MinMax
.ptMaxTrackSize
.x
= max( MinMax
.ptMaxTrackSize
.x
,
972 MinMax
.ptMinTrackSize
.x
);
973 MinMax
.ptMaxTrackSize
.y
= max( MinMax
.ptMaxTrackSize
.y
,
974 MinMax
.ptMinTrackSize
.y
);
976 if (maxSize
) *maxSize
= MinMax
.ptMaxSize
;
977 if (maxPos
) *maxPos
= MinMax
.ptMaxPosition
;
978 if (minTrack
) *minTrack
= MinMax
.ptMinTrackSize
;
979 if (maxTrack
) *maxTrack
= MinMax
.ptMaxTrackSize
;
982 /***********************************************************************
983 * ShowWindowAsync (USER32.@)
985 * doesn't wait; returns immediately.
986 * used by threads to toggle windows in other (possibly hanging) threads
988 BOOL WINAPI
ShowWindowAsync( HWND hwnd
, INT cmd
)
990 /* FIXME: does ShowWindow() return immediately ? */
991 return ShowWindow(hwnd
, cmd
);
995 /***********************************************************************
996 * ShowWindow (USER32.@)
998 BOOL WINAPI
ShowWindow( HWND hwnd
, INT cmd
)
1002 if ((full_handle
= WIN_IsCurrentThread( hwnd
)))
1003 return USER_Driver
.pShowWindow( full_handle
, cmd
);
1004 return SendMessageW( hwnd
, WM_WINE_SHOWWINDOW
, cmd
, 0 );
1008 /***********************************************************************
1009 * GetInternalWindowPos (USER.460)
1011 UINT16 WINAPI
GetInternalWindowPos16( HWND16 hwnd
, LPRECT16 rectWnd
,
1014 WINDOWPLACEMENT16 wndpl
;
1015 if (GetWindowPlacement16( hwnd
, &wndpl
))
1017 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
1018 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
1019 return wndpl
.showCmd
;
1025 /***********************************************************************
1026 * GetInternalWindowPos (USER32.@)
1028 UINT WINAPI
GetInternalWindowPos( HWND hwnd
, LPRECT rectWnd
,
1031 WINDOWPLACEMENT wndpl
;
1032 if (GetWindowPlacement( hwnd
, &wndpl
))
1034 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
1035 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
1036 return wndpl
.showCmd
;
1042 /***********************************************************************
1043 * GetWindowPlacement (USER32.@)
1046 * Fails if wndpl->length of Win95 (!) apps is invalid.
1048 BOOL WINAPI
GetWindowPlacement( HWND hwnd
, WINDOWPLACEMENT
*wndpl
)
1050 WND
*pWnd
= WIN_FindWndPtr( hwnd
);
1051 LPINTERNALPOS lpPos
;
1053 if(!pWnd
) return FALSE
;
1055 lpPos
= WINPOS_InitInternalPos( pWnd
, *(LPPOINT
)&pWnd
->rectWindow
.left
, &pWnd
->rectWindow
);
1056 wndpl
->length
= sizeof(*wndpl
);
1057 if( pWnd
->dwStyle
& WS_MINIMIZE
)
1058 wndpl
->showCmd
= SW_SHOWMINIMIZED
;
1060 wndpl
->showCmd
= ( pWnd
->dwStyle
& WS_MAXIMIZE
) ? SW_SHOWMAXIMIZED
: SW_SHOWNORMAL
;
1061 if( pWnd
->flags
& WIN_RESTORE_MAX
)
1062 wndpl
->flags
= WPF_RESTORETOMAXIMIZED
;
1065 CONV_POINT16TO32( &lpPos
->ptIconPos
, &wndpl
->ptMinPosition
);
1066 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &wndpl
->ptMaxPosition
);
1067 CONV_RECT16TO32( &lpPos
->rectNormal
, &wndpl
->rcNormalPosition
);
1068 WIN_ReleaseWndPtr(pWnd
);
1073 /***********************************************************************
1074 * WINPOS_SetPlacement
1076 static BOOL
WINPOS_SetPlacement( HWND hwnd
, const WINDOWPLACEMENT
*wndpl
, UINT flags
)
1078 WND
*pWnd
= WIN_FindWndPtr( hwnd
);
1081 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)WINPOS_InitInternalPos( pWnd
,
1082 *(LPPOINT
)&pWnd
->rectWindow
.left
, &pWnd
->rectWindow
);
1084 if( flags
& PLACE_MIN
) CONV_POINT32TO16( &wndpl
->ptMinPosition
, &lpPos
->ptIconPos
);
1085 if( flags
& PLACE_MAX
) CONV_POINT32TO16( &wndpl
->ptMaxPosition
, &lpPos
->ptMaxPos
);
1086 if( flags
& PLACE_RECT
) CONV_RECT32TO16( &wndpl
->rcNormalPosition
, &lpPos
->rectNormal
);
1088 if( pWnd
->dwStyle
& WS_MINIMIZE
)
1090 WINPOS_ShowIconTitle( pWnd
->hwndSelf
, FALSE
);
1091 if( wndpl
->flags
& WPF_SETMINPOSITION
&& !EMPTYPOINT(lpPos
->ptIconPos
))
1092 SetWindowPos( hwnd
, 0, lpPos
->ptIconPos
.x
, lpPos
->ptIconPos
.y
,
1093 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1095 else if( pWnd
->dwStyle
& WS_MAXIMIZE
)
1097 if( !EMPTYPOINT(lpPos
->ptMaxPos
) )
1098 SetWindowPos( hwnd
, 0, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
,
1099 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1101 else if( flags
& PLACE_RECT
)
1102 SetWindowPos( hwnd
, 0, lpPos
->rectNormal
.left
, lpPos
->rectNormal
.top
,
1103 lpPos
->rectNormal
.right
- lpPos
->rectNormal
.left
,
1104 lpPos
->rectNormal
.bottom
- lpPos
->rectNormal
.top
,
1105 SWP_NOZORDER
| SWP_NOACTIVATE
);
1107 ShowWindow( hwnd
, wndpl
->showCmd
);
1108 if( IsWindow(hwnd
) && pWnd
->dwStyle
& WS_MINIMIZE
)
1110 if( pWnd
->dwStyle
& WS_VISIBLE
) WINPOS_ShowIconTitle( pWnd
->hwndSelf
, TRUE
);
1112 /* SDK: ...valid only the next time... */
1113 if( wndpl
->flags
& WPF_RESTORETOMAXIMIZED
) pWnd
->flags
|= WIN_RESTORE_MAX
;
1115 WIN_ReleaseWndPtr(pWnd
);
1122 /***********************************************************************
1123 * SetWindowPlacement (USER32.@)
1126 * Fails if wndpl->length of Win95 (!) apps is invalid.
1128 BOOL WINAPI
SetWindowPlacement( HWND hwnd
, const WINDOWPLACEMENT
*wpl
)
1130 if (!wpl
) return FALSE
;
1131 return WINPOS_SetPlacement( hwnd
, wpl
, PLACE_MIN
| PLACE_MAX
| PLACE_RECT
);
1135 /***********************************************************************
1136 * AnimateWindow (USER32.@)
1137 * Shows/Hides a window with an animation
1140 BOOL WINAPI
AnimateWindow(HWND hwnd
, DWORD dwTime
, DWORD dwFlags
)
1142 FIXME("partial stub\n");
1144 /* If trying to show/hide and it's already *
1145 * shown/hidden or invalid window, fail with *
1146 * invalid parameter */
1147 if(!IsWindow(hwnd
) ||
1148 (IsWindowVisible(hwnd
) && !(dwFlags
& AW_HIDE
)) ||
1149 (!IsWindowVisible(hwnd
) && (dwFlags
& AW_HIDE
)))
1151 SetLastError(ERROR_INVALID_PARAMETER
);
1155 ShowWindow(hwnd
, (dwFlags
& AW_HIDE
) ? SW_HIDE
: ((dwFlags
& AW_ACTIVATE
) ? SW_SHOW
: SW_SHOWNA
));
1160 /***********************************************************************
1161 * SetInternalWindowPos (USER32.@)
1163 void WINAPI
SetInternalWindowPos( HWND hwnd
, UINT showCmd
,
1164 LPRECT rect
, LPPOINT pt
)
1166 if( IsWindow(hwnd
) )
1168 WINDOWPLACEMENT wndpl
;
1171 wndpl
.length
= sizeof(wndpl
);
1172 wndpl
.showCmd
= showCmd
;
1173 wndpl
.flags
= flags
= 0;
1178 wndpl
.flags
|= WPF_SETMINPOSITION
;
1179 wndpl
.ptMinPosition
= *pt
;
1183 flags
|= PLACE_RECT
;
1184 wndpl
.rcNormalPosition
= *rect
;
1186 WINPOS_SetPlacement( hwnd
, &wndpl
, flags
);
1190 /*******************************************************************
1191 * WINPOS_SetActiveWindow
1193 * SetActiveWindow() back-end. This is the only function that
1194 * can assign active status to a window. It must be called only
1195 * for the top level windows.
1197 BOOL
WINPOS_SetActiveWindow( HWND hWnd
, BOOL fMouse
, BOOL fChangeFocus
)
1199 WND
* wndPtr
=0, *wndTemp
;
1200 HQUEUE16 hOldActiveQueue
, hNewActiveQueue
;
1201 MESSAGEQUEUE
*pOldActiveQueue
= 0, *pNewActiveQueue
= 0;
1203 HWND hwndActive
= 0;
1206 TRACE("(%04x, %d, %d)\n", hWnd
, fMouse
, fChangeFocus
);
1208 /* Get current active window from the active queue */
1211 pOldActiveQueue
= QUEUE_Lock( hActiveQueue
);
1212 if ( pOldActiveQueue
)
1213 hwndActive
= PERQDATA_GetActiveWnd( pOldActiveQueue
->pQData
);
1216 if ((wndPtr
= WIN_FindWndPtr(hWnd
)))
1217 hWnd
= wndPtr
->hwndSelf
; /* make it a full handle */
1219 /* paranoid checks */
1220 if( hWnd
== GetDesktopWindow() || (bRet
= (hWnd
== hwndActive
)) )
1223 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1226 hOldActiveQueue
= hActiveQueue
;
1228 if( (wndTemp
= WIN_FindWndPtr(hwndActive
)) )
1230 wIconized
= HIWORD(wndTemp
->dwStyle
& WS_MINIMIZE
);
1231 WIN_ReleaseWndPtr(wndTemp
);
1234 TRACE("no current active window.\n");
1236 /* call CBT hook chain */
1237 if (HOOK_IsHooked( WH_CBT
))
1239 CBTACTIVATESTRUCT cbt
;
1240 cbt
.fMouse
= fMouse
;
1241 cbt
.hWndActive
= hwndActive
;
1242 if (HOOK_CallHooksA( WH_CBT
, HCBT_ACTIVATE
, (WPARAM
)hWnd
, (LPARAM
)&cbt
)) goto CLEANUP_END
;
1245 /* set prev active wnd to current active wnd and send notification */
1246 if ((hwndPrevActive
= hwndActive
) && IsWindow(hwndPrevActive
))
1248 MESSAGEQUEUE
*pTempActiveQueue
= 0;
1250 SendNotifyMessageA( hwndPrevActive
, WM_NCACTIVATE
, FALSE
, 0 );
1251 SendNotifyMessageA( hwndPrevActive
, WM_ACTIVATE
,
1252 MAKEWPARAM( WA_INACTIVE
, wIconized
),
1255 /* check if something happened during message processing
1256 * (global active queue may have changed)
1258 pTempActiveQueue
= QUEUE_Lock( hActiveQueue
);
1259 if(!pTempActiveQueue
)
1262 hwndActive
= PERQDATA_GetActiveWnd( pTempActiveQueue
->pQData
);
1263 QUEUE_Unlock( pTempActiveQueue
);
1264 if( hwndPrevActive
!= hwndActive
)
1268 /* Set new active window in the message queue */
1272 pNewActiveQueue
= QUEUE_Lock( wndPtr
->hmemTaskQ
);
1273 if ( pNewActiveQueue
)
1274 PERQDATA_SetActiveWnd( pNewActiveQueue
->pQData
, hwndActive
);
1276 else /* have to do this or MDI frame activation goes to hell */
1277 if( pOldActiveQueue
)
1278 PERQDATA_SetActiveWnd( pOldActiveQueue
->pQData
, 0 );
1280 /* send palette messages */
1281 if (hWnd
&& SendMessageW( hWnd
, WM_QUERYNEWPALETTE
, 0, 0L))
1282 SendMessageW( HWND_BROADCAST
, WM_PALETTEISCHANGING
, (WPARAM
)hWnd
, 0 );
1284 /* if prev wnd is minimized redraw icon title */
1285 if( IsIconic( hwndPrevActive
) ) WINPOS_RedrawIconTitle(hwndPrevActive
);
1287 /* managed windows will get ConfigureNotify event */
1288 if (wndPtr
&& !(wndPtr
->dwStyle
& WS_CHILD
) && !(wndPtr
->dwExStyle
& WS_EX_MANAGED
))
1290 /* check Z-order and bring hWnd to the top */
1291 HWND tmp
= GetTopWindow(0);
1292 while (tmp
&& !(GetWindowLongA( tmp
, GWL_STYLE
) & WS_VISIBLE
))
1293 tmp
= GetWindow( tmp
, GW_HWNDNEXT
);
1296 SetWindowPos(hWnd
, HWND_TOP
, 0,0,0,0,
1297 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
1298 if (!IsWindow(hWnd
))
1302 /* Get a handle to the new active queue */
1303 hNewActiveQueue
= wndPtr
? wndPtr
->hmemTaskQ
: 0;
1305 /* send WM_ACTIVATEAPP if necessary */
1306 if (hOldActiveQueue
!= hNewActiveQueue
)
1309 DWORD old_thread
= GetWindowThreadProcessId( hwndPrevActive
, NULL
);
1310 DWORD new_thread
= GetWindowThreadProcessId( hwndActive
, NULL
);
1312 if ((list
= WIN_ListChildren( GetDesktopWindow() )))
1314 for (phwnd
= list
; *phwnd
; phwnd
++)
1316 if (!IsWindow( *phwnd
)) continue;
1317 if (GetWindowThreadProcessId( *phwnd
, NULL
) == old_thread
)
1318 SendNotifyMessageW( *phwnd
, WM_ACTIVATEAPP
, 0, new_thread
);
1320 HeapFree( GetProcessHeap(), 0, list
);
1323 hActiveQueue
= hNewActiveQueue
;
1325 if ((list
= WIN_ListChildren( GetDesktopWindow() )))
1327 for (phwnd
= list
; *phwnd
; phwnd
++)
1329 if (!IsWindow( *phwnd
)) continue;
1330 if (GetWindowThreadProcessId( *phwnd
, NULL
) == new_thread
)
1331 SendMessageW( *phwnd
, WM_ACTIVATEAPP
, 1, old_thread
);
1333 HeapFree( GetProcessHeap(), 0, list
);
1336 if (hWnd
&& !IsWindow(hWnd
)) goto CLEANUP
;
1341 /* walk up to the first unowned window */
1342 HWND tmp
= GetAncestor( hWnd
, GA_ROOTOWNER
);
1343 if ((wndTemp
= WIN_FindWndPtr( tmp
)))
1345 /* and set last active owned popup */
1346 wndTemp
->hwndLastActive
= hWnd
;
1348 wIconized
= HIWORD(wndTemp
->dwStyle
& WS_MINIMIZE
);
1349 WIN_ReleaseWndPtr(wndTemp
);
1351 SendMessageA( hWnd
, WM_NCACTIVATE
, TRUE
, 0 );
1352 SendMessageA( hWnd
, WM_ACTIVATE
,
1353 MAKEWPARAM( (fMouse
) ? WA_CLICKACTIVE
: WA_ACTIVE
, wIconized
),
1354 (LPARAM
)hwndPrevActive
);
1355 if( !IsWindow(hWnd
) ) goto CLEANUP
;
1358 /* change focus if possible */
1361 if ( pNewActiveQueue
)
1363 HWND hOldFocus
= PERQDATA_GetFocusWnd( pNewActiveQueue
->pQData
);
1365 if ( !hOldFocus
|| GetAncestor( hOldFocus
, GA_ROOT
) != hwndActive
)
1366 FOCUS_SwitchFocus( pNewActiveQueue
, hOldFocus
,
1367 (wndPtr
&& (wndPtr
->dwStyle
& WS_MINIMIZE
))?
1371 if ( pOldActiveQueue
&&
1372 ( !pNewActiveQueue
||
1373 pNewActiveQueue
->pQData
!= pOldActiveQueue
->pQData
) )
1375 HWND hOldFocus
= PERQDATA_GetFocusWnd( pOldActiveQueue
->pQData
);
1377 FOCUS_SwitchFocus( pOldActiveQueue
, hOldFocus
, 0 );
1381 if( !hwndPrevActive
&& wndPtr
)
1383 if (USER_Driver
.pForceWindowRaise
) USER_Driver
.pForceWindowRaise( wndPtr
->hwndSelf
);
1386 /* if active wnd is minimized redraw icon title */
1387 if( IsIconic(hwndActive
) ) WINPOS_RedrawIconTitle(hwndActive
);
1389 bRet
= (hWnd
== hwndActive
); /* Success? */
1391 CLEANUP
: /* Unlock the message queues before returning */
1393 if ( pNewActiveQueue
)
1394 QUEUE_Unlock( pNewActiveQueue
);
1398 if ( pOldActiveQueue
)
1399 QUEUE_Unlock( pOldActiveQueue
);
1401 WIN_ReleaseWndPtr(wndPtr
);
1405 /*******************************************************************
1406 * WINPOS_ActivateOtherWindow
1408 * Activates window other than pWnd.
1410 void WINPOS_ActivateOtherWindow(HWND hwnd
)
1412 HWND hwndActive
= 0;
1414 HWND hwndDefaultTo
= 0;
1417 /* Get current active window from the active queue */
1420 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
1423 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
1424 QUEUE_Unlock( pActiveQueue
);
1428 if (!(hwnd
= WIN_IsCurrentThread( hwnd
))) return;
1430 if( hwnd
== hwndPrevActive
)
1433 if( hwndActive
!= hwnd
&& (hwndActive
|| USER_IsExitingThread( GetCurrentThreadId() )))
1436 if (!(GetWindowLongW( hwnd
, GWL_STYLE
) & WS_POPUP
) ||
1437 !(owner
= GetWindow( hwnd
, GW_OWNER
)) ||
1438 !WINPOS_CanActivate((hwndTo
= GetAncestor( owner
, GA_ROOT
))) ||
1439 !WINPOS_IsVisible(hwndTo
))
1441 HWND tmp
= GetAncestor( hwnd
, GA_ROOT
);
1442 hwndTo
= hwndPrevActive
;
1444 while( !WINPOS_CanActivate(hwndTo
) || !WINPOS_IsVisible(hwndTo
))
1446 /* by now owned windows should've been taken care of */
1447 if(!hwndDefaultTo
&& WINPOS_CanActivate(hwndTo
))
1448 hwndDefaultTo
= hwndTo
;
1449 tmp
= hwndTo
= GetWindow( tmp
, GW_HWNDNEXT
);
1452 hwndTo
= hwndDefaultTo
;
1458 SetActiveWindow( hwndTo
);
1463 /***********************************************************************
1464 * WINPOS_HandleWindowPosChanging16
1466 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
1468 LONG
WINPOS_HandleWindowPosChanging16( HWND hwnd
, WINDOWPOS16
*winpos
)
1470 POINT maxSize
, minTrack
;
1471 LONG style
= GetWindowLongA( hwnd
, GWL_STYLE
);
1473 if (winpos
->flags
& SWP_NOSIZE
) return 0;
1474 if ((style
& WS_THICKFRAME
) || ((style
& (WS_POPUP
| WS_CHILD
)) == 0))
1476 WINPOS_GetMinMaxInfo( hwnd
, &maxSize
, NULL
, &minTrack
, NULL
);
1477 if (maxSize
.x
< winpos
->cx
) winpos
->cx
= maxSize
.x
;
1478 if (maxSize
.y
< winpos
->cy
) winpos
->cy
= maxSize
.y
;
1479 if (!(style
& WS_MINIMIZE
))
1481 if (winpos
->cx
< minTrack
.x
) winpos
->cx
= minTrack
.x
;
1482 if (winpos
->cy
< minTrack
.y
) winpos
->cy
= minTrack
.y
;
1489 /***********************************************************************
1490 * WINPOS_HandleWindowPosChanging
1492 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
1494 LONG
WINPOS_HandleWindowPosChanging( HWND hwnd
, WINDOWPOS
*winpos
)
1496 POINT maxSize
, minTrack
;
1497 LONG style
= GetWindowLongA( hwnd
, GWL_STYLE
);
1499 if (winpos
->flags
& SWP_NOSIZE
) return 0;
1500 if ((style
& WS_THICKFRAME
) || ((style
& (WS_POPUP
| WS_CHILD
)) == 0))
1502 WINPOS_GetMinMaxInfo( hwnd
, &maxSize
, NULL
, &minTrack
, NULL
);
1503 winpos
->cx
= min( winpos
->cx
, maxSize
.x
);
1504 winpos
->cy
= min( winpos
->cy
, maxSize
.y
);
1505 if (!(style
& WS_MINIMIZE
))
1507 if (winpos
->cx
< minTrack
.x
) winpos
->cx
= minTrack
.x
;
1508 if (winpos
->cy
< minTrack
.y
) winpos
->cy
= minTrack
.y
;
1515 /***********************************************************************
1516 * SetWindowPos (USER32.@)
1518 BOOL WINAPI
SetWindowPos( HWND hwnd
, HWND hwndInsertAfter
,
1519 INT x
, INT y
, INT cx
, INT cy
, UINT flags
)
1524 winpos
.hwndInsertAfter
= hwndInsertAfter
;
1529 winpos
.flags
= flags
;
1530 if (WIN_IsCurrentThread( hwnd
)) return USER_Driver
.pSetWindowPos( &winpos
);
1531 return SendMessageW( winpos
.hwnd
, WM_WINE_SETWINDOWPOS
, 0, (LPARAM
)&winpos
);
1535 /***********************************************************************
1536 * BeginDeferWindowPos (USER32.@)
1538 HDWP WINAPI
BeginDeferWindowPos( INT count
)
1545 SetLastError(ERROR_INVALID_PARAMETER
);
1548 /* Windows allows zero count, in which case it allocates context for 8 moves */
1549 if (count
== 0) count
= 8;
1551 handle
= USER_HEAP_ALLOC( sizeof(DWP
) + (count
-1)*sizeof(WINDOWPOS
) );
1552 if (!handle
) return 0;
1553 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( handle
);
1554 pDWP
->actualCount
= 0;
1555 pDWP
->suggestedCount
= count
;
1557 pDWP
->wMagic
= DWP_MAGIC
;
1558 pDWP
->hwndParent
= 0;
1563 /***********************************************************************
1564 * DeferWindowPos (USER32.@)
1566 HDWP WINAPI
DeferWindowPos( HDWP hdwp
, HWND hwnd
, HWND hwndAfter
,
1567 INT x
, INT y
, INT cx
, INT cy
,
1572 HDWP newhdwp
= hdwp
,retvalue
;
1574 hwnd
= WIN_GetFullHandle( hwnd
);
1575 if (hwnd
== GetDesktopWindow()) return 0;
1577 if (!(pDWP
= USER_HEAP_LIN_ADDR( hdwp
))) return 0;
1581 for (i
= 0; i
< pDWP
->actualCount
; i
++)
1583 if (pDWP
->winPos
[i
].hwnd
== hwnd
)
1585 /* Merge with the other changes */
1586 if (!(flags
& SWP_NOZORDER
))
1588 pDWP
->winPos
[i
].hwndInsertAfter
= hwndAfter
;
1590 if (!(flags
& SWP_NOMOVE
))
1592 pDWP
->winPos
[i
].x
= x
;
1593 pDWP
->winPos
[i
].y
= y
;
1595 if (!(flags
& SWP_NOSIZE
))
1597 pDWP
->winPos
[i
].cx
= cx
;
1598 pDWP
->winPos
[i
].cy
= cy
;
1600 pDWP
->winPos
[i
].flags
&= flags
| ~(SWP_NOSIZE
| SWP_NOMOVE
|
1601 SWP_NOZORDER
| SWP_NOREDRAW
|
1602 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
1604 pDWP
->winPos
[i
].flags
|= flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
|
1610 if (pDWP
->actualCount
>= pDWP
->suggestedCount
)
1612 newhdwp
= USER_HEAP_REALLOC( hdwp
,
1613 sizeof(DWP
) + pDWP
->suggestedCount
*sizeof(WINDOWPOS
) );
1619 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( newhdwp
);
1620 pDWP
->suggestedCount
++;
1622 pDWP
->winPos
[pDWP
->actualCount
].hwnd
= hwnd
;
1623 pDWP
->winPos
[pDWP
->actualCount
].hwndInsertAfter
= hwndAfter
;
1624 pDWP
->winPos
[pDWP
->actualCount
].x
= x
;
1625 pDWP
->winPos
[pDWP
->actualCount
].y
= y
;
1626 pDWP
->winPos
[pDWP
->actualCount
].cx
= cx
;
1627 pDWP
->winPos
[pDWP
->actualCount
].cy
= cy
;
1628 pDWP
->winPos
[pDWP
->actualCount
].flags
= flags
;
1629 pDWP
->actualCount
++;
1637 /***********************************************************************
1638 * EndDeferWindowPos (USER32.@)
1640 BOOL WINAPI
EndDeferWindowPos( HDWP hdwp
)
1647 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
1648 if (!pDWP
) return FALSE
;
1649 for (i
= 0, winpos
= pDWP
->winPos
; i
< pDWP
->actualCount
; i
++, winpos
++)
1651 if (!(res
= USER_Driver
.pSetWindowPos( winpos
))) break;
1653 USER_HEAP_FREE( hdwp
);
1658 /***********************************************************************
1659 * TileChildWindows (USER.199)
1661 void WINAPI
TileChildWindows16( HWND16 parent
, WORD action
)
1663 FIXME("(%04x, %d): stub\n", parent
, action
);
1666 /***********************************************************************
1667 * CascadeChildWindows (USER.198)
1669 void WINAPI
CascadeChildWindows16( HWND16 parent
, WORD action
)
1671 FIXME("(%04x, %d): stub\n", parent
, action
);
1674 /***********************************************************************
1675 * SetProgmanWindow (USER32.@)
1677 HWND WINAPI
SetProgmanWindow ( HWND hwnd
)
1679 hGlobalProgmanWindow
= hwnd
;
1680 return hGlobalProgmanWindow
;
1683 /***********************************************************************
1684 * GetProgmanWindow (USER32.@)
1686 HWND WINAPI
GetProgmanWindow(void)
1688 return hGlobalProgmanWindow
;
1691 /***********************************************************************
1692 * SetShellWindowEx (USER32.@)
1693 * hwndProgman = Progman[Program Manager]
1694 * |-> SHELLDLL_DefView
1695 * hwndListView = | |-> SysListView32
1696 * | | |-> tooltips_class32
1702 HWND WINAPI
SetShellWindowEx ( HWND hwndProgman
, HWND hwndListView
)
1704 FIXME("0x%08x 0x%08x stub\n",hwndProgman
,hwndListView
);
1705 hGlobalShellWindow
= hwndProgman
;
1706 return hGlobalShellWindow
;
1710 /***********************************************************************
1711 * SetTaskmanWindow (USER32.@)
1713 * hwnd = MSTaskSwWClass
1714 * |-> SysTabControl32
1716 HWND WINAPI
SetTaskmanWindow ( HWND hwnd
)
1718 hGlobalTaskmanWindow
= hwnd
;
1719 return hGlobalTaskmanWindow
;
1722 /***********************************************************************
1723 * GetTaskmanWindow (USER32.@)
1725 HWND WINAPI
GetTaskmanWindow(void)
1727 return hGlobalTaskmanWindow
;