In the protocol it's a new request/event that is sent instead of the
touch up event.
In the library this is implemented as ei_touch_cancel() which
transparently sends cancel() or up depending on the EIS implementation
support. This is mirrored for the EIS implementation.
Where touch cancel is received as an event it is presented
as EI_EVENT_TOUCH_UP with an ei_event_touch_is_cancel() flag to
check if it was a cancel. This is required for backwards compatbility,
we cannot replace the TOUCH_UP event with a TOUCH_CANCEL event without
breaking existing callers. To add a new event type we would need clients
announcing support for those event types but that's an effort that's
better postponed until we have a stronger need for it (see #68).
Closes#60
Part-of: <https://gitlab.freedesktop.org/libinput/libei/-/merge_requests/308>
Previously the only way to disconnect from the EIS implementation was
to call ei_unref() and release all resources. This makes it more
difficult for shared cleanup code - clients already have code in place
to deal with DEVICE_REMOVED, SEAT_REMOVED, etc. but that code has to
be triggered manually before ei_unref() is called.
OTOH where the server disconnects us, libei already unwound the state
so we would artificially generate these removed events, allowing the
client to clean up.
Make life easier for client by allowing them to ei_disconnect() and
get the benefits of our state unwinding. ei_disconnect() was already
used internally to disconnect on any error so this merely makes this
function public.
Closes#67
Part-of: <https://gitlab.freedesktop.org/libinput/libei/-/merge_requests/311>
Because of the asynchronous protocol, we may get this interaction
server sends A->destroyed()
client sends A->foo()
client receives A->destroyed()
server receives A->foo()
server sends invalid_object_id(A)
client receives invalid_object_id(A)
Previously we dropped the object after destroyed() and were thus
guaranteed to warn about the invalid object id for that same object
later.
Fix this by keeping a cache of defunct object IDs that we know about and
ignoring errors for recently dropped objects.
Every 20 ei_dispatch() calls we drop any defunct objects that were
unregistered more than 5 seconds ago.
Fixes#49
Build a separate libei-eierpecken.so that is identical to libei.so but
allows adding an offset to ei_now() for the eierpecken tests. That
offset is added to the return value of ei_now(), removing the real-time
dependency of the tests.
In other words, we can call peck_ei_add_time_offset(peck, s2us(5)) to
add 5 seconds to the time and continue the test as if that time has
elapsed.
If we get disconnected there's no point sending anything anymore, the
server may have already closed the connection.
Otherwise this produces a confusing warning in the log:
18:37:31 | INFO | Disconnected by EIS
... | WARN | failed to send message: Broken pipe
See https://gitlab.freedesktop.org/libinput/libei/-/merge_requests/262#note_2132619
Any error will cause ei_disconnect() which in turn unwinds our context.
Each object removed will cause an ei_send_message() to notify the server
but that will only cause error messages - our socket is already gone.
Fix this by removing the source and checking if the fd is still valid
before we write to it.
Fixes#47
This allows a caller to match up a region with other data, e.g. in the
remote desktop case the same mapping_id can be assigned to the pipewire
stream that represents that output.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This makes the debug logs easier to read - previously we'd get an error
and disconnect. That causes unwinding of the state internally
(including lots of debug messages) and then eventually the actual error
that caused the disconnect.
Reshuffle this, so we see the "Connection error" first before all the
unwiding of the state, making it easier to spot what caused the actual
error.
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).
Split the ei_pointer protocol interface into ei_pointer,
ei_pointer_absolute, ei_scroll and ei_button.
This gets rid of the slightly awkward pointer vs pointer absolute
handling. Those were two different capabilities but tied to the same
interface.
Plus it paves the way for devices that are keyboards with scroll
buttons, etc.
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.
Leave the ei_callback as-is and instead add ei_pingpong for the same
thing initiated by the server. The interface is otherwise identical but
for the direction it is supposed to flow.
This reduces the possibility of a client accidentally sending a
request when it is supposed to handle an event or vice versa.
This is effectively the same as connection.sync, but goes the other way.
This adds the ei_callback.done request.
In libeis this is (currently) enforced immediately after sending the
connection object. Not required there and makes the code a bit messier
but this way we can ensure that any client library handles that part of
the code.
This event is to notify the client that an object used in a request was
unknown. This allows the client to work around race conditions like
binding to a seat that was removed.
This is currently the server-side only which is probably enough for now.
The only client-side created objects we have are the callbacks.
This changes the initial connection negotiation to have the
ei_connection_setup as the pre-existing object id 0. Once the client has
sent all the data to set up the connection, the EIS implementation
replies with a new object ID that is the ei_connection protocol object,
i.e. the main object.
This allows for version negotiation of our main protocol object.
This allows us to have a device support multiple interfaces and evolve
those interfaces individually, e.g. add things to the keyboard interface
without having to bump the touchscreen interface.
Note that due to a name clash with the existing struct ei_touch public
API the protocol interface is named touchscreen.
The idea here is that the client announces the interfaces it can support
and their version (including the core ei_connection). The server can
then send the various bits based on those versions, where applicable.
This replaces the connect/connect_done and version/get_version requests.
Immediately after connecting, the server sends an ei_protocol_setup
event to the client with the ID of the object and the server's highest
supported version number (of this object).
This is a one-shot object that the client can use to configure its name
and whether it is a sender or receiver context. Once .done is sent, the
object is discarded.
The server version is sent along to the client to allow for requests to
be added to this object in the future.
As a fixme left: the client now assumes to be connected as soon as the
.done request is sent and the following sync event is received. The
EIS implementation will not have actually eis_client_connect()ed the
client yet, but it's good enough for now.
Arguably, the CONNECTED event is superfluous anyway since *any* event
other than DISCONNECTED indicates connected status. CONNECTED is a
leftover from when the client created devices and needed to know if it's
worth doing so.
Directly copied from wayland. Note that while the wayland protocol
specifies the data is the last event serial in our case here it's just
0 since we don't have any event serials (yet).
The sync request is currently triggered after connection, merely to
ensure it works, it's not actually needed.
In the protocol this is a simple rename but in the implementation we can
now separate the protocol object out from the ei/ei-client context
itself by having the ei_connection objects.
This protocol is wayland-like though it uses a slightly different
message format. The XML file uses the same structure, except for the
"fixed" type which is "float" here.
The scanner uses a jinja template to generate source and header files
for ei and eis which are now used instead of the protobuf-generated
objects. Note that the scanner is a minimal working version, some
features like enum value checks are not yet implemented.
Unlike wayland we do not need to generate the libwayland-like library,
we only need the wire protocol parser - some shortcuts can thus be taken.
To keep the changes simple, the protocol currently is a flat protocol
with only one interface and all messages copied over from the previous
ei.proto file. In future commits, this will be moved to the respective
interfaces instead.
With the planned switch to a protocol supporting multiple interfaces
(a la wayland), a single version number is no longer useful. Remove this
API, we can add something more specific later if we need to.