Commit graph

40 commits

Author SHA1 Message Date
Peter Hutterer
2c85e2bd9c Revert "Add support for swipe, pinch and hold gestures"
This reverts commit ff9e8905a0.

Part-of: <https://gitlab.freedesktop.org/libinput/libei/-/merge_requests/386>
2026-04-23 14:19:29 +10:00
Peter Hutterer
ff9e8905a0 Add support for swipe, pinch and hold gestures
On the protocol level these are implemented as three separate interfaces
for swipe, pinch and hold, each interface has the begin/update/end
sequence and effectively matches the wayland pointer-gestures protocol.

Notably, only one of each gesture may be active at any time though the
protocol allows for separate gestures to be active (i.e. swipe while
pinching).

On the library side the gestures match the touch interface so the
sequence for a sender is:

  swipe = ei_device_new_swipe(device, finger_count);
  ei_swipe_begin(swipe);
  ei_swipe_update(swipe, dx, dy);
  ei_swipe_end(swipe);

with the corresponding APIs for pinch and hold.

On the receiver side the event types are separated for BEGIN/UPDATE/END
for all three gestures and thus match the libinput interface.

The notable difference however: there is only one CAP_GESTURES (similar
to libinput) and it is set if any gesture is available on the caller.
Creating a swipe gesture if the remote end does not support it will
return NULL though.

Co-Authored-by: Claude Code <noreply@anthropic.com>
Part-of: <https://gitlab.freedesktop.org/libinput/libei/-/merge_requests/309>
2026-04-21 11:12:29 +10:00
Peter Hutterer
1f9be0fd0a Add a new text interface for sending keysyms and utf8 text
The text capability allows for two types of events on that interface:
- XKB keysym events, e.g. XK_ssharp (0x00df) with a press/release state
- UTF8 strings

Keysym events are useful for scenarious where the hardware keycode is
unsuitable due to potentially different key mappings on the client and
server side and/or the client just not wanting to worry about those
mappings. For example a client may want to send Ctrl+C instead of
what effectively is now keycodes for what may or may not be a C key.

UTF8 strings take this a step further and provide a full string (with
implementation-defined size limits to avoid OOM). Unlike e.g. the
wayland text input protocols the assumption is here that the
interaction required to generate that string has already been
performed before the final string is sent over the wire.

Closes #73

Part-of: <https://gitlab.freedesktop.org/libinput/libei/-/merge_requests/355>
2026-04-02 05:09:37 +00:00
Peter Hutterer
a6028a7b87 Format the code with clang-format
clang-format taken from libinput, except for
  ColumnLimit: 100
and some macro definitions (which don't all have an effect anyway...)

It's not perfect but good enough and at least consistent.

Part-of: <https://gitlab.freedesktop.org/libinput/libei/-/merge_requests/383>
2026-03-12 13:55:19 +10:00
Peter Hutterer
5f9e181073 proto: add support for requesting devices
Add support for a client to request the creation of a new device
from the EIS implementation. This is necessary in situations where the
devices created by the EIS implementation are not (or no longer)
suitable for the client to function correctly.

The primary use-case of this is the upcoming tablet tool support where a
client may need to create multiple tablet tools in response to a new
physical tool brought into proximity locally.

Other use-cases include a client closing a device but requiring that
device (or one with similar capabilities) later.

The implementation in libei is straightforward
- on the client side we have a new function to request the new device:
  ei_seat_request_device_with_capabilities()
- on the server side we have a new event EIS_EVENT_SEAT_DEVICE_REQUESTED
  that can make use of the existing eis_event_seat_has_capability() API

Part-of: <https://gitlab.freedesktop.org/libinput/libei/-/merge_requests/345>
2026-01-06 04:50:46 +00:00
Peter Hutterer
bf03c56300 Add a few missing va_end
Found by gcc -fanalyze
2024-09-11 12:25:41 +10:00
Peter Hutterer
b14405d3cd ei: fix a whitespace error 2023-06-07 23:08:16 +00:00
Peter Hutterer
c99f4ffa2c libei: check incoming objects' version for correctness
If the server sends a protocol version higher than we support, fail.
2023-05-26 19:16:15 +10:00
Peter Hutterer
3e47f544c2 ei: drop ei_seat_bind_capability() and the unbind equivalent
This function is almost always wrong, very few clients will want to bind
to a single capability. Having this function means clients will use it to
bind caps one-by-one, causing the EIS implementation to create (an later
destroy) devices with capabilities that are about to be bound again anyway.
Better to have an API that encourages clients to bind all at once.

EIS implementation could avoid this by using a pingpong roundtrip in
response to a bind call, but removing this API is likely going to have
the same utility.
2023-05-10 12:25:40 +10:00
Peter Hutterer
da37da1308 ei: change the API to match the protocol interfaces closer
Now that the protocol interfaces are more fine-grained, let's match this
with the C API too.

This is just a rename of things so that in general
ei_pointer_*foo now becomes ei_foo*.

A few notable renames for better readability here:
- ei_device_scroll_delta (because scroll_scroll is awkward)
- ei_event_scroll_get_dx/dy and
  ei_event_scroll_get_discrete_dx/dy to indicate the delta-ness

Beyond that, clients must ensure to check/bind to the new
EI_DEVICE_CAP_BUTTON and EI_DEVICE_CAP_SCROLL capabilities to be able
to send button or scroll events.

Note that this API now allows for an EIS implementation to send a device
that only has a button or a scroll cap. Or a pointer cap without
buttons, etc. It's up to the clients how to handle such devices
(probably: ignore them).
2023-05-05 14:02:33 +10:00
Peter Hutterer
a902d5dbd8 protocol: replace the capabilities enum with an interface list
Previously we had ei_seat.capabilities and ei_device.capabilities,
both referring to the same enum. The seat caps were used to bind,
the device caps were used to announce capabilities.

The device caps were already mostly superfluous as the information
they carried was implicitly available by the set of interfaces
the device announced - if the device has a keyboard interface
it must also have the keyboard capability.

So let's drop the separate enum and make the capabilities
the set of supported interfaces. In the device we can drop the
event directly and just send the interface list. In the seat
we have a capability event that sends each *possible* interface
with a custom-assigned mask. The client can then use that mask
to bind to the capability as before.

For example:
   <- ei_seat.capability(0x1, "ei_pointer")
   <- ei_seat.capability(0x4, "ei_keyboard")
   <- ei_seat.capability(0x8, "ei_touchscreen")
   <- ei_seat.done()
   -> ei_seat.bind(0x4 | 0x8)  # bind to keyboard and touchscreen
   <- ei_seat.device()
   -> ei_device.interface("ei_keyboard")
   -> ei_device.interface("ei_touchscreen")
   <- ei_device.done()

In the generated bindings we simply use the interface index
to generate the masks, but the protocol at least states that
the mask may not be constant.

Because the button/scroll interfaces are not exposed by the C API, some
of the handling is a bit awkward since we need to use both depending
whether we have pointer/pointer_absolute selected.

Fixes #28

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2023-05-02 05:53:25 +00:00
Peter Hutterer
9c5c3c890f ei: de-duplicate ei_seat_unbind_capability
ei_seat_unbind_capabilities does the same, so let's use that.
2023-04-14 10:52:39 +10:00
Peter Hutterer
cf74cfeb1e ei: fix ei_seat_unbind_capabilities
Simplify the code a little but more importantly: if we get down to zero
capabilities close the devices - just like we do in
ei_seat_unbind_capability.
2023-04-14 10:51:40 +10:00
Peter Hutterer
1a64b4963d Check incoming ids for validity
In libei we just check the range is correct.
In libeis we also check that the client is monotonically increasing the
id.
2023-03-03 11:27:01 +10:00
Peter Hutterer
ba51f434a6 proto: switch object ids to 64 bits 2023-03-03 11:27:01 +10:00
Peter Hutterer
b309798bf1 Switch object ids to use the object_id_t typedef 2023-03-03 11:27:01 +10:00
Peter Hutterer
8ea6b81f40 Change the ei_device_capability values to match the protocol
In the protocol this is a bitmask, let's make it the same in the
interface to avoid confusion in the implementation.
2023-03-03 11:27:01 +10:00
Peter Hutterer
38dc5dc72f proto: shift the capabilities down by one
These were previously (1 << cap) for convenience but that results in the
capability mask on the wire starting at 2 - which is a bit awkward.

Lets shift them down by one so we start the mask at 1.
2023-03-03 11:27:01 +10:00
Peter Hutterer
e5b37dedc8 protocol: add serial numbers to the various destroy events
This should allow EIS to track whether events that were sent before or
after a destruction of a resource.
2023-03-03 11:27:01 +10:00
Peter Hutterer
cc7a8cb95e ei: make more ei_queue* functions semi-public for consistency
And drop the ei_add_seat() indirection.
2023-03-03 11:27:01 +10:00
Peter Hutterer
1a21c4854b ei: better protocol checking for invalid messages 2023-03-03 11:22:09 +10:00
Peter Hutterer
e67a0a7777 brei: add the brei_result object and bubble it up as error case
Add a new simple object "brei_result" that maps to the protocol-type
reason + explanation. That object is now returned instead of the errno,
giving us better debugging options.

This changes the dispatcher functions from returning an int to returning
a brei_result instead (default NULL for success). A helper function for
converting a neg errno to a result is provided for convenience for now,
eventually all these paths should deal with things correctly.
2023-03-03 11:22:08 +10:00
Peter Hutterer
df673b140d ei: remove now-unused function 2023-03-03 11:21:26 +10:00
Peter Hutterer
fadc1853c9 protocol: add the ei_device interface
Sitting nested below the ei_seat, the client gets a notification for a
device through the ei_seat.device event.
2023-03-03 11:21:26 +10:00
Peter Hutterer
2a8661f7ad protocol: move the seat bind to the seat object
Needs documentation but we can do this when we're done with everything.
2023-03-03 11:21:26 +10:00
Peter Hutterer
aaf72f9263 protocol: add a seat interface
Incomplete, only supports the initial seat setup but binding to a seat
is still outside this interface.
2023-03-03 11:20:42 +10:00
Peter Hutterer
9d85b1289d Change to allow dynamic binding of capabilities
Previously, a client could only bind to a capability immediately after
SEAT_ADDED and with a rather awkward API to confirm the capabilities.

Change this to allow for dynamic binding of capabilities, i.e. a client
calls ei_bind_capability() or ei_unbind_capability() whenever it feels
like, causing the respective devices of this capabilty to be added or
removed.

This allows for clients that are temporarily disinterested in a
capability but may require said capability later.

The default function takes one capability, a helper for enable/disable
multiple capabilities in one go is provided as well. On the protocol,
only the "bind" request exists which always represents the currently
wanted set of capabilities.

Note that the helper functions for multiple capabilities require NULL
(not zero) as sentinel, thanks to gcc.
2022-04-04 05:24:16 +00:00
Peter Hutterer
541dcb415d ei: require the client to confirm capabilities rather than drop them
Our API requires a client to know which capability to pass into the
drop_capabilities function. This doesn't work for capabilities newer
than the client's version so they do not get disabled. The client will
thus receive devices it didn't ask for and doesn't know how to handle.

Let's invert the requirement and require the caller to confirm the
capabilities it wants - all others are dropped.

This is an API break but also requires updates of all clients, the
previous simple case of just calling ei_seat_bind() will now result in
zero capabilities.
2022-03-07 11:02:35 +10:00
Peter Hutterer
b6f477fb96 util-object: split macro to generate unref into one two
One macro that also defines the cleanup function, one macro that only
defines the unref. This is required for any place where we want to
use cleanup from multiple source files - like the test suite.
2022-03-03 05:41:15 +00:00
Peter Hutterer
46681e2855 Add SPDX identifiers to all source files
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2022-03-03 00:27:36 +00:00
Peter Hutterer
ceaabd0fd5 ei: add missing ei_seat_has_capability implementation
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2021-08-20 13:32:13 +10:00
Peter Hutterer
cb4dcaa078 ei: two more bug log messages
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2021-08-09 18:48:11 +10:00
Peter Hutterer
926644e669 util: remove the need for a tmp argument in list_for_each_safe
With a bit of trickery, we can declare the tmp variable inside the for
loop.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2021-07-22 13:13:03 +10:00
Peter Hutterer
3e66c87e81 ei: make the device refcounting a bit easier to follow
Once a device is removed, it is moved to the seat's devices_removed
list and the seat's ref is dropped - meaning the seat no longer keeps
the device alive. Once the caller's refcounts drop, the device can be
destroyed.

The device still keeps the seat alive though through a ref.

Signed-off-by:	Peter Hutterer <peter.hutterer@who-t.net>
2021-07-21 11:02:54 +10:00
Peter Hutterer
2bb846696f Change to use server-created devices
This changes the protocol so that it is the EIS implementation that
creates devices within a seat.

A client now "binds" to a seat and the EIS implementation creates
devices matching the requested capabilities. A client can close a device
if it no longer wants those but otherwise everything (including pointer
ranges) is handled by the server.

This is one giant patch because changes at the protocol level cannot
easily be broken out into smaller patches. Some FIXMEs are left which
will be handled in follow-up patches, e.g. the keymap handling is
basically broken right now.

Fixes #7

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2021-07-21 11:02:54 +10:00
Peter Hutterer
57fc23c67d libei: require ei_device_remove() for a never-added device
This simplifies the handling of devices that were never added a bit, including
handling the refs between seat and device. And for legitimate use-cases
there's no reason why a caller would create a device but never add it.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2020-10-29 12:23:35 +10:00
Peter Hutterer
eef9c51df3 libei: fix the device/seat ref handling once again
Previously we didn't always clean up properly, especially where unexpected
removals happened. So the new approach is:
- the device always has a ref to the seat, we must not remove the seat until
  even not-yet-added devices are released
- the seat has a ref to the device *after* it was added. this is a circular
  ref so we need to make sure the device is manually removed from the seat
  so we can actually reach a refcount 1

This is made slightly more complicated by us calling ei_disconnect() whenever
we fail to write on the fd. The result is re-entrant functions that we need to
protect against inadvertent changes. The best option here is probably to mark
the context as degraded and clean up once we finished whatever we were really
doing - that's a larger rework though.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2020-10-29 11:28:29 +10:00
Peter Hutterer
683ff5cca0 Fix double device removal
Removing a seat could cause two device remove events to happen. Fix this by
splitting the removal up into two bits: removed by server and removed by
client. Only once both bits are set, remove the device.

This needs to happen in libei and libeis.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2020-10-27 11:35:06 +10:00
Peter Hutterer
ab386f3cdb util: add an _unref_ cleanup + declaration function
To cut down on the boilerplate, an unref-able struct variable can now be
declared as
   _unref_(type) *name = NULL;
which is the equivalent of
   _cleanup_(type_unrefp) struct type *name = NULL;

Let's see how that style ends up reading.

This means we can get rid of the custom _cleanup_foo_ functions everywhere, no
need for all the extra #defines etc. A somewhat special case is systemd which
defines the various unrefp functions for us in the headers, so we can use them
directly.

OBJECT_IMPLEMENT_UNREF now also creates the unrefp function for this object -
this of course conflicts where DECLARE_UNREF_CLEANUP_FUNC is in scope. Not a
problem so far, let's see how we go.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2020-10-21 11:17:16 +10:00
Peter Hutterer
93b96e42ad Add an EIS-controlled seat to the hierarchy
After CONNECT, the EIS implementation needs to add one or more seats. The
libei client can only create devices within those seats. This mirrors the
wayland hierarchy as well as the X.Org one.

The seat has a set of allowed capabilities, so the client knows ahead of time
when it may not be possible to create a specific device.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2020-10-21 10:47:47 +10:00