v0.3.0 cf370a0

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	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		deviceConfigs: make(chan ports.InputDevicesConfig, 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}

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 26

Tags 10

↑↓ moveenter openesc close