scene.go RawHistoryFolder

1package ports
2
3import "os"
4
5// Scene carries core → renderer immutable snapshots with fresh Windows slices,
6// one per output. Rects and the output size are logical and local to the
7// output; the renderer multiplies by Scale.
8type Scene struct {
9	// Security is the owner epoch captured when this scene was published.
10	// Output owners reject stale scenes rather than showing a queued desktop
11	// or accepting old locker buffers across acquisition/release.
12	Security                  SecurityState
13	Output                    string
14	Seq                       uint64
15	OutputWidth, OutputHeight int
16	Scale                     float64
17	// Off turns the display off (output power management): nothing is
18	// drawn until a scene without it.
19	Off        bool
20	Background string
21	Border     Border
22	// WorkspaceClip bounds workspace windows, their popups and separators
23	// in logical output coordinates. Zero inherits the full output. Layers
24	// remain output-wide; overview previews do not use this clip.
25	WorkspaceClip Rect
26	// Dim darkens the background, bottom layers and tiles (tile lines
27	// included) inside WorkspaceClip when set, with black at this opacity,
28	// 0 to 1, under the first
29	// visible float. 0 draws nothing.
30	Dim     float64
31	Windows []SceneWindow
32	// Separators are the lines between windows, drawn in slice order with
33	// the Border colors: tile lines over the tiles, under the floats; a
34	// float's border right after the float.
35	Separators []Separator
36	// DropHints show where a dragged tile lands, filled with Border.Active
37	// over the windows of the workspace, under the top layers. Only the
38	// output under the pointer has them, during a drag.
39	DropHints []Rect
40	// Layers are the shown layer surfaces, drawn in slice order: background
41	// and bottom before windows, top and overlay after. Core leaves out
42	// those a fullscreen window hides (all but the background and a surface
43	// taking the keyboard exclusively); adapters draw every layer given.
44	// Window popups are drawn after the windows, layer popups
45	// (SceneWindow.OverLayers) last, over every layer.
46	Layers []SceneLayer
47	// Capture is the capture state of this output: exclusion and hidden
48	// workspace; nil while nothing is captured (capture.go).
49	Capture *SceneCapture
50	// CaptureScene is the workspace captured off screen (Capture.Workspace)
51	// drawn for capture only: a workspace that is not on screen. Only the
52	// root scene carries it; CaptureScene.Capture and .CaptureScene are nil.
53	CaptureScene *Scene
54	// CaptureIndicators are the marks of live captures of this output,
55	// drawn over everything; nil when none. Captures never hold them: the
56	// capture pipeline serves requests from a scene without them.
57	CaptureIndicators []CaptureIndicator
58}
59
60// Shows reports whether the scene draws the surface of id: only its
61// content changes need a new frame. A window scrolled off the output is
62// not drawn. WorkspaceClip also excludes off-viewport windows; OverLayers
63// popups remain output-wide.
64func (s Scene) Shows(id WindowID) bool {
65	for _, w := range s.Windows {
66		if w.ID == id && !w.Hidden && w.Rect.Overlaps(Rect{W: s.OutputWidth, H: s.OutputHeight}) &&
67			(w.OverLayers || s.WorkspaceClip == (Rect{}) || w.Rect.Overlaps(s.WorkspaceClip)) {
68			return true
69		}
70	}
71	for _, l := range s.Layers {
72		if l.ID == id {
73			return true
74		}
75	}
76	return false
77}
78
79// Border carries the window border style; colors are #rrggbb, "" skips
80// drawing. Width is in logical pixels.
81type Border struct {
82	Width            int
83	Active, Inactive string
84}
85
86// Separator is a line between windows, in logical pixels. Active lines
87// mark the focused window and use Border.Active, others Border.Inactive.
88// Window is the float whose border it is; 0 for lines between tiles.
89type Separator struct {
90	Rect   Rect
91	Active bool
92	Window WindowID
93}
94
95// SceneLayer carries core → renderer layer surface placement.
96type SceneLayer struct {
97	ID    WindowID
98	Layer Layer
99	Rect  Rect
100}
101
102// SurfaceColor is the committed encoding of a surface. Zero means sRGB.
103// PQ+BT.2020 and extended-linear sRGB are color-managed; zero is legacy
104// sRGB. MaxCLL/MaxFALL are in nits. YUV metadata is per surface commit.
105type SurfaceColor struct {
106	TF, Primaries   uint8
107	MaxCLL, MaxFALL uint16
108	// Coefficients/range follow wp_color_representation_v1 (zero =
109	// unspecified, for YUV interpreted as BT.709 limited). Chroma is a
110	// H.273 Chroma420SampleLocType + 1 (zero defaults to type 0).
111	Coefficients, Range, Chroma uint8
112}
113
114const (
115	ColorTFPQ             uint8 = 11 // wp_color_manager_v1 ST2084 PQ
116	ColorTFExtendedLinear uint8 = 5  // wp_color_manager_v1 ext_linear
117	ColorPrimariesBT2020  uint8 = 6  // wp_color_manager_v1 BT.2020
118	ColorPrimariesSRGB    uint8 = 1
119)
120
121func (c SurfaceColor) IsPQ2020() bool {
122	return c.TF == ColorTFPQ && c.Primaries == ColorPrimariesBT2020
123}
124
125func (c SurfaceColor) IsExtendedLinear() bool {
126	return c.TF == ColorTFExtendedLinear && c.Primaries == ColorPrimariesSRGB
127}
128
129// ContentType is the committed wp_content_type_v1 hint.
130type ContentType uint8
131
132const (
133	ContentNone ContentType = iota
134	ContentPhoto
135	ContentVideo
136	ContentGame
137)
138
139// SurfaceContent carries wayland → output the latest committed content of a
140// window: SHM, a client shared-memory buffer, or DMABuf, a GPU buffer.
141// Renderers read both in place and never modify them. Empty means the window
142// has no content. LogicalW and LogicalH are the surface size in logical
143// pixels (buffer scale and viewport applied). Subsurfaces come in Children;
144// Geometry is the part of the surface that is the window (xdg window
145// geometry), the rest being client shadows.
146type SurfaceContent struct {
147	ID          WindowID
148	ContentType ContentType
149	// Surface is a never-reused wl_surface identity; Version identifies its
150	// applied buffer content independently of the window publication Seq.
151	Surface, Version uint64
152	// Seq counts the window's contents (wayland sets it), for release.
153	Seq                uint64
154	Width, Height      int
155	LogicalW, LogicalH int
156	// Source is the committed crop in buffer pixels: x, y, width, height.
157	// Zero width means the entire buffer is used.
158	Source [4]float32
159	// Transform is the wl_output.transform the client applied to the
160	// buffer: readers apply its inverse. Width and Height stay the buffer's.
161	Transform BufferTransform
162	// Opaque ignores the alpha byte: an x format, or an opaque region that
163	// covers the whole surface. It is false while Fade is set.
164	Opaque bool
165	// Fade is how much wp_alpha_modifier_v1 fades the surface: 0 none,
166	// 1 invisible. Its opacity is multiplied by 1-Fade.
167	Fade   float32
168	Color  SurfaceColor
169	SHM    *SHMBuffer
170	DMABuf *DMABuf
171	// Children are the subsurfaces, bottom to top, flattened.
172	Children []Subsurface
173	// Geometry is in logical pixels from the surface origin; empty means
174	// the whole surface.
175	Geometry Rect
176	// Async asks for tearing presentation (wp_tearing_control_v1); outputs
177	// honour it only in direct scanout.
178	Async bool
179	// Acquire is the explicit-sync fence of this content's root buffer
180	// (wp_linux_drm_syncobj_v1): readers wait on it before reading the
181	// buffer, instead of the buffer's implicit fences. Wayland owns it and
182	// closes it when the buffer is released; a reader that keeps it past
183	// the call duplicates it under Acquire.SyscallConn. nil: implicit sync.
184	// Wayland closes it only after every output reported a later content of
185	// the window as seen, so a reader never gets it already closed.
186	Acquire *os.File
187	// DamageHistory is what changed in the root surface's buffer over the
188	// window's last contents, oldest first, ending with this one (Seq).
189	// A renderer holding an older content redraws the union of the
190	// entries after it, or everything when the history does not reach it.
191	DamageHistory []SeqDamage
192}
193
194// BufferTransform is a wl_output.transform value: bit 0 rotates 90°
195// counter-clockwise, bit 1 rotates 180°, bit 2 flips around the vertical
196// axis first.
197type BufferTransform uint8
198
199// Rotated reports whether width and height swap between buffer and surface.
200func (t BufferTransform) Rotated() bool { return t&1 != 0 }
201
202// ToBuffer maps a point of a w×h surface (logical, before scale) to the
203// same point of its buffer, in the buffer's untransformed w'×h' axes, where
204// w' and h' swap when the transform is Rotated.
205func (t BufferTransform) ToBuffer(x, y, w, h float64) (float64, float64) {
206	if t&4 != 0 {
207		x = w - x
208	}
209	switch t & 3 {
210	case 1:
211		return y, w - x
212	case 2:
213		return w - x, h - y
214	case 3:
215		return h - y, x
216	}
217	return x, y
218}
219
220// SeqDamage is what content Seq changed from the one before: Rects in
221// root buffer pixels, or everything when Full.
222type SeqDamage struct {
223	Seq   uint64
224	Full  bool
225	Rects []Rect
226}
227
228// DamageSince is the union of changes after content seq up to this one,
229// and false when the history does not reach back to seq (redraw all).
230func (c SurfaceContent) DamageSince(seq uint64) ([]Rect, bool) {
231	if seq >= c.Seq {
232		return nil, true
233	}
234	h := c.DamageHistory
235	if len(h) == 0 || h[0].Seq > seq+1 || h[len(h)-1].Seq != c.Seq {
236		return nil, false
237	}
238	var out []Rect
239	for _, d := range h {
240		if d.Seq <= seq {
241			continue
242		}
243		if d.Full {
244			return nil, false
245		}
246		out = append(out, d.Rects...)
247	}
248	return out, true
249}
250
251// Subsurface is a child surface at X, Y logical pixels from the root
252// surface origin. Below children are drawn under the root surface.
253type Subsurface struct {
254	X, Y  int
255	Below bool
256	SurfaceContent
257}
258
259// Empty reports whether the content has nothing to draw.
260func (c SurfaceContent) Empty() bool {
261	return c.SHM == nil && c.DMABuf == nil && len(c.Children) == 0
262}
263
264// SHMBuffer is a client wl_shm buffer: B8G8R8A8 pixels (argb8888/xrgb8888
265// little-endian) at Offset in the pool File, Stride bytes per row. The
266// client keeps writing the file, so renderers copy from it when they draw.
267// Pool is unique per wl_shm pool for the session: renderers map a pool
268// once. File stays open while the client's buffer exists and follows the
269// DMABuf rules: duplicate it under File.SyscallConn before keeping it. A
270// client may shrink the file at any time, so readers must survive faults.
271type SHMBuffer struct {
272	Pool           uint64
273	File           *os.File
274	Offset, Stride int
275}
276
277// DMABuf is a client GPU buffer (linux-dmabuf). Its files stay open while
278// the client's buffer exists; a renderer that keeps it must duplicate the
279// descriptors under File.SyscallConn so a concurrent close cannot hand it a
280// reused one. ID is unique per buffer for the whole session: renderers key
281// their imports on it.
282type DMABuf struct {
283	ID            uint64
284	Width, Height int
285	Format        uint32 // DRM fourcc
286	Modifier      uint64
287	Planes        []DMABufPlane
288}
289
290// DMABufPlane is one plane of a DMABuf.
291type DMABufPlane struct {
292	File           *os.File
293	Offset, Stride uint32
294}
295
296// DMABufFormat is a DRM fourcc with a modifier the renderer can import.
297type DMABufFormat struct {
298	Format   uint32
299	Modifier uint64
300}
301
302// DMABufSupport is what the renderer imports: the render device (a dev_t,
303// 0 when unknown) and the formats. No formats means no dmabuf.
304type DMABufSupport struct {
305	Device  uint64
306	Formats []DMABufFormat
307}
308
309// SceneWindow carries core → renderer window placement.
310type SceneWindow struct {
311	ID                          WindowID
312	Rect                        Rect
313	Focused, Fullscreen, Hidden bool
314	// Inset sides carry a separator line inside Rect: the client is drawn
315	// inside it.
316	Inset Sides
317	// Floating windows draw at their placed size. Below marks a native
318	// covering float behind the column group.
319	Floating, Below bool
320	// Dim darkens the window, border included, with black at this
321	// opacity, 0 to 1: a stashed window peeking in. 0 draws nothing.
322	Dim float64
323	// FocusEffect, above 0, is the focus indicator's effect at this frame
324	// (focus.animation, focus.effect): the window's surfaces are lifted
325	// toward white by that fraction (screen blend). Renderers without the
326	// effect ignore it.
327	//
328	// Only focus.effect = screen exists, so the effect kind is not carried:
329	// core ignores Config.Focus.Effect and the shaders always apply screen
330	// (compose.frag, compose_hdr.frag, push constant mapy.z). A second effect
331	// needs its kind here and in the push constants (a misc flag).
332	FocusEffect float64
333	// Preview, above 0, draws the window's surfaces that much smaller in
334	// Rect (an overview thumbnail): the client keeps its size.
335	Preview float64
336	// Popups are drawn from their content only: no border, no background.
337	Popup bool
338	// OverLayers popups hang from a layer surface: drawn over the top and
339	// overlay layers. Window popups stay with the windows, under them.
340	OverLayers bool
341}

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 25

Tags 10

↑↓ moveenter openesc close