One small error corrected and the 102th key...
[wine/wine-kai.git] / windows / winpos.c
blobdbe7ec156c2fa9ffd560041e7d10dc3bf372191f
1 /*
2 * Window position related functions.
4 * Copyright 1993, 1994, 1995 Alexandre Julliard
5 * 1995, 1996 Alex Korobka
6 */
8 #include "x11drv.h"
10 #include <string.h>
11 #include "sysmetrics.h"
12 #include "heap.h"
13 #include "module.h"
14 #include "user.h"
15 #include "win.h"
16 #include "hook.h"
17 #include "message.h"
18 #include "queue.h"
19 #include "options.h"
20 #include "task.h"
21 #include "winpos.h"
22 #include "dce.h"
23 #include "nonclient.h"
24 #include "debug.h"
25 #include "local.h"
26 #include "ldt.h"
28 #define HAS_DLGFRAME(style,exStyle) \
29 (((exStyle) & WS_EX_DLGMODALFRAME) || \
30 (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
32 #define HAS_THICKFRAME(style) \
33 (((style) & WS_THICKFRAME) && \
34 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
36 #define SWP_AGG_NOGEOMETRYCHANGE \
37 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
38 #define SWP_AGG_NOPOSCHANGE \
39 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
40 #define SWP_AGG_STATUSFLAGS \
41 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
43 #define EMPTYPOINT(pt) ((*(LONG*)&(pt)) == -1)
45 #define PLACE_MIN 0x0001
46 #define PLACE_MAX 0x0002
47 #define PLACE_RECT 0x0004
49 #define SMC_NOCOPY 0x0001
50 #define SMC_NOPARENTERASE 0x0002
51 #define SMC_DRAWFRAME 0x0004
52 #define SMC_SETXPOS 0x0008
54 /* ----- internal variables ----- */
56 static HWND hwndPrevActive = 0; /* Previously active window */
57 static HWND hGlobalShellWindow=0; /*the shell*/
59 static LPCSTR atomInternalPos;
61 extern HQUEUE16 hActiveQueue;
63 /***********************************************************************
64 * WINPOS_CreateInternalPosAtom
66 BOOL WINPOS_CreateInternalPosAtom()
68 LPSTR str = "SysIP";
69 atomInternalPos = (LPCSTR)(DWORD)GlobalAddAtomA(str);
70 return (atomInternalPos) ? TRUE : FALSE;
73 /***********************************************************************
74 * WINPOS_CheckInternalPos
76 * Called when a window is destroyed.
78 void WINPOS_CheckInternalPos( WND* wndPtr )
80 LPINTERNALPOS lpPos;
81 MESSAGEQUEUE *pMsgQ = 0;
82 HWND hwnd = wndPtr->hwndSelf;
84 lpPos = (LPINTERNALPOS) GetPropA( hwnd, atomInternalPos );
86 /* Retrieve the message queue associated with this window */
87 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
88 if ( !pMsgQ )
90 WARN( win, "\tMessage queue not found. Exiting!\n" );
91 return;
94 if( hwnd == hwndPrevActive ) hwndPrevActive = 0;
96 if( hwnd == PERQDATA_GetActiveWnd( pMsgQ->pQData ) )
98 PERQDATA_SetActiveWnd( pMsgQ->pQData, 0 );
99 WARN(win, "\tattempt to activate destroyed window!\n");
102 if( lpPos )
104 if( IsWindow(lpPos->hwndIconTitle) )
105 DestroyWindow( lpPos->hwndIconTitle );
106 HeapFree( SystemHeap, 0, lpPos );
109 QUEUE_Unlock( pMsgQ );
110 return;
113 /***********************************************************************
114 * WINPOS_FindIconPos
116 * Find a suitable place for an iconic window.
118 static POINT16 WINPOS_FindIconPos( WND* wndPtr, POINT16 pt )
120 RECT16 rectParent;
121 short x, y, xspacing, yspacing;
123 GetClientRect16( wndPtr->parent->hwndSelf, &rectParent );
124 if ((pt.x >= rectParent.left) && (pt.x + SYSMETRICS_CXICON < rectParent.right) &&
125 (pt.y >= rectParent.top) && (pt.y + SYSMETRICS_CYICON < rectParent.bottom))
126 return pt; /* The icon already has a suitable position */
128 xspacing = SYSMETRICS_CXICONSPACING;
129 yspacing = SYSMETRICS_CYICONSPACING;
131 y = rectParent.bottom;
132 for (;;)
134 for (x = rectParent.left; x <= rectParent.right-xspacing; x += xspacing)
136 /* Check if another icon already occupies this spot */
137 WND *childPtr = WIN_LockWndPtr(wndPtr->parent->child);
138 while (childPtr)
140 if ((childPtr->dwStyle & WS_MINIMIZE) && (childPtr != wndPtr))
142 if ((childPtr->rectWindow.left < x + xspacing) &&
143 (childPtr->rectWindow.right >= x) &&
144 (childPtr->rectWindow.top <= y) &&
145 (childPtr->rectWindow.bottom > y - yspacing))
146 break; /* There's a window in there */
148 WIN_UpdateWndPtr(&childPtr,childPtr->next);
150 WIN_ReleaseWndPtr(childPtr);
151 if (!childPtr) /* No window was found, so it's OK for us */
153 pt.x = x + (xspacing - SYSMETRICS_CXICON) / 2;
154 pt.y = y - (yspacing + SYSMETRICS_CYICON) / 2;
155 return pt;
158 y -= yspacing;
163 /***********************************************************************
164 * ArrangeIconicWindows16 (USER.170)
166 UINT16 WINAPI ArrangeIconicWindows16( HWND16 parent)
168 return ArrangeIconicWindows(parent);
170 /***********************************************************************
171 * ArrangeIconicWindows (USER32.7)
173 UINT WINAPI ArrangeIconicWindows( HWND parent )
175 RECT rectParent;
176 HWND hwndChild;
177 INT x, y, xspacing, yspacing;
179 GetClientRect( parent, &rectParent );
180 x = rectParent.left;
181 y = rectParent.bottom;
182 xspacing = SYSMETRICS_CXICONSPACING;
183 yspacing = SYSMETRICS_CYICONSPACING;
185 hwndChild = GetWindow( parent, GW_CHILD );
186 while (hwndChild)
188 if( IsIconic( hwndChild ) )
190 WND *wndPtr = WIN_FindWndPtr(hwndChild);
192 WINPOS_ShowIconTitle( wndPtr, FALSE );
194 SetWindowPos( hwndChild, 0, x + (xspacing - SYSMETRICS_CXICON) / 2,
195 y - yspacing - SYSMETRICS_CYICON/2, 0, 0,
196 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
197 if( IsWindow(hwndChild) )
198 WINPOS_ShowIconTitle(wndPtr , TRUE );
199 WIN_ReleaseWndPtr(wndPtr);
201 if (x <= rectParent.right - xspacing) x += xspacing;
202 else
204 x = rectParent.left;
205 y -= yspacing;
208 hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
210 return yspacing;
214 /***********************************************************************
215 * SwitchToThisWindow16 (USER.172)
217 void WINAPI SwitchToThisWindow16( HWND16 hwnd, BOOL16 restore )
219 SwitchToThisWindow( hwnd, restore );
223 /***********************************************************************
224 * SwitchToThisWindow (USER32.539)
226 void WINAPI SwitchToThisWindow( HWND hwnd, BOOL restore )
228 ShowWindow( hwnd, restore ? SW_RESTORE : SW_SHOWMINIMIZED );
232 /***********************************************************************
233 * GetWindowRect16 (USER.32)
235 void WINAPI GetWindowRect16( HWND16 hwnd, LPRECT16 rect )
237 WND * wndPtr = WIN_FindWndPtr( hwnd );
238 if (!wndPtr) return;
240 CONV_RECT32TO16( &wndPtr->rectWindow, rect );
241 if (wndPtr->dwStyle & WS_CHILD)
242 MapWindowPoints16( wndPtr->parent->hwndSelf, 0, (POINT16 *)rect, 2 );
243 WIN_ReleaseWndPtr(wndPtr);
247 /***********************************************************************
248 * GetWindowRect (USER32.308)
250 BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect )
252 WND * wndPtr = WIN_FindWndPtr( hwnd );
253 if (!wndPtr) return FALSE;
255 *rect = wndPtr->rectWindow;
256 if (wndPtr->dwStyle & WS_CHILD)
257 MapWindowPoints( wndPtr->parent->hwndSelf, 0, (POINT *)rect, 2 );
258 WIN_ReleaseWndPtr(wndPtr);
259 return TRUE;
263 /***********************************************************************
264 * GetWindowRgn
266 BOOL WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
269 RECT rect;
270 WND * wndPtr = WIN_FindWndPtr( hwnd );
271 if (!wndPtr) return (ERROR);
273 FIXME (win, "GetWindowRgn: doesn't really do regions\n");
275 memset (&rect, 0, sizeof(rect));
277 GetWindowRect ( hwnd, &rect );
279 FIXME (win, "Check whether a valid region here\n");
281 SetRectRgn ( hrgn, rect.left, rect.top, rect.right, rect.bottom );
283 WIN_ReleaseWndPtr(wndPtr);
284 return (SIMPLEREGION);
287 /***********************************************************************
288 * SetWindowRgn
290 INT WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn,BOOL bRedraw)
294 FIXME (win, "SetWindowRgn: stub\n");
295 return TRUE;
298 /***********************************************************************
299 * SetWindowRgn16
301 INT16 WINAPI SetWindowRgn16( HWND16 hwnd, HRGN16 hrgn,BOOL16 bRedraw)
305 FIXME (win, "SetWindowRgn16: stub\n");
306 return TRUE;
310 /***********************************************************************
311 * GetClientRect16 (USER.33)
313 void WINAPI GetClientRect16( HWND16 hwnd, LPRECT16 rect )
315 WND * wndPtr = WIN_FindWndPtr( hwnd );
317 rect->left = rect->top = rect->right = rect->bottom = 0;
318 if (wndPtr)
320 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
321 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
323 WIN_ReleaseWndPtr(wndPtr);
327 /***********************************************************************
328 * GetClientRect (USER.220)
330 BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect )
332 WND * wndPtr = WIN_FindWndPtr( hwnd );
334 rect->left = rect->top = rect->right = rect->bottom = 0;
335 if (!wndPtr) return FALSE;
336 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
337 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
339 WIN_ReleaseWndPtr(wndPtr);
340 return TRUE;
344 /*******************************************************************
345 * ClientToScreen16 (USER.28)
347 void WINAPI ClientToScreen16( HWND16 hwnd, LPPOINT16 lppnt )
349 MapWindowPoints16( hwnd, 0, lppnt, 1 );
353 /*******************************************************************
354 * ClientToScreen (USER32.52)
356 BOOL WINAPI ClientToScreen( HWND hwnd, LPPOINT lppnt )
358 MapWindowPoints( hwnd, 0, lppnt, 1 );
359 return TRUE;
363 /*******************************************************************
364 * ScreenToClient16 (USER.29)
366 void WINAPI ScreenToClient16( HWND16 hwnd, LPPOINT16 lppnt )
368 MapWindowPoints16( 0, hwnd, lppnt, 1 );
372 /*******************************************************************
373 * ScreenToClient (USER32.447)
375 BOOL WINAPI ScreenToClient( HWND hwnd, LPPOINT lppnt )
377 MapWindowPoints( 0, hwnd, lppnt, 1 );
378 return TRUE;
382 /***********************************************************************
383 * WINPOS_WindowFromPoint
385 * Find the window and hittest for a given point.
387 INT16 WINPOS_WindowFromPoint( WND* wndScope, POINT16 pt, WND **ppWnd )
389 WND *wndPtr;
390 INT16 hittest = HTERROR;
391 INT16 retvalue;
392 POINT16 xy = pt;
394 *ppWnd = NULL;
395 wndPtr = WIN_LockWndPtr(wndScope->child);
397 if( wndScope->flags & WIN_MANAGED )
399 /* this prevents mouse clicks from going "through" scrollbars in managed mode */
400 if( pt.x < wndScope->rectClient.left || pt.x >= wndScope->rectClient.right ||
401 pt.y < wndScope->rectClient.top || pt.y >= wndScope->rectClient.bottom )
402 goto hittest;
404 MapWindowPoints16( GetDesktopWindow16(), wndScope->hwndSelf, &xy, 1 );
406 for (;;)
408 while (wndPtr)
410 /* If point is in window, and window is visible, and it */
411 /* is enabled (or it's a top-level window), then explore */
412 /* its children. Otherwise, go to the next window. */
414 if ((wndPtr->dwStyle & WS_VISIBLE) &&
415 (!(wndPtr->dwStyle & WS_DISABLED) ||
416 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)) &&
417 (xy.x >= wndPtr->rectWindow.left) &&
418 (xy.x < wndPtr->rectWindow.right) &&
419 (xy.y >= wndPtr->rectWindow.top) &&
420 (xy.y < wndPtr->rectWindow.bottom))
422 *ppWnd = wndPtr; /* Got a suitable window */
424 /* If window is minimized or disabled, return at once */
425 if (wndPtr->dwStyle & WS_MINIMIZE)
427 retvalue = HTCAPTION;
428 goto end;
430 if (wndPtr->dwStyle & WS_DISABLED)
432 retvalue = HTERROR;
433 goto end;
436 /* If point is not in client area, ignore the children */
437 if ((xy.x < wndPtr->rectClient.left) ||
438 (xy.x >= wndPtr->rectClient.right) ||
439 (xy.y < wndPtr->rectClient.top) ||
440 (xy.y >= wndPtr->rectClient.bottom)) break;
442 xy.x -= wndPtr->rectClient.left;
443 xy.y -= wndPtr->rectClient.top;
444 WIN_UpdateWndPtr(&wndPtr,wndPtr->child);
446 else
448 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
452 hittest:
453 /* If nothing found, try the scope window */
454 if (!*ppWnd) *ppWnd = wndScope;
456 /* Send the WM_NCHITTEST message (only if to the same task) */
457 if ((*ppWnd)->hmemTaskQ == GetFastQueue16())
459 hittest = (INT16)SendMessage16( (*ppWnd)->hwndSelf, WM_NCHITTEST,
460 0, MAKELONG( pt.x, pt.y ) );
461 if (hittest != HTTRANSPARENT)
463 retvalue = hittest; /* Found the window */
464 goto end;
467 else
469 retvalue = HTCLIENT;
470 goto end;
473 /* If no children found in last search, make point relative to parent */
474 if (!wndPtr)
476 xy.x += (*ppWnd)->rectClient.left;
477 xy.y += (*ppWnd)->rectClient.top;
480 /* Restart the search from the next sibling */
481 WIN_UpdateWndPtr(&wndPtr,(*ppWnd)->next);
482 *ppWnd = (*ppWnd)->parent;
485 end:
486 WIN_ReleaseWndPtr(wndPtr);
487 return retvalue;
491 /*******************************************************************
492 * WindowFromPoint16 (USER.30)
494 HWND16 WINAPI WindowFromPoint16( POINT16 pt )
496 WND *pWnd;
497 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt, &pWnd );
498 WIN_ReleaseDesktop();
499 return pWnd->hwndSelf;
503 /*******************************************************************
504 * WindowFromPoint (USER32.582)
506 HWND WINAPI WindowFromPoint( POINT pt )
508 WND *pWnd;
509 POINT16 pt16;
510 CONV_POINT32TO16( &pt, &pt16 );
511 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16, &pWnd );
512 WIN_ReleaseDesktop();
513 return (HWND)pWnd->hwndSelf;
517 /*******************************************************************
518 * ChildWindowFromPoint16 (USER.191)
520 HWND16 WINAPI ChildWindowFromPoint16( HWND16 hwndParent, POINT16 pt )
522 POINT pt32;
523 CONV_POINT16TO32( &pt, &pt32 );
524 return (HWND16)ChildWindowFromPoint( hwndParent, pt32 );
528 /*******************************************************************
529 * ChildWindowFromPoint (USER32.49)
531 HWND WINAPI ChildWindowFromPoint( HWND hwndParent, POINT pt )
533 /* pt is in the client coordinates */
535 WND* wnd = WIN_FindWndPtr(hwndParent);
536 RECT rect;
537 HWND retvalue;
539 if( !wnd ) return 0;
541 /* get client rect fast */
542 rect.top = rect.left = 0;
543 rect.right = wnd->rectClient.right - wnd->rectClient.left;
544 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
546 if (!PtInRect( &rect, pt ))
548 retvalue = 0;
549 goto end;
551 WIN_UpdateWndPtr(&wnd,wnd->child);
552 while ( wnd )
554 if (PtInRect( &wnd->rectWindow, pt ))
556 retvalue = wnd->hwndSelf;
557 goto end;
559 WIN_UpdateWndPtr(&wnd,wnd->next);
561 retvalue = hwndParent;
562 end:
563 WIN_ReleaseWndPtr(wnd);
564 return retvalue;
567 /*******************************************************************
568 * ChildWindowFromPointEx16 (USER.50)
570 HWND16 WINAPI ChildWindowFromPointEx16( HWND16 hwndParent, POINT16 pt, UINT16 uFlags)
572 POINT pt32;
573 CONV_POINT16TO32( &pt, &pt32 );
574 return (HWND16)ChildWindowFromPointEx( hwndParent, pt32, uFlags );
578 /*******************************************************************
579 * ChildWindowFromPointEx32 (USER32.50)
581 HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt,
582 UINT uFlags)
584 /* pt is in the client coordinates */
586 WND* wnd = WIN_FindWndPtr(hwndParent);
587 RECT rect;
588 HWND retvalue;
590 if( !wnd ) return 0;
592 /* get client rect fast */
593 rect.top = rect.left = 0;
594 rect.right = wnd->rectClient.right - wnd->rectClient.left;
595 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
597 if (!PtInRect( &rect, pt ))
599 retvalue = 0;
600 goto end;
602 WIN_UpdateWndPtr(&wnd,wnd->child);
604 while ( wnd )
606 if (PtInRect( &wnd->rectWindow, pt )) {
607 if ( (uFlags & CWP_SKIPINVISIBLE) &&
608 !(wnd->dwStyle & WS_VISIBLE) );
609 else if ( (uFlags & CWP_SKIPDISABLED) &&
610 (wnd->dwStyle & WS_DISABLED) );
611 else if ( (uFlags & CWP_SKIPTRANSPARENT) &&
612 (wnd->dwExStyle & WS_EX_TRANSPARENT) );
613 else
615 retvalue = wnd->hwndSelf;
616 goto end;
618 WIN_UpdateWndPtr(&wnd,wnd->next);
622 retvalue = hwndParent;
623 end:
624 WIN_ReleaseWndPtr(wnd);
625 return retvalue;
629 /*******************************************************************
630 * WINPOS_GetWinOffset
632 * Calculate the offset between the origin of the two windows. Used
633 * to implement MapWindowPoints.
635 static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo,
636 POINT *offset )
638 WND * wndPtr = 0;
640 offset->x = offset->y = 0;
641 if (hwndFrom == hwndTo ) return;
643 /* Translate source window origin to screen coords */
644 if (hwndFrom)
646 if (!(wndPtr = WIN_FindWndPtr( hwndFrom )))
648 ERR(win,"bad hwndFrom = %04x\n",hwndFrom);
649 return;
651 while (wndPtr->parent)
653 offset->x += wndPtr->rectClient.left;
654 offset->y += wndPtr->rectClient.top;
655 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
659 /* Translate origin to destination window coords */
660 if (hwndTo)
662 if (!(wndPtr = WIN_FindWndPtr( hwndTo )))
664 ERR(win,"bad hwndTo = %04x\n", hwndTo );
665 return;
667 while (wndPtr->parent)
669 offset->x -= wndPtr->rectClient.left;
670 offset->y -= wndPtr->rectClient.top;
671 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
674 WIN_ReleaseWndPtr(wndPtr);
678 /*******************************************************************
679 * MapWindowPoints16 (USER.258)
681 void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
682 LPPOINT16 lppt, UINT16 count )
684 POINT offset;
686 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
687 while (count--)
689 lppt->x += offset.x;
690 lppt->y += offset.y;
691 lppt++;
696 /*******************************************************************
697 * MapWindowPoints (USER32.386)
699 INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo,
700 LPPOINT lppt, UINT count )
702 POINT offset;
704 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
705 while (count--)
707 lppt->x += offset.x;
708 lppt->y += offset.y;
709 lppt++;
711 return MAKELONG( LOWORD(offset.x), LOWORD(offset.y) );
715 /***********************************************************************
716 * IsIconic16 (USER.31)
718 BOOL16 WINAPI IsIconic16(HWND16 hWnd)
720 return IsIconic(hWnd);
724 /***********************************************************************
725 * IsIconic (USER32.345)
727 BOOL WINAPI IsIconic(HWND hWnd)
729 BOOL retvalue;
730 WND * wndPtr = WIN_FindWndPtr(hWnd);
731 if (wndPtr == NULL) return FALSE;
732 retvalue = (wndPtr->dwStyle & WS_MINIMIZE) != 0;
733 WIN_ReleaseWndPtr(wndPtr);
734 return retvalue;
738 /***********************************************************************
739 * IsZoomed (USER.272)
741 BOOL16 WINAPI IsZoomed16(HWND16 hWnd)
743 return IsZoomed(hWnd);
747 /***********************************************************************
748 * IsZoomed (USER.352)
750 BOOL WINAPI IsZoomed(HWND hWnd)
752 BOOL retvalue;
753 WND * wndPtr = WIN_FindWndPtr(hWnd);
754 if (wndPtr == NULL) return FALSE;
755 retvalue = (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
756 WIN_ReleaseWndPtr(wndPtr);
757 return retvalue;
761 /*******************************************************************
762 * GetActiveWindow (USER.60)
764 HWND16 WINAPI GetActiveWindow16(void)
766 return (HWND16)GetActiveWindow();
769 /*******************************************************************
770 * GetActiveWindow (USER32.205)
772 HWND WINAPI GetActiveWindow(void)
774 MESSAGEQUEUE *pCurMsgQ = 0;
775 HWND hwndActive = 0;
777 /* Get the messageQ for the current thread */
778 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
780 WARN( win, "\tCurrent message queue not found. Exiting!\n" );
781 return 0;
784 /* Return the current active window from the perQ data of the current message Q */
785 hwndActive = PERQDATA_GetActiveWnd( pCurMsgQ->pQData );
787 QUEUE_Unlock( pCurMsgQ );
788 return hwndActive;
792 /*******************************************************************
793 * WINPOS_CanActivate
795 static BOOL WINPOS_CanActivate(WND* pWnd)
797 if( pWnd && ((pWnd->dwStyle & (WS_DISABLED | WS_VISIBLE | WS_CHILD))
798 == WS_VISIBLE) ) return TRUE;
799 return FALSE;
803 /*******************************************************************
804 * SetActiveWindow16 (USER.59)
806 HWND16 WINAPI SetActiveWindow16( HWND16 hwnd )
808 return SetActiveWindow(hwnd);
812 /*******************************************************************
813 * SetActiveWindow (USER32.463)
815 HWND WINAPI SetActiveWindow( HWND hwnd )
817 HWND prev = 0;
818 WND *wndPtr = WIN_FindWndPtr( hwnd );
819 MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
821 if ( !WINPOS_CanActivate(wndPtr) )
823 prev = 0;
824 goto end;
827 /* Get the messageQ for the current thread */
828 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
830 WARN( win, "\tCurrent message queue not found. Exiting!\n" );
831 goto CLEANUP;
834 /* Retrieve the message queue associated with this window */
835 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
836 if ( !pMsgQ )
838 WARN( win, "\tWindow message queue not found. Exiting!\n" );
839 goto CLEANUP;
842 /* Make sure that the window is associated with the calling threads
843 * message queue. It must share the same perQ data.
846 if ( pCurMsgQ->pQData != pMsgQ->pQData )
847 goto CLEANUP;
849 /* Save current active window */
850 prev = PERQDATA_GetActiveWnd( pMsgQ->pQData );
852 WINPOS_SetActiveWindow( hwnd, 0, 0 );
854 CLEANUP:
855 /* Unlock the queues before returning */
856 if ( pMsgQ )
857 QUEUE_Unlock( pMsgQ );
858 if ( pCurMsgQ )
859 QUEUE_Unlock( pCurMsgQ );
861 end:
862 WIN_ReleaseWndPtr(wndPtr);
863 return prev;
867 /*******************************************************************
868 * GetForegroundWindow16 (USER.608)
870 HWND16 WINAPI GetForegroundWindow16(void)
872 return (HWND16)GetForegroundWindow();
876 /*******************************************************************
877 * SetForegroundWindow16 (USER.609)
879 BOOL16 WINAPI SetForegroundWindow16( HWND16 hwnd )
881 return SetForegroundWindow( hwnd );
885 /*******************************************************************
886 * GetForegroundWindow (USER32.241)
888 HWND WINAPI GetForegroundWindow(void)
890 return GetActiveWindow();
894 /*******************************************************************
895 * SetForegroundWindow (USER32.482)
897 BOOL WINAPI SetForegroundWindow( HWND hwnd )
899 SetActiveWindow( hwnd );
900 return TRUE;
904 /*******************************************************************
905 * GetShellWindow16 (USER.600)
907 HWND16 WINAPI GetShellWindow16(void)
909 return GetShellWindow();
912 /*******************************************************************
913 * SetShellWindow (USER32.504)
915 HWND WINAPI SetShellWindow(HWND hwndshell)
916 { WARN(win, "(hWnd=%08x) semi stub\n",hwndshell );
918 hGlobalShellWindow = hwndshell;
919 return hGlobalShellWindow;
923 /*******************************************************************
924 * GetShellWindow (USER32.287)
926 HWND WINAPI GetShellWindow(void)
927 { WARN(win, "(hWnd=%x) semi stub\n",hGlobalShellWindow );
929 return hGlobalShellWindow;
933 /***********************************************************************
934 * BringWindowToTop16 (USER.45)
936 BOOL16 WINAPI BringWindowToTop16( HWND16 hwnd )
938 return BringWindowToTop(hwnd);
942 /***********************************************************************
943 * BringWindowToTop (USER32.11)
945 BOOL WINAPI BringWindowToTop( HWND hwnd )
947 return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
951 /***********************************************************************
952 * MoveWindow16 (USER.56)
954 BOOL16 WINAPI MoveWindow16( HWND16 hwnd, INT16 x, INT16 y, INT16 cx, INT16 cy,
955 BOOL16 repaint )
957 return MoveWindow(hwnd,x,y,cx,cy,repaint);
961 /***********************************************************************
962 * MoveWindow (USER32.399)
964 BOOL WINAPI MoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy,
965 BOOL repaint )
967 int flags = SWP_NOZORDER | SWP_NOACTIVATE;
968 if (!repaint) flags |= SWP_NOREDRAW;
969 TRACE(win, "%04x %d,%d %dx%d %d\n",
970 hwnd, x, y, cx, cy, repaint );
971 return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
974 /***********************************************************************
975 * WINPOS_InitInternalPos
977 static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT pt,
978 LPRECT restoreRect )
980 LPINTERNALPOS lpPos = (LPINTERNALPOS) GetPropA( wnd->hwndSelf,
981 atomInternalPos );
982 if( !lpPos )
984 /* this happens when the window is minimized/maximized
985 * for the first time (rectWindow is not adjusted yet) */
987 lpPos = HeapAlloc( SystemHeap, 0, sizeof(INTERNALPOS) );
988 if( !lpPos ) return NULL;
990 SetPropA( wnd->hwndSelf, atomInternalPos, (HANDLE)lpPos );
991 lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
992 CONV_RECT32TO16( &wnd->rectWindow, &lpPos->rectNormal );
993 *(UINT*)&lpPos->ptIconPos = *(UINT*)&lpPos->ptMaxPos = 0xFFFFFFFF;
996 if( wnd->dwStyle & WS_MINIMIZE )
997 CONV_POINT32TO16( &pt, &lpPos->ptIconPos );
998 else if( wnd->dwStyle & WS_MAXIMIZE )
999 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1000 else if( restoreRect )
1001 CONV_RECT32TO16( restoreRect, &lpPos->rectNormal );
1003 return lpPos;
1006 /***********************************************************************
1007 * WINPOS_RedrawIconTitle
1009 BOOL WINPOS_RedrawIconTitle( HWND hWnd )
1011 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hWnd, atomInternalPos );
1012 if( lpPos )
1014 if( lpPos->hwndIconTitle )
1016 SendMessageA( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
1017 InvalidateRect( lpPos->hwndIconTitle, NULL, TRUE );
1018 return TRUE;
1021 return FALSE;
1024 /***********************************************************************
1025 * WINPOS_ShowIconTitle
1027 BOOL WINPOS_ShowIconTitle( WND* pWnd, BOOL bShow )
1029 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( pWnd->hwndSelf, atomInternalPos );
1031 if( lpPos && !(pWnd->flags & WIN_MANAGED))
1033 HWND16 hWnd = lpPos->hwndIconTitle;
1035 TRACE(win,"0x%04x %i\n", pWnd->hwndSelf, (bShow != 0) );
1037 if( !hWnd )
1038 lpPos->hwndIconTitle = hWnd = ICONTITLE_Create( pWnd );
1039 if( bShow )
1041 pWnd = WIN_FindWndPtr(hWnd);
1043 if( !(pWnd->dwStyle & WS_VISIBLE) )
1045 SendMessageA( hWnd, WM_SHOWWINDOW, TRUE, 0 );
1046 SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
1047 SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
1049 WIN_ReleaseWndPtr(pWnd);
1051 else ShowWindow( hWnd, SW_HIDE );
1053 return FALSE;
1056 /*******************************************************************
1057 * WINPOS_GetMinMaxInfo
1059 * Get the minimized and maximized information for a window.
1061 void WINPOS_GetMinMaxInfo( WND *wndPtr, POINT *maxSize, POINT *maxPos,
1062 POINT *minTrack, POINT *maxTrack )
1064 LPINTERNALPOS lpPos;
1065 MINMAXINFO MinMax;
1066 INT xinc, yinc;
1068 /* Compute default values */
1070 MinMax.ptMaxSize.x = SYSMETRICS_CXSCREEN;
1071 MinMax.ptMaxSize.y = SYSMETRICS_CYSCREEN;
1072 MinMax.ptMinTrackSize.x = SYSMETRICS_CXMINTRACK;
1073 MinMax.ptMinTrackSize.y = SYSMETRICS_CYMINTRACK;
1074 MinMax.ptMaxTrackSize.x = SYSMETRICS_CXSCREEN;
1075 MinMax.ptMaxTrackSize.y = SYSMETRICS_CYSCREEN;
1077 if (wndPtr->flags & WIN_MANAGED) xinc = yinc = 0;
1078 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1080 xinc = SYSMETRICS_CXDLGFRAME;
1081 yinc = SYSMETRICS_CYDLGFRAME;
1083 else
1085 xinc = yinc = 0;
1086 if (HAS_THICKFRAME(wndPtr->dwStyle))
1088 xinc += SYSMETRICS_CXFRAME;
1089 yinc += SYSMETRICS_CYFRAME;
1091 if (wndPtr->dwStyle & WS_BORDER)
1093 xinc += SYSMETRICS_CXBORDER;
1094 yinc += SYSMETRICS_CYBORDER;
1097 MinMax.ptMaxSize.x += 2 * xinc;
1098 MinMax.ptMaxSize.y += 2 * yinc;
1100 lpPos = (LPINTERNALPOS)GetPropA( wndPtr->hwndSelf, atomInternalPos );
1101 if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
1102 CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
1103 else
1105 MinMax.ptMaxPosition.x = -xinc;
1106 MinMax.ptMaxPosition.y = -yinc;
1109 SendMessageA( wndPtr->hwndSelf, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
1111 /* Some sanity checks */
1113 TRACE(win,"%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1114 MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
1115 MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
1116 MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
1117 MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
1118 MinMax.ptMaxTrackSize.x = MAX( MinMax.ptMaxTrackSize.x,
1119 MinMax.ptMinTrackSize.x );
1120 MinMax.ptMaxTrackSize.y = MAX( MinMax.ptMaxTrackSize.y,
1121 MinMax.ptMinTrackSize.y );
1123 if (maxSize) *maxSize = MinMax.ptMaxSize;
1124 if (maxPos) *maxPos = MinMax.ptMaxPosition;
1125 if (minTrack) *minTrack = MinMax.ptMinTrackSize;
1126 if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
1129 /***********************************************************************
1130 * WINPOS_MinMaximize
1132 * Fill in lpRect and return additional flags to be used with SetWindowPos().
1133 * This function assumes that 'cmd' is different from the current window
1134 * state.
1136 UINT16 WINPOS_MinMaximize( WND* wndPtr, UINT16 cmd, LPRECT16 lpRect )
1138 UINT16 swpFlags = 0;
1139 POINT pt;
1140 POINT size = { wndPtr->rectWindow.left, wndPtr->rectWindow.top };
1141 LPINTERNALPOS lpPos = WINPOS_InitInternalPos( wndPtr, size,
1142 &wndPtr->rectWindow );
1144 TRACE(win,"0x%04x %u\n", wndPtr->hwndSelf, cmd );
1146 if (lpPos && !HOOK_CallHooks16(WH_CBT, HCBT_MINMAX, wndPtr->hwndSelf, cmd))
1148 if( wndPtr->dwStyle & WS_MINIMIZE )
1150 if( !SendMessageA( wndPtr->hwndSelf, WM_QUERYOPEN, 0, 0L ) )
1151 return (SWP_NOSIZE | SWP_NOMOVE);
1152 swpFlags |= SWP_NOCOPYBITS;
1154 switch( cmd )
1156 case SW_MINIMIZE:
1157 if( wndPtr->dwStyle & WS_MAXIMIZE)
1159 wndPtr->flags |= WIN_RESTORE_MAX;
1160 wndPtr->dwStyle &= ~WS_MAXIMIZE;
1162 else
1163 wndPtr->flags &= ~WIN_RESTORE_MAX;
1164 wndPtr->dwStyle |= WS_MINIMIZE;
1166 lpPos->ptIconPos = WINPOS_FindIconPos( wndPtr, lpPos->ptIconPos );
1168 SetRect16( lpRect, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1169 SYSMETRICS_CXICON, SYSMETRICS_CYICON );
1170 swpFlags |= SWP_NOCOPYBITS;
1171 break;
1173 case SW_MAXIMIZE:
1174 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1175 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL );
1176 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1178 if( wndPtr->dwStyle & WS_MINIMIZE )
1180 WINPOS_ShowIconTitle( wndPtr, FALSE );
1181 wndPtr->dwStyle &= ~WS_MINIMIZE;
1183 wndPtr->dwStyle |= WS_MAXIMIZE;
1185 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1186 size.x, size.y );
1187 break;
1189 case SW_RESTORE:
1190 if( wndPtr->dwStyle & WS_MINIMIZE )
1192 wndPtr->dwStyle &= ~WS_MINIMIZE;
1193 WINPOS_ShowIconTitle( wndPtr, FALSE );
1194 if( wndPtr->flags & WIN_RESTORE_MAX)
1196 /* Restore to maximized position */
1197 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1198 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL);
1199 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1200 wndPtr->dwStyle |= WS_MAXIMIZE;
1201 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y, size.x, size.y );
1202 break;
1205 else
1206 if( !(wndPtr->dwStyle & WS_MAXIMIZE) ) return (UINT16)(-1);
1207 else wndPtr->dwStyle &= ~WS_MAXIMIZE;
1209 /* Restore to normal position */
1211 *lpRect = lpPos->rectNormal;
1212 lpRect->right -= lpRect->left;
1213 lpRect->bottom -= lpRect->top;
1215 break;
1217 } else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
1218 return swpFlags;
1221 /***********************************************************************
1222 * ShowWindowAsync (USER32.535)
1224 * doesn't wait; returns immediately.
1225 * used by threads to toggle windows in other (possibly hanging) threads
1227 BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd )
1229 /* FIXME: does ShowWindow() return immediately ? */
1230 return ShowWindow(hwnd, cmd);
1234 /***********************************************************************
1235 * ShowWindow16 (USER.42)
1237 BOOL16 WINAPI ShowWindow16( HWND16 hwnd, INT16 cmd )
1239 return ShowWindow(hwnd,cmd);
1243 /***********************************************************************
1244 * ShowWindow (USER32.534)
1246 BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
1248 WND* wndPtr = WIN_FindWndPtr( hwnd );
1249 BOOL wasVisible, showFlag;
1250 RECT16 newPos = {0, 0, 0, 0};
1251 int swp = 0;
1253 if (!wndPtr) return FALSE;
1255 TRACE(win,"hwnd=%04x, cmd=%d\n", hwnd, cmd);
1257 wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
1259 switch(cmd)
1261 case SW_HIDE:
1262 if (!wasVisible) goto END;;
1263 swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
1264 SWP_NOACTIVATE | SWP_NOZORDER;
1265 if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus()))
1267 /* Revert focus to parent */
1268 SetFocus( GetParent(hwnd) );
1270 break;
1272 case SW_SHOWMINNOACTIVE:
1273 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1274 /* fall through */
1275 case SW_SHOWMINIMIZED:
1276 swp |= SWP_SHOWWINDOW;
1277 /* fall through */
1278 case SW_MINIMIZE:
1279 swp |= SWP_FRAMECHANGED;
1280 if( !(wndPtr->dwStyle & WS_MINIMIZE) )
1281 swp |= WINPOS_MinMaximize( wndPtr, SW_MINIMIZE, &newPos );
1282 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1283 break;
1285 case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
1286 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1287 if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
1288 swp |= WINPOS_MinMaximize( wndPtr, SW_MAXIMIZE, &newPos );
1289 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1290 break;
1292 case SW_SHOWNA:
1293 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1294 /* fall through */
1295 case SW_SHOW:
1296 swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
1297 break;
1299 case SW_SHOWNOACTIVATE:
1300 swp |= SWP_NOZORDER;
1301 if (GetActiveWindow()) swp |= SWP_NOACTIVATE;
1302 /* fall through */
1303 case SW_SHOWNORMAL: /* same as SW_NORMAL: */
1304 case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
1305 case SW_RESTORE:
1306 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1308 if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) )
1309 swp |= WINPOS_MinMaximize( wndPtr, SW_RESTORE, &newPos );
1310 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1311 break;
1314 showFlag = (cmd != SW_HIDE);
1315 if (showFlag != wasVisible)
1317 SendMessageA( hwnd, WM_SHOWWINDOW, showFlag, 0 );
1318 if (!IsWindow( hwnd )) goto END;
1321 if ((wndPtr->dwStyle & WS_CHILD) &&
1322 !IsWindowVisible( wndPtr->parent->hwndSelf ) &&
1323 (swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE) )
1325 /* Don't call SetWindowPos() on invisible child windows */
1326 if (cmd == SW_HIDE) wndPtr->dwStyle &= ~WS_VISIBLE;
1327 else wndPtr->dwStyle |= WS_VISIBLE;
1329 else
1331 /* We can't activate a child window */
1332 if (wndPtr->dwStyle & WS_CHILD) swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1333 SetWindowPos( hwnd, HWND_TOP,
1334 newPos.left, newPos.top, newPos.right, newPos.bottom, swp );
1335 if (!IsWindow( hwnd )) goto END;
1336 else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( wndPtr, TRUE );
1339 if (wndPtr->flags & WIN_NEED_SIZE)
1341 /* should happen only in CreateWindowEx() */
1342 int wParam = SIZE_RESTORED;
1344 wndPtr->flags &= ~WIN_NEED_SIZE;
1345 if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
1346 else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
1347 SendMessageA( hwnd, WM_SIZE, wParam,
1348 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
1349 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
1350 SendMessageA( hwnd, WM_MOVE, 0,
1351 MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
1354 END:
1355 WIN_ReleaseWndPtr(wndPtr);
1356 return wasVisible;
1360 /***********************************************************************
1361 * GetInternalWindowPos16 (USER.460)
1363 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
1364 LPPOINT16 ptIcon )
1366 WINDOWPLACEMENT16 wndpl;
1367 if (GetWindowPlacement16( hwnd, &wndpl ))
1369 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1370 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1371 return wndpl.showCmd;
1373 return 0;
1377 /***********************************************************************
1378 * GetInternalWindowPos (USER32.245)
1380 UINT WINAPI GetInternalWindowPos( HWND hwnd, LPRECT rectWnd,
1381 LPPOINT ptIcon )
1383 WINDOWPLACEMENT wndpl;
1384 if (GetWindowPlacement( hwnd, &wndpl ))
1386 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1387 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1388 return wndpl.showCmd;
1390 return 0;
1393 /***********************************************************************
1394 * GetWindowPlacement16 (USER.370)
1396 BOOL16 WINAPI GetWindowPlacement16( HWND16 hwnd, WINDOWPLACEMENT16 *wndpl )
1398 WND *pWnd = WIN_FindWndPtr( hwnd );
1399 LPINTERNALPOS lpPos;
1401 if(!pWnd ) return FALSE;
1403 lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1404 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1405 wndpl->length = sizeof(*wndpl);
1406 if( pWnd->dwStyle & WS_MINIMIZE )
1407 wndpl->showCmd = SW_SHOWMINIMIZED;
1408 else
1409 wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE )
1410 ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
1411 if( pWnd->flags & WIN_RESTORE_MAX )
1412 wndpl->flags = WPF_RESTORETOMAXIMIZED;
1413 else
1414 wndpl->flags = 0;
1415 wndpl->ptMinPosition = lpPos->ptIconPos;
1416 wndpl->ptMaxPosition = lpPos->ptMaxPos;
1417 wndpl->rcNormalPosition = lpPos->rectNormal;
1419 WIN_ReleaseWndPtr(pWnd);
1420 return TRUE;
1424 /***********************************************************************
1425 * GetWindowPlacement (USER32.307)
1427 * Win95:
1428 * Fails if wndpl->length of Win95 (!) apps is invalid.
1430 BOOL WINAPI GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *pwpl32 )
1432 if( pwpl32 )
1434 WINDOWPLACEMENT16 wpl;
1435 wpl.length = sizeof(wpl);
1436 if( GetWindowPlacement16( hwnd, &wpl ) )
1438 pwpl32->length = sizeof(*pwpl32);
1439 pwpl32->flags = wpl.flags;
1440 pwpl32->showCmd = wpl.showCmd;
1441 CONV_POINT16TO32( &wpl.ptMinPosition, &pwpl32->ptMinPosition );
1442 CONV_POINT16TO32( &wpl.ptMaxPosition, &pwpl32->ptMaxPosition );
1443 CONV_RECT16TO32( &wpl.rcNormalPosition, &pwpl32->rcNormalPosition );
1444 return TRUE;
1447 return FALSE;
1451 /***********************************************************************
1452 * WINPOS_SetPlacement
1454 static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT16 *wndpl,
1455 UINT flags )
1457 WND *pWnd = WIN_FindWndPtr( hwnd );
1458 if( pWnd )
1460 LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1461 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1463 if( flags & PLACE_MIN ) lpPos->ptIconPos = wndpl->ptMinPosition;
1464 if( flags & PLACE_MAX ) lpPos->ptMaxPos = wndpl->ptMaxPosition;
1465 if( flags & PLACE_RECT) lpPos->rectNormal = wndpl->rcNormalPosition;
1467 if( pWnd->dwStyle & WS_MINIMIZE )
1469 WINPOS_ShowIconTitle( pWnd, FALSE );
1470 if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1471 SetWindowPos( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1472 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1474 else if( pWnd->dwStyle & WS_MAXIMIZE )
1476 if( !EMPTYPOINT(lpPos->ptMaxPos) )
1477 SetWindowPos( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1478 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1480 else if( flags & PLACE_RECT )
1481 SetWindowPos( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1482 lpPos->rectNormal.right - lpPos->rectNormal.left,
1483 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1484 SWP_NOZORDER | SWP_NOACTIVATE );
1486 ShowWindow( hwnd, wndpl->showCmd );
1487 if( IsWindow(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1489 if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd, TRUE );
1491 /* SDK: ...valid only the next time... */
1492 if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1494 WIN_ReleaseWndPtr(pWnd);
1495 return TRUE;
1497 return FALSE;
1501 /***********************************************************************
1502 * SetWindowPlacement16 (USER.371)
1504 BOOL16 WINAPI SetWindowPlacement16(HWND16 hwnd, const WINDOWPLACEMENT16 *wndpl)
1506 return WINPOS_SetPlacement( hwnd, wndpl,
1507 PLACE_MIN | PLACE_MAX | PLACE_RECT );
1510 /***********************************************************************
1511 * SetWindowPlacement (USER32.519)
1513 * Win95:
1514 * Fails if wndpl->length of Win95 (!) apps is invalid.
1516 BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *pwpl32 )
1518 if( pwpl32 )
1520 WINDOWPLACEMENT16 wpl = { sizeof(WINDOWPLACEMENT16),
1521 pwpl32->flags, pwpl32->showCmd, { pwpl32->ptMinPosition.x,
1522 pwpl32->ptMinPosition.y }, { pwpl32->ptMaxPosition.x,
1523 pwpl32->ptMaxPosition.y }, { pwpl32->rcNormalPosition.left,
1524 pwpl32->rcNormalPosition.top, pwpl32->rcNormalPosition.right,
1525 pwpl32->rcNormalPosition.bottom } };
1527 return WINPOS_SetPlacement( hwnd, &wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1529 return FALSE;
1533 /***********************************************************************
1534 * SetInternalWindowPos16 (USER.461)
1536 void WINAPI SetInternalWindowPos16( HWND16 hwnd, UINT16 showCmd,
1537 LPRECT16 rect, LPPOINT16 pt )
1539 if( IsWindow16(hwnd) )
1541 WINDOWPLACEMENT16 wndpl;
1542 UINT flags;
1544 wndpl.length = sizeof(wndpl);
1545 wndpl.showCmd = showCmd;
1546 wndpl.flags = flags = 0;
1548 if( pt )
1550 flags |= PLACE_MIN;
1551 wndpl.flags |= WPF_SETMINPOSITION;
1552 wndpl.ptMinPosition = *pt;
1554 if( rect )
1556 flags |= PLACE_RECT;
1557 wndpl.rcNormalPosition = *rect;
1559 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1564 /***********************************************************************
1565 * SetInternalWindowPos (USER32.483)
1567 void WINAPI SetInternalWindowPos( HWND hwnd, UINT showCmd,
1568 LPRECT rect, LPPOINT pt )
1570 if( IsWindow(hwnd) )
1572 WINDOWPLACEMENT16 wndpl;
1573 UINT flags;
1575 wndpl.length = sizeof(wndpl);
1576 wndpl.showCmd = showCmd;
1577 wndpl.flags = flags = 0;
1579 if( pt )
1581 flags |= PLACE_MIN;
1582 wndpl.flags |= WPF_SETMINPOSITION;
1583 CONV_POINT32TO16( pt, &wndpl.ptMinPosition );
1585 if( rect )
1587 flags |= PLACE_RECT;
1588 CONV_RECT32TO16( rect, &wndpl.rcNormalPosition );
1590 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1594 /*******************************************************************
1595 * WINPOS_SetActiveWindow
1597 * SetActiveWindow() back-end. This is the only function that
1598 * can assign active status to a window. It must be called only
1599 * for the top level windows.
1601 BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
1603 CBTACTIVATESTRUCT16* cbtStruct;
1604 WND* wndPtr=0, *wndTemp;
1605 HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1606 MESSAGEQUEUE *pOldActiveQueue = 0, *pNewActiveQueue = 0;
1607 WORD wIconized = 0;
1608 HWND hwndActive = 0;
1609 BOOL bRet = 0;
1611 /* Get current active window from the active queue */
1612 if ( hActiveQueue )
1614 pOldActiveQueue = QUEUE_Lock( hActiveQueue );
1615 if ( pOldActiveQueue )
1616 hwndActive = PERQDATA_GetActiveWnd( pOldActiveQueue->pQData );
1619 /* paranoid checks */
1620 if( hWnd == GetDesktopWindow() || hWnd == hwndActive ) goto CLEANUP;
1622 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1623 * return 0;
1625 wndPtr = WIN_FindWndPtr(hWnd);
1626 hOldActiveQueue = hActiveQueue;
1628 if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1629 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1630 else
1631 TRACE(win,"no current active window.\n");
1632 WIN_ReleaseWndPtr(wndTemp);
1633 /* call CBT hook chain */
1634 if ((cbtStruct = SEGPTR_NEW(CBTACTIVATESTRUCT16)))
1636 LRESULT wRet;
1637 cbtStruct->fMouse = fMouse;
1638 cbtStruct->hWndActive = hwndActive;
1639 wRet = HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
1640 (LPARAM)SEGPTR_GET(cbtStruct) );
1641 SEGPTR_FREE(cbtStruct);
1642 if (wRet)
1644 /* Unlock the active queue before returning */
1645 if ( pOldActiveQueue )
1646 QUEUE_Unlock( pOldActiveQueue );
1647 return wRet;
1651 /* set prev active wnd to current active wnd and send notification */
1652 if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
1654 MESSAGEQUEUE *pTempActiveQueue = 0;
1656 if (!SendMessageA( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1658 if (GetSysModalWindow16() != hWnd) goto CLEANUP;
1659 /* disregard refusal if hWnd is sysmodal */
1662 #if 1
1663 SendMessageA( hwndPrevActive, WM_ACTIVATE,
1664 MAKEWPARAM( WA_INACTIVE, wIconized ),
1665 (LPARAM)hWnd );
1666 #else
1667 /* FIXME: must be SendMessage16() because A doesn't do
1668 * intertask at this time */
1669 SendMessage16( hwndPrevActive, WM_ACTIVATE, WA_INACTIVE,
1670 MAKELPARAM( (HWND16)hWnd, wIconized ) );
1671 #endif
1673 /* check if something happened during message processing
1674 * (global active queue may have changed)
1676 pTempActiveQueue = QUEUE_Lock( hActiveQueue );
1677 hwndActive = PERQDATA_GetActiveWnd( pTempActiveQueue->pQData );
1678 QUEUE_Unlock( pTempActiveQueue );
1679 if( hwndPrevActive != hwndActive )
1680 goto CLEANUP;
1683 /* Set new active window in the message queue */
1684 hwndActive = hWnd;
1685 if ( wndPtr )
1687 pNewActiveQueue = QUEUE_Lock( wndPtr->hmemTaskQ );
1688 if ( pNewActiveQueue )
1689 PERQDATA_SetActiveWnd( pNewActiveQueue->pQData, hwndActive );
1692 /* send palette messages */
1693 if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1694 SendMessage16((HWND16)-1, WM_PALETTEISCHANGING, (WPARAM16)hWnd, 0L );
1696 /* if prev wnd is minimized redraw icon title */
1697 if( IsIconic( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1699 /* managed windows will get ConfigureNotify event */
1700 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->flags & WIN_MANAGED))
1702 /* check Z-order and bring hWnd to the top */
1703 for (wndTemp = WIN_LockWndPtr(WIN_GetDesktop()->child); wndTemp; WIN_UpdateWndPtr(&wndTemp,wndTemp->next))
1705 if (wndTemp->dwStyle & WS_VISIBLE) break;
1707 WIN_ReleaseDesktop();
1708 WIN_ReleaseWndPtr(wndTemp);
1710 if( wndTemp != wndPtr )
1711 SetWindowPos(hWnd, HWND_TOP, 0,0,0,0,
1712 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1713 if (!IsWindow(hWnd)) goto CLEANUP;
1716 /* Get a handle to the new active queue */
1717 hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1719 /* send WM_ACTIVATEAPP if necessary */
1720 if (hOldActiveQueue != hNewActiveQueue)
1722 WND **list, **ppWnd;
1723 WND *pDesktop = WIN_GetDesktop();
1725 if ((list = WIN_BuildWinArray( pDesktop, 0, NULL )))
1727 for (ppWnd = list; *ppWnd; ppWnd++)
1729 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1731 if ((*ppWnd)->hmemTaskQ == hOldActiveQueue)
1732 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1733 0, QUEUE_GetQueueTask(hNewActiveQueue) );
1735 WIN_ReleaseWinArray(list);
1738 hActiveQueue = hNewActiveQueue;
1740 if ((list = WIN_BuildWinArray(pDesktop, 0, NULL )))
1742 for (ppWnd = list; *ppWnd; ppWnd++)
1744 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1746 if ((*ppWnd)->hmemTaskQ == hNewActiveQueue)
1747 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1748 1, QUEUE_GetQueueTask( hOldActiveQueue ) );
1750 WIN_ReleaseWinArray(list);
1752 WIN_ReleaseDesktop();
1754 if (!IsWindow(hWnd)) goto CLEANUP;
1757 if (hWnd)
1759 /* walk up to the first unowned window */
1760 wndTemp = WIN_LockWndPtr(wndPtr);
1761 while (wndTemp->owner)
1763 WIN_UpdateWndPtr(&wndTemp,wndTemp->owner);
1765 /* and set last active owned popup */
1766 wndTemp->hwndLastActive = hWnd;
1768 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1769 SendMessageA( hWnd, WM_NCACTIVATE, TRUE, 0 );
1770 #if 1
1771 SendMessageA( hWnd, WM_ACTIVATE,
1772 MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1773 (LPARAM)hwndPrevActive );
1774 #else
1775 SendMessage16(hWnd, WM_ACTIVATE, (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE,
1776 MAKELPARAM( (HWND16)hwndPrevActive, wIconized) );
1777 #endif
1779 if( !IsWindow(hWnd) ) goto CLEANUP;
1782 /* change focus if possible */
1783 if( fChangeFocus && GetFocus() )
1784 if( WIN_GetTopParent(GetFocus()) != hwndActive )
1785 FOCUS_SwitchFocus( pNewActiveQueue, GetFocus(),
1786 (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
1788 hwndActive
1791 if( !hwndPrevActive && wndPtr )
1792 (*wndPtr->pDriver->pForceWindowRaise)(wndPtr);
1794 /* if active wnd is minimized redraw icon title */
1795 if( IsIconic(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1797 bRet = 1; // Success
1799 CLEANUP:
1801 /* Unlock the message queues before returning */
1802 if ( pOldActiveQueue )
1803 QUEUE_Unlock( pOldActiveQueue );
1804 if ( pNewActiveQueue )
1805 QUEUE_Unlock( pNewActiveQueue );
1806 WIN_ReleaseWndPtr(wndPtr);
1807 return bRet ? (hWnd == hwndActive) : 0;
1810 /*******************************************************************
1811 * WINPOS_ActivateOtherWindow
1813 * Activates window other than pWnd.
1815 BOOL WINPOS_ActivateOtherWindow(WND* pWnd)
1817 BOOL bRet = 0;
1818 WND* pWndTo = NULL;
1819 HWND hwndActive = 0;
1821 /* Get current active window from the active queue */
1822 if ( hActiveQueue )
1824 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1825 if ( pActiveQueue )
1827 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1828 QUEUE_Unlock( pActiveQueue );
1832 if( pWnd->hwndSelf == hwndPrevActive )
1833 hwndPrevActive = 0;
1835 if( hwndActive != pWnd->hwndSelf &&
1836 ( hwndActive || QUEUE_IsExitingQueue(pWnd->hmemTaskQ)) )
1837 return 0;
1839 if( !(pWnd->dwStyle & WS_POPUP) || !(pWnd->owner) ||
1840 !WINPOS_CanActivate((pWndTo = WIN_GetTopParentPtr(pWnd->owner))) )
1842 WND* pWndPtr = WIN_GetTopParentPtr(pWnd);
1844 pWndTo = WIN_FindWndPtr(hwndPrevActive);
1846 while( !WINPOS_CanActivate(pWndTo) )
1848 /* by now owned windows should've been taken care of */
1849 WIN_ReleaseWndPtr(pWndTo);
1850 pWndTo = WIN_LockWndPtr(pWndPtr->next);
1851 WIN_ReleaseWndPtr(pWndPtr);
1852 pWndPtr = WIN_LockWndPtr(pWndTo);
1853 if( !pWndTo ) break;
1855 WIN_ReleaseWndPtr(pWndPtr);
1858 bRet = WINPOS_SetActiveWindow( pWndTo ? pWndTo->hwndSelf : 0, FALSE, TRUE );
1860 /* switch desktop queue to current active */
1861 if( pWndTo )
1863 WIN_GetDesktop()->hmemTaskQ = pWndTo->hmemTaskQ;
1864 WIN_ReleaseWndPtr(pWndTo);
1865 WIN_ReleaseDesktop();
1868 hwndPrevActive = 0;
1869 return bRet;
1872 /*******************************************************************
1873 * WINPOS_ChangeActiveWindow
1876 BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
1878 WND *wndPtr = WIN_FindWndPtr(hWnd);
1879 WND *wndTemp;
1880 BOOL retvalue;
1881 HWND hwndActive = 0;
1883 if( !wndPtr ) return FALSE;
1885 /* Get current active window from the active queue */
1886 if ( hActiveQueue )
1888 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1889 if ( pActiveQueue )
1891 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1892 QUEUE_Unlock( pActiveQueue );
1896 if (!hWnd)
1898 retvalue = WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
1899 goto end;
1903 /* child windows get WM_CHILDACTIVATE message */
1904 if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
1906 retvalue = SendMessageA(hWnd, WM_CHILDACTIVATE, 0, 0L);
1907 goto end;
1910 /* owned popups imply owner activation - not sure */
1911 if ((wndPtr->dwStyle & WS_POPUP) && wndPtr->owner &&
1912 (wndPtr->owner->dwStyle & WS_VISIBLE ) &&
1913 !(wndPtr->owner->dwStyle & WS_DISABLED ))
1915 WIN_UpdateWndPtr(&wndPtr,wndPtr->owner);
1916 if (!wndPtr)
1918 retvalue = FALSE;
1919 goto end;
1921 hWnd = wndPtr->hwndSelf;
1924 if( hWnd == hwndActive )
1926 retvalue = FALSE;
1927 goto end;
1930 if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
1932 retvalue = FALSE;
1933 goto end;
1936 /* switch desktop queue to current active */
1937 wndTemp = WIN_GetDesktop();
1938 if( wndPtr->parent == wndTemp)
1939 wndTemp->hmemTaskQ = wndPtr->hmemTaskQ;
1940 WIN_ReleaseDesktop();
1942 retvalue = TRUE;
1943 end:
1944 WIN_ReleaseWndPtr(wndPtr);
1945 return retvalue;
1949 /***********************************************************************
1950 * WINPOS_SendNCCalcSize
1952 * Send a WM_NCCALCSIZE message to a window.
1953 * All parameters are read-only except newClientRect.
1954 * oldWindowRect, oldClientRect and winpos must be non-NULL only
1955 * when calcValidRect is TRUE.
1957 LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect,
1958 RECT *newWindowRect, RECT *oldWindowRect,
1959 RECT *oldClientRect, WINDOWPOS *winpos,
1960 RECT *newClientRect )
1962 NCCALCSIZE_PARAMS params;
1963 WINDOWPOS winposCopy;
1964 LONG result;
1966 params.rgrc[0] = *newWindowRect;
1967 if (calcValidRect)
1969 winposCopy = *winpos;
1970 params.rgrc[1] = *oldWindowRect;
1971 params.rgrc[2] = *oldClientRect;
1972 params.lppos = &winposCopy;
1974 result = SendMessageA( hwnd, WM_NCCALCSIZE, calcValidRect,
1975 (LPARAM)&params );
1976 TRACE(win, "%d,%d-%d,%d\n",
1977 params.rgrc[0].left, params.rgrc[0].top,
1978 params.rgrc[0].right, params.rgrc[0].bottom );
1979 *newClientRect = params.rgrc[0];
1980 return result;
1984 /***********************************************************************
1985 * WINPOS_HandleWindowPosChanging16
1987 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
1989 LONG WINPOS_HandleWindowPosChanging16( WND *wndPtr, WINDOWPOS16 *winpos )
1991 POINT maxSize, minTrack;
1992 if (winpos->flags & SWP_NOSIZE) return 0;
1993 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
1994 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
1996 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
1997 if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
1998 if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
1999 if (!(wndPtr->dwStyle & WS_MINIMIZE))
2001 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
2002 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
2005 return 0;
2009 /***********************************************************************
2010 * WINPOS_HandleWindowPosChanging
2012 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2014 LONG WINPOS_HandleWindowPosChanging( WND *wndPtr, WINDOWPOS *winpos )
2016 POINT maxSize;
2017 if (winpos->flags & SWP_NOSIZE) return 0;
2018 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2019 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2021 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, NULL, NULL );
2022 winpos->cx = MIN( winpos->cx, maxSize.x );
2023 winpos->cy = MIN( winpos->cy, maxSize.y );
2025 return 0;
2029 /***********************************************************************
2030 * WINPOS_MoveWindowZOrder
2032 * Move a window in Z order, invalidating everything that needs it.
2033 * Only necessary for windows without associated X window.
2035 static void WINPOS_MoveWindowZOrder( HWND hwnd, HWND hwndAfter )
2037 BOOL movingUp;
2038 WND *pWndAfter, *pWndCur, *wndPtr = WIN_FindWndPtr( hwnd );
2040 /* We have two possible cases:
2041 * - The window is moving up: we have to invalidate all areas
2042 * of the window that were covered by other windows
2043 * - The window is moving down: we have to invalidate areas
2044 * of other windows covered by this one.
2047 if (hwndAfter == HWND_TOP)
2049 movingUp = TRUE;
2051 else if (hwndAfter == HWND_BOTTOM)
2053 if (!wndPtr->next) goto END; /* Already at the bottom */
2054 movingUp = FALSE;
2056 else
2058 if (!(pWndAfter = WIN_FindWndPtr( hwndAfter ))) goto END;
2059 if (wndPtr->next == pWndAfter)
2061 WIN_ReleaseWndPtr(pWndAfter);
2062 goto END; /* Already placed right */
2065 /* Determine which window we encounter first in Z-order */
2066 pWndCur = WIN_LockWndPtr(wndPtr->parent->child);
2067 while ((pWndCur != wndPtr) && (pWndCur != pWndAfter))
2069 WIN_UpdateWndPtr(&pWndCur,pWndCur->next);
2071 movingUp = (pWndCur == pWndAfter);
2072 WIN_ReleaseWndPtr(pWndCur);
2073 WIN_ReleaseWndPtr(pWndAfter);
2076 if (movingUp)
2078 WND *pWndPrevAfter = WIN_LockWndPtr(wndPtr->next);
2079 WIN_UnlinkWindow( hwnd );
2080 WIN_LinkWindow( hwnd, hwndAfter );
2081 pWndCur = WIN_LockWndPtr(wndPtr->next);
2082 while (pWndCur != pWndPrevAfter)
2084 RECT rect = { pWndCur->rectWindow.left,
2085 pWndCur->rectWindow.top,
2086 pWndCur->rectWindow.right,
2087 pWndCur->rectWindow.bottom };
2088 OffsetRect( &rect, -wndPtr->rectClient.left,
2089 -wndPtr->rectClient.top );
2090 PAINT_RedrawWindow( hwnd, &rect, 0, RDW_INVALIDATE | RDW_ALLCHILDREN |
2091 RDW_FRAME | RDW_ERASE, 0 );
2092 WIN_UpdateWndPtr(&pWndCur,pWndCur->next);
2094 WIN_ReleaseWndPtr(pWndPrevAfter);
2096 else /* Moving down */
2098 pWndCur = WIN_LockWndPtr(wndPtr->next);
2099 WIN_UnlinkWindow( hwnd );
2100 WIN_LinkWindow( hwnd, hwndAfter );
2101 while (pWndCur != wndPtr)
2103 RECT rect = { pWndCur->rectWindow.left,
2104 pWndCur->rectWindow.top,
2105 pWndCur->rectWindow.right,
2106 pWndCur->rectWindow.bottom };
2107 OffsetRect( &rect, -pWndCur->rectClient.left,
2108 -pWndCur->rectClient.top );
2109 PAINT_RedrawWindow( pWndCur->hwndSelf, &rect, 0, RDW_INVALIDATE |
2110 RDW_ALLCHILDREN | RDW_FRAME | RDW_ERASE, 0 );
2111 WIN_UpdateWndPtr(&pWndCur,pWndCur->next);
2114 END:
2115 WIN_ReleaseWndPtr(wndPtr);
2118 /***********************************************************************
2119 * WINPOS_ReorderOwnedPopups
2121 * fix Z order taking into account owned popups -
2122 * basically we need to maintain them above the window that owns them
2124 HWND WINPOS_ReorderOwnedPopups(HWND hwndInsertAfter,WND* wndPtr,WORD flags)
2126 WND* pDesktop = WIN_GetDesktop();
2127 WND* w = WIN_LockWndPtr(pDesktop->child);
2129 if( wndPtr->dwStyle & WS_POPUP && wndPtr->owner )
2131 /* implement "local z-order" between the top and owner window */
2133 HWND hwndLocalPrev = HWND_TOP;
2135 if( hwndInsertAfter != HWND_TOP )
2137 while( w != wndPtr->owner )
2139 if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
2140 if( hwndLocalPrev == hwndInsertAfter ) break;
2141 WIN_UpdateWndPtr(&w,w->next);
2143 hwndInsertAfter = hwndLocalPrev;
2147 else if( wndPtr->dwStyle & WS_CHILD )
2148 goto END;
2150 WIN_UpdateWndPtr(&w,pDesktop->child);
2152 while( w )
2154 if( w == wndPtr ) break;
2156 if( w->dwStyle & WS_POPUP && w->owner == wndPtr )
2158 SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
2159 SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
2160 hwndInsertAfter = w->hwndSelf;
2162 WIN_UpdateWndPtr(&w,w->next);
2165 END:
2166 WIN_ReleaseWndPtr(w);
2167 WIN_ReleaseDesktop();
2168 return hwndInsertAfter;
2171 /***********************************************************************
2172 * WINPOS_SizeMoveClean
2174 * Make window look nice without excessive repainting
2176 * the pain:
2178 * visible regions are in window coordinates
2179 * update regions are in window client coordinates
2180 * client and window rectangles are in parent client coordinates
2182 * FIXME: Move visible and update regions to the same coordinate system
2183 * (either parent client or window). This is a lot of work though.
2185 static UINT WINPOS_SizeMoveClean( WND* Wnd, HRGN oldVisRgn,
2186 LPRECT lpOldWndRect,
2187 LPRECT lpOldClientRect, UINT uFlags )
2189 HRGN newVisRgn = DCE_GetVisRgn(Wnd->hwndSelf,DCX_WINDOW | DCX_CLIPSIBLINGS,0,0);
2190 HRGN dirtyRgn = CreateRectRgn(0,0,0,0);
2191 int other, my;
2193 TRACE(win,"cleaning up...new wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i)\n",
2194 Wnd->rectWindow.left, Wnd->rectWindow.top,
2195 Wnd->rectWindow.right, Wnd->rectWindow.bottom,
2196 lpOldWndRect->left, lpOldWndRect->top,
2197 lpOldWndRect->right, lpOldWndRect->bottom);
2198 TRACE(win,"\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2199 Wnd->rectClient.left, Wnd->rectClient.top,
2200 Wnd->rectClient.right, Wnd->rectClient.bottom,
2201 lpOldClientRect->left, lpOldClientRect->top,
2202 lpOldClientRect->right,lpOldClientRect->bottom );
2204 if( (lpOldWndRect->right - lpOldWndRect->left) != (Wnd->rectWindow.right - Wnd->rectWindow.left) ||
2205 (lpOldWndRect->bottom - lpOldWndRect->top) != (Wnd->rectWindow.bottom - Wnd->rectWindow.top) )
2206 uFlags |= SMC_DRAWFRAME;
2208 CombineRgn( dirtyRgn, newVisRgn, 0, RGN_COPY);
2210 if( !(uFlags & SMC_NOCOPY) )
2211 CombineRgn( newVisRgn, newVisRgn, oldVisRgn, RGN_AND );
2213 /* map regions to the parent client area */
2215 OffsetRgn( dirtyRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2216 OffsetRgn( oldVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2218 /* compute invalidated region outside Wnd - (in client coordinates of the parent window) */
2220 other = CombineRgn(dirtyRgn, oldVisRgn, dirtyRgn, RGN_DIFF);
2222 /* map visible region to the Wnd client area */
2224 OffsetRgn( newVisRgn, Wnd->rectWindow.left - Wnd->rectClient.left,
2225 Wnd->rectWindow.top - Wnd->rectClient.top );
2227 /* substract previously invalidated region from the Wnd visible region */
2229 my = (Wnd->hrgnUpdate > 1) ? CombineRgn( newVisRgn, newVisRgn,
2230 Wnd->hrgnUpdate, RGN_DIFF)
2231 : COMPLEXREGION;
2233 if( uFlags & SMC_NOCOPY ) /* invalidate Wnd visible region */
2235 if (my != NULLREGION)
2236 PAINT_RedrawWindow( Wnd->hwndSelf, NULL, newVisRgn, RDW_INVALIDATE |
2237 RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE, RDW_C_USEHRGN );
2238 else if(uFlags & SMC_DRAWFRAME)
2239 Wnd->flags |= WIN_NEEDS_NCPAINT;
2241 else /* bitblt old client area */
2243 HDC hDC;
2244 int update;
2245 HRGN updateRgn;
2246 int xfrom,yfrom,xto,yto,width,height;
2248 if( uFlags & SMC_DRAWFRAME )
2250 /* copy only client area, frame will be redrawn anyway */
2252 xfrom = lpOldClientRect->left; yfrom = lpOldClientRect->top;
2253 xto = Wnd->rectClient.left; yto = Wnd->rectClient.top;
2254 width = lpOldClientRect->right - xfrom; height = lpOldClientRect->bottom - yfrom;
2255 updateRgn = CreateRectRgn( 0, 0, width, height );
2256 CombineRgn( newVisRgn, newVisRgn, updateRgn, RGN_AND );
2257 SetRectRgn( updateRgn, 0, 0, Wnd->rectClient.right - xto,
2258 Wnd->rectClient.bottom - yto );
2260 else
2262 xfrom = lpOldWndRect->left; yfrom = lpOldWndRect->top;
2263 xto = Wnd->rectWindow.left; yto = Wnd->rectWindow.top;
2264 width = lpOldWndRect->right - xfrom; height = lpOldWndRect->bottom - yfrom;
2265 updateRgn = CreateRectRgn( xto - Wnd->rectClient.left,
2266 yto - Wnd->rectClient.top,
2267 Wnd->rectWindow.right - Wnd->rectClient.left,
2268 Wnd->rectWindow.bottom - Wnd->rectClient.top );
2271 CombineRgn( newVisRgn, newVisRgn, updateRgn, RGN_AND );
2273 /* substract new visRgn from target rect to get a region that won't be copied */
2275 update = CombineRgn( updateRgn, updateRgn, newVisRgn, RGN_DIFF );
2277 /* Blt valid bits using parent window DC */
2279 if( my != NULLREGION && (xfrom != xto || yfrom != yto) )
2282 /* compute clipping region in parent client coordinates */
2284 OffsetRgn( newVisRgn, Wnd->rectClient.left, Wnd->rectClient.top );
2285 CombineRgn( oldVisRgn, oldVisRgn, newVisRgn, RGN_OR );
2287 hDC = GetDCEx( Wnd->parent->hwndSelf, oldVisRgn,
2288 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN |
2289 DCX_CACHE | DCX_CLIPSIBLINGS);
2291 BitBlt( hDC, xto, yto, width, height, hDC, xfrom, yfrom, SRCCOPY );
2292 ReleaseDC( Wnd->parent->hwndSelf, hDC);
2295 if( update != NULLREGION )
2296 PAINT_RedrawWindow( Wnd->hwndSelf, NULL, updateRgn, RDW_INVALIDATE |
2297 RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE, RDW_C_USEHRGN );
2298 else if( uFlags & SMC_DRAWFRAME ) Wnd->flags |= WIN_NEEDS_NCPAINT;
2299 DeleteObject( updateRgn );
2302 /* erase uncovered areas */
2304 if( !(uFlags & SMC_NOPARENTERASE) && (other != NULLREGION ) )
2305 PAINT_RedrawWindow( Wnd->parent->hwndSelf, NULL, dirtyRgn,
2306 RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE, RDW_C_USEHRGN );
2307 DeleteObject(dirtyRgn);
2308 DeleteObject(newVisRgn);
2309 return uFlags;
2312 /***********************************************************************
2313 * SetWindowPos (USER.2)
2315 BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
2316 INT16 x, INT16 y, INT16 cx, INT16 cy, WORD flags)
2318 return SetWindowPos(hwnd,(INT)(INT16)hwndInsertAfter,x,y,cx,cy,flags);
2321 /***********************************************************************
2322 * SetWindowPos (USER32.520)
2324 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
2325 INT x, INT y, INT cx, INT cy, WORD flags)
2327 WINDOWPOS winpos;
2328 WND * wndPtr,*wndTemp;
2329 RECT newWindowRect, newClientRect, oldWindowRect;
2330 HRGN visRgn = 0;
2331 HWND tempInsertAfter= 0;
2332 int result = 0;
2333 UINT uFlags = 0;
2334 BOOL resync = FALSE,retvalue;
2335 HWND hwndActive = 0;
2337 /* Get current active window from the active queue */
2338 if ( hActiveQueue )
2340 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2341 if ( pActiveQueue )
2343 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2344 QUEUE_Unlock( pActiveQueue );
2348 TRACE(win,"hwnd %04x, (%i,%i)-(%i,%i) flags %08x\n",
2349 hwnd, x, y, x+cx, y+cy, flags);
2350 /* Check window handle */
2352 if (hwnd == GetDesktopWindow()) return FALSE;
2353 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2355 if(wndPtr->dwStyle & WS_VISIBLE)
2356 flags &= ~SWP_SHOWWINDOW;
2357 else
2359 uFlags |= SMC_NOPARENTERASE;
2360 flags &= ~SWP_HIDEWINDOW;
2361 if (!(flags & SWP_SHOWWINDOW)) flags |= SWP_NOREDRAW;
2364 /* Check for windows that may not be resized
2365 FIXME: this should be done only for Windows 3.0 programs
2366 if (flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW ) )
2367 flags |= SWP_NOSIZE | SWP_NOMOVE;
2369 /* Check dimensions */
2371 if (cx <= 0) cx = 1;
2372 if (cy <= 0) cy = 1;
2374 /* Check flags */
2376 if (hwnd == hwndActive) flags |= SWP_NOACTIVATE; /* Already active */
2377 if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
2378 (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
2379 flags |= SWP_NOSIZE; /* Already the right size */
2380 if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
2381 flags |= SWP_NOMOVE; /* Already the right position */
2383 /* Check hwndInsertAfter */
2385 if (!(flags & (SWP_NOZORDER | SWP_NOACTIVATE)))
2387 /* Ignore TOPMOST flags when activating a window */
2388 /* _and_ moving it in Z order. */
2389 if ((hwndInsertAfter == HWND_TOPMOST) ||
2390 (hwndInsertAfter == HWND_NOTOPMOST))
2391 hwndInsertAfter = HWND_TOP;
2393 /* TOPMOST not supported yet */
2394 if ((hwndInsertAfter == HWND_TOPMOST) ||
2395 (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
2397 /* hwndInsertAfter must be a sibling of the window */
2398 if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
2400 WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
2402 if( wnd ) {
2403 if( wnd->parent != wndPtr->parent )
2405 retvalue = FALSE;
2406 WIN_ReleaseWndPtr(wnd);
2407 goto END;
2409 if( wnd->next == wndPtr ) flags |= SWP_NOZORDER;
2411 WIN_ReleaseWndPtr(wnd);
2413 else if (!X11DRV_WND_GetXWindow(wndPtr))
2415 /* FIXME: the following optimization is no good for "X-ed" windows */
2416 if (hwndInsertAfter == HWND_TOP)
2417 flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
2418 else /* HWND_BOTTOM */
2419 flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
2422 /* Fill the WINDOWPOS structure */
2424 winpos.hwnd = hwnd;
2425 winpos.hwndInsertAfter = hwndInsertAfter;
2426 winpos.x = x;
2427 winpos.y = y;
2428 winpos.cx = cx;
2429 winpos.cy = cy;
2430 winpos.flags = flags;
2432 /* Send WM_WINDOWPOSCHANGING message */
2434 if (!(winpos.flags & SWP_NOSENDCHANGING))
2435 SendMessageA( hwnd, WM_WINDOWPOSCHANGING, 0, (LPARAM)&winpos );
2437 /* Calculate new position and size */
2439 newWindowRect = wndPtr->rectWindow;
2440 newClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
2441 : wndPtr->rectClient;
2443 if (!(winpos.flags & SWP_NOSIZE))
2445 newWindowRect.right = newWindowRect.left + winpos.cx;
2446 newWindowRect.bottom = newWindowRect.top + winpos.cy;
2448 if (!(winpos.flags & SWP_NOMOVE))
2450 newWindowRect.left = winpos.x;
2451 newWindowRect.top = winpos.y;
2452 newWindowRect.right += winpos.x - wndPtr->rectWindow.left;
2453 newWindowRect.bottom += winpos.y - wndPtr->rectWindow.top;
2455 OffsetRect( &newClientRect, winpos.x - wndPtr->rectWindow.left,
2456 winpos.y - wndPtr->rectWindow.top );
2459 winpos.flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
2461 /* Reposition window in Z order */
2463 if (!(winpos.flags & SWP_NOZORDER))
2465 /* reorder owned popups if hwnd is top-level window
2467 if( wndPtr->parent == WIN_GetDesktop() )
2469 hwndInsertAfter = WINPOS_ReorderOwnedPopups( hwndInsertAfter,
2470 wndPtr, winpos.flags );
2472 WIN_ReleaseDesktop();
2474 if (X11DRV_WND_GetXWindow(wndPtr))
2477 WIN_UnlinkWindow( winpos.hwnd );
2478 WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
2480 else
2481 WINPOS_MoveWindowZOrder( winpos.hwnd, hwndInsertAfter );
2484 if ( !X11DRV_WND_GetXWindow(wndPtr) && !(winpos.flags & SWP_NOREDRAW) &&
2485 ((winpos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED))
2486 != (SWP_NOMOVE | SWP_NOSIZE)) )
2487 visRgn = DCE_GetVisRgn(hwnd, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
2489 /* Send WM_NCCALCSIZE message to get new client area */
2490 if( (winpos.flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
2492 result = WINPOS_SendNCCalcSize( winpos.hwnd, TRUE, &newWindowRect,
2493 &wndPtr->rectWindow, &wndPtr->rectClient,
2494 &winpos, &newClientRect );
2496 /* FIXME: WVR_ALIGNxxx */
2498 if( newClientRect.left != wndPtr->rectClient.left ||
2499 newClientRect.top != wndPtr->rectClient.top )
2500 winpos.flags &= ~SWP_NOCLIENTMOVE;
2502 if( (newClientRect.right - newClientRect.left !=
2503 wndPtr->rectClient.right - wndPtr->rectClient.left) ||
2504 (newClientRect.bottom - newClientRect.top !=
2505 wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
2506 winpos.flags &= ~SWP_NOCLIENTSIZE;
2508 else
2509 if( !(flags & SWP_NOMOVE) && (newClientRect.left != wndPtr->rectClient.left ||
2510 newClientRect.top != wndPtr->rectClient.top) )
2511 winpos.flags &= ~SWP_NOCLIENTMOVE;
2513 /* Update active DCEs
2514 * TODO: Optimize conditions that trigger DCE update.
2517 if( (((winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) &&
2518 wndPtr->dwStyle & WS_VISIBLE) ||
2519 (flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
2521 RECT rect;
2523 UnionRect(&rect, &newWindowRect, &wndPtr->rectWindow);
2524 DCE_InvalidateDCE(wndPtr, &rect);
2527 /* change geometry */
2529 oldWindowRect = wndPtr->rectWindow;
2531 if (X11DRV_WND_GetXWindow(wndPtr))
2533 RECT oldClientRect = wndPtr->rectClient;
2535 tempInsertAfter = winpos.hwndInsertAfter;
2537 winpos.hwndInsertAfter = hwndInsertAfter;
2539 /* postpone geometry change */
2541 if( !(flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW)) )
2543 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, TRUE);
2544 winpos.hwndInsertAfter = tempInsertAfter;
2546 else uFlags |= SMC_SETXPOS;
2548 wndPtr->rectWindow = newWindowRect;
2549 wndPtr->rectClient = newClientRect;
2551 if( !(flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW)) )
2553 if( (oldClientRect.left - oldWindowRect.left !=
2554 newClientRect.left - newWindowRect.left) ||
2555 (oldClientRect.top - oldWindowRect.top !=
2556 newClientRect.top - newWindowRect.top) ||
2557 (winpos.flags & SWP_NOCOPYBITS) )
2559 /* if the client area moved as a result of WM_NCCALCSIZE returning
2560 * obscure WVR_ALIGNxxx flags then we simply redraw the whole thing
2562 * TODO: use WINPOS_SizeMoveClean() if there is no SWP_NOCOPYBITS
2565 PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, 0, RDW_INVALIDATE |
2566 RDW_ALLCHILDREN | RDW_FRAME | RDW_ERASE, 0 );
2568 else
2569 if( winpos.flags & SWP_FRAMECHANGED )
2571 WORD wErase = 0;
2572 RECT rect;
2574 if( newClientRect.right > oldClientRect.right ) /* redraw exposed client area on the right */
2576 rect.top = 0; rect.bottom = newClientRect.bottom - newClientRect.top;
2577 rect.left = oldClientRect.right - newClientRect.left;
2578 rect.right = newClientRect.right - newClientRect.left;
2579 wErase = 1;
2580 PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, 0,
2581 RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW | RDW_ALLCHILDREN, 0 );
2583 if( newClientRect.bottom > oldClientRect.bottom ) /* redraw exposed client area on the bottom */
2585 rect.left = 0; rect.right = ((wErase)?oldClientRect.right:newClientRect.right) - newClientRect.left;
2586 rect.top = oldClientRect.bottom - newClientRect.top;
2587 rect.bottom = newClientRect.bottom - newClientRect.top;
2588 wErase = 1;
2589 PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, 0,
2590 RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW | RDW_ALLCHILDREN, 0 );
2592 if( !wErase ) /* just update the nonclient area */
2593 // the previous command (wndPtr->flags |= WIN_NEEDS_NCPAINT)
2594 // was not enough. Absolutly need a non client update at this point
2595 // Cannot wait for the next WM_PAINT message, particularly in the menu-bar redrawing
2596 WIN_UpdateNCArea(wndPtr,TRUE);
2599 uFlags |= SMC_NOPARENTERASE; /* X windows do not have eraseable parents */
2601 else /* not an X window */
2603 RECT oldClientRect = wndPtr->rectClient;
2605 wndPtr->rectWindow = newWindowRect;
2606 wndPtr->rectClient = newClientRect;
2608 if( oldClientRect.bottom - oldClientRect.top ==
2609 newClientRect.bottom - newClientRect.top ) result &= ~WVR_VREDRAW;
2611 if( oldClientRect.right - oldClientRect.left ==
2612 newClientRect.right - newClientRect.left ) result &= ~WVR_HREDRAW;
2614 if( !(flags & (SWP_NOREDRAW | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
2616 uFlags |= ((winpos.flags & SWP_NOCOPYBITS) ||
2617 (result >= WVR_HREDRAW && result < WVR_VALIDRECTS)) ? SMC_NOCOPY : 0;
2618 uFlags |= (winpos.flags & SWP_FRAMECHANGED) ? SMC_DRAWFRAME : 0;
2620 if( (winpos.flags & SWP_AGG_NOGEOMETRYCHANGE) != SWP_AGG_NOGEOMETRYCHANGE )
2621 uFlags = WINPOS_SizeMoveClean(wndPtr, visRgn, &oldWindowRect,
2622 &oldClientRect, uFlags);
2623 else
2625 /* adjust the frame and do not erase the parent */
2627 if( winpos.flags & SWP_FRAMECHANGED ) wndPtr->flags |= WIN_NEEDS_NCPAINT;
2628 if( winpos.flags & SWP_NOZORDER ) uFlags |= SMC_NOPARENTERASE;
2631 DeleteObject(visRgn);
2634 if (flags & SWP_SHOWWINDOW)
2636 wndPtr->dwStyle |= WS_VISIBLE;
2637 if (X11DRV_WND_GetXWindow(wndPtr))
2639 HWND focus, curr;
2641 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, uFlags & SMC_SETXPOS );
2642 if( uFlags & SMC_SETXPOS )
2644 winpos.hwndInsertAfter = tempInsertAfter;
2647 if (wndPtr->flags & WIN_MANAGED) resync = TRUE;
2649 /* If focus was set to an unmapped window, reset X focus now */
2650 focus = curr = GetFocus();
2651 while (curr) {
2652 if (curr == hwnd) {
2653 WND *pFocus = WIN_FindWndPtr( focus );
2654 if (pFocus)
2655 pFocus->pDriver->pSetFocus(pFocus);
2656 WIN_ReleaseWndPtr(pFocus);
2657 break;
2659 curr = GetParent(curr);
2662 else
2664 if (!(flags & SWP_NOREDRAW))
2665 PAINT_RedrawWindow( winpos.hwnd, NULL, 0,
2666 RDW_INVALIDATE | RDW_ALLCHILDREN |
2667 RDW_FRAME | RDW_ERASENOW | RDW_ERASE, 0 );
2670 else if (flags & SWP_HIDEWINDOW)
2672 wndPtr->dwStyle &= ~WS_VISIBLE;
2673 if (X11DRV_WND_GetXWindow(wndPtr))
2675 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, uFlags & SMC_SETXPOS );
2676 if( uFlags & SMC_SETXPOS )
2678 winpos.hwndInsertAfter = tempInsertAfter;
2681 else
2683 if (!(flags & SWP_NOREDRAW))
2684 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, &oldWindowRect,
2685 0, RDW_INVALIDATE | RDW_ALLCHILDREN |
2686 RDW_ERASE | RDW_ERASENOW, 0 );
2687 uFlags |= SMC_NOPARENTERASE;
2690 if (hwnd == CARET_GetHwnd()) DestroyCaret();
2692 /* FIXME: This will cause the window to be activated irrespective
2693 * of whether it is owned by the same thread.
2694 * Should this behaviour be allowed in SetWindowPos?
2696 if (winpos.hwnd == hwndActive)
2697 WINPOS_ActivateOtherWindow( wndPtr );
2700 /* Activate the window */
2702 if (!(flags & SWP_NOACTIVATE))
2703 WINPOS_ChangeActiveWindow( winpos.hwnd, FALSE );
2705 /* Repaint the window */
2707 if (X11DRV_WND_GetXWindow(wndPtr))
2708 EVENT_Synchronize(); /* Wait for all expose events */
2710 if (!GetCapture() && ((wndPtr->dwStyle & WS_VISIBLE) || (flags & SWP_HIDEWINDOW)))
2711 EVENT_DummyMotionNotify(); /* Simulate a mouse event to set the cursor */
2713 wndTemp = WIN_GetDesktop();
2714 if (!(flags & SWP_DEFERERASE) && !(uFlags & SMC_NOPARENTERASE) )
2715 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0, RDW_ALLCHILDREN | RDW_ERASENOW, 0 );
2716 else if( wndPtr->parent == wndTemp && wndPtr->parent->flags & WIN_NEEDS_ERASEBKGND )
2718 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0, RDW_NOCHILDREN | RDW_ERASENOW, 0 );
2720 WIN_ReleaseDesktop();
2722 /* And last, send the WM_WINDOWPOSCHANGED message */
2724 TRACE(win,"\tstatus flags = %04x\n", winpos.flags & SWP_AGG_STATUSFLAGS);
2726 if ( resync ||
2727 (((winpos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) &&
2728 !(winpos.flags & SWP_NOSENDCHANGING)) )
2730 SendMessageA( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
2731 if (resync) EVENT_Synchronize ();
2734 retvalue = TRUE;
2735 END:
2736 WIN_ReleaseWndPtr(wndPtr);
2737 return retvalue;
2741 /***********************************************************************
2742 * BeginDeferWindowPos16 (USER.259)
2744 HDWP16 WINAPI BeginDeferWindowPos16( INT16 count )
2746 return BeginDeferWindowPos( count );
2750 /***********************************************************************
2751 * BeginDeferWindowPos (USER32.9)
2753 HDWP WINAPI BeginDeferWindowPos( INT count )
2755 HDWP handle;
2756 DWP *pDWP;
2758 if (count <= 0) return 0;
2759 handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
2760 if (!handle) return 0;
2761 pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
2762 pDWP->actualCount = 0;
2763 pDWP->suggestedCount = count;
2764 pDWP->valid = TRUE;
2765 pDWP->wMagic = DWP_MAGIC;
2766 pDWP->hwndParent = 0;
2767 return handle;
2771 /***********************************************************************
2772 * DeferWindowPos16 (USER.260)
2774 HDWP16 WINAPI DeferWindowPos16( HDWP16 hdwp, HWND16 hwnd, HWND16 hwndAfter,
2775 INT16 x, INT16 y, INT16 cx, INT16 cy,
2776 UINT16 flags )
2778 return DeferWindowPos( hdwp, hwnd, (INT)(INT16)hwndAfter,
2779 x, y, cx, cy, flags );
2783 /***********************************************************************
2784 * DeferWindowPos (USER32.128)
2786 HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter,
2787 INT x, INT y, INT cx, INT cy,
2788 UINT flags )
2790 DWP *pDWP;
2791 int i;
2792 HDWP newhdwp = hdwp,retvalue;
2793 /* HWND parent; */
2794 WND *pWnd;
2796 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
2797 if (!pDWP) return 0;
2798 if (hwnd == GetDesktopWindow()) return 0;
2800 if (!(pWnd=WIN_FindWndPtr( hwnd ))) {
2801 USER_HEAP_FREE( hdwp );
2802 return 0;
2805 /* Numega Bounds Checker Demo dislikes the following code.
2806 In fact, I've not been able to find any "same parent" requirement in any docu
2807 [AM 980509]
2809 #if 0
2810 /* All the windows of a DeferWindowPos() must have the same parent */
2811 parent = pWnd->parent->hwndSelf;
2812 if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
2813 else if (parent != pDWP->hwndParent)
2815 USER_HEAP_FREE( hdwp );
2816 retvalue = 0;
2817 goto END;
2819 #endif
2821 for (i = 0; i < pDWP->actualCount; i++)
2823 if (pDWP->winPos[i].hwnd == hwnd)
2825 /* Merge with the other changes */
2826 if (!(flags & SWP_NOZORDER))
2828 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
2830 if (!(flags & SWP_NOMOVE))
2832 pDWP->winPos[i].x = x;
2833 pDWP->winPos[i].y = y;
2835 if (!(flags & SWP_NOSIZE))
2837 pDWP->winPos[i].cx = cx;
2838 pDWP->winPos[i].cy = cy;
2840 pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
2841 SWP_NOZORDER | SWP_NOREDRAW |
2842 SWP_NOACTIVATE | SWP_NOCOPYBITS|
2843 SWP_NOOWNERZORDER);
2844 pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
2845 SWP_FRAMECHANGED);
2846 retvalue = hdwp;
2847 goto END;
2850 if (pDWP->actualCount >= pDWP->suggestedCount)
2852 newhdwp = USER_HEAP_REALLOC( hdwp,
2853 sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
2854 if (!newhdwp)
2856 retvalue = 0;
2857 goto END;
2859 pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
2860 pDWP->suggestedCount++;
2862 pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
2863 pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
2864 pDWP->winPos[pDWP->actualCount].x = x;
2865 pDWP->winPos[pDWP->actualCount].y = y;
2866 pDWP->winPos[pDWP->actualCount].cx = cx;
2867 pDWP->winPos[pDWP->actualCount].cy = cy;
2868 pDWP->winPos[pDWP->actualCount].flags = flags;
2869 pDWP->actualCount++;
2870 retvalue = newhdwp;
2871 END:
2872 WIN_ReleaseWndPtr(pWnd);
2873 return retvalue;
2877 /***********************************************************************
2878 * EndDeferWindowPos16 (USER.261)
2880 BOOL16 WINAPI EndDeferWindowPos16( HDWP16 hdwp )
2882 return EndDeferWindowPos( hdwp );
2886 /***********************************************************************
2887 * EndDeferWindowPos (USER32.173)
2889 BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
2891 DWP *pDWP;
2892 WINDOWPOS *winpos;
2893 BOOL res = TRUE;
2894 int i;
2896 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
2897 if (!pDWP) return FALSE;
2898 for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
2900 if (!(res = SetWindowPos( winpos->hwnd, winpos->hwndInsertAfter,
2901 winpos->x, winpos->y, winpos->cx,
2902 winpos->cy, winpos->flags ))) break;
2904 USER_HEAP_FREE( hdwp );
2905 return res;
2909 /***********************************************************************
2910 * TileChildWindows (USER.199)
2912 void WINAPI TileChildWindows16( HWND16 parent, WORD action )
2914 FIXME(win, "(%04x, %d): stub\n", parent, action);
2917 /***********************************************************************
2918 * CascageChildWindows (USER.198)
2920 void WINAPI CascadeChildWindows16( HWND16 parent, WORD action )
2922 FIXME(win, "(%04x, %d): stub\n", parent, action);
2924 /***********************************************************************
2925 * GetProgmanWindow [USER32.289]
2927 HRESULT WINAPI GetProgmanWindow ( )
2928 { FIXME(win,"stub\n");
2929 return 0;
2931 /***********************************************************************
2932 * GetTaskmanWindow [USER32.304]
2934 HRESULT WINAPI GetTaskmanWindow ( )
2935 { FIXME(win,"stub\n");
2936 return 0;
2938 /***********************************************************************
2939 * SetProgmanWindow [USER32.522]
2941 HRESULT WINAPI SetProgmanWindow ( DWORD x )
2942 { FIXME(win,"0x%08lx stub\n",x);
2943 return 0;
2945 /***********************************************************************
2946 * SetShellWindowEx [USER32.531]
2948 HRESULT WINAPI SetShellWindowEx ( DWORD x, DWORD y )
2949 { FIXME(win,"0x%08lx 0x%08lx stub\n",x,y);
2950 return 0;
2952 /***********************************************************************
2953 * SetTaskmanWindow [USER32.537]
2955 HRESULT WINAPI SetTaskmanWindow ( DWORD x )
2956 { FIXME(win,"0x%08lx stub\n",x);
2957 return 0;