mirror of
https://gitlab.freedesktop.org/libinput/libei.git
synced 2026-05-08 10:28:03 +02:00
Implement key modifier mask events similar to Wayland
Since the server controls the keymap, and that keymap is likely merged with some other device let's add the events so we notify the client of things like numlock-is-down etc. Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
parent
730a82d28d
commit
6f70e97cce
15 changed files with 266 additions and 0 deletions
|
|
@ -217,6 +217,14 @@ message DevicePaused {
|
|||
uint32 deviceid = 1;
|
||||
}
|
||||
|
||||
message KeyboardModifiers {
|
||||
uint32 deviceid = 1;
|
||||
uint32 depressed = 2;
|
||||
uint32 locked = 3;
|
||||
uint32 latched = 4;
|
||||
uint32 group = 5;
|
||||
}
|
||||
|
||||
message ServerMessage {
|
||||
oneof msg {
|
||||
Connected connected = 2;
|
||||
|
|
@ -230,6 +238,7 @@ message ServerMessage {
|
|||
DeviceRemoved device_removed = 10;
|
||||
DeviceResumed device_resumed = 11;
|
||||
DevicePaused device_paused = 12;
|
||||
KeyboardModifiers keyboard_modifiers = 13;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ ei_event_type_to_string(enum ei_event_type type)
|
|||
CASE_RETURN_STRING(EI_EVENT_DEVICE_REMOVED);
|
||||
CASE_RETURN_STRING(EI_EVENT_DEVICE_PAUSED);
|
||||
CASE_RETURN_STRING(EI_EVENT_DEVICE_RESUMED);
|
||||
CASE_RETURN_STRING(EI_EVENT_KEYBOARD_MODIFIERS);
|
||||
}
|
||||
|
||||
assert(!"Unhandled event type");
|
||||
|
|
@ -64,6 +65,7 @@ ei_event_destroy(struct ei_event *event)
|
|||
case EI_EVENT_DEVICE_REMOVED:
|
||||
case EI_EVENT_DEVICE_PAUSED:
|
||||
case EI_EVENT_DEVICE_RESUMED:
|
||||
case EI_EVENT_KEYBOARD_MODIFIERS:
|
||||
break;
|
||||
}
|
||||
ei_device_unref(event->device);
|
||||
|
|
@ -121,3 +123,35 @@ check_event_type(struct ei_event *event,
|
|||
if (!check_event_type(event_, __func__, __VA_ARGS__, -1)) \
|
||||
return retval_; \
|
||||
|
||||
|
||||
_public_ uint32_t
|
||||
ei_event_keyboard_get_xkb_mods_depressed(struct ei_event *event)
|
||||
{
|
||||
require_event_type(event, 0, EI_EVENT_KEYBOARD_MODIFIERS);
|
||||
|
||||
return event->modifiers.depressed;
|
||||
}
|
||||
|
||||
_public_ uint32_t
|
||||
ei_event_keyboard_get_xkb_mods_latched(struct ei_event *event)
|
||||
{
|
||||
require_event_type(event, 0, EI_EVENT_KEYBOARD_MODIFIERS);
|
||||
|
||||
return event->modifiers.latched;
|
||||
}
|
||||
|
||||
_public_ uint32_t
|
||||
ei_event_keyboard_get_xkb_mods_locked(struct ei_event *event)
|
||||
{
|
||||
require_event_type(event, 0, EI_EVENT_KEYBOARD_MODIFIERS);
|
||||
|
||||
return event->modifiers.locked;
|
||||
}
|
||||
|
||||
_public_ uint32_t
|
||||
ei_event_keyboard_get_xkb_group(struct ei_event *event)
|
||||
{
|
||||
require_event_type(event, 0, EI_EVENT_KEYBOARD_MODIFIERS);
|
||||
|
||||
return event->modifiers.group;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -153,12 +153,21 @@ struct ei_touch {
|
|||
double x, y;
|
||||
};
|
||||
|
||||
struct ei_xkb_modifiers {
|
||||
uint32_t depressed;
|
||||
uint32_t latched;
|
||||
uint32_t locked;
|
||||
uint32_t group;
|
||||
};
|
||||
|
||||
struct ei_event {
|
||||
struct object object; /* Parent is struct ei */
|
||||
enum ei_event_type type;
|
||||
struct list link;
|
||||
struct ei_seat *seat; /* NULL if device is non-NULL */
|
||||
struct ei_device *device;
|
||||
|
||||
struct ei_xkb_modifiers modifiers;
|
||||
};
|
||||
|
||||
struct ei_event *
|
||||
|
|
|
|||
|
|
@ -105,6 +105,14 @@ ei_proto_handle_message(struct ei *ei,
|
|||
proto->device_region->height,
|
||||
proto->device_region->scale);
|
||||
break;
|
||||
case SERVER_MESSAGE__MSG_KEYBOARD_MODIFIERS:
|
||||
rc = call(keyboard_modifiers, ei,
|
||||
proto->keyboard_modifiers->deviceid,
|
||||
proto->keyboard_modifiers->depressed,
|
||||
proto->keyboard_modifiers->latched,
|
||||
proto->keyboard_modifiers->locked,
|
||||
proto->keyboard_modifiers->group);
|
||||
break;
|
||||
case SERVER_MESSAGE__MSG_DEVICE_REMOVED:
|
||||
rc = call(device_removed, ei,
|
||||
proto->device_removed->deviceid);
|
||||
|
|
|
|||
|
|
@ -51,6 +51,9 @@ struct ei_proto_interface {
|
|||
enum ei_keymap_type keymap_type,
|
||||
int keymap_fd,
|
||||
size_t keymap_size);
|
||||
int (*keyboard_modifiers)(struct ei *ei, uint32_t deviceid,
|
||||
uint32_t depressed, uint32_t latched,
|
||||
uint32_t locked, uint32_t group);
|
||||
};
|
||||
|
||||
struct ei_proto_requests {
|
||||
|
|
|
|||
42
src/libei.c
42
src/libei.c
|
|
@ -262,6 +262,21 @@ queue_resumed_event(struct ei_device *device)
|
|||
queue_event(ei, e);
|
||||
}
|
||||
|
||||
static void
|
||||
queue_keyboard_modifiers_event(struct ei_device *device,
|
||||
const struct ei_xkb_modifiers *mods)
|
||||
{
|
||||
struct ei *ei= ei_device_get_context(device);
|
||||
|
||||
struct ei_event *e = ei_event_new(ei);
|
||||
e->type = EI_EVENT_KEYBOARD_MODIFIERS;
|
||||
e->seat = ei_seat_ref(ei_device_get_seat(device));
|
||||
e->device = ei_device_ref(device);
|
||||
e->modifiers = *mods;
|
||||
|
||||
queue_event(ei, e);
|
||||
}
|
||||
|
||||
void
|
||||
ei_disconnect(struct ei *ei)
|
||||
{
|
||||
|
|
@ -423,6 +438,32 @@ handle_msg_device_region(struct ei *ei, uint32_t deviceid,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
handle_msg_keyboard_modifiers(struct ei *ei, uint32_t deviceid,
|
||||
uint32_t depressed, uint32_t latched,
|
||||
uint32_t locked, uint32_t group)
|
||||
{
|
||||
log_debug(ei, "Setting modifiers for %#x\n", deviceid);
|
||||
|
||||
struct ei_device *device = ei_find_device(ei, deviceid);
|
||||
if (!device)
|
||||
return 0;
|
||||
|
||||
if (!ei_device_has_capability(device, EI_DEVICE_CAP_KEYBOARD)) {
|
||||
log_bug(ei,"Modifier event for non-keyboard\n");
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
struct ei_xkb_modifiers mods = {
|
||||
.depressed = depressed,
|
||||
.latched = latched,
|
||||
.locked = locked,
|
||||
.group = group,
|
||||
};
|
||||
queue_keyboard_modifiers_event(device, &mods);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
handle_msg_device_removed(struct ei *ei, uint32_t deviceid)
|
||||
|
|
@ -687,6 +728,7 @@ static const struct ei_proto_interface intf_state_connected = {
|
|||
.device_region = handle_msg_device_region,
|
||||
.device_keymap = handle_msg_device_keymap,
|
||||
.device_done = handle_msg_device_added_done,
|
||||
.keyboard_modifiers = handle_msg_keyboard_modifiers,
|
||||
};
|
||||
|
||||
static const struct ei_proto_interface *interfaces[] = {
|
||||
|
|
|
|||
48
src/libei.h
48
src/libei.h
|
|
@ -236,6 +236,22 @@ enum ei_event_type {
|
|||
* The client may send events.
|
||||
*/
|
||||
EI_EVENT_DEVICE_RESUMED,
|
||||
|
||||
/**
|
||||
* The server has changed the modifier state on the device's
|
||||
* keymap. See
|
||||
* ei_event_keyboard_get_xkb_mods_depressed(),
|
||||
* ei_event_keyboard_get_xkb_mods_latched(),
|
||||
* ei_event_keyboard_get_xkb_mods_locked(), and
|
||||
* ei_event_keyboard_get_xkb_group().
|
||||
*
|
||||
* This event is sent in response to an external modifier state
|
||||
* change. Where the client triggers a modifier state change in
|
||||
* response to ei_device_keyboard_key(), no such event is sent.
|
||||
*
|
||||
* This event may arrive while a device is paused.
|
||||
*/
|
||||
EI_EVENT_KEYBOARD_MODIFIERS,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -545,6 +561,38 @@ ei_event_get_device(struct ei_event *event);
|
|||
uint64_t
|
||||
ei_event_get_time(struct ei_event *event);
|
||||
|
||||
/**
|
||||
* For an event of type @ref EI_EVENT_KEYBOARD_MODIFIERS, get the
|
||||
* mask of currently logically pressed-down modifiers.
|
||||
* See ei_device_get_keymap() for the corresponding keymap.
|
||||
*/
|
||||
uint32_t
|
||||
ei_event_keyboard_get_xkb_mods_depressed(struct ei_event *event);
|
||||
|
||||
/**
|
||||
* For an event of type @ref EI_EVENT_KEYBOARD_MODIFIERS, get the
|
||||
* mask of currently logically latched modifiers.
|
||||
* See ei_device_get_keymap() for the corresponding keymap.
|
||||
*/
|
||||
uint32_t
|
||||
ei_event_keyboard_get_xkb_mods_latched(struct ei_event *event);
|
||||
|
||||
/**
|
||||
* For an event of type @ref EI_EVENT_KEYBOARD_MODIFIERS, get the
|
||||
* mask of currently logically locked modifiers.
|
||||
* See ei_device_get_keymap() for the corresponding keymap.
|
||||
*/
|
||||
uint32_t
|
||||
ei_event_keyboard_get_xkb_mods_locked(struct ei_event *event);
|
||||
|
||||
/**
|
||||
* For an event of type @ref EI_EVENT_KEYBOARD_MODIFIERS, get the
|
||||
* logical group state.
|
||||
* See ei_device_get_keymap() for the corresponding keymap.
|
||||
*/
|
||||
uint32_t
|
||||
ei_event_keyboard_get_xkb_group(struct ei_event *event);
|
||||
|
||||
/**
|
||||
* Increase the refcount of this struct by one. Use ei_device_unref() to
|
||||
* decrease the refcount.
|
||||
|
|
|
|||
|
|
@ -143,6 +143,14 @@ client_send_device_resumed(struct eis_client *client, struct eis_device *device)
|
|||
return eis->requests->device_resumed(device);
|
||||
}
|
||||
|
||||
static int
|
||||
client_send_keyboard_modifiers(struct eis_client *client, struct eis_device *device,
|
||||
const struct eis_xkb_modifiers *mods)
|
||||
{
|
||||
struct eis *eis = eis_client_get_context(client);
|
||||
return eis->requests->keyboard_modifiers(device, mods);
|
||||
}
|
||||
|
||||
_public_ void
|
||||
eis_client_connect(struct eis_client *client)
|
||||
{
|
||||
|
|
@ -643,3 +651,18 @@ eis_client_resume_device(struct eis_client *client, struct eis_device *device)
|
|||
{
|
||||
client_send_device_resumed(client, device);
|
||||
}
|
||||
|
||||
void
|
||||
eis_client_keyboard_modifiers(struct eis_client *client, struct eis_device *device,
|
||||
uint32_t depressed, uint32_t latched, uint32_t locked,
|
||||
uint32_t group)
|
||||
{
|
||||
struct eis_xkb_modifiers mods = {
|
||||
.depressed = depressed,
|
||||
.locked = locked,
|
||||
.latched = latched,
|
||||
.group = group,
|
||||
};
|
||||
client_send_keyboard_modifiers(client, device, &mods);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -474,3 +474,17 @@ eis_device_resume(struct eis_device *device)
|
|||
device->state = EIS_DEVICE_STATE_RESUMED;
|
||||
eis_client_resume_device(eis_device_get_client(device), device);
|
||||
}
|
||||
|
||||
_public_ void
|
||||
eis_device_keyboard_send_xkb_modifiers(struct eis_device *device, uint32_t depressed,
|
||||
uint32_t latched, uint32_t locked, uint32_t group)
|
||||
{
|
||||
if (!eis_device_has_capability(device, EIS_DEVICE_CAP_KEYBOARD)) {
|
||||
log_bug_client(eis_device_get_context(device),
|
||||
"%s: device is not a keyboard\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
eis_client_keyboard_modifiers(eis_device_get_client(device),
|
||||
device, depressed, latched, locked, group);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -181,6 +181,13 @@ struct eis_keymap {
|
|||
bool assigned;
|
||||
};
|
||||
|
||||
struct eis_xkb_modifiers {
|
||||
uint32_t depressed;
|
||||
uint32_t locked;
|
||||
uint32_t latched;
|
||||
uint32_t group;
|
||||
};
|
||||
|
||||
void
|
||||
eis_init_object(struct eis *eis, struct object *parent);
|
||||
|
||||
|
|
@ -213,6 +220,11 @@ void
|
|||
eis_client_pause_device(struct eis_client *client,
|
||||
struct eis_device *device);
|
||||
|
||||
void
|
||||
eis_client_keyboard_modifiers(struct eis_client *client, struct eis_device *device,
|
||||
uint32_t depressed, uint32_t latched, uint32_t locked,
|
||||
uint32_t group);
|
||||
|
||||
void
|
||||
eis_seat_bind(struct eis_seat *seat, uint32_t cap);
|
||||
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ log_wire_message(struct eis *eis, const ServerMessage *msg)
|
|||
MSG_STRING_CASE(DEVICE_REMOVED);
|
||||
MSG_STRING_CASE(DEVICE_RESUMED);
|
||||
MSG_STRING_CASE(DEVICE_PAUSED);
|
||||
MSG_STRING_CASE(KEYBOARD_MODIFIERS);
|
||||
break;
|
||||
default:
|
||||
assert(!"Unimplemented message type");
|
||||
|
|
@ -202,6 +203,21 @@ eis_proto_send_device_region(struct eis_device *device, const struct eis_region
|
|||
return eis_proto_send_msg(eis_device_get_client(device), &msg);
|
||||
}
|
||||
|
||||
static int
|
||||
eis_proto_send_keyboard_modifiers(struct eis_device *device, const struct eis_xkb_modifiers *mods)
|
||||
{
|
||||
prepare_msg(KEYBOARD_MODIFIERS, KeyboardModifiers, keyboard_modifiers);
|
||||
|
||||
keyboard_modifiers.deviceid = device->id;
|
||||
keyboard_modifiers.depressed = mods->depressed;
|
||||
keyboard_modifiers.locked = mods->locked;
|
||||
keyboard_modifiers.latched = mods->latched;
|
||||
keyboard_modifiers.group = mods->group;
|
||||
|
||||
return eis_proto_send_msg(eis_device_get_client(device), &msg);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
eis_proto_send_device_removed(struct eis_device *device)
|
||||
{
|
||||
|
|
@ -244,6 +260,7 @@ static const struct eis_proto_requests requests = {
|
|||
.device_keymap = eis_proto_send_device_keymap,
|
||||
.device_done = eis_proto_send_device_done,
|
||||
.device_region = eis_proto_send_device_region,
|
||||
.keyboard_modifiers = eis_proto_send_keyboard_modifiers,
|
||||
};
|
||||
|
||||
const struct eis_proto_requests *
|
||||
|
|
|
|||
|
|
@ -70,6 +70,8 @@ struct eis_proto_requests {
|
|||
int (*device_done)(struct eis_device *device);
|
||||
int (*device_region)(struct eis_device *device,
|
||||
const struct eis_region *region);
|
||||
int (*keyboard_modifiers)(struct eis_device *device,
|
||||
const struct eis_xkb_modifiers *mods);
|
||||
};
|
||||
|
||||
int
|
||||
|
|
|
|||
|
|
@ -633,6 +633,15 @@ eis_keymap_get_device(struct eis_keymap *keymap);
|
|||
struct eis_keymap *
|
||||
eis_device_keyboard_get_keymap(struct eis_device *device);
|
||||
|
||||
/**
|
||||
* Notify the client of the current XKB modifier state.
|
||||
*/
|
||||
void
|
||||
eis_device_keyboard_send_xkb_modifiers(struct eis_device *device,
|
||||
uint32_t depressed,
|
||||
uint32_t latched,
|
||||
uint32_t locked,
|
||||
uint32_t group);
|
||||
|
||||
/**
|
||||
* For an event of type @ref EIS_EVENT_SEAT_BIND, return the capabilities
|
||||
|
|
|
|||
|
|
@ -943,6 +943,7 @@ peck_ei_event_type_name(enum ei_event_type type)
|
|||
CASE_STRING(DEVICE_REMOVED);
|
||||
CASE_STRING(DEVICE_PAUSED);
|
||||
CASE_STRING(DEVICE_RESUMED);
|
||||
CASE_STRING(KEYBOARD_MODIFIERS);
|
||||
}
|
||||
#undef CASE_STRING
|
||||
assert(!"Unhandled ei event type");
|
||||
|
|
|
|||
|
|
@ -768,3 +768,38 @@ MUNIT_TEST(test_ei_keymap_set)
|
|||
|
||||
return MUNIT_OK;
|
||||
}
|
||||
|
||||
MUNIT_TEST(test_ei_keyboard_modifiers)
|
||||
{
|
||||
_unref_(peck) *peck = peck_new();
|
||||
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL);
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_KEYBOARD);
|
||||
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTODEVICES);
|
||||
peck_dispatch_until_stable(peck);
|
||||
|
||||
with_server(peck) {
|
||||
struct eis_device *kbd = peck_eis_get_default_keyboard(peck);
|
||||
eis_device_keyboard_send_xkb_modifiers(kbd, 0x1, 0x2, 0x4, 0x8);
|
||||
}
|
||||
|
||||
peck_dispatch_until_stable(peck);
|
||||
|
||||
with_client(peck) {
|
||||
_unref_(ei_event) *event =
|
||||
peck_ei_next_event(ei, EI_EVENT_KEYBOARD_MODIFIERS);
|
||||
|
||||
uint32_t depressed, locked, latched, group;
|
||||
depressed = ei_event_keyboard_get_xkb_mods_depressed(event);
|
||||
latched = ei_event_keyboard_get_xkb_mods_latched(event);
|
||||
locked = ei_event_keyboard_get_xkb_mods_locked(event);
|
||||
group = ei_event_keyboard_get_xkb_group(event);
|
||||
|
||||
munit_assert_uint(depressed, ==, 0x1);
|
||||
munit_assert_uint(latched, ==, 0x2);
|
||||
munit_assert_uint(locked, ==, 0x4);
|
||||
munit_assert_uint(group, ==, 0x8);
|
||||
}
|
||||
|
||||
return MUNIT_OK;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue