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
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>
Updates protocol and API documentation to specify that the modifiers
event should be sent by the EIS implementation every time the modifier
or group state changes, including when the change is triggered by key
events on the emulated keyboard.
The previous approach of expecting the client to track modifier state
using xkb_state_update_key() for injected keys resulted in multiple
opportunities for the client and server to get out of sync (both due to
unavoidable race conditions and due the client not having access to the
complete state used by the server to calculate state changes), with no
way for the client to ensure it had a correct modifier map short of
unbinding and rebinding the seat.
The new approach allows the client to track state solely by applying
modifiers events with xkb_state_update_mask(), simplifying client
implementation. Because the event is sent for all changes, the client
can use ei_connection.sync / ei_ping() to ensure that it has received
the latest state incorporating all key requests sent prior to the sync
request (along with any externally-caused modifier state changes that
may have occured up to the time the sync message was received).
Part-of: <https://gitlab.freedesktop.org/libinput/libei/-/merge_requests/318>
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>
This is an event in response to "something change the modifier state"
where "something" was not an ei_keyboard.key event on this interface.
Examples are NumLock on after resumed, a nonzero XKB group, etc.
Closes#57
This is now obsolete after [1]. The ei_device.interface event announces
which interfaces are available on the device so we don't need
documentation to say "it's a bug to send this request if the device
doesn't have the capability" since the client won't have the interface
to begin with.
Fixes: a902d5dbd8 ("protocol: replace the capabilities enum with an interface list")
Remove leftovers from when this was an ei_device.capability event
but since removed, see [1]. Instead make clear that this needs to be
one of the bound interfaces.
[1] a902d5dbd8 ("protocol: replace the capabilities enum with an interface list")
Changing this would be an API-breaking change (depending on how
bindings are generated) so we'll have to live with this typo for the
foreseeable future.
Closes#53
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 is the only request that creates a new object but doesn't specify
the version for that object, courtesy of copy/paste from the wayland
protocol. In libei/libeis this a bit was hidden away so it didn't get
noticed - but it was already buggy: libei would always hardcode to
version 1 but libeis would take whichever ei_callback version was agreed
upon during handshake. This version could be higher than 1.
This is a protocol break but we're still pre-1.0, there are very few
people that will be affected by this and it's better than having to
carry this bug around for years.
Fixes#35
The only invocations we have right now of these callbacks ignore the
argument or force it to zero. But in the future we may have an interface
that requires a callback and that interface may need to store a
timestamp or object ID in this argument - so let's make sure we have
enough space for that.
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>
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.
Since these events are merely notifications of a single object, we can make
this more generic. This allows us to introduce future capabilities without
having to bump the seat.
Regardless of the ei_seat version, ei_seat.bind will support all
capablities of the negotiated ei_device interface. This means we don't need
to bump ei_seat just to add a new capability to ei_device.
Now that we have 64 bit integers on the wire and 64 bit object IDs,
we're already different to the Wayland protocol. So we might as well get
the full length and split message length and opcode again to make header
parsing and composing simpler.
This effectively reverts commit bf45a7182cb2f4c13f11e141fc846244d3ac6212.
Previously, we'd send one interface_version event for "ei_handshake"
immediately but all others after the client requests handshake.finish.
This was too confusing to document and not clear how it would work, so
let's make this simpler by splitting it up.
There is now a handshake_version event from the server, sent immediately
on connection that denotes the maximum version number for the interface.
And a handshake_version request from the client which must be the first
one by the client.