v0.2.1 7e79979

capture.go RawHistoryFolder

1// Package ports defines framework-independent capture contracts.
2package ports
3
4import (
5	"context"
6	"io"
7	"time"
8)
9
10// Output IDs are stable only within a Source connection. Name is wl_output.name.
11type Output struct {
12	ID            uint32
13	Name          string
14	Width, Height int // physical mode dimensions, informational
15	Scale         int
16}
17
18// Region uses output-local logical coordinates. Zero value means the full output.
19type Region struct{ X, Y, Width, Height int }
20
21type Target struct {
22	OutputID uint32
23	Region   Region
24	// WorkspaceID is a Source-local identity from Source.Workspaces, never an
25	// index or monitor alias. Nonzero requires a zero Region. A workspace
26	// that is not displayed can be captured only if the compositor supports
27	// it; otherwise it is captured as its output while Active.
28	WorkspaceID uint64
29}
30
31// Capabilities says what the compositor behind a Source offers beyond
32// capturing whole outputs. It is fixed once the Source is created.
33type Capabilities struct {
34	// Workspaces: Source.Workspaces lists the compositor's workspaces.
35	Workspaces bool
36	// Exclusion: a client's own layer surfaces can be left out of its frames,
37	// so a recording indicator can be shown without appearing in the video.
38	Exclusion bool
39}
40
41// Workspace is compositor workspace metadata. Region is output-local, logical
42// geometry (the whole output). Active means this workspace is displayed.
43type Workspace struct {
44	ID       uint64
45	OutputID uint32
46	Name     string
47	Region   Region
48	Active   bool
49}
50
51// PixelFormat names the native little-endian wl_shm 32-bit pixel layout.
52type PixelFormat uint32
53
54const (
55	ARGB8888 PixelFormat = 0
56	XRGB8888 PixelFormat = 1
57)
58
59// Frame borrows storage from Source until the next Capture or Close call.
60// Consumers must finish reading synchronously and must not retain Pixels.
61// Output is opaque SDR.
62type Frame struct {
63	Pixels                []byte
64	Width, Height, Stride int
65	Format                PixelFormat
66}
67
68// Source has one sequential owner; cancellation must interrupt blocked I/O.
69// Cancellation errors wrap ctx.Err(), not a custom cancellation cause.
70// A failed Capture invalidates its borrowed frame. Close is idempotent.
71type Source interface {
72	Capabilities() Capabilities
73	Outputs(context.Context) ([]Output, error)
74	// Workspaces returns nil without error when the compositor has none.
75	Workspaces(context.Context) ([]Workspace, error)
76	Capture(context.Context, Target) (Frame, error)
77	Close() error
78}
79
80// ScreenshotWriter writes an opaque PNG without overwriting an existing path.
81// Save completes all reads from borrowed frame storage before returning.
82type ScreenshotWriter interface {
83	Save(context.Context, Frame, string) error
84	// Encode consumes borrowed pixels synchronously without creating a file.
85	Encode(context.Context, io.Writer, Frame) error
86}
87
88// Clipboard accepts PNG bytes synchronously. Its owner may outlive this process.
89type Clipboard interface {
90	Copy(context.Context, io.Reader) error
91}
92
93// VideoSettings describes fixed-rate silent SDR video. Zero output dimensions
94// retain source resolution. Both dimensions must be specified for scaling.
95type VideoSettings struct {
96	FPS           int
97	Width, Height int
98}
99
100// VideoWriter has one owner. Start fixes input geometry and reserves a new path.
101// Start does not encode its frame; pass the first frame explicitly to Write.
102// Start rejects input/output geometry that its encoder cannot use; it must not
103// silently crop when zero output dimensions request source resolution.
104// Write consumes borrowed pixels before returning; it must not queue frames.
105// Close drains and finalizes the encoder with a bounded shutdown deadline.
106// Abort as the first terminal operation interrupts writes and discards output.
107// Abort is safe concurrently with Write or a draining Close. During Close it
108// escalates shutdown unless Close already observed encoder exit; Close's result
109// is authoritative. Abort after completed Close is a no-op. Close after Abort
110// returns Abort's cleanup result. Close preserves frames on a clean exit.
111// Cancellation errors wrap ctx.Err(); unrelated failures must be preserved.
112// Write rejects width, height or format changes with ErrGeometryChanged.
113// Stride changes are allowed. Close and Abort are idempotent terminal operations;
114// Write after termination returns ErrClosed. Other methods have one owner.
115type VideoWriter interface {
116	Start(context.Context, Frame, string, VideoSettings) error
117	Write(context.Context, Frame) error
118	Close() error
119	Abort() error
120}
121
122type Mode string
123
124const (
125	Screenshot Mode = "screenshot"
126	Record     Mode = "record"
127)
128
129// Selection is returned by a control panel before capture begins.
130type Selection struct {
131	Mode      Mode
132	Target    Target
133	Path      string
134	Clipboard bool // screenshot only; permits an empty Path
135	Video     VideoSettings
136	Duration  time.Duration // zero records until context cancellation
137}
138
139// Selector must close its surface before returning an accepted selection.
140type Selector interface {
141	Select(context.Context, []Output) (Selection, bool, error)
142}

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