8 cfg = config.services.libinput;
10 xorgBool = v: if v then "on" else "off";
12 mkConfigForDevice = deviceType: {
14 type = lib.types.nullOr lib.types.str;
16 example = "/dev/input/event0";
18 Path for ${deviceType} device. Set to `null` to apply to any
19 auto-detected ${deviceType}.
23 accelProfile = lib.mkOption {
24 type = lib.types.enum [
32 Sets the pointer acceleration profile to the given profile.
33 Permitted values are `adaptive`, `flat`, `custom`.
34 Not all devices support this option or all profiles.
35 If a profile is unsupported, the default profile for this is used.
36 `flat`: Pointer motion is accelerated by a constant
37 (device-specific) factor, depending on the current speed.
38 `adaptive`: Pointer acceleration depends on the input speed.
39 This is the default profile for most devices.
40 `custom`: Allows the user to define a custom acceleration function.
41 To define custom functions use the accelPoints<Fallback/Motion/Scroll>
42 and accelStep<Fallback/Motion/Scroll> options.
46 accelSpeed = lib.mkOption {
47 type = lib.types.nullOr lib.types.str;
51 Cursor acceleration (how fast speed increases from minSpeed to maxSpeed).
52 This only applies to the flat or adaptive profile.
56 accelPointsFallback = lib.mkOption {
57 type = lib.types.nullOr (lib.types.listOf lib.types.number);
66 Sets the points of the fallback acceleration function. The value must be a list of
67 floating point non-negative numbers. This only applies to the custom profile.
71 accelPointsMotion = lib.mkOption {
72 type = lib.types.nullOr (lib.types.listOf lib.types.number);
81 Sets the points of the (pointer) motion acceleration function. The value must be a
82 list of floating point non-negative numbers. This only applies to the custom profile.
86 accelPointsScroll = lib.mkOption {
87 type = lib.types.nullOr (lib.types.listOf lib.types.number);
96 Sets the points of the scroll acceleration function. The value must be a list of
97 floating point non-negative numbers. This only applies to the custom profile.
101 accelStepFallback = lib.mkOption {
102 type = lib.types.nullOr lib.types.number;
106 Sets the step between the points of the fallback acceleration function. When a step of
107 0.0 is provided, libinput's Fallback acceleration function is used. This only applies
108 to the custom profile.
112 accelStepMotion = lib.mkOption {
113 type = lib.types.nullOr lib.types.number;
117 Sets the step between the points of the (pointer) motion acceleration function. When a
118 step of 0.0 is provided, libinput's Fallback acceleration function is used. This only
119 applies to the custom profile.
123 accelStepScroll = lib.mkOption {
124 type = lib.types.nullOr lib.types.number;
128 Sets the step between the points of the scroll acceleration function. When a step of
129 0.0 is provided, libinput's Fallback acceleration function is used. This only applies
130 to the custom profile.
134 buttonMapping = lib.mkOption {
135 type = lib.types.nullOr lib.types.str;
137 example = "1 6 3 4 5 0 7";
139 Sets the logical button mapping for this device, see XSetPointerMapping(3). The string must
140 be a space-separated list of button mappings in the order of the logical buttons on the
141 device, starting with button 1. The default mapping is "1 2 3 ... 32". A mapping of 0 deac‐
142 tivates the button. Multiple buttons can have the same mapping. Invalid mapping strings are
143 discarded and the default mapping is used for all buttons. Buttons not specified in the
144 user's mapping use the default mapping. See section BUTTON MAPPING for more details.
148 calibrationMatrix = lib.mkOption {
149 type = lib.types.nullOr lib.types.str;
151 example = "0.5 0 0 0 0.8 0.1 0 0 1";
153 A string of 9 space-separated floating point numbers. Sets the calibration matrix to the
154 3x3 matrix where the first row is (abc), the second row is (def) and the third row is (ghi).
158 clickMethod = lib.mkOption {
159 type = lib.types.nullOr (
167 example = "buttonareas";
169 Enables a click method. Permitted values are `none`,
170 `buttonareas`, `clickfinger`.
171 Not all devices support all methods, if an option is unsupported,
172 the default click method for this device is used.
176 leftHanded = lib.mkOption {
177 type = lib.types.bool;
179 description = "Enables left-handed button orientation, i.e. swapping left and right buttons.";
182 middleEmulation = lib.mkOption {
183 type = lib.types.bool;
186 Enables middle button emulation. When enabled, pressing the left and right buttons
187 simultaneously produces a middle mouse button click.
191 naturalScrolling = lib.mkOption {
192 type = lib.types.bool;
194 description = "Enables or disables natural scrolling behavior.";
197 scrollButton = lib.mkOption {
198 type = lib.types.nullOr lib.types.int;
202 Designates a button as scroll button. If the ScrollMethod is button and the button is logically
203 held down, x/y axis movement is converted into scroll events.
207 scrollMethod = lib.mkOption {
208 type = lib.types.enum [
214 default = "twofinger";
217 Specify the scrolling method: `twofinger`, `edge`,
222 horizontalScrolling = lib.mkOption {
223 type = lib.types.bool;
226 Enables or disables horizontal scrolling. When disabled, this driver will discard any
227 horizontal scroll events from libinput. This does not disable horizontal scroll events
228 from libinput; it merely discards the horizontal axis from any scroll events.
232 sendEventsMode = lib.mkOption {
233 type = lib.types.enum [
236 "disabled-on-external-mouse"
239 example = "disabled";
241 Sets the send events mode to `disabled`, `enabled`,
242 or `disabled-on-external-mouse`
246 tapping = lib.mkOption {
247 type = lib.types.bool;
250 Enables or disables tap-to-click behavior.
254 tappingButtonMap = lib.mkOption {
255 type = lib.types.nullOr (
263 Set the button mapping for 1/2/3-finger taps to left/right/middle or left/middle/right, respectively.
267 tappingDragLock = lib.mkOption {
268 type = lib.types.bool;
271 Enables or disables drag lock during tapping behavior. When enabled, a finger up during tap-
272 and-drag will not immediately release the button. If the finger is set down again within the
273 timeout, the dragging process continues.
277 transformationMatrix = lib.mkOption {
278 type = lib.types.nullOr lib.types.str;
280 example = "0.5 0 0 0 0.8 0.1 0 0 1";
282 A string of 9 space-separated floating point numbers. Sets the transformation matrix to
283 the 3x3 matrix where the first row is (abc), the second row is (def) and the third row is (ghi).
287 disableWhileTyping = lib.mkOption {
288 type = lib.types.bool;
291 Disable input method while typing.
295 additionalOptions = lib.mkOption {
296 type = lib.types.lines;
299 Option "DragLockButtons" "L1 B1 L2 B2"
302 Additional options for libinput ${deviceType} driver. See
303 {manpage}`libinput(4)`
304 for available options.";
309 mkX11ConfigForDevice = deviceType: matchIs: ''
310 Identifier "libinput ${deviceType} configuration"
311 MatchDriver "libinput"
312 MatchIs${matchIs} "${xorgBool true}"
313 ${lib.optionalString (cfg.${deviceType}.dev != null) ''MatchDevicePath "${cfg.${deviceType}.dev}"''}
314 Option "AccelProfile" "${cfg.${deviceType}.accelProfile}"
315 ${lib.optionalString (
316 cfg.${deviceType}.accelSpeed != null
317 ) ''Option "AccelSpeed" "${cfg.${deviceType}.accelSpeed}"''}
318 ${lib.optionalString (
319 cfg.${deviceType}.accelPointsFallback != null
320 ) ''Option "AccelPointsFallback" "${toString cfg.${deviceType}.accelPointsFallback}"''}
321 ${lib.optionalString (cfg.${deviceType}.accelPointsMotion != null)
322 ''Option "AccelPointsMotion" "${toString cfg.${deviceType}.accelPointsMotion}"''
324 ${lib.optionalString (cfg.${deviceType}.accelPointsScroll != null)
325 ''Option "AccelPointsScroll" "${toString cfg.${deviceType}.accelPointsScroll}"''
327 ${lib.optionalString (cfg.${deviceType}.accelStepFallback != null)
328 ''Option "AccelStepFallback" "${toString cfg.${deviceType}.accelStepFallback}"''
330 ${lib.optionalString (cfg.${deviceType}.accelStepMotion != null)
331 ''Option "AccelStepMotion" "${toString cfg.${deviceType}.accelStepMotion}"''
333 ${lib.optionalString (cfg.${deviceType}.accelStepScroll != null)
334 ''Option "AccelStepScroll" "${toString cfg.${deviceType}.accelStepScroll}"''
336 ${lib.optionalString (cfg.${deviceType}.buttonMapping != null)
337 ''Option "ButtonMapping" "${cfg.${deviceType}.buttonMapping}"''
339 ${lib.optionalString (cfg.${deviceType}.calibrationMatrix != null)
340 ''Option "CalibrationMatrix" "${cfg.${deviceType}.calibrationMatrix}"''
342 ${lib.optionalString (
343 cfg.${deviceType}.transformationMatrix != null
344 ) ''Option "TransformationMatrix" "${cfg.${deviceType}.transformationMatrix}"''}
345 ${lib.optionalString (
346 cfg.${deviceType}.clickMethod != null
347 ) ''Option "ClickMethod" "${cfg.${deviceType}.clickMethod}"''}
348 Option "LeftHanded" "${xorgBool cfg.${deviceType}.leftHanded}"
349 Option "MiddleEmulation" "${xorgBool cfg.${deviceType}.middleEmulation}"
350 Option "NaturalScrolling" "${xorgBool cfg.${deviceType}.naturalScrolling}"
351 ${lib.optionalString (cfg.${deviceType}.scrollButton != null)
352 ''Option "ScrollButton" "${toString cfg.${deviceType}.scrollButton}"''
354 Option "ScrollMethod" "${cfg.${deviceType}.scrollMethod}"
355 Option "HorizontalScrolling" "${xorgBool cfg.${deviceType}.horizontalScrolling}"
356 Option "SendEventsMode" "${cfg.${deviceType}.sendEventsMode}"
357 Option "Tapping" "${xorgBool cfg.${deviceType}.tapping}"
358 ${lib.optionalString (cfg.${deviceType}.tappingButtonMap != null)
359 ''Option "TappingButtonMap" "${cfg.${deviceType}.tappingButtonMap}"''
361 Option "TappingDragLock" "${xorgBool cfg.${deviceType}.tappingDragLock}"
362 Option "DisableWhileTyping" "${xorgBool cfg.${deviceType}.disableWhileTyping}"
363 ${cfg.${deviceType}.additionalOptions}
372 lib.mkRenamedOptionModule
397 "horizontalScrolling"
402 "transformationMatrix"
408 (lib.mkRenamedOptionModule
409 [ "services" "xserver" "libinput" "enable" ]
410 [ "services" "libinput" "enable" ]
412 (lib.mkRenamedOptionModule
413 [ "services" "xserver" "libinput" "mouse" ]
414 [ "services" "libinput" "mouse" ]
416 (lib.mkRenamedOptionModule
417 [ "services" "xserver" "libinput" "touchpad" ]
418 [ "services" "libinput" "touchpad" ]
424 services.libinput = {
425 enable = lib.mkEnableOption "libinput" // {
426 default = config.services.xserver.enable;
427 defaultText = lib.literalExpression "config.services.xserver.enable";
429 mouse = mkConfigForDevice "mouse";
430 touchpad = mkConfigForDevice "touchpad";
434 config = lib.mkIf cfg.enable {
436 services.xserver.modules = [ pkgs.xorg.xf86inputlibinput ];
438 environment.systemPackages = [ pkgs.xorg.xf86inputlibinput ];
442 cfgPath = "X11/xorg.conf.d/40-libinput.conf";
446 source = pkgs.xorg.xf86inputlibinput.out + "/share/" + cfgPath;
450 services.udev.packages = [ pkgs.libinput.out ];
452 services.xserver.inputClassSections = [
453 (mkX11ConfigForDevice "mouse" "Pointer")
454 (mkX11ConfigForDevice "touchpad" "Touchpad")
458 # already present in synaptics.nix
461 assertion = !config.services.xserver.synaptics.enable;
462 message = "Synaptics and libinput are incompatible, you cannot enable both (in services.xserver).";