mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2025-12-25 22:10:05 +01:00
doc/user: update the lua plugin documentation
Some clarifications, some fixes, some reshuffling, overall somewhat better. Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1349>
This commit is contained in:
parent
22dda5b154
commit
2784973b4d
3 changed files with 108 additions and 44 deletions
31
doc/user/dot/plugin-stack.gv
Normal file
31
doc/user/dot/plugin-stack.gv
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
digraph stack
|
||||||
|
{
|
||||||
|
compound=true;
|
||||||
|
rankdir="LR";
|
||||||
|
node [
|
||||||
|
shape="box";
|
||||||
|
]
|
||||||
|
|
||||||
|
subgraph cluster_2 {
|
||||||
|
label="Kernel";
|
||||||
|
event0 [label="/dev/input/event0"]
|
||||||
|
}
|
||||||
|
|
||||||
|
subgraph cluster_1 {
|
||||||
|
label="libinput";
|
||||||
|
subgraph cluster_0 {
|
||||||
|
label="Plugin pipeline";
|
||||||
|
p1 [label="00-foo.lua"];
|
||||||
|
p2 [label="10-bar.lua"];
|
||||||
|
}
|
||||||
|
libinput [label="libinput core"];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
compositor [label="Compositor"];
|
||||||
|
|
||||||
|
event0 -> p1;
|
||||||
|
p1 -> p2;
|
||||||
|
p2 -> libinput;
|
||||||
|
libinput -> compositor [ltail=cluster_1 label="libinput API"];
|
||||||
|
}
|
||||||
|
|
@ -10,15 +10,24 @@ device and/or modify the event stream seen by this device before it is passed
|
||||||
to libinput.
|
to libinput.
|
||||||
|
|
||||||
Plugins are implemented in `Lua <https://www.lua.org/>`_ (version 5.1)
|
Plugins are implemented in `Lua <https://www.lua.org/>`_ (version 5.1)
|
||||||
and are typically loaded from ``/usr/lib{64}/libinput/plugins`` and
|
and are typically loaded from the following paths:
|
||||||
``/etc/libinput/plugins``. Plugins are loaded in alphabetical order and where
|
|
||||||
|
- ``/etc/libinput/plugins/*.lua``, and
|
||||||
|
- ``/usr/lib{64}/libinput/plugins/*.lua``
|
||||||
|
|
||||||
|
Plugins are loaded in alphabetical order and where
|
||||||
multiple plugins share the same file name, the one in the highest precedence
|
multiple plugins share the same file name, the one in the highest precedence
|
||||||
directory is used. Plugins in ``/etc`` take precedence over
|
directory is used. Plugins in ``/etc`` take precedence over
|
||||||
plugins in ``/usr``.
|
plugins in ``/usr``.
|
||||||
|
|
||||||
|
.. note:: Plugins lookup paths and their order are decided by the compositor.
|
||||||
|
Some compositors may support more/fewer/other lookup paths than the
|
||||||
|
above defaults.
|
||||||
|
|
||||||
Plugins are run sequentially in ascending sort-order (i.e. ``00-foo.lua`` runs
|
Plugins are run sequentially in ascending sort-order (i.e. ``00-foo.lua`` runs
|
||||||
before ``10-bar.lua``) and each plugin sees the state left by any previous
|
before ``10-bar.lua``) and each plugin sees the state left by any previous
|
||||||
plugins.
|
plugins. For example if ``00-foo.lua`` changes all left button events to right
|
||||||
|
button events, ``10-bar.lua`` only ever sees right button events.
|
||||||
|
|
||||||
See the `Lua Reference manual <https://www.lua.org/manual/5.1/manual.html>`_ for
|
See the `Lua Reference manual <https://www.lua.org/manual/5.1/manual.html>`_ for
|
||||||
details on the Lua language.
|
details on the Lua language.
|
||||||
|
|
@ -45,8 +54,8 @@ The Lua API available to plugins is limited to the following calls::
|
||||||
|
|
||||||
It is not possible to e.g. use the ``io`` module from a script.
|
It is not possible to e.g. use the ``io`` module from a script.
|
||||||
|
|
||||||
To use methods on instantiated objects, the method call syntax must be used.
|
To use methods on instantiated objects, the ``object:method`` method call
|
||||||
For example:
|
syntax must be used. For example:
|
||||||
|
|
||||||
.. code-block:: lua
|
.. code-block:: lua
|
||||||
|
|
||||||
|
|
@ -88,14 +97,19 @@ Lua Plugin API
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
Lua plugins sit effectively below libinput and the API is not a
|
Lua plugins sit effectively below libinput and the API is not a
|
||||||
representation of the libinput API. The API revolves around two types:
|
representation of the libinput API. Plugins modify the evdev event stream
|
||||||
``libinput`` and ``EvdevDevice``. The former is used to register a
|
received from the kernel.
|
||||||
plugin from a script, the latter represents one device that is present
|
|
||||||
in the system (but may not have yet been added by libinput).
|
.. graphviz:: plugin-stack.gv
|
||||||
|
|
||||||
|
The API revolves around two types: ``libinput`` and ``EvdevDevice``. The
|
||||||
|
``libinput`` type is used to register a plugin from a script, the
|
||||||
|
``EvdevDevice`` represents one device that is present in the system (but may
|
||||||
|
not have yet been added by libinput).
|
||||||
|
|
||||||
Typically a script does the following steps:
|
Typically a script does the following steps:
|
||||||
|
|
||||||
- register with libinput via ``libinput:register(version)``
|
- register with libinput via ``libinput:register({versions})``
|
||||||
- connect to the ``"new-evdev-device"`` event
|
- connect to the ``"new-evdev-device"`` event
|
||||||
- receive an ``EvdevDevice`` object in the ``"new-evdev-device"`` callback
|
- receive an ``EvdevDevice`` object in the ``"new-evdev-device"`` callback
|
||||||
|
|
||||||
|
|
@ -142,14 +156,17 @@ evdev types and codes. They are used by libinput internally and are a 32-bit
|
||||||
combination of ``type << 16 | code``. Each usage carries the type and code and
|
combination of ``type << 16 | code``. Each usage carries the type and code and
|
||||||
is thus simpler to pass around and less prone to type confusion.
|
is thus simpler to pass around and less prone to type confusion.
|
||||||
|
|
||||||
For the case where the :ref:`evdev global <plugins_api_evdev_global>` does not
|
The :ref:`evdev global <plugins_api_evdev_global>` attempts to provide all
|
||||||
provide a named constant the value can be crafted manually:
|
available usages but for the niche cases where it does not provide a named constant
|
||||||
|
the value can be crafted manually:
|
||||||
|
|
||||||
.. code-block:: lua
|
.. code-block:: lua
|
||||||
|
|
||||||
type = 0x3 -- EV_REL
|
evdev_type = 0x3 -- EV_REL
|
||||||
code = 0x1 -- REL_Y
|
evdev_code = 0x1 -- REL_Y
|
||||||
usage = (type << 16) | code
|
evdev_usage = (evdev_type << 16) | evdev_code
|
||||||
|
|
||||||
|
assert(usage == evdev.REL_Y)
|
||||||
|
|
||||||
.. _plugins_api_evdev_global:
|
.. _plugins_api_evdev_global:
|
||||||
|
|
||||||
|
|
@ -173,8 +190,8 @@ effectively in the form:
|
||||||
|
|
||||||
|
|
||||||
This global is provided for convenience to improve readability in the code.
|
This global is provided for convenience to improve readability in the code.
|
||||||
Note that the name uses the event code name only but the value is an
|
Note that the name uses the event code name only (e.g. ``evdev.ABS_Y``) but the
|
||||||
:ref:`Evdev Usage <plugins_api_evdev_usage>` (type and code).
|
value is an :ref:`Evdev Usage <plugins_api_evdev_usage>` (type and code).
|
||||||
|
|
||||||
See the ``linux/input-event-codes.h`` header file provided by your kernel
|
See the ``linux/input-event-codes.h`` header file provided by your kernel
|
||||||
for a list of all evdev types and codes.
|
for a list of all evdev types and codes.
|
||||||
|
|
@ -204,10 +221,10 @@ In our API a frame is exposed as a nested table with the following structure:
|
||||||
{ usage = evdev.BTN_LEFT, value = 1 },
|
{ usage = evdev.BTN_LEFT, value = 1 },
|
||||||
}
|
}
|
||||||
frame2 = {
|
frame2 = {
|
||||||
{ sage = evdev.ABS_Y, value = 457 },
|
{ usage = evdev.ABS_Y, value = 457 },
|
||||||
}
|
}
|
||||||
frame3 = {
|
frame3 = {
|
||||||
{ sage = evdev.ABS_X, value = 124 },
|
{ usage = evdev.ABS_X, value = 124 },
|
||||||
{ usage = evdev.BTN_LEFT, value = 0 },
|
{ usage = evdev.BTN_LEFT, value = 0 },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -259,7 +276,7 @@ location as other libinput log messages and are not discarded.
|
||||||
The ``libinput`` global object
|
The ``libinput`` global object
|
||||||
................................................................................
|
................................................................................
|
||||||
|
|
||||||
The core of our plugin's API is the ``libinput`` global object. A script must
|
The core of our plugin API is the ``libinput`` global object. A script must
|
||||||
immediately ``register()`` to be active, otherwise it is unloaded immediately.
|
immediately ``register()`` to be active, otherwise it is unloaded immediately.
|
||||||
|
|
||||||
All libinput-specific APIs can be accessed through the ``libinput`` object.
|
All libinput-specific APIs can be accessed through the ``libinput`` object.
|
||||||
|
|
@ -279,7 +296,8 @@ All libinput-specific APIs can be accessed through the ``libinput`` object.
|
||||||
|
|
||||||
This function must be the first function called.
|
This function must be the first function called.
|
||||||
If the plugin calls any other functions before ``register()``, those functions
|
If the plugin calls any other functions before ``register()``, those functions
|
||||||
return ``nil``, 0, an empty table, etc.
|
return the default zero value for the return type (``nil``, ``0``, an empty
|
||||||
|
table, etc.).
|
||||||
|
|
||||||
If the plugin does not call ``register()`` it will be removed immediately.
|
If the plugin does not call ``register()`` it will be removed immediately.
|
||||||
Once registered, any connected callbacks will be invoked whenever libinput
|
Once registered, any connected callbacks will be invoked whenever libinput
|
||||||
|
|
@ -290,8 +308,8 @@ All libinput-specific APIs can be accessed through the ``libinput`` object.
|
||||||
.. function:: libinput:unregister()
|
.. function:: libinput:unregister()
|
||||||
|
|
||||||
Unregister this plugin. This removes the plugin from libinput and releases
|
Unregister this plugin. This removes the plugin from libinput and releases
|
||||||
any resources. This call must be the last call in your plugin, it is
|
any resources associated with this plugin. This call must be the last call
|
||||||
effectively equivalent to Lua's
|
in your plugin, it is effectively equivalent to Lua's
|
||||||
`os.exit() <https://www.lua.org/manual/5.4/manual.html#pdf-os.exit>`_.
|
`os.exit() <https://www.lua.org/manual/5.4/manual.html#pdf-os.exit>`_.
|
||||||
|
|
||||||
.. function:: libinput:now()
|
.. function:: libinput:now()
|
||||||
|
|
@ -305,7 +323,7 @@ All libinput-specific APIs can be accessed through the ``libinput`` object.
|
||||||
.. function:: libinput:version()
|
.. function:: libinput:version()
|
||||||
|
|
||||||
Returns the agreed-on version of the plugin, see ``libinput:register()``.
|
Returns the agreed-on version of the plugin, see ``libinput:register()``.
|
||||||
If called before ``libinput:register()`` this function returns 0.
|
If called before ``libinput:register()`` this function returns ``0``.
|
||||||
|
|
||||||
.. function:: libinput:connect(name, function)
|
.. function:: libinput:connect(name, function)
|
||||||
|
|
||||||
|
|
@ -327,7 +345,7 @@ All libinput-specific APIs can be accessed through the ``libinput`` object.
|
||||||
|
|
||||||
.. code-block:: lua
|
.. code-block:: lua
|
||||||
|
|
||||||
libinput:connect("timer-expired", function (plugin, now) ... end)
|
libinput:connect("timer-expired", function (now) ... end)
|
||||||
|
|
||||||
The ``now`` argument is the current time in microseconds in
|
The ``now`` argument is the current time in microseconds in
|
||||||
``CLOCK_MONOTONIC`` (see ``libinput.now()``).
|
``CLOCK_MONOTONIC`` (see ``libinput.now()``).
|
||||||
|
|
@ -382,6 +400,12 @@ The ``EvdevDevice`` type represents a device available in the system
|
||||||
but not (yet) added by libinput. This device may be used to modify
|
but not (yet) added by libinput. This device may be used to modify
|
||||||
a device's capabilities before the device is processed by libinput.
|
a device's capabilities before the device is processed by libinput.
|
||||||
|
|
||||||
|
A plugin should always ``connect()`` to the ``"device-removed"`` callback
|
||||||
|
to be notified when a device is removed. If the plugin keeps a reference
|
||||||
|
to this device but the device is discarded by libinput, the device's query
|
||||||
|
methods will return zero values (e.g. ``nil``, ``0``, an empty table) and
|
||||||
|
methods will be noops.
|
||||||
|
|
||||||
.. function:: EvdevDevice:info()
|
.. function:: EvdevDevice:info()
|
||||||
|
|
||||||
A table containing static information about the device, e.g.
|
A table containing static information about the device, e.g.
|
||||||
|
|
@ -403,13 +427,16 @@ a device's capabilities before the device is processed by libinput.
|
||||||
- ``vid``: The 16-bit vendor ID of the device
|
- ``vid``: The 16-bit vendor ID of the device
|
||||||
- ``pid``: The 16-bit product ID of the device
|
- ``pid``: The 16-bit product ID of the device
|
||||||
|
|
||||||
|
If the device has since been discarded by libinput, this function returns an
|
||||||
|
empty table.
|
||||||
|
|
||||||
.. function:: EvdevDevice:name()
|
.. function:: EvdevDevice:name()
|
||||||
|
|
||||||
The device name as set by the kernel
|
The device name as set by the kernel
|
||||||
|
|
||||||
.. function:: EvdevDevice:usages()
|
.. function:: EvdevDevice:usages()
|
||||||
|
|
||||||
Returns a nested table of all usages that are currently enabled for this
|
Returns a table of all usages that are currently enabled for this
|
||||||
device. Any type that exists on the device has a table assigned and in this
|
device. Any type that exists on the device has a table assigned and in this
|
||||||
table any code that exists on the device is a boolean true.
|
table any code that exists on the device is a boolean true.
|
||||||
For example:
|
For example:
|
||||||
|
|
@ -480,7 +507,11 @@ a device's capabilities before the device is processed by libinput.
|
||||||
Enable the given :ref:`evdev usage <plugins_api_evdev_usage>` for this device.
|
Enable the given :ref:`evdev usage <plugins_api_evdev_usage>` for this device.
|
||||||
Use :ref:`plugins_api_evdev_global` for better readability,
|
Use :ref:`plugins_api_evdev_global` for better readability,
|
||||||
e.g. ``device:enable_evdev_usage(evdev.REL_X)``.
|
e.g. ``device:enable_evdev_usage(evdev.REL_X)``.
|
||||||
This function must not be used for ``ABS_*`` events, use ``set_absinfo()`` instead.
|
This function must not be used for ``ABS_*`` events, use ``set_absinfo()``
|
||||||
|
instead.
|
||||||
|
|
||||||
|
Once a usage is enabled, events for that usage may be added to a device's
|
||||||
|
frame.
|
||||||
|
|
||||||
If the device has since been discarded by libinput, this function does nothing.
|
If the device has since been discarded by libinput, this function does nothing.
|
||||||
|
|
||||||
|
|
@ -490,17 +521,20 @@ a device's capabilities before the device is processed by libinput.
|
||||||
Use :ref:`plugins_api_evdev_global` for better readability,
|
Use :ref:`plugins_api_evdev_global` for better readability,
|
||||||
e.g. ``device:disable_evdev_usage(evdev.REL_X)``.
|
e.g. ``device:disable_evdev_usage(evdev.REL_X)``.
|
||||||
|
|
||||||
|
Once a usage is disabled, events for that usage are discarded from any
|
||||||
|
device frame.
|
||||||
|
|
||||||
If the device has since been discarded by libinput, this function does nothing.
|
If the device has since been discarded by libinput, this function does nothing.
|
||||||
|
|
||||||
.. function:: EvdevDevice:set_absinfo(usage, absinfo)
|
.. function:: EvdevDevice:set_absinfo(usage, absinfo)
|
||||||
|
|
||||||
Set the absolute axis information for the given :ref:`evdev usage <plugins_api_evdev_usage>`
|
Set the absolute axis information for the given :ref:`evdev usage <plugins_api_evdev_usage>`
|
||||||
if it does not yet exist on the device. The ``absinfo`` argument is a table
|
and enable it if it does not yet exist on the device. The ``absinfo`` argument is a table
|
||||||
containing zero or more of the following keys: ``min``, ``max``, ``fuzz``,
|
containing zero or more of the following keys: ``min``, ``max``, ``fuzz``,
|
||||||
``flat``, ``resolution``. Any missing key defaults the corresponding
|
``flat``, ``resolution``. Any missing key defaults the corresponding
|
||||||
value from the device if the device already has this event code or zero otherwise.
|
value from the device if the device already has this event usage or zero otherwise.
|
||||||
In other words the following code is enough to change the resolution but leave
|
For example, the following code changes the resolution but leaves everything
|
||||||
everything else as-is:
|
else as-is:
|
||||||
|
|
||||||
.. code-block:: lua
|
.. code-block:: lua
|
||||||
|
|
||||||
|
|
@ -591,12 +625,11 @@ a device's capabilities before the device is processed by libinput.
|
||||||
.. function:: EvdevDevice:prepend_frame(frame)
|
.. function:: EvdevDevice:prepend_frame(frame)
|
||||||
|
|
||||||
Prepend an :ref:`evdev frame <plugins_api_evdev_frame>` for this device
|
Prepend an :ref:`evdev frame <plugins_api_evdev_frame>` for this device
|
||||||
**before** the current frame (if any). This function can only be called from
|
**before** the current frame (if any). The **next** plugin will see the
|
||||||
within a device's ``frame()`` handler or from within the plugin's timer
|
prepended frame first followed by the current frame.
|
||||||
callback function.
|
|
||||||
|
|
||||||
Assuming three plugins P1, P2 and P3, if P2 injects a frame the frame is
|
This function can only be called from within a device's ``frame()`` handler
|
||||||
seen only by P3.
|
or from within the plugin's timer callback function.
|
||||||
|
|
||||||
For example, to change a single event into a drag, prepend a button
|
For example, to change a single event into a drag, prepend a button
|
||||||
down and append a button up before each event:
|
down and append a button up before each event:
|
||||||
|
|
@ -610,11 +643,10 @@ a device's capabilities before the device is processed by libinput.
|
||||||
device:append_frame({
|
device:append_frame({
|
||||||
{ usage = evdev.BTN_LEFT, value = 0}
|
{ usage = evdev.BTN_LEFT, value = 0}
|
||||||
})
|
})
|
||||||
return nil -- return the frame unmodified
|
return nil -- return the current frame unmodified
|
||||||
|
|
||||||
-- this results in the event sequence
|
-- The next plugin sees the event sequence:
|
||||||
-- button down, frame, button up
|
-- button down, frame, button up
|
||||||
-- to be passed to the next plugin
|
|
||||||
end
|
end
|
||||||
|
|
||||||
If called from within the plugin's timer there is no current frame and this
|
If called from within the plugin's timer there is no current frame and this
|
||||||
|
|
@ -644,9 +676,9 @@ a device's capabilities before the device is processed by libinput.
|
||||||
|
|
||||||
Version 1 of the plugin API supports the following features:
|
Version 1 of the plugin API supports the following features:
|
||||||
|
|
||||||
- ``button-debouncing``: see :ref:`button_debouncing`
|
- ``"button-debouncing"``: see :ref:`button_debouncing`
|
||||||
- ``touchpad-hysteresis``: see :ref:`touchpad_jitter`
|
- ``"touchpad-hysteresis"``: see :ref:`touchpad_jitter`
|
||||||
- ``touchpad-jump-detection``: see :ref:`touchpad_jumping_cursor`
|
- ``"touchpad-jump-detection"``: see :ref:`touchpad_jumping_cursor`
|
||||||
- ``touchpad-palm-detection``: see :ref:`palm_detection`
|
- ``"touchpad-palm-detection"``: see :ref:`palm_detection`
|
||||||
- ``wheel-debouncing``: some high-resolution mouse wheel movements inside libinput
|
- ``"wheel-debouncing"``: some high-resolution mouse wheel movements inside libinput
|
||||||
are delayed and/or modified
|
are delayed and/or modified
|
||||||
|
|
|
||||||
|
|
@ -100,6 +100,7 @@ src_rst = files(
|
||||||
'dot/libinput-stack-gnome.gv',
|
'dot/libinput-stack-gnome.gv',
|
||||||
'dot/evemu.gv',
|
'dot/evemu.gv',
|
||||||
'dot/libinput-record.gv',
|
'dot/libinput-record.gv',
|
||||||
|
'dot/plugin-stack.gv',
|
||||||
# svgs
|
# svgs
|
||||||
'svg/button-debouncing-wave-diagram.svg',
|
'svg/button-debouncing-wave-diagram.svg',
|
||||||
'svg/button-scrolling.svg',
|
'svg/button-scrolling.svg',
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue