1package core
2
3import (
4 "testing"
5
6 "github.com/bnema/neferwl/internal/ports"
7)
8
9func TestConfiguresNext(t *testing.T) {
10 area := Rect{W: 1000, H: 800}
11 tiled := Placement{ID: 1, Rect: Rect{W: 500, H: 800}}
12 target := configureTarget{output: "A", view: whole(area), focused: true, client: Rect{W: 496, H: 796}}
13 tests := []struct {
14 name string
15 first *Placement // sent before p, with target
16 p Placement
17 t configureTarget
18 want ports.ConfigureWindow
19 send bool
20 }{
21 {name: "tiled", p: tiled, t: target, want: ports.ConfigureWindow{ID: 1, Width: 496, Height: 796, Activated: true, Output: "A", Visible: true}, send: true},
22 {name: "unchanged", first: &tiled, p: tiled, t: target, want: ports.ConfigureWindow{ID: 1, Width: 496, Height: 796, Activated: true, Output: "A", Visible: true}},
23 {name: "scrolled off", p: Placement{ID: 1, Rect: Rect{X: 1000, W: 500, H: 800}}, t: target, want: ports.ConfigureWindow{ID: 1, Width: 496, Height: 796, Activated: true, Output: "A"}, send: true},
24 {name: "native float", p: Placement{ID: 1, Rect: Rect{W: 300, H: 200}, Floating: true}, t: target, want: ports.ConfigureWindow{ID: 1, Activated: true, Floating: true, Output: "A", Visible: true}, send: true},
25 {name: "imposed float", p: Placement{ID: 1, Rect: Rect{W: 300, H: 200}, Floating: true}, t: configureTarget{output: "A", view: whole(area), client: Rect{W: 300, H: 200}, imposed: true}, want: ports.ConfigureWindow{ID: 1, Width: 300, Height: 200, Floating: true, Output: "A", Visible: true}, send: true},
26 {name: "fullscreen float", p: Placement{ID: 1, Rect: area, Floating: true, Fullscreen: true}, t: configureTarget{output: "A", view: whole(area), client: area}, want: ports.ConfigureWindow{ID: 1, Width: 1000, Height: 800, Fullscreen: true, Output: "A", Visible: true}, send: true},
27 {name: "hidden new", p: Placement{ID: 1, Hidden: true, Floating: true}, t: target, want: ports.ConfigureWindow{ID: 1, Floating: true, Output: "A"}, send: true},
28 {name: "hidden keeps size", first: &tiled, p: Placement{ID: 1, Hidden: true}, t: configureTarget{output: "B"}, want: ports.ConfigureWindow{ID: 1, Width: 496, Height: 796, Output: "B"}, send: true},
29 {name: "preview new", p: Placement{ID: 1, Rect: Rect{W: 250, H: 200}, Preview: 0.5}, t: target, want: ports.ConfigureWindow{ID: 1, Width: 500, Height: 400, Activated: true, Output: "A", Visible: true}, send: true},
30 {name: "fullscreen preview keeps size and state", first: &Placement{ID: 1, Rect: area, Floating: true, Fullscreen: true}, p: Placement{ID: 1, Rect: Rect{W: 100, H: 80}, Preview: 0.1}, t: configureTarget{output: "A", view: whole(area)}, want: ports.ConfigureWindow{ID: 1, Width: 496, Height: 796, Fullscreen: true, Output: "A", Visible: true}, send: true},
31 {name: "hidden float made fullscreen previews fullscreen", first: &Placement{ID: 1, Hidden: true, Floating: true}, p: Placement{ID: 1, Rect: Rect{W: 100, H: 80}, Preview: 0.1, Fullscreen: true}, t: configureTarget{output: "A", view: whole(area)}, want: ports.ConfigureWindow{ID: 1, Width: 1000, Height: 800, Fullscreen: true, Output: "A", Visible: true}, send: true},
32 {name: "preview keeps size", first: &tiled, p: Placement{ID: 1, Rect: Rect{W: 100, H: 100}, Preview: 0.5}, t: configureTarget{output: "A", view: whole(area)}, want: ports.ConfigureWindow{ID: 1, Width: 496, Height: 796, Output: "A", Visible: true}, send: true},
33 {name: "new float preview stays floating", p: Placement{ID: 1, Rect: Rect{W: 600, H: 480}, Preview: 0.6, Floating: true}, t: target, want: ports.ConfigureWindow{ID: 1, Floating: true, Activated: true, Output: "A", Visible: true}, send: true},
34 {name: "covering float preview keeps native size", first: &Placement{ID: 1, Rect: area, Floating: true}, p: Placement{ID: 1, Rect: Rect{W: 600, H: 480}, Preview: 0.6, Floating: true}, t: target, want: ports.ConfigureWindow{ID: 1, Floating: true, Activated: true, Output: "A", Visible: true}},
35 {name: "covering float peek keeps native size", first: &Placement{ID: 1, Rect: area, Floating: true}, p: Placement{ID: 1, Rect: Rect{X: 20, Y: 20, W: 600, H: 480}, Preview: 0.6, Floating: true, Peek: true}, t: target, want: ports.ConfigureWindow{ID: 1, Floating: true, Activated: true, Output: "A", Visible: true}},
36 }
37 for _, tt := range tests {
38 t.Run(tt.name, func(t *testing.T) {
39 s := newConfigures()
40 if tt.first != nil {
41 v, _ := s.next(*tt.first, target)
42 s.mark(v)
43 }
44 got, send := s.next(tt.p, tt.t)
45 if got != tt.want || send != tt.send {
46 t.Fatalf("next = %+v, %v; want %+v, %v", got, send, tt.want, tt.send)
47 }
48 })
49 }
50}
51
52// A window awaiting an answer gets its configure once, even unchanged.
53func TestConfiguresAnswer(t *testing.T) {
54 s := newConfigures()
55 p, target := Placement{ID: 1, Rect: Rect{W: 10, H: 10}}, configureTarget{output: "A"}
56 v, _ := s.next(p, target)
57 s.mark(v)
58 s.answer[1] = true
59 if _, send := s.next(p, target); !send {
60 t.Fatal("answer not sent")
61 }
62 s.mark(v)
63 if _, send := s.next(p, target); send {
64 t.Fatal("answered twice")
65 }
66}
67
68func TestConfiguresPruneForgetsUnseen(t *testing.T) {
69 s := newConfigures()
70 for _, id := range []WindowID{1, 2} {
71 v, _ := s.next(Placement{ID: id}, configureTarget{})
72 s.mark(v)
73 }
74 s.prune()
75 s.next(Placement{ID: 1}, configureTarget{})
76 s.prune()
77 if _, ok := s.sent[2]; ok {
78 t.Fatal("window out of the layout kept")
79 }
80 if _, send := s.next(Placement{ID: 1}, configureTarget{}); send {
81 t.Fatal("window still in the layout configured again")
82 }
83 if _, send := s.next(Placement{ID: 2}, configureTarget{}); !send {
84 t.Fatal("returning window not configured")
85 }
86 // A request from a window out of the layout is forgotten too.
87 s.answer[9] = true
88 s.prune()
89 if s.answer[9] {
90 t.Fatal("answer for a window out of the layout kept")
91 }
92}