Added internal Wine messages to perform SetWindowPos, ShowWindow and
[wine/multimedia.git] / windows / winpos.c
blob64e11fed8ec10b0fd7c6283fe20ecd84ff3aa902
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 "wine/server.h"
15 #include "controls.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 "winpos.h"
23 #include "dce.h"
24 #include "nonclient.h"
25 #include "debugtools.h"
26 #include "input.h"
28 DEFAULT_DEBUG_CHANNEL(win);
30 #define HAS_DLGFRAME(style,exStyle) \
31 (((exStyle) & WS_EX_DLGMODALFRAME) || \
32 (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
34 #define HAS_THICKFRAME(style) \
35 (((style) & WS_THICKFRAME) && \
36 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
38 #define EMPTYPOINT(pt) ((*(LONG*)&(pt)) == -1)
40 #define PLACE_MIN 0x0001
41 #define PLACE_MAX 0x0002
42 #define PLACE_RECT 0x0004
45 #define DWP_MAGIC ((INT)('W' | ('P' << 8) | ('O' << 16) | ('S' << 24)))
47 typedef struct
49 INT actualCount;
50 INT suggestedCount;
51 BOOL valid;
52 INT wMagic;
53 HWND hwndParent;
54 WINDOWPOS winPos[1];
55 } DWP;
57 /* ----- internal variables ----- */
59 static HWND hwndPrevActive = 0; /* Previously active window */
60 static HWND hGlobalShellWindow=0; /*the shell*/
61 static HWND hGlobalTaskmanWindow=0;
62 static HWND hGlobalProgmanWindow=0;
64 static LPCSTR atomInternalPos;
66 extern HQUEUE16 hActiveQueue;
68 /***********************************************************************
69 * WINPOS_CreateInternalPosAtom
71 BOOL WINPOS_CreateInternalPosAtom()
73 LPSTR str = "SysIP";
74 atomInternalPos = (LPCSTR)(DWORD)GlobalAddAtomA(str);
75 return (atomInternalPos) ? TRUE : FALSE;
78 /***********************************************************************
79 * WINPOS_CheckInternalPos
81 * Called when a window is destroyed.
83 void WINPOS_CheckInternalPos( HWND hwnd )
85 LPINTERNALPOS lpPos;
86 MESSAGEQUEUE *pMsgQ = 0;
87 WND *wndPtr = WIN_GetPtr( hwnd );
89 if (!wndPtr || wndPtr == WND_OTHER_PROCESS) return;
91 lpPos = (LPINTERNALPOS) GetPropA( hwnd, atomInternalPos );
93 /* Retrieve the message queue associated with this window */
94 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
95 if ( !pMsgQ )
97 WARN("\tMessage queue not found. Exiting!\n" );
98 WIN_ReleasePtr( wndPtr );
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 WIN_ReleasePtr( wndPtr );
121 /***********************************************************************
122 * ArrangeIconicWindows (USER32.@)
124 UINT WINAPI ArrangeIconicWindows( HWND parent )
126 RECT rectParent;
127 HWND hwndChild;
128 INT x, y, xspacing, yspacing;
130 GetClientRect( parent, &rectParent );
131 x = rectParent.left;
132 y = rectParent.bottom;
133 xspacing = GetSystemMetrics(SM_CXICONSPACING);
134 yspacing = GetSystemMetrics(SM_CYICONSPACING);
136 hwndChild = GetWindow( parent, GW_CHILD );
137 while (hwndChild)
139 if( IsIconic( hwndChild ) )
141 WINPOS_ShowIconTitle( hwndChild, FALSE );
143 SetWindowPos( hwndChild, 0, x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2,
144 y - yspacing - GetSystemMetrics(SM_CYICON)/2, 0, 0,
145 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
146 if( IsWindow(hwndChild) )
147 WINPOS_ShowIconTitle(hwndChild , TRUE );
149 if (x <= rectParent.right - xspacing) x += xspacing;
150 else
152 x = rectParent.left;
153 y -= yspacing;
156 hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
158 return yspacing;
162 /***********************************************************************
163 * SwitchToThisWindow (USER32.@)
165 void WINAPI SwitchToThisWindow( HWND hwnd, BOOL restore )
167 ShowWindow( hwnd, restore ? SW_RESTORE : SW_SHOWMINIMIZED );
171 /***********************************************************************
172 * GetWindowRect (USER32.@)
174 BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect )
176 BOOL ret;
177 WND *wndPtr = WIN_GetPtr( hwnd );
179 if (!wndPtr) return FALSE;
181 if (wndPtr != WND_OTHER_PROCESS)
183 *rect = wndPtr->rectWindow;
184 WIN_ReleasePtr( wndPtr );
185 ret = TRUE;
187 else
189 SERVER_START_REQ( get_window_rectangles )
191 req->handle = hwnd;
192 if ((ret = !SERVER_CALL_ERR()))
194 rect->left = req->window.left;
195 rect->top = req->window.top;
196 rect->right = req->window.right;
197 rect->bottom = req->window.bottom;
200 SERVER_END_REQ;
202 if (ret)
204 MapWindowPoints( GetAncestor( hwnd, GA_PARENT ), 0, (POINT *)rect, 2 );
205 TRACE( "hwnd %04x (%d,%d)-(%d,%d)\n",
206 hwnd, rect->left, rect->top, rect->right, rect->bottom);
208 return ret;
212 /***********************************************************************
213 * GetWindowRgn (USER32.@)
215 int WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
217 int nRet = ERROR;
218 WND *wndPtr = WIN_FindWndPtr( hwnd );
219 if (wndPtr)
221 if (wndPtr->hrgnWnd) nRet = CombineRgn( hrgn, wndPtr->hrgnWnd, 0, RGN_COPY );
222 WIN_ReleaseWndPtr(wndPtr);
224 return nRet;
227 /***********************************************************************
228 * SetWindowRgn (USER32.@)
230 int WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL bRedraw )
232 RECT rect;
233 WND *wndPtr;
234 int ret = FALSE;
236 if (USER_Driver.pSetWindowRgn)
237 return USER_Driver.pSetWindowRgn( hwnd, hrgn, bRedraw );
239 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
241 if (wndPtr->hrgnWnd == hrgn)
243 ret = TRUE;
244 goto done;
247 if (hrgn) /* verify that region really exists */
249 if (GetRgnBox( hrgn, &rect ) == ERROR) goto done;
252 if (wndPtr->hrgnWnd)
254 /* delete previous region */
255 DeleteObject(wndPtr->hrgnWnd);
256 wndPtr->hrgnWnd = 0;
258 wndPtr->hrgnWnd = hrgn;
260 /* Size the window to the rectangle of the new region (if it isn't NULL) */
261 if (hrgn) SetWindowPos( hwnd, 0, rect.left, rect.top,
262 rect.right - rect.left, rect.bottom - rect.top,
263 SWP_NOSIZE | SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOACTIVATE |
264 SWP_NOZORDER | (bRedraw ? 0 : SWP_NOREDRAW) );
265 ret = TRUE;
267 done:
268 WIN_ReleaseWndPtr(wndPtr);
269 return ret;
273 /***********************************************************************
274 * GetClientRect (USER32.@)
276 BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect )
278 BOOL ret;
279 WND *wndPtr = WIN_GetPtr( hwnd );
281 rect->left = rect->top = rect->right = rect->bottom = 0;
282 if (!wndPtr) return FALSE;
284 if (wndPtr != WND_OTHER_PROCESS)
286 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
287 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
288 WIN_ReleasePtr( wndPtr );
289 ret = TRUE;
291 else
293 SERVER_START_REQ( get_window_rectangles )
295 req->handle = hwnd;
296 if ((ret = !SERVER_CALL_ERR()))
298 rect->right = req->client.right - req->client.left;
299 rect->bottom = req->client.bottom - req->client.top;
302 SERVER_END_REQ;
304 return ret;
308 /*******************************************************************
309 * ClientToScreen (USER32.@)
311 BOOL WINAPI ClientToScreen( HWND hwnd, LPPOINT lppnt )
313 MapWindowPoints( hwnd, 0, lppnt, 1 );
314 return TRUE;
318 /*******************************************************************
319 * ScreenToClient (USER32.@)
321 BOOL WINAPI ScreenToClient( HWND hwnd, LPPOINT lppnt )
323 MapWindowPoints( 0, hwnd, lppnt, 1 );
324 return TRUE;
328 /***********************************************************************
329 * find_child_from_point
331 * Find the child that contains pt. Helper for WindowFromPoint.
332 * pt is in parent client coordinates.
333 * lparam is the param to pass in the WM_NCHITTEST message.
335 static HWND find_child_from_point( HWND parent, POINT pt, INT *hittest, LPARAM lparam )
337 int i, res;
338 WND *wndPtr;
339 HWND *list = WIN_ListChildren( parent );
341 if (!list) return 0;
342 for (i = 0; list[i]; i++)
344 if (!(wndPtr = WIN_FindWndPtr( list[i] ))) continue;
345 /* If point is in window, and window is visible, and it */
346 /* is enabled (or it's a top-level window), then explore */
347 /* its children. Otherwise, go to the next window. */
349 if (!(wndPtr->dwStyle & WS_VISIBLE)) goto next; /* not visible -> skip */
350 if ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD | WS_DISABLED)) == (WS_CHILD | WS_DISABLED))
351 goto next; /* disabled child -> skip */
352 if ((wndPtr->dwExStyle & (WS_EX_LAYERED | WS_EX_TRANSPARENT)) == (WS_EX_LAYERED | WS_EX_TRANSPARENT))
353 goto next; /* transparent -> skip */
354 if (wndPtr->hrgnWnd)
356 if (!PtInRegion( wndPtr->hrgnWnd, pt.x - wndPtr->rectWindow.left,
357 pt.y - wndPtr->rectWindow.top ))
358 goto next; /* point outside window region -> skip */
360 else if (!PtInRect( &wndPtr->rectWindow, pt )) goto next; /* not in window -> skip */
362 /* If window is minimized or disabled, return at once */
363 if (wndPtr->dwStyle & WS_MINIMIZE)
365 WIN_ReleaseWndPtr( wndPtr );
366 *hittest = HTCAPTION;
367 return list[i];
369 if (wndPtr->dwStyle & WS_DISABLED)
371 WIN_ReleaseWndPtr( wndPtr );
372 *hittest = HTERROR;
373 return list[i];
376 /* If point is in client area, explore children */
377 if (PtInRect( &wndPtr->rectClient, pt ))
379 POINT new_pt;
380 HWND ret;
382 new_pt.x = pt.x - wndPtr->rectClient.left;
383 new_pt.y = pt.y - wndPtr->rectClient.top;
384 WIN_ReleaseWndPtr( wndPtr );
385 if ((ret = find_child_from_point( list[i], new_pt, hittest, lparam )))
386 return ret;
388 else WIN_ReleaseWndPtr( wndPtr );
390 /* Now it's inside window, send WM_NCCHITTEST (if same thread) */
391 if (!WIN_IsCurrentThread( list[i] ))
393 *hittest = HTCLIENT;
394 return list[i];
396 if ((res = SendMessageA( list[i], WM_NCHITTEST, 0, lparam )) != HTTRANSPARENT)
398 *hittest = res; /* Found the window */
399 return list[i];
401 continue; /* continue search with next sibling */
403 next:
404 WIN_ReleaseWndPtr( wndPtr );
406 return 0;
410 /***********************************************************************
411 * WINPOS_WindowFromPoint
413 * Find the window and hittest for a given point.
415 HWND WINPOS_WindowFromPoint( HWND hwndScope, POINT pt, INT *hittest )
417 WND *wndScope;
418 POINT xy = pt;
419 int res;
421 TRACE("scope %04x %ld,%ld\n", hwndScope, pt.x, pt.y);
423 if (!hwndScope) hwndScope = GetDesktopWindow();
424 if (!(wndScope = WIN_FindWndPtr( hwndScope ))) return 0;
425 hwndScope = wndScope->hwndSelf; /* make it a full handle */
427 *hittest = HTERROR;
428 if( wndScope->dwStyle & WS_DISABLED )
430 WIN_ReleaseWndPtr(wndScope);
431 return 0;
434 if (wndScope->parent)
435 MapWindowPoints( GetDesktopWindow(), wndScope->parent, &xy, 1 );
437 if (!(wndScope->dwStyle & WS_MINIMIZE) && PtInRect( &wndScope->rectClient, xy ))
439 HWND ret;
441 xy.x -= wndScope->rectClient.left;
442 xy.y -= wndScope->rectClient.top;
443 WIN_ReleaseWndPtr( wndScope );
444 if ((ret = find_child_from_point( hwndScope, xy, hittest, MAKELONG( pt.x, pt.y ) )))
446 TRACE( "found child %x\n", ret );
447 return ret;
450 else WIN_ReleaseWndPtr( wndScope );
452 /* If nothing found, try the scope window */
453 if (!WIN_IsCurrentThread( hwndScope ))
455 *hittest = HTCLIENT;
456 TRACE( "returning %x\n", hwndScope );
457 return hwndScope;
459 res = SendMessageA( hwndScope, WM_NCHITTEST, 0, MAKELONG( pt.x, pt.y ) );
460 if (res != HTTRANSPARENT)
462 *hittest = res; /* Found the window */
463 TRACE( "returning %x\n", hwndScope );
464 return hwndScope;
466 *hittest = HTNOWHERE;
467 TRACE( "nothing found\n" );
468 return 0;
472 /*******************************************************************
473 * WindowFromPoint (USER32.@)
475 HWND WINAPI WindowFromPoint( POINT pt )
477 INT hittest;
478 return WINPOS_WindowFromPoint( 0, pt, &hittest );
482 /*******************************************************************
483 * ChildWindowFromPoint (USER32.@)
485 HWND WINAPI ChildWindowFromPoint( HWND hwndParent, POINT pt )
487 return ChildWindowFromPointEx( hwndParent, pt, CWP_ALL );
490 /*******************************************************************
491 * ChildWindowFromPointEx (USER32.@)
493 HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt, UINT uFlags)
495 /* pt is in the client coordinates */
496 HWND *list;
497 int i;
498 RECT rect;
499 HWND retvalue = 0;
501 GetClientRect( hwndParent, &rect );
502 if (!PtInRect( &rect, pt )) return 0;
503 if (!(list = WIN_ListChildren( hwndParent ))) return 0;
505 for (i = 0; list[i] && !retvalue; i++)
507 WND *wnd = WIN_FindWndPtr( list[i] );
508 if (!wnd) continue;
509 if (PtInRect( &wnd->rectWindow, pt ))
511 if ( (uFlags & CWP_SKIPINVISIBLE) &&
512 !(wnd->dwStyle & WS_VISIBLE) );
513 else if ( (uFlags & CWP_SKIPDISABLED) &&
514 (wnd->dwStyle & WS_DISABLED) );
515 else if ( (uFlags & CWP_SKIPTRANSPARENT) &&
516 (wnd->dwExStyle & WS_EX_TRANSPARENT) );
517 else retvalue = list[i];
519 WIN_ReleaseWndPtr( wnd );
521 HeapFree( GetProcessHeap(), 0, list );
522 if (!retvalue) retvalue = hwndParent;
523 return retvalue;
527 /*******************************************************************
528 * WINPOS_GetWinOffset
530 * Calculate the offset between the origin of the two windows. Used
531 * to implement MapWindowPoints.
533 static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo, POINT *offset )
535 WND * wndPtr;
537 offset->x = offset->y = 0;
539 /* Translate source window origin to screen coords */
540 if (hwndFrom)
542 HWND hwnd = hwndFrom;
544 while (hwnd)
546 if (hwnd == hwndTo) return;
547 if (!(wndPtr = WIN_GetPtr( hwnd )))
549 ERR( "bad hwndFrom = %04x\n", hwnd );
550 return;
552 if (wndPtr == WND_OTHER_PROCESS) goto other_process;
553 offset->x += wndPtr->rectClient.left;
554 offset->y += wndPtr->rectClient.top;
555 hwnd = wndPtr->parent;
556 WIN_ReleasePtr( wndPtr );
560 /* Translate origin to destination window coords */
561 if (hwndTo)
563 HWND hwnd = hwndTo;
565 while (hwnd)
567 if (!(wndPtr = WIN_GetPtr( hwnd )))
569 ERR( "bad hwndTo = %04x\n", hwnd );
570 return;
572 if (wndPtr == WND_OTHER_PROCESS) goto other_process;
573 offset->x -= wndPtr->rectClient.left;
574 offset->y -= wndPtr->rectClient.top;
575 hwnd = wndPtr->parent;
576 WIN_ReleasePtr( wndPtr );
579 return;
581 other_process: /* one of the parents may belong to another process, do it the hard way */
582 offset->x = offset->y = 0;
583 SERVER_START_REQ( get_windows_offset )
585 req->from = hwndFrom;
586 req->to = hwndTo;
587 if (!SERVER_CALL())
589 offset->x = req->x;
590 offset->y = req->y;
593 SERVER_END_REQ;
597 /*******************************************************************
598 * MapWindowPoints (USER.258)
600 void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
601 LPPOINT16 lppt, UINT16 count )
603 POINT offset;
605 WINPOS_GetWinOffset( WIN_Handle32(hwndFrom), WIN_Handle32(hwndTo), &offset );
606 while (count--)
608 lppt->x += offset.x;
609 lppt->y += offset.y;
610 lppt++;
615 /*******************************************************************
616 * MapWindowPoints (USER32.@)
618 INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo, LPPOINT lppt, UINT count )
620 POINT offset;
622 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
623 while (count--)
625 lppt->x += offset.x;
626 lppt->y += offset.y;
627 lppt++;
629 return MAKELONG( LOWORD(offset.x), LOWORD(offset.y) );
633 /***********************************************************************
634 * IsIconic (USER32.@)
636 BOOL WINAPI IsIconic(HWND hWnd)
638 return (GetWindowLongW( hWnd, GWL_STYLE ) & WS_MINIMIZE) != 0;
642 /***********************************************************************
643 * IsZoomed (USER32.@)
645 BOOL WINAPI IsZoomed(HWND hWnd)
647 return (GetWindowLongW( hWnd, GWL_STYLE ) & WS_MAXIMIZE) != 0;
651 /*******************************************************************
652 * GetActiveWindow (USER32.@)
654 HWND WINAPI GetActiveWindow(void)
656 MESSAGEQUEUE *pCurMsgQ = 0;
658 /* Get the messageQ for the current thread */
659 if (!(pCurMsgQ = QUEUE_Current()))
661 WARN("\tCurrent message queue not found. Exiting!\n" );
662 return 0;
665 /* Return the current active window from the perQ data of the current message Q */
666 return PERQDATA_GetActiveWnd( pCurMsgQ->pQData );
670 /*******************************************************************
671 * WINPOS_CanActivate
673 static BOOL WINPOS_CanActivate(HWND hwnd)
675 if (!hwnd) return FALSE;
676 return ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_DISABLED|WS_VISIBLE|WS_CHILD)) == WS_VISIBLE);
680 /*******************************************************************
681 * SetActiveWindow (USER32.@)
683 HWND WINAPI SetActiveWindow( HWND hwnd )
685 HWND prev = 0;
686 WND *wndPtr = WIN_FindWndPtr( hwnd );
687 MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
689 if (!wndPtr) return 0;
691 if (wndPtr->dwStyle & (WS_DISABLED | WS_CHILD)) goto error;
693 /* Get the messageQ for the current thread */
694 if (!(pCurMsgQ = QUEUE_Current()))
696 WARN("\tCurrent message queue not found. Exiting!\n" );
697 goto error;
700 /* Retrieve the message queue associated with this window */
701 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
702 if ( !pMsgQ )
704 WARN("\tWindow message queue not found. Exiting!\n" );
705 goto error;
708 /* Make sure that the window is associated with the calling threads
709 * message queue. It must share the same perQ data.
711 if ( pCurMsgQ->pQData != pMsgQ->pQData )
713 QUEUE_Unlock( pMsgQ );
714 goto error;
717 /* Save current active window */
718 prev = PERQDATA_GetActiveWnd( pMsgQ->pQData );
719 QUEUE_Unlock( pMsgQ );
720 WIN_ReleaseWndPtr(wndPtr);
721 WINPOS_SetActiveWindow( hwnd, 0, 0 );
722 return prev;
724 error:
725 WIN_ReleaseWndPtr(wndPtr);
726 return 0;
730 /*******************************************************************
731 * GetForegroundWindow (USER32.@)
733 HWND WINAPI GetForegroundWindow(void)
735 HWND hwndActive = 0;
737 /* Get the foreground window (active window of hActiveQueue) */
738 if ( hActiveQueue )
740 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
741 if ( pActiveQueue )
742 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
744 QUEUE_Unlock( pActiveQueue );
747 return hwndActive;
750 /*******************************************************************
751 * SetForegroundWindow (USER32.@)
753 BOOL WINAPI SetForegroundWindow( HWND hwnd )
755 return WINPOS_ChangeActiveWindow( hwnd, FALSE );
759 /*******************************************************************
760 * AllowSetForegroundWindow (USER32.@)
762 BOOL WINAPI AllowSetForegroundWindow( DWORD procid )
764 /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
765 * implemented, then fix this function. */
766 return TRUE;
770 /*******************************************************************
771 * LockSetForegroundWindow (USER32.@)
773 BOOL WINAPI LockSetForegroundWindow( UINT lockcode )
775 /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
776 * implemented, then fix this function. */
777 return TRUE;
781 /*******************************************************************
782 * SetShellWindow (USER32.@)
784 HWND WINAPI SetShellWindow(HWND hwndshell)
785 { WARN("(hWnd=%08x) semi stub\n",hwndshell );
787 hGlobalShellWindow = WIN_GetFullHandle( hwndshell );
788 return hGlobalShellWindow;
792 /*******************************************************************
793 * GetShellWindow (USER32.@)
795 HWND WINAPI GetShellWindow(void)
796 { WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow );
798 return hGlobalShellWindow;
802 /***********************************************************************
803 * BringWindowToTop (USER32.@)
805 BOOL WINAPI BringWindowToTop( HWND hwnd )
807 return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
811 /***********************************************************************
812 * MoveWindow (USER32.@)
814 BOOL WINAPI MoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy,
815 BOOL repaint )
817 int flags = SWP_NOZORDER | SWP_NOACTIVATE;
818 if (!repaint) flags |= SWP_NOREDRAW;
819 TRACE("%04x %d,%d %dx%d %d\n",
820 hwnd, x, y, cx, cy, repaint );
821 return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
824 /***********************************************************************
825 * WINPOS_InitInternalPos
827 static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT pt, const RECT *restoreRect )
829 LPINTERNALPOS lpPos = (LPINTERNALPOS) GetPropA( wnd->hwndSelf,
830 atomInternalPos );
831 if( !lpPos )
833 /* this happens when the window is minimized/maximized
834 * for the first time (rectWindow is not adjusted yet) */
836 lpPos = HeapAlloc( GetProcessHeap(), 0, sizeof(INTERNALPOS) );
837 if( !lpPos ) return NULL;
839 SetPropA( wnd->hwndSelf, atomInternalPos, (HANDLE)lpPos );
840 lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
841 CONV_RECT32TO16( &wnd->rectWindow, &lpPos->rectNormal );
842 *(UINT*)&lpPos->ptIconPos = *(UINT*)&lpPos->ptMaxPos = 0xFFFFFFFF;
845 if( wnd->dwStyle & WS_MINIMIZE )
846 CONV_POINT32TO16( &pt, &lpPos->ptIconPos );
847 else if( wnd->dwStyle & WS_MAXIMIZE )
848 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
849 else if( restoreRect )
850 CONV_RECT32TO16( restoreRect, &lpPos->rectNormal );
852 return lpPos;
855 /***********************************************************************
856 * WINPOS_RedrawIconTitle
858 BOOL WINPOS_RedrawIconTitle( HWND hWnd )
860 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hWnd, atomInternalPos );
861 if( lpPos )
863 if( lpPos->hwndIconTitle )
865 SendMessageA( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
866 InvalidateRect( lpPos->hwndIconTitle, NULL, TRUE );
867 return TRUE;
870 return FALSE;
873 /***********************************************************************
874 * WINPOS_ShowIconTitle
876 BOOL WINPOS_ShowIconTitle( HWND hwnd, BOOL bShow )
878 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hwnd, atomInternalPos );
880 if( lpPos && !(GetWindowLongA( hwnd, GWL_EXSTYLE) & WS_EX_MANAGED))
882 HWND title = lpPos->hwndIconTitle;
884 TRACE("0x%04x %i\n", hwnd, (bShow != 0) );
886 if( !title )
887 lpPos->hwndIconTitle = title = ICONTITLE_Create( hwnd );
888 if( bShow )
890 if (!IsWindowVisible(title))
892 SendMessageA( title, WM_SHOWWINDOW, TRUE, 0 );
893 SetWindowPos( title, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
894 SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
897 else ShowWindow( title, SW_HIDE );
899 return FALSE;
902 /*******************************************************************
903 * WINPOS_GetMinMaxInfo
905 * Get the minimized and maximized information for a window.
907 void WINPOS_GetMinMaxInfo( HWND hwnd, POINT *maxSize, POINT *maxPos,
908 POINT *minTrack, POINT *maxTrack )
910 LPINTERNALPOS lpPos;
911 MINMAXINFO MinMax;
912 INT xinc, yinc;
913 LONG style = GetWindowLongA( hwnd, GWL_STYLE );
914 LONG exstyle = GetWindowLongA( hwnd, GWL_EXSTYLE );
916 /* Compute default values */
918 MinMax.ptMaxSize.x = GetSystemMetrics(SM_CXSCREEN);
919 MinMax.ptMaxSize.y = GetSystemMetrics(SM_CYSCREEN);
920 MinMax.ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
921 MinMax.ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
922 MinMax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXSCREEN);
923 MinMax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYSCREEN);
925 if (HAS_DLGFRAME( style, exstyle ))
927 xinc = GetSystemMetrics(SM_CXDLGFRAME);
928 yinc = GetSystemMetrics(SM_CYDLGFRAME);
930 else
932 xinc = yinc = 0;
933 if (HAS_THICKFRAME(style))
935 xinc += GetSystemMetrics(SM_CXFRAME);
936 yinc += GetSystemMetrics(SM_CYFRAME);
938 if (style & WS_BORDER)
940 xinc += GetSystemMetrics(SM_CXBORDER);
941 yinc += GetSystemMetrics(SM_CYBORDER);
944 MinMax.ptMaxSize.x += 2 * xinc;
945 MinMax.ptMaxSize.y += 2 * yinc;
947 lpPos = (LPINTERNALPOS)GetPropA( hwnd, atomInternalPos );
948 if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
949 CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
950 else
952 MinMax.ptMaxPosition.x = -xinc;
953 MinMax.ptMaxPosition.y = -yinc;
956 SendMessageA( hwnd, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
958 /* Some sanity checks */
960 TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
961 MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
962 MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
963 MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
964 MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
965 MinMax.ptMaxTrackSize.x = max( MinMax.ptMaxTrackSize.x,
966 MinMax.ptMinTrackSize.x );
967 MinMax.ptMaxTrackSize.y = max( MinMax.ptMaxTrackSize.y,
968 MinMax.ptMinTrackSize.y );
970 if (maxSize) *maxSize = MinMax.ptMaxSize;
971 if (maxPos) *maxPos = MinMax.ptMaxPosition;
972 if (minTrack) *minTrack = MinMax.ptMinTrackSize;
973 if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
976 /***********************************************************************
977 * ShowWindowAsync (USER32.@)
979 * doesn't wait; returns immediately.
980 * used by threads to toggle windows in other (possibly hanging) threads
982 BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd )
984 /* FIXME: does ShowWindow() return immediately ? */
985 return ShowWindow(hwnd, cmd);
989 /***********************************************************************
990 * ShowWindow (USER32.@)
992 BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
994 HWND full_handle;
996 if ((full_handle = WIN_IsCurrentThread( hwnd )))
997 return USER_Driver.pShowWindow( full_handle, cmd );
998 return SendMessageW( hwnd, WM_WINE_SHOWWINDOW, cmd, 0 );
1002 /***********************************************************************
1003 * GetInternalWindowPos (USER.460)
1005 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
1006 LPPOINT16 ptIcon )
1008 WINDOWPLACEMENT16 wndpl;
1009 if (GetWindowPlacement16( hwnd, &wndpl ))
1011 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1012 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1013 return wndpl.showCmd;
1015 return 0;
1019 /***********************************************************************
1020 * GetInternalWindowPos (USER32.@)
1022 UINT WINAPI GetInternalWindowPos( HWND hwnd, LPRECT rectWnd,
1023 LPPOINT ptIcon )
1025 WINDOWPLACEMENT wndpl;
1026 if (GetWindowPlacement( hwnd, &wndpl ))
1028 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1029 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1030 return wndpl.showCmd;
1032 return 0;
1036 /***********************************************************************
1037 * GetWindowPlacement (USER32.@)
1039 * Win95:
1040 * Fails if wndpl->length of Win95 (!) apps is invalid.
1042 BOOL WINAPI GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *wndpl )
1044 WND *pWnd = WIN_FindWndPtr( hwnd );
1045 LPINTERNALPOS lpPos;
1047 if(!pWnd ) return FALSE;
1049 lpPos = WINPOS_InitInternalPos( pWnd, *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1050 wndpl->length = sizeof(*wndpl);
1051 if( pWnd->dwStyle & WS_MINIMIZE )
1052 wndpl->showCmd = SW_SHOWMINIMIZED;
1053 else
1054 wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE ) ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
1055 if( pWnd->flags & WIN_RESTORE_MAX )
1056 wndpl->flags = WPF_RESTORETOMAXIMIZED;
1057 else
1058 wndpl->flags = 0;
1059 CONV_POINT16TO32( &lpPos->ptIconPos, &wndpl->ptMinPosition );
1060 CONV_POINT16TO32( &lpPos->ptMaxPos, &wndpl->ptMaxPosition );
1061 CONV_RECT16TO32( &lpPos->rectNormal, &wndpl->rcNormalPosition );
1062 WIN_ReleaseWndPtr(pWnd);
1063 return TRUE;
1067 /***********************************************************************
1068 * WINPOS_SetPlacement
1070 static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT *wndpl, UINT flags )
1072 WND *pWnd = WIN_FindWndPtr( hwnd );
1073 if( pWnd )
1075 LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1076 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1078 if( flags & PLACE_MIN ) CONV_POINT32TO16( &wndpl->ptMinPosition, &lpPos->ptIconPos );
1079 if( flags & PLACE_MAX ) CONV_POINT32TO16( &wndpl->ptMaxPosition, &lpPos->ptMaxPos );
1080 if( flags & PLACE_RECT) CONV_RECT32TO16( &wndpl->rcNormalPosition, &lpPos->rectNormal );
1082 if( pWnd->dwStyle & WS_MINIMIZE )
1084 WINPOS_ShowIconTitle( pWnd->hwndSelf, FALSE );
1085 if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1086 SetWindowPos( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1087 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1089 else if( pWnd->dwStyle & WS_MAXIMIZE )
1091 if( !EMPTYPOINT(lpPos->ptMaxPos) )
1092 SetWindowPos( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1093 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1095 else if( flags & PLACE_RECT )
1096 SetWindowPos( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1097 lpPos->rectNormal.right - lpPos->rectNormal.left,
1098 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1099 SWP_NOZORDER | SWP_NOACTIVATE );
1101 ShowWindow( hwnd, wndpl->showCmd );
1102 if( IsWindow(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1104 if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd->hwndSelf, TRUE );
1106 /* SDK: ...valid only the next time... */
1107 if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1109 WIN_ReleaseWndPtr(pWnd);
1110 return TRUE;
1112 return FALSE;
1116 /***********************************************************************
1117 * SetWindowPlacement (USER32.@)
1119 * Win95:
1120 * Fails if wndpl->length of Win95 (!) apps is invalid.
1122 BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *wpl )
1124 if (!wpl) return FALSE;
1125 return WINPOS_SetPlacement( hwnd, wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1129 /***********************************************************************
1130 * AnimateWindow (USER32.@)
1131 * Shows/Hides a window with an animation
1132 * NO ANIMATION YET
1134 BOOL WINAPI AnimateWindow(HWND hwnd, DWORD dwTime, DWORD dwFlags)
1136 FIXME("partial stub\n");
1138 /* If trying to show/hide and it's already *
1139 * shown/hidden or invalid window, fail with *
1140 * invalid parameter */
1141 if(!IsWindow(hwnd) ||
1142 (IsWindowVisible(hwnd) && !(dwFlags & AW_HIDE)) ||
1143 (!IsWindowVisible(hwnd) && (dwFlags & AW_HIDE)))
1145 SetLastError(ERROR_INVALID_PARAMETER);
1146 return FALSE;
1149 ShowWindow(hwnd, (dwFlags & AW_HIDE) ? SW_HIDE : ((dwFlags & AW_ACTIVATE) ? SW_SHOW : SW_SHOWNA));
1151 return TRUE;
1154 /***********************************************************************
1155 * SetInternalWindowPos (USER32.@)
1157 void WINAPI SetInternalWindowPos( HWND hwnd, UINT showCmd,
1158 LPRECT rect, LPPOINT pt )
1160 if( IsWindow(hwnd) )
1162 WINDOWPLACEMENT wndpl;
1163 UINT flags;
1165 wndpl.length = sizeof(wndpl);
1166 wndpl.showCmd = showCmd;
1167 wndpl.flags = flags = 0;
1169 if( pt )
1171 flags |= PLACE_MIN;
1172 wndpl.flags |= WPF_SETMINPOSITION;
1173 wndpl.ptMinPosition = *pt;
1175 if( rect )
1177 flags |= PLACE_RECT;
1178 wndpl.rcNormalPosition = *rect;
1180 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1184 /*******************************************************************
1185 * WINPOS_SetActiveWindow
1187 * SetActiveWindow() back-end. This is the only function that
1188 * can assign active status to a window. It must be called only
1189 * for the top level windows.
1191 BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
1193 WND* wndPtr=0, *wndTemp;
1194 HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1195 MESSAGEQUEUE *pOldActiveQueue = 0, *pNewActiveQueue = 0;
1196 WORD wIconized = 0;
1197 HWND hwndActive = 0;
1198 BOOL bRet = 0;
1200 TRACE("(%04x, %d, %d)\n", hWnd, fMouse, fChangeFocus );
1202 /* Get current active window from the active queue */
1203 if ( hActiveQueue )
1205 pOldActiveQueue = QUEUE_Lock( hActiveQueue );
1206 if ( pOldActiveQueue )
1207 hwndActive = PERQDATA_GetActiveWnd( pOldActiveQueue->pQData );
1210 if ((wndPtr = WIN_FindWndPtr(hWnd)))
1211 hWnd = wndPtr->hwndSelf; /* make it a full handle */
1213 /* paranoid checks */
1214 if( hWnd == GetDesktopWindow() || (bRet = (hWnd == hwndActive)) )
1215 goto CLEANUP_END;
1217 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1218 * return 0;
1220 hOldActiveQueue = hActiveQueue;
1222 if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1224 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1225 WIN_ReleaseWndPtr(wndTemp);
1227 else
1228 TRACE("no current active window.\n");
1230 /* call CBT hook chain */
1231 if (HOOK_IsHooked( WH_CBT ))
1233 CBTACTIVATESTRUCT cbt;
1234 cbt.fMouse = fMouse;
1235 cbt.hWndActive = hwndActive;
1236 if (HOOK_CallHooksA( WH_CBT, HCBT_ACTIVATE, (WPARAM)hWnd, (LPARAM)&cbt )) goto CLEANUP_END;
1239 /* set prev active wnd to current active wnd and send notification */
1240 if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
1242 MESSAGEQUEUE *pTempActiveQueue = 0;
1244 if (!SendMessageA( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1246 if (GetSysModalWindow16() != WIN_Handle16(hWnd)) goto CLEANUP_END;
1247 /* disregard refusal if hWnd is sysmodal */
1250 SendMessageA( hwndPrevActive, WM_ACTIVATE,
1251 MAKEWPARAM( WA_INACTIVE, wIconized ),
1252 (LPARAM)hWnd );
1254 /* check if something happened during message processing
1255 * (global active queue may have changed)
1257 pTempActiveQueue = QUEUE_Lock( hActiveQueue );
1258 if(!pTempActiveQueue)
1259 goto CLEANUP_END;
1261 hwndActive = PERQDATA_GetActiveWnd( pTempActiveQueue->pQData );
1262 QUEUE_Unlock( pTempActiveQueue );
1263 if( hwndPrevActive != hwndActive )
1264 goto CLEANUP_END;
1267 /* Set new active window in the message queue */
1268 hwndActive = hWnd;
1269 if ( wndPtr )
1271 pNewActiveQueue = QUEUE_Lock( wndPtr->hmemTaskQ );
1272 if ( pNewActiveQueue )
1273 PERQDATA_SetActiveWnd( pNewActiveQueue->pQData, hwndActive );
1275 else /* have to do this or MDI frame activation goes to hell */
1276 if( pOldActiveQueue )
1277 PERQDATA_SetActiveWnd( pOldActiveQueue->pQData, 0 );
1279 /* send palette messages */
1280 if (hWnd && SendMessageW( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1281 SendMessageW( HWND_BROADCAST, WM_PALETTEISCHANGING, (WPARAM)hWnd, 0 );
1283 /* if prev wnd is minimized redraw icon title */
1284 if( IsIconic( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1286 /* managed windows will get ConfigureNotify event */
1287 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_MANAGED))
1289 /* check Z-order and bring hWnd to the top */
1290 HWND tmp = GetTopWindow(0);
1291 while (tmp && !(GetWindowLongA( tmp, GWL_STYLE ) & WS_VISIBLE))
1292 tmp = GetWindow( tmp, GW_HWNDNEXT );
1294 if( tmp != hWnd )
1295 SetWindowPos(hWnd, HWND_TOP, 0,0,0,0,
1296 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1297 if (!IsWindow(hWnd))
1298 goto CLEANUP;
1301 /* Get a handle to the new active queue */
1302 hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1304 /* send WM_ACTIVATEAPP if necessary */
1305 if (hOldActiveQueue != hNewActiveQueue)
1307 HWND *list, *phwnd;
1308 DWORD old_thread = GetWindowThreadProcessId( hwndPrevActive, NULL );
1309 DWORD new_thread = GetWindowThreadProcessId( hwndActive, NULL );
1311 if ((list = WIN_ListChildren( GetDesktopWindow() )))
1313 for (phwnd = list; *phwnd; phwnd++)
1315 if (!IsWindow( *phwnd )) continue;
1316 if (GetWindowThreadProcessId( *phwnd, NULL ) == old_thread)
1317 SendMessageW( *phwnd, WM_ACTIVATEAPP, 0, new_thread );
1319 HeapFree( GetProcessHeap(), 0, list );
1322 hActiveQueue = hNewActiveQueue;
1324 if ((list = WIN_ListChildren( GetDesktopWindow() )))
1326 for (phwnd = list; *phwnd; phwnd++)
1328 if (!IsWindow( *phwnd )) continue;
1329 if (GetWindowThreadProcessId( *phwnd, NULL ) == new_thread)
1330 SendMessageW( *phwnd, WM_ACTIVATEAPP, 1, old_thread );
1332 HeapFree( GetProcessHeap(), 0, list );
1335 if (hWnd && !IsWindow(hWnd)) goto CLEANUP;
1338 if (hWnd)
1340 /* walk up to the first unowned window */
1341 HWND tmp = GetAncestor( hWnd, GA_ROOTOWNER );
1342 wndTemp = WIN_FindWndPtr( tmp );
1343 /* and set last active owned popup */
1344 wndTemp->hwndLastActive = hWnd;
1346 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1347 WIN_ReleaseWndPtr(wndTemp);
1348 SendMessageA( hWnd, WM_NCACTIVATE, TRUE, 0 );
1349 SendMessageA( hWnd, WM_ACTIVATE,
1350 MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1351 (LPARAM)hwndPrevActive );
1352 if( !IsWindow(hWnd) ) goto CLEANUP;
1355 /* change focus if possible */
1356 if ( fChangeFocus )
1358 if ( pNewActiveQueue )
1360 HWND hOldFocus = PERQDATA_GetFocusWnd( pNewActiveQueue->pQData );
1362 if ( hOldFocus && GetAncestor( hOldFocus, GA_ROOT ) != hwndActive )
1363 FOCUS_SwitchFocus( pNewActiveQueue, hOldFocus,
1364 (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
1365 0 : hwndActive );
1368 if ( pOldActiveQueue &&
1369 ( !pNewActiveQueue ||
1370 pNewActiveQueue->pQData != pOldActiveQueue->pQData ) )
1372 HWND hOldFocus = PERQDATA_GetFocusWnd( pOldActiveQueue->pQData );
1373 if ( hOldFocus )
1374 FOCUS_SwitchFocus( pOldActiveQueue, hOldFocus, 0 );
1378 if( !hwndPrevActive && wndPtr )
1380 if (USER_Driver.pForceWindowRaise) USER_Driver.pForceWindowRaise( wndPtr->hwndSelf );
1383 /* if active wnd is minimized redraw icon title */
1384 if( IsIconic(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1386 bRet = (hWnd == hwndActive); /* Success? */
1388 CLEANUP: /* Unlock the message queues before returning */
1390 if ( pNewActiveQueue )
1391 QUEUE_Unlock( pNewActiveQueue );
1393 CLEANUP_END:
1395 if ( pOldActiveQueue )
1396 QUEUE_Unlock( pOldActiveQueue );
1398 WIN_ReleaseWndPtr(wndPtr);
1399 return bRet;
1402 /*******************************************************************
1403 * WINPOS_ActivateOtherWindow
1405 * Activates window other than pWnd.
1407 BOOL WINPOS_ActivateOtherWindow(HWND hwnd)
1409 BOOL bRet = 0;
1410 HWND hwndActive = 0;
1411 HWND hwndTo = 0;
1412 HWND owner;
1414 /* Get current active window from the active queue */
1415 if ( hActiveQueue )
1417 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1418 if ( pActiveQueue )
1420 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1421 QUEUE_Unlock( pActiveQueue );
1425 if (!(hwnd = WIN_IsCurrentThread( hwnd ))) return 0;
1427 if( hwnd == hwndPrevActive )
1428 hwndPrevActive = 0;
1430 if( hwndActive != hwnd && (hwndActive || USER_IsExitingThread( GetCurrentThreadId() )))
1431 return 0;
1433 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_POPUP) ||
1434 !(owner = GetWindow( hwnd, GW_OWNER )) ||
1435 !WINPOS_CanActivate((hwndTo = GetAncestor( owner, GA_ROOT ))) )
1437 HWND tmp = GetAncestor( hwnd, GA_ROOT );
1438 hwndTo = hwndPrevActive;
1440 while( !WINPOS_CanActivate(hwndTo) )
1442 /* by now owned windows should've been taken care of */
1443 tmp = hwndTo = GetWindow( tmp, GW_HWNDNEXT );
1444 if( !hwndTo ) break;
1448 bRet = WINPOS_SetActiveWindow( hwndTo, FALSE, TRUE );
1450 hwndPrevActive = 0;
1451 return bRet;
1454 /*******************************************************************
1455 * WINPOS_ChangeActiveWindow
1458 BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
1460 WND *wndPtr;
1461 HWND hwndActive = 0;
1463 /* Get current active window from the active queue */
1464 if ( hActiveQueue )
1466 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1467 if ( pActiveQueue )
1469 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1470 QUEUE_Unlock( pActiveQueue );
1474 if (!hWnd)
1475 return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
1477 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1478 hWnd = wndPtr->hwndSelf;
1480 /* child windows get WM_CHILDACTIVATE message */
1481 if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
1483 WIN_ReleaseWndPtr(wndPtr);
1484 return SendMessageA(hWnd, WM_CHILDACTIVATE, 0, 0L);
1486 WIN_ReleaseWndPtr(wndPtr);
1488 if( hWnd == hwndActive ) return FALSE;
1490 return WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE);
1494 /***********************************************************************
1495 * WINPOS_HandleWindowPosChanging16
1497 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
1499 LONG WINPOS_HandleWindowPosChanging16( HWND hwnd, WINDOWPOS16 *winpos )
1501 POINT maxSize, minTrack;
1502 LONG style = GetWindowLongA( hwnd, GWL_STYLE );
1504 if (winpos->flags & SWP_NOSIZE) return 0;
1505 if ((style & WS_THICKFRAME) || ((style & (WS_POPUP | WS_CHILD)) == 0))
1507 WINPOS_GetMinMaxInfo( hwnd, &maxSize, NULL, &minTrack, NULL );
1508 if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
1509 if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
1510 if (!(style & WS_MINIMIZE))
1512 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
1513 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
1516 return 0;
1520 /***********************************************************************
1521 * WINPOS_HandleWindowPosChanging
1523 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
1525 LONG WINPOS_HandleWindowPosChanging( HWND hwnd, WINDOWPOS *winpos )
1527 POINT maxSize, minTrack;
1528 LONG style = GetWindowLongA( hwnd, GWL_STYLE );
1530 if (winpos->flags & SWP_NOSIZE) return 0;
1531 if ((style & WS_THICKFRAME) || ((style & (WS_POPUP | WS_CHILD)) == 0))
1533 WINPOS_GetMinMaxInfo( hwnd, &maxSize, NULL, &minTrack, NULL );
1534 winpos->cx = min( winpos->cx, maxSize.x );
1535 winpos->cy = min( winpos->cy, maxSize.y );
1536 if (!(style & WS_MINIMIZE))
1538 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
1539 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
1542 return 0;
1546 /***********************************************************************
1547 * SetWindowPos (USER32.@)
1549 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
1550 INT x, INT y, INT cx, INT cy, UINT flags )
1552 WINDOWPOS winpos;
1554 winpos.hwnd = hwnd;
1555 winpos.hwndInsertAfter = hwndInsertAfter;
1556 winpos.x = x;
1557 winpos.y = y;
1558 winpos.cx = cx;
1559 winpos.cy = cy;
1560 winpos.flags = flags;
1561 if (WIN_IsCurrentThread( hwnd )) return USER_Driver.pSetWindowPos( &winpos );
1562 return SendMessageW( winpos.hwnd, WM_WINE_SETWINDOWPOS, 0, (LPARAM)&winpos );
1566 /***********************************************************************
1567 * BeginDeferWindowPos (USER32.@)
1569 HDWP WINAPI BeginDeferWindowPos( INT count )
1571 HDWP handle;
1572 DWP *pDWP;
1574 if (count < 0)
1576 SetLastError(ERROR_INVALID_PARAMETER);
1577 return 0;
1579 /* Windows allows zero count, in which case it allocates context for 8 moves */
1580 if (count == 0) count = 8;
1582 handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
1583 if (!handle) return 0;
1584 pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
1585 pDWP->actualCount = 0;
1586 pDWP->suggestedCount = count;
1587 pDWP->valid = TRUE;
1588 pDWP->wMagic = DWP_MAGIC;
1589 pDWP->hwndParent = 0;
1590 return handle;
1594 /***********************************************************************
1595 * DeferWindowPos (USER32.@)
1597 HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter,
1598 INT x, INT y, INT cx, INT cy,
1599 UINT flags )
1601 DWP *pDWP;
1602 int i;
1603 HDWP newhdwp = hdwp,retvalue;
1605 hwnd = WIN_GetFullHandle( hwnd );
1606 if (hwnd == GetDesktopWindow()) return 0;
1608 if (!(pDWP = USER_HEAP_LIN_ADDR( hdwp ))) return 0;
1610 USER_Lock();
1612 for (i = 0; i < pDWP->actualCount; i++)
1614 if (pDWP->winPos[i].hwnd == hwnd)
1616 /* Merge with the other changes */
1617 if (!(flags & SWP_NOZORDER))
1619 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
1621 if (!(flags & SWP_NOMOVE))
1623 pDWP->winPos[i].x = x;
1624 pDWP->winPos[i].y = y;
1626 if (!(flags & SWP_NOSIZE))
1628 pDWP->winPos[i].cx = cx;
1629 pDWP->winPos[i].cy = cy;
1631 pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
1632 SWP_NOZORDER | SWP_NOREDRAW |
1633 SWP_NOACTIVATE | SWP_NOCOPYBITS|
1634 SWP_NOOWNERZORDER);
1635 pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
1636 SWP_FRAMECHANGED);
1637 retvalue = hdwp;
1638 goto END;
1641 if (pDWP->actualCount >= pDWP->suggestedCount)
1643 newhdwp = USER_HEAP_REALLOC( hdwp,
1644 sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
1645 if (!newhdwp)
1647 retvalue = 0;
1648 goto END;
1650 pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
1651 pDWP->suggestedCount++;
1653 pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
1654 pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
1655 pDWP->winPos[pDWP->actualCount].x = x;
1656 pDWP->winPos[pDWP->actualCount].y = y;
1657 pDWP->winPos[pDWP->actualCount].cx = cx;
1658 pDWP->winPos[pDWP->actualCount].cy = cy;
1659 pDWP->winPos[pDWP->actualCount].flags = flags;
1660 pDWP->actualCount++;
1661 retvalue = newhdwp;
1662 END:
1663 USER_Unlock();
1664 return retvalue;
1668 /***********************************************************************
1669 * EndDeferWindowPos (USER32.@)
1671 BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
1673 DWP *pDWP;
1674 WINDOWPOS *winpos;
1675 BOOL res = TRUE;
1676 int i;
1678 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
1679 if (!pDWP) return FALSE;
1680 for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
1682 if (!(res = USER_Driver.pSetWindowPos( winpos ))) break;
1684 USER_HEAP_FREE( hdwp );
1685 return res;
1689 /***********************************************************************
1690 * TileChildWindows (USER.199)
1692 void WINAPI TileChildWindows16( HWND16 parent, WORD action )
1694 FIXME("(%04x, %d): stub\n", parent, action);
1697 /***********************************************************************
1698 * CascadeChildWindows (USER.198)
1700 void WINAPI CascadeChildWindows16( HWND16 parent, WORD action )
1702 FIXME("(%04x, %d): stub\n", parent, action);
1705 /***********************************************************************
1706 * SetProgmanWindow (USER32.@)
1708 HWND WINAPI SetProgmanWindow ( HWND hwnd )
1710 hGlobalProgmanWindow = hwnd;
1711 return hGlobalProgmanWindow;
1714 /***********************************************************************
1715 * GetProgmanWindow (USER32.@)
1717 HWND WINAPI GetProgmanWindow(void)
1719 return hGlobalProgmanWindow;
1722 /***********************************************************************
1723 * SetShellWindowEx (USER32.@)
1724 * hwndProgman = Progman[Program Manager]
1725 * |-> SHELLDLL_DefView
1726 * hwndListView = | |-> SysListView32
1727 * | | |-> tooltips_class32
1728 * | |
1729 * | |-> SysHeader32
1730 * |
1731 * |-> ProxyTarget
1733 HWND WINAPI SetShellWindowEx ( HWND hwndProgman, HWND hwndListView )
1735 FIXME("0x%08x 0x%08x stub\n",hwndProgman ,hwndListView );
1736 hGlobalShellWindow = hwndProgman;
1737 return hGlobalShellWindow;
1741 /***********************************************************************
1742 * SetTaskmanWindow (USER32.@)
1743 * NOTES
1744 * hwnd = MSTaskSwWClass
1745 * |-> SysTabControl32
1747 HWND WINAPI SetTaskmanWindow ( HWND hwnd )
1749 hGlobalTaskmanWindow = hwnd;
1750 return hGlobalTaskmanWindow;
1753 /***********************************************************************
1754 * GetTaskmanWindow (USER32.@)
1756 HWND WINAPI GetTaskmanWindow(void)
1758 return hGlobalTaskmanWindow;