at 21.11-pre 9.8 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let cfg = config.services.xserver.libinput; 6 7 xorgBool = v: if v then "on" else "off"; 8 9 mkConfigForDevice = deviceType: { 10 dev = mkOption { 11 type = types.nullOr types.str; 12 default = null; 13 example = "/dev/input/event0"; 14 description = 15 '' 16 Path for ${deviceType} device. Set to null to apply to any 17 auto-detected ${deviceType}. 18 ''; 19 }; 20 21 accelProfile = mkOption { 22 type = types.enum [ "flat" "adaptive" ]; 23 default = "adaptive"; 24 example = "flat"; 25 description = 26 '' 27 Sets the pointer acceleration profile to the given profile. 28 Permitted values are adaptive, flat. 29 Not all devices support this option or all profiles. 30 If a profile is unsupported, the default profile for this is used. 31 <literal>flat</literal>: Pointer motion is accelerated by a constant 32 (device-specific) factor, depending on the current speed. 33 <literal>adaptive</literal>: Pointer acceleration depends on the input speed. 34 This is the default profile for most devices. 35 ''; 36 }; 37 38 accelSpeed = mkOption { 39 type = types.nullOr types.str; 40 default = null; 41 description = "Cursor acceleration (how fast speed increases from minSpeed to maxSpeed)."; 42 }; 43 44 buttonMapping = mkOption { 45 type = types.nullOr types.str; 46 default = null; 47 description = 48 '' 49 Sets the logical button mapping for this device, see XSetPointerMapping(3). The string must 50 be a space-separated list of button mappings in the order of the logical buttons on the 51 device, starting with button 1. The default mapping is "1 2 3 ... 32". A mapping of 0 deac 52 tivates the button. Multiple buttons can have the same mapping. Invalid mapping strings are 53 discarded and the default mapping is used for all buttons. Buttons not specified in the 54 user's mapping use the default mapping. See section BUTTON MAPPING for more details. 55 ''; 56 }; 57 58 calibrationMatrix = mkOption { 59 type = types.nullOr types.str; 60 default = null; 61 description = 62 '' 63 A string of 9 space-separated floating point numbers. Sets the calibration matrix to the 64 3x3 matrix where the first row is (abc), the second row is (def) and the third row is (ghi). 65 ''; 66 }; 67 68 clickMethod = mkOption { 69 type = types.nullOr (types.enum [ "none" "buttonareas" "clickfinger" ]); 70 default = null; 71 description = 72 '' 73 Enables a click method. Permitted values are <literal>none</literal>, 74 <literal>buttonareas</literal>, <literal>clickfinger</literal>. 75 Not all devices support all methods, if an option is unsupported, 76 the default click method for this device is used. 77 ''; 78 }; 79 80 leftHanded = mkOption { 81 type = types.bool; 82 default = false; 83 description = "Enables left-handed button orientation, i.e. swapping left and right buttons."; 84 }; 85 86 middleEmulation = mkOption { 87 type = types.bool; 88 default = true; 89 description = 90 '' 91 Enables middle button emulation. When enabled, pressing the left and right buttons 92 simultaneously produces a middle mouse button click. 93 ''; 94 }; 95 96 naturalScrolling = mkOption { 97 type = types.bool; 98 default = false; 99 description = "Enables or disables natural scrolling behavior."; 100 }; 101 102 scrollButton = mkOption { 103 type = types.nullOr types.int; 104 default = null; 105 example = 1; 106 description = 107 '' 108 Designates a button as scroll button. If the ScrollMethod is button and the button is logically 109 held down, x/y axis movement is converted into scroll events. 110 ''; 111 }; 112 113 scrollMethod = mkOption { 114 type = types.enum [ "twofinger" "edge" "button" "none" ]; 115 default = "twofinger"; 116 example = "edge"; 117 description = 118 '' 119 Specify the scrolling method: <literal>twofinger</literal>, <literal>edge</literal>, 120 <literal>button</literal>, or <literal>none</literal> 121 ''; 122 }; 123 124 horizontalScrolling = mkOption { 125 type = types.bool; 126 default = true; 127 description = 128 '' 129 Disables horizontal scrolling. When disabled, this driver will discard any horizontal scroll 130 events from libinput. Note that this does not disable horizontal scrolling, it merely 131 discards the horizontal axis from any scroll events. 132 ''; 133 }; 134 135 sendEventsMode = mkOption { 136 type = types.enum [ "disabled" "enabled" "disabled-on-external-mouse" ]; 137 default = "enabled"; 138 example = "disabled"; 139 description = 140 '' 141 Sets the send events mode to <literal>disabled</literal>, <literal>enabled</literal>, 142 or <literal>disabled-on-external-mouse</literal> 143 ''; 144 }; 145 146 tapping = mkOption { 147 type = types.bool; 148 default = true; 149 description = 150 '' 151 Enables or disables tap-to-click behavior. 152 ''; 153 }; 154 155 tappingDragLock = mkOption { 156 type = types.bool; 157 default = true; 158 description = 159 '' 160 Enables or disables drag lock during tapping behavior. When enabled, a finger up during tap- 161 and-drag will not immediately release the button. If the finger is set down again within the 162 timeout, the draging process continues. 163 ''; 164 }; 165 166 disableWhileTyping = mkOption { 167 type = types.bool; 168 default = false; 169 description = 170 '' 171 Disable input method while typing. 172 ''; 173 }; 174 175 additionalOptions = mkOption { 176 type = types.lines; 177 default = ""; 178 example = 179 '' 180 Option "DragLockButtons" "L1 B1 L2 B2" 181 ''; 182 description = '' 183 Additional options for libinput ${deviceType} driver. See 184 <citerefentry><refentrytitle>libinput</refentrytitle><manvolnum>4</manvolnum></citerefentry> 185 for available options."; 186 ''; 187 }; 188 }; 189 190 mkX11ConfigForDevice = deviceType: matchIs: '' 191 Identifier "libinput ${deviceType} configuration" 192 MatchDriver "libinput" 193 MatchIs${matchIs} "${xorgBool true}" 194 ${optionalString (cfg.${deviceType}.dev != null) ''MatchDevicePath "${cfg.${deviceType}.dev}"''} 195 Option "AccelProfile" "${cfg.${deviceType}.accelProfile}" 196 ${optionalString (cfg.${deviceType}.accelSpeed != null) ''Option "AccelSpeed" "${cfg.${deviceType}.accelSpeed}"''} 197 ${optionalString (cfg.${deviceType}.buttonMapping != null) ''Option "ButtonMapping" "${cfg.${deviceType}.buttonMapping}"''} 198 ${optionalString (cfg.${deviceType}.calibrationMatrix != null) ''Option "CalibrationMatrix" "${cfg.${deviceType}.calibrationMatrix}"''} 199 ${optionalString (cfg.${deviceType}.clickMethod != null) ''Option "ClickMethod" "${cfg.${deviceType}.clickMethod}"''} 200 Option "LeftHanded" "${xorgBool cfg.${deviceType}.leftHanded}" 201 Option "MiddleEmulation" "${xorgBool cfg.${deviceType}.middleEmulation}" 202 Option "NaturalScrolling" "${xorgBool cfg.${deviceType}.naturalScrolling}" 203 ${optionalString (cfg.${deviceType}.scrollButton != null) ''Option "ScrollButton" "${toString cfg.${deviceType}.scrollButton}"''} 204 Option "ScrollMethod" "${cfg.${deviceType}.scrollMethod}" 205 Option "HorizontalScrolling" "${xorgBool cfg.${deviceType}.horizontalScrolling}" 206 Option "SendEventsMode" "${cfg.${deviceType}.sendEventsMode}" 207 Option "Tapping" "${xorgBool cfg.${deviceType}.tapping}" 208 Option "TappingDragLock" "${xorgBool cfg.${deviceType}.tappingDragLock}" 209 Option "DisableWhileTyping" "${xorgBool cfg.${deviceType}.disableWhileTyping}" 210 ${cfg.${deviceType}.additionalOptions} 211 ''; 212in { 213 214 imports = 215 (map (option: mkRenamedOptionModule ([ "services" "xserver" "libinput" option ]) [ "services" "xserver" "libinput" "touchpad" option ]) [ 216 "accelProfile" 217 "accelSpeed" 218 "buttonMapping" 219 "calibrationMatrix" 220 "clickMethod" 221 "leftHanded" 222 "middleEmulation" 223 "naturalScrolling" 224 "scrollButton" 225 "scrollMethod" 226 "horizontalScrolling" 227 "sendEventsMode" 228 "tapping" 229 "tappingDragLock" 230 "disableWhileTyping" 231 "additionalOptions" 232 ]); 233 234 options = { 235 236 services.xserver.libinput = { 237 enable = mkEnableOption "libinput"; 238 mouse = mkConfigForDevice "mouse"; 239 touchpad = mkConfigForDevice "touchpad"; 240 }; 241 }; 242 243 244 config = mkIf cfg.enable { 245 246 services.xserver.modules = [ pkgs.xorg.xf86inputlibinput ]; 247 248 environment.systemPackages = [ pkgs.xorg.xf86inputlibinput ]; 249 250 environment.etc = 251 let cfgPath = "X11/xorg.conf.d/40-libinput.conf"; 252 in { 253 ${cfgPath} = { 254 source = pkgs.xorg.xf86inputlibinput.out + "/share/" + cfgPath; 255 }; 256 }; 257 258 services.udev.packages = [ pkgs.libinput.out ]; 259 260 services.xserver.inputClassSections = [ 261 (mkX11ConfigForDevice "mouse" "Pointer") 262 (mkX11ConfigForDevice "touchpad" "Touchpad") 263 ]; 264 265 assertions = [ 266 # already present in synaptics.nix 267 /* { 268 assertion = !config.services.xserver.synaptics.enable; 269 message = "Synaptics and libinput are incompatible, you cannot enable both (in services.xserver)."; 270 } */ 271 ]; 272 273 }; 274 275}