Implement pointer button and keyboard key events

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
Peter Hutterer 2020-08-03 12:00:31 +10:00
parent 81d4556dcc
commit a9f07368a5
11 changed files with 332 additions and 0 deletions

View file

@ -64,6 +64,18 @@ message PointerRelative {
int32 y = 3;
}
message PointerButton {
uint32 deviceid = 1;
uint32 button = 2;
bool state = 3;
}
message KeyboardKey {
uint32 deviceid = 1;
uint32 key = 2;
bool state = 3;
}
message ClientMessage {
oneof msg {
Connect connect = 1;
@ -71,6 +83,8 @@ message ClientMessage {
AddDevice add = 3;
RemoveDevice remove = 4;
PointerRelative rel = 5;
PointerButton button = 6;
KeyboardKey key = 7;
}
}

View file

@ -124,3 +124,29 @@ ei_device_pointer_motion(struct ei_device *device,
ei_pointer_rel(device, x, y);
}
_public_ void
ei_device_pointer_button(struct ei_device *device,
uint32_t button, bool is_press)
{
if (!ei_device_has_capability(device, EI_DEVICE_CAP_POINTER))
return;
if (device->state != EI_DEVICE_STATE_ACCEPTED)
return;
ei_pointer_button(device, button, is_press);
}
_public_ void
ei_device_keyboard_key(struct ei_device *device,
uint32_t key, bool is_press)
{
if (!ei_device_has_capability(device, EI_DEVICE_CAP_KEYBOARD))
return;
if (device->state != EI_DEVICE_STATE_ACCEPTED)
return;
ei_keyboard_key(device, key, is_press);
}

View file

@ -98,5 +98,13 @@ int
ei_pointer_rel(struct ei_device *device,
int32_t x, int32_t y);
int
ei_pointer_button(struct ei_device *device,
uint32_t button, bool is_press);
int
ei_keyboard_key(struct ei_device *device,
uint32_t key, bool is_press);
void
ei_device_accepted(struct ei_device *device);

View file

@ -310,6 +310,46 @@ connection_send_rel(struct ei *ei, struct ei_device *device, int32_t x, int32_t
return connection_send_msg(ei, &msg);
}
static int
connection_send_button(struct ei *ei, struct ei_device *device,
uint32_t b, bool is_press)
{
if (ei->state == EI_STATE_DISCONNECTED)
return 0;
ClientMessage msg = CLIENT_MESSAGE__INIT;
PointerButton button = POINTER_BUTTON__INIT;
button.deviceid = device->id;
button.button = b;
button.state = is_press;
msg.button = &button;
msg.msg_case = CLIENT_MESSAGE__MSG_BUTTON;
return connection_send_msg(ei, &msg);
}
static int
connection_send_key(struct ei *ei, struct ei_device *device,
uint32_t k, bool is_press)
{
if (ei->state == EI_STATE_DISCONNECTED)
return 0;
ClientMessage msg = CLIENT_MESSAGE__INIT;
KeyboardKey key = KEYBOARD_KEY__INIT;
key.deviceid = device->id;
key.key = k;
key.state = is_press;
msg.key = &key;
msg.msg_case = CLIENT_MESSAGE__MSG_KEY;
return connection_send_msg(ei, &msg);
}
static void
ei_disconnect(struct ei *ei)
{
@ -395,6 +435,25 @@ ei_pointer_rel(struct ei_device *device, int32_t x, int32_t y)
return rc;
}
int
ei_pointer_button(struct ei_device *device, uint32_t button, bool is_press)
{
struct ei *ei = ei_device_get_context(device);
int rc = connection_send_button(ei, device, button, is_press);
if (rc)
ei_disconnect(ei);
return rc;
}
int
ei_keyboard_key(struct ei_device *device, uint32_t key, bool is_press)
{
struct ei *ei = ei_device_get_context(device);
int rc = connection_send_key(ei, device, key, is_press);
if (rc)
ei_disconnect(ei);
return rc;
}
_public_ struct ei_event*
ei_get_event(struct ei *ei)

View file

@ -47,6 +47,8 @@ enum message_type {
MESSAGE_ADD_DEVICE,
MESSAGE_REMOVE_DEVICE,
MESSAGE_POINTER_REL,
MESSAGE_POINTER_BUTTON,
MESSAGE_KEYBOARD_KEY,
};
struct message {
@ -70,6 +72,16 @@ struct message {
int32_t x;
int32_t y;
} pointer_rel;
struct message_pointer_button {
uint32_t deviceid;
uint32_t button;
bool state;
} pointer_button;
struct message_keyboard_key {
uint32_t deviceid;
uint32_t key;
bool state;
} keyboard_key;;
};
};
@ -277,6 +289,34 @@ client_pointer_rel(struct eis_client *client, uint32_t deviceid,
return -EINVAL;
}
static int
client_pointer_button(struct eis_client *client, uint32_t deviceid,
uint32_t button, bool state)
{
struct eis_device *device;
list_for_each(device, &client->devices, link) {
if (device->id == deviceid) {
return eis_device_pointer_button(device, button, state);
}
}
return -EINVAL;
}
static int
client_keyboard_key(struct eis_client *client, uint32_t deviceid,
uint32_t key, bool state)
{
struct eis_device *device;
list_for_each(device, &client->devices, link) {
if (device->id == deviceid) {
return eis_device_keyboard_key(device, key, state);
}
}
return -EINVAL;
}
static int
client_hello_handle_msg(struct eis_client *client, struct message *msg)
{
@ -294,6 +334,8 @@ client_hello_handle_msg(struct eis_client *client, struct message *msg)
case MESSAGE_ADD_DEVICE:
case MESSAGE_REMOVE_DEVICE:
case MESSAGE_POINTER_REL:
case MESSAGE_POINTER_BUTTON:
case MESSAGE_KEYBOARD_KEY:
rc = -EPROTO;
break;
}
@ -316,6 +358,8 @@ client_connecting_handle_msg(struct eis_client *client, const struct message *ms
case MESSAGE_ADD_DEVICE:
case MESSAGE_REMOVE_DEVICE:
case MESSAGE_POINTER_REL:
case MESSAGE_POINTER_BUTTON:
case MESSAGE_KEYBOARD_KEY:
rc = -EPROTO;
break;
}
@ -348,6 +392,16 @@ client_connected_handle_msg(struct eis_client *client,
rc = client_pointer_rel(client, msg->pointer_rel.deviceid,
msg->pointer_rel.x, msg->pointer_rel.y);
break;
case MESSAGE_POINTER_BUTTON:
rc = client_pointer_button(client, msg->pointer_button.deviceid,
msg->pointer_button.button,
msg->pointer_button.state);
break;
case MESSAGE_KEYBOARD_KEY:
rc = client_keyboard_key(client, msg->keyboard_key.deviceid,
msg->keyboard_key.key,
msg->keyboard_key.state);
break;
}
return rc;
}
@ -428,6 +482,28 @@ client_parse_message(const char *data, size_t *len)
};
}
break;
case CLIENT_MESSAGE__MSG_BUTTON:
{
PointerButton *b = proto->button;
*msg = (struct message) {
.type = MESSAGE_POINTER_BUTTON,
.pointer_button.deviceid = b->deviceid,
.pointer_button.button = b->button,
.pointer_button.state = b->state,
};
}
break;
case CLIENT_MESSAGE__MSG_KEY:
{
KeyboardKey *k = proto->key;
*msg = (struct message) {
.type = MESSAGE_KEYBOARD_KEY,
.keyboard_key.deviceid = k->deviceid,
.keyboard_key.key = k->key,
.keyboard_key.state = k->state,
};
}
break;
default:
success = false;
break;

View file

@ -91,6 +91,36 @@ eis_device_pointer_rel(struct eis_device *device,
return 0;
}
int
eis_device_pointer_button(struct eis_device *device,
uint32_t button, bool is_press)
{
if (!eis_device_has_capability(device, EIS_DEVICE_CAP_POINTER))
return -EINVAL;
if (device->state != EIS_DEVICE_STATE_ACCEPTED)
return -EINVAL;
eis_queue_pointer_button_event(device, button, is_press);
return 0;
}
int
eis_device_keyboard_key(struct eis_device *device,
uint32_t key, bool is_press)
{
if (!eis_device_has_capability(device, EIS_DEVICE_CAP_KEYBOARD))
return -EINVAL;
if (device->state != EIS_DEVICE_STATE_ACCEPTED)
return -EINVAL;
eis_queue_keyboard_key_event(device, key, is_press);
return 0;
}
_public_ void
eis_device_connect(struct eis_device *device)
{

View file

@ -91,6 +91,14 @@ struct eis_event_client {
struct eis_event_pointer {
struct eis_event base;
int x, y; /* relative motion */
uint32_t button;
bool button_is_press;
};
struct eis_event_keyboard {
struct eis_event base;
uint32_t key;
bool key_is_press;
};
void
@ -120,6 +128,13 @@ eis_device_new(struct eis_client *client,
int
eis_device_pointer_rel(struct eis_device *device,
int x, int y);
int
eis_device_pointer_button(struct eis_device *device,
uint32_t button, bool state);
int
eis_device_keyboard_key(struct eis_device *device,
uint32_t key, bool state);
void
eis_queue_connect_event(struct eis_client *client);
@ -135,3 +150,11 @@ eis_queue_removed_event(struct eis_device *device);
void
eis_queue_pointer_rel_event(struct eis_device *device, int x, int y);
void
eis_queue_pointer_button_event(struct eis_device *device, uint32_t button,
bool is_press);
void
eis_queue_keyboard_key_event(struct eis_device *device, uint32_t key,
bool is_press);

View file

@ -74,6 +74,14 @@ _public_
OBJECT_IMPLEMENT_GETTER(eis_event_pointer, x, int);
_public_
OBJECT_IMPLEMENT_GETTER(eis_event_pointer, y, int);
_public_
OBJECT_IMPLEMENT_GETTER(eis_event_pointer, button, uint32_t);
_public_
OBJECT_IMPLEMENT_GETTER(eis_event_pointer, button_is_press, bool);
_public_
OBJECT_IMPLEMENT_GETTER(eis_event_keyboard, key, uint32_t);
_public_
OBJECT_IMPLEMENT_GETTER(eis_event_keyboard, key_is_press, bool);
_public_ struct eis_event_pointer *
eis_event_get_pointer_event(struct eis_event *e)
@ -102,6 +110,34 @@ eis_event_get_pointer_event(struct eis_event *e)
return NULL;
}
_public_ struct eis_event_keyboard *
eis_event_get_keyboard_event(struct eis_event *e)
{
switch (e->type) {
case EIS_EVENT_NONE:
case EIS_EVENT_CLIENT_CONNECT:
case EIS_EVENT_CLIENT_DISCONNECT:
case EIS_EVENT_DEVICE_ADDED:
case EIS_EVENT_DEVICE_REMOVED:
case EIS_EVENT_REQUEST_CAPABILITY:
case EIS_EVENT_CANCEL_CAPABILITY:
case EIS_EVENT_POINTER_MOTION:
case EIS_EVENT_POINTER_MOTION_ABSOLUTE:
case EIS_EVENT_POINTER_BUTTON:
case EIS_EVENT_POINTER_SCROLL:
case EIS_EVENT_POINTER_SCROLL_DISCRETE:
break;
case EIS_EVENT_KEYBOARD_KEY:
return container_of(e, struct eis_event_keyboard, base);
case EIS_EVENT_TOUCH_DOWN:
case EIS_EVENT_TOUCH_UP:
case EIS_EVENT_TOUCH_MOTION:
break;
}
return NULL;
}
static void
eis_destroy(struct eis *eis)
{
@ -227,6 +263,42 @@ eis_queue_pointer_rel_event(struct eis_device *device, int x, int y)
eis_queue_event(eis, &e->base);
}
void
eis_queue_pointer_button_event(struct eis_device *device, uint32_t button,
bool is_press)
{
struct eis_client *client = eis_device_get_client(device);
struct eis *eis = eis_client_get_context(client);
struct eis_event_pointer *e = xalloc(sizeof(*e));
eis_event_init_object(&e->base, &eis->object);
e->base.type = EIS_EVENT_POINTER_BUTTON;
e->base.client = eis_client_ref(client);
e->base.device = eis_device_ref(device);
e->button = button;
e->button_is_press = is_press;
eis_queue_event(eis, &e->base);
}
void
eis_queue_keyboard_key_event(struct eis_device *device, uint32_t key,
bool is_press)
{
struct eis_client *client = eis_device_get_client(device);
struct eis *eis = eis_client_get_context(client);
struct eis_event_keyboard *e = xalloc(sizeof(*e));
eis_event_init_object(&e->base, &eis->object);
e->base.type = EIS_EVENT_KEYBOARD_KEY;
e->base.client = eis_client_ref(client);
e->base.device = eis_device_ref(device);
e->key = key;
e->key_is_press = is_press;
eis_queue_event(eis, &e->base);
}
_public_ struct eis_event*
eis_get_event(struct eis *eis)
{

View file

@ -386,6 +386,9 @@ eis_event_get_device(struct eis_event *event);
struct eis_event_pointer *
eis_event_get_pointer_event(struct eis_event *event);
struct eis_event_keyboard *
eis_event_get_keyboard_event(struct eis_event *event);
/**
* For an event of type @ref EIS_EVENT_POINTER_MOTION return the x movement
* in 1/1000th of a logical pixel.

View file

@ -101,7 +101,12 @@ int main(int argc, char **argv)
}
if (have_device) {
printf("client: sending motion event\n");
ei_device_pointer_motion(ptr, -1, 1);
/* BTN_LEFT */
printf("client: sending button event\n");
ei_device_pointer_button(ptr, 0x110, true);
ei_device_pointer_button(ptr, 0x110, false);
}
}

View file

@ -122,6 +122,22 @@ int main(int argc, char **argv)
eis_event_pointer_get_y(p));
}
break;
case EIS_EVENT_POINTER_BUTTON:
{
struct eis_event_pointer *p = eis_event_get_pointer_event(e);
printf("server: button %d (%s)\n",
eis_event_pointer_get_button(p),
eis_event_pointer_get_button_is_press(p) ? "press" : "release");
}
break;
case EIS_EVENT_KEYBOARD_KEY:
{
struct eis_event_keyboard *k = eis_event_get_keyboard_event(e);
printf("server: key %d (%s)\n",
eis_event_keyboard_get_key(k),
eis_event_keyboard_get_key_is_press(k) ? "press" : "release");
}
break;
default:
abort();
}