diff --git a/include/xwayland.h b/include/xwayland.h index 40b831c8..8bb475ba 100644 --- a/include/xwayland.h +++ b/include/xwayland.h @@ -46,6 +46,8 @@ void xwayland_unmanaged_create(struct server *server, void xwayland_view_create(struct server *server, struct wlr_xwayland_surface *xsurface, bool mapped); +void xwayland_adjust_stacking_order(struct server *server); + struct wlr_xwayland_surface *xwayland_surface_from_view(struct view *view); void xwayland_server_init(struct server *server, diff --git a/src/workspaces.c b/src/workspaces.c index ae333a4f..c04bc34a 100644 --- a/src/workspaces.c +++ b/src/workspaces.c @@ -7,6 +7,7 @@ #include #include #include +#include "config.h" #include "buffer.h" #include "common/font.h" #include "common/graphic-helpers.h" @@ -16,6 +17,7 @@ #include "labwc.h" #include "view.h" #include "workspaces.h" +#include "xwayland.h" /* Internal helpers */ static size_t @@ -297,6 +299,10 @@ workspaces_switch_to(struct workspace *target, bool update_focus) /* And finally show the OSD */ _osd_show(server); +#if HAVE_XWAYLAND + /* Ensure xwayland internal stacking order corresponds to the current workspace */ + xwayland_adjust_stacking_order(server); +#endif /* * Make sure we are not carrying around a * cursor image from the previous desktop diff --git a/src/xwayland.c b/src/xwayland.c index eee7eb6c..37e9aba6 100644 --- a/src/xwayland.c +++ b/src/xwayland.c @@ -3,6 +3,7 @@ #include #include #include +#include "common/array.h" #include "common/macros.h" #include "common/mem.h" #include "labwc.h" @@ -855,6 +856,46 @@ xwayland_server_init(struct server *server, struct wlr_compositor *compositor) } } +/* + * Until we expose the workspaces to xwayland we need a way to + * ensure that xwayland views on the current workspace are always + * stacked above xwayland views on other workspaces. + * + * If we fail to do so, issues arise in scenarios where we change + * the mouse focus but do not change the (xwayland) stacking order. + * + * Reproducer: + * - open at least two xwayland windows which allow scrolling + * (some X11 terminal with 'man man' for example) + * - switch to another workspace, open another xwayland + * window which allows scrolling and maximize it + * - switch back to the previous workspace with the two windows + * - move the mouse to the xwayland window that does *not* have focus + * - start scrolling + * - all scroll events should end up on the maximized window on the other workspace + */ +void +xwayland_adjust_stacking_order(struct server *server) +{ + struct view **view; + struct wl_array views; + + wl_array_init(&views); + view_array_append(server, &views, LAB_VIEW_CRITERIA_ALWAYS_ON_TOP); + view_array_append(server, &views, LAB_VIEW_CRITERIA_CURRENT_WORKSPACE + | LAB_VIEW_CRITERIA_NO_ALWAYS_ON_TOP); + + /* + * view_array_append() provides top-most windows + * first so we simply reverse the iteration here + */ + wl_array_for_each_reverse(view, &views) { + view_move_to_front(*view); + } + + wl_array_release(&views); +} + void xwayland_server_finish(struct server *server) {