<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title>Isaac Freund's Blog</title><link href="https://isaacfreund.com/blog/"/><link rel="self" href="https://isaacfreund.com/blog/feed.xml" type="application/atom+xml"/><id>https://isaacfreund.com/blog/feed.xml</id><author><name>Isaac Freund</name><email>mail@isaacfreund.com</email></author><updated>2026-03-15T00:00:00Z</updated><entry><title>Separating the Wayland Compositor and Window Manager</title><link href="https://isaacfreund.com/blog/river-window-management/"/><id>https://isaacfreund.com/blog/river-window-management/</id><published>2026-03-15T00:00:00Z</published><updated>2026-03-15T00:00:00Z</updated><content type="html">&lt;p&gt;Traditional Wayland compositors have a monolithic architecture that combines the
compositor and window manager into a single program. This has the downside of
requiring Wayland window managers to do the significant work of implementing an
entire Wayland compositor as well.&lt;/p&gt;
&lt;p&gt;The new 0.4.0 release of &lt;a href="/software/river/"&gt;river&lt;/a&gt;, a non-monolithic Wayland compositor, breaks
from this traditional architecture and splits the window manager into a separate
program. There are already &lt;a href="https://codeberg.org/river/wiki/src/branch/main/pages/wm-list.md"&gt;many window managers&lt;/a&gt; compatible with river.&lt;/p&gt;
&lt;p&gt;The stable &lt;a href="/docs/wayland/river-window-management-v1/"&gt;river-window-management-v1&lt;/a&gt; protocol gives window managers full
control over window position, keybindings, and all other window management
policy while river itself provides frame-perfect rendering, good performance,
and all the low-level plumbing required.&lt;/p&gt;
&lt;p&gt;This blog post gives a high level overview of the design decisions behind this
protocol. This is roughly the same information I presented in my &lt;a href="https://fosdem.org/2026/schedule/event/GR8BFE-separating_the_wayland_compositor_and_window_manager/"&gt;FOSDEM 2026 Talk&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Display Server, Compositor, Window Manager&lt;/h2&gt;
&lt;p&gt;The traditional Wayland architecture combines three separate roles in the
compositor process:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Display Server: Route input events from the kernel to windows and give the
kernel buffers to display.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Compositor: Combine all buffers from visible windows into a single buffer to be
displayed by the kernel.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Window Manager: Arrange windows, define keybindings, other user-facing behavior.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To understand why Wayland compositors thus far have chosen to combine these
roles, it is first necessary to understand some of the fundamental problems with
X11’s architecture that Wayland was designed to solve.&lt;/p&gt;
&lt;p&gt;With the X11 protocol, the display server is a separate process from the
compositor and window manager:&lt;/p&gt;
&lt;img src="/blog/river-window-management/x11.svg" width="60%"/&gt;
&lt;p&gt;Following the steps taken from a user clicking on a button in a window to the
change in the window’s displayed content is quite informative. Referring to the
numbers in the diagram above:&lt;/p&gt;
&lt;ol start="0"&gt;
&lt;li&gt;
&lt;p&gt;The user clicks on a button in a window.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The kernel sends an input event to the display server.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The display server decides which window to route the input event to.
Already there is a problem here: since the display server is not aware
of the compositor’s scene graph it cannot be 100% sure which window
is rendered under the user’s mouse at the time of the click. The
display server makes its best guess and sends the event to a window.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The window submits a new buffer to the display server.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The display server passes the window’s new buffer on to the compositor.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The compositor combines the window’s new buffer with the rest of the user’s
desktop and sends the new buffer to the display server.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The display server passes the compositor’s new buffer to the kernel.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;With this architecture, the display server is acting as an unnecessary
middle-man between the kernel, X11 windows, and compositor. This results in
unnecessary roundtrips between the display server and compositor, adding
latency to every frame.&lt;/p&gt;
&lt;p&gt;The traditional Wayland architecture eliminates these unnecessary roundtrips
and solves the input routing problem mentioned in step 2. by combining the
display server and compositor into a single process:&lt;/p&gt;
&lt;img src="/blog/river-window-management/trad-wayland.svg" width="80%"/&gt;
&lt;p&gt;Traditionally, Wayland compositors have taken on the role of the window manager
as well, but this is not in fact a necessary step to solve the architectural
problems with X11. Although, I do not know for sure why the original Wayland
authors chose to combine the window manager and Wayland compositor, I assume it
was simply the path of least resistance. It is not trivial to design a window
management protocol that keeps all the advantages of Wayland, but it’s certainly
possible.&lt;/p&gt;
&lt;h2&gt;Window Management Protocol Design Constraints&lt;/h2&gt;
&lt;p&gt;The &lt;a href="/docs/wayland/river-window-management-v1/"&gt;river-window-management-v1&lt;/a&gt; protocol is designed to give window managers
maximum control without losing any of the key advantages of Wayland.
Specifically, the window management protocol must not require a roundtrip every
frame or every input event. There should be no input latency penalty compared to
the traditional monolithic Wayland architecture when, for example, typing into a
terminal emulator or playing a game.&lt;/p&gt;
&lt;p&gt;Furthermore, the Wayland ideal of “frame perfection” must be upheld. To
illustrate what frame perfection means in the context of window management,
consider the following example: several windows are in a tiled layout taking up
the entire display area and a new window is opened. The window manager decides
to add the new window to the tiled layout, resizing and rearranging the existing
windows to make space.&lt;/p&gt;
&lt;p&gt;In this case, frame perfection means that the user must not see a frame where
there is a gap in the tiled layout or where windows are overlapping and have
dimensions that do not fit cleanly with their neighbors. Achieving frame
perfection here requires waiting to render the new state until all windows have
submitted buffers with the newly requested dimensions.&lt;/p&gt;
&lt;p&gt;Note however that frame perfection is only achievable if the windows are drawn
by well-implemented programs. The compositor cannot delay rendering the new
state forever while waiting for windows to submit new buffers, delaying too long
makes things feel less responsive to the user rather than smoother. To solve
this the compositor uses a short timeout. If windows are too slow, frame
perfection is not possible.&lt;/p&gt;
&lt;h2&gt;Window Management State Machine&lt;/h2&gt;
&lt;p&gt;The &lt;a href="/docs/wayland/river-window-management-v1/"&gt;river-window-management-v1&lt;/a&gt; protocol divides the state managed by the
window manager into two disjoint categories: window management state and
rendering state.&lt;/p&gt;
&lt;p&gt;Window management state influences the communication between the compositor and
individual windows. It includes window dimensions, fullscreen
state, keyboard focus, keyboard bindings, etc.&lt;/p&gt;
&lt;p&gt;Rendering state on the other hand only affects the rendered output of the
compositor and does not influence communication between the compositor and
individual windows. It includes the position and rendering order of windows,
server-side decorations, window cropping, etc.&lt;/p&gt;
&lt;p&gt;To achieve frame perfection, the modifications made to this state by the window
manager are batched into atomic updates by the &lt;a href="/docs/wayland/river-window-management-v1/"&gt;river-window-management-v1&lt;/a&gt;
protocol. Changes to window management state can only occur during a “manage
sequence” and changes to rendering state can only occur during a “render
sequence.”&lt;/p&gt;
&lt;img src="/blog/river-window-management/state-machine.svg" width="100%"/&gt;
&lt;p&gt;As seen in the state machine above, the compositor initiates manage/render
sequences and no roundtrip with the window manager is required when no
window-management-related state has changed. In other words, the window manager
stays idle while the user is, for example, typing into a terminal and is woken
up again when, for example, the user triggers a window manager keybinding or a
new window is opened.&lt;/p&gt;
&lt;p&gt;At the same time, frame perfection is possible even with complex tiled layouts
or server-side decorations rendered by the window manager. The compositor
handles all the synchronization work with the windows and the window manager
only needs to, for example, adjust the position of windows or size of its server
side decorations to adapt to the new window dimensions.&lt;/p&gt;
&lt;p&gt;This state machine is not really a new idea, something similar can be found
hiding inside most existing Wayland compositors including &lt;a href="https://codeberg.org/river/river-classic/"&gt;river-classic&lt;/a&gt; and
&lt;a href="https://github.com/swaywm/sway"&gt;sway&lt;/a&gt; for example. In a way, this state machine is a clarification and
formalization of the internal architecture used by older river versions. It is
the result of 6+ years of experience working on river and slowly refining the
architecture over time.&lt;/p&gt;
&lt;h2&gt;Motivation&lt;/h2&gt;
&lt;p&gt;Separating the Wayland compositor and window manager greatly lowers the barrier
to entry for writing a Wayland window manager. Window manager authors can focus
on window management policy without needing to implement an entire Wayland
compositor as well. While libraries such as &lt;a href="https://gitlab.freedesktop.org/wlroots/wlroots"&gt;wlroots&lt;/a&gt; make writing a compositor
somewhat easier, it remains a great deal of work. Writing a Wayland compositor
is not a weekend project, but with the new &lt;a href="/docs/wayland/river-window-management-v1/"&gt;river-window-management-v1&lt;/a&gt; protocol
writing a basic but usable Wayland window manager over the weekend is now very
possible.&lt;/p&gt;
&lt;p&gt;The window manager developer experience is also greatly improved. A window
manager crash does not cause the Wayland session to be lost. Window managers can
be restarted and switched between. Debugging a window manager is much less
of an ordeal than debugging a Wayland compositor. Anyone who has written a
Wayland compositor knows the pain of debugging issues that only reproduce when
running on “bare metal” (i.e. using DRM/KMS directly), one might be forced to
ssh in from a different computer to figure out what has gone wrong.&lt;/p&gt;
&lt;p&gt;Furthermore, window managers can be implemented in slow, high-level,
garbage-collected languages without sacrificing compositor performance/latency.
Having a garbage collector in the compositor is great way to miss frame
deadlines and cause input latency spikes. However, since the
&lt;a href="/docs/wayland/river-window-management-v1/"&gt;river-window-management-v1&lt;/a&gt; protocol does not require a round-trip with the
window manager every frame, having a garbage collector in the window manager
does not really matter. I don’t have any performance issues daily driving my
slow, garbage-collected window manager on a &amp;gt;10 year old ThinkPad x220.&lt;/p&gt;
&lt;p&gt;Wayland currently does not come close to the diversity of X11 window managers.
I believe that separating the Wayland compositor and window manager will change
this and I see the beginnings of this change with the &lt;a href="https://codeberg.org/river/wiki/src/branch/main/pages/wm-list.md"&gt;15 window managers&lt;/a&gt;
already written for river!&lt;/p&gt;
&lt;h2&gt;Limitations&lt;/h2&gt;
&lt;p&gt;The &lt;a href="/docs/wayland/river-window-management-v1/"&gt;river-window-management-v1&lt;/a&gt; protocol does not support use-cases that deviate
from the traditional, 2D desktop paradigm. This means no VR support for example.&lt;/p&gt;
&lt;p&gt;Crazy visual effects like wobbly windows are also out of scope for river currently,
though simple animations already work well. I am open to exploring custom shaders
to give window managers more control over rendering eventually but don’t expect
that to happen for a year or two at the earliest, there are other priorities for now.&lt;/p&gt;
&lt;p&gt;I am not aware of any limitations river places on window management policy that
cannot be resolved by extending the protocol. If you are developing a window
manager and have a use-case that river does not yet support please &lt;a href="https://codeberg.org/river/river/issues/new/choose"&gt;open an issue&lt;/a&gt;
and we will figure out how to get it supported!&lt;/p&gt;
&lt;h2&gt;Roadmap&lt;/h2&gt;
&lt;p&gt;With the 0.4.0 release, river is already more than featureful enough to daily
drive in combination with a &lt;a href="https://codeberg.org/river/wiki/src/branch/main/pages/wm-list.md"&gt;window manager&lt;/a&gt; of your choice. Furthermore, the
&lt;a href="/docs/wayland/river-window-management-v1/"&gt;river-window-management-v1&lt;/a&gt; protocol is stable, we do not break window
managers.&lt;/p&gt;
&lt;p&gt;The best way to get a sense of what features are planned to be added in the
future is to look at the &lt;a href="https://codeberg.org/river/river/issues?q=&amp;amp;type=all&amp;amp;state=open&amp;amp;labels=848511"&gt;accepted label&lt;/a&gt; on our issue tracker.&lt;/p&gt;
&lt;p&gt;As far as what needs to happen before river 1.0.0, I want to explore some ideas
for how to improve the UX of starting and switching between river compatible
window managers. All window managers written for river 0.4.0 will remain
compatible with river 1.0.0 and beyond, but I may need to make minor breaking
changes to river’s CLI depending on how those plans work out. In any case,
expect the next major river release to be 1.0.0!&lt;/p&gt;
&lt;h2&gt;Donate&lt;/h2&gt;
&lt;p&gt;Unfortunately, the current pace of river’s development is not sustainable
without more financial support. If my work on river adds value to your life
please consider setting up a recurring donation through &lt;a href="https://liberapay.com/ifreund"&gt;liberapay&lt;/a&gt;. You can
also support me with a one-time or monthly donation on &lt;a href="https://github.com/sponsors/ifreund"&gt;github sponsors&lt;/a&gt; or
&lt;a href="https://ko-fi.com/ifreund"&gt;ko-fi&lt;/a&gt; though I prefer liberapay as it is run by a non-profit. Thank you for
your support!&lt;/p&gt;
&lt;h2&gt;Gallery&lt;/h2&gt;
&lt;p&gt;To make all this talk about window managers a bit more tangible, please enjoy
these screenshots of window managers running under river. Note that this
selection is heavily biased towards the most visually interesting window managers,
there are plenty of other excellent &lt;a href="https://codeberg.org/river/wiki/src/branch/main/pages/wm-list.md"&gt;window managers&lt;/a&gt; to choose from!&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/roblillack/canoe"&gt;Canoe&lt;/a&gt; - Stacking window manager with classic look and feel:&lt;/p&gt;
&lt;img src="/blog/river-window-management/canoe.png" width="100%"/&gt;
&lt;p&gt;&lt;a href="https://code.tvl.fyi/about/tools/emacs-pkgs/reka"&gt;reka&lt;/a&gt; - An Emacs-based window manager for river (similar to EXWM):&lt;/p&gt;
&lt;img src="/blog/river-window-management/reka.png" width="100%"/&gt;
&lt;p&gt;&lt;a href="https://git.sr.ht/~leon_plickat/tarazed"&gt;tarazed&lt;/a&gt; - A powerful and distraction-free desktop experience:&lt;/p&gt;
&lt;img src="/blog/river-window-management/tarazed.png" width="100%"/&gt;
&lt;p&gt;&lt;a href="https://codeberg.org/sivecano/rhine"&gt;rhine&lt;/a&gt; - Recursive and modular window management with animations:&lt;/p&gt;
&lt;video autoplay loop controls width="100%"&gt;
&lt;source src="/blog/river-window-management/rhine.mp4" type="video/mp4"/&gt;
&lt;/video&gt;</content></entry><entry><title>River 0.3.0, Waylock 1.0.0, Status Update</title><link href="https://isaacfreund.com/blog/river-0.3-waylock-1.0/"/><id>https://isaacfreund.com/blog/river-0.3-waylock-1.0/</id><published>2024-04-16T00:00:00Z</published><updated>2024-04-16T00:00:00Z</updated><content type="html">&lt;p&gt;Things have been a bit quiet on this blog recently.
I spent most of 2023 writing my bachelor’s thesis and finishing up my degree.
That’s all wrapped up now though,
which means I’ve finally had time to wrap up some other things for my open source projects.&lt;/p&gt;
&lt;h2&gt;River 0.3.0&lt;/h2&gt;
&lt;p&gt;The river 0.3.0 release has finally been &lt;a href="https://codeberg.org/river/river/releases/tag/v0.3.0"&gt;tagged&lt;/a&gt;!
This one’s been in the pipeline for quite a while,
it’s been over a year since 0.2.0 was released and river has seen significant improvements since then.
The past few months I’ve done my best to fix as many bugs as possible
but a non-bugfix release always entails new code reaching a lot of people with diverse setups.
If you find a bug in river please &lt;a href="https://codeberg.org/river/river/issues/new/choose"&gt;open an issue&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The biggest change in river 0.3.0 is not immediately visible:
river 0.3.0 uses the wlroots scene graph API and has see a lot of internal improvements related to that transition.
An initial version of the wlroots scene graph API was landed in wlroots over two years ago and has seen steady improvement since.
I helped to push it forward in upstream wlroots over the years and am very happy to finally be using it in river.
It brings finely-grained damage tracking and other performance optimizations to river which should positively
impact battery life and make running river with software rendering bearable.&lt;/p&gt;
&lt;p&gt;Aside from that more behind-the-scenes work, river 0.3.0 brings many nice usability enhancements.
There is now a “rules system” for automatically assigning tags to new windows and performing other actions.
The input-method-v2 and text-input-v3 protocols are supported,
allowing use of alternative input software for users that speak a language not well supported by western keyboards.
River also now has basic support for drawing tablet input.
For a full list of changes, see the release notes &lt;a href="https://codeberg.org/river/river/releases/tag/v0.3.0"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Thank you to everyone who has contributed code and bug reports to river!
River would not be where it is today without you.&lt;/p&gt;
&lt;p&gt;In other river news, the upstream river repository has moved to &lt;a href="https://codeberg.org/river/river"&gt;https://codeberg.org/river/river&lt;/a&gt;.
Github is a proprietary platform with interests increasingly misaligned with my values.
Free and open source software like river should not require contributors to have a github account or interact with github in any way.
There is still a read-only mirror of the river repository on github for now to ease the transition,
it may be dropped eventually if/when I decide to delete my personal github account.&lt;/p&gt;
&lt;p&gt;River also now has a page &lt;a href="/software/river"&gt;here&lt;/a&gt; on my website,
I’ve written a bit about my future plans for river there if you’re curious :)
River also has gained a written &lt;a href="https://codeberg.org/river/river/src/branch/master/CODE_OF_CONDUCT.md"&gt;Code of Conduct&lt;/a&gt;
documenting the existing standards and moderation practice.
Luckily, we have a wonderful community and haven’t yet had to deal with any notable unacceptable behavior I’m aware of.&lt;/p&gt;
&lt;h2&gt;Waylock 1.0.0&lt;/h2&gt;
&lt;p&gt;There haven’t been any breaking changes to waylock in over a year and I’m happy with its feature set.
Therefore, I’ve tagged a stable 1.0 &lt;a href="https://codeberg.org/ifreund/waylock/releases/tag/v1.0.0"&gt;release&lt;/a&gt;.
The only change since the last waylock release is the addition of the &lt;code&gt;-ready-fd&lt;/code&gt; flag contributed by tiosgz.
This is an alternative to the &lt;code&gt;-fork-on-lock&lt;/code&gt; flag for notification that waylock has successfully locked the session.
The new flag is compatible with the readiness notification protocol used by the &lt;code&gt;s6&lt;/code&gt; and &lt;code&gt;dinit&lt;/code&gt; service managers
as well as being more flexible than &lt;code&gt;-fork-on-lock&lt;/code&gt; for use in scripting.&lt;/p&gt;
&lt;p&gt;Don’t be alarmed if waylock development slows down to a snail’s pace after this release.
I consider it to be feature complete and as long as there are no bugs found there is little reason to make changes.
I will of course continue to update it to be compatible with new Zig releases as needed.&lt;/p&gt;
&lt;h2&gt;Website Rewrite&lt;/h2&gt;
&lt;p&gt;You may have noticed that my website looks a bit different than it used to and has a few new pages.
I’d been wanting to add some new pages for a while but had entirely forgotten how to use hugo.
Since I didn’t like hugo very much in practice anyways,
I decided to switch to something more transparent and chose &lt;a href="https://bagatto.co"&gt;Bagatto&lt;/a&gt;.
It has been lovely to work with and I’m much more confident that I’ll remember how to modify and extend my website years from now.
Source code &lt;a href="https://codeberg.org/ifreund/website"&gt;here&lt;/a&gt; for the curious.
This was also my first time using &lt;a href="https://janet-lang.org"&gt;Janet&lt;/a&gt; (or any lispy language) for anything “real” and I found the experience very pleasant.&lt;/p&gt;
&lt;h2&gt;Donate&lt;/h2&gt;
&lt;p&gt;If my work on river and waylock adds value to your life and you’d like to
support me financially you can find donation information &lt;a href="/donate/"&gt;here&lt;/a&gt;.&lt;/p&gt;</content></entry><entry><title>May 2022 Status Update</title><link href="https://isaacfreund.com/blog/2022-05/"/><id>https://isaacfreund.com/blog/2022-05/</id><published>2022-05-23T00:00:00Z</published><updated>2022-05-23T00:00:00Z</updated><content type="html">&lt;p&gt;Welcome back to my blog, it’s been a while.
Over the past few months I’ve been busier with other aspects of my life than expected, hence the lack of status updates.
Despite that, I’ve made progress on various fronts.&lt;/p&gt;
&lt;h2&gt;Waylock 0.4.0 and Rewrite&lt;/h2&gt;
&lt;p&gt;Yesterday I finally released &lt;a href="https://github.com/ifreund/waylock/releases/tag/v0.4.0"&gt;waylock 0.4.0&lt;/a&gt; which has been rewritten in &lt;a href="https://ziglang.org/"&gt;Zig&lt;/a&gt;.
It now uses the &lt;a href="https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/131"&gt;ext-session-lock-v1&lt;/a&gt; protocol,
which I worked on earlier this year and discussed in my &lt;a href="https://isaacfreund.com/blog/2022-02/"&gt;February 2022&lt;/a&gt; update.
Unfortunately, &lt;a href="https://github.com/riverwm/river"&gt;river&lt;/a&gt; itself does not yet support this protocol.
The work is already done and there’s been a &lt;a href="https://github.com/riverwm/river/pull/497"&gt;pull request&lt;/a&gt; implementing it open for quite some time,
the only thing I’m waiting on is a wlroots release including the session lock implementation.
I intend to spend some more time working on upstream wlroots to help tie up various loose ends before 0.16.0 and further develop the scene graph API.&lt;/p&gt;
&lt;p&gt;Rewriting waylock from Rust into Zig has made me think once again about the different trade-offs made by the two languages and their ecosystems.
Looking at the Rust code I wrote several years ago I am rather appalled by how many dependencies it has.
If I’ve managed to use the cargo tooling correctly, I count 48 crates that waylock 0.3.5 depends on in addition to linking the system libxkbcommon and PAM libraries.
That is a &lt;em&gt;lot&lt;/em&gt; of code running inside my application that I never read let alone seriously audited.&lt;/p&gt;
&lt;p&gt;To compare, waylock 0.4.0 depends only on libwayland, libxkbcommon, and PAM as well as thin Zig bindings I have written to make their APIs a bit more type safe.&lt;/p&gt;
&lt;p&gt;This is also reflected in the binary size of waylock 0.3.5 vs 0.4.0.
A stripped release build of the Rust version weighs in at 1.7MiB or, if the native Rust Wayland implementation is replaced by linking libwayland, 1.6MiB.
A stripped “release-safe” build of the Zig version with all runtime safety checks and assertions enabled is just 69KiB.&lt;/p&gt;
&lt;p&gt;If this makes you wonder what all that extra code in the Rust version was doing, waylock 0.3.5 did have a few more features than 0.4.0 such as reading a config file.
However, even after removing the config file feature out of curiosity, the Rust version was still 1.5MiB.&lt;/p&gt;
&lt;p&gt;The only real answer I have to this question is that the Rust version and its dependencies do a lot of abstraction,
and that abstractions are seldom “zero cost” in practice despite what people may tell you.&lt;/p&gt;
&lt;h2&gt;zig-wayland Improvements&lt;/h2&gt;
&lt;p&gt;Rewriting waylock in Zig also led me to reexamine some aspects of &lt;a href="https://github.com/ifreund/zig-wayland"&gt;zig-wayland&lt;/a&gt;,
particularly regarding its usage in client applications.
The scanner (which generates zig bindings from XML protocol specifications) now requires the user to explicitly request
code generation for each global Wayland interface used.
For example, the application must now call e.g.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;scanner.generate(&amp;quot;wl_compositor&amp;quot;, 4);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;as part of its build process,
passing the global interface name and the version for which to generate code.
In this example the wl_surface.offset request would not be generated as it is only available since version 5.&lt;/p&gt;
&lt;p&gt;(If you’re not familiar with Wayland, wl_surface is created through wl_compositor and inherits its version,
see the Wayland &lt;a href="https://wayland.freedesktop.org/docs/html/ch04.html#sect-Protocol-Versioning"&gt;docs on protocol versioning&lt;/a&gt; for more information.)&lt;/p&gt;
&lt;p&gt;This solves the outstanding forward compatibility issue and allows building against newer system Wayland protocol versions than the application supports.&lt;/p&gt;
&lt;p&gt;The knowledge of what maximum version a client application supports at compile time allows us to make another improvement as well.
One of the most common Wayland client bugs I’ve seen in clients using libwayland is passing the interface version received from the server
in the wl_registry.global event straight to wl_registry_bind().
A forwards compatible client must check the version advertised by the server against the maximum version the client supports, otherwise
the client will be terminated when the server sends events unknown to the client.&lt;/p&gt;
&lt;p&gt;This is a particularly nasty bug because everything will work fine until your software is around long enough for Wayland protocols to evolve.
For example, Chromium &lt;a href="https://chromium.googlesource.com/chromium/src/+/dd4c3ddadbb9869f59cee201a38e9ca3b9154f4d"&gt;recently fixed&lt;/a&gt; this bug.
I’ve also written this bug a few times myself, including in previous Rust versions of waylock.&lt;/p&gt;
&lt;p&gt;That’s why it’s pretty cool that zig-wayland now makes this bug impossible.
Since we know the maximum version the client supports at build time, it’s trivial to insert the required version check into the generated code
for zig-wayland’s wl_registry_bind() equivalent as a safeguard.&lt;/p&gt;
&lt;h2&gt;River Progress&lt;/h2&gt;
&lt;p&gt;River has also gained some nice new features recently:&lt;/p&gt;
&lt;p&gt;Automatic cursor hiding after a timeout or when typing was contributed by Duncan Overbruck.
On moving the cursor after it has been hidden it will be shown again.&lt;/p&gt;
&lt;p&gt;Initial support for the idle-inhibit protocol was contributed by dfangx.
No longer shall swayidle put your monitor to sleep while watching a movie in mpv!&lt;/p&gt;
&lt;p&gt;Mapping of lid and tablet switches was contributed by Peter Kaplan.
Now you can have a command run when you close the lid of your laptop!&lt;/p&gt;
&lt;p&gt;Peter Kaplan also contributed a very nice feature for people switching between multiple keyboard layouts: layout independent mappings.
The riverctl map command has gained a -layout option taking an index into the list of layouts set with XKB_DEFAULT_LAYOUT.
If passed, keyboard input will always be interpreted using the given layout, ignoring the currently active xkb layout.&lt;/p&gt;
&lt;p&gt;Note that these features are not yet available in a released version of river, only on the git master branch.
I plan to release river 0.2.0 shortly after wlroots 0.16.0 is released.&lt;/p&gt;
&lt;p&gt;Thanks for reading and till next time!&lt;/p&gt;</content></entry><entry><title>February 2022 Status Update</title><link href="https://isaacfreund.com/blog/2022-02/"/><id>https://isaacfreund.com/blog/2022-02/</id><published>2022-02-11T00:00:00Z</published><updated>2022-02-11T00:00:00Z</updated><content type="html">&lt;p&gt;Hello again!
It’s been nearly a month and a half since my last status update.
Since I hope to fall into a monthly rhythm with these this is a decent start, look for the next one around the middle of March.
I’ve also gotten a proper &lt;a href="https://isaacfreund.com/blog/feed.xml"&gt;Atom Feed&lt;/a&gt; set up for this blog now for those of you using feed readers of some kind.&lt;/p&gt;
&lt;p&gt;I spent a fair bit of time over the past month an a half working on a better screenlocking protocol for Wayland.
This resulted in the ext-session-lock-v1 protocol which was merged into the upstream &lt;a href="https://gitlab.freedesktop.org/wayland/wayland-protocols/"&gt;wayland-protocols&lt;/a&gt; repository three weeks ago.
This marks the first upstream Wayland protocol I have written and the first protocol in the ext- namespace to be accepted into wayland-protocols!&lt;/p&gt;
&lt;p&gt;The ext-session-lock-v1 protocol makes it possible for lockscreens implemented outside of the Wayland compositor to be far more secure, compared to the status quo wlr-input-inhibitor-v1 plus wlr-layer-shell-v1 solution that has been used by &lt;a href="https://github.com/swaywm/swaylock"&gt;swaylock&lt;/a&gt; and &lt;a href="https://github.com/ifreund/waylock"&gt;waylock&lt;/a&gt; thus far.
Currently if, for example, swaylock crashes while the session is locked then the session will no longer be locked.
With ext-session-lock-v1, the session does not unlock if the client crashes.
Furthermore, hotplugging outputs is inherently racy with the current solution which means that a few frames of the unlocked session may be visible if a monitor is plugged in while the session is locked.
Again, with ext-session-lock-v1 this problem is solved.&lt;/p&gt;
&lt;p&gt;Many thanks to &lt;a href="https://emersion.fr"&gt;Simon Ser&lt;/a&gt; for the excellent code reviews of the protocol and &lt;a href="https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/3414"&gt;wlroots implementation&lt;/a&gt;, as well as for &lt;a href="https://github.com/swaywm/swaylock/pull/219"&gt;updating swaylock&lt;/a&gt; to use ext-session-lock-v1.
I’ve &lt;a href="https://github.com/riverwm/river/pull/497"&gt;implemented&lt;/a&gt; ext-session-lock-v1 for river but am waiting for the 0.16.0 wlroots release to merge it as river tracks the latest wlroots release not the master branch.
I’ve also started rewriting &lt;a href="https://github.com/ifreund/waylock"&gt;waylock&lt;/a&gt; from the ground up in Zig with a much higher focus on security and benefiting from the experience I’ve gained over the past 2 years of doing this stuff.
Until that work is complete I recommend using swaylock instead.&lt;/p&gt;
&lt;p&gt;The goal of this work is to ensure, to the best of my ability, that &lt;a href="https://www.jwz.org/"&gt;jwz&lt;/a&gt; doesn’t have to say &lt;a href="https://www.jwz.org/blog/2021/01/i-told-you-so-2021-edition/"&gt;“I told you so”&lt;/a&gt; about screen locking on my Wayland compositor.
Once the security problem has been satisfactorily solved I want to explore making fun graphics possible without compromising security, but that may take me a long time to get around to.&lt;/p&gt;
&lt;p&gt;I &lt;a href="https://github.com/riverwm/river/releases/tag/v0.1.3"&gt;released&lt;/a&gt; river 0.1.3 about a week ago.
It includes quite a few bug fixes, so if you’re not yet using river 0.1.3 and wlroots 0.15.1 I’d highly recommend upgrading.
I also decided to change river’s license from GPL-3.0-or-later to GPL-3.0-only with this release,
primarily because I decided that I do not feel comfortable licensing software under a hypothetical future license version which is outside my control.
What if I disagree with the changes made?
I’m happy with locking in on version 3 of the GPL for river as there’s no real need to worry about the compatibility benefits of the “or later” clause as river is not a library.&lt;/p&gt;
&lt;p&gt;That’s all for now, see you all in March!&lt;/p&gt;</content></entry><entry><title>2021 Year's End Status Update</title><link href="https://isaacfreund.com/blog/2021-years-end/"/><id>https://isaacfreund.com/blog/2021-years-end/</id><published>2022-01-01T00:00:00Z</published><updated>2022-01-01T00:00:00Z</updated><content type="html">&lt;p&gt;Hello all!
This is my first ever status update so I’ve ambitiously decided to cover all of 2021.
In the future I intend to write these updates on a monthly basis and provide a bit more detail.
Since so much has happened in the past year I’ll be leaving out a lot, but here are some of the highlights.&lt;/p&gt;
&lt;p&gt;In January I spent most of my time on &lt;a href="https://github.com/riverwm/river"&gt;river&lt;/a&gt;,
fixing bugs and implementing an experimental &lt;a href="https://github.com/riverwm/river/pull/202"&gt;river-options protocol&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://archive.fosdem.org/2021/"&gt;FOSDEM 2021&lt;/a&gt; took place online during first weekend of February and
I gave a &lt;a href="https://archive.fosdem.org/2021/schedule/event/zig_wayland/"&gt;talk&lt;/a&gt; on my type safe &lt;a href="https://ziglang.org"&gt;Zig&lt;/a&gt; bindings for wlroots/libwayland.
Around the same time I got sucked into Andrew Kelley’s work applying data oriented design principles to Zig’s Abstract Syntax Tree.
I collaborated with him on the data structure that became &lt;a href="https://zig.news/kristoff/struct-of-arrays-soa-in-zig-easy-in-userland-40m0"&gt;std.MultiArrayList&lt;/a&gt;
and contributed a significant amount of code to his &lt;a href="https://github.com/ziglang/zig/pull/7920"&gt;PR branch&lt;/a&gt;.
Andrew gave a &lt;a href="https://media.handmade-seattle.com/practical-data-oriented-design/"&gt;talk&lt;/a&gt; on this subject at Handmade Seattle later on in November which I highly recommend checking out if you haven’t seen it yet.&lt;/p&gt;
&lt;p&gt;In March I joined the team working on &lt;a href="https://www.tigerbeetle.com"&gt;TigerBeetle&lt;/a&gt; and got paid to write Zig code for the first time.
I also contributed to Andrew’s further application of data oriented design to the &lt;a href="https://github.com/ziglang/zig/pull/8266"&gt;ZIR memory layout&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In April my stalwart collaborator &lt;a href="https://leon_plickat.srht.site"&gt;Leon Plickat&lt;/a&gt; and I finally got the &lt;a href="https://github.com/riverwm/river/pull/112"&gt;river-layout protocol&lt;/a&gt; merged to master branch.
We’d been discussing and working on this off and on for ~6 months at that point so it was really great to get it merged and start daily driving it.
As is normal with such large changes, there were still some rough edges to be smoothed out and I &lt;a href="https://github.com/riverwm/river/pull/274"&gt;bumped the protocol to version 2 and removed the river-options protocol&lt;/a&gt; shortly afterwards.&lt;/p&gt;
&lt;p&gt;One of the critical missing features for river at this point in time was damage tracking support to improve performance and save battery life.
To remedy this I &lt;a href="https://github.com/riverwm/river/pull/296"&gt;implemented&lt;/a&gt; basic yes/no damage tracking in May.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://ziglang.org/download/0.8.0/release-notes.html"&gt;Zig 0.8.0&lt;/a&gt; was released in the first week of June, which included several improvements I made to Zig’s handling of linking libc.
These improvements directly affected users building river, solving a few long-standing issues on that front.
Around this time I also started to think about a first river release and resumed my effort to &lt;a href="https://github.com/void-linux/void-packages/pull/29288"&gt;properly package zig software for void Linux&lt;/a&gt;.
This lead to a series of zig patches to allow for cross compilation while linking system libraries and integration into void Linux’s build system.&lt;/p&gt;
&lt;p&gt;In July I focused on stabilizing and simplifying river’s behavior, aiming for consistency and predictability.
As part of this, I &lt;a href="https://github.com/riverwm/river/pull/359"&gt;further simplified our layout protocol&lt;/a&gt; and cleaned up all of river’s user-facing interfaces.
The goal was to get a first release out the door, but unfortunately exams got in the way.&lt;/p&gt;
&lt;p&gt;Throughout August and September I had relatively little time for my open source work as I was busy with exams at my university.
I did however manage to keep up with bug reports from river’s small but steadily growing number of users fairly well.
In retrospect, it was nice to allow bug reports to trickle in for another couple months before tagging the first release as the end result was much more polished.&lt;/p&gt;
&lt;p&gt;I ended up changing domains for my personal website and email from ifreund.xyz to isaacfreund.com after reading &lt;a href="https://www.spotvirtual.com/blog/the-perils-of-an-xyz-domain/"&gt;this post&lt;/a&gt; in October.
It makes me sad that this is the way things are, but I’d rather die on a different hill.
I set up &lt;a href="https://github.com/sponsors/ifreund"&gt;GitHub Sponsors&lt;/a&gt; and &lt;a href="https://liberapay.com/ifreund"&gt;Liberapay&lt;/a&gt; around this time and was pleasantly surprised to immediately see some support.
Thank you to all my current sponsors, you are helping make my open source work sustainable in the long term!&lt;/p&gt;
&lt;p&gt;On the river front, I spent October fixing every bug I could and finally tagged the &lt;a href="https://github.com/riverwm/river/releases/tag/v0.1.0"&gt;river 0.1.0 release&lt;/a&gt; on November 2nd.
If you haven’t yet seen my &lt;a href="https://isaacfreund.com/blog/river-intro"&gt;blog post introducing river&lt;/a&gt; you may want to check that out.
Later in November my focus shifted to helping push the new wlroots scene graph API forward, &lt;a href="https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/3250"&gt;getting tinywl using it&lt;/a&gt;
as well as &lt;a href="https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/3398"&gt;other&lt;/a&gt; &lt;a href="https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/3403"&gt;improvements&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This wlroots work carried on into December, when &lt;a href="https://gitlab.freedesktop.org/wlroots/wlroots/-/releases/0.15.0"&gt;wlroots 0.15.0&lt;/a&gt; was released.
As it so happened, &lt;a href="https://ziglang.org/download/0.9.0/release-notes.html"&gt;Zig 0.9.0&lt;/a&gt; was released only a few days later.
Thus, &lt;a href="https://github.com/riverwm/river/releases/tag/v0.1.1"&gt;river 0.1.1&lt;/a&gt; and &lt;a href="https://github.com/riverwm/river/releases/tag/v0.1.2"&gt;river 0.1.2&lt;/a&gt; were released in quick succession,
fixing several bugs and updating the wlroots and Zig version requirements.&lt;/p&gt;
&lt;p&gt;I also ended up starting and finishing a tiny new project in December, &lt;a href="https://github.com/ifreund/dumb_runtime_dir"&gt;dumb_runtime_dir&lt;/a&gt;,
to replace my older, more complex &lt;a href="https://github.com/ifreund/rundird"&gt;rundird&lt;/a&gt; project.
This is useful on systems that do not run logind, opting for a simpler alternative such as &lt;a href="https://sr.ht/~kennylevinsen/seatd"&gt;seatd&lt;/a&gt; instead.&lt;/p&gt;
&lt;p&gt;2021 was an action packed year for me, I’m very happy looking back on the progress I’ve made on river and the surrounding open source ecosystem.
Here’s to another year of work towards building my ideal Linux graphical environment in 2022!&lt;/p&gt;</content></entry><entry><title>Introducing River, a Dynamic Tiling Wayland Compositor</title><link href="https://isaacfreund.com/blog/river-intro/"/><id>https://isaacfreund.com/blog/river-intro/</id><published>2021-11-03T00:00:00Z</published><updated>2021-11-03T00:00:00Z</updated><content type="html">&lt;p&gt;In the spring of 2020 I found myself hooked on Wayland thanks to
&lt;a href="https://swaywm.org/"&gt;sway&lt;/a&gt; but increasingly frustrated with the
&lt;a href="https://i3wm.org/"&gt;i3&lt;/a&gt; style window management sway implements.
I tried several of the other more mature Wayland compositors
including &lt;a href="https://hub.darcs.net/raichoo/hikari"&gt;hikari&lt;/a&gt; and
&lt;a href="https://wayfire.org"&gt;Wayfire&lt;/a&gt; but didn’t enjoy them any more
than sway. I wanted dynamic tiling window management similar to
&lt;a href="https://dwm.suckless.org/"&gt;dwm&lt;/a&gt; but on Wayland and without dwm’s configuration
through patching the source code approach.&lt;/p&gt;
&lt;p&gt;As I had a newfound abundance of free time at home in front of
my computer thanks to the global pandemic that was ramping up
that spring, I decided to write my own Wayland compositor. Thus,
&lt;a href="https://github.com/riverwm/river"&gt;river&lt;/a&gt; was born.&lt;/p&gt;
&lt;h2&gt;Features&lt;/h2&gt;
&lt;p&gt;The core guiding principle in river’s design is that its behavior should
be predictable. This means keeping things as simple as possible, reducing
implicit state the user must keep in their head while using river.&lt;/p&gt;
&lt;p&gt;River’s window management is based on a linear stack of windows much like
dwm. These windows are arranged by a separate program called a layout
generator. Users are encouraged to write and share their own layout
generators, they are simply Wayland clients which implement a custom
river-layout-v3 protocol. You can find links to several nice ones on this
&lt;a href="https://github.com/riverwm/river/wiki/Community-Layouts"&gt;wiki page&lt;/a&gt;. River
also ships with a layout generator, rivertile, that provides a few simple
layouts for those who don’t need anything custom or fancy.&lt;/p&gt;
&lt;p&gt;Instead of traditional workspaces, river supports tags. Each window may be
assigned one or more tags and multiple tags may be displayed at once. Again,
this behavior is strongly influenced by dwm.&lt;/p&gt;
&lt;p&gt;All configuration and control of river happens at runtime through the riverctl
tool. It can be used to create keybindings, move focus between windows,
set the border color, etc. River doesn’t have any traditional configuration
file, instead it runs an arbitrary executable on startup which is generally
a shell script invoking riverctl to setup the user’s desired configuration.&lt;/p&gt;
&lt;h2&gt;River 0.1.0&lt;/h2&gt;
&lt;p&gt;I’ve been using river as my daily driver for well over a year now, and am
happy to announce the first release today, river 0.1.0. In recent months
there has been little churn in river’s codebase and it is currently quite
stable and bug free. Because of this, people seem to have started using it.
As I plan to cause a lot more churn on the master branch in the near future
which will inevitably create new bugs and break people’s configuration,
this is the perfect time for a release.&lt;/p&gt;
&lt;p&gt;I’d like to thank everyone who has contributed code, documentation
and bug reports to river. In particular, thanks to &lt;a href="https://leon_plickat.srht.site/"&gt;Leon Henrik
Plickat&lt;/a&gt; for his consistent, high quality
collaboration since the early days of the project. Without all of you this
release would not have been possible.&lt;/p&gt;
&lt;h2&gt;The Future of River&lt;/h2&gt;
&lt;p&gt;Although I consider river useful enough today to tag a first release, it
is not yet complete. The core functionality and standard use cases are well
supported but river is not yet nearly as flexible as I would like it to be.
I have several ideas that I plan to try out to improve river’s flexibility
and ease of customization, but this will take time. For this reason,
users should expect widely breaking changes to how river is configured
and controlled before we approach a stable 1.0 release. Fear not though,
the core functionality and spirit of river are here to stay!&lt;/p&gt;
&lt;p&gt;If you’d like to contribute financially to my work on river, please consider
sponsoring me on &lt;a href="https://github.com/sponsors/ifreund"&gt;GitHub Sponsors&lt;/a&gt;
or &lt;a href="https://liberapay.com/ifreund"&gt;Liberapay&lt;/a&gt;. To those already donating,
thank you so much for your support!&lt;/p&gt;</content></entry></feed>