diff --git a/hw/xwayland/xwayland-screen.c b/hw/xwayland/xwayland-screen.c index a8db081eb..9f9cd6bc0 100644 --- a/hw/xwayland/xwayland-screen.c +++ b/hw/xwayland/xwayland-screen.c @@ -332,6 +332,32 @@ xwl_cursor_warped_to(DeviceIntPtr device, xwl_seat_emulate_pointer_warp(xwl_seat, xwl_window, sprite, x, y); } +static void +xwl_set_shape(WindowPtr window, + int kind) +{ + ScreenPtr screen = window->drawable.pScreen; + struct xwl_screen *xwl_screen; + struct xwl_window *xwl_window; + + xwl_screen = xwl_screen_get(screen); + xwl_window = xwl_window_from_window(window); + + screen->SetShape = xwl_screen->SetShape; + (*screen->SetShape) (window, kind); + xwl_screen->SetShape = screen->SetShape; + screen->SetShape = xwl_set_shape; + + if (!xwl_window) + return; + + if (kind == ShapeInput) { + xwl_window_set_input_region(xwl_window, wInputShape(window)); + if (xwl_window->allow_commits) + wl_surface_commit(xwl_window->surface); + } +} + static struct xwl_window * find_matching_input_output_window(struct xwl_screen *xwl_screen, WindowPtr window) @@ -1125,6 +1151,9 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv) xwl_screen->SetWindowPixmap = pScreen->SetWindowPixmap; pScreen->SetWindowPixmap = xwl_window_set_window_pixmap; + xwl_screen->SetShape = pScreen->SetShape; + pScreen->SetShape = xwl_set_shape; + pScreen->CursorWarpedTo = xwl_cursor_warped_to; pScreen->CursorConfinedTo = xwl_cursor_confined_to; diff --git a/hw/xwayland/xwayland-screen.h b/hw/xwayland/xwayland-screen.h index f3949af0a..e05497a66 100644 --- a/hw/xwayland/xwayland-screen.h +++ b/hw/xwayland/xwayland-screen.h @@ -80,6 +80,7 @@ struct xwl_screen { ChangeWindowAttributesProcPtr ChangeWindowAttributes; MoveWindowProcPtr MoveWindow; SourceValidateProcPtr SourceValidate; + SetShapeProcPtr SetShape; int (*GrabServer) (ClientPtr client); int (*UngrabServer) (ClientPtr client); diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c index b111a1e4a..b8a2ddb18 100644 --- a/hw/xwayland/xwayland-window.c +++ b/hw/xwayland/xwayland-window.c @@ -1502,6 +1502,8 @@ ensure_surface_for_window(WindowPtr window) xwl_screen->tearing_control_manager, xwl_window->surface); } + xwl_window_set_input_region(xwl_window, wInputShape(window)); + return xwl_window; err: @@ -1971,6 +1973,34 @@ xwl_window_post_damage(struct xwl_window *xwl_window) DamageEmpty(window_get_damage(xwl_window->surface_window)); } +void +xwl_window_set_input_region(struct xwl_window *xwl_window, + RegionPtr input_shape) +{ + struct wl_region *region; + BoxPtr box; + int i; + + if (!input_shape) { + wl_surface_set_input_region(xwl_window->surface, NULL); + return; + } + + region = wl_compositor_create_region(xwl_window->xwl_screen->compositor); + box = RegionRects(input_shape); + + for (i = 0; i < RegionNumRects(input_shape); ++i, ++box) { + wl_region_add(region, + box->x1, + box->y1, + box->x2 - box->x1, + box->y2 - box->y1); + } + + wl_surface_set_input_region(xwl_window->surface, region); + wl_region_destroy(region); +} + Bool xwl_window_init(void) { diff --git a/hw/xwayland/xwayland-window.h b/hw/xwayland/xwayland-window.h index 836f654a3..f73d05684 100644 --- a/hw/xwayland/xwayland-window.h +++ b/hw/xwayland/xwayland-window.h @@ -143,6 +143,7 @@ Bool xwl_destroy_window(WindowPtr window); void xwl_window_post_damage(struct xwl_window *xwl_window); void xwl_window_create_frame_callback(struct xwl_window *xwl_window); void xwl_window_surface_do_destroy(struct xwl_wl_surface *xwl_wl_surface); +void xwl_window_set_input_region(struct xwl_window *xwl_window, RegionPtr input_shape); Bool xwl_window_init(void);