Make SGML ID attributes in packaging.sgml more unique to avoid
[wine/wine64.git] / windows / winpos.c
bloba74da46b6b8ab073dbc046b561defd800cabf01f
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 * SetActiveWindow16 (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 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
1306 swpFlags |= MINMAX_NOSWP;
1308 wndPtr->dwStyle &= ~WS_MINIMIZE;
1309 WINPOS_ShowIconTitle( wndPtr, FALSE );
1311 if( wndPtr->flags & WIN_RESTORE_MAX)
1313 /* Restore to maximized position */
1314 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1315 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL);
1316 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1317 wndPtr->dwStyle |= WS_MAXIMIZE;
1318 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y, size.x, size.y );
1319 break;
1322 else
1323 if( !(wndPtr->dwStyle & WS_MAXIMIZE) ) return (UINT16)(-1);
1324 else wndPtr->dwStyle &= ~WS_MAXIMIZE;
1326 /* Restore to normal position */
1328 *lpRect = lpPos->rectNormal;
1329 lpRect->right -= lpRect->left;
1330 lpRect->bottom -= lpRect->top;
1332 break;
1334 } else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
1335 return swpFlags;
1338 /***********************************************************************
1339 * ShowWindowAsync (USER32.@)
1341 * doesn't wait; returns immediately.
1342 * used by threads to toggle windows in other (possibly hanging) threads
1344 BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd )
1346 /* FIXME: does ShowWindow() return immediately ? */
1347 return ShowWindow(hwnd, cmd);
1351 /***********************************************************************
1352 * ShowWindow (USER.42)
1354 BOOL16 WINAPI ShowWindow16( HWND16 hwnd, INT16 cmd )
1356 return ShowWindow(hwnd,cmd);
1360 /***********************************************************************
1361 * ShowWindow (USER32.@)
1363 BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
1365 WND* wndPtr = WIN_FindWndPtr( hwnd );
1366 BOOL wasVisible, showFlag;
1367 RECT16 newPos = {0, 0, 0, 0};
1368 UINT swp = 0;
1370 if (!wndPtr) return FALSE;
1372 TRACE("hwnd=%04x, cmd=%d\n", hwnd, cmd);
1374 wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
1376 switch(cmd)
1378 case SW_HIDE:
1379 if (!wasVisible) goto END;;
1380 swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
1381 SWP_NOACTIVATE | SWP_NOZORDER;
1382 break;
1384 case SW_SHOWMINNOACTIVE:
1385 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1386 /* fall through */
1387 case SW_SHOWMINIMIZED:
1388 swp |= SWP_SHOWWINDOW;
1389 /* fall through */
1390 case SW_MINIMIZE:
1391 swp |= SWP_FRAMECHANGED;
1392 if( !(wndPtr->dwStyle & WS_MINIMIZE) )
1393 swp |= WINPOS_MinMaximize( wndPtr, SW_MINIMIZE, &newPos );
1394 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1395 break;
1397 case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
1398 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1399 if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
1400 swp |= WINPOS_MinMaximize( wndPtr, SW_MAXIMIZE, &newPos );
1401 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1402 break;
1404 case SW_SHOWNA:
1405 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1406 /* fall through */
1407 case SW_SHOW:
1408 swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
1411 * ShowWindow has a little peculiar behavior that if the
1412 * window is already the topmost window, it will not
1413 * activate it.
1415 if (GetTopWindow((HWND)0)==hwnd && (wasVisible || GetActiveWindow() == hwnd))
1416 swp |= SWP_NOACTIVATE;
1418 break;
1420 case SW_SHOWNOACTIVATE:
1421 swp |= SWP_NOZORDER;
1422 if (GetActiveWindow()) swp |= SWP_NOACTIVATE;
1423 /* fall through */
1424 case SW_SHOWNORMAL: /* same as SW_NORMAL: */
1425 case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
1426 case SW_RESTORE:
1427 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1429 if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) )
1430 swp |= WINPOS_MinMaximize( wndPtr, SW_RESTORE, &newPos );
1431 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1432 break;
1435 showFlag = (cmd != SW_HIDE);
1436 if (showFlag != wasVisible)
1438 SendMessageA( hwnd, WM_SHOWWINDOW, showFlag, 0 );
1439 if (!IsWindow( hwnd )) goto END;
1442 if ((wndPtr->dwStyle & WS_CHILD) &&
1443 !IsWindowVisible( wndPtr->parent->hwndSelf ) &&
1444 (swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE) )
1446 /* Don't call SetWindowPos() on invisible child windows */
1447 if (cmd == SW_HIDE) wndPtr->dwStyle &= ~WS_VISIBLE;
1448 else wndPtr->dwStyle |= WS_VISIBLE;
1450 else
1452 /* We can't activate a child window */
1453 if ((wndPtr->dwStyle & WS_CHILD) &&
1454 !(wndPtr->dwExStyle & WS_EX_MDICHILD))
1455 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1456 if (!(swp & MINMAX_NOSWP))
1458 SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top,
1459 newPos.right, newPos.bottom, LOWORD(swp) );
1460 if (cmd == SW_HIDE)
1462 /* FIXME: This will cause the window to be activated irrespective
1463 * of whether it is owned by the same thread. Has to be done
1464 * asynchronously.
1467 if (hwnd == GetActiveWindow())
1468 WINPOS_ActivateOtherWindow(wndPtr);
1470 /* Revert focus to parent */
1471 if (hwnd == GetFocus() || IsChild(hwnd, GetFocus()))
1472 SetFocus( GetParent(hwnd) );
1475 if (!IsWindow( hwnd )) goto END;
1476 else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( wndPtr, TRUE );
1479 if (wndPtr->flags & WIN_NEED_SIZE)
1481 /* should happen only in CreateWindowEx() */
1482 int wParam = SIZE_RESTORED;
1484 wndPtr->flags &= ~WIN_NEED_SIZE;
1485 if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
1486 else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
1487 SendMessageA( hwnd, WM_SIZE, wParam,
1488 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
1489 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
1490 SendMessageA( hwnd, WM_MOVE, 0,
1491 MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
1494 END:
1495 WIN_ReleaseWndPtr(wndPtr);
1496 return wasVisible;
1500 /***********************************************************************
1501 * GetInternalWindowPos (USER.460)
1503 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
1504 LPPOINT16 ptIcon )
1506 WINDOWPLACEMENT16 wndpl;
1507 if (GetWindowPlacement16( hwnd, &wndpl ))
1509 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1510 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1511 return wndpl.showCmd;
1513 return 0;
1517 /***********************************************************************
1518 * GetInternalWindowPos (USER32.@)
1520 UINT WINAPI GetInternalWindowPos( HWND hwnd, LPRECT rectWnd,
1521 LPPOINT ptIcon )
1523 WINDOWPLACEMENT wndpl;
1524 if (GetWindowPlacement( hwnd, &wndpl ))
1526 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1527 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1528 return wndpl.showCmd;
1530 return 0;
1533 /***********************************************************************
1534 * GetWindowPlacement (USER.370)
1536 BOOL16 WINAPI GetWindowPlacement16( HWND16 hwnd, WINDOWPLACEMENT16 *wndpl )
1538 WND *pWnd = WIN_FindWndPtr( hwnd );
1539 LPINTERNALPOS lpPos;
1541 if(!pWnd ) return FALSE;
1543 lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1544 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1545 wndpl->length = sizeof(*wndpl);
1546 if( pWnd->dwStyle & WS_MINIMIZE )
1547 wndpl->showCmd = SW_SHOWMINIMIZED;
1548 else
1549 wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE )
1550 ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
1551 if( pWnd->flags & WIN_RESTORE_MAX )
1552 wndpl->flags = WPF_RESTORETOMAXIMIZED;
1553 else
1554 wndpl->flags = 0;
1555 wndpl->ptMinPosition = lpPos->ptIconPos;
1556 wndpl->ptMaxPosition = lpPos->ptMaxPos;
1557 wndpl->rcNormalPosition = lpPos->rectNormal;
1559 WIN_ReleaseWndPtr(pWnd);
1560 return TRUE;
1564 /***********************************************************************
1565 * GetWindowPlacement (USER32.@)
1567 * Win95:
1568 * Fails if wndpl->length of Win95 (!) apps is invalid.
1570 BOOL WINAPI GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *pwpl32 )
1572 if( pwpl32 )
1574 WINDOWPLACEMENT16 wpl;
1575 wpl.length = sizeof(wpl);
1576 if( GetWindowPlacement16( hwnd, &wpl ) )
1578 pwpl32->length = sizeof(*pwpl32);
1579 pwpl32->flags = wpl.flags;
1580 pwpl32->showCmd = wpl.showCmd;
1581 CONV_POINT16TO32( &wpl.ptMinPosition, &pwpl32->ptMinPosition );
1582 CONV_POINT16TO32( &wpl.ptMaxPosition, &pwpl32->ptMaxPosition );
1583 CONV_RECT16TO32( &wpl.rcNormalPosition, &pwpl32->rcNormalPosition );
1584 return TRUE;
1587 return FALSE;
1591 /***********************************************************************
1592 * WINPOS_SetPlacement
1594 static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT16 *wndpl,
1595 UINT flags )
1597 WND *pWnd = WIN_FindWndPtr( hwnd );
1598 if( pWnd )
1600 LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1601 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1603 if( flags & PLACE_MIN ) lpPos->ptIconPos = wndpl->ptMinPosition;
1604 if( flags & PLACE_MAX ) lpPos->ptMaxPos = wndpl->ptMaxPosition;
1605 if( flags & PLACE_RECT) lpPos->rectNormal = wndpl->rcNormalPosition;
1607 if( pWnd->dwStyle & WS_MINIMIZE )
1609 WINPOS_ShowIconTitle( pWnd, FALSE );
1610 if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1611 SetWindowPos( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1612 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1614 else if( pWnd->dwStyle & WS_MAXIMIZE )
1616 if( !EMPTYPOINT(lpPos->ptMaxPos) )
1617 SetWindowPos( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1618 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1620 else if( flags & PLACE_RECT )
1621 SetWindowPos( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1622 lpPos->rectNormal.right - lpPos->rectNormal.left,
1623 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1624 SWP_NOZORDER | SWP_NOACTIVATE );
1626 ShowWindow( hwnd, wndpl->showCmd );
1627 if( IsWindow(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1629 if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd, TRUE );
1631 /* SDK: ...valid only the next time... */
1632 if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1634 WIN_ReleaseWndPtr(pWnd);
1635 return TRUE;
1637 return FALSE;
1641 /***********************************************************************
1642 * SetWindowPlacement (USER.371)
1644 BOOL16 WINAPI SetWindowPlacement16(HWND16 hwnd, const WINDOWPLACEMENT16 *wndpl)
1646 return WINPOS_SetPlacement( hwnd, wndpl,
1647 PLACE_MIN | PLACE_MAX | PLACE_RECT );
1650 /***********************************************************************
1651 * SetWindowPlacement (USER32.@)
1653 * Win95:
1654 * Fails if wndpl->length of Win95 (!) apps is invalid.
1656 BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *pwpl32 )
1658 if( pwpl32 )
1660 WINDOWPLACEMENT16 wpl;
1662 wpl.length = sizeof(WINDOWPLACEMENT16);
1663 wpl.flags = pwpl32->flags;
1664 wpl.showCmd = pwpl32->showCmd;
1665 wpl.ptMinPosition.x = pwpl32->ptMinPosition.x;
1666 wpl.ptMinPosition.y = pwpl32->ptMinPosition.y;
1667 wpl.ptMaxPosition.x = pwpl32->ptMaxPosition.x;
1668 wpl.ptMaxPosition.y = pwpl32->ptMaxPosition.y;
1669 wpl.rcNormalPosition.left = pwpl32->rcNormalPosition.left;
1670 wpl.rcNormalPosition.top = pwpl32->rcNormalPosition.top;
1671 wpl.rcNormalPosition.right = pwpl32->rcNormalPosition.right;
1672 wpl.rcNormalPosition.bottom = pwpl32->rcNormalPosition.bottom;
1674 return WINPOS_SetPlacement( hwnd, &wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1676 return FALSE;
1680 /***********************************************************************
1681 * SetInternalWindowPos (USER.461)
1683 void WINAPI SetInternalWindowPos16( HWND16 hwnd, UINT16 showCmd,
1684 LPRECT16 rect, LPPOINT16 pt )
1686 if( IsWindow16(hwnd) )
1688 WINDOWPLACEMENT16 wndpl;
1689 UINT flags;
1691 wndpl.length = sizeof(wndpl);
1692 wndpl.showCmd = showCmd;
1693 wndpl.flags = flags = 0;
1695 if( pt )
1697 flags |= PLACE_MIN;
1698 wndpl.flags |= WPF_SETMINPOSITION;
1699 wndpl.ptMinPosition = *pt;
1701 if( rect )
1703 flags |= PLACE_RECT;
1704 wndpl.rcNormalPosition = *rect;
1706 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1711 /***********************************************************************
1712 * SetInternalWindowPos (USER32.@)
1714 void WINAPI SetInternalWindowPos( HWND hwnd, UINT showCmd,
1715 LPRECT rect, LPPOINT pt )
1717 if( IsWindow(hwnd) )
1719 WINDOWPLACEMENT16 wndpl;
1720 UINT flags;
1722 wndpl.length = sizeof(wndpl);
1723 wndpl.showCmd = showCmd;
1724 wndpl.flags = flags = 0;
1726 if( pt )
1728 flags |= PLACE_MIN;
1729 wndpl.flags |= WPF_SETMINPOSITION;
1730 CONV_POINT32TO16( pt, &wndpl.ptMinPosition );
1732 if( rect )
1734 flags |= PLACE_RECT;
1735 CONV_RECT32TO16( rect, &wndpl.rcNormalPosition );
1737 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1741 /*******************************************************************
1742 * WINPOS_SetActiveWindow
1744 * SetActiveWindow() back-end. This is the only function that
1745 * can assign active status to a window. It must be called only
1746 * for the top level windows.
1748 BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
1750 CBTACTIVATESTRUCT16* cbtStruct;
1751 WND* wndPtr=0, *wndTemp;
1752 HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1753 MESSAGEQUEUE *pOldActiveQueue = 0, *pNewActiveQueue = 0;
1754 WORD wIconized = 0;
1755 HWND hwndActive = 0;
1756 BOOL bRet = 0;
1758 TRACE("(%04x, %d, %d)\n", hWnd, fMouse, fChangeFocus );
1760 /* Get current active window from the active queue */
1761 if ( hActiveQueue )
1763 pOldActiveQueue = QUEUE_Lock( hActiveQueue );
1764 if ( pOldActiveQueue )
1765 hwndActive = PERQDATA_GetActiveWnd( pOldActiveQueue->pQData );
1768 /* paranoid checks */
1769 if( hWnd == GetDesktopWindow() || (bRet = (hWnd == hwndActive)) )
1770 goto CLEANUP_END;
1772 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1773 * return 0;
1775 wndPtr = WIN_FindWndPtr(hWnd);
1776 hOldActiveQueue = hActiveQueue;
1778 if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1780 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1781 WIN_ReleaseWndPtr(wndTemp);
1783 else
1784 TRACE("no current active window.\n");
1786 /* call CBT hook chain */
1787 if ((cbtStruct = SEGPTR_NEW(CBTACTIVATESTRUCT16)))
1789 cbtStruct->fMouse = fMouse;
1790 cbtStruct->hWndActive = hwndActive;
1791 bRet = (BOOL)HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
1792 (LPARAM)SEGPTR_GET(cbtStruct) );
1793 SEGPTR_FREE(cbtStruct);
1794 if (bRet) goto CLEANUP_END;
1797 /* set prev active wnd to current active wnd and send notification */
1798 if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
1800 MESSAGEQUEUE *pTempActiveQueue = 0;
1802 if (!SendMessageA( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1804 if (GetSysModalWindow16() != hWnd)
1805 goto CLEANUP_END;
1806 /* disregard refusal if hWnd is sysmodal */
1809 SendMessageA( hwndPrevActive, WM_ACTIVATE,
1810 MAKEWPARAM( WA_INACTIVE, wIconized ),
1811 (LPARAM)hWnd );
1813 /* check if something happened during message processing
1814 * (global active queue may have changed)
1816 pTempActiveQueue = QUEUE_Lock( hActiveQueue );
1817 if(!pTempActiveQueue)
1818 goto CLEANUP_END;
1820 hwndActive = PERQDATA_GetActiveWnd( pTempActiveQueue->pQData );
1821 QUEUE_Unlock( pTempActiveQueue );
1822 if( hwndPrevActive != hwndActive )
1823 goto CLEANUP_END;
1826 /* Set new active window in the message queue */
1827 hwndActive = hWnd;
1828 if ( wndPtr )
1830 pNewActiveQueue = QUEUE_Lock( wndPtr->hmemTaskQ );
1831 if ( pNewActiveQueue )
1832 PERQDATA_SetActiveWnd( pNewActiveQueue->pQData, hwndActive );
1834 else /* have to do this or MDI frame activation goes to hell */
1835 if( pOldActiveQueue )
1836 PERQDATA_SetActiveWnd( pOldActiveQueue->pQData, 0 );
1838 /* send palette messages */
1839 if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1840 SendMessage16((HWND16)-1, WM_PALETTEISCHANGING, (WPARAM16)hWnd, 0L );
1842 /* if prev wnd is minimized redraw icon title */
1843 if( IsIconic( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1845 /* managed windows will get ConfigureNotify event */
1846 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_MANAGED))
1848 /* check Z-order and bring hWnd to the top */
1849 for (wndTemp = WIN_LockWndPtr(WIN_GetDesktop()->child); wndTemp; WIN_UpdateWndPtr(&wndTemp,wndTemp->next))
1851 if (wndTemp->dwStyle & WS_VISIBLE) break;
1853 WIN_ReleaseDesktop();
1854 WIN_ReleaseWndPtr(wndTemp);
1856 if( wndTemp != wndPtr )
1857 SetWindowPos(hWnd, HWND_TOP, 0,0,0,0,
1858 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1859 if (!IsWindow(hWnd))
1860 goto CLEANUP;
1863 /* Get a handle to the new active queue */
1864 hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1866 /* send WM_ACTIVATEAPP if necessary */
1867 if (hOldActiveQueue != hNewActiveQueue)
1869 WND **list, **ppWnd;
1870 WND *pDesktop = WIN_GetDesktop();
1872 if ((list = WIN_BuildWinArray( pDesktop, 0, NULL )))
1874 for (ppWnd = list; *ppWnd; ppWnd++)
1876 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1878 if ((*ppWnd)->hmemTaskQ == hOldActiveQueue)
1879 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1880 0, QUEUE_GetQueueTask(hNewActiveQueue) );
1882 WIN_ReleaseWinArray(list);
1885 hActiveQueue = hNewActiveQueue;
1887 if ((list = WIN_BuildWinArray(pDesktop, 0, NULL )))
1889 for (ppWnd = list; *ppWnd; ppWnd++)
1891 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1893 if ((*ppWnd)->hmemTaskQ == hNewActiveQueue)
1894 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1895 1, QUEUE_GetQueueTask( hOldActiveQueue ) );
1897 WIN_ReleaseWinArray(list);
1899 WIN_ReleaseDesktop();
1901 if (hWnd && !IsWindow(hWnd)) goto CLEANUP;
1904 if (hWnd)
1906 /* walk up to the first unowned window */
1907 wndTemp = WIN_LockWndPtr(wndPtr);
1908 while (wndTemp->owner)
1910 WIN_UpdateWndPtr(&wndTemp,wndTemp->owner);
1912 /* and set last active owned popup */
1913 wndTemp->hwndLastActive = hWnd;
1915 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1916 WIN_ReleaseWndPtr(wndTemp);
1917 SendMessageA( hWnd, WM_NCACTIVATE, TRUE, 0 );
1918 SendMessageA( hWnd, WM_ACTIVATE,
1919 MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1920 (LPARAM)hwndPrevActive );
1921 if( !IsWindow(hWnd) ) goto CLEANUP;
1924 /* change focus if possible */
1925 if ( fChangeFocus )
1927 if ( pNewActiveQueue )
1929 HWND hOldFocus = PERQDATA_GetFocusWnd( pNewActiveQueue->pQData );
1931 if ( hOldFocus && WIN_GetTopParent( hOldFocus ) != hwndActive )
1932 FOCUS_SwitchFocus( pNewActiveQueue, hOldFocus,
1933 (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
1934 0 : hwndActive );
1937 if ( pOldActiveQueue &&
1938 ( !pNewActiveQueue ||
1939 pNewActiveQueue->pQData != pOldActiveQueue->pQData ) )
1941 HWND hOldFocus = PERQDATA_GetFocusWnd( pOldActiveQueue->pQData );
1942 if ( hOldFocus )
1943 FOCUS_SwitchFocus( pOldActiveQueue, hOldFocus, 0 );
1947 if( !hwndPrevActive && wndPtr )
1948 (*wndPtr->pDriver->pForceWindowRaise)(wndPtr);
1950 /* if active wnd is minimized redraw icon title */
1951 if( IsIconic(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1953 bRet = (hWnd == hwndActive); /* Success? */
1955 CLEANUP: /* Unlock the message queues before returning */
1957 if ( pNewActiveQueue )
1958 QUEUE_Unlock( pNewActiveQueue );
1960 CLEANUP_END:
1962 if ( pOldActiveQueue )
1963 QUEUE_Unlock( pOldActiveQueue );
1965 WIN_ReleaseWndPtr(wndPtr);
1966 return bRet;
1969 /*******************************************************************
1970 * WINPOS_ActivateOtherWindow
1972 * Activates window other than pWnd.
1974 BOOL WINPOS_ActivateOtherWindow(WND* pWnd)
1976 BOOL bRet = 0;
1977 WND* pWndTo = NULL;
1978 HWND hwndActive = 0;
1980 /* Get current active window from the active queue */
1981 if ( hActiveQueue )
1983 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1984 if ( pActiveQueue )
1986 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1987 QUEUE_Unlock( pActiveQueue );
1991 if( pWnd->hwndSelf == hwndPrevActive )
1992 hwndPrevActive = 0;
1994 if( hwndActive != pWnd->hwndSelf &&
1995 ( hwndActive || QUEUE_IsExitingQueue(pWnd->hmemTaskQ)) )
1996 return 0;
1998 if( !(pWnd->dwStyle & WS_POPUP) || !(pWnd->owner) ||
1999 !WINPOS_CanActivate((pWndTo = WIN_GetTopParentPtr(pWnd->owner))) )
2001 WND* pWndPtr = WIN_GetTopParentPtr(pWnd);
2003 WIN_ReleaseWndPtr(pWndTo);
2004 pWndTo = WIN_FindWndPtr(hwndPrevActive);
2006 while( !WINPOS_CanActivate(pWndTo) )
2008 /* by now owned windows should've been taken care of */
2009 WIN_UpdateWndPtr(&pWndTo,pWndPtr->next);
2010 WIN_UpdateWndPtr(&pWndPtr,pWndTo);
2011 if( !pWndTo ) break;
2013 WIN_ReleaseWndPtr(pWndPtr);
2016 bRet = WINPOS_SetActiveWindow( pWndTo ? pWndTo->hwndSelf : 0, FALSE, TRUE );
2018 /* switch desktop queue to current active */
2019 if( pWndTo )
2021 WIN_GetDesktop()->hmemTaskQ = pWndTo->hmemTaskQ;
2022 WIN_ReleaseWndPtr(pWndTo);
2023 WIN_ReleaseDesktop();
2026 hwndPrevActive = 0;
2027 return bRet;
2030 /*******************************************************************
2031 * WINPOS_ChangeActiveWindow
2034 BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
2036 WND *wndPtr, *wndTemp;
2037 BOOL retvalue;
2038 HWND hwndActive = 0;
2040 /* Get current active window from the active queue */
2041 if ( hActiveQueue )
2043 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2044 if ( pActiveQueue )
2046 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2047 QUEUE_Unlock( pActiveQueue );
2051 if (!hWnd)
2052 return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
2054 wndPtr = WIN_FindWndPtr(hWnd);
2055 if( !wndPtr ) return FALSE;
2057 /* child windows get WM_CHILDACTIVATE message */
2058 if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
2060 retvalue = SendMessageA(hWnd, WM_CHILDACTIVATE, 0, 0L);
2061 goto end;
2064 if( hWnd == hwndActive )
2066 retvalue = FALSE;
2067 goto end;
2070 if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
2072 retvalue = FALSE;
2073 goto end;
2076 /* switch desktop queue to current active */
2077 wndTemp = WIN_GetDesktop();
2078 if( wndPtr->parent == wndTemp)
2079 wndTemp->hmemTaskQ = wndPtr->hmemTaskQ;
2080 WIN_ReleaseDesktop();
2082 retvalue = TRUE;
2083 end:
2084 WIN_ReleaseWndPtr(wndPtr);
2085 return retvalue;
2089 /***********************************************************************
2090 * WINPOS_SendNCCalcSize
2092 * Send a WM_NCCALCSIZE message to a window.
2093 * All parameters are read-only except newClientRect.
2094 * oldWindowRect, oldClientRect and winpos must be non-NULL only
2095 * when calcValidRect is TRUE.
2097 LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect,
2098 RECT *newWindowRect, RECT *oldWindowRect,
2099 RECT *oldClientRect, WINDOWPOS *winpos,
2100 RECT *newClientRect )
2102 NCCALCSIZE_PARAMS params;
2103 WINDOWPOS winposCopy;
2104 LONG result;
2106 params.rgrc[0] = *newWindowRect;
2107 if (calcValidRect)
2109 winposCopy = *winpos;
2110 params.rgrc[1] = *oldWindowRect;
2111 params.rgrc[2] = *oldClientRect;
2112 params.lppos = &winposCopy;
2114 result = SendMessageA( hwnd, WM_NCCALCSIZE, calcValidRect,
2115 (LPARAM)&params );
2116 TRACE("%d,%d-%d,%d\n",
2117 params.rgrc[0].left, params.rgrc[0].top,
2118 params.rgrc[0].right, params.rgrc[0].bottom );
2120 /* If the application send back garbage, ignore it */
2121 if (params.rgrc[0].left <= params.rgrc[0].right && params.rgrc[0].top <= params.rgrc[0].bottom)
2122 *newClientRect = params.rgrc[0];
2124 return result;
2128 /***********************************************************************
2129 * WINPOS_HandleWindowPosChanging16
2131 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2133 LONG WINPOS_HandleWindowPosChanging16( WND *wndPtr, WINDOWPOS16 *winpos )
2135 POINT maxSize, minTrack;
2136 if (winpos->flags & SWP_NOSIZE) return 0;
2137 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2138 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2140 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
2141 if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
2142 if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
2143 if (!(wndPtr->dwStyle & WS_MINIMIZE))
2145 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
2146 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
2149 return 0;
2153 /***********************************************************************
2154 * WINPOS_HandleWindowPosChanging
2156 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2158 LONG WINPOS_HandleWindowPosChanging( WND *wndPtr, WINDOWPOS *winpos )
2160 POINT maxSize, minTrack;
2161 if (winpos->flags & SWP_NOSIZE) return 0;
2162 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2163 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2165 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
2166 winpos->cx = min( winpos->cx, maxSize.x );
2167 winpos->cy = min( winpos->cy, maxSize.y );
2168 if (!(wndPtr->dwStyle & WS_MINIMIZE))
2170 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
2171 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
2174 return 0;
2177 /***********************************************************************
2178 * SWP_DoOwnedPopups
2180 * fix Z order taking into account owned popups -
2181 * basically we need to maintain them above the window that owns them
2183 * FIXME: hide/show owned popups when owner visibility changes.
2185 static HWND SWP_DoOwnedPopups(WND* pDesktop, WND* wndPtr, HWND hwndInsertAfter, WORD flags)
2187 WND* w = WIN_LockWndPtr(pDesktop->child);
2189 WARN("(%04x) hInsertAfter = %04x\n", wndPtr->hwndSelf, hwndInsertAfter );
2191 if( (wndPtr->dwStyle & WS_POPUP) && wndPtr->owner )
2193 /* make sure this popup stays above the owner */
2195 HWND hwndLocalPrev = HWND_TOP;
2197 if( hwndInsertAfter != HWND_TOP )
2199 while( w != wndPtr->owner )
2201 if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
2202 if( hwndLocalPrev == hwndInsertAfter ) break;
2203 WIN_UpdateWndPtr(&w,w->next);
2205 hwndInsertAfter = hwndLocalPrev;
2208 else if( wndPtr->dwStyle & WS_CHILD )
2209 goto END;
2211 WIN_UpdateWndPtr(&w, pDesktop->child);
2213 while( w )
2215 if( w == wndPtr ) break;
2217 if( (w->dwStyle & WS_POPUP) && w->owner == wndPtr )
2219 SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0,
2220 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
2221 hwndInsertAfter = w->hwndSelf;
2223 WIN_UpdateWndPtr(&w, w->next);
2226 END:
2227 WIN_ReleaseWndPtr(w);
2228 return hwndInsertAfter;
2231 /***********************************************************************
2232 * SWP_CopyValidBits
2234 * Make window look nice without excessive repainting
2236 * visible and update regions are in window coordinates
2237 * client and window rectangles are in parent client coordinates
2239 * Returns: uFlags and a dirty region in *pVisRgn.
2241 static UINT SWP_CopyValidBits( WND* Wnd, HRGN* pVisRgn,
2242 LPRECT lpOldWndRect,
2243 LPRECT lpOldClientRect, UINT uFlags )
2245 RECT r;
2246 HRGN newVisRgn, dirtyRgn;
2247 INT my = COMPLEXREGION;
2249 TRACE("\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2250 Wnd->rectWindow.left, Wnd->rectWindow.top,
2251 Wnd->rectWindow.right, Wnd->rectWindow.bottom,
2252 lpOldWndRect->left, lpOldWndRect->top,
2253 lpOldWndRect->right, lpOldWndRect->bottom, *pVisRgn);
2254 TRACE("\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2255 Wnd->rectClient.left, Wnd->rectClient.top,
2256 Wnd->rectClient.right, Wnd->rectClient.bottom,
2257 lpOldClientRect->left, lpOldClientRect->top,
2258 lpOldClientRect->right,lpOldClientRect->bottom );
2260 if( Wnd->hrgnUpdate == 1 )
2261 uFlags |= SWP_EX_NOCOPY; /* whole window is invalid, nothing to copy */
2263 newVisRgn = DCE_GetVisRgn( Wnd->hwndSelf, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
2264 dirtyRgn = CreateRectRgn( 0, 0, 0, 0 );
2266 if( !(uFlags & SWP_EX_NOCOPY) ) /* make sure dst region covers only valid bits */
2267 my = CombineRgn( dirtyRgn, newVisRgn, *pVisRgn, RGN_AND );
2269 if( (my == NULLREGION) || (uFlags & SWP_EX_NOCOPY) )
2271 nocopy:
2273 TRACE("\twon't copy anything!\n");
2275 /* set dirtyRgn to the sum of old and new visible regions
2276 * in parent client coordinates */
2278 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2279 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2281 CombineRgn(*pVisRgn, *pVisRgn, newVisRgn, RGN_OR );
2283 else /* copy valid bits to a new location */
2285 INT dx, dy, ow, oh, nw, nh, ocw, ncw, och, nch;
2286 HRGN hrgnValid = dirtyRgn; /* non-empty intersection of old and new visible rgns */
2288 /* subtract already invalid region inside Wnd from the dst region */
2290 if( Wnd->hrgnUpdate )
2291 if( CombineRgn( hrgnValid, hrgnValid, Wnd->hrgnUpdate, RGN_DIFF) == NULLREGION )
2292 goto nocopy;
2294 /* check if entire window can be copied */
2296 ow = lpOldWndRect->right - lpOldWndRect->left;
2297 oh = lpOldWndRect->bottom - lpOldWndRect->top;
2298 nw = Wnd->rectWindow.right - Wnd->rectWindow.left;
2299 nh = Wnd->rectWindow.bottom - Wnd->rectWindow.top;
2301 ocw = lpOldClientRect->right - lpOldClientRect->left;
2302 och = lpOldClientRect->bottom - lpOldClientRect->top;
2303 ncw = Wnd->rectClient.right - Wnd->rectClient.left;
2304 nch = Wnd->rectClient.bottom - Wnd->rectClient.top;
2306 if( (ocw != ncw) || (och != nch) ||
2307 ( ow != nw) || ( oh != nh) ||
2308 ((lpOldClientRect->top - lpOldWndRect->top) !=
2309 (Wnd->rectClient.top - Wnd->rectWindow.top)) ||
2310 ((lpOldClientRect->left - lpOldWndRect->left) !=
2311 (Wnd->rectClient.left - Wnd->rectWindow.left)) )
2313 if(uFlags & SWP_EX_PAINTSELF)
2315 /* movement relative to the window itself */
2316 dx = (Wnd->rectClient.left - Wnd->rectWindow.left) -
2317 (lpOldClientRect->left - lpOldWndRect->left) ;
2318 dy = (Wnd->rectClient.top - Wnd->rectWindow.top) -
2319 (lpOldClientRect->top - lpOldWndRect->top) ;
2321 else
2323 /* movement relative to the parent's client area */
2324 dx = Wnd->rectClient.left - lpOldClientRect->left;
2325 dy = Wnd->rectClient.top - lpOldClientRect->top;
2328 /* restrict valid bits to the common client rect */
2330 r.left = Wnd->rectClient.left - Wnd->rectWindow.left;
2331 r.top = Wnd->rectClient.top - Wnd->rectWindow.top;
2332 r.right = r.left + min( ocw, ncw );
2333 r.bottom = r.top + min( och, nch );
2335 REGION_CropRgn( hrgnValid, hrgnValid, &r,
2336 (uFlags & SWP_EX_PAINTSELF) ? NULL : (POINT*)&(Wnd->rectWindow));
2337 GetRgnBox( hrgnValid, &r );
2338 if( IsRectEmpty( &r ) )
2339 goto nocopy;
2340 r = *lpOldClientRect;
2342 else
2344 if(uFlags & SWP_EX_PAINTSELF) {
2346 * with SWP_EX_PAINTSELF, the window repaints itself. Since a window can't move
2347 * relative to itself, only the client area can change.
2348 * if the client rect didn't change, there's nothing to do.
2350 dx = 0;
2351 dy = 0;
2353 else
2355 dx = Wnd->rectWindow.left - lpOldWndRect->left;
2356 dy = Wnd->rectWindow.top - lpOldWndRect->top;
2357 OffsetRgn( hrgnValid, Wnd->rectWindow.left, Wnd->rectWindow.top );
2359 r = *lpOldWndRect;
2362 if( !(uFlags & SWP_EX_PAINTSELF) )
2364 /* Move remaining regions to parent coordinates */
2365 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2366 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2368 else
2369 OffsetRect( &r, -lpOldWndRect->left, -lpOldWndRect->top );
2371 TRACE("\tcomputing dirty region!\n");
2373 /* Compute combined dirty region (old + new - valid) */
2374 CombineRgn( *pVisRgn, *pVisRgn, newVisRgn, RGN_OR);
2375 CombineRgn( *pVisRgn, *pVisRgn, hrgnValid, RGN_DIFF);
2377 /* Blt valid bits, r is the rect to copy */
2379 if( dx || dy )
2381 RECT rClip;
2382 HDC hDC;
2384 /* get DC and clip rect with drawable rect to avoid superfluous expose events
2385 from copying clipped areas */
2387 if( uFlags & SWP_EX_PAINTSELF )
2389 hDC = GetDCEx( Wnd->hwndSelf, hrgnValid, DCX_WINDOW | DCX_CACHE |
2390 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2391 rClip.right = nw; rClip.bottom = nh;
2393 else
2395 hDC = GetDCEx( Wnd->parent->hwndSelf, hrgnValid, DCX_CACHE |
2396 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2397 rClip.right = Wnd->parent->rectClient.right - Wnd->parent->rectClient.left;
2398 rClip.bottom = Wnd->parent->rectClient.bottom - Wnd->parent->rectClient.top;
2400 rClip.left = rClip.top = 0;
2402 if( oh > nh ) r.bottom = r.top + nh;
2403 if( ow < nw ) r.right = r.left + nw;
2405 if( IntersectRect( &r, &r, &rClip ) )
2407 Wnd->pDriver->pSurfaceCopy( Wnd->parent, hDC, dx, dy, &r, TRUE );
2409 /* When you copy the bits without repainting, parent doesn't
2410 get validated appropriately. Therefore, we have to validate
2411 the parent with the windows' updated region when the
2412 parent's update region is not empty. */
2414 if (Wnd->parent->hrgnUpdate != 0 && !(Wnd->parent->dwStyle & WS_CLIPCHILDREN))
2416 OffsetRect(&r, dx, dy);
2417 ValidateRect(Wnd->parent->hwndSelf, &r);
2420 ReleaseDC( (uFlags & SWP_EX_PAINTSELF) ?
2421 Wnd->hwndSelf : Wnd->parent->hwndSelf, hDC);
2425 /* *pVisRgn now points to the invalidated region */
2427 DeleteObject(newVisRgn);
2428 DeleteObject(dirtyRgn);
2429 return uFlags;
2432 /***********************************************************************
2433 * SWP_DoSimpleFrameChanged
2435 * NOTE: old and new client rect origins are identical, only
2436 * extents may have changed. Window extents are the same.
2438 static void SWP_DoSimpleFrameChanged( WND* wndPtr, RECT* pOldClientRect, WORD swpFlags, UINT uFlags )
2440 INT i = 0;
2441 RECT rect;
2442 HRGN hrgn = 0;
2444 if( !(swpFlags & SWP_NOCLIENTSIZE) )
2446 /* Client rect changed its position/size, most likely a scrollar
2447 * was added/removed.
2449 * FIXME: WVR alignment flags
2452 if( wndPtr->rectClient.right > pOldClientRect->right ) /* right edge */
2454 i++;
2455 rect.top = 0;
2456 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2457 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2458 if(!(uFlags & SWP_EX_NOCOPY))
2459 rect.left = pOldClientRect->right - wndPtr->rectClient.left;
2460 else
2462 rect.left = 0;
2463 goto redraw;
2467 if( wndPtr->rectClient.bottom > pOldClientRect->bottom ) /* bottom edge */
2469 if( i )
2470 hrgn = CreateRectRgnIndirect( &rect );
2471 rect.left = 0;
2472 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2473 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2474 if(!(uFlags & SWP_EX_NOCOPY))
2475 rect.top = pOldClientRect->bottom - wndPtr->rectClient.top;
2476 else
2477 rect.top = 0;
2478 if( i++ )
2479 REGION_UnionRectWithRgn( hrgn, &rect );
2482 if( i == 0 && (uFlags & SWP_EX_NOCOPY) ) /* force redraw anyway */
2484 rect = wndPtr->rectWindow;
2485 OffsetRect( &rect, wndPtr->rectWindow.left - wndPtr->rectClient.left,
2486 wndPtr->rectWindow.top - wndPtr->rectClient.top );
2487 i++;
2491 if( i )
2493 redraw:
2494 PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
2495 RDW_ERASENOW | RDW_ALLCHILDREN, RDW_EX_TOPFRAME | RDW_EX_USEHRGN );
2497 else
2499 WIN_UpdateNCRgn(wndPtr, 0, UNC_UPDATE | UNC_ENTIRE);
2502 if( hrgn > 1 )
2503 DeleteObject( hrgn );
2506 /***********************************************************************
2507 * SWP_DoWinPosChanging
2509 static BOOL SWP_DoWinPosChanging( WND* wndPtr, WINDOWPOS* pWinpos,
2510 RECT* pNewWindowRect, RECT* pNewClientRect )
2512 /* Send WM_WINDOWPOSCHANGING message */
2514 if (!(pWinpos->flags & SWP_NOSENDCHANGING))
2515 SendMessageA( wndPtr->hwndSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM)pWinpos );
2517 /* Calculate new position and size */
2519 *pNewWindowRect = wndPtr->rectWindow;
2520 *pNewClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
2521 : wndPtr->rectClient;
2523 if (!(pWinpos->flags & SWP_NOSIZE))
2525 pNewWindowRect->right = pNewWindowRect->left + pWinpos->cx;
2526 pNewWindowRect->bottom = pNewWindowRect->top + pWinpos->cy;
2528 if (!(pWinpos->flags & SWP_NOMOVE))
2530 pNewWindowRect->left = pWinpos->x;
2531 pNewWindowRect->top = pWinpos->y;
2532 pNewWindowRect->right += pWinpos->x - wndPtr->rectWindow.left;
2533 pNewWindowRect->bottom += pWinpos->y - wndPtr->rectWindow.top;
2535 OffsetRect( pNewClientRect, pWinpos->x - wndPtr->rectWindow.left,
2536 pWinpos->y - wndPtr->rectWindow.top );
2539 pWinpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
2540 return TRUE;
2543 /***********************************************************************
2544 * SWP_DoNCCalcSize
2546 static UINT SWP_DoNCCalcSize( WND* wndPtr, WINDOWPOS* pWinpos,
2547 RECT* pNewWindowRect, RECT* pNewClientRect, WORD f)
2549 UINT wvrFlags = 0;
2551 /* Send WM_NCCALCSIZE message to get new client area */
2552 if( (pWinpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
2554 wvrFlags = WINPOS_SendNCCalcSize( pWinpos->hwnd, TRUE, pNewWindowRect,
2555 &wndPtr->rectWindow, &wndPtr->rectClient,
2556 pWinpos, pNewClientRect );
2558 /* FIXME: WVR_ALIGNxxx */
2560 if( pNewClientRect->left != wndPtr->rectClient.left ||
2561 pNewClientRect->top != wndPtr->rectClient.top )
2562 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2564 if( (pNewClientRect->right - pNewClientRect->left !=
2565 wndPtr->rectClient.right - wndPtr->rectClient.left) ||
2566 (pNewClientRect->bottom - pNewClientRect->top !=
2567 wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
2568 pWinpos->flags &= ~SWP_NOCLIENTSIZE;
2570 else
2571 if( !(f & SWP_NOMOVE) && (pNewClientRect->left != wndPtr->rectClient.left ||
2572 pNewClientRect->top != wndPtr->rectClient.top) )
2573 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2574 return wvrFlags;
2577 /***********************************************************************
2578 * SetWindowPos (USER.232)
2580 BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
2581 INT16 x, INT16 y, INT16 cx, INT16 cy, WORD flags)
2583 return SetWindowPos(hwnd,(INT)(INT16)hwndInsertAfter,x,y,cx,cy,flags);
2586 /***********************************************************************
2587 * SetWindowPos (USER32.@)
2589 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
2590 INT x, INT y, INT cx, INT cy, UINT flags )
2592 WINDOWPOS winpos;
2593 WND * wndPtr,*wndTemp;
2594 RECT newWindowRect, newClientRect;
2595 RECT oldWindowRect, oldClientRect;
2596 HRGN visRgn = 0;
2597 UINT wvrFlags = 0, uFlags = 0;
2598 BOOL retvalue, resync = FALSE, bChangePos;
2599 HWND hwndActive = 0;
2601 /* Get current active window from the active queue */
2602 if ( hActiveQueue )
2604 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2605 if ( pActiveQueue )
2607 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2608 QUEUE_Unlock( pActiveQueue );
2612 TRACE("hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2613 hwnd, x, y, x+cx, y+cy, flags);
2615 bChangePos = !(flags & SWP_WINE_NOHOSTMOVE);
2616 flags &= ~SWP_WINE_NOHOSTMOVE;
2619 /* ------------------------------------------------------------------------ CHECKS */
2621 /* Check window handle */
2623 if (hwnd == GetDesktopWindow()) return FALSE;
2624 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2626 TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr->rectWindow.left, wndPtr->rectWindow.top,
2627 wndPtr->rectWindow.right, wndPtr->rectWindow.bottom, (unsigned)wndPtr->dwStyle );
2629 /* Fix redundant flags */
2631 if(wndPtr->dwStyle & WS_VISIBLE)
2632 flags &= ~SWP_SHOWWINDOW;
2633 else
2635 if (!(flags & SWP_SHOWWINDOW))
2636 flags |= SWP_NOREDRAW;
2637 flags &= ~SWP_HIDEWINDOW;
2640 if ( cx < 0 ) cx = 0; if( cy < 0 ) cy = 0;
2642 if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
2643 (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
2644 flags |= SWP_NOSIZE; /* Already the right size */
2646 if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
2647 flags |= SWP_NOMOVE; /* Already the right position */
2649 if (hwnd == hwndActive)
2650 flags |= SWP_NOACTIVATE; /* Already active */
2651 else if ( (wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD )
2653 if(!(flags & SWP_NOACTIVATE)) /* Bring to the top when activating */
2655 flags &= ~SWP_NOZORDER;
2656 hwndInsertAfter = HWND_TOP;
2657 goto Pos;
2661 /* Check hwndInsertAfter */
2663 /* FIXME: TOPMOST not supported yet */
2664 if ((hwndInsertAfter == HWND_TOPMOST) ||
2665 (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
2667 /* hwndInsertAfter must be a sibling of the window */
2668 if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
2670 WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
2672 if( wnd ) {
2673 if( wnd->parent != wndPtr->parent )
2675 retvalue = FALSE;
2676 WIN_ReleaseWndPtr(wnd);
2677 goto END;
2679 /* don't need to change the Zorder of hwnd if it's already inserted
2680 * after hwndInsertAfter or when inserting hwnd after itself.
2682 if(( wnd->next == wndPtr ) || (hwnd == hwndInsertAfter)) flags |= SWP_NOZORDER;
2684 WIN_ReleaseWndPtr(wnd);
2687 Pos: /* ------------------------------------------------------------------------ MAIN part */
2689 /* Fill the WINDOWPOS structure */
2691 winpos.hwnd = hwnd;
2692 winpos.hwndInsertAfter = hwndInsertAfter;
2693 winpos.x = x;
2694 winpos.y = y;
2695 winpos.cx = cx;
2696 winpos.cy = cy;
2697 winpos.flags = flags;
2699 SWP_DoWinPosChanging( wndPtr, &winpos, &newWindowRect, &newClientRect );
2701 if((winpos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER)
2703 if( wndPtr->parent == WIN_GetDesktop() )
2704 hwndInsertAfter = SWP_DoOwnedPopups( wndPtr->parent, wndPtr,
2705 hwndInsertAfter, winpos.flags );
2706 WIN_ReleaseDesktop();
2709 if(!(wndPtr->flags & WIN_NATIVE) )
2711 if( hwndInsertAfter == HWND_TOP )
2712 winpos.flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
2713 else
2714 if( hwndInsertAfter == HWND_BOTTOM )
2715 winpos.flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
2716 else
2717 if( !(winpos.flags & SWP_NOZORDER) )
2718 if( GetWindow(hwndInsertAfter, GW_HWNDNEXT) == wndPtr->hwndSelf )
2719 winpos.flags |= SWP_NOZORDER;
2721 if( !(winpos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) &&
2722 ((winpos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW | SWP_FRAMECHANGED))
2723 != (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)) )
2725 /* get a previous visible region for SWP_CopyValidBits() */
2726 DWORD dflags = DCX_WINDOW;
2728 if (wndPtr->dwStyle & WS_CLIPSIBLINGS)
2729 dflags |= DCX_CLIPSIBLINGS;
2731 visRgn = DCE_GetVisRgn(hwnd, dflags, 0, 0);
2735 /* Common operations */
2737 wvrFlags = SWP_DoNCCalcSize( wndPtr, &winpos, &newWindowRect, &newClientRect, flags );
2739 if(!(winpos.flags & SWP_NOZORDER) && winpos.hwnd != hwndInsertAfter)
2741 if ( WIN_UnlinkWindow( winpos.hwnd ) )
2742 WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
2745 /* Reset active DCEs */
2747 if( (((winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) &&
2748 wndPtr->dwStyle & WS_VISIBLE) ||
2749 (flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
2751 RECT rect;
2753 UnionRect(&rect, &newWindowRect, &wndPtr->rectWindow);
2754 DCE_InvalidateDCE(wndPtr, &rect);
2757 oldWindowRect = wndPtr->rectWindow;
2758 oldClientRect = wndPtr->rectClient;
2760 /* Find out if we have to redraw the whole client rect */
2762 if( oldClientRect.bottom - oldClientRect.top ==
2763 newClientRect.bottom - newClientRect.top ) wvrFlags &= ~WVR_VREDRAW;
2765 if( oldClientRect.right - oldClientRect.left ==
2766 newClientRect.right - newClientRect.left ) wvrFlags &= ~WVR_HREDRAW;
2768 if( (winpos.flags & SWP_NOCOPYBITS) || (!(winpos.flags & SWP_NOCLIENTSIZE) &&
2769 (wvrFlags >= WVR_HREDRAW) && (wvrFlags < WVR_VALIDRECTS)) )
2771 uFlags |= SWP_EX_NOCOPY;
2774 * Use this later in CopyValidBits()
2776 else if( 0 )
2777 uFlags |= SWP_EX_NONCLIENT;
2780 /* FIXME: actually do something with WVR_VALIDRECTS */
2782 wndPtr->rectWindow = newWindowRect;
2783 wndPtr->rectClient = newClientRect;
2785 if (wndPtr->flags & WIN_NATIVE) /* -------------------------------------------- hosted window */
2787 BOOL bCallDriver = TRUE;
2788 HWND tempInsertAfter = winpos.hwndInsertAfter;
2790 winpos.hwndInsertAfter = hwndInsertAfter;
2792 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2794 /* This is the only place where we need to force repainting of the contents
2795 of windows created by the host window system, all other cases go through the
2796 expose event handling */
2798 if( (winpos.flags & (SWP_NOSIZE | SWP_FRAMECHANGED)) == (SWP_NOSIZE | SWP_FRAMECHANGED) )
2800 cx = newWindowRect.right - newWindowRect.left;
2801 cy = newWindowRect.bottom - newWindowRect.top;
2803 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2804 winpos.hwndInsertAfter = tempInsertAfter;
2805 bCallDriver = FALSE;
2807 if( winpos.flags & SWP_NOCLIENTMOVE )
2808 SWP_DoSimpleFrameChanged(wndPtr, &oldClientRect, winpos.flags, uFlags );
2809 else
2811 /* client area moved but window extents remained the same, copy valid bits */
2813 visRgn = CreateRectRgn( 0, 0, cx, cy );
2814 uFlags = SWP_CopyValidBits( wndPtr, &visRgn, &oldWindowRect, &oldClientRect,
2815 uFlags | SWP_EX_PAINTSELF );
2820 if( bCallDriver )
2822 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2824 if( (oldClientRect.left - oldWindowRect.left == newClientRect.left - newWindowRect.left) &&
2825 (oldClientRect.top - oldWindowRect.top == newClientRect.top - newWindowRect.top) &&
2826 !(uFlags & SWP_EX_NOCOPY) )
2828 /* The origin of the client rect didn't move so we can try to repaint
2829 * only the nonclient area by setting bit gravity hint for the host window system.
2832 if( !(wndPtr->dwExStyle & WS_EX_MANAGED) )
2834 HRGN hrgn = CreateRectRgn( 0, 0, newWindowRect.right - newWindowRect.left,
2835 newWindowRect.bottom - newWindowRect.top);
2836 RECT rcn = newClientRect;
2837 RECT rco = oldClientRect;
2839 OffsetRect( &rcn, -newWindowRect.left, -newWindowRect.top );
2840 OffsetRect( &rco, -oldWindowRect.left, -oldWindowRect.top );
2841 IntersectRect( &rcn, &rcn, &rco );
2842 visRgn = CreateRectRgnIndirect( &rcn );
2843 CombineRgn( visRgn, hrgn, visRgn, RGN_DIFF );
2844 DeleteObject( hrgn );
2845 uFlags = SWP_EX_PAINTSELF;
2847 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGNorthWest );
2849 else
2850 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGForget );
2853 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2854 winpos.hwndInsertAfter = tempInsertAfter;
2857 if( winpos.flags & SWP_SHOWWINDOW )
2859 HWND focus, curr;
2861 wndPtr->dwStyle |= WS_VISIBLE;
2863 if (wndPtr->dwExStyle & WS_EX_MANAGED) resync = TRUE;
2865 /* focus was set to unmapped window, reset host focus
2866 * since the window is now visible */
2868 focus = curr = GetFocus();
2869 while (curr)
2871 if (curr == hwnd)
2873 WND *pFocus = WIN_FindWndPtr( focus );
2874 if (pFocus)
2875 pFocus->pDriver->pSetFocus(pFocus);
2876 WIN_ReleaseWndPtr(pFocus);
2877 break;
2879 curr = GetParent(curr);
2883 else /* -------------------------------------------- emulated window */
2885 if( winpos.flags & SWP_SHOWWINDOW )
2887 wndPtr->dwStyle |= WS_VISIBLE;
2888 uFlags |= SWP_EX_PAINTSELF;
2889 visRgn = 1; /* redraw the whole window */
2891 else if( !(winpos.flags & SWP_NOREDRAW) )
2893 if( winpos.flags & SWP_HIDEWINDOW )
2895 if( visRgn > 1 ) /* map to parent */
2896 OffsetRgn( visRgn, oldWindowRect.left, oldWindowRect.top );
2897 else
2898 visRgn = 0;
2900 else
2902 if( (winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE )
2904 /* if window was not resized and not moved try to repaint itself */
2905 if((winpos.flags & SWP_AGG_NOGEOMETRYCHANGE) == SWP_AGG_NOGEOMETRYCHANGE)
2906 uFlags |= SWP_EX_PAINTSELF;
2907 uFlags = SWP_CopyValidBits(wndPtr, &visRgn, &oldWindowRect,
2908 &oldClientRect, uFlags);
2910 else
2912 /* nothing moved, redraw frame if needed */
2914 if( winpos.flags & SWP_FRAMECHANGED )
2915 SWP_DoSimpleFrameChanged( wndPtr, &oldClientRect, winpos.flags, uFlags );
2916 if( visRgn )
2918 DeleteObject( visRgn );
2919 visRgn = 0;
2926 if( winpos.flags & SWP_HIDEWINDOW )
2928 wndPtr->dwStyle &= ~WS_VISIBLE;
2931 if (hwnd == CARET_GetHwnd())
2933 if( winpos.flags & SWP_HIDEWINDOW )
2934 HideCaret(hwnd);
2935 else if (winpos.flags & SWP_SHOWWINDOW)
2936 ShowCaret(hwnd);
2939 /* ------------------------------------------------------------------------ FINAL */
2941 if (wndPtr->flags & WIN_NATIVE)
2942 EVENT_Synchronize(); /* Synchronize with the host window system */
2944 wndTemp = WIN_GetDesktop();
2946 /* repaint invalidated region (if any)
2948 * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2949 * and force update after ChangeActiveWindow() to avoid painting frames twice.
2952 if( visRgn )
2954 if( !(winpos.flags & SWP_NOREDRAW) )
2957 /* Use PAINT_RedrawWindow to explicitly force an invalidation of the window,
2958 its parent and sibling and so on, and then erase the parent window
2959 back ground if the parent is either a top-level window or its parent's parent
2960 is top-level window. Rely on the system to repaint other affected
2961 windows later on. */
2962 if( uFlags & SWP_EX_PAINTSELF )
2964 PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn,
2965 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN,
2966 RDW_EX_XYWINDOW | RDW_EX_USEHRGN );
2968 else
2970 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn,
2971 RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN,
2972 RDW_EX_USEHRGN );
2975 if(wndPtr -> parent == wndTemp || wndPtr->parent->parent == wndTemp )
2977 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0,
2978 RDW_ERASENOW | RDW_NOCHILDREN, 0 );
2981 if( visRgn != 1 )
2982 DeleteObject( visRgn );
2985 WIN_ReleaseDesktop();
2987 if (!(flags & SWP_NOACTIVATE))
2988 WINPOS_ChangeActiveWindow( winpos.hwnd, FALSE );
2990 /* And last, send the WM_WINDOWPOSCHANGED message */
2992 TRACE("\tstatus flags = %04x\n", winpos.flags & SWP_AGG_STATUSFLAGS);
2994 if ( resync ||
2995 (((winpos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) &&
2996 !(winpos.flags & SWP_NOSENDCHANGING)) )
2998 SendMessageA( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
2999 if (resync) EVENT_Synchronize();
3002 retvalue = TRUE;
3003 END:
3004 WIN_ReleaseWndPtr(wndPtr);
3005 return retvalue;
3009 /***********************************************************************
3010 * BeginDeferWindowPos (USER.259)
3012 HDWP16 WINAPI BeginDeferWindowPos16( INT16 count )
3014 return BeginDeferWindowPos( count );
3018 /***********************************************************************
3019 * BeginDeferWindowPos (USER32.@)
3021 HDWP WINAPI BeginDeferWindowPos( INT count )
3023 HDWP handle;
3024 DWP *pDWP;
3026 if (count < 0)
3028 SetLastError(ERROR_INVALID_PARAMETER);
3029 return 0;
3031 /* Windows allows zero count, in which case it allocates context for 8 moves */
3032 if (count == 0) count = 8;
3034 handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
3035 if (!handle) return 0;
3036 pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
3037 pDWP->actualCount = 0;
3038 pDWP->suggestedCount = count;
3039 pDWP->valid = TRUE;
3040 pDWP->wMagic = DWP_MAGIC;
3041 pDWP->hwndParent = 0;
3042 return handle;
3046 /***********************************************************************
3047 * DeferWindowPos (USER.260)
3049 HDWP16 WINAPI DeferWindowPos16( HDWP16 hdwp, HWND16 hwnd, HWND16 hwndAfter,
3050 INT16 x, INT16 y, INT16 cx, INT16 cy,
3051 UINT16 flags )
3053 return DeferWindowPos( hdwp, hwnd, (INT)(INT16)hwndAfter,
3054 x, y, cx, cy, flags );
3058 /***********************************************************************
3059 * DeferWindowPos (USER32.@)
3061 HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter,
3062 INT x, INT y, INT cx, INT cy,
3063 UINT flags )
3065 DWP *pDWP;
3066 int i;
3067 HDWP newhdwp = hdwp,retvalue;
3068 /* HWND parent; */
3069 WND *pWnd;
3071 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
3072 if (!pDWP) return 0;
3073 if (hwnd == GetDesktopWindow()) return 0;
3075 if (!(pWnd=WIN_FindWndPtr( hwnd ))) {
3076 USER_HEAP_FREE( hdwp );
3077 return 0;
3080 /* Numega Bounds Checker Demo dislikes the following code.
3081 In fact, I've not been able to find any "same parent" requirement in any docu
3082 [AM 980509]
3084 #if 0
3085 /* All the windows of a DeferWindowPos() must have the same parent */
3086 parent = pWnd->parent->hwndSelf;
3087 if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
3088 else if (parent != pDWP->hwndParent)
3090 USER_HEAP_FREE( hdwp );
3091 retvalue = 0;
3092 goto END;
3094 #endif
3096 for (i = 0; i < pDWP->actualCount; i++)
3098 if (pDWP->winPos[i].hwnd == hwnd)
3100 /* Merge with the other changes */
3101 if (!(flags & SWP_NOZORDER))
3103 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
3105 if (!(flags & SWP_NOMOVE))
3107 pDWP->winPos[i].x = x;
3108 pDWP->winPos[i].y = y;
3110 if (!(flags & SWP_NOSIZE))
3112 pDWP->winPos[i].cx = cx;
3113 pDWP->winPos[i].cy = cy;
3115 pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
3116 SWP_NOZORDER | SWP_NOREDRAW |
3117 SWP_NOACTIVATE | SWP_NOCOPYBITS|
3118 SWP_NOOWNERZORDER);
3119 pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
3120 SWP_FRAMECHANGED);
3121 retvalue = hdwp;
3122 goto END;
3125 if (pDWP->actualCount >= pDWP->suggestedCount)
3127 newhdwp = USER_HEAP_REALLOC( hdwp,
3128 sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
3129 if (!newhdwp)
3131 retvalue = 0;
3132 goto END;
3134 pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
3135 pDWP->suggestedCount++;
3137 pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
3138 pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
3139 pDWP->winPos[pDWP->actualCount].x = x;
3140 pDWP->winPos[pDWP->actualCount].y = y;
3141 pDWP->winPos[pDWP->actualCount].cx = cx;
3142 pDWP->winPos[pDWP->actualCount].cy = cy;
3143 pDWP->winPos[pDWP->actualCount].flags = flags;
3144 pDWP->actualCount++;
3145 retvalue = newhdwp;
3146 END:
3147 WIN_ReleaseWndPtr(pWnd);
3148 return retvalue;
3152 /***********************************************************************
3153 * EndDeferWindowPos (USER.261)
3155 BOOL16 WINAPI EndDeferWindowPos16( HDWP16 hdwp )
3157 return EndDeferWindowPos( hdwp );
3161 /***********************************************************************
3162 * EndDeferWindowPos (USER32.@)
3164 BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
3166 DWP *pDWP;
3167 WINDOWPOS *winpos;
3168 BOOL res = TRUE;
3169 int i;
3171 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
3172 if (!pDWP) return FALSE;
3173 for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
3175 if (!(res = SetWindowPos( winpos->hwnd, winpos->hwndInsertAfter,
3176 winpos->x, winpos->y, winpos->cx,
3177 winpos->cy, winpos->flags ))) break;
3179 USER_HEAP_FREE( hdwp );
3180 return res;
3184 /***********************************************************************
3185 * TileChildWindows (USER.199)
3187 void WINAPI TileChildWindows16( HWND16 parent, WORD action )
3189 FIXME("(%04x, %d): stub\n", parent, action);
3192 /***********************************************************************
3193 * CascadeChildWindows (USER.198)
3195 void WINAPI CascadeChildWindows16( HWND16 parent, WORD action )
3197 FIXME("(%04x, %d): stub\n", parent, action);
3200 /***********************************************************************
3201 * SetProgmanWindow (USER32.@)
3203 HRESULT WINAPI SetProgmanWindow ( HWND hwnd )
3205 hGlobalProgmanWindow = hwnd;
3206 return hGlobalProgmanWindow;
3209 /***********************************************************************
3210 * GetProgmanWindow (USER32.@)
3212 HRESULT WINAPI GetProgmanWindow ( )
3214 return hGlobalProgmanWindow;
3217 /***********************************************************************
3218 * SetShellWindowEx (USER32.@)
3219 * hwndProgman = Progman[Program Manager]
3220 * |-> SHELLDLL_DefView
3221 * hwndListView = | |-> SysListView32
3222 * | | |-> tooltips_class32
3223 * | |
3224 * | |-> SysHeader32
3225 * |
3226 * |-> ProxyTarget
3228 HRESULT WINAPI SetShellWindowEx ( HWND hwndProgman, HWND hwndListView )
3230 FIXME("0x%08x 0x%08x stub\n",hwndProgman ,hwndListView );
3231 hGlobalShellWindow = hwndProgman;
3232 return hGlobalShellWindow;
3236 /***********************************************************************
3237 * SetTaskmanWindow (USER32.@)
3238 * NOTES
3239 * hwnd = MSTaskSwWClass
3240 * |-> SysTabControl32
3242 HRESULT WINAPI SetTaskmanWindow ( HWND hwnd )
3244 hGlobalTaskmanWindow = hwnd;
3245 return hGlobalTaskmanWindow;
3248 /***********************************************************************
3249 * GetTaskmanWindow (USER32.@)
3251 HRESULT WINAPI GetTaskmanWindow ( )
3253 return hGlobalTaskmanWindow;