This is the fourth post in a series on achieving an orderly desktop environment in GNOME 3, using no add-ons, only old school hacks. See also the first, second and third post in the series.
Following the first two set of instructions we’ve got static workspaces and windows spawn where they should. That in itself is not terribly convenient as I now have to run up and down in the GNOME workspace stack to find the window I’m looking for – even if I just launched it – or rely on the old alt-tab trot that we know and hate from Windows. To torture this metaphor, we’re going to skip the stairs and install an express elevator thus also justifying the arbitrary choice of the post’s header image.
This is where the final piece of the puzzle comes in: A better way to start applications and switch between them. These two kinds of actions tend to be treated separately. You start up an application by clicking an icon or typing a command and then you find it again later on by different means. Both actions stem from the ‘I need application X now’ impulse. So you should channel that impulse the same way. There is an established way to integrate them, though. Windows 7+, GNOME Shell, and Mac OS X (I believe?) all tie an icon to a permanent process bar and have this work as both process launch and recall. I don’t think this is a good solution for a number of reasons: a) it’s not convenient (read: keyboard-centric) and b) I dislike bars (the taking-up-screen-space kind, not the other one one). The simple solution: Associate one application with one keyboard shortcut and leave it to the computer to figure out whether this means starting the application or retrieving a running instance. Either way it will obviously have to be on it’s proper workspace, see post the second, so we want to come to (move the focus to) the workspace of the window, rather than janking it out of it’s place and having it come to us.
To this end we introduce two tools that will help us achieve this: wmctrl for manipulating windows and xbindkeys for the keyboard shortcut bit. Also bits of Bash for glue. All of these are omnipresent on linux distibutions and should be installable as packages named just as written above. One word of warning, though. This entire series is composed of hacks but the previous ones are so established and solid that it hardly counts. This is where it gets a bit hairy.
The following is the command (in Bash) that either launches or redirects my focus to Nautilus, the Gnome file manager:
wmctrl -s1; (wmctrl -Fx -a nautilus.Nautilus || nautilus &)
Technically, it’s two commands, divided by the semi-colon. The first bit is a wmctrl command that moves focus to the second workspace. Yes, the second; wmctrl starts counts from 0. So if you go to a terminal and type in ‘wmctrl -s 4’ and hit enter you’ll get taken to the fifth workspace (if you’ve got five or more, of course). The workspace chosen here should obviously correspond to the one set for Nautilus in devilspie if any such is set. The second bit is an either/or command (demarcated by ‘||’): If the command on the left side of the two vertical lines is succesful, then the command on the right side won’t run and vice versa. The ‘either’ in this particular case is again a wmctrl command which says to switch focus to a window with the exact class name (as written and understood by wmctrl) ‘nautilus.Nautilus’. If it finds such a window it get’s focus and no more happens. If not the ‘either’ part is considered a failure (the command returns something other than 0) and we move on to the ‘or’ part, the command on the right side of the lines. This simply says to launch nautilus and quit. To sum up: We go to workspace 2 and there we either launch nautilus (if there isn’t a nautilus window already) or we simply note that there already is a window which identifies as belonging to Nautilus and we give that window focus. Either way we get a file manager and avoid having more than one instance running at a time. This works regardless of what workspace you are currently on and what window is currently focused. Even if you’ve got lots of random windows all over workspace 2, nautilus should get focus and be taken to the top of the heap.
A few technical notes. We use wmctrl to identify windows and focus a window by running wmctrl -a [match_this] rather than say pid to identify processes. That a given program has a process running does not guarantee that it has a window. Secondly, using wmctrl to identify window titles (the default wmctrl window matching behaviour) is almost as bad as using pid. Matching by window titles can over-match: If you’re reading an article on Nautilus called ‘Nautilus – the GNOME file manager’ in Firefox it will get picked up by running ‘wmctrl -a nautilus’. But it can also ‘under-match’ as programs such as Nautilus and Gnome terminal change their window title depending on the location being browsed and so they will not be matched by ‘wmctrl -a nautilus’. Therefore the use of the -F and -x switch. The latter means that matching is done against the class name of the window (‘nautilus.Nautilus’) rather than the window title (e.g. ‘Music’ if you’re looking at the Music folder). The former means that it has to be an exact match: We do not accept ‘not_nautilus.Nautilus’. This makes window matching using wmctrl a much more reliable way of identifying and manipulating windows.
And another note on the form of the class name. If you use a tool like xprop (should come standard with any Xorg install) you can get the class name of a window, like this:
[~] xprop | grep -i class WM_CLASS(STRING) = "nautilus", "Nautilus"
Entering the command the cursor will change to a crosshairs and you simply click on the window you want to inspect. It will then spit out a lot but seeing as we use grep as a filter here we only get the line containing the word ‘class’. As you can see the class is written a bit differently than we just did with wmctrl. Seeing as we tell wmctrl to only accept exact matches I will encourage you to use wmctrl itself to learn the correct class name (as wmctrl understands it) by issuing the command:
wmctrl -lGx
This will simply list (-l) all windows with their class names (-x) and geometry (-G) for easier identification.
Finally, I think that the parantheses around the second command are superfluous, a vestige of an older style. But they don’t do any harm so I’ll leave them.
And that’s really it. Different programs will require slightly different variations but all such launch/switch operations can be achieved merely by tweaking this simple line of Bash (it might also work in other shells but no guarantees). It plays it safe by first moving position (wmctrl -s[workspace number]) and only then looking for the window rather than attempting to kill more birds with one stone. I like it safe and I’ve yet to see this approach fail.
But wait, how do you actually use it in day to day operation? If you’re reading this you probably know about keyboard shortcuts and how to set them in GNOME or any other desktop environment. And that is an option. However, I prefer using a separate program for keyboard shortcuts. That means I will not loose them should I decide to switch to Cinnamon, MATE, KDE, Xfce or any other EWMH compliant window manager.
Xbindkeys is one such program. The configuration file explains the syntax itself but just as an example here’s how the Nautilus line as well as a shortcut to my terminal looks in the context of my .xbindkeysrc:
"wmctrl -s1; (wmctrl -Fx -a nautilus.Nautilus || nautilus &)" Mod4 + f "wmctrl -s2; (wmctrl -a local_screen || xfce4-terminal --title='local_screen' -e 'screen -Rd' --hide-menubar --hide-borders &)" Mod4 + t
Mod4 is .xbindkeysrc code for the Super/Win key. So holding down Super while pressing f will get me my file manager. Yes, I am intentionally breaking with Windows convention. In your face, Satya Nadella.
Also notice that the xfce4-terminal line does use title matching. Yes, that is normally a bad idea but in this case xfce4-terminal allows me very exact control over the window title, just see the ‘–title’ setting among the launch parameters. This control also includes an option to stick with this title regardless of current directory position. No rule without exceptions.
That’s it for the ‘stay-here’ windows. Next time I’ll detail how to get smaller windows like Empathy to come to you and disappear when they’re not wanted anymore, the ‘magic pencils’ of the intoductory post.