Input devices#
carrot decodes evdev itself: no libinput, no libxkbcommon. Devices hotplug live, and pointer settings re-resolve per event, so a config reload applies instantly. Event timestamps ride the monotonic clock, the same base as the presentation clock, so nothing steps under ntp.
The input block#
input {
keyboard {
xkb { layout "us"; variant "colemak"; options "compose:ralt" }
repeat-delay 600 // ms, 1..5000
repeat-rate 25 // per second, 1..200
numlock
}
touchpad { natural-scroll; accel-profile "flat"; accel-speed 0.2 }
mouse { accel-profile "flat"; accel-speed 0.0 }
device "name substring" { accel-speed -0.5; dpi 1600 }
mod-key "super"
}
keyboard#
| Key | Type | Default | Notes |
|---|---|---|---|
xkb { layout } | string | unset | selects the keymap; needs xkeyboard-config on disk for non-US layouts |
xkb { variant }, xkb { options } | string | unset | parse today ahead of support; only layout is applied yet |
repeat-rate | 1..200 | 25 | repeats per second |
repeat-delay | 1..5000 | 600 | ms before repeat starts |
numlock | flag | off | latch numlock at startup |
With no layout set, carrot uses its embedded US keymap and never touches disk. A configured layout resolves against xkeyboard-config via XKB_CONFIG_ROOT or the standard system paths; if the data is missing, the error says which variable to set.
mouse and touchpad#
Both take accel-profile "flat"|"adaptive", accel-speed (-1.0..1.0), and natural-scroll. Touchpad tap and dwt are reserved and error with "not implemented yet"; gestures and touch are staged after the pointer work.
mod-key#
"super" or "alt": what Mod means in every bind chord. One config file works for both conventions by binding everything through Mod.
Per-device rules#
device "turtle-beach" {
accel-speed -0.85
accel-profile "flat"
natural-scroll #false
dpi 1600
}
Device names match loosely: the live name is lowercased with spaces and underscores turned to dashes, and a rule applies if its name is a substring of that. carrot input-probe lists your device names.
| Key | Does |
|---|---|
accel-speed | pointer speed, -1.0..1.0 |
accel-profile | flat or adaptive, overriding the class setting |
natural-scroll | override per device |
dpi | your mouse's real DPI (100..40000); deltas normalize to a 1000 DPI baseline so speed feels identical on any mouse |
Without a dpi override, carrot reads DPI from udev's hardware database the same way libinput would.
Per-window key remaps#
Remap profiles rewrite keys for specific windows: give one stubborn game a different keyboard without touching the rest of the desktop. Minecraft speedrunners rebinding the F3 debug screen onto a reachable key, for example:
remap "mcsr" {
match title="MCSR Ranked" workspace=6 is-xwayland=#false
map "R" "F3"
}
While a window whose title contains MCSR Ranked sits focused on workspace 6, pressing R delivers F3; every other window sees the keyboard untouched.
Criteria on the match node AND together (app-id, title, is-xwayland, pid, workspace), and the first matching profile wins, in file order. app-id is an exact string, title a substring; workspace is 1-based. Each map "From" "To" uses the same key names as binds, and at least one is required. Find a window's matchable facts with burrow clients.
Cursor#
cursor { xcursor-theme "catppuccin-frappe-dark-cursors"; xcursor-size 24; software }
software forces the composited cursor. xcursor-theme and xcursor-size (1..512) pick the pointer theme; the config wins, and the XCURSOR_THEME/XCURSOR_SIZE environment variables keep working as the fallback.