Skip to main content

Input devices

COMPOSITOR.input configures keyboards, pointers (mice), and touchpads. As with outputs, you register a factory that the compositor calls whenever the set of input devices changes; you mutate the draft it passes in.

COMPOSITOR.input.configure((input, context) => {
// Global defaults applied to all matching devices
input.global = {
touchpad: {
tapToClick: true,
naturalScroll: true,
scrollMethod: 'twoFinger',
disableWhileTyping: true,
scrollFactor: 0.3,
},
pointer: {
pointerAccel: 0.0,
accelProfile: 'flat',
},
keyboard: {
options: 'caps:ctrl_modifier',
repeatRate: 60,
repeatDelay: 250,
},
};

// Per-device override, keyed by device name
input.device['Razer Razer Blade Keyboard'] = {
keyboard: {layout: 'us'},
};
});

input.global applies to every device of that kind. input.device[name] overrides settings for one specific device (set it to null to clear an override). Each value is an InputDeviceConfig with optional keyboard, pointer, and touchpad sub-objects.

Keyboard settings

keyboard — an InputDeviceConfig.keyboard object. The rules/model/ layout/variant/options fields are standard XKB settings.

FieldTypeMeaning
layoutstringXKB layout, e.g. "us", "jp", "de"
variantstringLayout variant, e.g. "dvorak"
optionsstringXKB options, e.g. "caps:ctrl_modifier", "ctrl:nocaps"
rulesstringXKB rules set
modelstringKeyboard model
repeatRatenumberKey repeats per second
repeatDelaynumberDelay (ms) before key repeat starts
input.global = {
keyboard: {layout: 'us', options: 'caps:ctrl_modifier', repeatRate: 60, repeatDelay: 250},
};

Pointer (mouse) settings

pointer — an InputDeviceConfig.pointer object.

FieldTypeMeaning
pointerAccelnumberAcceleration speed, -1.01.0
accelProfile"adaptive" | "flat"Acceleration curve ("flat" = 1:1, no accel)
naturalScrollbooleanReverse scroll direction
leftHandedbooleanSwap left/right buttons
middleEmulationbooleanEmulate middle click via left+right
input.global = {pointer: {accelProfile: 'flat', pointerAccel: 0.0}};

Touchpad settings

touchpad — a TouchpadInputConfig. It extends the pointer settings above, so every pointer field is also valid here, plus:

FieldTypeMeaning
tapToClickbooleanTap the pad to click
tapButtonMap"leftRightMiddle" | "leftMiddleRight"Multi-finger tap → button mapping
clickMethod"buttonAreas" | "clickfinger"How physical clicks map to buttons
scrollMethod"none" | "twoFinger" | "edge" | "onButtonDown"How scrolling is triggered
scrollFactornumberScroll speed multiplier
disableWhileTypingbooleanIgnore the pad while typing

…plus all pointer fields (pointerAccel, accelProfile, naturalScroll, leftHanded, middleEmulation).

input.global = {
touchpad: {
tapToClick: true,
naturalScroll: true,
scrollMethod: 'twoFinger',
scrollFactor: 0.3,
disableWhileTyping: true,
},
};

Reading and targeting devices

The factory's second argument (and the controller itself) exposes the connected devices, so you can apply settings conditionally by kind.

MemberReturns
devicesInputDeviceInfo[]
currentRecord<string, InputDeviceInfo>
get(key)InputDeviceInfo | undefined
find(predicate)first matching device
configure(factory)register a config factory
reconfigure()re-run all factories now

Each InputDeviceInfo has key, name, optional vendor/product, and a kind flag object (keyboard, pointer, touchpad, touch, tabletTool, tabletPad, gesture, switch).

COMPOSITOR.input.configure((input, ctx) => {
for (const device of ctx.devices) {
if (device.kind.touchpad) {
input.device[device.key] = {touchpad: {scrollMethod: 'twoFinger'}};
}
}
});