After trying the answers in this question: How to start an app with "Always On Top" set?, specially the one in the comments by @MichaelTunnell:
This is the best option for me because I can create a bash script or a keyboard shortcut (which I did) using this command and that way I can use it when I need it but not when I don't. I did make a change though...I wanted a shortcut to turn always on top for the active window and only when I needed so here is my command.
wmctrl -r :ACTIVE: -b toggle,above
I was able to toggle always on top in Ubuntu 16.10 or below, but not on Ubuntu 17.10 which is the one I have installed right now and would like to have this same shortcut
I have also tried this post which is basically a more detailed post of the comment of Michael Tunnell: Keyboard shortcut for always on top Ubuntu
The shortcut can be seen in the image below and it works for setting the window Always-on-top to True, but even if I use the same command again to "turn it off", I can't get the active application to remove that property.
Is this a bug in GNOME Ubuntu 17.10? Or am I missing any extra configuration in this particular version?
After a lot of research and working out how to write proper code in bash, I have 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! Behold:
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 thewmctrl
command with the parameteradd
orremove
as appropriate.Command breakdown (each command is inserted into the next, replacing the
■
placeholder):xprop -root -f _NET_ACTIVE_WINDOW 0x " \$0\\n" _NET_ACTIVE_WINDOW | awk "{print \$2}"
xprop -id $(■) _NET_WM_STATE
[[ $(■) =~ "ABOVE" ]]
■ && echo "remove" || echo "add"
wmctrl -r :ACTIVE: -b $(■),above
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.
wmctrl
is not fully compatible with Wayland, which is the default session on Ubuntu 17.10.As a workaround you switch back to an Xorg session following this Q&A: How do you switch from Wayland back to Xorg in Ubuntu 17.10?
I think Geoff's solution is great but I wanted something a little more readable/adaptable so I wrote this quick bash script that functions very similarly but employs
xdotool
to get the id forxprop
Now I just make my shortcut point to this script and it works for me.
Pretty self-explanatory, I think. The one part that might need explaining is the
$?
which just returns the exit code of the previous command (in this case grep: 0 if it matched, 1 if it failed). Note that it's probably not good practice to use the exit code this way sincegrep
could fail for some other reason, but this script failing is pretty low risk ;)