mirror of
https://gitlab.freedesktop.org/libinput/libei.git
synced 2026-02-04 14:10:27 +01:00
Add concept of active/passive libei contexts
A libei context can be initialized as active or passive context - an "active" context sends events, a "passive" context receives events. The EIS context supports both simultaneously, it is up to the implementation to disconnect libei clients that it does not want to suppport. For example, the xdotool use-case creates an active libei context. The EIS implementation controls and sets up the devices, but libei sends the events. In an input-capturing use-case, the EIS implementation controls and sets up the devices **and** sends the events. libei is merely the receiver for any event, it cannot send events. Thus this use-case requires a passive libei context. Most of this code is copy/paste with minor modifications - libei already had the code to send events, libeis had the code to receive events, so the vast majority of this patch is copying the code into the respective other library, swap "ei" and "eis" and then apply the various minor modifications needed to hook into the existing library. Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
parent
72cfef9a56
commit
faa9500afe
17 changed files with 2105 additions and 15 deletions
|
|
@ -60,6 +60,7 @@ message ConfigureCapabilities {
|
|||
|
||||
message Connect {
|
||||
string name = 1;
|
||||
bool is_active = 2;
|
||||
}
|
||||
|
||||
message ConnectDone {
|
||||
|
|
@ -195,6 +196,7 @@ message Connected {
|
|||
}
|
||||
|
||||
message Disconnected {
|
||||
bool is_active = 2;
|
||||
}
|
||||
|
||||
message SeatAdded {
|
||||
|
|
@ -256,6 +258,7 @@ message KeyboardModifiers {
|
|||
|
||||
message ServerMessage {
|
||||
oneof msg {
|
||||
/* Server setup and configuration */
|
||||
Connected connected = 2;
|
||||
Disconnected disconnected = 3;
|
||||
SeatAdded seat_added = 4;
|
||||
|
|
@ -269,6 +272,21 @@ message ServerMessage {
|
|||
DevicePaused device_paused = 12;
|
||||
KeyboardModifiers keyboard_modifiers = 13;
|
||||
Property property = 14;
|
||||
|
||||
/* Events */
|
||||
StartEmulating start_emulating = 20;
|
||||
StopEmulating stop_emulating = 21;
|
||||
PointerRelative pointer_relative = 22;
|
||||
PointerAbsolute pointer_absolute = 23;
|
||||
PointerScroll pointer_scroll = 24;
|
||||
PointerScrollDiscrete pointer_scroll_discrete = 25;
|
||||
PointerScrollStop pointer_scroll_stop = 26;
|
||||
PointerButton pointer_button = 27;
|
||||
KeyboardKey keyboard_key = 28;
|
||||
TouchDown touch_down = 29;
|
||||
TouchMotion touch_motion = 30;
|
||||
TouchUp touch_up = 31;
|
||||
Frame frame = 32;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -638,3 +638,265 @@ ei_device_frame(struct ei_device *device)
|
|||
|
||||
ei_send_frame(device);
|
||||
}
|
||||
|
||||
void
|
||||
ei_device_event_start_emulating(struct ei_device *device)
|
||||
{
|
||||
switch (device->state) {
|
||||
case EI_DEVICE_STATE_DEAD:
|
||||
case EI_DEVICE_STATE_NEW:
|
||||
case EI_DEVICE_STATE_PAUSED:
|
||||
case EI_DEVICE_STATE_EMULATING:
|
||||
break;
|
||||
case EI_DEVICE_STATE_RESUMED:
|
||||
ei_queue_device_start_emulating_event(device);
|
||||
device->state = EI_DEVICE_STATE_EMULATING;
|
||||
break;
|
||||
case EI_DEVICE_STATE_REMOVED_FROM_CLIENT:
|
||||
case EI_DEVICE_STATE_REMOVED_FROM_SERVER:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ei_device_event_stop_emulating(struct ei_device *device)
|
||||
{
|
||||
switch (device->state) {
|
||||
case EI_DEVICE_STATE_DEAD:
|
||||
case EI_DEVICE_STATE_NEW:
|
||||
case EI_DEVICE_STATE_PAUSED:
|
||||
case EI_DEVICE_STATE_RESUMED:
|
||||
break;
|
||||
case EI_DEVICE_STATE_EMULATING:
|
||||
ei_queue_device_stop_emulating_event(device);
|
||||
device->state = EI_DEVICE_STATE_RESUMED;
|
||||
break;
|
||||
case EI_DEVICE_STATE_REMOVED_FROM_CLIENT:
|
||||
case EI_DEVICE_STATE_REMOVED_FROM_SERVER:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
ei_device_event_frame(struct ei_device *device)
|
||||
{
|
||||
if (device->state != EI_DEVICE_STATE_RESUMED)
|
||||
return -EINVAL;
|
||||
|
||||
ei_queue_frame_event(device);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ei_device_event_pointer_rel(struct ei_device *device, double x, double y)
|
||||
{
|
||||
if (!ei_device_has_capability(device, EI_DEVICE_CAP_POINTER)) {
|
||||
log_bug_client(ei_device_get_context(device),
|
||||
"%s: device is not a pointer\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (device->state != EI_DEVICE_STATE_EMULATING)
|
||||
return -EINVAL;
|
||||
|
||||
ei_queue_pointer_rel_event(device, x, y);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
ei_device_in_region(struct ei_device *device, double x, double y)
|
||||
{
|
||||
struct ei_region *r;
|
||||
|
||||
list_for_each(r, &device->regions, link) {
|
||||
if (ei_region_contains(r, x, y))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int
|
||||
ei_device_event_pointer_abs(struct ei_device *device,
|
||||
double x, double y)
|
||||
{
|
||||
if (!ei_device_has_capability(device, EI_DEVICE_CAP_POINTER_ABSOLUTE)) {
|
||||
log_bug_client(ei_device_get_context(device),
|
||||
"%s: device is not an absolute pointer\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (device->state != EI_DEVICE_STATE_EMULATING)
|
||||
return -EINVAL;
|
||||
|
||||
if (!ei_device_in_region(device, x, y))
|
||||
return -EINVAL;
|
||||
|
||||
ei_queue_pointer_abs_event(device, x, y);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ei_device_event_pointer_button(struct ei_device *device,
|
||||
uint32_t button, bool is_press)
|
||||
{
|
||||
if (!ei_device_has_capability(device, EI_DEVICE_CAP_POINTER)) {
|
||||
log_bug_client(ei_device_get_context(device),
|
||||
"%s: device is not a pointer\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (device->state != EI_DEVICE_STATE_EMULATING)
|
||||
return -EINVAL;
|
||||
|
||||
ei_queue_pointer_button_event(device, button, is_press);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ei_device_event_pointer_scroll(struct ei_device *device,
|
||||
double x, double y)
|
||||
{
|
||||
if (!ei_device_has_capability(device, EI_DEVICE_CAP_POINTER) &&
|
||||
!ei_device_has_capability(device, EI_DEVICE_CAP_POINTER_ABSOLUTE)) {
|
||||
log_bug_client(ei_device_get_context(device),
|
||||
"%s: device is not a (absolute) pointer\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (device->state != EI_DEVICE_STATE_EMULATING)
|
||||
return -EINVAL;
|
||||
|
||||
ei_queue_pointer_scroll_event(device, x, y);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ei_device_event_pointer_scroll_discrete(struct ei_device *device,
|
||||
int32_t x, int32_t y)
|
||||
{
|
||||
if (!ei_device_has_capability(device, EI_DEVICE_CAP_POINTER) &&
|
||||
!ei_device_has_capability(device, EI_DEVICE_CAP_POINTER_ABSOLUTE)) {
|
||||
log_bug_client(ei_device_get_context(device),
|
||||
"%s: device is not a (absolute) pointer\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (device->state != EI_DEVICE_STATE_EMULATING)
|
||||
return -EINVAL;
|
||||
|
||||
ei_queue_pointer_scroll_discrete_event(device, x, y);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ei_device_event_pointer_scroll_stop(struct ei_device *device, bool x, bool y)
|
||||
{
|
||||
if (!ei_device_has_capability(device, EI_DEVICE_CAP_POINTER) &&
|
||||
!ei_device_has_capability(device, EI_DEVICE_CAP_POINTER_ABSOLUTE)) {
|
||||
log_bug_client(ei_device_get_context(device),
|
||||
"%s: device is not a (absolute) pointer\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (device->state != EI_DEVICE_STATE_EMULATING)
|
||||
return -EINVAL;
|
||||
|
||||
ei_queue_pointer_scroll_stop_event(device, x, y);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ei_device_event_pointer_scroll_cancel(struct ei_device *device, bool x, bool y)
|
||||
{
|
||||
if (!ei_device_has_capability(device, EI_DEVICE_CAP_POINTER) &&
|
||||
!ei_device_has_capability(device, EI_DEVICE_CAP_POINTER_ABSOLUTE)) {
|
||||
log_bug_client(ei_device_get_context(device),
|
||||
"%s: device is not a (absolute) pointer\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (device->state != EI_DEVICE_STATE_EMULATING)
|
||||
return -EINVAL;
|
||||
|
||||
ei_queue_pointer_scroll_cancel_event(device, x, y);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ei_device_event_keyboard_key(struct ei_device *device,
|
||||
uint32_t key, bool is_press)
|
||||
{
|
||||
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 -EINVAL;
|
||||
}
|
||||
|
||||
if (device->state != EI_DEVICE_STATE_EMULATING)
|
||||
return -EINVAL;
|
||||
|
||||
ei_queue_keyboard_key_event(device, key, is_press);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ei_device_event_touch_down(struct ei_device *device, uint32_t touchid, double x, double y)
|
||||
{
|
||||
if (!ei_device_has_capability(device, EI_DEVICE_CAP_TOUCH)) {
|
||||
log_bug_client(ei_device_get_context(device),
|
||||
"%s: device is not a touch device\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (device->state != EI_DEVICE_STATE_EMULATING)
|
||||
return -EINVAL;
|
||||
|
||||
ei_queue_touch_down_event(device, touchid, x, y);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ei_device_event_touch_motion(struct ei_device *device, uint32_t touchid, double x, double y)
|
||||
{
|
||||
if (!ei_device_has_capability(device, EI_DEVICE_CAP_TOUCH)) {
|
||||
log_bug_client(ei_device_get_context(device),
|
||||
"%s: device is not a touch device\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (device->state != EI_DEVICE_STATE_EMULATING)
|
||||
return -EINVAL;
|
||||
|
||||
ei_queue_touch_motion_event(device, touchid, x, y);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ei_device_event_touch_up(struct ei_device *device, uint32_t touchid)
|
||||
{
|
||||
if (!ei_device_has_capability(device, EI_DEVICE_CAP_TOUCH)) {
|
||||
log_bug_client(ei_device_get_context(device),
|
||||
"%s: device is not a touch device\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (device->state != EI_DEVICE_STATE_EMULATING)
|
||||
return -EINVAL;
|
||||
|
||||
ei_queue_touch_up_event(device, touchid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -50,6 +50,20 @@ ei_event_type_to_string(enum ei_event_type type)
|
|||
CASE_RETURN_STRING(EI_EVENT_DEVICE_RESUMED);
|
||||
CASE_RETURN_STRING(EI_EVENT_KEYBOARD_MODIFIERS);
|
||||
CASE_RETURN_STRING(EI_EVENT_PROPERTY);
|
||||
CASE_RETURN_STRING(EI_EVENT_FRAME);
|
||||
CASE_RETURN_STRING(EI_EVENT_DEVICE_START_EMULATING);
|
||||
CASE_RETURN_STRING(EI_EVENT_DEVICE_STOP_EMULATING);
|
||||
CASE_RETURN_STRING(EI_EVENT_POINTER_MOTION);
|
||||
CASE_RETURN_STRING(EI_EVENT_POINTER_MOTION_ABSOLUTE);
|
||||
CASE_RETURN_STRING(EI_EVENT_POINTER_BUTTON);
|
||||
CASE_RETURN_STRING(EI_EVENT_POINTER_SCROLL);
|
||||
CASE_RETURN_STRING(EI_EVENT_POINTER_SCROLL_STOP);
|
||||
CASE_RETURN_STRING(EI_EVENT_POINTER_SCROLL_CANCEL);
|
||||
CASE_RETURN_STRING(EI_EVENT_POINTER_SCROLL_DISCRETE);
|
||||
CASE_RETURN_STRING(EI_EVENT_KEYBOARD_KEY);
|
||||
CASE_RETURN_STRING(EI_EVENT_TOUCH_DOWN);
|
||||
CASE_RETURN_STRING(EI_EVENT_TOUCH_UP);
|
||||
CASE_RETURN_STRING(EI_EVENT_TOUCH_MOTION);
|
||||
}
|
||||
|
||||
assert(!"Unhandled event type");
|
||||
|
|
@ -73,6 +87,21 @@ ei_event_destroy(struct ei_event *event)
|
|||
free(event->prop.name);
|
||||
free(event->prop.value);
|
||||
break;
|
||||
case EI_EVENT_FRAME:
|
||||
case EI_EVENT_DEVICE_START_EMULATING:
|
||||
case EI_EVENT_DEVICE_STOP_EMULATING:
|
||||
case EI_EVENT_POINTER_MOTION:
|
||||
case EI_EVENT_POINTER_MOTION_ABSOLUTE:
|
||||
case EI_EVENT_POINTER_BUTTON:
|
||||
case EI_EVENT_POINTER_SCROLL:
|
||||
case EI_EVENT_POINTER_SCROLL_STOP:
|
||||
case EI_EVENT_POINTER_SCROLL_CANCEL:
|
||||
case EI_EVENT_POINTER_SCROLL_DISCRETE:
|
||||
case EI_EVENT_KEYBOARD_KEY:
|
||||
case EI_EVENT_TOUCH_DOWN:
|
||||
case EI_EVENT_TOUCH_UP:
|
||||
case EI_EVENT_TOUCH_MOTION:
|
||||
break;
|
||||
}
|
||||
ei_device_unref(event->device);
|
||||
ei_seat_unref(event->seat);
|
||||
|
|
@ -200,3 +229,196 @@ ei_event_property_get_permissions(struct ei_event *event)
|
|||
return event->prop.permissions;
|
||||
}
|
||||
|
||||
|
||||
_public_ double
|
||||
ei_event_pointer_get_dx(struct ei_event *event)
|
||||
{
|
||||
require_event_type(event, 0.0,
|
||||
EI_EVENT_POINTER_MOTION,
|
||||
EI_EVENT_POINTER_MOTION_ABSOLUTE,
|
||||
EI_EVENT_POINTER_BUTTON,
|
||||
EI_EVENT_POINTER_SCROLL,
|
||||
EI_EVENT_POINTER_SCROLL_DISCRETE);
|
||||
|
||||
return event->pointer.dx;
|
||||
}
|
||||
|
||||
_public_ double
|
||||
ei_event_pointer_get_dy(struct ei_event *event)
|
||||
{
|
||||
require_event_type(event, 0.0,
|
||||
EI_EVENT_POINTER_MOTION,
|
||||
EI_EVENT_POINTER_MOTION_ABSOLUTE,
|
||||
EI_EVENT_POINTER_BUTTON,
|
||||
EI_EVENT_POINTER_SCROLL,
|
||||
EI_EVENT_POINTER_SCROLL_DISCRETE);
|
||||
|
||||
return event->pointer.dy;
|
||||
}
|
||||
|
||||
_public_ double
|
||||
ei_event_pointer_get_absolute_x(struct ei_event *event)
|
||||
{
|
||||
require_event_type(event, 0.0,
|
||||
EI_EVENT_POINTER_MOTION,
|
||||
EI_EVENT_POINTER_MOTION_ABSOLUTE,
|
||||
EI_EVENT_POINTER_BUTTON,
|
||||
EI_EVENT_POINTER_SCROLL,
|
||||
EI_EVENT_POINTER_SCROLL_DISCRETE);
|
||||
|
||||
return event->pointer.absx;
|
||||
}
|
||||
|
||||
_public_ double
|
||||
ei_event_pointer_get_absolute_y(struct ei_event *event)
|
||||
{
|
||||
require_event_type(event, 0.0,
|
||||
EI_EVENT_POINTER_MOTION,
|
||||
EI_EVENT_POINTER_MOTION_ABSOLUTE,
|
||||
EI_EVENT_POINTER_BUTTON,
|
||||
EI_EVENT_POINTER_SCROLL,
|
||||
EI_EVENT_POINTER_SCROLL_DISCRETE);
|
||||
|
||||
return event->pointer.absy;
|
||||
}
|
||||
|
||||
_public_ uint32_t
|
||||
ei_event_pointer_get_button(struct ei_event *event)
|
||||
{
|
||||
require_event_type(event, 0,
|
||||
EI_EVENT_POINTER_MOTION,
|
||||
EI_EVENT_POINTER_MOTION_ABSOLUTE,
|
||||
EI_EVENT_POINTER_BUTTON,
|
||||
EI_EVENT_POINTER_SCROLL,
|
||||
EI_EVENT_POINTER_SCROLL_DISCRETE);
|
||||
|
||||
return event->pointer.button;
|
||||
}
|
||||
|
||||
_public_ bool
|
||||
ei_event_pointer_get_button_is_press(struct ei_event *event)
|
||||
{
|
||||
require_event_type(event, false,
|
||||
EI_EVENT_POINTER_MOTION,
|
||||
EI_EVENT_POINTER_MOTION_ABSOLUTE,
|
||||
EI_EVENT_POINTER_BUTTON,
|
||||
EI_EVENT_POINTER_SCROLL,
|
||||
EI_EVENT_POINTER_SCROLL_DISCRETE);
|
||||
|
||||
return event->pointer.button_is_press;
|
||||
}
|
||||
|
||||
_public_ double
|
||||
ei_event_pointer_get_scroll_x(struct ei_event *event)
|
||||
{
|
||||
require_event_type(event, 0,
|
||||
EI_EVENT_POINTER_MOTION,
|
||||
EI_EVENT_POINTER_MOTION_ABSOLUTE,
|
||||
EI_EVENT_POINTER_BUTTON,
|
||||
EI_EVENT_POINTER_SCROLL,
|
||||
EI_EVENT_POINTER_SCROLL_DISCRETE);
|
||||
return event->pointer.sx;
|
||||
}
|
||||
|
||||
_public_ double
|
||||
ei_event_pointer_get_scroll_y(struct ei_event *event)
|
||||
{
|
||||
require_event_type(event, 0,
|
||||
EI_EVENT_POINTER_MOTION,
|
||||
EI_EVENT_POINTER_MOTION_ABSOLUTE,
|
||||
EI_EVENT_POINTER_BUTTON,
|
||||
EI_EVENT_POINTER_SCROLL,
|
||||
EI_EVENT_POINTER_SCROLL_DISCRETE);
|
||||
return event->pointer.sy;
|
||||
}
|
||||
|
||||
_public_ int32_t
|
||||
ei_event_pointer_get_scroll_discrete_x(struct ei_event *event)
|
||||
{
|
||||
require_event_type(event, 0,
|
||||
EI_EVENT_POINTER_MOTION,
|
||||
EI_EVENT_POINTER_MOTION_ABSOLUTE,
|
||||
EI_EVENT_POINTER_BUTTON,
|
||||
EI_EVENT_POINTER_SCROLL,
|
||||
EI_EVENT_POINTER_SCROLL_DISCRETE);
|
||||
return event->pointer.sdx;
|
||||
}
|
||||
|
||||
_public_ int32_t
|
||||
ei_event_pointer_get_scroll_discrete_y(struct ei_event *event)
|
||||
{
|
||||
require_event_type(event, 0,
|
||||
EI_EVENT_POINTER_MOTION,
|
||||
EI_EVENT_POINTER_MOTION_ABSOLUTE,
|
||||
EI_EVENT_POINTER_BUTTON,
|
||||
EI_EVENT_POINTER_SCROLL,
|
||||
EI_EVENT_POINTER_SCROLL_DISCRETE);
|
||||
return event->pointer.sdy;
|
||||
}
|
||||
|
||||
_public_ bool
|
||||
ei_event_pointer_get_scroll_stop_x(struct ei_event *event)
|
||||
{
|
||||
require_event_type(event, 0,
|
||||
EI_EVENT_POINTER_SCROLL_STOP,
|
||||
EI_EVENT_POINTER_SCROLL_CANCEL);
|
||||
return event->pointer.stop_x;
|
||||
}
|
||||
|
||||
_public_ bool
|
||||
ei_event_pointer_get_scroll_stop_y(struct ei_event *event)
|
||||
{
|
||||
require_event_type(event, 0,
|
||||
EI_EVENT_POINTER_SCROLL_STOP,
|
||||
EI_EVENT_POINTER_SCROLL_CANCEL);
|
||||
return event->pointer.stop_y;
|
||||
}
|
||||
|
||||
_public_ uint32_t
|
||||
ei_event_keyboard_get_key(struct ei_event *event)
|
||||
{
|
||||
require_event_type(event, 0,
|
||||
EI_EVENT_KEYBOARD_KEY);
|
||||
|
||||
return event->keyboard.key;
|
||||
}
|
||||
|
||||
_public_ bool
|
||||
ei_event_keyboard_get_key_is_press(struct ei_event *event)
|
||||
{
|
||||
require_event_type(event, false,
|
||||
EI_EVENT_KEYBOARD_KEY);
|
||||
|
||||
return event->keyboard.key_is_press;
|
||||
}
|
||||
|
||||
_public_ uint32_t
|
||||
ei_event_touch_get_id(struct ei_event *event)
|
||||
{
|
||||
require_event_type(event, 0,
|
||||
EI_EVENT_TOUCH_DOWN,
|
||||
EI_EVENT_TOUCH_UP,
|
||||
EI_EVENT_TOUCH_MOTION);
|
||||
|
||||
return event->touch.touchid;
|
||||
}
|
||||
|
||||
_public_ double
|
||||
ei_event_touch_get_x(struct ei_event *event)
|
||||
{
|
||||
require_event_type(event, 0.0,
|
||||
EI_EVENT_TOUCH_DOWN,
|
||||
EI_EVENT_TOUCH_MOTION);
|
||||
|
||||
return event->touch.x;
|
||||
}
|
||||
|
||||
_public_ double
|
||||
ei_event_touch_get_y(struct ei_event *event)
|
||||
{
|
||||
require_event_type(event, 0.0,
|
||||
EI_EVENT_TOUCH_DOWN,
|
||||
EI_EVENT_TOUCH_MOTION);
|
||||
|
||||
return event->touch.y;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,6 +67,8 @@ struct ei {
|
|||
} log;
|
||||
|
||||
const struct ei_proto_requests *requests;
|
||||
|
||||
bool is_active;
|
||||
};
|
||||
|
||||
enum ei_seat_state {
|
||||
|
|
@ -183,6 +185,23 @@ struct ei_event {
|
|||
char *value;
|
||||
uint32_t permissions;
|
||||
} prop;
|
||||
struct {
|
||||
double dx, dy; /* relative motion */
|
||||
double absx, absy; /* absolute motion */
|
||||
double sx, sy; /* scroll */
|
||||
int32_t sdx, sdy; /* discrete scroll */
|
||||
bool stop_x, stop_y; /* scroll stop */
|
||||
uint32_t button;
|
||||
bool button_is_press;
|
||||
} pointer;
|
||||
struct {
|
||||
uint32_t key;
|
||||
bool key_is_press;
|
||||
} keyboard;
|
||||
struct {
|
||||
uint32_t touchid;
|
||||
double x, y;
|
||||
} touch;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -265,6 +284,50 @@ ei_insert_device_removed_event(struct ei_device *device);
|
|||
void
|
||||
ei_queue_seat_removed_event(struct ei_seat *seat);
|
||||
|
||||
void
|
||||
ei_queue_device_start_emulating_event(struct ei_device *device);
|
||||
|
||||
void
|
||||
ei_queue_device_stop_emulating_event(struct ei_device *device);
|
||||
|
||||
void
|
||||
ei_queue_frame_event(struct ei_device *device);
|
||||
|
||||
void
|
||||
ei_queue_pointer_rel_event(struct ei_device *device, double x, double y);
|
||||
|
||||
void
|
||||
ei_queue_pointer_abs_event(struct ei_device *device, double x, double y);
|
||||
|
||||
void
|
||||
ei_queue_pointer_button_event(struct ei_device *device, uint32_t button, bool is_press);
|
||||
|
||||
void
|
||||
ei_queue_keyboard_key_event(struct ei_device *device, uint32_t key, bool is_press);
|
||||
|
||||
void
|
||||
ei_queue_pointer_scroll_event(struct ei_device *device, double x, double y);
|
||||
|
||||
void
|
||||
ei_queue_pointer_scroll_discrete_event(struct ei_device *device, int32_t x, int32_t y);
|
||||
|
||||
void
|
||||
ei_queue_pointer_scroll_stop_event(struct ei_device *device, bool x, bool y);
|
||||
|
||||
void
|
||||
ei_queue_pointer_scroll_cancel_event(struct ei_device *device, bool x, bool y);
|
||||
|
||||
void
|
||||
ei_queue_touch_down_event(struct ei_device *device, uint32_t touchid,
|
||||
double x, double y);
|
||||
|
||||
void
|
||||
ei_queue_touch_motion_event(struct ei_device *device, uint32_t touchid,
|
||||
double x, double y);
|
||||
|
||||
void
|
||||
ei_queue_touch_up_event(struct ei_device *device, uint32_t touchid);
|
||||
|
||||
struct ei_device *
|
||||
ei_device_new(struct ei_seat *seat, uint32_t deviceid);
|
||||
|
||||
|
|
@ -277,6 +340,53 @@ ei_device_done(struct ei_device *device);
|
|||
void
|
||||
ei_device_removed_by_server(struct ei_device *device);
|
||||
|
||||
int
|
||||
ei_device_event_frame(struct ei_device *device);
|
||||
|
||||
void
|
||||
ei_device_event_start_emulating(struct ei_device *device);
|
||||
|
||||
void
|
||||
ei_device_event_stop_emulating(struct ei_device *device);
|
||||
|
||||
int
|
||||
ei_device_event_pointer_rel(struct ei_device *device,
|
||||
double x, double y);
|
||||
|
||||
int
|
||||
ei_device_event_pointer_abs(struct ei_device *device,
|
||||
double x, double y);
|
||||
|
||||
int
|
||||
ei_device_event_pointer_button(struct ei_device *device,
|
||||
uint32_t button, bool is_press);
|
||||
|
||||
int
|
||||
ei_device_event_pointer_scroll(struct ei_device *device,
|
||||
double x, double y);
|
||||
int
|
||||
ei_device_event_pointer_scroll_stop(struct ei_device *device, bool x, bool y);
|
||||
|
||||
int
|
||||
ei_device_event_pointer_scroll_cancel(struct ei_device *device, bool x, bool y);
|
||||
|
||||
int
|
||||
ei_device_event_pointer_scroll_discrete(struct ei_device *device,
|
||||
int32_t x, int32_t y);
|
||||
|
||||
int
|
||||
ei_device_event_keyboard_key(struct ei_device *device,
|
||||
uint32_t key, bool is_press);
|
||||
|
||||
int
|
||||
ei_device_event_touch_down(struct ei_device *device, uint32_t tid,
|
||||
double x, double y);
|
||||
int
|
||||
ei_device_event_touch_motion(struct ei_device *device, uint32_t tid,
|
||||
double x, double y);
|
||||
int
|
||||
ei_device_event_touch_up(struct ei_device *device, uint32_t tid);
|
||||
|
||||
int
|
||||
ei_send_pointer_rel(struct ei_device *device,
|
||||
double x, double y);
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ ei_proto_handle_message(struct ei *ei,
|
|||
rc = call(connected, ei);
|
||||
break;
|
||||
case SERVER_MESSAGE__MSG_DISCONNECTED:
|
||||
rc = call(disconnected, ei);
|
||||
rc = call(disconnected, ei, proto->disconnected->is_active);
|
||||
break;
|
||||
case SERVER_MESSAGE__MSG_SEAT_ADDED:
|
||||
rc = call(seat_added, ei,
|
||||
|
|
@ -132,6 +132,80 @@ ei_proto_handle_message(struct ei *ei,
|
|||
proto->property->value[0] ? proto->property->value : NULL,
|
||||
proto->property->permissions);
|
||||
break;
|
||||
/* Events */
|
||||
case SERVER_MESSAGE__MSG_START_EMULATING:
|
||||
rc = call(start_emulating, ei,
|
||||
proto->start_emulating->deviceid);
|
||||
break;
|
||||
case SERVER_MESSAGE__MSG_STOP_EMULATING:
|
||||
rc = call(stop_emulating, ei,
|
||||
proto->stop_emulating->deviceid);
|
||||
break;
|
||||
case SERVER_MESSAGE__MSG_POINTER_RELATIVE:
|
||||
rc = call(rel, ei,
|
||||
proto->pointer_relative->deviceid,
|
||||
proto->pointer_relative->x,
|
||||
proto->pointer_relative->y);
|
||||
break;
|
||||
case SERVER_MESSAGE__MSG_POINTER_ABSOLUTE:
|
||||
rc = call(abs, ei,
|
||||
proto->pointer_absolute->deviceid,
|
||||
proto->pointer_absolute->x,
|
||||
proto->pointer_absolute->y);
|
||||
break;
|
||||
case SERVER_MESSAGE__MSG_POINTER_BUTTON:
|
||||
rc = call(button, ei,
|
||||
proto->pointer_button->deviceid,
|
||||
proto->pointer_button->button,
|
||||
proto->pointer_button->state);
|
||||
break;
|
||||
case SERVER_MESSAGE__MSG_POINTER_SCROLL:
|
||||
rc = call(scroll, ei,
|
||||
proto->pointer_scroll->deviceid,
|
||||
proto->pointer_scroll->x,
|
||||
proto->pointer_scroll->y);
|
||||
break;
|
||||
case SERVER_MESSAGE__MSG_POINTER_SCROLL_STOP:
|
||||
rc = call(scroll_stop, ei,
|
||||
proto->pointer_scroll_stop->deviceid,
|
||||
proto->pointer_scroll_stop->x,
|
||||
proto->pointer_scroll_stop->y,
|
||||
proto->pointer_scroll_stop->is_cancel);
|
||||
break;
|
||||
case SERVER_MESSAGE__MSG_POINTER_SCROLL_DISCRETE:
|
||||
rc = call(scroll_discrete, ei,
|
||||
proto->pointer_scroll_discrete->deviceid,
|
||||
proto->pointer_scroll_discrete->x,
|
||||
proto->pointer_scroll_discrete->y);
|
||||
break;
|
||||
case SERVER_MESSAGE__MSG_KEYBOARD_KEY:
|
||||
rc = call(key, ei,
|
||||
proto->keyboard_key->deviceid,
|
||||
proto->keyboard_key->key,
|
||||
proto->keyboard_key->state);
|
||||
break;
|
||||
case SERVER_MESSAGE__MSG_TOUCH_DOWN:
|
||||
rc = call(touch_down, ei,
|
||||
proto->touch_down->deviceid,
|
||||
proto->touch_down->touchid,
|
||||
proto->touch_down->x,
|
||||
proto->touch_down->y);
|
||||
break;
|
||||
case SERVER_MESSAGE__MSG_TOUCH_MOTION:
|
||||
rc = call(touch_motion, ei,
|
||||
proto->touch_motion->deviceid,
|
||||
proto->touch_motion->touchid,
|
||||
proto->touch_motion->x,
|
||||
proto->touch_motion->y);
|
||||
break;
|
||||
case SERVER_MESSAGE__MSG_TOUCH_UP:
|
||||
rc = call(touch_up, ei,
|
||||
proto->touch_up->deviceid,
|
||||
proto->touch_up->touchid);
|
||||
break;
|
||||
case SERVER_MESSAGE__MSG_FRAME:
|
||||
rc = call(frame, ei, proto->frame->deviceid);
|
||||
break;
|
||||
default:
|
||||
rc = -EBADMSG;
|
||||
break;
|
||||
|
|
@ -240,6 +314,7 @@ ei_proto_send_connect(struct ei *ei)
|
|||
prepare_msg(CONNECT, Connect, connect);
|
||||
|
||||
connect.name = ei->name;
|
||||
connect.is_active = ei->is_active;
|
||||
|
||||
return ei_proto_send_msg(ei, &msg);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@
|
|||
/* callbacks invoked during ei_proto_parse_message() */
|
||||
struct ei_proto_interface {
|
||||
int (*connected)(struct ei *ei);
|
||||
int (*disconnected)(struct ei *ei);
|
||||
int (*disconnected)(struct ei *ei, bool is_active);
|
||||
int (*seat_added)(struct ei *ei, uint32_t seatid,
|
||||
const char *name, uint32_t capabilities);
|
||||
int (*seat_removed)(struct ei *ei, uint32_t seatid);
|
||||
|
|
@ -58,6 +58,23 @@ struct ei_proto_interface {
|
|||
int (*property)(struct ei *ei,
|
||||
const char *name, const char *value,
|
||||
uint32_t permissions);
|
||||
|
||||
/* events */
|
||||
int (*start_emulating)(struct ei *ei, uint32_t deviceid);
|
||||
int (*stop_emulating)(struct ei *ei, uint32_t deviceid);
|
||||
int (*rel)(struct ei *ei, uint32_t deviceid, double x, double y);
|
||||
int (*abs)(struct ei *ei, uint32_t deviceid, double x, double y);
|
||||
int (*button)(struct ei *ei, uint32_t deviceid, uint32_t button, bool is_press);
|
||||
int (*key)(struct ei *ei, uint32_t deviceid, uint32_t key, bool is_press);
|
||||
int (*scroll)(struct ei *ei, uint32_t deviceid, double x, double y);
|
||||
int (*scroll_stop)(struct ei *ei, uint32_t deviceid, bool x, bool y, bool is_cancel);
|
||||
int (*scroll_discrete)(struct ei *ei, uint32_t deviceid, int32_t x, int32_t y);
|
||||
int (*touch_down)(struct ei *ei, uint32_t deviceid,
|
||||
uint32_t tid, double x, double y);
|
||||
int (*touch_motion)(struct ei *ei, uint32_t deviceid,
|
||||
uint32_t tid, double x, double y);
|
||||
int (*touch_up)(struct ei *ei, uint32_t deviceid, uint32_t tid);
|
||||
int (*frame) (struct ei *ei, uint32_t deviceid);
|
||||
};
|
||||
|
||||
struct ei_proto_requests {
|
||||
|
|
|
|||
405
src/libei.c
405
src/libei.c
|
|
@ -132,8 +132,8 @@ set_prop_type(struct ei *ei)
|
|||
ei_property_update(ei, "ei.connection.type", "socket", EI_PROPERTY_PERM_NONE);
|
||||
}
|
||||
|
||||
_public_ struct ei *
|
||||
ei_new(void *user_data)
|
||||
static struct ei *
|
||||
ei_create_context(bool is_active, void *user_data)
|
||||
{
|
||||
_unref_(ei) *ei = ei_create(NULL);
|
||||
|
||||
|
|
@ -151,6 +151,7 @@ ei_new(void *user_data)
|
|||
|
||||
ei->user_data = user_data;
|
||||
ei->backend = NULL;
|
||||
ei->is_active = is_active;
|
||||
|
||||
set_prop_pid(ei);
|
||||
set_prop_cmdline(ei);
|
||||
|
|
@ -159,6 +160,24 @@ ei_new(void *user_data)
|
|||
return steal(&ei);
|
||||
}
|
||||
|
||||
_public_ struct ei *
|
||||
ei_new(void *user_data)
|
||||
{
|
||||
return ei_new_active(user_data);
|
||||
}
|
||||
|
||||
_public_ struct ei *
|
||||
ei_new_active(void *user_data)
|
||||
{
|
||||
return ei_create_context(true, user_data);
|
||||
}
|
||||
|
||||
_public_ struct ei *
|
||||
ei_new_passive(void *user_data)
|
||||
{
|
||||
return ei_create_context(false, user_data);
|
||||
}
|
||||
|
||||
_public_ int
|
||||
ei_get_fd(struct ei *ei)
|
||||
{
|
||||
|
|
@ -319,6 +338,177 @@ queue_property_event(struct ei *ei, const char *name,
|
|||
queue_event(ei, e);
|
||||
}
|
||||
|
||||
void
|
||||
ei_queue_frame_event(struct ei_device *device)
|
||||
{
|
||||
struct ei_event *e = ei_event_new_for_device(device);
|
||||
|
||||
e->type = EI_EVENT_FRAME;
|
||||
|
||||
queue_event(ei_device_get_context(device), e);
|
||||
}
|
||||
|
||||
void
|
||||
ei_queue_device_start_emulating_event(struct ei_device *device)
|
||||
{
|
||||
struct ei_event *e = ei_event_new_for_device(device);
|
||||
|
||||
e->type = EI_EVENT_DEVICE_START_EMULATING;
|
||||
|
||||
queue_event(ei_device_get_context(device), e);
|
||||
}
|
||||
|
||||
void
|
||||
ei_queue_device_stop_emulating_event(struct ei_device *device)
|
||||
{
|
||||
struct ei_event *e = ei_event_new_for_device(device);
|
||||
|
||||
e->type = EI_EVENT_DEVICE_STOP_EMULATING;
|
||||
|
||||
queue_event(ei_device_get_context(device), e);
|
||||
}
|
||||
|
||||
void
|
||||
ei_queue_pointer_rel_event(struct ei_device *device,
|
||||
double dx, double dy)
|
||||
{
|
||||
struct ei_event *e = ei_event_new_for_device(device);
|
||||
|
||||
e->type = EI_EVENT_POINTER_MOTION;
|
||||
e->pointer.dx = dx;
|
||||
e->pointer.dy = dy;
|
||||
|
||||
queue_event(ei_device_get_context(device), e);
|
||||
}
|
||||
|
||||
void
|
||||
ei_queue_pointer_abs_event(struct ei_device *device,
|
||||
double x, double y)
|
||||
{
|
||||
struct ei_event *e = ei_event_new_for_device(device);
|
||||
|
||||
e->type = EI_EVENT_POINTER_MOTION_ABSOLUTE;
|
||||
e->pointer.absx = x;
|
||||
e->pointer.absy = y;
|
||||
|
||||
queue_event(ei_device_get_context(device), e);
|
||||
}
|
||||
|
||||
void
|
||||
ei_queue_pointer_button_event(struct ei_device *device, uint32_t button,
|
||||
bool is_press)
|
||||
{
|
||||
struct ei_event *e = ei_event_new_for_device(device);
|
||||
|
||||
e->type = EI_EVENT_POINTER_BUTTON;
|
||||
e->pointer.button = button;
|
||||
e->pointer.button_is_press = is_press;
|
||||
|
||||
queue_event(ei_device_get_context(device), e);
|
||||
}
|
||||
|
||||
void
|
||||
ei_queue_pointer_scroll_event(struct ei_device *device,
|
||||
double x, double y)
|
||||
{
|
||||
struct ei_event *e = ei_event_new_for_device(device);
|
||||
|
||||
e->type = EI_EVENT_POINTER_SCROLL;
|
||||
e->pointer.sx = x;
|
||||
e->pointer.sy = y;
|
||||
|
||||
queue_event(ei_device_get_context(device), e);
|
||||
}
|
||||
|
||||
void
|
||||
ei_queue_pointer_scroll_discrete_event(struct ei_device *device,
|
||||
int32_t x, int32_t y)
|
||||
{
|
||||
struct ei_event *e = ei_event_new_for_device(device);
|
||||
|
||||
e->type = EI_EVENT_POINTER_SCROLL_DISCRETE;
|
||||
e->pointer.sdx = x;
|
||||
e->pointer.sdy = y;
|
||||
|
||||
queue_event(ei_device_get_context(device), e);
|
||||
}
|
||||
|
||||
void
|
||||
ei_queue_pointer_scroll_stop_event(struct ei_device *device, bool x, bool y)
|
||||
{
|
||||
struct ei_event *e = ei_event_new_for_device(device);
|
||||
|
||||
e->type = EI_EVENT_POINTER_SCROLL_STOP;
|
||||
e->pointer.stop_x = x;
|
||||
e->pointer.stop_y = y;
|
||||
|
||||
queue_event(ei_device_get_context(device), e);
|
||||
}
|
||||
|
||||
void
|
||||
ei_queue_pointer_scroll_cancel_event(struct ei_device *device, bool x, bool y)
|
||||
{
|
||||
struct ei_event *e = ei_event_new_for_device(device);
|
||||
|
||||
e->type = EI_EVENT_POINTER_SCROLL_CANCEL;
|
||||
e->pointer.stop_x = x;
|
||||
e->pointer.stop_y = y;
|
||||
|
||||
queue_event(ei_device_get_context(device), e);
|
||||
}
|
||||
|
||||
void
|
||||
ei_queue_keyboard_key_event(struct ei_device *device, uint32_t key,
|
||||
bool is_press)
|
||||
{
|
||||
struct ei_event *e = ei_event_new_for_device(device);
|
||||
|
||||
e->type = EI_EVENT_KEYBOARD_KEY;
|
||||
e->keyboard.key = key;
|
||||
e->keyboard.key_is_press = is_press;
|
||||
|
||||
queue_event(ei_device_get_context(device), e);
|
||||
}
|
||||
|
||||
void
|
||||
ei_queue_touch_down_event(struct ei_device *device, uint32_t touchid,
|
||||
double x, double y)
|
||||
{
|
||||
struct ei_event *e = ei_event_new_for_device(device);
|
||||
|
||||
e->type = EI_EVENT_TOUCH_DOWN;
|
||||
e->touch.touchid = touchid,
|
||||
e->touch.x = x;
|
||||
e->touch.y = y;
|
||||
|
||||
queue_event(ei_device_get_context(device), e);
|
||||
}
|
||||
|
||||
void
|
||||
ei_queue_touch_motion_event(struct ei_device *device, uint32_t touchid,
|
||||
double x, double y)
|
||||
{
|
||||
struct ei_event *e = ei_event_new_for_device(device);
|
||||
|
||||
e->type = EI_EVENT_TOUCH_MOTION;
|
||||
e->touch.touchid = touchid,
|
||||
e->touch.x = x;
|
||||
e->touch.y = y;
|
||||
|
||||
queue_event(ei_device_get_context(device), e);
|
||||
}
|
||||
|
||||
void
|
||||
ei_queue_touch_up_event(struct ei_device *device, uint32_t touchid)
|
||||
{
|
||||
struct ei_event *e = ei_event_new_for_device(device);
|
||||
|
||||
e->type = EI_EVENT_TOUCH_UP;
|
||||
e->touch.touchid = touchid,
|
||||
|
||||
queue_event(ei_device_get_context(device), e);
|
||||
}
|
||||
|
||||
void
|
||||
ei_disconnect(struct ei *ei)
|
||||
{
|
||||
|
|
@ -838,10 +1028,204 @@ static int handle_msg_connected(struct ei *ei) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int handle_msg_disconnected(struct ei *ei) {
|
||||
static int handle_msg_disconnected(struct ei *ei, bool is_active) {
|
||||
if (ei->is_active == is_active) {
|
||||
log_bug_client(ei, "Unable to connect %s ei context to %s EIS implementation\n",
|
||||
is_active ? "active" : "passive",
|
||||
is_active ? "active" : "passive");
|
||||
}
|
||||
return -ECANCELED;
|
||||
}
|
||||
|
||||
#define DISCONNECT_IF_ACTIVE_CONTEXT(ei_) do {\
|
||||
if (ei_->is_active) { \
|
||||
log_bug_client(ei_, "Invalid event from passive EIS context. Disconnecting\n"); \
|
||||
return -ECANCELED; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
static int
|
||||
handle_msg_start_emulating(struct ei *ei, uint32_t deviceid)
|
||||
{
|
||||
DISCONNECT_IF_ACTIVE_CONTEXT(ei);
|
||||
|
||||
struct ei_device *device = ei_find_device(ei, deviceid);
|
||||
|
||||
if (device)
|
||||
ei_device_event_start_emulating(device);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
handle_msg_stop_emulating(struct ei *ei, uint32_t deviceid)
|
||||
{
|
||||
DISCONNECT_IF_ACTIVE_CONTEXT(ei);
|
||||
|
||||
struct ei_device *device = ei_find_device(ei, deviceid);
|
||||
|
||||
if (device)
|
||||
ei_device_event_stop_emulating(device);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
handle_msg_frame(struct ei *ei, uint32_t deviceid)
|
||||
{
|
||||
DISCONNECT_IF_ACTIVE_CONTEXT(ei);
|
||||
|
||||
struct ei_device *device = ei_find_device(ei, deviceid);
|
||||
|
||||
if (device)
|
||||
return ei_device_event_frame(device);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
handle_msg_pointer_rel(struct ei *ei, uint32_t deviceid,
|
||||
double x, double y)
|
||||
{
|
||||
DISCONNECT_IF_ACTIVE_CONTEXT(ei);
|
||||
|
||||
struct ei_device *device = ei_find_device(ei, deviceid);
|
||||
|
||||
if (device)
|
||||
return ei_device_event_pointer_rel(device, x, y);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int
|
||||
handle_msg_pointer_abs(struct ei *ei, uint32_t deviceid,
|
||||
double x, double y)
|
||||
{
|
||||
DISCONNECT_IF_ACTIVE_CONTEXT(ei);
|
||||
|
||||
struct ei_device *device = ei_find_device(ei, deviceid);
|
||||
|
||||
if (device)
|
||||
return ei_device_event_pointer_abs(device, x, y);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int
|
||||
handle_msg_pointer_button(struct ei *ei, uint32_t deviceid,
|
||||
uint32_t button, bool state)
|
||||
{
|
||||
DISCONNECT_IF_ACTIVE_CONTEXT(ei);
|
||||
|
||||
struct ei_device *device = ei_find_device(ei, deviceid);
|
||||
|
||||
if (device)
|
||||
return ei_device_event_pointer_button(device, button, state);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int
|
||||
handle_msg_pointer_scroll(struct ei *ei, uint32_t deviceid,
|
||||
double x, double y)
|
||||
{
|
||||
DISCONNECT_IF_ACTIVE_CONTEXT(ei);
|
||||
|
||||
struct ei_device *device = ei_find_device(ei, deviceid);
|
||||
|
||||
if (device)
|
||||
return ei_device_event_pointer_scroll(device, x, y);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int
|
||||
handle_msg_pointer_scroll_discrete(struct ei *ei, uint32_t deviceid,
|
||||
int32_t x, int32_t y)
|
||||
{
|
||||
DISCONNECT_IF_ACTIVE_CONTEXT(ei);
|
||||
|
||||
struct ei_device *device = ei_find_device(ei, deviceid);
|
||||
|
||||
if (device)
|
||||
return ei_device_event_pointer_scroll_discrete(device, x, y);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int
|
||||
handle_msg_pointer_scroll_stop(struct ei *ei, uint32_t deviceid,
|
||||
bool x, bool y, bool is_cancel)
|
||||
{
|
||||
DISCONNECT_IF_ACTIVE_CONTEXT(ei);
|
||||
|
||||
struct ei_device *device = ei_find_device(ei, deviceid);
|
||||
|
||||
if (device) {
|
||||
if (is_cancel)
|
||||
return ei_device_event_pointer_scroll_cancel(device, x, y);
|
||||
else
|
||||
return ei_device_event_pointer_scroll_stop(device, x, y);
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int
|
||||
handle_msg_keyboard_key(struct ei *ei, uint32_t deviceid,
|
||||
uint32_t key, bool state)
|
||||
{
|
||||
DISCONNECT_IF_ACTIVE_CONTEXT(ei);
|
||||
|
||||
struct ei_device *device = ei_find_device(ei, deviceid);
|
||||
|
||||
if (device)
|
||||
return ei_device_event_keyboard_key(device, key, state);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int
|
||||
handle_msg_touch_down(struct ei *ei, uint32_t deviceid,
|
||||
uint32_t touchid, double x, double y)
|
||||
{
|
||||
DISCONNECT_IF_ACTIVE_CONTEXT(ei);
|
||||
|
||||
struct ei_device *device = ei_find_device(ei, deviceid);
|
||||
|
||||
if (device)
|
||||
return ei_device_event_touch_down(device, touchid, x, y);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int
|
||||
handle_msg_touch_motion(struct ei *ei, uint32_t deviceid,
|
||||
uint32_t touchid, double x, double y)
|
||||
{
|
||||
DISCONNECT_IF_ACTIVE_CONTEXT(ei);
|
||||
|
||||
struct ei_device *device = ei_find_device(ei, deviceid);
|
||||
|
||||
if (device)
|
||||
return ei_device_event_touch_motion(device, touchid, x, y);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int
|
||||
handle_msg_touch_up(struct ei *ei, uint32_t deviceid, uint32_t touchid)
|
||||
{
|
||||
DISCONNECT_IF_ACTIVE_CONTEXT(ei);
|
||||
|
||||
struct ei_device *device = ei_find_device(ei, deviceid);
|
||||
|
||||
if (device)
|
||||
return ei_device_event_touch_up(device, touchid);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static const struct ei_proto_interface intf_state_backend = {
|
||||
/* Everything triggers -EPROTO */
|
||||
.connected = NULL,
|
||||
|
|
@ -865,6 +1249,21 @@ static const struct ei_proto_interface intf_state_connected = {
|
|||
.device_done = handle_msg_device_added_done,
|
||||
.keyboard_modifiers = handle_msg_keyboard_modifiers,
|
||||
.property = handle_msg_property,
|
||||
|
||||
/* events */
|
||||
.start_emulating = handle_msg_start_emulating,
|
||||
.stop_emulating = handle_msg_stop_emulating,
|
||||
.rel = handle_msg_pointer_rel,
|
||||
.abs = handle_msg_pointer_abs,
|
||||
.button = handle_msg_pointer_button,
|
||||
.scroll = handle_msg_pointer_scroll,
|
||||
.scroll_stop = handle_msg_pointer_scroll_stop,
|
||||
.scroll_discrete = handle_msg_pointer_scroll_discrete,
|
||||
.key = handle_msg_keyboard_key,
|
||||
.touch_down = handle_msg_touch_down,
|
||||
.touch_motion = handle_msg_touch_motion,
|
||||
.touch_up = handle_msg_touch_up,
|
||||
.frame = handle_msg_frame,
|
||||
};
|
||||
|
||||
static const struct ei_proto_interface *interfaces[] = {
|
||||
|
|
|
|||
213
src/libei.h
213
src/libei.h
|
|
@ -38,6 +38,12 @@ extern "C" {
|
|||
* libei is the client-side module. This API should be used by processes
|
||||
* that need to emulate devices.
|
||||
*
|
||||
* libei clients come in "active" and "passive" modes, depending on whether
|
||||
* the client sends or receives events. A libeis context however is both
|
||||
* active and passive at the same time, it is up to the implementation to
|
||||
* disconnect clients that it does not want to allow. See
|
||||
* eis_client_is_active() for details.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
|
@ -278,11 +284,65 @@ enum ei_event_type {
|
|||
* This event may arrive while a device is paused.
|
||||
*/
|
||||
EI_EVENT_KEYBOARD_MODIFIERS,
|
||||
|
||||
/**
|
||||
* "Hardware" frame event. This event **must** be sent by the server
|
||||
* and notifies the client that the previous set of events belong to
|
||||
* the same logical hardware event.
|
||||
*
|
||||
* These events are only generated on a passive ei context.
|
||||
*
|
||||
* This event is most commonly used to implement multitouch (multiple
|
||||
* touches may update within the same hardware scanout cycle).
|
||||
*/
|
||||
EI_EVENT_FRAME = 100,
|
||||
|
||||
/**
|
||||
* The server is about to send events for a device. This event should
|
||||
* be used by the client to clear the logical state of the emulated
|
||||
* devices and/or provide UI to the user.
|
||||
*
|
||||
* These events are only generated on a passive ei context.
|
||||
*
|
||||
* Note that a server start multiple emulating sequences
|
||||
* simultaneously, depending on the devices available.
|
||||
* For example, in a synergy-like situation, the server
|
||||
* may start sending pointer and keyboard once the remote device
|
||||
* logically entered the screen.
|
||||
*/
|
||||
EI_EVENT_DEVICE_START_EMULATING = 200,
|
||||
EI_EVENT_DEVICE_STOP_EMULATING,
|
||||
|
||||
/* These events are only generated on a passive ei context. */
|
||||
EI_EVENT_POINTER_MOTION = 300,
|
||||
EI_EVENT_POINTER_MOTION_ABSOLUTE,
|
||||
EI_EVENT_POINTER_BUTTON,
|
||||
EI_EVENT_POINTER_SCROLL,
|
||||
EI_EVENT_POINTER_SCROLL_STOP,
|
||||
EI_EVENT_POINTER_SCROLL_CANCEL,
|
||||
EI_EVENT_POINTER_SCROLL_DISCRETE,
|
||||
|
||||
EI_EVENT_KEYBOARD_KEY = 400,
|
||||
|
||||
EI_EVENT_TOUCH_DOWN = 500,
|
||||
EI_EVENT_TOUCH_UP,
|
||||
EI_EVENT_TOUCH_MOTION,
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new ei context. The context is refcounted and must be released
|
||||
* with ei_unref().
|
||||
* This is an alias for @ref ei_new_active.
|
||||
*/
|
||||
struct ei *
|
||||
ei_new(void *user_data);
|
||||
|
||||
/**
|
||||
* Create a new active ei context. The context is refcounted and must be
|
||||
* released with ei_unref().
|
||||
*
|
||||
* An active ei context sends events to the EIS implementation but cannot
|
||||
* receive events. An active ei context can only connect to a passive EIS
|
||||
* implementation, connecting to an active EIS implementation will immediately
|
||||
* disconnect the client.
|
||||
*
|
||||
* A context supports exactly one backend, set up with one of
|
||||
* ei_setup_backend_socket() or ei_setup_backend_fd().
|
||||
|
|
@ -295,7 +355,29 @@ enum ei_event_type {
|
|||
* @see ei_setup_backend_socket
|
||||
*/
|
||||
struct ei *
|
||||
ei_new(void *user_data);
|
||||
ei_new_active(void *user_data);
|
||||
|
||||
/**
|
||||
* Create a new passive ei context. The context is refcounted and must be
|
||||
* released with ei_unref().
|
||||
*
|
||||
* A passive ei context receives events from the EIS implementation but cannot
|
||||
* send events. A passive ei context can only connect to an active EIS
|
||||
* implementation, connecting to a passive EIS implementation will immediately
|
||||
* disconnect the client.
|
||||
*
|
||||
* A context supports exactly one backend, set up with one of
|
||||
* ei_setup_backend_socket() or ei_setup_backend_fd().
|
||||
*
|
||||
* @param user_data An opaque pointer to be returned with ei_get_user_data()
|
||||
*
|
||||
* @see ei_set_user_data
|
||||
* @see ei_get_user_data
|
||||
* @see ei_setup_backend_fd
|
||||
* @see ei_setup_backend_socket
|
||||
*/
|
||||
struct ei *
|
||||
ei_new_passive(void *user_data);
|
||||
|
||||
enum ei_log_priority {
|
||||
EI_LOG_PRIORITY_DEBUG = 10,
|
||||
|
|
@ -1298,6 +1380,131 @@ ei_event_property_get_value(struct ei_event *event);
|
|||
uint32_t
|
||||
ei_event_property_get_permissions(struct ei_event *event);
|
||||
|
||||
/**
|
||||
* For an event of type @ref EI_EVENT_POINTER_MOTION return the relative x
|
||||
* movement in logical pixels.
|
||||
*/
|
||||
double
|
||||
ei_event_pointer_get_dx(struct ei_event *event);
|
||||
|
||||
/**
|
||||
* For an event of type @ref EI_EVENT_POINTER_MOTION return the relative y
|
||||
uint32_* movement in logical pixels.
|
||||
*/
|
||||
double
|
||||
ei_event_pointer_get_dy(struct ei_event *event);
|
||||
|
||||
/**
|
||||
* For an event of type @ref EI_EVENT_POINTER_MOTION_ABSOLUTE return the x
|
||||
* position in logical pixels.
|
||||
*/
|
||||
double
|
||||
ei_event_pointer_get_absolute_x(struct ei_event *event);
|
||||
|
||||
/**
|
||||
* For an event of type @ref EI_EVENT_POINTER_MOTION_ABSOLUTE return the y
|
||||
* position in logical pixels.
|
||||
*/
|
||||
double
|
||||
ei_event_pointer_get_absolute_y(struct ei_event *event);
|
||||
|
||||
/**
|
||||
* For an event of type @ref EI_EVENT_POINTER_BUTTON return the button
|
||||
* code as defined in linux/input-event-codes.h
|
||||
*/
|
||||
uint32_t
|
||||
ei_event_pointer_get_button(struct ei_event *event);
|
||||
|
||||
/**
|
||||
* For an event of type @ref EI_EVENT_POINTER_BUTTON return true if the
|
||||
* event is a button press, false for a release.
|
||||
*/
|
||||
bool
|
||||
ei_event_pointer_get_button_is_press(struct ei_event *event);
|
||||
|
||||
/**
|
||||
* For an event of type @ref EI_EVENT_POINTER_SCROLL return the x scroll
|
||||
* distance in logical pixels.
|
||||
*/
|
||||
double
|
||||
ei_event_pointer_get_scroll_x(struct ei_event *event);
|
||||
|
||||
/**
|
||||
* For an event of type @ref EI_EVENT_POINTER_SCROLL return the y scroll
|
||||
* distance in logical pixels.
|
||||
*/
|
||||
double
|
||||
ei_event_pointer_get_scroll_y(struct ei_event *event);
|
||||
|
||||
/**
|
||||
* For an event of type @ref EI_EVENT_POINTER_SCROLL_CANCEL return whether the
|
||||
* x axis has cancelled scrolling.
|
||||
*/
|
||||
bool
|
||||
ei_event_pointer_get_scroll_stop_x(struct ei_event *event);
|
||||
|
||||
/**
|
||||
* For an event of type @ref EI_EVENT_POINTER_SCROLL_STOP return whether the
|
||||
* y axis has stopped scrolling.
|
||||
*/
|
||||
bool
|
||||
ei_event_pointer_get_scroll_stop_y(struct ei_event *event);
|
||||
|
||||
/**
|
||||
* For an event of type @ref EI_EVENT_POINTER_SCROLL_DISCRETE return the x
|
||||
* scroll distance in fractions or multiples of 120.
|
||||
*/
|
||||
int32_t
|
||||
ei_event_pointer_get_scroll_discrete_x(struct ei_event *event);
|
||||
|
||||
/**
|
||||
* For an event of type @ref EI_EVENT_POINTER_SCROLL_DISCRETE return the y
|
||||
* scroll distance in fractions or multiples of 120.
|
||||
*/
|
||||
int32_t
|
||||
ei_event_pointer_get_scroll_discrete_y(struct ei_event *event);
|
||||
|
||||
/**
|
||||
* For an event of type @ref EI_EVENT_KEYBOARD_KEY return the key code (as
|
||||
* defined in include/linux/input-event-codes.h).
|
||||
*/
|
||||
uint32_t
|
||||
ei_event_keyboard_get_key(struct ei_event *event);
|
||||
|
||||
/**
|
||||
* For an event of type @ref EI_EVENT_KEYBOARD_KEY return true if the
|
||||
* event is a key down, false for a release.
|
||||
*/
|
||||
bool
|
||||
ei_event_keyboard_get_key_is_press(struct ei_event *event);
|
||||
|
||||
/**
|
||||
* For an event of type @ref EI_EVENT_TOUCH_DOWN, @ref
|
||||
* EI_EVENT_TOUCH_MOTION, or @ref EI_EVENT_TOUCH_UP, return the tracking
|
||||
* ID of the touch.
|
||||
*
|
||||
* The tracking ID is a unique identifier for a touch and is valid from
|
||||
* touch down through to touch up but may be re-used in the future.
|
||||
* The tracking ID is randomly assigned to a touch, a client
|
||||
* must not expect any specific value.
|
||||
*/
|
||||
uint32_t
|
||||
ei_event_touch_get_id(struct ei_event *event);
|
||||
|
||||
/**
|
||||
* For an event of type @ref EI_EVENT_TOUCH_DOWN, or @ref
|
||||
* EI_EVENT_TOUCH_MOTION, return the x coordinate of the touch.
|
||||
*/
|
||||
double
|
||||
ei_event_touch_get_x(struct ei_event *event);
|
||||
|
||||
/**
|
||||
* For an event of type @ref EI_EVENT_TOUCH_DOWN, or @ref
|
||||
* EI_EVENT_TOUCH_MOTION, return the y coordinate of the touch.
|
||||
*/
|
||||
double
|
||||
ei_event_touch_get_y(struct ei_event *event);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -79,6 +79,12 @@ eis_client_get_context(struct eis_client *client)
|
|||
return eis_client_parent(client);
|
||||
}
|
||||
|
||||
_public_ bool
|
||||
eis_client_is_active(struct eis_client *client)
|
||||
{
|
||||
return client->is_active;
|
||||
}
|
||||
|
||||
static struct eis_device *
|
||||
eis_client_find_device(struct eis_client *client, uint32_t deviceid)
|
||||
{
|
||||
|
|
@ -268,9 +274,19 @@ client_msg_unbind_seat(struct eis_client *client, uint32_t seatid)
|
|||
return seat ? 0 : -EINVAL;
|
||||
}
|
||||
|
||||
#define DISCONNECT_IF_ACTIVE_CONTEXT(client_) do { \
|
||||
struct eis *_ctx = eis_client_get_context(client_); \
|
||||
if (_ctx->is_active) { \
|
||||
log_bug_client(_ctx, "Invalid event from passive ei context. Disconnecting client\n"); \
|
||||
return -EINVAL; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
static int
|
||||
client_msg_start_emulating(struct eis_client *client, uint32_t deviceid)
|
||||
{
|
||||
DISCONNECT_IF_ACTIVE_CONTEXT(client);
|
||||
|
||||
struct eis_device *device = eis_client_find_device(client, deviceid);
|
||||
|
||||
if (device)
|
||||
|
|
@ -282,6 +298,8 @@ client_msg_start_emulating(struct eis_client *client, uint32_t deviceid)
|
|||
static int
|
||||
client_msg_stop_emulating(struct eis_client *client, uint32_t deviceid)
|
||||
{
|
||||
DISCONNECT_IF_ACTIVE_CONTEXT(client);
|
||||
|
||||
struct eis_device *device = eis_client_find_device(client, deviceid);
|
||||
|
||||
if (device)
|
||||
|
|
@ -293,6 +311,8 @@ client_msg_stop_emulating(struct eis_client *client, uint32_t deviceid)
|
|||
static int
|
||||
client_msg_frame(struct eis_client *client, uint32_t deviceid)
|
||||
{
|
||||
DISCONNECT_IF_ACTIVE_CONTEXT(client);
|
||||
|
||||
struct eis_device *device = eis_client_find_device(client, deviceid);
|
||||
|
||||
if (device)
|
||||
|
|
@ -305,6 +325,8 @@ static int
|
|||
client_msg_pointer_rel(struct eis_client *client, uint32_t deviceid,
|
||||
double x, double y)
|
||||
{
|
||||
DISCONNECT_IF_ACTIVE_CONTEXT(client);
|
||||
|
||||
struct eis_device *device = eis_client_find_device(client, deviceid);
|
||||
|
||||
if (device)
|
||||
|
|
@ -317,6 +339,8 @@ static int
|
|||
client_msg_pointer_abs(struct eis_client *client, uint32_t deviceid,
|
||||
double x, double y)
|
||||
{
|
||||
DISCONNECT_IF_ACTIVE_CONTEXT(client);
|
||||
|
||||
struct eis_device *device = eis_client_find_device(client, deviceid);
|
||||
|
||||
if (device)
|
||||
|
|
@ -329,6 +353,8 @@ static int
|
|||
client_msg_pointer_button(struct eis_client *client, uint32_t deviceid,
|
||||
uint32_t button, bool state)
|
||||
{
|
||||
DISCONNECT_IF_ACTIVE_CONTEXT(client);
|
||||
|
||||
struct eis_device *device = eis_client_find_device(client, deviceid);
|
||||
|
||||
if (device)
|
||||
|
|
@ -341,6 +367,8 @@ static int
|
|||
client_msg_pointer_scroll(struct eis_client *client, uint32_t deviceid,
|
||||
double x, double y)
|
||||
{
|
||||
DISCONNECT_IF_ACTIVE_CONTEXT(client);
|
||||
|
||||
struct eis_device *device = eis_client_find_device(client, deviceid);
|
||||
|
||||
if (device)
|
||||
|
|
@ -353,6 +381,8 @@ static int
|
|||
client_msg_pointer_scroll_discrete(struct eis_client *client, uint32_t deviceid,
|
||||
int32_t x, int32_t y)
|
||||
{
|
||||
DISCONNECT_IF_ACTIVE_CONTEXT(client);
|
||||
|
||||
struct eis_device *device = eis_client_find_device(client, deviceid);
|
||||
|
||||
if (device)
|
||||
|
|
@ -365,6 +395,8 @@ static int
|
|||
client_msg_pointer_scroll_stop(struct eis_client *client, uint32_t deviceid,
|
||||
bool x, bool y, bool is_cancel)
|
||||
{
|
||||
DISCONNECT_IF_ACTIVE_CONTEXT(client);
|
||||
|
||||
struct eis_device *device = eis_client_find_device(client, deviceid);
|
||||
|
||||
if (device) {
|
||||
|
|
@ -381,6 +413,8 @@ static int
|
|||
client_msg_keyboard_key(struct eis_client *client, uint32_t deviceid,
|
||||
uint32_t key, bool state)
|
||||
{
|
||||
DISCONNECT_IF_ACTIVE_CONTEXT(client);
|
||||
|
||||
struct eis_device *device = eis_client_find_device(client, deviceid);
|
||||
|
||||
if (device)
|
||||
|
|
@ -393,6 +427,8 @@ static int
|
|||
client_msg_touch_down(struct eis_client *client, uint32_t deviceid,
|
||||
uint32_t touchid, double x, double y)
|
||||
{
|
||||
DISCONNECT_IF_ACTIVE_CONTEXT(client);
|
||||
|
||||
struct eis_device *device = eis_client_find_device(client, deviceid);
|
||||
|
||||
if (device)
|
||||
|
|
@ -405,6 +441,8 @@ static int
|
|||
client_msg_touch_motion(struct eis_client *client, uint32_t deviceid,
|
||||
uint32_t touchid, double x, double y)
|
||||
{
|
||||
DISCONNECT_IF_ACTIVE_CONTEXT(client);
|
||||
|
||||
struct eis_device *device = eis_client_find_device(client, deviceid);
|
||||
|
||||
if (device)
|
||||
|
|
@ -416,6 +454,8 @@ client_msg_touch_motion(struct eis_client *client, uint32_t deviceid,
|
|||
static int
|
||||
client_msg_touch_up(struct eis_client *client, uint32_t deviceid, uint32_t touchid)
|
||||
{
|
||||
DISCONNECT_IF_ACTIVE_CONTEXT(client);
|
||||
|
||||
struct eis_device *device = eis_client_find_device(client, deviceid);
|
||||
|
||||
if (device)
|
||||
|
|
@ -450,11 +490,13 @@ client_msg_configure_capabilities(struct eis_client *client, uint32_t allowed_ca
|
|||
}
|
||||
|
||||
static int
|
||||
client_msg_connect(struct eis_client *client, const char *name)
|
||||
client_msg_connect(struct eis_client *client, const char *name, bool is_active)
|
||||
{
|
||||
if (client->name == NULL)
|
||||
client->name = xstrdup(name);
|
||||
|
||||
client->is_active = is_active;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -589,6 +631,7 @@ eis_client_new(struct eis *eis, int fd)
|
|||
static uint32_t client_id;
|
||||
struct eis_client *client = eis_client_create(&eis->object);
|
||||
|
||||
client->is_active = true;
|
||||
client->id = ++client_id;
|
||||
list_init(&client->seats);
|
||||
list_init(&client->seats_pending);
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include "util-io.h"
|
||||
|
||||
#include "libeis-private.h"
|
||||
#include "libeis-proto.h"
|
||||
|
||||
_public_
|
||||
OBJECT_IMPLEMENT_REF(eis_keymap);
|
||||
|
|
@ -247,6 +248,9 @@ eis_device_remove(struct eis_device *device)
|
|||
if (device->state == EIS_DEVICE_STATE_DEAD)
|
||||
return;
|
||||
|
||||
if (device->state == EIS_DEVICE_STATE_EMULATING)
|
||||
eis_device_stop_emulating(device);
|
||||
|
||||
device->state = EIS_DEVICE_STATE_DEAD;
|
||||
eis_client_remove_device(eis_device_get_client(device), device);
|
||||
list_remove(&device->link);
|
||||
|
|
@ -267,6 +271,331 @@ eis_device_has_capability(struct eis_device *device,
|
|||
return false;
|
||||
}
|
||||
|
||||
#define handle_request_noargs(device_, func_) { \
|
||||
struct eis *eis = eis_device_get_context(device); \
|
||||
eis->requests->func_(device_, device->id); \
|
||||
}
|
||||
|
||||
#define handle_request(device_, func_, ...) { \
|
||||
struct eis *eis = eis_device_get_context(device); \
|
||||
eis->requests->func_(device_, device->id, __VA_ARGS__); \
|
||||
}
|
||||
|
||||
_public_ void
|
||||
eis_device_start_emulating(struct eis_device *device)
|
||||
{
|
||||
if (device->state != EIS_DEVICE_STATE_RESUMED)
|
||||
return;
|
||||
|
||||
device->state = EIS_DEVICE_STATE_EMULATING;
|
||||
|
||||
handle_request_noargs(device, start_emulating);
|
||||
}
|
||||
|
||||
_public_ void
|
||||
eis_device_stop_emulating(struct eis_device *device)
|
||||
{
|
||||
if (device->state != EIS_DEVICE_STATE_EMULATING)
|
||||
return;
|
||||
|
||||
device->state = EIS_DEVICE_STATE_RESUMED;
|
||||
|
||||
handle_request_noargs(device, stop_emulating);
|
||||
}
|
||||
|
||||
_public_ void
|
||||
eis_device_pointer_motion(struct eis_device *device,
|
||||
double x, double y)
|
||||
{
|
||||
if (!eis_device_has_capability(device, EIS_DEVICE_CAP_POINTER)) {
|
||||
log_bug_client(eis_device_get_context(device),
|
||||
"%s: device is not a pointer\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (device->state != EIS_DEVICE_STATE_EMULATING)
|
||||
return;
|
||||
|
||||
handle_request(device, rel, x, y);
|
||||
}
|
||||
|
||||
_public_ void
|
||||
eis_device_pointer_motion_absolute(struct eis_device *device,
|
||||
double x, double y)
|
||||
{
|
||||
if (!eis_device_has_capability(device, EIS_DEVICE_CAP_POINTER_ABSOLUTE)) {
|
||||
log_bug_client(eis_device_get_context(device),
|
||||
"%s: device is not an absolute pointer\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (device->state != EIS_DEVICE_STATE_EMULATING)
|
||||
return;
|
||||
|
||||
struct eis_region *r;
|
||||
list_for_each(r, &device->regions, link) {
|
||||
if (!eis_region_contains(r, x, y)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
handle_request(device, abs, x, y);
|
||||
}
|
||||
|
||||
_public_ void
|
||||
eis_device_pointer_button(struct eis_device *device,
|
||||
uint32_t button, bool is_press)
|
||||
{
|
||||
if (!eis_device_has_capability(device, EIS_DEVICE_CAP_POINTER)) {
|
||||
log_bug_client(eis_device_get_context(device),
|
||||
"%s: device is not a pointer\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (device->state != EIS_DEVICE_STATE_EMULATING)
|
||||
return;
|
||||
|
||||
/* Ignore anything < BTN_MOUSE. Avoids the common error of sending
|
||||
* numerical buttons instead of BTN_LEFT and friends. */
|
||||
if (button < 0x110) {
|
||||
log_bug_client(eis_device_get_context(device),
|
||||
"%s: button code must be one of BTN_*\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
handle_request(device, button, button, is_press);
|
||||
}
|
||||
|
||||
static inline void
|
||||
eis_device_resume_scrolling(struct eis_device *device, double x, double y)
|
||||
{
|
||||
if (x) {
|
||||
device->scroll.x_is_stopped = false;
|
||||
device->scroll.x_is_cancelled = false;
|
||||
}
|
||||
if (y) {
|
||||
device->scroll.y_is_stopped = false;
|
||||
device->scroll.y_is_cancelled = false;
|
||||
}
|
||||
}
|
||||
|
||||
_public_ void
|
||||
eis_device_pointer_scroll(struct eis_device *device,
|
||||
double x, double y)
|
||||
{
|
||||
if (!eis_device_has_capability(device, EIS_DEVICE_CAP_POINTER) &&
|
||||
!eis_device_has_capability(device, EIS_DEVICE_CAP_POINTER_ABSOLUTE)) {
|
||||
log_bug_client(eis_device_get_context(device),
|
||||
"%s: device is not a (absolute) pointer\n", __func__);
|
||||
}
|
||||
|
||||
if (device->state != EIS_DEVICE_STATE_EMULATING)
|
||||
return;
|
||||
|
||||
eis_device_resume_scrolling(device, x, y);
|
||||
|
||||
handle_request(device, scroll, x, y);
|
||||
}
|
||||
|
||||
_public_ void
|
||||
eis_device_pointer_scroll_stop(struct eis_device *device, bool x, bool y)
|
||||
{
|
||||
if (!eis_device_has_capability(device, EIS_DEVICE_CAP_POINTER) &&
|
||||
!eis_device_has_capability(device, EIS_DEVICE_CAP_POINTER_ABSOLUTE)) {
|
||||
log_bug_client(eis_device_get_context(device),
|
||||
"%s: device is not a (absolute) pointer\n", __func__);
|
||||
}
|
||||
if (device->state != EIS_DEVICE_STATE_EMULATING)
|
||||
return;
|
||||
|
||||
/* Filter out duplicate scroll stop requests */
|
||||
if (x && !device->scroll.x_is_stopped)
|
||||
device->scroll.x_is_stopped = true;
|
||||
else
|
||||
x = false;
|
||||
|
||||
if (y && !device->scroll.y_is_stopped)
|
||||
device->scroll.y_is_stopped = true;
|
||||
else
|
||||
y = false;
|
||||
|
||||
if (x || y)
|
||||
handle_request(device, scroll_stop, x, y, false);
|
||||
}
|
||||
|
||||
_public_ void
|
||||
eis_device_pointer_scroll_cancel(struct eis_device *device, bool x, bool y)
|
||||
{
|
||||
if (!eis_device_has_capability(device, EIS_DEVICE_CAP_POINTER) &&
|
||||
!eis_device_has_capability(device, EIS_DEVICE_CAP_POINTER_ABSOLUTE)) {
|
||||
log_bug_client(eis_device_get_context(device),
|
||||
"%s: device is not a (absolute) pointer\n", __func__);
|
||||
}
|
||||
if (device->state != EIS_DEVICE_STATE_EMULATING)
|
||||
return;
|
||||
|
||||
/* Filter out duplicate scroll cancelled requests */
|
||||
if (x && !device->scroll.x_is_cancelled) {
|
||||
device->scroll.x_is_stopped = true;
|
||||
device->scroll.x_is_cancelled = true;
|
||||
} else {
|
||||
x = false;
|
||||
}
|
||||
|
||||
if (y && !device->scroll.y_is_cancelled) {
|
||||
device->scroll.y_is_stopped = true;
|
||||
device->scroll.y_is_cancelled = true;
|
||||
} else {
|
||||
y = false;
|
||||
}
|
||||
|
||||
if (x || y)
|
||||
handle_request(device, scroll_stop, x, y, true);
|
||||
}
|
||||
|
||||
_public_ void
|
||||
eis_device_pointer_scroll_discrete(struct eis_device *device,
|
||||
int32_t x, int32_t y)
|
||||
{
|
||||
if (!eis_device_has_capability(device, EIS_DEVICE_CAP_POINTER) &&
|
||||
!eis_device_has_capability(device, EIS_DEVICE_CAP_POINTER_ABSOLUTE)) {
|
||||
log_bug_client(eis_device_get_context(device),
|
||||
"%s: device is not a (absolute) pointer\n", __func__);
|
||||
}
|
||||
|
||||
if (device->state != EIS_DEVICE_STATE_EMULATING)
|
||||
return;
|
||||
|
||||
eis_device_resume_scrolling(device, x, y);
|
||||
|
||||
handle_request(device, scroll_discrete, x, y);
|
||||
}
|
||||
|
||||
_public_ void
|
||||
eis_device_keyboard_key(struct eis_device *device,
|
||||
uint32_t key, bool is_press)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
if (device->state != EIS_DEVICE_STATE_EMULATING)
|
||||
return;
|
||||
|
||||
handle_request(device, key, key, is_press);
|
||||
}
|
||||
|
||||
|
||||
_public_
|
||||
OBJECT_IMPLEMENT_REF(eis_touch);
|
||||
_public_
|
||||
OBJECT_IMPLEMENT_UNREF_CLEANUP(eis_touch);
|
||||
_public_
|
||||
OBJECT_IMPLEMENT_GETTER(eis_touch, device, struct eis_device*);
|
||||
_public_
|
||||
OBJECT_IMPLEMENT_GETTER(eis_touch, user_data, void *);
|
||||
_public_
|
||||
OBJECT_IMPLEMENT_SETTER(eis_touch, user_data, void *);
|
||||
|
||||
static void
|
||||
eis_touch_destroy(struct eis_touch *touch)
|
||||
{
|
||||
eis_touch_up(touch);
|
||||
eis_device_unref(touch->device);
|
||||
}
|
||||
|
||||
static
|
||||
OBJECT_IMPLEMENT_CREATE(eis_touch);
|
||||
|
||||
_public_ struct eis_touch *
|
||||
eis_device_touch_new(struct eis_device *device)
|
||||
{
|
||||
static uint32_t tracking_id = 0;
|
||||
|
||||
/* Not using the device as parent object because we need a ref
|
||||
* to it */
|
||||
struct eis_touch *touch = eis_touch_create(NULL);
|
||||
|
||||
touch->device = eis_device_ref(device);
|
||||
touch->state = TOUCH_IS_NEW;
|
||||
touch->tracking_id = ++tracking_id;
|
||||
|
||||
return touch;
|
||||
}
|
||||
|
||||
_public_ void
|
||||
eis_touch_down(struct eis_touch *touch, double x, double y)
|
||||
{
|
||||
struct eis_device *device = eis_touch_get_device(touch);
|
||||
|
||||
if (touch->state != TOUCH_IS_NEW) {
|
||||
log_bug_client(eis_device_get_context(device),
|
||||
"%s: device is not a keyboard\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
struct eis_region *r;
|
||||
list_for_each(r, &device->regions, link) {
|
||||
if (!eis_region_contains(r, x, y)) {
|
||||
log_bug_client(eis_device_get_context(device),
|
||||
"%s: invalid x/y coordinates\n", __func__);
|
||||
touch->state = TOUCH_IS_UP;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
touch->state = TOUCH_IS_DOWN;
|
||||
|
||||
handle_request(device, touch_down, touch->tracking_id, x, y);
|
||||
}
|
||||
|
||||
_public_ void
|
||||
eis_touch_motion(struct eis_touch *touch, double x, double y)
|
||||
{
|
||||
if (touch->state != TOUCH_IS_DOWN)
|
||||
return;
|
||||
|
||||
struct eis_device *device = eis_touch_get_device(touch);
|
||||
struct eis_region *r;
|
||||
list_for_each(r, &device->regions, link) {
|
||||
if (!eis_region_contains(r, x, y)) {
|
||||
log_bug_client(eis_device_get_context(device),
|
||||
"%s: invalid x/y coordinates\n", __func__);
|
||||
eis_touch_up(touch);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
handle_request(device, touch_motion, touch->tracking_id, x, y);
|
||||
}
|
||||
|
||||
_public_ void
|
||||
eis_touch_up(struct eis_touch *touch)
|
||||
{
|
||||
struct eis_device *device = eis_touch_get_device(touch);
|
||||
|
||||
if (touch->state != TOUCH_IS_DOWN) {
|
||||
log_bug_client(eis_device_get_context(device),
|
||||
"%s: touch is not currently down\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
touch->state = TOUCH_IS_UP;
|
||||
|
||||
handle_request(device, touch_up, touch->tracking_id);
|
||||
}
|
||||
|
||||
_public_ void
|
||||
eis_device_frame(struct eis_device *device)
|
||||
{
|
||||
if (device->state != EIS_DEVICE_STATE_RESUMED)
|
||||
return;
|
||||
|
||||
handle_request_noargs(device, frame);
|
||||
}
|
||||
|
||||
int
|
||||
eis_device_event_frame(struct eis_device *device)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -54,6 +54,8 @@ struct eis {
|
|||
} log;
|
||||
|
||||
const struct eis_proto_requests *requests;
|
||||
|
||||
bool is_active;
|
||||
};
|
||||
|
||||
enum eis_client_state {
|
||||
|
|
@ -71,7 +73,7 @@ struct eis_client {
|
|||
uint32_t id;
|
||||
enum eis_client_state state;
|
||||
char *name;
|
||||
|
||||
bool is_active;
|
||||
|
||||
struct list seats;
|
||||
struct list seats_pending;
|
||||
|
|
@ -139,6 +141,26 @@ struct eis_device {
|
|||
struct list regions_new; /* not yet added */
|
||||
|
||||
struct eis_keymap *keymap;
|
||||
|
||||
struct {
|
||||
bool x_is_stopped, y_is_stopped;
|
||||
bool x_is_cancelled, y_is_cancelled;
|
||||
} scroll;
|
||||
|
||||
};
|
||||
|
||||
struct eis_touch {
|
||||
struct object object;
|
||||
struct eis_device *device;
|
||||
void *user_data;
|
||||
uint32_t tracking_id;
|
||||
enum {
|
||||
TOUCH_IS_NEW,
|
||||
TOUCH_IS_DOWN,
|
||||
TOUCH_IS_UP,
|
||||
} state;
|
||||
|
||||
double x, y;
|
||||
};
|
||||
|
||||
struct eis_event {
|
||||
|
|
|
|||
|
|
@ -66,6 +66,20 @@ log_wire_message(struct eis *eis, const ServerMessage *msg)
|
|||
MSG_STRING_CASE(DEVICE_PAUSED);
|
||||
MSG_STRING_CASE(KEYBOARD_MODIFIERS);
|
||||
MSG_STRING_CASE(PROPERTY);
|
||||
/* events */
|
||||
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);
|
||||
MSG_STRING_CASE(POINTER_SCROLL);
|
||||
MSG_STRING_CASE(POINTER_SCROLL_STOP);
|
||||
MSG_STRING_CASE(POINTER_SCROLL_DISCRETE);
|
||||
MSG_STRING_CASE(KEYBOARD_KEY);
|
||||
MSG_STRING_CASE(TOUCH_DOWN);
|
||||
MSG_STRING_CASE(TOUCH_MOTION);
|
||||
MSG_STRING_CASE(TOUCH_UP);
|
||||
MSG_STRING_CASE(FRAME);
|
||||
break;
|
||||
}
|
||||
if (message == NULL)
|
||||
|
|
@ -118,7 +132,10 @@ eis_proto_send_msg_with_fds(struct eis_client *client, const ServerMessage *msg,
|
|||
static int
|
||||
eis_proto_send_disconnected(struct eis_client *client)
|
||||
{
|
||||
struct eis *eis = eis_client_get_context(client);
|
||||
|
||||
prepare_msg(DISCONNECTED, Disconnected, disconnected);
|
||||
disconnected.is_active = eis->is_active;
|
||||
|
||||
return eis_proto_send_msg(client, &msg);
|
||||
}
|
||||
|
|
@ -271,6 +288,167 @@ eis_proto_send_property(struct eis_client *client, const char *name,
|
|||
return eis_proto_send_msg(client, &msg);
|
||||
}
|
||||
|
||||
static int
|
||||
eis_proto_send_start_emulating(struct eis_device *device, uint32_t deviceid)
|
||||
{
|
||||
prepare_msg(START_EMULATING, StartEmulating, start_emulating);
|
||||
|
||||
start_emulating.deviceid = device->id;
|
||||
|
||||
return eis_proto_send_msg(eis_device_get_client(device), &msg);
|
||||
}
|
||||
|
||||
static int
|
||||
eis_proto_send_stop_emulating(struct eis_device *device, uint32_t deviceid)
|
||||
{
|
||||
prepare_msg(STOP_EMULATING, StopEmulating, stop_emulating);
|
||||
|
||||
stop_emulating.deviceid = device->id;
|
||||
|
||||
return eis_proto_send_msg(eis_device_get_client(device), &msg);
|
||||
}
|
||||
|
||||
static int
|
||||
eis_proto_send_rel(struct eis_device *device, uint32_t deviceid, double x, double y)
|
||||
{
|
||||
prepare_msg(POINTER_RELATIVE, PointerRelative, pointer_relative);
|
||||
|
||||
pointer_relative.deviceid = device->id;
|
||||
pointer_relative.x = x;
|
||||
pointer_relative.y = y;
|
||||
|
||||
return eis_proto_send_msg(eis_device_get_client(device), &msg);
|
||||
}
|
||||
|
||||
static int
|
||||
eis_proto_send_abs(struct eis_device *device, uint32_t deviceid, double x, double y)
|
||||
{
|
||||
prepare_msg(POINTER_ABSOLUTE, PointerAbsolute, pointer_absolute);
|
||||
|
||||
pointer_absolute.deviceid = device->id;
|
||||
pointer_absolute.x = x;
|
||||
pointer_absolute.y = y;
|
||||
|
||||
return eis_proto_send_msg(eis_device_get_client(device), &msg);
|
||||
}
|
||||
|
||||
static int
|
||||
eis_proto_send_button(struct eis_device *device, uint32_t deviceid,
|
||||
uint32_t button, bool is_press)
|
||||
{
|
||||
prepare_msg(POINTER_BUTTON, PointerButton, pointer_button);
|
||||
|
||||
pointer_button.deviceid = device->id;
|
||||
pointer_button.button = button;
|
||||
pointer_button.state = is_press;
|
||||
|
||||
return eis_proto_send_msg(eis_device_get_client(device), &msg);
|
||||
}
|
||||
|
||||
static int
|
||||
eis_proto_send_key(struct eis_device *device, uint32_t deviceid,
|
||||
uint32_t key, bool is_press)
|
||||
{
|
||||
prepare_msg(KEYBOARD_KEY, KeyboardKey, keyboard_key);
|
||||
|
||||
keyboard_key.deviceid = device->id;
|
||||
keyboard_key.key = key;
|
||||
keyboard_key.state = is_press;
|
||||
|
||||
return eis_proto_send_msg(eis_device_get_client(device), &msg);
|
||||
}
|
||||
|
||||
static int
|
||||
eis_proto_send_scroll(struct eis_device *device, uint32_t deviceid,
|
||||
double x, double y)
|
||||
{
|
||||
prepare_msg(POINTER_SCROLL, PointerScroll, pointer_scroll);
|
||||
|
||||
pointer_scroll.deviceid = device->id;
|
||||
pointer_scroll.x = x;
|
||||
pointer_scroll.y = y;
|
||||
|
||||
|
||||
return eis_proto_send_msg(eis_device_get_client(device), &msg);
|
||||
}
|
||||
|
||||
static int
|
||||
eis_proto_send_scroll_stop(struct eis_device *device, uint32_t deviceid,
|
||||
bool x, bool y, bool is_cancel)
|
||||
{
|
||||
prepare_msg(POINTER_SCROLL_STOP, PointerScrollStop, pointer_scroll_stop);
|
||||
|
||||
pointer_scroll_stop.deviceid = device->id;
|
||||
pointer_scroll_stop.x = x;
|
||||
pointer_scroll_stop.y = y;
|
||||
pointer_scroll_stop.is_cancel = is_cancel;
|
||||
|
||||
return eis_proto_send_msg(eis_device_get_client(device), &msg);
|
||||
}
|
||||
|
||||
static int
|
||||
eis_proto_send_scroll_discrete(struct eis_device *device, uint32_t deviceid,
|
||||
int32_t x, int32_t y)
|
||||
{
|
||||
|
||||
prepare_msg(POINTER_SCROLL_DISCRETE, PointerScrollDiscrete, pointer_scroll_discrete);
|
||||
|
||||
pointer_scroll_discrete.deviceid = device->id;
|
||||
pointer_scroll_discrete.x = x;
|
||||
pointer_scroll_discrete.y = y;
|
||||
|
||||
return eis_proto_send_msg(eis_device_get_client(device), &msg);
|
||||
}
|
||||
|
||||
static int
|
||||
eis_proto_send_touch_down(struct eis_device *device, uint32_t deviceid,
|
||||
uint32_t tid, double x, double y)
|
||||
{
|
||||
prepare_msg(TOUCH_DOWN, TouchDown, touch_down);
|
||||
|
||||
touch_down.deviceid = device->id;
|
||||
touch_down.touchid = tid;
|
||||
touch_down.x = x;
|
||||
touch_down.y = y;
|
||||
|
||||
return eis_proto_send_msg(eis_device_get_client(device), &msg);
|
||||
}
|
||||
|
||||
static int
|
||||
eis_proto_send_touch_motion(struct eis_device *device, uint32_t deviceid,
|
||||
uint32_t tid, double x, double y)
|
||||
{
|
||||
prepare_msg(TOUCH_MOTION, TouchMotion, touch_motion);
|
||||
|
||||
touch_motion.deviceid = device->id;
|
||||
touch_motion.touchid = tid;
|
||||
touch_motion.x = x;
|
||||
touch_motion.y = y;
|
||||
|
||||
return eis_proto_send_msg(eis_device_get_client(device), &msg);
|
||||
}
|
||||
|
||||
static int
|
||||
eis_proto_send_touch_up(struct eis_device *device, uint32_t deviceid, uint32_t tid)
|
||||
{
|
||||
prepare_msg(TOUCH_UP, TouchUp, touch_up);
|
||||
|
||||
touch_up.deviceid = device->id;
|
||||
touch_up.touchid = tid;
|
||||
|
||||
return eis_proto_send_msg(eis_device_get_client(device), &msg);
|
||||
}
|
||||
|
||||
static int
|
||||
eis_proto_send_frame(struct eis_device *device, uint32_t deviceid)
|
||||
{
|
||||
prepare_msg(FRAME, Frame, frame);
|
||||
|
||||
frame.deviceid = device->id;
|
||||
|
||||
return eis_proto_send_msg(eis_device_get_client(device), &msg);
|
||||
}
|
||||
|
||||
static const struct eis_proto_requests requests = {
|
||||
.disconnected = eis_proto_send_disconnected,
|
||||
.connected = eis_proto_send_connected,
|
||||
|
|
@ -285,6 +463,21 @@ static const struct eis_proto_requests requests = {
|
|||
.device_region = eis_proto_send_device_region,
|
||||
.keyboard_modifiers = eis_proto_send_keyboard_modifiers,
|
||||
.property = eis_proto_send_property,
|
||||
|
||||
/* events */
|
||||
.start_emulating = eis_proto_send_start_emulating,
|
||||
.stop_emulating = eis_proto_send_stop_emulating,
|
||||
.rel = eis_proto_send_rel,
|
||||
.abs = eis_proto_send_abs,
|
||||
.button = eis_proto_send_button,
|
||||
.scroll = eis_proto_send_scroll,
|
||||
.scroll_stop = eis_proto_send_scroll_stop,
|
||||
.scroll_discrete = eis_proto_send_scroll_discrete,
|
||||
.key = eis_proto_send_key,
|
||||
.touch_down = eis_proto_send_touch_down,
|
||||
.touch_motion = eis_proto_send_touch_motion,
|
||||
.touch_up = eis_proto_send_touch_up,
|
||||
.frame = eis_proto_send_frame,
|
||||
};
|
||||
|
||||
const struct eis_proto_requests *
|
||||
|
|
@ -318,7 +511,7 @@ eis_proto_handle_message(struct eis_client *client,
|
|||
int rc;
|
||||
switch (proto->msg_case) {
|
||||
case CLIENT_MESSAGE__MSG_CONNECT:
|
||||
rc = call(connect, client, proto->connect->name);
|
||||
rc = call(connect, client, proto->connect->name, proto->connect->is_active);
|
||||
break;
|
||||
case CLIENT_MESSAGE__MSG_CONNECT_DONE:
|
||||
rc = call(connect_done, client);
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
/* callbacks invoked during eis_proto_parse_message() */
|
||||
struct eis_proto_interface {
|
||||
int (*connect)(struct eis_client *client, const char *name);
|
||||
int (*connect)(struct eis_client *client, const char *name, bool is_active);
|
||||
int (*connect_done)(struct eis_client *client);
|
||||
int (*disconnect)(struct eis_client *client);
|
||||
int (*bind_seat)(struct eis_client *client, uint32_t seatid, uint32_t capabilities);
|
||||
|
|
@ -81,6 +81,23 @@ struct eis_proto_requests {
|
|||
const struct eis_xkb_modifiers *mods);
|
||||
int (*property)(struct eis_client *client, const char *name,
|
||||
const char *value, uint32_t permissions);
|
||||
|
||||
/* events */
|
||||
int (*start_emulating)(struct eis_device *device, uint32_t deviceid);
|
||||
int (*stop_emulating)(struct eis_device *device, uint32_t deviceid);
|
||||
int (*rel)(struct eis_device *device, uint32_t deviceid, double x, double y);
|
||||
int (*abs)(struct eis_device *device, uint32_t deviceid, double x, double y);
|
||||
int (*button)(struct eis_device *device, uint32_t deviceid, uint32_t button, bool is_press);
|
||||
int (*key)(struct eis_device *device, uint32_t deviceid, uint32_t key, bool is_press);
|
||||
int (*scroll)(struct eis_device *device, uint32_t deviceid, double x, double y);
|
||||
int (*scroll_stop)(struct eis_device *device, uint32_t deviceid, bool x, bool y, bool is_cancel);
|
||||
int (*scroll_discrete)(struct eis_device *device, uint32_t deviceid, int32_t x, int32_t y);
|
||||
int (*touch_down)(struct eis_device *device, uint32_t deviceid,
|
||||
uint32_t tid, double x, double y);
|
||||
int (*touch_motion)(struct eis_device *device, uint32_t deviceid,
|
||||
uint32_t tid, double x, double y);
|
||||
int (*touch_up)(struct eis_device *device, uint32_t deviceid, uint32_t tid);
|
||||
int (*frame) (struct eis_device *device, uint32_t deviceid);
|
||||
};
|
||||
|
||||
int
|
||||
|
|
|
|||
111
src/libeis.h
111
src/libeis.h
|
|
@ -39,6 +39,18 @@ extern "C" {
|
|||
* libeis is the server-side module. This API should be used by processes
|
||||
* that have control over input devices, e.g. Wayland compositors.
|
||||
*
|
||||
* libei clients come in "active" and "passive" modes, depending on whether
|
||||
* the client sends or receives events. A libeis context however is both
|
||||
* active and passive at the same time, it is up to the implementation to
|
||||
* disconnect clients that it does not want to allow. See
|
||||
* eis_client_is_active() for details.
|
||||
*
|
||||
* Note that usually the differentiation between active and passive client
|
||||
* has an effect on the devices that should be sent to the client. Active
|
||||
* clients typically expect devices representing the available screen area so
|
||||
* they can control input, passive clients typically expect devices
|
||||
* representing the physical input devices.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
|
@ -48,6 +60,7 @@ struct eis_device;
|
|||
struct eis_seat;
|
||||
struct eis_event;
|
||||
struct eis_keymap;
|
||||
struct eis_touch;
|
||||
|
||||
/**
|
||||
* @struct eis_region
|
||||
|
|
@ -144,6 +157,8 @@ enum eis_event_type {
|
|||
* and notifies the server that the previous set of events belong to
|
||||
* the same logical hardware event.
|
||||
*
|
||||
* These events are only generated on a passive EIS context.
|
||||
*
|
||||
* This event is most commonly used to implement multitouch (multiple
|
||||
* touches may update within the same hardware scanout cycle).
|
||||
*/
|
||||
|
|
@ -154,7 +169,9 @@ enum eis_event_type {
|
|||
* 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
|
||||
* These events are only generated on a passive EIS context.
|
||||
*
|
||||
* Note that a client start multiple emulating sequences
|
||||
* simultaneously, depending on the devices it received from the
|
||||
* server. For example, in a synergy-like situation, the client
|
||||
* may start emulating of pointer and keyboard once the remote device
|
||||
|
|
@ -169,6 +186,8 @@ enum eis_event_type {
|
|||
*/
|
||||
EIS_EVENT_DEVICE_STOP_EMULATING,
|
||||
|
||||
/* These events are only generated on a passive EIS context */
|
||||
|
||||
/**
|
||||
* A relative motion event with delta coordinates
|
||||
*/
|
||||
|
|
@ -286,6 +305,14 @@ eis_get_user_data(struct eis *eis);
|
|||
void
|
||||
eis_set_user_data(struct eis *eis, void *user_data);
|
||||
|
||||
/**
|
||||
* Returns true if the client is active, false otherwise. An active client may
|
||||
* send events to the EIS implementation, a passive client expects to receive
|
||||
* events from the EIS implementation.
|
||||
*/
|
||||
bool
|
||||
eis_client_is_active(struct eis_client *client);
|
||||
|
||||
/**
|
||||
* See eis_client_property_set_with_permissions(), but the permissions are
|
||||
* left as-is. If the property does not exist, it is created with permissions
|
||||
|
|
@ -842,6 +869,88 @@ eis_device_keyboard_send_xkb_modifiers(struct eis_device *device,
|
|||
uint32_t locked,
|
||||
uint32_t group);
|
||||
|
||||
/** see @ref ei_device_start_emulating */
|
||||
void
|
||||
eis_device_start_emulating(struct eis_device *device);
|
||||
|
||||
/** see @ref ei_device_stop_emulating */
|
||||
void
|
||||
eis_device_stop_emulating(struct eis_device *device);
|
||||
|
||||
/** see @ref ei_device_frame */
|
||||
void
|
||||
eis_device_frame(struct eis_device *device);
|
||||
|
||||
/** see @ref ei_device_pointer_motion */
|
||||
void
|
||||
eis_device_pointer_motion(struct eis_device *device, double x, double y);
|
||||
|
||||
/** see @ref ei_device_pointer_motion_absolute */
|
||||
void
|
||||
eis_device_pointer_motion_absolute(struct eis_device *device,
|
||||
double x, double y);
|
||||
|
||||
/** see @ref ei_device_pointer_button */
|
||||
void
|
||||
eis_device_pointer_button(struct eis_device *device,
|
||||
uint32_t button, bool is_press);
|
||||
|
||||
/** see @ref ei_device_pointer_scroll */
|
||||
void
|
||||
eis_device_pointer_scroll(struct eis_device *device, double x, double y);
|
||||
|
||||
/** see @ref ei_device_pointer_scroll_discrete */
|
||||
void
|
||||
eis_device_pointer_scroll_discrete(struct eis_device *device, int32_t x, int32_t y);
|
||||
|
||||
/** see @ref ei_device_pointer_scroll_stop */
|
||||
void
|
||||
eis_device_pointer_scroll_stop(struct eis_device *device, bool stop_x, bool stop_y);
|
||||
|
||||
/** see @ref ei_device_pointer_scroll_cancel */
|
||||
void
|
||||
eis_device_pointer_scroll_cancel(struct eis_device *device, bool cancel_x, bool cancel_y);
|
||||
|
||||
/** see @ref ei_device_keyboard_key */
|
||||
void
|
||||
eis_device_keyboard_key(struct eis_device *device, uint32_t keycode, bool is_press);
|
||||
|
||||
/** see @ref ei_device_touch_new */
|
||||
struct eis_touch *
|
||||
eis_device_touch_new(struct eis_device *device);
|
||||
|
||||
/** see @ref ei_touch_down */
|
||||
void
|
||||
eis_touch_down(struct eis_touch *touch, double x, double y);
|
||||
|
||||
/** see @ref ei_touch_motion */
|
||||
void
|
||||
eis_touch_motion(struct eis_touch *touch, double x, double y);
|
||||
|
||||
/** see @ref ei_touch_up */
|
||||
void
|
||||
eis_touch_up(struct eis_touch *touch);
|
||||
|
||||
/** see @ref ei_touch_ref */
|
||||
struct eis_touch *
|
||||
eis_touch_ref(struct eis_touch *touch);
|
||||
|
||||
/** see @ref ei_touch_unref */
|
||||
struct eis_touch *
|
||||
eis_touch_unref(struct eis_touch *touch);
|
||||
|
||||
/** see @ref ei_touch_set_user_data */
|
||||
void
|
||||
eis_touch_set_user_data(struct eis_touch *touch, void *user_data);
|
||||
|
||||
/** see @ref ei_touch_get_user_data */
|
||||
void *
|
||||
eis_touch_get_user_data(struct eis_touch *touch);
|
||||
|
||||
/** see @ref ei_touch_get_device */
|
||||
struct eis_device *
|
||||
eis_touch_get_device(struct eis_touch *touch);
|
||||
|
||||
/**
|
||||
* For an event of type @ref EIS_EVENT_SEAT_BIND, return the capabilities
|
||||
* requested by the client.
|
||||
|
|
|
|||
|
|
@ -314,15 +314,17 @@ peck_log_handler(struct logger *logger,
|
|||
}
|
||||
|
||||
struct peck *
|
||||
peck_new(void)
|
||||
peck_new_context(enum peck_ei_mode ei_mode)
|
||||
{
|
||||
struct peck *peck = peck_create(NULL);
|
||||
|
||||
assert(ei_mode == PECK_EI_PASSIVE || ei_mode == PECK_EI_ACTIVE);
|
||||
|
||||
int sv[2];
|
||||
int rc = socketpair(AF_UNIX, SOCK_STREAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0, sv);
|
||||
munit_assert_int(rc, ==, 0);
|
||||
|
||||
struct ei *ei = ei_new(peck);
|
||||
struct ei *ei = ei_mode == PECK_EI_PASSIVE ? ei_new_passive(peck) : ei_new_active(peck);
|
||||
ei_set_user_data(ei, peck);
|
||||
ei_log_set_handler(ei, peck_ei_log_handler);
|
||||
ei_log_set_priority(ei, EI_LOG_PRIORITY_DEBUG);
|
||||
|
|
@ -352,6 +354,12 @@ peck_new(void)
|
|||
return peck;
|
||||
}
|
||||
|
||||
struct peck *
|
||||
peck_new(void)
|
||||
{
|
||||
return peck_new_context(PECK_EI_ACTIVE);
|
||||
}
|
||||
|
||||
void
|
||||
peck_enable_eis_behavior(struct peck *peck, enum peck_eis_behavior behavior)
|
||||
{
|
||||
|
|
@ -1014,6 +1022,20 @@ peck_ei_event_type_name(enum ei_event_type type)
|
|||
CASE_STRING(DEVICE_RESUMED);
|
||||
CASE_STRING(KEYBOARD_MODIFIERS);
|
||||
CASE_STRING(PROPERTY);
|
||||
CASE_STRING(FRAME);
|
||||
CASE_STRING(DEVICE_START_EMULATING);
|
||||
CASE_STRING(DEVICE_STOP_EMULATING);
|
||||
CASE_STRING(POINTER_MOTION);
|
||||
CASE_STRING(POINTER_MOTION_ABSOLUTE);
|
||||
CASE_STRING(POINTER_BUTTON);
|
||||
CASE_STRING(POINTER_SCROLL);
|
||||
CASE_STRING(POINTER_SCROLL_STOP);
|
||||
CASE_STRING(POINTER_SCROLL_CANCEL);
|
||||
CASE_STRING(POINTER_SCROLL_DISCRETE);
|
||||
CASE_STRING(KEYBOARD_KEY);
|
||||
CASE_STRING(TOUCH_DOWN);
|
||||
CASE_STRING(TOUCH_UP);
|
||||
CASE_STRING(TOUCH_MOTION);
|
||||
}
|
||||
#undef CASE_STRING
|
||||
assert(!"Unhandled ei event type");
|
||||
|
|
|
|||
|
|
@ -31,6 +31,11 @@
|
|||
|
||||
#include "util-mem.h"
|
||||
|
||||
enum peck_ei_mode {
|
||||
PECK_EI_PASSIVE = 20,
|
||||
PECK_EI_ACTIVE,
|
||||
};
|
||||
|
||||
/**
|
||||
* An enum to define basic server behavior in peck_dispatch_eis().
|
||||
* Where a flag is **not** set for any specific behaviour, that event will
|
||||
|
|
@ -134,6 +139,9 @@ struct peck;
|
|||
struct peck *
|
||||
peck_new(void);
|
||||
|
||||
struct peck *
|
||||
peck_new_context(enum peck_ei_mode ei_mode);
|
||||
|
||||
void _peck_mark(struct peck *peck, const char *func, int line);
|
||||
/** Add debug marker to the log output */
|
||||
#define peck_mark(peck_) _peck_mark(peck_, __func__, __LINE__)
|
||||
|
|
|
|||
|
|
@ -860,6 +860,43 @@ MUNIT_TEST(test_ei_disconnect_after_unbind_after_received)
|
|||
return MUNIT_OK;
|
||||
}
|
||||
|
||||
MUNIT_TEST(test_client_is_active)
|
||||
{
|
||||
_unref_(peck) *peck = peck_new_context(PECK_EI_ACTIVE);
|
||||
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_NONE);
|
||||
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_NONE);
|
||||
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTOCONNECT);
|
||||
peck_dispatch_until_stable(peck);
|
||||
|
||||
with_server(peck) {
|
||||
_unref_(eis_event) *connect = peck_eis_next_event(eis, EIS_EVENT_CLIENT_CONNECT);
|
||||
struct eis_client *client = eis_event_get_client(connect);
|
||||
munit_assert_true(eis_client_is_active(client));
|
||||
}
|
||||
|
||||
return MUNIT_OK;
|
||||
}
|
||||
|
||||
MUNIT_TEST(test_client_is_passive)
|
||||
{
|
||||
_unref_(peck) *peck = peck_new_context(PECK_EI_PASSIVE);
|
||||
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_NONE);
|
||||
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_NONE);
|
||||
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTOCONNECT);
|
||||
peck_dispatch_until_stable(peck);
|
||||
|
||||
with_server(peck) {
|
||||
_unref_(eis_event) *connect = peck_eis_next_event(eis, EIS_EVENT_CLIENT_CONNECT);
|
||||
struct eis_client *client = eis_event_get_client(connect);
|
||||
munit_assert_false(eis_client_is_active(client));
|
||||
}
|
||||
|
||||
return MUNIT_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Emulates the XWayland behavior for calling
|
||||
* xdotool mousemove_relative -- -1 10
|
||||
*/
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue