Commit cbd4f354 authored by Peter Hutterer's avatar Peter Hutterer
Browse files

dox: switch to sphinx for the user-visible documentation

This is a large commit because it's difficult to split this up and we don't
care about bisecting here anyway.

doxygen is going to produce the API documentation only
sphinx is going to produce the prose user (and a bit of developer) documentation.

The source split is doc/api and doc/user.

Steps performed:
- run the script to convert all .dox sources to .rst
- manually fixed the .rst to render correctly
- add a few extra .rst documents to generate the right hierarchy
- hook up sphinx-build in meson
- add a new @mainpage for doxygen more aimed at developers

For the build directory:
- sphinx produces /Documentation
- doxygen now produces /api/

These need to be manually combined in the wayland-web repo, meson doesn't
support subdirectories as output paths within the build dir and the
documentation doesn't need to be installed anywhere.
Signed-off-by: Peter Hutterer's avatarPeter Hutterer <>
parent 581fbbea
......@@ -13,7 +13,7 @@ INPUT = "@builddir@"
IMAGE_PATH = "@builddir@"
HTML_OUTPUT = Documentation
......@@ -31,4 +31,3 @@ HTML_FOOTER = "@builddir@/footer.html"
HTML_EXTRA_STYLESHEET = "@builddir@/bootstrap.css" \
"@builddir@/customdoxygen.css" \
This is the libinput API reference.
This documentation is aimed at developers of Wayland compositors. User
documentation is available
@section concepts Concepts
@subsection concepts_initialization Initialization of a libinput context
libinput provides two different backends:
- a @ref libinput_udev_create_context "udev backend" where notifications
about new and removed devices are provided by udev, and
- a @ref libinput_path_create_context "path backend" where
@ref libinput_path_add_device "device addition" and
@ref libinput_path_remove_device "device removal" need to be handled by
the caller.
See section @ref base for information about initializing a libinput context.
@subsection concepts_events Monitoring for events
libinput exposes a single @ref libinput_get_fd "file descriptor" to the
caller. This file descriptor should be monitored by the caller, whenever
data is available the caller **must** immediately call libinput_dispatch().
Failure to do so will result in erroneous behavior.
libinput_dispatch() may result in one or more events being available to the
caller. After libinput_dispatch() a caller **should** call
libinput_get_event() to retrieve and process this event. Whenever
libinput_get_event() returns `NULL`, no further events are available.
See section @ref event for more information about events.
@subsection concepts_seats Device grouping into seats
All devices are grouped into physical and logical seats. Button and key
states are available per-device and per-seat. See @ref seat for more
@subsection concepts_devices Device capabilities
libinput does not use device types. All devices have @ref
libinput_device_has_capability "capabilities" that define which events may
be generated. See @ref device for more information about devices.
Specific event types include:
- @ref event_keyboard
- @ref event_pointer
- @ref event_touch
- @ref event_gesture
- @ref event_tablet
- @ref event_tablet_pad
- @ref event_switch
@subsection concepts_configuration Device configuration
libinput relies on the caller for device configuration. See
@ref config for more information.
@subsection example An example libinput program
The simplest libinput program looks like this:
static int open_restricted(const char *path, int flags, void *user_data)
int fd = open(path, flags);
return fd < 0 ? -errno : fd;
static void close_restricted(int fd, void *user_data)
const static struct libinput_interface interface = {
.open_restricted = open_restricted,
.close_restricted = close_restricted,
int main(void) {
struct libinput *li;
struct libinput_event *event;
li = libinput_udev_create_context(&interface, NULL, udev);
libinput_udev_assign_seat(li, "seat0");
while ((event = libinput_get_event(li)) != NULL) {
// handle the event here
return 0;
@section building_against Building against libinput
libinput provides a
[pkg-config]( file.
Software that uses libinput should use pkg-config and the
`PKG_CHECK_MODULES` autoconf macro.
Otherwise, the most rudimentary way to compile and link a program against
libinput is:
gcc -o myprogram myprogram.c `pkg-config --cflags --libs libinput`
For further information on using pkgconfig see the pkg-config documentation.
@section stability Backwards-compatibility
libinput promises backwards-compatibility across all the 1.x.y version. An
application built against libinput 1.x.y will work with any future 1.*.*
@section About
Documentation generated by from git commit [__GIT_VERSION__](
......@@ -35,98 +35,26 @@ doc_git_version = vcs_tag(command : ['git', 'log', '-1', '--format=%h'],
output : 'git-version.dox',
replace_string: '__GIT_VERSION__')
readme = vcs_tag(command : ['git', 'log', '-1', '--format=%h'],
mainpage = vcs_tag(command : ['git', 'log', '-1', '--format=%h'],
fallback : 'unknown',
input : '../',
output : '',
input : 'mainpage.dox',
output : 'mainpage.dox',
replace_string: '__GIT_VERSION__')
src_extra = [
# dot drawings
# svgs
src_doxygen = files(
# source files
# written docs
join_paths(meson.source_root(), 'src', 'libinput.h'),
# style files
doxyfiles = custom_target('doxyfiles',
input : src_doxygen,
output : '.',
output : 'doxyfiles',
command : [prg_install, '-t', '@OUTDIR@', '@INPUT@'],
build_by_default: true)
......@@ -141,9 +69,9 @@ doxyfile = configure_file(input : '',
install : false)
input : [ doxyfile, readme, doc_git_version] + src_doxygen + src_extra,
output : [ 'Documentation' ],
input : [ doxyfile, mainpage, doc_git_version] + src_doxygen,
output : [ '.' ],
command : [ doxygen, doxyfile ],
install : false,
depends: [doxyfiles, readme, doc_git_version],
depends: [doxyfiles, mainpage, doc_git_version],
build_by_default : true)
@page Tablets
- @subpage tablet serial numbers
......@@ -252,4 +252,3 @@ blockquote {
margin: 0 24px 0 4px;
padding: 0 12px 0 16px;
......@@ -8,7 +8,7 @@
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta name="generator" content="Doxygen $doxygenversion"/>
<script type="text/javascript" src=""></script>
<!--BEGIN PROJECT_NAME--><title>$projectname: $title</title><!--END PROJECT_NAME-->
@page architecture libinput's internal architecture
This page provides an outline of libinput's internal architecture. The goal
here is to get the high-level picture across and point out the components
and their interplay to new developers.
The public facing API is in `libinput.c`, this file is thus the entry point
for almost all API calls. General device handling is in `evdev.c` with the
device-type-specific implementations in `evdev-<type>.c`. It is not
necessary to understand all of libinput to contribute a patch.
@ref architecture-contexts is the only user-visible implementation detail,
everything else is purely internal implementation and may change when
@section architecture-contexts The udev and path contexts
The first building block is the "context" which can be one of
two types, "path" and "udev". See libinput_path_create_context() and
libinput_udev_create_context(). The path/udev specific bits are in
`path-seat.c` and `udev-seat.c`. This includes the functions that add new
devices to a context.
digraph context
node [
libudev [label="libudev 'add' event"]
udev [label="libinput_udev_create_context()"];
udev_backend [label="udev-specific backend"];
context [label="libinput context"]
udev -> udev_backend;
libudev -> udev_backend;
udev_backend -> context;
The udev context provides automatic device hotplugging as udev's "add"
events are handled directly by libinput. The path context requires that the
caller adds devices.
digraph context
node [
path [label="libinput_path_create_context()"];
path_backend [label="path-specific backend"];
xdriver [label="libinput_path_add_device()"]
context [label="libinput context"]
path -> path_backend;
xdriver -> path_backend;
path_backend -> context;
As a general rule: all Wayland compositors use a udev context, the
stack uses a path context.
Which context was initialized only matters for creating/destroying a context
and adding devices. The device handling itself is the same for both types of
@section architecture-device Device initialization
libinput only supports evdev devices, all the device initialization is done
in `evdev.c`. Much of the libinput public API is also a thin wrapper around
the matching implementation in the evdev device.
There is a 1:1 mapping between libinput devices and `/dev/input/eventX`
device nodes.
digraph context
node [
devnode [label="/dev/input/event0"]
libudev [label="libudev 'add' event"]
xdriver [label="libinput_path_add_device()"]
context [label="libinput context"]
evdev [label="evdev_device_create()"]
devnode -> xdriver;
devnode -> libudev;
xdriver -> context;
libudev -> context;
Entry point for all devices is `evdev_device_create()`, this function
decides to create a `struct evdev_device` for the given device node.
Based on the udev tags (e.g. `ID_INPUT_TOUCHPAD`), a @ref
architecture-dispatch is initialized. All event handling is then in this
Rejection of devices and the application of quirks is generally handled in
`evdev.c` as well. Common functionality shared across multiple device types
(like button-scrolling) is also handled here.
@section architecture-dispatch Device-type specific event dispatch
Depending on the device type, `evdev_configure_device` creates the matching
`struct evdev_dispatch`. This dispatch interface contains the function
pointers to handle events. Four such dispatch methods are currently
implemented: touchpad, tablet, tablet pad, and the fallback dispatch which
handles mice, keyboards and touchscreens.
digraph context
node [
evdev [label="evdev_device_create()"]
fallback [label="evdev-fallback.c"]
touchpad [label="evdev-mt-touchpad.c"]
tablet [label="evdev-tablet.c"]
pad [label="evdev-tablet-pad.c"]
evdev -> fallback;
evdev -> touchpad;
evdev -> tablet;
evdev -> pad;
While `evdev.c` pulls the event out of libevdev, the actual handling of the
events is performed within the dispatch method.
digraph context
node [
evdev [label="evdev_device_dispatch()"]
fallback [label="fallback_interface_process()"];
touchpad [label="tp_interface_process()"]
tablet [label="tablet_process()"]
pad [label="pad_process()"]
evdev -> fallback;
evdev -> touchpad;
evdev -> tablet;
evdev -> pad;
The dispatch methods then look at the `struct input_event` and proceed to
update the state. Note: the serialized nature of the kernel evdev protocol
requires that the device updates the state with each event but to delay
processing until the `SYN_REPORT` event is received.
@section architecture-configuration Device configuration
All device-specific configuration is handled through `struct
libinput_device_config_FOO` instances. These are set up during device init
and provide the function pointers for the `get`, `set`, `get_default`
triplet of configuration queries (or more, where applicable).
For example, the `struct tablet_dispatch` for tablet devices has a
`struct libinput_device_config_accel`. This struct is set up with the
required function pointers to change the profiles.
digraph context
node [
tablet [label="struct tablet_dispatch"]
config [label="struct libinput_device_config_accel"];
tablet_config [label="tablet_accel_config_set_profile()"];
When the matching `libinput_device_config_set_FOO()` is called, this goes
through to the config struct and invokes the function there. Thus, it is
possible to have different configuration functions for a mouse vs a
touchpad, even though the interface is the same.
digraph context
node [
libinput [label="libinput_device_config_accel_set_profile()"];
tablet_config [label="tablet_accel_config_set_profile()"];
@section architecture-filter Pointer acceleration filters
All pointer acceleration is handled in the `filter.c` file and its
associated files.
The `struct motion_filter` is initialized during device init, whenever
deltas are available they are passed to `filter_dispatch()`. This function
returns a set of @ref motion_normalization_customization "normalized coordinates".
All actual acceleration is handled within the filter, the device itself has
no further knowledge. Thus it is possible to have different acceleration
filters for the same device types (e.g. the Lenovo X230 touchpad has a
custom filter).
digraph context
node [
fallback [label="fallback deltas"];
touchpad [label="touchpad deltas"];
tablet [label="tablet deltas"];
filter [label="filter_dispatch"];
flat [label="accelerator_interface_flat()"];
x230 [label="accelerator_filter_x230()"];
pen [label="tablet_accelerator_filter_flat_pen()"];
Most filters convert the deltas (incl. timestamps) to a motion speed and
then apply a so-called profile function. This function returns a factor that
is then applied to the current delta, converting it into an accelerated
delta. See @ref pointer-acceleration for more details.
the current
@page building_libinput libinput build instructions
Instructions on how to build libinput and its tools and how to build against
The build instruction on this page detail how to overwrite your
system-provided libinput with one from the git repository, see
see @ref reverting_install to revert to the previous state.
@section building Building libinput
libinput uses [meson]( and
[ninja]( A build is usually the three-step
process below. A successful build requires the @ref
building_dependencies to be installed before running meson.
$> git clone
$> cd libinput
$> meson --prefix=/usr builddir/
$> ninja -C builddir/
$> sudo ninja -C builddir/ install
When running libinput versions 1.11.x or earlier, you must run
$> sudo udevadm hwdb --update
Additional options may also be specified. For example:
$> meson --prefix=/usr -Ddocumentation=false builddir/
We recommend that users disable the documentation, it's not usually required
for testing and reduces the number of dependencies needed.
The `prefix` or other options can be changed later with the
`mesonconf` command. For example:
$> mesonconf builddir/ -Dprefix=/some/other/prefix -Ddocumentation=true
$> ninja -C builddir
$> sudo ninja -C builddir/ install
Running ``mesonconf builddir/`` with no other arguments lists all
configurable options meson provides.
To rebuild from scratch, simply remove the build directory and run meson
$> rm -r builddir/
$> meson --prefix=....
@subsection verifying_install Verifying the install
To verify the install worked correctly, check that is in
the library path and that all symlinks point to the new library.
$> ls -l /usr/lib64/libinput.*
-rwxr-xr-x 1 root root 946 Apr 28 2015 /usr/lib64/
lrwxrwxrwx 1 root root 19 Feb 1 15:12 /usr/lib64/ ->
lrwxrwxrwx 1 root root 19 Feb 1 15:12 /usr/lib64/ ->
-rwxr-xr-x 1 root root 204992 Feb 1 15:12 /usr/lib64/