Make sure that HWND comparisons are always done with full 32-bit
[wine] / dlls / x11drv / winpos.c
1 /*
2  * Window position related functions.
3  *
4  * Copyright 1993, 1994, 1995, 2001 Alexandre Julliard
5  * Copyright 1995, 1996, 1999 Alex Korobka
6  */
7
8 #include "config.h"
9
10 #include "ts_xlib.h"
11 #include "ts_xutil.h"
12 #include "ts_shape.h"
13
14 #include "winbase.h"
15 #include "wingdi.h"
16 #include "winuser.h"
17
18 #include "x11drv.h"
19 #include "hook.h"
20 #include "win.h"
21 #include "winpos.h"
22 #include "region.h"
23 #include "dce.h"
24 #include "cursoricon.h"
25 #include "nonclient.h"
26 #include "message.h"
27
28 #include "debugtools.h"
29
30 DEFAULT_DEBUG_CHANNEL(x11drv);
31
32 #define SWP_AGG_NOGEOMETRYCHANGE \
33     (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
34 #define SWP_AGG_NOPOSCHANGE \
35     (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
36 #define SWP_AGG_STATUSFLAGS \
37     (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
38
39 #define SWP_EX_NOCOPY       0x0001
40 #define SWP_EX_PAINTSELF    0x0002
41 #define SWP_EX_NONCLIENT    0x0004
42
43 #define HAS_THICKFRAME(style,exStyle) \
44     (((style) & WS_THICKFRAME) && \
45      !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
46
47 #define ON_LEFT_BORDER(hit) \
48  (((hit) == HTLEFT) || ((hit) == HTTOPLEFT) || ((hit) == HTBOTTOMLEFT))
49 #define ON_RIGHT_BORDER(hit) \
50  (((hit) == HTRIGHT) || ((hit) == HTTOPRIGHT) || ((hit) == HTBOTTOMRIGHT))
51 #define ON_TOP_BORDER(hit) \
52  (((hit) == HTTOP) || ((hit) == HTTOPLEFT) || ((hit) == HTTOPRIGHT))
53 #define ON_BOTTOM_BORDER(hit) \
54  (((hit) == HTBOTTOM) || ((hit) == HTBOTTOMLEFT) || ((hit) == HTBOTTOMRIGHT))
55
56
57 /***********************************************************************
58  *              clip_children
59  *
60  * Clip all children of a given window out of the visible region
61  */
62 static int clip_children( WND *win, WND *last, HRGN hrgn, int whole_window )
63 {
64     WND *ptr;
65     HRGN rectRgn;
66     int x, y, ret = SIMPLEREGION;
67
68     /* first check if we have anything to do */
69     for (ptr = win->child; ptr && ptr != last; ptr = ptr->next)
70         if (ptr->dwStyle & WS_VISIBLE) break;
71     if (!ptr || ptr == last) return ret; /* no children to clip */
72
73     if (whole_window)
74     {
75         x = win->rectWindow.left - win->rectClient.left;
76         y = win->rectWindow.top - win->rectClient.top;
77     }
78     else x = y = 0;
79
80     rectRgn = CreateRectRgn( 0, 0, 0, 0 );
81     while (ptr && ptr != last)
82     {
83         if (ptr->dwStyle & WS_VISIBLE)
84         {
85             SetRectRgn( rectRgn, ptr->rectWindow.left + x, ptr->rectWindow.top + y,
86                         ptr->rectWindow.right + x, ptr->rectWindow.bottom + y );
87             if ((ret = CombineRgn( hrgn, hrgn, rectRgn, RGN_DIFF )) == NULLREGION)
88                 break;  /* no need to go on, region is empty */
89         }
90         ptr = ptr->next;
91     }
92     DeleteObject( rectRgn );
93     return ret;
94 }
95
96
97 /***********************************************************************
98  *              get_visible_region
99  *
100  * Compute the visible region of a window
101  */
102 static HRGN get_visible_region( WND *win, WND *top, UINT flags, int mode )
103 {
104     HRGN rgn;
105     RECT rect;
106     int xoffset, yoffset;
107     X11DRV_WND_DATA *data = win->pDriverData;
108
109     if (flags & DCX_WINDOW)
110     {
111         xoffset = win->rectWindow.left;
112         yoffset = win->rectWindow.top;
113     }
114     else
115     {
116         xoffset = win->rectClient.left;
117         yoffset = win->rectClient.top;
118     }
119
120     if (flags & DCX_PARENTCLIP)
121         GetClientRect( win->parent->hwndSelf, &rect );
122     else if (flags & DCX_WINDOW)
123         rect = data->whole_rect;
124     else
125         rect = win->rectClient;
126
127     /* vis region is relative to the start of the client/window area */
128     OffsetRect( &rect, -xoffset, -yoffset );
129
130     if (!(rgn = CreateRectRgn( rect.left, rect.top, rect.right, rect.bottom ))) return 0;
131
132     if ((flags & DCX_CLIPCHILDREN) && (mode != ClipByChildren))
133     {
134         /* we need to clip children by hand */
135         if (clip_children( win, NULL, rgn, (flags & DCX_WINDOW) ) == NULLREGION) return rgn;
136     }
137
138     if (top && top != win)  /* need to clip siblings of ancestors */
139     {
140         WND *ptr = win;
141         HRGN tmp = 0;
142
143         OffsetRgn( rgn, xoffset, yoffset );
144         for (;;)
145         {
146             if (ptr->dwStyle & WS_CLIPSIBLINGS)
147             {
148                 if (clip_children( ptr->parent, ptr, rgn, FALSE ) == NULLREGION) break;
149             }
150             if (ptr == top) break;
151             ptr = ptr->parent;
152             /* clip to parent client area */
153             if (tmp) SetRectRgn( tmp, 0, 0, ptr->rectClient.right - ptr->rectClient.left,
154                                  ptr->rectClient.bottom - ptr->rectClient.top );
155             else tmp = CreateRectRgn( 0, 0, ptr->rectClient.right - ptr->rectClient.left,
156                                       ptr->rectClient.bottom - ptr->rectClient.top );
157             CombineRgn( rgn, rgn, tmp, RGN_AND );
158             OffsetRgn( rgn, ptr->rectClient.left, ptr->rectClient.top );
159             xoffset += ptr->rectClient.left;
160             yoffset += ptr->rectClient.top;
161         }
162         /* make it relative to the target window again */
163         OffsetRgn( rgn, -xoffset, -yoffset );
164         if (tmp) DeleteObject( tmp );
165     }
166
167     return rgn;
168 }
169
170
171 /***********************************************************************
172  *              get_covered_region
173  *
174  * Compute the portion of 'rgn' that is covered by non-clipped siblings.
175  * This is the area that is covered from X point of view, but may still need
176  * to be exposed.
177  * 'rgn' must be relative to the client area of the parent of 'win'.
178  */
179 static int get_covered_region( WND *win, HRGN rgn )
180 {
181     HRGN tmp;
182     int ret;
183     WND *ptr = win;
184     int xoffset = 0, yoffset = 0;
185
186     tmp = CreateRectRgn( 0, 0, 0, 0 );
187     CombineRgn( tmp, rgn, 0, RGN_COPY );
188
189     /* to make things easier we actually build the uncovered
190      * area by removing all siblings and then we subtract that
191      * from the total region to get the covered area */
192     for (;;)
193     {
194         if (!(ptr->dwStyle & WS_CLIPSIBLINGS))
195         {
196             if (clip_children( ptr->parent, ptr, tmp, FALSE ) == NULLREGION) break;
197         }
198         if (!(ptr = ptr->parent)) break;
199         OffsetRgn( tmp, ptr->rectClient.left, ptr->rectClient.top );
200         xoffset += ptr->rectClient.left;
201         yoffset += ptr->rectClient.top;
202     }
203     /* make it relative to the target window again */
204     OffsetRgn( tmp, -xoffset, -yoffset );
205
206     /* now subtract the computed region from the original one */
207     ret = CombineRgn( rgn, rgn, tmp, RGN_DIFF );
208     DeleteObject( tmp );
209     return ret;
210 }
211
212
213 /***********************************************************************
214  *              expose_window
215  *
216  * Expose a region of a given window.
217  */
218 static void expose_window( WND *win, RECT *rect, HRGN rgn, int flags )
219 {
220     WND *ptr, *top;
221     int xoffset = 0, yoffset = 0;
222
223     /* find the top most parent that doesn't clip children or siblings and
224      * invalidate the area on its parent, including all children */
225     top = NULL;
226     for (ptr = win; ptr && ptr->parent; ptr = ptr->parent)
227     {
228         if (!(ptr->dwStyle & WS_CLIPSIBLINGS)) top = ptr;
229         if (!(ptr->parent->dwStyle & WS_CLIPCHILDREN)) top = ptr;
230     }
231
232     if (top)
233     {
234         if (top->parent && top->parent->hwndSelf != GetDesktopWindow()) top = top->parent;
235         flags &= ~RDW_FRAME;  /* parent will invalidate children frame anyway */
236         flags |= RDW_ALLCHILDREN;
237     }
238     else top = win;
239
240     /* make coords relative to top */
241     for (ptr = win; ptr != top; ptr = ptr->parent)
242     {
243         xoffset += ptr->rectClient.left;
244         yoffset += ptr->rectClient.top;
245     }
246
247     if (rect)
248     {
249         OffsetRect( rect, xoffset, yoffset );
250         RedrawWindow( top->hwndSelf, rect, 0, flags );
251     }
252     else
253     {
254         OffsetRgn( rgn, xoffset, yoffset );
255         RedrawWindow( top->hwndSelf, NULL, rgn, flags );
256     }
257 }
258
259
260 /***********************************************************************
261  *              expose_covered_parent_area
262  *
263  * Expose the parent area that has been uncovered by moving/hiding a
264  * given window, but that is still covered by other siblings (the area
265  * not covered by siblings will be exposed automatically by X).
266  */
267 static void expose_covered_parent_area( WND *win, const RECT *old_rect )
268 {
269     int ret = SIMPLEREGION;
270     HRGN hrgn = CreateRectRgnIndirect( old_rect );
271
272     if (win->dwStyle & WS_VISIBLE)
273     {
274         HRGN tmp = CreateRectRgnIndirect( &win->rectWindow );
275         ret = CombineRgn( hrgn, hrgn, tmp, RGN_DIFF );
276         DeleteObject( tmp );
277     }
278
279     if (ret != NULLREGION)
280     {
281         if (get_covered_region( win, hrgn ) != NULLREGION)
282             expose_window( win->parent, NULL, hrgn, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN );
283     }
284     DeleteObject( hrgn );
285 }
286
287
288 /***********************************************************************
289  *              expose_covered_window_area
290  *
291  * Expose the area of a window that is covered by other siblings.
292  */
293 static void expose_covered_window_area( WND *win, const RECT *old_client_rect, BOOL frame )
294 {
295     HRGN hrgn;
296     int ret = SIMPLEREGION;
297
298     if (frame)
299         hrgn = CreateRectRgn( win->rectWindow.left - win->rectClient.left,
300                               win->rectWindow.top - win->rectClient.top,
301                               win->rectWindow.right - win->rectWindow.left,
302                               win->rectWindow.bottom - win->rectWindow.top );
303     else
304         hrgn = CreateRectRgn( 0, 0,
305                               win->rectClient.right - win->rectClient.left,
306                               win->rectClient.bottom - win->rectClient.top );
307
308     /* if the client rect didn't move we don't need to repaint it all */
309     if (old_client_rect->left == win->rectClient.left &&
310         old_client_rect->top == win->rectClient.top)
311     {
312         RECT rc;
313
314         if (IntersectRect( &rc, old_client_rect, &win->rectClient ))
315         {
316             HRGN tmp;
317             /* subtract the unchanged client area from the region to expose */
318             OffsetRect( &rc, -win->rectClient.left, -win->rectClient.top );
319             if ((tmp = CreateRectRgnIndirect( &rc )))
320             {
321                 ret = CombineRgn( hrgn, hrgn, tmp, RGN_DIFF );
322                 DeleteObject( tmp );
323             }
324         }
325     }
326
327     if (ret != NULLREGION)
328     {
329         if (get_covered_region( win, hrgn ) != NULLREGION)
330             expose_window( win, NULL, hrgn,
331                            RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN );
332     }
333
334     DeleteObject( hrgn );
335 }
336
337
338 /***********************************************************************
339  *           X11DRV_Expose
340  */
341 void X11DRV_Expose( HWND hwnd, XExposeEvent *event )
342 {
343     RECT rect;
344     struct x11drv_win_data *data;
345     int flags = RDW_INVALIDATE | RDW_ERASE;
346     WND *win;
347
348     TRACE( "win %x (%lx) %d,%d %dx%d\n",
349            hwnd, event->window, event->x, event->y, event->width, event->height );
350
351     rect.left   = event->x;
352     rect.top    = event->y;
353     rect.right  = rect.left + event->width;
354     rect.bottom = rect.top + event->height;
355
356     if (!(win = WIN_FindWndPtr(hwnd))) return;
357     data = win->pDriverData;
358
359     if (event->window != data->client_window)  /* whole window or icon window */
360     {
361         flags |= RDW_FRAME;
362         /* make position relative to client area instead of window */
363         OffsetRect( &rect, -data->client_rect.left, -data->client_rect.top );
364     }
365
366     expose_window( win, &rect, 0, flags );
367     WIN_ReleaseWndPtr( win );
368 }
369
370
371 /***********************************************************************
372  *              GetDC (X11DRV.@)
373  *
374  * Set the drawable, origin and dimensions for the DC associated to
375  * a given window.
376  */
377 BOOL X11DRV_GetDC( HWND hwnd, HDC hdc, HRGN hrgn, DWORD flags )
378 {
379     WND *win = WIN_FindWndPtr( hwnd );
380     WND *ptr, *top;
381     X11DRV_WND_DATA *data = win->pDriverData;
382     Drawable drawable;
383     BOOL visible;
384     int org_x, org_y, mode = IncludeInferiors;
385
386     /* don't clip siblings if using parent clip region */
387     if (flags & DCX_PARENTCLIP) flags &= ~DCX_CLIPSIBLINGS;
388
389     /* find the top parent in the hierarchy that isn't clipping siblings */
390     top = NULL;
391     visible = (win->dwStyle & WS_VISIBLE) != 0;
392
393     if (visible)
394     {
395         for (ptr = win->parent; ptr && ptr->parent; ptr = ptr->parent)
396         {
397             if (!(ptr->dwStyle & WS_VISIBLE))
398             {
399                 visible = FALSE;
400                 top = NULL;
401                 break;
402             }
403             if (!(ptr->dwStyle & WS_CLIPSIBLINGS)) top = ptr;
404         }
405         if (!top && visible && !(flags & DCX_CLIPSIBLINGS)) top = win;
406     }
407
408     if (top)
409     {
410         org_x = org_y = 0;
411         if (flags & DCX_WINDOW)
412         {
413             org_x = win->rectWindow.left - win->rectClient.left;
414             org_y = win->rectWindow.top - win->rectClient.top;
415         }
416         for (ptr = win; ptr != top->parent; ptr = ptr->parent)
417         {
418             org_x += ptr->rectClient.left;
419             org_y += ptr->rectClient.top;
420         }
421         /* have to use the parent so that we include siblings */
422         if (top->parent) drawable = get_client_window( top->parent );
423         else drawable = root_window;
424     }
425     else
426     {
427         if (IsIconic( hwnd ))
428         {
429             drawable = data->icon_window ? data->icon_window : data->whole_window;
430             org_x = 0;
431             org_y = 0;
432         }
433         else if (flags & DCX_WINDOW)
434         {
435             drawable = data->whole_window;
436             org_x = win->rectWindow.left - data->whole_rect.left;
437             org_y = win->rectWindow.top - data->whole_rect.top;
438         }
439         else
440         {
441             drawable = data->client_window;
442             org_x = 0;
443             org_y = 0;
444             if (flags & DCX_CLIPCHILDREN) mode = ClipByChildren;  /* can use X11 clipping */
445         }
446     }
447
448     X11DRV_SetDrawable( hdc, drawable, mode, org_x, org_y );
449
450     if (flags & (DCX_EXCLUDERGN | DCX_INTERSECTRGN) ||
451         SetHookFlags16( hdc, DCHF_VALIDATEVISRGN ))  /* DC was dirty */
452     {
453         /* need to recompute the visible region */
454         HRGN visRgn;
455
456         if (visible)
457         {
458             visRgn = get_visible_region( win, top, flags, mode );
459
460             if (flags & (DCX_EXCLUDERGN | DCX_INTERSECTRGN))
461                 CombineRgn( visRgn, visRgn, hrgn,
462                             (flags & DCX_INTERSECTRGN) ? RGN_AND : RGN_DIFF );
463
464             /* make it relative to the drawable origin */
465             OffsetRgn( visRgn, org_x, org_y );
466         }
467         else visRgn = CreateRectRgn( 0, 0, 0, 0 );
468
469         SelectVisRgn16( hdc, visRgn );
470         DeleteObject( visRgn );
471     }
472
473     WIN_ReleaseWndPtr( win );
474     return TRUE;
475 }
476
477
478
479 /***********************************************************************
480  *           SWP_DoWinPosChanging
481  */
482 static BOOL SWP_DoWinPosChanging( WINDOWPOS* pWinpos, RECT* pNewWindowRect, RECT* pNewClientRect )
483 {
484     WND *wndPtr;
485
486     /* Send WM_WINDOWPOSCHANGING message */
487
488     if (!(pWinpos->flags & SWP_NOSENDCHANGING))
489         SendMessageA( pWinpos->hwnd, WM_WINDOWPOSCHANGING, 0, (LPARAM)pWinpos );
490
491     if (!(wndPtr = WIN_FindWndPtr( pWinpos->hwnd ))) return FALSE;
492
493     /* Calculate new position and size */
494
495     *pNewWindowRect = wndPtr->rectWindow;
496     *pNewClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
497                                                     : wndPtr->rectClient;
498
499     if (!(pWinpos->flags & SWP_NOSIZE))
500     {
501         pNewWindowRect->right  = pNewWindowRect->left + pWinpos->cx;
502         pNewWindowRect->bottom = pNewWindowRect->top + pWinpos->cy;
503     }
504     if (!(pWinpos->flags & SWP_NOMOVE))
505     {
506         pNewWindowRect->left    = pWinpos->x;
507         pNewWindowRect->top     = pWinpos->y;
508         pNewWindowRect->right  += pWinpos->x - wndPtr->rectWindow.left;
509         pNewWindowRect->bottom += pWinpos->y - wndPtr->rectWindow.top;
510
511         OffsetRect( pNewClientRect, pWinpos->x - wndPtr->rectWindow.left,
512                                     pWinpos->y - wndPtr->rectWindow.top );
513     }
514     pWinpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
515     WIN_ReleaseWndPtr( wndPtr );
516     return TRUE;
517 }
518
519 /***********************************************************************
520  *           SWP_DoNCCalcSize
521  */
522 static UINT SWP_DoNCCalcSize( WND* wndPtr, WINDOWPOS* pWinpos,
523                               RECT* pNewWindowRect, RECT* pNewClientRect )
524 {
525     UINT wvrFlags = 0;
526
527       /* Send WM_NCCALCSIZE message to get new client area */
528     if( (pWinpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
529     {
530          wvrFlags = WINPOS_SendNCCalcSize( pWinpos->hwnd, TRUE, pNewWindowRect,
531                                     &wndPtr->rectWindow, &wndPtr->rectClient,
532                                     pWinpos, pNewClientRect );
533          /* FIXME: WVR_ALIGNxxx */
534
535          if( pNewClientRect->left != wndPtr->rectClient.left ||
536              pNewClientRect->top != wndPtr->rectClient.top )
537              pWinpos->flags &= ~SWP_NOCLIENTMOVE;
538
539          if( (pNewClientRect->right - pNewClientRect->left !=
540               wndPtr->rectClient.right - wndPtr->rectClient.left) ||
541              (pNewClientRect->bottom - pNewClientRect->top !=
542               wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
543              pWinpos->flags &= ~SWP_NOCLIENTSIZE;
544     }
545     else
546       if( !(pWinpos->flags & SWP_NOMOVE) && (pNewClientRect->left != wndPtr->rectClient.left ||
547                                              pNewClientRect->top != wndPtr->rectClient.top) )
548             pWinpos->flags &= ~SWP_NOCLIENTMOVE;
549     return wvrFlags;
550 }
551
552 /***********************************************************************
553  *           SWP_DoOwnedPopups
554  *
555  * fix Z order taking into account owned popups -
556  * basically we need to maintain them above the window that owns them
557  *
558  * FIXME: hide/show owned popups when owner visibility changes.
559  */
560 static HWND SWP_DoOwnedPopups(HWND hwnd, HWND hwndInsertAfter)
561 {
562     HWND *list = NULL;
563     HWND owner = GetWindow( hwnd, GW_OWNER );
564     LONG style = GetWindowLongW( hwnd, GWL_STYLE );
565
566     WARN("(%04x) hInsertAfter = %04x\n", hwnd, hwndInsertAfter );
567
568     if ((style & WS_POPUP) && owner)
569     {
570         /* make sure this popup stays above the owner */
571
572         HWND hwndLocalPrev = HWND_TOP;
573
574         if( hwndInsertAfter != HWND_TOP )
575         {
576             if ((list = WIN_ListChildren( GetDesktopWindow() )))
577             {
578                 int i;
579                 for (i = 0; list[i]; i++)
580                 {
581                     if (list[i] == owner) break;
582                     if (list[i] != hwnd) hwndLocalPrev = list[i];
583                     if (hwndLocalPrev == hwndInsertAfter) break;
584                 }
585                 hwndInsertAfter = hwndLocalPrev;
586             }
587         }
588     }
589     else if (style & WS_CHILD) return hwndInsertAfter;
590
591     if (!list) list = WIN_ListChildren( GetDesktopWindow() );
592     if (list)
593     {
594         int i;
595         for (i = 0; list[i]; i++)
596         {
597             if (list[i] == hwnd) break;
598             if ((GetWindowLongW( list[i], GWL_STYLE ) & WS_POPUP) &&
599                 GetWindow( list[i], GW_OWNER ) == hwnd)
600             {
601                 SetWindowPos( list[i], hwndInsertAfter, 0, 0, 0, 0,
602                               SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE |
603                               SWP_NOSENDCHANGING | SWP_DEFERERASE );
604                 hwndInsertAfter = list[i];
605             }
606         }
607         HeapFree( GetProcessHeap(), 0, list );
608     }
609
610     return hwndInsertAfter;
611 }
612
613
614 /* fix redundant flags and values in the WINDOWPOS structure */
615 static BOOL fixup_flags( WINDOWPOS *winpos )
616 {
617     WND *wndPtr = WIN_FindWndPtr( winpos->hwnd );
618     BOOL ret = TRUE;
619
620     if (!wndPtr) return FALSE;
621     winpos->hwnd = wndPtr->hwndSelf;  /* make it a full handle */
622
623     if (wndPtr->dwStyle & WS_VISIBLE) winpos->flags &= ~SWP_SHOWWINDOW;
624     else
625     {
626         winpos->flags &= ~SWP_HIDEWINDOW;
627         if (!(winpos->flags & SWP_SHOWWINDOW)) winpos->flags |= SWP_NOREDRAW;
628     }
629
630     if (winpos->cx < 0) winpos->cx = 0;
631     if (winpos->cy < 0) winpos->cy = 0;
632
633     if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == winpos->cx) &&
634         (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == winpos->cy))
635         winpos->flags |= SWP_NOSIZE;    /* Already the right size */
636
637     if ((wndPtr->rectWindow.left == winpos->x) && (wndPtr->rectWindow.top == winpos->y))
638         winpos->flags |= SWP_NOMOVE;    /* Already the right position */
639
640     if (winpos->hwnd == GetForegroundWindow())
641         winpos->flags |= SWP_NOACTIVATE;   /* Already active */
642     else if ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)
643     {
644         if (!(winpos->flags & SWP_NOACTIVATE)) /* Bring to the top when activating */
645         {
646             winpos->flags &= ~SWP_NOZORDER;
647             winpos->hwndInsertAfter = HWND_TOP;
648             goto done;
649         }
650     }
651
652     /* Check hwndInsertAfter */
653
654       /* FIXME: TOPMOST not supported yet */
655     if ((winpos->hwndInsertAfter == HWND_TOPMOST) ||
656         (winpos->hwndInsertAfter == HWND_NOTOPMOST)) winpos->hwndInsertAfter = HWND_TOP;
657
658     /* hwndInsertAfter must be a sibling of the window */
659     if ((winpos->hwndInsertAfter != HWND_TOP) && (winpos->hwndInsertAfter != HWND_BOTTOM))
660     {
661         WND* wnd = WIN_FindWndPtr(winpos->hwndInsertAfter);
662         if (wnd)
663         {
664             winpos->hwndInsertAfter = wnd->hwndSelf;  /* make it a full handle */
665             if (wnd->parent != wndPtr->parent) ret = FALSE;
666             else
667             {
668                 /* don't need to change the Zorder of hwnd if it's already inserted
669                  * after hwndInsertAfter or when inserting hwnd after itself.
670                  */
671                 if ((wnd->next == wndPtr ) || (winpos->hwnd == winpos->hwndInsertAfter))
672                     winpos->flags |= SWP_NOZORDER;
673             }
674             WIN_ReleaseWndPtr(wnd);
675         }
676     }
677  done:
678     WIN_ReleaseWndPtr(wndPtr);
679     return ret;
680 }
681
682
683 /***********************************************************************
684  *              SetWindowPos   (X11DRV.@)
685  */
686 BOOL X11DRV_SetWindowPos( WINDOWPOS *winpos )
687 {
688     WND *wndPtr;
689     RECT newWindowRect, newClientRect;
690     RECT oldWindowRect, oldClientRect;
691     UINT wvrFlags = 0;
692     BOOL bChangePos;
693
694     TRACE( "hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
695            winpos->hwnd, winpos->x, winpos->y,
696            winpos->x + winpos->cx, winpos->y + winpos->cy, winpos->flags);
697
698     bChangePos = !(winpos->flags & SWP_WINE_NOHOSTMOVE);
699     winpos->flags &= ~SWP_WINE_NOHOSTMOVE;
700
701     /* Fix redundant flags */
702     if (!fixup_flags( winpos )) return FALSE;
703
704     /* Check window handle */
705     if (winpos->hwnd == GetDesktopWindow()) return FALSE;
706
707     SWP_DoWinPosChanging( winpos, &newWindowRect, &newClientRect );
708
709     if (!(wndPtr = WIN_FindWndPtr( winpos->hwnd ))) return FALSE;
710
711     TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n",
712           wndPtr->rectWindow.left, wndPtr->rectWindow.top,
713           wndPtr->rectWindow.right, wndPtr->rectWindow.bottom, (unsigned)wndPtr->dwStyle );
714
715     if((winpos->flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER)
716     {
717         if (GetAncestor( winpos->hwnd, GA_PARENT ) == GetDesktopWindow())
718             winpos->hwndInsertAfter = SWP_DoOwnedPopups( winpos->hwnd, winpos->hwndInsertAfter );
719     }
720
721     /* Common operations */
722
723     wvrFlags = SWP_DoNCCalcSize( wndPtr, winpos, &newWindowRect, &newClientRect );
724
725     if(!(winpos->flags & SWP_NOZORDER) && winpos->hwnd != winpos->hwndInsertAfter)
726     {
727         HWND parent = GetAncestor( winpos->hwnd, GA_PARENT );
728         if (parent) WIN_LinkWindow( winpos->hwnd, parent, winpos->hwndInsertAfter );
729     }
730
731     /* Reset active DCEs */
732
733     if( (((winpos->flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) &&
734          wndPtr->dwStyle & WS_VISIBLE) ||
735         (winpos->flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
736     {
737         RECT rect;
738
739         UnionRect(&rect, &newWindowRect, &wndPtr->rectWindow);
740         DCE_InvalidateDCE(wndPtr->hwndSelf, &rect);
741     }
742
743     oldWindowRect = wndPtr->rectWindow;
744     oldClientRect = wndPtr->rectClient;
745
746     /* Find out if we have to redraw the whole client rect */
747
748     if( oldClientRect.bottom - oldClientRect.top ==
749         newClientRect.bottom - newClientRect.top ) wvrFlags &= ~WVR_VREDRAW;
750
751     if( oldClientRect.right - oldClientRect.left ==
752         newClientRect.right - newClientRect.left ) wvrFlags &= ~WVR_HREDRAW;
753
754     /* FIXME: actually do something with WVR_VALIDRECTS */
755
756     wndPtr->rectWindow = newWindowRect;
757     wndPtr->rectClient = newClientRect;
758
759     if (winpos->flags & SWP_SHOWWINDOW) wndPtr->dwStyle |= WS_VISIBLE;
760     else if (winpos->flags & SWP_HIDEWINDOW)
761     {
762         /* clear the update region */
763         RedrawWindow( winpos->hwnd, NULL, 0, RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE |
764                                              RDW_NOINTERNALPAINT | RDW_ALLCHILDREN );
765         wndPtr->dwStyle &= ~WS_VISIBLE;
766     }
767
768     if (get_whole_window(wndPtr))  /* don't do anything if X window not created yet */
769     {
770         Display *display = thread_display();
771
772         wine_tsx11_lock();
773         if (!(winpos->flags & SWP_SHOWWINDOW) && (winpos->flags & SWP_HIDEWINDOW))
774         {
775             if (!IsRectEmpty( &oldWindowRect ))
776             {
777                 XUnmapWindow( display, get_whole_window(wndPtr) );
778                 TRACE( "unmapping win %x\n", winpos->hwnd );
779             }
780             else TRACE( "not unmapping zero size win %x\n", winpos->hwnd );
781         }
782         else if ((wndPtr->dwStyle & WS_VISIBLE) &&
783                  !IsRectEmpty( &oldWindowRect ) && IsRectEmpty( &newWindowRect ))
784         {
785             /* resizing to zero size -> unmap */
786             TRACE( "unmapping zero size win %x\n", winpos->hwnd );
787             XUnmapWindow( display, get_whole_window(wndPtr) );
788         }
789
790         if (bChangePos)
791             X11DRV_sync_whole_window_position( display, wndPtr, !(winpos->flags & SWP_NOZORDER) );
792         else
793         {
794             struct x11drv_win_data *data = wndPtr->pDriverData;
795             data->whole_rect = wndPtr->rectWindow;
796             X11DRV_window_to_X_rect( wndPtr, &data->whole_rect );
797         }
798
799         if (X11DRV_sync_client_window_position( display, wndPtr ) ||
800             (winpos->flags & SWP_FRAMECHANGED))
801         {
802             /* if we moved the client area, repaint the whole non-client window */
803             XClearArea( display, get_whole_window(wndPtr), 0, 0, 0, 0, True );
804             winpos->flags |= SWP_FRAMECHANGED;
805         }
806         if (winpos->flags & SWP_SHOWWINDOW)
807         {
808             if (!IsRectEmpty( &newWindowRect ))
809             {
810                 XMapWindow( display, get_whole_window(wndPtr) );
811                 TRACE( "mapping win %x\n", winpos->hwnd );
812             }
813             else TRACE( "not mapping win %x, size is zero\n", winpos->hwnd );
814         }
815         else if ((wndPtr->dwStyle & WS_VISIBLE) &&
816                  IsRectEmpty( &oldWindowRect ) && !IsRectEmpty( &newWindowRect ))
817         {
818             /* resizing from zero size to non-zero -> map */
819             TRACE( "mapping non zero size win %x\n", winpos->hwnd );
820             XMapWindow( display, get_whole_window(wndPtr) );
821         }
822         XFlush( display );  /* FIXME: should not be necessary */
823         wine_tsx11_unlock();
824     }
825
826     /* manually expose the areas that X won't expose because they are still covered by something */
827
828     if (!(winpos->flags & SWP_SHOWWINDOW))
829         expose_covered_parent_area( wndPtr, &oldWindowRect );
830
831     if (wndPtr->dwStyle & WS_VISIBLE)
832         expose_covered_window_area( wndPtr, &oldClientRect, winpos->flags & SWP_FRAMECHANGED );
833
834     WIN_ReleaseWndPtr(wndPtr);
835
836     if (wvrFlags & WVR_REDRAW) RedrawWindow( winpos->hwnd, NULL, 0, RDW_INVALIDATE | RDW_ERASE );
837
838     if (winpos->hwnd == CARET_GetHwnd())
839     {
840         if( winpos->flags & SWP_HIDEWINDOW )
841             HideCaret(winpos->hwnd);
842         else if (winpos->flags & SWP_SHOWWINDOW)
843             ShowCaret(winpos->hwnd);
844     }
845
846     if (!(winpos->flags & SWP_NOACTIVATE))
847         WINPOS_ChangeActiveWindow( winpos->hwnd, FALSE );
848
849       /* And last, send the WM_WINDOWPOSCHANGED message */
850
851     TRACE("\tstatus flags = %04x\n", winpos->flags & SWP_AGG_STATUSFLAGS);
852
853     if (((winpos->flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) &&
854           !(winpos->flags & SWP_NOSENDCHANGING))
855         SendMessageA( winpos->hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)winpos );
856
857     return TRUE;
858 }
859
860
861 /***********************************************************************
862  *           WINPOS_FindIconPos
863  *
864  * Find a suitable place for an iconic window.
865  */
866 static POINT WINPOS_FindIconPos( WND* wndPtr, POINT pt )
867 {
868     RECT rectParent;
869     short x, y, xspacing, yspacing;
870
871     GetClientRect( wndPtr->parent->hwndSelf, &rectParent );
872     if ((pt.x >= rectParent.left) && (pt.x + GetSystemMetrics(SM_CXICON) < rectParent.right) &&
873         (pt.y >= rectParent.top) && (pt.y + GetSystemMetrics(SM_CYICON) < rectParent.bottom))
874         return pt;  /* The icon already has a suitable position */
875
876     xspacing = GetSystemMetrics(SM_CXICONSPACING);
877     yspacing = GetSystemMetrics(SM_CYICONSPACING);
878
879     y = rectParent.bottom;
880     for (;;)
881     {
882         x = rectParent.left;
883         do
884         {
885               /* Check if another icon already occupies this spot */
886             WND *childPtr = WIN_LockWndPtr(wndPtr->parent->child);
887             while (childPtr)
888             {
889                 if ((childPtr->dwStyle & WS_MINIMIZE) && (childPtr != wndPtr))
890                 {
891                     if ((childPtr->rectWindow.left < x + xspacing) &&
892                         (childPtr->rectWindow.right >= x) &&
893                         (childPtr->rectWindow.top <= y) &&
894                         (childPtr->rectWindow.bottom > y - yspacing))
895                         break;  /* There's a window in there */
896                 }
897                 WIN_UpdateWndPtr(&childPtr,childPtr->next);
898             }
899             WIN_ReleaseWndPtr(childPtr);
900             if (!childPtr) /* No window was found, so it's OK for us */
901             {
902                 pt.x = x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2;
903                 pt.y = y - (yspacing + GetSystemMetrics(SM_CYICON)) / 2;
904                 return pt;
905             }
906             x += xspacing;
907         } while(x <= rectParent.right-xspacing);
908         y -= yspacing;
909     }
910 }
911
912
913
914
915
916 UINT WINPOS_MinMaximize( HWND hwnd, UINT cmd, LPRECT rect )
917 {
918     WND *wndPtr = WIN_FindWndPtr( hwnd );
919     UINT swpFlags = 0;
920     POINT size;
921     WINDOWPLACEMENT wpl;
922
923     TRACE("0x%04x %u\n", hwnd, cmd );
924
925     wpl.length = sizeof(wpl);
926     GetWindowPlacement( hwnd, &wpl );
927
928     size.x = wndPtr->rectWindow.left;
929     size.y = wndPtr->rectWindow.top;
930
931     if (!HOOK_CallHooksA(WH_CBT, HCBT_MINMAX, wndPtr->hwndSelf, cmd))
932     {
933         if( wndPtr->dwStyle & WS_MINIMIZE )
934         {
935             if( !SendMessageA( wndPtr->hwndSelf, WM_QUERYOPEN, 0, 0L ) )
936             {
937                 swpFlags = SWP_NOSIZE | SWP_NOMOVE;
938                 goto done;
939             }
940             swpFlags |= SWP_NOCOPYBITS;
941         }
942         switch( cmd )
943         {
944         case SW_MINIMIZE:
945             if( wndPtr->dwStyle & WS_MAXIMIZE)
946             {
947                 wndPtr->flags |= WIN_RESTORE_MAX;
948                 wndPtr->dwStyle &= ~WS_MAXIMIZE;
949             }
950             else
951                 wndPtr->flags &= ~WIN_RESTORE_MAX;
952             wndPtr->dwStyle |= WS_MINIMIZE;
953
954             X11DRV_set_iconic_state( wndPtr );
955
956             wpl.ptMinPosition = WINPOS_FindIconPos( wndPtr, wpl.ptMinPosition );
957
958             SetRect( rect, wpl.ptMinPosition.x, wpl.ptMinPosition.y,
959                      GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON) );
960             swpFlags |= SWP_NOCOPYBITS;
961             break;
962
963         case SW_MAXIMIZE:
964             WINPOS_GetMinMaxInfo( hwnd, &size, &wpl.ptMaxPosition, NULL, NULL );
965
966             if( wndPtr->dwStyle & WS_MINIMIZE )
967             {
968                 wndPtr->dwStyle &= ~WS_MINIMIZE;
969                 WINPOS_ShowIconTitle( hwnd, FALSE );
970                 X11DRV_set_iconic_state( wndPtr );
971             }
972             wndPtr->dwStyle |= WS_MAXIMIZE;
973
974             SetRect( rect, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, size.x, size.y );
975             break;
976
977         case SW_RESTORE:
978             if( wndPtr->dwStyle & WS_MINIMIZE )
979             {
980                 wndPtr->dwStyle &= ~WS_MINIMIZE;
981                 WINPOS_ShowIconTitle( hwnd, FALSE );
982                 X11DRV_set_iconic_state( wndPtr );
983
984                 if( wndPtr->flags & WIN_RESTORE_MAX)
985                 {
986                     /* Restore to maximized position */
987                     WINPOS_GetMinMaxInfo( hwnd, &size, &wpl.ptMaxPosition, NULL, NULL);
988                     wndPtr->dwStyle |= WS_MAXIMIZE;
989                     SetRect( rect, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, size.x, size.y );
990                     break;
991                 }
992             }
993             else
994                 if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
995                 {
996                     swpFlags = (UINT16)(-1);
997                     goto done;
998                 }
999                 else wndPtr->dwStyle &= ~WS_MAXIMIZE;
1000
1001             /* Restore to normal position */
1002
1003             *rect = wpl.rcNormalPosition;
1004             rect->right -= rect->left;
1005             rect->bottom -= rect->top;
1006
1007             break;
1008         }
1009     } else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
1010
1011  done:
1012     WIN_ReleaseWndPtr( wndPtr );
1013     return swpFlags;
1014 }
1015
1016
1017 /***********************************************************************
1018  *              ShowWindow   (X11DRV.@)
1019  */
1020 BOOL X11DRV_ShowWindow( HWND hwnd, INT cmd )
1021 {
1022     WND*        wndPtr = WIN_FindWndPtr( hwnd );
1023     BOOL        wasVisible, showFlag;
1024     RECT        newPos = {0, 0, 0, 0};
1025     UINT        swp = 0;
1026
1027     if (!wndPtr) return FALSE;
1028     hwnd = wndPtr->hwndSelf;  /* make it a full handle */
1029
1030     TRACE("hwnd=%04x, cmd=%d\n", hwnd, cmd);
1031
1032     wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
1033
1034     switch(cmd)
1035     {
1036         case SW_HIDE:
1037             if (!wasVisible) goto END;;
1038             swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
1039                         SWP_NOACTIVATE | SWP_NOZORDER;
1040             break;
1041
1042         case SW_SHOWMINNOACTIVE:
1043             swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1044             /* fall through */
1045         case SW_SHOWMINIMIZED:
1046             swp |= SWP_SHOWWINDOW;
1047             /* fall through */
1048         case SW_MINIMIZE:
1049             swp |= SWP_FRAMECHANGED;
1050             if( !(wndPtr->dwStyle & WS_MINIMIZE) )
1051                  swp |= WINPOS_MinMaximize( hwnd, SW_MINIMIZE, &newPos );
1052             else swp |= SWP_NOSIZE | SWP_NOMOVE;
1053             break;
1054
1055         case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
1056             swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1057             if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
1058                  swp |= WINPOS_MinMaximize( hwnd, SW_MAXIMIZE, &newPos );
1059             else swp |= SWP_NOSIZE | SWP_NOMOVE;
1060             break;
1061
1062         case SW_SHOWNA:
1063             swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1064             /* fall through */
1065         case SW_SHOW:
1066             swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
1067
1068             /*
1069              * ShowWindow has a little peculiar behavior that if the
1070              * window is already the topmost window, it will not
1071              * activate it.
1072              */
1073             if (GetTopWindow((HWND)0)==hwnd && (wasVisible || GetActiveWindow() == hwnd))
1074               swp |= SWP_NOACTIVATE;
1075
1076             break;
1077
1078         case SW_SHOWNOACTIVATE:
1079             swp |= SWP_NOZORDER;
1080             if (GetActiveWindow()) swp |= SWP_NOACTIVATE;
1081             /* fall through */
1082         case SW_SHOWNORMAL:  /* same as SW_NORMAL: */
1083         case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
1084         case SW_RESTORE:
1085             swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1086
1087             if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) )
1088                  swp |= WINPOS_MinMaximize( hwnd, SW_RESTORE, &newPos );
1089             else swp |= SWP_NOSIZE | SWP_NOMOVE;
1090             break;
1091     }
1092
1093     showFlag = (cmd != SW_HIDE);
1094     if (showFlag != wasVisible)
1095     {
1096         SendMessageA( hwnd, WM_SHOWWINDOW, showFlag, 0 );
1097         if (!IsWindow( hwnd )) goto END;
1098     }
1099
1100     /* We can't activate a child window */
1101     if ((wndPtr->dwStyle & WS_CHILD) &&
1102         !(wndPtr->dwExStyle & WS_EX_MDICHILD))
1103         swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1104
1105     SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top,
1106                   newPos.right, newPos.bottom, LOWORD(swp) );
1107     if (cmd == SW_HIDE)
1108     {
1109         /* FIXME: This will cause the window to be activated irrespective
1110          * of whether it is owned by the same thread. Has to be done
1111          * asynchronously.
1112          */
1113
1114         if (hwnd == GetActiveWindow())
1115             WINPOS_ActivateOtherWindow(hwnd);
1116
1117         /* Revert focus to parent */
1118         if (hwnd == GetFocus() || IsChild(hwnd, GetFocus()))
1119             SetFocus( GetParent(hwnd) );
1120     }
1121     if (!IsWindow( hwnd )) goto END;
1122     else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( hwnd, TRUE );
1123
1124     if (wndPtr->flags & WIN_NEED_SIZE)
1125     {
1126         /* should happen only in CreateWindowEx() */
1127         int wParam = SIZE_RESTORED;
1128
1129         wndPtr->flags &= ~WIN_NEED_SIZE;
1130         if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
1131         else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
1132         SendMessageA( hwnd, WM_SIZE, wParam,
1133                      MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
1134                             wndPtr->rectClient.bottom-wndPtr->rectClient.top));
1135         SendMessageA( hwnd, WM_MOVE, 0,
1136                    MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
1137     }
1138
1139 END:
1140     WIN_ReleaseWndPtr(wndPtr);
1141     return wasVisible;
1142 }
1143
1144
1145 /**********************************************************************
1146  *              X11DRV_MapNotify
1147  */
1148 void X11DRV_MapNotify( HWND hwnd, XMapEvent *event )
1149 {
1150     HWND hwndFocus = GetFocus();
1151     WND *win;
1152
1153     if (!(win = WIN_FindWndPtr( hwnd ))) return;
1154
1155     if ((win->dwStyle & WS_VISIBLE) &&
1156         (win->dwStyle & WS_MINIMIZE) &&
1157         (win->dwExStyle & WS_EX_MANAGED))
1158     {
1159         int x, y;
1160         unsigned int width, height, border, depth;
1161         Window root, top;
1162         RECT rect;
1163
1164         DCE_InvalidateDCE( hwnd, &win->rectWindow );
1165         win->dwStyle &= ~WS_MINIMIZE;
1166         win->dwStyle |= WS_VISIBLE;
1167         WIN_InternalShowOwnedPopups( hwnd, TRUE, TRUE );
1168
1169         if (win->flags & WIN_RESTORE_MAX)
1170             win->dwStyle |= WS_MAXIMIZE;
1171         else
1172             win->dwStyle &= ~WS_MAXIMIZE;
1173
1174         /* FIXME: hack */
1175         wine_tsx11_lock();
1176         XGetGeometry( event->display, get_whole_window(win), &root, &x, &y, &width, &height,
1177                         &border, &depth );
1178         XTranslateCoordinates( event->display, get_whole_window(win), root, 0, 0, &x, &y, &top );
1179         wine_tsx11_unlock();
1180         rect.left   = x;
1181         rect.top    = y;
1182         rect.right  = x + width;
1183         rect.bottom = y + height;
1184         X11DRV_X_to_window_rect( win, &rect );
1185
1186         SendMessageA( hwnd, WM_SHOWWINDOW, SW_RESTORE, 0 );
1187         SetWindowPos( hwnd, 0, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top,
1188                       SWP_NOZORDER | SWP_WINE_NOHOSTMOVE );
1189     }
1190     if (hwndFocus && IsChild( hwnd, hwndFocus )) X11DRV_SetFocus(hwndFocus);  /* FIXME */
1191     WIN_ReleaseWndPtr( win );
1192 }
1193
1194
1195 /**********************************************************************
1196  *              X11DRV_UnmapNotify
1197  */
1198 void X11DRV_UnmapNotify( HWND hwnd, XUnmapEvent *event )
1199 {
1200     WND *win;
1201
1202     if (!(win = WIN_FindWndPtr( hwnd ))) return;
1203
1204     if ((win->dwStyle & WS_VISIBLE) && (win->dwExStyle & WS_EX_MANAGED))
1205     {
1206         EndMenu();
1207         SendMessageA( hwnd, WM_SHOWWINDOW, SW_MINIMIZE, 0 );
1208
1209         win->flags &= ~WIN_RESTORE_MAX;
1210         win->dwStyle |= WS_MINIMIZE;
1211
1212         if (win->dwStyle & WS_MAXIMIZE)
1213         {
1214             win->flags |= WIN_RESTORE_MAX;
1215             win->dwStyle &= ~WS_MAXIMIZE;
1216         }
1217
1218         SetWindowPos( hwnd, 0, 0, 0, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON),
1219                       SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_WINE_NOHOSTMOVE );
1220
1221         WIN_InternalShowOwnedPopups( hwnd, FALSE, TRUE );
1222     }
1223     WIN_ReleaseWndPtr( win );
1224 }
1225
1226
1227 /***********************************************************************
1228  *           query_zorder
1229  *
1230  * Synchronize internal z-order with the window manager's.
1231  */
1232 static BOOL __check_query_condition( WND** pWndA, WND** pWndB )
1233 {
1234     /* return TRUE if we have at least two managed windows */
1235
1236     for( *pWndB = NULL; *pWndA; *pWndA = (*pWndA)->next )
1237         if( ((*pWndA)->dwExStyle & WS_EX_MANAGED) &&
1238             ((*pWndA)->dwStyle & WS_VISIBLE )) break;
1239     if( *pWndA )
1240         for( *pWndB = (*pWndA)->next; *pWndB; *pWndB = (*pWndB)->next )
1241             if( ((*pWndB)->dwExStyle & WS_EX_MANAGED) &&
1242                 ((*pWndB)->dwStyle & WS_VISIBLE )) break;
1243     return ((*pWndB) != NULL);
1244 }
1245
1246 static Window __get_common_ancestor( Display *display, Window A, Window B,
1247                                      Window** children, unsigned* total )
1248 {
1249     /* find the real root window */
1250
1251     Window      root, *childrenB;
1252     unsigned    totalB;
1253
1254     while( A != B && A && B )
1255     {
1256       TSXQueryTree( display, A, &root, &A, children, total );
1257       TSXQueryTree( display, B, &root, &B, &childrenB, &totalB );
1258       if( childrenB ) TSXFree( childrenB );
1259       if( *children ) TSXFree( *children ), *children = NULL;
1260     }
1261
1262     if( A && B )
1263     {
1264         TSXQueryTree( display, A, &root, &B, children, total );
1265         return A;
1266     }
1267     return 0 ;
1268 }
1269
1270 static Window __get_top_decoration( Display *display, Window w, Window ancestor )
1271 {
1272     Window*     children, root, prev = w, parent = w;
1273     unsigned    total;
1274
1275     do
1276     {
1277         w = parent;
1278         TSXQueryTree( display, w, &root, &parent, &children, &total );
1279         if( children ) TSXFree( children );
1280     } while( parent && parent != ancestor );
1281     TRACE("\t%08x -> %08x\n", (unsigned)prev, (unsigned)w );
1282     return ( parent ) ? w : 0 ;
1283 }
1284
1285 static unsigned __td_lookup( Window w, Window* list, unsigned max )
1286 {
1287     unsigned    i;
1288     for( i = max - 1; i >= 0; i-- ) if( list[i] == w ) break;
1289     return i;
1290 }
1291
1292 static HWND query_zorder( Display *display, HWND hWndCheck)
1293 {
1294     HWND      hwndInsertAfter = HWND_TOP;
1295     WND      *pWndCheck = WIN_FindWndPtr(hWndCheck);
1296     WND *top = WIN_FindWndPtr( GetTopWindow(0) );
1297     WND *pWnd, *pWndZ = top;
1298     Window      w, parent, *children = NULL;
1299     unsigned    total, check, pos, best;
1300
1301     if( !__check_query_condition(&pWndZ, &pWnd) )
1302     {
1303         WIN_ReleaseWndPtr(pWndCheck);
1304         WIN_ReleaseWndPtr(top);
1305         return hwndInsertAfter;
1306     }
1307     WIN_LockWndPtr(pWndZ);
1308     WIN_LockWndPtr(pWnd);
1309     WIN_ReleaseWndPtr(top);
1310
1311     parent = __get_common_ancestor( display, get_whole_window(pWndZ),
1312                                     get_whole_window(pWnd), &children, &total );
1313     if( parent && children )
1314     {
1315         /* w is the ancestor if pWndCheck that is a direct descendant of 'parent' */
1316
1317         w = __get_top_decoration( display, get_whole_window(pWndCheck), parent );
1318
1319         if( w != children[total-1] ) /* check if at the top */
1320         {
1321             /* X child at index 0 is at the bottom, at index total-1 is at the top */
1322             check = __td_lookup( w, children, total );
1323             best = total;
1324
1325             for( WIN_UpdateWndPtr(&pWnd,pWndZ); pWnd;WIN_UpdateWndPtr(&pWnd,pWnd->next))
1326             {
1327                 /* go through all windows in Wine z-order... */
1328
1329                 if( pWnd != pWndCheck )
1330                 {
1331                     if( !(pWnd->dwExStyle & WS_EX_MANAGED) ||
1332                         !(w = __get_top_decoration( display, get_whole_window(pWnd), parent )) )
1333                         continue;
1334                     pos = __td_lookup( w, children, total );
1335                     if( pos < best && pos > check )
1336                     {
1337                         /* find a nearest Wine window precedes
1338                          * pWndCheck in the real z-order... */
1339                         best = pos;
1340                         hwndInsertAfter = pWnd->hwndSelf;
1341                     }
1342                     if( best - check == 1 ) break;
1343                 }
1344             }
1345         }
1346     }
1347     if( children ) TSXFree( children );
1348     WIN_ReleaseWndPtr(pWnd);
1349     WIN_ReleaseWndPtr(pWndZ);
1350     WIN_ReleaseWndPtr(pWndCheck);
1351     return hwndInsertAfter;
1352 }
1353
1354
1355 /***********************************************************************
1356  *              X11DRV_ConfigureNotify
1357  */
1358 void X11DRV_ConfigureNotify( HWND hwnd, XConfigureEvent *event )
1359 {
1360     HWND oldInsertAfter;
1361     struct x11drv_win_data *data;
1362     WND *win;
1363     RECT rect;
1364     WINDOWPOS winpos;
1365     int x = event->x, y = event->y;
1366
1367     if (!(win = WIN_FindWndPtr( hwnd ))) return;
1368     data = win->pDriverData;
1369
1370     /* Get geometry */
1371
1372     if (!event->send_event)  /* normal event, need to map coordinates to the root */
1373     {
1374         Window child;
1375         wine_tsx11_lock();
1376         XTranslateCoordinates( event->display, data->whole_window, root_window,
1377                                0, 0, &x, &y, &child );
1378         wine_tsx11_unlock();
1379     }
1380     rect.left   = x;
1381     rect.top    = y;
1382     rect.right  = x + event->width;
1383     rect.bottom = y + event->height;
1384     TRACE( "win %x new X rect %d,%d,%dx%d (event %d,%d,%dx%d)\n",
1385            hwnd, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top,
1386            event->x, event->y, event->width, event->height );
1387     X11DRV_X_to_window_rect( win, &rect );
1388     WIN_ReleaseWndPtr( win );
1389
1390     winpos.hwnd  = hwnd;
1391     winpos.x     = rect.left;
1392     winpos.y     = rect.top;
1393     winpos.cx    = rect.right - rect.left;
1394     winpos.cy    = rect.bottom - rect.top;
1395     winpos.flags = SWP_NOACTIVATE;
1396
1397     /* Get Z-order (FIXME) */
1398
1399     winpos.hwndInsertAfter = query_zorder( event->display, hwnd );
1400
1401     /* needs to find the first Visible Window above the current one */
1402     oldInsertAfter = hwnd;
1403     for (;;)
1404     {
1405         oldInsertAfter = GetWindow( oldInsertAfter, GW_HWNDPREV );
1406         if (!oldInsertAfter)
1407         {
1408             oldInsertAfter = HWND_TOP;
1409             break;
1410         }
1411         if (GetWindowLongA( oldInsertAfter, GWL_STYLE ) & WS_VISIBLE) break;
1412     }
1413
1414     /* Compare what has changed */
1415
1416     GetWindowRect( hwnd, &rect );
1417     if (rect.left == winpos.x && rect.top == winpos.y) winpos.flags |= SWP_NOMOVE;
1418     else
1419         TRACE( "%04x moving from (%d,%d) to (%d,%d)\n",
1420                hwnd, rect.left, rect.top, winpos.x, winpos.y );
1421
1422     if ((rect.right - rect.left == winpos.cx && rect.bottom - rect.top == winpos.cy) ||
1423         (IsRectEmpty( &rect ) && winpos.cx == 1 && winpos.cy == 1))
1424         winpos.flags |= SWP_NOSIZE;
1425     else
1426         TRACE( "%04x resizing from (%dx%d) to (%dx%d)\n",
1427                hwnd, rect.right - rect.left, rect.bottom - rect.top,
1428                winpos.cx, winpos.cy );
1429
1430     if (winpos.hwndInsertAfter == oldInsertAfter) winpos.flags |= SWP_NOZORDER;
1431     else
1432         TRACE( "%04x restacking from after %04x to after %04x\n",
1433                hwnd, oldInsertAfter, winpos.hwndInsertAfter );
1434
1435     /* if nothing changed, don't do anything */
1436     if (winpos.flags == (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE)) return;
1437
1438     SetWindowPos( hwnd, winpos.hwndInsertAfter, winpos.x, winpos.y,
1439                   winpos.cx, winpos.cy, winpos.flags | SWP_WINE_NOHOSTMOVE );
1440 }
1441
1442
1443 /***********************************************************************
1444  *              SetWindowRgn  (X11DRV.@)
1445  *
1446  * Assign specified region to window (for non-rectangular windows)
1447  */
1448 BOOL X11DRV_SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL redraw )
1449 {
1450     RECT rect;
1451     WND *wndPtr = WIN_FindWndPtr(hwnd);
1452     int ret = FALSE;
1453
1454     if (!wndPtr) return FALSE;
1455
1456     if (wndPtr->hrgnWnd == hrgn)
1457     {
1458         ret = TRUE;
1459         goto done;
1460     }
1461
1462     if (hrgn) /* verify that region really exists */
1463     {
1464         if (GetRgnBox( hrgn, &rect ) == ERROR) goto done;
1465     }
1466
1467     if (wndPtr->hrgnWnd)
1468     {
1469         /* delete previous region */
1470         DeleteObject(wndPtr->hrgnWnd);
1471         wndPtr->hrgnWnd = 0;
1472     }
1473     wndPtr->hrgnWnd = hrgn;
1474
1475 #ifdef HAVE_LIBXSHAPE
1476     {
1477         Display *display = thread_display();
1478         X11DRV_WND_DATA *data = wndPtr->pDriverData;
1479
1480         if (data->whole_window)
1481         {
1482             if (!hrgn)
1483             {
1484                 TSXShapeCombineMask( display, data->whole_window,
1485                                      ShapeBounding, 0, 0, None, ShapeSet );
1486             }
1487             else
1488             {
1489                 XRectangle *aXRect;
1490                 int x_offset, y_offset;
1491                 DWORD size;
1492                 DWORD dwBufferSize = GetRegionData(hrgn, 0, NULL);
1493                 PRGNDATA pRegionData = HeapAlloc(GetProcessHeap(), 0, dwBufferSize);
1494                 if (!pRegionData) goto done;
1495
1496                 GetRegionData(hrgn, dwBufferSize, pRegionData);
1497                 size = pRegionData->rdh.nCount;
1498                 x_offset = wndPtr->rectWindow.left - data->whole_rect.left;
1499                 y_offset = wndPtr->rectWindow.top - data->whole_rect.top;
1500                 /* convert region's "Windows rectangles" to XRectangles */
1501                 aXRect = HeapAlloc(GetProcessHeap(), 0, size * sizeof(*aXRect) );
1502                 if (aXRect)
1503                 {
1504                     XRectangle* pCurrRect = aXRect;
1505                     RECT *pRect = (RECT*) pRegionData->Buffer;
1506                     for (; pRect < ((RECT*) pRegionData->Buffer) + size ; ++pRect, ++pCurrRect)
1507                     {
1508                         pCurrRect->x      = pRect->left + x_offset;
1509                         pCurrRect->y      = pRect->top + y_offset;
1510                         pCurrRect->height = pRect->bottom - pRect->top;
1511                         pCurrRect->width  = pRect->right  - pRect->left;
1512
1513                         TRACE("Rectangle %04d of %04ld data: X=%04d, Y=%04d, Height=%04d, Width=%04d.\n",
1514                               pRect - (RECT*) pRegionData->Buffer,
1515                               size,
1516                               pCurrRect->x,
1517                               pCurrRect->y,
1518                               pCurrRect->height,
1519                               pCurrRect->width);
1520                     }
1521
1522                     /* shape = non-rectangular windows (X11/extensions) */
1523                     TSXShapeCombineRectangles( display, data->whole_window, ShapeBounding,
1524                                                0, 0, aXRect,
1525                                                pCurrRect - aXRect, ShapeSet, YXBanded );
1526                     HeapFree(GetProcessHeap(), 0, aXRect );
1527                 }
1528                 HeapFree(GetProcessHeap(), 0, pRegionData);
1529             }
1530         }
1531     }
1532 #endif  /* HAVE_LIBXSHAPE */
1533
1534     if (redraw) RedrawWindow( hwnd, NULL, 0, RDW_FRAME | RDW_INVALIDATE | RDW_ERASE );
1535     ret = TRUE;
1536
1537  done:
1538     WIN_ReleaseWndPtr(wndPtr);
1539     return ret;
1540 }
1541
1542
1543 /***********************************************************************
1544  *           draw_moving_frame
1545  *
1546  * Draw the frame used when moving or resizing window.
1547  *
1548  * FIXME:  This causes problems in Win95 mode.  (why?)
1549  */
1550 static void draw_moving_frame( HDC hdc, RECT *rect, BOOL thickframe )
1551 {
1552     if (thickframe)
1553     {
1554         const int width = GetSystemMetrics(SM_CXFRAME);
1555         const int height = GetSystemMetrics(SM_CYFRAME);
1556
1557         HBRUSH hbrush = SelectObject( hdc, GetStockObject( GRAY_BRUSH ) );
1558         PatBlt( hdc, rect->left, rect->top,
1559                 rect->right - rect->left - width, height, PATINVERT );
1560         PatBlt( hdc, rect->left, rect->top + height, width,
1561                 rect->bottom - rect->top - height, PATINVERT );
1562         PatBlt( hdc, rect->left + width, rect->bottom - 1,
1563                 rect->right - rect->left - width, -height, PATINVERT );
1564         PatBlt( hdc, rect->right - 1, rect->top, -width,
1565                 rect->bottom - rect->top - height, PATINVERT );
1566         SelectObject( hdc, hbrush );
1567     }
1568     else DrawFocusRect( hdc, rect );
1569 }
1570
1571
1572 /***********************************************************************
1573  *           start_size_move
1574  *
1575  * Initialisation of a move or resize, when initiatied from a menu choice.
1576  * Return hit test code for caption or sizing border.
1577  */
1578 static LONG start_size_move( HWND hwnd, WPARAM wParam, POINT *capturePoint, LONG style )
1579 {
1580     LONG hittest = 0;
1581     POINT pt;
1582     MSG msg;
1583     RECT rectWindow;
1584
1585     GetWindowRect( hwnd, &rectWindow );
1586
1587     if ((wParam & 0xfff0) == SC_MOVE)
1588     {
1589         /* Move pointer at the center of the caption */
1590         RECT rect;
1591         NC_GetInsideRect( hwnd, &rect );
1592         if (style & WS_SYSMENU)
1593             rect.left += GetSystemMetrics(SM_CXSIZE) + 1;
1594         if (style & WS_MINIMIZEBOX)
1595             rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1596         if (style & WS_MAXIMIZEBOX)
1597             rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1598         pt.x = rectWindow.left + (rect.right - rect.left) / 2;
1599         pt.y = rectWindow.top + rect.top + GetSystemMetrics(SM_CYSIZE)/2;
1600         hittest = HTCAPTION;
1601         *capturePoint = pt;
1602     }
1603     else  /* SC_SIZE */
1604     {
1605         while(!hittest)
1606         {
1607             GetMessageW( &msg, 0, WM_KEYFIRST, WM_MOUSELAST );
1608             if (CallMsgFilterW( &msg, MSGF_SIZE )) continue;
1609
1610             switch(msg.message)
1611             {
1612             case WM_MOUSEMOVE:
1613                 hittest = NC_HandleNCHitTest( hwnd, msg.pt );
1614                 if ((hittest < HTLEFT) || (hittest > HTBOTTOMRIGHT))
1615                     hittest = 0;
1616                 break;
1617
1618             case WM_LBUTTONUP:
1619                 return 0;
1620
1621             case WM_KEYDOWN:
1622                 switch(msg.wParam)
1623                 {
1624                 case VK_UP:
1625                     hittest = HTTOP;
1626                     pt.x =(rectWindow.left+rectWindow.right)/2;
1627                     pt.y = rectWindow.top + GetSystemMetrics(SM_CYFRAME) / 2;
1628                     break;
1629                 case VK_DOWN:
1630                     hittest = HTBOTTOM;
1631                     pt.x =(rectWindow.left+rectWindow.right)/2;
1632                     pt.y = rectWindow.bottom - GetSystemMetrics(SM_CYFRAME) / 2;
1633                     break;
1634                 case VK_LEFT:
1635                     hittest = HTLEFT;
1636                     pt.x = rectWindow.left + GetSystemMetrics(SM_CXFRAME) / 2;
1637                     pt.y =(rectWindow.top+rectWindow.bottom)/2;
1638                     break;
1639                 case VK_RIGHT:
1640                     hittest = HTRIGHT;
1641                     pt.x = rectWindow.right - GetSystemMetrics(SM_CXFRAME) / 2;
1642                     pt.y =(rectWindow.top+rectWindow.bottom)/2;
1643                     break;
1644                 case VK_RETURN:
1645                 case VK_ESCAPE: return 0;
1646                 }
1647             }
1648         }
1649         *capturePoint = pt;
1650     }
1651     SetCursorPos( pt.x, pt.y );
1652     NC_HandleSetCursor( hwnd, hwnd, MAKELONG( hittest, WM_MOUSEMOVE ));
1653     return hittest;
1654 }
1655
1656
1657 /***********************************************************************
1658  *           SysCommandSizeMove   (X11DRV.@)
1659  *
1660  * Perform SC_MOVE and SC_SIZE commands.
1661  */
1662 void X11DRV_SysCommandSizeMove( HWND hwnd, WPARAM wParam )
1663 {
1664     MSG msg;
1665     RECT sizingRect, mouseRect, origRect;
1666     HDC hdc;
1667     HWND parent;
1668     LONG hittest = (LONG)(wParam & 0x0f);
1669     HCURSOR16 hDragCursor = 0, hOldCursor = 0;
1670     POINT minTrack, maxTrack;
1671     POINT capturePoint, pt;
1672     LONG style = GetWindowLongA( hwnd, GWL_STYLE );
1673     LONG exstyle = GetWindowLongA( hwnd, GWL_EXSTYLE );
1674     BOOL    thickframe = HAS_THICKFRAME( style, exstyle );
1675     BOOL    iconic = style & WS_MINIMIZE;
1676     BOOL    moved = FALSE;
1677     DWORD     dwPoint = GetMessagePos ();
1678     BOOL DragFullWindows = FALSE;
1679     BOOL grab;
1680     int iWndsLocks;
1681     Display *old_gdi_display = NULL;
1682     Display *display = thread_display();
1683
1684     SystemParametersInfoA(SPI_GETDRAGFULLWINDOWS, 0, &DragFullWindows, 0);
1685
1686     pt.x = SLOWORD(dwPoint);
1687     pt.y = SHIWORD(dwPoint);
1688     capturePoint = pt;
1689
1690     if (IsZoomed(hwnd) || !IsWindowVisible(hwnd) || (exstyle & WS_EX_MANAGED)) return;
1691
1692     if ((wParam & 0xfff0) == SC_MOVE)
1693     {
1694         if (!hittest) hittest = start_size_move( hwnd, wParam, &capturePoint, style );
1695         if (!hittest) return;
1696     }
1697     else  /* SC_SIZE */
1698     {
1699         if (!thickframe) return;
1700         if ( hittest && hittest != HTSYSMENU ) hittest += 2;
1701         else
1702         {
1703             SetCapture(hwnd);
1704             hittest = start_size_move( hwnd, wParam, &capturePoint, style );
1705             if (!hittest)
1706             {
1707                 ReleaseCapture();
1708                 return;
1709             }
1710         }
1711     }
1712
1713       /* Get min/max info */
1714
1715     WINPOS_GetMinMaxInfo( hwnd, NULL, NULL, &minTrack, &maxTrack );
1716     GetWindowRect( hwnd, &sizingRect );
1717     if (style & WS_CHILD)
1718     {
1719         parent = GetParent(hwnd);
1720         /* make sizing rect relative to parent */
1721         MapWindowPoints( 0, parent, (POINT*)&sizingRect, 2 );
1722         GetClientRect( parent, &mouseRect );
1723     }
1724     else
1725     {
1726         parent = 0;
1727         SetRect(&mouseRect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
1728     }
1729     origRect = sizingRect;
1730
1731     if (ON_LEFT_BORDER(hittest))
1732     {
1733         mouseRect.left  = max( mouseRect.left, sizingRect.right-maxTrack.x );
1734         mouseRect.right = min( mouseRect.right, sizingRect.right-minTrack.x );
1735     }
1736     else if (ON_RIGHT_BORDER(hittest))
1737     {
1738         mouseRect.left  = max( mouseRect.left, sizingRect.left+minTrack.x );
1739         mouseRect.right = min( mouseRect.right, sizingRect.left+maxTrack.x );
1740     }
1741     if (ON_TOP_BORDER(hittest))
1742     {
1743         mouseRect.top    = max( mouseRect.top, sizingRect.bottom-maxTrack.y );
1744         mouseRect.bottom = min( mouseRect.bottom,sizingRect.bottom-minTrack.y);
1745     }
1746     else if (ON_BOTTOM_BORDER(hittest))
1747     {
1748         mouseRect.top    = max( mouseRect.top, sizingRect.top+minTrack.y );
1749         mouseRect.bottom = min( mouseRect.bottom, sizingRect.top+maxTrack.y );
1750     }
1751     if (parent) MapWindowPoints( parent, 0, (LPPOINT)&mouseRect, 2 );
1752
1753     /* Retrieve a default cache DC (without using the window style) */
1754     hdc = GetDCEx( parent, 0, DCX_CACHE );
1755
1756     if( iconic ) /* create a cursor for dragging */
1757     {
1758         HICON hIcon = GetClassLongA( hwnd, GCL_HICON);
1759         if(!hIcon) hIcon = (HICON)SendMessageA( hwnd, WM_QUERYDRAGICON, 0, 0L);
1760         if( hIcon ) hDragCursor =  CURSORICON_IconToCursor( hIcon, TRUE );
1761         if( !hDragCursor ) iconic = FALSE;
1762     }
1763
1764     /* repaint the window before moving it around */
1765     RedrawWindow( hwnd, NULL, 0, RDW_UPDATENOW | RDW_ALLCHILDREN );
1766
1767     SendMessageA( hwnd, WM_ENTERSIZEMOVE, 0, 0 );
1768     SetCapture( hwnd );
1769
1770     /* grab the server only when moving top-level windows without desktop */
1771     grab = (!DragFullWindows && !parent && (root_window == DefaultRootWindow(gdi_display)));
1772
1773     wine_tsx11_lock();
1774     if (grab)
1775     {
1776         XSync( gdi_display, False );
1777         XGrabServer( display );
1778         XSync( display, False );
1779         /* switch gdi display to the thread display, since the server is grabbed */
1780         old_gdi_display = gdi_display;
1781         gdi_display = display;
1782     }
1783     XGrabPointer( display, X11DRV_get_whole_window(hwnd), False,
1784                   PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
1785                   GrabModeAsync, GrabModeAsync,
1786                   parent ? X11DRV_get_client_window(parent) : root_window,
1787                   None, CurrentTime );
1788     wine_tsx11_unlock();
1789
1790     while(1)
1791     {
1792         int dx = 0, dy = 0;
1793
1794         if (!GetMessageW( &msg, 0, WM_KEYFIRST, WM_MOUSELAST )) break;
1795         if (CallMsgFilterW( &msg, MSGF_SIZE )) continue;
1796
1797         /* Exit on button-up, Return, or Esc */
1798         if ((msg.message == WM_LBUTTONUP) ||
1799             ((msg.message == WM_KEYDOWN) &&
1800              ((msg.wParam == VK_RETURN) || (msg.wParam == VK_ESCAPE)))) break;
1801
1802         if ((msg.message != WM_KEYDOWN) && (msg.message != WM_MOUSEMOVE))
1803             continue;  /* We are not interested in other messages */
1804
1805         pt = msg.pt;
1806
1807         if (msg.message == WM_KEYDOWN) switch(msg.wParam)
1808         {
1809         case VK_UP:    pt.y -= 8; break;
1810         case VK_DOWN:  pt.y += 8; break;
1811         case VK_LEFT:  pt.x -= 8; break;
1812         case VK_RIGHT: pt.x += 8; break;
1813         }
1814
1815         pt.x = max( pt.x, mouseRect.left );
1816         pt.x = min( pt.x, mouseRect.right );
1817         pt.y = max( pt.y, mouseRect.top );
1818         pt.y = min( pt.y, mouseRect.bottom );
1819
1820         dx = pt.x - capturePoint.x;
1821         dy = pt.y - capturePoint.y;
1822
1823         if (dx || dy)
1824         {
1825             if( !moved )
1826             {
1827                 moved = TRUE;
1828
1829                 if( iconic ) /* ok, no system popup tracking */
1830                 {
1831                     hOldCursor = SetCursor(hDragCursor);
1832                     ShowCursor( TRUE );
1833                     WINPOS_ShowIconTitle( hwnd, FALSE );
1834                 }
1835                 else if(!DragFullWindows)
1836                     draw_moving_frame( hdc, &sizingRect, thickframe );
1837             }
1838
1839             if (msg.message == WM_KEYDOWN) SetCursorPos( pt.x, pt.y );
1840             else
1841             {
1842                 RECT newRect = sizingRect;
1843                 WPARAM wpSizingHit = 0;
1844
1845                 if (hittest == HTCAPTION) OffsetRect( &newRect, dx, dy );
1846                 if (ON_LEFT_BORDER(hittest)) newRect.left += dx;
1847                 else if (ON_RIGHT_BORDER(hittest)) newRect.right += dx;
1848                 if (ON_TOP_BORDER(hittest)) newRect.top += dy;
1849                 else if (ON_BOTTOM_BORDER(hittest)) newRect.bottom += dy;
1850                 if(!iconic && !DragFullWindows) draw_moving_frame( hdc, &sizingRect, thickframe );
1851                 capturePoint = pt;
1852
1853                 /* determine the hit location */
1854                 if (hittest >= HTLEFT && hittest <= HTBOTTOMRIGHT)
1855                     wpSizingHit = WMSZ_LEFT + (hittest - HTLEFT);
1856                 SendMessageA( hwnd, WM_SIZING, wpSizingHit, (LPARAM)&newRect );
1857
1858                 if (!iconic)
1859                 {
1860                     if(!DragFullWindows)
1861                         draw_moving_frame( hdc, &newRect, thickframe );
1862                     else {
1863                         /* To avoid any deadlocks, all the locks on the windows
1864                            structures must be suspended before the SetWindowPos */
1865                         iWndsLocks = WIN_SuspendWndsLock();
1866                         SetWindowPos( hwnd, 0, newRect.left, newRect.top,
1867                                       newRect.right - newRect.left,
1868                                       newRect.bottom - newRect.top,
1869                                       ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
1870                         WIN_RestoreWndsLock(iWndsLocks);
1871                     }
1872                 }
1873                 sizingRect = newRect;
1874             }
1875         }
1876     }
1877
1878     ReleaseCapture();
1879     if( iconic )
1880     {
1881         if( moved ) /* restore cursors, show icon title later on */
1882         {
1883             ShowCursor( FALSE );
1884             SetCursor( hOldCursor );
1885         }
1886         DestroyCursor( hDragCursor );
1887     }
1888     else if (moved && !DragFullWindows)
1889         draw_moving_frame( hdc, &sizingRect, thickframe );
1890
1891     ReleaseDC( parent, hdc );
1892
1893     wine_tsx11_lock();
1894     XUngrabPointer( display, CurrentTime );
1895     if (grab)
1896     {
1897         XSync( display, False );
1898         XUngrabServer( display );
1899         XSync( display, False );
1900         gdi_display = old_gdi_display;
1901     }
1902     wine_tsx11_unlock();
1903
1904     if (HOOK_CallHooksA( WH_CBT, HCBT_MOVESIZE, hwnd, (LPARAM)&sizingRect )) moved = FALSE;
1905
1906     SendMessageA( hwnd, WM_EXITSIZEMOVE, 0, 0 );
1907     SendMessageA( hwnd, WM_SETVISIBLE, !IsIconic(hwnd), 0L);
1908
1909     /* window moved or resized */
1910     if (moved)
1911     {
1912         /* To avoid any deadlocks, all the locks on the windows
1913            structures must be suspended before the SetWindowPos */
1914         iWndsLocks = WIN_SuspendWndsLock();
1915
1916         /* if the moving/resizing isn't canceled call SetWindowPos
1917          * with the new position or the new size of the window
1918          */
1919         if (!((msg.message == WM_KEYDOWN) && (msg.wParam == VK_ESCAPE)) )
1920         {
1921             /* NOTE: SWP_NOACTIVATE prevents document window activation in Word 6 */
1922             if(!DragFullWindows)
1923                 SetWindowPos( hwnd, 0, sizingRect.left, sizingRect.top,
1924                               sizingRect.right - sizingRect.left,
1925                               sizingRect.bottom - sizingRect.top,
1926                               ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
1927         }
1928         else
1929         { /* restore previous size/position */
1930             if(DragFullWindows)
1931                 SetWindowPos( hwnd, 0, origRect.left, origRect.top,
1932                               origRect.right - origRect.left,
1933                               origRect.bottom - origRect.top,
1934                               ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
1935         }
1936
1937         WIN_RestoreWndsLock(iWndsLocks);
1938     }
1939
1940     if (IsIconic(hwnd))
1941     {
1942         /* Single click brings up the system menu when iconized */
1943
1944         if( !moved )
1945         {
1946             if(style & WS_SYSMENU )
1947                 SendMessageA( hwnd, WM_SYSCOMMAND,
1948                               SC_MOUSEMENU + HTSYSMENU, MAKELONG(pt.x,pt.y));
1949         }
1950         else WINPOS_ShowIconTitle( hwnd, TRUE );
1951     }
1952 }
1953
1954
1955 /***********************************************************************
1956  *              ForceWindowRaise   (X11DRV.@)
1957  *
1958  * Raise a window on top of the X stacking order, while preserving
1959  * the correct Windows Z order.
1960  *
1961  * FIXME: this should go away.
1962  */
1963 void X11DRV_ForceWindowRaise( HWND hwnd )
1964 {
1965     XWindowChanges winChanges;
1966     Display *display = thread_display();
1967     WND *wndPrev, *wndPtr = WIN_FindWndPtr( hwnd );
1968
1969     if (!wndPtr) return;
1970
1971     if ((wndPtr->dwExStyle & WS_EX_MANAGED) ||
1972         wndPtr->parent->hwndSelf != GetDesktopWindow() ||
1973         IsRectEmpty( &wndPtr->rectWindow ) ||
1974         !get_whole_window(wndPtr))
1975     {
1976         WIN_ReleaseWndPtr( wndPtr );
1977         return;
1978     }
1979
1980     /* Raise all windows up to wndPtr according to their Z order.
1981      * (it would be easier with sibling-related Below but it doesn't
1982      * work very well with SGI mwm for instance)
1983      */
1984     winChanges.stack_mode = Above;
1985     while (wndPtr)
1986     {
1987         if (!IsRectEmpty( &wndPtr->rectWindow ) && get_whole_window(wndPtr))
1988             TSXReconfigureWMWindow( display, get_whole_window(wndPtr), 0,
1989                                     CWStackMode, &winChanges );
1990         wndPrev = wndPtr->parent->child;
1991         if (wndPrev == wndPtr) break;
1992         while (wndPrev && (wndPrev->next != wndPtr)) wndPrev = wndPrev->next;
1993         WIN_UpdateWndPtr( &wndPtr, wndPrev );
1994     }
1995     WIN_ReleaseWndPtr( wndPtr );
1996 }