2 * Window position related functions.
4 * Copyright 1993, 1994, 1995 Alexandre Julliard
7 #include "sysmetrics.h"
12 #include "nonclient.h"
14 /* #define DEBUG_WIN */
17 static HWND hwndActive = 0; /* Currently active window */
20 /***********************************************************************
23 * Find a suitable place for an iconic window.
24 * The new position is stored into wndPtr->ptIconPos.
26 static void WINPOS_FindIconPos( HWND hwnd )
29 short x, y, xspacing, yspacing;
30 WND * wndPtr = WIN_FindWndPtr( hwnd );
33 GetClientRect( wndPtr->hwndParent, &rectParent );
34 if ((wndPtr->ptIconPos.x >= rectParent.left) &&
35 (wndPtr->ptIconPos.x + SYSMETRICS_CXICON < rectParent.right) &&
36 (wndPtr->ptIconPos.y >= rectParent.top) &&
37 (wndPtr->ptIconPos.y + SYSMETRICS_CYICON < rectParent.bottom))
38 return; /* The icon already has a suitable position */
40 xspacing = yspacing = 70; /* FIXME: This should come from WIN.INI */
41 y = rectParent.bottom;
44 for (x = rectParent.left; x<=rectParent.right-xspacing; x += xspacing)
46 /* Check if another icon already occupies this spot */
47 HWND hwndChild = GetWindow( wndPtr->hwndParent, GW_CHILD );
50 WND *childPtr = WIN_FindWndPtr( hwndChild );
51 if ((childPtr->dwStyle & WS_MINIMIZE) && (hwndChild != hwnd))
53 if ((childPtr->rectWindow.left < x + xspacing) &&
54 (childPtr->rectWindow.right >= x) &&
55 (childPtr->rectWindow.top <= y) &&
56 (childPtr->rectWindow.bottom > y - yspacing))
57 break; /* There's a window in there */
60 hwndChild = childPtr->hwndNext;
64 /* No window was found, so it's OK for us */
65 wndPtr->ptIconPos.x = x + (xspacing - SYSMETRICS_CXICON) / 2;
66 wndPtr->ptIconPos.y = y - (yspacing + SYSMETRICS_CYICON) / 2;
75 /***********************************************************************
76 * ArrangeIconicWindows (USER.170)
78 WORD ArrangeIconicWindows( HWND parent )
82 short x, y, xspacing, yspacing;
84 GetClientRect( parent, &rectParent );
86 y = rectParent.bottom;
87 xspacing = yspacing = 70; /* FIXME: This should come from WIN.INI */
88 hwndChild = GetWindow( parent, GW_CHILD );
91 if (IsIconic( hwndChild ))
93 SetWindowPos( hwndChild, 0, x + (xspacing - SYSMETRICS_CXICON) / 2,
94 y - (yspacing + SYSMETRICS_CYICON) / 2, 0, 0,
95 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
96 if (x <= rectParent.right - xspacing) x += xspacing;
103 hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
109 /***********************************************************************
110 * GetWindowRect (USER.32)
112 void GetWindowRect( HWND hwnd, LPRECT rect )
114 WND * wndPtr = WIN_FindWndPtr( hwnd );
117 *rect = wndPtr->rectWindow;
118 if (wndPtr->dwStyle & WS_CHILD)
119 MapWindowPoints( wndPtr->hwndParent, 0, (POINT *)rect, 2 );
123 /***********************************************************************
124 * GetClientRect (USER.33)
126 void GetClientRect( HWND hwnd, LPRECT rect )
128 WND * wndPtr = WIN_FindWndPtr( hwnd );
130 rect->left = rect->top = rect->right = rect->bottom = 0;
133 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
134 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
139 /*******************************************************************
140 * ClientToScreen (USER.28)
142 void ClientToScreen( HWND hwnd, LPPOINT lppnt )
144 MapWindowPoints( hwnd, 0, lppnt, 1 );
148 /*******************************************************************
149 * ScreenToClient (USER.29)
151 void ScreenToClient( HWND hwnd, LPPOINT lppnt )
153 MapWindowPoints( 0, hwnd, lppnt, 1 );
157 /*******************************************************************
158 * WindowFromPoint (USER.30)
160 HWND WindowFromPoint( POINT pt )
163 HWND hwnd = GetDesktopWindow();
167 /* If point is in window, and window is visible, */
168 /* not disabled and not transparent, then explore */
169 /* its children. Otherwise, go to the next window. */
171 WND *wndPtr = WIN_FindWndPtr( hwnd );
172 if ((pt.x >= wndPtr->rectWindow.left) &&
173 (pt.x < wndPtr->rectWindow.right) &&
174 (pt.y >= wndPtr->rectWindow.top) &&
175 (pt.y < wndPtr->rectWindow.bottom) &&
176 !(wndPtr->dwStyle & WS_DISABLED) &&
177 (wndPtr->dwStyle & WS_VISIBLE) &&
178 !(wndPtr->dwExStyle & WS_EX_TRANSPARENT))
181 /* If window is minimized, ignore its children */
182 if (wndPtr->dwStyle & WS_MINIMIZE) break;
183 pt.x -= wndPtr->rectClient.left;
184 pt.y -= wndPtr->rectClient.top;
185 hwnd = wndPtr->hwndChild;
187 else hwnd = wndPtr->hwndNext;
193 /*******************************************************************
194 * ChildWindowFromPoint (USER.191)
196 HWND ChildWindowFromPoint( HWND hwndParent, POINT pt )
201 GetWindowRect( hwndParent, &rect );
202 if (!PtInRect( &rect, pt )) return 0;
203 hwnd = GetTopWindow( hwndParent );
206 GetWindowRect( hwnd, &rect );
207 if (PtInRect( &rect, pt )) return hwnd;
208 hwnd = GetWindow( hwnd, GW_HWNDNEXT );
214 /*******************************************************************
215 * MapWindowPoints (USER.258)
217 void MapWindowPoints( HWND hwndFrom, HWND hwndTo, LPPOINT lppt, WORD count )
221 POINT origin = { 0, 0 };
224 /* Translate source window origin to screen coords */
227 wndPtr = WIN_FindWndPtr( hwndFrom );
228 origin.x += wndPtr->rectClient.left;
229 origin.y += wndPtr->rectClient.top;
230 hwndFrom = (wndPtr->dwStyle & WS_CHILD) ? wndPtr->hwndParent : 0;
233 /* Translate origin to destination window coords */
236 wndPtr = WIN_FindWndPtr( hwndTo );
237 origin.x -= wndPtr->rectClient.left;
238 origin.y -= wndPtr->rectClient.top;
239 hwndTo = (wndPtr->dwStyle & WS_CHILD) ? wndPtr->hwndParent : 0;
242 /* Translate points */
243 for (i = 0, curpt = lppt; i < count; i++, curpt++)
245 curpt->x += origin.x;
246 curpt->y += origin.y;
251 /***********************************************************************
254 BOOL IsIconic(HWND hWnd)
256 WND * wndPtr = WIN_FindWndPtr(hWnd);
257 if (wndPtr == NULL) return FALSE;
258 return (wndPtr->dwStyle & WS_MINIMIZE) != 0;
262 /***********************************************************************
263 * IsZoomed (USER.272)
265 BOOL IsZoomed(HWND hWnd)
267 WND * wndPtr = WIN_FindWndPtr(hWnd);
268 if (wndPtr == NULL) return FALSE;
269 return (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
273 /*******************************************************************
274 * GetActiveWindow (USER.60)
276 HWND GetActiveWindow()
282 /*******************************************************************
283 * SetActiveWindow (USER.59)
285 HWND SetActiveWindow( HWND hwnd )
287 HWND prev = hwndActive;
288 WND *wndPtr = WIN_FindWndPtr( hwnd );
289 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD)) return 0;
290 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
295 /***********************************************************************
296 * BringWindowToTop (USER.45)
298 BOOL BringWindowToTop( HWND hwnd )
300 return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
304 /***********************************************************************
305 * MoveWindow (USER.56)
307 BOOL MoveWindow( HWND hwnd, short x, short y, short cx, short cy, BOOL repaint)
309 int flags = SWP_NOZORDER | SWP_NOACTIVATE;
310 if (!repaint) flags |= SWP_NOREDRAW;
311 dprintf_win(stddeb, "MoveWindow: %d %d,%d %dx%d %d\n",
312 hwnd, x, y, cx, cy, repaint );
313 return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
317 /***********************************************************************
318 * ShowWindow (USER.42)
320 BOOL ShowWindow( HWND hwnd, int cmd )
322 WND * wndPtr = WIN_FindWndPtr( hwnd );
326 short x = 0, y = 0, cx = 0, cy = 0;
328 if (!wndPtr) return FALSE;
330 dprintf_win(stddeb,"ShowWindow: hwnd=%04X, cmd=%d\n", hwnd, cmd);
332 wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
337 swpflags |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
338 SWP_NOACTIVATE | SWP_NOZORDER;
341 case SW_SHOWMINNOACTIVE:
342 swpflags |= SWP_NOACTIVATE | SWP_NOZORDER;
344 case SW_SHOWMINIMIZED:
345 swpflags |= SWP_SHOWWINDOW;
348 swpflags |= SWP_FRAMECHANGED;
349 if (!(wndPtr->dwStyle & WS_MINIMIZE))
351 if (wndPtr->dwStyle & WS_MAXIMIZE)
353 wndPtr->flags |= WIN_RESTORE_MAX;
354 wndPtr->dwStyle &= ~WS_MAXIMIZE;
358 wndPtr->flags &= ~WIN_RESTORE_MAX;
359 wndPtr->rectNormal = wndPtr->rectWindow;
361 wndPtr->dwStyle |= WS_MINIMIZE;
362 WINPOS_FindIconPos( hwnd );
363 x = wndPtr->ptIconPos.x;
364 y = wndPtr->ptIconPos.y;
365 cx = SYSMETRICS_CXICON;
366 cy = SYSMETRICS_CYICON;
368 else swpflags |= SWP_NOSIZE | SWP_NOMOVE;
371 case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE: */
372 swpflags |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
373 if (!(wndPtr->dwStyle & WS_MAXIMIZE))
375 /* Store the current position and find the maximized size */
376 if (!(wndPtr->dwStyle & WS_MINIMIZE))
377 wndPtr->rectNormal = wndPtr->rectWindow;
378 NC_GetMinMaxInfo( hwnd, &maxSize,
379 &wndPtr->ptMaxPos, NULL, NULL );
380 x = wndPtr->ptMaxPos.x;
381 y = wndPtr->ptMaxPos.y;
384 wndPtr->dwStyle &= ~WS_MINIMIZE;
385 wndPtr->dwStyle |= WS_MAXIMIZE;
387 else swpflags |= SWP_NOSIZE | SWP_NOMOVE;
391 swpflags |= SWP_NOACTIVATE | SWP_NOZORDER;
394 swpflags |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
397 case SW_SHOWNOACTIVATE:
398 swpflags |= SWP_NOZORDER;
399 if (GetActiveWindow()) swpflags |= SWP_NOACTIVATE;
401 case SW_SHOWNORMAL: /* same as SW_NORMAL: */
403 swpflags |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
404 if (wndPtr->dwStyle & WS_MINIMIZE)
406 wndPtr->ptIconPos.x = wndPtr->rectWindow.left;
407 wndPtr->ptIconPos.y = wndPtr->rectWindow.top;
408 wndPtr->dwStyle &= ~WS_MINIMIZE;
409 if (wndPtr->flags & WIN_RESTORE_MAX)
411 /* Restore to maximized position */
412 NC_GetMinMaxInfo( hwnd, &maxSize, &wndPtr->ptMaxPos,
414 x = wndPtr->ptMaxPos.x;
415 y = wndPtr->ptMaxPos.y;
418 wndPtr->dwStyle |= WS_MAXIMIZE;
420 else /* Restore to normal position */
422 x = wndPtr->rectNormal.left;
423 y = wndPtr->rectNormal.top;
424 cx = wndPtr->rectNormal.right - wndPtr->rectNormal.left;
425 cy = wndPtr->rectNormal.bottom - wndPtr->rectNormal.top;
428 else if (wndPtr->dwStyle & WS_MAXIMIZE)
430 wndPtr->ptMaxPos.x = wndPtr->rectWindow.left;
431 wndPtr->ptMaxPos.y = wndPtr->rectWindow.top;
432 wndPtr->dwStyle &= ~WS_MAXIMIZE;
433 x = wndPtr->rectNormal.left;
434 y = wndPtr->rectNormal.top;
435 cx = wndPtr->rectNormal.right - wndPtr->rectNormal.left;
436 cy = wndPtr->rectNormal.bottom - wndPtr->rectNormal.top;
438 else swpflags |= SWP_NOSIZE | SWP_NOMOVE;
442 SendMessage( hwnd, WM_SHOWWINDOW, (cmd != SW_HIDE), 0 );
443 SetWindowPos( hwnd, HWND_TOP, x, y, cx, cy, swpflags );
445 /* Send WM_SIZE and WM_MOVE messages if not already done */
446 if (!(wndPtr->flags & WIN_GOT_SIZEMSG))
448 int wParam = SIZE_RESTORED;
449 if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
450 else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
451 wndPtr->flags |= WIN_GOT_SIZEMSG;
452 SendMessage( hwnd, WM_SIZE, wParam,
453 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
454 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
455 SendMessage( hwnd, WM_MOVE, 0,
456 MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
463 /***********************************************************************
464 * GetInternalWindowPos (USER.460)
466 WORD GetInternalWindowPos( HWND hwnd, LPRECT rectWnd, LPPOINT ptIcon )
468 WINDOWPLACEMENT wndpl;
469 if (!GetWindowPlacement( hwnd, &wndpl )) return 0;
470 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
471 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
472 return wndpl.showCmd;
476 /***********************************************************************
477 * SetInternalWindowPos (USER.461)
479 void SetInternalWindowPos( HWND hwnd, WORD showCmd, LPRECT rect, LPPOINT pt )
481 WINDOWPLACEMENT wndpl;
482 WND *wndPtr = WIN_FindWndPtr( hwnd );
484 wndpl.length = sizeof(wndpl);
485 wndpl.flags = (pt != NULL) ? WPF_SETMINPOSITION : 0;
486 wndpl.showCmd = showCmd;
487 if (pt) wndpl.ptMinPosition = *pt;
488 wndpl.rcNormalPosition = (rect != NULL) ? *rect : wndPtr->rectNormal;
489 wndpl.ptMaxPosition = wndPtr->ptMaxPos;
490 SetWindowPlacement( hwnd, &wndpl );
494 /***********************************************************************
495 * GetWindowPlacement (USER.370)
497 BOOL GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *wndpl )
499 WND *wndPtr = WIN_FindWndPtr( hwnd );
500 if (!wndPtr) return FALSE;
502 wndpl->length = sizeof(*wndpl);
504 wndpl->showCmd = IsZoomed(hwnd) ? SW_SHOWMAXIMIZED :
505 (IsIconic(hwnd) ? SW_SHOWMINIMIZED : SW_SHOWNORMAL);
506 wndpl->ptMinPosition = wndPtr->ptIconPos;
507 wndpl->ptMaxPosition = wndPtr->ptMaxPos;
508 wndpl->rcNormalPosition = wndPtr->rectNormal;
513 /***********************************************************************
514 * SetWindowPlacement (USER.371)
516 BOOL SetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *wndpl )
518 WND *wndPtr = WIN_FindWndPtr( hwnd );
519 if (!wndPtr) return FALSE;
521 if (wndpl->flags & WPF_SETMINPOSITION)
522 wndPtr->ptIconPos = wndpl->ptMinPosition;
523 if ((wndpl->flags & WPF_RESTORETOMAXIMIZED) &&
524 (wndpl->showCmd == SW_SHOWMINIMIZED)) wndPtr->flags |= WIN_RESTORE_MAX;
525 wndPtr->ptMaxPos = wndpl->ptMaxPosition;
526 wndPtr->rectNormal = wndpl->rcNormalPosition;
527 ShowWindow( hwnd, wndpl->showCmd );
532 /*******************************************************************
533 * WINPOS_NextWindowFromPoint
535 * Looks for next enabled window that is
536 * a) sibling of hwnd, later in Z-order and encloses pt, or
539 HWND WINPOS_NextWindowFromPoint( HWND hwnd, POINT pt )
541 WND *wndPtr = WIN_FindWndPtr( hwnd );
543 if (!wndPtr->hwndParent) return hwnd; /* desktop window */
544 ScreenToClient( wndPtr->hwndParent, &pt ); /* make pt relative to parent */
547 if (!wndPtr->hwndNext) break; /* No more children */
548 hwnd = wndPtr->hwndNext;
549 wndPtr = WIN_FindWndPtr( hwnd );
550 if ((wndPtr->dwStyle & WS_VISIBLE) &&
551 !(wndPtr->dwStyle & WS_DISABLED) &&
552 PtInRect( &wndPtr->rectWindow, pt )) return hwnd;
554 return wndPtr->hwndParent;
558 /*******************************************************************
559 * WINPOS_ChangeActiveWindow
561 * Change the active window and send the corresponding messages.
563 HWND WINPOS_ChangeActiveWindow( HWND hwnd, BOOL mouseMsg )
565 HWND prevActive = hwndActive;
566 if (hwnd == hwndActive) return 0;
569 if (!SendMessage( hwndActive, WM_NCACTIVATE, FALSE, 0 )) return 0;
570 SendMessage( hwndActive, WM_ACTIVATE, WA_INACTIVE,
571 MAKELONG( IsIconic(hwndActive), hwnd ) );
572 /* Send WM_ACTIVATEAPP here */
578 WND *wndPtr = WIN_FindWndPtr( hwndActive );
579 wndPtr->hwndPrevActive = prevActive;
581 /* Send WM_ACTIVATEAPP here */
582 SendMessage( hwnd, WM_NCACTIVATE, TRUE, 0 );
583 SendMessage( hwnd, WM_ACTIVATE, mouseMsg ? WA_CLICKACTIVE : WA_ACTIVE,
584 MAKELONG( IsIconic(hwnd), prevActive ) );
590 /***********************************************************************
591 * WINPOS_SendNCCalcSize
593 * Send a WM_NCCALCSIZE message to a window.
594 * All parameters are read-only except newClientRect.
595 * oldWindowRect, oldClientRect and winpos must be non-NULL only
596 * when calcValidRect is TRUE.
598 LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect, RECT *newWindowRect,
599 RECT *oldWindowRect, RECT *oldClientRect,
600 WINDOWPOS *winpos, RECT *newClientRect )
602 NCCALCSIZE_PARAMS *params;
606 if (!(hparams = USER_HEAP_ALLOC( sizeof(*params) ))) return 0;
607 params = (NCCALCSIZE_PARAMS *) USER_HEAP_LIN_ADDR( hparams );
608 params->rgrc[0] = *newWindowRect;
611 params->rgrc[1] = *oldWindowRect;
612 params->rgrc[2] = *oldClientRect;
613 params->lppos = winpos;
615 result = SendMessage( hwnd, WM_NCCALCSIZE, calcValidRect,
616 USER_HEAP_SEG_ADDR(hparams) );
617 *newClientRect = params->rgrc[0];
618 USER_HEAP_FREE( hparams );
623 /***********************************************************************
624 * WINPOS_HandleWindowPosChanging
626 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
628 LONG WINPOS_HandleWindowPosChanging( WINDOWPOS *winpos )
631 WND *wndPtr = WIN_FindWndPtr( winpos->hwnd );
632 if (!wndPtr || (winpos->flags & SWP_NOSIZE)) return 0;
633 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
634 (wndPtr->dwStyle & (WS_POPUP | WS_CHILD) == 0))
636 NC_GetMinMaxInfo( winpos->hwnd, &maxSize, NULL, NULL, NULL );
637 winpos->cx = min( winpos->cx, maxSize.x );
638 winpos->cy = min( winpos->cy, maxSize.y );
644 /***********************************************************************
645 * WINPOS_MoveWindowZOrder
647 * Move a window in Z order, invalidating everything that needs it.
648 * Only necessary for windows without associated X window.
650 static void WINPOS_MoveWindowZOrder( HWND hwnd, HWND hwndAfter )
654 WND *wndPtr = WIN_FindWndPtr( hwnd );
656 /* We have two possible cases:
657 * - The window is moving up: we have to invalidate all areas
658 * of the window that were covered by other windows
659 * - The window is moving down: we have to invalidate areas
660 * of other windows covered by this one.
663 if (hwndAfter == HWND_TOP)
667 else if (hwndAfter == HWND_BOTTOM)
669 if (!wndPtr->hwndNext) return; /* Already at the bottom */
674 if (wndPtr->hwndNext == hwndAfter) return; /* Already placed right */
676 /* Determine which window we encounter first in Z-order */
677 hwndCur = GetWindow( wndPtr->hwndParent, GW_CHILD );
678 while ((hwndCur != hwnd) && (hwndCur != hwndAfter))
679 hwndCur = GetWindow( hwndCur, GW_HWNDNEXT );
680 movingUp = (hwndCur == hwndAfter);
685 HWND hwndPrevAfter = wndPtr->hwndNext;
686 WIN_UnlinkWindow( hwnd );
687 WIN_LinkWindow( hwnd, hwndAfter );
688 hwndCur = wndPtr->hwndNext;
689 while (hwndCur != hwndPrevAfter)
691 WND *curPtr = WIN_FindWndPtr( hwndCur );
692 RECT rect = curPtr->rectWindow;
693 OffsetRect( &rect, -wndPtr->rectClient.left,
694 -wndPtr->rectClient.top );
695 RedrawWindow( hwnd, &rect, 0, RDW_INVALIDATE | RDW_ALLCHILDREN |
696 RDW_FRAME | RDW_ERASE );
697 hwndCur = curPtr->hwndNext;
700 else /* Moving down */
702 hwndCur = wndPtr->hwndNext;
703 WIN_UnlinkWindow( hwnd );
704 WIN_LinkWindow( hwnd, hwndAfter );
705 while (hwndCur != hwnd)
707 WND *curPtr = WIN_FindWndPtr( hwndCur );
708 RECT rect = wndPtr->rectWindow;
709 OffsetRect( &rect, -curPtr->rectClient.left,
710 -curPtr->rectClient.top );
711 RedrawWindow( hwndCur, &rect, 0, RDW_INVALIDATE | RDW_ALLCHILDREN |
712 RDW_FRAME | RDW_ERASE );
713 hwndCur = curPtr->hwndNext;
719 /***********************************************************************
720 * WINPOS_SetXWindosPos
722 * SetWindowPos() for an X window. Used by the real SetWindowPos().
724 static void WINPOS_SetXWindowPos( WINDOWPOS *winpos )
726 XWindowChanges winChanges;
728 WND *wndPtr = WIN_FindWndPtr( winpos->hwnd );
730 if (!(winpos->flags & SWP_NOSIZE))
732 winChanges.width = winpos->cx;
733 winChanges.height = winpos->cy;
734 changeMask |= CWWidth | CWHeight;
736 if (!(winpos->flags & SWP_NOMOVE))
738 winChanges.x = winpos->x;
739 winChanges.y = winpos->y;
740 changeMask |= CWX | CWY;
742 if (!(winpos->flags & SWP_NOZORDER))
744 if (winpos->hwndInsertAfter == HWND_TOP) winChanges.stack_mode = Above;
745 else winChanges.stack_mode = Below;
746 if ((winpos->hwndInsertAfter != HWND_TOP) &&
747 (winpos->hwndInsertAfter != HWND_BOTTOM))
749 WND * insertPtr = WIN_FindWndPtr( winpos->hwndInsertAfter );
750 winChanges.sibling = insertPtr->window;
751 changeMask |= CWSibling;
753 changeMask |= CWStackMode;
756 XConfigureWindow( display, wndPtr->window, changeMask, &winChanges );
760 /***********************************************************************
761 * SetWindowPos (USER.232)
763 BOOL SetWindowPos( HWND hwnd, HWND hwndInsertAfter, INT x, INT y,
764 INT cx, INT cy, WORD flags )
769 RECT newWindowRect, newClientRect;
772 /* Check window handle */
774 if (hwnd == GetDesktopWindow()) return FALSE;
775 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
777 /* Check dimensions */
784 if (hwnd == hwndActive) flags |= SWP_NOACTIVATE; /* Already active */
785 if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
786 (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
787 flags |= SWP_NOSIZE; /* Already the right size */
788 if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
789 flags |= SWP_NOMOVE; /* Already the right position */
791 /* Check hwndInsertAfter */
793 if (!(flags & (SWP_NOZORDER | SWP_NOACTIVATE)))
795 /* Ignore TOPMOST flags when activating a window */
796 /* _and_ moving it in Z order. */
797 if ((hwndInsertAfter == HWND_TOPMOST) ||
798 (hwndInsertAfter == HWND_NOTOPMOST))
799 hwndInsertAfter = HWND_TOP;
801 /* TOPMOST not supported yet */
802 if ((hwndInsertAfter == HWND_TOPMOST) ||
803 (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
804 /* hwndInsertAfter must be a sibling of the window */
805 if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM) &&
806 (GetParent(hwnd) != GetParent(hwndInsertAfter))) return FALSE;
808 /* Allocate the WINDOWPOS structure */
810 hWinPos = USER_HEAP_ALLOC( sizeof(WINDOWPOS) );
811 if (!hWinPos) return FALSE;
812 winpos = USER_HEAP_LIN_ADDR( hWinPos );
814 winpos->hwndInsertAfter = hwndInsertAfter;
819 winpos->flags = flags;
821 /* Send WM_WINDOWPOSCHANGING message */
823 if (!(flags & SWP_NOSENDCHANGING))
824 SendMessage( hwnd, WM_WINDOWPOSCHANGING, 0,
825 USER_HEAP_SEG_ADDR(hWinPos) );
827 /* Calculate new position and size */
829 newWindowRect = wndPtr->rectWindow;
830 newClientRect = wndPtr->rectClient;
832 if (!(winpos->flags & SWP_NOSIZE))
834 newWindowRect.right = newWindowRect.left + winpos->cx;
835 newWindowRect.bottom = newWindowRect.top + winpos->cy;
837 if (!(winpos->flags & SWP_NOMOVE))
839 newWindowRect.left = winpos->x;
840 newWindowRect.top = winpos->y;
841 newWindowRect.right += winpos->x - wndPtr->rectWindow.left;
842 newWindowRect.bottom += winpos->y - wndPtr->rectWindow.top;
845 /* Reposition window in Z order */
847 if (!(winpos->flags & SWP_NOZORDER))
851 WIN_UnlinkWindow( winpos->hwnd );
852 WIN_LinkWindow( winpos->hwnd, hwndInsertAfter );
854 else WINPOS_MoveWindowZOrder( winpos->hwnd, hwndInsertAfter );
857 /* Send WM_NCCALCSIZE message to get new client area */
859 result = WINPOS_SendNCCalcSize( winpos->hwnd, TRUE, &newWindowRect,
860 &wndPtr->rectWindow, &wndPtr->rectClient,
861 winpos, &newClientRect );
862 /* .... Should handle result here */
864 /* Perform the moving and resizing */
868 WINPOS_SetXWindowPos( winpos );
869 wndPtr->rectWindow = newWindowRect;
870 wndPtr->rectClient = newClientRect;
874 RECT oldWindowRect = wndPtr->rectWindow;
876 wndPtr->rectWindow = newWindowRect;
877 wndPtr->rectClient = newClientRect;
879 if (!(flags & SWP_NOREDRAW) &&
880 (!(flags & SWP_NOSIZE) || !(flags & SWP_NOMOVE) ||
881 !(flags & SWP_NOZORDER)))
883 HRGN hrgn1 = CreateRectRgnIndirect( &oldWindowRect );
884 HRGN hrgn2 = CreateRectRgnIndirect( &wndPtr->rectWindow );
885 HRGN hrgn3 = CreateRectRgn( 0, 0, 0, 0 );
886 CombineRgn( hrgn3, hrgn1, hrgn2, RGN_DIFF );
887 RedrawWindow( wndPtr->hwndParent, NULL, hrgn3,
888 RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE );
889 if ((oldWindowRect.left != wndPtr->rectWindow.left) ||
890 (oldWindowRect.top != wndPtr->rectWindow.top))
892 RedrawWindow( winpos->hwnd, NULL, 0, RDW_INVALIDATE |
893 RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE );
895 DeleteObject( hrgn1 );
896 DeleteObject( hrgn2 );
897 DeleteObject( hrgn3 );
901 if (flags & SWP_SHOWWINDOW)
903 wndPtr->dwStyle |= WS_VISIBLE;
906 XMapWindow( display, wndPtr->window );
910 if (!(flags & SWP_NOREDRAW))
911 RedrawWindow( winpos->hwnd, NULL, 0,
912 RDW_INVALIDATE | RDW_FRAME | RDW_ERASE );
915 else if (flags & SWP_HIDEWINDOW)
917 wndPtr->dwStyle &= ~WS_VISIBLE;
920 XUnmapWindow( display, wndPtr->window );
924 if (!(flags & SWP_NOREDRAW))
925 RedrawWindow( wndPtr->hwndParent, &wndPtr->rectWindow, 0,
926 RDW_INVALIDATE | RDW_FRAME |
927 RDW_ALLCHILDREN | RDW_ERASE );
929 if ((winpos->hwnd == GetFocus()) || IsChild(winpos->hwnd, GetFocus()))
930 SetFocus( GetParent(winpos->hwnd) ); /* Revert focus to parent */
931 if (winpos->hwnd == hwndActive)
933 /* Activate previously active window if possible */
934 HWND newActive = wndPtr->hwndPrevActive;
935 if (!IsWindow(newActive) || (newActive == winpos->hwnd))
937 newActive = GetTopWindow(GetDesktopWindow());
938 if (newActive == winpos->hwnd) newActive = wndPtr->hwndNext;
940 WINPOS_ChangeActiveWindow( newActive, FALSE );
944 /* Activate the window */
946 if (!(flags & SWP_NOACTIVATE))
948 if (!(wndPtr->dwStyle & WS_CHILD))
949 WINPOS_ChangeActiveWindow( winpos->hwnd, FALSE );
952 /* Repaint the window */
954 if (wndPtr->window) MSG_Synchronize(); /* Wait for all expose events */
955 if ((flags & SWP_FRAMECHANGED) && !(flags & SWP_NOREDRAW))
956 RedrawWindow( winpos->hwnd, NULL, 0,
957 RDW_INVALIDATE | RDW_FRAME | RDW_ERASE );
958 if (!(flags & SWP_DEFERERASE))
959 RedrawWindow( wndPtr->hwndParent, NULL, 0,
960 RDW_ALLCHILDREN | RDW_ERASENOW );
962 /* And last, send the WM_WINDOWPOSCHANGED message */
964 if (!(winpos->flags & SWP_NOSENDCHANGING))
965 SendMessage( winpos->hwnd, WM_WINDOWPOSCHANGED, 0,
966 USER_HEAP_SEG_ADDR(hWinPos) );
968 USER_HEAP_FREE( hWinPos );
973 /***********************************************************************
974 * BeginDeferWindowPos (USER.259)
976 HDWP BeginDeferWindowPos( INT count )
981 if (count <= 0) return 0;
982 handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
983 if (!handle) return 0;
984 pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
985 pDWP->actualCount = 0;
986 pDWP->suggestedCount = count;
988 pDWP->wMagic = DWP_MAGIC;
989 pDWP->hwndParent = 0;
994 /***********************************************************************
995 * DeferWindowPos (USER.260)
997 HDWP DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter, INT x, INT y,
998 INT cx, INT cy, WORD flags )
1002 HDWP newhdwp = hdwp;
1004 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
1005 if (!pDWP) return 0;
1007 /* All the windows of a DeferWindowPos() must have the same parent */
1009 if (pDWP->actualCount == 0) pDWP->hwndParent = GetParent( hwnd );
1010 else if (GetParent( hwnd ) != pDWP->hwndParent)
1012 USER_HEAP_FREE( hdwp );
1016 for (i = 0; i < pDWP->actualCount; i++)
1018 if (pDWP->winPos[i].hwnd == hwnd)
1020 /* Merge with the other changes */
1021 if (!(flags & SWP_NOZORDER))
1023 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
1025 if (!(flags & SWP_NOMOVE))
1027 pDWP->winPos[i].x = x;
1028 pDWP->winPos[i].y = y;
1030 if (!(flags & SWP_NOSIZE))
1032 pDWP->winPos[i].cx = cx;
1033 pDWP->winPos[i].cy = cy;
1035 pDWP->winPos[i].flags &= flags & (SWP_NOSIZE | SWP_NOMOVE |
1036 SWP_NOZORDER | SWP_NOREDRAW |
1037 SWP_NOACTIVATE | SWP_NOCOPYBITS |
1039 pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
1044 if (pDWP->actualCount >= pDWP->suggestedCount)
1046 newhdwp = USER_HEAP_REALLOC( hdwp,
1047 sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
1048 if (!newhdwp) return 0;
1049 pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
1050 pDWP->suggestedCount++;
1052 pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
1053 pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
1054 pDWP->winPos[pDWP->actualCount].x = x;
1055 pDWP->winPos[pDWP->actualCount].y = y;
1056 pDWP->winPos[pDWP->actualCount].cx = cx;
1057 pDWP->winPos[pDWP->actualCount].cy = cy;
1058 pDWP->winPos[pDWP->actualCount].flags = flags;
1059 pDWP->actualCount++;
1064 /***********************************************************************
1065 * EndDeferWindowPos (USER.261)
1067 BOOL EndDeferWindowPos( HDWP hdwp )
1074 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
1075 if (!pDWP) return FALSE;
1076 for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
1078 if (!(res = SetWindowPos( winpos->hwnd, winpos->hwndInsertAfter,
1079 winpos->x, winpos->y, winpos->cx, winpos->cy,
1080 winpos->flags ))) break;
1082 USER_HEAP_FREE( hdwp );
1087 /***********************************************************************
1088 * TileChildWindows (USER.199)
1090 void TileChildWindows( HWND parent, WORD action )
1092 printf("STUB TileChildWindows(%04X, %d)\n", parent, action);
1095 /***********************************************************************
1096 * CascageChildWindows (USER.198)
1098 void CascadeChildWindows( HWND parent, WORD action )
1100 printf("STUB CascadeChildWindows(%04X, %d)\n", parent, action);