picom: the backend and damage tracking are each machine's settings (hq issue 345)
mesh/merge-gate pass: builds picom → g14, shanks; no bus step; every machine composes with the change as it did without (4 of 4 compose)
mesh/repo-check pass: its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-check-typescript.sh (typescript)
mesh/delivery superseded: a newer head of the same pull request
mesh/merge-gate pass: builds picom → g14, shanks; no bus step; every machine composes with the change as it did without (4 of 4 compose)
mesh/repo-check pass: its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-check-typescript.sh (typescript)
mesh/delivery superseded: a newer head of the same pull request
A window mapped but left unpainted, or stale after a workspace switch, is a known failure of picom's glx backend with damage tracking on some drivers, and the first suspect for the empty calendar reminder on the workstation. Research 037 already found the backend to depend on the machine's driver. Both become preferences whose defaults are today's (glx, use-damage true), so nothing changes until a machine is given xrender or use-damage false to test it.
This commit is contained in:
@@ -13,6 +13,23 @@ The X compositor as a module (novox/hq ADR 0208, research 026).
|
||||
a process has one starter. Its package's autostart entry is that starter where there is one, and
|
||||
the `xinitrc` slot where there is none.
|
||||
|
||||
## Settings
|
||||
|
||||
Two preferences, each a machine's own (the per-node layer of `settings`), because the right values follow
|
||||
the machine's graphics driver (novox/hq research 037):
|
||||
|
||||
| setting | default | what it changes |
|
||||
|---|---|---|
|
||||
| `backend` | `glx` | how picom draws: `glx` on the graphics card, `xrender` on the CPU |
|
||||
| `use-damage` | `true` | `true` repaints only what changed (picom's own default); `false` repaints the whole screen each frame |
|
||||
|
||||
The defaults are what every machine ran before, so the file filled with them changes nothing. They exist
|
||||
for hq issue 345: a window that is mapped but shows nothing (a calendar reminder) or stays stale after a
|
||||
workspace switch (a chat window) is a known failure of glx with damage tracking on some drivers, and
|
||||
`xrender` or `use-damage` false is how a machine is set to test that. The file is `"trusted": false`: only
|
||||
the operator's own compositor reads it, so a verb may set these (issue 339). A changed file is read at
|
||||
the next `picom_restart` or login: the module has no unit to reload.
|
||||
|
||||
## Tools
|
||||
|
||||
Served by the node's runtime as the operator account (ADR 0175). The tools find the operator's X
|
||||
|
||||
@@ -12,21 +12,29 @@ import (
|
||||
// every desktop module that carries it.
|
||||
|
||||
type manifest struct {
|
||||
Module string `json:"module"`
|
||||
Version string `json:"version"`
|
||||
Capabilities []string `json:"capabilities"`
|
||||
Requires []string `json:"requires"`
|
||||
Claims []claim `json:"claims"`
|
||||
Seats []any `json:"seats"`
|
||||
Tools []string `json:"tools"`
|
||||
Environment *environment `json:"environment"`
|
||||
Shell []shellCode `json:"shell"`
|
||||
Resources []map[string]any `json:"resources"`
|
||||
Module string `json:"module"`
|
||||
Version string `json:"version"`
|
||||
Capabilities []string `json:"capabilities"`
|
||||
Requires []string `json:"requires"`
|
||||
Claims []claim `json:"claims"`
|
||||
Seats []any `json:"seats"`
|
||||
Tools []string `json:"tools"`
|
||||
Settings map[string]setting `json:"settings"`
|
||||
Environment *environment `json:"environment"`
|
||||
Shell []shellCode `json:"shell"`
|
||||
Resources []map[string]any `json:"resources"`
|
||||
Build struct {
|
||||
Artifacts []map[string]any `json:"artifacts"`
|
||||
} `json:"build"`
|
||||
}
|
||||
|
||||
// setting is one key's default, as the definition gives it (novox/hq ADR 0262).
|
||||
type setting struct {
|
||||
Kind string `json:"kind"`
|
||||
Default any `json:"default"`
|
||||
Why string `json:"why"`
|
||||
}
|
||||
|
||||
type claim struct {
|
||||
Name string `json:"name"`
|
||||
Scope string `json:"scope"`
|
||||
|
||||
@@ -59,3 +59,33 @@ func TestTheToolsAgreeWithTheManifest(t *testing.T) {
|
||||
checkTheToolsAgree(t, m)
|
||||
checkNoSecretsOrInstallationNames(t)
|
||||
}
|
||||
|
||||
// The backend and damage tracking are each machine's (novox/hq research 037: the backend depends on the
|
||||
// machine's graphics driver; issue 345: a window left unpainted under glx is the first suspect). Both
|
||||
// are settings whose defaults are what every machine ran before, so the file filled with them is today's.
|
||||
func TestTheBackendAndDamageTrackingAreSettingsWithTodaysDefaults(t *testing.T) {
|
||||
m := readManifest(t)
|
||||
b, d := m.Settings["backend"], m.Settings["use-damage"]
|
||||
if b.Kind != "preference" || b.Default != "glx" || b.Why == "" || d.Kind != "preference" || d.Default != true || d.Why == "" {
|
||||
t.Fatalf("settings: %+v", m.Settings)
|
||||
}
|
||||
r := m.resource(t, "configuration")
|
||||
c := r["content"].(string)
|
||||
for _, want := range []string{`backend = "${setting:backend}";`, "use-damage = ${setting:use-damage};"} {
|
||||
if !strings.Contains(c, want) {
|
||||
t.Errorf("the file asks for %q", want)
|
||||
}
|
||||
}
|
||||
if r["trusted"] != false {
|
||||
t.Fatal("only the operator's own compositor reads the file: trusted false, so a verb may set a machine's backend (issue 339)")
|
||||
}
|
||||
got := parseRules("picom.conf", withDefaults(c), nil)
|
||||
if got.Global["backend"] != "glx" || got.Global["use-damage"] != "true" || got.Global["vsync"] != "true" {
|
||||
t.Fatalf("filled with the defaults: %v", got.Global)
|
||||
}
|
||||
}
|
||||
|
||||
// withDefaults fills the file's settings with their defaults, as a machine without its own values gets it.
|
||||
func withDefaults(c string) string {
|
||||
return strings.NewReplacer("${setting:backend}", "glx", "${setting:use-damage}", "true").Replace(c)
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ func TestTheModulesOwnConfigurationReadsAsRulesInOrder(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
r := parseRules("picom.conf", string(raw), nil)
|
||||
r := parseRules("picom.conf", withDefaults(string(raw)), nil)
|
||||
if r.Global["backend"] != "glx" || r.Global["vsync"] != "true" || r.Global["shadow"] != "false" {
|
||||
t.Fatalf("global options: %v", r.Global)
|
||||
}
|
||||
|
||||
@@ -2,7 +2,13 @@
|
||||
# replaced at every push. Adopted from the two workstations' file of 2026-10-04 and moved to
|
||||
# picom's window rules, which supersede opacity-rule, inactive-opacity and inactive-dim.
|
||||
|
||||
backend = "glx";
|
||||
# The backend and damage tracking are each machine's settings (backend, use-damage; novox/hq research
|
||||
# 037, issue 345): the right ones depend on the machine's graphics driver. The defaults are what every
|
||||
# machine ran before: glx, and picom's own default of repainting only what changed. xrender, or
|
||||
# use-damage false (repaint the whole screen each frame), is what to try on a machine where a window is
|
||||
# left unpainted or stale.
|
||||
backend = "${setting:backend}";
|
||||
use-damage = ${setting:use-damage};
|
||||
vsync = true;
|
||||
|
||||
fading = true;
|
||||
|
||||
@@ -13,6 +13,18 @@
|
||||
"scope": "node"
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
"backend": {
|
||||
"kind": "preference",
|
||||
"default": "glx",
|
||||
"why": "glx draws with the graphics card and has served every machine so far; xrender draws on the CPU and is what to try where glx leaves a window unpainted or stale on the machine's driver (novox/hq research 037, issue 345)"
|
||||
},
|
||||
"use-damage": {
|
||||
"kind": "preference",
|
||||
"default": true,
|
||||
"why": "true repaints only what changed, picom's own default; false repaints the whole screen each frame, which costs work and cures a window left stale or unpainted on some drivers (novox/hq issue 345)"
|
||||
}
|
||||
},
|
||||
"tools": [
|
||||
"picom_restart",
|
||||
"picom_rules",
|
||||
@@ -39,11 +51,12 @@
|
||||
},
|
||||
{
|
||||
"id": "configuration",
|
||||
"trusted": false,
|
||||
"type": "file",
|
||||
"path": "${machine:account-home}/.config/picom/picom.conf",
|
||||
"owner": "${machine:account}",
|
||||
"mode": "0644",
|
||||
"content": "# picom, the X compositor (module picom, novox/hq ADR 0208). Owned by the mesh: this file is\n# replaced at every push. Adopted from the two workstations' file of 2026-10-04 and moved to\n# picom's window rules, which supersede opacity-rule, inactive-opacity and inactive-dim.\n\nbackend = \"glx\";\nvsync = true;\n\nfading = true;\nfade-in-step = 0.05;\nfade-out-step = 0.05;\n\n# Tiled windows hide their shadows and corners, so neither is drawn.\nshadow = false;\ncorner-radius = 0;\nblur-method = \"none\";\n\n# \"Focused\" is i3's _NET_ACTIVE_WINDOW, not X focus events: under i3 those do not reliably reach\n# the toplevel picom tracks, and a terminal then never lifts to its focused opacity.\nuse-ewmh-active-win = true;\n\n# Window rules are applied in order, and a later match wins. Only terminals are translucent:\n# nothing else on screen (browsers, video, games) is touched. A terminal is matched by its class;\n# the node's terminal emulator today is xterm (class XTerm). A window's own opacity property is\n# used wherever no rule sets one, which is what the window-opacity tool sets.\nrules = (\n { match = \"window_type = 'tooltip'\"; fade = false; opacity = 0.95; },\n { match = \"window_type = 'dock' || window_type = 'desktop'\"; fade = false; },\n { match = \"class_g = 'XTerm' && focused\"; opacity = 0.95; },\n { match = \"class_g = 'XTerm' && !focused\"; opacity = 0.75; },\n # A full-screen window is opaque, a terminal included: a video or a game is never see-through.\n { match = \"fullscreen\"; opacity = 1; }\n);\n"
|
||||
"content": "# picom, the X compositor (module picom, novox/hq ADR 0208). Owned by the mesh: this file is\n# replaced at every push. Adopted from the two workstations' file of 2026-10-04 and moved to\n# picom's window rules, which supersede opacity-rule, inactive-opacity and inactive-dim.\n\n# The backend and damage tracking are each machine's settings (backend, use-damage; novox/hq research\n# 037, issue 345): the right ones depend on the machine's graphics driver. The defaults are what every\n# machine ran before: glx, and picom's own default of repainting only what changed. xrender, or\n# use-damage false (repaint the whole screen each frame), is what to try on a machine where a window is\n# left unpainted or stale.\nbackend = \"${setting:backend}\";\nuse-damage = ${setting:use-damage};\nvsync = true;\n\nfading = true;\nfade-in-step = 0.05;\nfade-out-step = 0.05;\n\n# Tiled windows hide their shadows and corners, so neither is drawn.\nshadow = false;\ncorner-radius = 0;\nblur-method = \"none\";\n\n# \"Focused\" is i3's _NET_ACTIVE_WINDOW, not X focus events: under i3 those do not reliably reach\n# the toplevel picom tracks, and a terminal then never lifts to its focused opacity.\nuse-ewmh-active-win = true;\n\n# Window rules are applied in order, and a later match wins. Only terminals are translucent:\n# nothing else on screen (browsers, video, games) is touched. A terminal is matched by its class;\n# the node's terminal emulator today is xterm (class XTerm). A window's own opacity property is\n# used wherever no rule sets one, which is what the window-opacity tool sets.\nrules = (\n { match = \"window_type = 'tooltip'\"; fade = false; opacity = 0.95; },\n { match = \"window_type = 'dock' || window_type = 'desktop'\"; fade = false; },\n { match = \"class_g = 'XTerm' && focused\"; opacity = 0.95; },\n { match = \"class_g = 'XTerm' && !focused\"; opacity = 0.75; },\n # A full-screen window is opaque, a terminal included: a video or a game is never see-through.\n { match = \"fullscreen\"; opacity = 1; }\n);\n"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
|
||||
Reference in New Issue
Block a user