ocamlPackages.hxd: 0.3.2 -> 0.3.3 (#364231)
[NixPkgs.git] / nixos / modules / services / hardware / libinput.nix
blob1ef62640ecce055d93842ce48d4fd5be5b0e0115
2   config,
3   lib,
4   pkgs,
5   ...
6 }:
7 let
8   cfg = config.services.libinput;
10   xorgBool = v: if v then "on" else "off";
12   mkConfigForDevice = deviceType: {
13     dev = lib.mkOption {
14       type = lib.types.nullOr lib.types.str;
15       default = null;
16       example = "/dev/input/event0";
17       description = ''
18         Path for ${deviceType} device.  Set to `null` to apply to any
19         auto-detected ${deviceType}.
20       '';
21     };
23     accelProfile = lib.mkOption {
24       type = lib.types.enum [
25         "flat"
26         "adaptive"
27         "custom"
28       ];
29       default = "adaptive";
30       example = "flat";
31       description = ''
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.
43       '';
44     };
46     accelSpeed = lib.mkOption {
47       type = lib.types.nullOr lib.types.str;
48       default = null;
49       example = "-0.5";
50       description = ''
51         Cursor acceleration (how fast speed increases from minSpeed to maxSpeed).
52         This only applies to the flat or adaptive profile.
53       '';
54     };
56     accelPointsFallback = lib.mkOption {
57       type = lib.types.nullOr (lib.types.listOf lib.types.number);
58       default = null;
59       example = [
60         0.0
61         1.0
62         2.4
63         2.5
64       ];
65       description = ''
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.
68       '';
69     };
71     accelPointsMotion = lib.mkOption {
72       type = lib.types.nullOr (lib.types.listOf lib.types.number);
73       default = null;
74       example = [
75         0.0
76         1.0
77         2.4
78         2.5
79       ];
80       description = ''
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.
83       '';
84     };
86     accelPointsScroll = lib.mkOption {
87       type = lib.types.nullOr (lib.types.listOf lib.types.number);
88       default = null;
89       example = [
90         0.0
91         1.0
92         2.4
93         2.5
94       ];
95       description = ''
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.
98       '';
99     };
101     accelStepFallback = lib.mkOption {
102       type = lib.types.nullOr lib.types.number;
103       default = null;
104       example = 0.1;
105       description = ''
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.
109       '';
110     };
112     accelStepMotion = lib.mkOption {
113       type = lib.types.nullOr lib.types.number;
114       default = null;
115       example = 0.1;
116       description = ''
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.
120       '';
121     };
123     accelStepScroll = lib.mkOption {
124       type = lib.types.nullOr lib.types.number;
125       default = null;
126       example = 0.1;
127       description = ''
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.
131       '';
132     };
134     buttonMapping = lib.mkOption {
135       type = lib.types.nullOr lib.types.str;
136       default = null;
137       example = "1 6 3 4 5 0 7";
138       description = ''
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.
145       '';
146     };
148     calibrationMatrix = lib.mkOption {
149       type = lib.types.nullOr lib.types.str;
150       default = null;
151       example = "0.5 0 0 0 0.8 0.1 0 0 1";
152       description = ''
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).
155       '';
156     };
158     clickMethod = lib.mkOption {
159       type = lib.types.nullOr (
160         lib.types.enum [
161           "none"
162           "buttonareas"
163           "clickfinger"
164         ]
165       );
166       default = null;
167       example = "buttonareas";
168       description = ''
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.
173       '';
174     };
176     leftHanded = lib.mkOption {
177       type = lib.types.bool;
178       default = false;
179       description = "Enables left-handed button orientation, i.e. swapping left and right buttons.";
180     };
182     middleEmulation = lib.mkOption {
183       type = lib.types.bool;
184       default = true;
185       description = ''
186         Enables middle button emulation. When enabled, pressing the left and right buttons
187         simultaneously produces a middle mouse button click.
188       '';
189     };
191     naturalScrolling = lib.mkOption {
192       type = lib.types.bool;
193       default = false;
194       description = "Enables or disables natural scrolling behavior.";
195     };
197     scrollButton = lib.mkOption {
198       type = lib.types.nullOr lib.types.int;
199       default = null;
200       example = 1;
201       description = ''
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.
204       '';
205     };
207     scrollMethod = lib.mkOption {
208       type = lib.types.enum [
209         "twofinger"
210         "edge"
211         "button"
212         "none"
213       ];
214       default = "twofinger";
215       example = "edge";
216       description = ''
217         Specify the scrolling method: `twofinger`, `edge`,
218         `button`, or `none`
219       '';
220     };
222     horizontalScrolling = lib.mkOption {
223       type = lib.types.bool;
224       default = true;
225       description = ''
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.
229       '';
230     };
232     sendEventsMode = lib.mkOption {
233       type = lib.types.enum [
234         "disabled"
235         "enabled"
236         "disabled-on-external-mouse"
237       ];
238       default = "enabled";
239       example = "disabled";
240       description = ''
241         Sets the send events mode to `disabled`, `enabled`,
242         or `disabled-on-external-mouse`
243       '';
244     };
246     tapping = lib.mkOption {
247       type = lib.types.bool;
248       default = true;
249       description = ''
250         Enables or disables tap-to-click behavior.
251       '';
252     };
254     tappingButtonMap = lib.mkOption {
255       type = lib.types.nullOr (
256         lib.types.enum [
257           "lrm"
258           "lmr"
259         ]
260       );
261       default = null;
262       description = ''
263         Set the button mapping for 1/2/3-finger taps to left/right/middle or left/middle/right, respectively.
264       '';
265     };
267     tappingDragLock = lib.mkOption {
268       type = lib.types.bool;
269       default = true;
270       description = ''
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.
274       '';
275     };
277     transformationMatrix = lib.mkOption {
278       type = lib.types.nullOr lib.types.str;
279       default = null;
280       example = "0.5 0 0 0 0.8 0.1 0 0 1";
281       description = ''
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).
284       '';
285     };
287     disableWhileTyping = lib.mkOption {
288       type = lib.types.bool;
289       default = false;
290       description = ''
291         Disable input method while typing.
292       '';
293     };
295     additionalOptions = lib.mkOption {
296       type = lib.types.lines;
297       default = "";
298       example = ''
299         Option "DragLockButtons" "L1 B1 L2 B2"
300       '';
301       description = ''
302         Additional options for libinput ${deviceType} driver. See
303         {manpage}`libinput(4)`
304         for available options.";
305       '';
306     };
307   };
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}"''
323     }
324     ${lib.optionalString (cfg.${deviceType}.accelPointsScroll != null)
325       ''Option "AccelPointsScroll" "${toString cfg.${deviceType}.accelPointsScroll}"''
326     }
327     ${lib.optionalString (cfg.${deviceType}.accelStepFallback != null)
328       ''Option "AccelStepFallback" "${toString cfg.${deviceType}.accelStepFallback}"''
329     }
330     ${lib.optionalString (cfg.${deviceType}.accelStepMotion != null)
331       ''Option "AccelStepMotion" "${toString cfg.${deviceType}.accelStepMotion}"''
332     }
333     ${lib.optionalString (cfg.${deviceType}.accelStepScroll != null)
334       ''Option "AccelStepScroll" "${toString cfg.${deviceType}.accelStepScroll}"''
335     }
336     ${lib.optionalString (cfg.${deviceType}.buttonMapping != null)
337       ''Option "ButtonMapping" "${cfg.${deviceType}.buttonMapping}"''
338     }
339     ${lib.optionalString (cfg.${deviceType}.calibrationMatrix != null)
340       ''Option "CalibrationMatrix" "${cfg.${deviceType}.calibrationMatrix}"''
341     }
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}"''
353     }
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}"''
360     }
361     Option "TappingDragLock" "${xorgBool cfg.${deviceType}.tappingDragLock}"
362     Option "DisableWhileTyping" "${xorgBool cfg.${deviceType}.disableWhileTyping}"
363     ${cfg.${deviceType}.additionalOptions}
364   '';
368   imports =
369     (map
370       (
371         option:
372         lib.mkRenamedOptionModule
373           ([
374             "services"
375             "xserver"
376             "libinput"
377             option
378           ])
379           [
380             "services"
381             "libinput"
382             "touchpad"
383             option
384           ]
385       )
386       [
387         "accelProfile"
388         "accelSpeed"
389         "buttonMapping"
390         "calibrationMatrix"
391         "clickMethod"
392         "leftHanded"
393         "middleEmulation"
394         "naturalScrolling"
395         "scrollButton"
396         "scrollMethod"
397         "horizontalScrolling"
398         "sendEventsMode"
399         "tapping"
400         "tappingButtonMap"
401         "tappingDragLock"
402         "transformationMatrix"
403         "disableWhileTyping"
404         "additionalOptions"
405       ]
406     )
407     ++ [
408       (lib.mkRenamedOptionModule
409         [ "services" "xserver" "libinput" "enable" ]
410         [ "services" "libinput" "enable" ]
411       )
412       (lib.mkRenamedOptionModule
413         [ "services" "xserver" "libinput" "mouse" ]
414         [ "services" "libinput" "mouse" ]
415       )
416       (lib.mkRenamedOptionModule
417         [ "services" "xserver" "libinput" "touchpad" ]
418         [ "services" "libinput" "touchpad" ]
419       )
420     ];
422   options = {
424     services.libinput = {
425       enable = lib.mkEnableOption "libinput" // {
426         default = config.services.xserver.enable;
427         defaultText = lib.literalExpression "config.services.xserver.enable";
428       };
429       mouse = mkConfigForDevice "mouse";
430       touchpad = mkConfigForDevice "touchpad";
431     };
432   };
434   config = lib.mkIf cfg.enable {
436     services.xserver.modules = [ pkgs.xorg.xf86inputlibinput ];
438     environment.systemPackages = [ pkgs.xorg.xf86inputlibinput ];
440     environment.etc =
441       let
442         cfgPath = "X11/xorg.conf.d/40-libinput.conf";
443       in
444       {
445         ${cfgPath} = {
446           source = pkgs.xorg.xf86inputlibinput.out + "/share/" + cfgPath;
447         };
448       };
450     services.udev.packages = [ pkgs.libinput.out ];
452     services.xserver.inputClassSections = [
453       (mkX11ConfigForDevice "mouse" "Pointer")
454       (mkX11ConfigForDevice "touchpad" "Touchpad")
455     ];
457     assertions = [
458       # already present in synaptics.nix
459       /*
460         {
461           assertion = !config.services.xserver.synaptics.enable;
462           message = "Synaptics and libinput are incompatible, you cannot enable both (in services.xserver).";
463         }
464       */
465     ];
467   };