2 * Window position related functions.
4 * Copyright 1993, 1994, 1995 Alexandre Julliard
5 * 1995, 1996 Alex Korobka
10 #include <X11/Xatom.h>
11 #include "sysmetrics.h"
22 #include "nonclient.h"
24 /* #define DEBUG_WIN */
27 #define HAS_DLGFRAME(style,exStyle) \
28 (((exStyle) & WS_EX_DLGMODALFRAME) || \
29 (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
31 #define HAS_THICKFRAME(style) \
32 (((style) & WS_THICKFRAME) && \
33 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
35 #define SWP_AGG_NOGEOMETRYCHANGE \
36 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
37 #define SWP_AGG_NOPOSCHANGE \
38 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
39 #define SWP_AGG_STATUSFLAGS \
40 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
42 #define EMPTYPOINT(pt) ((*(LONG*)&(pt)) == -1)
44 #define PLACE_MIN 0x0001
45 #define PLACE_MAX 0x0002
46 #define PLACE_RECT 0x0004
48 #define SMC_NOCOPY 0x0001
49 #define SMC_NOPARENTERASE 0x0002
50 #define SMC_DRAWFRAME 0x0004
51 #define SMC_SETXPOS 0x0008
53 /* ----- external functions ----- */
55 extern void FOCUS_SwitchFocus( HWND32 , HWND32 );
56 extern HWND32 CARET_GetHwnd();
58 /* ----- internal variables ----- */
60 static HWND32 hwndActive = 0; /* Currently active window */
61 static HWND32 hwndPrevActive = 0; /* Previously active window */
63 static LPCSTR atomInternalPos;
65 extern MESSAGEQUEUE* pActiveQueue;
67 /***********************************************************************
68 * WINPOS_CreateInternalPosAtom
70 BOOL32 WINPOS_CreateInternalPosAtom()
73 atomInternalPos = (LPCSTR)(DWORD)GlobalAddAtom32A(str);
74 return (atomInternalPos) ? TRUE : FALSE;
77 /***********************************************************************
78 * WINPOS_CheckInternalPos
80 * Called when a window is destroyed.
82 void WINPOS_CheckInternalPos( HWND32 hwnd )
84 LPINTERNALPOS lpPos = (LPINTERNALPOS) GetProp32A( hwnd, atomInternalPos );
86 if( hwnd == hwndPrevActive ) hwndPrevActive = 0;
87 if( hwnd == hwndActive )
90 dprintf_win(stddeb,"\tattempt to activate destroyed window!\n");
95 if( IsWindow32(lpPos->hwndIconTitle) )
96 DestroyWindow32( lpPos->hwndIconTitle );
97 HeapFree( SystemHeap, 0, lpPos );
101 /***********************************************************************
104 * Find a suitable place for an iconic window.
106 static POINT16 WINPOS_FindIconPos( WND* wndPtr, POINT16 pt )
109 short x, y, xspacing, yspacing;
111 GetClientRect16( wndPtr->parent->hwndSelf, &rectParent );
112 if ((pt.x >= rectParent.left) && (pt.x + SYSMETRICS_CXICON < rectParent.right) &&
113 (pt.y >= rectParent.top) && (pt.y + SYSMETRICS_CYICON < rectParent.bottom))
114 return pt; /* The icon already has a suitable position */
116 xspacing = SYSMETRICS_CXICONSPACING;
117 yspacing = SYSMETRICS_CYICONSPACING;
119 y = rectParent.bottom;
122 for (x = rectParent.left; x <= rectParent.right-xspacing; x += xspacing)
124 /* Check if another icon already occupies this spot */
125 WND *childPtr = wndPtr->parent->child;
128 if ((childPtr->dwStyle & WS_MINIMIZE) && (childPtr != wndPtr))
130 if ((childPtr->rectWindow.left < x + xspacing) &&
131 (childPtr->rectWindow.right >= x) &&
132 (childPtr->rectWindow.top <= y) &&
133 (childPtr->rectWindow.bottom > y - yspacing))
134 break; /* There's a window in there */
136 childPtr = childPtr->next;
138 if (!childPtr) /* No window was found, so it's OK for us */
140 pt.x = x + (xspacing - SYSMETRICS_CXICON) / 2;
141 pt.y = y - (yspacing + SYSMETRICS_CYICON) / 2;
150 /***********************************************************************
151 * ArrangeIconicWindows16 (USER.170)
153 UINT16 WINAPI ArrangeIconicWindows16( HWND16 parent)
155 return ArrangeIconicWindows32(parent);
157 /***********************************************************************
158 * ArrangeIconicWindows32 (USER32.6)
160 UINT32 WINAPI ArrangeIconicWindows32( HWND32 parent )
164 INT32 x, y, xspacing, yspacing;
166 GetClientRect32( parent, &rectParent );
168 y = rectParent.bottom;
169 xspacing = SYSMETRICS_CXICONSPACING;
170 yspacing = SYSMETRICS_CYICONSPACING;
172 hwndChild = GetWindow32( parent, GW_CHILD );
175 if( IsIconic32( hwndChild ) )
177 WINPOS_ShowIconTitle( WIN_FindWndPtr(hwndChild), FALSE );
178 SetWindowPos32( hwndChild, 0, x + (xspacing - SYSMETRICS_CXICON) / 2,
179 y - yspacing - SYSMETRICS_CYICON/2, 0, 0,
180 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
181 if( IsWindow32(hwndChild) )
182 WINPOS_ShowIconTitle( WIN_FindWndPtr(hwndChild), TRUE );
183 if (x <= rectParent.right - xspacing) x += xspacing;
190 hwndChild = GetWindow32( hwndChild, GW_HWNDNEXT );
196 /***********************************************************************
197 * SwitchToThisWindow16 (USER.172)
199 void WINAPI SwitchToThisWindow16( HWND16 hwnd, BOOL16 restore )
201 SwitchToThisWindow32( hwnd, restore );
205 /***********************************************************************
206 * SwitchToThisWindow32 (USER32.538)
208 void WINAPI SwitchToThisWindow32( HWND32 hwnd, BOOL32 restore )
210 ShowWindow32( hwnd, restore ? SW_RESTORE : SW_SHOWMINIMIZED );
214 /***********************************************************************
215 * GetWindowRect16 (USER.32)
217 void WINAPI GetWindowRect16( HWND16 hwnd, LPRECT16 rect )
219 WND * wndPtr = WIN_FindWndPtr( hwnd );
222 CONV_RECT32TO16( &wndPtr->rectWindow, rect );
223 if (wndPtr->dwStyle & WS_CHILD)
224 MapWindowPoints16( wndPtr->parent->hwndSelf, 0, (POINT16 *)rect, 2 );
228 /***********************************************************************
229 * GetWindowRect32 (USER.32)
231 void WINAPI GetWindowRect32( HWND32 hwnd, LPRECT32 rect )
233 WND * wndPtr = WIN_FindWndPtr( hwnd );
236 *rect = wndPtr->rectWindow;
237 if (wndPtr->dwStyle & WS_CHILD)
238 MapWindowPoints32( wndPtr->parent->hwndSelf, 0, (POINT32 *)rect, 2 );
242 /***********************************************************************
243 * GetClientRect16 (USER.33)
245 void WINAPI GetClientRect16( HWND16 hwnd, LPRECT16 rect )
247 WND * wndPtr = WIN_FindWndPtr( hwnd );
249 rect->left = rect->top = rect->right = rect->bottom = 0;
252 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
253 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
258 /***********************************************************************
259 * GetClientRect32 (USER32.219)
261 void WINAPI GetClientRect32( HWND32 hwnd, LPRECT32 rect )
263 WND * wndPtr = WIN_FindWndPtr( hwnd );
265 rect->left = rect->top = rect->right = rect->bottom = 0;
268 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
269 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
274 /*******************************************************************
275 * ClientToScreen16 (USER.28)
277 void WINAPI ClientToScreen16( HWND16 hwnd, LPPOINT16 lppnt )
279 MapWindowPoints16( hwnd, 0, lppnt, 1 );
283 /*******************************************************************
284 * ClientToScreen32 (USER32.51)
286 BOOL32 WINAPI ClientToScreen32( HWND32 hwnd, LPPOINT32 lppnt )
288 MapWindowPoints32( hwnd, 0, lppnt, 1 );
293 /*******************************************************************
294 * ScreenToClient16 (USER.29)
296 void WINAPI ScreenToClient16( HWND16 hwnd, LPPOINT16 lppnt )
298 MapWindowPoints16( 0, hwnd, lppnt, 1 );
302 /*******************************************************************
303 * ScreenToClient32 (USER32.446)
305 void WINAPI ScreenToClient32( HWND32 hwnd, LPPOINT32 lppnt )
307 MapWindowPoints32( 0, hwnd, lppnt, 1 );
311 /***********************************************************************
312 * WINPOS_WindowFromPoint
314 * Find the window and hittest for a given point.
316 INT16 WINPOS_WindowFromPoint( WND* wndScope, POINT16 pt, WND **ppWnd )
319 INT16 hittest = HTERROR;
323 wndPtr = wndScope->child;
324 MapWindowPoints16( GetDesktopWindow16(), wndScope->hwndSelf, &xy, 1 );
330 /* If point is in window, and window is visible, and it */
331 /* is enabled (or it's a top-level window), then explore */
332 /* its children. Otherwise, go to the next window. */
334 if ((wndPtr->dwStyle & WS_VISIBLE) &&
335 (!(wndPtr->dwStyle & WS_DISABLED) ||
336 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)) &&
337 (xy.x >= wndPtr->rectWindow.left) &&
338 (xy.x < wndPtr->rectWindow.right) &&
339 (xy.y >= wndPtr->rectWindow.top) &&
340 (xy.y < wndPtr->rectWindow.bottom))
342 *ppWnd = wndPtr; /* Got a suitable window */
344 /* If window is minimized or disabled, return at once */
345 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
346 if (wndPtr->dwStyle & WS_DISABLED) return HTERROR;
348 /* If point is not in client area, ignore the children */
349 if ((xy.x < wndPtr->rectClient.left) ||
350 (xy.x >= wndPtr->rectClient.right) ||
351 (xy.y < wndPtr->rectClient.top) ||
352 (xy.y >= wndPtr->rectClient.bottom)) break;
354 xy.x -= wndPtr->rectClient.left;
355 xy.y -= wndPtr->rectClient.top;
356 wndPtr = wndPtr->child;
358 else wndPtr = wndPtr->next;
361 /* If nothing found, try the scope window */
362 if (!*ppWnd) *ppWnd = wndScope;
364 /* Send the WM_NCHITTEST message (only if to the same task) */
365 if ((*ppWnd)->hmemTaskQ == GetTaskQueue(0))
367 hittest = (INT16)SendMessage16( (*ppWnd)->hwndSelf, WM_NCHITTEST,
368 0, MAKELONG( pt.x, pt.y ) );
369 if (hittest != HTTRANSPARENT) return hittest; /* Found the window */
371 else return HTCLIENT;
373 /* If no children found in last search, make point relative to parent */
376 xy.x += (*ppWnd)->rectClient.left;
377 xy.y += (*ppWnd)->rectClient.top;
380 /* Restart the search from the next sibling */
381 wndPtr = (*ppWnd)->next;
382 *ppWnd = (*ppWnd)->parent;
387 /*******************************************************************
388 * WindowFromPoint16 (USER.30)
390 HWND16 WINAPI WindowFromPoint16( POINT16 pt )
393 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt, &pWnd );
394 return pWnd->hwndSelf;
398 /*******************************************************************
399 * WindowFromPoint32 (USER32.581)
401 HWND32 WINAPI WindowFromPoint32( POINT32 pt )
405 CONV_POINT32TO16( &pt, &pt16 );
406 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16, &pWnd );
407 return (HWND32)pWnd->hwndSelf;
411 /*******************************************************************
412 * ChildWindowFromPoint16 (USER.191)
414 HWND16 WINAPI ChildWindowFromPoint16( HWND16 hwndParent, POINT16 pt )
417 CONV_POINT16TO32( &pt, &pt32 );
418 return (HWND16)ChildWindowFromPoint32( hwndParent, pt32 );
422 /*******************************************************************
423 * ChildWindowFromPoint32 (USER32.48)
425 HWND32 WINAPI ChildWindowFromPoint32( HWND32 hwndParent, POINT32 pt )
427 /* pt is in the client coordinates */
429 WND* wnd = WIN_FindWndPtr(hwndParent);
434 /* get client rect fast */
435 rect.top = rect.left = 0;
436 rect.right = wnd->rectClient.right - wnd->rectClient.left;
437 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
439 if (!PtInRect32( &rect, pt )) return 0;
444 if (PtInRect32( &wnd->rectWindow, pt )) return wnd->hwndSelf;
451 /*******************************************************************
452 * WINPOS_GetWinOffset
454 * Calculate the offset between the origin of the two windows. Used
455 * to implement MapWindowPoints.
457 static void WINPOS_GetWinOffset( HWND32 hwndFrom, HWND32 hwndTo,
462 offset->x = offset->y = 0;
463 if (hwndFrom == hwndTo ) return;
465 /* Translate source window origin to screen coords */
468 if (!(wndPtr = WIN_FindWndPtr( hwndFrom )))
470 fprintf(stderr,"MapWindowPoints: bad hwndFrom = %04x\n",hwndFrom);
473 while (wndPtr->parent)
475 offset->x += wndPtr->rectClient.left;
476 offset->y += wndPtr->rectClient.top;
477 wndPtr = wndPtr->parent;
481 /* Translate origin to destination window coords */
484 if (!(wndPtr = WIN_FindWndPtr( hwndTo )))
486 fprintf(stderr,"MapWindowPoints: bad hwndTo = %04x\n", hwndTo );
489 while (wndPtr->parent)
491 offset->x -= wndPtr->rectClient.left;
492 offset->y -= wndPtr->rectClient.top;
493 wndPtr = wndPtr->parent;
499 /*******************************************************************
500 * MapWindowPoints16 (USER.258)
502 void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
503 LPPOINT16 lppt, UINT16 count )
507 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
517 /*******************************************************************
518 * MapWindowPoints32 (USER32.385)
520 void WINAPI MapWindowPoints32( HWND32 hwndFrom, HWND32 hwndTo,
521 LPPOINT32 lppt, UINT32 count )
525 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
535 /***********************************************************************
536 * IsIconic16 (USER.31)
538 BOOL16 WINAPI IsIconic16(HWND16 hWnd)
540 return IsIconic32(hWnd);
544 /***********************************************************************
545 * IsIconic32 (USER32.344)
547 BOOL32 WINAPI IsIconic32(HWND32 hWnd)
549 WND * wndPtr = WIN_FindWndPtr(hWnd);
550 if (wndPtr == NULL) return FALSE;
551 return (wndPtr->dwStyle & WS_MINIMIZE) != 0;
555 /***********************************************************************
556 * IsZoomed (USER.272)
558 BOOL16 WINAPI IsZoomed16(HWND16 hWnd)
560 return IsZoomed32(hWnd);
564 /***********************************************************************
565 * IsZoomed (USER32.351)
567 BOOL32 WINAPI IsZoomed32(HWND32 hWnd)
569 WND * wndPtr = WIN_FindWndPtr(hWnd);
570 if (wndPtr == NULL) return FALSE;
571 return (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
575 /*******************************************************************
576 * GetActiveWindow (USER.60)
578 HWND16 WINAPI GetActiveWindow16(void)
580 return (HWND16)hwndActive;
583 /*******************************************************************
584 * GetActiveWindow (USER32.204)
586 HWND32 WINAPI GetActiveWindow32(void)
588 return (HWND32)hwndActive;
592 /*******************************************************************
595 static BOOL32 WINPOS_CanActivate(WND* pWnd)
597 if( pWnd && ((pWnd->dwStyle & (WS_DISABLED | WS_VISIBLE | WS_CHILD))
598 == WS_VISIBLE) ) return TRUE;
603 /*******************************************************************
604 * SetActiveWindow16 (USER.59)
606 HWND16 WINAPI SetActiveWindow16( HWND16 hwnd )
608 return SetActiveWindow32(hwnd);
612 /*******************************************************************
613 * SetActiveWindow32 (USER32.462)
615 HWND32 WINAPI SetActiveWindow32( HWND32 hwnd )
617 HWND32 prev = hwndActive;
618 WND *wndPtr = WIN_FindWndPtr( hwnd );
620 if ( !WINPOS_CanActivate(wndPtr) ) return 0;
622 WINPOS_SetActiveWindow( hwnd, 0, 0 );
627 /***********************************************************************
628 * BringWindowToTop16 (USER.45)
630 BOOL16 WINAPI BringWindowToTop16( HWND16 hwnd )
632 return BringWindowToTop32(hwnd);
636 /***********************************************************************
637 * BringWindowToTop32 (USER32.10)
639 BOOL32 WINAPI BringWindowToTop32( HWND32 hwnd )
641 return SetWindowPos32( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
645 /***********************************************************************
646 * MoveWindow16 (USER.56)
648 BOOL16 WINAPI MoveWindow16( HWND16 hwnd, INT16 x, INT16 y, INT16 cx, INT16 cy,
651 return MoveWindow32(hwnd,x,y,cx,cy,repaint);
655 /***********************************************************************
656 * MoveWindow32 (USER32.398)
658 BOOL32 WINAPI MoveWindow32( HWND32 hwnd, INT32 x, INT32 y, INT32 cx, INT32 cy,
661 int flags = SWP_NOZORDER | SWP_NOACTIVATE;
662 if (!repaint) flags |= SWP_NOREDRAW;
663 dprintf_win(stddeb, "MoveWindow: %04x %d,%d %dx%d %d\n",
664 hwnd, x, y, cx, cy, repaint );
665 return SetWindowPos32( hwnd, 0, x, y, cx, cy, flags );
668 /***********************************************************************
669 * WINPOS_InitInternalPos
671 static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT32 pt,
672 LPRECT32 restoreRect )
674 LPINTERNALPOS lpPos = (LPINTERNALPOS) GetProp32A( wnd->hwndSelf,
678 /* this happens when the window is minimized/maximized
679 * for the first time (rectWindow is not adjusted yet) */
681 lpPos = HeapAlloc( SystemHeap, 0, sizeof(INTERNALPOS) );
682 if( !lpPos ) return NULL;
684 SetProp32A( wnd->hwndSelf, atomInternalPos, (HANDLE32)lpPos );
685 lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
686 CONV_RECT32TO16( &wnd->rectWindow, &lpPos->rectNormal );
687 *(UINT32*)&lpPos->ptIconPos = *(UINT32*)&lpPos->ptMaxPos = 0xFFFFFFFF;
690 if( wnd->dwStyle & WS_MINIMIZE )
691 CONV_POINT32TO16( &pt, &lpPos->ptIconPos );
692 else if( wnd->dwStyle & WS_MAXIMIZE )
693 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
694 else if( restoreRect )
695 CONV_RECT32TO16( restoreRect, &lpPos->rectNormal );
700 /***********************************************************************
701 * WINPOS_RedrawIconTitle
703 BOOL32 WINPOS_RedrawIconTitle( HWND32 hWnd )
705 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetProp32A( hWnd, atomInternalPos );
708 if( lpPos->hwndIconTitle )
710 SendMessage32A( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
711 InvalidateRect32( lpPos->hwndIconTitle, NULL, TRUE );
718 /***********************************************************************
719 * WINPOS_ShowIconTitle
721 BOOL32 WINPOS_ShowIconTitle( WND* pWnd, BOOL32 bShow )
723 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetProp32A( pWnd->hwndSelf, atomInternalPos );
725 if( lpPos && !(pWnd->flags & WIN_MANAGED))
727 HWND16 hWnd = lpPos->hwndIconTitle;
729 dprintf_win(stddeb,"ShowIconTitle: 0x%04x %i\n", pWnd->hwndSelf, (bShow != 0) );
732 lpPos->hwndIconTitle = hWnd = ICONTITLE_Create( pWnd );
735 pWnd = WIN_FindWndPtr(hWnd);
737 if( !(pWnd->dwStyle & WS_VISIBLE) )
739 SendMessage32A( hWnd, WM_SHOWWINDOW, TRUE, 0 );
740 SetWindowPos32( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
741 SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
744 else ShowWindow32( hWnd, SW_HIDE );
749 /*******************************************************************
750 * WINPOS_GetMinMaxInfo
752 * Get the minimized and maximized information for a window.
754 void WINPOS_GetMinMaxInfo( WND *wndPtr, POINT32 *maxSize, POINT32 *maxPos,
755 POINT32 *minTrack, POINT32 *maxTrack )
761 /* Compute default values */
763 MinMax.ptMaxSize.x = SYSMETRICS_CXSCREEN;
764 MinMax.ptMaxSize.y = SYSMETRICS_CYSCREEN;
765 MinMax.ptMinTrackSize.x = SYSMETRICS_CXMINTRACK;
766 MinMax.ptMinTrackSize.y = SYSMETRICS_CYMINTRACK;
767 MinMax.ptMaxTrackSize.x = SYSMETRICS_CXSCREEN;
768 MinMax.ptMaxTrackSize.y = SYSMETRICS_CYSCREEN;
770 if (wndPtr->flags & WIN_MANAGED) xinc = yinc = 0;
771 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
773 xinc = SYSMETRICS_CXDLGFRAME;
774 yinc = SYSMETRICS_CYDLGFRAME;
779 if (HAS_THICKFRAME(wndPtr->dwStyle))
781 xinc += SYSMETRICS_CXFRAME;
782 yinc += SYSMETRICS_CYFRAME;
784 if (wndPtr->dwStyle & WS_BORDER)
786 xinc += SYSMETRICS_CXBORDER;
787 yinc += SYSMETRICS_CYBORDER;
790 MinMax.ptMaxSize.x += 2 * xinc;
791 MinMax.ptMaxSize.y += 2 * yinc;
793 lpPos = (LPINTERNALPOS)GetProp32A( wndPtr->hwndSelf, atomInternalPos );
794 if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
795 CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
798 MinMax.ptMaxPosition.x = -xinc;
799 MinMax.ptMaxPosition.y = -yinc;
802 SendMessage32A( wndPtr->hwndSelf, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
804 /* Some sanity checks */
806 dprintf_win(stddeb,"GetMinMaxInfo: %d %d / %d %d / %d %d / %d %d\n",
807 MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
808 MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
809 MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
810 MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
811 MinMax.ptMaxTrackSize.x = MAX( MinMax.ptMaxTrackSize.x,
812 MinMax.ptMinTrackSize.x );
813 MinMax.ptMaxTrackSize.y = MAX( MinMax.ptMaxTrackSize.y,
814 MinMax.ptMinTrackSize.y );
816 if (maxSize) *maxSize = MinMax.ptMaxSize;
817 if (maxPos) *maxPos = MinMax.ptMaxPosition;
818 if (minTrack) *minTrack = MinMax.ptMinTrackSize;
819 if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
822 /***********************************************************************
825 * Fill in lpRect and return additional flags to be used with SetWindowPos().
826 * This function assumes that 'cmd' is different from the current window
829 UINT16 WINPOS_MinMaximize( WND* wndPtr, UINT16 cmd, LPRECT16 lpRect )
833 POINT32 size = { wndPtr->rectWindow.left, wndPtr->rectWindow.top };
834 LPINTERNALPOS lpPos = WINPOS_InitInternalPos( wndPtr, size,
835 &wndPtr->rectWindow );
837 dprintf_win(stddeb,"MinMaximize: 0x%04x %u\n", wndPtr->hwndSelf, cmd );
839 if (lpPos && !HOOK_CallHooks16(WH_CBT, HCBT_MINMAX, wndPtr->hwndSelf, cmd))
841 if( wndPtr->dwStyle & WS_MINIMIZE )
843 if( !SendMessage32A( wndPtr->hwndSelf, WM_QUERYOPEN, 0, 0L ) )
844 return (SWP_NOSIZE | SWP_NOMOVE);
845 swpFlags |= SWP_NOCOPYBITS;
850 if( wndPtr->dwStyle & WS_MAXIMIZE)
852 wndPtr->flags |= WIN_RESTORE_MAX;
853 wndPtr->dwStyle &= ~WS_MAXIMIZE;
856 wndPtr->flags &= ~WIN_RESTORE_MAX;
857 wndPtr->dwStyle |= WS_MINIMIZE;
859 lpPos->ptIconPos = WINPOS_FindIconPos( wndPtr, lpPos->ptIconPos );
861 SetRect16( lpRect, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
862 SYSMETRICS_CXICON, SYSMETRICS_CYICON );
863 swpFlags |= SWP_NOCOPYBITS;
867 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
868 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL );
869 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
871 if( wndPtr->dwStyle & WS_MINIMIZE )
873 WINPOS_ShowIconTitle( wndPtr, FALSE );
874 wndPtr->dwStyle &= ~WS_MINIMIZE;
876 wndPtr->dwStyle |= WS_MAXIMIZE;
878 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
883 if( wndPtr->dwStyle & WS_MINIMIZE )
885 wndPtr->dwStyle &= ~WS_MINIMIZE;
886 WINPOS_ShowIconTitle( wndPtr, FALSE );
887 if( wndPtr->flags & WIN_RESTORE_MAX)
889 /* Restore to maximized position */
890 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
891 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL);
892 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
893 wndPtr->dwStyle |= WS_MAXIMIZE;
897 if( !(wndPtr->dwStyle & WS_MAXIMIZE) ) return (UINT16)(-1);
898 else wndPtr->dwStyle &= ~WS_MAXIMIZE;
900 /* Restore to normal position */
902 *lpRect = lpPos->rectNormal;
903 lpRect->right -= lpRect->left;
904 lpRect->bottom -= lpRect->top;
908 } else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
912 /***********************************************************************
913 * ShowWindow16 (USER.42)
915 BOOL16 WINAPI ShowWindow16( HWND16 hwnd, INT16 cmd )
917 return ShowWindow32(hwnd,cmd);
921 /***********************************************************************
922 * ShowWindow32 (USER.42)
924 BOOL32 WINAPI ShowWindow32( HWND32 hwnd, INT32 cmd )
926 WND* wndPtr = WIN_FindWndPtr( hwnd );
927 BOOL32 wasVisible, showFlag;
928 RECT16 newPos = {0, 0, 0, 0};
931 if (!wndPtr) return FALSE;
933 dprintf_win(stddeb,"ShowWindow: hwnd=%04x, cmd=%d\n", hwnd, cmd);
935 wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
940 if (!wasVisible) return FALSE;
941 swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
942 SWP_NOACTIVATE | SWP_NOZORDER;
945 case SW_SHOWMINNOACTIVE:
946 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
948 case SW_SHOWMINIMIZED:
949 swp |= SWP_SHOWWINDOW;
952 swp |= SWP_FRAMECHANGED;
953 if( !(wndPtr->dwStyle & WS_MINIMIZE) )
954 swp |= WINPOS_MinMaximize( wndPtr, SW_MINIMIZE, &newPos );
955 else swp |= SWP_NOSIZE | SWP_NOMOVE;
958 case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
959 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
960 if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
961 swp |= WINPOS_MinMaximize( wndPtr, SW_MAXIMIZE, &newPos );
962 else swp |= SWP_NOSIZE | SWP_NOMOVE;
966 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
969 swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
972 case SW_SHOWNOACTIVATE:
974 if (GetActiveWindow32()) swp |= SWP_NOACTIVATE;
976 case SW_SHOWNORMAL: /* same as SW_NORMAL: */
977 case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
979 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
981 if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) )
982 swp |= WINPOS_MinMaximize( wndPtr, SW_RESTORE, &newPos );
983 else swp |= SWP_NOSIZE | SWP_NOMOVE;
987 showFlag = (cmd != SW_HIDE);
988 if (showFlag != wasVisible)
990 SendMessage32A( hwnd, WM_SHOWWINDOW, showFlag, 0 );
991 if (!IsWindow32( hwnd )) return wasVisible;
994 if ((wndPtr->dwStyle & WS_CHILD) &&
995 !IsWindowVisible32( wndPtr->parent->hwndSelf ) &&
996 (swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE) )
998 /* Don't call SetWindowPos32() on invisible child windows */
999 if (cmd == SW_HIDE) wndPtr->dwStyle &= ~WS_VISIBLE;
1000 else wndPtr->dwStyle |= WS_VISIBLE;
1004 /* We can't activate a child window */
1005 if (wndPtr->dwStyle & WS_CHILD) swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1006 SetWindowPos32( hwnd, HWND_TOP,
1007 newPos.left, newPos.top, newPos.right, newPos.bottom, swp );
1008 if (!IsWindow32( hwnd )) return wasVisible;
1009 else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( wndPtr, TRUE );
1012 if (wndPtr->flags & WIN_NEED_SIZE)
1014 /* should happen only in CreateWindowEx() */
1015 int wParam = SIZE_RESTORED;
1017 wndPtr->flags &= ~WIN_NEED_SIZE;
1018 if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
1019 else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
1020 SendMessage32A( hwnd, WM_SIZE, wParam,
1021 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
1022 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
1023 SendMessage32A( hwnd, WM_MOVE, 0,
1024 MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
1031 /***********************************************************************
1032 * GetInternalWindowPos16 (USER.460)
1034 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
1037 WINDOWPLACEMENT16 wndpl;
1038 if (GetWindowPlacement16( hwnd, &wndpl ))
1040 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1041 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1042 return wndpl.showCmd;
1048 /***********************************************************************
1049 * GetInternalWindowPos32 (USER32.244)
1051 UINT32 WINAPI GetInternalWindowPos32( HWND32 hwnd, LPRECT32 rectWnd,
1054 WINDOWPLACEMENT32 wndpl;
1055 if (GetWindowPlacement32( hwnd, &wndpl ))
1057 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1058 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1059 return wndpl.showCmd;
1064 /***********************************************************************
1065 * GetWindowPlacement16 (USER.370)
1067 BOOL16 WINAPI GetWindowPlacement16( HWND16 hwnd, WINDOWPLACEMENT16 *wndpl )
1069 WND *pWnd = WIN_FindWndPtr( hwnd );
1072 LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1073 *(LPPOINT32)&pWnd->rectWindow.left, &pWnd->rectWindow );
1074 wndpl->length = sizeof(*wndpl);
1075 if( pWnd->dwStyle & WS_MINIMIZE )
1076 wndpl->showCmd = SW_SHOWMAXIMIZED;
1078 wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE )
1079 ? SW_SHOWMINIMIZED : SW_SHOWNORMAL ;
1080 if( pWnd->flags & WIN_RESTORE_MAX )
1081 wndpl->flags = WPF_RESTORETOMAXIMIZED;
1084 wndpl->ptMinPosition = lpPos->ptIconPos;
1085 wndpl->ptMaxPosition = lpPos->ptMaxPos;
1086 wndpl->rcNormalPosition = lpPos->rectNormal;
1093 /***********************************************************************
1094 * GetWindowPlacement32 (USER32.306)
1096 BOOL32 WINAPI GetWindowPlacement32( HWND32 hwnd, WINDOWPLACEMENT32 *pwpl32 )
1100 WINDOWPLACEMENT16 wpl;
1101 wpl.length = sizeof(wpl);
1102 if( GetWindowPlacement16( hwnd, &wpl ) )
1104 pwpl32->length = sizeof(*pwpl32);
1105 pwpl32->flags = wpl.flags;
1106 pwpl32->showCmd = wpl.showCmd;
1107 CONV_POINT16TO32( &wpl.ptMinPosition, &pwpl32->ptMinPosition );
1108 CONV_POINT16TO32( &wpl.ptMaxPosition, &pwpl32->ptMaxPosition );
1109 CONV_RECT16TO32( &wpl.rcNormalPosition, &pwpl32->rcNormalPosition );
1117 /***********************************************************************
1118 * WINPOS_SetPlacement
1120 static BOOL32 WINPOS_SetPlacement( HWND32 hwnd, const WINDOWPLACEMENT16 *wndpl,
1123 WND *pWnd = WIN_FindWndPtr( hwnd );
1126 LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1127 *(LPPOINT32)&pWnd->rectWindow.left, &pWnd->rectWindow );
1129 if( flags & PLACE_MIN ) lpPos->ptIconPos = wndpl->ptMinPosition;
1130 if( flags & PLACE_MAX ) lpPos->ptMaxPos = wndpl->ptMaxPosition;
1131 if( flags & PLACE_RECT) lpPos->rectNormal = wndpl->rcNormalPosition;
1133 if( pWnd->dwStyle & WS_MINIMIZE )
1135 WINPOS_ShowIconTitle( pWnd, FALSE );
1136 if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1137 SetWindowPos32( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1138 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1140 else if( pWnd->dwStyle & WS_MAXIMIZE )
1142 if( !EMPTYPOINT(lpPos->ptMaxPos) )
1143 SetWindowPos32( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1144 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1146 else if( flags & PLACE_RECT )
1147 SetWindowPos32( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1148 lpPos->rectNormal.right - lpPos->rectNormal.left,
1149 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1150 SWP_NOZORDER | SWP_NOACTIVATE );
1152 ShowWindow32( hwnd, wndpl->showCmd );
1153 if( IsWindow32(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1155 if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd, TRUE );
1157 /* SDK: ...valid only the next time... */
1158 if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1166 /***********************************************************************
1167 * SetWindowPlacement16 (USER.371)
1169 BOOL16 WINAPI SetWindowPlacement16(HWND16 hwnd, const WINDOWPLACEMENT16 *wndpl)
1171 return WINPOS_SetPlacement( hwnd, wndpl,
1172 PLACE_MIN | PLACE_MAX | PLACE_RECT );
1175 /***********************************************************************
1176 * SetWindowPlacement32 (USER32.518)
1178 BOOL32 WINAPI SetWindowPlacement32( HWND32 hwnd, const WINDOWPLACEMENT32 *pwpl32 )
1182 WINDOWPLACEMENT16 wpl = { sizeof(WINDOWPLACEMENT16),
1183 pwpl32->flags, pwpl32->showCmd, { pwpl32->ptMinPosition.x,
1184 pwpl32->ptMinPosition.y }, { pwpl32->ptMaxPosition.x,
1185 pwpl32->ptMaxPosition.y }, { pwpl32->rcNormalPosition.left,
1186 pwpl32->rcNormalPosition.top, pwpl32->rcNormalPosition.right,
1187 pwpl32->rcNormalPosition.bottom } };
1189 return WINPOS_SetPlacement( hwnd, &wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1195 /***********************************************************************
1196 * SetInternalWindowPos16 (USER.461)
1198 void WINAPI SetInternalWindowPos16( HWND16 hwnd, UINT16 showCmd,
1199 LPRECT16 rect, LPPOINT16 pt )
1201 if( IsWindow16(hwnd) )
1203 WINDOWPLACEMENT16 wndpl;
1206 wndpl.length = sizeof(wndpl);
1207 wndpl.showCmd = showCmd;
1208 wndpl.flags = flags = 0;
1213 wndpl.flags |= WPF_SETMINPOSITION;
1214 wndpl.ptMinPosition = *pt;
1218 flags |= PLACE_RECT;
1219 wndpl.rcNormalPosition = *rect;
1221 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1226 /***********************************************************************
1227 * SetInternalWindowPos32 (USER32.482)
1229 void WINAPI SetInternalWindowPos32( HWND32 hwnd, UINT32 showCmd,
1230 LPRECT32 rect, LPPOINT32 pt )
1232 if( IsWindow32(hwnd) )
1234 WINDOWPLACEMENT16 wndpl;
1237 wndpl.length = sizeof(wndpl);
1238 wndpl.showCmd = showCmd;
1239 wndpl.flags = flags = 0;
1244 wndpl.flags |= WPF_SETMINPOSITION;
1245 CONV_POINT32TO16( pt, &wndpl.ptMinPosition );
1249 flags |= PLACE_RECT;
1250 CONV_RECT32TO16( rect, &wndpl.rcNormalPosition );
1252 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1257 /***********************************************************************
1258 * WINPOS_ForceXWindowRaise
1260 * Raise a window on top of the X stacking order, while preserving
1261 * the correct Windows Z order.
1263 static void WINPOS_ForceXWindowRaise( WND* pWnd )
1265 XWindowChanges winChanges;
1268 /* Raise all windows up to pWnd according to their Z order.
1269 * (it would be easier with sibling-related Below but it doesn't
1270 * work very well with SGI mwm for instance)
1272 winChanges.stack_mode = Above;
1275 if (pWnd->window) XReconfigureWMWindow( display, pWnd->window, 0,
1276 CWStackMode, &winChanges );
1277 wndPrev = WIN_GetDesktop()->child;
1278 if (wndPrev == pWnd) break;
1279 while (wndPrev && (wndPrev->next != pWnd)) wndPrev = wndPrev->next;
1285 /*******************************************************************
1286 * WINPOS_SetActiveWindow
1288 * SetActiveWindow() back-end. This is the only function that
1289 * can assign active status to a window. It must be called only
1290 * for the top level windows.
1292 BOOL32 WINPOS_SetActiveWindow( HWND32 hWnd, BOOL32 fMouse, BOOL32 fChangeFocus)
1294 CBTACTIVATESTRUCT16* cbtStruct;
1295 WND* wndPtr, *wndTemp;
1296 HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1299 /* paranoid checks */
1300 if( hWnd == GetDesktopWindow32() || hWnd == hwndActive ) return 0;
1302 /* if (wndPtr && (GetTaskQueue(0) != wndPtr->hmemTaskQ))
1305 wndPtr = WIN_FindWndPtr(hWnd);
1306 hOldActiveQueue = (pActiveQueue)?pActiveQueue->self : 0;
1308 if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1309 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1311 dprintf_win(stddeb,"WINPOS_ActivateWindow: no current active window.\n");
1313 /* call CBT hook chain */
1314 if ((cbtStruct = SEGPTR_NEW(CBTACTIVATESTRUCT16)))
1317 cbtStruct->fMouse = fMouse;
1318 cbtStruct->hWndActive = hwndActive;
1319 wRet = HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
1320 (LPARAM)SEGPTR_GET(cbtStruct) );
1321 SEGPTR_FREE(cbtStruct);
1322 if (wRet) return wRet;
1325 /* set prev active wnd to current active wnd and send notification */
1326 if ((hwndPrevActive = hwndActive) && IsWindow32(hwndPrevActive))
1328 if (!SendMessage32A( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1330 if (GetSysModalWindow16() != hWnd) return 0;
1331 /* disregard refusal if hWnd is sysmodal */
1335 SendMessage32A( hwndPrevActive, WM_ACTIVATE,
1336 MAKEWPARAM( WA_INACTIVE, wIconized ),
1339 /* FIXME: must be SendMessage16() because 32A doesn't do
1340 * intertask at this time */
1341 SendMessage16( hwndPrevActive, WM_ACTIVATE, WA_INACTIVE,
1342 MAKELPARAM( (HWND16)hWnd, wIconized ) );
1345 /* check if something happened during message processing */
1346 if( hwndPrevActive != hwndActive ) return 0;
1349 /* set active wnd */
1352 /* send palette messages */
1353 if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1354 SendMessage16((HWND16)-1, WM_PALETTEISCHANGING, (WPARAM16)hWnd, 0L );
1356 /* if prev wnd is minimized redraw icon title */
1357 if( IsIconic32( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1359 /* managed windows will get ConfigureNotify event */
1360 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->flags & WIN_MANAGED))
1362 /* check Z-order and bring hWnd to the top */
1363 for (wndTemp = WIN_GetDesktop()->child; wndTemp; wndTemp = wndTemp->next)
1364 if (wndTemp->dwStyle & WS_VISIBLE) break;
1366 if( wndTemp != wndPtr )
1367 SetWindowPos32(hWnd, HWND_TOP, 0,0,0,0,
1368 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1369 if (!IsWindow32(hWnd)) return 0;
1372 hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1374 /* send WM_ACTIVATEAPP if necessary */
1375 if (hOldActiveQueue != hNewActiveQueue)
1377 WND **list, **ppWnd;
1379 if ((list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
1381 for (ppWnd = list; *ppWnd; ppWnd++)
1383 if (!IsWindow32( (*ppWnd)->hwndSelf )) continue;
1385 if ((*ppWnd)->hmemTaskQ == hOldActiveQueue)
1386 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1387 0, QUEUE_GetQueueTask(hNewActiveQueue) );
1389 HeapFree( SystemHeap, 0, list );
1392 pActiveQueue = (hNewActiveQueue)
1393 ? (MESSAGEQUEUE*) GlobalLock16(hNewActiveQueue) : NULL;
1395 if ((list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
1397 for (ppWnd = list; *ppWnd; ppWnd++)
1399 if (!IsWindow32( (*ppWnd)->hwndSelf )) continue;
1401 if ((*ppWnd)->hmemTaskQ == hNewActiveQueue)
1402 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1403 1, QUEUE_GetQueueTask( hOldActiveQueue ) );
1405 HeapFree( SystemHeap, 0, list );
1407 if (!IsWindow32(hWnd)) return 0;
1412 /* walk up to the first unowned window */
1414 while (wndTemp->owner) wndTemp = wndTemp->owner;
1415 /* and set last active owned popup */
1416 wndTemp->hwndLastActive = hWnd;
1418 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1419 SendMessage32A( hWnd, WM_NCACTIVATE, TRUE, 0 );
1421 SendMessage32A( hWnd, WM_ACTIVATE,
1422 MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1423 (LPARAM)hwndPrevActive );
1425 SendMessage16(hWnd, WM_ACTIVATE, (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE,
1426 MAKELPARAM( (HWND16)hwndPrevActive, wIconized) );
1429 if( !IsWindow32(hWnd) ) return 0;
1432 /* change focus if possible */
1433 if( fChangeFocus && GetFocus32() )
1434 if( WIN_GetTopParent(GetFocus32()) != hwndActive )
1435 FOCUS_SwitchFocus( GetFocus32(),
1436 (wndPtr->dwStyle & WS_MINIMIZE)? 0: hwndActive);
1438 if( !hwndPrevActive && wndPtr &&
1439 wndPtr->window && !(wndPtr->flags & WIN_MANAGED) )
1440 WINPOS_ForceXWindowRaise(wndPtr);
1442 /* if active wnd is minimized redraw icon title */
1443 if( IsIconic32(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1445 return (hWnd == hwndActive);
1448 /*******************************************************************
1449 * WINPOS_ActivateOtherWindow
1451 * Activates window other than pWnd.
1453 BOOL32 WINPOS_ActivateOtherWindow(WND* pWnd)
1458 if( pWnd->hwndSelf == hwndPrevActive )
1461 if( hwndActive != pWnd->hwndSelf &&
1462 ( hwndActive || QUEUE_IsExitingQueue(pWnd->hmemTaskQ)) )
1465 if( !(pWnd->dwStyle & WS_POPUP) || !(pWnd->owner) ||
1466 !WINPOS_CanActivate((pWndTo = WIN_GetTopParentPtr(pWnd->owner))) )
1468 WND* pWndPtr = WIN_GetTopParentPtr(pWnd);
1470 pWndTo = WIN_FindWndPtr(hwndPrevActive);
1472 while( !WINPOS_CanActivate(pWndTo) )
1474 /* by now owned windows should've been taken care of */
1476 pWndTo = pWndPtr->next;
1478 if( !pWndTo ) break;
1482 bRet = WINPOS_SetActiveWindow( pWndTo ? pWndTo->hwndSelf : 0, FALSE, TRUE );
1484 /* switch desktop queue to current active */
1485 if( pWndTo ) WIN_GetDesktop()->hmemTaskQ = pWndTo->hmemTaskQ;
1491 /*******************************************************************
1492 * WINPOS_ChangeActiveWindow
1495 BOOL32 WINPOS_ChangeActiveWindow( HWND32 hWnd, BOOL32 mouseMsg )
1497 WND *wndPtr = WIN_FindWndPtr(hWnd);
1499 if (!hWnd) return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
1501 if( !wndPtr ) return FALSE;
1503 /* child windows get WM_CHILDACTIVATE message */
1504 if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
1505 return SendMessage32A(hWnd, WM_CHILDACTIVATE, 0, 0L);
1507 /* owned popups imply owner activation - not sure */
1508 if ((wndPtr->dwStyle & WS_POPUP) && wndPtr->owner &&
1509 !(wndPtr->owner->dwStyle & WS_DISABLED ))
1511 if (!(wndPtr = wndPtr->owner)) return FALSE;
1512 hWnd = wndPtr->hwndSelf;
1515 if( hWnd == hwndActive ) return FALSE;
1517 if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
1520 /* switch desktop queue to current active */
1521 if( wndPtr->parent == WIN_GetDesktop())
1522 WIN_GetDesktop()->hmemTaskQ = wndPtr->hmemTaskQ;
1528 /***********************************************************************
1529 * WINPOS_SendNCCalcSize
1531 * Send a WM_NCCALCSIZE message to a window.
1532 * All parameters are read-only except newClientRect.
1533 * oldWindowRect, oldClientRect and winpos must be non-NULL only
1534 * when calcValidRect is TRUE.
1536 LONG WINPOS_SendNCCalcSize( HWND32 hwnd, BOOL32 calcValidRect,
1537 RECT32 *newWindowRect, RECT32 *oldWindowRect,
1538 RECT32 *oldClientRect, WINDOWPOS32 *winpos,
1539 RECT32 *newClientRect )
1541 NCCALCSIZE_PARAMS32 params;
1544 params.rgrc[0] = *newWindowRect;
1547 params.rgrc[1] = *oldWindowRect;
1548 params.rgrc[2] = *oldClientRect;
1549 params.lppos = winpos;
1551 result = SendMessage32A( hwnd, WM_NCCALCSIZE, calcValidRect,
1553 dprintf_win( stddeb, "WINPOS_SendNCCalcSize: %d,%d-%d,%d\n",
1554 params.rgrc[0].left, params.rgrc[0].top,
1555 params.rgrc[0].right, params.rgrc[0].bottom );
1556 *newClientRect = params.rgrc[0];
1561 /***********************************************************************
1562 * WINPOS_HandleWindowPosChanging16
1564 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
1566 LONG WINPOS_HandleWindowPosChanging16( WND *wndPtr, WINDOWPOS16 *winpos )
1568 POINT32 maxSize, minTrack;
1569 if (winpos->flags & SWP_NOSIZE) return 0;
1570 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
1571 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
1573 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
1574 if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
1575 if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
1576 if (!(wndPtr->dwStyle & WS_MINIMIZE))
1578 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
1579 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
1586 /***********************************************************************
1587 * WINPOS_HandleWindowPosChanging32
1589 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
1591 LONG WINPOS_HandleWindowPosChanging32( WND *wndPtr, WINDOWPOS32 *winpos )
1594 if (winpos->flags & SWP_NOSIZE) return 0;
1595 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
1596 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
1598 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, NULL, NULL );
1599 winpos->cx = MIN( winpos->cx, maxSize.x );
1600 winpos->cy = MIN( winpos->cy, maxSize.y );
1606 /***********************************************************************
1607 * WINPOS_MoveWindowZOrder
1609 * Move a window in Z order, invalidating everything that needs it.
1610 * Only necessary for windows without associated X window.
1612 static void WINPOS_MoveWindowZOrder( HWND32 hwnd, HWND32 hwndAfter )
1615 WND *pWndAfter, *pWndCur, *wndPtr = WIN_FindWndPtr( hwnd );
1617 /* We have two possible cases:
1618 * - The window is moving up: we have to invalidate all areas
1619 * of the window that were covered by other windows
1620 * - The window is moving down: we have to invalidate areas
1621 * of other windows covered by this one.
1624 if (hwndAfter == HWND_TOP)
1628 else if (hwndAfter == HWND_BOTTOM)
1630 if (!wndPtr->next) return; /* Already at the bottom */
1635 if (!(pWndAfter = WIN_FindWndPtr( hwndAfter ))) return;
1636 if (wndPtr->next == pWndAfter) return; /* Already placed right */
1638 /* Determine which window we encounter first in Z-order */
1639 pWndCur = wndPtr->parent->child;
1640 while ((pWndCur != wndPtr) && (pWndCur != pWndAfter))
1641 pWndCur = pWndCur->next;
1642 movingUp = (pWndCur == pWndAfter);
1647 WND *pWndPrevAfter = wndPtr->next;
1648 WIN_UnlinkWindow( hwnd );
1649 WIN_LinkWindow( hwnd, hwndAfter );
1650 pWndCur = wndPtr->next;
1651 while (pWndCur != pWndPrevAfter)
1653 RECT32 rect = { pWndCur->rectWindow.left,
1654 pWndCur->rectWindow.top,
1655 pWndCur->rectWindow.right,
1656 pWndCur->rectWindow.bottom };
1657 OffsetRect32( &rect, -wndPtr->rectClient.left,
1658 -wndPtr->rectClient.top );
1659 PAINT_RedrawWindow( hwnd, &rect, 0, RDW_INVALIDATE | RDW_ALLCHILDREN |
1660 RDW_FRAME | RDW_ERASE, 0 );
1661 pWndCur = pWndCur->next;
1664 else /* Moving down */
1666 pWndCur = wndPtr->next;
1667 WIN_UnlinkWindow( hwnd );
1668 WIN_LinkWindow( hwnd, hwndAfter );
1669 while (pWndCur != wndPtr)
1671 RECT32 rect = { pWndCur->rectWindow.left,
1672 pWndCur->rectWindow.top,
1673 pWndCur->rectWindow.right,
1674 pWndCur->rectWindow.bottom };
1675 OffsetRect32( &rect, -pWndCur->rectClient.left,
1676 -pWndCur->rectClient.top );
1677 PAINT_RedrawWindow( pWndCur->hwndSelf, &rect, 0, RDW_INVALIDATE |
1678 RDW_ALLCHILDREN | RDW_FRAME | RDW_ERASE, 0 );
1679 pWndCur = pWndCur->next;
1684 /***********************************************************************
1685 * WINPOS_ReorderOwnedPopups
1687 * fix Z order taking into account owned popups -
1688 * basically we need to maintain them above owner window
1690 HWND32 WINPOS_ReorderOwnedPopups(HWND32 hwndInsertAfter,WND* wndPtr,WORD flags)
1692 WND* w = WIN_GetDesktop()->child;
1694 if( wndPtr->dwStyle & WS_POPUP && wndPtr->owner )
1696 /* implement "local z-order" between the top and owner window */
1698 HWND32 hwndLocalPrev = HWND_TOP;
1700 if( hwndInsertAfter != HWND_TOP )
1702 while( w != wndPtr->owner )
1704 if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
1705 if( hwndLocalPrev == hwndInsertAfter ) break;
1708 hwndInsertAfter = hwndLocalPrev;
1712 else if( wndPtr->dwStyle & WS_CHILD ) return hwndInsertAfter;
1714 w = WIN_GetDesktop()->child;
1717 if( w == wndPtr ) break;
1719 if( w->dwStyle & WS_POPUP && w->owner == wndPtr )
1721 SetWindowPos32(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1722 SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
1723 hwndInsertAfter = w->hwndSelf;
1728 return hwndInsertAfter;
1731 /***********************************************************************
1732 * WINPOS_SizeMoveClean
1734 * Make window look nice without excessive repainting
1738 * visible regions are in window coordinates
1739 * update regions are in window client coordinates
1740 * client and window rectangles are in parent client coordinates
1742 * FIXME: Move visible and update regions to the same coordinate system
1743 * (either parent client or window). This is a lot of work though.
1745 static UINT32 WINPOS_SizeMoveClean( WND* Wnd, HRGN32 oldVisRgn,
1746 LPRECT32 lpOldWndRect,
1747 LPRECT32 lpOldClientRect, UINT32 uFlags )
1749 HRGN32 newVisRgn = DCE_GetVisRgn(Wnd->hwndSelf,DCX_WINDOW | DCX_CLIPSIBLINGS);
1750 HRGN32 dirtyRgn = CreateRectRgn32(0,0,0,0);
1753 dprintf_win(stddeb,"cleaning up...new wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i)\n\
1754 \t\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
1755 Wnd->rectWindow.left, Wnd->rectWindow.top,
1756 Wnd->rectWindow.right, Wnd->rectWindow.bottom,
1757 lpOldWndRect->left, lpOldWndRect->top,
1758 lpOldWndRect->right, lpOldWndRect->bottom,
1759 Wnd->rectClient.left, Wnd->rectClient.top,
1760 Wnd->rectClient.right, Wnd->rectClient.bottom,
1761 lpOldClientRect->left, lpOldClientRect->top,
1762 lpOldClientRect->right,lpOldClientRect->bottom );
1764 if( (lpOldWndRect->right - lpOldWndRect->left) != (Wnd->rectWindow.right - Wnd->rectWindow.left) ||
1765 (lpOldWndRect->bottom - lpOldWndRect->top) != (Wnd->rectWindow.bottom - Wnd->rectWindow.top) )
1766 uFlags |= SMC_DRAWFRAME;
1768 CombineRgn32( dirtyRgn, newVisRgn, 0, RGN_COPY);
1770 if( !(uFlags & SMC_NOCOPY) )
1771 CombineRgn32( newVisRgn, newVisRgn, oldVisRgn, RGN_AND );
1773 /* map regions to the parent client area */
1775 OffsetRgn32( dirtyRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
1776 OffsetRgn32( oldVisRgn, lpOldWndRect->left, lpOldWndRect->top );
1778 /* compute invalidated region outside Wnd - (in client coordinates of the parent window) */
1780 other = CombineRgn32(dirtyRgn, oldVisRgn, dirtyRgn, RGN_DIFF);
1782 /* map visible region to the Wnd client area */
1784 OffsetRgn32( newVisRgn, Wnd->rectWindow.left - Wnd->rectClient.left,
1785 Wnd->rectWindow.top - Wnd->rectClient.top );
1787 /* substract previously invalidated region from the Wnd visible region */
1789 my = (Wnd->hrgnUpdate > 1) ? CombineRgn32( newVisRgn, newVisRgn,
1790 Wnd->hrgnUpdate, RGN_DIFF)
1793 if( uFlags & SMC_NOCOPY ) /* invalidate Wnd visible region */
1795 if (my != NULLREGION)
1796 PAINT_RedrawWindow( Wnd->hwndSelf, NULL, newVisRgn, RDW_INVALIDATE |
1797 RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE, RDW_C_USEHRGN );
1798 else if(uFlags & SMC_DRAWFRAME)
1799 Wnd->flags |= WIN_NEEDS_NCPAINT;
1801 else /* bitblt old client area */
1806 int xfrom,yfrom,xto,yto,width,height;
1808 if( uFlags & SMC_DRAWFRAME )
1810 /* copy only client area, frame will be redrawn anyway */
1812 xfrom = lpOldClientRect->left; yfrom = lpOldClientRect->top;
1813 xto = Wnd->rectClient.left; yto = Wnd->rectClient.top;
1814 width = lpOldClientRect->right - xfrom; height = lpOldClientRect->bottom - yfrom;
1815 updateRgn = CreateRectRgn32( 0, 0, width, height );
1816 CombineRgn32( newVisRgn, newVisRgn, updateRgn, RGN_AND );
1817 SetRectRgn32( updateRgn, 0, 0, Wnd->rectClient.right - xto,
1818 Wnd->rectClient.bottom - yto );
1822 xfrom = lpOldWndRect->left; yfrom = lpOldWndRect->top;
1823 xto = Wnd->rectWindow.left; yto = Wnd->rectWindow.top;
1824 width = lpOldWndRect->right - xfrom; height = lpOldWndRect->bottom - yfrom;
1825 updateRgn = CreateRectRgn32( xto - Wnd->rectClient.left,
1826 yto - Wnd->rectClient.top,
1827 Wnd->rectWindow.right - Wnd->rectClient.left,
1828 Wnd->rectWindow.bottom - Wnd->rectClient.top );
1831 CombineRgn32( newVisRgn, newVisRgn, updateRgn, RGN_AND );
1833 /* substract new visRgn from target rect to get a region that won't be copied */
1835 update = CombineRgn32( updateRgn, updateRgn, newVisRgn, RGN_DIFF );
1837 /* Blt valid bits using parent window DC */
1839 if( my != NULLREGION && (xfrom != xto || yfrom != yto) )
1842 /* compute clipping region in parent client coordinates */
1844 OffsetRgn32( newVisRgn, Wnd->rectClient.left, Wnd->rectClient.top );
1845 CombineRgn32( oldVisRgn, oldVisRgn, newVisRgn, RGN_OR );
1847 hDC = GetDCEx32( Wnd->parent->hwndSelf, oldVisRgn,
1848 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN |
1849 DCX_CACHE | DCX_CLIPSIBLINGS);
1851 BitBlt32( hDC, xto, yto, width, height, hDC, xfrom, yfrom, SRCCOPY );
1852 ReleaseDC32( Wnd->parent->hwndSelf, hDC);
1855 if( update != NULLREGION )
1856 PAINT_RedrawWindow( Wnd->hwndSelf, NULL, updateRgn, RDW_INVALIDATE |
1857 RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE, RDW_C_USEHRGN );
1858 else if( uFlags & SMC_DRAWFRAME ) Wnd->flags |= WIN_NEEDS_NCPAINT;
1859 DeleteObject32( updateRgn );
1862 /* erase uncovered areas */
1864 if( !(uFlags & SMC_NOPARENTERASE) && (other != NULLREGION ) )
1865 PAINT_RedrawWindow( Wnd->parent->hwndSelf, NULL, dirtyRgn,
1866 RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE, RDW_C_USEHRGN );
1867 DeleteObject32(dirtyRgn);
1868 DeleteObject32(newVisRgn);
1873 /***********************************************************************
1874 * WINPOS_FindDeskTopXWindow
1876 * Find the actual X window which needs be restacked.
1877 * Used by WINPOS_SetXWindowPos().
1879 static Window WINPOS_FindDeskTopXWindow( WND *wndPtr )
1881 if (!(wndPtr->flags & WIN_MANAGED))
1882 return wndPtr->window;
1885 Window window, root, parent, *children;
1887 window = wndPtr->window;
1890 XQueryTree( display, window, &root, &parent,
1891 &children, &nchildren );
1900 /***********************************************************************
1901 * WINPOS_SetXWindowPos
1903 * SetWindowPos() for an X window. Used by the real SetWindowPos().
1905 static void WINPOS_SetXWindowPos( const WINDOWPOS32 *winpos )
1907 XWindowChanges winChanges;
1909 WND *wndPtr = WIN_FindWndPtr( winpos->hwnd );
1911 if (!(winpos->flags & SWP_NOSIZE))
1913 winChanges.width = winpos->cx;
1914 winChanges.height = winpos->cy;
1915 changeMask |= CWWidth | CWHeight;
1917 /* Tweak dialog window size hints */
1919 if ((wndPtr->flags & WIN_MANAGED) &&
1920 (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME))
1922 XSizeHints *size_hints = XAllocSizeHints();
1926 long supplied_return;
1928 XGetWMSizeHints( display, wndPtr->window, size_hints,
1929 &supplied_return, XA_WM_NORMAL_HINTS);
1930 size_hints->min_width = size_hints->max_width = winpos->cx;
1931 size_hints->min_height = size_hints->max_height = winpos->cy;
1932 XSetWMSizeHints( display, wndPtr->window, size_hints,
1933 XA_WM_NORMAL_HINTS );
1938 if (!(winpos->flags & SWP_NOMOVE))
1940 winChanges.x = winpos->x;
1941 winChanges.y = winpos->y;
1942 changeMask |= CWX | CWY;
1944 if (!(winpos->flags & SWP_NOZORDER))
1946 winChanges.stack_mode = Below;
1947 changeMask |= CWStackMode;
1949 if (winpos->hwndInsertAfter == HWND_TOP) winChanges.stack_mode = Above;
1950 else if (winpos->hwndInsertAfter != HWND_BOTTOM)
1952 WND* insertPtr = WIN_FindWndPtr( winpos->hwndInsertAfter );
1955 stack[0] = WINPOS_FindDeskTopXWindow( insertPtr );
1956 stack[1] = WINPOS_FindDeskTopXWindow( wndPtr );
1958 /* for stupid window managers (i.e. all of them) */
1960 XRestackWindows(display, stack, 2);
1961 changeMask &= ~CWStackMode;
1964 if (!changeMask) return;
1966 XReconfigureWMWindow( display, wndPtr->window, 0, changeMask, &winChanges );
1970 /***********************************************************************
1971 * SetWindowPos (USER.232)
1973 BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
1974 INT16 x, INT16 y, INT16 cx, INT16 cy, WORD flags)
1976 return SetWindowPos32(hwnd,(INT32)(INT16)hwndInsertAfter,x,y,cx,cy,flags);
1979 /***********************************************************************
1980 * SetWindowPos (USER32.519)
1982 BOOL32 WINAPI SetWindowPos32( HWND32 hwnd, HWND32 hwndInsertAfter,
1983 INT32 x, INT32 y, INT32 cx, INT32 cy, WORD flags)
1987 RECT32 newWindowRect, newClientRect, oldWindowRect;
1989 HWND32 tempInsertAfter= 0;
1993 dprintf_win(stddeb,"SetWindowPos: hwnd %04x, (%i,%i)-(%i,%i) flags %08x\n",
1994 hwnd, x, y, x+cx, y+cy, flags);
1995 /* Check window handle */
1997 if (hwnd == GetDesktopWindow32()) return FALSE;
1998 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2000 if (wndPtr->dwStyle & WS_VISIBLE) flags &= ~SWP_SHOWWINDOW;
2003 uFlags |= SMC_NOPARENTERASE;
2004 flags &= ~SWP_HIDEWINDOW;
2005 if (!(flags & SWP_SHOWWINDOW)) flags |= SWP_NOREDRAW;
2008 /* Check for windows that may not be resized
2009 FIXME: this should be done only for Windows 3.0 programs
2010 if (flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW ) )
2011 flags |= SWP_NOSIZE | SWP_NOMOVE;
2013 /* Check dimensions */
2015 if (cx <= 0) cx = 1;
2016 if (cy <= 0) cy = 1;
2020 if (hwnd == hwndActive) flags |= SWP_NOACTIVATE; /* Already active */
2021 if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
2022 (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
2023 flags |= SWP_NOSIZE; /* Already the right size */
2024 if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
2025 flags |= SWP_NOMOVE; /* Already the right position */
2027 /* Check hwndInsertAfter */
2029 if (!(flags & (SWP_NOZORDER | SWP_NOACTIVATE)))
2031 /* Ignore TOPMOST flags when activating a window */
2032 /* _and_ moving it in Z order. */
2033 if ((hwndInsertAfter == HWND_TOPMOST) ||
2034 (hwndInsertAfter == HWND_NOTOPMOST))
2035 hwndInsertAfter = HWND_TOP;
2037 /* TOPMOST not supported yet */
2038 if ((hwndInsertAfter == HWND_TOPMOST) ||
2039 (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
2041 /* hwndInsertAfter must be a sibling of the window */
2042 if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
2044 WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
2045 if( wnd->parent != wndPtr->parent ) return FALSE;
2046 if( wnd->next == wndPtr ) flags |= SWP_NOZORDER;
2048 else if (!(wndPtr->window))
2049 /* FIXME: the following optimization is no good for "X-ed" windows */
2050 if (hwndInsertAfter == HWND_TOP)
2051 flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
2052 else /* HWND_BOTTOM */
2053 flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
2055 /* Fill the WINDOWPOS structure */
2058 winpos.hwndInsertAfter = hwndInsertAfter;
2063 winpos.flags = flags;
2065 /* Send WM_WINDOWPOSCHANGING message */
2067 if (!(flags & SWP_NOSENDCHANGING))
2068 SendMessage32A( hwnd, WM_WINDOWPOSCHANGING, 0, (LPARAM)&winpos );
2070 /* Calculate new position and size */
2072 newWindowRect = wndPtr->rectWindow;
2073 newClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
2074 : wndPtr->rectClient;
2076 if (!(winpos.flags & SWP_NOSIZE))
2078 newWindowRect.right = newWindowRect.left + winpos.cx;
2079 newWindowRect.bottom = newWindowRect.top + winpos.cy;
2081 if (!(winpos.flags & SWP_NOMOVE))
2083 newWindowRect.left = winpos.x;
2084 newWindowRect.top = winpos.y;
2085 newWindowRect.right += winpos.x - wndPtr->rectWindow.left;
2086 newWindowRect.bottom += winpos.y - wndPtr->rectWindow.top;
2088 OffsetRect32( &newClientRect, winpos.x - wndPtr->rectWindow.left,
2089 winpos.y - wndPtr->rectWindow.top );
2092 winpos.flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
2094 /* Reposition window in Z order */
2096 if (!(winpos.flags & SWP_NOZORDER))
2098 /* reorder owned popups if hwnd is top-level window
2100 if( wndPtr->parent == WIN_GetDesktop() )
2101 hwndInsertAfter = WINPOS_ReorderOwnedPopups( hwndInsertAfter,
2106 WIN_UnlinkWindow( winpos.hwnd );
2107 WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
2109 else WINPOS_MoveWindowZOrder( winpos.hwnd, hwndInsertAfter );
2112 if ( !wndPtr->window && !(flags & SWP_NOREDRAW) &&
2113 (!(flags & SWP_NOMOVE) || !(flags & SWP_NOSIZE) || (flags & SWP_FRAMECHANGED)) )
2114 visRgn = DCE_GetVisRgn(hwnd, DCX_WINDOW | DCX_CLIPSIBLINGS);
2117 /* Send WM_NCCALCSIZE message to get new client area */
2118 if( (flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
2120 result = WINPOS_SendNCCalcSize( winpos.hwnd, TRUE, &newWindowRect,
2121 &wndPtr->rectWindow, &wndPtr->rectClient,
2122 &winpos, &newClientRect );
2124 /* FIXME: WVR_ALIGNxxx */
2126 if( newClientRect.left != wndPtr->rectClient.left ||
2127 newClientRect.top != wndPtr->rectClient.top )
2128 winpos.flags &= ~SWP_NOCLIENTMOVE;
2130 if( (newClientRect.right - newClientRect.left !=
2131 wndPtr->rectClient.right - wndPtr->rectClient.left) ||
2132 (newClientRect.bottom - newClientRect.top !=
2133 wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
2134 winpos.flags &= ~SWP_NOCLIENTSIZE;
2137 if( !(flags & SWP_NOMOVE) && (newClientRect.left != wndPtr->rectClient.left ||
2138 newClientRect.top != wndPtr->rectClient.top) )
2139 winpos.flags &= ~SWP_NOCLIENTMOVE;
2141 /* Update active DCEs */
2143 if( !(flags & SWP_NOZORDER) || (flags & SWP_HIDEWINDOW) || (flags & SWP_SHOWWINDOW)
2144 || (memcmp(&newWindowRect,&wndPtr->rectWindow,sizeof(newWindowRect))
2145 && wndPtr->dwStyle & WS_VISIBLE ) )
2149 UnionRect32(&rect,&newWindowRect,&wndPtr->rectWindow);
2150 DCE_InvalidateDCE(wndPtr->parent, &rect);
2153 /* change geometry */
2155 oldWindowRect = wndPtr->rectWindow;
2159 RECT32 oldClientRect = wndPtr->rectClient;
2161 tempInsertAfter = winpos.hwndInsertAfter;
2163 winpos.hwndInsertAfter = hwndInsertAfter;
2165 /* postpone geometry change */
2167 if( !(flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW)) )
2169 WINPOS_SetXWindowPos( &winpos );
2170 winpos.hwndInsertAfter = tempInsertAfter;
2172 else uFlags |= SMC_SETXPOS;
2174 wndPtr->rectWindow = newWindowRect;
2175 wndPtr->rectClient = newClientRect;
2177 if( !(flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW)) )
2178 if( (oldClientRect.left - oldWindowRect.left !=
2179 newClientRect.left - newWindowRect.left) ||
2180 (oldClientRect.top - oldWindowRect.top !=
2181 newClientRect.top - newWindowRect.top) ||
2182 winpos.flags & SWP_NOCOPYBITS )
2184 PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, 0, RDW_INVALIDATE |
2185 RDW_ALLCHILDREN | RDW_FRAME | RDW_ERASE, 0 );
2187 if( winpos.flags & SWP_FRAMECHANGED )
2192 if( oldClientRect.right > newClientRect.right )
2194 rect.left = newClientRect.right; rect.top = newClientRect.top;
2195 rect.right = oldClientRect.right; rect.bottom = newClientRect.bottom;
2197 PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, 0,
2198 RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN, 0 );
2200 if( oldClientRect.bottom > newClientRect.bottom )
2202 rect.left = newClientRect.left; rect.top = newClientRect.bottom;
2203 rect.right = (wErase)?oldClientRect.right:newClientRect.right;
2204 rect.bottom = oldClientRect.bottom;
2206 PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, 0,
2207 RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN, 0 );
2209 if( !wErase ) wndPtr->flags |= WIN_NEEDS_NCPAINT;
2214 RECT32 oldClientRect = wndPtr->rectClient;
2216 wndPtr->rectWindow = newWindowRect;
2217 wndPtr->rectClient = newClientRect;
2219 if( oldClientRect.bottom - oldClientRect.top ==
2220 newClientRect.bottom - newClientRect.top ) result &= ~WVR_VREDRAW;
2222 if( oldClientRect.right - oldClientRect.left ==
2223 newClientRect.right - newClientRect.left ) result &= ~WVR_HREDRAW;
2225 if( !(flags & (SWP_NOREDRAW | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
2227 uFlags |= ((winpos.flags & SWP_NOCOPYBITS) ||
2228 (result >= WVR_HREDRAW && result < WVR_VALIDRECTS)) ? SMC_NOCOPY : 0;
2229 uFlags |= (winpos.flags & SWP_FRAMECHANGED) ? SMC_DRAWFRAME : 0;
2231 if( (winpos.flags & SWP_AGG_NOGEOMETRYCHANGE) != SWP_AGG_NOGEOMETRYCHANGE )
2232 uFlags = WINPOS_SizeMoveClean(wndPtr, visRgn, &oldWindowRect,
2233 &oldClientRect, uFlags);
2236 /* adjust frame and do not erase parent */
2238 if( winpos.flags & SWP_FRAMECHANGED ) wndPtr->flags |= WIN_NEEDS_NCPAINT;
2239 if( winpos.flags & SWP_NOZORDER ) uFlags |= SMC_NOPARENTERASE;
2242 DeleteObject32(visRgn);
2245 if (flags & SWP_SHOWWINDOW)
2247 wndPtr->dwStyle |= WS_VISIBLE;
2250 if( uFlags & SMC_SETXPOS )
2252 WINPOS_SetXWindowPos( &winpos );
2253 winpos.hwndInsertAfter = tempInsertAfter;
2255 XMapWindow( display, wndPtr->window );
2259 if (!(flags & SWP_NOREDRAW))
2260 PAINT_RedrawWindow( winpos.hwnd, NULL, 0,
2261 RDW_INVALIDATE | RDW_ALLCHILDREN |
2262 RDW_FRAME | RDW_ERASENOW | RDW_ERASE, 0 );
2265 else if (flags & SWP_HIDEWINDOW)
2267 wndPtr->dwStyle &= ~WS_VISIBLE;
2270 XUnmapWindow( display, wndPtr->window );
2271 if( uFlags & SMC_SETXPOS )
2273 WINPOS_SetXWindowPos( &winpos );
2274 winpos.hwndInsertAfter = tempInsertAfter;
2279 if (!(flags & SWP_NOREDRAW))
2280 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, &oldWindowRect,
2281 0, RDW_INVALIDATE | RDW_ALLCHILDREN |
2282 RDW_ERASE | RDW_ERASENOW, 0 );
2283 uFlags |= SMC_NOPARENTERASE;
2286 if ((winpos.hwnd == GetFocus32()) ||
2287 IsChild32( winpos.hwnd, GetFocus32()))
2289 /* Revert focus to parent */
2290 SetFocus32( GetParent32(winpos.hwnd) );
2292 if (hwnd == CARET_GetHwnd()) DestroyCaret32();
2294 if (winpos.hwnd == hwndActive)
2295 WINPOS_ActivateOtherWindow( wndPtr );
2298 /* Activate the window */
2300 if (!(flags & SWP_NOACTIVATE))
2301 WINPOS_ChangeActiveWindow( winpos.hwnd, FALSE );
2303 /* Repaint the window */
2305 if (wndPtr->window) EVENT_Synchronize(); /* Wait for all expose events */
2307 if (!GetCapture32())
2308 EVENT_DummyMotionNotify(); /* Simulate a mouse event to set the cursor */
2310 if (!(flags & SWP_DEFERERASE) && !(uFlags & SMC_NOPARENTERASE) )
2312 PAINT_RedrawWindow( wndPtr->parent->hwndSelf,
2313 (wndPtr->flags & WIN_SAVEUNDER_OVERRIDE) ? &oldWindowRect : NULL,
2314 0, RDW_ALLCHILDREN | RDW_ERASENOW |
2315 ((wndPtr->flags & WIN_SAVEUNDER_OVERRIDE) ? RDW_INVALIDATE : 0), 0 );
2316 wndPtr->flags &= ~WIN_SAVEUNDER_OVERRIDE;
2318 else if( wndPtr->parent == WIN_GetDesktop() && wndPtr->parent->flags & WIN_NEEDS_ERASEBKGND )
2319 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0, RDW_NOCHILDREN | RDW_ERASENOW, 0 );
2321 /* And last, send the WM_WINDOWPOSCHANGED message */
2323 dprintf_win(stddeb,"\tstatus flags = %04x\n", winpos.flags & SWP_AGG_STATUSFLAGS);
2325 if ( ((winpos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) &&
2326 !(winpos.flags & SWP_NOSENDCHANGING))
2327 SendMessage32A( winpos.hwnd, WM_WINDOWPOSCHANGED,
2328 0, (LPARAM)&winpos );
2334 /***********************************************************************
2335 * BeginDeferWindowPos16 (USER.259)
2337 HDWP16 WINAPI BeginDeferWindowPos16( INT16 count )
2339 return BeginDeferWindowPos32( count );
2343 /***********************************************************************
2344 * BeginDeferWindowPos32 (USER32.8)
2346 HDWP32 WINAPI BeginDeferWindowPos32( INT32 count )
2351 if (count <= 0) return 0;
2352 handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS32) );
2353 if (!handle) return 0;
2354 pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
2355 pDWP->actualCount = 0;
2356 pDWP->suggestedCount = count;
2358 pDWP->wMagic = DWP_MAGIC;
2359 pDWP->hwndParent = 0;
2364 /***********************************************************************
2365 * DeferWindowPos16 (USER.260)
2367 HDWP16 WINAPI DeferWindowPos16( HDWP16 hdwp, HWND16 hwnd, HWND16 hwndAfter,
2368 INT16 x, INT16 y, INT16 cx, INT16 cy,
2371 return DeferWindowPos32( hdwp, hwnd, (INT32)(INT16)hwndAfter,
2372 x, y, cx, cy, flags );
2376 /***********************************************************************
2377 * DeferWindowPos32 (USER32.127)
2379 HDWP32 WINAPI DeferWindowPos32( HDWP32 hdwp, HWND32 hwnd, HWND32 hwndAfter,
2380 INT32 x, INT32 y, INT32 cx, INT32 cy,
2385 HDWP32 newhdwp = hdwp;
2389 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
2390 if (!pDWP) return 0;
2391 if (hwnd == GetDesktopWindow32()) return 0;
2393 /* All the windows of a DeferWindowPos() must have the same parent */
2394 if (!(pWnd=WIN_FindWndPtr( hwnd ))) {
2395 USER_HEAP_FREE( hdwp );
2399 parent = pWnd->parent->hwndSelf;
2400 if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
2401 else if (parent != pDWP->hwndParent)
2403 USER_HEAP_FREE( hdwp );
2407 for (i = 0; i < pDWP->actualCount; i++)
2409 if (pDWP->winPos[i].hwnd == hwnd)
2411 /* Merge with the other changes */
2412 if (!(flags & SWP_NOZORDER))
2414 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
2416 if (!(flags & SWP_NOMOVE))
2418 pDWP->winPos[i].x = x;
2419 pDWP->winPos[i].y = y;
2421 if (!(flags & SWP_NOSIZE))
2423 pDWP->winPos[i].cx = cx;
2424 pDWP->winPos[i].cy = cy;
2426 pDWP->winPos[i].flags &= flags & (SWP_NOSIZE | SWP_NOMOVE |
2427 SWP_NOZORDER | SWP_NOREDRAW |
2428 SWP_NOACTIVATE | SWP_NOCOPYBITS |
2430 pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
2435 if (pDWP->actualCount >= pDWP->suggestedCount)
2437 newhdwp = USER_HEAP_REALLOC( hdwp,
2438 sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS32) );
2439 if (!newhdwp) return 0;
2440 pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
2441 pDWP->suggestedCount++;
2443 pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
2444 pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
2445 pDWP->winPos[pDWP->actualCount].x = x;
2446 pDWP->winPos[pDWP->actualCount].y = y;
2447 pDWP->winPos[pDWP->actualCount].cx = cx;
2448 pDWP->winPos[pDWP->actualCount].cy = cy;
2449 pDWP->winPos[pDWP->actualCount].flags = flags;
2450 pDWP->actualCount++;
2455 /***********************************************************************
2456 * EndDeferWindowPos16 (USER.261)
2458 BOOL16 WINAPI EndDeferWindowPos16( HDWP16 hdwp )
2460 return EndDeferWindowPos32( hdwp );
2464 /***********************************************************************
2465 * EndDeferWindowPos32 (USER32.172)
2467 BOOL32 WINAPI EndDeferWindowPos32( HDWP32 hdwp )
2470 WINDOWPOS32 *winpos;
2474 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
2475 if (!pDWP) return FALSE;
2476 for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
2478 if (!(res = SetWindowPos32( winpos->hwnd, winpos->hwndInsertAfter,
2479 winpos->x, winpos->y, winpos->cx,
2480 winpos->cy, winpos->flags ))) break;
2482 USER_HEAP_FREE( hdwp );
2487 /***********************************************************************
2488 * TileChildWindows (USER.199)
2490 void WINAPI TileChildWindows( HWND16 parent, WORD action )
2492 printf("STUB TileChildWindows(%04x, %d)\n", parent, action);
2495 /***********************************************************************
2496 * CascageChildWindows (USER.198)
2498 void WINAPI CascadeChildWindows( HWND16 parent, WORD action )
2500 printf("STUB CascadeChildWindows(%04x, %d)\n", parent, action);