From 6e5bec261c3f7af069b57618d6c82b070dc4579d Mon Sep 17 00:00:00 2001 From: Olivier Fourdan Date: Thu, 23 Jun 2016 15:31:30 +0200 Subject: wayland: Emulate crossing for native window Emitting a LeaveNotify event every time the pointer leaves an X11 window may confuse focus follow mouse mode in window managers such as mutter/gnome-shell. Keep the previously found X window and compare against the new one, and if they match then it means the pointer has left an Xwayland window for a native Wayland surface, only in this case fake the crossing to the root window. Signed-off-by: Olivier Fourdan Reviewed-by: Peter Hutterer Signed-off-by: Peter Hutterer --- hw/xwayland/xwayland-input.c | 15 ++++++++++++++- hw/xwayland/xwayland.c | 3 ++- hw/xwayland/xwayland.h | 1 + 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c index e295c71a4..043379ea3 100644 --- a/hw/xwayland/xwayland-input.c +++ b/hw/xwayland/xwayland-input.c @@ -959,7 +959,7 @@ xwl_xy_to_window(ScreenPtr screen, SpritePtr sprite, int x, int y) } } - if (xwl_seat == NULL || !xwl_seat->focus_window) { + if (xwl_seat == NULL) { sprite->spriteTraceGood = 1; return sprite->spriteTrace[0]; } @@ -969,6 +969,19 @@ xwl_xy_to_window(ScreenPtr screen, SpritePtr sprite, int x, int y) xwl_seat->xwl_screen->XYToWindow = screen->XYToWindow; screen->XYToWindow = xwl_xy_to_window; + /* If the pointer has left the Wayland surface but the DIX still + * finds the pointer within the previous X11 window, it means that + * the pointer has crossed to another native Wayland window, in this + * case, pretend we entered the root window so that a LeaveNotify + * event is emitted. + */ + if (xwl_seat->focus_window == NULL && xwl_seat->last_xwindow == ret) { + sprite->spriteTraceGood = 1; + return sprite->spriteTrace[0]; + } + + xwl_seat->last_xwindow = ret; + return ret; } diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c index a41b619bf..847321e87 100644 --- a/hw/xwayland/xwayland.c +++ b/hw/xwayland/xwayland.c @@ -324,7 +324,8 @@ xwl_unrealize_window(WindowPtr window) xorg_list_for_each_entry(xwl_seat, &xwl_screen->seat_list, link) { if (xwl_seat->focus_window && xwl_seat->focus_window->window == window) xwl_seat->focus_window = NULL; - + if (xwl_seat->last_xwindow == window) + xwl_seat->last_xwindow = NullWindow; xwl_seat_clear_touch(xwl_seat, window); } diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h index 8db8df589..db3dd0b77 100644 --- a/hw/xwayland/xwayland.h +++ b/hw/xwayland/xwayland.h @@ -132,6 +132,7 @@ struct xwl_seat { struct wl_surface *cursor; struct wl_callback *cursor_frame_cb; Bool cursor_needs_update; + WindowPtr last_xwindow; struct xorg_list touches; -- cgit v1.2.3