Werden wir Helden für einen Tag

Home | About | Archive

On Sway(WM)

Posted on May 1, 2023 by Chung-hong Chan

In order to understand the context of this blog post, I recommend reading the previous blog on StumpWM, AwesomeWM, and xmonad. But a quick summary is that I need a window manager that can only do two things: (1) can use strange emacs-style key combinations, e.g. C-. b and (2) can do run-or-raise (run a software if it is not running; raise that software to my attention otherwise). I actually don’t need any tiling because I prefer full screen. Of course, no input lag issue like StumpWM. In the previous blog, I said xmonad fits my use case. Why switch again?

After using xmonad for over a month, I know that I don’t know enough Haskell to customize it any further. I at least know some Common Lisp and lua to hack StumpWM and AwesomeWM. All of my xmonad “customizations” so far were stealing things off github or guess work. I can’t comprehend my configuration file. Honestly, I have zero intention to learn Haskell just to configure xmonad. Without any Haskell knowledge, it also means that I don’t understand xmonad at all (the API documentation is not easy to read without any knowledge in Haskell, for example). Overall, I am not 100% happy with xmonad. For example, I can never get things as fundamental as the darn xmobar to work on full screen. Also, there is a weird bug related to right click on Firefox (sometimes, the right click contextual menu disappears automatically; can “refresh” it by changing the xmonad layout). I am pretty sure it is an issue of xmonad, but I don’t know enough Haskell to fix it. See, I am such a bad software user.

So now, what’s next? My choice is Sway. I think it’s better to write it as SwayWM, because searching for “sway” will probably give you Microsoft Sway. But let’s say Sway more to purge Microsoft’s search engine optimization.

This choice was made mainly because of this insightful post by Troels Henriksen. It actually addresses my first requirement of using strange emacs-style key combinations. A quick summary is this: By default, Sway (and its predecessor i3) doesn’t support these emacs-(or Ratpoison-, or GNU Screen-, or Tmux-, or StumpWM-)style key combinations. Similar to AwesomeWM, it uses just one “modifier key” ($mod), usually gets mapped to the Super key. However, Sway has a VI-like modal configuration, which can be defined to do whatever one wants. Mode can be triggered by a two-key combination such as C-t (the default of StumpWM and Ratpoison). In order to make a mode works like StumpWM/Ratpoison, the trick is to do an action and then immediately switch back to the “default” mode. In the default configuration file, there is a defined mode called “resize”, which can be triggered by $mod+r. I can just modify that to make it works for me.

Another requirement is “run-or-raise”. Actually, I’ve come to realize that I actually don’t need to “run-or-raise”. What I need is just “raise” (or in Sway’s lingo: focus), if the program has been started by default. I also find that I only use “run-or-raise” for maybe just 4 things: emacs, firefox, terminal, and Spotify. However, it is still nice if I can have a working implementation of “run-or-raise”. Sway by default doesn’t have native “run-or-raise” support like StumpWM and xmonad. However, as Sway is mainly controlled through messages and there is a shell program called swaymsg to send those messages, I can emulate “run-or-raise”. For example, to “run or raise” Firefox, I can do this: exec swaymsg "[app_id=firefox] focus" || exec firefox. It is just like bash: If sending a message to focus the thing with app_id=firefox fails (i.e. with a non-zero exit code), execute the shell command firefox. Functionally, it is just run-or-raise.

I also like the fact that I can discover what I am doing myself. For example, non-Wayland software doesn’t have an app_id and emacs is one such software. swaymsg -t get_tree can show me all the relevant information as a json file, representing what Sway is seeing. And man 5 sway is easy to read (also available online). I am able to experiment things on my shell, like typing: swaymsg "[instance=emacs] focus". I have a REPL, similar to StumpWM’s swank.

In the end, I hack together a “stumpwm” mode in Sway like this and it works quite well for me:

mode "stumpwm" {
     bindsym Return mode "default"
     bindsym Escape mode "default"
     bindsym g mode "default"
     bindsym Control+g mode "default"
     bindsym c exec $term; mode "default"
     bindsym f fullscreen; mode "default"
     bindsym Shift+c reload; mode "default"
     bindsym bracketright exec rofi -modi drun -show drun; mode "default"
     bindsym n focus left; mode "default"
     bindsym p focus right; mode "default"
     bindsym b exec swaymsg "[app_id=firefox] focus" || exec firefox; mode "default"
     bindsym e exec swaymsg "[instance=emacs] focus" || exec emacsclient -c; mode "default"
bindsym Control+period mode "stumpwm"
workspace_layout tabbed

Of course, it is not perfect. Unlike StumpWM or xmonad, typing C-. and then pressing something not defined in the mode still keeps me in the “stumpwm” mode. But one nice thing is that I have some visual clue in the menu bar (thanks god, I have a working menu bar by default!) so that I know I am still in the “stumpwm” mode. I can just quit, by using the emacs panic button C-g (or g or Return or Escape).

An added benefit of Sway is that it is a Wayland compositor (not X11). So far, I am quite happy with Sway. Let’s see how long this happiness can hold.

Powered by Jekyll and profdr theme