Repository navigation
Configuration
The patchset adds one new gestures {} block to the niri config. niri
reloads the config on save, and every option below applies live, without a
re-login (the debug-log flag takes effect from the next touch).
Every action node takes any niri action, same as keybinds. If you can bind it to a key, you can bind it to a gesture. The niri wiki's actions list is the menu.
config/gestures.kdl in the repo is the scheme the project ships and its
author runs daily. Either paste its gestures block into your config.kdl,
or include the file:
include "~/.config/niri/cfg/gestures.kdl"and copy it there:
mkdir -p ~/.config/niri/cfg
cp niri-tablet/config/gestures.kdl ~/.config/niri/cfg/Prefer not to hand-edit KDL at all? EasySetup is a GUI that does the above for you and then some.
What follows is the full node reference.
Multi-finger gestures: the two animated drags, taps, flicks, and hold-swipes.
On top of the animated swipes, discrete actions can be bound to taps and
specific swipe shapes, and the horizontal swipe can be switched to resize the
focused window. Anything left unbound falls back to the animated gesture (or,
for taps with more fingers than fingers, to the regular tap action).
Renamed after v26.04.18: tap-4/swipe-4-up/swipe-4-down became
tap-more/swipe-more-up/swipe-more-down and apply at one finger more than
fingers instead of a fixed four.
-
fingers- number of fingers required for everything in this block that has no "more" in its name (the drags andtap). Must be 3 or 4; default 3. The*-morenodes below override their gesture at one finger more than this (4 by default). -
off- disable touchscreen swipe gestures entirely. -
horizontal-swipe- what a quick horizontal swipe does. Default:"move-view"(scroll the view across columns)."resize-column"makes the swipe resize the focused window's width, tracking the fingers 1:1: dragging right widens it, dragging left narrows it, and the width stays where the fingers leave it. Tiled: the focused column; floating: the focused window. Without a focused window the swipe falls back to moving the view. -
tap- action for a quick tap withfingersfingers. Default:maximize-column. All fingers down and up within a short window, without enough movement to become a swipe. -
tap-more- action for taps with one finger more thanfingers(4 by default); overridestapfor those. -
swipe-more-down/swipe-more-up- discrete action for a quick vertical swipe with one finger more thanfingers(4 by default). Unset, such swipes drive the workspace carousel. -
swipe-more-left/swipe-more-right- discrete action for a quick horizontal swipe with one finger more thanfingers(4 by default), added after v26.04.18. Unset, such swipes keep thehorizontal-swipebehavior (move the view, or resize the focused column). -
hold { left/right/up/down { ... } }- discrete actions for held swipes: fingers resting still for ~400ms before swiping. A direction left unset falls back to the animated swipe.
gestures {
touchscreen-swipe {
fingers 3
// off
horizontal-swipe "resize-column"
tap { maximize-column; }
tap-more { toggle-overview; }
swipe-more-down { close-window; }
swipe-more-up { fullscreen-window; }
// swipe-more-left { focus-column-left; }
// swipe-more-right { focus-column-right; }
hold {
left { move-column-left; }
right { move-column-right; }
up { move-window-to-workspace-up; }
down { move-window-to-workspace-down; }
}
}
}gestures {
// Disable touchscreen swipe gestures.
touchscreen-swipe {
off
}
}The recognition rules (hold vs quick, tap vs swipe, fallbacks) are described on Gestures.
Single-finger swipes that start at a screen edge. A finger starting within
~48 logical pixels of an edge and swiping inward past ~40 pixels (with the
inward direction dominant) runs the action bound to that edge. Each of
bottom (swipe up), top (swipe down), left (swipe right) and right
(swipe left) takes any niri action:
gestures {
touchscreen-edge-swipe {
bottom { spawn-sh "~/.local/bin/niri-osk.sh"; }
top { toggle-overview; }
left { focus-column-left; }
right { focus-column-right; }
}
}Touches in an edge strip deliver to applications normally until the trigger distance is crossed, unbound zones are inert, and the zones follow the output's transform (details on Gestures). Avoid binding edges occupied by swipe-driven shell surfaces (e.g. a pull-down notification panel along the top): the bound gesture would fire mid-drag.
Breaking change in v26.04.18: the old touchscreen-edge-swipe { spawn ...; }
form no longer parses (it never worked on hardware); use the per-zone children
shown above.
Single-finger diagonal swipes that start at a screen corner: the corner zones
are the ~48 logical pixel squares where two edge strips meet, and the swipe
must move inward by ~20 pixels on both axes. Each of top-left, top-right,
bottom-left and bottom-right takes any niri action; unbound corners are
inert.
gestures {
touchscreen-corner-swipe {
top-left { maximize-column; }
top-right { toggle-overview; }
bottom-left { spawn "foot"; }
bottom-right { close-window; }
}
}Corners win over edges when the touch starts within range of both.
Translucent dots that follow your fingers, drawn by the compositor. For demo videos and gesture debugging; off by default.
gestures {
show-touch-points "gestures" // only while a multi-finger gesture is down
// show-touch-points "all" // every finger (debugging)
}The values are quoted strings. A bare unquoted show-touch-points gestures
passes the unit-test parser but niri's strict file loader rejects it, so
niri validate is the only check that catches it before a re-login.
Per-event logging of the touchscreen gesture stack, for bug reports. Every
line is prefixed gesture-debug:. Off by default, toggles live (applies from
the next touch). See Troubleshooting for how to collect a reproduction.
gestures {
debug-log
}If you use the on-screen keyboard with a non-US system layout, the
two-group xkb setup that keeps the OSK typing US while the physical keyboard
stays native belongs in your input config, not in the gestures block:
OSK and auto-rotation.