OpenRiot v5.10 — The Fade Annihilation
“The compositor giveth shadows and rounded corners, and the compositor taketh away thy keystrokes. Blessed are they who disable the fade, for they shall type in peace.” — Ancient OpenBSD proverb, probably etched into a framed
xorg.conf
Release Overview
OpenRiot v5.10 was a long, humbling journey through the entire X11 stack because we refused to trust the user who said the problem was picom from the start. We blamed polybar, then i3 IPC, then the clipboard daemon, then Intel graphics, then the moon phase. The compositor sat there quietly, fading windows in 10ms increments, while we chased our tails for two releases.
The actual fixes: disable picom fading, replace xrandr with i3 get_outputs, stagger polybar spawn intervals, consolidate left-side modules, relax date polling, and remove Alacritty transparency. The typing is now smooth. We are sorry about the detours.
Total changes: 4 commits, 1 compositor put on a leash, 1 xrandr funeral, 0 apologies to xrender.
🎭 Picom: The User Was Right
The Problem: Every time you opened a window — Alacritty, crush, Gnome Text Editor — picom ran a 10ms fade-in animation. During those ~333ms of fade theater, the compositor was busy rendering frames instead of processing your keystrokes. Typing hung after 8–10 words, cursor stuttered, and we blamed everything except the compositor.
We rewrote polybar modules, disabled clipmenud, tweaked xrandr settings, blamed the Intel driver, and even suspected the clipboard daemon. The user said it was picom from the start. They were right.
The Fix:
fading = false;
use-damage = true;
vsync = false;
fading = false— Windows appear instantly. No animation. No blocked input queue.use-damage = true— Picom redraws only damaged regions. On OpenBSD xrender, this eliminates full-screen CPU arson.vsync = false— Compositor doesn’t block on vblank, reducing input latency.glx-no-stencil = true— Stencil buffer overhead removed (later reverted; not supported on this OpenBSD build).
| Before | After |
|---|---|
| Fade-in blocks X11 event loop | Windows appear instantly |
| Full-screen redraw every frame | Damaged regions only |
| Typing hangs after 8–10 words | Typing is smooth |
| Gnome Text Editor hangs on open | Gnome Text Editor opens like a normal app |
“The user said it was picom from the beginning. We should have listened. Instead we wrote a
detect-hang.shscript and learned the exact same thing the hard way.”
🔌 HDMI: xrandr Was Blocking the Entire X11 Server
The Problem: The [module/hdmi] polybar module ran --hdmi every 30 seconds. Inside source/display/hdmi.go, getLaptopDisplay() called xrandr, getExternalDisplay() called xrandr, HasExternalDisplay() called xrandr, and isDisplayActive() called xrandr --listactivemonitors. Four blocking DRM queries in a single process spawn, every 30 seconds, synchronized with volume, battery, and network-eth modules.
xrandr is not just a status query — on OpenBSD it opens /dev/drm0 and blocks on the kernel DRM event queue. When four modules fired simultaneously, four processes hit the DRM driver at once. The X11 event loop stalled for 300–400ms. Your keystrokes queued up and flushed in a burst.
This happened every 30 seconds. Like clockwork. We just couldn’t see it because we blamed picom instead of profiling polybar.
The Fix: Replaced xrandr with i3-msg -t get_outputs — an IPC socket read that returns identical output state without touching /dev/drm0, without fork+exec overhead, and without blocking the X server.
| Before (per –hdmi invocation) | After |
|---|---|
4 × xrandr (DRM blocking) |
1 × i3-msg -t get_outputs (socket read) |
| ~50–100ms stall per call | ~2–5ms latency |
| Synchronized with volume/battery/network | Independent, staggered |
Refactored hdmi.go to parse i3 output JSON once per call, derive laptop name, external name, and active status from the same parsed structure.
“xrandr is a status query the way a sledgehammer is a precision instrument. We will not make this mistake again.”
📊 Polybar: Staggering the Fork Storm
The Problem: Four polybar modules fired exactly every 30 seconds:
[module/volume]— 30s[module/battery]— 30s[module/network-eth]— 30s[module/hdmi]— 30s
Each spawned a 15MB binary via fork+exec. All four hit simultaneously, creating a CPU scheduling + X11 event burst. The 15MB binary itself was not the bottleneck; the synchronized spawn cluster was.
The Fix: Staggered intervals so modules never fire simultaneously:
| Module | Old Interval | New Interval |
|---|---|---|
all (left side) |
2s | 4s (later moved to 3s) |
volume |
10s | 31s |
battery |
10s | 32s |
network-eth |
10s | 33s |
hdmi |
10s | 65s |
Also changed [module/date] from interval = 1 to interval = 60. Every second, polybar was redrawing the entire bar for a clock that only updates per minute.
“Your status bar should tell you the time, not steal it — literally, one full redraw per second for a minute-precision clock.”
📊 Polybar: One Module to Rule Them All (Left Side)
The Problem: workspaces and window-title modules each called i3-msg -t get_tree, every 2 seconds — two JSON tree serializations blocking i3’s event loop simultaneously.
The Fix: Consolidated into [module/all] running --polybar-all. One call parses the i3 tree once, extracts workspace icons and window title from the same structure.
- Left-side process spawning: 2 → 1 every interval
i3-msg -t get_treecalls: 2 → 1- Redundant
GetAllWindowIcons()eliminated
🔌 HDMI Runtime Power Management
The Problem: Install script hardcoded hw.perfpolicy=high and hw.allowpowerdown=0, destroying laptop battery life and disabling the power button.
The Fix: Removed from install script; runtime-managed in hdmi.go. setLidAction() reads current sysctl values before writing via getSysctl() and setSysctlIfChanged(). Install script now purges stale entries instead of appending duplicates.
| State | hw.perfpolicy |
Lid / Power Button |
|---|---|---|
| Docked + AC | high |
Disabled |
| Mobile / Battery | auto |
Enabled |
🖥️ Alacritty: Opaque Is Faster
The Fix: Removed opacity = 0.96 from config/alacritty/alacritty.toml. Transparent windows force picom to composite the wallpaper underneath on every keystroke. With use-damage = false (required to avoid damage-queue stalls on OpenBSD), this meant a full-screen alpha-blended redraw for every cursor blink.
🦊 README: Firefox WebRender Crash Fix
Added documentation for Firefox hardware acceleration crash on OpenBSD Intel Xe: disable it in Preferences → General → Performance.
🧾 Files Changed
| File | Nature of Change |
|---|---|
config/picom.conf |
fading = false;, use-damage = true;, vsync = false;, corner-radius intact |
source/polybar/polybar.go |
RunAll() consolidated workspace + title logic; eliminated redundant i3-msg -t get_tree and GetAllWindowIcons() calls |
config/polybar/config.ini |
[module/all] single module; intervals staggered (31/32/33/65s); date 1→60s; enable-ipc = true |
source/display/hdmi.go |
Complete refactor: replaced 4× xrandr with single i3-msg -t get_outputs; xrandrParse struct → i3Outputs JSON parser; getLaptopDisplay(), getExternalDisplay(), isActive() all derived from one IPC call |
config/alacritty/alacritty.toml |
Removed opacity = 0.96 |
config/i3/config |
clipmenud disabled; polybar watchdog retained |
install/openriot |
Removed hardcoded sysctls; stale-entry purge logic |
README.md |
Firefox WebRender crash workaround |
🗣️ Final Words
“We blamed the compositor, then polybar, then i3, then the clipboard daemon, then the Intel driver, then the moon phase. We spent two releases chasing symptoms. The root causes were: (1) picom fade animation blocking input, and (2) xrandr blocking the DRM driver in a synchronized polybar spawn storm. The user knew it was picom from day one. We should have listened. In our defense, xrandr was very quiet about its crimes too.”
This release is dedicated to everyone who ever typed a sentence, watched the cursor freeze, and wondered if they’d imagined the keystroke. You didn’t. It was the fade animation and a DRM driver query. And now both are dead.
Upgrade with the usual command:
curl -fsSL https://OpenRiot.org/setup.sh | sh
— The OpenRiot Crew
“No fades, no xrandr, no mercy, no lag.”