I dug into this one in the Mutter and Sushi sources, and I think I can explain what’s happening — it’s not Sushi touching your Nautilus window directly, it’s the transient-parent link plus the way Mutter propagates workspace changes upwards.
How Sushi attaches to Nautilus
When you hit space, Nautilus exports its Wayland surface handle and passes it to Sushi over D-Bus (ShowFile(uri, windowHandle, ...)). Sushi then calls sushi_window_set_child_of_external(), which does gdk_wayland_toplevel_set_transient_for_exported() — so the preview window is registered as a transient child of your Nautilus window.
Source: src/libsushi/externalwindow.c and src/core/application.js in GNOME/sushi; src/nautilus-previewer.c in GNOME/nautilus.
Why your sticky flag gets clobbered
The relevant part is meta_window_change_workspace() in Mutter’s src/core/window.c:
meta_window_change_workspace_without_transients (window, workspace);
meta_window_foreach_transient (window, change_workspace_foreach, workspace);
meta_window_foreach_ancestor (window, change_workspace_foreach, workspace);
Note the last line — it walks the transient chain upwards to ancestors, not just down to children. And change_workspace_without_transients() starts with:
/* Try to unstick the window if it's stuck. */
if (window->on_all_workspaces_requested)
meta_window_unstick (window);
So when Sushi’s window is moved to a workspace, that change propagates up the transient chain to Nautilus, and Nautilus gets unstick()ed as a side effect.
Why it’s intermittent: the activation path is only taken when Sushi’s window isn’t already on the active workspace. If you’re previewing while the active workspace matches where things already are, nothing moves and the flag survives — matching your “works fine most of the time and then it fails.” The timing of focus/activation on Wayland means it’s not deterministic.
What you can try
-
Test whether the transient link is really the culprit. Launch Sushi standalone on a file without Nautilus involved and watch the flag:
sushi /path/to/some-file.png &
Standalone Sushi has no parent handle, so no transient link. If your Nautilus window’s sticky flag still gets cleared, this analysis is wrong and something else (possibly Deja Window) is responsible.
-
Deja Window is worth ruling in or out. Since it persists window state, it may be re-applying — or fighting over — the workspace assignment when Sushi appears/disappears. Try disabling it for a session. I couldn’t find its source to confirm, so this is a hypothesis, not a finding.
-
The workspaces-only-on-primary angle. With a dual-monitor setup, if org.gnome.mutter workspaces-only-on-primary is true, any window on the non-primary monitor is implicitly on_all_workspaces (should_be_on_all_workspaces() returns TRUE for those). Check:
gsettings get org.gnome.mutter workspaces-only-on-primary
If it’s true, your sticky setting is interacting with a monitor-based override, which would make the flag churn much more likely.
I’m fairly confident in the mechanism, since it’s straight from the Mutter source — but the trigger in your specific setup is the part I can’t verify without your machine. If the standalone-sushi test shows the flag survives, then Sushi’s transient link is exonerated and I’d look at Deja Window next.