From 2f69329a370954188af401f8270c89e626c5b3fd Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Tue, 22 Jan 2008 20:01:21 +0100 Subject: [PATCH] server: Add a separate request to set the window visible rect. --- dlls/winex11.drv/winpos.c | 53 +++++++++++++-------- include/wine/server_protocol.h | 20 +++++++- server/protocol.def | 9 ++++ server/request.h | 2 + server/trace.c | 15 +++++- server/window.c | 86 +++++++++++++++++++++++++++------- 6 files changed, 147 insertions(+), 38 deletions(-) diff --git a/dlls/winex11.drv/winpos.c b/dlls/winex11.drv/winpos.c index ba91e8bc45c..37c36ec0828 100644 --- a/dlls/winex11.drv/winpos.c +++ b/dlls/winex11.drv/winpos.c @@ -241,7 +241,7 @@ BOOL X11DRV_SetWindowPos( HWND hwnd, HWND insert_after, const RECT *rectWindow, { Display *display = thread_display(); struct x11drv_win_data *data; - RECT new_whole_rect, old_client_rect; + RECT new_whole_rect, old_client_rect, visible_rect; WND *win; DWORD old_style, new_style, new_ex_style; BOOL ret, make_managed = FALSE; @@ -262,15 +262,12 @@ BOOL X11DRV_SetWindowPos( HWND hwnd, HWND insert_after, const RECT *rectWindow, } } - new_whole_rect = *rectWindow; - X11DRV_window_to_X_rect( data, &new_whole_rect ); - old_client_rect = data->client_rect; if (!data->whole_window) swp_flags |= SWP_NOCOPYBITS; /* we can't rely on X11 to move the bits */ if (!(win = WIN_GetPtr( hwnd ))) return FALSE; - if (win == WND_OTHER_PROCESS) + if (win == WND_DESKTOP || win == WND_OTHER_PROCESS) { if (IsWindow( hwnd )) ERR( "cannot set rectangles of other process window %p\n", hwnd ); return FALSE; @@ -288,34 +285,52 @@ BOOL X11DRV_SetWindowPos( HWND hwnd, HWND insert_after, const RECT *rectWindow, req->client.top = rectClient->top; req->client.right = rectClient->right; req->client.bottom = rectClient->bottom; - if (memcmp( rectWindow, &new_whole_rect, sizeof(RECT) ) || !IsRectEmpty( &valid_rects[0] )) + if (!IsRectEmpty( &valid_rects[0] )) + wine_server_add_data( req, valid_rects, 2 * sizeof(*valid_rects) ); + if ((ret = !wine_server_call( req ))) { - wine_server_add_data( req, &new_whole_rect, sizeof(new_whole_rect) ); - if (!IsRectEmpty( &valid_rects[0] )) - wine_server_add_data( req, valid_rects, 2 * sizeof(*valid_rects) ); + new_style = reply->new_style; + new_ex_style = reply->new_ex_style; + visible_rect.left = reply->visible.left; + visible_rect.top = reply->visible.top; + visible_rect.right = reply->visible.right; + visible_rect.bottom = reply->visible.bottom; } - ret = !wine_server_call( req ); - new_style = reply->new_style; - new_ex_style = reply->new_ex_style; } SERVER_END_REQ; - if (win == WND_DESKTOP || data->whole_window == DefaultRootWindow(gdi_display)) + if (ret) { - data->whole_rect = data->client_rect = data->window_rect = *rectWindow; - if (win != WND_DESKTOP) + if (data->whole_window == DefaultRootWindow(gdi_display)) { + data->whole_rect = data->client_rect = data->window_rect = *rectWindow; win->rectWindow = *rectWindow; win->rectClient = *rectClient; win->dwStyle = new_style; win->dwExStyle = new_ex_style; WIN_ReleasePtr( win ); + return TRUE; + } + + new_whole_rect = *rectWindow; + X11DRV_window_to_X_rect( data, &new_whole_rect ); + if (memcmp( &visible_rect, &new_whole_rect, sizeof(RECT) )) + { + TRACE( "%p: need to update visible rect %s -> %s\n", hwnd, + wine_dbgstr_rect(&visible_rect), wine_dbgstr_rect(&new_whole_rect) ); + SERVER_START_REQ( set_window_visible_rect ) + { + req->handle = hwnd; + req->flags = swp_flags; + req->visible.left = new_whole_rect.left; + req->visible.top = new_whole_rect.top; + req->visible.right = new_whole_rect.right; + req->visible.bottom = new_whole_rect.bottom; + wine_server_call( req ); + } + SERVER_END_REQ; } - return ret; - } - if (ret) - { /* invalidate DCEs */ if ((((swp_flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) && (new_style & WS_VISIBLE)) || diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index b26ac154e46..a659d82d1d6 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -2965,6 +2965,21 @@ struct set_window_pos_reply struct reply_header __header; unsigned int new_style; unsigned int new_ex_style; + rectangle_t visible; +}; + + + +struct set_window_visible_rect_request +{ + struct request_header __header; + unsigned int flags; + user_handle_t handle; + rectangle_t visible; +}; +struct set_window_visible_rect_reply +{ + struct reply_header __header; }; @@ -4416,6 +4431,7 @@ enum request REQ_get_window_children_from_point, REQ_get_window_tree, REQ_set_window_pos, + REQ_set_window_visible_rect, REQ_get_window_rectangles, REQ_get_window_text, REQ_set_window_text, @@ -4655,6 +4671,7 @@ union generic_request struct get_window_children_from_point_request get_window_children_from_point_request; struct get_window_tree_request get_window_tree_request; struct set_window_pos_request set_window_pos_request; + struct set_window_visible_rect_request set_window_visible_rect_request; struct get_window_rectangles_request get_window_rectangles_request; struct get_window_text_request get_window_text_request; struct set_window_text_request set_window_text_request; @@ -4892,6 +4909,7 @@ union generic_reply struct get_window_children_from_point_reply get_window_children_from_point_reply; struct get_window_tree_reply get_window_tree_reply; struct set_window_pos_reply set_window_pos_reply; + struct set_window_visible_rect_reply set_window_visible_rect_reply; struct get_window_rectangles_reply get_window_rectangles_reply; struct get_window_text_reply get_window_text_reply; struct set_window_text_reply set_window_text_reply; @@ -4976,6 +4994,6 @@ union generic_reply struct add_fd_completion_reply add_fd_completion_reply; }; -#define SERVER_PROTOCOL_VERSION 336 +#define SERVER_PROTOCOL_VERSION 337 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/protocol.def b/server/protocol.def index 1dff790931e..ff8bf52e215 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -2185,6 +2185,15 @@ enum message_type @REPLY unsigned int new_style; /* new window style */ unsigned int new_ex_style; /* new window extended style */ + rectangle_t visible; /* new visible rectangle */ +@END + + +/* Set the visible rectangle of a window */ +@REQ(set_window_visible_rect) + unsigned int flags; /* SWP_* flags */ + user_handle_t handle; /* handle to the window */ + rectangle_t visible; /* visible rectangle */ @END diff --git a/server/request.h b/server/request.h index 3f035db46db..283ad97aea7 100644 --- a/server/request.h +++ b/server/request.h @@ -260,6 +260,7 @@ DECL_HANDLER(get_window_children); DECL_HANDLER(get_window_children_from_point); DECL_HANDLER(get_window_tree); DECL_HANDLER(set_window_pos); +DECL_HANDLER(set_window_visible_rect); DECL_HANDLER(get_window_rectangles); DECL_HANDLER(get_window_text); DECL_HANDLER(set_window_text); @@ -498,6 +499,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] = (req_handler)req_get_window_children_from_point, (req_handler)req_get_window_tree, (req_handler)req_set_window_pos, + (req_handler)req_set_window_visible_rect, (req_handler)req_get_window_rectangles, (req_handler)req_get_window_text, (req_handler)req_set_window_text, diff --git a/server/trace.c b/server/trace.c index e188b3f631c..61d0238d011 100644 --- a/server/trace.c +++ b/server/trace.c @@ -2719,7 +2719,17 @@ static void dump_set_window_pos_request( const struct set_window_pos_request *re static void dump_set_window_pos_reply( const struct set_window_pos_reply *req ) { fprintf( stderr, " new_style=%08x,", req->new_style ); - fprintf( stderr, " new_ex_style=%08x", req->new_ex_style ); + fprintf( stderr, " new_ex_style=%08x,", req->new_ex_style ); + fprintf( stderr, " visible=" ); + dump_rectangle( &req->visible ); +} + +static void dump_set_window_visible_rect_request( const struct set_window_visible_rect_request *req ) +{ + fprintf( stderr, " flags=%08x,", req->flags ); + fprintf( stderr, " handle=%p,", req->handle ); + fprintf( stderr, " visible=" ); + dump_rectangle( &req->visible ); } static void dump_get_window_rectangles_request( const struct get_window_rectangles_request *req ) @@ -3921,6 +3931,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_get_window_children_from_point_request, (dump_func)dump_get_window_tree_request, (dump_func)dump_set_window_pos_request, + (dump_func)dump_set_window_visible_rect_request, (dump_func)dump_get_window_rectangles_request, (dump_func)dump_get_window_text_request, (dump_func)dump_set_window_text_request, @@ -4156,6 +4167,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_get_window_children_from_point_reply, (dump_func)dump_get_window_tree_reply, (dump_func)dump_set_window_pos_reply, + (dump_func)0, (dump_func)dump_get_window_rectangles_reply, (dump_func)dump_get_window_text_reply, (dump_func)0, @@ -4391,6 +4403,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = { "get_window_children_from_point", "get_window_tree", "set_window_pos", + "set_window_visible_rect", "get_window_rectangles", "get_window_text", "set_window_text", diff --git a/server/window.c b/server/window.c index 201f804e90d..6c1b816dfb9 100644 --- a/server/window.c +++ b/server/window.c @@ -1409,12 +1409,10 @@ static struct region *expose_window( struct window *win, const rectangle_t *old_ /* set the window and client rectangles, updating the update region if necessary */ 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 *visible_rect, - const rectangle_t *valid_rects ) + const rectangle_t *client_rect, const rectangle_t *valid_rects ) { struct region *old_vis_rgn = NULL, *exposed_rgn = NULL; const rectangle_t old_window_rect = win->window_rect; - const rectangle_t old_visible_rect = win->visible_rect; const rectangle_t old_client_rect = win->client_rect; int client_changed, frame_changed; int visible = (win->style & WS_VISIBLE) || (swp_flags & SWP_SHOWWINDOW); @@ -1426,12 +1424,26 @@ static void set_window_pos( struct window *win, struct window *previous, /* set the new window info before invalidating anything */ win->window_rect = *window_rect; - win->visible_rect = *visible_rect; win->client_rect = *client_rect; if (!(swp_flags & SWP_NOZORDER) && win->parent) link_window( win, previous ); if (swp_flags & SWP_SHOWWINDOW) win->style |= WS_VISIBLE; else if (swp_flags & SWP_HIDEWINDOW) win->style &= ~WS_VISIBLE; + /* assume the visible rect stays at the same offset from the window rect */ + win->visible_rect.left += window_rect->left - old_window_rect.left; + win->visible_rect.top += window_rect->top - old_window_rect.top; + win->visible_rect.right += window_rect->right - old_window_rect.right; + win->visible_rect.bottom += window_rect->bottom - old_window_rect.bottom; + /* but don't make it smaller than the client rect */ + if (win->visible_rect.left > client_rect->left) + win->visible_rect.left = max( window_rect->left, client_rect->left ); + if (win->visible_rect.top > client_rect->top) + win->visible_rect.top = max( window_rect->top, client_rect->top ); + if (win->visible_rect.right < client_rect->right) + win->visible_rect.right = min( window_rect->right, client_rect->right ); + if (win->visible_rect.bottom < client_rect->bottom) + win->visible_rect.bottom = min( window_rect->bottom, client_rect->bottom ); + /* if the window is not visible, everything is easy */ if (!visible) return; @@ -1474,8 +1486,7 @@ static void set_window_pos( struct window *win, struct window *previous, if (swp_flags & SWP_NOCOPYBITS) { frame_changed = ((swp_flags & SWP_FRAMECHANGED) || - memcmp( window_rect, &old_window_rect, sizeof(old_window_rect) ) || - memcmp( visible_rect, &old_visible_rect, sizeof(old_visible_rect) )); + memcmp( window_rect, &old_window_rect, sizeof(old_window_rect) )); client_changed = memcmp( client_rect, &old_client_rect, sizeof(old_client_rect) ); } else @@ -1485,11 +1496,7 @@ static void set_window_pos( struct window *win, struct window *previous, int y_offset = window_rect->top - old_window_rect.top; frame_changed = ((swp_flags & SWP_FRAMECHANGED) || window_rect->right - old_window_rect.right != x_offset || - window_rect->bottom - old_window_rect.bottom != y_offset || - visible_rect->left - old_visible_rect.left != x_offset || - visible_rect->right - old_visible_rect.right != x_offset || - visible_rect->top - old_visible_rect.top != y_offset || - visible_rect->bottom - old_visible_rect.bottom != y_offset); + window_rect->bottom - old_window_rect.bottom != y_offset); client_changed = (client_rect->left - old_client_rect.left != x_offset || client_rect->right - old_client_rect.right != x_offset || client_rect->top - old_client_rect.top != y_offset || @@ -1533,6 +1540,45 @@ done: clear_error(); /* we ignore out of memory errors once the new rects have been set */ } +/* set the window visible rect */ +static void set_window_visible_rect( struct window *win, const rectangle_t *visible_rect, + unsigned int swp_flags ) +{ + struct region *old_vis_rgn = NULL, *exposed_rgn = NULL; + const rectangle_t old_visible_rect = win->visible_rect; + + if (!memcmp( visible_rect, &old_visible_rect, sizeof(old_visible_rect) )) return; + + /* if the window is not visible, everything is easy */ + if (!is_visible( win ) || (swp_flags & SWP_NOREDRAW)) + { + win->visible_rect = *visible_rect; + return; + } + + if (!(old_vis_rgn = get_visible_region( win, DCX_WINDOW ))) return; + win->visible_rect = *visible_rect; + + /* expose anything revealed by the change */ + + exposed_rgn = expose_window( win, &win->window_rect, old_vis_rgn ); + if (exposed_rgn) + { + /* subtract the client rect from the total window rect */ + set_region_rect( exposed_rgn, &win->window_rect ); + set_region_rect( old_vis_rgn, &win->client_rect ); + if (subtract_region( exposed_rgn, exposed_rgn, old_vis_rgn )) + { + if (!is_desktop_window(win)) + offset_region( exposed_rgn, -win->client_rect.left, -win->client_rect.top ); + redraw_window( win, exposed_rgn, 1, RDW_INVALIDATE | RDW_FRAME | RDW_NOCHILDREN ); + } + free_region( exposed_rgn ); + } + free_region( old_vis_rgn ); + clear_error(); /* we ignore out of memory errors once the new rect has been set */ +} + /* set the window region, updating the update region if necessary */ static void set_window_region( struct window *win, struct region *region, int redraw ) @@ -1850,7 +1896,7 @@ DECL_HANDLER(get_window_tree) /* set the position and Z order of a window */ DECL_HANDLER(set_window_pos) { - const rectangle_t *visible_rect = NULL, *valid_rects = NULL; + const rectangle_t *valid_rects = NULL; struct window *previous = NULL; struct window *win = get_window( req->handle ); unsigned int flags = req->flags; @@ -1894,13 +1940,19 @@ DECL_HANDLER(set_window_pos) return; } - if (get_req_data_size() >= sizeof(rectangle_t)) visible_rect = get_req_data(); - if (get_req_data_size() >= 3 * sizeof(rectangle_t)) valid_rects = visible_rect + 1; - - if (!visible_rect) visible_rect = &req->window; - set_window_pos( win, previous, flags, &req->window, &req->client, visible_rect, valid_rects ); + if (get_req_data_size() >= 2 * sizeof(rectangle_t)) valid_rects = get_req_data(); + set_window_pos( win, previous, flags, &req->window, &req->client, valid_rects ); reply->new_style = win->style; reply->new_ex_style = win->ex_style; + reply->visible = win->visible_rect; +} + + +/* set the visible rectangle of a window */ +DECL_HANDLER(set_window_visible_rect) +{ + struct window *win = get_window( req->handle ); + if (win) set_window_visible_rect( win, &req->visible, req->flags ); }