Made exception_event_request non-blocking, and added
[wine.git] / windows / winpos.c
blob2f3cc4fd955540bf7824eebd3e36e5701aaf91cf
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 "winerror.h"
10 #include "windef.h"
11 #include "wingdi.h"
12 #include "winerror.h"
13 #include "wine/winuser16.h"
14 #include "controls.h"
15 #include "heap.h"
16 #include "user.h"
17 #include "region.h"
18 #include "win.h"
19 #include "hook.h"
20 #include "message.h"
21 #include "queue.h"
22 #include "options.h"
23 #include "winpos.h"
24 #include "dce.h"
25 #include "nonclient.h"
26 #include "debugtools.h"
27 #include "input.h"
29 DEFAULT_DEBUG_CHANNEL(win);
31 #define HAS_DLGFRAME(style,exStyle) \
32 (((exStyle) & WS_EX_DLGMODALFRAME) || \
33 (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
35 #define HAS_THICKFRAME(style) \
36 (((style) & WS_THICKFRAME) && \
37 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
39 #define SWP_AGG_NOGEOMETRYCHANGE \
40 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
41 #define SWP_AGG_NOPOSCHANGE \
42 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
43 #define SWP_AGG_STATUSFLAGS \
44 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
46 #define EMPTYPOINT(pt) ((*(LONG*)&(pt)) == -1)
48 #define PLACE_MIN 0x0001
49 #define PLACE_MAX 0x0002
50 #define PLACE_RECT 0x0004
52 #define SWP_EX_NOCOPY 0x0001
53 #define SWP_EX_PAINTSELF 0x0002
54 #define SWP_EX_NONCLIENT 0x0004
56 #define MINMAX_NOSWP 0x00010000
58 /* ----- internal variables ----- */
60 static HWND hwndPrevActive = 0; /* Previously active window */
61 static HWND hGlobalShellWindow=0; /*the shell*/
62 static HWND hGlobalTaskmanWindow=0;
63 static HWND hGlobalProgmanWindow=0;
65 static LPCSTR atomInternalPos;
67 extern HQUEUE16 hActiveQueue;
69 /***********************************************************************
70 * WINPOS_CreateInternalPosAtom
72 BOOL WINPOS_CreateInternalPosAtom()
74 LPSTR str = "SysIP";
75 atomInternalPos = (LPCSTR)(DWORD)GlobalAddAtomA(str);
76 return (atomInternalPos) ? TRUE : FALSE;
79 /***********************************************************************
80 * WINPOS_CheckInternalPos
82 * Called when a window is destroyed.
84 void WINPOS_CheckInternalPos( WND* wndPtr )
86 LPINTERNALPOS lpPos;
87 MESSAGEQUEUE *pMsgQ = 0;
88 HWND hwnd = wndPtr->hwndSelf;
90 lpPos = (LPINTERNALPOS) GetPropA( hwnd, atomInternalPos );
92 /* Retrieve the message queue associated with this window */
93 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
94 if ( !pMsgQ )
96 WARN("\tMessage queue not found. Exiting!\n" );
97 return;
100 if( hwnd == hwndPrevActive ) hwndPrevActive = 0;
102 if( hwnd == PERQDATA_GetActiveWnd( pMsgQ->pQData ) )
104 PERQDATA_SetActiveWnd( pMsgQ->pQData, 0 );
105 WARN("\tattempt to activate destroyed window!\n");
108 if( lpPos )
110 if( IsWindow(lpPos->hwndIconTitle) )
111 DestroyWindow( lpPos->hwndIconTitle );
112 HeapFree( SystemHeap, 0, lpPos );
115 QUEUE_Unlock( pMsgQ );
116 return;
119 /***********************************************************************
120 * WINPOS_FindIconPos
122 * Find a suitable place for an iconic window.
124 static POINT16 WINPOS_FindIconPos( WND* wndPtr, POINT16 pt )
126 RECT16 rectParent;
127 short x, y, xspacing, yspacing;
129 GetClientRect16( wndPtr->parent->hwndSelf, &rectParent );
130 if ((pt.x >= rectParent.left) && (pt.x + GetSystemMetrics(SM_CXICON) < rectParent.right) &&
131 (pt.y >= rectParent.top) && (pt.y + GetSystemMetrics(SM_CYICON) < rectParent.bottom))
132 return pt; /* The icon already has a suitable position */
134 xspacing = GetSystemMetrics(SM_CXICONSPACING);
135 yspacing = GetSystemMetrics(SM_CYICONSPACING);
137 y = rectParent.bottom;
138 for (;;)
140 x = rectParent.left;
143 /* Check if another icon already occupies this spot */
144 WND *childPtr = WIN_LockWndPtr(wndPtr->parent->child);
145 while (childPtr)
147 if ((childPtr->dwStyle & WS_MINIMIZE) && (childPtr != wndPtr))
149 if ((childPtr->rectWindow.left < x + xspacing) &&
150 (childPtr->rectWindow.right >= x) &&
151 (childPtr->rectWindow.top <= y) &&
152 (childPtr->rectWindow.bottom > y - yspacing))
153 break; /* There's a window in there */
155 WIN_UpdateWndPtr(&childPtr,childPtr->next);
157 WIN_ReleaseWndPtr(childPtr);
158 if (!childPtr) /* No window was found, so it's OK for us */
160 pt.x = x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2;
161 pt.y = y - (yspacing + GetSystemMetrics(SM_CYICON)) / 2;
162 return pt;
164 x += xspacing;
165 } while(x <= rectParent.right-xspacing);
166 y -= yspacing;
171 /***********************************************************************
172 * ArrangeIconicWindows (USER.170)
174 UINT16 WINAPI ArrangeIconicWindows16( HWND16 parent)
176 return ArrangeIconicWindows(parent);
178 /***********************************************************************
179 * ArrangeIconicWindows (USER32.@)
181 UINT WINAPI ArrangeIconicWindows( HWND parent )
183 RECT rectParent;
184 HWND hwndChild;
185 INT x, y, xspacing, yspacing;
187 GetClientRect( parent, &rectParent );
188 x = rectParent.left;
189 y = rectParent.bottom;
190 xspacing = GetSystemMetrics(SM_CXICONSPACING);
191 yspacing = GetSystemMetrics(SM_CYICONSPACING);
193 hwndChild = GetWindow( parent, GW_CHILD );
194 while (hwndChild)
196 if( IsIconic( hwndChild ) )
198 WND *wndPtr = WIN_FindWndPtr(hwndChild);
200 WINPOS_ShowIconTitle( wndPtr, FALSE );
202 SetWindowPos( hwndChild, 0, x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2,
203 y - yspacing - GetSystemMetrics(SM_CYICON)/2, 0, 0,
204 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
205 if( IsWindow(hwndChild) )
206 WINPOS_ShowIconTitle(wndPtr , TRUE );
207 WIN_ReleaseWndPtr(wndPtr);
209 if (x <= rectParent.right - xspacing) x += xspacing;
210 else
212 x = rectParent.left;
213 y -= yspacing;
216 hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
218 return yspacing;
222 /***********************************************************************
223 * SwitchToThisWindow (USER.172)
225 void WINAPI SwitchToThisWindow16( HWND16 hwnd, BOOL16 restore )
227 SwitchToThisWindow( hwnd, restore );
231 /***********************************************************************
232 * SwitchToThisWindow (USER32.@)
234 void WINAPI SwitchToThisWindow( HWND hwnd, BOOL restore )
236 ShowWindow( hwnd, restore ? SW_RESTORE : SW_SHOWMINIMIZED );
240 /***********************************************************************
241 * GetWindowRect (USER.32)
243 void WINAPI GetWindowRect16( HWND16 hwnd, LPRECT16 rect )
245 WND * wndPtr = WIN_FindWndPtr( hwnd );
246 if (!wndPtr) return;
248 CONV_RECT32TO16( &wndPtr->rectWindow, rect );
249 if (wndPtr->dwStyle & WS_CHILD)
250 MapWindowPoints16( wndPtr->parent->hwndSelf, 0, (POINT16 *)rect, 2 );
251 WIN_ReleaseWndPtr(wndPtr);
255 /***********************************************************************
256 * GetWindowRect (USER32.@)
258 BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect )
260 WND * wndPtr = WIN_FindWndPtr( hwnd );
261 if (!wndPtr) return FALSE;
263 *rect = wndPtr->rectWindow;
264 if (wndPtr->dwStyle & WS_CHILD)
265 MapWindowPoints( wndPtr->parent->hwndSelf, 0, (POINT *)rect, 2 );
266 WIN_ReleaseWndPtr(wndPtr);
267 return TRUE;
271 /***********************************************************************
272 * GetWindowRgn (USER32.@)
274 int WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
276 int nRet = ERROR;
277 WND *wndPtr = WIN_FindWndPtr( hwnd );
278 if (wndPtr)
280 if (wndPtr->hrgnWnd) nRet = CombineRgn( hrgn, wndPtr->hrgnWnd, 0, RGN_COPY );
281 WIN_ReleaseWndPtr(wndPtr);
283 return nRet;
286 /***********************************************************************
287 * SetWindowRgn (USER32.@)
289 int WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL bRedraw )
291 int ret = FALSE;
292 RECT tempRect;
294 WND *wndPtr = WIN_FindWndPtr(hwnd);
296 if (!wndPtr) return FALSE;
298 /* a region exists for this window */
299 if (hrgn != 0 && hrgn == wndPtr->hrgnWnd)
301 /* can't replace actual region with same region
302 since we're now owner of that region
304 SetLastError(ERROR_INVALID_HANDLE);
305 goto done;
309 /* we'd like to set it back to 0 */
310 if (hrgn == 0)
312 GetWindowRect(hwnd, &tempRect);
314 else
316 /* verify that region really exists */
317 if (GetRgnBox(hrgn, &tempRect) == ERROR) goto done;
321 /* Size the window to the rectangle of the new region
322 (if it isn't NULL) */
323 SetWindowPos( hwnd, 0, tempRect.left, tempRect.top,
324 tempRect.right - tempRect.left, tempRect.bottom - tempRect.top,
325 SWP_NOSIZE | SWP_FRAMECHANGED | SWP_NOMOVE |
326 SWP_NOZORDER | (bRedraw ? 0 : SWP_NOREDRAW) );
329 if (wndPtr->hrgnWnd)
331 /* delete previous region */
332 DeleteObject(wndPtr->hrgnWnd);
333 wndPtr->hrgnWnd = 0;
335 else if (!hrgn)
337 /* if there was no previous region (stored in wndPtr->hrgnWnd) and
338 the region to be set is also NULL, there is nothing more to do
340 ret = TRUE;
341 goto done;
344 /* valid region handle */
345 wndPtr->hrgnWnd = hrgn;
346 wndPtr->pDriver->pSetWindowRgn(wndPtr, hrgn);
348 ret = TRUE;
350 done:
351 WIN_ReleaseWndPtr(wndPtr);
352 return ret;
355 /***********************************************************************
356 * SetWindowRgn (USER.668)
358 INT16 WINAPI SetWindowRgn16( HWND16 hwnd, HRGN16 hrgn,BOOL16 bRedraw)
362 FIXME("SetWindowRgn16: stub\n");
363 return TRUE;
367 /***********************************************************************
368 * GetClientRect (USER.33)
370 void WINAPI GetClientRect16( HWND16 hwnd, LPRECT16 rect )
372 WND * wndPtr = WIN_FindWndPtr( hwnd );
374 rect->left = rect->top = rect->right = rect->bottom = 0;
375 if (wndPtr)
377 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
378 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
380 WIN_ReleaseWndPtr(wndPtr);
384 /***********************************************************************
385 * GetClientRect (USER32.@)
387 BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect )
389 WND * wndPtr = WIN_FindWndPtr( hwnd );
391 rect->left = rect->top = rect->right = rect->bottom = 0;
392 if (!wndPtr) return FALSE;
393 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
394 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
396 WIN_ReleaseWndPtr(wndPtr);
397 return TRUE;
401 /*******************************************************************
402 * ClientToScreen (USER.28)
404 void WINAPI ClientToScreen16( HWND16 hwnd, LPPOINT16 lppnt )
406 MapWindowPoints16( hwnd, 0, lppnt, 1 );
410 /*******************************************************************
411 * ClientToScreen (USER32.@)
413 BOOL WINAPI ClientToScreen( HWND hwnd, LPPOINT lppnt )
415 MapWindowPoints( hwnd, 0, lppnt, 1 );
416 return TRUE;
420 /*******************************************************************
421 * ScreenToClient (USER.29)
423 void WINAPI ScreenToClient16( HWND16 hwnd, LPPOINT16 lppnt )
425 MapWindowPoints16( 0, hwnd, lppnt, 1 );
429 /*******************************************************************
430 * ScreenToClient (USER32.@)
432 BOOL WINAPI ScreenToClient( HWND hwnd, LPPOINT lppnt )
434 MapWindowPoints( 0, hwnd, lppnt, 1 );
435 return TRUE;
439 /***********************************************************************
440 * WINPOS_WindowFromPoint
442 * Find the window and hittest for a given point.
444 INT16 WINPOS_WindowFromPoint( WND* wndScope, POINT16 pt, WND **ppWnd )
446 WND *wndPtr;
447 INT16 hittest = HTERROR;
448 INT16 retvalue;
449 POINT16 xy = pt;
451 TRACE("scope %04x %d,%d\n", wndScope->hwndSelf, pt.x, pt.y);
452 *ppWnd = NULL;
453 wndPtr = WIN_LockWndPtr(wndScope->child);
455 if( wndScope->dwStyle & WS_DISABLED )
457 retvalue = HTERROR;
458 goto end;
461 if( wndScope->dwExStyle & WS_EX_MANAGED)
463 /* In managed mode we have to check wndScope first as it is also
464 * a window which received the mouse event. */
466 if( pt.x < wndScope->rectClient.left || pt.x >= wndScope->rectClient.right ||
467 pt.y < wndScope->rectClient.top || pt.y >= wndScope->rectClient.bottom )
468 goto hittest;
470 MapWindowPoints16( GetDesktopWindow16(), wndScope->hwndSelf, &xy, 1 );
472 for (;;)
474 while (wndPtr)
476 /* If point is in window, and window is visible, and it */
477 /* is enabled (or it's a top-level window), then explore */
478 /* its children. Otherwise, go to the next window. */
480 if ((wndPtr->dwStyle & WS_VISIBLE) &&
481 (!(wndPtr->dwStyle & WS_DISABLED) ||
482 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)) &&
483 (wndPtr->hrgnWnd ?
484 PtInRegion(wndPtr->hrgnWnd, xy.x - wndPtr->rectWindow.left,
485 xy.y - wndPtr->rectWindow.top) :
486 ((xy.x >= wndPtr->rectWindow.left) &&
487 (xy.x < wndPtr->rectWindow.right) &&
488 (xy.y >= wndPtr->rectWindow.top) &&
489 (xy.y < wndPtr->rectWindow.bottom))))
491 TRACE("%d,%d is inside %04x\n", xy.x, xy.y, wndPtr->hwndSelf);
492 *ppWnd = wndPtr; /* Got a suitable window */
494 /* If window is minimized or disabled, return at once */
495 if (wndPtr->dwStyle & WS_MINIMIZE)
497 retvalue = HTCAPTION;
498 goto end;
500 if (wndPtr->dwStyle & WS_DISABLED)
502 retvalue = HTERROR;
503 goto end;
506 /* If point is not in client area, ignore the children */
507 if ((xy.x < wndPtr->rectClient.left) ||
508 (xy.x >= wndPtr->rectClient.right) ||
509 (xy.y < wndPtr->rectClient.top) ||
510 (xy.y >= wndPtr->rectClient.bottom)) break;
512 xy.x -= wndPtr->rectClient.left;
513 xy.y -= wndPtr->rectClient.top;
514 WIN_UpdateWndPtr(&wndPtr,wndPtr->child);
516 else
518 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
522 hittest:
523 /* If nothing found, try the scope window */
524 if (!*ppWnd) *ppWnd = wndScope;
526 /* Send the WM_NCHITTEST message (only if to the same task) */
527 if ((*ppWnd)->hmemTaskQ == GetFastQueue16())
529 hittest = (INT16)SendMessage16( (*ppWnd)->hwndSelf, WM_NCHITTEST,
530 0, MAKELONG( pt.x, pt.y ) );
531 if (hittest != HTTRANSPARENT)
533 retvalue = hittest; /* Found the window */
534 goto end;
537 else
539 retvalue = HTCLIENT;
540 goto end;
543 /* If no children found in last search, make point relative to parent */
544 if (!wndPtr)
546 xy.x += (*ppWnd)->rectClient.left;
547 xy.y += (*ppWnd)->rectClient.top;
550 /* Restart the search from the next sibling */
551 WIN_UpdateWndPtr(&wndPtr,(*ppWnd)->next);
552 *ppWnd = (*ppWnd)->parent;
555 end:
556 WIN_ReleaseWndPtr(wndPtr);
557 return retvalue;
561 /*******************************************************************
562 * WindowFromPoint (USER.30)
564 HWND16 WINAPI WindowFromPoint16( POINT16 pt )
566 WND *pWnd;
567 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt, &pWnd );
568 WIN_ReleaseDesktop();
569 return pWnd->hwndSelf;
573 /*******************************************************************
574 * WindowFromPoint (USER32.@)
576 HWND WINAPI WindowFromPoint( POINT pt )
578 WND *pWnd;
579 POINT16 pt16;
580 CONV_POINT32TO16( &pt, &pt16 );
581 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16, &pWnd );
582 WIN_ReleaseDesktop();
583 return (HWND)pWnd->hwndSelf;
587 /*******************************************************************
588 * ChildWindowFromPoint (USER.191)
590 HWND16 WINAPI ChildWindowFromPoint16( HWND16 hwndParent, POINT16 pt )
592 POINT pt32;
593 CONV_POINT16TO32( &pt, &pt32 );
594 return (HWND16)ChildWindowFromPoint( hwndParent, pt32 );
598 /*******************************************************************
599 * ChildWindowFromPoint (USER32.@)
601 HWND WINAPI ChildWindowFromPoint( HWND hwndParent, POINT pt )
603 /* pt is in the client coordinates */
605 WND* wnd = WIN_FindWndPtr(hwndParent);
606 RECT rect;
607 HWND retvalue;
609 if( !wnd ) return 0;
611 /* get client rect fast */
612 rect.top = rect.left = 0;
613 rect.right = wnd->rectClient.right - wnd->rectClient.left;
614 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
616 if (!PtInRect( &rect, pt ))
618 retvalue = 0;
619 goto end;
621 WIN_UpdateWndPtr(&wnd,wnd->child);
622 while ( wnd )
624 if (PtInRect( &wnd->rectWindow, pt ))
626 retvalue = wnd->hwndSelf;
627 goto end;
629 WIN_UpdateWndPtr(&wnd,wnd->next);
631 retvalue = hwndParent;
632 end:
633 WIN_ReleaseWndPtr(wnd);
634 return retvalue;
637 /*******************************************************************
638 * ChildWindowFromPointEx (USER.399)
640 HWND16 WINAPI ChildWindowFromPointEx16( HWND16 hwndParent, POINT16 pt, UINT16 uFlags)
642 POINT pt32;
643 CONV_POINT16TO32( &pt, &pt32 );
644 return (HWND16)ChildWindowFromPointEx( hwndParent, pt32, uFlags );
648 /*******************************************************************
649 * ChildWindowFromPointEx (USER32.@)
651 HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt,
652 UINT uFlags)
654 /* pt is in the client coordinates */
656 WND* wnd = WIN_FindWndPtr(hwndParent);
657 RECT rect;
658 HWND retvalue;
660 if( !wnd ) return 0;
662 /* get client rect fast */
663 rect.top = rect.left = 0;
664 rect.right = wnd->rectClient.right - wnd->rectClient.left;
665 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
667 if (!PtInRect( &rect, pt ))
669 retvalue = 0;
670 goto end;
672 WIN_UpdateWndPtr(&wnd,wnd->child);
674 while ( wnd )
676 if (PtInRect( &wnd->rectWindow, pt )) {
677 if ( (uFlags & CWP_SKIPINVISIBLE) &&
678 !(wnd->dwStyle & WS_VISIBLE) );
679 else if ( (uFlags & CWP_SKIPDISABLED) &&
680 (wnd->dwStyle & WS_DISABLED) );
681 else if ( (uFlags & CWP_SKIPTRANSPARENT) &&
682 (wnd->dwExStyle & WS_EX_TRANSPARENT) );
683 else
685 retvalue = wnd->hwndSelf;
686 goto end;
690 WIN_UpdateWndPtr(&wnd,wnd->next);
692 retvalue = hwndParent;
693 end:
694 WIN_ReleaseWndPtr(wnd);
695 return retvalue;
699 /*******************************************************************
700 * WINPOS_GetWinOffset
702 * Calculate the offset between the origin of the two windows. Used
703 * to implement MapWindowPoints.
705 static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo,
706 POINT *offset )
708 WND * wndPtr = 0;
710 offset->x = offset->y = 0;
711 if (hwndFrom == hwndTo ) return;
713 /* Translate source window origin to screen coords */
714 if (hwndFrom)
716 if (!(wndPtr = WIN_FindWndPtr( hwndFrom )))
718 ERR("bad hwndFrom = %04x\n",hwndFrom);
719 return;
721 while (wndPtr->parent)
723 offset->x += wndPtr->rectClient.left;
724 offset->y += wndPtr->rectClient.top;
725 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
727 WIN_ReleaseWndPtr(wndPtr);
730 /* Translate origin to destination window coords */
731 if (hwndTo)
733 if (!(wndPtr = WIN_FindWndPtr( hwndTo )))
735 ERR("bad hwndTo = %04x\n", hwndTo );
736 return;
738 while (wndPtr->parent)
740 offset->x -= wndPtr->rectClient.left;
741 offset->y -= wndPtr->rectClient.top;
742 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
744 WIN_ReleaseWndPtr(wndPtr);
749 /*******************************************************************
750 * MapWindowPoints (USER.258)
752 void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
753 LPPOINT16 lppt, UINT16 count )
755 POINT offset;
757 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
758 while (count--)
760 lppt->x += offset.x;
761 lppt->y += offset.y;
762 lppt++;
767 /*******************************************************************
768 * MapWindowPoints (USER32.@)
770 INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo,
771 LPPOINT lppt, UINT count )
773 POINT offset;
775 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
776 while (count--)
778 lppt->x += offset.x;
779 lppt->y += offset.y;
780 lppt++;
782 return MAKELONG( LOWORD(offset.x), LOWORD(offset.y) );
786 /***********************************************************************
787 * IsIconic (USER.31)
789 BOOL16 WINAPI IsIconic16(HWND16 hWnd)
791 return IsIconic(hWnd);
795 /***********************************************************************
796 * IsIconic (USER32.@)
798 BOOL WINAPI IsIconic(HWND hWnd)
800 BOOL retvalue;
801 WND * wndPtr = WIN_FindWndPtr(hWnd);
802 if (wndPtr == NULL) return FALSE;
803 retvalue = (wndPtr->dwStyle & WS_MINIMIZE) != 0;
804 WIN_ReleaseWndPtr(wndPtr);
805 return retvalue;
809 /***********************************************************************
810 * IsZoomed (USER.272)
812 BOOL16 WINAPI IsZoomed16(HWND16 hWnd)
814 return IsZoomed(hWnd);
818 /***********************************************************************
819 * IsZoomed (USER32.@)
821 BOOL WINAPI IsZoomed(HWND hWnd)
823 BOOL retvalue;
824 WND * wndPtr = WIN_FindWndPtr(hWnd);
825 if (wndPtr == NULL) return FALSE;
826 retvalue = (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
827 WIN_ReleaseWndPtr(wndPtr);
828 return retvalue;
832 /*******************************************************************
833 * GetActiveWindow (USER.60)
835 HWND16 WINAPI GetActiveWindow16(void)
837 return (HWND16)GetActiveWindow();
840 /*******************************************************************
841 * GetActiveWindow (USER32.@)
843 HWND WINAPI GetActiveWindow(void)
845 MESSAGEQUEUE *pCurMsgQ = 0;
846 HWND hwndActive = 0;
848 /* Get the messageQ for the current thread */
849 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
851 WARN("\tCurrent message queue not found. Exiting!\n" );
852 return 0;
855 /* Return the current active window from the perQ data of the current message Q */
856 hwndActive = PERQDATA_GetActiveWnd( pCurMsgQ->pQData );
858 QUEUE_Unlock( pCurMsgQ );
859 return hwndActive;
863 /*******************************************************************
864 * WINPOS_CanActivate
866 static BOOL WINPOS_CanActivate(WND* pWnd)
868 if( pWnd && ( (pWnd->dwStyle & (WS_DISABLED | WS_VISIBLE | WS_CHILD))
869 == WS_VISIBLE ) ) return TRUE;
870 return FALSE;
874 /*******************************************************************
875 * SetActiveWindow (USER.59)
877 HWND16 WINAPI SetActiveWindow16( HWND16 hwnd )
879 return SetActiveWindow(hwnd);
883 /*******************************************************************
884 * SetActiveWindow (USER32.@)
886 HWND WINAPI SetActiveWindow( HWND hwnd )
888 HWND prev = 0;
889 WND *wndPtr = WIN_FindWndPtr( hwnd );
890 MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
892 if (!wndPtr || (wndPtr->dwStyle & (WS_DISABLED | WS_CHILD)))
894 prev = 0;
895 goto end;
898 /* Get the messageQ for the current thread */
899 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
901 WARN("\tCurrent message queue not found. Exiting!\n" );
902 goto CLEANUP;
905 /* Retrieve the message queue associated with this window */
906 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
907 if ( !pMsgQ )
909 WARN("\tWindow message queue not found. Exiting!\n" );
910 goto CLEANUP;
913 /* Make sure that the window is associated with the calling threads
914 * message queue. It must share the same perQ data.
917 if ( pCurMsgQ->pQData != pMsgQ->pQData )
918 goto CLEANUP;
920 /* Save current active window */
921 prev = PERQDATA_GetActiveWnd( pMsgQ->pQData );
923 WINPOS_SetActiveWindow( hwnd, 0, 0 );
925 CLEANUP:
926 /* Unlock the queues before returning */
927 if ( pMsgQ )
928 QUEUE_Unlock( pMsgQ );
929 if ( pCurMsgQ )
930 QUEUE_Unlock( pCurMsgQ );
932 end:
933 WIN_ReleaseWndPtr(wndPtr);
934 return prev;
938 /*******************************************************************
939 * GetForegroundWindow (USER.608)
941 HWND16 WINAPI GetForegroundWindow16(void)
943 return (HWND16)GetForegroundWindow();
947 /*******************************************************************
948 * SetForegroundWindow (USER.609)
950 BOOL16 WINAPI SetForegroundWindow16( HWND16 hwnd )
952 return SetForegroundWindow( hwnd );
956 /*******************************************************************
957 * GetForegroundWindow (USER32.@)
959 HWND WINAPI GetForegroundWindow(void)
961 HWND hwndActive = 0;
963 /* Get the foreground window (active window of hActiveQueue) */
964 if ( hActiveQueue )
966 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
967 if ( pActiveQueue )
968 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
970 QUEUE_Unlock( pActiveQueue );
973 return hwndActive;
976 /*******************************************************************
977 * SetForegroundWindow (USER32.@)
979 BOOL WINAPI SetForegroundWindow( HWND hwnd )
981 return WINPOS_ChangeActiveWindow( hwnd, FALSE );
985 /*******************************************************************
986 * AllowSetForegroundWindow (USER32.@)
988 BOOL WINAPI AllowSetForegroundWindow( DWORD procid )
990 /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
991 * implemented, then fix this function. */
992 return TRUE;
996 /*******************************************************************
997 * LockSetForegroundWindow (USER32.@)
999 BOOL WINAPI LockSetForegroundWindow( UINT lockcode )
1001 /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
1002 * implemented, then fix this function. */
1003 return TRUE;
1007 /*******************************************************************
1008 * GetShellWindow (USER.600)
1010 HWND16 WINAPI GetShellWindow16(void)
1012 return GetShellWindow();
1015 /*******************************************************************
1016 * SetShellWindow (USER32.@)
1018 HWND WINAPI SetShellWindow(HWND hwndshell)
1019 { WARN("(hWnd=%08x) semi stub\n",hwndshell );
1021 hGlobalShellWindow = hwndshell;
1022 return hGlobalShellWindow;
1026 /*******************************************************************
1027 * GetShellWindow (USER32.@)
1029 HWND WINAPI GetShellWindow(void)
1030 { WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow );
1032 return hGlobalShellWindow;
1036 /***********************************************************************
1037 * BringWindowToTop (USER.45)
1039 BOOL16 WINAPI BringWindowToTop16( HWND16 hwnd )
1041 return BringWindowToTop(hwnd);
1045 /***********************************************************************
1046 * BringWindowToTop (USER32.@)
1048 BOOL WINAPI BringWindowToTop( HWND hwnd )
1050 return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
1054 /***********************************************************************
1055 * MoveWindow (USER.56)
1057 BOOL16 WINAPI MoveWindow16( HWND16 hwnd, INT16 x, INT16 y, INT16 cx, INT16 cy,
1058 BOOL16 repaint )
1060 return MoveWindow(hwnd,x,y,cx,cy,repaint);
1064 /***********************************************************************
1065 * MoveWindow (USER32.@)
1067 BOOL WINAPI MoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy,
1068 BOOL repaint )
1070 int flags = SWP_NOZORDER | SWP_NOACTIVATE;
1071 if (!repaint) flags |= SWP_NOREDRAW;
1072 TRACE("%04x %d,%d %dx%d %d\n",
1073 hwnd, x, y, cx, cy, repaint );
1074 return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
1077 /***********************************************************************
1078 * WINPOS_InitInternalPos
1080 static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT pt,
1081 LPRECT restoreRect )
1083 LPINTERNALPOS lpPos = (LPINTERNALPOS) GetPropA( wnd->hwndSelf,
1084 atomInternalPos );
1085 if( !lpPos )
1087 /* this happens when the window is minimized/maximized
1088 * for the first time (rectWindow is not adjusted yet) */
1090 lpPos = HeapAlloc( SystemHeap, 0, sizeof(INTERNALPOS) );
1091 if( !lpPos ) return NULL;
1093 SetPropA( wnd->hwndSelf, atomInternalPos, (HANDLE)lpPos );
1094 lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
1095 CONV_RECT32TO16( &wnd->rectWindow, &lpPos->rectNormal );
1096 *(UINT*)&lpPos->ptIconPos = *(UINT*)&lpPos->ptMaxPos = 0xFFFFFFFF;
1099 if( wnd->dwStyle & WS_MINIMIZE )
1100 CONV_POINT32TO16( &pt, &lpPos->ptIconPos );
1101 else if( wnd->dwStyle & WS_MAXIMIZE )
1102 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1103 else if( restoreRect )
1104 CONV_RECT32TO16( restoreRect, &lpPos->rectNormal );
1106 return lpPos;
1109 /***********************************************************************
1110 * WINPOS_RedrawIconTitle
1112 BOOL WINPOS_RedrawIconTitle( HWND hWnd )
1114 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hWnd, atomInternalPos );
1115 if( lpPos )
1117 if( lpPos->hwndIconTitle )
1119 SendMessageA( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
1120 InvalidateRect( lpPos->hwndIconTitle, NULL, TRUE );
1121 return TRUE;
1124 return FALSE;
1127 /***********************************************************************
1128 * WINPOS_ShowIconTitle
1130 BOOL WINPOS_ShowIconTitle( WND* pWnd, BOOL bShow )
1132 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( pWnd->hwndSelf, atomInternalPos );
1134 if( lpPos && !(pWnd->dwExStyle & WS_EX_MANAGED))
1136 HWND16 hWnd = lpPos->hwndIconTitle;
1138 TRACE("0x%04x %i\n", pWnd->hwndSelf, (bShow != 0) );
1140 if( !hWnd )
1141 lpPos->hwndIconTitle = hWnd = ICONTITLE_Create( pWnd );
1142 if( bShow )
1144 if( ( pWnd = WIN_FindWndPtr(hWnd) ) != NULL)
1146 if( !(pWnd->dwStyle & WS_VISIBLE) )
1148 SendMessageA( hWnd, WM_SHOWWINDOW, TRUE, 0 );
1149 SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
1150 SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
1152 WIN_ReleaseWndPtr(pWnd);
1155 else ShowWindow( hWnd, SW_HIDE );
1157 return FALSE;
1160 /*******************************************************************
1161 * WINPOS_GetMinMaxInfo
1163 * Get the minimized and maximized information for a window.
1165 void WINPOS_GetMinMaxInfo( WND *wndPtr, POINT *maxSize, POINT *maxPos,
1166 POINT *minTrack, POINT *maxTrack )
1168 LPINTERNALPOS lpPos;
1169 MINMAXINFO MinMax;
1170 INT xinc, yinc;
1172 /* Compute default values */
1174 MinMax.ptMaxSize.x = GetSystemMetrics(SM_CXSCREEN);
1175 MinMax.ptMaxSize.y = GetSystemMetrics(SM_CYSCREEN);
1176 MinMax.ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
1177 MinMax.ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
1178 MinMax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXSCREEN);
1179 MinMax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYSCREEN);
1181 if (wndPtr->dwExStyle & WS_EX_MANAGED) xinc = yinc = 0;
1182 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1184 xinc = GetSystemMetrics(SM_CXDLGFRAME);
1185 yinc = GetSystemMetrics(SM_CYDLGFRAME);
1187 else
1189 xinc = yinc = 0;
1190 if (HAS_THICKFRAME(wndPtr->dwStyle))
1192 xinc += GetSystemMetrics(SM_CXFRAME);
1193 yinc += GetSystemMetrics(SM_CYFRAME);
1195 if (wndPtr->dwStyle & WS_BORDER)
1197 xinc += GetSystemMetrics(SM_CXBORDER);
1198 yinc += GetSystemMetrics(SM_CYBORDER);
1201 MinMax.ptMaxSize.x += 2 * xinc;
1202 MinMax.ptMaxSize.y += 2 * yinc;
1204 lpPos = (LPINTERNALPOS)GetPropA( wndPtr->hwndSelf, atomInternalPos );
1205 if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
1206 CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
1207 else
1209 MinMax.ptMaxPosition.x = -xinc;
1210 MinMax.ptMaxPosition.y = -yinc;
1213 SendMessageA( wndPtr->hwndSelf, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
1215 /* Some sanity checks */
1217 TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1218 MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
1219 MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
1220 MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
1221 MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
1222 MinMax.ptMaxTrackSize.x = max( MinMax.ptMaxTrackSize.x,
1223 MinMax.ptMinTrackSize.x );
1224 MinMax.ptMaxTrackSize.y = max( MinMax.ptMaxTrackSize.y,
1225 MinMax.ptMinTrackSize.y );
1227 if (maxSize) *maxSize = MinMax.ptMaxSize;
1228 if (maxPos) *maxPos = MinMax.ptMaxPosition;
1229 if (minTrack) *minTrack = MinMax.ptMinTrackSize;
1230 if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
1233 /***********************************************************************
1234 * WINPOS_MinMaximize
1236 * Fill in lpRect and return additional flags to be used with SetWindowPos().
1237 * This function assumes that 'cmd' is different from the current window
1238 * state.
1240 UINT WINPOS_MinMaximize( WND* wndPtr, UINT16 cmd, LPRECT16 lpRect )
1242 UINT swpFlags = 0;
1243 POINT pt, size;
1244 LPINTERNALPOS lpPos;
1246 TRACE("0x%04x %u\n", wndPtr->hwndSelf, cmd );
1248 size.x = wndPtr->rectWindow.left; size.y = wndPtr->rectWindow.top;
1249 lpPos = WINPOS_InitInternalPos( wndPtr, size, &wndPtr->rectWindow );
1251 if (lpPos && !HOOK_CallHooks16(WH_CBT, HCBT_MINMAX, wndPtr->hwndSelf, cmd))
1253 if( wndPtr->dwStyle & WS_MINIMIZE )
1255 if( !SendMessageA( wndPtr->hwndSelf, WM_QUERYOPEN, 0, 0L ) )
1256 return (SWP_NOSIZE | SWP_NOMOVE);
1257 swpFlags |= SWP_NOCOPYBITS;
1259 switch( cmd )
1261 case SW_MINIMIZE:
1262 if( wndPtr->dwStyle & WS_MAXIMIZE)
1264 wndPtr->flags |= WIN_RESTORE_MAX;
1265 wndPtr->dwStyle &= ~WS_MAXIMIZE;
1267 else
1268 wndPtr->flags &= ~WIN_RESTORE_MAX;
1269 wndPtr->dwStyle |= WS_MINIMIZE;
1271 if( wndPtr->flags & WIN_NATIVE )
1272 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, TRUE ) )
1273 swpFlags |= MINMAX_NOSWP;
1275 lpPos->ptIconPos = WINPOS_FindIconPos( wndPtr, lpPos->ptIconPos );
1277 SetRect16( lpRect, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1278 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON) );
1279 swpFlags |= SWP_NOCOPYBITS;
1280 break;
1282 case SW_MAXIMIZE:
1283 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1284 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL );
1285 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1287 if( wndPtr->dwStyle & WS_MINIMIZE )
1289 if( wndPtr->flags & WIN_NATIVE )
1290 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE );
1292 WINPOS_ShowIconTitle( wndPtr, FALSE );
1293 wndPtr->dwStyle &= ~WS_MINIMIZE;
1295 wndPtr->dwStyle |= WS_MAXIMIZE;
1297 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1298 size.x, size.y );
1299 break;
1301 case SW_RESTORE:
1302 if( wndPtr->dwStyle & WS_MINIMIZE )
1304 if( wndPtr->flags & WIN_NATIVE )
1305 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE );
1307 wndPtr->dwStyle &= ~WS_MINIMIZE;
1308 WINPOS_ShowIconTitle( wndPtr, FALSE );
1310 if( wndPtr->flags & WIN_RESTORE_MAX)
1312 /* Restore to maximized position */
1313 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1314 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL);
1315 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1316 wndPtr->dwStyle |= WS_MAXIMIZE;
1317 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y, size.x, size.y );
1318 break;
1321 else
1322 if( !(wndPtr->dwStyle & WS_MAXIMIZE) ) return (UINT16)(-1);
1323 else wndPtr->dwStyle &= ~WS_MAXIMIZE;
1325 /* Restore to normal position */
1327 *lpRect = lpPos->rectNormal;
1328 lpRect->right -= lpRect->left;
1329 lpRect->bottom -= lpRect->top;
1331 break;
1333 } else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
1334 return swpFlags;
1337 /***********************************************************************
1338 * ShowWindowAsync (USER32.@)
1340 * doesn't wait; returns immediately.
1341 * used by threads to toggle windows in other (possibly hanging) threads
1343 BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd )
1345 /* FIXME: does ShowWindow() return immediately ? */
1346 return ShowWindow(hwnd, cmd);
1350 /***********************************************************************
1351 * ShowWindow (USER.42)
1353 BOOL16 WINAPI ShowWindow16( HWND16 hwnd, INT16 cmd )
1355 return ShowWindow(hwnd,cmd);
1359 /***********************************************************************
1360 * ShowWindow (USER32.@)
1362 BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
1364 WND* wndPtr = WIN_FindWndPtr( hwnd );
1365 BOOL wasVisible, showFlag;
1366 RECT16 newPos = {0, 0, 0, 0};
1367 UINT swp = 0;
1369 if (!wndPtr) return FALSE;
1371 TRACE("hwnd=%04x, cmd=%d\n", hwnd, cmd);
1373 wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
1375 switch(cmd)
1377 case SW_HIDE:
1378 if (!wasVisible) goto END;;
1379 swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
1380 SWP_NOACTIVATE | SWP_NOZORDER;
1381 break;
1383 case SW_SHOWMINNOACTIVE:
1384 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1385 /* fall through */
1386 case SW_SHOWMINIMIZED:
1387 swp |= SWP_SHOWWINDOW;
1388 /* fall through */
1389 case SW_MINIMIZE:
1390 swp |= SWP_FRAMECHANGED;
1391 if( !(wndPtr->dwStyle & WS_MINIMIZE) )
1392 swp |= WINPOS_MinMaximize( wndPtr, SW_MINIMIZE, &newPos );
1393 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1394 break;
1396 case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
1397 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1398 if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
1399 swp |= WINPOS_MinMaximize( wndPtr, SW_MAXIMIZE, &newPos );
1400 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1401 break;
1403 case SW_SHOWNA:
1404 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1405 /* fall through */
1406 case SW_SHOW:
1407 swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
1410 * ShowWindow has a little peculiar behavior that if the
1411 * window is already the topmost window, it will not
1412 * activate it.
1414 if (GetTopWindow((HWND)0)==hwnd && (wasVisible || GetActiveWindow() == hwnd))
1415 swp |= SWP_NOACTIVATE;
1417 break;
1419 case SW_SHOWNOACTIVATE:
1420 swp |= SWP_NOZORDER;
1421 if (GetActiveWindow()) swp |= SWP_NOACTIVATE;
1422 /* fall through */
1423 case SW_SHOWNORMAL: /* same as SW_NORMAL: */
1424 case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
1425 case SW_RESTORE:
1426 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1428 if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) )
1429 swp |= WINPOS_MinMaximize( wndPtr, SW_RESTORE, &newPos );
1430 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1431 break;
1434 showFlag = (cmd != SW_HIDE);
1435 if (showFlag != wasVisible)
1437 SendMessageA( hwnd, WM_SHOWWINDOW, showFlag, 0 );
1438 if (!IsWindow( hwnd )) goto END;
1441 if ((wndPtr->dwStyle & WS_CHILD) &&
1442 !IsWindowVisible( wndPtr->parent->hwndSelf ) &&
1443 (swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE) )
1445 /* Don't call SetWindowPos() on invisible child windows */
1446 if (cmd == SW_HIDE) wndPtr->dwStyle &= ~WS_VISIBLE;
1447 else wndPtr->dwStyle |= WS_VISIBLE;
1449 else
1451 /* We can't activate a child window */
1452 if ((wndPtr->dwStyle & WS_CHILD) &&
1453 !(wndPtr->dwExStyle & WS_EX_MDICHILD))
1454 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1455 if (!(swp & MINMAX_NOSWP))
1457 SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top,
1458 newPos.right, newPos.bottom, LOWORD(swp) );
1459 if (cmd == SW_HIDE)
1461 /* FIXME: This will cause the window to be activated irrespective
1462 * of whether it is owned by the same thread. Has to be done
1463 * asynchronously.
1466 if (hwnd == GetActiveWindow())
1467 WINPOS_ActivateOtherWindow(wndPtr);
1469 /* Revert focus to parent */
1470 if (hwnd == GetFocus() || IsChild(hwnd, GetFocus()))
1471 SetFocus( GetParent(hwnd) );
1474 if (!IsWindow( hwnd )) goto END;
1475 else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( wndPtr, TRUE );
1478 if (wndPtr->flags & WIN_NEED_SIZE)
1480 /* should happen only in CreateWindowEx() */
1481 int wParam = SIZE_RESTORED;
1483 wndPtr->flags &= ~WIN_NEED_SIZE;
1484 if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
1485 else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
1486 SendMessageA( hwnd, WM_SIZE, wParam,
1487 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
1488 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
1489 SendMessageA( hwnd, WM_MOVE, 0,
1490 MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
1493 END:
1494 WIN_ReleaseWndPtr(wndPtr);
1495 return wasVisible;
1499 /***********************************************************************
1500 * GetInternalWindowPos (USER.460)
1502 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
1503 LPPOINT16 ptIcon )
1505 WINDOWPLACEMENT16 wndpl;
1506 if (GetWindowPlacement16( hwnd, &wndpl ))
1508 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1509 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1510 return wndpl.showCmd;
1512 return 0;
1516 /***********************************************************************
1517 * GetInternalWindowPos (USER32.@)
1519 UINT WINAPI GetInternalWindowPos( HWND hwnd, LPRECT rectWnd,
1520 LPPOINT ptIcon )
1522 WINDOWPLACEMENT wndpl;
1523 if (GetWindowPlacement( hwnd, &wndpl ))
1525 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1526 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1527 return wndpl.showCmd;
1529 return 0;
1532 /***********************************************************************
1533 * GetWindowPlacement (USER.370)
1535 BOOL16 WINAPI GetWindowPlacement16( HWND16 hwnd, WINDOWPLACEMENT16 *wndpl )
1537 WND *pWnd = WIN_FindWndPtr( hwnd );
1538 LPINTERNALPOS lpPos;
1540 if(!pWnd ) return FALSE;
1542 lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1543 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1544 wndpl->length = sizeof(*wndpl);
1545 if( pWnd->dwStyle & WS_MINIMIZE )
1546 wndpl->showCmd = SW_SHOWMINIMIZED;
1547 else
1548 wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE )
1549 ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
1550 if( pWnd->flags & WIN_RESTORE_MAX )
1551 wndpl->flags = WPF_RESTORETOMAXIMIZED;
1552 else
1553 wndpl->flags = 0;
1554 wndpl->ptMinPosition = lpPos->ptIconPos;
1555 wndpl->ptMaxPosition = lpPos->ptMaxPos;
1556 wndpl->rcNormalPosition = lpPos->rectNormal;
1558 WIN_ReleaseWndPtr(pWnd);
1559 return TRUE;
1563 /***********************************************************************
1564 * GetWindowPlacement (USER32.@)
1566 * Win95:
1567 * Fails if wndpl->length of Win95 (!) apps is invalid.
1569 BOOL WINAPI GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *pwpl32 )
1571 if( pwpl32 )
1573 WINDOWPLACEMENT16 wpl;
1574 wpl.length = sizeof(wpl);
1575 if( GetWindowPlacement16( hwnd, &wpl ) )
1577 pwpl32->length = sizeof(*pwpl32);
1578 pwpl32->flags = wpl.flags;
1579 pwpl32->showCmd = wpl.showCmd;
1580 CONV_POINT16TO32( &wpl.ptMinPosition, &pwpl32->ptMinPosition );
1581 CONV_POINT16TO32( &wpl.ptMaxPosition, &pwpl32->ptMaxPosition );
1582 CONV_RECT16TO32( &wpl.rcNormalPosition, &pwpl32->rcNormalPosition );
1583 return TRUE;
1586 return FALSE;
1590 /***********************************************************************
1591 * WINPOS_SetPlacement
1593 static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT16 *wndpl,
1594 UINT flags )
1596 WND *pWnd = WIN_FindWndPtr( hwnd );
1597 if( pWnd )
1599 LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1600 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1602 if( flags & PLACE_MIN ) lpPos->ptIconPos = wndpl->ptMinPosition;
1603 if( flags & PLACE_MAX ) lpPos->ptMaxPos = wndpl->ptMaxPosition;
1604 if( flags & PLACE_RECT) lpPos->rectNormal = wndpl->rcNormalPosition;
1606 if( pWnd->dwStyle & WS_MINIMIZE )
1608 WINPOS_ShowIconTitle( pWnd, FALSE );
1609 if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1610 SetWindowPos( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1611 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1613 else if( pWnd->dwStyle & WS_MAXIMIZE )
1615 if( !EMPTYPOINT(lpPos->ptMaxPos) )
1616 SetWindowPos( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1617 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1619 else if( flags & PLACE_RECT )
1620 SetWindowPos( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1621 lpPos->rectNormal.right - lpPos->rectNormal.left,
1622 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1623 SWP_NOZORDER | SWP_NOACTIVATE );
1625 ShowWindow( hwnd, wndpl->showCmd );
1626 if( IsWindow(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1628 if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd, TRUE );
1630 /* SDK: ...valid only the next time... */
1631 if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1633 WIN_ReleaseWndPtr(pWnd);
1634 return TRUE;
1636 return FALSE;
1640 /***********************************************************************
1641 * SetWindowPlacement (USER.371)
1643 BOOL16 WINAPI SetWindowPlacement16(HWND16 hwnd, const WINDOWPLACEMENT16 *wndpl)
1645 return WINPOS_SetPlacement( hwnd, wndpl,
1646 PLACE_MIN | PLACE_MAX | PLACE_RECT );
1649 /***********************************************************************
1650 * SetWindowPlacement (USER32.@)
1652 * Win95:
1653 * Fails if wndpl->length of Win95 (!) apps is invalid.
1655 BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *pwpl32 )
1657 if( pwpl32 )
1659 WINDOWPLACEMENT16 wpl;
1661 wpl.length = sizeof(WINDOWPLACEMENT16);
1662 wpl.flags = pwpl32->flags;
1663 wpl.showCmd = pwpl32->showCmd;
1664 wpl.ptMinPosition.x = pwpl32->ptMinPosition.x;
1665 wpl.ptMinPosition.y = pwpl32->ptMinPosition.y;
1666 wpl.ptMaxPosition.x = pwpl32->ptMaxPosition.x;
1667 wpl.ptMaxPosition.y = pwpl32->ptMaxPosition.y;
1668 wpl.rcNormalPosition.left = pwpl32->rcNormalPosition.left;
1669 wpl.rcNormalPosition.top = pwpl32->rcNormalPosition.top;
1670 wpl.rcNormalPosition.right = pwpl32->rcNormalPosition.right;
1671 wpl.rcNormalPosition.bottom = pwpl32->rcNormalPosition.bottom;
1673 return WINPOS_SetPlacement( hwnd, &wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1675 return FALSE;
1679 /***********************************************************************
1680 * SetInternalWindowPos (USER.461)
1682 void WINAPI SetInternalWindowPos16( HWND16 hwnd, UINT16 showCmd,
1683 LPRECT16 rect, LPPOINT16 pt )
1685 if( IsWindow16(hwnd) )
1687 WINDOWPLACEMENT16 wndpl;
1688 UINT flags;
1690 wndpl.length = sizeof(wndpl);
1691 wndpl.showCmd = showCmd;
1692 wndpl.flags = flags = 0;
1694 if( pt )
1696 flags |= PLACE_MIN;
1697 wndpl.flags |= WPF_SETMINPOSITION;
1698 wndpl.ptMinPosition = *pt;
1700 if( rect )
1702 flags |= PLACE_RECT;
1703 wndpl.rcNormalPosition = *rect;
1705 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1710 /***********************************************************************
1711 * SetInternalWindowPos (USER32.@)
1713 void WINAPI SetInternalWindowPos( HWND hwnd, UINT showCmd,
1714 LPRECT rect, LPPOINT pt )
1716 if( IsWindow(hwnd) )
1718 WINDOWPLACEMENT16 wndpl;
1719 UINT flags;
1721 wndpl.length = sizeof(wndpl);
1722 wndpl.showCmd = showCmd;
1723 wndpl.flags = flags = 0;
1725 if( pt )
1727 flags |= PLACE_MIN;
1728 wndpl.flags |= WPF_SETMINPOSITION;
1729 CONV_POINT32TO16( pt, &wndpl.ptMinPosition );
1731 if( rect )
1733 flags |= PLACE_RECT;
1734 CONV_RECT32TO16( rect, &wndpl.rcNormalPosition );
1736 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1740 /*******************************************************************
1741 * WINPOS_SetActiveWindow
1743 * SetActiveWindow() back-end. This is the only function that
1744 * can assign active status to a window. It must be called only
1745 * for the top level windows.
1747 BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
1749 CBTACTIVATESTRUCT16* cbtStruct;
1750 WND* wndPtr=0, *wndTemp;
1751 HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1752 MESSAGEQUEUE *pOldActiveQueue = 0, *pNewActiveQueue = 0;
1753 WORD wIconized = 0;
1754 HWND hwndActive = 0;
1755 BOOL bRet = 0;
1757 TRACE("(%04x, %d, %d)\n", hWnd, fMouse, fChangeFocus );
1759 /* Get current active window from the active queue */
1760 if ( hActiveQueue )
1762 pOldActiveQueue = QUEUE_Lock( hActiveQueue );
1763 if ( pOldActiveQueue )
1764 hwndActive = PERQDATA_GetActiveWnd( pOldActiveQueue->pQData );
1767 /* paranoid checks */
1768 if( hWnd == GetDesktopWindow() || (bRet = (hWnd == hwndActive)) )
1769 goto CLEANUP_END;
1771 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1772 * return 0;
1774 wndPtr = WIN_FindWndPtr(hWnd);
1775 hOldActiveQueue = hActiveQueue;
1777 if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1779 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1780 WIN_ReleaseWndPtr(wndTemp);
1782 else
1783 TRACE("no current active window.\n");
1785 /* call CBT hook chain */
1786 if ((cbtStruct = SEGPTR_NEW(CBTACTIVATESTRUCT16)))
1788 cbtStruct->fMouse = fMouse;
1789 cbtStruct->hWndActive = hwndActive;
1790 bRet = (BOOL)HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
1791 (LPARAM)SEGPTR_GET(cbtStruct) );
1792 SEGPTR_FREE(cbtStruct);
1793 if (bRet) goto CLEANUP_END;
1796 /* set prev active wnd to current active wnd and send notification */
1797 if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
1799 MESSAGEQUEUE *pTempActiveQueue = 0;
1801 if (!SendMessageA( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1803 if (GetSysModalWindow16() != hWnd)
1804 goto CLEANUP_END;
1805 /* disregard refusal if hWnd is sysmodal */
1808 SendMessageA( hwndPrevActive, WM_ACTIVATE,
1809 MAKEWPARAM( WA_INACTIVE, wIconized ),
1810 (LPARAM)hWnd );
1812 /* check if something happened during message processing
1813 * (global active queue may have changed)
1815 pTempActiveQueue = QUEUE_Lock( hActiveQueue );
1816 if(!pTempActiveQueue)
1817 goto CLEANUP_END;
1819 hwndActive = PERQDATA_GetActiveWnd( pTempActiveQueue->pQData );
1820 QUEUE_Unlock( pTempActiveQueue );
1821 if( hwndPrevActive != hwndActive )
1822 goto CLEANUP_END;
1825 /* Set new active window in the message queue */
1826 hwndActive = hWnd;
1827 if ( wndPtr )
1829 pNewActiveQueue = QUEUE_Lock( wndPtr->hmemTaskQ );
1830 if ( pNewActiveQueue )
1831 PERQDATA_SetActiveWnd( pNewActiveQueue->pQData, hwndActive );
1833 else /* have to do this or MDI frame activation goes to hell */
1834 if( pOldActiveQueue )
1835 PERQDATA_SetActiveWnd( pOldActiveQueue->pQData, 0 );
1837 /* send palette messages */
1838 if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1839 SendMessage16((HWND16)-1, WM_PALETTEISCHANGING, (WPARAM16)hWnd, 0L );
1841 /* if prev wnd is minimized redraw icon title */
1842 if( IsIconic( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1844 /* managed windows will get ConfigureNotify event */
1845 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_MANAGED))
1847 /* check Z-order and bring hWnd to the top */
1848 for (wndTemp = WIN_LockWndPtr(WIN_GetDesktop()->child); wndTemp; WIN_UpdateWndPtr(&wndTemp,wndTemp->next))
1850 if (wndTemp->dwStyle & WS_VISIBLE) break;
1852 WIN_ReleaseDesktop();
1853 WIN_ReleaseWndPtr(wndTemp);
1855 if( wndTemp != wndPtr )
1856 SetWindowPos(hWnd, HWND_TOP, 0,0,0,0,
1857 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1858 if (!IsWindow(hWnd))
1859 goto CLEANUP;
1862 /* Get a handle to the new active queue */
1863 hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1865 /* send WM_ACTIVATEAPP if necessary */
1866 if (hOldActiveQueue != hNewActiveQueue)
1868 WND **list, **ppWnd;
1869 WND *pDesktop = WIN_GetDesktop();
1871 if ((list = WIN_BuildWinArray( pDesktop, 0, NULL )))
1873 for (ppWnd = list; *ppWnd; ppWnd++)
1875 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1877 if ((*ppWnd)->hmemTaskQ == hOldActiveQueue)
1878 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1879 0, QUEUE_GetQueueTask(hNewActiveQueue) );
1881 WIN_ReleaseWinArray(list);
1884 hActiveQueue = hNewActiveQueue;
1886 if ((list = WIN_BuildWinArray(pDesktop, 0, NULL )))
1888 for (ppWnd = list; *ppWnd; ppWnd++)
1890 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1892 if ((*ppWnd)->hmemTaskQ == hNewActiveQueue)
1893 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1894 1, QUEUE_GetQueueTask( hOldActiveQueue ) );
1896 WIN_ReleaseWinArray(list);
1898 WIN_ReleaseDesktop();
1900 if (hWnd && !IsWindow(hWnd)) goto CLEANUP;
1903 if (hWnd)
1905 /* walk up to the first unowned window */
1906 wndTemp = WIN_LockWndPtr(wndPtr);
1907 while (wndTemp->owner)
1909 WIN_UpdateWndPtr(&wndTemp,wndTemp->owner);
1911 /* and set last active owned popup */
1912 wndTemp->hwndLastActive = hWnd;
1914 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1915 WIN_ReleaseWndPtr(wndTemp);
1916 SendMessageA( hWnd, WM_NCACTIVATE, TRUE, 0 );
1917 SendMessageA( hWnd, WM_ACTIVATE,
1918 MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1919 (LPARAM)hwndPrevActive );
1920 if( !IsWindow(hWnd) ) goto CLEANUP;
1923 /* change focus if possible */
1924 if ( fChangeFocus )
1926 if ( pNewActiveQueue )
1928 HWND hOldFocus = PERQDATA_GetFocusWnd( pNewActiveQueue->pQData );
1930 if ( hOldFocus && WIN_GetTopParent( hOldFocus ) != hwndActive )
1931 FOCUS_SwitchFocus( pNewActiveQueue, hOldFocus,
1932 (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
1933 0 : hwndActive );
1936 if ( pOldActiveQueue &&
1937 ( !pNewActiveQueue ||
1938 pNewActiveQueue->pQData != pOldActiveQueue->pQData ) )
1940 HWND hOldFocus = PERQDATA_GetFocusWnd( pOldActiveQueue->pQData );
1941 if ( hOldFocus )
1942 FOCUS_SwitchFocus( pOldActiveQueue, hOldFocus, 0 );
1946 if( !hwndPrevActive && wndPtr )
1947 (*wndPtr->pDriver->pForceWindowRaise)(wndPtr);
1949 /* if active wnd is minimized redraw icon title */
1950 if( IsIconic(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1952 bRet = (hWnd == hwndActive); /* Success? */
1954 CLEANUP: /* Unlock the message queues before returning */
1956 if ( pNewActiveQueue )
1957 QUEUE_Unlock( pNewActiveQueue );
1959 CLEANUP_END:
1961 if ( pOldActiveQueue )
1962 QUEUE_Unlock( pOldActiveQueue );
1964 WIN_ReleaseWndPtr(wndPtr);
1965 return bRet;
1968 /*******************************************************************
1969 * WINPOS_ActivateOtherWindow
1971 * Activates window other than pWnd.
1973 BOOL WINPOS_ActivateOtherWindow(WND* pWnd)
1975 BOOL bRet = 0;
1976 WND* pWndTo = NULL;
1977 HWND hwndActive = 0;
1979 /* Get current active window from the active queue */
1980 if ( hActiveQueue )
1982 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1983 if ( pActiveQueue )
1985 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1986 QUEUE_Unlock( pActiveQueue );
1990 if( pWnd->hwndSelf == hwndPrevActive )
1991 hwndPrevActive = 0;
1993 if( hwndActive != pWnd->hwndSelf &&
1994 ( hwndActive || QUEUE_IsExitingQueue(pWnd->hmemTaskQ)) )
1995 return 0;
1997 if( !(pWnd->dwStyle & WS_POPUP) || !(pWnd->owner) ||
1998 !WINPOS_CanActivate((pWndTo = WIN_GetTopParentPtr(pWnd->owner))) )
2000 WND* pWndPtr = WIN_GetTopParentPtr(pWnd);
2002 WIN_ReleaseWndPtr(pWndTo);
2003 pWndTo = WIN_FindWndPtr(hwndPrevActive);
2005 while( !WINPOS_CanActivate(pWndTo) )
2007 /* by now owned windows should've been taken care of */
2008 WIN_UpdateWndPtr(&pWndTo,pWndPtr->next);
2009 WIN_UpdateWndPtr(&pWndPtr,pWndTo);
2010 if( !pWndTo ) break;
2012 WIN_ReleaseWndPtr(pWndPtr);
2015 bRet = WINPOS_SetActiveWindow( pWndTo ? pWndTo->hwndSelf : 0, FALSE, TRUE );
2017 /* switch desktop queue to current active */
2018 if( pWndTo )
2020 WIN_GetDesktop()->hmemTaskQ = pWndTo->hmemTaskQ;
2021 WIN_ReleaseWndPtr(pWndTo);
2022 WIN_ReleaseDesktop();
2025 hwndPrevActive = 0;
2026 return bRet;
2029 /*******************************************************************
2030 * WINPOS_ChangeActiveWindow
2033 BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
2035 WND *wndPtr, *wndTemp;
2036 BOOL retvalue;
2037 HWND hwndActive = 0;
2039 /* Get current active window from the active queue */
2040 if ( hActiveQueue )
2042 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2043 if ( pActiveQueue )
2045 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2046 QUEUE_Unlock( pActiveQueue );
2050 if (!hWnd)
2051 return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
2053 wndPtr = WIN_FindWndPtr(hWnd);
2054 if( !wndPtr ) return FALSE;
2056 /* child windows get WM_CHILDACTIVATE message */
2057 if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
2059 retvalue = SendMessageA(hWnd, WM_CHILDACTIVATE, 0, 0L);
2060 goto end;
2063 if( hWnd == hwndActive )
2065 retvalue = FALSE;
2066 goto end;
2069 if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
2071 retvalue = FALSE;
2072 goto end;
2075 /* switch desktop queue to current active */
2076 wndTemp = WIN_GetDesktop();
2077 if( wndPtr->parent == wndTemp)
2078 wndTemp->hmemTaskQ = wndPtr->hmemTaskQ;
2079 WIN_ReleaseDesktop();
2081 retvalue = TRUE;
2082 end:
2083 WIN_ReleaseWndPtr(wndPtr);
2084 return retvalue;
2088 /***********************************************************************
2089 * WINPOS_SendNCCalcSize
2091 * Send a WM_NCCALCSIZE message to a window.
2092 * All parameters are read-only except newClientRect.
2093 * oldWindowRect, oldClientRect and winpos must be non-NULL only
2094 * when calcValidRect is TRUE.
2096 LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect,
2097 RECT *newWindowRect, RECT *oldWindowRect,
2098 RECT *oldClientRect, WINDOWPOS *winpos,
2099 RECT *newClientRect )
2101 NCCALCSIZE_PARAMS params;
2102 WINDOWPOS winposCopy;
2103 LONG result;
2105 params.rgrc[0] = *newWindowRect;
2106 if (calcValidRect)
2108 winposCopy = *winpos;
2109 params.rgrc[1] = *oldWindowRect;
2110 params.rgrc[2] = *oldClientRect;
2111 params.lppos = &winposCopy;
2113 result = SendMessageA( hwnd, WM_NCCALCSIZE, calcValidRect,
2114 (LPARAM)&params );
2115 TRACE("%d,%d-%d,%d\n",
2116 params.rgrc[0].left, params.rgrc[0].top,
2117 params.rgrc[0].right, params.rgrc[0].bottom );
2119 /* If the application send back garbage, ignore it */
2120 if (params.rgrc[0].left <= params.rgrc[0].right && params.rgrc[0].top <= params.rgrc[0].bottom)
2121 *newClientRect = params.rgrc[0];
2123 return result;
2127 /***********************************************************************
2128 * WINPOS_HandleWindowPosChanging16
2130 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2132 LONG WINPOS_HandleWindowPosChanging16( WND *wndPtr, WINDOWPOS16 *winpos )
2134 POINT maxSize, minTrack;
2135 if (winpos->flags & SWP_NOSIZE) return 0;
2136 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2137 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2139 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
2140 if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
2141 if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
2142 if (!(wndPtr->dwStyle & WS_MINIMIZE))
2144 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
2145 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
2148 return 0;
2152 /***********************************************************************
2153 * WINPOS_HandleWindowPosChanging
2155 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2157 LONG WINPOS_HandleWindowPosChanging( WND *wndPtr, WINDOWPOS *winpos )
2159 POINT maxSize, minTrack;
2160 if (winpos->flags & SWP_NOSIZE) return 0;
2161 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2162 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2164 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
2165 winpos->cx = min( winpos->cx, maxSize.x );
2166 winpos->cy = min( winpos->cy, maxSize.y );
2167 if (!(wndPtr->dwStyle & WS_MINIMIZE))
2169 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
2170 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
2173 return 0;
2176 /***********************************************************************
2177 * SWP_DoOwnedPopups
2179 * fix Z order taking into account owned popups -
2180 * basically we need to maintain them above the window that owns them
2182 * FIXME: hide/show owned popups when owner visibility changes.
2184 static HWND SWP_DoOwnedPopups(WND* pDesktop, WND* wndPtr, HWND hwndInsertAfter, WORD flags)
2186 WND* w = WIN_LockWndPtr(pDesktop->child);
2188 WARN("(%04x) hInsertAfter = %04x\n", wndPtr->hwndSelf, hwndInsertAfter );
2190 if( (wndPtr->dwStyle & WS_POPUP) && wndPtr->owner )
2192 /* make sure this popup stays above the owner */
2194 HWND hwndLocalPrev = HWND_TOP;
2196 if( hwndInsertAfter != HWND_TOP )
2198 while( w != wndPtr->owner )
2200 if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
2201 if( hwndLocalPrev == hwndInsertAfter ) break;
2202 WIN_UpdateWndPtr(&w,w->next);
2204 hwndInsertAfter = hwndLocalPrev;
2207 else if( wndPtr->dwStyle & WS_CHILD )
2208 goto END;
2210 WIN_UpdateWndPtr(&w, pDesktop->child);
2212 while( w )
2214 if( w == wndPtr ) break;
2216 if( (w->dwStyle & WS_POPUP) && w->owner == wndPtr )
2218 SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0,
2219 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
2220 hwndInsertAfter = w->hwndSelf;
2222 WIN_UpdateWndPtr(&w, w->next);
2225 END:
2226 WIN_ReleaseWndPtr(w);
2227 return hwndInsertAfter;
2230 /***********************************************************************
2231 * SWP_CopyValidBits
2233 * Make window look nice without excessive repainting
2235 * visible and update regions are in window coordinates
2236 * client and window rectangles are in parent client coordinates
2238 * Returns: uFlags and a dirty region in *pVisRgn.
2240 static UINT SWP_CopyValidBits( WND* Wnd, HRGN* pVisRgn,
2241 LPRECT lpOldWndRect,
2242 LPRECT lpOldClientRect, UINT uFlags )
2244 RECT r;
2245 HRGN newVisRgn, dirtyRgn;
2246 INT my = COMPLEXREGION;
2248 TRACE("\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2249 Wnd->rectWindow.left, Wnd->rectWindow.top,
2250 Wnd->rectWindow.right, Wnd->rectWindow.bottom,
2251 lpOldWndRect->left, lpOldWndRect->top,
2252 lpOldWndRect->right, lpOldWndRect->bottom, *pVisRgn);
2253 TRACE("\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2254 Wnd->rectClient.left, Wnd->rectClient.top,
2255 Wnd->rectClient.right, Wnd->rectClient.bottom,
2256 lpOldClientRect->left, lpOldClientRect->top,
2257 lpOldClientRect->right,lpOldClientRect->bottom );
2259 if( Wnd->hrgnUpdate == 1 )
2260 uFlags |= SWP_EX_NOCOPY; /* whole window is invalid, nothing to copy */
2262 newVisRgn = DCE_GetVisRgn( Wnd->hwndSelf, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
2263 dirtyRgn = CreateRectRgn( 0, 0, 0, 0 );
2265 if( !(uFlags & SWP_EX_NOCOPY) ) /* make sure dst region covers only valid bits */
2266 my = CombineRgn( dirtyRgn, newVisRgn, *pVisRgn, RGN_AND );
2268 if( (my == NULLREGION) || (uFlags & SWP_EX_NOCOPY) )
2270 nocopy:
2272 TRACE("\twon't copy anything!\n");
2274 /* set dirtyRgn to the sum of old and new visible regions
2275 * in parent client coordinates */
2277 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2278 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2280 CombineRgn(*pVisRgn, *pVisRgn, newVisRgn, RGN_OR );
2282 else /* copy valid bits to a new location */
2284 INT dx, dy, ow, oh, nw, nh, ocw, ncw, och, nch;
2285 HRGN hrgnValid = dirtyRgn; /* non-empty intersection of old and new visible rgns */
2287 /* subtract already invalid region inside Wnd from the dst region */
2289 if( Wnd->hrgnUpdate )
2290 if( CombineRgn( hrgnValid, hrgnValid, Wnd->hrgnUpdate, RGN_DIFF) == NULLREGION )
2291 goto nocopy;
2293 /* check if entire window can be copied */
2295 ow = lpOldWndRect->right - lpOldWndRect->left;
2296 oh = lpOldWndRect->bottom - lpOldWndRect->top;
2297 nw = Wnd->rectWindow.right - Wnd->rectWindow.left;
2298 nh = Wnd->rectWindow.bottom - Wnd->rectWindow.top;
2300 ocw = lpOldClientRect->right - lpOldClientRect->left;
2301 och = lpOldClientRect->bottom - lpOldClientRect->top;
2302 ncw = Wnd->rectClient.right - Wnd->rectClient.left;
2303 nch = Wnd->rectClient.bottom - Wnd->rectClient.top;
2305 if( (ocw != ncw) || (och != nch) ||
2306 ( ow != nw) || ( oh != nh) ||
2307 ((lpOldClientRect->top - lpOldWndRect->top) !=
2308 (Wnd->rectClient.top - Wnd->rectWindow.top)) ||
2309 ((lpOldClientRect->left - lpOldWndRect->left) !=
2310 (Wnd->rectClient.left - Wnd->rectWindow.left)) )
2312 if(uFlags & SWP_EX_PAINTSELF)
2314 /* movement relative to the window itself */
2315 dx = (Wnd->rectClient.left - Wnd->rectWindow.left) -
2316 (lpOldClientRect->left - lpOldWndRect->left) ;
2317 dy = (Wnd->rectClient.top - Wnd->rectWindow.top) -
2318 (lpOldClientRect->top - lpOldWndRect->top) ;
2320 else
2322 /* movement relative to the parent's client area */
2323 dx = Wnd->rectClient.left - lpOldClientRect->left;
2324 dy = Wnd->rectClient.top - lpOldClientRect->top;
2327 /* restrict valid bits to the common client rect */
2329 r.left = Wnd->rectClient.left - Wnd->rectWindow.left;
2330 r.top = Wnd->rectClient.top - Wnd->rectWindow.top;
2331 r.right = r.left + min( ocw, ncw );
2332 r.bottom = r.top + min( och, nch );
2334 REGION_CropRgn( hrgnValid, hrgnValid, &r,
2335 (uFlags & SWP_EX_PAINTSELF) ? NULL : (POINT*)&(Wnd->rectWindow));
2336 GetRgnBox( hrgnValid, &r );
2337 if( IsRectEmpty( &r ) )
2338 goto nocopy;
2339 r = *lpOldClientRect;
2341 else
2343 if(uFlags & SWP_EX_PAINTSELF) {
2345 * with SWP_EX_PAINTSELF, the window repaints itself. Since a window can't move
2346 * relative to itself, only the client area can change.
2347 * if the client rect didn't change, there's nothing to do.
2349 dx = 0;
2350 dy = 0;
2352 else
2354 dx = Wnd->rectWindow.left - lpOldWndRect->left;
2355 dy = Wnd->rectWindow.top - lpOldWndRect->top;
2356 OffsetRgn( hrgnValid, Wnd->rectWindow.left, Wnd->rectWindow.top );
2358 r = *lpOldWndRect;
2361 if( !(uFlags & SWP_EX_PAINTSELF) )
2363 /* Move remaining regions to parent coordinates */
2364 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2365 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2367 else
2368 OffsetRect( &r, -lpOldWndRect->left, -lpOldWndRect->top );
2370 TRACE("\tcomputing dirty region!\n");
2372 /* Compute combined dirty region (old + new - valid) */
2373 CombineRgn( *pVisRgn, *pVisRgn, newVisRgn, RGN_OR);
2374 CombineRgn( *pVisRgn, *pVisRgn, hrgnValid, RGN_DIFF);
2376 /* Blt valid bits, r is the rect to copy */
2378 if( dx || dy )
2380 RECT rClip;
2381 HDC hDC;
2383 /* get DC and clip rect with drawable rect to avoid superfluous expose events
2384 from copying clipped areas */
2386 if( uFlags & SWP_EX_PAINTSELF )
2388 hDC = GetDCEx( Wnd->hwndSelf, hrgnValid, DCX_WINDOW | DCX_CACHE |
2389 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2390 rClip.right = nw; rClip.bottom = nh;
2392 else
2394 hDC = GetDCEx( Wnd->parent->hwndSelf, hrgnValid, DCX_CACHE |
2395 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2396 rClip.right = Wnd->parent->rectClient.right - Wnd->parent->rectClient.left;
2397 rClip.bottom = Wnd->parent->rectClient.bottom - Wnd->parent->rectClient.top;
2399 rClip.left = rClip.top = 0;
2401 if( oh > nh ) r.bottom = r.top + nh;
2402 if( ow < nw ) r.right = r.left + nw;
2404 if( IntersectRect( &r, &r, &rClip ) )
2406 Wnd->pDriver->pSurfaceCopy( Wnd->parent, hDC, dx, dy, &r, TRUE );
2408 /* When you copy the bits without repainting, parent doesn't
2409 get validated appropriately. Therefore, we have to validate
2410 the parent with the windows' updated region when the
2411 parent's update region is not empty. */
2413 if (Wnd->parent->hrgnUpdate != 0 && !(Wnd->parent->dwStyle & WS_CLIPCHILDREN))
2415 OffsetRect(&r, dx, dy);
2416 ValidateRect(Wnd->parent->hwndSelf, &r);
2419 ReleaseDC( (uFlags & SWP_EX_PAINTSELF) ?
2420 Wnd->hwndSelf : Wnd->parent->hwndSelf, hDC);
2424 /* *pVisRgn now points to the invalidated region */
2426 DeleteObject(newVisRgn);
2427 DeleteObject(dirtyRgn);
2428 return uFlags;
2431 /***********************************************************************
2432 * SWP_DoSimpleFrameChanged
2434 * NOTE: old and new client rect origins are identical, only
2435 * extents may have changed. Window extents are the same.
2437 static void SWP_DoSimpleFrameChanged( WND* wndPtr, RECT* pOldClientRect, WORD swpFlags, UINT uFlags )
2439 INT i = 0;
2440 RECT rect;
2441 HRGN hrgn = 0;
2443 if( !(swpFlags & SWP_NOCLIENTSIZE) )
2445 /* Client rect changed its position/size, most likely a scrollar
2446 * was added/removed.
2448 * FIXME: WVR alignment flags
2451 if( wndPtr->rectClient.right > pOldClientRect->right ) /* right edge */
2453 i++;
2454 rect.top = 0;
2455 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2456 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2457 if(!(uFlags & SWP_EX_NOCOPY))
2458 rect.left = pOldClientRect->right - wndPtr->rectClient.left;
2459 else
2461 rect.left = 0;
2462 goto redraw;
2466 if( wndPtr->rectClient.bottom > pOldClientRect->bottom ) /* bottom edge */
2468 if( i )
2469 hrgn = CreateRectRgnIndirect( &rect );
2470 rect.left = 0;
2471 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2472 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2473 if(!(uFlags & SWP_EX_NOCOPY))
2474 rect.top = pOldClientRect->bottom - wndPtr->rectClient.top;
2475 else
2476 rect.top = 0;
2477 if( i++ )
2478 REGION_UnionRectWithRgn( hrgn, &rect );
2481 if( i == 0 && (uFlags & SWP_EX_NOCOPY) ) /* force redraw anyway */
2483 rect = wndPtr->rectWindow;
2484 OffsetRect( &rect, wndPtr->rectWindow.left - wndPtr->rectClient.left,
2485 wndPtr->rectWindow.top - wndPtr->rectClient.top );
2486 i++;
2490 if( i )
2492 redraw:
2493 PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
2494 RDW_ERASENOW | RDW_ALLCHILDREN, RDW_EX_TOPFRAME | RDW_EX_USEHRGN );
2496 else
2498 WIN_UpdateNCRgn(wndPtr, 0, UNC_UPDATE | UNC_ENTIRE);
2501 if( hrgn > 1 )
2502 DeleteObject( hrgn );
2505 /***********************************************************************
2506 * SWP_DoWinPosChanging
2508 static BOOL SWP_DoWinPosChanging( WND* wndPtr, WINDOWPOS* pWinpos,
2509 RECT* pNewWindowRect, RECT* pNewClientRect )
2511 /* Send WM_WINDOWPOSCHANGING message */
2513 if (!(pWinpos->flags & SWP_NOSENDCHANGING))
2514 SendMessageA( wndPtr->hwndSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM)pWinpos );
2516 /* Calculate new position and size */
2518 *pNewWindowRect = wndPtr->rectWindow;
2519 *pNewClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
2520 : wndPtr->rectClient;
2522 if (!(pWinpos->flags & SWP_NOSIZE))
2524 pNewWindowRect->right = pNewWindowRect->left + pWinpos->cx;
2525 pNewWindowRect->bottom = pNewWindowRect->top + pWinpos->cy;
2527 if (!(pWinpos->flags & SWP_NOMOVE))
2529 pNewWindowRect->left = pWinpos->x;
2530 pNewWindowRect->top = pWinpos->y;
2531 pNewWindowRect->right += pWinpos->x - wndPtr->rectWindow.left;
2532 pNewWindowRect->bottom += pWinpos->y - wndPtr->rectWindow.top;
2534 OffsetRect( pNewClientRect, pWinpos->x - wndPtr->rectWindow.left,
2535 pWinpos->y - wndPtr->rectWindow.top );
2538 pWinpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
2539 return TRUE;
2542 /***********************************************************************
2543 * SWP_DoNCCalcSize
2545 static UINT SWP_DoNCCalcSize( WND* wndPtr, WINDOWPOS* pWinpos,
2546 RECT* pNewWindowRect, RECT* pNewClientRect, WORD f)
2548 UINT wvrFlags = 0;
2550 /* Send WM_NCCALCSIZE message to get new client area */
2551 if( (pWinpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
2553 wvrFlags = WINPOS_SendNCCalcSize( pWinpos->hwnd, TRUE, pNewWindowRect,
2554 &wndPtr->rectWindow, &wndPtr->rectClient,
2555 pWinpos, pNewClientRect );
2557 /* FIXME: WVR_ALIGNxxx */
2559 if( pNewClientRect->left != wndPtr->rectClient.left ||
2560 pNewClientRect->top != wndPtr->rectClient.top )
2561 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2563 if( (pNewClientRect->right - pNewClientRect->left !=
2564 wndPtr->rectClient.right - wndPtr->rectClient.left) ||
2565 (pNewClientRect->bottom - pNewClientRect->top !=
2566 wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
2567 pWinpos->flags &= ~SWP_NOCLIENTSIZE;
2569 else
2570 if( !(f & SWP_NOMOVE) && (pNewClientRect->left != wndPtr->rectClient.left ||
2571 pNewClientRect->top != wndPtr->rectClient.top) )
2572 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2573 return wvrFlags;
2576 /***********************************************************************
2577 * SetWindowPos (USER.232)
2579 BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
2580 INT16 x, INT16 y, INT16 cx, INT16 cy, WORD flags)
2582 return SetWindowPos(hwnd,(INT)(INT16)hwndInsertAfter,x,y,cx,cy,flags);
2585 /***********************************************************************
2586 * SetWindowPos (USER32.@)
2588 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
2589 INT x, INT y, INT cx, INT cy, UINT flags )
2591 WINDOWPOS winpos;
2592 WND * wndPtr,*wndTemp;
2593 RECT newWindowRect, newClientRect;
2594 RECT oldWindowRect, oldClientRect;
2595 HRGN visRgn = 0;
2596 UINT wvrFlags = 0, uFlags = 0;
2597 BOOL retvalue, resync = FALSE, bChangePos;
2598 HWND hwndActive = 0;
2600 /* Get current active window from the active queue */
2601 if ( hActiveQueue )
2603 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2604 if ( pActiveQueue )
2606 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2607 QUEUE_Unlock( pActiveQueue );
2611 TRACE("hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2612 hwnd, x, y, x+cx, y+cy, flags);
2614 bChangePos = !(flags & SWP_WINE_NOHOSTMOVE);
2615 flags &= ~SWP_WINE_NOHOSTMOVE;
2618 /* ------------------------------------------------------------------------ CHECKS */
2620 /* Check window handle */
2622 if (hwnd == GetDesktopWindow()) return FALSE;
2623 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2625 TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr->rectWindow.left, wndPtr->rectWindow.top,
2626 wndPtr->rectWindow.right, wndPtr->rectWindow.bottom, (unsigned)wndPtr->dwStyle );
2628 /* Fix redundant flags */
2630 if(wndPtr->dwStyle & WS_VISIBLE)
2631 flags &= ~SWP_SHOWWINDOW;
2632 else
2634 if (!(flags & SWP_SHOWWINDOW))
2635 flags |= SWP_NOREDRAW;
2636 flags &= ~SWP_HIDEWINDOW;
2639 if ( cx < 0 ) cx = 0; if( cy < 0 ) cy = 0;
2641 if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
2642 (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
2643 flags |= SWP_NOSIZE; /* Already the right size */
2645 if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
2646 flags |= SWP_NOMOVE; /* Already the right position */
2648 if (hwnd == hwndActive)
2649 flags |= SWP_NOACTIVATE; /* Already active */
2650 else if ( (wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD )
2652 if(!(flags & SWP_NOACTIVATE)) /* Bring to the top when activating */
2654 flags &= ~SWP_NOZORDER;
2655 hwndInsertAfter = HWND_TOP;
2656 goto Pos;
2660 /* Check hwndInsertAfter */
2662 /* FIXME: TOPMOST not supported yet */
2663 if ((hwndInsertAfter == HWND_TOPMOST) ||
2664 (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
2666 /* hwndInsertAfter must be a sibling of the window */
2667 if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
2669 WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
2671 if( wnd ) {
2672 if( wnd->parent != wndPtr->parent )
2674 retvalue = FALSE;
2675 WIN_ReleaseWndPtr(wnd);
2676 goto END;
2678 /* don't need to change the Zorder of hwnd if it's already inserted
2679 * after hwndInsertAfter or when inserting hwnd after itself.
2681 if(( wnd->next == wndPtr ) || (hwnd == hwndInsertAfter)) flags |= SWP_NOZORDER;
2683 WIN_ReleaseWndPtr(wnd);
2686 Pos: /* ------------------------------------------------------------------------ MAIN part */
2688 /* Fill the WINDOWPOS structure */
2690 winpos.hwnd = hwnd;
2691 winpos.hwndInsertAfter = hwndInsertAfter;
2692 winpos.x = x;
2693 winpos.y = y;
2694 winpos.cx = cx;
2695 winpos.cy = cy;
2696 winpos.flags = flags;
2698 SWP_DoWinPosChanging( wndPtr, &winpos, &newWindowRect, &newClientRect );
2700 if((winpos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER)
2702 if( wndPtr->parent == WIN_GetDesktop() )
2703 hwndInsertAfter = SWP_DoOwnedPopups( wndPtr->parent, wndPtr,
2704 hwndInsertAfter, winpos.flags );
2705 WIN_ReleaseDesktop();
2708 if(!(wndPtr->flags & WIN_NATIVE) )
2710 if( hwndInsertAfter == HWND_TOP )
2711 winpos.flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
2712 else
2713 if( hwndInsertAfter == HWND_BOTTOM )
2714 winpos.flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
2715 else
2716 if( !(winpos.flags & SWP_NOZORDER) )
2717 if( GetWindow(hwndInsertAfter, GW_HWNDNEXT) == wndPtr->hwndSelf )
2718 winpos.flags |= SWP_NOZORDER;
2720 if( !(winpos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) &&
2721 ((winpos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW | SWP_FRAMECHANGED))
2722 != (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)) )
2724 /* get a previous visible region for SWP_CopyValidBits() */
2725 DWORD dflags = DCX_WINDOW;
2727 if (wndPtr->dwStyle & WS_CLIPSIBLINGS)
2728 dflags |= DCX_CLIPSIBLINGS;
2730 visRgn = DCE_GetVisRgn(hwnd, dflags, 0, 0);
2734 /* Common operations */
2736 wvrFlags = SWP_DoNCCalcSize( wndPtr, &winpos, &newWindowRect, &newClientRect, flags );
2738 if(!(winpos.flags & SWP_NOZORDER) && winpos.hwnd != hwndInsertAfter)
2740 if ( WIN_UnlinkWindow( winpos.hwnd ) )
2741 WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
2744 /* Reset active DCEs */
2746 if( (((winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) &&
2747 wndPtr->dwStyle & WS_VISIBLE) ||
2748 (flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
2750 RECT rect;
2752 UnionRect(&rect, &newWindowRect, &wndPtr->rectWindow);
2753 DCE_InvalidateDCE(wndPtr, &rect);
2756 oldWindowRect = wndPtr->rectWindow;
2757 oldClientRect = wndPtr->rectClient;
2759 /* Find out if we have to redraw the whole client rect */
2761 if( oldClientRect.bottom - oldClientRect.top ==
2762 newClientRect.bottom - newClientRect.top ) wvrFlags &= ~WVR_VREDRAW;
2764 if( oldClientRect.right - oldClientRect.left ==
2765 newClientRect.right - newClientRect.left ) wvrFlags &= ~WVR_HREDRAW;
2767 if( (winpos.flags & SWP_NOCOPYBITS) || (!(winpos.flags & SWP_NOCLIENTSIZE) &&
2768 (wvrFlags >= WVR_HREDRAW) && (wvrFlags < WVR_VALIDRECTS)) )
2770 uFlags |= SWP_EX_NOCOPY;
2773 * Use this later in CopyValidBits()
2775 else if( 0 )
2776 uFlags |= SWP_EX_NONCLIENT;
2779 /* FIXME: actually do something with WVR_VALIDRECTS */
2781 wndPtr->rectWindow = newWindowRect;
2782 wndPtr->rectClient = newClientRect;
2784 if (wndPtr->flags & WIN_NATIVE) /* -------------------------------------------- hosted window */
2786 BOOL bCallDriver = TRUE;
2787 HWND tempInsertAfter = winpos.hwndInsertAfter;
2789 winpos.hwndInsertAfter = hwndInsertAfter;
2791 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2793 /* This is the only place where we need to force repainting of the contents
2794 of windows created by the host window system, all other cases go through the
2795 expose event handling */
2797 if( (winpos.flags & (SWP_NOSIZE | SWP_FRAMECHANGED)) == (SWP_NOSIZE | SWP_FRAMECHANGED) )
2799 cx = newWindowRect.right - newWindowRect.left;
2800 cy = newWindowRect.bottom - newWindowRect.top;
2802 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2803 winpos.hwndInsertAfter = tempInsertAfter;
2804 bCallDriver = FALSE;
2806 if( winpos.flags & SWP_NOCLIENTMOVE )
2807 SWP_DoSimpleFrameChanged(wndPtr, &oldClientRect, winpos.flags, uFlags );
2808 else
2810 /* client area moved but window extents remained the same, copy valid bits */
2812 visRgn = CreateRectRgn( 0, 0, cx, cy );
2813 uFlags = SWP_CopyValidBits( wndPtr, &visRgn, &oldWindowRect, &oldClientRect,
2814 uFlags | SWP_EX_PAINTSELF );
2819 if( bCallDriver )
2821 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2823 if( (oldClientRect.left - oldWindowRect.left == newClientRect.left - newWindowRect.left) &&
2824 (oldClientRect.top - oldWindowRect.top == newClientRect.top - newWindowRect.top) &&
2825 !(uFlags & SWP_EX_NOCOPY) )
2827 /* The origin of the client rect didn't move so we can try to repaint
2828 * only the nonclient area by setting bit gravity hint for the host window system.
2831 if( !(wndPtr->dwExStyle & WS_EX_MANAGED) )
2833 HRGN hrgn = CreateRectRgn( 0, 0, newWindowRect.right - newWindowRect.left,
2834 newWindowRect.bottom - newWindowRect.top);
2835 RECT rcn = newClientRect;
2836 RECT rco = oldClientRect;
2838 OffsetRect( &rcn, -newWindowRect.left, -newWindowRect.top );
2839 OffsetRect( &rco, -oldWindowRect.left, -oldWindowRect.top );
2840 IntersectRect( &rcn, &rcn, &rco );
2841 visRgn = CreateRectRgnIndirect( &rcn );
2842 CombineRgn( visRgn, hrgn, visRgn, RGN_DIFF );
2843 DeleteObject( hrgn );
2844 uFlags = SWP_EX_PAINTSELF;
2846 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGNorthWest );
2850 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2851 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGForget );
2852 winpos.hwndInsertAfter = tempInsertAfter;
2855 if( winpos.flags & SWP_SHOWWINDOW )
2857 HWND focus, curr;
2859 wndPtr->dwStyle |= WS_VISIBLE;
2861 if (wndPtr->dwExStyle & WS_EX_MANAGED) resync = TRUE;
2863 /* focus was set to unmapped window, reset host focus
2864 * since the window is now visible */
2866 focus = curr = GetFocus();
2867 while (curr)
2869 if (curr == hwnd)
2871 WND *pFocus = WIN_FindWndPtr( focus );
2872 if (pFocus)
2873 pFocus->pDriver->pSetFocus(pFocus);
2874 WIN_ReleaseWndPtr(pFocus);
2875 break;
2877 curr = GetParent(curr);
2881 else /* -------------------------------------------- emulated window */
2883 if( winpos.flags & SWP_SHOWWINDOW )
2885 wndPtr->dwStyle |= WS_VISIBLE;
2886 uFlags |= SWP_EX_PAINTSELF;
2887 visRgn = 1; /* redraw the whole window */
2889 else if( !(winpos.flags & SWP_NOREDRAW) )
2891 if( winpos.flags & SWP_HIDEWINDOW )
2893 if( visRgn > 1 ) /* map to parent */
2894 OffsetRgn( visRgn, oldWindowRect.left, oldWindowRect.top );
2895 else
2896 visRgn = 0;
2898 else
2900 if( (winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE )
2902 /* if window was not resized and not moved try to repaint itself */
2903 if((winpos.flags & SWP_AGG_NOGEOMETRYCHANGE) == SWP_AGG_NOGEOMETRYCHANGE)
2904 uFlags |= SWP_EX_PAINTSELF;
2905 uFlags = SWP_CopyValidBits(wndPtr, &visRgn, &oldWindowRect,
2906 &oldClientRect, uFlags);
2908 else
2910 /* nothing moved, redraw frame if needed */
2912 if( winpos.flags & SWP_FRAMECHANGED )
2913 SWP_DoSimpleFrameChanged( wndPtr, &oldClientRect, winpos.flags, uFlags );
2914 if( visRgn )
2916 DeleteObject( visRgn );
2917 visRgn = 0;
2924 if( winpos.flags & SWP_HIDEWINDOW )
2926 wndPtr->dwStyle &= ~WS_VISIBLE;
2929 if (hwnd == CARET_GetHwnd())
2931 if( winpos.flags & SWP_HIDEWINDOW )
2932 HideCaret(hwnd);
2933 else if (winpos.flags & SWP_SHOWWINDOW)
2934 ShowCaret(hwnd);
2937 /* ------------------------------------------------------------------------ FINAL */
2939 if (wndPtr->flags & WIN_NATIVE)
2940 EVENT_Synchronize(); /* Synchronize with the host window system */
2942 wndTemp = WIN_GetDesktop();
2944 /* repaint invalidated region (if any)
2946 * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2947 * and force update after ChangeActiveWindow() to avoid painting frames twice.
2950 if( visRgn )
2952 if( !(winpos.flags & SWP_NOREDRAW) )
2955 /* Use PAINT_RedrawWindow to explicitly force an invalidation of the window,
2956 its parent and sibling and so on, and then erase the parent window
2957 back ground if the parent is either a top-level window or its parent's parent
2958 is top-level window. Rely on the system to repaint other affected
2959 windows later on. */
2960 if( uFlags & SWP_EX_PAINTSELF )
2962 PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn,
2963 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN,
2964 RDW_EX_XYWINDOW | RDW_EX_USEHRGN );
2966 else
2968 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn,
2969 RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN,
2970 RDW_EX_USEHRGN );
2973 if(wndPtr -> parent == wndTemp || wndPtr->parent->parent == wndTemp )
2975 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0,
2976 RDW_ERASENOW | RDW_NOCHILDREN, 0 );
2979 if( visRgn != 1 )
2980 DeleteObject( visRgn );
2983 WIN_ReleaseDesktop();
2985 if (!(flags & SWP_NOACTIVATE))
2986 WINPOS_ChangeActiveWindow( winpos.hwnd, FALSE );
2988 /* And last, send the WM_WINDOWPOSCHANGED message */
2990 TRACE("\tstatus flags = %04x\n", winpos.flags & SWP_AGG_STATUSFLAGS);
2992 if ( resync ||
2993 (((winpos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) &&
2994 !(winpos.flags & SWP_NOSENDCHANGING)) )
2996 SendMessageA( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
2997 if (resync) EVENT_Synchronize();
3000 retvalue = TRUE;
3001 END:
3002 WIN_ReleaseWndPtr(wndPtr);
3003 return retvalue;
3007 /***********************************************************************
3008 * BeginDeferWindowPos (USER.259)
3010 HDWP16 WINAPI BeginDeferWindowPos16( INT16 count )
3012 return BeginDeferWindowPos( count );
3016 /***********************************************************************
3017 * BeginDeferWindowPos (USER32.@)
3019 HDWP WINAPI BeginDeferWindowPos( INT count )
3021 HDWP handle;
3022 DWP *pDWP;
3024 if (count < 0)
3026 SetLastError(ERROR_INVALID_PARAMETER);
3027 return 0;
3029 /* Windows allows zero count, in which case it allocates context for 8 moves */
3030 if (count == 0) count = 8;
3032 handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
3033 if (!handle) return 0;
3034 pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
3035 pDWP->actualCount = 0;
3036 pDWP->suggestedCount = count;
3037 pDWP->valid = TRUE;
3038 pDWP->wMagic = DWP_MAGIC;
3039 pDWP->hwndParent = 0;
3040 return handle;
3044 /***********************************************************************
3045 * DeferWindowPos (USER.260)
3047 HDWP16 WINAPI DeferWindowPos16( HDWP16 hdwp, HWND16 hwnd, HWND16 hwndAfter,
3048 INT16 x, INT16 y, INT16 cx, INT16 cy,
3049 UINT16 flags )
3051 return DeferWindowPos( hdwp, hwnd, (INT)(INT16)hwndAfter,
3052 x, y, cx, cy, flags );
3056 /***********************************************************************
3057 * DeferWindowPos (USER32.@)
3059 HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter,
3060 INT x, INT y, INT cx, INT cy,
3061 UINT flags )
3063 DWP *pDWP;
3064 int i;
3065 HDWP newhdwp = hdwp,retvalue;
3066 /* HWND parent; */
3067 WND *pWnd;
3069 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
3070 if (!pDWP) return 0;
3071 if (hwnd == GetDesktopWindow()) return 0;
3073 if (!(pWnd=WIN_FindWndPtr( hwnd ))) {
3074 USER_HEAP_FREE( hdwp );
3075 return 0;
3078 /* Numega Bounds Checker Demo dislikes the following code.
3079 In fact, I've not been able to find any "same parent" requirement in any docu
3080 [AM 980509]
3082 #if 0
3083 /* All the windows of a DeferWindowPos() must have the same parent */
3084 parent = pWnd->parent->hwndSelf;
3085 if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
3086 else if (parent != pDWP->hwndParent)
3088 USER_HEAP_FREE( hdwp );
3089 retvalue = 0;
3090 goto END;
3092 #endif
3094 for (i = 0; i < pDWP->actualCount; i++)
3096 if (pDWP->winPos[i].hwnd == hwnd)
3098 /* Merge with the other changes */
3099 if (!(flags & SWP_NOZORDER))
3101 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
3103 if (!(flags & SWP_NOMOVE))
3105 pDWP->winPos[i].x = x;
3106 pDWP->winPos[i].y = y;
3108 if (!(flags & SWP_NOSIZE))
3110 pDWP->winPos[i].cx = cx;
3111 pDWP->winPos[i].cy = cy;
3113 pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
3114 SWP_NOZORDER | SWP_NOREDRAW |
3115 SWP_NOACTIVATE | SWP_NOCOPYBITS|
3116 SWP_NOOWNERZORDER);
3117 pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
3118 SWP_FRAMECHANGED);
3119 retvalue = hdwp;
3120 goto END;
3123 if (pDWP->actualCount >= pDWP->suggestedCount)
3125 newhdwp = USER_HEAP_REALLOC( hdwp,
3126 sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
3127 if (!newhdwp)
3129 retvalue = 0;
3130 goto END;
3132 pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
3133 pDWP->suggestedCount++;
3135 pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
3136 pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
3137 pDWP->winPos[pDWP->actualCount].x = x;
3138 pDWP->winPos[pDWP->actualCount].y = y;
3139 pDWP->winPos[pDWP->actualCount].cx = cx;
3140 pDWP->winPos[pDWP->actualCount].cy = cy;
3141 pDWP->winPos[pDWP->actualCount].flags = flags;
3142 pDWP->actualCount++;
3143 retvalue = newhdwp;
3144 END:
3145 WIN_ReleaseWndPtr(pWnd);
3146 return retvalue;
3150 /***********************************************************************
3151 * EndDeferWindowPos (USER.261)
3153 BOOL16 WINAPI EndDeferWindowPos16( HDWP16 hdwp )
3155 return EndDeferWindowPos( hdwp );
3159 /***********************************************************************
3160 * EndDeferWindowPos (USER32.@)
3162 BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
3164 DWP *pDWP;
3165 WINDOWPOS *winpos;
3166 BOOL res = TRUE;
3167 int i;
3169 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
3170 if (!pDWP) return FALSE;
3171 for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
3173 if (!(res = SetWindowPos( winpos->hwnd, winpos->hwndInsertAfter,
3174 winpos->x, winpos->y, winpos->cx,
3175 winpos->cy, winpos->flags ))) break;
3177 USER_HEAP_FREE( hdwp );
3178 return res;
3182 /***********************************************************************
3183 * TileChildWindows (USER.199)
3185 void WINAPI TileChildWindows16( HWND16 parent, WORD action )
3187 FIXME("(%04x, %d): stub\n", parent, action);
3190 /***********************************************************************
3191 * CascadeChildWindows (USER.198)
3193 void WINAPI CascadeChildWindows16( HWND16 parent, WORD action )
3195 FIXME("(%04x, %d): stub\n", parent, action);
3198 /***********************************************************************
3199 * SetProgmanWindow (USER32.@)
3201 HRESULT WINAPI SetProgmanWindow ( HWND hwnd )
3203 hGlobalProgmanWindow = hwnd;
3204 return hGlobalProgmanWindow;
3207 /***********************************************************************
3208 * GetProgmanWindow (USER32.@)
3210 HRESULT WINAPI GetProgmanWindow ( )
3212 return hGlobalProgmanWindow;
3215 /***********************************************************************
3216 * SetShellWindowEx (USER32.@)
3217 * hwndProgman = Progman[Program Manager]
3218 * |-> SHELLDLL_DefView
3219 * hwndListView = | |-> SysListView32
3220 * | | |-> tooltips_class32
3221 * | |
3222 * | |-> SysHeader32
3223 * |
3224 * |-> ProxyTarget
3226 HRESULT WINAPI SetShellWindowEx ( HWND hwndProgman, HWND hwndListView )
3228 FIXME("0x%08x 0x%08x stub\n",hwndProgman ,hwndListView );
3229 hGlobalShellWindow = hwndProgman;
3230 return hGlobalShellWindow;
3234 /***********************************************************************
3235 * SetTaskmanWindow (USER32.@)
3236 * NOTES
3237 * hwnd = MSTaskSwWClass
3238 * |-> SysTabControl32
3240 HRESULT WINAPI SetTaskmanWindow ( HWND hwnd )
3242 hGlobalTaskmanWindow = hwnd;
3243 return hGlobalTaskmanWindow;
3246 /***********************************************************************
3247 * GetTaskmanWindow (USER32.@)
3249 HRESULT WINAPI GetTaskmanWindow ( )
3251 return hGlobalTaskmanWindow;