libei: make the pointer/touch ranges constant and client-determined

We assume that any libei client has access to the windowing system through
other means (at least where it matters) so they can set up the pointer range
accordingly. This also allows the server to do heuristics on monitor mapping,
similar to what we have for Wacom tablets already.

And forcing the ranges to be constant means the race conditions are halved,
only the client is now affected by a potential race condition between the
screen size changing and the pointer ranges needing updates. Those can be
mitigated by the server though, e.g. an input device that maps to a
single-monitor *should* still be mapped to that same monitor after another
monitor is plugged in (and this should apply before the client is notified of
the screen mapping). So the client events in transit will still go to the
right position of the screen (though admittedly the target areas may have
migrated to the new screen so the click now goes wrong anyway).

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
Peter Hutterer 2020-07-16 09:42:56 +10:00
parent 562e120da8
commit e6b280a98e
2 changed files with 90 additions and 69 deletions

View file

@ -84,13 +84,6 @@ enum ei_event_type {
* Any events sent will be discarded until the next resume.
*/
EI_EVENT_POINTER_SUSPEND,
/**
* Update pointer ranges. This provides the client with the allowed
* axis ranges for absolute pointer motion. The axis ranges may not
* match the available screen ranges and the axis range may only map
* to a portion of the available screen size.
*/
EI_EVENT_POINTER_RANGES_CHANGED,
/**
* The client may send events.
@ -113,13 +106,6 @@ enum ei_event_type {
* Any events sent will be discarded until the next resume.
*/
EI_EVENT_TOUCH_SUSPEND,
/**
* Update touch ranges. This provides the client with the allowed
* axis ranges for absolute pointer motion. The axis ranges may not
* match the available screen ranges and the axis range may only map
* to a portion of the available screen size.
*/
EI_EVENT_TOUCH_RANGES_CHANGED,
};
struct ei_ctx *
@ -213,6 +199,53 @@ void
ei_device_configure_capability(struct ei_device *device,
enum ei_device_capability cap);
/**
* Set the range of the absolute pointer device in 1/1000th of a logical
* pixel. 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 values are in 1/1000th of logical pixels, i.e. the value 100 000
* refers to 100 pixels.
*
* 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 client bug to call this function on a device without the @ref
* EI_DEVICE_CAP_POINTER_ABSOLUTE capability.
*
* This function has no effect if called after ei_device_add()
*
* @param width The maximum (exclusive) x value in 1/1000th of a pixel
* @param heigth The maximum (exclusive) y value in 1/1000th of a pixel
*/
void
ei_device_configure_pointer_range(struct ei_device *device,
uint32_t width,
uint32_t height);
/**
* Set the range of the touch device in 1/1000th of a logical pixels. This
* function is identical to ei_device_configure_pointer_range() but
* configures the touch range instead.
*/
void
ei_device_configure_touch_range(struct ei_device *device,
uint32_t width,
uint32_t height);
/**
* Request that the device be added to the server.
* The server will respond with an @ref EI_EVENT_DEVICE_ADDED or @ref
@ -369,54 +402,12 @@ ei_event_get_device(struct ei_event *event);
uint64_t
ei_event_pointer_get_time(struct ei_event_pointer *event);
/**
* For an event of type @ref EI_EVENT_POINTER_RANGES_CHANGED, this function
* defines the allowable range for x - 0 (inclusive) to width (exclusive).
*
* The value is in 1/1000th of logical pixels, i.e. the value 1000 000
* refers to 1000 pixels.
*
* It is a client bug to send pointer values outside this range.
*
* If the touch range changes at runtime, an event of @ref
* EI_EVENT_POINTER_RANGES_CHANGED is generated.
*/
uint32_t
ei_event_pointer_get_width(struct ei_event_pointer *event);
/**
* @see ei_event_pointer_get_width
*/
uint32_t
ei_event_pointer_get_height(struct ei_event_pointer *event);
/**
* @return the event time in microseconds
*/
uint64_t
ei_event_keyboard_get_time(struct ei_event_keyboard *event);
/**
* For an event of type @ref EI_EVENT_TOUCH_RANGES_CHANGED, this function
* defines the allowable range for x - 0 (inclusive) to width (exclusive).
*
* The value is in 1/1000th of logical pixels, i.e. the value 1000 000
* refers to 1000 pixels.
*
* It is a client bug to send touch values outside this range.
*
* If the touch range changes at runtime, an event of @ref
* EI_EVENT_TOUCH_RANGES_CHANGED is generated.
*/
uint32_t
ei_event_touch_get_width(struct ei_event_touch *event);
/**
* @see ei_event_touch_get_width
*/
uint32_t
ei_event_touch_get_height(struct ei_event_touch *event);
/**
* @return the event time in microseconds
*/

View file

@ -250,25 +250,55 @@ void
eis_device_resume_capability(struct eis_device *device, uint32_t cap);
/**
* Notify the client of a new range for absolute pointer events.
* The range is 0 (inclusive) to width (exclusive).
* Get the width of the absolute pointer device in 1/1000th of a logical
* pixel. 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 value is in 1/1000th of logical pixels, i.e. the value 1000 000
* refers to 1000 pixels.
* The values are in 1/1000th of logical pixels, i.e. the value 100 000
* refers to 100 pixels.
*
* Due to inherent race conditions with changing the width of a device in an
* asynchronous communication channel, a server should alway suspend the
* pointer capability before changing the width.
* 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.
*
* @param width The new width in 1/1000th of logical pixels
* 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 1/1000th of logical pixels
*/
void
eis_device_pointer_set_width(struct eis_device *device, uint32_t width);
uint32_t
eis_device_get_pointer_width(struct eis_device *device);
/**
* @see eis_device_pointer_set_width
* @see eis_device_get_pointer_width
*/
void
eis_device_pointer_set_height(struct eis_device *device, uint32_t height);
uint32_t
eis_device_get_pointer_height(struct eis_device *device);
/**
* @see eis_device_get_pointer_width
*/
uint32_t
eis_device_get_touch_width(struct eis_device *device);
/**
* @see eis_device_get_touch_width
*/
uint32_t
eis_device_get_touch_height(struct eis_device *device);
/**
* Set the keymap on the device.