main 3d41bc5

outputs.go RawHistoryFolder

1package testserver
2
3import (
4	"github.com/bnema/purego-libwayland/protocol/extimagecapturesource"
5	"github.com/bnema/purego-libwayland/protocol/wayland"
6	"github.com/bnema/purego-libwayland/server"
7	"golang.org/x/sys/unix"
8)
9
10func (s *Server) addOutput(spec OutputSpec, must func(error)) {
11	o := &output{spec: spec}
12	v := spec.Version
13	if v == 0 {
14		v = 4
15	}
16	g, err := s.d.AddGlobal(wayland.OutputInterface, int32(v), func(c server.Client, ver, id uint32) {
17		res, err := wayland.NewOutput(c, int32(ver), id, outputHandler{})
18		if err != nil {
19			must(err)
20			return
21		}
22		o.res = append(o.res, res)
23		res.SendGeometry(0, 0, 0, 0, 0, "test", "test", 0)
24		res.SendMode(1, int32(spec.Width), int32(spec.Height), 60000)
25		if ver >= 2 {
26			scale := spec.Scale
27			if scale == 0 {
28				scale = 1
29			}
30			res.SendScale(scale)
31		}
32		if ver >= 4 {
33			res.SendName(spec.Name)
34		}
35		if ver >= 2 {
36			res.SendDone()
37		}
38	})
39	must(err)
40	o.global = g
41	s.outputs = append(s.outputs, o)
42}
43
44type outputHandler struct{}
45
46func (outputHandler) Release(*wayland.Output) {}
47
48func (s *Server) outputOf(r *server.Resource) *output {
49	for _, o := range s.outputs {
50		for _, res := range o.res {
51			if res.Resource == r {
52				return o
53			}
54		}
55	}
56	return nil
57}
58
59// RemoveOutput withdraws the named output's global and stops its sessions.
60func (s *Server) RemoveOutput(name string) {
61	s.Do(func() {
62		for _, o := range s.outputs {
63			if o.spec.Name == name && !o.removed {
64				o.removed = true
65				o.global.Remove()
66				for _, c := range s.sessions {
67					if c.out == o {
68						c.stop()
69					}
70				}
71			}
72		}
73	})
74}
75
76// pool is one wl_shm_pool mapping, shared by the buffers made from it.
77type pool struct {
78	data      []byte
79	refs      int
80	destroyed bool
81}
82
83func (p *pool) release() {
84	if p.refs == 0 && p.destroyed && p.data != nil {
85		_ = unix.Munmap(p.data)
86		p.data = nil
87	}
88}
89
90type buffer struct {
91	p                             *pool
92	offset                        int
93	width, height, stride, format uint32
94}
95
96func (b *buffer) bytes() []byte {
97	n := int(b.stride) * int(b.height)
98	if b.p.data == nil || b.offset+n > len(b.p.data) {
99		return nil
100	}
101	return b.p.data[b.offset : b.offset+n]
102}
103
104type shmHandler struct{ s *Server }
105
106func (h shmHandler) CreatePool(self *wayland.Shm, id uint32, fd int, size int32) {
107	defer unix.Close(fd)
108	data, err := unix.Mmap(fd, 0, int(size), unix.PROT_READ|unix.PROT_WRITE, unix.MAP_SHARED)
109	if err != nil {
110		self.PostError(0, "mmap failed")
111		return
112	}
113	_, _ = wayland.NewShmPool(self.Client(), 1, id, &poolHandler{s: h.s, p: &pool{data: data}})
114}
115func (shmHandler) Release(*wayland.Shm) {}
116
117type poolHandler struct {
118	s *Server
119	p *pool
120}
121
122func (h *poolHandler) CreateBuffer(self *wayland.ShmPool, id uint32, offset, width, height, stride int32, format uint32) {
123	b := &buffer{p: h.p, offset: int(offset), width: uint32(width), height: uint32(height), stride: uint32(stride), format: format}
124	res, err := wayland.NewBuffer(self.Client(), 1, id, bufferHandler{h.s, b})
125	if err != nil {
126		return
127	}
128	h.p.refs++
129	h.s.bufs[res.Resource] = b
130	h.s.stats.Buffers++
131	res.OnDestroy = func() {
132		delete(h.s.bufs, res.Resource)
133		h.s.stats.DestroyedBuffers++
134		h.p.refs--
135		h.p.release()
136	}
137}
138func (h *poolHandler) Destroy(*wayland.ShmPool)       { h.p.destroyed = true; h.p.release() }
139func (h *poolHandler) Resize(*wayland.ShmPool, int32) {}
140
141type bufferHandler struct {
142	s *Server
143	b *buffer
144}
145
146func (bufferHandler) Destroy(*wayland.Buffer) {}
147
148type outputSourceManager struct{ s *Server }
149
150func (m outputSourceManager) CreateSource(self *extimagecapturesource.ExtOutputImageCaptureSourceManagerV1, id uint32, out *wayland.Output) {
151	m.s.newSource(self.Client(), id, &source{kind: "output", out: m.s.outputOf(out.Resource)})
152}
153func (outputSourceManager) Destroy(*extimagecapturesource.ExtOutputImageCaptureSourceManagerV1) {}
154
155type source struct {
156	kind   string // output, region, workspace
157	out    *output
158	region [4]int32
159	ws     *workspace
160	gone   bool // the workspace handle was already removed
161}
162
163func (s *Server) newSource(c server.Client, id uint32, src *source) {
164	res, err := extimagecapturesource.NewExtImageCaptureSourceV1(c, 1, id, sourceHandler{})
165	if err != nil {
166		return
167	}
168	s.sources[res.Resource] = src
169	res.OnDestroy = func() { delete(s.sources, res.Resource) } // sessions keep their own pointer
170}
171
172type sourceHandler struct{}
173
174func (sourceHandler) Destroy(*extimagecapturesource.ExtImageCaptureSourceV1) {}

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 2

Tags 9

↑↓ moveenter openesc close