mirror of
https://github.com/labwc/labwc.git
synced 2025-10-29 05:40:24 -04:00
input: support tablet tools with relative motion
This commit is contained in:
parent
b663c9ea46
commit
8501a1281c
2 changed files with 91 additions and 35 deletions
|
|
@ -9,12 +9,18 @@ struct seat;
|
||||||
struct wlr_device;
|
struct wlr_device;
|
||||||
struct wlr_input_device;
|
struct wlr_input_device;
|
||||||
|
|
||||||
|
enum lab_tablet_motion_mode {
|
||||||
|
LAB_TABLET_MOTION_ABSOLUTE = 0,
|
||||||
|
LAB_TABLET_MOTION_RELATIVE,
|
||||||
|
};
|
||||||
|
|
||||||
struct drawing_tablet {
|
struct drawing_tablet {
|
||||||
struct wlr_input_device *wlr_input_device;
|
struct wlr_input_device *wlr_input_device;
|
||||||
struct seat *seat;
|
struct seat *seat;
|
||||||
struct wlr_tablet *tablet;
|
struct wlr_tablet *tablet;
|
||||||
struct wlr_tablet_v2_tablet *tablet_v2;
|
struct wlr_tablet_v2_tablet *tablet_v2;
|
||||||
double x, y;
|
enum lab_tablet_motion_mode motion_mode;
|
||||||
|
double x, y, dx, dy;
|
||||||
double distance;
|
double distance;
|
||||||
double pressure;
|
double pressure;
|
||||||
double tilt_x, tilt_y;
|
double tilt_x, tilt_y;
|
||||||
|
|
|
||||||
|
|
@ -19,15 +19,19 @@
|
||||||
#include "idle.h"
|
#include "idle.h"
|
||||||
#include "action.h"
|
#include "action.h"
|
||||||
|
|
||||||
static bool
|
static enum lab_tablet_motion_mode
|
||||||
tool_supports_absolute_motion(struct wlr_tablet_tool *tool)
|
tool_motion_mode(struct wlr_tablet_tool *tool)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* Absolute positioning doesn't make sense
|
||||||
|
* for tablet mouses and lenses.
|
||||||
|
*/
|
||||||
switch (tool->type) {
|
switch (tool->type) {
|
||||||
case WLR_TABLET_TOOL_TYPE_MOUSE:
|
case WLR_TABLET_TOOL_TYPE_MOUSE:
|
||||||
case WLR_TABLET_TOOL_TYPE_LENS:
|
case WLR_TABLET_TOOL_TYPE_LENS:
|
||||||
return false;
|
return LAB_TABLET_MOTION_RELATIVE;
|
||||||
default:
|
default:
|
||||||
return true;
|
return LAB_TABLET_MOTION_ABSOLUTE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -108,29 +112,47 @@ adjust_for_rotation_relative(enum rotation rotation, double *dx, double *dy)
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct wlr_surface*
|
static struct wlr_surface*
|
||||||
tablet_get_coords(struct drawing_tablet *tablet, double *x, double *y)
|
tablet_get_coords(struct drawing_tablet *tablet, double *x, double *y, double *dx, double *dy)
|
||||||
{
|
{
|
||||||
*x = tablet->x;
|
*x = tablet->x;
|
||||||
*y = tablet->y;
|
*y = tablet->y;
|
||||||
|
*dx = tablet->dx;
|
||||||
|
*dy = tablet->dy;
|
||||||
adjust_for_tablet_area(tablet->tablet->width_mm, tablet->tablet->height_mm,
|
adjust_for_tablet_area(tablet->tablet->width_mm, tablet->tablet->height_mm,
|
||||||
rc.tablet.box, x, y);
|
rc.tablet.box, x, y);
|
||||||
adjust_for_rotation(rc.tablet.rotation, x, y);
|
adjust_for_rotation(rc.tablet.rotation, x, y);
|
||||||
|
adjust_for_rotation_relative(rc.tablet.rotation, dx, dy);
|
||||||
|
|
||||||
if (rc.tablet.force_mouse_emulation
|
if (rc.tablet.force_mouse_emulation
|
||||||
|| !tablet->tablet_v2) {
|
|| !tablet->tablet_v2) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert coordinates: first [0, 1] => layout, then layout => surface */
|
/* convert coordinates: first [0, 1] => layout, then layout => surface */
|
||||||
double lx, ly;
|
|
||||||
wlr_cursor_absolute_to_layout_coords(tablet->seat->cursor,
|
/* initialize here to avoid a maybe-uninitialized compiler warning */
|
||||||
tablet->wlr_input_device, *x, *y, &lx, &ly);
|
double lx = -1, ly = -1;
|
||||||
|
switch (tablet->motion_mode) {
|
||||||
|
case LAB_TABLET_MOTION_ABSOLUTE:
|
||||||
|
wlr_cursor_absolute_to_layout_coords(tablet->seat->cursor,
|
||||||
|
tablet->wlr_input_device, *x, *y, &lx, &ly);
|
||||||
|
break;
|
||||||
|
case LAB_TABLET_MOTION_RELATIVE:
|
||||||
|
/*
|
||||||
|
* Deltas dx,dy will be directly passed into wlr_cursor_move,
|
||||||
|
* so we can add those directly here to determine our future
|
||||||
|
* position.
|
||||||
|
*/
|
||||||
|
lx = tablet->seat->cursor->x + *dx;
|
||||||
|
ly = tablet->seat->cursor->y + *dy;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
double sx, sy;
|
double sx, sy;
|
||||||
struct wlr_scene_node *node =
|
struct wlr_scene_node *node =
|
||||||
wlr_scene_node_at(&tablet->seat->server->scene->tree.node, lx, ly, &sx, &sy);
|
wlr_scene_node_at(&tablet->seat->server->scene->tree.node, lx, ly, &sx, &sy);
|
||||||
|
|
||||||
/* Find the surface and return it if it accepts tablet events */
|
/* find the surface and return it if it accepts tablet events */
|
||||||
struct wlr_surface *surface = lab_wlr_surface_from_node(node);
|
struct wlr_surface *surface = lab_wlr_surface_from_node(node);
|
||||||
|
|
||||||
if (surface && !wlr_surface_accepts_tablet_v2(tablet->tablet_v2, surface)) {
|
if (surface && !wlr_surface_accepts_tablet_v2(tablet->tablet_v2, surface)) {
|
||||||
|
|
@ -141,7 +163,8 @@ tablet_get_coords(struct drawing_tablet *tablet, double *x, double *y)
|
||||||
|
|
||||||
static void
|
static void
|
||||||
notify_motion(struct drawing_tablet *tablet, struct drawing_tablet_tool *tool,
|
notify_motion(struct drawing_tablet *tablet, struct drawing_tablet_tool *tool,
|
||||||
struct wlr_surface *surface, double x, double y, uint32_t time)
|
struct wlr_surface *surface, double x, double y, double dx, double dy,
|
||||||
|
uint32_t time)
|
||||||
{
|
{
|
||||||
idle_manager_notify_activity(tool->seat->seat);
|
idle_manager_notify_activity(tool->seat->seat);
|
||||||
|
|
||||||
|
|
@ -153,8 +176,16 @@ notify_motion(struct drawing_tablet *tablet, struct drawing_tablet_tool *tool,
|
||||||
tablet->tablet_v2, surface);
|
tablet->tablet_v2, surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_cursor_warp_absolute(tablet->seat->cursor,
|
switch (tablet->motion_mode) {
|
||||||
tablet->wlr_input_device, x, y);
|
case LAB_TABLET_MOTION_ABSOLUTE:
|
||||||
|
wlr_cursor_warp_absolute(tablet->seat->cursor,
|
||||||
|
tablet->wlr_input_device, x, y);
|
||||||
|
break;
|
||||||
|
case LAB_TABLET_MOTION_RELATIVE:
|
||||||
|
wlr_cursor_move(tablet->seat->cursor,
|
||||||
|
tablet->wlr_input_device, dx, dy);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
double sx, sy;
|
double sx, sy;
|
||||||
bool notify = cursor_process_motion(tablet->seat->server, time, &sx, &sy);
|
bool notify = cursor_process_motion(tablet->seat->server, time, &sx, &sy);
|
||||||
|
|
@ -203,18 +234,22 @@ handle_proximity(struct wl_listener *listener, void *data)
|
||||||
struct drawing_tablet *tablet = ev->tablet->data;
|
struct drawing_tablet *tablet = ev->tablet->data;
|
||||||
struct drawing_tablet_tool *tool = ev->tool->data;
|
struct drawing_tablet_tool *tool = ev->tool->data;
|
||||||
|
|
||||||
if (!tool_supports_absolute_motion(ev->tool)) {
|
if (ev->state == WLR_TABLET_TOOL_PROXIMITY_IN) {
|
||||||
if (ev->state == WLR_TABLET_TOOL_PROXIMITY_IN) {
|
tablet->motion_mode = tool_motion_mode(ev->tool);
|
||||||
wlr_log(WLR_INFO, "ignoring not supporting tablet tool");
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reset relative coordinates, we don't want to move the
|
||||||
|
* cursor on proximity-in for relative positioning.
|
||||||
|
*/
|
||||||
|
tablet->dx = 0;
|
||||||
|
tablet->dy = 0;
|
||||||
|
|
||||||
tablet->x = ev->x;
|
tablet->x = ev->x;
|
||||||
tablet->y = ev->y;
|
tablet->y = ev->y;
|
||||||
|
|
||||||
double x, y;
|
double x, y, dx, dy;
|
||||||
struct wlr_surface *surface = tablet_get_coords(tablet, &x, &y);
|
struct wlr_surface *surface = tablet_get_coords(tablet, &x, &y, &dx, &dy);
|
||||||
|
|
||||||
if (!rc.tablet.force_mouse_emulation
|
if (!rc.tablet.force_mouse_emulation
|
||||||
&& tablet->seat->server->tablet_manager && !tool) {
|
&& tablet->seat->server->tablet_manager && !tool) {
|
||||||
|
|
@ -231,7 +266,7 @@ handle_proximity(struct wl_listener *listener, void *data)
|
||||||
*/
|
*/
|
||||||
if (tool && surface) {
|
if (tool && surface) {
|
||||||
if (tool->tool_v2 && ev->state == WLR_TABLET_TOOL_PROXIMITY_IN) {
|
if (tool->tool_v2 && ev->state == WLR_TABLET_TOOL_PROXIMITY_IN) {
|
||||||
notify_motion(tablet, tool, surface, x, y, ev->time_msec);
|
notify_motion(tablet, tool, surface, x, y, dx, dy, ev->time_msec);
|
||||||
}
|
}
|
||||||
if (tool->tool_v2 && ev->state == WLR_TABLET_TOOL_PROXIMITY_OUT) {
|
if (tool->tool_v2 && ev->state == WLR_TABLET_TOOL_PROXIMITY_OUT) {
|
||||||
wlr_tablet_v2_tablet_tool_notify_proximity_out(tool->tool_v2);
|
wlr_tablet_v2_tablet_tool_notify_proximity_out(tool->tool_v2);
|
||||||
|
|
@ -248,18 +283,22 @@ handle_axis(struct wl_listener *listener, void *data)
|
||||||
struct drawing_tablet *tablet = ev->tablet->data;
|
struct drawing_tablet *tablet = ev->tablet->data;
|
||||||
struct drawing_tablet_tool *tool = ev->tool->data;
|
struct drawing_tablet_tool *tool = ev->tool->data;
|
||||||
|
|
||||||
if (!tool_supports_absolute_motion(ev->tool)) {
|
/*
|
||||||
return;
|
* Reset relative coordinates. If those axes aren't updated,
|
||||||
}
|
* the delta is zero.
|
||||||
|
*/
|
||||||
|
tablet->dx = 0;
|
||||||
|
tablet->dy = 0;
|
||||||
tablet->tilt_x = 0;
|
tablet->tilt_x = 0;
|
||||||
tablet->tilt_y = 0;
|
tablet->tilt_y = 0;
|
||||||
|
|
||||||
if (ev->updated_axes & WLR_TABLET_TOOL_AXIS_X) {
|
if (ev->updated_axes & WLR_TABLET_TOOL_AXIS_X) {
|
||||||
tablet->x = ev->x;
|
tablet->x = ev->x;
|
||||||
|
tablet->dx = ev->dx;
|
||||||
}
|
}
|
||||||
if (ev->updated_axes & WLR_TABLET_TOOL_AXIS_Y) {
|
if (ev->updated_axes & WLR_TABLET_TOOL_AXIS_Y) {
|
||||||
tablet->y = ev->y;
|
tablet->y = ev->y;
|
||||||
|
tablet->dy = ev->dy;
|
||||||
}
|
}
|
||||||
if (ev->updated_axes & WLR_TABLET_TOOL_AXIS_DISTANCE) {
|
if (ev->updated_axes & WLR_TABLET_TOOL_AXIS_DISTANCE) {
|
||||||
tablet->distance = ev->distance;
|
tablet->distance = ev->distance;
|
||||||
|
|
@ -283,8 +322,8 @@ handle_axis(struct wl_listener *listener, void *data)
|
||||||
tablet->wheel_delta = ev->wheel_delta;
|
tablet->wheel_delta = ev->wheel_delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
double x, y;
|
double x, y, dx, dy;
|
||||||
struct wlr_surface *surface = tablet_get_coords(tablet, &x, &y);
|
struct wlr_surface *surface = tablet_get_coords(tablet, &x, &y, &dx, &dy);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We are sending tablet notifications on the following conditions:
|
* We are sending tablet notifications on the following conditions:
|
||||||
|
|
@ -301,7 +340,7 @@ handle_axis(struct wl_listener *listener, void *data)
|
||||||
&& tablet->seat->server->input_mode == LAB_INPUT_STATE_PASSTHROUGH)
|
&& tablet->seat->server->input_mode == LAB_INPUT_STATE_PASSTHROUGH)
|
||||||
|| wlr_tablet_tool_v2_has_implicit_grab(tool->tool_v2))) {
|
|| wlr_tablet_tool_v2_has_implicit_grab(tool->tool_v2))) {
|
||||||
/* motion seems to be supported by all tools */
|
/* motion seems to be supported by all tools */
|
||||||
notify_motion(tablet, tool, surface, x, y, ev->time_msec);
|
notify_motion(tablet, tool, surface, x, y, dx, dy, ev->time_msec);
|
||||||
|
|
||||||
/* notify about other axis based on tool capabilities */
|
/* notify about other axis based on tool capabilities */
|
||||||
if (ev->tool->distance) {
|
if (ev->tool->distance) {
|
||||||
|
|
@ -349,8 +388,19 @@ handle_axis(struct wl_listener *listener, void *data)
|
||||||
wlr_tablet_v2_tablet_tool_notify_proximity_out(
|
wlr_tablet_v2_tablet_tool_notify_proximity_out(
|
||||||
tool->tool_v2);
|
tool->tool_v2);
|
||||||
}
|
}
|
||||||
cursor_emulate_move_absolute(tablet->seat, &ev->tablet->base,
|
|
||||||
x, y, ev->time_msec);
|
switch (tablet->motion_mode) {
|
||||||
|
case LAB_TABLET_MOTION_ABSOLUTE:
|
||||||
|
cursor_emulate_move_absolute(tablet->seat,
|
||||||
|
&ev->tablet->base,
|
||||||
|
x, y, ev->time_msec);
|
||||||
|
break;
|
||||||
|
case LAB_TABLET_MOTION_RELATIVE:
|
||||||
|
cursor_emulate_move(tablet->seat,
|
||||||
|
&ev->tablet->base,
|
||||||
|
dx, dy, ev->time_msec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -407,8 +457,8 @@ handle_tip(struct wl_listener *listener, void *data)
|
||||||
struct drawing_tablet *tablet = ev->tablet->data;
|
struct drawing_tablet *tablet = ev->tablet->data;
|
||||||
struct drawing_tablet_tool *tool = ev->tool->data;
|
struct drawing_tablet_tool *tool = ev->tool->data;
|
||||||
|
|
||||||
double x, y;
|
double x, y, dx, dy;
|
||||||
struct wlr_surface *surface = tablet_get_coords(tablet, &x, &y);
|
struct wlr_surface *surface = tablet_get_coords(tablet, &x, &y, &dx, &dy);
|
||||||
|
|
||||||
uint32_t button = tablet_get_mapped_button(BTN_TOOL_PEN);
|
uint32_t button = tablet_get_mapped_button(BTN_TOOL_PEN);
|
||||||
|
|
||||||
|
|
@ -482,8 +532,8 @@ handle_button(struct wl_listener *listener, void *data)
|
||||||
struct drawing_tablet *tablet = ev->tablet->data;
|
struct drawing_tablet *tablet = ev->tablet->data;
|
||||||
struct drawing_tablet_tool *tool = ev->tool->data;
|
struct drawing_tablet_tool *tool = ev->tool->data;
|
||||||
|
|
||||||
double x, y;
|
double x, y, dx, dy;
|
||||||
struct wlr_surface *surface = tablet_get_coords(tablet, &x, &y);
|
struct wlr_surface *surface = tablet_get_coords(tablet, &x, &y, &dx, &dy);
|
||||||
|
|
||||||
uint32_t button = tablet_get_mapped_button(ev->button);
|
uint32_t button = tablet_get_mapped_button(ev->button);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue