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