My 2 year after the last post, post is again about a window manager. :-)
The image below shows my current Awesome desktop while writing this (using the centerwork layout):
I was pretty happy with Openbox, but I was missing those couple of moments when a tiling layout made sense. Even though I mainly have only 2 or 3 open windows on each workspace, there are a few occasions where tiling works, i.e. having terminals side by side, an editor and a Firefox window, etc, and it seemed silly to resize with the mouse all the time, since tiling is a thing. On the other hand tiling isn’t always productive, usually when there are gui apps that don’t like being stretched or get shrunk. Get a few windows open at the same time, and it can be messy.
There’s also the thing about laptops. Contrary to having a large 25, 27 inch display where the mouse is also in close reach, on laptops tiling window managers make more sense. On their smaller screens, typically I use one window in fullscreen most of the time, and keep others behind. Having to deal with resizing windows using the touch pad is a nightmare. I wanted a window manager that I could ran on both.
Window managers in general only seem to cater for only one of those paradigms. Openbox is a floating wm. There are some tiling scripts, but you can always tell it’s an afterthought. i3 or bspwm are mainly tiling window managers, and are focused on that.
Awesome advertises itself as both a “dynamic floating and tiling window manager” (at least that’s what’s on Gentoo’s package description), and states at it’s home page:
Does not distinguish between layers: there is no floating or tiled layer.
Framework window manager
But perhaps it’s biggest strength is that it’s not just a window manager, it’s a framework window manager. What that means is that you can code for it without touching it’s main core source. It’s configuration file is actually lua code. Similar to what DWM does but using a more civil/suited scripting language, which doesn’t require recompiling the whole code base. As an example, I was looking for a way to stop on tags 1 or 9 when cycling through them (i.e. not allow to go from 9 to 1 or from 1 to 9). (Btw, tags are workspaces for awesome). It’s default “configuration” is:
awful.key({ modkey, }, "Left", awful.tag.viewprev, {description = "view previous", group = "tag"}), awful.key({ modkey, }, "Right", awful.tag.viewnext, {description = "view next", group = "tag"}),
awful.tag.viewprev and awful.tag.viewnext are functions of the tag class. When called, they will switch awesome to the previous and next tag respectively. In the above case they get executed when you press the modkey (usually the windows key) and Left and Right arrows. To implement the “stop at the first and last tags” functionality, you can replace those with a new function, like this:
awful.key({ modkey, }, "Left", function() local t = awful.tag.selected(1).name if t > "1" then awful.tag.viewprev() end end, {description = "view previous", group = "tag"}), awful.key({ modkey, }, "Right", function() local t = awful.tag.selected(1).name if t < "9" then awful.tag.viewnext() end end, {description = "view next", group = "tag"}),
awful.tag.selected(1).name returns the number of the currently selected tag.
As you can imagine, there are countless third party modules, or plugins, available to extend the functionality of Awesome.
Basics
When started for the first time, Awesome runs a default rc.lua (the “config” file), usually located in /etc/xdg/awesome/rc.lua. You should copy this locally in .config/awesome/.
You could also start with an rc.lua (and some themes) from Awesome WM Copycats. These provide some more options and goodies over the default rc.lua, and having a good starting point really helps (especially if like me don’t have a clue about lua). Note that Copycats take everything having to do with themeing outside of rc.lua, and in it’s own file (usually in themes/something).
Out of the box Awesome provides a taskbar (called wibox) on top of the screen, which implements a menu launcher, indicators for the tags, a task list, a keyboard layout indicator, a systray, a clock and date and finally an indicator of the current tag’s layout. There’s also a launcher (similar to dmenu), which can be activated with Win + R.
There is also a god-sent popup of current shortcuts, activated with Win + S. (Bonus: when invoked while in a VIM window, it will also list VIM shortcuts!).
Kinda expected, Awesome lacks traditional Alt-Tab functionality, like most WM’s these days, except of course Openbox. Having been used to it for many years, it has prevented me from really investing time in a wm that doesn’t have it. There are some third party plugins available, but I’ve decided to try and work without it. Awesome can be configured to at least provide window minimizing functionality (and to some extend restore a minimized window).
Window minimizing is at least for my workflow, required. i3’s (and of most tiling wm that is) mentality for example, of sending a window to another workspace when not needed, simply doesn’t work for me. It clutters the whole environment, binning the “each workspace for a specific job” paradigm. You should be able to remove a window from a layout temporarily without closing it. BSPWM does implement a minimizing function, but no real way of restoring it. In Awesome, the window remains in the task list, and can be clicked to restore it. I’ve also implemented two more ways to restore a window:
The first one is by having Win+a restore minimized windows (one window at a time). If you have more than one, then it’s not perfectly clear which one will get restored first or second, but it’s good enough for quick keyboard navigating.
awful.key({ modkey }, "a", function () local c = awful.client.restore() -- Focus restored client if c then client.focus = c c:raise() end end, {description = "restore minimized", group = "client"}),
The next one is by using rofi’s window list functionality. By default, even though rofi will list the minimized windows, they won’t get restored when selected. Adding the following to rc.lua will do the trick:
-- raise window if requested from rofi window list client.connect_signal("request::activate", function(c, context, hints) if not awesome.startup then if c.minimized then c.minimized = false end awful.ewmh.activate(c, context, hints) end end)
Finally, Alt-Tab is configured to call the awful.client.focus.byidx(-1) function, so it will cycle through un-minimized windows on the current tag (ala MacOS :-) ). (However, it still lacks the functionality of going to the last selected window. There is awful.client.focus.history.previous() but it will only go back and forth between two windows, not all of them).
Of course there’s always a way to focus a window (clients in awesome) using directional functions (e.g. awful.client.focus.global_bydirection(“down”)). I have those bound to Win+Arrow keys.
Awesome also ships with it’s own notification daemon (naughty), which will prevail over e.g. dunst (it will most likely start first). Luckily in Gentoo you can compile awesome without dbus support which disables naughty completely. (Of course I did this just because I have dunst configured as I like; naughty is just as good if given the effort).
Generally Awesome works as you would expect it. I remember having trouble with e.g. full screen youtube windows in bspwm or in i3. Steam and full screen games also work perfectly.
Configuration
rc.lua doesn’t require much in programming experience to do simple changes to your config. Most of the things are pretty self-explanatory, i.e. change the terminal variable to what you like:
terminal = "my_fav_term"
After a change in rc.lua, restart awesome with Win+Ctrl+R.
Available layouts are listed in awful.layout.layouts section. You can change each tag’s layout using Win+Space. Try them out, and pick those that you like. I only keep 3:
awful.layout.layouts = { awful.layout.suit.floating, awful.layout.suit.tile, --awful.layout.suit.tile.left, --awful.layout.suit.tile.bottom, --awful.layout.suit.tile.top, --awful.layout.suit.fair, --awful.layout.suit.fair.horizontal, --awful.layout.suit.spiral, --awful.layout.suit.spiral.dwindle, --awful.layout.suit.max, --awful.layout.suit.max.fullscreen, --awful.layout.suit.magnifier, --awful.layout.suit.corner.nw, --awful.layout.suit.corner.ne, --awful.layout.suit.corner.sw, --awful.layout.suit.corner.se, --lain.layout.cascade, --lain.layout.cascade.tile, lain.layout.centerwork, --lain.layout.centerwork.horizontal, --lain.layout.termfair, --lain.layout.termfair.center, }
Floating is the classic floating mode, tile will tile a master client in half the screen, and all other windows (slaves) in the rest, on top of each other. Centerwork is actually a third party tiling layout from Lain. It will keep the master tag in the center of the screen, having the rest of clients in the left and right of the master. Very useful for widescreen monitors.
Each tag can have a default starting layout. I keep all of mine in floating mode by default.
A client can be also maximized using Win+M, and un-maximized using the same combination. Sometimes it is useful to have a bigger picture and focus on a specific task.
Keybindings are also easy to change, but check beforehand if new keybindings are already taken using Win+R.
Wibox
Wibox, is the standard bar in Awesome. It follows the same logic, i.e. lua is used to describe and place the bar items (widgets). If you went for the Copycats method, then the bar code will be in a separate file from rc.lua (usually in themes/selected_theme/theme.lua).
Choosing a third party theme to start on, is I think the best way to go, and the best time to do it is before any changes to the default rc.lua file. (r/unixporn is also a good place to find themes).
There are tons of widgets on the net for the wibar, ranging from the simple cpu/filesystem stuff, to weather and calendars. The bar can also respond to clicks, mouse overs, etc.
On my screenshot at the start of the page, my bar contains a group on the left, and another on the right. (This is actually a single wibox, having it’s background color transparent). It was based on the Holo theme from Copycats.
The left part contains indicators for the tags, a graphic showing the current tag’s layout, and a task list with icons only. I haven’t found a good way yet to resize the icons in the tasklist (would like them to be a bit smaller).
On the other side there is a widget showing the MPD’s current song, a headphone icon (clickable) which launches ncmpcpp, a bar that shows sound volume (and responds real time to when I change it via keyboard shortcuts), a current weather widget, a keyboard layout indicator, and time and date.
The current song and weather indicator just run a shell command and place it’s output on the bar, using the awful.widget.watch function. It’s not very efficient, but it gets the work done.
What I’ve found lacking is the systray rendering. Common maybe among other bars too, it seems to be hard to get right. I think I only saw tint2 having a good implementation of it. You can’t really specify a size for the icons, and there is no transparency behind them. I’ve stoically accepted to live without it. The only icons I had there was nextcloud’s client, and the pidgin indicator. Loosing the pidgin indicator was perhaps a good idea after all, I now have way less interruptions :-)
Conclusion
I’ve been using Awesome for a couple of months now. It seems the longest I’ve gone without Openbox (but it’s still installed!). I’ve yet to scratch the surface; since I did my initial configuration it has stayed out of my way. No crashes, minimal ram/cpu consumption, what else can you ask!?
Having the ability to extend it with lua, it really allows you to make a completely different environment than what Awesome provides as default. Some really interesting modifications are listed below:
Screenshots from Awesome’s github repo
Thanks for reading!