mirror of
https://gitlab.freedesktop.org/libinput/libei.git
synced 2026-01-05 02:00:15 +01:00
Add DeviceRegions to replace the pointer/touch ranges
This is required for supporting synergy/barrier and similar clients. Replacing the touch and pointer range we now have server-defined rectangular regions that specify the active zones for this device. For example, a dual-monitor EIS server would create two touch devices with one region each for the respective monitors - libei-generated touches would thus fall on the right area of the monitor. Or just one device with one region if the second screen should be inaccessible. A relative device may have multiple regions since it can reach all screens in the layout. This leaks the screen layout to libei but that is necessary for the functionality to work. A libei client may need to control devices through absolute coordinates and it needs to know where screen transitions from one to the next screen happen: +-----------++----------------+ | || | | B||Q | | |+----------------+ | | | A|P +-----------+ In the above example, position P is unreachable and a client that controls input on both screens must know that it cannot transition from A to P but it can transition from B to Q. Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
parent
12b04fdeb0
commit
56b82c2b8f
19 changed files with 574 additions and 226 deletions
|
|
@ -51,6 +51,7 @@ src_libei = [
|
|||
'src/libei-fd.c',
|
||||
'src/libei-proto.h',
|
||||
'src/libei-proto.c',
|
||||
'src/libei-region.c',
|
||||
'src/libei-stubs.c',
|
||||
proto_headers,
|
||||
]
|
||||
|
|
@ -100,6 +101,7 @@ src_libeis = [
|
|||
'src/libeis-device.c',
|
||||
'src/libeis-event.c',
|
||||
'src/libeis-log.c',
|
||||
'src/libeis-region.c',
|
||||
'src/libeis-seat.c',
|
||||
'src/libeis-socket.c',
|
||||
'src/libeis-fd.c',
|
||||
|
|
|
|||
|
|
@ -175,10 +175,14 @@ message DeviceAdded {
|
|||
uint32 keymap_size = 5;
|
||||
string name = 6;
|
||||
uint32 seatid = 7;
|
||||
uint32 pointer_width = 8;
|
||||
uint32 pointer_height = 9;
|
||||
uint32 touch_width = 10;
|
||||
uint32 touch_height = 11;
|
||||
}
|
||||
|
||||
message DeviceRegion {
|
||||
uint32 deviceid = 1;
|
||||
uint32 offset_x = 2;
|
||||
uint32 offset_y = 3;
|
||||
uint32 width = 4;
|
||||
uint32 height = 5;
|
||||
}
|
||||
|
||||
message DeviceAddedDone {
|
||||
|
|
@ -204,6 +208,7 @@ message ServerMessage {
|
|||
SeatAdded seat_added = 4;
|
||||
SeatRemoved seat_removed = 5;
|
||||
DeviceAdded device_added = 6;
|
||||
DeviceRegion device_region = 7;
|
||||
DeviceAddedDone device_added_done = 8;
|
||||
DeviceRemoved device_removed = 9;
|
||||
DeviceResumed device_resumed = 10;
|
||||
|
|
|
|||
|
|
@ -62,8 +62,13 @@ static void
|
|||
ei_device_destroy(struct ei_device *device)
|
||||
{
|
||||
struct ei_seat *seat = ei_device_get_seat(device);
|
||||
struct ei_region *region;
|
||||
|
||||
assert(device->state == EI_DEVICE_STATE_DEAD);
|
||||
|
||||
list_for_each_safe(region, &device->regions, link)
|
||||
ei_region_unref(region);
|
||||
|
||||
list_remove(&device->link);
|
||||
ei_keymap_unref(device->keymap);
|
||||
ei_seat_unref(seat);
|
||||
|
|
@ -108,6 +113,7 @@ ei_device_new(struct ei_seat *seat, uint32_t deviceid)
|
|||
device->id = deviceid;
|
||||
device->state = EI_DEVICE_STATE_NEW;
|
||||
device->name = xaprintf("unnamed device %d", device->id);
|
||||
list_init(&device->regions);
|
||||
|
||||
/* We have a ref to the seat to make sure our seat doesn't get
|
||||
* destroyed while a ref to the device is still alive.
|
||||
|
|
@ -126,7 +132,17 @@ ei_device_new(struct ei_seat *seat, uint32_t deviceid)
|
|||
void
|
||||
ei_device_done(struct ei_device *device)
|
||||
{
|
||||
ei_device_set_state(device, EI_DEVICE_STATE_SUSPENDED);
|
||||
ei_device_suspended(device);
|
||||
}
|
||||
|
||||
void
|
||||
ei_device_add_region(struct ei_device *device, struct ei_region *region)
|
||||
{
|
||||
if (device->state != EI_DEVICE_STATE_NEW)
|
||||
return;
|
||||
|
||||
ei_region_ref(region);
|
||||
list_append(&device->regions, ®ion->link);
|
||||
}
|
||||
|
||||
_public_
|
||||
|
|
@ -305,7 +321,6 @@ ei_device_suspended(struct ei_device *device)
|
|||
void
|
||||
ei_device_added(struct ei_device *device)
|
||||
{
|
||||
ei_device_suspended(device);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -322,20 +337,6 @@ ei_device_set_capabilities(struct ei_device *device,
|
|||
device->capabilities = capabilities;
|
||||
}
|
||||
|
||||
void
|
||||
ei_device_set_pointer_range(struct ei_device *device, uint32_t w, uint32_t h)
|
||||
{
|
||||
device->abs.dim.width = w;
|
||||
device->abs.dim.height = h;
|
||||
}
|
||||
|
||||
void
|
||||
ei_device_set_touch_range(struct ei_device *device, uint32_t w, uint32_t h)
|
||||
{
|
||||
device->touch.dim.width = w;
|
||||
device->touch.dim.height = h;
|
||||
}
|
||||
|
||||
_public_ bool
|
||||
ei_device_has_capability(struct ei_device *device,
|
||||
enum ei_device_capability cap)
|
||||
|
|
@ -350,28 +351,10 @@ ei_device_has_capability(struct ei_device *device,
|
|||
return false;
|
||||
}
|
||||
|
||||
_public_ uint32_t
|
||||
ei_device_pointer_get_width(struct ei_device *device)
|
||||
_public_ struct ei_region *
|
||||
ei_device_get_region(struct ei_device *device, size_t index)
|
||||
{
|
||||
return device->abs.dim.width;
|
||||
}
|
||||
|
||||
_public_ uint32_t
|
||||
ei_device_pointer_get_height(struct ei_device *device)
|
||||
{
|
||||
return device->abs.dim.height;
|
||||
}
|
||||
|
||||
_public_ uint32_t
|
||||
ei_device_touch_get_width(struct ei_device *device)
|
||||
{
|
||||
return device->touch.dim.width;
|
||||
}
|
||||
|
||||
_public_ uint32_t
|
||||
ei_device_touch_get_height(struct ei_device *device)
|
||||
{
|
||||
return device->touch.dim.height;
|
||||
return list_nth_entry(struct ei_region, &device->regions, link, index);
|
||||
}
|
||||
|
||||
_public_ void
|
||||
|
|
@ -403,9 +386,12 @@ ei_device_pointer_motion_absolute(struct ei_device *device,
|
|||
if (device->state != EI_DEVICE_STATE_RESUMED)
|
||||
return;
|
||||
|
||||
if (x < 0 || x >= device->abs.dim.width ||
|
||||
y < 0 || y >= device->abs.dim.height)
|
||||
return;
|
||||
struct ei_region *r;
|
||||
list_for_each(r, &device->regions, link) {
|
||||
if (!ei_region_contains(r, x, y)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ei_send_pointer_abs(device, x, y);
|
||||
}
|
||||
|
|
@ -513,25 +499,27 @@ ei_device_touch_new(struct ei_device *device)
|
|||
_public_ void
|
||||
ei_touch_down(struct ei_touch *touch, double x, double y)
|
||||
{
|
||||
struct ei_device *device = ei_touch_get_device(touch);
|
||||
|
||||
if (touch->state != TOUCH_IS_NEW) {
|
||||
struct ei_device *device = ei_touch_get_device(touch);
|
||||
log_bug_client(ei_device_get_context(device),
|
||||
"%s: device is not a keyboard\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (x < 0 || x >= touch->device->touch.dim.width ||
|
||||
y < 0 || y >= touch->device->touch.dim.height) {
|
||||
struct ei_device *device = ei_touch_get_device(touch);
|
||||
log_bug_client(ei_device_get_context(device),
|
||||
"%s: invalid x/y coordinates\n", __func__);
|
||||
touch->state = TOUCH_IS_UP;
|
||||
return;
|
||||
struct ei_region *r;
|
||||
list_for_each(r, &device->regions, link) {
|
||||
if (!ei_region_contains(r, x, y)) {
|
||||
log_bug_client(ei_device_get_context(device),
|
||||
"%s: invalid x/y coordinates\n", __func__);
|
||||
touch->state = TOUCH_IS_UP;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
touch->state = TOUCH_IS_DOWN;
|
||||
|
||||
ei_send_touch_down(touch->device, touch->tracking_id, x, y);
|
||||
ei_send_touch_down(device, touch->tracking_id, x, y);
|
||||
}
|
||||
|
||||
_public_ void
|
||||
|
|
@ -540,13 +528,15 @@ ei_touch_motion(struct ei_touch *touch, double x, double y)
|
|||
if (touch->state != TOUCH_IS_DOWN)
|
||||
return;
|
||||
|
||||
if (x < 0 || x >= touch->device->touch.dim.width ||
|
||||
y < 0 || y >= touch->device->touch.dim.height) {
|
||||
struct ei_device *device = ei_touch_get_device(touch);
|
||||
log_bug_client(ei_device_get_context(device),
|
||||
"%s: invalid x/y coordinates\n", __func__);
|
||||
ei_touch_up(touch);
|
||||
return;
|
||||
struct ei_device *device = ei_touch_get_device(touch);
|
||||
struct ei_region *r;
|
||||
list_for_each(r, &device->regions, link) {
|
||||
if (!ei_region_contains(r, x, y)) {
|
||||
log_bug_client(ei_device_get_context(device),
|
||||
"%s: invalid x/y coordinates\n", __func__);
|
||||
ei_touch_up(touch);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ei_send_touch_motion(touch->device, touch->tracking_id, x, y);
|
||||
|
|
|
|||
|
|
@ -104,6 +104,14 @@ enum ei_device_state {
|
|||
EI_DEVICE_STATE_DEAD,
|
||||
};
|
||||
|
||||
struct ei_region {
|
||||
struct object object;
|
||||
void *user_data;
|
||||
struct list link;
|
||||
uint32_t x, y;
|
||||
uint32_t width, height;
|
||||
};
|
||||
|
||||
struct ei_device {
|
||||
struct object object;
|
||||
void *user_data;
|
||||
|
|
@ -113,13 +121,7 @@ struct ei_device {
|
|||
uint32_t capabilities;
|
||||
char *name;
|
||||
|
||||
struct {
|
||||
struct dimensions dim;
|
||||
} abs;
|
||||
|
||||
struct {
|
||||
struct dimensions dim;
|
||||
} touch;
|
||||
struct list regions;
|
||||
|
||||
struct ei_keymap *keymap;
|
||||
};
|
||||
|
|
@ -197,6 +199,9 @@ ei_queue_seat_removed_event(struct ei_seat *seat);
|
|||
struct ei_device *
|
||||
ei_device_new(struct ei_seat *seat, uint32_t deviceid);
|
||||
|
||||
void
|
||||
ei_device_add_region(struct ei_device *device, struct ei_region *r);
|
||||
|
||||
void
|
||||
ei_device_done(struct ei_device *device);
|
||||
|
||||
|
|
@ -254,10 +259,6 @@ ei_device_set_seat(struct ei_device *device, const char *seat);
|
|||
void
|
||||
ei_device_set_capabilities(struct ei_device *device,
|
||||
uint32_t capabilities);
|
||||
void
|
||||
ei_device_set_pointer_range(struct ei_device *device, uint32_t w, uint32_t h);
|
||||
void
|
||||
ei_device_set_touch_range(struct ei_device *device, uint32_t w, uint32_t h);
|
||||
|
||||
void
|
||||
ei_device_set_keymap(struct ei_device *device,
|
||||
|
|
@ -265,6 +266,18 @@ ei_device_set_keymap(struct ei_device *device,
|
|||
int keymap_fd,
|
||||
size_t size);
|
||||
|
||||
struct ei_region *
|
||||
ei_region_new(void);
|
||||
|
||||
void
|
||||
ei_region_set_size(struct ei_region *region, uint32_t w, uint32_t h);
|
||||
|
||||
void
|
||||
ei_region_set_offset(struct ei_region *region, uint32_t x, uint32_t y);
|
||||
|
||||
bool
|
||||
ei_region_contains(struct ei_region *region, double x, double y);
|
||||
|
||||
_printf_(6, 7) void
|
||||
ei_log_msg(struct ei *ei,
|
||||
enum ei_log_priority priority,
|
||||
|
|
|
|||
|
|
@ -113,10 +113,6 @@ ei_proto_parse_message(struct brei_message *bmsg, size_t *consumed)
|
|||
.device_added.keymap_from_server = a->keymap_from_server,
|
||||
.device_added.keymap_size = a->keymap_size,
|
||||
.device_added.seatid = a->seatid,
|
||||
.device_added.pointer_width = a->pointer_width,
|
||||
.device_added.pointer_height = a->pointer_height,
|
||||
.device_added.touch_width = a->touch_width,
|
||||
.device_added.touch_height = a->touch_height,
|
||||
};
|
||||
if (a->keymap_type && a->keymap_from_server)
|
||||
msg->device_added.keymap_fd = brei_message_take_fd(bmsg);
|
||||
|
|
@ -131,6 +127,19 @@ ei_proto_parse_message(struct brei_message *bmsg, size_t *consumed)
|
|||
};
|
||||
}
|
||||
break;
|
||||
case SERVER_MESSAGE__MSG_DEVICE_REGION:
|
||||
{
|
||||
DeviceRegion *r = proto->device_region;
|
||||
*msg = (struct message) {
|
||||
.type = MESSAGE_DEVICE_REGION,
|
||||
.device_region.deviceid = r->deviceid,
|
||||
.device_region.x = r->offset_x,
|
||||
.device_region.y = r->offset_y,
|
||||
.device_region.w = r->width,
|
||||
.device_region.h = r->height,
|
||||
};
|
||||
}
|
||||
break;
|
||||
case SERVER_MESSAGE__MSG_DEVICE_REMOVED:
|
||||
{
|
||||
DeviceRemoved *r = proto->device_removed;
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ enum message_type {
|
|||
MESSAGE_SEAT_REMOVED,
|
||||
MESSAGE_DEVICE_ADDED,
|
||||
MESSAGE_DEVICE_ADDED_DONE,
|
||||
MESSAGE_DEVICE_REGION,
|
||||
MESSAGE_DEVICE_REMOVED,
|
||||
MESSAGE_DEVICE_RESUMED,
|
||||
MESSAGE_DEVICE_SUSPENDED,
|
||||
|
|
@ -54,6 +55,7 @@ message_type_to_string(enum message_type type)
|
|||
CASE_RETURN_STRING(MESSAGE_SEAT_REMOVED);
|
||||
CASE_RETURN_STRING(MESSAGE_DEVICE_ADDED);
|
||||
CASE_RETURN_STRING(MESSAGE_DEVICE_ADDED_DONE);
|
||||
CASE_RETURN_STRING(MESSAGE_DEVICE_REGION);
|
||||
CASE_RETURN_STRING(MESSAGE_DEVICE_REMOVED);
|
||||
CASE_RETURN_STRING(MESSAGE_DEVICE_RESUMED);
|
||||
CASE_RETURN_STRING(MESSAGE_DEVICE_SUSPENDED);
|
||||
|
|
@ -95,6 +97,13 @@ struct message {
|
|||
struct message_device_added_done {
|
||||
uint32_t deviceid;
|
||||
} device_added_done;
|
||||
struct message_device_region {
|
||||
uint32_t deviceid;
|
||||
uint32_t x;
|
||||
uint32_t y;
|
||||
uint32_t w;
|
||||
uint32_t h;
|
||||
} device_region;
|
||||
struct message_device_removed {
|
||||
uint32_t deviceid;
|
||||
} device_removed;
|
||||
|
|
|
|||
83
src/libei-region.c
Normal file
83
src/libei-region.c
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Copyright © 2020 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
|
||||
#include "libei-private.h"
|
||||
|
||||
static void
|
||||
ei_region_destroy(struct ei_region *region)
|
||||
{
|
||||
list_remove(®ion->link);
|
||||
}
|
||||
|
||||
_public_
|
||||
OBJECT_IMPLEMENT_REF(ei_region);
|
||||
_public_
|
||||
OBJECT_IMPLEMENT_UNREF(ei_region);
|
||||
static
|
||||
OBJECT_IMPLEMENT_CREATE(ei_region);
|
||||
_public_
|
||||
OBJECT_IMPLEMENT_GETTER(ei_region, user_data, void *);
|
||||
_public_
|
||||
OBJECT_IMPLEMENT_SETTER(ei_region, user_data, void *);
|
||||
_public_
|
||||
OBJECT_IMPLEMENT_GETTER(ei_region, x, uint32_t);
|
||||
_public_
|
||||
OBJECT_IMPLEMENT_GETTER(ei_region, y, uint32_t);
|
||||
_public_
|
||||
OBJECT_IMPLEMENT_GETTER(ei_region, width, uint32_t);
|
||||
_public_
|
||||
OBJECT_IMPLEMENT_GETTER(ei_region, height, uint32_t);
|
||||
|
||||
struct ei_region *
|
||||
ei_region_new(void)
|
||||
{
|
||||
struct ei_region *region = ei_region_create(NULL);
|
||||
|
||||
list_init(®ion->link);
|
||||
|
||||
return region;
|
||||
}
|
||||
|
||||
void
|
||||
ei_region_set_offset(struct ei_region *region, uint32_t x, uint32_t y)
|
||||
{
|
||||
region->x = x;
|
||||
region->y = y;
|
||||
}
|
||||
|
||||
void
|
||||
ei_region_set_size(struct ei_region *region, uint32_t w, uint32_t h)
|
||||
{
|
||||
region->width = w;
|
||||
region->height = h;
|
||||
}
|
||||
|
||||
bool
|
||||
ei_region_contains(struct ei_region *r, double x, double y)
|
||||
{
|
||||
return (x >= r->x && x < r->x + r->width &&
|
||||
y >= r->y && y < r->y + r->height);
|
||||
}
|
||||
31
src/libei.c
31
src/libei.c
|
|
@ -148,6 +148,7 @@ _public_
|
|||
OBJECT_IMPLEMENT_GETTER(ei, user_data, void *);
|
||||
|
||||
DEFINE_UNREF_CLEANUP_FUNC(ei_device);
|
||||
DEFINE_UNREF_CLEANUP_FUNC(ei_region);
|
||||
|
||||
_public_ struct ei *
|
||||
ei_new(void *user_data)
|
||||
|
|
@ -549,8 +550,6 @@ handle_msg_device_added(struct ei *ei, uint32_t deviceid,
|
|||
_unref_(ei_device) *device = ei_device_new(seat, deviceid);
|
||||
ei_device_set_name(device, name);
|
||||
ei_device_set_capabilities(device, capabilities);
|
||||
ei_device_set_pointer_range(device, pointer_width, pointer_height);
|
||||
ei_device_set_touch_range(device, touch_width, touch_height);
|
||||
if (keymap_from_server)
|
||||
ei_device_set_keymap(device, keymap_type,
|
||||
keymap_fd, keymap_sz);
|
||||
|
|
@ -595,6 +594,27 @@ handle_msg_device_added_done(struct ei *ei, uint32_t deviceid)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
handle_msg_device_region(struct ei *ei, uint32_t deviceid,
|
||||
uint32_t x, uint32_t y,
|
||||
uint32_t w, uint32_t h)
|
||||
{
|
||||
log_debug(ei, "Adding device region for %#x\n", deviceid);
|
||||
|
||||
struct ei_device *device = ei_find_device(ei, deviceid);
|
||||
if (!device)
|
||||
return 0;
|
||||
|
||||
_unref_(ei_region) *r = ei_region_new();
|
||||
ei_region_set_offset(r, x, y);
|
||||
ei_region_set_size(r, w, h);
|
||||
|
||||
ei_device_add_region(device, r);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
handle_msg_device_removed(struct ei *ei, uint32_t deviceid)
|
||||
{
|
||||
|
|
@ -792,6 +812,7 @@ connection_new_handle_msg(struct ei *ei, struct message *msg)
|
|||
case MESSAGE_SEAT_REMOVED:
|
||||
case MESSAGE_DEVICE_ADDED:
|
||||
case MESSAGE_DEVICE_ADDED_DONE:
|
||||
case MESSAGE_DEVICE_REGION:
|
||||
case MESSAGE_DEVICE_REMOVED:
|
||||
case MESSAGE_DEVICE_RESUMED:
|
||||
case MESSAGE_DEVICE_SUSPENDED:
|
||||
|
|
@ -819,6 +840,7 @@ connection_connecting_handle_msg(struct ei *ei, struct message *msg)
|
|||
case MESSAGE_SEAT_REMOVED:
|
||||
case MESSAGE_DEVICE_ADDED:
|
||||
case MESSAGE_DEVICE_ADDED_DONE:
|
||||
case MESSAGE_DEVICE_REGION:
|
||||
case MESSAGE_DEVICE_REMOVED:
|
||||
case MESSAGE_DEVICE_RESUMED:
|
||||
case MESSAGE_DEVICE_SUSPENDED:
|
||||
|
|
@ -869,6 +891,11 @@ connection_connected_handle_msg(struct ei *ei, struct message *msg)
|
|||
case MESSAGE_DEVICE_ADDED_DONE:
|
||||
rc = handle_msg_device_added_done(ei, msg->device_added_done.deviceid);
|
||||
break;
|
||||
case MESSAGE_DEVICE_REGION:
|
||||
rc = handle_msg_device_region(ei, msg->device_region.deviceid,
|
||||
msg->device_region.x, msg->device_region.y,
|
||||
msg->device_region.w, msg->device_region.h);
|
||||
break;
|
||||
case MESSAGE_DEVICE_REMOVED:
|
||||
rc = handle_msg_device_removed(ei, msg->device_removed.deviceid);
|
||||
break;
|
||||
|
|
|
|||
82
src/libei.h
82
src/libei.h
|
|
@ -98,6 +98,27 @@ struct ei_event;
|
|||
*/
|
||||
struct ei_keymap;
|
||||
|
||||
/**
|
||||
* @struct ei_region
|
||||
*
|
||||
* A rectangular region, defined by an x/y offset and a width and a height.
|
||||
* A region defines the area on an EIS desktop layout that is accessible by
|
||||
* this device - this region may not be the full area of the desktop.
|
||||
* Input events may only be sent for points within the regions.
|
||||
*
|
||||
* The use of regions is private to the EIS compositor and coordinates may not
|
||||
* match the size of the actual desktop. For example, a compositor may set a
|
||||
* 1920x1080 region to represent a 4K monitor and transparently map input
|
||||
* events into the respective true pixels.
|
||||
*
|
||||
* Absolute devices may have different regions, it is up to the libei client
|
||||
* to send events through the correct device to target the right pixel. For
|
||||
* example, a dual-head setup my have two absolute devices, the first with a
|
||||
* zero offset region spanning the first screen, the second with a nonzero
|
||||
* offset spanning the second screen.
|
||||
*/
|
||||
struct ei_region;
|
||||
|
||||
/**
|
||||
* @enum ei_device_capability
|
||||
*
|
||||
|
|
@ -761,37 +782,48 @@ bool
|
|||
ei_device_has_capability(struct ei_device *device,
|
||||
enum ei_device_capability cap);
|
||||
|
||||
/**
|
||||
* Return the requested width for an @ref EI_DEVICE_CAP_POINTER_ABSOLUTE
|
||||
* device. The width and height is constant after the @ref
|
||||
* EI_EVENT_DEVICE_ADDED event.
|
||||
*/
|
||||
uint32_t
|
||||
ei_device_pointer_get_width(struct ei_device *device);
|
||||
|
||||
/**
|
||||
* Return the requested height for an @ref EI_DEVICE_CAP_POINTER_ABSOLUTE
|
||||
* device. The width and height is constant after the @ref
|
||||
* EI_EVENT_DEVICE_ADDED event.
|
||||
* Obtain a region from the device. The number of regions is constant for a
|
||||
* device and the indices of any region remains the same for the lifetime of
|
||||
* the device.
|
||||
*
|
||||
* Regions are shared between all capabilities. Where two capabilities need
|
||||
* different region, the EIS implementation must create multiple devices with
|
||||
* individual capabilities and regions.
|
||||
*
|
||||
* This function returns the given region or NULL if the index is larger than
|
||||
* the number of regions available.
|
||||
*
|
||||
* This does not increase the refcount of the region. Use ei_region_ref() to
|
||||
* keep a reference beyond the immediate scope.
|
||||
*/
|
||||
uint32_t
|
||||
ei_device_pointer_get_height(struct ei_device *device);
|
||||
struct ei_region *
|
||||
ei_device_get_region(struct ei_device *device, size_t index);
|
||||
|
||||
/**
|
||||
* Return the requested width for an @ref EI_DEVICE_CAP_TOUCH
|
||||
* device. The width and height is constant after the @ref
|
||||
* EI_EVENT_DEVICE_ADDED event.
|
||||
*/
|
||||
uint32_t
|
||||
ei_device_touch_get_width(struct ei_device *device);
|
||||
struct ei_region *
|
||||
ei_region_ref(struct ei_region *region);
|
||||
|
||||
struct ei_region *
|
||||
ei_region_unref(struct ei_region *region);
|
||||
|
||||
void
|
||||
ei_region_set_user_data(struct ei_region *region, void *user_data);
|
||||
|
||||
void *
|
||||
ei_region_get_user_data(struct ei_region *region);
|
||||
|
||||
/**
|
||||
* Return the requested height for an @ref EI_DEVICE_CAP_TOUCH
|
||||
* device. The width and height is constant after the @ref
|
||||
* EI_EVENT_DEVICE_ADDED event.
|
||||
*/
|
||||
uint32_t
|
||||
ei_device_touch_get_height(struct ei_device *device);
|
||||
ei_region_get_x(struct ei_region *region);
|
||||
|
||||
uint32_t
|
||||
ei_region_get_y(struct ei_region *region);
|
||||
|
||||
uint32_t
|
||||
ei_region_get_width(struct ei_region *region);
|
||||
|
||||
uint32_t
|
||||
ei_region_get_height(struct ei_region *region);
|
||||
|
||||
/**
|
||||
* Return the keymap for this device or `NULL`. The keymap is constant for
|
||||
|
|
|
|||
|
|
@ -102,6 +102,11 @@ client_send_device_added(struct eis_client *client, struct eis_device *device)
|
|||
{
|
||||
int rc = eis_proto_send_device_added(client, device);
|
||||
|
||||
struct eis_region *r;
|
||||
list_for_each(r, &device->regions, link) {
|
||||
rc = eis_proto_send_device_region(client, device, r);
|
||||
}
|
||||
|
||||
if (rc >= 0)
|
||||
rc = eis_proto_send_device_added_done(client, device);
|
||||
return rc;
|
||||
|
|
|
|||
|
|
@ -121,6 +121,11 @@ eis_device_keyboard_get_keymap(struct eis_device *device)
|
|||
static void
|
||||
eis_device_destroy(struct eis_device *device)
|
||||
{
|
||||
struct eis_region *r;
|
||||
|
||||
list_for_each_safe(r, &device->regions, link)
|
||||
eis_region_unref(r);
|
||||
|
||||
eis_keymap_unref(device->keymap);
|
||||
free(device->name);
|
||||
}
|
||||
|
|
@ -175,6 +180,7 @@ eis_device_new(struct eis_seat *seat)
|
|||
device->name = xstrdup("unnamed device");
|
||||
device->capabilities = 0;
|
||||
device->state = EIS_DEVICE_STATE_NEW;
|
||||
list_init(&device->regions);
|
||||
|
||||
list_append(&seat->devices, &device->link);
|
||||
|
||||
|
|
@ -204,25 +210,18 @@ eis_device_configure_capability(struct eis_device *device, enum eis_device_capab
|
|||
}
|
||||
|
||||
_public_ void
|
||||
eis_device_configure_pointer_range(struct eis_device *device,
|
||||
uint32_t w, uint32_t h)
|
||||
eis_device_configure_region(struct eis_device *device,
|
||||
struct eis_region *region)
|
||||
{
|
||||
if (device->state != EIS_DEVICE_STATE_NEW)
|
||||
return;
|
||||
|
||||
device->abs.dim.width = w;
|
||||
device->abs.dim.height = h;
|
||||
}
|
||||
|
||||
_public_ void
|
||||
eis_device_configure_touch_range(struct eis_device *device,
|
||||
uint32_t w, uint32_t h)
|
||||
{
|
||||
if (device->state != EIS_DEVICE_STATE_NEW)
|
||||
if (region->added_to_device)
|
||||
return;
|
||||
|
||||
device->touch.dim.width = w;
|
||||
device->touch.dim.height = h;
|
||||
region->added_to_device = true;
|
||||
eis_region_ref(region);
|
||||
list_append(&device->regions, ®ion->link);
|
||||
}
|
||||
|
||||
_public_ void
|
||||
|
|
@ -289,30 +288,6 @@ eis_device_has_capability(struct eis_device *device,
|
|||
}
|
||||
|
||||
|
||||
_public_ uint32_t
|
||||
eis_device_pointer_get_width(struct eis_device *device)
|
||||
{
|
||||
return device->abs.dim.width;
|
||||
}
|
||||
|
||||
_public_ uint32_t
|
||||
eis_device_pointer_get_height(struct eis_device *device)
|
||||
{
|
||||
return device->abs.dim.height;
|
||||
}
|
||||
|
||||
_public_ uint32_t
|
||||
eis_device_touch_get_width(struct eis_device *device)
|
||||
{
|
||||
return device->touch.dim.width;
|
||||
}
|
||||
|
||||
_public_ uint32_t
|
||||
eis_device_touch_get_height(struct eis_device *device)
|
||||
{
|
||||
return device->touch.dim.height;
|
||||
}
|
||||
|
||||
int
|
||||
eis_device_pointer_rel(struct eis_device *device,
|
||||
double x, double y)
|
||||
|
|
@ -331,6 +306,19 @@ eis_device_pointer_rel(struct eis_device *device,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
eis_device_in_region(struct eis_device *device, double x, double y)
|
||||
{
|
||||
struct eis_region *r;
|
||||
|
||||
list_for_each(r, &device->regions, link) {
|
||||
if (eis_region_contains(r, x, y))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int
|
||||
eis_device_pointer_abs(struct eis_device *device,
|
||||
double x, double y)
|
||||
|
|
@ -344,8 +332,7 @@ eis_device_pointer_abs(struct eis_device *device,
|
|||
if (device->state != EIS_DEVICE_STATE_RESUMED)
|
||||
return -EINVAL;
|
||||
|
||||
if (x < 0 || x >= device->abs.dim.width ||
|
||||
y < 0 || y >= device->abs.dim.height)
|
||||
if (!eis_device_in_region(device, x, y))
|
||||
return -EINVAL;
|
||||
|
||||
eis_queue_pointer_abs_event(device, x, y);
|
||||
|
|
|
|||
|
|
@ -112,6 +112,14 @@ enum eis_device_state {
|
|||
EIS_DEVICE_STATE_DEAD,
|
||||
};
|
||||
|
||||
struct eis_region {
|
||||
struct object object;
|
||||
void *user_data;
|
||||
bool added_to_device;
|
||||
struct list link;
|
||||
uint32_t x, y;
|
||||
uint32_t width, height;
|
||||
};
|
||||
|
||||
struct eis_device {
|
||||
struct object object; /* parent is ei_seat, and we have a ref to it */
|
||||
|
|
@ -122,12 +130,7 @@ struct eis_device {
|
|||
uint32_t capabilities;
|
||||
void *user_data;
|
||||
|
||||
struct {
|
||||
struct dimensions dim;
|
||||
} abs;
|
||||
struct {
|
||||
struct dimensions dim;
|
||||
} touch;
|
||||
struct list regions;
|
||||
|
||||
struct eis_keymap *keymap;
|
||||
};
|
||||
|
|
@ -211,13 +214,6 @@ eis_seat_bind(struct eis_seat *seat, uint32_t cap);
|
|||
void
|
||||
eis_seat_unbind(struct eis_seat *seat);
|
||||
|
||||
void
|
||||
eis_device_set_pointer_range(struct eis_device *device,
|
||||
uint32_t w, uint32_t h);
|
||||
void
|
||||
eis_device_set_touch_range(struct eis_device *device,
|
||||
uint32_t w, uint32_t h);
|
||||
|
||||
void
|
||||
eis_device_set_client_keymap(struct eis_device *device,
|
||||
enum eis_keymap_type type,
|
||||
|
|
@ -253,6 +249,9 @@ eis_device_touch(struct eis_device *device, uint32_t touchid,
|
|||
void
|
||||
eis_device_closed_by_client(struct eis_device *device);
|
||||
|
||||
bool
|
||||
eis_region_contains(struct eis_region *r, double x, double y);
|
||||
|
||||
struct eis_event *
|
||||
eis_event_new_for_client(struct eis_client *client);
|
||||
|
||||
|
|
|
|||
|
|
@ -60,13 +60,14 @@ log_wire_message(struct eis *eis, const ServerMessage *msg)
|
|||
|
||||
switch (msg->msg_case) {
|
||||
case SERVER_MESSAGE__MSG__NOT_SET:
|
||||
abort();
|
||||
assert(!"SERVER_MESSAGE__MSG__NOT_SET");
|
||||
MSG_STRING_CASE(CONNECTED);
|
||||
MSG_STRING_CASE(DISCONNECTED);
|
||||
MSG_STRING_CASE(SEAT_ADDED);
|
||||
MSG_STRING_CASE(SEAT_REMOVED);
|
||||
MSG_STRING_CASE(DEVICE_ADDED);
|
||||
MSG_STRING_CASE(DEVICE_ADDED_DONE);
|
||||
MSG_STRING_CASE(DEVICE_REGION);
|
||||
MSG_STRING_CASE(DEVICE_REMOVED);
|
||||
MSG_STRING_CASE(DEVICE_RESUMED);
|
||||
MSG_STRING_CASE(DEVICE_SUSPENDED);
|
||||
|
|
@ -193,12 +194,6 @@ eis_proto_send_device_added(struct eis_client *client, struct eis_device *device
|
|||
/* it's NULL anyway */
|
||||
added.keymap_from_server = true;
|
||||
}
|
||||
added.seatid = seat->id;
|
||||
|
||||
added.pointer_width = device->abs.dim.width;
|
||||
added.pointer_height = device->abs.dim.height;
|
||||
added.touch_width = device->touch.dim.width;
|
||||
added.touch_height = device->touch.dim.height;
|
||||
|
||||
msg.device_added = &added;
|
||||
msg.msg_case = SERVER_MESSAGE__MSG_DEVICE_ADDED;
|
||||
|
|
@ -220,6 +215,25 @@ eis_proto_send_device_added_done(struct eis_client *client, struct eis_device *d
|
|||
return eis_proto_send_msg(client, &msg);
|
||||
}
|
||||
|
||||
int
|
||||
eis_proto_send_device_region(struct eis_client *client, struct eis_device *device,
|
||||
const struct eis_region *r)
|
||||
{
|
||||
ServerMessage msg = SERVER_MESSAGE__INIT;
|
||||
DeviceRegion region = DEVICE_REGION__INIT;
|
||||
|
||||
region.deviceid = device->id;
|
||||
region.offset_x = r->x;
|
||||
region.offset_y = r->y;
|
||||
region.width = r->width;
|
||||
region.height = r->height;
|
||||
|
||||
msg.device_region = ®ion;
|
||||
msg.msg_case = SERVER_MESSAGE__MSG_DEVICE_REGION;
|
||||
|
||||
return eis_proto_send_msg(client, &msg);
|
||||
}
|
||||
|
||||
int
|
||||
eis_proto_send_device_removed(struct eis_client *client, struct eis_device *device)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -168,6 +168,10 @@ eis_proto_send_device_added(struct eis_client *client,
|
|||
int
|
||||
eis_proto_send_device_added_done(struct eis_client *client,
|
||||
struct eis_device *device);
|
||||
int
|
||||
eis_proto_send_device_region(struct eis_client *client,
|
||||
struct eis_device *device,
|
||||
const struct eis_region *region);
|
||||
|
||||
int
|
||||
eis_proto_send_device_removed(struct eis_client *client,
|
||||
|
|
|
|||
75
src/libeis-region.c
Normal file
75
src/libeis-region.c
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright © 2020 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "libeis-private.h"
|
||||
|
||||
static void
|
||||
eis_region_destroy(struct eis_region *region)
|
||||
{
|
||||
list_remove(®ion->link);
|
||||
}
|
||||
|
||||
_public_
|
||||
OBJECT_IMPLEMENT_REF(eis_region);
|
||||
_public_
|
||||
OBJECT_IMPLEMENT_UNREF(eis_region);
|
||||
_public_
|
||||
OBJECT_IMPLEMENT_GETTER(eis_region, user_data, void *);
|
||||
_public_
|
||||
OBJECT_IMPLEMENT_SETTER(eis_region, user_data, void *);
|
||||
|
||||
static
|
||||
OBJECT_IMPLEMENT_CREATE(eis_region);
|
||||
|
||||
_public_ struct eis_region *
|
||||
eis_region_new(void)
|
||||
{
|
||||
struct eis_region *region = eis_region_create(NULL);
|
||||
|
||||
list_init(®ion->link);
|
||||
|
||||
return region;
|
||||
}
|
||||
|
||||
_public_ void
|
||||
eis_region_set_offset(struct eis_region *region, uint32_t x, uint32_t y)
|
||||
{
|
||||
region->x = x;
|
||||
region->y = y;
|
||||
}
|
||||
|
||||
_public_ void
|
||||
eis_region_set_size(struct eis_region *region, uint32_t w, uint32_t h)
|
||||
{
|
||||
region->width = w;
|
||||
region->height = h;
|
||||
}
|
||||
|
||||
bool
|
||||
eis_region_contains(struct eis_region *r, double x, double y)
|
||||
{
|
||||
return (x >= r->x && x < r->x + r->width &&
|
||||
y >= r->y && y < r->y + r->height);
|
||||
}
|
||||
110
src/libeis.h
110
src/libeis.h
|
|
@ -48,6 +48,30 @@ struct eis_seat;
|
|||
struct eis_event;
|
||||
struct eis_keymap;
|
||||
|
||||
/**
|
||||
* @struct ei_region
|
||||
*
|
||||
* A rectangular region, defined by an x/y offset and a width and a height.
|
||||
* A region defines the area on an EIS desktop layout that is accessible by
|
||||
* this device - this region may not be the full area of the desktop.
|
||||
* Input events may only be sent for points within the regions.
|
||||
*
|
||||
* The use of regions is private to the EIS compositor and coordinates do not
|
||||
* need match the size of the actual desktop. For example, a compositor may
|
||||
* set a 1920x1080 region to represent a 4K monitor and transparently map
|
||||
* input events into the respective true pixels.
|
||||
*
|
||||
* Absolute devices may have different regions, it is up to the libei client
|
||||
* to send events through the correct device to target the right pixel. For
|
||||
* example, a dual-head setup my have two absolute devices, the first with a
|
||||
* zero offset region spanning the first screen, the second with a nonzero
|
||||
* offset spanning the second screen.
|
||||
*
|
||||
* Regions must be assigned when the device is created and are static for the
|
||||
* lifetime of the device.
|
||||
*/
|
||||
struct eis_region;
|
||||
|
||||
enum eis_device_capability {
|
||||
EIS_DEVICE_CAP_POINTER = 1,
|
||||
EIS_DEVICE_CAP_POINTER_ABSOLUTE,
|
||||
|
|
@ -418,12 +442,40 @@ eis_device_configure_name(struct eis_device *device, const char *name);
|
|||
void
|
||||
eis_device_configure_capability(struct eis_device *device, enum eis_device_capability cap);
|
||||
|
||||
/**
|
||||
* Add a new region to this device. The caller should immediately call
|
||||
* ei_region_unref() after this call to release any references it has to the
|
||||
* region.
|
||||
*
|
||||
* Adding the same region twice will be silently ignored.
|
||||
*/
|
||||
void
|
||||
eis_device_configure_pointer_range(struct eis_device *device,
|
||||
uint32_t w, uint32_t h);
|
||||
eis_device_configure_region(struct eis_device *device,
|
||||
struct eis_region *region);
|
||||
|
||||
/**
|
||||
* Create a new region with an initial refcount of 1.
|
||||
*/
|
||||
struct eis_region *
|
||||
eis_region_new(void);
|
||||
|
||||
void
|
||||
eis_device_configure_touch_range(struct eis_device *device,
|
||||
uint32_t w, uint32_t h);
|
||||
eis_region_set_size(struct eis_region *region, uint32_t w, uint32_t h);
|
||||
|
||||
void
|
||||
eis_region_set_offset(struct eis_region *region, uint32_t x, uint32_t y);
|
||||
|
||||
struct eis_region *
|
||||
eis_region_ref(struct eis_region *region);
|
||||
|
||||
struct eis_region *
|
||||
eis_region_unref(struct eis_region *region);
|
||||
|
||||
void *
|
||||
eis_region_get_user_data(struct eis_region *region);
|
||||
|
||||
void
|
||||
eis_region_set_user_data(struct eis_region *region, void *user_data);
|
||||
|
||||
/**
|
||||
* Add this device to its seat and notify the client of the device's
|
||||
|
|
@ -467,56 +519,6 @@ eis_device_suspend(struct eis_device *device);
|
|||
void
|
||||
eis_device_resume(struct eis_device *device);
|
||||
|
||||
/**
|
||||
* Get the width of the absolute pointer device in logical
|
||||
* pixels. The allowable range for absolute pointer motion is
|
||||
* [0, max) for each axis, i.e. zero inclusive, max exclusive. Coordinates
|
||||
* outside this range may be discarded or clipped silently by the library.
|
||||
*
|
||||
* The pointer range is constant. Where the pointer range is no longer
|
||||
* applicable, the client needs to remove the device and create and add a
|
||||
* new device with the updated pointer range.
|
||||
*
|
||||
* The server may use this in mapping heuristics. For example, a pointer
|
||||
* device with a pixel range of 1920x1200 **may** be automatically mapped by
|
||||
* the server to the monitor with this range, or a pointer device with a
|
||||
* ratio of R **may** be mapped to the monitor with the same ratio. This is
|
||||
* not a guarantee, the mapping policy is a private implementation detail
|
||||
* in the server. It is assumed that the client has other communication
|
||||
* channels (e.g. Wayland) to obtain the pointer range it needs to emulate
|
||||
* input on a device and channels to notify the server of desired mappings
|
||||
* (e.g. gsettings).
|
||||
*
|
||||
* It is a client bug to send pointer values outside this range.
|
||||
*
|
||||
* It is a server bug to call this function on a device without the @ref
|
||||
* EIS_DEVICE_CAP_POINTER_ABSOLUTE capability.
|
||||
*
|
||||
* @return The new width in logical pixels
|
||||
*/
|
||||
uint32_t
|
||||
eis_device_pointer_get_width(struct eis_device *device);
|
||||
|
||||
/**
|
||||
* @see eis_device_pointer_get_width
|
||||
*/
|
||||
uint32_t
|
||||
eis_device_pointer_get_height(struct eis_device *device);
|
||||
|
||||
/**
|
||||
* @see eis_device_pointer_get_width
|
||||
*/
|
||||
uint32_t
|
||||
eis_device_touch_get_width(struct eis_device *device);
|
||||
|
||||
/**
|
||||
* @param device The EI device
|
||||
*
|
||||
* @see eis_device_touch_get_width
|
||||
*/
|
||||
uint32_t
|
||||
eis_device_touch_get_height(struct eis_device *device);
|
||||
|
||||
/**
|
||||
* Create a new keymap of the given @a type. This keymap does not immediately
|
||||
* apply to the device, use eis_device_keyboard_set_keymap() to apply
|
||||
|
|
|
|||
|
|
@ -463,10 +463,14 @@ static inline struct eis_device *
|
|||
peck_eis_create_pointer_absolute(struct peck *peck, struct eis_seat *seat, const char *name)
|
||||
{
|
||||
struct eis_device *device = eis_device_new(seat);
|
||||
_unref_(eis_region) *region = eis_region_new();
|
||||
|
||||
eis_region_set_offset(region, 0, 0);
|
||||
eis_region_set_size(region, 1920, 1080);
|
||||
|
||||
eis_device_configure_name(device, name);
|
||||
eis_device_configure_capability(device, EIS_DEVICE_CAP_POINTER_ABSOLUTE);
|
||||
eis_device_configure_pointer_range(device, 1920, 1080); /* FIXME */
|
||||
eis_device_configure_region(device, region);
|
||||
eis_device_add(device);
|
||||
|
||||
if (!peck->eis_abs)
|
||||
|
|
@ -494,10 +498,14 @@ static inline struct eis_device *
|
|||
peck_eis_create_touch(struct peck *peck, struct eis_seat *seat, const char *name)
|
||||
{
|
||||
struct eis_device *device = eis_device_new(seat);
|
||||
_unref_(eis_region) *region = eis_region_new();
|
||||
|
||||
eis_region_set_offset(region, 0, 0);
|
||||
eis_region_set_size(region, 1920, 1080);
|
||||
|
||||
eis_device_configure_name(device, name);
|
||||
eis_device_configure_capability(device, EIS_DEVICE_CAP_TOUCH);
|
||||
eis_device_configure_touch_range(device, 1920, 1080); /* FIXME */
|
||||
eis_device_configure_region(device, region);
|
||||
eis_device_add(device);
|
||||
|
||||
if (!peck->eis_touch)
|
||||
|
|
|
|||
|
|
@ -268,6 +268,7 @@ DEFINE_UNREF_CLEANUP_FUNC(ei_device);
|
|||
DEFINE_UNREF_CLEANUP_FUNC(ei_touch);
|
||||
DEFINE_UNREF_CLEANUP_FUNC(ei_keymap);
|
||||
DEFINE_UNREF_CLEANUP_FUNC(ei_seat);
|
||||
DEFINE_UNREF_CLEANUP_FUNC(ei_region);
|
||||
|
||||
DEFINE_UNREF_CLEANUP_FUNC(eis);
|
||||
DEFINE_UNREF_CLEANUP_FUNC(eis_client);
|
||||
|
|
@ -275,6 +276,7 @@ DEFINE_UNREF_CLEANUP_FUNC(eis_event);
|
|||
DEFINE_UNREF_CLEANUP_FUNC(eis_device);
|
||||
DEFINE_UNREF_CLEANUP_FUNC(eis_keymap);
|
||||
DEFINE_UNREF_CLEANUP_FUNC(eis_seat);
|
||||
DEFINE_UNREF_CLEANUP_FUNC(eis_region);
|
||||
|
||||
/* Macros intended just for readability to make it more obvious which part
|
||||
of a test handles server vs client */
|
||||
|
|
|
|||
|
|
@ -263,20 +263,92 @@ MUNIT_TEST(test_ei_device_pointer_rel)
|
|||
return MUNIT_OK;
|
||||
}
|
||||
|
||||
MUNIT_TEST(test_ei_device_regions)
|
||||
{
|
||||
_unref_(peck) *peck = peck_new();
|
||||
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL);
|
||||
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTODEVICES);
|
||||
peck_dispatch_until_stable(peck);
|
||||
|
||||
with_server(peck) {
|
||||
struct eis_seat *seat = peck_eis_get_default_seat(peck);
|
||||
_unref_(eis_device) *device = eis_device_new(seat);
|
||||
eis_device_configure_name(device, __func__);
|
||||
eis_device_configure_capability(device, EIS_DEVICE_CAP_POINTER_ABSOLUTE);
|
||||
|
||||
/* nothing cares about the actual values, so we're just
|
||||
* checking for correct passthrough here */
|
||||
_unref_(eis_region) *r1 = eis_region_new();
|
||||
eis_region_set_size(r1, 100, 200);
|
||||
eis_region_set_offset(r1, 300, 400);
|
||||
eis_device_configure_region(device, r1);
|
||||
|
||||
_unref_(eis_region) *r2 = eis_region_new();
|
||||
eis_region_set_size(r2, 500, 600);
|
||||
eis_region_set_offset(r2, 700, 800);
|
||||
eis_device_configure_region(device, r2);
|
||||
|
||||
_unref_(eis_region) *r3 = eis_region_new();
|
||||
eis_region_set_size(r3, 900, 1000);
|
||||
eis_region_set_offset(r3, 1100, 1200);
|
||||
eis_device_configure_region(device, r3);
|
||||
|
||||
/* Add the same region twice, should be ignored */
|
||||
eis_device_configure_region(device, r3);
|
||||
|
||||
eis_device_add(device);
|
||||
}
|
||||
|
||||
peck_dispatch_until_stable(peck);
|
||||
|
||||
with_client(peck) {
|
||||
struct ei_device *device = peck_ei_get_default_pointer_absolute(peck);
|
||||
struct ei_region *r;
|
||||
|
||||
r = ei_device_get_region(device, 0);
|
||||
munit_assert_int(ei_region_get_width(r), ==, 100);
|
||||
munit_assert_int(ei_region_get_height(r), ==, 200);
|
||||
munit_assert_int(ei_region_get_x(r), ==, 300);
|
||||
munit_assert_int(ei_region_get_y(r), ==, 400);
|
||||
|
||||
r = ei_device_get_region(device, 1);
|
||||
munit_assert_int(ei_region_get_width(r), ==, 500);
|
||||
munit_assert_int(ei_region_get_height(r), ==, 600);
|
||||
munit_assert_int(ei_region_get_x(r), ==, 700);
|
||||
munit_assert_int(ei_region_get_y(r), ==, 800);
|
||||
|
||||
r = ei_device_get_region(device, 2);
|
||||
munit_assert_int(ei_region_get_width(r), ==, 900);
|
||||
munit_assert_int(ei_region_get_height(r), ==, 1000);
|
||||
munit_assert_int(ei_region_get_x(r), ==, 1100);
|
||||
munit_assert_int(ei_region_get_y(r), ==, 1200);
|
||||
|
||||
munit_assert_ptr_null(ei_device_get_region(device, 3));
|
||||
}
|
||||
|
||||
return MUNIT_OK;
|
||||
}
|
||||
|
||||
MUNIT_TEST(test_ei_device_pointer_abs)
|
||||
{
|
||||
_unref_(peck) *peck = peck_new();
|
||||
struct ei_device *device = NULL;
|
||||
uint32_t maxx = 0, maxy = 0;
|
||||
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL);
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_POINTER_ABSOLUTE);
|
||||
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTODEVICES);
|
||||
peck_dispatch_until_stable(peck);
|
||||
|
||||
/* FIXME: missing the currently unimplemented region checks */
|
||||
|
||||
with_client(peck) {
|
||||
device = peck_ei_get_default_pointer_absolute(peck);
|
||||
|
||||
/* We know our default device has one region */
|
||||
struct ei_region *r = ei_device_get_region(device, 0);
|
||||
maxx = ei_region_get_x(r) + ei_region_get_width(r);
|
||||
maxy = ei_region_get_y(r) + ei_region_get_height(r);
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
ei_device_pointer_motion_absolute(device, 1 * i , 2 + i);
|
||||
}
|
||||
|
|
@ -294,8 +366,8 @@ MUNIT_TEST(test_ei_device_pointer_abs)
|
|||
|
||||
with_client(peck) {
|
||||
/* outside of pointer range, expect to be discarded */
|
||||
ei_device_pointer_motion_absolute(device, 1920, 1200);
|
||||
ei_device_pointer_motion_absolute(device, 2000, 1400);
|
||||
ei_device_pointer_motion_absolute(device, maxx + 1, maxy/2);
|
||||
ei_device_pointer_motion_absolute(device, maxx/2 , maxy + 1);
|
||||
}
|
||||
|
||||
peck_dispatch_until_stable(peck);
|
||||
|
|
@ -328,16 +400,21 @@ MUNIT_TEST(test_ei_device_touch)
|
|||
{
|
||||
_unref_(peck) *peck = peck_new();
|
||||
struct ei_device *device = NULL;
|
||||
uint32_t maxx = 0, maxy = 0;
|
||||
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL);
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_TOUCH);
|
||||
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTODEVICES);
|
||||
peck_dispatch_until_stable(peck);
|
||||
|
||||
/* FIXME: missing the currently unimplemented region checks */
|
||||
|
||||
with_client(peck) {
|
||||
device = peck_ei_get_default_touch(peck);
|
||||
/* We know our default device has one region */
|
||||
|
||||
struct ei_region *r = ei_device_get_region(device, 0);
|
||||
maxx = ei_region_get_x(r) + ei_region_get_width(r);
|
||||
maxy = ei_region_get_y(r) + ei_region_get_height(r);
|
||||
|
||||
_unref_(ei_touch) *t = ei_device_touch_new(device);
|
||||
ei_touch_down(t, 1, 2);
|
||||
ei_touch_motion(t, 200, 500);
|
||||
|
|
@ -360,8 +437,13 @@ MUNIT_TEST(test_ei_device_touch)
|
|||
with_client(peck) {
|
||||
_unref_(ei_touch) *t = ei_device_touch_new(device);
|
||||
/* outside clip range, expect touch to be dropped */
|
||||
ei_touch_down(t, 1920, 1200);
|
||||
ei_touch_motion(t, 1920, 1000);
|
||||
ei_touch_down(t, maxx + 1, maxy/2);
|
||||
ei_touch_motion(t, maxx + 1, maxy/3);
|
||||
ei_touch_up(t);
|
||||
|
||||
/* outside clip range, expect touch to be dropped */
|
||||
ei_touch_down(t, maxx/2, maxy + 1);
|
||||
ei_touch_motion(t, maxx/3, maxy + 1);
|
||||
ei_touch_up(t);
|
||||
}
|
||||
|
||||
|
|
@ -375,7 +457,7 @@ MUNIT_TEST(test_ei_device_touch)
|
|||
_unref_(ei_touch) *t = ei_device_touch_new(device);
|
||||
ei_touch_down(t, 100, 200);
|
||||
/* outside allowed range, generates a touch up */
|
||||
ei_touch_motion(t, 1950, 200);
|
||||
ei_touch_motion(t, maxx + 1, 200);
|
||||
ei_touch_up(t);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue