| /* | 
 |  * Window position related functions. | 
 |  * | 
 |  * Copyright 1993, 1994, 1995, 2001 Alexandre Julliard | 
 |  * Copyright 1995, 1996, 1999 Alex Korobka | 
 |  * | 
 |  * This library is free software; you can redistribute it and/or | 
 |  * modify it under the terms of the GNU Lesser General Public | 
 |  * License as published by the Free Software Foundation; either | 
 |  * version 2.1 of the License, or (at your option) any later version. | 
 |  * | 
 |  * This library is distributed in the hope that it will be useful, | 
 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
 |  * Lesser General Public License for more details. | 
 |  * | 
 |  * You should have received a copy of the GNU Lesser General Public | 
 |  * License along with this library; if not, write to the Free Software | 
 |  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | 
 |  */ | 
 |  | 
 | #include "config.h" | 
 |  | 
 | #include "ts_xlib.h" | 
 | #ifdef HAVE_LIBXSHAPE | 
 | #include <X11/IntrinsicP.h> | 
 | #include <X11/extensions/shape.h> | 
 | #endif /* HAVE_LIBXSHAPE */ | 
 |  | 
 | #include "winbase.h" | 
 | #include "wingdi.h" | 
 | #include "winuser.h" | 
 | #include "winerror.h" | 
 | #include "wownt32.h" | 
 |  | 
 | #include "x11drv.h" | 
 | #include "win.h" | 
 | #include "winpos.h" | 
 | #include "dce.h" | 
 | #include "cursoricon.h" | 
 | #include "nonclient.h" | 
 | #include "message.h" | 
 |  | 
 | #include "wine/server.h" | 
 | #include "wine/debug.h" | 
 |  | 
 | WINE_DEFAULT_DEBUG_CHANNEL(x11drv); | 
 |  | 
 | #define SWP_AGG_NOGEOMETRYCHANGE \ | 
 |     (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE) | 
 | #define SWP_AGG_NOPOSCHANGE \ | 
 |     (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER) | 
 | #define SWP_AGG_STATUSFLAGS \ | 
 |     (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW) | 
 |  | 
 | #define SWP_EX_NOCOPY       0x0001 | 
 | #define SWP_EX_PAINTSELF    0x0002 | 
 | #define SWP_EX_NONCLIENT    0x0004 | 
 |  | 
 | #define HAS_THICKFRAME(style,exStyle) \ | 
 |     (((style) & WS_THICKFRAME) && \ | 
 |      !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME)) | 
 |  | 
 | #define ON_LEFT_BORDER(hit) \ | 
 |  (((hit) == HTLEFT) || ((hit) == HTTOPLEFT) || ((hit) == HTBOTTOMLEFT)) | 
 | #define ON_RIGHT_BORDER(hit) \ | 
 |  (((hit) == HTRIGHT) || ((hit) == HTTOPRIGHT) || ((hit) == HTBOTTOMRIGHT)) | 
 | #define ON_TOP_BORDER(hit) \ | 
 |  (((hit) == HTTOP) || ((hit) == HTTOPLEFT) || ((hit) == HTTOPRIGHT)) | 
 | #define ON_BOTTOM_BORDER(hit) \ | 
 |  (((hit) == HTBOTTOM) || ((hit) == HTBOTTOMLEFT) || ((hit) == HTBOTTOMRIGHT)) | 
 |  | 
 |  | 
 | /*********************************************************************** | 
 |  *		clip_children | 
 |  * | 
 |  * Clip all children of a given window out of the visible region | 
 |  */ | 
 | static int clip_children( HWND parent, HWND last, HRGN hrgn, int whole_window ) | 
 | { | 
 |     HWND *list; | 
 |     WND *ptr; | 
 |     HRGN rectRgn; | 
 |     int i, x, y, ret = SIMPLEREGION; | 
 |  | 
 |     /* first check if we have anything to do */ | 
 |     if (!(list = WIN_ListChildren( parent ))) return ret; | 
 |     for (i = 0; list[i] && list[i] != last; i++) | 
 |         if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE) break; | 
 |     if (!list[i] || list[i] == last) goto done; /* no children to clip */ | 
 |  | 
 |     if (whole_window) | 
 |     { | 
 |         WND *win = WIN_FindWndPtr( parent ); | 
 |         x = win->rectWindow.left - win->rectClient.left; | 
 |         y = win->rectWindow.top - win->rectClient.top; | 
 |         WIN_ReleaseWndPtr( win ); | 
 |     } | 
 |     else x = y = 0; | 
 |  | 
 |     rectRgn = CreateRectRgn( 0, 0, 0, 0 ); | 
 |  | 
 |     for ( ; list[i] && list[i] != last; i++) | 
 |     { | 
 |         if (!(ptr = WIN_FindWndPtr( list[i] ))) continue; | 
 |         if (ptr->dwStyle & WS_VISIBLE) | 
 |         { | 
 |             SetRectRgn( rectRgn, ptr->rectWindow.left + x, ptr->rectWindow.top + y, | 
 |                         ptr->rectWindow.right + x, ptr->rectWindow.bottom + y ); | 
 |             if ((ret = CombineRgn( hrgn, hrgn, rectRgn, RGN_DIFF )) == NULLREGION) | 
 |             { | 
 |                 WIN_ReleaseWndPtr( ptr ); | 
 |                 break;  /* no need to go on, region is empty */ | 
 |             } | 
 |         } | 
 |         WIN_ReleaseWndPtr( ptr ); | 
 |     } | 
 |     DeleteObject( rectRgn ); | 
 |  done: | 
 |     HeapFree( GetProcessHeap(), 0, list ); | 
 |     return ret; | 
 | } | 
 |  | 
 |  | 
 | /*********************************************************************** | 
 |  *		get_visible_region | 
 |  * | 
 |  * Compute the visible region of a window | 
 |  */ | 
 | static HRGN get_visible_region( WND *win, HWND top, UINT flags, int mode ) | 
 | { | 
 |     HRGN rgn; | 
 |     RECT rect; | 
 |     int xoffset, yoffset; | 
 |     X11DRV_WND_DATA *data = win->pDriverData; | 
 |  | 
 |     if (flags & DCX_WINDOW) | 
 |     { | 
 |         xoffset = win->rectWindow.left; | 
 |         yoffset = win->rectWindow.top; | 
 |     } | 
 |     else | 
 |     { | 
 |         xoffset = win->rectClient.left; | 
 |         yoffset = win->rectClient.top; | 
 |     } | 
 |  | 
 |     if (flags & DCX_PARENTCLIP) | 
 |         GetClientRect( win->parent, &rect ); | 
 |     else if (flags & DCX_WINDOW) | 
 |         rect = data->whole_rect; | 
 |     else | 
 |         rect = win->rectClient; | 
 |  | 
 |     /* vis region is relative to the start of the client/window area */ | 
 |     OffsetRect( &rect, -xoffset, -yoffset ); | 
 |  | 
 |     if (!(rgn = CreateRectRgn( rect.left, rect.top, rect.right, rect.bottom ))) return 0; | 
 |  | 
 |     if ((flags & DCX_CLIPCHILDREN) && (mode != ClipByChildren)) | 
 |     { | 
 |         /* we need to clip children by hand */ | 
 |         if (clip_children( win->hwndSelf, 0, rgn, (flags & DCX_WINDOW) ) == NULLREGION) return rgn; | 
 |     } | 
 |  | 
 |     if (top && top != win->hwndSelf)  /* need to clip siblings of ancestors */ | 
 |     { | 
 |         WND *parent, *ptr = WIN_FindWndPtr( win->hwndSelf ); | 
 |         HRGN tmp = 0; | 
 |  | 
 |         OffsetRgn( rgn, xoffset, yoffset ); | 
 |         for (;;) | 
 |         { | 
 |             if (ptr->dwStyle & WS_CLIPSIBLINGS) | 
 |             { | 
 |                 if (clip_children( ptr->parent, ptr->hwndSelf, rgn, FALSE ) == NULLREGION) break; | 
 |             } | 
 |             if (ptr->hwndSelf == top) break; | 
 |             if (!(parent = WIN_FindWndPtr( ptr->parent ))) break; | 
 |             WIN_ReleaseWndPtr( ptr ); | 
 |             ptr = parent; | 
 |             /* clip to parent client area */ | 
 |             if (tmp) SetRectRgn( tmp, 0, 0, ptr->rectClient.right - ptr->rectClient.left, | 
 |                                  ptr->rectClient.bottom - ptr->rectClient.top ); | 
 |             else tmp = CreateRectRgn( 0, 0, ptr->rectClient.right - ptr->rectClient.left, | 
 |                                       ptr->rectClient.bottom - ptr->rectClient.top ); | 
 |             CombineRgn( rgn, rgn, tmp, RGN_AND ); | 
 |             OffsetRgn( rgn, ptr->rectClient.left, ptr->rectClient.top ); | 
 |             xoffset += ptr->rectClient.left; | 
 |             yoffset += ptr->rectClient.top; | 
 |         } | 
 |         WIN_ReleaseWndPtr( ptr ); | 
 |         /* make it relative to the target window again */ | 
 |         OffsetRgn( rgn, -xoffset, -yoffset ); | 
 |         if (tmp) DeleteObject( tmp ); | 
 |     } | 
 |  | 
 |     return rgn; | 
 | } | 
 |  | 
 |  | 
 | /*********************************************************************** | 
 |  *		get_covered_region | 
 |  * | 
 |  * Compute the portion of 'rgn' that is covered by non-clipped siblings. | 
 |  * This is the area that is covered from X point of view, but may still need | 
 |  * to be exposed. | 
 |  * 'rgn' must be relative to the client area of the parent of 'win'. | 
 |  */ | 
 | static int get_covered_region( WND *win, HRGN rgn ) | 
 | { | 
 |     HRGN tmp; | 
 |     int ret; | 
 |     WND *parent, *ptr = WIN_FindWndPtr( win->hwndSelf ); | 
 |     int xoffset = 0, yoffset = 0; | 
 |  | 
 |     tmp = CreateRectRgn( 0, 0, 0, 0 ); | 
 |     CombineRgn( tmp, rgn, 0, RGN_COPY ); | 
 |  | 
 |     /* to make things easier we actually build the uncovered | 
 |      * area by removing all siblings and then we subtract that | 
 |      * from the total region to get the covered area */ | 
 |     for (;;) | 
 |     { | 
 |         if (!(ptr->dwStyle & WS_CLIPSIBLINGS)) | 
 |         { | 
 |             if (clip_children( ptr->parent, ptr->hwndSelf, tmp, FALSE ) == NULLREGION) break; | 
 |         } | 
 |         if (!(parent = WIN_FindWndPtr( ptr->parent ))) break; | 
 |         WIN_ReleaseWndPtr( ptr ); | 
 |         ptr = parent; | 
 |         OffsetRgn( tmp, ptr->rectClient.left, ptr->rectClient.top ); | 
 |         xoffset += ptr->rectClient.left; | 
 |         yoffset += ptr->rectClient.top; | 
 |     } | 
 |     WIN_ReleaseWndPtr( ptr ); | 
 |     /* make it relative to the target window again */ | 
 |     OffsetRgn( tmp, -xoffset, -yoffset ); | 
 |  | 
 |     /* now subtract the computed region from the original one */ | 
 |     ret = CombineRgn( rgn, rgn, tmp, RGN_DIFF ); | 
 |     DeleteObject( tmp ); | 
 |     return ret; | 
 | } | 
 |  | 
 |  | 
 | /*********************************************************************** | 
 |  *		expose_window | 
 |  * | 
 |  * Expose a region of a given window. | 
 |  */ | 
 | static void expose_window( HWND hwnd, RECT *rect, HRGN rgn, int flags ) | 
 | { | 
 |     POINT offset; | 
 |     HWND top = 0; | 
 |     HWND *list; | 
 |     int i; | 
 |  | 
 |     /* find the top most parent that doesn't clip children or siblings and | 
 |      * invalidate the area on its parent, including all children */ | 
 |     if ((list = WIN_ListParents( hwnd ))) | 
 |     { | 
 |         HWND current = hwnd; | 
 |         LONG style = GetWindowLongW( hwnd, GWL_STYLE ); | 
 |         for (i = 0; list[i] && list[i] != GetDesktopWindow(); i++) | 
 |         { | 
 |             if (!(style & WS_CLIPSIBLINGS)) top = current; | 
 |             style = GetWindowLongW( list[i], GWL_STYLE ); | 
 |             if (!(style & WS_CLIPCHILDREN)) top = current; | 
 |             current = list[i]; | 
 |         } | 
 |  | 
 |         if (top) | 
 |         { | 
 |             /* find the parent of the top window, reusing the parent list */ | 
 |             if (top == hwnd) i = 0; | 
 |             else | 
 |             { | 
 |                 for (i = 0; list[i]; i++) if (list[i] == top) break; | 
 |                 if (list[i] && list[i+1]) i++; | 
 |             } | 
 |             if (list[i] != GetDesktopWindow()) top = list[i]; | 
 |             flags &= ~RDW_FRAME;  /* parent will invalidate children frame anyway */ | 
 |             flags |= RDW_ALLCHILDREN; | 
 |         } | 
 |         HeapFree( GetProcessHeap(), 0, list ); | 
 |     } | 
 |  | 
 |     if (!top) top = hwnd; | 
 |  | 
 |     /* make coords relative to top */ | 
 |     offset.x = offset.y = 0; | 
 |     MapWindowPoints( hwnd, top, &offset, 1 ); | 
 |  | 
 |     if (rect) | 
 |     { | 
 |         OffsetRect( rect, offset.x, offset.y ); | 
 |         RedrawWindow( top, rect, 0, flags ); | 
 |     } | 
 |     else | 
 |     { | 
 |         OffsetRgn( rgn, offset.x, offset.y ); | 
 |         RedrawWindow( top, NULL, rgn, flags ); | 
 |     } | 
 | } | 
 |  | 
 |  | 
 | /*********************************************************************** | 
 |  *		expose_covered_parent_area | 
 |  * | 
 |  * Expose the parent area that has been uncovered by moving/hiding a | 
 |  * given window, but that is still covered by other siblings (the area | 
 |  * not covered by siblings will be exposed automatically by X). | 
 |  */ | 
 | static void expose_covered_parent_area( WND *win, const RECT *old_rect ) | 
 | { | 
 |     int ret = SIMPLEREGION; | 
 |     HRGN hrgn = CreateRectRgnIndirect( old_rect ); | 
 |  | 
 |     if (win->dwStyle & WS_VISIBLE) | 
 |     { | 
 |         HRGN tmp = CreateRectRgnIndirect( &win->rectWindow ); | 
 |         ret = CombineRgn( hrgn, hrgn, tmp, RGN_DIFF ); | 
 |         DeleteObject( tmp ); | 
 |     } | 
 |  | 
 |     if (ret != NULLREGION) | 
 |     { | 
 |         if (get_covered_region( win, hrgn ) != NULLREGION) | 
 |             expose_window( win->parent, NULL, hrgn, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN ); | 
 |     } | 
 |     DeleteObject( hrgn ); | 
 | } | 
 |  | 
 |  | 
 | /*********************************************************************** | 
 |  *		expose_covered_window_area | 
 |  * | 
 |  * Expose the area of a window that is covered by other siblings. | 
 |  */ | 
 | static void expose_covered_window_area( WND *win, const RECT *old_client_rect, BOOL frame ) | 
 | { | 
 |     HRGN hrgn; | 
 |     int ret = SIMPLEREGION; | 
 |  | 
 |     if (frame) | 
 |         hrgn = CreateRectRgn( win->rectWindow.left - win->rectClient.left, | 
 |                               win->rectWindow.top - win->rectClient.top, | 
 |                               win->rectWindow.right - win->rectWindow.left, | 
 |                               win->rectWindow.bottom - win->rectWindow.top ); | 
 |     else | 
 |         hrgn = CreateRectRgn( 0, 0, | 
 |                               win->rectClient.right - win->rectClient.left, | 
 |                               win->rectClient.bottom - win->rectClient.top ); | 
 |  | 
 |     /* if the client rect didn't move we don't need to repaint it all */ | 
 |     if (old_client_rect->left == win->rectClient.left && | 
 |         old_client_rect->top == win->rectClient.top) | 
 |     { | 
 |         RECT rc; | 
 |  | 
 |         if (IntersectRect( &rc, old_client_rect, &win->rectClient )) | 
 |         { | 
 |             HRGN tmp; | 
 |             /* subtract the unchanged client area from the region to expose */ | 
 |             OffsetRect( &rc, -win->rectClient.left, -win->rectClient.top ); | 
 |             if ((tmp = CreateRectRgnIndirect( &rc ))) | 
 |             { | 
 |                 ret = CombineRgn( hrgn, hrgn, tmp, RGN_DIFF ); | 
 |                 DeleteObject( tmp ); | 
 |             } | 
 |         } | 
 |     } | 
 |  | 
 |     if (ret != NULLREGION) | 
 |     { | 
 |         if (get_covered_region( win, hrgn ) != NULLREGION) | 
 |             expose_window( win->hwndSelf, NULL, hrgn, | 
 |                            RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN ); | 
 |     } | 
 |  | 
 |     DeleteObject( hrgn ); | 
 | } | 
 |  | 
 |  | 
 | /*********************************************************************** | 
 |  *           X11DRV_Expose | 
 |  */ | 
 | void X11DRV_Expose( HWND hwnd, XExposeEvent *event ) | 
 | { | 
 |     RECT rect; | 
 |     struct x11drv_win_data *data; | 
 |     int flags = RDW_INVALIDATE | RDW_ERASE; | 
 |     WND *win; | 
 |  | 
 |     TRACE( "win %p (%lx) %d,%d %dx%d\n", | 
 |            hwnd, event->window, event->x, event->y, event->width, event->height ); | 
 |  | 
 |     rect.left   = event->x; | 
 |     rect.top    = event->y; | 
 |     rect.right  = rect.left + event->width; | 
 |     rect.bottom = rect.top + event->height; | 
 |  | 
 |     if (!(win = WIN_GetPtr( hwnd ))) return; | 
 |     data = win->pDriverData; | 
 |  | 
 |     if (event->window != data->client_window)  /* whole window or icon window */ | 
 |     { | 
 |         flags |= RDW_FRAME; | 
 |         /* make position relative to client area instead of window */ | 
 |         OffsetRect( &rect, -data->client_rect.left, -data->client_rect.top ); | 
 |     } | 
 |     WIN_ReleasePtr( win ); | 
 |  | 
 |     expose_window( hwnd, &rect, 0, flags ); | 
 | } | 
 |  | 
 |  | 
 | /*********************************************************************** | 
 |  *		GetDC (X11DRV.@) | 
 |  * | 
 |  * Set the drawable, origin and dimensions for the DC associated to | 
 |  * a given window. | 
 |  */ | 
 | BOOL X11DRV_GetDC( HWND hwnd, HDC hdc, HRGN hrgn, DWORD flags ) | 
 | { | 
 |     WND *win = WIN_GetPtr( hwnd ); | 
 |     HWND top = 0; | 
 |     X11DRV_WND_DATA *data = win->pDriverData; | 
 |     Drawable drawable; | 
 |     BOOL visible; | 
 |     POINT org, drawable_org; | 
 |     int mode = IncludeInferiors; | 
 |  | 
 |     /* don't clip siblings if using parent clip region */ | 
 |     if (flags & DCX_PARENTCLIP) flags &= ~DCX_CLIPSIBLINGS; | 
 |  | 
 |     /* find the top parent in the hierarchy that isn't clipping siblings */ | 
 |     visible = (win->dwStyle & WS_VISIBLE) != 0; | 
 |  | 
 |     if (visible) | 
 |     { | 
 |         HWND *list = WIN_ListParents( hwnd ); | 
 |         if (list) | 
 |         { | 
 |             int i; | 
 |             for (i = 0; list[i] != GetDesktopWindow(); i++) | 
 |             { | 
 |                 LONG style = GetWindowLongW( list[i], GWL_STYLE ); | 
 |                 if (!(style & WS_VISIBLE)) | 
 |                 { | 
 |                     visible = FALSE; | 
 |                     top = 0; | 
 |                     break; | 
 |                 } | 
 |                 if (!(style & WS_CLIPSIBLINGS)) top = list[i]; | 
 |             } | 
 |             HeapFree( GetProcessHeap(), 0, list ); | 
 |         } | 
 |         if (!top && visible && !(flags & DCX_CLIPSIBLINGS)) top = hwnd; | 
 |     } | 
 |  | 
 |     if (top) | 
 |     { | 
 |         HWND parent = GetAncestor( top, GA_PARENT ); | 
 |         org.x = org.y = 0; | 
 |         if (flags & DCX_WINDOW) | 
 |         { | 
 |             org.x = win->rectWindow.left - win->rectClient.left; | 
 |             org.y = win->rectWindow.top - win->rectClient.top; | 
 |         } | 
 |         drawable_org = org; | 
 |         MapWindowPoints( hwnd, parent, &org, 1 ); | 
 |         MapWindowPoints( hwnd, 0, &drawable_org, 1 ); | 
 |         /* have to use the parent so that we include siblings */ | 
 |         if (parent) drawable = X11DRV_get_client_window( parent ); | 
 |         else drawable = root_window; | 
 |     } | 
 |     else | 
 |     { | 
 |         if (IsIconic( hwnd )) | 
 |         { | 
 |             drawable = data->icon_window ? data->icon_window : data->whole_window; | 
 |             org.x = 0; | 
 |             org.y = 0; | 
 |             drawable_org = org; | 
 |         } | 
 |         else if (flags & DCX_WINDOW) | 
 |         { | 
 |             drawable = data->whole_window; | 
 |             org.x = win->rectWindow.left - data->whole_rect.left; | 
 |             org.y = win->rectWindow.top - data->whole_rect.top; | 
 |             drawable_org.x = data->whole_rect.left - win->rectClient.left; | 
 |             drawable_org.y = data->whole_rect.top - win->rectClient.top; | 
 |         } | 
 |         else | 
 |         { | 
 |             drawable = data->client_window; | 
 |             org.x = 0; | 
 |             org.y = 0; | 
 |             drawable_org = org; | 
 |             if (flags & DCX_CLIPCHILDREN) mode = ClipByChildren;  /* can use X11 clipping */ | 
 |         } | 
 |         MapWindowPoints( hwnd, 0, &drawable_org, 1 ); | 
 |     } | 
 |  | 
 |     X11DRV_SetDrawable( hdc, drawable, mode, &org, &drawable_org ); | 
 |  | 
 |     if (flags & (DCX_EXCLUDERGN | DCX_INTERSECTRGN) || | 
 |         SetHookFlags16( HDC_16(hdc), DCHF_VALIDATEVISRGN ))  /* DC was dirty */ | 
 |     { | 
 |         /* need to recompute the visible region */ | 
 |         HRGN visRgn; | 
 |  | 
 |         if (visible) | 
 |         { | 
 |             visRgn = get_visible_region( win, top, flags, mode ); | 
 |  | 
 |             if (flags & (DCX_EXCLUDERGN | DCX_INTERSECTRGN)) | 
 |                 CombineRgn( visRgn, visRgn, hrgn, | 
 |                             (flags & DCX_INTERSECTRGN) ? RGN_AND : RGN_DIFF ); | 
 |         } | 
 |         else visRgn = CreateRectRgn( 0, 0, 0, 0 ); | 
 |  | 
 |         SelectVisRgn16( HDC_16(hdc), HRGN_16(visRgn) ); | 
 |         DeleteObject( visRgn ); | 
 |     } | 
 |  | 
 |     WIN_ReleasePtr( win ); | 
 |     return TRUE; | 
 | } | 
 |  | 
 |  | 
 |  | 
 | /*********************************************************************** | 
 |  *           SWP_DoWinPosChanging | 
 |  */ | 
 | static BOOL SWP_DoWinPosChanging( WINDOWPOS* pWinpos, RECT* pNewWindowRect, RECT* pNewClientRect ) | 
 | { | 
 |     WND *wndPtr; | 
 |  | 
 |     /* Send WM_WINDOWPOSCHANGING message */ | 
 |  | 
 |     if (!(pWinpos->flags & SWP_NOSENDCHANGING)) | 
 |         SendMessageA( pWinpos->hwnd, WM_WINDOWPOSCHANGING, 0, (LPARAM)pWinpos ); | 
 |  | 
 |     if (!(wndPtr = WIN_GetPtr( pWinpos->hwnd )) || wndPtr == WND_OTHER_PROCESS) return FALSE; | 
 |  | 
 |     /* Calculate new position and size */ | 
 |  | 
 |     *pNewWindowRect = wndPtr->rectWindow; | 
 |     *pNewClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow | 
 |                                                     : wndPtr->rectClient; | 
 |  | 
 |     if (!(pWinpos->flags & SWP_NOSIZE)) | 
 |     { | 
 |         pNewWindowRect->right  = pNewWindowRect->left + pWinpos->cx; | 
 |         pNewWindowRect->bottom = pNewWindowRect->top + pWinpos->cy; | 
 |     } | 
 |     if (!(pWinpos->flags & SWP_NOMOVE)) | 
 |     { | 
 |         pNewWindowRect->left    = pWinpos->x; | 
 |         pNewWindowRect->top     = pWinpos->y; | 
 |         pNewWindowRect->right  += pWinpos->x - wndPtr->rectWindow.left; | 
 |         pNewWindowRect->bottom += pWinpos->y - wndPtr->rectWindow.top; | 
 |  | 
 |         OffsetRect( pNewClientRect, pWinpos->x - wndPtr->rectWindow.left, | 
 |                                     pWinpos->y - wndPtr->rectWindow.top ); | 
 |     } | 
 |     pWinpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE; | 
 |     WIN_ReleasePtr( wndPtr ); | 
 |     return TRUE; | 
 | } | 
 |  | 
 | /*********************************************************************** | 
 |  *           SWP_DoNCCalcSize | 
 |  */ | 
 | static UINT SWP_DoNCCalcSize( WINDOWPOS* pWinpos, RECT* pNewWindowRect, RECT* pNewClientRect ) | 
 | { | 
 |     UINT wvrFlags = 0; | 
 |     WND *wndPtr; | 
 |  | 
 |     if (!(wndPtr = WIN_GetPtr( pWinpos->hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0; | 
 |  | 
 |       /* Send WM_NCCALCSIZE message to get new client area */ | 
 |     if( (pWinpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE ) | 
 |     { | 
 |         NCCALCSIZE_PARAMS params; | 
 |         WINDOWPOS winposCopy; | 
 |  | 
 |         params.rgrc[0] = *pNewWindowRect; | 
 |         params.rgrc[1] = wndPtr->rectWindow; | 
 |         params.rgrc[2] = wndPtr->rectClient; | 
 |         params.lppos = &winposCopy; | 
 |         winposCopy = *pWinpos; | 
 |         WIN_ReleasePtr( wndPtr ); | 
 |  | 
 |         wvrFlags = SendMessageW( pWinpos->hwnd, WM_NCCALCSIZE, TRUE, (LPARAM)¶ms ); | 
 |  | 
 |         TRACE( "%d,%d-%d,%d\n", params.rgrc[0].left, params.rgrc[0].top, | 
 |                params.rgrc[0].right, params.rgrc[0].bottom ); | 
 |  | 
 |         /* If the application send back garbage, ignore it */ | 
 |         if (params.rgrc[0].left <= params.rgrc[0].right && | 
 |             params.rgrc[0].top <= params.rgrc[0].bottom) | 
 |             *pNewClientRect = params.rgrc[0]; | 
 |  | 
 |          /* FIXME: WVR_ALIGNxxx */ | 
 |  | 
 |         if (!(wndPtr = WIN_GetPtr( pWinpos->hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0; | 
 |  | 
 |         if( pNewClientRect->left != wndPtr->rectClient.left || | 
 |             pNewClientRect->top != wndPtr->rectClient.top ) | 
 |             pWinpos->flags &= ~SWP_NOCLIENTMOVE; | 
 |  | 
 |         if( (pNewClientRect->right - pNewClientRect->left != | 
 |              wndPtr->rectClient.right - wndPtr->rectClient.left) || | 
 |             (pNewClientRect->bottom - pNewClientRect->top != | 
 |              wndPtr->rectClient.bottom - wndPtr->rectClient.top) ) | 
 |             pWinpos->flags &= ~SWP_NOCLIENTSIZE; | 
 |     } | 
 |     else | 
 |     { | 
 |         if (!(pWinpos->flags & SWP_NOMOVE) && | 
 |             (pNewClientRect->left != wndPtr->rectClient.left || | 
 |              pNewClientRect->top != wndPtr->rectClient.top)) | 
 |             pWinpos->flags &= ~SWP_NOCLIENTMOVE; | 
 |     } | 
 |     WIN_ReleasePtr( wndPtr ); | 
 |     return wvrFlags; | 
 | } | 
 |  | 
 |  | 
 | /*********************************************************************** | 
 |  *           SWP_DoOwnedPopups | 
 |  * | 
 |  * fix Z order taking into account owned popups - | 
 |  * basically we need to maintain them above the window that owns them | 
 |  * | 
 |  * FIXME: hide/show owned popups when owner visibility changes. | 
 |  */ | 
 | static HWND SWP_DoOwnedPopups(HWND hwnd, HWND hwndInsertAfter) | 
 | { | 
 |     HWND *list = NULL; | 
 |     HWND owner = GetWindow( hwnd, GW_OWNER ); | 
 |     LONG style = GetWindowLongW( hwnd, GWL_STYLE ); | 
 |  | 
 |     WARN("(%p) hInsertAfter = %p\n", hwnd, hwndInsertAfter ); | 
 |  | 
 |     if ((style & WS_POPUP) && owner) | 
 |     { | 
 |         /* make sure this popup stays above the owner */ | 
 |  | 
 |         HWND hwndLocalPrev = HWND_TOP; | 
 |  | 
 |         if( hwndInsertAfter != HWND_TOP ) | 
 |         { | 
 |             if ((list = WIN_ListChildren( GetDesktopWindow() ))) | 
 |             { | 
 |                 int i; | 
 |                 for (i = 0; list[i]; i++) | 
 |                 { | 
 |                     if (list[i] == owner) break; | 
 |                     if (list[i] != hwnd) hwndLocalPrev = list[i]; | 
 |                     if (hwndLocalPrev == hwndInsertAfter) break; | 
 |                 } | 
 |                 hwndInsertAfter = hwndLocalPrev; | 
 |             } | 
 |         } | 
 |     } | 
 |     else if (style & WS_CHILD) return hwndInsertAfter; | 
 |  | 
 |     if (!list) list = WIN_ListChildren( GetDesktopWindow() ); | 
 |     if (list) | 
 |     { | 
 |         int i; | 
 |         for (i = 0; list[i]; i++) | 
 |         { | 
 |             if (list[i] == hwnd) break; | 
 |             if ((GetWindowLongW( list[i], GWL_STYLE ) & WS_POPUP) && | 
 |                 GetWindow( list[i], GW_OWNER ) == hwnd) | 
 |             { | 
 |                 SetWindowPos( list[i], hwndInsertAfter, 0, 0, 0, 0, | 
 |                               SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | | 
 |                               SWP_NOSENDCHANGING | SWP_DEFERERASE ); | 
 |                 hwndInsertAfter = list[i]; | 
 |             } | 
 |         } | 
 |         HeapFree( GetProcessHeap(), 0, list ); | 
 |     } | 
 |  | 
 |     return hwndInsertAfter; | 
 | } | 
 |  | 
 |  | 
 | /* fix redundant flags and values in the WINDOWPOS structure */ | 
 | static BOOL fixup_flags( WINDOWPOS *winpos ) | 
 | { | 
 |     WND *wndPtr = WIN_GetPtr( winpos->hwnd ); | 
 |     BOOL ret = TRUE; | 
 |  | 
 |     if (!wndPtr || wndPtr == WND_OTHER_PROCESS) | 
 |     { | 
 |         SetLastError( ERROR_INVALID_WINDOW_HANDLE ); | 
 |         return FALSE; | 
 |     } | 
 |     winpos->hwnd = wndPtr->hwndSelf;  /* make it a full handle */ | 
 |  | 
 |     if (wndPtr->dwStyle & WS_VISIBLE) winpos->flags &= ~SWP_SHOWWINDOW; | 
 |     else | 
 |     { | 
 |         winpos->flags &= ~SWP_HIDEWINDOW; | 
 |         if (!(winpos->flags & SWP_SHOWWINDOW)) winpos->flags |= SWP_NOREDRAW; | 
 |     } | 
 |  | 
 |     if (winpos->cx < 0) winpos->cx = 0; | 
 |     if (winpos->cy < 0) winpos->cy = 0; | 
 |  | 
 |     if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == winpos->cx) && | 
 |         (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == winpos->cy)) | 
 |         winpos->flags |= SWP_NOSIZE;    /* Already the right size */ | 
 |  | 
 |     if ((wndPtr->rectWindow.left == winpos->x) && (wndPtr->rectWindow.top == winpos->y)) | 
 |         winpos->flags |= SWP_NOMOVE;    /* Already the right position */ | 
 |  | 
 |     if (winpos->hwnd == GetForegroundWindow()) | 
 |         winpos->flags |= SWP_NOACTIVATE;   /* Already active */ | 
 |     else if ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD) | 
 |     { | 
 |         if (!(winpos->flags & SWP_NOACTIVATE)) /* Bring to the top when activating */ | 
 |         { | 
 |             winpos->flags &= ~SWP_NOZORDER; | 
 |             winpos->hwndInsertAfter = HWND_TOP; | 
 |             goto done; | 
 |         } | 
 |     } | 
 |  | 
 |     /* Check hwndInsertAfter */ | 
 |     if (winpos->flags & SWP_NOZORDER) goto done; | 
 |  | 
 |     /* fix sign extension */ | 
 |     if (winpos->hwndInsertAfter == (HWND)0xffff) winpos->hwndInsertAfter = HWND_TOPMOST; | 
 |     else if (winpos->hwndInsertAfter == (HWND)0xfffe) winpos->hwndInsertAfter = HWND_NOTOPMOST; | 
 |  | 
 |       /* FIXME: TOPMOST not supported yet */ | 
 |     if ((winpos->hwndInsertAfter == HWND_TOPMOST) || | 
 |         (winpos->hwndInsertAfter == HWND_NOTOPMOST)) winpos->hwndInsertAfter = HWND_TOP; | 
 |  | 
 |     /* hwndInsertAfter must be a sibling of the window */ | 
 |     if ((winpos->hwndInsertAfter != HWND_TOP) && (winpos->hwndInsertAfter != HWND_BOTTOM)) | 
 |     { | 
 |         if (GetAncestor( winpos->hwndInsertAfter, GA_PARENT ) != wndPtr->parent) ret = FALSE; | 
 |         else | 
 |         { | 
 |             /* don't need to change the Zorder of hwnd if it's already inserted | 
 |              * after hwndInsertAfter or when inserting hwnd after itself. | 
 |              */ | 
 |             if ((winpos->hwnd == winpos->hwndInsertAfter) || | 
 |                 (winpos->hwnd == GetWindow( winpos->hwndInsertAfter, GW_HWNDNEXT ))) | 
 |                 winpos->flags |= SWP_NOZORDER; | 
 |         } | 
 |     } | 
 |  done: | 
 |     WIN_ReleasePtr( wndPtr ); | 
 |     return ret; | 
 | } | 
 |  | 
 |  | 
 | /*********************************************************************** | 
 |  *		set_visible_style | 
 |  * | 
 |  * Set/clear the WS_VISIBLE style of a window and map/unmap the X window. | 
 |  */ | 
 | static void set_visible_style( HWND hwnd, BOOL set ) | 
 | { | 
 |     WND *win; | 
 |  | 
 |     if (!(win = WIN_GetPtr( hwnd ))) return; | 
 |     if (win == WND_OTHER_PROCESS) return; | 
 |  | 
 |     TRACE( "hwnd %p (%lx) set %d visible %d empty %d\n", | 
 |            hwnd, get_whole_window(win), | 
 |            set, (win->dwStyle & WS_VISIBLE) != 0, IsRectEmpty(&win->rectWindow) ); | 
 |  | 
 |     if (set) | 
 |     { | 
 |         if (win->dwStyle & WS_VISIBLE) goto done; | 
 |         WIN_SetStyle( hwnd, win->dwStyle | WS_VISIBLE ); | 
 |         if (!IsRectEmpty( &win->rectWindow ) && get_whole_window(win) && is_window_top_level(win)) | 
 |         { | 
 |             Display *display = thread_display(); | 
 |             X11DRV_sync_window_style( display, win ); | 
 |             X11DRV_set_wm_hints( display, win ); | 
 |             TRACE( "mapping win %p\n", hwnd ); | 
 |             TSXMapWindow( display, get_whole_window(win) ); | 
 |         } | 
 |     } | 
 |     else | 
 |     { | 
 |         if (!(win->dwStyle & WS_VISIBLE)) goto done; | 
 |         WIN_SetStyle( hwnd, win->dwStyle & ~WS_VISIBLE ); | 
 |         if (!IsRectEmpty( &win->rectWindow ) && get_whole_window(win) && is_window_top_level(win)) | 
 |         { | 
 |             TRACE( "unmapping win %p\n", hwnd ); | 
 |             TSXUnmapWindow( thread_display(), get_whole_window(win) ); | 
 |         } | 
 |     } | 
 |  done: | 
 |     WIN_ReleasePtr( win ); | 
 | } | 
 |  | 
 |  | 
 | /*********************************************************************** | 
 |  *		SetWindowStyle   (X11DRV.@) | 
 |  * | 
 |  * Update the X state of a window to reflect a style change | 
 |  */ | 
 | void X11DRV_SetWindowStyle( HWND hwnd, LONG oldStyle ) | 
 | { | 
 |     Display *display = thread_display(); | 
 |     WND *wndPtr; | 
 |     LONG changed; | 
 |  | 
 |     if (hwnd == GetDesktopWindow()) return; | 
 |     if (!(wndPtr = WIN_GetPtr( hwnd ))) return; | 
 |     if (wndPtr == WND_OTHER_PROCESS) return; | 
 |  | 
 |     changed = wndPtr->dwStyle ^ oldStyle; | 
 |  | 
 |     if (changed & WS_VISIBLE) | 
 |     { | 
 |         if (!IsRectEmpty( &wndPtr->rectWindow ) && !is_window_top_level(wndPtr)) | 
 |         { | 
 |             if (wndPtr->dwStyle & WS_VISIBLE) | 
 |             { | 
 |                 TRACE( "mapping win %p\n", hwnd ); | 
 |                 TSXMapWindow( display, get_whole_window(wndPtr) ); | 
 |             } | 
 |             else | 
 |             { | 
 |                 TRACE( "unmapping win %p\n", hwnd ); | 
 |                 TSXUnmapWindow( display, get_whole_window(wndPtr) ); | 
 |             } | 
 |         } | 
 |     } | 
 |  | 
 |     if (changed & WS_DISABLED) | 
 |     { | 
 |         if (wndPtr->dwExStyle & WS_EX_MANAGED) | 
 |         { | 
 |             XWMHints *wm_hints; | 
 |             wine_tsx11_lock(); | 
 |             if (!(wm_hints = XGetWMHints( display, get_whole_window(wndPtr) ))) | 
 |                 wm_hints = XAllocWMHints(); | 
 |             if (wm_hints) | 
 |             { | 
 |                 wm_hints->flags |= InputHint; | 
 |                 wm_hints->input = !(wndPtr->dwStyle & WS_DISABLED); | 
 |                 XSetWMHints( display, get_whole_window(wndPtr), wm_hints ); | 
 |                 XFree(wm_hints); | 
 |             } | 
 |             wine_tsx11_unlock(); | 
 |         } | 
 |     } | 
 |     WIN_ReleasePtr(wndPtr); | 
 | } | 
 |  | 
 |  | 
 | /*********************************************************************** | 
 |  *		SetWindowPos   (X11DRV.@) | 
 |  */ | 
 | BOOL X11DRV_SetWindowPos( WINDOWPOS *winpos ) | 
 | { | 
 |     WND *wndPtr; | 
 |     RECT newWindowRect, newClientRect; | 
 |     RECT oldWindowRect, oldClientRect; | 
 |     UINT wvrFlags = 0; | 
 |     BOOL bChangePos; | 
 |  | 
 |     TRACE( "hwnd %p, swp (%i,%i)-(%i,%i) flags %08x\n", | 
 |            winpos->hwnd, winpos->x, winpos->y, | 
 |            winpos->x + winpos->cx, winpos->y + winpos->cy, winpos->flags); | 
 |  | 
 |     bChangePos = !(winpos->flags & SWP_WINE_NOHOSTMOVE); | 
 |     winpos->flags &= ~SWP_WINE_NOHOSTMOVE; | 
 |  | 
 |     /* Fix redundant flags */ | 
 |     if (!fixup_flags( winpos )) return FALSE; | 
 |  | 
 |     /* Check window handle */ | 
 |     if (winpos->hwnd == GetDesktopWindow()) return FALSE; | 
 |  | 
 |     SWP_DoWinPosChanging( winpos, &newWindowRect, &newClientRect ); | 
 |  | 
 |     if (!(wndPtr = WIN_FindWndPtr( winpos->hwnd ))) return FALSE; | 
 |  | 
 |     TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n", | 
 |           wndPtr->rectWindow.left, wndPtr->rectWindow.top, | 
 |           wndPtr->rectWindow.right, wndPtr->rectWindow.bottom, (unsigned)wndPtr->dwStyle ); | 
 |  | 
 |     if((winpos->flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER) | 
 |     { | 
 |         if (GetAncestor( winpos->hwnd, GA_PARENT ) == GetDesktopWindow()) | 
 |             winpos->hwndInsertAfter = SWP_DoOwnedPopups( winpos->hwnd, winpos->hwndInsertAfter ); | 
 |     } | 
 |  | 
 |     /* Common operations */ | 
 |  | 
 |     wvrFlags = SWP_DoNCCalcSize( winpos, &newWindowRect, &newClientRect ); | 
 |  | 
 |     if(!(winpos->flags & SWP_NOZORDER) && winpos->hwnd != winpos->hwndInsertAfter) | 
 |     { | 
 |         HWND parent = GetAncestor( winpos->hwnd, GA_PARENT ); | 
 |         if (parent) WIN_LinkWindow( winpos->hwnd, parent, winpos->hwndInsertAfter ); | 
 |     } | 
 |  | 
 |     /* Reset active DCEs */ | 
 |  | 
 |     if( (((winpos->flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) && | 
 |          wndPtr->dwStyle & WS_VISIBLE) || | 
 |         (winpos->flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)) ) | 
 |     { | 
 |         RECT rect; | 
 |  | 
 |         UnionRect(&rect, &newWindowRect, &wndPtr->rectWindow); | 
 |         DCE_InvalidateDCE(wndPtr->hwndSelf, &rect); | 
 |     } | 
 |  | 
 |     oldWindowRect = wndPtr->rectWindow; | 
 |     oldClientRect = wndPtr->rectClient; | 
 |  | 
 |     /* Find out if we have to redraw the whole client rect */ | 
 |  | 
 |     if( oldClientRect.bottom - oldClientRect.top == | 
 |         newClientRect.bottom - newClientRect.top ) wvrFlags &= ~WVR_VREDRAW; | 
 |  | 
 |     if( oldClientRect.right - oldClientRect.left == | 
 |         newClientRect.right - newClientRect.left ) wvrFlags &= ~WVR_HREDRAW; | 
 |  | 
 |     /* FIXME: actually do something with WVR_VALIDRECTS */ | 
 |  | 
 |     WIN_SetRectangles( winpos->hwnd, &newWindowRect, &newClientRect ); | 
 |  | 
 |     if (get_whole_window(wndPtr))  /* don't do anything if X window not created yet */ | 
 |     { | 
 |         Display *display = thread_display(); | 
 |  | 
 |         if (!(winpos->flags & SWP_SHOWWINDOW) && (winpos->flags & SWP_HIDEWINDOW)) | 
 |         { | 
 |             /* clear the update region */ | 
 |             RedrawWindow( winpos->hwnd, NULL, 0, RDW_VALIDATE | RDW_NOFRAME | | 
 |                           RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_ALLCHILDREN ); | 
 |             set_visible_style( winpos->hwnd, FALSE ); | 
 |         } | 
 |         else if ((wndPtr->dwStyle & WS_VISIBLE) && | 
 |                  !IsRectEmpty( &oldWindowRect ) && IsRectEmpty( &newWindowRect )) | 
 |         { | 
 |             /* resizing to zero size -> unmap */ | 
 |             TRACE( "unmapping zero size win %p\n", winpos->hwnd ); | 
 |             TSXUnmapWindow( display, get_whole_window(wndPtr) ); | 
 |         } | 
 |  | 
 |         wine_tsx11_lock(); | 
 |         if (bChangePos) | 
 |             X11DRV_sync_whole_window_position( display, wndPtr, !(winpos->flags & SWP_NOZORDER) ); | 
 |         else | 
 |         { | 
 |             struct x11drv_win_data *data = wndPtr->pDriverData; | 
 |             data->whole_rect = wndPtr->rectWindow; | 
 |             X11DRV_window_to_X_rect( wndPtr, &data->whole_rect ); | 
 |         } | 
 |  | 
 |         if (X11DRV_sync_client_window_position( display, wndPtr ) || | 
 |             (winpos->flags & SWP_FRAMECHANGED)) | 
 |         { | 
 |             /* if we moved the client area, repaint the whole non-client window */ | 
 |             XClearArea( display, get_whole_window(wndPtr), 0, 0, 0, 0, True ); | 
 |             winpos->flags |= SWP_FRAMECHANGED; | 
 |         } | 
 |         if (winpos->flags & SWP_SHOWWINDOW) | 
 |         { | 
 |             set_visible_style( winpos->hwnd, TRUE ); | 
 |         } | 
 |         else if ((wndPtr->dwStyle & WS_VISIBLE) && | 
 |                  IsRectEmpty( &oldWindowRect ) && !IsRectEmpty( &newWindowRect )) | 
 |         { | 
 |             /* resizing from zero size to non-zero -> map */ | 
 |             TRACE( "mapping non zero size win %p\n", winpos->hwnd ); | 
 |             XMapWindow( display, get_whole_window(wndPtr) ); | 
 |         } | 
 |         XFlush( display );  /* FIXME: should not be necessary */ | 
 |         wine_tsx11_unlock(); | 
 |     } | 
 |     else  /* no X window, simply toggle the window style */ | 
 |     { | 
 |         if (winpos->flags & SWP_SHOWWINDOW) | 
 |             set_visible_style( winpos->hwnd, TRUE ); | 
 |         else if (winpos->flags & SWP_HIDEWINDOW) | 
 |             set_visible_style( winpos->hwnd, FALSE ); | 
 |     } | 
 |  | 
 |     /* manually expose the areas that X won't expose because they are still covered by something */ | 
 |  | 
 |     if (!(winpos->flags & SWP_SHOWWINDOW)) | 
 |         expose_covered_parent_area( wndPtr, &oldWindowRect ); | 
 |  | 
 |     if (wndPtr->dwStyle & WS_VISIBLE) | 
 |         expose_covered_window_area( wndPtr, &oldClientRect, winpos->flags & SWP_FRAMECHANGED ); | 
 |  | 
 |     WIN_ReleaseWndPtr(wndPtr); | 
 |  | 
 |     if (wvrFlags & WVR_REDRAW) RedrawWindow( winpos->hwnd, NULL, 0, RDW_INVALIDATE | RDW_ERASE ); | 
 |  | 
 |     if( winpos->flags & SWP_HIDEWINDOW ) | 
 |         HideCaret(winpos->hwnd); | 
 |     else if (winpos->flags & SWP_SHOWWINDOW) | 
 |         ShowCaret(winpos->hwnd); | 
 |  | 
 |     if (!(winpos->flags & SWP_NOACTIVATE)) | 
 |     { | 
 |         /* child windows get WM_CHILDACTIVATE message */ | 
 |         if ((GetWindowLongW( winpos->hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD) | 
 |             SendMessageA( winpos->hwnd, WM_CHILDACTIVATE, 0, 0 ); | 
 |         else | 
 |             SetForegroundWindow( winpos->hwnd ); | 
 |     } | 
 |  | 
 |       /* And last, send the WM_WINDOWPOSCHANGED message */ | 
 |  | 
 |     TRACE("\tstatus flags = %04x\n", winpos->flags & SWP_AGG_STATUSFLAGS); | 
 |  | 
 |     if (((winpos->flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE)) | 
 |         SendMessageA( winpos->hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)winpos ); | 
 |         /* WM_WINDOWPOSCHANGED is send even if SWP_NOSENDCHANGING is set */ | 
 |  | 
 |     return TRUE; | 
 | } | 
 |  | 
 |  | 
 | /*********************************************************************** | 
 |  *           WINPOS_FindIconPos | 
 |  * | 
 |  * Find a suitable place for an iconic window. | 
 |  */ | 
 | static POINT WINPOS_FindIconPos( WND* wndPtr, POINT pt ) | 
 | { | 
 |     RECT rectParent; | 
 |     HWND *list; | 
 |     short x, y, xspacing, yspacing; | 
 |  | 
 |     GetClientRect( wndPtr->parent, &rectParent ); | 
 |     if ((pt.x >= rectParent.left) && (pt.x + GetSystemMetrics(SM_CXICON) < rectParent.right) && | 
 |         (pt.y >= rectParent.top) && (pt.y + GetSystemMetrics(SM_CYICON) < rectParent.bottom)) | 
 |         return pt;  /* The icon already has a suitable position */ | 
 |  | 
 |     xspacing = GetSystemMetrics(SM_CXICONSPACING); | 
 |     yspacing = GetSystemMetrics(SM_CYICONSPACING); | 
 |  | 
 |     list = WIN_ListChildren( wndPtr->parent ); | 
 |     y = rectParent.bottom; | 
 |     for (;;) | 
 |     { | 
 |         x = rectParent.left; | 
 |         do | 
 |         { | 
 |             /* Check if another icon already occupies this spot */ | 
 |             /* FIXME: this is completely inefficient */ | 
 |             if (list) | 
 |             { | 
 |                 int i; | 
 |                 WND *childPtr; | 
 |  | 
 |                 for (i = 0; list[i]; i++) | 
 |                 { | 
 |                     if (list[i] == wndPtr->hwndSelf) continue; | 
 |                     if (!IsIconic( list[i] )) continue; | 
 |                     if (!(childPtr = WIN_FindWndPtr( list[i] ))) continue; | 
 |                     if ((childPtr->rectWindow.left < x + xspacing) && | 
 |                         (childPtr->rectWindow.right >= x) && | 
 |                         (childPtr->rectWindow.top <= y) && | 
 |                         (childPtr->rectWindow.bottom > y - yspacing)) | 
 |                     { | 
 |                         WIN_ReleaseWndPtr( childPtr ); | 
 |                         break;  /* There's a window in there */ | 
 |                     } | 
 |                     WIN_ReleaseWndPtr( childPtr ); | 
 |                 } | 
 |                 if (list[i]) | 
 |                 { | 
 |                     /* found something here, try next spot */ | 
 |                     x += xspacing; | 
 |                     continue; | 
 |                 } | 
 |             } | 
 |  | 
 |             /* No window was found, so it's OK for us */ | 
 |             pt.x = x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2; | 
 |             pt.y = y - (yspacing + GetSystemMetrics(SM_CYICON)) / 2; | 
 |             HeapFree( GetProcessHeap(), 0, list ); | 
 |             return pt; | 
 |  | 
 |         } while(x <= rectParent.right-xspacing); | 
 |         y -= yspacing; | 
 |     } | 
 | } | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 | UINT WINPOS_MinMaximize( HWND hwnd, UINT cmd, LPRECT rect ) | 
 | { | 
 |     WND *wndPtr; | 
 |     UINT swpFlags = 0; | 
 |     POINT size; | 
 |     LONG old_style; | 
 |     WINDOWPLACEMENT wpl; | 
 |  | 
 |     TRACE("%p %u\n", hwnd, cmd ); | 
 |  | 
 |     wpl.length = sizeof(wpl); | 
 |     GetWindowPlacement( hwnd, &wpl ); | 
 |  | 
 |     if (HOOK_CallHooks( WH_CBT, HCBT_MINMAX, (WPARAM)hwnd, cmd, TRUE )) | 
 |         return SWP_NOSIZE | SWP_NOMOVE; | 
 |  | 
 |     if (IsIconic( hwnd )) | 
 |     { | 
 |         if (cmd == SW_MINIMIZE) return SWP_NOSIZE | SWP_NOMOVE; | 
 |         if (!SendMessageA( hwnd, WM_QUERYOPEN, 0, 0 )) return SWP_NOSIZE | SWP_NOMOVE; | 
 |         swpFlags |= SWP_NOCOPYBITS; | 
 |     } | 
 |  | 
 |     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0; | 
 |  | 
 |     size.x = wndPtr->rectWindow.left; | 
 |     size.y = wndPtr->rectWindow.top; | 
 |  | 
 |     switch( cmd ) | 
 |     { | 
 |     case SW_MINIMIZE: | 
 |         if( wndPtr->dwStyle & WS_MAXIMIZE) wndPtr->flags |= WIN_RESTORE_MAX; | 
 |         else wndPtr->flags &= ~WIN_RESTORE_MAX; | 
 |  | 
 |         WIN_SetStyle( hwnd, (wndPtr->dwStyle & ~WS_MAXIMIZE) | WS_MINIMIZE ); | 
 |  | 
 |         X11DRV_set_iconic_state( wndPtr ); | 
 |  | 
 |         wpl.ptMinPosition = WINPOS_FindIconPos( wndPtr, wpl.ptMinPosition ); | 
 |  | 
 |         SetRect( rect, wpl.ptMinPosition.x, wpl.ptMinPosition.y, | 
 |                  GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON) ); | 
 |         swpFlags |= SWP_NOCOPYBITS; | 
 |         break; | 
 |  | 
 |     case SW_MAXIMIZE: | 
 |         WINPOS_GetMinMaxInfo( hwnd, &size, &wpl.ptMaxPosition, NULL, NULL ); | 
 |  | 
 |         old_style = WIN_SetStyle( hwnd, (wndPtr->dwStyle & ~WS_MINIMIZE) | WS_MAXIMIZE ); | 
 |         if (old_style & WS_MINIMIZE) | 
 |         { | 
 |             WINPOS_ShowIconTitle( hwnd, FALSE ); | 
 |             X11DRV_set_iconic_state( wndPtr ); | 
 |         } | 
 |         SetRect( rect, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, size.x, size.y ); | 
 |         break; | 
 |  | 
 |     case SW_RESTORE: | 
 |         old_style = WIN_SetStyle( hwnd, wndPtr->dwStyle & ~(WS_MINIMIZE|WS_MAXIMIZE) ); | 
 |         if (old_style & WS_MINIMIZE) | 
 |         { | 
 |             WINPOS_ShowIconTitle( hwnd, FALSE ); | 
 |             X11DRV_set_iconic_state( wndPtr ); | 
 |  | 
 |             if( wndPtr->flags & WIN_RESTORE_MAX) | 
 |             { | 
 |                 /* Restore to maximized position */ | 
 |                 WINPOS_GetMinMaxInfo( hwnd, &size, &wpl.ptMaxPosition, NULL, NULL); | 
 |                 WIN_SetStyle( hwnd, wndPtr->dwStyle | WS_MAXIMIZE ); | 
 |                 SetRect( rect, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, size.x, size.y ); | 
 |                 break; | 
 |             } | 
 |         } | 
 |         else if (!(old_style & WS_MAXIMIZE)) break; | 
 |  | 
 |         /* Restore to normal position */ | 
 |  | 
 |         *rect = wpl.rcNormalPosition; | 
 |         rect->right -= rect->left; | 
 |         rect->bottom -= rect->top; | 
 |  | 
 |         break; | 
 |     } | 
 |  | 
 |     WIN_ReleaseWndPtr( wndPtr ); | 
 |     return swpFlags; | 
 | } | 
 |  | 
 |  | 
 | /*********************************************************************** | 
 |  *              ShowWindow   (X11DRV.@) | 
 |  */ | 
 | BOOL X11DRV_ShowWindow( HWND hwnd, INT cmd ) | 
 | { | 
 |     WND* 	wndPtr = WIN_FindWndPtr( hwnd ); | 
 |     BOOL 	wasVisible, showFlag; | 
 |     RECT 	newPos = {0, 0, 0, 0}; | 
 |     UINT 	swp = 0; | 
 |  | 
 |     if (!wndPtr) return FALSE; | 
 |     hwnd = wndPtr->hwndSelf;  /* make it a full handle */ | 
 |  | 
 |     TRACE("hwnd=%p, cmd=%d\n", hwnd, cmd); | 
 |  | 
 |     wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0; | 
 |  | 
 |     switch(cmd) | 
 |     { | 
 |         case SW_HIDE: | 
 |             if (!wasVisible) goto END; | 
 | 	    swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | | 
 | 		        SWP_NOACTIVATE | SWP_NOZORDER; | 
 | 	    break; | 
 |  | 
 | 	case SW_SHOWMINNOACTIVE: | 
 |             swp |= SWP_NOACTIVATE | SWP_NOZORDER; | 
 |             /* fall through */ | 
 | 	case SW_SHOWMINIMIZED: | 
 |         case SW_FORCEMINIMIZE: /* FIXME: Does not work if thread is hung. */ | 
 |             swp |= SWP_SHOWWINDOW; | 
 |             /* fall through */ | 
 | 	case SW_MINIMIZE: | 
 |             swp |= SWP_FRAMECHANGED; | 
 |             if( !(wndPtr->dwStyle & WS_MINIMIZE) ) | 
 | 		 swp |= WINPOS_MinMaximize( hwnd, SW_MINIMIZE, &newPos ); | 
 |             else swp |= SWP_NOSIZE | SWP_NOMOVE; | 
 | 	    break; | 
 |  | 
 | 	case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */ | 
 |             swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED; | 
 |             if( !(wndPtr->dwStyle & WS_MAXIMIZE) ) | 
 | 		 swp |= WINPOS_MinMaximize( hwnd, SW_MAXIMIZE, &newPos ); | 
 |             else swp |= SWP_NOSIZE | SWP_NOMOVE; | 
 |             break; | 
 |  | 
 | 	case SW_SHOWNA: | 
 |             swp |= SWP_NOACTIVATE | SWP_NOZORDER; | 
 |             /* fall through */ | 
 | 	case SW_SHOW: | 
 | 	    swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE; | 
 |  | 
 | 	    /* | 
 | 	     * ShowWindow has a little peculiar behavior that if the | 
 | 	     * window is already the topmost window, it will not | 
 | 	     * activate it. | 
 | 	     */ | 
 | 	    if (GetTopWindow((HWND)0)==hwnd && (wasVisible || GetActiveWindow() == hwnd)) | 
 | 	      swp |= SWP_NOACTIVATE; | 
 |  | 
 | 	    break; | 
 |  | 
 | 	case SW_SHOWNOACTIVATE: | 
 |             swp |= SWP_NOACTIVATE | SWP_NOZORDER; | 
 |             /* fall through */ | 
 | 	case SW_SHOWNORMAL:  /* same as SW_NORMAL: */ | 
 | 	case SW_SHOWDEFAULT: /* FIXME: should have its own handler */ | 
 | 	case SW_RESTORE: | 
 | 	    swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED; | 
 |  | 
 |             if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) ) | 
 | 		 swp |= WINPOS_MinMaximize( hwnd, SW_RESTORE, &newPos ); | 
 |             else swp |= SWP_NOSIZE | SWP_NOMOVE; | 
 | 	    break; | 
 |     } | 
 |  | 
 |     showFlag = (cmd != SW_HIDE); | 
 |     if (showFlag != wasVisible) | 
 |     { | 
 |         SendMessageA( hwnd, WM_SHOWWINDOW, showFlag, 0 ); | 
 |         if (!IsWindow( hwnd )) goto END; | 
 |     } | 
 |  | 
 |     /* We can't activate a child window */ | 
 |     if ((wndPtr->dwStyle & WS_CHILD) && | 
 |         !(wndPtr->dwExStyle & WS_EX_MDICHILD)) | 
 |         swp |= SWP_NOACTIVATE | SWP_NOZORDER; | 
 |  | 
 |     SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top, | 
 |                   newPos.right, newPos.bottom, LOWORD(swp) ); | 
 |     if (cmd == SW_HIDE) | 
 |     { | 
 |         /* FIXME: This will cause the window to be activated irrespective | 
 |          * of whether it is owned by the same thread. Has to be done | 
 |          * asynchronously. | 
 |          */ | 
 |  | 
 |         if (hwnd == GetActiveWindow()) | 
 |             WINPOS_ActivateOtherWindow(hwnd); | 
 |  | 
 |         /* Revert focus to parent */ | 
 |         if (hwnd == GetFocus() || IsChild(hwnd, GetFocus())) | 
 |             SetFocus( GetParent(hwnd) ); | 
 |     } | 
 |     if (!IsWindow( hwnd )) goto END; | 
 |     else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( hwnd, TRUE ); | 
 |  | 
 |     if (wndPtr->flags & WIN_NEED_SIZE) | 
 |     { | 
 |         /* should happen only in CreateWindowEx() */ | 
 | 	int wParam = SIZE_RESTORED; | 
 |  | 
 | 	wndPtr->flags &= ~WIN_NEED_SIZE; | 
 | 	if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED; | 
 | 	else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED; | 
 | 	SendMessageA( hwnd, WM_SIZE, wParam, | 
 | 		     MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left, | 
 | 			    wndPtr->rectClient.bottom-wndPtr->rectClient.top)); | 
 | 	SendMessageA( hwnd, WM_MOVE, 0, | 
 | 		   MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) ); | 
 |     } | 
 |  | 
 | END: | 
 |     WIN_ReleaseWndPtr(wndPtr); | 
 |     return wasVisible; | 
 | } | 
 |  | 
 |  | 
 | /********************************************************************** | 
 |  *		X11DRV_MapNotify | 
 |  */ | 
 | void X11DRV_MapNotify( HWND hwnd, XMapEvent *event ) | 
 | { | 
 |     HWND hwndFocus = GetFocus(); | 
 |     WND *win; | 
 |  | 
 |     if (!(win = WIN_GetPtr( hwnd ))) return; | 
 |  | 
 |     if ((win->dwStyle & WS_VISIBLE) && | 
 |         (win->dwStyle & WS_MINIMIZE) && | 
 |         (win->dwExStyle & WS_EX_MANAGED)) | 
 |     { | 
 |         int x, y; | 
 |         unsigned int width, height, border, depth; | 
 |         Window root, top; | 
 |         RECT rect; | 
 |         LONG style = (win->dwStyle & ~(WS_MINIMIZE|WS_MAXIMIZE)) | WS_VISIBLE; | 
 |  | 
 |         /* FIXME: hack */ | 
 |         wine_tsx11_lock(); | 
 |         XGetGeometry( event->display, get_whole_window(win), &root, &x, &y, &width, &height, | 
 |                         &border, &depth ); | 
 |         XTranslateCoordinates( event->display, get_whole_window(win), root, 0, 0, &x, &y, &top ); | 
 |         wine_tsx11_unlock(); | 
 |         rect.left   = x; | 
 |         rect.top    = y; | 
 |         rect.right  = x + width; | 
 |         rect.bottom = y + height; | 
 |         X11DRV_X_to_window_rect( win, &rect ); | 
 |  | 
 |         DCE_InvalidateDCE( hwnd, &win->rectWindow ); | 
 |  | 
 |         if (win->flags & WIN_RESTORE_MAX) style |= WS_MAXIMIZE; | 
 |         WIN_SetStyle( hwnd, style ); | 
 |         WIN_ReleasePtr( win ); | 
 |  | 
 |         SendMessageA( hwnd, WM_SHOWWINDOW, SW_RESTORE, 0 ); | 
 |         SetWindowPos( hwnd, 0, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, | 
 |                       SWP_NOZORDER | SWP_WINE_NOHOSTMOVE ); | 
 |     } | 
 |     else WIN_ReleasePtr( win ); | 
 |     if (hwndFocus && IsChild( hwnd, hwndFocus )) X11DRV_SetFocus(hwndFocus);  /* FIXME */ | 
 | } | 
 |  | 
 |  | 
 | /********************************************************************** | 
 |  *              X11DRV_UnmapNotify | 
 |  */ | 
 | void X11DRV_UnmapNotify( HWND hwnd, XUnmapEvent *event ) | 
 | { | 
 |     WND *win; | 
 |  | 
 |     if (!(win = WIN_GetPtr( hwnd ))) return; | 
 |  | 
 |     if ((win->dwStyle & WS_VISIBLE) && (win->dwExStyle & WS_EX_MANAGED)) | 
 |     { | 
 |         if (win->dwStyle & WS_MAXIMIZE) | 
 |             win->flags |= WIN_RESTORE_MAX; | 
 |         else | 
 |             win->flags &= ~WIN_RESTORE_MAX; | 
 |  | 
 |         WIN_SetStyle( hwnd, (win->dwStyle & ~WS_MAXIMIZE) | WS_MINIMIZE ); | 
 |         WIN_ReleasePtr( win ); | 
 |  | 
 |         EndMenu(); | 
 |         SendMessageA( hwnd, WM_SHOWWINDOW, SW_MINIMIZE, 0 ); | 
 |         SetWindowPos( hwnd, 0, 0, 0, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), | 
 |                       SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_WINE_NOHOSTMOVE ); | 
 |     } | 
 |     else WIN_ReleasePtr( win ); | 
 | } | 
 |  | 
 |  | 
 | /*********************************************************************** | 
 |  *           query_zorder | 
 |  * | 
 |  * Synchronize internal z-order with the window manager's. | 
 |  */ | 
 | static Window __get_common_ancestor( Display *display, Window A, Window B, | 
 |                                      Window** children, unsigned* total ) | 
 | { | 
 |     /* find the real root window */ | 
 |  | 
 |     Window      root, *childrenB; | 
 |     unsigned    totalB; | 
 |  | 
 |     while( A != B && A && B ) | 
 |     { | 
 |       TSXQueryTree( display, A, &root, &A, children, total ); | 
 |       TSXQueryTree( display, B, &root, &B, &childrenB, &totalB ); | 
 |       if( childrenB ) TSXFree( childrenB ); | 
 |       if( *children ) TSXFree( *children ), *children = NULL; | 
 |     } | 
 |  | 
 |     if( A && B ) | 
 |     { | 
 |         TSXQueryTree( display, A, &root, &B, children, total ); | 
 |         return A; | 
 |     } | 
 |     return 0 ; | 
 | } | 
 |  | 
 | static Window __get_top_decoration( Display *display, Window w, Window ancestor ) | 
 | { | 
 |     Window*     children, root, prev = w, parent = w; | 
 |     unsigned    total; | 
 |  | 
 |     do | 
 |     { | 
 |         w = parent; | 
 |         TSXQueryTree( display, w, &root, &parent, &children, &total ); | 
 |         if( children ) TSXFree( children ); | 
 |     } while( parent && parent != ancestor ); | 
 |     TRACE("\t%08x -> %08x\n", (unsigned)prev, (unsigned)w ); | 
 |     return ( parent ) ? w : 0 ; | 
 | } | 
 |  | 
 | static unsigned __td_lookup( Window w, Window* list, unsigned max ) | 
 | { | 
 |     unsigned    i; | 
 |     for( i = max; i > 0; i-- ) if( list[i - 1] == w ) break; | 
 |     return i; | 
 | } | 
 |  | 
 | static HWND query_zorder( Display *display, HWND hWndCheck) | 
 | { | 
 |     HWND      hwndInsertAfter = HWND_TOP; | 
 |     Window      w, parent, *children = NULL; | 
 |     unsigned    total, check, pos, best; | 
 |     HWND *list = WIN_ListChildren( GetDesktopWindow() ); | 
 |     HWND hwndA = 0, hwndB = 0; | 
 |     int i; | 
 |  | 
 |     /* find at least two managed windows */ | 
 |     if (!list) return 0; | 
 |     for (i = 0; list[i]; i++) | 
 |     { | 
 |         if (!(GetWindowLongW( list[i], GWL_EXSTYLE ) & WS_EX_MANAGED)) continue; | 
 |         if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) continue; | 
 |         if (!hwndA) hwndA = list[i]; | 
 |         else | 
 |         { | 
 |             hwndB = list[i]; | 
 |             break; | 
 |         } | 
 |     } | 
 |     if (!hwndA || !hwndB) goto done; | 
 |  | 
 |     parent = __get_common_ancestor( display, X11DRV_get_whole_window(hwndA), | 
 |                                     X11DRV_get_whole_window(hwndB), &children, &total ); | 
 |     if( parent && children ) | 
 |     { | 
 |         /* w is the ancestor if hWndCheck that is a direct descendant of 'parent' */ | 
 |  | 
 |         w = __get_top_decoration( display, X11DRV_get_whole_window(hWndCheck), parent ); | 
 |  | 
 |         if( w != children[total-1] ) /* check if at the top */ | 
 |         { | 
 |             /* X child at index 0 is at the bottom, at index total-1 is at the top */ | 
 |             check = __td_lookup( w, children, total ); | 
 |             best = total; | 
 |  | 
 |             /* go through all windows in Wine z-order... */ | 
 |             for (i = 0; list[i]; i++) | 
 |             { | 
 |                 if (list[i] == hWndCheck) continue; | 
 |                 if (!(GetWindowLongW( list[i], GWL_EXSTYLE ) & WS_EX_MANAGED)) continue; | 
 |                 if (!(w = __get_top_decoration( display, X11DRV_get_whole_window(list[i]), | 
 |                                                 parent ))) continue; | 
 |                 pos = __td_lookup( w, children, total ); | 
 |                 if( pos < best && pos > check ) | 
 |                 { | 
 |                     /* find a nearest Wine window precedes hWndCheck in the real z-order */ | 
 |                     best = pos; | 
 |                     hwndInsertAfter = list[i]; | 
 |                 } | 
 |                 if( best - check == 1 ) break; | 
 |             } | 
 |         } | 
 |     } | 
 |     if( children ) TSXFree( children ); | 
 |  | 
 |  done: | 
 |     HeapFree( GetProcessHeap(), 0, list ); | 
 |     return hwndInsertAfter; | 
 | } | 
 |  | 
 |  | 
 | /*********************************************************************** | 
 |  *		X11DRV_ConfigureNotify | 
 |  */ | 
 | void X11DRV_ConfigureNotify( HWND hwnd, XConfigureEvent *event ) | 
 | { | 
 |     HWND oldInsertAfter; | 
 |     struct x11drv_win_data *data; | 
 |     WND *win; | 
 |     RECT rect; | 
 |     WINDOWPOS winpos; | 
 |     int x = event->x, y = event->y; | 
 |  | 
 |     if (!(win = WIN_GetPtr( hwnd ))) return; | 
 |     data = win->pDriverData; | 
 |  | 
 |     /* Get geometry */ | 
 |  | 
 |     if (!event->send_event)  /* normal event, need to map coordinates to the root */ | 
 |     { | 
 |         Window child; | 
 |         wine_tsx11_lock(); | 
 |         XTranslateCoordinates( event->display, data->whole_window, root_window, | 
 |                                0, 0, &x, &y, &child ); | 
 |         wine_tsx11_unlock(); | 
 |     } | 
 |     rect.left   = x; | 
 |     rect.top    = y; | 
 |     rect.right  = x + event->width; | 
 |     rect.bottom = y + event->height; | 
 |     TRACE( "win %p new X rect %d,%d,%dx%d (event %d,%d,%dx%d)\n", | 
 |            hwnd, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, | 
 |            event->x, event->y, event->width, event->height ); | 
 |     X11DRV_X_to_window_rect( win, &rect ); | 
 |     WIN_ReleasePtr( win ); | 
 |  | 
 |     winpos.hwnd  = hwnd; | 
 |     winpos.x     = rect.left; | 
 |     winpos.y     = rect.top; | 
 |     winpos.cx    = rect.right - rect.left; | 
 |     winpos.cy    = rect.bottom - rect.top; | 
 |     winpos.flags = SWP_NOACTIVATE; | 
 |  | 
 |     /* Get Z-order (FIXME) */ | 
 |  | 
 |     winpos.hwndInsertAfter = query_zorder( event->display, hwnd ); | 
 |  | 
 |     /* needs to find the first Visible Window above the current one */ | 
 |     oldInsertAfter = hwnd; | 
 |     for (;;) | 
 |     { | 
 |         oldInsertAfter = GetWindow( oldInsertAfter, GW_HWNDPREV ); | 
 |         if (!oldInsertAfter) | 
 |         { | 
 |             oldInsertAfter = HWND_TOP; | 
 |             break; | 
 |         } | 
 |         if (GetWindowLongA( oldInsertAfter, GWL_STYLE ) & WS_VISIBLE) break; | 
 |     } | 
 |  | 
 |     /* Compare what has changed */ | 
 |  | 
 |     GetWindowRect( hwnd, &rect ); | 
 |     if (rect.left == winpos.x && rect.top == winpos.y) winpos.flags |= SWP_NOMOVE; | 
 |     else | 
 |         TRACE( "%p moving from (%d,%d) to (%d,%d)\n", | 
 |                hwnd, rect.left, rect.top, winpos.x, winpos.y ); | 
 |  | 
 |     if ((rect.right - rect.left == winpos.cx && rect.bottom - rect.top == winpos.cy) || | 
 |         IsIconic(hwnd) || | 
 |         (IsRectEmpty( &rect ) && winpos.cx == 1 && winpos.cy == 1)) | 
 |         winpos.flags |= SWP_NOSIZE; | 
 |     else | 
 |         TRACE( "%p resizing from (%dx%d) to (%dx%d)\n", | 
 |                hwnd, rect.right - rect.left, rect.bottom - rect.top, | 
 |                winpos.cx, winpos.cy ); | 
 |  | 
 |     if (winpos.hwndInsertAfter == oldInsertAfter) winpos.flags |= SWP_NOZORDER; | 
 |     else | 
 |         TRACE( "%p restacking from after %p to after %p\n", | 
 |                hwnd, oldInsertAfter, winpos.hwndInsertAfter ); | 
 |  | 
 |     /* if nothing changed, don't do anything */ | 
 |     if (winpos.flags == (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE)) return; | 
 |  | 
 |     SetWindowPos( hwnd, winpos.hwndInsertAfter, winpos.x, winpos.y, | 
 |                   winpos.cx, winpos.cy, winpos.flags | SWP_WINE_NOHOSTMOVE ); | 
 | } | 
 |  | 
 |  | 
 | /*********************************************************************** | 
 |  *		SetWindowRgn  (X11DRV.@) | 
 |  * | 
 |  * Assign specified region to window (for non-rectangular windows) | 
 |  */ | 
 | int X11DRV_SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL redraw ) | 
 | { | 
 |     WND *wndPtr; | 
 |  | 
 |     if ((wndPtr = WIN_GetPtr( hwnd )) == WND_OTHER_PROCESS) | 
 |     { | 
 |         if (IsWindow( hwnd )) | 
 |             FIXME( "not supported on other process window %p\n", hwnd ); | 
 |         wndPtr = NULL; | 
 |     } | 
 |     if (!wndPtr) | 
 |     { | 
 |         SetLastError( ERROR_INVALID_WINDOW_HANDLE ); | 
 |         return FALSE; | 
 |     } | 
 |  | 
 |     if (wndPtr->hrgnWnd == hrgn) | 
 |     { | 
 |         WIN_ReleasePtr( wndPtr ); | 
 |         return TRUE; | 
 |     } | 
 |  | 
 |     if (wndPtr->hrgnWnd) | 
 |     { | 
 |         /* delete previous region */ | 
 |         DeleteObject(wndPtr->hrgnWnd); | 
 |         wndPtr->hrgnWnd = 0; | 
 |     } | 
 |     wndPtr->hrgnWnd = hrgn; | 
 |  | 
 | #ifdef HAVE_LIBXSHAPE | 
 |     { | 
 |         Display *display = thread_display(); | 
 |         X11DRV_WND_DATA *data = wndPtr->pDriverData; | 
 |  | 
 |         if (data->whole_window) | 
 |         { | 
 |             if (!hrgn) | 
 |             { | 
 |                 wine_tsx11_lock(); | 
 |                 XShapeCombineMask( display, data->whole_window, | 
 |                                    ShapeBounding, 0, 0, None, ShapeSet ); | 
 |                 wine_tsx11_unlock(); | 
 |             } | 
 |             else | 
 |             { | 
 |                 XRectangle *aXRect; | 
 |                 int x_offset, y_offset; | 
 |                 DWORD size; | 
 |                 DWORD dwBufferSize = GetRegionData(hrgn, 0, NULL); | 
 |                 PRGNDATA pRegionData = HeapAlloc(GetProcessHeap(), 0, dwBufferSize); | 
 |                 if (!pRegionData) | 
 |                 { | 
 |                     WIN_ReleasePtr( wndPtr ); | 
 |                     return TRUE; | 
 |                 } | 
 |                 GetRegionData(hrgn, dwBufferSize, pRegionData); | 
 |                 size = pRegionData->rdh.nCount; | 
 |                 x_offset = wndPtr->rectWindow.left - data->whole_rect.left; | 
 |                 y_offset = wndPtr->rectWindow.top - data->whole_rect.top; | 
 |                 /* convert region's "Windows rectangles" to XRectangles */ | 
 |                 aXRect = HeapAlloc(GetProcessHeap(), 0, size * sizeof(*aXRect) ); | 
 |                 if (aXRect) | 
 |                 { | 
 |                     XRectangle* pCurrRect = aXRect; | 
 |                     RECT *pRect = (RECT*) pRegionData->Buffer; | 
 |                     for (; pRect < ((RECT*) pRegionData->Buffer) + size ; ++pRect, ++pCurrRect) | 
 |                     { | 
 |                         pCurrRect->x      = pRect->left + x_offset; | 
 |                         pCurrRect->y      = pRect->top + y_offset; | 
 |                         pCurrRect->height = pRect->bottom - pRect->top; | 
 |                         pCurrRect->width  = pRect->right  - pRect->left; | 
 |  | 
 |                         TRACE("Rectangle %04d of %04ld data: X=%04d, Y=%04d, Height=%04d, Width=%04d.\n", | 
 |                               pRect - (RECT*) pRegionData->Buffer, | 
 |                               size, | 
 |                               pCurrRect->x, | 
 |                               pCurrRect->y, | 
 |                               pCurrRect->height, | 
 |                               pCurrRect->width); | 
 |                     } | 
 |  | 
 |                     /* shape = non-rectangular windows (X11/extensions) */ | 
 |                     wine_tsx11_lock(); | 
 |                     XShapeCombineRectangles( display, data->whole_window, ShapeBounding, | 
 |                                              0, 0, aXRect, | 
 |                                              pCurrRect - aXRect, ShapeSet, YXBanded ); | 
 |                     wine_tsx11_unlock(); | 
 |                     HeapFree(GetProcessHeap(), 0, aXRect ); | 
 |                 } | 
 |                 HeapFree(GetProcessHeap(), 0, pRegionData); | 
 |             } | 
 |         } | 
 |     } | 
 | #endif  /* HAVE_LIBXSHAPE */ | 
 |  | 
 |     WIN_ReleasePtr( wndPtr ); | 
 |     if (redraw) RedrawWindow( hwnd, NULL, 0, RDW_FRAME | RDW_INVALIDATE | RDW_ERASE ); | 
 |     return TRUE; | 
 | } | 
 |  | 
 |  | 
 | /*********************************************************************** | 
 |  *           draw_moving_frame | 
 |  * | 
 |  * Draw the frame used when moving or resizing window. | 
 |  * | 
 |  * FIXME:  This causes problems in Win95 mode.  (why?) | 
 |  */ | 
 | static void draw_moving_frame( HDC hdc, RECT *rect, BOOL thickframe ) | 
 | { | 
 |     if (thickframe) | 
 |     { | 
 |         const int width = GetSystemMetrics(SM_CXFRAME); | 
 |         const int height = GetSystemMetrics(SM_CYFRAME); | 
 |  | 
 |         HBRUSH hbrush = SelectObject( hdc, GetStockObject( GRAY_BRUSH ) ); | 
 |         PatBlt( hdc, rect->left, rect->top, | 
 |                 rect->right - rect->left - width, height, PATINVERT ); | 
 |         PatBlt( hdc, rect->left, rect->top + height, width, | 
 |                 rect->bottom - rect->top - height, PATINVERT ); | 
 |         PatBlt( hdc, rect->left + width, rect->bottom - 1, | 
 |                 rect->right - rect->left - width, -height, PATINVERT ); | 
 |         PatBlt( hdc, rect->right - 1, rect->top, -width, | 
 |                 rect->bottom - rect->top - height, PATINVERT ); | 
 |         SelectObject( hdc, hbrush ); | 
 |     } | 
 |     else DrawFocusRect( hdc, rect ); | 
 | } | 
 |  | 
 |  | 
 | /*********************************************************************** | 
 |  *           start_size_move | 
 |  * | 
 |  * Initialisation of a move or resize, when initiatied from a menu choice. | 
 |  * Return hit test code for caption or sizing border. | 
 |  */ | 
 | static LONG start_size_move( HWND hwnd, WPARAM wParam, POINT *capturePoint, LONG style ) | 
 | { | 
 |     LONG hittest = 0; | 
 |     POINT pt; | 
 |     MSG msg; | 
 |     RECT rectWindow; | 
 |  | 
 |     GetWindowRect( hwnd, &rectWindow ); | 
 |  | 
 |     if ((wParam & 0xfff0) == SC_MOVE) | 
 |     { | 
 |         /* Move pointer at the center of the caption */ | 
 |         RECT rect; | 
 |         NC_GetInsideRect( hwnd, &rect ); | 
 |         if (style & WS_SYSMENU) | 
 |             rect.left += GetSystemMetrics(SM_CXSIZE) + 1; | 
 |         if (style & WS_MINIMIZEBOX) | 
 |             rect.right -= GetSystemMetrics(SM_CXSIZE) + 1; | 
 |         if (style & WS_MAXIMIZEBOX) | 
 |             rect.right -= GetSystemMetrics(SM_CXSIZE) + 1; | 
 |         pt.x = rectWindow.left + (rect.right - rect.left) / 2; | 
 |         pt.y = rectWindow.top + rect.top + GetSystemMetrics(SM_CYSIZE)/2; | 
 |         hittest = HTCAPTION; | 
 |         *capturePoint = pt; | 
 |     } | 
 |     else  /* SC_SIZE */ | 
 |     { | 
 |         while(!hittest) | 
 |         { | 
 |             GetMessageW( &msg, 0, WM_KEYFIRST, WM_MOUSELAST ); | 
 |             if (CallMsgFilterW( &msg, MSGF_SIZE )) continue; | 
 |  | 
 |             switch(msg.message) | 
 |             { | 
 |             case WM_MOUSEMOVE: | 
 |                 hittest = NC_HandleNCHitTest( hwnd, msg.pt ); | 
 |                 if ((hittest < HTLEFT) || (hittest > HTBOTTOMRIGHT)) | 
 |                     hittest = 0; | 
 |                 break; | 
 |  | 
 |             case WM_LBUTTONUP: | 
 |                 return 0; | 
 |  | 
 |             case WM_KEYDOWN: | 
 |                 switch(msg.wParam) | 
 |                 { | 
 |                 case VK_UP: | 
 |                     hittest = HTTOP; | 
 |                     pt.x =(rectWindow.left+rectWindow.right)/2; | 
 |                     pt.y = rectWindow.top + GetSystemMetrics(SM_CYFRAME) / 2; | 
 |                     break; | 
 |                 case VK_DOWN: | 
 |                     hittest = HTBOTTOM; | 
 |                     pt.x =(rectWindow.left+rectWindow.right)/2; | 
 |                     pt.y = rectWindow.bottom - GetSystemMetrics(SM_CYFRAME) / 2; | 
 |                     break; | 
 |                 case VK_LEFT: | 
 |                     hittest = HTLEFT; | 
 |                     pt.x = rectWindow.left + GetSystemMetrics(SM_CXFRAME) / 2; | 
 |                     pt.y =(rectWindow.top+rectWindow.bottom)/2; | 
 |                     break; | 
 |                 case VK_RIGHT: | 
 |                     hittest = HTRIGHT; | 
 |                     pt.x = rectWindow.right - GetSystemMetrics(SM_CXFRAME) / 2; | 
 |                     pt.y =(rectWindow.top+rectWindow.bottom)/2; | 
 |                     break; | 
 |                 case VK_RETURN: | 
 |                 case VK_ESCAPE: return 0; | 
 |                 } | 
 |             } | 
 |         } | 
 |         *capturePoint = pt; | 
 |     } | 
 |     SetCursorPos( pt.x, pt.y ); | 
 |     NC_HandleSetCursor( hwnd, (WPARAM)hwnd, MAKELONG( hittest, WM_MOUSEMOVE )); | 
 |     return hittest; | 
 | } | 
 |  | 
 |  | 
 | /*********************************************************************** | 
 |  *           set_movesize_capture | 
 |  */ | 
 | static void set_movesize_capture( HWND hwnd ) | 
 | { | 
 |     HWND previous = 0; | 
 |  | 
 |     SERVER_START_REQ( set_capture_window ) | 
 |     { | 
 |         req->handle = hwnd; | 
 |         req->flags  = CAPTURE_MOVESIZE; | 
 |         if (!wine_server_call_err( req )) | 
 |         { | 
 |             previous = reply->previous; | 
 |             hwnd = reply->full_handle; | 
 |         } | 
 |     } | 
 |     SERVER_END_REQ; | 
 |     if (previous && previous != hwnd) | 
 |         SendMessageW( previous, WM_CAPTURECHANGED, 0, (LPARAM)hwnd ); | 
 | } | 
 |  | 
 |  | 
 | /*********************************************************************** | 
 |  *           SysCommandSizeMove   (X11DRV.@) | 
 |  * | 
 |  * Perform SC_MOVE and SC_SIZE commands. | 
 |  */ | 
 | void X11DRV_SysCommandSizeMove( HWND hwnd, WPARAM wParam ) | 
 | { | 
 |     MSG msg; | 
 |     RECT sizingRect, mouseRect, origRect; | 
 |     HDC hdc; | 
 |     HWND parent; | 
 |     LONG hittest = (LONG)(wParam & 0x0f); | 
 |     HCURSOR hDragCursor = 0, hOldCursor = 0; | 
 |     POINT minTrack, maxTrack; | 
 |     POINT capturePoint, pt; | 
 |     LONG style = GetWindowLongA( hwnd, GWL_STYLE ); | 
 |     LONG exstyle = GetWindowLongA( hwnd, GWL_EXSTYLE ); | 
 |     BOOL    thickframe = HAS_THICKFRAME( style, exstyle ); | 
 |     BOOL    iconic = style & WS_MINIMIZE; | 
 |     BOOL    moved = FALSE; | 
 |     DWORD     dwPoint = GetMessagePos (); | 
 |     BOOL DragFullWindows = FALSE; | 
 |     BOOL grab; | 
 |     int iWndsLocks; | 
 |     Display *old_gdi_display = NULL; | 
 |     Display *display = thread_display(); | 
 |  | 
 |     SystemParametersInfoA(SPI_GETDRAGFULLWINDOWS, 0, &DragFullWindows, 0); | 
 |  | 
 |     pt.x = SLOWORD(dwPoint); | 
 |     pt.y = SHIWORD(dwPoint); | 
 |     capturePoint = pt; | 
 |  | 
 |     if (IsZoomed(hwnd) || !IsWindowVisible(hwnd) || (exstyle & WS_EX_MANAGED)) return; | 
 |  | 
 |     if ((wParam & 0xfff0) == SC_MOVE) | 
 |     { | 
 |         if (!hittest) hittest = start_size_move( hwnd, wParam, &capturePoint, style ); | 
 |         if (!hittest) return; | 
 |     } | 
 |     else  /* SC_SIZE */ | 
 |     { | 
 |         if (!thickframe) return; | 
 |         if ( hittest && hittest != HTSYSMENU ) hittest += 2; | 
 |         else | 
 |         { | 
 |             set_movesize_capture( hwnd ); | 
 |             hittest = start_size_move( hwnd, wParam, &capturePoint, style ); | 
 |             if (!hittest) | 
 |             { | 
 |                 set_movesize_capture(0); | 
 |                 return; | 
 |             } | 
 |         } | 
 |     } | 
 |  | 
 |       /* Get min/max info */ | 
 |  | 
 |     WINPOS_GetMinMaxInfo( hwnd, NULL, NULL, &minTrack, &maxTrack ); | 
 |     GetWindowRect( hwnd, &sizingRect ); | 
 |     if (style & WS_CHILD) | 
 |     { | 
 |         parent = GetParent(hwnd); | 
 |         /* make sizing rect relative to parent */ | 
 |         MapWindowPoints( 0, parent, (POINT*)&sizingRect, 2 ); | 
 |         GetClientRect( parent, &mouseRect ); | 
 |     } | 
 |     else | 
 |     { | 
 |         parent = 0; | 
 |         SetRect(&mouseRect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); | 
 |     } | 
 |     origRect = sizingRect; | 
 |  | 
 |     if (ON_LEFT_BORDER(hittest)) | 
 |     { | 
 |         mouseRect.left  = max( mouseRect.left, sizingRect.right-maxTrack.x ); | 
 |         mouseRect.right = min( mouseRect.right, sizingRect.right-minTrack.x ); | 
 |     } | 
 |     else if (ON_RIGHT_BORDER(hittest)) | 
 |     { | 
 |         mouseRect.left  = max( mouseRect.left, sizingRect.left+minTrack.x ); | 
 |         mouseRect.right = min( mouseRect.right, sizingRect.left+maxTrack.x ); | 
 |     } | 
 |     if (ON_TOP_BORDER(hittest)) | 
 |     { | 
 |         mouseRect.top    = max( mouseRect.top, sizingRect.bottom-maxTrack.y ); | 
 |         mouseRect.bottom = min( mouseRect.bottom,sizingRect.bottom-minTrack.y); | 
 |     } | 
 |     else if (ON_BOTTOM_BORDER(hittest)) | 
 |     { | 
 |         mouseRect.top    = max( mouseRect.top, sizingRect.top+minTrack.y ); | 
 |         mouseRect.bottom = min( mouseRect.bottom, sizingRect.top+maxTrack.y ); | 
 |     } | 
 |     if (parent) MapWindowPoints( parent, 0, (LPPOINT)&mouseRect, 2 ); | 
 |  | 
 |     /* Retrieve a default cache DC (without using the window style) */ | 
 |     hdc = GetDCEx( parent, 0, DCX_CACHE ); | 
 |  | 
 |     if( iconic ) /* create a cursor for dragging */ | 
 |     { | 
 |         hDragCursor = (HCURSOR)GetClassLongA( hwnd, GCL_HICON); | 
 |         if( !hDragCursor ) hDragCursor = (HCURSOR)SendMessageA( hwnd, WM_QUERYDRAGICON, 0, 0L); | 
 |         if( !hDragCursor ) iconic = FALSE; | 
 |     } | 
 |  | 
 |     /* repaint the window before moving it around */ | 
 |     RedrawWindow( hwnd, NULL, 0, RDW_UPDATENOW | RDW_ALLCHILDREN ); | 
 |  | 
 |     SendMessageA( hwnd, WM_ENTERSIZEMOVE, 0, 0 ); | 
 |     set_movesize_capture( hwnd ); | 
 |  | 
 |     /* grab the server only when moving top-level windows without desktop */ | 
 |     grab = (!DragFullWindows && !parent && (root_window == DefaultRootWindow(gdi_display))); | 
 |  | 
 |     wine_tsx11_lock(); | 
 |     if (grab) | 
 |     { | 
 |         XSync( gdi_display, False ); | 
 |         XGrabServer( display ); | 
 |         XSync( display, False ); | 
 |         /* switch gdi display to the thread display, since the server is grabbed */ | 
 |         old_gdi_display = gdi_display; | 
 |         gdi_display = display; | 
 |     } | 
 |     XGrabPointer( display, X11DRV_get_whole_window(hwnd), False, | 
 |                   PointerMotionMask | ButtonPressMask | ButtonReleaseMask, | 
 |                   GrabModeAsync, GrabModeAsync, | 
 |                   parent ? X11DRV_get_client_window(parent) : root_window, | 
 |                   None, CurrentTime ); | 
 |     wine_tsx11_unlock(); | 
 |  | 
 |     while(1) | 
 |     { | 
 |         int dx = 0, dy = 0; | 
 |  | 
 |         if (!GetMessageW( &msg, 0, WM_KEYFIRST, WM_MOUSELAST )) break; | 
 |         if (CallMsgFilterW( &msg, MSGF_SIZE )) continue; | 
 |  | 
 |         /* Exit on button-up, Return, or Esc */ | 
 |         if ((msg.message == WM_LBUTTONUP) || | 
 |             ((msg.message == WM_KEYDOWN) && | 
 |              ((msg.wParam == VK_RETURN) || (msg.wParam == VK_ESCAPE)))) break; | 
 |  | 
 |         if ((msg.message != WM_KEYDOWN) && (msg.message != WM_MOUSEMOVE)) | 
 |             continue;  /* We are not interested in other messages */ | 
 |  | 
 |         pt = msg.pt; | 
 |  | 
 |         if (msg.message == WM_KEYDOWN) switch(msg.wParam) | 
 |         { | 
 |         case VK_UP:    pt.y -= 8; break; | 
 |         case VK_DOWN:  pt.y += 8; break; | 
 |         case VK_LEFT:  pt.x -= 8; break; | 
 |         case VK_RIGHT: pt.x += 8; break; | 
 |         } | 
 |  | 
 |         pt.x = max( pt.x, mouseRect.left ); | 
 |         pt.x = min( pt.x, mouseRect.right ); | 
 |         pt.y = max( pt.y, mouseRect.top ); | 
 |         pt.y = min( pt.y, mouseRect.bottom ); | 
 |  | 
 |         dx = pt.x - capturePoint.x; | 
 |         dy = pt.y - capturePoint.y; | 
 |  | 
 |         if (dx || dy) | 
 |         { | 
 |             if( !moved ) | 
 |             { | 
 |                 moved = TRUE; | 
 |  | 
 |                 if( iconic ) /* ok, no system popup tracking */ | 
 |                 { | 
 |                     hOldCursor = SetCursor(hDragCursor); | 
 |                     ShowCursor( TRUE ); | 
 |                     WINPOS_ShowIconTitle( hwnd, FALSE ); | 
 |                 } | 
 |                 else if(!DragFullWindows) | 
 |                     draw_moving_frame( hdc, &sizingRect, thickframe ); | 
 |             } | 
 |  | 
 |             if (msg.message == WM_KEYDOWN) SetCursorPos( pt.x, pt.y ); | 
 |             else | 
 |             { | 
 |                 RECT newRect = sizingRect; | 
 |                 WPARAM wpSizingHit = 0; | 
 |  | 
 |                 if (hittest == HTCAPTION) OffsetRect( &newRect, dx, dy ); | 
 |                 if (ON_LEFT_BORDER(hittest)) newRect.left += dx; | 
 |                 else if (ON_RIGHT_BORDER(hittest)) newRect.right += dx; | 
 |                 if (ON_TOP_BORDER(hittest)) newRect.top += dy; | 
 |                 else if (ON_BOTTOM_BORDER(hittest)) newRect.bottom += dy; | 
 |                 if(!iconic && !DragFullWindows) draw_moving_frame( hdc, &sizingRect, thickframe ); | 
 |                 capturePoint = pt; | 
 |  | 
 |                 /* determine the hit location */ | 
 |                 if (hittest >= HTLEFT && hittest <= HTBOTTOMRIGHT) | 
 |                     wpSizingHit = WMSZ_LEFT + (hittest - HTLEFT); | 
 |                 SendMessageA( hwnd, WM_SIZING, wpSizingHit, (LPARAM)&newRect ); | 
 |  | 
 |                 if (!iconic) | 
 |                 { | 
 |                     if(!DragFullWindows) | 
 |                         draw_moving_frame( hdc, &newRect, thickframe ); | 
 |                     else { | 
 |                         /* To avoid any deadlocks, all the locks on the windows | 
 | 			   structures must be suspended before the SetWindowPos */ | 
 |                         iWndsLocks = WIN_SuspendWndsLock(); | 
 |                         SetWindowPos( hwnd, 0, newRect.left, newRect.top, | 
 |                                       newRect.right - newRect.left, | 
 |                                       newRect.bottom - newRect.top, | 
 |                                       ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 ); | 
 |                         WIN_RestoreWndsLock(iWndsLocks); | 
 |                     } | 
 |                 } | 
 |                 sizingRect = newRect; | 
 |             } | 
 |         } | 
 |     } | 
 |  | 
 |     set_movesize_capture(0); | 
 |     if( iconic ) | 
 |     { | 
 |         if( moved ) /* restore cursors, show icon title later on */ | 
 |         { | 
 |             ShowCursor( FALSE ); | 
 |             SetCursor( hOldCursor ); | 
 |         } | 
 |     } | 
 |     else if (moved && !DragFullWindows) | 
 |         draw_moving_frame( hdc, &sizingRect, thickframe ); | 
 |  | 
 |     ReleaseDC( parent, hdc ); | 
 |  | 
 |     wine_tsx11_lock(); | 
 |     XUngrabPointer( display, CurrentTime ); | 
 |     if (grab) | 
 |     { | 
 |         XSync( display, False ); | 
 |         XUngrabServer( display ); | 
 |         XSync( display, False ); | 
 |         gdi_display = old_gdi_display; | 
 |     } | 
 |     wine_tsx11_unlock(); | 
 |  | 
 |     if (HOOK_CallHooks( WH_CBT, HCBT_MOVESIZE, (WPARAM)hwnd, (LPARAM)&sizingRect, TRUE )) | 
 |         moved = FALSE; | 
 |  | 
 |     SendMessageA( hwnd, WM_EXITSIZEMOVE, 0, 0 ); | 
 |     SendMessageA( hwnd, WM_SETVISIBLE, !IsIconic(hwnd), 0L); | 
 |  | 
 |     /* window moved or resized */ | 
 |     if (moved) | 
 |     { | 
 |         /* To avoid any deadlocks, all the locks on the windows | 
 | 	   structures must be suspended before the SetWindowPos */ | 
 |         iWndsLocks = WIN_SuspendWndsLock(); | 
 |  | 
 |         /* if the moving/resizing isn't canceled call SetWindowPos | 
 |          * with the new position or the new size of the window | 
 |          */ | 
 |         if (!((msg.message == WM_KEYDOWN) && (msg.wParam == VK_ESCAPE)) ) | 
 |         { | 
 |             /* NOTE: SWP_NOACTIVATE prevents document window activation in Word 6 */ | 
 |             if(!DragFullWindows) | 
 |                 SetWindowPos( hwnd, 0, sizingRect.left, sizingRect.top, | 
 |                               sizingRect.right - sizingRect.left, | 
 |                               sizingRect.bottom - sizingRect.top, | 
 |                               ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 ); | 
 |         } | 
 |         else | 
 |         { /* restore previous size/position */ | 
 |             if(DragFullWindows) | 
 |                 SetWindowPos( hwnd, 0, origRect.left, origRect.top, | 
 |                               origRect.right - origRect.left, | 
 |                               origRect.bottom - origRect.top, | 
 |                               ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 ); | 
 |         } | 
 |  | 
 |         WIN_RestoreWndsLock(iWndsLocks); | 
 |     } | 
 |  | 
 |     if (IsIconic(hwnd)) | 
 |     { | 
 |         /* Single click brings up the system menu when iconized */ | 
 |  | 
 |         if( !moved ) | 
 |         { | 
 |             if(style & WS_SYSMENU ) | 
 |                 SendMessageA( hwnd, WM_SYSCOMMAND, | 
 |                               SC_MOUSEMENU + HTSYSMENU, MAKELONG(pt.x,pt.y)); | 
 |         } | 
 |         else WINPOS_ShowIconTitle( hwnd, TRUE ); | 
 |     } | 
 | } | 
 |  | 
 |  | 
 | /*********************************************************************** | 
 |  *		ForceWindowRaise   (X11DRV.@) | 
 |  * | 
 |  * Raise a window on top of the X stacking order, while preserving | 
 |  * the correct Windows Z order. | 
 |  * | 
 |  * FIXME: this should go away. | 
 |  */ | 
 | void X11DRV_ForceWindowRaise( HWND hwnd ) | 
 | { | 
 |     int i = 0; | 
 |     HWND *list; | 
 |     XWindowChanges winChanges; | 
 |     Display *display = thread_display(); | 
 |     WND *wndPtr = WIN_FindWndPtr( hwnd ); | 
 |  | 
 |     if (!wndPtr) return; | 
 |  | 
 |     if ((wndPtr->dwExStyle & WS_EX_MANAGED) || | 
 |         wndPtr->parent != GetDesktopWindow() || | 
 |         IsRectEmpty( &wndPtr->rectWindow ) || | 
 |         !get_whole_window(wndPtr)) | 
 |     { | 
 |         WIN_ReleaseWndPtr( wndPtr ); | 
 |         return; | 
 |     } | 
 |     WIN_ReleaseWndPtr( wndPtr ); | 
 |  | 
 |     /* Raise all windows up to wndPtr according to their Z order. | 
 |      * (it would be easier with sibling-related Below but it doesn't | 
 |      * work very well with SGI mwm for instance) | 
 |      */ | 
 |     winChanges.stack_mode = Above; | 
 |     if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return; | 
 |     while (list[i] && list[i] != hwnd) i++; | 
 |     if (list[i]) | 
 |     { | 
 |         for ( ; i >= 0; i--) | 
 |         { | 
 |             WND *ptr = WIN_FindWndPtr( list[i] ); | 
 |             if (!ptr) continue; | 
 |             if (!IsRectEmpty( &ptr->rectWindow ) && get_whole_window(ptr)) | 
 |                 TSXReconfigureWMWindow( display, get_whole_window(ptr), 0, | 
 |                                         CWStackMode, &winChanges ); | 
 |             WIN_ReleaseWndPtr( ptr ); | 
 |         } | 
 |     } | 
 |     HeapFree( GetProcessHeap(), 0, list ); | 
 | } |