sway icon indicating copy to clipboard operation
sway copied to clipboard

firefox does not grab focus when opening urls externally

Open MichaelAquilina opened this issue 5 years ago • 7 comments

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.

MichaelAquilina avatar May 14 '19 11:05 MichaelAquilina

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.

emersion avatar May 14 '19 16:05 emersion

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.

mdeff avatar Jun 03 '19 18:06 mdeff

One possible workaround is to make external links open in a new browser window

siikamiika avatar Oct 16 '21 12:10 siikamiika

Dupe of https://github.com/swaywm/sway/issues/4830 ?

sethidden avatar Nov 21 '21 19:11 sethidden

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.

AdamantGarth avatar Feb 03 '22 14:02 AdamantGarth

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).

joanbm avatar Apr 19 '22 23:04 joanbm

Can confirm this happens with Brave browser as well.

UtkarshVerma avatar Jun 01 '22 12:06 UtkarshVerma

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.

JosefLitos avatar Oct 16 '22 18:10 JosefLitos

We now have the xdg-activation protocol, which is implemented in wlroots and Sway.

Closing this as a missing feature in the client.

emersion avatar Oct 16 '22 19:10 emersion

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.

joanbm avatar Nov 28 '22 21:11 joanbm

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).

joanbm avatar Nov 29 '22 20:11 joanbm

https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/5293

emersion avatar Dec 05 '22 10:12 emersion