]> git.mdlowis.com Git - proto/labwc.git/commitdiff
xwayland: handle rare case of focus_in event occurring before map
authorJohn Lindgren <john@jlindgren.net>
Wed, 11 Jun 2025 19:10:10 +0000 (15:10 -0400)
committerJohan Malm <johanmalm@users.noreply.github.com>
Thu, 12 Jun 2025 19:33:25 +0000 (20:33 +0100)
This fixes a timing-dependent issue where the CLion main window was
sometimes not correctly focused at startup.

include/xwayland.h
src/xwayland.c

index c202d37d4a6d610ccf94fb8366865a2f2609f01f..b5bd26230c79960360d8cd82ddba727dd1d80112 100644 (file)
@@ -39,6 +39,7 @@ struct xwayland_unmanaged {
 struct xwayland_view {
        struct view base;
        struct wlr_xwayland_surface *xwayland_surface;
+       bool focused_before_map;
 
        /* Events unique to XWayland views */
        struct wl_listener associate;
index 7a4aed9bbc5d1b8aea168fba96bb7c48a063ac6f..dfc38add642c284414a22e53b6c958d92658f2fd 100644 (file)
@@ -587,6 +587,25 @@ handle_focus_in(struct wl_listener *listener, void *data)
                wl_container_of(listener, xwayland_view, focus_in);
        struct view *view = &xwayland_view->base;
        struct seat *seat = &view->server->seat;
+
+       if (!view->surface) {
+               /*
+                * It is rare but possible for the focus_in event to be
+                * received before the map event. This has been seen
+                * during CLion startup, when focus is initially offered
+                * to the splash screen but accepted later by the main
+                * window instead. (In this case, the focus transfer is
+                * client-initiated but allowed by wlroots because the
+                * same PID owns both windows.)
+                *
+                * Set a flag to record this condition, and update the
+                * seat focus later when the view is actually mapped.
+                */
+               wlr_log(WLR_DEBUG, "focus_in received before map");
+               xwayland_view->focused_before_map = true;
+               return;
+       }
+
        if (view->surface != seat->seat->keyboard_state.focused_surface) {
                seat_focus_surface(seat, view->surface);
        }
@@ -805,6 +824,18 @@ xwayland_view_map(struct view *view)
        wl_signal_add(&xwayland_surface->surface->events.commit, &view->commit);
        view->commit.notify = handle_commit;
 
+       /*
+        * If the view was focused (on the xwayland server side) before
+        * being mapped, update the seat focus now. Note that this only
+        * really matters in the case of Globally Active input windows.
+        * In all other cases, it's redundant since view_impl_map()
+        * results in the view being focused anyway.
+        */
+       if (xwayland_view->focused_before_map) {
+               xwayland_view->focused_before_map = false;
+               seat_focus_surface(&view->server->seat, view->surface);
+       }
+
        view_impl_map(view);
        view->been_mapped = true;