v0.4.0 5f1ad00

globals.go RawHistoryFolder

1package neferclient
2
3import (
4	"errors"
5	"fmt"
6
7	"github.com/bnema/go-wayland-bindings/client/extsessionlock"
8	"github.com/bnema/go-wayland-bindings/client/fractionalscale"
9	"github.com/bnema/go-wayland-bindings/client/linuxdmabuf"
10	"github.com/bnema/go-wayland-bindings/client/linuxdrmsyncobj"
11	"github.com/bnema/go-wayland-bindings/client/viewporter"
12	"github.com/bnema/go-wayland-bindings/client/wayland"
13	"github.com/bnema/go-wayland-bindings/client/wlrlayershell"
14	"github.com/bnema/go-wayland-bindings/client/xdgshell"
15	"github.com/bnema/wlturbo/wl"
16)
17
18// CapabilityError reports a missing or too old required protocol global.
19type CapabilityError struct {
20	Name  string
21	Cause error
22}
23
24func (e *CapabilityError) Error() string {
25	return fmt.Sprintf("neferclient: capability %s: %v", e.Name, e.Cause)
26}
27func (e *CapabilityError) Unwrap() error { return e.Cause }
28
29// globals holds the protocol globals bound on first use. Owner goroutine only.
30type globals struct {
31	compositor *wayland.Compositor
32	dmabuf     *linuxdmabuf.LinuxDmabuf
33	syncobj    *linuxdrmsyncobj.WpLinuxDrmSyncobjManager
34	xdg        *xdgshell.XdgWmBase
35	layer      *wlrlayershell.LayerShell
36	lockMgr    *extsessionlock.ExtSessionLockManager
37	viewporter *viewporter.WpViewporter
38	fscale     *fractionalscale.WpFractionalScaleManager
39
40	layerVersion  uint32
41	xdgVersion    uint32
42	triedViewport bool
43	triedFScale   bool
44}
45
46// require binds iface at min(announced, supported) and fails with a
47// *CapabilityError when it is absent or older than minimum.
48func (c *Conn) require[P wl.Proxy](iface string, supported, minimum uint32, newProxy func(*wl.Context) P) (P, uint32, error) {
49	p, v, err := c.Bind(iface, supported, newProxy)
50	if err != nil {
51		var zero P
52		return zero, 0, &CapabilityError{Name: iface, Cause: err}
53	}
54	if v < minimum {
55		var zero P
56		return zero, 0, &CapabilityError{Name: iface, Cause: fmt.Errorf("requires version %d, negotiated %d", minimum, v)}
57	}
58	return p, v, nil
59}
60
61// ensureCore binds wl_compositor, linux-dmabuf (v4) and drm-syncobj, and the
62// optional viewporter and fractional-scale managers.
63func (c *Conn) ensureCore() error {
64	g := &c.g
65	var err error
66	if g.compositor == nil {
67		if g.compositor, _, err = c.require(wayland.CompositorInterface, 6, 4, wayland.NewCompositor); err != nil {
68			return err
69		}
70	}
71	if g.dmabuf == nil {
72		if g.dmabuf, _, err = c.require(linuxdmabuf.LinuxDmabufInterface, 4, 4, linuxdmabuf.NewLinuxDmabuf); err != nil {
73			return err
74		}
75	}
76	if g.syncobj == nil {
77		if g.syncobj, _, err = c.require(linuxdrmsyncobj.WpLinuxDrmSyncobjManagerInterface, 1, 1, linuxdrmsyncobj.NewWpLinuxDrmSyncobjManager); err != nil {
78			return err
79		}
80	}
81	if !g.triedViewport {
82		g.triedViewport = true
83		v, _, e := c.Bind(viewporter.WpViewporterInterface, 1, viewporter.NewWpViewporter)
84		if e != nil && !errors.Is(e, ErrGlobalNotFound) {
85			return e
86		}
87		g.viewporter = v
88	}
89	if !g.triedFScale {
90		g.triedFScale = true
91		v, _, e := c.Bind(fractionalscale.WpFractionalScaleManagerInterface, 1, fractionalscale.NewWpFractionalScaleManager)
92		if e != nil && !errors.Is(e, ErrGlobalNotFound) {
93			return e
94		}
95		g.fscale = v
96	}
97	return nil
98}
99
100func (c *Conn) ensureXdg() error {
101	if c.g.xdg != nil {
102		return nil
103	}
104	q := c.q
105	x, v, err := c.require(xdgshell.XdgWmBaseInterface, 6, 1, func(ctx *wl.Context) *xdgshell.XdgWmBase {
106		x := xdgshell.NewXdgWmBase(ctx)
107		x.OnPing(func(serial uint32) {
108			e := event{kind: evPing, serial: serial}
109			q.post(&e)
110		})
111		return x
112	})
113	c.g.xdg, c.g.xdgVersion = x, v
114	return err
115}
116
117func (c *Conn) ensureLayerShell() error {
118	if c.g.layer != nil {
119		return nil
120	}
121	l, v, err := c.require(wlrlayershell.LayerShellInterface, 4, 1, wlrlayershell.NewLayerShell)
122	c.g.layer, c.g.layerVersion = l, v
123	return err
124}
125
126func (c *Conn) ensureLockManager() error {
127	if c.g.lockMgr != nil {
128		return nil
129	}
130	m, _, err := c.require(extsessionlock.ExtSessionLockManagerInterface, 1, 1, extsessionlock.NewExtSessionLockManager)
131	c.g.lockMgr = m
132	return err
133}

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 1

Tags 4

↑↓ moveenter openesc close