Table of Contents
- Example: tty baseline
- What this config is trying to do
- How to use it
- Controls
- Why this example matters
- The tty-specific config block
- The focus helper enables Super+mouse interaction here
- Move/resize update hooks are still simple
- Why it autostarts a repo-owned panel
- Why the probe binds matter so much on tty
- The hook assignments keep the file easy to scan
- What you should use it for
- What it is not claiming
Example: tty baseline
File:
examples/tty-baseline.lua
This is the practical standalone tty example.
What this config is trying to do
This file adapts the baseline config shape to the udev / tty backend and makes manual testing easier.
It adds:
backend = "udev"- tty-specific control settings
- repo-owned probe commands
- a repo-owned layer-shell panel on startup
The goal is not to be a polished everyday desktop profile. The goal is to be a predictable tty validation profile.
How to use it
Validate it
cargo run --bin evilwm -- --check-config --config examples/tty-baseline.lua
Recommended way to run it
scripts/start-tty.sh
That is the canonical launcher for the repo's current tty workflow.
Direct cargo command if you need it
cargo run --bin evilwm --release --features udev -- --backend udev --config examples/tty-baseline.lua
Use this only on a spare VT. Do not casually run the tty backend inside your current graphical session.
Controls
Keyboard controls
Session / tty controls
| Keys | Action |
|---|---|
Ctrl+Alt+Backspace |
quit the tty session |
Ctrl+Alt+F1 ... Ctrl+Alt+F12 |
switch VT |
Launch / utility binds
| Keys | Action |
|---|---|
Super+Return |
spawn the example terminal |
Super+T |
spawn the example terminal |
Super+W |
spawn the example browser command |
Super+E |
spawn the example file-manager command |
Super+D |
spawn the example launcher |
Super+Y |
spawn the repo-owned Wayland probe |
Super+X |
spawn the repo-owned X11 probe or fallback X11 app |
Super+Shift+S |
run the example screenshot helper |
Super+Q |
close the focused window |
Canvas navigation
| Keys | Action |
|---|---|
Super+H |
pan canvas left |
Super+L |
pan canvas right |
Super+J |
pan canvas down |
Super+K |
pan canvas up |
Super+Equal |
zoom in |
Super+Minus |
zoom out |
Mouse actions
| Mouse action | Behavior |
|---|---|
| click a window | focus that window |
| click empty space | clear focus |
Super+left click on a window |
begin interactive move |
Super+right click on a window |
begin interactive resize |
Touchpad-related behavior
From the tty config section:
- tap-to-click is enabled
- natural scrolling is disabled
Why this example matters
The tty backend is still narrower and rougher than the nested backend. So a good tty example should make testing repeatable.
This file does that by giving the standalone path a predictable story for:
- startup
- input
- panel presence
- terminal launch
- Wayland probe launch
- X11 probe launch
- VT switching
- clean quit
The tty-specific config block
The main backend-specific section is:
tty = {
quit_keyspec = "Ctrl+Alt+Backspace",
vt_switch_modifiers = { "Ctrl", "Alt" },
output_layout = "horizontal",
tap_to_click = true,
natural_scroll = false,
}
What this snippet is teaching
This block is where the tty baseline becomes meaningfully different from the nested baseline. It defines:
- how to quit the session safely
- which modifiers are used for VT switching
- the current narrow multi-output layout direction
- a first practical slice of tty-specific input tuning
These are deliberately tty-focused settings, not a promise of identical behavior across every backend.
The focus helper enables Super+mouse interaction here
Unlike the baseline config, this example explicitly enables drag gestures in its shared focus helper:
local resolve_focus = common.make_resolve_focus({ drag_modifier = "super" })
Why this matters
That one option is what makes these interactions work in the tty profile:
Super+left click→ begin moveSuper+right click→ begin resize
The rest of the movement/resizing path is still handled by the normal update hooks.
Move/resize update hooks are still simple
The file keeps the update behavior very close to the normal baseline config:
local function move_window_with_pointer_delta(ctx)
evil.window.move(ctx.window.id, ctx.window.x + ctx.dx, ctx.window.y + ctx.dy)
end
local function resize_window_with_pointer_delta(ctx)
local bounds = common.resize_bounds(ctx.window, ctx.dx, ctx.dy, ctx.edges)
evil.window.set_bounds(ctx.window.id, bounds.x, bounds.y, bounds.w, bounds.h)
end
That is useful because it separates two concerns cleanly:
- starting the interactive operation is a focus/input policy decision
- updating the operation is normal movement/resize logic
Why it autostarts a repo-owned panel
The panel startup is explicit:
local panel_probe_command = "./scripts/example-launch.sh layer-panel"
...
evil.autostart(panel_probe_command)
Why this matters
That gives the tty baseline a deterministic panel/bar story instead of depending on whatever external desktop pieces happen to be installed on the machine.
For a testing-oriented profile, that is much more useful than a vague "start your normal bar somehow" setup.
Caveat: the tty (udev) render path does not currently render wlr-layer-shell surfaces. The panel probe proves that the layer-shell client maps and participates in session artifacts (event log, IPC snapshots), but it is not yet visually rendered on the tty backend. The tiling and winit backends render layer-shell surfaces normally.
Why the probe binds matter so much on tty
The tty baseline includes repo-owned probe paths on purpose:
local wayland_probe_command = "./scripts/example-launch.sh wayland-probe"
local panel_probe_command = "./scripts/example-launch.sh layer-panel"
local x11_test_command = "./scripts/example-launch.sh x11-probe-or-test"
and then binds them like this:
evil.bind("Super+Y", "spawn", { command = wayland_probe_command })
evil.bind("Super+X", "spawn", { command = x11_test_command })
What this is teaching
These commands make manual tty validation much easier because they give you known-good, repo-owned test surfaces for:
- a Wayland client
- a layer-shell panel
- an X11 client path
That is much better for debugging than depending entirely on whatever apps happen to be installed on the host.
The hook assignments keep the file easy to scan
At the bottom, the file wires the shared and local helpers together:
evil.on.resolve_focus = resolve_focus
evil.on.move_update = move_window_with_pointer_delta
evil.on.resize_update = resize_window_with_pointer_delta
evil.on.draw_background = common.draw_background
evil.on.draw_window_overlay = common.draw_focus_border
This means the file still looks and reads like the normal baseline config even though it is adapted for tty.
What you should use it for
Use this example when:
- testing the
udevbackend on a spare VT - validating input basics on tty
- checking panel + Wayland client + X11 client behavior on tty
- comparing tty behavior against the nested baseline
What it is not claiming
This file is a practical first tty profile. It is not claiming that tty support is already broad, polished, or non-experimental.
It is best understood as the repo's canonical narrow tty validation config.
evil wiki
- Home
- Getting started
- Architecture and philosophy
- Configuration guide
- Writing your first config
- Lua basics for evil users
- Lua API guide
- Lua API cheat sheet
- Hooks guide
- Hook payload summary
- Queries, commands, and actions
- Drawing and visuals
- Example configs overview
- Example shared helpers and rules
- IPC protocol
- Testing and debugging
- Contributor validation matrix
- Feature status and limitations
- Feature and support matrix
- Recipes