diff options
author | Vlad Zahorodnii <vlad.zahorodnii@kde.org> | 2024-04-25 19:53:56 +0300 |
---|---|---|
committer | Marge Bot <emma+marge@anholt.net> | 2024-04-30 12:46:49 +0000 |
commit | a4ed100c0cb8cb35a2e4dd837cd9eea80d2345f4 (patch) | |
tree | 16c5c6a85cb1b2ca6eb69267511e2793fd7332aa /hw | |
parent | 4053782443f99761cf26e1acc31a9712253f4329 (diff) |
xwayland: Set wl_surface input region
Some applications that use client side decorations usually set custom
input shape in order to prevent drop shadows stealing pointer events
from windows below. Currently, the only way to get it is to use some
XFixes APIs.
On the other hand, plenty of wayland compositors use solely the
wl_surface input region to decide what view can receive pointer input,
which results in some pointer input issues around client side drop
shadows because Xwayland doesn't set wl_surface.input_region.
See-also: https://bugs.kde.org/show_bug.cgi?id=448119
Signed-off-by: Vlad Zahorodnii <vlad.zahorodnii@kde.org>
Reviewed-by: Olivier Fourdan <ofourdan@redhat.com>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1510>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/xwayland/xwayland-screen.c | 29 | ||||
-rw-r--r-- | hw/xwayland/xwayland-screen.h | 1 | ||||
-rw-r--r-- | hw/xwayland/xwayland-window.c | 30 | ||||
-rw-r--r-- | hw/xwayland/xwayland-window.h | 1 |
4 files changed, 61 insertions, 0 deletions
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); |