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}