So i have my 5 defined desktops but there is an additional desktop which i havent defined anywhere and its name is just "Desktop".
Heres my bspwmrc file:
#! /bin/sh
bspc config remove_disabled_monitor true
EXTERNAL_OUTPUT="VGA1"
INTERNAL_OUTPUT="eDP1"
xrandr |grep $EXTERNAL_OUTPUT | grep " connected "
if [ $? -eq 0 ]; then
xrandr --output $INTERNAL_OUTPUT --off --output $EXTERNAL_OUTPUT --auto
bspc monitor $EXTERNAL_OUTPUT -d I II III IV V
else
xrandr --output $INTERNAL_OUTPUT --auto --output $EXTERNAL_OUTPUT --off
bspc monitor $INTERNAL_OUTPUT -d I II III IV V
fi
sxhkd &
#if [ "$(bspc query -M | wc -l)" -eq "2" ]; then
# bspc monitor $(bspc query -M | sed -n 1p) -d I II III
# bspc monitor $(bspc query -M | sed -n 2p) -d IV V
#else
# bspc monitor -d I II III IV V
#fi
bspc config border_width 5
bspc config window_gap 12
bspc config split_ratio 0.50
bspc config borderless_monocle true
bspc config gapless_monocle false
/usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1 &
compton -b
wal -t -i "$(< "${HOME}/.cache/wal/wal")"
source $HOME/.config/bspwm/colors.sh
polybar top &
The name "Desktop" is the default desktop name used when a desktop has no given name. This is just speculation, but could it be caused by a timing issue between bspwm knowing the monitors have changed and your call to bspc? Am I correct to assume you problem only occurs when you have an external monitor connected? Or can a monitor be known to the system while being disconnected other than the builtin monitor? Anyway, this is likely what is happening:
xrandr this disables one of the monitors, but this is not known yet to bspwm, otherwise your --reset-desktops (-d) call would have removed the "Desktop" monitor.bspwm is made aware of the changes made in the monitor setup, so it will remove the monitor, causing the default "Desktop" desktop to be moved to the other monitor to prevent loss.How to fix? Well you could use: bspc subscribe monitor_remove and then call bspc monitor -d I II III IV V. I do not specify which monitor, because I assumed you have only one monitor active at that point.
@msteen Very good analysis. One thing I could add is an option to subscribe, for example -c COUNT that would create a subscriber that gets removed after having received exactlyCOUNT events.
@baskerville That would be great. I was looking for something like that and tried to experiment with how I could achieve this in bash in the general case (quit after receiving something N times from some piped producer), but have yet to find good solution. However it would probably be better if bspc would just provide this, because such a solution likely will be quite involved or shell specific.
@msteen c744b74
Note to myself: try to take advantage of this in tests/prelude.
@baskerville Nice, but one suggestion I would make is to make sure bspc query closes when the output buffer closes. Right now it stays alive for the next event until it realizes it cannot write to the output and exists.
bspc subscribe node_focus | { read -n 1; echo 5 }
Requires me to focus two windows before it exists. The first will cause read -n 1 to complete and it will echo 5, but it requires a subsequent event before bspc subscribe node_focus closes as well.
PS: If someone read this topic and wondered about general solution to this, were there is no support for it in the producer itself. You can do this if the producer exists as soon the its output buffer closes or if you do not mind that it will keep on running until it tries write to it again (e.g. next event):
N=2
bspc subscribe node_focus | stdbuf -oL -eL head -n $N | { while read; do echo 5; done }
If you do mind the producer does not exit immediately you could do this:
N=2
BSPC_SUB_FIFO="$XDG_RUNTIME_DIR/bspc-sub.fifo"
rm -f "$BSPC_SUB_FIFO"
mkfifo "$BSPC_SUB_FIFO"
bspc subscribe node_focus > "$BSPC_SUB_FIFO" &
BSPC_SUB_PID=$!
cat "$BSPC_SUB_FIFO" | stdbuf -oL -eL head -n $N | { while read; do echo 5; done; kill $BSPC_SUB_PID }
Or how about:
N=2
{ bspc subscribe node_focus & echo $!; wait $! } \
| stdbuf -oL -eL head -n $((N + 1)) \
| { read pid; while read; do echo 5; done; kill $pid }
So yeah, the count option is much preferred over this.
Thank you! Since you are right, im only using 1 Monitor at a time your solution should work perfectly.
EDIT: But it doesn't. As it seems calling bspc subscribe monitor_remove never ends. Calling it in a terminal doesn't work and it is running infinitely long and doesn't output anything(have to kill it with ctrl+c). This makes bspwm never start if i add this in my bspwmrc.
EDIT2: I got it kind of fixed by executing the xrandr lines in lightdm rather than bspwmrc.(makes sense i know)
@Clyybber That is because bspc subscribe is a long running process, which you generally would want to put in the background. This is why it blocks the rest of your program and why bspwmrc will not continue executing. So you would want to make sure you run bspc subscribe in the background and to run in before your xrandr call that removes one of the monitors. So something like this:
EXTERNAL_OUTPUT="VGA1"
INTERNAL_OUTPUT="eDP1"
{ bspc subscribe monitor_remove & echo $!; wait $! } | stdbuf -oL -eL head -2 | {
read pid
read -n 1
bspc monitor -d I II III IV V
kill $pid
} &
xrandr | grep $EXTERNAL_OUTPUT | grep " connected "
if [ $? -eq 0 ]; then
xrandr --output $INTERNAL_OUTPUT --off --output $EXTERNAL_OUTPUT --auto
else
xrandr --output $INTERNAL_OUTPUT --auto --output $EXTERNAL_OUTPUT --off
fi
@Clyybber I just confirmed, the code I gave you should work, however, you did make a typo in your bspwmrc and were missing a setting for it to work. It is bspc config remove_disabled_monitors true (monitors, not monitor) and you should have bspc config remove_unplugged_monitors true as well. This seems to be a bug in bspwm.
@baskerville Should setting remove_disabled_monitors to true not have worked, otherwise I find the naming confusing. I would consider running xrandr --output <monitor> --off to be disabling your monitor and unplugging when you physically remove the connection with your monitor, right?
@baskerville Regarding closing bspc subscribe when the output in which it is piped is closed, should I create a separate issue for this? That would make my read and kill PID bits in my above examples obsolete.
I would consider running
xrandr --output <monitor> --offto be disabling your monitor and unplugging when you physically remove the connection with your monitor, right?
That's correct, but unfortunately I have no way of knowing if any the *_monitors settings work as intended (I only have one monitor).
I should probably handle xcb_randr_notify_event_t events instead of querying for the monitor setup each time something happens (cf. awesome WM).
Regarding closing
bspc subscribewhen the output in which it is piped is closed, should I create a separate issue for this?
Please go ahead.
@baskerville You should be able to test remove_disabled_monitors even if you have one monitor, e.g. just have a keyboard shortcut to reset the xrandr setup. The same goes for remove_unplugged_monitors, unless you have a laptop. I have three monitors (one decent and two small old flatscreens) and just tested with:
bspc config remove_unplugged_monitors true
bspc config remove_disabled_monitors true
bspc subscribe monitor_remove
And got no output after physically disconnecting my monitor. Disabling a monitor with xrandr will only work with both settings set to true, I just tested it with all combinations and that was the only one in which I got to see any output.
I made the issue regarding closing bspc subscribe when the output in which it is piped is closed: #681
@baskerville I have looked at the external monitor support and it seems to be correct, although I think the wording could be improved, otherwise the users intuition will not match the implementation.
My intuition was, as it is worded right now, the following:
remove_disabled_monitors meant that if I disable my monitor e.g. via xrandr --output <output_name> --off the the monitor with <output_name> would be removed as a monitor known to bspwm.
remove_unplugged_monitors meant that if you disconnect your monitor physically (unplug it) it would be removed as a monitor known to bspwm.
The actual meaning is the following:
remove_disabled_monitors means that if I disable my monitor e.g. via xrandr --output <output_name> --off the the monitor with <output_name> would be considered unplugged (disconnected).
remove_unplugged_monitors means that if your monitor is found to be unplugged (physically unplugged or with remove_disabled_monitors set to true also if disabled) it would be removed as a monitor known to bspwm.
I also looked whether it was possible to implement my intuition of remove_unplugged_monitors, and it is, but it is not as nice as I would have liked. I checked the code you linked, that of Awesome WM, but it won't generate an event when you disconnect your monitor. The are several ways to implement this, but I think this is outside the scope of bspwm. You could poll the monitor entries in sysfs, poll xrandr, or create an udev rule with a script callback.
Some references:
https://askubuntu.com/questions/335992/not-updating-display-settings-when-disconnecting-external-monitor
https://faq.i3wm.org/question/377/disconnecting-external-monitor/
Thanks, I'll try to have sensible defaults regarding those settings.
Most helpful comment
The name "Desktop" is the default desktop name used when a desktop has no given name. This is just speculation, but could it be caused by a timing issue between
bspwmknowing the monitors have changed and your call tobspc? Am I correct to assume you problem only occurs when you have an external monitor connected? Or can a monitor be known to the system while being disconnected other than the builtin monitor? Anyway, this is likely what is happening:xrandrthis disables one of the monitors, but this is not known yet tobspwm, otherwise your--reset-desktops(-d) call would have removed the "Desktop" monitor.bspwmis made aware of the changes made in the monitor setup, so it will remove the monitor, causing the default "Desktop" desktop to be moved to the other monitor to prevent loss.How to fix? Well you could use:
bspc subscribe monitor_removeand then callbspc monitor -d I II III IV V. I do not specify which monitor, because I assumed you have only one monitor active at that point.