mirror of
https://gitlab.freedesktop.org/libinput/libei.git
synced 2026-05-08 09:18:03 +02:00
Restructure keymap handling to server-side only
This keeps most of the current structure but gets rid of client-side keymaps (which have been broken since the server-side devices anyway). The new approach: clients get a keymap (or NULL) from the server, if they don't like it they will have to do transformation on their side. Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
parent
55b79c44a5
commit
3abf13742a
13 changed files with 95 additions and 303 deletions
|
|
@ -170,7 +170,6 @@ message DeviceAdded {
|
|||
uint32 deviceid = 1;
|
||||
uint32 capabilities = 2;
|
||||
/* keymap is passed as fd if size is nonzero and type is not none */
|
||||
bool keymap_from_server = 3;
|
||||
uint32 keymap_type = 4;
|
||||
uint32 keymap_size = 5;
|
||||
string name = 6;
|
||||
|
|
|
|||
|
|
@ -152,8 +152,6 @@ OBJECT_IMPLEMENT_UNREF(ei_keymap);
|
|||
_public_
|
||||
OBJECT_IMPLEMENT_GETTER(ei_keymap, type, enum ei_keymap_type);
|
||||
_public_
|
||||
OBJECT_IMPLEMENT_GETTER(ei_keymap, source, enum ei_keymap_source);
|
||||
_public_
|
||||
OBJECT_IMPLEMENT_GETTER(ei_keymap, fd, int);
|
||||
_public_
|
||||
OBJECT_IMPLEMENT_GETTER(ei_keymap, size, size_t);
|
||||
|
|
@ -175,43 +173,7 @@ ei_device_keyboard_get_keymap(struct ei_device *device)
|
|||
return device->keymap;
|
||||
}
|
||||
|
||||
_public_ void
|
||||
ei_device_keyboard_configure_keymap(struct ei_device *device,
|
||||
struct ei_keymap *keymap)
|
||||
{
|
||||
if (!ei_device_has_capability(device, EI_DEVICE_CAP_KEYBOARD)) {
|
||||
log_bug_client(ei_device_get_context(device),
|
||||
"%s: Device is not a keyboard\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Can only call this once */
|
||||
if (device->keymap) {
|
||||
log_bug_client(ei_device_get_context(device),
|
||||
"%s: Device already has a keymap\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!keymap) {
|
||||
log_bug_client(ei_device_get_context(device),
|
||||
"%s: Keymap has already been used\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Reject any previously used keymaps */
|
||||
if (keymap->assigned) {
|
||||
log_bug_client(ei_device_get_context(device),
|
||||
"%s: Keymap has already been used\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
keymap->assigned = true;
|
||||
keymap->source = EI_KEYMAP_SOURCE_CLIENT;
|
||||
keymap->device = device;
|
||||
device->keymap = ei_keymap_ref(keymap);
|
||||
}
|
||||
|
||||
_public_ struct ei_keymap *
|
||||
static struct ei_keymap *
|
||||
ei_keymap_new(enum ei_keymap_type type, int fd, size_t size)
|
||||
{
|
||||
_unref_(ei_keymap) *keymap = ei_keymap_create(NULL);
|
||||
|
|
@ -255,7 +217,6 @@ ei_device_set_keymap(struct ei_device *device,
|
|||
}
|
||||
|
||||
keymap->device = device;
|
||||
keymap->source = EI_KEYMAP_SOURCE_SERVER;
|
||||
device->keymap = ei_keymap_ref(keymap);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -130,7 +130,6 @@ struct ei_device {
|
|||
struct ei_keymap {
|
||||
struct object object;
|
||||
struct ei_device *device;
|
||||
enum ei_keymap_source source;
|
||||
enum ei_keymap_type type;
|
||||
int fd;
|
||||
size_t size;
|
||||
|
|
|
|||
|
|
@ -110,11 +110,10 @@ ei_proto_parse_message(struct brei_message *bmsg, size_t *consumed)
|
|||
.device_added.capabilities = a->capabilities,
|
||||
.device_added.keymap_fd = -1,
|
||||
.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)
|
||||
if (a->keymap_type)
|
||||
msg->device_added.keymap_fd = brei_message_take_fd(bmsg);
|
||||
}
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -85,7 +85,6 @@ struct message {
|
|||
char *name;
|
||||
uint32_t capabilities;
|
||||
enum ei_keymap_type keymap_type;
|
||||
bool keymap_from_server;
|
||||
int keymap_fd;
|
||||
size_t keymap_size;
|
||||
uint32_t seatid;
|
||||
|
|
|
|||
|
|
@ -524,7 +524,7 @@ handle_msg_seat_removed(struct ei *ei, uint32_t seatid)
|
|||
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,
|
||||
enum ei_keymap_type keymap_type,
|
||||
int keymap_fd, size_t keymap_sz,
|
||||
uint32_t seatid)
|
||||
{
|
||||
|
|
@ -548,9 +548,7 @@ handle_msg_device_added(struct ei *ei, uint32_t deviceid,
|
|||
_unref_(ei_device) *device = ei_device_new(seat, deviceid);
|
||||
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_set_keymap(device, keymap_type, keymap_fd, keymap_sz);
|
||||
ei_device_added(device);
|
||||
|
||||
log_debug(ei,
|
||||
|
|
@ -877,7 +875,6 @@ connection_connected_handle_msg(struct ei *ei, struct message *msg)
|
|||
msg->device_added.deviceid,
|
||||
msg->device_added.name,
|
||||
msg->device_added.capabilities,
|
||||
msg->device_added.keymap_from_server,
|
||||
msg->device_added.keymap_type,
|
||||
msg->device_added.keymap_fd,
|
||||
msg->device_added.keymap_size,
|
||||
|
|
|
|||
86
src/libei.h
86
src/libei.h
|
|
@ -154,25 +154,6 @@ enum ei_keymap_type {
|
|||
EI_KEYMAP_TYPE_XKB = 1,
|
||||
};
|
||||
|
||||
/**
|
||||
* @enum ei_keymap_source
|
||||
*
|
||||
* Identifies who provided a struct @ref ei_keymap.
|
||||
*/
|
||||
enum ei_keymap_source {
|
||||
/**
|
||||
* The keymap is the one provided by the client.
|
||||
*/
|
||||
EI_KEYMAP_SOURCE_CLIENT = 1,
|
||||
/**
|
||||
* The keymap is provided by the server.
|
||||
*/
|
||||
EI_KEYMAP_SOURCE_SERVER,
|
||||
};
|
||||
|
||||
/**
|
||||
* @enum ei_keymap_source
|
||||
*/
|
||||
enum ei_event_type {
|
||||
/**
|
||||
* The server has approved the connection to this client. Where the
|
||||
|
|
@ -615,24 +596,8 @@ void *
|
|||
ei_device_get_user_data(struct ei_device *device);
|
||||
|
||||
|
||||
/**
|
||||
* Create a new keymap of the given @a type. This keymap does not immediately
|
||||
* apply to the device, use ei_device_keyboard_configure_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 ei_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 @a size pointing to the
|
||||
* keymap used by this device. @a fd can be closed by the caller after this
|
||||
* function completes.
|
||||
* @param size The size of the data at @a fd in bytes
|
||||
*
|
||||
* @return A keymap object or `NULL` on failure.
|
||||
*/
|
||||
struct ei_keymap *
|
||||
ei_keymap_new(enum ei_keymap_type type, int fd, size_t size);
|
||||
ei_device_get_keymap(struct ei_device *device);
|
||||
|
||||
/**
|
||||
* @return the size of the keymap in bytes
|
||||
|
|
@ -655,22 +620,6 @@ ei_keymap_get_type(struct ei_keymap *keymap);
|
|||
int
|
||||
ei_keymap_get_fd(struct ei_keymap *keymap);
|
||||
|
||||
/**
|
||||
* Returns the source for the keymap on this device, if any. This is a
|
||||
* convenience function for the client to check if its keymap was accepted.
|
||||
*
|
||||
* Where ei_device_keyboard_get_keymap() returns a value other `NULL` and
|
||||
* this function returns @ref EI_KEYMAP_SOURCE_CLIENT, the keymap is the one
|
||||
* provided with ei_device_keyboard_configure_keymap().
|
||||
*
|
||||
* Where ei_device_keyboard_get_keymap() returns a value other than `NULL`
|
||||
* and this function returns @ref EI_KEYMAP_SOURCE_SERVER, the keymap is one
|
||||
* created by the server and **not** the one provided with
|
||||
* ei_device_keyboard_configure_keymap().
|
||||
*/
|
||||
enum ei_keymap_source
|
||||
ei_keymap_get_source(struct ei_keymap *keymap);
|
||||
|
||||
/**
|
||||
* Return the device this keymap belongs to, or `NULL` if it has not yet
|
||||
* been assigned to a device.
|
||||
|
|
@ -705,39 +654,6 @@ ei_keymap_ref(struct ei_keymap *keymap);
|
|||
struct ei_keymap *
|
||||
ei_keymap_unref(struct ei_keymap *keymap);
|
||||
|
||||
/**
|
||||
* Request this keymap for this device with the @ref EI_DEVICE_CAP_KEYBOARD
|
||||
* capability.
|
||||
*
|
||||
* The keymap for this device is a suggestion to the server, the actual
|
||||
* keymap used by this device is provided with the @ref
|
||||
* EI_EVENT_DEVICE_ADDED event. It is the client's responsibility to
|
||||
* handle the situation where the server assigns a specific keymap (or none)
|
||||
* that differs to the requested keymap.
|
||||
*
|
||||
* Note that keymap handling for individual input devices is largely
|
||||
* left to private implementation details in the server. For example,
|
||||
* modifier state or group handling may differ between server
|
||||
* implementations.
|
||||
*
|
||||
* A keymap can only be used once and for one device only.
|
||||
* Once a keymap has been assigned to a device, the caller may drop
|
||||
* remaining references using ei_keymap_unref().
|
||||
*
|
||||
* This function can only be called once per device, further calls are
|
||||
* ignored.
|
||||
*
|
||||
* This function has no effect if called after ei_device_add(). To change
|
||||
* the keymap, the device must be removed and re-added with a different
|
||||
* keymap.
|
||||
*
|
||||
* @param device The EI device
|
||||
* @param keymap A non-`NULL` keymap
|
||||
*/
|
||||
void
|
||||
ei_device_keyboard_configure_keymap(struct ei_device *device,
|
||||
struct ei_keymap *keymap);
|
||||
|
||||
/**
|
||||
* Notify the server that the client is no longer listening to events
|
||||
* from this device.
|
||||
|
|
|
|||
|
|
@ -41,10 +41,14 @@ _public_
|
|||
OBJECT_IMPLEMENT_GETTER(eis_keymap, fd, int);
|
||||
_public_
|
||||
OBJECT_IMPLEMENT_GETTER(eis_keymap, size, size_t);
|
||||
_public_
|
||||
OBJECT_IMPLEMENT_GETTER(eis_keymap, device, struct eis_device *);
|
||||
|
||||
static void
|
||||
eis_keymap_destroy(struct eis_keymap *keymap)
|
||||
{
|
||||
if (!keymap->assigned)
|
||||
eis_device_unref(keymap->device);
|
||||
xclose(keymap->fd);
|
||||
}
|
||||
|
||||
|
|
@ -52,10 +56,9 @@ static
|
|||
OBJECT_IMPLEMENT_CREATE(eis_keymap);
|
||||
|
||||
_public_ struct eis_keymap *
|
||||
eis_keymap_new(enum eis_keymap_type type, int fd, size_t size)
|
||||
eis_keymap_new(struct eis_device *device,
|
||||
enum eis_keymap_type type, int fd, size_t size)
|
||||
{
|
||||
_unref_(eis_keymap) *keymap = eis_keymap_create(NULL);
|
||||
|
||||
switch (type) {
|
||||
case EIS_KEYMAP_TYPE_XKB:
|
||||
break;
|
||||
|
|
@ -70,11 +73,13 @@ eis_keymap_new(enum eis_keymap_type type, int fd, size_t size)
|
|||
if (newfd < 0)
|
||||
return NULL;
|
||||
|
||||
struct eis_keymap *keymap = eis_keymap_create(NULL);
|
||||
keymap->device = eis_device_ref(device);
|
||||
keymap->fd = newfd;
|
||||
keymap->type = type;
|
||||
keymap->size = size;
|
||||
|
||||
return eis_keymap_ref(keymap);
|
||||
return keymap;
|
||||
}
|
||||
|
||||
struct eis *
|
||||
|
|
@ -84,32 +89,27 @@ eis_device_get_context(struct eis_device *device)
|
|||
}
|
||||
|
||||
_public_ void
|
||||
eis_device_keyboard_set_keymap(struct eis_device *device,
|
||||
struct eis_keymap *keymap)
|
||||
eis_keymap_add(struct eis_keymap *keymap)
|
||||
{
|
||||
struct eis_device *device = eis_keymap_get_device(keymap);
|
||||
|
||||
if (device->state != EIS_DEVICE_STATE_NEW) {
|
||||
log_bug_client(eis_device_get_context(device),
|
||||
"%s: device already (dis)connected\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (device->keymap && !device->keymap->is_client_keymap) {
|
||||
if (device->keymap) {
|
||||
log_bug_client(eis_device_get_context(device),
|
||||
"%s: keymap can only be configured once\n", __func__);
|
||||
"%s: only one keymap can only be assigned and only once\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (keymap && keymap->assigned) {
|
||||
log_bug_client(eis_device_get_context(device),
|
||||
"%s: keymaps cannot be re-used\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
device->keymap = eis_keymap_unref(device->keymap);
|
||||
if (keymap) {
|
||||
keymap->assigned = true;
|
||||
device->keymap = eis_keymap_ref(keymap);
|
||||
}
|
||||
/* New keymap holds ref to the device, for assigned keymap the device
|
||||
* holds the ref to the keymap instead */
|
||||
device->keymap = eis_keymap_ref(keymap);
|
||||
keymap->assigned = true;
|
||||
eis_device_unref(keymap->device);
|
||||
}
|
||||
|
||||
_public_ struct eis_keymap *
|
||||
|
|
@ -215,8 +215,16 @@ eis_device_configure_capability(struct eis_device *device, enum eis_device_capab
|
|||
_public_ void
|
||||
eis_device_add(struct eis_device *device)
|
||||
{
|
||||
if (device->state != EIS_DEVICE_STATE_NEW)
|
||||
if (device->state != EIS_DEVICE_STATE_NEW) {
|
||||
log_bug_client(eis_device_get_context(device),
|
||||
"%s: device already (dis)connected\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!device->capabilities) {
|
||||
log_bug_client(eis_device_get_context(device),
|
||||
"%s: adding device without capabilities\n", __func__);
|
||||
}
|
||||
|
||||
device->state = EIS_DEVICE_STATE_SUSPENDED;
|
||||
eis_client_add_device(eis_device_get_client(device), device);
|
||||
|
|
@ -234,33 +242,6 @@ eis_device_remove(struct eis_device *device)
|
|||
eis_device_unref(device);
|
||||
}
|
||||
|
||||
void
|
||||
eis_device_set_client_keymap(struct eis_device *device,
|
||||
enum eis_keymap_type type,
|
||||
int keymap_fd, size_t size)
|
||||
{
|
||||
if (device->state != EIS_DEVICE_STATE_NEW) {
|
||||
log_bug(eis_device_get_context(device),
|
||||
"%s: device already (dis)connected\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (type == 0 && keymap_fd == -1)
|
||||
return;
|
||||
|
||||
_unref_(eis_keymap) *keymap =
|
||||
eis_keymap_new(type, keymap_fd, size);
|
||||
if (!keymap) {
|
||||
log_bug(eis_device_get_context(device),
|
||||
"%s: keymap creation failed, using NULL keymap\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
eis_device_keyboard_set_keymap(device, keymap);
|
||||
keymap->is_client_keymap = true;
|
||||
keymap->assigned = true;
|
||||
}
|
||||
|
||||
_public_ bool
|
||||
eis_device_has_capability(struct eis_device *device,
|
||||
enum eis_device_capability cap)
|
||||
|
|
|
|||
|
|
@ -176,7 +176,6 @@ struct eis_keymap {
|
|||
int fd;
|
||||
size_t size;
|
||||
bool assigned;
|
||||
bool is_client_keymap;
|
||||
};
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -187,12 +187,7 @@ eis_proto_send_device_added(struct eis_client *client, struct eis_device *device
|
|||
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;
|
||||
fds[0] = keymap->fd;
|
||||
}
|
||||
|
||||
msg.device_added = &added;
|
||||
|
|
|
|||
46
src/libeis.h
46
src/libeis.h
|
|
@ -537,12 +537,13 @@ eis_device_resume(struct eis_device *device);
|
|||
|
||||
/**
|
||||
* Create a new keymap of the given @a 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.
|
||||
* apply to the device, use eis_keymap_add() 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 device The device with a @ref EIS_DEVICE_CAP_KEYBOARD capability
|
||||
* @param type The type of the keymap.
|
||||
* @param fd A memmap-able file descriptor of size @a size pointing to the
|
||||
* keymap used by this device. @a fd can be closed by the caller after this
|
||||
|
|
@ -552,7 +553,26 @@ eis_device_resume(struct eis_device *device);
|
|||
* @return A keymap object or `NULL` on failure.
|
||||
*/
|
||||
struct eis_keymap *
|
||||
eis_keymap_new(enum eis_keymap_type type, int fd, size_t size);
|
||||
eis_keymap_new(struct eis_device *device,
|
||||
enum eis_keymap_type type, int fd, size_t size);
|
||||
|
||||
/**
|
||||
* Set the keymap on the device. Note that **not** calling this function when
|
||||
* eis_device_keyboard_get_keymap() returns non-`NULL` meas the keymap is not
|
||||
* applied to the device.
|
||||
*
|
||||
* The 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 a keymap is `NULL`, the device does not have an individual keymap
|
||||
* assigned. Note that this may mean the client needs to guess at the
|
||||
* keymap layout.
|
||||
*
|
||||
* This function has no effect if called after eis_device_add()
|
||||
*/
|
||||
void
|
||||
eis_keymap_add(struct eis_keymap *keymap);
|
||||
|
||||
/**
|
||||
* @return the size of the keymap in bytes
|
||||
|
|
@ -601,26 +621,6 @@ eis_keymap_get_device(struct eis_keymap *keymap);
|
|||
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 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 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 @a keymap of `NULL`.
|
||||
*
|
||||
* This function has no effect if called after eis_device_connect()
|
||||
*/
|
||||
void
|
||||
eis_device_keyboard_set_keymap(struct eis_device *device,
|
||||
struct eis_keymap *keymap);
|
||||
|
||||
/**
|
||||
* For an event of type @ref EIS_EVENT_SEAT_BIND, return the capabilities
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <linux/input-event-codes.h>
|
||||
|
||||
#if HAVE_LIBXKBCOMMON
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
|
|
@ -69,43 +70,46 @@ colorprint(const char *format, ...)
|
|||
DEFINE_UNREF_CLEANUP_FUNC(xkb_context);
|
||||
DEFINE_UNREF_CLEANUP_FUNC(xkb_keymap);
|
||||
DEFINE_UNREF_CLEANUP_FUNC(xkb_state);
|
||||
DEFINE_UNREF_CLEANUP_FUNC(memfile);
|
||||
#endif
|
||||
|
||||
#if 0 /* FIXME: needs keymap revamp */
|
||||
static void
|
||||
setup_keymap(struct ei_device *kbd, const char *layout)
|
||||
setup_xkb_keymap(struct ei_keymap *keymap)
|
||||
{
|
||||
#if HAVE_LIBXKBCOMMON
|
||||
if (!keymap)
|
||||
return;
|
||||
|
||||
_unref_(xkb_context) *ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||
if (!ctx)
|
||||
return;
|
||||
|
||||
struct xkb_rule_names names = {
|
||||
.rules = "evdev",
|
||||
.model = "pc105",
|
||||
.layout = layout,
|
||||
};
|
||||
size_t sz = ei_keymap_get_size(keymap);
|
||||
_cleanup_free_ char *buf = xalloc(sz + 1);
|
||||
read(ei_keymap_get_fd(keymap), buf, sz);
|
||||
buf[sz] = '\0';
|
||||
|
||||
_unref_(xkb_keymap) *keymap = xkb_keymap_new_from_names(ctx, &names, 0);
|
||||
if (!keymap)
|
||||
_unref_(xkb_keymap) *xkbmap = xkb_keymap_new_from_string(ctx, buf,
|
||||
XKB_KEYMAP_FORMAT_TEXT_V1,
|
||||
XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
if (!xkbmap)
|
||||
return;
|
||||
|
||||
const char *str = xkb_keymap_get_as_string(keymap, XKB_KEYMAP_FORMAT_TEXT_V1);
|
||||
size_t len = strlen(str) - 1;
|
||||
|
||||
struct memfile *f = memfile_new(str, len);
|
||||
if (!f)
|
||||
_unref_(xkb_state) *xkbstate = xkb_state_new(xkbmap);
|
||||
if (!xkbstate)
|
||||
return;
|
||||
|
||||
_unref_(ei_keymap) *ei_keymap = ei_keymap_new(EI_KEYMAP_TYPE_XKB,
|
||||
memfile_get_fd(f),
|
||||
memfile_get_size(f));
|
||||
ei_device_keyboard_configure_keymap(kbd, ei_keymap);
|
||||
char layout[6 * 7 + 1] = {0}; /* 6 keys, 7 bytes per key min */
|
||||
for (unsigned int evcode = KEY_Q; evcode <= KEY_Y; evcode++) {
|
||||
char utf8[7];
|
||||
xkb_keysym_t keysym = xkb_state_key_get_one_sym(xkbstate, evcode + 8);
|
||||
xkb_keysym_to_utf8(keysym, utf8, sizeof(utf8));
|
||||
strcat(layout, utf8);
|
||||
}
|
||||
|
||||
memfile_unref(f);
|
||||
colorprint("XKB keymap: %s\n", layout);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
handle_keymap(struct ei_event *event)
|
||||
|
|
@ -115,21 +119,16 @@ handle_keymap(struct ei_event *event)
|
|||
if (!ei_device_has_capability(device, EI_DEVICE_CAP_KEYBOARD))
|
||||
return;
|
||||
|
||||
const char *type = "none";
|
||||
const char *source = "unknown";
|
||||
struct ei_keymap *keymap = ei_device_keyboard_get_keymap(device);
|
||||
if (keymap) {
|
||||
switch (ei_keymap_get_type(keymap)) {
|
||||
case EI_KEYMAP_TYPE_XKB: type = "xkb"; break;
|
||||
}
|
||||
if (!keymap)
|
||||
return;
|
||||
|
||||
switch(ei_keymap_get_source(keymap)) {
|
||||
case EI_KEYMAP_SOURCE_CLIENT: source = "client"; break;
|
||||
case EI_KEYMAP_SOURCE_SERVER: source = "server"; break;
|
||||
}
|
||||
enum ei_keymap_type type = ei_keymap_get_type(keymap);
|
||||
switch (type) {
|
||||
case EI_KEYMAP_TYPE_XKB:
|
||||
setup_xkb_keymap(keymap);
|
||||
break;
|
||||
}
|
||||
|
||||
colorprint("Using keymap type %s from the %s\n", type, source);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -147,7 +146,6 @@ usage(FILE *fp, const char *argv0)
|
|||
" otherwise XDG_RUNTIME/eis-0\n"
|
||||
" --portal Use the portal backend.\n"
|
||||
" --busname Use the given busname (default: org.freedesktop.portal.Desktop)\n"
|
||||
" --layout Use the given XKB layout (requires libxkbcommon). Default: none\n"
|
||||
" --verbose Enable debugging output\n"
|
||||
"",
|
||||
argv0);
|
||||
|
|
@ -160,8 +158,6 @@ int main(int argc, char **argv)
|
|||
PORTAL,
|
||||
} backend = SOCKET;
|
||||
bool verbose = false;
|
||||
_unused_ const char *layout = NULL;
|
||||
|
||||
_cleanup_free_ char *busname = xstrdup("org.freedesktop.portal.Desktop");
|
||||
|
||||
while (1) {
|
||||
|
|
@ -169,14 +165,12 @@ int main(int argc, char **argv)
|
|||
OPT_BACKEND_SOCKET,
|
||||
OPT_BACKEND_PORTAL,
|
||||
OPT_BUSNAME,
|
||||
OPT_LAYOUT,
|
||||
OPT_VERBOSE,
|
||||
};
|
||||
static struct option long_opts[] = {
|
||||
{"socket", no_argument, 0, OPT_BACKEND_SOCKET},
|
||||
{ "portal", no_argument, 0, OPT_BACKEND_PORTAL},
|
||||
{ "busname", required_argument, 0, OPT_BUSNAME},
|
||||
{ "layout", required_argument, 0, OPT_LAYOUT},
|
||||
{ "verbose", no_argument, 0, OPT_VERBOSE},
|
||||
{ "help", no_argument, 0, 'h'},
|
||||
{NULL},
|
||||
|
|
@ -204,9 +198,6 @@ int main(int argc, char **argv)
|
|||
free(busname);
|
||||
busname = xstrdup(optarg);
|
||||
break;
|
||||
case OPT_LAYOUT:
|
||||
layout = optarg;
|
||||
break;
|
||||
default:
|
||||
usage(stderr, argv[0]);
|
||||
return EXIT_FAILURE;
|
||||
|
|
@ -298,7 +289,6 @@ int main(int argc, char **argv)
|
|||
if (ei_device_has_capability(device, EI_DEVICE_CAP_KEYBOARD)) {
|
||||
colorprint("New keyboard device: %s\n", ei_device_get_name(device));
|
||||
kbd = device;
|
||||
/* FIXME */
|
||||
handle_keymap(e);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ DEFINE_UNREF_CLEANUP_FUNC(xkb_state);
|
|||
#endif
|
||||
|
||||
static void
|
||||
setup_server_keymap(struct eis_demo_server *server, struct eis_device *device)
|
||||
setup_keymap(struct eis_demo_server *server, struct eis_device *device)
|
||||
{
|
||||
#if HAVE_LIBXKBCOMMON
|
||||
colorprint("Using server layout: %s\n", server->layout);
|
||||
|
|
@ -111,9 +111,10 @@ setup_server_keymap(struct eis_demo_server *server, struct eis_device *device)
|
|||
if (!f)
|
||||
return;
|
||||
|
||||
_unref_(eis_keymap) *k = eis_keymap_new(EIS_KEYMAP_TYPE_XKB, memfile_get_fd(f),
|
||||
_unref_(eis_keymap) *k = eis_keymap_new(device,
|
||||
EIS_KEYMAP_TYPE_XKB, memfile_get_fd(f),
|
||||
memfile_get_size(f));
|
||||
eis_device_keyboard_set_keymap(device, k);
|
||||
eis_keymap_add(k);
|
||||
memfile_unref(f);
|
||||
|
||||
_unref_(xkb_state) *state = xkb_state_new(keymap);
|
||||
|
|
@ -126,49 +127,6 @@ setup_server_keymap(struct eis_demo_server *server, struct eis_device *device)
|
|||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
setup_client_keymap(struct eis_demo_server *server, struct eis_device *device)
|
||||
{
|
||||
#if HAVE_LIBXKBCOMMON
|
||||
struct eis_keymap *keymap = eis_device_keyboard_get_keymap(device);
|
||||
if (!keymap)
|
||||
return;
|
||||
|
||||
colorprint("Using client keymap\n");
|
||||
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;
|
||||
|
||||
_unref_(xkb_context) *ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||
if (!ctx)
|
||||
return;
|
||||
|
||||
_unref_(xkb_keymap) *xkb_keymap = xkb_keymap_new_from_string(ctx, str,
|
||||
XKB_KEYMAP_FORMAT_TEXT_V1, 0);
|
||||
if (!keymap)
|
||||
return;
|
||||
|
||||
_unref_(xkb_state) *state = xkb_state_new(xkb_keymap);
|
||||
if (!state)
|
||||
return;
|
||||
|
||||
server->ctx = steal(&ctx);
|
||||
server->keymap = steal(&xkb_keymap);
|
||||
server->state = steal(&state);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
setup_keymap(struct eis_demo_server *server, struct eis_device *device)
|
||||
{
|
||||
if (server->layout)
|
||||
setup_server_keymap(server, device);
|
||||
else
|
||||
setup_client_keymap(server, device);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_key(struct eis_demo_server *server, uint32_t keycode, bool is_press)
|
||||
{
|
||||
|
|
@ -239,9 +197,9 @@ eis_demo_server_printf_handle_event(struct eis_demo_server *server,
|
|||
|
||||
struct eis_device *kbd = eis_device_new(seat);
|
||||
eis_device_configure_name(kbd, "test keyboard");
|
||||
/* FIXME: review keymaps */
|
||||
setup_keymap(server, kbd);
|
||||
eis_device_configure_capability(kbd, EIS_DEVICE_CAP_KEYBOARD);
|
||||
if (server->layout)
|
||||
setup_keymap(server, kbd);
|
||||
colorprint("Creating keyboard device %s for %s\n", eis_device_get_name(kbd),
|
||||
eis_client_get_name(client));
|
||||
eis_device_add(kbd);
|
||||
|
|
@ -338,8 +296,7 @@ usage(FILE *fp, const char *argv0)
|
|||
"Options:\n"
|
||||
" --socketpath Use the given socket path. Default: $XDG_RUNTIME/eis-0\n"
|
||||
" --force Remove the socket if it already exists\n"
|
||||
" --layout Use the given XKB layout (requires libxkbcommon). Default:\n"
|
||||
" use the client-supplied keymap, if any\n"
|
||||
" --layout Use the given XKB layout (requires libxkbcommon). Default: none\n"
|
||||
" --uinput Set up each device as uinput device (this requires root)\n"
|
||||
" --verbose Enable debugging output\n"
|
||||
"",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue