2 * Window position related functions.
4 * Copyright 1993, 1994, 1995 Alexandre Julliard
5 * 1995, 1996, 1999 Alex Korobka
13 #include "wine/winuser16.h"
14 #include "wine/server.h"
24 #include "nonclient.h"
25 #include "debugtools.h"
28 DEFAULT_DEBUG_CHANNEL(win);
30 #define HAS_DLGFRAME(style,exStyle) \
31 (((exStyle) & WS_EX_DLGMODALFRAME) || \
32 (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
34 #define HAS_THICKFRAME(style) \
35 (((style) & WS_THICKFRAME) && \
36 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
38 #define EMPTYPOINT(pt) ((*(LONG*)&(pt)) == -1)
40 #define PLACE_MIN 0x0001
41 #define PLACE_MAX 0x0002
42 #define PLACE_RECT 0x0004
45 #define DWP_MAGIC ((INT)('W' | ('P' << 8) | ('O' << 16) | ('S' << 24)))
57 /* ----- internal variables ----- */
59 static HWND hwndPrevActive = 0; /* Previously active window */
60 static HWND hGlobalShellWindow=0; /*the shell*/
61 static HWND hGlobalTaskmanWindow=0;
62 static HWND hGlobalProgmanWindow=0;
64 static LPCSTR atomInternalPos;
66 extern HQUEUE16 hActiveQueue;
68 /***********************************************************************
69 * WINPOS_CreateInternalPosAtom
71 BOOL WINPOS_CreateInternalPosAtom()
74 atomInternalPos = (LPCSTR)(DWORD)GlobalAddAtomA(str);
75 return (atomInternalPos) ? TRUE : FALSE;
78 /***********************************************************************
79 * WINPOS_CheckInternalPos
81 * Called when a window is destroyed.
83 void WINPOS_CheckInternalPos( HWND hwnd )
86 MESSAGEQUEUE *pMsgQ = 0;
87 WND *wndPtr = WIN_GetPtr( hwnd );
89 if (!wndPtr || wndPtr == WND_OTHER_PROCESS) return;
91 lpPos = (LPINTERNALPOS) GetPropA( hwnd, atomInternalPos );
93 /* Retrieve the message queue associated with this window */
94 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
97 WARN("\tMessage queue not found. Exiting!\n" );
98 WIN_ReleasePtr( wndPtr );
102 if( hwnd == hwndPrevActive ) hwndPrevActive = 0;
104 if( hwnd == PERQDATA_GetActiveWnd( pMsgQ->pQData ) )
106 PERQDATA_SetActiveWnd( pMsgQ->pQData, 0 );
107 WARN("\tattempt to activate destroyed window!\n");
112 if( IsWindow(lpPos->hwndIconTitle) )
113 DestroyWindow( lpPos->hwndIconTitle );
114 HeapFree( GetProcessHeap(), 0, lpPos );
117 QUEUE_Unlock( pMsgQ );
118 WIN_ReleasePtr( wndPtr );
121 /***********************************************************************
122 * ArrangeIconicWindows (USER32.@)
124 UINT WINAPI ArrangeIconicWindows( HWND parent )
128 INT x, y, xspacing, yspacing;
130 GetClientRect( parent, &rectParent );
132 y = rectParent.bottom;
133 xspacing = GetSystemMetrics(SM_CXICONSPACING);
134 yspacing = GetSystemMetrics(SM_CYICONSPACING);
136 hwndChild = GetWindow( parent, GW_CHILD );
139 if( IsIconic( hwndChild ) )
141 WINPOS_ShowIconTitle( hwndChild, FALSE );
143 SetWindowPos( hwndChild, 0, x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2,
144 y - yspacing - GetSystemMetrics(SM_CYICON)/2, 0, 0,
145 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
146 if( IsWindow(hwndChild) )
147 WINPOS_ShowIconTitle(hwndChild , TRUE );
149 if (x <= rectParent.right - xspacing) x += xspacing;
156 hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
162 /***********************************************************************
163 * SwitchToThisWindow (USER32.@)
165 void WINAPI SwitchToThisWindow( HWND hwnd, BOOL restore )
167 ShowWindow( hwnd, restore ? SW_RESTORE : SW_SHOWMINIMIZED );
171 /***********************************************************************
172 * GetWindowRect (USER32.@)
174 BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect )
177 WND *wndPtr = WIN_GetPtr( hwnd );
179 if (!wndPtr) return FALSE;
181 if (wndPtr != WND_OTHER_PROCESS)
183 *rect = wndPtr->rectWindow;
184 WIN_ReleasePtr( wndPtr );
189 SERVER_START_REQ( get_window_rectangles )
192 if ((ret = !SERVER_CALL_ERR()))
194 rect->left = req->window.left;
195 rect->top = req->window.top;
196 rect->right = req->window.right;
197 rect->bottom = req->window.bottom;
204 MapWindowPoints( GetAncestor( hwnd, GA_PARENT ), 0, (POINT *)rect, 2 );
205 TRACE( "hwnd %04x (%d,%d)-(%d,%d)\n",
206 hwnd, rect->left, rect->top, rect->right, rect->bottom);
212 /***********************************************************************
213 * GetWindowRgn (USER32.@)
215 int WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
218 WND *wndPtr = WIN_FindWndPtr( hwnd );
221 if (wndPtr->hrgnWnd) nRet = CombineRgn( hrgn, wndPtr->hrgnWnd, 0, RGN_COPY );
222 WIN_ReleaseWndPtr(wndPtr);
227 /***********************************************************************
228 * SetWindowRgn (USER32.@)
230 int WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL bRedraw )
236 if (USER_Driver.pSetWindowRgn)
237 return USER_Driver.pSetWindowRgn( hwnd, hrgn, bRedraw );
239 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
241 if (wndPtr->hrgnWnd == hrgn)
247 if (hrgn) /* verify that region really exists */
249 if (GetRgnBox( hrgn, &rect ) == ERROR) goto done;
254 /* delete previous region */
255 DeleteObject(wndPtr->hrgnWnd);
258 wndPtr->hrgnWnd = hrgn;
260 /* Size the window to the rectangle of the new region (if it isn't NULL) */
261 if (hrgn) SetWindowPos( hwnd, 0, rect.left, rect.top,
262 rect.right - rect.left, rect.bottom - rect.top,
263 SWP_NOSIZE | SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOACTIVATE |
264 SWP_NOZORDER | (bRedraw ? 0 : SWP_NOREDRAW) );
268 WIN_ReleaseWndPtr(wndPtr);
273 /***********************************************************************
274 * GetClientRect (USER32.@)
276 BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect )
279 WND *wndPtr = WIN_GetPtr( hwnd );
281 rect->left = rect->top = rect->right = rect->bottom = 0;
282 if (!wndPtr) return FALSE;
284 if (wndPtr != WND_OTHER_PROCESS)
286 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
287 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
288 WIN_ReleasePtr( wndPtr );
293 SERVER_START_REQ( get_window_rectangles )
296 if ((ret = !SERVER_CALL_ERR()))
298 rect->right = req->client.right - req->client.left;
299 rect->bottom = req->client.bottom - req->client.top;
308 /*******************************************************************
309 * ClientToScreen (USER32.@)
311 BOOL WINAPI ClientToScreen( HWND hwnd, LPPOINT lppnt )
313 MapWindowPoints( hwnd, 0, lppnt, 1 );
318 /*******************************************************************
319 * ScreenToClient (USER32.@)
321 BOOL WINAPI ScreenToClient( HWND hwnd, LPPOINT lppnt )
323 MapWindowPoints( 0, hwnd, lppnt, 1 );
328 /***********************************************************************
329 * find_child_from_point
331 * Find the child that contains pt. Helper for WindowFromPoint.
332 * pt is in parent client coordinates.
333 * lparam is the param to pass in the WM_NCHITTEST message.
335 static HWND find_child_from_point( HWND parent, POINT pt, INT *hittest, LPARAM lparam )
339 HWND *list = WIN_ListChildren( parent );
342 for (i = 0; list[i]; i++)
344 if (!(wndPtr = WIN_FindWndPtr( list[i] ))) continue;
345 /* If point is in window, and window is visible, and it */
346 /* is enabled (or it's a top-level window), then explore */
347 /* its children. Otherwise, go to the next window. */
349 if (!(wndPtr->dwStyle & WS_VISIBLE)) goto next; /* not visible -> skip */
350 if ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD | WS_DISABLED)) == (WS_CHILD | WS_DISABLED))
351 goto next; /* disabled child -> skip */
352 if ((wndPtr->dwExStyle & (WS_EX_LAYERED | WS_EX_TRANSPARENT)) == (WS_EX_LAYERED | WS_EX_TRANSPARENT))
353 goto next; /* transparent -> skip */
356 if (!PtInRegion( wndPtr->hrgnWnd, pt.x - wndPtr->rectWindow.left,
357 pt.y - wndPtr->rectWindow.top ))
358 goto next; /* point outside window region -> skip */
360 else if (!PtInRect( &wndPtr->rectWindow, pt )) goto next; /* not in window -> skip */
362 /* If window is minimized or disabled, return at once */
363 if (wndPtr->dwStyle & WS_MINIMIZE)
365 WIN_ReleaseWndPtr( wndPtr );
366 *hittest = HTCAPTION;
369 if (wndPtr->dwStyle & WS_DISABLED)
371 WIN_ReleaseWndPtr( wndPtr );
376 /* If point is in client area, explore children */
377 if (PtInRect( &wndPtr->rectClient, pt ))
382 new_pt.x = pt.x - wndPtr->rectClient.left;
383 new_pt.y = pt.y - wndPtr->rectClient.top;
384 WIN_ReleaseWndPtr( wndPtr );
385 if ((ret = find_child_from_point( list[i], new_pt, hittest, lparam )))
388 else WIN_ReleaseWndPtr( wndPtr );
390 /* Now it's inside window, send WM_NCCHITTEST (if same thread) */
391 if (!WIN_IsCurrentThread( list[i] ))
396 if ((res = SendMessageA( list[i], WM_NCHITTEST, 0, lparam )) != HTTRANSPARENT)
398 *hittest = res; /* Found the window */
401 continue; /* continue search with next sibling */
404 WIN_ReleaseWndPtr( wndPtr );
410 /***********************************************************************
411 * WINPOS_WindowFromPoint
413 * Find the window and hittest for a given point.
415 HWND WINPOS_WindowFromPoint( HWND hwndScope, POINT pt, INT *hittest )
421 TRACE("scope %04x %ld,%ld\n", hwndScope, pt.x, pt.y);
423 if (!hwndScope) hwndScope = GetDesktopWindow();
424 if (!(wndScope = WIN_FindWndPtr( hwndScope ))) return 0;
425 hwndScope = wndScope->hwndSelf; /* make it a full handle */
428 if( wndScope->dwStyle & WS_DISABLED )
430 WIN_ReleaseWndPtr(wndScope);
434 if (wndScope->parent)
435 MapWindowPoints( GetDesktopWindow(), wndScope->parent, &xy, 1 );
437 if (!(wndScope->dwStyle & WS_MINIMIZE) && PtInRect( &wndScope->rectClient, xy ))
441 xy.x -= wndScope->rectClient.left;
442 xy.y -= wndScope->rectClient.top;
443 WIN_ReleaseWndPtr( wndScope );
444 if ((ret = find_child_from_point( hwndScope, xy, hittest, MAKELONG( pt.x, pt.y ) )))
446 TRACE( "found child %x\n", ret );
450 else WIN_ReleaseWndPtr( wndScope );
452 /* If nothing found, try the scope window */
453 if (!WIN_IsCurrentThread( hwndScope ))
456 TRACE( "returning %x\n", hwndScope );
459 res = SendMessageA( hwndScope, WM_NCHITTEST, 0, MAKELONG( pt.x, pt.y ) );
460 if (res != HTTRANSPARENT)
462 *hittest = res; /* Found the window */
463 TRACE( "returning %x\n", hwndScope );
466 *hittest = HTNOWHERE;
467 TRACE( "nothing found\n" );
472 /*******************************************************************
473 * WindowFromPoint (USER32.@)
475 HWND WINAPI WindowFromPoint( POINT pt )
478 return WINPOS_WindowFromPoint( 0, pt, &hittest );
482 /*******************************************************************
483 * ChildWindowFromPoint (USER32.@)
485 HWND WINAPI ChildWindowFromPoint( HWND hwndParent, POINT pt )
487 return ChildWindowFromPointEx( hwndParent, pt, CWP_ALL );
490 /*******************************************************************
491 * ChildWindowFromPointEx (USER32.@)
493 HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt, UINT uFlags)
495 /* pt is in the client coordinates */
501 GetClientRect( hwndParent, &rect );
502 if (!PtInRect( &rect, pt )) return 0;
503 if (!(list = WIN_ListChildren( hwndParent ))) return 0;
505 for (i = 0; list[i] && !retvalue; i++)
507 WND *wnd = WIN_FindWndPtr( list[i] );
509 if (PtInRect( &wnd->rectWindow, pt ))
511 if ( (uFlags & CWP_SKIPINVISIBLE) &&
512 !(wnd->dwStyle & WS_VISIBLE) );
513 else if ( (uFlags & CWP_SKIPDISABLED) &&
514 (wnd->dwStyle & WS_DISABLED) );
515 else if ( (uFlags & CWP_SKIPTRANSPARENT) &&
516 (wnd->dwExStyle & WS_EX_TRANSPARENT) );
517 else retvalue = list[i];
519 WIN_ReleaseWndPtr( wnd );
521 HeapFree( GetProcessHeap(), 0, list );
522 if (!retvalue) retvalue = hwndParent;
527 /*******************************************************************
528 * WINPOS_GetWinOffset
530 * Calculate the offset between the origin of the two windows. Used
531 * to implement MapWindowPoints.
533 static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo, POINT *offset )
537 offset->x = offset->y = 0;
539 /* Translate source window origin to screen coords */
542 HWND hwnd = hwndFrom;
546 if (hwnd == hwndTo) return;
547 if (!(wndPtr = WIN_GetPtr( hwnd )))
549 ERR( "bad hwndFrom = %04x\n", hwnd );
552 if (wndPtr == WND_OTHER_PROCESS) goto other_process;
553 offset->x += wndPtr->rectClient.left;
554 offset->y += wndPtr->rectClient.top;
555 hwnd = wndPtr->parent;
556 WIN_ReleasePtr( wndPtr );
560 /* Translate origin to destination window coords */
567 if (!(wndPtr = WIN_GetPtr( hwnd )))
569 ERR( "bad hwndTo = %04x\n", hwnd );
572 if (wndPtr == WND_OTHER_PROCESS) goto other_process;
573 offset->x -= wndPtr->rectClient.left;
574 offset->y -= wndPtr->rectClient.top;
575 hwnd = wndPtr->parent;
576 WIN_ReleasePtr( wndPtr );
581 other_process: /* one of the parents may belong to another process, do it the hard way */
582 offset->x = offset->y = 0;
583 SERVER_START_REQ( get_windows_offset )
585 req->from = hwndFrom;
597 /*******************************************************************
598 * MapWindowPoints (USER.258)
600 void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
601 LPPOINT16 lppt, UINT16 count )
605 WINPOS_GetWinOffset( WIN_Handle32(hwndFrom), WIN_Handle32(hwndTo), &offset );
615 /*******************************************************************
616 * MapWindowPoints (USER32.@)
618 INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo, LPPOINT lppt, UINT count )
622 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
629 return MAKELONG( LOWORD(offset.x), LOWORD(offset.y) );
633 /***********************************************************************
634 * IsIconic (USER32.@)
636 BOOL WINAPI IsIconic(HWND hWnd)
638 return (GetWindowLongW( hWnd, GWL_STYLE ) & WS_MINIMIZE) != 0;
642 /***********************************************************************
643 * IsZoomed (USER32.@)
645 BOOL WINAPI IsZoomed(HWND hWnd)
647 return (GetWindowLongW( hWnd, GWL_STYLE ) & WS_MAXIMIZE) != 0;
651 /*******************************************************************
652 * GetActiveWindow (USER32.@)
654 HWND WINAPI GetActiveWindow(void)
656 MESSAGEQUEUE *pCurMsgQ = 0;
658 /* Get the messageQ for the current thread */
659 if (!(pCurMsgQ = QUEUE_Current()))
661 WARN("\tCurrent message queue not found. Exiting!\n" );
665 /* Return the current active window from the perQ data of the current message Q */
666 return PERQDATA_GetActiveWnd( pCurMsgQ->pQData );
670 /*******************************************************************
673 static BOOL WINPOS_CanActivate(HWND hwnd)
675 if (!hwnd) return FALSE;
676 return ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_DISABLED|WS_VISIBLE|WS_CHILD)) == WS_VISIBLE);
680 /*******************************************************************
681 * SetActiveWindow (USER32.@)
683 HWND WINAPI SetActiveWindow( HWND hwnd )
686 WND *wndPtr = WIN_FindWndPtr( hwnd );
687 MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
689 if (!wndPtr) return 0;
691 if (wndPtr->dwStyle & (WS_DISABLED | WS_CHILD)) goto error;
693 /* Get the messageQ for the current thread */
694 if (!(pCurMsgQ = QUEUE_Current()))
696 WARN("\tCurrent message queue not found. Exiting!\n" );
700 /* Retrieve the message queue associated with this window */
701 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
704 WARN("\tWindow message queue not found. Exiting!\n" );
708 /* Make sure that the window is associated with the calling threads
709 * message queue. It must share the same perQ data.
711 if ( pCurMsgQ->pQData != pMsgQ->pQData )
713 QUEUE_Unlock( pMsgQ );
717 /* Save current active window */
718 prev = PERQDATA_GetActiveWnd( pMsgQ->pQData );
719 QUEUE_Unlock( pMsgQ );
720 WIN_ReleaseWndPtr(wndPtr);
721 WINPOS_SetActiveWindow( hwnd, 0, 0 );
725 WIN_ReleaseWndPtr(wndPtr);
730 /*******************************************************************
731 * GetForegroundWindow (USER32.@)
733 HWND WINAPI GetForegroundWindow(void)
737 /* Get the foreground window (active window of hActiveQueue) */
740 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
742 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
744 QUEUE_Unlock( pActiveQueue );
750 /*******************************************************************
751 * SetForegroundWindow (USER32.@)
753 BOOL WINAPI SetForegroundWindow( HWND hwnd )
755 return WINPOS_ChangeActiveWindow( hwnd, FALSE );
759 /*******************************************************************
760 * AllowSetForegroundWindow (USER32.@)
762 BOOL WINAPI AllowSetForegroundWindow( DWORD procid )
764 /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
765 * implemented, then fix this function. */
770 /*******************************************************************
771 * LockSetForegroundWindow (USER32.@)
773 BOOL WINAPI LockSetForegroundWindow( UINT lockcode )
775 /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
776 * implemented, then fix this function. */
781 /*******************************************************************
782 * SetShellWindow (USER32.@)
784 HWND WINAPI SetShellWindow(HWND hwndshell)
785 { WARN("(hWnd=%08x) semi stub\n",hwndshell );
787 hGlobalShellWindow = WIN_GetFullHandle( hwndshell );
788 return hGlobalShellWindow;
792 /*******************************************************************
793 * GetShellWindow (USER32.@)
795 HWND WINAPI GetShellWindow(void)
796 { WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow );
798 return hGlobalShellWindow;
802 /***********************************************************************
803 * BringWindowToTop (USER32.@)
805 BOOL WINAPI BringWindowToTop( HWND hwnd )
807 return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
811 /***********************************************************************
812 * MoveWindow (USER32.@)
814 BOOL WINAPI MoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy,
817 int flags = SWP_NOZORDER | SWP_NOACTIVATE;
818 if (!repaint) flags |= SWP_NOREDRAW;
819 TRACE("%04x %d,%d %dx%d %d\n",
820 hwnd, x, y, cx, cy, repaint );
821 return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
824 /***********************************************************************
825 * WINPOS_InitInternalPos
827 static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT pt, const RECT *restoreRect )
829 LPINTERNALPOS lpPos = (LPINTERNALPOS) GetPropA( wnd->hwndSelf,
833 /* this happens when the window is minimized/maximized
834 * for the first time (rectWindow is not adjusted yet) */
836 lpPos = HeapAlloc( GetProcessHeap(), 0, sizeof(INTERNALPOS) );
837 if( !lpPos ) return NULL;
839 SetPropA( wnd->hwndSelf, atomInternalPos, (HANDLE)lpPos );
840 lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
841 CONV_RECT32TO16( &wnd->rectWindow, &lpPos->rectNormal );
842 *(UINT*)&lpPos->ptIconPos = *(UINT*)&lpPos->ptMaxPos = 0xFFFFFFFF;
845 if( wnd->dwStyle & WS_MINIMIZE )
846 CONV_POINT32TO16( &pt, &lpPos->ptIconPos );
847 else if( wnd->dwStyle & WS_MAXIMIZE )
848 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
849 else if( restoreRect )
850 CONV_RECT32TO16( restoreRect, &lpPos->rectNormal );
855 /***********************************************************************
856 * WINPOS_RedrawIconTitle
858 BOOL WINPOS_RedrawIconTitle( HWND hWnd )
860 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hWnd, atomInternalPos );
863 if( lpPos->hwndIconTitle )
865 SendMessageA( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
866 InvalidateRect( lpPos->hwndIconTitle, NULL, TRUE );
873 /***********************************************************************
874 * WINPOS_ShowIconTitle
876 BOOL WINPOS_ShowIconTitle( HWND hwnd, BOOL bShow )
878 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hwnd, atomInternalPos );
880 if( lpPos && !(GetWindowLongA( hwnd, GWL_EXSTYLE) & WS_EX_MANAGED))
882 HWND title = lpPos->hwndIconTitle;
884 TRACE("0x%04x %i\n", hwnd, (bShow != 0) );
887 lpPos->hwndIconTitle = title = ICONTITLE_Create( hwnd );
890 if (!IsWindowVisible(title))
892 SendMessageA( title, WM_SHOWWINDOW, TRUE, 0 );
893 SetWindowPos( title, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
894 SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
897 else ShowWindow( title, SW_HIDE );
902 /*******************************************************************
903 * WINPOS_GetMinMaxInfo
905 * Get the minimized and maximized information for a window.
907 void WINPOS_GetMinMaxInfo( HWND hwnd, POINT *maxSize, POINT *maxPos,
908 POINT *minTrack, POINT *maxTrack )
913 LONG style = GetWindowLongA( hwnd, GWL_STYLE );
914 LONG exstyle = GetWindowLongA( hwnd, GWL_EXSTYLE );
916 /* Compute default values */
918 MinMax.ptMaxSize.x = GetSystemMetrics(SM_CXSCREEN);
919 MinMax.ptMaxSize.y = GetSystemMetrics(SM_CYSCREEN);
920 MinMax.ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
921 MinMax.ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
922 MinMax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXSCREEN);
923 MinMax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYSCREEN);
925 if (HAS_DLGFRAME( style, exstyle ))
927 xinc = GetSystemMetrics(SM_CXDLGFRAME);
928 yinc = GetSystemMetrics(SM_CYDLGFRAME);
933 if (HAS_THICKFRAME(style))
935 xinc += GetSystemMetrics(SM_CXFRAME);
936 yinc += GetSystemMetrics(SM_CYFRAME);
938 if (style & WS_BORDER)
940 xinc += GetSystemMetrics(SM_CXBORDER);
941 yinc += GetSystemMetrics(SM_CYBORDER);
944 MinMax.ptMaxSize.x += 2 * xinc;
945 MinMax.ptMaxSize.y += 2 * yinc;
947 lpPos = (LPINTERNALPOS)GetPropA( hwnd, atomInternalPos );
948 if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
949 CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
952 MinMax.ptMaxPosition.x = -xinc;
953 MinMax.ptMaxPosition.y = -yinc;
956 SendMessageA( hwnd, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
958 /* Some sanity checks */
960 TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
961 MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
962 MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
963 MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
964 MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
965 MinMax.ptMaxTrackSize.x = max( MinMax.ptMaxTrackSize.x,
966 MinMax.ptMinTrackSize.x );
967 MinMax.ptMaxTrackSize.y = max( MinMax.ptMaxTrackSize.y,
968 MinMax.ptMinTrackSize.y );
970 if (maxSize) *maxSize = MinMax.ptMaxSize;
971 if (maxPos) *maxPos = MinMax.ptMaxPosition;
972 if (minTrack) *minTrack = MinMax.ptMinTrackSize;
973 if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
976 /***********************************************************************
977 * ShowWindowAsync (USER32.@)
979 * doesn't wait; returns immediately.
980 * used by threads to toggle windows in other (possibly hanging) threads
982 BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd )
984 /* FIXME: does ShowWindow() return immediately ? */
985 return ShowWindow(hwnd, cmd);
989 /***********************************************************************
990 * ShowWindow (USER32.@)
992 BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
996 if ((full_handle = WIN_IsCurrentThread( hwnd )))
997 return USER_Driver.pShowWindow( full_handle, cmd );
998 return SendMessageW( hwnd, WM_WINE_SHOWWINDOW, cmd, 0 );
1002 /***********************************************************************
1003 * GetInternalWindowPos (USER.460)
1005 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
1008 WINDOWPLACEMENT16 wndpl;
1009 if (GetWindowPlacement16( hwnd, &wndpl ))
1011 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1012 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1013 return wndpl.showCmd;
1019 /***********************************************************************
1020 * GetInternalWindowPos (USER32.@)
1022 UINT WINAPI GetInternalWindowPos( HWND hwnd, LPRECT rectWnd,
1025 WINDOWPLACEMENT wndpl;
1026 if (GetWindowPlacement( hwnd, &wndpl ))
1028 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1029 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1030 return wndpl.showCmd;
1036 /***********************************************************************
1037 * GetWindowPlacement (USER32.@)
1040 * Fails if wndpl->length of Win95 (!) apps is invalid.
1042 BOOL WINAPI GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *wndpl )
1044 WND *pWnd = WIN_FindWndPtr( hwnd );
1045 LPINTERNALPOS lpPos;
1047 if(!pWnd ) return FALSE;
1049 lpPos = WINPOS_InitInternalPos( pWnd, *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1050 wndpl->length = sizeof(*wndpl);
1051 if( pWnd->dwStyle & WS_MINIMIZE )
1052 wndpl->showCmd = SW_SHOWMINIMIZED;
1054 wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE ) ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
1055 if( pWnd->flags & WIN_RESTORE_MAX )
1056 wndpl->flags = WPF_RESTORETOMAXIMIZED;
1059 CONV_POINT16TO32( &lpPos->ptIconPos, &wndpl->ptMinPosition );
1060 CONV_POINT16TO32( &lpPos->ptMaxPos, &wndpl->ptMaxPosition );
1061 CONV_RECT16TO32( &lpPos->rectNormal, &wndpl->rcNormalPosition );
1062 WIN_ReleaseWndPtr(pWnd);
1067 /***********************************************************************
1068 * WINPOS_SetPlacement
1070 static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT *wndpl, UINT flags )
1072 WND *pWnd = WIN_FindWndPtr( hwnd );
1075 LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1076 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1078 if( flags & PLACE_MIN ) CONV_POINT32TO16( &wndpl->ptMinPosition, &lpPos->ptIconPos );
1079 if( flags & PLACE_MAX ) CONV_POINT32TO16( &wndpl->ptMaxPosition, &lpPos->ptMaxPos );
1080 if( flags & PLACE_RECT) CONV_RECT32TO16( &wndpl->rcNormalPosition, &lpPos->rectNormal );
1082 if( pWnd->dwStyle & WS_MINIMIZE )
1084 WINPOS_ShowIconTitle( pWnd->hwndSelf, FALSE );
1085 if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1086 SetWindowPos( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1087 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1089 else if( pWnd->dwStyle & WS_MAXIMIZE )
1091 if( !EMPTYPOINT(lpPos->ptMaxPos) )
1092 SetWindowPos( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1093 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1095 else if( flags & PLACE_RECT )
1096 SetWindowPos( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1097 lpPos->rectNormal.right - lpPos->rectNormal.left,
1098 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1099 SWP_NOZORDER | SWP_NOACTIVATE );
1101 ShowWindow( hwnd, wndpl->showCmd );
1102 if( IsWindow(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1104 if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd->hwndSelf, TRUE );
1106 /* SDK: ...valid only the next time... */
1107 if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1109 WIN_ReleaseWndPtr(pWnd);
1116 /***********************************************************************
1117 * SetWindowPlacement (USER32.@)
1120 * Fails if wndpl->length of Win95 (!) apps is invalid.
1122 BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *wpl )
1124 if (!wpl) return FALSE;
1125 return WINPOS_SetPlacement( hwnd, wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1129 /***********************************************************************
1130 * AnimateWindow (USER32.@)
1131 * Shows/Hides a window with an animation
1134 BOOL WINAPI AnimateWindow(HWND hwnd, DWORD dwTime, DWORD dwFlags)
1136 FIXME("partial stub\n");
1138 /* If trying to show/hide and it's already *
1139 * shown/hidden or invalid window, fail with *
1140 * invalid parameter */
1141 if(!IsWindow(hwnd) ||
1142 (IsWindowVisible(hwnd) && !(dwFlags & AW_HIDE)) ||
1143 (!IsWindowVisible(hwnd) && (dwFlags & AW_HIDE)))
1145 SetLastError(ERROR_INVALID_PARAMETER);
1149 ShowWindow(hwnd, (dwFlags & AW_HIDE) ? SW_HIDE : ((dwFlags & AW_ACTIVATE) ? SW_SHOW : SW_SHOWNA));
1154 /***********************************************************************
1155 * SetInternalWindowPos (USER32.@)
1157 void WINAPI SetInternalWindowPos( HWND hwnd, UINT showCmd,
1158 LPRECT rect, LPPOINT pt )
1160 if( IsWindow(hwnd) )
1162 WINDOWPLACEMENT wndpl;
1165 wndpl.length = sizeof(wndpl);
1166 wndpl.showCmd = showCmd;
1167 wndpl.flags = flags = 0;
1172 wndpl.flags |= WPF_SETMINPOSITION;
1173 wndpl.ptMinPosition = *pt;
1177 flags |= PLACE_RECT;
1178 wndpl.rcNormalPosition = *rect;
1180 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1184 /*******************************************************************
1185 * WINPOS_SetActiveWindow
1187 * SetActiveWindow() back-end. This is the only function that
1188 * can assign active status to a window. It must be called only
1189 * for the top level windows.
1191 BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
1193 WND* wndPtr=0, *wndTemp;
1194 HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1195 MESSAGEQUEUE *pOldActiveQueue = 0, *pNewActiveQueue = 0;
1197 HWND hwndActive = 0;
1200 TRACE("(%04x, %d, %d)\n", hWnd, fMouse, fChangeFocus );
1202 /* Get current active window from the active queue */
1205 pOldActiveQueue = QUEUE_Lock( hActiveQueue );
1206 if ( pOldActiveQueue )
1207 hwndActive = PERQDATA_GetActiveWnd( pOldActiveQueue->pQData );
1210 if ((wndPtr = WIN_FindWndPtr(hWnd)))
1211 hWnd = wndPtr->hwndSelf; /* make it a full handle */
1213 /* paranoid checks */
1214 if( hWnd == GetDesktopWindow() || (bRet = (hWnd == hwndActive)) )
1217 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1220 hOldActiveQueue = hActiveQueue;
1222 if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1224 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1225 WIN_ReleaseWndPtr(wndTemp);
1228 TRACE("no current active window.\n");
1230 /* call CBT hook chain */
1231 if (HOOK_IsHooked( WH_CBT ))
1233 CBTACTIVATESTRUCT cbt;
1234 cbt.fMouse = fMouse;
1235 cbt.hWndActive = hwndActive;
1236 if (HOOK_CallHooksA( WH_CBT, HCBT_ACTIVATE, (WPARAM)hWnd, (LPARAM)&cbt )) goto CLEANUP_END;
1239 /* set prev active wnd to current active wnd and send notification */
1240 if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
1242 MESSAGEQUEUE *pTempActiveQueue = 0;
1244 if (!SendMessageA( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1246 if (GetSysModalWindow16() != WIN_Handle16(hWnd)) goto CLEANUP_END;
1247 /* disregard refusal if hWnd is sysmodal */
1250 SendMessageA( hwndPrevActive, WM_ACTIVATE,
1251 MAKEWPARAM( WA_INACTIVE, wIconized ),
1254 /* check if something happened during message processing
1255 * (global active queue may have changed)
1257 pTempActiveQueue = QUEUE_Lock( hActiveQueue );
1258 if(!pTempActiveQueue)
1261 hwndActive = PERQDATA_GetActiveWnd( pTempActiveQueue->pQData );
1262 QUEUE_Unlock( pTempActiveQueue );
1263 if( hwndPrevActive != hwndActive )
1267 /* Set new active window in the message queue */
1271 pNewActiveQueue = QUEUE_Lock( wndPtr->hmemTaskQ );
1272 if ( pNewActiveQueue )
1273 PERQDATA_SetActiveWnd( pNewActiveQueue->pQData, hwndActive );
1275 else /* have to do this or MDI frame activation goes to hell */
1276 if( pOldActiveQueue )
1277 PERQDATA_SetActiveWnd( pOldActiveQueue->pQData, 0 );
1279 /* send palette messages */
1280 if (hWnd && SendMessageW( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1281 SendMessageW( HWND_BROADCAST, WM_PALETTEISCHANGING, (WPARAM)hWnd, 0 );
1283 /* if prev wnd is minimized redraw icon title */
1284 if( IsIconic( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1286 /* managed windows will get ConfigureNotify event */
1287 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_MANAGED))
1289 /* check Z-order and bring hWnd to the top */
1290 HWND tmp = GetTopWindow(0);
1291 while (tmp && !(GetWindowLongA( tmp, GWL_STYLE ) & WS_VISIBLE))
1292 tmp = GetWindow( tmp, GW_HWNDNEXT );
1295 SetWindowPos(hWnd, HWND_TOP, 0,0,0,0,
1296 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1297 if (!IsWindow(hWnd))
1301 /* Get a handle to the new active queue */
1302 hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1304 /* send WM_ACTIVATEAPP if necessary */
1305 if (hOldActiveQueue != hNewActiveQueue)
1308 DWORD old_thread = GetWindowThreadProcessId( hwndPrevActive, NULL );
1309 DWORD new_thread = GetWindowThreadProcessId( hwndActive, NULL );
1311 if ((list = WIN_ListChildren( GetDesktopWindow() )))
1313 for (phwnd = list; *phwnd; phwnd++)
1315 if (!IsWindow( *phwnd )) continue;
1316 if (GetWindowThreadProcessId( *phwnd, NULL ) == old_thread)
1317 SendMessageW( *phwnd, WM_ACTIVATEAPP, 0, new_thread );
1319 HeapFree( GetProcessHeap(), 0, list );
1322 hActiveQueue = hNewActiveQueue;
1324 if ((list = WIN_ListChildren( GetDesktopWindow() )))
1326 for (phwnd = list; *phwnd; phwnd++)
1328 if (!IsWindow( *phwnd )) continue;
1329 if (GetWindowThreadProcessId( *phwnd, NULL ) == new_thread)
1330 SendMessageW( *phwnd, WM_ACTIVATEAPP, 1, old_thread );
1332 HeapFree( GetProcessHeap(), 0, list );
1335 if (hWnd && !IsWindow(hWnd)) goto CLEANUP;
1340 /* walk up to the first unowned window */
1341 HWND tmp = GetAncestor( hWnd, GA_ROOTOWNER );
1342 if ((wndTemp = WIN_FindWndPtr( tmp )))
1344 /* and set last active owned popup */
1345 wndTemp->hwndLastActive = hWnd;
1347 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1348 WIN_ReleaseWndPtr(wndTemp);
1350 SendMessageA( hWnd, WM_NCACTIVATE, TRUE, 0 );
1351 SendMessageA( hWnd, WM_ACTIVATE,
1352 MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1353 (LPARAM)hwndPrevActive );
1354 if( !IsWindow(hWnd) ) goto CLEANUP;
1357 /* change focus if possible */
1360 if ( pNewActiveQueue )
1362 HWND hOldFocus = PERQDATA_GetFocusWnd( pNewActiveQueue->pQData );
1364 if ( hOldFocus && GetAncestor( hOldFocus, GA_ROOT ) != hwndActive )
1365 FOCUS_SwitchFocus( pNewActiveQueue, hOldFocus,
1366 (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
1370 if ( pOldActiveQueue &&
1371 ( !pNewActiveQueue ||
1372 pNewActiveQueue->pQData != pOldActiveQueue->pQData ) )
1374 HWND hOldFocus = PERQDATA_GetFocusWnd( pOldActiveQueue->pQData );
1376 FOCUS_SwitchFocus( pOldActiveQueue, hOldFocus, 0 );
1380 if( !hwndPrevActive && wndPtr )
1382 if (USER_Driver.pForceWindowRaise) USER_Driver.pForceWindowRaise( wndPtr->hwndSelf );
1385 /* if active wnd is minimized redraw icon title */
1386 if( IsIconic(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1388 bRet = (hWnd == hwndActive); /* Success? */
1390 CLEANUP: /* Unlock the message queues before returning */
1392 if ( pNewActiveQueue )
1393 QUEUE_Unlock( pNewActiveQueue );
1397 if ( pOldActiveQueue )
1398 QUEUE_Unlock( pOldActiveQueue );
1400 WIN_ReleaseWndPtr(wndPtr);
1404 /*******************************************************************
1405 * WINPOS_ActivateOtherWindow
1407 * Activates window other than pWnd.
1409 BOOL WINPOS_ActivateOtherWindow(HWND hwnd)
1412 HWND hwndActive = 0;
1416 /* Get current active window from the active queue */
1419 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1422 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1423 QUEUE_Unlock( pActiveQueue );
1427 if (!(hwnd = WIN_IsCurrentThread( hwnd ))) return 0;
1429 if( hwnd == hwndPrevActive )
1432 if( hwndActive != hwnd && (hwndActive || USER_IsExitingThread( GetCurrentThreadId() )))
1435 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_POPUP) ||
1436 !(owner = GetWindow( hwnd, GW_OWNER )) ||
1437 !WINPOS_CanActivate((hwndTo = GetAncestor( owner, GA_ROOT ))) )
1439 HWND tmp = GetAncestor( hwnd, GA_ROOT );
1440 hwndTo = hwndPrevActive;
1442 while( !WINPOS_CanActivate(hwndTo) )
1444 /* by now owned windows should've been taken care of */
1445 tmp = hwndTo = GetWindow( tmp, GW_HWNDNEXT );
1446 if( !hwndTo ) break;
1450 bRet = WINPOS_SetActiveWindow( hwndTo, FALSE, TRUE );
1456 /*******************************************************************
1457 * WINPOS_ChangeActiveWindow
1460 BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
1463 HWND hwndActive = 0;
1465 /* Get current active window from the active queue */
1468 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1471 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1472 QUEUE_Unlock( pActiveQueue );
1477 return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
1479 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1480 hWnd = wndPtr->hwndSelf;
1482 /* child windows get WM_CHILDACTIVATE message */
1483 if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
1485 WIN_ReleaseWndPtr(wndPtr);
1486 return SendMessageA(hWnd, WM_CHILDACTIVATE, 0, 0L);
1488 WIN_ReleaseWndPtr(wndPtr);
1490 if( hWnd == hwndActive ) return FALSE;
1492 return WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE);
1496 /***********************************************************************
1497 * WINPOS_HandleWindowPosChanging16
1499 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
1501 LONG WINPOS_HandleWindowPosChanging16( HWND hwnd, WINDOWPOS16 *winpos )
1503 POINT maxSize, minTrack;
1504 LONG style = GetWindowLongA( hwnd, GWL_STYLE );
1506 if (winpos->flags & SWP_NOSIZE) return 0;
1507 if ((style & WS_THICKFRAME) || ((style & (WS_POPUP | WS_CHILD)) == 0))
1509 WINPOS_GetMinMaxInfo( hwnd, &maxSize, NULL, &minTrack, NULL );
1510 if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
1511 if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
1512 if (!(style & WS_MINIMIZE))
1514 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
1515 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
1522 /***********************************************************************
1523 * WINPOS_HandleWindowPosChanging
1525 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
1527 LONG WINPOS_HandleWindowPosChanging( HWND hwnd, WINDOWPOS *winpos )
1529 POINT maxSize, minTrack;
1530 LONG style = GetWindowLongA( hwnd, GWL_STYLE );
1532 if (winpos->flags & SWP_NOSIZE) return 0;
1533 if ((style & WS_THICKFRAME) || ((style & (WS_POPUP | WS_CHILD)) == 0))
1535 WINPOS_GetMinMaxInfo( hwnd, &maxSize, NULL, &minTrack, NULL );
1536 winpos->cx = min( winpos->cx, maxSize.x );
1537 winpos->cy = min( winpos->cy, maxSize.y );
1538 if (!(style & WS_MINIMIZE))
1540 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
1541 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
1548 /***********************************************************************
1549 * SetWindowPos (USER32.@)
1551 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
1552 INT x, INT y, INT cx, INT cy, UINT flags )
1557 winpos.hwndInsertAfter = hwndInsertAfter;
1562 winpos.flags = flags;
1563 if (WIN_IsCurrentThread( hwnd )) return USER_Driver.pSetWindowPos( &winpos );
1564 return SendMessageW( winpos.hwnd, WM_WINE_SETWINDOWPOS, 0, (LPARAM)&winpos );
1568 /***********************************************************************
1569 * BeginDeferWindowPos (USER32.@)
1571 HDWP WINAPI BeginDeferWindowPos( INT count )
1578 SetLastError(ERROR_INVALID_PARAMETER);
1581 /* Windows allows zero count, in which case it allocates context for 8 moves */
1582 if (count == 0) count = 8;
1584 handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
1585 if (!handle) return 0;
1586 pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
1587 pDWP->actualCount = 0;
1588 pDWP->suggestedCount = count;
1590 pDWP->wMagic = DWP_MAGIC;
1591 pDWP->hwndParent = 0;
1596 /***********************************************************************
1597 * DeferWindowPos (USER32.@)
1599 HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter,
1600 INT x, INT y, INT cx, INT cy,
1605 HDWP newhdwp = hdwp,retvalue;
1607 hwnd = WIN_GetFullHandle( hwnd );
1608 if (hwnd == GetDesktopWindow()) return 0;
1610 if (!(pDWP = USER_HEAP_LIN_ADDR( hdwp ))) return 0;
1614 for (i = 0; i < pDWP->actualCount; i++)
1616 if (pDWP->winPos[i].hwnd == hwnd)
1618 /* Merge with the other changes */
1619 if (!(flags & SWP_NOZORDER))
1621 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
1623 if (!(flags & SWP_NOMOVE))
1625 pDWP->winPos[i].x = x;
1626 pDWP->winPos[i].y = y;
1628 if (!(flags & SWP_NOSIZE))
1630 pDWP->winPos[i].cx = cx;
1631 pDWP->winPos[i].cy = cy;
1633 pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
1634 SWP_NOZORDER | SWP_NOREDRAW |
1635 SWP_NOACTIVATE | SWP_NOCOPYBITS|
1637 pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
1643 if (pDWP->actualCount >= pDWP->suggestedCount)
1645 newhdwp = USER_HEAP_REALLOC( hdwp,
1646 sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
1652 pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
1653 pDWP->suggestedCount++;
1655 pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
1656 pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
1657 pDWP->winPos[pDWP->actualCount].x = x;
1658 pDWP->winPos[pDWP->actualCount].y = y;
1659 pDWP->winPos[pDWP->actualCount].cx = cx;
1660 pDWP->winPos[pDWP->actualCount].cy = cy;
1661 pDWP->winPos[pDWP->actualCount].flags = flags;
1662 pDWP->actualCount++;
1670 /***********************************************************************
1671 * EndDeferWindowPos (USER32.@)
1673 BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
1680 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
1681 if (!pDWP) return FALSE;
1682 for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
1684 if (!(res = USER_Driver.pSetWindowPos( winpos ))) break;
1686 USER_HEAP_FREE( hdwp );
1691 /***********************************************************************
1692 * TileChildWindows (USER.199)
1694 void WINAPI TileChildWindows16( HWND16 parent, WORD action )
1696 FIXME("(%04x, %d): stub\n", parent, action);
1699 /***********************************************************************
1700 * CascadeChildWindows (USER.198)
1702 void WINAPI CascadeChildWindows16( HWND16 parent, WORD action )
1704 FIXME("(%04x, %d): stub\n", parent, action);
1707 /***********************************************************************
1708 * SetProgmanWindow (USER32.@)
1710 HWND WINAPI SetProgmanWindow ( HWND hwnd )
1712 hGlobalProgmanWindow = hwnd;
1713 return hGlobalProgmanWindow;
1716 /***********************************************************************
1717 * GetProgmanWindow (USER32.@)
1719 HWND WINAPI GetProgmanWindow(void)
1721 return hGlobalProgmanWindow;
1724 /***********************************************************************
1725 * SetShellWindowEx (USER32.@)
1726 * hwndProgman = Progman[Program Manager]
1727 * |-> SHELLDLL_DefView
1728 * hwndListView = | |-> SysListView32
1729 * | | |-> tooltips_class32
1735 HWND WINAPI SetShellWindowEx ( HWND hwndProgman, HWND hwndListView )
1737 FIXME("0x%08x 0x%08x stub\n",hwndProgman ,hwndListView );
1738 hGlobalShellWindow = hwndProgman;
1739 return hGlobalShellWindow;
1743 /***********************************************************************
1744 * SetTaskmanWindow (USER32.@)
1746 * hwnd = MSTaskSwWClass
1747 * |-> SysTabControl32
1749 HWND WINAPI SetTaskmanWindow ( HWND hwnd )
1751 hGlobalTaskmanWindow = hwnd;
1752 return hGlobalTaskmanWindow;
1755 /***********************************************************************
1756 * GetTaskmanWindow (USER32.@)
1758 HWND WINAPI GetTaskmanWindow(void)
1760 return hGlobalTaskmanWindow;