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"
38 #include "nonclient.h"
39 #include "wine/debug.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(win
);
44 #define HAS_DLGFRAME(style,exStyle) \
45 (((exStyle) & WS_EX_DLGMODALFRAME) || \
46 (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
48 #define HAS_THICKFRAME(style) \
49 (((style) & WS_THICKFRAME) && \
50 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
52 #define EMPTYPOINT(pt) ((*(LONG*)&(pt)) == -1)
54 #define PLACE_MIN 0x0001
55 #define PLACE_MAX 0x0002
56 #define PLACE_RECT 0x0004
59 #define DWP_MAGIC ((INT)('W' | ('P' << 8) | ('O' << 16) | ('S' << 24)))
71 /* ----- internal variables ----- */
73 static HWND hwndPrevActive
= 0; /* Previously active window */
74 static HWND hGlobalShellWindow
=0; /*the shell*/
75 static HWND hGlobalTaskmanWindow
=0;
76 static HWND hGlobalProgmanWindow
=0;
78 static LPCSTR atomInternalPos
;
80 extern HQUEUE16 hActiveQueue
;
82 /***********************************************************************
83 * WINPOS_CreateInternalPosAtom
85 BOOL
WINPOS_CreateInternalPosAtom()
88 atomInternalPos
= (LPCSTR
)(DWORD
)GlobalAddAtomA(str
);
89 return (atomInternalPos
) ? TRUE
: FALSE
;
92 /***********************************************************************
93 * WINPOS_CheckInternalPos
95 * Called when a window is destroyed.
97 void WINPOS_CheckInternalPos( HWND hwnd
)
100 MESSAGEQUEUE
*pMsgQ
= 0;
101 WND
*wndPtr
= WIN_GetPtr( hwnd
);
103 if (!wndPtr
|| wndPtr
== WND_OTHER_PROCESS
) return;
105 lpPos
= (LPINTERNALPOS
) GetPropA( hwnd
, atomInternalPos
);
107 /* Retrieve the message queue associated with this window */
108 pMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( wndPtr
->hmemTaskQ
);
111 WARN("\tMessage queue not found. Exiting!\n" );
112 WIN_ReleasePtr( wndPtr
);
116 if( hwnd
== hwndPrevActive
) hwndPrevActive
= 0;
118 if( hwnd
== PERQDATA_GetActiveWnd( pMsgQ
->pQData
) )
120 PERQDATA_SetActiveWnd( pMsgQ
->pQData
, 0 );
121 WARN("\tattempt to activate destroyed window!\n");
126 if( IsWindow(lpPos
->hwndIconTitle
) )
127 DestroyWindow( lpPos
->hwndIconTitle
);
128 HeapFree( GetProcessHeap(), 0, lpPos
);
131 QUEUE_Unlock( pMsgQ
);
132 WIN_ReleasePtr( wndPtr
);
135 /***********************************************************************
136 * ArrangeIconicWindows (USER32.@)
138 UINT WINAPI
ArrangeIconicWindows( HWND parent
)
142 INT x
, y
, xspacing
, yspacing
;
144 GetClientRect( parent
, &rectParent
);
146 y
= rectParent
.bottom
;
147 xspacing
= GetSystemMetrics(SM_CXICONSPACING
);
148 yspacing
= GetSystemMetrics(SM_CYICONSPACING
);
150 hwndChild
= GetWindow( parent
, GW_CHILD
);
153 if( IsIconic( hwndChild
) )
155 WINPOS_ShowIconTitle( hwndChild
, FALSE
);
157 SetWindowPos( hwndChild
, 0, x
+ (xspacing
- GetSystemMetrics(SM_CXICON
)) / 2,
158 y
- yspacing
- GetSystemMetrics(SM_CYICON
)/2, 0, 0,
159 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
160 if( IsWindow(hwndChild
) )
161 WINPOS_ShowIconTitle(hwndChild
, TRUE
);
163 if (x
<= rectParent
.right
- xspacing
) x
+= xspacing
;
170 hwndChild
= GetWindow( hwndChild
, GW_HWNDNEXT
);
176 /***********************************************************************
177 * SwitchToThisWindow (USER32.@)
179 void WINAPI
SwitchToThisWindow( HWND hwnd
, BOOL restore
)
181 ShowWindow( hwnd
, restore
? SW_RESTORE
: SW_SHOWMINIMIZED
);
185 /***********************************************************************
186 * GetWindowRect (USER32.@)
188 BOOL WINAPI
GetWindowRect( HWND hwnd
, LPRECT rect
)
190 BOOL ret
= WIN_GetRectangles( hwnd
, rect
, NULL
);
193 MapWindowPoints( GetAncestor( hwnd
, GA_PARENT
), 0, (POINT
*)rect
, 2 );
194 TRACE( "hwnd %04x (%d,%d)-(%d,%d)\n",
195 hwnd
, rect
->left
, rect
->top
, rect
->right
, rect
->bottom
);
201 /***********************************************************************
202 * GetWindowRgn (USER32.@)
204 int WINAPI
GetWindowRgn ( HWND hwnd
, HRGN hrgn
)
207 WND
*wndPtr
= WIN_GetPtr( hwnd
);
209 if (wndPtr
== WND_OTHER_PROCESS
)
211 if (IsWindow( hwnd
))
212 FIXME( "not supported on other process window %x\n", hwnd
);
217 SetLastError( ERROR_INVALID_WINDOW_HANDLE
);
220 if (wndPtr
->hrgnWnd
) nRet
= CombineRgn( hrgn
, wndPtr
->hrgnWnd
, 0, RGN_COPY
);
221 WIN_ReleasePtr( wndPtr
);
226 /***********************************************************************
227 * SetWindowRgn (USER32.@)
229 int WINAPI
SetWindowRgn( HWND hwnd
, HRGN hrgn
, BOOL bRedraw
)
234 if (hrgn
) /* verify that region really exists */
236 if (GetRgnBox( hrgn
, &rect
) == ERROR
) return FALSE
;
239 if (USER_Driver
.pSetWindowRgn
)
240 return USER_Driver
.pSetWindowRgn( hwnd
, hrgn
, bRedraw
);
242 if ((wndPtr
= WIN_GetPtr( hwnd
)) == WND_OTHER_PROCESS
)
244 if (IsWindow( hwnd
))
245 FIXME( "not supported on other process window %x\n", hwnd
);
250 SetLastError( ERROR_INVALID_WINDOW_HANDLE
);
254 if (wndPtr
->hrgnWnd
== hrgn
)
256 WIN_ReleasePtr( wndPtr
);
262 /* delete previous region */
263 DeleteObject(wndPtr
->hrgnWnd
);
266 wndPtr
->hrgnWnd
= hrgn
;
267 WIN_ReleasePtr( wndPtr
);
269 /* Size the window to the rectangle of the new region (if it isn't NULL) */
270 if (hrgn
) SetWindowPos( hwnd
, 0, rect
.left
, rect
.top
,
271 rect
.right
- rect
.left
, rect
.bottom
- rect
.top
,
272 SWP_NOSIZE
| SWP_FRAMECHANGED
| SWP_NOMOVE
| SWP_NOACTIVATE
|
273 SWP_NOZORDER
| (bRedraw
? 0 : SWP_NOREDRAW
) );
278 /***********************************************************************
279 * GetClientRect (USER32.@)
281 BOOL WINAPI
GetClientRect( HWND hwnd
, LPRECT rect
)
285 rect
->right
= rect
->bottom
= 0;
286 if ((ret
= WIN_GetRectangles( hwnd
, NULL
, rect
)))
288 rect
->right
-= rect
->left
;
289 rect
->bottom
-= rect
->top
;
291 rect
->left
= rect
->top
= 0;
296 /*******************************************************************
297 * ClientToScreen (USER32.@)
299 BOOL WINAPI
ClientToScreen( HWND hwnd
, LPPOINT lppnt
)
301 MapWindowPoints( hwnd
, 0, lppnt
, 1 );
306 /*******************************************************************
307 * ScreenToClient (USER32.@)
309 BOOL WINAPI
ScreenToClient( HWND hwnd
, LPPOINT lppnt
)
311 MapWindowPoints( 0, hwnd
, lppnt
, 1 );
316 /***********************************************************************
317 * find_child_from_point
319 * Find the child that contains pt. Helper for WindowFromPoint.
320 * pt is in parent client coordinates.
321 * lparam is the param to pass in the WM_NCHITTEST message.
323 static HWND
find_child_from_point( HWND parent
, POINT pt
, INT
*hittest
, LPARAM lparam
)
327 RECT rectWindow
, rectClient
;
329 HWND
*list
= WIN_ListChildren( parent
);
332 for (i
= 0; list
[i
]; i
++)
334 /* If point is in window, and window is visible, and it */
335 /* is enabled (or it's a top-level window), then explore */
336 /* its children. Otherwise, go to the next window. */
338 style
= GetWindowLongW( list
[i
], GWL_STYLE
);
339 if (!(style
& WS_VISIBLE
)) continue; /* not visible -> skip */
340 if ((style
& (WS_POPUP
| WS_CHILD
| WS_DISABLED
)) == (WS_CHILD
| WS_DISABLED
))
341 continue; /* disabled child -> skip */
342 exstyle
= GetWindowLongW( list
[i
], GWL_EXSTYLE
);
343 if ((exstyle
& (WS_EX_LAYERED
| WS_EX_TRANSPARENT
)) == (WS_EX_LAYERED
| WS_EX_TRANSPARENT
))
344 continue; /* transparent -> skip */
346 if (!WIN_GetRectangles( list
[i
], &rectWindow
, &rectClient
)) continue;
347 if (!PtInRect( &rectWindow
, pt
)) continue; /* not in window -> skip */
349 /* FIXME: check window region for other processes too */
350 if ((wndPtr
= WIN_GetPtr( list
[i
] )) && wndPtr
!= WND_OTHER_PROCESS
)
352 if (wndPtr
->hrgnWnd
&& !PtInRegion( wndPtr
->hrgnWnd
,
353 pt
.x
- rectWindow
.left
, pt
.y
- rectWindow
.top
))
355 WIN_ReleasePtr( wndPtr
);
356 continue; /* point outside window region -> skip */
358 WIN_ReleasePtr( wndPtr
);
361 /* If window is minimized or disabled, return at once */
362 if (style
& WS_MINIMIZE
)
364 *hittest
= HTCAPTION
;
367 if (style
& WS_DISABLED
)
373 /* If point is in client area, explore children */
374 if (PtInRect( &rectClient
, pt
))
379 new_pt
.x
= pt
.x
- rectClient
.left
;
380 new_pt
.y
= pt
.y
- rectClient
.top
;
381 if ((ret
= find_child_from_point( list
[i
], new_pt
, hittest
, lparam
)))
385 /* Now it's inside window, send WM_NCCHITTEST (if same thread) */
386 if (!WIN_IsCurrentThread( list
[i
] ))
391 if ((res
= SendMessageA( list
[i
], WM_NCHITTEST
, 0, lparam
)) != HTTRANSPARENT
)
393 *hittest
= res
; /* Found the window */
396 /* continue search with next sibling */
402 /***********************************************************************
403 * WINPOS_WindowFromPoint
405 * Find the window and hittest for a given point.
407 HWND
WINPOS_WindowFromPoint( HWND hwndScope
, POINT pt
, INT
*hittest
)
413 TRACE("scope %04x %ld,%ld\n", hwndScope
, pt
.x
, pt
.y
);
415 if (!hwndScope
) hwndScope
= GetDesktopWindow();
416 style
= GetWindowLongW( hwndScope
, GWL_STYLE
);
419 if (style
& WS_DISABLED
) return 0;
421 MapWindowPoints( GetDesktopWindow(), GetAncestor( hwndScope
, GA_PARENT
), &xy
, 1 );
423 if (!(style
& WS_MINIMIZE
))
426 if (WIN_GetRectangles( hwndScope
, NULL
, &rectClient
) && PtInRect( &rectClient
, xy
))
430 xy
.x
-= rectClient
.left
;
431 xy
.y
-= rectClient
.top
;
432 if ((ret
= find_child_from_point( hwndScope
, xy
, hittest
, MAKELONG( pt
.x
, pt
.y
) )))
434 TRACE( "found child %x\n", ret
);
440 /* If nothing found, try the scope window */
441 if (!WIN_IsCurrentThread( hwndScope
))
444 TRACE( "returning %x\n", hwndScope
);
447 res
= SendMessageA( hwndScope
, WM_NCHITTEST
, 0, MAKELONG( pt
.x
, pt
.y
) );
448 if (res
!= HTTRANSPARENT
)
450 *hittest
= res
; /* Found the window */
451 TRACE( "returning %x\n", hwndScope
);
454 *hittest
= HTNOWHERE
;
455 TRACE( "nothing found\n" );
460 /*******************************************************************
461 * WindowFromPoint (USER32.@)
463 HWND WINAPI
WindowFromPoint( POINT pt
)
466 return WINPOS_WindowFromPoint( 0, pt
, &hittest
);
470 /*******************************************************************
471 * ChildWindowFromPoint (USER32.@)
473 HWND WINAPI
ChildWindowFromPoint( HWND hwndParent
, POINT pt
)
475 return ChildWindowFromPointEx( hwndParent
, pt
, CWP_ALL
);
478 /*******************************************************************
479 * ChildWindowFromPointEx (USER32.@)
481 HWND WINAPI
ChildWindowFromPointEx( HWND hwndParent
, POINT pt
, UINT uFlags
)
483 /* pt is in the client coordinates */
489 GetClientRect( hwndParent
, &rect
);
490 if (!PtInRect( &rect
, pt
)) return 0;
491 if (!(list
= WIN_ListChildren( hwndParent
))) return 0;
493 for (i
= 0; list
[i
]; i
++)
495 if (!WIN_GetRectangles( list
[i
], &rect
, NULL
)) continue;
496 if (!PtInRect( &rect
, pt
)) continue;
497 if (uFlags
& (CWP_SKIPINVISIBLE
|CWP_SKIPDISABLED
))
499 LONG style
= GetWindowLongW( list
[i
], GWL_STYLE
);
500 if ((uFlags
& CWP_SKIPINVISIBLE
) && !(style
& WS_VISIBLE
)) continue;
501 if ((uFlags
& CWP_SKIPDISABLED
) && (style
& WS_DISABLED
)) continue;
503 if (uFlags
& CWP_SKIPTRANSPARENT
)
505 if (GetWindowLongW( list
[i
], GWL_EXSTYLE
) & WS_EX_TRANSPARENT
) continue;
510 HeapFree( GetProcessHeap(), 0, list
);
511 if (!retvalue
) retvalue
= hwndParent
;
516 /*******************************************************************
517 * WINPOS_GetWinOffset
519 * Calculate the offset between the origin of the two windows. Used
520 * to implement MapWindowPoints.
522 static void WINPOS_GetWinOffset( HWND hwndFrom
, HWND hwndTo
, POINT
*offset
)
526 offset
->x
= offset
->y
= 0;
528 /* Translate source window origin to screen coords */
531 HWND hwnd
= hwndFrom
;
535 if (hwnd
== hwndTo
) return;
536 if (!(wndPtr
= WIN_GetPtr( hwnd
)))
538 ERR( "bad hwndFrom = %04x\n", hwnd
);
541 if (wndPtr
== WND_OTHER_PROCESS
) goto other_process
;
542 offset
->x
+= wndPtr
->rectClient
.left
;
543 offset
->y
+= wndPtr
->rectClient
.top
;
544 hwnd
= wndPtr
->parent
;
545 WIN_ReleasePtr( wndPtr
);
549 /* Translate origin to destination window coords */
556 if (!(wndPtr
= WIN_GetPtr( hwnd
)))
558 ERR( "bad hwndTo = %04x\n", hwnd
);
561 if (wndPtr
== WND_OTHER_PROCESS
) goto other_process
;
562 offset
->x
-= wndPtr
->rectClient
.left
;
563 offset
->y
-= wndPtr
->rectClient
.top
;
564 hwnd
= wndPtr
->parent
;
565 WIN_ReleasePtr( wndPtr
);
570 other_process
: /* one of the parents may belong to another process, do it the hard way */
571 offset
->x
= offset
->y
= 0;
572 SERVER_START_REQ( get_windows_offset
)
574 req
->from
= hwndFrom
;
576 if (!wine_server_call( req
))
578 offset
->x
= reply
->x
;
579 offset
->y
= reply
->y
;
586 /*******************************************************************
587 * MapWindowPoints (USER.258)
589 void WINAPI
MapWindowPoints16( HWND16 hwndFrom
, HWND16 hwndTo
,
590 LPPOINT16 lppt
, UINT16 count
)
594 WINPOS_GetWinOffset( WIN_Handle32(hwndFrom
), WIN_Handle32(hwndTo
), &offset
);
604 /*******************************************************************
605 * MapWindowPoints (USER32.@)
607 INT WINAPI
MapWindowPoints( HWND hwndFrom
, HWND hwndTo
, LPPOINT lppt
, UINT count
)
611 WINPOS_GetWinOffset( hwndFrom
, hwndTo
, &offset
);
618 return MAKELONG( LOWORD(offset
.x
), LOWORD(offset
.y
) );
622 /***********************************************************************
623 * IsIconic (USER32.@)
625 BOOL WINAPI
IsIconic(HWND hWnd
)
627 return (GetWindowLongW( hWnd
, GWL_STYLE
) & WS_MINIMIZE
) != 0;
631 /***********************************************************************
632 * IsZoomed (USER32.@)
634 BOOL WINAPI
IsZoomed(HWND hWnd
)
636 return (GetWindowLongW( hWnd
, GWL_STYLE
) & WS_MAXIMIZE
) != 0;
640 /*******************************************************************
641 * GetActiveWindow (USER32.@)
643 HWND WINAPI
GetActiveWindow(void)
645 MESSAGEQUEUE
*pCurMsgQ
= 0;
647 /* Get the messageQ for the current thread */
648 if (!(pCurMsgQ
= QUEUE_Current()))
650 WARN("\tCurrent message queue not found. Exiting!\n" );
654 /* Return the current active window from the perQ data of the current message Q */
655 return PERQDATA_GetActiveWnd( pCurMsgQ
->pQData
);
659 /*******************************************************************
662 static BOOL
WINPOS_CanActivate(HWND hwnd
)
664 if (!hwnd
) return FALSE
;
665 return ((GetWindowLongW( hwnd
, GWL_STYLE
) & (WS_DISABLED
|WS_CHILD
)) == 0);
668 /*******************************************************************
671 static BOOL
WINPOS_IsVisible(HWND hwnd
)
673 if (!hwnd
) return FALSE
;
674 return ((GetWindowLongW( hwnd
, GWL_STYLE
) & WS_VISIBLE
) == WS_VISIBLE
);
678 /*******************************************************************
679 * SetActiveWindow (USER32.@)
681 HWND WINAPI
SetActiveWindow( HWND hwnd
)
684 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
685 MESSAGEQUEUE
*pMsgQ
= 0, *pCurMsgQ
= 0;
687 if (!wndPtr
) return 0;
689 if (wndPtr
->dwStyle
& (WS_DISABLED
| WS_CHILD
)) goto error
;
691 /* Get the messageQ for the current thread */
692 if (!(pCurMsgQ
= QUEUE_Current()))
694 WARN("\tCurrent message queue not found. Exiting!\n" );
698 /* Retrieve the message queue associated with this window */
699 pMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( wndPtr
->hmemTaskQ
);
702 WARN("\tWindow message queue not found. Exiting!\n" );
706 /* Make sure that the window is associated with the calling threads
707 * message queue. It must share the same perQ data.
709 if ( pCurMsgQ
->pQData
!= pMsgQ
->pQData
)
711 QUEUE_Unlock( pMsgQ
);
715 /* Save current active window */
716 prev
= PERQDATA_GetActiveWnd( pMsgQ
->pQData
);
717 QUEUE_Unlock( pMsgQ
);
718 WIN_ReleaseWndPtr(wndPtr
);
719 WINPOS_SetActiveWindow( hwnd
, FALSE
, TRUE
);
723 WIN_ReleaseWndPtr(wndPtr
);
728 /*******************************************************************
729 * GetForegroundWindow (USER32.@)
731 HWND WINAPI
GetForegroundWindow(void)
735 /* Get the foreground window (active window of hActiveQueue) */
738 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
740 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
742 QUEUE_Unlock( pActiveQueue
);
748 /*******************************************************************
749 * SetForegroundWindow (USER32.@)
751 BOOL WINAPI
SetForegroundWindow( HWND hwnd
)
753 if (!hwnd
) return WINPOS_SetActiveWindow( 0, FALSE
, TRUE
);
755 /* child windows get WM_CHILDACTIVATE message */
756 if ((GetWindowLongW( hwnd
, GWL_STYLE
) & (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
757 return SendMessageA( hwnd
, WM_CHILDACTIVATE
, 0, 0 );
759 hwnd
= WIN_GetFullHandle( hwnd
);
760 if( hwnd
== GetForegroundWindow() ) return FALSE
;
762 return WINPOS_SetActiveWindow( hwnd
, FALSE
, TRUE
);
766 /*******************************************************************
767 * AllowSetForegroundWindow (USER32.@)
769 BOOL WINAPI
AllowSetForegroundWindow( DWORD procid
)
771 /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
772 * implemented, then fix this function. */
777 /*******************************************************************
778 * LockSetForegroundWindow (USER32.@)
780 BOOL WINAPI
LockSetForegroundWindow( UINT lockcode
)
782 /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
783 * implemented, then fix this function. */
788 /*******************************************************************
789 * SetShellWindow (USER32.@)
791 HWND WINAPI
SetShellWindow(HWND hwndshell
)
792 { WARN("(hWnd=%08x) semi stub\n",hwndshell
);
794 hGlobalShellWindow
= WIN_GetFullHandle( hwndshell
);
795 return hGlobalShellWindow
;
799 /*******************************************************************
800 * GetShellWindow (USER32.@)
802 HWND WINAPI
GetShellWindow(void)
803 { WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow
);
805 return hGlobalShellWindow
;
809 /***********************************************************************
810 * BringWindowToTop (USER32.@)
812 BOOL WINAPI
BringWindowToTop( HWND hwnd
)
814 return SetWindowPos( hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
);
818 /***********************************************************************
819 * MoveWindow (USER32.@)
821 BOOL WINAPI
MoveWindow( HWND hwnd
, INT x
, INT y
, INT cx
, INT cy
,
824 int flags
= SWP_NOZORDER
| SWP_NOACTIVATE
;
825 if (!repaint
) flags
|= SWP_NOREDRAW
;
826 TRACE("%04x %d,%d %dx%d %d\n",
827 hwnd
, x
, y
, cx
, cy
, repaint
);
828 return SetWindowPos( hwnd
, 0, x
, y
, cx
, cy
, flags
);
831 /***********************************************************************
832 * WINPOS_InitInternalPos
834 static LPINTERNALPOS
WINPOS_InitInternalPos( WND
* wnd
, POINT pt
, const RECT
*restoreRect
)
836 LPINTERNALPOS lpPos
= (LPINTERNALPOS
) GetPropA( wnd
->hwndSelf
,
840 /* this happens when the window is minimized/maximized
841 * for the first time (rectWindow is not adjusted yet) */
843 lpPos
= HeapAlloc( GetProcessHeap(), 0, sizeof(INTERNALPOS
) );
844 if( !lpPos
) return NULL
;
846 SetPropA( wnd
->hwndSelf
, atomInternalPos
, (HANDLE
)lpPos
);
847 lpPos
->hwndIconTitle
= 0; /* defer until needs to be shown */
848 CONV_RECT32TO16( &wnd
->rectWindow
, &lpPos
->rectNormal
);
849 *(UINT
*)&lpPos
->ptIconPos
= *(UINT
*)&lpPos
->ptMaxPos
= 0xFFFFFFFF;
852 if( wnd
->dwStyle
& WS_MINIMIZE
)
853 CONV_POINT32TO16( &pt
, &lpPos
->ptIconPos
);
854 else if( wnd
->dwStyle
& WS_MAXIMIZE
)
855 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
856 else if( restoreRect
)
857 CONV_RECT32TO16( restoreRect
, &lpPos
->rectNormal
);
862 /***********************************************************************
863 * WINPOS_RedrawIconTitle
865 BOOL
WINPOS_RedrawIconTitle( HWND hWnd
)
867 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)GetPropA( hWnd
, atomInternalPos
);
870 if( lpPos
->hwndIconTitle
)
872 SendMessageA( lpPos
->hwndIconTitle
, WM_SHOWWINDOW
, TRUE
, 0);
873 InvalidateRect( lpPos
->hwndIconTitle
, NULL
, TRUE
);
880 /***********************************************************************
881 * WINPOS_ShowIconTitle
883 BOOL
WINPOS_ShowIconTitle( HWND hwnd
, BOOL bShow
)
885 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)GetPropA( hwnd
, atomInternalPos
);
887 if( lpPos
&& !(GetWindowLongA( hwnd
, GWL_EXSTYLE
) & WS_EX_MANAGED
))
889 HWND title
= lpPos
->hwndIconTitle
;
891 TRACE("0x%04x %i\n", hwnd
, (bShow
!= 0) );
894 lpPos
->hwndIconTitle
= title
= ICONTITLE_Create( hwnd
);
897 if (!IsWindowVisible(title
))
899 SendMessageA( title
, WM_SHOWWINDOW
, TRUE
, 0 );
900 SetWindowPos( title
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
901 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_SHOWWINDOW
);
904 else ShowWindow( title
, SW_HIDE
);
909 /*******************************************************************
910 * WINPOS_GetMinMaxInfo
912 * Get the minimized and maximized information for a window.
914 void WINPOS_GetMinMaxInfo( HWND hwnd
, POINT
*maxSize
, POINT
*maxPos
,
915 POINT
*minTrack
, POINT
*maxTrack
)
920 LONG style
= GetWindowLongA( hwnd
, GWL_STYLE
);
921 LONG exstyle
= GetWindowLongA( hwnd
, GWL_EXSTYLE
);
923 /* Compute default values */
925 MinMax
.ptMaxSize
.x
= GetSystemMetrics(SM_CXSCREEN
);
926 MinMax
.ptMaxSize
.y
= GetSystemMetrics(SM_CYSCREEN
);
927 MinMax
.ptMinTrackSize
.x
= GetSystemMetrics(SM_CXMINTRACK
);
928 MinMax
.ptMinTrackSize
.y
= GetSystemMetrics(SM_CYMINTRACK
);
929 MinMax
.ptMaxTrackSize
.x
= GetSystemMetrics(SM_CXSCREEN
);
930 MinMax
.ptMaxTrackSize
.y
= GetSystemMetrics(SM_CYSCREEN
);
932 if (HAS_DLGFRAME( style
, exstyle
))
934 xinc
= GetSystemMetrics(SM_CXDLGFRAME
);
935 yinc
= GetSystemMetrics(SM_CYDLGFRAME
);
940 if (HAS_THICKFRAME(style
))
942 xinc
+= GetSystemMetrics(SM_CXFRAME
);
943 yinc
+= GetSystemMetrics(SM_CYFRAME
);
945 if (style
& WS_BORDER
)
947 xinc
+= GetSystemMetrics(SM_CXBORDER
);
948 yinc
+= GetSystemMetrics(SM_CYBORDER
);
951 MinMax
.ptMaxSize
.x
+= 2 * xinc
;
952 MinMax
.ptMaxSize
.y
+= 2 * yinc
;
954 lpPos
= (LPINTERNALPOS
)GetPropA( hwnd
, atomInternalPos
);
955 if( lpPos
&& !EMPTYPOINT(lpPos
->ptMaxPos
) )
956 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &MinMax
.ptMaxPosition
);
959 MinMax
.ptMaxPosition
.x
= -xinc
;
960 MinMax
.ptMaxPosition
.y
= -yinc
;
963 SendMessageA( hwnd
, WM_GETMINMAXINFO
, 0, (LPARAM
)&MinMax
);
965 /* Some sanity checks */
967 TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
968 MinMax
.ptMaxSize
.x
, MinMax
.ptMaxSize
.y
,
969 MinMax
.ptMaxPosition
.x
, MinMax
.ptMaxPosition
.y
,
970 MinMax
.ptMaxTrackSize
.x
, MinMax
.ptMaxTrackSize
.y
,
971 MinMax
.ptMinTrackSize
.x
, MinMax
.ptMinTrackSize
.y
);
972 MinMax
.ptMaxTrackSize
.x
= max( MinMax
.ptMaxTrackSize
.x
,
973 MinMax
.ptMinTrackSize
.x
);
974 MinMax
.ptMaxTrackSize
.y
= max( MinMax
.ptMaxTrackSize
.y
,
975 MinMax
.ptMinTrackSize
.y
);
977 if (maxSize
) *maxSize
= MinMax
.ptMaxSize
;
978 if (maxPos
) *maxPos
= MinMax
.ptMaxPosition
;
979 if (minTrack
) *minTrack
= MinMax
.ptMinTrackSize
;
980 if (maxTrack
) *maxTrack
= MinMax
.ptMaxTrackSize
;
983 /***********************************************************************
984 * ShowWindowAsync (USER32.@)
986 * doesn't wait; returns immediately.
987 * used by threads to toggle windows in other (possibly hanging) threads
989 BOOL WINAPI
ShowWindowAsync( HWND hwnd
, INT cmd
)
991 /* FIXME: does ShowWindow() return immediately ? */
992 return ShowWindow(hwnd
, cmd
);
996 /***********************************************************************
997 * ShowWindow (USER32.@)
999 BOOL WINAPI
ShowWindow( HWND hwnd
, INT cmd
)
1003 if ((full_handle
= WIN_IsCurrentThread( hwnd
)))
1004 return USER_Driver
.pShowWindow( full_handle
, cmd
);
1005 return SendMessageW( hwnd
, WM_WINE_SHOWWINDOW
, cmd
, 0 );
1009 /***********************************************************************
1010 * GetInternalWindowPos (USER.460)
1012 UINT16 WINAPI
GetInternalWindowPos16( HWND16 hwnd
, LPRECT16 rectWnd
,
1015 WINDOWPLACEMENT16 wndpl
;
1016 if (GetWindowPlacement16( hwnd
, &wndpl
))
1018 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
1019 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
1020 return wndpl
.showCmd
;
1026 /***********************************************************************
1027 * GetInternalWindowPos (USER32.@)
1029 UINT WINAPI
GetInternalWindowPos( HWND hwnd
, LPRECT rectWnd
,
1032 WINDOWPLACEMENT wndpl
;
1033 if (GetWindowPlacement( hwnd
, &wndpl
))
1035 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
1036 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
1037 return wndpl
.showCmd
;
1043 /***********************************************************************
1044 * GetWindowPlacement (USER32.@)
1047 * Fails if wndpl->length of Win95 (!) apps is invalid.
1049 BOOL WINAPI
GetWindowPlacement( HWND hwnd
, WINDOWPLACEMENT
*wndpl
)
1051 WND
*pWnd
= WIN_FindWndPtr( hwnd
);
1052 LPINTERNALPOS lpPos
;
1054 if(!pWnd
) return FALSE
;
1056 lpPos
= WINPOS_InitInternalPos( pWnd
, *(LPPOINT
)&pWnd
->rectWindow
.left
, &pWnd
->rectWindow
);
1057 wndpl
->length
= sizeof(*wndpl
);
1058 if( pWnd
->dwStyle
& WS_MINIMIZE
)
1059 wndpl
->showCmd
= SW_SHOWMINIMIZED
;
1061 wndpl
->showCmd
= ( pWnd
->dwStyle
& WS_MAXIMIZE
) ? SW_SHOWMAXIMIZED
: SW_SHOWNORMAL
;
1062 if( pWnd
->flags
& WIN_RESTORE_MAX
)
1063 wndpl
->flags
= WPF_RESTORETOMAXIMIZED
;
1066 CONV_POINT16TO32( &lpPos
->ptIconPos
, &wndpl
->ptMinPosition
);
1067 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &wndpl
->ptMaxPosition
);
1068 CONV_RECT16TO32( &lpPos
->rectNormal
, &wndpl
->rcNormalPosition
);
1069 WIN_ReleaseWndPtr(pWnd
);
1074 /***********************************************************************
1075 * WINPOS_SetPlacement
1077 static BOOL
WINPOS_SetPlacement( HWND hwnd
, const WINDOWPLACEMENT
*wndpl
, UINT flags
)
1079 WND
*pWnd
= WIN_FindWndPtr( hwnd
);
1082 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)WINPOS_InitInternalPos( pWnd
,
1083 *(LPPOINT
)&pWnd
->rectWindow
.left
, &pWnd
->rectWindow
);
1085 if( flags
& PLACE_MIN
) CONV_POINT32TO16( &wndpl
->ptMinPosition
, &lpPos
->ptIconPos
);
1086 if( flags
& PLACE_MAX
) CONV_POINT32TO16( &wndpl
->ptMaxPosition
, &lpPos
->ptMaxPos
);
1087 if( flags
& PLACE_RECT
) CONV_RECT32TO16( &wndpl
->rcNormalPosition
, &lpPos
->rectNormal
);
1089 if( pWnd
->dwStyle
& WS_MINIMIZE
)
1091 WINPOS_ShowIconTitle( pWnd
->hwndSelf
, FALSE
);
1092 if( wndpl
->flags
& WPF_SETMINPOSITION
&& !EMPTYPOINT(lpPos
->ptIconPos
))
1093 SetWindowPos( hwnd
, 0, lpPos
->ptIconPos
.x
, lpPos
->ptIconPos
.y
,
1094 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1096 else if( pWnd
->dwStyle
& WS_MAXIMIZE
)
1098 if( !EMPTYPOINT(lpPos
->ptMaxPos
) )
1099 SetWindowPos( hwnd
, 0, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
,
1100 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1102 else if( flags
& PLACE_RECT
)
1103 SetWindowPos( hwnd
, 0, lpPos
->rectNormal
.left
, lpPos
->rectNormal
.top
,
1104 lpPos
->rectNormal
.right
- lpPos
->rectNormal
.left
,
1105 lpPos
->rectNormal
.bottom
- lpPos
->rectNormal
.top
,
1106 SWP_NOZORDER
| SWP_NOACTIVATE
);
1108 ShowWindow( hwnd
, wndpl
->showCmd
);
1109 if( IsWindow(hwnd
) && pWnd
->dwStyle
& WS_MINIMIZE
)
1111 if( pWnd
->dwStyle
& WS_VISIBLE
) WINPOS_ShowIconTitle( pWnd
->hwndSelf
, TRUE
);
1113 /* SDK: ...valid only the next time... */
1114 if( wndpl
->flags
& WPF_RESTORETOMAXIMIZED
) pWnd
->flags
|= WIN_RESTORE_MAX
;
1116 WIN_ReleaseWndPtr(pWnd
);
1123 /***********************************************************************
1124 * SetWindowPlacement (USER32.@)
1127 * Fails if wndpl->length of Win95 (!) apps is invalid.
1129 BOOL WINAPI
SetWindowPlacement( HWND hwnd
, const WINDOWPLACEMENT
*wpl
)
1131 if (!wpl
) return FALSE
;
1132 return WINPOS_SetPlacement( hwnd
, wpl
, PLACE_MIN
| PLACE_MAX
| PLACE_RECT
);
1136 /***********************************************************************
1137 * AnimateWindow (USER32.@)
1138 * Shows/Hides a window with an animation
1141 BOOL WINAPI
AnimateWindow(HWND hwnd
, DWORD dwTime
, DWORD dwFlags
)
1143 FIXME("partial stub\n");
1145 /* If trying to show/hide and it's already *
1146 * shown/hidden or invalid window, fail with *
1147 * invalid parameter */
1148 if(!IsWindow(hwnd
) ||
1149 (IsWindowVisible(hwnd
) && !(dwFlags
& AW_HIDE
)) ||
1150 (!IsWindowVisible(hwnd
) && (dwFlags
& AW_HIDE
)))
1152 SetLastError(ERROR_INVALID_PARAMETER
);
1156 ShowWindow(hwnd
, (dwFlags
& AW_HIDE
) ? SW_HIDE
: ((dwFlags
& AW_ACTIVATE
) ? SW_SHOW
: SW_SHOWNA
));
1161 /***********************************************************************
1162 * SetInternalWindowPos (USER32.@)
1164 void WINAPI
SetInternalWindowPos( HWND hwnd
, UINT showCmd
,
1165 LPRECT rect
, LPPOINT pt
)
1167 if( IsWindow(hwnd
) )
1169 WINDOWPLACEMENT wndpl
;
1172 wndpl
.length
= sizeof(wndpl
);
1173 wndpl
.showCmd
= showCmd
;
1174 wndpl
.flags
= flags
= 0;
1179 wndpl
.flags
|= WPF_SETMINPOSITION
;
1180 wndpl
.ptMinPosition
= *pt
;
1184 flags
|= PLACE_RECT
;
1185 wndpl
.rcNormalPosition
= *rect
;
1187 WINPOS_SetPlacement( hwnd
, &wndpl
, flags
);
1191 /*******************************************************************
1192 * WINPOS_SetActiveWindow
1194 * SetActiveWindow() back-end. This is the only function that
1195 * can assign active status to a window. It must be called only
1196 * for the top level windows.
1198 BOOL
WINPOS_SetActiveWindow( HWND hWnd
, BOOL fMouse
, BOOL fChangeFocus
)
1200 WND
* wndPtr
=0, *wndTemp
;
1201 HQUEUE16 hOldActiveQueue
, hNewActiveQueue
;
1202 MESSAGEQUEUE
*pOldActiveQueue
= 0, *pNewActiveQueue
= 0;
1204 HWND hwndActive
= 0;
1207 TRACE("(%04x, %d, %d)\n", hWnd
, fMouse
, fChangeFocus
);
1209 /* Get current active window from the active queue */
1212 pOldActiveQueue
= QUEUE_Lock( hActiveQueue
);
1213 if ( pOldActiveQueue
)
1214 hwndActive
= PERQDATA_GetActiveWnd( pOldActiveQueue
->pQData
);
1217 if ((wndPtr
= WIN_FindWndPtr(hWnd
)))
1218 hWnd
= wndPtr
->hwndSelf
; /* make it a full handle */
1220 /* paranoid checks */
1221 if( hWnd
== GetDesktopWindow() || (bRet
= (hWnd
== hwndActive
)) )
1224 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1227 hOldActiveQueue
= hActiveQueue
;
1229 if( (wndTemp
= WIN_FindWndPtr(hwndActive
)) )
1231 wIconized
= HIWORD(wndTemp
->dwStyle
& WS_MINIMIZE
);
1232 WIN_ReleaseWndPtr(wndTemp
);
1235 TRACE("no current active window.\n");
1237 /* call CBT hook chain */
1238 if (HOOK_IsHooked( WH_CBT
))
1240 CBTACTIVATESTRUCT cbt
;
1241 cbt
.fMouse
= fMouse
;
1242 cbt
.hWndActive
= hwndActive
;
1243 if (HOOK_CallHooksA( WH_CBT
, HCBT_ACTIVATE
, (WPARAM
)hWnd
, (LPARAM
)&cbt
)) goto CLEANUP_END
;
1246 /* set prev active wnd to current active wnd and send notification */
1247 if ((hwndPrevActive
= hwndActive
) && IsWindow(hwndPrevActive
))
1249 MESSAGEQUEUE
*pTempActiveQueue
= 0;
1251 SendNotifyMessageA( hwndPrevActive
, WM_NCACTIVATE
, FALSE
, 0 );
1252 SendNotifyMessageA( hwndPrevActive
, WM_ACTIVATE
,
1253 MAKEWPARAM( WA_INACTIVE
, wIconized
),
1256 /* check if something happened during message processing
1257 * (global active queue may have changed)
1259 pTempActiveQueue
= QUEUE_Lock( hActiveQueue
);
1260 if(!pTempActiveQueue
)
1263 hwndActive
= PERQDATA_GetActiveWnd( pTempActiveQueue
->pQData
);
1264 QUEUE_Unlock( pTempActiveQueue
);
1265 if( hwndPrevActive
!= hwndActive
)
1269 /* Set new active window in the message queue */
1273 pNewActiveQueue
= QUEUE_Lock( wndPtr
->hmemTaskQ
);
1274 if ( pNewActiveQueue
)
1275 PERQDATA_SetActiveWnd( pNewActiveQueue
->pQData
, hwndActive
);
1277 else /* have to do this or MDI frame activation goes to hell */
1278 if( pOldActiveQueue
)
1279 PERQDATA_SetActiveWnd( pOldActiveQueue
->pQData
, 0 );
1281 /* send palette messages */
1282 if (hWnd
&& SendMessageW( hWnd
, WM_QUERYNEWPALETTE
, 0, 0L))
1283 SendMessageW( HWND_BROADCAST
, WM_PALETTEISCHANGING
, (WPARAM
)hWnd
, 0 );
1285 /* if prev wnd is minimized redraw icon title */
1286 if( IsIconic( hwndPrevActive
) ) WINPOS_RedrawIconTitle(hwndPrevActive
);
1288 /* managed windows will get ConfigureNotify event */
1289 if (wndPtr
&& !(wndPtr
->dwStyle
& WS_CHILD
) && !(wndPtr
->dwExStyle
& WS_EX_MANAGED
))
1291 /* check Z-order and bring hWnd to the top */
1292 HWND tmp
= GetTopWindow(0);
1293 while (tmp
&& !(GetWindowLongA( tmp
, GWL_STYLE
) & WS_VISIBLE
))
1294 tmp
= GetWindow( tmp
, GW_HWNDNEXT
);
1297 SetWindowPos(hWnd
, HWND_TOP
, 0,0,0,0,
1298 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
1299 if (!IsWindow(hWnd
))
1303 /* Get a handle to the new active queue */
1304 hNewActiveQueue
= wndPtr
? wndPtr
->hmemTaskQ
: 0;
1306 /* send WM_ACTIVATEAPP if necessary */
1307 if (hOldActiveQueue
!= hNewActiveQueue
)
1310 DWORD old_thread
= GetWindowThreadProcessId( hwndPrevActive
, NULL
);
1311 DWORD new_thread
= GetWindowThreadProcessId( hwndActive
, NULL
);
1313 if ((list
= WIN_ListChildren( GetDesktopWindow() )))
1315 for (phwnd
= list
; *phwnd
; phwnd
++)
1317 if (!IsWindow( *phwnd
)) continue;
1318 if (GetWindowThreadProcessId( *phwnd
, NULL
) == old_thread
)
1319 SendNotifyMessageW( *phwnd
, WM_ACTIVATEAPP
, 0, new_thread
);
1321 HeapFree( GetProcessHeap(), 0, list
);
1324 hActiveQueue
= hNewActiveQueue
;
1326 if ((list
= WIN_ListChildren( GetDesktopWindow() )))
1328 for (phwnd
= list
; *phwnd
; phwnd
++)
1330 if (!IsWindow( *phwnd
)) continue;
1331 if (GetWindowThreadProcessId( *phwnd
, NULL
) == new_thread
)
1332 SendMessageW( *phwnd
, WM_ACTIVATEAPP
, 1, old_thread
);
1334 HeapFree( GetProcessHeap(), 0, list
);
1337 if (hWnd
&& !IsWindow(hWnd
)) goto CLEANUP
;
1342 /* walk up to the first unowned window */
1343 HWND tmp
= GetAncestor( hWnd
, GA_ROOTOWNER
);
1344 if ((wndTemp
= WIN_FindWndPtr( tmp
)))
1346 /* and set last active owned popup */
1347 wndTemp
->hwndLastActive
= hWnd
;
1349 wIconized
= HIWORD(wndTemp
->dwStyle
& WS_MINIMIZE
);
1350 WIN_ReleaseWndPtr(wndTemp
);
1352 SendMessageA( hWnd
, WM_NCACTIVATE
, TRUE
, 0 );
1353 SendMessageA( hWnd
, WM_ACTIVATE
,
1354 MAKEWPARAM( (fMouse
) ? WA_CLICKACTIVE
: WA_ACTIVE
, wIconized
),
1355 (LPARAM
)hwndPrevActive
);
1356 if( !IsWindow(hWnd
) ) goto CLEANUP
;
1359 /* change focus if possible */
1362 if ( pNewActiveQueue
)
1364 HWND hOldFocus
= PERQDATA_GetFocusWnd( pNewActiveQueue
->pQData
);
1366 if ( !hOldFocus
|| GetAncestor( hOldFocus
, GA_ROOT
) != hwndActive
)
1367 FOCUS_SwitchFocus( pNewActiveQueue
, hOldFocus
,
1368 (wndPtr
&& (wndPtr
->dwStyle
& WS_MINIMIZE
))?
1372 if ( pOldActiveQueue
&&
1373 ( !pNewActiveQueue
||
1374 pNewActiveQueue
->pQData
!= pOldActiveQueue
->pQData
) )
1376 HWND hOldFocus
= PERQDATA_GetFocusWnd( pOldActiveQueue
->pQData
);
1378 FOCUS_SwitchFocus( pOldActiveQueue
, hOldFocus
, 0 );
1382 if( !hwndPrevActive
&& wndPtr
)
1384 if (USER_Driver
.pForceWindowRaise
) USER_Driver
.pForceWindowRaise( wndPtr
->hwndSelf
);
1387 /* if active wnd is minimized redraw icon title */
1388 if( IsIconic(hwndActive
) ) WINPOS_RedrawIconTitle(hwndActive
);
1390 bRet
= (hWnd
== hwndActive
); /* Success? */
1392 CLEANUP
: /* Unlock the message queues before returning */
1394 if ( pNewActiveQueue
)
1395 QUEUE_Unlock( pNewActiveQueue
);
1399 if ( pOldActiveQueue
)
1400 QUEUE_Unlock( pOldActiveQueue
);
1402 WIN_ReleaseWndPtr(wndPtr
);
1406 /*******************************************************************
1407 * WINPOS_ActivateOtherWindow
1409 * Activates window other than pWnd.
1411 void WINPOS_ActivateOtherWindow(HWND hwnd
)
1413 HWND hwndActive
= 0;
1415 HWND hwndDefaultTo
= 0;
1418 /* Get current active window from the active queue */
1421 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
1424 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
1425 QUEUE_Unlock( pActiveQueue
);
1429 if (!(hwnd
= WIN_IsCurrentThread( hwnd
))) return;
1431 if( hwnd
== hwndPrevActive
)
1434 if( hwndActive
!= hwnd
&& (hwndActive
|| USER_IsExitingThread( GetCurrentThreadId() )))
1437 if (!(GetWindowLongW( hwnd
, GWL_STYLE
) & WS_POPUP
) ||
1438 !(owner
= GetWindow( hwnd
, GW_OWNER
)) ||
1439 !WINPOS_CanActivate((hwndTo
= GetAncestor( owner
, GA_ROOT
))) ||
1440 !WINPOS_IsVisible(hwndTo
))
1442 HWND tmp
= GetAncestor( hwnd
, GA_ROOT
);
1443 hwndTo
= hwndPrevActive
;
1445 while( !WINPOS_CanActivate(hwndTo
) || !WINPOS_IsVisible(hwndTo
))
1447 /* by now owned windows should've been taken care of */
1448 if(!hwndDefaultTo
&& WINPOS_CanActivate(hwndTo
))
1449 hwndDefaultTo
= hwndTo
;
1450 tmp
= hwndTo
= GetWindow( tmp
, GW_HWNDNEXT
);
1453 hwndTo
= hwndDefaultTo
;
1459 SetActiveWindow( hwndTo
);
1464 /***********************************************************************
1465 * WINPOS_HandleWindowPosChanging16
1467 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
1469 LONG
WINPOS_HandleWindowPosChanging16( HWND hwnd
, WINDOWPOS16
*winpos
)
1471 POINT maxSize
, minTrack
;
1472 LONG style
= GetWindowLongA( hwnd
, GWL_STYLE
);
1474 if (winpos
->flags
& SWP_NOSIZE
) return 0;
1475 if ((style
& WS_THICKFRAME
) || ((style
& (WS_POPUP
| WS_CHILD
)) == 0))
1477 WINPOS_GetMinMaxInfo( hwnd
, &maxSize
, NULL
, &minTrack
, NULL
);
1478 if (maxSize
.x
< winpos
->cx
) winpos
->cx
= maxSize
.x
;
1479 if (maxSize
.y
< winpos
->cy
) winpos
->cy
= maxSize
.y
;
1480 if (!(style
& WS_MINIMIZE
))
1482 if (winpos
->cx
< minTrack
.x
) winpos
->cx
= minTrack
.x
;
1483 if (winpos
->cy
< minTrack
.y
) winpos
->cy
= minTrack
.y
;
1490 /***********************************************************************
1491 * WINPOS_HandleWindowPosChanging
1493 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
1495 LONG
WINPOS_HandleWindowPosChanging( HWND hwnd
, WINDOWPOS
*winpos
)
1497 POINT maxSize
, minTrack
;
1498 LONG style
= GetWindowLongA( hwnd
, GWL_STYLE
);
1500 if (winpos
->flags
& SWP_NOSIZE
) return 0;
1501 if ((style
& WS_THICKFRAME
) || ((style
& (WS_POPUP
| WS_CHILD
)) == 0))
1503 WINPOS_GetMinMaxInfo( hwnd
, &maxSize
, NULL
, &minTrack
, NULL
);
1504 winpos
->cx
= min( winpos
->cx
, maxSize
.x
);
1505 winpos
->cy
= min( winpos
->cy
, maxSize
.y
);
1506 if (!(style
& WS_MINIMIZE
))
1508 if (winpos
->cx
< minTrack
.x
) winpos
->cx
= minTrack
.x
;
1509 if (winpos
->cy
< minTrack
.y
) winpos
->cy
= minTrack
.y
;
1516 /***********************************************************************
1517 * SetWindowPos (USER32.@)
1519 BOOL WINAPI
SetWindowPos( HWND hwnd
, HWND hwndInsertAfter
,
1520 INT x
, INT y
, INT cx
, INT cy
, UINT flags
)
1525 winpos
.hwndInsertAfter
= hwndInsertAfter
;
1530 winpos
.flags
= flags
;
1531 if (WIN_IsCurrentThread( hwnd
)) return USER_Driver
.pSetWindowPos( &winpos
);
1532 return SendMessageW( winpos
.hwnd
, WM_WINE_SETWINDOWPOS
, 0, (LPARAM
)&winpos
);
1536 /***********************************************************************
1537 * BeginDeferWindowPos (USER32.@)
1539 HDWP WINAPI
BeginDeferWindowPos( INT count
)
1546 SetLastError(ERROR_INVALID_PARAMETER
);
1549 /* Windows allows zero count, in which case it allocates context for 8 moves */
1550 if (count
== 0) count
= 8;
1552 handle
= USER_HEAP_ALLOC( sizeof(DWP
) + (count
-1)*sizeof(WINDOWPOS
) );
1553 if (!handle
) return 0;
1554 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( handle
);
1555 pDWP
->actualCount
= 0;
1556 pDWP
->suggestedCount
= count
;
1558 pDWP
->wMagic
= DWP_MAGIC
;
1559 pDWP
->hwndParent
= 0;
1564 /***********************************************************************
1565 * DeferWindowPos (USER32.@)
1567 HDWP WINAPI
DeferWindowPos( HDWP hdwp
, HWND hwnd
, HWND hwndAfter
,
1568 INT x
, INT y
, INT cx
, INT cy
,
1573 HDWP newhdwp
= hdwp
,retvalue
;
1575 hwnd
= WIN_GetFullHandle( hwnd
);
1576 if (hwnd
== GetDesktopWindow()) return 0;
1578 if (!(pDWP
= USER_HEAP_LIN_ADDR( hdwp
))) return 0;
1582 for (i
= 0; i
< pDWP
->actualCount
; i
++)
1584 if (pDWP
->winPos
[i
].hwnd
== hwnd
)
1586 /* Merge with the other changes */
1587 if (!(flags
& SWP_NOZORDER
))
1589 pDWP
->winPos
[i
].hwndInsertAfter
= hwndAfter
;
1591 if (!(flags
& SWP_NOMOVE
))
1593 pDWP
->winPos
[i
].x
= x
;
1594 pDWP
->winPos
[i
].y
= y
;
1596 if (!(flags
& SWP_NOSIZE
))
1598 pDWP
->winPos
[i
].cx
= cx
;
1599 pDWP
->winPos
[i
].cy
= cy
;
1601 pDWP
->winPos
[i
].flags
&= flags
| ~(SWP_NOSIZE
| SWP_NOMOVE
|
1602 SWP_NOZORDER
| SWP_NOREDRAW
|
1603 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
1605 pDWP
->winPos
[i
].flags
|= flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
|
1611 if (pDWP
->actualCount
>= pDWP
->suggestedCount
)
1613 newhdwp
= USER_HEAP_REALLOC( hdwp
,
1614 sizeof(DWP
) + pDWP
->suggestedCount
*sizeof(WINDOWPOS
) );
1620 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( newhdwp
);
1621 pDWP
->suggestedCount
++;
1623 pDWP
->winPos
[pDWP
->actualCount
].hwnd
= hwnd
;
1624 pDWP
->winPos
[pDWP
->actualCount
].hwndInsertAfter
= hwndAfter
;
1625 pDWP
->winPos
[pDWP
->actualCount
].x
= x
;
1626 pDWP
->winPos
[pDWP
->actualCount
].y
= y
;
1627 pDWP
->winPos
[pDWP
->actualCount
].cx
= cx
;
1628 pDWP
->winPos
[pDWP
->actualCount
].cy
= cy
;
1629 pDWP
->winPos
[pDWP
->actualCount
].flags
= flags
;
1630 pDWP
->actualCount
++;
1638 /***********************************************************************
1639 * EndDeferWindowPos (USER32.@)
1641 BOOL WINAPI
EndDeferWindowPos( HDWP hdwp
)
1648 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
1649 if (!pDWP
) return FALSE
;
1650 for (i
= 0, winpos
= pDWP
->winPos
; i
< pDWP
->actualCount
; i
++, winpos
++)
1652 if (!(res
= USER_Driver
.pSetWindowPos( winpos
))) break;
1654 USER_HEAP_FREE( hdwp
);
1659 /***********************************************************************
1660 * TileChildWindows (USER.199)
1662 void WINAPI
TileChildWindows16( HWND16 parent
, WORD action
)
1664 FIXME("(%04x, %d): stub\n", parent
, action
);
1667 /***********************************************************************
1668 * CascadeChildWindows (USER.198)
1670 void WINAPI
CascadeChildWindows16( HWND16 parent
, WORD action
)
1672 FIXME("(%04x, %d): stub\n", parent
, action
);
1675 /***********************************************************************
1676 * SetProgmanWindow (USER32.@)
1678 HWND WINAPI
SetProgmanWindow ( HWND hwnd
)
1680 hGlobalProgmanWindow
= hwnd
;
1681 return hGlobalProgmanWindow
;
1684 /***********************************************************************
1685 * GetProgmanWindow (USER32.@)
1687 HWND WINAPI
GetProgmanWindow(void)
1689 return hGlobalProgmanWindow
;
1692 /***********************************************************************
1693 * SetShellWindowEx (USER32.@)
1694 * hwndProgman = Progman[Program Manager]
1695 * |-> SHELLDLL_DefView
1696 * hwndListView = | |-> SysListView32
1697 * | | |-> tooltips_class32
1703 HWND WINAPI
SetShellWindowEx ( HWND hwndProgman
, HWND hwndListView
)
1705 FIXME("0x%08x 0x%08x stub\n",hwndProgman
,hwndListView
);
1706 hGlobalShellWindow
= hwndProgman
;
1707 return hGlobalShellWindow
;
1711 /***********************************************************************
1712 * SetTaskmanWindow (USER32.@)
1714 * hwnd = MSTaskSwWClass
1715 * |-> SysTabControl32
1717 HWND WINAPI
SetTaskmanWindow ( HWND hwnd
)
1719 hGlobalTaskmanWindow
= hwnd
;
1720 return hGlobalTaskmanWindow
;
1723 /***********************************************************************
1724 * GetTaskmanWindow (USER32.@)
1726 HWND WINAPI
GetTaskmanWindow(void)
1728 return hGlobalTaskmanWindow
;