2020-07-14 14:41:32 +10:00
|
|
|
libei
|
|
|
|
|
=====
|
|
|
|
|
|
|
|
|
|
**libei** is a library for Emulated Input, primarily aimed at the Wayland
|
2023-01-30 08:58:15 +10:00
|
|
|
stack. It provides three parts:
|
2020-08-12 14:09:22 +10:00
|
|
|
- 🥚 EI (Emulated Input) for the client side (`libei`)
|
|
|
|
|
- 🍦 EIS (Emulated Input Server) for the server side (`libeis`)
|
2022-12-02 12:08:40 +10:00
|
|
|
- 🚌 oeffis is an optional helper library for DBus communication with the
|
|
|
|
|
XDG RemoteDesktop portal (`liboeffis`)
|
2020-07-14 14:41:32 +10:00
|
|
|
|
2023-05-17 12:27:52 +10:00
|
|
|
The communication between EI and EIS happens over a UNIX socket via a custom
|
|
|
|
|
binary protocol. See the [EI protocol documentation](https://libinput.pages.freedesktop.org/libei/)
|
|
|
|
|
for details.
|
2020-07-14 14:41:32 +10:00
|
|
|
|
|
|
|
|
For the purpose of this document, **libei** refers to the project,
|
2023-01-30 08:58:15 +10:00
|
|
|
`libei`/`libeis` to the libraries provided.
|
2020-07-14 14:41:32 +10:00
|
|
|
|
2020-09-25 11:42:28 +10:00
|
|
|
Documentation
|
|
|
|
|
-------------
|
2023-03-03 14:57:20 +10:00
|
|
|
|
|
|
|
|
The protocol documentation is available
|
2020-09-25 11:42:28 +10:00
|
|
|
[here](https://libinput.pages.freedesktop.org/libei/)
|
|
|
|
|
|
2023-03-03 14:57:20 +10:00
|
|
|
The C library API documentation is available here:
|
|
|
|
|
- [libei](https://libinput.pages.freedesktop.org/libei/api/group__libei.html)
|
|
|
|
|
- [libeis](https://libinput.pages.freedesktop.org/libei/api/group__libeis.html)
|
|
|
|
|
- [liboffis](https://libinput.pages.freedesktop.org/libei/api/group__liboeffis.html)
|
|
|
|
|
|
2020-09-25 11:42:28 +10:00
|
|
|
Overview
|
|
|
|
|
--------
|
|
|
|
|
|
2020-07-14 14:41:32 +10:00
|
|
|
In the Wayland stack, the EIS server component is part of the
|
|
|
|
|
compositor, the EI client component is part of the Wayland client.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
+--------------------+ +------------------+
|
|
|
|
|
| Wayland compositor |---wayland---| Wayland client B |
|
|
|
|
|
+--------------------+\ +------------------+
|
|
|
|
|
| libinput | libeis | \_wayland______
|
|
|
|
|
+----------+---------+ \
|
|
|
|
|
| | +-------+------------------+
|
|
|
|
|
/dev/input/ +---brei----| libei | Wayland client A |
|
|
|
|
|
+-------+------------------+
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The use-cases **libei** attempts to solve are:
|
|
|
|
|
- on-demand input device emulation, e.g. `xdotool` or more generically the
|
|
|
|
|
XTEST extension
|
2022-06-07 10:29:58 +10:00
|
|
|
- input forwarding, e.g. `synergy`, for both client-emulated input as well as
|
|
|
|
|
the forwarding of physical or logical devices.
|
2020-07-14 14:41:32 +10:00
|
|
|
|
|
|
|
|
**libei** provides three benefits:
|
|
|
|
|
- separation
|
|
|
|
|
- distinction
|
|
|
|
|
- control
|
|
|
|
|
|
|
|
|
|
**libei** provides **separation** of emulated input from normal input.
|
|
|
|
|
Emulated input is a distinct channel for the compositor and can thus be
|
2020-07-29 20:21:27 +10:00
|
|
|
handled accordingly. For example, the compositor may show a warning sign in
|
|
|
|
|
the task bar while emulated input is active.
|
2020-07-14 14:41:32 +10:00
|
|
|
|
|
|
|
|
The second benefit is **distinction**. Each **libei** client has its own
|
|
|
|
|
input device set, the server is always aware of which client is requesting
|
|
|
|
|
input at any time. It is possible for the server to treat input from
|
|
|
|
|
different emulated input devices differently.
|
|
|
|
|
|
|
|
|
|
The server is in **control** of emulated input - it can filter input or
|
|
|
|
|
discard at will. For example, if the current focus window is a password
|
|
|
|
|
prompt, the server can simply discard any emulated input. If the screen is
|
2021-08-23 08:25:33 +10:00
|
|
|
locked, the server can pause all emulated input devices.
|
2020-07-14 14:41:32 +10:00
|
|
|
|
2022-06-07 10:29:58 +10:00
|
|
|
Sender vs receiver contexts
|
|
|
|
|
---------------------------
|
|
|
|
|
|
|
|
|
|
As of version 0.3, libei allows a ``libei`` context to be either a sender or a
|
|
|
|
|
receiver. In the "sender" mode, the ``libei`` context gets a list of devices
|
|
|
|
|
from the EIS implementation and can emulate events on these devices. The
|
|
|
|
|
devices usually represent virtual devices, e.g. a generic relative pointer
|
|
|
|
|
corresponding to the cursor or per-screen absolute input devices.
|
|
|
|
|
|
|
|
|
|
In the "receiver" mode, the ``libei`` context gets a list of devices from the
|
|
|
|
|
EIS implementation and *receives* events from those. This allows for input
|
|
|
|
|
capture, provided the EIS implementation supports it. The devices can
|
|
|
|
|
correspond to virtual devices, e.g. a generic relative pointer corresponding
|
|
|
|
|
to the cursor. Or they may be representations of physical devices, e.g. a
|
|
|
|
|
tablet device getting forwarded.
|
|
|
|
|
|
|
|
|
|
A ``libei`` context may only be in one mode. It is up to the EIS
|
|
|
|
|
implementation to accept a sender or receiver ``libei`` context.
|
|
|
|
|
|
2020-07-29 20:21:27 +10:00
|
|
|
Why not $foo?
|
|
|
|
|
-------------
|
|
|
|
|
|
|
|
|
|
We start from the baseline of: "there is no emulated input in Wayland (the
|
|
|
|
|
protocol)".
|
|
|
|
|
|
|
|
|
|
There is emulated input in X through XTEST but it provides neither
|
|
|
|
|
separation, distinction nor control in a useful manner. There are however
|
|
|
|
|
many X clients that require XTEST to work.
|
|
|
|
|
|
|
|
|
|
There are several suggestions that overlap with **libei**, with the main
|
|
|
|
|
proposals being:
|
|
|
|
|
- a Wayland protocol for virtual input
|
|
|
|
|
- a (compositor-specific) DBus interface for virtual input
|
|
|
|
|
|
|
|
|
|
Emulated input is not specifically Wayland-y. Clients that emulate input
|
|
|
|
|
generally don't care about Wayland itself. It's not needed to emulate
|
|
|
|
|
events on their own surfaces and Wayland does not provide global state. The
|
|
|
|
|
only connection to Wayland is merely that input events are *received*
|
|
|
|
|
through the Wayland protocol. So a Wayland protocol for emulating input is
|
|
|
|
|
not a great fit, it merely ticks the convenient box of "we already have IPC
|
|
|
|
|
through the wayland protocol, why not just do it there".
|
|
|
|
|
|
|
|
|
|
DBus is the most prevalent generic IPC channel on the Linux desktop but it's
|
|
|
|
|
not available in some compositors. Any other specific side-channel requires
|
|
|
|
|
an IPC mechanism to be implemented in the sender and receiver.
|
|
|
|
|
|
|
|
|
|
The current situation looks like that neither proposal will be universally
|
|
|
|
|
available. Wayland clients (including Xwayland) would need to support any
|
|
|
|
|
combination of methods.
|
|
|
|
|
|
|
|
|
|
**libei** side-steps this issue by making the *communication* itself a
|
|
|
|
|
an implementation detail and providing different *negotiation* backends.
|
|
|
|
|
A client can attempt to establish a **libei** context through a Flatpak
|
2022-02-16 13:47:30 +10:00
|
|
|
Portal first and fall back onto a public DBus interface and then fall back
|
|
|
|
|
onto e.g. a named UNIX socket. All with a few lines of code only. There is
|
|
|
|
|
only one spot the client has to care about this, the actual emulation of input
|
|
|
|
|
is identical regardless of backend.
|
2020-07-29 20:21:27 +10:00
|
|
|
|
2020-07-14 14:41:32 +10:00
|
|
|
High-level summary
|
|
|
|
|
------------------
|
|
|
|
|
|
2023-05-04 14:10:05 +10:00
|
|
|
Simple demo implementations for server and client are available in
|
2023-05-04 14:10:51 +10:00
|
|
|
the [`tools/`](https://gitlab.freedesktop.org/libinput/libei/-/tree/main/tools)
|
2020-07-14 14:41:32 +10:00
|
|
|
directory.
|
|
|
|
|
|
|
|
|
|
The server starts a `libeis` context (which can be integrated with flatpak
|
|
|
|
|
portals) and uses the `libeis` file descriptor to monitor for
|
|
|
|
|
client requests.
|
|
|
|
|
|
|
|
|
|
A client starts a `libei` context and connects to the server - either
|
|
|
|
|
directly, via DBus or via a portal. The server (or the portal) approves or
|
2020-10-26 09:26:47 +10:00
|
|
|
denies the client. After successful authentication the server sends one or
|
|
|
|
|
more seats (a logical group of devices) to the client; the client can
|
2022-02-16 13:47:30 +10:00
|
|
|
request the creation of devices with capabilities `pointer`, `keyboard` or
|
2020-10-26 09:26:47 +10:00
|
|
|
`touch`, etc. in those seats.
|
2020-07-14 14:41:32 +10:00
|
|
|
|
2022-02-16 13:47:30 +10:00
|
|
|
The client triggers input events on these devices, the server receives those
|
|
|
|
|
as events through `libeis` and can forward them as if they were regular input
|
2020-07-14 14:41:32 +10:00
|
|
|
events. The server has control of the client stream. If the stream is
|
|
|
|
|
paused, events from the client are discarded. If the stream is resumed, the
|
|
|
|
|
server will receive the events (but may discard them anyway depending on
|
|
|
|
|
local state).
|
|
|
|
|
|
|
|
|
|
The above caters for the `xdotool` use-case.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
For a `synergy` use-case, the setup requires:
|
2020-09-23 09:59:06 +10:00
|
|
|
- `synergy-client` on host A capturing mouse and keyboard events via an
|
|
|
|
|
unspecified protocol
|
2020-07-14 14:41:32 +10:00
|
|
|
- `synergy-server` on host B requesting a mouse/keyboard capability device
|
2020-09-23 09:59:06 +10:00
|
|
|
from the compositor
|
|
|
|
|
- when `synergy-client` receives events via from compositor A it
|
2020-07-14 14:41:32 +10:00
|
|
|
forwards those to the remote `synergy-server` which sends them via `libei`
|
|
|
|
|
to the compositor B.
|
|
|
|
|
|
2022-06-07 10:29:58 +10:00
|
|
|
**libei** does not provide a method for deciding when events should be
|
|
|
|
|
captured, it merely provides the transport layer for events once that decision
|
|
|
|
|
has been made.
|
2020-07-14 14:41:32 +10:00
|
|
|
|
2020-08-28 13:11:39 +10:00
|
|
|
Differences between XTest vs libei
|
|
|
|
|
----------------------------------
|
|
|
|
|
|
|
|
|
|
**libei** functionality is a superset of XTest's input emulation which
|
|
|
|
|
consists of a single request, `XTestFakeInput`. This request allows
|
|
|
|
|
emulation of button, key and motion events, including X Input 1.x events
|
|
|
|
|
(but not XI2). So **libei** can be a drop-in replacement since it supports
|
|
|
|
|
the same functionality and more.
|
|
|
|
|
|
|
|
|
|
However, XTest is an X protocol extension and users of XTest usually obtain
|
|
|
|
|
more information out-of-band ("out-of-band" here means "not through XTest
|
|
|
|
|
but instead other X protocol requests").
|
|
|
|
|
|
|
|
|
|
One example is `xdotool` which does window focus and modifier mangling (see
|
|
|
|
|
below). Window focus notification is not available to a pure **libei**
|
|
|
|
|
client and would have to be obtained or handled on a separate channel, e.g.
|
|
|
|
|
X or Wayland. Having said that, a Wayland client does not usually have acess
|
|
|
|
|
to query or modifiy the window focus.
|
|
|
|
|
|
|
|
|
|
Modifiers in `xdotool` are handled by obtaining the modifier mask from the X
|
|
|
|
|
server, identifying any difference to the intended mask and emulating key
|
|
|
|
|
events to change the modifier state to the intended one. For example, if
|
|
|
|
|
capslock is on, xdotool would send a capslock key event first (thus
|
|
|
|
|
disabling capslock) and then the actual key sequence. This is followed by
|
|
|
|
|
another capslock key event to restore the modifier mask.
|
|
|
|
|
|
|
|
|
|
This is not possible for a pure **libei** client as the modifier state is
|
|
|
|
|
maintained by the windowing system (if any). A client can obtain the
|
|
|
|
|
modifier state on Wayland on `wl_keyboard.enter` but when the client is
|
|
|
|
|
in-focus, there is rarely a need to emulate events.
|
|
|
|
|
|
|
|
|
|
Overall, it is best to think of **libei** devices as virtual equivalents to
|
|
|
|
|
a hardware device.
|
2020-07-14 14:41:32 +10:00
|
|
|
|
|
|
|
|
Open questions
|
|
|
|
|
--------------
|
|
|
|
|
|
|
|
|
|
### Flatpak integration
|
|
|
|
|
|
2020-08-11 20:54:01 +10:00
|
|
|
Where flatpak portals are in use, `libei` can communicate with
|
|
|
|
|
the portal through a custom backend. The above diagram modified for
|
|
|
|
|
Flatpak would be:
|
2020-07-14 14:41:32 +10:00
|
|
|
|
2020-08-11 20:54:01 +10:00
|
|
|
```
|
|
|
|
|
+--------------------+
|
|
|
|
|
| Wayland compositor |_
|
|
|
|
|
+--------------------+ \
|
|
|
|
|
| libinput | libeis | \_wayland______
|
|
|
|
|
+----------+---------+ \
|
|
|
|
|
| [eis-0.socket] \
|
|
|
|
|
/dev/input/ / \\ +-------+------------------+
|
|
|
|
|
| ======>| libei | Wayland client A |
|
|
|
|
|
| after +-------+------------------+
|
|
|
|
|
initial| handover /
|
|
|
|
|
connection| / initial request
|
2022-09-08 09:07:10 +10:00
|
|
|
| / dbus[org.freedesktop.portal.RemoteDesktop.ConnectToEIS]
|
2020-08-11 20:54:01 +10:00
|
|
|
+--------------------+
|
|
|
|
|
| xdg-desktop-portal |
|
|
|
|
|
+--------------------+
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The current approach works so that
|
|
|
|
|
- the compositor starts an `libeis` socket backend at `$XDG_RUNTIME_DIR/eis-0`
|
2022-09-08 09:07:10 +10:00
|
|
|
- `xdg-desktop-portal` provides `org.freedesktop.portal.RemoteDesktop.ConnectToEIS`
|
2020-08-11 20:54:01 +10:00
|
|
|
- a client connects to the `xdg-desktop-portal` to request emulated input
|
|
|
|
|
- `xdg-desktop-portal` authenticates a client and opens the initial
|
2023-01-30 08:58:15 +10:00
|
|
|
connection to the `libeis` socket.
|
2020-08-11 20:54:01 +10:00
|
|
|
- `xdg-desktop-portal` hands over the file descriptor to the client which
|
|
|
|
|
can initialize a `libei` context
|
|
|
|
|
- from then on, `libei` and `libeis` talk directly to each other, the portal
|
|
|
|
|
has no further influence.
|
|
|
|
|
|
|
|
|
|
This describes the **current** implementation. Changes to this approach are
|
2021-08-23 08:25:33 +10:00
|
|
|
likely, e.g. the portal **may** control pauseing/resuming devices (in addition to the
|
2020-07-14 14:41:32 +10:00
|
|
|
server). The UI for this is not yet sorted.
|
|
|
|
|
|
|
|
|
|
### Authentication
|
|
|
|
|
|
|
|
|
|
Sandboxing is addressed via flatpak portals but a further level is likely
|
|
|
|
|
desirable, esp. outside flatpak. The simplest solution is the client
|
|
|
|
|
announcing the name so the UI can be adjusted accordingly. API wise-maybe an
|
|
|
|
|
opaque key/value system so the exact auth can be left to the implementation.
|
|
|
|
|
|
2020-09-23 09:59:06 +10:00
|
|
|
### Capability monitoring
|
|
|
|
|
|
|
|
|
|
For the use-case of fowarding input (e.g. `synergy`) we need a method of
|
|
|
|
|
capturing input as well as forwarding input. An initial idea was for
|
|
|
|
|
**libei** to provide capability monitoring, i.e. a client requests all
|
|
|
|
|
events from a specific capability. As with input emulation same benefits
|
|
|
|
|
would apply - input can only be forwarded if the compositor explicitly does so.
|
2020-07-14 14:41:32 +10:00
|
|
|
|
2020-09-23 09:59:06 +10:00
|
|
|
However, this fails in the details. For example, for `synergy` we need
|
|
|
|
|
capability monitoring started by triggers, e.g. the client requests a
|
|
|
|
|
pointer capability monitoring when the real pointer hits
|
2020-07-14 14:41:32 +10:00
|
|
|
the screen edge. Or in response to a keyboard shortcut.
|
2020-09-23 09:59:06 +10:00
|
|
|
|
|
|
|
|
Some of the capabilities are distinctively display server-specific, for
|
|
|
|
|
example the concept of a seat and a device is different between X and
|
|
|
|
|
Wayland.
|
2020-07-14 14:41:32 +10:00
|
|
|
|
2022-02-16 13:47:30 +10:00
|
|
|
At this point, no implementation of capability monitoring is planned for
|
|
|
|
|
**libei**.
|
|
|
|
|
|
2020-07-14 14:41:32 +10:00
|
|
|
### Keyboard layouts
|
|
|
|
|
|
2020-07-16 12:54:02 +10:00
|
|
|
The emulated input may require a specific keyboard layout, for example
|
|
|
|
|
for softtokens (usually: constant layout "us") or for the `synergy` case
|
|
|
|
|
where the remote keyboard should have the same keymap as the local one, even
|
|
|
|
|
where the remote host is configured otherwise.
|
|
|
|
|
|
2022-02-16 13:47:30 +10:00
|
|
|
In **libei**, the server informs the client about the keymap it expects and it
|
|
|
|
|
is up to the client to provide the correct keyboard events.
|
2020-07-16 12:54:02 +10:00
|
|
|
|
|
|
|
|
Modifier state handling, group handling, etc. is still a private
|
|
|
|
|
implementation so even where the server supports individual keymaps. So it
|
|
|
|
|
remains to be seen if this approach is sufficient.
|
2020-07-31 14:02:33 +10:00
|
|
|
|
|
|
|
|
### Xwayland and XTEST
|
|
|
|
|
|
|
|
|
|
There are PoC implementations of using `libei` within Xwayland and
|
|
|
|
|
connecting it to a `libeis` context in the compositor (PoC with Weston).
|
|
|
|
|
This allows Xwayland to intercept XTEST events and route those through
|
|
|
|
|
the compositor instead.
|
|
|
|
|
|
2020-08-25 14:30:17 +10:00
|
|
|
```
|
|
|
|
|
+--------------------+ +------------------+
|
|
|
|
|
| Wayland compositor |---wayland---| Wayland client B |
|
|
|
|
|
+--------------------+\ +------------------+
|
|
|
|
|
| libinput | libeis | \_wayland______
|
|
|
|
|
+----------+---------+ \
|
|
|
|
|
| | +-------+------------------+
|
2022-07-18 10:25:56 +02:00
|
|
|
/dev/input/ +---brei----| libei | Xwayland |
|
2020-08-25 14:30:17 +10:00
|
|
|
+-------+------------------+
|
|
|
|
|
|
|
|
|
|
|
| XTEST
|
|
|
|
|
|
|
|
|
|
|
+-----------+
|
|
|
|
|
| X client |
|
|
|
|
|
+-----------+
|
|
|
|
|
```
|
2022-07-18 10:25:56 +02:00
|
|
|
Of course, Xwayland is just another Wayland client, so the connection
|
2020-08-25 14:30:17 +10:00
|
|
|
between libei and libeis could be handled through a portal.
|
|
|
|
|
|
2020-07-31 14:02:33 +10:00
|
|
|
### Short-lived applications
|
|
|
|
|
|
2020-08-12 14:15:35 +10:00
|
|
|
**libei** is not designed for short-lived fire-and-forget-type applications
|
|
|
|
|
like `xdotool`. It provides context and device negotiation between the
|
2020-07-31 14:02:33 +10:00
|
|
|
server and the client - the latter must be able to adjust to limitations the
|
|
|
|
|
server imposes.
|
|
|
|
|
|
2024-08-22 12:12:20 +10:00
|
|
|
The current implementation of the protocol does not allow for a `libei` client
|
|
|
|
|
to connect, send all requests in bulk and exit. The decision on which devices
|
|
|
|
|
are available is made by the EIS implementation and that requires the `libei`
|
|
|
|
|
client to wait until such devices are available. On a technical level the
|
|
|
|
|
protocol is object-oriented and requests cannot be sent until the respective
|
|
|
|
|
device object is available.
|
|
|
|
|
|
|
|
|
|
The duration until devices become available is non-deterministic, and so is
|
|
|
|
|
what types of devices are available to a client. For **libei** to support a
|
|
|
|
|
connect-send-exit approach, it would still require the client process to stay
|
|
|
|
|
alive until device negotiation is complete within libei and all events have
|
|
|
|
|
been sent. And since the client process must stay alive, we might as well
|
|
|
|
|
have the device negotiation handled in the caller.
|
2020-08-27 11:45:15 +10:00
|
|
|
|
|
|
|
|
### uinput vs libei
|
|
|
|
|
|
|
|
|
|
uinput is a Linux kernel module that allows creating
|
|
|
|
|
`/dev/input/event`-compatible devices. Unlike XTest it is independent of a
|
|
|
|
|
windowing system but requires write access to `/dev/uinput`, usually limited
|
|
|
|
|
to root. uinput devices are effectively identical to physical devices and
|
|
|
|
|
will thus work on the tty and in any windowing system.
|
|
|
|
|
|
|
|
|
|
From the POV of a ``libei`` client, uinput is a server implementation
|
|
|
|
|
detail. The client does not need to know that the manager employs uinput to
|
|
|
|
|
create the devices, it merely connects to an available EIS instance.
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
+---------+
|
|
|
|
|
| server |___auth channel__________
|
|
|
|
|
+---------+ \
|
|
|
|
|
| libeis |- +---------------------+
|
|
|
|
|
+---------+ \____brei___| libei | application |
|
|
|
|
|
| +---------------------+
|
|
|
|
|
/dev/uinput/
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Note that the server would likely need some authentication channel
|
|
|
|
|
to verify which client is allowed to emulate input devices at the
|
|
|
|
|
kernel level (polkit? config files?). This however is out of scope for **libei**.
|
|
|
|
|
An example uinput server is implemented in the `eis-server-demo` in the
|
|
|
|
|
with libei repository.
|
2022-12-02 12:08:40 +10:00
|
|
|
|
|
|
|
|
# liboeffis
|
|
|
|
|
|
|
|
|
|
In a Wayland and/or sandboxed environment, emulating input events requires
|
|
|
|
|
going through the XDG RemoteDesktop portal. This portal is available on DBus
|
|
|
|
|
but communication with DBus is often cumbersome, especially for small tools.
|
|
|
|
|
|
|
|
|
|
`liboeffis` is an optional library that provides the communication with the
|
|
|
|
|
portal, sufficient to start a RemoteDesktop session and retrieve the file
|
|
|
|
|
descriptor to the EIS implementation.
|