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.
This commit is contained in:
Peter Hutterer 2023-02-03 17:04:54 +10:00
parent 01a2ff2d72
commit fadc1853c9
11 changed files with 363 additions and 350 deletions

View file

@ -86,10 +86,6 @@
<request name="disconnect">
</request>
<request name="close_device">
<arg name="device_id" type="uint"/>
</request>
<request name="pointer_relative">
<arg name="device_id" type="uint"/>
<arg name="x" type="float"/>
@ -228,48 +224,6 @@
<arg name="version" type="uint" summary="the interface version"/>
</event>
<event name="device_added">
<arg name="device_id" type="uint"/>
<arg name="capabilities" type="uint"/>
<arg name="name" type="string"/>
<arg name="seat_id" type="uint"/>
<arg name="type" type="uint"/>
<arg name="width" type="uint"/>
<arg name="height" type="uint"/>
</event>
<event name="device_keymap">
<arg name="device_id" type="uint"/>
<arg name="keymap_type" type="uint"/>
<arg name="keymap_size" type="uint"/>
<arg name="keymap" type="fd"/>
</event>
<event name="device_region">
<arg name="device_id" type="uint"/>
<arg name="offset_x" type="uint"/>
<arg name="offset_y" type="uint"/>
<arg name="width" type="uint"/>
<arg name="hight" type="uint"/>
<arg name="scale" type="float"/>
</event>
<event name="device_done">
<arg name="device_id" type="uint"/>
</event>
<event name="device_removed">
<arg name="device_id" type="uint"/>
</event>
<event name="device_resumed">
<arg name="device_id" type="uint"/>
</event>
<event name="device_paused">
<arg name="device_id" type="uint"/>
</event>
<event name="pointer_relative">
<arg name="device_id" type="uint"/>
<arg name="x" type="float"/>
@ -484,6 +438,105 @@
the client can set up this seat now.
</description>
</event>
<event name="device" since="1">
<description summary="Device presence notification">
Notification that a new device has been added.
The interface version is equal or less to the client-supported
version in ei_connection_setup.interface for the "ei_device"
interface.
</description>
<arg name="device" type="new_id" interface="ei_device"/>
<arg name="version" type="uint" summary="the interface version"/>
</event>
</interface>
<interface name="ei_device" version="1">
<request name="release">
<description summary="Device removal request">
Notification that the client is no longer interested in this device.
The EIS implementation will release any resources related to this device and
send the ei_device.destroyed event once complete.
</description>
</request>
<event name="destroyed" since="1">
<description summary="Device removal notification">
This device has been removed and a client should release all
associated resources.
</description>
</event>
<event name="name" since="1">
<description summary="device name notification">
The name of this device, if any. This event is optional and sent once immediately
after object creation.
</description>
<arg name="name" type="string" help="the device name"/>
</event>
<enum name="capabilities" since="1">
<entry name="pointer" value="2"/>
<entry name="pointer_absolute" value="4"/>
<entry name="keyboard" value="8"/>
<entry name="touch" value="16"/>
</enum>
<event name="capabilities" since="1">
<description summary="device capability notification">
A bitmask of the capabilties of this device.
</description>
<arg name="capabilities" type="uint" enum="capabilities" help="the device name"/>
</event>
<enum name="device_type" since="1">
<entry name="virtual" value="1"/>
<entry name="physical" value="2"/>
</enum>
<event name="type" since="1">
<description summary="device type notification">
The device type, one of virtual or physical.
</description>
<arg name="type" type="uint" enum="device_type" help="the device type"/>
</event>
<event name="dimensions" since="1">
<description summary="device dimensions notification">
The device dimensions in mm.
</description>
<arg name="width" type="uint" help="the device physical width"/>
<arg name="height" type="uint" help="the device physical height"/>
</event>
<event name="keymap" since="1">
<arg name="type" type="uint" enum="keymap_type" help="the keymap type"/>
<arg name="size" type="uint" help="the keymap size in bytes"/>
<arg name="keymap" type="fd" help="file descriptor to the keymap"/>
</event>
<event name="region" since="1">
<arg name="offset_x" type="uint"/>
<arg name="offset_y" type="uint"/>
<arg name="width" type="uint"/>
<arg name="hight" type="uint"/>
<arg name="scale" type="float"/>
</event>
<event name="done" since="1">
<description summary="device setup completion notification">
Notification that the initial burst of events is complete and
the client can set up this device now.
</description>
</event>
<event name="resumed">
</event>
<event name="paused">
</event>
</interface>
</protocol>

View file

@ -33,6 +33,9 @@
#include "util-strings.h"
#include "libei-private.h"
#include "ei-proto.h"
DEFINE_UNREF_CLEANUP_FUNC(ei_region);
static const char *
ei_device_state_to_string(enum ei_device_state state)
@ -103,6 +106,7 @@ OBJECT_IMPLEMENT_SETTER(ei_device, user_data, void *);
OBJECT_IMPLEMENT_GETTER(ei_device, width, uint32_t);
OBJECT_IMPLEMENT_GETTER(ei_device, height, uint32_t);
OBJECT_IMPLEMENT_GETTER(ei_device, id, uint32_t);
OBJECT_IMPLEMENT_GETTER_AS_REF(ei_device, proto_object, const struct brei_object *);
_public_ struct ei_seat *
ei_device_get_seat(struct ei_device *device)
@ -117,10 +121,132 @@ ei_device_get_context(struct ei_device *device)
return ei_seat_get_context(ei_device_get_seat(device));
}
static int
handle_msg_destroy(struct ei_device *device)
{
struct ei *ei = ei_device_get_context(device);
log_debug(ei, "Removed device %#x", ei_device_get_id(device));
ei_device_removed_by_server(device);
return 0;
}
static int
handle_msg_name(struct ei_device *device, const char *name)
{
ei_device_set_name(device, name);
return 0;
}
static int
handle_msg_capabilities(struct ei_device *device, uint32_t caps)
{
ei_device_set_capabilities(device, caps);
return 0;
}
static int
handle_msg_type(struct ei_device *device, enum ei_device_type type)
{
ei_device_set_type(device, type);
return 0;
}
static int
handle_msg_dimensions(struct ei_device *device, uint32_t width, uint32_t height)
{
ei_device_set_size(device, width, height);
return 0;
}
static int
handle_msg_region(struct ei_device *device, uint32_t x, uint32_t y,
uint32_t w, uint32_t h, float scale)
{
_unref_(ei_region) *r = ei_region_new();
ei_region_set_offset(r, x, y);
ei_region_set_size(r, w, h);
ei_region_set_physical_scale(r, scale);
ei_device_add_region(device, r);
return 0;
}
static int
handle_msg_keymap(struct ei_device *device, uint32_t keymap_type, uint32_t keymap_sz, int keymap_fd)
{
ei_device_set_keymap(device, keymap_type, keymap_fd, keymap_sz);
return 0;
}
static int
handle_msg_done(struct ei_device *device)
{
struct ei *ei = ei_device_get_context(device);
ei_device_added(device);
ei_queue_device_added_event(device);
ei_device_done(device);
log_debug(ei,
"Added device %#x '%s' caps: %s%s%s%s seat: %s",
ei_device_get_id(device), ei_device_get_name(device),
ei_device_has_capability(device, EI_DEVICE_CAP_POINTER) ? "p" : "",
ei_device_has_capability(device, EI_DEVICE_CAP_POINTER_ABSOLUTE) ? "a" : "",
ei_device_has_capability(device, EI_DEVICE_CAP_KEYBOARD) ? "k" : "",
ei_device_has_capability(device, EI_DEVICE_CAP_TOUCH) ? "t" : "",
ei_seat_get_name(ei_device_get_seat(device)));
return 0;
}
static int
handle_msg_resumed(struct ei_device *device)
{
ei_device_resumed(device);
ei_queue_device_resumed_event(device);
return 0;
}
static int
handle_msg_paused(struct ei_device *device)
{
ei_device_paused(device);
ei_queue_device_paused_event(device);
return 0;
}
static const struct ei_device_interface interface = {
.destroyed = handle_msg_destroy,
.name = handle_msg_name,
.capabilities = handle_msg_capabilities,
.type = handle_msg_type,
.dimensions = handle_msg_dimensions,
.region = handle_msg_region,
.keymap = handle_msg_keymap,
.done = handle_msg_done,
.resumed = handle_msg_resumed,
.paused = handle_msg_paused,
};
const struct ei_device_interface *
ei_device_get_interface(struct ei_device *device)
{
return &interface;
}
struct ei_device *
ei_device_new(struct ei_seat *seat, uint32_t deviceid)
ei_device_new(struct ei_seat *seat, uint32_t deviceid, uint32_t version)
{
struct ei_device *device = ei_device_create(&seat->object);
struct ei *ei = ei_seat_get_context(seat);
device->proto_object.id = deviceid,
device->proto_object.implementation = device;
device->proto_object.interface = &ei_device_proto_interface;
device->proto_object.version = version;
list_init(&device->proto_object.link);
ei_register_object(ei, &device->proto_object);
device->capabilities = 0;
device->id = deviceid;
@ -136,10 +262,6 @@ ei_device_new(struct ei_seat *seat, uint32_t deviceid)
*/
ei_seat_ref(seat);
/* this list "owns" the ref for this device */
ei_device_ref(device);
list_append(&seat->devices, &device->link);
return device;
}
@ -238,6 +360,20 @@ ei_device_set_keymap(struct ei_device *device,
device->keymap = ei_keymap_ref(keymap);
}
static int
ei_device_send_release(struct ei_device *device)
{
struct ei *ei = ei_device_get_context(device);
if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED)
return 0;
int rc = ei_device_request_release(device);
if (rc)
ei_disconnect(ei);
return rc;
}
_public_ void
ei_device_close(struct ei_device *device)
@ -255,7 +391,7 @@ ei_device_close(struct ei_device *device)
case EI_DEVICE_STATE_PAUSED:
case EI_DEVICE_STATE_RESUMED:
ei_device_set_state(device, EI_DEVICE_STATE_REMOVED_FROM_CLIENT);
ei_send_close_device(device);
ei_device_send_release(device);
break;
}
}
@ -264,6 +400,7 @@ void
ei_device_removed_by_server(struct ei_device *device)
{
struct ei_seat *seat = ei_device_get_seat(device);
struct ei *ei = ei_device_get_context(device);
switch (device->state) {
case EI_DEVICE_STATE_NEW:
@ -274,6 +411,7 @@ ei_device_removed_by_server(struct ei_device *device)
case EI_DEVICE_STATE_PAUSED:
case EI_DEVICE_STATE_RESUMED:
case EI_DEVICE_STATE_EMULATING:
ei_unregister_object(ei, &device->proto_object);
ei_queue_device_removed_event(device);
ei_device_set_state(device, EI_DEVICE_STATE_DEAD);
/* Device is dead now. Move it from the devices list to

View file

@ -54,8 +54,10 @@ enum ei_device_state {
struct ei_device {
struct object object;
void *user_data;
struct brei_object proto_object;
struct list link;
uint32_t id;
uint32_t id; /* FIXME: remove this one */
enum ei_device_state state;
uint32_t capabilities;
char *name;
@ -102,13 +104,15 @@ struct ei_touch {
};
OBJECT_DECLARE_GETTER(ei_device, id, uint32_t);
OBJECT_DECLARE_GETTER(ei_device, proto_object, const struct brei_object *);
OBJECT_DECLARE_GETTER(ei_device, interface, const struct ei_device_interface *);
OBJECT_DECLARE_SETTER(ei_device, type, enum ei_device_type);
OBJECT_DECLARE_SETTER(ei_device, name, const char*);
OBJECT_DECLARE_SETTER(ei_device, seat, const char*);
OBJECT_DECLARE_SETTER(ei_device, capabilities, uint32_t);
struct ei_device *
ei_device_new(struct ei_seat *seat, uint32_t deviceid);
ei_device_new(struct ei_seat *seat, uint32_t deviceid, uint32_t version);
void
ei_device_add_region(struct ei_device *device, struct ei_region *r);

View file

@ -114,9 +114,6 @@ ei_send_message(struct ei *ei, const struct brei_object *object,
void
ei_add_seat(struct ei_seat *seat);
int
ei_send_close_device(struct ei_device *device);
int
ei_send_start_emulating(struct ei_device *device, uint32_t sequence);
@ -129,6 +126,15 @@ ei_send_frame(struct ei_device *device, uint64_t time);
void
ei_queue_device_removed_event(struct ei_device *device);
void
ei_queue_device_added_event(struct ei_device *device);
void
ei_queue_device_resumed_event(struct ei_device *device);
void
ei_queue_device_paused_event(struct ei_device *device);
void
ei_insert_device_removed_event(struct ei_device *device);

View file

@ -109,11 +109,25 @@ static int handle_msg_done(struct ei_seat *seat)
return 0;
}
static int handle_msg_device(struct ei_seat *seat, uint32_t id, uint32_t version)
{
struct ei *ei = ei_seat_get_context(seat);
log_debug(ei, "Added device %#x@v%u", id, version);
/* device is in the seat's device list */
struct ei_device *device = ei_device_new(seat, id, version);
/* this list "owns" the ref for this device */
list_append(&seat->devices, &device->link);
return 0;
}
static const struct ei_seat_interface interface = {
.destroyed = handle_msg_destroyed,
.name = handle_msg_name,
.capabilities = handle_msg_capabilities,
.done = handle_msg_done,
.device = handle_msg_device,
};
const struct ei_seat_interface *

View file

@ -50,19 +50,6 @@ _Static_assert(sizeof(enum ei_keymap_type) == sizeof(int), "Invalid enum size");
_Static_assert(sizeof(enum ei_event_type) == sizeof(int), "Invalid enum size");
_Static_assert(sizeof(enum ei_log_priority) == sizeof(int), "Invalid enum size");
static struct ei_seat *
ei_find_seat(struct ei *ei, uint32_t seatid)
{
struct ei_seat *seat;
list_for_each(seat, &ei->seats, link) {
if (ei_seat_get_id(seat) == seatid)
return seat;
}
return NULL;
}
static struct ei_device *
ei_find_device(struct ei *ei, uint32_t deviceid)
{
@ -367,8 +354,8 @@ insert_device_removed_event(struct ei_device *device)
insert_event(ei, e);
}
static void
queue_paused_event(struct ei_device *device)
void
ei_queue_device_paused_event(struct ei_device *device)
{
struct ei *ei= ei_device_get_context(device);
struct ei_event *e = ei_event_new_for_device(device);
@ -378,8 +365,8 @@ queue_paused_event(struct ei_device *device)
queue_event(ei, e);
}
static void
queue_resumed_event(struct ei_device *device)
void
ei_queue_device_resumed_event(struct ei_device *device)
{
struct ei *ei= ei_device_get_context(device);
struct ei_event *e = ei_event_new_for_device(device);
@ -616,129 +603,24 @@ handle_msg_seat(struct ei_connection *connection, uint32_t seat_id, uint32_t ver
return 0;
}
static int
handle_msg_device_added(struct ei_connection *connection, uint32_t deviceid, uint32_t capabilities,
const char *name, uint32_t seatid, uint32_t type,
uint32_t width, uint32_t height)
{
struct ei *ei = ei_connection_get_context(connection);
struct ei_seat *seat = ei_find_seat(ei, seatid);
if (!seat) {
log_bug(ei, "Invalid seat id %#x for device %s (%#x)",
seatid, name, deviceid);
return 0;
}
/* Wrong device id or a device already removed by the client but we
* won't know which unless we keep some device ID table. Not worth
* it, so just silently ignore */
if (ei_seat_find_device(seat, deviceid)) {
log_error(ei, "Server sent duplicate device id %#x", deviceid);
return -EINVAL;
}
switch (type) {
case EI_DEVICE_TYPE_PHYSICAL:
case EI_DEVICE_TYPE_VIRTUAL:
break;
default:
log_error(ei, "Server sent invalid device type %u", type);
return -EINVAL;
}
_unref_(ei_device) *device = ei_device_new(seat, deviceid);
ei_device_set_type(device, type);
if (type == EI_DEVICE_TYPE_PHYSICAL)
ei_device_set_size(device, width, height);
ei_device_set_name(device, name);
ei_device_set_capabilities(device, capabilities);
ei_device_added(device);
log_debug(ei,
"Added device %#x '%s' caps: %s%s%s%s seat: %s",
deviceid, name,
ei_device_has_capability(device, EI_DEVICE_CAP_POINTER) ? "p" : "",
ei_device_has_capability(device, EI_DEVICE_CAP_POINTER_ABSOLUTE) ? "a" : "",
ei_device_has_capability(device, EI_DEVICE_CAP_KEYBOARD) ? "k" : "",
ei_device_has_capability(device, EI_DEVICE_CAP_TOUCH) ? "t" : "",
ei_seat_get_name(seat));
return 0;
}
static int
handle_msg_device_keymap(struct ei_connection *connection, uint32_t deviceid,
enum ei_keymap_type keymap_type,
uint32_t keymap_sz, int keymap_fd)
{
struct ei *ei = ei_connection_get_context(connection);
log_debug(ei, "Adding keymap for %#x", deviceid);
struct ei_device *device = ei_find_device(ei, deviceid);
if (!device)
return 0;
ei_device_set_keymap(device, keymap_type, keymap_fd, keymap_sz);
return 0;
}
void
ei_queue_device_removed_event(struct ei_device *device)
{
queue_device_removed_event(device);
}
void
ei_queue_device_added_event(struct ei_device *device)
{
queue_device_added_event(device);
}
void
ei_insert_device_removed_event(struct ei_device *device)
{
insert_device_removed_event(device);
}
static int
handle_msg_device_added_done(struct ei_connection *connection, uint32_t deviceid)
{
struct ei *ei = ei_connection_get_context(connection);
log_debug(ei, "Done with device %#x", deviceid);
struct ei_device *device = ei_find_device(ei, deviceid);
if (!device)
return 0;
queue_device_added_event(device);
ei_device_done(device);
return 0;
}
static int
handle_msg_device_region(struct ei_connection *connection, uint32_t deviceid,
uint32_t x, uint32_t y,
uint32_t w, uint32_t h,
float scale)
{
struct ei *ei = ei_connection_get_context(connection);
log_debug(ei, "Adding device region for %#x", deviceid);
struct ei_device *device = ei_find_device(ei, deviceid);
if (!device)
return 0;
_unref_(ei_region) *r = ei_region_new();
ei_region_set_offset(r, x, y);
ei_region_set_size(r, w, h);
ei_region_set_physical_scale(r, scale);
ei_device_add_region(device, r);
return 0;
}
static int
handle_msg_keyboard_modifiers(struct ei_connection *connection, uint32_t deviceid,
uint32_t depressed, uint32_t locked,
@ -768,68 +650,6 @@ handle_msg_keyboard_modifiers(struct ei_connection *connection, uint32_t devicei
return 0;
}
static int
handle_msg_device_removed(struct ei_connection *connection, uint32_t deviceid)
{
struct ei *ei = ei_connection_get_context(connection);
log_debug(ei, "Removed device %#x", deviceid);
struct ei_device *device = ei_find_device(ei, deviceid);
if (!device)
return 0;
ei_device_removed_by_server(device);
return 0;
}
static int
handle_msg_device_resumed(struct ei_connection *connection, uint32_t deviceid)
{
struct ei *ei = ei_connection_get_context(connection);
log_debug(ei, "Resumed device %#x", deviceid);
struct ei_device *device = ei_find_device(ei, deviceid);
if (device) {
ei_device_resumed(device);
queue_resumed_event(device);
}
return 0;
}
static int
handle_msg_device_paused(struct ei_connection *connection, uint32_t deviceid)
{
struct ei *ei = ei_connection_get_context(connection);
log_debug(ei, "Paused device %#x", deviceid);
struct ei_device *device = ei_find_device(ei, deviceid);
if (device) {
ei_device_paused(device);
queue_paused_event(device);
}
return 0;
}
int
ei_send_close_device(struct ei_device *device)
{
struct ei *ei = ei_device_get_context(device);
if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED)
return 0;
int rc = ei_connection_request_close_device(ei->connection, device->id);
if (rc)
ei_disconnect(ei);
return rc;
}
int
ei_send_start_emulating(struct ei_device *device, uint32_t sequence)
{
@ -1326,6 +1146,7 @@ handle_msg_connection_setup(struct ei_connection *connection, uint32_t new_id, u
ei_connection_setup_request_interface(setup, "ei_connection", VERSION_V(1));
ei_connection_setup_request_interface(setup, "ei_callback", VERSION_V(1));
ei_connection_setup_request_interface(setup, "ei_seat", VERSION_V(1));
ei_connection_setup_request_interface(setup, "ei_device", VERSION_V(1));
}
ei_connection_setup_request_done(setup);
ei_connection_setup_unref(setup);
@ -1351,13 +1172,6 @@ static const struct ei_connection_interface intf_state_connected = {
.connection_setup = NULL, /* EPROTO */
.disconnected = handle_msg_disconnected,
.seat = handle_msg_seat,
.device_added = handle_msg_device_added,
.device_removed = handle_msg_device_removed,
.device_resumed = handle_msg_device_resumed,
.device_paused = handle_msg_device_paused,
.device_region = handle_msg_device_region,
.device_keymap = handle_msg_device_keymap,
.device_done = handle_msg_device_added_done,
.keyboard_modifiers = handle_msg_keyboard_modifiers,
/* events */
@ -1406,6 +1220,8 @@ lookup_object(uint32_t object_id, struct brei_object **object, void *userdata)
}
}
log_debug(ei, "Failed to find object %#x", object_id);
return -ENOENT;
}

View file

@ -202,47 +202,6 @@ client_send_seat_added(struct eis_client *client, struct eis_seat *seat)
eis_seat_get_version(seat));
}
static int
client_send_device_added(struct eis_client *client, struct eis_device *device)
{
struct eis_seat *seat = eis_device_get_seat(device);
int rc = eis_connection_event_device_added(client->connection, device->id, device->capabilities,
device->name, eis_seat_get_id(seat),
device->type, device->width, device->height);
if (rc >= 0 && device->keymap)
rc = eis_connection_event_device_keymap(client->connection, device->id, device->keymap->type, device->keymap->size, device->keymap->fd);
if (rc >= 0 && device->type == EIS_DEVICE_TYPE_VIRTUAL) {
struct eis_region *r;
list_for_each(r, &device->regions, link) {
rc = eis_connection_event_device_region(client->connection, device->id, r->x, r->y, r->width, r->height, r->physical_scale);
}
}
if (rc >= 0)
rc = eis_connection_event_device_done(client->connection, device->id);
return rc;
}
static int
client_send_device_removed(struct eis_client *client, struct eis_device *device)
{
return eis_connection_event_device_removed(client->connection, device->id);
}
static int
client_send_device_paused(struct eis_client *client, struct eis_device *device)
{
return eis_connection_event_device_paused(client->connection, device->id);
}
static int
client_send_device_resumed(struct eis_client *client, struct eis_device *device)
{
return eis_connection_event_device_resumed(client->connection, device->id);
}
static int
client_send_keyboard_modifiers(struct eis_client *client, struct eis_device *device,
const struct eis_xkb_modifiers *mods)
@ -315,18 +274,6 @@ eis_client_setup_done(struct eis_client *client, const char *name, bool is_sende
client->state = EIS_CLIENT_STATE_CONNECTING;
}
static int
client_msg_close_device(struct eis_connection *connection, uint32_t deviceid)
{
struct eis_client *client = eis_connection_get_client(connection);
struct eis_device *device = eis_client_find_device(client, deviceid);
if (device)
eis_device_closed_by_client(device);
return 0;
}
#define DISCONNECT_IF_RECEIVER_CONTEXT(client_) do { \
if (!(client_)->is_sender) { \
struct eis *_ctx = eis_client_get_context(client_); \
@ -579,7 +526,6 @@ static const struct eis_connection_interface intf_state_connecting = {
static const struct eis_connection_interface intf_state_connected = {
.sync = client_msg_sync,
.disconnect = client_msg_disconnect,
.close_device = client_msg_close_device,
/* events */
.start_emulating = client_msg_start_emulating,
@ -624,6 +570,8 @@ lookup_object(uint32_t object_id, struct brei_object **object, void *userdata)
}
}
log_debug(eis_client_get_context(client), "Failed to find object %#x", object_id);
return -ENOENT;
}
@ -677,6 +625,7 @@ eis_client_new(struct eis *eis, int fd)
.ei_connection_setup = VERSION_V(1),
.ei_callback = VERSION_V(1),
.ei_seat = VERSION_V(1),
.ei_device = VERSION_V(1),
};
client->connection = eis_connection_new(client);
@ -721,30 +670,6 @@ eis_client_add_seat(struct eis_client *client, struct eis_seat *seat)
client_send_seat_added(client, seat);
}
void
eis_client_add_device(struct eis_client *client, struct eis_device *device)
{
client_send_device_added(client, device);
}
void
eis_client_remove_device(struct eis_client *client, struct eis_device *device)
{
client_send_device_removed(client, device);
}
void
eis_client_pause_device(struct eis_client *client, struct eis_device *device)
{
client_send_device_paused(client, device);
}
void
eis_client_resume_device(struct eis_client *client, struct eis_device *device)
{
client_send_device_resumed(client, device);
}
void
eis_client_keyboard_modifiers(struct eis_client *client, struct eis_device *device,
uint32_t depressed, uint32_t latched, uint32_t locked,

View file

@ -42,6 +42,7 @@ struct eis_client_interface_versions {
uint32_t ei_connection_setup;
uint32_t ei_callback;
uint32_t ei_seat;
uint32_t ei_device;
};
struct eis_client {
@ -103,18 +104,6 @@ eis_client_send_message(struct eis_client *client, const struct brei_object *obj
void
eis_client_add_seat(struct eis_client *client, struct eis_seat *seat);
void
eis_client_add_device(struct eis_client *client, struct eis_device *device);
void
eis_client_remove_device(struct eis_client *client, struct eis_device *device);
void
eis_client_resume_device(struct eis_client *client,
struct eis_device *device);
void
eis_client_pause_device(struct eis_client *client,
struct eis_device *device);
void
eis_client_keyboard_modifiers(struct eis_client *client, struct eis_device *device,
uint32_t depressed, uint32_t latched, uint32_t locked,

View file

@ -134,6 +134,7 @@ client_msg_interface(struct eis_connection_setup *setup, const char *name, uint3
VERSION_ENTRY(ei_connection),
VERSION_ENTRY(ei_connection_setup),
VERSION_ENTRY(ei_seat),
VERSION_ENTRY(ei_device),
#undef VERSION_ENTRY
};

View file

@ -34,6 +34,13 @@
#include "libeis-private.h"
#include "eis-proto.h"
static_assert((1 << EIS_DEVICE_CAP_POINTER) == EIS_DEVICE_CAPABILITIES_POINTER, "ABI mismatch");
static_assert((1 << EIS_DEVICE_CAP_POINTER_ABSOLUTE) == EIS_DEVICE_CAPABILITIES_POINTER_ABSOLUTE, "ABI mismatch");
static_assert((1 << EIS_DEVICE_CAP_KEYBOARD) == EIS_DEVICE_CAPABILITIES_KEYBOARD, "ABI mismatch");
static_assert((1 << EIS_DEVICE_CAP_TOUCH) == EIS_DEVICE_CAPABILITIES_TOUCH, "ABI mismatch");
static_assert((int)EIS_DEVICE_TYPE_VIRTUAL == EIS_DEVICE_DEVICE_TYPE_VIRTUAL, "ABI mismatch");
static_assert((int)EIS_DEVICE_TYPE_PHYSICAL == EIS_DEVICE_DEVICE_TYPE_PHYSICAL, "ABI mismatch");
_public_
OBJECT_IMPLEMENT_REF(eis_keymap);
_public_
@ -167,6 +174,7 @@ OBJECT_IMPLEMENT_GETTER(eis_device, width, uint32_t);
_public_
OBJECT_IMPLEMENT_GETTER(eis_device, height, uint32_t);
OBJECT_IMPLEMENT_GETTER(eis_device, id, uint32_t);
OBJECT_IMPLEMENT_GETTER_AS_REF(eis_device, proto_object, const struct brei_object *);
_public_ struct eis_seat *
eis_device_get_seat(struct eis_device *device)
@ -186,13 +194,37 @@ eis_device_get_client(struct eis_device *device)
return eis_seat_get_client(eis_device_get_seat(device));
}
static int
client_msg_release(struct eis_device *device)
{
eis_device_closed_by_client(device);
return 0;
}
static const struct eis_device_interface interface = {
.release = client_msg_release,
};
const struct eis_device_interface *
eis_device_get_interface(struct eis_device *device)
{
return &interface;
}
_public_ struct eis_device *
eis_seat_new_device(struct eis_seat *seat)
{
static uint32_t deviceid;
struct eis_device *device = eis_device_create(&seat->object);
struct eis_client *client = eis_seat_get_client(seat);
device->id = eis_seat_get_id(seat) << 16 | ++deviceid;
device->proto_object.id = eis_client_get_new_id(client);
device->proto_object.implementation = device;
device->proto_object.interface = &eis_device_proto_interface;
device->proto_object.version = client->interface_versions.ei_device;
assert(device->proto_object.version != 0);
list_init(&device->proto_object.link);
device->id = device->proto_object.id; /* FIXME: remove once all messages are in the device */
device->name = xstrdup("unnamed device");
device->capabilities = 0;
device->state = EIS_DEVICE_STATE_NEW;
@ -264,6 +296,9 @@ eis_device_configure_size(struct eis_device *device, uint32_t width, uint32_t he
_public_ void
eis_device_add(struct eis_device *device)
{
struct eis_client *client = eis_device_get_client(device);
struct eis_seat *seat = eis_device_get_seat(device);
if (device->state != EIS_DEVICE_STATE_NEW) {
log_bug_client(eis_device_get_context(device),
"%s: device already (dis)connected", __func__);
@ -276,12 +311,36 @@ eis_device_add(struct eis_device *device)
}
device->state = EIS_DEVICE_STATE_PAUSED;
eis_client_add_device(eis_device_get_client(device), device);
eis_client_register_object(client, &device->proto_object);
eis_seat_event_device(seat, device->proto_object.id, device->proto_object.version);
int rc = eis_device_event_name(device, device->name);
if (rc == 0)
rc = eis_device_event_capabilities(device, device->capabilities);
if (rc == 0)
rc = eis_device_event_type(device, device->type);
if (rc == 0 && device->type == EIS_DEVICE_TYPE_PHYSICAL)
rc = eis_device_event_dimensions(device, device->width, device->height);
if (rc == 0 &&device->type == EIS_DEVICE_TYPE_VIRTUAL) {
struct eis_region *r;
list_for_each(r, &device->regions, link) {
rc = eis_device_event_region(device, r->x, r->y, r->width, r->height, r->physical_scale);
if (rc != 0)
break;
}
}
if (rc >= 0 && device->keymap)
rc = eis_device_event_keymap(device, device->keymap->type, device->keymap->size, device->keymap->fd);
if (rc == 0)
eis_device_event_done(device);
/* FIXME: check rc */
}
_public_ void
eis_device_remove(struct eis_device *device)
{
struct eis_client *client = eis_device_get_client(device);
if (device->state == EIS_DEVICE_STATE_DEAD)
return;
@ -289,8 +348,10 @@ eis_device_remove(struct eis_device *device)
!eis_client_is_sender(eis_device_get_client(device)))
eis_device_stop_emulating(device);
if (device->state != EIS_DEVICE_STATE_NEW)
eis_device_event_destroyed(device);
device->state = EIS_DEVICE_STATE_DEAD;
eis_client_remove_device(eis_device_get_client(device), device);
eis_client_unregister_object(client, &device->proto_object);
list_remove(&device->link);
eis_device_unref(device);
}
@ -972,7 +1033,7 @@ eis_device_pause(struct eis_device *device)
return;
device->state = EIS_DEVICE_STATE_PAUSED;
eis_client_pause_device(eis_device_get_client(device), device);
eis_device_event_paused(device);
}
_public_ void
@ -982,7 +1043,7 @@ eis_device_resume(struct eis_device *device)
return;
device->state = EIS_DEVICE_STATE_RESUMED;
eis_client_resume_device(eis_device_get_client(device), device);
eis_device_event_resumed(device);
}
_public_ void

View file

@ -28,6 +28,7 @@
#include "util-object.h"
#include "util-list.h"
#include "brei-shared.h"
enum eis_device_state {
EIS_DEVICE_STATE_NEW,
@ -41,6 +42,9 @@ enum eis_device_state {
struct eis_device {
struct object object; /* parent is ei_seat, and we have a ref to it */
struct list link;
struct brei_object proto_object;
uint32_t id;
char *name;
enum eis_device_state state;
@ -99,6 +103,8 @@ struct eis_xkb_modifiers {
OBJECT_DECLARE_GETTER(eis_device, id, uint32_t);
OBJECT_DECLARE_GETTER(eis_device, context, struct eis *);
OBJECT_DECLARE_GETTER(eis_device, proto_object, const struct brei_object *);
OBJECT_DECLARE_GETTER(eis_device, interface, const struct eis_device_interface *);
void
eis_device_set_client_keymap(struct eis_device *device,