Release 951105
[wine/multimedia.git] / windows / winpos.c
blob119b2651538b73cc1486f3efa30ac4e788914646
1 /*
2 * Window position related functions.
4 * Copyright 1993, 1994, 1995 Alexandre Julliard
5 */
7 #include "sysmetrics.h"
8 #include "user.h"
9 #include "win.h"
10 #include "event.h"
11 #include "message.h"
12 #include "stackframe.h"
13 #include "winpos.h"
14 #include "nonclient.h"
15 #include "stddebug.h"
16 /* #define DEBUG_WIN */
17 #include "debug.h"
19 static HWND hwndActive = 0; /* Currently active window */
22 /***********************************************************************
23 * WINPOS_FindIconPos
25 * Find a suitable place for an iconic window.
26 * The new position is stored into wndPtr->ptIconPos.
28 void WINPOS_FindIconPos( HWND hwnd )
30 RECT rectParent;
31 short x, y, xspacing, yspacing;
32 WND * wndPtr = WIN_FindWndPtr( hwnd );
34 if (!wndPtr) return;
35 GetClientRect( wndPtr->hwndParent, &rectParent );
36 if ((wndPtr->ptIconPos.x >= rectParent.left) &&
37 (wndPtr->ptIconPos.x + SYSMETRICS_CXICON < rectParent.right) &&
38 (wndPtr->ptIconPos.y >= rectParent.top) &&
39 (wndPtr->ptIconPos.y + SYSMETRICS_CYICON < rectParent.bottom))
40 return; /* The icon already has a suitable position */
42 xspacing = yspacing = 70; /* FIXME: This should come from WIN.INI */
43 y = rectParent.bottom;
44 for (;;)
46 for (x = rectParent.left; x<=rectParent.right-xspacing; x += xspacing)
48 /* Check if another icon already occupies this spot */
49 HWND hwndChild = GetWindow( wndPtr->hwndParent, GW_CHILD );
50 while (hwndChild)
52 WND *childPtr = WIN_FindWndPtr( hwndChild );
53 if ((childPtr->dwStyle & WS_MINIMIZE) && (hwndChild != hwnd))
55 if ((childPtr->rectWindow.left < x + xspacing) &&
56 (childPtr->rectWindow.right >= x) &&
57 (childPtr->rectWindow.top <= y) &&
58 (childPtr->rectWindow.bottom > y - yspacing))
59 break; /* There's a window in there */
62 hwndChild = childPtr->hwndNext;
64 if (!hwndChild)
66 /* No window was found, so it's OK for us */
67 wndPtr->ptIconPos.x = x + (xspacing - SYSMETRICS_CXICON) / 2;
68 wndPtr->ptIconPos.y = y - (yspacing + SYSMETRICS_CYICON) / 2;
69 return;
72 y -= yspacing;
77 /***********************************************************************
78 * ArrangeIconicWindows (USER.170)
80 WORD ArrangeIconicWindows( HWND parent )
82 RECT rectParent;
83 HWND hwndChild;
84 short x, y, xspacing, yspacing;
86 GetClientRect( parent, &rectParent );
87 x = rectParent.left;
88 y = rectParent.bottom;
89 xspacing = yspacing = 70; /* FIXME: This should come from WIN.INI */
90 hwndChild = GetWindow( parent, GW_CHILD );
91 while (hwndChild)
93 if (IsIconic( hwndChild ))
95 SetWindowPos( hwndChild, 0, x + (xspacing - SYSMETRICS_CXICON) / 2,
96 y - (yspacing + SYSMETRICS_CYICON) / 2, 0, 0,
97 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
98 if (x <= rectParent.right - xspacing) x += xspacing;
99 else
101 x = rectParent.left;
102 y -= yspacing;
105 hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
107 return yspacing;
111 /***********************************************************************
112 * GetWindowRect (USER.32)
114 void GetWindowRect( HWND hwnd, LPRECT rect )
116 WND * wndPtr = WIN_FindWndPtr( hwnd );
117 if (!wndPtr) return;
119 *rect = wndPtr->rectWindow;
120 if (wndPtr->dwStyle & WS_CHILD)
121 MapWindowPoints( wndPtr->hwndParent, 0, (POINT *)rect, 2 );
125 /***********************************************************************
126 * GetClientRect (USER.33)
128 void GetClientRect( HWND hwnd, LPRECT rect )
130 WND * wndPtr = WIN_FindWndPtr( hwnd );
132 rect->left = rect->top = rect->right = rect->bottom = 0;
133 if (wndPtr)
135 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
136 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
141 /*******************************************************************
142 * ClientToScreen (USER.28)
144 void ClientToScreen( HWND hwnd, LPPOINT lppnt )
146 MapWindowPoints( hwnd, 0, lppnt, 1 );
150 /*******************************************************************
151 * ScreenToClient (USER.29)
153 void ScreenToClient( HWND hwnd, LPPOINT lppnt )
155 MapWindowPoints( 0, hwnd, lppnt, 1 );
159 /*******************************************************************
160 * WindowFromPoint (USER.30)
162 HWND WindowFromPoint( POINT pt )
164 HWND hwndRet = 0;
165 HWND hwnd = GetDesktopWindow();
167 while(hwnd)
169 /* If point is in window, and window is visible, */
170 /* not disabled and not transparent, then explore */
171 /* its children. Otherwise, go to the next window. */
173 WND *wndPtr = WIN_FindWndPtr( hwnd );
174 if ((pt.x >= wndPtr->rectWindow.left) &&
175 (pt.x < wndPtr->rectWindow.right) &&
176 (pt.y >= wndPtr->rectWindow.top) &&
177 (pt.y < wndPtr->rectWindow.bottom) &&
178 !(wndPtr->dwStyle & WS_DISABLED) &&
179 (wndPtr->dwStyle & WS_VISIBLE) &&
180 !(wndPtr->dwExStyle & WS_EX_TRANSPARENT))
182 hwndRet = hwnd;
183 /* If window is minimized, ignore its children */
184 if (wndPtr->dwStyle & WS_MINIMIZE) break;
185 pt.x -= wndPtr->rectClient.left;
186 pt.y -= wndPtr->rectClient.top;
187 hwnd = wndPtr->hwndChild;
189 else hwnd = wndPtr->hwndNext;
191 return hwndRet;
195 /*******************************************************************
196 * ChildWindowFromPoint (USER.191)
198 HWND ChildWindowFromPoint( HWND hwndParent, POINT pt )
200 RECT rect;
201 HWND hwnd;
203 GetWindowRect( hwndParent, &rect );
204 if (!PtInRect( &rect, pt )) return 0;
205 hwnd = GetTopWindow( hwndParent );
206 while (hwnd)
208 GetWindowRect( hwnd, &rect );
209 if (PtInRect( &rect, pt )) return hwnd;
210 hwnd = GetWindow( hwnd, GW_HWNDNEXT );
212 return hwndParent;
216 /*******************************************************************
217 * MapWindowPoints (USER.258)
219 void MapWindowPoints( HWND hwndFrom, HWND hwndTo, LPPOINT lppt, WORD count )
221 WND * wndPtr;
222 POINT * curpt;
223 POINT origin = { 0, 0 };
224 WORD i;
226 /* Translate source window origin to screen coords */
227 while(hwndFrom)
229 wndPtr = WIN_FindWndPtr( hwndFrom );
230 origin.x += wndPtr->rectClient.left;
231 origin.y += wndPtr->rectClient.top;
232 hwndFrom = (wndPtr->dwStyle & WS_CHILD) ? wndPtr->hwndParent : 0;
235 /* Translate origin to destination window coords */
236 while(hwndTo)
238 wndPtr = WIN_FindWndPtr( hwndTo );
239 origin.x -= wndPtr->rectClient.left;
240 origin.y -= wndPtr->rectClient.top;
241 hwndTo = (wndPtr->dwStyle & WS_CHILD) ? wndPtr->hwndParent : 0;
244 /* Translate points */
245 for (i = 0, curpt = lppt; i < count; i++, curpt++)
247 curpt->x += origin.x;
248 curpt->y += origin.y;
253 /***********************************************************************
254 * IsIconic (USER.31)
256 BOOL IsIconic(HWND hWnd)
258 WND * wndPtr = WIN_FindWndPtr(hWnd);
259 if (wndPtr == NULL) return FALSE;
260 return (wndPtr->dwStyle & WS_MINIMIZE) != 0;
264 /***********************************************************************
265 * IsZoomed (USER.272)
267 BOOL IsZoomed(HWND hWnd)
269 WND * wndPtr = WIN_FindWndPtr(hWnd);
270 if (wndPtr == NULL) return FALSE;
271 return (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
275 /*******************************************************************
276 * GetActiveWindow (USER.60)
278 HWND GetActiveWindow()
280 return hwndActive;
284 /*******************************************************************
285 * SetActiveWindow (USER.59)
287 HWND SetActiveWindow( HWND hwnd )
289 HWND prev = hwndActive;
290 WND *wndPtr = WIN_FindWndPtr( hwnd );
291 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD)) return 0;
292 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
293 return prev;
297 /***********************************************************************
298 * BringWindowToTop (USER.45)
300 BOOL BringWindowToTop( HWND hwnd )
302 return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
306 /***********************************************************************
307 * MoveWindow (USER.56)
309 BOOL MoveWindow( HWND hwnd, short x, short y, short cx, short cy, BOOL repaint)
311 int flags = SWP_NOZORDER | SWP_NOACTIVATE;
312 if (!repaint) flags |= SWP_NOREDRAW;
313 dprintf_win(stddeb, "MoveWindow: "NPFMT" %d,%d %dx%d %d\n",
314 hwnd, x, y, cx, cy, repaint );
315 return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
319 /***********************************************************************
320 * ShowWindow (USER.42)
322 BOOL ShowWindow( HWND hwnd, int cmd )
324 WND * wndPtr = WIN_FindWndPtr( hwnd );
325 BOOL wasVisible;
326 POINT maxSize;
327 int swpflags = 0;
328 short x = 0, y = 0, cx = 0, cy = 0;
330 if (!wndPtr) return FALSE;
332 dprintf_win(stddeb,"ShowWindow: hwnd="NPFMT", cmd=%d\n", hwnd, cmd);
334 wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
336 switch(cmd)
338 case SW_HIDE:
339 swpflags |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
340 SWP_NOACTIVATE | SWP_NOZORDER;
341 break;
343 case SW_SHOWMINNOACTIVE:
344 swpflags |= SWP_NOACTIVATE | SWP_NOZORDER;
345 /* fall through */
346 case SW_SHOWMINIMIZED:
347 swpflags |= SWP_SHOWWINDOW;
348 /* fall through */
349 case SW_MINIMIZE:
350 swpflags |= SWP_FRAMECHANGED;
351 if (!(wndPtr->dwStyle & WS_MINIMIZE))
353 if (wndPtr->dwStyle & WS_MAXIMIZE)
355 wndPtr->flags |= WIN_RESTORE_MAX;
356 wndPtr->dwStyle &= ~WS_MAXIMIZE;
358 else
360 wndPtr->flags &= ~WIN_RESTORE_MAX;
361 wndPtr->rectNormal = wndPtr->rectWindow;
363 wndPtr->dwStyle |= WS_MINIMIZE;
364 WINPOS_FindIconPos( hwnd );
365 x = wndPtr->ptIconPos.x;
366 y = wndPtr->ptIconPos.y;
367 cx = SYSMETRICS_CXICON;
368 cy = SYSMETRICS_CYICON;
370 else swpflags |= SWP_NOSIZE | SWP_NOMOVE;
371 break;
373 case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE: */
374 swpflags |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
375 if (!(wndPtr->dwStyle & WS_MAXIMIZE))
377 /* Store the current position and find the maximized size */
378 if (!(wndPtr->dwStyle & WS_MINIMIZE))
379 wndPtr->rectNormal = wndPtr->rectWindow;
380 NC_GetMinMaxInfo( hwnd, &maxSize,
381 &wndPtr->ptMaxPos, NULL, NULL );
382 x = wndPtr->ptMaxPos.x;
383 y = wndPtr->ptMaxPos.y;
384 cx = maxSize.x;
385 cy = maxSize.y;
386 wndPtr->dwStyle &= ~WS_MINIMIZE;
387 wndPtr->dwStyle |= WS_MAXIMIZE;
389 else swpflags |= SWP_NOSIZE | SWP_NOMOVE;
390 break;
392 case SW_SHOWNA:
393 swpflags |= SWP_NOACTIVATE | SWP_NOZORDER;
394 /* fall through */
395 case SW_SHOW:
396 swpflags |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
397 break;
399 case SW_SHOWNOACTIVATE:
400 swpflags |= SWP_NOZORDER;
401 if (GetActiveWindow()) swpflags |= SWP_NOACTIVATE;
402 /* fall through */
403 case SW_SHOWNORMAL: /* same as SW_NORMAL: */
404 case SW_RESTORE:
405 swpflags |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
406 if (wndPtr->dwStyle & WS_MINIMIZE)
408 wndPtr->ptIconPos.x = wndPtr->rectWindow.left;
409 wndPtr->ptIconPos.y = wndPtr->rectWindow.top;
410 wndPtr->dwStyle &= ~WS_MINIMIZE;
411 if (wndPtr->flags & WIN_RESTORE_MAX)
413 /* Restore to maximized position */
414 NC_GetMinMaxInfo( hwnd, &maxSize, &wndPtr->ptMaxPos,
415 NULL, NULL );
416 x = wndPtr->ptMaxPos.x;
417 y = wndPtr->ptMaxPos.y;
418 cx = maxSize.x;
419 cy = maxSize.y;
420 wndPtr->dwStyle |= WS_MAXIMIZE;
422 else /* Restore to normal position */
424 x = wndPtr->rectNormal.left;
425 y = wndPtr->rectNormal.top;
426 cx = wndPtr->rectNormal.right - wndPtr->rectNormal.left;
427 cy = wndPtr->rectNormal.bottom - wndPtr->rectNormal.top;
430 else if (wndPtr->dwStyle & WS_MAXIMIZE)
432 wndPtr->ptMaxPos.x = wndPtr->rectWindow.left;
433 wndPtr->ptMaxPos.y = wndPtr->rectWindow.top;
434 wndPtr->dwStyle &= ~WS_MAXIMIZE;
435 x = wndPtr->rectNormal.left;
436 y = wndPtr->rectNormal.top;
437 cx = wndPtr->rectNormal.right - wndPtr->rectNormal.left;
438 cy = wndPtr->rectNormal.bottom - wndPtr->rectNormal.top;
440 else swpflags |= SWP_NOSIZE | SWP_NOMOVE;
441 break;
444 SendMessage( hwnd, WM_SHOWWINDOW, (cmd != SW_HIDE), 0 );
445 SetWindowPos( hwnd, HWND_TOP, x, y, cx, cy, swpflags );
447 /* Send WM_SIZE and WM_MOVE messages if not already done */
448 if (!(wndPtr->flags & WIN_GOT_SIZEMSG))
450 int wParam = SIZE_RESTORED;
451 if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
452 else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
453 wndPtr->flags |= WIN_GOT_SIZEMSG;
454 SendMessage( hwnd, WM_SIZE, wParam,
455 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
456 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
457 SendMessage( hwnd, WM_MOVE, 0,
458 MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
461 return wasVisible;
465 /***********************************************************************
466 * GetInternalWindowPos (USER.460)
468 WORD GetInternalWindowPos( HWND hwnd, LPRECT rectWnd, LPPOINT ptIcon )
470 WINDOWPLACEMENT wndpl;
471 if (!GetWindowPlacement( hwnd, &wndpl )) return 0;
472 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
473 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
474 return wndpl.showCmd;
478 /***********************************************************************
479 * SetInternalWindowPos (USER.461)
481 void SetInternalWindowPos( HWND hwnd, WORD showCmd, LPRECT rect, LPPOINT pt )
483 WINDOWPLACEMENT wndpl;
484 WND *wndPtr = WIN_FindWndPtr( hwnd );
486 wndpl.length = sizeof(wndpl);
487 wndpl.flags = (pt != NULL) ? WPF_SETMINPOSITION : 0;
488 wndpl.showCmd = showCmd;
489 if (pt) wndpl.ptMinPosition = *pt;
490 wndpl.rcNormalPosition = (rect != NULL) ? *rect : wndPtr->rectNormal;
491 wndpl.ptMaxPosition = wndPtr->ptMaxPos;
492 SetWindowPlacement( hwnd, &wndpl );
496 /***********************************************************************
497 * GetWindowPlacement (USER.370)
499 BOOL GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *wndpl )
501 WND *wndPtr = WIN_FindWndPtr( hwnd );
502 if (!wndPtr) return FALSE;
504 wndpl->length = sizeof(*wndpl);
505 wndpl->flags = 0;
506 wndpl->showCmd = IsZoomed(hwnd) ? SW_SHOWMAXIMIZED :
507 (IsIconic(hwnd) ? SW_SHOWMINIMIZED : SW_SHOWNORMAL);
508 wndpl->ptMinPosition = wndPtr->ptIconPos;
509 wndpl->ptMaxPosition = wndPtr->ptMaxPos;
510 wndpl->rcNormalPosition = wndPtr->rectNormal;
511 return TRUE;
515 /***********************************************************************
516 * SetWindowPlacement (USER.371)
518 BOOL SetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *wndpl )
520 WND *wndPtr = WIN_FindWndPtr( hwnd );
521 if (!wndPtr) return FALSE;
523 if (wndpl->flags & WPF_SETMINPOSITION)
524 wndPtr->ptIconPos = wndpl->ptMinPosition;
525 if ((wndpl->flags & WPF_RESTORETOMAXIMIZED) &&
526 (wndpl->showCmd == SW_SHOWMINIMIZED)) wndPtr->flags |= WIN_RESTORE_MAX;
527 wndPtr->ptMaxPos = wndpl->ptMaxPosition;
528 wndPtr->rectNormal = wndpl->rcNormalPosition;
529 ShowWindow( hwnd, wndpl->showCmd );
530 return TRUE;
534 /*******************************************************************
535 * WINPOS_ChangeActiveWindow
537 * Change the active window and send the corresponding messages.
539 HWND WINPOS_ChangeActiveWindow( HWND hwnd, BOOL mouseMsg )
541 HWND prevActive = hwndActive;
542 if (hwnd == hwndActive) return 0;
543 if (hwndActive)
545 if (!SendMessage( hwndActive, WM_NCACTIVATE, FALSE, 0 )) return 0;
546 #ifdef WINELIB32
547 SendMessage( hwndActive, WM_ACTIVATE,
548 MAKEWPARAM( WA_INACTIVE, IsIconic(hwndActive) ),
549 (LPARAM)hwnd );
550 #else
551 SendMessage( hwndActive, WM_ACTIVATE, WA_INACTIVE,
552 MAKELONG( IsIconic(hwndActive), hwnd ) );
553 #endif
554 /* Send WM_ACTIVATEAPP here */
557 hwndActive = hwnd;
558 if (hwndActive)
560 WND *wndPtr = WIN_FindWndPtr( hwndActive );
561 wndPtr->hwndPrevActive = prevActive;
563 /* Send WM_ACTIVATEAPP here */
564 SendMessage( hwnd, WM_NCACTIVATE, TRUE, 0 );
565 #ifdef WINELIB32
566 SendMessage( hwnd, WM_ACTIVATE,
567 MAKEWPARAM( mouseMsg ? WA_CLICKACTIVE : WA_ACTIVE,
568 IsIconic(hwnd) )
569 , (LPARAM)prevActive );
570 #else
571 SendMessage( hwnd, WM_ACTIVATE, mouseMsg ? WA_CLICKACTIVE : WA_ACTIVE,
572 MAKELONG( IsIconic(hwnd), prevActive ) );
573 #endif
575 return prevActive;
579 /***********************************************************************
580 * WINPOS_SendNCCalcSize
582 * Send a WM_NCCALCSIZE message to a window.
583 * All parameters are read-only except newClientRect.
584 * oldWindowRect, oldClientRect and winpos must be non-NULL only
585 * when calcValidRect is TRUE.
587 LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect, RECT *newWindowRect,
588 RECT *oldWindowRect, RECT *oldClientRect,
589 WINDOWPOS *winpos, RECT *newClientRect )
591 NCCALCSIZE_PARAMS params;
592 LONG result;
594 params.rgrc[0] = *newWindowRect;
595 if (calcValidRect)
597 params.rgrc[1] = *oldWindowRect;
598 params.rgrc[2] = *oldClientRect;
599 params.lppos = winpos;
601 result = SendMessage( hwnd, WM_NCCALCSIZE, calcValidRect,
602 MAKE_SEGPTR( &params ) );
603 *newClientRect = params.rgrc[0];
604 return result;
608 /***********************************************************************
609 * WINPOS_HandleWindowPosChanging
611 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
613 LONG WINPOS_HandleWindowPosChanging( WINDOWPOS *winpos )
615 POINT maxSize;
616 WND *wndPtr = WIN_FindWndPtr( winpos->hwnd );
617 if (!wndPtr || (winpos->flags & SWP_NOSIZE)) return 0;
618 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
619 (wndPtr->dwStyle & (WS_POPUP | WS_CHILD) == 0))
621 NC_GetMinMaxInfo( winpos->hwnd, &maxSize, NULL, NULL, NULL );
622 winpos->cx = MIN( winpos->cx, maxSize.x );
623 winpos->cy = MIN( winpos->cy, maxSize.y );
625 return 0;
629 /***********************************************************************
630 * WINPOS_MoveWindowZOrder
632 * Move a window in Z order, invalidating everything that needs it.
633 * Only necessary for windows without associated X window.
635 static void WINPOS_MoveWindowZOrder( HWND hwnd, HWND hwndAfter )
637 BOOL movingUp;
638 HWND hwndCur;
639 WND *wndPtr = WIN_FindWndPtr( hwnd );
641 /* We have two possible cases:
642 * - The window is moving up: we have to invalidate all areas
643 * of the window that were covered by other windows
644 * - The window is moving down: we have to invalidate areas
645 * of other windows covered by this one.
648 if (hwndAfter == HWND_TOP)
650 movingUp = TRUE;
652 else if (hwndAfter == HWND_BOTTOM)
654 if (!wndPtr->hwndNext) return; /* Already at the bottom */
655 movingUp = FALSE;
657 else
659 if (wndPtr->hwndNext == hwndAfter) return; /* Already placed right */
661 /* Determine which window we encounter first in Z-order */
662 hwndCur = GetWindow( wndPtr->hwndParent, GW_CHILD );
663 while ((hwndCur != hwnd) && (hwndCur != hwndAfter))
664 hwndCur = GetWindow( hwndCur, GW_HWNDNEXT );
665 movingUp = (hwndCur == hwndAfter);
668 if (movingUp)
670 HWND hwndPrevAfter = wndPtr->hwndNext;
671 WIN_UnlinkWindow( hwnd );
672 WIN_LinkWindow( hwnd, hwndAfter );
673 hwndCur = wndPtr->hwndNext;
674 while (hwndCur != hwndPrevAfter)
676 WND *curPtr = WIN_FindWndPtr( hwndCur );
677 RECT rect = curPtr->rectWindow;
678 OffsetRect( &rect, -wndPtr->rectClient.left,
679 -wndPtr->rectClient.top );
680 RedrawWindow( hwnd, &rect, 0, RDW_INVALIDATE | RDW_ALLCHILDREN |
681 RDW_FRAME | RDW_ERASE );
682 hwndCur = curPtr->hwndNext;
685 else /* Moving down */
687 hwndCur = wndPtr->hwndNext;
688 WIN_UnlinkWindow( hwnd );
689 WIN_LinkWindow( hwnd, hwndAfter );
690 while (hwndCur != hwnd)
692 WND *curPtr = WIN_FindWndPtr( hwndCur );
693 RECT rect = wndPtr->rectWindow;
694 OffsetRect( &rect, -curPtr->rectClient.left,
695 -curPtr->rectClient.top );
696 RedrawWindow( hwndCur, &rect, 0, RDW_INVALIDATE | RDW_ALLCHILDREN |
697 RDW_FRAME | RDW_ERASE );
698 hwndCur = curPtr->hwndNext;
704 /***********************************************************************
705 * WINPOS_SetXWindowPos
707 * SetWindowPos() for an X window. Used by the real SetWindowPos().
709 static void WINPOS_SetXWindowPos( WINDOWPOS *winpos )
711 XWindowChanges winChanges;
712 int changeMask = 0;
713 WND *wndPtr = WIN_FindWndPtr( winpos->hwnd );
715 if (!(winpos->flags & SWP_NOSIZE))
717 winChanges.width = winpos->cx;
718 winChanges.height = winpos->cy;
719 changeMask |= CWWidth | CWHeight;
721 if (!(winpos->flags & SWP_NOMOVE))
723 winChanges.x = winpos->x;
724 winChanges.y = winpos->y;
725 changeMask |= CWX | CWY;
727 if (!(winpos->flags & SWP_NOZORDER))
729 if (winpos->hwndInsertAfter == HWND_TOP) winChanges.stack_mode = Above;
730 else winChanges.stack_mode = Below;
731 if ((winpos->hwndInsertAfter != HWND_TOP) &&
732 (winpos->hwndInsertAfter != HWND_BOTTOM))
734 WND * insertPtr = WIN_FindWndPtr( winpos->hwndInsertAfter );
735 winChanges.sibling = insertPtr->window;
736 changeMask |= CWSibling;
738 changeMask |= CWStackMode;
740 if (changeMask)
741 XConfigureWindow( display, wndPtr->window, changeMask, &winChanges );
745 /***********************************************************************
746 * SetWindowPos (USER.232)
748 BOOL SetWindowPos( HWND hwnd, HWND hwndInsertAfter, INT x, INT y,
749 INT cx, INT cy, WORD flags )
751 WINDOWPOS winpos;
752 WND *wndPtr;
753 RECT newWindowRect, newClientRect;
754 int result;
756 /* Check window handle */
758 if (hwnd == GetDesktopWindow()) return FALSE;
759 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
761 /* Check dimensions */
763 if (cx <= 0) cx = 1;
764 if (cy <= 0) cy = 1;
766 /* Check flags */
768 if (hwnd == hwndActive) flags |= SWP_NOACTIVATE; /* Already active */
769 if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
770 (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
771 flags |= SWP_NOSIZE; /* Already the right size */
772 if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
773 flags |= SWP_NOMOVE; /* Already the right position */
775 /* Check hwndInsertAfter */
777 if (!(flags & (SWP_NOZORDER | SWP_NOACTIVATE)))
779 /* Ignore TOPMOST flags when activating a window */
780 /* _and_ moving it in Z order. */
781 if ((hwndInsertAfter == HWND_TOPMOST) ||
782 (hwndInsertAfter == HWND_NOTOPMOST))
783 hwndInsertAfter = HWND_TOP;
785 /* TOPMOST not supported yet */
786 if ((hwndInsertAfter == HWND_TOPMOST) ||
787 (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
788 /* hwndInsertAfter must be a sibling of the window */
789 if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM) &&
790 (wndPtr->hwndParent != WIN_FindWndPtr(hwndInsertAfter)->hwndParent))
791 return FALSE;
793 /* Fill the WINDOWPOS structure */
795 winpos.hwnd = hwnd;
796 winpos.hwndInsertAfter = hwndInsertAfter;
797 winpos.x = x;
798 winpos.y = y;
799 winpos.cx = cx;
800 winpos.cy = cy;
801 winpos.flags = flags;
803 /* Send WM_WINDOWPOSCHANGING message */
805 if (!(flags & SWP_NOSENDCHANGING))
806 SendMessage( hwnd, WM_WINDOWPOSCHANGING, 0, MAKE_SEGPTR(&winpos) );
808 /* Calculate new position and size */
810 newWindowRect = wndPtr->rectWindow;
811 newClientRect = wndPtr->rectClient;
813 if (!(winpos.flags & SWP_NOSIZE))
815 newWindowRect.right = newWindowRect.left + winpos.cx;
816 newWindowRect.bottom = newWindowRect.top + winpos.cy;
818 if (!(winpos.flags & SWP_NOMOVE))
820 newWindowRect.left = winpos.x;
821 newWindowRect.top = winpos.y;
822 newWindowRect.right += winpos.x - wndPtr->rectWindow.left;
823 newWindowRect.bottom += winpos.y - wndPtr->rectWindow.top;
826 /* Reposition window in Z order */
828 if (!(winpos.flags & SWP_NOZORDER))
830 if (wndPtr->window)
832 WIN_UnlinkWindow( winpos.hwnd );
833 WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
835 else WINPOS_MoveWindowZOrder( winpos.hwnd, hwndInsertAfter );
838 /* Send WM_NCCALCSIZE message to get new client area */
840 result = WINPOS_SendNCCalcSize( winpos.hwnd, TRUE, &newWindowRect,
841 &wndPtr->rectWindow, &wndPtr->rectClient,
842 &winpos, &newClientRect );
843 /* .... Should handle result here */
845 /* Perform the moving and resizing */
847 if (wndPtr->window)
849 WINPOS_SetXWindowPos( &winpos );
850 wndPtr->rectWindow = newWindowRect;
851 wndPtr->rectClient = newClientRect;
853 else
855 RECT oldWindowRect = wndPtr->rectWindow;
857 wndPtr->rectWindow = newWindowRect;
858 wndPtr->rectClient = newClientRect;
860 if (!(flags & SWP_NOREDRAW) &&
861 (!(flags & SWP_NOSIZE) || !(flags & SWP_NOMOVE) ||
862 !(flags & SWP_NOZORDER)))
864 HRGN hrgn1 = CreateRectRgnIndirect( &oldWindowRect );
865 HRGN hrgn2 = CreateRectRgnIndirect( &wndPtr->rectWindow );
866 HRGN hrgn3 = CreateRectRgn( 0, 0, 0, 0 );
867 CombineRgn( hrgn3, hrgn1, hrgn2, RGN_DIFF );
868 RedrawWindow( wndPtr->hwndParent, NULL, hrgn3,
869 RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE );
870 if ((oldWindowRect.left != wndPtr->rectWindow.left) ||
871 (oldWindowRect.top != wndPtr->rectWindow.top))
873 RedrawWindow( winpos.hwnd, NULL, 0, RDW_INVALIDATE |
874 RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE );
876 DeleteObject( hrgn1 );
877 DeleteObject( hrgn2 );
878 DeleteObject( hrgn3 );
882 if (flags & SWP_SHOWWINDOW)
884 wndPtr->dwStyle |= WS_VISIBLE;
885 if (wndPtr->window)
887 XMapWindow( display, wndPtr->window );
889 else
891 if (!(flags & SWP_NOREDRAW))
892 RedrawWindow( winpos.hwnd, NULL, 0,
893 RDW_INVALIDATE | RDW_FRAME | RDW_ERASE );
896 else if (flags & SWP_HIDEWINDOW)
898 wndPtr->dwStyle &= ~WS_VISIBLE;
899 if (wndPtr->window)
901 XUnmapWindow( display, wndPtr->window );
903 else
905 if (!(flags & SWP_NOREDRAW))
906 RedrawWindow( wndPtr->hwndParent, &wndPtr->rectWindow, 0,
907 RDW_INVALIDATE | RDW_FRAME |
908 RDW_ALLCHILDREN | RDW_ERASE );
910 if ((winpos.hwnd == GetFocus()) || IsChild(winpos.hwnd, GetFocus()))
911 SetFocus( GetParent(winpos.hwnd) ); /* Revert focus to parent */
912 if (winpos.hwnd == hwndActive)
914 /* Activate previously active window if possible */
915 HWND newActive = wndPtr->hwndPrevActive;
916 if (!IsWindow(newActive) || (newActive == winpos.hwnd))
918 newActive = GetTopWindow(GetDesktopWindow());
919 if (newActive == winpos.hwnd) newActive = wndPtr->hwndNext;
921 WINPOS_ChangeActiveWindow( newActive, FALSE );
925 /* Activate the window */
927 if (!(flags & SWP_NOACTIVATE))
929 if (!(wndPtr->dwStyle & WS_CHILD))
930 WINPOS_ChangeActiveWindow( winpos.hwnd, FALSE );
933 /* Repaint the window */
935 if (wndPtr->window) MSG_Synchronize(); /* Wait for all expose events */
936 EVENT_DummyMotionNotify(); /* Simulate a mouse event to set the cursor */
937 if ((flags & SWP_FRAMECHANGED) && !(flags & SWP_NOREDRAW))
938 RedrawWindow( winpos.hwnd, NULL, 0,
939 RDW_INVALIDATE | RDW_FRAME | RDW_ERASE );
940 if (!(flags & SWP_DEFERERASE))
941 RedrawWindow( wndPtr->hwndParent, NULL, 0,
942 RDW_ALLCHILDREN | RDW_ERASENOW );
944 /* And last, send the WM_WINDOWPOSCHANGED message */
946 winpos.flags |= SWP_NOMOVE; /* prevent looping.. window is already moved ??? (FIXME)*/
948 if (!(winpos.flags & SWP_NOSENDCHANGING))
949 SendMessage( winpos.hwnd, WM_WINDOWPOSCHANGED,
950 0, MAKE_SEGPTR(&winpos) );
952 return TRUE;
956 /***********************************************************************
957 * BeginDeferWindowPos (USER.259)
959 HDWP BeginDeferWindowPos( INT count )
961 HDWP handle;
962 DWP *pDWP;
964 if (count <= 0) return 0;
965 handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
966 if (!handle) return 0;
967 pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
968 pDWP->actualCount = 0;
969 pDWP->suggestedCount = count;
970 pDWP->valid = TRUE;
971 pDWP->wMagic = DWP_MAGIC;
972 pDWP->hwndParent = 0;
973 return handle;
977 /***********************************************************************
978 * DeferWindowPos (USER.260)
980 HDWP DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter, INT x, INT y,
981 INT cx, INT cy, WORD flags )
983 DWP *pDWP;
984 int i;
985 HDWP newhdwp = hdwp;
986 HWND parent;
988 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
989 if (!pDWP) return 0;
991 /* All the windows of a DeferWindowPos() must have the same parent */
993 parent = WIN_FindWndPtr( hwnd )->hwndParent;
994 if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
995 else if (parent != pDWP->hwndParent)
997 USER_HEAP_FREE( hdwp );
998 return 0;
1001 for (i = 0; i < pDWP->actualCount; i++)
1003 if (pDWP->winPos[i].hwnd == hwnd)
1005 /* Merge with the other changes */
1006 if (!(flags & SWP_NOZORDER))
1008 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
1010 if (!(flags & SWP_NOMOVE))
1012 pDWP->winPos[i].x = x;
1013 pDWP->winPos[i].y = y;
1015 if (!(flags & SWP_NOSIZE))
1017 pDWP->winPos[i].cx = cx;
1018 pDWP->winPos[i].cy = cy;
1020 pDWP->winPos[i].flags &= flags & (SWP_NOSIZE | SWP_NOMOVE |
1021 SWP_NOZORDER | SWP_NOREDRAW |
1022 SWP_NOACTIVATE | SWP_NOCOPYBITS |
1023 SWP_NOOWNERZORDER);
1024 pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
1025 SWP_FRAMECHANGED);
1026 return hdwp;
1029 if (pDWP->actualCount >= pDWP->suggestedCount)
1031 newhdwp = USER_HEAP_REALLOC( hdwp,
1032 sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
1033 if (!newhdwp) return 0;
1034 pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
1035 pDWP->suggestedCount++;
1037 pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
1038 pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
1039 pDWP->winPos[pDWP->actualCount].x = x;
1040 pDWP->winPos[pDWP->actualCount].y = y;
1041 pDWP->winPos[pDWP->actualCount].cx = cx;
1042 pDWP->winPos[pDWP->actualCount].cy = cy;
1043 pDWP->winPos[pDWP->actualCount].flags = flags;
1044 pDWP->actualCount++;
1045 return newhdwp;
1049 /***********************************************************************
1050 * EndDeferWindowPos (USER.261)
1052 BOOL EndDeferWindowPos( HDWP hdwp )
1054 DWP *pDWP;
1055 WINDOWPOS *winpos;
1056 BOOL res = TRUE;
1057 int i;
1059 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
1060 if (!pDWP) return FALSE;
1061 for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
1063 if (!(res = SetWindowPos( winpos->hwnd, winpos->hwndInsertAfter,
1064 winpos->x, winpos->y, winpos->cx, winpos->cy,
1065 winpos->flags ))) break;
1067 USER_HEAP_FREE( hdwp );
1068 return res;
1072 /***********************************************************************
1073 * TileChildWindows (USER.199)
1075 void TileChildWindows( HWND parent, WORD action )
1077 printf("STUB TileChildWindows("NPFMT", %d)\n", parent, action);
1080 /***********************************************************************
1081 * CascageChildWindows (USER.198)
1083 void CascadeChildWindows( HWND parent, WORD action )
1085 printf("STUB CascadeChildWindows("NPFMT", %d)\n", parent, action);