Use poll() instead of select() for the server main loop.
[wine/multimedia.git] / windows / winpos.c
blob74771e5cdf3150a34d11d945f7237c92ad573dfd
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 "wine/winuser16.h"
10 #include "heap.h"
11 #include "module.h"
12 #include "user.h"
13 #include "region.h"
14 #include "win.h"
15 #include "hook.h"
16 #include "message.h"
17 #include "queue.h"
18 #include "options.h"
19 #include "task.h"
20 #include "winpos.h"
21 #include "dce.h"
22 #include "nonclient.h"
23 #include "debugtools.h"
24 #include "local.h"
25 #include "ldt.h"
26 #include "input.h"
28 DEFAULT_DEBUG_CHANNEL(win)
30 #define HAS_DLGFRAME(style,exStyle) \
31 (((exStyle) & WS_EX_DLGMODALFRAME) || \
32 (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
34 #define HAS_THICKFRAME(style) \
35 (((style) & WS_THICKFRAME) && \
36 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
38 #define SWP_AGG_NOGEOMETRYCHANGE \
39 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
40 #define SWP_AGG_NOPOSCHANGE \
41 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
42 #define SWP_AGG_STATUSFLAGS \
43 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
45 #define EMPTYPOINT(pt) ((*(LONG*)&(pt)) == -1)
47 #define PLACE_MIN 0x0001
48 #define PLACE_MAX 0x0002
49 #define PLACE_RECT 0x0004
51 #define SWP_EX_NOCOPY 0x0001
52 #define SWP_EX_PAINTSELF 0x0002
53 #define SWP_EX_NONCLIENT 0x0004
55 #define MINMAX_NOSWP 0x00010000
57 /* ----- internal variables ----- */
59 static HWND hwndPrevActive = 0; /* Previously active window */
60 static HWND hGlobalShellWindow=0; /*the shell*/
61 static HWND hGlobalTaskmanWindow=0;
62 static HWND hGlobalProgmanWindow=0;
64 static LPCSTR atomInternalPos;
66 extern HQUEUE16 hActiveQueue;
68 /***********************************************************************
69 * WINPOS_CreateInternalPosAtom
71 BOOL WINPOS_CreateInternalPosAtom()
73 LPSTR str = "SysIP";
74 atomInternalPos = (LPCSTR)(DWORD)GlobalAddAtomA(str);
75 return (atomInternalPos) ? TRUE : FALSE;
78 /***********************************************************************
79 * WINPOS_CheckInternalPos
81 * Called when a window is destroyed.
83 void WINPOS_CheckInternalPos( WND* wndPtr )
85 LPINTERNALPOS lpPos;
86 MESSAGEQUEUE *pMsgQ = 0;
87 HWND hwnd = wndPtr->hwndSelf;
89 lpPos = (LPINTERNALPOS) GetPropA( hwnd, atomInternalPos );
91 /* Retrieve the message queue associated with this window */
92 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
93 if ( !pMsgQ )
95 WARN("\tMessage queue not found. Exiting!\n" );
96 return;
99 if( hwnd == hwndPrevActive ) hwndPrevActive = 0;
101 if( hwnd == PERQDATA_GetActiveWnd( pMsgQ->pQData ) )
103 PERQDATA_SetActiveWnd( pMsgQ->pQData, 0 );
104 WARN("\tattempt to activate destroyed window!\n");
107 if( lpPos )
109 if( IsWindow(lpPos->hwndIconTitle) )
110 DestroyWindow( lpPos->hwndIconTitle );
111 HeapFree( SystemHeap, 0, lpPos );
114 QUEUE_Unlock( pMsgQ );
115 return;
118 /***********************************************************************
119 * WINPOS_FindIconPos
121 * Find a suitable place for an iconic window.
123 static POINT16 WINPOS_FindIconPos( WND* wndPtr, POINT16 pt )
125 RECT16 rectParent;
126 short x, y, xspacing, yspacing;
128 GetClientRect16( wndPtr->parent->hwndSelf, &rectParent );
129 if ((pt.x >= rectParent.left) && (pt.x + GetSystemMetrics(SM_CXICON) < rectParent.right) &&
130 (pt.y >= rectParent.top) && (pt.y + GetSystemMetrics(SM_CYICON) < rectParent.bottom))
131 return pt; /* The icon already has a suitable position */
133 xspacing = GetSystemMetrics(SM_CXICONSPACING);
134 yspacing = GetSystemMetrics(SM_CYICONSPACING);
136 y = rectParent.bottom;
137 for (;;)
139 for (x = rectParent.left; x <= rectParent.right-xspacing; x += xspacing)
141 /* Check if another icon already occupies this spot */
142 WND *childPtr = WIN_LockWndPtr(wndPtr->parent->child);
143 while (childPtr)
145 if ((childPtr->dwStyle & WS_MINIMIZE) && (childPtr != wndPtr))
147 if ((childPtr->rectWindow.left < x + xspacing) &&
148 (childPtr->rectWindow.right >= x) &&
149 (childPtr->rectWindow.top <= y) &&
150 (childPtr->rectWindow.bottom > y - yspacing))
151 break; /* There's a window in there */
153 WIN_UpdateWndPtr(&childPtr,childPtr->next);
155 WIN_ReleaseWndPtr(childPtr);
156 if (!childPtr) /* No window was found, so it's OK for us */
158 pt.x = x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2;
159 pt.y = y - (yspacing + GetSystemMetrics(SM_CYICON)) / 2;
160 return pt;
163 y -= yspacing;
168 /***********************************************************************
169 * ArrangeIconicWindows16 (USER.170)
171 UINT16 WINAPI ArrangeIconicWindows16( HWND16 parent)
173 return ArrangeIconicWindows(parent);
175 /***********************************************************************
176 * ArrangeIconicWindows (USER32.7)
178 UINT WINAPI ArrangeIconicWindows( HWND parent )
180 RECT rectParent;
181 HWND hwndChild;
182 INT x, y, xspacing, yspacing;
184 GetClientRect( parent, &rectParent );
185 x = rectParent.left;
186 y = rectParent.bottom;
187 xspacing = GetSystemMetrics(SM_CXICONSPACING);
188 yspacing = GetSystemMetrics(SM_CYICONSPACING);
190 hwndChild = GetWindow( parent, GW_CHILD );
191 while (hwndChild)
193 if( IsIconic( hwndChild ) )
195 WND *wndPtr = WIN_FindWndPtr(hwndChild);
197 WINPOS_ShowIconTitle( wndPtr, FALSE );
199 SetWindowPos( hwndChild, 0, x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2,
200 y - yspacing - GetSystemMetrics(SM_CYICON)/2, 0, 0,
201 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
202 if( IsWindow(hwndChild) )
203 WINPOS_ShowIconTitle(wndPtr , TRUE );
204 WIN_ReleaseWndPtr(wndPtr);
206 if (x <= rectParent.right - xspacing) x += xspacing;
207 else
209 x = rectParent.left;
210 y -= yspacing;
213 hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
215 return yspacing;
219 /***********************************************************************
220 * SwitchToThisWindow16 (USER.172)
222 void WINAPI SwitchToThisWindow16( HWND16 hwnd, BOOL16 restore )
224 SwitchToThisWindow( hwnd, restore );
228 /***********************************************************************
229 * SwitchToThisWindow (USER32.539)
231 void WINAPI SwitchToThisWindow( HWND hwnd, BOOL restore )
233 ShowWindow( hwnd, restore ? SW_RESTORE : SW_SHOWMINIMIZED );
237 /***********************************************************************
238 * GetWindowRect16 (USER.32)
240 void WINAPI GetWindowRect16( HWND16 hwnd, LPRECT16 rect )
242 WND * wndPtr = WIN_FindWndPtr( hwnd );
243 if (!wndPtr) return;
245 CONV_RECT32TO16( &wndPtr->rectWindow, rect );
246 if (wndPtr->dwStyle & WS_CHILD)
247 MapWindowPoints16( wndPtr->parent->hwndSelf, 0, (POINT16 *)rect, 2 );
248 WIN_ReleaseWndPtr(wndPtr);
252 /***********************************************************************
253 * GetWindowRect (USER32.308)
255 BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect )
257 WND * wndPtr = WIN_FindWndPtr( hwnd );
258 if (!wndPtr) return FALSE;
260 *rect = wndPtr->rectWindow;
261 if (wndPtr->dwStyle & WS_CHILD)
262 MapWindowPoints( wndPtr->parent->hwndSelf, 0, (POINT *)rect, 2 );
263 WIN_ReleaseWndPtr(wndPtr);
264 return TRUE;
268 /***********************************************************************
269 * GetWindowRgn
271 BOOL WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
274 RECT rect;
275 WND * wndPtr = WIN_FindWndPtr( hwnd );
276 if (!wndPtr) return (ERROR);
278 FIXME("GetWindowRgn: doesn't really do regions\n");
280 memset (&rect, 0, sizeof(rect));
282 GetWindowRect ( hwnd, &rect );
284 FIXME("Check whether a valid region here\n");
286 SetRectRgn ( hrgn, rect.left, rect.top, rect.right, rect.bottom );
288 WIN_ReleaseWndPtr(wndPtr);
289 return (SIMPLEREGION);
292 /***********************************************************************
293 * SetWindowRgn
295 INT WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn,BOOL bRedraw)
299 FIXME("SetWindowRgn: stub\n");
300 return TRUE;
303 /***********************************************************************
304 * SetWindowRgn16
306 INT16 WINAPI SetWindowRgn16( HWND16 hwnd, HRGN16 hrgn,BOOL16 bRedraw)
310 FIXME("SetWindowRgn16: stub\n");
311 return TRUE;
315 /***********************************************************************
316 * GetClientRect16 (USER.33)
318 void WINAPI GetClientRect16( HWND16 hwnd, LPRECT16 rect )
320 WND * wndPtr = WIN_FindWndPtr( hwnd );
322 rect->left = rect->top = rect->right = rect->bottom = 0;
323 if (wndPtr)
325 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
326 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
328 WIN_ReleaseWndPtr(wndPtr);
332 /***********************************************************************
333 * GetClientRect (USER.220)
335 BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect )
337 WND * wndPtr = WIN_FindWndPtr( hwnd );
339 rect->left = rect->top = rect->right = rect->bottom = 0;
340 if (!wndPtr) return FALSE;
341 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
342 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
344 WIN_ReleaseWndPtr(wndPtr);
345 return TRUE;
349 /*******************************************************************
350 * ClientToScreen16 (USER.28)
352 void WINAPI ClientToScreen16( HWND16 hwnd, LPPOINT16 lppnt )
354 MapWindowPoints16( hwnd, 0, lppnt, 1 );
358 /*******************************************************************
359 * ClientToScreen (USER32.52)
361 BOOL WINAPI ClientToScreen( HWND hwnd, LPPOINT lppnt )
363 MapWindowPoints( hwnd, 0, lppnt, 1 );
364 return TRUE;
368 /*******************************************************************
369 * ScreenToClient16 (USER.29)
371 void WINAPI ScreenToClient16( HWND16 hwnd, LPPOINT16 lppnt )
373 MapWindowPoints16( 0, hwnd, lppnt, 1 );
377 /*******************************************************************
378 * ScreenToClient (USER32.447)
380 BOOL WINAPI ScreenToClient( HWND hwnd, LPPOINT lppnt )
382 MapWindowPoints( 0, hwnd, lppnt, 1 );
383 return TRUE;
387 /***********************************************************************
388 * WINPOS_WindowFromPoint
390 * Find the window and hittest for a given point.
392 INT16 WINPOS_WindowFromPoint( WND* wndScope, POINT16 pt, WND **ppWnd )
394 WND *wndPtr;
395 INT16 hittest = HTERROR;
396 INT16 retvalue;
397 POINT16 xy = pt;
399 *ppWnd = NULL;
400 wndPtr = WIN_LockWndPtr(wndScope->child);
402 if( wndScope->flags & WIN_MANAGED )
404 /* In managed mode we have to check wndScope first as it is also
405 * a window which received the mouse event. */
407 if( wndScope->dwStyle & WS_DISABLED )
409 retvalue = HTERROR;
410 goto end;
412 if( pt.x < wndScope->rectClient.left || pt.x >= wndScope->rectClient.right ||
413 pt.y < wndScope->rectClient.top || pt.y >= wndScope->rectClient.bottom )
414 goto hittest;
416 MapWindowPoints16( GetDesktopWindow16(), wndScope->hwndSelf, &xy, 1 );
418 for (;;)
420 while (wndPtr)
422 /* If point is in window, and window is visible, and it */
423 /* is enabled (or it's a top-level window), then explore */
424 /* its children. Otherwise, go to the next window. */
426 if ((wndPtr->dwStyle & WS_VISIBLE) &&
427 (!(wndPtr->dwStyle & WS_DISABLED) ||
428 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)) &&
429 (xy.x >= wndPtr->rectWindow.left) &&
430 (xy.x < wndPtr->rectWindow.right) &&
431 (xy.y >= wndPtr->rectWindow.top) &&
432 (xy.y < wndPtr->rectWindow.bottom))
434 *ppWnd = wndPtr; /* Got a suitable window */
436 /* If window is minimized or disabled, return at once */
437 if (wndPtr->dwStyle & WS_MINIMIZE)
439 retvalue = HTCAPTION;
440 goto end;
442 if (wndPtr->dwStyle & WS_DISABLED)
444 retvalue = HTERROR;
445 goto end;
448 /* If point is not in client area, ignore the children */
449 if ((xy.x < wndPtr->rectClient.left) ||
450 (xy.x >= wndPtr->rectClient.right) ||
451 (xy.y < wndPtr->rectClient.top) ||
452 (xy.y >= wndPtr->rectClient.bottom)) break;
454 xy.x -= wndPtr->rectClient.left;
455 xy.y -= wndPtr->rectClient.top;
456 WIN_UpdateWndPtr(&wndPtr,wndPtr->child);
458 else
460 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
464 hittest:
465 /* If nothing found, try the scope window */
466 if (!*ppWnd) *ppWnd = wndScope;
468 /* Send the WM_NCHITTEST message (only if to the same task) */
469 if ((*ppWnd)->hmemTaskQ == GetFastQueue16())
471 hittest = (INT16)SendMessage16( (*ppWnd)->hwndSelf, WM_NCHITTEST,
472 0, MAKELONG( pt.x, pt.y ) );
473 if (hittest != HTTRANSPARENT)
475 retvalue = hittest; /* Found the window */
476 goto end;
479 else
481 retvalue = HTCLIENT;
482 goto end;
485 /* If no children found in last search, make point relative to parent */
486 if (!wndPtr)
488 xy.x += (*ppWnd)->rectClient.left;
489 xy.y += (*ppWnd)->rectClient.top;
492 /* Restart the search from the next sibling */
493 WIN_UpdateWndPtr(&wndPtr,(*ppWnd)->next);
494 *ppWnd = (*ppWnd)->parent;
497 end:
498 WIN_ReleaseWndPtr(wndPtr);
499 return retvalue;
503 /*******************************************************************
504 * WindowFromPoint16 (USER.30)
506 HWND16 WINAPI WindowFromPoint16( POINT16 pt )
508 WND *pWnd;
509 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt, &pWnd );
510 WIN_ReleaseDesktop();
511 return pWnd->hwndSelf;
515 /*******************************************************************
516 * WindowFromPoint (USER32.582)
518 HWND WINAPI WindowFromPoint( POINT pt )
520 WND *pWnd;
521 POINT16 pt16;
522 CONV_POINT32TO16( &pt, &pt16 );
523 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16, &pWnd );
524 WIN_ReleaseDesktop();
525 return (HWND)pWnd->hwndSelf;
529 /*******************************************************************
530 * ChildWindowFromPoint16 (USER.191)
532 HWND16 WINAPI ChildWindowFromPoint16( HWND16 hwndParent, POINT16 pt )
534 POINT pt32;
535 CONV_POINT16TO32( &pt, &pt32 );
536 return (HWND16)ChildWindowFromPoint( hwndParent, pt32 );
540 /*******************************************************************
541 * ChildWindowFromPoint (USER32.49)
543 HWND WINAPI ChildWindowFromPoint( HWND hwndParent, POINT pt )
545 /* pt is in the client coordinates */
547 WND* wnd = WIN_FindWndPtr(hwndParent);
548 RECT rect;
549 HWND retvalue;
551 if( !wnd ) return 0;
553 /* get client rect fast */
554 rect.top = rect.left = 0;
555 rect.right = wnd->rectClient.right - wnd->rectClient.left;
556 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
558 if (!PtInRect( &rect, pt ))
560 retvalue = 0;
561 goto end;
563 WIN_UpdateWndPtr(&wnd,wnd->child);
564 while ( wnd )
566 if (PtInRect( &wnd->rectWindow, pt ))
568 retvalue = wnd->hwndSelf;
569 goto end;
571 WIN_UpdateWndPtr(&wnd,wnd->next);
573 retvalue = hwndParent;
574 end:
575 WIN_ReleaseWndPtr(wnd);
576 return retvalue;
579 /*******************************************************************
580 * ChildWindowFromPointEx16 (USER.50)
582 HWND16 WINAPI ChildWindowFromPointEx16( HWND16 hwndParent, POINT16 pt, UINT16 uFlags)
584 POINT pt32;
585 CONV_POINT16TO32( &pt, &pt32 );
586 return (HWND16)ChildWindowFromPointEx( hwndParent, pt32, uFlags );
590 /*******************************************************************
591 * ChildWindowFromPointEx32 (USER32.50)
593 HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt,
594 UINT uFlags)
596 /* pt is in the client coordinates */
598 WND* wnd = WIN_FindWndPtr(hwndParent);
599 RECT rect;
600 HWND retvalue;
602 if( !wnd ) return 0;
604 /* get client rect fast */
605 rect.top = rect.left = 0;
606 rect.right = wnd->rectClient.right - wnd->rectClient.left;
607 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
609 if (!PtInRect( &rect, pt ))
611 retvalue = 0;
612 goto end;
614 WIN_UpdateWndPtr(&wnd,wnd->child);
616 while ( wnd )
618 if (PtInRect( &wnd->rectWindow, pt )) {
619 if ( (uFlags & CWP_SKIPINVISIBLE) &&
620 !(wnd->dwStyle & WS_VISIBLE) );
621 else if ( (uFlags & CWP_SKIPDISABLED) &&
622 (wnd->dwStyle & WS_DISABLED) );
623 else if ( (uFlags & CWP_SKIPTRANSPARENT) &&
624 (wnd->dwExStyle & WS_EX_TRANSPARENT) );
625 else
627 retvalue = wnd->hwndSelf;
628 goto end;
632 WIN_UpdateWndPtr(&wnd,wnd->next);
634 retvalue = hwndParent;
635 end:
636 WIN_ReleaseWndPtr(wnd);
637 return retvalue;
641 /*******************************************************************
642 * WINPOS_GetWinOffset
644 * Calculate the offset between the origin of the two windows. Used
645 * to implement MapWindowPoints.
647 static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo,
648 POINT *offset )
650 WND * wndPtr = 0;
652 offset->x = offset->y = 0;
653 if (hwndFrom == hwndTo ) return;
655 /* Translate source window origin to screen coords */
656 if (hwndFrom)
658 if (!(wndPtr = WIN_FindWndPtr( hwndFrom )))
660 ERR("bad hwndFrom = %04x\n",hwndFrom);
661 return;
663 while (wndPtr->parent)
665 offset->x += wndPtr->rectClient.left;
666 offset->y += wndPtr->rectClient.top;
667 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
669 WIN_ReleaseWndPtr(wndPtr);
672 /* Translate origin to destination window coords */
673 if (hwndTo)
675 if (!(wndPtr = WIN_FindWndPtr( hwndTo )))
677 ERR("bad hwndTo = %04x\n", hwndTo );
678 return;
680 while (wndPtr->parent)
682 offset->x -= wndPtr->rectClient.left;
683 offset->y -= wndPtr->rectClient.top;
684 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
686 WIN_ReleaseWndPtr(wndPtr);
691 /*******************************************************************
692 * MapWindowPoints16 (USER.258)
694 void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
695 LPPOINT16 lppt, UINT16 count )
697 POINT offset;
699 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
700 while (count--)
702 lppt->x += offset.x;
703 lppt->y += offset.y;
704 lppt++;
709 /*******************************************************************
710 * MapWindowPoints (USER32.386)
712 INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo,
713 LPPOINT lppt, UINT count )
715 POINT offset;
717 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
718 while (count--)
720 lppt->x += offset.x;
721 lppt->y += offset.y;
722 lppt++;
724 return MAKELONG( LOWORD(offset.x), LOWORD(offset.y) );
728 /***********************************************************************
729 * IsIconic16 (USER.31)
731 BOOL16 WINAPI IsIconic16(HWND16 hWnd)
733 return IsIconic(hWnd);
737 /***********************************************************************
738 * IsIconic (USER32.345)
740 BOOL WINAPI IsIconic(HWND hWnd)
742 BOOL retvalue;
743 WND * wndPtr = WIN_FindWndPtr(hWnd);
744 if (wndPtr == NULL) return FALSE;
745 retvalue = (wndPtr->dwStyle & WS_MINIMIZE) != 0;
746 WIN_ReleaseWndPtr(wndPtr);
747 return retvalue;
751 /***********************************************************************
752 * IsZoomed (USER.272)
754 BOOL16 WINAPI IsZoomed16(HWND16 hWnd)
756 return IsZoomed(hWnd);
760 /***********************************************************************
761 * IsZoomed (USER.352)
763 BOOL WINAPI IsZoomed(HWND hWnd)
765 BOOL retvalue;
766 WND * wndPtr = WIN_FindWndPtr(hWnd);
767 if (wndPtr == NULL) return FALSE;
768 retvalue = (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
769 WIN_ReleaseWndPtr(wndPtr);
770 return retvalue;
774 /*******************************************************************
775 * GetActiveWindow (USER.60)
777 HWND16 WINAPI GetActiveWindow16(void)
779 return (HWND16)GetActiveWindow();
782 /*******************************************************************
783 * GetActiveWindow (USER32.205)
785 HWND WINAPI GetActiveWindow(void)
787 MESSAGEQUEUE *pCurMsgQ = 0;
788 HWND hwndActive = 0;
790 /* Get the messageQ for the current thread */
791 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
793 WARN("\tCurrent message queue not found. Exiting!\n" );
794 return 0;
797 /* Return the current active window from the perQ data of the current message Q */
798 hwndActive = PERQDATA_GetActiveWnd( pCurMsgQ->pQData );
800 QUEUE_Unlock( pCurMsgQ );
801 return hwndActive;
805 /*******************************************************************
806 * WINPOS_CanActivate
808 static BOOL WINPOS_CanActivate(WND* pWnd)
810 if( pWnd && !(pWnd->dwStyle & (WS_DISABLED | WS_CHILD)) ) return TRUE;
811 return FALSE;
815 /*******************************************************************
816 * SetActiveWindow16 (USER.59)
818 HWND16 WINAPI SetActiveWindow16( HWND16 hwnd )
820 return SetActiveWindow(hwnd);
824 /*******************************************************************
825 * SetActiveWindow (USER32.463)
827 HWND WINAPI SetActiveWindow( HWND hwnd )
829 HWND prev = 0;
830 WND *wndPtr = WIN_FindWndPtr( hwnd );
831 MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
833 if ( !WINPOS_CanActivate(wndPtr) )
835 prev = 0;
836 goto end;
839 /* Get the messageQ for the current thread */
840 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
842 WARN("\tCurrent message queue not found. Exiting!\n" );
843 goto CLEANUP;
846 /* Retrieve the message queue associated with this window */
847 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
848 if ( !pMsgQ )
850 WARN("\tWindow message queue not found. Exiting!\n" );
851 goto CLEANUP;
854 /* Make sure that the window is associated with the calling threads
855 * message queue. It must share the same perQ data.
858 if ( pCurMsgQ->pQData != pMsgQ->pQData )
859 goto CLEANUP;
861 /* Save current active window */
862 prev = PERQDATA_GetActiveWnd( pMsgQ->pQData );
864 WINPOS_SetActiveWindow( hwnd, 0, 0 );
866 CLEANUP:
867 /* Unlock the queues before returning */
868 if ( pMsgQ )
869 QUEUE_Unlock( pMsgQ );
870 if ( pCurMsgQ )
871 QUEUE_Unlock( pCurMsgQ );
873 end:
874 WIN_ReleaseWndPtr(wndPtr);
875 return prev;
879 /*******************************************************************
880 * GetForegroundWindow16 (USER.608)
882 HWND16 WINAPI GetForegroundWindow16(void)
884 return (HWND16)GetForegroundWindow();
888 /*******************************************************************
889 * SetForegroundWindow16 (USER.609)
891 BOOL16 WINAPI SetForegroundWindow16( HWND16 hwnd )
893 return SetForegroundWindow( hwnd );
897 /*******************************************************************
898 * GetForegroundWindow (USER32.241)
900 HWND WINAPI GetForegroundWindow(void)
902 HWND hwndActive = 0;
904 /* Get the foreground window (active window of hActiveQueue) */
905 if ( hActiveQueue )
907 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
908 if ( pActiveQueue )
909 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
911 QUEUE_Unlock( pActiveQueue );
914 return hwndActive;
917 /*******************************************************************
918 * SetForegroundWindow (USER32.482)
920 BOOL WINAPI SetForegroundWindow( HWND hwnd )
922 return WINPOS_ChangeActiveWindow( hwnd, FALSE );
926 /*******************************************************************
927 * GetShellWindow16 (USER.600)
929 HWND16 WINAPI GetShellWindow16(void)
931 return GetShellWindow();
934 /*******************************************************************
935 * SetShellWindow (USER32.504)
937 HWND WINAPI SetShellWindow(HWND hwndshell)
938 { WARN("(hWnd=%08x) semi stub\n",hwndshell );
940 hGlobalShellWindow = hwndshell;
941 return hGlobalShellWindow;
945 /*******************************************************************
946 * GetShellWindow (USER32.287)
948 HWND WINAPI GetShellWindow(void)
949 { WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow );
951 return hGlobalShellWindow;
955 /***********************************************************************
956 * BringWindowToTop16 (USER.45)
958 BOOL16 WINAPI BringWindowToTop16( HWND16 hwnd )
960 return BringWindowToTop(hwnd);
964 /***********************************************************************
965 * BringWindowToTop (USER32.11)
967 BOOL WINAPI BringWindowToTop( HWND hwnd )
969 return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
973 /***********************************************************************
974 * MoveWindow16 (USER.56)
976 BOOL16 WINAPI MoveWindow16( HWND16 hwnd, INT16 x, INT16 y, INT16 cx, INT16 cy,
977 BOOL16 repaint )
979 return MoveWindow(hwnd,x,y,cx,cy,repaint);
983 /***********************************************************************
984 * MoveWindow (USER32.399)
986 BOOL WINAPI MoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy,
987 BOOL repaint )
989 int flags = SWP_NOZORDER | SWP_NOACTIVATE;
990 if (!repaint) flags |= SWP_NOREDRAW;
991 TRACE("%04x %d,%d %dx%d %d\n",
992 hwnd, x, y, cx, cy, repaint );
993 return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
996 /***********************************************************************
997 * WINPOS_InitInternalPos
999 static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT pt,
1000 LPRECT restoreRect )
1002 LPINTERNALPOS lpPos = (LPINTERNALPOS) GetPropA( wnd->hwndSelf,
1003 atomInternalPos );
1004 if( !lpPos )
1006 /* this happens when the window is minimized/maximized
1007 * for the first time (rectWindow is not adjusted yet) */
1009 lpPos = HeapAlloc( SystemHeap, 0, sizeof(INTERNALPOS) );
1010 if( !lpPos ) return NULL;
1012 SetPropA( wnd->hwndSelf, atomInternalPos, (HANDLE)lpPos );
1013 lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
1014 CONV_RECT32TO16( &wnd->rectWindow, &lpPos->rectNormal );
1015 *(UINT*)&lpPos->ptIconPos = *(UINT*)&lpPos->ptMaxPos = 0xFFFFFFFF;
1018 if( wnd->dwStyle & WS_MINIMIZE )
1019 CONV_POINT32TO16( &pt, &lpPos->ptIconPos );
1020 else if( wnd->dwStyle & WS_MAXIMIZE )
1021 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1022 else if( restoreRect )
1023 CONV_RECT32TO16( restoreRect, &lpPos->rectNormal );
1025 return lpPos;
1028 /***********************************************************************
1029 * WINPOS_RedrawIconTitle
1031 BOOL WINPOS_RedrawIconTitle( HWND hWnd )
1033 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hWnd, atomInternalPos );
1034 if( lpPos )
1036 if( lpPos->hwndIconTitle )
1038 SendMessageA( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
1039 InvalidateRect( lpPos->hwndIconTitle, NULL, TRUE );
1040 return TRUE;
1043 return FALSE;
1046 /***********************************************************************
1047 * WINPOS_ShowIconTitle
1049 BOOL WINPOS_ShowIconTitle( WND* pWnd, BOOL bShow )
1051 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( pWnd->hwndSelf, atomInternalPos );
1053 if( lpPos && !(pWnd->flags & WIN_MANAGED))
1055 HWND16 hWnd = lpPos->hwndIconTitle;
1057 TRACE("0x%04x %i\n", pWnd->hwndSelf, (bShow != 0) );
1059 if( !hWnd )
1060 lpPos->hwndIconTitle = hWnd = ICONTITLE_Create( pWnd );
1061 if( bShow )
1063 if( ( pWnd = WIN_FindWndPtr(hWnd) ) != NULL)
1065 if( !(pWnd->dwStyle & WS_VISIBLE) )
1067 SendMessageA( hWnd, WM_SHOWWINDOW, TRUE, 0 );
1068 SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
1069 SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
1071 WIN_ReleaseWndPtr(pWnd);
1074 else ShowWindow( hWnd, SW_HIDE );
1076 return FALSE;
1079 /*******************************************************************
1080 * WINPOS_GetMinMaxInfo
1082 * Get the minimized and maximized information for a window.
1084 void WINPOS_GetMinMaxInfo( WND *wndPtr, POINT *maxSize, POINT *maxPos,
1085 POINT *minTrack, POINT *maxTrack )
1087 LPINTERNALPOS lpPos;
1088 MINMAXINFO MinMax;
1089 INT xinc, yinc;
1091 /* Compute default values */
1093 MinMax.ptMaxSize.x = GetSystemMetrics(SM_CXSCREEN);
1094 MinMax.ptMaxSize.y = GetSystemMetrics(SM_CYSCREEN);
1095 MinMax.ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
1096 MinMax.ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
1097 MinMax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXSCREEN);
1098 MinMax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYSCREEN);
1100 if (wndPtr->flags & WIN_MANAGED) xinc = yinc = 0;
1101 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1103 xinc = GetSystemMetrics(SM_CXDLGFRAME);
1104 yinc = GetSystemMetrics(SM_CYDLGFRAME);
1106 else
1108 xinc = yinc = 0;
1109 if (HAS_THICKFRAME(wndPtr->dwStyle))
1111 xinc += GetSystemMetrics(SM_CXFRAME);
1112 yinc += GetSystemMetrics(SM_CYFRAME);
1114 if (wndPtr->dwStyle & WS_BORDER)
1116 xinc += GetSystemMetrics(SM_CXBORDER);
1117 yinc += GetSystemMetrics(SM_CYBORDER);
1120 MinMax.ptMaxSize.x += 2 * xinc;
1121 MinMax.ptMaxSize.y += 2 * yinc;
1123 lpPos = (LPINTERNALPOS)GetPropA( wndPtr->hwndSelf, atomInternalPos );
1124 if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
1125 CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
1126 else
1128 MinMax.ptMaxPosition.x = -xinc;
1129 MinMax.ptMaxPosition.y = -yinc;
1132 SendMessageA( wndPtr->hwndSelf, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
1134 /* Some sanity checks */
1136 TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1137 MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
1138 MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
1139 MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
1140 MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
1141 MinMax.ptMaxTrackSize.x = MAX( MinMax.ptMaxTrackSize.x,
1142 MinMax.ptMinTrackSize.x );
1143 MinMax.ptMaxTrackSize.y = MAX( MinMax.ptMaxTrackSize.y,
1144 MinMax.ptMinTrackSize.y );
1146 if (maxSize) *maxSize = MinMax.ptMaxSize;
1147 if (maxPos) *maxPos = MinMax.ptMaxPosition;
1148 if (minTrack) *minTrack = MinMax.ptMinTrackSize;
1149 if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
1152 /***********************************************************************
1153 * WINPOS_MinMaximize
1155 * Fill in lpRect and return additional flags to be used with SetWindowPos().
1156 * This function assumes that 'cmd' is different from the current window
1157 * state.
1159 UINT WINPOS_MinMaximize( WND* wndPtr, UINT16 cmd, LPRECT16 lpRect )
1161 UINT swpFlags = 0;
1162 POINT pt, size;
1163 LPINTERNALPOS lpPos;
1165 TRACE("0x%04x %u\n", wndPtr->hwndSelf, cmd );
1167 size.x = wndPtr->rectWindow.left; size.y = wndPtr->rectWindow.top;
1168 lpPos = WINPOS_InitInternalPos( wndPtr, size, &wndPtr->rectWindow );
1170 if (lpPos && !HOOK_CallHooks16(WH_CBT, HCBT_MINMAX, wndPtr->hwndSelf, cmd))
1172 if( wndPtr->dwStyle & WS_MINIMIZE )
1174 if( !SendMessageA( wndPtr->hwndSelf, WM_QUERYOPEN, 0, 0L ) )
1175 return (SWP_NOSIZE | SWP_NOMOVE);
1176 swpFlags |= SWP_NOCOPYBITS;
1178 switch( cmd )
1180 case SW_MINIMIZE:
1181 if( wndPtr->dwStyle & WS_MAXIMIZE)
1183 wndPtr->flags |= WIN_RESTORE_MAX;
1184 wndPtr->dwStyle &= ~WS_MAXIMIZE;
1186 else
1187 wndPtr->flags &= ~WIN_RESTORE_MAX;
1188 wndPtr->dwStyle |= WS_MINIMIZE;
1190 if( wndPtr->flags & WIN_NATIVE )
1191 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, TRUE ) )
1192 swpFlags |= MINMAX_NOSWP;
1194 lpPos->ptIconPos = WINPOS_FindIconPos( wndPtr, lpPos->ptIconPos );
1196 SetRect16( lpRect, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1197 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON) );
1198 swpFlags |= SWP_NOCOPYBITS;
1199 break;
1201 case SW_MAXIMIZE:
1202 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1203 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL );
1204 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1206 if( wndPtr->dwStyle & WS_MINIMIZE )
1208 if( wndPtr->flags & WIN_NATIVE )
1209 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
1210 swpFlags |= MINMAX_NOSWP;
1212 WINPOS_ShowIconTitle( wndPtr, FALSE );
1213 wndPtr->dwStyle &= ~WS_MINIMIZE;
1215 wndPtr->dwStyle |= WS_MAXIMIZE;
1217 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1218 size.x, size.y );
1219 break;
1221 case SW_RESTORE:
1222 if( wndPtr->dwStyle & WS_MINIMIZE )
1224 if( wndPtr->flags & WIN_NATIVE )
1225 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
1226 swpFlags |= MINMAX_NOSWP;
1228 wndPtr->dwStyle &= ~WS_MINIMIZE;
1229 WINPOS_ShowIconTitle( wndPtr, FALSE );
1231 if( wndPtr->flags & WIN_RESTORE_MAX)
1233 /* Restore to maximized position */
1234 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1235 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL);
1236 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1237 wndPtr->dwStyle |= WS_MAXIMIZE;
1238 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y, size.x, size.y );
1239 break;
1242 else
1243 if( !(wndPtr->dwStyle & WS_MAXIMIZE) ) return (UINT16)(-1);
1244 else wndPtr->dwStyle &= ~WS_MAXIMIZE;
1246 /* Restore to normal position */
1248 *lpRect = lpPos->rectNormal;
1249 lpRect->right -= lpRect->left;
1250 lpRect->bottom -= lpRect->top;
1252 break;
1254 } else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
1255 return swpFlags;
1258 /***********************************************************************
1259 * ShowWindowAsync (USER32.535)
1261 * doesn't wait; returns immediately.
1262 * used by threads to toggle windows in other (possibly hanging) threads
1264 BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd )
1266 /* FIXME: does ShowWindow() return immediately ? */
1267 return ShowWindow(hwnd, cmd);
1271 /***********************************************************************
1272 * ShowWindow16 (USER.42)
1274 BOOL16 WINAPI ShowWindow16( HWND16 hwnd, INT16 cmd )
1276 return ShowWindow(hwnd,cmd);
1280 /***********************************************************************
1281 * ShowWindow (USER32.534)
1283 BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
1285 WND* wndPtr = WIN_FindWndPtr( hwnd );
1286 BOOL wasVisible, showFlag;
1287 RECT16 newPos = {0, 0, 0, 0};
1288 UINT swp = 0;
1290 if (!wndPtr) return FALSE;
1292 TRACE("hwnd=%04x, cmd=%d\n", hwnd, cmd);
1294 wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
1296 switch(cmd)
1298 case SW_HIDE:
1299 if (!wasVisible) goto END;;
1300 swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
1301 SWP_NOACTIVATE | SWP_NOZORDER;
1302 break;
1304 case SW_SHOWMINNOACTIVE:
1305 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1306 /* fall through */
1307 case SW_SHOWMINIMIZED:
1308 swp |= SWP_SHOWWINDOW;
1309 /* fall through */
1310 case SW_MINIMIZE:
1311 swp |= SWP_FRAMECHANGED;
1312 if( !(wndPtr->dwStyle & WS_MINIMIZE) )
1313 swp |= WINPOS_MinMaximize( wndPtr, SW_MINIMIZE, &newPos );
1314 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1315 break;
1317 case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
1318 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1319 if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
1320 swp |= WINPOS_MinMaximize( wndPtr, SW_MAXIMIZE, &newPos );
1321 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1322 break;
1324 case SW_SHOWNA:
1325 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1326 /* fall through */
1327 case SW_SHOW:
1328 swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
1331 * ShowWindow has a little peculiar behavior that if the
1332 * window is already the topmost window, it will not
1333 * activate it.
1335 if (GetTopWindow((HWND)0)==hwnd && (wasVisible || GetActiveWindow() == hwnd))
1336 swp |= SWP_NOACTIVATE;
1338 break;
1340 case SW_SHOWNOACTIVATE:
1341 swp |= SWP_NOZORDER;
1342 if (GetActiveWindow()) swp |= SWP_NOACTIVATE;
1343 /* fall through */
1344 case SW_SHOWNORMAL: /* same as SW_NORMAL: */
1345 case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
1346 case SW_RESTORE:
1347 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1349 if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) )
1350 swp |= WINPOS_MinMaximize( wndPtr, SW_RESTORE, &newPos );
1351 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1352 break;
1355 showFlag = (cmd != SW_HIDE);
1356 if (showFlag != wasVisible)
1358 SendMessageA( hwnd, WM_SHOWWINDOW, showFlag, 0 );
1359 if (!IsWindow( hwnd )) goto END;
1362 if ((wndPtr->dwStyle & WS_CHILD) &&
1363 !IsWindowVisible( wndPtr->parent->hwndSelf ) &&
1364 (swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE) )
1366 /* Don't call SetWindowPos() on invisible child windows */
1367 if (cmd == SW_HIDE) wndPtr->dwStyle &= ~WS_VISIBLE;
1368 else wndPtr->dwStyle |= WS_VISIBLE;
1370 else
1372 /* We can't activate a child window */
1373 if ((wndPtr->dwStyle & WS_CHILD) &&
1374 !(wndPtr->dwExStyle & WS_EX_MDICHILD))
1375 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1376 if (!(swp & MINMAX_NOSWP))
1378 SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top,
1379 newPos.right, newPos.bottom, LOWORD(swp) );
1380 if (cmd == SW_HIDE)
1382 /* FIXME: This will cause the window to be activated irrespective
1383 * of whether it is owned by the same thread. Has to be done
1384 * asynchronously.
1387 if (hwnd == GetActiveWindow())
1388 WINPOS_ActivateOtherWindow(wndPtr);
1390 /* Revert focus to parent */
1391 if (hwnd == GetFocus() || IsChild(hwnd, GetFocus()))
1392 SetFocus( GetParent(hwnd) );
1395 if (!IsWindow( hwnd )) goto END;
1396 else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( wndPtr, TRUE );
1399 if (wndPtr->flags & WIN_NEED_SIZE)
1401 /* should happen only in CreateWindowEx() */
1402 int wParam = SIZE_RESTORED;
1404 wndPtr->flags &= ~WIN_NEED_SIZE;
1405 if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
1406 else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
1407 SendMessageA( hwnd, WM_SIZE, wParam,
1408 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
1409 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
1410 SendMessageA( hwnd, WM_MOVE, 0,
1411 MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
1414 END:
1415 WIN_ReleaseWndPtr(wndPtr);
1416 return wasVisible;
1420 /***********************************************************************
1421 * GetInternalWindowPos16 (USER.460)
1423 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
1424 LPPOINT16 ptIcon )
1426 WINDOWPLACEMENT16 wndpl;
1427 if (GetWindowPlacement16( hwnd, &wndpl ))
1429 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1430 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1431 return wndpl.showCmd;
1433 return 0;
1437 /***********************************************************************
1438 * GetInternalWindowPos (USER32.245)
1440 UINT WINAPI GetInternalWindowPos( HWND hwnd, LPRECT rectWnd,
1441 LPPOINT ptIcon )
1443 WINDOWPLACEMENT wndpl;
1444 if (GetWindowPlacement( hwnd, &wndpl ))
1446 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1447 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1448 return wndpl.showCmd;
1450 return 0;
1453 /***********************************************************************
1454 * GetWindowPlacement16 (USER.370)
1456 BOOL16 WINAPI GetWindowPlacement16( HWND16 hwnd, WINDOWPLACEMENT16 *wndpl )
1458 WND *pWnd = WIN_FindWndPtr( hwnd );
1459 LPINTERNALPOS lpPos;
1461 if(!pWnd ) return FALSE;
1463 lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1464 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1465 wndpl->length = sizeof(*wndpl);
1466 if( pWnd->dwStyle & WS_MINIMIZE )
1467 wndpl->showCmd = SW_SHOWMINIMIZED;
1468 else
1469 wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE )
1470 ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
1471 if( pWnd->flags & WIN_RESTORE_MAX )
1472 wndpl->flags = WPF_RESTORETOMAXIMIZED;
1473 else
1474 wndpl->flags = 0;
1475 wndpl->ptMinPosition = lpPos->ptIconPos;
1476 wndpl->ptMaxPosition = lpPos->ptMaxPos;
1477 wndpl->rcNormalPosition = lpPos->rectNormal;
1479 WIN_ReleaseWndPtr(pWnd);
1480 return TRUE;
1484 /***********************************************************************
1485 * GetWindowPlacement (USER32.307)
1487 * Win95:
1488 * Fails if wndpl->length of Win95 (!) apps is invalid.
1490 BOOL WINAPI GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *pwpl32 )
1492 if( pwpl32 )
1494 WINDOWPLACEMENT16 wpl;
1495 wpl.length = sizeof(wpl);
1496 if( GetWindowPlacement16( hwnd, &wpl ) )
1498 pwpl32->length = sizeof(*pwpl32);
1499 pwpl32->flags = wpl.flags;
1500 pwpl32->showCmd = wpl.showCmd;
1501 CONV_POINT16TO32( &wpl.ptMinPosition, &pwpl32->ptMinPosition );
1502 CONV_POINT16TO32( &wpl.ptMaxPosition, &pwpl32->ptMaxPosition );
1503 CONV_RECT16TO32( &wpl.rcNormalPosition, &pwpl32->rcNormalPosition );
1504 return TRUE;
1507 return FALSE;
1511 /***********************************************************************
1512 * WINPOS_SetPlacement
1514 static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT16 *wndpl,
1515 UINT flags )
1517 WND *pWnd = WIN_FindWndPtr( hwnd );
1518 if( pWnd )
1520 LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1521 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1523 if( flags & PLACE_MIN ) lpPos->ptIconPos = wndpl->ptMinPosition;
1524 if( flags & PLACE_MAX ) lpPos->ptMaxPos = wndpl->ptMaxPosition;
1525 if( flags & PLACE_RECT) lpPos->rectNormal = wndpl->rcNormalPosition;
1527 if( pWnd->dwStyle & WS_MINIMIZE )
1529 WINPOS_ShowIconTitle( pWnd, FALSE );
1530 if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1531 SetWindowPos( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1532 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1534 else if( pWnd->dwStyle & WS_MAXIMIZE )
1536 if( !EMPTYPOINT(lpPos->ptMaxPos) )
1537 SetWindowPos( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1538 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1540 else if( flags & PLACE_RECT )
1541 SetWindowPos( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1542 lpPos->rectNormal.right - lpPos->rectNormal.left,
1543 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1544 SWP_NOZORDER | SWP_NOACTIVATE );
1546 ShowWindow( hwnd, wndpl->showCmd );
1547 if( IsWindow(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1549 if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd, TRUE );
1551 /* SDK: ...valid only the next time... */
1552 if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1554 WIN_ReleaseWndPtr(pWnd);
1555 return TRUE;
1557 return FALSE;
1561 /***********************************************************************
1562 * SetWindowPlacement16 (USER.371)
1564 BOOL16 WINAPI SetWindowPlacement16(HWND16 hwnd, const WINDOWPLACEMENT16 *wndpl)
1566 return WINPOS_SetPlacement( hwnd, wndpl,
1567 PLACE_MIN | PLACE_MAX | PLACE_RECT );
1570 /***********************************************************************
1571 * SetWindowPlacement (USER32.519)
1573 * Win95:
1574 * Fails if wndpl->length of Win95 (!) apps is invalid.
1576 BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *pwpl32 )
1578 if( pwpl32 )
1580 WINDOWPLACEMENT16 wpl;
1582 wpl.length = sizeof(WINDOWPLACEMENT16);
1583 wpl.flags = pwpl32->flags;
1584 wpl.showCmd = pwpl32->showCmd;
1585 wpl.ptMinPosition.x = pwpl32->ptMinPosition.x;
1586 wpl.ptMinPosition.y = pwpl32->ptMinPosition.y;
1587 wpl.ptMaxPosition.x = pwpl32->ptMaxPosition.x;
1588 wpl.ptMaxPosition.y = pwpl32->ptMaxPosition.y;
1589 wpl.rcNormalPosition.left = pwpl32->rcNormalPosition.left;
1590 wpl.rcNormalPosition.top = pwpl32->rcNormalPosition.top;
1591 wpl.rcNormalPosition.right = pwpl32->rcNormalPosition.right;
1592 wpl.rcNormalPosition.bottom = pwpl32->rcNormalPosition.bottom;
1594 return WINPOS_SetPlacement( hwnd, &wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1596 return FALSE;
1600 /***********************************************************************
1601 * SetInternalWindowPos16 (USER.461)
1603 void WINAPI SetInternalWindowPos16( HWND16 hwnd, UINT16 showCmd,
1604 LPRECT16 rect, LPPOINT16 pt )
1606 if( IsWindow16(hwnd) )
1608 WINDOWPLACEMENT16 wndpl;
1609 UINT flags;
1611 wndpl.length = sizeof(wndpl);
1612 wndpl.showCmd = showCmd;
1613 wndpl.flags = flags = 0;
1615 if( pt )
1617 flags |= PLACE_MIN;
1618 wndpl.flags |= WPF_SETMINPOSITION;
1619 wndpl.ptMinPosition = *pt;
1621 if( rect )
1623 flags |= PLACE_RECT;
1624 wndpl.rcNormalPosition = *rect;
1626 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1631 /***********************************************************************
1632 * SetInternalWindowPos (USER32.483)
1634 void WINAPI SetInternalWindowPos( HWND hwnd, UINT showCmd,
1635 LPRECT rect, LPPOINT pt )
1637 if( IsWindow(hwnd) )
1639 WINDOWPLACEMENT16 wndpl;
1640 UINT flags;
1642 wndpl.length = sizeof(wndpl);
1643 wndpl.showCmd = showCmd;
1644 wndpl.flags = flags = 0;
1646 if( pt )
1648 flags |= PLACE_MIN;
1649 wndpl.flags |= WPF_SETMINPOSITION;
1650 CONV_POINT32TO16( pt, &wndpl.ptMinPosition );
1652 if( rect )
1654 flags |= PLACE_RECT;
1655 CONV_RECT32TO16( rect, &wndpl.rcNormalPosition );
1657 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1661 /*******************************************************************
1662 * WINPOS_SetActiveWindow
1664 * SetActiveWindow() back-end. This is the only function that
1665 * can assign active status to a window. It must be called only
1666 * for the top level windows.
1668 BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
1670 CBTACTIVATESTRUCT16* cbtStruct;
1671 WND* wndPtr=0, *wndTemp;
1672 HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1673 MESSAGEQUEUE *pOldActiveQueue = 0, *pNewActiveQueue = 0;
1674 WORD wIconized = 0;
1675 HWND hwndActive = 0;
1676 BOOL bRet = 0;
1678 TRACE("(%04x, %d, %d)\n", hWnd, fMouse, fChangeFocus );
1680 /* Get current active window from the active queue */
1681 if ( hActiveQueue )
1683 pOldActiveQueue = QUEUE_Lock( hActiveQueue );
1684 if ( pOldActiveQueue )
1685 hwndActive = PERQDATA_GetActiveWnd( pOldActiveQueue->pQData );
1688 /* paranoid checks */
1689 if( hWnd == GetDesktopWindow() || (bRet = (hWnd == hwndActive)) )
1690 goto CLEANUP_END;
1692 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1693 * return 0;
1695 wndPtr = WIN_FindWndPtr(hWnd);
1696 hOldActiveQueue = hActiveQueue;
1698 if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1700 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1701 WIN_ReleaseWndPtr(wndTemp);
1703 else
1704 TRACE("no current active window.\n");
1706 /* call CBT hook chain */
1707 if ((cbtStruct = SEGPTR_NEW(CBTACTIVATESTRUCT16)))
1709 cbtStruct->fMouse = fMouse;
1710 cbtStruct->hWndActive = hwndActive;
1711 bRet = (BOOL)HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
1712 (LPARAM)SEGPTR_GET(cbtStruct) );
1713 SEGPTR_FREE(cbtStruct);
1714 if (bRet) goto CLEANUP_END;
1717 /* set prev active wnd to current active wnd and send notification */
1718 if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
1720 MESSAGEQUEUE *pTempActiveQueue = 0;
1722 if (!SendMessageA( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1724 if (GetSysModalWindow16() != hWnd)
1725 goto CLEANUP_END;
1726 /* disregard refusal if hWnd is sysmodal */
1729 SendMessageA( hwndPrevActive, WM_ACTIVATE,
1730 MAKEWPARAM( WA_INACTIVE, wIconized ),
1731 (LPARAM)hWnd );
1733 /* check if something happened during message processing
1734 * (global active queue may have changed)
1736 pTempActiveQueue = QUEUE_Lock( hActiveQueue );
1737 if(!pTempActiveQueue)
1738 goto CLEANUP_END;
1740 hwndActive = PERQDATA_GetActiveWnd( pTempActiveQueue->pQData );
1741 QUEUE_Unlock( pTempActiveQueue );
1742 if( hwndPrevActive != hwndActive )
1743 goto CLEANUP_END;
1746 /* Set new active window in the message queue */
1747 hwndActive = hWnd;
1748 if ( wndPtr )
1750 pNewActiveQueue = QUEUE_Lock( wndPtr->hmemTaskQ );
1751 if ( pNewActiveQueue )
1752 PERQDATA_SetActiveWnd( pNewActiveQueue->pQData, hwndActive );
1754 else /* have to do this or MDI frame activation goes to hell */
1755 if( pOldActiveQueue )
1756 PERQDATA_SetActiveWnd( pOldActiveQueue->pQData, 0 );
1758 /* send palette messages */
1759 if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1760 SendMessage16((HWND16)-1, WM_PALETTEISCHANGING, (WPARAM16)hWnd, 0L );
1762 /* if prev wnd is minimized redraw icon title */
1763 if( IsIconic( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1765 /* managed windows will get ConfigureNotify event */
1766 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->flags & WIN_MANAGED))
1768 /* check Z-order and bring hWnd to the top */
1769 for (wndTemp = WIN_LockWndPtr(WIN_GetDesktop()->child); wndTemp; WIN_UpdateWndPtr(&wndTemp,wndTemp->next))
1771 if (wndTemp->dwStyle & WS_VISIBLE) break;
1773 WIN_ReleaseDesktop();
1774 WIN_ReleaseWndPtr(wndTemp);
1776 if( wndTemp != wndPtr )
1777 SetWindowPos(hWnd, HWND_TOP, 0,0,0,0,
1778 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1779 if (!IsWindow(hWnd))
1780 goto CLEANUP;
1783 /* Get a handle to the new active queue */
1784 hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1786 /* send WM_ACTIVATEAPP if necessary */
1787 if (hOldActiveQueue != hNewActiveQueue)
1789 WND **list, **ppWnd;
1790 WND *pDesktop = WIN_GetDesktop();
1792 if ((list = WIN_BuildWinArray( pDesktop, 0, NULL )))
1794 for (ppWnd = list; *ppWnd; ppWnd++)
1796 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1798 if ((*ppWnd)->hmemTaskQ == hOldActiveQueue)
1799 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1800 0, QUEUE_GetQueueTask(hNewActiveQueue) );
1802 WIN_ReleaseWinArray(list);
1805 hActiveQueue = hNewActiveQueue;
1807 if ((list = WIN_BuildWinArray(pDesktop, 0, NULL )))
1809 for (ppWnd = list; *ppWnd; ppWnd++)
1811 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1813 if ((*ppWnd)->hmemTaskQ == hNewActiveQueue)
1814 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1815 1, QUEUE_GetQueueTask( hOldActiveQueue ) );
1817 WIN_ReleaseWinArray(list);
1819 WIN_ReleaseDesktop();
1821 if (hWnd && !IsWindow(hWnd)) goto CLEANUP;
1824 if (hWnd)
1826 /* walk up to the first unowned window */
1827 wndTemp = WIN_LockWndPtr(wndPtr);
1828 while (wndTemp->owner)
1830 WIN_UpdateWndPtr(&wndTemp,wndTemp->owner);
1832 /* and set last active owned popup */
1833 wndTemp->hwndLastActive = hWnd;
1835 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1836 WIN_ReleaseWndPtr(wndTemp);
1837 SendMessageA( hWnd, WM_NCACTIVATE, TRUE, 0 );
1838 SendMessageA( hWnd, WM_ACTIVATE,
1839 MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1840 (LPARAM)hwndPrevActive );
1841 if( !IsWindow(hWnd) ) goto CLEANUP;
1844 /* change focus if possible */
1845 if ( fChangeFocus )
1847 if ( pNewActiveQueue )
1849 HWND hOldFocus = PERQDATA_GetFocusWnd( pNewActiveQueue->pQData );
1851 if ( WIN_GetTopParent( hOldFocus ) != hwndActive )
1852 FOCUS_SwitchFocus( pNewActiveQueue, hOldFocus,
1853 (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
1854 0 : hwndActive );
1857 if ( pOldActiveQueue &&
1858 ( !pNewActiveQueue ||
1859 pNewActiveQueue->pQData != pOldActiveQueue->pQData ) )
1861 HWND hOldFocus = PERQDATA_GetFocusWnd( pOldActiveQueue->pQData );
1862 if ( hOldFocus )
1863 FOCUS_SwitchFocus( pOldActiveQueue, hOldFocus, 0 );
1867 if( !hwndPrevActive && wndPtr )
1868 (*wndPtr->pDriver->pForceWindowRaise)(wndPtr);
1870 /* if active wnd is minimized redraw icon title */
1871 if( IsIconic(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1873 bRet = (hWnd == hwndActive); /* Success? */
1875 CLEANUP: /* Unlock the message queues before returning */
1877 if ( pNewActiveQueue )
1878 QUEUE_Unlock( pNewActiveQueue );
1880 CLEANUP_END:
1882 if ( pOldActiveQueue )
1883 QUEUE_Unlock( pOldActiveQueue );
1885 WIN_ReleaseWndPtr(wndPtr);
1886 return bRet;
1889 /*******************************************************************
1890 * WINPOS_ActivateOtherWindow
1892 * Activates window other than pWnd.
1894 BOOL WINPOS_ActivateOtherWindow(WND* pWnd)
1896 BOOL bRet = 0;
1897 WND* pWndTo = NULL;
1898 HWND hwndActive = 0;
1900 /* Get current active window from the active queue */
1901 if ( hActiveQueue )
1903 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1904 if ( pActiveQueue )
1906 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1907 QUEUE_Unlock( pActiveQueue );
1911 if( pWnd->hwndSelf == hwndPrevActive )
1912 hwndPrevActive = 0;
1914 if( hwndActive != pWnd->hwndSelf &&
1915 ( hwndActive || QUEUE_IsExitingQueue(pWnd->hmemTaskQ)) )
1916 return 0;
1918 if( !(pWnd->dwStyle & WS_POPUP) || !(pWnd->owner) ||
1919 !WINPOS_CanActivate((pWndTo = WIN_GetTopParentPtr(pWnd->owner))) )
1921 WND* pWndPtr = WIN_GetTopParentPtr(pWnd);
1923 WIN_ReleaseWndPtr(pWndTo);
1924 pWndTo = WIN_FindWndPtr(hwndPrevActive);
1926 while( !WINPOS_CanActivate(pWndTo) )
1928 /* by now owned windows should've been taken care of */
1929 WIN_UpdateWndPtr(&pWndTo,pWndPtr->next);
1930 WIN_UpdateWndPtr(&pWndPtr,pWndTo);
1931 if( !pWndTo ) break;
1933 WIN_ReleaseWndPtr(pWndPtr);
1936 bRet = WINPOS_SetActiveWindow( pWndTo ? pWndTo->hwndSelf : 0, FALSE, TRUE );
1938 /* switch desktop queue to current active */
1939 if( pWndTo )
1941 WIN_GetDesktop()->hmemTaskQ = pWndTo->hmemTaskQ;
1942 WIN_ReleaseWndPtr(pWndTo);
1943 WIN_ReleaseDesktop();
1946 hwndPrevActive = 0;
1947 return bRet;
1950 /*******************************************************************
1951 * WINPOS_ChangeActiveWindow
1954 BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
1956 WND *wndPtr, *wndTemp;
1957 BOOL retvalue;
1958 HWND hwndActive = 0;
1960 /* Get current active window from the active queue */
1961 if ( hActiveQueue )
1963 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1964 if ( pActiveQueue )
1966 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1967 QUEUE_Unlock( pActiveQueue );
1971 if (!hWnd)
1972 return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
1974 wndPtr = WIN_FindWndPtr(hWnd);
1975 if( !wndPtr ) return FALSE;
1977 /* child windows get WM_CHILDACTIVATE message */
1978 if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
1980 retvalue = SendMessageA(hWnd, WM_CHILDACTIVATE, 0, 0L);
1981 goto end;
1984 if( hWnd == hwndActive )
1986 retvalue = FALSE;
1987 goto end;
1990 if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
1992 retvalue = FALSE;
1993 goto end;
1996 /* switch desktop queue to current active */
1997 wndTemp = WIN_GetDesktop();
1998 if( wndPtr->parent == wndTemp)
1999 wndTemp->hmemTaskQ = wndPtr->hmemTaskQ;
2000 WIN_ReleaseDesktop();
2002 retvalue = TRUE;
2003 end:
2004 WIN_ReleaseWndPtr(wndPtr);
2005 return retvalue;
2009 /***********************************************************************
2010 * WINPOS_SendNCCalcSize
2012 * Send a WM_NCCALCSIZE message to a window.
2013 * All parameters are read-only except newClientRect.
2014 * oldWindowRect, oldClientRect and winpos must be non-NULL only
2015 * when calcValidRect is TRUE.
2017 LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect,
2018 RECT *newWindowRect, RECT *oldWindowRect,
2019 RECT *oldClientRect, WINDOWPOS *winpos,
2020 RECT *newClientRect )
2022 NCCALCSIZE_PARAMS params;
2023 WINDOWPOS winposCopy;
2024 LONG result;
2026 params.rgrc[0] = *newWindowRect;
2027 if (calcValidRect)
2029 winposCopy = *winpos;
2030 params.rgrc[1] = *oldWindowRect;
2031 params.rgrc[2] = *oldClientRect;
2032 params.lppos = &winposCopy;
2034 result = SendMessageA( hwnd, WM_NCCALCSIZE, calcValidRect,
2035 (LPARAM)&params );
2036 TRACE("%d,%d-%d,%d\n",
2037 params.rgrc[0].left, params.rgrc[0].top,
2038 params.rgrc[0].right, params.rgrc[0].bottom );
2040 /* If the application send back garbage, ignore it */
2041 if (params.rgrc[0].left <= params.rgrc[0].right && params.rgrc[0].top <= params.rgrc[0].bottom)
2042 *newClientRect = params.rgrc[0];
2044 return result;
2048 /***********************************************************************
2049 * WINPOS_HandleWindowPosChanging16
2051 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2053 LONG WINPOS_HandleWindowPosChanging16( WND *wndPtr, WINDOWPOS16 *winpos )
2055 POINT maxSize, minTrack;
2056 if (winpos->flags & SWP_NOSIZE) return 0;
2057 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2058 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2060 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
2061 if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
2062 if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
2063 if (!(wndPtr->dwStyle & WS_MINIMIZE))
2065 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
2066 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
2069 return 0;
2073 /***********************************************************************
2074 * WINPOS_HandleWindowPosChanging
2076 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2078 LONG WINPOS_HandleWindowPosChanging( WND *wndPtr, WINDOWPOS *winpos )
2080 POINT maxSize;
2081 if (winpos->flags & SWP_NOSIZE) return 0;
2082 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2083 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2085 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, NULL, NULL );
2086 winpos->cx = MIN( winpos->cx, maxSize.x );
2087 winpos->cy = MIN( winpos->cy, maxSize.y );
2089 return 0;
2092 /***********************************************************************
2093 * SWP_DoOwnedPopups
2095 * fix Z order taking into account owned popups -
2096 * basically we need to maintain them above the window that owns them
2098 * FIXME: hide/show owned popups when owner visibility changes.
2100 static HWND SWP_DoOwnedPopups(WND* pDesktop, WND* wndPtr, HWND hwndInsertAfter, WORD flags)
2102 WND* w = WIN_LockWndPtr(pDesktop->child);
2104 WARN("(%04x) hInsertAfter = %04x\n", wndPtr->hwndSelf, hwndInsertAfter );
2106 if( (wndPtr->dwStyle & WS_POPUP) && wndPtr->owner )
2108 /* make sure this popup stays above the owner */
2110 HWND hwndLocalPrev = HWND_TOP;
2112 if( hwndInsertAfter != HWND_TOP )
2114 while( w != wndPtr->owner )
2116 if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
2117 if( hwndLocalPrev == hwndInsertAfter ) break;
2118 WIN_UpdateWndPtr(&w,w->next);
2120 hwndInsertAfter = hwndLocalPrev;
2123 else if( wndPtr->dwStyle & WS_CHILD )
2124 goto END;
2126 WIN_UpdateWndPtr(&w, pDesktop->child);
2128 while( w )
2130 if( w == wndPtr ) break;
2132 if( (w->dwStyle & WS_POPUP) && w->owner == wndPtr )
2134 SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0,
2135 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
2136 hwndInsertAfter = w->hwndSelf;
2138 WIN_UpdateWndPtr(&w, w->next);
2141 END:
2142 WIN_ReleaseWndPtr(w);
2143 return hwndInsertAfter;
2146 /***********************************************************************
2147 * SWP_CopyValidBits
2149 * Make window look nice without excessive repainting
2151 * visible and update regions are in window coordinates
2152 * client and window rectangles are in parent client coordinates
2154 * FIXME: SWP_EX_PAINTSELF in uFlags works only if both old and new
2155 * window rects have the same origin.
2157 * Returns: uFlags and a dirty region in *pVisRgn.
2159 static UINT SWP_CopyValidBits( WND* Wnd, HRGN* pVisRgn,
2160 LPRECT lpOldWndRect,
2161 LPRECT lpOldClientRect, UINT uFlags )
2163 RECT r;
2164 HRGN newVisRgn, dirtyRgn;
2165 INT my = COMPLEXREGION;
2167 TRACE("\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2168 Wnd->rectWindow.left, Wnd->rectWindow.top,
2169 Wnd->rectWindow.right, Wnd->rectWindow.bottom,
2170 lpOldWndRect->left, lpOldWndRect->top,
2171 lpOldWndRect->right, lpOldWndRect->bottom, *pVisRgn);
2172 TRACE("\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2173 Wnd->rectClient.left, Wnd->rectClient.top,
2174 Wnd->rectClient.right, Wnd->rectClient.bottom,
2175 lpOldClientRect->left, lpOldClientRect->top,
2176 lpOldClientRect->right,lpOldClientRect->bottom );
2178 if( Wnd->hrgnUpdate == 1 )
2179 uFlags |= SWP_EX_NOCOPY; /* whole window is invalid, nothing to copy */
2181 newVisRgn = DCE_GetVisRgn( Wnd->hwndSelf, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
2182 dirtyRgn = CreateRectRgn( 0, 0, 0, 0 );
2184 if( !(uFlags & SWP_EX_NOCOPY) ) /* make sure dst region covers only valid bits */
2185 my = CombineRgn( dirtyRgn, newVisRgn, *pVisRgn, RGN_AND );
2187 if( (my == NULLREGION) || (uFlags & SWP_EX_NOCOPY) )
2189 nocopy:
2191 TRACE("\twon't copy anything!\n");
2193 /* set dirtyRgn to the sum of old and new visible regions
2194 * in parent client coordinates */
2196 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2197 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2199 CombineRgn(*pVisRgn, *pVisRgn, newVisRgn, RGN_OR );
2201 else /* copy valid bits to a new location */
2203 INT dx, dy, ow, oh, nw, nh, ocw, ncw, och, nch;
2204 HRGN hrgnValid = dirtyRgn; /* non-empty intersection of old and new visible rgns */
2206 /* subtract already invalid region inside Wnd from the dst region */
2208 if( Wnd->hrgnUpdate )
2209 if( CombineRgn( hrgnValid, hrgnValid, Wnd->hrgnUpdate, RGN_DIFF) == NULLREGION )
2210 goto nocopy;
2212 /* check if entire window can be copied */
2214 ow = lpOldWndRect->right - lpOldWndRect->left;
2215 oh = lpOldWndRect->bottom - lpOldWndRect->top;
2216 nw = Wnd->rectWindow.right - Wnd->rectWindow.left;
2217 nh = Wnd->rectWindow.bottom - Wnd->rectWindow.top;
2219 ocw = lpOldClientRect->right - lpOldClientRect->left;
2220 och = lpOldClientRect->bottom - lpOldClientRect->top;
2221 ncw = Wnd->rectClient.right - Wnd->rectClient.left;
2222 nch = Wnd->rectClient.bottom - Wnd->rectClient.top;
2224 if( (ocw != ncw) || (och != nch) ||
2225 ( ow != nw) || ( oh != nh) ||
2226 ((lpOldClientRect->top - lpOldWndRect->top) !=
2227 (Wnd->rectClient.top - Wnd->rectWindow.top)) ||
2228 ((lpOldClientRect->left - lpOldWndRect->left) !=
2229 (Wnd->rectClient.left - Wnd->rectWindow.left)) )
2231 dx = Wnd->rectClient.left - lpOldClientRect->left;
2232 dy = Wnd->rectClient.top - lpOldClientRect->top;
2234 /* restrict valid bits to the common client rect */
2236 r.left = Wnd->rectClient.left - Wnd->rectWindow.left;
2237 r.top = Wnd->rectClient.top - Wnd->rectWindow.top;
2238 r.right = r.left + MIN( ocw, ncw );
2239 r.bottom = r.top + MIN( och, nch );
2241 REGION_CropRgn( hrgnValid, hrgnValid, &r,
2242 (uFlags & SWP_EX_PAINTSELF) ? NULL : (POINT*)&(Wnd->rectWindow));
2243 GetRgnBox( hrgnValid, &r );
2244 if( IsRectEmpty( &r ) )
2245 goto nocopy;
2246 r = *lpOldClientRect;
2248 else
2250 dx = Wnd->rectWindow.left - lpOldWndRect->left;
2251 dy = Wnd->rectWindow.top - lpOldWndRect->top;
2252 if( !(uFlags & SWP_EX_PAINTSELF) )
2253 OffsetRgn( hrgnValid, Wnd->rectWindow.left, Wnd->rectWindow.top );
2254 r = *lpOldWndRect;
2257 if( !(uFlags & SWP_EX_PAINTSELF) )
2259 /* Move remaining regions to parent coordinates */
2260 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2261 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2263 else
2264 OffsetRect( &r, -lpOldWndRect->left, -lpOldWndRect->top );
2266 TRACE("\tcomputing dirty region!\n");
2268 /* Compute combined dirty region (old + new - valid) */
2269 CombineRgn( *pVisRgn, *pVisRgn, newVisRgn, RGN_OR);
2270 CombineRgn( *pVisRgn, *pVisRgn, hrgnValid, RGN_DIFF);
2272 /* Blt valid bits, r is the rect to copy */
2274 if( dx || dy )
2276 RECT rClip;
2277 HDC hDC;
2278 DC* dc;
2280 /* get DC and clip rect with drawable rect to avoid superfluous expose events
2281 from copying clipped areas */
2283 if( uFlags & SWP_EX_PAINTSELF )
2285 hDC = GetDCEx( Wnd->hwndSelf, hrgnValid, DCX_WINDOW | DCX_CACHE |
2286 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2287 rClip.right = nw; rClip.bottom = nh;
2289 else
2291 hDC = GetDCEx( Wnd->parent->hwndSelf, hrgnValid, DCX_CACHE |
2292 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2293 rClip.right = Wnd->parent->rectClient.right - Wnd->parent->rectClient.left;
2294 rClip.bottom = Wnd->parent->rectClient.bottom - Wnd->parent->rectClient.top;
2296 rClip.left = rClip.top = 0;
2298 if( (dc = (DC *)GDI_GetObjPtr(hDC, DC_MAGIC)) )
2300 if( oh > nh ) r.bottom = r.top + nh;
2301 if( ow < nw ) r.right = r.left + nw;
2303 if( IntersectRect( &r, &r, &rClip ) )
2305 Wnd->pDriver->pSurfaceCopy( Wnd->parent, dc, dx, dy, &r, TRUE );
2307 /* When you copy the bits without repainting, parent doesn't
2308 get validated appropriately. Therefore, we have to validate
2309 the parent with the windows' updated region when the
2310 parent's update region is not empty. */
2312 if (Wnd->parent->hrgnUpdate != 0 && !(Wnd->parent->dwStyle & WS_CLIPCHILDREN))
2314 OffsetRect(&r, dx, dy);
2315 ValidateRect(Wnd->parent->hwndSelf, &r);
2319 GDI_HEAP_UNLOCK( hDC );
2321 ReleaseDC( (uFlags & SWP_EX_PAINTSELF) ?
2322 Wnd->hwndSelf : Wnd->parent->hwndSelf, hDC);
2326 /* *pVisRgn now points to the invalidated region */
2328 DeleteObject(newVisRgn);
2329 DeleteObject(dirtyRgn);
2330 return uFlags;
2333 /***********************************************************************
2334 * SWP_DoSimpleFrameChanged
2336 * NOTE: old and new client rect origins are identical, only
2337 * extents may have changed. Window extents are the same.
2339 static void SWP_DoSimpleFrameChanged( WND* wndPtr, RECT* pOldClientRect, WORD swpFlags, UINT uFlags )
2341 INT i = 0;
2342 RECT rect;
2343 HRGN hrgn = 0;
2345 if( !(swpFlags & SWP_NOCLIENTSIZE) )
2347 /* Client rect changed its position/size, most likely a scrollar
2348 * was added/removed.
2350 * FIXME: WVR alignment flags
2353 if( wndPtr->rectClient.right > pOldClientRect->right ) /* right edge */
2355 i++;
2356 rect.top = 0;
2357 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2358 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2359 if(!(uFlags & SWP_EX_NOCOPY))
2360 rect.left = pOldClientRect->right - wndPtr->rectClient.left;
2361 else
2363 rect.left = 0;
2364 goto redraw;
2368 if( wndPtr->rectClient.bottom > pOldClientRect->bottom ) /* bottom edge */
2370 if( i )
2371 hrgn = CreateRectRgnIndirect( &rect );
2372 rect.left = 0;
2373 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2374 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2375 if(!(uFlags & SWP_EX_NOCOPY))
2376 rect.top = pOldClientRect->bottom - wndPtr->rectClient.top;
2377 else
2378 rect.top = 0;
2379 if( i++ )
2380 REGION_UnionRectWithRgn( hrgn, &rect );
2383 if( i == 0 && (uFlags & SWP_EX_NOCOPY) ) /* force redraw anyway */
2385 rect = wndPtr->rectWindow;
2386 OffsetRect( &rect, wndPtr->rectWindow.left - wndPtr->rectClient.left,
2387 wndPtr->rectWindow.top - wndPtr->rectClient.top );
2388 i++;
2392 if( i )
2394 redraw:
2395 PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
2396 RDW_ERASENOW | RDW_ALLCHILDREN, RDW_EX_TOPFRAME | RDW_EX_USEHRGN );
2398 else
2400 WIN_UpdateNCRgn(wndPtr, 0, UNC_UPDATE | UNC_ENTIRE);
2403 if( hrgn > 1 )
2404 DeleteObject( hrgn );
2407 /***********************************************************************
2408 * SWP_DoWinPosChanging
2410 static BOOL SWP_DoWinPosChanging( WND* wndPtr, WINDOWPOS* pWinpos,
2411 RECT* pNewWindowRect, RECT* pNewClientRect )
2413 /* Send WM_WINDOWPOSCHANGING message */
2415 if (!(pWinpos->flags & SWP_NOSENDCHANGING))
2416 SendMessageA( wndPtr->hwndSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM)pWinpos );
2418 /* Calculate new position and size */
2420 *pNewWindowRect = wndPtr->rectWindow;
2421 *pNewClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
2422 : wndPtr->rectClient;
2424 if (!(pWinpos->flags & SWP_NOSIZE))
2426 pNewWindowRect->right = pNewWindowRect->left + pWinpos->cx;
2427 pNewWindowRect->bottom = pNewWindowRect->top + pWinpos->cy;
2429 if (!(pWinpos->flags & SWP_NOMOVE))
2431 pNewWindowRect->left = pWinpos->x;
2432 pNewWindowRect->top = pWinpos->y;
2433 pNewWindowRect->right += pWinpos->x - wndPtr->rectWindow.left;
2434 pNewWindowRect->bottom += pWinpos->y - wndPtr->rectWindow.top;
2436 OffsetRect( pNewClientRect, pWinpos->x - wndPtr->rectWindow.left,
2437 pWinpos->y - wndPtr->rectWindow.top );
2440 pWinpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
2441 return TRUE;
2444 /***********************************************************************
2445 * SWP_DoNCCalcSize
2447 static UINT SWP_DoNCCalcSize( WND* wndPtr, WINDOWPOS* pWinpos,
2448 RECT* pNewWindowRect, RECT* pNewClientRect, WORD f)
2450 UINT wvrFlags = 0;
2452 /* Send WM_NCCALCSIZE message to get new client area */
2453 if( (pWinpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
2455 wvrFlags = WINPOS_SendNCCalcSize( pWinpos->hwnd, TRUE, pNewWindowRect,
2456 &wndPtr->rectWindow, &wndPtr->rectClient,
2457 pWinpos, pNewClientRect );
2459 /* FIXME: WVR_ALIGNxxx */
2461 if( pNewClientRect->left != wndPtr->rectClient.left ||
2462 pNewClientRect->top != wndPtr->rectClient.top )
2463 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2465 if( (pNewClientRect->right - pNewClientRect->left !=
2466 wndPtr->rectClient.right - wndPtr->rectClient.left) ||
2467 (pNewClientRect->bottom - pNewClientRect->top !=
2468 wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
2469 pWinpos->flags &= ~SWP_NOCLIENTSIZE;
2471 else
2472 if( !(f & SWP_NOMOVE) && (pNewClientRect->left != wndPtr->rectClient.left ||
2473 pNewClientRect->top != wndPtr->rectClient.top) )
2474 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2475 return wvrFlags;
2478 /***********************************************************************
2479 * SetWindowPos (USER.2)
2481 BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
2482 INT16 x, INT16 y, INT16 cx, INT16 cy, WORD flags)
2484 return SetWindowPos(hwnd,(INT)(INT16)hwndInsertAfter,x,y,cx,cy,flags);
2487 /***********************************************************************
2488 * SetWindowPos (USER32.520)
2490 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
2491 INT x, INT y, INT cx, INT cy, UINT flags )
2493 WINDOWPOS winpos;
2494 WND * wndPtr,*wndTemp;
2495 RECT newWindowRect, newClientRect;
2496 RECT oldWindowRect, oldClientRect;
2497 HRGN visRgn = 0;
2498 UINT wvrFlags = 0, uFlags = 0;
2499 BOOL retvalue, resync = FALSE, bChangePos;
2500 HWND hwndActive = 0;
2502 /* Get current active window from the active queue */
2503 if ( hActiveQueue )
2505 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2506 if ( pActiveQueue )
2508 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2509 QUEUE_Unlock( pActiveQueue );
2513 TRACE("hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2514 hwnd, x, y, x+cx, y+cy, flags);
2516 bChangePos = !(flags & SWP_WINE_NOHOSTMOVE);
2517 flags &= ~SWP_WINE_NOHOSTMOVE;
2520 /* ------------------------------------------------------------------------ CHECKS */
2522 /* Check window handle */
2524 if (hwnd == GetDesktopWindow()) return FALSE;
2525 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2527 TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr->rectWindow.left, wndPtr->rectWindow.top,
2528 wndPtr->rectWindow.right, wndPtr->rectWindow.bottom, (unsigned)wndPtr->dwStyle );
2530 /* Fix redundant flags */
2532 if(wndPtr->dwStyle & WS_VISIBLE)
2533 flags &= ~SWP_SHOWWINDOW;
2534 else
2536 if (!(flags & SWP_SHOWWINDOW))
2537 flags |= SWP_NOREDRAW;
2538 flags &= ~SWP_HIDEWINDOW;
2541 if ( cx < 0 ) cx = 0; if( cy < 0 ) cy = 0;
2543 if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
2544 (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
2545 flags |= SWP_NOSIZE; /* Already the right size */
2547 if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
2548 flags |= SWP_NOMOVE; /* Already the right position */
2550 if (hwnd == hwndActive)
2551 flags |= SWP_NOACTIVATE; /* Already active */
2552 else if ( (wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD )
2554 if(!(flags & SWP_NOACTIVATE)) /* Bring to the top when activating */
2556 flags &= ~SWP_NOZORDER;
2557 hwndInsertAfter = HWND_TOP;
2558 goto Pos;
2562 /* Check hwndInsertAfter */
2564 /* FIXME: TOPMOST not supported yet */
2565 if ((hwndInsertAfter == HWND_TOPMOST) ||
2566 (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
2568 /* hwndInsertAfter must be a sibling of the window */
2569 if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
2571 WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
2573 if( wnd ) {
2574 if( wnd->parent != wndPtr->parent )
2576 retvalue = FALSE;
2577 WIN_ReleaseWndPtr(wnd);
2578 goto END;
2580 if( wnd->next == wndPtr ) flags |= SWP_NOZORDER;
2582 WIN_ReleaseWndPtr(wnd);
2585 Pos: /* ------------------------------------------------------------------------ MAIN part */
2587 /* Fill the WINDOWPOS structure */
2589 winpos.hwnd = hwnd;
2590 winpos.hwndInsertAfter = hwndInsertAfter;
2591 winpos.x = x;
2592 winpos.y = y;
2593 winpos.cx = cx;
2594 winpos.cy = cy;
2595 winpos.flags = flags;
2597 SWP_DoWinPosChanging( wndPtr, &winpos, &newWindowRect, &newClientRect );
2599 if((winpos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER)
2601 if( wndPtr->parent == WIN_GetDesktop() )
2602 hwndInsertAfter = SWP_DoOwnedPopups( wndPtr->parent, wndPtr,
2603 hwndInsertAfter, winpos.flags );
2604 WIN_ReleaseDesktop();
2607 if(!(wndPtr->flags & WIN_NATIVE) )
2609 if( hwndInsertAfter == HWND_TOP )
2610 winpos.flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
2611 else
2612 if( hwndInsertAfter == HWND_BOTTOM )
2613 winpos.flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
2614 else
2615 if( !(winpos.flags & SWP_NOZORDER) )
2616 if( GetWindow(hwndInsertAfter, GW_HWNDNEXT) == wndPtr->hwndSelf )
2617 winpos.flags |= SWP_NOZORDER;
2619 if( !(winpos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) &&
2620 ((winpos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW | SWP_FRAMECHANGED))
2621 != (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)) )
2623 /* get a previous visible region for SWP_CopyValidBits() */
2624 DWORD flags = DCX_WINDOW;
2626 if (wndPtr->dwStyle & WS_CLIPSIBLINGS)
2627 flags |= DCX_CLIPSIBLINGS;
2629 visRgn = DCE_GetVisRgn(hwnd, flags, 0, 0);
2633 /* Common operations */
2635 wvrFlags = SWP_DoNCCalcSize( wndPtr, &winpos, &newWindowRect, &newClientRect, flags );
2637 if(!(winpos.flags & SWP_NOZORDER))
2639 if ( WIN_UnlinkWindow( winpos.hwnd ) )
2640 WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
2643 /* Reset active DCEs */
2645 if( (((winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) &&
2646 wndPtr->dwStyle & WS_VISIBLE) ||
2647 (flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
2649 RECT rect;
2651 UnionRect(&rect, &newWindowRect, &wndPtr->rectWindow);
2652 DCE_InvalidateDCE(wndPtr, &rect);
2655 oldWindowRect = wndPtr->rectWindow;
2656 oldClientRect = wndPtr->rectClient;
2658 /* Find out if we have to redraw the whole client rect */
2660 if( oldClientRect.bottom - oldClientRect.top ==
2661 newClientRect.bottom - newClientRect.top ) wvrFlags &= ~WVR_VREDRAW;
2663 if( oldClientRect.right - oldClientRect.left ==
2664 newClientRect.right - newClientRect.left ) wvrFlags &= ~WVR_HREDRAW;
2666 if( (winpos.flags & SWP_NOCOPYBITS) || (!(winpos.flags & SWP_NOCLIENTSIZE) &&
2667 (wvrFlags >= WVR_HREDRAW) && (wvrFlags < WVR_VALIDRECTS)) )
2669 uFlags |= SWP_EX_NOCOPY;
2672 * Use this later in CopyValidBits()
2674 else if( 0 )
2675 uFlags |= SWP_EX_NONCLIENT;
2678 /* FIXME: actually do something with WVR_VALIDRECTS */
2680 wndPtr->rectWindow = newWindowRect;
2681 wndPtr->rectClient = newClientRect;
2683 if (wndPtr->flags & WIN_NATIVE) /* -------------------------------------------- hosted window */
2685 BOOL bCallDriver = TRUE;
2686 HWND tempInsertAfter = winpos.hwndInsertAfter;
2688 winpos.hwndInsertAfter = hwndInsertAfter;
2690 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2692 /* This is the only place where we need to force repainting of the contents
2693 of windows created by the host window system, all other cases go through the
2694 expose event handling */
2696 if( (winpos.flags & (SWP_NOSIZE | SWP_FRAMECHANGED)) == (SWP_NOSIZE | SWP_FRAMECHANGED) )
2698 cx = newWindowRect.right - newWindowRect.left;
2699 cy = newWindowRect.bottom - newWindowRect.top;
2701 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2702 winpos.hwndInsertAfter = tempInsertAfter;
2703 bCallDriver = FALSE;
2705 if( winpos.flags & SWP_NOCLIENTMOVE )
2706 SWP_DoSimpleFrameChanged(wndPtr, &oldClientRect, winpos.flags, uFlags );
2707 else
2709 /* client area moved but window extents remained the same, copy valid bits */
2711 visRgn = CreateRectRgn( 0, 0, cx, cy );
2712 uFlags = SWP_CopyValidBits( wndPtr, &visRgn, &oldWindowRect, &oldClientRect,
2713 uFlags | SWP_EX_PAINTSELF );
2718 if( bCallDriver )
2720 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2722 if( (oldClientRect.left - oldWindowRect.left == newClientRect.left - newWindowRect.left) &&
2723 (oldClientRect.top - oldWindowRect.top == newClientRect.top - newWindowRect.top) &&
2724 !(uFlags & SWP_EX_NOCOPY) )
2726 /* The origin of the client rect didn't move so we can try to repaint
2727 * only the nonclient area by setting bit gravity hint for the host window system.
2730 if( !(wndPtr->flags & WIN_MANAGED) )
2732 HRGN hrgn = CreateRectRgn( 0, 0, newWindowRect.right - newWindowRect.left,
2733 newWindowRect.bottom - newWindowRect.top);
2734 RECT rcn = newClientRect;
2735 RECT rco = oldClientRect;
2737 OffsetRect( &rcn, -newWindowRect.left, -newWindowRect.top );
2738 OffsetRect( &rco, -oldWindowRect.left, -oldWindowRect.top );
2739 IntersectRect( &rcn, &rcn, &rco );
2740 visRgn = CreateRectRgnIndirect( &rcn );
2741 CombineRgn( visRgn, hrgn, visRgn, RGN_DIFF );
2742 DeleteObject( hrgn );
2743 uFlags = SWP_EX_PAINTSELF;
2745 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGNorthWest );
2747 else
2748 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGForget );
2751 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2752 winpos.hwndInsertAfter = tempInsertAfter;
2755 if( winpos.flags & SWP_SHOWWINDOW )
2757 HWND focus, curr;
2759 wndPtr->dwStyle |= WS_VISIBLE;
2761 if (wndPtr->flags & WIN_MANAGED) resync = TRUE;
2763 /* focus was set to unmapped window, reset host focus
2764 * since the window is now visible */
2766 focus = curr = GetFocus();
2767 while (curr)
2769 if (curr == hwnd)
2771 WND *pFocus = WIN_FindWndPtr( focus );
2772 if (pFocus)
2773 pFocus->pDriver->pSetFocus(pFocus);
2774 WIN_ReleaseWndPtr(pFocus);
2775 break;
2777 curr = GetParent(curr);
2781 else /* -------------------------------------------- emulated window */
2783 if( winpos.flags & SWP_SHOWWINDOW )
2785 wndPtr->dwStyle |= WS_VISIBLE;
2786 uFlags |= SWP_EX_PAINTSELF;
2787 visRgn = 1; /* redraw the whole window */
2789 else if( !(winpos.flags & SWP_NOREDRAW) )
2791 if( winpos.flags & SWP_HIDEWINDOW )
2793 if( visRgn > 1 ) /* map to parent */
2794 OffsetRgn( visRgn, oldWindowRect.left, oldWindowRect.top );
2795 else
2796 visRgn = 0;
2798 else
2800 if( (winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE )
2801 uFlags = SWP_CopyValidBits(wndPtr, &visRgn, &oldWindowRect,
2802 &oldClientRect, uFlags);
2803 else
2805 /* nothing moved, redraw frame if needed */
2807 if( winpos.flags & SWP_FRAMECHANGED )
2808 SWP_DoSimpleFrameChanged( wndPtr, &oldClientRect, winpos.flags, uFlags );
2809 if( visRgn )
2811 DeleteObject( visRgn );
2812 visRgn = 0;
2819 if( winpos.flags & SWP_HIDEWINDOW )
2821 wndPtr->dwStyle &= ~WS_VISIBLE;
2823 if (hwnd == CARET_GetHwnd()) DestroyCaret();
2826 /* ------------------------------------------------------------------------ FINAL */
2828 if (wndPtr->flags & WIN_NATIVE)
2829 EVENT_Synchronize(); /* Synchronize with the host window system */
2831 if (!GetCapture() && ((wndPtr->dwStyle & WS_VISIBLE) || (flags & SWP_HIDEWINDOW)))
2833 /* Simulate a mouse event to set the cursor */
2834 int iWndsLocks = WIN_SuspendWndsLock();
2836 hardware_event( WM_MOUSEMOVE, GET_KEYSTATE(), 0,
2837 PosX, PosY, GetTickCount(), 0 );
2839 WIN_RestoreWndsLock(iWndsLocks);
2842 wndTemp = WIN_GetDesktop();
2844 /* repaint invalidated region (if any)
2846 * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2847 * and force update after ChangeActiveWindow() to avoid painting frames twice.
2850 if( visRgn )
2852 if( !(winpos.flags & SWP_NOREDRAW) )
2855 /* Use PAINT_RedrawWindow to explicitly force an invalidation of the window,
2856 its parent and sibling and so on, and then erase the parent window
2857 back ground if the parent is either a top-level window or its parent's parent
2858 is top-level window. Rely on the system to repaint other affected
2859 windows later on. */
2860 if( uFlags & SWP_EX_PAINTSELF )
2862 PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn,
2863 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN,
2864 RDW_EX_XYWINDOW | RDW_EX_USEHRGN );
2866 else
2868 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn,
2869 RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN,
2870 RDW_EX_USEHRGN );
2873 if(wndPtr -> parent == wndTemp || wndPtr->parent->parent == wndTemp )
2875 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0,
2876 RDW_ERASENOW | RDW_NOCHILDREN, 0 );
2879 if( visRgn != 1 )
2880 DeleteObject( visRgn );
2883 WIN_ReleaseDesktop();
2885 if (!(flags & SWP_NOACTIVATE))
2886 WINPOS_ChangeActiveWindow( winpos.hwnd, FALSE );
2888 /* And last, send the WM_WINDOWPOSCHANGED message */
2890 TRACE("\tstatus flags = %04x\n", winpos.flags & SWP_AGG_STATUSFLAGS);
2892 if ( resync ||
2893 (((winpos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) &&
2894 !(winpos.flags & SWP_NOSENDCHANGING)) )
2896 SendMessageA( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
2897 if (resync) EVENT_Synchronize();
2900 retvalue = TRUE;
2901 END:
2902 WIN_ReleaseWndPtr(wndPtr);
2903 return retvalue;
2907 /***********************************************************************
2908 * BeginDeferWindowPos16 (USER.259)
2910 HDWP16 WINAPI BeginDeferWindowPos16( INT16 count )
2912 return BeginDeferWindowPos( count );
2916 /***********************************************************************
2917 * BeginDeferWindowPos (USER32.9)
2919 HDWP WINAPI BeginDeferWindowPos( INT count )
2921 HDWP handle;
2922 DWP *pDWP;
2924 if (count <= 0) return 0;
2925 handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
2926 if (!handle) return 0;
2927 pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
2928 pDWP->actualCount = 0;
2929 pDWP->suggestedCount = count;
2930 pDWP->valid = TRUE;
2931 pDWP->wMagic = DWP_MAGIC;
2932 pDWP->hwndParent = 0;
2933 return handle;
2937 /***********************************************************************
2938 * DeferWindowPos16 (USER.260)
2940 HDWP16 WINAPI DeferWindowPos16( HDWP16 hdwp, HWND16 hwnd, HWND16 hwndAfter,
2941 INT16 x, INT16 y, INT16 cx, INT16 cy,
2942 UINT16 flags )
2944 return DeferWindowPos( hdwp, hwnd, (INT)(INT16)hwndAfter,
2945 x, y, cx, cy, flags );
2949 /***********************************************************************
2950 * DeferWindowPos (USER32.128)
2952 HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter,
2953 INT x, INT y, INT cx, INT cy,
2954 UINT flags )
2956 DWP *pDWP;
2957 int i;
2958 HDWP newhdwp = hdwp,retvalue;
2959 /* HWND parent; */
2960 WND *pWnd;
2962 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
2963 if (!pDWP) return 0;
2964 if (hwnd == GetDesktopWindow()) return 0;
2966 if (!(pWnd=WIN_FindWndPtr( hwnd ))) {
2967 USER_HEAP_FREE( hdwp );
2968 return 0;
2971 /* Numega Bounds Checker Demo dislikes the following code.
2972 In fact, I've not been able to find any "same parent" requirement in any docu
2973 [AM 980509]
2975 #if 0
2976 /* All the windows of a DeferWindowPos() must have the same parent */
2977 parent = pWnd->parent->hwndSelf;
2978 if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
2979 else if (parent != pDWP->hwndParent)
2981 USER_HEAP_FREE( hdwp );
2982 retvalue = 0;
2983 goto END;
2985 #endif
2987 for (i = 0; i < pDWP->actualCount; i++)
2989 if (pDWP->winPos[i].hwnd == hwnd)
2991 /* Merge with the other changes */
2992 if (!(flags & SWP_NOZORDER))
2994 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
2996 if (!(flags & SWP_NOMOVE))
2998 pDWP->winPos[i].x = x;
2999 pDWP->winPos[i].y = y;
3001 if (!(flags & SWP_NOSIZE))
3003 pDWP->winPos[i].cx = cx;
3004 pDWP->winPos[i].cy = cy;
3006 pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
3007 SWP_NOZORDER | SWP_NOREDRAW |
3008 SWP_NOACTIVATE | SWP_NOCOPYBITS|
3009 SWP_NOOWNERZORDER);
3010 pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
3011 SWP_FRAMECHANGED);
3012 retvalue = hdwp;
3013 goto END;
3016 if (pDWP->actualCount >= pDWP->suggestedCount)
3018 newhdwp = USER_HEAP_REALLOC( hdwp,
3019 sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
3020 if (!newhdwp)
3022 retvalue = 0;
3023 goto END;
3025 pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
3026 pDWP->suggestedCount++;
3028 pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
3029 pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
3030 pDWP->winPos[pDWP->actualCount].x = x;
3031 pDWP->winPos[pDWP->actualCount].y = y;
3032 pDWP->winPos[pDWP->actualCount].cx = cx;
3033 pDWP->winPos[pDWP->actualCount].cy = cy;
3034 pDWP->winPos[pDWP->actualCount].flags = flags;
3035 pDWP->actualCount++;
3036 retvalue = newhdwp;
3037 END:
3038 WIN_ReleaseWndPtr(pWnd);
3039 return retvalue;
3043 /***********************************************************************
3044 * EndDeferWindowPos16 (USER.261)
3046 BOOL16 WINAPI EndDeferWindowPos16( HDWP16 hdwp )
3048 return EndDeferWindowPos( hdwp );
3052 /***********************************************************************
3053 * EndDeferWindowPos (USER32.173)
3055 BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
3057 DWP *pDWP;
3058 WINDOWPOS *winpos;
3059 BOOL res = TRUE;
3060 int i;
3062 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
3063 if (!pDWP) return FALSE;
3064 for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
3066 if (!(res = SetWindowPos( winpos->hwnd, winpos->hwndInsertAfter,
3067 winpos->x, winpos->y, winpos->cx,
3068 winpos->cy, winpos->flags ))) break;
3070 USER_HEAP_FREE( hdwp );
3071 return res;
3075 /***********************************************************************
3076 * TileChildWindows (USER.199)
3078 void WINAPI TileChildWindows16( HWND16 parent, WORD action )
3080 FIXME("(%04x, %d): stub\n", parent, action);
3083 /***********************************************************************
3084 * CascageChildWindows (USER.198)
3086 void WINAPI CascadeChildWindows16( HWND16 parent, WORD action )
3088 FIXME("(%04x, %d): stub\n", parent, action);
3091 /***********************************************************************
3092 * SetProgmanWindow [USER32.522]
3094 HRESULT WINAPI SetProgmanWindow ( HWND hwnd )
3096 hGlobalProgmanWindow = hwnd;
3097 return hGlobalProgmanWindow;
3100 /***********************************************************************
3101 * GetProgmanWindow [USER32.289]
3103 HRESULT WINAPI GetProgmanWindow ( )
3105 return hGlobalProgmanWindow;
3108 /***********************************************************************
3109 * SetShellWindowEx [USER32.531]
3110 * hwndProgman = Progman[Program Manager]
3111 * |-> SHELLDLL_DefView
3112 * hwndListView = | |-> SysListView32
3113 * | | |-> tooltips_class32
3114 * | |
3115 * | |-> SysHeader32
3116 * |
3117 * |-> ProxyTarget
3119 HRESULT WINAPI SetShellWindowEx ( HWND hwndProgman, HWND hwndListView )
3121 FIXME("0x%08x 0x%08x stub\n",hwndProgman ,hwndListView );
3122 hGlobalShellWindow = hwndProgman;
3123 return hGlobalShellWindow;
3127 /***********************************************************************
3128 * SetTaskmanWindow [USER32.537]
3129 * NOTES
3130 * hwnd = MSTaskSwWClass
3131 * |-> SysTabControl32
3133 HRESULT WINAPI SetTaskmanWindow ( HWND hwnd )
3135 hGlobalTaskmanWindow = hwnd;
3136 return hGlobalTaskmanWindow;
3139 /***********************************************************************
3140 * GetTaskmanWindow [USER32.304]
3142 HRESULT WINAPI GetTaskmanWindow ( )
3144 return hGlobalTaskmanWindow;