1package core
2
3import (
4 "reflect"
5 "slices"
6 "testing"
7)
8
9func TestMoveWindowInColumn(t *testing.T) {
10 for _, o := range []Overflow{OverflowScroll, OverflowFixed} {
11 w := workspace()
12 w.Overflow = o
13 w.Columns = []Column{{Windows: []WindowID{1, 2, 3}, Focus: 1}}
14 w.Apply(ActionMoveWindowUp)
15 if !slices.Equal(w.Columns[0].Windows, []WindowID{2, 1, 3}) || w.Columns[0].Focus != 0 {
16 t.Fatal(o, w.Columns)
17 }
18 // Top end: nothing moves.
19 w.Apply(ActionMoveWindowUp)
20 if !slices.Equal(w.Columns[0].Windows, []WindowID{2, 1, 3}) || w.Columns[0].Focus != 0 {
21 t.Fatal(o, w.Columns)
22 }
23 w.Apply(ActionMoveWindowDown)
24 w.Apply(ActionMoveWindowDown)
25 if !slices.Equal(w.Columns[0].Windows, []WindowID{1, 3, 2}) || w.Columns[0].Focus != 2 {
26 t.Fatal(o, w.Columns)
27 }
28 w.Apply(ActionMoveWindowDown)
29 if id, _ := w.Focused(); id != 2 || w.Columns[0].Focus != 2 {
30 t.Fatal(o, w.Columns)
31 }
32 }
33}
34
35func TestMoveWindowReleasesSlot(t *testing.T) {
36 w := workspace()
37 w.Columns = []Column{{Windows: []WindowID{1, 2}, Slot: 7}}
38 w.Apply(ActionMoveWindowDown)
39 if w.Columns[0].Slot != 0 || !slices.Equal(w.Columns[0].Windows, []WindowID{2, 1}) {
40 t.Fatal(w.Columns)
41 }
42 // A window moving into row 0 takes the place of the slot window: the
43 // slot is released too.
44 w = workspace()
45 w.Columns = []Column{{Windows: []WindowID{1, 2}, Slot: 7, Focus: 1}}
46 w.Apply(ActionMoveWindowUp)
47 if w.Columns[0].Slot != 0 {
48 t.Fatal(w.Columns)
49 }
50 // Rows below keep it.
51 w = workspace()
52 w.Columns = []Column{{Windows: []WindowID{1, 2, 3}, Slot: 7, Focus: 1}}
53 w.Apply(ActionMoveWindowDown)
54 if w.Columns[0].Slot != 7 {
55 t.Fatal(w.Columns)
56 }
57}
58
59func TestMoveWindowOnFloat(t *testing.T) {
60 w := workspace()
61 w.Columns = []Column{{Windows: []WindowID{1, 2}}}
62 w.AddFloating(3, 20, 20)
63 w.Apply(ActionMoveWindowDown)
64 if !slices.Equal(w.Columns[0].Windows, []WindowID{1, 2}) {
65 t.Fatal(w.Columns)
66 }
67}
68
69func TestResizeColumn(t *testing.T) {
70 w := workspace()
71 w.SetOutput(1000, 800)
72 w.SetGaps(10)
73 w.AddWindow(1)
74 w.AddWindow(2)
75 before := w.columnWidth(w.Focus)
76 w.Apply("set-column-width +10%")
77 if w.Columns[w.Focus].Width.Den != 100 || w.columnWidth(w.Focus) <= before {
78 t.Fatal(w.Columns[w.Focus].Width, w.columnWidth(w.Focus), before)
79 }
80 w.Apply("set-column-width -10%")
81 if d := w.columnWidth(w.Focus) - before; d < -1 || d > 1 {
82 t.Fatal(w.columnWidth(w.Focus), before)
83 }
84 for range 20 {
85 w.Apply("set-column-width +10%")
86 }
87 if w.Columns[w.Focus].Width != (Width{Num: 100, Den: 100}) {
88 t.Fatal(w.Columns[w.Focus].Width)
89 }
90 for range 20 {
91 w.Apply("set-column-width -10%")
92 }
93 if w.Columns[w.Focus].Width != (Width{Num: 10, Den: 100}) {
94 t.Fatal(w.Columns[w.Focus].Width)
95 }
96 // A preset snaps to the nearest whole percent once; steps then
97 // round-trip exactly.
98 for _, p := range []Width{{Num: 1, Den: 3}, {Num: 1, Den: 2}, {Num: 2, Den: 3}} {
99 w.Columns[w.Focus].Width = p
100 px := w.columnWidth(w.Focus)
101 w.Apply("set-column-width +7%")
102 w.Apply("set-column-width -7%")
103 snapped := w.columnWidth(w.Focus)
104 if d := snapped - px; d < -w.Usable.W/100 || d > w.Usable.W/100 {
105 t.Fatal(p, snapped, px)
106 }
107 w.Apply("set-column-width +7%")
108 w.Apply("set-column-width -7%")
109 if w.columnWidth(w.Focus) != snapped {
110 t.Fatal(p, w.columnWidth(w.Focus), snapped)
111 }
112 }
113}
114
115func TestResizeColumnUnmaximizesAndCycles(t *testing.T) {
116 w := workspace()
117 w.SetOutput(1000, 800)
118 w.SetPresets([]Width{{Num: 1, Den: 2}, {Num: 1, Den: 1}})
119 w.AddWindow(1)
120 w.ToggleFullWidth()
121 w.Apply("set-column-width -10%")
122 if w.Columns[0].FullWidth {
123 t.Fatal("still maximized")
124 }
125 // A width outside the presets restarts the cycle at the first preset.
126 w.CycleWidth()
127 if w.Columns[0].Width != (Width{Num: 1, Den: 2}) {
128 t.Fatal(w.Columns[0].Width)
129 }
130}
131
132func TestResizeColumnSameValueAsPreset(t *testing.T) {
133 w := workspace()
134 w.SetOutput(1000, 800)
135 w.SetPresets([]Width{{Num: 1, Den: 3}, {Num: 1, Den: 2}, {Num: 1, Den: 1}})
136 w.AddWindow(1)
137 w.Columns[0].Width = Width{Num: 50, Den: 100}
138 w.CycleWidth()
139 if w.Columns[0].Width != (Width{Num: 1, Den: 1}) {
140 t.Fatal(w.Columns[0].Width)
141 }
142}
143
144func TestColumnEditsUnderFullscreen(t *testing.T) {
145 w := workspace()
146 w.SetOutput(1000, 800)
147 w.Columns = []Column{{Windows: []WindowID{1, 2}, Width: Width{Num: 1, Den: 2}}}
148 w.SetFullscreen(1, true)
149 w.Apply("set-column-width -10%")
150 w.Apply(ActionMoveWindowDown)
151 c := w.Columns[0]
152 if c.Width != (Width{Num: 1, Den: 2}) || !slices.Equal(c.Windows, []WindowID{1, 2}) {
153 t.Fatal(c)
154 }
155}
156
157func TestResizeColumnFixedNoop(t *testing.T) {
158 w := workspace()
159 w.Overflow = OverflowFixed
160 w.AddWindow(1)
161 w.Apply("set-column-width +10%")
162 if w.Columns[0].Width != (Width{}) {
163 t.Fatal(w.Columns[0].Width)
164 }
165}
166
167func TestMoveWorkspace(t *testing.T) {
168 m := monitor()
169 m.AddWindow(1)
170 m.FocusNumber(2)
171 m.AddWindow(2)
172 m.FocusNumber(3)
173 m.AddWindow(3)
174 // [1:{1}] [2:{2}] [3:{3}] [4:{}]
175 m.Apply(ActionMoveWorkspaceUp)
176 if !reflect.DeepEqual(windows(m), [][]WindowID{{1}, {3}, {2}, {}}) || m.Active != 1 {
177 t.Fatal(windows(m), m.Active)
178 }
179 m.Apply(ActionMoveWorkspaceUp)
180 m.Apply(ActionMoveWorkspaceUp)
181 if !reflect.DeepEqual(windows(m), [][]WindowID{{3}, {1}, {2}, {}}) || m.Active != 0 {
182 t.Fatal(windows(m), m.Active)
183 }
184 m.Apply(ActionMoveWorkspaceDown)
185 m.Apply(ActionMoveWorkspaceDown)
186 // Never past the trailing empty workspace.
187 m.Apply(ActionMoveWorkspaceDown)
188 if !reflect.DeepEqual(windows(m), [][]WindowID{{1}, {2}, {3}, {}}) || m.Active != 2 {
189 t.Fatal(windows(m), m.Active)
190 }
191 // The trailing empty workspace does not move.
192 m.FocusNumber(4)
193 m.Apply(ActionMoveWorkspaceUp)
194 if !reflect.DeepEqual(windows(m), [][]WindowID{{1}, {2}, {3}, {}}) || m.Active != 3 {
195 t.Fatal(windows(m), m.Active)
196 }
197}
198
199func TestMoveWorkspaceHidden(t *testing.T) {
200 m := named(monitor(), NamedWorkspace{Name: "dev"})
201 m.AddWindow(1)
202 m.FocusNumber(2)
203 m.AddWindow(2)
204 m.ToggleNamed("dev")
205 m.Apply(ActionMoveWorkspaceUp)
206 if !reflect.DeepEqual(windows(m), [][]WindowID{{1}, {2}, {}}) {
207 t.Fatal(windows(m))
208 }
209}