From 1642fc3a60f543cb2b4b78ae425bc39f14ed55b3 Mon Sep 17 00:00:00 2001 From: Dmitry Timoshkov Date: Wed, 17 May 2017 23:55:55 +0800 Subject: [PATCH] server: Add support for a layered window region. (v3) --- dlls/user32/tests/input.c | 2 -- dlls/winex11.drv/bitblt.c | 45 ++++++++++++++++++++++++++++++++++ include/wine/server_protocol.h | 18 +++++++++++++- server/protocol.def | 7 ++++++ server/request.h | 4 +++ server/trace.c | 9 +++++++ server/window.c | 32 ++++++++++++++++++++++++ 7 files changed, 114 insertions(+), 3 deletions(-) diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c index e87a11642ed7..ac2a340b8832 100644 --- a/dlls/user32/tests/input.c +++ b/dlls/user32/tests/input.c @@ -2882,13 +2882,11 @@ static void test_Input_mouse(void) if (msg.message == WM_LBUTTONDOWN) { - todo_wine ok(msg.hwnd == button_win, "msg.hwnd = %p\n", msg.hwnd); got_button_down = TRUE; } else if (msg.message == WM_LBUTTONUP) { - todo_wine ok(msg.hwnd == button_win, "msg.hwnd = %p\n", msg.hwnd); got_button_up = TRUE; break; diff --git a/dlls/winex11.drv/bitblt.c b/dlls/winex11.drv/bitblt.c index b530ba7ba627..865d4ef45d45 100644 --- a/dlls/winex11.drv/bitblt.c +++ b/dlls/winex11.drv/bitblt.c @@ -48,6 +48,7 @@ #include "winuser.h" #include "x11drv.h" #include "winternl.h" +#include "wine/server.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(bitblt); @@ -1613,6 +1614,48 @@ static inline void add_row( HRGN rgn, RGNDATA *data, int x, int y, int len ) } #endif +static void set_layer_region( struct x11drv_window_surface *surface, HRGN hrgn ) +{ + static const RECT empty_rect; + RGNDATA *data; + DWORD size; + HWND hwnd; + + if (XFindContext( thread_init_display(), surface->window, winContext, (char **)&hwnd )) + return; + + if (hrgn) + { + if (!(size = GetRegionData( hrgn, 0, NULL ))) return; + if (!(data = HeapAlloc( GetProcessHeap(), 0, size ))) return; + if (!GetRegionData( hrgn, size, data )) + { + HeapFree( GetProcessHeap(), 0, data ); + return; + } + SERVER_START_REQ( set_layer_region ) + { + req->window = wine_server_user_handle( hwnd ); + if (data->rdh.nCount) + wine_server_add_data( req, data->Buffer, data->rdh.nCount * sizeof(RECT) ); + else + wine_server_add_data( req, &empty_rect, sizeof(empty_rect) ); + wine_server_call( req ); + } + SERVER_END_REQ; + HeapFree( GetProcessHeap(), 0, data ); + } + else /* clear existing region */ + { + SERVER_START_REQ( set_layer_region ) + { + req->window = wine_server_user_handle( hwnd ); + wine_server_call( req ); + } + SERVER_END_REQ; + } +} + /*********************************************************************** * update_surface_region */ @@ -1631,6 +1674,7 @@ static void update_surface_region( struct x11drv_window_surface *surface ) if (!surface->is_argb && surface->color_key == CLR_INVALID) { XShapeCombineMask( gdi_display, surface->window, ShapeBounding, 0, 0, None, ShapeSet ); + set_layer_region( surface, NULL ); return; } @@ -1741,6 +1785,7 @@ static void update_surface_region( struct x11drv_window_surface *surface ) HeapFree( GetProcessHeap(), 0, data ); } + set_layer_region( surface, rgn ); DeleteObject( rgn ); #endif } diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 5f7136946cf6..5b4cea617cb9 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -3922,6 +3922,19 @@ struct set_window_region_reply +struct set_layer_region_request +{ + struct request_header __header; + user_handle_t window; + /* VARARG(region,rectangles); */ +}; +struct set_layer_region_reply +{ + struct reply_header __header; +}; + + + struct get_update_region_request { struct request_header __header; @@ -6251,6 +6264,7 @@ enum request REQ_get_surface_region, REQ_get_window_region, REQ_set_window_region, + REQ_set_layer_region, REQ_get_update_region, REQ_update_window_zorder, REQ_redraw_window, @@ -6572,6 +6586,7 @@ union generic_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 set_layer_region_request set_layer_region_request; struct get_update_region_request get_update_region_request; struct update_window_zorder_request update_window_zorder_request; struct redraw_window_request redraw_window_request; @@ -6891,6 +6906,7 @@ union generic_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 set_layer_region_reply set_layer_region_reply; struct get_update_region_reply get_update_region_reply; struct update_window_zorder_reply update_window_zorder_reply; struct redraw_window_reply redraw_window_reply; @@ -7028,7 +7044,7 @@ union generic_reply /* ### protocol_version begin ### */ -#define SERVER_PROTOCOL_VERSION 632 +#define SERVER_PROTOCOL_VERSION 633 /* ### protocol_version end ### */ diff --git a/server/protocol.def b/server/protocol.def index 1f69448caef7..b388b2da81a1 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -2817,6 +2817,13 @@ enum coords_relative @END +/* Set the layer region */ +@REQ(set_layer_region) + user_handle_t window; /* handle to the window */ + VARARG(region,rectangles); /* list of rectangles for the region (in window coords) */ +@END + + /* Get the window update region */ @REQ(get_update_region) user_handle_t window; /* handle to the window */ diff --git a/server/request.h b/server/request.h index 66c1855a1f73..85b8610867f6 100644 --- a/server/request.h +++ b/server/request.h @@ -294,6 +294,7 @@ DECL_HANDLER(get_visible_region); DECL_HANDLER(get_surface_region); DECL_HANDLER(get_window_region); DECL_HANDLER(set_window_region); +DECL_HANDLER(set_layer_region); DECL_HANDLER(get_update_region); DECL_HANDLER(update_window_zorder); DECL_HANDLER(redraw_window); @@ -614,6 +615,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] = (req_handler)req_get_surface_region, (req_handler)req_get_window_region, (req_handler)req_set_window_region, + (req_handler)req_set_layer_region, (req_handler)req_get_update_region, (req_handler)req_update_window_zorder, (req_handler)req_redraw_window, @@ -1870,6 +1872,8 @@ C_ASSERT( sizeof(struct get_window_region_reply) == 16 ); C_ASSERT( FIELD_OFFSET(struct set_window_region_request, window) == 12 ); C_ASSERT( FIELD_OFFSET(struct set_window_region_request, redraw) == 16 ); C_ASSERT( sizeof(struct set_window_region_request) == 24 ); +C_ASSERT( FIELD_OFFSET(struct set_layer_region_request, window) == 12 ); +C_ASSERT( sizeof(struct set_layer_region_request) == 16 ); C_ASSERT( FIELD_OFFSET(struct get_update_region_request, window) == 12 ); C_ASSERT( FIELD_OFFSET(struct get_update_region_request, from_child) == 16 ); C_ASSERT( FIELD_OFFSET(struct get_update_region_request, flags) == 20 ); diff --git a/server/trace.c b/server/trace.c index 5359e6183092..384e3a6a6ab2 100644 --- a/server/trace.c +++ b/server/trace.c @@ -3351,6 +3351,12 @@ static void dump_set_window_region_request( const struct set_window_region_reque dump_varargs_rectangles( ", region=", cur_size ); } +static void dump_set_layer_region_request( const struct set_layer_region_request *req ) +{ + fprintf( stderr, " window=%08x", req->window ); + dump_varargs_rectangles( ", region=", cur_size ); +} + static void dump_get_update_region_request( const struct get_update_region_request *req ) { fprintf( stderr, " window=%08x", req->window ); @@ -4957,6 +4963,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_get_surface_region_request, (dump_func)dump_get_window_region_request, (dump_func)dump_set_window_region_request, + (dump_func)dump_set_layer_region_request, (dump_func)dump_get_update_region_request, (dump_func)dump_update_window_zorder_request, (dump_func)dump_redraw_window_request, @@ -5274,6 +5281,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_get_surface_region_reply, (dump_func)dump_get_window_region_reply, NULL, + NULL, (dump_func)dump_get_update_region_reply, NULL, NULL, @@ -5591,6 +5599,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = { "get_surface_region", "get_window_region", "set_window_region", + "set_layer_region", "get_update_region", "update_window_zorder", "redraw_window", diff --git a/server/window.c b/server/window.c index 3a88b7f34fa1..a0ed6bb8f609 100644 --- a/server/window.c +++ b/server/window.c @@ -73,6 +73,7 @@ struct window rectangle_t surface_rect; /* window surface rectangle (relative to parent client area) */ rectangle_t client_rect; /* client rectangle (relative to parent client area) */ struct region *win_region; /* region for shaped windows (relative to window rect) */ + struct region *layer_region; /* region for layered windows (relative to window rect) */ struct region *update_region; /* update region (relative to window rect) */ unsigned int style; /* window style */ unsigned int ex_style; /* window extended style */ @@ -495,6 +496,7 @@ static struct window *create_window( struct window *parent, struct window *owner win->atom = atom; win->last_active = win->handle; win->win_region = NULL; + win->layer_region = NULL; win->update_region = NULL; win->style = 0; win->ex_style = 0; @@ -725,6 +727,9 @@ static int is_point_in_window( struct window *win, int *x, int *y, unsigned int if (win->win_region && !point_in_region( win->win_region, *x - win->window_rect.left, *y - win->window_rect.top )) return 0; /* not in window region */ + if (win->layer_region && + !point_in_region( win->layer_region, *x - win->window_rect.left, *y - win->window_rect.top )) + return 0; /* not in layer mask region */ return 1; } @@ -1870,6 +1875,14 @@ static void set_window_region( struct window *win, struct region *region, int re } +/* set the layer region */ +static void set_layer_region( struct window *win, struct region *region ) +{ + if (win->layer_region) free_region( win->layer_region ); + win->layer_region = region; +} + + /* destroy a window */ void destroy_window( struct window *win ) { @@ -1918,6 +1931,7 @@ void destroy_window( struct window *win ) detach_window_thread( win ); if (win->win_region) free_region( win->win_region ); + if (win->layer_region) free_region( win->layer_region ); if (win->update_region) free_region( win->update_region ); if (win->class) release_class( win->class ); free( win->text ); @@ -2566,6 +2580,24 @@ DECL_HANDLER(set_window_region) } +/* set the layer region */ +DECL_HANDLER(set_layer_region) +{ + struct region *region = NULL; + struct window *win = get_window( req->window ); + + if (!win) return; + + if (get_req_data_size()) /* no data means remove the region completely */ + { + if (!(region = create_region_from_req_data( get_req_data(), get_req_data_size() ))) + return; + if (win->ex_style & WS_EX_LAYOUTRTL) mirror_region( &win->window_rect, region ); + } + set_layer_region( win, region ); +} + + /* get a window update region */ DECL_HANDLER(get_update_region) {