Compute the top clipping window directly on the server side.

diff --git a/dlls/ttydrv/wnd.c b/dlls/ttydrv/wnd.c
index bc07de1..72b1f9d 100644
--- a/dlls/ttydrv/wnd.c
+++ b/dlls/ttydrv/wnd.c
@@ -41,7 +41,7 @@
 /***********************************************************************
  *		get_server_visible_region
  */
-static HRGN get_server_visible_region( HWND hwnd, HWND top, UINT flags )
+static HRGN get_server_visible_region( HWND hwnd, UINT flags )
 {
     RGNDATA *data;
     NTSTATUS status;
@@ -54,7 +54,6 @@
         SERVER_START_REQ( get_visible_region )
         {
             req->window  = hwnd;
-            req->top_win = top;
             req->flags   = flags;
             wine_server_set_reply( req, data->Buffer, size );
             if (!(status = wine_server_call( req )))
@@ -97,7 +96,6 @@
     SERVER_START_REQ( set_window_pos )
     {
         req->handle        = hwnd;
-        req->top_win       = 0;
         req->previous      = insert_after;
         req->flags         = swp_flags;
         req->window.left   = rectWindow->left;
@@ -238,7 +236,7 @@
         SetHookFlags16( HDC_16(hdc), DCHF_VALIDATEVISRGN ))  /* DC was dirty */
     {
         /* need to recompute the visible region */
-        HRGN visRgn = get_server_visible_region( hwnd, GetDesktopWindow(), flags );
+        HRGN visRgn = get_server_visible_region( hwnd, flags );
 
         if (flags & (DCX_EXCLUDERGN | DCX_INTERSECTRGN))
             CombineRgn( visRgn, visRgn, hrgn, (flags & DCX_INTERSECTRGN) ? RGN_AND : RGN_DIFF );
diff --git a/dlls/x11drv/winpos.c b/dlls/x11drv/winpos.c
index a66bf8c..7643c05 100644
--- a/dlls/x11drv/winpos.c
+++ b/dlls/x11drv/winpos.c
@@ -85,7 +85,7 @@
 /***********************************************************************
  *		get_server_visible_region
  */
-static HRGN get_server_visible_region( HWND hwnd, HWND top, UINT flags )
+static HRGN get_server_visible_region( HWND hwnd, UINT flags )
 {
     RGNDATA *data;
     NTSTATUS status;
@@ -98,7 +98,6 @@
         SERVER_START_REQ( get_visible_region )
         {
             req->window  = hwnd;
-            req->top_win = top;
             req->flags   = flags;
             wine_server_set_reply( req, data->Buffer, size );
             if (!(status = wine_server_call( req )))
@@ -248,7 +247,7 @@
         SetHookFlags16( HDC_16(hdc), DCHF_VALIDATEVISRGN ))  /* DC was dirty */
     {
         /* need to recompute the visible region */
-        HRGN visRgn = get_server_visible_region( hwnd, top, flags );
+        HRGN visRgn = get_server_visible_region( hwnd, flags );
 
         if (flags & (DCX_EXCLUDERGN | DCX_INTERSECTRGN))
             CombineRgn( visRgn, visRgn, hrgn, (flags & DCX_INTERSECTRGN) ? RGN_AND : RGN_DIFF );
@@ -680,7 +679,6 @@
                             const RECT *rectClient, UINT swp_flags, const RECT *valid_rects )
 {
     struct x11drv_win_data *data;
-    HWND top = get_top_clipping_window( hwnd );
     RECT new_whole_rect;
     WND *win;
     DWORD old_style, new_style;
@@ -720,7 +718,6 @@
     SERVER_START_REQ( set_window_pos )
     {
         req->handle        = hwnd;
-        req->top_win       = top;
         req->previous      = insert_after;
         req->flags         = swp_flags & ~SWP_WINE_NOHOSTMOVE;
         req->window.left   = rectWindow->left;
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index 74667f2..5958f71 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -2584,7 +2584,6 @@
 {
     struct request_header __header;
     user_handle_t  handle;
-    user_handle_t  top_win;
     user_handle_t  previous;
     unsigned int   flags;
     rectangle_t    window;
@@ -2658,7 +2657,6 @@
 {
     struct request_header __header;
     user_handle_t  window;
-    user_handle_t  top_win;
     unsigned int   flags;
 };
 struct get_visible_region_reply
@@ -3782,6 +3780,6 @@
     struct duplicate_token_reply duplicate_token_reply;
 };
 
-#define SERVER_PROTOCOL_VERSION 159
+#define SERVER_PROTOCOL_VERSION 160
 
 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/server/protocol.def b/server/protocol.def
index 0158451..b86d460 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -1826,7 +1826,6 @@
 /* Set the position and Z order of a window */
 @REQ(set_window_pos)
     user_handle_t  handle;        /* handle to the window */
-    user_handle_t  top_win;       /* top window to clip against */
     user_handle_t  previous;      /* previous window in Z order */
     unsigned int   flags;         /* SWP_* flags */
     rectangle_t    window;        /* window rectangle */
@@ -1874,7 +1873,6 @@
 /* Get the visible region of a window */
 @REQ(get_visible_region)
     user_handle_t  window;        /* handle to the window */
-    user_handle_t  top_win;       /* top window to clip against */
     unsigned int   flags;         /* DCX flags */
 @REPLY
     size_t         total_size;    /* total size of the resulting region */
diff --git a/server/trace.c b/server/trace.c
index 3b46f25..149e10f 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -2191,7 +2191,6 @@
 static void dump_set_window_pos_request( const struct set_window_pos_request *req )
 {
     fprintf( stderr, " handle=%p,", req->handle );
-    fprintf( stderr, " top_win=%p,", req->top_win );
     fprintf( stderr, " previous=%p,", req->previous );
     fprintf( stderr, " flags=%08x,", req->flags );
     fprintf( stderr, " window=" );
@@ -2256,7 +2255,6 @@
 static void dump_get_visible_region_request( const struct get_visible_region_request *req )
 {
     fprintf( stderr, " window=%p,", req->window );
-    fprintf( stderr, " top_win=%p,", req->top_win );
     fprintf( stderr, " flags=%08x", req->flags );
 }
 
diff --git a/server/window.c b/server/window.c
index 296eda8..cf7951d 100644
--- a/server/window.c
+++ b/server/window.c
@@ -657,12 +657,20 @@
 }
 
 
+/* get the top-level window to clip against for a given window */
+static inline struct window *get_top_clipping_window( struct window *win )
+{
+    while (win->parent && win->parent != top_window) win = win->parent;
+    return win;
+}
+
+
 /* compute the visible region of a window */
-static struct region *get_visible_region( struct window *win, struct window *top,
-                                          unsigned int flags )
+static struct region *get_visible_region( struct window *win, unsigned int flags )
 {
     struct region *tmp, *region;
     int offset_x, offset_y;
+    struct window *top = get_top_clipping_window( win );
 
     if (!(region = create_empty_region())) return NULL;
 
@@ -1028,10 +1036,11 @@
 
 /* expose a region of a window, looking for the top most parent that needs to be exposed */
 /* the region is in window coordinates */
-static void expose_window( struct window *win, struct window *top, struct region *region )
+static void expose_window( struct window *win, struct region *region )
 {
     struct window *parent, *ptr;
     int offset_x, offset_y;
+    struct window *top = get_top_clipping_window( win );
 
     /* find the top most parent that doesn't clip either siblings or children */
     for (parent = ptr = win; ptr != top; ptr = ptr->parent)
@@ -1056,28 +1065,18 @@
 
 
 /* set the window and client rectangles, updating the update region if necessary */
-static void set_window_pos( struct window *win, struct window *top, struct window *previous,
+static void set_window_pos( struct window *win, struct window *previous,
                             unsigned int swp_flags, const rectangle_t *window_rect,
                             const rectangle_t *client_rect, const rectangle_t *valid_rects )
 {
-    struct region *old_vis_rgn, *new_vis_rgn;
+    struct region *old_vis_rgn = NULL, *new_vis_rgn;
     const rectangle_t old_window_rect = win->window_rect;
     const rectangle_t old_client_rect = win->client_rect;
+    int visible = (win->style & WS_VISIBLE) || (swp_flags & SWP_SHOWWINDOW);
 
-    /* if the window is not visible, everything is easy */
+    if (win->parent && !is_visible( win->parent )) visible = 0;
 
-    if ((win->parent && !is_visible( win->parent )) ||
-        (!(win->style & WS_VISIBLE) && !(swp_flags & SWP_SHOWWINDOW)))
-    {
-        win->window_rect = *window_rect;
-        win->client_rect = *client_rect;
-        if (!(swp_flags & SWP_NOZORDER)) link_window( win, win->parent, previous );
-        if (swp_flags & SWP_SHOWWINDOW) win->style |= WS_VISIBLE;
-        else if (swp_flags & SWP_HIDEWINDOW) win->style &= ~WS_VISIBLE;
-        return;
-    }
-
-    if (!(old_vis_rgn = get_visible_region( win, top, DCX_WINDOW ))) return;
+    if (visible && !(old_vis_rgn = get_visible_region( win, DCX_WINDOW ))) return;
 
     /* set the new window info before invalidating anything */
 
@@ -1087,7 +1086,10 @@
     if (swp_flags & SWP_SHOWWINDOW) win->style |= WS_VISIBLE;
     else if (swp_flags & SWP_HIDEWINDOW) win->style &= ~WS_VISIBLE;
 
-    if (!(new_vis_rgn = get_visible_region( win, top, DCX_WINDOW )))
+    /* if the window is not visible, everything is easy */
+    if (!visible) return;
+
+    if (!(new_vis_rgn = get_visible_region( win, DCX_WINDOW )))
     {
         free_region( old_vis_rgn );
         clear_error();  /* ignore error since the window info has been modified already */
@@ -1101,7 +1103,7 @@
         offset_region( old_vis_rgn, old_window_rect.left - window_rect->left,
                        old_window_rect.top - window_rect->top );
         if (xor_region( new_vis_rgn, old_vis_rgn, new_vis_rgn ))
-            expose_window( win, top, new_vis_rgn );
+            expose_window( win, new_vis_rgn );
     }
     free_region( old_vis_rgn );
 
@@ -1426,18 +1428,12 @@
 {
     const rectangle_t *valid_rects = NULL;
     struct window *previous = NULL;
-    struct window *top = top_window;
     struct window *win = get_window( req->handle );
     unsigned int flags = req->flags;
 
     if (!win) return;
     if (!win->parent) flags |= SWP_NOZORDER;  /* no Z order for the desktop */
 
-    if (req->top_win)
-    {
-        if (!(top = get_window( req->top_win ))) return;
-    }
-
     if (!(flags & SWP_NOZORDER))
     {
         if (!req->previous)  /* special case: HWND_TOP */
@@ -1470,7 +1466,7 @@
 
     if (get_req_data_size() >= 2 * sizeof(rectangle_t)) valid_rects = get_req_data();
 
-    set_window_pos( win, top, previous, flags, &req->window, &req->client, valid_rects );
+    set_window_pos( win, previous, flags, &req->window, &req->client, valid_rects );
     reply->new_style = win->style;
 }
 
@@ -1557,12 +1553,10 @@
 {
     struct region *region;
     struct window *win = get_window( req->window );
-    struct window *top = NULL;
 
     if (!win) return;
-    if (req->top_win && !(top = get_window( req->top_win ))) return;
 
-    if ((region = get_visible_region( win, top, req->flags )))
+    if ((region = get_visible_region( win, req->flags )))
     {
         rectangle_t *data = get_region_data_and_free( region, get_reply_max_size(), &reply->total_size );
         if (data) set_reply_data_ptr( data, reply->total_size );