Rearranged PAINT_RedrawWindow() so that it first recursively updates
[wine/multimedia.git] / windows / winpos.c
blobb729de06ce1baf90a4d958a2f72be8cbdeba06d2
1 /*
2 * Window position related functions.
4 * Copyright 1993, 1994, 1995 Alexandre Julliard
5 * 1995, 1996, 1999 Alex Korobka
6 */
8 #include <string.h>
9 #include "wine/winuser16.h"
10 #include "sysmetrics.h"
11 #include "heap.h"
12 #include "module.h"
13 #include "user.h"
14 #include "region.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 DEFAULT_DEBUG_CHANNEL(win)
30 #define HAS_DLGFRAME(style,exStyle) \
31 (((exStyle) & WS_EX_DLGMODALFRAME) || \
32 (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
34 #define HAS_THICKFRAME(style) \
35 (((style) & WS_THICKFRAME) && \
36 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
38 #define SWP_AGG_NOGEOMETRYCHANGE \
39 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
40 #define SWP_AGG_NOPOSCHANGE \
41 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
42 #define SWP_AGG_STATUSFLAGS \
43 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
45 #define EMPTYPOINT(pt) ((*(LONG*)&(pt)) == -1)
47 #define PLACE_MIN 0x0001
48 #define PLACE_MAX 0x0002
49 #define PLACE_RECT 0x0004
51 #define SWP_EX_NOCOPY 0x0001
52 #define SWP_EX_PAINTSELF 0x0002
53 #define SWP_EX_NONCLIENT 0x0004
55 #define MINMAX_NOSWP 0x00010000
57 /* ----- internal variables ----- */
59 static HWND hwndPrevActive = 0; /* Previously active window */
60 static HWND hGlobalShellWindow=0; /*the shell*/
61 static HWND hGlobalTaskmanWindow=0;
62 static HWND hGlobalProgmanWindow=0;
64 static LPCSTR atomInternalPos;
66 extern HQUEUE16 hActiveQueue;
68 /***********************************************************************
69 * WINPOS_CreateInternalPosAtom
71 BOOL WINPOS_CreateInternalPosAtom()
73 LPSTR str = "SysIP";
74 atomInternalPos = (LPCSTR)(DWORD)GlobalAddAtomA(str);
75 return (atomInternalPos) ? TRUE : FALSE;
78 /***********************************************************************
79 * WINPOS_CheckInternalPos
81 * Called when a window is destroyed.
83 void WINPOS_CheckInternalPos( WND* wndPtr )
85 LPINTERNALPOS lpPos;
86 MESSAGEQUEUE *pMsgQ = 0;
87 HWND hwnd = wndPtr->hwndSelf;
89 lpPos = (LPINTERNALPOS) GetPropA( hwnd, atomInternalPos );
91 /* Retrieve the message queue associated with this window */
92 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
93 if ( !pMsgQ )
95 WARN( win, "\tMessage queue not found. Exiting!\n" );
96 return;
99 if( hwnd == hwndPrevActive ) hwndPrevActive = 0;
101 if( hwnd == PERQDATA_GetActiveWnd( pMsgQ->pQData ) )
103 PERQDATA_SetActiveWnd( pMsgQ->pQData, 0 );
104 WARN(win, "\tattempt to activate destroyed window!\n");
107 if( lpPos )
109 if( IsWindow(lpPos->hwndIconTitle) )
110 DestroyWindow( lpPos->hwndIconTitle );
111 HeapFree( SystemHeap, 0, lpPos );
114 QUEUE_Unlock( pMsgQ );
115 return;
118 /***********************************************************************
119 * WINPOS_FindIconPos
121 * Find a suitable place for an iconic window.
123 static POINT16 WINPOS_FindIconPos( WND* wndPtr, POINT16 pt )
125 RECT16 rectParent;
126 short x, y, xspacing, yspacing;
128 GetClientRect16( wndPtr->parent->hwndSelf, &rectParent );
129 if ((pt.x >= rectParent.left) && (pt.x + SYSMETRICS_CXICON < rectParent.right) &&
130 (pt.y >= rectParent.top) && (pt.y + SYSMETRICS_CYICON < rectParent.bottom))
131 return pt; /* The icon already has a suitable position */
133 xspacing = SYSMETRICS_CXICONSPACING;
134 yspacing = SYSMETRICS_CYICONSPACING;
136 y = rectParent.bottom;
137 for (;;)
139 for (x = rectParent.left; x <= rectParent.right-xspacing; x += xspacing)
141 /* Check if another icon already occupies this spot */
142 WND *childPtr = WIN_LockWndPtr(wndPtr->parent->child);
143 while (childPtr)
145 if ((childPtr->dwStyle & WS_MINIMIZE) && (childPtr != wndPtr))
147 if ((childPtr->rectWindow.left < x + xspacing) &&
148 (childPtr->rectWindow.right >= x) &&
149 (childPtr->rectWindow.top <= y) &&
150 (childPtr->rectWindow.bottom > y - yspacing))
151 break; /* There's a window in there */
153 WIN_UpdateWndPtr(&childPtr,childPtr->next);
155 WIN_ReleaseWndPtr(childPtr);
156 if (!childPtr) /* No window was found, so it's OK for us */
158 pt.x = x + (xspacing - SYSMETRICS_CXICON) / 2;
159 pt.y = y - (yspacing + SYSMETRICS_CYICON) / 2;
160 return pt;
163 y -= yspacing;
168 /***********************************************************************
169 * ArrangeIconicWindows16 (USER.170)
171 UINT16 WINAPI ArrangeIconicWindows16( HWND16 parent)
173 return ArrangeIconicWindows(parent);
175 /***********************************************************************
176 * ArrangeIconicWindows (USER32.7)
178 UINT WINAPI ArrangeIconicWindows( HWND parent )
180 RECT rectParent;
181 HWND hwndChild;
182 INT x, y, xspacing, yspacing;
184 GetClientRect( parent, &rectParent );
185 x = rectParent.left;
186 y = rectParent.bottom;
187 xspacing = SYSMETRICS_CXICONSPACING;
188 yspacing = SYSMETRICS_CYICONSPACING;
190 hwndChild = GetWindow( parent, GW_CHILD );
191 while (hwndChild)
193 if( IsIconic( hwndChild ) )
195 WND *wndPtr = WIN_FindWndPtr(hwndChild);
197 WINPOS_ShowIconTitle( wndPtr, FALSE );
199 SetWindowPos( hwndChild, 0, x + (xspacing - SYSMETRICS_CXICON) / 2,
200 y - yspacing - SYSMETRICS_CYICON/2, 0, 0,
201 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
202 if( IsWindow(hwndChild) )
203 WINPOS_ShowIconTitle(wndPtr , TRUE );
204 WIN_ReleaseWndPtr(wndPtr);
206 if (x <= rectParent.right - xspacing) x += xspacing;
207 else
209 x = rectParent.left;
210 y -= yspacing;
213 hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
215 return yspacing;
219 /***********************************************************************
220 * SwitchToThisWindow16 (USER.172)
222 void WINAPI SwitchToThisWindow16( HWND16 hwnd, BOOL16 restore )
224 SwitchToThisWindow( hwnd, restore );
228 /***********************************************************************
229 * SwitchToThisWindow (USER32.539)
231 void WINAPI SwitchToThisWindow( HWND hwnd, BOOL restore )
233 ShowWindow( hwnd, restore ? SW_RESTORE : SW_SHOWMINIMIZED );
237 /***********************************************************************
238 * GetWindowRect16 (USER.32)
240 void WINAPI GetWindowRect16( HWND16 hwnd, LPRECT16 rect )
242 WND * wndPtr = WIN_FindWndPtr( hwnd );
243 if (!wndPtr) return;
245 CONV_RECT32TO16( &wndPtr->rectWindow, rect );
246 if (wndPtr->dwStyle & WS_CHILD)
247 MapWindowPoints16( wndPtr->parent->hwndSelf, 0, (POINT16 *)rect, 2 );
248 WIN_ReleaseWndPtr(wndPtr);
252 /***********************************************************************
253 * GetWindowRect (USER32.308)
255 BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect )
257 WND * wndPtr = WIN_FindWndPtr( hwnd );
258 if (!wndPtr) return FALSE;
260 *rect = wndPtr->rectWindow;
261 if (wndPtr->dwStyle & WS_CHILD)
262 MapWindowPoints( wndPtr->parent->hwndSelf, 0, (POINT *)rect, 2 );
263 WIN_ReleaseWndPtr(wndPtr);
264 return TRUE;
268 /***********************************************************************
269 * GetWindowRgn
271 BOOL WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
274 RECT rect;
275 WND * wndPtr = WIN_FindWndPtr( hwnd );
276 if (!wndPtr) return (ERROR);
278 FIXME (win, "GetWindowRgn: doesn't really do regions\n");
280 memset (&rect, 0, sizeof(rect));
282 GetWindowRect ( hwnd, &rect );
284 FIXME (win, "Check whether a valid region here\n");
286 SetRectRgn ( hrgn, rect.left, rect.top, rect.right, rect.bottom );
288 WIN_ReleaseWndPtr(wndPtr);
289 return (SIMPLEREGION);
292 /***********************************************************************
293 * SetWindowRgn
295 INT WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn,BOOL bRedraw)
299 FIXME (win, "SetWindowRgn: stub\n");
300 return TRUE;
303 /***********************************************************************
304 * SetWindowRgn16
306 INT16 WINAPI SetWindowRgn16( HWND16 hwnd, HRGN16 hrgn,BOOL16 bRedraw)
310 FIXME (win, "SetWindowRgn16: stub\n");
311 return TRUE;
315 /***********************************************************************
316 * GetClientRect16 (USER.33)
318 void WINAPI GetClientRect16( HWND16 hwnd, LPRECT16 rect )
320 WND * wndPtr = WIN_FindWndPtr( hwnd );
322 rect->left = rect->top = rect->right = rect->bottom = 0;
323 if (wndPtr)
325 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
326 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
328 WIN_ReleaseWndPtr(wndPtr);
332 /***********************************************************************
333 * GetClientRect (USER.220)
335 BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect )
337 WND * wndPtr = WIN_FindWndPtr( hwnd );
339 rect->left = rect->top = rect->right = rect->bottom = 0;
340 if (!wndPtr) return FALSE;
341 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
342 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
344 WIN_ReleaseWndPtr(wndPtr);
345 return TRUE;
349 /*******************************************************************
350 * ClientToScreen16 (USER.28)
352 void WINAPI ClientToScreen16( HWND16 hwnd, LPPOINT16 lppnt )
354 MapWindowPoints16( hwnd, 0, lppnt, 1 );
358 /*******************************************************************
359 * ClientToScreen (USER32.52)
361 BOOL WINAPI ClientToScreen( HWND hwnd, LPPOINT lppnt )
363 MapWindowPoints( hwnd, 0, lppnt, 1 );
364 return TRUE;
368 /*******************************************************************
369 * ScreenToClient16 (USER.29)
371 void WINAPI ScreenToClient16( HWND16 hwnd, LPPOINT16 lppnt )
373 MapWindowPoints16( 0, hwnd, lppnt, 1 );
377 /*******************************************************************
378 * ScreenToClient (USER32.447)
380 BOOL WINAPI ScreenToClient( HWND hwnd, LPPOINT lppnt )
382 MapWindowPoints( 0, hwnd, lppnt, 1 );
383 return TRUE;
387 /***********************************************************************
388 * WINPOS_WindowFromPoint
390 * Find the window and hittest for a given point.
392 INT16 WINPOS_WindowFromPoint( WND* wndScope, POINT16 pt, WND **ppWnd )
394 WND *wndPtr;
395 INT16 hittest = HTERROR;
396 INT16 retvalue;
397 POINT16 xy = pt;
399 *ppWnd = NULL;
400 wndPtr = WIN_LockWndPtr(wndScope->child);
402 if( wndScope->flags & WIN_MANAGED )
404 /* In managed mode we have to check wndScope first as it is also
405 * a window which received the mouse event. */
407 if( wndScope->dwStyle & WS_DISABLED )
409 retvalue = HTERROR;
410 goto end;
412 if( pt.x < wndScope->rectClient.left || pt.x >= wndScope->rectClient.right ||
413 pt.y < wndScope->rectClient.top || pt.y >= wndScope->rectClient.bottom )
414 goto hittest;
416 MapWindowPoints16( GetDesktopWindow16(), wndScope->hwndSelf, &xy, 1 );
418 for (;;)
420 while (wndPtr)
422 /* If point is in window, and window is visible, and it */
423 /* is enabled (or it's a top-level window), then explore */
424 /* its children. Otherwise, go to the next window. */
426 if ((wndPtr->dwStyle & WS_VISIBLE) &&
427 (!(wndPtr->dwStyle & WS_DISABLED) ||
428 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)) &&
429 (xy.x >= wndPtr->rectWindow.left) &&
430 (xy.x < wndPtr->rectWindow.right) &&
431 (xy.y >= wndPtr->rectWindow.top) &&
432 (xy.y < wndPtr->rectWindow.bottom))
434 *ppWnd = wndPtr; /* Got a suitable window */
436 /* If window is minimized or disabled, return at once */
437 if (wndPtr->dwStyle & WS_MINIMIZE)
439 retvalue = HTCAPTION;
440 goto end;
442 if (wndPtr->dwStyle & WS_DISABLED)
444 retvalue = HTERROR;
445 goto end;
448 /* If point is not in client area, ignore the children */
449 if ((xy.x < wndPtr->rectClient.left) ||
450 (xy.x >= wndPtr->rectClient.right) ||
451 (xy.y < wndPtr->rectClient.top) ||
452 (xy.y >= wndPtr->rectClient.bottom)) break;
454 xy.x -= wndPtr->rectClient.left;
455 xy.y -= wndPtr->rectClient.top;
456 WIN_UpdateWndPtr(&wndPtr,wndPtr->child);
458 else
460 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
464 hittest:
465 /* If nothing found, try the scope window */
466 if (!*ppWnd) *ppWnd = wndScope;
468 /* Send the WM_NCHITTEST message (only if to the same task) */
469 if ((*ppWnd)->hmemTaskQ == GetFastQueue16())
471 hittest = (INT16)SendMessage16( (*ppWnd)->hwndSelf, WM_NCHITTEST,
472 0, MAKELONG( pt.x, pt.y ) );
473 if (hittest != HTTRANSPARENT)
475 retvalue = hittest; /* Found the window */
476 goto end;
479 else
481 retvalue = HTCLIENT;
482 goto end;
485 /* If no children found in last search, make point relative to parent */
486 if (!wndPtr)
488 xy.x += (*ppWnd)->rectClient.left;
489 xy.y += (*ppWnd)->rectClient.top;
492 /* Restart the search from the next sibling */
493 WIN_UpdateWndPtr(&wndPtr,(*ppWnd)->next);
494 *ppWnd = (*ppWnd)->parent;
497 end:
498 WIN_ReleaseWndPtr(wndPtr);
499 return retvalue;
503 /*******************************************************************
504 * WindowFromPoint16 (USER.30)
506 HWND16 WINAPI WindowFromPoint16( POINT16 pt )
508 WND *pWnd;
509 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt, &pWnd );
510 WIN_ReleaseDesktop();
511 return pWnd->hwndSelf;
515 /*******************************************************************
516 * WindowFromPoint (USER32.582)
518 HWND WINAPI WindowFromPoint( POINT pt )
520 WND *pWnd;
521 POINT16 pt16;
522 CONV_POINT32TO16( &pt, &pt16 );
523 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16, &pWnd );
524 WIN_ReleaseDesktop();
525 return (HWND)pWnd->hwndSelf;
529 /*******************************************************************
530 * ChildWindowFromPoint16 (USER.191)
532 HWND16 WINAPI ChildWindowFromPoint16( HWND16 hwndParent, POINT16 pt )
534 POINT pt32;
535 CONV_POINT16TO32( &pt, &pt32 );
536 return (HWND16)ChildWindowFromPoint( hwndParent, pt32 );
540 /*******************************************************************
541 * ChildWindowFromPoint (USER32.49)
543 HWND WINAPI ChildWindowFromPoint( HWND hwndParent, POINT pt )
545 /* pt is in the client coordinates */
547 WND* wnd = WIN_FindWndPtr(hwndParent);
548 RECT rect;
549 HWND retvalue;
551 if( !wnd ) return 0;
553 /* get client rect fast */
554 rect.top = rect.left = 0;
555 rect.right = wnd->rectClient.right - wnd->rectClient.left;
556 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
558 if (!PtInRect( &rect, pt ))
560 retvalue = 0;
561 goto end;
563 WIN_UpdateWndPtr(&wnd,wnd->child);
564 while ( wnd )
566 if (PtInRect( &wnd->rectWindow, pt ))
568 retvalue = wnd->hwndSelf;
569 goto end;
571 WIN_UpdateWndPtr(&wnd,wnd->next);
573 retvalue = hwndParent;
574 end:
575 WIN_ReleaseWndPtr(wnd);
576 return retvalue;
579 /*******************************************************************
580 * ChildWindowFromPointEx16 (USER.50)
582 HWND16 WINAPI ChildWindowFromPointEx16( HWND16 hwndParent, POINT16 pt, UINT16 uFlags)
584 POINT pt32;
585 CONV_POINT16TO32( &pt, &pt32 );
586 return (HWND16)ChildWindowFromPointEx( hwndParent, pt32, uFlags );
590 /*******************************************************************
591 * ChildWindowFromPointEx32 (USER32.50)
593 HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt,
594 UINT uFlags)
596 /* pt is in the client coordinates */
598 WND* wnd = WIN_FindWndPtr(hwndParent);
599 RECT rect;
600 HWND retvalue;
602 if( !wnd ) return 0;
604 /* get client rect fast */
605 rect.top = rect.left = 0;
606 rect.right = wnd->rectClient.right - wnd->rectClient.left;
607 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
609 if (!PtInRect( &rect, pt ))
611 retvalue = 0;
612 goto end;
614 WIN_UpdateWndPtr(&wnd,wnd->child);
616 while ( wnd )
618 if (PtInRect( &wnd->rectWindow, pt )) {
619 if ( (uFlags & CWP_SKIPINVISIBLE) &&
620 !(wnd->dwStyle & WS_VISIBLE) );
621 else if ( (uFlags & CWP_SKIPDISABLED) &&
622 (wnd->dwStyle & WS_DISABLED) );
623 else if ( (uFlags & CWP_SKIPTRANSPARENT) &&
624 (wnd->dwExStyle & WS_EX_TRANSPARENT) );
625 else
627 retvalue = wnd->hwndSelf;
628 goto end;
630 WIN_UpdateWndPtr(&wnd,wnd->next);
634 retvalue = hwndParent;
635 end:
636 WIN_ReleaseWndPtr(wnd);
637 return retvalue;
641 /*******************************************************************
642 * WINPOS_GetWinOffset
644 * Calculate the offset between the origin of the two windows. Used
645 * to implement MapWindowPoints.
647 static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo,
648 POINT *offset )
650 WND * wndPtr = 0;
652 offset->x = offset->y = 0;
653 if (hwndFrom == hwndTo ) return;
655 /* Translate source window origin to screen coords */
656 if (hwndFrom)
658 if (!(wndPtr = WIN_FindWndPtr( hwndFrom )))
660 ERR(win,"bad hwndFrom = %04x\n",hwndFrom);
661 return;
663 while (wndPtr->parent)
665 offset->x += wndPtr->rectClient.left;
666 offset->y += wndPtr->rectClient.top;
667 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
669 WIN_ReleaseWndPtr(wndPtr);
672 /* Translate origin to destination window coords */
673 if (hwndTo)
675 if (!(wndPtr = WIN_FindWndPtr( hwndTo )))
677 ERR(win,"bad hwndTo = %04x\n", hwndTo );
678 return;
680 while (wndPtr->parent)
682 offset->x -= wndPtr->rectClient.left;
683 offset->y -= wndPtr->rectClient.top;
684 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
686 WIN_ReleaseWndPtr(wndPtr);
691 /*******************************************************************
692 * MapWindowPoints16 (USER.258)
694 void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
695 LPPOINT16 lppt, UINT16 count )
697 POINT offset;
699 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
700 while (count--)
702 lppt->x += offset.x;
703 lppt->y += offset.y;
704 lppt++;
709 /*******************************************************************
710 * MapWindowPoints (USER32.386)
712 INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo,
713 LPPOINT lppt, UINT count )
715 POINT offset;
717 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
718 while (count--)
720 lppt->x += offset.x;
721 lppt->y += offset.y;
722 lppt++;
724 return MAKELONG( LOWORD(offset.x), LOWORD(offset.y) );
728 /***********************************************************************
729 * IsIconic16 (USER.31)
731 BOOL16 WINAPI IsIconic16(HWND16 hWnd)
733 return IsIconic(hWnd);
737 /***********************************************************************
738 * IsIconic (USER32.345)
740 BOOL WINAPI IsIconic(HWND hWnd)
742 BOOL retvalue;
743 WND * wndPtr = WIN_FindWndPtr(hWnd);
744 if (wndPtr == NULL) return FALSE;
745 retvalue = (wndPtr->dwStyle & WS_MINIMIZE) != 0;
746 WIN_ReleaseWndPtr(wndPtr);
747 return retvalue;
751 /***********************************************************************
752 * IsZoomed (USER.272)
754 BOOL16 WINAPI IsZoomed16(HWND16 hWnd)
756 return IsZoomed(hWnd);
760 /***********************************************************************
761 * IsZoomed (USER.352)
763 BOOL WINAPI IsZoomed(HWND hWnd)
765 BOOL retvalue;
766 WND * wndPtr = WIN_FindWndPtr(hWnd);
767 if (wndPtr == NULL) return FALSE;
768 retvalue = (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
769 WIN_ReleaseWndPtr(wndPtr);
770 return retvalue;
774 /*******************************************************************
775 * GetActiveWindow (USER.60)
777 HWND16 WINAPI GetActiveWindow16(void)
779 return (HWND16)GetActiveWindow();
782 /*******************************************************************
783 * GetActiveWindow (USER32.205)
785 HWND WINAPI GetActiveWindow(void)
787 MESSAGEQUEUE *pCurMsgQ = 0;
788 HWND hwndActive = 0;
790 /* Get the messageQ for the current thread */
791 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
793 WARN( win, "\tCurrent message queue not found. Exiting!\n" );
794 return 0;
797 /* Return the current active window from the perQ data of the current message Q */
798 hwndActive = PERQDATA_GetActiveWnd( pCurMsgQ->pQData );
800 QUEUE_Unlock( pCurMsgQ );
801 return hwndActive;
805 /*******************************************************************
806 * WINPOS_CanActivate
808 static BOOL WINPOS_CanActivate(WND* pWnd)
810 if( pWnd && ((pWnd->dwStyle & (WS_DISABLED | WS_VISIBLE | WS_CHILD))
811 == WS_VISIBLE) ) return TRUE;
812 return FALSE;
816 /*******************************************************************
817 * SetActiveWindow16 (USER.59)
819 HWND16 WINAPI SetActiveWindow16( HWND16 hwnd )
821 return SetActiveWindow(hwnd);
825 /*******************************************************************
826 * SetActiveWindow (USER32.463)
828 HWND WINAPI SetActiveWindow( HWND hwnd )
830 HWND prev = 0;
831 WND *wndPtr = WIN_FindWndPtr( hwnd );
832 MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
834 if ( !WINPOS_CanActivate(wndPtr) )
836 prev = 0;
837 goto end;
840 /* Get the messageQ for the current thread */
841 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
843 WARN( win, "\tCurrent message queue not found. Exiting!\n" );
844 goto CLEANUP;
847 /* Retrieve the message queue associated with this window */
848 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
849 if ( !pMsgQ )
851 WARN( win, "\tWindow message queue not found. Exiting!\n" );
852 goto CLEANUP;
855 /* Make sure that the window is associated with the calling threads
856 * message queue. It must share the same perQ data.
859 if ( pCurMsgQ->pQData != pMsgQ->pQData )
860 goto CLEANUP;
862 /* Save current active window */
863 prev = PERQDATA_GetActiveWnd( pMsgQ->pQData );
865 WINPOS_SetActiveWindow( hwnd, 0, 0 );
867 CLEANUP:
868 /* Unlock the queues before returning */
869 if ( pMsgQ )
870 QUEUE_Unlock( pMsgQ );
871 if ( pCurMsgQ )
872 QUEUE_Unlock( pCurMsgQ );
874 end:
875 WIN_ReleaseWndPtr(wndPtr);
876 return prev;
880 /*******************************************************************
881 * GetForegroundWindow16 (USER.608)
883 HWND16 WINAPI GetForegroundWindow16(void)
885 return (HWND16)GetForegroundWindow();
889 /*******************************************************************
890 * SetForegroundWindow16 (USER.609)
892 BOOL16 WINAPI SetForegroundWindow16( HWND16 hwnd )
894 return SetForegroundWindow( hwnd );
898 /*******************************************************************
899 * GetForegroundWindow (USER32.241)
901 HWND WINAPI GetForegroundWindow(void)
903 return GetActiveWindow();
907 /*******************************************************************
908 * SetForegroundWindow (USER32.482)
910 BOOL WINAPI SetForegroundWindow( HWND hwnd )
912 SetActiveWindow( hwnd );
913 return TRUE;
917 /*******************************************************************
918 * GetShellWindow16 (USER.600)
920 HWND16 WINAPI GetShellWindow16(void)
922 return GetShellWindow();
925 /*******************************************************************
926 * SetShellWindow (USER32.504)
928 HWND WINAPI SetShellWindow(HWND hwndshell)
929 { WARN(win, "(hWnd=%08x) semi stub\n",hwndshell );
931 hGlobalShellWindow = hwndshell;
932 return hGlobalShellWindow;
936 /*******************************************************************
937 * GetShellWindow (USER32.287)
939 HWND WINAPI GetShellWindow(void)
940 { WARN(win, "(hWnd=%x) semi stub\n",hGlobalShellWindow );
942 return hGlobalShellWindow;
946 /***********************************************************************
947 * BringWindowToTop16 (USER.45)
949 BOOL16 WINAPI BringWindowToTop16( HWND16 hwnd )
951 return BringWindowToTop(hwnd);
955 /***********************************************************************
956 * BringWindowToTop (USER32.11)
958 BOOL WINAPI BringWindowToTop( HWND hwnd )
960 return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
964 /***********************************************************************
965 * MoveWindow16 (USER.56)
967 BOOL16 WINAPI MoveWindow16( HWND16 hwnd, INT16 x, INT16 y, INT16 cx, INT16 cy,
968 BOOL16 repaint )
970 return MoveWindow(hwnd,x,y,cx,cy,repaint);
974 /***********************************************************************
975 * MoveWindow (USER32.399)
977 BOOL WINAPI MoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy,
978 BOOL repaint )
980 int flags = SWP_NOZORDER | SWP_NOACTIVATE;
981 if (!repaint) flags |= SWP_NOREDRAW;
982 TRACE(win, "%04x %d,%d %dx%d %d\n",
983 hwnd, x, y, cx, cy, repaint );
984 return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
987 /***********************************************************************
988 * WINPOS_InitInternalPos
990 static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT pt,
991 LPRECT restoreRect )
993 LPINTERNALPOS lpPos = (LPINTERNALPOS) GetPropA( wnd->hwndSelf,
994 atomInternalPos );
995 if( !lpPos )
997 /* this happens when the window is minimized/maximized
998 * for the first time (rectWindow is not adjusted yet) */
1000 lpPos = HeapAlloc( SystemHeap, 0, sizeof(INTERNALPOS) );
1001 if( !lpPos ) return NULL;
1003 SetPropA( wnd->hwndSelf, atomInternalPos, (HANDLE)lpPos );
1004 lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
1005 CONV_RECT32TO16( &wnd->rectWindow, &lpPos->rectNormal );
1006 *(UINT*)&lpPos->ptIconPos = *(UINT*)&lpPos->ptMaxPos = 0xFFFFFFFF;
1009 if( wnd->dwStyle & WS_MINIMIZE )
1010 CONV_POINT32TO16( &pt, &lpPos->ptIconPos );
1011 else if( wnd->dwStyle & WS_MAXIMIZE )
1012 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1013 else if( restoreRect )
1014 CONV_RECT32TO16( restoreRect, &lpPos->rectNormal );
1016 return lpPos;
1019 /***********************************************************************
1020 * WINPOS_RedrawIconTitle
1022 BOOL WINPOS_RedrawIconTitle( HWND hWnd )
1024 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hWnd, atomInternalPos );
1025 if( lpPos )
1027 if( lpPos->hwndIconTitle )
1029 SendMessageA( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
1030 InvalidateRect( lpPos->hwndIconTitle, NULL, TRUE );
1031 return TRUE;
1034 return FALSE;
1037 /***********************************************************************
1038 * WINPOS_ShowIconTitle
1040 BOOL WINPOS_ShowIconTitle( WND* pWnd, BOOL bShow )
1042 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( pWnd->hwndSelf, atomInternalPos );
1044 if( lpPos && !(pWnd->flags & WIN_MANAGED))
1046 HWND16 hWnd = lpPos->hwndIconTitle;
1048 TRACE(win,"0x%04x %i\n", pWnd->hwndSelf, (bShow != 0) );
1050 if( !hWnd )
1051 lpPos->hwndIconTitle = hWnd = ICONTITLE_Create( pWnd );
1052 if( bShow )
1054 pWnd = WIN_FindWndPtr(hWnd);
1056 if( !(pWnd->dwStyle & WS_VISIBLE) )
1058 SendMessageA( hWnd, WM_SHOWWINDOW, TRUE, 0 );
1059 SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
1060 SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
1062 WIN_ReleaseWndPtr(pWnd);
1064 else ShowWindow( hWnd, SW_HIDE );
1066 return FALSE;
1069 /*******************************************************************
1070 * WINPOS_GetMinMaxInfo
1072 * Get the minimized and maximized information for a window.
1074 void WINPOS_GetMinMaxInfo( WND *wndPtr, POINT *maxSize, POINT *maxPos,
1075 POINT *minTrack, POINT *maxTrack )
1077 LPINTERNALPOS lpPos;
1078 MINMAXINFO MinMax;
1079 INT xinc, yinc;
1081 /* Compute default values */
1083 MinMax.ptMaxSize.x = SYSMETRICS_CXSCREEN;
1084 MinMax.ptMaxSize.y = SYSMETRICS_CYSCREEN;
1085 MinMax.ptMinTrackSize.x = SYSMETRICS_CXMINTRACK;
1086 MinMax.ptMinTrackSize.y = SYSMETRICS_CYMINTRACK;
1087 MinMax.ptMaxTrackSize.x = SYSMETRICS_CXSCREEN;
1088 MinMax.ptMaxTrackSize.y = SYSMETRICS_CYSCREEN;
1090 if (wndPtr->flags & WIN_MANAGED) xinc = yinc = 0;
1091 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1093 xinc = SYSMETRICS_CXDLGFRAME;
1094 yinc = SYSMETRICS_CYDLGFRAME;
1096 else
1098 xinc = yinc = 0;
1099 if (HAS_THICKFRAME(wndPtr->dwStyle))
1101 xinc += SYSMETRICS_CXFRAME;
1102 yinc += SYSMETRICS_CYFRAME;
1104 if (wndPtr->dwStyle & WS_BORDER)
1106 xinc += SYSMETRICS_CXBORDER;
1107 yinc += SYSMETRICS_CYBORDER;
1110 MinMax.ptMaxSize.x += 2 * xinc;
1111 MinMax.ptMaxSize.y += 2 * yinc;
1113 lpPos = (LPINTERNALPOS)GetPropA( wndPtr->hwndSelf, atomInternalPos );
1114 if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
1115 CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
1116 else
1118 MinMax.ptMaxPosition.x = -xinc;
1119 MinMax.ptMaxPosition.y = -yinc;
1122 SendMessageA( wndPtr->hwndSelf, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
1124 /* Some sanity checks */
1126 TRACE(win,"%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1127 MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
1128 MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
1129 MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
1130 MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
1131 MinMax.ptMaxTrackSize.x = MAX( MinMax.ptMaxTrackSize.x,
1132 MinMax.ptMinTrackSize.x );
1133 MinMax.ptMaxTrackSize.y = MAX( MinMax.ptMaxTrackSize.y,
1134 MinMax.ptMinTrackSize.y );
1136 if (maxSize) *maxSize = MinMax.ptMaxSize;
1137 if (maxPos) *maxPos = MinMax.ptMaxPosition;
1138 if (minTrack) *minTrack = MinMax.ptMinTrackSize;
1139 if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
1142 /***********************************************************************
1143 * WINPOS_MinMaximize
1145 * Fill in lpRect and return additional flags to be used with SetWindowPos().
1146 * This function assumes that 'cmd' is different from the current window
1147 * state.
1149 UINT WINPOS_MinMaximize( WND* wndPtr, UINT16 cmd, LPRECT16 lpRect )
1151 UINT swpFlags = 0;
1152 POINT pt, size;
1153 LPINTERNALPOS lpPos;
1155 TRACE(win,"0x%04x %u\n", wndPtr->hwndSelf, cmd );
1157 size.x = wndPtr->rectWindow.left; size.y = wndPtr->rectWindow.top;
1158 lpPos = WINPOS_InitInternalPos( wndPtr, size, &wndPtr->rectWindow );
1160 if (lpPos && !HOOK_CallHooks16(WH_CBT, HCBT_MINMAX, wndPtr->hwndSelf, cmd))
1162 if( wndPtr->dwStyle & WS_MINIMIZE )
1164 if( !SendMessageA( wndPtr->hwndSelf, WM_QUERYOPEN, 0, 0L ) )
1165 return (SWP_NOSIZE | SWP_NOMOVE);
1166 swpFlags |= SWP_NOCOPYBITS;
1168 switch( cmd )
1170 case SW_MINIMIZE:
1171 if( wndPtr->dwStyle & WS_MAXIMIZE)
1173 wndPtr->flags |= WIN_RESTORE_MAX;
1174 wndPtr->dwStyle &= ~WS_MAXIMIZE;
1176 else
1177 wndPtr->flags &= ~WIN_RESTORE_MAX;
1178 wndPtr->dwStyle |= WS_MINIMIZE;
1180 if( wndPtr->flags & WIN_NATIVE )
1181 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, TRUE ) )
1182 swpFlags |= MINMAX_NOSWP;
1184 lpPos->ptIconPos = WINPOS_FindIconPos( wndPtr, lpPos->ptIconPos );
1186 SetRect16( lpRect, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1187 SYSMETRICS_CXICON, SYSMETRICS_CYICON );
1188 swpFlags |= SWP_NOCOPYBITS;
1189 break;
1191 case SW_MAXIMIZE:
1192 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1193 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL );
1194 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1196 if( wndPtr->dwStyle & WS_MINIMIZE )
1198 if( wndPtr->flags & WIN_NATIVE )
1199 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
1200 swpFlags |= MINMAX_NOSWP;
1202 WINPOS_ShowIconTitle( wndPtr, FALSE );
1203 wndPtr->dwStyle &= ~WS_MINIMIZE;
1205 wndPtr->dwStyle |= WS_MAXIMIZE;
1207 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1208 size.x, size.y );
1209 break;
1211 case SW_RESTORE:
1212 if( wndPtr->dwStyle & WS_MINIMIZE )
1214 if( wndPtr->flags & WIN_NATIVE )
1215 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
1216 swpFlags |= MINMAX_NOSWP;
1218 wndPtr->dwStyle &= ~WS_MINIMIZE;
1219 WINPOS_ShowIconTitle( wndPtr, FALSE );
1221 if( wndPtr->flags & WIN_RESTORE_MAX)
1223 /* Restore to maximized position */
1224 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1225 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL);
1226 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1227 wndPtr->dwStyle |= WS_MAXIMIZE;
1228 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y, size.x, size.y );
1229 break;
1232 else
1233 if( !(wndPtr->dwStyle & WS_MAXIMIZE) ) return (UINT16)(-1);
1234 else wndPtr->dwStyle &= ~WS_MAXIMIZE;
1236 /* Restore to normal position */
1238 *lpRect = lpPos->rectNormal;
1239 lpRect->right -= lpRect->left;
1240 lpRect->bottom -= lpRect->top;
1242 break;
1244 } else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
1245 return swpFlags;
1248 /***********************************************************************
1249 * ShowWindowAsync (USER32.535)
1251 * doesn't wait; returns immediately.
1252 * used by threads to toggle windows in other (possibly hanging) threads
1254 BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd )
1256 /* FIXME: does ShowWindow() return immediately ? */
1257 return ShowWindow(hwnd, cmd);
1261 /***********************************************************************
1262 * ShowWindow16 (USER.42)
1264 BOOL16 WINAPI ShowWindow16( HWND16 hwnd, INT16 cmd )
1266 return ShowWindow(hwnd,cmd);
1270 /***********************************************************************
1271 * ShowWindow (USER32.534)
1273 BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
1275 WND* wndPtr = WIN_FindWndPtr( hwnd );
1276 BOOL wasVisible, showFlag;
1277 RECT16 newPos = {0, 0, 0, 0};
1278 UINT swp = 0;
1280 if (!wndPtr) return FALSE;
1282 TRACE(win,"hwnd=%04x, cmd=%d\n", hwnd, cmd);
1284 wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
1286 switch(cmd)
1288 case SW_HIDE:
1289 if (!wasVisible) goto END;;
1290 swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
1291 SWP_NOACTIVATE | SWP_NOZORDER;
1292 if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus()))
1294 /* Revert focus to parent */
1295 SetFocus( GetParent(hwnd) );
1297 break;
1299 case SW_SHOWMINNOACTIVE:
1300 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1301 /* fall through */
1302 case SW_SHOWMINIMIZED:
1303 swp |= SWP_SHOWWINDOW;
1304 /* fall through */
1305 case SW_MINIMIZE:
1306 swp |= SWP_FRAMECHANGED;
1307 if( !(wndPtr->dwStyle & WS_MINIMIZE) )
1308 swp |= WINPOS_MinMaximize( wndPtr, SW_MINIMIZE, &newPos );
1309 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1310 break;
1312 case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
1313 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1314 if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
1315 swp |= WINPOS_MinMaximize( wndPtr, SW_MAXIMIZE, &newPos );
1316 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1317 break;
1319 case SW_SHOWNA:
1320 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1321 /* fall through */
1322 case SW_SHOW:
1323 swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
1324 break;
1326 case SW_SHOWNOACTIVATE:
1327 swp |= SWP_NOZORDER;
1328 if (GetActiveWindow()) swp |= SWP_NOACTIVATE;
1329 /* fall through */
1330 case SW_SHOWNORMAL: /* same as SW_NORMAL: */
1331 case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
1332 case SW_RESTORE:
1333 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1335 if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) )
1336 swp |= WINPOS_MinMaximize( wndPtr, SW_RESTORE, &newPos );
1337 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1338 break;
1341 showFlag = (cmd != SW_HIDE);
1342 if (showFlag != wasVisible)
1344 SendMessageA( hwnd, WM_SHOWWINDOW, showFlag, 0 );
1345 if (!IsWindow( hwnd )) goto END;
1348 if ((wndPtr->dwStyle & WS_CHILD) &&
1349 !IsWindowVisible( wndPtr->parent->hwndSelf ) &&
1350 (swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE) )
1352 /* Don't call SetWindowPos() on invisible child windows */
1353 if (cmd == SW_HIDE) wndPtr->dwStyle &= ~WS_VISIBLE;
1354 else wndPtr->dwStyle |= WS_VISIBLE;
1356 else
1358 /* We can't activate a child window */
1359 if (wndPtr->dwStyle & WS_CHILD) swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1360 if (!(swp & MINMAX_NOSWP))
1361 SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top,
1362 newPos.right, newPos.bottom, LOWORD(swp) );
1363 if (!IsWindow( hwnd )) goto END;
1364 else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( wndPtr, TRUE );
1367 if (wndPtr->flags & WIN_NEED_SIZE)
1369 /* should happen only in CreateWindowEx() */
1370 int wParam = SIZE_RESTORED;
1372 wndPtr->flags &= ~WIN_NEED_SIZE;
1373 if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
1374 else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
1375 SendMessageA( hwnd, WM_SIZE, wParam,
1376 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
1377 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
1378 SendMessageA( hwnd, WM_MOVE, 0,
1379 MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
1382 END:
1383 WIN_ReleaseWndPtr(wndPtr);
1384 return wasVisible;
1388 /***********************************************************************
1389 * GetInternalWindowPos16 (USER.460)
1391 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
1392 LPPOINT16 ptIcon )
1394 WINDOWPLACEMENT16 wndpl;
1395 if (GetWindowPlacement16( hwnd, &wndpl ))
1397 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1398 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1399 return wndpl.showCmd;
1401 return 0;
1405 /***********************************************************************
1406 * GetInternalWindowPos (USER32.245)
1408 UINT WINAPI GetInternalWindowPos( HWND hwnd, LPRECT rectWnd,
1409 LPPOINT ptIcon )
1411 WINDOWPLACEMENT wndpl;
1412 if (GetWindowPlacement( hwnd, &wndpl ))
1414 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1415 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1416 return wndpl.showCmd;
1418 return 0;
1421 /***********************************************************************
1422 * GetWindowPlacement16 (USER.370)
1424 BOOL16 WINAPI GetWindowPlacement16( HWND16 hwnd, WINDOWPLACEMENT16 *wndpl )
1426 WND *pWnd = WIN_FindWndPtr( hwnd );
1427 LPINTERNALPOS lpPos;
1429 if(!pWnd ) return FALSE;
1431 lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1432 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1433 wndpl->length = sizeof(*wndpl);
1434 if( pWnd->dwStyle & WS_MINIMIZE )
1435 wndpl->showCmd = SW_SHOWMINIMIZED;
1436 else
1437 wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE )
1438 ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
1439 if( pWnd->flags & WIN_RESTORE_MAX )
1440 wndpl->flags = WPF_RESTORETOMAXIMIZED;
1441 else
1442 wndpl->flags = 0;
1443 wndpl->ptMinPosition = lpPos->ptIconPos;
1444 wndpl->ptMaxPosition = lpPos->ptMaxPos;
1445 wndpl->rcNormalPosition = lpPos->rectNormal;
1447 WIN_ReleaseWndPtr(pWnd);
1448 return TRUE;
1452 /***********************************************************************
1453 * GetWindowPlacement (USER32.307)
1455 * Win95:
1456 * Fails if wndpl->length of Win95 (!) apps is invalid.
1458 BOOL WINAPI GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *pwpl32 )
1460 if( pwpl32 )
1462 WINDOWPLACEMENT16 wpl;
1463 wpl.length = sizeof(wpl);
1464 if( GetWindowPlacement16( hwnd, &wpl ) )
1466 pwpl32->length = sizeof(*pwpl32);
1467 pwpl32->flags = wpl.flags;
1468 pwpl32->showCmd = wpl.showCmd;
1469 CONV_POINT16TO32( &wpl.ptMinPosition, &pwpl32->ptMinPosition );
1470 CONV_POINT16TO32( &wpl.ptMaxPosition, &pwpl32->ptMaxPosition );
1471 CONV_RECT16TO32( &wpl.rcNormalPosition, &pwpl32->rcNormalPosition );
1472 return TRUE;
1475 return FALSE;
1479 /***********************************************************************
1480 * WINPOS_SetPlacement
1482 static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT16 *wndpl,
1483 UINT flags )
1485 WND *pWnd = WIN_FindWndPtr( hwnd );
1486 if( pWnd )
1488 LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1489 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1491 if( flags & PLACE_MIN ) lpPos->ptIconPos = wndpl->ptMinPosition;
1492 if( flags & PLACE_MAX ) lpPos->ptMaxPos = wndpl->ptMaxPosition;
1493 if( flags & PLACE_RECT) lpPos->rectNormal = wndpl->rcNormalPosition;
1495 if( pWnd->dwStyle & WS_MINIMIZE )
1497 WINPOS_ShowIconTitle( pWnd, FALSE );
1498 if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1499 SetWindowPos( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1500 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1502 else if( pWnd->dwStyle & WS_MAXIMIZE )
1504 if( !EMPTYPOINT(lpPos->ptMaxPos) )
1505 SetWindowPos( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1506 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1508 else if( flags & PLACE_RECT )
1509 SetWindowPos( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1510 lpPos->rectNormal.right - lpPos->rectNormal.left,
1511 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1512 SWP_NOZORDER | SWP_NOACTIVATE );
1514 ShowWindow( hwnd, wndpl->showCmd );
1515 if( IsWindow(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1517 if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd, TRUE );
1519 /* SDK: ...valid only the next time... */
1520 if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1522 WIN_ReleaseWndPtr(pWnd);
1523 return TRUE;
1525 return FALSE;
1529 /***********************************************************************
1530 * SetWindowPlacement16 (USER.371)
1532 BOOL16 WINAPI SetWindowPlacement16(HWND16 hwnd, const WINDOWPLACEMENT16 *wndpl)
1534 return WINPOS_SetPlacement( hwnd, wndpl,
1535 PLACE_MIN | PLACE_MAX | PLACE_RECT );
1538 /***********************************************************************
1539 * SetWindowPlacement (USER32.519)
1541 * Win95:
1542 * Fails if wndpl->length of Win95 (!) apps is invalid.
1544 BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *pwpl32 )
1546 if( pwpl32 )
1548 WINDOWPLACEMENT16 wpl;
1550 wpl.length = sizeof(WINDOWPLACEMENT16);
1551 wpl.flags = pwpl32->flags;
1552 wpl.showCmd = pwpl32->showCmd;
1553 wpl.ptMinPosition.x = pwpl32->ptMinPosition.x;
1554 wpl.ptMinPosition.y = pwpl32->ptMinPosition.y;
1555 wpl.ptMaxPosition.x = pwpl32->ptMaxPosition.x;
1556 wpl.ptMaxPosition.y = pwpl32->ptMaxPosition.y;
1557 wpl.rcNormalPosition.left = pwpl32->rcNormalPosition.left;
1558 wpl.rcNormalPosition.top = pwpl32->rcNormalPosition.top;
1559 wpl.rcNormalPosition.right = pwpl32->rcNormalPosition.right;
1560 wpl.rcNormalPosition.bottom = pwpl32->rcNormalPosition.bottom;
1562 return WINPOS_SetPlacement( hwnd, &wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1564 return FALSE;
1568 /***********************************************************************
1569 * SetInternalWindowPos16 (USER.461)
1571 void WINAPI SetInternalWindowPos16( HWND16 hwnd, UINT16 showCmd,
1572 LPRECT16 rect, LPPOINT16 pt )
1574 if( IsWindow16(hwnd) )
1576 WINDOWPLACEMENT16 wndpl;
1577 UINT flags;
1579 wndpl.length = sizeof(wndpl);
1580 wndpl.showCmd = showCmd;
1581 wndpl.flags = flags = 0;
1583 if( pt )
1585 flags |= PLACE_MIN;
1586 wndpl.flags |= WPF_SETMINPOSITION;
1587 wndpl.ptMinPosition = *pt;
1589 if( rect )
1591 flags |= PLACE_RECT;
1592 wndpl.rcNormalPosition = *rect;
1594 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1599 /***********************************************************************
1600 * SetInternalWindowPos (USER32.483)
1602 void WINAPI SetInternalWindowPos( HWND hwnd, UINT showCmd,
1603 LPRECT rect, LPPOINT pt )
1605 if( IsWindow(hwnd) )
1607 WINDOWPLACEMENT16 wndpl;
1608 UINT flags;
1610 wndpl.length = sizeof(wndpl);
1611 wndpl.showCmd = showCmd;
1612 wndpl.flags = flags = 0;
1614 if( pt )
1616 flags |= PLACE_MIN;
1617 wndpl.flags |= WPF_SETMINPOSITION;
1618 CONV_POINT32TO16( pt, &wndpl.ptMinPosition );
1620 if( rect )
1622 flags |= PLACE_RECT;
1623 CONV_RECT32TO16( rect, &wndpl.rcNormalPosition );
1625 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1629 /*******************************************************************
1630 * WINPOS_SetActiveWindow
1632 * SetActiveWindow() back-end. This is the only function that
1633 * can assign active status to a window. It must be called only
1634 * for the top level windows.
1636 BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
1638 CBTACTIVATESTRUCT16* cbtStruct;
1639 WND* wndPtr=0, *wndTemp;
1640 HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1641 MESSAGEQUEUE *pOldActiveQueue = 0, *pNewActiveQueue = 0;
1642 WORD wIconized = 0;
1643 HWND hwndActive = 0;
1644 BOOL bRet = 0;
1646 /* Get current active window from the active queue */
1647 if ( hActiveQueue )
1649 pOldActiveQueue = QUEUE_Lock( hActiveQueue );
1650 if ( pOldActiveQueue )
1651 hwndActive = PERQDATA_GetActiveWnd( pOldActiveQueue->pQData );
1654 /* paranoid checks */
1655 if( hWnd == GetDesktopWindow() || (bRet = (hWnd == hwndActive)) )
1656 goto CLEANUP_END;
1658 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1659 * return 0;
1661 wndPtr = WIN_FindWndPtr(hWnd);
1662 hOldActiveQueue = hActiveQueue;
1664 if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1666 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1667 WIN_ReleaseWndPtr(wndTemp);
1669 else
1670 TRACE(win,"no current active window.\n");
1672 /* call CBT hook chain */
1673 if ((cbtStruct = SEGPTR_NEW(CBTACTIVATESTRUCT16)))
1675 cbtStruct->fMouse = fMouse;
1676 cbtStruct->hWndActive = hwndActive;
1677 bRet = (BOOL)HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
1678 (LPARAM)SEGPTR_GET(cbtStruct) );
1679 SEGPTR_FREE(cbtStruct);
1680 if (bRet) goto CLEANUP_END;
1683 /* set prev active wnd to current active wnd and send notification */
1684 if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
1686 MESSAGEQUEUE *pTempActiveQueue = 0;
1688 if (!SendMessageA( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1690 if (GetSysModalWindow16() != hWnd)
1691 goto CLEANUP_END;
1692 /* disregard refusal if hWnd is sysmodal */
1695 SendMessageA( hwndPrevActive, WM_ACTIVATE,
1696 MAKEWPARAM( WA_INACTIVE, wIconized ),
1697 (LPARAM)hWnd );
1699 /* check if something happened during message processing
1700 * (global active queue may have changed)
1702 pTempActiveQueue = QUEUE_Lock( hActiveQueue );
1703 if(!pTempActiveQueue)
1704 goto CLEANUP_END;
1706 hwndActive = PERQDATA_GetActiveWnd( pTempActiveQueue->pQData );
1707 QUEUE_Unlock( pTempActiveQueue );
1708 if( hwndPrevActive != hwndActive )
1709 goto CLEANUP_END;
1712 /* Set new active window in the message queue */
1713 hwndActive = hWnd;
1714 if ( wndPtr )
1716 pNewActiveQueue = QUEUE_Lock( wndPtr->hmemTaskQ );
1717 if ( pNewActiveQueue )
1718 PERQDATA_SetActiveWnd( pNewActiveQueue->pQData, hwndActive );
1720 else /* have to do this or MDI frame activation goes to hell */
1721 if( pOldActiveQueue )
1722 PERQDATA_SetActiveWnd( pOldActiveQueue->pQData, 0 );
1724 /* send palette messages */
1725 if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1726 SendMessage16((HWND16)-1, WM_PALETTEISCHANGING, (WPARAM16)hWnd, 0L );
1728 /* if prev wnd is minimized redraw icon title */
1729 if( IsIconic( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1731 /* managed windows will get ConfigureNotify event */
1732 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->flags & WIN_MANAGED))
1734 /* check Z-order and bring hWnd to the top */
1735 for (wndTemp = WIN_LockWndPtr(WIN_GetDesktop()->child); wndTemp; WIN_UpdateWndPtr(&wndTemp,wndTemp->next))
1737 if (wndTemp->dwStyle & WS_VISIBLE) break;
1739 WIN_ReleaseDesktop();
1740 WIN_ReleaseWndPtr(wndTemp);
1742 if( wndTemp != wndPtr )
1743 SetWindowPos(hWnd, HWND_TOP, 0,0,0,0,
1744 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1745 if (!IsWindow(hWnd))
1746 goto CLEANUP;
1749 /* Get a handle to the new active queue */
1750 hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1752 /* send WM_ACTIVATEAPP if necessary */
1753 if (hOldActiveQueue != hNewActiveQueue)
1755 WND **list, **ppWnd;
1756 WND *pDesktop = WIN_GetDesktop();
1758 if ((list = WIN_BuildWinArray( pDesktop, 0, NULL )))
1760 for (ppWnd = list; *ppWnd; ppWnd++)
1762 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1764 if ((*ppWnd)->hmemTaskQ == hOldActiveQueue)
1765 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1766 0, QUEUE_GetQueueTask(hNewActiveQueue) );
1768 WIN_ReleaseWinArray(list);
1771 hActiveQueue = hNewActiveQueue;
1773 if ((list = WIN_BuildWinArray(pDesktop, 0, NULL )))
1775 for (ppWnd = list; *ppWnd; ppWnd++)
1777 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1779 if ((*ppWnd)->hmemTaskQ == hNewActiveQueue)
1780 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1781 1, QUEUE_GetQueueTask( hOldActiveQueue ) );
1783 WIN_ReleaseWinArray(list);
1785 WIN_ReleaseDesktop();
1787 if (!IsWindow(hWnd)) goto CLEANUP;
1790 if (hWnd)
1792 /* walk up to the first unowned window */
1793 wndTemp = WIN_LockWndPtr(wndPtr);
1794 while (wndTemp->owner)
1796 WIN_UpdateWndPtr(&wndTemp,wndTemp->owner);
1798 /* and set last active owned popup */
1799 wndTemp->hwndLastActive = hWnd;
1801 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1802 WIN_ReleaseWndPtr(wndTemp);
1803 SendMessageA( hWnd, WM_NCACTIVATE, TRUE, 0 );
1804 SendMessageA( hWnd, WM_ACTIVATE,
1805 MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1806 (LPARAM)hwndPrevActive );
1807 if( !IsWindow(hWnd) ) goto CLEANUP;
1810 /* change focus if possible */
1811 if( fChangeFocus && GetFocus() )
1812 if( WIN_GetTopParent(GetFocus()) != hwndActive )
1813 FOCUS_SwitchFocus( pNewActiveQueue, GetFocus(),
1814 (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
1816 hwndActive
1819 if( !hwndPrevActive && wndPtr )
1820 (*wndPtr->pDriver->pForceWindowRaise)(wndPtr);
1822 /* if active wnd is minimized redraw icon title */
1823 if( IsIconic(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1825 bRet = (hWnd == hwndActive); /* Success? */
1827 CLEANUP: /* Unlock the message queues before returning */
1829 if ( pNewActiveQueue )
1830 QUEUE_Unlock( pNewActiveQueue );
1832 CLEANUP_END:
1834 if ( pOldActiveQueue )
1835 QUEUE_Unlock( pOldActiveQueue );
1837 WIN_ReleaseWndPtr(wndPtr);
1838 return bRet;
1841 /*******************************************************************
1842 * WINPOS_ActivateOtherWindow
1844 * Activates window other than pWnd.
1846 BOOL WINPOS_ActivateOtherWindow(WND* pWnd)
1848 BOOL bRet = 0;
1849 WND* pWndTo = NULL;
1850 HWND hwndActive = 0;
1852 /* Get current active window from the active queue */
1853 if ( hActiveQueue )
1855 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1856 if ( pActiveQueue )
1858 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1859 QUEUE_Unlock( pActiveQueue );
1863 if( pWnd->hwndSelf == hwndPrevActive )
1864 hwndPrevActive = 0;
1866 if( hwndActive != pWnd->hwndSelf &&
1867 ( hwndActive || QUEUE_IsExitingQueue(pWnd->hmemTaskQ)) )
1868 return 0;
1870 if( !(pWnd->dwStyle & WS_POPUP) || !(pWnd->owner) ||
1871 !WINPOS_CanActivate((pWndTo = WIN_GetTopParentPtr(pWnd->owner))) )
1873 WND* pWndPtr = WIN_GetTopParentPtr(pWnd);
1875 WIN_ReleaseWndPtr(pWndTo);
1876 pWndTo = WIN_FindWndPtr(hwndPrevActive);
1878 while( !WINPOS_CanActivate(pWndTo) )
1880 /* by now owned windows should've been taken care of */
1881 WIN_UpdateWndPtr(&pWndTo,pWndPtr->next);
1882 WIN_UpdateWndPtr(&pWndPtr,pWndTo);
1883 if( !pWndTo ) break;
1885 WIN_ReleaseWndPtr(pWndPtr);
1888 bRet = WINPOS_SetActiveWindow( pWndTo ? pWndTo->hwndSelf : 0, FALSE, TRUE );
1890 /* switch desktop queue to current active */
1891 if( pWndTo )
1893 WIN_GetDesktop()->hmemTaskQ = pWndTo->hmemTaskQ;
1894 WIN_ReleaseWndPtr(pWndTo);
1895 WIN_ReleaseDesktop();
1898 hwndPrevActive = 0;
1899 return bRet;
1902 /*******************************************************************
1903 * WINPOS_ChangeActiveWindow
1906 BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
1908 WND *wndPtr, *wndTemp;
1909 BOOL retvalue;
1910 HWND hwndActive = 0;
1912 /* Get current active window from the active queue */
1913 if ( hActiveQueue )
1915 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1916 if ( pActiveQueue )
1918 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1919 QUEUE_Unlock( pActiveQueue );
1923 if (!hWnd)
1924 return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
1926 wndPtr = WIN_FindWndPtr(hWnd);
1927 if( !wndPtr ) return FALSE;
1929 /* child windows get WM_CHILDACTIVATE message */
1930 if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
1932 retvalue = SendMessageA(hWnd, WM_CHILDACTIVATE, 0, 0L);
1933 goto end;
1936 if( hWnd == hwndActive )
1938 retvalue = FALSE;
1939 goto end;
1942 if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
1944 retvalue = FALSE;
1945 goto end;
1948 /* switch desktop queue to current active */
1949 wndTemp = WIN_GetDesktop();
1950 if( wndPtr->parent == wndTemp)
1951 wndTemp->hmemTaskQ = wndPtr->hmemTaskQ;
1952 WIN_ReleaseDesktop();
1954 retvalue = TRUE;
1955 end:
1956 WIN_ReleaseWndPtr(wndPtr);
1957 return retvalue;
1961 /***********************************************************************
1962 * WINPOS_SendNCCalcSize
1964 * Send a WM_NCCALCSIZE message to a window.
1965 * All parameters are read-only except newClientRect.
1966 * oldWindowRect, oldClientRect and winpos must be non-NULL only
1967 * when calcValidRect is TRUE.
1969 LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect,
1970 RECT *newWindowRect, RECT *oldWindowRect,
1971 RECT *oldClientRect, WINDOWPOS *winpos,
1972 RECT *newClientRect )
1974 NCCALCSIZE_PARAMS params;
1975 WINDOWPOS winposCopy;
1976 LONG result;
1978 params.rgrc[0] = *newWindowRect;
1979 if (calcValidRect)
1981 winposCopy = *winpos;
1982 params.rgrc[1] = *oldWindowRect;
1983 params.rgrc[2] = *oldClientRect;
1984 params.lppos = &winposCopy;
1986 result = SendMessageA( hwnd, WM_NCCALCSIZE, calcValidRect,
1987 (LPARAM)&params );
1988 TRACE(win, "%d,%d-%d,%d\n",
1989 params.rgrc[0].left, params.rgrc[0].top,
1990 params.rgrc[0].right, params.rgrc[0].bottom );
1991 *newClientRect = params.rgrc[0];
1992 return result;
1996 /***********************************************************************
1997 * WINPOS_HandleWindowPosChanging16
1999 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2001 LONG WINPOS_HandleWindowPosChanging16( WND *wndPtr, WINDOWPOS16 *winpos )
2003 POINT maxSize, minTrack;
2004 if (winpos->flags & SWP_NOSIZE) return 0;
2005 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2006 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2008 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
2009 if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
2010 if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
2011 if (!(wndPtr->dwStyle & WS_MINIMIZE))
2013 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
2014 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
2017 return 0;
2021 /***********************************************************************
2022 * WINPOS_HandleWindowPosChanging
2024 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2026 LONG WINPOS_HandleWindowPosChanging( WND *wndPtr, WINDOWPOS *winpos )
2028 POINT maxSize;
2029 if (winpos->flags & SWP_NOSIZE) return 0;
2030 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2031 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2033 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, NULL, NULL );
2034 winpos->cx = MIN( winpos->cx, maxSize.x );
2035 winpos->cy = MIN( winpos->cy, maxSize.y );
2037 return 0;
2040 /***********************************************************************
2041 * SWP_DoOwnedPopups
2043 * fix Z order taking into account owned popups -
2044 * basically we need to maintain them above the window that owns them
2046 * FIXME: hide/show owned popups when owner visibility changes.
2048 static HWND SWP_DoOwnedPopups(WND* pDesktop, WND* wndPtr, HWND hwndInsertAfter, WORD flags)
2050 WND* w = WIN_LockWndPtr(pDesktop->child);
2052 WARN(win, "(%04x) hInsertAfter = %04x\n", wndPtr->hwndSelf, hwndInsertAfter );
2054 if( (wndPtr->dwStyle & WS_POPUP) && wndPtr->owner )
2056 /* make sure this popup stays above the owner */
2058 HWND hwndLocalPrev = HWND_TOP;
2060 if( hwndInsertAfter != HWND_TOP )
2062 while( w != wndPtr->owner )
2064 if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
2065 if( hwndLocalPrev == hwndInsertAfter ) break;
2066 WIN_UpdateWndPtr(&w,w->next);
2068 hwndInsertAfter = hwndLocalPrev;
2071 else if( wndPtr->dwStyle & WS_CHILD )
2072 goto END;
2074 WIN_UpdateWndPtr(&w, pDesktop->child);
2076 while( w )
2078 if( w == wndPtr ) break;
2080 if( (w->dwStyle & WS_POPUP) && w->owner == wndPtr )
2082 SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0,
2083 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
2084 hwndInsertAfter = w->hwndSelf;
2086 WIN_UpdateWndPtr(&w, w->next);
2089 END:
2090 WIN_ReleaseWndPtr(w);
2091 return hwndInsertAfter;
2094 /***********************************************************************
2095 * SWP_CopyValidBits
2097 * Make window look nice without excessive repainting
2099 * visible and update regions are in window coordinates
2100 * client and window rectangles are in parent client coordinates
2102 * FIXME: SWP_EX_PAINTSELF in uFlags works only if both old and new
2103 * window rects have the same origin.
2105 * Returns: uFlags and a dirty region in *pVisRgn.
2107 static UINT SWP_CopyValidBits( WND* Wnd, HRGN* pVisRgn,
2108 LPRECT lpOldWndRect,
2109 LPRECT lpOldClientRect, UINT uFlags )
2111 RECT r;
2112 HRGN newVisRgn, dirtyRgn;
2113 INT my = COMPLEXREGION;
2115 TRACE(win,"\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2116 Wnd->rectWindow.left, Wnd->rectWindow.top,
2117 Wnd->rectWindow.right, Wnd->rectWindow.bottom,
2118 lpOldWndRect->left, lpOldWndRect->top,
2119 lpOldWndRect->right, lpOldWndRect->bottom, *pVisRgn);
2120 TRACE(win,"\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2121 Wnd->rectClient.left, Wnd->rectClient.top,
2122 Wnd->rectClient.right, Wnd->rectClient.bottom,
2123 lpOldClientRect->left, lpOldClientRect->top,
2124 lpOldClientRect->right,lpOldClientRect->bottom );
2126 if( Wnd->hrgnUpdate == 1 )
2127 uFlags |= SWP_EX_NOCOPY; /* whole window is invalid, nothing to copy */
2129 newVisRgn = DCE_GetVisRgn( Wnd->hwndSelf, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
2130 dirtyRgn = CreateRectRgn( 0, 0, 0, 0 );
2132 if( !(uFlags & SWP_EX_NOCOPY) ) /* make sure dst region covers only valid bits */
2133 my = CombineRgn( dirtyRgn, newVisRgn, *pVisRgn, RGN_AND );
2135 if( (my == NULLREGION) || (uFlags & SWP_EX_NOCOPY) )
2137 nocopy:
2139 TRACE(win,"\twon't copy anything!\n");
2141 /* set dirtyRgn to the sum of old and new visible regions
2142 * in parent client coordinates */
2144 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2145 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2147 CombineRgn(*pVisRgn, *pVisRgn, newVisRgn, RGN_OR );
2149 else /* copy valid bits to a new location */
2151 INT dx, dy, ow, oh, nw, nh, ocw, ncw, och, nch;
2152 HRGN hrgnValid = dirtyRgn; /* non-empty intersection of old and new visible rgns */
2154 /* subtract already invalid region inside Wnd from the dst region */
2156 if( Wnd->hrgnUpdate )
2157 if( CombineRgn( hrgnValid, hrgnValid, Wnd->hrgnUpdate, RGN_DIFF) == NULLREGION )
2158 goto nocopy;
2160 /* check if entire window can be copied */
2162 ow = lpOldWndRect->right - lpOldWndRect->left;
2163 oh = lpOldWndRect->bottom - lpOldWndRect->top;
2164 nw = Wnd->rectWindow.right - Wnd->rectWindow.left;
2165 nh = Wnd->rectWindow.bottom - Wnd->rectWindow.top;
2167 ocw = lpOldClientRect->right - lpOldClientRect->left;
2168 och = lpOldClientRect->bottom - lpOldClientRect->top;
2169 ncw = Wnd->rectClient.right - Wnd->rectClient.left;
2170 nch = Wnd->rectClient.bottom - Wnd->rectClient.top;
2172 if( (ocw != ncw) || (och != nch) ||
2173 ( ow != nw) || ( oh != nh) ||
2174 ((lpOldClientRect->top - lpOldWndRect->top) !=
2175 (Wnd->rectClient.top - Wnd->rectWindow.top)) ||
2176 ((lpOldClientRect->left - lpOldWndRect->left) !=
2177 (Wnd->rectClient.left - Wnd->rectWindow.left)) )
2179 dx = Wnd->rectClient.left - lpOldClientRect->left;
2180 dy = Wnd->rectClient.top - lpOldClientRect->top;
2182 /* restrict valid bits to the common client rect */
2184 r.left = Wnd->rectClient.left - Wnd->rectWindow.left;
2185 r.top = Wnd->rectClient.top - Wnd->rectWindow.top;
2186 r.right = r.left + MIN( ocw, ncw );
2187 r.bottom = r.top + MIN( och, nch );
2189 REGION_CropRgn( hrgnValid, hrgnValid, &r,
2190 (uFlags & SWP_EX_PAINTSELF) ? NULL : (POINT*)&(Wnd->rectWindow));
2191 GetRgnBox( hrgnValid, &r );
2192 if( IsRectEmpty( &r ) )
2193 goto nocopy;
2194 r = *lpOldClientRect;
2196 else
2198 dx = Wnd->rectWindow.left - lpOldWndRect->left;
2199 dy = Wnd->rectWindow.top - lpOldWndRect->top;
2200 if( !(uFlags & SWP_EX_PAINTSELF) )
2201 OffsetRgn( hrgnValid, Wnd->rectWindow.left, Wnd->rectWindow.top );
2202 r = *lpOldWndRect;
2205 if( !(uFlags & SWP_EX_PAINTSELF) )
2207 /* Move remaining regions to parent coordinates */
2208 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2209 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2211 else
2212 OffsetRect( &r, -lpOldWndRect->left, -lpOldWndRect->top );
2214 TRACE(win,"\tcomputing dirty region!\n");
2216 /* Compute combined dirty region (old + new - valid) */
2217 CombineRgn( *pVisRgn, *pVisRgn, newVisRgn, RGN_OR);
2218 CombineRgn( *pVisRgn, *pVisRgn, hrgnValid, RGN_DIFF);
2220 /* Blt valid bits, r is the rect to copy */
2222 if( dx || dy )
2224 RECT rClip;
2225 HDC hDC;
2226 DC* dc;
2228 /* get DC and clip rect with drawable rect to avoid superfluous expose events
2229 from copying clipped areas */
2231 if( uFlags & SWP_EX_PAINTSELF )
2233 hDC = GetDCEx( Wnd->hwndSelf, hrgnValid, DCX_WINDOW | DCX_CACHE |
2234 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2235 rClip.right = nw; rClip.bottom = nh;
2237 else
2239 hDC = GetDCEx( Wnd->parent->hwndSelf, hrgnValid, DCX_CACHE |
2240 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2241 rClip.right = Wnd->parent->rectClient.right - Wnd->parent->rectClient.left;
2242 rClip.bottom = Wnd->parent->rectClient.bottom - Wnd->parent->rectClient.top;
2244 rClip.left = rClip.top = 0;
2246 if( (dc = (DC *)GDI_GetObjPtr(hDC, DC_MAGIC)) )
2248 if( oh > nh ) r.bottom = r.top + nh;
2249 if( ow < nw ) r.right = r.left + nw;
2251 if( IntersectRect( &r, &r, &rClip ) )
2252 Wnd->pDriver->pSurfaceCopy( Wnd->parent, dc, dx, dy, &r, TRUE );
2254 GDI_HEAP_UNLOCK( hDC );
2256 ReleaseDC( (uFlags & SWP_EX_PAINTSELF) ?
2257 Wnd->hwndSelf : Wnd->parent->hwndSelf, hDC);
2261 /* *pVisRgn now points to the invalidated region */
2263 DeleteObject(newVisRgn);
2264 DeleteObject(dirtyRgn);
2265 return uFlags;
2268 /***********************************************************************
2269 * SWP_DoSimpleFrameChanged
2271 * NOTE: old and new client rect origins are identical, only
2272 * extents may have changed. Window extents are the same.
2274 static void SWP_DoSimpleFrameChanged( WND* wndPtr, RECT* pOldClientRect, WORD swpFlags, UINT uFlags )
2276 INT i = 0;
2277 RECT rect;
2278 HRGN hrgn = 0;
2280 if( !(swpFlags & SWP_NOCLIENTSIZE) )
2282 /* Client rect changed its position/size, most likely a scrollar
2283 * was added/removed.
2285 * FIXME: WVR alignment flags
2288 if( wndPtr->rectClient.right > pOldClientRect->right ) /* right edge */
2290 i++;
2291 rect.top = 0;
2292 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2293 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2294 if(!(uFlags & SWP_EX_NOCOPY))
2295 rect.left = pOldClientRect->right - wndPtr->rectClient.left;
2296 else
2298 rect.left = 0;
2299 goto redraw;
2303 if( wndPtr->rectClient.bottom > pOldClientRect->bottom ) /* bottom edge */
2305 if( i )
2306 hrgn = CreateRectRgnIndirect( &rect );
2307 rect.left = 0;
2308 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2309 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2310 if(!(uFlags & SWP_EX_NOCOPY))
2311 rect.top = pOldClientRect->bottom - wndPtr->rectClient.top;
2312 else
2313 rect.top = 0;
2314 if( i++ )
2315 REGION_UnionRectWithRgn( hrgn, &rect );
2318 if( i == 0 && (uFlags & SWP_EX_NOCOPY) ) /* force redraw anyway */
2320 rect = wndPtr->rectWindow;
2321 OffsetRect( &rect, wndPtr->rectWindow.left - wndPtr->rectClient.left,
2322 wndPtr->rectWindow.top - wndPtr->rectClient.top );
2323 i++;
2327 if( i )
2329 redraw:
2330 PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
2331 RDW_ERASENOW | RDW_ALLCHILDREN, RDW_EX_TOPFRAME | RDW_EX_USEHRGN );
2333 else
2335 WIN_UpdateNCRgn(wndPtr, 0, UNC_UPDATE | UNC_ENTIRE);
2338 if( hrgn > 1 )
2339 DeleteObject( hrgn );
2342 /***********************************************************************
2343 * SWP_DoWinPosChanging
2345 static BOOL SWP_DoWinPosChanging( WND* wndPtr, WINDOWPOS* pWinpos,
2346 RECT* pNewWindowRect, RECT* pNewClientRect )
2348 /* Send WM_WINDOWPOSCHANGING message */
2350 if (!(pWinpos->flags & SWP_NOSENDCHANGING))
2351 SendMessageA( wndPtr->hwndSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM)pWinpos );
2353 /* Calculate new position and size */
2355 *pNewWindowRect = wndPtr->rectWindow;
2356 *pNewClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
2357 : wndPtr->rectClient;
2359 if (!(pWinpos->flags & SWP_NOSIZE))
2361 pNewWindowRect->right = pNewWindowRect->left + pWinpos->cx;
2362 pNewWindowRect->bottom = pNewWindowRect->top + pWinpos->cy;
2364 if (!(pWinpos->flags & SWP_NOMOVE))
2366 pNewWindowRect->left = pWinpos->x;
2367 pNewWindowRect->top = pWinpos->y;
2368 pNewWindowRect->right += pWinpos->x - wndPtr->rectWindow.left;
2369 pNewWindowRect->bottom += pWinpos->y - wndPtr->rectWindow.top;
2371 OffsetRect( pNewClientRect, pWinpos->x - wndPtr->rectWindow.left,
2372 pWinpos->y - wndPtr->rectWindow.top );
2375 pWinpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
2376 return TRUE;
2379 /***********************************************************************
2380 * SWP_DoNCCalcSize
2382 static UINT SWP_DoNCCalcSize( WND* wndPtr, WINDOWPOS* pWinpos,
2383 RECT* pNewWindowRect, RECT* pNewClientRect, WORD f)
2385 UINT wvrFlags = 0;
2387 /* Send WM_NCCALCSIZE message to get new client area */
2388 if( (pWinpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
2390 wvrFlags = WINPOS_SendNCCalcSize( pWinpos->hwnd, TRUE, pNewWindowRect,
2391 &wndPtr->rectWindow, &wndPtr->rectClient,
2392 pWinpos, pNewClientRect );
2394 /* FIXME: WVR_ALIGNxxx */
2396 if( pNewClientRect->left != wndPtr->rectClient.left ||
2397 pNewClientRect->top != wndPtr->rectClient.top )
2398 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2400 if( (pNewClientRect->right - pNewClientRect->left !=
2401 wndPtr->rectClient.right - wndPtr->rectClient.left) ||
2402 (pNewClientRect->bottom - pNewClientRect->top !=
2403 wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
2404 pWinpos->flags &= ~SWP_NOCLIENTSIZE;
2406 else
2407 if( !(f & SWP_NOMOVE) && (pNewClientRect->left != wndPtr->rectClient.left ||
2408 pNewClientRect->top != wndPtr->rectClient.top) )
2409 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2410 return wvrFlags;
2413 /***********************************************************************
2414 * SetWindowPos (USER.2)
2416 BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
2417 INT16 x, INT16 y, INT16 cx, INT16 cy, WORD flags)
2419 return SetWindowPos(hwnd,(INT)(INT16)hwndInsertAfter,x,y,cx,cy,flags);
2422 /***********************************************************************
2423 * SetWindowPos (USER32.520)
2425 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
2426 INT x, INT y, INT cx, INT cy, WORD flags)
2428 WINDOWPOS winpos;
2429 WND * wndPtr,*wndTemp;
2430 RECT newWindowRect, newClientRect;
2431 RECT oldWindowRect, oldClientRect;
2432 HRGN visRgn = 0;
2433 UINT wvrFlags = 0, uFlags = 0;
2434 BOOL retvalue, resync = FALSE;
2435 HWND hwndActive = 0;
2437 /* Get current active window from the active queue */
2438 if ( hActiveQueue )
2440 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2441 if ( pActiveQueue )
2443 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2444 QUEUE_Unlock( pActiveQueue );
2448 TRACE(win,"hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2449 hwnd, x, y, x+cx, y+cy, flags);
2451 /* ------------------------------------------------------------------------ CHECKS */
2453 /* Check window handle */
2455 if (hwnd == GetDesktopWindow()) return FALSE;
2456 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2458 TRACE(win,"\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr->rectWindow.left, wndPtr->rectWindow.top,
2459 wndPtr->rectWindow.right, wndPtr->rectWindow.bottom, (unsigned)wndPtr->dwStyle );
2461 /* Fix redundant flags */
2463 if(wndPtr->dwStyle & WS_VISIBLE)
2464 flags &= ~SWP_SHOWWINDOW;
2465 else
2467 if (!(flags & SWP_SHOWWINDOW))
2468 flags |= SWP_NOREDRAW;
2469 flags &= ~SWP_HIDEWINDOW;
2472 if ( cx < 0 ) cx = 0; if( cy < 0 ) cy = 0;
2474 if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
2475 (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
2476 flags |= SWP_NOSIZE; /* Already the right size */
2478 if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
2479 flags |= SWP_NOMOVE; /* Already the right position */
2481 if (hwnd == hwndActive)
2482 flags |= SWP_NOACTIVATE; /* Already active */
2483 else
2485 if(!(flags & SWP_NOACTIVATE)) /* Bring to the top when activating */
2487 flags &= ~SWP_NOZORDER;
2488 hwndInsertAfter = HWND_TOP;
2489 goto Pos;
2493 /* Check hwndInsertAfter */
2495 /* FIXME: TOPMOST not supported yet */
2496 if ((hwndInsertAfter == HWND_TOPMOST) ||
2497 (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
2499 /* hwndInsertAfter must be a sibling of the window */
2500 if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
2502 WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
2504 if( wnd ) {
2505 if( wnd->parent != wndPtr->parent )
2507 retvalue = FALSE;
2508 WIN_ReleaseWndPtr(wnd);
2509 goto END;
2511 if( wnd->next == wndPtr ) flags |= SWP_NOZORDER;
2513 WIN_ReleaseWndPtr(wnd);
2516 Pos: /* ------------------------------------------------------------------------ MAIN part */
2518 /* Fill the WINDOWPOS structure */
2520 winpos.hwnd = hwnd;
2521 winpos.hwndInsertAfter = hwndInsertAfter;
2522 winpos.x = x;
2523 winpos.y = y;
2524 winpos.cx = cx;
2525 winpos.cy = cy;
2526 winpos.flags = flags;
2528 SWP_DoWinPosChanging( wndPtr, &winpos, &newWindowRect, &newClientRect );
2530 if((winpos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER)
2532 if( wndPtr->parent == WIN_GetDesktop() )
2533 hwndInsertAfter = SWP_DoOwnedPopups( wndPtr->parent, wndPtr,
2534 hwndInsertAfter, winpos.flags );
2535 WIN_ReleaseDesktop();
2538 if(!(wndPtr->flags & WIN_NATIVE) )
2540 if( hwndInsertAfter == HWND_TOP )
2541 winpos.flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
2542 else
2543 if( hwndInsertAfter == HWND_BOTTOM )
2544 winpos.flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
2545 else
2546 if( !(winpos.flags & SWP_NOZORDER) )
2547 if( GetWindow(hwndInsertAfter, GW_HWNDNEXT) == wndPtr->hwndSelf )
2548 winpos.flags |= SWP_NOZORDER;
2550 if( !(winpos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) &&
2551 ((winpos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW | SWP_FRAMECHANGED))
2552 != (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)) )
2554 /* get a previous visible region for SWP_CopyValidBits() */
2556 visRgn = DCE_GetVisRgn(hwnd, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
2560 /* Common operations */
2562 wvrFlags = SWP_DoNCCalcSize( wndPtr, &winpos, &newWindowRect, &newClientRect, flags );
2564 if(!(winpos.flags & SWP_NOZORDER))
2566 WIN_UnlinkWindow( winpos.hwnd );
2567 WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
2570 /* Reset active DCEs */
2572 if( (((winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) &&
2573 wndPtr->dwStyle & WS_VISIBLE) ||
2574 (flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
2576 RECT rect;
2578 UnionRect(&rect, &newWindowRect, &wndPtr->rectWindow);
2579 DCE_InvalidateDCE(wndPtr, &rect);
2582 oldWindowRect = wndPtr->rectWindow;
2583 oldClientRect = wndPtr->rectClient;
2585 /* Find out if we have to redraw the whole client rect */
2587 if( oldClientRect.bottom - oldClientRect.top ==
2588 newClientRect.bottom - newClientRect.top ) wvrFlags &= ~WVR_VREDRAW;
2590 if( oldClientRect.right - oldClientRect.left ==
2591 newClientRect.right - newClientRect.left ) wvrFlags &= ~WVR_HREDRAW;
2593 if( (winpos.flags & SWP_NOCOPYBITS) || (!(winpos.flags & SWP_NOCLIENTSIZE) &&
2594 (wvrFlags >= WVR_HREDRAW) && (wvrFlags < WVR_VALIDRECTS)) )
2596 uFlags |= SWP_EX_NOCOPY;
2599 * Use this later in CopyValidBits()
2601 else if( 0 )
2602 uFlags |= SWP_EX_NONCLIENT;
2605 /* FIXME: actually do something with WVR_VALIDRECTS */
2607 wndPtr->rectWindow = newWindowRect;
2608 wndPtr->rectClient = newClientRect;
2610 if (wndPtr->flags & WIN_NATIVE) /* -------------------------------------------- hosted window */
2612 BOOL bCallDriver = TRUE;
2613 HWND tempInsertAfter = winpos.hwndInsertAfter;
2615 winpos.hwndInsertAfter = hwndInsertAfter;
2617 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2619 /* This is the only place where we need to force repainting of the contents
2620 of windows created by the host window system, all other cases go through the
2621 expose event handling */
2623 if( (winpos.flags & (SWP_NOSIZE | SWP_FRAMECHANGED)) == (SWP_NOSIZE | SWP_FRAMECHANGED) )
2625 cx = newWindowRect.right - newWindowRect.left;
2626 cy = newWindowRect.bottom - newWindowRect.top;
2628 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, TRUE);
2629 winpos.hwndInsertAfter = tempInsertAfter;
2630 bCallDriver = FALSE;
2632 if( winpos.flags & SWP_NOCLIENTMOVE )
2633 SWP_DoSimpleFrameChanged(wndPtr, &oldClientRect, winpos.flags, uFlags );
2634 else
2636 /* client area moved but window extents remained the same, copy valid bits */
2638 visRgn = CreateRectRgn( 0, 0, cx, cy );
2639 uFlags = SWP_CopyValidBits( wndPtr, &visRgn, &oldWindowRect, &oldClientRect,
2640 uFlags | SWP_EX_PAINTSELF );
2645 if( bCallDriver )
2647 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2649 if( (oldClientRect.left - oldWindowRect.left == newClientRect.left - newWindowRect.left) &&
2650 (oldClientRect.top - oldWindowRect.top == newClientRect.top - newWindowRect.top) &&
2651 !(uFlags & SWP_EX_NOCOPY) )
2653 /* The origin of the client rect didn't move so we can try to repaint
2654 * only the nonclient area by setting bit gravity hint for the host window system.
2657 if( !(wndPtr->flags & WIN_MANAGED) )
2659 HRGN hrgn = CreateRectRgn( 0, 0, newWindowRect.right - newWindowRect.left,
2660 newWindowRect.bottom - newWindowRect.top);
2661 RECT rcn = newClientRect;
2662 RECT rco = oldClientRect;
2664 OffsetRect( &rcn, -newWindowRect.left, -newWindowRect.top );
2665 OffsetRect( &rco, -oldWindowRect.left, -oldWindowRect.top );
2666 IntersectRect( &rcn, &rcn, &rco );
2667 visRgn = CreateRectRgnIndirect( &rcn );
2668 CombineRgn( visRgn, hrgn, visRgn, RGN_DIFF );
2669 DeleteObject( hrgn );
2670 uFlags = SWP_EX_PAINTSELF;
2672 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGNorthWest );
2674 else
2675 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGForget );
2678 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, TRUE);
2679 winpos.hwndInsertAfter = tempInsertAfter;
2682 if( winpos.flags & SWP_SHOWWINDOW )
2684 HWND focus, curr;
2686 wndPtr->dwStyle |= WS_VISIBLE;
2688 if (wndPtr->flags & WIN_MANAGED) resync = TRUE;
2690 /* focus was set to unmapped window, reset host focus
2691 * since the window is now visible */
2693 focus = curr = GetFocus();
2694 while (curr)
2696 if (curr == hwnd)
2698 WND *pFocus = WIN_FindWndPtr( focus );
2699 if (pFocus)
2700 pFocus->pDriver->pSetFocus(pFocus);
2701 WIN_ReleaseWndPtr(pFocus);
2702 break;
2704 curr = GetParent(curr);
2708 else /* -------------------------------------------- emulated window */
2710 if( winpos.flags & SWP_SHOWWINDOW )
2712 wndPtr->dwStyle |= WS_VISIBLE;
2713 uFlags |= SWP_EX_PAINTSELF;
2714 visRgn = 1; /* redraw the whole window */
2716 else if( !(winpos.flags & SWP_NOREDRAW) )
2718 if( winpos.flags & SWP_HIDEWINDOW )
2720 if( visRgn > 1 ) /* map to parent */
2721 OffsetRgn( visRgn, oldWindowRect.left, oldWindowRect.top );
2722 else
2723 visRgn = 0;
2725 else
2727 if( (winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE )
2728 uFlags = SWP_CopyValidBits(wndPtr, &visRgn, &oldWindowRect,
2729 &oldClientRect, uFlags);
2730 else
2732 /* nothing moved, redraw frame if needed */
2734 if( winpos.flags & SWP_FRAMECHANGED )
2735 SWP_DoSimpleFrameChanged( wndPtr, &oldClientRect, winpos.flags, uFlags );
2736 if( visRgn )
2738 DeleteObject( visRgn );
2739 visRgn = 0;
2746 if( winpos.flags & SWP_HIDEWINDOW )
2748 wndPtr->dwStyle &= ~WS_VISIBLE;
2750 if (hwnd == CARET_GetHwnd()) DestroyCaret();
2752 /* FIXME: This will cause the window to be activated irrespective
2753 * of whether it is owned by the same thread. Has to be done
2754 * asynchronously.
2757 if (winpos.hwnd == hwndActive)
2758 WINPOS_ActivateOtherWindow( wndPtr );
2761 /* ------------------------------------------------------------------------ FINAL */
2763 if (wndPtr->flags & WIN_NATIVE)
2764 EVENT_Synchronize(); /* Synchronize with the host window system */
2766 if (!GetCapture() && ((wndPtr->dwStyle & WS_VISIBLE) || (flags & SWP_HIDEWINDOW)))
2767 EVENT_DummyMotionNotify(); /* Simulate a mouse event to set the cursor */
2769 wndTemp = WIN_GetDesktop();
2771 /* repaint invalidated region (if any)
2773 * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2774 * and force update after ChangeActiveWindow() to avoid painting frames twice.
2777 if( visRgn )
2779 if( !(winpos.flags & SWP_NOREDRAW) )
2781 if( uFlags & SWP_EX_PAINTSELF )
2783 PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn, RDW_ERASE | RDW_FRAME |
2784 ((winpos.flags & SWP_DEFERERASE) ? 0 : RDW_ERASENOW) | RDW_INVALIDATE |
2785 RDW_ALLCHILDREN, RDW_EX_XYWINDOW | RDW_EX_USEHRGN );
2787 else
2789 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn, RDW_ERASE |
2790 ((winpos.flags & SWP_DEFERERASE) ? 0 : RDW_ERASENOW) | RDW_INVALIDATE |
2791 RDW_ALLCHILDREN, RDW_EX_USEHRGN );
2794 if( visRgn != 1 )
2795 DeleteObject( visRgn );
2798 WIN_ReleaseDesktop();
2800 if (!(flags & SWP_NOACTIVATE))
2801 WINPOS_ChangeActiveWindow( winpos.hwnd, FALSE );
2803 /* And last, send the WM_WINDOWPOSCHANGED message */
2805 TRACE(win,"\tstatus flags = %04x\n", winpos.flags & SWP_AGG_STATUSFLAGS);
2807 if ( resync ||
2808 (((winpos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) &&
2809 !(winpos.flags & SWP_NOSENDCHANGING)) )
2811 SendMessageA( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
2812 if (resync) EVENT_Synchronize ();
2815 retvalue = TRUE;
2816 END:
2817 WIN_ReleaseWndPtr(wndPtr);
2818 return retvalue;
2822 /***********************************************************************
2823 * BeginDeferWindowPos16 (USER.259)
2825 HDWP16 WINAPI BeginDeferWindowPos16( INT16 count )
2827 return BeginDeferWindowPos( count );
2831 /***********************************************************************
2832 * BeginDeferWindowPos (USER32.9)
2834 HDWP WINAPI BeginDeferWindowPos( INT count )
2836 HDWP handle;
2837 DWP *pDWP;
2839 if (count <= 0) return 0;
2840 handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
2841 if (!handle) return 0;
2842 pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
2843 pDWP->actualCount = 0;
2844 pDWP->suggestedCount = count;
2845 pDWP->valid = TRUE;
2846 pDWP->wMagic = DWP_MAGIC;
2847 pDWP->hwndParent = 0;
2848 return handle;
2852 /***********************************************************************
2853 * DeferWindowPos16 (USER.260)
2855 HDWP16 WINAPI DeferWindowPos16( HDWP16 hdwp, HWND16 hwnd, HWND16 hwndAfter,
2856 INT16 x, INT16 y, INT16 cx, INT16 cy,
2857 UINT16 flags )
2859 return DeferWindowPos( hdwp, hwnd, (INT)(INT16)hwndAfter,
2860 x, y, cx, cy, flags );
2864 /***********************************************************************
2865 * DeferWindowPos (USER32.128)
2867 HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter,
2868 INT x, INT y, INT cx, INT cy,
2869 UINT flags )
2871 DWP *pDWP;
2872 int i;
2873 HDWP newhdwp = hdwp,retvalue;
2874 /* HWND parent; */
2875 WND *pWnd;
2877 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
2878 if (!pDWP) return 0;
2879 if (hwnd == GetDesktopWindow()) return 0;
2881 if (!(pWnd=WIN_FindWndPtr( hwnd ))) {
2882 USER_HEAP_FREE( hdwp );
2883 return 0;
2886 /* Numega Bounds Checker Demo dislikes the following code.
2887 In fact, I've not been able to find any "same parent" requirement in any docu
2888 [AM 980509]
2890 #if 0
2891 /* All the windows of a DeferWindowPos() must have the same parent */
2892 parent = pWnd->parent->hwndSelf;
2893 if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
2894 else if (parent != pDWP->hwndParent)
2896 USER_HEAP_FREE( hdwp );
2897 retvalue = 0;
2898 goto END;
2900 #endif
2902 for (i = 0; i < pDWP->actualCount; i++)
2904 if (pDWP->winPos[i].hwnd == hwnd)
2906 /* Merge with the other changes */
2907 if (!(flags & SWP_NOZORDER))
2909 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
2911 if (!(flags & SWP_NOMOVE))
2913 pDWP->winPos[i].x = x;
2914 pDWP->winPos[i].y = y;
2916 if (!(flags & SWP_NOSIZE))
2918 pDWP->winPos[i].cx = cx;
2919 pDWP->winPos[i].cy = cy;
2921 pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
2922 SWP_NOZORDER | SWP_NOREDRAW |
2923 SWP_NOACTIVATE | SWP_NOCOPYBITS|
2924 SWP_NOOWNERZORDER);
2925 pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
2926 SWP_FRAMECHANGED);
2927 retvalue = hdwp;
2928 goto END;
2931 if (pDWP->actualCount >= pDWP->suggestedCount)
2933 newhdwp = USER_HEAP_REALLOC( hdwp,
2934 sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
2935 if (!newhdwp)
2937 retvalue = 0;
2938 goto END;
2940 pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
2941 pDWP->suggestedCount++;
2943 pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
2944 pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
2945 pDWP->winPos[pDWP->actualCount].x = x;
2946 pDWP->winPos[pDWP->actualCount].y = y;
2947 pDWP->winPos[pDWP->actualCount].cx = cx;
2948 pDWP->winPos[pDWP->actualCount].cy = cy;
2949 pDWP->winPos[pDWP->actualCount].flags = flags;
2950 pDWP->actualCount++;
2951 retvalue = newhdwp;
2952 END:
2953 WIN_ReleaseWndPtr(pWnd);
2954 return retvalue;
2958 /***********************************************************************
2959 * EndDeferWindowPos16 (USER.261)
2961 BOOL16 WINAPI EndDeferWindowPos16( HDWP16 hdwp )
2963 return EndDeferWindowPos( hdwp );
2967 /***********************************************************************
2968 * EndDeferWindowPos (USER32.173)
2970 BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
2972 DWP *pDWP;
2973 WINDOWPOS *winpos;
2974 BOOL res = TRUE;
2975 int i;
2977 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
2978 if (!pDWP) return FALSE;
2979 for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
2981 if (!(res = SetWindowPos( winpos->hwnd, winpos->hwndInsertAfter,
2982 winpos->x, winpos->y, winpos->cx,
2983 winpos->cy, winpos->flags ))) break;
2985 USER_HEAP_FREE( hdwp );
2986 return res;
2990 /***********************************************************************
2991 * TileChildWindows (USER.199)
2993 void WINAPI TileChildWindows16( HWND16 parent, WORD action )
2995 FIXME(win, "(%04x, %d): stub\n", parent, action);
2998 /***********************************************************************
2999 * CascageChildWindows (USER.198)
3001 void WINAPI CascadeChildWindows16( HWND16 parent, WORD action )
3003 FIXME(win, "(%04x, %d): stub\n", parent, action);
3006 /***********************************************************************
3007 * SetProgmanWindow [USER32.522]
3009 HRESULT WINAPI SetProgmanWindow ( HWND hwnd )
3011 hGlobalProgmanWindow = hwnd;
3012 return hGlobalProgmanWindow;
3015 /***********************************************************************
3016 * GetProgmanWindow [USER32.289]
3018 HRESULT WINAPI GetProgmanWindow ( )
3020 return hGlobalProgmanWindow;
3023 /***********************************************************************
3024 * SetShellWindowEx [USER32.531]
3025 * hwndProgman = Progman[Program Manager]
3026 * |-> SHELLDLL_DefView
3027 * hwndListView = | |-> SysListView32
3028 * | | |-> tooltips_class32
3029 * | |
3030 * | |-> SysHeader32
3031 * |
3032 * |-> ProxyTarget
3034 HRESULT WINAPI SetShellWindowEx ( HWND hwndProgman, HWND hwndListView )
3036 FIXME(win,"0x%08x 0x%08x stub\n",hwndProgman ,hwndListView );
3037 hGlobalShellWindow = hwndProgman;
3038 return hGlobalShellWindow;
3042 /***********************************************************************
3043 * SetTaskmanWindow [USER32.537]
3044 * NOTES
3045 * hwnd = MSTaskSwWClass
3046 * |-> SysTabControl32
3048 HRESULT WINAPI SetTaskmanWindow ( HWND hwnd )
3050 hGlobalTaskmanWindow = hwnd;
3051 return hGlobalTaskmanWindow;
3054 /***********************************************************************
3055 * GetTaskmanWindow [USER32.304]
3057 HRESULT WINAPI GetTaskmanWindow ( )
3059 return hGlobalTaskmanWindow;