Merge pull request 'Issue 345: a calendar reminder shows transparent and empty, and the mesh had no tool to look at it' (#245) from issues/345-a-reminder-window-shows-transparent-and-empty into main

This commit was merged in pull request #245.
This commit is contained in:
2026-10-09 10:50:55 +00:00
2 changed files with 170 additions and 0 deletions
@@ -0,0 +1,64 @@
---
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.*
## Reported history
The operator reports (2026-10-09) earlier trouble with picom on the workstations, never recorded: a chat
window (Telegram) froze, not redrawn, after a change of i3 workspace. `records_search` for picom finds
nothing about it. It is the same kind of failure as this one, a window the compositor shows without its
content, and it makes picom the first suspect here.
## 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.
- The `picom` module's backend and damage tracking become settings of each machine (defaults unchanged:
`glx`, `use-damage` true), so the candidate fixes can be set and proved without a hand edit.
What is not done: the cause, and so the fix. See the diagnosis.
@@ -0,0 +1,106 @@
# 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 graphics stack** (2026-10-09, read on the workstation; no mesh tool answers it yet, so it was read
with the login shell's command verb): an AMD Radeon RX 6950 XT (Navi 21) on the kernel's `amdgpu` driver,
the X server's `amdgpu` driver (`xf86-video-amdgpu` 25.0.0) on X.Org 1.21.1.24, Mesa 26.2.4 (`radeonsi`),
kernel 7.2.8, picom 13. picom runs with the `glx` backend, vsync, fading, and damage tracking at picom's
default (on).
**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, the first suspect first:**
1. **picom.** The operator has seen picom leave a window stale after a workspace switch before (the
reported history). picom's `glx` backend with vsync and damage tracking on (its default) is a known
source of windows left unpainted or stale on some drivers: picom repaints only the regions it was
told changed, and a missed damage event leaves a window's area as it was, for a new window empty.
That fits a reminder that appears while the operator is on another workspace. Not yet seen
happening;
2. the long-running Betterbird: 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;
3. Owl's reminders, which the test cannot raise without the operator's account;
4. 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 that shows empty, 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. **`picom.picom_toggle` with `on` false: compositing off.** If the reminder's content appears, picom is
the cause. This needs no restart of Betterbird and loses nothing. `xorg_screenshot` again, then
`picom_toggle` with `on` true to put compositing back.
4. Only if the content does not appear with compositing off: `betterbird_status` (how long it has run),
then `betterbird_restart`. It refuses while a composer window is open, because the unsent message
would be lost; `discard_unsent` is given only on the operator's yes. Then `betterbird_reminder_test`
with `carry` of the theme shows whether a fresh process draws it.
**If picom is the cause**, the candidate fixes are the `picom` module's settings for that machine, never a
hand edit: `use-damage` false first (repaint the whole screen each frame), else `backend` `xrender`. Each
is proved on the workstation before the operator relies on it: set it, `picom_restart`, raise a reminder
with `betterbird_reminder_test` while on another workspace, switch back, and look with `xorg_screenshot`.
The reported chat-window freeze is checked the same way.
**If a fresh Betterbird draws it and picom is not the cause**, the fix is in Betterbird or its renderer, not
the mesh; a preference to try then (`gfx.webrender.software` true, declared through the `betterbird`
module's setting) is proved with the same test.
Until then this record stays `diagnosing`, and the acceptance sentence is not met.