Added a missing LeaveCriticalSection.
[wine.git] / windows / winpos.c
blob16d793e75ef444d75a191b6537e103cbb15e76e8
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 "sysmetrics.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 "debug.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
53 #define MINMAX_NOSWP 0x00010000
55 /* ----- internal variables ----- */
57 static HWND hwndPrevActive = 0; /* Previously active window */
58 static HWND hGlobalShellWindow=0; /*the shell*/
60 static LPCSTR atomInternalPos;
62 extern HQUEUE16 hActiveQueue;
64 /***********************************************************************
65 * WINPOS_CreateInternalPosAtom
67 BOOL WINPOS_CreateInternalPosAtom()
69 LPSTR str = "SysIP";
70 atomInternalPos = (LPCSTR)(DWORD)GlobalAddAtomA(str);
71 return (atomInternalPos) ? TRUE : FALSE;
74 /***********************************************************************
75 * WINPOS_CheckInternalPos
77 * Called when a window is destroyed.
79 void WINPOS_CheckInternalPos( WND* wndPtr )
81 LPINTERNALPOS lpPos;
82 MESSAGEQUEUE *pMsgQ = 0;
83 HWND hwnd = wndPtr->hwndSelf;
85 lpPos = (LPINTERNALPOS) GetPropA( hwnd, atomInternalPos );
87 /* Retrieve the message queue associated with this window */
88 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
89 if ( !pMsgQ )
91 WARN( win, "\tMessage queue not found. Exiting!\n" );
92 return;
95 if( hwnd == hwndPrevActive ) hwndPrevActive = 0;
97 if( hwnd == PERQDATA_GetActiveWnd( pMsgQ->pQData ) )
99 PERQDATA_SetActiveWnd( pMsgQ->pQData, 0 );
100 WARN(win, "\tattempt to activate destroyed window!\n");
103 if( lpPos )
105 if( IsWindow(lpPos->hwndIconTitle) )
106 DestroyWindow( lpPos->hwndIconTitle );
107 HeapFree( SystemHeap, 0, lpPos );
110 QUEUE_Unlock( pMsgQ );
111 return;
114 /***********************************************************************
115 * WINPOS_FindIconPos
117 * Find a suitable place for an iconic window.
119 static POINT16 WINPOS_FindIconPos( WND* wndPtr, POINT16 pt )
121 RECT16 rectParent;
122 short x, y, xspacing, yspacing;
124 GetClientRect16( wndPtr->parent->hwndSelf, &rectParent );
125 if ((pt.x >= rectParent.left) && (pt.x + SYSMETRICS_CXICON < rectParent.right) &&
126 (pt.y >= rectParent.top) && (pt.y + SYSMETRICS_CYICON < rectParent.bottom))
127 return pt; /* The icon already has a suitable position */
129 xspacing = SYSMETRICS_CXICONSPACING;
130 yspacing = SYSMETRICS_CYICONSPACING;
132 y = rectParent.bottom;
133 for (;;)
135 for (x = rectParent.left; x <= rectParent.right-xspacing; x += xspacing)
137 /* Check if another icon already occupies this spot */
138 WND *childPtr = WIN_LockWndPtr(wndPtr->parent->child);
139 while (childPtr)
141 if ((childPtr->dwStyle & WS_MINIMIZE) && (childPtr != wndPtr))
143 if ((childPtr->rectWindow.left < x + xspacing) &&
144 (childPtr->rectWindow.right >= x) &&
145 (childPtr->rectWindow.top <= y) &&
146 (childPtr->rectWindow.bottom > y - yspacing))
147 break; /* There's a window in there */
149 WIN_UpdateWndPtr(&childPtr,childPtr->next);
151 WIN_ReleaseWndPtr(childPtr);
152 if (!childPtr) /* No window was found, so it's OK for us */
154 pt.x = x + (xspacing - SYSMETRICS_CXICON) / 2;
155 pt.y = y - (yspacing + SYSMETRICS_CYICON) / 2;
156 return pt;
159 y -= yspacing;
164 /***********************************************************************
165 * ArrangeIconicWindows16 (USER.170)
167 UINT16 WINAPI ArrangeIconicWindows16( HWND16 parent)
169 return ArrangeIconicWindows(parent);
171 /***********************************************************************
172 * ArrangeIconicWindows (USER32.7)
174 UINT WINAPI ArrangeIconicWindows( HWND parent )
176 RECT rectParent;
177 HWND hwndChild;
178 INT x, y, xspacing, yspacing;
180 GetClientRect( parent, &rectParent );
181 x = rectParent.left;
182 y = rectParent.bottom;
183 xspacing = SYSMETRICS_CXICONSPACING;
184 yspacing = SYSMETRICS_CYICONSPACING;
186 hwndChild = GetWindow( parent, GW_CHILD );
187 while (hwndChild)
189 if( IsIconic( hwndChild ) )
191 WND *wndPtr = WIN_FindWndPtr(hwndChild);
193 WINPOS_ShowIconTitle( wndPtr, FALSE );
195 SetWindowPos( hwndChild, 0, x + (xspacing - SYSMETRICS_CXICON) / 2,
196 y - yspacing - SYSMETRICS_CYICON/2, 0, 0,
197 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
198 if( IsWindow(hwndChild) )
199 WINPOS_ShowIconTitle(wndPtr , TRUE );
200 WIN_ReleaseWndPtr(wndPtr);
202 if (x <= rectParent.right - xspacing) x += xspacing;
203 else
205 x = rectParent.left;
206 y -= yspacing;
209 hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
211 return yspacing;
215 /***********************************************************************
216 * SwitchToThisWindow16 (USER.172)
218 void WINAPI SwitchToThisWindow16( HWND16 hwnd, BOOL16 restore )
220 SwitchToThisWindow( hwnd, restore );
224 /***********************************************************************
225 * SwitchToThisWindow (USER32.539)
227 void WINAPI SwitchToThisWindow( HWND hwnd, BOOL restore )
229 ShowWindow( hwnd, restore ? SW_RESTORE : SW_SHOWMINIMIZED );
233 /***********************************************************************
234 * GetWindowRect16 (USER.32)
236 void WINAPI GetWindowRect16( HWND16 hwnd, LPRECT16 rect )
238 WND * wndPtr = WIN_FindWndPtr( hwnd );
239 if (!wndPtr) return;
241 CONV_RECT32TO16( &wndPtr->rectWindow, rect );
242 if (wndPtr->dwStyle & WS_CHILD)
243 MapWindowPoints16( wndPtr->parent->hwndSelf, 0, (POINT16 *)rect, 2 );
244 WIN_ReleaseWndPtr(wndPtr);
248 /***********************************************************************
249 * GetWindowRect (USER32.308)
251 BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect )
253 WND * wndPtr = WIN_FindWndPtr( hwnd );
254 if (!wndPtr) return FALSE;
256 *rect = wndPtr->rectWindow;
257 if (wndPtr->dwStyle & WS_CHILD)
258 MapWindowPoints( wndPtr->parent->hwndSelf, 0, (POINT *)rect, 2 );
259 WIN_ReleaseWndPtr(wndPtr);
260 return TRUE;
264 /***********************************************************************
265 * GetWindowRgn
267 BOOL WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
270 RECT rect;
271 WND * wndPtr = WIN_FindWndPtr( hwnd );
272 if (!wndPtr) return (ERROR);
274 FIXME (win, "GetWindowRgn: doesn't really do regions\n");
276 memset (&rect, 0, sizeof(rect));
278 GetWindowRect ( hwnd, &rect );
280 FIXME (win, "Check whether a valid region here\n");
282 SetRectRgn ( hrgn, rect.left, rect.top, rect.right, rect.bottom );
284 WIN_ReleaseWndPtr(wndPtr);
285 return (SIMPLEREGION);
288 /***********************************************************************
289 * SetWindowRgn
291 INT WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn,BOOL bRedraw)
295 FIXME (win, "SetWindowRgn: stub\n");
296 return TRUE;
299 /***********************************************************************
300 * SetWindowRgn16
302 INT16 WINAPI SetWindowRgn16( HWND16 hwnd, HRGN16 hrgn,BOOL16 bRedraw)
306 FIXME (win, "SetWindowRgn16: stub\n");
307 return TRUE;
311 /***********************************************************************
312 * GetClientRect16 (USER.33)
314 void WINAPI GetClientRect16( HWND16 hwnd, LPRECT16 rect )
316 WND * wndPtr = WIN_FindWndPtr( hwnd );
318 rect->left = rect->top = rect->right = rect->bottom = 0;
319 if (wndPtr)
321 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
322 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
324 WIN_ReleaseWndPtr(wndPtr);
328 /***********************************************************************
329 * GetClientRect (USER.220)
331 BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect )
333 WND * wndPtr = WIN_FindWndPtr( hwnd );
335 rect->left = rect->top = rect->right = rect->bottom = 0;
336 if (!wndPtr) return FALSE;
337 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
338 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
340 WIN_ReleaseWndPtr(wndPtr);
341 return TRUE;
345 /*******************************************************************
346 * ClientToScreen16 (USER.28)
348 void WINAPI ClientToScreen16( HWND16 hwnd, LPPOINT16 lppnt )
350 MapWindowPoints16( hwnd, 0, lppnt, 1 );
354 /*******************************************************************
355 * ClientToScreen (USER32.52)
357 BOOL WINAPI ClientToScreen( HWND hwnd, LPPOINT lppnt )
359 MapWindowPoints( hwnd, 0, lppnt, 1 );
360 return TRUE;
364 /*******************************************************************
365 * ScreenToClient16 (USER.29)
367 void WINAPI ScreenToClient16( HWND16 hwnd, LPPOINT16 lppnt )
369 MapWindowPoints16( 0, hwnd, lppnt, 1 );
373 /*******************************************************************
374 * ScreenToClient (USER32.447)
376 BOOL WINAPI ScreenToClient( HWND hwnd, LPPOINT lppnt )
378 MapWindowPoints( 0, hwnd, lppnt, 1 );
379 return TRUE;
383 /***********************************************************************
384 * WINPOS_WindowFromPoint
386 * Find the window and hittest for a given point.
388 INT16 WINPOS_WindowFromPoint( WND* wndScope, POINT16 pt, WND **ppWnd )
390 WND *wndPtr;
391 INT16 hittest = HTERROR;
392 INT16 retvalue;
393 POINT16 xy = pt;
395 *ppWnd = NULL;
396 wndPtr = WIN_LockWndPtr(wndScope->child);
398 if( wndScope->flags & WIN_MANAGED )
400 /* In managed mode we have to check wndScope first as it is also
401 * a window which received the mouse event. */
403 if( wndScope->dwStyle & WS_DISABLED )
405 retvalue = HTERROR;
406 goto end;
408 if( pt.x < wndScope->rectClient.left || pt.x >= wndScope->rectClient.right ||
409 pt.y < wndScope->rectClient.top || pt.y >= wndScope->rectClient.bottom )
410 goto hittest;
412 MapWindowPoints16( GetDesktopWindow16(), wndScope->hwndSelf, &xy, 1 );
414 for (;;)
416 while (wndPtr)
418 /* If point is in window, and window is visible, and it */
419 /* is enabled (or it's a top-level window), then explore */
420 /* its children. Otherwise, go to the next window. */
422 if ((wndPtr->dwStyle & WS_VISIBLE) &&
423 (!(wndPtr->dwStyle & WS_DISABLED) ||
424 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)) &&
425 (xy.x >= wndPtr->rectWindow.left) &&
426 (xy.x < wndPtr->rectWindow.right) &&
427 (xy.y >= wndPtr->rectWindow.top) &&
428 (xy.y < wndPtr->rectWindow.bottom))
430 *ppWnd = wndPtr; /* Got a suitable window */
432 /* If window is minimized or disabled, return at once */
433 if (wndPtr->dwStyle & WS_MINIMIZE)
435 retvalue = HTCAPTION;
436 goto end;
438 if (wndPtr->dwStyle & WS_DISABLED)
440 retvalue = HTERROR;
441 goto end;
444 /* If point is not in client area, ignore the children */
445 if ((xy.x < wndPtr->rectClient.left) ||
446 (xy.x >= wndPtr->rectClient.right) ||
447 (xy.y < wndPtr->rectClient.top) ||
448 (xy.y >= wndPtr->rectClient.bottom)) break;
450 xy.x -= wndPtr->rectClient.left;
451 xy.y -= wndPtr->rectClient.top;
452 WIN_UpdateWndPtr(&wndPtr,wndPtr->child);
454 else
456 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
460 hittest:
461 /* If nothing found, try the scope window */
462 if (!*ppWnd) *ppWnd = wndScope;
464 /* Send the WM_NCHITTEST message (only if to the same task) */
465 if ((*ppWnd)->hmemTaskQ == GetFastQueue16())
467 hittest = (INT16)SendMessage16( (*ppWnd)->hwndSelf, WM_NCHITTEST,
468 0, MAKELONG( pt.x, pt.y ) );
469 if (hittest != HTTRANSPARENT)
471 retvalue = hittest; /* Found the window */
472 goto end;
475 else
477 retvalue = HTCLIENT;
478 goto end;
481 /* If no children found in last search, make point relative to parent */
482 if (!wndPtr)
484 xy.x += (*ppWnd)->rectClient.left;
485 xy.y += (*ppWnd)->rectClient.top;
488 /* Restart the search from the next sibling */
489 WIN_UpdateWndPtr(&wndPtr,(*ppWnd)->next);
490 *ppWnd = (*ppWnd)->parent;
493 end:
494 WIN_ReleaseWndPtr(wndPtr);
495 return retvalue;
499 /*******************************************************************
500 * WindowFromPoint16 (USER.30)
502 HWND16 WINAPI WindowFromPoint16( POINT16 pt )
504 WND *pWnd;
505 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt, &pWnd );
506 WIN_ReleaseDesktop();
507 return pWnd->hwndSelf;
511 /*******************************************************************
512 * WindowFromPoint (USER32.582)
514 HWND WINAPI WindowFromPoint( POINT pt )
516 WND *pWnd;
517 POINT16 pt16;
518 CONV_POINT32TO16( &pt, &pt16 );
519 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16, &pWnd );
520 WIN_ReleaseDesktop();
521 return (HWND)pWnd->hwndSelf;
525 /*******************************************************************
526 * ChildWindowFromPoint16 (USER.191)
528 HWND16 WINAPI ChildWindowFromPoint16( HWND16 hwndParent, POINT16 pt )
530 POINT pt32;
531 CONV_POINT16TO32( &pt, &pt32 );
532 return (HWND16)ChildWindowFromPoint( hwndParent, pt32 );
536 /*******************************************************************
537 * ChildWindowFromPoint (USER32.49)
539 HWND WINAPI ChildWindowFromPoint( HWND hwndParent, POINT pt )
541 /* pt is in the client coordinates */
543 WND* wnd = WIN_FindWndPtr(hwndParent);
544 RECT rect;
545 HWND retvalue;
547 if( !wnd ) return 0;
549 /* get client rect fast */
550 rect.top = rect.left = 0;
551 rect.right = wnd->rectClient.right - wnd->rectClient.left;
552 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
554 if (!PtInRect( &rect, pt ))
556 retvalue = 0;
557 goto end;
559 WIN_UpdateWndPtr(&wnd,wnd->child);
560 while ( wnd )
562 if (PtInRect( &wnd->rectWindow, pt ))
564 retvalue = wnd->hwndSelf;
565 goto end;
567 WIN_UpdateWndPtr(&wnd,wnd->next);
569 retvalue = hwndParent;
570 end:
571 WIN_ReleaseWndPtr(wnd);
572 return retvalue;
575 /*******************************************************************
576 * ChildWindowFromPointEx16 (USER.50)
578 HWND16 WINAPI ChildWindowFromPointEx16( HWND16 hwndParent, POINT16 pt, UINT16 uFlags)
580 POINT pt32;
581 CONV_POINT16TO32( &pt, &pt32 );
582 return (HWND16)ChildWindowFromPointEx( hwndParent, pt32, uFlags );
586 /*******************************************************************
587 * ChildWindowFromPointEx32 (USER32.50)
589 HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt,
590 UINT uFlags)
592 /* pt is in the client coordinates */
594 WND* wnd = WIN_FindWndPtr(hwndParent);
595 RECT rect;
596 HWND retvalue;
598 if( !wnd ) return 0;
600 /* get client rect fast */
601 rect.top = rect.left = 0;
602 rect.right = wnd->rectClient.right - wnd->rectClient.left;
603 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
605 if (!PtInRect( &rect, pt ))
607 retvalue = 0;
608 goto end;
610 WIN_UpdateWndPtr(&wnd,wnd->child);
612 while ( wnd )
614 if (PtInRect( &wnd->rectWindow, pt )) {
615 if ( (uFlags & CWP_SKIPINVISIBLE) &&
616 !(wnd->dwStyle & WS_VISIBLE) );
617 else if ( (uFlags & CWP_SKIPDISABLED) &&
618 (wnd->dwStyle & WS_DISABLED) );
619 else if ( (uFlags & CWP_SKIPTRANSPARENT) &&
620 (wnd->dwExStyle & WS_EX_TRANSPARENT) );
621 else
623 retvalue = wnd->hwndSelf;
624 goto end;
626 WIN_UpdateWndPtr(&wnd,wnd->next);
630 retvalue = hwndParent;
631 end:
632 WIN_ReleaseWndPtr(wnd);
633 return retvalue;
637 /*******************************************************************
638 * WINPOS_GetWinOffset
640 * Calculate the offset between the origin of the two windows. Used
641 * to implement MapWindowPoints.
643 static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo,
644 POINT *offset )
646 WND * wndPtr = 0;
648 offset->x = offset->y = 0;
649 if (hwndFrom == hwndTo ) return;
651 /* Translate source window origin to screen coords */
652 if (hwndFrom)
654 if (!(wndPtr = WIN_FindWndPtr( hwndFrom )))
656 ERR(win,"bad hwndFrom = %04x\n",hwndFrom);
657 return;
659 while (wndPtr->parent)
661 offset->x += wndPtr->rectClient.left;
662 offset->y += wndPtr->rectClient.top;
663 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
665 WIN_ReleaseWndPtr(wndPtr);
668 /* Translate origin to destination window coords */
669 if (hwndTo)
671 if (!(wndPtr = WIN_FindWndPtr( hwndTo )))
673 ERR(win,"bad hwndTo = %04x\n", hwndTo );
674 return;
676 while (wndPtr->parent)
678 offset->x -= wndPtr->rectClient.left;
679 offset->y -= wndPtr->rectClient.top;
680 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
682 WIN_ReleaseWndPtr(wndPtr);
687 /*******************************************************************
688 * MapWindowPoints16 (USER.258)
690 void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
691 LPPOINT16 lppt, UINT16 count )
693 POINT offset;
695 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
696 while (count--)
698 lppt->x += offset.x;
699 lppt->y += offset.y;
700 lppt++;
705 /*******************************************************************
706 * MapWindowPoints (USER32.386)
708 INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo,
709 LPPOINT lppt, UINT count )
711 POINT offset;
713 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
714 while (count--)
716 lppt->x += offset.x;
717 lppt->y += offset.y;
718 lppt++;
720 return MAKELONG( LOWORD(offset.x), LOWORD(offset.y) );
724 /***********************************************************************
725 * IsIconic16 (USER.31)
727 BOOL16 WINAPI IsIconic16(HWND16 hWnd)
729 return IsIconic(hWnd);
733 /***********************************************************************
734 * IsIconic (USER32.345)
736 BOOL WINAPI IsIconic(HWND hWnd)
738 BOOL retvalue;
739 WND * wndPtr = WIN_FindWndPtr(hWnd);
740 if (wndPtr == NULL) return FALSE;
741 retvalue = (wndPtr->dwStyle & WS_MINIMIZE) != 0;
742 WIN_ReleaseWndPtr(wndPtr);
743 return retvalue;
747 /***********************************************************************
748 * IsZoomed (USER.272)
750 BOOL16 WINAPI IsZoomed16(HWND16 hWnd)
752 return IsZoomed(hWnd);
756 /***********************************************************************
757 * IsZoomed (USER.352)
759 BOOL WINAPI IsZoomed(HWND hWnd)
761 BOOL retvalue;
762 WND * wndPtr = WIN_FindWndPtr(hWnd);
763 if (wndPtr == NULL) return FALSE;
764 retvalue = (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
765 WIN_ReleaseWndPtr(wndPtr);
766 return retvalue;
770 /*******************************************************************
771 * GetActiveWindow (USER.60)
773 HWND16 WINAPI GetActiveWindow16(void)
775 return (HWND16)GetActiveWindow();
778 /*******************************************************************
779 * GetActiveWindow (USER32.205)
781 HWND WINAPI GetActiveWindow(void)
783 MESSAGEQUEUE *pCurMsgQ = 0;
784 HWND hwndActive = 0;
786 /* Get the messageQ for the current thread */
787 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
789 WARN( win, "\tCurrent message queue not found. Exiting!\n" );
790 return 0;
793 /* Return the current active window from the perQ data of the current message Q */
794 hwndActive = PERQDATA_GetActiveWnd( pCurMsgQ->pQData );
796 QUEUE_Unlock( pCurMsgQ );
797 return hwndActive;
801 /*******************************************************************
802 * WINPOS_CanActivate
804 static BOOL WINPOS_CanActivate(WND* pWnd)
806 if( pWnd && ((pWnd->dwStyle & (WS_DISABLED | WS_VISIBLE | WS_CHILD))
807 == WS_VISIBLE) ) return TRUE;
808 return FALSE;
812 /*******************************************************************
813 * SetActiveWindow16 (USER.59)
815 HWND16 WINAPI SetActiveWindow16( HWND16 hwnd )
817 return SetActiveWindow(hwnd);
821 /*******************************************************************
822 * SetActiveWindow (USER32.463)
824 HWND WINAPI SetActiveWindow( HWND hwnd )
826 HWND prev = 0;
827 WND *wndPtr = WIN_FindWndPtr( hwnd );
828 MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
830 if ( !WINPOS_CanActivate(wndPtr) )
832 prev = 0;
833 goto end;
836 /* Get the messageQ for the current thread */
837 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
839 WARN( win, "\tCurrent message queue not found. Exiting!\n" );
840 goto CLEANUP;
843 /* Retrieve the message queue associated with this window */
844 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
845 if ( !pMsgQ )
847 WARN( win, "\tWindow message queue not found. Exiting!\n" );
848 goto CLEANUP;
851 /* Make sure that the window is associated with the calling threads
852 * message queue. It must share the same perQ data.
855 if ( pCurMsgQ->pQData != pMsgQ->pQData )
856 goto CLEANUP;
858 /* Save current active window */
859 prev = PERQDATA_GetActiveWnd( pMsgQ->pQData );
861 WINPOS_SetActiveWindow( hwnd, 0, 0 );
863 CLEANUP:
864 /* Unlock the queues before returning */
865 if ( pMsgQ )
866 QUEUE_Unlock( pMsgQ );
867 if ( pCurMsgQ )
868 QUEUE_Unlock( pCurMsgQ );
870 end:
871 WIN_ReleaseWndPtr(wndPtr);
872 return prev;
876 /*******************************************************************
877 * GetForegroundWindow16 (USER.608)
879 HWND16 WINAPI GetForegroundWindow16(void)
881 return (HWND16)GetForegroundWindow();
885 /*******************************************************************
886 * SetForegroundWindow16 (USER.609)
888 BOOL16 WINAPI SetForegroundWindow16( HWND16 hwnd )
890 return SetForegroundWindow( hwnd );
894 /*******************************************************************
895 * GetForegroundWindow (USER32.241)
897 HWND WINAPI GetForegroundWindow(void)
899 return GetActiveWindow();
903 /*******************************************************************
904 * SetForegroundWindow (USER32.482)
906 BOOL WINAPI SetForegroundWindow( HWND hwnd )
908 SetActiveWindow( hwnd );
909 return TRUE;
913 /*******************************************************************
914 * GetShellWindow16 (USER.600)
916 HWND16 WINAPI GetShellWindow16(void)
918 return GetShellWindow();
921 /*******************************************************************
922 * SetShellWindow (USER32.504)
924 HWND WINAPI SetShellWindow(HWND hwndshell)
925 { WARN(win, "(hWnd=%08x) semi stub\n",hwndshell );
927 hGlobalShellWindow = hwndshell;
928 return hGlobalShellWindow;
932 /*******************************************************************
933 * GetShellWindow (USER32.287)
935 HWND WINAPI GetShellWindow(void)
936 { WARN(win, "(hWnd=%x) semi stub\n",hGlobalShellWindow );
938 return hGlobalShellWindow;
942 /***********************************************************************
943 * BringWindowToTop16 (USER.45)
945 BOOL16 WINAPI BringWindowToTop16( HWND16 hwnd )
947 return BringWindowToTop(hwnd);
951 /***********************************************************************
952 * BringWindowToTop (USER32.11)
954 BOOL WINAPI BringWindowToTop( HWND hwnd )
956 return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
960 /***********************************************************************
961 * MoveWindow16 (USER.56)
963 BOOL16 WINAPI MoveWindow16( HWND16 hwnd, INT16 x, INT16 y, INT16 cx, INT16 cy,
964 BOOL16 repaint )
966 return MoveWindow(hwnd,x,y,cx,cy,repaint);
970 /***********************************************************************
971 * MoveWindow (USER32.399)
973 BOOL WINAPI MoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy,
974 BOOL repaint )
976 int flags = SWP_NOZORDER | SWP_NOACTIVATE;
977 if (!repaint) flags |= SWP_NOREDRAW;
978 TRACE(win, "%04x %d,%d %dx%d %d\n",
979 hwnd, x, y, cx, cy, repaint );
980 return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
983 /***********************************************************************
984 * WINPOS_InitInternalPos
986 static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT pt,
987 LPRECT restoreRect )
989 LPINTERNALPOS lpPos = (LPINTERNALPOS) GetPropA( wnd->hwndSelf,
990 atomInternalPos );
991 if( !lpPos )
993 /* this happens when the window is minimized/maximized
994 * for the first time (rectWindow is not adjusted yet) */
996 lpPos = HeapAlloc( SystemHeap, 0, sizeof(INTERNALPOS) );
997 if( !lpPos ) return NULL;
999 SetPropA( wnd->hwndSelf, atomInternalPos, (HANDLE)lpPos );
1000 lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
1001 CONV_RECT32TO16( &wnd->rectWindow, &lpPos->rectNormal );
1002 *(UINT*)&lpPos->ptIconPos = *(UINT*)&lpPos->ptMaxPos = 0xFFFFFFFF;
1005 if( wnd->dwStyle & WS_MINIMIZE )
1006 CONV_POINT32TO16( &pt, &lpPos->ptIconPos );
1007 else if( wnd->dwStyle & WS_MAXIMIZE )
1008 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1009 else if( restoreRect )
1010 CONV_RECT32TO16( restoreRect, &lpPos->rectNormal );
1012 return lpPos;
1015 /***********************************************************************
1016 * WINPOS_RedrawIconTitle
1018 BOOL WINPOS_RedrawIconTitle( HWND hWnd )
1020 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hWnd, atomInternalPos );
1021 if( lpPos )
1023 if( lpPos->hwndIconTitle )
1025 SendMessageA( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
1026 InvalidateRect( lpPos->hwndIconTitle, NULL, TRUE );
1027 return TRUE;
1030 return FALSE;
1033 /***********************************************************************
1034 * WINPOS_ShowIconTitle
1036 BOOL WINPOS_ShowIconTitle( WND* pWnd, BOOL bShow )
1038 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( pWnd->hwndSelf, atomInternalPos );
1040 if( lpPos && !(pWnd->flags & WIN_MANAGED))
1042 HWND16 hWnd = lpPos->hwndIconTitle;
1044 TRACE(win,"0x%04x %i\n", pWnd->hwndSelf, (bShow != 0) );
1046 if( !hWnd )
1047 lpPos->hwndIconTitle = hWnd = ICONTITLE_Create( pWnd );
1048 if( bShow )
1050 pWnd = WIN_FindWndPtr(hWnd);
1052 if( !(pWnd->dwStyle & WS_VISIBLE) )
1054 SendMessageA( hWnd, WM_SHOWWINDOW, TRUE, 0 );
1055 SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
1056 SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
1058 WIN_ReleaseWndPtr(pWnd);
1060 else ShowWindow( hWnd, SW_HIDE );
1062 return FALSE;
1065 /*******************************************************************
1066 * WINPOS_GetMinMaxInfo
1068 * Get the minimized and maximized information for a window.
1070 void WINPOS_GetMinMaxInfo( WND *wndPtr, POINT *maxSize, POINT *maxPos,
1071 POINT *minTrack, POINT *maxTrack )
1073 LPINTERNALPOS lpPos;
1074 MINMAXINFO MinMax;
1075 INT xinc, yinc;
1077 /* Compute default values */
1079 MinMax.ptMaxSize.x = SYSMETRICS_CXSCREEN;
1080 MinMax.ptMaxSize.y = SYSMETRICS_CYSCREEN;
1081 MinMax.ptMinTrackSize.x = SYSMETRICS_CXMINTRACK;
1082 MinMax.ptMinTrackSize.y = SYSMETRICS_CYMINTRACK;
1083 MinMax.ptMaxTrackSize.x = SYSMETRICS_CXSCREEN;
1084 MinMax.ptMaxTrackSize.y = SYSMETRICS_CYSCREEN;
1086 if (wndPtr->flags & WIN_MANAGED) xinc = yinc = 0;
1087 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1089 xinc = SYSMETRICS_CXDLGFRAME;
1090 yinc = SYSMETRICS_CYDLGFRAME;
1092 else
1094 xinc = yinc = 0;
1095 if (HAS_THICKFRAME(wndPtr->dwStyle))
1097 xinc += SYSMETRICS_CXFRAME;
1098 yinc += SYSMETRICS_CYFRAME;
1100 if (wndPtr->dwStyle & WS_BORDER)
1102 xinc += SYSMETRICS_CXBORDER;
1103 yinc += SYSMETRICS_CYBORDER;
1106 MinMax.ptMaxSize.x += 2 * xinc;
1107 MinMax.ptMaxSize.y += 2 * yinc;
1109 lpPos = (LPINTERNALPOS)GetPropA( wndPtr->hwndSelf, atomInternalPos );
1110 if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
1111 CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
1112 else
1114 MinMax.ptMaxPosition.x = -xinc;
1115 MinMax.ptMaxPosition.y = -yinc;
1118 SendMessageA( wndPtr->hwndSelf, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
1120 /* Some sanity checks */
1122 TRACE(win,"%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1123 MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
1124 MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
1125 MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
1126 MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
1127 MinMax.ptMaxTrackSize.x = MAX( MinMax.ptMaxTrackSize.x,
1128 MinMax.ptMinTrackSize.x );
1129 MinMax.ptMaxTrackSize.y = MAX( MinMax.ptMaxTrackSize.y,
1130 MinMax.ptMinTrackSize.y );
1132 if (maxSize) *maxSize = MinMax.ptMaxSize;
1133 if (maxPos) *maxPos = MinMax.ptMaxPosition;
1134 if (minTrack) *minTrack = MinMax.ptMinTrackSize;
1135 if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
1138 /***********************************************************************
1139 * WINPOS_MinMaximize
1141 * Fill in lpRect and return additional flags to be used with SetWindowPos().
1142 * This function assumes that 'cmd' is different from the current window
1143 * state.
1145 UINT WINPOS_MinMaximize( WND* wndPtr, UINT16 cmd, LPRECT16 lpRect )
1147 UINT swpFlags = 0;
1148 POINT pt;
1149 POINT size;
1150 LPINTERNALPOS lpPos;
1152 TRACE(win,"0x%04x %u\n", wndPtr->hwndSelf, cmd );
1154 size.x = wndPtr->rectWindow.left;
1155 size.y = wndPtr->rectWindow.top;
1157 lpPos = WINPOS_InitInternalPos( wndPtr, size, &wndPtr->rectWindow );
1159 if (lpPos && !HOOK_CallHooks16(WH_CBT, HCBT_MINMAX, wndPtr->hwndSelf, cmd))
1161 if( wndPtr->dwStyle & WS_MINIMIZE )
1163 if( !SendMessageA( wndPtr->hwndSelf, WM_QUERYOPEN, 0, 0L ) )
1164 return (SWP_NOSIZE | SWP_NOMOVE);
1165 swpFlags |= SWP_NOCOPYBITS;
1167 switch( cmd )
1169 case SW_MINIMIZE:
1170 if( wndPtr->dwStyle & WS_MAXIMIZE)
1172 wndPtr->flags |= WIN_RESTORE_MAX;
1173 wndPtr->dwStyle &= ~WS_MAXIMIZE;
1175 else
1176 wndPtr->flags &= ~WIN_RESTORE_MAX;
1177 wndPtr->dwStyle |= WS_MINIMIZE;
1179 if( wndPtr->flags & WIN_NATIVE )
1180 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, TRUE ) )
1181 swpFlags |= MINMAX_NOSWP;
1183 lpPos->ptIconPos = WINPOS_FindIconPos( wndPtr, lpPos->ptIconPos );
1185 SetRect16( lpRect, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1186 SYSMETRICS_CXICON, SYSMETRICS_CYICON );
1187 swpFlags |= SWP_NOCOPYBITS;
1188 break;
1190 case SW_MAXIMIZE:
1191 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1192 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL );
1193 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1195 if( wndPtr->dwStyle & WS_MINIMIZE )
1197 if( wndPtr->flags & WIN_NATIVE )
1198 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
1199 swpFlags |= MINMAX_NOSWP;
1201 WINPOS_ShowIconTitle( wndPtr, FALSE );
1202 wndPtr->dwStyle &= ~WS_MINIMIZE;
1204 wndPtr->dwStyle |= WS_MAXIMIZE;
1206 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1207 size.x, size.y );
1208 break;
1210 case SW_RESTORE:
1211 if( wndPtr->dwStyle & WS_MINIMIZE )
1213 if( wndPtr->flags & WIN_NATIVE )
1214 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
1215 swpFlags |= MINMAX_NOSWP;
1217 wndPtr->dwStyle &= ~WS_MINIMIZE;
1218 WINPOS_ShowIconTitle( wndPtr, FALSE );
1220 if( wndPtr->flags & WIN_RESTORE_MAX)
1222 /* Restore to maximized position */
1223 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1224 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL);
1225 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1226 wndPtr->dwStyle |= WS_MAXIMIZE;
1227 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y, size.x, size.y );
1228 break;
1231 else
1232 if( !(wndPtr->dwStyle & WS_MAXIMIZE) ) return (UINT16)(-1);
1233 else wndPtr->dwStyle &= ~WS_MAXIMIZE;
1235 /* Restore to normal position */
1237 *lpRect = lpPos->rectNormal;
1238 lpRect->right -= lpRect->left;
1239 lpRect->bottom -= lpRect->top;
1241 break;
1243 } else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
1244 return swpFlags;
1247 /***********************************************************************
1248 * ShowWindowAsync (USER32.535)
1250 * doesn't wait; returns immediately.
1251 * used by threads to toggle windows in other (possibly hanging) threads
1253 BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd )
1255 /* FIXME: does ShowWindow() return immediately ? */
1256 return ShowWindow(hwnd, cmd);
1260 /***********************************************************************
1261 * ShowWindow16 (USER.42)
1263 BOOL16 WINAPI ShowWindow16( HWND16 hwnd, INT16 cmd )
1265 return ShowWindow(hwnd,cmd);
1269 /***********************************************************************
1270 * ShowWindow (USER32.534)
1272 BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
1274 WND* wndPtr = WIN_FindWndPtr( hwnd );
1275 BOOL wasVisible, showFlag;
1276 RECT16 newPos = {0, 0, 0, 0};
1277 UINT swp = 0;
1279 if (!wndPtr) return FALSE;
1281 TRACE(win,"hwnd=%04x, cmd=%d\n", hwnd, cmd);
1283 wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
1285 switch(cmd)
1287 case SW_HIDE:
1288 if (!wasVisible) goto END;;
1289 swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
1290 SWP_NOACTIVATE | SWP_NOZORDER;
1291 if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus()))
1293 /* Revert focus to parent */
1294 SetFocus( GetParent(hwnd) );
1296 break;
1298 case SW_SHOWMINNOACTIVE:
1299 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1300 /* fall through */
1301 case SW_SHOWMINIMIZED:
1302 swp |= SWP_SHOWWINDOW;
1303 /* fall through */
1304 case SW_MINIMIZE:
1305 swp |= SWP_FRAMECHANGED;
1306 if( !(wndPtr->dwStyle & WS_MINIMIZE) )
1307 swp |= WINPOS_MinMaximize( wndPtr, SW_MINIMIZE, &newPos );
1308 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1309 break;
1311 case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
1312 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1313 if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
1314 swp |= WINPOS_MinMaximize( wndPtr, SW_MAXIMIZE, &newPos );
1315 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1316 break;
1318 case SW_SHOWNA:
1319 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1320 /* fall through */
1321 case SW_SHOW:
1322 swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
1323 break;
1325 case SW_SHOWNOACTIVATE:
1326 swp |= SWP_NOZORDER;
1327 if (GetActiveWindow()) swp |= SWP_NOACTIVATE;
1328 /* fall through */
1329 case SW_SHOWNORMAL: /* same as SW_NORMAL: */
1330 case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
1331 case SW_RESTORE:
1332 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1334 if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) )
1335 swp |= WINPOS_MinMaximize( wndPtr, SW_RESTORE, &newPos );
1336 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1337 break;
1340 showFlag = (cmd != SW_HIDE);
1341 if (showFlag != wasVisible)
1343 SendMessageA( hwnd, WM_SHOWWINDOW, showFlag, 0 );
1344 if (!IsWindow( hwnd )) goto END;
1347 if ((wndPtr->dwStyle & WS_CHILD) &&
1348 !IsWindowVisible( wndPtr->parent->hwndSelf ) &&
1349 (swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE) )
1351 /* Don't call SetWindowPos() on invisible child windows */
1352 if (cmd == SW_HIDE) wndPtr->dwStyle &= ~WS_VISIBLE;
1353 else wndPtr->dwStyle |= WS_VISIBLE;
1355 else
1357 /* We can't activate a child window */
1358 if (wndPtr->dwStyle & WS_CHILD) swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1359 if (!(swp & MINMAX_NOSWP))
1360 SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top,
1361 newPos.right, newPos.bottom, LOWORD(swp) );
1362 if (!IsWindow( hwnd )) goto END;
1363 else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( wndPtr, TRUE );
1366 if (wndPtr->flags & WIN_NEED_SIZE)
1368 /* should happen only in CreateWindowEx() */
1369 int wParam = SIZE_RESTORED;
1371 wndPtr->flags &= ~WIN_NEED_SIZE;
1372 if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
1373 else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
1374 SendMessageA( hwnd, WM_SIZE, wParam,
1375 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
1376 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
1377 SendMessageA( hwnd, WM_MOVE, 0,
1378 MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
1381 END:
1382 WIN_ReleaseWndPtr(wndPtr);
1383 return wasVisible;
1387 /***********************************************************************
1388 * GetInternalWindowPos16 (USER.460)
1390 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
1391 LPPOINT16 ptIcon )
1393 WINDOWPLACEMENT16 wndpl;
1394 if (GetWindowPlacement16( hwnd, &wndpl ))
1396 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1397 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1398 return wndpl.showCmd;
1400 return 0;
1404 /***********************************************************************
1405 * GetInternalWindowPos (USER32.245)
1407 UINT WINAPI GetInternalWindowPos( HWND hwnd, LPRECT rectWnd,
1408 LPPOINT ptIcon )
1410 WINDOWPLACEMENT wndpl;
1411 if (GetWindowPlacement( hwnd, &wndpl ))
1413 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1414 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1415 return wndpl.showCmd;
1417 return 0;
1420 /***********************************************************************
1421 * GetWindowPlacement16 (USER.370)
1423 BOOL16 WINAPI GetWindowPlacement16( HWND16 hwnd, WINDOWPLACEMENT16 *wndpl )
1425 WND *pWnd = WIN_FindWndPtr( hwnd );
1426 LPINTERNALPOS lpPos;
1428 if(!pWnd ) return FALSE;
1430 lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1431 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1432 wndpl->length = sizeof(*wndpl);
1433 if( pWnd->dwStyle & WS_MINIMIZE )
1434 wndpl->showCmd = SW_SHOWMINIMIZED;
1435 else
1436 wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE )
1437 ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
1438 if( pWnd->flags & WIN_RESTORE_MAX )
1439 wndpl->flags = WPF_RESTORETOMAXIMIZED;
1440 else
1441 wndpl->flags = 0;
1442 wndpl->ptMinPosition = lpPos->ptIconPos;
1443 wndpl->ptMaxPosition = lpPos->ptMaxPos;
1444 wndpl->rcNormalPosition = lpPos->rectNormal;
1446 WIN_ReleaseWndPtr(pWnd);
1447 return TRUE;
1451 /***********************************************************************
1452 * GetWindowPlacement (USER32.307)
1454 * Win95:
1455 * Fails if wndpl->length of Win95 (!) apps is invalid.
1457 BOOL WINAPI GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *pwpl32 )
1459 if( pwpl32 )
1461 WINDOWPLACEMENT16 wpl;
1462 wpl.length = sizeof(wpl);
1463 if( GetWindowPlacement16( hwnd, &wpl ) )
1465 pwpl32->length = sizeof(*pwpl32);
1466 pwpl32->flags = wpl.flags;
1467 pwpl32->showCmd = wpl.showCmd;
1468 CONV_POINT16TO32( &wpl.ptMinPosition, &pwpl32->ptMinPosition );
1469 CONV_POINT16TO32( &wpl.ptMaxPosition, &pwpl32->ptMaxPosition );
1470 CONV_RECT16TO32( &wpl.rcNormalPosition, &pwpl32->rcNormalPosition );
1471 return TRUE;
1474 return FALSE;
1478 /***********************************************************************
1479 * WINPOS_SetPlacement
1481 static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT16 *wndpl,
1482 UINT flags )
1484 WND *pWnd = WIN_FindWndPtr( hwnd );
1485 if( pWnd )
1487 LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1488 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1490 if( flags & PLACE_MIN ) lpPos->ptIconPos = wndpl->ptMinPosition;
1491 if( flags & PLACE_MAX ) lpPos->ptMaxPos = wndpl->ptMaxPosition;
1492 if( flags & PLACE_RECT) lpPos->rectNormal = wndpl->rcNormalPosition;
1494 if( pWnd->dwStyle & WS_MINIMIZE )
1496 WINPOS_ShowIconTitle( pWnd, FALSE );
1497 if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1498 SetWindowPos( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1499 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1501 else if( pWnd->dwStyle & WS_MAXIMIZE )
1503 if( !EMPTYPOINT(lpPos->ptMaxPos) )
1504 SetWindowPos( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1505 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1507 else if( flags & PLACE_RECT )
1508 SetWindowPos( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1509 lpPos->rectNormal.right - lpPos->rectNormal.left,
1510 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1511 SWP_NOZORDER | SWP_NOACTIVATE );
1513 ShowWindow( hwnd, wndpl->showCmd );
1514 if( IsWindow(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1516 if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd, TRUE );
1518 /* SDK: ...valid only the next time... */
1519 if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1521 WIN_ReleaseWndPtr(pWnd);
1522 return TRUE;
1524 return FALSE;
1528 /***********************************************************************
1529 * SetWindowPlacement16 (USER.371)
1531 BOOL16 WINAPI SetWindowPlacement16(HWND16 hwnd, const WINDOWPLACEMENT16 *wndpl)
1533 return WINPOS_SetPlacement( hwnd, wndpl,
1534 PLACE_MIN | PLACE_MAX | PLACE_RECT );
1537 /***********************************************************************
1538 * SetWindowPlacement (USER32.519)
1540 * Win95:
1541 * Fails if wndpl->length of Win95 (!) apps is invalid.
1543 BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *pwpl32 )
1545 if( pwpl32 )
1547 WINDOWPLACEMENT16 wpl;
1549 wpl.length = sizeof(WINDOWPLACEMENT16);
1550 wpl.flags = pwpl32->flags;
1551 wpl.showCmd = pwpl32->showCmd;
1552 wpl.ptMinPosition.x = pwpl32->ptMinPosition.x;
1553 wpl.ptMinPosition.y = pwpl32->ptMinPosition.y;
1554 wpl.ptMaxPosition.x = pwpl32->ptMaxPosition.x;
1555 wpl.ptMaxPosition.y = pwpl32->ptMaxPosition.y;
1556 wpl.rcNormalPosition.left = pwpl32->rcNormalPosition.left;
1557 wpl.rcNormalPosition.top = pwpl32->rcNormalPosition.top;
1558 wpl.rcNormalPosition.right = pwpl32->rcNormalPosition.right;
1559 wpl.rcNormalPosition.bottom = pwpl32->rcNormalPosition.bottom;
1561 return WINPOS_SetPlacement( hwnd, &wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1563 return FALSE;
1567 /***********************************************************************
1568 * SetInternalWindowPos16 (USER.461)
1570 void WINAPI SetInternalWindowPos16( HWND16 hwnd, UINT16 showCmd,
1571 LPRECT16 rect, LPPOINT16 pt )
1573 if( IsWindow16(hwnd) )
1575 WINDOWPLACEMENT16 wndpl;
1576 UINT flags;
1578 wndpl.length = sizeof(wndpl);
1579 wndpl.showCmd = showCmd;
1580 wndpl.flags = flags = 0;
1582 if( pt )
1584 flags |= PLACE_MIN;
1585 wndpl.flags |= WPF_SETMINPOSITION;
1586 wndpl.ptMinPosition = *pt;
1588 if( rect )
1590 flags |= PLACE_RECT;
1591 wndpl.rcNormalPosition = *rect;
1593 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1598 /***********************************************************************
1599 * SetInternalWindowPos (USER32.483)
1601 void WINAPI SetInternalWindowPos( HWND hwnd, UINT showCmd,
1602 LPRECT rect, LPPOINT pt )
1604 if( IsWindow(hwnd) )
1606 WINDOWPLACEMENT16 wndpl;
1607 UINT flags;
1609 wndpl.length = sizeof(wndpl);
1610 wndpl.showCmd = showCmd;
1611 wndpl.flags = flags = 0;
1613 if( pt )
1615 flags |= PLACE_MIN;
1616 wndpl.flags |= WPF_SETMINPOSITION;
1617 CONV_POINT32TO16( pt, &wndpl.ptMinPosition );
1619 if( rect )
1621 flags |= PLACE_RECT;
1622 CONV_RECT32TO16( rect, &wndpl.rcNormalPosition );
1624 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1628 /*******************************************************************
1629 * WINPOS_SetActiveWindow
1631 * SetActiveWindow() back-end. This is the only function that
1632 * can assign active status to a window. It must be called only
1633 * for the top level windows.
1635 BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
1637 CBTACTIVATESTRUCT16* cbtStruct;
1638 WND* wndPtr=0, *wndTemp;
1639 HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1640 MESSAGEQUEUE *pOldActiveQueue = 0, *pNewActiveQueue = 0;
1641 WORD wIconized = 0;
1642 HWND hwndActive = 0;
1643 BOOL bRet = 0;
1645 /* Get current active window from the active queue */
1646 if ( hActiveQueue )
1648 pOldActiveQueue = QUEUE_Lock( hActiveQueue );
1649 if ( pOldActiveQueue )
1650 hwndActive = PERQDATA_GetActiveWnd( pOldActiveQueue->pQData );
1653 /* paranoid checks */
1654 if( hWnd == GetDesktopWindow() || (bRet = (hWnd == hwndActive)) )
1655 goto CLEANUP_END;
1657 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1658 * return 0;
1660 wndPtr = WIN_FindWndPtr(hWnd);
1661 hOldActiveQueue = hActiveQueue;
1663 if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1665 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1666 WIN_ReleaseWndPtr(wndTemp);
1668 else
1669 TRACE(win,"no current active window.\n");
1671 /* call CBT hook chain */
1672 if ((cbtStruct = SEGPTR_NEW(CBTACTIVATESTRUCT16)))
1674 cbtStruct->fMouse = fMouse;
1675 cbtStruct->hWndActive = hwndActive;
1676 bRet = (BOOL)HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
1677 (LPARAM)SEGPTR_GET(cbtStruct) );
1678 SEGPTR_FREE(cbtStruct);
1679 if (bRet) goto CLEANUP_END;
1682 /* set prev active wnd to current active wnd and send notification */
1683 if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
1685 MESSAGEQUEUE *pTempActiveQueue = 0;
1687 if (!SendMessageA( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1689 if (GetSysModalWindow16() != hWnd)
1690 goto CLEANUP_END;
1691 /* disregard refusal if hWnd is sysmodal */
1694 SendMessageA( hwndPrevActive, WM_ACTIVATE,
1695 MAKEWPARAM( WA_INACTIVE, wIconized ),
1696 (LPARAM)hWnd );
1698 /* check if something happened during message processing
1699 * (global active queue may have changed)
1701 pTempActiveQueue = QUEUE_Lock( hActiveQueue );
1702 if(!pTempActiveQueue)
1703 goto CLEANUP_END;
1705 hwndActive = PERQDATA_GetActiveWnd( pTempActiveQueue->pQData );
1706 QUEUE_Unlock( pTempActiveQueue );
1707 if( hwndPrevActive != hwndActive )
1708 goto CLEANUP_END;
1711 /* Set new active window in the message queue */
1712 hwndActive = hWnd;
1713 if ( wndPtr )
1715 pNewActiveQueue = QUEUE_Lock( wndPtr->hmemTaskQ );
1716 if ( pNewActiveQueue )
1717 PERQDATA_SetActiveWnd( pNewActiveQueue->pQData, hwndActive );
1719 else /* have to do this or MDI frame activation goes to hell */
1720 if( pOldActiveQueue )
1721 PERQDATA_SetActiveWnd( pOldActiveQueue->pQData, 0 );
1723 /* send palette messages */
1724 if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1725 SendMessage16((HWND16)-1, WM_PALETTEISCHANGING, (WPARAM16)hWnd, 0L );
1727 /* if prev wnd is minimized redraw icon title */
1728 if( IsIconic( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1730 /* managed windows will get ConfigureNotify event */
1731 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->flags & WIN_MANAGED))
1733 /* check Z-order and bring hWnd to the top */
1734 for (wndTemp = WIN_LockWndPtr(WIN_GetDesktop()->child); wndTemp; WIN_UpdateWndPtr(&wndTemp,wndTemp->next))
1736 if (wndTemp->dwStyle & WS_VISIBLE) break;
1738 WIN_ReleaseDesktop();
1739 WIN_ReleaseWndPtr(wndTemp);
1741 if( wndTemp != wndPtr )
1742 SetWindowPos(hWnd, HWND_TOP, 0,0,0,0,
1743 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1744 if (!IsWindow(hWnd))
1745 goto CLEANUP;
1748 /* Get a handle to the new active queue */
1749 hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1751 /* send WM_ACTIVATEAPP if necessary */
1752 if (hOldActiveQueue != hNewActiveQueue)
1754 WND **list, **ppWnd;
1755 WND *pDesktop = WIN_GetDesktop();
1757 if ((list = WIN_BuildWinArray( pDesktop, 0, NULL )))
1759 for (ppWnd = list; *ppWnd; ppWnd++)
1761 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1763 if ((*ppWnd)->hmemTaskQ == hOldActiveQueue)
1764 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1765 0, QUEUE_GetQueueTask(hNewActiveQueue) );
1767 WIN_ReleaseWinArray(list);
1770 hActiveQueue = hNewActiveQueue;
1772 if ((list = WIN_BuildWinArray(pDesktop, 0, NULL )))
1774 for (ppWnd = list; *ppWnd; ppWnd++)
1776 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1778 if ((*ppWnd)->hmemTaskQ == hNewActiveQueue)
1779 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1780 1, QUEUE_GetQueueTask( hOldActiveQueue ) );
1782 WIN_ReleaseWinArray(list);
1784 WIN_ReleaseDesktop();
1786 if (!IsWindow(hWnd)) goto CLEANUP;
1789 if (hWnd)
1791 /* walk up to the first unowned window */
1792 wndTemp = WIN_LockWndPtr(wndPtr);
1793 while (wndTemp->owner)
1795 WIN_UpdateWndPtr(&wndTemp,wndTemp->owner);
1797 /* and set last active owned popup */
1798 wndTemp->hwndLastActive = hWnd;
1800 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1801 WIN_ReleaseWndPtr(wndTemp);
1802 SendMessageA( hWnd, WM_NCACTIVATE, TRUE, 0 );
1803 SendMessageA( hWnd, WM_ACTIVATE,
1804 MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1805 (LPARAM)hwndPrevActive );
1806 if( !IsWindow(hWnd) ) goto CLEANUP;
1809 /* change focus if possible */
1810 if( fChangeFocus && GetFocus() )
1811 if( WIN_GetTopParent(GetFocus()) != hwndActive )
1812 FOCUS_SwitchFocus( pNewActiveQueue, GetFocus(),
1813 (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
1815 hwndActive
1818 if( !hwndPrevActive && wndPtr )
1819 (*wndPtr->pDriver->pForceWindowRaise)(wndPtr);
1821 /* if active wnd is minimized redraw icon title */
1822 if( IsIconic(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1824 bRet = (hWnd == hwndActive); /* Success? */
1826 CLEANUP: /* Unlock the message queues before returning */
1828 if ( pNewActiveQueue )
1829 QUEUE_Unlock( pNewActiveQueue );
1831 CLEANUP_END:
1833 if ( pOldActiveQueue )
1834 QUEUE_Unlock( pOldActiveQueue );
1836 WIN_ReleaseWndPtr(wndPtr);
1837 return bRet;
1840 /*******************************************************************
1841 * WINPOS_ActivateOtherWindow
1843 * Activates window other than pWnd.
1845 BOOL WINPOS_ActivateOtherWindow(WND* pWnd)
1847 BOOL bRet = 0;
1848 WND* pWndTo = NULL;
1849 HWND hwndActive = 0;
1851 /* Get current active window from the active queue */
1852 if ( hActiveQueue )
1854 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1855 if ( pActiveQueue )
1857 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1858 QUEUE_Unlock( pActiveQueue );
1862 if( pWnd->hwndSelf == hwndPrevActive )
1863 hwndPrevActive = 0;
1865 if( hwndActive != pWnd->hwndSelf &&
1866 ( hwndActive || QUEUE_IsExitingQueue(pWnd->hmemTaskQ)) )
1867 return 0;
1869 if( !(pWnd->dwStyle & WS_POPUP) || !(pWnd->owner) ||
1870 !WINPOS_CanActivate((pWndTo = WIN_GetTopParentPtr(pWnd->owner))) )
1872 WND* pWndPtr = WIN_GetTopParentPtr(pWnd);
1874 pWndTo = WIN_FindWndPtr(hwndPrevActive);
1876 while( !WINPOS_CanActivate(pWndTo) )
1878 /* by now owned windows should've been taken care of */
1879 WIN_UpdateWndPtr(&pWndTo,pWndPtr->next);
1880 WIN_UpdateWndPtr(&pWndPtr,pWndTo);
1881 if( !pWndTo ) break;
1883 WIN_ReleaseWndPtr(pWndPtr);
1886 bRet = WINPOS_SetActiveWindow( pWndTo ? pWndTo->hwndSelf : 0, FALSE, TRUE );
1888 /* switch desktop queue to current active */
1889 if( pWndTo )
1891 WIN_GetDesktop()->hmemTaskQ = pWndTo->hmemTaskQ;
1892 WIN_ReleaseWndPtr(pWndTo);
1893 WIN_ReleaseDesktop();
1896 hwndPrevActive = 0;
1897 return bRet;
1900 /*******************************************************************
1901 * WINPOS_ChangeActiveWindow
1904 BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
1906 WND *wndPtr, *wndTemp;
1907 BOOL retvalue;
1908 HWND hwndActive = 0;
1910 /* Get current active window from the active queue */
1911 if ( hActiveQueue )
1913 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1914 if ( pActiveQueue )
1916 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1917 QUEUE_Unlock( pActiveQueue );
1921 if (!hWnd)
1922 return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
1924 wndPtr = WIN_FindWndPtr(hWnd);
1925 if( !wndPtr ) return FALSE;
1927 /* child windows get WM_CHILDACTIVATE message */
1928 if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
1930 retvalue = SendMessageA(hWnd, WM_CHILDACTIVATE, 0, 0L);
1931 goto end;
1934 if( hWnd == hwndActive )
1936 retvalue = FALSE;
1937 goto end;
1940 if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
1942 retvalue = FALSE;
1943 goto end;
1946 /* switch desktop queue to current active */
1947 wndTemp = WIN_GetDesktop();
1948 if( wndPtr->parent == wndTemp)
1949 wndTemp->hmemTaskQ = wndPtr->hmemTaskQ;
1950 WIN_ReleaseDesktop();
1952 retvalue = TRUE;
1953 end:
1954 WIN_ReleaseWndPtr(wndPtr);
1955 return retvalue;
1959 /***********************************************************************
1960 * WINPOS_SendNCCalcSize
1962 * Send a WM_NCCALCSIZE message to a window.
1963 * All parameters are read-only except newClientRect.
1964 * oldWindowRect, oldClientRect and winpos must be non-NULL only
1965 * when calcValidRect is TRUE.
1967 LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect,
1968 RECT *newWindowRect, RECT *oldWindowRect,
1969 RECT *oldClientRect, WINDOWPOS *winpos,
1970 RECT *newClientRect )
1972 NCCALCSIZE_PARAMS params;
1973 WINDOWPOS winposCopy;
1974 LONG result;
1976 params.rgrc[0] = *newWindowRect;
1977 if (calcValidRect)
1979 winposCopy = *winpos;
1980 params.rgrc[1] = *oldWindowRect;
1981 params.rgrc[2] = *oldClientRect;
1982 params.lppos = &winposCopy;
1984 result = SendMessageA( hwnd, WM_NCCALCSIZE, calcValidRect,
1985 (LPARAM)&params );
1986 TRACE(win, "%d,%d-%d,%d\n",
1987 params.rgrc[0].left, params.rgrc[0].top,
1988 params.rgrc[0].right, params.rgrc[0].bottom );
1989 *newClientRect = params.rgrc[0];
1990 return result;
1994 /***********************************************************************
1995 * WINPOS_HandleWindowPosChanging16
1997 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
1999 LONG WINPOS_HandleWindowPosChanging16( WND *wndPtr, WINDOWPOS16 *winpos )
2001 POINT maxSize, minTrack;
2002 if (winpos->flags & SWP_NOSIZE) return 0;
2003 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2004 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2006 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
2007 if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
2008 if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
2009 if (!(wndPtr->dwStyle & WS_MINIMIZE))
2011 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
2012 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
2015 return 0;
2019 /***********************************************************************
2020 * WINPOS_HandleWindowPosChanging
2022 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2024 LONG WINPOS_HandleWindowPosChanging( WND *wndPtr, WINDOWPOS *winpos )
2026 POINT maxSize;
2027 if (winpos->flags & SWP_NOSIZE) return 0;
2028 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2029 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2031 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, NULL, NULL );
2032 winpos->cx = MIN( winpos->cx, maxSize.x );
2033 winpos->cy = MIN( winpos->cy, maxSize.y );
2035 return 0;
2038 /***********************************************************************
2039 * SWP_DoOwnedPopups
2041 * fix Z order taking into account owned popups -
2042 * basically we need to maintain them above the window that owns them
2044 * FIXME: hide/show owned popups when owner visibility changes.
2046 static HWND SWP_DoOwnedPopups(WND* pDesktop, WND* wndPtr, HWND hwndInsertAfter, WORD flags)
2048 WND* w = WIN_LockWndPtr(pDesktop->child);
2050 WARN(win, "(%04x) hInsertAfter = %04x\n", wndPtr->hwndSelf, hwndInsertAfter );
2052 if( (wndPtr->dwStyle & WS_POPUP) && wndPtr->owner )
2054 /* make sure this popup stays above the owner */
2056 HWND hwndLocalPrev = HWND_TOP;
2058 if( hwndInsertAfter != HWND_TOP )
2060 while( w != wndPtr->owner )
2062 if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
2063 if( hwndLocalPrev == hwndInsertAfter ) break;
2064 WIN_UpdateWndPtr(&w,w->next);
2066 hwndInsertAfter = hwndLocalPrev;
2069 else if( wndPtr->dwStyle & WS_CHILD )
2070 goto END;
2072 WIN_UpdateWndPtr(&w, pDesktop->child);
2074 while( w )
2076 if( w == wndPtr ) break;
2078 if( (w->dwStyle & WS_POPUP) && w->owner == wndPtr )
2080 SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0,
2081 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
2082 hwndInsertAfter = w->hwndSelf;
2084 WIN_UpdateWndPtr(&w, w->next);
2087 END:
2088 WIN_ReleaseWndPtr(w);
2089 return hwndInsertAfter;
2092 /***********************************************************************
2093 * SWP_CopyValidBits
2095 * Make window look nice without excessive repainting
2097 * visible and update regions are in window coordinates
2098 * client and window rectangles are in parent client coordinates
2100 * FIXME: SWP_EX_PAINTSELF in uFlags works only if both old and new
2101 * window rects have the same origin.
2103 * Returns: uFlags and a dirty region in *pVisRgn.
2105 static UINT SWP_CopyValidBits( WND* Wnd, HRGN* pVisRgn,
2106 LPRECT lpOldWndRect,
2107 LPRECT lpOldClientRect, UINT uFlags )
2109 RECT r;
2110 HRGN newVisRgn, dirtyRgn;
2111 INT my = COMPLEXREGION;
2113 TRACE(win,"\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2114 Wnd->rectWindow.left, Wnd->rectWindow.top,
2115 Wnd->rectWindow.right, Wnd->rectWindow.bottom,
2116 lpOldWndRect->left, lpOldWndRect->top,
2117 lpOldWndRect->right, lpOldWndRect->bottom, *pVisRgn);
2118 TRACE(win,"\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2119 Wnd->rectClient.left, Wnd->rectClient.top,
2120 Wnd->rectClient.right, Wnd->rectClient.bottom,
2121 lpOldClientRect->left, lpOldClientRect->top,
2122 lpOldClientRect->right,lpOldClientRect->bottom );
2124 if( Wnd->hrgnUpdate == 1 )
2125 uFlags |= SWP_EX_NOCOPY; /* whole window is invalid, nothing to copy */
2127 newVisRgn = DCE_GetVisRgn( Wnd->hwndSelf, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
2128 dirtyRgn = CreateRectRgn( 0, 0, 0, 0 );
2130 if( !(uFlags & SWP_EX_NOCOPY) ) /* make sure dst region covers only valid bits */
2131 my = CombineRgn( dirtyRgn, newVisRgn, *pVisRgn, RGN_AND );
2133 if( (my == NULLREGION) || (uFlags & SWP_EX_NOCOPY) )
2135 nocopy:
2137 TRACE(win,"\twon't copy anything!\n");
2139 /* set dirtyRgn to the sum of old and new visible regions
2140 * in parent client coordinates */
2142 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2143 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2145 CombineRgn(*pVisRgn, *pVisRgn, newVisRgn, RGN_OR );
2147 else /* copy valid bits to a new location */
2149 INT dx, dy, ow, oh, nw, nh, ocw, ncw, och, nch;
2150 HRGN hrgnValid = dirtyRgn; /* non-empty intersection of old and new visible rgns */
2152 /* subtract already invalid region inside Wnd from the dst region */
2154 if( Wnd->hrgnUpdate )
2155 if( CombineRgn( hrgnValid, hrgnValid, Wnd->hrgnUpdate, RGN_DIFF) == NULLREGION )
2156 goto nocopy;
2158 /* check if entire window can be copied */
2160 ow = lpOldWndRect->right - lpOldWndRect->left;
2161 oh = lpOldWndRect->bottom - lpOldWndRect->top;
2162 nw = Wnd->rectWindow.right - Wnd->rectWindow.left;
2163 nh = Wnd->rectWindow.bottom - Wnd->rectWindow.top;
2165 ocw = lpOldClientRect->right - lpOldClientRect->left;
2166 och = lpOldClientRect->bottom - lpOldClientRect->top;
2167 ncw = Wnd->rectClient.right - Wnd->rectClient.left;
2168 nch = Wnd->rectClient.bottom - Wnd->rectClient.top;
2170 if( (ocw != ncw) || (och != nch) ||
2171 ( ow != nw) || ( oh != nw) ||
2172 ((lpOldClientRect->top - lpOldWndRect->top) !=
2173 (Wnd->rectClient.top - Wnd->rectWindow.top)) ||
2174 ((lpOldClientRect->left - lpOldWndRect->left) !=
2175 (Wnd->rectClient.left - Wnd->rectWindow.left)) )
2177 dx = Wnd->rectClient.left - lpOldClientRect->left;
2178 dy = Wnd->rectClient.top - lpOldClientRect->top;
2180 /* restrict valid bits to the common client rect */
2182 r.left = Wnd->rectClient.left - Wnd->rectWindow.left;
2183 r.top = Wnd->rectClient.top - Wnd->rectWindow.top;
2184 r.right = r.left + MIN( ocw, ncw );
2185 r.bottom = r.top + MIN( och, nch );
2187 REGION_CropRgn( hrgnValid, hrgnValid, &r,
2188 (uFlags & SWP_EX_PAINTSELF) ? NULL : (POINT*)&(Wnd->rectWindow));
2189 GetRgnBox( hrgnValid, &r );
2190 if( IsRectEmpty( &r ) )
2191 goto nocopy;
2192 r = *lpOldClientRect;
2194 else
2196 dx = Wnd->rectWindow.left - lpOldWndRect->left;
2197 dy = Wnd->rectWindow.top - lpOldWndRect->top;
2198 if( !(uFlags & SWP_EX_PAINTSELF) )
2199 OffsetRgn( hrgnValid, Wnd->rectWindow.left, Wnd->rectWindow.top );
2200 r = *lpOldWndRect;
2203 if( !(uFlags & SWP_EX_PAINTSELF) )
2205 /* Move remaining regions to parent coordinates */
2206 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2207 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2209 else
2210 OffsetRect( &r, -lpOldWndRect->left, -lpOldWndRect->top );
2212 TRACE(win,"\tcomputing dirty region!\n");
2214 /* Compute combined dirty region (old + new - valid) */
2215 CombineRgn( *pVisRgn, *pVisRgn, newVisRgn, RGN_OR);
2216 CombineRgn( *pVisRgn, *pVisRgn, hrgnValid, RGN_DIFF);
2218 /* Blt valid bits, r is the rect to copy */
2220 if( dx || dy )
2222 DC* dc;
2223 HDC hDC = ( uFlags & SWP_EX_PAINTSELF)
2224 ? GetDCEx( Wnd->hwndSelf, hrgnValid, DCX_WINDOW | DCX_CACHE |
2225 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS )
2226 : GetDCEx( Wnd->parent->hwndSelf, hrgnValid, DCX_CACHE |
2227 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2228 if( (dc = (DC *)GDI_GetObjPtr(hDC, DC_MAGIC)) )
2230 if( oh > nh ) r.bottom = r.top + nh;
2231 if( ow < nw ) r.right = r.left + nw;
2233 Wnd->pDriver->pSurfaceCopy( Wnd->parent, dc, dx, dy, &r, TRUE );
2235 GDI_HEAP_UNLOCK( hDC );
2237 ReleaseDC( (uFlags & SWP_EX_PAINTSELF) ?
2238 Wnd->hwndSelf : Wnd->parent->hwndSelf, hDC);
2242 /* *pVisRgn now points to the invalidated region */
2244 DeleteObject(newVisRgn);
2245 DeleteObject(dirtyRgn);
2246 return uFlags;
2249 /***********************************************************************
2250 * SWP_DoSimpleFrameChanged
2252 * NOTE: old and new client rect origins are identical, only
2253 * extents may have changed. Window extents are the same.
2255 static void SWP_DoSimpleFrameChanged( WND* wndPtr, RECT* pOldClientRect, WORD swpFlags, UINT uFlags )
2257 INT i = 0;
2258 RECT rect;
2259 HRGN hrgn = 0;
2261 if( !(swpFlags & SWP_NOCLIENTSIZE) )
2263 /* FIXME: WVR alignment flags */
2265 if( wndPtr->rectClient.right > pOldClientRect->right ) /* right edge */
2267 i++;
2268 rect.top = 0;
2269 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2270 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2271 if(!(uFlags & SWP_EX_NOCOPY))
2272 rect.left = pOldClientRect->right - wndPtr->rectClient.left;
2273 else
2275 rect.left = 0;
2276 goto redraw;
2280 if( wndPtr->rectClient.bottom > pOldClientRect->bottom ) /* bottom edge */
2282 if( i )
2283 hrgn = CreateRectRgnIndirect( &rect );
2284 rect.left = 0;
2285 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2286 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2287 if(!(uFlags & SWP_EX_NOCOPY))
2288 rect.top = pOldClientRect->bottom - wndPtr->rectClient.top;
2289 else
2290 rect.top = 0;
2291 if( i++ )
2292 REGION_UnionRectWithRgn( hrgn, &rect );
2295 if( i == 0 && (uFlags & SWP_EX_NOCOPY) ) /* force redraw anyway */
2297 rect = wndPtr->rectWindow;
2298 OffsetRect( &rect, wndPtr->rectWindow.left - wndPtr->rectClient.left,
2299 wndPtr->rectWindow.top - wndPtr->rectClient.top );
2300 i++;
2304 if( i )
2306 redraw:
2307 PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
2308 RDW_ERASENOW | RDW_ALLCHILDREN, RDW_EX_TOPFRAME | RDW_EX_USEHRGN );
2310 else
2311 hrgn = WIN_UpdateNCRgn(wndPtr, TRUE, TRUE);
2313 if( hrgn > 1 )
2314 DeleteObject( hrgn );
2317 /***********************************************************************
2318 * SWP_DoWinPosChanging
2320 static BOOL SWP_DoWinPosChanging( WND* wndPtr, WINDOWPOS* pWinpos,
2321 RECT* pNewWindowRect, RECT* pNewClientRect )
2323 /* Send WM_WINDOWPOSCHANGING message */
2325 if (!(pWinpos->flags & SWP_NOSENDCHANGING))
2326 SendMessageA( wndPtr->hwndSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM)pWinpos );
2328 /* Calculate new position and size */
2330 *pNewWindowRect = wndPtr->rectWindow;
2331 *pNewClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
2332 : wndPtr->rectClient;
2334 if (!(pWinpos->flags & SWP_NOSIZE))
2336 pNewWindowRect->right = pNewWindowRect->left + pWinpos->cx;
2337 pNewWindowRect->bottom = pNewWindowRect->top + pWinpos->cy;
2339 if (!(pWinpos->flags & SWP_NOMOVE))
2341 pNewWindowRect->left = pWinpos->x;
2342 pNewWindowRect->top = pWinpos->y;
2343 pNewWindowRect->right += pWinpos->x - wndPtr->rectWindow.left;
2344 pNewWindowRect->bottom += pWinpos->y - wndPtr->rectWindow.top;
2346 OffsetRect( pNewClientRect, pWinpos->x - wndPtr->rectWindow.left,
2347 pWinpos->y - wndPtr->rectWindow.top );
2350 pWinpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
2351 return TRUE;
2354 /***********************************************************************
2355 * SWP_DoNCCalcSize
2357 static UINT SWP_DoNCCalcSize( WND* wndPtr, WINDOWPOS* pWinpos,
2358 RECT* pNewWindowRect, RECT* pNewClientRect, WORD f)
2360 UINT wvrFlags = 0;
2362 /* Send WM_NCCALCSIZE message to get new client area */
2363 if( (pWinpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
2365 wvrFlags = WINPOS_SendNCCalcSize( pWinpos->hwnd, TRUE, pNewWindowRect,
2366 &wndPtr->rectWindow, &wndPtr->rectClient,
2367 pWinpos, pNewClientRect );
2369 /* FIXME: WVR_ALIGNxxx */
2371 if( pNewClientRect->left != wndPtr->rectClient.left ||
2372 pNewClientRect->top != wndPtr->rectClient.top )
2373 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2375 if( (pNewClientRect->right - pNewClientRect->left !=
2376 wndPtr->rectClient.right - wndPtr->rectClient.left) ||
2377 (pNewClientRect->bottom - pNewClientRect->top !=
2378 wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
2379 pWinpos->flags &= ~SWP_NOCLIENTSIZE;
2381 else
2382 if( !(f & SWP_NOMOVE) && (pNewClientRect->left != wndPtr->rectClient.left ||
2383 pNewClientRect->top != wndPtr->rectClient.top) )
2384 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2385 return wvrFlags;
2388 /***********************************************************************
2389 * SetWindowPos (USER.2)
2391 BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
2392 INT16 x, INT16 y, INT16 cx, INT16 cy, WORD flags)
2394 return SetWindowPos(hwnd,(INT)(INT16)hwndInsertAfter,x,y,cx,cy,flags);
2397 /***********************************************************************
2398 * SetWindowPos (USER32.520)
2400 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
2401 INT x, INT y, INT cx, INT cy, WORD flags)
2403 WINDOWPOS winpos;
2404 WND * wndPtr,*wndTemp;
2405 RECT newWindowRect, newClientRect;
2406 RECT oldWindowRect, oldClientRect;
2407 HRGN visRgn = 0;
2408 UINT wvrFlags = 0, uFlags = 0;
2409 BOOL retvalue, resync = FALSE;
2410 HWND hwndActive = 0;
2412 /* Get current active window from the active queue */
2413 if ( hActiveQueue )
2415 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2416 if ( pActiveQueue )
2418 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2419 QUEUE_Unlock( pActiveQueue );
2423 TRACE(win,"hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2424 hwnd, x, y, x+cx, y+cy, flags);
2426 /* ------------------------------------------------------------------------ CHECKS */
2428 /* Check window handle */
2430 if (hwnd == GetDesktopWindow()) return FALSE;
2431 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2433 TRACE(win,"\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr->rectWindow.left, wndPtr->rectWindow.top,
2434 wndPtr->rectWindow.right, wndPtr->rectWindow.bottom, (unsigned)wndPtr->dwStyle );
2436 /* Fix redundant flags */
2438 if(wndPtr->dwStyle & WS_VISIBLE)
2439 flags &= ~SWP_SHOWWINDOW;
2440 else
2442 if (!(flags & SWP_SHOWWINDOW))
2443 flags |= SWP_NOREDRAW;
2444 flags &= ~SWP_HIDEWINDOW;
2447 if ( cx < 0 ) cx = 0; if( cy < 0 ) cy = 0;
2449 if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
2450 (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
2451 flags |= SWP_NOSIZE; /* Already the right size */
2453 if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
2454 flags |= SWP_NOMOVE; /* Already the right position */
2456 if (hwnd == hwndActive)
2457 flags |= SWP_NOACTIVATE; /* Already active */
2458 else
2460 if(!(flags & SWP_NOACTIVATE)) /* Bring to the top when activating */
2462 flags &= ~SWP_NOZORDER;
2463 hwndInsertAfter = HWND_TOP;
2464 goto Pos;
2468 /* Check hwndInsertAfter */
2470 /* FIXME: TOPMOST not supported yet */
2471 if ((hwndInsertAfter == HWND_TOPMOST) ||
2472 (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
2474 /* hwndInsertAfter must be a sibling of the window */
2475 if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
2477 WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
2479 if( wnd ) {
2480 if( wnd->parent != wndPtr->parent )
2482 retvalue = FALSE;
2483 WIN_ReleaseWndPtr(wnd);
2484 goto END;
2486 if( wnd->next == wndPtr ) flags |= SWP_NOZORDER;
2488 WIN_ReleaseWndPtr(wnd);
2491 Pos: /* ------------------------------------------------------------------------ MAIN part */
2493 /* Fill the WINDOWPOS structure */
2495 winpos.hwnd = hwnd;
2496 winpos.hwndInsertAfter = hwndInsertAfter;
2497 winpos.x = x;
2498 winpos.y = y;
2499 winpos.cx = cx;
2500 winpos.cy = cy;
2501 winpos.flags = flags;
2503 SWP_DoWinPosChanging( wndPtr, &winpos, &newWindowRect, &newClientRect );
2505 if((winpos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER)
2507 if( wndPtr->parent == WIN_GetDesktop() )
2508 hwndInsertAfter = SWP_DoOwnedPopups( wndPtr->parent, wndPtr,
2509 hwndInsertAfter, winpos.flags );
2510 WIN_ReleaseDesktop();
2513 if(!(wndPtr->flags & WIN_NATIVE) )
2515 if( hwndInsertAfter == HWND_TOP )
2516 winpos.flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
2517 else
2518 if( hwndInsertAfter == HWND_BOTTOM )
2519 winpos.flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
2520 else
2521 if( !(winpos.flags & SWP_NOZORDER) )
2522 if( GetWindow(hwndInsertAfter, GW_HWNDNEXT) == wndPtr->hwndSelf )
2523 winpos.flags |= SWP_NOZORDER;
2525 if( !(winpos.flags & SWP_NOREDRAW) &&
2526 ((winpos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW | SWP_FRAMECHANGED))
2527 != (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)) )
2529 /* get a previous visible region for SWP_CopyValidBits() */
2531 visRgn = DCE_GetVisRgn(hwnd, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
2535 /* Common operations */
2537 wvrFlags = SWP_DoNCCalcSize( wndPtr, &winpos, &newWindowRect, &newClientRect, flags );
2539 if(!(winpos.flags & SWP_NOZORDER))
2541 /* upon window creation (while processing WM_NCCREATE), wndPtr->parent is set correctly
2542 * but wndPtr is not yet in wndPtr->parent->child list
2543 * in those cases (SetWindowPos called while processing WM_NCCREATE),
2544 * do not unlink/link winPtr in parent->child
2546 if ( WIN_UnlinkWindow( winpos.hwnd ) )
2547 WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
2550 /* Reset active DCEs */
2552 if( (((winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) &&
2553 wndPtr->dwStyle & WS_VISIBLE) ||
2554 (flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
2556 RECT rect;
2558 UnionRect(&rect, &newWindowRect, &wndPtr->rectWindow);
2559 DCE_InvalidateDCE(wndPtr, &rect);
2562 oldWindowRect = wndPtr->rectWindow;
2563 oldClientRect = wndPtr->rectClient;
2565 /* Find out if we have to redraw the whole client rect */
2567 if( oldClientRect.bottom - oldClientRect.top ==
2568 newClientRect.bottom - newClientRect.top ) wvrFlags &= ~WVR_VREDRAW;
2570 if( oldClientRect.right - oldClientRect.left ==
2571 newClientRect.right - newClientRect.left ) wvrFlags &= ~WVR_HREDRAW;
2573 uFlags |= ((winpos.flags & SWP_NOCOPYBITS) ||
2574 (!(winpos.flags & SWP_NOCLIENTSIZE) &&
2575 (wvrFlags >= WVR_HREDRAW) && (wvrFlags < WVR_VALIDRECTS))) ? SWP_EX_NOCOPY : 0;
2577 /* FIXME: actually do something with WVR_VALIDRECTS */
2579 wndPtr->rectWindow = newWindowRect;
2580 wndPtr->rectClient = newClientRect;
2582 if (wndPtr->flags & WIN_NATIVE) /* -------------------------------------------- hosted window */
2584 BOOL bCallDriver = TRUE;
2585 HWND tempInsertAfter = winpos.hwndInsertAfter;
2587 winpos.hwndInsertAfter = hwndInsertAfter;
2589 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2591 /* This is the only place where we need to force repainting of the contents
2592 of windows created by the host window system, all other cases go through the
2593 expose event handling */
2595 if( (winpos.flags & SWP_FRAMECHANGED) )
2597 INT x, y;
2599 if( (x = (newWindowRect.right - newWindowRect.left)) == (oldWindowRect.right - oldWindowRect.left) &&
2600 (y = (newWindowRect.bottom - newWindowRect.top)) == (oldWindowRect.bottom - oldWindowRect.top) )
2603 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, TRUE);
2604 winpos.hwndInsertAfter = tempInsertAfter;
2605 bCallDriver = FALSE;
2607 if( winpos.flags & SWP_NOCLIENTMOVE )
2608 SWP_DoSimpleFrameChanged(wndPtr, &oldClientRect, winpos.flags, uFlags );
2609 else
2611 /* client area moved but window extents remained the same, copy valid bits */
2613 visRgn = CreateRectRgn( 0, 0, x, y );
2614 uFlags = SWP_CopyValidBits( wndPtr, &visRgn, &oldWindowRect, &oldClientRect,
2615 uFlags | SWP_EX_PAINTSELF );
2621 if( bCallDriver )
2623 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2625 if( (oldClientRect.left - oldWindowRect.left == newClientRect.left - newWindowRect.left) &&
2626 (oldClientRect.top - oldWindowRect.top == newClientRect.top - newWindowRect.top) &&
2627 !(uFlags & SWP_EX_NOCOPY) )
2629 /* The origin of the client rect didn't move so we can try to repaint
2630 * only the nonclient area by setting bit gravity hint for the host window system.
2633 if( !(wndPtr->flags & WIN_MANAGED) )
2635 HRGN hrgn = CreateRectRgn( 0, 0, newWindowRect.right - newWindowRect.left,
2636 newWindowRect.bottom - newWindowRect.top);
2637 RECT rcn = newClientRect;
2638 RECT rco = oldClientRect;
2640 OffsetRect( &rcn, -newWindowRect.left, -newWindowRect.top );
2641 OffsetRect( &rco, -oldWindowRect.left, -oldWindowRect.top );
2642 IntersectRect( &rcn, &rcn, &rco );
2643 visRgn = CreateRectRgnIndirect( &rcn );
2644 CombineRgn( visRgn, hrgn, visRgn, RGN_DIFF );
2645 DeleteObject( hrgn );
2646 uFlags = SWP_EX_PAINTSELF;
2648 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGNorthWest );
2650 else
2651 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGForget );
2653 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, TRUE);
2654 winpos.hwndInsertAfter = tempInsertAfter;
2657 if( winpos.flags & SWP_SHOWWINDOW )
2659 HWND focus, curr;
2661 wndPtr->dwStyle |= WS_VISIBLE;
2663 if (wndPtr->flags & WIN_MANAGED) resync = TRUE;
2665 /* focus was set to unmapped window, reset host focus
2666 * since the window is now visible */
2668 focus = curr = GetFocus();
2669 while (curr)
2671 if (curr == hwnd)
2673 WND *pFocus = WIN_FindWndPtr( focus );
2674 if (pFocus)
2675 pFocus->pDriver->pSetFocus(pFocus);
2676 WIN_ReleaseWndPtr(pFocus);
2677 break;
2679 curr = GetParent(curr);
2683 else /* -------------------------------------------- emulated window */
2685 if( winpos.flags & SWP_SHOWWINDOW )
2687 wndPtr->dwStyle |= WS_VISIBLE;
2688 uFlags |= SWP_EX_PAINTSELF;
2689 visRgn = 1; /* redraw the whole window */
2691 else if( !(winpos.flags & SWP_NOREDRAW) )
2693 if( winpos.flags & SWP_HIDEWINDOW )
2695 if( visRgn > 1 ) /* map to parent */
2696 OffsetRgn( visRgn, oldWindowRect.left, oldWindowRect.top );
2697 else
2698 visRgn = 0;
2700 else
2702 if( (winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE )
2703 uFlags = SWP_CopyValidBits(wndPtr, &visRgn, &oldWindowRect,
2704 &oldClientRect, uFlags);
2705 else
2707 /* nothing moved, redraw frame if needed */
2709 if( winpos.flags & SWP_FRAMECHANGED )
2710 SWP_DoSimpleFrameChanged( wndPtr, &oldClientRect, winpos.flags, uFlags );
2711 if( visRgn )
2713 DeleteObject( visRgn );
2714 visRgn = 0;
2721 if( winpos.flags & SWP_HIDEWINDOW )
2723 wndPtr->dwStyle &= ~WS_VISIBLE;
2725 if (hwnd == CARET_GetHwnd()) DestroyCaret();
2727 /* FIXME: This will cause the window to be activated irrespective
2728 * of whether it is owned by the same thread. Has to be done
2729 * asynchronously.
2732 if (winpos.hwnd == hwndActive)
2733 WINPOS_ActivateOtherWindow( wndPtr );
2736 /* ------------------------------------------------------------------------ FINAL */
2738 if (wndPtr->flags & WIN_NATIVE)
2739 EVENT_Synchronize(); /* Synchronize with the host window system */
2741 if (!GetCapture() && ((wndPtr->dwStyle & WS_VISIBLE) || (flags & SWP_HIDEWINDOW)))
2742 EVENT_DummyMotionNotify(); /* Simulate a mouse event to set the cursor */
2744 wndTemp = WIN_GetDesktop();
2746 /* repaint invalidated region (if any)
2748 * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2749 * and force update after ChangeActiveWindow() to avoid painting frames twice.
2752 if( visRgn )
2754 if( !(winpos.flags & SWP_NOREDRAW) )
2756 if( uFlags & SWP_EX_PAINTSELF )
2758 PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn, RDW_ERASE | RDW_FRAME |
2759 ((winpos.flags & SWP_DEFERERASE) ? 0 : RDW_ERASENOW) | RDW_INVALIDATE |
2760 RDW_ALLCHILDREN, RDW_EX_XYWINDOW | RDW_EX_USEHRGN );
2762 else
2764 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn, RDW_ERASE |
2765 ((winpos.flags & SWP_DEFERERASE) ? 0 : RDW_ERASENOW) | RDW_INVALIDATE |
2766 RDW_ALLCHILDREN, RDW_EX_USEHRGN );
2769 if( visRgn != 1 )
2770 DeleteObject( visRgn );
2773 WIN_ReleaseDesktop();
2775 if (!(flags & SWP_NOACTIVATE))
2776 WINPOS_ChangeActiveWindow( winpos.hwnd, FALSE );
2778 /* And last, send the WM_WINDOWPOSCHANGED message */
2780 TRACE(win,"\tstatus flags = %04x\n", winpos.flags & SWP_AGG_STATUSFLAGS);
2782 if ( resync ||
2783 (((winpos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) &&
2784 !(winpos.flags & SWP_NOSENDCHANGING)) )
2786 SendMessageA( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
2787 if (resync) EVENT_Synchronize ();
2790 retvalue = TRUE;
2791 END:
2792 WIN_ReleaseWndPtr(wndPtr);
2793 return retvalue;
2797 /***********************************************************************
2798 * BeginDeferWindowPos16 (USER.259)
2800 HDWP16 WINAPI BeginDeferWindowPos16( INT16 count )
2802 return BeginDeferWindowPos( count );
2806 /***********************************************************************
2807 * BeginDeferWindowPos (USER32.9)
2809 HDWP WINAPI BeginDeferWindowPos( INT count )
2811 HDWP handle;
2812 DWP *pDWP;
2814 if (count <= 0) return 0;
2815 handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
2816 if (!handle) return 0;
2817 pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
2818 pDWP->actualCount = 0;
2819 pDWP->suggestedCount = count;
2820 pDWP->valid = TRUE;
2821 pDWP->wMagic = DWP_MAGIC;
2822 pDWP->hwndParent = 0;
2823 return handle;
2827 /***********************************************************************
2828 * DeferWindowPos16 (USER.260)
2830 HDWP16 WINAPI DeferWindowPos16( HDWP16 hdwp, HWND16 hwnd, HWND16 hwndAfter,
2831 INT16 x, INT16 y, INT16 cx, INT16 cy,
2832 UINT16 flags )
2834 return DeferWindowPos( hdwp, hwnd, (INT)(INT16)hwndAfter,
2835 x, y, cx, cy, flags );
2839 /***********************************************************************
2840 * DeferWindowPos (USER32.128)
2842 HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter,
2843 INT x, INT y, INT cx, INT cy,
2844 UINT flags )
2846 DWP *pDWP;
2847 int i;
2848 HDWP newhdwp = hdwp,retvalue;
2849 /* HWND parent; */
2850 WND *pWnd;
2852 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
2853 if (!pDWP) return 0;
2854 if (hwnd == GetDesktopWindow()) return 0;
2856 if (!(pWnd=WIN_FindWndPtr( hwnd ))) {
2857 USER_HEAP_FREE( hdwp );
2858 return 0;
2861 /* Numega Bounds Checker Demo dislikes the following code.
2862 In fact, I've not been able to find any "same parent" requirement in any docu
2863 [AM 980509]
2865 #if 0
2866 /* All the windows of a DeferWindowPos() must have the same parent */
2867 parent = pWnd->parent->hwndSelf;
2868 if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
2869 else if (parent != pDWP->hwndParent)
2871 USER_HEAP_FREE( hdwp );
2872 retvalue = 0;
2873 goto END;
2875 #endif
2877 for (i = 0; i < pDWP->actualCount; i++)
2879 if (pDWP->winPos[i].hwnd == hwnd)
2881 /* Merge with the other changes */
2882 if (!(flags & SWP_NOZORDER))
2884 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
2886 if (!(flags & SWP_NOMOVE))
2888 pDWP->winPos[i].x = x;
2889 pDWP->winPos[i].y = y;
2891 if (!(flags & SWP_NOSIZE))
2893 pDWP->winPos[i].cx = cx;
2894 pDWP->winPos[i].cy = cy;
2896 pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
2897 SWP_NOZORDER | SWP_NOREDRAW |
2898 SWP_NOACTIVATE | SWP_NOCOPYBITS|
2899 SWP_NOOWNERZORDER);
2900 pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
2901 SWP_FRAMECHANGED);
2902 retvalue = hdwp;
2903 goto END;
2906 if (pDWP->actualCount >= pDWP->suggestedCount)
2908 newhdwp = USER_HEAP_REALLOC( hdwp,
2909 sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
2910 if (!newhdwp)
2912 retvalue = 0;
2913 goto END;
2915 pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
2916 pDWP->suggestedCount++;
2918 pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
2919 pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
2920 pDWP->winPos[pDWP->actualCount].x = x;
2921 pDWP->winPos[pDWP->actualCount].y = y;
2922 pDWP->winPos[pDWP->actualCount].cx = cx;
2923 pDWP->winPos[pDWP->actualCount].cy = cy;
2924 pDWP->winPos[pDWP->actualCount].flags = flags;
2925 pDWP->actualCount++;
2926 retvalue = newhdwp;
2927 END:
2928 WIN_ReleaseWndPtr(pWnd);
2929 return retvalue;
2933 /***********************************************************************
2934 * EndDeferWindowPos16 (USER.261)
2936 BOOL16 WINAPI EndDeferWindowPos16( HDWP16 hdwp )
2938 return EndDeferWindowPos( hdwp );
2942 /***********************************************************************
2943 * EndDeferWindowPos (USER32.173)
2945 BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
2947 DWP *pDWP;
2948 WINDOWPOS *winpos;
2949 BOOL res = TRUE;
2950 int i;
2952 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
2953 if (!pDWP) return FALSE;
2954 for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
2956 if (!(res = SetWindowPos( winpos->hwnd, winpos->hwndInsertAfter,
2957 winpos->x, winpos->y, winpos->cx,
2958 winpos->cy, winpos->flags ))) break;
2960 USER_HEAP_FREE( hdwp );
2961 return res;
2965 /***********************************************************************
2966 * TileChildWindows (USER.199)
2968 void WINAPI TileChildWindows16( HWND16 parent, WORD action )
2970 FIXME(win, "(%04x, %d): stub\n", parent, action);
2973 /***********************************************************************
2974 * CascageChildWindows (USER.198)
2976 void WINAPI CascadeChildWindows16( HWND16 parent, WORD action )
2978 FIXME(win, "(%04x, %d): stub\n", parent, action);
2980 /***********************************************************************
2981 * GetProgmanWindow [USER32.289]
2983 HRESULT WINAPI GetProgmanWindow ( )
2984 { FIXME(win,"stub\n");
2985 return 0;
2987 /***********************************************************************
2988 * GetTaskmanWindow [USER32.304]
2990 HRESULT WINAPI GetTaskmanWindow ( )
2991 { FIXME(win,"stub\n");
2992 return 0;
2994 /***********************************************************************
2995 * SetProgmanWindow [USER32.522]
2997 HRESULT WINAPI SetProgmanWindow ( DWORD x )
2998 { FIXME(win,"0x%08lx stub\n",x);
2999 return 0;
3001 /***********************************************************************
3002 * SetShellWindowEx [USER32.531]
3004 HRESULT WINAPI SetShellWindowEx ( DWORD x, DWORD y )
3005 { FIXME(win,"0x%08lx 0x%08lx stub\n",x,y);
3006 return 0;
3008 /***********************************************************************
3009 * SetTaskmanWindow [USER32.537]
3011 HRESULT WINAPI SetTaskmanWindow ( DWORD x )
3012 { FIXME(win,"0x%08lx stub\n",x);
3013 return 0;