HDE Advent Calendar Day 24: Windows Management on macOS

How many windows do you have floating on the screen of your PC right now? If you are still counting, how do you manage those windows? You could make all windows fullscreen and put one in each desktop. Or you might not care so much about the arrangement: to find a window, just drag other windows that get in your way to the corners, like you are looking for a pair of socks from a pile of clothes on the floor.

Navigating through windows on macOS.

One of the many benefits of using Linux is that we have the freedom to choose the right window manager (WM) to help us "manage" the mess. My personal favourite is i3, which is a tiling window manager. "Tiling" means that your windows will be resized and positioned in a grid-like style so that they do not overlap with each other. Another example of tiling window manager is awesome: My colleague wrote about this WM in an article for HDE Advent Calendar 2014 (in Japanese). However, since we are using macOS at work, we don't have the luxury to use the any of the above, at least not natively.

I've been searching for a i3-like WM for macOS environment for a while. Recently, I've found a solution that I really like: chunkwm*1, which unlike other wm for macOS, gives us a lot of freedom for customization. In this 24th article of HDE Advent Calendar, I would like to share how I setup chunkwm to mimic my workflow as in i3.

Installation

There are two components to be installed*2:

  1. chunkwm: the tiling window manager
  2. skhd: the hotkey daemon which we will use to setup the keyboard shortcuts.

Installations for both are pretty straightforward and written clearly on the README of each project. Using Homebrew, I've installed both components as below:

$ brew tap crisidev/homebrew-chunkwm
$ brew install --HEAD --with-tmp-logging chunkwm
$ brew install --HEAD --with-logging  koekeishiya/formulae/skhd

where the logs can be found in

  1. /tmp/chunkwm.[out|err].log
  2. /usr/local/var/log/skhd/skhd.[out|err].log

To start the formulae at login via macOS' launchctl:

$ brew services start chunkwm
$ brew services start skbd

Setting up the rc-files

chunkwm

The config file for chunkwm should be placed in your home directory: ~/.chunkwmrc and given the executable permissions:

$ chmod +x ~/.chunkwmrc

I've set up my config file (.chunkwmrc), based on the example provided by the project itself. chunkwm uses a plugin architecture. Three plugins (border, tiling, and ffm) are loaded and their behaviour/appearances are configured.

...
chunkc core::load border.so
chunkc core::load tiling.so
chunkc core::load ffm.so
...

skhd

The config file for skhd is the most important part since this is where we define how to navigate in chunkwm. Once again, the config file for skhd should be placed in your home directory: ~/.skhdrc. An example of the config file is also provided in the project repo. However, I've decided to create one for myself based on how I use i3. Here are the settings that I have in my config file:

Switching between Layouts

# enter fullscreen mode for the focused container
alt - f : chunkc tiling::window --toggle fullscreen

# change focus between tiling / floating windows
shift + alt - space : chunkc tiling::window --toggle float

# change layout of desktop
alt - e : chunkc tiling::desktop --layout bsp
alt - s : chunkc tiling::desktop --layout monocle

chunkwm supports the following three desktop layouts:

  1. To enable binary space partitioned (tiling) layout: alt + e
  2. To switch to monocle layout (full size windows stack on top of each others): alt + s
  3. To make a single window floats, shift + alt + space on the focused window

We can also trigger fullscreen with alt + f.

Basic layouts in chunkwm.

Focusing

# kill focused window
shift + alt - q : chunkc tiling::window --close

# change focus
alt - h : chunkc tiling::window --focus west
alt - j : chunkc tiling::window --focus south
alt - k : chunkc tiling::window --focus north
alt - l : chunkc tiling::window --focus east
alt - p : chunkc tiling::window --focus prev
alt - n : chunkc tiling::window --focus next

To focus on a window without moving the mouse cursor:

  • alt + h/j/k/l to move the focus to the left, lower, upper, right window.
  • alt + p/n to move the focus to previous or next window.
  • shift + alt + q to close a window.

Focusing on window without mouse.

Moving the Windows

# move focused window
shift + alt - h : chunkc tiling::window --warp west
shift + alt - j : chunkc tiling::window --warp south
shift + alt - k : chunkc tiling::window --warp north
shift + alt - l : chunkc tiling::window --warp east

alt - r : chunkc tiling::desktop --rotate 90

# move focused container to workspace
shift + alt - p : chunkc tiling::window --send-to-desktop prev
shift + alt - n : chunkc tiling::window --send-to-desktop next
shift + alt - 1 : chunkc tiling::window --send-to-desktop 1
shift + alt - 2 : chunkc tiling::window --send-to-desktop 2

The final part configures the keyboard shortcuts to move the windows around.

  • To move a focused window to the left, lower, upper, right: shift + alt + h/j/k/l
  • To rotate the desktop layout 90 degrees: alt + r
  • To move a focused window to the next desktop: shift + alt + n

Moving windows with chunkwm.

I think you already have some ideas what chunkwm/skhd can do. What I've shown on the above is just a tip of the iceberg and it can be overwhelming to setup. If you plan to create your own configs for the WM, I would suggest that you start with a small and simple configs and add "new features" when you see necessary.

Bonus

When I was using chunkwm I found that it is a bit inconvenient to navigate around without a quick way to lookup the ID and layout of the current desktop. For that, I've create a very simple bitbar plugin to display the current ID and layout on the menu bar. You can also restart/stop chunkwm and skhd services via the plugin. To install the plugin, just copy chunkwm_skhd.1s.sh to your bitbar plugins folder and do "Refresh all" from the bitbar menu.

f:id:shihanng:20171220185748g:plain


(edit: Jan 19, 2018) Added info about .chunkwmrc needs executable permissions. Thank you Zach Taylor for pointing that out.

*1:Since macOS does not provide APIs for windows management, as many other WMs for macOS, it will request permission access to the macOS' accessibility API.

*2:Both are written by the same author: Åsmund Vikane.