diff --git a/proto/ei.proto b/proto/ei.proto index 91d6c1b..69f6577 100644 --- a/proto/ei.proto +++ b/proto/ei.proto @@ -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; } } diff --git a/src/libei-device.c b/src/libei-device.c index 8b3c832..8aad544 100644 --- a/src/libei-device.c +++ b/src/libei-device.c @@ -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); +} diff --git a/src/libei-private.h b/src/libei-private.h index 4fd0697..f0cb0f1 100644 --- a/src/libei-private.h +++ b/src/libei-private.h @@ -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); diff --git a/src/libei.c b/src/libei.c index a0fc857..ca666d1 100644 --- a/src/libei.c +++ b/src/libei.c @@ -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) diff --git a/src/libeis-client.c b/src/libeis-client.c index cc58f7f..4c33cf6 100644 --- a/src/libeis-client.c +++ b/src/libeis-client.c @@ -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; diff --git a/src/libeis-device.c b/src/libeis-device.c index 057ad67..d94c911 100644 --- a/src/libeis-device.c +++ b/src/libeis-device.c @@ -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) { diff --git a/src/libeis-private.h b/src/libeis-private.h index 28f2eee..7f68547 100644 --- a/src/libeis-private.h +++ b/src/libeis-private.h @@ -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); diff --git a/src/libeis.c b/src/libeis.c index f54db44..e968177 100644 --- a/src/libeis.c +++ b/src/libeis.c @@ -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) { diff --git a/src/libeis.h b/src/libeis.h index a66a124..8b3137a 100644 --- a/src/libeis.h +++ b/src/libeis.h @@ -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. diff --git a/tools/ei-socket-client.c b/tools/ei-socket-client.c index c34a463..eb98e09 100644 --- a/tools/ei-socket-client.c +++ b/tools/ei-socket-client.c @@ -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); } } diff --git a/tools/eis-socket-server.c b/tools/eis-socket-server.c index 29a775a..9c2785b 100644 --- a/tools/eis-socket-server.c +++ b/tools/eis-socket-server.c @@ -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(); }