Try to always keep the server window Z-order in sync with the X11 one
using a heuristic based on mouse and expose events.

diff --git a/server/protocol.def b/server/protocol.def
index 9602819..c899ce9 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -1916,6 +1916,13 @@
 #define UPDATE_NOREGION        0x40  /* don't return a region, only the flags */
 
 
+/* Update the z order of a window so that a given rectangle is fully visible */
+@REQ(update_window_zorder)
+    user_handle_t  window;        /* handle to the window */
+    rectangle_t    rect;          /* rectangle that must be visible */
+@END
+
+
 /* Mark parts of a window as needing a redraw */
 @REQ(redraw_window)
     user_handle_t  window;        /* handle to the window */
diff --git a/server/request.h b/server/request.h
index 3902c7b..dc57117 100644
--- a/server/request.h
+++ b/server/request.h
@@ -257,6 +257,7 @@
 DECL_HANDLER(get_window_region);
 DECL_HANDLER(set_window_region);
 DECL_HANDLER(get_update_region);
+DECL_HANDLER(update_window_zorder);
 DECL_HANDLER(redraw_window);
 DECL_HANDLER(set_window_property);
 DECL_HANDLER(remove_window_property);
@@ -446,6 +447,7 @@
     (req_handler)req_get_window_region,
     (req_handler)req_set_window_region,
     (req_handler)req_get_update_region,
+    (req_handler)req_update_window_zorder,
     (req_handler)req_redraw_window,
     (req_handler)req_set_window_property,
     (req_handler)req_remove_window_property,
diff --git a/server/trace.c b/server/trace.c
index 266673f..a07a54c 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -2302,6 +2302,13 @@
     dump_varargs_rectangles( cur_size );
 }
 
+static void dump_update_window_zorder_request( const struct update_window_zorder_request *req )
+{
+    fprintf( stderr, " window=%p,", req->window );
+    fprintf( stderr, " rect=" );
+    dump_rectangle( &req->rect );
+}
+
 static void dump_redraw_window_request( const struct redraw_window_request *req )
 {
     fprintf( stderr, " window=%p,", req->window );
@@ -2839,6 +2846,7 @@
     (dump_func)dump_get_window_region_request,
     (dump_func)dump_set_window_region_request,
     (dump_func)dump_get_update_region_request,
+    (dump_func)dump_update_window_zorder_request,
     (dump_func)dump_redraw_window_request,
     (dump_func)dump_set_window_property_request,
     (dump_func)dump_remove_window_property_request,
@@ -3027,6 +3035,7 @@
     (dump_func)dump_get_update_region_reply,
     (dump_func)0,
     (dump_func)0,
+    (dump_func)0,
     (dump_func)dump_remove_window_property_reply,
     (dump_func)dump_get_window_property_reply,
     (dump_func)dump_get_window_properties_reply,
@@ -3211,6 +3220,7 @@
     "get_window_region",
     "set_window_region",
     "get_update_region",
+    "update_window_zorder",
     "redraw_window",
     "set_window_property",
     "remove_window_property",
diff --git a/server/window.c b/server/window.c
index 219a244..ae46dc9 100644
--- a/server/window.c
+++ b/server/window.c
@@ -645,15 +645,23 @@
 }
 
 
+/* compute the intersection of two rectangles; return 0 if the result is empty */
+static inline int intersect_rect( rectangle_t *dst, const rectangle_t *src1, const rectangle_t *src2 )
+{
+    dst->left   = max( src1->left, src2->left );
+    dst->top    = max( src1->top, src2->top );
+    dst->right  = min( src1->right, src2->right );
+    dst->bottom = min( src1->bottom, src2->bottom );
+    return (dst->left < dst->right && dst->top < dst->bottom);
+}
+
+
 /* set the region to the client rect clipped by the window rect, in parent-relative coordinates */
 static void set_region_client_rect( struct region *region, struct window *win )
 {
     rectangle_t rect;
 
-    rect.left   = max( win->window_rect.left, win->client_rect.left );
-    rect.top    = max( win->window_rect.top, win->client_rect.top );
-    rect.right  = min( win->window_rect.right, win->client_rect.right );
-    rect.bottom = min( win->window_rect.bottom, win->client_rect.bottom );
+    intersect_rect( &rect, &win->window_rect, &win->client_rect );
     set_region_rect( region, &rect );
 }
 
@@ -1667,6 +1675,29 @@
 }
 
 
+/* update the z order of a window so that a given rectangle is fully visible */
+DECL_HANDLER(update_window_zorder)
+{
+    rectangle_t tmp;
+    struct window *ptr, *win = get_window( req->window );
+
+    if (!win || !win->parent || !is_visible( win )) return;  /* nothing to do */
+
+    LIST_FOR_EACH_ENTRY( ptr, &win->parent->children, struct window, entry )
+    {
+        if (ptr == win) break;
+        if (!(ptr->style & WS_VISIBLE)) continue;
+        if (ptr->ex_style & WS_EX_TRANSPARENT) continue;
+        if (!intersect_rect( &tmp, &ptr->visible_rect, &req->rect )) continue;
+        if (ptr->win_region && !rect_in_region( ptr->win_region, &req->rect )) continue;
+        /* found a window obscuring the rectangle, now move win above this one */
+        list_remove( &win->entry );
+        list_add_before( &ptr->entry, &win->entry );
+        break;
+    }
+}
+
+
 /* mark parts of a window as needing a redraw */
 DECL_HANDLER(redraw_window)
 {