mirror of
https://gitlab.freedesktop.org/libinput/libei.git
synced 2026-02-04 14:10:27 +01:00
Add an EIS-controlled seat to the hierarchy
After CONNECT, the EIS implementation needs to add one or more seats. The libei client can only create devices within those seats. This mirrors the wayland hierarchy as well as the X.Org one. The seat has a set of allowed capabilities, so the client knows ahead of time when it may not be possible to create a specific device. Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
parent
207cd5fd24
commit
93b96e42ad
22 changed files with 1173 additions and 241 deletions
|
|
@ -46,6 +46,7 @@ src_libei = [
|
|||
'src/libei.c',
|
||||
'src/libei-device.c',
|
||||
'src/libei-log.c',
|
||||
'src/libei-seat.c',
|
||||
'src/libei-socket.c',
|
||||
'src/libei-fd.c',
|
||||
'src/libei-proto.h',
|
||||
|
|
@ -99,6 +100,7 @@ src_libeis = [
|
|||
'src/libeis-device.c',
|
||||
'src/libeis-event.c',
|
||||
'src/libeis-log.c',
|
||||
'src/libeis-seat.c',
|
||||
'src/libeis-socket.c',
|
||||
'src/libeis-fd.c',
|
||||
'src/libeis-proto.h',
|
||||
|
|
|
|||
|
|
@ -15,13 +15,14 @@ syntax = "proto3";
|
|||
* 2. - client sends "Connect"
|
||||
* 2.a - server replies with "Connected" or
|
||||
* 2.b - server replies with "Disconnected" and closes its end of the socket
|
||||
* 3. - client sends "AddDevice"
|
||||
* 3.a - server replies with "DeviceAdded" or
|
||||
* 3.b - server replies with "DeviceRemoved"
|
||||
* 4. - server sends "DeviceResumed"
|
||||
* 5. - client sends "PointerRelative" or any other event
|
||||
* 6. - client sends "RemoveDevice"
|
||||
* 7. - client sends "Disconnect" and closes its end of the socket
|
||||
* 3. - server sends "AddSeat" (once or multiple times)
|
||||
* 4. - client sends "AddDevice" for a specific seat
|
||||
* 4.a - server replies with "DeviceAdded" or
|
||||
* 4.b - server replies with "DeviceRemoved"
|
||||
* 5. - server sends "DeviceResumed"
|
||||
* 6. - client sends "PointerRelative" or any other event
|
||||
* 7. - client sends "RemoveDevice"
|
||||
* 8. - client sends "Disconnect" and closes its end of the socket
|
||||
*
|
||||
* The server may send Disconnect at any time.
|
||||
* The server may send Removed for a device at any time after that device's
|
||||
|
|
@ -91,6 +92,7 @@ message AddDevice {
|
|||
uint32 keymap_type = 8;
|
||||
uint32 keymap_size = 9;
|
||||
string name = 10;
|
||||
uint32 seat = 11;
|
||||
}
|
||||
|
||||
message RemoveDevice {
|
||||
|
|
@ -152,6 +154,16 @@ message Connected {
|
|||
message Disconnected {
|
||||
}
|
||||
|
||||
message SeatAdded {
|
||||
uint32 seatid = 1;
|
||||
uint32 capabilities = 2;
|
||||
string name = 3;
|
||||
}
|
||||
|
||||
message SeatRemoved {
|
||||
uint32 seatid = 1;
|
||||
}
|
||||
|
||||
message DeviceAdded {
|
||||
uint32 deviceid = 1;
|
||||
uint32 capabilities = 2;
|
||||
|
|
@ -160,6 +172,7 @@ message DeviceAdded {
|
|||
uint32 keymap_type = 4;
|
||||
uint32 keymap_size = 5;
|
||||
string name = 6;
|
||||
uint32 seatid = 7;
|
||||
}
|
||||
|
||||
message DeviceRemoved {
|
||||
|
|
@ -178,10 +191,12 @@ message ServerMessage {
|
|||
oneof msg {
|
||||
Connected connected = 2;
|
||||
Disconnected disconnected = 3;
|
||||
DeviceAdded device_added = 4;
|
||||
DeviceRemoved device_removed = 5;
|
||||
DeviceResumed device_resumed = 6;
|
||||
DeviceSuspended device_suspended = 7;
|
||||
SeatAdded seat_added = 4;
|
||||
SeatRemoved seat_removed = 5;
|
||||
DeviceAdded device_added = 6;
|
||||
DeviceRemoved device_removed = 7;
|
||||
DeviceResumed device_resumed = 8;
|
||||
DeviceSuspended device_suspended = 9;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ ei_device_set_state(struct ei_device *device,
|
|||
{
|
||||
enum ei_device_state old_state = device->state;
|
||||
device->state = state;
|
||||
log_debug(ei_device_get_context(device), "device %d: %s → %s\n",
|
||||
log_debug(ei_device_get_context(device), "device %#x: %s → %s\n",
|
||||
device->id, ei_device_state_to_string(old_state),
|
||||
ei_device_state_to_string(state));
|
||||
}
|
||||
|
|
@ -60,6 +60,19 @@ ei_device_set_state(struct ei_device *device,
|
|||
static void
|
||||
ei_device_destroy(struct ei_device *device)
|
||||
{
|
||||
struct ei_seat *seat = ei_device_get_seat(device);
|
||||
struct ei_device *d;
|
||||
|
||||
/* If the device was still pending, the client held the only ref to
|
||||
* it. Any other case, the device should've been removed from the
|
||||
* seat by the time we get here. */
|
||||
list_for_each(d, &seat->devices_pending, link) {
|
||||
if (device == d) {
|
||||
list_remove(&d->link);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ei_keymap_unref(device->keymap);
|
||||
free(device->name);
|
||||
}
|
||||
|
|
@ -73,7 +86,7 @@ OBJECT_IMPLEMENT_UNREF(ei_device);
|
|||
static
|
||||
OBJECT_IMPLEMENT_CREATE(ei_device);
|
||||
static
|
||||
OBJECT_IMPLEMENT_PARENT(ei_device, ei);
|
||||
OBJECT_IMPLEMENT_PARENT(ei_device, ei_seat);
|
||||
_public_
|
||||
OBJECT_IMPLEMENT_GETTER(ei_device, name, const char *);
|
||||
_public_
|
||||
|
|
@ -81,27 +94,34 @@ OBJECT_IMPLEMENT_GETTER(ei_device, user_data, void *);
|
|||
_public_
|
||||
OBJECT_IMPLEMENT_SETTER(ei_device, user_data, void *);
|
||||
|
||||
_public_ struct ei_seat *
|
||||
ei_device_get_seat(struct ei_device *device)
|
||||
{
|
||||
return ei_device_parent(device);
|
||||
}
|
||||
|
||||
_public_ struct ei*
|
||||
ei_device_get_context(struct ei_device *device)
|
||||
{
|
||||
assert(device);
|
||||
return ei_device_parent(device);
|
||||
return ei_seat_get_context(ei_device_get_seat(device));
|
||||
}
|
||||
|
||||
_public_
|
||||
struct ei_device *
|
||||
ei_device_new(struct ei *ei)
|
||||
_public_ struct ei_device *
|
||||
ei_device_new(struct ei_seat *seat)
|
||||
{
|
||||
/* device IDs are managed by the client, the server merely accepts
|
||||
* them and fails where they're being reused. */
|
||||
static uint32_t deviceid = 0;
|
||||
struct ei_device *device = ei_device_create(&ei->object);
|
||||
struct ei_device *device = ei_device_create(&seat->object);
|
||||
|
||||
device->capabilities = 0;
|
||||
device->id = ++deviceid;
|
||||
device->id = seat->id | ++deviceid;
|
||||
device->state = EI_DEVICE_STATE_NEW;
|
||||
device->name = xaprintf("unnamed device %d", device->id);
|
||||
|
||||
list_append(&seat->devices_pending, &device->link); /* not a ref! */
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
|
|
@ -552,10 +572,21 @@ ei_touch_up(struct ei_touch *touch)
|
|||
#include "src/util-munit.h"
|
||||
#include "src/util-memfile.h"
|
||||
|
||||
#define FAKE_SEAT(_seat) \
|
||||
struct ei_seat seat_##__LINE__ = { \
|
||||
.id = __LINE__ << 16, \
|
||||
.capabilities = ~0, \
|
||||
.name = "default", \
|
||||
}; \
|
||||
list_init(&seat_##__LINE__.devices); \
|
||||
list_init(&seat_##__LINE__.devices_pending); \
|
||||
struct ei_seat *_seat = &seat_ ## __LINE__;
|
||||
|
||||
|
||||
MUNIT_TEST(test_device_new)
|
||||
{
|
||||
struct ei ei = {0};
|
||||
struct ei_device *d = ei_device_new(&ei);
|
||||
FAKE_SEAT(seat);
|
||||
struct ei_device *d = ei_device_new(seat);
|
||||
|
||||
munit_assert_int(d->id, >, 0);
|
||||
munit_assert_int(d->capabilities, ==, 0);
|
||||
|
|
@ -568,10 +599,10 @@ MUNIT_TEST(test_device_new)
|
|||
|
||||
MUNIT_TEST(test_device_ids)
|
||||
{
|
||||
struct ei ei = {0};
|
||||
_cleanup_ei_device_ struct ei_device *d1 = ei_device_new(&ei);
|
||||
_cleanup_ei_device_ struct ei_device *d2 = ei_device_new(&ei);
|
||||
_cleanup_ei_device_ struct ei_device *d3 = ei_device_new(&ei);
|
||||
FAKE_SEAT(seat);
|
||||
_cleanup_ei_device_ struct ei_device *d1 = ei_device_new(seat);
|
||||
_cleanup_ei_device_ struct ei_device *d2 = ei_device_new(seat);
|
||||
_cleanup_ei_device_ struct ei_device *d3 = ei_device_new(seat);
|
||||
|
||||
munit_assert_int(d1->id, <, d2->id);
|
||||
munit_assert_int(d1->id, <, d3->id);
|
||||
|
|
@ -582,8 +613,8 @@ MUNIT_TEST(test_device_ids)
|
|||
|
||||
MUNIT_TEST(test_device_ref_unref)
|
||||
{
|
||||
struct ei ei = {0};
|
||||
struct ei_device *d = ei_device_new(&ei);
|
||||
FAKE_SEAT(seat);
|
||||
struct ei_device *d = ei_device_new(seat);
|
||||
|
||||
munit_assert_int(d->object.refcount, ==, 1);
|
||||
|
||||
|
|
@ -603,8 +634,8 @@ MUNIT_TEST(test_device_ref_unref)
|
|||
|
||||
MUNIT_TEST(test_device_cap)
|
||||
{
|
||||
struct ei ei = {0};
|
||||
_cleanup_ei_device_ struct ei_device *d = ei_device_new(&ei);
|
||||
FAKE_SEAT(seat);
|
||||
_cleanup_ei_device_ struct ei_device *d = ei_device_new(seat);
|
||||
|
||||
munit_assert(ei_device_configure_capability(d, EI_DEVICE_CAP_POINTER));
|
||||
/* twice is fine */
|
||||
|
|
@ -629,20 +660,21 @@ MUNIT_TEST(test_device_cap)
|
|||
return MUNIT_OK;
|
||||
}
|
||||
|
||||
MUNIT_TEST(test_device_context)
|
||||
MUNIT_TEST(test_device_get_seat)
|
||||
{
|
||||
struct ei ei = {0};
|
||||
_cleanup_ei_device_ struct ei_device *d = ei_device_new(&ei);
|
||||
FAKE_SEAT(seat);
|
||||
_cleanup_ei_device_ struct ei_device *d = ei_device_new(seat);
|
||||
|
||||
munit_assert_ptr_equal(d->object.parent, &ei);
|
||||
munit_assert_ptr_equal(d->object.parent, seat);
|
||||
munit_assert_ptr_equal(ei_device_get_seat(d), seat);
|
||||
|
||||
return MUNIT_OK;
|
||||
}
|
||||
|
||||
MUNIT_TEST(test_device_pointer_ranges)
|
||||
{
|
||||
struct ei ei = {0};
|
||||
_cleanup_ei_device_ struct ei_device *d = ei_device_new(&ei);
|
||||
FAKE_SEAT(seat);
|
||||
_cleanup_ei_device_ struct ei_device *d = ei_device_new(seat);
|
||||
|
||||
/* Missing the cap */
|
||||
ei_device_pointer_configure_range(d, 1920, 1200);
|
||||
|
|
@ -673,8 +705,8 @@ MUNIT_TEST(test_device_pointer_ranges)
|
|||
|
||||
MUNIT_TEST(test_device_touch_ranges)
|
||||
{
|
||||
struct ei ei = {0};
|
||||
_cleanup_ei_device_ struct ei_device *d = ei_device_new(&ei);
|
||||
FAKE_SEAT(seat);
|
||||
_cleanup_ei_device_ struct ei_device *d = ei_device_new(seat);
|
||||
|
||||
/* Missing the cap */
|
||||
ei_device_touch_configure_range(d, 1920, 1200);
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ struct ei {
|
|||
void *backend;
|
||||
enum ei_state state;
|
||||
struct list event_queue;
|
||||
struct list devices;
|
||||
struct list seats;
|
||||
char *name;
|
||||
|
||||
struct {
|
||||
|
|
@ -64,6 +64,18 @@ struct ei {
|
|||
} log;
|
||||
};
|
||||
|
||||
struct ei_seat {
|
||||
struct object object;
|
||||
void *user_data;
|
||||
struct list link;
|
||||
/* devices created by client but not yet added */
|
||||
struct list devices_pending;
|
||||
struct list devices;
|
||||
uint32_t id;
|
||||
uint32_t capabilities;
|
||||
char *name;
|
||||
};
|
||||
|
||||
enum ei_device_state {
|
||||
EI_DEVICE_STATE_NEW,
|
||||
EI_DEVICE_STATE_CONNECTING,
|
||||
|
|
@ -121,6 +133,7 @@ struct ei_event {
|
|||
enum ei_event_type type;
|
||||
struct list link;
|
||||
struct ei_client *client;
|
||||
struct ei_seat *seat; /* NULL if device is non-NULL */
|
||||
struct ei_device *device;
|
||||
};
|
||||
|
||||
|
|
@ -130,12 +143,31 @@ ei_set_connection(struct ei *ei, int fd);
|
|||
void
|
||||
ei_disconnect(struct ei *ei);
|
||||
|
||||
struct ei_seat *
|
||||
ei_seat_new(struct ei *ei, uint32_t id, const char *name,
|
||||
uint32_t capabilities);
|
||||
|
||||
struct ei_device *
|
||||
ei_seat_find_device(struct ei_seat *seat, uint32_t deviceid);
|
||||
|
||||
void
|
||||
ei_seat_remove(struct ei_seat *seat);
|
||||
|
||||
void
|
||||
ei_seat_add_device(struct ei_device *device);
|
||||
|
||||
void
|
||||
ei_seat_remove_device(struct ei_device *device);
|
||||
|
||||
int
|
||||
ei_add_device(struct ei_device *device);
|
||||
|
||||
int
|
||||
ei_remove_device(struct ei_device *device);
|
||||
|
||||
void
|
||||
ei_drop_device(struct ei_device *device);
|
||||
|
||||
int
|
||||
ei_pointer_rel(struct ei_device *device,
|
||||
double x, double y);
|
||||
|
|
@ -173,6 +205,9 @@ ei_device_resumed(struct ei_device *device);
|
|||
void
|
||||
ei_device_set_name(struct ei_device *device, const char *name);
|
||||
|
||||
void
|
||||
ei_device_set_seat(struct ei_device *device, const char *seat);
|
||||
|
||||
void
|
||||
ei_device_set_capabilities(struct ei_device *device,
|
||||
uint32_t capabilities);
|
||||
|
|
|
|||
|
|
@ -36,6 +36,9 @@ void
|
|||
message_free(struct message *msg)
|
||||
{
|
||||
switch (msg->type) {
|
||||
case MESSAGE_SEAT_ADDED:
|
||||
free(msg->seat_added.name);
|
||||
break;
|
||||
case MESSAGE_DEVICE_ADDED:
|
||||
xclose(msg->device_added.keymap_fd);
|
||||
free(msg->device_added.name);
|
||||
|
|
@ -77,6 +80,26 @@ ei_proto_parse_message(struct brei_message *bmsg, size_t *consumed)
|
|||
.type = MESSAGE_DISCONNECTED,
|
||||
};
|
||||
break;
|
||||
case SERVER_MESSAGE__MSG_SEAT_ADDED:
|
||||
{
|
||||
SeatAdded *a = proto->seat_added;
|
||||
*msg = (struct message) {
|
||||
.type = MESSAGE_SEAT_ADDED,
|
||||
.seat_added.seatid = a->seatid,
|
||||
.seat_added.name = xstrdup(a->name),
|
||||
.seat_added.capabilities = a->capabilities,
|
||||
};
|
||||
}
|
||||
break;
|
||||
case SERVER_MESSAGE__MSG_SEAT_REMOVED:
|
||||
{
|
||||
SeatRemoved *r = proto->seat_removed;
|
||||
*msg = (struct message) {
|
||||
.type = MESSAGE_SEAT_REMOVED,
|
||||
.seat_removed.seatid = r->seatid,
|
||||
};
|
||||
}
|
||||
break;
|
||||
case SERVER_MESSAGE__MSG_DEVICE_ADDED:
|
||||
{
|
||||
DeviceAdded *a = proto->device_added;
|
||||
|
|
@ -89,6 +112,7 @@ ei_proto_parse_message(struct brei_message *bmsg, size_t *consumed)
|
|||
.device_added.keymap_type = a->keymap_type,
|
||||
.device_added.keymap_from_server = a->keymap_from_server,
|
||||
.device_added.keymap_size = a->keymap_size,
|
||||
.device_added.seatid = a->seatid,
|
||||
};
|
||||
if (a->keymap_type && a->keymap_from_server)
|
||||
msg->device_added.keymap_fd = brei_message_take_fd(bmsg);
|
||||
|
|
@ -228,6 +252,7 @@ ei_proto_send_add(struct ei *ei, struct ei_device *device)
|
|||
{
|
||||
ClientMessage msg = CLIENT_MESSAGE__INIT;
|
||||
AddDevice add = ADD_DEVICE__INIT;
|
||||
struct ei_seat *seat = ei_device_get_seat(device);
|
||||
|
||||
add.deviceid = device->id;
|
||||
add.name = device->name;
|
||||
|
|
@ -246,6 +271,7 @@ ei_proto_send_add(struct ei *ei, struct ei_device *device)
|
|||
add.keymap_size = ei_keymap_get_size(keymap);
|
||||
fd[0] = ei_keymap_get_fd(keymap);
|
||||
}
|
||||
add.seat = seat->id;
|
||||
|
||||
msg.add_device = &add;
|
||||
msg.msg_case = CLIENT_MESSAGE__MSG_ADD_DEVICE;
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@
|
|||
enum message_type {
|
||||
MESSAGE_CONNECTED = 1,
|
||||
MESSAGE_DISCONNECTED,
|
||||
MESSAGE_SEAT_ADDED,
|
||||
MESSAGE_SEAT_REMOVED,
|
||||
MESSAGE_DEVICE_ADDED,
|
||||
MESSAGE_DEVICE_REMOVED,
|
||||
MESSAGE_DEVICE_RESUMED,
|
||||
|
|
@ -47,6 +49,8 @@ message_type_to_string(enum message_type type)
|
|||
switch(type) {
|
||||
CASE_RETURN_STRING(MESSAGE_CONNECTED);
|
||||
CASE_RETURN_STRING(MESSAGE_DISCONNECTED);
|
||||
CASE_RETURN_STRING(MESSAGE_SEAT_ADDED);
|
||||
CASE_RETURN_STRING(MESSAGE_SEAT_REMOVED);
|
||||
CASE_RETURN_STRING(MESSAGE_DEVICE_ADDED);
|
||||
CASE_RETURN_STRING(MESSAGE_DEVICE_REMOVED);
|
||||
CASE_RETURN_STRING(MESSAGE_DEVICE_RESUMED);
|
||||
|
|
@ -64,6 +68,14 @@ struct message {
|
|||
struct message_disconnected {
|
||||
uint8_t pad; /* no data */
|
||||
} disconnected;
|
||||
struct message_seat_added {
|
||||
uint32_t seatid;
|
||||
char *name;
|
||||
uint32_t capabilities;
|
||||
} seat_added;
|
||||
struct message_seat_removed {
|
||||
uint32_t seatid;
|
||||
} seat_removed;
|
||||
struct message_device_added {
|
||||
uint32_t deviceid;
|
||||
char *name;
|
||||
|
|
@ -72,6 +84,7 @@ struct message {
|
|||
bool keymap_from_server;
|
||||
int keymap_fd;
|
||||
size_t keymap_size;
|
||||
uint32_t seatid;
|
||||
} device_added;
|
||||
struct message_device_removed {
|
||||
uint32_t deviceid;
|
||||
|
|
|
|||
129
src/libei-seat.c
Normal file
129
src/libei-seat.c
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
* Copyright © 2020 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "util-bits.h"
|
||||
#include "util-macros.h"
|
||||
#include "util-mem.h"
|
||||
#include "util-io.h"
|
||||
#include "util-strings.h"
|
||||
|
||||
#include "libei-private.h"
|
||||
|
||||
static void
|
||||
ei_seat_destroy(struct ei_seat *seat)
|
||||
{
|
||||
free(seat->name);
|
||||
}
|
||||
|
||||
_public_
|
||||
OBJECT_IMPLEMENT_REF(ei_seat);
|
||||
_public_
|
||||
OBJECT_IMPLEMENT_UNREF(ei_seat);
|
||||
#define _cleanup_ei_seat_ _cleanup_(ei_seat_cleanup)
|
||||
|
||||
static
|
||||
OBJECT_IMPLEMENT_CREATE(ei_seat);
|
||||
static
|
||||
OBJECT_IMPLEMENT_PARENT(ei_seat, ei);
|
||||
_public_
|
||||
OBJECT_IMPLEMENT_GETTER(ei_seat, name, const char *);
|
||||
_public_
|
||||
OBJECT_IMPLEMENT_SETTER(ei_seat, user_data, void *);
|
||||
|
||||
_public_ struct ei*
|
||||
ei_seat_get_context(struct ei_seat *seat)
|
||||
{
|
||||
assert(seat);
|
||||
return ei_seat_parent(seat);
|
||||
}
|
||||
|
||||
struct ei_seat *
|
||||
ei_seat_new(struct ei *ei, uint32_t id, const char *name, uint32_t capabilities)
|
||||
{
|
||||
struct ei_seat *seat = ei_seat_create(&ei->object);
|
||||
|
||||
seat->name = xstrdup(name);
|
||||
seat->id = id;
|
||||
seat->capabilities = capabilities;
|
||||
|
||||
list_init(&seat->devices);
|
||||
list_init(&seat->devices_pending);
|
||||
list_init(&seat->link);
|
||||
|
||||
return seat; /* ref owned by caller */
|
||||
}
|
||||
|
||||
void
|
||||
ei_seat_remove(struct ei_seat *seat)
|
||||
{
|
||||
struct ei_device *d, *tmp;
|
||||
|
||||
/* If the server disconnects us before processing a new device, we
|
||||
* need to clean this up in the library */
|
||||
list_for_each_safe(d, tmp, &seat->devices, link) {
|
||||
ei_drop_device(d);
|
||||
}
|
||||
|
||||
list_remove(&seat->link);
|
||||
list_init(&seat->link);
|
||||
}
|
||||
|
||||
void
|
||||
ei_seat_add_device(struct ei_device *device)
|
||||
{
|
||||
struct ei_seat *seat = ei_device_get_seat(device);
|
||||
|
||||
/* the seat owns the ref to the device */
|
||||
ei_device_ref(device);
|
||||
/* remove from pending list */
|
||||
list_remove(&device->link);
|
||||
list_append(&seat->devices, &device->link);
|
||||
}
|
||||
|
||||
struct ei_device *
|
||||
ei_seat_find_device(struct ei_seat *seat, uint32_t deviceid)
|
||||
{
|
||||
struct ei_device *device;
|
||||
|
||||
list_for_each(device, &seat->devices, link) {
|
||||
if (device->id == deviceid)
|
||||
return device;
|
||||
}
|
||||
|
||||
list_for_each(device, &seat->devices_pending, link) {
|
||||
if (device->id == deviceid)
|
||||
return device;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
ei_seat_remove_device(struct ei_device *device)
|
||||
{
|
||||
list_remove(&device->link);
|
||||
ei_device_unref(device);
|
||||
}
|
||||
233
src/libei.c
233
src/libei.c
|
|
@ -45,6 +45,8 @@ ei_event_type_to_string(enum ei_event_type type)
|
|||
switch(type) {
|
||||
CASE_RETURN_STRING(EI_EVENT_CONNECT);
|
||||
CASE_RETURN_STRING(EI_EVENT_DISCONNECT);
|
||||
CASE_RETURN_STRING(EI_EVENT_SEAT_ADDED);
|
||||
CASE_RETURN_STRING(EI_EVENT_SEAT_REMOVED);
|
||||
CASE_RETURN_STRING(EI_EVENT_DEVICE_ADDED);
|
||||
CASE_RETURN_STRING(EI_EVENT_DEVICE_REMOVED);
|
||||
CASE_RETURN_STRING(EI_EVENT_DEVICE_SUSPENDED);
|
||||
|
|
@ -60,6 +62,8 @@ ei_event_destroy(struct ei_event *event)
|
|||
switch (event->type) {
|
||||
case EI_EVENT_CONNECT:
|
||||
case EI_EVENT_DISCONNECT:
|
||||
case EI_EVENT_SEAT_ADDED:
|
||||
case EI_EVENT_SEAT_REMOVED:
|
||||
case EI_EVENT_DEVICE_ADDED:
|
||||
case EI_EVENT_DEVICE_REMOVED:
|
||||
case EI_EVENT_DEVICE_SUSPENDED:
|
||||
|
|
@ -69,6 +73,7 @@ ei_event_destroy(struct ei_event *event)
|
|||
assert(!"destroy not implemented for this type");
|
||||
}
|
||||
ei_device_unref(event->device);
|
||||
ei_seat_unref(event->seat);
|
||||
}
|
||||
|
||||
static
|
||||
|
|
@ -82,6 +87,39 @@ OBJECT_IMPLEMENT_GETTER(ei_event, type, enum ei_event_type);
|
|||
_public_
|
||||
OBJECT_IMPLEMENT_GETTER(ei_event, device, struct ei_device*);
|
||||
|
||||
_public_ struct ei_seat *
|
||||
ei_event_get_seat(struct ei_event *event)
|
||||
{
|
||||
return event->device ? ei_device_get_seat(event->device) : event->seat;
|
||||
}
|
||||
|
||||
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 (seat->id == seatid)
|
||||
return seat;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct ei_device *
|
||||
ei_find_device(struct ei *ei, uint32_t deviceid)
|
||||
{
|
||||
struct ei_seat *seat;
|
||||
|
||||
list_for_each(seat, &ei->seats, link) {
|
||||
struct ei_device *device = ei_seat_find_device(seat, deviceid);
|
||||
if (device)
|
||||
return device;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
ei_destroy(struct ei *ei)
|
||||
{
|
||||
|
|
@ -117,7 +155,7 @@ ei_new(void *user_data)
|
|||
|
||||
ei->state = EI_STATE_NEW;
|
||||
list_init(&ei->event_queue);
|
||||
list_init(&ei->devices);
|
||||
list_init(&ei->seats);
|
||||
|
||||
ei_log_set_handler(ei, NULL);
|
||||
ei_log_set_priority(ei, EI_LOG_PRIORITY_INFO);
|
||||
|
|
@ -170,6 +208,30 @@ queue_disconnect_event(struct ei *ei)
|
|||
queue_event(ei, e);
|
||||
}
|
||||
|
||||
static void
|
||||
queue_seat_added_event(struct ei_seat *seat)
|
||||
{
|
||||
struct ei *ei= ei_seat_get_context(seat);
|
||||
|
||||
struct ei_event *e = ei_event_create(&ei->object);
|
||||
e->type = EI_EVENT_SEAT_ADDED;
|
||||
e->seat = ei_seat_ref(seat);
|
||||
|
||||
queue_event(ei, e);
|
||||
}
|
||||
|
||||
static void
|
||||
queue_seat_removed_event(struct ei_seat *seat)
|
||||
{
|
||||
struct ei *ei= ei_seat_get_context(seat);
|
||||
|
||||
struct ei_event *e = ei_event_create(&ei->object);
|
||||
e->type = EI_EVENT_SEAT_REMOVED;
|
||||
e->seat = ei_seat_ref(seat);
|
||||
|
||||
queue_event(ei, e);
|
||||
}
|
||||
|
||||
static void
|
||||
queue_device_added_event(struct ei_device *device)
|
||||
{
|
||||
|
|
@ -334,7 +396,7 @@ connection_send_touch_up(struct ei *ei, struct ei_device *device, uint32_t tid)
|
|||
return ei_proto_send_touch_up(ei, device, tid);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
ei_drop_device(struct ei_device *device)
|
||||
{
|
||||
switch (device->state) {
|
||||
|
|
@ -349,8 +411,15 @@ ei_drop_device(struct ei_device *device)
|
|||
queue_device_removed_event(device);
|
||||
break;
|
||||
}
|
||||
list_remove(&device->link);
|
||||
ei_device_unref(device);
|
||||
ei_seat_remove_device(device);
|
||||
}
|
||||
|
||||
static void
|
||||
ei_drop_seat(struct ei_seat *seat)
|
||||
{
|
||||
queue_seat_removed_event(seat);
|
||||
list_remove(&seat->link);
|
||||
ei_seat_unref(seat);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -366,13 +435,18 @@ ei_disconnect(struct ei *ei)
|
|||
ei_device_remove() may call ei_disconnect() on a socket error */
|
||||
ei->state = EI_STATE_DISCONNECTING;
|
||||
|
||||
struct ei_device *d, *tmp;
|
||||
list_for_each_safe(d, tmp, &ei->devices, link) {
|
||||
/* remove the device */
|
||||
ei_device_remove(d);
|
||||
/* And pretend to process the removed message from the
|
||||
* server */
|
||||
ei_drop_device(d);
|
||||
struct ei_seat *seat, *tmps;
|
||||
list_for_each_safe(seat, tmps, &ei->seats, link) {
|
||||
struct ei_device *d, *tmpd;
|
||||
list_for_each_safe(d, tmpd, &seat->devices, link) {
|
||||
/* remove the device */
|
||||
ei_device_remove(d);
|
||||
/* And pretend to process the removed message from
|
||||
* the server */
|
||||
ei_drop_device(d);
|
||||
}
|
||||
ei_seat_remove(seat);
|
||||
ei_drop_seat(seat);
|
||||
}
|
||||
|
||||
if (state != EI_STATE_NEW) {
|
||||
|
|
@ -395,8 +469,7 @@ ei_add_device(struct ei_device *device)
|
|||
return rc;
|
||||
}
|
||||
|
||||
ei_device_ref(device);
|
||||
list_append(&ei->devices, &device->link);
|
||||
ei_seat_add_device(device);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -412,51 +485,88 @@ ei_remove_device(struct ei_device *device)
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
handle_msg_seat_added(struct ei *ei, uint32_t seatid,
|
||||
const char *name, uint32_t capabilities)
|
||||
{
|
||||
log_debug(ei, "Added seat %#x '%s' with caps %#x\n",
|
||||
seatid, name, capabilities);
|
||||
|
||||
struct ei_seat *seat = ei_seat_new(ei, seatid, name, capabilities);
|
||||
|
||||
list_append(&ei->seats, &seat->link);
|
||||
|
||||
queue_seat_added_event(seat);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
handle_msg_seat_removed(struct ei *ei, uint32_t seatid)
|
||||
{
|
||||
log_debug(ei, "Removed seat %#x\n", seatid);
|
||||
|
||||
struct ei_seat *seat = ei_find_seat(ei, seatid);
|
||||
if (seat) {
|
||||
ei_seat_remove(seat);
|
||||
queue_seat_removed_event(seat);
|
||||
ei_seat_unref(seat);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
handle_msg_device_added(struct ei *ei, uint32_t deviceid,
|
||||
const char *name, uint32_t capabilities,
|
||||
bool keymap_from_server, enum ei_keymap_type keymap_type,
|
||||
int keymap_fd, size_t keymap_sz)
|
||||
int keymap_fd, size_t keymap_sz,
|
||||
uint32_t seatid)
|
||||
{
|
||||
struct ei_device *d;
|
||||
struct ei_seat *seat = ei_find_seat(ei, seatid);
|
||||
|
||||
list_for_each(d, &ei->devices, link) {
|
||||
if (d->id == deviceid) {
|
||||
ei_device_set_name(d, name);
|
||||
ei_device_set_capabilities(d, capabilities);
|
||||
if (keymap_from_server)
|
||||
ei_device_set_keymap(d, keymap_type, keymap_fd, keymap_sz);
|
||||
ei_device_added(d);
|
||||
|
||||
log_debug(ei, "Added device %d '%s' caps: %s%s%s%s\n", deviceid, name,
|
||||
ei_device_has_capability(d, EI_DEVICE_CAP_POINTER) ? "p" : "",
|
||||
ei_device_has_capability(d, EI_DEVICE_CAP_POINTER_ABSOLUTE) ? "a" : "",
|
||||
ei_device_has_capability(d, EI_DEVICE_CAP_KEYBOARD) ? "k" : "",
|
||||
ei_device_has_capability(d, EI_DEVICE_CAP_TOUCH) ? "t" : "");
|
||||
|
||||
queue_device_added_event(d);
|
||||
return 0;
|
||||
}
|
||||
if (!seat) {
|
||||
log_bug(ei, "Invalid seat id %d for device %s (%d)\n",
|
||||
seatid, name, deviceid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct ei_device *device = ei_seat_find_device(seat, deviceid);
|
||||
|
||||
/* 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 (!device)
|
||||
return 0;
|
||||
|
||||
ei_device_set_name(device, name);
|
||||
ei_device_set_capabilities(device, capabilities);
|
||||
if (keymap_from_server)
|
||||
ei_device_set_keymap(device, keymap_type,
|
||||
keymap_fd, keymap_sz);
|
||||
ei_device_added(device);
|
||||
|
||||
log_debug(ei,
|
||||
"Added device %d '%s' caps: %s%s%s%s seat: %s\n",
|
||||
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));
|
||||
|
||||
queue_device_added_event(device);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
handle_msg_device_removed(struct ei *ei, uint32_t deviceid)
|
||||
{
|
||||
struct ei_device *d;
|
||||
|
||||
log_debug(ei, "Removed device %d\n", deviceid);
|
||||
|
||||
list_for_each(d, &ei->devices, link) {
|
||||
if (d->id == deviceid) {
|
||||
ei_drop_device(d);
|
||||
break;
|
||||
}
|
||||
struct ei_device *device = ei_find_device(ei, deviceid);
|
||||
if (device) {
|
||||
ei_drop_device(device);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -465,16 +575,12 @@ handle_msg_device_removed(struct ei *ei, uint32_t deviceid)
|
|||
static int
|
||||
handle_msg_resumed(struct ei *ei, uint32_t deviceid)
|
||||
{
|
||||
struct ei_device *d;
|
||||
|
||||
log_debug(ei, "Resumed device %d\n", deviceid);
|
||||
|
||||
list_for_each(d, &ei->devices, link) {
|
||||
if (d->id == deviceid) {
|
||||
ei_device_resumed(d);
|
||||
queue_resumed_event(d);
|
||||
break;
|
||||
}
|
||||
struct ei_device *device = ei_find_device(ei, deviceid);
|
||||
if (device) {
|
||||
ei_device_resumed(device);
|
||||
queue_resumed_event(device);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -483,16 +589,12 @@ handle_msg_resumed(struct ei *ei, uint32_t deviceid)
|
|||
static int
|
||||
handle_msg_suspended(struct ei *ei, uint32_t deviceid)
|
||||
{
|
||||
struct ei_device *d;
|
||||
|
||||
log_debug(ei, "Suspended device %d\n", deviceid);
|
||||
|
||||
list_for_each(d, &ei->devices, link) {
|
||||
if (d->id == deviceid) {
|
||||
ei_device_suspended(d);
|
||||
queue_suspended_event(d);
|
||||
break;
|
||||
}
|
||||
struct ei_device *device = ei_find_device(ei, deviceid);
|
||||
if (device) {
|
||||
ei_device_suspended(device);
|
||||
queue_suspended_event(device);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -600,6 +702,8 @@ connection_new_handle_msg(struct ei *ei, struct message *msg)
|
|||
switch (msg->type) {
|
||||
case MESSAGE_CONNECTED:
|
||||
case MESSAGE_DISCONNECTED:
|
||||
case MESSAGE_SEAT_ADDED:
|
||||
case MESSAGE_SEAT_REMOVED:
|
||||
case MESSAGE_DEVICE_ADDED:
|
||||
case MESSAGE_DEVICE_REMOVED:
|
||||
case MESSAGE_DEVICE_RESUMED:
|
||||
|
|
@ -624,6 +728,8 @@ connection_connecting_handle_msg(struct ei *ei, struct message *msg)
|
|||
case MESSAGE_DISCONNECTED:
|
||||
rc = -ECANCELED;
|
||||
break;
|
||||
case MESSAGE_SEAT_ADDED:
|
||||
case MESSAGE_SEAT_REMOVED:
|
||||
case MESSAGE_DEVICE_ADDED:
|
||||
case MESSAGE_DEVICE_REMOVED:
|
||||
case MESSAGE_DEVICE_RESUMED:
|
||||
|
|
@ -647,6 +753,15 @@ connection_connected_handle_msg(struct ei *ei, struct message *msg)
|
|||
case MESSAGE_DISCONNECTED:
|
||||
rc = -ECANCELED;
|
||||
break;
|
||||
case MESSAGE_SEAT_ADDED:
|
||||
rc = handle_msg_seat_added(ei,
|
||||
msg->seat_added.seatid,
|
||||
msg->seat_added.name,
|
||||
msg->seat_added.capabilities);
|
||||
break;
|
||||
case MESSAGE_SEAT_REMOVED:
|
||||
rc = handle_msg_seat_removed(ei, msg->seat_removed.seatid);
|
||||
break;
|
||||
case MESSAGE_DEVICE_ADDED:
|
||||
rc = handle_msg_device_added(ei,
|
||||
msg->device_added.deviceid,
|
||||
|
|
@ -655,7 +770,8 @@ connection_connected_handle_msg(struct ei *ei, struct message *msg)
|
|||
msg->device_added.keymap_from_server,
|
||||
msg->device_added.keymap_type,
|
||||
msg->device_added.keymap_fd,
|
||||
msg->device_added.keymap_size);
|
||||
msg->device_added.keymap_size,
|
||||
msg->device_added.seatid);
|
||||
break;
|
||||
case MESSAGE_DEVICE_REMOVED:
|
||||
rc = handle_msg_device_removed(ei, msg->device_removed.deviceid);
|
||||
|
|
@ -698,7 +814,8 @@ connection_message_callback(struct brei_message *bmsg, void *userdata)
|
|||
break;
|
||||
case EI_STATE_DISCONNECTING:
|
||||
case EI_STATE_DISCONNECTED:
|
||||
abort();
|
||||
assert(!"Protocol error: message received while disconnecting\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (rc < 0)
|
||||
|
|
@ -783,7 +900,7 @@ MUNIT_TEST(test_init_unref)
|
|||
|
||||
munit_assert_int(ei->state, ==, EI_STATE_NEW);
|
||||
munit_assert(list_empty(&ei->event_queue));
|
||||
munit_assert(list_empty(&ei->devices));
|
||||
munit_assert(list_empty(&ei->seats));
|
||||
|
||||
munit_assert_not_null(ei->sink);
|
||||
|
||||
|
|
|
|||
97
src/libei.h
97
src/libei.h
|
|
@ -64,6 +64,21 @@ struct ei;
|
|||
*/
|
||||
struct ei_device;
|
||||
|
||||
/**
|
||||
* @struct ei_seat
|
||||
*
|
||||
* A logical seat for a group of devices. Seats are provided by the EIS
|
||||
* implementation, devices may be added to a seat. The hierarchy of objects
|
||||
* looks like this:
|
||||
* <pre>
|
||||
* ei ---- ei_seat one ---- ei_device 1
|
||||
* \ \
|
||||
* \ --- ei device 2
|
||||
* --- ei_seat two --- ei device 3
|
||||
* </pre>
|
||||
*/
|
||||
struct ei_seat;
|
||||
|
||||
/**
|
||||
* @struct ei_event
|
||||
*
|
||||
|
|
@ -162,6 +177,29 @@ enum ei_event_type {
|
|||
*/
|
||||
EI_EVENT_DISCONNECT,
|
||||
|
||||
/**
|
||||
* The server has added a seat available to this client.
|
||||
*
|
||||
* libei guarantees that any seat added has a corresponding @ref
|
||||
* EI_EVENT_SEAT_REMOVED event before @ref EI_EVENT_DISCONNECT.
|
||||
* libei guarantees that any device in this seat generates a @ref
|
||||
* EI_EVENT_DEVICE_REMOVED event before the @ref
|
||||
* EI_EVENT_SEAT_REMOVED event.
|
||||
*/
|
||||
EI_EVENT_SEAT_ADDED,
|
||||
|
||||
/**
|
||||
* The server has removed a seat previously available to this
|
||||
* client. The caller should release the struct @ref ei_seat and
|
||||
* all its associated resources. No devices can be created through
|
||||
* this seat anymore.
|
||||
*
|
||||
* libei guarantees that any device in this seat generates a @ref
|
||||
* EI_EVENT_DEVICE_REMOVED event before the @ref
|
||||
* EI_EVENT_SEAT_REMOVED event.
|
||||
*/
|
||||
EI_EVENT_SEAT_REMOVED,
|
||||
|
||||
/**
|
||||
* The server has added a device for this client. The capabilities
|
||||
* of the device may not match the requested capabilities - it is up
|
||||
|
|
@ -418,6 +456,25 @@ ei_peek_event(struct ei *ei);
|
|||
struct ei_event *
|
||||
ei_event_unref(struct ei_event *event);
|
||||
|
||||
const char *
|
||||
ei_seat_get_name(struct ei_seat *seat);
|
||||
|
||||
bool
|
||||
ei_seat_has_capability(struct ei_seat *seat,
|
||||
enum ei_device_capability cap);
|
||||
|
||||
struct ei_seat *
|
||||
ei_seat_ref(struct ei_seat *seat);
|
||||
|
||||
struct ei_seat *
|
||||
ei_seat_unref(struct ei_seat *seat);
|
||||
|
||||
/**
|
||||
* Return the struct @ref ei context this seat is associated with.
|
||||
*/
|
||||
struct ei *
|
||||
ei_seat_get_context(struct ei_seat *seat);
|
||||
|
||||
/**
|
||||
* @return the type of this event
|
||||
*/
|
||||
|
|
@ -462,10 +519,10 @@ struct ei_device *
|
|||
ei_device_unref(struct ei_device *device);
|
||||
|
||||
/**
|
||||
* Create a new device. This device is a proxy representing the server's
|
||||
* device and should be used for initial device configuration. It does not
|
||||
* represent the server-created device until the @ref EI_EVENT_DEVICE_ADDED
|
||||
* for this device has been received.
|
||||
* Create a new device in the given seat. This device is a proxy
|
||||
* representing the server's device and should be used for initial device
|
||||
* configuration. It does not represent the server-created device until the
|
||||
* @ref EI_EVENT_DEVICE_ADDED for this device has been received.
|
||||
*
|
||||
* Use the configure API (e.g. ei_device_configure_capability()) to set up
|
||||
* the device, then call ei_device_add() to request creation of the device
|
||||
|
|
@ -474,7 +531,25 @@ ei_device_unref(struct ei_device *device);
|
|||
* The returned object must be released by the caller with ei_event_unref()
|
||||
*/
|
||||
struct ei_device *
|
||||
ei_device_new(struct ei *ei);
|
||||
ei_device_new(struct ei_seat *ei_seat);
|
||||
|
||||
struct ei_seat *
|
||||
ei_device_get_seat(struct ei_device *device);
|
||||
|
||||
/**
|
||||
* Set a custom data pointer for this context. libei will not look at or
|
||||
* modify the pointer. Use ei_seat_get_user_data() to retrieve a
|
||||
* previously set user data.
|
||||
*/
|
||||
void
|
||||
ei_seat_set_user_data(struct ei_seat *seat, void *user_data);
|
||||
|
||||
/**
|
||||
* Return the custom data pointer for this context. libei will not look at or
|
||||
* modify the pointer. Use ei_seat_get_user_data() to change the user data.
|
||||
*/
|
||||
void *
|
||||
ei_seat_get_user_data(struct ei_seat *seat);
|
||||
|
||||
/**
|
||||
* Set a custom data pointer for this context. libei will not look at or
|
||||
|
|
@ -991,6 +1066,18 @@ ei_touch_get_user_data(struct ei_touch *touch);
|
|||
struct ei_device *
|
||||
ei_touch_get_device(struct ei_touch *touch);
|
||||
|
||||
/**
|
||||
* Return the seat from this event.
|
||||
*
|
||||
* For events of type @ref EI_EVENT_CONNECT and @ref EI_EVENT_DISCONNECT,
|
||||
* this function returns NULL.
|
||||
*
|
||||
* This does not increase the refcount of the seat. Use eis_seat_ref()
|
||||
* to keep a reference beyond the immediate scope.
|
||||
*/
|
||||
struct ei_seat *
|
||||
ei_event_get_seat(struct ei_event *event);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -82,6 +82,18 @@ client_send_connect(struct eis_client *client)
|
|||
return eis_proto_send_connect(client);
|
||||
}
|
||||
|
||||
static int
|
||||
client_send_seat_added(struct eis_client *client, struct eis_seat *seat)
|
||||
{
|
||||
return eis_proto_send_seat_added(client, seat);
|
||||
}
|
||||
|
||||
static int
|
||||
client_send_seat_removed(struct eis_client *client, struct eis_seat *seat)
|
||||
{
|
||||
return eis_proto_send_seat_removed(client, seat);
|
||||
}
|
||||
|
||||
static int
|
||||
client_send_device_added(struct eis_client *client, struct eis_device *device)
|
||||
{
|
||||
|
|
@ -138,9 +150,9 @@ eis_client_disconnect(struct eis_client *client)
|
|||
case EIS_CLIENT_STATE_CONNECTING:
|
||||
case EIS_CLIENT_STATE_CONNECTED:
|
||||
{
|
||||
struct eis_device *d, *tmp;
|
||||
list_for_each_safe(d, tmp, &client->devices, link)
|
||||
eis_device_disconnect(d);
|
||||
struct eis_seat *s, *tmp;
|
||||
list_for_each_safe(s, tmp, &client->seats, link)
|
||||
eis_seat_remove(s);
|
||||
}
|
||||
eis_queue_disconnect_event(client);
|
||||
_fallthrough_;
|
||||
|
|
@ -160,11 +172,24 @@ client_new_device(struct eis_client *client,
|
|||
const struct dimensions *dim_pointer,
|
||||
const struct dimensions *dim_touch,
|
||||
enum eis_keymap_type keymap_type,
|
||||
int keymap_fd, size_t keymap_sz)
|
||||
int keymap_fd, size_t keymap_sz,
|
||||
uint32_t seatid)
|
||||
{
|
||||
struct eis_seat *s, *seat = NULL;
|
||||
|
||||
list_for_each(s, &client->seats, link) {
|
||||
if (s->id == seatid) {
|
||||
seat = s;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (seat == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
/* Check for duplicate IDs */
|
||||
struct eis_device *d;
|
||||
list_for_each(d, &client->devices, link) {
|
||||
list_for_each(d, &seat->devices, link) {
|
||||
if (d->id == id)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -176,8 +201,8 @@ client_new_device(struct eis_client *client,
|
|||
bit(EIS_DEVICE_CAP_TOUCH)))
|
||||
return -EINVAL;
|
||||
|
||||
struct eis_device *device = eis_device_new(client, id, name, capabilities);
|
||||
list_append(&client->devices, &device->link);
|
||||
struct eis_device *device = eis_device_new(seat, id, name, capabilities);
|
||||
list_append(&seat->devices, &device->link);
|
||||
|
||||
if (flag_is_set(capabilities, EIS_DEVICE_CAP_POINTER_ABSOLUTE))
|
||||
eis_device_set_pointer_range(device, dim_pointer->width,
|
||||
|
|
@ -190,12 +215,13 @@ client_new_device(struct eis_client *client,
|
|||
eis_device_set_client_keymap(device, keymap_type, keymap_fd, keymap_sz);
|
||||
|
||||
log_debug(eis_client_parent(client),
|
||||
"New device %d '%s' caps: %s%s%s%s\n",
|
||||
"New device %#x '%s' caps: %s%s%s%s seat: %s\n",
|
||||
id, name,
|
||||
eis_device_has_capability(device, EIS_DEVICE_CAP_POINTER) ? "p" : "",
|
||||
eis_device_has_capability(device, EIS_DEVICE_CAP_POINTER_ABSOLUTE) ? "a" : "",
|
||||
eis_device_has_capability(device, EIS_DEVICE_CAP_KEYBOARD) ? "k" : "",
|
||||
eis_device_has_capability(device, EIS_DEVICE_CAP_TOUCH) ? "t" : "");
|
||||
eis_device_has_capability(device, EIS_DEVICE_CAP_TOUCH) ? "t" : "",
|
||||
eis_seat_get_name(seat));
|
||||
|
||||
eis_queue_added_event(device);
|
||||
|
||||
|
|
@ -205,12 +231,16 @@ client_new_device(struct eis_client *client,
|
|||
static int
|
||||
client_remove_device(struct eis_client *client, uint32_t deviceid)
|
||||
{
|
||||
struct eis_device *device;
|
||||
struct eis_seat *seat;
|
||||
|
||||
list_for_each(device, &client->devices, link) {
|
||||
if (device->id == deviceid) {
|
||||
eis_queue_removed_event(device);
|
||||
break;
|
||||
list_for_each(seat, &client->seats, link) {
|
||||
struct eis_device *device;
|
||||
|
||||
list_for_each(device, &seat->devices, link) {
|
||||
if (device->id == deviceid) {
|
||||
eis_queue_removed_event(device);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
|
@ -220,11 +250,15 @@ static int
|
|||
client_pointer_rel(struct eis_client *client, uint32_t deviceid,
|
||||
double x, double y)
|
||||
{
|
||||
struct eis_device *device;
|
||||
struct eis_seat *seat;
|
||||
|
||||
list_for_each(device, &client->devices, link) {
|
||||
if (device->id == deviceid) {
|
||||
return eis_device_pointer_rel(device, x, y);
|
||||
list_for_each(seat, &client->seats, link) {
|
||||
struct eis_device *device;
|
||||
|
||||
list_for_each(device, &seat->devices, link) {
|
||||
if (device->id == deviceid) {
|
||||
return eis_device_pointer_rel(device, x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
return -EINVAL;
|
||||
|
|
@ -234,11 +268,15 @@ static int
|
|||
client_pointer_abs(struct eis_client *client, uint32_t deviceid,
|
||||
double x, double y)
|
||||
{
|
||||
struct eis_device *device;
|
||||
struct eis_seat *seat;
|
||||
|
||||
list_for_each(device, &client->devices, link) {
|
||||
if (device->id == deviceid) {
|
||||
return eis_device_pointer_abs(device, x, y);
|
||||
list_for_each(seat, &client->seats, link) {
|
||||
struct eis_device *device;
|
||||
|
||||
list_for_each(device, &seat->devices, link) {
|
||||
if (device->id == deviceid) {
|
||||
return eis_device_pointer_abs(device, x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
return -EINVAL;
|
||||
|
|
@ -248,11 +286,15 @@ static int
|
|||
client_pointer_button(struct eis_client *client, uint32_t deviceid,
|
||||
uint32_t button, bool state)
|
||||
{
|
||||
struct eis_device *device;
|
||||
struct eis_seat *seat;
|
||||
|
||||
list_for_each(device, &client->devices, link) {
|
||||
if (device->id == deviceid) {
|
||||
return eis_device_pointer_button(device, button, state);
|
||||
list_for_each(seat, &client->seats, link) {
|
||||
struct eis_device *device;
|
||||
|
||||
list_for_each(device, &seat->devices, link) {
|
||||
if (device->id == deviceid) {
|
||||
return eis_device_pointer_button(device, button, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
return -EINVAL;
|
||||
|
|
@ -262,11 +304,15 @@ static int
|
|||
client_keyboard_key(struct eis_client *client, uint32_t deviceid,
|
||||
uint32_t key, bool state)
|
||||
{
|
||||
struct eis_device *device;
|
||||
struct eis_seat *seat;
|
||||
|
||||
list_for_each(device, &client->devices, link) {
|
||||
if (device->id == deviceid) {
|
||||
return eis_device_keyboard_key(device, key, state);
|
||||
list_for_each(seat, &client->seats, link) {
|
||||
struct eis_device *device;
|
||||
|
||||
list_for_each(device, &seat->devices, link) {
|
||||
if (device->id == deviceid) {
|
||||
return eis_device_keyboard_key(device, key, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
return -EINVAL;
|
||||
|
|
@ -277,12 +323,16 @@ client_touch(struct eis_client *client, uint32_t deviceid,
|
|||
uint32_t touchid, bool is_down, bool is_up,
|
||||
double x, double y)
|
||||
{
|
||||
struct eis_device *device;
|
||||
struct eis_seat *seat;
|
||||
|
||||
list_for_each(device, &client->devices, link) {
|
||||
if (device->id == deviceid) {
|
||||
return eis_device_touch(device, touchid,
|
||||
is_down, is_up, x, y);
|
||||
list_for_each(seat, &client->seats, link) {
|
||||
struct eis_device *device;
|
||||
|
||||
list_for_each(device, &seat->devices, link) {
|
||||
if (device->id == deviceid) {
|
||||
return eis_device_touch(device, touchid,
|
||||
is_down, is_up, x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
return -EINVAL;
|
||||
|
|
@ -418,7 +468,8 @@ client_connected_handle_msg(struct eis_client *client,
|
|||
&msg->add_device.dim_touch,
|
||||
msg->add_device.keymap_type,
|
||||
msg->add_device.keymap_fd,
|
||||
msg->add_device.keymap_size);
|
||||
msg->add_device.keymap_size,
|
||||
msg->add_device.seat);
|
||||
break;
|
||||
case MESSAGE_REMOVE_DEVICE:
|
||||
rc = client_remove_device(client, msg->remove_device.deviceid);
|
||||
|
|
@ -527,7 +578,8 @@ eis_client_new(struct eis *eis, int fd)
|
|||
struct eis_client *client = eis_client_create(&eis->object);
|
||||
|
||||
client->id = ++client_id;
|
||||
list_init(&client->devices);
|
||||
list_init(&client->seats);
|
||||
list_init(&client->seats_pending);
|
||||
|
||||
struct source *s = source_new(fd, client_dispatch, client);
|
||||
int rc = sink_add_source(eis->sink, s);
|
||||
|
|
@ -550,6 +602,31 @@ eis_client_new(struct eis *eis, int fd)
|
|||
return client;
|
||||
}
|
||||
|
||||
void
|
||||
eis_client_add_seat(struct eis_client *client, struct eis_seat *seat)
|
||||
{
|
||||
/* remove from the pending list first */
|
||||
list_remove(&seat->link);
|
||||
/* We own this seat now */
|
||||
eis_seat_ref(seat);
|
||||
list_append(&client->seats, &seat->link);
|
||||
client_send_seat_added(client, seat);
|
||||
}
|
||||
|
||||
void
|
||||
eis_client_remove_seat(struct eis_client *client, struct eis_seat *seat)
|
||||
{
|
||||
struct eis_device *d, *tmp;
|
||||
|
||||
list_for_each_safe(d, tmp, &seat->devices, link) {
|
||||
eis_device_disconnect(d);
|
||||
}
|
||||
list_remove(&seat->link);
|
||||
if (seat->state != EIS_SEAT_STATE_ADDED)
|
||||
client_send_seat_removed(client, seat);
|
||||
eis_seat_unref(seat);
|
||||
}
|
||||
|
||||
void
|
||||
eis_client_connect_device(struct eis_client *client, struct eis_device *device)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ OBJECT_IMPLEMENT_UNREF(eis_device);
|
|||
static
|
||||
OBJECT_IMPLEMENT_CREATE(eis_device);
|
||||
static
|
||||
OBJECT_IMPLEMENT_PARENT(eis_device, eis_client);
|
||||
OBJECT_IMPLEMENT_PARENT(eis_device, eis_seat);
|
||||
_public_
|
||||
OBJECT_IMPLEMENT_GETTER(eis_device, user_data, void *);
|
||||
_public_
|
||||
|
|
@ -141,6 +141,12 @@ OBJECT_IMPLEMENT_SETTER(eis_device, user_data, void *);
|
|||
_public_
|
||||
OBJECT_IMPLEMENT_GETTER(eis_device, name, const char *);
|
||||
|
||||
_public_ struct eis_seat *
|
||||
eis_device_get_seat(struct eis_device *device)
|
||||
{
|
||||
return eis_device_parent(device);
|
||||
}
|
||||
|
||||
_public_ void
|
||||
eis_device_set_name(struct eis_device *device, const char *name)
|
||||
{
|
||||
|
|
@ -157,16 +163,16 @@ eis_device_set_name(struct eis_device *device, const char *name)
|
|||
_public_ struct eis_client *
|
||||
eis_device_get_client(struct eis_device *device)
|
||||
{
|
||||
return eis_device_parent(device);
|
||||
return eis_seat_get_client(eis_device_get_seat(device));
|
||||
}
|
||||
|
||||
struct eis_device *
|
||||
eis_device_new(struct eis_client *client,
|
||||
eis_device_new(struct eis_seat *seat,
|
||||
uint32_t id,
|
||||
const char *name,
|
||||
uint32_t capabilities)
|
||||
{
|
||||
struct eis_device *device = eis_device_create(&client->object);
|
||||
struct eis_device *device = eis_device_create(&seat->object);
|
||||
|
||||
device->name = xstrdup(name);
|
||||
device->capabilities_mask = 0;
|
||||
|
|
|
|||
|
|
@ -67,7 +67,8 @@ struct eis_client {
|
|||
enum eis_client_state state;
|
||||
char *name;
|
||||
|
||||
struct list devices;
|
||||
struct list seats;
|
||||
struct list seats_pending;
|
||||
|
||||
struct {
|
||||
enum {
|
||||
|
|
@ -79,6 +80,25 @@ struct eis_client {
|
|||
} restrictions;
|
||||
};
|
||||
|
||||
enum eis_seat_state {
|
||||
EIS_SEAT_STATE_PENDING,
|
||||
EIS_SEAT_STATE_ADDED,
|
||||
EIS_SEAT_STATE_REMOVED,
|
||||
};
|
||||
|
||||
struct eis_seat {
|
||||
struct object object; /* parent is ei_client */
|
||||
struct list link;
|
||||
void *user_data;
|
||||
uint32_t id;
|
||||
|
||||
enum eis_seat_state state;
|
||||
char *name;
|
||||
uint32_t capabilities_mask;
|
||||
|
||||
struct list devices;
|
||||
};
|
||||
|
||||
enum eis_device_state {
|
||||
EIS_DEVICE_STATE_NEW,
|
||||
EIS_DEVICE_STATE_SUSPENDED,
|
||||
|
|
@ -86,8 +106,9 @@ enum eis_device_state {
|
|||
EIS_DEVICE_STATE_REMOVED,
|
||||
};
|
||||
|
||||
|
||||
struct eis_device {
|
||||
struct object object;
|
||||
struct object object; /* parent is ei_seat */
|
||||
struct list link;
|
||||
uint32_t id;
|
||||
char *name;
|
||||
|
|
@ -156,6 +177,11 @@ eis_client_get_context(struct eis_client *client);
|
|||
void
|
||||
eis_add_client(struct eis *eis, struct eis_client *client);
|
||||
|
||||
void
|
||||
eis_client_add_seat(struct eis_client *client, struct eis_seat *seat);
|
||||
void
|
||||
eis_client_remove_seat(struct eis_client *client, struct eis_seat *seat);
|
||||
|
||||
void
|
||||
eis_client_connect_device(struct eis_client *client,
|
||||
struct eis_device *device);
|
||||
|
|
@ -171,7 +197,7 @@ eis_client_suspend_device(struct eis_client *client,
|
|||
struct eis_device *device);
|
||||
|
||||
struct eis_device *
|
||||
eis_device_new(struct eis_client *client,
|
||||
eis_device_new(struct eis_seat *seat,
|
||||
uint32_t id,
|
||||
const char *name,
|
||||
uint32_t capabilities);
|
||||
|
|
|
|||
|
|
@ -66,6 +66,8 @@ log_wire_message(struct eis *eis, const ServerMessage *msg)
|
|||
abort();
|
||||
MSG_STRING_CASE(CONNECTED);
|
||||
MSG_STRING_CASE(DISCONNECTED);
|
||||
MSG_STRING_CASE(SEAT_ADDED);
|
||||
MSG_STRING_CASE(SEAT_REMOVED);
|
||||
MSG_STRING_CASE(DEVICE_ADDED);
|
||||
MSG_STRING_CASE(DEVICE_REMOVED);
|
||||
MSG_STRING_CASE(DEVICE_RESUMED);
|
||||
|
|
@ -137,16 +139,50 @@ eis_proto_send_connect(struct eis_client *client)
|
|||
return eis_proto_send_msg(client, &msg);
|
||||
}
|
||||
|
||||
int
|
||||
eis_proto_send_seat_added(struct eis_client *client,
|
||||
struct eis_seat *seat)
|
||||
{
|
||||
ServerMessage msg = SERVER_MESSAGE__INIT;
|
||||
SeatAdded added = SEAT_ADDED__INIT;
|
||||
|
||||
added.seatid = seat->id;
|
||||
added.name = seat->name;
|
||||
added.capabilities = seat->capabilities_mask;
|
||||
|
||||
msg.seat_added = &added;
|
||||
msg.msg_case = SERVER_MESSAGE__MSG_SEAT_ADDED;
|
||||
|
||||
return eis_proto_send_msg(client, &msg);
|
||||
}
|
||||
|
||||
int
|
||||
eis_proto_send_seat_removed(struct eis_client *client,
|
||||
struct eis_seat *seat)
|
||||
{
|
||||
ServerMessage msg = SERVER_MESSAGE__INIT;
|
||||
SeatRemoved removed = SEAT_REMOVED__INIT;
|
||||
|
||||
removed.seatid = seat->id;
|
||||
|
||||
msg.seat_removed = &removed;
|
||||
msg.msg_case = SERVER_MESSAGE__MSG_SEAT_REMOVED;
|
||||
|
||||
return eis_proto_send_msg(client, &msg);
|
||||
}
|
||||
|
||||
int
|
||||
eis_proto_send_device_added(struct eis_client *client, struct eis_device *device)
|
||||
{
|
||||
ServerMessage msg = SERVER_MESSAGE__INIT;
|
||||
DeviceAdded added = DEVICE_ADDED__INIT;
|
||||
struct eis_seat *seat = eis_device_get_seat(device);
|
||||
int fds[2] = {-1, -1};
|
||||
|
||||
added.deviceid = device->id;
|
||||
added.name = device->name;
|
||||
added.capabilities = device->capabilities;
|
||||
|
||||
if (device->keymap) {
|
||||
struct eis_keymap *keymap = device->keymap;
|
||||
added.keymap_type = keymap->type;
|
||||
|
|
@ -158,6 +194,7 @@ eis_proto_send_device_added(struct eis_client *client, struct eis_device *device
|
|||
/* it's NULL anyway */
|
||||
added.keymap_from_server = true;
|
||||
}
|
||||
added.seatid = seat->id;
|
||||
|
||||
msg.device_added = &added;
|
||||
msg.msg_case = SERVER_MESSAGE__MSG_DEVICE_ADDED;
|
||||
|
|
@ -250,6 +287,7 @@ eis_proto_parse_message(struct brei_message *bmsg, size_t *consumed)
|
|||
.add_device.keymap_fd = -1,
|
||||
.add_device.keymap_type = a->keymap_type,
|
||||
.add_device.keymap_size = a->keymap_size,
|
||||
.add_device.seat = a->seat,
|
||||
};
|
||||
|
||||
if (a->keymap_type)
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ struct message {
|
|||
enum eis_keymap_type keymap_type;
|
||||
int keymap_fd;
|
||||
size_t keymap_size;
|
||||
uint32_t seat;
|
||||
} add_device;
|
||||
struct message_remove_device {
|
||||
uint32_t deviceid;
|
||||
|
|
@ -122,6 +123,14 @@ eis_proto_send_disconnect(struct eis_client *client);
|
|||
int
|
||||
eis_proto_send_connect(struct eis_client *client);
|
||||
|
||||
int
|
||||
eis_proto_send_seat_added(struct eis_client *client,
|
||||
struct eis_seat *seat);
|
||||
|
||||
int
|
||||
eis_proto_send_seat_removed(struct eis_client *client,
|
||||
struct eis_seat *seat);
|
||||
|
||||
int
|
||||
eis_proto_send_device_added(struct eis_client *client,
|
||||
struct eis_device *device);
|
||||
|
|
|
|||
130
src/libeis-seat.c
Normal file
130
src/libeis-seat.c
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* Copyright © 2020 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "util-macros.h"
|
||||
#include "util-bits.h"
|
||||
#include "util-strings.h"
|
||||
#include "libeis-private.h"
|
||||
|
||||
static void
|
||||
eis_seat_destroy(struct eis_seat *seat)
|
||||
{
|
||||
struct eis_device *d;
|
||||
|
||||
/* We expect those to have been removed already*/
|
||||
list_for_each(d, &seat->devices, link) {
|
||||
assert(!"device list not empty");
|
||||
}
|
||||
free(seat->name);
|
||||
}
|
||||
|
||||
_public_
|
||||
OBJECT_IMPLEMENT_REF(eis_seat);
|
||||
_public_
|
||||
OBJECT_IMPLEMENT_UNREF(eis_seat);
|
||||
static
|
||||
OBJECT_IMPLEMENT_CREATE(eis_seat);
|
||||
static
|
||||
OBJECT_IMPLEMENT_PARENT(eis_seat, eis_client);
|
||||
_public_
|
||||
OBJECT_IMPLEMENT_GETTER(eis_seat, user_data, void *);
|
||||
_public_
|
||||
OBJECT_IMPLEMENT_SETTER(eis_seat, user_data, void *);
|
||||
_public_
|
||||
OBJECT_IMPLEMENT_GETTER(eis_seat, name, const char *);
|
||||
|
||||
_public_ struct eis_client *
|
||||
eis_seat_get_client(struct eis_seat *seat)
|
||||
{
|
||||
return eis_seat_parent(seat);
|
||||
}
|
||||
|
||||
_public_ struct eis_seat *
|
||||
eis_client_new_seat(struct eis_client *client, const char *name)
|
||||
{
|
||||
static uint32_t seatid = 0x10000; /* we leave the lower bits to the deviceids */
|
||||
struct eis_seat *seat = eis_seat_create(&client->object);
|
||||
|
||||
seat->id = seatid++;
|
||||
seat->state = EIS_SEAT_STATE_PENDING;
|
||||
seat->name = xstrdup(name);
|
||||
list_init(&seat->devices);
|
||||
/* seat is owned by caller until it's added */
|
||||
list_append(&client->seats_pending, &seat->link);
|
||||
|
||||
return seat;
|
||||
}
|
||||
|
||||
_public_ void
|
||||
eis_seat_add(struct eis_seat *seat)
|
||||
{
|
||||
struct eis_client *client = eis_seat_get_client(seat);
|
||||
|
||||
switch (seat->state) {
|
||||
case EIS_SEAT_STATE_PENDING:
|
||||
break;
|
||||
case EIS_SEAT_STATE_ADDED:
|
||||
case EIS_SEAT_STATE_REMOVED:
|
||||
log_bug_client(eis_client_get_context(client),
|
||||
"%s: seat already added/removed\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
seat->state = EIS_SEAT_STATE_ADDED;
|
||||
eis_client_add_seat(client, seat);
|
||||
}
|
||||
|
||||
_public_ void
|
||||
eis_seat_remove(struct eis_seat *seat)
|
||||
{
|
||||
struct eis_client *client = eis_seat_get_client(seat);
|
||||
|
||||
switch (seat->state) {
|
||||
case EIS_SEAT_STATE_PENDING:
|
||||
case EIS_SEAT_STATE_ADDED:
|
||||
break;
|
||||
case EIS_SEAT_STATE_REMOVED:
|
||||
log_bug_client(eis_client_get_context(client),
|
||||
"%s: seat already removed\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
seat->state = EIS_SEAT_STATE_REMOVED;
|
||||
eis_client_remove_seat(eis_seat_get_client(seat), seat);
|
||||
}
|
||||
|
||||
_public_ void
|
||||
eis_seat_allow_capability(struct eis_seat *seat,
|
||||
enum eis_device_capability cap)
|
||||
{
|
||||
switch (cap) {
|
||||
case EIS_DEVICE_CAP_POINTER:
|
||||
case EIS_DEVICE_CAP_POINTER_ABSOLUTE:
|
||||
case EIS_DEVICE_CAP_KEYBOARD:
|
||||
case EIS_DEVICE_CAP_TOUCH:
|
||||
seat->capabilities_mask |= bit(cap);
|
||||
break;
|
||||
}
|
||||
}
|
||||
66
src/libeis.h
66
src/libeis.h
|
|
@ -44,6 +44,7 @@ extern "C" {
|
|||
struct eis;
|
||||
struct eis_client;
|
||||
struct eis_device;
|
||||
struct eis_seat;
|
||||
struct eis_event;
|
||||
struct eis_keymap;
|
||||
|
||||
|
|
@ -277,6 +278,65 @@ eis_client_connect(struct eis_client *client);
|
|||
void
|
||||
eis_client_disconnect(struct eis_client *client);
|
||||
|
||||
/**
|
||||
* Create a new logical seat with a given name. Devices created by the
|
||||
* client must bind to a seat, or in other words: a client cannot create
|
||||
* devices until at least one seat is bound.
|
||||
*
|
||||
* This seat is not immediately active, use eis_seat_add() to bind this
|
||||
* seat on the client and notify the client of it's availability.
|
||||
*
|
||||
* The returned seat is refcounted, use eis_seat_unref() to drop the
|
||||
* reference.
|
||||
*/
|
||||
struct eis_seat *
|
||||
eis_client_new_seat(struct eis_client *client, const char *name);
|
||||
|
||||
struct eis_seat *
|
||||
eis_seat_ref(struct eis_seat *seat);
|
||||
|
||||
struct eis_seat *
|
||||
eis_seat_unref(struct eis_seat *seat);
|
||||
|
||||
struct eis_client *
|
||||
eis_seat_get_client(struct eis_seat *eis_seat);
|
||||
|
||||
const char *
|
||||
eis_seat_get_name(struct eis_seat *eis_seat);
|
||||
|
||||
void *
|
||||
eis_seat_get_user_data(struct eis_seat *eis_seat);
|
||||
|
||||
void
|
||||
eis_seat_set_user_data(struct eis_seat *eis_seat, void *user_data);
|
||||
|
||||
/**
|
||||
* Allow a capability on the seat. This indicates to the client
|
||||
* that it may create devices with with the given capabilities, though the
|
||||
* EIS implementation may restrict the of capabilities on a device to a
|
||||
* subset of those in the seat, see eis_device_allow_capability().
|
||||
*
|
||||
* This function must be called before eis_seat_add().
|
||||
*
|
||||
* This function has no effect if called after eis_seat_add()
|
||||
*/
|
||||
void
|
||||
eis_seat_allow_capability(struct eis_seat *seat,
|
||||
enum eis_device_capability cap);
|
||||
|
||||
/**
|
||||
* Add this seat to its client and notify the client of the seat's
|
||||
* availability. This allows the client to create a device within this seat.
|
||||
*/
|
||||
void
|
||||
eis_seat_add(struct eis_seat *seat);
|
||||
|
||||
/**
|
||||
* Remove this seat and all its remaining devices.
|
||||
*/
|
||||
void
|
||||
eis_seat_remove(struct eis_seat *seat);
|
||||
|
||||
enum eis_event_type
|
||||
eis_event_get_type(struct eis_event *event);
|
||||
|
||||
|
|
@ -286,6 +346,9 @@ eis_event_get_client(struct eis_event *event);
|
|||
struct eis_client *
|
||||
eis_device_get_client(struct eis_device *device);
|
||||
|
||||
struct eis_seat *
|
||||
eis_device_get_seat(struct eis_device *device);
|
||||
|
||||
struct eis_device *
|
||||
eis_device_ref(struct eis_device *device);
|
||||
|
||||
|
|
@ -323,7 +386,8 @@ eis_device_has_capability(struct eis_device *device,
|
|||
* eis_device_connect().
|
||||
*
|
||||
* This function has no effect if called for a capability the device does
|
||||
* not support.
|
||||
* not support. This function has no effect if called for a capability not
|
||||
* allowed on the seat this device belongs to.
|
||||
*
|
||||
* This function has no effect if called after eis_device_connect()
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -48,6 +48,11 @@ struct peck {
|
|||
uint32_t ei_behavior;
|
||||
struct logger *logger;
|
||||
|
||||
struct eis_seat *eis_seat;
|
||||
struct ei_seat *ei_seat;
|
||||
|
||||
struct eis_client *eis_client;
|
||||
|
||||
uint32_t indent;
|
||||
};
|
||||
|
||||
|
|
@ -76,6 +81,11 @@ peck_destroy(struct peck *peck)
|
|||
peck_drain_ei(peck->ei);
|
||||
peck_drain_eis(peck->eis);
|
||||
|
||||
eis_client_unref(peck->eis_client);
|
||||
|
||||
ei_seat_unref(peck->ei_seat);
|
||||
eis_seat_unref(peck->eis_seat);
|
||||
|
||||
ei_unref(peck->ei);
|
||||
eis_unref(peck->eis);
|
||||
logger_unref(peck->logger);
|
||||
|
|
@ -87,6 +97,27 @@ OBJECT_IMPLEMENT_UNREF(peck);
|
|||
OBJECT_IMPLEMENT_GETTER(peck, ei, struct ei*);
|
||||
OBJECT_IMPLEMENT_GETTER(peck, eis, struct eis*);
|
||||
|
||||
struct eis_client *
|
||||
peck_eis_get_default_client(struct peck *peck)
|
||||
{
|
||||
munit_assert_ptr_not_null(peck->eis_client);
|
||||
return peck->eis_client;
|
||||
};
|
||||
|
||||
struct eis_seat *
|
||||
peck_eis_get_default_seat(struct peck *peck)
|
||||
{
|
||||
munit_assert_ptr_not_null(peck->eis_seat);
|
||||
return peck->eis_seat;
|
||||
};
|
||||
|
||||
struct ei_seat *
|
||||
peck_ei_get_default_seat(struct peck *peck)
|
||||
{
|
||||
munit_assert_ptr_not_null(peck->ei_seat);
|
||||
return peck->ei_seat;
|
||||
}
|
||||
|
||||
static void
|
||||
peck_ei_log_handler(struct ei *ei,
|
||||
enum ei_log_priority priority,
|
||||
|
|
@ -178,6 +209,7 @@ peck_new(void)
|
|||
munit_assert_int(rc, ==, 0);
|
||||
peck->ei = ei;
|
||||
flag_set(peck->ei_behavior, PECK_EI_BEHAVIOR_AUTOCONNNECT);
|
||||
flag_set(peck->ei_behavior, PECK_EI_BEHAVIOR_AUTOSEAT);
|
||||
|
||||
struct eis *eis = eis_new(peck);
|
||||
eis_log_set_handler(eis, peck_eis_log_handler);
|
||||
|
|
@ -203,7 +235,12 @@ peck_enable_eis_behavior(struct peck *peck, enum peck_eis_behavior behavior)
|
|||
case PECK_EIS_BEHAVIOR_NONE:
|
||||
peck->eis_behavior = 0;
|
||||
break;
|
||||
case PECK_EIS_BEHAVIOR_DEFAULT_SEAT:
|
||||
case PECK_EIS_BEHAVIOR_NO_DEFAULT_SEAT:
|
||||
flag_set(peck->eis_behavior, behavior);
|
||||
break;
|
||||
case PECK_EIS_BEHAVIOR_ACCEPT_ALL:
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_DEFAULT_SEAT);
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_CLIENT);
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_DEVICE);
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_RESUME_DEVICE);
|
||||
|
|
@ -266,10 +303,12 @@ peck_enable_ei_behavior(struct peck *peck, enum peck_ei_behavior behavior)
|
|||
peck->ei_behavior = 0;
|
||||
break;
|
||||
case PECK_EI_BEHAVIOR_AUTOCONNNECT:
|
||||
case PECK_EI_BEHAVIOR_AUTOSEAT:
|
||||
flag_set(peck->ei_behavior, behavior);
|
||||
break;
|
||||
case PECK_EI_BEHAVIOR_AUTODEVICES:
|
||||
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTOCONNNECT);
|
||||
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTOSEAT);
|
||||
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_ADDED);
|
||||
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_RESUMED);
|
||||
break;
|
||||
|
|
@ -292,6 +331,22 @@ peck_enable_ei_behavior(struct peck *peck, enum peck_ei_behavior behavior)
|
|||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
peck_create_eis_seat(struct peck *peck, struct eis_client *client)
|
||||
{
|
||||
_cleanup_eis_seat_ struct eis_seat *seat = eis_client_new_seat(client, "default");
|
||||
|
||||
eis_seat_allow_capability(seat, EIS_DEVICE_CAP_POINTER);
|
||||
eis_seat_allow_capability(seat, EIS_DEVICE_CAP_POINTER_ABSOLUTE);
|
||||
eis_seat_allow_capability(seat, EIS_DEVICE_CAP_KEYBOARD);
|
||||
eis_seat_allow_capability(seat, EIS_DEVICE_CAP_TOUCH);
|
||||
|
||||
log_debug(peck, "EIS adding seat: '%s'\n", eis_seat_get_name(seat));
|
||||
eis_seat_add(seat);
|
||||
|
||||
peck->eis_seat = eis_seat_ref(seat);
|
||||
}
|
||||
|
||||
static inline void
|
||||
peck_handle_eis_connect(struct peck *peck, struct eis_event *e)
|
||||
{
|
||||
|
|
@ -299,7 +354,10 @@ peck_handle_eis_connect(struct peck *peck, struct eis_event *e)
|
|||
|
||||
if (flag_is_set(peck->eis_behavior, PECK_EIS_BEHAVIOR_ACCEPT_CLIENT)) {
|
||||
log_debug(peck, "EIS accepting client: '%s'\n", eis_client_get_name(client));
|
||||
peck->eis_client = eis_client_ref(client);
|
||||
eis_client_connect(client);
|
||||
if (flag_is_set(peck->eis_behavior, PECK_EIS_BEHAVIOR_DEFAULT_SEAT))
|
||||
peck_create_eis_seat(peck, client);
|
||||
} else {
|
||||
log_debug(peck, "EIS disconnecting client: '%s'\n", eis_client_get_name(client));
|
||||
eis_client_disconnect(client);
|
||||
|
|
@ -470,6 +528,12 @@ _peck_dispatch_ei(struct peck *peck, int lineno)
|
|||
PECK_EI_BEHAVIOR_AUTOCONNNECT))
|
||||
process_event = tristate_yes;
|
||||
break;
|
||||
case EI_EVENT_SEAT_ADDED:
|
||||
if (peck->ei_seat == NULL &&
|
||||
flag_is_set(peck->ei_behavior,
|
||||
PECK_EI_BEHAVIOR_AUTOSEAT))
|
||||
process_event = tristate_yes;
|
||||
break;
|
||||
case EI_EVENT_DEVICE_ADDED:
|
||||
process_event = peck_check_ei_added(peck, e);
|
||||
break;
|
||||
|
|
@ -504,6 +568,14 @@ _peck_dispatch_ei(struct peck *peck, int lineno)
|
|||
log_debug(peck, "ei is connected\n");
|
||||
/* Nothing to do here */
|
||||
break;
|
||||
case EI_EVENT_SEAT_ADDED:
|
||||
{
|
||||
struct ei_seat *seat = ei_event_get_seat(e);
|
||||
munit_assert_ptr_null(peck->ei_seat);
|
||||
peck->ei_seat = ei_seat_ref(seat);
|
||||
log_debug(peck, "default seat: %s\n");
|
||||
break;
|
||||
}
|
||||
case EI_EVENT_DEVICE_ADDED:
|
||||
case EI_EVENT_DEVICE_RESUMED:
|
||||
case EI_EVENT_DEVICE_SUSPENDED:
|
||||
|
|
@ -644,12 +716,14 @@ peck_ei_event_type_name(enum ei_event_type type)
|
|||
switch (type) {
|
||||
CASE_STRING(CONNECT);
|
||||
CASE_STRING(DISCONNECT);
|
||||
CASE_STRING(SEAT_ADDED);
|
||||
CASE_STRING(SEAT_REMOVED);
|
||||
CASE_STRING(DEVICE_ADDED);
|
||||
CASE_STRING(DEVICE_REMOVED);
|
||||
CASE_STRING(DEVICE_SUSPENDED);
|
||||
CASE_STRING(DEVICE_RESUMED);
|
||||
default:
|
||||
abort();
|
||||
assert(!"Unhandled ei event type");
|
||||
}
|
||||
#undef CASE_STRING
|
||||
}
|
||||
|
|
@ -679,7 +753,7 @@ peck_eis_event_type_name(enum eis_event_type type)
|
|||
CASE_STRING(TOUCH_UP);
|
||||
CASE_STRING(TOUCH_MOTION);
|
||||
default:
|
||||
abort();
|
||||
assert(!"Unhandled EIS event type");
|
||||
}
|
||||
#undef CASE_STRING
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,9 +42,19 @@ enum peck_eis_behavior {
|
|||
* Behavior of EIS is implemented in the test case.
|
||||
*/
|
||||
PECK_EIS_BEHAVIOR_NONE,
|
||||
/**
|
||||
* Create a "default" seat. This behavior is enabled as part of
|
||||
* PECK_EIS_BEHAVIOR_ACCEPT_ALL.
|
||||
*/
|
||||
PECK_EIS_BEHAVIOR_DEFAULT_SEAT,
|
||||
/**
|
||||
* Do not create a "default" seat.
|
||||
*/
|
||||
PECK_EIS_BEHAVIOR_NO_DEFAULT_SEAT,
|
||||
/**
|
||||
* Accept all client connection requests and device additions
|
||||
* **and** resume any device immediately after add.
|
||||
* This also enables @ref PECK_EIS_BEHAVIOR_DEFAULT_SEAT.
|
||||
*/
|
||||
PECK_EIS_BEHAVIOR_ACCEPT_ALL,
|
||||
/**
|
||||
|
|
@ -83,10 +93,13 @@ enum peck_eis_behavior {
|
|||
|
||||
enum peck_ei_behavior {
|
||||
PECK_EI_BEHAVIOR_NONE,
|
||||
/* the default - handle the Connect event */
|
||||
/* enabled by default - handle the Connect event */
|
||||
PECK_EI_BEHAVIOR_AUTOCONNNECT,
|
||||
/* handle Connect/Added/Resumed events, i.e. anything until
|
||||
* the first real device event */
|
||||
/* enabled by default - handle the first seat added event, setting
|
||||
* the default seat to the first seat */
|
||||
PECK_EI_BEHAVIOR_AUTOSEAT,
|
||||
/* handle Connect/Seat/Added/Resumed events, i.e. anything until the
|
||||
* first real device event */
|
||||
PECK_EI_BEHAVIOR_AUTODEVICES,
|
||||
PECK_EI_BEHAVIOR_HANDLE_ADDED,
|
||||
PECK_EI_BEHAVIOR_HANDLE_ADDED_POINTER,
|
||||
|
|
@ -115,6 +128,15 @@ peck_get_ei(struct peck *peck);
|
|||
struct eis *
|
||||
peck_get_eis(struct peck *peck);
|
||||
|
||||
struct eis_client *
|
||||
peck_eis_get_default_client(struct peck *peck);
|
||||
|
||||
struct eis_seat *
|
||||
peck_eis_get_default_seat(struct peck *peck);
|
||||
|
||||
struct ei_seat *
|
||||
peck_ei_get_default_seat(struct peck *peck);
|
||||
|
||||
/**
|
||||
* Dispatch all events according to the currently defined behavior.
|
||||
* When this function returns false, the connection is in a "stable" state
|
||||
|
|
@ -235,6 +257,8 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(struct eis_device *, eis_device_unref);
|
|||
#define _cleanup_eis_device_ _cleanup_(eis_device_unrefp)
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct eis_keymap *, eis_keymap_unref);
|
||||
#define _cleanup_eis_keymap_ _cleanup_(eis_keymap_unrefp)
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct eis_seat *, eis_seat_unref);
|
||||
#define _cleanup_eis_seat_ _cleanup_(eis_seat_unrefp)
|
||||
|
||||
/* Macros intended just for readability to make it more obvious which part
|
||||
of a test handles server vs client */
|
||||
|
|
|
|||
144
test/test-ei.c
144
test/test-ei.c
|
|
@ -87,20 +87,12 @@ MUNIT_TEST(test_ei_disconnect_after_add_before_received)
|
|||
_cleanup_peck_ struct peck *peck = peck_new();
|
||||
_cleanup_eis_client_ struct eis_client *client = NULL;
|
||||
|
||||
peck_dispatch_until_stable(peck);
|
||||
|
||||
with_server(peck) {
|
||||
eis_dispatch(eis);
|
||||
_cleanup_eis_event_ struct eis_event *e =
|
||||
peck_eis_next_event(eis, EIS_EVENT_CLIENT_CONNECT);
|
||||
client = eis_client_ref(eis_event_get_client(e));
|
||||
eis_client_connect(client);
|
||||
}
|
||||
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL);
|
||||
peck_dispatch_until_stable(peck);
|
||||
|
||||
with_client(peck) {
|
||||
_cleanup_ei_device_ struct ei_device *device = ei_device_new(ei);
|
||||
struct ei_seat *seat = peck_ei_get_default_seat(peck);
|
||||
_cleanup_ei_device_ struct ei_device *device = ei_device_new(seat);
|
||||
ei_device_configure_name(device, __func__);
|
||||
ei_device_configure_capability(device, EI_DEVICE_CAP_POINTER);
|
||||
ei_device_add(device);
|
||||
|
|
@ -109,13 +101,16 @@ MUNIT_TEST(test_ei_disconnect_after_add_before_received)
|
|||
/* We have *not* called eis_dispatch, so the device add hasn't been
|
||||
* processed by the server yet */
|
||||
with_server(peck) {
|
||||
struct eis_client *client = peck_eis_get_default_client(peck);
|
||||
eis_client_disconnect(client);
|
||||
}
|
||||
|
||||
with_client(peck) {
|
||||
ei_dispatch(ei);
|
||||
_cleanup_ei_event_ struct ei_event *removed =
|
||||
_cleanup_ei_event_ struct ei_event *device_removed =
|
||||
peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED);
|
||||
_cleanup_ei_event_ struct ei_event *seat_removed =
|
||||
peck_ei_next_event(ei, EI_EVENT_SEAT_REMOVED);
|
||||
_cleanup_ei_event_ struct ei_event *disconnect =
|
||||
peck_ei_next_event(ei, EI_EVENT_DISCONNECT);
|
||||
}
|
||||
|
|
@ -128,20 +123,13 @@ MUNIT_TEST(test_ei_disconnect_after_add_after_received)
|
|||
_cleanup_peck_ struct peck *peck = peck_new();
|
||||
_cleanup_eis_client_ struct eis_client *client = NULL;
|
||||
|
||||
peck_dispatch_until_stable(peck);
|
||||
|
||||
with_server(peck) {
|
||||
eis_dispatch(eis);
|
||||
_cleanup_eis_event_ struct eis_event *e =
|
||||
peck_eis_next_event(eis, EIS_EVENT_CLIENT_CONNECT);
|
||||
client = eis_client_ref(eis_event_get_client(e));
|
||||
eis_client_connect(client);
|
||||
}
|
||||
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_CLIENT);
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_DEFAULT_SEAT);
|
||||
peck_dispatch_until_stable(peck);
|
||||
|
||||
with_client(peck) {
|
||||
_cleanup_ei_device_ struct ei_device *device = ei_device_new(ei);
|
||||
struct ei_seat *seat = peck_ei_get_default_seat(peck);
|
||||
_cleanup_ei_device_ struct ei_device *device = ei_device_new(seat);
|
||||
ei_device_configure_name(device, __func__);
|
||||
ei_device_configure_capability(device, EI_DEVICE_CAP_POINTER);
|
||||
ei_device_add(device);
|
||||
|
|
@ -151,13 +139,16 @@ MUNIT_TEST(test_ei_disconnect_after_add_after_received)
|
|||
peck_dispatch_eis(peck);
|
||||
|
||||
with_server(peck) {
|
||||
struct eis_client *client = peck_eis_get_default_client(peck);
|
||||
eis_client_disconnect(client);
|
||||
}
|
||||
|
||||
with_client(peck) {
|
||||
ei_dispatch(ei);
|
||||
_cleanup_ei_event_ struct ei_event *removed =
|
||||
_cleanup_ei_event_ struct ei_event *device_removed =
|
||||
peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED);
|
||||
_cleanup_ei_event_ struct ei_event *seat_removed =
|
||||
peck_ei_next_event(ei, EI_EVENT_SEAT_REMOVED);
|
||||
_cleanup_ei_event_ struct ei_event *disconnect =
|
||||
peck_ei_next_event(ei, EI_EVENT_DISCONNECT);
|
||||
}
|
||||
|
|
@ -168,29 +159,22 @@ MUNIT_TEST(test_ei_disconnect_after_add_after_received)
|
|||
MUNIT_TEST(test_ei_disconnect_after_remove_before_received)
|
||||
{
|
||||
_cleanup_peck_ struct peck *peck = peck_new();
|
||||
_cleanup_eis_client_ struct eis_client *client = NULL;
|
||||
_cleanup_ei_device_ struct ei_device *device = NULL;
|
||||
|
||||
peck_dispatch_until_stable(peck);
|
||||
|
||||
with_server(peck) {
|
||||
eis_dispatch(eis);
|
||||
_cleanup_eis_event_ struct eis_event *e =
|
||||
peck_eis_next_event(eis, EIS_EVENT_CLIENT_CONNECT);
|
||||
client = eis_client_ref(eis_event_get_client(e));
|
||||
eis_client_connect(client);
|
||||
}
|
||||
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL);
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_CLIENT);
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_DEFAULT_SEAT);
|
||||
peck_dispatch_until_stable(peck);
|
||||
|
||||
with_client(peck) {
|
||||
device = ei_device_new(ei);
|
||||
struct ei_seat *seat = peck_ei_get_default_seat(peck);
|
||||
device = ei_device_new(seat);
|
||||
ei_device_configure_name(device, __func__);
|
||||
ei_device_configure_capability(device, EI_DEVICE_CAP_POINTER);
|
||||
ei_device_add(device);
|
||||
}
|
||||
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL);
|
||||
|
||||
/* server has the device now */
|
||||
peck_dispatch_until_stable(peck);
|
||||
|
||||
|
|
@ -206,13 +190,16 @@ MUNIT_TEST(test_ei_disconnect_after_remove_before_received)
|
|||
* ei_device_remove() call. Disconnect the client, this
|
||||
* automatically removes all devices */
|
||||
with_server(peck) {
|
||||
struct eis_client *client = peck_eis_get_default_client(peck);
|
||||
eis_client_disconnect(client);
|
||||
}
|
||||
|
||||
with_client(peck) {
|
||||
ei_dispatch(ei);
|
||||
_cleanup_ei_event_ struct ei_event *removed =
|
||||
_cleanup_ei_event_ struct ei_event *device_removed =
|
||||
peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED);
|
||||
_cleanup_ei_event_ struct ei_event *seat_removed =
|
||||
peck_ei_next_event(ei, EI_EVENT_SEAT_REMOVED);
|
||||
_cleanup_ei_event_ struct ei_event *disconnect =
|
||||
peck_ei_next_event(ei, EI_EVENT_DISCONNECT);
|
||||
}
|
||||
|
|
@ -223,24 +210,14 @@ MUNIT_TEST(test_ei_disconnect_after_remove_before_received)
|
|||
MUNIT_TEST(test_ei_disconnect_after_remove_after_received)
|
||||
{
|
||||
_cleanup_peck_ struct peck *peck = peck_new();
|
||||
_cleanup_eis_client_ struct eis_client *client = NULL;
|
||||
_cleanup_ei_device_ struct ei_device *device = NULL;
|
||||
|
||||
peck_dispatch_until_stable(peck);
|
||||
|
||||
with_server(peck) {
|
||||
eis_dispatch(eis);
|
||||
_cleanup_eis_event_ struct eis_event *e =
|
||||
peck_eis_next_event(eis, EIS_EVENT_CLIENT_CONNECT);
|
||||
client = eis_client_ref(eis_event_get_client(e));
|
||||
eis_client_connect(client);
|
||||
}
|
||||
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL);
|
||||
peck_dispatch_until_stable(peck);
|
||||
|
||||
with_client(peck) {
|
||||
device = ei_device_new(ei);
|
||||
struct ei_seat *seat = peck_ei_get_default_seat(peck);
|
||||
device = ei_device_new(seat);
|
||||
ei_device_configure_name(device, __func__);
|
||||
ei_device_configure_capability(device, EI_DEVICE_CAP_POINTER);
|
||||
ei_device_add(device);
|
||||
|
|
@ -260,14 +237,18 @@ MUNIT_TEST(test_ei_disconnect_after_remove_after_received)
|
|||
/* Dispatch, server is aware of the ei_device_remove() */
|
||||
peck_dispatch_eis(peck);
|
||||
with_server(peck) {
|
||||
struct eis_client *client = peck_eis_get_default_client(peck);
|
||||
eis_client_disconnect(client);
|
||||
}
|
||||
|
||||
with_client(peck) {
|
||||
ei_dispatch(ei);
|
||||
_cleanup_ei_event_ struct ei_event *removed =
|
||||
_cleanup_ei_event_ struct ei_event *device_removed =
|
||||
peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED);
|
||||
|
||||
_cleanup_ei_event_ struct ei_event *seat_removed =
|
||||
peck_ei_next_event(ei, EI_EVENT_SEAT_REMOVED);
|
||||
|
||||
_cleanup_ei_event_ struct ei_event *disconnect =
|
||||
peck_ei_next_event(ei, EI_EVENT_DISCONNECT);
|
||||
}
|
||||
|
|
@ -285,7 +266,8 @@ MUNIT_TEST(test_ei_device_basics)
|
|||
|
||||
/* device creation and getters/setters test */
|
||||
with_client(peck) {
|
||||
device = ei_device_new(ei);
|
||||
struct ei_seat *seat = peck_ei_get_default_seat(peck);
|
||||
device = ei_device_new(seat);
|
||||
munit_assert_not_null(device);
|
||||
ei_device_configure_name(device, __func__);
|
||||
munit_assert_string_equal(ei_device_get_name(device), __func__);
|
||||
|
|
@ -329,21 +311,23 @@ MUNIT_TEST(test_ei_device_set_name)
|
|||
_cleanup_ei_device_ struct ei_device *d3 = NULL;
|
||||
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_CLIENT);
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_DEFAULT_SEAT);
|
||||
peck_dispatch_until_stable(peck);
|
||||
|
||||
with_client(peck) {
|
||||
d1 = ei_device_new(ei);
|
||||
struct ei_seat *seat = peck_ei_get_default_seat(peck);
|
||||
d1 = ei_device_new(seat);
|
||||
ei_device_configure_name(d1, "first device");
|
||||
ei_device_configure_capability(d1, EI_DEVICE_CAP_POINTER);
|
||||
ei_device_add(d1);
|
||||
|
||||
d2 = ei_device_new(ei);
|
||||
d2 = ei_device_new(seat);
|
||||
munit_assert_not_null(d2);
|
||||
ei_device_configure_name(d2, "second device");
|
||||
ei_device_configure_capability(d2, EI_DEVICE_CAP_POINTER);
|
||||
ei_device_add(d2);
|
||||
|
||||
d3 = ei_device_new(ei);
|
||||
d3 = ei_device_new(seat);
|
||||
munit_assert_not_null(d3);
|
||||
ei_device_configure_name(d3, "third device");
|
||||
ei_device_configure_capability(d3, EI_DEVICE_CAP_POINTER);
|
||||
|
|
@ -411,19 +395,15 @@ MUNIT_TEST(test_ei_device_add_remove)
|
|||
{
|
||||
_cleanup_peck_ struct peck *peck = peck_new();
|
||||
|
||||
with_server(peck) {
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_CLIENT);
|
||||
peck_dispatch_eis(peck);
|
||||
}
|
||||
|
||||
with_client(peck) {
|
||||
peck_drain_ei(ei);
|
||||
}
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_CLIENT);
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_DEFAULT_SEAT);
|
||||
peck_dispatch_until_stable(peck);
|
||||
|
||||
_cleanup_ei_device_ struct ei_device *device = NULL;
|
||||
|
||||
with_client(peck) {
|
||||
device = ei_device_new(ei);
|
||||
struct ei_seat *seat = peck_ei_get_default_seat(peck);
|
||||
device = ei_device_new(seat);
|
||||
ei_device_configure_name(device, __func__);
|
||||
ei_device_configure_capability(device, EI_DEVICE_CAP_POINTER);
|
||||
ei_device_add(device);
|
||||
|
|
@ -490,12 +470,13 @@ MUNIT_TEST(test_ei_device_remove_forget_disconnect)
|
|||
_cleanup_ei_device_ struct ei_device *d2 = NULL;
|
||||
|
||||
with_client(peck) {
|
||||
d1 = ei_device_new(ei);
|
||||
struct ei_seat *seat = peck_ei_get_default_seat(peck);
|
||||
d1 = ei_device_new(seat);
|
||||
ei_device_configure_name(d1, "first");
|
||||
ei_device_configure_capability(d1, EI_DEVICE_CAP_POINTER);
|
||||
ei_device_add(d1);
|
||||
|
||||
d2 = ei_device_new(ei);
|
||||
d2 = ei_device_new(seat);
|
||||
ei_device_configure_name(d2, "second");
|
||||
ei_device_configure_capability(d2, EI_DEVICE_CAP_KEYBOARD);
|
||||
ei_device_add(d2);
|
||||
|
|
@ -564,7 +545,8 @@ MUNIT_TEST(test_ei_device_add_drop_caps)
|
|||
_cleanup_ei_device_ struct ei_device *device = NULL;
|
||||
|
||||
with_client(peck) {
|
||||
device = ei_device_new(ei);
|
||||
struct ei_seat *seat = peck_ei_get_default_seat(peck);
|
||||
device = ei_device_new(seat);
|
||||
ei_device_configure_name(device, __func__);
|
||||
ei_device_configure_capability(device, EI_DEVICE_CAP_POINTER);
|
||||
ei_device_configure_capability(device, EI_DEVICE_CAP_KEYBOARD);
|
||||
|
|
@ -602,7 +584,8 @@ MUNIT_TEST(test_ei_device_add_zero_caps)
|
|||
_cleanup_ei_device_ struct ei_device *device = NULL;
|
||||
|
||||
with_client(peck) {
|
||||
device = ei_device_new(ei);
|
||||
struct ei_seat *seat = peck_ei_get_default_seat(peck);
|
||||
device = ei_device_new(seat);
|
||||
ei_device_configure_name(device, __func__);
|
||||
ei_device_configure_capability(device, EI_DEVICE_CAP_POINTER);
|
||||
ei_device_add(device);
|
||||
|
|
@ -630,7 +613,8 @@ MUNIT_TEST(test_ei_device_pointer_rel)
|
|||
peck_dispatch_until_stable(peck);
|
||||
|
||||
with_client(peck) {
|
||||
device = ei_device_new(ei);
|
||||
struct ei_seat *seat = peck_ei_get_default_seat(peck);
|
||||
device = ei_device_new(seat);
|
||||
munit_assert_not_null(device);
|
||||
ei_device_configure_name(device, __func__);
|
||||
|
||||
|
|
@ -674,11 +658,13 @@ MUNIT_TEST(test_ei_device_pointer_abs)
|
|||
_cleanup_ei_device_ struct ei_device *device = NULL;
|
||||
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL);
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_DEFAULT_SEAT);
|
||||
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTODEVICES);
|
||||
peck_dispatch_until_stable(peck);
|
||||
|
||||
with_client(peck) {
|
||||
device = ei_device_new(ei);
|
||||
struct ei_seat *seat = peck_ei_get_default_seat(peck);
|
||||
device = ei_device_new(seat);
|
||||
munit_assert_not_null(device);
|
||||
ei_device_configure_name(device, __func__);
|
||||
|
||||
|
|
@ -746,7 +732,8 @@ MUNIT_TEST(test_ei_device_touch)
|
|||
peck_dispatch_until_stable(peck);
|
||||
|
||||
with_client(peck) {
|
||||
device = ei_device_new(ei);
|
||||
struct ei_seat *seat = peck_ei_get_default_seat(peck);
|
||||
device = ei_device_new(seat);
|
||||
munit_assert_not_null(device);
|
||||
ei_device_configure_name(device, __func__);
|
||||
|
||||
|
|
@ -888,7 +875,8 @@ MUNIT_TEST(test_ei_device_multitouch)
|
|||
peck_dispatch_until_stable(peck);
|
||||
|
||||
with_client(peck) {
|
||||
device = ei_device_new(ei);
|
||||
struct ei_seat *seat = peck_ei_get_default_seat(peck);
|
||||
device = ei_device_new(seat);
|
||||
munit_assert_not_null(device);
|
||||
ei_device_configure_name(device, __func__);
|
||||
|
||||
|
|
@ -969,13 +957,15 @@ MUNIT_TEST(test_ei_keymap_set)
|
|||
_cleanup_ei_keymap_ struct ei_keymap *keymap = NULL;
|
||||
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_CLIENT);
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_DEFAULT_SEAT);
|
||||
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTODEVICES);
|
||||
peck_dispatch_until_stable(peck);
|
||||
|
||||
with_client(peck) {
|
||||
_cleanup_memfile_ struct memfile *fd2 = memfile_new(data, sizeof(data));
|
||||
|
||||
device = ei_device_new(ei);
|
||||
struct ei_seat *seat = peck_ei_get_default_seat(peck);
|
||||
device = ei_device_new(seat);
|
||||
ei_device_configure_name(device, __func__);
|
||||
ei_device_configure_capability(device, EI_DEVICE_CAP_KEYBOARD);
|
||||
|
||||
|
|
@ -1038,11 +1028,13 @@ MUNIT_TEST(test_ei_keymap_null)
|
|||
_cleanup_memfile_ struct memfile *fd = memfile_new(data, sizeof(data));
|
||||
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_CLIENT);
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_DEFAULT_SEAT);
|
||||
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTOCONNNECT);
|
||||
peck_dispatch_until_stable(peck);
|
||||
|
||||
with_client(peck) {
|
||||
_cleanup_ei_device_ struct ei_device *device = ei_device_new(ei);
|
||||
struct ei_seat *seat = peck_ei_get_default_seat(peck);
|
||||
_cleanup_ei_device_ struct ei_device *device = ei_device_new(seat);
|
||||
ei_device_configure_name(device, __func__);
|
||||
ei_device_configure_capability(device, EI_DEVICE_CAP_KEYBOARD);
|
||||
|
||||
|
|
@ -1085,6 +1077,7 @@ MUNIT_TEST(test_ei_keymap_changed)
|
|||
_cleanup_memfile_ struct memfile *fd1 = memfile_new(data, sizeof(data));
|
||||
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_CLIENT);
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_DEFAULT_SEAT);
|
||||
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTOCONNNECT);
|
||||
peck_dispatch_until_stable(peck);
|
||||
|
||||
|
|
@ -1093,7 +1086,8 @@ MUNIT_TEST(test_ei_keymap_changed)
|
|||
const char otherdata[2] = {10, 20};
|
||||
_cleanup_memfile_ struct memfile *fd2 = memfile_new(data, sizeof(otherdata));
|
||||
|
||||
device = ei_device_new(ei);
|
||||
struct ei_seat *seat = peck_ei_get_default_seat(peck);
|
||||
device = ei_device_new(seat);
|
||||
ei_device_configure_name(device, __func__);
|
||||
ei_device_configure_capability(device, EI_DEVICE_CAP_KEYBOARD);
|
||||
|
||||
|
|
|
|||
|
|
@ -79,11 +79,13 @@ MUNIT_TEST(eistest_ranges)
|
|||
_cleanup_peck_ struct peck *peck = peck_new();
|
||||
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_CLIENT);
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_DEFAULT_SEAT);
|
||||
|
||||
peck_dispatch_until_stable(peck);
|
||||
|
||||
with_client(peck) {
|
||||
_cleanup_ei_device_ struct ei_device *d = ei_device_new(ei);
|
||||
struct ei_seat *seat = peck_ei_get_default_seat(peck);
|
||||
_cleanup_ei_device_ struct ei_device *d = ei_device_new(seat);
|
||||
ei_device_configure_capability(d, EI_DEVICE_CAP_POINTER_ABSOLUTE);
|
||||
ei_device_configure_capability(d, EI_DEVICE_CAP_TOUCH);
|
||||
ei_device_pointer_configure_range(d, 1024, 768);
|
||||
|
|
@ -115,10 +117,12 @@ MUNIT_TEST(eistest_device_resume_suspend_twice)
|
|||
_cleanup_eis_device_ struct eis_device *device = NULL;
|
||||
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_CLIENT);
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_DEFAULT_SEAT);
|
||||
peck_dispatch_until_stable(peck);
|
||||
|
||||
with_client(peck) {
|
||||
_cleanup_ei_device_ struct ei_device *d = ei_device_new(ei);
|
||||
struct ei_seat *seat = peck_ei_get_default_seat(peck);
|
||||
_cleanup_ei_device_ struct ei_device *d = ei_device_new(seat);
|
||||
ei_device_configure_capability(d, EI_DEVICE_CAP_POINTER);
|
||||
ei_device_add(d);
|
||||
}
|
||||
|
|
@ -181,10 +185,12 @@ MUNIT_TEST(eistest_device_ignore_suspended)
|
|||
_cleanup_eis_device_ struct eis_device *device = NULL;
|
||||
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_CLIENT);
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_DEFAULT_SEAT);
|
||||
peck_dispatch_until_stable(peck);
|
||||
|
||||
with_client(peck) {
|
||||
_cleanup_ei_device_ struct ei_device *d = ei_device_new(ei);
|
||||
struct ei_seat *seat = peck_ei_get_default_seat(peck);
|
||||
_cleanup_ei_device_ struct ei_device *d = ei_device_new(seat);
|
||||
ei_device_configure_capability(d, EI_DEVICE_CAP_POINTER);
|
||||
ei_device_add(d);
|
||||
}
|
||||
|
|
@ -264,10 +270,12 @@ MUNIT_TEST(eistest_device_late_connect)
|
|||
_cleanup_ei_device_ struct ei_device *ei_device = NULL;
|
||||
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_CLIENT);
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_DEFAULT_SEAT);
|
||||
peck_dispatch_until_stable(peck);
|
||||
|
||||
with_client(peck) {
|
||||
ei_device = ei_device_new(ei);
|
||||
struct ei_seat *seat = peck_ei_get_default_seat(peck);
|
||||
ei_device = ei_device_new(seat);
|
||||
ei_device_configure_capability(ei_device, EI_DEVICE_CAP_POINTER);
|
||||
ei_device_add(ei_device);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -247,18 +247,14 @@ int main(int argc, char **argv)
|
|||
.events = POLLIN,
|
||||
.revents = 0,
|
||||
};
|
||||
|
||||
_cleanup_(ei_device_unrefp) struct ei_device *ptr = ei_device_new(ei);
|
||||
ei_device_configure_capability(ptr, EI_DEVICE_CAP_POINTER);
|
||||
|
||||
_cleanup_(ei_device_unrefp) struct ei_device *kbd = ei_device_new(ei);
|
||||
ei_device_configure_capability(kbd, EI_DEVICE_CAP_KEYBOARD);
|
||||
if (layout)
|
||||
setup_keymap(kbd, layout);
|
||||
_cleanup_(ei_device_unrefp) struct ei_device *ptr = NULL;
|
||||
_cleanup_(ei_device_unrefp) struct ei_device *kbd = NULL;
|
||||
|
||||
bool stop = false;
|
||||
bool have_ptr = false;
|
||||
bool have_kbd = false;
|
||||
struct ei_seat *default_seat = NULL;
|
||||
|
||||
while (!stop && poll(&fds, 1, 2000) > -1) {
|
||||
ei_dispatch(ei);
|
||||
|
||||
|
|
@ -270,8 +266,6 @@ int main(int argc, char **argv)
|
|||
switch(ei_event_get_type(e)) {
|
||||
case EI_EVENT_CONNECT:
|
||||
colorprint("connected\n");
|
||||
ei_device_add(ptr);
|
||||
ei_device_add(kbd);
|
||||
break;
|
||||
case EI_EVENT_DISCONNECT:
|
||||
{
|
||||
|
|
@ -279,6 +273,30 @@ int main(int argc, char **argv)
|
|||
stop = true;
|
||||
break;
|
||||
}
|
||||
case EI_EVENT_SEAT_ADDED:
|
||||
{
|
||||
if (default_seat) {
|
||||
colorprint("ignoring other seats\n");
|
||||
break;
|
||||
}
|
||||
default_seat = ei_seat_ref(ei_event_get_seat(e));
|
||||
colorprint("seat added: %s\n", ei_seat_get_name(default_seat));
|
||||
ptr = ei_device_new(default_seat);
|
||||
ei_device_configure_capability(ptr, EI_DEVICE_CAP_POINTER);
|
||||
|
||||
kbd = ei_device_new(default_seat);
|
||||
ei_device_configure_capability(kbd, EI_DEVICE_CAP_KEYBOARD);
|
||||
if (layout)
|
||||
setup_keymap(kbd, layout);
|
||||
|
||||
ei_device_add(ptr);
|
||||
ei_device_add(kbd);
|
||||
break;
|
||||
}
|
||||
case EI_EVENT_SEAT_REMOVED:
|
||||
if (ei_event_get_seat(e) == default_seat)
|
||||
default_seat = ei_seat_unref(default_seat);
|
||||
break;
|
||||
case EI_EVENT_DEVICE_ADDED:
|
||||
colorprint("our device was accepted, waiting for resume\n");
|
||||
handle_keymap(e);
|
||||
|
|
|
|||
|
|
@ -55,6 +55,8 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(struct eis_event *, eis_event_unref);
|
|||
#define _cleanup_eis_event_ _cleanup_(eis_event_unrefp)
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct eis_keymap *, eis_keymap_unref);
|
||||
#define _cleanup_eis_keymap_ _cleanup_(eis_keymap_unrefp)
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct eis_seat *, eis_seat_unref);
|
||||
#define _cleanup_eis_seat_ _cleanup_(eis_seat_unrefp)
|
||||
|
||||
static void unlink_free(char **path) {
|
||||
if (*path) {
|
||||
|
|
@ -192,7 +194,13 @@ eis_demo_server_printf_handle_event(struct eis_demo_server *server,
|
|||
colorprint("new client: %s\n", eis_client_get_name(client));
|
||||
/* insert sophisticated authentication here */
|
||||
eis_client_connect(client);
|
||||
colorprint("accepting client\n");
|
||||
colorprint("accepting client, creating new seat 'default'\n");
|
||||
_cleanup_eis_seat_ struct eis_seat *seat = eis_client_new_seat(client, "default");
|
||||
eis_seat_allow_capability(seat, EIS_DEVICE_CAP_POINTER);
|
||||
eis_seat_allow_capability(seat, EIS_DEVICE_CAP_POINTER_ABSOLUTE);
|
||||
eis_seat_allow_capability(seat, EIS_DEVICE_CAP_KEYBOARD);
|
||||
eis_seat_allow_capability(seat, EIS_DEVICE_CAP_TOUCH);
|
||||
eis_seat_add(seat);
|
||||
break;
|
||||
}
|
||||
case EIS_EVENT_CLIENT_DISCONNECT:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue