bspwm: Google Chrome / Electron apps don't "unfocus" when changing desktop

Hi,

when focusing a window, if the previous window is Chrome, it doesn’t “unfocus”, if they are not both on the same desktop.

Exemple :

  • with bspc node -f older (called from sxhkdrc)
  • if I go from a google chrome window to, say, a terminal on another desktop
  • the chrome window still believes it’s focused.

I did confirm it by typing this in the DevTools of any chrome window :

setInterval( function(){ console.log( document.hasFocus()); }, 500 );

✔ The “focus” goes from true to false when I focus another window on the same desktop. ✘ The “focus” keeps being true when I focus another window on another desktop.

This doesn’t happen with firefox. I suppose Chrome doesn’t have the same method to check it’s focused state.

It’s a real problem for some Electron applications (like discord), which notifies you when focus is lost. In this case, changing desktop doesn’t show notifications.

Thank you for reading 😃

About this issue

  • Original URL
  • State: open
  • Created 6 years ago
  • Reactions: 34
  • Comments: 86 (21 by maintainers)

Commits related to this issue

Most upvoted comments

@baskerville Any ideas what could be going wrong? Unfortunately all the most popular communication apps are Electron-based and thus all their messaging notifications are affected.

I too face this issue, and it’s very annoying. For me, the issue is with discord notifications - I don’t get notifications of the focused channel if I change workspaces normally with discord in focus in that workspace. My workarounds are focusing a different window before changing workspaces, or going to the Friends tab so I get notifications.

I found this reddit post from 5 months ago, whose OP had the exact same issue as me. They’ve found this interesting thing:

I found something strange. If I switch desktop by using the keyboard shortcut, the notification does not work. But if I switch desktop by using the mouse click on polybar, the notification works. Maybe polybar use different commands to switching desktop ?

And they’ve also come up with a workaround to the normal workspace-switching command.

Why hasn’t there been any progress in this issue for nearly 2 years now?

@baskerville @soenkeliebau This 2-year old issue seems to be bothering several users, so as a little incentive, I’m rewarding a $200 bounty to the person providing a fix that can be merged to master.

This patch is a good start, however, as others have pointed out, it is not a full solution. For example, it doesn’t work in empty desktops or when the focus changes to Java (and maybe other) applications.

I encourage others to increase the “reward pool” in order to bring more attention to this annoying issue.

Thanks!

Right now my solution is just to use the web versions of Discord, Slack, etc., which has pros and cons but is a viable workaround for this issue. The hacks didn’t work for me and aren’t very palatable.

I definitely experienced the same kind of focus/notification issue on dwm in the past. I can’t speak for the latest version though.

I’m not opposed to using other WMs (in fact, I’ve been considering switching back to dwm just because of glitches in bspwm in general and zero support). But I’m a long-time dwm user and wanted something new that’s decent. I disagree with some design choices in i3, it’s basically unusable for me, though it does a lot of things right. I’ve tried most WMs.

It is a shame because bspwm has potential. Perhaps someone will maintain a decent fork in the future.

Ok, the workaround @cubetastic33 mentioned is working great, although it is ugly as hell.

I’ve replaced all bspc node -d or bspc desktop -f by calls to a script :

#!/bin/sh
eval "$(xdotool getmouselocation --shell)"
xdotool mousemove 960 1080
if [ "$2" = "move" ]; then
	bspc node -d "$1"
elif [ "$2" = "follow" ]; then
	bspc node -d "$1" -f
else
	bspc desktop -f "$1"
fi
xdotool mousemove --screen $SCREEN $X $Y

xev correctly reports the EnterNotify and LeaveNotify events with or without the patch so I wondered if Electron might be the issue, like others suspected.

Running the app with the latest version of Electron (v27 instead of the v9 specified in the package.json) doesn’t seem to solve the issue.

With the patch enabled (and the latest version of Electron), the app correctly reports “blur” (loss of focus) when switching to an empty desktop with the mouse over the app (it prints bye), or when sending the app window to another desktop, leaving the current desktop empty. The patch is still not enough though, because with the pointer inside the window, it doesn’t report “focus” when switching back to the desktop with the app window. It does though with the pointer outside of the window when switching.

The version of Discord I’m running uses Electron v22 so it might explain why my tests where successful with Discord.

My guess is that newer versions of Electron rely on EWMH while older ones used something else / didn’t work properly.

With a stock bspwm (no patch), I noticed that the app correctly reports focus and blur when changing desktop with the pointer over the window, without the window being focused (could Electron be using the pointer coordinates directly ?). Doing so with the patch enabled causes the window to rapidly report focus and blur, and then blur again when switching back to the desktop, so clearly my proposal doesn’t work in all cases.

The only obvious “solution” is to switch window managers, you should check out qtile and xmonad if you like WMs that you only get a wm and you add your own bar, qtile has it’s own bar though but it’s very good and it’s written entirely in python so the syntax is easy

It’s been 4 years I don’t think this will be solved anytime soon

I’ll pitch in 30 USD, that brings us to 250 overall I believe.

I’d pitch in $20 USD.

But I am asking if you are sure you have tested discord with your mouse on it. If your mouse is not on discord when you change desktop, it should already work without problems even without the patch.

@baskerville Any plans to fix this? Still an issue.

@emanuele6 You’re right: in fact I think the electron window really wants a LeaveNotify event. So if you have a floating window in another desktop, and your pointer is inside this window, you can leave the pointer inside the electron window, and when the desktop is switched, your test script will print bye!

The way I’m testing it is by running a script that executes a webhook to send a message every second. If I change desktop with the mouse on Discord, any new message correctly triggers a notification, while it doesn’t without the patch.

I’ll close the pull request for now though.

As I said, I only tested it with Discord, but you’re right, with your app it doesn’t seem to make any difference. Discord must be doing additional checks.

@cortobeau Are you sure that patch does anything? I tested it with the electron test app i posted in this thread 3 years ago and it makes no difference https://github.com/baskerville/bspwm/issues/811#issuecomment-667896738

The bug is that if you have your mouse on a electron window, and then change desktop to an empty desktop, the electron window still thinks you have your mouse on it even if you unfocused it by changing desktops and are interacting with other windows on other desktops.

Again, note that the bug only occurs if you have your mouse on the window before changing desktop, please make sure you have the mouse on the window when reproducing.

Any solutions? almost all comm apps are now electron-based. And this a big issue, especially Work From Home situation.

I’m still using my patch + some scripting to fix it, so I haven’t even thought about the bug since December, but I’m not very hopeful of a real fix ever tbh, it’s been almost 3 years

I got the bug both with the patch as well as without it.

If Slack is alone on a workspace, it will not unfocus when I switch workspace. It does not matter what desktop I switch to, weather it is empty or populated. However, if Slack has another window, say a terminal on the same workspace I can switch workspace as expected. This is not the case with Signal; I can always switch away from a workspace with Signal app on, weather Signal is the only window or not and it works as expected.

I also noticed some intense flickering when moving the cursor around if Slack is alone on a workspace. This is made worse when running a compositor; if compton is running Slack does not render any changes to the window at all. I dont know if this might be reelvant…

I can confirm that @neeasade’s script works for me on Discord.

EDIT: After using it for a bit of time, I notice a few caveats:

  • Once the node is hidden, clicking notifications do not take me to the window.
  • If there is more than one window on the desktop, it is quite jarring when switching to the desktop as the windows quickly resize themselves.

linking a heavyhanded attempted script workaround that works for me in the Chrome console logging case (I couldn’t repro Discord). I have the following in an electron_fix script that runs on it’s own with no args:

#!/usr/bin/env bash

get_class_wids() {
    for wid in ${!wid_to_class[@]}; do
	if grep -qi "$*" <<< "${wid_to_class[$wid]}" ; then
	    echo "$wid"
	fi
    done
}

set_state() {
    for wid in $(get_class_wids "$*"); do
	# if wid is not in our dtop, hide it (attempt to force unfocus)
	if bspc query -N -d .focused -n $wid >/dev/null; then
	    echo "$*: showing!"
	    bspc node $wid -g hidden=false
	else
	    echo "$*: hiding!"
	    bspc node $wid -g hidden=true
	fi
    done
}

declare -A wid_to_class=();
act() {
    # cache
    wid_to_class=();
    for wid in $(bspc query -N -n .window); do
	wid_to_class[$wid]=$(xprop WM_CLASS -id "$wid")
    done

    # NB: add cases here:
    set_state google-chrome
    set_state discord
}

act

while read -r event mon_id desk_id; do
    act

    # fix refocus issue by using xqp: https://github.com/baskerville/xqp
    # if $(bspc config focus_follows_pointer); then
    # 	bspc node -f $(xqp)
    # fi
done < <(bspc subscribe desktop_focus)

(disclaimer: not looking for the bounty, would appreciate if someone affected by this issue more thoroughly than myself could test this)

That’s cool of you guys. Spent another few hours looking at it today but still can’t wrap my head around what’s missing. To me it looks like everything that interacts with the previously focused window runs exactly the same no matter if the destination desktop is empty or not. 😭 I’ll continue later this evening if I can find the motivation…

Some of the events do have a time field, for example xcb_enter_notify_event_t.

https://github.com/baskerville/bspwm/issues/811#issuecomment-667889182

@instantepiphany, I tried to use that patch and the problem wasn’t fixed.

@instantepiphany do you have focus_follows_pointer or pointer_follows_focus set in bspwmrc?

I think the issue is likely with bspwm, because this issue doesn’t happen with other WMs like i3, for example. And I’ve been facing this issue for so long that I always move my mouse outside discord from muscle memory 😂 It would be really cool if this issue were fixed