]> git.mdlowis.com Git - proto/labwc.git/commitdiff
Keep xwayland stacking order in sync when switching workspaces
authorConsolatis <35009135+Consolatis@users.noreply.github.com>
Tue, 21 Nov 2023 02:09:22 +0000 (03:09 +0100)
committerConsolatis <35009135+Consolatis@users.noreply.github.com>
Tue, 21 Nov 2023 21:31:05 +0000 (22:31 +0100)
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:
- If followMouse is enabled, raiseOnFocus must be disabled
- 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

This patch fixes the issue by simply raising all windows from
the current workspace again in their original stacking order
when switching workspaces.

Reported-by: Domo via IRC (thanks!)
include/xwayland.h
src/workspaces.c
src/xwayland.c

index 40b831c8bcb5d1968687908d3edbd12e4baa5226..8bb475ba5a7bf6ac28738eda28e74fdb250b8b33 100644 (file)
@@ -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,
index ae333a4ff9f0cc70ac7c884fc39f164d28aca1f6..c04bc34a513dca8968f8dd14ed2db1dd732f9838 100644 (file)
@@ -7,6 +7,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <strings.h>
+#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
index eee7eb6cc96e3dc3b2b29ea309d084b52b364e2e..37e9aba6e02d756ff87ee2195dc694da3b317b4a 100644 (file)
@@ -3,6 +3,7 @@
 #include <assert.h>
 #include <stdlib.h>
 #include <wlr/xwayland.h>
+#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)
 {