SystemParametersInfo: fixed return value for SPI_SETFASTTASKSWITCH.
[wine] / windows / winpos.c
1 /*
2  * Window position related functions.
3  *
4  * Copyright 1993, 1994, 1995 Alexandre Julliard
5  *                       1995, 1996, 1999 Alex Korobka
6  */
7
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"
27
28 DEFAULT_DEBUG_CHANNEL(win);
29
30 #define HAS_DLGFRAME(style,exStyle) \
31     (((exStyle) & WS_EX_DLGMODALFRAME) || \
32      (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
33
34 #define HAS_THICKFRAME(style) \
35     (((style) & WS_THICKFRAME) && \
36      !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
37
38 #define EMPTYPOINT(pt)          ((*(LONG*)&(pt)) == -1)
39
40 #define PLACE_MIN               0x0001
41 #define PLACE_MAX               0x0002
42 #define PLACE_RECT              0x0004
43
44
45 #define DWP_MAGIC  ((INT)('W' | ('P' << 8) | ('O' << 16) | ('S' << 24)))
46
47 typedef struct
48 {
49     INT       actualCount;
50     INT       suggestedCount;
51     BOOL      valid;
52     INT       wMagic;
53     HWND      hwndParent;
54     WINDOWPOS winPos[1];
55 } DWP;
56
57 /* ----- internal variables ----- */
58
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;
63
64 static LPCSTR atomInternalPos;
65
66 extern HQUEUE16 hActiveQueue;
67
68 /***********************************************************************
69  *           WINPOS_CreateInternalPosAtom
70  */
71 BOOL WINPOS_CreateInternalPosAtom()
72 {
73     LPSTR str = "SysIP";
74     atomInternalPos = (LPCSTR)(DWORD)GlobalAddAtomA(str);
75     return (atomInternalPos) ? TRUE : FALSE;
76 }
77
78 /***********************************************************************
79  *           WINPOS_CheckInternalPos
80  *
81  * Called when a window is destroyed.
82  */
83 void WINPOS_CheckInternalPos( HWND hwnd )
84 {
85     LPINTERNALPOS lpPos;
86     MESSAGEQUEUE *pMsgQ = 0;
87     WND *wndPtr = WIN_GetPtr( hwnd );
88
89     if (!wndPtr || wndPtr == WND_OTHER_PROCESS) return;
90
91     lpPos = (LPINTERNALPOS) GetPropA( hwnd, atomInternalPos );
92
93     /* Retrieve the message queue associated with this window */
94     pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
95     if ( !pMsgQ )
96     {
97         WARN("\tMessage queue not found. Exiting!\n" );
98         WIN_ReleasePtr( wndPtr );
99         return;
100     }
101
102     if( hwnd == hwndPrevActive ) hwndPrevActive = 0;
103
104     if( hwnd == PERQDATA_GetActiveWnd( pMsgQ->pQData ) )
105     {
106         PERQDATA_SetActiveWnd( pMsgQ->pQData, 0 );
107         WARN("\tattempt to activate destroyed window!\n");
108     }
109
110     if( lpPos )
111     {
112         if( IsWindow(lpPos->hwndIconTitle) ) 
113             DestroyWindow( lpPos->hwndIconTitle );
114         HeapFree( GetProcessHeap(), 0, lpPos );
115     }
116
117     QUEUE_Unlock( pMsgQ );
118     WIN_ReleasePtr( wndPtr );
119 }
120
121 /***********************************************************************
122  *              ArrangeIconicWindows (USER32.@)
123  */
124 UINT WINAPI ArrangeIconicWindows( HWND parent )
125 {
126     RECT rectParent;
127     HWND hwndChild;
128     INT x, y, xspacing, yspacing;
129
130     GetClientRect( parent, &rectParent );
131     x = rectParent.left;
132     y = rectParent.bottom;
133     xspacing = GetSystemMetrics(SM_CXICONSPACING);
134     yspacing = GetSystemMetrics(SM_CYICONSPACING);
135
136     hwndChild = GetWindow( parent, GW_CHILD );
137     while (hwndChild)
138     {
139         if( IsIconic( hwndChild ) )
140         {
141             WINPOS_ShowIconTitle( hwndChild, FALSE );
142
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 );
148
149             if (x <= rectParent.right - xspacing) x += xspacing;
150             else
151             {
152                 x = rectParent.left;
153                 y -= yspacing;
154             }
155         }
156         hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
157     }
158     return yspacing;
159 }
160
161
162 /***********************************************************************
163  *              SwitchToThisWindow (USER32.@)
164  */
165 void WINAPI SwitchToThisWindow( HWND hwnd, BOOL restore )
166 {
167     ShowWindow( hwnd, restore ? SW_RESTORE : SW_SHOWMINIMIZED );
168 }
169
170
171 /***********************************************************************
172  *              GetWindowRect (USER32.@)
173  */
174 BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect )
175 {
176     BOOL ret = WIN_GetRectangles( hwnd, rect, NULL );
177     if (ret)
178     {
179         MapWindowPoints( GetAncestor( hwnd, GA_PARENT ), 0, (POINT *)rect, 2 );
180         TRACE( "hwnd %04x (%d,%d)-(%d,%d)\n",
181                hwnd, rect->left, rect->top, rect->right, rect->bottom);
182     }
183     return ret;
184 }
185
186
187 /***********************************************************************
188  *              GetWindowRgn (USER32.@)
189  */
190 int WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
191 {
192     int nRet = ERROR;
193     WND *wndPtr = WIN_GetPtr( hwnd );
194
195     if (wndPtr == WND_OTHER_PROCESS)
196     {
197         if (IsWindow( hwnd ))
198             FIXME( "not supported on other process window %x\n", hwnd );
199         wndPtr = NULL;
200     }
201     if (!wndPtr)
202     {
203         SetLastError( ERROR_INVALID_WINDOW_HANDLE );
204         return ERROR;
205     }
206     if (wndPtr->hrgnWnd) nRet = CombineRgn( hrgn, wndPtr->hrgnWnd, 0, RGN_COPY );
207     WIN_ReleasePtr( wndPtr );
208     return nRet;
209 }
210
211
212 /***********************************************************************
213  *              SetWindowRgn (USER32.@)
214  */
215 int WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL bRedraw )
216 {
217     RECT rect;
218     WND *wndPtr;
219
220     if (hrgn) /* verify that region really exists */
221     {
222         if (GetRgnBox( hrgn, &rect ) == ERROR) return FALSE;
223     }
224
225     if (USER_Driver.pSetWindowRgn)
226         return USER_Driver.pSetWindowRgn( hwnd, hrgn, bRedraw );
227
228     if ((wndPtr = WIN_GetPtr( hwnd )) == WND_OTHER_PROCESS)
229     {
230         if (IsWindow( hwnd ))
231             FIXME( "not supported on other process window %x\n", hwnd );
232         wndPtr = NULL;
233     }
234     if (!wndPtr)
235     {
236         SetLastError( ERROR_INVALID_WINDOW_HANDLE );
237         return FALSE;
238     }
239
240     if (wndPtr->hrgnWnd == hrgn)
241     {
242         WIN_ReleasePtr( wndPtr );
243         return TRUE;
244     }
245
246     if (wndPtr->hrgnWnd)
247     {
248         /* delete previous region */
249         DeleteObject(wndPtr->hrgnWnd);
250         wndPtr->hrgnWnd = 0;
251     }
252     wndPtr->hrgnWnd = hrgn;
253     WIN_ReleasePtr( wndPtr );
254
255     /* Size the window to the rectangle of the new region (if it isn't NULL) */
256     if (hrgn) SetWindowPos( hwnd, 0, rect.left, rect.top,
257                             rect.right  - rect.left, rect.bottom - rect.top,
258                             SWP_NOSIZE | SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOACTIVATE |
259                             SWP_NOZORDER | (bRedraw ? 0 : SWP_NOREDRAW) );
260     return TRUE;
261 }
262
263
264 /***********************************************************************
265  *              GetClientRect (USER32.@)
266  */
267 BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect )
268 {
269     BOOL ret;
270
271     rect->right = rect->bottom = 0;
272     if ((ret = WIN_GetRectangles( hwnd, NULL, rect )))
273     {
274         rect->right -= rect->left;
275         rect->bottom -= rect->top;
276     }
277     rect->left = rect->top = 0;
278     return ret;
279 }
280
281
282 /*******************************************************************
283  *              ClientToScreen (USER32.@)
284  */
285 BOOL WINAPI ClientToScreen( HWND hwnd, LPPOINT lppnt )
286 {
287     MapWindowPoints( hwnd, 0, lppnt, 1 );
288     return TRUE;
289 }
290
291
292 /*******************************************************************
293  *              ScreenToClient (USER32.@)
294  */
295 BOOL WINAPI ScreenToClient( HWND hwnd, LPPOINT lppnt )
296 {
297     MapWindowPoints( 0, hwnd, lppnt, 1 );
298     return TRUE;
299 }
300
301
302 /***********************************************************************
303  *           find_child_from_point
304  *
305  * Find the child that contains pt. Helper for WindowFromPoint.
306  * pt is in parent client coordinates.
307  * lparam is the param to pass in the WM_NCHITTEST message.
308  */
309 static HWND find_child_from_point( HWND parent, POINT pt, INT *hittest, LPARAM lparam )
310 {
311     int i, res;
312     LONG style, exstyle;
313     RECT rectWindow, rectClient;
314     WND *wndPtr;
315     HWND *list = WIN_ListChildren( parent );
316
317     if (!list) return 0;
318     for (i = 0; list[i]; i++)
319     {
320         /* If point is in window, and window is visible, and it  */
321         /* is enabled (or it's a top-level window), then explore */
322         /* its children. Otherwise, go to the next window.       */
323
324         style = GetWindowLongW( list[i], GWL_STYLE );
325         if (!(style & WS_VISIBLE)) continue;  /* not visible -> skip */
326         if ((style & (WS_POPUP | WS_CHILD | WS_DISABLED)) == (WS_CHILD | WS_DISABLED))
327             continue;  /* disabled child -> skip */
328         exstyle = GetWindowLongW( list[i], GWL_EXSTYLE );
329         if ((exstyle & (WS_EX_LAYERED | WS_EX_TRANSPARENT)) == (WS_EX_LAYERED | WS_EX_TRANSPARENT))
330             continue;  /* transparent -> skip */
331
332         if (!WIN_GetRectangles( list[i], &rectWindow, &rectClient )) continue;
333         if (!PtInRect( &rectWindow, pt )) continue;  /* not in window -> skip */
334
335         /* FIXME: check window region for other processes too */
336         if ((wndPtr = WIN_GetPtr( list[i] )) && wndPtr != WND_OTHER_PROCESS)
337         {
338             if (wndPtr->hrgnWnd && !PtInRegion( wndPtr->hrgnWnd,
339                                                 pt.x - rectWindow.left, pt.y - rectWindow.top ))
340             {
341                 WIN_ReleasePtr( wndPtr );
342                 continue;  /* point outside window region -> skip */
343             }
344             WIN_ReleasePtr( wndPtr );
345         }
346
347         /* If window is minimized or disabled, return at once */
348         if (style & WS_MINIMIZE)
349         {
350             *hittest = HTCAPTION;
351             return list[i];
352         }
353         if (style & WS_DISABLED)
354         {
355             *hittest = HTERROR;
356             return list[i];
357         }
358
359         /* If point is in client area, explore children */
360         if (PtInRect( &rectClient, pt ))
361         {
362             POINT new_pt;
363             HWND ret;
364
365             new_pt.x = pt.x - rectClient.left;
366             new_pt.y = pt.y - rectClient.top;
367             if ((ret = find_child_from_point( list[i], new_pt, hittest, lparam )))
368                 return ret;
369         }
370
371         /* Now it's inside window, send WM_NCCHITTEST (if same thread) */
372         if (!WIN_IsCurrentThread( list[i] ))
373         {
374             *hittest = HTCLIENT;
375             return list[i];
376         }
377         if ((res = SendMessageA( list[i], WM_NCHITTEST, 0, lparam )) != HTTRANSPARENT)
378         {
379             *hittest = res;  /* Found the window */
380             return list[i];
381         }
382         /* continue search with next sibling */
383     }
384     return 0;
385 }
386
387
388 /***********************************************************************
389  *           WINPOS_WindowFromPoint
390  *
391  * Find the window and hittest for a given point.
392  */
393 HWND WINPOS_WindowFromPoint( HWND hwndScope, POINT pt, INT *hittest )
394 {
395     POINT xy = pt;
396     int res;
397     LONG style;
398
399     TRACE("scope %04x %ld,%ld\n", hwndScope, pt.x, pt.y);
400
401     if (!hwndScope) hwndScope = GetDesktopWindow();
402     style = GetWindowLongW( hwndScope, GWL_STYLE );
403
404     *hittest = HTERROR;
405     if (style & WS_DISABLED) return 0;
406
407     MapWindowPoints( GetDesktopWindow(), GetAncestor( hwndScope, GA_PARENT ), &xy, 1 );
408
409     if (!(style & WS_MINIMIZE))
410     {
411         RECT rectClient;
412         if (WIN_GetRectangles( hwndScope, NULL, &rectClient ) && PtInRect( &rectClient, xy ))
413         {
414             HWND ret;
415
416             xy.x -= rectClient.left;
417             xy.y -= rectClient.top;
418             if ((ret = find_child_from_point( hwndScope, xy, hittest, MAKELONG( pt.x, pt.y ) )))
419             {
420                 TRACE( "found child %x\n", ret );
421                 return ret;
422             }
423         }
424     }
425
426     /* If nothing found, try the scope window */
427     if (!WIN_IsCurrentThread( hwndScope ))
428     {
429         *hittest = HTCLIENT;
430         TRACE( "returning %x\n", hwndScope );
431         return hwndScope;
432     }
433     res = SendMessageA( hwndScope, WM_NCHITTEST, 0, MAKELONG( pt.x, pt.y ) );
434     if (res != HTTRANSPARENT)
435     {
436         *hittest = res;  /* Found the window */
437         TRACE( "returning %x\n", hwndScope );
438         return hwndScope;
439     }
440     *hittest = HTNOWHERE;
441     TRACE( "nothing found\n" );
442     return 0;
443 }
444
445
446 /*******************************************************************
447  *              WindowFromPoint (USER32.@)
448  */
449 HWND WINAPI WindowFromPoint( POINT pt )
450 {
451     INT hittest;
452     return WINPOS_WindowFromPoint( 0, pt, &hittest );
453 }
454
455
456 /*******************************************************************
457  *              ChildWindowFromPoint (USER32.@)
458  */
459 HWND WINAPI ChildWindowFromPoint( HWND hwndParent, POINT pt )
460 {
461     return ChildWindowFromPointEx( hwndParent, pt, CWP_ALL );
462 }
463
464 /*******************************************************************
465  *              ChildWindowFromPointEx (USER32.@)
466  */
467 HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt, UINT uFlags)
468 {
469     /* pt is in the client coordinates */
470     HWND *list;
471     int i;
472     RECT rect;
473     HWND retvalue;
474
475     GetClientRect( hwndParent, &rect );
476     if (!PtInRect( &rect, pt )) return 0;
477     if (!(list = WIN_ListChildren( hwndParent ))) return 0;
478
479     for (i = 0; list[i]; i++)
480     {
481         if (!WIN_GetRectangles( list[i], &rect, NULL )) continue;
482         if (!PtInRect( &rect, pt )) continue;
483         if (uFlags & (CWP_SKIPINVISIBLE|CWP_SKIPDISABLED))
484         {
485             LONG style = GetWindowLongW( list[i], GWL_STYLE );
486             if ((uFlags & CWP_SKIPINVISIBLE) && !(style & WS_VISIBLE)) continue;
487             if ((uFlags & CWP_SKIPDISABLED) && (style & WS_DISABLED)) continue;
488         }
489         if (uFlags & CWP_SKIPTRANSPARENT)
490         {
491             if (GetWindowLongW( list[i], GWL_EXSTYLE ) & WS_EX_TRANSPARENT) continue;
492         }
493         break;
494     }
495     retvalue = list[i];
496     HeapFree( GetProcessHeap(), 0, list );
497     if (!retvalue) retvalue = hwndParent;
498     return retvalue;
499 }
500
501
502 /*******************************************************************
503  *         WINPOS_GetWinOffset
504  *
505  * Calculate the offset between the origin of the two windows. Used
506  * to implement MapWindowPoints.
507  */
508 static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo, POINT *offset )
509 {
510     WND * wndPtr;
511
512     offset->x = offset->y = 0;
513
514     /* Translate source window origin to screen coords */
515     if (hwndFrom)
516     {
517         HWND hwnd = hwndFrom;
518
519         while (hwnd)
520         {
521             if (hwnd == hwndTo) return;
522             if (!(wndPtr = WIN_GetPtr( hwnd )))
523             {
524                 ERR( "bad hwndFrom = %04x\n", hwnd );
525                 return;
526             }
527             if (wndPtr == WND_OTHER_PROCESS) goto other_process;
528             offset->x += wndPtr->rectClient.left;
529             offset->y += wndPtr->rectClient.top;
530             hwnd = wndPtr->parent;
531             WIN_ReleasePtr( wndPtr );
532         }
533     }
534
535     /* Translate origin to destination window coords */
536     if (hwndTo)
537     {
538         HWND hwnd = hwndTo;
539
540         while (hwnd)
541         {
542             if (!(wndPtr = WIN_GetPtr( hwnd )))
543             {
544                 ERR( "bad hwndTo = %04x\n", hwnd );
545                 return;
546             }
547             if (wndPtr == WND_OTHER_PROCESS) goto other_process;
548             offset->x -= wndPtr->rectClient.left;
549             offset->y -= wndPtr->rectClient.top;
550             hwnd = wndPtr->parent;
551             WIN_ReleasePtr( wndPtr );
552         }
553     }
554     return;
555
556  other_process:  /* one of the parents may belong to another process, do it the hard way */
557     offset->x = offset->y = 0;
558     SERVER_START_REQ( get_windows_offset )
559     {
560         req->from = hwndFrom;
561         req->to   = hwndTo;
562         if (!wine_server_call( req ))
563         {
564             offset->x = reply->x;
565             offset->y = reply->y;
566         }
567     }
568     SERVER_END_REQ;
569 }
570
571
572 /*******************************************************************
573  *              MapWindowPoints (USER.258)
574  */
575 void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
576                                LPPOINT16 lppt, UINT16 count )
577 {
578     POINT offset;
579
580     WINPOS_GetWinOffset( WIN_Handle32(hwndFrom), WIN_Handle32(hwndTo), &offset );
581     while (count--)
582     {
583         lppt->x += offset.x;
584         lppt->y += offset.y;
585         lppt++;
586     }
587 }
588
589
590 /*******************************************************************
591  *              MapWindowPoints (USER32.@)
592  */
593 INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo, LPPOINT lppt, UINT count )
594 {
595     POINT offset;
596
597     WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
598     while (count--)
599     {
600         lppt->x += offset.x;
601         lppt->y += offset.y;
602         lppt++;
603     }
604     return MAKELONG( LOWORD(offset.x), LOWORD(offset.y) );
605 }
606
607
608 /***********************************************************************
609  *              IsIconic (USER32.@)
610  */
611 BOOL WINAPI IsIconic(HWND hWnd)
612 {
613     return (GetWindowLongW( hWnd, GWL_STYLE ) & WS_MINIMIZE) != 0;
614 }
615
616
617 /***********************************************************************
618  *              IsZoomed (USER32.@)
619  */
620 BOOL WINAPI IsZoomed(HWND hWnd)
621 {
622     return (GetWindowLongW( hWnd, GWL_STYLE ) & WS_MAXIMIZE) != 0;
623 }
624
625
626 /*******************************************************************
627  *              GetActiveWindow (USER32.@)
628  */
629 HWND WINAPI GetActiveWindow(void)
630 {
631     MESSAGEQUEUE *pCurMsgQ = 0;
632
633     /* Get the messageQ for the current thread */
634     if (!(pCurMsgQ = QUEUE_Current()))
635 {
636         WARN("\tCurrent message queue not found. Exiting!\n" );
637         return 0;
638     }
639
640     /* Return the current active window from the perQ data of the current message Q */
641     return PERQDATA_GetActiveWnd( pCurMsgQ->pQData );
642 }
643
644
645 /*******************************************************************
646  *         WINPOS_CanActivate
647  */
648 static BOOL WINPOS_CanActivate(HWND hwnd)
649 {
650     if (!hwnd) return FALSE;
651     return ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_DISABLED|WS_CHILD)) == 0);
652 }
653
654 /*******************************************************************
655  *         WINPOS_IsVisible
656  */
657 static BOOL WINPOS_IsVisible(HWND hwnd)
658 {
659     if (!hwnd) return FALSE;
660     return ((GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE) == WS_VISIBLE);
661 }
662
663
664 /*******************************************************************
665  *              SetActiveWindow (USER32.@)
666  */
667 HWND WINAPI SetActiveWindow( HWND hwnd )
668 {
669     HWND prev = 0;
670     WND *wndPtr = WIN_FindWndPtr( hwnd );
671     MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
672
673     if (!wndPtr) return 0;
674
675     if (wndPtr->dwStyle & (WS_DISABLED | WS_CHILD)) goto error;
676
677     /* Get the messageQ for the current thread */
678     if (!(pCurMsgQ = QUEUE_Current()))
679     {
680         WARN("\tCurrent message queue not found. Exiting!\n" );
681         goto error;
682     }
683
684     /* Retrieve the message queue associated with this window */
685     pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
686     if ( !pMsgQ )
687     {
688         WARN("\tWindow message queue not found. Exiting!\n" );
689         goto error;
690     }
691
692     /* Make sure that the window is associated with the calling threads
693      * message queue. It must share the same perQ data.
694      */
695     if ( pCurMsgQ->pQData != pMsgQ->pQData )
696     {
697         QUEUE_Unlock( pMsgQ );
698         goto error;
699     }
700
701     /* Save current active window */
702     prev = PERQDATA_GetActiveWnd( pMsgQ->pQData );
703     QUEUE_Unlock( pMsgQ );
704     WIN_ReleaseWndPtr(wndPtr);
705     WINPOS_SetActiveWindow( hwnd, FALSE, TRUE );
706     return prev;
707
708  error:
709     WIN_ReleaseWndPtr(wndPtr);
710     return 0;
711 }
712
713
714 /*******************************************************************
715  *              GetForegroundWindow (USER32.@)
716  */
717 HWND WINAPI GetForegroundWindow(void)
718 {
719     HWND hwndActive = 0;
720
721     /* Get the foreground window (active window of hActiveQueue) */
722     if ( hActiveQueue )
723     {
724         MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
725         if ( pActiveQueue )
726             hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
727
728         QUEUE_Unlock( pActiveQueue );
729     }
730
731     return hwndActive;
732 }
733
734 /*******************************************************************
735  *              SetForegroundWindow (USER32.@)
736  */
737 BOOL WINAPI SetForegroundWindow( HWND hwnd )
738 {
739     if (!hwnd) return WINPOS_SetActiveWindow( 0, FALSE, TRUE );
740
741     /* child windows get WM_CHILDACTIVATE message */
742     if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD)
743         return SendMessageA( hwnd, WM_CHILDACTIVATE, 0, 0 );
744
745     hwnd = WIN_GetFullHandle( hwnd );
746     if( hwnd == GetForegroundWindow() ) return FALSE;
747
748     return WINPOS_SetActiveWindow( hwnd, FALSE, TRUE );
749 }
750
751
752 /*******************************************************************
753  *              AllowSetForegroundWindow (USER32.@)
754  */
755 BOOL WINAPI AllowSetForegroundWindow( DWORD procid )
756 {
757     /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
758      * implemented, then fix this function. */
759     return TRUE;
760 }
761
762
763 /*******************************************************************
764  *              LockSetForegroundWindow (USER32.@)
765  */
766 BOOL WINAPI LockSetForegroundWindow( UINT lockcode )
767 {
768     /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
769      * implemented, then fix this function. */
770     return TRUE;
771 }
772
773
774 /*******************************************************************
775  *              SetShellWindow (USER32.@)
776  */
777 HWND WINAPI SetShellWindow(HWND hwndshell)
778 {   WARN("(hWnd=%08x) semi stub\n",hwndshell );
779
780     hGlobalShellWindow = WIN_GetFullHandle( hwndshell );
781     return hGlobalShellWindow;
782 }
783
784
785 /*******************************************************************
786  *              GetShellWindow (USER32.@)
787  */
788 HWND WINAPI GetShellWindow(void)
789 {   WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow );
790
791     return hGlobalShellWindow;
792 }
793
794
795 /***********************************************************************
796  *              BringWindowToTop (USER32.@)
797  */
798 BOOL WINAPI BringWindowToTop( HWND hwnd )
799 {
800     return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
801 }
802
803
804 /***********************************************************************
805  *              MoveWindow (USER32.@)
806  */
807 BOOL WINAPI MoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy,
808                             BOOL repaint )
809 {    
810     int flags = SWP_NOZORDER | SWP_NOACTIVATE;
811     if (!repaint) flags |= SWP_NOREDRAW;
812     TRACE("%04x %d,%d %dx%d %d\n", 
813             hwnd, x, y, cx, cy, repaint );
814     return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
815 }
816
817 /***********************************************************************
818  *           WINPOS_InitInternalPos
819  */
820 static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT pt, const RECT *restoreRect )
821 {
822     LPINTERNALPOS lpPos = (LPINTERNALPOS) GetPropA( wnd->hwndSelf,
823                                                       atomInternalPos );
824     if( !lpPos )
825     {
826         /* this happens when the window is minimized/maximized 
827          * for the first time (rectWindow is not adjusted yet) */
828
829         lpPos = HeapAlloc( GetProcessHeap(), 0, sizeof(INTERNALPOS) );
830         if( !lpPos ) return NULL;
831
832         SetPropA( wnd->hwndSelf, atomInternalPos, (HANDLE)lpPos );
833         lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
834         CONV_RECT32TO16( &wnd->rectWindow, &lpPos->rectNormal );
835         *(UINT*)&lpPos->ptIconPos = *(UINT*)&lpPos->ptMaxPos = 0xFFFFFFFF;
836     }
837
838     if( wnd->dwStyle & WS_MINIMIZE ) 
839         CONV_POINT32TO16( &pt, &lpPos->ptIconPos );
840     else if( wnd->dwStyle & WS_MAXIMIZE ) 
841         CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
842     else if( restoreRect ) 
843         CONV_RECT32TO16( restoreRect, &lpPos->rectNormal );
844
845     return lpPos;
846 }
847
848 /***********************************************************************
849  *           WINPOS_RedrawIconTitle
850  */
851 BOOL WINPOS_RedrawIconTitle( HWND hWnd )
852 {
853     LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hWnd, atomInternalPos );
854     if( lpPos )
855     {
856         if( lpPos->hwndIconTitle )
857         {
858             SendMessageA( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
859             InvalidateRect( lpPos->hwndIconTitle, NULL, TRUE );
860             return TRUE;
861         }
862     }
863     return FALSE;
864 }
865
866 /***********************************************************************
867  *           WINPOS_ShowIconTitle
868  */
869 BOOL WINPOS_ShowIconTitle( HWND hwnd, BOOL bShow )
870 {
871     LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hwnd, atomInternalPos );
872
873     if( lpPos && !(GetWindowLongA( hwnd, GWL_EXSTYLE) & WS_EX_MANAGED))
874     {
875         HWND title = lpPos->hwndIconTitle;
876
877         TRACE("0x%04x %i\n", hwnd, (bShow != 0) );
878
879         if( !title )
880             lpPos->hwndIconTitle = title = ICONTITLE_Create( hwnd );
881         if( bShow )
882         {
883             if (!IsWindowVisible(title))
884             {
885                 SendMessageA( title, WM_SHOWWINDOW, TRUE, 0 );
886                 SetWindowPos( title, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
887                               SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
888             }
889         }
890         else ShowWindow( title, SW_HIDE );
891     }
892     return FALSE;
893 }
894
895 /*******************************************************************
896  *           WINPOS_GetMinMaxInfo
897  *
898  * Get the minimized and maximized information for a window.
899  */
900 void WINPOS_GetMinMaxInfo( HWND hwnd, POINT *maxSize, POINT *maxPos,
901                            POINT *minTrack, POINT *maxTrack )
902 {
903     LPINTERNALPOS lpPos;
904     MINMAXINFO MinMax;
905     INT xinc, yinc;
906     LONG style = GetWindowLongA( hwnd, GWL_STYLE );
907     LONG exstyle = GetWindowLongA( hwnd, GWL_EXSTYLE );
908
909     /* Compute default values */
910
911     MinMax.ptMaxSize.x = GetSystemMetrics(SM_CXSCREEN);
912     MinMax.ptMaxSize.y = GetSystemMetrics(SM_CYSCREEN);
913     MinMax.ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
914     MinMax.ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
915     MinMax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXSCREEN);
916     MinMax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYSCREEN);
917
918     if (HAS_DLGFRAME( style, exstyle ))
919     {
920         xinc = GetSystemMetrics(SM_CXDLGFRAME);
921         yinc = GetSystemMetrics(SM_CYDLGFRAME);
922     }
923     else
924     {
925         xinc = yinc = 0;
926         if (HAS_THICKFRAME(style))
927         {
928             xinc += GetSystemMetrics(SM_CXFRAME);
929             yinc += GetSystemMetrics(SM_CYFRAME);
930         }
931         if (style & WS_BORDER)
932         {
933             xinc += GetSystemMetrics(SM_CXBORDER);
934             yinc += GetSystemMetrics(SM_CYBORDER);
935         }
936     }
937     MinMax.ptMaxSize.x += 2 * xinc;
938     MinMax.ptMaxSize.y += 2 * yinc;
939
940     lpPos = (LPINTERNALPOS)GetPropA( hwnd, atomInternalPos );
941     if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
942         CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
943     else
944     {
945         MinMax.ptMaxPosition.x = -xinc;
946         MinMax.ptMaxPosition.y = -yinc;
947     }
948
949     SendMessageA( hwnd, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
950
951       /* Some sanity checks */
952
953     TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
954                       MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
955                       MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
956                       MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
957                       MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
958     MinMax.ptMaxTrackSize.x = max( MinMax.ptMaxTrackSize.x,
959                                    MinMax.ptMinTrackSize.x );
960     MinMax.ptMaxTrackSize.y = max( MinMax.ptMaxTrackSize.y,
961                                    MinMax.ptMinTrackSize.y );
962
963     if (maxSize) *maxSize = MinMax.ptMaxSize;
964     if (maxPos) *maxPos = MinMax.ptMaxPosition;
965     if (minTrack) *minTrack = MinMax.ptMinTrackSize;
966     if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
967 }
968
969 /***********************************************************************
970  *              ShowWindowAsync (USER32.@)
971  *
972  * doesn't wait; returns immediately.
973  * used by threads to toggle windows in other (possibly hanging) threads
974  */
975 BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd )
976 {
977     /* FIXME: does ShowWindow() return immediately ? */
978     return ShowWindow(hwnd, cmd);
979 }
980
981
982 /***********************************************************************
983  *              ShowWindow (USER32.@)
984  */
985 BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
986 {
987     HWND full_handle;
988
989     if ((full_handle = WIN_IsCurrentThread( hwnd )))
990         return USER_Driver.pShowWindow( full_handle, cmd );
991     return SendMessageW( hwnd, WM_WINE_SHOWWINDOW, cmd, 0 );
992 }
993
994
995 /***********************************************************************
996  *              GetInternalWindowPos (USER.460)
997  */
998 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
999                                       LPPOINT16 ptIcon )
1000 {
1001     WINDOWPLACEMENT16 wndpl;
1002     if (GetWindowPlacement16( hwnd, &wndpl )) 
1003     {
1004         if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1005         if (ptIcon)  *ptIcon = wndpl.ptMinPosition;
1006         return wndpl.showCmd;
1007     }
1008     return 0;
1009 }
1010
1011
1012 /***********************************************************************
1013  *              GetInternalWindowPos (USER32.@)
1014  */
1015 UINT WINAPI GetInternalWindowPos( HWND hwnd, LPRECT rectWnd,
1016                                       LPPOINT ptIcon )
1017 {
1018     WINDOWPLACEMENT wndpl;
1019     if (GetWindowPlacement( hwnd, &wndpl ))
1020     {
1021         if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1022         if (ptIcon)  *ptIcon = wndpl.ptMinPosition;
1023         return wndpl.showCmd;
1024     }
1025     return 0;
1026 }
1027
1028
1029 /***********************************************************************
1030  *              GetWindowPlacement (USER32.@)
1031  *
1032  * Win95:
1033  * Fails if wndpl->length of Win95 (!) apps is invalid.
1034  */
1035 BOOL WINAPI GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *wndpl )
1036 {
1037     WND *pWnd = WIN_FindWndPtr( hwnd );
1038     LPINTERNALPOS lpPos;
1039
1040     if(!pWnd ) return FALSE;
1041
1042     lpPos = WINPOS_InitInternalPos( pWnd, *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1043     wndpl->length  = sizeof(*wndpl);
1044     if( pWnd->dwStyle & WS_MINIMIZE )
1045         wndpl->showCmd = SW_SHOWMINIMIZED;
1046     else
1047         wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE ) ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
1048     if( pWnd->flags & WIN_RESTORE_MAX )
1049         wndpl->flags = WPF_RESTORETOMAXIMIZED;
1050     else
1051         wndpl->flags = 0;
1052     CONV_POINT16TO32( &lpPos->ptIconPos, &wndpl->ptMinPosition );
1053     CONV_POINT16TO32( &lpPos->ptMaxPos, &wndpl->ptMaxPosition );
1054     CONV_RECT16TO32( &lpPos->rectNormal, &wndpl->rcNormalPosition );
1055     WIN_ReleaseWndPtr(pWnd);
1056     return TRUE;
1057 }
1058
1059
1060 /***********************************************************************
1061  *           WINPOS_SetPlacement
1062  */
1063 static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT *wndpl, UINT flags )
1064 {
1065     WND *pWnd = WIN_FindWndPtr( hwnd );
1066     if( pWnd )
1067     {
1068         LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1069                              *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1070
1071         if( flags & PLACE_MIN ) CONV_POINT32TO16( &wndpl->ptMinPosition, &lpPos->ptIconPos );
1072         if( flags & PLACE_MAX ) CONV_POINT32TO16( &wndpl->ptMaxPosition, &lpPos->ptMaxPos );
1073         if( flags & PLACE_RECT) CONV_RECT32TO16( &wndpl->rcNormalPosition, &lpPos->rectNormal );
1074
1075         if( pWnd->dwStyle & WS_MINIMIZE )
1076         {
1077             WINPOS_ShowIconTitle( pWnd->hwndSelf, FALSE );
1078             if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1079                 SetWindowPos( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1080                                 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1081         } 
1082         else if( pWnd->dwStyle & WS_MAXIMIZE )
1083         {
1084             if( !EMPTYPOINT(lpPos->ptMaxPos) )
1085                 SetWindowPos( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1086                                 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1087         }
1088         else if( flags & PLACE_RECT )
1089                 SetWindowPos( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1090                                 lpPos->rectNormal.right - lpPos->rectNormal.left,
1091                                 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1092                                 SWP_NOZORDER | SWP_NOACTIVATE );
1093
1094         ShowWindow( hwnd, wndpl->showCmd );
1095         if( IsWindow(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1096         {
1097             if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd->hwndSelf, TRUE );
1098
1099             /* SDK: ...valid only the next time... */
1100             if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1101         }
1102         WIN_ReleaseWndPtr(pWnd);
1103         return TRUE;
1104     }
1105     return FALSE;
1106 }
1107
1108
1109 /***********************************************************************
1110  *              SetWindowPlacement (USER32.@)
1111  *
1112  * Win95:
1113  * Fails if wndpl->length of Win95 (!) apps is invalid.
1114  */
1115 BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *wpl )
1116 {
1117     if (!wpl) return FALSE;
1118     return WINPOS_SetPlacement( hwnd, wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1119 }
1120
1121
1122 /***********************************************************************
1123  *              AnimateWindow (USER32.@)
1124  *              Shows/Hides a window with an animation
1125  *              NO ANIMATION YET
1126  */
1127 BOOL WINAPI AnimateWindow(HWND hwnd, DWORD dwTime, DWORD dwFlags)
1128 {
1129         FIXME("partial stub\n");
1130
1131         /* If trying to show/hide and it's already   *
1132          * shown/hidden or invalid window, fail with *
1133          * invalid parameter                         */
1134         if(!IsWindow(hwnd) ||
1135            (IsWindowVisible(hwnd) && !(dwFlags & AW_HIDE)) ||
1136            (!IsWindowVisible(hwnd) && (dwFlags & AW_HIDE)))
1137         {
1138                 SetLastError(ERROR_INVALID_PARAMETER);
1139                 return FALSE;
1140         }
1141
1142         ShowWindow(hwnd, (dwFlags & AW_HIDE) ? SW_HIDE : ((dwFlags & AW_ACTIVATE) ? SW_SHOW : SW_SHOWNA));
1143
1144         return TRUE;
1145 }
1146
1147 /***********************************************************************
1148  *              SetInternalWindowPos (USER32.@)
1149  */
1150 void WINAPI SetInternalWindowPos( HWND hwnd, UINT showCmd,
1151                                     LPRECT rect, LPPOINT pt )
1152 {
1153     if( IsWindow(hwnd) )
1154     {
1155         WINDOWPLACEMENT wndpl;
1156         UINT flags;
1157
1158         wndpl.length  = sizeof(wndpl);
1159         wndpl.showCmd = showCmd;
1160         wndpl.flags = flags = 0;
1161
1162         if( pt )
1163         {
1164             flags |= PLACE_MIN;
1165             wndpl.flags |= WPF_SETMINPOSITION;
1166             wndpl.ptMinPosition = *pt;
1167         }
1168         if( rect )
1169         {
1170             flags |= PLACE_RECT;
1171             wndpl.rcNormalPosition = *rect;
1172         }
1173         WINPOS_SetPlacement( hwnd, &wndpl, flags );
1174     }
1175 }
1176
1177 /*******************************************************************
1178  *         WINPOS_SetActiveWindow
1179  *
1180  * SetActiveWindow() back-end. This is the only function that
1181  * can assign active status to a window. It must be called only
1182  * for the top level windows.
1183  */
1184 BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
1185 {
1186     WND*     wndPtr=0, *wndTemp;
1187     HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1188     MESSAGEQUEUE *pOldActiveQueue = 0, *pNewActiveQueue = 0;
1189     WORD     wIconized = 0;
1190     HWND     hwndActive = 0;
1191     BOOL     bRet = 0;
1192
1193     TRACE("(%04x, %d, %d)\n", hWnd, fMouse, fChangeFocus );
1194
1195     /* Get current active window from the active queue */
1196     if ( hActiveQueue )
1197     {
1198         pOldActiveQueue = QUEUE_Lock( hActiveQueue );
1199         if ( pOldActiveQueue )
1200             hwndActive = PERQDATA_GetActiveWnd( pOldActiveQueue->pQData );
1201     }
1202
1203     if ((wndPtr = WIN_FindWndPtr(hWnd)))
1204         hWnd = wndPtr->hwndSelf;  /* make it a full handle */
1205
1206     /* paranoid checks */
1207     if( hWnd == GetDesktopWindow() || (bRet = (hWnd == hwndActive)) )
1208         goto CLEANUP_END;
1209
1210 /*  if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1211  *      return 0;
1212  */
1213     hOldActiveQueue = hActiveQueue;
1214
1215     if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1216     {
1217         wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1218         WIN_ReleaseWndPtr(wndTemp);
1219     }
1220     else
1221         TRACE("no current active window.\n");
1222
1223     /* call CBT hook chain */
1224     if (HOOK_IsHooked( WH_CBT ))
1225     {
1226         CBTACTIVATESTRUCT cbt;
1227         cbt.fMouse     = fMouse;
1228         cbt.hWndActive = hwndActive;
1229         if (HOOK_CallHooksA( WH_CBT, HCBT_ACTIVATE, (WPARAM)hWnd, (LPARAM)&cbt )) goto CLEANUP_END;
1230     }
1231
1232     /* set prev active wnd to current active wnd and send notification */
1233     if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
1234     {
1235         MESSAGEQUEUE *pTempActiveQueue = 0;
1236         
1237         if (!SendMessageA( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1238         {
1239             if (GetSysModalWindow16() != WIN_Handle16(hWnd)) goto CLEANUP_END;
1240             /* disregard refusal if hWnd is sysmodal */
1241         }
1242
1243         SendMessageA( hwndPrevActive, WM_ACTIVATE,
1244                         MAKEWPARAM( WA_INACTIVE, wIconized ),
1245                         (LPARAM)hWnd );
1246
1247         /* check if something happened during message processing
1248          * (global active queue may have changed)
1249          */
1250         pTempActiveQueue = QUEUE_Lock( hActiveQueue );
1251         if(!pTempActiveQueue)
1252             goto CLEANUP_END;
1253
1254         hwndActive = PERQDATA_GetActiveWnd( pTempActiveQueue->pQData );
1255         QUEUE_Unlock( pTempActiveQueue );
1256         if( hwndPrevActive != hwndActive )
1257             goto CLEANUP_END;
1258     }
1259
1260     /* Set new active window in the message queue */
1261     hwndActive = hWnd;
1262     if ( wndPtr )
1263     {
1264         pNewActiveQueue = QUEUE_Lock( wndPtr->hmemTaskQ );
1265         if ( pNewActiveQueue )
1266             PERQDATA_SetActiveWnd( pNewActiveQueue->pQData, hwndActive );
1267     }
1268     else /* have to do this or MDI frame activation goes to hell */
1269         if( pOldActiveQueue )
1270             PERQDATA_SetActiveWnd( pOldActiveQueue->pQData, 0 );
1271
1272     /* send palette messages */
1273     if (hWnd && SendMessageW( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1274         SendMessageW( HWND_BROADCAST, WM_PALETTEISCHANGING, (WPARAM)hWnd, 0 );
1275
1276     /* if prev wnd is minimized redraw icon title */
1277     if( IsIconic( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1278
1279     /* managed windows will get ConfigureNotify event */  
1280     if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_MANAGED))
1281     {
1282         /* check Z-order and bring hWnd to the top */
1283         HWND tmp = GetTopWindow(0);
1284         while (tmp && !(GetWindowLongA( tmp, GWL_STYLE ) & WS_VISIBLE))
1285             tmp = GetWindow( tmp, GW_HWNDNEXT );
1286
1287         if( tmp != hWnd )
1288             SetWindowPos(hWnd, HWND_TOP, 0,0,0,0, 
1289                            SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1290         if (!IsWindow(hWnd))  
1291             goto CLEANUP;
1292     }
1293
1294     /* Get a handle to the new active queue */
1295     hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1296
1297     /* send WM_ACTIVATEAPP if necessary */
1298     if (hOldActiveQueue != hNewActiveQueue)
1299     {
1300         HWND *list, *phwnd;
1301         DWORD old_thread = GetWindowThreadProcessId( hwndPrevActive, NULL );
1302         DWORD new_thread = GetWindowThreadProcessId( hwndActive, NULL );
1303
1304         if ((list = WIN_ListChildren( GetDesktopWindow() )))
1305         {
1306             for (phwnd = list; *phwnd; phwnd++)
1307             {
1308                 if (!IsWindow( *phwnd )) continue;
1309                 if (GetWindowThreadProcessId( *phwnd, NULL ) == old_thread)
1310                     SendMessageW( *phwnd, WM_ACTIVATEAPP, 0, new_thread );
1311             }
1312             HeapFree( GetProcessHeap(), 0, list );
1313         }
1314
1315         hActiveQueue = hNewActiveQueue;
1316
1317         if ((list = WIN_ListChildren( GetDesktopWindow() )))
1318         {
1319             for (phwnd = list; *phwnd; phwnd++)
1320             {
1321                 if (!IsWindow( *phwnd )) continue;
1322                 if (GetWindowThreadProcessId( *phwnd, NULL ) == new_thread)
1323                     SendMessageW( *phwnd, WM_ACTIVATEAPP, 1, old_thread );
1324             }
1325             HeapFree( GetProcessHeap(), 0, list );
1326         }
1327         
1328         if (hWnd && !IsWindow(hWnd)) goto CLEANUP;
1329     }
1330
1331     if (hWnd)
1332     {
1333         /* walk up to the first unowned window */
1334         HWND tmp = GetAncestor( hWnd, GA_ROOTOWNER );
1335         if ((wndTemp = WIN_FindWndPtr( tmp )))
1336         {
1337             /* and set last active owned popup */
1338             wndTemp->hwndLastActive = hWnd;
1339
1340             wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1341             WIN_ReleaseWndPtr(wndTemp);
1342         }
1343         SendMessageA( hWnd, WM_NCACTIVATE, TRUE, 0 );
1344         SendMessageA( hWnd, WM_ACTIVATE,
1345                  MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1346                  (LPARAM)hwndPrevActive );
1347         if( !IsWindow(hWnd) ) goto CLEANUP;
1348     }
1349
1350     /* change focus if possible */
1351     if ( fChangeFocus )
1352     {
1353         if ( pNewActiveQueue )
1354         {
1355             HWND hOldFocus = PERQDATA_GetFocusWnd( pNewActiveQueue->pQData );
1356
1357             if ( !hOldFocus || GetAncestor( hOldFocus, GA_ROOT ) != hwndActive )
1358                 FOCUS_SwitchFocus( pNewActiveQueue, hOldFocus, 
1359                                    (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
1360                                    0 : hwndActive );
1361         }
1362
1363         if ( pOldActiveQueue && 
1364              ( !pNewActiveQueue || 
1365                 pNewActiveQueue->pQData != pOldActiveQueue->pQData ) )
1366         {
1367             HWND hOldFocus = PERQDATA_GetFocusWnd( pOldActiveQueue->pQData );
1368             if ( hOldFocus )
1369                 FOCUS_SwitchFocus( pOldActiveQueue, hOldFocus, 0 );
1370         }
1371     }
1372
1373     if( !hwndPrevActive && wndPtr )
1374     {
1375         if (USER_Driver.pForceWindowRaise) USER_Driver.pForceWindowRaise( wndPtr->hwndSelf );
1376     }
1377
1378     /* if active wnd is minimized redraw icon title */
1379     if( IsIconic(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1380
1381     bRet = (hWnd == hwndActive);  /* Success? */
1382     
1383 CLEANUP: /* Unlock the message queues before returning */
1384
1385     if ( pNewActiveQueue )
1386         QUEUE_Unlock( pNewActiveQueue );
1387
1388 CLEANUP_END:
1389
1390     if ( pOldActiveQueue )
1391         QUEUE_Unlock( pOldActiveQueue );
1392
1393     WIN_ReleaseWndPtr(wndPtr);
1394     return bRet;
1395 }
1396
1397 /*******************************************************************
1398  *         WINPOS_ActivateOtherWindow
1399  *
1400  *  Activates window other than pWnd.
1401  */
1402 void WINPOS_ActivateOtherWindow(HWND hwnd)
1403 {
1404     HWND hwndActive = 0;
1405     HWND hwndTo = 0;
1406     HWND hwndDefaultTo = 0;
1407     HWND owner;
1408
1409     /* Get current active window from the active queue */
1410     if ( hActiveQueue )
1411     {
1412         MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1413         if ( pActiveQueue )
1414         {
1415             hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1416             QUEUE_Unlock( pActiveQueue );
1417         }
1418     }
1419
1420     if (!(hwnd = WIN_IsCurrentThread( hwnd ))) return;
1421
1422     if( hwnd == hwndPrevActive )
1423         hwndPrevActive = 0;
1424
1425     if( hwndActive != hwnd && (hwndActive || USER_IsExitingThread( GetCurrentThreadId() )))
1426         return;
1427
1428     if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_POPUP) ||
1429         !(owner = GetWindow( hwnd, GW_OWNER )) ||
1430         !WINPOS_CanActivate((hwndTo = GetAncestor( owner, GA_ROOT ))) ||
1431         !WINPOS_IsVisible(hwndTo))
1432     {
1433         HWND tmp = GetAncestor( hwnd, GA_ROOT );
1434         hwndTo = hwndPrevActive;
1435
1436         while( !WINPOS_CanActivate(hwndTo) || !WINPOS_IsVisible(hwndTo))
1437         {
1438             /* by now owned windows should've been taken care of */
1439             if(!hwndDefaultTo && WINPOS_CanActivate(hwndTo))
1440                 hwndDefaultTo = hwndTo;
1441             tmp = hwndTo = GetWindow( tmp, GW_HWNDNEXT );
1442             if( !hwndTo )
1443             {
1444                 hwndTo = hwndDefaultTo;
1445                 break;
1446             }
1447         }
1448     }
1449
1450     SetActiveWindow( hwndTo );
1451     hwndPrevActive = 0;
1452 }
1453
1454
1455 /***********************************************************************
1456  *           WINPOS_HandleWindowPosChanging16
1457  *
1458  * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
1459  */
1460 LONG WINPOS_HandleWindowPosChanging16( HWND hwnd, WINDOWPOS16 *winpos )
1461 {
1462     POINT maxSize, minTrack;
1463     LONG style = GetWindowLongA( hwnd, GWL_STYLE );
1464
1465     if (winpos->flags & SWP_NOSIZE) return 0;
1466     if ((style & WS_THICKFRAME) || ((style & (WS_POPUP | WS_CHILD)) == 0))
1467     {
1468         WINPOS_GetMinMaxInfo( hwnd, &maxSize, NULL, &minTrack, NULL );
1469         if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
1470         if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
1471         if (!(style & WS_MINIMIZE))
1472         {
1473             if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
1474             if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
1475         }
1476     }
1477     return 0;
1478 }
1479
1480
1481 /***********************************************************************
1482  *           WINPOS_HandleWindowPosChanging
1483  *
1484  * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
1485  */
1486 LONG WINPOS_HandleWindowPosChanging( HWND hwnd, WINDOWPOS *winpos )
1487 {
1488     POINT maxSize, minTrack;
1489     LONG style = GetWindowLongA( hwnd, GWL_STYLE );
1490
1491     if (winpos->flags & SWP_NOSIZE) return 0;
1492     if ((style & WS_THICKFRAME) || ((style & (WS_POPUP | WS_CHILD)) == 0))
1493     {
1494         WINPOS_GetMinMaxInfo( hwnd, &maxSize, NULL, &minTrack, NULL );
1495         winpos->cx = min( winpos->cx, maxSize.x );
1496         winpos->cy = min( winpos->cy, maxSize.y );
1497         if (!(style & WS_MINIMIZE))
1498         {
1499             if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
1500             if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
1501         }
1502     }
1503     return 0;
1504 }
1505
1506
1507 /***********************************************************************
1508  *              SetWindowPos (USER32.@)
1509  */
1510 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
1511                           INT x, INT y, INT cx, INT cy, UINT flags )
1512 {
1513     WINDOWPOS winpos;
1514
1515     winpos.hwnd = hwnd;
1516     winpos.hwndInsertAfter = hwndInsertAfter;
1517     winpos.x = x;
1518     winpos.y = y;
1519     winpos.cx = cx;
1520     winpos.cy = cy;
1521     winpos.flags = flags;
1522     if (WIN_IsCurrentThread( hwnd )) return USER_Driver.pSetWindowPos( &winpos );
1523     return SendMessageW( winpos.hwnd, WM_WINE_SETWINDOWPOS, 0, (LPARAM)&winpos );
1524 }
1525
1526
1527 /***********************************************************************
1528  *              BeginDeferWindowPos (USER32.@)
1529  */
1530 HDWP WINAPI BeginDeferWindowPos( INT count )
1531 {
1532     HDWP handle;
1533     DWP *pDWP;
1534
1535     if (count < 0) 
1536     {
1537         SetLastError(ERROR_INVALID_PARAMETER);
1538         return 0;
1539     }
1540     /* Windows allows zero count, in which case it allocates context for 8 moves */
1541     if (count == 0) count = 8;
1542
1543     handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
1544     if (!handle) return 0;
1545     pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
1546     pDWP->actualCount    = 0;
1547     pDWP->suggestedCount = count;
1548     pDWP->valid          = TRUE;
1549     pDWP->wMagic         = DWP_MAGIC;
1550     pDWP->hwndParent     = 0;
1551     return handle;
1552 }
1553
1554
1555 /***********************************************************************
1556  *              DeferWindowPos (USER32.@)
1557  */
1558 HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter,
1559                                 INT x, INT y, INT cx, INT cy,
1560                                 UINT flags )
1561 {
1562     DWP *pDWP;
1563     int i;
1564     HDWP newhdwp = hdwp,retvalue;
1565
1566     hwnd = WIN_GetFullHandle( hwnd );
1567     if (hwnd == GetDesktopWindow()) return 0;
1568
1569     if (!(pDWP = USER_HEAP_LIN_ADDR( hdwp ))) return 0;
1570
1571     USER_Lock();
1572
1573     for (i = 0; i < pDWP->actualCount; i++)
1574     {
1575         if (pDWP->winPos[i].hwnd == hwnd)
1576         {
1577               /* Merge with the other changes */
1578             if (!(flags & SWP_NOZORDER))
1579             {
1580                 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
1581             }
1582             if (!(flags & SWP_NOMOVE))
1583             {
1584                 pDWP->winPos[i].x = x;
1585                 pDWP->winPos[i].y = y;
1586             }
1587             if (!(flags & SWP_NOSIZE))
1588             {
1589                 pDWP->winPos[i].cx = cx;
1590                 pDWP->winPos[i].cy = cy;
1591             }
1592             pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
1593                                                SWP_NOZORDER | SWP_NOREDRAW |
1594                                                SWP_NOACTIVATE | SWP_NOCOPYBITS|
1595                                                SWP_NOOWNERZORDER);
1596             pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
1597                                               SWP_FRAMECHANGED);
1598             retvalue = hdwp;
1599             goto END;
1600         }
1601     }
1602     if (pDWP->actualCount >= pDWP->suggestedCount)
1603     {
1604         newhdwp = USER_HEAP_REALLOC( hdwp,
1605                       sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
1606         if (!newhdwp)
1607         {
1608             retvalue = 0;
1609             goto END;
1610         }
1611         pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
1612         pDWP->suggestedCount++;
1613     }
1614     pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
1615     pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
1616     pDWP->winPos[pDWP->actualCount].x = x;
1617     pDWP->winPos[pDWP->actualCount].y = y;
1618     pDWP->winPos[pDWP->actualCount].cx = cx;
1619     pDWP->winPos[pDWP->actualCount].cy = cy;
1620     pDWP->winPos[pDWP->actualCount].flags = flags;
1621     pDWP->actualCount++;
1622     retvalue = newhdwp;
1623 END:
1624     USER_Unlock();
1625     return retvalue;
1626 }
1627
1628
1629 /***********************************************************************
1630  *              EndDeferWindowPos (USER32.@)
1631  */
1632 BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
1633 {
1634     DWP *pDWP;
1635     WINDOWPOS *winpos;
1636     BOOL res = TRUE;
1637     int i;
1638
1639     pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
1640     if (!pDWP) return FALSE;
1641     for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
1642     {
1643         if (!(res = USER_Driver.pSetWindowPos( winpos ))) break;
1644     }
1645     USER_HEAP_FREE( hdwp );
1646     return res;
1647 }
1648
1649
1650 /***********************************************************************
1651  *              TileChildWindows (USER.199)
1652  */
1653 void WINAPI TileChildWindows16( HWND16 parent, WORD action )
1654 {
1655     FIXME("(%04x, %d): stub\n", parent, action);
1656 }
1657
1658 /***********************************************************************
1659  *              CascadeChildWindows (USER.198)
1660  */
1661 void WINAPI CascadeChildWindows16( HWND16 parent, WORD action )
1662 {
1663     FIXME("(%04x, %d): stub\n", parent, action);
1664 }
1665
1666 /***********************************************************************
1667  *              SetProgmanWindow (USER32.@)
1668  */
1669 HWND WINAPI SetProgmanWindow ( HWND hwnd )
1670 {
1671         hGlobalProgmanWindow = hwnd;
1672         return hGlobalProgmanWindow;
1673 }
1674
1675 /***********************************************************************
1676  *              GetProgmanWindow (USER32.@)
1677  */
1678 HWND WINAPI GetProgmanWindow(void)
1679 {
1680         return hGlobalProgmanWindow;
1681 }
1682
1683 /***********************************************************************
1684  *              SetShellWindowEx (USER32.@)
1685  * hwndProgman =  Progman[Program Manager]
1686  *                |-> SHELLDLL_DefView
1687  * hwndListView = |   |-> SysListView32
1688  *                |   |   |-> tooltips_class32
1689  *                |   |
1690  *                |   |-> SysHeader32
1691  *                |   
1692  *                |-> ProxyTarget
1693  */
1694 HWND WINAPI SetShellWindowEx ( HWND hwndProgman, HWND hwndListView )
1695 {
1696         FIXME("0x%08x 0x%08x stub\n",hwndProgman ,hwndListView );
1697         hGlobalShellWindow = hwndProgman;
1698         return hGlobalShellWindow;
1699
1700 }
1701
1702 /***********************************************************************
1703  *              SetTaskmanWindow (USER32.@)
1704  * NOTES
1705  *   hwnd = MSTaskSwWClass 
1706  *          |-> SysTabControl32
1707  */
1708 HWND WINAPI SetTaskmanWindow ( HWND hwnd )
1709 {
1710         hGlobalTaskmanWindow = hwnd;
1711         return hGlobalTaskmanWindow;
1712 }
1713
1714 /***********************************************************************
1715  *              GetTaskmanWindow (USER32.@)
1716  */
1717 HWND WINAPI GetTaskmanWindow(void)
1718 {
1719         return hGlobalTaskmanWindow;
1720 }