1package app
2
3import (
4 "github.com/bnema/neferwl/internal/adapters/wayland"
5 "github.com/bnema/neferwl/internal/adapters/xkb"
6 "github.com/bnema/neferwl/internal/core"
7 "github.com/bnema/neferwl/internal/ports"
8)
9
10// pipes are the channels between a session's goroutines. newPipes makes
11// them all, with their buffer sizes; core, wayland and outputs hand each
12// side the ends it uses.
13type pipes struct {
14 securityChanges chan ports.SecurityState
15 securityEvents chan ports.SecurityBackendEvent
16
17 client chan ports.ClientEvent
18 input chan ports.InputEvent
19 output chan ports.OutputEvent
20 commands chan ports.ClientCommand
21 spawn chan ports.SpawnRequest
22
23 // Capacity 1: each holds the latest value its sender published.
24 scenes chan []ports.Scene
25 renderScenes chan []ports.Scene
26 layouts chan ports.Layout
27 constraints chan ports.PointerConstraint
28 states chan ports.State
29 workspaces chan ports.Workspaces
30 cursorChanges chan ports.CursorChange
31 keymaps chan *xkb.Keymap
32 touchpads chan ports.TouchpadConfig
33
34 // Configuration: watched from the file, filtered by relayConfig, then
35 // configured (overrides included) by outputs for core.
36 watched chan ports.ConfigChanged
37 filtered chan ports.ConfigChanged
38 configured chan ports.ConfigChanged
39 configErrors chan error
40 // scales is nil outside a real session: headless runs never touch the
41 // config file.
42 scales chan ports.ScaleChanged
43
44 contents chan ports.SurfaceContent
45 presented chan ports.OutputPresented
46 // Outputs report on flips; relayPresented passes them to wayland
47 // (presented) and tells core about each flip (frames) to move running
48 // slides.
49 flips chan ports.OutputPresented
50 frames chan ports.OutputFrame
51
52 captures chan ports.CaptureRequest
53 // Every admitted capture owns one reply slot until wayland consumes it.
54 // Keep this capacity tied to admission so output routing never waits.
55 captured chan ports.CaptureDone
56
57 outputFormats chan ports.OutputFormats
58 outputHeads chan ports.OutputHeads
59 leaseRequests chan ports.LeaseMessage
60 leaseEvents chan ports.LeaseMessage
61 applyOutput chan ports.OutputApply
62 appliedOutput chan ports.OutputApplied
63
64 // D-Bus idle inhibition and SimulateUserActivity (screensaver), for
65 // wayland's idle notifications. Activity sends never block: capacity 1
66 // coalesces them.
67 idleInhibited chan bool
68 idleActivity chan struct{}
69}
70
71func newPipes(realSession bool) *pipes {
72 p := &pipes{
73 securityChanges: make(chan ports.SecurityState, 8),
74 securityEvents: make(chan ports.SecurityBackendEvent, 64),
75
76 client: make(chan ports.ClientEvent, 32),
77 input: make(chan ports.InputEvent, 32),
78 output: make(chan ports.OutputEvent, 32),
79 commands: make(chan ports.ClientCommand, 32),
80 spawn: make(chan ports.SpawnRequest, 32),
81
82 scenes: make(chan []ports.Scene, 1),
83 renderScenes: make(chan []ports.Scene, 1),
84 layouts: make(chan ports.Layout, 1),
85 constraints: make(chan ports.PointerConstraint, 1),
86 states: make(chan ports.State, 1),
87 workspaces: make(chan ports.Workspaces, 1),
88 cursorChanges: make(chan ports.CursorChange, 1),
89 keymaps: make(chan *xkb.Keymap, 1),
90 touchpads: make(chan ports.TouchpadConfig, 1),
91
92 watched: make(chan ports.ConfigChanged, 8),
93 filtered: make(chan ports.ConfigChanged, 8),
94 configured: make(chan ports.ConfigChanged, 8),
95 configErrors: make(chan error, 8),
96
97 contents: make(chan ports.SurfaceContent, 64),
98 presented: make(chan ports.OutputPresented, 64),
99 flips: make(chan ports.OutputPresented, 64),
100 frames: make(chan ports.OutputFrame, 8),
101
102 captures: make(chan ports.CaptureRequest, ports.MaxCaptureInflight),
103 captured: make(chan ports.CaptureDone, ports.MaxCaptureInflight),
104
105 outputFormats: make(chan ports.OutputFormats, 8),
106 outputHeads: make(chan ports.OutputHeads, 8),
107 leaseRequests: make(chan ports.LeaseMessage, 32),
108 leaseEvents: make(chan ports.LeaseMessage, 32),
109 applyOutput: make(chan ports.OutputApply, 8),
110 appliedOutput: make(chan ports.OutputApplied, 8),
111
112 idleInhibited: make(chan bool, 1),
113 idleActivity: make(chan struct{}, 1),
114 }
115 if realSession {
116 p.scales = make(chan ports.ScaleChanged, 8)
117 }
118 return p
119}
120
121// core is core's side. Security, Terminal and Clock are not channels: the
122// caller sets them.
123func (p *pipes) core() core.Channels {
124 return core.Channels{
125 Client: p.client,
126 Input: p.input,
127 Output: p.output,
128 Config: p.configured,
129 Commands: p.commands,
130 Spawn: p.spawn,
131 Scenes: p.scenes,
132 Layouts: p.layouts,
133 Constraints: p.constraints,
134 State: p.states,
135 Workspaces: p.workspaces,
136 ConfigErrors: p.configErrors,
137 Scales: p.scales,
138 Frames: p.frames,
139 }
140}
141
142// wayland is the wayland server's side.
143func (p *pipes) wayland() wayland.Channels {
144 return wayland.Channels{
145 SecurityChanges: p.securityChanges,
146 SecurityEvents: p.securityEvents,
147 Events: p.client,
148 Commands: p.commands,
149 Workspaces: p.workspaces,
150 Contents: p.contents,
151 Cursors: p.cursorChanges,
152 Presented: p.presented,
153 Captures: p.captures,
154 Captured: p.captured,
155 OutputFormats: p.outputFormats,
156 OutputHeads: p.outputHeads,
157 LeaseRequests: p.leaseRequests,
158 LeaseEvents: p.leaseEvents,
159 OutputApply: p.applyOutput,
160 OutputApplied: p.appliedOutput,
161 IdleInhibited: p.idleInhibited,
162 IdleActivity: p.idleActivity,
163 }
164}
165
166// outputs is the outputs' side (DRM or headless).
167func (p *pipes) outputs(security ports.SessionSecurity) outputChannels {
168 return outputChannels{
169 security: security,
170 securityChanges: p.securityChanges,
171 securityEvents: p.securityEvents,
172 events: p.output,
173 scenes: p.renderScenes,
174 contents: p.contents,
175 cursorChanges: p.cursorChanges,
176 presented: p.flips,
177 captures: p.captures,
178 captured: p.captured,
179 formats: p.outputFormats,
180 heads: p.outputHeads,
181 leaseRequests: p.leaseRequests,
182 leaseEvents: p.leaseEvents,
183 reloads: p.filtered,
184 configured: p.configured,
185 requests: p.applyOutput,
186 replies: p.appliedOutput,
187 }
188}