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>
This commit is contained in:
Vlad Zahorodnii 2024-04-25 19:53:56 +03:00 committed by Marge Bot
parent 4053782443
commit a4ed100c0c
4 changed files with 61 additions and 0 deletions

View File

@ -332,6 +332,32 @@ xwl_cursor_warped_to(DeviceIntPtr device,
xwl_seat_emulate_pointer_warp(xwl_seat, xwl_window, sprite, x, y); 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 * static struct xwl_window *
find_matching_input_output_window(struct xwl_screen *xwl_screen, find_matching_input_output_window(struct xwl_screen *xwl_screen,
WindowPtr window) WindowPtr window)
@ -1125,6 +1151,9 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
xwl_screen->SetWindowPixmap = pScreen->SetWindowPixmap; xwl_screen->SetWindowPixmap = pScreen->SetWindowPixmap;
pScreen->SetWindowPixmap = xwl_window_set_window_pixmap; pScreen->SetWindowPixmap = xwl_window_set_window_pixmap;
xwl_screen->SetShape = pScreen->SetShape;
pScreen->SetShape = xwl_set_shape;
pScreen->CursorWarpedTo = xwl_cursor_warped_to; pScreen->CursorWarpedTo = xwl_cursor_warped_to;
pScreen->CursorConfinedTo = xwl_cursor_confined_to; pScreen->CursorConfinedTo = xwl_cursor_confined_to;

View File

@ -80,6 +80,7 @@ struct xwl_screen {
ChangeWindowAttributesProcPtr ChangeWindowAttributes; ChangeWindowAttributesProcPtr ChangeWindowAttributes;
MoveWindowProcPtr MoveWindow; MoveWindowProcPtr MoveWindow;
SourceValidateProcPtr SourceValidate; SourceValidateProcPtr SourceValidate;
SetShapeProcPtr SetShape;
int (*GrabServer) (ClientPtr client); int (*GrabServer) (ClientPtr client);
int (*UngrabServer) (ClientPtr client); int (*UngrabServer) (ClientPtr client);

View File

@ -1502,6 +1502,8 @@ ensure_surface_for_window(WindowPtr window)
xwl_screen->tearing_control_manager, xwl_window->surface); xwl_screen->tearing_control_manager, xwl_window->surface);
} }
xwl_window_set_input_region(xwl_window, wInputShape(window));
return xwl_window; return xwl_window;
err: err:
@ -1971,6 +1973,34 @@ xwl_window_post_damage(struct xwl_window *xwl_window)
DamageEmpty(window_get_damage(xwl_window->surface_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 Bool
xwl_window_init(void) xwl_window_init(void)
{ {

View File

@ -143,6 +143,7 @@ Bool xwl_destroy_window(WindowPtr window);
void xwl_window_post_damage(struct xwl_window *xwl_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_create_frame_callback(struct xwl_window *xwl_window);
void xwl_window_surface_do_destroy(struct xwl_wl_surface *xwl_wl_surface); 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); Bool xwl_window_init(void);