mirror of
https://gitlab.freedesktop.org/libinput/libei.git
synced 2026-05-04 21:18:04 +02:00
Add a mapping_id to the regions
This allows a caller to match up a region with other data, e.g. in the remote desktop case the same mapping_id can be assigned to the pipewire stream that represents that output. Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
parent
2fbd22984f
commit
76652350cc
14 changed files with 187 additions and 12 deletions
|
|
@ -555,7 +555,7 @@
|
|||
</event>
|
||||
</interface>
|
||||
|
||||
<interface name="ei_device" version="1">
|
||||
<interface name="ei_device" version="2">
|
||||
<description summary="device object">
|
||||
An ei_device represents a single logical input devices. Like physical input devices
|
||||
an ei_device may have multiple capabilities and may e.g. function as pointer
|
||||
|
|
@ -871,6 +871,30 @@
|
|||
<arg name="serial" type="uint32" summary="this event's serial number"/>
|
||||
<arg name="timestamp" type="uint64" summary="timestamp in microseconds"/>
|
||||
</event>
|
||||
|
||||
<!-- ei_device events version 2 -->
|
||||
|
||||
<event name="region_mapping_id" since="2">
|
||||
<description summary="region id notification">
|
||||
Notifies the client that the region specified in the next ei_device.region
|
||||
event is to be assigned the given mapping_id.
|
||||
|
||||
This ID can be used by the client to identify an external resource that has a
|
||||
relationship with this region.
|
||||
For example the client may receive a data stream with the video
|
||||
data that this region represents. By attaching the same identifier to the data
|
||||
stream and this region the EIS implementation can inform the client
|
||||
that the video data stream and the region represent paired data.
|
||||
|
||||
This event is optional and sent immediately after object creation but before
|
||||
the corresponding ei_device.region event. Where a device has multiple regions,
|
||||
this event may be sent zero or one time for each region.
|
||||
It is a protocol violation to send this event after the ei_device.done event or
|
||||
to send this event without a corresponding following ei_device.region event.
|
||||
</description>
|
||||
<arg name="mapping_id" type="string" summary="region mapping id"/>
|
||||
</event>
|
||||
|
||||
</interface>
|
||||
|
||||
<interface name="ei_pointer" version="1">
|
||||
|
|
|
|||
|
|
@ -91,6 +91,7 @@ ei_device_destroy(struct ei_device *device)
|
|||
ei_keyboard_unref(device->keyboard);
|
||||
ei_seat_unref(seat);
|
||||
free(device->name);
|
||||
free(device->pending_region_mapping_id);
|
||||
}
|
||||
|
||||
_public_
|
||||
|
|
@ -194,11 +195,26 @@ handle_msg_region(struct ei_device *device, uint32_t x, uint32_t y,
|
|||
ei_region_set_offset(r, x, y);
|
||||
ei_region_set_size(r, w, h);
|
||||
ei_region_set_physical_scale(r, scale);
|
||||
|
||||
_cleanup_free_ char *mapping_id = steal(&device->pending_region_mapping_id);
|
||||
if (mapping_id)
|
||||
ei_region_set_mapping_id(r, mapping_id);
|
||||
|
||||
ei_device_add_region(device, r);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct brei_result *
|
||||
handle_msg_region_mapping_id(struct ei_device *device, const char *mapping_id)
|
||||
{
|
||||
if (device->pending_region_mapping_id)
|
||||
return brei_result_new(EI_CONNECTION_DISCONNECT_REASON_PROTOCOL,
|
||||
"EIS sent the region mapping_id twice");
|
||||
device->pending_region_mapping_id = xstrdup(mapping_id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct brei_result *
|
||||
handle_msg_done(struct ei_device *device)
|
||||
{
|
||||
|
|
@ -464,6 +480,8 @@ static const struct ei_device_interface interface = {
|
|||
.stop_emulating = handle_msg_stop_emulating,
|
||||
.frame = handle_msg_frame,
|
||||
.interface = handle_msg_interface,
|
||||
/* v2 */
|
||||
.region_mapping_id = handle_msg_region_mapping_id,
|
||||
};
|
||||
|
||||
const struct ei_device_interface *
|
||||
|
|
|
|||
|
|
@ -86,6 +86,8 @@ struct ei_device {
|
|||
} scroll_state;
|
||||
|
||||
struct ei_keymap *keymap;
|
||||
|
||||
char *pending_region_mapping_id;
|
||||
};
|
||||
|
||||
struct ei_keymap {
|
||||
|
|
|
|||
|
|
@ -24,12 +24,14 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
#include "util-strings.h"
|
||||
|
||||
#include "libei-private.h"
|
||||
|
||||
static void
|
||||
ei_region_destroy(struct ei_region *region)
|
||||
{
|
||||
free(region->mapping_id);
|
||||
list_remove(®ion->link);
|
||||
}
|
||||
|
||||
|
|
@ -54,6 +56,8 @@ OBJECT_IMPLEMENT_GETTER(ei_region, height, uint32_t);
|
|||
_public_
|
||||
OBJECT_IMPLEMENT_GETTER(ei_region, physical_scale, double);
|
||||
OBJECT_IMPLEMENT_SETTER(ei_region, physical_scale, double);
|
||||
_public_
|
||||
OBJECT_IMPLEMENT_GETTER(ei_region, mapping_id, const char *);
|
||||
|
||||
struct ei_region *
|
||||
ei_region_new(void)
|
||||
|
|
@ -80,6 +84,12 @@ ei_region_set_size(struct ei_region *region, uint32_t w, uint32_t h)
|
|||
region->height = h;
|
||||
}
|
||||
|
||||
void
|
||||
ei_region_set_mapping_id(struct ei_region *region, const char *mapping_id)
|
||||
{
|
||||
region->mapping_id = xstrdup(mapping_id);
|
||||
}
|
||||
|
||||
_public_ bool
|
||||
ei_region_contains(struct ei_region *r, double x, double y)
|
||||
{
|
||||
|
|
@ -103,17 +113,19 @@ ei_region_convert_point(struct ei_region *r, double *x, double *y)
|
|||
#include "util-munit.h"
|
||||
MUNIT_TEST(test_region_setters)
|
||||
{
|
||||
struct ei_region r = {0};
|
||||
_unref_(ei_region) *r = ei_region_new();
|
||||
|
||||
ei_region_set_size(&r, 1, 2);
|
||||
ei_region_set_offset(&r, 3, 4);
|
||||
ei_region_set_physical_scale(&r, 5.6);
|
||||
ei_region_set_size(r, 1, 2);
|
||||
ei_region_set_offset(r, 3, 4);
|
||||
ei_region_set_physical_scale(r, 5.6);
|
||||
ei_region_set_mapping_id(r, "foo");
|
||||
|
||||
munit_assert_int(ei_region_get_width(&r), ==, 1);
|
||||
munit_assert_int(ei_region_get_height(&r), ==, 2);
|
||||
munit_assert_int(ei_region_get_x(&r), ==, 3);
|
||||
munit_assert_int(ei_region_get_y(&r), ==, 4);
|
||||
munit_assert_double(ei_region_get_physical_scale(&r), ==, 5.6);
|
||||
munit_assert_int(ei_region_get_width(r), ==, 1);
|
||||
munit_assert_int(ei_region_get_height(r), ==, 2);
|
||||
munit_assert_int(ei_region_get_x(r), ==, 3);
|
||||
munit_assert_int(ei_region_get_y(r), ==, 4);
|
||||
munit_assert_double(ei_region_get_physical_scale(r), ==, 5.6);
|
||||
munit_assert_string_equal(ei_region_get_mapping_id(r), "foo");
|
||||
|
||||
return MUNIT_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ struct ei_region {
|
|||
uint32_t x, y;
|
||||
uint32_t width, height;
|
||||
double physical_scale;
|
||||
char *mapping_id;
|
||||
};
|
||||
|
||||
struct ei_region *
|
||||
|
|
@ -47,3 +48,6 @@ ei_region_set_offset(struct ei_region *region, uint32_t x, uint32_t y);
|
|||
|
||||
void
|
||||
ei_region_set_physical_scale(struct ei_region *region, double scale);
|
||||
|
||||
void
|
||||
ei_region_set_mapping_id(struct ei_region *region, const char *mapping_id);
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ ei_create_context(bool is_sender, void *user_data)
|
|||
.ei_callback = VERSION_V(1),
|
||||
.ei_pingpong = VERSION_V(1),
|
||||
.ei_seat = VERSION_V(1),
|
||||
.ei_device = VERSION_V(1),
|
||||
.ei_device = VERSION_V(2),
|
||||
.ei_pointer = VERSION_V(1),
|
||||
.ei_pointer_absolute = VERSION_V(1),
|
||||
.ei_scroll = VERSION_V(1),
|
||||
|
|
|
|||
30
src/libei.h
30
src/libei.h
|
|
@ -1217,6 +1217,36 @@ ei_region_get_width(struct ei_region *region);
|
|||
uint32_t
|
||||
ei_region_get_height(struct ei_region *region);
|
||||
|
||||
/**
|
||||
* @ingroup libei-region
|
||||
*
|
||||
* Get the unique identifier (representing an external resource) that is
|
||||
* attached to this region, if any. This is only available if the EIS
|
||||
* implementation supports version 2 or later of the ei_device protocol
|
||||
* interface *and* the EIS implementation chooses to attach such an identifer to
|
||||
* the region.
|
||||
*
|
||||
* This ID can be used by the client to identify an external resource that has a
|
||||
* relationship with this region.
|
||||
*
|
||||
* For example the client may receive a data stream with the video
|
||||
* data that this region represents. By attaching the same identifier to the data
|
||||
* stream and this region the EIS implementation can inform the client
|
||||
* that the video data stream and the region represent paired data.
|
||||
* Note that in this example use-case, if the stream is resized
|
||||
* there may be a transition period where two regions have the same identifier -
|
||||
* the old region and the new region with the updated size. A client must be
|
||||
* able to handle the case where to mapping ids are identical.
|
||||
*
|
||||
* libei does not look at or modify the value of the mapping id. Because the ID is
|
||||
* assigned by the caller libei makes no guarantee that the ID is unique
|
||||
* and/or corresponds to any particular format.
|
||||
*
|
||||
* @since 1.1
|
||||
*/
|
||||
const char *
|
||||
ei_region_get_mapping_id(struct ei_region *region);
|
||||
|
||||
/**
|
||||
* @ingroup libei-region
|
||||
*
|
||||
|
|
|
|||
|
|
@ -444,7 +444,7 @@ eis_client_new(struct eis *eis, int fd)
|
|||
.ei_callback = VERSION_V(1),
|
||||
.ei_pingpong = VERSION_V(1),
|
||||
.ei_seat = VERSION_V(1),
|
||||
.ei_device = VERSION_V(1),
|
||||
.ei_device = VERSION_V(2),
|
||||
.ei_pointer = VERSION_V(1),
|
||||
.ei_pointer_absolute = VERSION_V(1),
|
||||
.ei_scroll = VERSION_V(1),
|
||||
|
|
|
|||
|
|
@ -819,6 +819,17 @@ eis_device_add(struct eis_device *device)
|
|||
if (device->type == EIS_DEVICE_TYPE_VIRTUAL) {
|
||||
struct eis_region *r;
|
||||
list_for_each(r, &device->regions, link) {
|
||||
if (r->mapping_id) {
|
||||
if (client->interface_versions.ei_device >= EIS_DEVICE_EVENT_REGION_MAPPING_ID_SINCE_VERSION) {
|
||||
rc = eis_device_event_region_mapping_id(device, r->mapping_id);
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
} else {
|
||||
/* If our client doesn't support mapping_id, drop it */
|
||||
free(r->mapping_id);
|
||||
r->mapping_id = NULL;
|
||||
}
|
||||
}
|
||||
rc = eis_device_event_region(device, r->x, r->y, r->width, r->height, r->physical_scale);
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
|
|
|
|||
|
|
@ -24,11 +24,13 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
#include "util-strings.h"
|
||||
#include "libeis-private.h"
|
||||
|
||||
static void
|
||||
eis_region_destroy(struct eis_region *region)
|
||||
{
|
||||
free(region->mapping_id);
|
||||
list_remove(®ion->link);
|
||||
if (!region->added_to_device)
|
||||
eis_device_unref(region->device);
|
||||
|
|
@ -52,6 +54,8 @@ _public_
|
|||
OBJECT_IMPLEMENT_GETTER(eis_region, height, uint32_t);
|
||||
_public_
|
||||
OBJECT_IMPLEMENT_GETTER(eis_region, physical_scale, double);
|
||||
_public_
|
||||
OBJECT_IMPLEMENT_GETTER(eis_region, mapping_id, const char *);
|
||||
|
||||
static
|
||||
OBJECT_IMPLEMENT_CREATE(eis_region);
|
||||
|
|
@ -109,6 +113,22 @@ eis_region_set_physical_scale(struct eis_region *region, double scale)
|
|||
region->physical_scale = scale;
|
||||
}
|
||||
|
||||
_public_ void
|
||||
eis_region_set_mapping_id(struct eis_region *region, const char *mapping_id)
|
||||
{
|
||||
if (region->added_to_device)
|
||||
return;
|
||||
|
||||
if (mapping_id == NULL) {
|
||||
struct eis_device *device = region->device;
|
||||
log_bug_client(eis_device_get_context(device),
|
||||
"%s: a region's mapping_id must not be NULL", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
region->mapping_id = xstrdup(mapping_id);
|
||||
}
|
||||
|
||||
_public_ void
|
||||
eis_region_add(struct eis_region *region)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -38,4 +38,5 @@ struct eis_region {
|
|||
uint32_t x, y;
|
||||
uint32_t width, height;
|
||||
double physical_scale;
|
||||
char *mapping_id;
|
||||
};
|
||||
|
|
|
|||
47
src/libeis.h
47
src/libeis.h
|
|
@ -920,6 +920,53 @@ eis_region_set_offset(struct eis_region *region, uint32_t x, uint32_t y);
|
|||
void
|
||||
eis_region_set_physical_scale(struct eis_region *region, double scale);
|
||||
|
||||
/**
|
||||
* @ingroup libeis-region
|
||||
*
|
||||
* Attach a unique identifier representing an external resource to this region.
|
||||
* libeis does not look at or modify the value, it is passed through to the
|
||||
* client if the client supports ei_device interface version 2 or later. Because
|
||||
* the ID is assigned by the caller libei makes no guarantee that the ID is
|
||||
* indeed unique and/or corresponds to any particular format.
|
||||
*
|
||||
* This ID can be used by the caller to identify an external resource
|
||||
* that has a relationship with this region. For example, a caller may have
|
||||
* a data stream with the video data that this region represents.
|
||||
* By attaching the same identifier to the data stream and this region a client
|
||||
* (who needs to be aware of this approach) can pair the video data stream
|
||||
* with the region. Note that in this example use-case, if the stream is resized
|
||||
* there may be a transition period where two regions have the same identifier -
|
||||
* the old region and the new region with the updated size. A client must be
|
||||
* able to handle the case where two mapping_ids are identical.
|
||||
*
|
||||
* This function has no effect if called after eis_device_add()
|
||||
*
|
||||
* @since 1.1
|
||||
*/
|
||||
void
|
||||
eis_region_set_mapping_id(struct eis_region *region, const char *mapping_id);
|
||||
|
||||
/**
|
||||
* @ingroup libeis-region
|
||||
*
|
||||
* Get the unique ID for this region previously set by this
|
||||
* caller, if any, or NULL if the client does not support region mapping id
|
||||
* or no region ID has been set.
|
||||
*
|
||||
* Region IDs require the client to support the ei_device interface
|
||||
* version 2 or later. This function can be used to detect support
|
||||
* for this interface: after eis_region_add() this region's ID is set
|
||||
* to NULL if the client does not support that interface version.
|
||||
*
|
||||
* In other words, if a caller sets a region ID with
|
||||
* eis_region_set_mapping_id() and that region ID is returned after eis_region_add(),
|
||||
* the client has been notified of the region ID.
|
||||
*
|
||||
* @since 1.1
|
||||
*/
|
||||
const char *
|
||||
eis_region_get_mapping_id(struct eis_region *region);
|
||||
|
||||
/**
|
||||
* @ingroup libeis-region
|
||||
*
|
||||
|
|
|
|||
|
|
@ -516,6 +516,7 @@ MUNIT_TEST(test_ei_device_regions)
|
|||
_unref_(eis_region) *r1 = eis_device_new_region(device);
|
||||
eis_region_set_size(r1, 100, 200);
|
||||
eis_region_set_offset(r1, 300, 400);
|
||||
eis_region_set_mapping_id(r1, "oo oo eye dee");
|
||||
/* no scale, default to 1.0 */
|
||||
eis_region_add(r1);
|
||||
|
||||
|
|
@ -551,6 +552,7 @@ MUNIT_TEST(test_ei_device_regions)
|
|||
munit_assert_int(ei_region_get_x(r), ==, 300);
|
||||
munit_assert_int(ei_region_get_y(r), ==, 400);
|
||||
munit_assert_double_equal(ei_region_get_physical_scale(r), 1.0, 2 /* precision */);
|
||||
munit_assert_string_equal(ei_region_get_mapping_id(r), "oo oo eye dee");
|
||||
|
||||
r2 = ei_device_get_region_at(device, 300, 400);
|
||||
munit_assert_ptr_equal(r, r2);
|
||||
|
|
@ -563,6 +565,7 @@ MUNIT_TEST(test_ei_device_regions)
|
|||
munit_assert_int(ei_region_get_x(r), ==, 700);
|
||||
munit_assert_int(ei_region_get_y(r), ==, 800);
|
||||
munit_assert_double_equal(ei_region_get_physical_scale(r), 3.9, 2 /* precision */);
|
||||
munit_assert_null(ei_region_get_mapping_id(r));
|
||||
|
||||
r2 = ei_device_get_region_at(device, 750, 850);
|
||||
munit_assert_ptr_equal(r, r2);
|
||||
|
|
@ -573,6 +576,7 @@ MUNIT_TEST(test_ei_device_regions)
|
|||
munit_assert_int(ei_region_get_x(r), ==, 1100);
|
||||
munit_assert_int(ei_region_get_y(r), ==, 1200);
|
||||
munit_assert_double_equal(ei_region_get_physical_scale(r), 0.3, 2 /* precision */);
|
||||
munit_assert_null(ei_region_get_mapping_id(r));
|
||||
|
||||
r2 = ei_device_get_region_at(device, 1999, 2199);
|
||||
munit_assert_ptr_equal(r, r2);
|
||||
|
|
|
|||
|
|
@ -260,6 +260,7 @@ add_device(struct eis_demo_server *server, struct eis_client *client,
|
|||
eis_device_configure_capability(ptr, EIS_DEVICE_CAP_BUTTON);
|
||||
eis_device_configure_capability(ptr, EIS_DEVICE_CAP_SCROLL);
|
||||
_unref_(eis_region) *rel_region = eis_device_new_region(ptr);
|
||||
eis_region_set_mapping_id(rel_region, "demo region");
|
||||
eis_region_set_size(rel_region, 1920, 1080);
|
||||
eis_region_set_offset(rel_region, 0, 0);
|
||||
eis_region_add(rel_region);
|
||||
|
|
@ -280,6 +281,7 @@ add_device(struct eis_demo_server *server, struct eis_client *client,
|
|||
eis_device_configure_capability(abs, EIS_DEVICE_CAP_BUTTON);
|
||||
eis_device_configure_capability(abs, EIS_DEVICE_CAP_SCROLL);
|
||||
_unref_(eis_region) *region = eis_device_new_region(abs);
|
||||
eis_region_set_mapping_id(region, "demo region");
|
||||
eis_region_set_size(region, 1920, 1080);
|
||||
eis_region_set_offset(region, 0, 0);
|
||||
eis_region_add(region);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue