proto: add a start/stop emulating message pair

This effectively provides the EIS implementation with a notification
that the client will actually send events in the near future. To be used
by e.g. synergy-like clients when the pointer enters the logical screen
so that the EIS implementation can flash a warning or something.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
Peter Hutterer 2021-08-24 09:53:10 +10:00
parent 9e83e2fb3e
commit a03f547989
22 changed files with 327 additions and 25 deletions

View file

@ -18,13 +18,16 @@ syntax = "proto3";
* 3. - server sends "AddSeat" (once or multiple times)
* 4. - client sends "BindSeat" for each seat
* 5. - server sends "DeviceAdded" for any device on this seat
* 5. - server sends "DeviceResumed"
* 6. - client sends "PointerRelative" or any other event
* 7. - client sends "CloseDevice"
* 8. - client sends "Disconnect" and closes its end of the socket
* 6. - server sends "DeviceResumed"
* 7. - client sends "StartEmulating" to notify the server emulation starts
* 8. - client sends "PointerRelative" or any other event
* 9. - client sends "StopEmulating" to notify the server emulation starts
* 10. - client sends "CloseDevice"
* 11. - client sends "Disconnect" and closes its end of the socket
*
* The server may send Disconnect at any time.
* The server may send SeatRemoved for a device at any time.
* The server may send DeviceSuspended for any currently resumed device at any time.
* The server may send DeviceRemoved for a device at any time.
*
* Where a connection error occurs, the library (libei or libeis) will
@ -148,6 +151,14 @@ message TouchUp {
uint32 touchid = 2;
}
message StartEmulating {
uint32 deviceid = 1;
}
message StopEmulating {
uint32 deviceid = 1;
}
message Frame {
uint32 deviceid = 1;
}
@ -172,6 +183,8 @@ message ClientMessage {
ConfigureName configure_name = 16;
ConfigureCapabilities configure_caps = 17;
Frame frame = 18;
StartEmulating start_emulating = 19;
StopEmulating stop_emulating = 20;
}
}

View file

@ -40,6 +40,7 @@ ei_device_state_to_string(enum ei_device_state state)
CASE_RETURN_STRING(EI_DEVICE_STATE_NEW);
CASE_RETURN_STRING(EI_DEVICE_STATE_PAUSED);
CASE_RETURN_STRING(EI_DEVICE_STATE_RESUMED);
CASE_RETURN_STRING(EI_DEVICE_STATE_EMULATING);
CASE_RETURN_STRING(EI_DEVICE_STATE_REMOVED_FROM_CLIENT);
CASE_RETURN_STRING(EI_DEVICE_STATE_REMOVED_FROM_SERVER);
CASE_RETURN_STRING(EI_DEVICE_STATE_DEAD);
@ -234,6 +235,9 @@ ei_device_close(struct ei_device *device)
case EI_DEVICE_STATE_REMOVED_FROM_CLIENT:
case EI_DEVICE_STATE_REMOVED_FROM_SERVER:
break;
case EI_DEVICE_STATE_EMULATING:
ei_send_stop_emulating(device);
_fallthrough_;
case EI_DEVICE_STATE_PAUSED:
case EI_DEVICE_STATE_RESUMED:
ei_device_set_state(device, EI_DEVICE_STATE_REMOVED_FROM_CLIENT);
@ -255,6 +259,7 @@ ei_device_removed_by_server(struct ei_device *device)
case EI_DEVICE_STATE_REMOVED_FROM_CLIENT:
case EI_DEVICE_STATE_PAUSED:
case EI_DEVICE_STATE_RESUMED:
case EI_DEVICE_STATE_EMULATING:
ei_queue_device_removed_event(device);
ei_device_set_state(device, EI_DEVICE_STATE_DEAD);
/* Device is dead now. Move it from the devices list to
@ -316,6 +321,26 @@ ei_device_has_capability(struct ei_device *device,
return false;
}
_public_ void
ei_device_start_emulating(struct ei_device *device)
{
if (device->state != EI_DEVICE_STATE_RESUMED)
return;
device->state = EI_DEVICE_STATE_EMULATING;
ei_send_start_emulating(device);
}
_public_ void
ei_device_stop_emulating(struct ei_device *device)
{
if (device->state != EI_DEVICE_STATE_EMULATING)
return;
device->state = EI_DEVICE_STATE_RESUMED;
ei_send_stop_emulating(device);
}
_public_ struct ei_region *
ei_device_get_region(struct ei_device *device, size_t index)
{
@ -332,7 +357,7 @@ ei_device_pointer_motion(struct ei_device *device,
return;
}
if (device->state != EI_DEVICE_STATE_RESUMED)
if (device->state != EI_DEVICE_STATE_EMULATING)
return;
ei_send_pointer_rel(device, x, y);
@ -348,7 +373,7 @@ ei_device_pointer_motion_absolute(struct ei_device *device,
return;
}
if (device->state != EI_DEVICE_STATE_RESUMED)
if (device->state != EI_DEVICE_STATE_EMULATING)
return;
struct ei_region *r;
@ -371,7 +396,7 @@ ei_device_pointer_button(struct ei_device *device,
return;
}
if (device->state != EI_DEVICE_STATE_RESUMED)
if (device->state != EI_DEVICE_STATE_EMULATING)
return;
/* Ignore anything < BTN_MOUSE. Avoids the common error of sending
@ -407,7 +432,8 @@ ei_device_pointer_scroll(struct ei_device *device,
log_bug_client(ei_device_get_context(device),
"%s: device is not a (absolute) pointer\n", __func__);
}
if (device->state != EI_DEVICE_STATE_RESUMED)
if (device->state != EI_DEVICE_STATE_EMULATING)
return;
ei_device_resume_scrolling(device, x, y);
@ -423,7 +449,7 @@ ei_device_pointer_scroll_stop(struct ei_device *device, bool x, bool y)
log_bug_client(ei_device_get_context(device),
"%s: device is not a (absolute) pointer\n", __func__);
}
if (device->state != EI_DEVICE_STATE_RESUMED)
if (device->state != EI_DEVICE_STATE_EMULATING)
return;
/* Filter out duplicate scroll stop requests */
@ -449,7 +475,7 @@ ei_device_pointer_scroll_cancel(struct ei_device *device, bool x, bool y)
log_bug_client(ei_device_get_context(device),
"%s: device is not a (absolute) pointer\n", __func__);
}
if (device->state != EI_DEVICE_STATE_RESUMED)
if (device->state != EI_DEVICE_STATE_EMULATING)
return;
/* Filter out duplicate scroll cancelled requests */
@ -480,7 +506,8 @@ ei_device_pointer_scroll_discrete(struct ei_device *device,
log_bug_client(ei_device_get_context(device),
"%s: device is not a (absolute) pointer\n", __func__);
}
if (device->state != EI_DEVICE_STATE_RESUMED)
if (device->state != EI_DEVICE_STATE_EMULATING)
return;
ei_device_resume_scrolling(device, x, y);
@ -498,7 +525,7 @@ ei_device_keyboard_key(struct ei_device *device,
return;
}
if (device->state != EI_DEVICE_STATE_RESUMED)
if (device->state != EI_DEVICE_STATE_EMULATING)
return;
ei_send_keyboard_key(device, key, is_press);

View file

@ -91,6 +91,7 @@ enum ei_device_state {
EI_DEVICE_STATE_NEW,
EI_DEVICE_STATE_PAUSED,
EI_DEVICE_STATE_RESUMED,
EI_DEVICE_STATE_EMULATING,
/**
* Client removed the device, we no longer accept events from the
* client
@ -212,6 +213,12 @@ ei_send_seat_unbind(struct ei_seat *seat);
int
ei_send_close_device(struct ei_device *device);
int
ei_send_start_emulating(struct ei_device *device);
int
ei_send_stop_emulating(struct ei_device *device);
int
ei_send_frame(struct ei_device *device);

View file

@ -151,6 +151,8 @@ log_wire_message(struct ei *ei, const ClientMessage *msg, int error)
MSG_STRING_CASE(BIND_SEAT);
MSG_STRING_CASE(UNBIND_SEAT);
MSG_STRING_CASE(CLOSE_DEVICE);
MSG_STRING_CASE(START_EMULATING);
MSG_STRING_CASE(STOP_EMULATING);
MSG_STRING_CASE(POINTER_RELATIVE);
MSG_STRING_CASE(POINTER_ABSOLUTE);
MSG_STRING_CASE(POINTER_BUTTON);
@ -266,6 +268,26 @@ ei_proto_send_close_device(struct ei_device *device)
return ei_proto_send_msg(ei_device_get_context(device), &msg);
}
static int
ei_proto_send_start_emulating(struct ei_device *device)
{
prepare_msg(START_EMULATING, StartEmulating, start_emulating);
start_emulating.deviceid = device->id;
return ei_proto_send_msg(ei_device_get_context(device), &msg);
}
static int
ei_proto_send_stop_emulating(struct ei_device *device)
{
prepare_msg(STOP_EMULATING, StopEmulating, stop_emulating);
stop_emulating.deviceid = device->id;
return ei_proto_send_msg(ei_device_get_context(device), &msg);
}
static int
ei_proto_send_rel(struct ei_device *device, double x, double y)
{
@ -418,6 +440,8 @@ static const struct ei_proto_requests requests = {
.bind_seat = ei_proto_send_bind_seat,
.unbind_seat = ei_proto_send_unbind_seat,
.close_device = ei_proto_send_close_device,
.start_emulating = ei_proto_send_start_emulating,
.stop_emulating = ei_proto_send_stop_emulating,
.rel = ei_proto_send_rel,
.abs = ei_proto_send_abs,
.button = ei_proto_send_button,

View file

@ -62,6 +62,8 @@ struct ei_proto_requests {
int (*bind_seat)(struct ei_seat *seat, uint32_t capabilities);
int (*unbind_seat)(struct ei_seat *seat);
int (*close_device)(struct ei_device *device);
int (*start_emulating)(struct ei_device *device);
int (*stop_emulating)(struct ei_device *device);
int (*rel)(struct ei_device *device, double x, double y);
int (*abs)(struct ei_device *device, double x, double y);

View file

@ -521,6 +521,34 @@ ei_send_close_device(struct ei_device *device)
return rc;
}
int
ei_send_start_emulating(struct ei_device *device)
{
struct ei *ei = ei_device_get_context(device);
if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED)
return 0;
int rc = ei->requests->start_emulating(device);
if (rc)
ei_disconnect(ei);
return rc;
}
int
ei_send_stop_emulating(struct ei_device *device)
{
struct ei *ei = ei_device_get_context(device);
if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED)
return 0;
int rc = ei->requests->stop_emulating(device);
if (rc)
ei_disconnect(ei);
return rc;
}
int
ei_send_seat_bind(struct ei_seat *seat, uint32_t capabilities)
{

View file

@ -911,6 +911,12 @@ ei_keymap_get_context(struct ei_keymap *keymap);
struct ei *
ei_device_get_context(struct ei_device *device);
void
ei_device_start_emulating(struct ei_device *device);
void
ei_device_stop_emulating(struct ei_device *device);
/**
* Generate a frame event to group the current set of events
* into a logical hardware event. This function **must** be called after any

View file

@ -219,6 +219,42 @@ client_msg_close_device(struct eis_client *client, uint32_t deviceid)
return 0;
}
static int
client_msg_start_emulating(struct eis_client *client, uint32_t deviceid)
{
struct eis_seat *seat;
list_for_each(seat, &client->seats, link) {
struct eis_device *device;
list_for_each(device, &seat->devices, link) {
if (device->id == deviceid) {
eis_device_start_emulating(device);
break;
}
}
}
return 0;
}
static int
client_msg_stop_emulating(struct eis_client *client, uint32_t deviceid)
{
struct eis_seat *seat;
list_for_each(seat, &client->seats, link) {
struct eis_device *device;
list_for_each(device, &seat->devices, link) {
if (device->id == deviceid) {
eis_device_stop_emulating(device);
break;
}
}
}
return 0;
}
static int
client_msg_bind_seat(struct eis_client *client, uint32_t seatid, uint32_t caps)
{
@ -525,6 +561,8 @@ static const struct eis_proto_interface intf_state_connected = {
.bind_seat = client_msg_bind_seat,
.unbind_seat = client_msg_unbind_seat,
.close_device = client_msg_close_device,
.start_emulating = client_msg_start_emulating,
.stop_emulating = client_msg_stop_emulating,
.rel = client_msg_pointer_rel,
.abs = client_msg_pointer_abs,
.button = client_msg_pointer_button,

View file

@ -281,7 +281,7 @@ eis_device_pointer_rel(struct eis_device *device,
return -EINVAL;
}
if (device->state != EIS_DEVICE_STATE_RESUMED)
if (device->state != EIS_DEVICE_STATE_EMULATING)
return -EINVAL;
eis_queue_pointer_rel_event(device, x, y);
@ -312,7 +312,7 @@ eis_device_pointer_abs(struct eis_device *device,
return -EINVAL;
}
if (device->state != EIS_DEVICE_STATE_RESUMED)
if (device->state != EIS_DEVICE_STATE_EMULATING)
return -EINVAL;
if (!eis_device_in_region(device, x, y))
@ -333,7 +333,7 @@ eis_device_pointer_button(struct eis_device *device,
return -EINVAL;
}
if (device->state != EIS_DEVICE_STATE_RESUMED)
if (device->state != EIS_DEVICE_STATE_EMULATING)
return -EINVAL;
eis_queue_pointer_button_event(device, button, is_press);
@ -352,7 +352,7 @@ eis_device_pointer_scroll(struct eis_device *device,
return -EINVAL;
}
if (device->state != EIS_DEVICE_STATE_RESUMED)
if (device->state != EIS_DEVICE_STATE_EMULATING)
return -EINVAL;
eis_queue_pointer_scroll_event(device, x, y);
@ -371,7 +371,7 @@ eis_device_pointer_scroll_discrete(struct eis_device *device,
return -EINVAL;
}
if (device->state != EIS_DEVICE_STATE_RESUMED)
if (device->state != EIS_DEVICE_STATE_EMULATING)
return -EINVAL;
eis_queue_pointer_scroll_discrete_event(device, x, y);
@ -389,7 +389,7 @@ eis_device_pointer_scroll_stop(struct eis_device *device, bool x, bool y)
return -EINVAL;
}
if (device->state != EIS_DEVICE_STATE_RESUMED)
if (device->state != EIS_DEVICE_STATE_EMULATING)
return -EINVAL;
eis_queue_pointer_scroll_stop_event(device, x, y);
@ -407,7 +407,7 @@ eis_device_pointer_scroll_cancel(struct eis_device *device, bool x, bool y)
return -EINVAL;
}
if (device->state != EIS_DEVICE_STATE_RESUMED)
if (device->state != EIS_DEVICE_STATE_EMULATING)
return -EINVAL;
eis_queue_pointer_scroll_cancel_event(device, x, y);
@ -425,7 +425,7 @@ eis_device_keyboard_key(struct eis_device *device,
return -EINVAL;
}
if (device->state != EIS_DEVICE_STATE_RESUMED)
if (device->state != EIS_DEVICE_STATE_EMULATING)
return -EINVAL;
eis_queue_keyboard_key_event(device, key, is_press);
@ -442,7 +442,7 @@ eis_device_touch_down(struct eis_device *device, uint32_t touchid, double x, dou
return -EINVAL;
}
if (device->state != EIS_DEVICE_STATE_RESUMED)
if (device->state != EIS_DEVICE_STATE_EMULATING)
return -EINVAL;
eis_queue_touch_down_event(device, touchid, x, y);
@ -459,7 +459,7 @@ eis_device_touch_motion(struct eis_device *device, uint32_t touchid, double x, d
return -EINVAL;
}
if (device->state != EIS_DEVICE_STATE_RESUMED)
if (device->state != EIS_DEVICE_STATE_EMULATING)
return -EINVAL;
eis_queue_touch_motion_event(device, touchid, x, y);
@ -476,7 +476,7 @@ eis_device_touch_up(struct eis_device *device, uint32_t touchid)
return -EINVAL;
}
if (device->state != EIS_DEVICE_STATE_RESUMED)
if (device->state != EIS_DEVICE_STATE_EMULATING)
return -EINVAL;
eis_queue_touch_up_event(device, touchid);
@ -492,6 +492,9 @@ eis_device_closed_by_client(struct eis_device *device)
case EIS_DEVICE_STATE_CLOSED_BY_CLIENT:
/* libei bug, ignore */
break;
case EIS_DEVICE_STATE_EMULATING:
eis_queue_device_stop_emulating_event(device);
_fallthrough_;
case EIS_DEVICE_STATE_NEW:
case EIS_DEVICE_STATE_PAUSED:
case EIS_DEVICE_STATE_RESUMED:
@ -501,6 +504,41 @@ eis_device_closed_by_client(struct eis_device *device)
}
}
void
eis_device_start_emulating(struct eis_device *device)
{
switch (device->state) {
case EIS_DEVICE_STATE_DEAD:
case EIS_DEVICE_STATE_CLOSED_BY_CLIENT:
case EIS_DEVICE_STATE_NEW:
case EIS_DEVICE_STATE_PAUSED:
break;
case EIS_DEVICE_STATE_RESUMED:
eis_queue_device_start_emulating_event(device);
device->state = EIS_DEVICE_STATE_EMULATING;
break;
case EIS_DEVICE_STATE_EMULATING:
break;
}
}
void
eis_device_stop_emulating(struct eis_device *device)
{
switch (device->state) {
case EIS_DEVICE_STATE_DEAD:
case EIS_DEVICE_STATE_CLOSED_BY_CLIENT:
case EIS_DEVICE_STATE_NEW:
case EIS_DEVICE_STATE_PAUSED:
case EIS_DEVICE_STATE_RESUMED:
break;
case EIS_DEVICE_STATE_EMULATING:
eis_queue_device_stop_emulating_event(device);
device->state = EIS_DEVICE_STATE_RESUMED;
break;
}
}
_public_ void
eis_device_pause(struct eis_device *device)
{

View file

@ -42,6 +42,8 @@ eis_event_destroy(struct eis_event *event)
case EIS_EVENT_SEAT_BIND:
case EIS_EVENT_SEAT_UNBIND:
case EIS_EVENT_DEVICE_CLOSED:
case EIS_EVENT_DEVICE_START_EMULATING:
case EIS_EVENT_DEVICE_STOP_EMULATING:
case EIS_EVENT_POINTER_BUTTON:
case EIS_EVENT_POINTER_MOTION:
case EIS_EVENT_POINTER_MOTION_ABSOLUTE:

View file

@ -110,6 +110,7 @@ enum eis_device_state {
EIS_DEVICE_STATE_NEW,
EIS_DEVICE_STATE_PAUSED,
EIS_DEVICE_STATE_RESUMED,
EIS_DEVICE_STATE_EMULATING,
EIS_DEVICE_STATE_CLOSED_BY_CLIENT,
EIS_DEVICE_STATE_DEAD,
};
@ -282,6 +283,12 @@ eis_device_touch_up(struct eis_device *device, uint32_t touchid);
void
eis_device_closed_by_client(struct eis_device *device);
void
eis_device_start_emulating(struct eis_device *device);
void
eis_device_stop_emulating(struct eis_device *device);
bool
eis_region_contains(struct eis_region *r, double x, double y);
@ -318,6 +325,12 @@ eis_queue_device_closed_event(struct eis_device *device);
void
eis_queue_frame_event(struct eis_device *device);
void
eis_queue_device_start_emulating_event(struct eis_device *device);
void
eis_queue_device_stop_emulating_event(struct eis_device *device);
void
eis_queue_pointer_rel_event(struct eis_device *device, double x, double y);

View file

@ -312,6 +312,14 @@ eis_proto_handle_message(struct eis_client *client,
rc = call(close_device, client,
proto->close_device->deviceid);
break;
case CLIENT_MESSAGE__MSG_START_EMULATING:
rc = call(start_emulating, client,
proto->start_emulating->deviceid);
break;
case CLIENT_MESSAGE__MSG_STOP_EMULATING:
rc = call(stop_emulating, client,
proto->stop_emulating->deviceid);
break;
case CLIENT_MESSAGE__MSG_POINTER_RELATIVE:
rc = call(rel, client,
proto->pointer_relative->deviceid,

View file

@ -40,6 +40,8 @@ struct eis_proto_interface {
int (*bind_seat)(struct eis_client *client, uint32_t seatid, uint32_t capabilities);
int (*unbind_seat)(struct eis_client *client, uint32_t seatid);
int (*close_device)(struct eis_client *client, uint32_t deviceid);
int (*start_emulating)(struct eis_client *client, uint32_t deviceid);
int (*stop_emulating)(struct eis_client *client, uint32_t deviceid);
int (*rel)(struct eis_client *client, uint32_t deviceid, double x, double y);
int (*abs)(struct eis_client *client, uint32_t deviceid, double x, double y);
int (*button)(struct eis_client *client, uint32_t deviceid, uint32_t button, bool is_press);

View file

@ -108,6 +108,8 @@ eis_event_type_to_string(enum eis_event_type type)
CASE_RETURN_STRING(EIS_EVENT_SEAT_BIND);
CASE_RETURN_STRING(EIS_EVENT_SEAT_UNBIND);
CASE_RETURN_STRING(EIS_EVENT_DEVICE_CLOSED);
CASE_RETURN_STRING(EIS_EVENT_DEVICE_START_EMULATING);
CASE_RETURN_STRING(EIS_EVENT_DEVICE_STOP_EMULATING);
CASE_RETURN_STRING(EIS_EVENT_POINTER_MOTION);
CASE_RETURN_STRING(EIS_EVENT_POINTER_MOTION_ABSOLUTE);
CASE_RETURN_STRING(EIS_EVENT_POINTER_BUTTON);
@ -185,6 +187,22 @@ eis_queue_frame_event(struct eis_device *device)
eis_queue_event(e);
}
void
eis_queue_device_start_emulating_event(struct eis_device *device)
{
struct eis_event *e = eis_event_new_for_device(device);
e->type = EIS_EVENT_DEVICE_START_EMULATING;
eis_queue_event(e);
}
void
eis_queue_device_stop_emulating_event(struct eis_device *device)
{
struct eis_event *e = eis_event_new_for_device(device);
e->type = EIS_EVENT_DEVICE_STOP_EMULATING;
eis_queue_event(e);
}
void
eis_queue_pointer_rel_event(struct eis_device *device,
double dx, double dy)

View file

@ -127,6 +127,23 @@ enum eis_event_type {
*/
EIS_EVENT_FRAME = 100,
/**
* The client is about to send events for a device. This event should
* be used by the server to clear the logical state of the emulated
* devices and/or provide UI to the user.
*
* Note that a client may need to start multiple emulating sequences
* simultaneously, depending on the devices it received from the
* server. For example, in a synergy-like situation, the device client
* may start emulating of pointer and keyboard once the remote device
* logically entered the screen.
*
* The server can cancel an ongoing emulating by suspending the
* device, see eis_device_suspend().
*/
EIS_EVENT_DEVICE_START_EMULATING = 200,
EIS_EVENT_DEVICE_STOP_EMULATING,
EIS_EVENT_POINTER_MOTION = 300,
EIS_EVENT_POINTER_MOTION_ABSOLUTE,
EIS_EVENT_POINTER_BUTTON,

View file

@ -331,6 +331,7 @@ peck_new(void)
peck->ei = ei;
flag_set(peck->ei_behavior, PECK_EI_BEHAVIOR_AUTOCONNECT);
flag_set(peck->ei_behavior, PECK_EI_BEHAVIOR_AUTOSEAT);
flag_set(peck->ei_behavior, PECK_EI_BEHAVIOR_AUTOSTART);
struct eis *eis = eis_new(peck);
eis_log_set_handler(eis, peck_eis_log_handler);
@ -367,6 +368,8 @@ peck_enable_eis_behavior(struct peck *peck, enum peck_eis_behavior behavior)
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_HANDLE_BIND_SEAT);
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_RESUME_DEVICE);
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_HANDLE_CLOSE_DEVICE);
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_HANDLE_START_EMULATING);
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_HANDLE_STOP_EMULATING);
break;
case PECK_EIS_BEHAVIOR_ADD_DEVICES:
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_POINTER);
@ -382,6 +385,8 @@ peck_enable_eis_behavior(struct peck *peck, enum peck_eis_behavior behavior)
case PECK_EIS_BEHAVIOR_HANDLE_UNBIND_SEAT:
case PECK_EIS_BEHAVIOR_HANDLE_CLOSE_DEVICE:
case PECK_EIS_BEHAVIOR_HANDLE_FRAME:
case PECK_EIS_BEHAVIOR_HANDLE_START_EMULATING:
case PECK_EIS_BEHAVIOR_HANDLE_STOP_EMULATING:
case PECK_EIS_BEHAVIOR_ADD_POINTER:
case PECK_EIS_BEHAVIOR_ADD_POINTER_ABSOLUTE:
case PECK_EIS_BEHAVIOR_ADD_KEYBOARD:
@ -426,6 +431,7 @@ peck_enable_ei_behavior(struct peck *peck, enum peck_ei_behavior behavior)
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_ADDED_KEYBOARD);
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_ADDED_TOUCH);
break;
case PECK_EI_BEHAVIOR_AUTOSTART:
case PECK_EI_BEHAVIOR_HANDLE_ADDED_POINTER:
case PECK_EI_BEHAVIOR_HANDLE_ADDED_POINTER_ABSOLUTE:
case PECK_EI_BEHAVIOR_HANDLE_ADDED_KEYBOARD:
@ -652,6 +658,14 @@ _peck_dispatch_eis(struct peck *peck, int lineno)
if (flag_is_set(peck->eis_behavior, PECK_EIS_BEHAVIOR_HANDLE_FRAME))
process_event = tristate_yes;
break;
case EIS_EVENT_DEVICE_START_EMULATING:
if (flag_is_set(peck->eis_behavior, PECK_EIS_BEHAVIOR_HANDLE_START_EMULATING))
process_event = tristate_yes;
break;
case EIS_EVENT_DEVICE_STOP_EMULATING:
if (flag_is_set(peck->eis_behavior, PECK_EIS_BEHAVIOR_HANDLE_STOP_EMULATING))
process_event = tristate_yes;
break;
default:
break;
}
@ -808,6 +822,11 @@ _peck_dispatch_ei(struct peck *peck, int lineno)
break;
}
case EI_EVENT_DEVICE_RESUMED:
if (flag_is_set(peck->ei_behavior, PECK_EI_BEHAVIOR_AUTOSTART)) {
struct ei_device *device = ei_event_get_device(e);
ei_device_start_emulating(device);
}
break;
case EI_EVENT_DEVICE_PAUSED:
/* Nothing to do here */
break;
@ -1016,6 +1035,8 @@ peck_eis_event_type_name(enum eis_event_type type)
CASE_STRING(SEAT_BIND);
CASE_STRING(SEAT_UNBIND);
CASE_STRING(DEVICE_CLOSED);
CASE_STRING(DEVICE_START_EMULATING);
CASE_STRING(DEVICE_STOP_EMULATING);
CASE_STRING(POINTER_MOTION);
CASE_STRING(POINTER_MOTION_ABSOLUTE);
CASE_STRING(POINTER_BUTTON);

View file

@ -84,6 +84,12 @@ enum peck_eis_behavior {
* Handle frame events. This behavior is enabled by default.
*/
PECK_EIS_BEHAVIOR_HANDLE_FRAME,
/**
* Handle the start/stop emulation event. This behavior is enabled as part of
* PECK_EIS_BEHAVIOR_ACCEPT_ALL.
*/
PECK_EIS_BEHAVIOR_HANDLE_START_EMULATING,
PECK_EIS_BEHAVIOR_HANDLE_STOP_EMULATING,
/**
* Create default devices
@ -108,6 +114,10 @@ enum peck_ei_behavior {
/* handle Connect/Seat/Added/Resumed events, i.e. anything until the
* first real device event */
PECK_EI_BEHAVIOR_AUTODEVICES,
/**
* Immediately send a StartEmulating request once a device is resumed.
*/
PECK_EI_BEHAVIOR_AUTOSTART,
PECK_EI_BEHAVIOR_HANDLE_ADDED,
PECK_EI_BEHAVIOR_HANDLE_ADDED_POINTER,
PECK_EI_BEHAVIOR_HANDLE_ADDED_POINTER_ABSOLUTE,
@ -287,6 +297,9 @@ DEFINE_UNREF_CLEANUP_FUNC(eis_region);
of a test handles server vs client */
#define with_server(peck_) for (struct eis *eis = peck_get_eis(peck_); eis; eis = NULL)
#define with_client(peck_) for (struct ei *ei = peck_get_ei(peck_); ei; ei = NULL)
#define with_emulation(d_) for (bool _loop = ({ ei_device_start_emulating(d_); true;});\
_loop; \
({ ei_device_stop_emulating(d_); _loop = false; }))
#define peck_errno_check(_rc) { \
const int xrc = (_rc); \

View file

@ -465,7 +465,9 @@ MUNIT_TEST(test_ei_device_pointer_abs)
peck_dispatch_until_stable(peck);
with_server(peck) {
_unref_(eis_event) *e =
_unref_(eis_event) *stop =
peck_eis_next_event(eis, EIS_EVENT_DEVICE_STOP_EMULATING);
_unref_(eis_event) *closed =
peck_eis_next_event(eis, EIS_EVENT_DEVICE_CLOSED);
peck_assert_no_eis_events(eis);
}

View file

@ -466,6 +466,7 @@ MUNIT_TEST(test_xdotool_rel_motion)
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL);
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_POINTER);
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTODEVICES);
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTOSTART);
peck_dispatch_until_stable(peck);
with_client(peck) {
@ -482,6 +483,8 @@ MUNIT_TEST(test_xdotool_rel_motion)
with_server(peck) {
_unref_(eis_event) *motion =
peck_eis_next_event(eis, EIS_EVENT_POINTER_MOTION);
_unref_(eis_event) *stop =
peck_eis_next_event(eis, EIS_EVENT_DEVICE_STOP_EMULATING);
_unref_(eis_event) *close =
peck_eis_next_event(eis, EIS_EVENT_DEVICE_CLOSED);
_unref_(eis_event) *unbind =

View file

@ -238,6 +238,7 @@ MUNIT_TEST(eistest_device_ignore_paused_device)
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_CLIENT);
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_DEFAULT_SEAT);
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_HANDLE_BIND_SEAT);
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_HANDLE_START_EMULATING);
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_POINTER);
peck_dispatch_until_stable(peck);
@ -269,7 +270,9 @@ MUNIT_TEST(eistest_device_ignore_paused_device)
struct ei_device *device = ei_event_get_device(resumed);
peck_assert_no_ei_events(ei);
ei_device_pointer_motion(device, 1, 1);
with_emulation(device) {
ei_device_pointer_motion(device, 1, 1);
}
}
peck_dispatch_until_stable(peck);
@ -278,6 +281,8 @@ MUNIT_TEST(eistest_device_ignore_paused_device)
with_server(peck) {
_unref_(eis_event) *rel =
peck_eis_next_event(eis, EIS_EVENT_POINTER_MOTION);
_unref_(eis_event) *stop =
peck_eis_next_event(eis, EIS_EVENT_DEVICE_STOP_EMULATING);
peck_assert_no_eis_events(eis);
eis_device_pause(device);
}

View file

@ -320,14 +320,17 @@ int main(int argc, char **argv)
break;
case EI_EVENT_DEVICE_RESUMED:
if (ei_event_get_device(e) == ptr) {
ei_device_start_emulating(ptr);
colorprint("Pointer device was resumed\n");
have_ptr = true;
}
if (ei_event_get_device(e) == kbd) {
ei_device_start_emulating(kbd);
colorprint("Keyboard device was resumed\n");
have_kbd = true;
}
if (ei_event_get_device(e) == abs) {
ei_device_start_emulating(abs);
colorprint("Abs pointer device was resumed\n");
have_abs = true;
}

View file

@ -236,6 +236,18 @@ eis_demo_server_printf_handle_event(struct eis_demo_server *server,
eis_device_unref(device); /* because our devices have a dangling */
}
break;
case EIS_EVENT_DEVICE_START_EMULATING:
{
struct eis_device *device = eis_event_get_device(e);
colorprint("Device %s is ready to send events\n", eis_device_get_name(device));
}
break;
case EIS_EVENT_DEVICE_STOP_EMULATING:
{
struct eis_device *device = eis_event_get_device(e);
colorprint("Device %s will no longer send events\n", eis_device_get_name(device));
}
break;
case EIS_EVENT_POINTER_MOTION:
{
colorprint("motion by %.2f/%.2f\n",