Removed the Release in case of error as we do not AddRef anymore.
[wine/multimedia.git] / windows / winpos.c
blobd46568257058261e306f9992e5f1fb6e2f23ee2d
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 "windef.h"
10 #include "wingdi.h"
11 #include "wine/winuser16.h"
12 #include "heap.h"
13 #include "module.h"
14 #include "user.h"
15 #include "region.h"
16 #include "win.h"
17 #include "hook.h"
18 #include "message.h"
19 #include "queue.h"
20 #include "options.h"
21 #include "task.h"
22 #include "winpos.h"
23 #include "dce.h"
24 #include "nonclient.h"
25 #include "debugtools.h"
26 #include "local.h"
27 #include "ldt.h"
28 #include "input.h"
30 DEFAULT_DEBUG_CHANNEL(win)
32 #define HAS_DLGFRAME(style,exStyle) \
33 (((exStyle) & WS_EX_DLGMODALFRAME) || \
34 (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
36 #define HAS_THICKFRAME(style) \
37 (((style) & WS_THICKFRAME) && \
38 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
40 #define SWP_AGG_NOGEOMETRYCHANGE \
41 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
42 #define SWP_AGG_NOPOSCHANGE \
43 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
44 #define SWP_AGG_STATUSFLAGS \
45 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
47 #define EMPTYPOINT(pt) ((*(LONG*)&(pt)) == -1)
49 #define PLACE_MIN 0x0001
50 #define PLACE_MAX 0x0002
51 #define PLACE_RECT 0x0004
53 #define SWP_EX_NOCOPY 0x0001
54 #define SWP_EX_PAINTSELF 0x0002
55 #define SWP_EX_NONCLIENT 0x0004
57 #define MINMAX_NOSWP 0x00010000
59 /* ----- internal variables ----- */
61 static HWND hwndPrevActive = 0; /* Previously active window */
62 static HWND hGlobalShellWindow=0; /*the shell*/
63 static HWND hGlobalTaskmanWindow=0;
64 static HWND hGlobalProgmanWindow=0;
66 static LPCSTR atomInternalPos;
68 extern HQUEUE16 hActiveQueue;
70 /***********************************************************************
71 * WINPOS_CreateInternalPosAtom
73 BOOL WINPOS_CreateInternalPosAtom()
75 LPSTR str = "SysIP";
76 atomInternalPos = (LPCSTR)(DWORD)GlobalAddAtomA(str);
77 return (atomInternalPos) ? TRUE : FALSE;
80 /***********************************************************************
81 * WINPOS_CheckInternalPos
83 * Called when a window is destroyed.
85 void WINPOS_CheckInternalPos( WND* wndPtr )
87 LPINTERNALPOS lpPos;
88 MESSAGEQUEUE *pMsgQ = 0;
89 HWND hwnd = wndPtr->hwndSelf;
91 lpPos = (LPINTERNALPOS) GetPropA( hwnd, atomInternalPos );
93 /* Retrieve the message queue associated with this window */
94 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
95 if ( !pMsgQ )
97 WARN("\tMessage queue not found. Exiting!\n" );
98 return;
101 if( hwnd == hwndPrevActive ) hwndPrevActive = 0;
103 if( hwnd == PERQDATA_GetActiveWnd( pMsgQ->pQData ) )
105 PERQDATA_SetActiveWnd( pMsgQ->pQData, 0 );
106 WARN("\tattempt to activate destroyed window!\n");
109 if( lpPos )
111 if( IsWindow(lpPos->hwndIconTitle) )
112 DestroyWindow( lpPos->hwndIconTitle );
113 HeapFree( SystemHeap, 0, lpPos );
116 QUEUE_Unlock( pMsgQ );
117 return;
120 /***********************************************************************
121 * WINPOS_FindIconPos
123 * Find a suitable place for an iconic window.
125 static POINT16 WINPOS_FindIconPos( WND* wndPtr, POINT16 pt )
127 RECT16 rectParent;
128 short x, y, xspacing, yspacing;
130 GetClientRect16( wndPtr->parent->hwndSelf, &rectParent );
131 if ((pt.x >= rectParent.left) && (pt.x + GetSystemMetrics(SM_CXICON) < rectParent.right) &&
132 (pt.y >= rectParent.top) && (pt.y + GetSystemMetrics(SM_CYICON) < rectParent.bottom))
133 return pt; /* The icon already has a suitable position */
135 xspacing = GetSystemMetrics(SM_CXICONSPACING);
136 yspacing = GetSystemMetrics(SM_CYICONSPACING);
138 y = rectParent.bottom;
139 for (;;)
141 x = rectParent.left;
144 /* Check if another icon already occupies this spot */
145 WND *childPtr = WIN_LockWndPtr(wndPtr->parent->child);
146 while (childPtr)
148 if ((childPtr->dwStyle & WS_MINIMIZE) && (childPtr != wndPtr))
150 if ((childPtr->rectWindow.left < x + xspacing) &&
151 (childPtr->rectWindow.right >= x) &&
152 (childPtr->rectWindow.top <= y) &&
153 (childPtr->rectWindow.bottom > y - yspacing))
154 break; /* There's a window in there */
156 WIN_UpdateWndPtr(&childPtr,childPtr->next);
158 WIN_ReleaseWndPtr(childPtr);
159 if (!childPtr) /* No window was found, so it's OK for us */
161 pt.x = x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2;
162 pt.y = y - (yspacing + GetSystemMetrics(SM_CYICON)) / 2;
163 return pt;
165 x += xspacing;
166 } while(x <= rectParent.right-xspacing);
167 y -= yspacing;
172 /***********************************************************************
173 * ArrangeIconicWindows16 (USER.170)
175 UINT16 WINAPI ArrangeIconicWindows16( HWND16 parent)
177 return ArrangeIconicWindows(parent);
179 /***********************************************************************
180 * ArrangeIconicWindows (USER32.7)
182 UINT WINAPI ArrangeIconicWindows( HWND parent )
184 RECT rectParent;
185 HWND hwndChild;
186 INT x, y, xspacing, yspacing;
188 GetClientRect( parent, &rectParent );
189 x = rectParent.left;
190 y = rectParent.bottom;
191 xspacing = GetSystemMetrics(SM_CXICONSPACING);
192 yspacing = GetSystemMetrics(SM_CYICONSPACING);
194 hwndChild = GetWindow( parent, GW_CHILD );
195 while (hwndChild)
197 if( IsIconic( hwndChild ) )
199 WND *wndPtr = WIN_FindWndPtr(hwndChild);
201 WINPOS_ShowIconTitle( wndPtr, FALSE );
203 SetWindowPos( hwndChild, 0, x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2,
204 y - yspacing - GetSystemMetrics(SM_CYICON)/2, 0, 0,
205 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
206 if( IsWindow(hwndChild) )
207 WINPOS_ShowIconTitle(wndPtr , TRUE );
208 WIN_ReleaseWndPtr(wndPtr);
210 if (x <= rectParent.right - xspacing) x += xspacing;
211 else
213 x = rectParent.left;
214 y -= yspacing;
217 hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
219 return yspacing;
223 /***********************************************************************
224 * SwitchToThisWindow16 (USER.172)
226 void WINAPI SwitchToThisWindow16( HWND16 hwnd, BOOL16 restore )
228 SwitchToThisWindow( hwnd, restore );
232 /***********************************************************************
233 * SwitchToThisWindow (USER32.539)
235 void WINAPI SwitchToThisWindow( HWND hwnd, BOOL restore )
237 ShowWindow( hwnd, restore ? SW_RESTORE : SW_SHOWMINIMIZED );
241 /***********************************************************************
242 * GetWindowRect16 (USER.32)
244 void WINAPI GetWindowRect16( HWND16 hwnd, LPRECT16 rect )
246 WND * wndPtr = WIN_FindWndPtr( hwnd );
247 if (!wndPtr) return;
249 CONV_RECT32TO16( &wndPtr->rectWindow, rect );
250 if (wndPtr->dwStyle & WS_CHILD)
251 MapWindowPoints16( wndPtr->parent->hwndSelf, 0, (POINT16 *)rect, 2 );
252 WIN_ReleaseWndPtr(wndPtr);
256 /***********************************************************************
257 * GetWindowRect (USER32.308)
259 BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect )
261 WND * wndPtr = WIN_FindWndPtr( hwnd );
262 if (!wndPtr) return FALSE;
264 *rect = wndPtr->rectWindow;
265 if (wndPtr->dwStyle & WS_CHILD)
266 MapWindowPoints( wndPtr->parent->hwndSelf, 0, (POINT *)rect, 2 );
267 WIN_ReleaseWndPtr(wndPtr);
268 return TRUE;
272 /***********************************************************************
273 * GetWindowRgn
275 BOOL WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
278 RECT rect;
279 WND * wndPtr = WIN_FindWndPtr( hwnd );
280 if (!wndPtr) return (ERROR);
282 FIXME("GetWindowRgn: doesn't really do regions\n");
284 memset (&rect, 0, sizeof(rect));
286 GetWindowRect ( hwnd, &rect );
288 FIXME("Check whether a valid region here\n");
290 SetRectRgn ( hrgn, rect.left, rect.top, rect.right, rect.bottom );
292 WIN_ReleaseWndPtr(wndPtr);
293 return (SIMPLEREGION);
296 /***********************************************************************
297 * SetWindowRgn
299 INT WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn,BOOL bRedraw)
303 FIXME("SetWindowRgn: stub\n");
304 return TRUE;
307 /***********************************************************************
308 * SetWindowRgn16
310 INT16 WINAPI SetWindowRgn16( HWND16 hwnd, HRGN16 hrgn,BOOL16 bRedraw)
314 FIXME("SetWindowRgn16: stub\n");
315 return TRUE;
319 /***********************************************************************
320 * GetClientRect16 (USER.33)
322 void WINAPI GetClientRect16( HWND16 hwnd, LPRECT16 rect )
324 WND * wndPtr = WIN_FindWndPtr( hwnd );
326 rect->left = rect->top = rect->right = rect->bottom = 0;
327 if (wndPtr)
329 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
330 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
332 WIN_ReleaseWndPtr(wndPtr);
336 /***********************************************************************
337 * GetClientRect (USER.220)
339 BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect )
341 WND * wndPtr = WIN_FindWndPtr( hwnd );
343 rect->left = rect->top = rect->right = rect->bottom = 0;
344 if (!wndPtr) return FALSE;
345 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
346 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
348 WIN_ReleaseWndPtr(wndPtr);
349 return TRUE;
353 /*******************************************************************
354 * ClientToScreen16 (USER.28)
356 void WINAPI ClientToScreen16( HWND16 hwnd, LPPOINT16 lppnt )
358 MapWindowPoints16( hwnd, 0, lppnt, 1 );
362 /*******************************************************************
363 * ClientToScreen (USER32.52)
365 BOOL WINAPI ClientToScreen( HWND hwnd, LPPOINT lppnt )
367 MapWindowPoints( hwnd, 0, lppnt, 1 );
368 return TRUE;
372 /*******************************************************************
373 * ScreenToClient16 (USER.29)
375 void WINAPI ScreenToClient16( HWND16 hwnd, LPPOINT16 lppnt )
377 MapWindowPoints16( 0, hwnd, lppnt, 1 );
381 /*******************************************************************
382 * ScreenToClient (USER32.447)
384 BOOL WINAPI ScreenToClient( HWND hwnd, LPPOINT lppnt )
386 MapWindowPoints( 0, hwnd, lppnt, 1 );
387 return TRUE;
391 /***********************************************************************
392 * WINPOS_WindowFromPoint
394 * Find the window and hittest for a given point.
396 INT16 WINPOS_WindowFromPoint( WND* wndScope, POINT16 pt, WND **ppWnd )
398 WND *wndPtr;
399 INT16 hittest = HTERROR;
400 INT16 retvalue;
401 POINT16 xy = pt;
403 *ppWnd = NULL;
404 wndPtr = WIN_LockWndPtr(wndScope->child);
406 if( wndScope->flags & WIN_MANAGED )
408 /* In managed mode we have to check wndScope first as it is also
409 * a window which received the mouse event. */
411 if( wndScope->dwStyle & WS_DISABLED )
413 retvalue = HTERROR;
414 goto end;
416 if( pt.x < wndScope->rectClient.left || pt.x >= wndScope->rectClient.right ||
417 pt.y < wndScope->rectClient.top || pt.y >= wndScope->rectClient.bottom )
418 goto hittest;
420 MapWindowPoints16( GetDesktopWindow16(), wndScope->hwndSelf, &xy, 1 );
422 for (;;)
424 while (wndPtr)
426 /* If point is in window, and window is visible, and it */
427 /* is enabled (or it's a top-level window), then explore */
428 /* its children. Otherwise, go to the next window. */
430 if ((wndPtr->dwStyle & WS_VISIBLE) &&
431 (!(wndPtr->dwStyle & WS_DISABLED) ||
432 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)) &&
433 (xy.x >= wndPtr->rectWindow.left) &&
434 (xy.x < wndPtr->rectWindow.right) &&
435 (xy.y >= wndPtr->rectWindow.top) &&
436 (xy.y < wndPtr->rectWindow.bottom))
438 *ppWnd = wndPtr; /* Got a suitable window */
440 /* If window is minimized or disabled, return at once */
441 if (wndPtr->dwStyle & WS_MINIMIZE)
443 retvalue = HTCAPTION;
444 goto end;
446 if (wndPtr->dwStyle & WS_DISABLED)
448 retvalue = HTERROR;
449 goto end;
452 /* If point is not in client area, ignore the children */
453 if ((xy.x < wndPtr->rectClient.left) ||
454 (xy.x >= wndPtr->rectClient.right) ||
455 (xy.y < wndPtr->rectClient.top) ||
456 (xy.y >= wndPtr->rectClient.bottom)) break;
458 xy.x -= wndPtr->rectClient.left;
459 xy.y -= wndPtr->rectClient.top;
460 WIN_UpdateWndPtr(&wndPtr,wndPtr->child);
462 else
464 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
468 hittest:
469 /* If nothing found, try the scope window */
470 if (!*ppWnd) *ppWnd = wndScope;
472 /* Send the WM_NCHITTEST message (only if to the same task) */
473 if ((*ppWnd)->hmemTaskQ == GetFastQueue16())
475 hittest = (INT16)SendMessage16( (*ppWnd)->hwndSelf, WM_NCHITTEST,
476 0, MAKELONG( pt.x, pt.y ) );
477 if (hittest != HTTRANSPARENT)
479 retvalue = hittest; /* Found the window */
480 goto end;
483 else
485 retvalue = HTCLIENT;
486 goto end;
489 /* If no children found in last search, make point relative to parent */
490 if (!wndPtr)
492 xy.x += (*ppWnd)->rectClient.left;
493 xy.y += (*ppWnd)->rectClient.top;
496 /* Restart the search from the next sibling */
497 WIN_UpdateWndPtr(&wndPtr,(*ppWnd)->next);
498 *ppWnd = (*ppWnd)->parent;
501 end:
502 WIN_ReleaseWndPtr(wndPtr);
503 return retvalue;
507 /*******************************************************************
508 * WindowFromPoint16 (USER.30)
510 HWND16 WINAPI WindowFromPoint16( POINT16 pt )
512 WND *pWnd;
513 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt, &pWnd );
514 WIN_ReleaseDesktop();
515 return pWnd->hwndSelf;
519 /*******************************************************************
520 * WindowFromPoint (USER32.582)
522 HWND WINAPI WindowFromPoint( POINT pt )
524 WND *pWnd;
525 POINT16 pt16;
526 CONV_POINT32TO16( &pt, &pt16 );
527 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16, &pWnd );
528 WIN_ReleaseDesktop();
529 return (HWND)pWnd->hwndSelf;
533 /*******************************************************************
534 * ChildWindowFromPoint16 (USER.191)
536 HWND16 WINAPI ChildWindowFromPoint16( HWND16 hwndParent, POINT16 pt )
538 POINT pt32;
539 CONV_POINT16TO32( &pt, &pt32 );
540 return (HWND16)ChildWindowFromPoint( hwndParent, pt32 );
544 /*******************************************************************
545 * ChildWindowFromPoint (USER32.49)
547 HWND WINAPI ChildWindowFromPoint( HWND hwndParent, POINT pt )
549 /* pt is in the client coordinates */
551 WND* wnd = WIN_FindWndPtr(hwndParent);
552 RECT rect;
553 HWND retvalue;
555 if( !wnd ) return 0;
557 /* get client rect fast */
558 rect.top = rect.left = 0;
559 rect.right = wnd->rectClient.right - wnd->rectClient.left;
560 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
562 if (!PtInRect( &rect, pt ))
564 retvalue = 0;
565 goto end;
567 WIN_UpdateWndPtr(&wnd,wnd->child);
568 while ( wnd )
570 if (PtInRect( &wnd->rectWindow, pt ))
572 retvalue = wnd->hwndSelf;
573 goto end;
575 WIN_UpdateWndPtr(&wnd,wnd->next);
577 retvalue = hwndParent;
578 end:
579 WIN_ReleaseWndPtr(wnd);
580 return retvalue;
583 /*******************************************************************
584 * ChildWindowFromPointEx16 (USER.50)
586 HWND16 WINAPI ChildWindowFromPointEx16( HWND16 hwndParent, POINT16 pt, UINT16 uFlags)
588 POINT pt32;
589 CONV_POINT16TO32( &pt, &pt32 );
590 return (HWND16)ChildWindowFromPointEx( hwndParent, pt32, uFlags );
594 /*******************************************************************
595 * ChildWindowFromPointEx (USER32.50)
597 HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt,
598 UINT uFlags)
600 /* pt is in the client coordinates */
602 WND* wnd = WIN_FindWndPtr(hwndParent);
603 RECT rect;
604 HWND retvalue;
606 if( !wnd ) return 0;
608 /* get client rect fast */
609 rect.top = rect.left = 0;
610 rect.right = wnd->rectClient.right - wnd->rectClient.left;
611 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
613 if (!PtInRect( &rect, pt ))
615 retvalue = 0;
616 goto end;
618 WIN_UpdateWndPtr(&wnd,wnd->child);
620 while ( wnd )
622 if (PtInRect( &wnd->rectWindow, pt )) {
623 if ( (uFlags & CWP_SKIPINVISIBLE) &&
624 !(wnd->dwStyle & WS_VISIBLE) );
625 else if ( (uFlags & CWP_SKIPDISABLED) &&
626 (wnd->dwStyle & WS_DISABLED) );
627 else if ( (uFlags & CWP_SKIPTRANSPARENT) &&
628 (wnd->dwExStyle & WS_EX_TRANSPARENT) );
629 else
631 retvalue = wnd->hwndSelf;
632 goto end;
636 WIN_UpdateWndPtr(&wnd,wnd->next);
638 retvalue = hwndParent;
639 end:
640 WIN_ReleaseWndPtr(wnd);
641 return retvalue;
645 /*******************************************************************
646 * WINPOS_GetWinOffset
648 * Calculate the offset between the origin of the two windows. Used
649 * to implement MapWindowPoints.
651 static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo,
652 POINT *offset )
654 WND * wndPtr = 0;
656 offset->x = offset->y = 0;
657 if (hwndFrom == hwndTo ) return;
659 /* Translate source window origin to screen coords */
660 if (hwndFrom)
662 if (!(wndPtr = WIN_FindWndPtr( hwndFrom )))
664 ERR("bad hwndFrom = %04x\n",hwndFrom);
665 return;
667 while (wndPtr->parent)
669 offset->x += wndPtr->rectClient.left;
670 offset->y += wndPtr->rectClient.top;
671 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
673 WIN_ReleaseWndPtr(wndPtr);
676 /* Translate origin to destination window coords */
677 if (hwndTo)
679 if (!(wndPtr = WIN_FindWndPtr( hwndTo )))
681 ERR("bad hwndTo = %04x\n", hwndTo );
682 return;
684 while (wndPtr->parent)
686 offset->x -= wndPtr->rectClient.left;
687 offset->y -= wndPtr->rectClient.top;
688 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
690 WIN_ReleaseWndPtr(wndPtr);
695 /*******************************************************************
696 * MapWindowPoints16 (USER.258)
698 void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
699 LPPOINT16 lppt, UINT16 count )
701 POINT offset;
703 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
704 while (count--)
706 lppt->x += offset.x;
707 lppt->y += offset.y;
708 lppt++;
713 /*******************************************************************
714 * MapWindowPoints (USER32.386)
716 INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo,
717 LPPOINT lppt, UINT count )
719 POINT offset;
721 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
722 while (count--)
724 lppt->x += offset.x;
725 lppt->y += offset.y;
726 lppt++;
728 return MAKELONG( LOWORD(offset.x), LOWORD(offset.y) );
732 /***********************************************************************
733 * IsIconic16 (USER.31)
735 BOOL16 WINAPI IsIconic16(HWND16 hWnd)
737 return IsIconic(hWnd);
741 /***********************************************************************
742 * IsIconic (USER32.345)
744 BOOL WINAPI IsIconic(HWND hWnd)
746 BOOL retvalue;
747 WND * wndPtr = WIN_FindWndPtr(hWnd);
748 if (wndPtr == NULL) return FALSE;
749 retvalue = (wndPtr->dwStyle & WS_MINIMIZE) != 0;
750 WIN_ReleaseWndPtr(wndPtr);
751 return retvalue;
755 /***********************************************************************
756 * IsZoomed (USER.272)
758 BOOL16 WINAPI IsZoomed16(HWND16 hWnd)
760 return IsZoomed(hWnd);
764 /***********************************************************************
765 * IsZoomed (USER.352)
767 BOOL WINAPI IsZoomed(HWND hWnd)
769 BOOL retvalue;
770 WND * wndPtr = WIN_FindWndPtr(hWnd);
771 if (wndPtr == NULL) return FALSE;
772 retvalue = (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
773 WIN_ReleaseWndPtr(wndPtr);
774 return retvalue;
778 /*******************************************************************
779 * GetActiveWindow (USER.60)
781 HWND16 WINAPI GetActiveWindow16(void)
783 return (HWND16)GetActiveWindow();
786 /*******************************************************************
787 * GetActiveWindow (USER32.205)
789 HWND WINAPI GetActiveWindow(void)
791 MESSAGEQUEUE *pCurMsgQ = 0;
792 HWND hwndActive = 0;
794 /* Get the messageQ for the current thread */
795 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
797 WARN("\tCurrent message queue not found. Exiting!\n" );
798 return 0;
801 /* Return the current active window from the perQ data of the current message Q */
802 hwndActive = PERQDATA_GetActiveWnd( pCurMsgQ->pQData );
804 QUEUE_Unlock( pCurMsgQ );
805 return hwndActive;
809 /*******************************************************************
810 * WINPOS_CanActivate
812 static BOOL WINPOS_CanActivate(WND* pWnd)
814 if( pWnd && ( (pWnd->dwStyle & (WS_DISABLED | WS_VISIBLE | WS_CHILD))
815 == WS_VISIBLE ) ) return TRUE;
816 return FALSE;
820 /*******************************************************************
821 * SetActiveWindow16 (USER.59)
823 HWND16 WINAPI SetActiveWindow16( HWND16 hwnd )
825 return SetActiveWindow(hwnd);
829 /*******************************************************************
830 * SetActiveWindow (USER32.463)
832 HWND WINAPI SetActiveWindow( HWND hwnd )
834 HWND prev = 0;
835 WND *wndPtr = WIN_FindWndPtr( hwnd );
836 MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
838 if (!wndPtr || (wndPtr->dwStyle & (WS_DISABLED | WS_CHILD)))
840 prev = 0;
841 goto end;
844 /* Get the messageQ for the current thread */
845 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
847 WARN("\tCurrent message queue not found. Exiting!\n" );
848 goto CLEANUP;
851 /* Retrieve the message queue associated with this window */
852 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
853 if ( !pMsgQ )
855 WARN("\tWindow message queue not found. Exiting!\n" );
856 goto CLEANUP;
859 /* Make sure that the window is associated with the calling threads
860 * message queue. It must share the same perQ data.
863 if ( pCurMsgQ->pQData != pMsgQ->pQData )
864 goto CLEANUP;
866 /* Save current active window */
867 prev = PERQDATA_GetActiveWnd( pMsgQ->pQData );
869 WINPOS_SetActiveWindow( hwnd, 0, 0 );
871 CLEANUP:
872 /* Unlock the queues before returning */
873 if ( pMsgQ )
874 QUEUE_Unlock( pMsgQ );
875 if ( pCurMsgQ )
876 QUEUE_Unlock( pCurMsgQ );
878 end:
879 WIN_ReleaseWndPtr(wndPtr);
880 return prev;
884 /*******************************************************************
885 * GetForegroundWindow16 (USER.608)
887 HWND16 WINAPI GetForegroundWindow16(void)
889 return (HWND16)GetForegroundWindow();
893 /*******************************************************************
894 * SetForegroundWindow16 (USER.609)
896 BOOL16 WINAPI SetForegroundWindow16( HWND16 hwnd )
898 return SetForegroundWindow( hwnd );
902 /*******************************************************************
903 * GetForegroundWindow (USER32.241)
905 HWND WINAPI GetForegroundWindow(void)
907 HWND hwndActive = 0;
909 /* Get the foreground window (active window of hActiveQueue) */
910 if ( hActiveQueue )
912 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
913 if ( pActiveQueue )
914 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
916 QUEUE_Unlock( pActiveQueue );
919 return hwndActive;
922 /*******************************************************************
923 * SetForegroundWindow (USER32.482)
925 BOOL WINAPI SetForegroundWindow( HWND hwnd )
927 return WINPOS_ChangeActiveWindow( hwnd, FALSE );
931 /*******************************************************************
932 * GetShellWindow16 (USER.600)
934 HWND16 WINAPI GetShellWindow16(void)
936 return GetShellWindow();
939 /*******************************************************************
940 * SetShellWindow (USER32.504)
942 HWND WINAPI SetShellWindow(HWND hwndshell)
943 { WARN("(hWnd=%08x) semi stub\n",hwndshell );
945 hGlobalShellWindow = hwndshell;
946 return hGlobalShellWindow;
950 /*******************************************************************
951 * GetShellWindow (USER32.287)
953 HWND WINAPI GetShellWindow(void)
954 { WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow );
956 return hGlobalShellWindow;
960 /***********************************************************************
961 * BringWindowToTop16 (USER.45)
963 BOOL16 WINAPI BringWindowToTop16( HWND16 hwnd )
965 return BringWindowToTop(hwnd);
969 /***********************************************************************
970 * BringWindowToTop (USER32.11)
972 BOOL WINAPI BringWindowToTop( HWND hwnd )
974 return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
978 /***********************************************************************
979 * MoveWindow16 (USER.56)
981 BOOL16 WINAPI MoveWindow16( HWND16 hwnd, INT16 x, INT16 y, INT16 cx, INT16 cy,
982 BOOL16 repaint )
984 return MoveWindow(hwnd,x,y,cx,cy,repaint);
988 /***********************************************************************
989 * MoveWindow (USER32.399)
991 BOOL WINAPI MoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy,
992 BOOL repaint )
994 int flags = SWP_NOZORDER | SWP_NOACTIVATE;
995 if (!repaint) flags |= SWP_NOREDRAW;
996 TRACE("%04x %d,%d %dx%d %d\n",
997 hwnd, x, y, cx, cy, repaint );
998 return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
1001 /***********************************************************************
1002 * WINPOS_InitInternalPos
1004 static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT pt,
1005 LPRECT restoreRect )
1007 LPINTERNALPOS lpPos = (LPINTERNALPOS) GetPropA( wnd->hwndSelf,
1008 atomInternalPos );
1009 if( !lpPos )
1011 /* this happens when the window is minimized/maximized
1012 * for the first time (rectWindow is not adjusted yet) */
1014 lpPos = HeapAlloc( SystemHeap, 0, sizeof(INTERNALPOS) );
1015 if( !lpPos ) return NULL;
1017 SetPropA( wnd->hwndSelf, atomInternalPos, (HANDLE)lpPos );
1018 lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
1019 CONV_RECT32TO16( &wnd->rectWindow, &lpPos->rectNormal );
1020 *(UINT*)&lpPos->ptIconPos = *(UINT*)&lpPos->ptMaxPos = 0xFFFFFFFF;
1023 if( wnd->dwStyle & WS_MINIMIZE )
1024 CONV_POINT32TO16( &pt, &lpPos->ptIconPos );
1025 else if( wnd->dwStyle & WS_MAXIMIZE )
1026 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1027 else if( restoreRect )
1028 CONV_RECT32TO16( restoreRect, &lpPos->rectNormal );
1030 return lpPos;
1033 /***********************************************************************
1034 * WINPOS_RedrawIconTitle
1036 BOOL WINPOS_RedrawIconTitle( HWND hWnd )
1038 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hWnd, atomInternalPos );
1039 if( lpPos )
1041 if( lpPos->hwndIconTitle )
1043 SendMessageA( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
1044 InvalidateRect( lpPos->hwndIconTitle, NULL, TRUE );
1045 return TRUE;
1048 return FALSE;
1051 /***********************************************************************
1052 * WINPOS_ShowIconTitle
1054 BOOL WINPOS_ShowIconTitle( WND* pWnd, BOOL bShow )
1056 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( pWnd->hwndSelf, atomInternalPos );
1058 if( lpPos && !(pWnd->flags & WIN_MANAGED))
1060 HWND16 hWnd = lpPos->hwndIconTitle;
1062 TRACE("0x%04x %i\n", pWnd->hwndSelf, (bShow != 0) );
1064 if( !hWnd )
1065 lpPos->hwndIconTitle = hWnd = ICONTITLE_Create( pWnd );
1066 if( bShow )
1068 if( ( pWnd = WIN_FindWndPtr(hWnd) ) != NULL)
1070 if( !(pWnd->dwStyle & WS_VISIBLE) )
1072 SendMessageA( hWnd, WM_SHOWWINDOW, TRUE, 0 );
1073 SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
1074 SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
1076 WIN_ReleaseWndPtr(pWnd);
1079 else ShowWindow( hWnd, SW_HIDE );
1081 return FALSE;
1084 /*******************************************************************
1085 * WINPOS_GetMinMaxInfo
1087 * Get the minimized and maximized information for a window.
1089 void WINPOS_GetMinMaxInfo( WND *wndPtr, POINT *maxSize, POINT *maxPos,
1090 POINT *minTrack, POINT *maxTrack )
1092 LPINTERNALPOS lpPos;
1093 MINMAXINFO MinMax;
1094 INT xinc, yinc;
1096 /* Compute default values */
1098 MinMax.ptMaxSize.x = GetSystemMetrics(SM_CXSCREEN);
1099 MinMax.ptMaxSize.y = GetSystemMetrics(SM_CYSCREEN);
1100 MinMax.ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
1101 MinMax.ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
1102 MinMax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXSCREEN);
1103 MinMax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYSCREEN);
1105 if (wndPtr->flags & WIN_MANAGED) xinc = yinc = 0;
1106 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1108 xinc = GetSystemMetrics(SM_CXDLGFRAME);
1109 yinc = GetSystemMetrics(SM_CYDLGFRAME);
1111 else
1113 xinc = yinc = 0;
1114 if (HAS_THICKFRAME(wndPtr->dwStyle))
1116 xinc += GetSystemMetrics(SM_CXFRAME);
1117 yinc += GetSystemMetrics(SM_CYFRAME);
1119 if (wndPtr->dwStyle & WS_BORDER)
1121 xinc += GetSystemMetrics(SM_CXBORDER);
1122 yinc += GetSystemMetrics(SM_CYBORDER);
1125 MinMax.ptMaxSize.x += 2 * xinc;
1126 MinMax.ptMaxSize.y += 2 * yinc;
1128 lpPos = (LPINTERNALPOS)GetPropA( wndPtr->hwndSelf, atomInternalPos );
1129 if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
1130 CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
1131 else
1133 MinMax.ptMaxPosition.x = -xinc;
1134 MinMax.ptMaxPosition.y = -yinc;
1137 SendMessageA( wndPtr->hwndSelf, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
1139 /* Some sanity checks */
1141 TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1142 MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
1143 MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
1144 MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
1145 MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
1146 MinMax.ptMaxTrackSize.x = max( MinMax.ptMaxTrackSize.x,
1147 MinMax.ptMinTrackSize.x );
1148 MinMax.ptMaxTrackSize.y = max( MinMax.ptMaxTrackSize.y,
1149 MinMax.ptMinTrackSize.y );
1151 if (maxSize) *maxSize = MinMax.ptMaxSize;
1152 if (maxPos) *maxPos = MinMax.ptMaxPosition;
1153 if (minTrack) *minTrack = MinMax.ptMinTrackSize;
1154 if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
1157 /***********************************************************************
1158 * WINPOS_MinMaximize
1160 * Fill in lpRect and return additional flags to be used with SetWindowPos().
1161 * This function assumes that 'cmd' is different from the current window
1162 * state.
1164 UINT WINPOS_MinMaximize( WND* wndPtr, UINT16 cmd, LPRECT16 lpRect )
1166 UINT swpFlags = 0;
1167 POINT pt, size;
1168 LPINTERNALPOS lpPos;
1170 TRACE("0x%04x %u\n", wndPtr->hwndSelf, cmd );
1172 size.x = wndPtr->rectWindow.left; size.y = wndPtr->rectWindow.top;
1173 lpPos = WINPOS_InitInternalPos( wndPtr, size, &wndPtr->rectWindow );
1175 if (lpPos && !HOOK_CallHooks16(WH_CBT, HCBT_MINMAX, wndPtr->hwndSelf, cmd))
1177 if( wndPtr->dwStyle & WS_MINIMIZE )
1179 if( !SendMessageA( wndPtr->hwndSelf, WM_QUERYOPEN, 0, 0L ) )
1180 return (SWP_NOSIZE | SWP_NOMOVE);
1181 swpFlags |= SWP_NOCOPYBITS;
1183 switch( cmd )
1185 case SW_MINIMIZE:
1186 if( wndPtr->dwStyle & WS_MAXIMIZE)
1188 wndPtr->flags |= WIN_RESTORE_MAX;
1189 wndPtr->dwStyle &= ~WS_MAXIMIZE;
1191 else
1192 wndPtr->flags &= ~WIN_RESTORE_MAX;
1193 wndPtr->dwStyle |= WS_MINIMIZE;
1195 if( wndPtr->flags & WIN_NATIVE )
1196 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, TRUE ) )
1197 swpFlags |= MINMAX_NOSWP;
1199 lpPos->ptIconPos = WINPOS_FindIconPos( wndPtr, lpPos->ptIconPos );
1201 SetRect16( lpRect, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1202 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON) );
1203 swpFlags |= SWP_NOCOPYBITS;
1204 break;
1206 case SW_MAXIMIZE:
1207 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1208 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL );
1209 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1211 if( wndPtr->dwStyle & WS_MINIMIZE )
1213 if( wndPtr->flags & WIN_NATIVE )
1214 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
1215 swpFlags |= MINMAX_NOSWP;
1217 WINPOS_ShowIconTitle( wndPtr, FALSE );
1218 wndPtr->dwStyle &= ~WS_MINIMIZE;
1220 wndPtr->dwStyle |= WS_MAXIMIZE;
1222 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1223 size.x, size.y );
1224 break;
1226 case SW_RESTORE:
1227 if( wndPtr->dwStyle & WS_MINIMIZE )
1229 if( wndPtr->flags & WIN_NATIVE )
1230 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
1231 swpFlags |= MINMAX_NOSWP;
1233 wndPtr->dwStyle &= ~WS_MINIMIZE;
1234 WINPOS_ShowIconTitle( wndPtr, FALSE );
1236 if( wndPtr->flags & WIN_RESTORE_MAX)
1238 /* Restore to maximized position */
1239 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1240 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL);
1241 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1242 wndPtr->dwStyle |= WS_MAXIMIZE;
1243 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y, size.x, size.y );
1244 break;
1247 else
1248 if( !(wndPtr->dwStyle & WS_MAXIMIZE) ) return (UINT16)(-1);
1249 else wndPtr->dwStyle &= ~WS_MAXIMIZE;
1251 /* Restore to normal position */
1253 *lpRect = lpPos->rectNormal;
1254 lpRect->right -= lpRect->left;
1255 lpRect->bottom -= lpRect->top;
1257 break;
1259 } else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
1260 return swpFlags;
1263 /***********************************************************************
1264 * ShowWindowAsync (USER32.535)
1266 * doesn't wait; returns immediately.
1267 * used by threads to toggle windows in other (possibly hanging) threads
1269 BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd )
1271 /* FIXME: does ShowWindow() return immediately ? */
1272 return ShowWindow(hwnd, cmd);
1276 /***********************************************************************
1277 * ShowWindow16 (USER.42)
1279 BOOL16 WINAPI ShowWindow16( HWND16 hwnd, INT16 cmd )
1281 return ShowWindow(hwnd,cmd);
1285 /***********************************************************************
1286 * ShowWindow (USER32.534)
1288 BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
1290 WND* wndPtr = WIN_FindWndPtr( hwnd );
1291 BOOL wasVisible, showFlag;
1292 RECT16 newPos = {0, 0, 0, 0};
1293 UINT swp = 0;
1295 if (!wndPtr) return FALSE;
1297 TRACE("hwnd=%04x, cmd=%d\n", hwnd, cmd);
1299 wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
1301 switch(cmd)
1303 case SW_HIDE:
1304 if (!wasVisible) goto END;;
1305 swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
1306 SWP_NOACTIVATE | SWP_NOZORDER;
1307 break;
1309 case SW_SHOWMINNOACTIVE:
1310 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1311 /* fall through */
1312 case SW_SHOWMINIMIZED:
1313 swp |= SWP_SHOWWINDOW;
1314 /* fall through */
1315 case SW_MINIMIZE:
1316 swp |= SWP_FRAMECHANGED;
1317 if( !(wndPtr->dwStyle & WS_MINIMIZE) )
1318 swp |= WINPOS_MinMaximize( wndPtr, SW_MINIMIZE, &newPos );
1319 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1320 break;
1322 case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
1323 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1324 if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
1325 swp |= WINPOS_MinMaximize( wndPtr, SW_MAXIMIZE, &newPos );
1326 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1327 break;
1329 case SW_SHOWNA:
1330 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1331 /* fall through */
1332 case SW_SHOW:
1333 swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
1336 * ShowWindow has a little peculiar behavior that if the
1337 * window is already the topmost window, it will not
1338 * activate it.
1340 if (GetTopWindow((HWND)0)==hwnd && (wasVisible || GetActiveWindow() == hwnd))
1341 swp |= SWP_NOACTIVATE;
1343 break;
1345 case SW_SHOWNOACTIVATE:
1346 swp |= SWP_NOZORDER;
1347 if (GetActiveWindow()) swp |= SWP_NOACTIVATE;
1348 /* fall through */
1349 case SW_SHOWNORMAL: /* same as SW_NORMAL: */
1350 case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
1351 case SW_RESTORE:
1352 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1354 if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) )
1355 swp |= WINPOS_MinMaximize( wndPtr, SW_RESTORE, &newPos );
1356 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1357 break;
1360 showFlag = (cmd != SW_HIDE);
1361 if (showFlag != wasVisible)
1363 SendMessageA( hwnd, WM_SHOWWINDOW, showFlag, 0 );
1364 if (!IsWindow( hwnd )) goto END;
1367 if ((wndPtr->dwStyle & WS_CHILD) &&
1368 !IsWindowVisible( wndPtr->parent->hwndSelf ) &&
1369 (swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE) )
1371 /* Don't call SetWindowPos() on invisible child windows */
1372 if (cmd == SW_HIDE) wndPtr->dwStyle &= ~WS_VISIBLE;
1373 else wndPtr->dwStyle |= WS_VISIBLE;
1375 else
1377 /* We can't activate a child window */
1378 if ((wndPtr->dwStyle & WS_CHILD) &&
1379 !(wndPtr->dwExStyle & WS_EX_MDICHILD))
1380 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1381 if (!(swp & MINMAX_NOSWP))
1383 SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top,
1384 newPos.right, newPos.bottom, LOWORD(swp) );
1385 if (cmd == SW_HIDE)
1387 /* FIXME: This will cause the window to be activated irrespective
1388 * of whether it is owned by the same thread. Has to be done
1389 * asynchronously.
1392 if (hwnd == GetActiveWindow())
1393 WINPOS_ActivateOtherWindow(wndPtr);
1395 /* Revert focus to parent */
1396 if (hwnd == GetFocus() || IsChild(hwnd, GetFocus()))
1397 SetFocus( GetParent(hwnd) );
1400 if (!IsWindow( hwnd )) goto END;
1401 else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( wndPtr, TRUE );
1404 if (wndPtr->flags & WIN_NEED_SIZE)
1406 /* should happen only in CreateWindowEx() */
1407 int wParam = SIZE_RESTORED;
1409 wndPtr->flags &= ~WIN_NEED_SIZE;
1410 if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
1411 else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
1412 SendMessageA( hwnd, WM_SIZE, wParam,
1413 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
1414 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
1415 SendMessageA( hwnd, WM_MOVE, 0,
1416 MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
1419 END:
1420 WIN_ReleaseWndPtr(wndPtr);
1421 return wasVisible;
1425 /***********************************************************************
1426 * GetInternalWindowPos16 (USER.460)
1428 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
1429 LPPOINT16 ptIcon )
1431 WINDOWPLACEMENT16 wndpl;
1432 if (GetWindowPlacement16( hwnd, &wndpl ))
1434 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1435 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1436 return wndpl.showCmd;
1438 return 0;
1442 /***********************************************************************
1443 * GetInternalWindowPos (USER32.245)
1445 UINT WINAPI GetInternalWindowPos( HWND hwnd, LPRECT rectWnd,
1446 LPPOINT ptIcon )
1448 WINDOWPLACEMENT wndpl;
1449 if (GetWindowPlacement( hwnd, &wndpl ))
1451 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1452 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1453 return wndpl.showCmd;
1455 return 0;
1458 /***********************************************************************
1459 * GetWindowPlacement16 (USER.370)
1461 BOOL16 WINAPI GetWindowPlacement16( HWND16 hwnd, WINDOWPLACEMENT16 *wndpl )
1463 WND *pWnd = WIN_FindWndPtr( hwnd );
1464 LPINTERNALPOS lpPos;
1466 if(!pWnd ) return FALSE;
1468 lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1469 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1470 wndpl->length = sizeof(*wndpl);
1471 if( pWnd->dwStyle & WS_MINIMIZE )
1472 wndpl->showCmd = SW_SHOWMINIMIZED;
1473 else
1474 wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE )
1475 ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
1476 if( pWnd->flags & WIN_RESTORE_MAX )
1477 wndpl->flags = WPF_RESTORETOMAXIMIZED;
1478 else
1479 wndpl->flags = 0;
1480 wndpl->ptMinPosition = lpPos->ptIconPos;
1481 wndpl->ptMaxPosition = lpPos->ptMaxPos;
1482 wndpl->rcNormalPosition = lpPos->rectNormal;
1484 WIN_ReleaseWndPtr(pWnd);
1485 return TRUE;
1489 /***********************************************************************
1490 * GetWindowPlacement (USER32.307)
1492 * Win95:
1493 * Fails if wndpl->length of Win95 (!) apps is invalid.
1495 BOOL WINAPI GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *pwpl32 )
1497 if( pwpl32 )
1499 WINDOWPLACEMENT16 wpl;
1500 wpl.length = sizeof(wpl);
1501 if( GetWindowPlacement16( hwnd, &wpl ) )
1503 pwpl32->length = sizeof(*pwpl32);
1504 pwpl32->flags = wpl.flags;
1505 pwpl32->showCmd = wpl.showCmd;
1506 CONV_POINT16TO32( &wpl.ptMinPosition, &pwpl32->ptMinPosition );
1507 CONV_POINT16TO32( &wpl.ptMaxPosition, &pwpl32->ptMaxPosition );
1508 CONV_RECT16TO32( &wpl.rcNormalPosition, &pwpl32->rcNormalPosition );
1509 return TRUE;
1512 return FALSE;
1516 /***********************************************************************
1517 * WINPOS_SetPlacement
1519 static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT16 *wndpl,
1520 UINT flags )
1522 WND *pWnd = WIN_FindWndPtr( hwnd );
1523 if( pWnd )
1525 LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1526 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1528 if( flags & PLACE_MIN ) lpPos->ptIconPos = wndpl->ptMinPosition;
1529 if( flags & PLACE_MAX ) lpPos->ptMaxPos = wndpl->ptMaxPosition;
1530 if( flags & PLACE_RECT) lpPos->rectNormal = wndpl->rcNormalPosition;
1532 if( pWnd->dwStyle & WS_MINIMIZE )
1534 WINPOS_ShowIconTitle( pWnd, FALSE );
1535 if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1536 SetWindowPos( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1537 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1539 else if( pWnd->dwStyle & WS_MAXIMIZE )
1541 if( !EMPTYPOINT(lpPos->ptMaxPos) )
1542 SetWindowPos( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1543 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1545 else if( flags & PLACE_RECT )
1546 SetWindowPos( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1547 lpPos->rectNormal.right - lpPos->rectNormal.left,
1548 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1549 SWP_NOZORDER | SWP_NOACTIVATE );
1551 ShowWindow( hwnd, wndpl->showCmd );
1552 if( IsWindow(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1554 if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd, TRUE );
1556 /* SDK: ...valid only the next time... */
1557 if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1559 WIN_ReleaseWndPtr(pWnd);
1560 return TRUE;
1562 return FALSE;
1566 /***********************************************************************
1567 * SetWindowPlacement16 (USER.371)
1569 BOOL16 WINAPI SetWindowPlacement16(HWND16 hwnd, const WINDOWPLACEMENT16 *wndpl)
1571 return WINPOS_SetPlacement( hwnd, wndpl,
1572 PLACE_MIN | PLACE_MAX | PLACE_RECT );
1575 /***********************************************************************
1576 * SetWindowPlacement (USER32.519)
1578 * Win95:
1579 * Fails if wndpl->length of Win95 (!) apps is invalid.
1581 BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *pwpl32 )
1583 if( pwpl32 )
1585 WINDOWPLACEMENT16 wpl;
1587 wpl.length = sizeof(WINDOWPLACEMENT16);
1588 wpl.flags = pwpl32->flags;
1589 wpl.showCmd = pwpl32->showCmd;
1590 wpl.ptMinPosition.x = pwpl32->ptMinPosition.x;
1591 wpl.ptMinPosition.y = pwpl32->ptMinPosition.y;
1592 wpl.ptMaxPosition.x = pwpl32->ptMaxPosition.x;
1593 wpl.ptMaxPosition.y = pwpl32->ptMaxPosition.y;
1594 wpl.rcNormalPosition.left = pwpl32->rcNormalPosition.left;
1595 wpl.rcNormalPosition.top = pwpl32->rcNormalPosition.top;
1596 wpl.rcNormalPosition.right = pwpl32->rcNormalPosition.right;
1597 wpl.rcNormalPosition.bottom = pwpl32->rcNormalPosition.bottom;
1599 return WINPOS_SetPlacement( hwnd, &wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1601 return FALSE;
1605 /***********************************************************************
1606 * SetInternalWindowPos16 (USER.461)
1608 void WINAPI SetInternalWindowPos16( HWND16 hwnd, UINT16 showCmd,
1609 LPRECT16 rect, LPPOINT16 pt )
1611 if( IsWindow16(hwnd) )
1613 WINDOWPLACEMENT16 wndpl;
1614 UINT flags;
1616 wndpl.length = sizeof(wndpl);
1617 wndpl.showCmd = showCmd;
1618 wndpl.flags = flags = 0;
1620 if( pt )
1622 flags |= PLACE_MIN;
1623 wndpl.flags |= WPF_SETMINPOSITION;
1624 wndpl.ptMinPosition = *pt;
1626 if( rect )
1628 flags |= PLACE_RECT;
1629 wndpl.rcNormalPosition = *rect;
1631 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1636 /***********************************************************************
1637 * SetInternalWindowPos (USER32.483)
1639 void WINAPI SetInternalWindowPos( HWND hwnd, UINT showCmd,
1640 LPRECT rect, LPPOINT pt )
1642 if( IsWindow(hwnd) )
1644 WINDOWPLACEMENT16 wndpl;
1645 UINT flags;
1647 wndpl.length = sizeof(wndpl);
1648 wndpl.showCmd = showCmd;
1649 wndpl.flags = flags = 0;
1651 if( pt )
1653 flags |= PLACE_MIN;
1654 wndpl.flags |= WPF_SETMINPOSITION;
1655 CONV_POINT32TO16( pt, &wndpl.ptMinPosition );
1657 if( rect )
1659 flags |= PLACE_RECT;
1660 CONV_RECT32TO16( rect, &wndpl.rcNormalPosition );
1662 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1666 /*******************************************************************
1667 * WINPOS_SetActiveWindow
1669 * SetActiveWindow() back-end. This is the only function that
1670 * can assign active status to a window. It must be called only
1671 * for the top level windows.
1673 BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
1675 CBTACTIVATESTRUCT16* cbtStruct;
1676 WND* wndPtr=0, *wndTemp;
1677 HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1678 MESSAGEQUEUE *pOldActiveQueue = 0, *pNewActiveQueue = 0;
1679 WORD wIconized = 0;
1680 HWND hwndActive = 0;
1681 BOOL bRet = 0;
1683 TRACE("(%04x, %d, %d)\n", hWnd, fMouse, fChangeFocus );
1685 /* Get current active window from the active queue */
1686 if ( hActiveQueue )
1688 pOldActiveQueue = QUEUE_Lock( hActiveQueue );
1689 if ( pOldActiveQueue )
1690 hwndActive = PERQDATA_GetActiveWnd( pOldActiveQueue->pQData );
1693 /* paranoid checks */
1694 if( hWnd == GetDesktopWindow() || (bRet = (hWnd == hwndActive)) )
1695 goto CLEANUP_END;
1697 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1698 * return 0;
1700 wndPtr = WIN_FindWndPtr(hWnd);
1701 hOldActiveQueue = hActiveQueue;
1703 if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1705 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1706 WIN_ReleaseWndPtr(wndTemp);
1708 else
1709 TRACE("no current active window.\n");
1711 /* call CBT hook chain */
1712 if ((cbtStruct = SEGPTR_NEW(CBTACTIVATESTRUCT16)))
1714 cbtStruct->fMouse = fMouse;
1715 cbtStruct->hWndActive = hwndActive;
1716 bRet = (BOOL)HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
1717 (LPARAM)SEGPTR_GET(cbtStruct) );
1718 SEGPTR_FREE(cbtStruct);
1719 if (bRet) goto CLEANUP_END;
1722 /* set prev active wnd to current active wnd and send notification */
1723 if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
1725 MESSAGEQUEUE *pTempActiveQueue = 0;
1727 if (!SendMessageA( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1729 if (GetSysModalWindow16() != hWnd)
1730 goto CLEANUP_END;
1731 /* disregard refusal if hWnd is sysmodal */
1734 SendMessageA( hwndPrevActive, WM_ACTIVATE,
1735 MAKEWPARAM( WA_INACTIVE, wIconized ),
1736 (LPARAM)hWnd );
1738 /* check if something happened during message processing
1739 * (global active queue may have changed)
1741 pTempActiveQueue = QUEUE_Lock( hActiveQueue );
1742 if(!pTempActiveQueue)
1743 goto CLEANUP_END;
1745 hwndActive = PERQDATA_GetActiveWnd( pTempActiveQueue->pQData );
1746 QUEUE_Unlock( pTempActiveQueue );
1747 if( hwndPrevActive != hwndActive )
1748 goto CLEANUP_END;
1751 /* Set new active window in the message queue */
1752 hwndActive = hWnd;
1753 if ( wndPtr )
1755 pNewActiveQueue = QUEUE_Lock( wndPtr->hmemTaskQ );
1756 if ( pNewActiveQueue )
1757 PERQDATA_SetActiveWnd( pNewActiveQueue->pQData, hwndActive );
1759 else /* have to do this or MDI frame activation goes to hell */
1760 if( pOldActiveQueue )
1761 PERQDATA_SetActiveWnd( pOldActiveQueue->pQData, 0 );
1763 /* send palette messages */
1764 if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1765 SendMessage16((HWND16)-1, WM_PALETTEISCHANGING, (WPARAM16)hWnd, 0L );
1767 /* if prev wnd is minimized redraw icon title */
1768 if( IsIconic( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1770 /* managed windows will get ConfigureNotify event */
1771 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->flags & WIN_MANAGED))
1773 /* check Z-order and bring hWnd to the top */
1774 for (wndTemp = WIN_LockWndPtr(WIN_GetDesktop()->child); wndTemp; WIN_UpdateWndPtr(&wndTemp,wndTemp->next))
1776 if (wndTemp->dwStyle & WS_VISIBLE) break;
1778 WIN_ReleaseDesktop();
1779 WIN_ReleaseWndPtr(wndTemp);
1781 if( wndTemp != wndPtr )
1782 SetWindowPos(hWnd, HWND_TOP, 0,0,0,0,
1783 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1784 if (!IsWindow(hWnd))
1785 goto CLEANUP;
1788 /* Get a handle to the new active queue */
1789 hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1791 /* send WM_ACTIVATEAPP if necessary */
1792 if (hOldActiveQueue != hNewActiveQueue)
1794 WND **list, **ppWnd;
1795 WND *pDesktop = WIN_GetDesktop();
1797 if ((list = WIN_BuildWinArray( pDesktop, 0, NULL )))
1799 for (ppWnd = list; *ppWnd; ppWnd++)
1801 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1803 if ((*ppWnd)->hmemTaskQ == hOldActiveQueue)
1804 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1805 0, QUEUE_GetQueueTask(hNewActiveQueue) );
1807 WIN_ReleaseWinArray(list);
1810 hActiveQueue = hNewActiveQueue;
1812 if ((list = WIN_BuildWinArray(pDesktop, 0, NULL )))
1814 for (ppWnd = list; *ppWnd; ppWnd++)
1816 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1818 if ((*ppWnd)->hmemTaskQ == hNewActiveQueue)
1819 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1820 1, QUEUE_GetQueueTask( hOldActiveQueue ) );
1822 WIN_ReleaseWinArray(list);
1824 WIN_ReleaseDesktop();
1826 if (hWnd && !IsWindow(hWnd)) goto CLEANUP;
1829 if (hWnd)
1831 /* walk up to the first unowned window */
1832 wndTemp = WIN_LockWndPtr(wndPtr);
1833 while (wndTemp->owner)
1835 WIN_UpdateWndPtr(&wndTemp,wndTemp->owner);
1837 /* and set last active owned popup */
1838 wndTemp->hwndLastActive = hWnd;
1840 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1841 WIN_ReleaseWndPtr(wndTemp);
1842 SendMessageA( hWnd, WM_NCACTIVATE, TRUE, 0 );
1843 SendMessageA( hWnd, WM_ACTIVATE,
1844 MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1845 (LPARAM)hwndPrevActive );
1846 if( !IsWindow(hWnd) ) goto CLEANUP;
1849 /* change focus if possible */
1850 if ( fChangeFocus )
1852 if ( pNewActiveQueue )
1854 HWND hOldFocus = PERQDATA_GetFocusWnd( pNewActiveQueue->pQData );
1856 if ( WIN_GetTopParent( hOldFocus ) != hwndActive )
1857 FOCUS_SwitchFocus( pNewActiveQueue, hOldFocus,
1858 (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
1859 0 : hwndActive );
1862 if ( pOldActiveQueue &&
1863 ( !pNewActiveQueue ||
1864 pNewActiveQueue->pQData != pOldActiveQueue->pQData ) )
1866 HWND hOldFocus = PERQDATA_GetFocusWnd( pOldActiveQueue->pQData );
1867 if ( hOldFocus )
1868 FOCUS_SwitchFocus( pOldActiveQueue, hOldFocus, 0 );
1872 if( !hwndPrevActive && wndPtr )
1873 (*wndPtr->pDriver->pForceWindowRaise)(wndPtr);
1875 /* if active wnd is minimized redraw icon title */
1876 if( IsIconic(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1878 bRet = (hWnd == hwndActive); /* Success? */
1880 CLEANUP: /* Unlock the message queues before returning */
1882 if ( pNewActiveQueue )
1883 QUEUE_Unlock( pNewActiveQueue );
1885 CLEANUP_END:
1887 if ( pOldActiveQueue )
1888 QUEUE_Unlock( pOldActiveQueue );
1890 WIN_ReleaseWndPtr(wndPtr);
1891 return bRet;
1894 /*******************************************************************
1895 * WINPOS_ActivateOtherWindow
1897 * Activates window other than pWnd.
1899 BOOL WINPOS_ActivateOtherWindow(WND* pWnd)
1901 BOOL bRet = 0;
1902 WND* pWndTo = NULL;
1903 HWND hwndActive = 0;
1905 /* Get current active window from the active queue */
1906 if ( hActiveQueue )
1908 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1909 if ( pActiveQueue )
1911 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1912 QUEUE_Unlock( pActiveQueue );
1916 if( pWnd->hwndSelf == hwndPrevActive )
1917 hwndPrevActive = 0;
1919 if( hwndActive != pWnd->hwndSelf &&
1920 ( hwndActive || QUEUE_IsExitingQueue(pWnd->hmemTaskQ)) )
1921 return 0;
1923 if( !(pWnd->dwStyle & WS_POPUP) || !(pWnd->owner) ||
1924 !WINPOS_CanActivate((pWndTo = WIN_GetTopParentPtr(pWnd->owner))) )
1926 WND* pWndPtr = WIN_GetTopParentPtr(pWnd);
1928 WIN_ReleaseWndPtr(pWndTo);
1929 pWndTo = WIN_FindWndPtr(hwndPrevActive);
1931 while( !WINPOS_CanActivate(pWndTo) )
1933 /* by now owned windows should've been taken care of */
1934 WIN_UpdateWndPtr(&pWndTo,pWndPtr->next);
1935 WIN_UpdateWndPtr(&pWndPtr,pWndTo);
1936 if( !pWndTo ) break;
1938 WIN_ReleaseWndPtr(pWndPtr);
1941 bRet = WINPOS_SetActiveWindow( pWndTo ? pWndTo->hwndSelf : 0, FALSE, TRUE );
1943 /* switch desktop queue to current active */
1944 if( pWndTo )
1946 WIN_GetDesktop()->hmemTaskQ = pWndTo->hmemTaskQ;
1947 WIN_ReleaseWndPtr(pWndTo);
1948 WIN_ReleaseDesktop();
1951 hwndPrevActive = 0;
1952 return bRet;
1955 /*******************************************************************
1956 * WINPOS_ChangeActiveWindow
1959 BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
1961 WND *wndPtr, *wndTemp;
1962 BOOL retvalue;
1963 HWND hwndActive = 0;
1965 /* Get current active window from the active queue */
1966 if ( hActiveQueue )
1968 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1969 if ( pActiveQueue )
1971 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1972 QUEUE_Unlock( pActiveQueue );
1976 if (!hWnd)
1977 return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
1979 wndPtr = WIN_FindWndPtr(hWnd);
1980 if( !wndPtr ) return FALSE;
1982 /* child windows get WM_CHILDACTIVATE message */
1983 if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
1985 retvalue = SendMessageA(hWnd, WM_CHILDACTIVATE, 0, 0L);
1986 goto end;
1989 if( hWnd == hwndActive )
1991 retvalue = FALSE;
1992 goto end;
1995 if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
1997 retvalue = FALSE;
1998 goto end;
2001 /* switch desktop queue to current active */
2002 wndTemp = WIN_GetDesktop();
2003 if( wndPtr->parent == wndTemp)
2004 wndTemp->hmemTaskQ = wndPtr->hmemTaskQ;
2005 WIN_ReleaseDesktop();
2007 retvalue = TRUE;
2008 end:
2009 WIN_ReleaseWndPtr(wndPtr);
2010 return retvalue;
2014 /***********************************************************************
2015 * WINPOS_SendNCCalcSize
2017 * Send a WM_NCCALCSIZE message to a window.
2018 * All parameters are read-only except newClientRect.
2019 * oldWindowRect, oldClientRect and winpos must be non-NULL only
2020 * when calcValidRect is TRUE.
2022 LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect,
2023 RECT *newWindowRect, RECT *oldWindowRect,
2024 RECT *oldClientRect, WINDOWPOS *winpos,
2025 RECT *newClientRect )
2027 NCCALCSIZE_PARAMS params;
2028 WINDOWPOS winposCopy;
2029 LONG result;
2031 params.rgrc[0] = *newWindowRect;
2032 if (calcValidRect)
2034 winposCopy = *winpos;
2035 params.rgrc[1] = *oldWindowRect;
2036 params.rgrc[2] = *oldClientRect;
2037 params.lppos = &winposCopy;
2039 result = SendMessageA( hwnd, WM_NCCALCSIZE, calcValidRect,
2040 (LPARAM)&params );
2041 TRACE("%d,%d-%d,%d\n",
2042 params.rgrc[0].left, params.rgrc[0].top,
2043 params.rgrc[0].right, params.rgrc[0].bottom );
2045 /* If the application send back garbage, ignore it */
2046 if (params.rgrc[0].left <= params.rgrc[0].right && params.rgrc[0].top <= params.rgrc[0].bottom)
2047 *newClientRect = params.rgrc[0];
2049 return result;
2053 /***********************************************************************
2054 * WINPOS_HandleWindowPosChanging16
2056 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2058 LONG WINPOS_HandleWindowPosChanging16( WND *wndPtr, WINDOWPOS16 *winpos )
2060 POINT maxSize, minTrack;
2061 if (winpos->flags & SWP_NOSIZE) return 0;
2062 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2063 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2065 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
2066 if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
2067 if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
2068 if (!(wndPtr->dwStyle & WS_MINIMIZE))
2070 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
2071 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
2074 return 0;
2078 /***********************************************************************
2079 * WINPOS_HandleWindowPosChanging
2081 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2083 LONG WINPOS_HandleWindowPosChanging( WND *wndPtr, WINDOWPOS *winpos )
2085 POINT maxSize;
2086 if (winpos->flags & SWP_NOSIZE) return 0;
2087 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2088 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2090 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, NULL, NULL );
2091 winpos->cx = min( winpos->cx, maxSize.x );
2092 winpos->cy = min( winpos->cy, maxSize.y );
2094 return 0;
2097 /***********************************************************************
2098 * SWP_DoOwnedPopups
2100 * fix Z order taking into account owned popups -
2101 * basically we need to maintain them above the window that owns them
2103 * FIXME: hide/show owned popups when owner visibility changes.
2105 static HWND SWP_DoOwnedPopups(WND* pDesktop, WND* wndPtr, HWND hwndInsertAfter, WORD flags)
2107 WND* w = WIN_LockWndPtr(pDesktop->child);
2109 WARN("(%04x) hInsertAfter = %04x\n", wndPtr->hwndSelf, hwndInsertAfter );
2111 if( (wndPtr->dwStyle & WS_POPUP) && wndPtr->owner )
2113 /* make sure this popup stays above the owner */
2115 HWND hwndLocalPrev = HWND_TOP;
2117 if( hwndInsertAfter != HWND_TOP )
2119 while( w != wndPtr->owner )
2121 if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
2122 if( hwndLocalPrev == hwndInsertAfter ) break;
2123 WIN_UpdateWndPtr(&w,w->next);
2125 hwndInsertAfter = hwndLocalPrev;
2128 else if( wndPtr->dwStyle & WS_CHILD )
2129 goto END;
2131 WIN_UpdateWndPtr(&w, pDesktop->child);
2133 while( w )
2135 if( w == wndPtr ) break;
2137 if( (w->dwStyle & WS_POPUP) && w->owner == wndPtr )
2139 SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0,
2140 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
2141 hwndInsertAfter = w->hwndSelf;
2143 WIN_UpdateWndPtr(&w, w->next);
2146 END:
2147 WIN_ReleaseWndPtr(w);
2148 return hwndInsertAfter;
2151 /***********************************************************************
2152 * SWP_CopyValidBits
2154 * Make window look nice without excessive repainting
2156 * visible and update regions are in window coordinates
2157 * client and window rectangles are in parent client coordinates
2159 * FIXME: SWP_EX_PAINTSELF in uFlags works only if both old and new
2160 * window rects have the same origin.
2162 * Returns: uFlags and a dirty region in *pVisRgn.
2164 static UINT SWP_CopyValidBits( WND* Wnd, HRGN* pVisRgn,
2165 LPRECT lpOldWndRect,
2166 LPRECT lpOldClientRect, UINT uFlags )
2168 RECT r;
2169 HRGN newVisRgn, dirtyRgn;
2170 INT my = COMPLEXREGION;
2172 TRACE("\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2173 Wnd->rectWindow.left, Wnd->rectWindow.top,
2174 Wnd->rectWindow.right, Wnd->rectWindow.bottom,
2175 lpOldWndRect->left, lpOldWndRect->top,
2176 lpOldWndRect->right, lpOldWndRect->bottom, *pVisRgn);
2177 TRACE("\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2178 Wnd->rectClient.left, Wnd->rectClient.top,
2179 Wnd->rectClient.right, Wnd->rectClient.bottom,
2180 lpOldClientRect->left, lpOldClientRect->top,
2181 lpOldClientRect->right,lpOldClientRect->bottom );
2183 if( Wnd->hrgnUpdate == 1 )
2184 uFlags |= SWP_EX_NOCOPY; /* whole window is invalid, nothing to copy */
2186 newVisRgn = DCE_GetVisRgn( Wnd->hwndSelf, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
2187 dirtyRgn = CreateRectRgn( 0, 0, 0, 0 );
2189 if( !(uFlags & SWP_EX_NOCOPY) ) /* make sure dst region covers only valid bits */
2190 my = CombineRgn( dirtyRgn, newVisRgn, *pVisRgn, RGN_AND );
2192 if( (my == NULLREGION) || (uFlags & SWP_EX_NOCOPY) )
2194 nocopy:
2196 TRACE("\twon't copy anything!\n");
2198 /* set dirtyRgn to the sum of old and new visible regions
2199 * in parent client coordinates */
2201 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2202 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2204 CombineRgn(*pVisRgn, *pVisRgn, newVisRgn, RGN_OR );
2206 else /* copy valid bits to a new location */
2208 INT dx, dy, ow, oh, nw, nh, ocw, ncw, och, nch;
2209 HRGN hrgnValid = dirtyRgn; /* non-empty intersection of old and new visible rgns */
2211 /* subtract already invalid region inside Wnd from the dst region */
2213 if( Wnd->hrgnUpdate )
2214 if( CombineRgn( hrgnValid, hrgnValid, Wnd->hrgnUpdate, RGN_DIFF) == NULLREGION )
2215 goto nocopy;
2217 /* check if entire window can be copied */
2219 ow = lpOldWndRect->right - lpOldWndRect->left;
2220 oh = lpOldWndRect->bottom - lpOldWndRect->top;
2221 nw = Wnd->rectWindow.right - Wnd->rectWindow.left;
2222 nh = Wnd->rectWindow.bottom - Wnd->rectWindow.top;
2224 ocw = lpOldClientRect->right - lpOldClientRect->left;
2225 och = lpOldClientRect->bottom - lpOldClientRect->top;
2226 ncw = Wnd->rectClient.right - Wnd->rectClient.left;
2227 nch = Wnd->rectClient.bottom - Wnd->rectClient.top;
2229 if( (ocw != ncw) || (och != nch) ||
2230 ( ow != nw) || ( oh != nh) ||
2231 ((lpOldClientRect->top - lpOldWndRect->top) !=
2232 (Wnd->rectClient.top - Wnd->rectWindow.top)) ||
2233 ((lpOldClientRect->left - lpOldWndRect->left) !=
2234 (Wnd->rectClient.left - Wnd->rectWindow.left)) )
2236 dx = Wnd->rectClient.left - lpOldClientRect->left;
2237 dy = Wnd->rectClient.top - lpOldClientRect->top;
2239 /* restrict valid bits to the common client rect */
2241 r.left = Wnd->rectClient.left - Wnd->rectWindow.left;
2242 r.top = Wnd->rectClient.top - Wnd->rectWindow.top;
2243 r.right = r.left + min( ocw, ncw );
2244 r.bottom = r.top + min( och, nch );
2246 REGION_CropRgn( hrgnValid, hrgnValid, &r,
2247 (uFlags & SWP_EX_PAINTSELF) ? NULL : (POINT*)&(Wnd->rectWindow));
2248 GetRgnBox( hrgnValid, &r );
2249 if( IsRectEmpty( &r ) )
2250 goto nocopy;
2251 r = *lpOldClientRect;
2253 else
2255 dx = Wnd->rectWindow.left - lpOldWndRect->left;
2256 dy = Wnd->rectWindow.top - lpOldWndRect->top;
2257 if( !(uFlags & SWP_EX_PAINTSELF) )
2258 OffsetRgn( hrgnValid, Wnd->rectWindow.left, Wnd->rectWindow.top );
2259 r = *lpOldWndRect;
2262 if( !(uFlags & SWP_EX_PAINTSELF) )
2264 /* Move remaining regions to parent coordinates */
2265 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2266 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2268 else
2269 OffsetRect( &r, -lpOldWndRect->left, -lpOldWndRect->top );
2271 TRACE("\tcomputing dirty region!\n");
2273 /* Compute combined dirty region (old + new - valid) */
2274 CombineRgn( *pVisRgn, *pVisRgn, newVisRgn, RGN_OR);
2275 CombineRgn( *pVisRgn, *pVisRgn, hrgnValid, RGN_DIFF);
2277 /* Blt valid bits, r is the rect to copy */
2279 if( dx || dy )
2281 RECT rClip;
2282 HDC hDC;
2283 DC* dc;
2285 /* get DC and clip rect with drawable rect to avoid superfluous expose events
2286 from copying clipped areas */
2288 if( uFlags & SWP_EX_PAINTSELF )
2290 hDC = GetDCEx( Wnd->hwndSelf, hrgnValid, DCX_WINDOW | DCX_CACHE |
2291 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2292 rClip.right = nw; rClip.bottom = nh;
2294 else
2296 hDC = GetDCEx( Wnd->parent->hwndSelf, hrgnValid, DCX_CACHE |
2297 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2298 rClip.right = Wnd->parent->rectClient.right - Wnd->parent->rectClient.left;
2299 rClip.bottom = Wnd->parent->rectClient.bottom - Wnd->parent->rectClient.top;
2301 rClip.left = rClip.top = 0;
2303 if( (dc = (DC *)GDI_GetObjPtr(hDC, DC_MAGIC)) )
2305 if( oh > nh ) r.bottom = r.top + nh;
2306 if( ow < nw ) r.right = r.left + nw;
2308 if( IntersectRect( &r, &r, &rClip ) )
2310 Wnd->pDriver->pSurfaceCopy( Wnd->parent, dc, dx, dy, &r, TRUE );
2312 /* When you copy the bits without repainting, parent doesn't
2313 get validated appropriately. Therefore, we have to validate
2314 the parent with the windows' updated region when the
2315 parent's update region is not empty. */
2317 if (Wnd->parent->hrgnUpdate != 0 && !(Wnd->parent->dwStyle & WS_CLIPCHILDREN))
2319 OffsetRect(&r, dx, dy);
2320 ValidateRect(Wnd->parent->hwndSelf, &r);
2324 GDI_HEAP_UNLOCK( hDC );
2326 ReleaseDC( (uFlags & SWP_EX_PAINTSELF) ?
2327 Wnd->hwndSelf : Wnd->parent->hwndSelf, hDC);
2331 /* *pVisRgn now points to the invalidated region */
2333 DeleteObject(newVisRgn);
2334 DeleteObject(dirtyRgn);
2335 return uFlags;
2338 /***********************************************************************
2339 * SWP_DoSimpleFrameChanged
2341 * NOTE: old and new client rect origins are identical, only
2342 * extents may have changed. Window extents are the same.
2344 static void SWP_DoSimpleFrameChanged( WND* wndPtr, RECT* pOldClientRect, WORD swpFlags, UINT uFlags )
2346 INT i = 0;
2347 RECT rect;
2348 HRGN hrgn = 0;
2350 if( !(swpFlags & SWP_NOCLIENTSIZE) )
2352 /* Client rect changed its position/size, most likely a scrollar
2353 * was added/removed.
2355 * FIXME: WVR alignment flags
2358 if( wndPtr->rectClient.right > pOldClientRect->right ) /* right edge */
2360 i++;
2361 rect.top = 0;
2362 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2363 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2364 if(!(uFlags & SWP_EX_NOCOPY))
2365 rect.left = pOldClientRect->right - wndPtr->rectClient.left;
2366 else
2368 rect.left = 0;
2369 goto redraw;
2373 if( wndPtr->rectClient.bottom > pOldClientRect->bottom ) /* bottom edge */
2375 if( i )
2376 hrgn = CreateRectRgnIndirect( &rect );
2377 rect.left = 0;
2378 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2379 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2380 if(!(uFlags & SWP_EX_NOCOPY))
2381 rect.top = pOldClientRect->bottom - wndPtr->rectClient.top;
2382 else
2383 rect.top = 0;
2384 if( i++ )
2385 REGION_UnionRectWithRgn( hrgn, &rect );
2388 if( i == 0 && (uFlags & SWP_EX_NOCOPY) ) /* force redraw anyway */
2390 rect = wndPtr->rectWindow;
2391 OffsetRect( &rect, wndPtr->rectWindow.left - wndPtr->rectClient.left,
2392 wndPtr->rectWindow.top - wndPtr->rectClient.top );
2393 i++;
2397 if( i )
2399 redraw:
2400 PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
2401 RDW_ERASENOW | RDW_ALLCHILDREN, RDW_EX_TOPFRAME | RDW_EX_USEHRGN );
2403 else
2405 WIN_UpdateNCRgn(wndPtr, 0, UNC_UPDATE | UNC_ENTIRE);
2408 if( hrgn > 1 )
2409 DeleteObject( hrgn );
2412 /***********************************************************************
2413 * SWP_DoWinPosChanging
2415 static BOOL SWP_DoWinPosChanging( WND* wndPtr, WINDOWPOS* pWinpos,
2416 RECT* pNewWindowRect, RECT* pNewClientRect )
2418 /* Send WM_WINDOWPOSCHANGING message */
2420 if (!(pWinpos->flags & SWP_NOSENDCHANGING))
2421 SendMessageA( wndPtr->hwndSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM)pWinpos );
2423 /* Calculate new position and size */
2425 *pNewWindowRect = wndPtr->rectWindow;
2426 *pNewClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
2427 : wndPtr->rectClient;
2429 if (!(pWinpos->flags & SWP_NOSIZE))
2431 pNewWindowRect->right = pNewWindowRect->left + pWinpos->cx;
2432 pNewWindowRect->bottom = pNewWindowRect->top + pWinpos->cy;
2434 if (!(pWinpos->flags & SWP_NOMOVE))
2436 pNewWindowRect->left = pWinpos->x;
2437 pNewWindowRect->top = pWinpos->y;
2438 pNewWindowRect->right += pWinpos->x - wndPtr->rectWindow.left;
2439 pNewWindowRect->bottom += pWinpos->y - wndPtr->rectWindow.top;
2441 OffsetRect( pNewClientRect, pWinpos->x - wndPtr->rectWindow.left,
2442 pWinpos->y - wndPtr->rectWindow.top );
2445 pWinpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
2446 return TRUE;
2449 /***********************************************************************
2450 * SWP_DoNCCalcSize
2452 static UINT SWP_DoNCCalcSize( WND* wndPtr, WINDOWPOS* pWinpos,
2453 RECT* pNewWindowRect, RECT* pNewClientRect, WORD f)
2455 UINT wvrFlags = 0;
2457 /* Send WM_NCCALCSIZE message to get new client area */
2458 if( (pWinpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
2460 wvrFlags = WINPOS_SendNCCalcSize( pWinpos->hwnd, TRUE, pNewWindowRect,
2461 &wndPtr->rectWindow, &wndPtr->rectClient,
2462 pWinpos, pNewClientRect );
2464 /* FIXME: WVR_ALIGNxxx */
2466 if( pNewClientRect->left != wndPtr->rectClient.left ||
2467 pNewClientRect->top != wndPtr->rectClient.top )
2468 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2470 if( (pNewClientRect->right - pNewClientRect->left !=
2471 wndPtr->rectClient.right - wndPtr->rectClient.left) ||
2472 (pNewClientRect->bottom - pNewClientRect->top !=
2473 wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
2474 pWinpos->flags &= ~SWP_NOCLIENTSIZE;
2476 else
2477 if( !(f & SWP_NOMOVE) && (pNewClientRect->left != wndPtr->rectClient.left ||
2478 pNewClientRect->top != wndPtr->rectClient.top) )
2479 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2480 return wvrFlags;
2483 /***********************************************************************
2484 * SetWindowPos (USER.2)
2486 BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
2487 INT16 x, INT16 y, INT16 cx, INT16 cy, WORD flags)
2489 return SetWindowPos(hwnd,(INT)(INT16)hwndInsertAfter,x,y,cx,cy,flags);
2492 /***********************************************************************
2493 * SetWindowPos (USER32.520)
2495 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
2496 INT x, INT y, INT cx, INT cy, UINT flags )
2498 WINDOWPOS winpos;
2499 WND * wndPtr,*wndTemp;
2500 RECT newWindowRect, newClientRect;
2501 RECT oldWindowRect, oldClientRect;
2502 HRGN visRgn = 0;
2503 UINT wvrFlags = 0, uFlags = 0;
2504 BOOL retvalue, resync = FALSE, bChangePos;
2505 HWND hwndActive = 0;
2507 /* Get current active window from the active queue */
2508 if ( hActiveQueue )
2510 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2511 if ( pActiveQueue )
2513 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2514 QUEUE_Unlock( pActiveQueue );
2518 TRACE("hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2519 hwnd, x, y, x+cx, y+cy, flags);
2521 bChangePos = !(flags & SWP_WINE_NOHOSTMOVE);
2522 flags &= ~SWP_WINE_NOHOSTMOVE;
2525 /* ------------------------------------------------------------------------ CHECKS */
2527 /* Check window handle */
2529 if (hwnd == GetDesktopWindow()) return FALSE;
2530 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2532 TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr->rectWindow.left, wndPtr->rectWindow.top,
2533 wndPtr->rectWindow.right, wndPtr->rectWindow.bottom, (unsigned)wndPtr->dwStyle );
2535 /* Fix redundant flags */
2537 if(wndPtr->dwStyle & WS_VISIBLE)
2538 flags &= ~SWP_SHOWWINDOW;
2539 else
2541 if (!(flags & SWP_SHOWWINDOW))
2542 flags |= SWP_NOREDRAW;
2543 flags &= ~SWP_HIDEWINDOW;
2546 if ( cx < 0 ) cx = 0; if( cy < 0 ) cy = 0;
2548 if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
2549 (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
2550 flags |= SWP_NOSIZE; /* Already the right size */
2552 if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
2553 flags |= SWP_NOMOVE; /* Already the right position */
2555 if (hwnd == hwndActive)
2556 flags |= SWP_NOACTIVATE; /* Already active */
2557 else if ( (wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD )
2559 if(!(flags & SWP_NOACTIVATE)) /* Bring to the top when activating */
2561 flags &= ~SWP_NOZORDER;
2562 hwndInsertAfter = HWND_TOP;
2563 goto Pos;
2567 /* Check hwndInsertAfter */
2569 /* FIXME: TOPMOST not supported yet */
2570 if ((hwndInsertAfter == HWND_TOPMOST) ||
2571 (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
2573 /* hwndInsertAfter must be a sibling of the window */
2574 if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
2576 WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
2578 if( wnd ) {
2579 if( wnd->parent != wndPtr->parent )
2581 retvalue = FALSE;
2582 WIN_ReleaseWndPtr(wnd);
2583 goto END;
2585 if( wnd->next == wndPtr ) flags |= SWP_NOZORDER;
2587 WIN_ReleaseWndPtr(wnd);
2590 Pos: /* ------------------------------------------------------------------------ MAIN part */
2592 /* Fill the WINDOWPOS structure */
2594 winpos.hwnd = hwnd;
2595 winpos.hwndInsertAfter = hwndInsertAfter;
2596 winpos.x = x;
2597 winpos.y = y;
2598 winpos.cx = cx;
2599 winpos.cy = cy;
2600 winpos.flags = flags;
2602 SWP_DoWinPosChanging( wndPtr, &winpos, &newWindowRect, &newClientRect );
2604 if((winpos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER)
2606 if( wndPtr->parent == WIN_GetDesktop() )
2607 hwndInsertAfter = SWP_DoOwnedPopups( wndPtr->parent, wndPtr,
2608 hwndInsertAfter, winpos.flags );
2609 WIN_ReleaseDesktop();
2612 if(!(wndPtr->flags & WIN_NATIVE) )
2614 if( hwndInsertAfter == HWND_TOP )
2615 winpos.flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
2616 else
2617 if( hwndInsertAfter == HWND_BOTTOM )
2618 winpos.flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
2619 else
2620 if( !(winpos.flags & SWP_NOZORDER) )
2621 if( GetWindow(hwndInsertAfter, GW_HWNDNEXT) == wndPtr->hwndSelf )
2622 winpos.flags |= SWP_NOZORDER;
2624 if( !(winpos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) &&
2625 ((winpos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW | SWP_FRAMECHANGED))
2626 != (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)) )
2628 /* get a previous visible region for SWP_CopyValidBits() */
2629 DWORD flags = DCX_WINDOW;
2631 if (wndPtr->dwStyle & WS_CLIPSIBLINGS)
2632 flags |= DCX_CLIPSIBLINGS;
2634 visRgn = DCE_GetVisRgn(hwnd, flags, 0, 0);
2638 /* Common operations */
2640 wvrFlags = SWP_DoNCCalcSize( wndPtr, &winpos, &newWindowRect, &newClientRect, flags );
2642 if(!(winpos.flags & SWP_NOZORDER) && winpos.hwnd != hwndInsertAfter)
2644 if ( WIN_UnlinkWindow( winpos.hwnd ) )
2645 WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
2648 /* Reset active DCEs */
2650 if( (((winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) &&
2651 wndPtr->dwStyle & WS_VISIBLE) ||
2652 (flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
2654 RECT rect;
2656 UnionRect(&rect, &newWindowRect, &wndPtr->rectWindow);
2657 DCE_InvalidateDCE(wndPtr, &rect);
2660 oldWindowRect = wndPtr->rectWindow;
2661 oldClientRect = wndPtr->rectClient;
2663 /* Find out if we have to redraw the whole client rect */
2665 if( oldClientRect.bottom - oldClientRect.top ==
2666 newClientRect.bottom - newClientRect.top ) wvrFlags &= ~WVR_VREDRAW;
2668 if( oldClientRect.right - oldClientRect.left ==
2669 newClientRect.right - newClientRect.left ) wvrFlags &= ~WVR_HREDRAW;
2671 if( (winpos.flags & SWP_NOCOPYBITS) || (!(winpos.flags & SWP_NOCLIENTSIZE) &&
2672 (wvrFlags >= WVR_HREDRAW) && (wvrFlags < WVR_VALIDRECTS)) )
2674 uFlags |= SWP_EX_NOCOPY;
2677 * Use this later in CopyValidBits()
2679 else if( 0 )
2680 uFlags |= SWP_EX_NONCLIENT;
2683 /* FIXME: actually do something with WVR_VALIDRECTS */
2685 wndPtr->rectWindow = newWindowRect;
2686 wndPtr->rectClient = newClientRect;
2688 if (wndPtr->flags & WIN_NATIVE) /* -------------------------------------------- hosted window */
2690 BOOL bCallDriver = TRUE;
2691 HWND tempInsertAfter = winpos.hwndInsertAfter;
2693 winpos.hwndInsertAfter = hwndInsertAfter;
2695 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2697 /* This is the only place where we need to force repainting of the contents
2698 of windows created by the host window system, all other cases go through the
2699 expose event handling */
2701 if( (winpos.flags & (SWP_NOSIZE | SWP_FRAMECHANGED)) == (SWP_NOSIZE | SWP_FRAMECHANGED) )
2703 cx = newWindowRect.right - newWindowRect.left;
2704 cy = newWindowRect.bottom - newWindowRect.top;
2706 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2707 winpos.hwndInsertAfter = tempInsertAfter;
2708 bCallDriver = FALSE;
2710 if( winpos.flags & SWP_NOCLIENTMOVE )
2711 SWP_DoSimpleFrameChanged(wndPtr, &oldClientRect, winpos.flags, uFlags );
2712 else
2714 /* client area moved but window extents remained the same, copy valid bits */
2716 visRgn = CreateRectRgn( 0, 0, cx, cy );
2717 uFlags = SWP_CopyValidBits( wndPtr, &visRgn, &oldWindowRect, &oldClientRect,
2718 uFlags | SWP_EX_PAINTSELF );
2723 if( bCallDriver )
2725 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2727 if( (oldClientRect.left - oldWindowRect.left == newClientRect.left - newWindowRect.left) &&
2728 (oldClientRect.top - oldWindowRect.top == newClientRect.top - newWindowRect.top) &&
2729 !(uFlags & SWP_EX_NOCOPY) )
2731 /* The origin of the client rect didn't move so we can try to repaint
2732 * only the nonclient area by setting bit gravity hint for the host window system.
2735 if( !(wndPtr->flags & WIN_MANAGED) )
2737 HRGN hrgn = CreateRectRgn( 0, 0, newWindowRect.right - newWindowRect.left,
2738 newWindowRect.bottom - newWindowRect.top);
2739 RECT rcn = newClientRect;
2740 RECT rco = oldClientRect;
2742 OffsetRect( &rcn, -newWindowRect.left, -newWindowRect.top );
2743 OffsetRect( &rco, -oldWindowRect.left, -oldWindowRect.top );
2744 IntersectRect( &rcn, &rcn, &rco );
2745 visRgn = CreateRectRgnIndirect( &rcn );
2746 CombineRgn( visRgn, hrgn, visRgn, RGN_DIFF );
2747 DeleteObject( hrgn );
2748 uFlags = SWP_EX_PAINTSELF;
2750 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGNorthWest );
2752 else
2753 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGForget );
2756 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2757 winpos.hwndInsertAfter = tempInsertAfter;
2760 if( winpos.flags & SWP_SHOWWINDOW )
2762 HWND focus, curr;
2764 wndPtr->dwStyle |= WS_VISIBLE;
2766 if (wndPtr->flags & WIN_MANAGED) resync = TRUE;
2768 /* focus was set to unmapped window, reset host focus
2769 * since the window is now visible */
2771 focus = curr = GetFocus();
2772 while (curr)
2774 if (curr == hwnd)
2776 WND *pFocus = WIN_FindWndPtr( focus );
2777 if (pFocus)
2778 pFocus->pDriver->pSetFocus(pFocus);
2779 WIN_ReleaseWndPtr(pFocus);
2780 break;
2782 curr = GetParent(curr);
2786 else /* -------------------------------------------- emulated window */
2788 if( winpos.flags & SWP_SHOWWINDOW )
2790 wndPtr->dwStyle |= WS_VISIBLE;
2791 uFlags |= SWP_EX_PAINTSELF;
2792 visRgn = 1; /* redraw the whole window */
2794 else if( !(winpos.flags & SWP_NOREDRAW) )
2796 if( winpos.flags & SWP_HIDEWINDOW )
2798 if( visRgn > 1 ) /* map to parent */
2799 OffsetRgn( visRgn, oldWindowRect.left, oldWindowRect.top );
2800 else
2801 visRgn = 0;
2803 else
2805 if( (winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE )
2806 uFlags = SWP_CopyValidBits(wndPtr, &visRgn, &oldWindowRect,
2807 &oldClientRect, uFlags);
2808 else
2810 /* nothing moved, redraw frame if needed */
2812 if( winpos.flags & SWP_FRAMECHANGED )
2813 SWP_DoSimpleFrameChanged( wndPtr, &oldClientRect, winpos.flags, uFlags );
2814 if( visRgn )
2816 DeleteObject( visRgn );
2817 visRgn = 0;
2824 if( winpos.flags & SWP_HIDEWINDOW )
2826 wndPtr->dwStyle &= ~WS_VISIBLE;
2828 if (hwnd == CARET_GetHwnd()) DestroyCaret();
2831 /* ------------------------------------------------------------------------ FINAL */
2833 if (wndPtr->flags & WIN_NATIVE)
2834 EVENT_Synchronize(); /* Synchronize with the host window system */
2836 if (!GetCapture() && ((wndPtr->dwStyle & WS_VISIBLE) || (flags & SWP_HIDEWINDOW)))
2838 /* Simulate a mouse event to set the cursor */
2839 int iWndsLocks = WIN_SuspendWndsLock();
2841 hardware_event( WM_MOUSEMOVE, GET_KEYSTATE(), 0,
2842 PosX, PosY, GetTickCount(), 0 );
2844 WIN_RestoreWndsLock(iWndsLocks);
2847 wndTemp = WIN_GetDesktop();
2849 /* repaint invalidated region (if any)
2851 * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2852 * and force update after ChangeActiveWindow() to avoid painting frames twice.
2855 if( visRgn )
2857 if( !(winpos.flags & SWP_NOREDRAW) )
2860 /* Use PAINT_RedrawWindow to explicitly force an invalidation of the window,
2861 its parent and sibling and so on, and then erase the parent window
2862 back ground if the parent is either a top-level window or its parent's parent
2863 is top-level window. Rely on the system to repaint other affected
2864 windows later on. */
2865 if( uFlags & SWP_EX_PAINTSELF )
2867 PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn,
2868 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN,
2869 RDW_EX_XYWINDOW | RDW_EX_USEHRGN );
2871 else
2873 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn,
2874 RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN,
2875 RDW_EX_USEHRGN );
2878 if(wndPtr -> parent == wndTemp || wndPtr->parent->parent == wndTemp )
2880 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0,
2881 RDW_ERASENOW | RDW_NOCHILDREN, 0 );
2884 if( visRgn != 1 )
2885 DeleteObject( visRgn );
2888 WIN_ReleaseDesktop();
2890 if (!(flags & SWP_NOACTIVATE))
2891 WINPOS_ChangeActiveWindow( winpos.hwnd, FALSE );
2893 /* And last, send the WM_WINDOWPOSCHANGED message */
2895 TRACE("\tstatus flags = %04x\n", winpos.flags & SWP_AGG_STATUSFLAGS);
2897 if ( resync ||
2898 (((winpos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) &&
2899 !(winpos.flags & SWP_NOSENDCHANGING)) )
2901 SendMessageA( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
2902 if (resync) EVENT_Synchronize();
2905 retvalue = TRUE;
2906 END:
2907 WIN_ReleaseWndPtr(wndPtr);
2908 return retvalue;
2912 /***********************************************************************
2913 * BeginDeferWindowPos16 (USER.259)
2915 HDWP16 WINAPI BeginDeferWindowPos16( INT16 count )
2917 return BeginDeferWindowPos( count );
2921 /***********************************************************************
2922 * BeginDeferWindowPos (USER32.9)
2924 HDWP WINAPI BeginDeferWindowPos( INT count )
2926 HDWP handle;
2927 DWP *pDWP;
2929 if (count <= 0) return 0;
2930 handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
2931 if (!handle) return 0;
2932 pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
2933 pDWP->actualCount = 0;
2934 pDWP->suggestedCount = count;
2935 pDWP->valid = TRUE;
2936 pDWP->wMagic = DWP_MAGIC;
2937 pDWP->hwndParent = 0;
2938 return handle;
2942 /***********************************************************************
2943 * DeferWindowPos16 (USER.260)
2945 HDWP16 WINAPI DeferWindowPos16( HDWP16 hdwp, HWND16 hwnd, HWND16 hwndAfter,
2946 INT16 x, INT16 y, INT16 cx, INT16 cy,
2947 UINT16 flags )
2949 return DeferWindowPos( hdwp, hwnd, (INT)(INT16)hwndAfter,
2950 x, y, cx, cy, flags );
2954 /***********************************************************************
2955 * DeferWindowPos (USER32.128)
2957 HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter,
2958 INT x, INT y, INT cx, INT cy,
2959 UINT flags )
2961 DWP *pDWP;
2962 int i;
2963 HDWP newhdwp = hdwp,retvalue;
2964 /* HWND parent; */
2965 WND *pWnd;
2967 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
2968 if (!pDWP) return 0;
2969 if (hwnd == GetDesktopWindow()) return 0;
2971 if (!(pWnd=WIN_FindWndPtr( hwnd ))) {
2972 USER_HEAP_FREE( hdwp );
2973 return 0;
2976 /* Numega Bounds Checker Demo dislikes the following code.
2977 In fact, I've not been able to find any "same parent" requirement in any docu
2978 [AM 980509]
2980 #if 0
2981 /* All the windows of a DeferWindowPos() must have the same parent */
2982 parent = pWnd->parent->hwndSelf;
2983 if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
2984 else if (parent != pDWP->hwndParent)
2986 USER_HEAP_FREE( hdwp );
2987 retvalue = 0;
2988 goto END;
2990 #endif
2992 for (i = 0; i < pDWP->actualCount; i++)
2994 if (pDWP->winPos[i].hwnd == hwnd)
2996 /* Merge with the other changes */
2997 if (!(flags & SWP_NOZORDER))
2999 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
3001 if (!(flags & SWP_NOMOVE))
3003 pDWP->winPos[i].x = x;
3004 pDWP->winPos[i].y = y;
3006 if (!(flags & SWP_NOSIZE))
3008 pDWP->winPos[i].cx = cx;
3009 pDWP->winPos[i].cy = cy;
3011 pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
3012 SWP_NOZORDER | SWP_NOREDRAW |
3013 SWP_NOACTIVATE | SWP_NOCOPYBITS|
3014 SWP_NOOWNERZORDER);
3015 pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
3016 SWP_FRAMECHANGED);
3017 retvalue = hdwp;
3018 goto END;
3021 if (pDWP->actualCount >= pDWP->suggestedCount)
3023 newhdwp = USER_HEAP_REALLOC( hdwp,
3024 sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
3025 if (!newhdwp)
3027 retvalue = 0;
3028 goto END;
3030 pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
3031 pDWP->suggestedCount++;
3033 pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
3034 pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
3035 pDWP->winPos[pDWP->actualCount].x = x;
3036 pDWP->winPos[pDWP->actualCount].y = y;
3037 pDWP->winPos[pDWP->actualCount].cx = cx;
3038 pDWP->winPos[pDWP->actualCount].cy = cy;
3039 pDWP->winPos[pDWP->actualCount].flags = flags;
3040 pDWP->actualCount++;
3041 retvalue = newhdwp;
3042 END:
3043 WIN_ReleaseWndPtr(pWnd);
3044 return retvalue;
3048 /***********************************************************************
3049 * EndDeferWindowPos16 (USER.261)
3051 BOOL16 WINAPI EndDeferWindowPos16( HDWP16 hdwp )
3053 return EndDeferWindowPos( hdwp );
3057 /***********************************************************************
3058 * EndDeferWindowPos (USER32.173)
3060 BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
3062 DWP *pDWP;
3063 WINDOWPOS *winpos;
3064 BOOL res = TRUE;
3065 int i;
3067 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
3068 if (!pDWP) return FALSE;
3069 for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
3071 if (!(res = SetWindowPos( winpos->hwnd, winpos->hwndInsertAfter,
3072 winpos->x, winpos->y, winpos->cx,
3073 winpos->cy, winpos->flags ))) break;
3075 USER_HEAP_FREE( hdwp );
3076 return res;
3080 /***********************************************************************
3081 * TileChildWindows (USER.199)
3083 void WINAPI TileChildWindows16( HWND16 parent, WORD action )
3085 FIXME("(%04x, %d): stub\n", parent, action);
3088 /***********************************************************************
3089 * CascadeChildWindows (USER.198)
3091 void WINAPI CascadeChildWindows16( HWND16 parent, WORD action )
3093 FIXME("(%04x, %d): stub\n", parent, action);
3096 /***********************************************************************
3097 * SetProgmanWindow [USER32.522]
3099 HRESULT WINAPI SetProgmanWindow ( HWND hwnd )
3101 hGlobalProgmanWindow = hwnd;
3102 return hGlobalProgmanWindow;
3105 /***********************************************************************
3106 * GetProgmanWindow [USER32.289]
3108 HRESULT WINAPI GetProgmanWindow ( )
3110 return hGlobalProgmanWindow;
3113 /***********************************************************************
3114 * SetShellWindowEx [USER32.531]
3115 * hwndProgman = Progman[Program Manager]
3116 * |-> SHELLDLL_DefView
3117 * hwndListView = | |-> SysListView32
3118 * | | |-> tooltips_class32
3119 * | |
3120 * | |-> SysHeader32
3121 * |
3122 * |-> ProxyTarget
3124 HRESULT WINAPI SetShellWindowEx ( HWND hwndProgman, HWND hwndListView )
3126 FIXME("0x%08x 0x%08x stub\n",hwndProgman ,hwndListView );
3127 hGlobalShellWindow = hwndProgman;
3128 return hGlobalShellWindow;
3132 /***********************************************************************
3133 * SetTaskmanWindow [USER32.537]
3134 * NOTES
3135 * hwnd = MSTaskSwWClass
3136 * |-> SysTabControl32
3138 HRESULT WINAPI SetTaskmanWindow ( HWND hwnd )
3140 hGlobalTaskmanWindow = hwnd;
3141 return hGlobalTaskmanWindow;
3144 /***********************************************************************
3145 * GetTaskmanWindow [USER32.304]
3147 HRESULT WINAPI GetTaskmanWindow ( )
3149 return hGlobalTaskmanWindow;