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.
132 lines
4.7 KiB
Go
132 lines
4.7 KiB
Go
package main
|
|
|
|
import (
|
|
"errors"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// A pid above the kernel's largest, so a signal a test sends reaches nothing.
|
|
const nobody = 4194400
|
|
|
|
func TestTheModulesOwnConfigurationReadsAsRulesInOrder(t *testing.T) {
|
|
raw, err := os.ReadFile(filepath.Join("..", "..", "files", "picom.conf"))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
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)
|
|
}
|
|
if len(r.Rules) != 5 {
|
|
t.Fatalf("five rules: %+v", r.Rules)
|
|
}
|
|
focused, unfocused := r.Rules[2], r.Rules[3]
|
|
if focused.Match != "class_g = 'XTerm' && focused" || focused.Options["opacity"] != "0.95" ||
|
|
unfocused.Match != "class_g = 'XTerm' && !focused" || unfocused.Options["opacity"] != "0.75" {
|
|
t.Fatalf("the terminal rules: %+v %+v", focused, unfocused)
|
|
}
|
|
if last := r.Rules[4]; last.Match != "fullscreen" || last.Options["opacity"] != "1" {
|
|
t.Fatalf("full screen is opaque, and last so it wins: %+v", last)
|
|
}
|
|
if len(r.Legacy) != 0 {
|
|
t.Fatalf("the module's file sets no option the rules supersede: %v", r.Legacy)
|
|
}
|
|
if _, inGlobal := r.Global["match"]; inGlobal {
|
|
t.Fatal("a rule's key leaked into the global options")
|
|
}
|
|
}
|
|
|
|
func TestTodaysFileIsReportedForTheOptionsItsRulesWouldIgnore(t *testing.T) {
|
|
conf := "inactive-opacity = 1.0;\nopacity-rule = [ \"95:class_g = 'XTerm'\" ];\nrules = (\n { match = \"focused\"; opacity = 1; }\n);\n"
|
|
r := parseRules("x", conf, []int{7})
|
|
if len(r.Rules) != 1 || r.Rules[0].Match != "focused" || len(r.Running) != 1 {
|
|
t.Fatalf("%+v", r)
|
|
}
|
|
if strings.Join(r.Legacy, ",") != "opacity-rule,inactive-opacity" {
|
|
t.Fatalf("legacy: %v", r.Legacy)
|
|
}
|
|
}
|
|
|
|
func TestAWindowIdIsHexOrDecimalAndNeverZero(t *testing.T) {
|
|
for in, want := range map[string]string{"0x3C00012": "0x3c00012", "62914578": "0x3c00012"} {
|
|
if got, err := windowID(in); err != nil || got != want {
|
|
t.Errorf("%s: %s, %v", in, got, err)
|
|
}
|
|
}
|
|
for _, bad := range []string{"0", "0x0", "window", "-1", "0x1ffffffff"} {
|
|
if _, err := windowID(bad); err == nil {
|
|
t.Errorf("%s was accepted", bad)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestOpacityIsAPercentOfTheFullCardinal(t *testing.T) {
|
|
if opacityCardinal(0) != 0 || opacityCardinal(100) != 0xffffffff || opacityCardinal(75) != 3221225471 {
|
|
t.Fatalf("%d %d %d", opacityCardinal(0), opacityCardinal(100), opacityCardinal(75))
|
|
}
|
|
r := parseWindow("0x1", "_NET_WM_WINDOW_OPACITY(CARDINAL) = 3221225471\nWM_CLASS(STRING) = \"xterm\", \"XTerm\"\n_NET_WM_NAME(UTF8_STRING) = \"op@host: ~\"\n")
|
|
if r.Opacity == nil || *r.Opacity != 75 || r.Class != "XTerm" || r.Title != "op@host: ~" {
|
|
t.Fatalf("%+v", r)
|
|
}
|
|
if r := parseWindow("0x1", "_NET_WM_WINDOW_OPACITY: not found.\n"); r.Opacity != nil {
|
|
t.Fatalf("no value of its own: %+v", r)
|
|
}
|
|
}
|
|
|
|
func TestSettingTheFocusedWindowsOpacityAsksXpropAndNamesTheRuleThatOutranksIt(t *testing.T) {
|
|
root := fakeMachine(t)
|
|
fakeProcess(t, nobody, "i3", "DISPLAY=:1")
|
|
conf := filepath.Join(root, "home", ".config", "picom")
|
|
if err := os.MkdirAll(conf, 0o755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
src, _ := os.ReadFile(filepath.Join("..", "..", "files", "picom.conf"))
|
|
if err := os.WriteFile(filepath.Join(conf, "picom.conf"), src, 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
bin := fakeBinaries(t, map[string]string{"xprop": `echo "xprop $* DISPLAY=$DISPLAY" >> "$LOG"
|
|
case "$*" in
|
|
"-root _NET_ACTIVE_WINDOW") echo "_NET_ACTIVE_WINDOW(WINDOW): window id # 0x3c00012" ;;
|
|
*WM_CLASS*) printf '_NET_WM_WINDOW_OPACITY(CARDINAL) = 2147483648\nWM_CLASS(STRING) = "xterm", "XTerm"\n' ;;
|
|
esac`})
|
|
t.Setenv("LOG", filepath.Join(bin, "log"))
|
|
r, err := WindowOpacity("", 50)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if r.Window != "0x3c00012" || r.Opacity == nil || *r.Opacity != 50 || !strings.Contains(r.Note, "XTerm") {
|
|
t.Fatalf("%+v", r)
|
|
}
|
|
log, _ := os.ReadFile(filepath.Join(bin, "log"))
|
|
if !strings.Contains(string(log), "xprop -id 0x3c00012 -f _NET_WM_WINDOW_OPACITY 32c -set _NET_WM_WINDOW_OPACITY 2147483648 DISPLAY=:1") {
|
|
t.Fatalf("xprop was asked:\n%s", log)
|
|
}
|
|
}
|
|
|
|
func TestWithoutASessionTheToolsThatDrawSaySo(t *testing.T) {
|
|
fakeMachine(t)
|
|
if _, err := WindowOpacity("", -1); !errors.Is(err, ErrNoSession) {
|
|
t.Fatalf("window opacity: %v", err)
|
|
}
|
|
on := true
|
|
if _, err := Toggle(&on); !errors.Is(err, ErrNoSession) {
|
|
t.Fatalf("toggle on: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestARunningPicomIsToldToReinitialiseNotRestarted(t *testing.T) {
|
|
fakeMachine(t)
|
|
fakeProcess(t, nobody, "picom", "DISPLAY=:1")
|
|
r, err := Restart(false)
|
|
if err != nil || r.Action != "reinitialised" {
|
|
t.Fatalf("%+v, %v", r, err)
|
|
}
|
|
on := true
|
|
if r, err := Toggle(&on); err != nil || !r.Compositing || r.PIDs[0] != nobody {
|
|
t.Fatalf("on while running: %+v, %v", r, err)
|
|
}
|
|
}
|