v0.3.0 2df0761

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	triedViewport bool
42	triedFScale   bool
43}
44
45// require binds iface at min(announced, supported) and fails with a
46// *CapabilityError when it is absent or older than minimum.
47func (c *Conn) require[P wl.Proxy](iface string, supported, minimum uint32, newProxy func(*wl.Context) P) (P, uint32, error) {
48	p, v, err := c.Bind(iface, supported, newProxy)
49	if err != nil {
50		var zero P
51		return zero, 0, &CapabilityError{Name: iface, Cause: err}
52	}
53	if v < minimum {
54		var zero P
55		return zero, 0, &CapabilityError{Name: iface, Cause: fmt.Errorf("requires version %d, negotiated %d", minimum, v)}
56	}
57	return p, v, nil
58}
59
60// ensureCore binds wl_compositor, linux-dmabuf (v4) and drm-syncobj, and the
61// optional viewporter and fractional-scale managers.
62func (c *Conn) ensureCore() error {
63	g := &c.g
64	var err error
65	if g.compositor == nil {
66		if g.compositor, _, err = c.require(wayland.CompositorInterface, 6, 4, wayland.NewCompositor); err != nil {
67			return err
68		}
69	}
70	if g.dmabuf == nil {
71		if g.dmabuf, _, err = c.require(linuxdmabuf.LinuxDmabufInterface, 4, 4, linuxdmabuf.NewLinuxDmabuf); err != nil {
72			return err
73		}
74	}
75	if g.syncobj == nil {
76		if g.syncobj, _, err = c.require(linuxdrmsyncobj.WpLinuxDrmSyncobjManagerInterface, 1, 1, linuxdrmsyncobj.NewWpLinuxDrmSyncobjManager); err != nil {
77			return err
78		}
79	}
80	if !g.triedViewport {
81		g.triedViewport = true
82		v, _, e := c.Bind(viewporter.WpViewporterInterface, 1, viewporter.NewWpViewporter)
83		if e != nil && !errors.Is(e, ErrGlobalNotFound) {
84			return e
85		}
86		g.viewporter = v
87	}
88	if !g.triedFScale {
89		g.triedFScale = true
90		v, _, e := c.Bind(fractionalscale.WpFractionalScaleManagerInterface, 1, fractionalscale.NewWpFractionalScaleManager)
91		if e != nil && !errors.Is(e, ErrGlobalNotFound) {
92			return e
93		}
94		g.fscale = v
95	}
96	return nil
97}
98
99func (c *Conn) ensureXdg() error {
100	if c.g.xdg != nil {
101		return nil
102	}
103	q := c.q
104	x, _, err := c.require(xdgshell.XdgWmBaseInterface, 6, 1, func(ctx *wl.Context) *xdgshell.XdgWmBase {
105		x := xdgshell.NewXdgWmBase(ctx)
106		x.OnPing(func(serial uint32) {
107			e := event{kind: evPing, serial: serial}
108			q.post(&e)
109		})
110		return x
111	})
112	c.g.xdg = x
113	return err
114}
115
116func (c *Conn) ensureLayerShell() error {
117	if c.g.layer != nil {
118		return nil
119	}
120	l, v, err := c.require(wlrlayershell.LayerShellInterface, 4, 1, wlrlayershell.NewLayerShell)
121	c.g.layer, c.g.layerVersion = l, v
122	return err
123}
124
125func (c *Conn) ensureLockManager() error {
126	if c.g.lockMgr != nil {
127		return nil
128	}
129	m, _, err := c.require(extsessionlock.ExtSessionLockManagerInterface, 1, 1, extsessionlock.NewExtSessionLockManager)
130	c.g.lockMgr = m
131	return err
132}

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