Release 980517
[wine/multimedia.git] / windows / winpos.c
blob043cf75874b916205055edb568cdc5226d86d85c
1 /*
2 * Window position related functions.
4 * Copyright 1993, 1994, 1995 Alexandre Julliard
5 * 1995, 1996 Alex Korobka
6 */
8 #include <string.h>
9 #include "ts_xlib.h"
10 #include "ts_xutil.h"
11 #include <X11/Xatom.h>
12 #include "sysmetrics.h"
13 #include "heap.h"
14 #include "module.h"
15 #include "user.h"
16 #include "win.h"
17 #include "hook.h"
18 #include "message.h"
19 #include "queue.h"
20 #include "options.h"
21 #include "winpos.h"
22 #include "dce.h"
23 #include "nonclient.h"
24 #include "debug.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 /* ----- external functions ----- */
54 extern void FOCUS_SwitchFocus( HWND32 , HWND32 );
55 extern HWND32 CARET_GetHwnd();
57 /* ----- internal variables ----- */
59 static HWND32 hwndActive = 0; /* Currently active window */
60 static HWND32 hwndPrevActive = 0; /* Previously active window */
62 static LPCSTR atomInternalPos;
64 extern MESSAGEQUEUE* pActiveQueue;
66 /***********************************************************************
67 * WINPOS_CreateInternalPosAtom
69 BOOL32 WINPOS_CreateInternalPosAtom()
71 LPSTR str = "SysIP";
72 atomInternalPos = (LPCSTR)(DWORD)GlobalAddAtom32A(str);
73 return (atomInternalPos) ? TRUE : FALSE;
76 /***********************************************************************
77 * WINPOS_CheckInternalPos
79 * Called when a window is destroyed.
81 void WINPOS_CheckInternalPos( HWND32 hwnd )
83 LPINTERNALPOS lpPos = (LPINTERNALPOS) GetProp32A( hwnd, atomInternalPos );
85 if( hwnd == hwndPrevActive ) hwndPrevActive = 0;
86 if( hwnd == hwndActive )
88 hwndActive = 0;
89 WARN(win, "\tattempt to activate destroyed window!\n");
92 if( lpPos )
94 if( IsWindow32(lpPos->hwndIconTitle) )
95 DestroyWindow32( lpPos->hwndIconTitle );
96 HeapFree( SystemHeap, 0, lpPos );
100 /***********************************************************************
101 * WINPOS_FindIconPos
103 * Find a suitable place for an iconic window.
105 static POINT16 WINPOS_FindIconPos( WND* wndPtr, POINT16 pt )
107 RECT16 rectParent;
108 short x, y, xspacing, yspacing;
110 GetClientRect16( wndPtr->parent->hwndSelf, &rectParent );
111 if ((pt.x >= rectParent.left) && (pt.x + SYSMETRICS_CXICON < rectParent.right) &&
112 (pt.y >= rectParent.top) && (pt.y + SYSMETRICS_CYICON < rectParent.bottom))
113 return pt; /* The icon already has a suitable position */
115 xspacing = SYSMETRICS_CXICONSPACING;
116 yspacing = SYSMETRICS_CYICONSPACING;
118 y = rectParent.bottom;
119 for (;;)
121 for (x = rectParent.left; x <= rectParent.right-xspacing; x += xspacing)
123 /* Check if another icon already occupies this spot */
124 WND *childPtr = wndPtr->parent->child;
125 while (childPtr)
127 if ((childPtr->dwStyle & WS_MINIMIZE) && (childPtr != wndPtr))
129 if ((childPtr->rectWindow.left < x + xspacing) &&
130 (childPtr->rectWindow.right >= x) &&
131 (childPtr->rectWindow.top <= y) &&
132 (childPtr->rectWindow.bottom > y - yspacing))
133 break; /* There's a window in there */
135 childPtr = childPtr->next;
137 if (!childPtr) /* No window was found, so it's OK for us */
139 pt.x = x + (xspacing - SYSMETRICS_CXICON) / 2;
140 pt.y = y - (yspacing + SYSMETRICS_CYICON) / 2;
141 return pt;
144 y -= yspacing;
149 /***********************************************************************
150 * ArrangeIconicWindows16 (USER.170)
152 UINT16 WINAPI ArrangeIconicWindows16( HWND16 parent)
154 return ArrangeIconicWindows32(parent);
156 /***********************************************************************
157 * ArrangeIconicWindows32 (USER32.7)
159 UINT32 WINAPI ArrangeIconicWindows32( HWND32 parent )
161 RECT32 rectParent;
162 HWND32 hwndChild;
163 INT32 x, y, xspacing, yspacing;
165 GetClientRect32( parent, &rectParent );
166 x = rectParent.left;
167 y = rectParent.bottom;
168 xspacing = SYSMETRICS_CXICONSPACING;
169 yspacing = SYSMETRICS_CYICONSPACING;
171 hwndChild = GetWindow32( parent, GW_CHILD );
172 while (hwndChild)
174 if( IsIconic32( hwndChild ) )
176 WINPOS_ShowIconTitle( WIN_FindWndPtr(hwndChild), FALSE );
177 SetWindowPos32( hwndChild, 0, x + (xspacing - SYSMETRICS_CXICON) / 2,
178 y - yspacing - SYSMETRICS_CYICON/2, 0, 0,
179 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
180 if( IsWindow32(hwndChild) )
181 WINPOS_ShowIconTitle( WIN_FindWndPtr(hwndChild), TRUE );
182 if (x <= rectParent.right - xspacing) x += xspacing;
183 else
185 x = rectParent.left;
186 y -= yspacing;
189 hwndChild = GetWindow32( hwndChild, GW_HWNDNEXT );
191 return yspacing;
195 /***********************************************************************
196 * SwitchToThisWindow16 (USER.172)
198 void WINAPI SwitchToThisWindow16( HWND16 hwnd, BOOL16 restore )
200 SwitchToThisWindow32( hwnd, restore );
204 /***********************************************************************
205 * SwitchToThisWindow32 (USER32.539)
207 void WINAPI SwitchToThisWindow32( HWND32 hwnd, BOOL32 restore )
209 ShowWindow32( hwnd, restore ? SW_RESTORE : SW_SHOWMINIMIZED );
213 /***********************************************************************
214 * GetWindowRect16 (USER.32)
216 void WINAPI GetWindowRect16( HWND16 hwnd, LPRECT16 rect )
218 WND * wndPtr = WIN_FindWndPtr( hwnd );
219 if (!wndPtr) return;
221 CONV_RECT32TO16( &wndPtr->rectWindow, rect );
222 if (wndPtr->dwStyle & WS_CHILD)
223 MapWindowPoints16( wndPtr->parent->hwndSelf, 0, (POINT16 *)rect, 2 );
227 /***********************************************************************
228 * GetWindowRect32 (USER32.308)
230 void WINAPI GetWindowRect32( HWND32 hwnd, LPRECT32 rect )
232 WND * wndPtr = WIN_FindWndPtr( hwnd );
233 if (!wndPtr) return;
235 *rect = wndPtr->rectWindow;
236 if (wndPtr->dwStyle & WS_CHILD)
237 MapWindowPoints32( wndPtr->parent->hwndSelf, 0, (POINT32 *)rect, 2 );
241 /***********************************************************************
242 * GetWindowRgn32
244 BOOL32 WINAPI GetWindowRgn32 ( HWND32 hwnd, HRGN32 hrgn )
247 RECT32 rect;
248 WND * wndPtr = WIN_FindWndPtr( hwnd );
249 if (!wndPtr) return (ERROR);
251 FIXME (win, "GetWindowRgn32: doesn't really do regions\n");
253 memset (&rect, 0, sizeof(rect));
255 GetWindowRect32 ( hwnd, &rect );
257 FIXME (win, "Check whether a valid region here\n");
259 SetRectRgn32 ( hrgn, rect.left, rect.top, rect.right, rect.bottom );
261 return (SIMPLEREGION);
264 /***********************************************************************
265 * SetWindowRgn32
267 BOOL32 WINAPI SetWindowRgn32 ( HWND32 hwnd, HRGN32 hrgn,BOOL32 bRedraw)
271 FIXME (win, "SetWindowRgn32: stub\n");
272 return TRUE;
276 /***********************************************************************
277 * GetClientRect16 (USER.33)
279 void WINAPI GetClientRect16( HWND16 hwnd, LPRECT16 rect )
281 WND * wndPtr = WIN_FindWndPtr( hwnd );
283 rect->left = rect->top = rect->right = rect->bottom = 0;
284 if (wndPtr)
286 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
287 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
292 /***********************************************************************
293 * GetClientRect32 (USER32.220)
295 void WINAPI GetClientRect32( HWND32 hwnd, LPRECT32 rect )
297 WND * wndPtr = WIN_FindWndPtr( hwnd );
299 rect->left = rect->top = rect->right = rect->bottom = 0;
300 if (wndPtr)
302 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
303 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
308 /*******************************************************************
309 * ClientToScreen16 (USER.28)
311 void WINAPI ClientToScreen16( HWND16 hwnd, LPPOINT16 lppnt )
313 MapWindowPoints16( hwnd, 0, lppnt, 1 );
317 /*******************************************************************
318 * ClientToScreen32 (USER32.52)
320 BOOL32 WINAPI ClientToScreen32( HWND32 hwnd, LPPOINT32 lppnt )
322 MapWindowPoints32( hwnd, 0, lppnt, 1 );
323 return TRUE;
327 /*******************************************************************
328 * ScreenToClient16 (USER.29)
330 void WINAPI ScreenToClient16( HWND16 hwnd, LPPOINT16 lppnt )
332 MapWindowPoints16( 0, hwnd, lppnt, 1 );
336 /*******************************************************************
337 * ScreenToClient32 (USER32.447)
339 void WINAPI ScreenToClient32( HWND32 hwnd, LPPOINT32 lppnt )
341 MapWindowPoints32( 0, hwnd, lppnt, 1 );
345 /***********************************************************************
346 * WINPOS_WindowFromPoint
348 * Find the window and hittest for a given point.
350 INT16 WINPOS_WindowFromPoint( WND* wndScope, POINT16 pt, WND **ppWnd )
352 WND *wndPtr;
353 INT16 hittest = HTERROR;
354 POINT16 xy = pt;
356 *ppWnd = NULL;
357 wndPtr = wndScope->child;
358 MapWindowPoints16( GetDesktopWindow16(), wndScope->hwndSelf, &xy, 1 );
360 for (;;)
362 while (wndPtr)
364 /* If point is in window, and window is visible, and it */
365 /* is enabled (or it's a top-level window), then explore */
366 /* its children. Otherwise, go to the next window. */
368 if ((wndPtr->dwStyle & WS_VISIBLE) &&
369 (!(wndPtr->dwStyle & WS_DISABLED) ||
370 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)) &&
371 (xy.x >= wndPtr->rectWindow.left) &&
372 (xy.x < wndPtr->rectWindow.right) &&
373 (xy.y >= wndPtr->rectWindow.top) &&
374 (xy.y < wndPtr->rectWindow.bottom))
376 *ppWnd = wndPtr; /* Got a suitable window */
378 /* If window is minimized or disabled, return at once */
379 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
380 if (wndPtr->dwStyle & WS_DISABLED) return HTERROR;
382 /* If point is not in client area, ignore the children */
383 if ((xy.x < wndPtr->rectClient.left) ||
384 (xy.x >= wndPtr->rectClient.right) ||
385 (xy.y < wndPtr->rectClient.top) ||
386 (xy.y >= wndPtr->rectClient.bottom)) break;
388 xy.x -= wndPtr->rectClient.left;
389 xy.y -= wndPtr->rectClient.top;
390 wndPtr = wndPtr->child;
392 else wndPtr = wndPtr->next;
395 /* If nothing found, try the scope window */
396 if (!*ppWnd) *ppWnd = wndScope;
398 /* Send the WM_NCHITTEST message (only if to the same task) */
399 if ((*ppWnd)->hmemTaskQ == GetTaskQueue(0))
401 hittest = (INT16)SendMessage16( (*ppWnd)->hwndSelf, WM_NCHITTEST,
402 0, MAKELONG( pt.x, pt.y ) );
403 if (hittest != HTTRANSPARENT) return hittest; /* Found the window */
405 else return HTCLIENT;
407 /* If no children found in last search, make point relative to parent */
408 if (!wndPtr)
410 xy.x += (*ppWnd)->rectClient.left;
411 xy.y += (*ppWnd)->rectClient.top;
414 /* Restart the search from the next sibling */
415 wndPtr = (*ppWnd)->next;
416 *ppWnd = (*ppWnd)->parent;
421 /*******************************************************************
422 * WindowFromPoint16 (USER.30)
424 HWND16 WINAPI WindowFromPoint16( POINT16 pt )
426 WND *pWnd;
427 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt, &pWnd );
428 return pWnd->hwndSelf;
432 /*******************************************************************
433 * WindowFromPoint32 (USER32.582)
435 HWND32 WINAPI WindowFromPoint32( POINT32 pt )
437 WND *pWnd;
438 POINT16 pt16;
439 CONV_POINT32TO16( &pt, &pt16 );
440 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16, &pWnd );
441 return (HWND32)pWnd->hwndSelf;
445 /*******************************************************************
446 * ChildWindowFromPoint16 (USER.191)
448 HWND16 WINAPI ChildWindowFromPoint16( HWND16 hwndParent, POINT16 pt )
450 POINT32 pt32;
451 CONV_POINT16TO32( &pt, &pt32 );
452 return (HWND16)ChildWindowFromPoint32( hwndParent, pt32 );
456 /*******************************************************************
457 * ChildWindowFromPoint32 (USER32.49)
459 HWND32 WINAPI ChildWindowFromPoint32( HWND32 hwndParent, POINT32 pt )
461 /* pt is in the client coordinates */
463 WND* wnd = WIN_FindWndPtr(hwndParent);
464 RECT32 rect;
466 if( !wnd ) return 0;
468 /* get client rect fast */
469 rect.top = rect.left = 0;
470 rect.right = wnd->rectClient.right - wnd->rectClient.left;
471 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
473 if (!PtInRect32( &rect, pt )) return 0;
475 wnd = wnd->child;
476 while ( wnd )
478 if (PtInRect32( &wnd->rectWindow, pt )) return wnd->hwndSelf;
479 wnd = wnd->next;
481 return hwndParent;
485 /*******************************************************************
486 * WINPOS_GetWinOffset
488 * Calculate the offset between the origin of the two windows. Used
489 * to implement MapWindowPoints.
491 static void WINPOS_GetWinOffset( HWND32 hwndFrom, HWND32 hwndTo,
492 POINT32 *offset )
494 WND * wndPtr;
496 offset->x = offset->y = 0;
497 if (hwndFrom == hwndTo ) return;
499 /* Translate source window origin to screen coords */
500 if (hwndFrom)
502 if (!(wndPtr = WIN_FindWndPtr( hwndFrom )))
504 ERR(win,"bad hwndFrom = %04x\n",hwndFrom);
505 return;
507 while (wndPtr->parent)
509 offset->x += wndPtr->rectClient.left;
510 offset->y += wndPtr->rectClient.top;
511 wndPtr = wndPtr->parent;
515 /* Translate origin to destination window coords */
516 if (hwndTo)
518 if (!(wndPtr = WIN_FindWndPtr( hwndTo )))
520 ERR(win,"bad hwndTo = %04x\n", hwndTo );
521 return;
523 while (wndPtr->parent)
525 offset->x -= wndPtr->rectClient.left;
526 offset->y -= wndPtr->rectClient.top;
527 wndPtr = wndPtr->parent;
533 /*******************************************************************
534 * MapWindowPoints16 (USER.258)
536 void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
537 LPPOINT16 lppt, UINT16 count )
539 POINT32 offset;
541 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
542 while (count--)
544 lppt->x += offset.x;
545 lppt->y += offset.y;
546 lppt++;
551 /*******************************************************************
552 * MapWindowPoints32 (USER32.386)
554 void WINAPI MapWindowPoints32( HWND32 hwndFrom, HWND32 hwndTo,
555 LPPOINT32 lppt, UINT32 count )
557 POINT32 offset;
559 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
560 while (count--)
562 lppt->x += offset.x;
563 lppt->y += offset.y;
564 lppt++;
569 /***********************************************************************
570 * IsIconic16 (USER.31)
572 BOOL16 WINAPI IsIconic16(HWND16 hWnd)
574 return IsIconic32(hWnd);
578 /***********************************************************************
579 * IsIconic32 (USER32.345)
581 BOOL32 WINAPI IsIconic32(HWND32 hWnd)
583 WND * wndPtr = WIN_FindWndPtr(hWnd);
584 if (wndPtr == NULL) return FALSE;
585 return (wndPtr->dwStyle & WS_MINIMIZE) != 0;
589 /***********************************************************************
590 * IsZoomed (USER.272)
592 BOOL16 WINAPI IsZoomed16(HWND16 hWnd)
594 return IsZoomed32(hWnd);
598 /***********************************************************************
599 * IsZoomed (USER32.352)
601 BOOL32 WINAPI IsZoomed32(HWND32 hWnd)
603 WND * wndPtr = WIN_FindWndPtr(hWnd);
604 if (wndPtr == NULL) return FALSE;
605 return (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
609 /*******************************************************************
610 * GetActiveWindow (USER.60)
612 HWND16 WINAPI GetActiveWindow16(void)
614 return (HWND16)hwndActive;
617 /*******************************************************************
618 * GetActiveWindow (USER32.205)
620 HWND32 WINAPI GetActiveWindow32(void)
622 return (HWND32)hwndActive;
626 /*******************************************************************
627 * WINPOS_CanActivate
629 static BOOL32 WINPOS_CanActivate(WND* pWnd)
631 if( pWnd && ((pWnd->dwStyle & (WS_DISABLED | WS_VISIBLE | WS_CHILD))
632 == WS_VISIBLE) ) return TRUE;
633 return FALSE;
637 /*******************************************************************
638 * SetActiveWindow16 (USER.59)
640 HWND16 WINAPI SetActiveWindow16( HWND16 hwnd )
642 return SetActiveWindow32(hwnd);
646 /*******************************************************************
647 * SetActiveWindow32 (USER32.463)
649 HWND32 WINAPI SetActiveWindow32( HWND32 hwnd )
651 HWND32 prev = hwndActive;
652 WND *wndPtr = WIN_FindWndPtr( hwnd );
654 if ( !WINPOS_CanActivate(wndPtr) ) return 0;
656 WINPOS_SetActiveWindow( hwnd, 0, 0 );
657 return prev;
661 /*******************************************************************
662 * GetForegroundWindow16 (USER.608)
664 HWND16 WINAPI GetForegroundWindow16(void)
666 return (HWND16)GetForegroundWindow32();
670 /*******************************************************************
671 * SetForegroundWindow16 (USER.609)
673 BOOL16 WINAPI SetForegroundWindow16( HWND16 hwnd )
675 return SetForegroundWindow32( hwnd );
679 /*******************************************************************
680 * GetForegroundWindow32 (USER32.241)
682 HWND32 WINAPI GetForegroundWindow32(void)
684 return GetActiveWindow32();
688 /*******************************************************************
689 * SetForegroundWindow32 (USER32.482)
691 BOOL32 WINAPI SetForegroundWindow32( HWND32 hwnd )
693 SetActiveWindow32( hwnd );
694 return TRUE;
698 /*******************************************************************
699 * GetShellWindow16 (USER.600)
701 HWND16 WINAPI GetShellWindow16(void)
703 return GetShellWindow32();
706 /*******************************************************************
707 * SetShellWindow32 (USER32.504)
709 HWND32 WINAPI SetShellWindow32(HWND32 hwndshell)
711 FIXME(win, "(%08x): empty stub\n",hwndshell );
712 return 0;
716 /*******************************************************************
717 * GetShellWindow32 (USER32.287)
719 HWND32 WINAPI GetShellWindow32(void)
721 FIXME(win, "(void): empty stub\n" );
722 return 0;
726 /***********************************************************************
727 * BringWindowToTop16 (USER.45)
729 BOOL16 WINAPI BringWindowToTop16( HWND16 hwnd )
731 return BringWindowToTop32(hwnd);
735 /***********************************************************************
736 * BringWindowToTop32 (USER32.11)
738 BOOL32 WINAPI BringWindowToTop32( HWND32 hwnd )
740 return SetWindowPos32( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
744 /***********************************************************************
745 * MoveWindow16 (USER.56)
747 BOOL16 WINAPI MoveWindow16( HWND16 hwnd, INT16 x, INT16 y, INT16 cx, INT16 cy,
748 BOOL16 repaint )
750 return MoveWindow32(hwnd,x,y,cx,cy,repaint);
754 /***********************************************************************
755 * MoveWindow32 (USER32.399)
757 BOOL32 WINAPI MoveWindow32( HWND32 hwnd, INT32 x, INT32 y, INT32 cx, INT32 cy,
758 BOOL32 repaint )
760 int flags = SWP_NOZORDER | SWP_NOACTIVATE;
761 if (!repaint) flags |= SWP_NOREDRAW;
762 TRACE(win, "%04x %d,%d %dx%d %d\n",
763 hwnd, x, y, cx, cy, repaint );
764 return SetWindowPos32( hwnd, 0, x, y, cx, cy, flags );
767 /***********************************************************************
768 * WINPOS_InitInternalPos
770 static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT32 pt,
771 LPRECT32 restoreRect )
773 LPINTERNALPOS lpPos = (LPINTERNALPOS) GetProp32A( wnd->hwndSelf,
774 atomInternalPos );
775 if( !lpPos )
777 /* this happens when the window is minimized/maximized
778 * for the first time (rectWindow is not adjusted yet) */
780 lpPos = HeapAlloc( SystemHeap, 0, sizeof(INTERNALPOS) );
781 if( !lpPos ) return NULL;
783 SetProp32A( wnd->hwndSelf, atomInternalPos, (HANDLE32)lpPos );
784 lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
785 CONV_RECT32TO16( &wnd->rectWindow, &lpPos->rectNormal );
786 *(UINT32*)&lpPos->ptIconPos = *(UINT32*)&lpPos->ptMaxPos = 0xFFFFFFFF;
789 if( wnd->dwStyle & WS_MINIMIZE )
790 CONV_POINT32TO16( &pt, &lpPos->ptIconPos );
791 else if( wnd->dwStyle & WS_MAXIMIZE )
792 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
793 else if( restoreRect )
794 CONV_RECT32TO16( restoreRect, &lpPos->rectNormal );
796 return lpPos;
799 /***********************************************************************
800 * WINPOS_RedrawIconTitle
802 BOOL32 WINPOS_RedrawIconTitle( HWND32 hWnd )
804 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetProp32A( hWnd, atomInternalPos );
805 if( lpPos )
807 if( lpPos->hwndIconTitle )
809 SendMessage32A( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
810 InvalidateRect32( lpPos->hwndIconTitle, NULL, TRUE );
811 return TRUE;
814 return FALSE;
817 /***********************************************************************
818 * WINPOS_ShowIconTitle
820 BOOL32 WINPOS_ShowIconTitle( WND* pWnd, BOOL32 bShow )
822 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetProp32A( pWnd->hwndSelf, atomInternalPos );
824 if( lpPos && !(pWnd->flags & WIN_MANAGED))
826 HWND16 hWnd = lpPos->hwndIconTitle;
828 TRACE(win,"0x%04x %i\n", pWnd->hwndSelf, (bShow != 0) );
830 if( !hWnd )
831 lpPos->hwndIconTitle = hWnd = ICONTITLE_Create( pWnd );
832 if( bShow )
834 pWnd = WIN_FindWndPtr(hWnd);
836 if( !(pWnd->dwStyle & WS_VISIBLE) )
838 SendMessage32A( hWnd, WM_SHOWWINDOW, TRUE, 0 );
839 SetWindowPos32( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
840 SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
843 else ShowWindow32( hWnd, SW_HIDE );
845 return FALSE;
848 /*******************************************************************
849 * WINPOS_GetMinMaxInfo
851 * Get the minimized and maximized information for a window.
853 void WINPOS_GetMinMaxInfo( WND *wndPtr, POINT32 *maxSize, POINT32 *maxPos,
854 POINT32 *minTrack, POINT32 *maxTrack )
856 LPINTERNALPOS lpPos;
857 MINMAXINFO32 MinMax;
858 INT32 xinc, yinc;
860 /* Compute default values */
862 MinMax.ptMaxSize.x = SYSMETRICS_CXSCREEN;
863 MinMax.ptMaxSize.y = SYSMETRICS_CYSCREEN;
864 MinMax.ptMinTrackSize.x = SYSMETRICS_CXMINTRACK;
865 MinMax.ptMinTrackSize.y = SYSMETRICS_CYMINTRACK;
866 MinMax.ptMaxTrackSize.x = SYSMETRICS_CXSCREEN;
867 MinMax.ptMaxTrackSize.y = SYSMETRICS_CYSCREEN;
869 if (wndPtr->flags & WIN_MANAGED) xinc = yinc = 0;
870 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
872 xinc = SYSMETRICS_CXDLGFRAME;
873 yinc = SYSMETRICS_CYDLGFRAME;
875 else
877 xinc = yinc = 0;
878 if (HAS_THICKFRAME(wndPtr->dwStyle))
880 xinc += SYSMETRICS_CXFRAME;
881 yinc += SYSMETRICS_CYFRAME;
883 if (wndPtr->dwStyle & WS_BORDER)
885 xinc += SYSMETRICS_CXBORDER;
886 yinc += SYSMETRICS_CYBORDER;
889 MinMax.ptMaxSize.x += 2 * xinc;
890 MinMax.ptMaxSize.y += 2 * yinc;
892 lpPos = (LPINTERNALPOS)GetProp32A( wndPtr->hwndSelf, atomInternalPos );
893 if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
894 CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
895 else
897 MinMax.ptMaxPosition.x = -xinc;
898 MinMax.ptMaxPosition.y = -yinc;
901 SendMessage32A( wndPtr->hwndSelf, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
903 /* Some sanity checks */
905 TRACE(win,"%d %d / %d %d / %d %d / %d %d\n",
906 MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
907 MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
908 MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
909 MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
910 MinMax.ptMaxTrackSize.x = MAX( MinMax.ptMaxTrackSize.x,
911 MinMax.ptMinTrackSize.x );
912 MinMax.ptMaxTrackSize.y = MAX( MinMax.ptMaxTrackSize.y,
913 MinMax.ptMinTrackSize.y );
915 if (maxSize) *maxSize = MinMax.ptMaxSize;
916 if (maxPos) *maxPos = MinMax.ptMaxPosition;
917 if (minTrack) *minTrack = MinMax.ptMinTrackSize;
918 if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
921 /***********************************************************************
922 * WINPOS_MinMaximize
924 * Fill in lpRect and return additional flags to be used with SetWindowPos().
925 * This function assumes that 'cmd' is different from the current window
926 * state.
928 UINT16 WINPOS_MinMaximize( WND* wndPtr, UINT16 cmd, LPRECT16 lpRect )
930 UINT16 swpFlags = 0;
931 POINT32 pt;
932 POINT32 size = { wndPtr->rectWindow.left, wndPtr->rectWindow.top };
933 LPINTERNALPOS lpPos = WINPOS_InitInternalPos( wndPtr, size,
934 &wndPtr->rectWindow );
936 TRACE(win,"0x%04x %u\n", wndPtr->hwndSelf, cmd );
938 if (lpPos && !HOOK_CallHooks16(WH_CBT, HCBT_MINMAX, wndPtr->hwndSelf, cmd))
940 if( wndPtr->dwStyle & WS_MINIMIZE )
942 if( !SendMessage32A( wndPtr->hwndSelf, WM_QUERYOPEN, 0, 0L ) )
943 return (SWP_NOSIZE | SWP_NOMOVE);
944 swpFlags |= SWP_NOCOPYBITS;
946 switch( cmd )
948 case SW_MINIMIZE:
949 if( wndPtr->dwStyle & WS_MAXIMIZE)
951 wndPtr->flags |= WIN_RESTORE_MAX;
952 wndPtr->dwStyle &= ~WS_MAXIMIZE;
954 else
955 wndPtr->flags &= ~WIN_RESTORE_MAX;
956 wndPtr->dwStyle |= WS_MINIMIZE;
958 lpPos->ptIconPos = WINPOS_FindIconPos( wndPtr, lpPos->ptIconPos );
960 SetRect16( lpRect, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
961 SYSMETRICS_CXICON, SYSMETRICS_CYICON );
962 swpFlags |= SWP_NOCOPYBITS;
963 break;
965 case SW_MAXIMIZE:
966 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
967 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL );
968 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
970 if( wndPtr->dwStyle & WS_MINIMIZE )
972 WINPOS_ShowIconTitle( wndPtr, FALSE );
973 wndPtr->dwStyle &= ~WS_MINIMIZE;
975 wndPtr->dwStyle |= WS_MAXIMIZE;
977 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
978 size.x, size.y );
979 break;
981 case SW_RESTORE:
982 if( wndPtr->dwStyle & WS_MINIMIZE )
984 wndPtr->dwStyle &= ~WS_MINIMIZE;
985 WINPOS_ShowIconTitle( wndPtr, FALSE );
986 if( wndPtr->flags & WIN_RESTORE_MAX)
988 /* Restore to maximized position */
989 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
990 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL);
991 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
992 wndPtr->dwStyle |= WS_MAXIMIZE;
993 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y, size.x, size.y );
994 break;
997 else
998 if( !(wndPtr->dwStyle & WS_MAXIMIZE) ) return (UINT16)(-1);
999 else wndPtr->dwStyle &= ~WS_MAXIMIZE;
1001 /* Restore to normal position */
1003 *lpRect = lpPos->rectNormal;
1004 lpRect->right -= lpRect->left;
1005 lpRect->bottom -= lpRect->top;
1007 break;
1009 } else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
1010 return swpFlags;
1013 /***********************************************************************
1014 * ShowWindowAsync32 (USER32.535)
1016 * doesn't wait; returns immediately.
1017 * used by threads to toggle windows in other (possibly hanging) threads
1019 BOOL32 WINAPI ShowWindowAsync32( HWND32 hwnd, INT32 cmd )
1021 /* FIXME: does ShowWindow32() return immediately ? */
1022 return ShowWindow32(hwnd, cmd);
1026 /***********************************************************************
1027 * ShowWindow16 (USER.42)
1029 BOOL16 WINAPI ShowWindow16( HWND16 hwnd, INT16 cmd )
1031 return ShowWindow32(hwnd,cmd);
1035 /***********************************************************************
1036 * ShowWindow32 (USER32.534)
1038 BOOL32 WINAPI ShowWindow32( HWND32 hwnd, INT32 cmd )
1040 WND* wndPtr = WIN_FindWndPtr( hwnd );
1041 BOOL32 wasVisible, showFlag;
1042 RECT16 newPos = {0, 0, 0, 0};
1043 int swp = 0;
1045 if (!wndPtr) return FALSE;
1047 TRACE(win,"hwnd=%04x, cmd=%d\n", hwnd, cmd);
1049 wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
1051 switch(cmd)
1053 case SW_HIDE:
1054 if (!wasVisible) return FALSE;
1055 swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
1056 SWP_NOACTIVATE | SWP_NOZORDER;
1057 break;
1059 case SW_SHOWMINNOACTIVE:
1060 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1061 /* fall through */
1062 case SW_SHOWMINIMIZED:
1063 swp |= SWP_SHOWWINDOW;
1064 /* fall through */
1065 case SW_MINIMIZE:
1066 swp |= SWP_FRAMECHANGED;
1067 if( !(wndPtr->dwStyle & WS_MINIMIZE) )
1068 swp |= WINPOS_MinMaximize( wndPtr, SW_MINIMIZE, &newPos );
1069 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1070 break;
1072 case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
1073 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1074 if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
1075 swp |= WINPOS_MinMaximize( wndPtr, SW_MAXIMIZE, &newPos );
1076 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1077 break;
1079 case SW_SHOWNA:
1080 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1081 /* fall through */
1082 case SW_SHOW:
1083 swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
1084 break;
1086 case SW_SHOWNOACTIVATE:
1087 swp |= SWP_NOZORDER;
1088 if (GetActiveWindow32()) swp |= SWP_NOACTIVATE;
1089 /* fall through */
1090 case SW_SHOWNORMAL: /* same as SW_NORMAL: */
1091 case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
1092 case SW_RESTORE:
1093 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1095 if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) )
1096 swp |= WINPOS_MinMaximize( wndPtr, SW_RESTORE, &newPos );
1097 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1098 break;
1101 showFlag = (cmd != SW_HIDE);
1102 if (showFlag != wasVisible)
1104 SendMessage32A( hwnd, WM_SHOWWINDOW, showFlag, 0 );
1105 if (!IsWindow32( hwnd )) return wasVisible;
1108 if ((wndPtr->dwStyle & WS_CHILD) &&
1109 !IsWindowVisible32( wndPtr->parent->hwndSelf ) &&
1110 (swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE) )
1112 /* Don't call SetWindowPos32() on invisible child windows */
1113 if (cmd == SW_HIDE) wndPtr->dwStyle &= ~WS_VISIBLE;
1114 else wndPtr->dwStyle |= WS_VISIBLE;
1116 else
1118 /* We can't activate a child window */
1119 if (wndPtr->dwStyle & WS_CHILD) swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1120 SetWindowPos32( hwnd, HWND_TOP,
1121 newPos.left, newPos.top, newPos.right, newPos.bottom, swp );
1122 if (!IsWindow32( hwnd )) return wasVisible;
1123 else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( wndPtr, TRUE );
1126 if (wndPtr->flags & WIN_NEED_SIZE)
1128 /* should happen only in CreateWindowEx() */
1129 int wParam = SIZE_RESTORED;
1131 wndPtr->flags &= ~WIN_NEED_SIZE;
1132 if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
1133 else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
1134 SendMessage32A( hwnd, WM_SIZE, wParam,
1135 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
1136 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
1137 SendMessage32A( hwnd, WM_MOVE, 0,
1138 MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
1141 return wasVisible;
1145 /***********************************************************************
1146 * GetInternalWindowPos16 (USER.460)
1148 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
1149 LPPOINT16 ptIcon )
1151 WINDOWPLACEMENT16 wndpl;
1152 if (GetWindowPlacement16( hwnd, &wndpl ))
1154 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1155 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1156 return wndpl.showCmd;
1158 return 0;
1162 /***********************************************************************
1163 * GetInternalWindowPos32 (USER32.245)
1165 UINT32 WINAPI GetInternalWindowPos32( HWND32 hwnd, LPRECT32 rectWnd,
1166 LPPOINT32 ptIcon )
1168 WINDOWPLACEMENT32 wndpl;
1169 if (GetWindowPlacement32( hwnd, &wndpl ))
1171 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1172 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1173 return wndpl.showCmd;
1175 return 0;
1178 /***********************************************************************
1179 * GetWindowPlacement16 (USER.370)
1181 BOOL16 WINAPI GetWindowPlacement16( HWND16 hwnd, WINDOWPLACEMENT16 *wndpl )
1183 WND *pWnd = WIN_FindWndPtr( hwnd );
1184 if( pWnd )
1186 LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1187 *(LPPOINT32)&pWnd->rectWindow.left, &pWnd->rectWindow );
1188 wndpl->length = sizeof(*wndpl);
1189 if( pWnd->dwStyle & WS_MINIMIZE )
1190 wndpl->showCmd = SW_SHOWMAXIMIZED;
1191 else
1192 wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE )
1193 ? SW_SHOWMINIMIZED : SW_SHOWNORMAL ;
1194 if( pWnd->flags & WIN_RESTORE_MAX )
1195 wndpl->flags = WPF_RESTORETOMAXIMIZED;
1196 else
1197 wndpl->flags = 0;
1198 wndpl->ptMinPosition = lpPos->ptIconPos;
1199 wndpl->ptMaxPosition = lpPos->ptMaxPos;
1200 wndpl->rcNormalPosition = lpPos->rectNormal;
1201 return TRUE;
1203 return FALSE;
1207 /***********************************************************************
1208 * GetWindowPlacement32 (USER32.307)
1210 BOOL32 WINAPI GetWindowPlacement32( HWND32 hwnd, WINDOWPLACEMENT32 *pwpl32 )
1212 if( pwpl32 )
1214 WINDOWPLACEMENT16 wpl;
1215 wpl.length = sizeof(wpl);
1216 if( GetWindowPlacement16( hwnd, &wpl ) )
1218 pwpl32->length = sizeof(*pwpl32);
1219 pwpl32->flags = wpl.flags;
1220 pwpl32->showCmd = wpl.showCmd;
1221 CONV_POINT16TO32( &wpl.ptMinPosition, &pwpl32->ptMinPosition );
1222 CONV_POINT16TO32( &wpl.ptMaxPosition, &pwpl32->ptMaxPosition );
1223 CONV_RECT16TO32( &wpl.rcNormalPosition, &pwpl32->rcNormalPosition );
1224 return TRUE;
1227 return FALSE;
1231 /***********************************************************************
1232 * WINPOS_SetPlacement
1234 static BOOL32 WINPOS_SetPlacement( HWND32 hwnd, const WINDOWPLACEMENT16 *wndpl,
1235 UINT32 flags )
1237 WND *pWnd = WIN_FindWndPtr( hwnd );
1238 if( pWnd )
1240 LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1241 *(LPPOINT32)&pWnd->rectWindow.left, &pWnd->rectWindow );
1243 if( flags & PLACE_MIN ) lpPos->ptIconPos = wndpl->ptMinPosition;
1244 if( flags & PLACE_MAX ) lpPos->ptMaxPos = wndpl->ptMaxPosition;
1245 if( flags & PLACE_RECT) lpPos->rectNormal = wndpl->rcNormalPosition;
1247 if( pWnd->dwStyle & WS_MINIMIZE )
1249 WINPOS_ShowIconTitle( pWnd, FALSE );
1250 if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1251 SetWindowPos32( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1252 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1254 else if( pWnd->dwStyle & WS_MAXIMIZE )
1256 if( !EMPTYPOINT(lpPos->ptMaxPos) )
1257 SetWindowPos32( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1258 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1260 else if( flags & PLACE_RECT )
1261 SetWindowPos32( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1262 lpPos->rectNormal.right - lpPos->rectNormal.left,
1263 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1264 SWP_NOZORDER | SWP_NOACTIVATE );
1266 ShowWindow32( hwnd, wndpl->showCmd );
1267 if( IsWindow32(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1269 if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd, TRUE );
1271 /* SDK: ...valid only the next time... */
1272 if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1274 return TRUE;
1276 return FALSE;
1280 /***********************************************************************
1281 * SetWindowPlacement16 (USER.371)
1283 BOOL16 WINAPI SetWindowPlacement16(HWND16 hwnd, const WINDOWPLACEMENT16 *wndpl)
1285 return WINPOS_SetPlacement( hwnd, wndpl,
1286 PLACE_MIN | PLACE_MAX | PLACE_RECT );
1289 /***********************************************************************
1290 * SetWindowPlacement32 (USER32.519)
1292 BOOL32 WINAPI SetWindowPlacement32( HWND32 hwnd, const WINDOWPLACEMENT32 *pwpl32 )
1294 if( pwpl32 )
1296 WINDOWPLACEMENT16 wpl = { sizeof(WINDOWPLACEMENT16),
1297 pwpl32->flags, pwpl32->showCmd, { pwpl32->ptMinPosition.x,
1298 pwpl32->ptMinPosition.y }, { pwpl32->ptMaxPosition.x,
1299 pwpl32->ptMaxPosition.y }, { pwpl32->rcNormalPosition.left,
1300 pwpl32->rcNormalPosition.top, pwpl32->rcNormalPosition.right,
1301 pwpl32->rcNormalPosition.bottom } };
1303 return WINPOS_SetPlacement( hwnd, &wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1305 return FALSE;
1309 /***********************************************************************
1310 * SetInternalWindowPos16 (USER.461)
1312 void WINAPI SetInternalWindowPos16( HWND16 hwnd, UINT16 showCmd,
1313 LPRECT16 rect, LPPOINT16 pt )
1315 if( IsWindow16(hwnd) )
1317 WINDOWPLACEMENT16 wndpl;
1318 UINT32 flags;
1320 wndpl.length = sizeof(wndpl);
1321 wndpl.showCmd = showCmd;
1322 wndpl.flags = flags = 0;
1324 if( pt )
1326 flags |= PLACE_MIN;
1327 wndpl.flags |= WPF_SETMINPOSITION;
1328 wndpl.ptMinPosition = *pt;
1330 if( rect )
1332 flags |= PLACE_RECT;
1333 wndpl.rcNormalPosition = *rect;
1335 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1340 /***********************************************************************
1341 * SetInternalWindowPos32 (USER32.483)
1343 void WINAPI SetInternalWindowPos32( HWND32 hwnd, UINT32 showCmd,
1344 LPRECT32 rect, LPPOINT32 pt )
1346 if( IsWindow32(hwnd) )
1348 WINDOWPLACEMENT16 wndpl;
1349 UINT32 flags;
1351 wndpl.length = sizeof(wndpl);
1352 wndpl.showCmd = showCmd;
1353 wndpl.flags = flags = 0;
1355 if( pt )
1357 flags |= PLACE_MIN;
1358 wndpl.flags |= WPF_SETMINPOSITION;
1359 CONV_POINT32TO16( pt, &wndpl.ptMinPosition );
1361 if( rect )
1363 flags |= PLACE_RECT;
1364 CONV_RECT32TO16( rect, &wndpl.rcNormalPosition );
1366 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1371 /***********************************************************************
1372 * WINPOS_ForceXWindowRaise
1374 * Raise a window on top of the X stacking order, while preserving
1375 * the correct Windows Z order.
1377 static void WINPOS_ForceXWindowRaise( WND* pWnd )
1379 XWindowChanges winChanges;
1380 WND *wndPrev;
1382 /* Raise all windows up to pWnd according to their Z order.
1383 * (it would be easier with sibling-related Below but it doesn't
1384 * work very well with SGI mwm for instance)
1386 winChanges.stack_mode = Above;
1387 while (pWnd)
1389 if (pWnd->window) TSXReconfigureWMWindow( display, pWnd->window, 0,
1390 CWStackMode, &winChanges );
1391 wndPrev = WIN_GetDesktop()->child;
1392 if (wndPrev == pWnd) break;
1393 while (wndPrev && (wndPrev->next != pWnd)) wndPrev = wndPrev->next;
1394 pWnd = wndPrev;
1399 /*******************************************************************
1400 * WINPOS_SetActiveWindow
1402 * SetActiveWindow() back-end. This is the only function that
1403 * can assign active status to a window. It must be called only
1404 * for the top level windows.
1406 BOOL32 WINPOS_SetActiveWindow( HWND32 hWnd, BOOL32 fMouse, BOOL32 fChangeFocus)
1408 CBTACTIVATESTRUCT16* cbtStruct;
1409 WND* wndPtr, *wndTemp;
1410 HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1411 WORD wIconized = 0;
1413 /* paranoid checks */
1414 if( hWnd == GetDesktopWindow32() || hWnd == hwndActive ) return 0;
1416 /* if (wndPtr && (GetTaskQueue(0) != wndPtr->hmemTaskQ))
1417 * return 0;
1419 wndPtr = WIN_FindWndPtr(hWnd);
1420 hOldActiveQueue = (pActiveQueue)?pActiveQueue->self : 0;
1422 if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1423 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1424 else
1425 TRACE(win,"no current active window.\n");
1427 /* call CBT hook chain */
1428 if ((cbtStruct = SEGPTR_NEW(CBTACTIVATESTRUCT16)))
1430 LRESULT wRet;
1431 cbtStruct->fMouse = fMouse;
1432 cbtStruct->hWndActive = hwndActive;
1433 wRet = HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
1434 (LPARAM)SEGPTR_GET(cbtStruct) );
1435 SEGPTR_FREE(cbtStruct);
1436 if (wRet) return wRet;
1439 /* set prev active wnd to current active wnd and send notification */
1440 if ((hwndPrevActive = hwndActive) && IsWindow32(hwndPrevActive))
1442 if (!SendMessage32A( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1444 if (GetSysModalWindow16() != hWnd) return 0;
1445 /* disregard refusal if hWnd is sysmodal */
1448 #if 1
1449 SendMessage32A( hwndPrevActive, WM_ACTIVATE,
1450 MAKEWPARAM( WA_INACTIVE, wIconized ),
1451 (LPARAM)hWnd );
1452 #else
1453 /* FIXME: must be SendMessage16() because 32A doesn't do
1454 * intertask at this time */
1455 SendMessage16( hwndPrevActive, WM_ACTIVATE, WA_INACTIVE,
1456 MAKELPARAM( (HWND16)hWnd, wIconized ) );
1457 #endif
1459 /* check if something happened during message processing */
1460 if( hwndPrevActive != hwndActive ) return 0;
1463 /* set active wnd */
1464 hwndActive = hWnd;
1466 /* send palette messages */
1467 if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1468 SendMessage16((HWND16)-1, WM_PALETTEISCHANGING, (WPARAM16)hWnd, 0L );
1470 /* if prev wnd is minimized redraw icon title */
1471 if( IsIconic32( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1473 /* managed windows will get ConfigureNotify event */
1474 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->flags & WIN_MANAGED))
1476 /* check Z-order and bring hWnd to the top */
1477 for (wndTemp = WIN_GetDesktop()->child; wndTemp; wndTemp = wndTemp->next)
1478 if (wndTemp->dwStyle & WS_VISIBLE) break;
1480 if( wndTemp != wndPtr )
1481 SetWindowPos32(hWnd, HWND_TOP, 0,0,0,0,
1482 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1483 if (!IsWindow32(hWnd)) return 0;
1486 hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1488 /* send WM_ACTIVATEAPP if necessary */
1489 if (hOldActiveQueue != hNewActiveQueue)
1491 WND **list, **ppWnd;
1493 if ((list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
1495 for (ppWnd = list; *ppWnd; ppWnd++)
1497 if (!IsWindow32( (*ppWnd)->hwndSelf )) continue;
1499 if ((*ppWnd)->hmemTaskQ == hOldActiveQueue)
1500 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1501 0, QUEUE_GetQueueTask(hNewActiveQueue) );
1503 HeapFree( SystemHeap, 0, list );
1506 pActiveQueue = (hNewActiveQueue)
1507 ? (MESSAGEQUEUE*) GlobalLock16(hNewActiveQueue) : NULL;
1509 if ((list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
1511 for (ppWnd = list; *ppWnd; ppWnd++)
1513 if (!IsWindow32( (*ppWnd)->hwndSelf )) continue;
1515 if ((*ppWnd)->hmemTaskQ == hNewActiveQueue)
1516 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1517 1, QUEUE_GetQueueTask( hOldActiveQueue ) );
1519 HeapFree( SystemHeap, 0, list );
1521 if (!IsWindow32(hWnd)) return 0;
1524 if (hWnd)
1526 /* walk up to the first unowned window */
1527 wndTemp = wndPtr;
1528 while (wndTemp->owner) wndTemp = wndTemp->owner;
1529 /* and set last active owned popup */
1530 wndTemp->hwndLastActive = hWnd;
1532 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1533 SendMessage32A( hWnd, WM_NCACTIVATE, TRUE, 0 );
1534 #if 1
1535 SendMessage32A( hWnd, WM_ACTIVATE,
1536 MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1537 (LPARAM)hwndPrevActive );
1538 #else
1539 SendMessage16(hWnd, WM_ACTIVATE, (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE,
1540 MAKELPARAM( (HWND16)hwndPrevActive, wIconized) );
1541 #endif
1543 if( !IsWindow32(hWnd) ) return 0;
1546 /* change focus if possible */
1547 if( fChangeFocus && GetFocus32() )
1548 if( WIN_GetTopParent(GetFocus32()) != hwndActive )
1549 FOCUS_SwitchFocus( GetFocus32(),
1550 (wndPtr->dwStyle & WS_MINIMIZE)? 0: hwndActive);
1552 if( !hwndPrevActive && wndPtr &&
1553 wndPtr->window && !(wndPtr->flags & WIN_MANAGED) )
1554 WINPOS_ForceXWindowRaise(wndPtr);
1556 /* if active wnd is minimized redraw icon title */
1557 if( IsIconic32(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1559 return (hWnd == hwndActive);
1562 /*******************************************************************
1563 * WINPOS_ActivateOtherWindow
1565 * Activates window other than pWnd.
1567 BOOL32 WINPOS_ActivateOtherWindow(WND* pWnd)
1569 BOOL32 bRet = 0;
1570 WND* pWndTo = NULL;
1572 if( pWnd->hwndSelf == hwndPrevActive )
1573 hwndPrevActive = 0;
1575 if( hwndActive != pWnd->hwndSelf &&
1576 ( hwndActive || QUEUE_IsExitingQueue(pWnd->hmemTaskQ)) )
1577 return 0;
1579 if( !(pWnd->dwStyle & WS_POPUP) || !(pWnd->owner) ||
1580 !WINPOS_CanActivate((pWndTo = WIN_GetTopParentPtr(pWnd->owner))) )
1582 WND* pWndPtr = WIN_GetTopParentPtr(pWnd);
1584 pWndTo = WIN_FindWndPtr(hwndPrevActive);
1586 while( !WINPOS_CanActivate(pWndTo) )
1588 /* by now owned windows should've been taken care of */
1590 pWndTo = pWndPtr->next;
1591 pWndPtr = pWndTo;
1592 if( !pWndTo ) break;
1596 bRet = WINPOS_SetActiveWindow( pWndTo ? pWndTo->hwndSelf : 0, FALSE, TRUE );
1598 /* switch desktop queue to current active */
1599 if( pWndTo ) WIN_GetDesktop()->hmemTaskQ = pWndTo->hmemTaskQ;
1601 hwndPrevActive = 0;
1602 return bRet;
1605 /*******************************************************************
1606 * WINPOS_ChangeActiveWindow
1609 BOOL32 WINPOS_ChangeActiveWindow( HWND32 hWnd, BOOL32 mouseMsg )
1611 WND *wndPtr = WIN_FindWndPtr(hWnd);
1613 if (!hWnd) return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
1615 if( !wndPtr ) return FALSE;
1617 /* child windows get WM_CHILDACTIVATE message */
1618 if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
1619 return SendMessage32A(hWnd, WM_CHILDACTIVATE, 0, 0L);
1621 /* owned popups imply owner activation - not sure */
1622 if ((wndPtr->dwStyle & WS_POPUP) && wndPtr->owner &&
1623 !(wndPtr->owner->dwStyle & WS_DISABLED ))
1625 if (!(wndPtr = wndPtr->owner)) return FALSE;
1626 hWnd = wndPtr->hwndSelf;
1629 if( hWnd == hwndActive ) return FALSE;
1631 if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
1632 return FALSE;
1634 /* switch desktop queue to current active */
1635 if( wndPtr->parent == WIN_GetDesktop())
1636 WIN_GetDesktop()->hmemTaskQ = wndPtr->hmemTaskQ;
1638 return TRUE;
1642 /***********************************************************************
1643 * WINPOS_SendNCCalcSize
1645 * Send a WM_NCCALCSIZE message to a window.
1646 * All parameters are read-only except newClientRect.
1647 * oldWindowRect, oldClientRect and winpos must be non-NULL only
1648 * when calcValidRect is TRUE.
1650 LONG WINPOS_SendNCCalcSize( HWND32 hwnd, BOOL32 calcValidRect,
1651 RECT32 *newWindowRect, RECT32 *oldWindowRect,
1652 RECT32 *oldClientRect, WINDOWPOS32 *winpos,
1653 RECT32 *newClientRect )
1655 NCCALCSIZE_PARAMS32 params;
1656 LONG result;
1658 params.rgrc[0] = *newWindowRect;
1659 if (calcValidRect)
1661 params.rgrc[1] = *oldWindowRect;
1662 params.rgrc[2] = *oldClientRect;
1663 params.lppos = winpos;
1665 result = SendMessage32A( hwnd, WM_NCCALCSIZE, calcValidRect,
1666 (LPARAM)&params );
1667 TRACE(win, "%d,%d-%d,%d\n",
1668 params.rgrc[0].left, params.rgrc[0].top,
1669 params.rgrc[0].right, params.rgrc[0].bottom );
1670 *newClientRect = params.rgrc[0];
1671 return result;
1675 /***********************************************************************
1676 * WINPOS_HandleWindowPosChanging16
1678 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
1680 LONG WINPOS_HandleWindowPosChanging16( WND *wndPtr, WINDOWPOS16 *winpos )
1682 POINT32 maxSize, minTrack;
1683 if (winpos->flags & SWP_NOSIZE) return 0;
1684 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
1685 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
1687 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
1688 if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
1689 if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
1690 if (!(wndPtr->dwStyle & WS_MINIMIZE))
1692 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
1693 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
1696 return 0;
1700 /***********************************************************************
1701 * WINPOS_HandleWindowPosChanging32
1703 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
1705 LONG WINPOS_HandleWindowPosChanging32( WND *wndPtr, WINDOWPOS32 *winpos )
1707 POINT32 maxSize;
1708 if (winpos->flags & SWP_NOSIZE) return 0;
1709 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
1710 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
1712 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, NULL, NULL );
1713 winpos->cx = MIN( winpos->cx, maxSize.x );
1714 winpos->cy = MIN( winpos->cy, maxSize.y );
1716 return 0;
1720 /***********************************************************************
1721 * WINPOS_MoveWindowZOrder
1723 * Move a window in Z order, invalidating everything that needs it.
1724 * Only necessary for windows without associated X window.
1726 static void WINPOS_MoveWindowZOrder( HWND32 hwnd, HWND32 hwndAfter )
1728 BOOL32 movingUp;
1729 WND *pWndAfter, *pWndCur, *wndPtr = WIN_FindWndPtr( hwnd );
1731 /* We have two possible cases:
1732 * - The window is moving up: we have to invalidate all areas
1733 * of the window that were covered by other windows
1734 * - The window is moving down: we have to invalidate areas
1735 * of other windows covered by this one.
1738 if (hwndAfter == HWND_TOP)
1740 movingUp = TRUE;
1742 else if (hwndAfter == HWND_BOTTOM)
1744 if (!wndPtr->next) return; /* Already at the bottom */
1745 movingUp = FALSE;
1747 else
1749 if (!(pWndAfter = WIN_FindWndPtr( hwndAfter ))) return;
1750 if (wndPtr->next == pWndAfter) return; /* Already placed right */
1752 /* Determine which window we encounter first in Z-order */
1753 pWndCur = wndPtr->parent->child;
1754 while ((pWndCur != wndPtr) && (pWndCur != pWndAfter))
1755 pWndCur = pWndCur->next;
1756 movingUp = (pWndCur == pWndAfter);
1759 if (movingUp)
1761 WND *pWndPrevAfter = wndPtr->next;
1762 WIN_UnlinkWindow( hwnd );
1763 WIN_LinkWindow( hwnd, hwndAfter );
1764 pWndCur = wndPtr->next;
1765 while (pWndCur != pWndPrevAfter)
1767 RECT32 rect = { pWndCur->rectWindow.left,
1768 pWndCur->rectWindow.top,
1769 pWndCur->rectWindow.right,
1770 pWndCur->rectWindow.bottom };
1771 OffsetRect32( &rect, -wndPtr->rectClient.left,
1772 -wndPtr->rectClient.top );
1773 PAINT_RedrawWindow( hwnd, &rect, 0, RDW_INVALIDATE | RDW_ALLCHILDREN |
1774 RDW_FRAME | RDW_ERASE, 0 );
1775 pWndCur = pWndCur->next;
1778 else /* Moving down */
1780 pWndCur = wndPtr->next;
1781 WIN_UnlinkWindow( hwnd );
1782 WIN_LinkWindow( hwnd, hwndAfter );
1783 while (pWndCur != wndPtr)
1785 RECT32 rect = { pWndCur->rectWindow.left,
1786 pWndCur->rectWindow.top,
1787 pWndCur->rectWindow.right,
1788 pWndCur->rectWindow.bottom };
1789 OffsetRect32( &rect, -pWndCur->rectClient.left,
1790 -pWndCur->rectClient.top );
1791 PAINT_RedrawWindow( pWndCur->hwndSelf, &rect, 0, RDW_INVALIDATE |
1792 RDW_ALLCHILDREN | RDW_FRAME | RDW_ERASE, 0 );
1793 pWndCur = pWndCur->next;
1798 /***********************************************************************
1799 * WINPOS_ReorderOwnedPopups
1801 * fix Z order taking into account owned popups -
1802 * basically we need to maintain them above owner window
1804 HWND32 WINPOS_ReorderOwnedPopups(HWND32 hwndInsertAfter,WND* wndPtr,WORD flags)
1806 WND* w = WIN_GetDesktop()->child;
1808 if( wndPtr->dwStyle & WS_POPUP && wndPtr->owner )
1810 /* implement "local z-order" between the top and owner window */
1812 HWND32 hwndLocalPrev = HWND_TOP;
1814 if( hwndInsertAfter != HWND_TOP )
1816 while( w != wndPtr->owner )
1818 if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
1819 if( hwndLocalPrev == hwndInsertAfter ) break;
1820 w = w->next;
1822 hwndInsertAfter = hwndLocalPrev;
1826 else if( wndPtr->dwStyle & WS_CHILD ) return hwndInsertAfter;
1828 w = WIN_GetDesktop()->child;
1829 while( w )
1831 if( w == wndPtr ) break;
1833 if( w->dwStyle & WS_POPUP && w->owner == wndPtr )
1835 SetWindowPos32(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1836 SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
1837 hwndInsertAfter = w->hwndSelf;
1839 w = w->next;
1842 return hwndInsertAfter;
1845 /***********************************************************************
1846 * WINPOS_SizeMoveClean
1848 * Make window look nice without excessive repainting
1850 * the pain:
1852 * visible regions are in window coordinates
1853 * update regions are in window client coordinates
1854 * client and window rectangles are in parent client coordinates
1856 * FIXME: Move visible and update regions to the same coordinate system
1857 * (either parent client or window). This is a lot of work though.
1859 static UINT32 WINPOS_SizeMoveClean( WND* Wnd, HRGN32 oldVisRgn,
1860 LPRECT32 lpOldWndRect,
1861 LPRECT32 lpOldClientRect, UINT32 uFlags )
1863 HRGN32 newVisRgn = DCE_GetVisRgn(Wnd->hwndSelf,DCX_WINDOW | DCX_CLIPSIBLINGS);
1864 HRGN32 dirtyRgn = CreateRectRgn32(0,0,0,0);
1865 int other, my;
1867 TRACE(win,"cleaning up...new wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i)\n",
1868 Wnd->rectWindow.left, Wnd->rectWindow.top,
1869 Wnd->rectWindow.right, Wnd->rectWindow.bottom,
1870 lpOldWndRect->left, lpOldWndRect->top,
1871 lpOldWndRect->right, lpOldWndRect->bottom);
1872 TRACE(win,"\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
1873 Wnd->rectClient.left, Wnd->rectClient.top,
1874 Wnd->rectClient.right, Wnd->rectClient.bottom,
1875 lpOldClientRect->left, lpOldClientRect->top,
1876 lpOldClientRect->right,lpOldClientRect->bottom );
1878 if( (lpOldWndRect->right - lpOldWndRect->left) != (Wnd->rectWindow.right - Wnd->rectWindow.left) ||
1879 (lpOldWndRect->bottom - lpOldWndRect->top) != (Wnd->rectWindow.bottom - Wnd->rectWindow.top) )
1880 uFlags |= SMC_DRAWFRAME;
1882 CombineRgn32( dirtyRgn, newVisRgn, 0, RGN_COPY);
1884 if( !(uFlags & SMC_NOCOPY) )
1885 CombineRgn32( newVisRgn, newVisRgn, oldVisRgn, RGN_AND );
1887 /* map regions to the parent client area */
1889 OffsetRgn32( dirtyRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
1890 OffsetRgn32( oldVisRgn, lpOldWndRect->left, lpOldWndRect->top );
1892 /* compute invalidated region outside Wnd - (in client coordinates of the parent window) */
1894 other = CombineRgn32(dirtyRgn, oldVisRgn, dirtyRgn, RGN_DIFF);
1896 /* map visible region to the Wnd client area */
1898 OffsetRgn32( newVisRgn, Wnd->rectWindow.left - Wnd->rectClient.left,
1899 Wnd->rectWindow.top - Wnd->rectClient.top );
1901 /* substract previously invalidated region from the Wnd visible region */
1903 my = (Wnd->hrgnUpdate > 1) ? CombineRgn32( newVisRgn, newVisRgn,
1904 Wnd->hrgnUpdate, RGN_DIFF)
1905 : COMPLEXREGION;
1907 if( uFlags & SMC_NOCOPY ) /* invalidate Wnd visible region */
1909 if (my != NULLREGION)
1910 PAINT_RedrawWindow( Wnd->hwndSelf, NULL, newVisRgn, RDW_INVALIDATE |
1911 RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE, RDW_C_USEHRGN );
1912 else if(uFlags & SMC_DRAWFRAME)
1913 Wnd->flags |= WIN_NEEDS_NCPAINT;
1915 else /* bitblt old client area */
1917 HDC32 hDC;
1918 int update;
1919 HRGN32 updateRgn;
1920 int xfrom,yfrom,xto,yto,width,height;
1922 if( uFlags & SMC_DRAWFRAME )
1924 /* copy only client area, frame will be redrawn anyway */
1926 xfrom = lpOldClientRect->left; yfrom = lpOldClientRect->top;
1927 xto = Wnd->rectClient.left; yto = Wnd->rectClient.top;
1928 width = lpOldClientRect->right - xfrom; height = lpOldClientRect->bottom - yfrom;
1929 updateRgn = CreateRectRgn32( 0, 0, width, height );
1930 CombineRgn32( newVisRgn, newVisRgn, updateRgn, RGN_AND );
1931 SetRectRgn32( updateRgn, 0, 0, Wnd->rectClient.right - xto,
1932 Wnd->rectClient.bottom - yto );
1934 else
1936 xfrom = lpOldWndRect->left; yfrom = lpOldWndRect->top;
1937 xto = Wnd->rectWindow.left; yto = Wnd->rectWindow.top;
1938 width = lpOldWndRect->right - xfrom; height = lpOldWndRect->bottom - yfrom;
1939 updateRgn = CreateRectRgn32( xto - Wnd->rectClient.left,
1940 yto - Wnd->rectClient.top,
1941 Wnd->rectWindow.right - Wnd->rectClient.left,
1942 Wnd->rectWindow.bottom - Wnd->rectClient.top );
1945 CombineRgn32( newVisRgn, newVisRgn, updateRgn, RGN_AND );
1947 /* substract new visRgn from target rect to get a region that won't be copied */
1949 update = CombineRgn32( updateRgn, updateRgn, newVisRgn, RGN_DIFF );
1951 /* Blt valid bits using parent window DC */
1953 if( my != NULLREGION && (xfrom != xto || yfrom != yto) )
1956 /* compute clipping region in parent client coordinates */
1958 OffsetRgn32( newVisRgn, Wnd->rectClient.left, Wnd->rectClient.top );
1959 CombineRgn32( oldVisRgn, oldVisRgn, newVisRgn, RGN_OR );
1961 hDC = GetDCEx32( Wnd->parent->hwndSelf, oldVisRgn,
1962 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN |
1963 DCX_CACHE | DCX_CLIPSIBLINGS);
1965 BitBlt32( hDC, xto, yto, width, height, hDC, xfrom, yfrom, SRCCOPY );
1966 ReleaseDC32( Wnd->parent->hwndSelf, hDC);
1969 if( update != NULLREGION )
1970 PAINT_RedrawWindow( Wnd->hwndSelf, NULL, updateRgn, RDW_INVALIDATE |
1971 RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE, RDW_C_USEHRGN );
1972 else if( uFlags & SMC_DRAWFRAME ) Wnd->flags |= WIN_NEEDS_NCPAINT;
1973 DeleteObject32( updateRgn );
1976 /* erase uncovered areas */
1978 if( !(uFlags & SMC_NOPARENTERASE) && (other != NULLREGION ) )
1979 PAINT_RedrawWindow( Wnd->parent->hwndSelf, NULL, dirtyRgn,
1980 RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE, RDW_C_USEHRGN );
1981 DeleteObject32(dirtyRgn);
1982 DeleteObject32(newVisRgn);
1983 return uFlags;
1987 /***********************************************************************
1988 * WINPOS_FindDeskTopXWindow
1990 * Find the actual X window which needs be restacked.
1991 * Used by WINPOS_SetXWindowPos().
1993 static Window WINPOS_FindDeskTopXWindow( WND *wndPtr )
1995 if (!(wndPtr->flags & WIN_MANAGED))
1996 return wndPtr->window;
1997 else
1999 Window window, root, parent, *children;
2000 int nchildren;
2001 window = wndPtr->window;
2002 for (;;)
2004 TSXQueryTree( display, window, &root, &parent,
2005 &children, &nchildren );
2006 TSXFree( children );
2007 if (parent == root)
2008 return window;
2009 window = parent;
2014 /***********************************************************************
2015 * WINPOS_SetXWindowPos
2017 * SetWindowPos() for an X window. Used by the real SetWindowPos().
2019 static void WINPOS_SetXWindowPos( const WINDOWPOS32 *winpos )
2021 XWindowChanges winChanges;
2022 int changeMask = 0;
2023 WND *wndPtr = WIN_FindWndPtr( winpos->hwnd );
2025 if (!(winpos->flags & SWP_NOSIZE))
2027 winChanges.width = winpos->cx;
2028 winChanges.height = winpos->cy;
2029 changeMask |= CWWidth | CWHeight;
2031 /* Tweak dialog window size hints */
2033 if ((wndPtr->flags & WIN_MANAGED) &&
2034 (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME))
2036 XSizeHints *size_hints = TSXAllocSizeHints();
2038 if (size_hints)
2040 long supplied_return;
2042 TSXGetWMSizeHints( display, wndPtr->window, size_hints,
2043 &supplied_return, XA_WM_NORMAL_HINTS);
2044 size_hints->min_width = size_hints->max_width = winpos->cx;
2045 size_hints->min_height = size_hints->max_height = winpos->cy;
2046 TSXSetWMSizeHints( display, wndPtr->window, size_hints,
2047 XA_WM_NORMAL_HINTS );
2048 TSXFree(size_hints);
2052 if (!(winpos->flags & SWP_NOMOVE))
2054 winChanges.x = winpos->x;
2055 winChanges.y = winpos->y;
2056 changeMask |= CWX | CWY;
2058 if (!(winpos->flags & SWP_NOZORDER))
2060 winChanges.stack_mode = Below;
2061 changeMask |= CWStackMode;
2063 if (winpos->hwndInsertAfter == HWND_TOP) winChanges.stack_mode = Above;
2064 else if (winpos->hwndInsertAfter != HWND_BOTTOM)
2066 WND* insertPtr = WIN_FindWndPtr( winpos->hwndInsertAfter );
2067 Window stack[2];
2069 stack[0] = WINPOS_FindDeskTopXWindow( insertPtr );
2070 stack[1] = WINPOS_FindDeskTopXWindow( wndPtr );
2072 /* for stupid window managers (i.e. all of them) */
2074 TSXRestackWindows(display, stack, 2);
2075 changeMask &= ~CWStackMode;
2078 if (!changeMask) return;
2080 TSXReconfigureWMWindow( display, wndPtr->window, 0, changeMask, &winChanges );
2084 /***********************************************************************
2085 * SetWindowPos (USER.232)
2087 BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
2088 INT16 x, INT16 y, INT16 cx, INT16 cy, WORD flags)
2090 return SetWindowPos32(hwnd,(INT32)(INT16)hwndInsertAfter,x,y,cx,cy,flags);
2093 /***********************************************************************
2094 * SetWindowPos (USER32.520)
2096 BOOL32 WINAPI SetWindowPos32( HWND32 hwnd, HWND32 hwndInsertAfter,
2097 INT32 x, INT32 y, INT32 cx, INT32 cy, WORD flags)
2099 WINDOWPOS32 winpos;
2100 WND * wndPtr;
2101 RECT32 newWindowRect, newClientRect, oldWindowRect;
2102 HRGN32 visRgn = 0;
2103 HWND32 tempInsertAfter= 0;
2104 int result = 0;
2105 UINT32 uFlags = 0;
2106 BOOL32 resync = FALSE;
2108 TRACE(win,"hwnd %04x, (%i,%i)-(%i,%i) flags %08x\n",
2109 hwnd, x, y, x+cx, y+cy, flags);
2110 /* Check window handle */
2112 if (hwnd == GetDesktopWindow32()) return FALSE;
2113 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2115 if(wndPtr->dwStyle & WS_VISIBLE)
2116 flags &= ~SWP_SHOWWINDOW;
2117 else
2119 uFlags |= SMC_NOPARENTERASE;
2120 flags &= ~SWP_HIDEWINDOW;
2121 if (!(flags & SWP_SHOWWINDOW)) flags |= SWP_NOREDRAW;
2124 /* Check for windows that may not be resized
2125 FIXME: this should be done only for Windows 3.0 programs
2126 if (flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW ) )
2127 flags |= SWP_NOSIZE | SWP_NOMOVE;
2129 /* Check dimensions */
2131 if (cx <= 0) cx = 1;
2132 if (cy <= 0) cy = 1;
2134 /* Check flags */
2136 if (hwnd == hwndActive) flags |= SWP_NOACTIVATE; /* Already active */
2137 if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
2138 (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
2139 flags |= SWP_NOSIZE; /* Already the right size */
2140 if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
2141 flags |= SWP_NOMOVE; /* Already the right position */
2143 /* Check hwndInsertAfter */
2145 if (!(flags & (SWP_NOZORDER | SWP_NOACTIVATE)))
2147 /* Ignore TOPMOST flags when activating a window */
2148 /* _and_ moving it in Z order. */
2149 if ((hwndInsertAfter == HWND_TOPMOST) ||
2150 (hwndInsertAfter == HWND_NOTOPMOST))
2151 hwndInsertAfter = HWND_TOP;
2153 /* TOPMOST not supported yet */
2154 if ((hwndInsertAfter == HWND_TOPMOST) ||
2155 (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
2157 /* hwndInsertAfter must be a sibling of the window */
2158 if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
2160 WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
2161 if( wnd->parent != wndPtr->parent ) return FALSE;
2162 if( wnd->next == wndPtr ) flags |= SWP_NOZORDER;
2164 else if (!(wndPtr->window))
2165 /* FIXME: the following optimization is no good for "X-ed" windows */
2166 if (hwndInsertAfter == HWND_TOP)
2167 flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
2168 else /* HWND_BOTTOM */
2169 flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
2171 /* Fill the WINDOWPOS structure */
2173 winpos.hwnd = hwnd;
2174 winpos.hwndInsertAfter = hwndInsertAfter;
2175 winpos.x = x;
2176 winpos.y = y;
2177 winpos.cx = cx;
2178 winpos.cy = cy;
2179 winpos.flags = flags;
2181 /* Send WM_WINDOWPOSCHANGING message */
2183 if (!(winpos.flags & SWP_NOSENDCHANGING))
2184 SendMessage32A( hwnd, WM_WINDOWPOSCHANGING, 0, (LPARAM)&winpos );
2186 /* Calculate new position and size */
2188 newWindowRect = wndPtr->rectWindow;
2189 newClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
2190 : wndPtr->rectClient;
2192 if (!(winpos.flags & SWP_NOSIZE))
2194 newWindowRect.right = newWindowRect.left + winpos.cx;
2195 newWindowRect.bottom = newWindowRect.top + winpos.cy;
2197 if (!(winpos.flags & SWP_NOMOVE))
2199 newWindowRect.left = winpos.x;
2200 newWindowRect.top = winpos.y;
2201 newWindowRect.right += winpos.x - wndPtr->rectWindow.left;
2202 newWindowRect.bottom += winpos.y - wndPtr->rectWindow.top;
2204 OffsetRect32( &newClientRect, winpos.x - wndPtr->rectWindow.left,
2205 winpos.y - wndPtr->rectWindow.top );
2208 winpos.flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
2210 /* Reposition window in Z order */
2212 if (!(winpos.flags & SWP_NOZORDER))
2214 /* reorder owned popups if hwnd is top-level window
2216 if( wndPtr->parent == WIN_GetDesktop() )
2217 hwndInsertAfter = WINPOS_ReorderOwnedPopups( hwndInsertAfter,
2218 wndPtr, winpos.flags );
2220 if (wndPtr->window)
2222 WIN_UnlinkWindow( winpos.hwnd );
2223 WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
2225 else WINPOS_MoveWindowZOrder( winpos.hwnd, hwndInsertAfter );
2228 if ( !wndPtr->window && !(winpos.flags & SWP_NOREDRAW) &&
2229 ((winpos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED))
2230 != (SWP_NOMOVE | SWP_NOSIZE)) )
2231 visRgn = DCE_GetVisRgn(hwnd, DCX_WINDOW | DCX_CLIPSIBLINGS);
2234 /* Send WM_NCCALCSIZE message to get new client area */
2235 if( (winpos.flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
2237 result = WINPOS_SendNCCalcSize( winpos.hwnd, TRUE, &newWindowRect,
2238 &wndPtr->rectWindow, &wndPtr->rectClient,
2239 &winpos, &newClientRect );
2241 /* FIXME: WVR_ALIGNxxx */
2243 if( newClientRect.left != wndPtr->rectClient.left ||
2244 newClientRect.top != wndPtr->rectClient.top )
2245 winpos.flags &= ~SWP_NOCLIENTMOVE;
2247 if( (newClientRect.right - newClientRect.left !=
2248 wndPtr->rectClient.right - wndPtr->rectClient.left) ||
2249 (newClientRect.bottom - newClientRect.top !=
2250 wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
2251 winpos.flags &= ~SWP_NOCLIENTSIZE;
2253 else
2254 if( !(flags & SWP_NOMOVE) && (newClientRect.left != wndPtr->rectClient.left ||
2255 newClientRect.top != wndPtr->rectClient.top) )
2256 winpos.flags &= ~SWP_NOCLIENTMOVE;
2258 /* Update active DCEs
2259 * TODO: Optimize conditions that trigger DCE update.
2262 if( (((winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) &&
2263 wndPtr->dwStyle & WS_VISIBLE) ||
2264 (flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
2266 RECT32 rect;
2268 UnionRect32(&rect, &newWindowRect, &wndPtr->rectWindow);
2269 DCE_InvalidateDCE(wndPtr, &rect);
2272 /* change geometry */
2274 oldWindowRect = wndPtr->rectWindow;
2276 if (wndPtr->window)
2278 RECT32 oldClientRect = wndPtr->rectClient;
2280 tempInsertAfter = winpos.hwndInsertAfter;
2282 winpos.hwndInsertAfter = hwndInsertAfter;
2284 /* postpone geometry change */
2286 if( !(flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW)) )
2288 WINPOS_SetXWindowPos( &winpos );
2289 winpos.hwndInsertAfter = tempInsertAfter;
2291 else uFlags |= SMC_SETXPOS;
2293 wndPtr->rectWindow = newWindowRect;
2294 wndPtr->rectClient = newClientRect;
2296 if( !(flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW)) )
2297 if( (oldClientRect.left - oldWindowRect.left !=
2298 newClientRect.left - newWindowRect.left) ||
2299 (oldClientRect.top - oldWindowRect.top !=
2300 newClientRect.top - newWindowRect.top) ||
2301 winpos.flags & SWP_NOCOPYBITS )
2303 PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, 0, RDW_INVALIDATE |
2304 RDW_ALLCHILDREN | RDW_FRAME | RDW_ERASE, 0 );
2305 else
2306 if( winpos.flags & SWP_FRAMECHANGED )
2308 WORD wErase = 0;
2309 RECT32 rect;
2311 if( oldClientRect.right > newClientRect.right )
2313 rect.left = newClientRect.right; rect.top = newClientRect.top;
2314 rect.right = oldClientRect.right; rect.bottom = newClientRect.bottom;
2315 wErase = 1;
2316 PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, 0,
2317 RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN, 0 );
2319 if( oldClientRect.bottom > newClientRect.bottom )
2321 rect.left = newClientRect.left; rect.top = newClientRect.bottom;
2322 rect.right = (wErase)?oldClientRect.right:newClientRect.right;
2323 rect.bottom = oldClientRect.bottom;
2324 wErase = 1;
2325 PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, 0,
2326 RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN, 0 );
2328 if( !wErase ) wndPtr->flags |= WIN_NEEDS_NCPAINT;
2331 else
2333 RECT32 oldClientRect = wndPtr->rectClient;
2335 wndPtr->rectWindow = newWindowRect;
2336 wndPtr->rectClient = newClientRect;
2338 if( oldClientRect.bottom - oldClientRect.top ==
2339 newClientRect.bottom - newClientRect.top ) result &= ~WVR_VREDRAW;
2341 if( oldClientRect.right - oldClientRect.left ==
2342 newClientRect.right - newClientRect.left ) result &= ~WVR_HREDRAW;
2344 if( !(flags & (SWP_NOREDRAW | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
2346 uFlags |= ((winpos.flags & SWP_NOCOPYBITS) ||
2347 (result >= WVR_HREDRAW && result < WVR_VALIDRECTS)) ? SMC_NOCOPY : 0;
2348 uFlags |= (winpos.flags & SWP_FRAMECHANGED) ? SMC_DRAWFRAME : 0;
2350 if( (winpos.flags & SWP_AGG_NOGEOMETRYCHANGE) != SWP_AGG_NOGEOMETRYCHANGE )
2351 uFlags = WINPOS_SizeMoveClean(wndPtr, visRgn, &oldWindowRect,
2352 &oldClientRect, uFlags);
2353 else
2355 /* adjust frame and do not erase parent */
2357 if( winpos.flags & SWP_FRAMECHANGED ) wndPtr->flags |= WIN_NEEDS_NCPAINT;
2358 if( winpos.flags & SWP_NOZORDER ) uFlags |= SMC_NOPARENTERASE;
2361 DeleteObject32(visRgn);
2364 if (flags & SWP_SHOWWINDOW)
2366 wndPtr->dwStyle |= WS_VISIBLE;
2367 if (wndPtr->window)
2369 HWND32 focus, curr;
2371 if( uFlags & SMC_SETXPOS )
2373 WINPOS_SetXWindowPos( &winpos );
2374 winpos.hwndInsertAfter = tempInsertAfter;
2376 TSXMapWindow( display, wndPtr->window );
2377 if (wndPtr->flags & WIN_MANAGED) resync = TRUE;
2379 /* If focus was set to an unmapped window, reset X focus now */
2380 focus = curr = GetFocus32();
2381 while (curr) {
2382 if (curr == hwnd) {
2383 SetFocus32( 0 );
2384 SetFocus32( focus );
2385 break;
2387 curr = GetParent32(curr);
2390 else
2392 if (!(flags & SWP_NOREDRAW))
2393 PAINT_RedrawWindow( winpos.hwnd, NULL, 0,
2394 RDW_INVALIDATE | RDW_ALLCHILDREN |
2395 RDW_FRAME | RDW_ERASENOW | RDW_ERASE, 0 );
2398 else if (flags & SWP_HIDEWINDOW)
2400 wndPtr->dwStyle &= ~WS_VISIBLE;
2401 if (wndPtr->window)
2403 TSXUnmapWindow( display, wndPtr->window );
2404 if( uFlags & SMC_SETXPOS )
2406 WINPOS_SetXWindowPos( &winpos );
2407 winpos.hwndInsertAfter = tempInsertAfter;
2410 else
2412 if (!(flags & SWP_NOREDRAW))
2413 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, &oldWindowRect,
2414 0, RDW_INVALIDATE | RDW_ALLCHILDREN |
2415 RDW_ERASE | RDW_ERASENOW, 0 );
2416 uFlags |= SMC_NOPARENTERASE;
2419 if ((winpos.hwnd == GetFocus32()) ||
2420 IsChild32( winpos.hwnd, GetFocus32()))
2422 /* Revert focus to parent */
2423 SetFocus32( GetParent32(winpos.hwnd) );
2425 if (hwnd == CARET_GetHwnd()) DestroyCaret32();
2427 if (winpos.hwnd == hwndActive)
2428 WINPOS_ActivateOtherWindow( wndPtr );
2431 /* Activate the window */
2433 if (!(flags & SWP_NOACTIVATE))
2434 WINPOS_ChangeActiveWindow( winpos.hwnd, FALSE );
2436 /* Repaint the window */
2438 if (wndPtr->window) EVENT_Synchronize(); /* Wait for all expose events */
2440 if (!GetCapture32())
2441 EVENT_DummyMotionNotify(); /* Simulate a mouse event to set the cursor */
2443 if (!(flags & SWP_DEFERERASE) && !(uFlags & SMC_NOPARENTERASE) )
2444 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0, RDW_ALLCHILDREN | RDW_ERASENOW, 0 );
2445 else if( wndPtr->parent == WIN_GetDesktop() && wndPtr->parent->flags & WIN_NEEDS_ERASEBKGND )
2446 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0, RDW_NOCHILDREN | RDW_ERASENOW, 0 );
2448 /* And last, send the WM_WINDOWPOSCHANGED message */
2450 TRACE(win,"\tstatus flags = %04x\n", winpos.flags & SWP_AGG_STATUSFLAGS);
2452 if ( resync ||
2453 (((winpos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) &&
2454 !(winpos.flags & SWP_NOSENDCHANGING)) )
2456 SendMessage32A( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
2457 if (resync) EVENT_Synchronize ();
2460 return TRUE;
2464 /***********************************************************************
2465 * BeginDeferWindowPos16 (USER.259)
2467 HDWP16 WINAPI BeginDeferWindowPos16( INT16 count )
2469 return BeginDeferWindowPos32( count );
2473 /***********************************************************************
2474 * BeginDeferWindowPos32 (USER32.9)
2476 HDWP32 WINAPI BeginDeferWindowPos32( INT32 count )
2478 HDWP32 handle;
2479 DWP *pDWP;
2481 if (count <= 0) return 0;
2482 handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS32) );
2483 if (!handle) return 0;
2484 pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
2485 pDWP->actualCount = 0;
2486 pDWP->suggestedCount = count;
2487 pDWP->valid = TRUE;
2488 pDWP->wMagic = DWP_MAGIC;
2489 pDWP->hwndParent = 0;
2490 return handle;
2494 /***********************************************************************
2495 * DeferWindowPos16 (USER.260)
2497 HDWP16 WINAPI DeferWindowPos16( HDWP16 hdwp, HWND16 hwnd, HWND16 hwndAfter,
2498 INT16 x, INT16 y, INT16 cx, INT16 cy,
2499 UINT16 flags )
2501 return DeferWindowPos32( hdwp, hwnd, (INT32)(INT16)hwndAfter,
2502 x, y, cx, cy, flags );
2506 /***********************************************************************
2507 * DeferWindowPos32 (USER32.128)
2509 HDWP32 WINAPI DeferWindowPos32( HDWP32 hdwp, HWND32 hwnd, HWND32 hwndAfter,
2510 INT32 x, INT32 y, INT32 cx, INT32 cy,
2511 UINT32 flags )
2513 DWP *pDWP;
2514 int i;
2515 HDWP32 newhdwp = hdwp;
2516 /* HWND32 parent; */
2517 WND *pWnd;
2519 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
2520 if (!pDWP) return 0;
2521 if (hwnd == GetDesktopWindow32()) return 0;
2523 if (!(pWnd=WIN_FindWndPtr( hwnd ))) {
2524 USER_HEAP_FREE( hdwp );
2525 return 0;
2528 /* Numega Bounds Checker Demo dislikes the following code.
2529 In fact, I've not been able to find any "same parent" requirement in any docu
2530 [AM 980509]
2532 #if 0
2533 /* All the windows of a DeferWindowPos() must have the same parent */
2534 parent = pWnd->parent->hwndSelf;
2535 if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
2536 else if (parent != pDWP->hwndParent)
2538 USER_HEAP_FREE( hdwp );
2539 return 0;
2541 #endif
2543 for (i = 0; i < pDWP->actualCount; i++)
2545 if (pDWP->winPos[i].hwnd == hwnd)
2547 /* Merge with the other changes */
2548 if (!(flags & SWP_NOZORDER))
2550 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
2552 if (!(flags & SWP_NOMOVE))
2554 pDWP->winPos[i].x = x;
2555 pDWP->winPos[i].y = y;
2557 if (!(flags & SWP_NOSIZE))
2559 pDWP->winPos[i].cx = cx;
2560 pDWP->winPos[i].cy = cy;
2562 pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
2563 SWP_NOZORDER | SWP_NOREDRAW |
2564 SWP_NOACTIVATE | SWP_NOCOPYBITS|
2565 SWP_NOOWNERZORDER);
2566 pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
2567 SWP_FRAMECHANGED);
2568 return hdwp;
2571 if (pDWP->actualCount >= pDWP->suggestedCount)
2573 newhdwp = USER_HEAP_REALLOC( hdwp,
2574 sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS32) );
2575 if (!newhdwp) return 0;
2576 pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
2577 pDWP->suggestedCount++;
2579 pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
2580 pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
2581 pDWP->winPos[pDWP->actualCount].x = x;
2582 pDWP->winPos[pDWP->actualCount].y = y;
2583 pDWP->winPos[pDWP->actualCount].cx = cx;
2584 pDWP->winPos[pDWP->actualCount].cy = cy;
2585 pDWP->winPos[pDWP->actualCount].flags = flags;
2586 pDWP->actualCount++;
2587 return newhdwp;
2591 /***********************************************************************
2592 * EndDeferWindowPos16 (USER.261)
2594 BOOL16 WINAPI EndDeferWindowPos16( HDWP16 hdwp )
2596 return EndDeferWindowPos32( hdwp );
2600 /***********************************************************************
2601 * EndDeferWindowPos32 (USER32.173)
2603 BOOL32 WINAPI EndDeferWindowPos32( HDWP32 hdwp )
2605 DWP *pDWP;
2606 WINDOWPOS32 *winpos;
2607 BOOL32 res = TRUE;
2608 int i;
2610 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
2611 if (!pDWP) return FALSE;
2612 for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
2614 if (!(res = SetWindowPos32( winpos->hwnd, winpos->hwndInsertAfter,
2615 winpos->x, winpos->y, winpos->cx,
2616 winpos->cy, winpos->flags ))) break;
2618 USER_HEAP_FREE( hdwp );
2619 return res;
2623 /***********************************************************************
2624 * TileChildWindows (USER.199)
2626 void WINAPI TileChildWindows( HWND16 parent, WORD action )
2628 FIXME(win, "(%04x, %d): stub\n", parent, action);
2631 /***********************************************************************
2632 * CascageChildWindows (USER.198)
2634 void WINAPI CascadeChildWindows( HWND16 parent, WORD action )
2636 FIXME(win, "(%04x, %d): stub\n", parent, action);