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