I did look into D-Bus and other Gnome DE specific methods that came to mind, but couldn't find a more reliable, sustainable and portable solution than what is described below ...
You can use xdotool
(which also seems to work on Wayland for this purpose) in a shell loop like:
#!/bin/sh
while sleep 0.2
do
v="$(xdotool get_desktop)"
if [ -z "$ws" ]
then
ws="$v"
elif [ "$ws" -ne "$v" ]
then
ws="$v"
echo "changed to $ws"
# Your command here
fi
done
... that tool still works on Wayland because it reads the _NET_CURRENT_DESKTOP
property of the EWMHExtended Window Manager Hints which many windowing managers/systems still support and set by standards.
Needless to say that there are other tools which support reading that property along with builtin capability to continuously monitor it (If you don't like a continuous loop with a sleep
call) like xprop
and you can similarly use it like so:
#!/bin/bash
xprop -root -spy _NET_CURRENT_DESKTOP |
while IFS=" " read -r p s n
do
if ! [[ "$ws" =~ ^[0-9]+$ ]]
then
ws="$n"
elif [ "$n" -ne "$ws" ]
then
ws="$n"
echo "changed to $ws"
# Your command here
fi
done
... or even xev
like so:
#!/bin/sh
xev -root -event property |
grep --line-buffered -o '_NET_CURRENT_DESKTOP' |
while read -r p
do
echo "Workspace changed."
# Your command here
done
... and of course you can, if you wish, alternatively implement your own app to read the _NET_CURRENT_DESKTOP
property in any language C, Python ... etc. and not necessarily in a shell script using those tools.
Notice:
The above first loop with xdotool
and the last one with xev
is not Bash specific and can run with other POSIX shells with sh
for example.
When using xprop
on Wayland, as reported by @Daniel T (Thank you Daniel), then the workspace has to be switched at least once before xprop
starts catching it and as a result your first switch between workspaces will be out of scope for the script ... So, if that is critical, use xdotool
instead.
Notice as well that (goes without saying) those loops need to be run while a user graphical session is running i.e. after login and before logout ... and therefore the best implementation for either is as a startup application be it they are contained in script file or even laid out in the Command: field as a single shell command string like this:
sh -c 'while sleep 0.2; do if [ -z "$ws" ]; then ws="$(xdotool get_desktop)"; elif [ "$ws" -ne "$(xdotool get_desktop)" ]; then ws="$(xdotool get_desktop)"; echo "changed to $ws"; fi done'
... or like this:
bash -c 'xprop -root -spy _NET_CURRENT_DESKTOP | while IFS=" " read -r p s n; do if ! [[ "$ws" =~ ^[0-9]+$ ]]; then ws="$n"; elif [ "$n" -ne "$ws" ]; then ws="$n"; echo "changet to $ws"; fi done'
... or like this:
sh -c 'xev -root -event property | grep --line-buffered -o '_NET_CURRENT_DESKTOP' | while read -r p; do echo "Workspace changed."; done'
... your custom command in those command strings should go in-place of the echo "..."
part.