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 deviceConfigs chan ports.InputDevicesConfig
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 // Outputs report to wayland through its presentation sink and, for each
45 // flip of an animating scene (Scene.Animating), tell core (frames) to
46 // move running slides.
47 frames chan ports.OutputFrame
48
49 captures chan ports.CaptureRequest
50 // Every admitted capture owns one reply slot until wayland consumes it.
51 // Keep this capacity tied to admission so output routing never waits.
52 captured chan ports.CaptureDone
53
54 outputFormats chan ports.OutputFormats
55 outputHeads chan ports.OutputHeads
56 leaseRequests chan ports.LeaseMessage
57 leaseEvents chan ports.LeaseMessage
58 applyOutput chan ports.OutputApply
59 appliedOutput chan ports.OutputApplied
60
61 // D-Bus idle inhibition and SimulateUserActivity (screensaver), for
62 // wayland's idle notifications. Activity sends never block: capacity 1
63 // coalesces them.
64 idleInhibited chan bool
65 idleActivity chan struct{}
66
67 // Screencast commands to wayland (the screencast adapter's side is the
68 // sender); the events come back through wayland.Options.Casts.
69 castCommands chan ports.CastCommand
70}
71
72func newPipes(realSession bool) *pipes {
73 p := &pipes{
74 securityChanges: make(chan ports.SecurityState, 8),
75 securityEvents: make(chan ports.SecurityBackendEvent, 64),
76
77 client: make(chan ports.ClientEvent, 32),
78 input: make(chan ports.InputEvent, 32),
79 output: make(chan ports.OutputEvent, 32),
80 commands: make(chan ports.ClientCommand, 32),
81 spawn: make(chan ports.SpawnRequest, 32),
82
83 scenes: make(chan []ports.Scene, 1),
84 renderScenes: make(chan []ports.Scene, 1),
85 layouts: make(chan ports.Layout, 1),
86 constraints: make(chan ports.PointerConstraint, 1),
87 states: make(chan ports.State, 1),
88 workspaces: make(chan ports.Workspaces, 1),
89 cursorChanges: make(chan ports.CursorChange, 1),
90 keymaps: make(chan *xkb.Keymap, 1),
91 deviceConfigs: make(chan ports.InputDevicesConfig, 1),
92
93 watched: make(chan ports.ConfigChanged, 8),
94 filtered: make(chan ports.ConfigChanged, 8),
95 configured: make(chan ports.ConfigChanged, 8),
96 configErrors: make(chan error, 8),
97
98 frames: make(chan ports.OutputFrame, 8),
99
100 captures: make(chan ports.CaptureRequest, ports.MaxCaptureInflight),
101 captured: make(chan ports.CaptureDone, ports.MaxCaptureInflight),
102
103 outputFormats: make(chan ports.OutputFormats, 8),
104 outputHeads: make(chan ports.OutputHeads, 8),
105 leaseRequests: make(chan ports.LeaseMessage, 32),
106 leaseEvents: make(chan ports.LeaseMessage, 32),
107 applyOutput: make(chan ports.OutputApply, 8),
108 appliedOutput: make(chan ports.OutputApplied, 8),
109
110 idleInhibited: make(chan bool, 1),
111 idleActivity: make(chan struct{}, 1),
112
113 castCommands: make(chan ports.CastCommand, 64),
114 }
115 if realSession {
116 p.scales = make(chan ports.ScaleChanged, 8)
117 }
118 return p
119}
120
121// core is core's side: channels only. The security gate, clock and terminal
122// flag are not channels; assembleSession passes them as core.Options.
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 Cursors: p.cursorChanges,
151 Captures: p.captures,
152 Captured: p.captured,
153 OutputFormats: p.outputFormats,
154 OutputHeads: p.outputHeads,
155 LeaseRequests: p.leaseRequests,
156 LeaseEvents: p.leaseEvents,
157 OutputApply: p.applyOutput,
158 OutputApplied: p.appliedOutput,
159 IdleInhibited: p.idleInhibited,
160 IdleActivity: p.idleActivity,
161 CastCommands: p.castCommands,
162 }
163}
164
165// outputs is the outputs' side (DRM or headless).
166func (p *pipes) outputs(security ports.SessionSecurity, presented ports.PresentationSink, content contentAttacher) outputChannels {
167 return outputChannels{
168 security: security,
169 securityChanges: p.securityChanges,
170 securityEvents: p.securityEvents,
171 events: p.output,
172 scenes: p.renderScenes,
173 cursorChanges: p.cursorChanges,
174 presented: presented,
175 content: content,
176 frames: p.frames,
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}