libeis: switch the keymap to be a separate object

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
Peter Hutterer 2020-09-29 13:56:58 +10:00
parent 937f9fd8c5
commit 7318512a89
8 changed files with 205 additions and 108 deletions

View file

@ -179,12 +179,8 @@ _public_
OBJECT_IMPLEMENT_GETTER(ei_keymap, fd, int);
_public_
OBJECT_IMPLEMENT_GETTER(ei_keymap, size, size_t);
_public_ struct ei_device *
ei_keymap_get_device(struct ei_keymap *keymap)
{
return keymap->device;
}
_public_
OBJECT_IMPLEMENT_GETTER(ei_keymap, device, struct ei_device *);
static void
ei_keymap_destroy(struct ei_keymap *keymap)
@ -276,6 +272,9 @@ ei_device_set_keymap(struct ei_device *device,
{
device->keymap = ei_keymap_unref(device->keymap);
if (!type)
return;
_cleanup_ei_keymap_ struct ei_keymap *keymap = ei_keymap_new(type, keymap_fd, size);
if (!keymap) {
log_bug(ei_device_get_context(device),

View file

@ -31,11 +31,84 @@
#include "libeis-private.h"
_public_
OBJECT_IMPLEMENT_REF(eis_keymap);
_public_
OBJECT_IMPLEMENT_UNREF(eis_keymap);
#define _cleanup_eis_keymap_ _cleanup_(eis_keymap_cleanup)
_public_
OBJECT_IMPLEMENT_GETTER(eis_keymap, type, enum eis_keymap_type);
_public_
OBJECT_IMPLEMENT_GETTER(eis_keymap, fd, int);
_public_
OBJECT_IMPLEMENT_GETTER(eis_keymap, size, size_t);
static void
eis_keymap_destroy(struct eis_keymap *keymap)
{
xclose(keymap->fd);
}
static
OBJECT_IMPLEMENT_CREATE(eis_keymap);
_public_ struct eis_keymap *
eis_keymap_new(enum eis_keymap_type type, int fd, size_t size)
{
_cleanup_eis_keymap_ struct eis_keymap *keymap = eis_keymap_create(NULL);
switch (type) {
case EIS_KEYMAP_TYPE_XKB:
break;
default:
return NULL;
}
if (fd < 0 || size == 0)
return NULL;
int newfd = dup(fd);
if (newfd < 0)
return NULL;
keymap->fd = newfd;
keymap->type = type;
keymap->size = size;
return eis_keymap_ref(keymap);
}
_public_ void
eis_device_keyboard_set_keymap(struct eis_device *device,
struct eis_keymap *keymap)
{
if (device->state != EIS_DEVICE_STATE_NEW)
return;
if (device->keymap && !device->keymap->is_client_keymap)
return;
if (keymap && keymap->assigned)
return;
device->keymap = eis_keymap_unref(device->keymap);
if (keymap) {
keymap->assigned = true;
device->keymap = eis_keymap_ref(keymap);
}
}
_public_ struct eis_keymap *
eis_device_keyboard_get_keymap(struct eis_device *device)
{
return device->keymap;
}
static void
eis_device_destroy(struct eis_device *device)
{
eis_keymap_unref(device->keymap);
free(device->name);
xclose(device->keymap.fd);
}
_public_
@ -83,11 +156,6 @@ eis_device_new(struct eis_client *client,
device->id = id;
device->state = EIS_DEVICE_STATE_NEW;
device->keymap.server_overrides = false;
device->keymap.fd = -1;
device->keymap.type = EIS_KEYMAP_TYPE_NONE;
device->keymap.size = 0;
return device;
}
@ -115,24 +183,14 @@ eis_device_set_client_keymap(struct eis_device *device,
if (device->state != EIS_DEVICE_STATE_NEW)
return;
device->keymap.fd = dup(keymap_fd);
device->keymap.type = type;
device->keymap.size = size;
}
_public_ void
eis_device_keyboard_set_keymap(struct eis_device *device,
enum eis_keymap_type type,
int keymap_fd, size_t size)
{
if (device->state != EIS_DEVICE_STATE_NEW)
_cleanup_eis_keymap_ struct eis_keymap *keymap =
eis_keymap_new(type, keymap_fd, size);
if (!keymap)
return;
device->keymap.type = type;
xclose(device->keymap.fd);
device->keymap.fd = dup(keymap_fd);
device->keymap.server_overrides = true;
device->keymap.size = size;
eis_device_keyboard_set_keymap(device, keymap);
keymap->is_client_keymap = true;
keymap->assigned = true;
}
_public_ bool
@ -187,24 +245,6 @@ eis_device_touch_get_height(struct eis_device *device)
return device->touch.dim.height;
}
_public_ enum eis_keymap_type
eis_device_keyboard_get_keymap_type(struct eis_device *device)
{
return device->keymap.type;
}
_public_ size_t
eis_device_keyboard_get_keymap_size(struct eis_device *device)
{
return device->keymap.size;
}
_public_ int
eis_device_keyboard_get_keymap(struct eis_device *device)
{
return device->keymap.fd;
}
int
eis_device_pointer_rel(struct eis_device *device,
double x, double y)

View file

@ -103,12 +103,7 @@ struct eis_device {
struct dimensions dim;
} touch;
struct {
bool server_overrides;
enum eis_keymap_type type;
int fd;
size_t size;
} keymap;
struct eis_keymap *keymap;
};
struct eis_event {
@ -136,6 +131,16 @@ struct eis_event {
};
};
struct eis_keymap {
struct object object;
struct eis_device *device;
enum eis_keymap_type type;
int fd;
size_t size;
bool assigned;
bool is_client_keymap;
};
void
eis_init_object(struct eis *eis, struct object *parent);
@ -183,11 +188,6 @@ eis_device_set_client_keymap(struct eis_device *device,
enum eis_keymap_type type,
int keymap_fd, size_t size);
void
eis_device_keyboard_set_keymap(struct eis_device *device,
enum eis_keymap_type type,
int keymap_fd, size_t size);
int
eis_device_pointer_rel(struct eis_device *device,
double x, double y);

View file

@ -142,21 +142,26 @@ eis_proto_send_device_added(struct eis_client *client, struct eis_device *device
{
ServerMessage msg = SERVER_MESSAGE__INIT;
DeviceAdded added = DEVICE_ADDED__INIT;
int fds[2] = {-1, -1};
added.deviceid = device->id;
added.name = device->name;
added.capabilities = device->capabilities;
added.keymap_type = device->keymap.type;
added.keymap_size = device->keymap.size;
added.keymap_from_server = device->keymap.server_overrides;
if (device->keymap) {
struct eis_keymap *keymap = device->keymap;
added.keymap_type = keymap->type;
added.keymap_size = keymap->size;
added.keymap_from_server = !keymap->is_client_keymap;
if (!keymap->is_client_keymap)
fds[0] = keymap->fd;
} else {
/* it's NULL anyway */
added.keymap_from_server = true;
}
msg.device_added = &added;
msg.msg_case = SERVER_MESSAGE__MSG_DEVICE_ADDED;
int fds[2] = {-1, -1};
if (device->keymap.server_overrides)
fds[0] = device->keymap.fd;
return eis_proto_send_msg_with_fds(client, &msg, fds);
}
@ -247,7 +252,7 @@ eis_proto_parse_message(struct brei_message *bmsg, size_t *consumed)
.add_device.keymap_size = a->keymap_size,
};
if (a->keymap_type != EIS_KEYMAP_TYPE_NONE)
if (a->keymap_type)
msg->add_device.keymap_fd = brei_message_take_fd(bmsg);
}
break;

View file

@ -45,6 +45,7 @@ struct eis;
struct eis_client;
struct eis_device;
struct eis_event;
struct eis_keymap;
enum eis_device_capability {
EIS_DEVICE_CAP_POINTER = 1,
@ -54,8 +55,7 @@ enum eis_device_capability {
};
enum eis_keymap_type {
EIS_KEYMAP_TYPE_NONE = 0,
EIS_KEYMAP_TYPE_XKB,
EIS_KEYMAP_TYPE_XKB = 1,
};
enum eis_event_type {
@ -433,50 +433,92 @@ eis_device_touch_get_width(struct eis_device *device);
uint32_t
eis_device_touch_get_height(struct eis_device *device);
/**
* Create a new keymap of the given @p type. This keymap does not immediately
* apply to the device, use eis_device_keyboard_set_keymap() to apply
* this keymap. A keymap may only be applied once and to a single device.
*
* The returned keymap has a refcount of at least 1, use eis_keymap_unref()
* to release resources associated with this keymap.
*
* @param type The type of the keymap.
* @param fd A memmap-able file descriptor of size @p size pointing to the
* keymap used by this device. @p fd can be closed by the caller after this
* function completes.
* @param size The size of the data at @p fd in bytes
*
* @return A keymap object or `NULL` on failure.
*/
struct eis_keymap *
eis_keymap_new(enum eis_keymap_type type, int fd, size_t size);
/**
* @return the size of the keymap in bytes
*/
size_t
eis_keymap_get_size(struct eis_keymap *keymap);
/**
* Returns the type for this keymap. The type specifies how to interpret the
* data at the file descriptor returned by eis_keymap_get_fd().
*/
enum eis_keymap_type
eis_keymap_get_type(struct eis_keymap *keymap);
/**
* Return a memmap-able file descriptor pointing to the keymap used by the
* device. The keymap is constant for the lifetime of the device and
* assigned to this device individually.
*
* If this function returns -1, this device does not have
* an individual keymap assigned.
*/
int
eis_device_keyboard_get_keymap(struct eis_device *device);
eis_keymap_get_fd(struct eis_keymap *keymap);
size_t
eis_device_keyboard_get_keymap_size(struct eis_device *device);
struct eis_keymap *
eis_keymap_ref(struct eis_keymap *keymap);
enum eis_keymap_type
eis_device_keyboard_get_keymap_type(struct eis_device *device);
struct eis_keymap *
eis_keymap_unref(struct eis_keymap *keymap);
/**
* Set the keymap on the device. This overwrites the client's choice of
* keyboard. Note that **not** calling this function when
* eis_device_keyboard_get_keymap() returns a value other than -1 is equivalent to
* Return the device this keymap belongs to, or `NULL` if it has not yet
* been assigned to a device.
*
* If the keymap is a client-assigned keymap and the server has changed or
* unset the keymap with eis_device_keyboard_set_keymap(), this function
* returns `NULL`.
*
*/
struct eis_device *
eis_keymap_get_device(struct eis_keymap *keymap);
/**
* Return the keymap assigned to this device. The return value of this
* function is the client-assigned keymap (if any) before the call to
* eis_device_keyboard_set_keymap(), or the server-assigned one after.
*/
struct eis_keymap *
eis_device_keyboard_get_keymap(struct eis_device *device);
/**
* Set the keymap on the device. This overwrites the client's keymap
* choice. Note that **not** calling this function when
* eis_device_keyboard_get_keymap() returns non-`NULL` is equivalent to
* accepting the client's choice of keymap.
*
* If the fd is not -1, it is a memmap-able file descriptor pointing to the
* keymap used by the device. This keymap is constant for the lifetime of
* the device and assigned to this device individually. Where the keymap has
* to change, remove the device and wait for the client to create a new one.
* If the keymap is not `NULL`, the keymap is the one used by this device.
* This keymap is constant for the lifetime of the device and assigned to
* this device individually. Where the keymap has to change, remove the
* device and wait for the client to create a new one.
*
* If the fd is -1, the device does not have an individual keymap assigned.
* and keymap type argument is ignored. A server that does not handle
* individual client keymaps must call this function with an fd of
* -1.
* If the keymap is `NULL`, the device does not have an individual keymap
* assigned. A server that does not handle individual client keymaps must
* call this function with an @p keymap of `NULL`.
*
* This function has no effect if called after eis_device_connect()
*
* @param device the EIS device
* @param type the type of the keymap
* @param fd a memmap-able file descriptor to the keymap
* @param size the size of the keymap in bytes
*/
void
eis_device_keyboard_set_keymap(struct eis_device *device,
enum eis_keymap_type type,
int fd, size_t size);
struct eis_keymap *keymap);
/**
* Return the device from this event.

View file

@ -233,6 +233,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_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)
/* Macros intended just for readability to make it more obvious which part
of a test handles server vs client */

View file

@ -1004,11 +1004,12 @@ MUNIT_TEST(test_ei_keymap_set)
_cleanup_eis_event_ struct eis_event *event =
peck_eis_next_event(eis, EIS_EVENT_DEVICE_ADDED);
struct eis_device *eis_device = eis_event_get_device(event);
struct eis_keymap *eis_keymap = eis_device_keyboard_get_keymap(eis_device);
int fd = eis_device_keyboard_get_keymap(eis_device);
int fd = eis_keymap_get_fd(eis_keymap);
munit_assert_int(fd, !=, -1);
munit_assert_uint(eis_device_keyboard_get_keymap_size(eis_device), ==, memfile_get_size(fd1));
munit_assert_uint(eis_device_keyboard_get_keymap_type(eis_device), ==, EIS_KEYMAP_TYPE_XKB);
munit_assert_uint(eis_keymap_get_size(eis_keymap), ==, memfile_get_size(fd1));
munit_assert_uint(eis_keymap_get_type(eis_keymap), ==, EIS_KEYMAP_TYPE_XKB);
eis_device_disconnect(eis_device);
}
@ -1058,7 +1059,7 @@ MUNIT_TEST(test_ei_keymap_null)
_cleanup_eis_event_ struct eis_event *event =
peck_eis_next_event(eis, EIS_EVENT_DEVICE_ADDED);
struct eis_device *device = eis_event_get_device(event);
eis_device_keyboard_set_keymap(device, EIS_KEYMAP_TYPE_NONE, -1, 0);
eis_device_keyboard_set_keymap(device, NULL);
eis_device_allow_capability(device, EIS_DEVICE_CAP_KEYBOARD);
eis_device_connect(device);
}
@ -1109,9 +1110,10 @@ MUNIT_TEST(test_ei_keymap_changed)
_cleanup_eis_event_ struct eis_event *event =
peck_eis_next_event(eis, EIS_EVENT_DEVICE_ADDED);
struct eis_device *device = eis_event_get_device(event);
eis_device_keyboard_set_keymap(device, EIS_KEYMAP_TYPE_XKB,
memfile_get_fd(fd1),
memfile_get_size(fd1));
_cleanup_eis_keymap_ struct eis_keymap *keymap =
eis_keymap_new(EIS_KEYMAP_TYPE_XKB, memfile_get_fd(fd1),
memfile_get_size(fd1));
eis_device_keyboard_set_keymap(device, keymap);
eis_device_allow_capability(device, EIS_DEVICE_CAP_KEYBOARD);
eis_device_connect(device);
}

View file

@ -53,6 +53,8 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(struct eis *, eis_unref);
#define _cleanup_eis_ _cleanup_(eis_unrefp)
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)
static void unlink_free(char **path) {
if (*path) {
@ -116,17 +118,22 @@ setup_keymap(struct eis_demo_server *server, struct eis_device *device)
if (!f)
return;
eis_device_keyboard_set_keymap(device, EIS_KEYMAP_TYPE_XKB,
memfile_get_fd(f), memfile_get_size(f));
_cleanup_eis_keymap_ struct eis_keymap *k =
eis_keymap_new(EIS_KEYMAP_TYPE_XKB, memfile_get_fd(f),
memfile_get_size(f));
eis_device_keyboard_set_keymap(device, k);
memfile_unref(f);
return;
}
if (eis_device_keyboard_get_keymap_type(device) == EIS_KEYMAP_TYPE_NONE)
struct eis_keymap *keymap = eis_device_keyboard_get_keymap(device);
if (!keymap)
return;
colorprint("Using client keymap\n");
int fd = eis_device_keyboard_get_keymap(device);
size_t size = eis_device_keyboard_get_keymap_size(device);
int fd = eis_keymap_get_fd(keymap);
size_t size = eis_keymap_get_size(keymap);
char *str = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
if (str == MAP_FAILED)
return;
@ -136,18 +143,18 @@ setup_keymap(struct eis_demo_server *server, struct eis_device *device)
if (!ctx)
return;
_cleanup_xkb_keymap_ struct xkb_keymap *keymap =
_cleanup_xkb_keymap_ struct xkb_keymap *xkb_keymap =
xkb_keymap_new_from_string(ctx, str,
XKB_KEYMAP_FORMAT_TEXT_V1, 0);
if (!keymap)
return;
_cleanup_xkb_state_ struct xkb_state *state = xkb_state_new(keymap);
_cleanup_xkb_state_ struct xkb_state *state = xkb_state_new(xkb_keymap);
if (!state)
return;
server->ctx = steal(&ctx);
server->keymap = steal(&keymap);
server->keymap = steal(&xkb_keymap);
server->state = steal(&state);
#endif
}