summaryrefslogtreecommitdiff
path: root/src/evdev-tablet.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/evdev-tablet.c')
-rw-r--r--src/evdev-tablet.c159
1 files changed, 147 insertions, 12 deletions
diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c
index fe5db8e0..27177b53 100644
--- a/src/evdev-tablet.c
+++ b/src/evdev-tablet.c
@@ -260,6 +260,40 @@ tablet_process_absolute(struct tablet_dispatch *tablet,
}
}
+static inline int
+axis_range_percentage(const struct input_absinfo *a, double percent)
+{
+ return (a->maximum - a->minimum) * percent/100.0 + a->minimum;
+}
+
+static void
+tablet_change_area(struct evdev_device *device)
+{
+ struct tablet_dispatch *tablet = tablet_dispatch(device->dispatch);
+
+ if (memcmp(&tablet->area.rect, &tablet->area.want_rect, sizeof(tablet->area.rect)) == 0)
+ return;
+
+ if (!tablet_has_status(tablet, TABLET_TOOL_OUT_OF_PROXIMITY))
+ return;
+
+ tablet->area.rect = tablet->area.want_rect;
+
+ evdev_log_debug(device,
+ "tablet-area: area is %.2f/%.2f - %.2f/%.2f\n",
+ tablet->area.rect.x1,
+ tablet->area.rect.y1,
+ tablet->area.rect.x2,
+ tablet->area.rect.y2);
+
+ const struct input_absinfo *absx = device->abs.absinfo_x;
+ const struct input_absinfo *absy = device->abs.absinfo_y;
+ tablet->area.x.minimum = axis_range_percentage(absx, tablet->area.rect.x1 * 100);
+ tablet->area.x.maximum = axis_range_percentage(absx, tablet->area.rect.x2 * 100);
+ tablet->area.y.minimum = axis_range_percentage(absy, tablet->area.rect.y1 * 100);
+ tablet->area.y.maximum = axis_range_percentage(absy, tablet->area.rect.y2 * 100);
+}
+
static void
tablet_apply_rotation(struct evdev_device *device)
{
@@ -442,6 +476,31 @@ normalize_wheel(struct tablet_dispatch *tablet,
return value * device->scroll.wheel_click_angle.x;
}
+static void
+apply_tablet_area(struct tablet_dispatch *tablet,
+ struct evdev_device *device,
+ struct device_coords *point)
+{
+ if (tablet->area.rect.x1 == 0.0 && tablet->area.rect.x2 == 1.0 &&
+ tablet->area.rect.y1 == 0.0 && tablet->area.rect.y2 == 1.0)
+ return;
+
+ /* The point is somewhere on the tablet in device coordinates,
+ * but we need it relative to the x/y offset.
+ * So clip it first, then offset it to our area min/max.
+ *
+ * Right now we're just clipping, we don't completely
+ * ignore events. What we should do is ignore events outside
+ * altogether and generate prox in/out events when we actually
+ * enter the area.
+ */
+ point->x = min(point->x, tablet->area.x.maximum);
+ point->y = min(point->y, tablet->area.y.maximum);
+
+ point->x = max(point->x, tablet->area.x.minimum);
+ point->y = max(point->y, tablet->area.y.minimum);
+}
+
static inline void
tablet_update_xy(struct tablet_dispatch *tablet,
struct evdev_device *device)
@@ -473,7 +532,10 @@ tablet_update_xy(struct tablet_dispatch *tablet,
tablet->axes.point.y = value;
+ /* calibration and area are currently mutually exclusive so
+ * one of those is a noop */
evdev_transform_absolute(device, &tablet->axes.point);
+ apply_tablet_area(tablet, device, &tablet->axes.point);
}
}
@@ -1070,12 +1132,6 @@ tool_set_bits(const struct tablet_dispatch *tablet,
}
}
-static inline int
-axis_range_percentage(const struct input_absinfo *a, double percent)
-{
- return (a->maximum - a->minimum) * percent/100.0 + a->minimum;
-}
-
static bool
tablet_get_quirked_pressure_thresholds(struct tablet_dispatch *tablet,
int *hi,
@@ -1338,7 +1394,9 @@ tablet_notify_button_mask(struct tablet_dispatch *tablet,
tip_state,
&tablet->axes,
i,
- state);
+ state,
+ &tablet->area.x,
+ &tablet->area.y);
}
}
@@ -1737,7 +1795,9 @@ tablet_send_proximity_in(struct tablet_dispatch *tablet,
tool,
LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN,
tablet->changed_axes,
- axes);
+ axes,
+ &tablet->area.x,
+ &tablet->area.y);
tablet_unset_status(tablet, TABLET_TOOL_ENTERING_PROXIMITY);
tablet_unset_status(tablet, TABLET_AXES_UPDATED);
@@ -1763,7 +1823,9 @@ tablet_send_proximity_out(struct tablet_dispatch *tablet,
tool,
LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT,
tablet->changed_axes,
- axes);
+ axes,
+ &tablet->area.x,
+ &tablet->area.y);
tablet_set_status(tablet, TABLET_TOOL_OUT_OF_PROXIMITY);
tablet_unset_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY);
@@ -1788,7 +1850,9 @@ tablet_send_tip(struct tablet_dispatch *tablet,
tool,
LIBINPUT_TABLET_TOOL_TIP_DOWN,
tablet->changed_axes,
- axes);
+ axes,
+ &tablet->area.x,
+ &tablet->area.y);
tablet_unset_status(tablet, TABLET_AXES_UPDATED);
tablet_unset_status(tablet, TABLET_TOOL_ENTERING_CONTACT);
tablet_set_status(tablet, TABLET_TOOL_IN_CONTACT);
@@ -1806,7 +1870,9 @@ tablet_send_tip(struct tablet_dispatch *tablet,
tool,
LIBINPUT_TABLET_TOOL_TIP_UP,
tablet->changed_axes,
- axes);
+ axes,
+ &tablet->area.x,
+ &tablet->area.y);
tablet_unset_status(tablet, TABLET_AXES_UPDATED);
tablet_unset_status(tablet, TABLET_TOOL_LEAVING_CONTACT);
tablet_unset_status(tablet, TABLET_TOOL_IN_CONTACT);
@@ -1844,7 +1910,9 @@ tablet_send_axes(struct tablet_dispatch *tablet,
tool,
tip_state,
tablet->changed_axes,
- axes);
+ axes,
+ &tablet->area.x,
+ &tablet->area.y);
tablet_unset_status(tablet, TABLET_AXES_UPDATED);
tablet_reset_changed_axes(tablet);
axes->delta.x = 0;
@@ -1914,6 +1982,7 @@ tablet_send_events(struct tablet_dispatch *tablet,
if (tablet_send_proximity_out(tablet, tool, device, &axes, time)) {
tablet_change_to_left_handed(device);
tablet_apply_rotation(device);
+ tablet_change_area(device);
tablet_history_reset(tablet);
}
}
@@ -2501,6 +2570,71 @@ tablet_init_calibration(struct tablet_dispatch *tablet,
evdev_init_calibration(device, &tablet->calibration);
}
+static int
+tablet_area_has_rectangle(struct libinput_device *device)
+{
+ return 1;
+}
+
+static enum libinput_config_status
+tablet_area_set_rectangle(struct libinput_device *device,
+ const struct libinput_config_area_rectangle *rectangle)
+{
+ struct evdev_device *evdev = evdev_device(device);
+ struct tablet_dispatch *tablet = tablet_dispatch(evdev->dispatch);
+
+ if (rectangle->x1 >= rectangle->x2 || rectangle->y1 >= rectangle->y2)
+ return LIBINPUT_CONFIG_STATUS_INVALID;
+
+ if (rectangle->x1 < 0.0 || rectangle->x2 > 1.0 ||
+ rectangle->y1 < 0.0 || rectangle->y2 > 1.0)
+ return LIBINPUT_CONFIG_STATUS_INVALID;
+
+ tablet->area.want_rect = *rectangle;
+
+ tablet_change_area(evdev);
+
+ return LIBINPUT_CONFIG_STATUS_SUCCESS;
+}
+
+static struct libinput_config_area_rectangle
+tablet_area_get_rectangle(struct libinput_device *device)
+{
+ struct evdev_device *evdev = evdev_device(device);
+ struct tablet_dispatch *tablet = tablet_dispatch(evdev->dispatch);
+
+ return tablet->area.rect;
+}
+
+static struct libinput_config_area_rectangle
+tablet_area_get_default_rectangle(struct libinput_device *device)
+{
+ struct libinput_config_area_rectangle rect = {
+ 0.0, 0.0, 1.0, 1.0,
+ };
+ return rect;
+}
+
+static void
+tablet_init_area(struct tablet_dispatch *tablet,
+ struct evdev_device *device)
+{
+ tablet->area.rect = (struct libinput_config_area_rectangle) {
+ 0.0, 0.0, 1.0, 1.0,
+ };
+ tablet->area.want_rect = tablet->area.rect;
+ tablet->area.x = *device->abs.absinfo_x;
+ tablet->area.y = *device->abs.absinfo_y;
+
+ if (!libevdev_has_property(device->evdev, INPUT_PROP_DIRECT)) {
+ device->base.config.area = &tablet->area.config;
+ tablet->area.config.has_rectangle = tablet_area_has_rectangle;
+ tablet->area.config.set_rectangle = tablet_area_set_rectangle;
+ tablet->area.config.get_rectangle = tablet_area_get_rectangle;
+ tablet->area.config.get_default_rectangle = tablet_area_get_default_rectangle;
+ }
+}
+
static void
tablet_init_proximity_threshold(struct tablet_dispatch *tablet,
struct evdev_device *device)
@@ -2791,6 +2925,7 @@ tablet_init(struct tablet_dispatch *tablet,
tablet_fix_tilt(tablet, device);
tablet_init_calibration(tablet, device, is_display_tablet);
+ tablet_init_area(tablet, device);
tablet_init_proximity_threshold(tablet, device);
rc = tablet_init_accel(tablet, device);
if (rc != 0)