Release 940912
[wine/gsoc-2012-control.git] / windows / winpos.c
bloba9415cdfde6ba8d105f73e02464a42054721ea97
1 /*
2 * Window position related functions.
4 * Copyright 1993 Alexandre Julliard
5 */
7 static char Copyright[] = "Copyright Alexandre Julliard, 1993";
9 #include "sysmetrics.h"
10 #include "user.h"
11 #include "win.h"
12 #include "message.h"
13 #include <assert.h>
15 static HWND hwndActive = 0; /* Currently active window */
17 /* #define DEBUG_WIN /**/
20 /***********************************************************************
21 * GetWindowRect (USER.32)
23 void GetWindowRect( HWND hwnd, LPRECT rect )
25 WND * wndPtr = WIN_FindWndPtr( hwnd );
26 if (!wndPtr) return;
28 *rect = wndPtr->rectWindow;
29 if (wndPtr->dwStyle & WS_CHILD)
30 MapWindowPoints( wndPtr->hwndParent, 0, (POINT *)rect, 2 );
34 /***********************************************************************
35 * GetClientRect (USER.33)
37 void GetClientRect( HWND hwnd, LPRECT rect )
39 WND * wndPtr = WIN_FindWndPtr( hwnd );
41 rect->left = rect->top = rect->right = rect->bottom = 0;
42 if (wndPtr)
44 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
45 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
50 /*******************************************************************
51 * ClientToScreen (USER.28)
53 void ClientToScreen( HWND hwnd, LPPOINT lppnt )
55 MapWindowPoints( hwnd, 0, lppnt, 1 );
59 /*******************************************************************
60 * ScreenToClient (USER.29)
62 void ScreenToClient( HWND hwnd, LPPOINT lppnt )
64 MapWindowPoints( 0, hwnd, lppnt, 1 );
68 /*******************************************************************
69 * WindowFromPoint (USER.30)
71 HWND WindowFromPoint( POINT pt )
73 HWND hwndRet = 0;
74 HWND hwnd = GetDesktopWindow();
76 while(hwnd)
78 /* If point is in window, and window is visible, */
79 /* not disabled and not transparent, then explore */
80 /* its children. Otherwise, go to the next window. */
82 WND *wndPtr = WIN_FindWndPtr( hwnd );
83 if ((pt.x >= wndPtr->rectWindow.left) &&
84 (pt.x < wndPtr->rectWindow.right) &&
85 (pt.y >= wndPtr->rectWindow.top) &&
86 (pt.y < wndPtr->rectWindow.bottom) &&
87 !(wndPtr->dwStyle & WS_DISABLED) &&
88 (wndPtr->dwStyle & WS_VISIBLE) &&
89 !(wndPtr->dwExStyle & WS_EX_TRANSPARENT))
91 pt.x -= wndPtr->rectClient.left;
92 pt.y -= wndPtr->rectClient.top;
93 hwndRet = hwnd;
94 hwnd = wndPtr->hwndChild;
96 else hwnd = wndPtr->hwndNext;
98 return hwndRet;
102 /*******************************************************************
103 * ChildWindowFromPoint (USER.191)
105 HWND ChildWindowFromPoint( HWND hwndParent, POINT pt )
107 RECT rect;
108 HWND hwnd;
110 GetWindowRect( hwndParent, &rect );
111 if (!PtInRect( &rect, pt )) return 0;
112 hwnd = GetTopWindow( hwndParent );
113 while (hwnd)
115 GetWindowRect( hwnd, &rect );
116 if (PtInRect( &rect, pt )) return hwnd;
117 hwnd = GetWindow( hwnd, GW_HWNDNEXT );
119 return hwndParent;
123 /*******************************************************************
124 * MapWindowPoints (USER.258)
126 void MapWindowPoints( HWND hwndFrom, HWND hwndTo, LPPOINT lppt, WORD count )
128 WND * wndPtr;
129 POINT * curpt;
130 POINT origin = { 0, 0 };
131 WORD i;
133 /* Translate source window origin to screen coords */
134 while(hwndFrom)
136 wndPtr = WIN_FindWndPtr( hwndFrom );
137 origin.x += wndPtr->rectClient.left;
138 origin.y += wndPtr->rectClient.top;
139 hwndFrom = (wndPtr->dwStyle & WS_CHILD) ? wndPtr->hwndParent : 0;
142 /* Translate origin to destination window coords */
143 while(hwndTo)
145 wndPtr = WIN_FindWndPtr( hwndTo );
146 origin.x -= wndPtr->rectClient.left;
147 origin.y -= wndPtr->rectClient.top;
148 hwndTo = (wndPtr->dwStyle & WS_CHILD) ? wndPtr->hwndParent : 0;
151 /* Translate points */
152 for (i = 0, curpt = lppt; i < count; i++, curpt++)
154 curpt->x += origin.x;
155 curpt->y += origin.y;
160 /***********************************************************************
161 * IsIconic (USER.31)
163 BOOL IsIconic(HWND hWnd)
165 WND * wndPtr = WIN_FindWndPtr(hWnd);
166 if (wndPtr == NULL) return FALSE;
167 return (wndPtr->dwStyle & WS_MINIMIZE) != 0;
171 /***********************************************************************
172 * IsZoomed (USER.272)
174 BOOL IsZoomed(HWND hWnd)
176 WND * wndPtr = WIN_FindWndPtr(hWnd);
177 if (wndPtr == NULL) return FALSE;
178 return (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
182 /*******************************************************************
183 * GetActiveWindow (USER.60)
185 HWND GetActiveWindow()
187 return hwndActive;
190 /*******************************************************************
191 * SetActiveWindow (USER.59)
193 HWND SetActiveWindow( HWND hwnd )
195 HWND prev = hwndActive;
196 WND *wndPtr = WIN_FindWndPtr( hwnd );
197 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD)) return 0;
198 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
199 return prev;
203 /***********************************************************************
204 * BringWindowToTop (USER.45)
206 BOOL BringWindowToTop( HWND hwnd )
208 return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
212 /***********************************************************************
213 * MoveWindow (USER.56)
215 BOOL MoveWindow( HWND hwnd, short x, short y, short cx, short cy, BOOL repaint)
217 int flags = SWP_NOZORDER | SWP_NOACTIVATE;
218 if (!repaint) flags |= SWP_NOREDRAW;
219 #ifdef DEBUG_WIN
220 printf( "MoveWindow: %d %d,%d %dx%d %d\n", hwnd, x, y, cx, cy, repaint );
221 #endif
222 return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
227 * hwnd is the handle to the first child window to hide
229 static void WINPOS_hideChildren(HWND hwnd)
231 WND *wndPtr;
233 while (hwnd) {
234 ShowWindow(hwnd, SW_HIDE);
235 wndPtr = WIN_FindWndPtr(hwnd);
236 assert(wndPtr);
237 WINPOS_hideChildren(wndPtr->hwndChild);
238 hwnd = wndPtr->hwndNext;
243 static void WINPOS_ChildrenComeOutToPlay(HWND hwnd)
245 WND *wndPtr;
247 while (hwnd) {
249 * we shouldn't really be calling SW_SHOWNOACTIVATE
250 * here because we wake up all windows, even the ones
251 * the user has decided to iconify or hide
253 * have to use SHOWNOACTIVATE instead of SHOWNORMAL
254 * since we are traversing the window tree and don't
255 * want windows linked/unlined under us
257 ShowWindow(hwnd, SW_SHOWNOACTIVATE);
258 wndPtr = WIN_FindWndPtr(hwnd);
259 assert(wndPtr);
260 WINPOS_ChildrenComeOutToPlay(wndPtr->hwndChild);
261 hwnd = wndPtr->hwndNext;
265 /***********************************************************************
266 * ShowWindow (USER.42)
268 BOOL ShowWindow( HWND hwnd, int cmd )
270 WND * wndPtr = WIN_FindWndPtr( hwnd );
271 BOOL wasVisible;
272 BOOL wasIconic;
273 int swpflags = 0;
275 if (!wndPtr) return FALSE;
277 #ifdef DEBUG_WIN
278 printf("ShowWindow: hwnd=%04X, cmd=%d\n", hwnd, cmd);
279 #endif
282 * wasVisible is true if user has not made window invisible
283 * wasIconic is true if the window is not iconified
285 wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
287 switch(cmd)
289 case SW_HIDE:
291 * if the window wasn't visible to begin with -- just return
293 if (!wasVisible)
294 return FALSE; /* Nothing to do */
295 swpflags |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
296 SWP_NOACTIVATE | SWP_NOZORDER;
297 break;
300 case SW_SHOWMINNOACTIVE:
301 case SW_SHOWMINIMIZED:
302 case SW_MINIMIZE:
303 wndPtr->dwStyle |= WS_MINIMIZE;
304 swpflags |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE |
305 SWP_NOACTIVATE | SWP_NOZORDER;
308 * tell children that they are getting hidden
310 WINPOS_hideChildren(wndPtr->hwndChild);
312 /* store the size and position of the window, so we can
313 * deiconify it to the same size and position
315 wndPtr->rectNormal = wndPtr->rectWindow;
316 wndPtr->ptIconPos.x = wndPtr->rectWindow.left;
317 wndPtr->ptIconPos.y = wndPtr->rectWindow.top;
318 /* move the window to icon size and position and
319 * tell it that it is going to have to be painted
321 MoveWindow(hwnd, wndPtr->ptIconPos.x, wndPtr->ptIconPos.y,
322 wndPtr->iconWidth, wndPtr->iconHeight, FALSE);
323 SendMessage(hwnd, WM_PAINTICON, 0, 0);
324 break;
327 case SW_SHOWNA:
328 case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE: */
329 case SW_SHOW:
330 swpflags |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
331 break;
334 case SW_SHOWNORMAL: /* same as SW_NORMAL: */
335 case SW_SHOWNOACTIVATE:
336 case SW_RESTORE:
337 wasIconic = IsIconic(hwnd);
338 wndPtr->dwStyle &= ~WS_MINIMIZE;
339 wndPtr->dwStyle &= ~WS_MAXIMIZE;
340 swpflags |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
341 if (cmd == SW_SHOWNOACTIVATE)
343 swpflags |= SWP_NOZORDER;
344 if (GetActiveWindow()) swpflags |= SWP_NOACTIVATE;
346 if (wasIconic) {
347 MoveWindow(hwnd, wndPtr->rectNormal.left,
348 wndPtr->rectNormal.top,
349 wndPtr->rectNormal.right - wndPtr->rectNormal.left,
350 wndPtr->rectNormal.bottom - wndPtr->rectNormal.top,
351 FALSE);
353 WINPOS_ChildrenComeOutToPlay(wndPtr->hwndChild);
354 break;
357 SendMessage( hwnd, WM_SHOWWINDOW, (cmd != SW_HIDE), 0 );
358 SetWindowPos( hwnd, 0, 0, 0, 0, 0, swpflags );
360 /* Send WM_SIZE and WM_MOVE messages if not already done */
361 if (!(wndPtr->flags & WIN_GOT_SIZEMSG))
363 int wParam = SIZE_RESTORED;
364 if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
365 else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
366 wndPtr->flags |= WIN_GOT_SIZEMSG;
367 SendMessage( hwnd, WM_SIZE, wParam,
368 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
369 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
370 SendMessage( hwnd, WM_MOVE, 0,
371 MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
374 return wasVisible;
378 /***********************************************************************
379 * GetInternalWindowPos (USER.460)
381 WORD GetInternalWindowPos( HWND hwnd, LPRECT rectWnd, LPPOINT ptIcon )
383 WINDOWPLACEMENT wndpl;
384 if (!GetWindowPlacement( hwnd, &wndpl )) return 0;
385 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
386 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
387 return wndpl.showCmd;
391 /***********************************************************************
392 * SetInternalWindowPos (USER.461)
394 void SetInternalWindowPos( HWND hwnd, WORD showCmd, LPRECT rect, LPPOINT pt )
396 WINDOWPLACEMENT wndpl;
397 WND *wndPtr = WIN_FindWndPtr( hwnd );
399 wndpl.length = sizeof(wndpl);
400 wndpl.flags = (pt != NULL) ? WPF_SETMINPOSITION : 0;
401 wndpl.showCmd = showCmd;
402 if (pt) wndpl.ptMinPosition = *pt;
403 wndpl.rcNormalPosition = (rect != NULL) ? *rect : wndPtr->rectNormal;
404 wndpl.ptMaxPosition = wndPtr->ptMaxPos;
405 SetWindowPlacement( hwnd, &wndpl );
409 /***********************************************************************
410 * GetWindowPlacement (USER.370)
412 BOOL GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *wndpl )
414 WND *wndPtr = WIN_FindWndPtr( hwnd );
415 if (!wndPtr) return FALSE;
417 wndpl->length = sizeof(*wndpl);
418 wndpl->flags = 0;
419 wndpl->showCmd = IsZoomed(hwnd) ? SW_SHOWMAXIMIZED :
420 (IsIconic(hwnd) ? SW_SHOWMINIMIZED : SW_SHOWNORMAL);
421 wndpl->ptMinPosition = wndPtr->ptIconPos;
422 wndpl->ptMaxPosition = wndPtr->ptMaxPos;
423 wndpl->rcNormalPosition = wndPtr->rectNormal;
424 return TRUE;
428 /***********************************************************************
429 * SetWindowPlacement (USER.371)
431 BOOL SetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *wndpl )
433 WND *wndPtr = WIN_FindWndPtr( hwnd );
434 if (!wndPtr) return FALSE;
436 if (wndpl->flags & WPF_SETMINPOSITION)
437 wndPtr->ptIconPos = wndpl->ptMinPosition;
438 if ((wndpl->flags & WPF_RESTORETOMAXIMIZED) &&
439 (wndpl->showCmd == SW_SHOWMINIMIZED)) wndPtr->flags |= WIN_RESTORE_MAX;
440 wndPtr->ptMaxPos = wndpl->ptMaxPosition;
441 wndPtr->rectNormal = wndpl->rcNormalPosition;
442 ShowWindow( hwnd, wndpl->showCmd );
443 return TRUE;
447 /*******************************************************************
448 * WINPOS_GetMinMaxInfo
450 * Send a WM_GETMINMAXINFO to the window.
452 void WINPOS_GetMinMaxInfo( HWND hwnd, POINT *maxSize, POINT *maxPos,
453 POINT *minTrack, POINT *maxTrack )
455 HANDLE minmaxHandle;
456 MINMAXINFO MinMax, *pMinMax;
457 WND *wndPtr = WIN_FindWndPtr( hwnd );
459 MinMax.ptMaxSize.x = SYSMETRICS_CXSCREEN;
460 MinMax.ptMaxSize.y = SYSMETRICS_CYSCREEN;
461 MinMax.ptMaxPosition = wndPtr->ptMaxPos;
462 MinMax.ptMinTrackSize.x = SYSMETRICS_CXMINTRACK;
463 MinMax.ptMinTrackSize.y = SYSMETRICS_CYMINTRACK;
464 MinMax.ptMaxTrackSize.x = SYSMETRICS_CXSCREEN;
465 MinMax.ptMaxTrackSize.y = SYSMETRICS_CYSCREEN;
467 minmaxHandle = USER_HEAP_ALLOC( LMEM_MOVEABLE, sizeof(MINMAXINFO) );
468 if (minmaxHandle)
470 pMinMax = (MINMAXINFO *) USER_HEAP_ADDR( minmaxHandle );
471 memcpy( pMinMax, &MinMax, sizeof(MinMax) );
472 SendMessage( hwnd, WM_GETMINMAXINFO, 0, (LONG)pMinMax );
474 else pMinMax = &MinMax;
476 /* Some sanity checks */
478 pMinMax->ptMaxTrackSize.x = max( pMinMax->ptMaxTrackSize.x,
479 pMinMax->ptMinTrackSize.x );
480 pMinMax->ptMaxTrackSize.y = max( pMinMax->ptMaxTrackSize.y,
481 pMinMax->ptMinTrackSize.y );
483 if (maxSize) *maxSize = pMinMax->ptMaxSize;
484 if (maxPos) *maxPos = pMinMax->ptMaxPosition;
485 if (minTrack) *minTrack = pMinMax->ptMinTrackSize;
486 if (maxTrack) *maxTrack = pMinMax->ptMaxTrackSize;
487 if (minmaxHandle) USER_HEAP_FREE( minmaxHandle );
491 /*******************************************************************
492 * WINPOS_ChangeActiveWindow
494 * Change the active window and send the corresponding messages.
496 HWND WINPOS_ChangeActiveWindow( HWND hwnd, BOOL mouseMsg )
498 HWND prevActive = hwndActive;
499 if (hwnd == hwndActive) return 0;
500 if (hwndActive)
502 if (!SendMessage( hwndActive, WM_NCACTIVATE, FALSE, 0 )) return 0;
503 SendMessage( hwndActive, WM_ACTIVATE, WA_INACTIVE,
504 MAKELONG( IsIconic(hwndActive), hwnd ) );
505 /* Send WM_ACTIVATEAPP here */
508 hwndActive = hwnd;
509 if (hwndActive)
511 WND *wndPtr = WIN_FindWndPtr( hwndActive );
512 wndPtr->hwndPrevActive = prevActive;
514 /* Send WM_ACTIVATEAPP here */
515 SendMessage( hwnd, WM_NCACTIVATE, TRUE, 0 );
516 SendMessage( hwnd, WM_ACTIVATE, mouseMsg ? WA_CLICKACTIVE : WA_ACTIVE,
517 MAKELONG( IsIconic(hwnd), prevActive ) );
519 return prevActive;
523 /***********************************************************************
524 * WINPOS_SendNCCalcSize
526 * Send a WM_NCCALCSIZE message to a window.
527 * All parameters are read-only except newClientRect.
528 * oldWindowRect, oldClientRect and winpos must be non-NULL only
529 * when calcValidRect is TRUE.
531 LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect, RECT *newWindowRect,
532 RECT *oldWindowRect, RECT *oldClientRect,
533 WINDOWPOS *winpos, RECT *newClientRect )
535 NCCALCSIZE_PARAMS *params;
536 HANDLE hparams;
537 LONG result;
539 if (!(hparams = USER_HEAP_ALLOC( GMEM_MOVEABLE, sizeof(*params) )))
540 return 0;
541 params = (NCCALCSIZE_PARAMS *) USER_HEAP_ADDR( hparams );
542 params->rgrc[0] = *newWindowRect;
543 if (calcValidRect)
545 params->rgrc[1] = *oldWindowRect;
546 params->rgrc[2] = *oldClientRect;
547 params->lppos = winpos;
549 result = SendMessage( hwnd, WM_NCCALCSIZE, calcValidRect, (LONG)params);
550 *newClientRect = params->rgrc[0];
551 USER_HEAP_FREE( hparams );
552 return result;
556 /***********************************************************************
557 * WINPOS_HandleWindowPosChanging
559 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
561 LONG WINPOS_HandleWindowPosChanging( WINDOWPOS *winpos )
563 POINT maxSize;
564 WND *wndPtr = WIN_FindWndPtr( winpos->hwnd );
565 if (!wndPtr || (winpos->flags & SWP_NOSIZE)) return 0;
566 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
567 (wndPtr->dwStyle & (WS_POPUP | WS_CHILD) == 0))
569 WINPOS_GetMinMaxInfo( winpos->hwnd, &maxSize, NULL, NULL, NULL );
570 winpos->cx = min( winpos->cx, maxSize.x );
571 winpos->cy = min( winpos->cy, maxSize.y );
573 return 0;
577 /***********************************************************************
578 * WINPOS_InternalSetWindowPos
580 * Helper function for SetWindowPos.
582 static BOOL WINPOS_InternalSetWindowPos( WINDOWPOS *winpos )
584 HWND hwndAfter;
585 WND *wndPtr;
586 RECT newWindowRect, newClientRect;
587 int flags, result;
588 int changeMask = 0;
589 XWindowChanges winChanges;
591 /* Send WM_WINDOWPOSCHANGING message */
593 if (!(winpos->flags & SWP_NOSENDCHANGING))
594 SendMessage( winpos->hwnd, WM_WINDOWPOSCHANGING, 0, (LONG)winpos );
596 /* Check window handle */
598 if (winpos->hwnd == GetDesktopWindow()) return FALSE;
599 if (!(wndPtr = WIN_FindWndPtr( winpos->hwnd ))) return FALSE;
601 /* Check dimensions */
603 if (winpos->cx <= 0) winpos->cx = 1;
604 if (winpos->cy <= 0) winpos->cy = 1;
606 /* Check flags */
608 flags = winpos->flags;
609 if (flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW))
610 flags |= SWP_NOMOVE | SWP_NOSIZE;
611 if (winpos->hwnd == hwndActive) flags |= SWP_NOACTIVATE; /*Already active*/
613 /* Check hwndAfter */
615 hwndAfter = winpos->hwndInsertAfter;
616 if (!(flags & (SWP_NOZORDER | SWP_NOACTIVATE)))
618 /* Ignore TOPMOST flags when activating a window */
619 /* _and_ moving it in Z order. */
620 if ((hwndAfter == HWND_TOPMOST) || (hwndAfter == HWND_NOTOPMOST))
621 hwndAfter = HWND_TOP;
623 /* TOPMOST not supported yet */
624 if ((hwndAfter == HWND_TOPMOST) || (hwndAfter == HWND_NOTOPMOST))
625 hwndAfter = HWND_TOP;
626 /* hwndAfter must be a sibling of the window */
627 if ((hwndAfter != HWND_TOP) && (hwndAfter != HWND_BOTTOM) &&
628 (GetParent(winpos->hwnd) != GetParent(hwndAfter))) return FALSE;
630 /* Calculate new position and size */
632 newWindowRect = wndPtr->rectWindow;
633 newClientRect = wndPtr->rectClient;
635 if (!(flags & SWP_NOSIZE))
637 newWindowRect.right = newWindowRect.left + winpos->cx;
638 newWindowRect.bottom = newWindowRect.top + winpos->cy;
639 winChanges.width = winpos->cx;
640 winChanges.height = winpos->cy;
641 changeMask |= CWWidth | CWHeight;
643 if (!(flags & SWP_NOMOVE))
645 newWindowRect.left = winpos->x;
646 newWindowRect.top = winpos->y;
647 newWindowRect.right += winpos->x - wndPtr->rectWindow.left;
648 newWindowRect.bottom += winpos->y - wndPtr->rectWindow.top;
649 if (wndPtr->dwStyle & WS_CHILD)
651 WND *parentPtr = WIN_FindWndPtr(wndPtr->hwndParent);
652 winChanges.x = winpos->x + parentPtr->rectClient.left
653 - parentPtr->rectWindow.left;
654 winChanges.y = winpos->y + parentPtr->rectClient.top
655 - parentPtr->rectWindow.top;
657 else
659 winChanges.x = winpos->x;
660 winChanges.y = winpos->y;
662 changeMask |= CWX | CWY;
665 /* Reposition window in Z order */
667 if (!(flags & SWP_NOZORDER))
669 WIN_UnlinkWindow( winpos->hwnd );
670 WIN_LinkWindow( winpos->hwnd, hwndAfter );
671 if (hwndAfter == HWND_TOP) winChanges.stack_mode = Above;
672 else winChanges.stack_mode = Below;
673 if ((hwndAfter != HWND_TOP) && (hwndAfter != HWND_BOTTOM))
675 WND * insertPtr = WIN_FindWndPtr( hwndAfter );
676 winChanges.sibling = insertPtr->window;
677 changeMask |= CWSibling;
679 changeMask |= CWStackMode;
682 /* Send WM_NCCALCSIZE message to get new client area */
684 result = WINPOS_SendNCCalcSize( winpos->hwnd, TRUE, &newWindowRect,
685 &wndPtr->rectWindow, &wndPtr->rectClient,
686 winpos, &newClientRect );
687 /* .... Should handle result here */
689 /* Perform the moving and resizing */
691 if (changeMask) XConfigureWindow( display, wndPtr->window,
692 changeMask, &winChanges );
693 wndPtr->rectWindow = newWindowRect;
694 wndPtr->rectClient = newClientRect;
696 if (flags & SWP_SHOWWINDOW)
698 wndPtr->dwStyle |= WS_VISIBLE;
699 XMapWindow( display, wndPtr->window );
700 MSG_Synchronize();
701 if (flags & SWP_NOREDRAW) /* Validate the whole window */
702 RedrawWindow( winpos->hwnd, NULL, 0, RDW_VALIDATE );
704 else if (flags & SWP_HIDEWINDOW)
706 wndPtr->dwStyle &= ~WS_VISIBLE;
707 XUnmapWindow( display, wndPtr->window );
708 if ((winpos->hwnd == GetFocus()) || IsChild(winpos->hwnd, GetFocus()))
709 SetFocus( GetParent(winpos->hwnd) ); /* Revert focus to parent */
710 if (winpos->hwnd == hwndActive)
712 /* Activate previously active window if possible */
713 HWND newActive = wndPtr->hwndPrevActive;
714 if (!IsWindow(newActive) || (newActive == winpos->hwnd))
716 newActive = GetTopWindow(GetDesktopWindow());
717 if (newActive == winpos->hwnd) newActive = wndPtr->hwndNext;
719 WINPOS_ChangeActiveWindow( newActive, FALSE );
723 /* Activate the window */
725 if (!(flags & SWP_NOACTIVATE))
727 if (!(wndPtr->dwStyle & WS_CHILD))
728 WINPOS_ChangeActiveWindow( winpos->hwnd, FALSE );
731 /* Send WM_NCPAINT message if needed */
733 if (flags & SWP_SHOWWINDOW)
735 /* Repaint the window frame and background */
736 RedrawWindow( winpos->hwnd, NULL, 0,
737 RDW_INVALIDATE | RDW_FRAME | RDW_ERASENOW );
739 else
741 if ((flags & SWP_FRAMECHANGED) ||
742 (!(flags & SWP_NOSIZE)) ||
743 (!(flags & SWP_NOMOVE)) ||
744 (!(flags & SWP_NOACTIVATE)) ||
745 (!(flags & SWP_NOZORDER)))
746 SendMessage( winpos->hwnd, WM_NCPAINT, 1, 0L );
749 /* And last, send the WM_WINDOWPOSCHANGED message */
751 SendMessage( winpos->hwnd, WM_WINDOWPOSCHANGED, 0, (LONG)winpos );
752 return TRUE;
756 /***********************************************************************
757 * SetWindowPos (USER.232)
759 /* Note: all this code should be in the DeferWindowPos() routines,
760 * and SetWindowPos() should simply call them. This will be implemented
761 * some day...
763 BOOL SetWindowPos( HWND hwnd, HWND hwndInsertAfter, short x, short y,
764 short cx, short cy, WORD flags )
766 WINDOWPOS *winPos;
767 HANDLE hmem = 0;
768 BOOL res;
770 #ifdef DEBUG_WIN
771 printf( "SetWindowPos: %04X %d %d,%d %dx%d 0x%x\n",
772 hwnd, hwndInsertAfter, x, y, cx, cy, flags );
773 #endif
775 if (!(hmem = USER_HEAP_ALLOC( GMEM_MOVEABLE, sizeof(WINDOWPOS) )))
776 return FALSE;
777 winPos = (WINDOWPOS *)USER_HEAP_ADDR( hmem );
778 winPos->hwnd = hwnd;
779 winPos->hwndInsertAfter = hwndInsertAfter;
780 winPos->x = x;
781 winPos->y = y;
782 winPos->cx = cx;
783 winPos->cy = cy;
784 winPos->flags = flags;
786 res = WINPOS_InternalSetWindowPos( winPos );
788 USER_HEAP_FREE( hmem );
789 return res;