Don't rely on X to expose windows covered by a sibling, do it
manually.

diff --git a/dlls/x11drv/winpos.c b/dlls/x11drv/winpos.c
index e22cb4b..a4a4183 100644
--- a/dlls/x11drv/winpos.c
+++ b/dlls/x11drv/winpos.c
@@ -169,6 +169,206 @@
 
 
 /***********************************************************************
+ *		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 *ptr = win;
+    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, tmp, FALSE ) == NULLREGION) break;
+        }
+        if (!(ptr = ptr->parent)) break;
+        OffsetRgn( tmp, ptr->rectClient.left, ptr->rectClient.top );
+        xoffset += ptr->rectClient.left;
+        yoffset += ptr->rectClient.top;
+    }
+    /* 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( WND *win, RECT *rect, HRGN rgn, int flags )
+{
+    WND *ptr, *top;
+    int xoffset = 0, yoffset = 0;
+
+    /* find the top most parent that doesn't clip children or siblings and
+     * invalidate the area on its parent, including all children */
+    top = NULL;
+    for (ptr = win; ptr && ptr->parent; ptr = ptr->parent)
+    {
+        if (!(ptr->dwStyle & WS_CLIPSIBLINGS)) top = ptr;
+        if (!(ptr->parent->dwStyle & WS_CLIPCHILDREN)) top = ptr;
+    }
+
+    if (top)
+    {
+        if (top->parent && top->parent->hwndSelf != GetDesktopWindow()) top = top->parent;
+        flags &= ~RDW_FRAME;  /* parent will invalidate children frame anyway */
+        flags |= RDW_ALLCHILDREN;
+    }
+    else top = win;
+
+    /* make coords relative to top */
+    for (ptr = win; ptr != top; ptr = ptr->parent)
+    {
+        xoffset += ptr->rectClient.left;
+        yoffset += ptr->rectClient.top;
+    }
+
+    if (rect)
+    {
+        OffsetRect( rect, xoffset, yoffset );
+        RedrawWindow( top->hwndSelf, rect, 0, flags );
+    }
+    else
+    {
+        OffsetRgn( rgn, xoffset, yoffset );
+        RedrawWindow( top->hwndSelf, 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, 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 %x (%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_FindWndPtr(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 );
+    }
+
+    expose_window( win, &rect, 0, flags );
+    WIN_ReleaseWndPtr( win );
+}
+
+
+/***********************************************************************
  *		X11DRV_GetDC (X11DRV.@)
  *
  * Set the drawable, origin and dimensions for the DC associated to
@@ -572,6 +772,7 @@
         {
             /* 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)
         {
@@ -593,6 +794,14 @@
         wine_tsx11_unlock();
     }
 
+    /* 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 );
diff --git a/windows/x11drv/event.c b/windows/x11drv/event.c
index e36506b..c9a8121 100644
--- a/windows/x11drv/event.c
+++ b/windows/x11drv/event.c
@@ -96,13 +96,13 @@
 static void EVENT_MotionNotify( HWND hWnd, XMotionEvent *event );
 static void EVENT_FocusIn( HWND hWnd, XFocusChangeEvent *event );
 static void EVENT_FocusOut( HWND hWnd, XFocusChangeEvent *event );
-static void EVENT_Expose( HWND hWnd, XExposeEvent *event );
 static void EVENT_SelectionRequest( HWND hWnd, XSelectionRequestEvent *event, BOOL bIsMultiple );
 static void EVENT_SelectionClear( HWND hWnd, XSelectionClearEvent *event);
 static void EVENT_PropertyNotify( XPropertyEvent *event );
 static void EVENT_ClientMessage( HWND hWnd, XClientMessageEvent *event );
 static void EVENT_MappingNotify( XMappingEvent *event );
 
+extern void X11DRV_Expose( HWND hwnd, XExposeEvent *event );
 extern void X11DRV_MapNotify( HWND hwnd, XMapEvent *event );
 extern void X11DRV_UnmapNotify( HWND hwnd, XUnmapEvent *event );
 extern void X11DRV_ConfigureNotify( HWND hwnd, XConfigureEvent *event );
@@ -319,7 +319,7 @@
       break;
 
     case Expose:
-      EVENT_Expose( hWnd, &event->xexpose );
+      X11DRV_Expose( hWnd, &event->xexpose );
       break;
 
     case ConfigureNotify:
@@ -388,50 +388,6 @@
 }
 
 
-/***********************************************************************
- *           EVENT_Expose
- */
-static void EVENT_Expose( HWND hwnd, XExposeEvent *event )
-{
-    RECT rect;
-    struct x11drv_win_data *data;
-    int flags = RDW_INVALIDATE | RDW_ERASE;
-    WND *win;
-
-    TRACE( "win %x (%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_FindWndPtr(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 );
-    }
-
-    /* find the top level parent that doesn't clip children and invalidate the area */
-    /* on the parent (which will invalidate all the children too) */
-    while (win->parent && win->parent->hwndSelf != GetDesktopWindow() &&
-           !(win->parent->dwStyle & WS_CLIPCHILDREN))
-    {
-        OffsetRect( &rect, win->rectClient.left, win->rectClient.top );
-        WIN_UpdateWndPtr( &win, win->parent );
-        flags &= ~RDW_FRAME;  /* parent will invalidate children frame anyway */
-        flags |= RDW_ALLCHILDREN;  /* force invalidating all children of siblings */
-    }
-    hwnd = win->hwndSelf;
-    WIN_ReleaseWndPtr(win);
-    RedrawWindow( hwnd, &rect, 0, flags );
-}
-
-
 /* get the coordinates of a mouse event */
 static void get_coords( HWND *hwnd, Window window, int x, int y, POINT *pt )
 {