lua-plugins.rst 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661
  1. .. _lua_plugins:
  2. ==============================================================================
  3. Lua Plugins
  4. ==============================================================================
  5. libinput provides a plugin system that allows users to modify the behavior
  6. of devices. For example, a plugin may add or remove axes and/or buttons on a
  7. device and/or modify the event stream seen by this device before it is passed
  8. to libinput.
  9. Plugins are implemented in `Lua <https://www.lua.org/>`_ (version 5.4)
  10. and are typically loaded from the following paths:
  11. - ``/etc/libinput/plugins/*.lua``, and
  12. - ``/usr/lib{64}/libinput/plugins/*.lua``
  13. Plugins are loaded in alphabetical order and where
  14. multiple plugins share the same file name, the one in the highest precedence
  15. directory is used. Plugins in ``/etc`` take precedence over
  16. plugins in ``/usr``.
  17. .. note:: Plugins lookup paths and their order are decided by the compositor.
  18. Some compositors may support more/fewer/other lookup paths than the
  19. above defaults.
  20. Plugins are run sequentially in ascending sort-order (i.e. ``00-foo.lua`` runs
  21. before ``10-bar.lua``) and each plugin sees the state left by any previous
  22. plugins. For example if ``00-foo.lua`` changes all left button events to right
  23. button events, ``10-bar.lua`` only ever sees right button events.
  24. See the `Lua Reference manual <https://www.lua.org/manual/5.4/manual.html>`_ for
  25. details on the Lua language.
  26. .. note:: Plugins are **not** loaded by default, it is up to the compositor
  27. whether to allow plugins. An explicit call to
  28. ``libinput_plugin_system_load_plugins()`` is required.
  29. ------------------------------------------------------------------------------
  30. Limitations
  31. ------------------------------------------------------------------------------
  32. Each script runs in its own sandbox and cannot communicate or share state with
  33. other scripts.
  34. Tables that hold API methods are not writable, i.e. it is not possible
  35. to overwrite the default functionality of those APIs.
  36. The Lua API available to plugins is limited to the following calls::
  37. assert error ipairs next pairs tonumber
  38. pcall select print tostring type xpcall
  39. table string math _VERSION
  40. It is not possible to e.g. use the ``io`` module from a script.
  41. To use methods on instantiated objects, the ``object:method`` method call
  42. syntax must be used. For example:
  43. .. code-block:: lua
  44. libinput:register()
  45. libinput.register() -- this will fail
  46. ------------------------------------------------------------------------------
  47. When to use plugins
  48. ------------------------------------------------------------------------------
  49. libinput plugins are a relatively niche use-case that typically need to
  50. address either once-off issues (e.g. those caused by worn-out hardware) or
  51. user preferences that libinput does not and will not cater for.
  52. Plugins should not be used for issues that can be fixed generically, for
  53. example via :ref:`device-quirks`.
  54. As a rule of thumb: a plugin should be a once-off that only works for one
  55. user's hardware. If a plugin can be shared with many users then the plugin
  56. implements functionality that should be integrated into libinput proper.
  57. ------------------------------------------------------------------------------
  58. Testing plugins
  59. ------------------------------------------------------------------------------
  60. Our :ref:`tools` support plugins if passed the ``--enable-plugins`` commandline
  61. option. For implementing and testing plugins the easiest commands to test are
  62. - ``libinput debug-events --enable-plugins`` (see :ref:`libinput-debug-events` docs)
  63. - ``libinput debug-gui --enable-plugins`` (see :ref:`libinput-debug-gui` docs)
  64. Where libinput is built and run from git, the tools will also look for plugins
  65. in the meson build directory. See the ``plugins/meson.build`` file for details.
  66. .. _plugins_api_lua:
  67. --------------------------------------------------------------------------------
  68. Lua Plugin API
  69. --------------------------------------------------------------------------------
  70. Lua plugins sit effectively below libinput and the API is not a
  71. representation of the libinput API. Plugins modify the evdev event stream
  72. received from the kernel.
  73. .. graphviz:: plugin-stack.gv
  74. The API revolves around two types: ``libinput`` and ``EvdevDevice``. The
  75. ``libinput`` type is used to register a plugin from a script, the
  76. ``EvdevDevice`` represents one device that is present in the system (but may
  77. not have yet been added by libinput).
  78. Typically a script does the following steps:
  79. - register with libinput via ``libinput:register({versions})``
  80. - connect to the ``"new-evdev-device"`` event
  81. - receive an ``EvdevDevice`` object in the ``"new-evdev-device"`` callback
  82. - check and/or modify the evdev event codes on the device
  83. - connect to the device's ``"evdev-frame"`` event
  84. - receive an :ref:`evdev frame <plugins_api_evdev_frame>` in the device's
  85. ``"evdev-frame"`` callback
  86. - check and/or modify the events in that frame
  87. Where multiple plugins are active, the evdev frame passed to the callback is
  88. the combined frame as processed by all previous plugins in ascending sort order.
  89. For example, if one plugin discards all button events subsequent plugins will
  90. never see those button events in the frame.
  91. .. _plugins_api_version_stability:
  92. ..............................................................................
  93. Plugin version stability
  94. ..............................................................................
  95. Plugin API version stability is provided on a best effort basis. We aim to provide
  96. stable plugin versions for as long as feasible but may need to retire some older
  97. versions over time. For this reason a plugin can select multiple versions it
  98. implements, libinput will pick one supported version and adjust the plugin
  99. behavior to match that version. See the ``libinput:register()`` call for details.
  100. --------------------------------------------------------------------------------
  101. Lua Plugin API Reference
  102. --------------------------------------------------------------------------------
  103. libinput provides the following globals and types:
  104. .. _plugins_api_evdev_usage:
  105. ................................................................................
  106. Evdev Usages
  107. ................................................................................
  108. Evdev usages are a libinput-specific wrapper around the ``linux/input-event-codes.h``
  109. evdev types and codes. They are used by libinput internally and are a 32-bit
  110. combination of ``type << 16 | code``. Each usage carries the type and code and
  111. is thus simpler to pass around and less prone to type confusion.
  112. The :ref:`evdev global <plugins_api_evdev_global>` attempts to provide all
  113. available usages but for the niche cases where it does not provide a named constant
  114. the value can be crafted manually:
  115. .. code-block:: lua
  116. evdev_type = 0x2 -- EV_REL
  117. evdev_code = 0x1 -- REL_Y
  118. evdev_usage = (evdev_type << 16) | evdev_code
  119. assert(usage == evdev.REL_Y)
  120. .. _plugins_api_evdev_global:
  121. ................................................................................
  122. The ``evdev`` global
  123. ................................................................................
  124. The ``evdev`` global represents all known :ref:`plugins_api_evdev_usage`,
  125. effectively in the form:
  126. .. code-block:: lua
  127. evdev = {
  128. ABS_X = (3 << 16) | 0,
  129. ABS_Y = (3 << 16) | 1,
  130. ...
  131. REL_X = (2 << 16) | 0,
  132. REL_Y = (2 << 16) | 1,
  133. ...
  134. }
  135. This global is provided for convenience to improve readability in the code.
  136. Note that the name uses the event code name only (e.g. ``evdev.ABS_Y``) but the
  137. value is an :ref:`Evdev Usage <plugins_api_evdev_usage>` (type and code).
  138. See the ``linux/input-event-codes.h`` header file provided by your kernel
  139. for a list of all evdev types and codes.
  140. The evdev global also provides the bus type constants, e.g. ``evdev.BUS_USB``.
  141. See the ``linux/input.h`` header file provided by your kernel
  142. for a list of bus types.
  143. .. _plugins_api_evdev_frame:
  144. ................................................................................
  145. Evdev frames
  146. ................................................................................
  147. Evdev frames represent a single frame of evdev events for a device. A frame
  148. is a group of events that occurred at the same time. The frame usually only
  149. contains state that has changed compared to the previous frame.
  150. In our API a frame is exposed as a nested table with the following structure:
  151. .. code-block:: lua
  152. frame1 = {
  153. { usage = evdev.ABS_X, value = 123 },
  154. { usage = evdev.ABS_Y, value = 456 },
  155. { usage = evdev.BTN_LEFT, value = 1 },
  156. }
  157. frame2 = {
  158. { usage = evdev.ABS_Y, value = 457 },
  159. }
  160. frame3 = {
  161. { usage = evdev.ABS_X, value = 124 },
  162. { usage = evdev.BTN_LEFT, value = 0 },
  163. }
  164. .. note:: This API does not use ``SYN_REPORT`` events, it is implied at the
  165. end of the table. Where a plugin writes a ``SYN_REPORT`` into the
  166. list of events, that ``SYN_REPORT`` terminates the event frame
  167. (similar to writing a ``\0`` into the middle of a C string).
  168. A frame containing only a ``SYN_REPORT`` is functionally equivalent
  169. to an empty frame.
  170. Events or frames do not have a timestamp. Where a timestamp is required, that
  171. timestamp is passed as additional argument to the function or return value.
  172. See :ref:`plugins_api_evdev_global` for a list of known usages.
  173. .. warning:: Evdev frames have an implementation-defined size limit of how many
  174. events can be added to a single frame. This limit should never be
  175. hit by valid plugins.
  176. .. _plugins_api_libinputglobal:
  177. ................................................................................
  178. The ``libinput`` global object
  179. ................................................................................
  180. The core of our plugin API is the ``libinput`` global object. A script must
  181. immediately ``register()`` to be active, otherwise it is unloaded immediately.
  182. All libinput-specific APIs can be accessed through the ``libinput`` object.
  183. .. function:: libinput:register({1, 2, ...})
  184. Register this plugin with the given table of supported version numbers and
  185. returns the version number selected by libinput for this plugin. See
  186. :ref:`plugins_api_version_stability` for details.
  187. .. code-block:: lua
  188. -- this plugin can support versions 1, 4 and 5
  189. version = libinput:register({1, 4, 5})
  190. if version == 1 then
  191. ...
  192. This function must be the first function called.
  193. If the plugin calls any other functions before ``register()``, those functions
  194. return the default zero value for the return type (``nil``, ``0``, an empty
  195. table, etc.).
  196. If the plugin does not call ``register()`` it will be removed immediately.
  197. Once registered, any connected callbacks will be invoked whenever libinput
  198. detects new devices, removes devices, etc.
  199. This function must only be called once.
  200. .. function:: libinput:unregister()
  201. Unregister this plugin. This removes the plugin from libinput and releases
  202. any resources associated with this plugin. This call must be the last call
  203. in your plugin, it is effectively equivalent to Lua's
  204. `os.exit() <https://www.lua.org/manual/5.4/manual.html#pdf-os.exit>`_.
  205. .. function:: libinput:log_debug(message)
  206. Log a message at the libinput debug log priority. See
  207. ``libinput:log_error()`` for details.
  208. .. function:: libinput:log_info(message)
  209. Log a message at the libinput info log priority. See
  210. ``libinput:log_error()`` for details.
  211. .. function:: libinput:log_error(message)
  212. Log a message at the libinput error log priority. Whether a message is
  213. displayed in the log depends on libinput's log priority, set by the caller.
  214. A compositor may disable stdout and stderr. Log messages should be preferred
  215. over Lua's ``print()`` function to ensure the messages end up in the same
  216. location as other libinput log messages and are not discarded.
  217. .. function:: libinput:now()
  218. Returns the current time in microseconds in ``CLOCK_MONOTONIC``. This is
  219. the timestamp libinput uses internally. This timestamp cannot be mapped
  220. to any particular time of day, see the
  221. `clock_gettime() man page <https://man7.org/linux/man-pages/man3/clock_gettime.3.html>`_
  222. for details.
  223. .. function:: libinput:version()
  224. Returns the agreed-on version of the plugin, see ``libinput:register()``.
  225. If called before ``libinput:register()`` this function returns ``0``.
  226. .. function:: libinput:connect(name, function)
  227. Set the callback to the given event name. Only one callback
  228. may be set for an event name at any time, subsequent callbacks
  229. will replace any earlier callbacks for the same name.
  230. Version 1 of the plugin API supports the following events and callback arguments:
  231. - ``"new-evdev-device"``: A new :ref:`EvdevDevice <plugins_api_evdevdevice>`
  232. has been seen by libinput but not yet added.
  233. .. code-block:: lua
  234. libinput:connect("new-evdev-device", function (device) ... end)
  235. - ``"timer-expired"``: The timer for this plugin has expired. This event is
  236. only sent if the plugin has set a timer with ``timer_set()``.
  237. .. code-block:: lua
  238. libinput:connect("timer-expired", function (now) ... end)
  239. The ``now`` argument is the current time in microseconds in
  240. ``CLOCK_MONOTONIC`` (see ``libinput:now()``).
  241. .. function:: libinput:timer_cancel()
  242. Cancel the timer for this plugin. This is a no-op if the timer
  243. has not been set or has already expired.
  244. .. function:: libinput:timer_set_absolute(time)
  245. Set a timer for this plugin, with the given time in microseconds.
  246. The timeout specifies an absolute time in microseconds (see
  247. ``libinput:now()``) The timer will expire once and then call the
  248. ``"timer-expired"`` event handler (if any).
  249. See ``libinput:timer_set_relative()`` for a relative timer.
  250. The following two lines of code are equivalent:
  251. .. code-block:: lua
  252. libinput:timer_set_relative(1000000) -- 1 second from now
  253. libinput:timer_set_absolute(libinput:now() + 1000000) -- 1 second from now
  254. Calling this function will cancel any existing (relative or absolute) timer.
  255. .. function:: libinput:timer_set_relative(timeout)
  256. Set a timer for this plugin, with the given timeout in microseconds from
  257. the current time. The timer will expire once and then call the
  258. ``"timer-expired"`` event handler (if any).
  259. See ``libinput:timer_set_absolute()`` for an absolute timer.
  260. The following two lines of code are equivalent:
  261. .. code-block:: lua
  262. libinput:timer_set_relative(1000000) -- 1 second from now
  263. libinput:timer_set_absolute(libinput:now() + 1000000) -- 1 second from now
  264. Calling this function will cancel any existing (relative or absolute) timer.
  265. .. _plugins_api_evdevdevice:
  266. ................................................................................
  267. The ``EvdevDevice`` type
  268. ................................................................................
  269. The ``EvdevDevice`` type represents a device available in the system
  270. but not (yet) added by libinput. This device may be used to modify
  271. a device's capabilities before the device is processed by libinput.
  272. A plugin should always ``connect()`` to the ``"device-removed"`` callback
  273. to be notified when a device is removed. If the plugin keeps a reference
  274. to this device but the device is discarded by libinput, the device's query
  275. methods will return zero values (e.g. ``nil``, ``0``, an empty table) and
  276. methods will be noops.
  277. .. function:: EvdevDevice:info()
  278. A table containing static information about the device, e.g.
  279. .. code-block:: lua
  280. {
  281. bustype = evdev.BUS_USB,
  282. vid = 0x1234,
  283. pid = 0x5678,
  284. }
  285. A plugin must ignore keys it does not know about.
  286. Version 1 of the plugin API supports the following keys and values:
  287. - ``bustype``: The numeric bustype of the device. See the
  288. ``BUS_*`` defines in ``linux/input.h`` for the list of possible values.
  289. - ``vid``: The 16-bit vendor ID of the device
  290. - ``pid``: The 16-bit product ID of the device
  291. If the device has since been discarded by libinput, this function returns an
  292. empty table.
  293. .. function:: EvdevDevice:name()
  294. The device name as set by the kernel
  295. .. function:: EvdevDevice:usages()
  296. Returns a table of all usages that are currently enabled for this
  297. device. Any type that exists on the device has a table assigned and in this
  298. table any code that exists on the device is a boolean true.
  299. For example:
  300. .. code-block:: lua
  301. {
  302. evdev.REL_X = true,
  303. evdev.REL_Y = true,
  304. evdev.BTN_LEFT = true,
  305. }
  306. All other usages are ``nil``, so that the following code is possible:
  307. .. code-block:: lua
  308. local usages = device:usages()
  309. if usages[evdev.REL_X] then
  310. -- do something
  311. end
  312. If the device has since been discarded by libinput, this function returns an
  313. empty table.
  314. .. function:: EvdevDevice:absinfos()
  315. Returns a table of all ``EV_ABS`` codes that are currently enabled for this device.
  316. The event code is the key, each value is a table containing the following keys:
  317. ``minimum``, ``maximum``, ``fuzz``, ``flat``, ``resolution``.
  318. .. code-block:: lua
  319. {
  320. evdev.ABS_X = {
  321. minimum = 0,
  322. maximum = 1234,
  323. fuzz = 0,
  324. flat = 0,
  325. resolution = 45,
  326. },
  327. }
  328. If the device has since been discarded by libinput, this function returns an
  329. empty table.
  330. .. function:: EvdevDevice:udev_properties()
  331. Returns a table containing a filtered list of udev properties available on this device
  332. in the form ``{ property_name = property_value, ... }``.
  333. udev properties used as a boolean (e.g. ``ID_INPUT``) are only present if their
  334. value is a logical true.
  335. Version 1 of the plugin API supports the following udev properties:
  336. - All of ``ID_INPUT_*`` that denote the device type as assigned
  337. by udev. This information is usually used by libinput to determine a
  338. device type. Note that for historical reasons these properties have
  339. varying rules - some properties may be mutually exclusive, others are
  340. independent, others may only be set if another property is set. Refer to
  341. the udev documentation (if any) for details. ``ID_INPUT_WIDTH_MM`` and
  342. ``ID_INPUT_HEIGHT_MM`` are excluded from this set.
  343. If the device has since been discarded by libinput, this function returns an
  344. empty table.
  345. .. function:: EvdevDevice:enable_evdev_usage(usage)
  346. Enable the given :ref:`evdev usage <plugins_api_evdev_usage>` for this device.
  347. Use :ref:`plugins_api_evdev_global` for better readability,
  348. e.g. ``device:enable_evdev_usage(evdev.REL_X)``.
  349. This function must not be used for ``ABS_*`` events, use ``set_absinfo()``
  350. instead.
  351. Once a usage is enabled, events for that usage may be added to a device's
  352. frame.
  353. If the device has since been discarded by libinput, this function does nothing.
  354. .. function:: EvdevDevice:disable_evdev_usage(usage)
  355. Disable the given :ref:`evdev usage <plugins_api_evdev_usage>` for this device.
  356. Use :ref:`plugins_api_evdev_global` for better readability,
  357. e.g. ``device:disable_evdev_usage(evdev.REL_X)``.
  358. Once a usage is disabled, events for that usage are discarded from any
  359. device frame.
  360. If the device has since been discarded by libinput, this function does nothing.
  361. .. function:: EvdevDevice:set_absinfo(usage, absinfo)
  362. Set the absolute axis information for the given :ref:`evdev usage <plugins_api_evdev_usage>`
  363. and enable it if it does not yet exist on the device. The ``absinfo`` argument is a table
  364. containing zero or more of the following keys: ``minimum``, ``maximum``, ``fuzz``,
  365. ``flat``, ``resolution``. Any missing key defaults the corresponding
  366. value from the device if the device already has this event usage or zero otherwise.
  367. For example, the following code changes the resolution but leaves everything
  368. else as-is:
  369. .. code-block:: lua
  370. local absinfo = {
  371. resolution = 40,
  372. }
  373. device:set_absinfo(evdev.ABS_X, absinfo)
  374. device:set_absinfo(evdev.ABS_Y, absinfo)
  375. Use :ref:`plugins_api_evdev_global` for better readability as shown in the
  376. example above.
  377. If the device has since been discarded by libinput, this function does nothing.
  378. .. note:: Overriding the absinfo values often indicates buggy firmware. This should
  379. typically be fixed with an entry in the
  380. `60-evdev.hwdb <https://github.com/systemd/systemd/blob/main/hwdb.d/60-evdev.hwdb>`_
  381. or :ref:`device-quirks` instead of a plugin so all users of that
  382. device can benefit from the fix.
  383. .. function:: EvdevDevice:connect(name, function)
  384. Set the callback to the given event name. Only one callback
  385. may be set for an event name at any time, subsequent callbacks
  386. will overwrite any earlier callbacks for the same name.
  387. If the device has since been discarded by libinput, this function does nothing.
  388. Version 1 of the plugin API supports the following events and callback arguments:
  389. - ``"evdev-frame"``: A new :ref:`evdev frame <plugins_api_evdev_frame>` has
  390. started for this device. If the callback returns a value other than
  391. ``nil``, that value is the frame with any modified events.
  392. An empty frame (``{}``) causes libinput to drop the current event frame.
  393. .. code-block:: lua
  394. device:connect("evdev-frame", function (device, frame, timestamp)
  395. -- change any event into a movement left by 1 pixel
  396. move_left = {
  397. { usage = evdev.REL_X, value = -1, },
  398. }
  399. return move_left
  400. end
  401. The timestamp of an event frame is in microseconds in ``CLOCK_MONOTONIC``, see
  402. ``libinput:now()`` for details.
  403. For performance reasons plugins that do not modify the event frame should
  404. return ``nil`` (or nothing) instead of the event frame that was passed
  405. as argument.
  406. - ``"device-removed"``: This device was removed by libinput. This may happen
  407. without the device ever becoming a libinput device as seen by libinput's
  408. public API (e.g. if the device does not meet the requirements to be
  409. added). Once this callback is invoked, the plugin should remove any
  410. references to this device and stop using it.
  411. .. code-block:: lua
  412. device:connect("device-removed", function (device) ... end)
  413. Functions to query the device's capabilities (e.g. ``usages()``) will
  414. return an empty table.
  415. .. function:: EvdevDevice:disconnect(name)
  416. Disconnect the existing callback (if any) for the given event name. See
  417. ``EvdevDevice:connect()`` for a list of supported names.
  418. .. function:: EvdevDevice:prepend_frame(frame)
  419. Prepend an :ref:`evdev frame <plugins_api_evdev_frame>` for this device
  420. **before** the current frame (if any). The **next** plugin will see the
  421. prepended frame first followed by the current frame.
  422. This function can only be called from within a device's ``"evdev-frame"``
  423. handler or from within the plugin's timer callback function.
  424. For example, to change a single event into a drag, prepend a button
  425. down and append a button up before each event:
  426. .. code:: lua
  427. function frame_handler(device, frame, timestamp)
  428. device:prepend_frame({
  429. { usage = evdev.BTN_LEFT, value = 1}
  430. })
  431. device:append_frame({
  432. { usage = evdev.BTN_LEFT, value = 0}
  433. })
  434. return nil -- return the current frame unmodified
  435. -- The next plugin sees the event sequence:
  436. -- button down, frame, button up
  437. end
  438. If called from within the plugin's timer there is no current frame and this
  439. function is identical to ``append_frame()``.
  440. .. function:: EvdevDevice:append_frame(frame)
  441. Appends an :ref:`evdev frame <plugins_api_evdev_frame>` for this device
  442. **after** the current frame (if any). This function can only be called from
  443. within a device's ``"evdev-frame"`` handler or from within the plugin's timer
  444. callback function.
  445. If called from within the plugin's timer there is no current frame and this
  446. function is identical to ``prepend_frame()``.
  447. See ``prepend_frame()`` for more details.
  448. .. function:: EvdevDevice:disable_feature(feature_name)
  449. Disable the given libinput-internal feature for this device. This should be used
  450. by plugins that replace that feature with a custom implementation for this device.
  451. libinput may have multiple internal implementations for any given feature, disabling
  452. it via this API disables any and all of those implementations, causing the feature to
  453. no longer work at all. It is up to the plugin implementation to re-implement that
  454. feature to match the user's expectation.
  455. Version 1 of the plugin API supports the following features:
  456. - ``"button-debouncing"``: see :ref:`button_debouncing`
  457. - ``"touchpad-hysteresis"``: see :ref:`touchpad_jitter`
  458. - ``"touchpad-jump-detection"``: see :ref:`touchpad_jumping_cursor`
  459. - ``"touchpad-palm-detection"``: see :ref:`palm_detection`
  460. - ``"wheel-debouncing"``: some high-resolution mouse wheel movements inside libinput
  461. are delayed and/or modified