v0.1.0 d9218d6

outputs_test.go RawHistoryFolder

1package wayland
2
3import (
4	"testing"
5	"time"
6
7	"github.com/bnema/neferwl/internal/ports"
8	"github.com/bnema/purego-libwayland/protocol/wayland"
9	"github.com/bnema/purego-libwayland/protocol/wlrlayershell"
10	"github.com/bnema/wlturbo"
11)
12
13var second = ports.OutputPlacement{Info: ports.OutputInfo{Name: "HEADLESS-2", Width: 1280, Height: 1024}, X: 1920, Width: 1280, Height: 1024, Scale: 1}
14
15// outputCount counts wl_output globals the client sees.
16func outputCount(c *wlturbo.Display) int {
17	n := 0
18	for _, g := range c.Registry().GetGlobals() {
19		if g.Interface == "wl_output" {
20			n++
21		}
22	}
23	return n
24}
25
26// waitOutputs round-trips until the client sees n wl_output globals.
27func waitOutputs(t *testing.T, c *wlturbo.Display, n int) {
28	t.Helper()
29	for deadline := time.Now().Add(2 * time.Second); time.Now().Before(deadline); {
30		if err := c.Roundtrip(); err != nil {
31			t.Fatal(err)
32		}
33		if outputCount(c) == n {
34			return
35		}
36		time.Sleep(5 * time.Millisecond)
37	}
38	t.Fatalf("wl_output globals: %d, want %d", outputCount(c), n)
39}
40
41type closedProxy struct {
42	wlturbo.BaseProxy
43	configured chan [3]uint32
44	closed     chan struct{}
45}
46
47func (p *closedProxy) Dispatch(e *wlturbo.Event) {
48	switch e.Opcode {
49	case uint16(wlrlayershell.ZwlrLayerSurfaceV1EventConfigure):
50		p.configured <- [3]uint32{e.Uint32(), e.Uint32(), e.Uint32()}
51	case uint16(wlrlayershell.ZwlrLayerSurfaceV1EventClosed):
52		close(p.closed)
53	}
54}
55
56func TestOutputHotplugAndLayerOutput(t *testing.T) {
57	s, _, commands, dir := lifecycleServer(t)
58	c := protocolClient(t, s, dir)
59	if outputCount(c) != 1 {
60		t.Fatal(outputCount(c))
61	}
62	commands <- ports.SetOutputs{Outputs: ports.Layout{testOutputs[0], second}, Focused: "HEADLESS-1"}
63	waitOutputs(t, c, 2)
64	// A layer surface on the second output is sized from it.
65	var name uint32
66	for n, g := range c.Registry().GetGlobals() {
67		if g.Interface == "wl_output" && (name == 0 || n > name) {
68			name = n
69		}
70	}
71	out, err := c.Registry().BindID(name, "wl_output", 4)
72	if err != nil {
73		t.Fatal(err)
74	}
75	registerProtocol(t, c, out)
76	comp := bindProtocol(t, c, "wl_compositor")
77	shell := bindProtocol(t, c, "zwlr_layer_shell_v1")
78	surf := c.AllocateID()
79	requestProtocol(t, c, comp, wayland.CompositorRequestCreateSurface, surf)
80	registerProtocol(t, c, surf)
81	layer := c.AllocateID()
82	proxy := &closedProxy{configured: make(chan [3]uint32, 2), closed: make(chan struct{})}
83	proxy.SetID(layer)
84	c.Context().Register(proxy)
85	requestProtocol(t, c, shell, wlrlayershell.ZwlrLayerShellV1RequestGetLayerSurface, layer, surf, out, uint32(ports.LayerTop), "bar")
86	requestProtocol(t, c, layer, wlrlayershell.ZwlrLayerSurfaceV1RequestSetAnchor, uint32(13))
87	requestProtocol(t, c, layer, wlrlayershell.ZwlrLayerSurfaceV1RequestSetSize, uint32(0), uint32(30))
88	requestProtocol(t, c, surf, wayland.SurfaceRequestCommit)
89	if err := c.Roundtrip(); err != nil {
90		t.Fatal(err)
91	}
92	select {
93	case cfg := <-proxy.configured:
94		if cfg[1] != 1280 {
95			t.Fatalf("configure %v", cfg)
96		}
97	case <-time.After(2 * time.Second):
98		t.Fatal("configure timeout")
99	}
100	// Unplugged: the global goes away and the layer surface is closed.
101	commands <- ports.SetOutputs{Outputs: ports.Layout{testOutputs[0]}, Focused: "HEADLESS-1"}
102	waitOutputs(t, c, 1)
103	select {
104	case <-proxy.closed:
105	case <-time.After(2 * time.Second):
106		t.Fatal("layer not closed")
107	}
108}

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 23

Tags 10

↑↓ moveenter openesc close