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>
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>
Even if the client is no longer emulating (and we're not queuing an
event) our local touch must be ended. Otherwise our touch will live on
forever, despite the client thinking it has ended properly.
This can't be triggered with libei because we can't send touch events
while not emulating and the only way to get into this state is pausing
the device - which already resets the state. But let's add a test case
anyway, in the hope that one day it picks up a bug.
Part-of: <https://gitlab.freedesktop.org/libinput/libei/-/merge_requests/368>
A client sending duplicate touch IDs will be disconnected but
motion or end events for touches that no longer exist will be silently
ignored.
The tracking state uses a uint64_t to store currently valid touch ids -
since the whole range of touch ids are uint32_t (including zero) this is
the simple way of using an out-of-range marker value (UINT64_MAX)
Part-of: <https://gitlab.freedesktop.org/libinput/libei/-/merge_requests/368>
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>
Reproducible with something that produces a frame event:
// queues e.g. pointer motion + frame
peck_eis_dispatch_until_stable()
with_server(peck) {
// process the motion only
}
peck_eis_dispatch_until_stable()
The second peck_eis_dispatch_until_stable() triggers an assertion
because we still have the unhandled frame event pending but need_frame
was reset to false.
Keep this as a field in peck so it remembers across invocations.
Part-of: <https://gitlab.freedesktop.org/libinput/libei/-/merge_requests/369>
The protocol currently supports a ei_device.done event to notify
the ei client that the initial description of the device is complete.
For some future use-cases the client may need to futher negotiate
properties of the device. For example for tablet tools the client may
narrow down capabilities of the tool.
The sequence with the new request is thus e.g.
-> ei_seat.device
-> ei_device.name
-> ei_device.interface
-> ei_device.interface
-> ei_device.done
<- ei_device.ready
-> ei_device.resumed
In libei the request is sent automatically on unref of
the DEVICE_ADDED event. This makes clients immediately compatible
and for the typical (future) use-case of device configuration. Said
configuration will likely be handled in response to the DEVICE_ADDED
event anyway.
In libeis, a new EIS_EVENT_DEVICE_READY event that is sent when the client
sends that same event on the protocol, informing the EIS implementation
that this device is ready. For clients that do not support that version
the event is emulated immediately after sending ei_device.done.
This requires a flag bit to be long-term maintainable. The typical
EIS implementation currently calls eis_device_add() immediately
followed by eis_device_resume(). This doesn't leave any room to
wait for the client's ei_device.ready request.
One backwards-compatible solution could be to buffer the
eis_device_resume() until the ei_device.ready has been received but this
is fraught with hairy corner cases, e.g. if the client is a receiver
context we would also have to buffer all events immediately sent to the
client.
So instead, we have a flag in the context and if set by the caller, we
change the internal behavior to match ei_device interface version 3.
Part-of: <https://gitlab.freedesktop.org/libinput/libei/-/merge_requests/346>
The peck_disable_eis_behavior and peck_disable_ei_behavior functions
would incorectly *enable* behaviors when called with certain arguments
that cover multiple behaviors (e.g. PECK_EIS_BEHAVIOR_ACCEPT_ALL).
This commit modifies the logic to instead disable the behaviors.
Part-of: <https://gitlab.freedesktop.org/libinput/libei/-/merge_requests/359>
Historically the preference for testing was to enable a bunch of
specific behaviors and then leave that as-is for the test. This can be
painful for some events, in particular sync/ping that are used
internally by libei's implementation.
Testing those events requires us to match the implementation-defined
internal setup which is a pain. Much easier to add a function
to allow disabling a specific behavior at some point during the test
Part-of: <https://gitlab.freedesktop.org/libinput/libei/-/merge_requests/340>
This test was checking for the capabilities for `EI_SCROLL` and
`EI_BUTTON`, but not advertising those interfaces initially. Presumably
this was unintentional, given there's no comment that it's intentionally
advertising some protocols but not others.
Also, should the test have failed to find the capabilities when it
didn't advertise the protocol to to start with? This change just fixes
the test, anyway.
This was causing the test to fail for `reis` CI in a proposed change in
https://github.com/ids1024/reis/pull/11.
Part-of: <https://gitlab.freedesktop.org/libinput/libei/-/merge_requests/352>
This makes peck_new_context() take variable arguments in the style
key, v1, v2... where each value is defined by the free-form key.
What we need right now is the mode of the context, so let's add that.
In the future we will add more configurable bits here.
Part-of: <https://gitlab.freedesktop.org/libinput/libei/-/merge_requests/351>
If a receiver client stops calling ei_dispatch for a while eventually
we fill up the send buffer, causing messages to be quietly dropped.
When the client resumes the message stream resumes with whatever we send
next but that can leave the client in an inconsistent state.
deskflow hit this in the server-side where our event sequence of pointer
motion+frames eventually filled up the buffer, causing
eis_device_stop_emulating() to be silently dropped. On the next
InputCapture sequence eis_device_start_emulating() was sent to an
already emulating client (as seen by the client).
This patch adds a secondary queue, if we fail to send a message with
EAGAIN queue it up and flush that queue whenever the next message is
sent. Meanwhile any newly added messages go straight into that queue.
The caveat here: a nonresponding client will eventually trigger OOM,
there is no upper limit on the messages yet
This is the libeis version of
commit 69e973e6b3 ("ei: queue unsent messages for later delivery if our buffer is full")
Closes: #79
Part-of: <https://gitlab.freedesktop.org/libinput/libei/-/merge_requests/331>
Currently libei's valgrind test setup has 100x timeout (3000s), but the
standalone protocol-test-valgrind still has 30s timeout, which is not enough
for RISC-V hardware. On Milk-V Pioneer (SG2042) it takes ~70s to complete. In
addition, `kill_gently` sends SIGKILL before the process terminates and fails
the test.
Bump protocol-test-valgrind timeout to 300s and increase timeout between kill
signals to 3s to solve the issue.
Part-of: <https://gitlab.freedesktop.org/libinput/libei/-/merge_requests/329>
This event is required to fix an issue with the current
ei_callback.done handling in libeis: previously we would imediately send
the ei_callback.done upon receiving ei_connection.sync from the client.
This results in incorrect behavior as we may have events in the queue
(and/or pending a frame) that the EIS implementation hasn't seen yet.
For example a client sending:
- ei_pointer.motion
- ei_connection.sync
- ei_device.frame
- ei_connection.sync
Will queue a motion + frame event on the EIS side during eis_dispatch()
but immediately receive done events for both sync requests.
This could be handled purely internally by keeping the sync event in the
queue but hidden to the caller - and automatically calling done when
it's that events turn, i.e. something like:
```
struct eis_event *eis_get_event(struct eis) {
struct eis_event *e = first_event(eis);
if (e == EIS_EVENT_SYNC) {
eis_callback_send_done(e);
eis_event_unref(e);
e = next_event(eis);
}
return e;
}
```
but that opens us up to a set of potential bugs detailed in
https://gitlab.freedesktop.org/libinput/libei/-/issues/71#note_2694603
So let's go the easy route by having a new event type that does nothing
other than eis_event_unref() in the EIS implementation. This way we can
queue the event and have everything behave in-order and as expected.
Closes#71
Part-of: <https://gitlab.freedesktop.org/libinput/libei/-/merge_requests/316>
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>
When running repeated tests in parallel, this one eventually fails
because the ei.send() doesn't trigger the expected BrokenPipeError.
Use ei.dispatch() instaed and check whether the connection still exists.
Part-of: <https://gitlab.freedesktop.org/libinput/libei/-/merge_requests/317>
Our automatic pong handler unconditionally sends a Pong back to the EIS
implementation. For some tests and depending on timing we may have
been disconnected already, resulting in a BrokenPipeError that fails
us the test. Ignore that error.
Part-of: <https://gitlab.freedesktop.org/libinput/libei/-/merge_requests/317>
If our server disconnects us with data still in the pipe we never picked
up on that data causing heisenbugs depending on whether we read things
(esp. the "disconnected" event) fast enough or not.
Part-of: <https://gitlab.freedesktop.org/libinput/libei/-/merge_requests/317>
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>
The protocol encoding is the string including the null byte. The test
wrappers sent the right string length but only encoded strlen() bytes so
where we had a string that's a multiple of 4 long we ended up claiming
it's a byte longer than was on the wire.
Part-of: <https://gitlab.freedesktop.org/libinput/libei/-/merge_requests/314>
This is primarily a development feature because it makes it easier to
develop a new feature for just one library without having to worry
about build errors in the other library (e.g. when new protocol parts
are added).
Part-of: <https://gitlab.freedesktop.org/libinput/libei/-/merge_requests/310>