Add a missing </sect3>.
[wine.git] / windows / winpos.c
blob45597978109c59f42009bfe473d92069bcfa2a5c
1 /*
2 * Window position related functions.
4 * Copyright 1993, 1994, 1995 Alexandre Julliard
5 * 1995, 1996, 1999 Alex Korobka
6 */
8 #include <string.h>
9 #include "winerror.h"
10 #include "windef.h"
11 #include "wingdi.h"
12 #include "winerror.h"
13 #include "wine/winuser16.h"
14 #include "controls.h"
15 #include "heap.h"
16 #include "user.h"
17 #include "region.h"
18 #include "win.h"
19 #include "hook.h"
20 #include "message.h"
21 #include "queue.h"
22 #include "options.h"
23 #include "winpos.h"
24 #include "dce.h"
25 #include "nonclient.h"
26 #include "debugtools.h"
27 #include "input.h"
29 DEFAULT_DEBUG_CHANNEL(win);
31 #define HAS_DLGFRAME(style,exStyle) \
32 (((exStyle) & WS_EX_DLGMODALFRAME) || \
33 (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
35 #define HAS_THICKFRAME(style) \
36 (((style) & WS_THICKFRAME) && \
37 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
39 #define SWP_AGG_NOGEOMETRYCHANGE \
40 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
41 #define SWP_AGG_NOPOSCHANGE \
42 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
43 #define SWP_AGG_STATUSFLAGS \
44 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
46 #define EMPTYPOINT(pt) ((*(LONG*)&(pt)) == -1)
48 #define PLACE_MIN 0x0001
49 #define PLACE_MAX 0x0002
50 #define PLACE_RECT 0x0004
52 #define SWP_EX_NOCOPY 0x0001
53 #define SWP_EX_PAINTSELF 0x0002
54 #define SWP_EX_NONCLIENT 0x0004
56 #define MINMAX_NOSWP 0x00010000
58 /* ----- internal variables ----- */
60 static HWND hwndPrevActive = 0; /* Previously active window */
61 static HWND hGlobalShellWindow=0; /*the shell*/
62 static HWND hGlobalTaskmanWindow=0;
63 static HWND hGlobalProgmanWindow=0;
65 static LPCSTR atomInternalPos;
67 extern HQUEUE16 hActiveQueue;
69 /***********************************************************************
70 * WINPOS_CreateInternalPosAtom
72 BOOL WINPOS_CreateInternalPosAtom()
74 LPSTR str = "SysIP";
75 atomInternalPos = (LPCSTR)(DWORD)GlobalAddAtomA(str);
76 return (atomInternalPos) ? TRUE : FALSE;
79 /***********************************************************************
80 * WINPOS_CheckInternalPos
82 * Called when a window is destroyed.
84 void WINPOS_CheckInternalPos( WND* wndPtr )
86 LPINTERNALPOS lpPos;
87 MESSAGEQUEUE *pMsgQ = 0;
88 HWND hwnd = wndPtr->hwndSelf;
90 lpPos = (LPINTERNALPOS) GetPropA( hwnd, atomInternalPos );
92 /* Retrieve the message queue associated with this window */
93 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
94 if ( !pMsgQ )
96 WARN("\tMessage queue not found. Exiting!\n" );
97 return;
100 if( hwnd == hwndPrevActive ) hwndPrevActive = 0;
102 if( hwnd == PERQDATA_GetActiveWnd( pMsgQ->pQData ) )
104 PERQDATA_SetActiveWnd( pMsgQ->pQData, 0 );
105 WARN("\tattempt to activate destroyed window!\n");
108 if( lpPos )
110 if( IsWindow(lpPos->hwndIconTitle) )
111 DestroyWindow( lpPos->hwndIconTitle );
112 HeapFree( GetProcessHeap(), 0, lpPos );
115 QUEUE_Unlock( pMsgQ );
116 return;
119 /***********************************************************************
120 * WINPOS_FindIconPos
122 * Find a suitable place for an iconic window.
124 static POINT16 WINPOS_FindIconPos( WND* wndPtr, POINT16 pt )
126 RECT16 rectParent;
127 short x, y, xspacing, yspacing;
129 GetClientRect16( wndPtr->parent->hwndSelf, &rectParent );
130 if ((pt.x >= rectParent.left) && (pt.x + GetSystemMetrics(SM_CXICON) < rectParent.right) &&
131 (pt.y >= rectParent.top) && (pt.y + GetSystemMetrics(SM_CYICON) < rectParent.bottom))
132 return pt; /* The icon already has a suitable position */
134 xspacing = GetSystemMetrics(SM_CXICONSPACING);
135 yspacing = GetSystemMetrics(SM_CYICONSPACING);
137 y = rectParent.bottom;
138 for (;;)
140 x = rectParent.left;
143 /* Check if another icon already occupies this spot */
144 WND *childPtr = WIN_LockWndPtr(wndPtr->parent->child);
145 while (childPtr)
147 if ((childPtr->dwStyle & WS_MINIMIZE) && (childPtr != wndPtr))
149 if ((childPtr->rectWindow.left < x + xspacing) &&
150 (childPtr->rectWindow.right >= x) &&
151 (childPtr->rectWindow.top <= y) &&
152 (childPtr->rectWindow.bottom > y - yspacing))
153 break; /* There's a window in there */
155 WIN_UpdateWndPtr(&childPtr,childPtr->next);
157 WIN_ReleaseWndPtr(childPtr);
158 if (!childPtr) /* No window was found, so it's OK for us */
160 pt.x = x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2;
161 pt.y = y - (yspacing + GetSystemMetrics(SM_CYICON)) / 2;
162 return pt;
164 x += xspacing;
165 } while(x <= rectParent.right-xspacing);
166 y -= yspacing;
171 /***********************************************************************
172 * ArrangeIconicWindows (USER.170)
174 UINT16 WINAPI ArrangeIconicWindows16( HWND16 parent)
176 return ArrangeIconicWindows(parent);
178 /***********************************************************************
179 * ArrangeIconicWindows (USER32.@)
181 UINT WINAPI ArrangeIconicWindows( HWND parent )
183 RECT rectParent;
184 HWND hwndChild;
185 INT x, y, xspacing, yspacing;
187 GetClientRect( parent, &rectParent );
188 x = rectParent.left;
189 y = rectParent.bottom;
190 xspacing = GetSystemMetrics(SM_CXICONSPACING);
191 yspacing = GetSystemMetrics(SM_CYICONSPACING);
193 hwndChild = GetWindow( parent, GW_CHILD );
194 while (hwndChild)
196 if( IsIconic( hwndChild ) )
198 WND *wndPtr = WIN_FindWndPtr(hwndChild);
200 WINPOS_ShowIconTitle( wndPtr, FALSE );
202 SetWindowPos( hwndChild, 0, x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2,
203 y - yspacing - GetSystemMetrics(SM_CYICON)/2, 0, 0,
204 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
205 if( IsWindow(hwndChild) )
206 WINPOS_ShowIconTitle(wndPtr , TRUE );
207 WIN_ReleaseWndPtr(wndPtr);
209 if (x <= rectParent.right - xspacing) x += xspacing;
210 else
212 x = rectParent.left;
213 y -= yspacing;
216 hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
218 return yspacing;
222 /***********************************************************************
223 * SwitchToThisWindow (USER.172)
225 void WINAPI SwitchToThisWindow16( HWND16 hwnd, BOOL16 restore )
227 SwitchToThisWindow( hwnd, restore );
231 /***********************************************************************
232 * SwitchToThisWindow (USER32.@)
234 void WINAPI SwitchToThisWindow( HWND hwnd, BOOL restore )
236 ShowWindow( hwnd, restore ? SW_RESTORE : SW_SHOWMINIMIZED );
240 /***********************************************************************
241 * GetWindowRect (USER.32)
243 void WINAPI GetWindowRect16( HWND16 hwnd, LPRECT16 rect )
245 WND * wndPtr = WIN_FindWndPtr( hwnd );
246 if (!wndPtr) return;
248 CONV_RECT32TO16( &wndPtr->rectWindow, rect );
249 if (wndPtr->parent)
250 MapWindowPoints16( wndPtr->parent->hwndSelf, 0, (POINT16 *)rect, 2 );
251 WIN_ReleaseWndPtr(wndPtr);
255 /***********************************************************************
256 * GetWindowRect (USER32.@)
258 BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect )
260 WND * wndPtr = WIN_FindWndPtr( hwnd );
261 if (!wndPtr) return FALSE;
263 *rect = wndPtr->rectWindow;
264 if (wndPtr->parent)
265 MapWindowPoints( wndPtr->parent->hwndSelf, 0, (POINT *)rect, 2 );
266 WIN_ReleaseWndPtr(wndPtr);
267 return TRUE;
271 /***********************************************************************
272 * GetWindowRgn (USER32.@)
274 int WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
276 int nRet = ERROR;
277 WND *wndPtr = WIN_FindWndPtr( hwnd );
278 if (wndPtr)
280 if (wndPtr->hrgnWnd) nRet = CombineRgn( hrgn, wndPtr->hrgnWnd, 0, RGN_COPY );
281 WIN_ReleaseWndPtr(wndPtr);
283 return nRet;
286 /***********************************************************************
287 * SetWindowRgn (USER32.@)
289 int WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL bRedraw )
291 int ret = FALSE;
292 RECT tempRect;
294 WND *wndPtr = WIN_FindWndPtr(hwnd);
296 if (!wndPtr) return FALSE;
298 /* a region exists for this window */
299 if (hrgn != 0 && hrgn == wndPtr->hrgnWnd)
301 /* can't replace actual region with same region
302 since we're now owner of that region
304 SetLastError(ERROR_INVALID_HANDLE);
305 goto done;
309 /* we'd like to set it back to 0 */
310 if (hrgn == 0)
312 GetWindowRect(hwnd, &tempRect);
314 else
316 /* verify that region really exists */
317 if (GetRgnBox(hrgn, &tempRect) == ERROR) goto done;
321 /* Size the window to the rectangle of the new region
322 (if it isn't NULL) */
323 /* James: Added SWP_NOACTIVATE because SetWindowRgn in Windows doesn't activate the
324 window (and this was REALLY screwing up my app) */
325 SetWindowPos( hwnd, 0, tempRect.left, tempRect.top,
326 tempRect.right - tempRect.left, tempRect.bottom - tempRect.top,
327 SWP_NOSIZE | SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOACTIVATE |
328 SWP_NOZORDER | (bRedraw ? 0 : SWP_NOREDRAW) );
331 if (wndPtr->hrgnWnd)
333 /* delete previous region */
334 DeleteObject(wndPtr->hrgnWnd);
335 wndPtr->hrgnWnd = 0;
337 else if (!hrgn)
339 /* if there was no previous region (stored in wndPtr->hrgnWnd) and
340 the region to be set is also NULL, there is nothing more to do
342 ret = TRUE;
343 goto done;
346 /* valid region handle */
347 wndPtr->hrgnWnd = hrgn;
348 wndPtr->pDriver->pSetWindowRgn(wndPtr, hrgn);
350 ret = TRUE;
352 done:
353 WIN_ReleaseWndPtr(wndPtr);
354 return ret;
357 /***********************************************************************
358 * SetWindowRgn (USER.668)
360 INT16 WINAPI SetWindowRgn16( HWND16 hwnd, HRGN16 hrgn,BOOL16 bRedraw)
364 FIXME("SetWindowRgn16: stub\n");
365 return TRUE;
369 /***********************************************************************
370 * GetClientRect (USER.33)
372 void WINAPI GetClientRect16( HWND16 hwnd, LPRECT16 rect )
374 WND * wndPtr = WIN_FindWndPtr( hwnd );
376 rect->left = rect->top = rect->right = rect->bottom = 0;
377 if (wndPtr)
379 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
380 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
382 WIN_ReleaseWndPtr(wndPtr);
386 /***********************************************************************
387 * GetClientRect (USER32.@)
389 BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect )
391 WND * wndPtr = WIN_FindWndPtr( hwnd );
393 rect->left = rect->top = rect->right = rect->bottom = 0;
394 if (!wndPtr) return FALSE;
395 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
396 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
398 WIN_ReleaseWndPtr(wndPtr);
399 return TRUE;
403 /*******************************************************************
404 * ClientToScreen (USER.28)
406 void WINAPI ClientToScreen16( HWND16 hwnd, LPPOINT16 lppnt )
408 MapWindowPoints16( hwnd, 0, lppnt, 1 );
412 /*******************************************************************
413 * ClientToScreen (USER32.@)
415 BOOL WINAPI ClientToScreen( HWND hwnd, LPPOINT lppnt )
417 MapWindowPoints( hwnd, 0, lppnt, 1 );
418 return TRUE;
422 /*******************************************************************
423 * ScreenToClient (USER.29)
425 void WINAPI ScreenToClient16( HWND16 hwnd, LPPOINT16 lppnt )
427 MapWindowPoints16( 0, hwnd, lppnt, 1 );
431 /*******************************************************************
432 * ScreenToClient (USER32.@)
434 BOOL WINAPI ScreenToClient( HWND hwnd, LPPOINT lppnt )
436 MapWindowPoints( 0, hwnd, lppnt, 1 );
437 return TRUE;
441 /***********************************************************************
442 * WINPOS_WindowFromPoint
444 * Find the window and hittest for a given point.
446 INT16 WINPOS_WindowFromPoint( WND* wndScope, POINT16 pt, WND **ppWnd )
448 WND *wndPtr;
449 INT16 hittest = HTERROR;
450 INT16 retvalue;
451 POINT16 xy = pt;
453 TRACE("scope %04x %d,%d\n", wndScope->hwndSelf, pt.x, pt.y);
454 *ppWnd = NULL;
455 wndPtr = WIN_LockWndPtr(wndScope->child);
457 if( wndScope->dwStyle & WS_DISABLED )
459 retvalue = HTERROR;
460 goto end;
463 if( wndScope->dwExStyle & WS_EX_MANAGED)
465 /* In managed mode we have to check wndScope first as it is also
466 * a window which received the mouse event. */
468 if( pt.x < wndScope->rectClient.left || pt.x >= wndScope->rectClient.right ||
469 pt.y < wndScope->rectClient.top || pt.y >= wndScope->rectClient.bottom )
470 goto hittest;
472 MapWindowPoints16( GetDesktopWindow16(), wndScope->hwndSelf, &xy, 1 );
474 for (;;)
476 while (wndPtr)
478 /* If point is in window, and window is visible, and it */
479 /* is enabled (or it's a top-level window), then explore */
480 /* its children. Otherwise, go to the next window. */
482 if ((wndPtr->dwStyle & WS_VISIBLE) &&
483 ((wndPtr->dwExStyle & (WS_EX_LAYERED | WS_EX_TRANSPARENT)) != (WS_EX_LAYERED | WS_EX_TRANSPARENT)) &&
484 (!(wndPtr->dwStyle & WS_DISABLED) ||
485 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)) &&
486 (wndPtr->hrgnWnd ?
487 PtInRegion(wndPtr->hrgnWnd, xy.x - wndPtr->rectWindow.left,
488 xy.y - wndPtr->rectWindow.top) :
489 ((xy.x >= wndPtr->rectWindow.left) &&
490 (xy.x < wndPtr->rectWindow.right) &&
491 (xy.y >= wndPtr->rectWindow.top) &&
492 (xy.y < wndPtr->rectWindow.bottom))))
494 TRACE("%d,%d is inside %04x\n", xy.x, xy.y, wndPtr->hwndSelf);
495 *ppWnd = wndPtr; /* Got a suitable window */
497 /* If window is minimized or disabled, return at once */
498 if (wndPtr->dwStyle & WS_MINIMIZE)
500 retvalue = HTCAPTION;
501 goto end;
503 if (wndPtr->dwStyle & WS_DISABLED)
505 retvalue = HTERROR;
506 goto end;
509 /* If point is not in client area, ignore the children */
510 if ((xy.x < wndPtr->rectClient.left) ||
511 (xy.x >= wndPtr->rectClient.right) ||
512 (xy.y < wndPtr->rectClient.top) ||
513 (xy.y >= wndPtr->rectClient.bottom)) break;
515 xy.x -= wndPtr->rectClient.left;
516 xy.y -= wndPtr->rectClient.top;
517 WIN_UpdateWndPtr(&wndPtr,wndPtr->child);
519 else
521 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
525 hittest:
526 /* If nothing found, try the scope window */
527 if (!*ppWnd) *ppWnd = wndScope;
529 /* Send the WM_NCHITTEST message (only if to the same task) */
530 if ((*ppWnd)->hmemTaskQ == GetFastQueue16())
532 hittest = (INT16)SendMessage16( (*ppWnd)->hwndSelf, WM_NCHITTEST,
533 0, MAKELONG( pt.x, pt.y ) );
534 if (hittest != HTTRANSPARENT)
536 retvalue = hittest; /* Found the window */
537 goto end;
540 else
542 retvalue = HTCLIENT;
543 goto end;
546 /* If no children found in last search, make point relative to parent */
547 if (!wndPtr)
549 xy.x += (*ppWnd)->rectClient.left;
550 xy.y += (*ppWnd)->rectClient.top;
553 /* Restart the search from the next sibling */
554 WIN_UpdateWndPtr(&wndPtr,(*ppWnd)->next);
555 *ppWnd = (*ppWnd)->parent;
558 end:
559 WIN_ReleaseWndPtr(wndPtr);
560 return retvalue;
564 /*******************************************************************
565 * WindowFromPoint (USER.30)
567 HWND16 WINAPI WindowFromPoint16( POINT16 pt )
569 WND *pWnd;
570 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt, &pWnd );
571 WIN_ReleaseDesktop();
572 return pWnd->hwndSelf;
576 /*******************************************************************
577 * WindowFromPoint (USER32.@)
579 HWND WINAPI WindowFromPoint( POINT pt )
581 WND *pWnd;
582 POINT16 pt16;
583 CONV_POINT32TO16( &pt, &pt16 );
584 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16, &pWnd );
585 WIN_ReleaseDesktop();
586 return (HWND)pWnd->hwndSelf;
590 /*******************************************************************
591 * ChildWindowFromPoint (USER.191)
593 HWND16 WINAPI ChildWindowFromPoint16( HWND16 hwndParent, POINT16 pt )
595 POINT pt32;
596 CONV_POINT16TO32( &pt, &pt32 );
597 return (HWND16)ChildWindowFromPoint( hwndParent, pt32 );
601 /*******************************************************************
602 * ChildWindowFromPoint (USER32.@)
604 HWND WINAPI ChildWindowFromPoint( HWND hwndParent, POINT pt )
606 /* pt is in the client coordinates */
608 WND* wnd = WIN_FindWndPtr(hwndParent);
609 RECT rect;
610 HWND retvalue;
612 if( !wnd ) return 0;
614 /* get client rect fast */
615 rect.top = rect.left = 0;
616 rect.right = wnd->rectClient.right - wnd->rectClient.left;
617 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
619 if (!PtInRect( &rect, pt ))
621 retvalue = 0;
622 goto end;
624 WIN_UpdateWndPtr(&wnd,wnd->child);
625 while ( wnd )
627 if (PtInRect( &wnd->rectWindow, pt ))
629 retvalue = wnd->hwndSelf;
630 goto end;
632 WIN_UpdateWndPtr(&wnd,wnd->next);
634 retvalue = hwndParent;
635 end:
636 WIN_ReleaseWndPtr(wnd);
637 return retvalue;
640 /*******************************************************************
641 * ChildWindowFromPointEx (USER.399)
643 HWND16 WINAPI ChildWindowFromPointEx16( HWND16 hwndParent, POINT16 pt, UINT16 uFlags)
645 POINT pt32;
646 CONV_POINT16TO32( &pt, &pt32 );
647 return (HWND16)ChildWindowFromPointEx( hwndParent, pt32, uFlags );
651 /*******************************************************************
652 * ChildWindowFromPointEx (USER32.@)
654 HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt,
655 UINT uFlags)
657 /* pt is in the client coordinates */
659 WND* wnd = WIN_FindWndPtr(hwndParent);
660 RECT rect;
661 HWND retvalue;
663 if( !wnd ) return 0;
665 /* get client rect fast */
666 rect.top = rect.left = 0;
667 rect.right = wnd->rectClient.right - wnd->rectClient.left;
668 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
670 if (!PtInRect( &rect, pt ))
672 retvalue = 0;
673 goto end;
675 WIN_UpdateWndPtr(&wnd,wnd->child);
677 while ( wnd )
679 if (PtInRect( &wnd->rectWindow, pt )) {
680 if ( (uFlags & CWP_SKIPINVISIBLE) &&
681 !(wnd->dwStyle & WS_VISIBLE) );
682 else if ( (uFlags & CWP_SKIPDISABLED) &&
683 (wnd->dwStyle & WS_DISABLED) );
684 else if ( (uFlags & CWP_SKIPTRANSPARENT) &&
685 (wnd->dwExStyle & WS_EX_TRANSPARENT) );
686 else
688 retvalue = wnd->hwndSelf;
689 goto end;
693 WIN_UpdateWndPtr(&wnd,wnd->next);
695 retvalue = hwndParent;
696 end:
697 WIN_ReleaseWndPtr(wnd);
698 return retvalue;
702 /*******************************************************************
703 * WINPOS_GetWinOffset
705 * Calculate the offset between the origin of the two windows. Used
706 * to implement MapWindowPoints.
708 static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo,
709 POINT *offset )
711 WND * wndPtr = 0;
713 offset->x = offset->y = 0;
714 if (hwndFrom == hwndTo ) return;
716 /* Translate source window origin to screen coords */
717 if (hwndFrom)
719 if (!(wndPtr = WIN_FindWndPtr( hwndFrom )))
721 ERR("bad hwndFrom = %04x\n",hwndFrom);
722 return;
724 while (wndPtr->parent)
726 offset->x += wndPtr->rectClient.left;
727 offset->y += wndPtr->rectClient.top;
728 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
730 WIN_ReleaseWndPtr(wndPtr);
733 /* Translate origin to destination window coords */
734 if (hwndTo)
736 if (!(wndPtr = WIN_FindWndPtr( hwndTo )))
738 ERR("bad hwndTo = %04x\n", hwndTo );
739 return;
741 while (wndPtr->parent)
743 offset->x -= wndPtr->rectClient.left;
744 offset->y -= wndPtr->rectClient.top;
745 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
747 WIN_ReleaseWndPtr(wndPtr);
752 /*******************************************************************
753 * MapWindowPoints (USER.258)
755 void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
756 LPPOINT16 lppt, UINT16 count )
758 POINT offset;
760 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
761 while (count--)
763 lppt->x += offset.x;
764 lppt->y += offset.y;
765 lppt++;
770 /*******************************************************************
771 * MapWindowPoints (USER32.@)
773 INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo,
774 LPPOINT lppt, UINT count )
776 POINT offset;
778 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
779 while (count--)
781 lppt->x += offset.x;
782 lppt->y += offset.y;
783 lppt++;
785 return MAKELONG( LOWORD(offset.x), LOWORD(offset.y) );
789 /***********************************************************************
790 * IsIconic (USER.31)
792 BOOL16 WINAPI IsIconic16(HWND16 hWnd)
794 return IsIconic(hWnd);
798 /***********************************************************************
799 * IsIconic (USER32.@)
801 BOOL WINAPI IsIconic(HWND hWnd)
803 BOOL retvalue;
804 WND * wndPtr = WIN_FindWndPtr(hWnd);
805 if (wndPtr == NULL) return FALSE;
806 retvalue = (wndPtr->dwStyle & WS_MINIMIZE) != 0;
807 WIN_ReleaseWndPtr(wndPtr);
808 return retvalue;
812 /***********************************************************************
813 * IsZoomed (USER.272)
815 BOOL16 WINAPI IsZoomed16(HWND16 hWnd)
817 return IsZoomed(hWnd);
821 /***********************************************************************
822 * IsZoomed (USER32.@)
824 BOOL WINAPI IsZoomed(HWND hWnd)
826 BOOL retvalue;
827 WND * wndPtr = WIN_FindWndPtr(hWnd);
828 if (wndPtr == NULL) return FALSE;
829 retvalue = (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
830 WIN_ReleaseWndPtr(wndPtr);
831 return retvalue;
835 /*******************************************************************
836 * GetActiveWindow (USER.60)
838 HWND16 WINAPI GetActiveWindow16(void)
840 return (HWND16)GetActiveWindow();
843 /*******************************************************************
844 * GetActiveWindow (USER32.@)
846 HWND WINAPI GetActiveWindow(void)
848 MESSAGEQUEUE *pCurMsgQ = 0;
849 HWND hwndActive = 0;
851 /* Get the messageQ for the current thread */
852 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
854 WARN("\tCurrent message queue not found. Exiting!\n" );
855 return 0;
858 /* Return the current active window from the perQ data of the current message Q */
859 hwndActive = PERQDATA_GetActiveWnd( pCurMsgQ->pQData );
861 QUEUE_Unlock( pCurMsgQ );
862 return hwndActive;
866 /*******************************************************************
867 * WINPOS_CanActivate
869 static BOOL WINPOS_CanActivate(WND* pWnd)
871 if( pWnd && ( (pWnd->dwStyle & (WS_DISABLED | WS_VISIBLE | WS_CHILD))
872 == WS_VISIBLE ) ) return TRUE;
873 return FALSE;
877 /*******************************************************************
878 * SetActiveWindow (USER.59)
880 HWND16 WINAPI SetActiveWindow16( HWND16 hwnd )
882 return SetActiveWindow(hwnd);
886 /*******************************************************************
887 * SetActiveWindow (USER32.@)
889 HWND WINAPI SetActiveWindow( HWND hwnd )
891 HWND prev = 0;
892 WND *wndPtr = WIN_FindWndPtr( hwnd );
893 MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
895 if (!wndPtr || (wndPtr->dwStyle & (WS_DISABLED | WS_CHILD)))
897 prev = 0;
898 goto end;
901 /* Get the messageQ for the current thread */
902 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
904 WARN("\tCurrent message queue not found. Exiting!\n" );
905 goto CLEANUP;
908 /* Retrieve the message queue associated with this window */
909 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
910 if ( !pMsgQ )
912 WARN("\tWindow message queue not found. Exiting!\n" );
913 goto CLEANUP;
916 /* Make sure that the window is associated with the calling threads
917 * message queue. It must share the same perQ data.
920 if ( pCurMsgQ->pQData != pMsgQ->pQData )
921 goto CLEANUP;
923 /* Save current active window */
924 prev = PERQDATA_GetActiveWnd( pMsgQ->pQData );
926 WINPOS_SetActiveWindow( hwnd, 0, 0 );
928 CLEANUP:
929 /* Unlock the queues before returning */
930 if ( pMsgQ )
931 QUEUE_Unlock( pMsgQ );
932 if ( pCurMsgQ )
933 QUEUE_Unlock( pCurMsgQ );
935 end:
936 WIN_ReleaseWndPtr(wndPtr);
937 return prev;
941 /*******************************************************************
942 * GetForegroundWindow (USER.608)
944 HWND16 WINAPI GetForegroundWindow16(void)
946 return (HWND16)GetForegroundWindow();
950 /*******************************************************************
951 * SetForegroundWindow (USER.609)
953 BOOL16 WINAPI SetForegroundWindow16( HWND16 hwnd )
955 return SetForegroundWindow( hwnd );
959 /*******************************************************************
960 * GetForegroundWindow (USER32.@)
962 HWND WINAPI GetForegroundWindow(void)
964 HWND hwndActive = 0;
966 /* Get the foreground window (active window of hActiveQueue) */
967 if ( hActiveQueue )
969 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
970 if ( pActiveQueue )
971 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
973 QUEUE_Unlock( pActiveQueue );
976 return hwndActive;
979 /*******************************************************************
980 * SetForegroundWindow (USER32.@)
982 BOOL WINAPI SetForegroundWindow( HWND hwnd )
984 return WINPOS_ChangeActiveWindow( hwnd, FALSE );
988 /*******************************************************************
989 * AllowSetForegroundWindow (USER32.@)
991 BOOL WINAPI AllowSetForegroundWindow( DWORD procid )
993 /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
994 * implemented, then fix this function. */
995 return TRUE;
999 /*******************************************************************
1000 * LockSetForegroundWindow (USER32.@)
1002 BOOL WINAPI LockSetForegroundWindow( UINT lockcode )
1004 /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
1005 * implemented, then fix this function. */
1006 return TRUE;
1010 /*******************************************************************
1011 * GetShellWindow (USER.600)
1013 HWND16 WINAPI GetShellWindow16(void)
1015 return GetShellWindow();
1018 /*******************************************************************
1019 * SetShellWindow (USER32.@)
1021 HWND WINAPI SetShellWindow(HWND hwndshell)
1022 { WARN("(hWnd=%08x) semi stub\n",hwndshell );
1024 hGlobalShellWindow = hwndshell;
1025 return hGlobalShellWindow;
1029 /*******************************************************************
1030 * GetShellWindow (USER32.@)
1032 HWND WINAPI GetShellWindow(void)
1033 { WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow );
1035 return hGlobalShellWindow;
1039 /***********************************************************************
1040 * BringWindowToTop (USER.45)
1042 BOOL16 WINAPI BringWindowToTop16( HWND16 hwnd )
1044 return BringWindowToTop(hwnd);
1048 /***********************************************************************
1049 * BringWindowToTop (USER32.@)
1051 BOOL WINAPI BringWindowToTop( HWND hwnd )
1053 return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
1057 /***********************************************************************
1058 * MoveWindow (USER.56)
1060 BOOL16 WINAPI MoveWindow16( HWND16 hwnd, INT16 x, INT16 y, INT16 cx, INT16 cy,
1061 BOOL16 repaint )
1063 return MoveWindow(hwnd,x,y,cx,cy,repaint);
1067 /***********************************************************************
1068 * MoveWindow (USER32.@)
1070 BOOL WINAPI MoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy,
1071 BOOL repaint )
1073 int flags = SWP_NOZORDER | SWP_NOACTIVATE;
1074 if (!repaint) flags |= SWP_NOREDRAW;
1075 TRACE("%04x %d,%d %dx%d %d\n",
1076 hwnd, x, y, cx, cy, repaint );
1077 return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
1080 /***********************************************************************
1081 * WINPOS_InitInternalPos
1083 static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT pt,
1084 LPRECT restoreRect )
1086 LPINTERNALPOS lpPos = (LPINTERNALPOS) GetPropA( wnd->hwndSelf,
1087 atomInternalPos );
1088 if( !lpPos )
1090 /* this happens when the window is minimized/maximized
1091 * for the first time (rectWindow is not adjusted yet) */
1093 lpPos = HeapAlloc( GetProcessHeap(), 0, sizeof(INTERNALPOS) );
1094 if( !lpPos ) return NULL;
1096 SetPropA( wnd->hwndSelf, atomInternalPos, (HANDLE)lpPos );
1097 lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
1098 CONV_RECT32TO16( &wnd->rectWindow, &lpPos->rectNormal );
1099 *(UINT*)&lpPos->ptIconPos = *(UINT*)&lpPos->ptMaxPos = 0xFFFFFFFF;
1102 if( wnd->dwStyle & WS_MINIMIZE )
1103 CONV_POINT32TO16( &pt, &lpPos->ptIconPos );
1104 else if( wnd->dwStyle & WS_MAXIMIZE )
1105 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1106 else if( restoreRect )
1107 CONV_RECT32TO16( restoreRect, &lpPos->rectNormal );
1109 return lpPos;
1112 /***********************************************************************
1113 * WINPOS_RedrawIconTitle
1115 BOOL WINPOS_RedrawIconTitle( HWND hWnd )
1117 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hWnd, atomInternalPos );
1118 if( lpPos )
1120 if( lpPos->hwndIconTitle )
1122 SendMessageA( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
1123 InvalidateRect( lpPos->hwndIconTitle, NULL, TRUE );
1124 return TRUE;
1127 return FALSE;
1130 /***********************************************************************
1131 * WINPOS_ShowIconTitle
1133 BOOL WINPOS_ShowIconTitle( WND* pWnd, BOOL bShow )
1135 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( pWnd->hwndSelf, atomInternalPos );
1137 if( lpPos && !(pWnd->dwExStyle & WS_EX_MANAGED))
1139 HWND16 hWnd = lpPos->hwndIconTitle;
1141 TRACE("0x%04x %i\n", pWnd->hwndSelf, (bShow != 0) );
1143 if( !hWnd )
1144 lpPos->hwndIconTitle = hWnd = ICONTITLE_Create( pWnd );
1145 if( bShow )
1147 if( ( pWnd = WIN_FindWndPtr(hWnd) ) != NULL)
1149 if( !(pWnd->dwStyle & WS_VISIBLE) )
1151 SendMessageA( hWnd, WM_SHOWWINDOW, TRUE, 0 );
1152 SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
1153 SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
1155 WIN_ReleaseWndPtr(pWnd);
1158 else ShowWindow( hWnd, SW_HIDE );
1160 return FALSE;
1163 /*******************************************************************
1164 * WINPOS_GetMinMaxInfo
1166 * Get the minimized and maximized information for a window.
1168 void WINPOS_GetMinMaxInfo( WND *wndPtr, POINT *maxSize, POINT *maxPos,
1169 POINT *minTrack, POINT *maxTrack )
1171 LPINTERNALPOS lpPos;
1172 MINMAXINFO MinMax;
1173 INT xinc, yinc;
1175 /* Compute default values */
1177 MinMax.ptMaxSize.x = GetSystemMetrics(SM_CXSCREEN);
1178 MinMax.ptMaxSize.y = GetSystemMetrics(SM_CYSCREEN);
1179 MinMax.ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
1180 MinMax.ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
1181 MinMax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXSCREEN);
1182 MinMax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYSCREEN);
1184 if (wndPtr->dwExStyle & WS_EX_MANAGED) xinc = yinc = 0;
1185 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1187 xinc = GetSystemMetrics(SM_CXDLGFRAME);
1188 yinc = GetSystemMetrics(SM_CYDLGFRAME);
1190 else
1192 xinc = yinc = 0;
1193 if (HAS_THICKFRAME(wndPtr->dwStyle))
1195 xinc += GetSystemMetrics(SM_CXFRAME);
1196 yinc += GetSystemMetrics(SM_CYFRAME);
1198 if (wndPtr->dwStyle & WS_BORDER)
1200 xinc += GetSystemMetrics(SM_CXBORDER);
1201 yinc += GetSystemMetrics(SM_CYBORDER);
1204 MinMax.ptMaxSize.x += 2 * xinc;
1205 MinMax.ptMaxSize.y += 2 * yinc;
1207 lpPos = (LPINTERNALPOS)GetPropA( wndPtr->hwndSelf, atomInternalPos );
1208 if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
1209 CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
1210 else
1212 MinMax.ptMaxPosition.x = -xinc;
1213 MinMax.ptMaxPosition.y = -yinc;
1216 SendMessageA( wndPtr->hwndSelf, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
1218 /* Some sanity checks */
1220 TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1221 MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
1222 MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
1223 MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
1224 MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
1225 MinMax.ptMaxTrackSize.x = max( MinMax.ptMaxTrackSize.x,
1226 MinMax.ptMinTrackSize.x );
1227 MinMax.ptMaxTrackSize.y = max( MinMax.ptMaxTrackSize.y,
1228 MinMax.ptMinTrackSize.y );
1230 if (maxSize) *maxSize = MinMax.ptMaxSize;
1231 if (maxPos) *maxPos = MinMax.ptMaxPosition;
1232 if (minTrack) *minTrack = MinMax.ptMinTrackSize;
1233 if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
1236 /***********************************************************************
1237 * WINPOS_MinMaximize
1239 * Fill in lpRect and return additional flags to be used with SetWindowPos().
1240 * This function assumes that 'cmd' is different from the current window
1241 * state.
1243 UINT WINPOS_MinMaximize( WND* wndPtr, UINT16 cmd, LPRECT16 lpRect )
1245 UINT swpFlags = 0;
1246 POINT pt, size;
1247 LPINTERNALPOS lpPos;
1249 TRACE("0x%04x %u\n", wndPtr->hwndSelf, cmd );
1251 size.x = wndPtr->rectWindow.left; size.y = wndPtr->rectWindow.top;
1252 lpPos = WINPOS_InitInternalPos( wndPtr, size, &wndPtr->rectWindow );
1254 if (lpPos && !HOOK_CallHooks16(WH_CBT, HCBT_MINMAX, wndPtr->hwndSelf, cmd))
1256 if( wndPtr->dwStyle & WS_MINIMIZE )
1258 if( !SendMessageA( wndPtr->hwndSelf, WM_QUERYOPEN, 0, 0L ) )
1259 return (SWP_NOSIZE | SWP_NOMOVE);
1260 swpFlags |= SWP_NOCOPYBITS;
1262 switch( cmd )
1264 case SW_MINIMIZE:
1265 if( wndPtr->dwStyle & WS_MAXIMIZE)
1267 wndPtr->flags |= WIN_RESTORE_MAX;
1268 wndPtr->dwStyle &= ~WS_MAXIMIZE;
1270 else
1271 wndPtr->flags &= ~WIN_RESTORE_MAX;
1272 wndPtr->dwStyle |= WS_MINIMIZE;
1274 if( wndPtr->flags & WIN_NATIVE )
1275 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, TRUE ) )
1276 swpFlags |= MINMAX_NOSWP;
1278 lpPos->ptIconPos = WINPOS_FindIconPos( wndPtr, lpPos->ptIconPos );
1280 SetRect16( lpRect, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1281 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON) );
1282 swpFlags |= SWP_NOCOPYBITS;
1283 break;
1285 case SW_MAXIMIZE:
1286 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1287 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL );
1288 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1290 if( wndPtr->dwStyle & WS_MINIMIZE )
1292 if( wndPtr->flags & WIN_NATIVE )
1293 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE );
1295 WINPOS_ShowIconTitle( wndPtr, FALSE );
1296 wndPtr->dwStyle &= ~WS_MINIMIZE;
1298 wndPtr->dwStyle |= WS_MAXIMIZE;
1300 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1301 size.x, size.y );
1302 break;
1304 case SW_RESTORE:
1305 if( wndPtr->dwStyle & WS_MINIMIZE )
1307 if( wndPtr->flags & WIN_NATIVE )
1308 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE );
1310 wndPtr->dwStyle &= ~WS_MINIMIZE;
1311 WINPOS_ShowIconTitle( wndPtr, FALSE );
1313 if( wndPtr->flags & WIN_RESTORE_MAX)
1315 /* Restore to maximized position */
1316 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1317 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL);
1318 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1319 wndPtr->dwStyle |= WS_MAXIMIZE;
1320 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y, size.x, size.y );
1321 break;
1324 else
1325 if( !(wndPtr->dwStyle & WS_MAXIMIZE) ) return (UINT16)(-1);
1326 else wndPtr->dwStyle &= ~WS_MAXIMIZE;
1328 /* Restore to normal position */
1330 *lpRect = lpPos->rectNormal;
1331 lpRect->right -= lpRect->left;
1332 lpRect->bottom -= lpRect->top;
1334 break;
1336 } else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
1337 return swpFlags;
1340 /***********************************************************************
1341 * ShowWindowAsync (USER32.@)
1343 * doesn't wait; returns immediately.
1344 * used by threads to toggle windows in other (possibly hanging) threads
1346 BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd )
1348 /* FIXME: does ShowWindow() return immediately ? */
1349 return ShowWindow(hwnd, cmd);
1353 /***********************************************************************
1354 * ShowWindow (USER.42)
1356 BOOL16 WINAPI ShowWindow16( HWND16 hwnd, INT16 cmd )
1358 return ShowWindow(hwnd,cmd);
1362 /***********************************************************************
1363 * ShowWindow (USER32.@)
1365 BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
1367 WND* wndPtr = WIN_FindWndPtr( hwnd );
1368 BOOL wasVisible, showFlag;
1369 RECT16 newPos = {0, 0, 0, 0};
1370 UINT swp = 0;
1372 if (!wndPtr) return FALSE;
1374 TRACE("hwnd=%04x, cmd=%d\n", hwnd, cmd);
1376 wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
1378 switch(cmd)
1380 case SW_HIDE:
1381 if (!wasVisible) goto END;;
1382 swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
1383 SWP_NOACTIVATE | SWP_NOZORDER;
1384 break;
1386 case SW_SHOWMINNOACTIVE:
1387 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1388 /* fall through */
1389 case SW_SHOWMINIMIZED:
1390 swp |= SWP_SHOWWINDOW;
1391 /* fall through */
1392 case SW_MINIMIZE:
1393 swp |= SWP_FRAMECHANGED;
1394 if( !(wndPtr->dwStyle & WS_MINIMIZE) )
1395 swp |= WINPOS_MinMaximize( wndPtr, SW_MINIMIZE, &newPos );
1396 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1397 break;
1399 case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
1400 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1401 if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
1402 swp |= WINPOS_MinMaximize( wndPtr, SW_MAXIMIZE, &newPos );
1403 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1404 break;
1406 case SW_SHOWNA:
1407 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1408 /* fall through */
1409 case SW_SHOW:
1410 swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
1413 * ShowWindow has a little peculiar behavior that if the
1414 * window is already the topmost window, it will not
1415 * activate it.
1417 if (GetTopWindow((HWND)0)==hwnd && (wasVisible || GetActiveWindow() == hwnd))
1418 swp |= SWP_NOACTIVATE;
1420 break;
1422 case SW_SHOWNOACTIVATE:
1423 swp |= SWP_NOZORDER;
1424 if (GetActiveWindow()) swp |= SWP_NOACTIVATE;
1425 /* fall through */
1426 case SW_SHOWNORMAL: /* same as SW_NORMAL: */
1427 case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
1428 case SW_RESTORE:
1429 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1431 if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) )
1432 swp |= WINPOS_MinMaximize( wndPtr, SW_RESTORE, &newPos );
1433 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1434 break;
1437 showFlag = (cmd != SW_HIDE);
1438 if (showFlag != wasVisible)
1440 SendMessageA( hwnd, WM_SHOWWINDOW, showFlag, 0 );
1441 if (!IsWindow( hwnd )) goto END;
1444 if ((wndPtr->dwStyle & WS_CHILD) &&
1445 !IsWindowVisible( wndPtr->parent->hwndSelf ) &&
1446 (swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE) )
1448 /* Don't call SetWindowPos() on invisible child windows */
1449 if (cmd == SW_HIDE) wndPtr->dwStyle &= ~WS_VISIBLE;
1450 else wndPtr->dwStyle |= WS_VISIBLE;
1452 else
1454 /* We can't activate a child window */
1455 if ((wndPtr->dwStyle & WS_CHILD) &&
1456 !(wndPtr->dwExStyle & WS_EX_MDICHILD))
1457 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1458 if (!(swp & MINMAX_NOSWP))
1460 SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top,
1461 newPos.right, newPos.bottom, LOWORD(swp) );
1462 if (cmd == SW_HIDE)
1464 /* FIXME: This will cause the window to be activated irrespective
1465 * of whether it is owned by the same thread. Has to be done
1466 * asynchronously.
1469 if (hwnd == GetActiveWindow())
1470 WINPOS_ActivateOtherWindow(wndPtr);
1472 /* Revert focus to parent */
1473 if (hwnd == GetFocus() || IsChild(hwnd, GetFocus()))
1474 SetFocus( GetParent(hwnd) );
1477 if (!IsWindow( hwnd )) goto END;
1478 else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( wndPtr, TRUE );
1481 if (wndPtr->flags & WIN_NEED_SIZE)
1483 /* should happen only in CreateWindowEx() */
1484 int wParam = SIZE_RESTORED;
1486 wndPtr->flags &= ~WIN_NEED_SIZE;
1487 if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
1488 else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
1489 SendMessageA( hwnd, WM_SIZE, wParam,
1490 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
1491 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
1492 SendMessageA( hwnd, WM_MOVE, 0,
1493 MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
1496 END:
1497 WIN_ReleaseWndPtr(wndPtr);
1498 return wasVisible;
1502 /***********************************************************************
1503 * GetInternalWindowPos (USER.460)
1505 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
1506 LPPOINT16 ptIcon )
1508 WINDOWPLACEMENT16 wndpl;
1509 if (GetWindowPlacement16( hwnd, &wndpl ))
1511 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1512 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1513 return wndpl.showCmd;
1515 return 0;
1519 /***********************************************************************
1520 * GetInternalWindowPos (USER32.@)
1522 UINT WINAPI GetInternalWindowPos( HWND hwnd, LPRECT rectWnd,
1523 LPPOINT ptIcon )
1525 WINDOWPLACEMENT wndpl;
1526 if (GetWindowPlacement( hwnd, &wndpl ))
1528 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1529 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1530 return wndpl.showCmd;
1532 return 0;
1535 /***********************************************************************
1536 * GetWindowPlacement (USER.370)
1538 BOOL16 WINAPI GetWindowPlacement16( HWND16 hwnd, WINDOWPLACEMENT16 *wndpl )
1540 WND *pWnd = WIN_FindWndPtr( hwnd );
1541 LPINTERNALPOS lpPos;
1543 if(!pWnd ) return FALSE;
1545 lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1546 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1547 wndpl->length = sizeof(*wndpl);
1548 if( pWnd->dwStyle & WS_MINIMIZE )
1549 wndpl->showCmd = SW_SHOWMINIMIZED;
1550 else
1551 wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE )
1552 ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
1553 if( pWnd->flags & WIN_RESTORE_MAX )
1554 wndpl->flags = WPF_RESTORETOMAXIMIZED;
1555 else
1556 wndpl->flags = 0;
1557 wndpl->ptMinPosition = lpPos->ptIconPos;
1558 wndpl->ptMaxPosition = lpPos->ptMaxPos;
1559 wndpl->rcNormalPosition = lpPos->rectNormal;
1561 WIN_ReleaseWndPtr(pWnd);
1562 return TRUE;
1566 /***********************************************************************
1567 * GetWindowPlacement (USER32.@)
1569 * Win95:
1570 * Fails if wndpl->length of Win95 (!) apps is invalid.
1572 BOOL WINAPI GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *pwpl32 )
1574 if( pwpl32 )
1576 WINDOWPLACEMENT16 wpl;
1577 wpl.length = sizeof(wpl);
1578 if( GetWindowPlacement16( hwnd, &wpl ) )
1580 pwpl32->length = sizeof(*pwpl32);
1581 pwpl32->flags = wpl.flags;
1582 pwpl32->showCmd = wpl.showCmd;
1583 CONV_POINT16TO32( &wpl.ptMinPosition, &pwpl32->ptMinPosition );
1584 CONV_POINT16TO32( &wpl.ptMaxPosition, &pwpl32->ptMaxPosition );
1585 CONV_RECT16TO32( &wpl.rcNormalPosition, &pwpl32->rcNormalPosition );
1586 return TRUE;
1589 return FALSE;
1593 /***********************************************************************
1594 * WINPOS_SetPlacement
1596 static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT16 *wndpl,
1597 UINT flags )
1599 WND *pWnd = WIN_FindWndPtr( hwnd );
1600 if( pWnd )
1602 LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1603 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1605 if( flags & PLACE_MIN ) lpPos->ptIconPos = wndpl->ptMinPosition;
1606 if( flags & PLACE_MAX ) lpPos->ptMaxPos = wndpl->ptMaxPosition;
1607 if( flags & PLACE_RECT) lpPos->rectNormal = wndpl->rcNormalPosition;
1609 if( pWnd->dwStyle & WS_MINIMIZE )
1611 WINPOS_ShowIconTitle( pWnd, FALSE );
1612 if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1613 SetWindowPos( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1614 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1616 else if( pWnd->dwStyle & WS_MAXIMIZE )
1618 if( !EMPTYPOINT(lpPos->ptMaxPos) )
1619 SetWindowPos( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1620 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1622 else if( flags & PLACE_RECT )
1623 SetWindowPos( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1624 lpPos->rectNormal.right - lpPos->rectNormal.left,
1625 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1626 SWP_NOZORDER | SWP_NOACTIVATE );
1628 ShowWindow( hwnd, wndpl->showCmd );
1629 if( IsWindow(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1631 if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd, TRUE );
1633 /* SDK: ...valid only the next time... */
1634 if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1636 WIN_ReleaseWndPtr(pWnd);
1637 return TRUE;
1639 return FALSE;
1643 /***********************************************************************
1644 * SetWindowPlacement (USER.371)
1646 BOOL16 WINAPI SetWindowPlacement16(HWND16 hwnd, const WINDOWPLACEMENT16 *wndpl)
1648 return WINPOS_SetPlacement( hwnd, wndpl,
1649 PLACE_MIN | PLACE_MAX | PLACE_RECT );
1652 /***********************************************************************
1653 * SetWindowPlacement (USER32.@)
1655 * Win95:
1656 * Fails if wndpl->length of Win95 (!) apps is invalid.
1658 BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *pwpl32 )
1660 if( pwpl32 )
1662 WINDOWPLACEMENT16 wpl;
1664 wpl.length = sizeof(WINDOWPLACEMENT16);
1665 wpl.flags = pwpl32->flags;
1666 wpl.showCmd = pwpl32->showCmd;
1667 wpl.ptMinPosition.x = pwpl32->ptMinPosition.x;
1668 wpl.ptMinPosition.y = pwpl32->ptMinPosition.y;
1669 wpl.ptMaxPosition.x = pwpl32->ptMaxPosition.x;
1670 wpl.ptMaxPosition.y = pwpl32->ptMaxPosition.y;
1671 wpl.rcNormalPosition.left = pwpl32->rcNormalPosition.left;
1672 wpl.rcNormalPosition.top = pwpl32->rcNormalPosition.top;
1673 wpl.rcNormalPosition.right = pwpl32->rcNormalPosition.right;
1674 wpl.rcNormalPosition.bottom = pwpl32->rcNormalPosition.bottom;
1676 return WINPOS_SetPlacement( hwnd, &wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1678 return FALSE;
1682 /***********************************************************************
1683 * SetInternalWindowPos (USER.461)
1685 void WINAPI SetInternalWindowPos16( HWND16 hwnd, UINT16 showCmd,
1686 LPRECT16 rect, LPPOINT16 pt )
1688 if( IsWindow16(hwnd) )
1690 WINDOWPLACEMENT16 wndpl;
1691 UINT flags;
1693 wndpl.length = sizeof(wndpl);
1694 wndpl.showCmd = showCmd;
1695 wndpl.flags = flags = 0;
1697 if( pt )
1699 flags |= PLACE_MIN;
1700 wndpl.flags |= WPF_SETMINPOSITION;
1701 wndpl.ptMinPosition = *pt;
1703 if( rect )
1705 flags |= PLACE_RECT;
1706 wndpl.rcNormalPosition = *rect;
1708 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1713 /***********************************************************************
1714 * SetInternalWindowPos (USER32.@)
1716 void WINAPI SetInternalWindowPos( HWND hwnd, UINT showCmd,
1717 LPRECT rect, LPPOINT pt )
1719 if( IsWindow(hwnd) )
1721 WINDOWPLACEMENT16 wndpl;
1722 UINT flags;
1724 wndpl.length = sizeof(wndpl);
1725 wndpl.showCmd = showCmd;
1726 wndpl.flags = flags = 0;
1728 if( pt )
1730 flags |= PLACE_MIN;
1731 wndpl.flags |= WPF_SETMINPOSITION;
1732 CONV_POINT32TO16( pt, &wndpl.ptMinPosition );
1734 if( rect )
1736 flags |= PLACE_RECT;
1737 CONV_RECT32TO16( rect, &wndpl.rcNormalPosition );
1739 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1743 /*******************************************************************
1744 * WINPOS_SetActiveWindow
1746 * SetActiveWindow() back-end. This is the only function that
1747 * can assign active status to a window. It must be called only
1748 * for the top level windows.
1750 BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
1752 CBTACTIVATESTRUCT16* cbtStruct;
1753 WND* wndPtr=0, *wndTemp;
1754 HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1755 MESSAGEQUEUE *pOldActiveQueue = 0, *pNewActiveQueue = 0;
1756 WORD wIconized = 0;
1757 HWND hwndActive = 0;
1758 BOOL bRet = 0;
1760 TRACE("(%04x, %d, %d)\n", hWnd, fMouse, fChangeFocus );
1762 /* Get current active window from the active queue */
1763 if ( hActiveQueue )
1765 pOldActiveQueue = QUEUE_Lock( hActiveQueue );
1766 if ( pOldActiveQueue )
1767 hwndActive = PERQDATA_GetActiveWnd( pOldActiveQueue->pQData );
1770 /* paranoid checks */
1771 if( hWnd == GetDesktopWindow() || (bRet = (hWnd == hwndActive)) )
1772 goto CLEANUP_END;
1774 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1775 * return 0;
1777 wndPtr = WIN_FindWndPtr(hWnd);
1778 hOldActiveQueue = hActiveQueue;
1780 if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1782 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1783 WIN_ReleaseWndPtr(wndTemp);
1785 else
1786 TRACE("no current active window.\n");
1788 /* call CBT hook chain */
1789 if ((cbtStruct = SEGPTR_NEW(CBTACTIVATESTRUCT16)))
1791 cbtStruct->fMouse = fMouse;
1792 cbtStruct->hWndActive = hwndActive;
1793 bRet = (BOOL)HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
1794 (LPARAM)SEGPTR_GET(cbtStruct) );
1795 SEGPTR_FREE(cbtStruct);
1796 if (bRet) goto CLEANUP_END;
1799 /* set prev active wnd to current active wnd and send notification */
1800 if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
1802 MESSAGEQUEUE *pTempActiveQueue = 0;
1804 if (!SendMessageA( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1806 if (GetSysModalWindow16() != hWnd)
1807 goto CLEANUP_END;
1808 /* disregard refusal if hWnd is sysmodal */
1811 SendMessageA( hwndPrevActive, WM_ACTIVATE,
1812 MAKEWPARAM( WA_INACTIVE, wIconized ),
1813 (LPARAM)hWnd );
1815 /* check if something happened during message processing
1816 * (global active queue may have changed)
1818 pTempActiveQueue = QUEUE_Lock( hActiveQueue );
1819 if(!pTempActiveQueue)
1820 goto CLEANUP_END;
1822 hwndActive = PERQDATA_GetActiveWnd( pTempActiveQueue->pQData );
1823 QUEUE_Unlock( pTempActiveQueue );
1824 if( hwndPrevActive != hwndActive )
1825 goto CLEANUP_END;
1828 /* Set new active window in the message queue */
1829 hwndActive = hWnd;
1830 if ( wndPtr )
1832 pNewActiveQueue = QUEUE_Lock( wndPtr->hmemTaskQ );
1833 if ( pNewActiveQueue )
1834 PERQDATA_SetActiveWnd( pNewActiveQueue->pQData, hwndActive );
1836 else /* have to do this or MDI frame activation goes to hell */
1837 if( pOldActiveQueue )
1838 PERQDATA_SetActiveWnd( pOldActiveQueue->pQData, 0 );
1840 /* send palette messages */
1841 if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1842 SendMessage16((HWND16)-1, WM_PALETTEISCHANGING, (WPARAM16)hWnd, 0L );
1844 /* if prev wnd is minimized redraw icon title */
1845 if( IsIconic( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1847 /* managed windows will get ConfigureNotify event */
1848 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_MANAGED))
1850 /* check Z-order and bring hWnd to the top */
1851 for (wndTemp = WIN_LockWndPtr(WIN_GetDesktop()->child); wndTemp; WIN_UpdateWndPtr(&wndTemp,wndTemp->next))
1853 if (wndTemp->dwStyle & WS_VISIBLE) break;
1855 WIN_ReleaseDesktop();
1856 WIN_ReleaseWndPtr(wndTemp);
1858 if( wndTemp != wndPtr )
1859 SetWindowPos(hWnd, HWND_TOP, 0,0,0,0,
1860 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1861 if (!IsWindow(hWnd))
1862 goto CLEANUP;
1865 /* Get a handle to the new active queue */
1866 hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1868 /* send WM_ACTIVATEAPP if necessary */
1869 if (hOldActiveQueue != hNewActiveQueue)
1871 WND **list, **ppWnd;
1872 WND *pDesktop = WIN_GetDesktop();
1874 if ((list = WIN_BuildWinArray( pDesktop, 0, NULL )))
1876 for (ppWnd = list; *ppWnd; ppWnd++)
1878 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1880 if ((*ppWnd)->hmemTaskQ == hOldActiveQueue)
1881 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1882 0, QUEUE_GetQueueTask(hNewActiveQueue) );
1884 WIN_ReleaseWinArray(list);
1887 hActiveQueue = hNewActiveQueue;
1889 if ((list = WIN_BuildWinArray(pDesktop, 0, NULL )))
1891 for (ppWnd = list; *ppWnd; ppWnd++)
1893 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1895 if ((*ppWnd)->hmemTaskQ == hNewActiveQueue)
1896 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1897 1, QUEUE_GetQueueTask( hOldActiveQueue ) );
1899 WIN_ReleaseWinArray(list);
1901 WIN_ReleaseDesktop();
1903 if (hWnd && !IsWindow(hWnd)) goto CLEANUP;
1906 if (hWnd)
1908 /* walk up to the first unowned window */
1909 wndTemp = WIN_LockWndPtr(wndPtr);
1910 while (wndTemp->owner)
1912 WIN_UpdateWndPtr(&wndTemp,wndTemp->owner);
1914 /* and set last active owned popup */
1915 wndTemp->hwndLastActive = hWnd;
1917 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1918 WIN_ReleaseWndPtr(wndTemp);
1919 SendMessageA( hWnd, WM_NCACTIVATE, TRUE, 0 );
1920 SendMessageA( hWnd, WM_ACTIVATE,
1921 MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1922 (LPARAM)hwndPrevActive );
1923 if( !IsWindow(hWnd) ) goto CLEANUP;
1926 /* change focus if possible */
1927 if ( fChangeFocus )
1929 if ( pNewActiveQueue )
1931 HWND hOldFocus = PERQDATA_GetFocusWnd( pNewActiveQueue->pQData );
1933 if ( hOldFocus && WIN_GetTopParent( hOldFocus ) != hwndActive )
1934 FOCUS_SwitchFocus( pNewActiveQueue, hOldFocus,
1935 (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
1936 0 : hwndActive );
1939 if ( pOldActiveQueue &&
1940 ( !pNewActiveQueue ||
1941 pNewActiveQueue->pQData != pOldActiveQueue->pQData ) )
1943 HWND hOldFocus = PERQDATA_GetFocusWnd( pOldActiveQueue->pQData );
1944 if ( hOldFocus )
1945 FOCUS_SwitchFocus( pOldActiveQueue, hOldFocus, 0 );
1949 if( !hwndPrevActive && wndPtr )
1950 (*wndPtr->pDriver->pForceWindowRaise)(wndPtr);
1952 /* if active wnd is minimized redraw icon title */
1953 if( IsIconic(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1955 bRet = (hWnd == hwndActive); /* Success? */
1957 CLEANUP: /* Unlock the message queues before returning */
1959 if ( pNewActiveQueue )
1960 QUEUE_Unlock( pNewActiveQueue );
1962 CLEANUP_END:
1964 if ( pOldActiveQueue )
1965 QUEUE_Unlock( pOldActiveQueue );
1967 WIN_ReleaseWndPtr(wndPtr);
1968 return bRet;
1971 /*******************************************************************
1972 * WINPOS_ActivateOtherWindow
1974 * Activates window other than pWnd.
1976 BOOL WINPOS_ActivateOtherWindow(WND* pWnd)
1978 BOOL bRet = 0;
1979 WND* pWndTo = NULL;
1980 HWND hwndActive = 0;
1982 /* Get current active window from the active queue */
1983 if ( hActiveQueue )
1985 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1986 if ( pActiveQueue )
1988 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1989 QUEUE_Unlock( pActiveQueue );
1993 if( pWnd->hwndSelf == hwndPrevActive )
1994 hwndPrevActive = 0;
1996 if( hwndActive != pWnd->hwndSelf &&
1997 ( hwndActive || QUEUE_IsExitingQueue(pWnd->hmemTaskQ)) )
1998 return 0;
2000 if( !(pWnd->dwStyle & WS_POPUP) || !(pWnd->owner) ||
2001 !WINPOS_CanActivate((pWndTo = WIN_GetTopParentPtr(pWnd->owner))) )
2003 WND* pWndPtr = WIN_GetTopParentPtr(pWnd);
2005 WIN_ReleaseWndPtr(pWndTo);
2006 pWndTo = WIN_FindWndPtr(hwndPrevActive);
2008 while( !WINPOS_CanActivate(pWndTo) )
2010 /* by now owned windows should've been taken care of */
2011 WIN_UpdateWndPtr(&pWndTo,pWndPtr->next);
2012 WIN_UpdateWndPtr(&pWndPtr,pWndTo);
2013 if( !pWndTo ) break;
2015 WIN_ReleaseWndPtr(pWndPtr);
2018 bRet = WINPOS_SetActiveWindow( pWndTo ? pWndTo->hwndSelf : 0, FALSE, TRUE );
2020 /* switch desktop queue to current active */
2021 if( pWndTo )
2023 WIN_GetDesktop()->hmemTaskQ = pWndTo->hmemTaskQ;
2024 WIN_ReleaseWndPtr(pWndTo);
2025 WIN_ReleaseDesktop();
2028 hwndPrevActive = 0;
2029 return bRet;
2032 /*******************************************************************
2033 * WINPOS_ChangeActiveWindow
2036 BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
2038 WND *wndPtr, *wndTemp;
2039 BOOL retvalue;
2040 HWND hwndActive = 0;
2042 /* Get current active window from the active queue */
2043 if ( hActiveQueue )
2045 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2046 if ( pActiveQueue )
2048 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2049 QUEUE_Unlock( pActiveQueue );
2053 if (!hWnd)
2054 return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
2056 wndPtr = WIN_FindWndPtr(hWnd);
2057 if( !wndPtr ) return FALSE;
2059 /* child windows get WM_CHILDACTIVATE message */
2060 if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
2062 retvalue = SendMessageA(hWnd, WM_CHILDACTIVATE, 0, 0L);
2063 goto end;
2066 if( hWnd == hwndActive )
2068 retvalue = FALSE;
2069 goto end;
2072 if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
2074 retvalue = FALSE;
2075 goto end;
2078 /* switch desktop queue to current active */
2079 wndTemp = WIN_GetDesktop();
2080 if( wndPtr->parent == wndTemp)
2081 wndTemp->hmemTaskQ = wndPtr->hmemTaskQ;
2082 WIN_ReleaseDesktop();
2084 retvalue = TRUE;
2085 end:
2086 WIN_ReleaseWndPtr(wndPtr);
2087 return retvalue;
2091 /***********************************************************************
2092 * WINPOS_SendNCCalcSize
2094 * Send a WM_NCCALCSIZE message to a window.
2095 * All parameters are read-only except newClientRect.
2096 * oldWindowRect, oldClientRect and winpos must be non-NULL only
2097 * when calcValidRect is TRUE.
2099 LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect,
2100 RECT *newWindowRect, RECT *oldWindowRect,
2101 RECT *oldClientRect, WINDOWPOS *winpos,
2102 RECT *newClientRect )
2104 NCCALCSIZE_PARAMS params;
2105 WINDOWPOS winposCopy;
2106 LONG result;
2108 params.rgrc[0] = *newWindowRect;
2109 if (calcValidRect)
2111 winposCopy = *winpos;
2112 params.rgrc[1] = *oldWindowRect;
2113 params.rgrc[2] = *oldClientRect;
2114 params.lppos = &winposCopy;
2116 result = SendMessageA( hwnd, WM_NCCALCSIZE, calcValidRect,
2117 (LPARAM)&params );
2118 TRACE("%d,%d-%d,%d\n",
2119 params.rgrc[0].left, params.rgrc[0].top,
2120 params.rgrc[0].right, params.rgrc[0].bottom );
2122 /* If the application send back garbage, ignore it */
2123 if (params.rgrc[0].left <= params.rgrc[0].right && params.rgrc[0].top <= params.rgrc[0].bottom)
2124 *newClientRect = params.rgrc[0];
2126 return result;
2130 /***********************************************************************
2131 * WINPOS_HandleWindowPosChanging16
2133 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2135 LONG WINPOS_HandleWindowPosChanging16( WND *wndPtr, WINDOWPOS16 *winpos )
2137 POINT maxSize, minTrack;
2138 if (winpos->flags & SWP_NOSIZE) return 0;
2139 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2140 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2142 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
2143 if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
2144 if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
2145 if (!(wndPtr->dwStyle & WS_MINIMIZE))
2147 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
2148 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
2151 return 0;
2155 /***********************************************************************
2156 * WINPOS_HandleWindowPosChanging
2158 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2160 LONG WINPOS_HandleWindowPosChanging( WND *wndPtr, WINDOWPOS *winpos )
2162 POINT maxSize, minTrack;
2163 if (winpos->flags & SWP_NOSIZE) return 0;
2164 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2165 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2167 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
2168 winpos->cx = min( winpos->cx, maxSize.x );
2169 winpos->cy = min( winpos->cy, maxSize.y );
2170 if (!(wndPtr->dwStyle & WS_MINIMIZE))
2172 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
2173 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
2176 return 0;
2179 /***********************************************************************
2180 * SWP_DoOwnedPopups
2182 * fix Z order taking into account owned popups -
2183 * basically we need to maintain them above the window that owns them
2185 * FIXME: hide/show owned popups when owner visibility changes.
2187 static HWND SWP_DoOwnedPopups(WND* pDesktop, WND* wndPtr, HWND hwndInsertAfter, WORD flags)
2189 WND* w = WIN_LockWndPtr(pDesktop->child);
2191 WARN("(%04x) hInsertAfter = %04x\n", wndPtr->hwndSelf, hwndInsertAfter );
2193 if( (wndPtr->dwStyle & WS_POPUP) && wndPtr->owner )
2195 /* make sure this popup stays above the owner */
2197 HWND hwndLocalPrev = HWND_TOP;
2199 if( hwndInsertAfter != HWND_TOP )
2201 while( w && w != wndPtr->owner )
2203 if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
2204 if( hwndLocalPrev == hwndInsertAfter ) break;
2205 WIN_UpdateWndPtr(&w,w->next);
2207 hwndInsertAfter = hwndLocalPrev;
2210 else if( wndPtr->dwStyle & WS_CHILD )
2211 goto END;
2213 WIN_UpdateWndPtr(&w, pDesktop->child);
2215 while( w )
2217 if( w == wndPtr ) break;
2219 if( (w->dwStyle & WS_POPUP) && w->owner == wndPtr )
2221 SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0,
2222 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
2223 hwndInsertAfter = w->hwndSelf;
2225 WIN_UpdateWndPtr(&w, w->next);
2228 END:
2229 WIN_ReleaseWndPtr(w);
2230 return hwndInsertAfter;
2233 /***********************************************************************
2234 * SWP_CopyValidBits
2236 * Make window look nice without excessive repainting
2238 * visible and update regions are in window coordinates
2239 * client and window rectangles are in parent client coordinates
2241 * Returns: uFlags and a dirty region in *pVisRgn.
2243 static UINT SWP_CopyValidBits( WND* Wnd, HRGN* pVisRgn,
2244 LPRECT lpOldWndRect,
2245 LPRECT lpOldClientRect, UINT uFlags )
2247 RECT r;
2248 HRGN newVisRgn, dirtyRgn;
2249 INT my = COMPLEXREGION;
2250 DWORD dflags;
2252 TRACE("\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2253 Wnd->rectWindow.left, Wnd->rectWindow.top,
2254 Wnd->rectWindow.right, Wnd->rectWindow.bottom,
2255 lpOldWndRect->left, lpOldWndRect->top,
2256 lpOldWndRect->right, lpOldWndRect->bottom, *pVisRgn);
2257 TRACE("\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2258 Wnd->rectClient.left, Wnd->rectClient.top,
2259 Wnd->rectClient.right, Wnd->rectClient.bottom,
2260 lpOldClientRect->left, lpOldClientRect->top,
2261 lpOldClientRect->right,lpOldClientRect->bottom );
2263 if( Wnd->hrgnUpdate == 1 )
2264 uFlags |= SWP_EX_NOCOPY; /* whole window is invalid, nothing to copy */
2266 dflags = DCX_WINDOW;
2267 if(Wnd->dwStyle & WS_CLIPSIBLINGS)
2268 dflags |= DCX_CLIPSIBLINGS;
2269 newVisRgn = DCE_GetVisRgn( Wnd->hwndSelf, dflags, 0, 0);
2271 dirtyRgn = CreateRectRgn( 0, 0, 0, 0 );
2273 if( !(uFlags & SWP_EX_NOCOPY) ) /* make sure dst region covers only valid bits */
2274 my = CombineRgn( dirtyRgn, newVisRgn, *pVisRgn, RGN_AND );
2276 if( (my == NULLREGION) || (uFlags & SWP_EX_NOCOPY) )
2278 nocopy:
2280 TRACE("\twon't copy anything!\n");
2282 /* set dirtyRgn to the sum of old and new visible regions
2283 * in parent client coordinates */
2285 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2286 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2288 CombineRgn(*pVisRgn, *pVisRgn, newVisRgn, RGN_OR );
2290 else /* copy valid bits to a new location */
2292 INT dx, dy, ow, oh, nw, nh, ocw, ncw, och, nch;
2293 HRGN hrgnValid = dirtyRgn; /* non-empty intersection of old and new visible rgns */
2295 /* subtract already invalid region inside Wnd from the dst region */
2297 if( Wnd->hrgnUpdate )
2298 if( CombineRgn( hrgnValid, hrgnValid, Wnd->hrgnUpdate, RGN_DIFF) == NULLREGION )
2299 goto nocopy;
2301 /* check if entire window can be copied */
2303 ow = lpOldWndRect->right - lpOldWndRect->left;
2304 oh = lpOldWndRect->bottom - lpOldWndRect->top;
2305 nw = Wnd->rectWindow.right - Wnd->rectWindow.left;
2306 nh = Wnd->rectWindow.bottom - Wnd->rectWindow.top;
2308 ocw = lpOldClientRect->right - lpOldClientRect->left;
2309 och = lpOldClientRect->bottom - lpOldClientRect->top;
2310 ncw = Wnd->rectClient.right - Wnd->rectClient.left;
2311 nch = Wnd->rectClient.bottom - Wnd->rectClient.top;
2313 if( (ocw != ncw) || (och != nch) ||
2314 ( ow != nw) || ( oh != nh) ||
2315 ((lpOldClientRect->top - lpOldWndRect->top) !=
2316 (Wnd->rectClient.top - Wnd->rectWindow.top)) ||
2317 ((lpOldClientRect->left - lpOldWndRect->left) !=
2318 (Wnd->rectClient.left - Wnd->rectWindow.left)) )
2320 if(uFlags & SWP_EX_PAINTSELF)
2322 /* movement relative to the window itself */
2323 dx = (Wnd->rectClient.left - Wnd->rectWindow.left) -
2324 (lpOldClientRect->left - lpOldWndRect->left) ;
2325 dy = (Wnd->rectClient.top - Wnd->rectWindow.top) -
2326 (lpOldClientRect->top - lpOldWndRect->top) ;
2328 else
2330 /* movement relative to the parent's client area */
2331 dx = Wnd->rectClient.left - lpOldClientRect->left;
2332 dy = Wnd->rectClient.top - lpOldClientRect->top;
2335 /* restrict valid bits to the common client rect */
2337 r.left = Wnd->rectClient.left - Wnd->rectWindow.left;
2338 r.top = Wnd->rectClient.top - Wnd->rectWindow.top;
2339 r.right = r.left + min( ocw, ncw );
2340 r.bottom = r.top + min( och, nch );
2342 REGION_CropRgn( hrgnValid, hrgnValid, &r,
2343 (uFlags & SWP_EX_PAINTSELF) ? NULL : (POINT*)&(Wnd->rectWindow));
2344 GetRgnBox( hrgnValid, &r );
2345 if( IsRectEmpty( &r ) )
2346 goto nocopy;
2347 r = *lpOldClientRect;
2349 else
2351 if(uFlags & SWP_EX_PAINTSELF) {
2353 * with SWP_EX_PAINTSELF, the window repaints itself. Since a window can't move
2354 * relative to itself, only the client area can change.
2355 * if the client rect didn't change, there's nothing to do.
2357 dx = 0;
2358 dy = 0;
2360 else
2362 dx = Wnd->rectWindow.left - lpOldWndRect->left;
2363 dy = Wnd->rectWindow.top - lpOldWndRect->top;
2364 OffsetRgn( hrgnValid, Wnd->rectWindow.left, Wnd->rectWindow.top );
2366 r = *lpOldWndRect;
2369 if( !(uFlags & SWP_EX_PAINTSELF) )
2371 /* Move remaining regions to parent coordinates */
2372 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2373 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2375 else
2376 OffsetRect( &r, -lpOldWndRect->left, -lpOldWndRect->top );
2378 TRACE("\tcomputing dirty region!\n");
2380 /* Compute combined dirty region (old + new - valid) */
2381 CombineRgn( *pVisRgn, *pVisRgn, newVisRgn, RGN_OR);
2382 CombineRgn( *pVisRgn, *pVisRgn, hrgnValid, RGN_DIFF);
2384 /* Blt valid bits, r is the rect to copy */
2386 if( dx || dy )
2388 RECT rClip;
2389 HDC hDC;
2391 /* get DC and clip rect with drawable rect to avoid superfluous expose events
2392 from copying clipped areas */
2394 if( uFlags & SWP_EX_PAINTSELF )
2396 hDC = GetDCEx( Wnd->hwndSelf, hrgnValid, DCX_WINDOW | DCX_CACHE |
2397 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2398 rClip.right = nw; rClip.bottom = nh;
2400 else
2402 hDC = GetDCEx( Wnd->parent->hwndSelf, hrgnValid, DCX_CACHE |
2403 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2404 rClip.right = Wnd->parent->rectClient.right - Wnd->parent->rectClient.left;
2405 rClip.bottom = Wnd->parent->rectClient.bottom - Wnd->parent->rectClient.top;
2407 rClip.left = rClip.top = 0;
2409 if( oh > nh ) r.bottom = r.top + nh;
2410 if( ow < nw ) r.right = r.left + nw;
2412 if( IntersectRect( &r, &r, &rClip ) )
2414 Wnd->pDriver->pSurfaceCopy( Wnd->parent, hDC, dx, dy, &r, TRUE );
2416 /* When you copy the bits without repainting, parent doesn't
2417 get validated appropriately. Therefore, we have to validate
2418 the parent with the windows' updated region when the
2419 parent's update region is not empty. */
2421 if (Wnd->parent->hrgnUpdate != 0 && !(Wnd->parent->dwStyle & WS_CLIPCHILDREN))
2423 OffsetRect(&r, dx, dy);
2424 ValidateRect(Wnd->parent->hwndSelf, &r);
2427 ReleaseDC( (uFlags & SWP_EX_PAINTSELF) ?
2428 Wnd->hwndSelf : Wnd->parent->hwndSelf, hDC);
2432 /* *pVisRgn now points to the invalidated region */
2434 DeleteObject(newVisRgn);
2435 DeleteObject(dirtyRgn);
2436 return uFlags;
2439 /***********************************************************************
2440 * SWP_DoSimpleFrameChanged
2442 * NOTE: old and new client rect origins are identical, only
2443 * extents may have changed. Window extents are the same.
2445 static void SWP_DoSimpleFrameChanged( WND* wndPtr, RECT* pOldClientRect, WORD swpFlags, UINT uFlags )
2447 INT i = 0;
2448 RECT rect;
2449 HRGN hrgn = 0;
2451 if( !(swpFlags & SWP_NOCLIENTSIZE) )
2453 /* Client rect changed its position/size, most likely a scrollar
2454 * was added/removed.
2456 * FIXME: WVR alignment flags
2459 if( wndPtr->rectClient.right > pOldClientRect->right ) /* right edge */
2461 i++;
2462 rect.top = 0;
2463 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2464 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2465 if(!(uFlags & SWP_EX_NOCOPY))
2466 rect.left = pOldClientRect->right - wndPtr->rectClient.left;
2467 else
2469 rect.left = 0;
2470 goto redraw;
2474 if( wndPtr->rectClient.bottom > pOldClientRect->bottom ) /* bottom edge */
2476 if( i )
2477 hrgn = CreateRectRgnIndirect( &rect );
2478 rect.left = 0;
2479 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2480 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2481 if(!(uFlags & SWP_EX_NOCOPY))
2482 rect.top = pOldClientRect->bottom - wndPtr->rectClient.top;
2483 else
2484 rect.top = 0;
2485 if( i++ )
2486 REGION_UnionRectWithRgn( hrgn, &rect );
2489 if( i == 0 && (uFlags & SWP_EX_NOCOPY) ) /* force redraw anyway */
2491 rect = wndPtr->rectWindow;
2492 OffsetRect( &rect, wndPtr->rectWindow.left - wndPtr->rectClient.left,
2493 wndPtr->rectWindow.top - wndPtr->rectClient.top );
2494 i++;
2498 if( i )
2500 redraw:
2501 PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
2502 RDW_ERASENOW | RDW_ALLCHILDREN, RDW_EX_TOPFRAME | RDW_EX_USEHRGN );
2504 else
2506 WIN_UpdateNCRgn(wndPtr, 0, UNC_UPDATE | UNC_ENTIRE);
2509 if( hrgn > 1 )
2510 DeleteObject( hrgn );
2513 /***********************************************************************
2514 * SWP_DoWinPosChanging
2516 static BOOL SWP_DoWinPosChanging( WND* wndPtr, WINDOWPOS* pWinpos,
2517 RECT* pNewWindowRect, RECT* pNewClientRect )
2519 /* Send WM_WINDOWPOSCHANGING message */
2521 if (!(pWinpos->flags & SWP_NOSENDCHANGING))
2522 SendMessageA( wndPtr->hwndSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM)pWinpos );
2524 /* Calculate new position and size */
2526 *pNewWindowRect = wndPtr->rectWindow;
2527 *pNewClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
2528 : wndPtr->rectClient;
2530 if (!(pWinpos->flags & SWP_NOSIZE))
2532 pNewWindowRect->right = pNewWindowRect->left + pWinpos->cx;
2533 pNewWindowRect->bottom = pNewWindowRect->top + pWinpos->cy;
2535 if (!(pWinpos->flags & SWP_NOMOVE))
2537 pNewWindowRect->left = pWinpos->x;
2538 pNewWindowRect->top = pWinpos->y;
2539 pNewWindowRect->right += pWinpos->x - wndPtr->rectWindow.left;
2540 pNewWindowRect->bottom += pWinpos->y - wndPtr->rectWindow.top;
2542 OffsetRect( pNewClientRect, pWinpos->x - wndPtr->rectWindow.left,
2543 pWinpos->y - wndPtr->rectWindow.top );
2546 pWinpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
2547 return TRUE;
2550 /***********************************************************************
2551 * SWP_DoNCCalcSize
2553 static UINT SWP_DoNCCalcSize( WND* wndPtr, WINDOWPOS* pWinpos,
2554 RECT* pNewWindowRect, RECT* pNewClientRect, WORD f)
2556 UINT wvrFlags = 0;
2558 /* Send WM_NCCALCSIZE message to get new client area */
2559 if( (pWinpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
2561 wvrFlags = WINPOS_SendNCCalcSize( pWinpos->hwnd, TRUE, pNewWindowRect,
2562 &wndPtr->rectWindow, &wndPtr->rectClient,
2563 pWinpos, pNewClientRect );
2565 /* FIXME: WVR_ALIGNxxx */
2567 if( pNewClientRect->left != wndPtr->rectClient.left ||
2568 pNewClientRect->top != wndPtr->rectClient.top )
2569 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2571 if( (pNewClientRect->right - pNewClientRect->left !=
2572 wndPtr->rectClient.right - wndPtr->rectClient.left) ||
2573 (pNewClientRect->bottom - pNewClientRect->top !=
2574 wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
2575 pWinpos->flags &= ~SWP_NOCLIENTSIZE;
2577 else
2578 if( !(f & SWP_NOMOVE) && (pNewClientRect->left != wndPtr->rectClient.left ||
2579 pNewClientRect->top != wndPtr->rectClient.top) )
2580 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2581 return wvrFlags;
2584 /***********************************************************************
2585 * SetWindowPos (USER.232)
2587 BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
2588 INT16 x, INT16 y, INT16 cx, INT16 cy, WORD flags)
2590 return SetWindowPos(hwnd,(INT)(INT16)hwndInsertAfter,x,y,cx,cy,flags);
2593 /***********************************************************************
2594 * SetWindowPos (USER32.@)
2596 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
2597 INT x, INT y, INT cx, INT cy, UINT flags )
2599 WINDOWPOS winpos;
2600 WND * wndPtr,*wndTemp;
2601 RECT newWindowRect, newClientRect;
2602 RECT oldWindowRect, oldClientRect;
2603 HRGN visRgn = 0;
2604 UINT wvrFlags = 0, uFlags = 0;
2605 BOOL retvalue, resync = FALSE, bChangePos;
2606 HWND hwndActive = 0;
2608 /* Get current active window from the active queue */
2609 if ( hActiveQueue )
2611 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2612 if ( pActiveQueue )
2614 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2615 QUEUE_Unlock( pActiveQueue );
2619 TRACE("hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2620 hwnd, x, y, x+cx, y+cy, flags);
2622 bChangePos = !(flags & SWP_WINE_NOHOSTMOVE);
2623 flags &= ~SWP_WINE_NOHOSTMOVE;
2626 /* ------------------------------------------------------------------------ CHECKS */
2628 /* Check window handle */
2630 if (hwnd == GetDesktopWindow()) return FALSE;
2631 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2633 TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr->rectWindow.left, wndPtr->rectWindow.top,
2634 wndPtr->rectWindow.right, wndPtr->rectWindow.bottom, (unsigned)wndPtr->dwStyle );
2636 /* Fix redundant flags */
2638 if(wndPtr->dwStyle & WS_VISIBLE)
2639 flags &= ~SWP_SHOWWINDOW;
2640 else
2642 if (!(flags & SWP_SHOWWINDOW))
2643 flags |= SWP_NOREDRAW;
2644 flags &= ~SWP_HIDEWINDOW;
2647 if ( cx < 0 ) cx = 0; if( cy < 0 ) cy = 0;
2649 if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
2650 (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
2651 flags |= SWP_NOSIZE; /* Already the right size */
2653 if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
2654 flags |= SWP_NOMOVE; /* Already the right position */
2656 if (hwnd == hwndActive)
2657 flags |= SWP_NOACTIVATE; /* Already active */
2658 else if ( (wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD )
2660 if(!(flags & SWP_NOACTIVATE)) /* Bring to the top when activating */
2662 flags &= ~SWP_NOZORDER;
2663 hwndInsertAfter = HWND_TOP;
2664 goto Pos;
2668 /* Check hwndInsertAfter */
2670 /* FIXME: TOPMOST not supported yet */
2671 if ((hwndInsertAfter == HWND_TOPMOST) ||
2672 (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
2674 /* hwndInsertAfter must be a sibling of the window */
2675 if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
2677 WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
2679 if( wnd ) {
2680 if( wnd->parent != wndPtr->parent )
2682 retvalue = FALSE;
2683 WIN_ReleaseWndPtr(wnd);
2684 goto END;
2686 /* don't need to change the Zorder of hwnd if it's already inserted
2687 * after hwndInsertAfter or when inserting hwnd after itself.
2689 if(( wnd->next == wndPtr ) || (hwnd == hwndInsertAfter)) flags |= SWP_NOZORDER;
2691 WIN_ReleaseWndPtr(wnd);
2694 Pos: /* ------------------------------------------------------------------------ MAIN part */
2696 /* Fill the WINDOWPOS structure */
2698 winpos.hwnd = hwnd;
2699 winpos.hwndInsertAfter = hwndInsertAfter;
2700 winpos.x = x;
2701 winpos.y = y;
2702 winpos.cx = cx;
2703 winpos.cy = cy;
2704 winpos.flags = flags;
2706 SWP_DoWinPosChanging( wndPtr, &winpos, &newWindowRect, &newClientRect );
2708 if((winpos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER)
2710 if( wndPtr->parent == WIN_GetDesktop() )
2711 hwndInsertAfter = SWP_DoOwnedPopups( wndPtr->parent, wndPtr,
2712 hwndInsertAfter, winpos.flags );
2713 WIN_ReleaseDesktop();
2716 if(!(wndPtr->flags & WIN_NATIVE) )
2718 if( hwndInsertAfter == HWND_TOP )
2719 winpos.flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
2720 else
2721 if( hwndInsertAfter == HWND_BOTTOM )
2722 winpos.flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
2723 else
2724 if( !(winpos.flags & SWP_NOZORDER) )
2725 if( GetWindow(hwndInsertAfter, GW_HWNDNEXT) == wndPtr->hwndSelf )
2726 winpos.flags |= SWP_NOZORDER;
2728 if( !(winpos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) &&
2729 ((winpos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW | SWP_FRAMECHANGED))
2730 != (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)) )
2732 /* get a previous visible region for SWP_CopyValidBits() */
2733 DWORD dflags = DCX_WINDOW;
2735 if (wndPtr->dwStyle & WS_CLIPSIBLINGS)
2736 dflags |= DCX_CLIPSIBLINGS;
2738 visRgn = DCE_GetVisRgn(hwnd, dflags, 0, 0);
2742 /* Common operations */
2744 wvrFlags = SWP_DoNCCalcSize( wndPtr, &winpos, &newWindowRect, &newClientRect, flags );
2746 if(!(winpos.flags & SWP_NOZORDER) && winpos.hwnd != hwndInsertAfter)
2748 if ( WIN_UnlinkWindow( winpos.hwnd ) )
2749 WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
2752 /* Reset active DCEs */
2754 if( (((winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) &&
2755 wndPtr->dwStyle & WS_VISIBLE) ||
2756 (flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
2758 RECT rect;
2760 UnionRect(&rect, &newWindowRect, &wndPtr->rectWindow);
2761 DCE_InvalidateDCE(wndPtr, &rect);
2764 oldWindowRect = wndPtr->rectWindow;
2765 oldClientRect = wndPtr->rectClient;
2767 /* Find out if we have to redraw the whole client rect */
2769 if( oldClientRect.bottom - oldClientRect.top ==
2770 newClientRect.bottom - newClientRect.top ) wvrFlags &= ~WVR_VREDRAW;
2772 if( oldClientRect.right - oldClientRect.left ==
2773 newClientRect.right - newClientRect.left ) wvrFlags &= ~WVR_HREDRAW;
2775 if( (winpos.flags & SWP_NOCOPYBITS) || (!(winpos.flags & SWP_NOCLIENTSIZE) &&
2776 (wvrFlags >= WVR_HREDRAW) && (wvrFlags < WVR_VALIDRECTS)) )
2778 uFlags |= SWP_EX_NOCOPY;
2781 * Use this later in CopyValidBits()
2783 else if( 0 )
2784 uFlags |= SWP_EX_NONCLIENT;
2787 /* FIXME: actually do something with WVR_VALIDRECTS */
2789 wndPtr->rectWindow = newWindowRect;
2790 wndPtr->rectClient = newClientRect;
2792 if (wndPtr->flags & WIN_NATIVE) /* -------------------------------------------- hosted window */
2794 BOOL bCallDriver = TRUE;
2795 HWND tempInsertAfter = winpos.hwndInsertAfter;
2797 winpos.hwndInsertAfter = hwndInsertAfter;
2799 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2801 /* This is the only place where we need to force repainting of the contents
2802 of windows created by the host window system, all other cases go through the
2803 expose event handling */
2805 if( (winpos.flags & (SWP_NOSIZE | SWP_FRAMECHANGED)) == (SWP_NOSIZE | SWP_FRAMECHANGED) )
2807 cx = newWindowRect.right - newWindowRect.left;
2808 cy = newWindowRect.bottom - newWindowRect.top;
2810 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2811 winpos.hwndInsertAfter = tempInsertAfter;
2812 bCallDriver = FALSE;
2814 if( winpos.flags & SWP_NOCLIENTMOVE )
2815 SWP_DoSimpleFrameChanged(wndPtr, &oldClientRect, winpos.flags, uFlags );
2816 else
2818 /* client area moved but window extents remained the same, copy valid bits */
2820 visRgn = CreateRectRgn( 0, 0, cx, cy );
2821 uFlags = SWP_CopyValidBits( wndPtr, &visRgn, &oldWindowRect, &oldClientRect,
2822 uFlags | SWP_EX_PAINTSELF );
2827 if( bCallDriver )
2829 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2831 if( (oldClientRect.left - oldWindowRect.left == newClientRect.left - newWindowRect.left) &&
2832 (oldClientRect.top - oldWindowRect.top == newClientRect.top - newWindowRect.top) &&
2833 !(uFlags & SWP_EX_NOCOPY) )
2835 /* The origin of the client rect didn't move so we can try to repaint
2836 * only the nonclient area by setting bit gravity hint for the host window system.
2839 if( !(wndPtr->dwExStyle & WS_EX_MANAGED) )
2841 HRGN hrgn = CreateRectRgn( 0, 0, newWindowRect.right - newWindowRect.left,
2842 newWindowRect.bottom - newWindowRect.top);
2843 RECT rcn = newClientRect;
2844 RECT rco = oldClientRect;
2846 OffsetRect( &rcn, -newWindowRect.left, -newWindowRect.top );
2847 OffsetRect( &rco, -oldWindowRect.left, -oldWindowRect.top );
2848 IntersectRect( &rcn, &rcn, &rco );
2849 visRgn = CreateRectRgnIndirect( &rcn );
2850 CombineRgn( visRgn, hrgn, visRgn, RGN_DIFF );
2851 DeleteObject( hrgn );
2852 uFlags = SWP_EX_PAINTSELF;
2854 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGNorthWest );
2858 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2859 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGForget );
2860 winpos.hwndInsertAfter = tempInsertAfter;
2863 if( winpos.flags & SWP_SHOWWINDOW )
2865 HWND focus, curr;
2867 wndPtr->dwStyle |= WS_VISIBLE;
2869 if (wndPtr->dwExStyle & WS_EX_MANAGED) resync = TRUE;
2871 /* focus was set to unmapped window, reset host focus
2872 * since the window is now visible */
2874 focus = curr = GetFocus();
2875 while (curr)
2877 if (curr == hwnd)
2879 WND *pFocus = WIN_FindWndPtr( focus );
2880 if (pFocus)
2881 pFocus->pDriver->pSetFocus(pFocus);
2882 WIN_ReleaseWndPtr(pFocus);
2883 break;
2885 curr = GetParent(curr);
2889 else /* -------------------------------------------- emulated window */
2891 if( winpos.flags & SWP_SHOWWINDOW )
2893 wndPtr->dwStyle |= WS_VISIBLE;
2894 uFlags |= SWP_EX_PAINTSELF;
2895 visRgn = 1; /* redraw the whole window */
2897 else if( !(winpos.flags & SWP_NOREDRAW) )
2899 if( winpos.flags & SWP_HIDEWINDOW )
2901 if( visRgn > 1 ) /* map to parent */
2902 OffsetRgn( visRgn, oldWindowRect.left, oldWindowRect.top );
2903 else
2904 visRgn = 0;
2906 else
2908 if( (winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE )
2909 uFlags = SWP_CopyValidBits(wndPtr, &visRgn, &oldWindowRect,
2910 &oldClientRect, uFlags);
2911 else
2913 /* nothing moved, redraw frame if needed */
2915 if( winpos.flags & SWP_FRAMECHANGED )
2916 SWP_DoSimpleFrameChanged( wndPtr, &oldClientRect, winpos.flags, uFlags );
2917 if( visRgn )
2919 DeleteObject( visRgn );
2920 visRgn = 0;
2927 if( winpos.flags & SWP_HIDEWINDOW )
2929 wndPtr->dwStyle &= ~WS_VISIBLE;
2932 if (hwnd == CARET_GetHwnd())
2934 if( winpos.flags & SWP_HIDEWINDOW )
2935 HideCaret(hwnd);
2936 else if (winpos.flags & SWP_SHOWWINDOW)
2937 ShowCaret(hwnd);
2940 /* ------------------------------------------------------------------------ FINAL */
2942 if (wndPtr->flags & WIN_NATIVE)
2943 EVENT_Synchronize(); /* Synchronize with the host window system */
2945 wndTemp = WIN_GetDesktop();
2947 /* repaint invalidated region (if any)
2949 * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2950 * and force update after ChangeActiveWindow() to avoid painting frames twice.
2953 if( visRgn )
2955 if( !(winpos.flags & SWP_NOREDRAW) )
2958 /* Use PAINT_RedrawWindow to explicitly force an invalidation of the window,
2959 its parent and sibling and so on, and then erase the parent window
2960 background if the parent is either a top-level window or its parent's parent
2961 is top-level window. Rely on the system to repaint other affected
2962 windows later on. */
2963 if( uFlags & SWP_EX_PAINTSELF )
2965 PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn,
2966 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN,
2967 RDW_EX_XYWINDOW | RDW_EX_USEHRGN );
2969 else
2971 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn,
2972 RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN,
2973 RDW_EX_USEHRGN );
2976 if(wndPtr -> parent == wndTemp || wndPtr->parent->parent == wndTemp )
2978 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0,
2979 RDW_ERASENOW | RDW_NOCHILDREN, 0 );
2982 if( visRgn != 1 )
2983 DeleteObject( visRgn );
2986 WIN_ReleaseDesktop();
2988 if (!(flags & SWP_NOACTIVATE))
2989 WINPOS_ChangeActiveWindow( winpos.hwnd, FALSE );
2991 /* And last, send the WM_WINDOWPOSCHANGED message */
2993 TRACE("\tstatus flags = %04x\n", winpos.flags & SWP_AGG_STATUSFLAGS);
2995 if ( resync ||
2996 (((winpos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) &&
2997 !(winpos.flags & SWP_NOSENDCHANGING)) )
2999 SendMessageA( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
3000 if (resync) EVENT_Synchronize();
3003 retvalue = TRUE;
3004 END:
3005 WIN_ReleaseWndPtr(wndPtr);
3006 return retvalue;
3010 /***********************************************************************
3011 * BeginDeferWindowPos (USER.259)
3013 HDWP16 WINAPI BeginDeferWindowPos16( INT16 count )
3015 return BeginDeferWindowPos( count );
3019 /***********************************************************************
3020 * BeginDeferWindowPos (USER32.@)
3022 HDWP WINAPI BeginDeferWindowPos( INT count )
3024 HDWP handle;
3025 DWP *pDWP;
3027 if (count < 0)
3029 SetLastError(ERROR_INVALID_PARAMETER);
3030 return 0;
3032 /* Windows allows zero count, in which case it allocates context for 8 moves */
3033 if (count == 0) count = 8;
3035 handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
3036 if (!handle) return 0;
3037 pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
3038 pDWP->actualCount = 0;
3039 pDWP->suggestedCount = count;
3040 pDWP->valid = TRUE;
3041 pDWP->wMagic = DWP_MAGIC;
3042 pDWP->hwndParent = 0;
3043 return handle;
3047 /***********************************************************************
3048 * DeferWindowPos (USER.260)
3050 HDWP16 WINAPI DeferWindowPos16( HDWP16 hdwp, HWND16 hwnd, HWND16 hwndAfter,
3051 INT16 x, INT16 y, INT16 cx, INT16 cy,
3052 UINT16 flags )
3054 return DeferWindowPos( hdwp, hwnd, (INT)(INT16)hwndAfter,
3055 x, y, cx, cy, flags );
3059 /***********************************************************************
3060 * DeferWindowPos (USER32.@)
3062 HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter,
3063 INT x, INT y, INT cx, INT cy,
3064 UINT flags )
3066 DWP *pDWP;
3067 int i;
3068 HDWP newhdwp = hdwp,retvalue;
3069 /* HWND parent; */
3070 WND *pWnd;
3072 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
3073 if (!pDWP) return 0;
3074 if (hwnd == GetDesktopWindow()) return 0;
3076 if (!(pWnd=WIN_FindWndPtr( hwnd ))) {
3077 USER_HEAP_FREE( hdwp );
3078 return 0;
3081 /* Numega Bounds Checker Demo dislikes the following code.
3082 In fact, I've not been able to find any "same parent" requirement in any docu
3083 [AM 980509]
3085 #if 0
3086 /* All the windows of a DeferWindowPos() must have the same parent */
3087 parent = pWnd->parent->hwndSelf;
3088 if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
3089 else if (parent != pDWP->hwndParent)
3091 USER_HEAP_FREE( hdwp );
3092 retvalue = 0;
3093 goto END;
3095 #endif
3097 for (i = 0; i < pDWP->actualCount; i++)
3099 if (pDWP->winPos[i].hwnd == hwnd)
3101 /* Merge with the other changes */
3102 if (!(flags & SWP_NOZORDER))
3104 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
3106 if (!(flags & SWP_NOMOVE))
3108 pDWP->winPos[i].x = x;
3109 pDWP->winPos[i].y = y;
3111 if (!(flags & SWP_NOSIZE))
3113 pDWP->winPos[i].cx = cx;
3114 pDWP->winPos[i].cy = cy;
3116 pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
3117 SWP_NOZORDER | SWP_NOREDRAW |
3118 SWP_NOACTIVATE | SWP_NOCOPYBITS|
3119 SWP_NOOWNERZORDER);
3120 pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
3121 SWP_FRAMECHANGED);
3122 retvalue = hdwp;
3123 goto END;
3126 if (pDWP->actualCount >= pDWP->suggestedCount)
3128 newhdwp = USER_HEAP_REALLOC( hdwp,
3129 sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
3130 if (!newhdwp)
3132 retvalue = 0;
3133 goto END;
3135 pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
3136 pDWP->suggestedCount++;
3138 pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
3139 pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
3140 pDWP->winPos[pDWP->actualCount].x = x;
3141 pDWP->winPos[pDWP->actualCount].y = y;
3142 pDWP->winPos[pDWP->actualCount].cx = cx;
3143 pDWP->winPos[pDWP->actualCount].cy = cy;
3144 pDWP->winPos[pDWP->actualCount].flags = flags;
3145 pDWP->actualCount++;
3146 retvalue = newhdwp;
3147 END:
3148 WIN_ReleaseWndPtr(pWnd);
3149 return retvalue;
3153 /***********************************************************************
3154 * EndDeferWindowPos (USER.261)
3156 BOOL16 WINAPI EndDeferWindowPos16( HDWP16 hdwp )
3158 return EndDeferWindowPos( hdwp );
3162 /***********************************************************************
3163 * EndDeferWindowPos (USER32.@)
3165 BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
3167 DWP *pDWP;
3168 WINDOWPOS *winpos;
3169 BOOL res = TRUE;
3170 int i;
3172 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
3173 if (!pDWP) return FALSE;
3174 for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
3176 if (!(res = SetWindowPos( winpos->hwnd, winpos->hwndInsertAfter,
3177 winpos->x, winpos->y, winpos->cx,
3178 winpos->cy, winpos->flags ))) break;
3180 USER_HEAP_FREE( hdwp );
3181 return res;
3185 /***********************************************************************
3186 * TileChildWindows (USER.199)
3188 void WINAPI TileChildWindows16( HWND16 parent, WORD action )
3190 FIXME("(%04x, %d): stub\n", parent, action);
3193 /***********************************************************************
3194 * CascadeChildWindows (USER.198)
3196 void WINAPI CascadeChildWindows16( HWND16 parent, WORD action )
3198 FIXME("(%04x, %d): stub\n", parent, action);
3201 /***********************************************************************
3202 * SetProgmanWindow (USER32.@)
3204 HRESULT WINAPI SetProgmanWindow ( HWND hwnd )
3206 hGlobalProgmanWindow = hwnd;
3207 return hGlobalProgmanWindow;
3210 /***********************************************************************
3211 * GetProgmanWindow (USER32.@)
3213 HRESULT WINAPI GetProgmanWindow ( )
3215 return hGlobalProgmanWindow;
3218 /***********************************************************************
3219 * SetShellWindowEx (USER32.@)
3220 * hwndProgman = Progman[Program Manager]
3221 * |-> SHELLDLL_DefView
3222 * hwndListView = | |-> SysListView32
3223 * | | |-> tooltips_class32
3224 * | |
3225 * | |-> SysHeader32
3226 * |
3227 * |-> ProxyTarget
3229 HRESULT WINAPI SetShellWindowEx ( HWND hwndProgman, HWND hwndListView )
3231 FIXME("0x%08x 0x%08x stub\n",hwndProgman ,hwndListView );
3232 hGlobalShellWindow = hwndProgman;
3233 return hGlobalShellWindow;
3237 /***********************************************************************
3238 * SetTaskmanWindow (USER32.@)
3239 * NOTES
3240 * hwnd = MSTaskSwWClass
3241 * |-> SysTabControl32
3243 HRESULT WINAPI SetTaskmanWindow ( HWND hwnd )
3245 hGlobalTaskmanWindow = hwnd;
3246 return hGlobalTaskmanWindow;
3249 /***********************************************************************
3250 * GetTaskmanWindow (USER32.@)
3252 HRESULT WINAPI GetTaskmanWindow ( )
3254 return hGlobalTaskmanWindow;