2 * Window position related functions.
4 * Copyright 1993, 1994, 1995 Alexandre Julliard
5 * 1995, 1996, 1999 Alex Korobka
13 #include "wine/winuser16.h"
23 #include "nonclient.h"
24 #include "debugtools.h"
27 DEFAULT_DEBUG_CHANNEL(win);
29 #define HAS_DLGFRAME(style,exStyle) \
30 (((exStyle) & WS_EX_DLGMODALFRAME) || \
31 (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
33 #define HAS_THICKFRAME(style) \
34 (((style) & WS_THICKFRAME) && \
35 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
37 #define EMPTYPOINT(pt) ((*(LONG*)&(pt)) == -1)
39 #define PLACE_MIN 0x0001
40 #define PLACE_MAX 0x0002
41 #define PLACE_RECT 0x0004
44 #define DWP_MAGIC ((INT)('W' | ('P' << 8) | ('O' << 16) | ('S' << 24)))
56 /* ----- internal variables ----- */
58 static HWND hwndPrevActive = 0; /* Previously active window */
59 static HWND hGlobalShellWindow=0; /*the shell*/
60 static HWND hGlobalTaskmanWindow=0;
61 static HWND hGlobalProgmanWindow=0;
63 static LPCSTR atomInternalPos;
65 extern HQUEUE16 hActiveQueue;
67 /***********************************************************************
68 * WINPOS_CreateInternalPosAtom
70 BOOL WINPOS_CreateInternalPosAtom()
73 atomInternalPos = (LPCSTR)(DWORD)GlobalAddAtomA(str);
74 return (atomInternalPos) ? TRUE : FALSE;
77 /***********************************************************************
78 * WINPOS_CheckInternalPos
80 * Called when a window is destroyed.
82 void WINPOS_CheckInternalPos( HWND hwnd )
85 MESSAGEQUEUE *pMsgQ = 0;
86 WND *wndPtr = WIN_FindWndPtr( hwnd );
88 lpPos = (LPINTERNALPOS) GetPropA( hwnd, atomInternalPos );
90 /* Retrieve the message queue associated with this window */
91 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
94 WARN("\tMessage queue not found. Exiting!\n" );
95 WIN_ReleaseWndPtr( wndPtr );
99 if( hwnd == hwndPrevActive ) hwndPrevActive = 0;
101 if( hwnd == PERQDATA_GetActiveWnd( pMsgQ->pQData ) )
103 PERQDATA_SetActiveWnd( pMsgQ->pQData, 0 );
104 WARN("\tattempt to activate destroyed window!\n");
109 if( IsWindow(lpPos->hwndIconTitle) )
110 DestroyWindow( lpPos->hwndIconTitle );
111 HeapFree( GetProcessHeap(), 0, lpPos );
114 QUEUE_Unlock( pMsgQ );
115 WIN_ReleaseWndPtr( wndPtr );
119 /***********************************************************************
120 * ArrangeIconicWindows (USER.170)
122 UINT16 WINAPI ArrangeIconicWindows16( HWND16 parent)
124 return ArrangeIconicWindows(parent);
126 /***********************************************************************
127 * ArrangeIconicWindows (USER32.@)
129 UINT WINAPI ArrangeIconicWindows( HWND parent )
133 INT x, y, xspacing, yspacing;
135 GetClientRect( parent, &rectParent );
137 y = rectParent.bottom;
138 xspacing = GetSystemMetrics(SM_CXICONSPACING);
139 yspacing = GetSystemMetrics(SM_CYICONSPACING);
141 hwndChild = GetWindow( parent, GW_CHILD );
144 if( IsIconic( hwndChild ) )
146 WINPOS_ShowIconTitle( hwndChild, FALSE );
148 SetWindowPos( hwndChild, 0, x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2,
149 y - yspacing - GetSystemMetrics(SM_CYICON)/2, 0, 0,
150 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
151 if( IsWindow(hwndChild) )
152 WINPOS_ShowIconTitle(hwndChild , TRUE );
154 if (x <= rectParent.right - xspacing) x += xspacing;
161 hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
167 /***********************************************************************
168 * SwitchToThisWindow (USER.172)
170 void WINAPI SwitchToThisWindow16( HWND16 hwnd, BOOL16 restore )
172 SwitchToThisWindow( hwnd, restore );
176 /***********************************************************************
177 * SwitchToThisWindow (USER32.@)
179 void WINAPI SwitchToThisWindow( HWND hwnd, BOOL restore )
181 ShowWindow( hwnd, restore ? SW_RESTORE : SW_SHOWMINIMIZED );
185 /***********************************************************************
186 * GetWindowRect (USER.32)
188 void WINAPI GetWindowRect16( HWND16 hwnd, LPRECT16 rect )
190 WND * wndPtr = WIN_FindWndPtr( hwnd );
193 CONV_RECT32TO16( &wndPtr->rectWindow, rect );
195 MapWindowPoints16( wndPtr->parent->hwndSelf, 0, (POINT16 *)rect, 2 );
196 WIN_ReleaseWndPtr(wndPtr);
200 /***********************************************************************
201 * GetWindowRect (USER32.@)
203 BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect )
205 WND * wndPtr = WIN_FindWndPtr( hwnd );
206 if (!wndPtr) return FALSE;
208 *rect = wndPtr->rectWindow;
210 MapWindowPoints( wndPtr->parent->hwndSelf, 0, (POINT *)rect, 2 );
211 WIN_ReleaseWndPtr(wndPtr);
212 TRACE("hwnd %04x (%d,%d)-(%d,%d)\n",
213 hwnd, rect->left, rect->top, rect->right, rect->bottom);
218 /***********************************************************************
219 * GetWindowRgn (USER32.@)
221 int WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
224 WND *wndPtr = WIN_FindWndPtr( hwnd );
227 if (wndPtr->hrgnWnd) nRet = CombineRgn( hrgn, wndPtr->hrgnWnd, 0, RGN_COPY );
228 WIN_ReleaseWndPtr(wndPtr);
233 /***********************************************************************
234 * SetWindowRgn (USER32.@)
236 int WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL bRedraw )
242 if (USER_Driver.pSetWindowRgn)
243 return USER_Driver.pSetWindowRgn( hwnd, hrgn, bRedraw );
245 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
247 if (wndPtr->hrgnWnd == hrgn)
253 if (hrgn) /* verify that region really exists */
255 if (GetRgnBox( hrgn, &rect ) == ERROR) goto done;
260 /* delete previous region */
261 DeleteObject(wndPtr->hrgnWnd);
264 wndPtr->hrgnWnd = hrgn;
266 /* Size the window to the rectangle of the new region (if it isn't NULL) */
267 if (hrgn) SetWindowPos( hwnd, 0, rect.left, rect.top,
268 rect.right - rect.left, rect.bottom - rect.top,
269 SWP_NOSIZE | SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOACTIVATE |
270 SWP_NOZORDER | (bRedraw ? 0 : SWP_NOREDRAW) );
274 WIN_ReleaseWndPtr(wndPtr);
278 /***********************************************************************
279 * SetWindowRgn (USER.668)
281 INT16 WINAPI SetWindowRgn16( HWND16 hwnd, HRGN16 hrgn,BOOL16 bRedraw)
285 FIXME("SetWindowRgn16: stub\n");
290 /***********************************************************************
291 * GetClientRect (USER.33)
293 void WINAPI GetClientRect16( HWND16 hwnd, LPRECT16 rect )
295 WND * wndPtr = WIN_FindWndPtr( hwnd );
297 rect->left = rect->top = rect->right = rect->bottom = 0;
300 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
301 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
303 WIN_ReleaseWndPtr(wndPtr);
307 /***********************************************************************
308 * GetClientRect (USER32.@)
310 BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect )
312 WND * wndPtr = WIN_FindWndPtr( hwnd );
314 rect->left = rect->top = rect->right = rect->bottom = 0;
315 if (!wndPtr) return FALSE;
316 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
317 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
319 WIN_ReleaseWndPtr(wndPtr);
320 TRACE("hwnd %04x (%d,%d)-(%d,%d)\n",
321 hwnd, rect->left, rect->top, rect->right, rect->bottom);
326 /*******************************************************************
327 * ClientToScreen (USER.28)
329 void WINAPI ClientToScreen16( HWND16 hwnd, LPPOINT16 lppnt )
331 MapWindowPoints16( hwnd, 0, lppnt, 1 );
335 /*******************************************************************
336 * ClientToScreen (USER32.@)
338 BOOL WINAPI ClientToScreen( HWND hwnd, LPPOINT lppnt )
340 MapWindowPoints( hwnd, 0, lppnt, 1 );
345 /*******************************************************************
346 * ScreenToClient (USER.29)
348 void WINAPI ScreenToClient16( HWND16 hwnd, LPPOINT16 lppnt )
350 MapWindowPoints16( 0, hwnd, lppnt, 1 );
354 /*******************************************************************
355 * ScreenToClient (USER32.@)
357 BOOL WINAPI ScreenToClient( HWND hwnd, LPPOINT lppnt )
359 MapWindowPoints( 0, hwnd, lppnt, 1 );
364 /***********************************************************************
365 * WINPOS_WindowFromPoint
367 * Find the window and hittest for a given point.
369 HWND WINPOS_WindowFromPoint( HWND hwndScope, POINT pt, INT *hittest )
371 WND *wndScope, *wndPtr, *wndTmp;
375 TRACE("scope %04x %ld,%ld\n", hwndScope, pt.x, pt.y);
377 if (!hwndScope) hwndScope = GetDesktopWindow();
378 if (!(wndScope = WIN_FindWndPtr( hwndScope ))) return 0;
381 wndPtr = WIN_LockWndPtr(wndScope->child);
383 if( wndScope->dwStyle & WS_DISABLED )
389 if (wndScope->parent)
390 MapWindowPoints( GetDesktopWindow(), wndScope->parent->hwndSelf, &xy, 1 );
392 if (xy.x < wndScope->rectClient.left || pt.x >= wndScope->rectClient.right ||
393 xy.y < wndScope->rectClient.top || pt.y >= wndScope->rectClient.bottom ||
394 wndScope->dwStyle & WS_MINIMIZE)
397 xy.x -= wndScope->rectClient.left;
398 xy.y -= wndScope->rectClient.top;
404 /* If point is in window, and window is visible, and it */
405 /* is enabled (or it's a top-level window), then explore */
406 /* its children. Otherwise, go to the next window. */
408 if ((wndPtr->dwStyle & WS_VISIBLE) &&
409 ((wndPtr->dwExStyle & (WS_EX_LAYERED | WS_EX_TRANSPARENT)) != (WS_EX_LAYERED | WS_EX_TRANSPARENT)) &&
410 (!(wndPtr->dwStyle & WS_DISABLED) ||
411 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)) &&
413 PtInRegion(wndPtr->hrgnWnd, xy.x - wndPtr->rectWindow.left,
414 xy.y - wndPtr->rectWindow.top) :
415 ((xy.x >= wndPtr->rectWindow.left) &&
416 (xy.x < wndPtr->rectWindow.right) &&
417 (xy.y >= wndPtr->rectWindow.top) &&
418 (xy.y < wndPtr->rectWindow.bottom))))
420 TRACE("%ld,%ld is inside %04x\n", xy.x, xy.y, wndPtr->hwndSelf);
421 hwnd_ret = wndPtr->hwndSelf; /* Got a suitable window */
423 /* If window is minimized or disabled, return at once */
424 if (wndPtr->dwStyle & WS_MINIMIZE)
426 *hittest = HTCAPTION;
429 if (wndPtr->dwStyle & WS_DISABLED)
435 /* If point is not in client area, ignore the children */
436 if ((xy.x < wndPtr->rectClient.left) ||
437 (xy.x >= wndPtr->rectClient.right) ||
438 (xy.y < wndPtr->rectClient.top) ||
439 (xy.y >= wndPtr->rectClient.bottom)) break;
441 xy.x -= wndPtr->rectClient.left;
442 xy.y -= wndPtr->rectClient.top;
443 WIN_UpdateWndPtr(&wndPtr,wndPtr->child);
447 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
452 /* If nothing found, try the scope window */
453 if (!hwnd_ret) hwnd_ret = hwndScope;
455 /* Send the WM_NCHITTEST message (only if to the same task) */
456 if (GetWindowThreadProcessId( hwnd_ret, NULL ) == GetCurrentThreadId())
458 INT res = SendMessageA( hwnd_ret, WM_NCHITTEST, 0, MAKELONG( pt.x, pt.y ) );
459 if (res != HTTRANSPARENT)
461 *hittest = res; /* Found the window */
471 if (!(wndTmp = WIN_FindWndPtr( hwnd_ret ))) break;
473 /* If no children found in last search, make point relative to parent */
476 xy.x += wndTmp->rectClient.left;
477 xy.y += wndTmp->rectClient.top;
480 /* Restart the search from the next sibling */
481 WIN_UpdateWndPtr(&wndPtr,wndTmp->next);
482 hwnd_ret = wndTmp->parent ? wndTmp->parent->hwndSelf : 0;
483 WIN_ReleaseWndPtr( wndTmp );
487 WIN_ReleaseWndPtr(wndPtr);
488 WIN_ReleaseWndPtr(wndScope);
493 /*******************************************************************
494 * WindowFromPoint (USER.30)
496 HWND16 WINAPI WindowFromPoint16( POINT16 pt )
500 CONV_POINT16TO32( &pt, &pt32 );
501 return WindowFromPoint( pt32 );
505 /*******************************************************************
506 * WindowFromPoint (USER32.@)
508 HWND WINAPI WindowFromPoint( POINT pt )
511 return WINPOS_WindowFromPoint( 0, pt, &hittest );
515 /*******************************************************************
516 * ChildWindowFromPoint (USER.191)
518 HWND16 WINAPI ChildWindowFromPoint16( HWND16 hwndParent, POINT16 pt )
521 CONV_POINT16TO32( &pt, &pt32 );
522 return (HWND16)ChildWindowFromPoint( hwndParent, pt32 );
526 /*******************************************************************
527 * ChildWindowFromPoint (USER32.@)
529 HWND WINAPI ChildWindowFromPoint( HWND hwndParent, POINT pt )
531 /* pt is in the client coordinates */
533 WND* wnd = WIN_FindWndPtr(hwndParent);
539 /* get client rect fast */
540 rect.top = rect.left = 0;
541 rect.right = wnd->rectClient.right - wnd->rectClient.left;
542 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
544 if (!PtInRect( &rect, pt ))
549 WIN_UpdateWndPtr(&wnd,wnd->child);
552 if (PtInRect( &wnd->rectWindow, pt ))
554 retvalue = wnd->hwndSelf;
557 WIN_UpdateWndPtr(&wnd,wnd->next);
559 retvalue = hwndParent;
561 WIN_ReleaseWndPtr(wnd);
565 /*******************************************************************
566 * ChildWindowFromPointEx (USER.399)
568 HWND16 WINAPI ChildWindowFromPointEx16( HWND16 hwndParent, POINT16 pt, UINT16 uFlags)
571 CONV_POINT16TO32( &pt, &pt32 );
572 return (HWND16)ChildWindowFromPointEx( hwndParent, pt32, uFlags );
576 /*******************************************************************
577 * ChildWindowFromPointEx (USER32.@)
579 HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt,
582 /* pt is in the client coordinates */
584 WND* wnd = WIN_FindWndPtr(hwndParent);
590 /* get client rect fast */
591 rect.top = rect.left = 0;
592 rect.right = wnd->rectClient.right - wnd->rectClient.left;
593 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
595 if (!PtInRect( &rect, pt ))
600 WIN_UpdateWndPtr(&wnd,wnd->child);
604 if (PtInRect( &wnd->rectWindow, pt )) {
605 if ( (uFlags & CWP_SKIPINVISIBLE) &&
606 !(wnd->dwStyle & WS_VISIBLE) );
607 else if ( (uFlags & CWP_SKIPDISABLED) &&
608 (wnd->dwStyle & WS_DISABLED) );
609 else if ( (uFlags & CWP_SKIPTRANSPARENT) &&
610 (wnd->dwExStyle & WS_EX_TRANSPARENT) );
613 retvalue = wnd->hwndSelf;
618 WIN_UpdateWndPtr(&wnd,wnd->next);
620 retvalue = hwndParent;
622 WIN_ReleaseWndPtr(wnd);
627 /*******************************************************************
628 * WINPOS_GetWinOffset
630 * Calculate the offset between the origin of the two windows. Used
631 * to implement MapWindowPoints.
633 static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo,
638 offset->x = offset->y = 0;
639 if (hwndFrom == hwndTo ) return;
641 /* Translate source window origin to screen coords */
644 if (!(wndPtr = WIN_FindWndPtr( hwndFrom )))
646 ERR("bad hwndFrom = %04x\n",hwndFrom);
649 while (wndPtr->parent)
651 offset->x += wndPtr->rectClient.left;
652 offset->y += wndPtr->rectClient.top;
653 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
655 WIN_ReleaseWndPtr(wndPtr);
658 /* Translate origin to destination window coords */
661 if (!(wndPtr = WIN_FindWndPtr( hwndTo )))
663 ERR("bad hwndTo = %04x\n", hwndTo );
666 while (wndPtr->parent)
668 offset->x -= wndPtr->rectClient.left;
669 offset->y -= wndPtr->rectClient.top;
670 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
672 WIN_ReleaseWndPtr(wndPtr);
677 /*******************************************************************
678 * MapWindowPoints (USER.258)
680 void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
681 LPPOINT16 lppt, UINT16 count )
685 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
695 /*******************************************************************
696 * MapWindowPoints (USER32.@)
698 INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo,
699 LPPOINT lppt, UINT count )
703 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
710 return MAKELONG( LOWORD(offset.x), LOWORD(offset.y) );
714 /***********************************************************************
717 BOOL16 WINAPI IsIconic16(HWND16 hWnd)
719 return IsIconic(hWnd);
723 /***********************************************************************
724 * IsIconic (USER32.@)
726 BOOL WINAPI IsIconic(HWND hWnd)
729 WND * wndPtr = WIN_FindWndPtr(hWnd);
730 if (wndPtr == NULL) return FALSE;
731 retvalue = (wndPtr->dwStyle & WS_MINIMIZE) != 0;
732 WIN_ReleaseWndPtr(wndPtr);
737 /***********************************************************************
738 * IsZoomed (USER.272)
740 BOOL16 WINAPI IsZoomed16(HWND16 hWnd)
742 return IsZoomed(hWnd);
746 /***********************************************************************
747 * IsZoomed (USER32.@)
749 BOOL WINAPI IsZoomed(HWND hWnd)
752 WND * wndPtr = WIN_FindWndPtr(hWnd);
753 if (wndPtr == NULL) return FALSE;
754 retvalue = (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
755 WIN_ReleaseWndPtr(wndPtr);
760 /*******************************************************************
761 * GetActiveWindow (USER.60)
763 HWND16 WINAPI GetActiveWindow16(void)
765 return (HWND16)GetActiveWindow();
768 /*******************************************************************
769 * GetActiveWindow (USER32.@)
771 HWND WINAPI GetActiveWindow(void)
773 MESSAGEQUEUE *pCurMsgQ = 0;
775 /* Get the messageQ for the current thread */
776 if (!(pCurMsgQ = QUEUE_Current()))
778 WARN("\tCurrent message queue not found. Exiting!\n" );
782 /* Return the current active window from the perQ data of the current message Q */
783 return PERQDATA_GetActiveWnd( pCurMsgQ->pQData );
787 /*******************************************************************
790 static BOOL WINPOS_CanActivate(WND* pWnd)
792 if( pWnd && ( (pWnd->dwStyle & (WS_DISABLED | WS_VISIBLE | WS_CHILD))
793 == WS_VISIBLE ) ) return TRUE;
798 /*******************************************************************
799 * SetActiveWindow (USER.59)
801 HWND16 WINAPI SetActiveWindow16( HWND16 hwnd )
803 return SetActiveWindow(hwnd);
807 /*******************************************************************
808 * SetActiveWindow (USER32.@)
810 HWND WINAPI SetActiveWindow( HWND hwnd )
813 WND *wndPtr = WIN_FindWndPtr( hwnd );
814 MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
816 if (!wndPtr || (wndPtr->dwStyle & (WS_DISABLED | WS_CHILD)))
822 /* Get the messageQ for the current thread */
823 if (!(pCurMsgQ = QUEUE_Current()))
825 WARN("\tCurrent message queue not found. Exiting!\n" );
829 /* Retrieve the message queue associated with this window */
830 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
833 WARN("\tWindow message queue not found. Exiting!\n" );
837 /* Make sure that the window is associated with the calling threads
838 * message queue. It must share the same perQ data.
841 if ( pCurMsgQ->pQData != pMsgQ->pQData )
844 /* Save current active window */
845 prev = PERQDATA_GetActiveWnd( pMsgQ->pQData );
847 WINPOS_SetActiveWindow( hwnd, 0, 0 );
850 /* Unlock the queues before returning */
852 QUEUE_Unlock( pMsgQ );
855 WIN_ReleaseWndPtr(wndPtr);
860 /*******************************************************************
861 * GetForegroundWindow (USER.608)
863 HWND16 WINAPI GetForegroundWindow16(void)
865 return (HWND16)GetForegroundWindow();
869 /*******************************************************************
870 * SetForegroundWindow (USER.609)
872 BOOL16 WINAPI SetForegroundWindow16( HWND16 hwnd )
874 return SetForegroundWindow( hwnd );
878 /*******************************************************************
879 * GetForegroundWindow (USER32.@)
881 HWND WINAPI GetForegroundWindow(void)
885 /* Get the foreground window (active window of hActiveQueue) */
888 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
890 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
892 QUEUE_Unlock( pActiveQueue );
898 /*******************************************************************
899 * SetForegroundWindow (USER32.@)
901 BOOL WINAPI SetForegroundWindow( HWND hwnd )
903 return WINPOS_ChangeActiveWindow( hwnd, FALSE );
907 /*******************************************************************
908 * AllowSetForegroundWindow (USER32.@)
910 BOOL WINAPI AllowSetForegroundWindow( DWORD procid )
912 /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
913 * implemented, then fix this function. */
918 /*******************************************************************
919 * LockSetForegroundWindow (USER32.@)
921 BOOL WINAPI LockSetForegroundWindow( UINT lockcode )
923 /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
924 * implemented, then fix this function. */
929 /*******************************************************************
930 * GetShellWindow (USER.600)
932 HWND16 WINAPI GetShellWindow16(void)
934 return GetShellWindow();
937 /*******************************************************************
938 * SetShellWindow (USER32.@)
940 HWND WINAPI SetShellWindow(HWND hwndshell)
941 { WARN("(hWnd=%08x) semi stub\n",hwndshell );
943 hGlobalShellWindow = hwndshell;
944 return hGlobalShellWindow;
948 /*******************************************************************
949 * GetShellWindow (USER32.@)
951 HWND WINAPI GetShellWindow(void)
952 { WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow );
954 return hGlobalShellWindow;
958 /***********************************************************************
959 * BringWindowToTop (USER.45)
961 BOOL16 WINAPI BringWindowToTop16( HWND16 hwnd )
963 return BringWindowToTop(hwnd);
967 /***********************************************************************
968 * BringWindowToTop (USER32.@)
970 BOOL WINAPI BringWindowToTop( HWND hwnd )
972 return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
976 /***********************************************************************
977 * MoveWindow (USER.56)
979 BOOL16 WINAPI MoveWindow16( HWND16 hwnd, INT16 x, INT16 y, INT16 cx, INT16 cy,
982 return MoveWindow(hwnd,x,y,cx,cy,repaint);
986 /***********************************************************************
987 * MoveWindow (USER32.@)
989 BOOL WINAPI MoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy,
992 int flags = SWP_NOZORDER | SWP_NOACTIVATE;
993 if (!repaint) flags |= SWP_NOREDRAW;
994 TRACE("%04x %d,%d %dx%d %d\n",
995 hwnd, x, y, cx, cy, repaint );
996 return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
999 /***********************************************************************
1000 * WINPOS_InitInternalPos
1002 static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT pt,
1003 LPRECT restoreRect )
1005 LPINTERNALPOS lpPos = (LPINTERNALPOS) GetPropA( wnd->hwndSelf,
1009 /* this happens when the window is minimized/maximized
1010 * for the first time (rectWindow is not adjusted yet) */
1012 lpPos = HeapAlloc( GetProcessHeap(), 0, sizeof(INTERNALPOS) );
1013 if( !lpPos ) return NULL;
1015 SetPropA( wnd->hwndSelf, atomInternalPos, (HANDLE)lpPos );
1016 lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
1017 CONV_RECT32TO16( &wnd->rectWindow, &lpPos->rectNormal );
1018 *(UINT*)&lpPos->ptIconPos = *(UINT*)&lpPos->ptMaxPos = 0xFFFFFFFF;
1021 if( wnd->dwStyle & WS_MINIMIZE )
1022 CONV_POINT32TO16( &pt, &lpPos->ptIconPos );
1023 else if( wnd->dwStyle & WS_MAXIMIZE )
1024 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1025 else if( restoreRect )
1026 CONV_RECT32TO16( restoreRect, &lpPos->rectNormal );
1031 /***********************************************************************
1032 * WINPOS_RedrawIconTitle
1034 BOOL WINPOS_RedrawIconTitle( HWND hWnd )
1036 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hWnd, atomInternalPos );
1039 if( lpPos->hwndIconTitle )
1041 SendMessageA( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
1042 InvalidateRect( lpPos->hwndIconTitle, NULL, TRUE );
1049 /***********************************************************************
1050 * WINPOS_ShowIconTitle
1052 BOOL WINPOS_ShowIconTitle( HWND hwnd, BOOL bShow )
1054 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hwnd, atomInternalPos );
1056 if( lpPos && !(GetWindowLongA( hwnd, GWL_EXSTYLE) & WS_EX_MANAGED))
1058 HWND title = lpPos->hwndIconTitle;
1060 TRACE("0x%04x %i\n", hwnd, (bShow != 0) );
1063 lpPos->hwndIconTitle = title = ICONTITLE_Create( hwnd );
1066 if (!IsWindowVisible(title))
1068 SendMessageA( title, WM_SHOWWINDOW, TRUE, 0 );
1069 SetWindowPos( title, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
1070 SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
1073 else ShowWindow( title, SW_HIDE );
1078 /*******************************************************************
1079 * WINPOS_GetMinMaxInfo
1081 * Get the minimized and maximized information for a window.
1083 void WINPOS_GetMinMaxInfo( HWND hwnd, POINT *maxSize, POINT *maxPos,
1084 POINT *minTrack, POINT *maxTrack )
1086 LPINTERNALPOS lpPos;
1089 LONG style = GetWindowLongA( hwnd, GWL_STYLE );
1090 LONG exstyle = GetWindowLongA( hwnd, GWL_EXSTYLE );
1092 /* Compute default values */
1094 MinMax.ptMaxSize.x = GetSystemMetrics(SM_CXSCREEN);
1095 MinMax.ptMaxSize.y = GetSystemMetrics(SM_CYSCREEN);
1096 MinMax.ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
1097 MinMax.ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
1098 MinMax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXSCREEN);
1099 MinMax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYSCREEN);
1101 if (HAS_DLGFRAME( style, exstyle ))
1103 xinc = GetSystemMetrics(SM_CXDLGFRAME);
1104 yinc = GetSystemMetrics(SM_CYDLGFRAME);
1109 if (HAS_THICKFRAME(style))
1111 xinc += GetSystemMetrics(SM_CXFRAME);
1112 yinc += GetSystemMetrics(SM_CYFRAME);
1114 if (style & WS_BORDER)
1116 xinc += GetSystemMetrics(SM_CXBORDER);
1117 yinc += GetSystemMetrics(SM_CYBORDER);
1120 MinMax.ptMaxSize.x += 2 * xinc;
1121 MinMax.ptMaxSize.y += 2 * yinc;
1123 lpPos = (LPINTERNALPOS)GetPropA( hwnd, atomInternalPos );
1124 if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
1125 CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
1128 MinMax.ptMaxPosition.x = -xinc;
1129 MinMax.ptMaxPosition.y = -yinc;
1132 SendMessageA( hwnd, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
1134 /* Some sanity checks */
1136 TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1137 MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
1138 MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
1139 MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
1140 MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
1141 MinMax.ptMaxTrackSize.x = max( MinMax.ptMaxTrackSize.x,
1142 MinMax.ptMinTrackSize.x );
1143 MinMax.ptMaxTrackSize.y = max( MinMax.ptMaxTrackSize.y,
1144 MinMax.ptMinTrackSize.y );
1146 if (maxSize) *maxSize = MinMax.ptMaxSize;
1147 if (maxPos) *maxPos = MinMax.ptMaxPosition;
1148 if (minTrack) *minTrack = MinMax.ptMinTrackSize;
1149 if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
1152 /***********************************************************************
1153 * ShowWindowAsync (USER32.@)
1155 * doesn't wait; returns immediately.
1156 * used by threads to toggle windows in other (possibly hanging) threads
1158 BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd )
1160 /* FIXME: does ShowWindow() return immediately ? */
1161 return ShowWindow(hwnd, cmd);
1165 /***********************************************************************
1166 * ShowWindow (USER.42)
1168 BOOL16 WINAPI ShowWindow16( HWND16 hwnd, INT16 cmd )
1170 return ShowWindow(hwnd,cmd);
1174 /***********************************************************************
1175 * ShowWindow (USER32.@)
1177 BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
1179 return USER_Driver.pShowWindow( hwnd, cmd );
1183 /***********************************************************************
1184 * GetInternalWindowPos (USER.460)
1186 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
1189 WINDOWPLACEMENT16 wndpl;
1190 if (GetWindowPlacement16( hwnd, &wndpl ))
1192 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1193 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1194 return wndpl.showCmd;
1200 /***********************************************************************
1201 * GetInternalWindowPos (USER32.@)
1203 UINT WINAPI GetInternalWindowPos( HWND hwnd, LPRECT rectWnd,
1206 WINDOWPLACEMENT wndpl;
1207 if (GetWindowPlacement( hwnd, &wndpl ))
1209 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1210 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1211 return wndpl.showCmd;
1216 /***********************************************************************
1217 * GetWindowPlacement (USER.370)
1219 BOOL16 WINAPI GetWindowPlacement16( HWND16 hwnd, WINDOWPLACEMENT16 *wndpl )
1221 WND *pWnd = WIN_FindWndPtr( hwnd );
1222 LPINTERNALPOS lpPos;
1224 if(!pWnd ) return FALSE;
1226 lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1227 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1228 wndpl->length = sizeof(*wndpl);
1229 if( pWnd->dwStyle & WS_MINIMIZE )
1230 wndpl->showCmd = SW_SHOWMINIMIZED;
1232 wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE )
1233 ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
1234 if( pWnd->flags & WIN_RESTORE_MAX )
1235 wndpl->flags = WPF_RESTORETOMAXIMIZED;
1238 wndpl->ptMinPosition = lpPos->ptIconPos;
1239 wndpl->ptMaxPosition = lpPos->ptMaxPos;
1240 wndpl->rcNormalPosition = lpPos->rectNormal;
1242 WIN_ReleaseWndPtr(pWnd);
1247 /***********************************************************************
1248 * GetWindowPlacement (USER32.@)
1251 * Fails if wndpl->length of Win95 (!) apps is invalid.
1253 BOOL WINAPI GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *pwpl32 )
1257 WINDOWPLACEMENT16 wpl;
1258 wpl.length = sizeof(wpl);
1259 if( GetWindowPlacement16( hwnd, &wpl ) )
1261 pwpl32->length = sizeof(*pwpl32);
1262 pwpl32->flags = wpl.flags;
1263 pwpl32->showCmd = wpl.showCmd;
1264 CONV_POINT16TO32( &wpl.ptMinPosition, &pwpl32->ptMinPosition );
1265 CONV_POINT16TO32( &wpl.ptMaxPosition, &pwpl32->ptMaxPosition );
1266 CONV_RECT16TO32( &wpl.rcNormalPosition, &pwpl32->rcNormalPosition );
1274 /***********************************************************************
1275 * WINPOS_SetPlacement
1277 static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT16 *wndpl,
1280 WND *pWnd = WIN_FindWndPtr( hwnd );
1283 LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1284 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1286 if( flags & PLACE_MIN ) lpPos->ptIconPos = wndpl->ptMinPosition;
1287 if( flags & PLACE_MAX ) lpPos->ptMaxPos = wndpl->ptMaxPosition;
1288 if( flags & PLACE_RECT) lpPos->rectNormal = wndpl->rcNormalPosition;
1290 if( pWnd->dwStyle & WS_MINIMIZE )
1292 WINPOS_ShowIconTitle( pWnd->hwndSelf, FALSE );
1293 if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1294 SetWindowPos( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1295 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1297 else if( pWnd->dwStyle & WS_MAXIMIZE )
1299 if( !EMPTYPOINT(lpPos->ptMaxPos) )
1300 SetWindowPos( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1301 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1303 else if( flags & PLACE_RECT )
1304 SetWindowPos( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1305 lpPos->rectNormal.right - lpPos->rectNormal.left,
1306 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1307 SWP_NOZORDER | SWP_NOACTIVATE );
1309 ShowWindow( hwnd, wndpl->showCmd );
1310 if( IsWindow(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1312 if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd->hwndSelf, TRUE );
1314 /* SDK: ...valid only the next time... */
1315 if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1317 WIN_ReleaseWndPtr(pWnd);
1324 /***********************************************************************
1325 * SetWindowPlacement (USER.371)
1327 BOOL16 WINAPI SetWindowPlacement16(HWND16 hwnd, const WINDOWPLACEMENT16 *wndpl)
1329 return WINPOS_SetPlacement( hwnd, wndpl,
1330 PLACE_MIN | PLACE_MAX | PLACE_RECT );
1333 /***********************************************************************
1334 * SetWindowPlacement (USER32.@)
1337 * Fails if wndpl->length of Win95 (!) apps is invalid.
1339 BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *pwpl32 )
1343 WINDOWPLACEMENT16 wpl;
1345 wpl.length = sizeof(WINDOWPLACEMENT16);
1346 wpl.flags = pwpl32->flags;
1347 wpl.showCmd = pwpl32->showCmd;
1348 wpl.ptMinPosition.x = pwpl32->ptMinPosition.x;
1349 wpl.ptMinPosition.y = pwpl32->ptMinPosition.y;
1350 wpl.ptMaxPosition.x = pwpl32->ptMaxPosition.x;
1351 wpl.ptMaxPosition.y = pwpl32->ptMaxPosition.y;
1352 wpl.rcNormalPosition.left = pwpl32->rcNormalPosition.left;
1353 wpl.rcNormalPosition.top = pwpl32->rcNormalPosition.top;
1354 wpl.rcNormalPosition.right = pwpl32->rcNormalPosition.right;
1355 wpl.rcNormalPosition.bottom = pwpl32->rcNormalPosition.bottom;
1357 return WINPOS_SetPlacement( hwnd, &wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1363 /***********************************************************************
1364 * SetInternalWindowPos (USER.461)
1366 void WINAPI SetInternalWindowPos16( HWND16 hwnd, UINT16 showCmd,
1367 LPRECT16 rect, LPPOINT16 pt )
1369 if( IsWindow16(hwnd) )
1371 WINDOWPLACEMENT16 wndpl;
1374 wndpl.length = sizeof(wndpl);
1375 wndpl.showCmd = showCmd;
1376 wndpl.flags = flags = 0;
1381 wndpl.flags |= WPF_SETMINPOSITION;
1382 wndpl.ptMinPosition = *pt;
1386 flags |= PLACE_RECT;
1387 wndpl.rcNormalPosition = *rect;
1389 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1393 /***********************************************************************
1394 * AnimateWindow (USER32.@)
1395 * Shows/Hides a window with an animation
1398 BOOL WINAPI AnimateWindow(HWND hwnd, DWORD dwTime, DWORD dwFlags)
1400 FIXME("partial stub\n");
1402 /* If trying to show/hide and it's already *
1403 * shown/hidden or invalid window, fail with *
1404 * invalid parameter */
1405 if(!IsWindow(hwnd) ||
1406 (IsWindowVisible(hwnd) && !(dwFlags & AW_HIDE)) ||
1407 (!IsWindowVisible(hwnd) && (dwFlags & AW_HIDE)))
1409 SetLastError(ERROR_INVALID_PARAMETER);
1413 ShowWindow(hwnd, (dwFlags & AW_HIDE) ? SW_HIDE : ((dwFlags & AW_ACTIVATE) ? SW_SHOW : SW_SHOWNA));
1418 /***********************************************************************
1419 * SetInternalWindowPos (USER32.@)
1421 void WINAPI SetInternalWindowPos( HWND hwnd, UINT showCmd,
1422 LPRECT rect, LPPOINT pt )
1424 if( IsWindow(hwnd) )
1426 WINDOWPLACEMENT16 wndpl;
1429 wndpl.length = sizeof(wndpl);
1430 wndpl.showCmd = showCmd;
1431 wndpl.flags = flags = 0;
1436 wndpl.flags |= WPF_SETMINPOSITION;
1437 CONV_POINT32TO16( pt, &wndpl.ptMinPosition );
1441 flags |= PLACE_RECT;
1442 CONV_RECT32TO16( rect, &wndpl.rcNormalPosition );
1444 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1448 /*******************************************************************
1449 * WINPOS_SetActiveWindow
1451 * SetActiveWindow() back-end. This is the only function that
1452 * can assign active status to a window. It must be called only
1453 * for the top level windows.
1455 BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
1457 WND* wndPtr=0, *wndTemp;
1458 HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1459 MESSAGEQUEUE *pOldActiveQueue = 0, *pNewActiveQueue = 0;
1461 HWND hwndActive = 0;
1464 TRACE("(%04x, %d, %d)\n", hWnd, fMouse, fChangeFocus );
1466 /* Get current active window from the active queue */
1469 pOldActiveQueue = QUEUE_Lock( hActiveQueue );
1470 if ( pOldActiveQueue )
1471 hwndActive = PERQDATA_GetActiveWnd( pOldActiveQueue->pQData );
1474 /* paranoid checks */
1475 if( hWnd == GetDesktopWindow() || (bRet = (hWnd == hwndActive)) )
1478 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1481 wndPtr = WIN_FindWndPtr(hWnd);
1482 hOldActiveQueue = hActiveQueue;
1484 if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1486 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1487 WIN_ReleaseWndPtr(wndTemp);
1490 TRACE("no current active window.\n");
1492 /* call CBT hook chain */
1493 if (HOOK_IsHooked( WH_CBT ))
1495 CBTACTIVATESTRUCT cbt;
1496 cbt.fMouse = fMouse;
1497 cbt.hWndActive = hwndActive;
1498 if (HOOK_CallHooksA( WH_CBT, HCBT_ACTIVATE, hWnd, (LPARAM)&cbt )) goto CLEANUP_END;
1501 /* set prev active wnd to current active wnd and send notification */
1502 if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
1504 MESSAGEQUEUE *pTempActiveQueue = 0;
1506 if (!SendMessageA( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1508 if (GetSysModalWindow16() != hWnd)
1510 /* disregard refusal if hWnd is sysmodal */
1513 SendMessageA( hwndPrevActive, WM_ACTIVATE,
1514 MAKEWPARAM( WA_INACTIVE, wIconized ),
1517 /* check if something happened during message processing
1518 * (global active queue may have changed)
1520 pTempActiveQueue = QUEUE_Lock( hActiveQueue );
1521 if(!pTempActiveQueue)
1524 hwndActive = PERQDATA_GetActiveWnd( pTempActiveQueue->pQData );
1525 QUEUE_Unlock( pTempActiveQueue );
1526 if( hwndPrevActive != hwndActive )
1530 /* Set new active window in the message queue */
1534 pNewActiveQueue = QUEUE_Lock( wndPtr->hmemTaskQ );
1535 if ( pNewActiveQueue )
1536 PERQDATA_SetActiveWnd( pNewActiveQueue->pQData, hwndActive );
1538 else /* have to do this or MDI frame activation goes to hell */
1539 if( pOldActiveQueue )
1540 PERQDATA_SetActiveWnd( pOldActiveQueue->pQData, 0 );
1542 /* send palette messages */
1543 if (hWnd && SendMessageW( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1544 SendMessageW( HWND_BROADCAST, WM_PALETTEISCHANGING, (WPARAM)hWnd, 0 );
1546 /* if prev wnd is minimized redraw icon title */
1547 if( IsIconic( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1549 /* managed windows will get ConfigureNotify event */
1550 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_MANAGED))
1552 /* check Z-order and bring hWnd to the top */
1553 for (wndTemp = WIN_LockWndPtr(WIN_GetDesktop()->child); wndTemp; WIN_UpdateWndPtr(&wndTemp,wndTemp->next))
1555 if (wndTemp->dwStyle & WS_VISIBLE) break;
1557 WIN_ReleaseDesktop();
1558 WIN_ReleaseWndPtr(wndTemp);
1560 if( wndTemp != wndPtr )
1561 SetWindowPos(hWnd, HWND_TOP, 0,0,0,0,
1562 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1563 if (!IsWindow(hWnd))
1567 /* Get a handle to the new active queue */
1568 hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1570 /* send WM_ACTIVATEAPP if necessary */
1571 if (hOldActiveQueue != hNewActiveQueue)
1573 WND **list, **ppWnd;
1574 WND *pDesktop = WIN_GetDesktop();
1576 if ((list = WIN_BuildWinArray( pDesktop, 0, NULL )))
1578 DWORD new_thread = GetWindowThreadProcessId( hwndActive, NULL );
1579 for (ppWnd = list; *ppWnd; ppWnd++)
1581 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1583 if ((*ppWnd)->hmemTaskQ == hOldActiveQueue)
1584 SendMessageW( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP, 0, new_thread );
1586 WIN_ReleaseWinArray(list);
1589 hActiveQueue = hNewActiveQueue;
1591 if ((list = WIN_BuildWinArray(pDesktop, 0, NULL )))
1593 DWORD old_thread = GetWindowThreadProcessId( hwndPrevActive, NULL );
1594 for (ppWnd = list; *ppWnd; ppWnd++)
1596 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1598 if ((*ppWnd)->hmemTaskQ == hNewActiveQueue)
1599 SendMessageW( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP, 1, old_thread );
1601 WIN_ReleaseWinArray(list);
1603 WIN_ReleaseDesktop();
1605 if (hWnd && !IsWindow(hWnd)) goto CLEANUP;
1610 /* walk up to the first unowned window */
1611 wndTemp = WIN_LockWndPtr(wndPtr);
1612 while (wndTemp->owner)
1614 WIN_UpdateWndPtr(&wndTemp,wndTemp->owner);
1616 /* and set last active owned popup */
1617 wndTemp->hwndLastActive = hWnd;
1619 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1620 WIN_ReleaseWndPtr(wndTemp);
1621 SendMessageA( hWnd, WM_NCACTIVATE, TRUE, 0 );
1622 SendMessageA( hWnd, WM_ACTIVATE,
1623 MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1624 (LPARAM)hwndPrevActive );
1625 if( !IsWindow(hWnd) ) goto CLEANUP;
1628 /* change focus if possible */
1631 if ( pNewActiveQueue )
1633 HWND hOldFocus = PERQDATA_GetFocusWnd( pNewActiveQueue->pQData );
1635 if ( hOldFocus && WIN_GetTopParent( hOldFocus ) != hwndActive )
1636 FOCUS_SwitchFocus( pNewActiveQueue, hOldFocus,
1637 (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
1641 if ( pOldActiveQueue &&
1642 ( !pNewActiveQueue ||
1643 pNewActiveQueue->pQData != pOldActiveQueue->pQData ) )
1645 HWND hOldFocus = PERQDATA_GetFocusWnd( pOldActiveQueue->pQData );
1647 FOCUS_SwitchFocus( pOldActiveQueue, hOldFocus, 0 );
1651 if( !hwndPrevActive && wndPtr )
1653 if (USER_Driver.pForceWindowRaise) USER_Driver.pForceWindowRaise( wndPtr->hwndSelf );
1656 /* if active wnd is minimized redraw icon title */
1657 if( IsIconic(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1659 bRet = (hWnd == hwndActive); /* Success? */
1661 CLEANUP: /* Unlock the message queues before returning */
1663 if ( pNewActiveQueue )
1664 QUEUE_Unlock( pNewActiveQueue );
1668 if ( pOldActiveQueue )
1669 QUEUE_Unlock( pOldActiveQueue );
1671 WIN_ReleaseWndPtr(wndPtr);
1675 /*******************************************************************
1676 * WINPOS_ActivateOtherWindow
1678 * Activates window other than pWnd.
1680 BOOL WINPOS_ActivateOtherWindow(HWND hwnd)
1683 WND *pWnd, *pWndTo = NULL;
1684 HWND hwndActive = 0;
1686 /* Get current active window from the active queue */
1689 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1692 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1693 QUEUE_Unlock( pActiveQueue );
1697 if( hwnd == hwndPrevActive )
1700 pWnd = WIN_FindWndPtr( hwnd );
1701 if( hwndActive != hwnd &&
1702 ( hwndActive || QUEUE_IsExitingQueue(pWnd->hmemTaskQ)) )
1704 WIN_ReleaseWndPtr( pWnd );
1708 if( !(pWnd->dwStyle & WS_POPUP) || !(pWnd->owner) ||
1709 !WINPOS_CanActivate((pWndTo = WIN_GetTopParentPtr(pWnd->owner))) )
1711 WND* pWndPtr = WIN_GetTopParentPtr(pWnd);
1713 WIN_ReleaseWndPtr(pWndTo);
1714 pWndTo = WIN_FindWndPtr(hwndPrevActive);
1716 while( !WINPOS_CanActivate(pWndTo) )
1718 /* by now owned windows should've been taken care of */
1719 WIN_UpdateWndPtr(&pWndTo,pWndPtr->next);
1720 WIN_UpdateWndPtr(&pWndPtr,pWndTo);
1721 if( !pWndTo ) break;
1723 WIN_ReleaseWndPtr(pWndPtr);
1725 WIN_ReleaseWndPtr( pWnd );
1727 bRet = WINPOS_SetActiveWindow( pWndTo ? pWndTo->hwndSelf : 0, FALSE, TRUE );
1729 if( pWndTo ) WIN_ReleaseWndPtr(pWndTo);
1735 /*******************************************************************
1736 * WINPOS_ChangeActiveWindow
1739 BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
1743 HWND hwndActive = 0;
1745 /* Get current active window from the active queue */
1748 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1751 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1752 QUEUE_Unlock( pActiveQueue );
1757 return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
1759 wndPtr = WIN_FindWndPtr(hWnd);
1760 if( !wndPtr ) return FALSE;
1762 /* child windows get WM_CHILDACTIVATE message */
1763 if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
1765 retvalue = SendMessageA(hWnd, WM_CHILDACTIVATE, 0, 0L);
1769 if( hWnd == hwndActive )
1775 if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
1783 WIN_ReleaseWndPtr(wndPtr);
1788 /***********************************************************************
1789 * WINPOS_SendNCCalcSize
1791 * Send a WM_NCCALCSIZE message to a window.
1792 * All parameters are read-only except newClientRect.
1793 * oldWindowRect, oldClientRect and winpos must be non-NULL only
1794 * when calcValidRect is TRUE.
1796 LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect,
1797 RECT *newWindowRect, RECT *oldWindowRect,
1798 RECT *oldClientRect, WINDOWPOS *winpos,
1799 RECT *newClientRect )
1801 NCCALCSIZE_PARAMS params;
1802 WINDOWPOS winposCopy;
1805 params.rgrc[0] = *newWindowRect;
1808 winposCopy = *winpos;
1809 params.rgrc[1] = *oldWindowRect;
1810 params.rgrc[2] = *oldClientRect;
1811 params.lppos = &winposCopy;
1813 result = SendMessageA( hwnd, WM_NCCALCSIZE, calcValidRect,
1815 TRACE("%d,%d-%d,%d\n",
1816 params.rgrc[0].left, params.rgrc[0].top,
1817 params.rgrc[0].right, params.rgrc[0].bottom );
1819 /* If the application send back garbage, ignore it */
1820 if (params.rgrc[0].left <= params.rgrc[0].right && params.rgrc[0].top <= params.rgrc[0].bottom)
1821 *newClientRect = params.rgrc[0];
1827 /***********************************************************************
1828 * WINPOS_HandleWindowPosChanging16
1830 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
1832 LONG WINPOS_HandleWindowPosChanging16( HWND hwnd, WINDOWPOS16 *winpos )
1834 POINT maxSize, minTrack;
1835 LONG style = GetWindowLongA( hwnd, GWL_STYLE );
1837 if (winpos->flags & SWP_NOSIZE) return 0;
1838 if ((style & WS_THICKFRAME) || ((style & (WS_POPUP | WS_CHILD)) == 0))
1840 WINPOS_GetMinMaxInfo( hwnd, &maxSize, NULL, &minTrack, NULL );
1841 if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
1842 if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
1843 if (!(style & WS_MINIMIZE))
1845 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
1846 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
1853 /***********************************************************************
1854 * WINPOS_HandleWindowPosChanging
1856 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
1858 LONG WINPOS_HandleWindowPosChanging( HWND hwnd, WINDOWPOS *winpos )
1860 POINT maxSize, minTrack;
1861 LONG style = GetWindowLongA( hwnd, GWL_STYLE );
1863 if (winpos->flags & SWP_NOSIZE) return 0;
1864 if ((style & WS_THICKFRAME) || ((style & (WS_POPUP | WS_CHILD)) == 0))
1866 WINPOS_GetMinMaxInfo( hwnd, &maxSize, NULL, &minTrack, NULL );
1867 winpos->cx = min( winpos->cx, maxSize.x );
1868 winpos->cy = min( winpos->cy, maxSize.y );
1869 if (!(style & WS_MINIMIZE))
1871 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
1872 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
1878 /***********************************************************************
1879 * SetWindowPos (USER.232)
1881 BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
1882 INT16 x, INT16 y, INT16 cx, INT16 cy, WORD flags)
1884 return SetWindowPos(hwnd,(INT)(INT16)hwndInsertAfter,x,y,cx,cy,flags);
1887 /***********************************************************************
1888 * SetWindowPos (USER32.@)
1890 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
1891 INT x, INT y, INT cx, INT cy, UINT flags )
1896 winpos.hwndInsertAfter = hwndInsertAfter;
1901 winpos.flags = flags;
1902 return USER_Driver.pSetWindowPos( &winpos );
1906 /***********************************************************************
1907 * BeginDeferWindowPos (USER.259)
1909 HDWP16 WINAPI BeginDeferWindowPos16( INT16 count )
1911 return BeginDeferWindowPos( count );
1915 /***********************************************************************
1916 * BeginDeferWindowPos (USER32.@)
1918 HDWP WINAPI BeginDeferWindowPos( INT count )
1925 SetLastError(ERROR_INVALID_PARAMETER);
1928 /* Windows allows zero count, in which case it allocates context for 8 moves */
1929 if (count == 0) count = 8;
1931 handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
1932 if (!handle) return 0;
1933 pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
1934 pDWP->actualCount = 0;
1935 pDWP->suggestedCount = count;
1937 pDWP->wMagic = DWP_MAGIC;
1938 pDWP->hwndParent = 0;
1943 /***********************************************************************
1944 * DeferWindowPos (USER.260)
1946 HDWP16 WINAPI DeferWindowPos16( HDWP16 hdwp, HWND16 hwnd, HWND16 hwndAfter,
1947 INT16 x, INT16 y, INT16 cx, INT16 cy,
1950 return DeferWindowPos( hdwp, hwnd, (INT)(INT16)hwndAfter,
1951 x, y, cx, cy, flags );
1955 /***********************************************************************
1956 * DeferWindowPos (USER32.@)
1958 HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter,
1959 INT x, INT y, INT cx, INT cy,
1964 HDWP newhdwp = hdwp,retvalue;
1968 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
1969 if (!pDWP) return 0;
1970 if (hwnd == GetDesktopWindow()) return 0;
1972 if (!(pWnd=WIN_FindWndPtr( hwnd ))) {
1973 USER_HEAP_FREE( hdwp );
1977 /* Numega Bounds Checker Demo dislikes the following code.
1978 In fact, I've not been able to find any "same parent" requirement in any docu
1982 /* All the windows of a DeferWindowPos() must have the same parent */
1983 parent = pWnd->parent->hwndSelf;
1984 if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
1985 else if (parent != pDWP->hwndParent)
1987 USER_HEAP_FREE( hdwp );
1993 for (i = 0; i < pDWP->actualCount; i++)
1995 if (pDWP->winPos[i].hwnd == hwnd)
1997 /* Merge with the other changes */
1998 if (!(flags & SWP_NOZORDER))
2000 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
2002 if (!(flags & SWP_NOMOVE))
2004 pDWP->winPos[i].x = x;
2005 pDWP->winPos[i].y = y;
2007 if (!(flags & SWP_NOSIZE))
2009 pDWP->winPos[i].cx = cx;
2010 pDWP->winPos[i].cy = cy;
2012 pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
2013 SWP_NOZORDER | SWP_NOREDRAW |
2014 SWP_NOACTIVATE | SWP_NOCOPYBITS|
2016 pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
2022 if (pDWP->actualCount >= pDWP->suggestedCount)
2024 newhdwp = USER_HEAP_REALLOC( hdwp,
2025 sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
2031 pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
2032 pDWP->suggestedCount++;
2034 pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
2035 pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
2036 pDWP->winPos[pDWP->actualCount].x = x;
2037 pDWP->winPos[pDWP->actualCount].y = y;
2038 pDWP->winPos[pDWP->actualCount].cx = cx;
2039 pDWP->winPos[pDWP->actualCount].cy = cy;
2040 pDWP->winPos[pDWP->actualCount].flags = flags;
2041 pDWP->actualCount++;
2044 WIN_ReleaseWndPtr(pWnd);
2049 /***********************************************************************
2050 * EndDeferWindowPos (USER.261)
2052 BOOL16 WINAPI EndDeferWindowPos16( HDWP16 hdwp )
2054 return EndDeferWindowPos( hdwp );
2058 /***********************************************************************
2059 * EndDeferWindowPos (USER32.@)
2061 BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
2068 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
2069 if (!pDWP) return FALSE;
2070 for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
2072 if (!(res = USER_Driver.pSetWindowPos( winpos ))) break;
2074 USER_HEAP_FREE( hdwp );
2079 /***********************************************************************
2080 * TileChildWindows (USER.199)
2082 void WINAPI TileChildWindows16( HWND16 parent, WORD action )
2084 FIXME("(%04x, %d): stub\n", parent, action);
2087 /***********************************************************************
2088 * CascadeChildWindows (USER.198)
2090 void WINAPI CascadeChildWindows16( HWND16 parent, WORD action )
2092 FIXME("(%04x, %d): stub\n", parent, action);
2095 /***********************************************************************
2096 * SetProgmanWindow (USER32.@)
2098 HRESULT WINAPI SetProgmanWindow ( HWND hwnd )
2100 hGlobalProgmanWindow = hwnd;
2101 return hGlobalProgmanWindow;
2104 /***********************************************************************
2105 * GetProgmanWindow (USER32.@)
2107 HRESULT WINAPI GetProgmanWindow ( )
2109 return hGlobalProgmanWindow;
2112 /***********************************************************************
2113 * SetShellWindowEx (USER32.@)
2114 * hwndProgman = Progman[Program Manager]
2115 * |-> SHELLDLL_DefView
2116 * hwndListView = | |-> SysListView32
2117 * | | |-> tooltips_class32
2123 HRESULT WINAPI SetShellWindowEx ( HWND hwndProgman, HWND hwndListView )
2125 FIXME("0x%08x 0x%08x stub\n",hwndProgman ,hwndListView );
2126 hGlobalShellWindow = hwndProgman;
2127 return hGlobalShellWindow;
2131 /***********************************************************************
2132 * SetTaskmanWindow (USER32.@)
2134 * hwnd = MSTaskSwWClass
2135 * |-> SysTabControl32
2137 HRESULT WINAPI SetTaskmanWindow ( HWND hwnd )
2139 hGlobalTaskmanWindow = hwnd;
2140 return hGlobalTaskmanWindow;
2143 /***********************************************************************
2144 * GetTaskmanWindow (USER32.@)
2146 HRESULT WINAPI GetTaskmanWindow ( )
2148 return hGlobalTaskmanWindow;