wiring.go RawHistoryFolder

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
68func newPipes(realSession bool) *pipes {
69	p := &pipes{
70		securityChanges: make(chan ports.SecurityState, 8),
71		securityEvents:  make(chan ports.SecurityBackendEvent, 64),
72
73		client:   make(chan ports.ClientEvent, 32),
74		input:    make(chan ports.InputEvent, 32),
75		output:   make(chan ports.OutputEvent, 32),
76		commands: make(chan ports.ClientCommand, 32),
77		spawn:    make(chan ports.SpawnRequest, 32),
78
79		scenes:        make(chan []ports.Scene, 1),
80		renderScenes:  make(chan []ports.Scene, 1),
81		layouts:       make(chan ports.Layout, 1),
82		constraints:   make(chan ports.PointerConstraint, 1),
83		states:        make(chan ports.State, 1),
84		workspaces:    make(chan ports.Workspaces, 1),
85		cursorChanges: make(chan ports.CursorChange, 1),
86		keymaps:       make(chan *xkb.Keymap, 1),
87		deviceConfigs: make(chan ports.InputDevicesConfig, 1),
88
89		watched:      make(chan ports.ConfigChanged, 8),
90		filtered:     make(chan ports.ConfigChanged, 8),
91		configured:   make(chan ports.ConfigChanged, 8),
92		configErrors: make(chan error, 8),
93
94		frames: make(chan ports.OutputFrame, 8),
95
96		captures: make(chan ports.CaptureRequest, ports.MaxCaptureInflight),
97		captured: make(chan ports.CaptureDone, ports.MaxCaptureInflight),
98
99		outputFormats: make(chan ports.OutputFormats, 8),
100		outputHeads:   make(chan ports.OutputHeads, 8),
101		leaseRequests: make(chan ports.LeaseMessage, 32),
102		leaseEvents:   make(chan ports.LeaseMessage, 32),
103		applyOutput:   make(chan ports.OutputApply, 8),
104		appliedOutput: make(chan ports.OutputApplied, 8),
105
106		idleInhibited: make(chan bool, 1),
107		idleActivity:  make(chan struct{}, 1),
108	}
109	if realSession {
110		p.scales = make(chan ports.ScaleChanged, 8)
111	}
112	return p
113}
114
115// core is core's side: channels only. The security gate, clock and terminal
116// flag are not channels; assembleSession passes them as core.Options.
117func (p *pipes) core() core.Channels {
118	return core.Channels{
119		Client:       p.client,
120		Input:        p.input,
121		Output:       p.output,
122		Config:       p.configured,
123		Commands:     p.commands,
124		Spawn:        p.spawn,
125		Scenes:       p.scenes,
126		Layouts:      p.layouts,
127		Constraints:  p.constraints,
128		State:        p.states,
129		Workspaces:   p.workspaces,
130		ConfigErrors: p.configErrors,
131		Scales:       p.scales,
132		Frames:       p.frames,
133	}
134}
135
136// wayland is the wayland server's side.
137func (p *pipes) wayland() wayland.Channels {
138	return wayland.Channels{
139		SecurityChanges: p.securityChanges,
140		SecurityEvents:  p.securityEvents,
141		Events:          p.client,
142		Commands:        p.commands,
143		Workspaces:      p.workspaces,
144		Cursors:         p.cursorChanges,
145		Captures:        p.captures,
146		Captured:        p.captured,
147		OutputFormats:   p.outputFormats,
148		OutputHeads:     p.outputHeads,
149		LeaseRequests:   p.leaseRequests,
150		LeaseEvents:     p.leaseEvents,
151		OutputApply:     p.applyOutput,
152		OutputApplied:   p.appliedOutput,
153		IdleInhibited:   p.idleInhibited,
154		IdleActivity:    p.idleActivity,
155	}
156}
157
158// outputs is the outputs' side (DRM or headless).
159func (p *pipes) outputs(security ports.SessionSecurity, presented ports.PresentationSink, content contentAttacher) outputChannels {
160	return outputChannels{
161		security:        security,
162		securityChanges: p.securityChanges,
163		securityEvents:  p.securityEvents,
164		events:          p.output,
165		scenes:          p.renderScenes,
166		cursorChanges:   p.cursorChanges,
167		presented:       presented,
168		content:         content,
169		frames:          p.frames,
170		captures:        p.captures,
171		captured:        p.captured,
172		formats:         p.outputFormats,
173		heads:           p.outputHeads,
174		leaseRequests:   p.leaseRequests,
175		leaseEvents:     p.leaseEvents,
176		reloads:         p.filtered,
177		configured:      p.configured,
178		requests:        p.applyOutput,
179		replies:         p.appliedOutput,
180	}
181}

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 23

Tags 10

↑↓ moveenter openesc close