Keyboard/mouse event proc thunk creation moved out of if1632/thunk.c.
[wine/multimedia.git] / windows / winpos.c
blob579c3efb146211ce94ec21c2294c172cb0f13b62
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"
27 DEFAULT_DEBUG_CHANNEL(win)
29 #define HAS_DLGFRAME(style,exStyle) \
30 (((exStyle) & WS_EX_DLGMODALFRAME) || \
31 (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
33 #define HAS_THICKFRAME(style) \
34 (((style) & WS_THICKFRAME) && \
35 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
37 #define SWP_AGG_NOGEOMETRYCHANGE \
38 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
39 #define SWP_AGG_NOPOSCHANGE \
40 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
41 #define SWP_AGG_STATUSFLAGS \
42 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
44 #define EMPTYPOINT(pt) ((*(LONG*)&(pt)) == -1)
46 #define PLACE_MIN 0x0001
47 #define PLACE_MAX 0x0002
48 #define PLACE_RECT 0x0004
50 #define SWP_EX_NOCOPY 0x0001
51 #define SWP_EX_PAINTSELF 0x0002
52 #define SWP_EX_NONCLIENT 0x0004
54 #define MINMAX_NOSWP 0x00010000
56 /* ----- internal variables ----- */
58 static HWND hwndPrevActive = 0; /* Previously active window */
59 static HWND hGlobalShellWindow=0; /*the shell*/
60 static HWND hGlobalTaskmanWindow=0;
61 static HWND hGlobalProgmanWindow=0;
63 static LPCSTR atomInternalPos;
65 extern HQUEUE16 hActiveQueue;
67 /***********************************************************************
68 * WINPOS_CreateInternalPosAtom
70 BOOL WINPOS_CreateInternalPosAtom()
72 LPSTR str = "SysIP";
73 atomInternalPos = (LPCSTR)(DWORD)GlobalAddAtomA(str);
74 return (atomInternalPos) ? TRUE : FALSE;
77 /***********************************************************************
78 * WINPOS_CheckInternalPos
80 * Called when a window is destroyed.
82 void WINPOS_CheckInternalPos( WND* wndPtr )
84 LPINTERNALPOS lpPos;
85 MESSAGEQUEUE *pMsgQ = 0;
86 HWND hwnd = wndPtr->hwndSelf;
88 lpPos = (LPINTERNALPOS) GetPropA( hwnd, atomInternalPos );
90 /* Retrieve the message queue associated with this window */
91 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
92 if ( !pMsgQ )
94 WARN("\tMessage queue not found. Exiting!\n" );
95 return;
98 if( hwnd == hwndPrevActive ) hwndPrevActive = 0;
100 if( hwnd == PERQDATA_GetActiveWnd( pMsgQ->pQData ) )
102 PERQDATA_SetActiveWnd( pMsgQ->pQData, 0 );
103 WARN("\tattempt to activate destroyed window!\n");
106 if( lpPos )
108 if( IsWindow(lpPos->hwndIconTitle) )
109 DestroyWindow( lpPos->hwndIconTitle );
110 HeapFree( SystemHeap, 0, lpPos );
113 QUEUE_Unlock( pMsgQ );
114 return;
117 /***********************************************************************
118 * WINPOS_FindIconPos
120 * Find a suitable place for an iconic window.
122 static POINT16 WINPOS_FindIconPos( WND* wndPtr, POINT16 pt )
124 RECT16 rectParent;
125 short x, y, xspacing, yspacing;
127 GetClientRect16( wndPtr->parent->hwndSelf, &rectParent );
128 if ((pt.x >= rectParent.left) && (pt.x + GetSystemMetrics(SM_CXICON) < rectParent.right) &&
129 (pt.y >= rectParent.top) && (pt.y + GetSystemMetrics(SM_CYICON) < rectParent.bottom))
130 return pt; /* The icon already has a suitable position */
132 xspacing = GetSystemMetrics(SM_CXICONSPACING);
133 yspacing = GetSystemMetrics(SM_CYICONSPACING);
135 y = rectParent.bottom;
136 for (;;)
138 for (x = rectParent.left; x <= rectParent.right-xspacing; x += xspacing)
140 /* Check if another icon already occupies this spot */
141 WND *childPtr = WIN_LockWndPtr(wndPtr->parent->child);
142 while (childPtr)
144 if ((childPtr->dwStyle & WS_MINIMIZE) && (childPtr != wndPtr))
146 if ((childPtr->rectWindow.left < x + xspacing) &&
147 (childPtr->rectWindow.right >= x) &&
148 (childPtr->rectWindow.top <= y) &&
149 (childPtr->rectWindow.bottom > y - yspacing))
150 break; /* There's a window in there */
152 WIN_UpdateWndPtr(&childPtr,childPtr->next);
154 WIN_ReleaseWndPtr(childPtr);
155 if (!childPtr) /* No window was found, so it's OK for us */
157 pt.x = x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2;
158 pt.y = y - (yspacing + GetSystemMetrics(SM_CYICON)) / 2;
159 return pt;
162 y -= yspacing;
167 /***********************************************************************
168 * ArrangeIconicWindows16 (USER.170)
170 UINT16 WINAPI ArrangeIconicWindows16( HWND16 parent)
172 return ArrangeIconicWindows(parent);
174 /***********************************************************************
175 * ArrangeIconicWindows (USER32.7)
177 UINT WINAPI ArrangeIconicWindows( HWND parent )
179 RECT rectParent;
180 HWND hwndChild;
181 INT x, y, xspacing, yspacing;
183 GetClientRect( parent, &rectParent );
184 x = rectParent.left;
185 y = rectParent.bottom;
186 xspacing = GetSystemMetrics(SM_CXICONSPACING);
187 yspacing = GetSystemMetrics(SM_CYICONSPACING);
189 hwndChild = GetWindow( parent, GW_CHILD );
190 while (hwndChild)
192 if( IsIconic( hwndChild ) )
194 WND *wndPtr = WIN_FindWndPtr(hwndChild);
196 WINPOS_ShowIconTitle( wndPtr, FALSE );
198 SetWindowPos( hwndChild, 0, x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2,
199 y - yspacing - GetSystemMetrics(SM_CYICON)/2, 0, 0,
200 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
201 if( IsWindow(hwndChild) )
202 WINPOS_ShowIconTitle(wndPtr , TRUE );
203 WIN_ReleaseWndPtr(wndPtr);
205 if (x <= rectParent.right - xspacing) x += xspacing;
206 else
208 x = rectParent.left;
209 y -= yspacing;
212 hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
214 return yspacing;
218 /***********************************************************************
219 * SwitchToThisWindow16 (USER.172)
221 void WINAPI SwitchToThisWindow16( HWND16 hwnd, BOOL16 restore )
223 SwitchToThisWindow( hwnd, restore );
227 /***********************************************************************
228 * SwitchToThisWindow (USER32.539)
230 void WINAPI SwitchToThisWindow( HWND hwnd, BOOL restore )
232 ShowWindow( hwnd, restore ? SW_RESTORE : SW_SHOWMINIMIZED );
236 /***********************************************************************
237 * GetWindowRect16 (USER.32)
239 void WINAPI GetWindowRect16( HWND16 hwnd, LPRECT16 rect )
241 WND * wndPtr = WIN_FindWndPtr( hwnd );
242 if (!wndPtr) return;
244 CONV_RECT32TO16( &wndPtr->rectWindow, rect );
245 if (wndPtr->dwStyle & WS_CHILD)
246 MapWindowPoints16( wndPtr->parent->hwndSelf, 0, (POINT16 *)rect, 2 );
247 WIN_ReleaseWndPtr(wndPtr);
251 /***********************************************************************
252 * GetWindowRect (USER32.308)
254 BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect )
256 WND * wndPtr = WIN_FindWndPtr( hwnd );
257 if (!wndPtr) return FALSE;
259 *rect = wndPtr->rectWindow;
260 if (wndPtr->dwStyle & WS_CHILD)
261 MapWindowPoints( wndPtr->parent->hwndSelf, 0, (POINT *)rect, 2 );
262 WIN_ReleaseWndPtr(wndPtr);
263 return TRUE;
267 /***********************************************************************
268 * GetWindowRgn
270 BOOL WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
273 RECT rect;
274 WND * wndPtr = WIN_FindWndPtr( hwnd );
275 if (!wndPtr) return (ERROR);
277 FIXME("GetWindowRgn: doesn't really do regions\n");
279 memset (&rect, 0, sizeof(rect));
281 GetWindowRect ( hwnd, &rect );
283 FIXME("Check whether a valid region here\n");
285 SetRectRgn ( hrgn, rect.left, rect.top, rect.right, rect.bottom );
287 WIN_ReleaseWndPtr(wndPtr);
288 return (SIMPLEREGION);
291 /***********************************************************************
292 * SetWindowRgn
294 INT WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn,BOOL bRedraw)
298 FIXME("SetWindowRgn: stub\n");
299 return TRUE;
302 /***********************************************************************
303 * SetWindowRgn16
305 INT16 WINAPI SetWindowRgn16( HWND16 hwnd, HRGN16 hrgn,BOOL16 bRedraw)
309 FIXME("SetWindowRgn16: stub\n");
310 return TRUE;
314 /***********************************************************************
315 * GetClientRect16 (USER.33)
317 void WINAPI GetClientRect16( HWND16 hwnd, LPRECT16 rect )
319 WND * wndPtr = WIN_FindWndPtr( hwnd );
321 rect->left = rect->top = rect->right = rect->bottom = 0;
322 if (wndPtr)
324 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
325 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
327 WIN_ReleaseWndPtr(wndPtr);
331 /***********************************************************************
332 * GetClientRect (USER.220)
334 BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect )
336 WND * wndPtr = WIN_FindWndPtr( hwnd );
338 rect->left = rect->top = rect->right = rect->bottom = 0;
339 if (!wndPtr) return FALSE;
340 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
341 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
343 WIN_ReleaseWndPtr(wndPtr);
344 return TRUE;
348 /*******************************************************************
349 * ClientToScreen16 (USER.28)
351 void WINAPI ClientToScreen16( HWND16 hwnd, LPPOINT16 lppnt )
353 MapWindowPoints16( hwnd, 0, lppnt, 1 );
357 /*******************************************************************
358 * ClientToScreen (USER32.52)
360 BOOL WINAPI ClientToScreen( HWND hwnd, LPPOINT lppnt )
362 MapWindowPoints( hwnd, 0, lppnt, 1 );
363 return TRUE;
367 /*******************************************************************
368 * ScreenToClient16 (USER.29)
370 void WINAPI ScreenToClient16( HWND16 hwnd, LPPOINT16 lppnt )
372 MapWindowPoints16( 0, hwnd, lppnt, 1 );
376 /*******************************************************************
377 * ScreenToClient (USER32.447)
379 BOOL WINAPI ScreenToClient( HWND hwnd, LPPOINT lppnt )
381 MapWindowPoints( 0, hwnd, lppnt, 1 );
382 return TRUE;
386 /***********************************************************************
387 * WINPOS_WindowFromPoint
389 * Find the window and hittest for a given point.
391 INT16 WINPOS_WindowFromPoint( WND* wndScope, POINT16 pt, WND **ppWnd )
393 WND *wndPtr;
394 INT16 hittest = HTERROR;
395 INT16 retvalue;
396 POINT16 xy = pt;
398 *ppWnd = NULL;
399 wndPtr = WIN_LockWndPtr(wndScope->child);
401 if( wndScope->flags & WIN_MANAGED )
403 /* In managed mode we have to check wndScope first as it is also
404 * a window which received the mouse event. */
406 if( wndScope->dwStyle & WS_DISABLED )
408 retvalue = HTERROR;
409 goto end;
411 if( pt.x < wndScope->rectClient.left || pt.x >= wndScope->rectClient.right ||
412 pt.y < wndScope->rectClient.top || pt.y >= wndScope->rectClient.bottom )
413 goto hittest;
415 MapWindowPoints16( GetDesktopWindow16(), wndScope->hwndSelf, &xy, 1 );
417 for (;;)
419 while (wndPtr)
421 /* If point is in window, and window is visible, and it */
422 /* is enabled (or it's a top-level window), then explore */
423 /* its children. Otherwise, go to the next window. */
425 if ((wndPtr->dwStyle & WS_VISIBLE) &&
426 (!(wndPtr->dwStyle & WS_DISABLED) ||
427 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)) &&
428 (xy.x >= wndPtr->rectWindow.left) &&
429 (xy.x < wndPtr->rectWindow.right) &&
430 (xy.y >= wndPtr->rectWindow.top) &&
431 (xy.y < wndPtr->rectWindow.bottom))
433 *ppWnd = wndPtr; /* Got a suitable window */
435 /* If window is minimized or disabled, return at once */
436 if (wndPtr->dwStyle & WS_MINIMIZE)
438 retvalue = HTCAPTION;
439 goto end;
441 if (wndPtr->dwStyle & WS_DISABLED)
443 retvalue = HTERROR;
444 goto end;
447 /* If point is not in client area, ignore the children */
448 if ((xy.x < wndPtr->rectClient.left) ||
449 (xy.x >= wndPtr->rectClient.right) ||
450 (xy.y < wndPtr->rectClient.top) ||
451 (xy.y >= wndPtr->rectClient.bottom)) break;
453 xy.x -= wndPtr->rectClient.left;
454 xy.y -= wndPtr->rectClient.top;
455 WIN_UpdateWndPtr(&wndPtr,wndPtr->child);
457 else
459 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
463 hittest:
464 /* If nothing found, try the scope window */
465 if (!*ppWnd) *ppWnd = wndScope;
467 /* Send the WM_NCHITTEST message (only if to the same task) */
468 if ((*ppWnd)->hmemTaskQ == GetFastQueue16())
470 hittest = (INT16)SendMessage16( (*ppWnd)->hwndSelf, WM_NCHITTEST,
471 0, MAKELONG( pt.x, pt.y ) );
472 if (hittest != HTTRANSPARENT)
474 retvalue = hittest; /* Found the window */
475 goto end;
478 else
480 retvalue = HTCLIENT;
481 goto end;
484 /* If no children found in last search, make point relative to parent */
485 if (!wndPtr)
487 xy.x += (*ppWnd)->rectClient.left;
488 xy.y += (*ppWnd)->rectClient.top;
491 /* Restart the search from the next sibling */
492 WIN_UpdateWndPtr(&wndPtr,(*ppWnd)->next);
493 *ppWnd = (*ppWnd)->parent;
496 end:
497 WIN_ReleaseWndPtr(wndPtr);
498 return retvalue;
502 /*******************************************************************
503 * WindowFromPoint16 (USER.30)
505 HWND16 WINAPI WindowFromPoint16( POINT16 pt )
507 WND *pWnd;
508 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt, &pWnd );
509 WIN_ReleaseDesktop();
510 return pWnd->hwndSelf;
514 /*******************************************************************
515 * WindowFromPoint (USER32.582)
517 HWND WINAPI WindowFromPoint( POINT pt )
519 WND *pWnd;
520 POINT16 pt16;
521 CONV_POINT32TO16( &pt, &pt16 );
522 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16, &pWnd );
523 WIN_ReleaseDesktop();
524 return (HWND)pWnd->hwndSelf;
528 /*******************************************************************
529 * ChildWindowFromPoint16 (USER.191)
531 HWND16 WINAPI ChildWindowFromPoint16( HWND16 hwndParent, POINT16 pt )
533 POINT pt32;
534 CONV_POINT16TO32( &pt, &pt32 );
535 return (HWND16)ChildWindowFromPoint( hwndParent, pt32 );
539 /*******************************************************************
540 * ChildWindowFromPoint (USER32.49)
542 HWND WINAPI ChildWindowFromPoint( HWND hwndParent, POINT pt )
544 /* pt is in the client coordinates */
546 WND* wnd = WIN_FindWndPtr(hwndParent);
547 RECT rect;
548 HWND retvalue;
550 if( !wnd ) return 0;
552 /* get client rect fast */
553 rect.top = rect.left = 0;
554 rect.right = wnd->rectClient.right - wnd->rectClient.left;
555 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
557 if (!PtInRect( &rect, pt ))
559 retvalue = 0;
560 goto end;
562 WIN_UpdateWndPtr(&wnd,wnd->child);
563 while ( wnd )
565 if (PtInRect( &wnd->rectWindow, pt ))
567 retvalue = wnd->hwndSelf;
568 goto end;
570 WIN_UpdateWndPtr(&wnd,wnd->next);
572 retvalue = hwndParent;
573 end:
574 WIN_ReleaseWndPtr(wnd);
575 return retvalue;
578 /*******************************************************************
579 * ChildWindowFromPointEx16 (USER.50)
581 HWND16 WINAPI ChildWindowFromPointEx16( HWND16 hwndParent, POINT16 pt, UINT16 uFlags)
583 POINT pt32;
584 CONV_POINT16TO32( &pt, &pt32 );
585 return (HWND16)ChildWindowFromPointEx( hwndParent, pt32, uFlags );
589 /*******************************************************************
590 * ChildWindowFromPointEx32 (USER32.50)
592 HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt,
593 UINT uFlags)
595 /* pt is in the client coordinates */
597 WND* wnd = WIN_FindWndPtr(hwndParent);
598 RECT rect;
599 HWND retvalue;
601 if( !wnd ) return 0;
603 /* get client rect fast */
604 rect.top = rect.left = 0;
605 rect.right = wnd->rectClient.right - wnd->rectClient.left;
606 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
608 if (!PtInRect( &rect, pt ))
610 retvalue = 0;
611 goto end;
613 WIN_UpdateWndPtr(&wnd,wnd->child);
615 while ( wnd )
617 if (PtInRect( &wnd->rectWindow, pt )) {
618 if ( (uFlags & CWP_SKIPINVISIBLE) &&
619 !(wnd->dwStyle & WS_VISIBLE) );
620 else if ( (uFlags & CWP_SKIPDISABLED) &&
621 (wnd->dwStyle & WS_DISABLED) );
622 else if ( (uFlags & CWP_SKIPTRANSPARENT) &&
623 (wnd->dwExStyle & WS_EX_TRANSPARENT) );
624 else
626 retvalue = wnd->hwndSelf;
627 goto end;
631 WIN_UpdateWndPtr(&wnd,wnd->next);
633 retvalue = hwndParent;
634 end:
635 WIN_ReleaseWndPtr(wnd);
636 return retvalue;
640 /*******************************************************************
641 * WINPOS_GetWinOffset
643 * Calculate the offset between the origin of the two windows. Used
644 * to implement MapWindowPoints.
646 static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo,
647 POINT *offset )
649 WND * wndPtr = 0;
651 offset->x = offset->y = 0;
652 if (hwndFrom == hwndTo ) return;
654 /* Translate source window origin to screen coords */
655 if (hwndFrom)
657 if (!(wndPtr = WIN_FindWndPtr( hwndFrom )))
659 ERR("bad hwndFrom = %04x\n",hwndFrom);
660 return;
662 while (wndPtr->parent)
664 offset->x += wndPtr->rectClient.left;
665 offset->y += wndPtr->rectClient.top;
666 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
668 WIN_ReleaseWndPtr(wndPtr);
671 /* Translate origin to destination window coords */
672 if (hwndTo)
674 if (!(wndPtr = WIN_FindWndPtr( hwndTo )))
676 ERR("bad hwndTo = %04x\n", hwndTo );
677 return;
679 while (wndPtr->parent)
681 offset->x -= wndPtr->rectClient.left;
682 offset->y -= wndPtr->rectClient.top;
683 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
685 WIN_ReleaseWndPtr(wndPtr);
690 /*******************************************************************
691 * MapWindowPoints16 (USER.258)
693 void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
694 LPPOINT16 lppt, UINT16 count )
696 POINT offset;
698 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
699 while (count--)
701 lppt->x += offset.x;
702 lppt->y += offset.y;
703 lppt++;
708 /*******************************************************************
709 * MapWindowPoints (USER32.386)
711 INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo,
712 LPPOINT lppt, UINT count )
714 POINT offset;
716 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
717 while (count--)
719 lppt->x += offset.x;
720 lppt->y += offset.y;
721 lppt++;
723 return MAKELONG( LOWORD(offset.x), LOWORD(offset.y) );
727 /***********************************************************************
728 * IsIconic16 (USER.31)
730 BOOL16 WINAPI IsIconic16(HWND16 hWnd)
732 return IsIconic(hWnd);
736 /***********************************************************************
737 * IsIconic (USER32.345)
739 BOOL WINAPI IsIconic(HWND hWnd)
741 BOOL retvalue;
742 WND * wndPtr = WIN_FindWndPtr(hWnd);
743 if (wndPtr == NULL) return FALSE;
744 retvalue = (wndPtr->dwStyle & WS_MINIMIZE) != 0;
745 WIN_ReleaseWndPtr(wndPtr);
746 return retvalue;
750 /***********************************************************************
751 * IsZoomed (USER.272)
753 BOOL16 WINAPI IsZoomed16(HWND16 hWnd)
755 return IsZoomed(hWnd);
759 /***********************************************************************
760 * IsZoomed (USER.352)
762 BOOL WINAPI IsZoomed(HWND hWnd)
764 BOOL retvalue;
765 WND * wndPtr = WIN_FindWndPtr(hWnd);
766 if (wndPtr == NULL) return FALSE;
767 retvalue = (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
768 WIN_ReleaseWndPtr(wndPtr);
769 return retvalue;
773 /*******************************************************************
774 * GetActiveWindow (USER.60)
776 HWND16 WINAPI GetActiveWindow16(void)
778 return (HWND16)GetActiveWindow();
781 /*******************************************************************
782 * GetActiveWindow (USER32.205)
784 HWND WINAPI GetActiveWindow(void)
786 MESSAGEQUEUE *pCurMsgQ = 0;
787 HWND hwndActive = 0;
789 /* Get the messageQ for the current thread */
790 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
792 WARN("\tCurrent message queue not found. Exiting!\n" );
793 return 0;
796 /* Return the current active window from the perQ data of the current message Q */
797 hwndActive = PERQDATA_GetActiveWnd( pCurMsgQ->pQData );
799 QUEUE_Unlock( pCurMsgQ );
800 return hwndActive;
804 /*******************************************************************
805 * WINPOS_CanActivate
807 static BOOL WINPOS_CanActivate(WND* pWnd)
809 if( pWnd && ((pWnd->dwStyle & (WS_DISABLED | WS_VISIBLE | WS_CHILD))
810 == WS_VISIBLE) ) 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 if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus()))
1304 /* Revert focus to parent */
1305 SetFocus( GetParent(hwnd) );
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)
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) swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1379 if (!(swp & MINMAX_NOSWP))
1380 SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top,
1381 newPos.right, newPos.bottom, LOWORD(swp) );
1382 if (!IsWindow( hwnd )) goto END;
1383 else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( wndPtr, TRUE );
1386 if (wndPtr->flags & WIN_NEED_SIZE)
1388 /* should happen only in CreateWindowEx() */
1389 int wParam = SIZE_RESTORED;
1391 wndPtr->flags &= ~WIN_NEED_SIZE;
1392 if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
1393 else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
1394 SendMessageA( hwnd, WM_SIZE, wParam,
1395 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
1396 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
1397 SendMessageA( hwnd, WM_MOVE, 0,
1398 MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
1401 END:
1402 WIN_ReleaseWndPtr(wndPtr);
1403 return wasVisible;
1407 /***********************************************************************
1408 * GetInternalWindowPos16 (USER.460)
1410 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
1411 LPPOINT16 ptIcon )
1413 WINDOWPLACEMENT16 wndpl;
1414 if (GetWindowPlacement16( hwnd, &wndpl ))
1416 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1417 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1418 return wndpl.showCmd;
1420 return 0;
1424 /***********************************************************************
1425 * GetInternalWindowPos (USER32.245)
1427 UINT WINAPI GetInternalWindowPos( HWND hwnd, LPRECT rectWnd,
1428 LPPOINT ptIcon )
1430 WINDOWPLACEMENT wndpl;
1431 if (GetWindowPlacement( hwnd, &wndpl ))
1433 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1434 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1435 return wndpl.showCmd;
1437 return 0;
1440 /***********************************************************************
1441 * GetWindowPlacement16 (USER.370)
1443 BOOL16 WINAPI GetWindowPlacement16( HWND16 hwnd, WINDOWPLACEMENT16 *wndpl )
1445 WND *pWnd = WIN_FindWndPtr( hwnd );
1446 LPINTERNALPOS lpPos;
1448 if(!pWnd ) return FALSE;
1450 lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1451 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1452 wndpl->length = sizeof(*wndpl);
1453 if( pWnd->dwStyle & WS_MINIMIZE )
1454 wndpl->showCmd = SW_SHOWMINIMIZED;
1455 else
1456 wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE )
1457 ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
1458 if( pWnd->flags & WIN_RESTORE_MAX )
1459 wndpl->flags = WPF_RESTORETOMAXIMIZED;
1460 else
1461 wndpl->flags = 0;
1462 wndpl->ptMinPosition = lpPos->ptIconPos;
1463 wndpl->ptMaxPosition = lpPos->ptMaxPos;
1464 wndpl->rcNormalPosition = lpPos->rectNormal;
1466 WIN_ReleaseWndPtr(pWnd);
1467 return TRUE;
1471 /***********************************************************************
1472 * GetWindowPlacement (USER32.307)
1474 * Win95:
1475 * Fails if wndpl->length of Win95 (!) apps is invalid.
1477 BOOL WINAPI GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *pwpl32 )
1479 if( pwpl32 )
1481 WINDOWPLACEMENT16 wpl;
1482 wpl.length = sizeof(wpl);
1483 if( GetWindowPlacement16( hwnd, &wpl ) )
1485 pwpl32->length = sizeof(*pwpl32);
1486 pwpl32->flags = wpl.flags;
1487 pwpl32->showCmd = wpl.showCmd;
1488 CONV_POINT16TO32( &wpl.ptMinPosition, &pwpl32->ptMinPosition );
1489 CONV_POINT16TO32( &wpl.ptMaxPosition, &pwpl32->ptMaxPosition );
1490 CONV_RECT16TO32( &wpl.rcNormalPosition, &pwpl32->rcNormalPosition );
1491 return TRUE;
1494 return FALSE;
1498 /***********************************************************************
1499 * WINPOS_SetPlacement
1501 static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT16 *wndpl,
1502 UINT flags )
1504 WND *pWnd = WIN_FindWndPtr( hwnd );
1505 if( pWnd )
1507 LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1508 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1510 if( flags & PLACE_MIN ) lpPos->ptIconPos = wndpl->ptMinPosition;
1511 if( flags & PLACE_MAX ) lpPos->ptMaxPos = wndpl->ptMaxPosition;
1512 if( flags & PLACE_RECT) lpPos->rectNormal = wndpl->rcNormalPosition;
1514 if( pWnd->dwStyle & WS_MINIMIZE )
1516 WINPOS_ShowIconTitle( pWnd, FALSE );
1517 if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1518 SetWindowPos( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1519 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1521 else if( pWnd->dwStyle & WS_MAXIMIZE )
1523 if( !EMPTYPOINT(lpPos->ptMaxPos) )
1524 SetWindowPos( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1525 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1527 else if( flags & PLACE_RECT )
1528 SetWindowPos( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1529 lpPos->rectNormal.right - lpPos->rectNormal.left,
1530 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1531 SWP_NOZORDER | SWP_NOACTIVATE );
1533 ShowWindow( hwnd, wndpl->showCmd );
1534 if( IsWindow(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1536 if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd, TRUE );
1538 /* SDK: ...valid only the next time... */
1539 if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1541 WIN_ReleaseWndPtr(pWnd);
1542 return TRUE;
1544 return FALSE;
1548 /***********************************************************************
1549 * SetWindowPlacement16 (USER.371)
1551 BOOL16 WINAPI SetWindowPlacement16(HWND16 hwnd, const WINDOWPLACEMENT16 *wndpl)
1553 return WINPOS_SetPlacement( hwnd, wndpl,
1554 PLACE_MIN | PLACE_MAX | PLACE_RECT );
1557 /***********************************************************************
1558 * SetWindowPlacement (USER32.519)
1560 * Win95:
1561 * Fails if wndpl->length of Win95 (!) apps is invalid.
1563 BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *pwpl32 )
1565 if( pwpl32 )
1567 WINDOWPLACEMENT16 wpl;
1569 wpl.length = sizeof(WINDOWPLACEMENT16);
1570 wpl.flags = pwpl32->flags;
1571 wpl.showCmd = pwpl32->showCmd;
1572 wpl.ptMinPosition.x = pwpl32->ptMinPosition.x;
1573 wpl.ptMinPosition.y = pwpl32->ptMinPosition.y;
1574 wpl.ptMaxPosition.x = pwpl32->ptMaxPosition.x;
1575 wpl.ptMaxPosition.y = pwpl32->ptMaxPosition.y;
1576 wpl.rcNormalPosition.left = pwpl32->rcNormalPosition.left;
1577 wpl.rcNormalPosition.top = pwpl32->rcNormalPosition.top;
1578 wpl.rcNormalPosition.right = pwpl32->rcNormalPosition.right;
1579 wpl.rcNormalPosition.bottom = pwpl32->rcNormalPosition.bottom;
1581 return WINPOS_SetPlacement( hwnd, &wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1583 return FALSE;
1587 /***********************************************************************
1588 * SetInternalWindowPos16 (USER.461)
1590 void WINAPI SetInternalWindowPos16( HWND16 hwnd, UINT16 showCmd,
1591 LPRECT16 rect, LPPOINT16 pt )
1593 if( IsWindow16(hwnd) )
1595 WINDOWPLACEMENT16 wndpl;
1596 UINT flags;
1598 wndpl.length = sizeof(wndpl);
1599 wndpl.showCmd = showCmd;
1600 wndpl.flags = flags = 0;
1602 if( pt )
1604 flags |= PLACE_MIN;
1605 wndpl.flags |= WPF_SETMINPOSITION;
1606 wndpl.ptMinPosition = *pt;
1608 if( rect )
1610 flags |= PLACE_RECT;
1611 wndpl.rcNormalPosition = *rect;
1613 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1618 /***********************************************************************
1619 * SetInternalWindowPos (USER32.483)
1621 void WINAPI SetInternalWindowPos( HWND hwnd, UINT showCmd,
1622 LPRECT rect, LPPOINT pt )
1624 if( IsWindow(hwnd) )
1626 WINDOWPLACEMENT16 wndpl;
1627 UINT flags;
1629 wndpl.length = sizeof(wndpl);
1630 wndpl.showCmd = showCmd;
1631 wndpl.flags = flags = 0;
1633 if( pt )
1635 flags |= PLACE_MIN;
1636 wndpl.flags |= WPF_SETMINPOSITION;
1637 CONV_POINT32TO16( pt, &wndpl.ptMinPosition );
1639 if( rect )
1641 flags |= PLACE_RECT;
1642 CONV_RECT32TO16( rect, &wndpl.rcNormalPosition );
1644 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1648 /*******************************************************************
1649 * WINPOS_SetActiveWindow
1651 * SetActiveWindow() back-end. This is the only function that
1652 * can assign active status to a window. It must be called only
1653 * for the top level windows.
1655 BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
1657 CBTACTIVATESTRUCT16* cbtStruct;
1658 WND* wndPtr=0, *wndTemp;
1659 HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1660 MESSAGEQUEUE *pOldActiveQueue = 0, *pNewActiveQueue = 0;
1661 WORD wIconized = 0;
1662 HWND hwndActive = 0;
1663 BOOL bRet = 0;
1665 TRACE("(%04x, %d, %d)\n", hWnd, fMouse, fChangeFocus );
1667 /* Get current active window from the active queue */
1668 if ( hActiveQueue )
1670 pOldActiveQueue = QUEUE_Lock( hActiveQueue );
1671 if ( pOldActiveQueue )
1672 hwndActive = PERQDATA_GetActiveWnd( pOldActiveQueue->pQData );
1675 /* paranoid checks */
1676 if( hWnd == GetDesktopWindow() || (bRet = (hWnd == hwndActive)) )
1677 goto CLEANUP_END;
1679 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1680 * return 0;
1682 wndPtr = WIN_FindWndPtr(hWnd);
1683 hOldActiveQueue = hActiveQueue;
1685 if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1687 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1688 WIN_ReleaseWndPtr(wndTemp);
1690 else
1691 TRACE("no current active window.\n");
1693 /* call CBT hook chain */
1694 if ((cbtStruct = SEGPTR_NEW(CBTACTIVATESTRUCT16)))
1696 cbtStruct->fMouse = fMouse;
1697 cbtStruct->hWndActive = hwndActive;
1698 bRet = (BOOL)HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
1699 (LPARAM)SEGPTR_GET(cbtStruct) );
1700 SEGPTR_FREE(cbtStruct);
1701 if (bRet) goto CLEANUP_END;
1704 /* set prev active wnd to current active wnd and send notification */
1705 if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
1707 MESSAGEQUEUE *pTempActiveQueue = 0;
1709 if (!SendMessageA( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1711 if (GetSysModalWindow16() != hWnd)
1712 goto CLEANUP_END;
1713 /* disregard refusal if hWnd is sysmodal */
1716 SendMessageA( hwndPrevActive, WM_ACTIVATE,
1717 MAKEWPARAM( WA_INACTIVE, wIconized ),
1718 (LPARAM)hWnd );
1720 /* check if something happened during message processing
1721 * (global active queue may have changed)
1723 pTempActiveQueue = QUEUE_Lock( hActiveQueue );
1724 if(!pTempActiveQueue)
1725 goto CLEANUP_END;
1727 hwndActive = PERQDATA_GetActiveWnd( pTempActiveQueue->pQData );
1728 QUEUE_Unlock( pTempActiveQueue );
1729 if( hwndPrevActive != hwndActive )
1730 goto CLEANUP_END;
1733 /* Set new active window in the message queue */
1734 hwndActive = hWnd;
1735 if ( wndPtr )
1737 pNewActiveQueue = QUEUE_Lock( wndPtr->hmemTaskQ );
1738 if ( pNewActiveQueue )
1739 PERQDATA_SetActiveWnd( pNewActiveQueue->pQData, hwndActive );
1741 else /* have to do this or MDI frame activation goes to hell */
1742 if( pOldActiveQueue )
1743 PERQDATA_SetActiveWnd( pOldActiveQueue->pQData, 0 );
1745 /* send palette messages */
1746 if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1747 SendMessage16((HWND16)-1, WM_PALETTEISCHANGING, (WPARAM16)hWnd, 0L );
1749 /* if prev wnd is minimized redraw icon title */
1750 if( IsIconic( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1752 /* managed windows will get ConfigureNotify event */
1753 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->flags & WIN_MANAGED))
1755 /* check Z-order and bring hWnd to the top */
1756 for (wndTemp = WIN_LockWndPtr(WIN_GetDesktop()->child); wndTemp; WIN_UpdateWndPtr(&wndTemp,wndTemp->next))
1758 if (wndTemp->dwStyle & WS_VISIBLE) break;
1760 WIN_ReleaseDesktop();
1761 WIN_ReleaseWndPtr(wndTemp);
1763 if( wndTemp != wndPtr )
1764 SetWindowPos(hWnd, HWND_TOP, 0,0,0,0,
1765 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1766 if (!IsWindow(hWnd))
1767 goto CLEANUP;
1770 /* Get a handle to the new active queue */
1771 hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1773 /* send WM_ACTIVATEAPP if necessary */
1774 if (hOldActiveQueue != hNewActiveQueue)
1776 WND **list, **ppWnd;
1777 WND *pDesktop = WIN_GetDesktop();
1779 if ((list = WIN_BuildWinArray( pDesktop, 0, NULL )))
1781 for (ppWnd = list; *ppWnd; ppWnd++)
1783 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1785 if ((*ppWnd)->hmemTaskQ == hOldActiveQueue)
1786 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1787 0, QUEUE_GetQueueTask(hNewActiveQueue) );
1789 WIN_ReleaseWinArray(list);
1792 hActiveQueue = hNewActiveQueue;
1794 if ((list = WIN_BuildWinArray(pDesktop, 0, NULL )))
1796 for (ppWnd = list; *ppWnd; ppWnd++)
1798 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1800 if ((*ppWnd)->hmemTaskQ == hNewActiveQueue)
1801 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1802 1, QUEUE_GetQueueTask( hOldActiveQueue ) );
1804 WIN_ReleaseWinArray(list);
1806 WIN_ReleaseDesktop();
1808 if (hWnd && !IsWindow(hWnd)) goto CLEANUP;
1811 if (hWnd)
1813 /* walk up to the first unowned window */
1814 wndTemp = WIN_LockWndPtr(wndPtr);
1815 while (wndTemp->owner)
1817 WIN_UpdateWndPtr(&wndTemp,wndTemp->owner);
1819 /* and set last active owned popup */
1820 wndTemp->hwndLastActive = hWnd;
1822 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1823 WIN_ReleaseWndPtr(wndTemp);
1824 SendMessageA( hWnd, WM_NCACTIVATE, TRUE, 0 );
1825 SendMessageA( hWnd, WM_ACTIVATE,
1826 MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1827 (LPARAM)hwndPrevActive );
1828 if( !IsWindow(hWnd) ) goto CLEANUP;
1831 /* change focus if possible */
1832 if ( fChangeFocus )
1834 if ( pNewActiveQueue )
1836 HWND hOldFocus = PERQDATA_GetFocusWnd( pNewActiveQueue->pQData );
1838 if ( WIN_GetTopParent( hOldFocus ) != hwndActive )
1839 FOCUS_SwitchFocus( pNewActiveQueue, hOldFocus,
1840 (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
1841 0 : hwndActive );
1844 if ( pOldActiveQueue &&
1845 ( !pNewActiveQueue ||
1846 pNewActiveQueue->pQData != pOldActiveQueue->pQData ) )
1848 HWND hOldFocus = PERQDATA_GetFocusWnd( pOldActiveQueue->pQData );
1849 if ( hOldFocus )
1850 FOCUS_SwitchFocus( pOldActiveQueue, hOldFocus, 0 );
1854 if( !hwndPrevActive && wndPtr )
1855 (*wndPtr->pDriver->pForceWindowRaise)(wndPtr);
1857 /* if active wnd is minimized redraw icon title */
1858 if( IsIconic(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1860 bRet = (hWnd == hwndActive); /* Success? */
1862 CLEANUP: /* Unlock the message queues before returning */
1864 if ( pNewActiveQueue )
1865 QUEUE_Unlock( pNewActiveQueue );
1867 CLEANUP_END:
1869 if ( pOldActiveQueue )
1870 QUEUE_Unlock( pOldActiveQueue );
1872 WIN_ReleaseWndPtr(wndPtr);
1873 return bRet;
1876 /*******************************************************************
1877 * WINPOS_ActivateOtherWindow
1879 * Activates window other than pWnd.
1881 BOOL WINPOS_ActivateOtherWindow(WND* pWnd)
1883 BOOL bRet = 0;
1884 WND* pWndTo = NULL;
1885 HWND hwndActive = 0;
1887 /* Get current active window from the active queue */
1888 if ( hActiveQueue )
1890 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1891 if ( pActiveQueue )
1893 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1894 QUEUE_Unlock( pActiveQueue );
1898 if( pWnd->hwndSelf == hwndPrevActive )
1899 hwndPrevActive = 0;
1901 if( hwndActive != pWnd->hwndSelf &&
1902 ( hwndActive || QUEUE_IsExitingQueue(pWnd->hmemTaskQ)) )
1903 return 0;
1905 if( !(pWnd->dwStyle & WS_POPUP) || !(pWnd->owner) ||
1906 !WINPOS_CanActivate((pWndTo = WIN_GetTopParentPtr(pWnd->owner))) )
1908 WND* pWndPtr = WIN_GetTopParentPtr(pWnd);
1910 WIN_ReleaseWndPtr(pWndTo);
1911 pWndTo = WIN_FindWndPtr(hwndPrevActive);
1913 while( !WINPOS_CanActivate(pWndTo) )
1915 /* by now owned windows should've been taken care of */
1916 WIN_UpdateWndPtr(&pWndTo,pWndPtr->next);
1917 WIN_UpdateWndPtr(&pWndPtr,pWndTo);
1918 if( !pWndTo ) break;
1920 WIN_ReleaseWndPtr(pWndPtr);
1923 bRet = WINPOS_SetActiveWindow( pWndTo ? pWndTo->hwndSelf : 0, FALSE, TRUE );
1925 /* switch desktop queue to current active */
1926 if( pWndTo )
1928 WIN_GetDesktop()->hmemTaskQ = pWndTo->hmemTaskQ;
1929 WIN_ReleaseWndPtr(pWndTo);
1930 WIN_ReleaseDesktop();
1933 hwndPrevActive = 0;
1934 return bRet;
1937 /*******************************************************************
1938 * WINPOS_ChangeActiveWindow
1941 BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
1943 WND *wndPtr, *wndTemp;
1944 BOOL retvalue;
1945 HWND hwndActive = 0;
1947 /* Get current active window from the active queue */
1948 if ( hActiveQueue )
1950 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1951 if ( pActiveQueue )
1953 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1954 QUEUE_Unlock( pActiveQueue );
1958 if (!hWnd)
1959 return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
1961 wndPtr = WIN_FindWndPtr(hWnd);
1962 if( !wndPtr ) return FALSE;
1964 /* child windows get WM_CHILDACTIVATE message */
1965 if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
1967 retvalue = SendMessageA(hWnd, WM_CHILDACTIVATE, 0, 0L);
1968 goto end;
1971 if( hWnd == hwndActive )
1973 retvalue = FALSE;
1974 goto end;
1977 if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
1979 retvalue = FALSE;
1980 goto end;
1983 /* switch desktop queue to current active */
1984 wndTemp = WIN_GetDesktop();
1985 if( wndPtr->parent == wndTemp)
1986 wndTemp->hmemTaskQ = wndPtr->hmemTaskQ;
1987 WIN_ReleaseDesktop();
1989 retvalue = TRUE;
1990 end:
1991 WIN_ReleaseWndPtr(wndPtr);
1992 return retvalue;
1996 /***********************************************************************
1997 * WINPOS_SendNCCalcSize
1999 * Send a WM_NCCALCSIZE message to a window.
2000 * All parameters are read-only except newClientRect.
2001 * oldWindowRect, oldClientRect and winpos must be non-NULL only
2002 * when calcValidRect is TRUE.
2004 LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect,
2005 RECT *newWindowRect, RECT *oldWindowRect,
2006 RECT *oldClientRect, WINDOWPOS *winpos,
2007 RECT *newClientRect )
2009 NCCALCSIZE_PARAMS params;
2010 WINDOWPOS winposCopy;
2011 LONG result;
2013 params.rgrc[0] = *newWindowRect;
2014 if (calcValidRect)
2016 winposCopy = *winpos;
2017 params.rgrc[1] = *oldWindowRect;
2018 params.rgrc[2] = *oldClientRect;
2019 params.lppos = &winposCopy;
2021 result = SendMessageA( hwnd, WM_NCCALCSIZE, calcValidRect,
2022 (LPARAM)&params );
2023 TRACE("%d,%d-%d,%d\n",
2024 params.rgrc[0].left, params.rgrc[0].top,
2025 params.rgrc[0].right, params.rgrc[0].bottom );
2027 /* If the application send back garbage, ignore it */
2028 if (params.rgrc[0].left <= params.rgrc[0].right && params.rgrc[0].top <= params.rgrc[0].bottom)
2029 *newClientRect = params.rgrc[0];
2031 return result;
2035 /***********************************************************************
2036 * WINPOS_HandleWindowPosChanging16
2038 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2040 LONG WINPOS_HandleWindowPosChanging16( WND *wndPtr, WINDOWPOS16 *winpos )
2042 POINT maxSize, minTrack;
2043 if (winpos->flags & SWP_NOSIZE) return 0;
2044 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2045 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2047 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
2048 if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
2049 if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
2050 if (!(wndPtr->dwStyle & WS_MINIMIZE))
2052 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
2053 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
2056 return 0;
2060 /***********************************************************************
2061 * WINPOS_HandleWindowPosChanging
2063 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2065 LONG WINPOS_HandleWindowPosChanging( WND *wndPtr, WINDOWPOS *winpos )
2067 POINT maxSize;
2068 if (winpos->flags & SWP_NOSIZE) return 0;
2069 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2070 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2072 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, NULL, NULL );
2073 winpos->cx = MIN( winpos->cx, maxSize.x );
2074 winpos->cy = MIN( winpos->cy, maxSize.y );
2076 return 0;
2079 /***********************************************************************
2080 * SWP_DoOwnedPopups
2082 * fix Z order taking into account owned popups -
2083 * basically we need to maintain them above the window that owns them
2085 * FIXME: hide/show owned popups when owner visibility changes.
2087 static HWND SWP_DoOwnedPopups(WND* pDesktop, WND* wndPtr, HWND hwndInsertAfter, WORD flags)
2089 WND* w = WIN_LockWndPtr(pDesktop->child);
2091 WARN("(%04x) hInsertAfter = %04x\n", wndPtr->hwndSelf, hwndInsertAfter );
2093 if( (wndPtr->dwStyle & WS_POPUP) && wndPtr->owner )
2095 /* make sure this popup stays above the owner */
2097 HWND hwndLocalPrev = HWND_TOP;
2099 if( hwndInsertAfter != HWND_TOP )
2101 while( w != wndPtr->owner )
2103 if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
2104 if( hwndLocalPrev == hwndInsertAfter ) break;
2105 WIN_UpdateWndPtr(&w,w->next);
2107 hwndInsertAfter = hwndLocalPrev;
2110 else if( wndPtr->dwStyle & WS_CHILD )
2111 goto END;
2113 WIN_UpdateWndPtr(&w, pDesktop->child);
2115 while( w )
2117 if( w == wndPtr ) break;
2119 if( (w->dwStyle & WS_POPUP) && w->owner == wndPtr )
2121 SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0,
2122 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
2123 hwndInsertAfter = w->hwndSelf;
2125 WIN_UpdateWndPtr(&w, w->next);
2128 END:
2129 WIN_ReleaseWndPtr(w);
2130 return hwndInsertAfter;
2133 /***********************************************************************
2134 * SWP_CopyValidBits
2136 * Make window look nice without excessive repainting
2138 * visible and update regions are in window coordinates
2139 * client and window rectangles are in parent client coordinates
2141 * FIXME: SWP_EX_PAINTSELF in uFlags works only if both old and new
2142 * window rects have the same origin.
2144 * Returns: uFlags and a dirty region in *pVisRgn.
2146 static UINT SWP_CopyValidBits( WND* Wnd, HRGN* pVisRgn,
2147 LPRECT lpOldWndRect,
2148 LPRECT lpOldClientRect, UINT uFlags )
2150 RECT r;
2151 HRGN newVisRgn, dirtyRgn;
2152 INT my = COMPLEXREGION;
2154 TRACE("\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2155 Wnd->rectWindow.left, Wnd->rectWindow.top,
2156 Wnd->rectWindow.right, Wnd->rectWindow.bottom,
2157 lpOldWndRect->left, lpOldWndRect->top,
2158 lpOldWndRect->right, lpOldWndRect->bottom, *pVisRgn);
2159 TRACE("\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2160 Wnd->rectClient.left, Wnd->rectClient.top,
2161 Wnd->rectClient.right, Wnd->rectClient.bottom,
2162 lpOldClientRect->left, lpOldClientRect->top,
2163 lpOldClientRect->right,lpOldClientRect->bottom );
2165 if( Wnd->hrgnUpdate == 1 )
2166 uFlags |= SWP_EX_NOCOPY; /* whole window is invalid, nothing to copy */
2168 newVisRgn = DCE_GetVisRgn( Wnd->hwndSelf, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
2169 dirtyRgn = CreateRectRgn( 0, 0, 0, 0 );
2171 if( !(uFlags & SWP_EX_NOCOPY) ) /* make sure dst region covers only valid bits */
2172 my = CombineRgn( dirtyRgn, newVisRgn, *pVisRgn, RGN_AND );
2174 if( (my == NULLREGION) || (uFlags & SWP_EX_NOCOPY) )
2176 nocopy:
2178 TRACE("\twon't copy anything!\n");
2180 /* set dirtyRgn to the sum of old and new visible regions
2181 * in parent client coordinates */
2183 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2184 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2186 CombineRgn(*pVisRgn, *pVisRgn, newVisRgn, RGN_OR );
2188 else /* copy valid bits to a new location */
2190 INT dx, dy, ow, oh, nw, nh, ocw, ncw, och, nch;
2191 HRGN hrgnValid = dirtyRgn; /* non-empty intersection of old and new visible rgns */
2193 /* subtract already invalid region inside Wnd from the dst region */
2195 if( Wnd->hrgnUpdate )
2196 if( CombineRgn( hrgnValid, hrgnValid, Wnd->hrgnUpdate, RGN_DIFF) == NULLREGION )
2197 goto nocopy;
2199 /* check if entire window can be copied */
2201 ow = lpOldWndRect->right - lpOldWndRect->left;
2202 oh = lpOldWndRect->bottom - lpOldWndRect->top;
2203 nw = Wnd->rectWindow.right - Wnd->rectWindow.left;
2204 nh = Wnd->rectWindow.bottom - Wnd->rectWindow.top;
2206 ocw = lpOldClientRect->right - lpOldClientRect->left;
2207 och = lpOldClientRect->bottom - lpOldClientRect->top;
2208 ncw = Wnd->rectClient.right - Wnd->rectClient.left;
2209 nch = Wnd->rectClient.bottom - Wnd->rectClient.top;
2211 if( (ocw != ncw) || (och != nch) ||
2212 ( ow != nw) || ( oh != nh) ||
2213 ((lpOldClientRect->top - lpOldWndRect->top) !=
2214 (Wnd->rectClient.top - Wnd->rectWindow.top)) ||
2215 ((lpOldClientRect->left - lpOldWndRect->left) !=
2216 (Wnd->rectClient.left - Wnd->rectWindow.left)) )
2218 dx = Wnd->rectClient.left - lpOldClientRect->left;
2219 dy = Wnd->rectClient.top - lpOldClientRect->top;
2221 /* restrict valid bits to the common client rect */
2223 r.left = Wnd->rectClient.left - Wnd->rectWindow.left;
2224 r.top = Wnd->rectClient.top - Wnd->rectWindow.top;
2225 r.right = r.left + MIN( ocw, ncw );
2226 r.bottom = r.top + MIN( och, nch );
2228 REGION_CropRgn( hrgnValid, hrgnValid, &r,
2229 (uFlags & SWP_EX_PAINTSELF) ? NULL : (POINT*)&(Wnd->rectWindow));
2230 GetRgnBox( hrgnValid, &r );
2231 if( IsRectEmpty( &r ) )
2232 goto nocopy;
2233 r = *lpOldClientRect;
2235 else
2237 dx = Wnd->rectWindow.left - lpOldWndRect->left;
2238 dy = Wnd->rectWindow.top - lpOldWndRect->top;
2239 if( !(uFlags & SWP_EX_PAINTSELF) )
2240 OffsetRgn( hrgnValid, Wnd->rectWindow.left, Wnd->rectWindow.top );
2241 r = *lpOldWndRect;
2244 if( !(uFlags & SWP_EX_PAINTSELF) )
2246 /* Move remaining regions to parent coordinates */
2247 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2248 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2250 else
2251 OffsetRect( &r, -lpOldWndRect->left, -lpOldWndRect->top );
2253 TRACE("\tcomputing dirty region!\n");
2255 /* Compute combined dirty region (old + new - valid) */
2256 CombineRgn( *pVisRgn, *pVisRgn, newVisRgn, RGN_OR);
2257 CombineRgn( *pVisRgn, *pVisRgn, hrgnValid, RGN_DIFF);
2259 /* Blt valid bits, r is the rect to copy */
2261 if( dx || dy )
2263 RECT rClip;
2264 HDC hDC;
2265 DC* dc;
2267 /* get DC and clip rect with drawable rect to avoid superfluous expose events
2268 from copying clipped areas */
2270 if( uFlags & SWP_EX_PAINTSELF )
2272 hDC = GetDCEx( Wnd->hwndSelf, hrgnValid, DCX_WINDOW | DCX_CACHE |
2273 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2274 rClip.right = nw; rClip.bottom = nh;
2276 else
2278 hDC = GetDCEx( Wnd->parent->hwndSelf, hrgnValid, DCX_CACHE |
2279 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2280 rClip.right = Wnd->parent->rectClient.right - Wnd->parent->rectClient.left;
2281 rClip.bottom = Wnd->parent->rectClient.bottom - Wnd->parent->rectClient.top;
2283 rClip.left = rClip.top = 0;
2285 if( (dc = (DC *)GDI_GetObjPtr(hDC, DC_MAGIC)) )
2287 if( oh > nh ) r.bottom = r.top + nh;
2288 if( ow < nw ) r.right = r.left + nw;
2290 if( IntersectRect( &r, &r, &rClip ) )
2292 Wnd->pDriver->pSurfaceCopy( Wnd->parent, dc, dx, dy, &r, TRUE );
2294 /* When you copy the bits without repainting, parent doesn't
2295 get validated appropriately. Therefore, we have to validate
2296 the parent with the windows' updated region when the
2297 parent's update region is not empty. */
2299 if (Wnd->parent->hrgnUpdate != 0 && !(Wnd->parent->dwStyle & WS_CLIPCHILDREN))
2301 OffsetRect(&r, dx, dy);
2302 ValidateRect(Wnd->parent->hwndSelf, &r);
2306 GDI_HEAP_UNLOCK( hDC );
2308 ReleaseDC( (uFlags & SWP_EX_PAINTSELF) ?
2309 Wnd->hwndSelf : Wnd->parent->hwndSelf, hDC);
2313 /* *pVisRgn now points to the invalidated region */
2315 DeleteObject(newVisRgn);
2316 DeleteObject(dirtyRgn);
2317 return uFlags;
2320 /***********************************************************************
2321 * SWP_DoSimpleFrameChanged
2323 * NOTE: old and new client rect origins are identical, only
2324 * extents may have changed. Window extents are the same.
2326 static void SWP_DoSimpleFrameChanged( WND* wndPtr, RECT* pOldClientRect, WORD swpFlags, UINT uFlags )
2328 INT i = 0;
2329 RECT rect;
2330 HRGN hrgn = 0;
2332 if( !(swpFlags & SWP_NOCLIENTSIZE) )
2334 /* Client rect changed its position/size, most likely a scrollar
2335 * was added/removed.
2337 * FIXME: WVR alignment flags
2340 if( wndPtr->rectClient.right > pOldClientRect->right ) /* right edge */
2342 i++;
2343 rect.top = 0;
2344 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2345 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2346 if(!(uFlags & SWP_EX_NOCOPY))
2347 rect.left = pOldClientRect->right - wndPtr->rectClient.left;
2348 else
2350 rect.left = 0;
2351 goto redraw;
2355 if( wndPtr->rectClient.bottom > pOldClientRect->bottom ) /* bottom edge */
2357 if( i )
2358 hrgn = CreateRectRgnIndirect( &rect );
2359 rect.left = 0;
2360 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2361 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2362 if(!(uFlags & SWP_EX_NOCOPY))
2363 rect.top = pOldClientRect->bottom - wndPtr->rectClient.top;
2364 else
2365 rect.top = 0;
2366 if( i++ )
2367 REGION_UnionRectWithRgn( hrgn, &rect );
2370 if( i == 0 && (uFlags & SWP_EX_NOCOPY) ) /* force redraw anyway */
2372 rect = wndPtr->rectWindow;
2373 OffsetRect( &rect, wndPtr->rectWindow.left - wndPtr->rectClient.left,
2374 wndPtr->rectWindow.top - wndPtr->rectClient.top );
2375 i++;
2379 if( i )
2381 redraw:
2382 PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
2383 RDW_ERASENOW | RDW_ALLCHILDREN, RDW_EX_TOPFRAME | RDW_EX_USEHRGN );
2385 else
2387 WIN_UpdateNCRgn(wndPtr, 0, UNC_UPDATE | UNC_ENTIRE);
2390 if( hrgn > 1 )
2391 DeleteObject( hrgn );
2394 /***********************************************************************
2395 * SWP_DoWinPosChanging
2397 static BOOL SWP_DoWinPosChanging( WND* wndPtr, WINDOWPOS* pWinpos,
2398 RECT* pNewWindowRect, RECT* pNewClientRect )
2400 /* Send WM_WINDOWPOSCHANGING message */
2402 if (!(pWinpos->flags & SWP_NOSENDCHANGING))
2403 SendMessageA( wndPtr->hwndSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM)pWinpos );
2405 /* Calculate new position and size */
2407 *pNewWindowRect = wndPtr->rectWindow;
2408 *pNewClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
2409 : wndPtr->rectClient;
2411 if (!(pWinpos->flags & SWP_NOSIZE))
2413 pNewWindowRect->right = pNewWindowRect->left + pWinpos->cx;
2414 pNewWindowRect->bottom = pNewWindowRect->top + pWinpos->cy;
2416 if (!(pWinpos->flags & SWP_NOMOVE))
2418 pNewWindowRect->left = pWinpos->x;
2419 pNewWindowRect->top = pWinpos->y;
2420 pNewWindowRect->right += pWinpos->x - wndPtr->rectWindow.left;
2421 pNewWindowRect->bottom += pWinpos->y - wndPtr->rectWindow.top;
2423 OffsetRect( pNewClientRect, pWinpos->x - wndPtr->rectWindow.left,
2424 pWinpos->y - wndPtr->rectWindow.top );
2427 pWinpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
2428 return TRUE;
2431 /***********************************************************************
2432 * SWP_DoNCCalcSize
2434 static UINT SWP_DoNCCalcSize( WND* wndPtr, WINDOWPOS* pWinpos,
2435 RECT* pNewWindowRect, RECT* pNewClientRect, WORD f)
2437 UINT wvrFlags = 0;
2439 /* Send WM_NCCALCSIZE message to get new client area */
2440 if( (pWinpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
2442 wvrFlags = WINPOS_SendNCCalcSize( pWinpos->hwnd, TRUE, pNewWindowRect,
2443 &wndPtr->rectWindow, &wndPtr->rectClient,
2444 pWinpos, pNewClientRect );
2446 /* FIXME: WVR_ALIGNxxx */
2448 if( pNewClientRect->left != wndPtr->rectClient.left ||
2449 pNewClientRect->top != wndPtr->rectClient.top )
2450 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2452 if( (pNewClientRect->right - pNewClientRect->left !=
2453 wndPtr->rectClient.right - wndPtr->rectClient.left) ||
2454 (pNewClientRect->bottom - pNewClientRect->top !=
2455 wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
2456 pWinpos->flags &= ~SWP_NOCLIENTSIZE;
2458 else
2459 if( !(f & SWP_NOMOVE) && (pNewClientRect->left != wndPtr->rectClient.left ||
2460 pNewClientRect->top != wndPtr->rectClient.top) )
2461 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2462 return wvrFlags;
2465 /***********************************************************************
2466 * SetWindowPos (USER.2)
2468 BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
2469 INT16 x, INT16 y, INT16 cx, INT16 cy, WORD flags)
2471 return SetWindowPos(hwnd,(INT)(INT16)hwndInsertAfter,x,y,cx,cy,flags);
2474 /***********************************************************************
2475 * SetWindowPos (USER32.520)
2477 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
2478 INT x, INT y, INT cx, INT cy, UINT flags )
2480 WINDOWPOS winpos;
2481 WND * wndPtr,*wndTemp;
2482 RECT newWindowRect, newClientRect;
2483 RECT oldWindowRect, oldClientRect;
2484 HRGN visRgn = 0;
2485 UINT wvrFlags = 0, uFlags = 0;
2486 BOOL retvalue, resync = FALSE, bChangePos;
2487 HWND hwndActive = 0;
2489 /* Get current active window from the active queue */
2490 if ( hActiveQueue )
2492 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2493 if ( pActiveQueue )
2495 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2496 QUEUE_Unlock( pActiveQueue );
2500 TRACE("hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2501 hwnd, x, y, x+cx, y+cy, flags);
2503 bChangePos = !(flags & SWP_WINE_NOHOSTMOVE);
2504 flags &= ~SWP_WINE_NOHOSTMOVE;
2507 /* ------------------------------------------------------------------------ CHECKS */
2509 /* Check window handle */
2511 if (hwnd == GetDesktopWindow()) return FALSE;
2512 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2514 TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr->rectWindow.left, wndPtr->rectWindow.top,
2515 wndPtr->rectWindow.right, wndPtr->rectWindow.bottom, (unsigned)wndPtr->dwStyle );
2517 /* Fix redundant flags */
2519 if(wndPtr->dwStyle & WS_VISIBLE)
2520 flags &= ~SWP_SHOWWINDOW;
2521 else
2523 if (!(flags & SWP_SHOWWINDOW))
2524 flags |= SWP_NOREDRAW;
2525 flags &= ~SWP_HIDEWINDOW;
2528 if ( cx < 0 ) cx = 0; if( cy < 0 ) cy = 0;
2530 if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
2531 (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
2532 flags |= SWP_NOSIZE; /* Already the right size */
2534 if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
2535 flags |= SWP_NOMOVE; /* Already the right position */
2537 if (hwnd == hwndActive)
2538 flags |= SWP_NOACTIVATE; /* Already active */
2539 else if ( (wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD )
2541 if(!(flags & SWP_NOACTIVATE)) /* Bring to the top when activating */
2543 flags &= ~SWP_NOZORDER;
2544 hwndInsertAfter = HWND_TOP;
2545 goto Pos;
2549 /* Check hwndInsertAfter */
2551 /* FIXME: TOPMOST not supported yet */
2552 if ((hwndInsertAfter == HWND_TOPMOST) ||
2553 (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
2555 /* hwndInsertAfter must be a sibling of the window */
2556 if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
2558 WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
2560 if( wnd ) {
2561 if( wnd->parent != wndPtr->parent )
2563 retvalue = FALSE;
2564 WIN_ReleaseWndPtr(wnd);
2565 goto END;
2567 if( wnd->next == wndPtr ) flags |= SWP_NOZORDER;
2569 WIN_ReleaseWndPtr(wnd);
2572 Pos: /* ------------------------------------------------------------------------ MAIN part */
2574 /* Fill the WINDOWPOS structure */
2576 winpos.hwnd = hwnd;
2577 winpos.hwndInsertAfter = hwndInsertAfter;
2578 winpos.x = x;
2579 winpos.y = y;
2580 winpos.cx = cx;
2581 winpos.cy = cy;
2582 winpos.flags = flags;
2584 SWP_DoWinPosChanging( wndPtr, &winpos, &newWindowRect, &newClientRect );
2586 if((winpos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER)
2588 if( wndPtr->parent == WIN_GetDesktop() )
2589 hwndInsertAfter = SWP_DoOwnedPopups( wndPtr->parent, wndPtr,
2590 hwndInsertAfter, winpos.flags );
2591 WIN_ReleaseDesktop();
2594 if(!(wndPtr->flags & WIN_NATIVE) )
2596 if( hwndInsertAfter == HWND_TOP )
2597 winpos.flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
2598 else
2599 if( hwndInsertAfter == HWND_BOTTOM )
2600 winpos.flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
2601 else
2602 if( !(winpos.flags & SWP_NOZORDER) )
2603 if( GetWindow(hwndInsertAfter, GW_HWNDNEXT) == wndPtr->hwndSelf )
2604 winpos.flags |= SWP_NOZORDER;
2606 if( !(winpos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) &&
2607 ((winpos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW | SWP_FRAMECHANGED))
2608 != (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)) )
2610 /* get a previous visible region for SWP_CopyValidBits() */
2611 DWORD flags = DCX_WINDOW;
2613 if (wndPtr->dwStyle & WS_CLIPSIBLINGS)
2614 flags |= DCX_CLIPSIBLINGS;
2616 visRgn = DCE_GetVisRgn(hwnd, flags, 0, 0);
2620 /* Common operations */
2622 wvrFlags = SWP_DoNCCalcSize( wndPtr, &winpos, &newWindowRect, &newClientRect, flags );
2624 if(!(winpos.flags & SWP_NOZORDER))
2626 if ( WIN_UnlinkWindow( winpos.hwnd ) )
2627 WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
2630 /* Reset active DCEs */
2632 if( (((winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) &&
2633 wndPtr->dwStyle & WS_VISIBLE) ||
2634 (flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
2636 RECT rect;
2638 UnionRect(&rect, &newWindowRect, &wndPtr->rectWindow);
2639 DCE_InvalidateDCE(wndPtr, &rect);
2642 oldWindowRect = wndPtr->rectWindow;
2643 oldClientRect = wndPtr->rectClient;
2645 /* Find out if we have to redraw the whole client rect */
2647 if( oldClientRect.bottom - oldClientRect.top ==
2648 newClientRect.bottom - newClientRect.top ) wvrFlags &= ~WVR_VREDRAW;
2650 if( oldClientRect.right - oldClientRect.left ==
2651 newClientRect.right - newClientRect.left ) wvrFlags &= ~WVR_HREDRAW;
2653 if( (winpos.flags & SWP_NOCOPYBITS) || (!(winpos.flags & SWP_NOCLIENTSIZE) &&
2654 (wvrFlags >= WVR_HREDRAW) && (wvrFlags < WVR_VALIDRECTS)) )
2656 uFlags |= SWP_EX_NOCOPY;
2659 * Use this later in CopyValidBits()
2661 else if( 0 )
2662 uFlags |= SWP_EX_NONCLIENT;
2665 /* FIXME: actually do something with WVR_VALIDRECTS */
2667 wndPtr->rectWindow = newWindowRect;
2668 wndPtr->rectClient = newClientRect;
2670 if (wndPtr->flags & WIN_NATIVE) /* -------------------------------------------- hosted window */
2672 BOOL bCallDriver = TRUE;
2673 HWND tempInsertAfter = winpos.hwndInsertAfter;
2675 winpos.hwndInsertAfter = hwndInsertAfter;
2677 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2679 /* This is the only place where we need to force repainting of the contents
2680 of windows created by the host window system, all other cases go through the
2681 expose event handling */
2683 if( (winpos.flags & (SWP_NOSIZE | SWP_FRAMECHANGED)) == (SWP_NOSIZE | SWP_FRAMECHANGED) )
2685 cx = newWindowRect.right - newWindowRect.left;
2686 cy = newWindowRect.bottom - newWindowRect.top;
2688 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2689 winpos.hwndInsertAfter = tempInsertAfter;
2690 bCallDriver = FALSE;
2692 if( winpos.flags & SWP_NOCLIENTMOVE )
2693 SWP_DoSimpleFrameChanged(wndPtr, &oldClientRect, winpos.flags, uFlags );
2694 else
2696 /* client area moved but window extents remained the same, copy valid bits */
2698 visRgn = CreateRectRgn( 0, 0, cx, cy );
2699 uFlags = SWP_CopyValidBits( wndPtr, &visRgn, &oldWindowRect, &oldClientRect,
2700 uFlags | SWP_EX_PAINTSELF );
2705 if( bCallDriver )
2707 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2709 if( (oldClientRect.left - oldWindowRect.left == newClientRect.left - newWindowRect.left) &&
2710 (oldClientRect.top - oldWindowRect.top == newClientRect.top - newWindowRect.top) &&
2711 !(uFlags & SWP_EX_NOCOPY) )
2713 /* The origin of the client rect didn't move so we can try to repaint
2714 * only the nonclient area by setting bit gravity hint for the host window system.
2717 if( !(wndPtr->flags & WIN_MANAGED) )
2719 HRGN hrgn = CreateRectRgn( 0, 0, newWindowRect.right - newWindowRect.left,
2720 newWindowRect.bottom - newWindowRect.top);
2721 RECT rcn = newClientRect;
2722 RECT rco = oldClientRect;
2724 OffsetRect( &rcn, -newWindowRect.left, -newWindowRect.top );
2725 OffsetRect( &rco, -oldWindowRect.left, -oldWindowRect.top );
2726 IntersectRect( &rcn, &rcn, &rco );
2727 visRgn = CreateRectRgnIndirect( &rcn );
2728 CombineRgn( visRgn, hrgn, visRgn, RGN_DIFF );
2729 DeleteObject( hrgn );
2730 uFlags = SWP_EX_PAINTSELF;
2732 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGNorthWest );
2734 else
2735 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGForget );
2738 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2739 winpos.hwndInsertAfter = tempInsertAfter;
2742 if( winpos.flags & SWP_SHOWWINDOW )
2744 HWND focus, curr;
2746 wndPtr->dwStyle |= WS_VISIBLE;
2748 if (wndPtr->flags & WIN_MANAGED) resync = TRUE;
2750 /* focus was set to unmapped window, reset host focus
2751 * since the window is now visible */
2753 focus = curr = GetFocus();
2754 while (curr)
2756 if (curr == hwnd)
2758 WND *pFocus = WIN_FindWndPtr( focus );
2759 if (pFocus)
2760 pFocus->pDriver->pSetFocus(pFocus);
2761 WIN_ReleaseWndPtr(pFocus);
2762 break;
2764 curr = GetParent(curr);
2768 else /* -------------------------------------------- emulated window */
2770 if( winpos.flags & SWP_SHOWWINDOW )
2772 wndPtr->dwStyle |= WS_VISIBLE;
2773 uFlags |= SWP_EX_PAINTSELF;
2774 visRgn = 1; /* redraw the whole window */
2776 else if( !(winpos.flags & SWP_NOREDRAW) )
2778 if( winpos.flags & SWP_HIDEWINDOW )
2780 if( visRgn > 1 ) /* map to parent */
2781 OffsetRgn( visRgn, oldWindowRect.left, oldWindowRect.top );
2782 else
2783 visRgn = 0;
2785 else
2787 if( (winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE )
2788 uFlags = SWP_CopyValidBits(wndPtr, &visRgn, &oldWindowRect,
2789 &oldClientRect, uFlags);
2790 else
2792 /* nothing moved, redraw frame if needed */
2794 if( winpos.flags & SWP_FRAMECHANGED )
2795 SWP_DoSimpleFrameChanged( wndPtr, &oldClientRect, winpos.flags, uFlags );
2796 if( visRgn )
2798 DeleteObject( visRgn );
2799 visRgn = 0;
2806 if( winpos.flags & SWP_HIDEWINDOW )
2808 wndPtr->dwStyle &= ~WS_VISIBLE;
2810 if (hwnd == CARET_GetHwnd()) DestroyCaret();
2812 /* FIXME: This will cause the window to be activated irrespective
2813 * of whether it is owned by the same thread. Has to be done
2814 * asynchronously.
2817 if (winpos.hwnd == hwndActive)
2818 WINPOS_ActivateOtherWindow( wndPtr );
2821 /* ------------------------------------------------------------------------ FINAL */
2823 if (wndPtr->flags & WIN_NATIVE)
2824 EVENT_Synchronize(); /* Synchronize with the host window system */
2826 if (!GetCapture() && ((wndPtr->dwStyle & WS_VISIBLE) || (flags & SWP_HIDEWINDOW)))
2828 /* Simulate a mouse event to set the cursor */
2829 DWORD posX, posY, keyState;
2831 if ( EVENT_QueryPointer( &posX, &posY, &keyState ) )
2833 int iWndsLocks = WIN_SuspendWndsLock();
2835 hardware_event( WM_MOUSEMOVE, keyState, 0,
2836 posX, posY, GetTickCount(), 0 );
2838 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;