Release 960331
[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 "sysmetrics.h"
9 #include "module.h"
10 #include "user.h"
11 #include "win.h"
12 #include "event.h"
13 #include "hook.h"
14 #include "message.h"
15 #include "queue.h"
16 #include "stackframe.h"
17 #include "winpos.h"
18 #include "nonclient.h"
19 #include "stddebug.h"
20 /* #define DEBUG_WIN */
21 #include "debug.h"
22
23 /* ----- external functions ----- */
24
25 void    FOCUS_SwitchFocus( HWND , HWND );
26
27 /* ----- internal variables ----- */
28
29 static HWND hwndActive      = 0;  /* Currently active window */
30 static HWND hwndPrevActive  = 0;  /* Previously active window */
31
32
33 /***********************************************************************
34  *           WINPOS_FindIconPos
35  *
36  * Find a suitable place for an iconic window.
37  * The new position is stored into wndPtr->ptIconPos.
38  */
39 void WINPOS_FindIconPos( HWND hwnd )
40 {
41     RECT rectParent;
42     short x, y, xspacing, yspacing;
43     WND * wndPtr = WIN_FindWndPtr( hwnd );
44
45     if (!wndPtr || !wndPtr->parent) return;
46     GetClientRect( wndPtr->parent->hwndSelf, &rectParent );
47     if ((wndPtr->ptIconPos.x >= rectParent.left) &&
48         (wndPtr->ptIconPos.x + SYSMETRICS_CXICON < rectParent.right) &&
49         (wndPtr->ptIconPos.y >= rectParent.top) &&
50         (wndPtr->ptIconPos.y + SYSMETRICS_CYICON < rectParent.bottom))
51         return;  /* The icon already has a suitable position */
52
53     xspacing = yspacing = 70;  /* FIXME: This should come from WIN.INI */
54     y = rectParent.bottom;
55     for (;;)
56     {
57         for (x = rectParent.left; x<=rectParent.right-xspacing; x += xspacing)
58         {
59               /* Check if another icon already occupies this spot */
60             WND *childPtr = wndPtr->parent->child;
61             while (childPtr)
62             {
63                 if ((childPtr->dwStyle & WS_MINIMIZE) && (childPtr != wndPtr))
64                 {
65                     if ((childPtr->rectWindow.left < x + xspacing) &&
66                         (childPtr->rectWindow.right >= x) &&
67                         (childPtr->rectWindow.top <= y) &&
68                         (childPtr->rectWindow.bottom > y - yspacing))
69                         break;  /* There's a window in there */
70                 }
71                 childPtr = childPtr->next;
72             }
73             if (!childPtr)
74             {
75                   /* No window was found, so it's OK for us */
76                 wndPtr->ptIconPos.x = x + (xspacing - SYSMETRICS_CXICON) / 2;
77                 wndPtr->ptIconPos.y = y - (yspacing + SYSMETRICS_CYICON) / 2;
78                 return;
79             }
80         }
81         y -= yspacing;
82     }
83 }
84
85
86 /***********************************************************************
87  *           ArrangeIconicWindows   (USER.170)
88  */
89 UINT ArrangeIconicWindows( HWND parent )
90 {
91     RECT rectParent;
92     HWND hwndChild;
93     INT x, y, xspacing, yspacing;
94
95     GetClientRect( parent, &rectParent );
96     x = rectParent.left;
97     y = rectParent.bottom;
98     xspacing = yspacing = 70;  /* FIXME: This should come from WIN.INI */
99     hwndChild = GetWindow( parent, GW_CHILD );
100     while (hwndChild)
101     {
102         if (IsIconic( hwndChild ))
103         {
104             SetWindowPos( hwndChild, 0, x + (xspacing - SYSMETRICS_CXICON) / 2,
105                           y - (yspacing + SYSMETRICS_CYICON) / 2, 0, 0,
106                           SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
107             if (x <= rectParent.right - xspacing) x += xspacing;
108             else
109             {
110                 x = rectParent.left;
111                 y -= yspacing;
112             }
113         }
114         hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
115     }
116     return yspacing;
117 }
118
119
120 /***********************************************************************
121  *           GetWindowRect   (USER.32)
122  */
123 void GetWindowRect( HWND hwnd, LPRECT rect ) 
124 {
125     WND * wndPtr = WIN_FindWndPtr( hwnd ); 
126     if (!wndPtr) return;
127     
128     *rect = wndPtr->rectWindow;
129     if (wndPtr->dwStyle & WS_CHILD)
130         MapWindowPoints( wndPtr->parent->hwndSelf, 0, (POINT *)rect, 2 );
131 }
132
133
134 /***********************************************************************
135  *           GetClientRect   (USER.33)
136  */
137 void GetClientRect( HWND hwnd, LPRECT rect ) 
138 {
139     WND * wndPtr = WIN_FindWndPtr( hwnd );
140
141     rect->left = rect->top = rect->right = rect->bottom = 0;
142     if (wndPtr) 
143     {
144         rect->right  = wndPtr->rectClient.right - wndPtr->rectClient.left;
145         rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
146     }
147 }
148
149
150 /*******************************************************************
151  *         ClientToScreen   (USER.28)
152  */
153 BOOL ClientToScreen( HWND hwnd, LPPOINT lppnt )
154 {
155     MapWindowPoints( hwnd, 0, lppnt, 1 );
156     return TRUE;
157 }
158
159
160 /*******************************************************************
161  *         ScreenToClient   (USER.29)
162  */
163 void ScreenToClient( HWND hwnd, LPPOINT lppnt )
164 {
165     MapWindowPoints( 0, hwnd, lppnt, 1 );
166 }
167
168
169 /***********************************************************************
170  *           WINPOS_WindowFromPoint
171  *
172  * Find the window and hittest for a given point.
173  */
174 INT WINPOS_WindowFromPoint( POINT pt, WND **ppWnd )
175 {
176     WND *wndPtr;
177     INT hittest = HTERROR;
178     INT x, y;
179
180     *ppWnd = NULL;
181     x = pt.x;
182     y = pt.y;
183     wndPtr = WIN_GetDesktop()->child;
184     for (;;)
185     {
186         while (wndPtr)
187         {
188             /* If point is in window, and window is visible, and it  */
189             /* is enabled (or it's a top-level window), then explore */
190             /* its children. Otherwise, go to the next window.       */
191
192             if ((wndPtr->dwStyle & WS_VISIBLE) &&
193                 (!(wndPtr->dwStyle & WS_DISABLED) ||
194                  ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)) &&
195                 (x >= wndPtr->rectWindow.left) &&
196                 (x < wndPtr->rectWindow.right) &&
197                 (y >= wndPtr->rectWindow.top) &&
198                 (y < wndPtr->rectWindow.bottom))
199             {
200                 *ppWnd = wndPtr;  /* Got a suitable window */
201
202                 /* If window is minimized or disabled, return at once */
203                 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
204                 if (wndPtr->dwStyle & WS_DISABLED) return HTERROR;
205
206                 /* If point is not in client area, ignore the children */
207                 if ((x < wndPtr->rectClient.left) ||
208                     (x >= wndPtr->rectClient.right) ||
209                     (y < wndPtr->rectClient.top) ||
210                     (y >= wndPtr->rectClient.bottom)) break;
211
212                 x -= wndPtr->rectClient.left;
213                 y -= wndPtr->rectClient.top;
214                 wndPtr = wndPtr->child;
215             }
216             else wndPtr = wndPtr->next;
217         }
218
219         /* If nothing found, return the desktop window */
220         if (!*ppWnd)
221         {
222             *ppWnd = WIN_GetDesktop();
223             return HTCLIENT;
224         }
225
226         /* Send the WM_NCHITTEST message (only if to the same task) */
227         if ((*ppWnd)->hmemTaskQ != GetTaskQueue(0)) return HTCLIENT;
228         hittest = (INT)SendMessage( (*ppWnd)->hwndSelf, WM_NCHITTEST, 0,
229                                     MAKELONG( pt.x, pt.y ) );
230         if (hittest != HTTRANSPARENT) return hittest;  /* Found the window */
231
232         /* If no children found in last search, make point relative to parent*/
233         if (!wndPtr)
234         {
235             x += (*ppWnd)->rectClient.left;
236             y += (*ppWnd)->rectClient.top;
237         }
238
239         /* Restart the search from the next sibling */
240         wndPtr = (*ppWnd)->next;
241         *ppWnd = (*ppWnd)->parent;
242     }
243 }
244
245
246 /*******************************************************************
247  *         WindowFromPoint   (USER.30)
248  */
249 HWND WindowFromPoint( POINT pt )
250 {
251     WND *pWnd;
252     WINPOS_WindowFromPoint( pt, &pWnd );
253     return pWnd->hwndSelf;
254 }
255
256
257 /*******************************************************************
258  *         ChildWindowFromPoint   (USER.191)
259  */
260 HWND ChildWindowFromPoint( HWND hwndParent, POINT pt )
261 {
262     /* pt is in the client coordinates */
263
264     WND* wnd = WIN_FindWndPtr(hwndParent);
265     RECT rect;
266
267     if( !wnd ) return 0;
268
269     /* get client rect fast */
270     rect.top = rect.left = 0;
271     rect.right = wnd->rectClient.right - wnd->rectClient.left;
272     rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
273
274     if (!PtInRect( &rect, pt )) return 0;
275
276     wnd = wnd->child;
277     while ( wnd )
278     {
279         if (PtInRect( &wnd->rectWindow, pt )) return wnd->hwndSelf;
280         wnd = wnd->next;
281     }
282     return hwndParent;
283 }
284
285 /*******************************************************************
286  *         MapWindowPoints   (USER.258)
287  */
288 void MapWindowPoints( HWND hwndFrom, HWND hwndTo, LPPOINT lppt, WORD count )
289 {
290     WND * wndPtr;
291     POINT * curpt;
292     POINT origin = { 0, 0 };
293     WORD i;
294
295     if( hwndFrom == hwndTo ) return;
296
297       /* Translate source window origin to screen coords */
298     if (hwndFrom)
299     {
300         if (!(wndPtr = WIN_FindWndPtr( hwndFrom )))
301         {
302             fprintf(stderr,"MapWindowPoints: bad hwndFrom = %04x\n",hwndFrom);
303             return;
304         }
305         while (wndPtr->parent)
306         {
307             origin.x += wndPtr->rectClient.left;
308             origin.y += wndPtr->rectClient.top;
309             wndPtr = wndPtr->parent;
310         }
311     }
312
313       /* Translate origin to destination window coords */
314     if (hwndTo)
315     {
316         if (!(wndPtr = WIN_FindWndPtr( hwndTo )))
317         {
318             fprintf(stderr,"MapWindowPoints: bad hwndTo = %04x\n", hwndTo );
319             return;
320         }
321         while (wndPtr->parent)
322         {
323             origin.x -= wndPtr->rectClient.left;
324             origin.y -= wndPtr->rectClient.top;
325             wndPtr = wndPtr->parent;
326         }    
327     }
328
329       /* Translate points */
330     for (i = 0, curpt = lppt; i < count; i++, curpt++)
331     {
332         curpt->x += origin.x;
333         curpt->y += origin.y;
334     }
335 }
336
337
338 /***********************************************************************
339  *           IsIconic   (USER.31)
340  */
341 BOOL IsIconic(HWND hWnd)
342 {
343     WND * wndPtr = WIN_FindWndPtr(hWnd);
344     if (wndPtr == NULL) return FALSE;
345     return (wndPtr->dwStyle & WS_MINIMIZE) != 0;
346 }
347  
348  
349 /***********************************************************************
350  *           IsZoomed   (USER.272)
351  */
352 BOOL IsZoomed(HWND hWnd)
353 {
354     WND * wndPtr = WIN_FindWndPtr(hWnd);
355     if (wndPtr == NULL) return FALSE;
356     return (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
357 }
358
359
360 /*******************************************************************
361  *         GetActiveWindow    (USER.60)
362  */
363 HWND GetActiveWindow()
364 {
365     return hwndActive;
366 }
367
368
369 /*******************************************************************
370  *         SetActiveWindow    (USER.59)
371  */
372 HWND SetActiveWindow( HWND hwnd )
373 {
374     HWND prev = hwndActive;
375     WND *wndPtr = WIN_FindWndPtr( hwnd );
376
377     if (!wndPtr || (wndPtr->dwStyle & WS_DISABLED) ||
378         !(wndPtr->dwStyle & WS_VISIBLE)) return 0;
379
380     WINPOS_SetActiveWindow( hwnd, 0, 0 );
381     return prev;
382 }
383
384
385 /***********************************************************************
386  *           BringWindowToTop   (USER.45)
387  */
388 BOOL BringWindowToTop( HWND hwnd )
389 {
390     return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
391 }
392
393
394 /***********************************************************************
395  *           MoveWindow   (USER.56)
396  */
397 BOOL MoveWindow( HWND hwnd, short x, short y, short cx, short cy, BOOL repaint)
398 {    
399     int flags = SWP_NOZORDER | SWP_NOACTIVATE;
400     if (!repaint) flags |= SWP_NOREDRAW;
401     dprintf_win(stddeb, "MoveWindow: %04x %d,%d %dx%d %d\n", 
402             hwnd, x, y, cx, cy, repaint );
403     return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
404 }
405
406
407 /***********************************************************************
408  *           ShowWindow   (USER.42)
409  */
410 BOOL ShowWindow( HWND hwnd, int cmd ) 
411 {    
412     WND * wndPtr = WIN_FindWndPtr( hwnd );
413     BOOL wasVisible;
414     POINT maxSize;
415     int swpflags = 0;
416     short x = 0, y = 0, cx = 0, cy = 0;
417
418     if (!wndPtr) return FALSE;
419
420     dprintf_win(stddeb,"ShowWindow: hwnd=%04x, cmd=%d\n", hwnd, cmd);
421
422     wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
423
424     switch(cmd)
425     {
426         case SW_HIDE:
427             swpflags |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | 
428                         SWP_NOACTIVATE | SWP_NOZORDER;
429             break;
430
431         case SW_SHOWMINNOACTIVE:
432             swpflags |= SWP_NOACTIVATE | SWP_NOZORDER;
433             /* fall through */
434         case SW_SHOWMINIMIZED:
435             swpflags |= SWP_SHOWWINDOW;
436             /* fall through */
437         case SW_MINIMIZE:
438             swpflags |= SWP_FRAMECHANGED;
439             if (!(wndPtr->dwStyle & WS_MINIMIZE))
440             {
441                 if (wndPtr->dwStyle & WS_MAXIMIZE)
442                 {
443                     wndPtr->flags |= WIN_RESTORE_MAX;
444                     wndPtr->dwStyle &= ~WS_MAXIMIZE;
445                 }
446                 else
447                 {
448                     wndPtr->flags &= ~WIN_RESTORE_MAX;
449                     wndPtr->rectNormal = wndPtr->rectWindow;
450                 }
451                 wndPtr->dwStyle |= WS_MINIMIZE;
452                 WINPOS_FindIconPos( hwnd );
453                 x  = wndPtr->ptIconPos.x;
454                 y  = wndPtr->ptIconPos.y;
455                 cx = SYSMETRICS_CXICON;
456                 cy = SYSMETRICS_CYICON;
457             }
458             else swpflags |= SWP_NOSIZE | SWP_NOMOVE;
459             break;
460
461         case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE: */
462             swpflags |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
463             if (!(wndPtr->dwStyle & WS_MAXIMIZE))
464             {
465                   /* Store the current position and find the maximized size */
466                 if (!(wndPtr->dwStyle & WS_MINIMIZE))
467                     wndPtr->rectNormal = wndPtr->rectWindow; 
468
469                 NC_GetMinMaxInfo( hwnd, &maxSize,
470                                   &wndPtr->ptMaxPos, NULL, NULL );
471                 x  = wndPtr->ptMaxPos.x;
472                 y  = wndPtr->ptMaxPos.y;
473
474                 if( wndPtr->dwStyle & WS_MINIMIZE )
475                     if( !SendMessage( hwnd, WM_QUERYOPEN, 0, 0L ) )
476                         {
477                          swpflags |= SWP_NOSIZE;
478                          break;
479                         }
480
481                 cx = maxSize.x;
482                 cy = maxSize.y;
483                 wndPtr->dwStyle &= ~WS_MINIMIZE;
484                 wndPtr->dwStyle |= WS_MAXIMIZE;
485             }
486             else swpflags |= SWP_NOSIZE | SWP_NOMOVE;
487             break;
488
489         case SW_SHOWNA:
490             swpflags |= SWP_NOACTIVATE | SWP_NOZORDER;
491             /* fall through */
492         case SW_SHOW:
493             swpflags |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
494             break;
495
496         case SW_SHOWNOACTIVATE:
497             swpflags |= SWP_NOZORDER;
498             if (GetActiveWindow()) swpflags |= SWP_NOACTIVATE;
499             /* fall through */
500         case SW_SHOWNORMAL:  /* same as SW_NORMAL: */
501         case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
502         case SW_RESTORE:
503             swpflags |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
504
505             if (wndPtr->dwStyle & WS_MINIMIZE)
506             {
507                 if( !SendMessage( hwnd, WM_QUERYOPEN, 0, 0L) )
508                   {
509                     swpflags |= SWP_NOSIZE;
510                     break;
511                   }
512                 wndPtr->ptIconPos.x = wndPtr->rectWindow.left;
513                 wndPtr->ptIconPos.y = wndPtr->rectWindow.top;
514                 wndPtr->dwStyle &= ~WS_MINIMIZE;
515                 if (wndPtr->flags & WIN_RESTORE_MAX)
516                 {
517                     /* Restore to maximized position */
518                     NC_GetMinMaxInfo( hwnd, &maxSize, &wndPtr->ptMaxPos,
519                                       NULL, NULL );
520                     x  = wndPtr->ptMaxPos.x;
521                     y  = wndPtr->ptMaxPos.y;
522                     cx = maxSize.x;
523                     cy = maxSize.y;
524                    wndPtr->dwStyle |= WS_MAXIMIZE;
525                 }
526                 else  /* Restore to normal position */
527                 {
528                     x  = wndPtr->rectNormal.left;
529                     y  = wndPtr->rectNormal.top;
530                     cx = wndPtr->rectNormal.right - wndPtr->rectNormal.left;
531                     cy = wndPtr->rectNormal.bottom - wndPtr->rectNormal.top;
532                 }
533             }
534             else if (wndPtr->dwStyle & WS_MAXIMIZE)
535             {
536                 wndPtr->ptMaxPos.x = wndPtr->rectWindow.left;
537                 wndPtr->ptMaxPos.y = wndPtr->rectWindow.top;
538                 wndPtr->dwStyle &= ~WS_MAXIMIZE;
539                 x  = wndPtr->rectNormal.left;
540                 y  = wndPtr->rectNormal.top;
541                 cx = wndPtr->rectNormal.right - wndPtr->rectNormal.left;
542                 cy = wndPtr->rectNormal.bottom - wndPtr->rectNormal.top;
543             }
544             else swpflags |= SWP_NOSIZE | SWP_NOMOVE;
545             break;
546     }
547
548     SendMessage( hwnd, WM_SHOWWINDOW, (cmd != SW_HIDE), 0 );
549     SetWindowPos( hwnd, HWND_TOP, x, y, cx, cy, swpflags );
550
551       /* Send WM_SIZE and WM_MOVE messages if not already done */
552     if (!(wndPtr->flags & WIN_GOT_SIZEMSG))
553     {
554         int wParam = SIZE_RESTORED;
555         if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
556         else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
557         wndPtr->flags |= WIN_GOT_SIZEMSG;
558         SendMessage( hwnd, WM_SIZE, wParam,
559                      MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
560                             wndPtr->rectClient.bottom-wndPtr->rectClient.top));
561         SendMessage( hwnd, WM_MOVE, 0,
562                    MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
563     }
564
565     return wasVisible;
566 }
567
568
569 /***********************************************************************
570  *           GetInternalWindowPos   (USER.460)
571  */
572 WORD GetInternalWindowPos( HWND hwnd, LPRECT rectWnd, LPPOINT ptIcon )
573 {
574     WINDOWPLACEMENT wndpl;
575     if (!GetWindowPlacement( hwnd, &wndpl )) return 0;
576     if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
577     if (ptIcon)  *ptIcon = wndpl.ptMinPosition;
578     return wndpl.showCmd;
579 }
580
581
582 /***********************************************************************
583  *           SetInternalWindowPos   (USER.461)
584  */
585 void SetInternalWindowPos( HWND hwnd, WORD showCmd, LPRECT rect, LPPOINT pt )
586 {
587     WINDOWPLACEMENT wndpl;
588     WND *wndPtr = WIN_FindWndPtr( hwnd );
589
590     wndpl.length  = sizeof(wndpl);
591     wndpl.flags   = (pt != NULL) ? WPF_SETMINPOSITION : 0;
592     wndpl.showCmd = showCmd;
593     if (pt) wndpl.ptMinPosition = *pt;
594     wndpl.rcNormalPosition = (rect != NULL) ? *rect : wndPtr->rectNormal;
595     wndpl.ptMaxPosition = wndPtr->ptMaxPos;
596     SetWindowPlacement( hwnd, &wndpl );
597 }
598
599
600 /***********************************************************************
601  *           GetWindowPlacement   (USER.370)
602  */
603 BOOL GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *wndpl )
604 {
605     WND *wndPtr = WIN_FindWndPtr( hwnd );
606     if (!wndPtr) return FALSE;
607
608     wndpl->length  = sizeof(*wndpl);
609     wndpl->flags   = 0;
610     wndpl->showCmd = IsZoomed(hwnd) ? SW_SHOWMAXIMIZED : 
611                      (IsIconic(hwnd) ? SW_SHOWMINIMIZED : SW_SHOWNORMAL);
612     wndpl->ptMinPosition = wndPtr->ptIconPos;
613     wndpl->ptMaxPosition = wndPtr->ptMaxPos;
614     wndpl->rcNormalPosition = wndPtr->rectNormal;
615     return TRUE;
616 }
617
618
619 /***********************************************************************
620  *           SetWindowPlacement   (USER.371)
621  */
622 BOOL SetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *wndpl )
623 {
624     WND *wndPtr = WIN_FindWndPtr( hwnd );
625     if (!wndPtr) return FALSE;
626
627     if (wndpl->flags & WPF_SETMINPOSITION)
628         wndPtr->ptIconPos = wndpl->ptMinPosition;
629     if ((wndpl->flags & WPF_RESTORETOMAXIMIZED) &&
630         (wndpl->showCmd == SW_SHOWMINIMIZED)) wndPtr->flags |= WIN_RESTORE_MAX;
631     wndPtr->ptMaxPos   = wndpl->ptMaxPosition;
632     wndPtr->rectNormal = wndpl->rcNormalPosition;
633     ShowWindow( hwnd, wndpl->showCmd );
634     return TRUE;
635 }
636
637 /*******************************************************************
638  *         ACTIVATEAPP_callback
639  */
640 BOOL ACTIVATEAPP_callback(HWND hWnd, LPARAM lParam)
641 {
642     ACTIVATESTRUCT  *lpActStruct = (ACTIVATESTRUCT*)lParam;
643  
644     if (GetWindowTask(hWnd) != lpActStruct->hTaskSendTo) return 1;
645
646     SendMessage( hWnd, WM_ACTIVATEAPP, lpActStruct->wFlag,
647                 (LPARAM)((lpActStruct->hWindowTask)?lpActStruct->hWindowTask:0));
648     return 1;
649 }
650
651
652 /*******************************************************************
653  *         WINPOS_SetActiveWindow
654  *
655  * back-end to SetActiveWindow
656  */
657 BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus )
658 {
659     WND                   *wndPtr          = WIN_FindWndPtr(hWnd);
660     WND                   *wndTemp         = WIN_FindWndPtr(hwndActive);
661     CBTACTIVATESTRUCT      cbtStruct       = { fMouse , hwndActive };
662     FARPROC                enumCallback    = MODULE_GetWndProcEntry16("ActivateAppProc");
663     ACTIVATESTRUCT         actStruct;
664     WORD                   wIconized=0,wRet= 0;
665
666     /* FIXME: When proper support for cooperative multitasking is in place 
667      *        hActiveQ will be global 
668      */
669
670     HANDLE                 hActiveQ = 0;   
671
672     /* paranoid checks */
673     if( !hWnd || hWnd == GetDesktopWindow() || hWnd == hwndActive )
674         return 0;
675
676     if( GetTaskQueue(0) != wndPtr->hmemTaskQ )
677         return 0;
678
679     if( wndTemp )
680         wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
681     else
682         dprintf_win(stddeb,"WINPOS_ActivateWindow: no current active window.\n");
683
684     /* call CBT hook chain */
685     wRet = HOOK_CallHooks(WH_CBT, HCBT_ACTIVATE, (WPARAM)hWnd,
686                           (LPARAM)MAKE_SEGPTR(&cbtStruct));
687
688     if( wRet ) return wRet;
689
690     /* set prev active wnd to current active wnd and send notification */
691     if( (hwndPrevActive = hwndActive) )
692     {
693 /* FIXME: need a Win32 translation for WINELIB32 */
694         if( !SendMessage(hwndPrevActive, WM_NCACTIVATE, 0, MAKELONG(hWnd,wIconized)) )
695         {
696             if (GetSysModalWindow() != hWnd) return 0;
697             /* disregard refusal if hWnd is sysmodal */
698         }
699
700 #ifdef WINELIB32
701         SendMessage( hwndActive, WM_ACTIVATE,
702                      MAKEWPARAM( WA_INACTIVE, wIconized ),
703                      (LPARAM)hWnd );
704 #else
705         SendMessage(hwndPrevActive, WM_ACTIVATE, WA_INACTIVE, 
706                     MAKELONG(hWnd,wIconized));
707 #endif
708
709         /* check if something happened during message processing */
710         if( hwndPrevActive != hwndActive ) return 0;
711     }
712
713     /* set active wnd */
714     hwndActive = hWnd;
715
716     /* send palette messages */
717     if( SendMessage( hWnd, WM_QUERYNEWPALETTE, 0, 0L) )
718         SendMessage((HWND)-1, WM_PALETTEISCHANGING, (WPARAM)hWnd, 0L );
719
720     /* if prev wnd is minimized redraw icon title 
721   if( hwndPrevActive )
722     {
723         wndTemp = WIN_FindWndPtr( WIN_GetTopParent( hwndPrevActive ) );
724         if(wndTemp)
725           if(wndTemp->dwStyle & WS_MINIMIZE)
726             RedrawIconTitle(hwndPrevActive); 
727       } 
728   */
729     if (!(wndPtr->dwStyle & WS_CHILD))
730     {
731         /* check Z-order and bring hWnd to the top */
732         for (wndTemp = WIN_GetDesktop()->child; wndTemp; wndTemp = wndTemp->next)
733             if (wndTemp->dwStyle & WS_VISIBLE) break;
734
735         if( wndTemp != wndPtr )
736             SetWindowPos(hWnd, HWND_TOP, 0,0,0,0, 
737                          SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
738     }
739
740     if( !IsWindow(hWnd) ) return 0;
741
742     if (hwndPrevActive)
743     {
744         wndTemp = WIN_FindWndPtr( hwndPrevActive );
745         if (wndTemp) hActiveQ = wndTemp->hmemTaskQ;
746     }
747
748     /* send WM_ACTIVATEAPP if necessary */
749     if (hActiveQ != wndPtr->hmemTaskQ)
750     {
751         HTASK hT = QUEUE_GetQueueTask( hActiveQ );
752
753         actStruct.wFlag = 0;                  /* deactivate */
754         actStruct.hWindowTask = QUEUE_GetQueueTask(wndPtr->hmemTaskQ);
755         actStruct.hTaskSendTo = hT;
756
757         /* send WM_ACTIVATEAPP to top-level windows
758          * that belong to the actStruct.hTaskSendTo task
759          */
760         EnumWindows( enumCallback , (LPARAM)&actStruct );
761
762         actStruct.wFlag = 1;                  /* activate */
763         actStruct.hWindowTask = hT;
764         actStruct.hTaskSendTo = QUEUE_GetQueueTask( wndPtr->hmemTaskQ );
765
766         EnumWindows( enumCallback , (LPARAM)&actStruct );
767
768         if( !IsWindow(hWnd) ) return 0;
769     }
770
771     /* walk up to the first unowned window */
772     wndTemp = wndPtr;
773     while (wndTemp->owner) wndTemp = wndTemp->owner;
774     /* and set last active owned popup */
775     wndTemp->hwndLastActive = hWnd;
776
777     wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
778 /* FIXME: Needs a Win32 translation for WINELIB32 */
779     SendMessage( hWnd, WM_NCACTIVATE, 1,
780                  MAKELONG(hwndPrevActive,wIconized));
781 #ifdef WINELIB32
782     SendMessage( hWnd, WM_ACTIVATE,
783                  MAKEWPARAM( (fMouse)?WA_CLICKACTIVE:WA_ACTIVE, wIconized),
784                  (LPARAM)hwndPrevActive );
785 #else
786     SendMessage( hWnd, WM_ACTIVATE, (fMouse)? WA_CLICKACTIVE : WA_ACTIVE,
787                  MAKELONG(hwndPrevActive,wIconized));
788 #endif
789
790     if( !IsWindow(hWnd) ) return 0;
791
792     /* change focus if possible */
793     if( fChangeFocus && GetFocus() )
794         if( WIN_GetTopParent(GetFocus()) != hwndActive )
795             FOCUS_SwitchFocus( GetFocus(),
796                                (wndPtr->dwStyle & WS_MINIMIZE)? 0: hwndActive);
797
798     /* if active wnd is minimized redraw icon title 
799   if( hwndActive )
800       {
801         wndPtr = WIN_FindWndPtr(hwndActive);
802         if(wndPtr->dwStyle & WS_MINIMIZE)
803            RedrawIconTitle(hwndActive);
804     }
805   */
806     return (hWnd == hwndActive);
807 }
808
809
810 /*******************************************************************
811  *         WINPOS_ChangeActiveWindow
812  *
813  */
814 BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
815 {
816     WND *wndPtr = WIN_FindWndPtr(hWnd);
817
818     if( !wndPtr ) return FALSE;
819
820     /* child windows get WM_CHILDACTIVATE message */
821     if( (wndPtr->dwStyle & WS_CHILD) && !( wndPtr->dwStyle & WS_POPUP))
822         return SendMessage(hWnd, WM_CHILDACTIVATE, 0, 0L);
823
824         /* owned popups imply owner activation */
825     if( wndPtr->dwStyle & WS_POPUP && wndPtr->owner )
826       {
827         wndPtr = wndPtr->owner;
828         if( !wndPtr ) return FALSE;
829         hWnd = wndPtr->hwndSelf;
830       }
831
832     if( hWnd == hwndActive ) return FALSE;
833
834     if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
835         return FALSE;
836
837     /* switch desktop queue to current active */
838     if( wndPtr->parent == WIN_GetDesktop())
839         WIN_GetDesktop()->hmemTaskQ = wndPtr->hmemTaskQ;
840
841     return TRUE;
842 }
843
844
845 /***********************************************************************
846  *           WINPOS_SendNCCalcSize
847  *
848  * Send a WM_NCCALCSIZE message to a window.
849  * All parameters are read-only except newClientRect.
850  * oldWindowRect, oldClientRect and winpos must be non-NULL only
851  * when calcValidRect is TRUE.
852  */
853 LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect, RECT *newWindowRect,
854                             RECT *oldWindowRect, RECT *oldClientRect,
855                             WINDOWPOS *winpos, RECT *newClientRect )
856 {
857     NCCALCSIZE_PARAMS params;
858     LONG result;
859
860     params.rgrc[0] = *newWindowRect;
861     if (calcValidRect)
862     {
863         params.rgrc[1] = *oldWindowRect;
864         params.rgrc[2] = *oldClientRect;
865         params.lppos = winpos;
866     }
867     result = SendMessage( hwnd, WM_NCCALCSIZE, calcValidRect,
868                           (LPARAM)MAKE_SEGPTR( &params ) );
869     dprintf_win(stddeb, "WINPOS_SendNCCalcSize: %d %d %d %d\n",
870                 (int)params.rgrc[0].top,    (int)params.rgrc[0].left,
871                 (int)params.rgrc[0].bottom, (int)params.rgrc[0].right);
872     *newClientRect = params.rgrc[0];
873     return result;
874 }
875
876
877 /***********************************************************************
878  *           WINPOS_HandleWindowPosChanging
879  *
880  * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
881  */
882 LONG WINPOS_HandleWindowPosChanging( WINDOWPOS *winpos )
883 {
884     POINT maxSize;
885     WND *wndPtr = WIN_FindWndPtr( winpos->hwnd );
886     if (!wndPtr || (winpos->flags & SWP_NOSIZE)) return 0;
887     if ((wndPtr->dwStyle & WS_THICKFRAME) ||
888         ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
889     {
890         NC_GetMinMaxInfo( winpos->hwnd, &maxSize, NULL, NULL, NULL );
891         winpos->cx = MIN( winpos->cx, maxSize.x );
892         winpos->cy = MIN( winpos->cy, maxSize.y );
893     }
894     return 0;
895 }
896
897
898 /***********************************************************************
899  *           WINPOS_MoveWindowZOrder
900  *
901  * Move a window in Z order, invalidating everything that needs it.
902  * Only necessary for windows without associated X window.
903  */
904 static void WINPOS_MoveWindowZOrder( HWND hwnd, HWND hwndAfter )
905 {
906     BOOL movingUp;
907     WND *pWndAfter, *pWndCur, *wndPtr = WIN_FindWndPtr( hwnd );
908
909     /* We have two possible cases:
910      * - The window is moving up: we have to invalidate all areas
911      *   of the window that were covered by other windows
912      * - The window is moving down: we have to invalidate areas
913      *   of other windows covered by this one.
914      */
915
916     if (hwndAfter == HWND_TOP)
917     {
918         movingUp = TRUE;
919     }
920     else if (hwndAfter == HWND_BOTTOM)
921     {
922         if (!wndPtr->next) return;  /* Already at the bottom */
923         movingUp = FALSE;
924     }
925     else
926     {
927         if (!(pWndAfter = WIN_FindWndPtr( hwndAfter ))) return;
928         if (wndPtr->next == pWndAfter) return;  /* Already placed right */
929
930           /* Determine which window we encounter first in Z-order */
931         pWndCur = wndPtr->parent->child;
932         while ((pWndCur != wndPtr) && (pWndCur != pWndAfter))
933             pWndCur = pWndCur->next;
934         movingUp = (pWndCur == pWndAfter);
935     }
936
937     if (movingUp)
938     {
939         WND *pWndPrevAfter = wndPtr->next;
940         WIN_UnlinkWindow( hwnd );
941         WIN_LinkWindow( hwnd, hwndAfter );
942         pWndCur = wndPtr->next;
943         while (pWndCur != pWndPrevAfter)
944         {
945             RECT rect = pWndCur->rectWindow;
946             OffsetRect( &rect, -wndPtr->rectClient.left,
947                         -wndPtr->rectClient.top );
948             RedrawWindow( hwnd, &rect, 0, RDW_INVALIDATE | RDW_ALLCHILDREN |
949                           RDW_FRAME | RDW_ERASE );
950             pWndCur = pWndCur->next;
951         }
952     }
953     else  /* Moving down */
954     {
955         pWndCur = wndPtr->next;
956         WIN_UnlinkWindow( hwnd );
957         WIN_LinkWindow( hwnd, hwndAfter );
958         while (pWndCur != wndPtr)
959         {
960             RECT rect = wndPtr->rectWindow;
961             OffsetRect( &rect, -pWndCur->rectClient.left,
962                         -pWndCur->rectClient.top );
963             RedrawWindow( pWndCur->hwndSelf, &rect, 0, RDW_INVALIDATE |
964                           RDW_ALLCHILDREN | RDW_FRAME | RDW_ERASE );
965             pWndCur = pWndCur->next;
966         }
967     }
968 }
969
970 /***********************************************************************
971  *           WINPOS_ReorderOwnedPopups
972  *
973  * fix Z order taking into account owned popups -
974  * basically we need to maintain them above owner window
975  */
976 HWND WINPOS_ReorderOwnedPopups(HWND hwndInsertAfter, WND* wndPtr, WORD flags)
977 {
978  WND*   w = WIN_GetDesktop();
979
980  w = w->child;
981
982  /* if we are dealing with owned popup... 
983   */
984  if( wndPtr->dwStyle & WS_POPUP && wndPtr->owner && hwndInsertAfter != HWND_TOP )
985    {
986      BOOL bFound = FALSE;
987      HWND hwndLocalPrev = HWND_TOP;
988      HWND hwndNewAfter = 0;
989
990      while( w )
991        {
992          if( !bFound && hwndInsertAfter == hwndLocalPrev )
993              hwndInsertAfter = HWND_TOP;
994
995          if( w->dwStyle & WS_POPUP && w->owner == wndPtr->owner )
996            {
997              bFound = TRUE;
998
999              if( hwndInsertAfter == HWND_TOP )
1000                {
1001                  hwndInsertAfter = hwndLocalPrev;
1002                  break;
1003                }
1004              hwndNewAfter = hwndLocalPrev;
1005            }
1006
1007          if( w == wndPtr->owner )
1008            {
1009              /* basically HWND_BOTTOM */
1010              hwndInsertAfter = hwndLocalPrev;
1011
1012              if( bFound )
1013                  hwndInsertAfter = hwndNewAfter;
1014              break;
1015            }
1016
1017            if( w != wndPtr )
1018                hwndLocalPrev = w->hwndSelf;
1019
1020            w = w->next;
1021         }
1022    }
1023  else 
1024    /* or overlapped top-level window... 
1025     */
1026    if( !(wndPtr->dwStyle & WS_CHILD) )
1027       while( w )
1028         {
1029           if( w == wndPtr ) break;
1030
1031           if( w->dwStyle & WS_POPUP && w->owner == wndPtr )
1032             {
1033               SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1034                                         SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
1035               hwndInsertAfter = w->hwndSelf;
1036             }
1037           w = w->next;
1038         }
1039
1040   return hwndInsertAfter;
1041 }
1042
1043
1044 /***********************************************************************
1045  *           WINPOS_SetXWindowPos
1046  *
1047  * SetWindowPos() for an X window. Used by the real SetWindowPos().
1048  */
1049 static void WINPOS_SetXWindowPos( WINDOWPOS *winpos )
1050 {
1051     XWindowChanges winChanges;
1052     int changeMask = 0;
1053     WND *wndPtr = WIN_FindWndPtr( winpos->hwnd );
1054
1055     if (!(winpos->flags & SWP_NOSIZE))
1056     {
1057         winChanges.width     = winpos->cx;
1058         winChanges.height    = winpos->cy;
1059         changeMask |= CWWidth | CWHeight;
1060     }
1061     if (!(winpos->flags & SWP_NOMOVE))
1062     {
1063         winChanges.x = winpos->x;
1064         winChanges.y = winpos->y;
1065         changeMask |= CWX | CWY;
1066     }
1067     if (!(winpos->flags & SWP_NOZORDER))
1068     {
1069         if (winpos->hwndInsertAfter == HWND_TOP) winChanges.stack_mode = Above;
1070         else winChanges.stack_mode = Below;
1071         if ((winpos->hwndInsertAfter != HWND_TOP) &&
1072             (winpos->hwndInsertAfter != HWND_BOTTOM))
1073         {
1074             WND * insertPtr = WIN_FindWndPtr( winpos->hwndInsertAfter );
1075             winChanges.sibling = insertPtr->window;
1076             changeMask |= CWSibling;
1077         }
1078         changeMask |= CWStackMode;
1079     }
1080     if (changeMask)
1081         XConfigureWindow( display, wndPtr->window, changeMask, &winChanges );
1082 }
1083
1084
1085 /***********************************************************************
1086  *           SetWindowPos   (USER.232)
1087  */
1088 BOOL SetWindowPos( HWND hwnd, HWND hwndInsertAfter, INT x, INT y,
1089                    INT cx, INT cy, WORD flags )
1090 {
1091     WINDOWPOS winpos;
1092     WND *wndPtr;
1093     RECT newWindowRect, newClientRect;
1094     int result;
1095
1096       /* Check window handle */
1097
1098     if (hwnd == GetDesktopWindow()) return FALSE;
1099     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1100
1101     /* Check for windows that may not be resized 
1102        FIXME: this should be done only for Windows 3.0 programs */
1103     if (flags ==(SWP_SHOWWINDOW) || flags ==(SWP_HIDEWINDOW ) )
1104        flags |= SWP_NOSIZE | SWP_NOMOVE;
1105
1106       /* Check dimensions */
1107
1108     if (cx <= 0) cx = 1;
1109     if (cy <= 0) cy = 1;
1110
1111       /* Check flags */
1112
1113     if (hwnd == hwndActive) flags |= SWP_NOACTIVATE;   /* Already active */
1114     if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
1115         (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
1116         flags |= SWP_NOSIZE;    /* Already the right size */
1117     if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
1118         flags |= SWP_NOMOVE;    /* Already the right position */
1119
1120       /* Check hwndInsertAfter */
1121
1122     if (!(flags & (SWP_NOZORDER | SWP_NOACTIVATE)))
1123     {
1124           /* Ignore TOPMOST flags when activating a window */
1125           /* _and_ moving it in Z order. */
1126         if ((hwndInsertAfter == HWND_TOPMOST) ||
1127             (hwndInsertAfter == HWND_NOTOPMOST))
1128             hwndInsertAfter = HWND_TOP; 
1129     }
1130       /* TOPMOST not supported yet */
1131     if ((hwndInsertAfter == HWND_TOPMOST) ||
1132         (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
1133       /* hwndInsertAfter must be a sibling of the window */
1134     if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM) &&
1135         (wndPtr->parent != WIN_FindWndPtr(hwndInsertAfter)->parent))
1136         return FALSE;
1137
1138       /* Fill the WINDOWPOS structure */
1139
1140     winpos.hwnd = hwnd;
1141     winpos.hwndInsertAfter = hwndInsertAfter;
1142     winpos.x = x;
1143     winpos.y = y;
1144     winpos.cx = cx;
1145     winpos.cy = cy;
1146     winpos.flags = flags;
1147     
1148       /* Send WM_WINDOWPOSCHANGING message */
1149
1150     if (!(flags & SWP_NOSENDCHANGING))
1151         SendMessage( hwnd, WM_WINDOWPOSCHANGING, 0, (LPARAM)MAKE_SEGPTR(&winpos) );
1152
1153       /* Calculate new position and size */
1154
1155     newWindowRect = wndPtr->rectWindow;
1156     newClientRect = wndPtr->rectClient;
1157
1158     if (!(winpos.flags & SWP_NOSIZE))
1159     {
1160         newWindowRect.right  = newWindowRect.left + winpos.cx;
1161         newWindowRect.bottom = newWindowRect.top + winpos.cy;
1162     }
1163     if (!(winpos.flags & SWP_NOMOVE))
1164     {
1165         newWindowRect.left    = winpos.x;
1166         newWindowRect.top     = winpos.y;
1167         newWindowRect.right  += winpos.x - wndPtr->rectWindow.left;
1168         newWindowRect.bottom += winpos.y - wndPtr->rectWindow.top;
1169     }
1170
1171       /* Reposition window in Z order */
1172
1173     if (!(winpos.flags & SWP_NOZORDER))
1174     {
1175         /* reorder owned popups if hwnd is top-level window 
1176          */
1177         if( wndPtr->parent == WIN_GetDesktop() )
1178             hwndInsertAfter = WINPOS_ReorderOwnedPopups( hwndInsertAfter,
1179                                                          wndPtr, flags );
1180
1181         if (wndPtr->window)
1182         {
1183             WIN_UnlinkWindow( winpos.hwnd );
1184             WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
1185         }
1186         else WINPOS_MoveWindowZOrder( winpos.hwnd, hwndInsertAfter );
1187     }
1188
1189       /* Send WM_NCCALCSIZE message to get new client area */
1190
1191     result = WINPOS_SendNCCalcSize( winpos.hwnd, TRUE, &newWindowRect,
1192                                     &wndPtr->rectWindow, &wndPtr->rectClient,
1193                                     &winpos, &newClientRect );
1194     /* FIXME: Should handle result here */
1195
1196     /* Perform the moving and resizing */
1197
1198     if (wndPtr->window)
1199     {
1200         HWND bogusInsertAfter = winpos.hwndInsertAfter;
1201
1202         winpos.hwndInsertAfter = hwndInsertAfter;
1203         WINPOS_SetXWindowPos( &winpos );
1204
1205         wndPtr->rectWindow = newWindowRect;
1206         wndPtr->rectClient = newClientRect;
1207         winpos.hwndInsertAfter = bogusInsertAfter;
1208     }
1209     else
1210     {
1211         RECT oldWindowRect = wndPtr->rectWindow;
1212
1213         wndPtr->rectWindow = newWindowRect;
1214         wndPtr->rectClient = newClientRect;
1215
1216         if (!(flags & SWP_NOREDRAW) &&
1217             (!(flags & SWP_NOSIZE) || !(flags & SWP_NOMOVE) ||
1218              (!(flags & SWP_NOZORDER) && (hwndInsertAfter != HWND_TOP))))
1219         {
1220             HRGN hrgn1 = CreateRectRgnIndirect( &oldWindowRect );
1221             HRGN hrgn2 = CreateRectRgnIndirect( &wndPtr->rectWindow );
1222             HRGN hrgn3 = CreateRectRgn( 0, 0, 0, 0 );
1223             CombineRgn( hrgn3, hrgn1, hrgn2, RGN_DIFF );
1224             RedrawWindow( wndPtr->parent->hwndSelf, NULL, hrgn3,
1225                           RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE );
1226
1227             /* DCE_GetVisRgn should be called for old coordinates
1228              * and for new, then OffsetRgn and CombineRgn -
1229              * voila, a nice update region to use here - AK.
1230              */ 
1231             if ((oldWindowRect.left != wndPtr->rectWindow.left) ||
1232                 (oldWindowRect.top != wndPtr->rectWindow.top))
1233             {
1234                 RedrawWindow( winpos.hwnd, NULL, 0, RDW_INVALIDATE |
1235                               RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE );
1236             }
1237             else
1238                 if( CombineRgn( hrgn3, hrgn2, hrgn1, RGN_DIFF) != NULLREGION )
1239                     RedrawWindow( winpos.hwnd, NULL, hrgn3, RDW_INVALIDATE |
1240                                   RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE );
1241
1242             DeleteObject( hrgn1 );
1243             DeleteObject( hrgn2 );
1244             DeleteObject( hrgn3 );
1245         }
1246     }
1247
1248     if (flags & SWP_SHOWWINDOW)
1249     {
1250         wndPtr->dwStyle |= WS_VISIBLE;
1251         if (wndPtr->window)
1252         {
1253             XMapWindow( display, wndPtr->window );
1254         }
1255         else
1256         {
1257             if (!(flags & SWP_NOREDRAW))
1258                 RedrawWindow( winpos.hwnd, NULL, 0,
1259                               RDW_INVALIDATE | RDW_ALLCHILDREN |
1260                               RDW_FRAME | RDW_ERASE );
1261         }
1262     }
1263     else if (flags & SWP_HIDEWINDOW)
1264     {
1265         wndPtr->dwStyle &= ~WS_VISIBLE;
1266         if (wndPtr->window)
1267         {
1268             XUnmapWindow( display, wndPtr->window );
1269         }
1270         else
1271         {
1272             if (!(flags & SWP_NOREDRAW))
1273                 RedrawWindow( wndPtr->parent->hwndSelf, &wndPtr->rectWindow, 0,
1274                               RDW_INVALIDATE | RDW_FRAME |
1275                               RDW_ALLCHILDREN | RDW_ERASE );
1276         }
1277
1278         if ((winpos.hwnd == GetFocus()) || IsChild(winpos.hwnd, GetFocus()))
1279             SetFocus( GetParent(winpos.hwnd) );  /* Revert focus to parent */
1280
1281         if (winpos.hwnd == hwndActive)
1282         {
1283               /* Activate previously active window if possible */
1284             HWND newActive = hwndPrevActive;
1285             if (!IsWindow(newActive) || (newActive == winpos.hwnd))
1286             {
1287                 newActive = GetTopWindow( GetDesktopWindow() );
1288                 if (newActive == winpos.hwnd)
1289                     newActive = wndPtr->next ? wndPtr->next->hwndSelf : 0;
1290             }       
1291             WINPOS_ChangeActiveWindow( newActive, FALSE );
1292         }
1293     }
1294
1295       /* Activate the window */
1296
1297     if (!(flags & SWP_NOACTIVATE))
1298             WINPOS_ChangeActiveWindow( winpos.hwnd, FALSE );
1299     
1300       /* Repaint the window */
1301
1302     if (wndPtr->window) MSG_Synchronize();  /* Wait for all expose events */
1303
1304     EVENT_DummyMotionNotify(); /* Simulate a mouse event to set the cursor */
1305
1306     if ((flags & SWP_FRAMECHANGED) && !(flags & SWP_NOREDRAW))
1307         RedrawWindow( winpos.hwnd, NULL, 0,
1308                       RDW_ALLCHILDREN | /*FIXME: this should not be necessary*/
1309                       RDW_INVALIDATE | RDW_FRAME | RDW_ERASE );
1310     if (!(flags & SWP_DEFERERASE))
1311         RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0,
1312                       RDW_ALLCHILDREN | RDW_ERASENOW );
1313
1314       /* And last, send the WM_WINDOWPOSCHANGED message */
1315
1316     winpos.flags |= SWP_NOMOVE; /* prevent looping.. window is already moved ??? (FIXME)*/
1317
1318     if (!(winpos.flags & SWP_NOSENDCHANGING))
1319         SendMessage( winpos.hwnd, WM_WINDOWPOSCHANGED,
1320                      0, (LPARAM)MAKE_SEGPTR(&winpos) );
1321
1322     return TRUE;
1323 }
1324
1325                                         
1326 /***********************************************************************
1327  *           BeginDeferWindowPos   (USER.259)
1328  */
1329 HDWP BeginDeferWindowPos( INT count )
1330 {
1331     HDWP handle;
1332     DWP *pDWP;
1333
1334     if (count <= 0) return 0;
1335     handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
1336     if (!handle) return 0;
1337     pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
1338     pDWP->actualCount    = 0;
1339     pDWP->suggestedCount = count;
1340     pDWP->valid          = TRUE;
1341     pDWP->wMagic         = DWP_MAGIC;
1342     pDWP->hwndParent     = 0;
1343     return handle;
1344 }
1345
1346
1347 /***********************************************************************
1348  *           DeferWindowPos   (USER.260)
1349  */
1350 HDWP DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter, INT x, INT y,
1351                      INT cx, INT cy, UINT flags )
1352 {
1353     DWP *pDWP;
1354     int i;
1355     HDWP newhdwp = hdwp;
1356     HWND parent;
1357
1358     pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
1359     if (!pDWP) return 0;
1360     if (hwnd == GetDesktopWindow()) return 0;
1361
1362       /* All the windows of a DeferWindowPos() must have the same parent */
1363
1364     parent = WIN_FindWndPtr( hwnd )->parent->hwndSelf;
1365     if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
1366     else if (parent != pDWP->hwndParent)
1367     {
1368         USER_HEAP_FREE( hdwp );
1369         return 0;
1370     }
1371
1372     for (i = 0; i < pDWP->actualCount; i++)
1373     {
1374         if (pDWP->winPos[i].hwnd == hwnd)
1375         {
1376               /* Merge with the other changes */
1377             if (!(flags & SWP_NOZORDER))
1378             {
1379                 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
1380             }
1381             if (!(flags & SWP_NOMOVE))
1382             {
1383                 pDWP->winPos[i].x = x;
1384                 pDWP->winPos[i].y = y;
1385             }                
1386             if (!(flags & SWP_NOSIZE))
1387             {
1388                 pDWP->winPos[i].cx = cx;
1389                 pDWP->winPos[i].cy = cy;
1390             }
1391             pDWP->winPos[i].flags &= flags & (SWP_NOSIZE | SWP_NOMOVE |
1392                                               SWP_NOZORDER | SWP_NOREDRAW |
1393                                               SWP_NOACTIVATE | SWP_NOCOPYBITS |
1394                                               SWP_NOOWNERZORDER);
1395             pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
1396                                               SWP_FRAMECHANGED);
1397             return hdwp;
1398         }
1399     }
1400     if (pDWP->actualCount >= pDWP->suggestedCount)
1401     {
1402         newhdwp = USER_HEAP_REALLOC( hdwp,
1403                       sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
1404         if (!newhdwp) return 0;
1405         pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
1406         pDWP->suggestedCount++;
1407     }
1408     pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
1409     pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
1410     pDWP->winPos[pDWP->actualCount].x = x;
1411     pDWP->winPos[pDWP->actualCount].y = y;
1412     pDWP->winPos[pDWP->actualCount].cx = cx;
1413     pDWP->winPos[pDWP->actualCount].cy = cy;
1414     pDWP->winPos[pDWP->actualCount].flags = flags;
1415     pDWP->actualCount++;
1416     return newhdwp;
1417 }
1418
1419
1420 /***********************************************************************
1421  *           EndDeferWindowPos   (USER.261)
1422  */
1423 BOOL EndDeferWindowPos( HDWP hdwp )
1424 {
1425     DWP *pDWP;
1426     WINDOWPOS *winpos;
1427     BOOL res = TRUE;
1428     int i;
1429
1430     pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
1431     if (!pDWP) return FALSE;
1432     for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
1433     {
1434         if (!(res = SetWindowPos( winpos->hwnd, winpos->hwndInsertAfter,
1435                                   winpos->x, winpos->y, winpos->cx, winpos->cy,
1436                                   winpos->flags ))) break;
1437     }
1438     USER_HEAP_FREE( hdwp );
1439     return res;
1440 }
1441
1442
1443 /***********************************************************************
1444  *           TileChildWindows   (USER.199)
1445  */
1446 void TileChildWindows( HWND parent, WORD action )
1447 {
1448     printf("STUB TileChildWindows(%04x, %d)\n", parent, action);
1449 }
1450
1451 /***********************************************************************
1452  *           CascageChildWindows   (USER.198)
1453  */
1454 void CascadeChildWindows( HWND parent, WORD action )
1455 {
1456     printf("STUB CascadeChildWindows(%04x, %d)\n", parent, action);
1457 }