Issue 345: a calendar reminder shows transparent and empty, and the mesh had no tool to look at it
mesh/merge-gate pass: the change touches no module of the mesh's graph
mesh/repo-check pass: its merge-check.sh passed
mesh/delivery superseded: a newer head of the same pull request

Records the symptom, what four reminders raised from a throw-away profile showed (drawn every time, at
depth 32), what that rules out, the candidates left, and what to measure at the next real reminder.
Status diagnosing: the cause is not known.
This commit is contained in:
2026-10-09 12:07:49 +02:00
parent d81ae38970
commit 599c3835f0
2 changed files with 138 additions and 0 deletions
@@ -0,0 +1,54 @@
---
status: diagnosing
opened: 2026-10-09
located-in: []
fixed-by:
amended-design:
---
# 345. A calendar reminder shows as a transparent, empty window, and the mesh had no tool to look at it
## Symptom
On 2026-10-09 the operator reported that on the workstation, when an Outlook (Exchange) meeting is
due, the mail client's reminder window appears, but it is transparent and shows no content: no title,
no time, no Dismiss or Snooze. The mail client is Betterbird (a Thunderbird fork, installed from the
AUR), with the Exchange calendar through the Owl add-on. The workstation runs i3 and the `picom`
compositor (glx backend, vsync, fading). No module owned Betterbird.
The operator's view of done: *on the workstation, when an Outlook meeting is due, the reminder window
shows the meeting (title, time, Dismiss/Snooze) on a normal background, not a transparent empty window,
and the mesh has tools to see and fix Betterbird.*
## Why it is an issue
Two gaps, and the symptom itself.
1. **A desktop application the operator uses every day ran outside the mesh.** Nothing could say which
window the reminder is, what the compositor makes of it, or which preferences the mail client runs
with. A change to it could only be made by hand in its profile, which the mesh's rules forbid and
which nothing would keep.
2. **The tools that look at a screen could not look at this window.** The window manager's list
(`node-display-session.windows`) leaves out every window it does not tile, the reminder among them,
and says nothing a compositor decides by (a window's depth, type, opacity). The screenshot tool of the
display server failed for one window with `X Error BadColor (invalid Colormap parameter)
X_QueryColors`, because it dumped the window by its id.
3. **The symptom's cause is not known yet.** A reminder that shows nothing is a missed meeting.
The diagnosis is in [01-diagnosis.md](01-diagnosis.md).
## Impact
- The operator cannot read or dismiss a meeting reminder: the window is there but empty.
- Until now, the next session that looked at it had to work around the mesh to see a window.
## What is done
- The display server's module gains a window list that includes unmanaged windows with their depth,
type, state, role and own opacity, and its screenshot of one window is cut from the screen as the
compositor shows it (catalogue pull request, linked from this record's pull request).
- A `betterbird` module: status, named preferences without credentials or accounts, a user.js declared
through the module's setting, its log, restart, check, and a reminder on demand from a throw-away
profile, so a fix can be proved without touching the operator's calendar.
What is not done: the cause, and so the fix. See the diagnosis.
@@ -0,0 +1,84 @@
# 345 — Diagnosis
All times 2026-10-09, local time of the workstation. "Measured" is what a tool answered; "guess" is
labelled as one.
## The record first
`records_search` for the symptom's words, `betterbird`, `thunderbird`, `picom transparent` and
`BadColor X_QueryColors xwd`: no hits. Nothing in the record covered this.
## What was measured
**The client.** `betterbird-bin` 153.1.0esr-1 (application 153.1.0, build 20260820183427), foreign to the
official repositories (from the AUR), on the workstation and on the laptop. On the workstation the main
process had run since 2026-10-04 16:05, in the login session's scope: started by hand from the launcher,
with no autostart entry and no line in i3's configuration. Its standard output is the login session's
pipe that nobody reads (the same pipe as the compositor's); its standard error is `/dev/null`. So nothing
it printed in five days was kept.
**The profile in use.** Betterbird holds the installation's default profile open (99 open files), named
by `[Install…] Default` in `profiles.ini`. Another profile is marked `Default=1`; it is not the one in
use. The profile has no `user.js`.
**Preferences that bear on how a window looks** (prefs.js, names and values only):
`browser.display.use_system_colors` true; `extensions.activeThemeID` the built-in compact dark theme;
`browser.theme.content-theme` and `toolbar-theme` 0; `mail.dark-reader.enabled` false. No `gfx.*`,
`layers.*`, `widget.*` or `alerts.*` preference is set, so the renderer and the notification path are
Betterbird's defaults. The one add-on the operator installed is Owl (Exchange). The reminder dialog's
saved place (`xulstore.json`) is 600×300 on the right-hand monitor.
**The renderer.** Both the long-running process and a fresh one load the GL libraries and run
WebRender's threads (`Renderer`, `WRRenderBackend`, `Compositor`): hardware WebRender, in-process.
The workstation did not suspend since boot, and the journal holds no GPU reset.
**The reminder window.** A reminder was raised without the operator's calendar: a second Betterbird with
`--no-remote` in a throw-away profile under the account's runtime directory, holding one local calendar
file with one event whose reminder was due 30 to 40 seconds after the start. Four runs:
| run | profile | window | depth | drawn |
|---|---|---|---|---|
| 1, 11:43 | Betterbird's defaults | class `Calendar` / `eu.betterbird.Betterbird`, role `AlarmWindow`, type `DIALOG`, 600×300, floating | 32 | not captured: it was snoozed from the desk at 11:44, before the image was taken (the calendar file recorded the snooze) |
| 2, 11:49 | the same; the snoozed reminder again | the same | 32 | **yes**: title, time, Snooze for, Dismiss, on a dark background |
| 3, 11:52 | with the operator's theme, `use_system_colors`, fonts and the dialog's saved place | the same | 32 | **yes** |
| 4, 11:54 | as 3, with `mozilla.widget.use-argb-visuals` false | the same | **still 32** | yes |
Each image was taken from the whole screen at the window's place and looked at. Every Betterbird window
on the workstation has depth 32 (an ARGB visual), the long-running one's mail window included.
**The screenshot tool's failure.** `xorg_screenshot` of the whole screen worked; of one window it
dumped the window by its id (`xwd -id`): that is the call reported failing with BadColor, and here it
answered BadWindow for a window that had just closed.
## What follows from it (guesses, each said as one)
- **Why "transparent" rather than black.** A window of depth 32 that its program never drew holds
zero alpha, and picom blends it with what is behind it: it looks transparent, with i3's frame around
it. That matches the report exactly. So the window is very likely **mapped but not painted** by
Betterbird. That is a guess from how compositing works; it was not seen, because the symptom did not
happen in four runs.
- **Not the preferences found.** The operator's theme and colour switch drew the reminder correctly in
a fresh process (run 3). The preference that would take away the alpha visual does not change the
depth in this version (run 4), so it is no lever.
- **Candidates not yet ruled out:**
1. the long-running process: five days of uptime, with WebRender's per-window state recreated many
times (its thread names count to 15). A fresh process drew every reminder;
2. Owl's reminders, which the test cannot raise without the operator's account;
3. the moment it appears: a reminder raised while a full-screen window holds the focused workspace
(Slack and a game were full screen on the day), or on the right-hand monitor where it was saved.
## What would decide it
At the next real reminder, before touching it:
1. `xorg_windows` with class `Calendar` on the workstation: the window's map state and depth.
2. `xorg_screenshot` with that window and `inline`: what the screen shows.
3. `betterbird_status`: how long the process has run.
If the window is mapped and empty, `betterbird_restart` (which also sends its output to the journal,
so the next failure leaves a trace) and `betterbird_reminder_test` with `carry` of the theme show
whether a fresh process draws it. If it does, candidate 1 holds, and the fix is in Betterbird or in its
renderer, not in the mesh; a preference to try then (`gfx.webrender.software` true, declared through the
module's setting) is proved with the same test before the operator relies on it.
Until then this record stays `diagnosing`, and the acceptance sentence is not met.