Input
Configure keyboard, pointer, touchpad, tablet, cursor, and focus behavior under [input].
Settings
Section titled “Settings”[input]middle_click_paste = falseclient_window_drag = truewindow_snapping = truewindow_drag_toggle = "none"mod_right_double_click = "none"middle_click_paste = false disables primary-selection paste, including Shift+Insert. The regular Ctrl+C and Ctrl+V clipboard is unaffected. Applications started while primary selection is disabled must be restarted after it is re-enabled.
window_snapping = true (the default) enables edge and corner drop zones for floating windows in any layout, using title bar, client move, or Mod+drag. Set it to false to drop windows exactly where released. A preview shows the placement before release. Left, right, top, and bottom edges snap to the corresponding half of the screen. All four corners snap to quarters. Maximize remains available through the title bar button, double-click, or an action. The targets respect panels, layout struts, gaps, borders, title bars, and client size limits, all in logical coordinates.
Dragging a snapped or maximized window away restores its normal size under the pointer, keeping the title bar and content aligned while the application redraws. Snapping on another monitor maps the normal restore position to that monitor. Shared monitor edges require a 150 ms dwell before offering a zone, so dragging straight across monitors remains possible. Tiled, pinned, scratchpad, overview, data-device, and toplevel-transfer drags do not use these zones. Keyboard actions window-snap:<region> and window-unsnap work independently of the pointer setting. See Actions.
client_window_drag = false ignores move requests from applications, such as dragging a client-side title bar or the empty tab strip of Chromium, Firefox, or Electron apps. Ordinary window moves then use Mod+drag, keybinds, or an enabled Umbriel title bar. Resizing from client-side borders and tab tear-off operations using xdg-toplevel-drag-v1 are unaffected.
When the title bar is shown by [appearance.title_bar] mode or a window rule, dragging empty server-side title bar space moves a window without a modifier. Double-click it to maximize or restore. Floating windows resize by dragging the frame’s edges or corners with the left button without a modifier, whether or not the Umbriel title bar is shown. This also works for individually floated windows in tiling layouts. Tiled windows use Mod+right-drag for compositor resizing. Application content and client-side resize controls keep their normal pointer behavior. These compositor-owned interactions work with client_window_drag = false.
Title bar presses keep the normal cursor until the pointer crosses a threshold of 10 logical pixels from its position at the original button press. Umbriel then starts dragging and switches to the grabbing cursor. Movement before an application’s move request counts toward that threshold. If the pointer has already crossed it, dragging starts immediately without requiring another motion event or another threshold.
In tiled layouts, pressing a client-side or Umbriel title bar focuses and reveals the window while keeping it in the layout. It detaches only after the pointer crosses the drag threshold. Holding or releasing a stationary press preserves the spacing between windows, including while applications repaint.
Dropping a floating window settles it into the usable area with the move animation: however far out of frame it was dragged, at release it glides back until at least a quarter of the window (10 to 75 logical pixels) is visible. Nothing else moves a floating window that is already inside that margin, including focus changes.
Mod+right-click drags a window’s resize edge. mod_right_double_click gives a second Mod+right-click on the same window a job beyond resizing:
| Value | Behavior |
|---|---|
"none" | (default) Mod+right-click only drags a resize edge. |
"maximize" | A second Mod+right-click on the same window within 300 ms and 8 px of the first toggles maximize, with the same target a client’s titlebar double-click picks: client_maximize decides between the column and the edges for a tiled window, and a floating window fills the usable area. |
With "maximize", the first click starts resizing only once the pointer moves more than 8 px from the press, and then resizes the edge under the press. A Mod+MouseRight keybind overrides the built-in button entirely.
window_drag_toggle controls what pressing the other main mouse button does during a window drag:
| Value | Behavior |
|---|---|
"none" | Leave the drag unchanged. |
"floating" | Toggle whether the dropped window is tiled or floating. |
"pinned" | Toggle whether the dropped window is pinned. |
The state changes when the window is dropped. Unsupported transitions, such as pinning a fullscreen window, leave the window unchanged.
Detached tabs and panels
Section titled “Detached tabs and panels”Umbriel supports xdg-toplevel-drag-v1 for native Wayland applications that implement it, including Chromium-based browsers. During a pointer drag, a detached window follows the pointer above ordinary windows and stays outside the tiling layout. Windows underneath it can receive the drop, allowing the application to merge a tab or dock a panel. If the application keeps the detached window after the drop, Umbriel places it using normal tiled or floating window-drag behavior. No additional configuration is needed.
Keyboard
Section titled “Keyboard”[input.keyboard]layout = "" # empty uses the system keymapvariant = ""options = ""model = ""repeat_rate = 25repeat_delay = 600numlock_toggle = truetrack_layout = "global"| Key | Range or values | Description |
|---|---|---|
repeat_rate | 0 to 1000 Hz | Key repeats per second; 0 disables repeat. |
repeat_delay | 0 to 10000 ms | Delay before a held key repeats. |
numlock_toggle | bool | Enable NumLock when a keyboard connects. |
track_layout | "global" or "window" | Choose session-wide or per-window layout tracking. |
Use a comma-separated layout list to configure several layouts:
[input.keyboard]layout = "us,de"options = "grp:alt_shift_toggle"options accepts XKB options such as caps:escape or compose:ralt. Invalid layouts, variants, and models are reported in the log and fall back to the system default. Run xkbcli list to inspect available values.
When [input.keyboard] sets none of layout, variant, options, and model, Umbriel uses the X11 keymap configured with localectl set-x11-keymap, read from systemd-localed at startup and on every config reload. Run umbriel msg config-reload to apply a keymap changed with localectl. Without systemd-localed, the XKB_DEFAULT_* environment variables apply, then us. A [[input.device]] rule that sets any of these keys uses only its own and [input.keyboard]’s values.
Run umbriel keyboard-layouts to list the configured layouts. The active one is prefixed with *.
Layout switching
Section titled “Layout switching”Bind keyboard-layout-next to cycle configured physical keyboard layouts:
[keybinds]"Mod+Shift+K" = "keyboard-layout-next"umbriel msg keyboard-layout-next provides the same action for scripts. Physical keyboards that provide the selected layout stay synchronized. Virtual keyboards retain their application-provided keymap.
When an input method removes its virtual keyboard, Umbriel restores the keyboard that supplied the input. Held shortcut modifiers stay active until they are released, even when another connected keyboard is idle.
Lock-key LEDs follow the active input source across physical keyboards, including newly connected devices. This keeps keyboard lights and LED-based lock-key OSDs working when an application forwards input through a uinput keyboard without LED feedback, such as a screen recorder’s global-hotkey helper.
Tracking the layout per window
Section titled “Tracking the layout per window”track_layout accepts:
| Value | Behavior |
|---|---|
"global" | Use one active layout for the session. |
"window" | Remember the active layout for each focused surface. |
In window mode, a surface that has not been focused before starts with the first configured layout. Reloading keyboard configuration clears remembered surface layouts.
Touchpad
Section titled “Touchpad”[input.touchpad]# enabled = truetap = true# tap_and_drag = false# drag_lock = "sticky"natural_scroll = trueleft_handed = false# accel_profile = "adaptive"# sensitivity = 0.5# scroll_factor = 1.5# disable_while_typing = true# disable_on_external_mouse = true# scroll_method = "edge"# click_method = "clickfinger"# tap_button_map = "left_middle_right"Omitted values preserve the device’s libinput defaults. Explicit unsupported settings are reported in the log.
| Key | Description |
|---|---|
enabled | Enable or disable touchpad input. |
tap | Enable tap-to-click. |
tap_and_drag | Keep dragging after a tap when the finger stays down and moves. |
drag_lock | Keep dragging after the finger lifts during a tap-and-drag: "off" disables it, "timeout" ends the drag shortly after the finger lifts, "sticky" holds the drag until the next tap. |
natural_scroll | Reverse scrolling and three-finger gesture direction. |
left_handed | Swap the primary and secondary buttons. |
accel_profile | Use "flat", "adaptive", or a custom acceleration curve. |
sensitivity | Pointer speed from -1.0 to 1.0. |
scroll_factor | Application scroll multiplier from 0.1 to 10.0. |
disable_while_typing | Disable the touchpad during keyboard input. |
disable_on_external_mouse | Disable the touchpad while an external mouse is connected. |
scroll_method | Scroll gesture for application content: "two_finger", "edge", or "none" to disable. |
click_method | Use "button_areas" or "clickfinger". |
tap_button_map | Buttons for one-, two-, and three-finger taps: "left_right_middle" or "left_middle_right". |
scroll_method selects the gesture a touchpad-style device uses to scroll applications. Devices support a subset (libinput list-devices reports them); an unsupported value is logged and ignored. An input.device rule that sets scroll_method replaces that device’s scroll_button scrolling, including its lock, and a rule that sets scroll_button takes the device’s scrolling away from the [input.touchpad] gesture. Mice and other device classes never inherit [input.touchpad] scroll_method.
scroll_factor also accepts per-axis values:
scroll_factor = { horizontal = 2.0, vertical = 1.5 }This factor changes continuous two-finger application scrolling. Overview navigation uses the factors documented in Workspaces Overview.
[input.mouse]natural_scroll = falseleft_handed = false# accel_profile = "flat"sensitivity = 0.0scroll_wheel_step = 60# scroll_button = "MouseBack"# scroll_button_lock = falsesensitivity ranges from -1.0 to 1.0. scroll_wheel_step accepts 1 to 1000 logical pixels per layout-scroll action. left_handed swaps the primary and secondary buttons; omit it to preserve the device default.
Omitting accel_profile preserves the device default. A custom libinput curve uses this form:
accel_profile = "custom 0.2 0.0 0.5 1.0 2.0"scroll_button turns pointer motion into scrolling while the named button is held. Set scroll_button_lock = true to toggle that mode with a press instead. Accepted names are MouseLeft, MouseRight, MouseMiddle, MouseBack, and MouseForward.
scroll_wheel_step controls the distance used by layout scroll actions, not the scrolling sent to applications.
Per-device overrides
Section titled “Per-device overrides”Use [[input.device]] for a device whose case-sensitive name exactly matches the Device value from libinput list-devices:
[[input.device]]name = "Acme Split Keyboard"layout = "us"variant = "colemak_dh"model = "pc104angle"repeat_rate = 40repeat_delay = 250
[[input.device]]name = "Acme Precision Touchpad"tap = truenatural_scroll = falseleft_handed = falsescroll_method = "edge"click_method = "clickfinger"
[[input.device]]name = "Acme Gaming Mouse"accel_profile = "flat"sensitivity = 0.0
[[input.device]]name = "Acme Controller Touchpad"enabled = falseEach rule inherits its keyboard, touchpad, or mouse class settings and replaces only the keys it contains. enabled = false turns off a keyboard, touchpad, or mouse. Duplicate rules for the same device name are rejected.
Tablet
Section titled “Tablet”[input.tablet]enabled = truemap_to_output = "DP-1"map_to_focused_output = falsemap_to_focused_window = falseleft_handed = falsecalibration_matrix = [1.0, 0.0, 0.0, 0.0, 1.0, 0.0]| Key | Description |
|---|---|
enabled | Enable tablet and pad input. |
map_to_output | Confine the tablet to a connector or monitor name. |
map_to_focused_output | Follow the output holding keyboard focus. |
map_to_focused_window | Map the tablet area to the focused window. |
left_handed | Flip the tablet orientation. |
calibration_matrix | Pass a six-number calibration matrix to libinput. |
Focused-window mapping takes precedence over focused-output mapping, which takes precedence over map_to_output.
[input.touch]enabled = truemap_to_output = "eDP-1"| Key | Description |
|---|---|
enabled | Enable or disable touch input. |
map_to_output | Confine touch input to a connector or monitor name. |
Without map_to_output, a touchscreen maps to the output its device reports, or else to the built-in panel (eDP-, LVDS-, or DSI-) when exactly one is enabled. Otherwise it spans the whole output layout.
Cursor
Section titled “Cursor”[input.cursor]theme = ""size = 24hardware_cursor = truefollows_focus = falsehide_when_typing = falsehide_timeout_ms = 0| Key | Range or values | Description |
|---|---|---|
theme | string | Xcursor theme; empty uses the environment default. |
size | 1 to 512 | Cursor size in logical pixels. |
hardware_cursor | bool | Use a hardware cursor plane when available. |
follows_focus | bool | Follow keyboard-driven window focus. |
hide_when_typing | bool | Hide after a non-modifier key press. |
hide_timeout_ms | 0 to 3600000 | Hide after inactivity; 0 disables the timeout. |
Set hardware_cursor = false to work around hardware cursor flicker or disappearance. Set hide_timeout_ms to a value from 1 to 3600000 to hide an inactive cursor; 0 disables the timeout.
follows_focus = true moves the cursor to a newly focused window after keyboard-driven focus and transfer actions. Pointer-driven focus, gestures, and automatic replacement focus do not move it. window-focus-warp:<id> always moves the cursor regardless of this setting. Active-workspace output swaps keep the cursor and seat focus on the invoking output when this setting is false; when it is true, both follow the previously focused window to its new output.
Drag edge scroll
Section titled “Drag edge scroll”[input.drag_edge_scroll]enabled = truetrigger_zone = 30delay_ms = 100max_speed = 1500.0While a drag-and-drop or a tiled window move (Mod+left-click or the tab bar) is held near either end of a scrolling layout, the layout scrolls so offscreen columns can be reached.
| Key | Range or values | Description |
|---|---|---|
enabled | bool | Enable edge scrolling during a data drag or a tiled window move. |
trigger_zone | 1 to 1000 | Width of the zone at each end, in logical pixels. |
delay_ms | 0 to 10000 | Time inside the zone before scrolling starts. |
max_speed | 1.0 to 100000.0 | Peak scroll speed in logical pixels per second. |
Speed rises from zero at the inner edge of the trigger zone to max_speed at the outer edge of the layout, so scrolling accelerates as the pointer pushes further in. The zone is clamped to half the viewport, so the two zones never overlap. delay_ms = 0 starts scrolling as soon as the pointer enters the zone. enabled = false turns the behavior off entirely.
[input.focus]follows_mouse = falsefollows_mouse_max_scroll = 0.5hover_raises = truefollows_mouse = true focuses the window that the pointer enters through real pointer motion. Scrolling or dragging a layout beneath a stationary pointer does not change focus. After explicit layout scrolling settles, the next real pointer motion can focus the window beneath it without a border crossing. Pointer motion during scrolling does not change focus. Consume and expel commands also let the next pointer motion refresh focus after rearranging windows. This follows the actual seat focus across tiled, floating, and pinned windows, including pinned windows whose owning workspace is inactive.
hover_raises = false narrows hovering to focus alone: the entered window does not move above its neighbors, so sweeping the pointer across a larger window underneath cannot bury the window above it. Clicks, keybinds, and activation still raise. The key only matters with follows_mouse = true, and defaults to true.
While a client holds a pointer or keyboard grab, such as an open tray menu, hovering a window or crossing outputs preserves that grab and its keyboard focus. An outside click or explicit focus action can still dismiss the menu.
X11 windows that declare Input=False without WM_TAKE_FOCUS, including Steam’s on-screen keyboard, receive pointer input without taking keyboard focus. Hovering or clicking the keyboard leaves typing directed at the previously focused window. These windows are also skipped when Umbriel chooses replacement focus after a window closes.
follows_mouse_max_scroll limits how far Umbriel may scroll a layout to reveal that window, measured in viewport widths. 0.0 allows only fully visible windows. Omit the key for no limit.
Controller desktop input
Section titled “Controller desktop input”Steam’s desktop controller mappings can control native Wayland windows through Umbriel’s X11 input emulation. Umbriel asks for permission on the first request and remembers the decision for the current session. See X11 desktop input for consent and lock-screen behavior.