v0.4.0 b6be3a8

layer_scale_test.go RawHistoryFolder

1package wayland
2
3import (
4	"testing"
5
6	"github.com/bnema/go-wayland-bindings/server/fractionalscale"
7	"github.com/bnema/go-wayland-bindings/server/wayland"
8	"github.com/bnema/go-wayland-bindings/server/wlrlayershell"
9	"github.com/bnema/neferwl/internal/ports"
10	"github.com/bnema/wlturbo"
11)
12
13// layerScaleOrderProxy is a real protocol client recording fractional-scale
14// and layer events in their wire order across the two protocol objects.
15type layerScaleOrderProxy struct {
16	wlturbo.BaseProxy
17	layer  bool
18	events chan [3]uint32
19}
20
21func (p *layerScaleOrderProxy) Dispatch(e *wlturbo.Event) {
22	if !p.layer {
23		p.events <- [3]uint32{0, e.Uint32()}
24		return
25	}
26	switch e.Opcode {
27	case uint16(wlrlayershell.ZwlrLayerSurfaceV1EventConfigure):
28		_ = e.Uint32() // serial
29		p.events <- [3]uint32{1, e.Uint32(), e.Uint32()}
30	case uint16(wlrlayershell.ZwlrLayerSurfaceV1EventClosed):
31		p.events <- [3]uint32{2}
32	}
33}
34
35func TestLayerTargetScaleBeforeConfigure(t *testing.T) {
36	for _, target := range []string{"fractional", "focused", "inferred", "removed"} {
37		t.Run(target, func(t *testing.T) {
38			s, _, commands, dir := lifecycleServer(t)
39			c := protocolClient(t, s, dir)
40			fractional := ports.OutputPlacement{Info: ports.OutputInfo{Name: "HEADLESS-2", Width: 900, Height: 600}, X: 1920, Width: 750, Height: 500, Scale: 1.2}
41			commands <- ports.SetOutputs{Outputs: ports.Layout{testOutputs[0], fractional}, Focused: "HEADLESS-1"}
42			waitOutputs(t, c, 2)
43			var first, last uint32
44			for n, g := range c.Registry().GetGlobals() {
45				if g.Interface == "wl_output" {
46					if first == 0 || n < first {
47						first = n
48					}
49					last = max(last, n)
50				}
51			}
52			var out uint32
53			if target != "inferred" {
54				name := last
55				if target == "focused" {
56					name = first
57				}
58				var err error
59				out, err = bindWireID(c, name, "wl_output", 4)
60				if err != nil {
61					t.Fatal(err)
62				}
63				registerProtocol(t, c, out)
64			}
65			if target == "removed" {
66				commands <- ports.SetOutputs{Outputs: testOutputs, Focused: "HEADLESS-1"}
67				waitOutputs(t, c, 1)
68			}
69			comp := bindVersion(t, c, "wl_compositor", 6)
70			shell := bindProtocol(t, c, "zwlr_layer_shell_v1")
71			fm := bindProtocol(t, c, "wp_fractional_scale_manager_v1")
72			surf := c.AllocateID()
73			integers := make(chan int32, 4)
74			sp := &surfaceScaleProxy{scales: integers}
75			sp.SetID(surf)
76			registerWireProxy(c, sp)
77			requestProtocol(t, c, comp, wayland.CompositorRequestCreateSurface, surf)
78			frac := c.AllocateID()
79			events := make(chan [3]uint32, 8)
80			fp := &layerScaleOrderProxy{events: events}
81			fp.SetID(frac)
82			registerWireProxy(c, fp)
83			requestProtocol(t, c, fm, fractionalscale.WpFractionalScaleManagerV1RequestGetFractionalScale, frac, surf)
84			if err := c.Roundtrip(); err != nil {
85				t.Fatal(err)
86			}
87			if len(events) != 1 || <-events != [3]uint32{0, 120} {
88				t.Fatal("surface must initially use focused output scale 120")
89			}
90			if len(integers) != 1 || <-integers != 1 {
91				t.Fatal("initial integer scale must be 1")
92			}
93			layer := c.AllocateID()
94			lp := &layerScaleOrderProxy{layer: true, events: events}
95			lp.SetID(layer)
96			registerWireProxy(c, lp)
97			requestProtocol(t, c, shell, wlrlayershell.ZwlrLayerShellV1RequestGetLayerSurface, layer, surf, out, uint32(ports.LayerOverlay), "scale-test")
98			requestProtocol(t, c, layer, wlrlayershell.ZwlrLayerSurfaceV1RequestSetAnchor, uint32(15))
99			requestProtocol(t, c, layer, wlrlayershell.ZwlrLayerSurfaceV1RequestSetSize, uint32(0), uint32(0))
100			requestProtocol(t, c, surf, wayland.SurfaceRequestCommit)
101			if err := c.Roundtrip(); err != nil {
102				t.Fatal(err)
103			}
104			want := [][3]uint32{{1, 1920, 1080}}
105			switch target {
106			case "fractional":
107				want = [][3]uint32{{0, 144}, {1, 750, 500}}
108				if len(integers) != 1 || <-integers != 2 {
109					t.Fatal("target integer scale must update to 2")
110				}
111			case "removed":
112				want = [][3]uint32{{2}}
113			}
114			if len(events) != len(want) {
115				t.Fatalf("events: %d, want %v", len(events), want)
116			}
117			for _, expected := range want {
118				if got := <-events; got != expected {
119					t.Fatalf("event %v, want %v", got, expected)
120				}
121			}
122			if len(integers) != 0 {
123				t.Fatal("unexpected integer scale notification")
124			}
125		})
126	}
127}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 25

Tags 10

↑↓ moveenter openesc close