From a52ebb158ef036f131a2386b0703896933840e94 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Tue, 9 Oct 2012 11:47:50 +0200 Subject: [PATCH] server: Add a request to compute the clipping region of a window surface. --- include/wine/server_protocol.h | 23 +++++++- server/protocol.def | 11 ++++ server/request.h | 10 +++- server/trace.c | 16 ++++++ server/window.c | 99 +++++++++++++++++++++++++++++++++- 5 files changed, 156 insertions(+), 3 deletions(-) diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 5d8ac26ad97..2a181fc851a 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -3325,6 +3325,8 @@ struct set_window_pos_reply struct reply_header __header; unsigned int new_style; unsigned int new_ex_style; + user_handle_t surface_win; + char __pad_20[4]; }; #define SET_WINPOS_PAINT_SURFACE 0x01 #define SET_WINPOS_PIXEL_FORMAT 0x02 @@ -3417,6 +3419,22 @@ struct get_visible_region_reply +struct get_surface_region_request +{ + struct request_header __header; + user_handle_t window; +}; +struct get_surface_region_reply +{ + struct reply_header __header; + rectangle_t visible_rect; + data_size_t total_size; + /* VARARG(region,rectangles); */ + char __pad_28[4]; +}; + + + struct get_window_region_request { struct request_header __header; @@ -5092,6 +5110,7 @@ enum request REQ_set_window_text, REQ_get_windows_offset, REQ_get_visible_region, + REQ_get_surface_region, REQ_get_window_region, REQ_set_window_region, REQ_get_update_region, @@ -5347,6 +5366,7 @@ union generic_request struct set_window_text_request set_window_text_request; struct get_windows_offset_request get_windows_offset_request; struct get_visible_region_request get_visible_region_request; + struct get_surface_region_request get_surface_region_request; struct get_window_region_request get_window_region_request; struct set_window_region_request set_window_region_request; struct get_update_region_request get_update_region_request; @@ -5600,6 +5620,7 @@ union generic_reply struct set_window_text_reply set_window_text_reply; struct get_windows_offset_reply get_windows_offset_reply; struct get_visible_region_reply get_visible_region_reply; + struct get_surface_region_reply get_surface_region_reply; struct get_window_region_reply get_window_region_reply; struct set_window_region_reply set_window_region_reply; struct get_update_region_reply get_update_region_reply; @@ -5692,6 +5713,6 @@ union generic_reply struct set_suspend_context_reply set_suspend_context_reply; }; -#define SERVER_PROTOCOL_VERSION 436 +#define SERVER_PROTOCOL_VERSION 437 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/protocol.def b/server/protocol.def index 6403338b936..886853f3a0c 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -2401,6 +2401,7 @@ enum message_type @REPLY unsigned int new_style; /* new window style */ unsigned int new_ex_style; /* new window extended style */ + user_handle_t surface_win; /* window that needs a surface update */ @END #define SET_WINPOS_PAINT_SURFACE 0x01 /* window has a paintable surface */ #define SET_WINPOS_PIXEL_FORMAT 0x02 /* window has a custom pixel format */ @@ -2462,6 +2463,16 @@ enum coords_relative @END +/* Get the visible surface region of a window */ +@REQ(get_surface_region) + user_handle_t window; /* handle to the window */ +@REPLY + rectangle_t visible_rect; /* window visible rect in screen coords */ + data_size_t total_size; /* total size of the resulting region */ + VARARG(region,rectangles); /* list of rectangles for the region (in screen coords) */ +@END + + /* Get the window region */ @REQ(get_window_region) user_handle_t window; /* handle to the window */ diff --git a/server/request.h b/server/request.h index c36fd1644b9..f566e0d5f6b 100644 --- a/server/request.h +++ b/server/request.h @@ -269,6 +269,7 @@ DECL_HANDLER(get_window_text); DECL_HANDLER(set_window_text); DECL_HANDLER(get_windows_offset); DECL_HANDLER(get_visible_region); +DECL_HANDLER(get_surface_region); DECL_HANDLER(get_window_region); DECL_HANDLER(set_window_region); DECL_HANDLER(get_update_region); @@ -523,6 +524,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] = (req_handler)req_set_window_text, (req_handler)req_get_windows_offset, (req_handler)req_get_visible_region, + (req_handler)req_get_surface_region, (req_handler)req_get_window_region, (req_handler)req_set_window_region, (req_handler)req_get_update_region, @@ -1597,7 +1599,8 @@ C_ASSERT( FIELD_OFFSET(struct set_window_pos_request, client) == 40 ); C_ASSERT( sizeof(struct set_window_pos_request) == 56 ); C_ASSERT( FIELD_OFFSET(struct set_window_pos_reply, new_style) == 8 ); C_ASSERT( FIELD_OFFSET(struct set_window_pos_reply, new_ex_style) == 12 ); -C_ASSERT( sizeof(struct set_window_pos_reply) == 16 ); +C_ASSERT( FIELD_OFFSET(struct set_window_pos_reply, surface_win) == 16 ); +C_ASSERT( sizeof(struct set_window_pos_reply) == 24 ); C_ASSERT( FIELD_OFFSET(struct get_window_rectangles_request, handle) == 12 ); C_ASSERT( FIELD_OFFSET(struct get_window_rectangles_request, relative) == 16 ); C_ASSERT( sizeof(struct get_window_rectangles_request) == 24 ); @@ -1625,6 +1628,11 @@ C_ASSERT( FIELD_OFFSET(struct get_visible_region_reply, top_rect) == 12 ); C_ASSERT( FIELD_OFFSET(struct get_visible_region_reply, win_rect) == 28 ); C_ASSERT( FIELD_OFFSET(struct get_visible_region_reply, total_size) == 44 ); C_ASSERT( sizeof(struct get_visible_region_reply) == 48 ); +C_ASSERT( FIELD_OFFSET(struct get_surface_region_request, window) == 12 ); +C_ASSERT( sizeof(struct get_surface_region_request) == 16 ); +C_ASSERT( FIELD_OFFSET(struct get_surface_region_reply, visible_rect) == 8 ); +C_ASSERT( FIELD_OFFSET(struct get_surface_region_reply, total_size) == 24 ); +C_ASSERT( sizeof(struct get_surface_region_reply) == 32 ); C_ASSERT( FIELD_OFFSET(struct get_window_region_request, window) == 12 ); C_ASSERT( sizeof(struct get_window_region_request) == 16 ); C_ASSERT( FIELD_OFFSET(struct get_window_region_reply, total_size) == 8 ); diff --git a/server/trace.c b/server/trace.c index f781a0049c6..dc5074f52fe 100644 --- a/server/trace.c +++ b/server/trace.c @@ -2828,6 +2828,7 @@ 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, ", surface_win=%08x", req->surface_win ); } static void dump_get_window_rectangles_request( const struct get_window_rectangles_request *req ) @@ -2887,6 +2888,18 @@ static void dump_get_visible_region_reply( const struct get_visible_region_reply dump_varargs_rectangles( ", region=", cur_size ); } +static void dump_get_surface_region_request( const struct get_surface_region_request *req ) +{ + fprintf( stderr, " window=%08x", req->window ); +} + +static void dump_get_surface_region_reply( const struct get_surface_region_reply *req ) +{ + dump_rectangle( " visible_rect=", &req->visible_rect ); + fprintf( stderr, ", total_size=%u", req->total_size ); + dump_varargs_rectangles( ", region=", cur_size ); +} + static void dump_get_window_region_request( const struct get_window_region_request *req ) { fprintf( stderr, " window=%08x", req->window ); @@ -4096,6 +4109,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_set_window_text_request, (dump_func)dump_get_windows_offset_request, (dump_func)dump_get_visible_region_request, + (dump_func)dump_get_surface_region_request, (dump_func)dump_get_window_region_request, (dump_func)dump_set_window_region_request, (dump_func)dump_get_update_region_request, @@ -4347,6 +4361,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { NULL, (dump_func)dump_get_windows_offset_reply, (dump_func)dump_get_visible_region_reply, + (dump_func)dump_get_surface_region_reply, (dump_func)dump_get_window_region_reply, NULL, (dump_func)dump_get_update_region_reply, @@ -4598,6 +4613,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = { "set_window_text", "get_windows_offset", "get_visible_region", + "get_surface_region", "get_window_region", "set_window_region", "get_update_region", diff --git a/server/window.c b/server/window.c index a7ac05cc88d..9943452fbce 100644 --- a/server/window.c +++ b/server/window.c @@ -1018,6 +1018,80 @@ error: } +/* clip all children with a custom pixel format out of the visible region */ +static struct region *clip_pixel_format_children( struct window *parent, struct region *parent_clip, + struct region *region, int offset_x, int offset_y ) +{ + struct window *ptr; + struct region *clip = create_empty_region(); + + if (!clip) return NULL; + + LIST_FOR_EACH_ENTRY_REV( ptr, &parent->children, struct window, entry ) + { + if (!(ptr->style & WS_VISIBLE)) continue; + if (ptr->ex_style & WS_EX_TRANSPARENT) continue; + + /* add the visible rect */ + set_region_rect( clip, &ptr->visible_rect ); + if (ptr->win_region && !intersect_window_region( clip, ptr )) break; + offset_region( clip, offset_x, offset_y ); + if (!intersect_region( clip, clip, parent_clip )) break; + if (!union_region( region, region, clip )) break; + + /* subtract the client rect if it uses a custom pixel format */ + set_region_rect( clip, &ptr->client_rect ); + if (ptr->win_region && !intersect_window_region( clip, ptr )) break; + offset_region( clip, offset_x, offset_y ); + if (!intersect_region( clip, clip, parent_clip )) break; + if ((ptr->paint_flags & PAINT_HAS_PIXEL_FORMAT) && !subtract_region( region, region, clip )) + break; + + if (!clip_pixel_format_children( ptr, clip, region, offset_x + ptr->client_rect.left, + offset_y + ptr->client_rect.top )) + break; + } + free_region( clip ); + return region; +} + + +/* compute the visible surface region of a window, in parent coordinates */ +static struct region *get_surface_region( struct window *win ) +{ + struct region *region, *clip; + int offset_x, offset_y; + + /* create a region relative to the window itself */ + + if (!(region = create_empty_region())) return NULL; + if (!(clip = create_empty_region())) goto error; + set_region_rect( region, &win->visible_rect ); + if (win->win_region && !intersect_window_region( region, win )) goto error; + set_region_rect( clip, &win->client_rect ); + if (win->win_region && !intersect_window_region( clip, win )) goto error; + + /* clip children */ + + if (!is_desktop_window(win)) + { + offset_x = win->client_rect.left; + offset_y = win->client_rect.top; + } + else offset_x = offset_y = 0; + + if (!clip_pixel_format_children( win, clip, region, offset_x, offset_y )) goto error; + + free_region( clip ); + return region; + +error: + if (clip) free_region( clip ); + free_region( region ); + return NULL; +} + + /* get the window class of a window */ struct window_class* get_window_class( user_handle_t window ) { @@ -2107,7 +2181,7 @@ DECL_HANDLER(set_window_pos) { rectangle_t window_rect, client_rect, visible_rect; struct window *previous = NULL; - struct window *win = get_window( req->handle ); + struct window *top, *win = get_window( req->handle ); unsigned int flags = req->swp_flags; if (!win) return; @@ -2180,6 +2254,9 @@ DECL_HANDLER(set_window_pos) reply->new_style = win->style; reply->new_ex_style = win->ex_style; + + top = get_top_clipping_window( win ); + if (is_visible( top ) && (top->paint_flags & PAINT_HAS_SURFACE)) reply->surface_win = top->handle; } @@ -2348,6 +2425,26 @@ DECL_HANDLER(get_visible_region) } +/* get the surface visible region of a window */ +DECL_HANDLER(get_surface_region) +{ + struct region *region; + struct window *win = get_window( req->window ); + + if (!win || !is_visible( win )) return; + + if ((region = get_surface_region( win ))) + { + rectangle_t *data; + if (win->parent) map_win_region_to_screen( win->parent, region ); + data = get_region_data_and_free( region, get_reply_max_size(), &reply->total_size ); + if (data) set_reply_data_ptr( data, reply->total_size ); + } + reply->visible_rect = win->visible_rect; + if (win->parent) client_to_screen_rect( win->parent, &reply->visible_rect ); +} + + /* get the window region */ DECL_HANDLER(get_window_region) {