Fixed Filesystem documentation.
[wine] / windows / winpos.c
1 /*
2  * Window position related functions.
3  *
4  * Copyright 1993, 1994, 1995 Alexandre Julliard
5  *                       1995, 1996 Alex Korobka
6  */
7
8 #include "x11drv.h"
9
10 #include <string.h>
11 #include "sysmetrics.h"
12 #include "heap.h"
13 #include "module.h"
14 #include "user.h"
15 #include "win.h"
16 #include "hook.h"
17 #include "message.h"
18 #include "queue.h"
19 #include "options.h"
20 #include "task.h"
21 #include "winpos.h"
22 #include "dce.h"
23 #include "nonclient.h"
24 #include "debug.h"
25 #include "local.h"
26 #include "ldt.h"
27
28 #define HAS_DLGFRAME(style,exStyle) \
29     (((exStyle) & WS_EX_DLGMODALFRAME) || \
30      (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
31
32 #define HAS_THICKFRAME(style) \
33     (((style) & WS_THICKFRAME) && \
34      !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
35
36 #define  SWP_AGG_NOGEOMETRYCHANGE \
37     (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
38 #define  SWP_AGG_NOPOSCHANGE \
39     (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
40 #define  SWP_AGG_STATUSFLAGS \
41     (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
42
43 #define EMPTYPOINT(pt)          ((*(LONG*)&(pt)) == -1)
44
45 #define PLACE_MIN               0x0001
46 #define PLACE_MAX               0x0002
47 #define PLACE_RECT              0x0004
48
49 #define SMC_NOCOPY              0x0001
50 #define SMC_NOPARENTERASE       0x0002
51 #define SMC_DRAWFRAME           0x0004
52 #define SMC_SETXPOS             0x0008
53
54 /* ----- internal variables ----- */
55
56 static HWND hwndPrevActive  = 0;  /* Previously active window */
57 static HWND hGlobalShellWindow=0; /*the shell*/
58
59 static LPCSTR atomInternalPos;
60
61 extern HQUEUE16 hActiveQueue;
62
63 /***********************************************************************
64  *           WINPOS_CreateInternalPosAtom
65  */
66 BOOL WINPOS_CreateInternalPosAtom()
67 {
68     LPSTR str = "SysIP";
69     atomInternalPos = (LPCSTR)(DWORD)GlobalAddAtomA(str);
70     return (atomInternalPos) ? TRUE : FALSE;
71 }
72
73 /***********************************************************************
74  *           WINPOS_CheckInternalPos
75  *
76  * Called when a window is destroyed.
77  */
78 void WINPOS_CheckInternalPos( WND* wndPtr )
79 {
80     LPINTERNALPOS lpPos;
81     MESSAGEQUEUE *pMsgQ = 0;
82     HWND hwnd = wndPtr->hwndSelf;
83
84     lpPos = (LPINTERNALPOS) GetPropA( hwnd, atomInternalPos );
85
86     /* Retrieve the message queue associated with this window */
87     pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
88     if ( !pMsgQ )
89     {
90         WARN( win, "\tMessage queue not found. Exiting!\n" );
91         return;
92     }
93
94     if( hwnd == hwndPrevActive ) hwndPrevActive = 0;
95
96     if( hwnd == PERQDATA_GetActiveWnd( pMsgQ->pQData ) )
97     {
98         PERQDATA_SetActiveWnd( pMsgQ->pQData, 0 );
99         WARN(win, "\tattempt to activate destroyed window!\n");
100     }
101
102     if( lpPos )
103     {
104         if( IsWindow(lpPos->hwndIconTitle) ) 
105             DestroyWindow( lpPos->hwndIconTitle );
106         HeapFree( SystemHeap, 0, lpPos );
107     }
108
109     QUEUE_Unlock( pMsgQ );
110     return;
111 }
112
113 /***********************************************************************
114  *           WINPOS_FindIconPos
115  *
116  * Find a suitable place for an iconic window.
117  */
118 static POINT16 WINPOS_FindIconPos( WND* wndPtr, POINT16 pt )
119 {
120     RECT16 rectParent;
121     short x, y, xspacing, yspacing;
122
123     GetClientRect16( wndPtr->parent->hwndSelf, &rectParent );
124     if ((pt.x >= rectParent.left) && (pt.x + SYSMETRICS_CXICON < rectParent.right) &&
125         (pt.y >= rectParent.top) && (pt.y + SYSMETRICS_CYICON < rectParent.bottom))
126         return pt;  /* The icon already has a suitable position */
127
128     xspacing = SYSMETRICS_CXICONSPACING;
129     yspacing = SYSMETRICS_CYICONSPACING;
130
131     y = rectParent.bottom;
132     for (;;)
133     {
134         for (x = rectParent.left; x <= rectParent.right-xspacing; x += xspacing)
135         {
136               /* Check if another icon already occupies this spot */
137             WND *childPtr = wndPtr->parent->child;
138             while (childPtr)
139             {
140                 if ((childPtr->dwStyle & WS_MINIMIZE) && (childPtr != wndPtr))
141                 {
142                     if ((childPtr->rectWindow.left < x + xspacing) &&
143                         (childPtr->rectWindow.right >= x) &&
144                         (childPtr->rectWindow.top <= y) &&
145                         (childPtr->rectWindow.bottom > y - yspacing))
146                         break;  /* There's a window in there */
147                 }
148                 childPtr = childPtr->next;
149             }
150             if (!childPtr) /* No window was found, so it's OK for us */
151             {
152                 pt.x = x + (xspacing - SYSMETRICS_CXICON) / 2;
153                 pt.y = y - (yspacing + SYSMETRICS_CYICON) / 2;
154                 return pt;
155             }
156         }
157         y -= yspacing;
158     }
159 }
160
161
162 /***********************************************************************
163  *           ArrangeIconicWindows16   (USER.170)
164  */
165 UINT16 WINAPI ArrangeIconicWindows16( HWND16 parent) 
166 {
167     return ArrangeIconicWindows(parent);
168 }
169 /***********************************************************************
170  *           ArrangeIconicWindows32   (USER32.7)
171  */
172 UINT WINAPI ArrangeIconicWindows( HWND parent )
173 {
174     RECT rectParent;
175     HWND hwndChild;
176     INT x, y, xspacing, yspacing;
177
178     GetClientRect( parent, &rectParent );
179     x = rectParent.left;
180     y = rectParent.bottom;
181     xspacing = SYSMETRICS_CXICONSPACING;
182     yspacing = SYSMETRICS_CYICONSPACING;
183
184     hwndChild = GetWindow( parent, GW_CHILD );
185     while (hwndChild)
186     {
187         if( IsIconic( hwndChild ) )
188         {
189             WINPOS_ShowIconTitle( WIN_FindWndPtr(hwndChild), FALSE );
190             SetWindowPos( hwndChild, 0, x + (xspacing - SYSMETRICS_CXICON) / 2,
191                             y - yspacing - SYSMETRICS_CYICON/2, 0, 0,
192                             SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
193             if( IsWindow(hwndChild) )
194                 WINPOS_ShowIconTitle( WIN_FindWndPtr(hwndChild), TRUE );
195             if (x <= rectParent.right - xspacing) x += xspacing;
196             else
197             {
198                 x = rectParent.left;
199                 y -= yspacing;
200             }
201         }
202         hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
203     }
204     return yspacing;
205 }
206
207
208 /***********************************************************************
209  *             SwitchToThisWindow16   (USER.172)
210  */
211 void WINAPI SwitchToThisWindow16( HWND16 hwnd, BOOL16 restore )
212 {
213     SwitchToThisWindow( hwnd, restore );
214 }
215
216
217 /***********************************************************************
218  *             SwitchToThisWindow32   (USER32.539)
219  */
220 void WINAPI SwitchToThisWindow( HWND hwnd, BOOL restore )
221 {
222     ShowWindow( hwnd, restore ? SW_RESTORE : SW_SHOWMINIMIZED );
223 }
224
225
226 /***********************************************************************
227  *           GetWindowRect16   (USER.32)
228  */
229 void WINAPI GetWindowRect16( HWND16 hwnd, LPRECT16 rect ) 
230 {
231     WND * wndPtr = WIN_FindWndPtr( hwnd ); 
232     if (!wndPtr) return;
233     
234     CONV_RECT32TO16( &wndPtr->rectWindow, rect );
235     if (wndPtr->dwStyle & WS_CHILD)
236         MapWindowPoints16( wndPtr->parent->hwndSelf, 0, (POINT16 *)rect, 2 );
237 }
238
239
240 /***********************************************************************
241  *           GetWindowRect32   (USER32.308)
242  */
243 BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect ) 
244 {
245     WND * wndPtr = WIN_FindWndPtr( hwnd ); 
246     if (!wndPtr) return FALSE;
247     
248     *rect = wndPtr->rectWindow;
249     if (wndPtr->dwStyle & WS_CHILD)
250         MapWindowPoints( wndPtr->parent->hwndSelf, 0, (POINT *)rect, 2 );
251     return TRUE;
252 }
253
254
255 /***********************************************************************
256  *           GetWindowRgn32 
257  */
258 BOOL WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
259
260 {
261   RECT    rect;
262   WND * wndPtr = WIN_FindWndPtr( hwnd ); 
263   if (!wndPtr) return (ERROR);
264
265   FIXME (win, "GetWindowRgn32: doesn't really do regions\n"); 
266   
267   memset (&rect, 0, sizeof(rect));
268
269   GetWindowRect ( hwnd, &rect );
270
271   FIXME (win, "Check whether a valid region here\n");
272
273   SetRectRgn ( hrgn, rect.left, rect.top, rect.right, rect.bottom );
274
275   return (SIMPLEREGION);
276 }
277
278 /***********************************************************************
279  *           SetWindowRgn32 
280  */
281 INT WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn,BOOL bRedraw)
282
283 {
284
285   FIXME (win, "SetWindowRgn32: stub\n"); 
286   return TRUE;
287 }
288
289 /***********************************************************************
290  *           SetWindowRgn16 
291  */
292 INT16 WINAPI SetWindowRgn16( HWND16 hwnd, HRGN16 hrgn,BOOL16 bRedraw)
293
294 {
295
296   FIXME (win, "SetWindowRgn16: stub\n"); 
297   return TRUE;
298 }
299
300
301 /***********************************************************************
302  *           GetClientRect16   (USER.33)
303  */
304 void WINAPI GetClientRect16( HWND16 hwnd, LPRECT16 rect ) 
305 {
306     WND * wndPtr = WIN_FindWndPtr( hwnd );
307
308     rect->left = rect->top = rect->right = rect->bottom = 0;
309     if (wndPtr) 
310     {
311         rect->right  = wndPtr->rectClient.right - wndPtr->rectClient.left;
312         rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
313     }
314 }
315
316
317 /***********************************************************************
318  *           GetClientRect32   (USER32.220)
319  */
320 BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect ) 
321 {
322     WND * wndPtr = WIN_FindWndPtr( hwnd );
323
324     rect->left = rect->top = rect->right = rect->bottom = 0;
325     if (!wndPtr) return FALSE;
326     rect->right  = wndPtr->rectClient.right - wndPtr->rectClient.left;
327     rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
328     return TRUE;
329 }
330
331
332 /*******************************************************************
333  *         ClientToScreen16   (USER.28)
334  */
335 void WINAPI ClientToScreen16( HWND16 hwnd, LPPOINT16 lppnt )
336 {
337     MapWindowPoints16( hwnd, 0, lppnt, 1 );
338 }
339
340
341 /*******************************************************************
342  *         ClientToScreen32   (USER32.52)
343  */
344 BOOL WINAPI ClientToScreen( HWND hwnd, LPPOINT lppnt )
345 {
346     MapWindowPoints( hwnd, 0, lppnt, 1 );
347     return TRUE;
348 }
349
350
351 /*******************************************************************
352  *         ScreenToClient16   (USER.29)
353  */
354 void WINAPI ScreenToClient16( HWND16 hwnd, LPPOINT16 lppnt )
355 {
356     MapWindowPoints16( 0, hwnd, lppnt, 1 );
357 }
358
359
360 /*******************************************************************
361  *         ScreenToClient32   (USER32.447)
362  */
363 BOOL WINAPI ScreenToClient( HWND hwnd, LPPOINT lppnt )
364 {
365     MapWindowPoints( 0, hwnd, lppnt, 1 );
366     return TRUE;
367 }
368
369
370 /***********************************************************************
371  *           WINPOS_WindowFromPoint
372  *
373  * Find the window and hittest for a given point.
374  */
375 INT16 WINPOS_WindowFromPoint( WND* wndScope, POINT16 pt, WND **ppWnd )
376 {
377     WND *wndPtr;
378     INT16 hittest = HTERROR;
379     POINT16 xy = pt;
380
381    *ppWnd = NULL;
382     wndPtr = wndScope->child;
383     if( wndScope->flags & WIN_MANAGED )
384     {
385         /* this prevents mouse clicks from going "through" scrollbars in managed mode */
386         if( pt.x < wndScope->rectClient.left || pt.x >= wndScope->rectClient.right ||
387             pt.y < wndScope->rectClient.top || pt.y >= wndScope->rectClient.bottom )
388             goto hittest;
389     }
390     MapWindowPoints16( GetDesktopWindow16(), wndScope->hwndSelf, &xy, 1 );
391
392     for (;;)
393     {
394         while (wndPtr)
395         {
396             /* If point is in window, and window is visible, and it  */
397             /* is enabled (or it's a top-level window), then explore */
398             /* its children. Otherwise, go to the next window.       */
399
400             if ((wndPtr->dwStyle & WS_VISIBLE) &&
401                 (!(wndPtr->dwStyle & WS_DISABLED) ||
402                  ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)) &&
403                 (xy.x >= wndPtr->rectWindow.left) &&
404                 (xy.x < wndPtr->rectWindow.right) &&
405                 (xy.y >= wndPtr->rectWindow.top) &&
406                 (xy.y < wndPtr->rectWindow.bottom))
407             {
408                 *ppWnd = wndPtr;  /* Got a suitable window */
409
410                 /* If window is minimized or disabled, return at once */
411                 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
412                 if (wndPtr->dwStyle & WS_DISABLED) return HTERROR;
413
414                 /* If point is not in client area, ignore the children */
415                 if ((xy.x < wndPtr->rectClient.left) ||
416                     (xy.x >= wndPtr->rectClient.right) ||
417                     (xy.y < wndPtr->rectClient.top) ||
418                     (xy.y >= wndPtr->rectClient.bottom)) break;
419
420                 xy.x -= wndPtr->rectClient.left;
421                 xy.y -= wndPtr->rectClient.top;
422                 wndPtr = wndPtr->child;
423             }
424             else wndPtr = wndPtr->next;
425         }
426
427 hittest:
428         /* If nothing found, try the scope window */
429         if (!*ppWnd) *ppWnd = wndScope;
430
431         /* Send the WM_NCHITTEST message (only if to the same task) */
432         if ((*ppWnd)->hmemTaskQ == GetFastQueue16())
433         {
434             hittest = (INT16)SendMessage16( (*ppWnd)->hwndSelf, WM_NCHITTEST, 
435                                                  0, MAKELONG( pt.x, pt.y ) );
436             if (hittest != HTTRANSPARENT) return hittest;  /* Found the window */
437         }
438         else return HTCLIENT;
439
440         /* If no children found in last search, make point relative to parent */
441         if (!wndPtr)
442         {
443             xy.x += (*ppWnd)->rectClient.left;
444             xy.y += (*ppWnd)->rectClient.top;
445         }
446
447         /* Restart the search from the next sibling */
448         wndPtr = (*ppWnd)->next;
449         *ppWnd = (*ppWnd)->parent;
450     }
451 }
452
453
454 /*******************************************************************
455  *         WindowFromPoint16   (USER.30)
456  */
457 HWND16 WINAPI WindowFromPoint16( POINT16 pt )
458 {
459     WND *pWnd;
460     WINPOS_WindowFromPoint( WIN_GetDesktop(), pt, &pWnd );
461     return pWnd->hwndSelf;
462 }
463
464
465 /*******************************************************************
466  *         WindowFromPoint32   (USER32.582)
467  */
468 HWND WINAPI WindowFromPoint( POINT pt )
469 {
470     WND *pWnd;
471     POINT16 pt16;
472     CONV_POINT32TO16( &pt, &pt16 );
473     WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16, &pWnd );
474     return (HWND)pWnd->hwndSelf;
475 }
476
477
478 /*******************************************************************
479  *         ChildWindowFromPoint16   (USER.191)
480  */
481 HWND16 WINAPI ChildWindowFromPoint16( HWND16 hwndParent, POINT16 pt )
482 {
483     POINT pt32;
484     CONV_POINT16TO32( &pt, &pt32 );
485     return (HWND16)ChildWindowFromPoint( hwndParent, pt32 );
486 }
487
488
489 /*******************************************************************
490  *         ChildWindowFromPoint32   (USER32.49)
491  */
492 HWND WINAPI ChildWindowFromPoint( HWND hwndParent, POINT pt )
493 {
494     /* pt is in the client coordinates */
495
496     WND* wnd = WIN_FindWndPtr(hwndParent);
497     RECT rect;
498
499     if( !wnd ) return 0;
500
501     /* get client rect fast */
502     rect.top = rect.left = 0;
503     rect.right = wnd->rectClient.right - wnd->rectClient.left;
504     rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
505
506     if (!PtInRect( &rect, pt )) return 0;
507
508     wnd = wnd->child;
509     while ( wnd )
510     {
511         if (PtInRect( &wnd->rectWindow, pt )) return wnd->hwndSelf;
512         wnd = wnd->next;
513     }
514     return hwndParent;
515 }
516
517 /*******************************************************************
518  *         ChildWindowFromPointEx16   (USER.50)
519  */
520 HWND16 WINAPI ChildWindowFromPointEx16( HWND16 hwndParent, POINT16 pt, UINT16 uFlags)
521 {
522     POINT pt32;
523     CONV_POINT16TO32( &pt, &pt32 );
524     return (HWND16)ChildWindowFromPointEx( hwndParent, pt32, uFlags );
525 }
526
527
528 /*******************************************************************
529  *         ChildWindowFromPointEx32   (USER32.50)
530  */
531 HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt,
532                 UINT uFlags)
533 {
534     /* pt is in the client coordinates */
535
536     WND* wnd = WIN_FindWndPtr(hwndParent);
537     RECT rect;
538
539     if( !wnd ) return 0;
540
541     /* get client rect fast */
542     rect.top = rect.left = 0;
543     rect.right = wnd->rectClient.right - wnd->rectClient.left;
544     rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
545
546     if (!PtInRect( &rect, pt )) return 0;
547
548     wnd = wnd->child;
549     while ( wnd )
550     {
551         if (PtInRect( &wnd->rectWindow, pt )) {
552                 if ( (uFlags & CWP_SKIPINVISIBLE) && 
553                                 !(wnd->dwStyle & WS_VISIBLE) )
554                         wnd = wnd->next;
555                 else if ( (uFlags & CWP_SKIPDISABLED) && 
556                                 (wnd->dwStyle & WS_DISABLED) )
557                         wnd = wnd->next;
558                 else if ( (uFlags & CWP_SKIPTRANSPARENT) && 
559                                 (wnd->dwExStyle & WS_EX_TRANSPARENT) )
560                         wnd = wnd->next;
561                 else
562                         return wnd->hwndSelf;
563         }
564     }
565     return hwndParent;
566 }
567
568
569 /*******************************************************************
570  *         WINPOS_GetWinOffset
571  *
572  * Calculate the offset between the origin of the two windows. Used
573  * to implement MapWindowPoints.
574  */
575 static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo,
576                                  POINT *offset )
577 {
578     WND * wndPtr;
579
580     offset->x = offset->y = 0;
581     if (hwndFrom == hwndTo ) return;
582
583       /* Translate source window origin to screen coords */
584     if (hwndFrom)
585     {
586         if (!(wndPtr = WIN_FindWndPtr( hwndFrom )))
587         {
588             ERR(win,"bad hwndFrom = %04x\n",hwndFrom);
589             return;
590         }
591         while (wndPtr->parent)
592         {
593             offset->x += wndPtr->rectClient.left;
594             offset->y += wndPtr->rectClient.top;
595             wndPtr = wndPtr->parent;
596         }
597     }
598
599       /* Translate origin to destination window coords */
600     if (hwndTo)
601     {
602         if (!(wndPtr = WIN_FindWndPtr( hwndTo )))
603         {
604             ERR(win,"bad hwndTo = %04x\n", hwndTo );
605             return;
606         }
607         while (wndPtr->parent)
608         {
609             offset->x -= wndPtr->rectClient.left;
610             offset->y -= wndPtr->rectClient.top;
611             wndPtr = wndPtr->parent;
612         }    
613     }
614 }
615
616
617 /*******************************************************************
618  *         MapWindowPoints16   (USER.258)
619  */
620 void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
621                                LPPOINT16 lppt, UINT16 count )
622 {
623     POINT offset;
624
625     WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
626     while (count--)
627     {
628         lppt->x += offset.x;
629         lppt->y += offset.y;
630         lppt++;
631     }
632 }
633
634
635 /*******************************************************************
636  *         MapWindowPoints32   (USER32.386)
637  */
638 INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo,
639                                LPPOINT lppt, UINT count )
640 {
641     POINT offset;
642
643     WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
644     while (count--)
645     {
646         lppt->x += offset.x;
647         lppt->y += offset.y;
648         lppt++;
649     }
650     return MAKELONG( LOWORD(offset.x), LOWORD(offset.y) );
651 }
652
653
654 /***********************************************************************
655  *           IsIconic16   (USER.31)
656  */
657 BOOL16 WINAPI IsIconic16(HWND16 hWnd)
658 {
659     return IsIconic(hWnd);
660 }
661
662
663 /***********************************************************************
664  *           IsIconic32   (USER32.345)
665  */
666 BOOL WINAPI IsIconic(HWND hWnd)
667 {
668     WND * wndPtr = WIN_FindWndPtr(hWnd);
669     if (wndPtr == NULL) return FALSE;
670     return (wndPtr->dwStyle & WS_MINIMIZE) != 0;
671 }
672  
673  
674 /***********************************************************************
675  *           IsZoomed   (USER.272)
676  */
677 BOOL16 WINAPI IsZoomed16(HWND16 hWnd)
678 {
679     return IsZoomed(hWnd);
680 }
681
682
683 /***********************************************************************
684  *           IsZoomed   (USER32.352)
685  */
686 BOOL WINAPI IsZoomed(HWND hWnd)
687 {
688     WND * wndPtr = WIN_FindWndPtr(hWnd);
689     if (wndPtr == NULL) return FALSE;
690     return (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
691 }
692
693
694 /*******************************************************************
695  *         GetActiveWindow    (USER.60)
696  */
697 HWND16 WINAPI GetActiveWindow16(void)
698 {
699     return (HWND16)GetActiveWindow();
700 }
701
702 /*******************************************************************
703  *         GetActiveWindow    (USER32.205)
704  */
705 HWND WINAPI GetActiveWindow(void)
706 {
707     MESSAGEQUEUE *pCurMsgQ = 0;
708     HWND hwndActive = 0;
709
710     /* Get the messageQ for the current thread */
711     if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
712 {
713         WARN( win, "\tCurrent message queue not found. Exiting!\n" );
714         return 0;
715     }
716
717     /* Return the current active window from the perQ data of the current message Q */
718     hwndActive = PERQDATA_GetActiveWnd( pCurMsgQ->pQData );
719
720     QUEUE_Unlock( pCurMsgQ );
721     return hwndActive;
722 }
723
724
725 /*******************************************************************
726  *         WINPOS_CanActivate
727  */
728 static BOOL WINPOS_CanActivate(WND* pWnd)
729 {
730     if( pWnd && ((pWnd->dwStyle & (WS_DISABLED | WS_VISIBLE | WS_CHILD)) 
731         == WS_VISIBLE) ) return TRUE;
732     return FALSE;
733 }
734
735
736 /*******************************************************************
737  *         SetActiveWindow16    (USER.59)
738  */
739 HWND16 WINAPI SetActiveWindow16( HWND16 hwnd )
740 {
741     return SetActiveWindow(hwnd);
742 }
743
744
745 /*******************************************************************
746  *         SetActiveWindow32    (USER32.463)
747  */
748 HWND WINAPI SetActiveWindow( HWND hwnd )
749 {
750     HWND prev = 0;
751     WND *wndPtr = WIN_FindWndPtr( hwnd );
752     MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
753
754     if ( !WINPOS_CanActivate(wndPtr) ) return 0;
755
756     /* Get the messageQ for the current thread */
757     if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
758     {
759         WARN( win, "\tCurrent message queue not found. Exiting!\n" );
760         goto CLEANUP;
761     }
762     
763     /* Retrieve the message queue associated with this window */
764     pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
765     if ( !pMsgQ )
766     {
767         WARN( win, "\tWindow message queue not found. Exiting!\n" );
768         goto CLEANUP;
769     }
770
771     /* Make sure that the window is associated with the calling threads
772      * message queue. It must share the same perQ data.
773      */
774     if ( pCurMsgQ->pQData != pMsgQ->pQData )
775         goto CLEANUP;
776     
777     /* Save current active window */
778     prev = PERQDATA_GetActiveWnd( pMsgQ->pQData );
779     
780     WINPOS_SetActiveWindow( hwnd, 0, 0 );
781
782 CLEANUP:
783     /* Unlock the queues before returning */
784     if ( pMsgQ )
785         QUEUE_Unlock( pMsgQ );
786     if ( pCurMsgQ )
787         QUEUE_Unlock( pCurMsgQ );
788     
789     return prev;
790 }
791
792
793 /*******************************************************************
794  *         GetForegroundWindow16    (USER.608)
795  */
796 HWND16 WINAPI GetForegroundWindow16(void)
797 {
798     return (HWND16)GetForegroundWindow();
799 }
800
801
802 /*******************************************************************
803  *         SetForegroundWindow16    (USER.609)
804  */
805 BOOL16 WINAPI SetForegroundWindow16( HWND16 hwnd )
806 {
807     return SetForegroundWindow( hwnd );
808 }
809
810
811 /*******************************************************************
812  *         GetForegroundWindow32    (USER32.241)
813  */
814 HWND WINAPI GetForegroundWindow(void)
815 {
816     return GetActiveWindow();
817 }
818
819
820 /*******************************************************************
821  *         SetForegroundWindow32    (USER32.482)
822  */
823 BOOL WINAPI SetForegroundWindow( HWND hwnd )
824 {
825     SetActiveWindow( hwnd );
826     return TRUE;
827 }
828
829
830 /*******************************************************************
831  *         GetShellWindow16    (USER.600)
832  */
833 HWND16 WINAPI GetShellWindow16(void)
834 {
835     return GetShellWindow();
836 }
837
838 /*******************************************************************
839  *         SetShellWindow32    (USER32.504)
840  */
841 HWND WINAPI SetShellWindow(HWND hwndshell)
842 {   WARN(win, "(hWnd=%08x) semi stub\n",hwndshell );
843
844     hGlobalShellWindow = hwndshell;
845     return hGlobalShellWindow;
846 }
847
848
849 /*******************************************************************
850  *         GetShellWindow32    (USER32.287)
851  */
852 HWND WINAPI GetShellWindow(void)
853 {   WARN(win, "(hWnd=%x) semi stub\n",hGlobalShellWindow );
854
855     return hGlobalShellWindow;
856 }
857
858
859 /***********************************************************************
860  *           BringWindowToTop16   (USER.45)
861  */
862 BOOL16 WINAPI BringWindowToTop16( HWND16 hwnd )
863 {
864     return BringWindowToTop(hwnd);
865 }
866
867
868 /***********************************************************************
869  *           BringWindowToTop32   (USER32.11)
870  */
871 BOOL WINAPI BringWindowToTop( HWND hwnd )
872 {
873     return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
874 }
875
876
877 /***********************************************************************
878  *           MoveWindow16   (USER.56)
879  */
880 BOOL16 WINAPI MoveWindow16( HWND16 hwnd, INT16 x, INT16 y, INT16 cx, INT16 cy,
881                             BOOL16 repaint )
882 {
883     return MoveWindow(hwnd,x,y,cx,cy,repaint);
884 }
885
886
887 /***********************************************************************
888  *           MoveWindow32   (USER32.399)
889  */
890 BOOL WINAPI MoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy,
891                             BOOL repaint )
892 {    
893     int flags = SWP_NOZORDER | SWP_NOACTIVATE;
894     if (!repaint) flags |= SWP_NOREDRAW;
895     TRACE(win, "%04x %d,%d %dx%d %d\n", 
896             hwnd, x, y, cx, cy, repaint );
897     return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
898 }
899
900 /***********************************************************************
901  *           WINPOS_InitInternalPos
902  */
903 static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT pt, 
904                                              LPRECT restoreRect )
905 {
906     LPINTERNALPOS lpPos = (LPINTERNALPOS) GetPropA( wnd->hwndSelf,
907                                                       atomInternalPos );
908     if( !lpPos )
909     {
910         /* this happens when the window is minimized/maximized 
911          * for the first time (rectWindow is not adjusted yet) */
912
913         lpPos = HeapAlloc( SystemHeap, 0, sizeof(INTERNALPOS) );
914         if( !lpPos ) return NULL;
915
916         SetPropA( wnd->hwndSelf, atomInternalPos, (HANDLE)lpPos );
917         lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
918         CONV_RECT32TO16( &wnd->rectWindow, &lpPos->rectNormal );
919         *(UINT*)&lpPos->ptIconPos = *(UINT*)&lpPos->ptMaxPos = 0xFFFFFFFF;
920     }
921
922     if( wnd->dwStyle & WS_MINIMIZE ) 
923         CONV_POINT32TO16( &pt, &lpPos->ptIconPos );
924     else if( wnd->dwStyle & WS_MAXIMIZE ) 
925         CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
926     else if( restoreRect ) 
927         CONV_RECT32TO16( restoreRect, &lpPos->rectNormal );
928
929     return lpPos;
930 }
931
932 /***********************************************************************
933  *           WINPOS_RedrawIconTitle
934  */
935 BOOL WINPOS_RedrawIconTitle( HWND hWnd )
936 {
937     LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hWnd, atomInternalPos );
938     if( lpPos )
939     {
940         if( lpPos->hwndIconTitle )
941         {
942             SendMessageA( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
943             InvalidateRect( lpPos->hwndIconTitle, NULL, TRUE );
944             return TRUE;
945         }
946     }
947     return FALSE;
948 }
949
950 /***********************************************************************
951  *           WINPOS_ShowIconTitle
952  */
953 BOOL WINPOS_ShowIconTitle( WND* pWnd, BOOL bShow )
954 {
955     LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( pWnd->hwndSelf, atomInternalPos );
956
957     if( lpPos && !(pWnd->flags & WIN_MANAGED))
958     {
959         HWND16 hWnd = lpPos->hwndIconTitle;
960
961         TRACE(win,"0x%04x %i\n", pWnd->hwndSelf, (bShow != 0) );
962
963         if( !hWnd )
964             lpPos->hwndIconTitle = hWnd = ICONTITLE_Create( pWnd );
965         if( bShow )
966         {
967             pWnd = WIN_FindWndPtr(hWnd);
968
969             if( !(pWnd->dwStyle & WS_VISIBLE) )
970             {
971                 SendMessageA( hWnd, WM_SHOWWINDOW, TRUE, 0 );
972                 SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
973                                 SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
974             }
975         }
976         else ShowWindow( hWnd, SW_HIDE );
977     }
978     return FALSE;
979 }
980
981 /*******************************************************************
982  *           WINPOS_GetMinMaxInfo
983  *
984  * Get the minimized and maximized information for a window.
985  */
986 void WINPOS_GetMinMaxInfo( WND *wndPtr, POINT *maxSize, POINT *maxPos,
987                            POINT *minTrack, POINT *maxTrack )
988 {
989     LPINTERNALPOS lpPos;
990     MINMAXINFO MinMax;
991     INT xinc, yinc;
992
993     /* Compute default values */
994
995     MinMax.ptMaxSize.x = SYSMETRICS_CXSCREEN;
996     MinMax.ptMaxSize.y = SYSMETRICS_CYSCREEN;
997     MinMax.ptMinTrackSize.x = SYSMETRICS_CXMINTRACK;
998     MinMax.ptMinTrackSize.y = SYSMETRICS_CYMINTRACK;
999     MinMax.ptMaxTrackSize.x = SYSMETRICS_CXSCREEN;
1000     MinMax.ptMaxTrackSize.y = SYSMETRICS_CYSCREEN;
1001
1002     if (wndPtr->flags & WIN_MANAGED) xinc = yinc = 0;
1003     else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1004     {
1005         xinc = SYSMETRICS_CXDLGFRAME;
1006         yinc = SYSMETRICS_CYDLGFRAME;
1007     }
1008     else
1009     {
1010         xinc = yinc = 0;
1011         if (HAS_THICKFRAME(wndPtr->dwStyle))
1012         {
1013             xinc += SYSMETRICS_CXFRAME;
1014             yinc += SYSMETRICS_CYFRAME;
1015         }
1016         if (wndPtr->dwStyle & WS_BORDER)
1017         {
1018             xinc += SYSMETRICS_CXBORDER;
1019             yinc += SYSMETRICS_CYBORDER;
1020         }
1021     }
1022     MinMax.ptMaxSize.x += 2 * xinc;
1023     MinMax.ptMaxSize.y += 2 * yinc;
1024
1025     lpPos = (LPINTERNALPOS)GetPropA( wndPtr->hwndSelf, atomInternalPos );
1026     if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
1027         CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
1028     else
1029     {
1030         MinMax.ptMaxPosition.x = -xinc;
1031         MinMax.ptMaxPosition.y = -yinc;
1032     }
1033
1034     SendMessageA( wndPtr->hwndSelf, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
1035
1036       /* Some sanity checks */
1037
1038     TRACE(win,"%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1039                       MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
1040                       MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
1041                       MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
1042                       MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
1043     MinMax.ptMaxTrackSize.x = MAX( MinMax.ptMaxTrackSize.x,
1044                                    MinMax.ptMinTrackSize.x );
1045     MinMax.ptMaxTrackSize.y = MAX( MinMax.ptMaxTrackSize.y,
1046                                    MinMax.ptMinTrackSize.y );
1047
1048     if (maxSize) *maxSize = MinMax.ptMaxSize;
1049     if (maxPos) *maxPos = MinMax.ptMaxPosition;
1050     if (minTrack) *minTrack = MinMax.ptMinTrackSize;
1051     if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
1052 }
1053
1054 /***********************************************************************
1055  *           WINPOS_MinMaximize
1056  *
1057  * Fill in lpRect and return additional flags to be used with SetWindowPos().
1058  * This function assumes that 'cmd' is different from the current window
1059  * state.
1060  */
1061 UINT16 WINPOS_MinMaximize( WND* wndPtr, UINT16 cmd, LPRECT16 lpRect )
1062 {
1063     UINT16 swpFlags = 0;
1064     POINT pt;
1065     POINT size = { wndPtr->rectWindow.left, wndPtr->rectWindow.top };
1066     LPINTERNALPOS lpPos = WINPOS_InitInternalPos( wndPtr, size,
1067                                                   &wndPtr->rectWindow );
1068
1069     TRACE(win,"0x%04x %u\n", wndPtr->hwndSelf, cmd );
1070
1071     if (lpPos && !HOOK_CallHooks16(WH_CBT, HCBT_MINMAX, wndPtr->hwndSelf, cmd))
1072     {
1073         if( wndPtr->dwStyle & WS_MINIMIZE )
1074         {
1075             if( !SendMessageA( wndPtr->hwndSelf, WM_QUERYOPEN, 0, 0L ) )
1076                 return (SWP_NOSIZE | SWP_NOMOVE);
1077             swpFlags |= SWP_NOCOPYBITS;
1078         }
1079         switch( cmd )
1080         {
1081             case SW_MINIMIZE:
1082                  if( wndPtr->dwStyle & WS_MAXIMIZE)
1083                  {
1084                      wndPtr->flags |= WIN_RESTORE_MAX;
1085                      wndPtr->dwStyle &= ~WS_MAXIMIZE;
1086                  }
1087                  else
1088                      wndPtr->flags &= ~WIN_RESTORE_MAX;
1089                  wndPtr->dwStyle |= WS_MINIMIZE;
1090
1091                  lpPos->ptIconPos = WINPOS_FindIconPos( wndPtr, lpPos->ptIconPos );
1092
1093                  SetRect16( lpRect, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1094                                     SYSMETRICS_CXICON, SYSMETRICS_CYICON );
1095                  swpFlags |= SWP_NOCOPYBITS;
1096                  break;
1097
1098             case SW_MAXIMIZE:
1099                 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1100                 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL );
1101                 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1102
1103                  if( wndPtr->dwStyle & WS_MINIMIZE )
1104                  {
1105                      WINPOS_ShowIconTitle( wndPtr, FALSE );
1106                      wndPtr->dwStyle &= ~WS_MINIMIZE;
1107                  }
1108                  wndPtr->dwStyle |= WS_MAXIMIZE;
1109
1110                  SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1111                                     size.x, size.y );
1112                  break;
1113
1114             case SW_RESTORE:
1115                  if( wndPtr->dwStyle & WS_MINIMIZE )
1116                  {
1117                      wndPtr->dwStyle &= ~WS_MINIMIZE;
1118                      WINPOS_ShowIconTitle( wndPtr, FALSE );
1119                      if( wndPtr->flags & WIN_RESTORE_MAX)
1120                      {
1121                          /* Restore to maximized position */
1122                          CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1123                          WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL);
1124                          CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1125                          wndPtr->dwStyle |= WS_MAXIMIZE;
1126                          SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y, size.x, size.y );
1127                          break;
1128                      }
1129                  } 
1130                  else 
1131                      if( !(wndPtr->dwStyle & WS_MAXIMIZE) ) return (UINT16)(-1);
1132                      else wndPtr->dwStyle &= ~WS_MAXIMIZE;
1133
1134                  /* Restore to normal position */
1135
1136                 *lpRect = lpPos->rectNormal; 
1137                  lpRect->right -= lpRect->left; 
1138                  lpRect->bottom -= lpRect->top;
1139
1140                  break;
1141         }
1142     } else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
1143     return swpFlags;
1144 }
1145
1146 /***********************************************************************
1147  *           ShowWindowAsync32   (USER32.535)
1148  *
1149  * doesn't wait; returns immediately.
1150  * used by threads to toggle windows in other (possibly hanging) threads
1151  */
1152 BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd )
1153 {
1154     /* FIXME: does ShowWindow32() return immediately ? */
1155     return ShowWindow(hwnd, cmd);
1156 }
1157
1158
1159 /***********************************************************************
1160  *           ShowWindow16   (USER.42)
1161  */
1162 BOOL16 WINAPI ShowWindow16( HWND16 hwnd, INT16 cmd ) 
1163 {    
1164     return ShowWindow(hwnd,cmd);
1165 }
1166
1167
1168 /***********************************************************************
1169  *           ShowWindow32   (USER32.534)
1170  */
1171 BOOL WINAPI ShowWindow( HWND hwnd, INT cmd ) 
1172 {    
1173     WND*        wndPtr = WIN_FindWndPtr( hwnd );
1174     BOOL        wasVisible, showFlag;
1175     RECT16      newPos = {0, 0, 0, 0};
1176     int         swp = 0;
1177
1178     if (!wndPtr) return FALSE;
1179
1180     TRACE(win,"hwnd=%04x, cmd=%d\n", hwnd, cmd);
1181
1182     wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
1183
1184     switch(cmd)
1185     {
1186         case SW_HIDE:
1187             if (!wasVisible) return FALSE;
1188             swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | 
1189                         SWP_NOACTIVATE | SWP_NOZORDER;
1190             if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus()))
1191             {
1192                 /* Revert focus to parent */
1193                 SetFocus( GetParent(hwnd) );
1194             }
1195             break;
1196
1197         case SW_SHOWMINNOACTIVE:
1198             swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1199             /* fall through */
1200         case SW_SHOWMINIMIZED:
1201             swp |= SWP_SHOWWINDOW;
1202             /* fall through */
1203         case SW_MINIMIZE:
1204             swp |= SWP_FRAMECHANGED;
1205             if( !(wndPtr->dwStyle & WS_MINIMIZE) )
1206                  swp |= WINPOS_MinMaximize( wndPtr, SW_MINIMIZE, &newPos );
1207             else swp |= SWP_NOSIZE | SWP_NOMOVE;
1208             break;
1209
1210         case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
1211             swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1212             if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
1213                  swp |= WINPOS_MinMaximize( wndPtr, SW_MAXIMIZE, &newPos );
1214             else swp |= SWP_NOSIZE | SWP_NOMOVE;
1215             break;
1216
1217         case SW_SHOWNA:
1218             swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1219             /* fall through */
1220         case SW_SHOW:
1221             swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
1222             break;
1223
1224         case SW_SHOWNOACTIVATE:
1225             swp |= SWP_NOZORDER;
1226             if (GetActiveWindow()) swp |= SWP_NOACTIVATE;
1227             /* fall through */
1228         case SW_SHOWNORMAL:  /* same as SW_NORMAL: */
1229         case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
1230         case SW_RESTORE:
1231             swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1232
1233             if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) )
1234                  swp |= WINPOS_MinMaximize( wndPtr, SW_RESTORE, &newPos );
1235             else swp |= SWP_NOSIZE | SWP_NOMOVE;
1236             break;
1237     }
1238
1239     showFlag = (cmd != SW_HIDE);
1240     if (showFlag != wasVisible)
1241     {
1242         SendMessageA( hwnd, WM_SHOWWINDOW, showFlag, 0 );
1243         if (!IsWindow( hwnd )) return wasVisible;
1244     }
1245
1246     if ((wndPtr->dwStyle & WS_CHILD) &&
1247         !IsWindowVisible( wndPtr->parent->hwndSelf ) &&
1248         (swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE) )
1249     {
1250         /* Don't call SetWindowPos32() on invisible child windows */
1251         if (cmd == SW_HIDE) wndPtr->dwStyle &= ~WS_VISIBLE;
1252         else wndPtr->dwStyle |= WS_VISIBLE;
1253     }
1254     else
1255     {
1256         /* We can't activate a child window */
1257         if (wndPtr->dwStyle & WS_CHILD) swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1258         SetWindowPos( hwnd, HWND_TOP, 
1259                         newPos.left, newPos.top, newPos.right, newPos.bottom, swp );
1260         if (!IsWindow( hwnd )) return wasVisible;
1261         else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( wndPtr, TRUE );
1262     }
1263
1264     if (wndPtr->flags & WIN_NEED_SIZE)
1265     {
1266         /* should happen only in CreateWindowEx() */
1267         int wParam = SIZE_RESTORED;
1268
1269         wndPtr->flags &= ~WIN_NEED_SIZE;
1270         if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
1271         else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
1272         SendMessageA( hwnd, WM_SIZE, wParam,
1273                      MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
1274                             wndPtr->rectClient.bottom-wndPtr->rectClient.top));
1275         SendMessageA( hwnd, WM_MOVE, 0,
1276                    MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
1277     }
1278
1279     return wasVisible;
1280 }
1281
1282
1283 /***********************************************************************
1284  *           GetInternalWindowPos16   (USER.460)
1285  */
1286 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
1287                                       LPPOINT16 ptIcon )
1288 {
1289     WINDOWPLACEMENT16 wndpl;
1290     if (GetWindowPlacement16( hwnd, &wndpl )) 
1291     {
1292         if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1293         if (ptIcon)  *ptIcon = wndpl.ptMinPosition;
1294         return wndpl.showCmd;
1295     }
1296     return 0;
1297 }
1298
1299
1300 /***********************************************************************
1301  *           GetInternalWindowPos32   (USER32.245)
1302  */
1303 UINT WINAPI GetInternalWindowPos( HWND hwnd, LPRECT rectWnd,
1304                                       LPPOINT ptIcon )
1305 {
1306     WINDOWPLACEMENT wndpl;
1307     if (GetWindowPlacement( hwnd, &wndpl ))
1308     {
1309         if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1310         if (ptIcon)  *ptIcon = wndpl.ptMinPosition;
1311         return wndpl.showCmd;
1312     }
1313     return 0;
1314 }
1315
1316 /***********************************************************************
1317  *           GetWindowPlacement16   (USER.370)
1318  */
1319 BOOL16 WINAPI GetWindowPlacement16( HWND16 hwnd, WINDOWPLACEMENT16 *wndpl )
1320 {
1321     WND *pWnd = WIN_FindWndPtr( hwnd );
1322     if( pWnd )
1323     {
1324         LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1325                              *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1326         wndpl->length  = sizeof(*wndpl);
1327         if( pWnd->dwStyle & WS_MINIMIZE )
1328             wndpl->showCmd = SW_SHOWMINIMIZED;
1329         else 
1330             wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE )
1331                              ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
1332         if( pWnd->flags & WIN_RESTORE_MAX )
1333             wndpl->flags = WPF_RESTORETOMAXIMIZED;
1334         else
1335             wndpl->flags = 0;
1336         wndpl->ptMinPosition = lpPos->ptIconPos;
1337         wndpl->ptMaxPosition = lpPos->ptMaxPos;
1338         wndpl->rcNormalPosition = lpPos->rectNormal;
1339         return TRUE;
1340     }
1341     return FALSE;
1342 }
1343
1344
1345 /***********************************************************************
1346  *           GetWindowPlacement32   (USER32.307)
1347  *
1348  * Win95:
1349  * Fails if wndpl->length of Win95 (!) apps is invalid.
1350  */
1351 BOOL WINAPI GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *pwpl32 )
1352 {
1353     if( pwpl32 )
1354     {
1355         WINDOWPLACEMENT16 wpl;
1356         wpl.length = sizeof(wpl);
1357         if( GetWindowPlacement16( hwnd, &wpl ) )
1358         {
1359             pwpl32->length = sizeof(*pwpl32);
1360             pwpl32->flags = wpl.flags;
1361             pwpl32->showCmd = wpl.showCmd;
1362             CONV_POINT16TO32( &wpl.ptMinPosition, &pwpl32->ptMinPosition );
1363             CONV_POINT16TO32( &wpl.ptMaxPosition, &pwpl32->ptMaxPosition );
1364             CONV_RECT16TO32( &wpl.rcNormalPosition, &pwpl32->rcNormalPosition );
1365             return TRUE;
1366         }
1367     }
1368     return FALSE;
1369 }
1370
1371
1372 /***********************************************************************
1373  *           WINPOS_SetPlacement
1374  */
1375 static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT16 *wndpl,
1376                                                 UINT flags )
1377 {
1378     WND *pWnd = WIN_FindWndPtr( hwnd );
1379     if( pWnd )
1380     {
1381         LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1382                              *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1383
1384         if( flags & PLACE_MIN ) lpPos->ptIconPos = wndpl->ptMinPosition;
1385         if( flags & PLACE_MAX ) lpPos->ptMaxPos = wndpl->ptMaxPosition;
1386         if( flags & PLACE_RECT) lpPos->rectNormal = wndpl->rcNormalPosition;
1387
1388         if( pWnd->dwStyle & WS_MINIMIZE )
1389         {
1390             WINPOS_ShowIconTitle( pWnd, FALSE );
1391             if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1392                 SetWindowPos( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1393                                 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1394         } 
1395         else if( pWnd->dwStyle & WS_MAXIMIZE )
1396         {
1397             if( !EMPTYPOINT(lpPos->ptMaxPos) )
1398                 SetWindowPos( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1399                                 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1400         }
1401         else if( flags & PLACE_RECT )
1402                 SetWindowPos( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1403                                 lpPos->rectNormal.right - lpPos->rectNormal.left,
1404                                 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1405                                 SWP_NOZORDER | SWP_NOACTIVATE );
1406
1407         ShowWindow( hwnd, wndpl->showCmd );
1408         if( IsWindow(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1409         {
1410             if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd, TRUE );
1411
1412             /* SDK: ...valid only the next time... */
1413             if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1414         }
1415         return TRUE;
1416     }
1417     return FALSE;
1418 }
1419
1420
1421 /***********************************************************************
1422  *           SetWindowPlacement16   (USER.371)
1423  */
1424 BOOL16 WINAPI SetWindowPlacement16(HWND16 hwnd, const WINDOWPLACEMENT16 *wndpl)
1425 {
1426     return WINPOS_SetPlacement( hwnd, wndpl,
1427                                 PLACE_MIN | PLACE_MAX | PLACE_RECT );
1428 }
1429
1430 /***********************************************************************
1431  *           SetWindowPlacement32   (USER32.519)
1432  *
1433  * Win95:
1434  * Fails if wndpl->length of Win95 (!) apps is invalid.
1435  */
1436 BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *pwpl32 )
1437 {
1438     if( pwpl32 )
1439     {
1440         WINDOWPLACEMENT16 wpl = { sizeof(WINDOWPLACEMENT16), 
1441                 pwpl32->flags, pwpl32->showCmd, { pwpl32->ptMinPosition.x,
1442                 pwpl32->ptMinPosition.y }, { pwpl32->ptMaxPosition.x,
1443                 pwpl32->ptMaxPosition.y }, { pwpl32->rcNormalPosition.left,
1444                 pwpl32->rcNormalPosition.top, pwpl32->rcNormalPosition.right,
1445                 pwpl32->rcNormalPosition.bottom } };
1446
1447         return WINPOS_SetPlacement( hwnd, &wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1448     }
1449     return FALSE;
1450 }
1451
1452
1453 /***********************************************************************
1454  *           SetInternalWindowPos16   (USER.461)
1455  */
1456 void WINAPI SetInternalWindowPos16( HWND16 hwnd, UINT16 showCmd,
1457                                     LPRECT16 rect, LPPOINT16 pt )
1458 {
1459     if( IsWindow16(hwnd) )
1460     {
1461         WINDOWPLACEMENT16 wndpl;
1462         UINT flags;
1463
1464         wndpl.length  = sizeof(wndpl);
1465         wndpl.showCmd = showCmd;
1466         wndpl.flags = flags = 0;
1467
1468         if( pt )
1469         {
1470             flags |= PLACE_MIN;
1471             wndpl.flags |= WPF_SETMINPOSITION;
1472             wndpl.ptMinPosition = *pt;
1473         }
1474         if( rect )
1475         {
1476             flags |= PLACE_RECT;
1477             wndpl.rcNormalPosition = *rect;
1478         }
1479         WINPOS_SetPlacement( hwnd, &wndpl, flags );
1480     }
1481 }
1482
1483
1484 /***********************************************************************
1485  *           SetInternalWindowPos32   (USER32.483)
1486  */
1487 void WINAPI SetInternalWindowPos( HWND hwnd, UINT showCmd,
1488                                     LPRECT rect, LPPOINT pt )
1489 {
1490     if( IsWindow(hwnd) )
1491     {
1492         WINDOWPLACEMENT16 wndpl;
1493         UINT flags;
1494
1495         wndpl.length  = sizeof(wndpl);
1496         wndpl.showCmd = showCmd;
1497         wndpl.flags = flags = 0;
1498
1499         if( pt )
1500         {
1501             flags |= PLACE_MIN;
1502             wndpl.flags |= WPF_SETMINPOSITION;
1503             CONV_POINT32TO16( pt, &wndpl.ptMinPosition );
1504         }
1505         if( rect )
1506         {
1507             flags |= PLACE_RECT;
1508             CONV_RECT32TO16( rect, &wndpl.rcNormalPosition );
1509         }
1510         WINPOS_SetPlacement( hwnd, &wndpl, flags );
1511     }
1512 }
1513
1514 /*******************************************************************
1515  *         WINPOS_SetActiveWindow
1516  *
1517  * SetActiveWindow() back-end. This is the only function that
1518  * can assign active status to a window. It must be called only
1519  * for the top level windows.
1520  */
1521 BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
1522 {
1523     CBTACTIVATESTRUCT16* cbtStruct;
1524     WND*     wndPtr, *wndTemp;
1525     HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1526     MESSAGEQUEUE *pOldActiveQueue = 0, *pNewActiveQueue = 0;
1527     WORD     wIconized = 0;
1528     HWND   hwndActive = 0;
1529     BOOL   bRet = 0;
1530
1531     /* Get current active window from the active queue */
1532     if ( hActiveQueue )
1533     {
1534         pOldActiveQueue = QUEUE_Lock( hActiveQueue );
1535         if ( pOldActiveQueue )
1536             hwndActive = PERQDATA_GetActiveWnd( pOldActiveQueue->pQData );
1537     }
1538
1539     /* paranoid checks */
1540     if( hWnd == GetDesktopWindow() || hWnd == hwndActive ) goto CLEANUP;
1541
1542 /*  if (wndPtr && (GetFastQueue() != wndPtr->hmemTaskQ))
1543  *      return 0;
1544  */
1545     wndPtr = WIN_FindWndPtr(hWnd);
1546     hOldActiveQueue = hActiveQueue;
1547
1548     if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1549         wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1550     else
1551         TRACE(win,"no current active window.\n");
1552
1553     /* call CBT hook chain */
1554     if ((cbtStruct = SEGPTR_NEW(CBTACTIVATESTRUCT16)))
1555     {
1556         LRESULT wRet;
1557         cbtStruct->fMouse     = fMouse;
1558         cbtStruct->hWndActive = hwndActive;
1559         wRet = HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
1560                                  (LPARAM)SEGPTR_GET(cbtStruct) );
1561         SEGPTR_FREE(cbtStruct);
1562         if (wRet)
1563         {
1564             /* Unlock the active queue before returning */
1565             if ( pOldActiveQueue )
1566                 QUEUE_Unlock( pOldActiveQueue );
1567             return wRet;
1568         }
1569     }
1570
1571     /* set prev active wnd to current active wnd and send notification */
1572     if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
1573     {
1574         MESSAGEQUEUE *pTempActiveQueue = 0;
1575         
1576         if (!SendMessageA( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1577         {
1578             if (GetSysModalWindow16() != hWnd) goto CLEANUP;
1579             /* disregard refusal if hWnd is sysmodal */
1580         }
1581
1582 #if 1
1583         SendMessageA( hwndPrevActive, WM_ACTIVATE,
1584                         MAKEWPARAM( WA_INACTIVE, wIconized ),
1585                         (LPARAM)hWnd );
1586 #else
1587         /* FIXME: must be SendMessage16() because 32A doesn't do
1588          * intertask at this time */
1589         SendMessage16( hwndPrevActive, WM_ACTIVATE, WA_INACTIVE,
1590                                 MAKELPARAM( (HWND16)hWnd, wIconized ) );
1591 #endif
1592
1593         /* check if something happened during message processing
1594          * (global active queue may have changed)
1595          */
1596         if (hActiveQueue==0)
1597           goto CLEANUP;
1598
1599         pTempActiveQueue = QUEUE_Lock( hActiveQueue );
1600         hwndActive = PERQDATA_GetActiveWnd( pTempActiveQueue->pQData );
1601         QUEUE_Unlock( pTempActiveQueue );
1602         if( hwndPrevActive != hwndActive )
1603             goto CLEANUP;
1604     }
1605
1606     /* Set new active window in the message queue */
1607     hwndActive = hWnd;
1608     if ( wndPtr )
1609     {
1610         pNewActiveQueue = QUEUE_Lock( wndPtr->hmemTaskQ );
1611         if ( pNewActiveQueue )
1612             PERQDATA_SetActiveWnd( pNewActiveQueue->pQData, hwndActive );
1613     }
1614
1615     /* send palette messages */
1616     if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1617         SendMessage16((HWND16)-1, WM_PALETTEISCHANGING, (WPARAM16)hWnd, 0L );
1618
1619     /* if prev wnd is minimized redraw icon title */
1620     if( IsIconic( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1621
1622     /* managed windows will get ConfigureNotify event */  
1623     if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->flags & WIN_MANAGED))
1624     {
1625         /* check Z-order and bring hWnd to the top */
1626         for (wndTemp = WIN_GetDesktop()->child; wndTemp; wndTemp = wndTemp->next)
1627             if (wndTemp->dwStyle & WS_VISIBLE) break;
1628
1629         if( wndTemp != wndPtr )
1630             SetWindowPos(hWnd, HWND_TOP, 0,0,0,0, 
1631                            SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1632         if (!IsWindow(hWnd))  goto CLEANUP;
1633     }
1634
1635     /* Get a handle to the new active queue */
1636     hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1637
1638     /* send WM_ACTIVATEAPP if necessary */
1639     if (hOldActiveQueue != hNewActiveQueue)
1640     {
1641         WND **list, **ppWnd;
1642
1643         if ( (hNewActiveQueue!=0) && 
1644              (list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
1645         {
1646             for (ppWnd = list; *ppWnd; ppWnd++)
1647             {
1648                 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1649
1650                 if ((*ppWnd)->hmemTaskQ == hOldActiveQueue)
1651                    SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1652                                    0, QUEUE_GetQueueTask(hNewActiveQueue) );
1653             }
1654             HeapFree( SystemHeap, 0, list );
1655         }
1656
1657         hActiveQueue = hNewActiveQueue;
1658
1659         if ( (hOldActiveQueue!=0) &&
1660              (list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
1661         {
1662             for (ppWnd = list; *ppWnd; ppWnd++)
1663             {
1664                 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1665
1666                 if ((*ppWnd)->hmemTaskQ == hNewActiveQueue)
1667                    SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1668                                   1, QUEUE_GetQueueTask( hOldActiveQueue ) );
1669             }
1670             HeapFree( SystemHeap, 0, list );
1671         }
1672         
1673         if (!IsWindow(hWnd)) goto CLEANUP;
1674     }
1675
1676     if (hWnd)
1677     {
1678         /* walk up to the first unowned window */
1679         wndTemp = wndPtr;
1680         while (wndTemp->owner) wndTemp = wndTemp->owner;
1681         /* and set last active owned popup */
1682         wndTemp->hwndLastActive = hWnd;
1683
1684         wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1685         SendMessageA( hWnd, WM_NCACTIVATE, TRUE, 0 );
1686 #if 1
1687         SendMessageA( hWnd, WM_ACTIVATE,
1688                  MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1689                  (LPARAM)hwndPrevActive );
1690 #else
1691         SendMessage16(hWnd, WM_ACTIVATE, (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE,
1692                       MAKELPARAM( (HWND16)hwndPrevActive, wIconized) );
1693 #endif
1694
1695         if( !IsWindow(hWnd) ) goto CLEANUP;
1696     }
1697
1698     /* change focus if possible */
1699     if( fChangeFocus && GetFocus() )
1700         if( WIN_GetTopParent(GetFocus()) != hwndActive )
1701             FOCUS_SwitchFocus( pNewActiveQueue, GetFocus(),
1702                                (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
1703                                0:
1704                                hwndActive
1705             );
1706
1707     if( !hwndPrevActive && wndPtr )
1708         (*wndPtr->pDriver->pForceWindowRaise)(wndPtr);
1709
1710     /* if active wnd is minimized redraw icon title */
1711     if( IsIconic(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1712
1713     bRet = 1;  // Success
1714     
1715 CLEANUP:
1716
1717     /* Unlock the message queues before returning */
1718     if ( pOldActiveQueue )
1719         QUEUE_Unlock( pOldActiveQueue );
1720     if ( pNewActiveQueue )
1721         QUEUE_Unlock( pNewActiveQueue );
1722     return bRet ? (hWnd == hwndActive) : 0;
1723 }
1724
1725 /*******************************************************************
1726  *         WINPOS_ActivateOtherWindow
1727  *
1728  *  Activates window other than pWnd.
1729  */
1730 BOOL WINPOS_ActivateOtherWindow(WND* pWnd)
1731 {
1732   BOOL  bRet = 0;
1733   WND*          pWndTo = NULL;
1734     HWND       hwndActive = 0;
1735
1736     /* Get current active window from the active queue */
1737     if ( hActiveQueue )
1738     {
1739         MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1740         if ( pActiveQueue )
1741         {
1742             hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1743             QUEUE_Unlock( pActiveQueue );
1744         }
1745     }
1746
1747   if( pWnd->hwndSelf == hwndPrevActive )
1748       hwndPrevActive = 0;
1749
1750   if( hwndActive != pWnd->hwndSelf && 
1751     ( hwndActive || QUEUE_IsExitingQueue(pWnd->hmemTaskQ)) )
1752       return 0;
1753
1754   if( !(pWnd->dwStyle & WS_POPUP) || !(pWnd->owner) ||
1755       !WINPOS_CanActivate((pWndTo = WIN_GetTopParentPtr(pWnd->owner))) ) 
1756   {
1757       WND* pWndPtr = WIN_GetTopParentPtr(pWnd);
1758
1759       pWndTo = WIN_FindWndPtr(hwndPrevActive);
1760
1761       while( !WINPOS_CanActivate(pWndTo) ) 
1762       {
1763          /* by now owned windows should've been taken care of */
1764
1765           pWndTo = pWndPtr->next;
1766           pWndPtr = pWndTo;
1767           if( !pWndTo ) break;
1768       }
1769   }
1770
1771   bRet = WINPOS_SetActiveWindow( pWndTo ? pWndTo->hwndSelf : 0, FALSE, TRUE );
1772
1773   /* switch desktop queue to current active */
1774   if( pWndTo ) WIN_GetDesktop()->hmemTaskQ = pWndTo->hmemTaskQ;
1775
1776   hwndPrevActive = 0;
1777   return bRet;  
1778 }
1779
1780 /*******************************************************************
1781  *         WINPOS_ChangeActiveWindow
1782  *
1783  */
1784 BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
1785 {
1786     WND *wndPtr = WIN_FindWndPtr(hWnd);
1787     HWND hwndActive = 0;
1788
1789     /* Get current active window from the active queue */
1790     if ( hActiveQueue )
1791     {
1792         MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1793         if ( pActiveQueue )
1794         {
1795             hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1796             QUEUE_Unlock( pActiveQueue );
1797         }
1798     }
1799
1800     if (!hWnd) return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
1801
1802     if( !wndPtr ) return FALSE;
1803
1804     /* child windows get WM_CHILDACTIVATE message */
1805     if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
1806         return SendMessageA(hWnd, WM_CHILDACTIVATE, 0, 0L);
1807
1808         /* owned popups imply owner activation - not sure */
1809     if ((wndPtr->dwStyle & WS_POPUP) && wndPtr->owner &&
1810         (wndPtr->owner->dwStyle & WS_VISIBLE ) &&
1811         !(wndPtr->owner->dwStyle & WS_DISABLED ))
1812     {
1813         if (!(wndPtr = wndPtr->owner)) return FALSE;
1814         hWnd = wndPtr->hwndSelf;
1815     }
1816
1817     if( hWnd == hwndActive ) return FALSE;
1818
1819     if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
1820         return FALSE;
1821
1822     /* switch desktop queue to current active */
1823     if( wndPtr->parent == WIN_GetDesktop())
1824         WIN_GetDesktop()->hmemTaskQ = wndPtr->hmemTaskQ;
1825
1826     return TRUE;
1827 }
1828
1829
1830 /***********************************************************************
1831  *           WINPOS_SendNCCalcSize
1832  *
1833  * Send a WM_NCCALCSIZE message to a window.
1834  * All parameters are read-only except newClientRect.
1835  * oldWindowRect, oldClientRect and winpos must be non-NULL only
1836  * when calcValidRect is TRUE.
1837  */
1838 LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect,
1839                             RECT *newWindowRect, RECT *oldWindowRect,
1840                             RECT *oldClientRect, WINDOWPOS *winpos,
1841                             RECT *newClientRect )
1842 {
1843     NCCALCSIZE_PARAMS params;
1844     WINDOWPOS winposCopy;
1845     LONG result;
1846
1847     params.rgrc[0] = *newWindowRect;
1848     if (calcValidRect)
1849     {
1850         winposCopy = *winpos;
1851         params.rgrc[1] = *oldWindowRect;
1852         params.rgrc[2] = *oldClientRect;
1853         params.lppos = &winposCopy;
1854     }
1855     result = SendMessageA( hwnd, WM_NCCALCSIZE, calcValidRect,
1856                              (LPARAM)&params );
1857     TRACE(win, "%d,%d-%d,%d\n",
1858                  params.rgrc[0].left, params.rgrc[0].top,
1859                  params.rgrc[0].right, params.rgrc[0].bottom );
1860     *newClientRect = params.rgrc[0];
1861     return result;
1862 }
1863
1864
1865 /***********************************************************************
1866  *           WINPOS_HandleWindowPosChanging16
1867  *
1868  * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
1869  */
1870 LONG WINPOS_HandleWindowPosChanging16( WND *wndPtr, WINDOWPOS16 *winpos )
1871 {
1872     POINT maxSize, minTrack;
1873     if (winpos->flags & SWP_NOSIZE) return 0;
1874     if ((wndPtr->dwStyle & WS_THICKFRAME) ||
1875         ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
1876     {
1877         WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
1878         if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
1879         if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
1880         if (!(wndPtr->dwStyle & WS_MINIMIZE))
1881         {
1882             if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
1883             if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
1884         }
1885     }
1886     return 0;
1887 }
1888
1889
1890 /***********************************************************************
1891  *           WINPOS_HandleWindowPosChanging32
1892  *
1893  * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
1894  */
1895 LONG WINPOS_HandleWindowPosChanging( WND *wndPtr, WINDOWPOS *winpos )
1896 {
1897     POINT maxSize;
1898     if (winpos->flags & SWP_NOSIZE) return 0;
1899     if ((wndPtr->dwStyle & WS_THICKFRAME) ||
1900         ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
1901     {
1902         WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, NULL, NULL );
1903         winpos->cx = MIN( winpos->cx, maxSize.x );
1904         winpos->cy = MIN( winpos->cy, maxSize.y );
1905     }
1906     return 0;
1907 }
1908
1909
1910 /***********************************************************************
1911  *           WINPOS_MoveWindowZOrder
1912  *
1913  * Move a window in Z order, invalidating everything that needs it.
1914  * Only necessary for windows without associated X window.
1915  */
1916 static void WINPOS_MoveWindowZOrder( HWND hwnd, HWND hwndAfter )
1917 {
1918     BOOL movingUp;
1919     WND *pWndAfter, *pWndCur, *wndPtr = WIN_FindWndPtr( hwnd );
1920
1921     /* We have two possible cases:
1922      * - The window is moving up: we have to invalidate all areas
1923      *   of the window that were covered by other windows
1924      * - The window is moving down: we have to invalidate areas
1925      *   of other windows covered by this one.
1926      */
1927
1928     if (hwndAfter == HWND_TOP)
1929     {
1930         movingUp = TRUE;
1931     }
1932     else if (hwndAfter == HWND_BOTTOM)
1933     {
1934         if (!wndPtr->next) return;  /* Already at the bottom */
1935         movingUp = FALSE;
1936     }
1937     else
1938     {
1939         if (!(pWndAfter = WIN_FindWndPtr( hwndAfter ))) return;
1940         if (wndPtr->next == pWndAfter) return;  /* Already placed right */
1941
1942           /* Determine which window we encounter first in Z-order */
1943         pWndCur = wndPtr->parent->child;
1944         while ((pWndCur != wndPtr) && (pWndCur != pWndAfter))
1945             pWndCur = pWndCur->next;
1946         movingUp = (pWndCur == pWndAfter);
1947     }
1948
1949     if (movingUp)
1950     {
1951         WND *pWndPrevAfter = wndPtr->next;
1952         WIN_UnlinkWindow( hwnd );
1953         WIN_LinkWindow( hwnd, hwndAfter );
1954         pWndCur = wndPtr->next;
1955         while (pWndCur != pWndPrevAfter)
1956         {
1957             RECT rect = { pWndCur->rectWindow.left,
1958                             pWndCur->rectWindow.top,
1959                             pWndCur->rectWindow.right,
1960                             pWndCur->rectWindow.bottom };
1961             OffsetRect( &rect, -wndPtr->rectClient.left,
1962                           -wndPtr->rectClient.top );
1963             PAINT_RedrawWindow( hwnd, &rect, 0, RDW_INVALIDATE | RDW_ALLCHILDREN |
1964                               RDW_FRAME | RDW_ERASE, 0 );
1965             pWndCur = pWndCur->next;
1966         }
1967     }
1968     else  /* Moving down */
1969     {
1970         pWndCur = wndPtr->next;
1971         WIN_UnlinkWindow( hwnd );
1972         WIN_LinkWindow( hwnd, hwndAfter );
1973         while (pWndCur != wndPtr)
1974         {
1975             RECT rect = { pWndCur->rectWindow.left,
1976                             pWndCur->rectWindow.top,
1977                             pWndCur->rectWindow.right,
1978                             pWndCur->rectWindow.bottom };
1979             OffsetRect( &rect, -pWndCur->rectClient.left,
1980                           -pWndCur->rectClient.top );
1981             PAINT_RedrawWindow( pWndCur->hwndSelf, &rect, 0, RDW_INVALIDATE |
1982                               RDW_ALLCHILDREN | RDW_FRAME | RDW_ERASE, 0 );
1983             pWndCur = pWndCur->next;
1984         }
1985     }
1986 }
1987
1988 /***********************************************************************
1989  *           WINPOS_ReorderOwnedPopups
1990  *
1991  * fix Z order taking into account owned popups -
1992  * basically we need to maintain them above the window that owns them
1993  */
1994 HWND WINPOS_ReorderOwnedPopups(HWND hwndInsertAfter,WND* wndPtr,WORD flags)
1995 {
1996  WND*   w = WIN_GetDesktop()->child;
1997
1998   if( wndPtr->dwStyle & WS_POPUP && wndPtr->owner )
1999   {
2000    /* implement "local z-order" between the top and owner window */
2001
2002      HWND hwndLocalPrev = HWND_TOP;
2003
2004      if( hwndInsertAfter != HWND_TOP )
2005      {
2006         while( w != wndPtr->owner )
2007         {
2008           if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
2009           if( hwndLocalPrev == hwndInsertAfter ) break;
2010           w = w->next;
2011         }
2012         hwndInsertAfter = hwndLocalPrev;
2013      }
2014
2015   }
2016   else if( wndPtr->dwStyle & WS_CHILD ) return hwndInsertAfter;
2017
2018   w = WIN_GetDesktop()->child;
2019   while( w )
2020   {
2021     if( w == wndPtr ) break;
2022
2023     if( w->dwStyle & WS_POPUP && w->owner == wndPtr )
2024     {
2025       SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
2026                      SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
2027       hwndInsertAfter = w->hwndSelf;
2028     }
2029     w = w->next;
2030   }
2031
2032   return hwndInsertAfter;
2033 }
2034
2035 /***********************************************************************
2036  *           WINPOS_SizeMoveClean
2037  *
2038  * Make window look nice without excessive repainting
2039  *
2040  * the pain:
2041  *
2042  * visible regions are in window coordinates
2043  * update regions are in window client coordinates
2044  * client and window rectangles are in parent client coordinates
2045  *
2046  * FIXME: Move visible and update regions to the same coordinate system
2047  *       (either parent client or window). This is a lot of work though.
2048  */
2049 static UINT WINPOS_SizeMoveClean( WND* Wnd, HRGN oldVisRgn,
2050                                     LPRECT lpOldWndRect,
2051                                     LPRECT lpOldClientRect, UINT uFlags )
2052 {
2053  HRGN newVisRgn = DCE_GetVisRgn(Wnd->hwndSelf,DCX_WINDOW | DCX_CLIPSIBLINGS,0,0);
2054  HRGN dirtyRgn = CreateRectRgn(0,0,0,0);
2055  int  other, my;
2056
2057  TRACE(win,"cleaning up...new wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i)\n",
2058               Wnd->rectWindow.left, Wnd->rectWindow.top,
2059               Wnd->rectWindow.right, Wnd->rectWindow.bottom,
2060               lpOldWndRect->left, lpOldWndRect->top,
2061               lpOldWndRect->right, lpOldWndRect->bottom);
2062  TRACE(win,"\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2063               Wnd->rectClient.left, Wnd->rectClient.top,
2064               Wnd->rectClient.right, Wnd->rectClient.bottom,
2065               lpOldClientRect->left, lpOldClientRect->top,
2066               lpOldClientRect->right,lpOldClientRect->bottom );
2067
2068  if( (lpOldWndRect->right - lpOldWndRect->left) != (Wnd->rectWindow.right - Wnd->rectWindow.left) ||
2069      (lpOldWndRect->bottom - lpOldWndRect->top) != (Wnd->rectWindow.bottom - Wnd->rectWindow.top) )
2070      uFlags |= SMC_DRAWFRAME;
2071
2072  CombineRgn( dirtyRgn, newVisRgn, 0, RGN_COPY);
2073
2074  if( !(uFlags & SMC_NOCOPY) )
2075    CombineRgn( newVisRgn, newVisRgn, oldVisRgn, RGN_AND ); 
2076
2077  /* map regions to the parent client area */
2078  
2079  OffsetRgn( dirtyRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2080  OffsetRgn( oldVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2081
2082  /* compute invalidated region outside Wnd - (in client coordinates of the parent window) */
2083
2084  other = CombineRgn(dirtyRgn, oldVisRgn, dirtyRgn, RGN_DIFF);
2085
2086  /* map visible region to the Wnd client area */
2087
2088  OffsetRgn( newVisRgn, Wnd->rectWindow.left - Wnd->rectClient.left,
2089                          Wnd->rectWindow.top - Wnd->rectClient.top );
2090
2091  /* substract previously invalidated region from the Wnd visible region */
2092
2093  my =  (Wnd->hrgnUpdate > 1) ? CombineRgn( newVisRgn, newVisRgn,
2094                                              Wnd->hrgnUpdate, RGN_DIFF)
2095                              : COMPLEXREGION;
2096
2097  if( uFlags & SMC_NOCOPY )      /* invalidate Wnd visible region */
2098    {
2099      if (my != NULLREGION)
2100          PAINT_RedrawWindow( Wnd->hwndSelf, NULL, newVisRgn, RDW_INVALIDATE |
2101           RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE, RDW_C_USEHRGN );
2102      else if(uFlags & SMC_DRAWFRAME)
2103          Wnd->flags |= WIN_NEEDS_NCPAINT;
2104    }
2105  else                   /* bitblt old client area */
2106    { 
2107      HDC hDC;
2108      int   update;
2109      HRGN updateRgn;
2110      int   xfrom,yfrom,xto,yto,width,height;
2111
2112      if( uFlags & SMC_DRAWFRAME )
2113        {
2114          /* copy only client area, frame will be redrawn anyway */
2115
2116          xfrom = lpOldClientRect->left; yfrom = lpOldClientRect->top;
2117          xto = Wnd->rectClient.left; yto = Wnd->rectClient.top;
2118          width = lpOldClientRect->right - xfrom; height = lpOldClientRect->bottom - yfrom;
2119          updateRgn = CreateRectRgn( 0, 0, width, height );
2120          CombineRgn( newVisRgn, newVisRgn, updateRgn, RGN_AND );
2121          SetRectRgn( updateRgn, 0, 0, Wnd->rectClient.right - xto,
2122                        Wnd->rectClient.bottom - yto );
2123        }
2124      else
2125        {
2126          xfrom = lpOldWndRect->left; yfrom = lpOldWndRect->top;
2127          xto = Wnd->rectWindow.left; yto = Wnd->rectWindow.top;
2128          width = lpOldWndRect->right - xfrom; height = lpOldWndRect->bottom - yfrom;
2129          updateRgn = CreateRectRgn( xto - Wnd->rectClient.left,
2130                                       yto - Wnd->rectClient.top,
2131                                 Wnd->rectWindow.right - Wnd->rectClient.left,
2132                                 Wnd->rectWindow.bottom - Wnd->rectClient.top );
2133        }
2134
2135      CombineRgn( newVisRgn, newVisRgn, updateRgn, RGN_AND );
2136
2137      /* substract new visRgn from target rect to get a region that won't be copied */
2138
2139      update = CombineRgn( updateRgn, updateRgn, newVisRgn, RGN_DIFF );
2140
2141      /* Blt valid bits using parent window DC */
2142
2143      if( my != NULLREGION && (xfrom != xto || yfrom != yto) )
2144        {
2145          
2146          /* compute clipping region in parent client coordinates */
2147
2148          OffsetRgn( newVisRgn, Wnd->rectClient.left, Wnd->rectClient.top );
2149          CombineRgn( oldVisRgn, oldVisRgn, newVisRgn, RGN_OR );
2150
2151          hDC = GetDCEx( Wnd->parent->hwndSelf, oldVisRgn,
2152                           DCX_KEEPCLIPRGN | DCX_INTERSECTRGN |
2153                           DCX_CACHE | DCX_CLIPSIBLINGS);
2154
2155          BitBlt( hDC, xto, yto, width, height, hDC, xfrom, yfrom, SRCCOPY );
2156          ReleaseDC( Wnd->parent->hwndSelf, hDC); 
2157        }
2158
2159      if( update != NULLREGION )
2160          PAINT_RedrawWindow( Wnd->hwndSelf, NULL, updateRgn, RDW_INVALIDATE |
2161                          RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE, RDW_C_USEHRGN );
2162      else if( uFlags & SMC_DRAWFRAME ) Wnd->flags |= WIN_NEEDS_NCPAINT;
2163      DeleteObject( updateRgn );
2164    }
2165
2166  /* erase uncovered areas */
2167
2168  if( !(uFlags & SMC_NOPARENTERASE) && (other != NULLREGION ) )
2169       PAINT_RedrawWindow( Wnd->parent->hwndSelf, NULL, dirtyRgn,
2170                         RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE, RDW_C_USEHRGN );
2171  DeleteObject(dirtyRgn);
2172  DeleteObject(newVisRgn);
2173  return uFlags;
2174 }
2175
2176 /***********************************************************************
2177  *           SetWindowPos   (USER.232)
2178  */
2179 BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
2180                               INT16 x, INT16 y, INT16 cx, INT16 cy, WORD flags)
2181 {
2182     return SetWindowPos(hwnd,(INT)(INT16)hwndInsertAfter,x,y,cx,cy,flags);
2183 }
2184
2185 /***********************************************************************
2186  *           SetWindowPos   (USER32.520)
2187  */
2188 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
2189                               INT x, INT y, INT cx, INT cy, WORD flags)
2190 {
2191     WINDOWPOS winpos;
2192     WND *       wndPtr;
2193     RECT        newWindowRect, newClientRect, oldWindowRect;
2194     HRGN        visRgn = 0;
2195     HWND        tempInsertAfter= 0;
2196     int         result = 0;
2197     UINT        uFlags = 0;
2198     BOOL      resync = FALSE;
2199     HWND      hwndActive = 0;
2200
2201     /* Get current active window from the active queue */
2202     if ( hActiveQueue )
2203     {
2204         MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2205         if ( pActiveQueue )
2206         {
2207             hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2208             QUEUE_Unlock( pActiveQueue );
2209         }
2210     }
2211
2212     TRACE(win,"hwnd %04x, (%i,%i)-(%i,%i) flags %08x\n", 
2213                                                  hwnd, x, y, x+cx, y+cy, flags);  
2214       /* Check window handle */
2215
2216     if (hwnd == GetDesktopWindow()) return FALSE;
2217     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2218
2219     if(wndPtr->dwStyle & WS_VISIBLE)
2220         flags &= ~SWP_SHOWWINDOW;
2221     else
2222     {
2223         uFlags |= SMC_NOPARENTERASE; 
2224         flags &= ~SWP_HIDEWINDOW;
2225         if (!(flags & SWP_SHOWWINDOW)) flags |= SWP_NOREDRAW;
2226     }
2227
2228 /*     Check for windows that may not be resized 
2229        FIXME: this should be done only for Windows 3.0 programs 
2230        if (flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW ) )
2231            flags |= SWP_NOSIZE | SWP_NOMOVE;
2232 */
2233       /* Check dimensions */
2234
2235     if (cx <= 0) cx = 1;
2236     if (cy <= 0) cy = 1;
2237
2238       /* Check flags */
2239
2240     if (hwnd == hwndActive) flags |= SWP_NOACTIVATE;   /* Already active */
2241     if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
2242         (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
2243         flags |= SWP_NOSIZE;    /* Already the right size */
2244     if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
2245         flags |= SWP_NOMOVE;    /* Already the right position */
2246
2247       /* Check hwndInsertAfter */
2248
2249     if (!(flags & (SWP_NOZORDER | SWP_NOACTIVATE)))
2250     {
2251           /* Ignore TOPMOST flags when activating a window */
2252           /* _and_ moving it in Z order. */
2253         if ((hwndInsertAfter == HWND_TOPMOST) ||
2254             (hwndInsertAfter == HWND_NOTOPMOST))
2255             hwndInsertAfter = HWND_TOP; 
2256     }
2257       /* TOPMOST not supported yet */
2258     if ((hwndInsertAfter == HWND_TOPMOST) ||
2259         (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
2260
2261       /* hwndInsertAfter must be a sibling of the window */
2262     if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
2263        {
2264          WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
2265
2266          if( wnd ) {
2267            if( wnd->parent != wndPtr->parent ) return FALSE;
2268            if( wnd->next == wndPtr ) flags |= SWP_NOZORDER;
2269          }
2270        }
2271     else if (!X11DRV_WND_GetXWindow(wndPtr))
2272     {
2273          /* FIXME: the following optimization is no good for "X-ed" windows */
2274        if (hwndInsertAfter == HWND_TOP)
2275            flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
2276        else /* HWND_BOTTOM */
2277            flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
2278     }
2279
2280       /* Fill the WINDOWPOS structure */
2281
2282     winpos.hwnd = hwnd;
2283     winpos.hwndInsertAfter = hwndInsertAfter;
2284     winpos.x = x;
2285     winpos.y = y;
2286     winpos.cx = cx;
2287     winpos.cy = cy;
2288     winpos.flags = flags;
2289     
2290       /* Send WM_WINDOWPOSCHANGING message */
2291
2292     if (!(winpos.flags & SWP_NOSENDCHANGING))
2293         SendMessageA( hwnd, WM_WINDOWPOSCHANGING, 0, (LPARAM)&winpos );
2294
2295       /* Calculate new position and size */
2296
2297     newWindowRect = wndPtr->rectWindow;
2298     newClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
2299                                                     : wndPtr->rectClient;
2300
2301     if (!(winpos.flags & SWP_NOSIZE))
2302     {
2303         newWindowRect.right  = newWindowRect.left + winpos.cx;
2304         newWindowRect.bottom = newWindowRect.top + winpos.cy;
2305     }
2306     if (!(winpos.flags & SWP_NOMOVE))
2307     {
2308         newWindowRect.left    = winpos.x;
2309         newWindowRect.top     = winpos.y;
2310         newWindowRect.right  += winpos.x - wndPtr->rectWindow.left;
2311         newWindowRect.bottom += winpos.y - wndPtr->rectWindow.top;
2312
2313         OffsetRect( &newClientRect, winpos.x - wndPtr->rectWindow.left, 
2314                                       winpos.y - wndPtr->rectWindow.top );
2315     }
2316
2317     winpos.flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
2318
2319       /* Reposition window in Z order */
2320
2321     if (!(winpos.flags & SWP_NOZORDER))
2322     {
2323         /* reorder owned popups if hwnd is top-level window 
2324          */
2325         if( wndPtr->parent == WIN_GetDesktop() )
2326             hwndInsertAfter = WINPOS_ReorderOwnedPopups( hwndInsertAfter,
2327                                                          wndPtr, winpos.flags );
2328         if (X11DRV_WND_GetXWindow(wndPtr))
2329
2330         {
2331             WIN_UnlinkWindow( winpos.hwnd );
2332             WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
2333         }
2334         else
2335           WINPOS_MoveWindowZOrder( winpos.hwnd, hwndInsertAfter );
2336     }
2337
2338     if ( !X11DRV_WND_GetXWindow(wndPtr) && !(winpos.flags & SWP_NOREDRAW) && 
2339         ((winpos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED)) 
2340                       != (SWP_NOMOVE | SWP_NOSIZE)) )
2341           visRgn = DCE_GetVisRgn(hwnd, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
2342
2343       /* Send WM_NCCALCSIZE message to get new client area */
2344     if( (winpos.flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
2345     {
2346          result = WINPOS_SendNCCalcSize( winpos.hwnd, TRUE, &newWindowRect,
2347                                     &wndPtr->rectWindow, &wndPtr->rectClient,
2348                                     &winpos, &newClientRect );
2349
2350          /* FIXME: WVR_ALIGNxxx */
2351
2352          if( newClientRect.left != wndPtr->rectClient.left ||
2353              newClientRect.top != wndPtr->rectClient.top )
2354              winpos.flags &= ~SWP_NOCLIENTMOVE;
2355
2356          if( (newClientRect.right - newClientRect.left !=
2357               wndPtr->rectClient.right - wndPtr->rectClient.left) ||
2358              (newClientRect.bottom - newClientRect.top !=
2359               wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
2360              winpos.flags &= ~SWP_NOCLIENTSIZE;
2361     }
2362     else
2363       if( !(flags & SWP_NOMOVE) && (newClientRect.left != wndPtr->rectClient.left ||
2364                                     newClientRect.top != wndPtr->rectClient.top) )
2365             winpos.flags &= ~SWP_NOCLIENTMOVE;
2366
2367     /* Update active DCEs 
2368      * TODO: Optimize conditions that trigger DCE update.
2369      */
2370
2371     if( (((winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) && 
2372                                          wndPtr->dwStyle & WS_VISIBLE) || 
2373         (flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)) ) 
2374     {
2375         RECT rect;
2376
2377         UnionRect(&rect, &newWindowRect, &wndPtr->rectWindow);
2378         DCE_InvalidateDCE(wndPtr, &rect);
2379     }
2380
2381     /* change geometry */
2382
2383     oldWindowRect = wndPtr->rectWindow;
2384
2385     if (X11DRV_WND_GetXWindow(wndPtr))
2386     {
2387         RECT oldClientRect = wndPtr->rectClient;
2388
2389         tempInsertAfter = winpos.hwndInsertAfter;
2390
2391         winpos.hwndInsertAfter = hwndInsertAfter;
2392
2393         /* postpone geometry change */
2394
2395         if( !(flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW)) )
2396         {
2397               wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, TRUE);
2398               winpos.hwndInsertAfter = tempInsertAfter;
2399         }
2400         else  uFlags |= SMC_SETXPOS;
2401
2402         wndPtr->rectWindow = newWindowRect;
2403         wndPtr->rectClient = newClientRect;
2404
2405         if( !(flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW)) )
2406         {
2407           if( (oldClientRect.left - oldWindowRect.left !=
2408                newClientRect.left - newWindowRect.left) ||
2409               (oldClientRect.top - oldWindowRect.top !=
2410                newClientRect.top - newWindowRect.top) ||
2411               (winpos.flags & SWP_NOCOPYBITS) )
2412           {
2413               /* if the client area moved as a result of WM_NCCALCSIZE returning 
2414                * obscure WVR_ALIGNxxx flags then we simply redraw the whole thing
2415                *
2416                * TODO: use WINPOS_SizeMoveClean() if there is no SWP_NOCOPYBITS 
2417                */
2418
2419               PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, 0, RDW_INVALIDATE |
2420                               RDW_ALLCHILDREN | RDW_FRAME | RDW_ERASE, 0 );
2421           }
2422           else
2423               if( winpos.flags & SWP_FRAMECHANGED )
2424               {
2425                 WORD wErase = 0;
2426                 RECT rect;
2427
2428                 if( newClientRect.right > oldClientRect.right ) /* redraw exposed client area on the right */
2429                 {
2430                     rect.top = 0; rect.bottom = newClientRect.bottom - newClientRect.top;
2431                     rect.left = oldClientRect.right - newClientRect.left;
2432                     rect.right = newClientRect.right - newClientRect.left;
2433                     wErase = 1;
2434                     PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, 0,
2435                                       RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW | RDW_ALLCHILDREN, 0 );
2436                 }
2437                 if( newClientRect.bottom > oldClientRect.bottom ) /* redraw exposed client area on the bottom */
2438                 {
2439                     rect.left = 0; rect.right = ((wErase)?oldClientRect.right:newClientRect.right) - newClientRect.left;
2440                     rect.top = oldClientRect.bottom - newClientRect.top;
2441                     rect.bottom = newClientRect.bottom - newClientRect.top;
2442                     wErase = 1;
2443                     PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, 0,
2444                                       RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW | RDW_ALLCHILDREN, 0 );
2445                 }
2446                 if( !wErase ) /* just update the nonclient area */
2447                     // the previous command (wndPtr->flags |= WIN_NEEDS_NCPAINT)
2448                     // was not enough. Absolutly need a non client update at this point
2449                     // Cannot wait for the next WM_PAINT message, particularly in the menu-bar redrawing
2450                     WIN_UpdateNCArea(wndPtr,TRUE);
2451               }
2452         }
2453         uFlags |= SMC_NOPARENTERASE; /* X windows do not have eraseable parents */
2454     }
2455     else /* not an X window */
2456     {
2457         RECT oldClientRect = wndPtr->rectClient;
2458
2459         wndPtr->rectWindow = newWindowRect;
2460         wndPtr->rectClient = newClientRect;
2461
2462         if( oldClientRect.bottom - oldClientRect.top ==
2463             newClientRect.bottom - newClientRect.top ) result &= ~WVR_VREDRAW;
2464
2465         if( oldClientRect.right - oldClientRect.left ==
2466             newClientRect.right - newClientRect.left ) result &= ~WVR_HREDRAW;
2467
2468         if( !(flags & (SWP_NOREDRAW | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
2469         {
2470             uFlags |=  ((winpos.flags & SWP_NOCOPYBITS) || 
2471                         (result >= WVR_HREDRAW && result < WVR_VALIDRECTS)) ? SMC_NOCOPY : 0;
2472             uFlags |=  (winpos.flags & SWP_FRAMECHANGED) ? SMC_DRAWFRAME : 0;
2473
2474             if( (winpos.flags & SWP_AGG_NOGEOMETRYCHANGE) != SWP_AGG_NOGEOMETRYCHANGE )
2475                 uFlags = WINPOS_SizeMoveClean(wndPtr, visRgn, &oldWindowRect, 
2476                                                               &oldClientRect, uFlags);
2477             else
2478             { 
2479                 /* adjust the frame and do not erase the parent */
2480
2481                 if( winpos.flags & SWP_FRAMECHANGED ) wndPtr->flags |= WIN_NEEDS_NCPAINT;
2482                 if( winpos.flags & SWP_NOZORDER ) uFlags |= SMC_NOPARENTERASE;
2483             }
2484         }
2485         DeleteObject(visRgn);
2486     }
2487
2488     if (flags & SWP_SHOWWINDOW)
2489     {
2490         wndPtr->dwStyle |= WS_VISIBLE;
2491         if (X11DRV_WND_GetXWindow(wndPtr))
2492         {
2493             HWND focus, curr;
2494
2495             wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, uFlags & SMC_SETXPOS );
2496             if( uFlags & SMC_SETXPOS )
2497             {
2498               winpos.hwndInsertAfter = tempInsertAfter;
2499             }
2500
2501             if (wndPtr->flags & WIN_MANAGED) resync = TRUE;
2502
2503             /* If focus was set to an unmapped window, reset X focus now */
2504             focus = curr = GetFocus();
2505             while (curr) {
2506                 if (curr == hwnd) {
2507                     WND *pFocus = WIN_FindWndPtr( focus );
2508                     if (pFocus)
2509                         pFocus->pDriver->pSetFocus(pFocus);
2510                     break;
2511                 }
2512                 curr = GetParent(curr);
2513             }
2514         }
2515         else
2516         {
2517             if (!(flags & SWP_NOREDRAW))
2518                 PAINT_RedrawWindow( winpos.hwnd, NULL, 0,
2519                                 RDW_INVALIDATE | RDW_ALLCHILDREN |
2520                                 RDW_FRAME | RDW_ERASENOW | RDW_ERASE, 0 );
2521         }
2522     }
2523     else if (flags & SWP_HIDEWINDOW)
2524     {
2525         wndPtr->dwStyle &= ~WS_VISIBLE;
2526         if (X11DRV_WND_GetXWindow(wndPtr))
2527         {
2528             wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, uFlags & SMC_SETXPOS );
2529             if( uFlags & SMC_SETXPOS )
2530             {
2531               winpos.hwndInsertAfter = tempInsertAfter;
2532             }
2533         }
2534         else
2535         {
2536             if (!(flags & SWP_NOREDRAW))
2537                 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, &oldWindowRect,
2538                                     0, RDW_INVALIDATE | RDW_ALLCHILDREN |
2539                                        RDW_ERASE | RDW_ERASENOW, 0 );
2540             uFlags |= SMC_NOPARENTERASE;
2541         }
2542
2543         if (hwnd == CARET_GetHwnd()) DestroyCaret();
2544
2545         /* FIXME: This will cause the window to be activated irrespective
2546          * of whether it is owned by the same thread.
2547          * Should this behaviour be allowed in SetWindowPos?
2548          */
2549         if (winpos.hwnd == hwndActive)
2550             WINPOS_ActivateOtherWindow( wndPtr );
2551     }
2552
2553       /* Activate the window */
2554
2555     if (!(flags & SWP_NOACTIVATE))
2556             WINPOS_ChangeActiveWindow( winpos.hwnd, FALSE );
2557     
2558       /* Repaint the window */
2559
2560     if (X11DRV_WND_GetXWindow(wndPtr))
2561         EVENT_Synchronize();  /* Wait for all expose events */
2562
2563     if (!GetCapture() && ((wndPtr->dwStyle & WS_VISIBLE) || (flags & SWP_HIDEWINDOW)))
2564         EVENT_DummyMotionNotify(); /* Simulate a mouse event to set the cursor */
2565
2566     if (!(flags & SWP_DEFERERASE) && !(uFlags & SMC_NOPARENTERASE) )
2567         PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0, RDW_ALLCHILDREN | RDW_ERASENOW, 0 );
2568     else if( wndPtr->parent == WIN_GetDesktop() && wndPtr->parent->flags & WIN_NEEDS_ERASEBKGND )
2569         PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0, RDW_NOCHILDREN | RDW_ERASENOW, 0 );
2570
2571       /* And last, send the WM_WINDOWPOSCHANGED message */
2572
2573     TRACE(win,"\tstatus flags = %04x\n", winpos.flags & SWP_AGG_STATUSFLAGS);
2574
2575     if ( resync ||
2576         (((winpos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) && 
2577          !(winpos.flags & SWP_NOSENDCHANGING)) )
2578     {
2579         SendMessageA( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
2580         if (resync) EVENT_Synchronize ();
2581     }
2582
2583     return TRUE;
2584 }
2585
2586                                         
2587 /***********************************************************************
2588  *           BeginDeferWindowPos16   (USER.259)
2589  */
2590 HDWP16 WINAPI BeginDeferWindowPos16( INT16 count )
2591 {
2592     return BeginDeferWindowPos( count );
2593 }
2594
2595
2596 /***********************************************************************
2597  *           BeginDeferWindowPos32   (USER32.9)
2598  */
2599 HDWP WINAPI BeginDeferWindowPos( INT count )
2600 {
2601     HDWP handle;
2602     DWP *pDWP;
2603
2604     if (count <= 0) return 0;
2605     handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
2606     if (!handle) return 0;
2607     pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
2608     pDWP->actualCount    = 0;
2609     pDWP->suggestedCount = count;
2610     pDWP->valid          = TRUE;
2611     pDWP->wMagic         = DWP_MAGIC;
2612     pDWP->hwndParent     = 0;
2613     return handle;
2614 }
2615
2616
2617 /***********************************************************************
2618  *           DeferWindowPos16   (USER.260)
2619  */
2620 HDWP16 WINAPI DeferWindowPos16( HDWP16 hdwp, HWND16 hwnd, HWND16 hwndAfter,
2621                                 INT16 x, INT16 y, INT16 cx, INT16 cy,
2622                                 UINT16 flags )
2623 {
2624     return DeferWindowPos( hdwp, hwnd, (INT)(INT16)hwndAfter,
2625                              x, y, cx, cy, flags );
2626 }
2627
2628
2629 /***********************************************************************
2630  *           DeferWindowPos32   (USER32.128)
2631  */
2632 HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter,
2633                                 INT x, INT y, INT cx, INT cy,
2634                                 UINT flags )
2635 {
2636     DWP *pDWP;
2637     int i;
2638     HDWP newhdwp = hdwp;
2639     /* HWND32 parent; */
2640     WND *pWnd;
2641
2642     pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
2643     if (!pDWP) return 0;
2644     if (hwnd == GetDesktopWindow()) return 0;
2645
2646     if (!(pWnd=WIN_FindWndPtr( hwnd ))) {
2647         USER_HEAP_FREE( hdwp );
2648         return 0;
2649     }
2650         
2651 /* Numega Bounds Checker Demo dislikes the following code.
2652    In fact, I've not been able to find any "same parent" requirement in any docu
2653    [AM 980509]
2654  */
2655 #if 0
2656     /* All the windows of a DeferWindowPos() must have the same parent */
2657     parent = pWnd->parent->hwndSelf;
2658     if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
2659     else if (parent != pDWP->hwndParent)
2660     {
2661         USER_HEAP_FREE( hdwp );
2662         return 0;
2663     }
2664 #endif
2665
2666     for (i = 0; i < pDWP->actualCount; i++)
2667     {
2668         if (pDWP->winPos[i].hwnd == hwnd)
2669         {
2670               /* Merge with the other changes */
2671             if (!(flags & SWP_NOZORDER))
2672             {
2673                 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
2674             }
2675             if (!(flags & SWP_NOMOVE))
2676             {
2677                 pDWP->winPos[i].x = x;
2678                 pDWP->winPos[i].y = y;
2679             }                
2680             if (!(flags & SWP_NOSIZE))
2681             {
2682                 pDWP->winPos[i].cx = cx;
2683                 pDWP->winPos[i].cy = cy;
2684             }
2685             pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
2686                                                SWP_NOZORDER | SWP_NOREDRAW |
2687                                                SWP_NOACTIVATE | SWP_NOCOPYBITS|
2688                                                SWP_NOOWNERZORDER);
2689             pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
2690                                               SWP_FRAMECHANGED);
2691             return hdwp;
2692         }
2693     }
2694     if (pDWP->actualCount >= pDWP->suggestedCount)
2695     {
2696         newhdwp = USER_HEAP_REALLOC( hdwp,
2697                       sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
2698         if (!newhdwp) return 0;
2699         pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
2700         pDWP->suggestedCount++;
2701     }
2702     pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
2703     pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
2704     pDWP->winPos[pDWP->actualCount].x = x;
2705     pDWP->winPos[pDWP->actualCount].y = y;
2706     pDWP->winPos[pDWP->actualCount].cx = cx;
2707     pDWP->winPos[pDWP->actualCount].cy = cy;
2708     pDWP->winPos[pDWP->actualCount].flags = flags;
2709     pDWP->actualCount++;
2710     return newhdwp;
2711 }
2712
2713
2714 /***********************************************************************
2715  *           EndDeferWindowPos16   (USER.261)
2716  */
2717 BOOL16 WINAPI EndDeferWindowPos16( HDWP16 hdwp )
2718 {
2719     return EndDeferWindowPos( hdwp );
2720 }
2721
2722
2723 /***********************************************************************
2724  *           EndDeferWindowPos32   (USER32.173)
2725  */
2726 BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
2727 {
2728     DWP *pDWP;
2729     WINDOWPOS *winpos;
2730     BOOL res = TRUE;
2731     int i;
2732
2733     pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
2734     if (!pDWP) return FALSE;
2735     for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
2736     {
2737         if (!(res = SetWindowPos( winpos->hwnd, winpos->hwndInsertAfter,
2738                                     winpos->x, winpos->y, winpos->cx,
2739                                     winpos->cy, winpos->flags ))) break;
2740     }
2741     USER_HEAP_FREE( hdwp );
2742     return res;
2743 }
2744
2745
2746 /***********************************************************************
2747  *           TileChildWindows   (USER.199)
2748  */
2749 void WINAPI TileChildWindows16( HWND16 parent, WORD action )
2750 {
2751     FIXME(win, "(%04x, %d): stub\n", parent, action);
2752 }
2753
2754 /***********************************************************************
2755  *           CascageChildWindows   (USER.198)
2756  */
2757 void WINAPI CascadeChildWindows16( HWND16 parent, WORD action )
2758 {
2759     FIXME(win, "(%04x, %d): stub\n", parent, action);
2760 }
2761 /***********************************************************************
2762  *           GetProgmanWindow                   [USER32.289]
2763  */
2764 HRESULT WINAPI GetProgmanWindow ( )
2765 {       FIXME(win,"stub\n");
2766         return 0;
2767 }
2768 /***********************************************************************
2769  *           GetTaskmanWindow                   [USER32.304]
2770  */
2771 HRESULT WINAPI GetTaskmanWindow ( )
2772 {       FIXME(win,"stub\n");
2773         return 0;
2774 }
2775 /***********************************************************************
2776  *           SetProgmanWindow                   [USER32.522]
2777  */
2778 HRESULT WINAPI SetProgmanWindow ( DWORD x )
2779 {       FIXME(win,"0x%08lx stub\n",x);
2780         return 0;
2781 }
2782 /***********************************************************************
2783  *           SetShellWindowEx                   [USER32.531]
2784  */
2785 HRESULT WINAPI SetShellWindowEx ( DWORD x, DWORD y )
2786 {       FIXME(win,"0x%08lx 0x%08lx stub\n",x,y);
2787         return 0;
2788 }
2789 /***********************************************************************
2790  *           SetTaskmanWindow                   [USER32.537]
2791  */
2792 HRESULT WINAPI SetTaskmanWindow ( DWORD x )
2793 {       FIXME(win,"0x%08lx stub\n",x);
2794         return 0;
2795 }