2 * Window position related functions.
4 * Copyright 1993, 1994, 1995 Alexandre Julliard
5 * 1995, 1996 Alex Korobka
11 #include <X11/Xatom.h>
12 #include "sysmetrics.h"
23 #include "nonclient.h"
26 #define HAS_DLGFRAME(style,exStyle) \
27 (((exStyle) & WS_EX_DLGMODALFRAME) || \
28 (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
30 #define HAS_THICKFRAME(style) \
31 (((style) & WS_THICKFRAME) && \
32 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
34 #define SWP_AGG_NOGEOMETRYCHANGE \
35 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
36 #define SWP_AGG_NOPOSCHANGE \
37 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
38 #define SWP_AGG_STATUSFLAGS \
39 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
41 #define EMPTYPOINT(pt) ((*(LONG*)&(pt)) == -1)
43 #define PLACE_MIN 0x0001
44 #define PLACE_MAX 0x0002
45 #define PLACE_RECT 0x0004
47 #define SMC_NOCOPY 0x0001
48 #define SMC_NOPARENTERASE 0x0002
49 #define SMC_DRAWFRAME 0x0004
50 #define SMC_SETXPOS 0x0008
52 /* ----- internal variables ----- */
54 static HWND32 hwndActive = 0; /* Currently active window */
55 static HWND32 hwndPrevActive = 0; /* Previously active window */
56 static HWND32 hGlobalShellWindow=0; /*the shell*/
58 static LPCSTR atomInternalPos;
60 extern MESSAGEQUEUE* pActiveQueue;
62 /***********************************************************************
63 * WINPOS_CreateInternalPosAtom
65 BOOL32 WINPOS_CreateInternalPosAtom()
68 atomInternalPos = (LPCSTR)(DWORD)GlobalAddAtom32A(str);
69 return (atomInternalPos) ? TRUE : FALSE;
72 /***********************************************************************
73 * WINPOS_CheckInternalPos
75 * Called when a window is destroyed.
77 void WINPOS_CheckInternalPos( HWND32 hwnd )
79 LPINTERNALPOS lpPos = (LPINTERNALPOS) GetProp32A( hwnd, atomInternalPos );
81 if( hwnd == hwndPrevActive ) hwndPrevActive = 0;
82 if( hwnd == hwndActive )
85 WARN(win, "\tattempt to activate destroyed window!\n");
90 if( IsWindow32(lpPos->hwndIconTitle) )
91 DestroyWindow32( lpPos->hwndIconTitle );
92 HeapFree( SystemHeap, 0, lpPos );
96 /***********************************************************************
99 * Find a suitable place for an iconic window.
101 static POINT16 WINPOS_FindIconPos( WND* wndPtr, POINT16 pt )
104 short x, y, xspacing, yspacing;
106 GetClientRect16( wndPtr->parent->hwndSelf, &rectParent );
107 if ((pt.x >= rectParent.left) && (pt.x + SYSMETRICS_CXICON < rectParent.right) &&
108 (pt.y >= rectParent.top) && (pt.y + SYSMETRICS_CYICON < rectParent.bottom))
109 return pt; /* The icon already has a suitable position */
111 xspacing = SYSMETRICS_CXICONSPACING;
112 yspacing = SYSMETRICS_CYICONSPACING;
114 y = rectParent.bottom;
117 for (x = rectParent.left; x <= rectParent.right-xspacing; x += xspacing)
119 /* Check if another icon already occupies this spot */
120 WND *childPtr = wndPtr->parent->child;
123 if ((childPtr->dwStyle & WS_MINIMIZE) && (childPtr != wndPtr))
125 if ((childPtr->rectWindow.left < x + xspacing) &&
126 (childPtr->rectWindow.right >= x) &&
127 (childPtr->rectWindow.top <= y) &&
128 (childPtr->rectWindow.bottom > y - yspacing))
129 break; /* There's a window in there */
131 childPtr = childPtr->next;
133 if (!childPtr) /* No window was found, so it's OK for us */
135 pt.x = x + (xspacing - SYSMETRICS_CXICON) / 2;
136 pt.y = y - (yspacing + SYSMETRICS_CYICON) / 2;
145 /***********************************************************************
146 * ArrangeIconicWindows16 (USER.170)
148 UINT16 WINAPI ArrangeIconicWindows16( HWND16 parent)
150 return ArrangeIconicWindows32(parent);
152 /***********************************************************************
153 * ArrangeIconicWindows32 (USER32.7)
155 UINT32 WINAPI ArrangeIconicWindows32( HWND32 parent )
159 INT32 x, y, xspacing, yspacing;
161 GetClientRect32( parent, &rectParent );
163 y = rectParent.bottom;
164 xspacing = SYSMETRICS_CXICONSPACING;
165 yspacing = SYSMETRICS_CYICONSPACING;
167 hwndChild = GetWindow32( parent, GW_CHILD );
170 if( IsIconic32( hwndChild ) )
172 WINPOS_ShowIconTitle( WIN_FindWndPtr(hwndChild), FALSE );
173 SetWindowPos32( hwndChild, 0, x + (xspacing - SYSMETRICS_CXICON) / 2,
174 y - yspacing - SYSMETRICS_CYICON/2, 0, 0,
175 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
176 if( IsWindow32(hwndChild) )
177 WINPOS_ShowIconTitle( WIN_FindWndPtr(hwndChild), TRUE );
178 if (x <= rectParent.right - xspacing) x += xspacing;
185 hwndChild = GetWindow32( hwndChild, GW_HWNDNEXT );
191 /***********************************************************************
192 * SwitchToThisWindow16 (USER.172)
194 void WINAPI SwitchToThisWindow16( HWND16 hwnd, BOOL16 restore )
196 SwitchToThisWindow32( hwnd, restore );
200 /***********************************************************************
201 * SwitchToThisWindow32 (USER32.539)
203 void WINAPI SwitchToThisWindow32( HWND32 hwnd, BOOL32 restore )
205 ShowWindow32( hwnd, restore ? SW_RESTORE : SW_SHOWMINIMIZED );
209 /***********************************************************************
210 * GetWindowRect16 (USER.32)
212 void WINAPI GetWindowRect16( HWND16 hwnd, LPRECT16 rect )
214 WND * wndPtr = WIN_FindWndPtr( hwnd );
217 CONV_RECT32TO16( &wndPtr->rectWindow, rect );
218 if (wndPtr->dwStyle & WS_CHILD)
219 MapWindowPoints16( wndPtr->parent->hwndSelf, 0, (POINT16 *)rect, 2 );
223 /***********************************************************************
224 * GetWindowRect32 (USER32.308)
226 BOOL32 WINAPI GetWindowRect32( HWND32 hwnd, LPRECT32 rect )
228 WND * wndPtr = WIN_FindWndPtr( hwnd );
229 if (!wndPtr) return FALSE;
231 *rect = wndPtr->rectWindow;
232 if (wndPtr->dwStyle & WS_CHILD)
233 MapWindowPoints32( wndPtr->parent->hwndSelf, 0, (POINT32 *)rect, 2 );
238 /***********************************************************************
241 BOOL32 WINAPI GetWindowRgn32 ( HWND32 hwnd, HRGN32 hrgn )
245 WND * wndPtr = WIN_FindWndPtr( hwnd );
246 if (!wndPtr) return (ERROR);
248 FIXME (win, "GetWindowRgn32: doesn't really do regions\n");
250 memset (&rect, 0, sizeof(rect));
252 GetWindowRect32 ( hwnd, &rect );
254 FIXME (win, "Check whether a valid region here\n");
256 SetRectRgn32 ( hrgn, rect.left, rect.top, rect.right, rect.bottom );
258 return (SIMPLEREGION);
261 /***********************************************************************
264 INT32 WINAPI SetWindowRgn32( HWND32 hwnd, HRGN32 hrgn,BOOL32 bRedraw)
268 FIXME (win, "SetWindowRgn32: stub\n");
272 /***********************************************************************
275 INT16 WINAPI SetWindowRgn16( HWND16 hwnd, HRGN16 hrgn,BOOL16 bRedraw)
279 FIXME (win, "SetWindowRgn16: stub\n");
284 /***********************************************************************
285 * GetClientRect16 (USER.33)
287 void WINAPI GetClientRect16( HWND16 hwnd, LPRECT16 rect )
289 WND * wndPtr = WIN_FindWndPtr( hwnd );
291 rect->left = rect->top = rect->right = rect->bottom = 0;
294 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
295 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
300 /***********************************************************************
301 * GetClientRect32 (USER32.220)
303 void WINAPI GetClientRect32( HWND32 hwnd, LPRECT32 rect )
305 WND * wndPtr = WIN_FindWndPtr( hwnd );
307 rect->left = rect->top = rect->right = rect->bottom = 0;
310 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
311 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
316 /*******************************************************************
317 * ClientToScreen16 (USER.28)
319 void WINAPI ClientToScreen16( HWND16 hwnd, LPPOINT16 lppnt )
321 MapWindowPoints16( hwnd, 0, lppnt, 1 );
325 /*******************************************************************
326 * ClientToScreen32 (USER32.52)
328 BOOL32 WINAPI ClientToScreen32( HWND32 hwnd, LPPOINT32 lppnt )
330 MapWindowPoints32( hwnd, 0, lppnt, 1 );
335 /*******************************************************************
336 * ScreenToClient16 (USER.29)
338 void WINAPI ScreenToClient16( HWND16 hwnd, LPPOINT16 lppnt )
340 MapWindowPoints16( 0, hwnd, lppnt, 1 );
344 /*******************************************************************
345 * ScreenToClient32 (USER32.447)
347 void WINAPI ScreenToClient32( HWND32 hwnd, LPPOINT32 lppnt )
349 MapWindowPoints32( 0, hwnd, lppnt, 1 );
353 /***********************************************************************
354 * WINPOS_WindowFromPoint
356 * Find the window and hittest for a given point.
358 INT16 WINPOS_WindowFromPoint( WND* wndScope, POINT16 pt, WND **ppWnd )
361 INT16 hittest = HTERROR;
365 wndPtr = wndScope->child;
366 if( wndScope->flags & WIN_MANAGED )
368 /* this prevents mouse clicks from going "through" scrollbars in managed mode */
369 if( pt.x < wndScope->rectClient.left || pt.x >= wndScope->rectClient.right ||
370 pt.y < wndScope->rectClient.top || pt.y >= wndScope->rectClient.bottom )
373 MapWindowPoints16( GetDesktopWindow16(), wndScope->hwndSelf, &xy, 1 );
379 /* If point is in window, and window is visible, and it */
380 /* is enabled (or it's a top-level window), then explore */
381 /* its children. Otherwise, go to the next window. */
383 if ((wndPtr->dwStyle & WS_VISIBLE) &&
384 (!(wndPtr->dwStyle & WS_DISABLED) ||
385 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)) &&
386 (xy.x >= wndPtr->rectWindow.left) &&
387 (xy.x < wndPtr->rectWindow.right) &&
388 (xy.y >= wndPtr->rectWindow.top) &&
389 (xy.y < wndPtr->rectWindow.bottom))
391 *ppWnd = wndPtr; /* Got a suitable window */
393 /* If window is minimized or disabled, return at once */
394 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
395 if (wndPtr->dwStyle & WS_DISABLED) return HTERROR;
397 /* If point is not in client area, ignore the children */
398 if ((xy.x < wndPtr->rectClient.left) ||
399 (xy.x >= wndPtr->rectClient.right) ||
400 (xy.y < wndPtr->rectClient.top) ||
401 (xy.y >= wndPtr->rectClient.bottom)) break;
403 xy.x -= wndPtr->rectClient.left;
404 xy.y -= wndPtr->rectClient.top;
405 wndPtr = wndPtr->child;
407 else wndPtr = wndPtr->next;
411 /* If nothing found, try the scope window */
412 if (!*ppWnd) *ppWnd = wndScope;
414 /* Send the WM_NCHITTEST message (only if to the same task) */
415 if ((*ppWnd)->hmemTaskQ == GetTaskQueue(0))
417 hittest = (INT16)SendMessage16( (*ppWnd)->hwndSelf, WM_NCHITTEST,
418 0, MAKELONG( pt.x, pt.y ) );
419 if (hittest != HTTRANSPARENT) return hittest; /* Found the window */
421 else return HTCLIENT;
423 /* If no children found in last search, make point relative to parent */
426 xy.x += (*ppWnd)->rectClient.left;
427 xy.y += (*ppWnd)->rectClient.top;
430 /* Restart the search from the next sibling */
431 wndPtr = (*ppWnd)->next;
432 *ppWnd = (*ppWnd)->parent;
437 /*******************************************************************
438 * WindowFromPoint16 (USER.30)
440 HWND16 WINAPI WindowFromPoint16( POINT16 pt )
443 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt, &pWnd );
444 return pWnd->hwndSelf;
448 /*******************************************************************
449 * WindowFromPoint32 (USER32.582)
451 HWND32 WINAPI WindowFromPoint32( POINT32 pt )
455 CONV_POINT32TO16( &pt, &pt16 );
456 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16, &pWnd );
457 return (HWND32)pWnd->hwndSelf;
461 /*******************************************************************
462 * ChildWindowFromPoint16 (USER.191)
464 HWND16 WINAPI ChildWindowFromPoint16( HWND16 hwndParent, POINT16 pt )
467 CONV_POINT16TO32( &pt, &pt32 );
468 return (HWND16)ChildWindowFromPoint32( hwndParent, pt32 );
472 /*******************************************************************
473 * ChildWindowFromPoint32 (USER32.49)
475 HWND32 WINAPI ChildWindowFromPoint32( HWND32 hwndParent, POINT32 pt )
477 /* pt is in the client coordinates */
479 WND* wnd = WIN_FindWndPtr(hwndParent);
484 /* get client rect fast */
485 rect.top = rect.left = 0;
486 rect.right = wnd->rectClient.right - wnd->rectClient.left;
487 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
489 if (!PtInRect32( &rect, pt )) return 0;
494 if (PtInRect32( &wnd->rectWindow, pt )) return wnd->hwndSelf;
501 /*******************************************************************
502 * WINPOS_GetWinOffset
504 * Calculate the offset between the origin of the two windows. Used
505 * to implement MapWindowPoints.
507 static void WINPOS_GetWinOffset( HWND32 hwndFrom, HWND32 hwndTo,
512 offset->x = offset->y = 0;
513 if (hwndFrom == hwndTo ) return;
515 /* Translate source window origin to screen coords */
518 if (!(wndPtr = WIN_FindWndPtr( hwndFrom )))
520 ERR(win,"bad hwndFrom = %04x\n",hwndFrom);
523 while (wndPtr->parent)
525 offset->x += wndPtr->rectClient.left;
526 offset->y += wndPtr->rectClient.top;
527 wndPtr = wndPtr->parent;
531 /* Translate origin to destination window coords */
534 if (!(wndPtr = WIN_FindWndPtr( hwndTo )))
536 ERR(win,"bad hwndTo = %04x\n", hwndTo );
539 while (wndPtr->parent)
541 offset->x -= wndPtr->rectClient.left;
542 offset->y -= wndPtr->rectClient.top;
543 wndPtr = wndPtr->parent;
549 /*******************************************************************
550 * MapWindowPoints16 (USER.258)
552 void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
553 LPPOINT16 lppt, UINT16 count )
557 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
567 /*******************************************************************
568 * MapWindowPoints32 (USER32.386)
570 void WINAPI MapWindowPoints32( HWND32 hwndFrom, HWND32 hwndTo,
571 LPPOINT32 lppt, UINT32 count )
575 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
585 /***********************************************************************
586 * IsIconic16 (USER.31)
588 BOOL16 WINAPI IsIconic16(HWND16 hWnd)
590 return IsIconic32(hWnd);
594 /***********************************************************************
595 * IsIconic32 (USER32.345)
597 BOOL32 WINAPI IsIconic32(HWND32 hWnd)
599 WND * wndPtr = WIN_FindWndPtr(hWnd);
600 if (wndPtr == NULL) return FALSE;
601 return (wndPtr->dwStyle & WS_MINIMIZE) != 0;
605 /***********************************************************************
606 * IsZoomed (USER.272)
608 BOOL16 WINAPI IsZoomed16(HWND16 hWnd)
610 return IsZoomed32(hWnd);
614 /***********************************************************************
615 * IsZoomed (USER32.352)
617 BOOL32 WINAPI IsZoomed32(HWND32 hWnd)
619 WND * wndPtr = WIN_FindWndPtr(hWnd);
620 if (wndPtr == NULL) return FALSE;
621 return (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
625 /*******************************************************************
626 * GetActiveWindow (USER.60)
628 HWND16 WINAPI GetActiveWindow16(void)
630 return (HWND16)hwndActive;
633 /*******************************************************************
634 * GetActiveWindow (USER32.205)
636 HWND32 WINAPI GetActiveWindow32(void)
638 return (HWND32)hwndActive;
642 /*******************************************************************
645 static BOOL32 WINPOS_CanActivate(WND* pWnd)
647 if( pWnd && ((pWnd->dwStyle & (WS_DISABLED | WS_VISIBLE | WS_CHILD))
648 == WS_VISIBLE) ) return TRUE;
653 /*******************************************************************
654 * SetActiveWindow16 (USER.59)
656 HWND16 WINAPI SetActiveWindow16( HWND16 hwnd )
658 return SetActiveWindow32(hwnd);
662 /*******************************************************************
663 * SetActiveWindow32 (USER32.463)
665 HWND32 WINAPI SetActiveWindow32( HWND32 hwnd )
667 HWND32 prev = hwndActive;
668 WND *wndPtr = WIN_FindWndPtr( hwnd );
670 if ( !WINPOS_CanActivate(wndPtr) ) return 0;
672 WINPOS_SetActiveWindow( hwnd, 0, 0 );
677 /*******************************************************************
678 * GetForegroundWindow16 (USER.608)
680 HWND16 WINAPI GetForegroundWindow16(void)
682 return (HWND16)GetForegroundWindow32();
686 /*******************************************************************
687 * SetForegroundWindow16 (USER.609)
689 BOOL16 WINAPI SetForegroundWindow16( HWND16 hwnd )
691 return SetForegroundWindow32( hwnd );
695 /*******************************************************************
696 * GetForegroundWindow32 (USER32.241)
698 HWND32 WINAPI GetForegroundWindow32(void)
700 return GetActiveWindow32();
704 /*******************************************************************
705 * SetForegroundWindow32 (USER32.482)
707 BOOL32 WINAPI SetForegroundWindow32( HWND32 hwnd )
709 SetActiveWindow32( hwnd );
714 /*******************************************************************
715 * GetShellWindow16 (USER.600)
717 HWND16 WINAPI GetShellWindow16(void)
719 return GetShellWindow32();
722 /*******************************************************************
723 * SetShellWindow32 (USER32.504)
725 HWND32 WINAPI SetShellWindow32(HWND32 hwndshell)
726 { WARN(win, "(hWnd=%08x) semi stub\n",hwndshell );
728 hGlobalShellWindow = hwndshell;
729 return hGlobalShellWindow;
733 /*******************************************************************
734 * GetShellWindow32 (USER32.287)
736 HWND32 WINAPI GetShellWindow32(void)
737 { WARN(win, "(hWnd=%x) semi stub\n",hGlobalShellWindow );
739 return hGlobalShellWindow;
743 /***********************************************************************
744 * BringWindowToTop16 (USER.45)
746 BOOL16 WINAPI BringWindowToTop16( HWND16 hwnd )
748 return BringWindowToTop32(hwnd);
752 /***********************************************************************
753 * BringWindowToTop32 (USER32.11)
755 BOOL32 WINAPI BringWindowToTop32( HWND32 hwnd )
757 return SetWindowPos32( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
761 /***********************************************************************
762 * MoveWindow16 (USER.56)
764 BOOL16 WINAPI MoveWindow16( HWND16 hwnd, INT16 x, INT16 y, INT16 cx, INT16 cy,
767 return MoveWindow32(hwnd,x,y,cx,cy,repaint);
771 /***********************************************************************
772 * MoveWindow32 (USER32.399)
774 BOOL32 WINAPI MoveWindow32( HWND32 hwnd, INT32 x, INT32 y, INT32 cx, INT32 cy,
777 int flags = SWP_NOZORDER | SWP_NOACTIVATE;
778 if (!repaint) flags |= SWP_NOREDRAW;
779 TRACE(win, "%04x %d,%d %dx%d %d\n",
780 hwnd, x, y, cx, cy, repaint );
781 return SetWindowPos32( hwnd, 0, x, y, cx, cy, flags );
784 /***********************************************************************
785 * WINPOS_InitInternalPos
787 static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT32 pt,
788 LPRECT32 restoreRect )
790 LPINTERNALPOS lpPos = (LPINTERNALPOS) GetProp32A( wnd->hwndSelf,
794 /* this happens when the window is minimized/maximized
795 * for the first time (rectWindow is not adjusted yet) */
797 lpPos = HeapAlloc( SystemHeap, 0, sizeof(INTERNALPOS) );
798 if( !lpPos ) return NULL;
800 SetProp32A( wnd->hwndSelf, atomInternalPos, (HANDLE32)lpPos );
801 lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
802 CONV_RECT32TO16( &wnd->rectWindow, &lpPos->rectNormal );
803 *(UINT32*)&lpPos->ptIconPos = *(UINT32*)&lpPos->ptMaxPos = 0xFFFFFFFF;
806 if( wnd->dwStyle & WS_MINIMIZE )
807 CONV_POINT32TO16( &pt, &lpPos->ptIconPos );
808 else if( wnd->dwStyle & WS_MAXIMIZE )
809 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
810 else if( restoreRect )
811 CONV_RECT32TO16( restoreRect, &lpPos->rectNormal );
816 /***********************************************************************
817 * WINPOS_RedrawIconTitle
819 BOOL32 WINPOS_RedrawIconTitle( HWND32 hWnd )
821 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetProp32A( hWnd, atomInternalPos );
824 if( lpPos->hwndIconTitle )
826 SendMessage32A( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
827 InvalidateRect32( lpPos->hwndIconTitle, NULL, TRUE );
834 /***********************************************************************
835 * WINPOS_ShowIconTitle
837 BOOL32 WINPOS_ShowIconTitle( WND* pWnd, BOOL32 bShow )
839 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetProp32A( pWnd->hwndSelf, atomInternalPos );
841 if( lpPos && !(pWnd->flags & WIN_MANAGED))
843 HWND16 hWnd = lpPos->hwndIconTitle;
845 TRACE(win,"0x%04x %i\n", pWnd->hwndSelf, (bShow != 0) );
848 lpPos->hwndIconTitle = hWnd = ICONTITLE_Create( pWnd );
851 pWnd = WIN_FindWndPtr(hWnd);
853 if( !(pWnd->dwStyle & WS_VISIBLE) )
855 SendMessage32A( hWnd, WM_SHOWWINDOW, TRUE, 0 );
856 SetWindowPos32( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
857 SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
860 else ShowWindow32( hWnd, SW_HIDE );
865 /*******************************************************************
866 * WINPOS_GetMinMaxInfo
868 * Get the minimized and maximized information for a window.
870 void WINPOS_GetMinMaxInfo( WND *wndPtr, POINT32 *maxSize, POINT32 *maxPos,
871 POINT32 *minTrack, POINT32 *maxTrack )
877 /* Compute default values */
879 MinMax.ptMaxSize.x = SYSMETRICS_CXSCREEN;
880 MinMax.ptMaxSize.y = SYSMETRICS_CYSCREEN;
881 MinMax.ptMinTrackSize.x = SYSMETRICS_CXMINTRACK;
882 MinMax.ptMinTrackSize.y = SYSMETRICS_CYMINTRACK;
883 MinMax.ptMaxTrackSize.x = SYSMETRICS_CXSCREEN;
884 MinMax.ptMaxTrackSize.y = SYSMETRICS_CYSCREEN;
886 if (wndPtr->flags & WIN_MANAGED) xinc = yinc = 0;
887 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
889 xinc = SYSMETRICS_CXDLGFRAME;
890 yinc = SYSMETRICS_CYDLGFRAME;
895 if (HAS_THICKFRAME(wndPtr->dwStyle))
897 xinc += SYSMETRICS_CXFRAME;
898 yinc += SYSMETRICS_CYFRAME;
900 if (wndPtr->dwStyle & WS_BORDER)
902 xinc += SYSMETRICS_CXBORDER;
903 yinc += SYSMETRICS_CYBORDER;
906 MinMax.ptMaxSize.x += 2 * xinc;
907 MinMax.ptMaxSize.y += 2 * yinc;
909 lpPos = (LPINTERNALPOS)GetProp32A( wndPtr->hwndSelf, atomInternalPos );
910 if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
911 CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
914 MinMax.ptMaxPosition.x = -xinc;
915 MinMax.ptMaxPosition.y = -yinc;
918 SendMessage32A( wndPtr->hwndSelf, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
920 /* Some sanity checks */
922 TRACE(win,"%d %d / %d %d / %d %d / %d %d\n",
923 MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
924 MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
925 MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
926 MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
927 MinMax.ptMaxTrackSize.x = MAX( MinMax.ptMaxTrackSize.x,
928 MinMax.ptMinTrackSize.x );
929 MinMax.ptMaxTrackSize.y = MAX( MinMax.ptMaxTrackSize.y,
930 MinMax.ptMinTrackSize.y );
932 if (maxSize) *maxSize = MinMax.ptMaxSize;
933 if (maxPos) *maxPos = MinMax.ptMaxPosition;
934 if (minTrack) *minTrack = MinMax.ptMinTrackSize;
935 if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
938 /***********************************************************************
941 * Fill in lpRect and return additional flags to be used with SetWindowPos().
942 * This function assumes that 'cmd' is different from the current window
945 UINT16 WINPOS_MinMaximize( WND* wndPtr, UINT16 cmd, LPRECT16 lpRect )
949 POINT32 size = { wndPtr->rectWindow.left, wndPtr->rectWindow.top };
950 LPINTERNALPOS lpPos = WINPOS_InitInternalPos( wndPtr, size,
951 &wndPtr->rectWindow );
953 TRACE(win,"0x%04x %u\n", wndPtr->hwndSelf, cmd );
955 if (lpPos && !HOOK_CallHooks16(WH_CBT, HCBT_MINMAX, wndPtr->hwndSelf, cmd))
957 if( wndPtr->dwStyle & WS_MINIMIZE )
959 if( !SendMessage32A( wndPtr->hwndSelf, WM_QUERYOPEN, 0, 0L ) )
960 return (SWP_NOSIZE | SWP_NOMOVE);
961 swpFlags |= SWP_NOCOPYBITS;
966 if( wndPtr->dwStyle & WS_MAXIMIZE)
968 wndPtr->flags |= WIN_RESTORE_MAX;
969 wndPtr->dwStyle &= ~WS_MAXIMIZE;
972 wndPtr->flags &= ~WIN_RESTORE_MAX;
973 wndPtr->dwStyle |= WS_MINIMIZE;
975 lpPos->ptIconPos = WINPOS_FindIconPos( wndPtr, lpPos->ptIconPos );
977 SetRect16( lpRect, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
978 SYSMETRICS_CXICON, SYSMETRICS_CYICON );
979 swpFlags |= SWP_NOCOPYBITS;
983 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
984 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL );
985 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
987 if( wndPtr->dwStyle & WS_MINIMIZE )
989 WINPOS_ShowIconTitle( wndPtr, FALSE );
990 wndPtr->dwStyle &= ~WS_MINIMIZE;
992 wndPtr->dwStyle |= WS_MAXIMIZE;
994 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
999 if( wndPtr->dwStyle & WS_MINIMIZE )
1001 wndPtr->dwStyle &= ~WS_MINIMIZE;
1002 WINPOS_ShowIconTitle( wndPtr, FALSE );
1003 if( wndPtr->flags & WIN_RESTORE_MAX)
1005 /* Restore to maximized position */
1006 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1007 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL);
1008 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1009 wndPtr->dwStyle |= WS_MAXIMIZE;
1010 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y, size.x, size.y );
1015 if( !(wndPtr->dwStyle & WS_MAXIMIZE) ) return (UINT16)(-1);
1016 else wndPtr->dwStyle &= ~WS_MAXIMIZE;
1018 /* Restore to normal position */
1020 *lpRect = lpPos->rectNormal;
1021 lpRect->right -= lpRect->left;
1022 lpRect->bottom -= lpRect->top;
1026 } else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
1030 /***********************************************************************
1031 * ShowWindowAsync32 (USER32.535)
1033 * doesn't wait; returns immediately.
1034 * used by threads to toggle windows in other (possibly hanging) threads
1036 BOOL32 WINAPI ShowWindowAsync32( HWND32 hwnd, INT32 cmd )
1038 /* FIXME: does ShowWindow32() return immediately ? */
1039 return ShowWindow32(hwnd, cmd);
1043 /***********************************************************************
1044 * ShowWindow16 (USER.42)
1046 BOOL16 WINAPI ShowWindow16( HWND16 hwnd, INT16 cmd )
1048 return ShowWindow32(hwnd,cmd);
1052 /***********************************************************************
1053 * ShowWindow32 (USER32.534)
1055 BOOL32 WINAPI ShowWindow32( HWND32 hwnd, INT32 cmd )
1057 WND* wndPtr = WIN_FindWndPtr( hwnd );
1058 BOOL32 wasVisible, showFlag;
1059 RECT16 newPos = {0, 0, 0, 0};
1062 if (!wndPtr) return FALSE;
1064 TRACE(win,"hwnd=%04x, cmd=%d\n", hwnd, cmd);
1066 wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
1071 if (!wasVisible) return FALSE;
1072 swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
1073 SWP_NOACTIVATE | SWP_NOZORDER;
1076 case SW_SHOWMINNOACTIVE:
1077 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1079 case SW_SHOWMINIMIZED:
1080 swp |= SWP_SHOWWINDOW;
1083 swp |= SWP_FRAMECHANGED;
1084 if( !(wndPtr->dwStyle & WS_MINIMIZE) )
1085 swp |= WINPOS_MinMaximize( wndPtr, SW_MINIMIZE, &newPos );
1086 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1089 case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
1090 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1091 if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
1092 swp |= WINPOS_MinMaximize( wndPtr, SW_MAXIMIZE, &newPos );
1093 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1097 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1100 swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
1103 case SW_SHOWNOACTIVATE:
1104 swp |= SWP_NOZORDER;
1105 if (GetActiveWindow32()) swp |= SWP_NOACTIVATE;
1107 case SW_SHOWNORMAL: /* same as SW_NORMAL: */
1108 case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
1110 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1112 if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) )
1113 swp |= WINPOS_MinMaximize( wndPtr, SW_RESTORE, &newPos );
1114 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1118 showFlag = (cmd != SW_HIDE);
1119 if (showFlag != wasVisible)
1121 SendMessage32A( hwnd, WM_SHOWWINDOW, showFlag, 0 );
1122 if (!IsWindow32( hwnd )) return wasVisible;
1125 if ((wndPtr->dwStyle & WS_CHILD) &&
1126 !IsWindowVisible32( wndPtr->parent->hwndSelf ) &&
1127 (swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE) )
1129 /* Don't call SetWindowPos32() on invisible child windows */
1130 if (cmd == SW_HIDE) wndPtr->dwStyle &= ~WS_VISIBLE;
1131 else wndPtr->dwStyle |= WS_VISIBLE;
1135 /* We can't activate a child window */
1136 if (wndPtr->dwStyle & WS_CHILD) swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1137 SetWindowPos32( hwnd, HWND_TOP,
1138 newPos.left, newPos.top, newPos.right, newPos.bottom, swp );
1139 if (!IsWindow32( hwnd )) return wasVisible;
1140 else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( wndPtr, TRUE );
1143 if (wndPtr->flags & WIN_NEED_SIZE)
1145 /* should happen only in CreateWindowEx() */
1146 int wParam = SIZE_RESTORED;
1148 wndPtr->flags &= ~WIN_NEED_SIZE;
1149 if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
1150 else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
1151 SendMessage32A( hwnd, WM_SIZE, wParam,
1152 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
1153 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
1154 SendMessage32A( hwnd, WM_MOVE, 0,
1155 MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
1162 /***********************************************************************
1163 * GetInternalWindowPos16 (USER.460)
1165 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
1168 WINDOWPLACEMENT16 wndpl;
1169 if (GetWindowPlacement16( hwnd, &wndpl ))
1171 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1172 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1173 return wndpl.showCmd;
1179 /***********************************************************************
1180 * GetInternalWindowPos32 (USER32.245)
1182 UINT32 WINAPI GetInternalWindowPos32( HWND32 hwnd, LPRECT32 rectWnd,
1185 WINDOWPLACEMENT32 wndpl;
1186 if (GetWindowPlacement32( hwnd, &wndpl ))
1188 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1189 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1190 return wndpl.showCmd;
1195 /***********************************************************************
1196 * GetWindowPlacement16 (USER.370)
1198 BOOL16 WINAPI GetWindowPlacement16( HWND16 hwnd, WINDOWPLACEMENT16 *wndpl )
1200 WND *pWnd = WIN_FindWndPtr( hwnd );
1203 LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1204 *(LPPOINT32)&pWnd->rectWindow.left, &pWnd->rectWindow );
1205 wndpl->length = sizeof(*wndpl);
1206 if( pWnd->dwStyle & WS_MINIMIZE )
1207 wndpl->showCmd = SW_SHOWMINIMIZED;
1209 wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE )
1210 ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
1211 if( pWnd->flags & WIN_RESTORE_MAX )
1212 wndpl->flags = WPF_RESTORETOMAXIMIZED;
1215 wndpl->ptMinPosition = lpPos->ptIconPos;
1216 wndpl->ptMaxPosition = lpPos->ptMaxPos;
1217 wndpl->rcNormalPosition = lpPos->rectNormal;
1224 /***********************************************************************
1225 * GetWindowPlacement32 (USER32.307)
1227 BOOL32 WINAPI GetWindowPlacement32( HWND32 hwnd, WINDOWPLACEMENT32 *pwpl32 )
1231 WINDOWPLACEMENT16 wpl;
1232 wpl.length = sizeof(wpl);
1233 if( GetWindowPlacement16( hwnd, &wpl ) )
1235 pwpl32->length = sizeof(*pwpl32);
1236 pwpl32->flags = wpl.flags;
1237 pwpl32->showCmd = wpl.showCmd;
1238 CONV_POINT16TO32( &wpl.ptMinPosition, &pwpl32->ptMinPosition );
1239 CONV_POINT16TO32( &wpl.ptMaxPosition, &pwpl32->ptMaxPosition );
1240 CONV_RECT16TO32( &wpl.rcNormalPosition, &pwpl32->rcNormalPosition );
1248 /***********************************************************************
1249 * WINPOS_SetPlacement
1251 static BOOL32 WINPOS_SetPlacement( HWND32 hwnd, const WINDOWPLACEMENT16 *wndpl,
1254 WND *pWnd = WIN_FindWndPtr( hwnd );
1257 LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1258 *(LPPOINT32)&pWnd->rectWindow.left, &pWnd->rectWindow );
1260 if( flags & PLACE_MIN ) lpPos->ptIconPos = wndpl->ptMinPosition;
1261 if( flags & PLACE_MAX ) lpPos->ptMaxPos = wndpl->ptMaxPosition;
1262 if( flags & PLACE_RECT) lpPos->rectNormal = wndpl->rcNormalPosition;
1264 if( pWnd->dwStyle & WS_MINIMIZE )
1266 WINPOS_ShowIconTitle( pWnd, FALSE );
1267 if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1268 SetWindowPos32( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1269 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1271 else if( pWnd->dwStyle & WS_MAXIMIZE )
1273 if( !EMPTYPOINT(lpPos->ptMaxPos) )
1274 SetWindowPos32( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1275 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1277 else if( flags & PLACE_RECT )
1278 SetWindowPos32( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1279 lpPos->rectNormal.right - lpPos->rectNormal.left,
1280 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1281 SWP_NOZORDER | SWP_NOACTIVATE );
1283 ShowWindow32( hwnd, wndpl->showCmd );
1284 if( IsWindow32(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1286 if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd, TRUE );
1288 /* SDK: ...valid only the next time... */
1289 if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1297 /***********************************************************************
1298 * SetWindowPlacement16 (USER.371)
1300 BOOL16 WINAPI SetWindowPlacement16(HWND16 hwnd, const WINDOWPLACEMENT16 *wndpl)
1302 return WINPOS_SetPlacement( hwnd, wndpl,
1303 PLACE_MIN | PLACE_MAX | PLACE_RECT );
1306 /***********************************************************************
1307 * SetWindowPlacement32 (USER32.519)
1309 BOOL32 WINAPI SetWindowPlacement32( HWND32 hwnd, const WINDOWPLACEMENT32 *pwpl32 )
1313 WINDOWPLACEMENT16 wpl = { sizeof(WINDOWPLACEMENT16),
1314 pwpl32->flags, pwpl32->showCmd, { pwpl32->ptMinPosition.x,
1315 pwpl32->ptMinPosition.y }, { pwpl32->ptMaxPosition.x,
1316 pwpl32->ptMaxPosition.y }, { pwpl32->rcNormalPosition.left,
1317 pwpl32->rcNormalPosition.top, pwpl32->rcNormalPosition.right,
1318 pwpl32->rcNormalPosition.bottom } };
1320 return WINPOS_SetPlacement( hwnd, &wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1326 /***********************************************************************
1327 * SetInternalWindowPos16 (USER.461)
1329 void WINAPI SetInternalWindowPos16( HWND16 hwnd, UINT16 showCmd,
1330 LPRECT16 rect, LPPOINT16 pt )
1332 if( IsWindow16(hwnd) )
1334 WINDOWPLACEMENT16 wndpl;
1337 wndpl.length = sizeof(wndpl);
1338 wndpl.showCmd = showCmd;
1339 wndpl.flags = flags = 0;
1344 wndpl.flags |= WPF_SETMINPOSITION;
1345 wndpl.ptMinPosition = *pt;
1349 flags |= PLACE_RECT;
1350 wndpl.rcNormalPosition = *rect;
1352 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1357 /***********************************************************************
1358 * SetInternalWindowPos32 (USER32.483)
1360 void WINAPI SetInternalWindowPos32( HWND32 hwnd, UINT32 showCmd,
1361 LPRECT32 rect, LPPOINT32 pt )
1363 if( IsWindow32(hwnd) )
1365 WINDOWPLACEMENT16 wndpl;
1368 wndpl.length = sizeof(wndpl);
1369 wndpl.showCmd = showCmd;
1370 wndpl.flags = flags = 0;
1375 wndpl.flags |= WPF_SETMINPOSITION;
1376 CONV_POINT32TO16( pt, &wndpl.ptMinPosition );
1380 flags |= PLACE_RECT;
1381 CONV_RECT32TO16( rect, &wndpl.rcNormalPosition );
1383 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1388 /***********************************************************************
1389 * WINPOS_ForceXWindowRaise
1391 * Raise a window on top of the X stacking order, while preserving
1392 * the correct Windows Z order.
1394 static void WINPOS_ForceXWindowRaise( WND* pWnd )
1396 XWindowChanges winChanges;
1399 /* Raise all windows up to pWnd according to their Z order.
1400 * (it would be easier with sibling-related Below but it doesn't
1401 * work very well with SGI mwm for instance)
1403 winChanges.stack_mode = Above;
1406 if (pWnd->window) TSXReconfigureWMWindow( display, pWnd->window, 0,
1407 CWStackMode, &winChanges );
1408 wndPrev = WIN_GetDesktop()->child;
1409 if (wndPrev == pWnd) break;
1410 while (wndPrev && (wndPrev->next != pWnd)) wndPrev = wndPrev->next;
1416 /*******************************************************************
1417 * WINPOS_SetActiveWindow
1419 * SetActiveWindow() back-end. This is the only function that
1420 * can assign active status to a window. It must be called only
1421 * for the top level windows.
1423 BOOL32 WINPOS_SetActiveWindow( HWND32 hWnd, BOOL32 fMouse, BOOL32 fChangeFocus)
1425 CBTACTIVATESTRUCT16* cbtStruct;
1426 WND* wndPtr, *wndTemp;
1427 HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1430 /* paranoid checks */
1431 if( hWnd == GetDesktopWindow32() || hWnd == hwndActive ) return 0;
1433 /* if (wndPtr && (GetTaskQueue(0) != wndPtr->hmemTaskQ))
1436 wndPtr = WIN_FindWndPtr(hWnd);
1437 hOldActiveQueue = (pActiveQueue)?pActiveQueue->self : 0;
1439 if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1440 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1442 TRACE(win,"no current active window.\n");
1444 /* call CBT hook chain */
1445 if ((cbtStruct = SEGPTR_NEW(CBTACTIVATESTRUCT16)))
1448 cbtStruct->fMouse = fMouse;
1449 cbtStruct->hWndActive = hwndActive;
1450 wRet = HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
1451 (LPARAM)SEGPTR_GET(cbtStruct) );
1452 SEGPTR_FREE(cbtStruct);
1453 if (wRet) return wRet;
1456 /* set prev active wnd to current active wnd and send notification */
1457 if ((hwndPrevActive = hwndActive) && IsWindow32(hwndPrevActive))
1459 if (!SendMessage32A( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1461 if (GetSysModalWindow16() != hWnd) return 0;
1462 /* disregard refusal if hWnd is sysmodal */
1466 SendMessage32A( hwndPrevActive, WM_ACTIVATE,
1467 MAKEWPARAM( WA_INACTIVE, wIconized ),
1470 /* FIXME: must be SendMessage16() because 32A doesn't do
1471 * intertask at this time */
1472 SendMessage16( hwndPrevActive, WM_ACTIVATE, WA_INACTIVE,
1473 MAKELPARAM( (HWND16)hWnd, wIconized ) );
1476 /* check if something happened during message processing */
1477 if( hwndPrevActive != hwndActive ) return 0;
1480 /* set active wnd */
1483 /* send palette messages */
1484 if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1485 SendMessage16((HWND16)-1, WM_PALETTEISCHANGING, (WPARAM16)hWnd, 0L );
1487 /* if prev wnd is minimized redraw icon title */
1488 if( IsIconic32( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1490 /* managed windows will get ConfigureNotify event */
1491 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->flags & WIN_MANAGED))
1493 /* check Z-order and bring hWnd to the top */
1494 for (wndTemp = WIN_GetDesktop()->child; wndTemp; wndTemp = wndTemp->next)
1495 if (wndTemp->dwStyle & WS_VISIBLE) break;
1497 if( wndTemp != wndPtr )
1498 SetWindowPos32(hWnd, HWND_TOP, 0,0,0,0,
1499 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1500 if (!IsWindow32(hWnd)) return 0;
1503 hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1505 /* send WM_ACTIVATEAPP if necessary */
1506 if (hOldActiveQueue != hNewActiveQueue)
1508 WND **list, **ppWnd;
1510 if ((list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
1512 for (ppWnd = list; *ppWnd; ppWnd++)
1514 if (!IsWindow32( (*ppWnd)->hwndSelf )) continue;
1516 if ((*ppWnd)->hmemTaskQ == hOldActiveQueue)
1517 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1518 0, QUEUE_GetQueueTask(hNewActiveQueue) );
1520 HeapFree( SystemHeap, 0, list );
1523 pActiveQueue = (hNewActiveQueue)
1524 ? (MESSAGEQUEUE*) GlobalLock16(hNewActiveQueue) : NULL;
1526 if ((list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
1528 for (ppWnd = list; *ppWnd; ppWnd++)
1530 if (!IsWindow32( (*ppWnd)->hwndSelf )) continue;
1532 if ((*ppWnd)->hmemTaskQ == hNewActiveQueue)
1533 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1534 1, QUEUE_GetQueueTask( hOldActiveQueue ) );
1536 HeapFree( SystemHeap, 0, list );
1538 if (!IsWindow32(hWnd)) return 0;
1543 /* walk up to the first unowned window */
1545 while (wndTemp->owner) wndTemp = wndTemp->owner;
1546 /* and set last active owned popup */
1547 wndTemp->hwndLastActive = hWnd;
1549 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1550 SendMessage32A( hWnd, WM_NCACTIVATE, TRUE, 0 );
1552 SendMessage32A( hWnd, WM_ACTIVATE,
1553 MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1554 (LPARAM)hwndPrevActive );
1556 SendMessage16(hWnd, WM_ACTIVATE, (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE,
1557 MAKELPARAM( (HWND16)hwndPrevActive, wIconized) );
1560 if( !IsWindow32(hWnd) ) return 0;
1563 /* change focus if possible */
1564 if( fChangeFocus && GetFocus32() )
1565 if( WIN_GetTopParent(GetFocus32()) != hwndActive )
1566 FOCUS_SwitchFocus( GetFocus32(),
1567 (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
1572 if( !hwndPrevActive && wndPtr &&
1573 wndPtr->window && !(wndPtr->flags & WIN_MANAGED) )
1574 WINPOS_ForceXWindowRaise(wndPtr);
1576 /* if active wnd is minimized redraw icon title */
1577 if( IsIconic32(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1579 return (hWnd == hwndActive);
1582 /*******************************************************************
1583 * WINPOS_ActivateOtherWindow
1585 * Activates window other than pWnd.
1587 BOOL32 WINPOS_ActivateOtherWindow(WND* pWnd)
1592 if( pWnd->hwndSelf == hwndPrevActive )
1595 if( hwndActive != pWnd->hwndSelf &&
1596 ( hwndActive || QUEUE_IsExitingQueue(pWnd->hmemTaskQ)) )
1599 if( !(pWnd->dwStyle & WS_POPUP) || !(pWnd->owner) ||
1600 !WINPOS_CanActivate((pWndTo = WIN_GetTopParentPtr(pWnd->owner))) )
1602 WND* pWndPtr = WIN_GetTopParentPtr(pWnd);
1604 pWndTo = WIN_FindWndPtr(hwndPrevActive);
1606 while( !WINPOS_CanActivate(pWndTo) )
1608 /* by now owned windows should've been taken care of */
1610 pWndTo = pWndPtr->next;
1612 if( !pWndTo ) break;
1616 bRet = WINPOS_SetActiveWindow( pWndTo ? pWndTo->hwndSelf : 0, FALSE, TRUE );
1618 /* switch desktop queue to current active */
1619 if( pWndTo ) WIN_GetDesktop()->hmemTaskQ = pWndTo->hmemTaskQ;
1625 /*******************************************************************
1626 * WINPOS_ChangeActiveWindow
1629 BOOL32 WINPOS_ChangeActiveWindow( HWND32 hWnd, BOOL32 mouseMsg )
1631 WND *wndPtr = WIN_FindWndPtr(hWnd);
1633 if (!hWnd) return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
1635 if( !wndPtr ) return FALSE;
1637 /* child windows get WM_CHILDACTIVATE message */
1638 if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
1639 return SendMessage32A(hWnd, WM_CHILDACTIVATE, 0, 0L);
1641 /* owned popups imply owner activation - not sure */
1642 if ((wndPtr->dwStyle & WS_POPUP) && wndPtr->owner &&
1643 !(wndPtr->owner->dwStyle & WS_DISABLED ))
1645 if (!(wndPtr = wndPtr->owner)) return FALSE;
1646 hWnd = wndPtr->hwndSelf;
1649 if( hWnd == hwndActive ) return FALSE;
1651 if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
1654 /* switch desktop queue to current active */
1655 if( wndPtr->parent == WIN_GetDesktop())
1656 WIN_GetDesktop()->hmemTaskQ = wndPtr->hmemTaskQ;
1662 /***********************************************************************
1663 * WINPOS_SendNCCalcSize
1665 * Send a WM_NCCALCSIZE message to a window.
1666 * All parameters are read-only except newClientRect.
1667 * oldWindowRect, oldClientRect and winpos must be non-NULL only
1668 * when calcValidRect is TRUE.
1670 LONG WINPOS_SendNCCalcSize( HWND32 hwnd, BOOL32 calcValidRect,
1671 RECT32 *newWindowRect, RECT32 *oldWindowRect,
1672 RECT32 *oldClientRect, WINDOWPOS32 *winpos,
1673 RECT32 *newClientRect )
1675 NCCALCSIZE_PARAMS32 params;
1676 WINDOWPOS32 winposCopy;
1679 params.rgrc[0] = *newWindowRect;
1682 winposCopy = *winpos;
1683 params.rgrc[1] = *oldWindowRect;
1684 params.rgrc[2] = *oldClientRect;
1685 params.lppos = &winposCopy;
1687 result = SendMessage32A( hwnd, WM_NCCALCSIZE, calcValidRect,
1689 TRACE(win, "%d,%d-%d,%d\n",
1690 params.rgrc[0].left, params.rgrc[0].top,
1691 params.rgrc[0].right, params.rgrc[0].bottom );
1692 *newClientRect = params.rgrc[0];
1697 /***********************************************************************
1698 * WINPOS_HandleWindowPosChanging16
1700 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
1702 LONG WINPOS_HandleWindowPosChanging16( WND *wndPtr, WINDOWPOS16 *winpos )
1704 POINT32 maxSize, minTrack;
1705 if (winpos->flags & SWP_NOSIZE) return 0;
1706 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
1707 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
1709 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
1710 if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
1711 if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
1712 if (!(wndPtr->dwStyle & WS_MINIMIZE))
1714 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
1715 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
1722 /***********************************************************************
1723 * WINPOS_HandleWindowPosChanging32
1725 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
1727 LONG WINPOS_HandleWindowPosChanging32( WND *wndPtr, WINDOWPOS32 *winpos )
1730 if (winpos->flags & SWP_NOSIZE) return 0;
1731 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
1732 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
1734 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, NULL, NULL );
1735 winpos->cx = MIN( winpos->cx, maxSize.x );
1736 winpos->cy = MIN( winpos->cy, maxSize.y );
1742 /***********************************************************************
1743 * WINPOS_MoveWindowZOrder
1745 * Move a window in Z order, invalidating everything that needs it.
1746 * Only necessary for windows without associated X window.
1748 static void WINPOS_MoveWindowZOrder( HWND32 hwnd, HWND32 hwndAfter )
1751 WND *pWndAfter, *pWndCur, *wndPtr = WIN_FindWndPtr( hwnd );
1753 /* We have two possible cases:
1754 * - The window is moving up: we have to invalidate all areas
1755 * of the window that were covered by other windows
1756 * - The window is moving down: we have to invalidate areas
1757 * of other windows covered by this one.
1760 if (hwndAfter == HWND_TOP)
1764 else if (hwndAfter == HWND_BOTTOM)
1766 if (!wndPtr->next) return; /* Already at the bottom */
1771 if (!(pWndAfter = WIN_FindWndPtr( hwndAfter ))) return;
1772 if (wndPtr->next == pWndAfter) return; /* Already placed right */
1774 /* Determine which window we encounter first in Z-order */
1775 pWndCur = wndPtr->parent->child;
1776 while ((pWndCur != wndPtr) && (pWndCur != pWndAfter))
1777 pWndCur = pWndCur->next;
1778 movingUp = (pWndCur == pWndAfter);
1783 WND *pWndPrevAfter = wndPtr->next;
1784 WIN_UnlinkWindow( hwnd );
1785 WIN_LinkWindow( hwnd, hwndAfter );
1786 pWndCur = wndPtr->next;
1787 while (pWndCur != pWndPrevAfter)
1789 RECT32 rect = { pWndCur->rectWindow.left,
1790 pWndCur->rectWindow.top,
1791 pWndCur->rectWindow.right,
1792 pWndCur->rectWindow.bottom };
1793 OffsetRect32( &rect, -wndPtr->rectClient.left,
1794 -wndPtr->rectClient.top );
1795 PAINT_RedrawWindow( hwnd, &rect, 0, RDW_INVALIDATE | RDW_ALLCHILDREN |
1796 RDW_FRAME | RDW_ERASE, 0 );
1797 pWndCur = pWndCur->next;
1800 else /* Moving down */
1802 pWndCur = wndPtr->next;
1803 WIN_UnlinkWindow( hwnd );
1804 WIN_LinkWindow( hwnd, hwndAfter );
1805 while (pWndCur != wndPtr)
1807 RECT32 rect = { pWndCur->rectWindow.left,
1808 pWndCur->rectWindow.top,
1809 pWndCur->rectWindow.right,
1810 pWndCur->rectWindow.bottom };
1811 OffsetRect32( &rect, -pWndCur->rectClient.left,
1812 -pWndCur->rectClient.top );
1813 PAINT_RedrawWindow( pWndCur->hwndSelf, &rect, 0, RDW_INVALIDATE |
1814 RDW_ALLCHILDREN | RDW_FRAME | RDW_ERASE, 0 );
1815 pWndCur = pWndCur->next;
1820 /***********************************************************************
1821 * WINPOS_ReorderOwnedPopups
1823 * fix Z order taking into account owned popups -
1824 * basically we need to maintain them above the window that owns them
1826 HWND32 WINPOS_ReorderOwnedPopups(HWND32 hwndInsertAfter,WND* wndPtr,WORD flags)
1828 WND* w = WIN_GetDesktop()->child;
1830 if( wndPtr->dwStyle & WS_POPUP && wndPtr->owner )
1832 /* implement "local z-order" between the top and owner window */
1834 HWND32 hwndLocalPrev = HWND_TOP;
1836 if( hwndInsertAfter != HWND_TOP )
1838 while( w != wndPtr->owner )
1840 if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
1841 if( hwndLocalPrev == hwndInsertAfter ) break;
1844 hwndInsertAfter = hwndLocalPrev;
1848 else if( wndPtr->dwStyle & WS_CHILD ) return hwndInsertAfter;
1850 w = WIN_GetDesktop()->child;
1853 if( w == wndPtr ) break;
1855 if( w->dwStyle & WS_POPUP && w->owner == wndPtr )
1857 SetWindowPos32(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1858 SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
1859 hwndInsertAfter = w->hwndSelf;
1864 return hwndInsertAfter;
1867 /***********************************************************************
1868 * WINPOS_SizeMoveClean
1870 * Make window look nice without excessive repainting
1874 * visible regions are in window coordinates
1875 * update regions are in window client coordinates
1876 * client and window rectangles are in parent client coordinates
1878 * FIXME: Move visible and update regions to the same coordinate system
1879 * (either parent client or window). This is a lot of work though.
1881 static UINT32 WINPOS_SizeMoveClean( WND* Wnd, HRGN32 oldVisRgn,
1882 LPRECT32 lpOldWndRect,
1883 LPRECT32 lpOldClientRect, UINT32 uFlags )
1885 HRGN32 newVisRgn = DCE_GetVisRgn(Wnd->hwndSelf,DCX_WINDOW | DCX_CLIPSIBLINGS);
1886 HRGN32 dirtyRgn = CreateRectRgn32(0,0,0,0);
1889 TRACE(win,"cleaning up...new wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i)\n",
1890 Wnd->rectWindow.left, Wnd->rectWindow.top,
1891 Wnd->rectWindow.right, Wnd->rectWindow.bottom,
1892 lpOldWndRect->left, lpOldWndRect->top,
1893 lpOldWndRect->right, lpOldWndRect->bottom);
1894 TRACE(win,"\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
1895 Wnd->rectClient.left, Wnd->rectClient.top,
1896 Wnd->rectClient.right, Wnd->rectClient.bottom,
1897 lpOldClientRect->left, lpOldClientRect->top,
1898 lpOldClientRect->right,lpOldClientRect->bottom );
1900 if( (lpOldWndRect->right - lpOldWndRect->left) != (Wnd->rectWindow.right - Wnd->rectWindow.left) ||
1901 (lpOldWndRect->bottom - lpOldWndRect->top) != (Wnd->rectWindow.bottom - Wnd->rectWindow.top) )
1902 uFlags |= SMC_DRAWFRAME;
1904 CombineRgn32( dirtyRgn, newVisRgn, 0, RGN_COPY);
1906 if( !(uFlags & SMC_NOCOPY) )
1907 CombineRgn32( newVisRgn, newVisRgn, oldVisRgn, RGN_AND );
1909 /* map regions to the parent client area */
1911 OffsetRgn32( dirtyRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
1912 OffsetRgn32( oldVisRgn, lpOldWndRect->left, lpOldWndRect->top );
1914 /* compute invalidated region outside Wnd - (in client coordinates of the parent window) */
1916 other = CombineRgn32(dirtyRgn, oldVisRgn, dirtyRgn, RGN_DIFF);
1918 /* map visible region to the Wnd client area */
1920 OffsetRgn32( newVisRgn, Wnd->rectWindow.left - Wnd->rectClient.left,
1921 Wnd->rectWindow.top - Wnd->rectClient.top );
1923 /* substract previously invalidated region from the Wnd visible region */
1925 my = (Wnd->hrgnUpdate > 1) ? CombineRgn32( newVisRgn, newVisRgn,
1926 Wnd->hrgnUpdate, RGN_DIFF)
1929 if( uFlags & SMC_NOCOPY ) /* invalidate Wnd visible region */
1931 if (my != NULLREGION)
1932 PAINT_RedrawWindow( Wnd->hwndSelf, NULL, newVisRgn, RDW_INVALIDATE |
1933 RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE, RDW_C_USEHRGN );
1934 else if(uFlags & SMC_DRAWFRAME)
1935 Wnd->flags |= WIN_NEEDS_NCPAINT;
1937 else /* bitblt old client area */
1942 int xfrom,yfrom,xto,yto,width,height;
1944 if( uFlags & SMC_DRAWFRAME )
1946 /* copy only client area, frame will be redrawn anyway */
1948 xfrom = lpOldClientRect->left; yfrom = lpOldClientRect->top;
1949 xto = Wnd->rectClient.left; yto = Wnd->rectClient.top;
1950 width = lpOldClientRect->right - xfrom; height = lpOldClientRect->bottom - yfrom;
1951 updateRgn = CreateRectRgn32( 0, 0, width, height );
1952 CombineRgn32( newVisRgn, newVisRgn, updateRgn, RGN_AND );
1953 SetRectRgn32( updateRgn, 0, 0, Wnd->rectClient.right - xto,
1954 Wnd->rectClient.bottom - yto );
1958 xfrom = lpOldWndRect->left; yfrom = lpOldWndRect->top;
1959 xto = Wnd->rectWindow.left; yto = Wnd->rectWindow.top;
1960 width = lpOldWndRect->right - xfrom; height = lpOldWndRect->bottom - yfrom;
1961 updateRgn = CreateRectRgn32( xto - Wnd->rectClient.left,
1962 yto - Wnd->rectClient.top,
1963 Wnd->rectWindow.right - Wnd->rectClient.left,
1964 Wnd->rectWindow.bottom - Wnd->rectClient.top );
1967 CombineRgn32( newVisRgn, newVisRgn, updateRgn, RGN_AND );
1969 /* substract new visRgn from target rect to get a region that won't be copied */
1971 update = CombineRgn32( updateRgn, updateRgn, newVisRgn, RGN_DIFF );
1973 /* Blt valid bits using parent window DC */
1975 if( my != NULLREGION && (xfrom != xto || yfrom != yto) )
1978 /* compute clipping region in parent client coordinates */
1980 OffsetRgn32( newVisRgn, Wnd->rectClient.left, Wnd->rectClient.top );
1981 CombineRgn32( oldVisRgn, oldVisRgn, newVisRgn, RGN_OR );
1983 hDC = GetDCEx32( Wnd->parent->hwndSelf, oldVisRgn,
1984 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN |
1985 DCX_CACHE | DCX_CLIPSIBLINGS);
1987 BitBlt32( hDC, xto, yto, width, height, hDC, xfrom, yfrom, SRCCOPY );
1988 ReleaseDC32( Wnd->parent->hwndSelf, hDC);
1991 if( update != NULLREGION )
1992 PAINT_RedrawWindow( Wnd->hwndSelf, NULL, updateRgn, RDW_INVALIDATE |
1993 RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE, RDW_C_USEHRGN );
1994 else if( uFlags & SMC_DRAWFRAME ) Wnd->flags |= WIN_NEEDS_NCPAINT;
1995 DeleteObject32( updateRgn );
1998 /* erase uncovered areas */
2000 if( !(uFlags & SMC_NOPARENTERASE) && (other != NULLREGION ) )
2001 PAINT_RedrawWindow( Wnd->parent->hwndSelf, NULL, dirtyRgn,
2002 RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE, RDW_C_USEHRGN );
2003 DeleteObject32(dirtyRgn);
2004 DeleteObject32(newVisRgn);
2009 /***********************************************************************
2010 * WINPOS_FindDeskTopXWindow
2012 * Find the actual X window which needs be restacked.
2013 * Used by WINPOS_SetXWindowPos().
2015 static Window WINPOS_FindDeskTopXWindow( WND *wndPtr )
2017 if (!(wndPtr->flags & WIN_MANAGED))
2018 return wndPtr->window;
2021 Window window, root, parent, *children;
2023 window = wndPtr->window;
2026 TSXQueryTree( display, window, &root, &parent,
2027 &children, &nchildren );
2028 TSXFree( children );
2036 /***********************************************************************
2037 * WINPOS_SetXWindowPos
2039 * SetWindowPos() for an X window. Used by the real SetWindowPos().
2041 static void WINPOS_SetXWindowPos( const WINDOWPOS32 *winpos )
2043 XWindowChanges winChanges;
2045 WND *wndPtr = WIN_FindWndPtr( winpos->hwnd );
2047 if (!(winpos->flags & SWP_NOSIZE))
2049 winChanges.width = winpos->cx;
2050 winChanges.height = winpos->cy;
2051 changeMask |= CWWidth | CWHeight;
2053 /* Tweak dialog window size hints */
2055 if ((wndPtr->flags & WIN_MANAGED) &&
2056 (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME))
2058 XSizeHints *size_hints = TSXAllocSizeHints();
2062 long supplied_return;
2064 TSXGetWMSizeHints( display, wndPtr->window, size_hints,
2065 &supplied_return, XA_WM_NORMAL_HINTS);
2066 size_hints->min_width = size_hints->max_width = winpos->cx;
2067 size_hints->min_height = size_hints->max_height = winpos->cy;
2068 TSXSetWMSizeHints( display, wndPtr->window, size_hints,
2069 XA_WM_NORMAL_HINTS );
2070 TSXFree(size_hints);
2074 if (!(winpos->flags & SWP_NOMOVE))
2076 winChanges.x = winpos->x;
2077 winChanges.y = winpos->y;
2078 changeMask |= CWX | CWY;
2080 if (!(winpos->flags & SWP_NOZORDER))
2082 winChanges.stack_mode = Below;
2083 changeMask |= CWStackMode;
2085 if (winpos->hwndInsertAfter == HWND_TOP) winChanges.stack_mode = Above;
2086 else if (winpos->hwndInsertAfter != HWND_BOTTOM)
2088 WND* insertPtr = WIN_FindWndPtr( winpos->hwndInsertAfter );
2091 stack[0] = WINPOS_FindDeskTopXWindow( insertPtr );
2092 stack[1] = WINPOS_FindDeskTopXWindow( wndPtr );
2094 /* for stupid window managers (i.e. all of them) */
2096 TSXRestackWindows(display, stack, 2);
2097 changeMask &= ~CWStackMode;
2100 if (!changeMask) return;
2102 TSXReconfigureWMWindow( display, wndPtr->window, 0, changeMask, &winChanges );
2106 /***********************************************************************
2107 * SetWindowPos (USER.232)
2109 BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
2110 INT16 x, INT16 y, INT16 cx, INT16 cy, WORD flags)
2112 return SetWindowPos32(hwnd,(INT32)(INT16)hwndInsertAfter,x,y,cx,cy,flags);
2115 /***********************************************************************
2116 * SetWindowPos (USER32.520)
2118 BOOL32 WINAPI SetWindowPos32( HWND32 hwnd, HWND32 hwndInsertAfter,
2119 INT32 x, INT32 y, INT32 cx, INT32 cy, WORD flags)
2123 RECT32 newWindowRect, newClientRect, oldWindowRect;
2125 HWND32 tempInsertAfter= 0;
2128 BOOL32 resync = FALSE;
2130 TRACE(win,"hwnd %04x, (%i,%i)-(%i,%i) flags %08x\n",
2131 hwnd, x, y, x+cx, y+cy, flags);
2132 /* Check window handle */
2134 if (hwnd == GetDesktopWindow32()) return FALSE;
2135 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2137 if(wndPtr->dwStyle & WS_VISIBLE)
2138 flags &= ~SWP_SHOWWINDOW;
2141 uFlags |= SMC_NOPARENTERASE;
2142 flags &= ~SWP_HIDEWINDOW;
2143 if (!(flags & SWP_SHOWWINDOW)) flags |= SWP_NOREDRAW;
2146 /* Check for windows that may not be resized
2147 FIXME: this should be done only for Windows 3.0 programs
2148 if (flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW ) )
2149 flags |= SWP_NOSIZE | SWP_NOMOVE;
2151 /* Check dimensions */
2153 if (cx <= 0) cx = 1;
2154 if (cy <= 0) cy = 1;
2158 if (hwnd == hwndActive) flags |= SWP_NOACTIVATE; /* Already active */
2159 if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
2160 (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
2161 flags |= SWP_NOSIZE; /* Already the right size */
2162 if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
2163 flags |= SWP_NOMOVE; /* Already the right position */
2165 /* Check hwndInsertAfter */
2167 if (!(flags & (SWP_NOZORDER | SWP_NOACTIVATE)))
2169 /* Ignore TOPMOST flags when activating a window */
2170 /* _and_ moving it in Z order. */
2171 if ((hwndInsertAfter == HWND_TOPMOST) ||
2172 (hwndInsertAfter == HWND_NOTOPMOST))
2173 hwndInsertAfter = HWND_TOP;
2175 /* TOPMOST not supported yet */
2176 if ((hwndInsertAfter == HWND_TOPMOST) ||
2177 (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
2179 /* hwndInsertAfter must be a sibling of the window */
2180 if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
2182 WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
2185 if( wnd->parent != wndPtr->parent ) return FALSE;
2186 if( wnd->next == wndPtr ) flags |= SWP_NOZORDER;
2189 else if (!(wndPtr->window))
2190 /* FIXME: the following optimization is no good for "X-ed" windows */
2191 if (hwndInsertAfter == HWND_TOP)
2192 flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
2193 else /* HWND_BOTTOM */
2194 flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
2196 /* Fill the WINDOWPOS structure */
2199 winpos.hwndInsertAfter = hwndInsertAfter;
2204 winpos.flags = flags;
2206 /* Send WM_WINDOWPOSCHANGING message */
2208 if (!(winpos.flags & SWP_NOSENDCHANGING))
2209 SendMessage32A( hwnd, WM_WINDOWPOSCHANGING, 0, (LPARAM)&winpos );
2211 /* Calculate new position and size */
2213 newWindowRect = wndPtr->rectWindow;
2214 newClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
2215 : wndPtr->rectClient;
2217 if (!(winpos.flags & SWP_NOSIZE))
2219 newWindowRect.right = newWindowRect.left + winpos.cx;
2220 newWindowRect.bottom = newWindowRect.top + winpos.cy;
2222 if (!(winpos.flags & SWP_NOMOVE))
2224 newWindowRect.left = winpos.x;
2225 newWindowRect.top = winpos.y;
2226 newWindowRect.right += winpos.x - wndPtr->rectWindow.left;
2227 newWindowRect.bottom += winpos.y - wndPtr->rectWindow.top;
2229 OffsetRect32( &newClientRect, winpos.x - wndPtr->rectWindow.left,
2230 winpos.y - wndPtr->rectWindow.top );
2233 winpos.flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
2235 /* Reposition window in Z order */
2237 if (!(winpos.flags & SWP_NOZORDER))
2239 /* reorder owned popups if hwnd is top-level window
2241 if( wndPtr->parent == WIN_GetDesktop() )
2242 hwndInsertAfter = WINPOS_ReorderOwnedPopups( hwndInsertAfter,
2243 wndPtr, winpos.flags );
2247 WIN_UnlinkWindow( winpos.hwnd );
2248 WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
2250 else WINPOS_MoveWindowZOrder( winpos.hwnd, hwndInsertAfter );
2253 if ( !wndPtr->window && !(winpos.flags & SWP_NOREDRAW) &&
2254 ((winpos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED))
2255 != (SWP_NOMOVE | SWP_NOSIZE)) )
2256 visRgn = DCE_GetVisRgn(hwnd, DCX_WINDOW | DCX_CLIPSIBLINGS);
2259 /* Send WM_NCCALCSIZE message to get new client area */
2260 if( (winpos.flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
2262 result = WINPOS_SendNCCalcSize( winpos.hwnd, TRUE, &newWindowRect,
2263 &wndPtr->rectWindow, &wndPtr->rectClient,
2264 &winpos, &newClientRect );
2266 /* FIXME: WVR_ALIGNxxx */
2268 if( newClientRect.left != wndPtr->rectClient.left ||
2269 newClientRect.top != wndPtr->rectClient.top )
2270 winpos.flags &= ~SWP_NOCLIENTMOVE;
2272 if( (newClientRect.right - newClientRect.left !=
2273 wndPtr->rectClient.right - wndPtr->rectClient.left) ||
2274 (newClientRect.bottom - newClientRect.top !=
2275 wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
2276 winpos.flags &= ~SWP_NOCLIENTSIZE;
2279 if( !(flags & SWP_NOMOVE) && (newClientRect.left != wndPtr->rectClient.left ||
2280 newClientRect.top != wndPtr->rectClient.top) )
2281 winpos.flags &= ~SWP_NOCLIENTMOVE;
2283 /* Update active DCEs
2284 * TODO: Optimize conditions that trigger DCE update.
2287 if( (((winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) &&
2288 wndPtr->dwStyle & WS_VISIBLE) ||
2289 (flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
2293 UnionRect32(&rect, &newWindowRect, &wndPtr->rectWindow);
2294 DCE_InvalidateDCE(wndPtr, &rect);
2297 /* change geometry */
2299 oldWindowRect = wndPtr->rectWindow;
2303 RECT32 oldClientRect = wndPtr->rectClient;
2305 tempInsertAfter = winpos.hwndInsertAfter;
2307 winpos.hwndInsertAfter = hwndInsertAfter;
2309 /* postpone geometry change */
2311 if( !(flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW)) )
2313 WINPOS_SetXWindowPos( &winpos );
2314 winpos.hwndInsertAfter = tempInsertAfter;
2316 else uFlags |= SMC_SETXPOS;
2318 wndPtr->rectWindow = newWindowRect;
2319 wndPtr->rectClient = newClientRect;
2321 if( !(flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW)) )
2322 if( (oldClientRect.left - oldWindowRect.left !=
2323 newClientRect.left - newWindowRect.left) ||
2324 (oldClientRect.top - oldWindowRect.top !=
2325 newClientRect.top - newWindowRect.top) ||
2326 (winpos.flags & SWP_NOCOPYBITS) )
2328 /* if the client area moved as a result of WM_NCCALCSIZE returning
2329 * obscure WVR_ALIGNxxx flags then we simply redraw the whole thing
2331 * TODO: use WINPOS_SizeMoveClean() if there is no SWP_NOCOPYBITS
2334 PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, 0, RDW_INVALIDATE |
2335 RDW_ALLCHILDREN | RDW_FRAME | RDW_ERASE, 0 );
2338 if( winpos.flags & SWP_FRAMECHANGED )
2343 if( newClientRect.right > oldClientRect.right ) /* redraw exposed client area on the right */
2345 rect.top = 0; rect.bottom = newClientRect.bottom - newClientRect.top;
2346 rect.left = oldClientRect.right - newClientRect.left;
2347 rect.right = newClientRect.right - newClientRect.left;
2349 PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, 0,
2350 RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW | RDW_ALLCHILDREN, 0 );
2352 if( newClientRect.bottom > oldClientRect.bottom ) /* redraw exposed client area on the bottom */
2354 rect.left = 0; rect.right = ((wErase)?oldClientRect.right:newClientRect.right) - newClientRect.left;
2355 rect.top = oldClientRect.bottom - newClientRect.top;
2356 rect.bottom = newClientRect.bottom - newClientRect.top;
2358 PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, 0,
2359 RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW | RDW_ALLCHILDREN, 0 );
2361 if( !wErase ) /* just update the nonclient area */
2362 wndPtr->flags |= WIN_NEEDS_NCPAINT;
2364 uFlags |= SMC_NOPARENTERASE; /* X windows do not have eraseable parents */
2366 else /* not an X window */
2368 RECT32 oldClientRect = wndPtr->rectClient;
2370 wndPtr->rectWindow = newWindowRect;
2371 wndPtr->rectClient = newClientRect;
2373 if( oldClientRect.bottom - oldClientRect.top ==
2374 newClientRect.bottom - newClientRect.top ) result &= ~WVR_VREDRAW;
2376 if( oldClientRect.right - oldClientRect.left ==
2377 newClientRect.right - newClientRect.left ) result &= ~WVR_HREDRAW;
2379 if( !(flags & (SWP_NOREDRAW | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
2381 uFlags |= ((winpos.flags & SWP_NOCOPYBITS) ||
2382 (result >= WVR_HREDRAW && result < WVR_VALIDRECTS)) ? SMC_NOCOPY : 0;
2383 uFlags |= (winpos.flags & SWP_FRAMECHANGED) ? SMC_DRAWFRAME : 0;
2385 if( (winpos.flags & SWP_AGG_NOGEOMETRYCHANGE) != SWP_AGG_NOGEOMETRYCHANGE )
2386 uFlags = WINPOS_SizeMoveClean(wndPtr, visRgn, &oldWindowRect,
2387 &oldClientRect, uFlags);
2390 /* adjust the frame and do not erase the parent */
2392 if( winpos.flags & SWP_FRAMECHANGED ) wndPtr->flags |= WIN_NEEDS_NCPAINT;
2393 if( winpos.flags & SWP_NOZORDER ) uFlags |= SMC_NOPARENTERASE;
2396 DeleteObject32(visRgn);
2399 if (flags & SWP_SHOWWINDOW)
2401 wndPtr->dwStyle |= WS_VISIBLE;
2406 if( uFlags & SMC_SETXPOS )
2408 WINPOS_SetXWindowPos( &winpos );
2409 winpos.hwndInsertAfter = tempInsertAfter;
2411 TSXMapWindow( display, wndPtr->window );
2412 if (wndPtr->flags & WIN_MANAGED) resync = TRUE;
2414 /* If focus was set to an unmapped window, reset X focus now */
2415 focus = curr = GetFocus32();
2419 SetFocus32( focus );
2422 curr = GetParent32(curr);
2427 if (!(flags & SWP_NOREDRAW))
2428 PAINT_RedrawWindow( winpos.hwnd, NULL, 0,
2429 RDW_INVALIDATE | RDW_ALLCHILDREN |
2430 RDW_FRAME | RDW_ERASENOW | RDW_ERASE, 0 );
2433 else if (flags & SWP_HIDEWINDOW)
2435 wndPtr->dwStyle &= ~WS_VISIBLE;
2438 TSXUnmapWindow( display, wndPtr->window );
2439 if( uFlags & SMC_SETXPOS )
2441 WINPOS_SetXWindowPos( &winpos );
2442 winpos.hwndInsertAfter = tempInsertAfter;
2447 if (!(flags & SWP_NOREDRAW))
2448 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, &oldWindowRect,
2449 0, RDW_INVALIDATE | RDW_ALLCHILDREN |
2450 RDW_ERASE | RDW_ERASENOW, 0 );
2451 uFlags |= SMC_NOPARENTERASE;
2454 if ((winpos.hwnd == GetFocus32()) ||
2455 IsChild32( winpos.hwnd, GetFocus32()))
2457 /* Revert focus to parent */
2458 SetFocus32( GetParent32(winpos.hwnd) );
2460 if (hwnd == CARET_GetHwnd()) DestroyCaret32();
2462 if (winpos.hwnd == hwndActive)
2463 WINPOS_ActivateOtherWindow( wndPtr );
2466 /* Activate the window */
2468 if (!(flags & SWP_NOACTIVATE))
2469 WINPOS_ChangeActiveWindow( winpos.hwnd, FALSE );
2471 /* Repaint the window */
2473 if (wndPtr->window) EVENT_Synchronize(); /* Wait for all expose events */
2475 if (!GetCapture32())
2476 EVENT_DummyMotionNotify(); /* Simulate a mouse event to set the cursor */
2478 if (!(flags & SWP_DEFERERASE) && !(uFlags & SMC_NOPARENTERASE) )
2479 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0, RDW_ALLCHILDREN | RDW_ERASENOW, 0 );
2480 else if( wndPtr->parent == WIN_GetDesktop() && wndPtr->parent->flags & WIN_NEEDS_ERASEBKGND )
2481 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0, RDW_NOCHILDREN | RDW_ERASENOW, 0 );
2483 /* And last, send the WM_WINDOWPOSCHANGED message */
2485 TRACE(win,"\tstatus flags = %04x\n", winpos.flags & SWP_AGG_STATUSFLAGS);
2488 (((winpos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) &&
2489 !(winpos.flags & SWP_NOSENDCHANGING)) )
2491 SendMessage32A( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
2492 if (resync) EVENT_Synchronize ();
2499 /***********************************************************************
2500 * BeginDeferWindowPos16 (USER.259)
2502 HDWP16 WINAPI BeginDeferWindowPos16( INT16 count )
2504 return BeginDeferWindowPos32( count );
2508 /***********************************************************************
2509 * BeginDeferWindowPos32 (USER32.9)
2511 HDWP32 WINAPI BeginDeferWindowPos32( INT32 count )
2516 if (count <= 0) return 0;
2517 handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS32) );
2518 if (!handle) return 0;
2519 pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
2520 pDWP->actualCount = 0;
2521 pDWP->suggestedCount = count;
2523 pDWP->wMagic = DWP_MAGIC;
2524 pDWP->hwndParent = 0;
2529 /***********************************************************************
2530 * DeferWindowPos16 (USER.260)
2532 HDWP16 WINAPI DeferWindowPos16( HDWP16 hdwp, HWND16 hwnd, HWND16 hwndAfter,
2533 INT16 x, INT16 y, INT16 cx, INT16 cy,
2536 return DeferWindowPos32( hdwp, hwnd, (INT32)(INT16)hwndAfter,
2537 x, y, cx, cy, flags );
2541 /***********************************************************************
2542 * DeferWindowPos32 (USER32.128)
2544 HDWP32 WINAPI DeferWindowPos32( HDWP32 hdwp, HWND32 hwnd, HWND32 hwndAfter,
2545 INT32 x, INT32 y, INT32 cx, INT32 cy,
2550 HDWP32 newhdwp = hdwp;
2551 /* HWND32 parent; */
2554 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
2555 if (!pDWP) return 0;
2556 if (hwnd == GetDesktopWindow32()) return 0;
2558 if (!(pWnd=WIN_FindWndPtr( hwnd ))) {
2559 USER_HEAP_FREE( hdwp );
2563 /* Numega Bounds Checker Demo dislikes the following code.
2564 In fact, I've not been able to find any "same parent" requirement in any docu
2568 /* All the windows of a DeferWindowPos() must have the same parent */
2569 parent = pWnd->parent->hwndSelf;
2570 if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
2571 else if (parent != pDWP->hwndParent)
2573 USER_HEAP_FREE( hdwp );
2578 for (i = 0; i < pDWP->actualCount; i++)
2580 if (pDWP->winPos[i].hwnd == hwnd)
2582 /* Merge with the other changes */
2583 if (!(flags & SWP_NOZORDER))
2585 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
2587 if (!(flags & SWP_NOMOVE))
2589 pDWP->winPos[i].x = x;
2590 pDWP->winPos[i].y = y;
2592 if (!(flags & SWP_NOSIZE))
2594 pDWP->winPos[i].cx = cx;
2595 pDWP->winPos[i].cy = cy;
2597 pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
2598 SWP_NOZORDER | SWP_NOREDRAW |
2599 SWP_NOACTIVATE | SWP_NOCOPYBITS|
2601 pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
2606 if (pDWP->actualCount >= pDWP->suggestedCount)
2608 newhdwp = USER_HEAP_REALLOC( hdwp,
2609 sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS32) );
2610 if (!newhdwp) return 0;
2611 pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
2612 pDWP->suggestedCount++;
2614 pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
2615 pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
2616 pDWP->winPos[pDWP->actualCount].x = x;
2617 pDWP->winPos[pDWP->actualCount].y = y;
2618 pDWP->winPos[pDWP->actualCount].cx = cx;
2619 pDWP->winPos[pDWP->actualCount].cy = cy;
2620 pDWP->winPos[pDWP->actualCount].flags = flags;
2621 pDWP->actualCount++;
2626 /***********************************************************************
2627 * EndDeferWindowPos16 (USER.261)
2629 BOOL16 WINAPI EndDeferWindowPos16( HDWP16 hdwp )
2631 return EndDeferWindowPos32( hdwp );
2635 /***********************************************************************
2636 * EndDeferWindowPos32 (USER32.173)
2638 BOOL32 WINAPI EndDeferWindowPos32( HDWP32 hdwp )
2641 WINDOWPOS32 *winpos;
2645 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
2646 if (!pDWP) return FALSE;
2647 for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
2649 if (!(res = SetWindowPos32( winpos->hwnd, winpos->hwndInsertAfter,
2650 winpos->x, winpos->y, winpos->cx,
2651 winpos->cy, winpos->flags ))) break;
2653 USER_HEAP_FREE( hdwp );
2658 /***********************************************************************
2659 * TileChildWindows (USER.199)
2661 void WINAPI TileChildWindows( HWND16 parent, WORD action )
2663 FIXME(win, "(%04x, %d): stub\n", parent, action);
2666 /***********************************************************************
2667 * CascageChildWindows (USER.198)
2669 void WINAPI CascadeChildWindows( HWND16 parent, WORD action )
2671 FIXME(win, "(%04x, %d): stub\n", parent, action);