1package ports
2
3import "slices"
4
5// SelectionOutline is a selection ring outside a preview. Rect and Radius
6// describe its outer edge; Radius zero denotes square corners.
7type SelectionOutline struct {
8 Rect Rect
9 Width int
10 Radius int
11 Active bool
12}
13
14// Scene carries core → renderer immutable snapshots with fresh Windows slices,
15// one per output. Rects and the output size are logical and local to the
16// output; the renderer multiplies by Scale.
17type Scene struct {
18 Outline *SelectionOutline
19 // Security is the owner epoch captured when this scene was published.
20 // Output owners reject stale scenes rather than showing a queued desktop
21 // or accepting old locker buffers across acquisition/release.
22 Security SecurityState
23 Output string
24 Seq uint64
25 OutputWidth, OutputHeight int
26 Scale float64
27 // Transform is how the output target holds this scene
28 // (wl_output.transform); 0 for capture child scenes. OutputWidth and
29 // OutputHeight are already in the transformed (logical) orientation.
30 Transform BufferTransform
31 // Off turns the display off (output power management): nothing is
32 // drawn until a scene without it.
33 Off bool
34 Background string
35 Border Border
36 // WorkspaceClip bounds workspace windows, their popups and separators
37 // in logical output coordinates. Zero inherits the full output. Layers
38 // remain output-wide; overview previews do not use this clip.
39 WorkspaceClip Rect
40 // TileInset is what exclusive layers (panels) and a workspace size
41 // override take from the output's edges: tiles (SceneWindow.Tile) and
42 // their lines are drawn only in what is left, the usable area
43 // (TileArea). A tile is never drawn over a panel, whatever its layer;
44 // insets covering the output leave no tile drawn. Zero: the usable
45 // area is the whole output (and the overview, capture scenes).
46 TileInset Insets
47 // Dim darkens the background, bottom layers and tiles (tile lines
48 // included) inside WorkspaceClip when set, with black at this opacity,
49 // 0 to 1, under the first
50 // visible float. 0 draws nothing.
51 Dim float64
52 // DimBehind draws the Dim veil under every window instead, right over
53 // the background and bottom layers (the overview).
54 DimBehind bool
55 Windows []SceneWindow
56 // Separators are the lines between windows, drawn in slice order with
57 // the Border colors: tile lines over the tiles, under the floats; a
58 // float's border right after the float.
59 Separators []Separator
60 // DropHints show where a dragged tile lands, filled with Border.Active
61 // over the windows of the workspace, under the top layers. Only the
62 // output under the pointer has them, during a drag.
63 DropHints []Rect
64 // Layers are the shown layer surfaces, drawn in slice order: background
65 // and bottom before windows, top and overlay after. Core leaves out
66 // those a fullscreen window hides (all but the background and a surface
67 // taking the keyboard exclusively); adapters draw every layer given.
68 // Window popups are drawn after the windows, layer popups
69 // (SceneWindow.OverLayers) last, over every layer.
70 Layers []SceneLayer
71 // Capture is the capture state of this output: exclusion and hidden
72 // workspace; nil while nothing is captured (capture.go).
73 Capture *SceneCapture
74 // CaptureScene is the workspace captured off screen (Capture.Workspace)
75 // drawn for capture only: a workspace that is not on screen. Only the
76 // root scene carries it; CaptureScene.Capture and .CaptureScene are nil.
77 CaptureScene *Scene
78 // CaptureIndicators are the marks of live captures of this output,
79 // drawn over everything; nil when none. Captures never hold them: the
80 // capture pipeline serves requests from a scene without them.
81 CaptureIndicators []CaptureIndicator
82 // HintLabels are the keyboard hint labels of this output, drawn over
83 // everything, after CaptureIndicators; nil when hint mode is not shown
84 // here. Captures never contain them unless HintStyle.Capture is set, and
85 // then only those of Wayland clients.
86 HintLabels []HintLabel
87 HintStyle HintStyle
88 // Flash is the focus flash drawn over everything of this output; nil
89 // draws nothing.
90 Flash *FocusFlash
91 // PositionHint is drawn on the physical output only, never in captures.
92 PositionHint PositionHint
93 // Animating is set by core when a spring, a focus flash or a position
94 // hint fade runs on this output after this frame was computed: the
95 // output reports the flip of the scene to core (OutputFrame), which
96 // moves the animation to the next frame. A scene of a settled output carries false, so a flip
97 // of it wakes nobody. It describes scheduling, not drawing: SameAs and
98 // the renderer ignore it.
99 Animating bool
100}
101
102// SameAs reports whether o draws exactly what s draws: every field other
103// than Seq and Animating (scheduling only, not drawn) is equal. A scene
104// carrying a CaptureScene is never the same (conservative: the capture image
105// is not compared). Add every new Scene field here;
106// TestSceneSameAsCoversEveryField fails until the field count is updated.
107func (s Scene) SameAs(o Scene) bool {
108 if s.PositionHint != o.PositionHint || s.Security != o.Security || s.Output != o.Output ||
109 s.OutputWidth != o.OutputWidth || s.OutputHeight != o.OutputHeight ||
110 s.Scale != o.Scale || s.Transform != o.Transform || s.Off != o.Off ||
111 s.Background != o.Background || s.Border != o.Border ||
112 s.WorkspaceClip != o.WorkspaceClip || s.TileInset != o.TileInset || s.Dim != o.Dim || s.DimBehind != o.DimBehind {
113 return false
114 }
115 if (s.Flash == nil) != (o.Flash == nil) || (s.Flash != nil && *s.Flash != *o.Flash) {
116 return false
117 }
118 if (s.Outline == nil) != (o.Outline == nil) || (s.Outline != nil && *s.Outline != *o.Outline) {
119 return false
120 }
121 if s.CaptureScene != nil || o.CaptureScene != nil {
122 return false
123 }
124 if (s.Capture == nil) != (o.Capture == nil) {
125 return false
126 }
127 if s.Capture != nil {
128 a, b := *s.Capture, *o.Capture
129 if a.Shown != b.Shown || a.Session != b.Session || a.Revision != b.Revision ||
130 a.Workspace != b.Workspace || a.Window != b.Window || !slices.Equal(a.Excluded, b.Excluded) {
131 return false
132 }
133 }
134 return slices.Equal(s.Windows, o.Windows) && slices.Equal(s.Separators, o.Separators) &&
135 slices.Equal(s.DropHints, o.DropHints) && slices.Equal(s.Layers, o.Layers) &&
136 slices.Equal(s.CaptureIndicators, o.CaptureIndicators) &&
137 s.HintStyle == o.HintStyle && slices.Equal(s.HintLabels, o.HintLabels)
138}
139
140// Shows reports whether the scene draws the surface of id: only its
141// content changes need a new frame. A window scrolled off the output is
142// not drawn (Draws).
143func (s Scene) Shows(id WindowID) bool {
144 for _, w := range s.Windows {
145 if w.ID == id && s.Draws(w) {
146 return true
147 }
148 }
149 for _, l := range s.Layers {
150 if l.ID == id {
151 return true
152 }
153 }
154 return false
155}
156
157// Draws reports whether any of w is drawn: not hidden, on the output,
158// inside WorkspaceClip (OverLayers popups remain output-wide) and, for a
159// tile, inside TileArea.
160func (s Scene) Draws(w SceneWindow) bool {
161 if w.Hidden || !w.Rect.Overlaps(Rect{W: s.OutputWidth, H: s.OutputHeight}) {
162 return false
163 }
164 if !w.OverLayers && s.WorkspaceClip != (Rect{}) && !w.Rect.Overlaps(s.WorkspaceClip) {
165 return false
166 }
167 if a, ok := s.TileArea(); ok && w.Tile() {
168 return w.Rect.Overlaps(a)
169 }
170 return true
171}
172
173// TileArea is where tiles are drawn: the output minus TileInset, empty
174// when the panels cover it. ok is false when TileInset is zero: tiles are
175// not clipped beyond the output and WorkspaceClip.
176func (s Scene) TileArea() (r Rect, ok bool) {
177 in := s.TileInset
178 if in == (Insets{}) {
179 return Rect{}, false
180 }
181 return Rect{X: in.Left, Y: in.Top, W: max(s.OutputWidth-in.Left-in.Right, 0), H: max(s.OutputHeight-in.Top-in.Bottom, 0)}, true
182}
183
184// Border carries the window border style; colors are #rrggbb, "" skips
185// drawing. Width and Radius are in logical pixels.
186type Border struct {
187 // Radius is the corner radius in logical pixels, >= 0. It rounds
188 // floats always and tiles when gaps > 0; the renderer uses
189 // SceneWindow.Radius, which core sets per window.
190 Radius int
191 Width int
192 Active, Inactive string
193}
194
195// Separator is a line between windows, in logical pixels. Active lines
196// mark the focused window and use Border.Active, others Border.Inactive.
197// Window owns the border (floats and tiles with gaps); 0 for shared tile lines.
198type Separator struct {
199 Rect Rect
200 Active bool
201 Window WindowID
202}
203
204// SceneLayer carries core → renderer layer surface placement.
205type SceneLayer struct {
206 ID WindowID
207 Layer Layer
208 Rect Rect
209}
210
211// FocusFlash is a brief inner border marking the entity an action just
212// changed: a window, a column or a whole output. Rect is in logical
213// pixels, Width the border width inside it, Color #rrggbb and Alpha its
214// opacity at this frame (0 to 1).
215type FocusFlash struct {
216 Rect Rect
217 Width int
218 // Radius is the target's corner radius in logical pixels (0 = square),
219 // the same as SceneWindow.Radius; the border follows it.
220 Radius int
221 Color string
222 Alpha float64
223}
224
225// SceneWindow carries core → renderer window placement.
226type SceneWindow struct {
227 // Radius rounds the window corners in logical pixels; zero is square.
228 // Core sets Border.Radius here for floats and tiles with gaps.
229 Radius int
230 ID WindowID
231 Rect Rect
232 Focused, Fullscreen, Hidden bool
233 // Inset sides carry a separator line inside Rect: the client is drawn
234 // inside it.
235 Inset Sides
236 // Floating windows draw at their placed size. Below marks a native
237 // covering float behind the column group.
238 Floating, Below bool
239 // Dim darkens the window, border included, with black at this
240 // opacity, 0 to 1: a stashed window peeking in. 0 draws nothing.
241 Dim float64
242 // Fade makes the whole window translucent, border and content: 0 is
243 // opaque, 1 invisible (like SurfaceContent.Fade). A window appearing
244 // or leaving animates it; a faded window is composed, never scanned
245 // out.
246 Fade float64
247 // Preview, above 0, draws the window's surfaces that much smaller in
248 // Rect (an overview thumbnail): the client keeps its size. A preview
249 // is a card: it never opens the floats.
250 Preview float64
251 // Zoom, above 0, is the content scale of a window whose frame is
252 // animating (appearing, leaving, an overview card in flight): it
253 // replaces Preview for drawing only; the window keeps its kind.
254 Zoom float64
255 // Popups are drawn from their content only: no border, no background.
256 Popup bool
257 // OverLayers popups hang from a layer surface: drawn over the top and
258 // overlay layers. Window popups stay with the windows, under them.
259 OverLayers bool
260}
261
262// Tile reports whether w is a tile: laid out in the usable area and
263// clipped to Scene.TileArea. Floats, fullscreen windows, overview previews
264// and popups are placed against the whole viewport.
265func (w SceneWindow) Tile() bool {
266 return !w.Floating && !w.Fullscreen && !w.Popup && w.Preview == 0
267}
268
269// HintStyle carries reloadable label settings and untransformed output density.
270type HintStyle struct {
271 // Capture (hint.capture) shows the labels in the captures requested by
272 // Wayland clients. Captures requested by the compositor itself
273 // (CaptureIDInternal) never contain them.
274 Capture bool
275 Size float64
276 Background, Foreground string
277 Width, Height, PhysicalW, PhysicalH int
278}