Stubs for CloseDesktop and CloseWindowStation.
[wine/wine-kai.git] / windows / winpos.c
blobd98a4d7d0283fc4df1d6dfad1d556d5f14dbfe4e
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 #define HAS_DLGFRAME(style,exStyle) \
28 (((exStyle) & WS_EX_DLGMODALFRAME) || \
29 (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
31 #define HAS_THICKFRAME(style) \
32 (((style) & WS_THICKFRAME) && \
33 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
35 #define SWP_AGG_NOGEOMETRYCHANGE \
36 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
37 #define SWP_AGG_NOPOSCHANGE \
38 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
39 #define SWP_AGG_STATUSFLAGS \
40 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
42 #define EMPTYPOINT(pt) ((*(LONG*)&(pt)) == -1)
44 #define PLACE_MIN 0x0001
45 #define PLACE_MAX 0x0002
46 #define PLACE_RECT 0x0004
48 #define SWP_EX_NOCOPY 0x0001
49 #define SWP_EX_PAINTSELF 0x0002
51 #define MINMAX_NOSWP 0x00010000
53 /* ----- internal variables ----- */
55 static HWND hwndPrevActive = 0; /* Previously active window */
56 static HWND hGlobalShellWindow=0; /*the shell*/
58 static LPCSTR atomInternalPos;
60 extern HQUEUE16 hActiveQueue;
62 /***********************************************************************
63 * WINPOS_CreateInternalPosAtom
65 BOOL WINPOS_CreateInternalPosAtom()
67 LPSTR str = "SysIP";
68 atomInternalPos = (LPCSTR)(DWORD)GlobalAddAtomA(str);
69 return (atomInternalPos) ? TRUE : FALSE;
72 /***********************************************************************
73 * WINPOS_CheckInternalPos
75 * Called when a window is destroyed.
77 void WINPOS_CheckInternalPos( WND* wndPtr )
79 LPINTERNALPOS lpPos;
80 MESSAGEQUEUE *pMsgQ = 0;
81 HWND hwnd = wndPtr->hwndSelf;
83 lpPos = (LPINTERNALPOS) GetPropA( hwnd, atomInternalPos );
85 /* Retrieve the message queue associated with this window */
86 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
87 if ( !pMsgQ )
89 WARN( win, "\tMessage queue not found. Exiting!\n" );
90 return;
93 if( hwnd == hwndPrevActive ) hwndPrevActive = 0;
95 if( hwnd == PERQDATA_GetActiveWnd( pMsgQ->pQData ) )
97 PERQDATA_SetActiveWnd( pMsgQ->pQData, 0 );
98 WARN(win, "\tattempt to activate destroyed window!\n");
101 if( lpPos )
103 if( IsWindow(lpPos->hwndIconTitle) )
104 DestroyWindow( lpPos->hwndIconTitle );
105 HeapFree( SystemHeap, 0, lpPos );
108 QUEUE_Unlock( pMsgQ );
109 return;
112 /***********************************************************************
113 * WINPOS_FindIconPos
115 * Find a suitable place for an iconic window.
117 static POINT16 WINPOS_FindIconPos( WND* wndPtr, POINT16 pt )
119 RECT16 rectParent;
120 short x, y, xspacing, yspacing;
122 GetClientRect16( wndPtr->parent->hwndSelf, &rectParent );
123 if ((pt.x >= rectParent.left) && (pt.x + SYSMETRICS_CXICON < rectParent.right) &&
124 (pt.y >= rectParent.top) && (pt.y + SYSMETRICS_CYICON < rectParent.bottom))
125 return pt; /* The icon already has a suitable position */
127 xspacing = SYSMETRICS_CXICONSPACING;
128 yspacing = SYSMETRICS_CYICONSPACING;
130 y = rectParent.bottom;
131 for (;;)
133 for (x = rectParent.left; x <= rectParent.right-xspacing; x += xspacing)
135 /* Check if another icon already occupies this spot */
136 WND *childPtr = WIN_LockWndPtr(wndPtr->parent->child);
137 while (childPtr)
139 if ((childPtr->dwStyle & WS_MINIMIZE) && (childPtr != wndPtr))
141 if ((childPtr->rectWindow.left < x + xspacing) &&
142 (childPtr->rectWindow.right >= x) &&
143 (childPtr->rectWindow.top <= y) &&
144 (childPtr->rectWindow.bottom > y - yspacing))
145 break; /* There's a window in there */
147 WIN_UpdateWndPtr(&childPtr,childPtr->next);
149 WIN_ReleaseWndPtr(childPtr);
150 if (!childPtr) /* No window was found, so it's OK for us */
152 pt.x = x + (xspacing - SYSMETRICS_CXICON) / 2;
153 pt.y = y - (yspacing + SYSMETRICS_CYICON) / 2;
154 return pt;
157 y -= yspacing;
162 /***********************************************************************
163 * ArrangeIconicWindows16 (USER.170)
165 UINT16 WINAPI ArrangeIconicWindows16( HWND16 parent)
167 return ArrangeIconicWindows(parent);
169 /***********************************************************************
170 * ArrangeIconicWindows (USER32.7)
172 UINT WINAPI ArrangeIconicWindows( HWND parent )
174 RECT rectParent;
175 HWND hwndChild;
176 INT x, y, xspacing, yspacing;
178 GetClientRect( parent, &rectParent );
179 x = rectParent.left;
180 y = rectParent.bottom;
181 xspacing = SYSMETRICS_CXICONSPACING;
182 yspacing = SYSMETRICS_CYICONSPACING;
184 hwndChild = GetWindow( parent, GW_CHILD );
185 while (hwndChild)
187 if( IsIconic( hwndChild ) )
189 WND *wndPtr = WIN_FindWndPtr(hwndChild);
191 WINPOS_ShowIconTitle( wndPtr, FALSE );
193 SetWindowPos( hwndChild, 0, x + (xspacing - SYSMETRICS_CXICON) / 2,
194 y - yspacing - SYSMETRICS_CYICON/2, 0, 0,
195 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
196 if( IsWindow(hwndChild) )
197 WINPOS_ShowIconTitle(wndPtr , TRUE );
198 WIN_ReleaseWndPtr(wndPtr);
200 if (x <= rectParent.right - xspacing) x += xspacing;
201 else
203 x = rectParent.left;
204 y -= yspacing;
207 hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
209 return yspacing;
213 /***********************************************************************
214 * SwitchToThisWindow16 (USER.172)
216 void WINAPI SwitchToThisWindow16( HWND16 hwnd, BOOL16 restore )
218 SwitchToThisWindow( hwnd, restore );
222 /***********************************************************************
223 * SwitchToThisWindow (USER32.539)
225 void WINAPI SwitchToThisWindow( HWND hwnd, BOOL restore )
227 ShowWindow( hwnd, restore ? SW_RESTORE : SW_SHOWMINIMIZED );
231 /***********************************************************************
232 * GetWindowRect16 (USER.32)
234 void WINAPI GetWindowRect16( HWND16 hwnd, LPRECT16 rect )
236 WND * wndPtr = WIN_FindWndPtr( hwnd );
237 if (!wndPtr) return;
239 CONV_RECT32TO16( &wndPtr->rectWindow, rect );
240 if (wndPtr->dwStyle & WS_CHILD)
241 MapWindowPoints16( wndPtr->parent->hwndSelf, 0, (POINT16 *)rect, 2 );
242 WIN_ReleaseWndPtr(wndPtr);
246 /***********************************************************************
247 * GetWindowRect (USER32.308)
249 BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect )
251 WND * wndPtr = WIN_FindWndPtr( hwnd );
252 if (!wndPtr) return FALSE;
254 *rect = wndPtr->rectWindow;
255 if (wndPtr->dwStyle & WS_CHILD)
256 MapWindowPoints( wndPtr->parent->hwndSelf, 0, (POINT *)rect, 2 );
257 WIN_ReleaseWndPtr(wndPtr);
258 return TRUE;
262 /***********************************************************************
263 * GetWindowRgn
265 BOOL WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
268 RECT rect;
269 WND * wndPtr = WIN_FindWndPtr( hwnd );
270 if (!wndPtr) return (ERROR);
272 FIXME (win, "GetWindowRgn: doesn't really do regions\n");
274 memset (&rect, 0, sizeof(rect));
276 GetWindowRect ( hwnd, &rect );
278 FIXME (win, "Check whether a valid region here\n");
280 SetRectRgn ( hrgn, rect.left, rect.top, rect.right, rect.bottom );
282 WIN_ReleaseWndPtr(wndPtr);
283 return (SIMPLEREGION);
286 /***********************************************************************
287 * SetWindowRgn
289 INT WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn,BOOL bRedraw)
293 FIXME (win, "SetWindowRgn: stub\n");
294 return TRUE;
297 /***********************************************************************
298 * SetWindowRgn16
300 INT16 WINAPI SetWindowRgn16( HWND16 hwnd, HRGN16 hrgn,BOOL16 bRedraw)
304 FIXME (win, "SetWindowRgn16: stub\n");
305 return TRUE;
309 /***********************************************************************
310 * GetClientRect16 (USER.33)
312 void WINAPI GetClientRect16( HWND16 hwnd, LPRECT16 rect )
314 WND * wndPtr = WIN_FindWndPtr( hwnd );
316 rect->left = rect->top = rect->right = rect->bottom = 0;
317 if (wndPtr)
319 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
320 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
322 WIN_ReleaseWndPtr(wndPtr);
326 /***********************************************************************
327 * GetClientRect (USER.220)
329 BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect )
331 WND * wndPtr = WIN_FindWndPtr( hwnd );
333 rect->left = rect->top = rect->right = rect->bottom = 0;
334 if (!wndPtr) return FALSE;
335 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
336 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
338 WIN_ReleaseWndPtr(wndPtr);
339 return TRUE;
343 /*******************************************************************
344 * ClientToScreen16 (USER.28)
346 void WINAPI ClientToScreen16( HWND16 hwnd, LPPOINT16 lppnt )
348 MapWindowPoints16( hwnd, 0, lppnt, 1 );
352 /*******************************************************************
353 * ClientToScreen (USER32.52)
355 BOOL WINAPI ClientToScreen( HWND hwnd, LPPOINT lppnt )
357 MapWindowPoints( hwnd, 0, lppnt, 1 );
358 return TRUE;
362 /*******************************************************************
363 * ScreenToClient16 (USER.29)
365 void WINAPI ScreenToClient16( HWND16 hwnd, LPPOINT16 lppnt )
367 MapWindowPoints16( 0, hwnd, lppnt, 1 );
371 /*******************************************************************
372 * ScreenToClient (USER32.447)
374 BOOL WINAPI ScreenToClient( HWND hwnd, LPPOINT lppnt )
376 MapWindowPoints( 0, hwnd, lppnt, 1 );
377 return TRUE;
381 /***********************************************************************
382 * WINPOS_WindowFromPoint
384 * Find the window and hittest for a given point.
386 INT16 WINPOS_WindowFromPoint( WND* wndScope, POINT16 pt, WND **ppWnd )
388 WND *wndPtr;
389 INT16 hittest = HTERROR;
390 INT16 retvalue;
391 POINT16 xy = pt;
393 *ppWnd = NULL;
394 wndPtr = WIN_LockWndPtr(wndScope->child);
396 if( wndScope->flags & WIN_MANAGED )
398 /* In managed mode we have to check wndScope first as it is also
399 * a window which received the mouse event. */
401 if( wndScope->dwStyle & WS_DISABLED )
403 retvalue = HTERROR;
404 goto end;
406 if( pt.x < wndScope->rectClient.left || pt.x >= wndScope->rectClient.right ||
407 pt.y < wndScope->rectClient.top || pt.y >= wndScope->rectClient.bottom )
408 goto hittest;
410 MapWindowPoints16( GetDesktopWindow16(), wndScope->hwndSelf, &xy, 1 );
412 for (;;)
414 while (wndPtr)
416 /* If point is in window, and window is visible, and it */
417 /* is enabled (or it's a top-level window), then explore */
418 /* its children. Otherwise, go to the next window. */
420 if ((wndPtr->dwStyle & WS_VISIBLE) &&
421 (!(wndPtr->dwStyle & WS_DISABLED) ||
422 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)) &&
423 (xy.x >= wndPtr->rectWindow.left) &&
424 (xy.x < wndPtr->rectWindow.right) &&
425 (xy.y >= wndPtr->rectWindow.top) &&
426 (xy.y < wndPtr->rectWindow.bottom))
428 *ppWnd = wndPtr; /* Got a suitable window */
430 /* If window is minimized or disabled, return at once */
431 if (wndPtr->dwStyle & WS_MINIMIZE)
433 retvalue = HTCAPTION;
434 goto end;
436 if (wndPtr->dwStyle & WS_DISABLED)
438 retvalue = HTERROR;
439 goto end;
442 /* If point is not in client area, ignore the children */
443 if ((xy.x < wndPtr->rectClient.left) ||
444 (xy.x >= wndPtr->rectClient.right) ||
445 (xy.y < wndPtr->rectClient.top) ||
446 (xy.y >= wndPtr->rectClient.bottom)) break;
448 xy.x -= wndPtr->rectClient.left;
449 xy.y -= wndPtr->rectClient.top;
450 WIN_UpdateWndPtr(&wndPtr,wndPtr->child);
452 else
454 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
458 hittest:
459 /* If nothing found, try the scope window */
460 if (!*ppWnd) *ppWnd = wndScope;
462 /* Send the WM_NCHITTEST message (only if to the same task) */
463 if ((*ppWnd)->hmemTaskQ == GetFastQueue16())
465 hittest = (INT16)SendMessage16( (*ppWnd)->hwndSelf, WM_NCHITTEST,
466 0, MAKELONG( pt.x, pt.y ) );
467 if (hittest != HTTRANSPARENT)
469 retvalue = hittest; /* Found the window */
470 goto end;
473 else
475 retvalue = HTCLIENT;
476 goto end;
479 /* If no children found in last search, make point relative to parent */
480 if (!wndPtr)
482 xy.x += (*ppWnd)->rectClient.left;
483 xy.y += (*ppWnd)->rectClient.top;
486 /* Restart the search from the next sibling */
487 WIN_UpdateWndPtr(&wndPtr,(*ppWnd)->next);
488 *ppWnd = (*ppWnd)->parent;
491 end:
492 WIN_ReleaseWndPtr(wndPtr);
493 return retvalue;
497 /*******************************************************************
498 * WindowFromPoint16 (USER.30)
500 HWND16 WINAPI WindowFromPoint16( POINT16 pt )
502 WND *pWnd;
503 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt, &pWnd );
504 WIN_ReleaseDesktop();
505 return pWnd->hwndSelf;
509 /*******************************************************************
510 * WindowFromPoint (USER32.582)
512 HWND WINAPI WindowFromPoint( POINT pt )
514 WND *pWnd;
515 POINT16 pt16;
516 CONV_POINT32TO16( &pt, &pt16 );
517 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16, &pWnd );
518 WIN_ReleaseDesktop();
519 return (HWND)pWnd->hwndSelf;
523 /*******************************************************************
524 * ChildWindowFromPoint16 (USER.191)
526 HWND16 WINAPI ChildWindowFromPoint16( HWND16 hwndParent, POINT16 pt )
528 POINT pt32;
529 CONV_POINT16TO32( &pt, &pt32 );
530 return (HWND16)ChildWindowFromPoint( hwndParent, pt32 );
534 /*******************************************************************
535 * ChildWindowFromPoint (USER32.49)
537 HWND WINAPI ChildWindowFromPoint( HWND hwndParent, POINT pt )
539 /* pt is in the client coordinates */
541 WND* wnd = WIN_FindWndPtr(hwndParent);
542 RECT rect;
543 HWND retvalue;
545 if( !wnd ) return 0;
547 /* get client rect fast */
548 rect.top = rect.left = 0;
549 rect.right = wnd->rectClient.right - wnd->rectClient.left;
550 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
552 if (!PtInRect( &rect, pt ))
554 retvalue = 0;
555 goto end;
557 WIN_UpdateWndPtr(&wnd,wnd->child);
558 while ( wnd )
560 if (PtInRect( &wnd->rectWindow, pt ))
562 retvalue = wnd->hwndSelf;
563 goto end;
565 WIN_UpdateWndPtr(&wnd,wnd->next);
567 retvalue = hwndParent;
568 end:
569 WIN_ReleaseWndPtr(wnd);
570 return retvalue;
573 /*******************************************************************
574 * ChildWindowFromPointEx16 (USER.50)
576 HWND16 WINAPI ChildWindowFromPointEx16( HWND16 hwndParent, POINT16 pt, UINT16 uFlags)
578 POINT pt32;
579 CONV_POINT16TO32( &pt, &pt32 );
580 return (HWND16)ChildWindowFromPointEx( hwndParent, pt32, uFlags );
584 /*******************************************************************
585 * ChildWindowFromPointEx32 (USER32.50)
587 HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt,
588 UINT uFlags)
590 /* pt is in the client coordinates */
592 WND* wnd = WIN_FindWndPtr(hwndParent);
593 RECT rect;
594 HWND retvalue;
596 if( !wnd ) return 0;
598 /* get client rect fast */
599 rect.top = rect.left = 0;
600 rect.right = wnd->rectClient.right - wnd->rectClient.left;
601 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
603 if (!PtInRect( &rect, pt ))
605 retvalue = 0;
606 goto end;
608 WIN_UpdateWndPtr(&wnd,wnd->child);
610 while ( wnd )
612 if (PtInRect( &wnd->rectWindow, pt )) {
613 if ( (uFlags & CWP_SKIPINVISIBLE) &&
614 !(wnd->dwStyle & WS_VISIBLE) );
615 else if ( (uFlags & CWP_SKIPDISABLED) &&
616 (wnd->dwStyle & WS_DISABLED) );
617 else if ( (uFlags & CWP_SKIPTRANSPARENT) &&
618 (wnd->dwExStyle & WS_EX_TRANSPARENT) );
619 else
621 retvalue = wnd->hwndSelf;
622 goto end;
624 WIN_UpdateWndPtr(&wnd,wnd->next);
628 retvalue = hwndParent;
629 end:
630 WIN_ReleaseWndPtr(wnd);
631 return retvalue;
635 /*******************************************************************
636 * WINPOS_GetWinOffset
638 * Calculate the offset between the origin of the two windows. Used
639 * to implement MapWindowPoints.
641 static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo,
642 POINT *offset )
644 WND * wndPtr = 0;
646 offset->x = offset->y = 0;
647 if (hwndFrom == hwndTo ) return;
649 /* Translate source window origin to screen coords */
650 if (hwndFrom)
652 if (!(wndPtr = WIN_FindWndPtr( hwndFrom )))
654 ERR(win,"bad hwndFrom = %04x\n",hwndFrom);
655 return;
657 while (wndPtr->parent)
659 offset->x += wndPtr->rectClient.left;
660 offset->y += wndPtr->rectClient.top;
661 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
663 WIN_ReleaseWndPtr(wndPtr);
666 /* Translate origin to destination window coords */
667 if (hwndTo)
669 if (!(wndPtr = WIN_FindWndPtr( hwndTo )))
671 ERR(win,"bad hwndTo = %04x\n", hwndTo );
672 return;
674 while (wndPtr->parent)
676 offset->x -= wndPtr->rectClient.left;
677 offset->y -= wndPtr->rectClient.top;
678 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
680 WIN_ReleaseWndPtr(wndPtr);
685 /*******************************************************************
686 * MapWindowPoints16 (USER.258)
688 void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
689 LPPOINT16 lppt, UINT16 count )
691 POINT offset;
693 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
694 while (count--)
696 lppt->x += offset.x;
697 lppt->y += offset.y;
698 lppt++;
703 /*******************************************************************
704 * MapWindowPoints (USER32.386)
706 INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo,
707 LPPOINT lppt, UINT count )
709 POINT offset;
711 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
712 while (count--)
714 lppt->x += offset.x;
715 lppt->y += offset.y;
716 lppt++;
718 return MAKELONG( LOWORD(offset.x), LOWORD(offset.y) );
722 /***********************************************************************
723 * IsIconic16 (USER.31)
725 BOOL16 WINAPI IsIconic16(HWND16 hWnd)
727 return IsIconic(hWnd);
731 /***********************************************************************
732 * IsIconic (USER32.345)
734 BOOL WINAPI IsIconic(HWND hWnd)
736 BOOL retvalue;
737 WND * wndPtr = WIN_FindWndPtr(hWnd);
738 if (wndPtr == NULL) return FALSE;
739 retvalue = (wndPtr->dwStyle & WS_MINIMIZE) != 0;
740 WIN_ReleaseWndPtr(wndPtr);
741 return retvalue;
745 /***********************************************************************
746 * IsZoomed (USER.272)
748 BOOL16 WINAPI IsZoomed16(HWND16 hWnd)
750 return IsZoomed(hWnd);
754 /***********************************************************************
755 * IsZoomed (USER.352)
757 BOOL WINAPI IsZoomed(HWND hWnd)
759 BOOL retvalue;
760 WND * wndPtr = WIN_FindWndPtr(hWnd);
761 if (wndPtr == NULL) return FALSE;
762 retvalue = (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
763 WIN_ReleaseWndPtr(wndPtr);
764 return retvalue;
768 /*******************************************************************
769 * GetActiveWindow (USER.60)
771 HWND16 WINAPI GetActiveWindow16(void)
773 return (HWND16)GetActiveWindow();
776 /*******************************************************************
777 * GetActiveWindow (USER32.205)
779 HWND WINAPI GetActiveWindow(void)
781 MESSAGEQUEUE *pCurMsgQ = 0;
782 HWND hwndActive = 0;
784 /* Get the messageQ for the current thread */
785 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
787 WARN( win, "\tCurrent message queue not found. Exiting!\n" );
788 return 0;
791 /* Return the current active window from the perQ data of the current message Q */
792 hwndActive = PERQDATA_GetActiveWnd( pCurMsgQ->pQData );
794 QUEUE_Unlock( pCurMsgQ );
795 return hwndActive;
799 /*******************************************************************
800 * WINPOS_CanActivate
802 static BOOL WINPOS_CanActivate(WND* pWnd)
804 if( pWnd && ((pWnd->dwStyle & (WS_DISABLED | WS_VISIBLE | WS_CHILD))
805 == WS_VISIBLE) ) return TRUE;
806 return FALSE;
810 /*******************************************************************
811 * SetActiveWindow16 (USER.59)
813 HWND16 WINAPI SetActiveWindow16( HWND16 hwnd )
815 return SetActiveWindow(hwnd);
819 /*******************************************************************
820 * SetActiveWindow (USER32.463)
822 HWND WINAPI SetActiveWindow( HWND hwnd )
824 HWND prev = 0;
825 WND *wndPtr = WIN_FindWndPtr( hwnd );
826 MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
828 if ( !WINPOS_CanActivate(wndPtr) )
830 prev = 0;
831 goto end;
834 /* Get the messageQ for the current thread */
835 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
837 WARN( win, "\tCurrent message queue not found. Exiting!\n" );
838 goto CLEANUP;
841 /* Retrieve the message queue associated with this window */
842 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
843 if ( !pMsgQ )
845 WARN( win, "\tWindow message queue not found. Exiting!\n" );
846 goto CLEANUP;
849 /* Make sure that the window is associated with the calling threads
850 * message queue. It must share the same perQ data.
853 if ( pCurMsgQ->pQData != pMsgQ->pQData )
854 goto CLEANUP;
856 /* Save current active window */
857 prev = PERQDATA_GetActiveWnd( pMsgQ->pQData );
859 WINPOS_SetActiveWindow( hwnd, 0, 0 );
861 CLEANUP:
862 /* Unlock the queues before returning */
863 if ( pMsgQ )
864 QUEUE_Unlock( pMsgQ );
865 if ( pCurMsgQ )
866 QUEUE_Unlock( pCurMsgQ );
868 end:
869 WIN_ReleaseWndPtr(wndPtr);
870 return prev;
874 /*******************************************************************
875 * GetForegroundWindow16 (USER.608)
877 HWND16 WINAPI GetForegroundWindow16(void)
879 return (HWND16)GetForegroundWindow();
883 /*******************************************************************
884 * SetForegroundWindow16 (USER.609)
886 BOOL16 WINAPI SetForegroundWindow16( HWND16 hwnd )
888 return SetForegroundWindow( hwnd );
892 /*******************************************************************
893 * GetForegroundWindow (USER32.241)
895 HWND WINAPI GetForegroundWindow(void)
897 return GetActiveWindow();
901 /*******************************************************************
902 * SetForegroundWindow (USER32.482)
904 BOOL WINAPI SetForegroundWindow( HWND hwnd )
906 SetActiveWindow( hwnd );
907 return TRUE;
911 /*******************************************************************
912 * GetShellWindow16 (USER.600)
914 HWND16 WINAPI GetShellWindow16(void)
916 return GetShellWindow();
919 /*******************************************************************
920 * SetShellWindow (USER32.504)
922 HWND WINAPI SetShellWindow(HWND hwndshell)
923 { WARN(win, "(hWnd=%08x) semi stub\n",hwndshell );
925 hGlobalShellWindow = hwndshell;
926 return hGlobalShellWindow;
930 /*******************************************************************
931 * GetShellWindow (USER32.287)
933 HWND WINAPI GetShellWindow(void)
934 { WARN(win, "(hWnd=%x) semi stub\n",hGlobalShellWindow );
936 return hGlobalShellWindow;
940 /***********************************************************************
941 * BringWindowToTop16 (USER.45)
943 BOOL16 WINAPI BringWindowToTop16( HWND16 hwnd )
945 return BringWindowToTop(hwnd);
949 /***********************************************************************
950 * BringWindowToTop (USER32.11)
952 BOOL WINAPI BringWindowToTop( HWND hwnd )
954 return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
958 /***********************************************************************
959 * MoveWindow16 (USER.56)
961 BOOL16 WINAPI MoveWindow16( HWND16 hwnd, INT16 x, INT16 y, INT16 cx, INT16 cy,
962 BOOL16 repaint )
964 return MoveWindow(hwnd,x,y,cx,cy,repaint);
968 /***********************************************************************
969 * MoveWindow (USER32.399)
971 BOOL WINAPI MoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy,
972 BOOL repaint )
974 int flags = SWP_NOZORDER | SWP_NOACTIVATE;
975 if (!repaint) flags |= SWP_NOREDRAW;
976 TRACE(win, "%04x %d,%d %dx%d %d\n",
977 hwnd, x, y, cx, cy, repaint );
978 return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
981 /***********************************************************************
982 * WINPOS_InitInternalPos
984 static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT pt,
985 LPRECT restoreRect )
987 LPINTERNALPOS lpPos = (LPINTERNALPOS) GetPropA( wnd->hwndSelf,
988 atomInternalPos );
989 if( !lpPos )
991 /* this happens when the window is minimized/maximized
992 * for the first time (rectWindow is not adjusted yet) */
994 lpPos = HeapAlloc( SystemHeap, 0, sizeof(INTERNALPOS) );
995 if( !lpPos ) return NULL;
997 SetPropA( wnd->hwndSelf, atomInternalPos, (HANDLE)lpPos );
998 lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
999 CONV_RECT32TO16( &wnd->rectWindow, &lpPos->rectNormal );
1000 *(UINT*)&lpPos->ptIconPos = *(UINT*)&lpPos->ptMaxPos = 0xFFFFFFFF;
1003 if( wnd->dwStyle & WS_MINIMIZE )
1004 CONV_POINT32TO16( &pt, &lpPos->ptIconPos );
1005 else if( wnd->dwStyle & WS_MAXIMIZE )
1006 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1007 else if( restoreRect )
1008 CONV_RECT32TO16( restoreRect, &lpPos->rectNormal );
1010 return lpPos;
1013 /***********************************************************************
1014 * WINPOS_RedrawIconTitle
1016 BOOL WINPOS_RedrawIconTitle( HWND hWnd )
1018 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hWnd, atomInternalPos );
1019 if( lpPos )
1021 if( lpPos->hwndIconTitle )
1023 SendMessageA( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
1024 InvalidateRect( lpPos->hwndIconTitle, NULL, TRUE );
1025 return TRUE;
1028 return FALSE;
1031 /***********************************************************************
1032 * WINPOS_ShowIconTitle
1034 BOOL WINPOS_ShowIconTitle( WND* pWnd, BOOL bShow )
1036 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( pWnd->hwndSelf, atomInternalPos );
1038 if( lpPos && !(pWnd->flags & WIN_MANAGED))
1040 HWND16 hWnd = lpPos->hwndIconTitle;
1042 TRACE(win,"0x%04x %i\n", pWnd->hwndSelf, (bShow != 0) );
1044 if( !hWnd )
1045 lpPos->hwndIconTitle = hWnd = ICONTITLE_Create( pWnd );
1046 if( bShow )
1048 pWnd = WIN_FindWndPtr(hWnd);
1050 if( !(pWnd->dwStyle & WS_VISIBLE) )
1052 SendMessageA( hWnd, WM_SHOWWINDOW, TRUE, 0 );
1053 SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
1054 SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
1056 WIN_ReleaseWndPtr(pWnd);
1058 else ShowWindow( hWnd, SW_HIDE );
1060 return FALSE;
1063 /*******************************************************************
1064 * WINPOS_GetMinMaxInfo
1066 * Get the minimized and maximized information for a window.
1068 void WINPOS_GetMinMaxInfo( WND *wndPtr, POINT *maxSize, POINT *maxPos,
1069 POINT *minTrack, POINT *maxTrack )
1071 LPINTERNALPOS lpPos;
1072 MINMAXINFO MinMax;
1073 INT xinc, yinc;
1075 /* Compute default values */
1077 MinMax.ptMaxSize.x = SYSMETRICS_CXSCREEN;
1078 MinMax.ptMaxSize.y = SYSMETRICS_CYSCREEN;
1079 MinMax.ptMinTrackSize.x = SYSMETRICS_CXMINTRACK;
1080 MinMax.ptMinTrackSize.y = SYSMETRICS_CYMINTRACK;
1081 MinMax.ptMaxTrackSize.x = SYSMETRICS_CXSCREEN;
1082 MinMax.ptMaxTrackSize.y = SYSMETRICS_CYSCREEN;
1084 if (wndPtr->flags & WIN_MANAGED) xinc = yinc = 0;
1085 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1087 xinc = SYSMETRICS_CXDLGFRAME;
1088 yinc = SYSMETRICS_CYDLGFRAME;
1090 else
1092 xinc = yinc = 0;
1093 if (HAS_THICKFRAME(wndPtr->dwStyle))
1095 xinc += SYSMETRICS_CXFRAME;
1096 yinc += SYSMETRICS_CYFRAME;
1098 if (wndPtr->dwStyle & WS_BORDER)
1100 xinc += SYSMETRICS_CXBORDER;
1101 yinc += SYSMETRICS_CYBORDER;
1104 MinMax.ptMaxSize.x += 2 * xinc;
1105 MinMax.ptMaxSize.y += 2 * yinc;
1107 lpPos = (LPINTERNALPOS)GetPropA( wndPtr->hwndSelf, atomInternalPos );
1108 if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
1109 CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
1110 else
1112 MinMax.ptMaxPosition.x = -xinc;
1113 MinMax.ptMaxPosition.y = -yinc;
1116 SendMessageA( wndPtr->hwndSelf, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
1118 /* Some sanity checks */
1120 TRACE(win,"%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1121 MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
1122 MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
1123 MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
1124 MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
1125 MinMax.ptMaxTrackSize.x = MAX( MinMax.ptMaxTrackSize.x,
1126 MinMax.ptMinTrackSize.x );
1127 MinMax.ptMaxTrackSize.y = MAX( MinMax.ptMaxTrackSize.y,
1128 MinMax.ptMinTrackSize.y );
1130 if (maxSize) *maxSize = MinMax.ptMaxSize;
1131 if (maxPos) *maxPos = MinMax.ptMaxPosition;
1132 if (minTrack) *minTrack = MinMax.ptMinTrackSize;
1133 if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
1136 /***********************************************************************
1137 * WINPOS_MinMaximize
1139 * Fill in lpRect and return additional flags to be used with SetWindowPos().
1140 * This function assumes that 'cmd' is different from the current window
1141 * state.
1143 UINT WINPOS_MinMaximize( WND* wndPtr, UINT16 cmd, LPRECT16 lpRect )
1145 UINT swpFlags = 0;
1146 POINT pt;
1147 POINT size = { wndPtr->rectWindow.left, wndPtr->rectWindow.top };
1148 LPINTERNALPOS lpPos = WINPOS_InitInternalPos( wndPtr, size,
1149 &wndPtr->rectWindow );
1151 TRACE(win,"0x%04x %u\n", wndPtr->hwndSelf, cmd );
1153 if (lpPos && !HOOK_CallHooks16(WH_CBT, HCBT_MINMAX, wndPtr->hwndSelf, cmd))
1155 if( wndPtr->dwStyle & WS_MINIMIZE )
1157 if( !SendMessageA( wndPtr->hwndSelf, WM_QUERYOPEN, 0, 0L ) )
1158 return (SWP_NOSIZE | SWP_NOMOVE);
1159 swpFlags |= SWP_NOCOPYBITS;
1161 switch( cmd )
1163 case SW_MINIMIZE:
1164 if( wndPtr->dwStyle & WS_MAXIMIZE)
1166 wndPtr->flags |= WIN_RESTORE_MAX;
1167 wndPtr->dwStyle &= ~WS_MAXIMIZE;
1169 else
1170 wndPtr->flags &= ~WIN_RESTORE_MAX;
1171 wndPtr->dwStyle |= WS_MINIMIZE;
1173 if( wndPtr->flags & WIN_NATIVE )
1174 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, TRUE ) )
1175 swpFlags |= MINMAX_NOSWP;
1177 lpPos->ptIconPos = WINPOS_FindIconPos( wndPtr, lpPos->ptIconPos );
1179 SetRect16( lpRect, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1180 SYSMETRICS_CXICON, SYSMETRICS_CYICON );
1181 swpFlags |= SWP_NOCOPYBITS;
1182 break;
1184 case SW_MAXIMIZE:
1185 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1186 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL );
1187 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1189 if( wndPtr->dwStyle & WS_MINIMIZE )
1191 if( wndPtr->flags & WIN_NATIVE )
1192 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
1193 swpFlags |= MINMAX_NOSWP;
1195 WINPOS_ShowIconTitle( wndPtr, FALSE );
1196 wndPtr->dwStyle &= ~WS_MINIMIZE;
1198 wndPtr->dwStyle |= WS_MAXIMIZE;
1200 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1201 size.x, size.y );
1202 break;
1204 case SW_RESTORE:
1205 if( wndPtr->dwStyle & WS_MINIMIZE )
1207 if( wndPtr->flags & WIN_NATIVE )
1208 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
1209 swpFlags |= MINMAX_NOSWP;
1211 wndPtr->dwStyle &= ~WS_MINIMIZE;
1212 WINPOS_ShowIconTitle( wndPtr, FALSE );
1214 if( wndPtr->flags & WIN_RESTORE_MAX)
1216 /* Restore to maximized position */
1217 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1218 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL);
1219 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1220 wndPtr->dwStyle |= WS_MAXIMIZE;
1221 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y, size.x, size.y );
1222 break;
1225 else
1226 if( !(wndPtr->dwStyle & WS_MAXIMIZE) ) return (UINT16)(-1);
1227 else wndPtr->dwStyle &= ~WS_MAXIMIZE;
1229 /* Restore to normal position */
1231 *lpRect = lpPos->rectNormal;
1232 lpRect->right -= lpRect->left;
1233 lpRect->bottom -= lpRect->top;
1235 break;
1237 } else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
1238 return swpFlags;
1241 /***********************************************************************
1242 * ShowWindowAsync (USER32.535)
1244 * doesn't wait; returns immediately.
1245 * used by threads to toggle windows in other (possibly hanging) threads
1247 BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd )
1249 /* FIXME: does ShowWindow() return immediately ? */
1250 return ShowWindow(hwnd, cmd);
1254 /***********************************************************************
1255 * ShowWindow16 (USER.42)
1257 BOOL16 WINAPI ShowWindow16( HWND16 hwnd, INT16 cmd )
1259 return ShowWindow(hwnd,cmd);
1263 /***********************************************************************
1264 * ShowWindow (USER32.534)
1266 BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
1268 WND* wndPtr = WIN_FindWndPtr( hwnd );
1269 BOOL wasVisible, showFlag;
1270 RECT16 newPos = {0, 0, 0, 0};
1271 UINT swp = 0;
1273 if (!wndPtr) return FALSE;
1275 TRACE(win,"hwnd=%04x, cmd=%d\n", hwnd, cmd);
1277 wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
1279 switch(cmd)
1281 case SW_HIDE:
1282 if (!wasVisible) goto END;;
1283 swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
1284 SWP_NOACTIVATE | SWP_NOZORDER;
1285 if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus()))
1287 /* Revert focus to parent */
1288 SetFocus( GetParent(hwnd) );
1290 break;
1292 case SW_SHOWMINNOACTIVE:
1293 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1294 /* fall through */
1295 case SW_SHOWMINIMIZED:
1296 swp |= SWP_SHOWWINDOW;
1297 /* fall through */
1298 case SW_MINIMIZE:
1299 swp |= SWP_FRAMECHANGED;
1300 if( !(wndPtr->dwStyle & WS_MINIMIZE) )
1301 swp |= WINPOS_MinMaximize( wndPtr, SW_MINIMIZE, &newPos );
1302 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1303 break;
1305 case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
1306 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1307 if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
1308 swp |= WINPOS_MinMaximize( wndPtr, SW_MAXIMIZE, &newPos );
1309 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1310 break;
1312 case SW_SHOWNA:
1313 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1314 /* fall through */
1315 case SW_SHOW:
1316 swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
1317 break;
1319 case SW_SHOWNOACTIVATE:
1320 swp |= SWP_NOZORDER;
1321 if (GetActiveWindow()) swp |= SWP_NOACTIVATE;
1322 /* fall through */
1323 case SW_SHOWNORMAL: /* same as SW_NORMAL: */
1324 case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
1325 case SW_RESTORE:
1326 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1328 if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) )
1329 swp |= WINPOS_MinMaximize( wndPtr, SW_RESTORE, &newPos );
1330 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1331 break;
1334 showFlag = (cmd != SW_HIDE);
1335 if (showFlag != wasVisible)
1337 SendMessageA( hwnd, WM_SHOWWINDOW, showFlag, 0 );
1338 if (!IsWindow( hwnd )) goto END;
1341 if ((wndPtr->dwStyle & WS_CHILD) &&
1342 !IsWindowVisible( wndPtr->parent->hwndSelf ) &&
1343 (swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE) )
1345 /* Don't call SetWindowPos() on invisible child windows */
1346 if (cmd == SW_HIDE) wndPtr->dwStyle &= ~WS_VISIBLE;
1347 else wndPtr->dwStyle |= WS_VISIBLE;
1349 else
1351 /* We can't activate a child window */
1352 if (wndPtr->dwStyle & WS_CHILD) swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1353 if (!(swp & MINMAX_NOSWP))
1354 SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top,
1355 newPos.right, newPos.bottom, LOWORD(swp) );
1356 if (!IsWindow( hwnd )) goto END;
1357 else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( wndPtr, TRUE );
1360 if (wndPtr->flags & WIN_NEED_SIZE)
1362 /* should happen only in CreateWindowEx() */
1363 int wParam = SIZE_RESTORED;
1365 wndPtr->flags &= ~WIN_NEED_SIZE;
1366 if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
1367 else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
1368 SendMessageA( hwnd, WM_SIZE, wParam,
1369 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
1370 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
1371 SendMessageA( hwnd, WM_MOVE, 0,
1372 MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
1375 END:
1376 WIN_ReleaseWndPtr(wndPtr);
1377 return wasVisible;
1381 /***********************************************************************
1382 * GetInternalWindowPos16 (USER.460)
1384 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
1385 LPPOINT16 ptIcon )
1387 WINDOWPLACEMENT16 wndpl;
1388 if (GetWindowPlacement16( hwnd, &wndpl ))
1390 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1391 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1392 return wndpl.showCmd;
1394 return 0;
1398 /***********************************************************************
1399 * GetInternalWindowPos (USER32.245)
1401 UINT WINAPI GetInternalWindowPos( HWND hwnd, LPRECT rectWnd,
1402 LPPOINT ptIcon )
1404 WINDOWPLACEMENT wndpl;
1405 if (GetWindowPlacement( hwnd, &wndpl ))
1407 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1408 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1409 return wndpl.showCmd;
1411 return 0;
1414 /***********************************************************************
1415 * GetWindowPlacement16 (USER.370)
1417 BOOL16 WINAPI GetWindowPlacement16( HWND16 hwnd, WINDOWPLACEMENT16 *wndpl )
1419 WND *pWnd = WIN_FindWndPtr( hwnd );
1420 LPINTERNALPOS lpPos;
1422 if(!pWnd ) return FALSE;
1424 lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1425 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1426 wndpl->length = sizeof(*wndpl);
1427 if( pWnd->dwStyle & WS_MINIMIZE )
1428 wndpl->showCmd = SW_SHOWMINIMIZED;
1429 else
1430 wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE )
1431 ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
1432 if( pWnd->flags & WIN_RESTORE_MAX )
1433 wndpl->flags = WPF_RESTORETOMAXIMIZED;
1434 else
1435 wndpl->flags = 0;
1436 wndpl->ptMinPosition = lpPos->ptIconPos;
1437 wndpl->ptMaxPosition = lpPos->ptMaxPos;
1438 wndpl->rcNormalPosition = lpPos->rectNormal;
1440 WIN_ReleaseWndPtr(pWnd);
1441 return TRUE;
1445 /***********************************************************************
1446 * GetWindowPlacement (USER32.307)
1448 * Win95:
1449 * Fails if wndpl->length of Win95 (!) apps is invalid.
1451 BOOL WINAPI GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *pwpl32 )
1453 if( pwpl32 )
1455 WINDOWPLACEMENT16 wpl;
1456 wpl.length = sizeof(wpl);
1457 if( GetWindowPlacement16( hwnd, &wpl ) )
1459 pwpl32->length = sizeof(*pwpl32);
1460 pwpl32->flags = wpl.flags;
1461 pwpl32->showCmd = wpl.showCmd;
1462 CONV_POINT16TO32( &wpl.ptMinPosition, &pwpl32->ptMinPosition );
1463 CONV_POINT16TO32( &wpl.ptMaxPosition, &pwpl32->ptMaxPosition );
1464 CONV_RECT16TO32( &wpl.rcNormalPosition, &pwpl32->rcNormalPosition );
1465 return TRUE;
1468 return FALSE;
1472 /***********************************************************************
1473 * WINPOS_SetPlacement
1475 static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT16 *wndpl,
1476 UINT flags )
1478 WND *pWnd = WIN_FindWndPtr( hwnd );
1479 if( pWnd )
1481 LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1482 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1484 if( flags & PLACE_MIN ) lpPos->ptIconPos = wndpl->ptMinPosition;
1485 if( flags & PLACE_MAX ) lpPos->ptMaxPos = wndpl->ptMaxPosition;
1486 if( flags & PLACE_RECT) lpPos->rectNormal = wndpl->rcNormalPosition;
1488 if( pWnd->dwStyle & WS_MINIMIZE )
1490 WINPOS_ShowIconTitle( pWnd, FALSE );
1491 if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1492 SetWindowPos( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1493 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1495 else if( pWnd->dwStyle & WS_MAXIMIZE )
1497 if( !EMPTYPOINT(lpPos->ptMaxPos) )
1498 SetWindowPos( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1499 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1501 else if( flags & PLACE_RECT )
1502 SetWindowPos( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1503 lpPos->rectNormal.right - lpPos->rectNormal.left,
1504 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1505 SWP_NOZORDER | SWP_NOACTIVATE );
1507 ShowWindow( hwnd, wndpl->showCmd );
1508 if( IsWindow(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1510 if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd, TRUE );
1512 /* SDK: ...valid only the next time... */
1513 if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1515 WIN_ReleaseWndPtr(pWnd);
1516 return TRUE;
1518 return FALSE;
1522 /***********************************************************************
1523 * SetWindowPlacement16 (USER.371)
1525 BOOL16 WINAPI SetWindowPlacement16(HWND16 hwnd, const WINDOWPLACEMENT16 *wndpl)
1527 return WINPOS_SetPlacement( hwnd, wndpl,
1528 PLACE_MIN | PLACE_MAX | PLACE_RECT );
1531 /***********************************************************************
1532 * SetWindowPlacement (USER32.519)
1534 * Win95:
1535 * Fails if wndpl->length of Win95 (!) apps is invalid.
1537 BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *pwpl32 )
1539 if( pwpl32 )
1541 WINDOWPLACEMENT16 wpl = { sizeof(WINDOWPLACEMENT16),
1542 pwpl32->flags, pwpl32->showCmd, { pwpl32->ptMinPosition.x,
1543 pwpl32->ptMinPosition.y }, { pwpl32->ptMaxPosition.x,
1544 pwpl32->ptMaxPosition.y }, { pwpl32->rcNormalPosition.left,
1545 pwpl32->rcNormalPosition.top, pwpl32->rcNormalPosition.right,
1546 pwpl32->rcNormalPosition.bottom } };
1548 return WINPOS_SetPlacement( hwnd, &wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1550 return FALSE;
1554 /***********************************************************************
1555 * SetInternalWindowPos16 (USER.461)
1557 void WINAPI SetInternalWindowPos16( HWND16 hwnd, UINT16 showCmd,
1558 LPRECT16 rect, LPPOINT16 pt )
1560 if( IsWindow16(hwnd) )
1562 WINDOWPLACEMENT16 wndpl;
1563 UINT flags;
1565 wndpl.length = sizeof(wndpl);
1566 wndpl.showCmd = showCmd;
1567 wndpl.flags = flags = 0;
1569 if( pt )
1571 flags |= PLACE_MIN;
1572 wndpl.flags |= WPF_SETMINPOSITION;
1573 wndpl.ptMinPosition = *pt;
1575 if( rect )
1577 flags |= PLACE_RECT;
1578 wndpl.rcNormalPosition = *rect;
1580 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1585 /***********************************************************************
1586 * SetInternalWindowPos (USER32.483)
1588 void WINAPI SetInternalWindowPos( HWND hwnd, UINT showCmd,
1589 LPRECT rect, LPPOINT pt )
1591 if( IsWindow(hwnd) )
1593 WINDOWPLACEMENT16 wndpl;
1594 UINT flags;
1596 wndpl.length = sizeof(wndpl);
1597 wndpl.showCmd = showCmd;
1598 wndpl.flags = flags = 0;
1600 if( pt )
1602 flags |= PLACE_MIN;
1603 wndpl.flags |= WPF_SETMINPOSITION;
1604 CONV_POINT32TO16( pt, &wndpl.ptMinPosition );
1606 if( rect )
1608 flags |= PLACE_RECT;
1609 CONV_RECT32TO16( rect, &wndpl.rcNormalPosition );
1611 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1615 /*******************************************************************
1616 * WINPOS_SetActiveWindow
1618 * SetActiveWindow() back-end. This is the only function that
1619 * can assign active status to a window. It must be called only
1620 * for the top level windows.
1622 BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
1624 CBTACTIVATESTRUCT16* cbtStruct;
1625 WND* wndPtr=0, *wndTemp;
1626 HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1627 MESSAGEQUEUE *pOldActiveQueue = 0, *pNewActiveQueue = 0;
1628 WORD wIconized = 0;
1629 HWND hwndActive = 0;
1630 BOOL bRet = 0;
1632 /* Get current active window from the active queue */
1633 if ( hActiveQueue )
1635 pOldActiveQueue = QUEUE_Lock( hActiveQueue );
1636 if ( pOldActiveQueue )
1637 hwndActive = PERQDATA_GetActiveWnd( pOldActiveQueue->pQData );
1640 /* paranoid checks */
1641 if( hWnd == GetDesktopWindow() || (bRet = (hWnd == hwndActive)) )
1642 goto CLEANUP_END;
1644 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1645 * return 0;
1647 wndPtr = WIN_FindWndPtr(hWnd);
1648 hOldActiveQueue = hActiveQueue;
1650 if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1652 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1653 WIN_ReleaseWndPtr(wndTemp);
1655 else
1656 TRACE(win,"no current active window.\n");
1658 /* call CBT hook chain */
1659 if ((cbtStruct = SEGPTR_NEW(CBTACTIVATESTRUCT16)))
1661 cbtStruct->fMouse = fMouse;
1662 cbtStruct->hWndActive = hwndActive;
1663 bRet = (BOOL)HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
1664 (LPARAM)SEGPTR_GET(cbtStruct) );
1665 SEGPTR_FREE(cbtStruct);
1666 if (bRet) goto CLEANUP_END;
1669 /* set prev active wnd to current active wnd and send notification */
1670 if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
1672 MESSAGEQUEUE *pTempActiveQueue = 0;
1674 if (!SendMessageA( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1676 if (GetSysModalWindow16() != hWnd)
1677 goto CLEANUP_END;
1678 /* disregard refusal if hWnd is sysmodal */
1681 SendMessageA( hwndPrevActive, WM_ACTIVATE,
1682 MAKEWPARAM( WA_INACTIVE, wIconized ),
1683 (LPARAM)hWnd );
1685 /* check if something happened during message processing
1686 * (global active queue may have changed)
1688 pTempActiveQueue = QUEUE_Lock( hActiveQueue );
1689 hwndActive = PERQDATA_GetActiveWnd( pTempActiveQueue->pQData );
1690 QUEUE_Unlock( pTempActiveQueue );
1691 if( hwndPrevActive != hwndActive )
1692 goto CLEANUP_END;
1695 /* Set new active window in the message queue */
1696 hwndActive = hWnd;
1697 if ( wndPtr )
1699 pNewActiveQueue = QUEUE_Lock( wndPtr->hmemTaskQ );
1700 if ( pNewActiveQueue )
1701 PERQDATA_SetActiveWnd( pNewActiveQueue->pQData, hwndActive );
1703 else /* have to do this or MDI frame activation goes to hell */
1704 if( pOldActiveQueue )
1705 PERQDATA_SetActiveWnd( pOldActiveQueue->pQData, 0 );
1707 /* send palette messages */
1708 if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1709 SendMessage16((HWND16)-1, WM_PALETTEISCHANGING, (WPARAM16)hWnd, 0L );
1711 /* if prev wnd is minimized redraw icon title */
1712 if( IsIconic( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1714 /* managed windows will get ConfigureNotify event */
1715 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->flags & WIN_MANAGED))
1717 /* check Z-order and bring hWnd to the top */
1718 for (wndTemp = WIN_LockWndPtr(WIN_GetDesktop()->child); wndTemp; WIN_UpdateWndPtr(&wndTemp,wndTemp->next))
1720 if (wndTemp->dwStyle & WS_VISIBLE) break;
1722 WIN_ReleaseDesktop();
1723 WIN_ReleaseWndPtr(wndTemp);
1725 if( wndTemp != wndPtr )
1726 SetWindowPos(hWnd, HWND_TOP, 0,0,0,0,
1727 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1728 if (!IsWindow(hWnd))
1729 goto CLEANUP;
1732 /* Get a handle to the new active queue */
1733 hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1735 /* send WM_ACTIVATEAPP if necessary */
1736 if (hOldActiveQueue != hNewActiveQueue)
1738 WND **list, **ppWnd;
1739 WND *pDesktop = WIN_GetDesktop();
1741 if ((list = WIN_BuildWinArray( pDesktop, 0, NULL )))
1743 for (ppWnd = list; *ppWnd; ppWnd++)
1745 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1747 if ((*ppWnd)->hmemTaskQ == hOldActiveQueue)
1748 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1749 0, QUEUE_GetQueueTask(hNewActiveQueue) );
1751 WIN_ReleaseWinArray(list);
1754 hActiveQueue = hNewActiveQueue;
1756 if ((list = WIN_BuildWinArray(pDesktop, 0, NULL )))
1758 for (ppWnd = list; *ppWnd; ppWnd++)
1760 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1762 if ((*ppWnd)->hmemTaskQ == hNewActiveQueue)
1763 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1764 1, QUEUE_GetQueueTask( hOldActiveQueue ) );
1766 WIN_ReleaseWinArray(list);
1768 WIN_ReleaseDesktop();
1770 if (!IsWindow(hWnd)) goto CLEANUP;
1773 if (hWnd)
1775 /* walk up to the first unowned window */
1776 wndTemp = WIN_LockWndPtr(wndPtr);
1777 while (wndTemp->owner)
1779 WIN_UpdateWndPtr(&wndTemp,wndTemp->owner);
1781 /* and set last active owned popup */
1782 wndTemp->hwndLastActive = hWnd;
1784 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1785 WIN_ReleaseWndPtr(wndTemp);
1786 SendMessageA( hWnd, WM_NCACTIVATE, TRUE, 0 );
1787 SendMessageA( hWnd, WM_ACTIVATE,
1788 MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1789 (LPARAM)hwndPrevActive );
1790 if( !IsWindow(hWnd) ) goto CLEANUP;
1793 /* change focus if possible */
1794 if( fChangeFocus && GetFocus() )
1795 if( WIN_GetTopParent(GetFocus()) != hwndActive )
1796 FOCUS_SwitchFocus( pNewActiveQueue, GetFocus(),
1797 (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
1799 hwndActive
1802 if( !hwndPrevActive && wndPtr )
1803 (*wndPtr->pDriver->pForceWindowRaise)(wndPtr);
1805 /* if active wnd is minimized redraw icon title */
1806 if( IsIconic(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1808 bRet = (hWnd == hwndActive); /* Success? */
1810 CLEANUP: /* Unlock the message queues before returning */
1812 if ( pNewActiveQueue )
1813 QUEUE_Unlock( pNewActiveQueue );
1815 CLEANUP_END:
1817 if ( pOldActiveQueue )
1818 QUEUE_Unlock( pOldActiveQueue );
1820 WIN_ReleaseWndPtr(wndPtr);
1821 return bRet;
1824 /*******************************************************************
1825 * WINPOS_ActivateOtherWindow
1827 * Activates window other than pWnd.
1829 BOOL WINPOS_ActivateOtherWindow(WND* pWnd)
1831 BOOL bRet = 0;
1832 WND* pWndTo = NULL;
1833 HWND hwndActive = 0;
1835 /* Get current active window from the active queue */
1836 if ( hActiveQueue )
1838 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1839 if ( pActiveQueue )
1841 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1842 QUEUE_Unlock( pActiveQueue );
1846 if( pWnd->hwndSelf == hwndPrevActive )
1847 hwndPrevActive = 0;
1849 if( hwndActive != pWnd->hwndSelf &&
1850 ( hwndActive || QUEUE_IsExitingQueue(pWnd->hmemTaskQ)) )
1851 return 0;
1853 if( !(pWnd->dwStyle & WS_POPUP) || !(pWnd->owner) ||
1854 !WINPOS_CanActivate((pWndTo = WIN_GetTopParentPtr(pWnd->owner))) )
1856 WND* pWndPtr = WIN_GetTopParentPtr(pWnd);
1858 pWndTo = WIN_FindWndPtr(hwndPrevActive);
1860 while( !WINPOS_CanActivate(pWndTo) )
1862 /* by now owned windows should've been taken care of */
1863 WIN_UpdateWndPtr(&pWndTo,pWndPtr->next);
1864 WIN_UpdateWndPtr(&pWndPtr,pWndTo);
1865 if( !pWndTo ) break;
1867 WIN_ReleaseWndPtr(pWndPtr);
1870 bRet = WINPOS_SetActiveWindow( pWndTo ? pWndTo->hwndSelf : 0, FALSE, TRUE );
1872 /* switch desktop queue to current active */
1873 if( pWndTo )
1875 WIN_GetDesktop()->hmemTaskQ = pWndTo->hmemTaskQ;
1876 WIN_ReleaseWndPtr(pWndTo);
1877 WIN_ReleaseDesktop();
1880 hwndPrevActive = 0;
1881 return bRet;
1884 /*******************************************************************
1885 * WINPOS_ChangeActiveWindow
1888 BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
1890 WND *wndPtr, *wndTemp;
1891 BOOL retvalue;
1892 HWND hwndActive = 0;
1894 /* Get current active window from the active queue */
1895 if ( hActiveQueue )
1897 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1898 if ( pActiveQueue )
1900 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1901 QUEUE_Unlock( pActiveQueue );
1905 if (!hWnd)
1906 return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
1908 wndPtr = WIN_FindWndPtr(hWnd);
1909 if( !wndPtr ) return FALSE;
1911 /* child windows get WM_CHILDACTIVATE message */
1912 if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
1914 retvalue = SendMessageA(hWnd, WM_CHILDACTIVATE, 0, 0L);
1915 goto end;
1918 if( hWnd == hwndActive )
1920 retvalue = FALSE;
1921 goto end;
1924 if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
1926 retvalue = FALSE;
1927 goto end;
1930 /* switch desktop queue to current active */
1931 wndTemp = WIN_GetDesktop();
1932 if( wndPtr->parent == wndTemp)
1933 wndTemp->hmemTaskQ = wndPtr->hmemTaskQ;
1934 WIN_ReleaseDesktop();
1936 retvalue = TRUE;
1937 end:
1938 WIN_ReleaseWndPtr(wndPtr);
1939 return retvalue;
1943 /***********************************************************************
1944 * WINPOS_SendNCCalcSize
1946 * Send a WM_NCCALCSIZE message to a window.
1947 * All parameters are read-only except newClientRect.
1948 * oldWindowRect, oldClientRect and winpos must be non-NULL only
1949 * when calcValidRect is TRUE.
1951 LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect,
1952 RECT *newWindowRect, RECT *oldWindowRect,
1953 RECT *oldClientRect, WINDOWPOS *winpos,
1954 RECT *newClientRect )
1956 NCCALCSIZE_PARAMS params;
1957 WINDOWPOS winposCopy;
1958 LONG result;
1960 params.rgrc[0] = *newWindowRect;
1961 if (calcValidRect)
1963 winposCopy = *winpos;
1964 params.rgrc[1] = *oldWindowRect;
1965 params.rgrc[2] = *oldClientRect;
1966 params.lppos = &winposCopy;
1968 result = SendMessageA( hwnd, WM_NCCALCSIZE, calcValidRect,
1969 (LPARAM)&params );
1970 TRACE(win, "%d,%d-%d,%d\n",
1971 params.rgrc[0].left, params.rgrc[0].top,
1972 params.rgrc[0].right, params.rgrc[0].bottom );
1973 *newClientRect = params.rgrc[0];
1974 return result;
1978 /***********************************************************************
1979 * WINPOS_HandleWindowPosChanging16
1981 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
1983 LONG WINPOS_HandleWindowPosChanging16( WND *wndPtr, WINDOWPOS16 *winpos )
1985 POINT maxSize, minTrack;
1986 if (winpos->flags & SWP_NOSIZE) return 0;
1987 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
1988 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
1990 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
1991 if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
1992 if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
1993 if (!(wndPtr->dwStyle & WS_MINIMIZE))
1995 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
1996 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
1999 return 0;
2003 /***********************************************************************
2004 * WINPOS_HandleWindowPosChanging
2006 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2008 LONG WINPOS_HandleWindowPosChanging( WND *wndPtr, WINDOWPOS *winpos )
2010 POINT maxSize;
2011 if (winpos->flags & SWP_NOSIZE) return 0;
2012 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2013 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2015 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, NULL, NULL );
2016 winpos->cx = MIN( winpos->cx, maxSize.x );
2017 winpos->cy = MIN( winpos->cy, maxSize.y );
2019 return 0;
2022 /***********************************************************************
2023 * SWP_DoOwnedPopups
2025 * fix Z order taking into account owned popups -
2026 * basically we need to maintain them above the window that owns them
2028 * FIXME: hide/show owned popups when owner visibility changes.
2030 static HWND SWP_DoOwnedPopups(WND* pDesktop, WND* wndPtr, HWND hwndInsertAfter, WORD flags)
2032 WND* w = WIN_LockWndPtr(pDesktop->child);
2034 WARN(win, "(%04x) hInsertAfter = %04x\n", wndPtr->hwndSelf, hwndInsertAfter );
2036 if( (wndPtr->dwStyle & WS_POPUP) && wndPtr->owner )
2038 /* make sure this popup stays above the owner */
2040 HWND hwndLocalPrev = HWND_TOP;
2042 if( hwndInsertAfter != HWND_TOP )
2044 while( w != wndPtr->owner )
2046 if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
2047 if( hwndLocalPrev == hwndInsertAfter ) break;
2048 WIN_UpdateWndPtr(&w,w->next);
2050 hwndInsertAfter = hwndLocalPrev;
2053 else if( wndPtr->dwStyle & WS_CHILD )
2054 goto END;
2056 WIN_UpdateWndPtr(&w, pDesktop->child);
2058 while( w )
2060 if( w == wndPtr ) break;
2062 if( (w->dwStyle & WS_POPUP) && w->owner == wndPtr )
2064 SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0,
2065 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
2066 hwndInsertAfter = w->hwndSelf;
2068 WIN_UpdateWndPtr(&w, w->next);
2071 END:
2072 WIN_ReleaseWndPtr(w);
2073 return hwndInsertAfter;
2076 /***********************************************************************
2077 * SWP_CopyValidBits
2079 * Make window look nice without excessive repainting
2081 * visible and update regions are in window coordinates
2082 * client and window rectangles are in parent client coordinates
2084 * FIXME: SWP_EX_PAINTSELF in uFlags works only if both old and new
2085 * window rects have the same origin.
2087 * Returns: uFlags and a dirty region in *pVisRgn.
2089 static UINT SWP_CopyValidBits( WND* Wnd, HRGN* pVisRgn,
2090 LPRECT lpOldWndRect,
2091 LPRECT lpOldClientRect, UINT uFlags )
2093 RECT r;
2094 HRGN newVisRgn, dirtyRgn;
2095 INT my = COMPLEXREGION;
2097 TRACE(win,"\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2098 Wnd->rectWindow.left, Wnd->rectWindow.top,
2099 Wnd->rectWindow.right, Wnd->rectWindow.bottom,
2100 lpOldWndRect->left, lpOldWndRect->top,
2101 lpOldWndRect->right, lpOldWndRect->bottom, *pVisRgn);
2102 TRACE(win,"\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2103 Wnd->rectClient.left, Wnd->rectClient.top,
2104 Wnd->rectClient.right, Wnd->rectClient.bottom,
2105 lpOldClientRect->left, lpOldClientRect->top,
2106 lpOldClientRect->right,lpOldClientRect->bottom );
2108 if( Wnd->hrgnUpdate == 1 )
2109 uFlags |= SWP_EX_NOCOPY; /* whole window is invalid, nothing to copy */
2111 newVisRgn = DCE_GetVisRgn( Wnd->hwndSelf, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
2112 dirtyRgn = CreateRectRgn( 0, 0, 0, 0 );
2114 if( !(uFlags & SWP_EX_NOCOPY) ) /* make sure dst region covers only valid bits */
2115 my = CombineRgn( dirtyRgn, newVisRgn, *pVisRgn, RGN_AND );
2117 if( (my == NULLREGION) || (uFlags & SWP_EX_NOCOPY) )
2119 nocopy:
2121 TRACE(win,"\twon't copy anything!\n");
2123 /* set dirtyRgn to the sum of old and new visible regions
2124 * in parent client coordinates */
2126 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2127 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2129 CombineRgn(*pVisRgn, *pVisRgn, newVisRgn, RGN_OR );
2131 else /* copy valid bits to a new location */
2133 INT dx, dy, ow, oh, nw, nh, ocw, ncw, och, nch;
2134 HRGN hrgnValid = dirtyRgn; /* non-empty intersection of old and new visible rgns */
2136 /* subtract already invalid region inside Wnd from the dst region */
2138 if( Wnd->hrgnUpdate )
2139 if( CombineRgn( hrgnValid, hrgnValid, Wnd->hrgnUpdate, RGN_DIFF) == NULLREGION )
2140 goto nocopy;
2142 /* check if entire window can be copied */
2144 ow = lpOldWndRect->right - lpOldWndRect->left;
2145 oh = lpOldWndRect->bottom - lpOldWndRect->top;
2146 nw = Wnd->rectWindow.right - Wnd->rectWindow.left;
2147 nh = Wnd->rectWindow.bottom - Wnd->rectWindow.top;
2149 ocw = lpOldClientRect->right - lpOldClientRect->left;
2150 och = lpOldClientRect->bottom - lpOldClientRect->top;
2151 ncw = Wnd->rectClient.right - Wnd->rectClient.left;
2152 nch = Wnd->rectClient.bottom - Wnd->rectClient.top;
2154 if( (ocw != ncw) || (och != nch) ||
2155 ( ow != nw) || ( oh != nw) ||
2156 ((lpOldClientRect->top - lpOldWndRect->top) !=
2157 (Wnd->rectClient.top - Wnd->rectWindow.top)) ||
2158 ((lpOldClientRect->left - lpOldWndRect->left) !=
2159 (Wnd->rectClient.left - Wnd->rectWindow.left)) )
2161 dx = Wnd->rectClient.left - lpOldClientRect->left;
2162 dy = Wnd->rectClient.top - lpOldClientRect->top;
2164 /* restrict valid bits to the common client rect */
2166 r.left = Wnd->rectClient.left - Wnd->rectWindow.left;
2167 r.top = Wnd->rectClient.top - Wnd->rectWindow.top;
2168 r.right = r.left + MIN( ocw, ncw );
2169 r.bottom = r.top + MIN( och, nch );
2171 REGION_CropRgn( hrgnValid, hrgnValid, &r,
2172 (uFlags & SWP_EX_PAINTSELF) ? NULL : (POINT*)&(Wnd->rectWindow));
2173 GetRgnBox( hrgnValid, &r );
2174 if( IsRectEmpty( &r ) )
2175 goto nocopy;
2176 r = *lpOldClientRect;
2178 else
2180 dx = Wnd->rectWindow.left - lpOldWndRect->left;
2181 dy = Wnd->rectWindow.top - lpOldWndRect->top;
2182 if( !(uFlags & SWP_EX_PAINTSELF) )
2183 OffsetRgn( hrgnValid, Wnd->rectWindow.left, Wnd->rectWindow.top );
2184 r = *lpOldWndRect;
2187 if( !(uFlags & SWP_EX_PAINTSELF) )
2189 /* Move remaining regions to parent coordinates */
2190 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2191 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2193 else
2194 OffsetRect( &r, -lpOldWndRect->left, -lpOldWndRect->top );
2196 TRACE(win,"\tcomputing dirty region!\n");
2198 /* Compute combined dirty region (old + new - valid) */
2199 CombineRgn( *pVisRgn, *pVisRgn, newVisRgn, RGN_OR);
2200 CombineRgn( *pVisRgn, *pVisRgn, hrgnValid, RGN_DIFF);
2202 /* Blt valid bits, r is the rect to copy */
2204 if( dx || dy )
2206 DC* dc;
2207 HDC hDC = ( uFlags & SWP_EX_PAINTSELF)
2208 ? GetDCEx( Wnd->hwndSelf, hrgnValid, DCX_WINDOW | DCX_CACHE |
2209 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS )
2210 : GetDCEx( Wnd->parent->hwndSelf, hrgnValid, DCX_CACHE |
2211 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2212 if( (dc = (DC *)GDI_GetObjPtr(hDC, DC_MAGIC)) )
2214 if( oh > nh ) r.bottom = r.top + nh;
2215 if( ow < nw ) r.right = r.left + nw;
2217 Wnd->pDriver->pSurfaceCopy( Wnd->parent, dc, dx, dy, &r, TRUE );
2219 GDI_HEAP_UNLOCK( hDC );
2221 ReleaseDC( (uFlags & SWP_EX_PAINTSELF) ?
2222 Wnd->hwndSelf : Wnd->parent->hwndSelf, hDC);
2226 /* *pVisRgn now points to the invalidated region */
2228 DeleteObject(newVisRgn);
2229 DeleteObject(dirtyRgn);
2230 return uFlags;
2233 /***********************************************************************
2234 * SWP_DoSimpleFrameChanged
2236 * NOTE: old and new client rect origins are identical, only
2237 * extents may have changed. Window extents are the same.
2239 static void SWP_DoSimpleFrameChanged( WND* wndPtr, RECT* pOldClientRect, WORD swpFlags, UINT uFlags )
2241 INT i = 0;
2242 RECT rect;
2243 HRGN hrgn = 0;
2245 if( !(swpFlags & SWP_NOCLIENTSIZE) )
2247 /* FIXME: WVR alignment flags */
2249 if( wndPtr->rectClient.right > pOldClientRect->right ) /* right edge */
2251 i++;
2252 rect.top = 0;
2253 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2254 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2255 if(!(uFlags & SWP_EX_NOCOPY))
2256 rect.left = pOldClientRect->right - wndPtr->rectClient.left;
2257 else
2259 rect.left = 0;
2260 goto redraw;
2264 if( wndPtr->rectClient.bottom > pOldClientRect->bottom ) /* bottom edge */
2266 if( i )
2267 hrgn = CreateRectRgnIndirect( &rect );
2268 rect.left = 0;
2269 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2270 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2271 if(!(uFlags & SWP_EX_NOCOPY))
2272 rect.top = pOldClientRect->bottom - wndPtr->rectClient.top;
2273 else
2274 rect.top = 0;
2275 if( i++ )
2276 REGION_UnionRectWithRgn( hrgn, &rect );
2279 if( i == 0 && (uFlags & SWP_EX_NOCOPY) ) /* force redraw anyway */
2281 rect = wndPtr->rectWindow;
2282 OffsetRect( &rect, wndPtr->rectWindow.left - wndPtr->rectClient.left,
2283 wndPtr->rectWindow.top - wndPtr->rectClient.top );
2284 i++;
2288 if( i )
2290 redraw:
2291 PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
2292 RDW_ERASENOW | RDW_ALLCHILDREN, RDW_EX_TOPFRAME | RDW_EX_USEHRGN );
2294 else
2295 hrgn = WIN_UpdateNCRgn(wndPtr, TRUE, TRUE);
2297 if( hrgn > 1 )
2298 DeleteObject( hrgn );
2301 /***********************************************************************
2302 * SWP_DoWinPosChanging
2304 static BOOL SWP_DoWinPosChanging( WND* wndPtr, WINDOWPOS* pWinpos,
2305 RECT* pNewWindowRect, RECT* pNewClientRect )
2307 /* Send WM_WINDOWPOSCHANGING message */
2309 if (!(pWinpos->flags & SWP_NOSENDCHANGING))
2310 SendMessageA( wndPtr->hwndSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM)pWinpos );
2312 /* Calculate new position and size */
2314 *pNewWindowRect = wndPtr->rectWindow;
2315 *pNewClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
2316 : wndPtr->rectClient;
2318 if (!(pWinpos->flags & SWP_NOSIZE))
2320 pNewWindowRect->right = pNewWindowRect->left + pWinpos->cx;
2321 pNewWindowRect->bottom = pNewWindowRect->top + pWinpos->cy;
2323 if (!(pWinpos->flags & SWP_NOMOVE))
2325 pNewWindowRect->left = pWinpos->x;
2326 pNewWindowRect->top = pWinpos->y;
2327 pNewWindowRect->right += pWinpos->x - wndPtr->rectWindow.left;
2328 pNewWindowRect->bottom += pWinpos->y - wndPtr->rectWindow.top;
2330 OffsetRect( pNewClientRect, pWinpos->x - wndPtr->rectWindow.left,
2331 pWinpos->y - wndPtr->rectWindow.top );
2334 pWinpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
2335 return TRUE;
2338 /***********************************************************************
2339 * SWP_DoNCCalcSize
2341 static UINT SWP_DoNCCalcSize( WND* wndPtr, WINDOWPOS* pWinpos,
2342 RECT* pNewWindowRect, RECT* pNewClientRect, WORD f)
2344 UINT wvrFlags = 0;
2346 /* Send WM_NCCALCSIZE message to get new client area */
2347 if( (pWinpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
2349 wvrFlags = WINPOS_SendNCCalcSize( pWinpos->hwnd, TRUE, pNewWindowRect,
2350 &wndPtr->rectWindow, &wndPtr->rectClient,
2351 pWinpos, pNewClientRect );
2353 /* FIXME: WVR_ALIGNxxx */
2355 if( pNewClientRect->left != wndPtr->rectClient.left ||
2356 pNewClientRect->top != wndPtr->rectClient.top )
2357 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2359 if( (pNewClientRect->right - pNewClientRect->left !=
2360 wndPtr->rectClient.right - wndPtr->rectClient.left) ||
2361 (pNewClientRect->bottom - pNewClientRect->top !=
2362 wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
2363 pWinpos->flags &= ~SWP_NOCLIENTSIZE;
2365 else
2366 if( !(f & SWP_NOMOVE) && (pNewClientRect->left != wndPtr->rectClient.left ||
2367 pNewClientRect->top != wndPtr->rectClient.top) )
2368 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2369 return wvrFlags;
2372 /***********************************************************************
2373 * SetWindowPos (USER.2)
2375 BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
2376 INT16 x, INT16 y, INT16 cx, INT16 cy, WORD flags)
2378 return SetWindowPos(hwnd,(INT)(INT16)hwndInsertAfter,x,y,cx,cy,flags);
2381 /***********************************************************************
2382 * SetWindowPos (USER32.520)
2384 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
2385 INT x, INT y, INT cx, INT cy, WORD flags)
2387 WINDOWPOS winpos;
2388 WND * wndPtr,*wndTemp;
2389 RECT newWindowRect, newClientRect;
2390 RECT oldWindowRect, oldClientRect;
2391 HRGN visRgn = 0;
2392 UINT wvrFlags = 0, uFlags = 0;
2393 BOOL retvalue, resync = FALSE;
2394 HWND hwndActive = 0;
2396 /* Get current active window from the active queue */
2397 if ( hActiveQueue )
2399 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2400 if ( pActiveQueue )
2402 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2403 QUEUE_Unlock( pActiveQueue );
2407 TRACE(win,"hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2408 hwnd, x, y, x+cx, y+cy, flags);
2410 /* ------------------------------------------------------------------------ CHECKS */
2412 /* Check window handle */
2414 if (hwnd == GetDesktopWindow()) return FALSE;
2415 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2417 TRACE(win,"\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr->rectWindow.left, wndPtr->rectWindow.top,
2418 wndPtr->rectWindow.right, wndPtr->rectWindow.bottom, (unsigned)wndPtr->dwStyle );
2420 /* Fix redundant flags */
2422 if(wndPtr->dwStyle & WS_VISIBLE)
2423 flags &= ~SWP_SHOWWINDOW;
2424 else
2426 if (!(flags & SWP_SHOWWINDOW))
2427 flags |= SWP_NOREDRAW;
2428 flags &= ~SWP_HIDEWINDOW;
2431 if ( cx < 0 ) cx = 0; if( cy < 0 ) cy = 0;
2433 if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
2434 (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
2435 flags |= SWP_NOSIZE; /* Already the right size */
2437 if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
2438 flags |= SWP_NOMOVE; /* Already the right position */
2440 if (hwnd == hwndActive)
2441 flags |= SWP_NOACTIVATE; /* Already active */
2442 else
2444 if(!(flags & SWP_NOACTIVATE)) /* Bring to the top when activating */
2446 flags &= ~SWP_NOZORDER;
2447 hwndInsertAfter = HWND_TOP;
2448 goto Pos;
2452 /* Check hwndInsertAfter */
2454 /* FIXME: TOPMOST not supported yet */
2455 if ((hwndInsertAfter == HWND_TOPMOST) ||
2456 (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
2458 /* hwndInsertAfter must be a sibling of the window */
2459 if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
2461 WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
2463 if( wnd ) {
2464 if( wnd->parent != wndPtr->parent )
2466 retvalue = FALSE;
2467 WIN_ReleaseWndPtr(wnd);
2468 goto END;
2470 if( wnd->next == wndPtr ) flags |= SWP_NOZORDER;
2472 WIN_ReleaseWndPtr(wnd);
2475 Pos: /* ------------------------------------------------------------------------ MAIN part */
2477 /* Fill the WINDOWPOS structure */
2479 winpos.hwnd = hwnd;
2480 winpos.hwndInsertAfter = hwndInsertAfter;
2481 winpos.x = x;
2482 winpos.y = y;
2483 winpos.cx = cx;
2484 winpos.cy = cy;
2485 winpos.flags = flags;
2487 SWP_DoWinPosChanging( wndPtr, &winpos, &newWindowRect, &newClientRect );
2489 if((winpos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER)
2491 if( wndPtr->parent == WIN_GetDesktop() )
2492 hwndInsertAfter = SWP_DoOwnedPopups( wndPtr->parent, wndPtr,
2493 hwndInsertAfter, winpos.flags );
2494 WIN_ReleaseDesktop();
2497 if(!(wndPtr->flags & WIN_NATIVE) )
2499 if( hwndInsertAfter == HWND_TOP )
2500 winpos.flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
2501 else
2502 if( hwndInsertAfter == HWND_BOTTOM )
2503 winpos.flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
2504 else
2505 if( !(winpos.flags & SWP_NOZORDER) )
2506 if( GetWindow(hwndInsertAfter, GW_HWNDNEXT) == wndPtr->hwndSelf )
2507 winpos.flags |= SWP_NOZORDER;
2509 if( !(winpos.flags & SWP_NOREDRAW) &&
2510 ((winpos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW | SWP_FRAMECHANGED))
2511 != (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)) )
2513 /* get a previous visible region for SWP_CopyValidBits() */
2515 visRgn = DCE_GetVisRgn(hwnd, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
2519 /* Common operations */
2521 wvrFlags = SWP_DoNCCalcSize( wndPtr, &winpos, &newWindowRect, &newClientRect, flags );
2523 if(!(winpos.flags & SWP_NOZORDER))
2525 WIN_UnlinkWindow( winpos.hwnd );
2526 WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
2529 /* Reset active DCEs */
2531 if( (((winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) &&
2532 wndPtr->dwStyle & WS_VISIBLE) ||
2533 (flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
2535 RECT rect;
2537 UnionRect(&rect, &newWindowRect, &wndPtr->rectWindow);
2538 DCE_InvalidateDCE(wndPtr, &rect);
2541 oldWindowRect = wndPtr->rectWindow;
2542 oldClientRect = wndPtr->rectClient;
2544 /* Find out if we have to redraw the whole client rect */
2546 if( oldClientRect.bottom - oldClientRect.top ==
2547 newClientRect.bottom - newClientRect.top ) wvrFlags &= ~WVR_VREDRAW;
2549 if( oldClientRect.right - oldClientRect.left ==
2550 newClientRect.right - newClientRect.left ) wvrFlags &= ~WVR_HREDRAW;
2552 uFlags |= ((winpos.flags & SWP_NOCOPYBITS) ||
2553 (!(winpos.flags & SWP_NOCLIENTSIZE) &&
2554 (wvrFlags >= WVR_HREDRAW) && (wvrFlags < WVR_VALIDRECTS))) ? SWP_EX_NOCOPY : 0;
2556 /* FIXME: actually do something with WVR_VALIDRECTS */
2558 wndPtr->rectWindow = newWindowRect;
2559 wndPtr->rectClient = newClientRect;
2561 if (wndPtr->flags & WIN_NATIVE) /* -------------------------------------------- hosted window */
2563 BOOL bCallDriver = TRUE;
2564 HWND tempInsertAfter = winpos.hwndInsertAfter;
2566 winpos.hwndInsertAfter = hwndInsertAfter;
2568 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2570 /* This is the only place where we need to force repainting of the contents
2571 of windows created by the host window system, all other cases go through the
2572 expose event handling */
2574 if( (winpos.flags & SWP_FRAMECHANGED) )
2576 INT x, y;
2578 if( (x = (newWindowRect.right - newWindowRect.left)) == (oldWindowRect.right - oldWindowRect.left) &&
2579 (y = (newWindowRect.bottom - newWindowRect.top)) == (oldWindowRect.bottom - oldWindowRect.top) )
2582 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, TRUE);
2583 winpos.hwndInsertAfter = tempInsertAfter;
2584 bCallDriver = FALSE;
2586 if( winpos.flags & SWP_NOCLIENTMOVE )
2587 SWP_DoSimpleFrameChanged(wndPtr, &oldClientRect, winpos.flags, uFlags );
2588 else
2590 /* client area moved but window extents remained the same, copy valid bits */
2592 visRgn = CreateRectRgn( 0, 0, x, y );
2593 uFlags = SWP_CopyValidBits( wndPtr, &visRgn, &oldWindowRect, &oldClientRect,
2594 uFlags | SWP_EX_PAINTSELF );
2600 if( bCallDriver )
2602 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2604 if( (oldClientRect.left - oldWindowRect.left == newClientRect.left - newWindowRect.left) &&
2605 (oldClientRect.top - oldWindowRect.top == newClientRect.top - newWindowRect.top) &&
2606 !(uFlags & SWP_EX_NOCOPY) )
2608 /* The origin of the client rect didn't move so we can try to repaint
2609 * only the nonclient area by setting bit gravity hint for the host window system.
2612 if( !(wndPtr->flags & WIN_MANAGED) )
2614 HRGN hrgn = CreateRectRgn( 0, 0, newWindowRect.right - newWindowRect.left,
2615 newWindowRect.bottom - newWindowRect.top);
2616 RECT rcn = newClientRect;
2617 RECT rco = oldClientRect;
2619 OffsetRect( &rcn, -newWindowRect.left, -newWindowRect.top );
2620 OffsetRect( &rco, -oldWindowRect.left, -oldWindowRect.top );
2621 IntersectRect( &rcn, &rcn, &rco );
2622 visRgn = CreateRectRgnIndirect( &rcn );
2623 CombineRgn( visRgn, hrgn, visRgn, RGN_DIFF );
2624 DeleteObject( hrgn );
2625 uFlags = SWP_EX_PAINTSELF;
2627 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGNorthWest );
2629 else
2630 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGForget );
2632 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, TRUE);
2633 winpos.hwndInsertAfter = tempInsertAfter;
2636 if( winpos.flags & SWP_SHOWWINDOW )
2638 HWND focus, curr;
2640 wndPtr->dwStyle |= WS_VISIBLE;
2642 if (wndPtr->flags & WIN_MANAGED) resync = TRUE;
2644 /* focus was set to unmapped window, reset host focus
2645 * since the window is now visible */
2647 focus = curr = GetFocus();
2648 while (curr)
2650 if (curr == hwnd)
2652 WND *pFocus = WIN_FindWndPtr( focus );
2653 if (pFocus)
2654 pFocus->pDriver->pSetFocus(pFocus);
2655 WIN_ReleaseWndPtr(pFocus);
2656 break;
2658 curr = GetParent(curr);
2662 else /* -------------------------------------------- emulated window */
2664 if( winpos.flags & SWP_SHOWWINDOW )
2666 wndPtr->dwStyle |= WS_VISIBLE;
2667 uFlags |= SWP_EX_PAINTSELF;
2668 visRgn = 1; /* redraw the whole window */
2670 else if( !(winpos.flags & SWP_NOREDRAW) )
2672 if( winpos.flags & SWP_HIDEWINDOW )
2674 if( visRgn > 1 ) /* map to parent */
2675 OffsetRgn( visRgn, oldWindowRect.left, oldWindowRect.top );
2676 else
2677 visRgn = 0;
2679 else
2681 if( (winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE )
2682 uFlags = SWP_CopyValidBits(wndPtr, &visRgn, &oldWindowRect,
2683 &oldClientRect, uFlags);
2684 else
2686 /* nothing moved, redraw frame if needed */
2688 if( winpos.flags & SWP_FRAMECHANGED )
2689 SWP_DoSimpleFrameChanged( wndPtr, &oldClientRect, winpos.flags, uFlags );
2690 if( visRgn )
2692 DeleteObject( visRgn );
2693 visRgn = 0;
2700 if( winpos.flags & SWP_HIDEWINDOW )
2702 wndPtr->dwStyle &= ~WS_VISIBLE;
2704 if (hwnd == CARET_GetHwnd()) DestroyCaret();
2706 /* FIXME: This will cause the window to be activated irrespective
2707 * of whether it is owned by the same thread. Has to be done
2708 * asynchronously.
2711 if (winpos.hwnd == hwndActive)
2712 WINPOS_ActivateOtherWindow( wndPtr );
2715 /* ------------------------------------------------------------------------ FINAL */
2717 if (wndPtr->flags & WIN_NATIVE)
2718 EVENT_Synchronize(); /* Synchronize with the host window system */
2720 if (!GetCapture() && ((wndPtr->dwStyle & WS_VISIBLE) || (flags & SWP_HIDEWINDOW)))
2721 EVENT_DummyMotionNotify(); /* Simulate a mouse event to set the cursor */
2723 wndTemp = WIN_GetDesktop();
2725 /* repaint invalidated region (if any)
2727 * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2728 * and force update after ChangeActiveWindow() to avoid painting frames twice.
2731 if( visRgn )
2733 if( !(winpos.flags & SWP_NOREDRAW) )
2735 if( uFlags & SWP_EX_PAINTSELF )
2737 PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn, RDW_ERASE | RDW_FRAME |
2738 ((winpos.flags & SWP_DEFERERASE) ? 0 : RDW_ERASENOW) | RDW_INVALIDATE |
2739 RDW_ALLCHILDREN, RDW_EX_XYWINDOW | RDW_EX_USEHRGN );
2741 else
2743 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn, RDW_ERASE |
2744 ((winpos.flags & SWP_DEFERERASE) ? 0 : RDW_ERASENOW) | RDW_INVALIDATE |
2745 RDW_ALLCHILDREN, RDW_EX_USEHRGN );
2748 if( visRgn != 1 )
2749 DeleteObject( visRgn );
2752 WIN_ReleaseDesktop();
2754 if (!(flags & SWP_NOACTIVATE))
2755 WINPOS_ChangeActiveWindow( winpos.hwnd, FALSE );
2757 /* And last, send the WM_WINDOWPOSCHANGED message */
2759 TRACE(win,"\tstatus flags = %04x\n", winpos.flags & SWP_AGG_STATUSFLAGS);
2761 if ( resync ||
2762 (((winpos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) &&
2763 !(winpos.flags & SWP_NOSENDCHANGING)) )
2765 SendMessageA( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
2766 if (resync) EVENT_Synchronize ();
2769 retvalue = TRUE;
2770 END:
2771 WIN_ReleaseWndPtr(wndPtr);
2772 return retvalue;
2776 /***********************************************************************
2777 * BeginDeferWindowPos16 (USER.259)
2779 HDWP16 WINAPI BeginDeferWindowPos16( INT16 count )
2781 return BeginDeferWindowPos( count );
2785 /***********************************************************************
2786 * BeginDeferWindowPos (USER32.9)
2788 HDWP WINAPI BeginDeferWindowPos( INT count )
2790 HDWP handle;
2791 DWP *pDWP;
2793 if (count <= 0) return 0;
2794 handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
2795 if (!handle) return 0;
2796 pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
2797 pDWP->actualCount = 0;
2798 pDWP->suggestedCount = count;
2799 pDWP->valid = TRUE;
2800 pDWP->wMagic = DWP_MAGIC;
2801 pDWP->hwndParent = 0;
2802 return handle;
2806 /***********************************************************************
2807 * DeferWindowPos16 (USER.260)
2809 HDWP16 WINAPI DeferWindowPos16( HDWP16 hdwp, HWND16 hwnd, HWND16 hwndAfter,
2810 INT16 x, INT16 y, INT16 cx, INT16 cy,
2811 UINT16 flags )
2813 return DeferWindowPos( hdwp, hwnd, (INT)(INT16)hwndAfter,
2814 x, y, cx, cy, flags );
2818 /***********************************************************************
2819 * DeferWindowPos (USER32.128)
2821 HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter,
2822 INT x, INT y, INT cx, INT cy,
2823 UINT flags )
2825 DWP *pDWP;
2826 int i;
2827 HDWP newhdwp = hdwp,retvalue;
2828 /* HWND parent; */
2829 WND *pWnd;
2831 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
2832 if (!pDWP) return 0;
2833 if (hwnd == GetDesktopWindow()) return 0;
2835 if (!(pWnd=WIN_FindWndPtr( hwnd ))) {
2836 USER_HEAP_FREE( hdwp );
2837 return 0;
2840 /* Numega Bounds Checker Demo dislikes the following code.
2841 In fact, I've not been able to find any "same parent" requirement in any docu
2842 [AM 980509]
2844 #if 0
2845 /* All the windows of a DeferWindowPos() must have the same parent */
2846 parent = pWnd->parent->hwndSelf;
2847 if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
2848 else if (parent != pDWP->hwndParent)
2850 USER_HEAP_FREE( hdwp );
2851 retvalue = 0;
2852 goto END;
2854 #endif
2856 for (i = 0; i < pDWP->actualCount; i++)
2858 if (pDWP->winPos[i].hwnd == hwnd)
2860 /* Merge with the other changes */
2861 if (!(flags & SWP_NOZORDER))
2863 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
2865 if (!(flags & SWP_NOMOVE))
2867 pDWP->winPos[i].x = x;
2868 pDWP->winPos[i].y = y;
2870 if (!(flags & SWP_NOSIZE))
2872 pDWP->winPos[i].cx = cx;
2873 pDWP->winPos[i].cy = cy;
2875 pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
2876 SWP_NOZORDER | SWP_NOREDRAW |
2877 SWP_NOACTIVATE | SWP_NOCOPYBITS|
2878 SWP_NOOWNERZORDER);
2879 pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
2880 SWP_FRAMECHANGED);
2881 retvalue = hdwp;
2882 goto END;
2885 if (pDWP->actualCount >= pDWP->suggestedCount)
2887 newhdwp = USER_HEAP_REALLOC( hdwp,
2888 sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
2889 if (!newhdwp)
2891 retvalue = 0;
2892 goto END;
2894 pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
2895 pDWP->suggestedCount++;
2897 pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
2898 pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
2899 pDWP->winPos[pDWP->actualCount].x = x;
2900 pDWP->winPos[pDWP->actualCount].y = y;
2901 pDWP->winPos[pDWP->actualCount].cx = cx;
2902 pDWP->winPos[pDWP->actualCount].cy = cy;
2903 pDWP->winPos[pDWP->actualCount].flags = flags;
2904 pDWP->actualCount++;
2905 retvalue = newhdwp;
2906 END:
2907 WIN_ReleaseWndPtr(pWnd);
2908 return retvalue;
2912 /***********************************************************************
2913 * EndDeferWindowPos16 (USER.261)
2915 BOOL16 WINAPI EndDeferWindowPos16( HDWP16 hdwp )
2917 return EndDeferWindowPos( hdwp );
2921 /***********************************************************************
2922 * EndDeferWindowPos (USER32.173)
2924 BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
2926 DWP *pDWP;
2927 WINDOWPOS *winpos;
2928 BOOL res = TRUE;
2929 int i;
2931 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
2932 if (!pDWP) return FALSE;
2933 for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
2935 if (!(res = SetWindowPos( winpos->hwnd, winpos->hwndInsertAfter,
2936 winpos->x, winpos->y, winpos->cx,
2937 winpos->cy, winpos->flags ))) break;
2939 USER_HEAP_FREE( hdwp );
2940 return res;
2944 /***********************************************************************
2945 * TileChildWindows (USER.199)
2947 void WINAPI TileChildWindows16( HWND16 parent, WORD action )
2949 FIXME(win, "(%04x, %d): stub\n", parent, action);
2952 /***********************************************************************
2953 * CascageChildWindows (USER.198)
2955 void WINAPI CascadeChildWindows16( HWND16 parent, WORD action )
2957 FIXME(win, "(%04x, %d): stub\n", parent, action);
2959 /***********************************************************************
2960 * GetProgmanWindow [USER32.289]
2962 HRESULT WINAPI GetProgmanWindow ( )
2963 { FIXME(win,"stub\n");
2964 return 0;
2966 /***********************************************************************
2967 * GetTaskmanWindow [USER32.304]
2969 HRESULT WINAPI GetTaskmanWindow ( )
2970 { FIXME(win,"stub\n");
2971 return 0;
2973 /***********************************************************************
2974 * SetProgmanWindow [USER32.522]
2976 HRESULT WINAPI SetProgmanWindow ( DWORD x )
2977 { FIXME(win,"0x%08lx stub\n",x);
2978 return 0;
2980 /***********************************************************************
2981 * SetShellWindowEx [USER32.531]
2983 HRESULT WINAPI SetShellWindowEx ( DWORD x, DWORD y )
2984 { FIXME(win,"0x%08lx 0x%08lx stub\n",x,y);
2985 return 0;
2987 /***********************************************************************
2988 * SetTaskmanWindow [USER32.537]
2990 HRESULT WINAPI SetTaskmanWindow ( DWORD x )
2991 { FIXME(win,"0x%08lx stub\n",x);
2992 return 0;