]> git.mdlowis.com Git - proto/labwc.git/commitdiff
cursor: allow re-focusing xwayland-unmanaged surfaces
authorJohn Lindgren <john@jlindgren.net>
Thu, 2 Nov 2023 03:01:19 +0000 (23:01 -0400)
committerJohan Malm <johanmalm@users.noreply.github.com>
Thu, 2 Nov 2023 19:31:10 +0000 (19:31 +0000)
We already allow some xwayland-unmanaged surfaces to take focus on map,
if indicated by wlr_xwayland_or_surface_wants_focus(). But once these
surfaces lose focus, they never regain it again.

Add desktop_focus_view_or_surface() and call it in the appropriate
places to allow these views to regain focus in the usual ways (e.g.
clicking on them or focus-follows-mouse).

include/labwc.h
src/desktop.c
src/input/cursor.c

index 7ac4ad181c1e4e356b54de613656e03f3bdaecc4..5701e9bbc62625cdc6ff262bc3eba256840cccf6 100644 (file)
@@ -382,6 +382,14 @@ void foreign_toplevel_update_outputs(struct view *view);
  * session is locked/input is inhibited; it will simply do nothing.
  */
 void desktop_focus_view(struct view *view, bool raise);
+
+/**
+ * desktop_focus_view_or_surface() - like desktop_focus_view() but can
+ * also focus other (e.g. xwayland-unmanaged) surfaces
+ */
+void desktop_focus_view_or_surface(struct seat *seat, struct view *view,
+       struct wlr_surface *surface, bool raise);
+
 void desktop_arrange_all_views(struct server *server);
 void desktop_focus_output(struct output *output);
 struct view *desktop_topmost_focusable_view(struct server *server);
index ab057fbeac497ec9bdc45e38a68588c5f8983b96..9eb54945b93de86468ec09dae3b396e3319caddf 100644 (file)
 #include "workspaces.h"
 #include "xwayland.h"
 
+#if HAVE_XWAYLAND
+#include <wlr/xwayland.h>
+#endif
+
 void
 desktop_arrange_all_views(struct server *server)
 {
@@ -84,6 +88,25 @@ desktop_focus_view(struct view *view, bool raise)
        }
 }
 
+/* TODO: focus layer-shell surfaces also? */
+void
+desktop_focus_view_or_surface(struct seat *seat, struct view *view,
+               struct wlr_surface *surface, bool raise)
+{
+       assert(view || surface);
+       if (view) {
+               desktop_focus_view(view, raise);
+#if HAVE_XWAYLAND
+       } else if (wlr_surface_is_xwayland_surface(surface)) {
+               struct wlr_xwayland_surface *xsurface =
+                       wlr_xwayland_surface_from_wlr_surface(surface);
+               if (xsurface && wlr_xwayland_or_surface_wants_focus(xsurface)) {
+                       seat_focus_surface(seat, surface);
+               }
+#endif
+       }
+}
+
 static struct wl_list *
 get_prev_item(struct wl_list *item)
 {
index 97de12b4c3d6c299a8fc1fc2baf3fd91d5dc6093..58f55be1e87fb21b64184c918b59cfbce3c18147 100644 (file)
@@ -479,8 +479,9 @@ process_cursor_motion(struct server *server, uint32_t time)
                dnd_icons_move(seat, seat->cursor->x, seat->cursor->y);
        }
 
-       if (ctx.view && rc.focus_follow_mouse) {
-               desktop_focus_view(ctx.view, rc.raise_on_focus);
+       if ((ctx.view || ctx.surface) && rc.focus_follow_mouse) {
+               desktop_focus_view_or_surface(seat, ctx.view, ctx.surface,
+                       rc.raise_on_focus);
        }
 
        struct mousebind *mousebind;
@@ -517,11 +518,12 @@ _cursor_update_focus(struct server *server)
        /* Focus surface under cursor if it isn't already focused */
        struct cursor_context ctx = get_cursor_context(server);
 
-       if (ctx.view && rc.focus_follow_mouse
+       if ((ctx.view || ctx.surface) && rc.focus_follow_mouse
                        && !rc.focus_follow_mouse_requires_movement
                        && !server->osd_state.cycle_view) {
                /* Prevents changing keyboard focus during A-Tab */
-               desktop_focus_view(ctx.view, rc.raise_on_focus);
+               desktop_focus_view_or_surface(&server->seat, ctx.view,
+                       ctx.surface, rc.raise_on_focus);
        }
 
        cursor_update_common(server, &ctx, msec(&now),
@@ -908,13 +910,22 @@ cursor_button_press(struct seat *seat, struct wlr_pointer_button_event *event)
                return;
        }
 
-       /* Handle _press_ on a layer surface */
+       /*
+        * On press, set focus to a non-view surface that wants it.
+        * Action processing does not run for these surfaces and thus
+        * the Focus action (used for normal views) does not work.
+        */
        if (ctx.type == LAB_SSD_LAYER_SURFACE) {
                struct wlr_layer_surface_v1 *layer =
                        wlr_layer_surface_v1_from_wlr_surface(ctx.surface);
                if (layer && layer->current.keyboard_interactive) {
                        seat_set_focus_layer(seat, layer);
                }
+#ifdef HAVE_XWAYLAND
+       } else if (ctx.type == LAB_SSD_UNMANAGED) {
+               desktop_focus_view_or_surface(seat, NULL, ctx.surface,
+                       /*raise*/ false);
+#endif
        }
 
        /*