sway
sway copied to clipboard
firefox does not grab focus when opening urls externally
sway version 1.0
When running firefox in wayland mode (GDK_BACKEND=wayland firefox
), firefox does not grab focus when external links are opened from other applications.
An easy way to reproduce this is:
- open firefox in a terminal:
GDK_BACKEND=wayland firefox
- go to the terminal again and open a url:
GDK_BACKEND=wayland firefox www.google.com
Notice how firefo's window does not grab focus.
This does not happen when running firefox in XWayland mode (i.e. you exclude GDK_BACKEND=wayland
)
I opened a ticket on firefox first thinking it might be a firefox issue - but I was told to open it here instead. Here is the original ticket: https://bugzilla.mozilla.org/show_bug.cgi?id=1551255
Not sure if a debug log is useful in this scenario. Let me know if it is and I'll add one to this ticket.
There is no way for Wayland applications to request focus. This would need a new Wayland protocol. There are a few proposals for this on the mailing list.
I'm facing that issue as well. Probably related, applications would set an urgent flag when requesting focus, and I could jump to them with bindsym $mod+x [urgent=latest] focus
.
One possible workaround is to make external links open in a new browser window
Dupe of https://github.com/swaywm/sway/issues/4830 ?
As a crude workaround, you can use a custom http(s) scheme handler that will open links in your browser and then will focus it. For example:
~/.local/share/applications/http-handler.desktop
[Desktop Entry]
Type=Application
Name=Custom HTTP scheme handler
Exec=/home/user/Scripts/http-handler.sh %U
StartupNotify=false
MimeType=x-scheme-handler/http;x-scheme-handler/https;
~/Scripts/http-handler.sh
#!/bin/sh
swaymsg exec chromium "$@" && swaymsg '[title="- Chromium$"] focus'
Then just set it as default http/https handler:
$ xdg-mime default http-handler.desktop x-scheme-handler/http
$ xdg-mime default http-handler.desktop x-scheme-handler/https
To check run:
$ xdg-mime query default x-scheme-handler/http
http-handler.desktop
$ xdg-mime query default x-scheme-handler/https
http-handler.desktop
For some reason I couldn't put the script in Exec=
, line. Probably some quoting issue, but whatever.
For firefox you'll probably want to replace sway message with [app_id=firefox] focus
. I use title, because chrome's SSB windows have the same app_id, so sometimes they'll get focused if you use `[app_id=chromium]. Firefox doesn't support SSB windows so you probably can just use app_id.
P.S. I haven't used this with multiple browser windows opened much, so can't say if it'll work fine in all situations.
AFAICT think this should be possible with the xdg_activation_v1 protocol which is supported by wlroots & sway.
Recent GTK4 has support for it when using functions like gtk_window_present
.
However, GTK3 which most programs currently use, doesn't have it. I found an old branch but it doesn't have the latest changes. This is my attempt to backport all the changes from GTK4, hopefully I can clean it up and submit it: https://gitlab.gnome.org/GNOME/gtk/-/issues/4335#note_1433023
I also needed to comment the following line from wlroots to get it to focus: https://gitlab.freedesktop.org/wlroots/wlroots/-/blob/dd03d839ab56c3e5d7c607a8d76e58e0b75edb85/types/wlr_xdg_activation_v1.c#L122 , still need to look what the "correct" solution should be.
And set focus_on_window_activation
as desired in the sway config.
With this, I can get most applications (e.g. Firefox, LibreOffice, Sublime Text, etc.) to focus their existing instance when launching them (e.g. from a terminal or xdg-open
).
Can confirm this happens with Brave browser as well.
is there any application thats sets an urgent flag under wayland? Because mpv doesn't take focus either, not anything else I tried so far.
We now have the xdg-activation protocol, which is implemented in wlroots and Sway.
Closing this as a missing feature in the client.
To add a bit more detail on what works and what doesn't:
xdg-activation-v1 is supported by GTK4 ≥4.7.1 (4 months old) and GTK3 ≥3.24.35 (6 days old). Note that most applications still use GTK3.
With wlroots ≥0.16.0 and Sway ≥1.8-rc1, the single-instance mode of some programs (e.g. (GNOME) Drawing, Transmission) works out-of-the-box when launching them with swaymsg exec ...
, this works through the XDG_ACTIVATION_TOKEN
and DESKTOP_STARTUP_ID
environment variables.
This won't work if launching those programs directly without swaymsg exec ...
, also for some reason, it doesn't work at all for some programs such as Sublime Text or Firefox, and also doesn't work with wlroots =0.15.0 and Sway =1.7.
In all those cases you will get a "Rejecting token commit request: surface doesn't have keyboard focus" on the debug logs. You can bypass it to work either by commenting this line in wlroots or this line in GTK.
I believe (but am not 100% sure) that the right fix is to change the call to xdg_activation_token_v1_set_surface
in GTK, since instead of passing in NULL
when we don't have a surface, it is passing the to-be-activated surface instead?
Also, while setting the surface to NULL
is certainly enough to pass the wlroots check now, I'm not sure if GTK can do something else to ensure we get the best chances to get the window activated in the future.
BTW, if you have GTK4 ≥4.7.1, GTK3 ≥3.24.35, wlroots ≥0.15.1 and Sway ≥1.7 but don't want to deal with recompiling anything, you can use the following LD_PRELOAD
hack:
#define _GNU_SOURCE
#include <dlfcn.h>
#include <execinfo.h>
#include <string.h>
#include <wayland-client.h>
struct wl_proxy *wl_proxy_marshal_array_flags(struct wl_proxy *proxy, uint32_t opcode,
const struct wl_interface *interface, uint32_t version, uint32_t flags, union wl_argument *args) {
/* Is it a call to xdg_activation_token_v1_set_surface from GTK3/4? */
void *stack[3];
Dl_info sym;
if (strcmp(wl_proxy_get_class(proxy), "xdg_activation_token_v1") == 0 &&
opcode == 2 /* =XDG_ACTIVATION_TOKEN_V1_SET_SURFACE */ && !interface && version == 1 && !flags &&
/* When GTK3/4 calls us, the stack looks like:
0 - Our function
1 - wl_proxy_marshal_flags (called us, we don't directly intercept it because it's variadic)
2 - Somewhere inside GTK */
backtrace(stack, 3) >= 3 && dladdr(stack[2], &sym) &&
(strstr(sym.dli_fname, "/libgtk-3.so") ||
strstr(sym.dli_fname, "/libgdk-3.so") ||
strstr(sym.dli_fname, "/libgtk-4.so"))) {
/* Ignore it */
return NULL;
}
/* Call the real function */
static struct wl_proxy *(*real_wl_proxy_marshal_array_flags)(struct wl_proxy *proxy, uint32_t opcode,
const struct wl_interface *interface, uint32_t version, uint32_t flags, union wl_argument *args);
if (!real_wl_proxy_marshal_array_flags) {
real_wl_proxy_marshal_array_flags = dlsym(RTLD_NEXT, "wl_proxy_marshal_array_flags");
}
return real_wl_proxy_marshal_array_flags(proxy, opcode, interface, version, flags, args);
}
Save as gtk-wlroots-xdg-activation-haxx.c
, make sure that you have gcc
and wayland
/wayland-devel
, then before you launch sway
, do something like:
gcc gtk-wlroots-xdg-activation-haxx.c -shared -lwayland-client -o "$XDG_RUNTIME_DIR"/gtk-wlroots-xdg-activation-haxx.so
export LD_PRELOAD="$XDG_RUNTIME_DIR"/gtk-wlroots-xdg-activation-haxx.so
And it should work (tested on Arch Linux and Fedora 37 with Firefox, Sublime Text, Drawing).
https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/5293