Added a small section about expressions in winedbg.
[wine.git] / windows / winpos.c
blobd88161810a41470f67d1f2f515a0913e651a2808
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 EMPTYPOINT(pt) ((*(LONG*)&(pt)) == -1)
41 #define PLACE_MIN 0x0001
42 #define PLACE_MAX 0x0002
43 #define PLACE_RECT 0x0004
45 #define MINMAX_NOSWP 0x00010000
48 #define DWP_MAGIC ((INT)('W' | ('P' << 8) | ('O' << 16) | ('S' << 24)))
50 typedef struct
52 INT actualCount;
53 INT suggestedCount;
54 BOOL valid;
55 INT wMagic;
56 HWND hwndParent;
57 WINDOWPOS winPos[1];
58 } DWP;
60 /* ----- internal variables ----- */
62 static HWND hwndPrevActive = 0; /* Previously active window */
63 static HWND hGlobalShellWindow=0; /*the shell*/
64 static HWND hGlobalTaskmanWindow=0;
65 static HWND hGlobalProgmanWindow=0;
67 static LPCSTR atomInternalPos;
69 extern HQUEUE16 hActiveQueue;
71 /***********************************************************************
72 * WINPOS_CreateInternalPosAtom
74 BOOL WINPOS_CreateInternalPosAtom()
76 LPSTR str = "SysIP";
77 atomInternalPos = (LPCSTR)(DWORD)GlobalAddAtomA(str);
78 return (atomInternalPos) ? TRUE : FALSE;
81 /***********************************************************************
82 * WINPOS_CheckInternalPos
84 * Called when a window is destroyed.
86 void WINPOS_CheckInternalPos( WND* wndPtr )
88 LPINTERNALPOS lpPos;
89 MESSAGEQUEUE *pMsgQ = 0;
90 HWND hwnd = wndPtr->hwndSelf;
92 lpPos = (LPINTERNALPOS) GetPropA( hwnd, atomInternalPos );
94 /* Retrieve the message queue associated with this window */
95 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
96 if ( !pMsgQ )
98 WARN("\tMessage queue not found. Exiting!\n" );
99 return;
102 if( hwnd == hwndPrevActive ) hwndPrevActive = 0;
104 if( hwnd == PERQDATA_GetActiveWnd( pMsgQ->pQData ) )
106 PERQDATA_SetActiveWnd( pMsgQ->pQData, 0 );
107 WARN("\tattempt to activate destroyed window!\n");
110 if( lpPos )
112 if( IsWindow(lpPos->hwndIconTitle) )
113 DestroyWindow( lpPos->hwndIconTitle );
114 HeapFree( GetProcessHeap(), 0, lpPos );
117 QUEUE_Unlock( pMsgQ );
118 return;
121 /***********************************************************************
122 * WINPOS_FindIconPos
124 * Find a suitable place for an iconic window.
126 static POINT16 WINPOS_FindIconPos( WND* wndPtr, POINT16 pt )
128 RECT16 rectParent;
129 short x, y, xspacing, yspacing;
131 GetClientRect16( wndPtr->parent->hwndSelf, &rectParent );
132 if ((pt.x >= rectParent.left) && (pt.x + GetSystemMetrics(SM_CXICON) < rectParent.right) &&
133 (pt.y >= rectParent.top) && (pt.y + GetSystemMetrics(SM_CYICON) < rectParent.bottom))
134 return pt; /* The icon already has a suitable position */
136 xspacing = GetSystemMetrics(SM_CXICONSPACING);
137 yspacing = GetSystemMetrics(SM_CYICONSPACING);
139 y = rectParent.bottom;
140 for (;;)
142 x = rectParent.left;
145 /* Check if another icon already occupies this spot */
146 WND *childPtr = WIN_LockWndPtr(wndPtr->parent->child);
147 while (childPtr)
149 if ((childPtr->dwStyle & WS_MINIMIZE) && (childPtr != wndPtr))
151 if ((childPtr->rectWindow.left < x + xspacing) &&
152 (childPtr->rectWindow.right >= x) &&
153 (childPtr->rectWindow.top <= y) &&
154 (childPtr->rectWindow.bottom > y - yspacing))
155 break; /* There's a window in there */
157 WIN_UpdateWndPtr(&childPtr,childPtr->next);
159 WIN_ReleaseWndPtr(childPtr);
160 if (!childPtr) /* No window was found, so it's OK for us */
162 pt.x = x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2;
163 pt.y = y - (yspacing + GetSystemMetrics(SM_CYICON)) / 2;
164 return pt;
166 x += xspacing;
167 } while(x <= rectParent.right-xspacing);
168 y -= yspacing;
173 /***********************************************************************
174 * ArrangeIconicWindows (USER.170)
176 UINT16 WINAPI ArrangeIconicWindows16( HWND16 parent)
178 return ArrangeIconicWindows(parent);
180 /***********************************************************************
181 * ArrangeIconicWindows (USER32.@)
183 UINT WINAPI ArrangeIconicWindows( HWND parent )
185 RECT rectParent;
186 HWND hwndChild;
187 INT x, y, xspacing, yspacing;
189 GetClientRect( parent, &rectParent );
190 x = rectParent.left;
191 y = rectParent.bottom;
192 xspacing = GetSystemMetrics(SM_CXICONSPACING);
193 yspacing = GetSystemMetrics(SM_CYICONSPACING);
195 hwndChild = GetWindow( parent, GW_CHILD );
196 while (hwndChild)
198 if( IsIconic( hwndChild ) )
200 WND *wndPtr = WIN_FindWndPtr(hwndChild);
202 WINPOS_ShowIconTitle( wndPtr, FALSE );
204 SetWindowPos( hwndChild, 0, x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2,
205 y - yspacing - GetSystemMetrics(SM_CYICON)/2, 0, 0,
206 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
207 if( IsWindow(hwndChild) )
208 WINPOS_ShowIconTitle(wndPtr , TRUE );
209 WIN_ReleaseWndPtr(wndPtr);
211 if (x <= rectParent.right - xspacing) x += xspacing;
212 else
214 x = rectParent.left;
215 y -= yspacing;
218 hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
220 return yspacing;
224 /***********************************************************************
225 * SwitchToThisWindow (USER.172)
227 void WINAPI SwitchToThisWindow16( HWND16 hwnd, BOOL16 restore )
229 SwitchToThisWindow( hwnd, restore );
233 /***********************************************************************
234 * SwitchToThisWindow (USER32.@)
236 void WINAPI SwitchToThisWindow( HWND hwnd, BOOL restore )
238 ShowWindow( hwnd, restore ? SW_RESTORE : SW_SHOWMINIMIZED );
242 /***********************************************************************
243 * GetWindowRect (USER.32)
245 void WINAPI GetWindowRect16( HWND16 hwnd, LPRECT16 rect )
247 WND * wndPtr = WIN_FindWndPtr( hwnd );
248 if (!wndPtr) return;
250 CONV_RECT32TO16( &wndPtr->rectWindow, rect );
251 if (wndPtr->parent)
252 MapWindowPoints16( wndPtr->parent->hwndSelf, 0, (POINT16 *)rect, 2 );
253 WIN_ReleaseWndPtr(wndPtr);
257 /***********************************************************************
258 * GetWindowRect (USER32.@)
260 BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect )
262 WND * wndPtr = WIN_FindWndPtr( hwnd );
263 if (!wndPtr) return FALSE;
265 *rect = wndPtr->rectWindow;
266 if (wndPtr->parent)
267 MapWindowPoints( wndPtr->parent->hwndSelf, 0, (POINT *)rect, 2 );
268 WIN_ReleaseWndPtr(wndPtr);
269 return TRUE;
273 /***********************************************************************
274 * GetWindowRgn (USER32.@)
276 int WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
278 int nRet = ERROR;
279 WND *wndPtr = WIN_FindWndPtr( hwnd );
280 if (wndPtr)
282 if (wndPtr->hrgnWnd) nRet = CombineRgn( hrgn, wndPtr->hrgnWnd, 0, RGN_COPY );
283 WIN_ReleaseWndPtr(wndPtr);
285 return nRet;
288 /***********************************************************************
289 * SetWindowRgn (USER32.@)
291 int WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL bRedraw )
293 RECT rect;
294 WND *wndPtr;
295 int ret = FALSE;
297 if (USER_Driver.pSetWindowRgn)
298 return USER_Driver.pSetWindowRgn( hwnd, hrgn, bRedraw );
300 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
302 if (wndPtr->hrgnWnd == hrgn)
304 ret = TRUE;
305 goto done;
308 if (hrgn) /* verify that region really exists */
310 if (GetRgnBox( hrgn, &rect ) == ERROR) goto done;
313 if (wndPtr->hrgnWnd)
315 /* delete previous region */
316 DeleteObject(wndPtr->hrgnWnd);
317 wndPtr->hrgnWnd = 0;
319 wndPtr->hrgnWnd = hrgn;
321 /* Size the window to the rectangle of the new region (if it isn't NULL) */
322 if (hrgn) SetWindowPos( hwnd, 0, rect.left, rect.top,
323 rect.right - rect.left, rect.bottom - rect.top,
324 SWP_NOSIZE | SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOACTIVATE |
325 SWP_NOZORDER | (bRedraw ? 0 : SWP_NOREDRAW) );
326 ret = TRUE;
328 done:
329 WIN_ReleaseWndPtr(wndPtr);
330 return ret;
333 /***********************************************************************
334 * SetWindowRgn (USER.668)
336 INT16 WINAPI SetWindowRgn16( HWND16 hwnd, HRGN16 hrgn,BOOL16 bRedraw)
340 FIXME("SetWindowRgn16: stub\n");
341 return TRUE;
345 /***********************************************************************
346 * GetClientRect (USER.33)
348 void WINAPI GetClientRect16( HWND16 hwnd, LPRECT16 rect )
350 WND * wndPtr = WIN_FindWndPtr( hwnd );
352 rect->left = rect->top = rect->right = rect->bottom = 0;
353 if (wndPtr)
355 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
356 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
358 WIN_ReleaseWndPtr(wndPtr);
362 /***********************************************************************
363 * GetClientRect (USER32.@)
365 BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect )
367 WND * wndPtr = WIN_FindWndPtr( hwnd );
369 rect->left = rect->top = rect->right = rect->bottom = 0;
370 if (!wndPtr) return FALSE;
371 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
372 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
374 WIN_ReleaseWndPtr(wndPtr);
375 return TRUE;
379 /*******************************************************************
380 * ClientToScreen (USER.28)
382 void WINAPI ClientToScreen16( HWND16 hwnd, LPPOINT16 lppnt )
384 MapWindowPoints16( hwnd, 0, lppnt, 1 );
388 /*******************************************************************
389 * ClientToScreen (USER32.@)
391 BOOL WINAPI ClientToScreen( HWND hwnd, LPPOINT lppnt )
393 MapWindowPoints( hwnd, 0, lppnt, 1 );
394 return TRUE;
398 /*******************************************************************
399 * ScreenToClient (USER.29)
401 void WINAPI ScreenToClient16( HWND16 hwnd, LPPOINT16 lppnt )
403 MapWindowPoints16( 0, hwnd, lppnt, 1 );
407 /*******************************************************************
408 * ScreenToClient (USER32.@)
410 BOOL WINAPI ScreenToClient( HWND hwnd, LPPOINT lppnt )
412 MapWindowPoints( 0, hwnd, lppnt, 1 );
413 return TRUE;
417 /***********************************************************************
418 * WINPOS_WindowFromPoint
420 * Find the window and hittest for a given point.
422 INT16 WINPOS_WindowFromPoint( WND* wndScope, POINT16 pt, WND **ppWnd )
424 WND *wndPtr;
425 INT16 hittest = HTERROR;
426 INT16 retvalue;
427 POINT16 xy = pt;
429 TRACE("scope %04x %d,%d\n", wndScope->hwndSelf, pt.x, pt.y);
430 *ppWnd = NULL;
431 wndPtr = WIN_LockWndPtr(wndScope->child);
433 if( wndScope->dwStyle & WS_DISABLED )
435 retvalue = HTERROR;
436 goto end;
439 if( wndScope->dwExStyle & WS_EX_MANAGED)
441 /* In managed mode we have to check wndScope first as it is also
442 * a window which received the mouse event. */
444 if( pt.x < wndScope->rectClient.left || pt.x >= wndScope->rectClient.right ||
445 pt.y < wndScope->rectClient.top || pt.y >= wndScope->rectClient.bottom )
446 goto hittest;
448 MapWindowPoints16( GetDesktopWindow16(), wndScope->hwndSelf, &xy, 1 );
450 for (;;)
452 while (wndPtr)
454 /* If point is in window, and window is visible, and it */
455 /* is enabled (or it's a top-level window), then explore */
456 /* its children. Otherwise, go to the next window. */
458 if ((wndPtr->dwStyle & WS_VISIBLE) &&
459 ((wndPtr->dwExStyle & (WS_EX_LAYERED | WS_EX_TRANSPARENT)) != (WS_EX_LAYERED | WS_EX_TRANSPARENT)) &&
460 (!(wndPtr->dwStyle & WS_DISABLED) ||
461 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)) &&
462 (wndPtr->hrgnWnd ?
463 PtInRegion(wndPtr->hrgnWnd, xy.x - wndPtr->rectWindow.left,
464 xy.y - wndPtr->rectWindow.top) :
465 ((xy.x >= wndPtr->rectWindow.left) &&
466 (xy.x < wndPtr->rectWindow.right) &&
467 (xy.y >= wndPtr->rectWindow.top) &&
468 (xy.y < wndPtr->rectWindow.bottom))))
470 TRACE("%d,%d is inside %04x\n", xy.x, xy.y, wndPtr->hwndSelf);
471 *ppWnd = wndPtr; /* Got a suitable window */
473 /* If window is minimized or disabled, return at once */
474 if (wndPtr->dwStyle & WS_MINIMIZE)
476 retvalue = HTCAPTION;
477 goto end;
479 if (wndPtr->dwStyle & WS_DISABLED)
481 retvalue = HTERROR;
482 goto end;
485 /* If point is not in client area, ignore the children */
486 if ((xy.x < wndPtr->rectClient.left) ||
487 (xy.x >= wndPtr->rectClient.right) ||
488 (xy.y < wndPtr->rectClient.top) ||
489 (xy.y >= wndPtr->rectClient.bottom)) break;
491 xy.x -= wndPtr->rectClient.left;
492 xy.y -= wndPtr->rectClient.top;
493 WIN_UpdateWndPtr(&wndPtr,wndPtr->child);
495 else
497 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
501 hittest:
502 /* If nothing found, try the scope window */
503 if (!*ppWnd) *ppWnd = wndScope;
505 /* Send the WM_NCHITTEST message (only if to the same task) */
506 if ((*ppWnd)->hmemTaskQ == GetFastQueue16())
508 hittest = (INT16)SendMessage16( (*ppWnd)->hwndSelf, WM_NCHITTEST,
509 0, MAKELONG( pt.x, pt.y ) );
510 if (hittest != HTTRANSPARENT)
512 retvalue = hittest; /* Found the window */
513 goto end;
516 else
518 retvalue = HTCLIENT;
519 goto end;
522 /* If no children found in last search, make point relative to parent */
523 if (!wndPtr)
525 xy.x += (*ppWnd)->rectClient.left;
526 xy.y += (*ppWnd)->rectClient.top;
529 /* Restart the search from the next sibling */
530 WIN_UpdateWndPtr(&wndPtr,(*ppWnd)->next);
531 *ppWnd = (*ppWnd)->parent;
534 end:
535 WIN_ReleaseWndPtr(wndPtr);
536 return retvalue;
540 /*******************************************************************
541 * WindowFromPoint (USER.30)
543 HWND16 WINAPI WindowFromPoint16( POINT16 pt )
545 WND *pWnd;
546 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt, &pWnd );
547 WIN_ReleaseDesktop();
548 return pWnd->hwndSelf;
552 /*******************************************************************
553 * WindowFromPoint (USER32.@)
555 HWND WINAPI WindowFromPoint( POINT pt )
557 WND *pWnd;
558 POINT16 pt16;
559 CONV_POINT32TO16( &pt, &pt16 );
560 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16, &pWnd );
561 WIN_ReleaseDesktop();
562 return (HWND)pWnd->hwndSelf;
566 /*******************************************************************
567 * ChildWindowFromPoint (USER.191)
569 HWND16 WINAPI ChildWindowFromPoint16( HWND16 hwndParent, POINT16 pt )
571 POINT pt32;
572 CONV_POINT16TO32( &pt, &pt32 );
573 return (HWND16)ChildWindowFromPoint( hwndParent, pt32 );
577 /*******************************************************************
578 * ChildWindowFromPoint (USER32.@)
580 HWND WINAPI ChildWindowFromPoint( HWND hwndParent, POINT pt )
582 /* pt is in the client coordinates */
584 WND* wnd = WIN_FindWndPtr(hwndParent);
585 RECT rect;
586 HWND retvalue;
588 if( !wnd ) return 0;
590 /* get client rect fast */
591 rect.top = rect.left = 0;
592 rect.right = wnd->rectClient.right - wnd->rectClient.left;
593 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
595 if (!PtInRect( &rect, pt ))
597 retvalue = 0;
598 goto end;
600 WIN_UpdateWndPtr(&wnd,wnd->child);
601 while ( wnd )
603 if (PtInRect( &wnd->rectWindow, pt ))
605 retvalue = wnd->hwndSelf;
606 goto end;
608 WIN_UpdateWndPtr(&wnd,wnd->next);
610 retvalue = hwndParent;
611 end:
612 WIN_ReleaseWndPtr(wnd);
613 return retvalue;
616 /*******************************************************************
617 * ChildWindowFromPointEx (USER.399)
619 HWND16 WINAPI ChildWindowFromPointEx16( HWND16 hwndParent, POINT16 pt, UINT16 uFlags)
621 POINT pt32;
622 CONV_POINT16TO32( &pt, &pt32 );
623 return (HWND16)ChildWindowFromPointEx( hwndParent, pt32, uFlags );
627 /*******************************************************************
628 * ChildWindowFromPointEx (USER32.@)
630 HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt,
631 UINT uFlags)
633 /* pt is in the client coordinates */
635 WND* wnd = WIN_FindWndPtr(hwndParent);
636 RECT rect;
637 HWND retvalue;
639 if( !wnd ) return 0;
641 /* get client rect fast */
642 rect.top = rect.left = 0;
643 rect.right = wnd->rectClient.right - wnd->rectClient.left;
644 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
646 if (!PtInRect( &rect, pt ))
648 retvalue = 0;
649 goto end;
651 WIN_UpdateWndPtr(&wnd,wnd->child);
653 while ( wnd )
655 if (PtInRect( &wnd->rectWindow, pt )) {
656 if ( (uFlags & CWP_SKIPINVISIBLE) &&
657 !(wnd->dwStyle & WS_VISIBLE) );
658 else if ( (uFlags & CWP_SKIPDISABLED) &&
659 (wnd->dwStyle & WS_DISABLED) );
660 else if ( (uFlags & CWP_SKIPTRANSPARENT) &&
661 (wnd->dwExStyle & WS_EX_TRANSPARENT) );
662 else
664 retvalue = wnd->hwndSelf;
665 goto end;
669 WIN_UpdateWndPtr(&wnd,wnd->next);
671 retvalue = hwndParent;
672 end:
673 WIN_ReleaseWndPtr(wnd);
674 return retvalue;
678 /*******************************************************************
679 * WINPOS_GetWinOffset
681 * Calculate the offset between the origin of the two windows. Used
682 * to implement MapWindowPoints.
684 static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo,
685 POINT *offset )
687 WND * wndPtr = 0;
689 offset->x = offset->y = 0;
690 if (hwndFrom == hwndTo ) return;
692 /* Translate source window origin to screen coords */
693 if (hwndFrom)
695 if (!(wndPtr = WIN_FindWndPtr( hwndFrom )))
697 ERR("bad hwndFrom = %04x\n",hwndFrom);
698 return;
700 while (wndPtr->parent)
702 offset->x += wndPtr->rectClient.left;
703 offset->y += wndPtr->rectClient.top;
704 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
706 WIN_ReleaseWndPtr(wndPtr);
709 /* Translate origin to destination window coords */
710 if (hwndTo)
712 if (!(wndPtr = WIN_FindWndPtr( hwndTo )))
714 ERR("bad hwndTo = %04x\n", hwndTo );
715 return;
717 while (wndPtr->parent)
719 offset->x -= wndPtr->rectClient.left;
720 offset->y -= wndPtr->rectClient.top;
721 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
723 WIN_ReleaseWndPtr(wndPtr);
728 /*******************************************************************
729 * MapWindowPoints (USER.258)
731 void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
732 LPPOINT16 lppt, UINT16 count )
734 POINT offset;
736 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
737 while (count--)
739 lppt->x += offset.x;
740 lppt->y += offset.y;
741 lppt++;
746 /*******************************************************************
747 * MapWindowPoints (USER32.@)
749 INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo,
750 LPPOINT lppt, UINT count )
752 POINT offset;
754 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
755 while (count--)
757 lppt->x += offset.x;
758 lppt->y += offset.y;
759 lppt++;
761 return MAKELONG( LOWORD(offset.x), LOWORD(offset.y) );
765 /***********************************************************************
766 * IsIconic (USER.31)
768 BOOL16 WINAPI IsIconic16(HWND16 hWnd)
770 return IsIconic(hWnd);
774 /***********************************************************************
775 * IsIconic (USER32.@)
777 BOOL WINAPI IsIconic(HWND hWnd)
779 BOOL retvalue;
780 WND * wndPtr = WIN_FindWndPtr(hWnd);
781 if (wndPtr == NULL) return FALSE;
782 retvalue = (wndPtr->dwStyle & WS_MINIMIZE) != 0;
783 WIN_ReleaseWndPtr(wndPtr);
784 return retvalue;
788 /***********************************************************************
789 * IsZoomed (USER.272)
791 BOOL16 WINAPI IsZoomed16(HWND16 hWnd)
793 return IsZoomed(hWnd);
797 /***********************************************************************
798 * IsZoomed (USER32.@)
800 BOOL WINAPI IsZoomed(HWND hWnd)
802 BOOL retvalue;
803 WND * wndPtr = WIN_FindWndPtr(hWnd);
804 if (wndPtr == NULL) return FALSE;
805 retvalue = (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
806 WIN_ReleaseWndPtr(wndPtr);
807 return retvalue;
811 /*******************************************************************
812 * GetActiveWindow (USER.60)
814 HWND16 WINAPI GetActiveWindow16(void)
816 return (HWND16)GetActiveWindow();
819 /*******************************************************************
820 * GetActiveWindow (USER32.@)
822 HWND WINAPI GetActiveWindow(void)
824 MESSAGEQUEUE *pCurMsgQ = 0;
825 HWND hwndActive = 0;
827 /* Get the messageQ for the current thread */
828 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
830 WARN("\tCurrent message queue not found. Exiting!\n" );
831 return 0;
834 /* Return the current active window from the perQ data of the current message Q */
835 hwndActive = PERQDATA_GetActiveWnd( pCurMsgQ->pQData );
837 QUEUE_Unlock( pCurMsgQ );
838 return hwndActive;
842 /*******************************************************************
843 * WINPOS_CanActivate
845 static BOOL WINPOS_CanActivate(WND* pWnd)
847 if( pWnd && ( (pWnd->dwStyle & (WS_DISABLED | WS_VISIBLE | WS_CHILD))
848 == WS_VISIBLE ) ) return TRUE;
849 return FALSE;
853 /*******************************************************************
854 * SetActiveWindow (USER.59)
856 HWND16 WINAPI SetActiveWindow16( HWND16 hwnd )
858 return SetActiveWindow(hwnd);
862 /*******************************************************************
863 * SetActiveWindow (USER32.@)
865 HWND WINAPI SetActiveWindow( HWND hwnd )
867 HWND prev = 0;
868 WND *wndPtr = WIN_FindWndPtr( hwnd );
869 MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
871 if (!wndPtr || (wndPtr->dwStyle & (WS_DISABLED | WS_CHILD)))
873 prev = 0;
874 goto end;
877 /* Get the messageQ for the current thread */
878 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
880 WARN("\tCurrent message queue not found. Exiting!\n" );
881 goto CLEANUP;
884 /* Retrieve the message queue associated with this window */
885 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
886 if ( !pMsgQ )
888 WARN("\tWindow message queue not found. Exiting!\n" );
889 goto CLEANUP;
892 /* Make sure that the window is associated with the calling threads
893 * message queue. It must share the same perQ data.
896 if ( pCurMsgQ->pQData != pMsgQ->pQData )
897 goto CLEANUP;
899 /* Save current active window */
900 prev = PERQDATA_GetActiveWnd( pMsgQ->pQData );
902 WINPOS_SetActiveWindow( hwnd, 0, 0 );
904 CLEANUP:
905 /* Unlock the queues before returning */
906 if ( pMsgQ )
907 QUEUE_Unlock( pMsgQ );
908 if ( pCurMsgQ )
909 QUEUE_Unlock( pCurMsgQ );
911 end:
912 WIN_ReleaseWndPtr(wndPtr);
913 return prev;
917 /*******************************************************************
918 * GetForegroundWindow (USER.608)
920 HWND16 WINAPI GetForegroundWindow16(void)
922 return (HWND16)GetForegroundWindow();
926 /*******************************************************************
927 * SetForegroundWindow (USER.609)
929 BOOL16 WINAPI SetForegroundWindow16( HWND16 hwnd )
931 return SetForegroundWindow( hwnd );
935 /*******************************************************************
936 * GetForegroundWindow (USER32.@)
938 HWND WINAPI GetForegroundWindow(void)
940 HWND hwndActive = 0;
942 /* Get the foreground window (active window of hActiveQueue) */
943 if ( hActiveQueue )
945 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
946 if ( pActiveQueue )
947 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
949 QUEUE_Unlock( pActiveQueue );
952 return hwndActive;
955 /*******************************************************************
956 * SetForegroundWindow (USER32.@)
958 BOOL WINAPI SetForegroundWindow( HWND hwnd )
960 return WINPOS_ChangeActiveWindow( hwnd, FALSE );
964 /*******************************************************************
965 * AllowSetForegroundWindow (USER32.@)
967 BOOL WINAPI AllowSetForegroundWindow( DWORD procid )
969 /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
970 * implemented, then fix this function. */
971 return TRUE;
975 /*******************************************************************
976 * LockSetForegroundWindow (USER32.@)
978 BOOL WINAPI LockSetForegroundWindow( UINT lockcode )
980 /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
981 * implemented, then fix this function. */
982 return TRUE;
986 /*******************************************************************
987 * GetShellWindow (USER.600)
989 HWND16 WINAPI GetShellWindow16(void)
991 return GetShellWindow();
994 /*******************************************************************
995 * SetShellWindow (USER32.@)
997 HWND WINAPI SetShellWindow(HWND hwndshell)
998 { WARN("(hWnd=%08x) semi stub\n",hwndshell );
1000 hGlobalShellWindow = hwndshell;
1001 return hGlobalShellWindow;
1005 /*******************************************************************
1006 * GetShellWindow (USER32.@)
1008 HWND WINAPI GetShellWindow(void)
1009 { WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow );
1011 return hGlobalShellWindow;
1015 /***********************************************************************
1016 * BringWindowToTop (USER.45)
1018 BOOL16 WINAPI BringWindowToTop16( HWND16 hwnd )
1020 return BringWindowToTop(hwnd);
1024 /***********************************************************************
1025 * BringWindowToTop (USER32.@)
1027 BOOL WINAPI BringWindowToTop( HWND hwnd )
1029 return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
1033 /***********************************************************************
1034 * MoveWindow (USER.56)
1036 BOOL16 WINAPI MoveWindow16( HWND16 hwnd, INT16 x, INT16 y, INT16 cx, INT16 cy,
1037 BOOL16 repaint )
1039 return MoveWindow(hwnd,x,y,cx,cy,repaint);
1043 /***********************************************************************
1044 * MoveWindow (USER32.@)
1046 BOOL WINAPI MoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy,
1047 BOOL repaint )
1049 int flags = SWP_NOZORDER | SWP_NOACTIVATE;
1050 if (!repaint) flags |= SWP_NOREDRAW;
1051 TRACE("%04x %d,%d %dx%d %d\n",
1052 hwnd, x, y, cx, cy, repaint );
1053 return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
1056 /***********************************************************************
1057 * WINPOS_InitInternalPos
1059 static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT pt,
1060 LPRECT restoreRect )
1062 LPINTERNALPOS lpPos = (LPINTERNALPOS) GetPropA( wnd->hwndSelf,
1063 atomInternalPos );
1064 if( !lpPos )
1066 /* this happens when the window is minimized/maximized
1067 * for the first time (rectWindow is not adjusted yet) */
1069 lpPos = HeapAlloc( GetProcessHeap(), 0, sizeof(INTERNALPOS) );
1070 if( !lpPos ) return NULL;
1072 SetPropA( wnd->hwndSelf, atomInternalPos, (HANDLE)lpPos );
1073 lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
1074 CONV_RECT32TO16( &wnd->rectWindow, &lpPos->rectNormal );
1075 *(UINT*)&lpPos->ptIconPos = *(UINT*)&lpPos->ptMaxPos = 0xFFFFFFFF;
1078 if( wnd->dwStyle & WS_MINIMIZE )
1079 CONV_POINT32TO16( &pt, &lpPos->ptIconPos );
1080 else if( wnd->dwStyle & WS_MAXIMIZE )
1081 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1082 else if( restoreRect )
1083 CONV_RECT32TO16( restoreRect, &lpPos->rectNormal );
1085 return lpPos;
1088 /***********************************************************************
1089 * WINPOS_RedrawIconTitle
1091 BOOL WINPOS_RedrawIconTitle( HWND hWnd )
1093 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hWnd, atomInternalPos );
1094 if( lpPos )
1096 if( lpPos->hwndIconTitle )
1098 SendMessageA( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
1099 InvalidateRect( lpPos->hwndIconTitle, NULL, TRUE );
1100 return TRUE;
1103 return FALSE;
1106 /***********************************************************************
1107 * WINPOS_ShowIconTitle
1109 BOOL WINPOS_ShowIconTitle( WND* pWnd, BOOL bShow )
1111 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( pWnd->hwndSelf, atomInternalPos );
1113 if( lpPos && !(pWnd->dwExStyle & WS_EX_MANAGED))
1115 HWND16 hWnd = lpPos->hwndIconTitle;
1117 TRACE("0x%04x %i\n", pWnd->hwndSelf, (bShow != 0) );
1119 if( !hWnd )
1120 lpPos->hwndIconTitle = hWnd = ICONTITLE_Create( pWnd );
1121 if( bShow )
1123 if( ( pWnd = WIN_FindWndPtr(hWnd) ) != NULL)
1125 if( !(pWnd->dwStyle & WS_VISIBLE) )
1127 SendMessageA( hWnd, WM_SHOWWINDOW, TRUE, 0 );
1128 SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
1129 SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
1131 WIN_ReleaseWndPtr(pWnd);
1134 else ShowWindow( hWnd, SW_HIDE );
1136 return FALSE;
1139 /*******************************************************************
1140 * WINPOS_GetMinMaxInfo
1142 * Get the minimized and maximized information for a window.
1144 void WINPOS_GetMinMaxInfo( WND *wndPtr, POINT *maxSize, POINT *maxPos,
1145 POINT *minTrack, POINT *maxTrack )
1147 LPINTERNALPOS lpPos;
1148 MINMAXINFO MinMax;
1149 INT xinc, yinc;
1151 /* Compute default values */
1153 MinMax.ptMaxSize.x = GetSystemMetrics(SM_CXSCREEN);
1154 MinMax.ptMaxSize.y = GetSystemMetrics(SM_CYSCREEN);
1155 MinMax.ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
1156 MinMax.ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
1157 MinMax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXSCREEN);
1158 MinMax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYSCREEN);
1160 if (wndPtr->dwExStyle & WS_EX_MANAGED) xinc = yinc = 0;
1161 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1163 xinc = GetSystemMetrics(SM_CXDLGFRAME);
1164 yinc = GetSystemMetrics(SM_CYDLGFRAME);
1166 else
1168 xinc = yinc = 0;
1169 if (HAS_THICKFRAME(wndPtr->dwStyle))
1171 xinc += GetSystemMetrics(SM_CXFRAME);
1172 yinc += GetSystemMetrics(SM_CYFRAME);
1174 if (wndPtr->dwStyle & WS_BORDER)
1176 xinc += GetSystemMetrics(SM_CXBORDER);
1177 yinc += GetSystemMetrics(SM_CYBORDER);
1180 MinMax.ptMaxSize.x += 2 * xinc;
1181 MinMax.ptMaxSize.y += 2 * yinc;
1183 lpPos = (LPINTERNALPOS)GetPropA( wndPtr->hwndSelf, atomInternalPos );
1184 if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
1185 CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
1186 else
1188 MinMax.ptMaxPosition.x = -xinc;
1189 MinMax.ptMaxPosition.y = -yinc;
1192 SendMessageA( wndPtr->hwndSelf, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
1194 /* Some sanity checks */
1196 TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1197 MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
1198 MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
1199 MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
1200 MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
1201 MinMax.ptMaxTrackSize.x = max( MinMax.ptMaxTrackSize.x,
1202 MinMax.ptMinTrackSize.x );
1203 MinMax.ptMaxTrackSize.y = max( MinMax.ptMaxTrackSize.y,
1204 MinMax.ptMinTrackSize.y );
1206 if (maxSize) *maxSize = MinMax.ptMaxSize;
1207 if (maxPos) *maxPos = MinMax.ptMaxPosition;
1208 if (minTrack) *minTrack = MinMax.ptMinTrackSize;
1209 if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
1212 /***********************************************************************
1213 * WINPOS_MinMaximize
1215 * Fill in lpRect and return additional flags to be used with SetWindowPos().
1216 * This function assumes that 'cmd' is different from the current window
1217 * state.
1219 UINT WINPOS_MinMaximize( WND* wndPtr, UINT16 cmd, LPRECT16 lpRect )
1221 UINT swpFlags = 0;
1222 POINT pt, size;
1223 LPINTERNALPOS lpPos;
1225 TRACE("0x%04x %u\n", wndPtr->hwndSelf, cmd );
1227 size.x = wndPtr->rectWindow.left; size.y = wndPtr->rectWindow.top;
1228 lpPos = WINPOS_InitInternalPos( wndPtr, size, &wndPtr->rectWindow );
1230 if (lpPos && !HOOK_CallHooks16(WH_CBT, HCBT_MINMAX, wndPtr->hwndSelf, cmd))
1232 if( wndPtr->dwStyle & WS_MINIMIZE )
1234 if( !SendMessageA( wndPtr->hwndSelf, WM_QUERYOPEN, 0, 0L ) )
1235 return (SWP_NOSIZE | SWP_NOMOVE);
1236 swpFlags |= SWP_NOCOPYBITS;
1238 switch( cmd )
1240 case SW_MINIMIZE:
1241 if( wndPtr->dwStyle & WS_MAXIMIZE)
1243 wndPtr->flags |= WIN_RESTORE_MAX;
1244 wndPtr->dwStyle &= ~WS_MAXIMIZE;
1246 else
1247 wndPtr->flags &= ~WIN_RESTORE_MAX;
1248 wndPtr->dwStyle |= WS_MINIMIZE;
1250 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, TRUE ) )
1251 swpFlags |= MINMAX_NOSWP;
1253 lpPos->ptIconPos = WINPOS_FindIconPos( wndPtr, lpPos->ptIconPos );
1255 SetRect16( lpRect, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1256 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON) );
1257 swpFlags |= SWP_NOCOPYBITS;
1258 break;
1260 case SW_MAXIMIZE:
1261 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1262 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL );
1263 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1265 if( wndPtr->dwStyle & WS_MINIMIZE )
1267 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE );
1269 WINPOS_ShowIconTitle( wndPtr, FALSE );
1270 wndPtr->dwStyle &= ~WS_MINIMIZE;
1272 wndPtr->dwStyle |= WS_MAXIMIZE;
1274 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1275 size.x, size.y );
1276 break;
1278 case SW_RESTORE:
1279 if( wndPtr->dwStyle & WS_MINIMIZE )
1281 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE );
1283 wndPtr->dwStyle &= ~WS_MINIMIZE;
1284 WINPOS_ShowIconTitle( wndPtr, FALSE );
1286 if( wndPtr->flags & WIN_RESTORE_MAX)
1288 /* Restore to maximized position */
1289 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1290 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL);
1291 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1292 wndPtr->dwStyle |= WS_MAXIMIZE;
1293 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y, size.x, size.y );
1294 break;
1297 else
1298 if( !(wndPtr->dwStyle & WS_MAXIMIZE) ) return (UINT16)(-1);
1299 else wndPtr->dwStyle &= ~WS_MAXIMIZE;
1301 /* Restore to normal position */
1303 *lpRect = lpPos->rectNormal;
1304 lpRect->right -= lpRect->left;
1305 lpRect->bottom -= lpRect->top;
1307 break;
1309 } else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
1310 return swpFlags;
1313 /***********************************************************************
1314 * ShowWindowAsync (USER32.@)
1316 * doesn't wait; returns immediately.
1317 * used by threads to toggle windows in other (possibly hanging) threads
1319 BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd )
1321 /* FIXME: does ShowWindow() return immediately ? */
1322 return ShowWindow(hwnd, cmd);
1326 /***********************************************************************
1327 * ShowWindow (USER.42)
1329 BOOL16 WINAPI ShowWindow16( HWND16 hwnd, INT16 cmd )
1331 return ShowWindow(hwnd,cmd);
1335 /***********************************************************************
1336 * ShowWindow (USER32.@)
1338 BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
1340 WND* wndPtr = WIN_FindWndPtr( hwnd );
1341 BOOL wasVisible, showFlag;
1342 RECT16 newPos = {0, 0, 0, 0};
1343 UINT swp = 0;
1345 if (!wndPtr) return FALSE;
1347 TRACE("hwnd=%04x, cmd=%d\n", hwnd, cmd);
1349 wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
1351 switch(cmd)
1353 case SW_HIDE:
1354 if (!wasVisible) goto END;;
1355 swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
1356 SWP_NOACTIVATE | SWP_NOZORDER;
1357 break;
1359 case SW_SHOWMINNOACTIVE:
1360 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1361 /* fall through */
1362 case SW_SHOWMINIMIZED:
1363 swp |= SWP_SHOWWINDOW;
1364 /* fall through */
1365 case SW_MINIMIZE:
1366 swp |= SWP_FRAMECHANGED;
1367 if( !(wndPtr->dwStyle & WS_MINIMIZE) )
1368 swp |= WINPOS_MinMaximize( wndPtr, SW_MINIMIZE, &newPos );
1369 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1370 break;
1372 case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
1373 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1374 if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
1375 swp |= WINPOS_MinMaximize( wndPtr, SW_MAXIMIZE, &newPos );
1376 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1377 break;
1379 case SW_SHOWNA:
1380 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1381 /* fall through */
1382 case SW_SHOW:
1383 swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
1386 * ShowWindow has a little peculiar behavior that if the
1387 * window is already the topmost window, it will not
1388 * activate it.
1390 if (GetTopWindow((HWND)0)==hwnd && (wasVisible || GetActiveWindow() == hwnd))
1391 swp |= SWP_NOACTIVATE;
1393 break;
1395 case SW_SHOWNOACTIVATE:
1396 swp |= SWP_NOZORDER;
1397 if (GetActiveWindow()) swp |= SWP_NOACTIVATE;
1398 /* fall through */
1399 case SW_SHOWNORMAL: /* same as SW_NORMAL: */
1400 case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
1401 case SW_RESTORE:
1402 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1404 if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) )
1405 swp |= WINPOS_MinMaximize( wndPtr, SW_RESTORE, &newPos );
1406 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1407 break;
1410 showFlag = (cmd != SW_HIDE);
1411 if (showFlag != wasVisible)
1413 SendMessageA( hwnd, WM_SHOWWINDOW, showFlag, 0 );
1414 if (!IsWindow( hwnd )) goto END;
1417 if ((wndPtr->dwStyle & WS_CHILD) &&
1418 !IsWindowVisible( wndPtr->parent->hwndSelf ) &&
1419 (swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE) )
1421 /* Don't call SetWindowPos() on invisible child windows */
1422 if (cmd == SW_HIDE) wndPtr->dwStyle &= ~WS_VISIBLE;
1423 else wndPtr->dwStyle |= WS_VISIBLE;
1425 else
1427 /* We can't activate a child window */
1428 if ((wndPtr->dwStyle & WS_CHILD) &&
1429 !(wndPtr->dwExStyle & WS_EX_MDICHILD))
1430 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1431 if (!(swp & MINMAX_NOSWP))
1433 SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top,
1434 newPos.right, newPos.bottom, LOWORD(swp) );
1435 if (cmd == SW_HIDE)
1437 /* FIXME: This will cause the window to be activated irrespective
1438 * of whether it is owned by the same thread. Has to be done
1439 * asynchronously.
1442 if (hwnd == GetActiveWindow())
1443 WINPOS_ActivateOtherWindow(wndPtr);
1445 /* Revert focus to parent */
1446 if (hwnd == GetFocus() || IsChild(hwnd, GetFocus()))
1447 SetFocus( GetParent(hwnd) );
1450 if (!IsWindow( hwnd )) goto END;
1451 else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( wndPtr, TRUE );
1454 if (wndPtr->flags & WIN_NEED_SIZE)
1456 /* should happen only in CreateWindowEx() */
1457 int wParam = SIZE_RESTORED;
1459 wndPtr->flags &= ~WIN_NEED_SIZE;
1460 if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
1461 else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
1462 SendMessageA( hwnd, WM_SIZE, wParam,
1463 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
1464 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
1465 SendMessageA( hwnd, WM_MOVE, 0,
1466 MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
1469 END:
1470 WIN_ReleaseWndPtr(wndPtr);
1471 return wasVisible;
1475 /***********************************************************************
1476 * GetInternalWindowPos (USER.460)
1478 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
1479 LPPOINT16 ptIcon )
1481 WINDOWPLACEMENT16 wndpl;
1482 if (GetWindowPlacement16( hwnd, &wndpl ))
1484 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1485 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1486 return wndpl.showCmd;
1488 return 0;
1492 /***********************************************************************
1493 * GetInternalWindowPos (USER32.@)
1495 UINT WINAPI GetInternalWindowPos( HWND hwnd, LPRECT rectWnd,
1496 LPPOINT ptIcon )
1498 WINDOWPLACEMENT wndpl;
1499 if (GetWindowPlacement( hwnd, &wndpl ))
1501 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1502 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1503 return wndpl.showCmd;
1505 return 0;
1508 /***********************************************************************
1509 * GetWindowPlacement (USER.370)
1511 BOOL16 WINAPI GetWindowPlacement16( HWND16 hwnd, WINDOWPLACEMENT16 *wndpl )
1513 WND *pWnd = WIN_FindWndPtr( hwnd );
1514 LPINTERNALPOS lpPos;
1516 if(!pWnd ) return FALSE;
1518 lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1519 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1520 wndpl->length = sizeof(*wndpl);
1521 if( pWnd->dwStyle & WS_MINIMIZE )
1522 wndpl->showCmd = SW_SHOWMINIMIZED;
1523 else
1524 wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE )
1525 ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
1526 if( pWnd->flags & WIN_RESTORE_MAX )
1527 wndpl->flags = WPF_RESTORETOMAXIMIZED;
1528 else
1529 wndpl->flags = 0;
1530 wndpl->ptMinPosition = lpPos->ptIconPos;
1531 wndpl->ptMaxPosition = lpPos->ptMaxPos;
1532 wndpl->rcNormalPosition = lpPos->rectNormal;
1534 WIN_ReleaseWndPtr(pWnd);
1535 return TRUE;
1539 /***********************************************************************
1540 * GetWindowPlacement (USER32.@)
1542 * Win95:
1543 * Fails if wndpl->length of Win95 (!) apps is invalid.
1545 BOOL WINAPI GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *pwpl32 )
1547 if( pwpl32 )
1549 WINDOWPLACEMENT16 wpl;
1550 wpl.length = sizeof(wpl);
1551 if( GetWindowPlacement16( hwnd, &wpl ) )
1553 pwpl32->length = sizeof(*pwpl32);
1554 pwpl32->flags = wpl.flags;
1555 pwpl32->showCmd = wpl.showCmd;
1556 CONV_POINT16TO32( &wpl.ptMinPosition, &pwpl32->ptMinPosition );
1557 CONV_POINT16TO32( &wpl.ptMaxPosition, &pwpl32->ptMaxPosition );
1558 CONV_RECT16TO32( &wpl.rcNormalPosition, &pwpl32->rcNormalPosition );
1559 return TRUE;
1562 return FALSE;
1566 /***********************************************************************
1567 * WINPOS_SetPlacement
1569 static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT16 *wndpl,
1570 UINT flags )
1572 WND *pWnd = WIN_FindWndPtr( hwnd );
1573 if( pWnd )
1575 LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1576 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1578 if( flags & PLACE_MIN ) lpPos->ptIconPos = wndpl->ptMinPosition;
1579 if( flags & PLACE_MAX ) lpPos->ptMaxPos = wndpl->ptMaxPosition;
1580 if( flags & PLACE_RECT) lpPos->rectNormal = wndpl->rcNormalPosition;
1582 if( pWnd->dwStyle & WS_MINIMIZE )
1584 WINPOS_ShowIconTitle( pWnd, FALSE );
1585 if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1586 SetWindowPos( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1587 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1589 else if( pWnd->dwStyle & WS_MAXIMIZE )
1591 if( !EMPTYPOINT(lpPos->ptMaxPos) )
1592 SetWindowPos( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1593 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1595 else if( flags & PLACE_RECT )
1596 SetWindowPos( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1597 lpPos->rectNormal.right - lpPos->rectNormal.left,
1598 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1599 SWP_NOZORDER | SWP_NOACTIVATE );
1601 ShowWindow( hwnd, wndpl->showCmd );
1602 if( IsWindow(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1604 if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd, TRUE );
1606 /* SDK: ...valid only the next time... */
1607 if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1609 WIN_ReleaseWndPtr(pWnd);
1610 return TRUE;
1612 return FALSE;
1616 /***********************************************************************
1617 * SetWindowPlacement (USER.371)
1619 BOOL16 WINAPI SetWindowPlacement16(HWND16 hwnd, const WINDOWPLACEMENT16 *wndpl)
1621 return WINPOS_SetPlacement( hwnd, wndpl,
1622 PLACE_MIN | PLACE_MAX | PLACE_RECT );
1625 /***********************************************************************
1626 * SetWindowPlacement (USER32.@)
1628 * Win95:
1629 * Fails if wndpl->length of Win95 (!) apps is invalid.
1631 BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *pwpl32 )
1633 if( pwpl32 )
1635 WINDOWPLACEMENT16 wpl;
1637 wpl.length = sizeof(WINDOWPLACEMENT16);
1638 wpl.flags = pwpl32->flags;
1639 wpl.showCmd = pwpl32->showCmd;
1640 wpl.ptMinPosition.x = pwpl32->ptMinPosition.x;
1641 wpl.ptMinPosition.y = pwpl32->ptMinPosition.y;
1642 wpl.ptMaxPosition.x = pwpl32->ptMaxPosition.x;
1643 wpl.ptMaxPosition.y = pwpl32->ptMaxPosition.y;
1644 wpl.rcNormalPosition.left = pwpl32->rcNormalPosition.left;
1645 wpl.rcNormalPosition.top = pwpl32->rcNormalPosition.top;
1646 wpl.rcNormalPosition.right = pwpl32->rcNormalPosition.right;
1647 wpl.rcNormalPosition.bottom = pwpl32->rcNormalPosition.bottom;
1649 return WINPOS_SetPlacement( hwnd, &wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1651 return FALSE;
1655 /***********************************************************************
1656 * SetInternalWindowPos (USER.461)
1658 void WINAPI SetInternalWindowPos16( HWND16 hwnd, UINT16 showCmd,
1659 LPRECT16 rect, LPPOINT16 pt )
1661 if( IsWindow16(hwnd) )
1663 WINDOWPLACEMENT16 wndpl;
1664 UINT flags;
1666 wndpl.length = sizeof(wndpl);
1667 wndpl.showCmd = showCmd;
1668 wndpl.flags = flags = 0;
1670 if( pt )
1672 flags |= PLACE_MIN;
1673 wndpl.flags |= WPF_SETMINPOSITION;
1674 wndpl.ptMinPosition = *pt;
1676 if( rect )
1678 flags |= PLACE_RECT;
1679 wndpl.rcNormalPosition = *rect;
1681 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1686 /***********************************************************************
1687 * SetInternalWindowPos (USER32.@)
1689 void WINAPI SetInternalWindowPos( HWND hwnd, UINT showCmd,
1690 LPRECT rect, LPPOINT pt )
1692 if( IsWindow(hwnd) )
1694 WINDOWPLACEMENT16 wndpl;
1695 UINT flags;
1697 wndpl.length = sizeof(wndpl);
1698 wndpl.showCmd = showCmd;
1699 wndpl.flags = flags = 0;
1701 if( pt )
1703 flags |= PLACE_MIN;
1704 wndpl.flags |= WPF_SETMINPOSITION;
1705 CONV_POINT32TO16( pt, &wndpl.ptMinPosition );
1707 if( rect )
1709 flags |= PLACE_RECT;
1710 CONV_RECT32TO16( rect, &wndpl.rcNormalPosition );
1712 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1716 /*******************************************************************
1717 * WINPOS_SetActiveWindow
1719 * SetActiveWindow() back-end. This is the only function that
1720 * can assign active status to a window. It must be called only
1721 * for the top level windows.
1723 BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
1725 CBTACTIVATESTRUCT16* cbtStruct;
1726 WND* wndPtr=0, *wndTemp;
1727 HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1728 MESSAGEQUEUE *pOldActiveQueue = 0, *pNewActiveQueue = 0;
1729 WORD wIconized = 0;
1730 HWND hwndActive = 0;
1731 BOOL bRet = 0;
1733 TRACE("(%04x, %d, %d)\n", hWnd, fMouse, fChangeFocus );
1735 /* Get current active window from the active queue */
1736 if ( hActiveQueue )
1738 pOldActiveQueue = QUEUE_Lock( hActiveQueue );
1739 if ( pOldActiveQueue )
1740 hwndActive = PERQDATA_GetActiveWnd( pOldActiveQueue->pQData );
1743 /* paranoid checks */
1744 if( hWnd == GetDesktopWindow() || (bRet = (hWnd == hwndActive)) )
1745 goto CLEANUP_END;
1747 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1748 * return 0;
1750 wndPtr = WIN_FindWndPtr(hWnd);
1751 hOldActiveQueue = hActiveQueue;
1753 if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1755 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1756 WIN_ReleaseWndPtr(wndTemp);
1758 else
1759 TRACE("no current active window.\n");
1761 /* call CBT hook chain */
1762 if ((cbtStruct = SEGPTR_NEW(CBTACTIVATESTRUCT16)))
1764 cbtStruct->fMouse = fMouse;
1765 cbtStruct->hWndActive = hwndActive;
1766 bRet = (BOOL)HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
1767 (LPARAM)SEGPTR_GET(cbtStruct) );
1768 SEGPTR_FREE(cbtStruct);
1769 if (bRet) goto CLEANUP_END;
1772 /* set prev active wnd to current active wnd and send notification */
1773 if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
1775 MESSAGEQUEUE *pTempActiveQueue = 0;
1777 if (!SendMessageA( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1779 if (GetSysModalWindow16() != hWnd)
1780 goto CLEANUP_END;
1781 /* disregard refusal if hWnd is sysmodal */
1784 SendMessageA( hwndPrevActive, WM_ACTIVATE,
1785 MAKEWPARAM( WA_INACTIVE, wIconized ),
1786 (LPARAM)hWnd );
1788 /* check if something happened during message processing
1789 * (global active queue may have changed)
1791 pTempActiveQueue = QUEUE_Lock( hActiveQueue );
1792 if(!pTempActiveQueue)
1793 goto CLEANUP_END;
1795 hwndActive = PERQDATA_GetActiveWnd( pTempActiveQueue->pQData );
1796 QUEUE_Unlock( pTempActiveQueue );
1797 if( hwndPrevActive != hwndActive )
1798 goto CLEANUP_END;
1801 /* Set new active window in the message queue */
1802 hwndActive = hWnd;
1803 if ( wndPtr )
1805 pNewActiveQueue = QUEUE_Lock( wndPtr->hmemTaskQ );
1806 if ( pNewActiveQueue )
1807 PERQDATA_SetActiveWnd( pNewActiveQueue->pQData, hwndActive );
1809 else /* have to do this or MDI frame activation goes to hell */
1810 if( pOldActiveQueue )
1811 PERQDATA_SetActiveWnd( pOldActiveQueue->pQData, 0 );
1813 /* send palette messages */
1814 if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1815 SendMessage16((HWND16)-1, WM_PALETTEISCHANGING, (WPARAM16)hWnd, 0L );
1817 /* if prev wnd is minimized redraw icon title */
1818 if( IsIconic( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1820 /* managed windows will get ConfigureNotify event */
1821 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_MANAGED))
1823 /* check Z-order and bring hWnd to the top */
1824 for (wndTemp = WIN_LockWndPtr(WIN_GetDesktop()->child); wndTemp; WIN_UpdateWndPtr(&wndTemp,wndTemp->next))
1826 if (wndTemp->dwStyle & WS_VISIBLE) break;
1828 WIN_ReleaseDesktop();
1829 WIN_ReleaseWndPtr(wndTemp);
1831 if( wndTemp != wndPtr )
1832 SetWindowPos(hWnd, HWND_TOP, 0,0,0,0,
1833 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1834 if (!IsWindow(hWnd))
1835 goto CLEANUP;
1838 /* Get a handle to the new active queue */
1839 hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1841 /* send WM_ACTIVATEAPP if necessary */
1842 if (hOldActiveQueue != hNewActiveQueue)
1844 WND **list, **ppWnd;
1845 WND *pDesktop = WIN_GetDesktop();
1847 if ((list = WIN_BuildWinArray( pDesktop, 0, NULL )))
1849 for (ppWnd = list; *ppWnd; ppWnd++)
1851 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1853 if ((*ppWnd)->hmemTaskQ == hOldActiveQueue)
1854 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1855 0, QUEUE_GetQueueTask(hNewActiveQueue) );
1857 WIN_ReleaseWinArray(list);
1860 hActiveQueue = hNewActiveQueue;
1862 if ((list = WIN_BuildWinArray(pDesktop, 0, NULL )))
1864 for (ppWnd = list; *ppWnd; ppWnd++)
1866 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1868 if ((*ppWnd)->hmemTaskQ == hNewActiveQueue)
1869 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1870 1, QUEUE_GetQueueTask( hOldActiveQueue ) );
1872 WIN_ReleaseWinArray(list);
1874 WIN_ReleaseDesktop();
1876 if (hWnd && !IsWindow(hWnd)) goto CLEANUP;
1879 if (hWnd)
1881 /* walk up to the first unowned window */
1882 wndTemp = WIN_LockWndPtr(wndPtr);
1883 while (wndTemp->owner)
1885 WIN_UpdateWndPtr(&wndTemp,wndTemp->owner);
1887 /* and set last active owned popup */
1888 wndTemp->hwndLastActive = hWnd;
1890 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1891 WIN_ReleaseWndPtr(wndTemp);
1892 SendMessageA( hWnd, WM_NCACTIVATE, TRUE, 0 );
1893 SendMessageA( hWnd, WM_ACTIVATE,
1894 MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1895 (LPARAM)hwndPrevActive );
1896 if( !IsWindow(hWnd) ) goto CLEANUP;
1899 /* change focus if possible */
1900 if ( fChangeFocus )
1902 if ( pNewActiveQueue )
1904 HWND hOldFocus = PERQDATA_GetFocusWnd( pNewActiveQueue->pQData );
1906 if ( hOldFocus && WIN_GetTopParent( hOldFocus ) != hwndActive )
1907 FOCUS_SwitchFocus( pNewActiveQueue, hOldFocus,
1908 (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
1909 0 : hwndActive );
1912 if ( pOldActiveQueue &&
1913 ( !pNewActiveQueue ||
1914 pNewActiveQueue->pQData != pOldActiveQueue->pQData ) )
1916 HWND hOldFocus = PERQDATA_GetFocusWnd( pOldActiveQueue->pQData );
1917 if ( hOldFocus )
1918 FOCUS_SwitchFocus( pOldActiveQueue, hOldFocus, 0 );
1922 if( !hwndPrevActive && wndPtr )
1923 (*wndPtr->pDriver->pForceWindowRaise)(wndPtr);
1925 /* if active wnd is minimized redraw icon title */
1926 if( IsIconic(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1928 bRet = (hWnd == hwndActive); /* Success? */
1930 CLEANUP: /* Unlock the message queues before returning */
1932 if ( pNewActiveQueue )
1933 QUEUE_Unlock( pNewActiveQueue );
1935 CLEANUP_END:
1937 if ( pOldActiveQueue )
1938 QUEUE_Unlock( pOldActiveQueue );
1940 WIN_ReleaseWndPtr(wndPtr);
1941 return bRet;
1944 /*******************************************************************
1945 * WINPOS_ActivateOtherWindow
1947 * Activates window other than pWnd.
1949 BOOL WINPOS_ActivateOtherWindow(WND* pWnd)
1951 BOOL bRet = 0;
1952 WND* pWndTo = NULL;
1953 HWND hwndActive = 0;
1955 /* Get current active window from the active queue */
1956 if ( hActiveQueue )
1958 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1959 if ( pActiveQueue )
1961 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1962 QUEUE_Unlock( pActiveQueue );
1966 if( pWnd->hwndSelf == hwndPrevActive )
1967 hwndPrevActive = 0;
1969 if( hwndActive != pWnd->hwndSelf &&
1970 ( hwndActive || QUEUE_IsExitingQueue(pWnd->hmemTaskQ)) )
1971 return 0;
1973 if( !(pWnd->dwStyle & WS_POPUP) || !(pWnd->owner) ||
1974 !WINPOS_CanActivate((pWndTo = WIN_GetTopParentPtr(pWnd->owner))) )
1976 WND* pWndPtr = WIN_GetTopParentPtr(pWnd);
1978 WIN_ReleaseWndPtr(pWndTo);
1979 pWndTo = WIN_FindWndPtr(hwndPrevActive);
1981 while( !WINPOS_CanActivate(pWndTo) )
1983 /* by now owned windows should've been taken care of */
1984 WIN_UpdateWndPtr(&pWndTo,pWndPtr->next);
1985 WIN_UpdateWndPtr(&pWndPtr,pWndTo);
1986 if( !pWndTo ) break;
1988 WIN_ReleaseWndPtr(pWndPtr);
1991 bRet = WINPOS_SetActiveWindow( pWndTo ? pWndTo->hwndSelf : 0, FALSE, TRUE );
1993 /* switch desktop queue to current active */
1994 if( pWndTo )
1996 WIN_GetDesktop()->hmemTaskQ = pWndTo->hmemTaskQ;
1997 WIN_ReleaseWndPtr(pWndTo);
1998 WIN_ReleaseDesktop();
2001 hwndPrevActive = 0;
2002 return bRet;
2005 /*******************************************************************
2006 * WINPOS_ChangeActiveWindow
2009 BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
2011 WND *wndPtr, *wndTemp;
2012 BOOL retvalue;
2013 HWND hwndActive = 0;
2015 /* Get current active window from the active queue */
2016 if ( hActiveQueue )
2018 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2019 if ( pActiveQueue )
2021 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2022 QUEUE_Unlock( pActiveQueue );
2026 if (!hWnd)
2027 return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
2029 wndPtr = WIN_FindWndPtr(hWnd);
2030 if( !wndPtr ) return FALSE;
2032 /* child windows get WM_CHILDACTIVATE message */
2033 if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
2035 retvalue = SendMessageA(hWnd, WM_CHILDACTIVATE, 0, 0L);
2036 goto end;
2039 if( hWnd == hwndActive )
2041 retvalue = FALSE;
2042 goto end;
2045 if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
2047 retvalue = FALSE;
2048 goto end;
2051 /* switch desktop queue to current active */
2052 wndTemp = WIN_GetDesktop();
2053 if( wndPtr->parent == wndTemp)
2054 wndTemp->hmemTaskQ = wndPtr->hmemTaskQ;
2055 WIN_ReleaseDesktop();
2057 retvalue = TRUE;
2058 end:
2059 WIN_ReleaseWndPtr(wndPtr);
2060 return retvalue;
2064 /***********************************************************************
2065 * WINPOS_SendNCCalcSize
2067 * Send a WM_NCCALCSIZE message to a window.
2068 * All parameters are read-only except newClientRect.
2069 * oldWindowRect, oldClientRect and winpos must be non-NULL only
2070 * when calcValidRect is TRUE.
2072 LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect,
2073 RECT *newWindowRect, RECT *oldWindowRect,
2074 RECT *oldClientRect, WINDOWPOS *winpos,
2075 RECT *newClientRect )
2077 NCCALCSIZE_PARAMS params;
2078 WINDOWPOS winposCopy;
2079 LONG result;
2081 params.rgrc[0] = *newWindowRect;
2082 if (calcValidRect)
2084 winposCopy = *winpos;
2085 params.rgrc[1] = *oldWindowRect;
2086 params.rgrc[2] = *oldClientRect;
2087 params.lppos = &winposCopy;
2089 result = SendMessageA( hwnd, WM_NCCALCSIZE, calcValidRect,
2090 (LPARAM)&params );
2091 TRACE("%d,%d-%d,%d\n",
2092 params.rgrc[0].left, params.rgrc[0].top,
2093 params.rgrc[0].right, params.rgrc[0].bottom );
2095 /* If the application send back garbage, ignore it */
2096 if (params.rgrc[0].left <= params.rgrc[0].right && params.rgrc[0].top <= params.rgrc[0].bottom)
2097 *newClientRect = params.rgrc[0];
2099 return result;
2103 /***********************************************************************
2104 * WINPOS_HandleWindowPosChanging16
2106 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2108 LONG WINPOS_HandleWindowPosChanging16( WND *wndPtr, WINDOWPOS16 *winpos )
2110 POINT maxSize, minTrack;
2111 if (winpos->flags & SWP_NOSIZE) return 0;
2112 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2113 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2115 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
2116 if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
2117 if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
2118 if (!(wndPtr->dwStyle & WS_MINIMIZE))
2120 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
2121 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
2124 return 0;
2128 /***********************************************************************
2129 * WINPOS_HandleWindowPosChanging
2131 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2133 LONG WINPOS_HandleWindowPosChanging( WND *wndPtr, WINDOWPOS *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 winpos->cx = min( winpos->cx, maxSize.x );
2142 winpos->cy = min( 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;
2152 /***********************************************************************
2153 * SetWindowPos (USER.232)
2155 BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
2156 INT16 x, INT16 y, INT16 cx, INT16 cy, WORD flags)
2158 return SetWindowPos(hwnd,(INT)(INT16)hwndInsertAfter,x,y,cx,cy,flags);
2161 /***********************************************************************
2162 * SetWindowPos (USER32.@)
2164 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
2165 INT x, INT y, INT cx, INT cy, UINT flags )
2167 WINDOWPOS winpos;
2169 winpos.hwnd = hwnd;
2170 winpos.hwndInsertAfter = hwndInsertAfter;
2171 winpos.x = x;
2172 winpos.y = y;
2173 winpos.cx = cx;
2174 winpos.cy = cy;
2175 winpos.flags = flags;
2176 return USER_Driver.pSetWindowPos( &winpos );
2180 /***********************************************************************
2181 * BeginDeferWindowPos (USER.259)
2183 HDWP16 WINAPI BeginDeferWindowPos16( INT16 count )
2185 return BeginDeferWindowPos( count );
2189 /***********************************************************************
2190 * BeginDeferWindowPos (USER32.@)
2192 HDWP WINAPI BeginDeferWindowPos( INT count )
2194 HDWP handle;
2195 DWP *pDWP;
2197 if (count < 0)
2199 SetLastError(ERROR_INVALID_PARAMETER);
2200 return 0;
2202 /* Windows allows zero count, in which case it allocates context for 8 moves */
2203 if (count == 0) count = 8;
2205 handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
2206 if (!handle) return 0;
2207 pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
2208 pDWP->actualCount = 0;
2209 pDWP->suggestedCount = count;
2210 pDWP->valid = TRUE;
2211 pDWP->wMagic = DWP_MAGIC;
2212 pDWP->hwndParent = 0;
2213 return handle;
2217 /***********************************************************************
2218 * DeferWindowPos (USER.260)
2220 HDWP16 WINAPI DeferWindowPos16( HDWP16 hdwp, HWND16 hwnd, HWND16 hwndAfter,
2221 INT16 x, INT16 y, INT16 cx, INT16 cy,
2222 UINT16 flags )
2224 return DeferWindowPos( hdwp, hwnd, (INT)(INT16)hwndAfter,
2225 x, y, cx, cy, flags );
2229 /***********************************************************************
2230 * DeferWindowPos (USER32.@)
2232 HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter,
2233 INT x, INT y, INT cx, INT cy,
2234 UINT flags )
2236 DWP *pDWP;
2237 int i;
2238 HDWP newhdwp = hdwp,retvalue;
2239 /* HWND parent; */
2240 WND *pWnd;
2242 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
2243 if (!pDWP) return 0;
2244 if (hwnd == GetDesktopWindow()) return 0;
2246 if (!(pWnd=WIN_FindWndPtr( hwnd ))) {
2247 USER_HEAP_FREE( hdwp );
2248 return 0;
2251 /* Numega Bounds Checker Demo dislikes the following code.
2252 In fact, I've not been able to find any "same parent" requirement in any docu
2253 [AM 980509]
2255 #if 0
2256 /* All the windows of a DeferWindowPos() must have the same parent */
2257 parent = pWnd->parent->hwndSelf;
2258 if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
2259 else if (parent != pDWP->hwndParent)
2261 USER_HEAP_FREE( hdwp );
2262 retvalue = 0;
2263 goto END;
2265 #endif
2267 for (i = 0; i < pDWP->actualCount; i++)
2269 if (pDWP->winPos[i].hwnd == hwnd)
2271 /* Merge with the other changes */
2272 if (!(flags & SWP_NOZORDER))
2274 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
2276 if (!(flags & SWP_NOMOVE))
2278 pDWP->winPos[i].x = x;
2279 pDWP->winPos[i].y = y;
2281 if (!(flags & SWP_NOSIZE))
2283 pDWP->winPos[i].cx = cx;
2284 pDWP->winPos[i].cy = cy;
2286 pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
2287 SWP_NOZORDER | SWP_NOREDRAW |
2288 SWP_NOACTIVATE | SWP_NOCOPYBITS|
2289 SWP_NOOWNERZORDER);
2290 pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
2291 SWP_FRAMECHANGED);
2292 retvalue = hdwp;
2293 goto END;
2296 if (pDWP->actualCount >= pDWP->suggestedCount)
2298 newhdwp = USER_HEAP_REALLOC( hdwp,
2299 sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
2300 if (!newhdwp)
2302 retvalue = 0;
2303 goto END;
2305 pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
2306 pDWP->suggestedCount++;
2308 pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
2309 pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
2310 pDWP->winPos[pDWP->actualCount].x = x;
2311 pDWP->winPos[pDWP->actualCount].y = y;
2312 pDWP->winPos[pDWP->actualCount].cx = cx;
2313 pDWP->winPos[pDWP->actualCount].cy = cy;
2314 pDWP->winPos[pDWP->actualCount].flags = flags;
2315 pDWP->actualCount++;
2316 retvalue = newhdwp;
2317 END:
2318 WIN_ReleaseWndPtr(pWnd);
2319 return retvalue;
2323 /***********************************************************************
2324 * EndDeferWindowPos (USER.261)
2326 BOOL16 WINAPI EndDeferWindowPos16( HDWP16 hdwp )
2328 return EndDeferWindowPos( hdwp );
2332 /***********************************************************************
2333 * EndDeferWindowPos (USER32.@)
2335 BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
2337 DWP *pDWP;
2338 WINDOWPOS *winpos;
2339 BOOL res = TRUE;
2340 int i;
2342 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
2343 if (!pDWP) return FALSE;
2344 for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
2346 if (!(res = USER_Driver.pSetWindowPos( winpos ))) break;
2348 USER_HEAP_FREE( hdwp );
2349 return res;
2353 /***********************************************************************
2354 * TileChildWindows (USER.199)
2356 void WINAPI TileChildWindows16( HWND16 parent, WORD action )
2358 FIXME("(%04x, %d): stub\n", parent, action);
2361 /***********************************************************************
2362 * CascadeChildWindows (USER.198)
2364 void WINAPI CascadeChildWindows16( HWND16 parent, WORD action )
2366 FIXME("(%04x, %d): stub\n", parent, action);
2369 /***********************************************************************
2370 * SetProgmanWindow (USER32.@)
2372 HRESULT WINAPI SetProgmanWindow ( HWND hwnd )
2374 hGlobalProgmanWindow = hwnd;
2375 return hGlobalProgmanWindow;
2378 /***********************************************************************
2379 * GetProgmanWindow (USER32.@)
2381 HRESULT WINAPI GetProgmanWindow ( )
2383 return hGlobalProgmanWindow;
2386 /***********************************************************************
2387 * SetShellWindowEx (USER32.@)
2388 * hwndProgman = Progman[Program Manager]
2389 * |-> SHELLDLL_DefView
2390 * hwndListView = | |-> SysListView32
2391 * | | |-> tooltips_class32
2392 * | |
2393 * | |-> SysHeader32
2394 * |
2395 * |-> ProxyTarget
2397 HRESULT WINAPI SetShellWindowEx ( HWND hwndProgman, HWND hwndListView )
2399 FIXME("0x%08x 0x%08x stub\n",hwndProgman ,hwndListView );
2400 hGlobalShellWindow = hwndProgman;
2401 return hGlobalShellWindow;
2405 /***********************************************************************
2406 * SetTaskmanWindow (USER32.@)
2407 * NOTES
2408 * hwnd = MSTaskSwWClass
2409 * |-> SysTabControl32
2411 HRESULT WINAPI SetTaskmanWindow ( HWND hwnd )
2413 hGlobalTaskmanWindow = hwnd;
2414 return hGlobalTaskmanWindow;
2417 /***********************************************************************
2418 * GetTaskmanWindow (USER32.@)
2420 HRESULT WINAPI GetTaskmanWindow ( )
2422 return hGlobalTaskmanWindow;