Support XDG activation for applications started from commands #5812
Replies: 8 comments 9 replies
-
|
Maybe this is 1:30am brain talking, but I'm not sure what you're asking for in this discussion... is there something concrete that Ghostty should implement? |
Beta Was this translation helpful? Give feedback.
-
|
Is there a realistic use case for this? I saw the I don't think that solving this via shell integration is the the right way. Ideally, each application would ask the terminal for the token when it needs it (this can be done even if all IO is redirected by opening If I understand the sequencing right, when an application launches it will check for |
Beta Was this translation helpful? Give feedback.
-
|
Additionally, is there any other compositor that actually does the "correct thing" and prevent focus stealing per the spec? From what I can tell none of Mutter, KWin, Sway, etc. do this, and niri only recently — as of 25.01 (!) — introduced this opt-in option. As far as I'm concerned this would only affect a tiny sliver of our userbase (this makes absolutely zero sense on anything except Linux Wayland on very few select compositors) at a cost of an extensive change to our shell integration and Wayland integration logic. If the situation changes and more compositors decide to support this or make this the default behavior, then I think this would be much more justifiable. |
Beta Was this translation helpful? Give feedback.
-
|
I think that we've got an XY problem here. I don't think that we understand what problem this is intended to solve. Is this somehow trying to hack around a limitation in |
Beta Was this translation helpful? Give feedback.
-
|
> If I understand the sequencing right, when an application launches it will
> check for `XDG_ACTIVATION_TOKEN` and if it is set, it activates with it and
> then unsets the value...this gives it focus but does not allow subprocesses
> to steal focus?
After a token is activated it's invalidated, which if a subprocess tries to
use the compositor would deny, so it's mostly good practice. In the proxy
token protocol proposed in the VTE issue it would become a problem, since now
you cannot determine if it was activated by a subprocess (potentially after a
long time has passed) or directly by the terminal, which allows it to steal
focus from the terminal when it shouldn't be able to.
I think I understand what this is trying to fix now, thanks. But...I don't think
this is the right way to do it. Shell integration will only inject at the
beginning of a command. If these tokens have timeouts, no one can be sure if it
will be valid in the pipeline of commands by the time the command spawning a
window execs. Also, a command like `firefox && firefox` would cause one to
activate, and not the other - it seems like the *last* command should be
activated, but this would activate the *first*.
I think a better solution is to design a protocol to get an activation token
from a terminal, OSC would be fine for this. Then write a small program that
obtains a token and spawns a child process to be activated with said token. Then
nothing needs to be aware of what is happening *except* the user who has fine
control over what gets activated. This also let's non-shells which spawn windows
perform activation (the github CLI when authenticating, for example).
|
Beta Was this translation helpful? Give feedback.
-
|
I've actually thought a bit more of this and realized that the whole reason the proposal is so convoluted in the first place is because we are relying on the Given this fact, I think it would be reasonable if we implement a bidirectional protocol where the CLI client could ask for an activation token and we can respond asynchronously. Then the terminal would only have to deal with token requests on an individual basis and do not need to delay executing a program, while the program can go on with its initialization process while waiting for the terminal (and compositor) to respond. |
Beta Was this translation helpful? Give feedback.
-
|
XDG_ACTIVATION is just a terrible design. It needs to be fixed in Wayland, not have poor terminals (and really any other applications that can potentially launch unrelated applications) jumping through unneccesarily complex hoops to make up for it. For example, a simple, robust fix would be for wayland to allow an application to register a token (like a uuid4). Then if any application requests focus with that token the compositor can grant it focus if the application that registered the token currently has focus. Or if you want more control the compositor can first check if the application registering the token has focus, and if it does it can ask it whether to allow focus stealing. |
Beta Was this translation helpful? Give feedback.
-
|
At least the XDG_ACTIVATION_TOKEN should be used when openUrl is called so the browser (or the corresponding app) gets focused when clicking on a link. The code to get the token in gtk4 is not complicated const token: ?[]const u8 = blk: {
const display = gdk.Display.getDefault() orelse break :blk null;
const context = gdk.Display.getAppLaunchContext(display);
const tokenPtr = gio.AppLaunchContext.getStartupNotifyId(context.as(gio.AppLaunchContext), null, null) orelse null;
break :blk std.mem.span(tokenPtr);
}; |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
On wayland, windows are generally not allowed to focus themselves (focus stealing prevention), including when they are first created. Instead, focus can be transferred from the currently focused window to a different window through the xdg-activation protocol, using a token (null terminated string) that is transferred between them. The means of transport is not defined in the protocol but has settled on the
XDG_ACTIVATION_TOKENenvironment variable.In practice, no compositor actually enforces full focus stealing prevention, due to missing client support (relevant mutter blog). The single biggest blocker is terminal support, this VTE issue goes into a lot of detail.
Since it's impossible to know ahead of time if a command will launch an application or not, and the activation tokens needing to be fresh (they'll usually get expired in the matter of seconds, and they optionally take the serial of the event that caused the activation), this has to be done preemptively for all commands (by command I a commandline that might include multiple commands - environment variables work well. If there are multiple applications spawned in one commandline they'll race for focus), which sounds bad but afaik should be cheap. Afaik there's no existing sequence for this so one will need to be created, afaik APC is the most appropriate here.
I've made a hack that calls out to the compositor directly to create the token, and I've been daily driving it with niri's
strict-new-window-focus-policyand it confirms the shell integration can work for fish.The biggest problem is shell supportthat's what I originally because comments of comments on the VTE issue:But I went ahead and actually tested it with my setup with bash and it works! And since ghostty already uses
trap DEBUGin the shell integration it shouldn't be a problem. Here's the complete setup:Still needs testing on zsh and elvish, shell integration already has preexec hooks for them so I'm optimistic they'll work.
Personally, in addition to better focus stealing preventing I'm really interested in this because of the flexibility this gives compositors, in particular implementing xdg activation based window grouping in niri which enables really cool things like viewing
man --htmldirectly "in the terminal", launching mpv instances without ending up with many "usless" terminals in the tiling/scrolling layout, viewing images (can also be done with kitty gfx, but less interactively). It's approaching things like awrit from the complete opposite direction (though I still think have "in terminal single client wayland compositor abusing kitty gfx" in my project ideas list :P)Beta Was this translation helpful? Give feedback.
All reactions