libei: 🍦 EIS - The server API

libei 1.4.0 A library for Emulated Input

Topics | Data Structures | Typedefs | Enumerations | Functions
🍦 EIS - The server API

libeis is the server-side module. More...

## Topics
| The logging API
| The API to control logging output.
| API for receiver clients
| The receiver API is available only to clients that are not eis_client_is_sender().
| API for sender clients
| This API is available only on clients that are eis_client_is_sender().
| The seat API
| The API to query and interact with a struct eis_seat.
| The device API
| The API to query and interact with a struct eis_device.
| The region API
| The API to query a struct eis_region for information.
| The keymap API
| The API to query a struct eis_keymap for information.

## Data Structures
struct | eis
struct | eis_client
struct | eis_device
struct | eis_seat
struct | eis_event
struct | eis_keymap
struct | eis_touch
struct | eis_ping
| A callback struct returned by eis_new_ping() to handle roundtrips to the client. More...
struct | eis_region
| Regions are only available on devices of type EIS_DEVICE_TYPE_VIRTUAL. More...

## Typedefs
typedef uint64_t(* | eis_clock_now_func) (struct eis *eis)
| Optional override function for eis_now().

## Enumerations
enum | eis_device_type { EIS_DEVICE_TYPE_VIRTUAL , EIS_DEVICE_TYPE_PHYSICAL }
| The device type determines what the device represents. More...
enum | eis_device_capability { EIS_DEVICE_CAP_POINTER , EIS_DEVICE_CAP_POINTER_ABSOLUTE , EIS_DEVICE_CAP_KEYBOARD , EIS_DEVICE_CAP_TOUCH , EIS_DEVICE_CAP_SCROLL , EIS_DEVICE_CAP_BUTTON }
enum | eis_keymap_type { EIS_KEYMAP_TYPE_XKB }
enum | eis_event_type { EIS_EVENT_CLIENT_CONNECT , EIS_EVENT_CLIENT_DISCONNECT , EIS_EVENT_SEAT_BIND , EIS_EVENT_DEVICE_CLOSED , EIS_EVENT_PONG , EIS_EVENT_SYNC , EIS_EVENT_FRAME , EIS_EVENT_DEVICE_START_EMULATING , EIS_EVENT_DEVICE_STOP_EMULATING , EIS_EVENT_POINTER_MOTION , EIS_EVENT_POINTER_MOTION_ABSOLUTE , EIS_EVENT_BUTTON_BUTTON , EIS_EVENT_SCROLL_DELTA , EIS_EVENT_SCROLL_STOP , EIS_EVENT_SCROLL_CANCEL , EIS_EVENT_SCROLL_DISCRETE , EIS_EVENT_KEYBOARD_KEY , EIS_EVENT_TOUCH_DOWN , EIS_EVENT_TOUCH_UP , EIS_EVENT_TOUCH_MOTION }
| This enum is not exhaustive, future versions of this library may add new event types. More...

## Functions
const char * | eis_event_type_to_string (enum eis_event_type)
| This is a debugging helper to return a string of the name of the event type, or NULL if the event type is invalid.
struct eis * | eis_new (void *user_data)
| Create a new libeis context with a refcount of 1.
void | eis_clock_set_now_func (struct eis *, eis_clock_now_func func)
| Override the function that returns the current time eis_now().
struct eis * | eis_ref (struct eis *eis)
struct eis * | eis_unref (struct eis *eis)
void * | eis_get_user_data (struct eis *eis)
void | eis_set_user_data (struct eis *eis, void *user_data)
int | eis_setup_backend_fd (struct eis *ctx)
| Initialize the context that can take pre-configured socket file descriptors, see eis_backend_fd_add_client().
int | eis_backend_fd_add_client (struct eis *ctx)
| Add a new client to a context set up with eis_setup_backend_fd().
int | eis_setup_backend_socket (struct eis *ctx, const char *path)
| Initialize the context with a UNIX socket name.
int | eis_get_fd (struct eis *eis)
| libeis keeps a single file descriptor for all events.
void | eis_dispatch (struct eis *eis)
| Main event dispatching function.
uint64_t | eis_ping_get_id (struct eis_ping *ping)
| Return a unique, increasing id for this struct.
struct eis_ping * | eis_ping_ref (struct eis_ping *eis_ping)
| Increase the refcount of this struct by one.
struct eis_ping * | eis_ping_unref (struct eis_ping *eis_ping)
| Decrease the refcount of this struct by one.
void | eis_ping_set_user_data (struct eis_ping *eis_ping, void *user_data)
| Set a custom data pointer for this struct.
void * | eis_ping_get_user_data (struct eis_ping *eis_ping)
| Return the custom data pointer for this struct.
void | eis_ping (struct eis_ping *ping)
| Issue a roundtrip request to the client, resulting in an EIS_EVENT_PONG event when this roundtrip has been processed.
struct eis_event * | eis_get_event (struct eis *eis)
| Returns the next event in the internal event queue (or NULL) and removes it from the queue.
struct eis_event * | eis_peek_event (struct eis *eis)
| Returns the next event in the internal event queue (or NULL) without removing that event from the queue, i.e.
struct eis_event * | eis_event_unref (struct eis_event *event)
| Release resources associated with this event.
enum eis_event_type | eis_event_get_type (struct eis_event *event)
struct eis_client * | eis_event_get_client (struct eis_event *event)
struct eis_seat * | eis_event_get_seat (struct eis_event *event)
struct eis_ping * | eis_event_pong_get_ping (struct eis_event *event)
| Returns the associated eis_ping struct with this event.
bool | eis_event_seat_has_capability (struct eis_event *event, enum eis_device_capability cap)
| For an event of type EIS_EVENT_SEAT_BIND, return the capabilities requested by the client.
struct eis_device * | eis_event_get_device (struct eis_event *event)
| Return the device from this event.
uint64_t | eis_event_get_time (struct eis_event *event)
| Return the time for the event of type EIS_EVENT_FRAME in microseconds.
struct eis_ping * | eis_client_new_ping (struct eis_client *client)
| Create a new eis_ping object to trigger a round trip to the client.
struct eis_client * | eis_client_ref (struct eis_client *client)
struct eis_client * | eis_client_unref (struct eis_client *client)
void * | eis_client_get_user_data (struct eis_client *eis_client)
void | eis_client_set_user_data (struct eis_client *eis_client, void *user_data)
struct eis * | eis_client_get_context (struct eis_client *client)
bool | eis_client_is_sender (struct eis_client *client)
| Returns true if the client is a sender, false otherwise.
const char * | eis_client_get_name (struct eis_client *client)
| Return the name set by this client.
void | eis_client_connect (struct eis_client *client)
| Allow connection from the client.
void | eis_client_disconnect (struct eis_client *client)
| Disconnect this client.
struct eis_seat * | eis_client_new_seat (struct eis_client *client, const char *name)
| Create a new logical seat with a given name.
uint64_t | eis_now (struct eis *eis)

## Detailed Description

libeis is the server-side module.

This API should be used by processes that have control over input devices, e.g. Wayland compositors.

For an example EIS implementation see the `tools/` directory in the libei repository. At its core, an EIS implementation will

- create a context with eis_new()
- set up a backend with eis_setup_backend_fd() or eis_setup_backend_socket()
- register the eis_get_fd() with its own event loop
- call eis_dispatch() whenever the fd triggers
- call eis_get_event() and process incoming events

And for each client:

- accept new clients with eis_client_connect()
- create one or more seats for the client with eis_client_new_seat()
- wait for EIS_EVENT_SEAT_BIND and then
- create one or more devices with the bound capabilities, see eis_seat_new_device()

libei clients come in "sender" and "receiver" modes, depending on whether the client sends or receives events. A libeis context however may accept both sender and receiver clients, the EIS implementation works as corresponding receiver or sender for this client. It is up to the implementation to disconnect clients that it does not want to allow. See eis_client_is_sender() for details.

## Typedef Documentation

## ◆ eis_clock_now_func

typedef uint64_t(* eis_clock_now_func) (struct eis *eis)

Optional override function for eis_now().

By default eis_now() returns the current timestamp in CLOCK_MONOTONIC. This may be overridden by a caller to provide a different timestamp.

There is rarely a need to override this function. It exists for the libeis-internal test suite.

## Enumeration Type Documentation

## ◆ eis_device_capability

enum eis_device_capability

Enumerator
EIS_DEVICE_CAP_POINTER |
EIS_DEVICE_CAP_POINTER_ABSOLUTE |
EIS_DEVICE_CAP_KEYBOARD |
EIS_DEVICE_CAP_TOUCH |
EIS_DEVICE_CAP_SCROLL |
EIS_DEVICE_CAP_BUTTON |

## ◆ eis_device_type

enum eis_device_type

The device type determines what the device represents.

If the device type is EIS_DEVICE_TYPE_VIRTUAL, the device is a virtual device representing input as applied on the EIS implementation's screen. A relative virtual device generates input events in logical pixels, an absolute virtual device generates input events in logical pixels on one of the device's regions. Virtual devices do not have a size.

If the device type is EIS_DEVICE_TYPE_PHYSICAL, the device is a representation of a physical device as if connected to the EIS implementation's host computer. A relative physical device generates input events in mm, an absolute physical device generates input events in mm within the device's specified physical size. Physical devices do not have regions.

See also
  eis_device_get_width
  eis_device_get_height

Enumerator
EIS_DEVICE_TYPE_VIRTUAL |
EIS_DEVICE_TYPE_PHYSICAL |

## ◆ eis_event_type

enum eis_event_type

This enum is not exhaustive, future versions of this library may add new event types.

Unknown events must be released by the caller with eis_event_unref(), see eis_get_event().

Enumerator
EIS_EVENT_CLIENT_CONNECT | A client has connected. This is the first event from any new client. The server is expected to either call eis_client_connect() or eis_client_disconnect().
EIS_EVENT_CLIENT_DISCONNECT | The client has disconnected, any pending requests for this client should be discarded.
EIS_EVENT_SEAT_BIND | The client wants to bind or unbind a capability on this seat. Devices associated with this seat should be sent to the client or removed if the capability is no longer bound
EIS_EVENT_DEVICE_CLOSED | The client no longer listens to events from this device. The caller should released resources associated with this device.
EIS_EVENT_PONG | Returned in response to eis_ping().
EIS_EVENT_SYNC | This event represents a synchronization request (ping) from the client implementation. The corresponding reply (pong) will be sent when it is unref'd. It has no other API. The caller must ensure that any state changes triggered by messages received prior to this event have been resolved and communicated to the client prior to calling eis_event_unref(). E.g., if the preceding frame included a key event that caused shift to become logically depressed, the caller should ensure that the updated modifier state has been sent before calling unref.
EIS_EVENT_FRAME | "Hardware" frame event. This event must be sent by the client and notifies the server that the previous set of events belong to the same logical hardware event. These events are only generated on a receiving EIS context. This event is most commonly used to implement multitouch (multiple touches may update within the same hardware scanout cycle).
EIS_EVENT_DEVICE_START_EMULATING | The client is about to send events for a device. This event should be used by the server to clear the logical state of the emulated devices and/or provide UI to the user. These events are only generated on a receiving EIS context. Note that a client start multiple emulating sequences simultaneously, depending on the devices it received from the server. For example, in a synergy-like situation, the client may start emulating of pointer and keyboard once the remote device logically entered the screen. The server can cancel an ongoing emulating by suspending the device, see eis_device_suspend().
EIS_EVENT_DEVICE_STOP_EMULATING | Stop emulating events on this device, see EIS_EVENT_DEVICE_START_EMULATING.
EIS_EVENT_POINTER_MOTION | A relative motion event with delta coordinates in logical pixels or mm, depending on the device type.
EIS_EVENT_POINTER_MOTION_ABSOLUTE | An absolute motion event with absolute position within the device's regions or size, depending on the device type.
EIS_EVENT_BUTTON_BUTTON | A button press or release event.
EIS_EVENT_SCROLL_DELTA | A vertical and/or horizontal scroll event with logical-pixels or mm precision, depending on the device type.
EIS_EVENT_SCROLL_STOP | An ongoing scroll sequence stopped.
EIS_EVENT_SCROLL_CANCEL | An ongoing scroll sequence was cancelled.
EIS_EVENT_SCROLL_DISCRETE | A vertical and/or horizontal scroll event with a discrete range in logical scroll steps, like a scroll wheel.
EIS_EVENT_KEYBOARD_KEY | A key press or release event.
EIS_EVENT_TOUCH_DOWN | Event for a single touch set down on the device's logical surface. A touch sequence is always down/up with an optional motion event in between. On multitouch capable devices, several touchs eqeuences may be active at any time.
EIS_EVENT_TOUCH_UP | Event for a single touch released from the device's logical surface.
EIS_EVENT_TOUCH_MOTION | Event for a single currently-down touch changing position (or other properties).

## ◆ eis_keymap_type

enum eis_keymap_type

Enumerator
EIS_KEYMAP_TYPE_XKB |

## Function Documentation

## ◆ eis_backend_fd_add_client()

int eis_backend_fd_add_client | ( | struct eis * | ctx | ) |

Add a new client to a context set up with eis_setup_backend_fd().

Returns a file descriptor to be passed to ei_setup_backend_fd(), or a negative errno on failure.

## ◆ eis_client_connect()

void eis_client_connect | ( | struct eis_client * | client | ) |

Allow connection from the client.

This can only be done once, further calls to this functions are ignored.

When receiving an event of type EIS_EVENT_CLIENT_CONNECT, the server should connect client as soon as possible to allow communication with the server. If the client is not authorized to talk to the server, call eis_client_disconnect().

## ◆ eis_client_disconnect()

void eis_client_disconnect | ( | struct eis_client * | client | ) |

Disconnect this client.

Once disconnected the client may no longer talk to this context, all resources associated with this client should be released.

It is not necessary to call this function when an EIS_EVENT_CLIENT_DISCONNECT event is received.

## ◆ eis_client_get_context()

struct eis * eis_client_get_context | ( | struct eis_client * | client | ) |

## ◆ eis_client_get_name()

const char * eis_client_get_name | ( | struct eis_client * | client | ) |

Return the name set by this client.

The server is under no obligation to use this name.

## ◆ eis_client_get_user_data()

void * eis_client_get_user_data | ( | struct eis_client * | eis_client | ) |

## ◆ eis_client_is_sender()

bool eis_client_is_sender | ( | struct eis_client * | client | ) |

Returns true if the client is a sender, false otherwise.

A sender client may send events to the EIS implementation, a receiver client expects to receive events from the EIS implementation.

## ◆ eis_client_new_ping()

struct eis_ping * eis_client_new_ping | ( | struct eis_client * | client | ) |

Create a new eis_ping object to trigger a round trip to the client.

See eis_ping() for details.

The returned eis_ping is refcounted, use eis_ping_unref() to drop the reference.

Since
  1.4

## ◆ eis_client_new_seat()

struct eis_seat * eis_client_new_seat | ( | struct eis_client * | client,
|  | const char * | name )

Create a new logical seat with a given name.

Devices available to a client belong to a bound seat, or in other words: a client cannot receive events from a device until it binds to a seat and receives all devices from that seat.

This seat is not immediately active, use eis_seat_add() to bind this seat on the client and notify the client of it's availability.

The returned seat is refcounted, use eis_seat_unref() to drop the reference.

## ◆ eis_client_ref()

struct eis_client * eis_client_ref | ( | struct eis_client * | client | ) |

## ◆ eis_client_set_user_data()

void eis_client_set_user_data | ( | struct eis_client * | eis_client,
|  | void * | user_data )

## ◆ eis_client_unref()

struct eis_client * eis_client_unref | ( | struct eis_client * | client | ) |

## ◆ eis_clock_set_now_func()

void eis_clock_set_now_func | ( | struct eis * | ,
|  | eis_clock_now_func | func )

Override the function that returns the current time eis_now().

There is rarely a need to override this function. It exists for the libeis-internal test suite.

## ◆ eis_dispatch()

void eis_dispatch | ( | struct eis * | eis | ) |

Main event dispatching function.

Reads events of the file descriptors and processes them internally. Use eis_get_event() to retrieve the events.

Dispatching does not necessarily queue events. This function should be called immediately once data is available on the file descriptor returned by eis_get_fd().

## ◆ eis_event_get_client()

struct eis_client * eis_event_get_client | ( | struct eis_event * | event | ) |

## ◆ eis_event_get_device()

struct eis_device * eis_event_get_device | ( | struct eis_event * | event | ) |

Return the device from this event.

This does not increase the refcount of the device. Use eis_device_ref() to keep a reference beyond the immediate scope.

## ◆ eis_event_get_seat()

struct eis_seat * eis_event_get_seat | ( | struct eis_event * | event | ) |

## ◆ eis_event_get_time()

uint64_t eis_event_get_time | ( | struct eis_event * | event | ) |

Return the time for the event of type EIS_EVENT_FRAME in microseconds.

Note
  : Only events of type EIS_EVENT_FRAME carry a timestamp. For convenience, the timestamp for other device events is retrofitted by this library.

Returns
  the event time in microseconds

## ◆ eis_event_get_type()

enum eis_event_type eis_event_get_type | ( | struct eis_event * | event | ) |

## ◆ eis_event_pong_get_ping()

struct eis_ping * eis_event_pong_get_ping | ( | struct eis_event * | event | ) |

Returns the associated eis_ping struct with this event.

For events of type other than EIS_EVENT_PONG this function returns NULL.

This does not increase the refcount of the eis_pong. Use eis_pong_ref() to ekeep a reference beyond the immediate scope.

## ◆ eis_event_seat_has_capability()

bool eis_event_seat_has_capability | ( | struct eis_event * | event,
|  | enum eis_device_capability | cap )

For an event of type EIS_EVENT_SEAT_BIND, return the capabilities requested by the client.

This is the set of all capabilities bound by the client as of this event, not just the changed ones.

## ◆ eis_event_type_to_string()

const char * eis_event_type_to_string | ( | enum | eis_event_type | ) |

This is a debugging helper to return a string of the name of the event type, or NULL if the event type is invalid.

For example, for EIS_EVENT_TOUCH_UP this function returns the string "EIS_EVENT_TOUCH_UP".

## ◆ eis_event_unref()

struct eis_event * eis_event_unref | ( | struct eis_event * | event | ) |

Release resources associated with this event.

This function always returns NULL.

The caller cannot increase the refcount of an event. Events should be considered transient data and not be held longer than required. eis_event_unref() is provided for consistency (as opposed to, say, eis_event_free()).

## ◆ eis_get_event()

struct eis_event * eis_get_event | ( | struct eis * | eis | ) |

Returns the next event in the internal event queue (or NULL) and removes it from the queue.

The returned event is refcounted, use eis_event_unref() to drop the reference even if the event type is unknown to the caller.

You must not call this function while holding a reference to an event returned by eis_peek_event().

## ◆ eis_get_fd()

int eis_get_fd | ( | struct eis * | eis | ) |

libeis keeps a single file descriptor for all events.

This fd should be monitored for events by the caller's mainloop, e.g. using select(). When events are available on this fd, call eis_dispatch() immediately to process.

## ◆ eis_get_user_data()

void * eis_get_user_data | ( | struct eis * | eis | ) |

## ◆ eis_new()

struct eis * eis_new | ( | void * | user_data | ) |

Create a new libeis context with a refcount of 1.

## ◆ eis_now()

uint64_t eis_now | ( | struct eis * | eis | ) |

Returns
  a timestamp for the current time to pass into eis_device_frame().

By default, the returned timestamp is CLOCK_MONOTONIC for compatibility with evdev and libinput. This can be overridden with eis_clock_set_now_func().

## ◆ eis_peek_event()

struct eis_event * eis_peek_event | ( | struct eis * | eis | ) |

Returns the next event in the internal event queue (or NULL) without removing that event from the queue, i.e.

the next call to eis_get_event() will return that same event.

This call is useful for checking whether there is an event and/or what type of event it is.

Repeated calls to eis_peek_event() return the same event.

The returned event is refcounted, use eis_event_unref() to drop the reference.

A caller must not call eis_get_event() while holding a ref to an event returned by eis_peek_event().

## ◆ eis_ping()

void eis_ping | ( | struct eis_ping * | ping | ) |

Issue a roundtrip request to the client, resulting in an EIS_EVENT_PONG event when this roundtrip has been processed.

Events are processed in-order by the client implementation so this function can be used as synchronization point between events.

If the client is disconnected before the roundtrip is complete, libeis will emulate a EIS_EVENT_PONG event before EIS_EVENT_DISCONNECT.

Since
  1.4

## ◆ eis_ping_get_id()

uint64_t eis_ping_get_id | ( | struct eis_ping * | ping | ) |

Return a unique, increasing id for this struct.

This ID is assigned at struct creation and constant for the lifetime of the struct. The ID does not exist at the protocol level.

This is a convenience API to make it easier to put this struct into e.g. a hashtable without having to use the pointer value itself.

The ID increases by an unspecified amount.

Since
  1.4

## ◆ eis_ping_get_user_data()

void * eis_ping_get_user_data | ( | struct eis_ping * | eis_ping | ) |

Return the custom data pointer for this struct.

libeis will not look at or modify the pointer. Use eis_ping_set_user_data() to change the user data.

Since
  1.4

## ◆ eis_ping_ref()

struct eis_ping * eis_ping_ref | ( | struct eis_ping * | eis_ping | ) |

Increase the refcount of this struct by one.

Use eis_ping_unref() to decrease the refcount.

Returns
  the argument passed into the function

Since
  1.4

## ◆ eis_ping_set_user_data()

void eis_ping_set_user_data | ( | struct eis_ping * | eis_ping,
|  | void * | user_data )

Set a custom data pointer for this struct.

libeis will not look at or modify the pointer. Use eis_ping_get_user_data() to retrieve a previously set user data.

Since
  1.4

## ◆ eis_ping_unref()

struct eis_ping * eis_ping_unref | ( | struct eis_ping * | eis_ping | ) |

Decrease the refcount of this struct by one.

When the refcount reaches zero, the context disconnects from the server and all allocated resources are released.

Returns
  always NULL

Since
  1.4

## ◆ eis_ref()

struct eis * eis_ref | ( | struct eis * | eis | ) |

## ◆ eis_set_user_data()

void eis_set_user_data | ( | struct eis * | eis,
|  | void * | user_data )

## ◆ eis_setup_backend_fd()

int eis_setup_backend_fd | ( | struct eis * | ctx | ) |

Initialize the context that can take pre-configured socket file descriptors, see eis_backend_fd_add_client().

This is the preferred backend to use for EIS implementations as it keeps the file descriptors private for each client and is not subject to race conditions or unauthorized clients attempting to connect.

## ◆ eis_setup_backend_socket()

int eis_setup_backend_socket | ( | struct eis * | ctx,
|  | const char * | path )

Initialize the context with a UNIX socket name.

If the path does not start with / it is relative to $XDG_RUNTIME_DIR.

The socket will be accessible by any client with permissions to do so and it is up to the EIS implementation to authenticate clients. In almost all cases, the EIS implementation should use eis_setup_backend_fd() instead. This backend is primarily useful for testing and debugging.

## ◆ eis_unref()

struct eis * eis_unref | ( | struct eis * | eis | ) |