Commit graph

145 commits

Author SHA1 Message Date
Peter Hutterer
01a2ff2d72 brei: pass the proto object through to send_message
Makes for easier debugging since we can print names instead of just
ids/opcodes.
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
a778a22e26 protocol: add an interface version announcement to the connection setup
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.
2023-03-03 11:20:42 +10:00
Peter Hutterer
09826b8bd3 eis: add a reason to the disconnect message
Allows for slightly easier debugging in the case where we get
disconnected after some protocol error.
2023-03-03 11:20:42 +10:00
Peter Hutterer
db786c7822 protocol: add a ei_connection_setup interface
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.
2023-03-03 11:20:42 +10:00
Peter Hutterer
9cbce95326 protocol: add a sync request and the ei_callback interface
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.
2023-03-03 11:20:42 +10:00
Peter Hutterer
d0e6c251b6 protocol: rename the ei core interface to ei_connection
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.
2023-03-03 11:20:42 +10:00
Peter Hutterer
b02b4f0901 Drop protobuf in favour of a custom protocol
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.
2023-03-03 11:20:42 +10:00
Peter Hutterer
e3c34830db ei: rename ei_set_connection to ei_set_socket
Current plans are to use the "connection" term for the ei_connection
interface in the (future) protocol, so let's rename this to avoid
clashes.
2023-03-03 11:20:42 +10:00
Peter Hutterer
d1282b3681 Add some extra getters for the context and the eis_client
These are all noops but this way we can ensure that get_context() and
get_client works on all objects - useful for (upcoming) generated code.
2023-02-13 14:00:19 +10:00
Peter Hutterer
56c992f4c6 Remove the public API to query the client version number
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.
2023-02-13 13:55:44 +10:00
Peter Hutterer
ff9830c122 Add a sequence number to START_EMULATING
This makes it easier to correlate a particular input transaction
(whether there are events or not) with out-of-band information like the
planned portal InputCapture::Activated signal's "activation-id".
2023-02-09 11:48:29 +10:00
Peter Hutterer
a5cc87c837 Purge the properties from the protocol
The primary use-case for these properties in libei itself was to send
some fixed information (pid, cmdline and conection type). In the portal
case, these can be obtained out-of-band via the portal. In the
non-portal case these can be obtained from the socket itself (fetch pid,
look up /proc/pid/cmdline) which is just as reliable as trusting
whatever libei sends.

The only other use-case for the properties was the activation id in the
InputCapture::Activated portal signal. This can be achieved with a
serial in the START_EMULATING event.
2023-02-09 11:48:29 +10:00
Peter Hutterer
19c85e7ee1 ei: fix a typo 2023-02-02 15:16:56 +10:00
Peter Hutterer
e515edafa5 ei: re-order a few arguments to match the order in the protocol
No functional changes
2023-02-01 12:52:34 +10:00
Peter Hutterer
bc78c24290 Fix some logging linebreak issues
One excessive linebreak, another one was missing.
2022-09-07 10:03:11 +10:00
Peter Hutterer
5535692ee0 proto: allow the client to set the protocol version
Let the client set the version number it wants on Connect. There is new
public API to query the client/server's version as set once the connect
finished (eis_client_get_version() and ei_get_version()) but there is
currently no public API for the client to select the version it actually
wants, other than whatever both support. IOW, it's not possible for the
client to say "I want version 8 but if that's not supported, use version
5".
2022-09-07 09:42:59 +10:00
Peter Hutterer
08a4ce4aac proto: add a version exchange prior to connect
Add a new protocol message "GetVersion" and the matching reply from the
server with "Version" that can be sent at any time. The server always
replies with the highest protocol version it supports, allowing the
client to choose the protocol version it wants.

These two messages also have a fixed string to make the protocol easy to
identify in hexdumps.

To avoid roundtrips on connection, libeis immediately sends the Version
message. Ideally and by the time the client actually starts, that
version is already available and we can continue without requiring a
full roundtrip.

This patch only adds the version exchange with the server, it does not
yet add the bits for the client to actually set the version.
2022-09-07 09:30:39 +10:00
Peter Hutterer
37467881e6 Drop the trailing newline from the log messages
Punt this job to the caller, any structured logging handler doesn't need
them anyway and it makes handling of messages more awkward.

For our default log handlers (fprintf) we can just append them
ourselves.

Fixes #19
2022-08-11 10:09:27 +10:00
Peter Hutterer
07f80cc002 proto: split the client's SetProperty from the server event
This makes the code/protocol slightly more readable.
2022-08-02 03:33:32 +00:00
Peter Hutterer
b4da6738d3 Retrofit event timestamps to all device events based on the frame
As we now buffer device frames we can apply the timestamp of the frame
event to all currently pending events.
2022-05-17 15:31:20 +10:00
Peter Hutterer
48bf74a5b9 Add a pending event queue for incoming device events
Incoming device events are now added to a device-internal queue. Once
the frame event comes in, that queue is shuffled over to the main event
queue. For libei/the EIS implementation this means that device events
are seen only once the frame event appears from the sender (or it is
emulated by other means).
2022-05-17 15:31:20 +10:00
Peter Hutterer
d99e42b808 Add timestamps to frame events
Currently only implemented for frame events, the vague plan for the
future is to merely queue the device events internally and "release"
them once a frame event was received, retrofitting the timestamp to the
C event struct (i.e. making ei_event_get_time() available on all device
events).

Meanwhile, the frame event it is.
2022-05-17 07:18:41 +10:00
Peter Hutterer
5b286a4d3a ei: add receiver handling for empty/flushing frame events
Where the sender sends empty frame events, or a device event without a
subsequent frame events ensure that event is filtered or emulated in our
event queue.

Note: because of our sender filters, we cannot actually test
this, at least not easily. Let's hope it works.
2022-05-05 13:46:26 +10:00
Peter Hutterer
f0605b5e53 Add a filter for empty frames on the receiver side 2022-05-05 13:41:36 +10:00
Peter Hutterer
a4dde7c35f Filter empty frame events
We only need frame events after device events (pointer, touch,
keyboard). In some cases, the library prevents an event from being
written to the wire, e.g. if the coordinates are out of region, but the
client will still call ei_device_frame() for that now-filtered event.

Keep a boolean to remember if we have sent something that requires a
frame event and filter accordingly.

Note that this currently filters the *sender* side only, not the
receiver side. A sender that gets an empty frame event onto the wire
will still get that into the other side.

This also doesn't handle the flushing of frame events before other
events, ideally we should enforce a frame event before e.g. stop
emulating.
2022-04-29 11:38:07 +10:00
Peter Hutterer
f35be22d2c Rename ei active/passive to sender/receiver
This is more explicit in what it actually does, making it easier to
immediately understand the code.
2022-04-04 15:42:27 +10:00
Peter Hutterer
fa091d7ac4 Differentiate between physical and virtual devices
With passive libei contexts receiving events sent by the EIS
implementation, the type of device changes significantly. While a
relative input device could still send data in logical pixels,
absolute devices may not have that luxury.

Best example here is an external tablet (think: Wacom Intuos): that
tablet has no built-in mapping to a screen and thus cannot capture input
events in logical pixels.

Address this by adding a device type, either virtual or physical.
In terms of functionality, the device's type decides:
- only virtual devices have regions
- only physical devices have a size

The event API remains as-is but the event data not represents either
logical pixels (virtual devices) or mm (physical device).

An EIS implementation connected to a passive libei context would likely
create:
- a virtual relative device (sending deltas in logical pixels)
- one or more physical absolute devices (sending deltas in mm)
2022-04-04 05:28:36 +00: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
7b760e5950 eis: the EIS context does not have a is_active setting
This is a leftover from an earlier implementation that didn't get
removed in time. This extends to a macro that was using the context flag
(rather than the client flag) and in turn caused a bunch of false
positives on the tests.
2022-03-28 16:53:11 +10:00
Peter Hutterer
42c1a69436 Add ei_is_active()
Typical clients shouldn't need this but the test suite does so let's add
it.
2022-03-28 16:39:10 +10:00
Peter Hutterer
faa9500afe Add concept of active/passive libei contexts
A libei context can be initialized as active or passive context -
an "active" context sends events, a "passive" context receives events.
The EIS context supports both simultaneously, it is up to the
implementation to disconnect libei clients that it does not want to
suppport.

For example, the xdotool use-case creates an active libei context. The
EIS implementation controls and sets up the devices, but libei
sends the events.

In an input-capturing use-case, the EIS implementation controls
and sets up the devices **and** sends the events. libei is merely the
receiver for any event, it cannot send events. Thus this use-case
requires a passive libei context.

Most of this code is copy/paste with minor modifications - libei already
had the code to send events, libeis had the code to receive events, so
the vast majority of this patch is copying the code into the respective
other library, swap "ei" and "eis" and then apply the various minor
modifications needed to hook into the existing library.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2022-03-04 14:04:33 +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
c15fcdc140 util: add a helper for fetching the cmdline.
Better than duplicating this three times.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2022-03-03 00:43:02 +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
5f2afdf806 Fix a bunch of compiler warnings
Most are signed vs unsigned, the remaining ones are an unused
variables/functions.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2022-03-01 23:28:49 +00:00
Peter Hutterer
2c4506fdb8 Drain all data from the fd if we are disconnecting anyway
If we get EPROTO or EINVAL on the connection, all we do is disconnect
(ourselves or the client). So let's drain the fd so there's no other
data to be parsed by accident and then continue with actually
disconnecting.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2022-03-01 23:25:43 +00:00
Peter Hutterer
bbbf2ff0f2 ei: add a helper function to create an event from a device
Just cuts down on duplication/room for error

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2022-02-28 02:23:40 +00:00
Peter Hutterer
47d8b2e0b5 Add static asserts to ensure our enums are sizeof(int)
Prevents any ABI suprprises by the enums being expanded to long or
shortened to char on special targets.

Fixes #11

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2022-02-16 03:25:42 +00:00
Peter Hutterer
5c017654e8 ei: always queue a disconnect event locally
In the case of a refused portal connection we get disconnected before we
had a chance to send the CONNECT message. This still needs to queue a
disconnect event and thus bubble back up to the caller.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2021-08-26 16:43:06 +10:00
Peter Hutterer
ed208f8374 ei: add an ei.connection.type property to be filled in automatically
Planned values: 'socket' and 'portal', the latter to be set by the
portal.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2021-08-26 12:47:07 +10:00
Peter Hutterer
1225bcb0e1 Add a property API for generic key/value exchanges
There is data that libei and the EIS implementation will want to
exchange that is not covered by the immediate API.

To avoid having to add APIs for all of these, let's provide a generic
property API that both server and client can use to exchange this info.

The property API provides read/write/delete permissions but those only
apply to the client, not the server. The idea is that a server can
create (or restrict) properties that the client can read but not modify
and/or delete. A special-case are properties filled in automatically by
libei: ei.application.pid and ei.application.cmdline. These could be
used by e.g. the portal implementation to match permissions.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2021-08-25 13:35:36 +10:00
Peter Hutterer
1bb5e103ab Split connect into an additional connect_done
This allows us to transmit extra information about the client before the
server has to decide on whether it wants to connect us.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2021-08-25 11:25:32 +10:00
Peter Hutterer
a03f547989 proto: add a start/stop emulating message pair
This effectively provides the EIS implementation with a notification
that the client will actually send events in the near future. To be used
by e.g. synergy-like clients when the pointer enters the logical screen
so that the EIS implementation can flash a warning or something.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2021-08-24 13:14:20 +10:00
Peter Hutterer
1884785a8a Add a scroll stop/cancel event
This allows a client to trigger kinetic scrolling (or prevent it).
For compositors implementing EIS, the only realistic scroll source is
continuous which allows for scroll stop events. So let's give the client
the opportunity to trigger those on demand.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2021-08-24 09:21:05 +10:00
Peter Hutterer
55594cd09c Add a frame event to logically group events together
Already present in e.g. libinput and wayland, this event allows us to
group several events together to denote them as a logical group.
Required for multi-touch but as we've learned with Wayland it's also
required to group other events (scroll events in the case of Wayland).

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2021-08-24 09:21:05 +10:00
Peter Hutterer
6f70e97cce Implement key modifier mask events similar to Wayland
Since the server controls the keymap, and that keymap is likely merged
with some other device let's add the events so we notify the client of
things like numlock-is-down etc.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2021-08-23 15:03:15 +10:00
Peter Hutterer
b08ec3cea4 ei: split event handling into its own source file
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2021-08-23 12:26:07 +10:00
Peter Hutterer
f8c2078bd3 ei: use a getter for ei_event_get_seat
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2021-08-23 12:26:07 +10:00