I tried to use the wmctrl
command toggle, but it didn't work on my Ubuntu set up. The toggle would toggle on, but not toggle off. (I think it might be because I'm using the gnome desktop environment, on which wmctrl
is slightly broken AFAIK).
Anyway, after a lot of research and working out how to write proper code in bash, I created a single command that uses the wmctrl
commands within a layer of logic to toggle the 'always on top' state effectively on the current GNOME desktop. I posted this answer on Ask Unix/Linux, but thought I'd post it here too in case anyone had the same issue.
Here is the command:
bash -c 'wmctrl -r :ACTIVE: -b $([[ $(xprop -id $(xprop -root -f _NET_ACTIVE_WINDOW 0x " \$0\\n" _NET_ACTIVE_WINDOW | awk "{print \$2}") _NET_WM_STATE) =~ "ABOVE" ]] && echo "remove" || echo "add"),above'
It checks the active window state property "_NET_WM_STATE" using xprops
, and if it contains the text "ABOVE" that means the 'always on top' option is active. Then it just runs the wmctrl
command with the parameter add
or remove
as appropriate.
Command breakdown (each command is inserted into the next, replacing the ■
placeholder):
Get active window id:
xprop -root -f _NET_ACTIVE_WINDOW 0x " \$0\\n" _NET_ACTIVE_WINDOW | awk "{print \$2}"
Get the window state from xprop
using the id:
xprop -id $(■) _NET_WM_STATE
Check if the state contains "ABOVE", indicating that the window is set to "always on top":
[[ $(■) =~ "ABOVE" ]]
Return "remove" if true, otherwise return "add":
■ && echo "remove" || echo "add"
run wmctrl
command using the returned value as a parameter:
wmctrl -r :ACTIVE: -b $(■),above
Send the whole thing to bash
so that you can use command substitution ${ ... }
, bash boolean evaluation [[ ... ]]
and the regex match operator =~
:
bash -c '■'
This last step in particular took me a very long time to figure out. Until I realised that the keyboard shortcuts weren't running in bash by default, I had no idea why the commands were working in the console as I was testing them but silently failing when run directly as a keyboard shortcut. It drove me up the wall for ages!
Note: because you need quotes around the command you're sending to bash, I had to be careful when writing the command that I never went more than one more level deep (using double quotes). Any further nesting of strings in quotes would have required lots of confusing backslashes to escape the quotes.
Further detailed notes: how to create the keyboard shortcut (thanks @rajesh_chaurasiya)
Install wmctrl using sudo apt-get install wmctrl
if you haven't already
Go to system settings > keyboard shortcuts. Click the +
button to add a custom shortcut.
Choose a name such as 'Toggle always on top' ( it can be anything you like ).
In the command field add the full command from the top of this answer.
Record a keybinding to complete the shortcut.