Release 970120
[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 #define NO_TRANSITION_TYPES
9 #include <X11/Xlib.h>
10 #include <X11/Xutil.h>
11 #include <X11/Xatom.h>
12 #include "sysmetrics.h"
13 #include "heap.h"
14 #include "module.h"
15 #include "user.h"
16 #include "win.h"
17 #include "hook.h"
18 #include "message.h"
19 #include "queue.h"
20 #include "options.h"
21 #include "winpos.h"
22 #include "dce.h"
23 #include "nonclient.h"
24 #include "stddebug.h"
25 /* #define DEBUG_WIN */
26 #include "debug.h"
27
28 #define  SWP_AGG_NOGEOMETRYCHANGE \
29     (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
30 #define  SWP_AGG_NOPOSCHANGE \
31     (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
32 #define  SWP_AGG_STATUSFLAGS \
33     (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
34
35 #define SMC_NOCOPY              0x0001
36 #define SMC_NOPARENTERASE       0x0002
37 #define SMC_DRAWFRAME           0x0004
38 #define SMC_SETXPOS             0x0008
39
40 /* ----- external functions ----- */
41
42 extern void     FOCUS_SwitchFocus( HWND32 , HWND32 );
43 extern HRGN32   DCE_GetVisRgn( HWND32, WORD );
44 extern HWND32   CARET_GetHwnd();
45 extern BOOL32   DCE_InvalidateDCE(WND*, RECT16* );
46
47 /* ----- internal variables ----- */
48
49 static HWND32 hwndActive      = 0;  /* Currently active window */
50 static HWND32 hwndPrevActive  = 0;  /* Previously active window */
51
52 extern MESSAGEQUEUE* pActiveQueue;
53
54 /***********************************************************************
55  *           WINPOS_CheckActive
56  */
57 void WINPOS_CheckActive( HWND32 hwnd )
58 {
59   if( hwnd == hwndPrevActive ) hwndPrevActive = 0;
60   if( hwnd == hwndActive )
61   {
62       hwndActive = 0; 
63       dprintf_win(stddeb,"\tattempt to activate destroyed window!\n");
64   }
65 }
66
67 /***********************************************************************
68  *           WINPOS_FindIconPos
69  *
70  * Find a suitable place for an iconic window.
71  * The new position is stored into wndPtr->ptIconPos.
72  */
73 void WINPOS_FindIconPos( HWND32 hwnd )
74 {
75     RECT16 rectParent;
76     short x, y, xspacing, yspacing;
77     WND * wndPtr = WIN_FindWndPtr( hwnd );
78
79     if (!wndPtr || !wndPtr->parent) return;
80     GetClientRect16( wndPtr->parent->hwndSelf, &rectParent );
81     if ((wndPtr->ptIconPos.x >= rectParent.left) &&
82         (wndPtr->ptIconPos.x + SYSMETRICS_CXICON < rectParent.right) &&
83         (wndPtr->ptIconPos.y >= rectParent.top) &&
84         (wndPtr->ptIconPos.y + SYSMETRICS_CYICON < rectParent.bottom))
85         return;  /* The icon already has a suitable position */
86
87     xspacing = yspacing = 70;  /* FIXME: This should come from WIN.INI */
88     y = rectParent.bottom;
89     for (;;)
90     {
91         for (x = rectParent.left; x<=rectParent.right-xspacing; x += xspacing)
92         {
93               /* Check if another icon already occupies this spot */
94             WND *childPtr = wndPtr->parent->child;
95             while (childPtr)
96             {
97                 if ((childPtr->dwStyle & WS_MINIMIZE) && (childPtr != wndPtr))
98                 {
99                     if ((childPtr->rectWindow.left < x + xspacing) &&
100                         (childPtr->rectWindow.right >= x) &&
101                         (childPtr->rectWindow.top <= y) &&
102                         (childPtr->rectWindow.bottom > y - yspacing))
103                         break;  /* There's a window in there */
104                 }
105                 childPtr = childPtr->next;
106             }
107             if (!childPtr)
108             {
109                   /* No window was found, so it's OK for us */
110                 wndPtr->ptIconPos.x = x + (xspacing - SYSMETRICS_CXICON) / 2;
111                 wndPtr->ptIconPos.y = y - (yspacing + SYSMETRICS_CYICON) / 2;
112                 return;
113             }
114         }
115         y -= yspacing;
116     }
117 }
118
119
120 /***********************************************************************
121  *           ArrangeIconicWindows   (USER32.6)
122  */
123 UINT16 ArrangeIconicWindows16( HWND16 parent) {
124     return ArrangeIconicWindows32(parent);
125 }
126 /***********************************************************************
127  *           ArrangeIconicWindows   (USER.170)
128  */
129 UINT32 ArrangeIconicWindows32( HWND32 parent )
130 {
131     RECT32 rectParent;
132     HWND32 hwndChild;
133     INT32 x, y, xspacing, yspacing;
134
135     GetClientRect32( parent, &rectParent );
136     x = rectParent.left;
137     y = rectParent.bottom;
138     xspacing = yspacing = 70;  /* FIXME: This should come from WIN.INI */
139     hwndChild = GetWindow32( parent, GW_CHILD );
140     while (hwndChild)
141     {
142         if (IsIconic32( hwndChild ))
143         {
144             SetWindowPos32( hwndChild, 0, x + (xspacing - SYSMETRICS_CXICON) / 2,
145                             y - (yspacing + SYSMETRICS_CYICON) / 2, 0, 0,
146                             SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE );
147             if (x <= rectParent.right - xspacing) x += xspacing;
148             else
149             {
150                 x = rectParent.left;
151                 y -= yspacing;
152             }
153         }
154         hwndChild = GetWindow32( hwndChild, GW_HWNDNEXT );
155     }
156     return yspacing;
157 }
158
159
160 /***********************************************************************
161  *           GetWindowRect16   (USER.32)
162  */
163 void GetWindowRect16( HWND16 hwnd, LPRECT16 rect ) 
164 {
165     WND * wndPtr = WIN_FindWndPtr( hwnd ); 
166     if (!wndPtr) return;
167     
168     *rect = wndPtr->rectWindow;
169     if (wndPtr->dwStyle & WS_CHILD)
170         MapWindowPoints16( wndPtr->parent->hwndSelf, 0, (POINT16 *)rect, 2 );
171 }
172
173
174 /***********************************************************************
175  *           GetWindowRect32   (USER.32)
176  */
177 void GetWindowRect32( HWND32 hwnd, LPRECT32 rect ) 
178 {
179     WND * wndPtr = WIN_FindWndPtr( hwnd ); 
180     if (!wndPtr) return;
181     
182     CONV_RECT16TO32( &wndPtr->rectWindow, rect );
183     if (wndPtr->dwStyle & WS_CHILD)
184         MapWindowPoints32( wndPtr->parent->hwndSelf, 0, (POINT32 *)rect, 2 );
185 }
186
187
188 /***********************************************************************
189  *           GetClientRect16   (USER.33)
190  */
191 void GetClientRect16( HWND16 hwnd, LPRECT16 rect ) 
192 {
193     WND * wndPtr = WIN_FindWndPtr( hwnd );
194
195     rect->left = rect->top = rect->right = rect->bottom = 0;
196     if (wndPtr) 
197     {
198         rect->right  = wndPtr->rectClient.right - wndPtr->rectClient.left;
199         rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
200     }
201 }
202
203
204 /***********************************************************************
205  *           GetClientRect32   (USER32.219)
206  */
207 void GetClientRect32( HWND32 hwnd, LPRECT32 rect ) 
208 {
209     WND * wndPtr = WIN_FindWndPtr( hwnd );
210
211     rect->left = rect->top = rect->right = rect->bottom = 0;
212     if (wndPtr) 
213     {
214         rect->right  = wndPtr->rectClient.right - wndPtr->rectClient.left;
215         rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
216     }
217 }
218
219
220 /*******************************************************************
221  *         ClientToScreen16   (USER.28)
222  */
223 BOOL16 ClientToScreen16( HWND16 hwnd, LPPOINT16 lppnt )
224 {
225     MapWindowPoints16( hwnd, 0, lppnt, 1 );
226     return TRUE;
227 }
228
229
230 /*******************************************************************
231  *         ClientToScreen32   (USER32.51)
232  */
233 BOOL32 ClientToScreen32( HWND32 hwnd, LPPOINT32 lppnt )
234 {
235     MapWindowPoints32( hwnd, 0, lppnt, 1 );
236     return TRUE;
237 }
238
239
240 /*******************************************************************
241  *         ScreenToClient16   (USER.29)
242  */
243 void ScreenToClient16( HWND16 hwnd, LPPOINT16 lppnt )
244 {
245     MapWindowPoints16( 0, hwnd, lppnt, 1 );
246 }
247
248
249 /*******************************************************************
250  *         ScreenToClient32   (USER32.446)
251  */
252 void ScreenToClient32( HWND32 hwnd, LPPOINT32 lppnt )
253 {
254     MapWindowPoints32( 0, hwnd, lppnt, 1 );
255 }
256
257
258 /***********************************************************************
259  *           WINPOS_WindowFromPoint
260  *
261  * Find the window and hittest for a given point.
262  */
263 INT16 WINPOS_WindowFromPoint( WND* wndScope, POINT16 pt, WND **ppWnd )
264 {
265     WND *wndPtr;
266     INT16 hittest = HTERROR;
267     INT16 x, y;
268
269     *ppWnd = NULL;
270     x = pt.x;
271     y = pt.y;
272     wndPtr = wndScope->child;
273     for (;;)
274     {
275         while (wndPtr)
276         {
277             /* If point is in window, and window is visible, and it  */
278             /* is enabled (or it's a top-level window), then explore */
279             /* its children. Otherwise, go to the next window.       */
280
281             if ((wndPtr->dwStyle & WS_VISIBLE) &&
282                 (!(wndPtr->dwStyle & WS_DISABLED) ||
283                  ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)) &&
284                 (x >= wndPtr->rectWindow.left) &&
285                 (x < wndPtr->rectWindow.right) &&
286                 (y >= wndPtr->rectWindow.top) &&
287                 (y < wndPtr->rectWindow.bottom))
288             {
289                 *ppWnd = wndPtr;  /* Got a suitable window */
290
291                 /* If window is minimized or disabled, return at once */
292                 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
293                 if (wndPtr->dwStyle & WS_DISABLED) return HTERROR;
294
295                 /* If point is not in client area, ignore the children */
296                 if ((x < wndPtr->rectClient.left) ||
297                     (x >= wndPtr->rectClient.right) ||
298                     (y < wndPtr->rectClient.top) ||
299                     (y >= wndPtr->rectClient.bottom)) break;
300
301                 x -= wndPtr->rectClient.left;
302                 y -= wndPtr->rectClient.top;
303                 wndPtr = wndPtr->child;
304             }
305             else wndPtr = wndPtr->next;
306         }
307
308         /* If nothing found, return the scope window */
309         if (!*ppWnd)
310         {
311             *ppWnd = wndScope;
312             if( pt.x >= (wndScope->rectClient.left - wndScope->rectWindow.left) &&
313                 pt.x >= (wndScope->rectClient.top - wndScope->rectWindow.top ) &&
314                 pt.x <= (wndScope->rectClient.right - wndScope->rectWindow.left) &&
315                 pt.x <= (wndScope->rectClient.bottom - wndScope->rectWindow.top ) )
316                 return HTCLIENT;
317             if( pt.x < 0 || pt.y < 0 || 
318                 pt.x > (wndScope->rectWindow.right - wndScope->rectWindow.left) ||
319                 pt.y > (wndScope->rectWindow.bottom - wndScope->rectWindow.top ) )
320                 return HTNOWHERE;
321             return HTCAPTION;   /* doesn't matter in this case */
322         }
323
324         /* Send the WM_NCHITTEST message (only if to the same task) */
325         if ((*ppWnd)->hmemTaskQ != GetTaskQueue(0)) return HTCLIENT;
326         hittest = (INT16)SendMessage16( (*ppWnd)->hwndSelf, WM_NCHITTEST, 0,
327                                     MAKELONG( pt.x, pt.y ) );
328         if (hittest != HTTRANSPARENT) return hittest;  /* Found the window */
329
330         /* If no children found in last search, make point relative to parent*/
331         if (!wndPtr)
332         {
333             x += (*ppWnd)->rectClient.left;
334             y += (*ppWnd)->rectClient.top;
335         }
336
337         /* Restart the search from the next sibling */
338         wndPtr = (*ppWnd)->next;
339         *ppWnd = (*ppWnd)->parent;
340     }
341 }
342
343
344 /*******************************************************************
345  *         WindowFromPoint16   (USER.30)
346  */
347 HWND16  WindowFromPoint16( POINT16 pt )
348 {
349     WND *pWnd;
350     WINPOS_WindowFromPoint( WIN_GetDesktop(), pt, &pWnd );
351     return pWnd->hwndSelf;
352 }
353
354
355 /*******************************************************************
356  *         WindowFromPoint32   (USER32.581)
357  */
358 HWND32 WindowFromPoint32( POINT32 pt )
359 {
360     WND *pWnd;
361     POINT16 pt16;
362     CONV_POINT32TO16( &pt, &pt16 );
363     WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16, &pWnd );
364     return (HWND32)pWnd->hwndSelf;
365 }
366
367
368 /*******************************************************************
369  *         ChildWindowFromPoint16   (USER.191)
370  */
371 HWND16 ChildWindowFromPoint16( HWND16 hwndParent, POINT16 pt )
372 {
373     /* pt is in the client coordinates */
374
375     WND* wnd = WIN_FindWndPtr(hwndParent);
376     RECT16 rect;
377
378     if( !wnd ) return 0;
379
380     /* get client rect fast */
381     rect.top = rect.left = 0;
382     rect.right = wnd->rectClient.right - wnd->rectClient.left;
383     rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
384
385     if (!PtInRect16( &rect, pt )) return 0;
386
387     wnd = wnd->child;
388     while ( wnd )
389     {
390         if (PtInRect16( &wnd->rectWindow, pt )) return wnd->hwndSelf;
391         wnd = wnd->next;
392     }
393     return hwndParent;
394 }
395
396
397 /*******************************************************************
398  *         ChildWindowFromPoint32   (USER32.)
399  */
400 HWND32 ChildWindowFromPoint32( HWND32 hwndParent, POINT32 pt )
401 {
402     POINT16 pt16;
403     CONV_POINT32TO16( &pt, &pt16 );
404     return (HWND32)ChildWindowFromPoint16( hwndParent, pt16 );
405 }
406
407
408 /*******************************************************************
409  *         WINPOS_GetWinOffset
410  *
411  * Calculate the offset between the origin of the two windows. Used
412  * to implement MapWindowPoints.
413  */
414 static void WINPOS_GetWinOffset( HWND32 hwndFrom, HWND32 hwndTo,
415                                  POINT32 *offset )
416 {
417     WND * wndPtr;
418
419     offset->x = offset->y = 0;
420     if (hwndFrom == hwndTo ) return;
421
422       /* Translate source window origin to screen coords */
423     if (hwndFrom)
424     {
425         if (!(wndPtr = WIN_FindWndPtr( hwndFrom )))
426         {
427             fprintf(stderr,"MapWindowPoints: bad hwndFrom = %04x\n",hwndFrom);
428             return;
429         }
430         while (wndPtr->parent)
431         {
432             offset->x += wndPtr->rectClient.left;
433             offset->y += wndPtr->rectClient.top;
434             wndPtr = wndPtr->parent;
435         }
436     }
437
438       /* Translate origin to destination window coords */
439     if (hwndTo)
440     {
441         if (!(wndPtr = WIN_FindWndPtr( hwndTo )))
442         {
443             fprintf(stderr,"MapWindowPoints: bad hwndTo = %04x\n", hwndTo );
444             return;
445         }
446         while (wndPtr->parent)
447         {
448             offset->x -= wndPtr->rectClient.left;
449             offset->y -= wndPtr->rectClient.top;
450             wndPtr = wndPtr->parent;
451         }    
452     }
453 }
454
455
456 /*******************************************************************
457  *         MapWindowPoints16   (USER.258)
458  */
459 void MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
460                         LPPOINT16 lppt, UINT16 count )
461 {
462     POINT32 offset;
463
464     WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
465     while (count--)
466     {
467         lppt->x += offset.x;
468         lppt->y += offset.y;
469         lppt++;
470     }
471 }
472
473
474 /*******************************************************************
475  *         MapWindowPoints32   (USER32.385)
476  */
477 void MapWindowPoints32( HWND32 hwndFrom, HWND32 hwndTo,
478                         LPPOINT32 lppt, UINT32 count )
479 {
480     POINT32 offset;
481
482     WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
483     while (count--)
484     {
485         lppt->x += offset.x;
486         lppt->y += offset.y;
487         lppt++;
488     }
489 }
490
491
492 /***********************************************************************
493  *           IsIconic   (USER.31)
494  */
495 BOOL16 IsIconic16(HWND16 hWnd)
496 {
497     return IsIconic32(hWnd);
498 }
499 /***********************************************************************
500  *           IsIconic   (USER32.344)
501  */
502 BOOL32 IsIconic32(HWND32 hWnd)
503 {
504     WND * wndPtr = WIN_FindWndPtr(hWnd);
505     if (wndPtr == NULL) return FALSE;
506     return (wndPtr->dwStyle & WS_MINIMIZE) != 0;
507 }
508  
509  
510 /***********************************************************************
511  *           IsZoomed   (USER.272)
512  */
513 BOOL16 IsZoomed16(HWND16 hWnd)
514 {
515     return IsZoomed32(hWnd);
516 }
517 /***********************************************************************
518  *           IsZoomed   (USER32.351)
519  */
520 BOOL32 IsZoomed32(HWND32 hWnd)
521 {
522     WND * wndPtr = WIN_FindWndPtr(hWnd);
523     if (wndPtr == NULL) return FALSE;
524     return (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
525 }
526
527
528 /*******************************************************************
529  *         GetActiveWindow    (USER.60)
530  */
531 HWND16 GetActiveWindow16(void)
532 {
533     return GetActiveWindow32();
534 }
535 /*******************************************************************
536  *         GetActiveWindow    (USER32.204)
537  */
538 HWND32 GetActiveWindow32(void)
539 {
540     return hwndActive;
541 }
542
543
544 /*******************************************************************
545  *         WINPOS_IsGoodEnough
546  */
547 static BOOL32 WINPOS_IsGoodEnough(WND* pWnd)
548 {
549  return (pWnd) ? ((!(pWnd->dwStyle & WS_DISABLED) &&
550                      pWnd->dwStyle & WS_VISIBLE ) ? TRUE : FALSE) : FALSE;
551 }
552
553
554 /*******************************************************************
555  *         SetActiveWindow    (USER.59)
556  */
557 HWND16 SetActiveWindow16( HWND16 hwnd )
558 {
559     return SetActiveWindow32(hwnd);
560 }
561 /*******************************************************************
562  *         SetActiveWindow    (USER.59)
563  */
564 HWND32 SetActiveWindow32( HWND32 hwnd )
565 {
566     HWND32 prev = hwndActive;
567     WND *wndPtr = WIN_FindWndPtr( hwnd );
568
569     if ( !WINPOS_IsGoodEnough(wndPtr) ) return 0;
570
571     WINPOS_SetActiveWindow( hwnd, 0, 0 );
572     return prev;
573 }
574
575
576 /***********************************************************************
577  *           BringWindowToTop   (USER.45)
578  */
579 BOOL16 BringWindowToTop16( HWND16 hwnd )
580 {
581     return BringWindowToTop32(hwnd);
582 }
583 /***********************************************************************
584  *           BringWindowToTop   (USER32.10)
585  */
586 BOOL32 BringWindowToTop32( HWND32 hwnd )
587 {
588     return SetWindowPos32( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
589 }
590
591
592 /***********************************************************************
593  *           MoveWindow   (USER.56)
594  */
595 BOOL16 MoveWindow16(
596         HWND16 hwnd, INT16 x, INT16 y, INT16 cx, INT16 cy, BOOL16 repaint
597 ) {
598     return MoveWindow32(hwnd,x,y,cx,cy,repaint);
599 }
600 /***********************************************************************
601  *           MoveWindow   (USER32.398)
602  */
603 BOOL32 MoveWindow32(
604         HWND32 hwnd, INT32 x, INT32 y, INT32 cx, INT32 cy, BOOL32 repaint
605 ) {    
606     int flags = SWP_NOZORDER | SWP_NOACTIVATE;
607     if (!repaint) flags |= SWP_NOREDRAW;
608     dprintf_win(stddeb, "MoveWindow: %04x %d,%d %dx%d %d\n", 
609             hwnd, x, y, cx, cy, repaint );
610     return SetWindowPos32( hwnd, 0, x, y, cx, cy, flags );
611 }
612
613 /***********************************************************************
614  *           ShowWindow   (USER.42)
615  */
616 BOOL16 ShowWindow16( HWND16 hwnd, INT16 cmd ) 
617 {    
618     return ShowWindow32(hwnd,cmd);
619 }
620 /***********************************************************************
621  *           ShowWindow   (USER.42)
622  */
623 BOOL32 ShowWindow32( HWND32 hwnd, INT32 cmd ) 
624 {    
625     WND * wndPtr = WIN_FindWndPtr( hwnd );
626     BOOL32 wasVisible, showFlag;
627     POINT16 maxSize;
628     int swpflags = 0;
629     short x = 0, y = 0, cx = 0, cy = 0;
630
631     if (!wndPtr) return FALSE;
632
633     dprintf_win(stddeb,"ShowWindow: hwnd=%04x, cmd=%d\n", hwnd, cmd);
634
635     wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
636
637     switch(cmd)
638     {
639         case SW_HIDE:
640             if (!wasVisible) return FALSE;
641             swpflags |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | 
642                         SWP_NOACTIVATE | SWP_NOZORDER;
643             break;
644
645         case SW_SHOWMINNOACTIVE:
646             swpflags |= SWP_NOACTIVATE | SWP_NOZORDER;
647             /* fall through */
648         case SW_SHOWMINIMIZED:
649             swpflags |= SWP_SHOWWINDOW;
650             /* fall through */
651         case SW_MINIMIZE:
652             swpflags |= SWP_FRAMECHANGED;
653             if (!(wndPtr->dwStyle & WS_MINIMIZE))
654             {
655                 if( HOOK_CallHooks16( WH_CBT, HCBT_MINMAX, hwnd, cmd) )
656                     return 0;
657
658                 if (wndPtr->dwStyle & WS_MAXIMIZE)
659                 {
660                     wndPtr->flags |= WIN_RESTORE_MAX;
661                     wndPtr->dwStyle &= ~WS_MAXIMIZE;
662                 }
663                 else
664                 {
665                     wndPtr->flags &= ~WIN_RESTORE_MAX;
666                     wndPtr->rectNormal = wndPtr->rectWindow;
667                 }
668                 wndPtr->dwStyle |= WS_MINIMIZE;
669                 WINPOS_FindIconPos( hwnd );
670                 x  = wndPtr->ptIconPos.x;
671                 y  = wndPtr->ptIconPos.y;
672                 cx = SYSMETRICS_CXICON;
673                 cy = SYSMETRICS_CYICON;
674                 swpflags |= SWP_NOCOPYBITS;
675             }
676             else swpflags |= SWP_NOSIZE | SWP_NOMOVE;
677             break;
678
679         case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE: */
680             swpflags |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
681             if (!(wndPtr->dwStyle & WS_MAXIMIZE))
682             {
683                 if( HOOK_CallHooks16( WH_CBT, HCBT_MINMAX, hwnd, cmd) )
684                     return 0;
685
686                   /* Store the current position and find the maximized size */
687                 if (!(wndPtr->dwStyle & WS_MINIMIZE))
688                     wndPtr->rectNormal = wndPtr->rectWindow; 
689
690                 NC_GetMinMaxInfo( wndPtr, &maxSize,
691                                   &wndPtr->ptMaxPos, NULL, NULL );
692                 x  = wndPtr->ptMaxPos.x;
693                 y  = wndPtr->ptMaxPos.y;
694
695                 if( wndPtr->dwStyle & WS_MINIMIZE )
696                     if( !SendMessage32A( hwnd, WM_QUERYOPEN, 0, 0L ) )
697                         {
698                          swpflags |= SWP_NOSIZE | SWP_NOMOVE;
699                          break;
700                         }
701                     else swpflags |= SWP_NOCOPYBITS;
702
703                 cx = maxSize.x;
704                 cy = maxSize.y;
705                 wndPtr->dwStyle &= ~WS_MINIMIZE;
706                 wndPtr->dwStyle |= WS_MAXIMIZE;
707             }
708             else swpflags |= SWP_NOSIZE | SWP_NOMOVE;
709             break;
710
711         case SW_SHOWNA:
712             swpflags |= SWP_NOACTIVATE | SWP_NOZORDER;
713             /* fall through */
714         case SW_SHOW:
715             swpflags |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
716             break;
717
718         case SW_SHOWNOACTIVATE:
719             swpflags |= SWP_NOZORDER;
720             if (GetActiveWindow32()) swpflags |= SWP_NOACTIVATE;
721             /* fall through */
722         case SW_SHOWNORMAL:  /* same as SW_NORMAL: */
723         case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
724         case SW_RESTORE:
725             swpflags |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
726
727             if (wndPtr->dwStyle & WS_MINIMIZE)
728             {
729                 if( HOOK_CallHooks16( WH_CBT, HCBT_MINMAX, hwnd, cmd) )
730                     return 0;
731
732                 if( !SendMessage16( hwnd, WM_QUERYOPEN, 0, 0L) )
733                   {
734                     swpflags |= SWP_NOSIZE | SWP_NOMOVE;
735                     break;
736                   }
737                 wndPtr->ptIconPos.x = wndPtr->rectWindow.left;
738                 wndPtr->ptIconPos.y = wndPtr->rectWindow.top;
739                 wndPtr->dwStyle &= ~WS_MINIMIZE;
740                 if (wndPtr->flags & WIN_RESTORE_MAX)
741                 {
742                     /* Restore to maximized position */
743                     NC_GetMinMaxInfo( wndPtr, &maxSize, &wndPtr->ptMaxPos,
744                                       NULL, NULL );
745                     x  = wndPtr->ptMaxPos.x;
746                     y  = wndPtr->ptMaxPos.y;
747                     cx = maxSize.x;
748                     cy = maxSize.y;
749                    wndPtr->dwStyle |= WS_MAXIMIZE;
750                 }
751                 else  /* Restore to normal position */
752                 {
753                     x  = wndPtr->rectNormal.left;
754                     y  = wndPtr->rectNormal.top;
755                     cx = wndPtr->rectNormal.right - wndPtr->rectNormal.left;
756                     cy = wndPtr->rectNormal.bottom - wndPtr->rectNormal.top;
757                 }
758                 swpflags |= SWP_NOCOPYBITS;
759             }
760             else if (wndPtr->dwStyle & WS_MAXIMIZE)
761             {
762                 if( HOOK_CallHooks16( WH_CBT, HCBT_MINMAX, hwnd, cmd) )
763                     return 0;
764
765                 wndPtr->ptMaxPos.x = wndPtr->rectWindow.left;
766                 wndPtr->ptMaxPos.y = wndPtr->rectWindow.top;
767                 wndPtr->dwStyle &= ~WS_MAXIMIZE;
768                 x  = wndPtr->rectNormal.left;
769                 y  = wndPtr->rectNormal.top;
770                 cx = wndPtr->rectNormal.right - wndPtr->rectNormal.left;
771                 cy = wndPtr->rectNormal.bottom - wndPtr->rectNormal.top;
772             }
773             else swpflags |= SWP_NOSIZE | SWP_NOMOVE;
774             break;
775     }
776
777     showFlag = (cmd != SW_HIDE);
778     if (showFlag != wasVisible)
779     {
780         SendMessage16( hwnd, WM_SHOWWINDOW, showFlag, 0 );
781         if (!IsWindow( hwnd )) return wasVisible;
782     }
783
784     if ((wndPtr->dwStyle & WS_CHILD) &&
785         !IsWindowVisible32( wndPtr->parent->hwndSelf ) &&
786         (swpflags & SWP_NOSIZE) && (swpflags & SWP_NOMOVE))
787     {
788         /* Don't call SetWindowPos32() on invisible child windows */
789         if (cmd == SW_HIDE) wndPtr->dwStyle &= ~WS_VISIBLE;
790         else wndPtr->dwStyle |= WS_VISIBLE;
791     }
792     else
793     {
794         /* We can't activate a child window */
795         if (wndPtr->dwStyle & WS_CHILD)
796             swpflags |= SWP_NOACTIVATE | SWP_NOZORDER;
797         SetWindowPos32( hwnd, HWND_TOP, x, y, cx, cy, swpflags );
798         if (!IsWindow( hwnd )) return wasVisible;
799     }
800
801     if (wndPtr->flags & WIN_NEED_SIZE)
802     {
803         /* should happen only in CreateWindowEx() */
804         int wParam = SIZE_RESTORED;
805
806         wndPtr->flags &= ~WIN_NEED_SIZE;
807         if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
808         else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
809         SendMessage16( hwnd, WM_SIZE, wParam,
810                      MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
811                             wndPtr->rectClient.bottom-wndPtr->rectClient.top));
812         SendMessage16( hwnd, WM_MOVE, 0,
813                    MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
814     }
815
816     return wasVisible;
817 }
818
819
820 /***********************************************************************
821  *           GetInternalWindowPos16   (USER.460)
822  */
823 UINT16 GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd, LPPOINT16 ptIcon)
824 {
825     WINDOWPLACEMENT16 wndpl;
826     if (!GetWindowPlacement16( hwnd, &wndpl )) return 0;
827     if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
828     if (ptIcon)  *ptIcon = wndpl.ptMinPosition;
829     return wndpl.showCmd;
830 }
831
832
833 /***********************************************************************
834  *           GetInternalWindowPos32   (USER32.244)
835  */
836 UINT32 GetInternalWindowPos32( HWND32 hwnd, LPRECT32 rectWnd, LPPOINT32 ptIcon)
837 {
838     WINDOWPLACEMENT32 wndpl;
839     if (!GetWindowPlacement32( hwnd, &wndpl )) return 0;
840     if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
841     if (ptIcon)  *ptIcon = wndpl.ptMinPosition;
842     return wndpl.showCmd;
843 }
844
845
846 /***********************************************************************
847  *           SetInternalWindowPos16   (USER.461)
848  */
849 void SetInternalWindowPos16( HWND16 hwnd, UINT16 showCmd,
850                              LPRECT16 rect, LPPOINT16 pt )
851 {
852     WINDOWPLACEMENT16 wndpl;
853     WND *wndPtr = WIN_FindWndPtr( hwnd );
854
855     wndpl.length  = sizeof(wndpl);
856     wndpl.flags   = (pt != NULL) ? WPF_SETMINPOSITION : 0;
857     wndpl.showCmd = showCmd;
858     if (pt) wndpl.ptMinPosition = *pt;
859     wndpl.rcNormalPosition = (rect != NULL) ? *rect : wndPtr->rectNormal;
860     wndpl.ptMaxPosition = wndPtr->ptMaxPos;
861     SetWindowPlacement16( hwnd, &wndpl );
862 }
863
864
865 /***********************************************************************
866  *           SetInternalWindowPos32   (USER32.482)
867  */
868 void SetInternalWindowPos32( HWND32 hwnd, UINT32 showCmd,
869                              LPRECT32 rect, LPPOINT32 pt )
870 {
871     WINDOWPLACEMENT32 wndpl;
872     WND *wndPtr = WIN_FindWndPtr( hwnd );
873
874     wndpl.length  = sizeof(wndpl);
875     wndpl.flags   = (pt != NULL) ? WPF_SETMINPOSITION : 0;
876     wndpl.showCmd = showCmd;
877     if (pt) wndpl.ptMinPosition = *pt;
878     if (rect) wndpl.rcNormalPosition = *rect;
879     else CONV_RECT16TO32( &wndPtr->rectNormal, &wndpl.rcNormalPosition );
880     CONV_POINT16TO32( &wndPtr->ptMaxPos, &wndpl.ptMaxPosition );
881     SetWindowPlacement32( hwnd, &wndpl );
882 }
883
884
885 /***********************************************************************
886  *           GetWindowPlacement16   (USER.370)
887  */
888 BOOL16 GetWindowPlacement16( HWND16 hwnd, WINDOWPLACEMENT16 *wndpl )
889 {
890     WND *wndPtr = WIN_FindWndPtr( hwnd );
891     if (!wndPtr) return FALSE;
892
893     wndpl->length  = sizeof(*wndpl);
894     wndpl->flags   = 0;
895     wndpl->showCmd = IsZoomed16(hwnd) ? SW_SHOWMAXIMIZED : 
896                      (IsIconic16(hwnd) ? SW_SHOWMINIMIZED : SW_SHOWNORMAL);
897     wndpl->ptMinPosition = wndPtr->ptIconPos;
898     wndpl->ptMaxPosition = wndPtr->ptMaxPos;
899     wndpl->rcNormalPosition = wndPtr->rectNormal;
900     return TRUE;
901 }
902
903
904 /***********************************************************************
905  *           GetWindowPlacement32   (USER32.306)
906  */
907 BOOL32 GetWindowPlacement32( HWND32 hwnd, WINDOWPLACEMENT32 *wndpl )
908 {
909     WND *wndPtr = WIN_FindWndPtr( hwnd );
910     if (!wndPtr) return FALSE;
911
912     wndpl->length  = sizeof(*wndpl);
913     wndpl->flags   = 0;
914     wndpl->showCmd = IsZoomed32(hwnd) ? SW_SHOWMAXIMIZED : 
915                      (IsIconic32(hwnd) ? SW_SHOWMINIMIZED : SW_SHOWNORMAL);
916     CONV_POINT16TO32( &wndPtr->ptIconPos, &wndpl->ptMinPosition );
917     CONV_POINT16TO32( &wndPtr->ptMaxPos, &wndpl->ptMaxPosition );
918     CONV_RECT16TO32( &wndPtr->rectNormal, &wndpl->rcNormalPosition );
919     return TRUE;
920 }
921
922
923 /***********************************************************************
924  *           SetWindowPlacement16   (USER.371)
925  */
926 BOOL16 SetWindowPlacement16( HWND16 hwnd, const WINDOWPLACEMENT16 *wndpl )
927 {
928     WND *wndPtr = WIN_FindWndPtr( hwnd );
929     if (!wndPtr) return FALSE;
930
931     if (wndpl->flags & WPF_SETMINPOSITION)
932         wndPtr->ptIconPos = wndpl->ptMinPosition;
933     if ((wndpl->flags & WPF_RESTORETOMAXIMIZED) &&
934         (wndpl->showCmd == SW_SHOWMINIMIZED)) wndPtr->flags |= WIN_RESTORE_MAX;
935     wndPtr->ptMaxPos   = wndpl->ptMaxPosition;
936     wndPtr->rectNormal = wndpl->rcNormalPosition;
937     ShowWindow16( hwnd, wndpl->showCmd );
938     return TRUE;
939 }
940
941
942 /***********************************************************************
943  *           SetWindowPlacement32   (USER32.518)
944  */
945 BOOL32 SetWindowPlacement32( HWND32 hwnd, const WINDOWPLACEMENT32 *wndpl )
946 {
947     WND *wndPtr = WIN_FindWndPtr( hwnd );
948     if (!wndPtr) return FALSE;
949
950     if (wndpl->flags & WPF_SETMINPOSITION)
951         CONV_POINT32TO16( &wndpl->ptMinPosition, &wndPtr->ptIconPos );
952     if ((wndpl->flags & WPF_RESTORETOMAXIMIZED) &&
953         (wndpl->showCmd == SW_SHOWMINIMIZED)) wndPtr->flags |= WIN_RESTORE_MAX;
954     CONV_POINT32TO16( &wndpl->ptMaxPosition, &wndPtr->ptMaxPos );
955     CONV_RECT32TO16( &wndpl->rcNormalPosition, &wndPtr->rectNormal );
956     ShowWindow32( hwnd, wndpl->showCmd );
957     return TRUE;
958 }
959
960
961 /***********************************************************************
962  *           WINPOS_ForceXWindowRaise
963  *
964  * Raise a window on top of the X stacking order, while preserving 
965  * the correct Windows Z order.
966  */
967 static void WINPOS_ForceXWindowRaise( WND* pWnd )
968 {
969     XWindowChanges winChanges;
970     WND *wndPrev;
971
972     /* Raise all windows up to pWnd according to their Z order.
973      * (it would be easier with sibling-related Below but it doesn't
974      * work very well with SGI mwm for instance)
975      */
976     winChanges.stack_mode = Above;
977     while (pWnd)
978     {
979         if (pWnd->window) XReconfigureWMWindow( display, pWnd->window, 0,
980                                                 CWStackMode, &winChanges );
981         wndPrev = WIN_GetDesktop()->child;
982         if (wndPrev == pWnd) break;
983         while (wndPrev && (wndPrev->next != pWnd)) wndPrev = wndPrev->next;
984         pWnd = wndPrev;
985     }
986 }
987
988
989 /*******************************************************************
990  *         WINPOS_SetActiveWindow
991  *
992  * back-end to SetActiveWindow
993  */
994 BOOL32 WINPOS_SetActiveWindow( HWND32 hWnd, BOOL32 fMouse, BOOL32 fChangeFocus)
995 {
996     WND                   *wndPtr          = WIN_FindWndPtr(hWnd);
997     WND                   *wndTemp         = WIN_FindWndPtr(hwndActive);
998     CBTACTIVATESTRUCT16   *cbtStruct;
999     WORD                   wIconized=0;
1000     HQUEUE16 hOldActiveQueue = (pActiveQueue)?pActiveQueue->self:0;
1001     HQUEUE16 hNewActiveQueue;
1002
1003     /* paranoid checks */
1004     if( hWnd == GetDesktopWindow32() || hWnd == hwndActive )
1005         return 0;
1006
1007 /* if (wndPtr && (GetTaskQueue(0) != wndPtr->hmemTaskQ))
1008         return 0;
1009         */
1010
1011     if( wndTemp )
1012         wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1013     else
1014         dprintf_win(stddeb,"WINPOS_ActivateWindow: no current active window.\n");
1015
1016     /* call CBT hook chain */
1017     if ((cbtStruct = SEGPTR_NEW(CBTACTIVATESTRUCT16)))
1018     {
1019         LRESULT wRet;
1020         cbtStruct->fMouse     = fMouse;
1021         cbtStruct->hWndActive = hwndActive;
1022         wRet = HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
1023                                  (LPARAM)SEGPTR_GET(cbtStruct) );
1024         SEGPTR_FREE(cbtStruct);
1025         if (wRet) return wRet;
1026     }
1027
1028     /* set prev active wnd to current active wnd and send notification */
1029     if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
1030     {
1031         if (!SendMessage16( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1032         {
1033             if (GetSysModalWindow16() != hWnd) return 0;
1034             /* disregard refusal if hWnd is sysmodal */
1035         }
1036
1037         SendMessage32A( hwndPrevActive, WM_ACTIVATE,
1038                         MAKEWPARAM( WA_INACTIVE, wIconized ),
1039                         (LPARAM)hWnd );
1040
1041         /* check if something happened during message processing */
1042         if( hwndPrevActive != hwndActive ) return 0;
1043     }
1044
1045     /* set active wnd */
1046     hwndActive = hWnd;
1047
1048     /* send palette messages */
1049     if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1050         SendMessage16((HWND16)-1, WM_PALETTEISCHANGING, (WPARAM16)hWnd, 0L );
1051
1052     /* if prev wnd is minimized redraw icon title 
1053   if( hwndPrevActive )
1054     {
1055         wndTemp = WIN_FindWndPtr( WIN_GetTopParent( hwndPrevActive ) );
1056         if(wndTemp)
1057           if(wndTemp->dwStyle & WS_MINIMIZE)
1058             RedrawIconTitle(hwndPrevActive); 
1059       } 
1060   */
1061
1062     /* managed windows will get ConfigureNotify event */  
1063     if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->flags & WIN_MANAGED))
1064     {
1065         /* check Z-order and bring hWnd to the top */
1066         for (wndTemp = WIN_GetDesktop()->child; wndTemp; wndTemp = wndTemp->next)
1067             if (wndTemp->dwStyle & WS_VISIBLE) break;
1068
1069         if( wndTemp != wndPtr )
1070             SetWindowPos32(hWnd, HWND_TOP, 0,0,0,0, 
1071                            SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1072         if( !IsWindow(hWnd) ) return 0;
1073     }
1074
1075     hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1076
1077     /* send WM_ACTIVATEAPP if necessary */
1078     if (hOldActiveQueue != hNewActiveQueue)
1079     {
1080         WND **list, **ppWnd;
1081
1082         if ((list = WIN_BuildWinArray( WIN_GetDesktop() )))
1083         {
1084             for (ppWnd = list; *ppWnd; ppWnd++)
1085             {
1086                 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1087
1088                 if ((*ppWnd)->hmemTaskQ == hOldActiveQueue)
1089                    SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1090                                    0, QUEUE_GetQueueTask(hNewActiveQueue) );
1091             }
1092             HeapFree( SystemHeap, 0, list );
1093         }
1094
1095         pActiveQueue = (hNewActiveQueue)
1096                        ? (MESSAGEQUEUE*) GlobalLock16(hNewActiveQueue) : NULL;
1097
1098         if ((list = WIN_BuildWinArray( WIN_GetDesktop() )))
1099         {
1100             for (ppWnd = list; *ppWnd; ppWnd++)
1101             {
1102                 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1103
1104                 if ((*ppWnd)->hmemTaskQ == hNewActiveQueue)
1105                    SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1106                                   1, QUEUE_GetQueueTask( hOldActiveQueue ) );
1107             }
1108             HeapFree( SystemHeap, 0, list );
1109         }
1110         if (!IsWindow(hWnd)) return 0;
1111     }
1112
1113     if (hWnd)
1114     {
1115         /* walk up to the first unowned window */
1116         wndTemp = wndPtr;
1117         while (wndTemp->owner) wndTemp = wndTemp->owner;
1118         /* and set last active owned popup */
1119         wndTemp->hwndLastActive = hWnd;
1120
1121         wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1122         SendMessage16( hWnd, WM_NCACTIVATE, TRUE, 0 );
1123         SendMessage32A( hWnd, WM_ACTIVATE,
1124                  MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1125                  (LPARAM)hwndPrevActive );
1126
1127         if( !IsWindow(hWnd) ) return 0;
1128     }
1129
1130     /* change focus if possible */
1131     if( fChangeFocus && GetFocus32() )
1132         if( WIN_GetTopParent(GetFocus32()) != hwndActive )
1133             FOCUS_SwitchFocus( GetFocus32(),
1134                                (wndPtr->dwStyle & WS_MINIMIZE)? 0: hwndActive);
1135
1136     if( !hwndPrevActive && wndPtr && 
1137          wndPtr->window && !(wndPtr->flags & WIN_MANAGED) )
1138         WINPOS_ForceXWindowRaise(wndPtr);
1139
1140     /* if active wnd is minimized redraw icon title 
1141   if( hwndActive )
1142       {
1143         wndPtr = WIN_FindWndPtr(hwndActive);
1144         if(wndPtr->dwStyle & WS_MINIMIZE)
1145            RedrawIconTitle(hwndActive);
1146     }
1147   */
1148     return (hWnd == hwndActive);
1149 }
1150
1151 /*******************************************************************
1152  *         WINPOS_ActivateOtherWindow
1153  *
1154  * DestroyWindow() helper. pWnd must be a top-level window.
1155  */
1156 BOOL32 WINPOS_ActivateOtherWindow(WND* pWnd)
1157 {
1158   BOOL32        bRet = 0;
1159   WND*          pWndTo = NULL;
1160
1161   if( pWnd->hwndSelf == hwndPrevActive )
1162       hwndPrevActive = 0;
1163
1164   if( hwndActive != pWnd->hwndSelf && 
1165     ( hwndActive || QUEUE_IsDoomedQueue(pWnd->hmemTaskQ)) )
1166       return 0;
1167
1168   if( pWnd->dwStyle & WS_POPUP &&
1169       WINPOS_IsGoodEnough( pWnd->owner ) ) pWndTo = pWnd->owner;
1170   else
1171   {
1172     WND* pWndPtr = pWnd;
1173
1174     pWndTo = WIN_FindWndPtr(hwndPrevActive);
1175
1176     while( !WINPOS_IsGoodEnough(pWndTo) ) 
1177     {
1178       /* by now owned windows should've been taken care of */
1179
1180       pWndTo = pWndPtr->next;
1181       pWndPtr = pWndTo;
1182       if( !pWndTo ) return 0;
1183     }
1184   }
1185
1186   bRet = WINPOS_SetActiveWindow( pWndTo->hwndSelf, FALSE, TRUE );
1187
1188   /* switch desktop queue to current active */
1189   if( pWndTo->parent == WIN_GetDesktop())
1190       WIN_GetDesktop()->hmemTaskQ = pWndTo->hmemTaskQ;
1191
1192   hwndPrevActive = 0;
1193   return bRet;  
1194 }
1195
1196 /*******************************************************************
1197  *         WINPOS_ChangeActiveWindow
1198  *
1199  */
1200 BOOL32 WINPOS_ChangeActiveWindow( HWND32 hWnd, BOOL32 mouseMsg )
1201 {
1202     WND *wndPtr = WIN_FindWndPtr(hWnd);
1203
1204     if (!hWnd) return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
1205
1206     if( !wndPtr ) return FALSE;
1207
1208     /* child windows get WM_CHILDACTIVATE message */
1209     if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
1210         return SendMessage16(hWnd, WM_CHILDACTIVATE, 0, 0L);
1211
1212         /* owned popups imply owner activation - not sure */
1213     if ((wndPtr->dwStyle & WS_POPUP) && wndPtr->owner &&
1214         !(wndPtr->owner->dwStyle & WS_DISABLED ))
1215     {
1216         if (!(wndPtr = wndPtr->owner)) return FALSE;
1217         hWnd = wndPtr->hwndSelf;
1218     }
1219
1220     if( hWnd == hwndActive ) return FALSE;
1221
1222     if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
1223         return FALSE;
1224
1225     /* switch desktop queue to current active */
1226     if( wndPtr->parent == WIN_GetDesktop())
1227         WIN_GetDesktop()->hmemTaskQ = wndPtr->hmemTaskQ;
1228
1229     return TRUE;
1230 }
1231
1232
1233 /***********************************************************************
1234  *           WINPOS_SendNCCalcSize
1235  *
1236  * Send a WM_NCCALCSIZE message to a window.
1237  * All parameters are read-only except newClientRect.
1238  * oldWindowRect, oldClientRect and winpos must be non-NULL only
1239  * when calcValidRect is TRUE.
1240  */
1241 LONG WINPOS_SendNCCalcSize( HWND32 hwnd, BOOL32 calcValidRect,
1242                             RECT16 *newWindowRect, RECT16 *oldWindowRect,
1243                             RECT16 *oldClientRect, SEGPTR winpos,
1244                             RECT16 *newClientRect )
1245 {
1246     NCCALCSIZE_PARAMS16 *params;
1247     LONG result;
1248
1249     if (!(params = SEGPTR_NEW(NCCALCSIZE_PARAMS16))) return 0;
1250     params->rgrc[0] = *newWindowRect;
1251     if (calcValidRect)
1252     {
1253         params->rgrc[1] = *oldWindowRect;
1254         params->rgrc[2] = *oldClientRect;
1255         params->lppos = winpos;
1256     }
1257     result = SendMessage16( hwnd, WM_NCCALCSIZE, calcValidRect,
1258                           (LPARAM)SEGPTR_GET( params ) );
1259     dprintf_win( stddeb, "WINPOS_SendNCCalcSize: %d,%d-%d,%d\n",
1260                  params->rgrc[0].left, params->rgrc[0].top,
1261                  params->rgrc[0].right, params->rgrc[0].bottom );
1262     *newClientRect = params->rgrc[0];
1263     SEGPTR_FREE(params);
1264     return result;
1265 }
1266
1267
1268 /***********************************************************************
1269  *           WINPOS_HandleWindowPosChanging16
1270  *
1271  * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
1272  */
1273 LONG WINPOS_HandleWindowPosChanging16( WND *wndPtr, WINDOWPOS16 *winpos )
1274 {
1275     POINT16 maxSize;
1276     if (winpos->flags & SWP_NOSIZE) return 0;
1277     if ((wndPtr->dwStyle & WS_THICKFRAME) ||
1278         ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
1279     {
1280         NC_GetMinMaxInfo( wndPtr, &maxSize, NULL, NULL, NULL );
1281         winpos->cx = MIN( winpos->cx, maxSize.x );
1282         winpos->cy = MIN( winpos->cy, maxSize.y );
1283     }
1284     return 0;
1285 }
1286
1287
1288 /***********************************************************************
1289  *           WINPOS_HandleWindowPosChanging32
1290  *
1291  * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
1292  */
1293 LONG WINPOS_HandleWindowPosChanging32( WND *wndPtr, WINDOWPOS32 *winpos )
1294 {
1295     POINT16 maxSize;
1296     if (winpos->flags & SWP_NOSIZE) return 0;
1297     if ((wndPtr->dwStyle & WS_THICKFRAME) ||
1298         ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
1299     {
1300         NC_GetMinMaxInfo( wndPtr, &maxSize, NULL, NULL, NULL );
1301         winpos->cx = MIN( winpos->cx, maxSize.x );
1302         winpos->cy = MIN( winpos->cy, maxSize.y );
1303     }
1304     return 0;
1305 }
1306
1307
1308 /***********************************************************************
1309  *           WINPOS_MoveWindowZOrder
1310  *
1311  * Move a window in Z order, invalidating everything that needs it.
1312  * Only necessary for windows without associated X window.
1313  */
1314 static void WINPOS_MoveWindowZOrder( HWND32 hwnd, HWND32 hwndAfter )
1315 {
1316     BOOL32 movingUp;
1317     WND *pWndAfter, *pWndCur, *wndPtr = WIN_FindWndPtr( hwnd );
1318
1319     /* We have two possible cases:
1320      * - The window is moving up: we have to invalidate all areas
1321      *   of the window that were covered by other windows
1322      * - The window is moving down: we have to invalidate areas
1323      *   of other windows covered by this one.
1324      */
1325
1326     if (hwndAfter == HWND_TOP)
1327     {
1328         movingUp = TRUE;
1329     }
1330     else if (hwndAfter == HWND_BOTTOM)
1331     {
1332         if (!wndPtr->next) return;  /* Already at the bottom */
1333         movingUp = FALSE;
1334     }
1335     else
1336     {
1337         if (!(pWndAfter = WIN_FindWndPtr( hwndAfter ))) return;
1338         if (wndPtr->next == pWndAfter) return;  /* Already placed right */
1339
1340           /* Determine which window we encounter first in Z-order */
1341         pWndCur = wndPtr->parent->child;
1342         while ((pWndCur != wndPtr) && (pWndCur != pWndAfter))
1343             pWndCur = pWndCur->next;
1344         movingUp = (pWndCur == pWndAfter);
1345     }
1346
1347     if (movingUp)
1348     {
1349         WND *pWndPrevAfter = wndPtr->next;
1350         WIN_UnlinkWindow( hwnd );
1351         WIN_LinkWindow( hwnd, hwndAfter );
1352         pWndCur = wndPtr->next;
1353         while (pWndCur != pWndPrevAfter)
1354         {
1355             RECT32 rect = { pWndCur->rectWindow.left,
1356                             pWndCur->rectWindow.top,
1357                             pWndCur->rectWindow.right,
1358                             pWndCur->rectWindow.bottom };
1359             OffsetRect32( &rect, -wndPtr->rectClient.left,
1360                           -wndPtr->rectClient.top );
1361             PAINT_RedrawWindow( hwnd, &rect, 0, RDW_INVALIDATE | RDW_ALLCHILDREN |
1362                               RDW_FRAME | RDW_ERASE, 0 );
1363             pWndCur = pWndCur->next;
1364         }
1365     }
1366     else  /* Moving down */
1367     {
1368         pWndCur = wndPtr->next;
1369         WIN_UnlinkWindow( hwnd );
1370         WIN_LinkWindow( hwnd, hwndAfter );
1371         while (pWndCur != wndPtr)
1372         {
1373             RECT32 rect = { pWndCur->rectWindow.left,
1374                             pWndCur->rectWindow.top,
1375                             pWndCur->rectWindow.right,
1376                             pWndCur->rectWindow.bottom };
1377             OffsetRect32( &rect, -pWndCur->rectClient.left,
1378                           -pWndCur->rectClient.top );
1379             PAINT_RedrawWindow( pWndCur->hwndSelf, &rect, 0, RDW_INVALIDATE |
1380                               RDW_ALLCHILDREN | RDW_FRAME | RDW_ERASE, 0 );
1381             pWndCur = pWndCur->next;
1382         }
1383     }
1384 }
1385
1386 /***********************************************************************
1387  *           WINPOS_ReorderOwnedPopups
1388  *
1389  * fix Z order taking into account owned popups -
1390  * basically we need to maintain them above owner window
1391  */
1392 HWND32 WINPOS_ReorderOwnedPopups(HWND32 hwndInsertAfter,WND* wndPtr,WORD flags)
1393 {
1394  WND*   w = WIN_GetDesktop()->child;
1395
1396   if( wndPtr->dwStyle & WS_POPUP && wndPtr->owner )
1397   {
1398    /* implement "local z-order" between the top and owner window */
1399
1400      HWND32 hwndLocalPrev = HWND_TOP;
1401
1402      if( hwndInsertAfter != HWND_TOP )
1403      {
1404         while( w != wndPtr->owner )
1405         {
1406           if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
1407           if( hwndLocalPrev == hwndInsertAfter ) break;
1408           w = w->next;
1409         }
1410         hwndInsertAfter = hwndLocalPrev;
1411      }
1412
1413   }
1414   else if( wndPtr->dwStyle & WS_CHILD ) return hwndInsertAfter;
1415
1416   w = WIN_GetDesktop()->child;
1417   while( w )
1418   {
1419     if( w == wndPtr ) break;
1420
1421     if( w->dwStyle & WS_POPUP && w->owner == wndPtr )
1422     {
1423       SetWindowPos32(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1424                      SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
1425       hwndInsertAfter = w->hwndSelf;
1426     }
1427     w = w->next;
1428   }
1429
1430   return hwndInsertAfter;
1431 }
1432
1433 /***********************************************************************
1434  *           WINPOS_SizeMoveClean
1435  *
1436  * Make window look nice without excessive repainting
1437  *
1438  * the pain:
1439  *
1440  * visible regions are in window coordinates
1441  * update regions are in window client coordinates
1442  * client and window rectangles are in parent client coordinates
1443  */
1444 static UINT32 WINPOS_SizeMoveClean(WND* Wnd, HRGN32 oldVisRgn, LPRECT16 lpOldWndRect, LPRECT16 lpOldClientRect, UINT32 uFlags )
1445 {
1446  HRGN32 newVisRgn = DCE_GetVisRgn(Wnd->hwndSelf,DCX_WINDOW | DCX_CLIPSIBLINGS);
1447  HRGN32 dirtyRgn = CreateRectRgn32(0,0,0,0);
1448  int  other, my;
1449
1450  dprintf_win(stddeb,"cleaning up...new wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i)\n\
1451 \t\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
1452                    Wnd->rectWindow.left, Wnd->rectWindow.top, Wnd->rectWindow.right, Wnd->rectWindow.bottom,
1453                    lpOldWndRect->left, lpOldWndRect->top, lpOldWndRect->right, lpOldWndRect->bottom,
1454                    Wnd->rectClient.left,Wnd->rectClient.top,Wnd->rectClient.right,Wnd->rectClient.bottom,
1455                    lpOldClientRect->left,lpOldClientRect->top,lpOldClientRect->right,lpOldClientRect->bottom);
1456
1457  if( (lpOldWndRect->right - lpOldWndRect->left) != (Wnd->rectWindow.right - Wnd->rectWindow.left) ||
1458      (lpOldWndRect->bottom - lpOldWndRect->top) != (Wnd->rectWindow.bottom - Wnd->rectWindow.top) )
1459      uFlags |= SMC_DRAWFRAME;
1460
1461  CombineRgn32( dirtyRgn, newVisRgn, 0, RGN_COPY);
1462
1463  if( !(uFlags & SMC_NOCOPY) )
1464    CombineRgn32( newVisRgn, newVisRgn, oldVisRgn, RGN_AND ); 
1465
1466  /* map regions to the parent client area */
1467  
1468  OffsetRgn32( dirtyRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
1469  OffsetRgn32( oldVisRgn, lpOldWndRect->left, lpOldWndRect->top );
1470
1471  /* compute invalidated region outside Wnd - (in client coordinates of the parent window) */
1472
1473  other = CombineRgn32(dirtyRgn, oldVisRgn, dirtyRgn, RGN_DIFF);
1474
1475  /* map visible region to the Wnd client area */
1476
1477  OffsetRgn32( newVisRgn, Wnd->rectWindow.left - Wnd->rectClient.left,
1478                          Wnd->rectWindow.top - Wnd->rectClient.top );
1479
1480  /* substract previously invalidated region from the Wnd visible region */
1481
1482  my =  (Wnd->hrgnUpdate > 1) ? CombineRgn32( newVisRgn, newVisRgn,
1483                                              Wnd->hrgnUpdate, RGN_DIFF)
1484                              : COMPLEXREGION;
1485
1486  if( uFlags & SMC_NOCOPY )      /* invalidate Wnd visible region */
1487    {
1488      if (my != NULLREGION)
1489          PAINT_RedrawWindow( Wnd->hwndSelf, NULL, newVisRgn, RDW_INVALIDATE |
1490           RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE, RDW_C_USEHRGN );
1491      else if(uFlags & SMC_DRAWFRAME)
1492          Wnd->flags |= WIN_NEEDS_NCPAINT;
1493    }
1494  else                   /* bitblt old client area */
1495    { 
1496      HDC32 hDC;
1497      int   update;
1498      HRGN32 updateRgn;
1499      int   xfrom,yfrom,xto,yto,width,height;
1500
1501      if( uFlags & SMC_DRAWFRAME )
1502        {
1503          /* copy only client area, frame will be redrawn anyway */
1504
1505          xfrom = lpOldClientRect->left; yfrom = lpOldClientRect->top;
1506          xto = Wnd->rectClient.left; yto = Wnd->rectClient.top;
1507          width = lpOldClientRect->right - xfrom; height = lpOldClientRect->bottom - yfrom;
1508          updateRgn = CreateRectRgn32( 0, 0, width, height );
1509          CombineRgn32( newVisRgn, newVisRgn, updateRgn, RGN_AND );
1510          SetRectRgn( updateRgn, 0, 0, Wnd->rectClient.right - xto, Wnd->rectClient.bottom - yto );
1511        }
1512      else
1513        {
1514          xfrom = lpOldWndRect->left; yfrom = lpOldWndRect->top;
1515          xto = Wnd->rectWindow.left; yto = Wnd->rectWindow.top;
1516          width = lpOldWndRect->right - xfrom; height = lpOldWndRect->bottom - yfrom;
1517          updateRgn = CreateRectRgn32( xto - Wnd->rectClient.left,
1518                                       yto - Wnd->rectClient.top,
1519                                 Wnd->rectWindow.right - Wnd->rectClient.left,
1520                                 Wnd->rectWindow.bottom - Wnd->rectClient.top );
1521        }
1522
1523      CombineRgn32( newVisRgn, newVisRgn, updateRgn, RGN_AND );
1524
1525      /* substract new visRgn from target rect to get a region that won't be copied */
1526
1527      update = CombineRgn32( updateRgn, updateRgn, newVisRgn, RGN_DIFF );
1528
1529      /* Blt valid bits using parent window DC */
1530
1531      if( my != NULLREGION && (xfrom != xto || yfrom != yto) )
1532        {
1533          
1534          /* compute clipping region in parent client coordinates */
1535
1536          OffsetRgn32( newVisRgn, Wnd->rectClient.left, Wnd->rectClient.top );
1537          CombineRgn32( oldVisRgn, oldVisRgn, newVisRgn, RGN_OR );
1538
1539          hDC = GetDCEx32( Wnd->parent->hwndSelf, oldVisRgn,
1540                           DCX_KEEPCLIPRGN | DCX_INTERSECTRGN |
1541                           DCX_CACHE | DCX_CLIPSIBLINGS);
1542
1543          BitBlt32( hDC, xto, yto, width, height, hDC, xfrom, yfrom, SRCCOPY );
1544          ReleaseDC32( Wnd->parent->hwndSelf, hDC); 
1545        }
1546
1547      if( update != NULLREGION )
1548          PAINT_RedrawWindow( Wnd->hwndSelf, NULL, updateRgn, RDW_INVALIDATE |
1549                          RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE, RDW_C_USEHRGN );
1550      else if( uFlags & SMC_DRAWFRAME ) Wnd->flags |= WIN_NEEDS_NCPAINT;
1551      DeleteObject32( updateRgn );
1552    }
1553
1554  /* erase uncovered areas */
1555
1556  if( !(uFlags & SMC_NOPARENTERASE) && (other != NULLREGION ) )
1557       PAINT_RedrawWindow( Wnd->parent->hwndSelf, NULL, dirtyRgn,
1558                         RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE, RDW_C_USEHRGN );
1559  DeleteObject32(dirtyRgn);
1560  DeleteObject32(newVisRgn);
1561  return uFlags;
1562 }
1563
1564
1565 /***********************************************************************
1566  *           WINPOS_FindDeskTopXWindow
1567  *
1568  * Find the actual X window which needs be restacked.
1569  * Used by WINPOS_SetXWindowPos().
1570  */
1571 static Window WINPOS_FindDeskTopXWindow( WND *wndPtr )
1572 {
1573     if (!(wndPtr->flags & WIN_MANAGED))
1574         return wndPtr->window;
1575     else
1576     {
1577         Window window, root, parent, *children;
1578         int nchildren;
1579         window = wndPtr->window;
1580         for (;;)
1581         {
1582             XQueryTree( display, window, &root, &parent,
1583                         &children, &nchildren );
1584             XFree( children );
1585             if (parent == root)
1586                 return window;
1587             window = parent;
1588         }
1589     }
1590 }
1591
1592 /***********************************************************************
1593  *           WINPOS_SetXWindowPos
1594  *
1595  * SetWindowPos() for an X window. Used by the real SetWindowPos().
1596  */
1597 static void WINPOS_SetXWindowPos( WINDOWPOS16 *winpos )
1598 {
1599     XWindowChanges winChanges;
1600     int changeMask = 0;
1601     WND *wndPtr = WIN_FindWndPtr( winpos->hwnd );
1602
1603     if (!(winpos->flags & SWP_NOSIZE))
1604     {
1605         winChanges.width     = winpos->cx;
1606         winChanges.height    = winpos->cy;
1607         changeMask |= CWWidth | CWHeight;
1608
1609         /* Tweak dialog window size hints */
1610
1611         if ((wndPtr->flags & WIN_MANAGED) &&
1612             (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME))
1613         {
1614             XSizeHints *size_hints = XAllocSizeHints();
1615
1616             if (size_hints)
1617             {
1618                 long supplied_return;
1619
1620                 XGetWMSizeHints( display, wndPtr->window, size_hints,
1621                                  &supplied_return, XA_WM_NORMAL_HINTS);
1622                 size_hints->min_width = size_hints->max_width = winpos->cx;
1623                 size_hints->min_height = size_hints->max_height = winpos->cy;
1624                 XSetWMSizeHints( display, wndPtr->window, size_hints,
1625                                  XA_WM_NORMAL_HINTS );
1626                 XFree(size_hints);
1627             }
1628         }
1629     }
1630     if (!(winpos->flags & SWP_NOMOVE))
1631     {
1632         winChanges.x = winpos->x;
1633         winChanges.y = winpos->y;
1634         changeMask |= CWX | CWY;
1635     }
1636     if (!(winpos->flags & SWP_NOZORDER))
1637     {
1638         winChanges.stack_mode = Below;
1639         changeMask |= CWStackMode;
1640
1641         if (winpos->hwndInsertAfter == HWND_TOP) winChanges.stack_mode = Above;
1642         else if (winpos->hwndInsertAfter != HWND_BOTTOM)
1643         {
1644             WND*   insertPtr = WIN_FindWndPtr( winpos->hwndInsertAfter );
1645             Window stack[2];
1646
1647             stack[0] = WINPOS_FindDeskTopXWindow( insertPtr );
1648             stack[1] = WINPOS_FindDeskTopXWindow( wndPtr );
1649
1650             /* for stupid window managers (i.e. all of them) */
1651
1652             XRestackWindows(display, stack, 2); 
1653             changeMask &= ~CWStackMode;
1654         }
1655     }
1656     if (!changeMask) return;
1657
1658     XReconfigureWMWindow( display, wndPtr->window, 0, changeMask, &winChanges );
1659 }
1660
1661
1662 /***********************************************************************
1663  *           SetWindowPos   (USER.232)
1664  */
1665 BOOL16 SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter, INT16 x, INT16 y,
1666                        INT16 cx, INT16 cy, WORD flags )
1667 {
1668     return SetWindowPos32(hwnd,(INT32)(INT16)hwndInsertAfter,x,y,cx,cy,flags);
1669 }
1670
1671 /***********************************************************************
1672  *           SetWindowPos   (USER32.519)
1673  */
1674 BOOL32 SetWindowPos32( HWND32 hwnd, HWND32 hwndInsertAfter, INT32 x, INT32 y,
1675                        INT32 cx, INT32 cy, WORD flags )
1676 {
1677     WINDOWPOS16 *winpos;
1678     WND *       wndPtr;
1679     RECT16      newWindowRect, newClientRect, oldWindowRect;
1680     HRGN32      visRgn = 0;
1681     HWND32      tempInsertAfter= 0;
1682     int         result = 0;
1683     UINT32      uFlags = 0;
1684
1685     dprintf_win(stddeb,"SetWindowPos: hwnd %04x, (%i,%i)-(%i,%i) flags %08x\n", 
1686                                                  hwnd, x, y, x+cx, y+cy, flags);  
1687       /* Check window handle */
1688
1689     if (hwnd == GetDesktopWindow32()) return FALSE;
1690     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1691
1692     if (wndPtr->dwStyle & WS_VISIBLE) flags &= ~SWP_SHOWWINDOW;
1693     else
1694     {
1695         uFlags |= SMC_NOPARENTERASE; 
1696         flags &= ~SWP_HIDEWINDOW;
1697         if (!(flags & SWP_SHOWWINDOW)) flags |= SWP_NOREDRAW;
1698     }
1699
1700 /*     Check for windows that may not be resized 
1701        FIXME: this should be done only for Windows 3.0 programs 
1702        if (flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW ) )
1703            flags |= SWP_NOSIZE | SWP_NOMOVE;
1704 */
1705       /* Check dimensions */
1706
1707     if (cx <= 0) cx = 1;
1708     if (cy <= 0) cy = 1;
1709
1710       /* Check flags */
1711
1712     if (hwnd == hwndActive) flags |= SWP_NOACTIVATE;   /* Already active */
1713     if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
1714         (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
1715         flags |= SWP_NOSIZE;    /* Already the right size */
1716     if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
1717         flags |= SWP_NOMOVE;    /* Already the right position */
1718
1719       /* Check hwndInsertAfter */
1720
1721     if (!(flags & (SWP_NOZORDER | SWP_NOACTIVATE)))
1722     {
1723           /* Ignore TOPMOST flags when activating a window */
1724           /* _and_ moving it in Z order. */
1725         if ((hwndInsertAfter == HWND_TOPMOST) ||
1726             (hwndInsertAfter == HWND_NOTOPMOST))
1727             hwndInsertAfter = HWND_TOP; 
1728     }
1729       /* TOPMOST not supported yet */
1730     if ((hwndInsertAfter == HWND_TOPMOST) ||
1731         (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
1732
1733       /* hwndInsertAfter must be a sibling of the window */
1734     if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
1735        {
1736          WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
1737          if( wnd->parent != wndPtr->parent ) return FALSE;
1738          if( wnd->next == wndPtr ) flags |= SWP_NOZORDER;
1739        }
1740     else if (!(wndPtr->window))
1741          /* FIXME: the following optimization is no good for "X-ed" windows */
1742        if (hwndInsertAfter == HWND_TOP)
1743            flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
1744        else /* HWND_BOTTOM */
1745            flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
1746
1747       /* Fill the WINDOWPOS structure */
1748
1749     if (!(winpos = SEGPTR_NEW(WINDOWPOS16))) return FALSE;
1750     winpos->hwnd = hwnd;
1751     winpos->hwndInsertAfter = hwndInsertAfter;
1752     winpos->x = x;
1753     winpos->y = y;
1754     winpos->cx = cx;
1755     winpos->cy = cy;
1756     winpos->flags = flags;
1757     
1758       /* Send WM_WINDOWPOSCHANGING message */
1759
1760     if (!(flags & SWP_NOSENDCHANGING))
1761         SendMessage16( hwnd, WM_WINDOWPOSCHANGING, 0,
1762                        (LPARAM)SEGPTR_GET(winpos) );
1763
1764       /* Calculate new position and size */
1765
1766     newWindowRect = wndPtr->rectWindow;
1767     newClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
1768                                                     : wndPtr->rectClient;
1769
1770     if (!(winpos->flags & SWP_NOSIZE))
1771     {
1772         newWindowRect.right  = newWindowRect.left + winpos->cx;
1773         newWindowRect.bottom = newWindowRect.top + winpos->cy;
1774     }
1775     if (!(winpos->flags & SWP_NOMOVE))
1776     {
1777         newWindowRect.left    = winpos->x;
1778         newWindowRect.top     = winpos->y;
1779         newWindowRect.right  += winpos->x - wndPtr->rectWindow.left;
1780         newWindowRect.bottom += winpos->y - wndPtr->rectWindow.top;
1781
1782         OffsetRect16( &newClientRect, winpos->x - wndPtr->rectWindow.left, 
1783                                       winpos->y - wndPtr->rectWindow.top );
1784     }
1785
1786     winpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
1787
1788       /* Reposition window in Z order */
1789
1790     if (!(winpos->flags & SWP_NOZORDER))
1791     {
1792         /* reorder owned popups if hwnd is top-level window 
1793          */
1794         if( wndPtr->parent == WIN_GetDesktop() )
1795             hwndInsertAfter = WINPOS_ReorderOwnedPopups( hwndInsertAfter,
1796                                                          wndPtr, flags );
1797
1798         if (wndPtr->window)
1799         {
1800             WIN_UnlinkWindow( winpos->hwnd );
1801             WIN_LinkWindow( winpos->hwnd, hwndInsertAfter );
1802         }
1803         else WINPOS_MoveWindowZOrder( winpos->hwnd, hwndInsertAfter );
1804     }
1805
1806     if ( !wndPtr->window && !(flags & SWP_NOREDRAW) && 
1807         (!(flags & SWP_NOMOVE) || !(flags & SWP_NOSIZE) || (flags & SWP_FRAMECHANGED)) )
1808           visRgn = DCE_GetVisRgn(hwnd, DCX_WINDOW | DCX_CLIPSIBLINGS);
1809
1810
1811       /* Send WM_NCCALCSIZE message to get new client area */
1812     if( (flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
1813       {
1814          result = WINPOS_SendNCCalcSize( winpos->hwnd, TRUE, &newWindowRect,
1815                                     &wndPtr->rectWindow, &wndPtr->rectClient,
1816                                     SEGPTR_GET(winpos), &newClientRect );
1817
1818          /* FIXME: WVR_ALIGNxxx */
1819
1820          if( newClientRect.left != wndPtr->rectClient.left ||
1821              newClientRect.top != wndPtr->rectClient.top )
1822              winpos->flags &= ~SWP_NOCLIENTMOVE;
1823
1824          if( (newClientRect.right - newClientRect.left !=
1825              wndPtr->rectClient.right - wndPtr->rectClient.left) ||
1826             (newClientRect.bottom - newClientRect.top !=
1827              wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
1828              winpos->flags &= ~SWP_NOCLIENTSIZE;
1829       }
1830     else
1831       if( !(flags & SWP_NOMOVE) && (newClientRect.left != wndPtr->rectClient.left ||
1832                                     newClientRect.top != wndPtr->rectClient.top) )
1833             winpos->flags &= ~SWP_NOCLIENTMOVE;
1834
1835     /* Update active DCEs */
1836
1837     if( !(flags & SWP_NOZORDER) || (flags & SWP_HIDEWINDOW) || (flags & SWP_SHOWWINDOW)
1838                                 || (memcmp(&newWindowRect,&wndPtr->rectWindow,sizeof(RECT16))
1839                                     && wndPtr->dwStyle & WS_VISIBLE ) )
1840       {
1841         RECT16 rect;
1842
1843         UnionRect16(&rect,&newWindowRect,&wndPtr->rectWindow);
1844         DCE_InvalidateDCE(wndPtr->parent, &rect);
1845       }
1846
1847     /* change geometry */
1848
1849     oldWindowRect = wndPtr->rectWindow;
1850
1851     if (wndPtr->window)
1852     {
1853         RECT16 oldClientRect = wndPtr->rectClient;
1854
1855         tempInsertAfter = winpos->hwndInsertAfter;
1856
1857         winpos->hwndInsertAfter = hwndInsertAfter;
1858
1859         /* postpone geometry change */
1860
1861         if( !(flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW)) )
1862           {
1863               WINPOS_SetXWindowPos( winpos );
1864               winpos->hwndInsertAfter = tempInsertAfter;
1865           }
1866         else  uFlags |= SMC_SETXPOS;
1867
1868         wndPtr->rectWindow = newWindowRect;
1869         wndPtr->rectClient = newClientRect;
1870
1871         if( !(flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW)) )
1872           if( (oldClientRect.left - oldWindowRect.left !=
1873                newClientRect.left - newWindowRect.left) ||
1874               (oldClientRect.top - oldWindowRect.top !=
1875                newClientRect.top - newWindowRect.top) || winpos->flags & SWP_NOCOPYBITS )
1876
1877               PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, 0, RDW_INVALIDATE |
1878                               RDW_ALLCHILDREN | RDW_FRAME | RDW_ERASE, 0 );
1879           else
1880               if( winpos->flags & SWP_FRAMECHANGED )
1881               {
1882                 WORD wErase = 0;
1883                 RECT32 rect;
1884
1885                 if( oldClientRect.right > newClientRect.right ) 
1886                 {
1887                     rect.left = newClientRect.right; rect.top = newClientRect.top;
1888                     rect.right = oldClientRect.right; rect.bottom = newClientRect.bottom;
1889                     wErase = 1;
1890                     PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, 0,
1891                                       RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN, 0 );
1892                 }
1893                 if( oldClientRect.bottom > newClientRect.bottom )
1894                 {
1895                     rect.left = newClientRect.left; rect.top = newClientRect.bottom;
1896                     rect.right = (wErase)?oldClientRect.right:newClientRect.right;
1897                     rect.bottom = oldClientRect.bottom;
1898                     wErase = 1;
1899                     PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, 0,
1900                                       RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN, 0 );
1901                 }
1902                 if( !wErase ) wndPtr->flags |= WIN_NEEDS_NCPAINT;
1903               }
1904     }
1905     else
1906     {
1907         RECT16 oldClientRect = wndPtr->rectClient;
1908
1909         wndPtr->rectWindow = newWindowRect;
1910         wndPtr->rectClient = newClientRect;
1911
1912         if( oldClientRect.bottom - oldClientRect.top ==
1913             newClientRect.bottom - newClientRect.top ) result &= ~WVR_VREDRAW;
1914
1915         if( oldClientRect.right - oldClientRect.left ==
1916             newClientRect.right - newClientRect.left ) result &= ~WVR_HREDRAW;
1917
1918         if( !(flags & (SWP_NOREDRAW | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
1919           {
1920             uFlags |=  ((winpos->flags & SWP_NOCOPYBITS) || 
1921                         (result >= WVR_HREDRAW && result < WVR_VALIDRECTS)) ? SMC_NOCOPY : 0;
1922             uFlags |=  (winpos->flags & SWP_FRAMECHANGED) ? SMC_DRAWFRAME : 0;
1923
1924             if( (winpos->flags & SWP_AGG_NOGEOMETRYCHANGE) != SWP_AGG_NOGEOMETRYCHANGE )
1925                 uFlags = WINPOS_SizeMoveClean(wndPtr, visRgn, &oldWindowRect, 
1926                                                               &oldClientRect, uFlags);
1927             else
1928               { 
1929                 /* adjust frame and do not erase parent */
1930
1931                 if( winpos->flags & SWP_FRAMECHANGED ) wndPtr->flags |= WIN_NEEDS_NCPAINT;
1932                 if( winpos->flags & SWP_NOZORDER ) uFlags |= SMC_NOPARENTERASE;
1933               }
1934           }
1935         DeleteObject32(visRgn);
1936     }
1937
1938     if (flags & SWP_SHOWWINDOW)
1939     {
1940         wndPtr->dwStyle |= WS_VISIBLE;
1941         if (wndPtr->window)
1942         {
1943             if( uFlags & SMC_SETXPOS )
1944             {
1945               WINPOS_SetXWindowPos( winpos );
1946               winpos->hwndInsertAfter = tempInsertAfter;
1947             }
1948             XMapWindow( display, wndPtr->window );
1949         }
1950         else
1951         {
1952             if (!(flags & SWP_NOREDRAW))
1953                 PAINT_RedrawWindow( winpos->hwnd, NULL, 0,
1954                                 RDW_INVALIDATE | RDW_ALLCHILDREN |
1955                                 RDW_FRAME | RDW_ERASENOW | RDW_ERASE, 0 );
1956         }
1957     }
1958     else if (flags & SWP_HIDEWINDOW)
1959     {
1960         wndPtr->dwStyle &= ~WS_VISIBLE;
1961         if (wndPtr->window)
1962         {
1963             XUnmapWindow( display, wndPtr->window );
1964             if( uFlags & SMC_SETXPOS )
1965             {
1966               WINPOS_SetXWindowPos( winpos );
1967               winpos->hwndInsertAfter = tempInsertAfter;
1968             }
1969         }
1970         else
1971         {
1972             if (!(flags & SWP_NOREDRAW))
1973             {
1974                 RECT32 rect = { oldWindowRect.left, oldWindowRect.top,
1975                                 oldWindowRect.right, oldWindowRect.bottom };
1976                 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, &rect, 0, 
1977                         RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE | RDW_ERASENOW, 0);
1978             }
1979             uFlags |= SMC_NOPARENTERASE;
1980         }
1981
1982         if ((winpos->hwnd == GetFocus32()) ||
1983             IsChild32( winpos->hwnd, GetFocus32()))
1984         {
1985             /* Revert focus to parent */
1986             SetFocus32( GetParent32(winpos->hwnd) );
1987         }
1988         if (hwnd == CARET_GetHwnd()) DestroyCaret();
1989
1990         if (winpos->hwnd == hwndActive)
1991         {
1992               /* Activate previously active window if possible */
1993             HWND32 newActive = hwndPrevActive;
1994             if (!IsWindow(newActive) || (newActive == winpos->hwnd))
1995             {
1996                 newActive = GetTopWindow32( GetDesktopWindow32() );
1997                 if (newActive == winpos->hwnd)
1998                     newActive = wndPtr->next ? wndPtr->next->hwndSelf : 0;
1999             }       
2000             WINPOS_ChangeActiveWindow( newActive, FALSE );
2001         }
2002     }
2003
2004       /* Activate the window */
2005
2006     if (!(flags & SWP_NOACTIVATE))
2007             WINPOS_ChangeActiveWindow( winpos->hwnd, FALSE );
2008     
2009       /* Repaint the window */
2010
2011     if (wndPtr->window) EVENT_Synchronize();  /* Wait for all expose events */
2012
2013     EVENT_DummyMotionNotify(); /* Simulate a mouse event to set the cursor */
2014
2015     if (!(flags & SWP_DEFERERASE) && !(uFlags & SMC_NOPARENTERASE) )
2016     {
2017         RECT32  rect;
2018         CONV_RECT16TO32( &oldWindowRect, &rect );
2019         PAINT_RedrawWindow( wndPtr->parent->hwndSelf, (wndPtr->flags & WIN_SAVEUNDER_OVERRIDE) 
2020                             ? &rect : NULL, 0, RDW_ALLCHILDREN | RDW_ERASENOW |
2021                           ((wndPtr->flags & WIN_SAVEUNDER_OVERRIDE) ? RDW_INVALIDATE : 0), 0 );
2022         wndPtr->flags &= ~WIN_SAVEUNDER_OVERRIDE;
2023     }
2024     else if( wndPtr->parent == WIN_GetDesktop() && wndPtr->parent->flags & WIN_NEEDS_ERASEBKGND )
2025         PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0, RDW_NOCHILDREN | RDW_ERASENOW, 0 );
2026
2027       /* And last, send the WM_WINDOWPOSCHANGED message */
2028
2029     dprintf_win(stddeb,"\tstatus flags = %04x\n", winpos->flags & SWP_AGG_STATUSFLAGS);
2030
2031     if ( ((winpos->flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) && 
2032         !(winpos->flags & SWP_NOSENDCHANGING))
2033         SendMessage16( winpos->hwnd, WM_WINDOWPOSCHANGED,
2034                        0, (LPARAM)SEGPTR_GET(winpos) );
2035
2036     SEGPTR_FREE(winpos);
2037     return TRUE;
2038 }
2039
2040                                         
2041 /***********************************************************************
2042  *           BeginDeferWindowPos16   (USER.259)
2043  */
2044 HDWP16 BeginDeferWindowPos16( INT16 count )
2045 {
2046     return BeginDeferWindowPos32( count );
2047 }
2048
2049
2050 /***********************************************************************
2051  *           BeginDeferWindowPos32   (USER32.8)
2052  */
2053 HDWP32 BeginDeferWindowPos32( INT32 count )
2054 {
2055     HDWP32 handle;
2056     DWP *pDWP;
2057
2058     if (count <= 0) return 0;
2059     handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS32) );
2060     if (!handle) return 0;
2061     pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
2062     pDWP->actualCount    = 0;
2063     pDWP->suggestedCount = count;
2064     pDWP->valid          = TRUE;
2065     pDWP->wMagic         = DWP_MAGIC;
2066     pDWP->hwndParent     = 0;
2067     return handle;
2068 }
2069
2070
2071 /***********************************************************************
2072  *           DeferWindowPos16   (USER.260)
2073  */
2074 HDWP16 DeferWindowPos16( HDWP16 hdwp, HWND16 hwnd, HWND16 hwndAfter,
2075                          INT16 x, INT16 y, INT16 cx, INT16 cy, UINT16 flags )
2076 {
2077     return DeferWindowPos32( hdwp, hwnd, (INT32)(INT16)hwndAfter,
2078                              x, y, cx, cy, flags );
2079 }
2080
2081
2082 /***********************************************************************
2083  *           DeferWindowPos32   (USER32.127)
2084  */
2085 HDWP32 DeferWindowPos32( HDWP32 hdwp, HWND32 hwnd, HWND32 hwndAfter,
2086                          INT32 x, INT32 y, INT32 cx, INT32 cy, UINT32 flags )
2087 {
2088     DWP *pDWP;
2089     int i;
2090     HDWP32 newhdwp = hdwp;
2091     HWND32 parent;
2092
2093     pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
2094     if (!pDWP) return 0;
2095     if (hwnd == GetDesktopWindow32()) return 0;
2096
2097       /* All the windows of a DeferWindowPos() must have the same parent */
2098
2099     parent = WIN_FindWndPtr( hwnd )->parent->hwndSelf;
2100     if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
2101     else if (parent != pDWP->hwndParent)
2102     {
2103         USER_HEAP_FREE( hdwp );
2104         return 0;
2105     }
2106
2107     for (i = 0; i < pDWP->actualCount; i++)
2108     {
2109         if (pDWP->winPos[i].hwnd == hwnd)
2110         {
2111               /* Merge with the other changes */
2112             if (!(flags & SWP_NOZORDER))
2113             {
2114                 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
2115             }
2116             if (!(flags & SWP_NOMOVE))
2117             {
2118                 pDWP->winPos[i].x = x;
2119                 pDWP->winPos[i].y = y;
2120             }                
2121             if (!(flags & SWP_NOSIZE))
2122             {
2123                 pDWP->winPos[i].cx = cx;
2124                 pDWP->winPos[i].cy = cy;
2125             }
2126             pDWP->winPos[i].flags &= flags & (SWP_NOSIZE | SWP_NOMOVE |
2127                                               SWP_NOZORDER | SWP_NOREDRAW |
2128                                               SWP_NOACTIVATE | SWP_NOCOPYBITS |
2129                                               SWP_NOOWNERZORDER);
2130             pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
2131                                               SWP_FRAMECHANGED);
2132             return hdwp;
2133         }
2134     }
2135     if (pDWP->actualCount >= pDWP->suggestedCount)
2136     {
2137         newhdwp = USER_HEAP_REALLOC( hdwp,
2138                       sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS32) );
2139         if (!newhdwp) return 0;
2140         pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
2141         pDWP->suggestedCount++;
2142     }
2143     pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
2144     pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
2145     pDWP->winPos[pDWP->actualCount].x = x;
2146     pDWP->winPos[pDWP->actualCount].y = y;
2147     pDWP->winPos[pDWP->actualCount].cx = cx;
2148     pDWP->winPos[pDWP->actualCount].cy = cy;
2149     pDWP->winPos[pDWP->actualCount].flags = flags;
2150     pDWP->actualCount++;
2151     return newhdwp;
2152 }
2153
2154
2155 /***********************************************************************
2156  *           EndDeferWindowPos16   (USER.261)
2157  */
2158 BOOL16 EndDeferWindowPos16( HDWP16 hdwp )
2159 {
2160     return EndDeferWindowPos32( hdwp );
2161 }
2162
2163
2164 /***********************************************************************
2165  *           EndDeferWindowPos32   (USER32.172)
2166  */
2167 BOOL32 EndDeferWindowPos32( HDWP32 hdwp )
2168 {
2169     DWP *pDWP;
2170     WINDOWPOS32 *winpos;
2171     BOOL32 res = TRUE;
2172     int i;
2173
2174     pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
2175     if (!pDWP) return FALSE;
2176     for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
2177     {
2178         if (!(res = SetWindowPos32( winpos->hwnd, winpos->hwndInsertAfter,
2179                                     winpos->x, winpos->y, winpos->cx,
2180                                     winpos->cy, winpos->flags ))) break;
2181     }
2182     USER_HEAP_FREE( hdwp );
2183     return res;
2184 }
2185
2186
2187 /***********************************************************************
2188  *           TileChildWindows   (USER.199)
2189  */
2190 void TileChildWindows( HWND16 parent, WORD action )
2191 {
2192     printf("STUB TileChildWindows(%04x, %d)\n", parent, action);
2193 }
2194
2195 /***********************************************************************
2196  *           CascageChildWindows   (USER.198)
2197  */
2198 void CascadeChildWindows( HWND16 parent, WORD action )
2199 {
2200     printf("STUB CascadeChildWindows(%04x, %d)\n", parent, action);
2201 }