Skip to content

rwm 2.0.0

Latest
Compare
Choose a tag to compare
@ntBre ntBre released this 20 Jan 01:47
f119600

This release has been a long time coming! The biggest change here is moving away from the compiled dwm-style config to a standalone config file. Initially I planned to use TOML as so many Rust projects do, but I wanted to preserve the dynamic aspects of the dwm config, like setting tags with left shift (1 << 3) and marking all tags with bitwise negation (~0) 1. Initially I wrote my own config language called fig but decided this would be too painful to support and switched to Lua. I'm not actually that familiar with Lua, but it was easy to embed with mlua and the syntax is straightforward enough. Lua is currently only used as a deserialization format for loading the config at startup, but it's obviously a full scripting language and could lead to opportunities for more runtime dynamism in the future.

The other major change is the inclusion of several dwm patches that I like in my own config. All of these (except the pertag patch), can easily be disabled by removing the relevant bindings from your config. Both of these changes are discussed more fully down below.

Finally, intermixed with these user-facing changes, are many internal improvements. There's still a ton of C-style unsafe code, but the amount has dropped a bit. There's also a new test (not a test suite, a single new test) that ensures the program at least builds, runs, and can handle receiving a single event. My attempts to extend this into a true test suite didn't go very well, but hopefully this can be improved in the future.

Thanks everyone for the support here and on YouTube! I've been using rwm as my daily driver for the past ~4 months now, and I think these changes make it a much nicer window manager to use. If you give it a try and run into any issues, please feel free to open an issue!

What's Changed

New config format

As mentioned above, rwm now has a config file read from $XDG_CONFIG_HOME/rwm/config.lua or $HOME/.config/rwm/config.lua. This file is evaluated in a context populated initially by the src/config.lua file from the repository and by adding useful X11 symbols from src/config/env.rs. rwm deserializes the rwm table after loading all of this configuration to get its Config struct, so the main job of your config.lua file is to update fields of this table. For a simple example, you could patch a couple of basic options:

rwm.resize_hints = true
rwm.fonts = {"monospace:size=12"}

Or you can write functions and loops to accomplish what you need:

-- Look for key collisions and replace any conflicts instead of appending. If
-- you actually want multiple behaviors on the same key, just call
-- `table.insert` directly
function locate_key (o)
   for i, k in ipairs(rwm.keys) do
	  if k.keysym == o.keysym and k.mod_ == o.mod_ then
		 return i
	  end
   end
   return false
end

for _, key in ipairs(keys) do
   idx = locate_key(key)
   if idx then
	  rwm.keys[idx] = key
   else
	  table.insert(rwm.keys, key)
   end
end

(These examples are duplicated from the README. This one in particular may be useful for adding custom key bindings)

ghostty came out while I was working on these changes, and their philosophy of having the default config work out of the box inspired me to take this approach. If you don't even have a config.lua file, rwm will still launch normally and use the default values, which are mostly drawn from dwm. Then you can iteratively patch your config.lua file and restart rwm without having to recompile. That workflow was the goal of these changes.

dwm patches

rwm is opinionated. I want to use it as my daily driver without having to apply or maintain a set of separate patches. As a result, I applied the patches that I used in my build of dwm:

  • systray for a system tray
  • swallow for window swallowing
  • pertag for per-tag layouts and other settings
  • scratchpad for a persistent but hidable scratch terminal
  • stacker (partial) for moving windows up and down the stack

Again, all of these can be "disabled" by simply not binding their functions or functionality in your config file, with the exception of pertag. I didn't really realize that about pertag until I was preparing for the release, but after trying pertag, I really didn't like going back to the default non-per-tag behavior. If you try it and don't like it, open an issue, and I'll try to gate it behind a config option too.

macOS support

Thanks to the report in #20, there is now a low level of support for macOS. I haven't tried this myself, but based on the comments there, rwm can be built on Mac and run inside of XQuartz.

Other changes

Full Changelog: 1.0.1...2.0.0

  1. This is a slightly touchy example because Lua doesn't have true integers. This means that you can't actually write ~0 in the new config file, unless you mean -1. To get all the bits set in a u32 in Rust, you need to use math.floor(2^32 - 1) in Lua, or the all_tags variable included in the base environment for this purpose.