desktop: only apply raise-on-focus delay to sloppy-focus

The raise_on_focus_delay is meant to dampen z-order churn from
focus-follows-mouse cursor passes. Applying it to every focus
change meant explicit actions (alt-tab cycle finish, Focus action,
xdg/xwayland activation, view map, etc.) also waited for the delay
before raising, which felt laggy.

Route all non-sloppy-focus callers through an immediate raise and
keep the timer-based raise only for desktop_focus_view_or_surface(),
which is the sloppy-focus entry point.
This commit is contained in:
Jos Dehaes 2026-04-18 20:54:28 +02:00 committed by Johan Malm
parent 6237e26a1d
commit e61d58e54d

View file

@ -90,15 +90,8 @@ desktop_cancel_pending_auto_raise(void)
}
static void
schedule_auto_raise(struct view *view)
schedule_delayed_auto_raise(struct view *view)
{
if (rc.raise_on_focus_delay_ms == 0) {
/* Immediate raise — preserves original behavior */
desktop_cancel_pending_auto_raise();
view_move_to_front(view);
return;
}
server.pending_auto_raise_view = view;
if (!server.pending_auto_raise_timer) {
server.pending_auto_raise_timer =
@ -109,8 +102,15 @@ schedule_auto_raise(struct view *view)
rc.raise_on_focus_delay_ms);
}
void
desktop_focus_view(struct view *view, bool raise)
/*
* The raise_on_focus_delay is only meant to dampen z-order churn from
* focus-follows-mouse cursor passes. Explicit focus changes (alt-tab,
* Focus action, xdg/xwayland activation, etc.) should raise immediately.
* allow_delay is therefore only set when the caller is the sloppy-focus
* path in desktop_focus_view_or_surface().
*/
static void
desktop_focus_view_internal(struct view *view, bool raise, bool allow_delay)
{
assert(view);
/*
@ -147,14 +147,17 @@ desktop_focus_view(struct view *view, bool raise)
workspaces_switch_to(view->workspace, /*update_focus*/ false);
}
/*
* A new focus change supersedes any pending auto-raise from a
* previous focus event, regardless of whether we raise now.
*/
desktop_cancel_pending_auto_raise();
if (raise) {
schedule_auto_raise(view);
} else {
/*
* A new focus change without a raise supersedes any
* pending auto-raise from a previous focus event.
*/
desktop_cancel_pending_auto_raise();
if (allow_delay && rc.raise_on_focus_delay_ms > 0) {
schedule_delayed_auto_raise(view);
} else {
view_move_to_front(view);
}
}
/*
@ -168,6 +171,12 @@ desktop_focus_view(struct view *view, bool raise)
show_desktop_reset();
}
void
desktop_focus_view(struct view *view, bool raise)
{
desktop_focus_view_internal(view, raise, /*allow_delay*/ false);
}
/* TODO: focus layer-shell surfaces also? */
void
desktop_focus_view_or_surface(struct seat *seat, struct view *view,
@ -175,7 +184,7 @@ desktop_focus_view_or_surface(struct seat *seat, struct view *view,
{
assert(view || surface);
if (view) {
desktop_focus_view(view, raise);
desktop_focus_view_internal(view, raise, /*allow_delay*/ true);
#if HAVE_XWAYLAND
} else {
struct wlr_xwayland_surface *xsurface =