mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2025-12-29 06:40:08 +01:00
Merge branch 'master' into tablet-support
This commit is contained in:
commit
2876575d06
22 changed files with 1141 additions and 571 deletions
|
|
@ -57,6 +57,11 @@ See @ref motion_normalization for details.
|
|||
<dd>The angle in degrees for each click on a mouse wheel. See
|
||||
libinput_pointer_get_axis_source() for details.
|
||||
</dd>
|
||||
<dt>TOUCHPAD_RESOLUTION</dt>
|
||||
<dd>The x and y resolution in units/mm for a touchpad. This value is only
|
||||
used if the touchpad kernel driver does not supply a valid resolution. It
|
||||
is only used on touchpad devices. The format is two unsigned integer values
|
||||
separated by a literal 'x', e.g. "42x129".</dd>
|
||||
</dl>
|
||||
|
||||
Below is an example udev rule to assign "seat1" to a device from vendor
|
||||
|
|
|
|||
|
|
@ -80,14 +80,14 @@ button_event_to_str(enum button_event event) {
|
|||
static inline bool
|
||||
is_inside_bottom_button_area(struct tp_dispatch *tp, struct tp_touch *t)
|
||||
{
|
||||
return t->y >= tp->buttons.bottom_area.top_edge;
|
||||
return t->point.y >= tp->buttons.bottom_area.top_edge;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
is_inside_bottom_right_area(struct tp_dispatch *tp, struct tp_touch *t)
|
||||
{
|
||||
return is_inside_bottom_button_area(tp, t) &&
|
||||
t->x > tp->buttons.bottom_area.rightbutton_left_edge;
|
||||
t->point.x > tp->buttons.bottom_area.rightbutton_left_edge;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
|
|
@ -100,29 +100,29 @@ is_inside_bottom_left_area(struct tp_dispatch *tp, struct tp_touch *t)
|
|||
static inline bool
|
||||
is_inside_top_button_area(struct tp_dispatch *tp, struct tp_touch *t)
|
||||
{
|
||||
return t->y <= tp->buttons.top_area.bottom_edge;
|
||||
return t->point.y <= tp->buttons.top_area.bottom_edge;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
is_inside_top_right_area(struct tp_dispatch *tp, struct tp_touch *t)
|
||||
{
|
||||
return is_inside_top_button_area(tp, t) &&
|
||||
t->x > tp->buttons.top_area.rightbutton_left_edge;
|
||||
t->point.x > tp->buttons.top_area.rightbutton_left_edge;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
is_inside_top_left_area(struct tp_dispatch *tp, struct tp_touch *t)
|
||||
{
|
||||
return is_inside_top_button_area(tp, t) &&
|
||||
t->x < tp->buttons.top_area.leftbutton_right_edge;
|
||||
t->point.x < tp->buttons.top_area.leftbutton_right_edge;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
is_inside_top_middle_area(struct tp_dispatch *tp, struct tp_touch *t)
|
||||
{
|
||||
return is_inside_top_button_area(tp, t) &&
|
||||
t->x >= tp->buttons.top_area.leftbutton_right_edge &&
|
||||
t->x <= tp->buttons.top_area.rightbutton_left_edge;
|
||||
t->point.x >= tp->buttons.top_area.leftbutton_right_edge &&
|
||||
t->point.x <= tp->buttons.top_area.rightbutton_left_edge;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -513,7 +513,7 @@ tp_init_softbuttons(struct tp_dispatch *tp,
|
|||
|
||||
/* button height: 10mm or 15% of the touchpad height,
|
||||
whichever is smaller */
|
||||
if (yres > 1 && (height * 0.15/yres) > 10) {
|
||||
if (!device->abs.fake_resolution && (height * 0.15/yres) > 10) {
|
||||
tp->buttons.bottom_area.top_edge =
|
||||
absinfo_y->maximum - 10 * yres;
|
||||
} else {
|
||||
|
|
@ -550,7 +550,7 @@ tp_init_top_softbuttons(struct tp_dispatch *tp,
|
|||
double topsize_mm = 10 * topbutton_size_mult;
|
||||
double topsize_pct = .15 * topbutton_size_mult;
|
||||
|
||||
if (yres > 1) {
|
||||
if (!device->abs.fake_resolution) {
|
||||
tp->buttons.top_area.bottom_edge =
|
||||
yoffset + topsize_mm * yres;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -45,17 +45,17 @@ enum scroll_event {
|
|||
};
|
||||
|
||||
static uint32_t
|
||||
tp_touch_get_edge(struct tp_dispatch *tp, struct tp_touch *touch)
|
||||
tp_touch_get_edge(struct tp_dispatch *tp, struct tp_touch *t)
|
||||
{
|
||||
uint32_t edge = EDGE_NONE;
|
||||
|
||||
if (tp->scroll.method != LIBINPUT_CONFIG_SCROLL_EDGE)
|
||||
return EDGE_NONE;
|
||||
|
||||
if (touch->x > tp->scroll.right_edge)
|
||||
if (t->point.x > tp->scroll.right_edge)
|
||||
edge |= EDGE_RIGHT;
|
||||
|
||||
if (touch->y > tp->scroll.bottom_edge)
|
||||
if (t->point.y > tp->scroll.bottom_edge)
|
||||
edge |= EDGE_BOTTOM;
|
||||
|
||||
return edge;
|
||||
|
|
@ -76,8 +76,7 @@ tp_edge_scroll_set_state(struct tp_dispatch *tp,
|
|||
break;
|
||||
case EDGE_SCROLL_TOUCH_STATE_EDGE_NEW:
|
||||
t->scroll.edge = tp_touch_get_edge(tp, t);
|
||||
t->scroll.initial_x = t->x;
|
||||
t->scroll.initial_y = t->y;
|
||||
t->scroll.initial = t->point;
|
||||
libinput_timer_set(&t->scroll.timer,
|
||||
t->millis + DEFAULT_SCROLL_LOCK_TIMEOUT);
|
||||
break;
|
||||
|
|
@ -256,6 +255,7 @@ tp_edge_scroll_init(struct tp_dispatch *tp, struct evdev_device *device)
|
|||
*/
|
||||
edge_width = width * .04;
|
||||
edge_height = height * .054;
|
||||
break;
|
||||
}
|
||||
|
||||
tp->scroll.right_edge = device->abs.absinfo_x->maximum - edge_width;
|
||||
|
|
@ -312,8 +312,11 @@ tp_edge_scroll_post_events(struct tp_dispatch *tp, uint64_t time)
|
|||
struct libinput_device *device = &tp->device->base;
|
||||
struct tp_touch *t;
|
||||
enum libinput_pointer_axis axis;
|
||||
double dx, dy, *delta;
|
||||
double *delta;
|
||||
double initial_dx, initial_dy, *initial_delta;
|
||||
struct normalized_coords normalized;
|
||||
const struct normalized_coords zero = { 0.0, 0.0 };
|
||||
const struct discrete_coords zero_discrete = { 0.0, 0.0 };
|
||||
|
||||
if (tp->scroll.method != LIBINPUT_CONFIG_SCROLL_EDGE)
|
||||
return 0;
|
||||
|
|
@ -329,27 +332,28 @@ tp_edge_scroll_post_events(struct tp_dispatch *tp, uint64_t time)
|
|||
pointer_notify_axis(device, time,
|
||||
AS_MASK(t->scroll.direction),
|
||||
LIBINPUT_POINTER_AXIS_SOURCE_FINGER,
|
||||
0.0, 0.0,
|
||||
0, 0);
|
||||
&zero,
|
||||
&zero_discrete);
|
||||
t->scroll.direction = -1;
|
||||
}
|
||||
continue;
|
||||
case EDGE_RIGHT:
|
||||
axis = LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL;
|
||||
delta = &dy;
|
||||
delta = &normalized.y;
|
||||
initial_delta = &initial_dy;
|
||||
break;
|
||||
case EDGE_BOTTOM:
|
||||
axis = LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL;
|
||||
delta = &dx;
|
||||
delta = &normalized.x;
|
||||
initial_delta = &initial_dx;
|
||||
break;
|
||||
default: /* EDGE_RIGHT | EDGE_BOTTOM */
|
||||
continue; /* Don't know direction yet, skip */
|
||||
}
|
||||
|
||||
tp_get_delta(t, &dx, &dy);
|
||||
tp_filter_motion(tp, &dx, &dy, NULL, NULL, time);
|
||||
normalized = tp_get_delta(t);
|
||||
tp_filter_motion(tp, &normalized.x, &normalized.y,
|
||||
NULL, NULL, time);
|
||||
|
||||
switch (t->scroll.edge_state) {
|
||||
case EDGE_SCROLL_TOUCH_STATE_NONE:
|
||||
|
|
@ -359,17 +363,15 @@ tp_edge_scroll_post_events(struct tp_dispatch *tp, uint64_t time)
|
|||
t->scroll.edge_state);
|
||||
break;
|
||||
case EDGE_SCROLL_TOUCH_STATE_EDGE_NEW:
|
||||
initial_dx = t->x - t->scroll.initial_x;
|
||||
initial_dy = t->y - t->scroll.initial_y;
|
||||
initial_dx = t->point.x - t->scroll.initial.x;
|
||||
initial_dy = t->point.y - t->scroll.initial.y;
|
||||
tp_normalize_delta(tp,
|
||||
&initial_dx,
|
||||
&initial_dy);
|
||||
initial_dx,
|
||||
initial_dy,
|
||||
&normalized);
|
||||
if (fabs(*initial_delta) < DEFAULT_SCROLL_THRESHOLD) {
|
||||
dx = 0.0;
|
||||
dy = 0.0;
|
||||
} else {
|
||||
dx = initial_dx;
|
||||
dy = initial_dy;
|
||||
normalized.x = 0.0;
|
||||
normalized.y = 0.0;
|
||||
}
|
||||
break;
|
||||
case EDGE_SCROLL_TOUCH_STATE_EDGE:
|
||||
|
|
@ -382,8 +384,8 @@ tp_edge_scroll_post_events(struct tp_dispatch *tp, uint64_t time)
|
|||
pointer_notify_axis(device, time,
|
||||
AS_MASK(axis),
|
||||
LIBINPUT_POINTER_AXIS_SOURCE_FINGER,
|
||||
dx, dy,
|
||||
0, 0);
|
||||
&normalized,
|
||||
&zero_discrete);
|
||||
t->scroll.direction = axis;
|
||||
|
||||
tp_edge_scroll_handle_event(tp, t, SCROLL_EVENT_POSTED);
|
||||
|
|
@ -397,14 +399,16 @@ tp_edge_scroll_stop_events(struct tp_dispatch *tp, uint64_t time)
|
|||
{
|
||||
struct libinput_device *device = &tp->device->base;
|
||||
struct tp_touch *t;
|
||||
const struct normalized_coords zero = { 0.0, 0.0 };
|
||||
const struct discrete_coords zero_discrete = { 0.0, 0.0 };
|
||||
|
||||
tp_for_each_touch(tp, t) {
|
||||
if (t->scroll.direction != -1) {
|
||||
pointer_notify_axis(device, time,
|
||||
AS_MASK(t->scroll.direction),
|
||||
LIBINPUT_POINTER_AXIS_SOURCE_FINGER,
|
||||
0.0, 0.0,
|
||||
0.0, 0.0);
|
||||
&zero,
|
||||
&zero_discrete);
|
||||
t->scroll.direction = -1;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,45 +31,45 @@
|
|||
|
||||
#define DEFAULT_GESTURE_SWITCH_TIMEOUT 100 /* ms */
|
||||
|
||||
static void
|
||||
tp_get_touches_delta(struct tp_dispatch *tp, double *dx, double *dy, bool average)
|
||||
static struct normalized_coords
|
||||
tp_get_touches_delta(struct tp_dispatch *tp, bool average)
|
||||
{
|
||||
struct tp_touch *t;
|
||||
unsigned int i, nchanged = 0;
|
||||
double tmpx, tmpy;
|
||||
|
||||
*dx = 0.0;
|
||||
*dy = 0.0;
|
||||
struct normalized_coords normalized;
|
||||
struct normalized_coords delta = {0.0, 0.0};
|
||||
|
||||
for (i = 0; i < tp->real_touches; i++) {
|
||||
t = &tp->touches[i];
|
||||
|
||||
if (tp_touch_active(tp, t) && t->dirty) {
|
||||
nchanged++;
|
||||
tp_get_delta(t, &tmpx, &tmpy);
|
||||
normalized = tp_get_delta(t);
|
||||
|
||||
*dx += tmpx;
|
||||
*dy += tmpy;
|
||||
delta.x += normalized.x;
|
||||
delta.y += normalized.y;
|
||||
}
|
||||
}
|
||||
|
||||
if (!average || nchanged == 0)
|
||||
return;
|
||||
return delta;
|
||||
|
||||
*dx /= nchanged;
|
||||
*dy /= nchanged;
|
||||
delta.x /= nchanged;
|
||||
delta.y /= nchanged;
|
||||
|
||||
return delta;
|
||||
}
|
||||
|
||||
static inline void
|
||||
tp_get_combined_touches_delta(struct tp_dispatch *tp, double *dx, double *dy)
|
||||
static inline struct normalized_coords
|
||||
tp_get_combined_touches_delta(struct tp_dispatch *tp)
|
||||
{
|
||||
tp_get_touches_delta(tp, dx, dy, false);
|
||||
return tp_get_touches_delta(tp, false);
|
||||
}
|
||||
|
||||
static inline void
|
||||
tp_get_average_touches_delta(struct tp_dispatch *tp, double *dx, double *dy)
|
||||
static inline struct normalized_coords
|
||||
tp_get_average_touches_delta(struct tp_dispatch *tp)
|
||||
{
|
||||
tp_get_touches_delta(tp, dx, dy, true);
|
||||
return tp_get_touches_delta(tp, true);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -89,39 +89,39 @@ tp_gesture_start(struct tp_dispatch *tp, uint64_t time)
|
|||
static void
|
||||
tp_gesture_post_pointer_motion(struct tp_dispatch *tp, uint64_t time)
|
||||
{
|
||||
double dx = 0.0, dy = 0.0;
|
||||
double dx_unaccel, dy_unaccel;
|
||||
struct normalized_coords delta, unaccel;
|
||||
|
||||
/* When a clickpad is clicked, combine motion of all active touches */
|
||||
if (tp->buttons.is_clickpad && tp->buttons.state)
|
||||
tp_get_combined_touches_delta(tp, &dx, &dy);
|
||||
delta = tp_get_combined_touches_delta(tp);
|
||||
else
|
||||
tp_get_average_touches_delta(tp, &dx, &dy);
|
||||
delta = tp_get_average_touches_delta(tp);
|
||||
|
||||
tp_filter_motion(tp, &dx, &dy, &dx_unaccel, &dy_unaccel, time);
|
||||
tp_filter_motion(tp, &delta.x, &delta.y, &unaccel.x, &unaccel.y, time);
|
||||
|
||||
if (dx != 0.0 || dy != 0.0 || dx_unaccel != 0.0 || dy_unaccel != 0.0) {
|
||||
if (delta.x != 0.0 || delta.y != 0.0 ||
|
||||
unaccel.x != 0.0 || unaccel.y != 0.0) {
|
||||
pointer_notify_motion(&tp->device->base, time,
|
||||
dx, dy, dx_unaccel, dy_unaccel);
|
||||
&delta, &unaccel);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tp_gesture_post_twofinger_scroll(struct tp_dispatch *tp, uint64_t time)
|
||||
{
|
||||
double dx = 0, dy =0;
|
||||
struct normalized_coords delta;
|
||||
|
||||
tp_get_average_touches_delta(tp, &dx, &dy);
|
||||
tp_filter_motion(tp, &dx, &dy, NULL, NULL, time);
|
||||
delta = tp_get_average_touches_delta(tp);
|
||||
tp_filter_motion(tp, &delta.x, &delta.y, NULL, NULL, time);
|
||||
|
||||
if (dx == 0.0 && dy == 0.0)
|
||||
if (delta.x == 0.0 && delta.y == 0.0)
|
||||
return;
|
||||
|
||||
tp_gesture_start(tp, time);
|
||||
evdev_post_scroll(tp->device,
|
||||
time,
|
||||
LIBINPUT_POINTER_AXIS_SOURCE_FINGER,
|
||||
dx, dy);
|
||||
&delta);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -532,12 +532,14 @@ tp_tap_exceeds_motion_threshold(struct tp_dispatch *tp,
|
|||
{
|
||||
int threshold = DEFAULT_TAP_MOVE_THRESHOLD;
|
||||
double dx, dy;
|
||||
struct normalized_coords normalized;
|
||||
|
||||
dx = abs(t->tap.initial_x - t->x);
|
||||
dy = abs(t->tap.initial_y - t->y);
|
||||
tp_normalize_delta(tp, &dx, &dy);
|
||||
dx = abs(t->tap.initial.x - t->point.x);
|
||||
dy = abs(t->tap.initial.y - t->point.y);
|
||||
tp_normalize_delta(tp, dx, dy, &normalized);
|
||||
|
||||
return dx * dx + dy * dy > threshold * threshold;
|
||||
return normalized.x * normalized.x + normalized.y * normalized.y
|
||||
> threshold * threshold;
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
@ -571,8 +573,7 @@ tp_tap_handle_state(struct tp_dispatch *tp, uint64_t time)
|
|||
|
||||
if (t->state == TOUCH_BEGIN) {
|
||||
t->tap.state = TAP_TOUCH_STATE_TOUCH;
|
||||
t->tap.initial_x = t->x;
|
||||
t->tap.initial_y = t->y;
|
||||
t->tap.initial = t->point;
|
||||
tp_tap_handle_event(tp, t, TAP_EVENT_TOUCH, time);
|
||||
} else if (t->state == TOUCH_END) {
|
||||
tp_tap_handle_event(tp, t, TAP_EVENT_RELEASE, time);
|
||||
|
|
|
|||
|
|
@ -29,7 +29,9 @@
|
|||
|
||||
#include "evdev-mt-touchpad.h"
|
||||
|
||||
#define DEFAULT_ACCEL_NUMERATOR 1200.0
|
||||
/* Number found by trial-and error, seems to be 1200, divided by the
|
||||
* TP_MAGIC_SLOWDOWN in filter.c */
|
||||
#define DEFAULT_ACCEL_NUMERATOR 3000.0
|
||||
#define DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR 700.0
|
||||
#define DEFAULT_TRACKPOINT_ACTIVITY_TIMEOUT 500 /* ms */
|
||||
|
||||
|
|
@ -46,7 +48,7 @@ tp_hysteresis(int in, int center, int margin)
|
|||
return center + diff + margin;
|
||||
}
|
||||
|
||||
static inline struct tp_motion *
|
||||
static inline struct device_coords *
|
||||
tp_motion_history_offset(struct tp_touch *t, int offset)
|
||||
{
|
||||
int offset_index =
|
||||
|
|
@ -87,8 +89,7 @@ tp_motion_history_push(struct tp_touch *t)
|
|||
if (t->history.count < TOUCHPAD_HISTORY_LENGTH)
|
||||
t->history.count++;
|
||||
|
||||
t->history.samples[motion_index].x = t->x;
|
||||
t->history.samples[motion_index].y = t->y;
|
||||
t->history.samples[motion_index] = t->point;
|
||||
t->history.index = motion_index;
|
||||
}
|
||||
|
||||
|
|
@ -96,23 +97,22 @@ static inline void
|
|||
tp_motion_hysteresis(struct tp_dispatch *tp,
|
||||
struct tp_touch *t)
|
||||
{
|
||||
int x = t->x,
|
||||
y = t->y;
|
||||
int x = t->point.x,
|
||||
y = t->point.y;
|
||||
|
||||
if (t->history.count == 0) {
|
||||
t->hysteresis.center_x = t->x;
|
||||
t->hysteresis.center_y = t->y;
|
||||
t->hysteresis_center = t->point;
|
||||
} else {
|
||||
x = tp_hysteresis(x,
|
||||
t->hysteresis.center_x,
|
||||
tp->hysteresis.margin_x);
|
||||
t->hysteresis_center.x,
|
||||
tp->hysteresis_margin.x);
|
||||
y = tp_hysteresis(y,
|
||||
t->hysteresis.center_y,
|
||||
tp->hysteresis.margin_y);
|
||||
t->hysteresis.center_x = x;
|
||||
t->hysteresis.center_y = y;
|
||||
t->x = x;
|
||||
t->y = y;
|
||||
t->hysteresis_center.y,
|
||||
tp->hysteresis_margin.y);
|
||||
t->hysteresis_center.x = x;
|
||||
t->hysteresis_center.y = y;
|
||||
t->point.x = x;
|
||||
t->point.y = y;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -252,24 +252,26 @@ tp_estimate_delta(int x0, int x1, int x2, int x3)
|
|||
return (x0 + x1 - x2 - x3) / 4.0;
|
||||
}
|
||||
|
||||
void
|
||||
tp_get_delta(struct tp_touch *t, double *dx, double *dy)
|
||||
struct normalized_coords
|
||||
tp_get_delta(struct tp_touch *t)
|
||||
{
|
||||
if (t->history.count < TOUCHPAD_MIN_SAMPLES) {
|
||||
*dx = 0;
|
||||
*dy = 0;
|
||||
return;
|
||||
}
|
||||
double dx, dy; /* in device coords */
|
||||
struct normalized_coords normalized = { 0.0, 0.0 };
|
||||
|
||||
*dx = tp_estimate_delta(tp_motion_history_offset(t, 0)->x,
|
||||
tp_motion_history_offset(t, 1)->x,
|
||||
tp_motion_history_offset(t, 2)->x,
|
||||
tp_motion_history_offset(t, 3)->x);
|
||||
*dy = tp_estimate_delta(tp_motion_history_offset(t, 0)->y,
|
||||
tp_motion_history_offset(t, 1)->y,
|
||||
tp_motion_history_offset(t, 2)->y,
|
||||
tp_motion_history_offset(t, 3)->y);
|
||||
tp_normalize_delta(t->tp, dx, dy);
|
||||
if (t->history.count < TOUCHPAD_MIN_SAMPLES)
|
||||
return normalized;
|
||||
|
||||
dx = tp_estimate_delta(tp_motion_history_offset(t, 0)->x,
|
||||
tp_motion_history_offset(t, 1)->x,
|
||||
tp_motion_history_offset(t, 2)->x,
|
||||
tp_motion_history_offset(t, 3)->x);
|
||||
dy = tp_estimate_delta(tp_motion_history_offset(t, 0)->y,
|
||||
tp_motion_history_offset(t, 1)->y,
|
||||
tp_motion_history_offset(t, 2)->y,
|
||||
tp_motion_history_offset(t, 3)->y);
|
||||
tp_normalize_delta(t->tp, dx, dy, &normalized);
|
||||
|
||||
return normalized;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -281,13 +283,13 @@ tp_process_absolute(struct tp_dispatch *tp,
|
|||
|
||||
switch(e->code) {
|
||||
case ABS_MT_POSITION_X:
|
||||
t->x = e->value;
|
||||
t->point.x = e->value;
|
||||
t->millis = time;
|
||||
t->dirty = true;
|
||||
tp->queued |= TOUCHPAD_EVENT_MOTION;
|
||||
break;
|
||||
case ABS_MT_POSITION_Y:
|
||||
t->y = e->value;
|
||||
t->point.y = e->value;
|
||||
t->millis = time;
|
||||
t->dirty = true;
|
||||
tp->queued |= TOUCHPAD_EVENT_MOTION;
|
||||
|
|
@ -312,13 +314,13 @@ tp_process_absolute_st(struct tp_dispatch *tp,
|
|||
|
||||
switch(e->code) {
|
||||
case ABS_X:
|
||||
t->x = e->value;
|
||||
t->point.x = e->value;
|
||||
t->millis = time;
|
||||
t->dirty = true;
|
||||
tp->queued |= TOUCHPAD_EVENT_MOTION;
|
||||
break;
|
||||
case ABS_Y:
|
||||
t->y = e->value;
|
||||
t->point.y = e->value;
|
||||
t->millis = time;
|
||||
t->dirty = true;
|
||||
tp->queued |= TOUCHPAD_EVENT_MOTION;
|
||||
|
|
@ -418,8 +420,8 @@ tp_unpin_finger(struct tp_dispatch *tp, struct tp_touch *t)
|
|||
if (!t->pinned.is_pinned)
|
||||
return;
|
||||
|
||||
xdist = abs(t->x - t->pinned.center_x);
|
||||
ydist = abs(t->y - t->pinned.center_y);
|
||||
xdist = abs(t->point.x - t->pinned.center.x);
|
||||
ydist = abs(t->point.y - t->pinned.center.y);
|
||||
|
||||
if (xdist * xdist + ydist * ydist >=
|
||||
tp->buttons.motion_dist * tp->buttons.motion_dist) {
|
||||
|
|
@ -428,8 +430,8 @@ tp_unpin_finger(struct tp_dispatch *tp, struct tp_touch *t)
|
|||
}
|
||||
|
||||
/* The finger may slowly drift, adjust the center */
|
||||
t->pinned.center_x = t->x + t->pinned.center_x / 2;
|
||||
t->pinned.center_y = t->y + t->pinned.center_y / 2;
|
||||
t->pinned.center.x = t->point.x + t->pinned.center.x / 2;
|
||||
t->pinned.center.y = t->point.y + t->pinned.center.y / 2;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -439,8 +441,7 @@ tp_pin_fingers(struct tp_dispatch *tp)
|
|||
|
||||
tp_for_each_touch(tp, t) {
|
||||
t->pinned.is_pinned = true;
|
||||
t->pinned.center_x = t->x;
|
||||
t->pinned.center_y = t->y;
|
||||
t->pinned.center = t->point;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -466,8 +467,9 @@ tp_palm_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
|
|||
*/
|
||||
if (t->palm.is_palm) {
|
||||
if (time < t->palm.time + PALM_TIMEOUT &&
|
||||
(t->x > tp->palm.left_edge && t->x < tp->palm.right_edge)) {
|
||||
int dirs = vector_get_direction(t->x - t->palm.x, t->y - t->palm.y);
|
||||
(t->point.x > tp->palm.left_edge && t->point.x < tp->palm.right_edge)) {
|
||||
int dirs = vector_get_direction(t->point.x - t->palm.first.x,
|
||||
t->point.y - t->palm.first.y);
|
||||
if ((dirs & DIRECTIONS) && !(dirs & ~DIRECTIONS)) {
|
||||
t->palm.is_palm = false;
|
||||
}
|
||||
|
|
@ -478,7 +480,7 @@ tp_palm_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
|
|||
/* palm must start in exclusion zone, it's ok to move into
|
||||
the zone without being a palm */
|
||||
if (t->state != TOUCH_BEGIN ||
|
||||
(t->x > tp->palm.left_edge && t->x < tp->palm.right_edge))
|
||||
(t->point.x > tp->palm.left_edge && t->point.x < tp->palm.right_edge))
|
||||
return;
|
||||
|
||||
/* don't detect palm in software button areas, it's
|
||||
|
|
@ -490,8 +492,7 @@ tp_palm_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
|
|||
|
||||
t->palm.is_palm = true;
|
||||
t->palm.time = time;
|
||||
t->palm.x = t->x;
|
||||
t->palm.y = t->y;
|
||||
t->palm.first = t->point;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -566,8 +567,7 @@ tp_process_state(struct tp_dispatch *tp, uint64_t time)
|
|||
tp_motion_history_reset(t);
|
||||
|
||||
if (i >= tp->real_touches && t->state != TOUCH_NONE) {
|
||||
t->x = first->x;
|
||||
t->y = first->y;
|
||||
t->point = first->point;
|
||||
if (!t->dirty)
|
||||
t->dirty = first->dirty;
|
||||
}
|
||||
|
|
@ -964,16 +964,23 @@ tp_init_accel(struct tp_dispatch *tp, double diagonal)
|
|||
{
|
||||
int res_x, res_y;
|
||||
|
||||
if (tp->has_mt) {
|
||||
res_x = libevdev_get_abs_resolution(tp->device->evdev,
|
||||
ABS_MT_POSITION_X);
|
||||
res_y = libevdev_get_abs_resolution(tp->device->evdev,
|
||||
ABS_MT_POSITION_Y);
|
||||
} else {
|
||||
res_x = libevdev_get_abs_resolution(tp->device->evdev,
|
||||
ABS_X);
|
||||
res_y = libevdev_get_abs_resolution(tp->device->evdev,
|
||||
ABS_Y);
|
||||
res_x = tp->device->abs.absinfo_x->resolution;
|
||||
res_y = tp->device->abs.absinfo_y->resolution;
|
||||
|
||||
/* Mac touchpads seem to all be the same size (except the most
|
||||
* recent ones)
|
||||
* http://www.moshi.com/trackpad-protector-trackguard-macbook-pro#silver
|
||||
*/
|
||||
if (tp->model == MODEL_UNIBODY_MACBOOK && tp->device->abs.fake_resolution) {
|
||||
const struct input_absinfo *abs;
|
||||
int width, height;
|
||||
|
||||
abs = tp->device->abs.absinfo_x;
|
||||
width = abs->maximum - abs->minimum;
|
||||
abs = tp->device->abs.absinfo_y;
|
||||
height = abs->maximum - abs->minimum;
|
||||
res_x = width/104.4;
|
||||
res_y = height/75.4;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -986,18 +993,6 @@ tp_init_accel(struct tp_dispatch *tp, double diagonal)
|
|||
if (res_x > 1 && res_y > 1) {
|
||||
tp->accel.x_scale_coeff = (DEFAULT_MOUSE_DPI/25.4) / res_x;
|
||||
tp->accel.y_scale_coeff = (DEFAULT_MOUSE_DPI/25.4) / res_y;
|
||||
|
||||
/* FIXME: once normalized, touchpads see the same
|
||||
acceleration as mice. that is technically correct but
|
||||
subjectively wrong, we expect a touchpad to be a lot
|
||||
slower than a mouse.
|
||||
For now, apply a magic factor here until this is
|
||||
fixed in the actual filter code.
|
||||
*/
|
||||
{
|
||||
tp->accel.x_scale_coeff *= TP_MAGIC_SLOWDOWN;
|
||||
tp->accel.y_scale_coeff *= TP_MAGIC_SLOWDOWN;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* For touchpads where the driver does not provide resolution, fall
|
||||
|
|
@ -1007,7 +1002,9 @@ tp_init_accel(struct tp_dispatch *tp, double diagonal)
|
|||
tp->accel.y_scale_coeff = DEFAULT_ACCEL_NUMERATOR / diagonal;
|
||||
}
|
||||
|
||||
if (evdev_device_init_pointer_acceleration(tp->device) == -1)
|
||||
if (evdev_device_init_pointer_acceleration(
|
||||
tp->device,
|
||||
touchpad_accel_profile_linear) == -1)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
|
|
@ -1137,6 +1134,32 @@ tp_init_sendevents(struct tp_dispatch *tp,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
tp_fix_resolution(struct tp_dispatch *tp, struct evdev_device *device)
|
||||
{
|
||||
struct libinput *libinput = device->base.seat->libinput;
|
||||
const char *prop;
|
||||
unsigned int resx, resy;
|
||||
|
||||
prop = udev_device_get_property_value(device->udev_device,
|
||||
"TOUCHPAD_RESOLUTION");
|
||||
if (!prop)
|
||||
return;
|
||||
|
||||
if (parse_touchpad_resolution_property(prop, &resx, &resy) == -1) {
|
||||
log_error(libinput,
|
||||
"Touchpad resolution property set for '%s', but invalid.\n",
|
||||
device->devname);
|
||||
return;
|
||||
}
|
||||
|
||||
if (evdev_fix_abs_resolution(device,
|
||||
tp->has_mt ? ABS_MT_POSITION_X : ABS_X,
|
||||
tp->has_mt ? ABS_MT_POSITION_Y : ABS_Y,
|
||||
resx, resy))
|
||||
device->abs.fake_resolution = 0;
|
||||
}
|
||||
|
||||
static int
|
||||
tp_init(struct tp_dispatch *tp,
|
||||
struct evdev_device *device)
|
||||
|
|
@ -1150,15 +1173,17 @@ tp_init(struct tp_dispatch *tp,
|
|||
if (tp_init_slots(tp, device) != 0)
|
||||
return -1;
|
||||
|
||||
tp_fix_resolution(tp, device);
|
||||
|
||||
width = abs(device->abs.absinfo_x->maximum -
|
||||
device->abs.absinfo_x->minimum);
|
||||
height = abs(device->abs.absinfo_y->maximum -
|
||||
device->abs.absinfo_y->minimum);
|
||||
diagonal = sqrt(width*width + height*height);
|
||||
|
||||
tp->hysteresis.margin_x =
|
||||
tp->hysteresis_margin.x =
|
||||
diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
|
||||
tp->hysteresis.margin_y =
|
||||
tp->hysteresis_margin.y =
|
||||
diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
|
||||
|
||||
if (tp_init_accel(tp, diagonal) != 0)
|
||||
|
|
|
|||
|
|
@ -34,10 +34,8 @@
|
|||
|
||||
#define VENDOR_ID_APPLE 0x5ac
|
||||
|
||||
/* Touchpad slowdown factor, see the FIXME in tp_init_accel() */
|
||||
#define TP_MAGIC_SLOWDOWN 0.4
|
||||
/* Convert mm to a distance normalized to DEFAULT_MOUSE_DPI */
|
||||
#define TP_MM_TO_DPI_NORMALIZED(mm) (DEFAULT_MOUSE_DPI/25.4 * TP_MAGIC_SLOWDOWN * mm)
|
||||
#define TP_MM_TO_DPI_NORMALIZED(mm) (DEFAULT_MOUSE_DPI/25.4 * mm)
|
||||
|
||||
enum touchpad_event {
|
||||
TOUCHPAD_EVENT_NONE = 0,
|
||||
|
|
@ -122,30 +120,21 @@ enum tp_edge_scroll_touch_state {
|
|||
EDGE_SCROLL_TOUCH_STATE_AREA,
|
||||
};
|
||||
|
||||
struct tp_motion {
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
};
|
||||
|
||||
struct tp_touch {
|
||||
struct tp_dispatch *tp;
|
||||
enum touch_state state;
|
||||
bool has_ended; /* TRACKING_ID == -1 */
|
||||
bool dirty;
|
||||
int32_t x; /* in device coordinates */
|
||||
int32_t y; /* in device coordinates */
|
||||
struct device_coords point;
|
||||
uint64_t millis;
|
||||
|
||||
struct {
|
||||
struct tp_motion samples[TOUCHPAD_HISTORY_LENGTH];
|
||||
struct device_coords samples[TOUCHPAD_HISTORY_LENGTH];
|
||||
unsigned int index;
|
||||
unsigned int count;
|
||||
} history;
|
||||
|
||||
struct {
|
||||
int32_t center_x; /* in device coordinates */
|
||||
int32_t center_y; /* in device coordinates */
|
||||
} hysteresis;
|
||||
struct device_coords hysteresis_center;
|
||||
|
||||
/* A pinned touchpoint is the one that pressed the physical button
|
||||
* on a clickpad. After the release, it won't move until the center
|
||||
|
|
@ -153,8 +142,7 @@ struct tp_touch {
|
|||
*/
|
||||
struct {
|
||||
bool is_pinned;
|
||||
int32_t center_x; /* in device coordinates */
|
||||
int32_t center_y; /* in device coordinates */
|
||||
struct device_coords center;
|
||||
} pinned;
|
||||
|
||||
/* Software-button state and timeout if applicable */
|
||||
|
|
@ -167,7 +155,7 @@ struct tp_touch {
|
|||
|
||||
struct {
|
||||
enum tp_tap_touch_state state;
|
||||
int32_t initial_x, initial_y; /* in device coordinates */
|
||||
struct device_coords initial;
|
||||
} tap;
|
||||
|
||||
struct {
|
||||
|
|
@ -175,14 +163,12 @@ struct tp_touch {
|
|||
uint32_t edge;
|
||||
int direction;
|
||||
struct libinput_timer timer;
|
||||
int32_t initial_x; /* in device coordinates */
|
||||
int32_t initial_y; /* in device coordinates */
|
||||
struct device_coords initial;
|
||||
} scroll;
|
||||
|
||||
struct {
|
||||
bool is_palm;
|
||||
int32_t x, y; /* first coordinates if is_palm == true,
|
||||
in device coordinates */
|
||||
struct device_coords first; /* first coordinates if is_palm == true */
|
||||
uint32_t time; /* first timestamp if is_palm == true */
|
||||
} palm;
|
||||
};
|
||||
|
|
@ -207,10 +193,7 @@ struct tp_dispatch {
|
|||
*/
|
||||
unsigned int fake_touches;
|
||||
|
||||
struct {
|
||||
int32_t margin_x; /* in device coordiantes */
|
||||
int32_t margin_y; /* in device coordiantes */
|
||||
} hysteresis;
|
||||
struct device_coords hysteresis_margin;
|
||||
|
||||
struct {
|
||||
double x_scale_coeff;
|
||||
|
|
@ -292,14 +275,16 @@ struct tp_dispatch {
|
|||
for (unsigned int _i = 0; _i < (_tp)->ntouches && (_t = &(_tp)->touches[_i]); _i++)
|
||||
|
||||
static inline void
|
||||
tp_normalize_delta(struct tp_dispatch *tp, double *dx, double *dy)
|
||||
tp_normalize_delta(struct tp_dispatch *tp,
|
||||
double dx, double dy,
|
||||
struct normalized_coords *normalized)
|
||||
{
|
||||
*dx = *dx * tp->accel.x_scale_coeff;
|
||||
*dy = *dy * tp->accel.y_scale_coeff;
|
||||
normalized->x = dx * tp->accel.x_scale_coeff;
|
||||
normalized->y = dy * tp->accel.y_scale_coeff;
|
||||
}
|
||||
|
||||
void
|
||||
tp_get_delta(struct tp_touch *t, double *dx, double *dy);
|
||||
struct normalized_coords
|
||||
tp_get_delta(struct tp_touch *t);
|
||||
|
||||
void
|
||||
tp_filter_motion(struct tp_dispatch *tp,
|
||||
|
|
|
|||
437
src/evdev.c
437
src/evdev.c
|
|
@ -193,12 +193,13 @@ evdev_device_led_update(struct evdev_device *device, enum libinput_led leds)
|
|||
}
|
||||
|
||||
static void
|
||||
transform_absolute(struct evdev_device *device, int32_t *x, int32_t *y)
|
||||
transform_absolute(struct evdev_device *device,
|
||||
struct device_coords *point)
|
||||
{
|
||||
if (!device->abs.apply_calibration)
|
||||
return;
|
||||
|
||||
matrix_mult_vec(&device->abs.calibration, x, y);
|
||||
matrix_mult_vec(&device->abs.calibration, &point->x, &point->y);
|
||||
}
|
||||
|
||||
static inline double
|
||||
|
|
@ -224,18 +225,26 @@ evdev_device_transform_y(struct evdev_device *device,
|
|||
return scale_axis(device->abs.absinfo_y, y, height);
|
||||
}
|
||||
|
||||
static inline void
|
||||
normalize_delta(struct evdev_device *device,
|
||||
const struct device_coords *delta,
|
||||
struct normalized_coords *normalized)
|
||||
{
|
||||
normalized->x = delta->x * (double)device->dpi / DEFAULT_MOUSE_DPI;
|
||||
normalized->y = delta->y * (double)device->dpi / DEFAULT_MOUSE_DPI;
|
||||
}
|
||||
|
||||
static void
|
||||
evdev_flush_pending_event(struct evdev_device *device, uint64_t time)
|
||||
{
|
||||
struct libinput *libinput = device->base.seat->libinput;
|
||||
struct motion_params motion;
|
||||
double dx_unaccel, dy_unaccel;
|
||||
int32_t cx, cy;
|
||||
int32_t x, y;
|
||||
int slot;
|
||||
int seat_slot;
|
||||
struct libinput_device *base = &device->base;
|
||||
struct libinput_seat *seat = base->seat;
|
||||
struct normalized_coords accel, unaccel;
|
||||
struct device_coords point;
|
||||
|
||||
slot = device->mt.slot;
|
||||
|
||||
|
|
@ -243,12 +252,9 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time)
|
|||
case EVDEV_NONE:
|
||||
return;
|
||||
case EVDEV_RELATIVE_MOTION:
|
||||
dx_unaccel = device->rel.dx / ((double) device->dpi /
|
||||
DEFAULT_MOUSE_DPI);
|
||||
dy_unaccel = device->rel.dy / ((double) device->dpi /
|
||||
DEFAULT_MOUSE_DPI);
|
||||
device->rel.dx = 0;
|
||||
device->rel.dy = 0;
|
||||
normalize_delta(device, &device->rel, &unaccel);
|
||||
device->rel.x = 0;
|
||||
device->rel.y = 0;
|
||||
|
||||
/* Use unaccelerated deltas for pointing stick scroll */
|
||||
if (device->scroll.method == LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN &&
|
||||
|
|
@ -256,23 +262,23 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time)
|
|||
if (device->scroll.button_scroll_active)
|
||||
evdev_post_scroll(device, time,
|
||||
LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS,
|
||||
dx_unaccel, dy_unaccel);
|
||||
&unaccel);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Apply pointer acceleration. */
|
||||
motion.dx = dx_unaccel;
|
||||
motion.dy = dy_unaccel;
|
||||
motion.dx = unaccel.x;
|
||||
motion.dy = unaccel.y;
|
||||
filter_dispatch(device->pointer.filter, &motion, device, time);
|
||||
accel.x = motion.dx;
|
||||
accel.y = motion.dy;
|
||||
|
||||
if (motion.dx == 0.0 && motion.dy == 0.0 &&
|
||||
dx_unaccel == 0.0 && dy_unaccel == 0.0) {
|
||||
if (accel.x == 0.0 && accel.y == 0.0 &&
|
||||
unaccel.x == 0.0 && unaccel.y == 0.0) {
|
||||
break;
|
||||
}
|
||||
|
||||
pointer_notify_motion(base, time,
|
||||
motion.dx, motion.dy,
|
||||
dx_unaccel, dy_unaccel);
|
||||
pointer_notify_motion(base, time, &accel, &unaccel);
|
||||
break;
|
||||
case EVDEV_ABSOLUTE_MT_DOWN:
|
||||
if (!(device->seat_caps & EVDEV_DEVICE_TOUCH))
|
||||
|
|
@ -293,25 +299,25 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time)
|
|||
break;
|
||||
|
||||
seat->slot_map |= 1 << seat_slot;
|
||||
x = device->mt.slots[slot].x;
|
||||
y = device->mt.slots[slot].y;
|
||||
transform_absolute(device, &x, &y);
|
||||
point = device->mt.slots[slot].point;
|
||||
transform_absolute(device, &point);
|
||||
|
||||
touch_notify_touch_down(base, time, slot, seat_slot, x, y);
|
||||
touch_notify_touch_down(base, time, slot, seat_slot,
|
||||
&point);
|
||||
break;
|
||||
case EVDEV_ABSOLUTE_MT_MOTION:
|
||||
if (!(device->seat_caps & EVDEV_DEVICE_TOUCH))
|
||||
break;
|
||||
|
||||
seat_slot = device->mt.slots[slot].seat_slot;
|
||||
x = device->mt.slots[slot].x;
|
||||
y = device->mt.slots[slot].y;
|
||||
point = device->mt.slots[slot].point;
|
||||
|
||||
if (seat_slot == -1)
|
||||
break;
|
||||
|
||||
transform_absolute(device, &x, &y);
|
||||
touch_notify_touch_motion(base, time, slot, seat_slot, x, y);
|
||||
transform_absolute(device, &point);
|
||||
touch_notify_touch_motion(base, time, slot, seat_slot,
|
||||
&point);
|
||||
break;
|
||||
case EVDEV_ABSOLUTE_MT_UP:
|
||||
if (!(device->seat_caps & EVDEV_DEVICE_TOUCH))
|
||||
|
|
@ -347,18 +353,14 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time)
|
|||
|
||||
seat->slot_map |= 1 << seat_slot;
|
||||
|
||||
cx = device->abs.x;
|
||||
cy = device->abs.y;
|
||||
transform_absolute(device, &cx, &cy);
|
||||
point = device->abs.point;
|
||||
transform_absolute(device, &point);
|
||||
|
||||
touch_notify_touch_down(base, time, -1, seat_slot, cx, cy);
|
||||
touch_notify_touch_down(base, time, -1, seat_slot, &point);
|
||||
break;
|
||||
case EVDEV_ABSOLUTE_MOTION:
|
||||
cx = device->abs.x;
|
||||
cy = device->abs.y;
|
||||
transform_absolute(device, &cx, &cy);
|
||||
x = cx;
|
||||
y = cy;
|
||||
point = device->abs.point;
|
||||
transform_absolute(device, &point);
|
||||
|
||||
if (device->seat_caps & EVDEV_DEVICE_TOUCH) {
|
||||
seat_slot = device->abs.seat_slot;
|
||||
|
|
@ -366,9 +368,10 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time)
|
|||
if (seat_slot == -1)
|
||||
break;
|
||||
|
||||
touch_notify_touch_motion(base, time, -1, seat_slot, x, y);
|
||||
touch_notify_touch_motion(base, time, -1, seat_slot,
|
||||
&point);
|
||||
} else if (device->seat_caps & EVDEV_DEVICE_POINTER) {
|
||||
pointer_notify_motion_absolute(base, time, x, y);
|
||||
pointer_notify_motion_absolute(base, time, &point);
|
||||
}
|
||||
break;
|
||||
case EVDEV_ABSOLUTE_TOUCH_UP:
|
||||
|
|
@ -547,12 +550,12 @@ evdev_process_touch(struct evdev_device *device,
|
|||
device->pending_event = EVDEV_ABSOLUTE_MT_UP;
|
||||
break;
|
||||
case ABS_MT_POSITION_X:
|
||||
device->mt.slots[device->mt.slot].x = e->value;
|
||||
device->mt.slots[device->mt.slot].point.x = e->value;
|
||||
if (device->pending_event == EVDEV_NONE)
|
||||
device->pending_event = EVDEV_ABSOLUTE_MT_MOTION;
|
||||
break;
|
||||
case ABS_MT_POSITION_Y:
|
||||
device->mt.slots[device->mt.slot].y = e->value;
|
||||
device->mt.slots[device->mt.slot].point.y = e->value;
|
||||
if (device->pending_event == EVDEV_NONE)
|
||||
device->pending_event = EVDEV_ABSOLUTE_MT_MOTION;
|
||||
break;
|
||||
|
|
@ -565,12 +568,12 @@ evdev_process_absolute_motion(struct evdev_device *device,
|
|||
{
|
||||
switch (e->code) {
|
||||
case ABS_X:
|
||||
device->abs.x = e->value;
|
||||
device->abs.point.x = e->value;
|
||||
if (device->pending_event == EVDEV_NONE)
|
||||
device->pending_event = EVDEV_ABSOLUTE_MOTION;
|
||||
break;
|
||||
case ABS_Y:
|
||||
device->abs.y = e->value;
|
||||
device->abs.point.y = e->value;
|
||||
if (device->pending_event == EVDEV_NONE)
|
||||
device->pending_event = EVDEV_ABSOLUTE_MOTION;
|
||||
break;
|
||||
|
|
@ -582,64 +585,71 @@ evdev_notify_axis(struct evdev_device *device,
|
|||
uint64_t time,
|
||||
uint32_t axes,
|
||||
enum libinput_pointer_axis_source source,
|
||||
double x, double y,
|
||||
double x_discrete, double y_discrete)
|
||||
const struct normalized_coords *delta_in,
|
||||
const struct discrete_coords *discrete_in)
|
||||
{
|
||||
struct normalized_coords delta = *delta_in;
|
||||
struct discrete_coords discrete = *discrete_in;
|
||||
|
||||
if (device->scroll.natural_scrolling_enabled) {
|
||||
x *= -1;
|
||||
y *= -1;
|
||||
x_discrete *= -1;
|
||||
y_discrete *= -1;
|
||||
delta.x *= -1;
|
||||
delta.y *= -1;
|
||||
discrete.x *= -1;
|
||||
discrete.y *= -1;
|
||||
}
|
||||
|
||||
pointer_notify_axis(&device->base,
|
||||
time,
|
||||
axes,
|
||||
source,
|
||||
x, y,
|
||||
x_discrete, y_discrete);
|
||||
&delta,
|
||||
&discrete);
|
||||
}
|
||||
|
||||
static inline void
|
||||
evdev_process_relative(struct evdev_device *device,
|
||||
struct input_event *e, uint64_t time)
|
||||
{
|
||||
struct normalized_coords wheel_degrees = { 0.0, 0.0 };
|
||||
struct discrete_coords discrete = { 0.0, 0.0 };
|
||||
|
||||
switch (e->code) {
|
||||
case REL_X:
|
||||
if (device->pending_event != EVDEV_RELATIVE_MOTION)
|
||||
evdev_flush_pending_event(device, time);
|
||||
device->rel.dx += e->value;
|
||||
device->rel.x += e->value;
|
||||
device->pending_event = EVDEV_RELATIVE_MOTION;
|
||||
break;
|
||||
case REL_Y:
|
||||
if (device->pending_event != EVDEV_RELATIVE_MOTION)
|
||||
evdev_flush_pending_event(device, time);
|
||||
device->rel.dy += e->value;
|
||||
device->rel.y += e->value;
|
||||
device->pending_event = EVDEV_RELATIVE_MOTION;
|
||||
break;
|
||||
case REL_WHEEL:
|
||||
evdev_flush_pending_event(device, time);
|
||||
wheel_degrees.y = -1 * e->value *
|
||||
device->scroll.wheel_click_angle;
|
||||
discrete.y = -1 * e->value;
|
||||
evdev_notify_axis(
|
||||
device,
|
||||
time,
|
||||
AS_MASK(LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL),
|
||||
LIBINPUT_POINTER_AXIS_SOURCE_WHEEL,
|
||||
0.0,
|
||||
-1 * e->value * device->scroll.wheel_click_angle,
|
||||
0.0,
|
||||
-1 * e->value);
|
||||
&wheel_degrees,
|
||||
&discrete);
|
||||
break;
|
||||
case REL_HWHEEL:
|
||||
evdev_flush_pending_event(device, time);
|
||||
wheel_degrees.x = e->value * device->scroll.wheel_click_angle;
|
||||
discrete.x = e->value;
|
||||
evdev_notify_axis(
|
||||
device,
|
||||
time,
|
||||
AS_MASK(LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL),
|
||||
LIBINPUT_POINTER_AXIS_SOURCE_WHEEL,
|
||||
e->value * device->scroll.wheel_click_angle,
|
||||
0.0,
|
||||
e->value,
|
||||
0.0);
|
||||
&wheel_degrees,
|
||||
&discrete);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -1257,11 +1267,10 @@ evdev_accel_config_get_default_speed(struct libinput_device *device)
|
|||
}
|
||||
|
||||
int
|
||||
evdev_device_init_pointer_acceleration(struct evdev_device *device)
|
||||
evdev_device_init_pointer_acceleration(struct evdev_device *device,
|
||||
accel_profile_func_t profile)
|
||||
{
|
||||
device->pointer.filter =
|
||||
create_pointer_accelerator_filter(
|
||||
pointer_accel_profile_linear);
|
||||
device->pointer.filter = create_pointer_accelerator_filter(profile);
|
||||
if (!device->pointer.filter)
|
||||
return -1;
|
||||
|
||||
|
|
@ -1342,23 +1351,66 @@ evdev_read_dpi_prop(struct evdev_device *device)
|
|||
return dpi;
|
||||
}
|
||||
|
||||
static inline int
|
||||
evdev_fix_abs_resolution(struct libevdev *evdev,
|
||||
unsigned int code,
|
||||
const struct input_absinfo *absinfo)
|
||||
/* Return 1 if the given resolutions have been set, or 0 otherwise */
|
||||
inline int
|
||||
evdev_fix_abs_resolution(struct evdev_device *device,
|
||||
unsigned int xcode,
|
||||
unsigned int ycode,
|
||||
int xresolution,
|
||||
int yresolution)
|
||||
{
|
||||
struct libinput *libinput = device->base.seat->libinput;
|
||||
struct libevdev *evdev = device->evdev;
|
||||
const struct input_absinfo *absx, *absy;
|
||||
struct input_absinfo fixed;
|
||||
int rc = 0;
|
||||
|
||||
if (absinfo->resolution == 0) {
|
||||
fixed = *absinfo;
|
||||
fixed.resolution = 1;
|
||||
/* libevdev_set_abs_info() changes the absinfo we already
|
||||
have a pointer to, no need to fetch it again */
|
||||
libevdev_set_abs_info(evdev, code, &fixed);
|
||||
return 1;
|
||||
} else {
|
||||
if (!(xcode == ABS_X && ycode == ABS_Y) &&
|
||||
!(xcode == ABS_MT_POSITION_X && ycode == ABS_MT_POSITION_Y)) {
|
||||
log_bug_libinput(libinput,
|
||||
"Invalid x/y code combination %d/%d\n",
|
||||
xcode, ycode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (xresolution == 0 || yresolution == 0 ||
|
||||
(xresolution == EVDEV_FAKE_RESOLUTION && xresolution != yresolution) ||
|
||||
(yresolution == EVDEV_FAKE_RESOLUTION && xresolution != yresolution)) {
|
||||
log_bug_libinput(libinput,
|
||||
"Invalid x/y resolutions %d/%d\n",
|
||||
xresolution, yresolution);
|
||||
return 0;
|
||||
}
|
||||
|
||||
absx = libevdev_get_abs_info(evdev, xcode);
|
||||
absy = libevdev_get_abs_info(evdev, ycode);
|
||||
|
||||
if ((absx->resolution == 0 && absy->resolution != 0) ||
|
||||
(absx->resolution != 0 && absy->resolution == 0)) {
|
||||
log_bug_kernel(libinput,
|
||||
"Kernel has only x or y resolution, not both.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (absx->resolution == 0 || absx->resolution == EVDEV_FAKE_RESOLUTION) {
|
||||
fixed = *absx;
|
||||
fixed.resolution = xresolution;
|
||||
/* libevdev_set_abs_info() changes the absinfo we already
|
||||
have a pointer to, no need to fetch it again */
|
||||
libevdev_set_abs_info(evdev, xcode, &fixed);
|
||||
rc = 1;
|
||||
}
|
||||
|
||||
if (absy->resolution == 0 || absy->resolution == EVDEV_FAKE_RESOLUTION) {
|
||||
fixed = *absy;
|
||||
fixed.resolution = yresolution;
|
||||
/* libevdev_set_abs_info() changes the absinfo we already
|
||||
have a pointer to, no need to fetch it again */
|
||||
libevdev_set_abs_info(evdev, ycode, &fixed);
|
||||
rc = 1;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static enum evdev_device_udev_tags
|
||||
|
|
@ -1387,16 +1439,103 @@ evdev_device_get_udev_tags(struct evdev_device *device,
|
|||
return tags;
|
||||
}
|
||||
|
||||
static inline void
|
||||
evdev_fix_android_mt(struct evdev_device *device)
|
||||
{
|
||||
struct libevdev *evdev = device->evdev;
|
||||
|
||||
if (libevdev_has_event_code(evdev, EV_ABS, ABS_X) ||
|
||||
libevdev_has_event_code(evdev, EV_ABS, ABS_Y))
|
||||
return;
|
||||
|
||||
if (!libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_X) ||
|
||||
!libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_Y))
|
||||
return;
|
||||
|
||||
libevdev_set_abs_info(evdev, ABS_X,
|
||||
libevdev_get_abs_info(evdev, ABS_MT_POSITION_X));
|
||||
libevdev_set_abs_info(evdev, ABS_Y,
|
||||
libevdev_get_abs_info(evdev, ABS_MT_POSITION_Y));
|
||||
}
|
||||
|
||||
static int
|
||||
evdev_reject_device(struct evdev_device *device)
|
||||
{
|
||||
struct libevdev *evdev = device->evdev;
|
||||
|
||||
if (libevdev_has_event_code(evdev, EV_ABS, ABS_X) ^
|
||||
libevdev_has_event_code(evdev, EV_ABS, ABS_Y))
|
||||
return -1;
|
||||
|
||||
if (libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_X) ^
|
||||
libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_Y))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
evdev_configure_mt_device(struct evdev_device *device)
|
||||
{
|
||||
struct libevdev *evdev = device->evdev;
|
||||
struct mt_slot *slots;
|
||||
int num_slots;
|
||||
int active_slot;
|
||||
int slot;
|
||||
|
||||
if (!libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_X) ||
|
||||
!libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_Y))
|
||||
return 0;
|
||||
|
||||
if (evdev_fix_abs_resolution(device,
|
||||
ABS_MT_POSITION_X,
|
||||
ABS_MT_POSITION_Y,
|
||||
EVDEV_FAKE_RESOLUTION,
|
||||
EVDEV_FAKE_RESOLUTION))
|
||||
device->abs.fake_resolution = 1;
|
||||
|
||||
device->abs.absinfo_x = libevdev_get_abs_info(evdev, ABS_MT_POSITION_X);
|
||||
device->abs.absinfo_y = libevdev_get_abs_info(evdev, ABS_MT_POSITION_Y);
|
||||
device->is_mt = 1;
|
||||
|
||||
/* We only handle the slotted Protocol B in libinput.
|
||||
Devices with ABS_MT_POSITION_* but not ABS_MT_SLOT
|
||||
require mtdev for conversion. */
|
||||
if (evdev_need_mtdev(device)) {
|
||||
device->mtdev = mtdev_new_open(device->fd);
|
||||
if (!device->mtdev)
|
||||
return -1;
|
||||
|
||||
/* pick 10 slots as default for type A
|
||||
devices. */
|
||||
num_slots = 10;
|
||||
active_slot = device->mtdev->caps.slot.value;
|
||||
} else {
|
||||
num_slots = libevdev_get_num_slots(device->evdev);
|
||||
active_slot = libevdev_get_current_slot(evdev);
|
||||
}
|
||||
|
||||
slots = calloc(num_slots, sizeof(struct mt_slot));
|
||||
if (!slots)
|
||||
return -1;
|
||||
|
||||
for (slot = 0; slot < num_slots; ++slot) {
|
||||
slots[slot].seat_slot = -1;
|
||||
slots[slot].point.x = 0;
|
||||
slots[slot].point.y = 0;
|
||||
}
|
||||
device->mt.slots = slots;
|
||||
device->mt.slots_len = num_slots;
|
||||
device->mt.slot = active_slot;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
evdev_configure_device(struct evdev_device *device)
|
||||
{
|
||||
struct libinput *libinput = device->base.seat->libinput;
|
||||
struct libevdev *evdev = device->evdev;
|
||||
const struct input_absinfo *absinfo;
|
||||
struct mt_slot *slots;
|
||||
int num_slots;
|
||||
int active_slot;
|
||||
int slot;
|
||||
const char *devnode = udev_device_get_devnode(device->udev_device);
|
||||
enum evdev_device_udev_tags udev_tags;
|
||||
|
||||
|
|
@ -1439,22 +1578,25 @@ evdev_configure_device(struct evdev_device *device)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (libevdev_has_event_type(evdev, EV_ABS)) {
|
||||
if (evdev_reject_device(device) == -1) {
|
||||
log_info(libinput,
|
||||
"input device '%s', %s was rejected.\n",
|
||||
device->devname, devnode);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((absinfo = libevdev_get_abs_info(evdev, ABS_X))) {
|
||||
if (evdev_fix_abs_resolution(evdev,
|
||||
ABS_X,
|
||||
absinfo))
|
||||
device->abs.fake_resolution = 1;
|
||||
device->abs.absinfo_x = absinfo;
|
||||
}
|
||||
if ((absinfo = libevdev_get_abs_info(evdev, ABS_Y))) {
|
||||
if (evdev_fix_abs_resolution(evdev,
|
||||
ABS_Y,
|
||||
absinfo))
|
||||
device->abs.fake_resolution = 1;
|
||||
device->abs.absinfo_y = absinfo;
|
||||
}
|
||||
if (libevdev_has_event_code(evdev, EV_ABS, ABS_X) ||
|
||||
libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_X)) {
|
||||
evdev_fix_android_mt(device);
|
||||
|
||||
if (evdev_fix_abs_resolution(device,
|
||||
ABS_X,
|
||||
ABS_Y,
|
||||
EVDEV_FAKE_RESOLUTION,
|
||||
EVDEV_FAKE_RESOLUTION))
|
||||
device->abs.fake_resolution = 1;
|
||||
device->abs.absinfo_x = libevdev_get_abs_info(evdev, ABS_X);
|
||||
device->abs.absinfo_y = libevdev_get_abs_info(evdev, ABS_Y);
|
||||
|
||||
/* Fake MT devices have the ABS_MT_SLOT bit set because of
|
||||
the limited ABS_* range - they aren't MT devices, they
|
||||
|
|
@ -1462,52 +1604,8 @@ evdev_configure_device(struct evdev_device *device)
|
|||
if (libevdev_has_event_code(evdev, EV_ABS, ABS_MT_SLOT) &&
|
||||
libevdev_get_num_slots(evdev) == -1) {
|
||||
udev_tags &= ~EVDEV_UDEV_TAG_TOUCHSCREEN;
|
||||
} else if (libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_X) &&
|
||||
libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_Y)) {
|
||||
absinfo = libevdev_get_abs_info(evdev, ABS_MT_POSITION_X);
|
||||
if (evdev_fix_abs_resolution(evdev,
|
||||
ABS_MT_POSITION_X,
|
||||
absinfo))
|
||||
device->abs.fake_resolution = 1;
|
||||
device->abs.absinfo_x = absinfo;
|
||||
|
||||
absinfo = libevdev_get_abs_info(evdev, ABS_MT_POSITION_Y);
|
||||
if (evdev_fix_abs_resolution(evdev,
|
||||
ABS_MT_POSITION_Y,
|
||||
absinfo))
|
||||
device->abs.fake_resolution = 1;
|
||||
device->abs.absinfo_y = absinfo;
|
||||
device->is_mt = 1;
|
||||
|
||||
/* We only handle the slotted Protocol B in libinput.
|
||||
Devices with ABS_MT_POSITION_* but not ABS_MT_SLOT
|
||||
require mtdev for conversion. */
|
||||
if (evdev_need_mtdev(device)) {
|
||||
device->mtdev = mtdev_new_open(device->fd);
|
||||
if (!device->mtdev)
|
||||
return -1;
|
||||
|
||||
/* pick 10 slots as default for type A
|
||||
devices. */
|
||||
num_slots = 10;
|
||||
active_slot = device->mtdev->caps.slot.value;
|
||||
} else {
|
||||
num_slots = libevdev_get_num_slots(device->evdev);
|
||||
active_slot = libevdev_get_current_slot(evdev);
|
||||
}
|
||||
|
||||
slots = calloc(num_slots, sizeof(struct mt_slot));
|
||||
if (!slots)
|
||||
return -1;
|
||||
|
||||
for (slot = 0; slot < num_slots; ++slot) {
|
||||
slots[slot].seat_slot = -1;
|
||||
slots[slot].x = 0;
|
||||
slots[slot].y = 0;
|
||||
}
|
||||
device->mt.slots = slots;
|
||||
device->mt.slots_len = num_slots;
|
||||
device->mt.slot = active_slot;
|
||||
} else if (evdev_configure_mt_device(device) == -1) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1535,7 +1633,9 @@ evdev_configure_device(struct evdev_device *device)
|
|||
if (udev_tags & EVDEV_UDEV_TAG_MOUSE) {
|
||||
if (!libevdev_has_event_code(evdev, EV_ABS, ABS_X) &&
|
||||
!libevdev_has_event_code(evdev, EV_ABS, ABS_Y) &&
|
||||
evdev_device_init_pointer_acceleration(device) == -1)
|
||||
evdev_device_init_pointer_acceleration(
|
||||
device,
|
||||
pointer_accel_profile_linear) == -1)
|
||||
return -1;
|
||||
|
||||
device->seat_caps |= EVDEV_DEVICE_POINTER;
|
||||
|
|
@ -1700,8 +1800,8 @@ evdev_device_create(struct libinput_seat *seat,
|
|||
device->is_mt = 0;
|
||||
device->mtdev = NULL;
|
||||
device->udev_device = udev_device_ref(udev_device);
|
||||
device->rel.dx = 0;
|
||||
device->rel.dy = 0;
|
||||
device->rel.x = 0;
|
||||
device->rel.y = 0;
|
||||
device->abs.seat_slot = -1;
|
||||
device->dispatch = NULL;
|
||||
device->fd = fd;
|
||||
|
|
@ -1936,20 +2036,19 @@ void
|
|||
evdev_post_scroll(struct evdev_device *device,
|
||||
uint64_t time,
|
||||
enum libinput_pointer_axis_source source,
|
||||
double dx,
|
||||
double dy)
|
||||
const struct normalized_coords *delta)
|
||||
{
|
||||
double trigger_horiz, trigger_vert;
|
||||
const struct normalized_coords *trigger;
|
||||
struct normalized_coords event;
|
||||
|
||||
if (!evdev_is_scrolling(device,
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL))
|
||||
device->scroll.buildup_vertical += dy;
|
||||
device->scroll.buildup.y += delta->y;
|
||||
if (!evdev_is_scrolling(device,
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL))
|
||||
device->scroll.buildup_horizontal += dx;
|
||||
device->scroll.buildup.x += delta->x;
|
||||
|
||||
trigger_vert = device->scroll.buildup_vertical;
|
||||
trigger_horiz = device->scroll.buildup_horizontal;
|
||||
trigger = &device->scroll.buildup;
|
||||
|
||||
/* If we're not scrolling yet, use a distance trigger: moving
|
||||
past a certain distance starts scrolling */
|
||||
|
|
@ -1957,43 +2056,48 @@ evdev_post_scroll(struct evdev_device *device,
|
|||
LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL) &&
|
||||
!evdev_is_scrolling(device,
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL)) {
|
||||
if (fabs(trigger_vert) >= device->scroll.threshold)
|
||||
if (fabs(trigger->y) >= device->scroll.threshold)
|
||||
evdev_start_scrolling(device,
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
|
||||
if (fabs(trigger_horiz) >= device->scroll.threshold)
|
||||
if (fabs(trigger->x) >= device->scroll.threshold)
|
||||
evdev_start_scrolling(device,
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL);
|
||||
/* We're already scrolling in one direction. Require some
|
||||
trigger speed to start scrolling in the other direction */
|
||||
} else if (!evdev_is_scrolling(device,
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL)) {
|
||||
if (fabs(dy) >= device->scroll.threshold)
|
||||
if (fabs(delta->y) >= device->scroll.threshold)
|
||||
evdev_start_scrolling(device,
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
|
||||
} else if (!evdev_is_scrolling(device,
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL)) {
|
||||
if (fabs(dx) >= device->scroll.threshold)
|
||||
if (fabs(delta->x) >= device->scroll.threshold)
|
||||
evdev_start_scrolling(device,
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL);
|
||||
}
|
||||
|
||||
event = *delta;
|
||||
|
||||
/* We use the trigger to enable, but the delta from this event for
|
||||
* the actual scroll movement. Otherwise we get a jump once
|
||||
* scrolling engages */
|
||||
if (!evdev_is_scrolling(device,
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL))
|
||||
dy = 0.0;
|
||||
event.y = 0.0;
|
||||
|
||||
if (!evdev_is_scrolling(device,
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL))
|
||||
dx = 0.0;
|
||||
event.x = 0.0;
|
||||
|
||||
if (dx != 0.0 || dy != 0.0)
|
||||
if (event.x != 0.0 || event.y != 0.0) {
|
||||
const struct discrete_coords zero_discrete = { 0.0, 0.0 };
|
||||
evdev_notify_axis(device,
|
||||
time,
|
||||
device->scroll.direction,
|
||||
source,
|
||||
dx, dy,
|
||||
0.0, 0.0);
|
||||
&event,
|
||||
&zero_discrete);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -2001,17 +2105,20 @@ evdev_stop_scroll(struct evdev_device *device,
|
|||
uint64_t time,
|
||||
enum libinput_pointer_axis_source source)
|
||||
{
|
||||
const struct normalized_coords zero = { 0.0, 0.0 };
|
||||
const struct discrete_coords zero_discrete = { 0.0, 0.0 };
|
||||
|
||||
/* terminate scrolling with a zero scroll event */
|
||||
if (device->scroll.direction != 0)
|
||||
pointer_notify_axis(&device->base,
|
||||
time,
|
||||
device->scroll.direction,
|
||||
source,
|
||||
0.0, 0.0,
|
||||
0.0, 0.0);
|
||||
&zero,
|
||||
&zero_discrete);
|
||||
|
||||
device->scroll.buildup_horizontal = 0;
|
||||
device->scroll.buildup_vertical = 0;
|
||||
device->scroll.buildup.x = 0;
|
||||
device->scroll.buildup.y = 0;
|
||||
device->scroll.direction = 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
27
src/evdev.h
27
src/evdev.h
|
|
@ -32,9 +32,12 @@
|
|||
|
||||
#include "libinput-private.h"
|
||||
#include "timer.h"
|
||||
#include "filter.h"
|
||||
|
||||
/* The HW DPI rate we normalize to before calculating pointer acceleration */
|
||||
#define DEFAULT_MOUSE_DPI 1000
|
||||
/* The fake resolution value for abs devices without resolution */
|
||||
#define EVDEV_FAKE_RESOLUTION 1
|
||||
|
||||
enum evdev_event_type {
|
||||
EVDEV_NONE,
|
||||
|
|
@ -63,7 +66,7 @@ enum evdev_device_tags {
|
|||
|
||||
struct mt_slot {
|
||||
int32_t seat_slot;
|
||||
int32_t x, y;
|
||||
struct device_coords point;
|
||||
};
|
||||
|
||||
struct evdev_device {
|
||||
|
|
@ -82,7 +85,7 @@ struct evdev_device {
|
|||
const struct input_absinfo *absinfo_x, *absinfo_y;
|
||||
int fake_resolution;
|
||||
|
||||
int32_t x, y;
|
||||
struct device_coords point;
|
||||
int32_t seat_slot;
|
||||
|
||||
int apply_calibration;
|
||||
|
|
@ -98,9 +101,7 @@ struct evdev_device {
|
|||
} mt;
|
||||
struct mtdev *mtdev;
|
||||
|
||||
struct {
|
||||
int dx, dy;
|
||||
} rel;
|
||||
struct device_coords rel;
|
||||
|
||||
struct {
|
||||
struct libinput_timer timer;
|
||||
|
|
@ -117,8 +118,7 @@ struct evdev_device {
|
|||
bool button_scroll_active;
|
||||
double threshold;
|
||||
uint32_t direction;
|
||||
double buildup_vertical;
|
||||
double buildup_horizontal;
|
||||
struct normalized_coords buildup;
|
||||
|
||||
struct libinput_device_config_natural_scroll config_natural;
|
||||
/* set during device init if we want natural scrolling,
|
||||
|
|
@ -221,7 +221,15 @@ evdev_device_create(struct libinput_seat *seat,
|
|||
struct udev_device *device);
|
||||
|
||||
int
|
||||
evdev_device_init_pointer_acceleration(struct evdev_device *device);
|
||||
evdev_fix_abs_resolution(struct evdev_device *device,
|
||||
unsigned int xcode,
|
||||
unsigned int ycode,
|
||||
int yresolution,
|
||||
int xresolution);
|
||||
|
||||
int
|
||||
evdev_device_init_pointer_acceleration(struct evdev_device *device,
|
||||
accel_profile_func_t profile);
|
||||
|
||||
struct evdev_dispatch *
|
||||
evdev_touchpad_create(struct evdev_device *device);
|
||||
|
|
@ -315,8 +323,7 @@ void
|
|||
evdev_post_scroll(struct evdev_device *device,
|
||||
uint64_t time,
|
||||
enum libinput_pointer_axis_source source,
|
||||
double dx,
|
||||
double dy);
|
||||
const struct normalized_coords *delta);
|
||||
|
||||
void
|
||||
evdev_stop_scroll(struct evdev_device *device,
|
||||
|
|
|
|||
21
src/filter.c
21
src/filter.c
|
|
@ -327,3 +327,24 @@ pointer_accel_profile_linear(struct motion_filter *filter,
|
|||
|
||||
return min(max_accel, s2 > 1 ? s2 : s1);
|
||||
}
|
||||
|
||||
double
|
||||
touchpad_accel_profile_linear(struct motion_filter *filter,
|
||||
void *data,
|
||||
double speed_in,
|
||||
uint64_t time)
|
||||
{
|
||||
/* Once normalized, touchpads see the same
|
||||
acceleration as mice. that is technically correct but
|
||||
subjectively wrong, we expect a touchpad to be a lot
|
||||
slower than a mouse. Apply a magic factor here and proceed
|
||||
as normal. */
|
||||
const double TP_MAGIC_SLOWDOWN = 0.4;
|
||||
double speed_out;
|
||||
|
||||
speed_in *= TP_MAGIC_SLOWDOWN;
|
||||
|
||||
speed_out = pointer_accel_profile_linear(filter, data, speed_in, time);
|
||||
|
||||
return speed_out * TP_MAGIC_SLOWDOWN;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,4 +64,9 @@ pointer_accel_profile_linear(struct motion_filter *filter,
|
|||
void *data,
|
||||
double speed_in,
|
||||
uint64_t time);
|
||||
double
|
||||
touchpad_accel_profile_linear(struct motion_filter *filter,
|
||||
void *data,
|
||||
double speed_in,
|
||||
uint64_t time);
|
||||
#endif /* FILTER_H */
|
||||
|
|
|
|||
|
|
@ -34,6 +34,21 @@
|
|||
|
||||
struct libinput_source;
|
||||
|
||||
/* A coordinate pair in device coordinates */
|
||||
struct device_coords {
|
||||
int x, y;
|
||||
};
|
||||
|
||||
/* A dpi-normalized coordinate pair */
|
||||
struct normalized_coords {
|
||||
double x, y;
|
||||
};
|
||||
|
||||
/* A discrete step pair (mouse wheels) */
|
||||
struct discrete_coords {
|
||||
int x, y;
|
||||
};
|
||||
|
||||
struct libinput_interface_backend {
|
||||
int (*resume)(struct libinput *libinput);
|
||||
void (*suspend)(struct libinput *libinput);
|
||||
|
|
@ -295,16 +310,13 @@ keyboard_notify_key(struct libinput_device *device,
|
|||
void
|
||||
pointer_notify_motion(struct libinput_device *device,
|
||||
uint64_t time,
|
||||
double dx,
|
||||
double dy,
|
||||
double dx_unaccel,
|
||||
double dy_unaccel);
|
||||
const struct normalized_coords *delta,
|
||||
const struct normalized_coords *unaccel);
|
||||
|
||||
void
|
||||
pointer_notify_motion_absolute(struct libinput_device *device,
|
||||
uint64_t time,
|
||||
double x,
|
||||
double y);
|
||||
const struct device_coords *point);
|
||||
|
||||
void
|
||||
pointer_notify_button(struct libinput_device *device,
|
||||
|
|
@ -317,26 +329,22 @@ pointer_notify_axis(struct libinput_device *device,
|
|||
uint64_t time,
|
||||
uint32_t axes,
|
||||
enum libinput_pointer_axis_source source,
|
||||
double x,
|
||||
double y,
|
||||
double x_discrete,
|
||||
double y_discrete);
|
||||
const struct normalized_coords *delta,
|
||||
const struct discrete_coords *discrete);
|
||||
|
||||
void
|
||||
touch_notify_touch_down(struct libinput_device *device,
|
||||
uint64_t time,
|
||||
int32_t slot,
|
||||
int32_t seat_slot,
|
||||
double x,
|
||||
double y);
|
||||
const struct device_coords *point);
|
||||
|
||||
void
|
||||
touch_notify_touch_motion(struct libinput_device *device,
|
||||
uint64_t time,
|
||||
int32_t slot,
|
||||
int32_t seat_slot,
|
||||
double x,
|
||||
double y);
|
||||
const struct device_coords *point);
|
||||
|
||||
void
|
||||
touch_notify_touch_up(struct libinput_device *device,
|
||||
|
|
|
|||
|
|
@ -201,3 +201,33 @@ parse_mouse_wheel_click_angle_property(const char *prop)
|
|||
|
||||
return angle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to parse the TOUCHPAD_RESOLUTION property from udev.
|
||||
* Property is of the form
|
||||
* TOUCHPAD_RESOLUTION=<integer>x<integer>
|
||||
* With both integer values in device units per mm.
|
||||
* @param prop The value of the udev property (without the
|
||||
* TOUCHPAD_RESOLUTION=)
|
||||
* @return
|
||||
*/
|
||||
int
|
||||
parse_touchpad_resolution_property(const char *prop,
|
||||
unsigned int *res_x,
|
||||
unsigned int *res_y)
|
||||
{
|
||||
int nconverted = 0;
|
||||
unsigned int rx, ry;
|
||||
nconverted = sscanf(prop, "%ux%u", &rx, &ry);
|
||||
if (nconverted != 2 || rx == 0 || ry == 0)
|
||||
return -1;
|
||||
|
||||
if (rx > 1000 || ry > 1000 || /* yeah, right... */
|
||||
rx < 10 || ry < 10) /* what is this? the 90s? */
|
||||
return -1;
|
||||
|
||||
*res_x = rx;
|
||||
*res_y = ry;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -323,5 +323,8 @@ enum ratelimit_state ratelimit_test(struct ratelimit *r);
|
|||
|
||||
int parse_mouse_dpi_property(const char *prop);
|
||||
int parse_mouse_wheel_click_angle_property(const char *prop);
|
||||
int parse_touchpad_resolution_property(const char *prop,
|
||||
unsigned int *res_x,
|
||||
unsigned int *res_y);
|
||||
|
||||
#endif /* LIBINPUT_UTIL_H */
|
||||
|
|
|
|||
462
src/libinput.c
462
src/libinput.c
|
|
@ -35,6 +35,42 @@
|
|||
#include "evdev.h"
|
||||
#include "timer.h"
|
||||
|
||||
#define require_event_type(li_, type_, retval_, ...) \
|
||||
if (type_ == LIBINPUT_EVENT_NONE) abort(); \
|
||||
if (!check_event_type(li_, __func__, type_, __VA_ARGS__, -1)) \
|
||||
return retval_; \
|
||||
|
||||
static inline bool
|
||||
check_event_type(struct libinput *libinput,
|
||||
const char *function_name,
|
||||
enum libinput_event_type type_in,
|
||||
...)
|
||||
{
|
||||
bool rc = false;
|
||||
va_list args;
|
||||
unsigned int type_permitted;
|
||||
|
||||
va_start(args, type_in);
|
||||
type_permitted = va_arg(args, unsigned int);
|
||||
|
||||
while (type_permitted != (unsigned int)-1) {
|
||||
if (type_permitted == type_in) {
|
||||
rc = true;
|
||||
break;
|
||||
}
|
||||
type_permitted = va_arg(args, unsigned int);
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
|
||||
if (!rc)
|
||||
log_bug_client(libinput,
|
||||
"Invalid event type %d passed to %s()\n",
|
||||
type_in, function_name);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
struct libinput_source {
|
||||
libinput_source_dispatch_t dispatch;
|
||||
void *user_data;
|
||||
|
|
@ -57,12 +93,10 @@ struct libinput_event_keyboard {
|
|||
struct libinput_event_pointer {
|
||||
struct libinput_event base;
|
||||
uint32_t time;
|
||||
double x;
|
||||
double y;
|
||||
double x_discrete;
|
||||
double y_discrete;
|
||||
double dx_unaccel;
|
||||
double dy_unaccel;
|
||||
struct normalized_coords delta;
|
||||
struct normalized_coords delta_unaccel;
|
||||
struct device_coords absolute;
|
||||
struct discrete_coords discrete;
|
||||
uint32_t button;
|
||||
uint32_t seat_button_count;
|
||||
enum libinput_button_state state;
|
||||
|
|
@ -75,8 +109,7 @@ struct libinput_event_touch {
|
|||
uint32_t time;
|
||||
int32_t slot;
|
||||
int32_t seat_slot;
|
||||
double x;
|
||||
double y;
|
||||
struct device_coords point;
|
||||
};
|
||||
|
||||
struct libinput_event_tablet {
|
||||
|
|
@ -179,161 +212,96 @@ libinput_event_get_device(struct libinput_event *event)
|
|||
LIBINPUT_EXPORT struct libinput_event_pointer *
|
||||
libinput_event_get_pointer_event(struct libinput_event *event)
|
||||
{
|
||||
switch (event->type) {
|
||||
case LIBINPUT_EVENT_NONE:
|
||||
abort(); /* not used as actual event type */
|
||||
case LIBINPUT_EVENT_DEVICE_ADDED:
|
||||
case LIBINPUT_EVENT_DEVICE_REMOVED:
|
||||
case LIBINPUT_EVENT_KEYBOARD_KEY:
|
||||
break;
|
||||
case LIBINPUT_EVENT_POINTER_MOTION:
|
||||
case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
|
||||
case LIBINPUT_EVENT_POINTER_BUTTON:
|
||||
case LIBINPUT_EVENT_POINTER_AXIS:
|
||||
return (struct libinput_event_pointer *) event;
|
||||
case LIBINPUT_EVENT_TOUCH_DOWN:
|
||||
case LIBINPUT_EVENT_TOUCH_UP:
|
||||
case LIBINPUT_EVENT_TOUCH_MOTION:
|
||||
case LIBINPUT_EVENT_TOUCH_CANCEL:
|
||||
case LIBINPUT_EVENT_TOUCH_FRAME:
|
||||
case LIBINPUT_EVENT_TABLET_AXIS:
|
||||
case LIBINPUT_EVENT_TABLET_PROXIMITY:
|
||||
case LIBINPUT_EVENT_TABLET_BUTTON:
|
||||
break;
|
||||
}
|
||||
require_event_type(libinput_event_get_context(event),
|
||||
event->type,
|
||||
NULL,
|
||||
LIBINPUT_EVENT_POINTER_MOTION,
|
||||
LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE,
|
||||
LIBINPUT_EVENT_POINTER_BUTTON,
|
||||
LIBINPUT_EVENT_POINTER_AXIS);
|
||||
|
||||
return NULL;
|
||||
return (struct libinput_event_pointer *) event;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT struct libinput_event_keyboard *
|
||||
libinput_event_get_keyboard_event(struct libinput_event *event)
|
||||
{
|
||||
switch (event->type) {
|
||||
case LIBINPUT_EVENT_NONE:
|
||||
abort(); /* not used as actual event type */
|
||||
case LIBINPUT_EVENT_DEVICE_ADDED:
|
||||
case LIBINPUT_EVENT_DEVICE_REMOVED:
|
||||
break;
|
||||
case LIBINPUT_EVENT_KEYBOARD_KEY:
|
||||
return (struct libinput_event_keyboard *) event;
|
||||
case LIBINPUT_EVENT_POINTER_MOTION:
|
||||
case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
|
||||
case LIBINPUT_EVENT_POINTER_BUTTON:
|
||||
case LIBINPUT_EVENT_POINTER_AXIS:
|
||||
case LIBINPUT_EVENT_TOUCH_DOWN:
|
||||
case LIBINPUT_EVENT_TOUCH_UP:
|
||||
case LIBINPUT_EVENT_TOUCH_MOTION:
|
||||
case LIBINPUT_EVENT_TOUCH_CANCEL:
|
||||
case LIBINPUT_EVENT_TOUCH_FRAME:
|
||||
case LIBINPUT_EVENT_TABLET_AXIS:
|
||||
case LIBINPUT_EVENT_TABLET_PROXIMITY:
|
||||
case LIBINPUT_EVENT_TABLET_BUTTON:
|
||||
break;
|
||||
}
|
||||
require_event_type(libinput_event_get_context(event),
|
||||
event->type,
|
||||
NULL,
|
||||
LIBINPUT_EVENT_KEYBOARD_KEY);
|
||||
|
||||
return NULL;
|
||||
return (struct libinput_event_keyboard *) event;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT struct libinput_event_touch *
|
||||
libinput_event_get_touch_event(struct libinput_event *event)
|
||||
{
|
||||
switch (event->type) {
|
||||
case LIBINPUT_EVENT_NONE:
|
||||
abort(); /* not used as actual event type */
|
||||
case LIBINPUT_EVENT_DEVICE_ADDED:
|
||||
case LIBINPUT_EVENT_DEVICE_REMOVED:
|
||||
case LIBINPUT_EVENT_KEYBOARD_KEY:
|
||||
case LIBINPUT_EVENT_POINTER_MOTION:
|
||||
case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
|
||||
case LIBINPUT_EVENT_POINTER_BUTTON:
|
||||
case LIBINPUT_EVENT_POINTER_AXIS:
|
||||
break;
|
||||
case LIBINPUT_EVENT_TOUCH_DOWN:
|
||||
case LIBINPUT_EVENT_TOUCH_UP:
|
||||
case LIBINPUT_EVENT_TOUCH_MOTION:
|
||||
case LIBINPUT_EVENT_TOUCH_CANCEL:
|
||||
case LIBINPUT_EVENT_TOUCH_FRAME:
|
||||
return (struct libinput_event_touch *) event;
|
||||
case LIBINPUT_EVENT_TABLET_AXIS:
|
||||
case LIBINPUT_EVENT_TABLET_PROXIMITY:
|
||||
case LIBINPUT_EVENT_TABLET_BUTTON:
|
||||
break;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
require_event_type(libinput_event_get_context(event),
|
||||
event->type,
|
||||
NULL,
|
||||
LIBINPUT_EVENT_TOUCH_DOWN,
|
||||
LIBINPUT_EVENT_TOUCH_UP,
|
||||
LIBINPUT_EVENT_TOUCH_MOTION,
|
||||
LIBINPUT_EVENT_TOUCH_CANCEL,
|
||||
LIBINPUT_EVENT_TOUCH_FRAME);
|
||||
return (struct libinput_event_touch *) event;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT struct libinput_event_tablet *
|
||||
libinput_event_get_tablet_event(struct libinput_event *event)
|
||||
{
|
||||
switch (event->type) {
|
||||
case LIBINPUT_EVENT_NONE:
|
||||
abort(); /* not used as actual event type */
|
||||
case LIBINPUT_EVENT_DEVICE_ADDED:
|
||||
case LIBINPUT_EVENT_DEVICE_REMOVED:
|
||||
case LIBINPUT_EVENT_KEYBOARD_KEY:
|
||||
case LIBINPUT_EVENT_POINTER_MOTION:
|
||||
case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
|
||||
case LIBINPUT_EVENT_POINTER_BUTTON:
|
||||
case LIBINPUT_EVENT_POINTER_AXIS:
|
||||
case LIBINPUT_EVENT_TOUCH_DOWN:
|
||||
case LIBINPUT_EVENT_TOUCH_UP:
|
||||
case LIBINPUT_EVENT_TOUCH_MOTION:
|
||||
case LIBINPUT_EVENT_TOUCH_CANCEL:
|
||||
case LIBINPUT_EVENT_TOUCH_FRAME:
|
||||
break;
|
||||
case LIBINPUT_EVENT_TABLET_AXIS:
|
||||
case LIBINPUT_EVENT_TABLET_PROXIMITY:
|
||||
case LIBINPUT_EVENT_TABLET_BUTTON:
|
||||
return (struct libinput_event_tablet *) event;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
require_event_type(libinput_event_get_context(event),
|
||||
event->type,
|
||||
NULL,
|
||||
LIBINPUT_EVENT_TABLET_AXIS,
|
||||
LIBINPUT_EVENT_TABLET_PROXIMITY,
|
||||
LIBINPUT_EVENT_TABLET_BUTTON);
|
||||
return (struct libinput_event_tablet *) event;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT struct libinput_event_device_notify *
|
||||
libinput_event_get_device_notify_event(struct libinput_event *event)
|
||||
{
|
||||
switch (event->type) {
|
||||
case LIBINPUT_EVENT_NONE:
|
||||
abort(); /* not used as actual event type */
|
||||
case LIBINPUT_EVENT_DEVICE_ADDED:
|
||||
case LIBINPUT_EVENT_DEVICE_REMOVED:
|
||||
return (struct libinput_event_device_notify *) event;
|
||||
case LIBINPUT_EVENT_KEYBOARD_KEY:
|
||||
case LIBINPUT_EVENT_POINTER_MOTION:
|
||||
case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
|
||||
case LIBINPUT_EVENT_POINTER_BUTTON:
|
||||
case LIBINPUT_EVENT_POINTER_AXIS:
|
||||
case LIBINPUT_EVENT_TOUCH_DOWN:
|
||||
case LIBINPUT_EVENT_TOUCH_UP:
|
||||
case LIBINPUT_EVENT_TOUCH_MOTION:
|
||||
case LIBINPUT_EVENT_TOUCH_CANCEL:
|
||||
case LIBINPUT_EVENT_TOUCH_FRAME:
|
||||
case LIBINPUT_EVENT_TABLET_AXIS:
|
||||
case LIBINPUT_EVENT_TABLET_PROXIMITY:
|
||||
case LIBINPUT_EVENT_TABLET_BUTTON:
|
||||
break;
|
||||
}
|
||||
require_event_type(libinput_event_get_context(event),
|
||||
event->type,
|
||||
NULL,
|
||||
LIBINPUT_EVENT_DEVICE_ADDED,
|
||||
LIBINPUT_EVENT_DEVICE_REMOVED);
|
||||
|
||||
return NULL;
|
||||
return (struct libinput_event_device_notify *) event;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT uint32_t
|
||||
libinput_event_keyboard_get_time(struct libinput_event_keyboard *event)
|
||||
{
|
||||
require_event_type(libinput_event_get_context(&event->base),
|
||||
event->base.type,
|
||||
0,
|
||||
LIBINPUT_EVENT_KEYBOARD_KEY);
|
||||
|
||||
return event->time;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT uint32_t
|
||||
libinput_event_keyboard_get_key(struct libinput_event_keyboard *event)
|
||||
{
|
||||
require_event_type(libinput_event_get_context(&event->base),
|
||||
event->base.type,
|
||||
0,
|
||||
LIBINPUT_EVENT_KEYBOARD_KEY);
|
||||
|
||||
return event->key;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT enum libinput_key_state
|
||||
libinput_event_keyboard_get_key_state(struct libinput_event_keyboard *event)
|
||||
{
|
||||
require_event_type(libinput_event_get_context(&event->base),
|
||||
event->base.type,
|
||||
0,
|
||||
LIBINPUT_EVENT_KEYBOARD_KEY);
|
||||
|
||||
return event->state;
|
||||
}
|
||||
|
||||
|
|
@ -341,39 +309,72 @@ LIBINPUT_EXPORT uint32_t
|
|||
libinput_event_keyboard_get_seat_key_count(
|
||||
struct libinput_event_keyboard *event)
|
||||
{
|
||||
require_event_type(libinput_event_get_context(&event->base),
|
||||
event->base.type,
|
||||
0,
|
||||
LIBINPUT_EVENT_KEYBOARD_KEY);
|
||||
|
||||
return event->seat_key_count;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT uint32_t
|
||||
libinput_event_pointer_get_time(struct libinput_event_pointer *event)
|
||||
{
|
||||
require_event_type(libinput_event_get_context(&event->base),
|
||||
event->base.type,
|
||||
0,
|
||||
LIBINPUT_EVENT_POINTER_MOTION,
|
||||
LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE,
|
||||
LIBINPUT_EVENT_POINTER_BUTTON,
|
||||
LIBINPUT_EVENT_POINTER_AXIS);
|
||||
|
||||
return event->time;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT double
|
||||
libinput_event_pointer_get_dx(struct libinput_event_pointer *event)
|
||||
{
|
||||
return event->x;
|
||||
require_event_type(libinput_event_get_context(&event->base),
|
||||
event->base.type,
|
||||
0,
|
||||
LIBINPUT_EVENT_POINTER_MOTION);
|
||||
|
||||
return event->delta.x;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT double
|
||||
libinput_event_pointer_get_dy(struct libinput_event_pointer *event)
|
||||
{
|
||||
return event->y;
|
||||
require_event_type(libinput_event_get_context(&event->base),
|
||||
event->base.type,
|
||||
0,
|
||||
LIBINPUT_EVENT_POINTER_MOTION);
|
||||
|
||||
return event->delta.y;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT double
|
||||
libinput_event_pointer_get_dx_unaccelerated(
|
||||
struct libinput_event_pointer *event)
|
||||
{
|
||||
return event->dx_unaccel;
|
||||
require_event_type(libinput_event_get_context(&event->base),
|
||||
event->base.type,
|
||||
0,
|
||||
LIBINPUT_EVENT_POINTER_MOTION);
|
||||
|
||||
return event->delta_unaccel.x;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT double
|
||||
libinput_event_pointer_get_dy_unaccelerated(
|
||||
struct libinput_event_pointer *event)
|
||||
{
|
||||
return event->dy_unaccel;
|
||||
require_event_type(libinput_event_get_context(&event->base),
|
||||
event->base.type,
|
||||
0,
|
||||
LIBINPUT_EVENT_POINTER_MOTION);
|
||||
|
||||
return event->delta_unaccel.y;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT double
|
||||
|
|
@ -382,7 +383,12 @@ libinput_event_pointer_get_absolute_x(struct libinput_event_pointer *event)
|
|||
struct evdev_device *device =
|
||||
(struct evdev_device *) event->base.device;
|
||||
|
||||
return evdev_convert_to_mm(device->abs.absinfo_x, event->x);
|
||||
require_event_type(libinput_event_get_context(&event->base),
|
||||
event->base.type,
|
||||
0,
|
||||
LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE);
|
||||
|
||||
return evdev_convert_to_mm(device->abs.absinfo_x, event->absolute.x);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT double
|
||||
|
|
@ -391,7 +397,12 @@ libinput_event_pointer_get_absolute_y(struct libinput_event_pointer *event)
|
|||
struct evdev_device *device =
|
||||
(struct evdev_device *) event->base.device;
|
||||
|
||||
return evdev_convert_to_mm(device->abs.absinfo_y, event->y);
|
||||
require_event_type(libinput_event_get_context(&event->base),
|
||||
event->base.type,
|
||||
0,
|
||||
LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE);
|
||||
|
||||
return evdev_convert_to_mm(device->abs.absinfo_y, event->absolute.y);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT double
|
||||
|
|
@ -402,7 +413,12 @@ libinput_event_pointer_get_absolute_x_transformed(
|
|||
struct evdev_device *device =
|
||||
(struct evdev_device *) event->base.device;
|
||||
|
||||
return evdev_device_transform_x(device, event->x, width);
|
||||
require_event_type(libinput_event_get_context(&event->base),
|
||||
event->base.type,
|
||||
0,
|
||||
LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE);
|
||||
|
||||
return evdev_device_transform_x(device, event->absolute.x, width);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT double
|
||||
|
|
@ -413,18 +429,33 @@ libinput_event_pointer_get_absolute_y_transformed(
|
|||
struct evdev_device *device =
|
||||
(struct evdev_device *) event->base.device;
|
||||
|
||||
return evdev_device_transform_y(device, event->y, height);
|
||||
require_event_type(libinput_event_get_context(&event->base),
|
||||
event->base.type,
|
||||
0,
|
||||
LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE);
|
||||
|
||||
return evdev_device_transform_y(device, event->absolute.y, height);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT uint32_t
|
||||
libinput_event_pointer_get_button(struct libinput_event_pointer *event)
|
||||
{
|
||||
require_event_type(libinput_event_get_context(&event->base),
|
||||
event->base.type,
|
||||
0,
|
||||
LIBINPUT_EVENT_POINTER_BUTTON);
|
||||
|
||||
return event->button;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT enum libinput_button_state
|
||||
libinput_event_pointer_get_button_state(struct libinput_event_pointer *event)
|
||||
{
|
||||
require_event_type(libinput_event_get_context(&event->base),
|
||||
event->base.type,
|
||||
0,
|
||||
LIBINPUT_EVENT_POINTER_BUTTON);
|
||||
|
||||
return event->state;
|
||||
}
|
||||
|
||||
|
|
@ -432,6 +463,11 @@ LIBINPUT_EXPORT uint32_t
|
|||
libinput_event_pointer_get_seat_button_count(
|
||||
struct libinput_event_pointer *event)
|
||||
{
|
||||
require_event_type(libinput_event_get_context(&event->base),
|
||||
event->base.type,
|
||||
0,
|
||||
LIBINPUT_EVENT_POINTER_BUTTON);
|
||||
|
||||
return event->seat_button_count;
|
||||
}
|
||||
|
||||
|
|
@ -439,13 +475,17 @@ LIBINPUT_EXPORT int
|
|||
libinput_event_pointer_has_axis(struct libinput_event_pointer *event,
|
||||
enum libinput_pointer_axis axis)
|
||||
{
|
||||
if (event->base.type == LIBINPUT_EVENT_POINTER_AXIS) {
|
||||
switch (axis) {
|
||||
case LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL:
|
||||
case LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL:
|
||||
return !!(event->axes & AS_MASK(axis));
|
||||
}
|
||||
require_event_type(libinput_event_get_context(&event->base),
|
||||
event->base.type,
|
||||
0,
|
||||
LIBINPUT_EVENT_POINTER_AXIS);
|
||||
|
||||
switch (axis) {
|
||||
case LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL:
|
||||
case LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL:
|
||||
return !!(event->axes & AS_MASK(axis));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -456,15 +496,20 @@ libinput_event_pointer_get_axis_value(struct libinput_event_pointer *event,
|
|||
struct libinput *libinput = event->base.device->seat->libinput;
|
||||
double value = 0;
|
||||
|
||||
require_event_type(libinput_event_get_context(&event->base),
|
||||
event->base.type,
|
||||
0.0,
|
||||
LIBINPUT_EVENT_POINTER_AXIS);
|
||||
|
||||
if (!libinput_event_pointer_has_axis(event, axis)) {
|
||||
log_bug_client(libinput, "value requested for unset axis\n");
|
||||
} else {
|
||||
switch (axis) {
|
||||
case LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL:
|
||||
value = event->x;
|
||||
value = event->delta.x;
|
||||
break;
|
||||
case LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL:
|
||||
value = event->y;
|
||||
value = event->delta.y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -479,15 +524,20 @@ libinput_event_pointer_get_axis_value_discrete(struct libinput_event_pointer *ev
|
|||
struct libinput *libinput = event->base.device->seat->libinput;
|
||||
double value = 0;
|
||||
|
||||
require_event_type(libinput_event_get_context(&event->base),
|
||||
event->base.type,
|
||||
0.0,
|
||||
LIBINPUT_EVENT_POINTER_AXIS);
|
||||
|
||||
if (!libinput_event_pointer_has_axis(event, axis)) {
|
||||
log_bug_client(libinput, "value requested for unset axis\n");
|
||||
} else {
|
||||
switch (axis) {
|
||||
case LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL:
|
||||
value = event->x_discrete;
|
||||
value = event->discrete.x;
|
||||
break;
|
||||
case LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL:
|
||||
value = event->y_discrete;
|
||||
value = event->discrete.y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -497,24 +547,54 @@ libinput_event_pointer_get_axis_value_discrete(struct libinput_event_pointer *ev
|
|||
LIBINPUT_EXPORT enum libinput_pointer_axis_source
|
||||
libinput_event_pointer_get_axis_source(struct libinput_event_pointer *event)
|
||||
{
|
||||
require_event_type(libinput_event_get_context(&event->base),
|
||||
event->base.type,
|
||||
0,
|
||||
LIBINPUT_EVENT_POINTER_AXIS);
|
||||
|
||||
return event->source;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT uint32_t
|
||||
libinput_event_touch_get_time(struct libinput_event_touch *event)
|
||||
{
|
||||
require_event_type(libinput_event_get_context(&event->base),
|
||||
event->base.type,
|
||||
0,
|
||||
LIBINPUT_EVENT_TOUCH_DOWN,
|
||||
LIBINPUT_EVENT_TOUCH_UP,
|
||||
LIBINPUT_EVENT_TOUCH_MOTION,
|
||||
LIBINPUT_EVENT_TOUCH_CANCEL,
|
||||
LIBINPUT_EVENT_TOUCH_FRAME);
|
||||
|
||||
return event->time;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT int32_t
|
||||
libinput_event_touch_get_slot(struct libinput_event_touch *event)
|
||||
{
|
||||
require_event_type(libinput_event_get_context(&event->base),
|
||||
event->base.type,
|
||||
0,
|
||||
LIBINPUT_EVENT_TOUCH_DOWN,
|
||||
LIBINPUT_EVENT_TOUCH_UP,
|
||||
LIBINPUT_EVENT_TOUCH_MOTION,
|
||||
LIBINPUT_EVENT_TOUCH_CANCEL);
|
||||
|
||||
return event->slot;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT int32_t
|
||||
libinput_event_touch_get_seat_slot(struct libinput_event_touch *event)
|
||||
{
|
||||
require_event_type(libinput_event_get_context(&event->base),
|
||||
event->base.type,
|
||||
0,
|
||||
LIBINPUT_EVENT_TOUCH_DOWN,
|
||||
LIBINPUT_EVENT_TOUCH_UP,
|
||||
LIBINPUT_EVENT_TOUCH_MOTION,
|
||||
LIBINPUT_EVENT_TOUCH_CANCEL);
|
||||
|
||||
return event->seat_slot;
|
||||
}
|
||||
|
||||
|
|
@ -524,7 +604,13 @@ libinput_event_touch_get_x(struct libinput_event_touch *event)
|
|||
struct evdev_device *device =
|
||||
(struct evdev_device *) event->base.device;
|
||||
|
||||
return evdev_convert_to_mm(device->abs.absinfo_x, event->x);
|
||||
require_event_type(libinput_event_get_context(&event->base),
|
||||
event->base.type,
|
||||
0,
|
||||
LIBINPUT_EVENT_TOUCH_DOWN,
|
||||
LIBINPUT_EVENT_TOUCH_MOTION);
|
||||
|
||||
return evdev_convert_to_mm(device->abs.absinfo_x, event->point.x);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT double
|
||||
|
|
@ -534,7 +620,13 @@ libinput_event_touch_get_x_transformed(struct libinput_event_touch *event,
|
|||
struct evdev_device *device =
|
||||
(struct evdev_device *) event->base.device;
|
||||
|
||||
return evdev_device_transform_x(device, event->x, width);
|
||||
require_event_type(libinput_event_get_context(&event->base),
|
||||
event->base.type,
|
||||
0,
|
||||
LIBINPUT_EVENT_TOUCH_DOWN,
|
||||
LIBINPUT_EVENT_TOUCH_MOTION);
|
||||
|
||||
return evdev_device_transform_x(device, event->point.x, width);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT double
|
||||
|
|
@ -544,7 +636,13 @@ libinput_event_touch_get_y_transformed(struct libinput_event_touch *event,
|
|||
struct evdev_device *device =
|
||||
(struct evdev_device *) event->base.device;
|
||||
|
||||
return evdev_device_transform_y(device, event->y, height);
|
||||
require_event_type(libinput_event_get_context(&event->base),
|
||||
event->base.type,
|
||||
0,
|
||||
LIBINPUT_EVENT_TOUCH_DOWN,
|
||||
LIBINPUT_EVENT_TOUCH_MOTION);
|
||||
|
||||
return evdev_device_transform_y(device, event->point.y, height);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT double
|
||||
|
|
@ -553,7 +651,13 @@ libinput_event_touch_get_y(struct libinput_event_touch *event)
|
|||
struct evdev_device *device =
|
||||
(struct evdev_device *) event->base.device;
|
||||
|
||||
return evdev_convert_to_mm(device->abs.absinfo_y, event->y);
|
||||
require_event_type(libinput_event_get_context(&event->base),
|
||||
event->base.type,
|
||||
0,
|
||||
LIBINPUT_EVENT_TOUCH_DOWN,
|
||||
LIBINPUT_EVENT_TOUCH_MOTION);
|
||||
|
||||
return evdev_convert_to_mm(device->abs.absinfo_y, event->point.y);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT int
|
||||
|
|
@ -1252,10 +1356,8 @@ keyboard_notify_key(struct libinput_device *device,
|
|||
void
|
||||
pointer_notify_motion(struct libinput_device *device,
|
||||
uint64_t time,
|
||||
double dx,
|
||||
double dy,
|
||||
double dx_unaccel,
|
||||
double dy_unaccel)
|
||||
const struct normalized_coords *delta,
|
||||
const struct normalized_coords *unaccel)
|
||||
{
|
||||
struct libinput_event_pointer *motion_event;
|
||||
|
||||
|
|
@ -1265,10 +1367,8 @@ pointer_notify_motion(struct libinput_device *device,
|
|||
|
||||
*motion_event = (struct libinput_event_pointer) {
|
||||
.time = time,
|
||||
.x = dx,
|
||||
.y = dy,
|
||||
.dx_unaccel = dx_unaccel,
|
||||
.dy_unaccel = dy_unaccel,
|
||||
.delta = *delta,
|
||||
.delta_unaccel = *unaccel,
|
||||
};
|
||||
|
||||
post_device_event(device, time,
|
||||
|
|
@ -1279,8 +1379,7 @@ pointer_notify_motion(struct libinput_device *device,
|
|||
void
|
||||
pointer_notify_motion_absolute(struct libinput_device *device,
|
||||
uint64_t time,
|
||||
double x,
|
||||
double y)
|
||||
const struct device_coords *point)
|
||||
{
|
||||
struct libinput_event_pointer *motion_absolute_event;
|
||||
|
||||
|
|
@ -1290,8 +1389,7 @@ pointer_notify_motion_absolute(struct libinput_device *device,
|
|||
|
||||
*motion_absolute_event = (struct libinput_event_pointer) {
|
||||
.time = time,
|
||||
.x = x,
|
||||
.y = y,
|
||||
.absolute = *point,
|
||||
};
|
||||
|
||||
post_device_event(device, time,
|
||||
|
|
@ -1333,8 +1431,8 @@ pointer_notify_axis(struct libinput_device *device,
|
|||
uint64_t time,
|
||||
uint32_t axes,
|
||||
enum libinput_pointer_axis_source source,
|
||||
double x, double y,
|
||||
double x_discrete, double y_discrete)
|
||||
const struct normalized_coords *delta,
|
||||
const struct discrete_coords *discrete)
|
||||
{
|
||||
struct libinput_event_pointer *axis_event;
|
||||
|
||||
|
|
@ -1344,12 +1442,10 @@ pointer_notify_axis(struct libinput_device *device,
|
|||
|
||||
*axis_event = (struct libinput_event_pointer) {
|
||||
.time = time,
|
||||
.x = x,
|
||||
.y = y,
|
||||
.delta = *delta,
|
||||
.source = source,
|
||||
.axes = axes,
|
||||
.x_discrete = x_discrete,
|
||||
.y_discrete = y_discrete,
|
||||
.discrete = *discrete,
|
||||
};
|
||||
|
||||
post_device_event(device, time,
|
||||
|
|
@ -1362,8 +1458,7 @@ touch_notify_touch_down(struct libinput_device *device,
|
|||
uint64_t time,
|
||||
int32_t slot,
|
||||
int32_t seat_slot,
|
||||
double x,
|
||||
double y)
|
||||
const struct device_coords *point)
|
||||
{
|
||||
struct libinput_event_touch *touch_event;
|
||||
|
||||
|
|
@ -1375,8 +1470,7 @@ touch_notify_touch_down(struct libinput_device *device,
|
|||
.time = time,
|
||||
.slot = slot,
|
||||
.seat_slot = seat_slot,
|
||||
.x = x,
|
||||
.y = y,
|
||||
.point = *point,
|
||||
};
|
||||
|
||||
post_device_event(device, time,
|
||||
|
|
@ -1389,8 +1483,7 @@ touch_notify_touch_motion(struct libinput_device *device,
|
|||
uint64_t time,
|
||||
int32_t slot,
|
||||
int32_t seat_slot,
|
||||
double x,
|
||||
double y)
|
||||
const struct device_coords *point)
|
||||
{
|
||||
struct libinput_event_touch *touch_event;
|
||||
|
||||
|
|
@ -1402,8 +1495,7 @@ touch_notify_touch_motion(struct libinput_device *device,
|
|||
.time = time,
|
||||
.slot = slot,
|
||||
.seat_slot = seat_slot,
|
||||
.x = x,
|
||||
.y = y,
|
||||
.point = *point,
|
||||
};
|
||||
|
||||
post_device_event(device, time,
|
||||
|
|
@ -1766,24 +1858,52 @@ libinput_device_pointer_has_button(struct libinput_device *device, uint32_t code
|
|||
LIBINPUT_EXPORT struct libinput_event *
|
||||
libinput_event_device_notify_get_base_event(struct libinput_event_device_notify *event)
|
||||
{
|
||||
require_event_type(libinput_event_get_context(&event->base),
|
||||
event->base.type,
|
||||
NULL,
|
||||
LIBINPUT_EVENT_DEVICE_ADDED,
|
||||
LIBINPUT_EVENT_DEVICE_REMOVED);
|
||||
|
||||
return &event->base;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT struct libinput_event *
|
||||
libinput_event_keyboard_get_base_event(struct libinput_event_keyboard *event)
|
||||
{
|
||||
require_event_type(libinput_event_get_context(&event->base),
|
||||
event->base.type,
|
||||
NULL,
|
||||
LIBINPUT_EVENT_KEYBOARD_KEY);
|
||||
|
||||
return &event->base;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT struct libinput_event *
|
||||
libinput_event_pointer_get_base_event(struct libinput_event_pointer *event)
|
||||
{
|
||||
require_event_type(libinput_event_get_context(&event->base),
|
||||
event->base.type,
|
||||
NULL,
|
||||
LIBINPUT_EVENT_POINTER_MOTION,
|
||||
LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE,
|
||||
LIBINPUT_EVENT_POINTER_BUTTON,
|
||||
LIBINPUT_EVENT_POINTER_AXIS);
|
||||
|
||||
return &event->base;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT struct libinput_event *
|
||||
libinput_event_touch_get_base_event(struct libinput_event_touch *event)
|
||||
{
|
||||
require_event_type(libinput_event_get_context(&event->base),
|
||||
event->base.type,
|
||||
NULL,
|
||||
LIBINPUT_EVENT_TOUCH_DOWN,
|
||||
LIBINPUT_EVENT_TOUCH_UP,
|
||||
LIBINPUT_EVENT_TOUCH_MOTION,
|
||||
LIBINPUT_EVENT_TOUCH_CANCEL,
|
||||
LIBINPUT_EVENT_TOUCH_FRAME);
|
||||
|
||||
return &event->base;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -788,6 +788,12 @@ libinput_event_pointer_get_seat_button_count(
|
|||
* libinput_event_pointer_get_axis_value() returns a value of 0, the event
|
||||
* is a scroll stop event.
|
||||
*
|
||||
* For pointer events that are not of type @ref LIBINPUT_EVENT_POINTER_AXIS,
|
||||
* this function returns 0.
|
||||
*
|
||||
* @note It is an application bug to call this function for events other than
|
||||
* @ref LIBINPUT_EVENT_POINTER_AXIS.
|
||||
*
|
||||
* @return Non-zero if this event contains a value for this axis
|
||||
*/
|
||||
int
|
||||
|
|
@ -911,8 +917,13 @@ libinput_event_touch_get_time(struct libinput_event_touch *event);
|
|||
* If the touch event has no assigned slot, for example if it is from a
|
||||
* single touch device, this function returns -1.
|
||||
*
|
||||
* @note this function should not be called for @ref
|
||||
* LIBINPUT_EVENT_TOUCH_CANCEL or @ref LIBINPUT_EVENT_TOUCH_FRAME.
|
||||
* For events not of type @ref LIBINPUT_EVENT_TOUCH_DOWN, @ref
|
||||
* LIBINPUT_EVENT_TOUCH_UP, @ref LIBINPUT_EVENT_TOUCH_MOTION or @ref
|
||||
* LIBINPUT_EVENT_TOUCH_CANCEL, this function returns 0.
|
||||
*
|
||||
* @note It is an application bug to call this function for events of type
|
||||
* other than @ref LIBINPUT_EVENT_TOUCH_DOWN, @ref LIBINPUT_EVENT_TOUCH_UP,
|
||||
* @ref LIBINPUT_EVENT_TOUCH_MOTION or @ref LIBINPUT_EVENT_TOUCH_CANCEL.
|
||||
*
|
||||
* @return The slot of this touch event
|
||||
*/
|
||||
|
|
@ -928,8 +939,13 @@ libinput_event_touch_get_slot(struct libinput_event_touch *event);
|
|||
* Events from single touch devices will be represented as one individual
|
||||
* touch point per device.
|
||||
*
|
||||
* @note this function should not be called for @ref
|
||||
* LIBINPUT_EVENT_TOUCH_CANCEL or @ref LIBINPUT_EVENT_TOUCH_FRAME.
|
||||
* For events not of type @ref LIBINPUT_EVENT_TOUCH_DOWN, @ref
|
||||
* LIBINPUT_EVENT_TOUCH_UP, @ref LIBINPUT_EVENT_TOUCH_MOTION or @ref
|
||||
* LIBINPUT_EVENT_TOUCH_CANCEL, this function returns 0.
|
||||
*
|
||||
* @note It is an application bug to call this function for events of type
|
||||
* other than @ref LIBINPUT_EVENT_TOUCH_DOWN, @ref LIBINPUT_EVENT_TOUCH_UP,
|
||||
* @ref LIBINPUT_EVENT_TOUCH_MOTION or @ref LIBINPUT_EVENT_TOUCH_CANCEL.
|
||||
*
|
||||
* @return The seat slot of the touch event
|
||||
*/
|
||||
|
|
@ -943,8 +959,11 @@ libinput_event_touch_get_seat_slot(struct libinput_event_touch *event);
|
|||
* the top left corner of the device. To get the corresponding output screen
|
||||
* coordinate, use libinput_event_touch_get_x_transformed().
|
||||
*
|
||||
* @note this function should only be called for @ref
|
||||
* LIBINPUT_EVENT_TOUCH_DOWN and @ref LIBINPUT_EVENT_TOUCH_MOTION.
|
||||
* For events not of type @ref LIBINPUT_EVENT_TOUCH_DOWN, @ref
|
||||
* LIBINPUT_EVENT_TOUCH_MOTION, this function returns 0.
|
||||
*
|
||||
* @note It is an application bug to call this function for events of type
|
||||
* @ref LIBINPUT_EVENT_TOUCH_DOWN or @ref LIBINPUT_EVENT_TOUCH_MOTION.
|
||||
*
|
||||
* @param event The libinput touch event
|
||||
* @return The current absolute x coordinate
|
||||
|
|
@ -959,10 +978,11 @@ libinput_event_touch_get_x(struct libinput_event_touch *event);
|
|||
* the top left corner of the device. To get the corresponding output screen
|
||||
* coordinate, use libinput_event_touch_get_y_transformed().
|
||||
*
|
||||
* For @ref LIBINPUT_EVENT_TOUCH_UP 0 is returned.
|
||||
* For events not of type @ref LIBINPUT_EVENT_TOUCH_DOWN, @ref
|
||||
* LIBINPUT_EVENT_TOUCH_MOTION, this function returns 0.
|
||||
*
|
||||
* @note this function should only be called for @ref LIBINPUT_EVENT_TOUCH_DOWN and
|
||||
* @ref LIBINPUT_EVENT_TOUCH_MOTION.
|
||||
* @note It is an application bug to call this function for events of type
|
||||
* @ref LIBINPUT_EVENT_TOUCH_DOWN or @ref LIBINPUT_EVENT_TOUCH_MOTION.
|
||||
*
|
||||
* @param event The libinput touch event
|
||||
* @return The current absolute y coordinate
|
||||
|
|
@ -976,8 +996,11 @@ libinput_event_touch_get_y(struct libinput_event_touch *event);
|
|||
* Return the current absolute x coordinate of the touch event, transformed to
|
||||
* screen coordinates.
|
||||
*
|
||||
* @note this function should only be called for @ref
|
||||
* LIBINPUT_EVENT_TOUCH_DOWN and @ref LIBINPUT_EVENT_TOUCH_MOTION.
|
||||
* For events not of type @ref LIBINPUT_EVENT_TOUCH_DOWN, @ref
|
||||
* LIBINPUT_EVENT_TOUCH_MOTION, this function returns 0.
|
||||
*
|
||||
* @note It is an application bug to call this function for events of type
|
||||
* @ref LIBINPUT_EVENT_TOUCH_DOWN or @ref LIBINPUT_EVENT_TOUCH_MOTION.
|
||||
*
|
||||
* @param event The libinput touch event
|
||||
* @param width The current output screen width
|
||||
|
|
@ -993,8 +1016,11 @@ libinput_event_touch_get_x_transformed(struct libinput_event_touch *event,
|
|||
* Return the current absolute y coordinate of the touch event, transformed to
|
||||
* screen coordinates.
|
||||
*
|
||||
* @note this function should only be called for @ref
|
||||
* LIBINPUT_EVENT_TOUCH_DOWN and @ref LIBINPUT_EVENT_TOUCH_MOTION.
|
||||
* For events not of type @ref LIBINPUT_EVENT_TOUCH_DOWN, @ref
|
||||
* LIBINPUT_EVENT_TOUCH_MOTION, this function returns 0.
|
||||
*
|
||||
* @note It is an application bug to call this function for events of type
|
||||
* @ref LIBINPUT_EVENT_TOUCH_DOWN or @ref LIBINPUT_EVENT_TOUCH_MOTION.
|
||||
*
|
||||
* @param event The libinput touch event
|
||||
* @param height The current output screen height
|
||||
|
|
|
|||
103
test/device.c
103
test/device.c
|
|
@ -716,6 +716,104 @@ START_TEST(device_group_ref)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(abs_device_no_absx)
|
||||
{
|
||||
struct libevdev_uinput *uinput;
|
||||
struct libinput *li;
|
||||
struct libinput_device *device;
|
||||
|
||||
uinput = litest_create_uinput_device("test device", NULL,
|
||||
EV_KEY, BTN_LEFT,
|
||||
EV_KEY, BTN_RIGHT,
|
||||
EV_ABS, ABS_Y,
|
||||
-1);
|
||||
li = litest_create_context();
|
||||
litest_disable_log_handler(li);
|
||||
device = libinput_path_add_device(li,
|
||||
libevdev_uinput_get_devnode(uinput));
|
||||
litest_restore_log_handler(li);
|
||||
ck_assert(device == NULL);
|
||||
libinput_unref(li);
|
||||
|
||||
libevdev_uinput_destroy(uinput);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(abs_device_no_absy)
|
||||
{
|
||||
struct libevdev_uinput *uinput;
|
||||
struct libinput *li;
|
||||
struct libinput_device *device;
|
||||
|
||||
uinput = litest_create_uinput_device("test device", NULL,
|
||||
EV_KEY, BTN_LEFT,
|
||||
EV_KEY, BTN_RIGHT,
|
||||
EV_ABS, ABS_X,
|
||||
-1);
|
||||
li = litest_create_context();
|
||||
litest_disable_log_handler(li);
|
||||
device = libinput_path_add_device(li,
|
||||
libevdev_uinput_get_devnode(uinput));
|
||||
litest_restore_log_handler(li);
|
||||
ck_assert(device == NULL);
|
||||
libinput_unref(li);
|
||||
|
||||
libevdev_uinput_destroy(uinput);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(abs_mt_device_no_absy)
|
||||
{
|
||||
struct libevdev_uinput *uinput;
|
||||
struct libinput *li;
|
||||
struct libinput_device *device;
|
||||
|
||||
uinput = litest_create_uinput_device("test device", NULL,
|
||||
EV_KEY, BTN_LEFT,
|
||||
EV_KEY, BTN_RIGHT,
|
||||
EV_ABS, ABS_X,
|
||||
EV_ABS, ABS_Y,
|
||||
EV_ABS, ABS_MT_SLOT,
|
||||
EV_ABS, ABS_MT_POSITION_X,
|
||||
-1);
|
||||
li = litest_create_context();
|
||||
litest_disable_log_handler(li);
|
||||
device = libinput_path_add_device(li,
|
||||
libevdev_uinput_get_devnode(uinput));
|
||||
litest_restore_log_handler(li);
|
||||
ck_assert(device == NULL);
|
||||
libinput_unref(li);
|
||||
|
||||
libevdev_uinput_destroy(uinput);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(abs_mt_device_no_absx)
|
||||
{
|
||||
struct libevdev_uinput *uinput;
|
||||
struct libinput *li;
|
||||
struct libinput_device *device;
|
||||
|
||||
uinput = litest_create_uinput_device("test device", NULL,
|
||||
EV_KEY, BTN_LEFT,
|
||||
EV_KEY, BTN_RIGHT,
|
||||
EV_ABS, ABS_X,
|
||||
EV_ABS, ABS_Y,
|
||||
EV_ABS, ABS_MT_SLOT,
|
||||
EV_ABS, ABS_MT_POSITION_Y,
|
||||
-1);
|
||||
li = litest_create_context();
|
||||
litest_disable_log_handler(li);
|
||||
device = libinput_path_add_device(li,
|
||||
libevdev_uinput_get_devnode(uinput));
|
||||
litest_restore_log_handler(li);
|
||||
ck_assert(device == NULL);
|
||||
libinput_unref(li);
|
||||
|
||||
libevdev_uinput_destroy(uinput);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
litest_add("device:sendevents", device_sendevents_config, LITEST_ANY, LITEST_TOUCHPAD|LITEST_TABLET);
|
||||
|
|
@ -745,5 +843,10 @@ int main (int argc, char **argv)
|
|||
litest_add("device:group", device_group_get, LITEST_ANY, LITEST_ANY);
|
||||
litest_add_no_device("device:group", device_group_ref);
|
||||
|
||||
litest_add_no_device("device:invalid devices", abs_device_no_absx);
|
||||
litest_add_no_device("device:invalid devices", abs_device_no_absy);
|
||||
litest_add_no_device("device:invalid devices", abs_mt_device_no_absx);
|
||||
litest_add_no_device("device:invalid devices", abs_mt_device_no_absy);
|
||||
|
||||
return litest_run(argc, argv);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -380,6 +380,8 @@ litest_log_handler(struct libinput *libinput,
|
|||
case LIBINPUT_LOG_PRIORITY_INFO: priority = "info"; break;
|
||||
case LIBINPUT_LOG_PRIORITY_ERROR: priority = "error"; break;
|
||||
case LIBINPUT_LOG_PRIORITY_DEBUG: priority = "debug"; break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
||||
fprintf(stderr, "litest %s: ", priority);
|
||||
|
|
@ -648,6 +650,18 @@ litest_create_context(void)
|
|||
return libinput;
|
||||
}
|
||||
|
||||
void
|
||||
litest_disable_log_handler(struct libinput *libinput)
|
||||
{
|
||||
libinput_log_set_handler(libinput, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
litest_restore_log_handler(struct libinput *libinput)
|
||||
{
|
||||
libinput_log_set_handler(libinput, litest_log_handler);
|
||||
}
|
||||
|
||||
struct litest_device *
|
||||
litest_add_device_with_overrides(struct libinput *libinput,
|
||||
enum litest_device_type which,
|
||||
|
|
@ -1000,6 +1014,28 @@ litest_tablet_motion(struct litest_device *d, int x, int y, struct axis_replacem
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
litest_touch_move_two_touches(struct litest_device *d,
|
||||
double x0, double y0,
|
||||
double x1, double y1,
|
||||
double dx, double dy,
|
||||
int steps, int sleep_ms)
|
||||
{
|
||||
for (int i = 0; i < steps - 1; i++) {
|
||||
litest_touch_move(d, 0, x0 + dx / steps * i,
|
||||
y0 + dy / steps * i);
|
||||
litest_touch_move(d, 1, x1 + dx / steps * i,
|
||||
y1 + dy / steps * i);
|
||||
if (sleep_ms) {
|
||||
libinput_dispatch(d->libinput);
|
||||
msleep(sleep_ms);
|
||||
libinput_dispatch(d->libinput);
|
||||
}
|
||||
}
|
||||
litest_touch_move(d, 0, x0 + dx, y0 + dy);
|
||||
litest_touch_move(d, 1, x1 + dx, y1 + dy);
|
||||
}
|
||||
|
||||
void
|
||||
litest_button_click(struct litest_device *d, unsigned int button, bool is_press)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -98,12 +98,15 @@ struct litest_device {
|
|||
char *udev_rule_file;
|
||||
};
|
||||
|
||||
struct libinput *litest_create_context(void);
|
||||
struct axis_replacement {
|
||||
int32_t evcode;
|
||||
int32_t value;
|
||||
};
|
||||
|
||||
struct libinput *litest_create_context(void);
|
||||
void litest_disable_log_handler(struct libinput *libinput);
|
||||
void litest_restore_log_handler(struct libinput *libinput);
|
||||
|
||||
void litest_add(const char *name, void *func,
|
||||
enum litest_device_feature required_feature,
|
||||
enum litest_device_feature excluded_feature);
|
||||
|
|
@ -161,6 +164,12 @@ void litest_touch_move_to(struct litest_device *d,
|
|||
double x_from, double y_from,
|
||||
double x_to, double y_to,
|
||||
int steps, int sleep_ms);
|
||||
void litest_touch_move_two_touches(struct litest_device *d,
|
||||
double x0, double y0,
|
||||
double x1, double y1,
|
||||
double dx, double dy,
|
||||
int steps, int sleep_ms);
|
||||
|
||||
void litest_tablet_proximity_in(struct litest_device *d,
|
||||
int x, int y,
|
||||
struct axis_replacement *axes);
|
||||
|
|
@ -168,6 +177,7 @@ void litest_tablet_proximity_out(struct litest_device *d);
|
|||
void litest_tablet_motion(struct litest_device *d,
|
||||
int x, int y,
|
||||
struct axis_replacement *axes);
|
||||
|
||||
void litest_button_click(struct litest_device *d,
|
||||
unsigned int button,
|
||||
bool is_press);
|
||||
|
|
|
|||
59
test/misc.c
59
test/misc.c
|
|
@ -127,9 +127,11 @@ START_TEST(event_conversion_device_notify)
|
|||
else if (type == LIBINPUT_EVENT_DEVICE_REMOVED)
|
||||
device_removed++;
|
||||
|
||||
litest_disable_log_handler(li);
|
||||
ck_assert(libinput_event_get_pointer_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_keyboard_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_touch_event(event) == NULL);
|
||||
litest_restore_log_handler(li);
|
||||
}
|
||||
|
||||
libinput_event_destroy(event);
|
||||
|
|
@ -179,9 +181,11 @@ START_TEST(event_conversion_pointer)
|
|||
else if (type == LIBINPUT_EVENT_POINTER_BUTTON)
|
||||
button++;
|
||||
|
||||
litest_disable_log_handler(li);
|
||||
ck_assert(libinput_event_get_device_notify_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_keyboard_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_touch_event(event) == NULL);
|
||||
litest_restore_log_handler(li);
|
||||
}
|
||||
libinput_event_destroy(event);
|
||||
}
|
||||
|
|
@ -225,9 +229,11 @@ START_TEST(event_conversion_pointer_abs)
|
|||
else if (type == LIBINPUT_EVENT_POINTER_BUTTON)
|
||||
button++;
|
||||
|
||||
litest_disable_log_handler(li);
|
||||
ck_assert(libinput_event_get_device_notify_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_keyboard_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_touch_event(event) == NULL);
|
||||
litest_restore_log_handler(li);
|
||||
}
|
||||
libinput_event_destroy(event);
|
||||
}
|
||||
|
|
@ -264,9 +270,11 @@ START_TEST(event_conversion_key)
|
|||
|
||||
key++;
|
||||
|
||||
litest_disable_log_handler(li);
|
||||
ck_assert(libinput_event_get_device_notify_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_pointer_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_touch_event(event) == NULL);
|
||||
litest_restore_log_handler(li);
|
||||
}
|
||||
libinput_event_destroy(event);
|
||||
}
|
||||
|
|
@ -310,9 +318,11 @@ START_TEST(event_conversion_touch)
|
|||
|
||||
touch++;
|
||||
|
||||
litest_disable_log_handler(li);
|
||||
ck_assert(libinput_event_get_device_notify_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_pointer_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_keyboard_event(event) == NULL);
|
||||
litest_restore_log_handler(li);
|
||||
}
|
||||
libinput_event_destroy(event);
|
||||
}
|
||||
|
|
@ -585,6 +595,54 @@ START_TEST(wheel_click_parser)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
struct res_parser_test {
|
||||
const char *value;
|
||||
int retvalue;
|
||||
int rx, ry;
|
||||
};
|
||||
|
||||
START_TEST(touchpad_resolution_parser)
|
||||
{
|
||||
struct res_parser_test tests[] = {
|
||||
{ "43x85", 0, 43, 85},
|
||||
{ "242x428", 0, 242, 428 },
|
||||
{ "1x1", -1, 0, 0},
|
||||
{ "abcd", -1, 0, 0},
|
||||
{ "", -1, 0, 0 },
|
||||
{ "x", -1, 0, 0 },
|
||||
{ "23x", -1, 0, 0 },
|
||||
{ "x58", -1, 0, 0 },
|
||||
{ "1x1", -1, 0, 0 },
|
||||
{ "9x9", -1, 0, 0 },
|
||||
{ "-34x-19", -1, 0, 0 },
|
||||
{ "-34x19", -1, 0, 0 },
|
||||
{ "34x-19", -1, 0, 0 },
|
||||
{ NULL, 0, 0, 0 }
|
||||
|
||||
};
|
||||
|
||||
struct res_parser_test *test = tests;
|
||||
int rc;
|
||||
unsigned int rx, ry;
|
||||
|
||||
while (test->value != NULL) {
|
||||
rx = 0xab;
|
||||
ry = 0xcd;
|
||||
rc = parse_touchpad_resolution_property(test->value, &rx, &ry);
|
||||
ck_assert_int_eq(rc, test->retvalue);
|
||||
if (rc == 0) {
|
||||
ck_assert_int_eq(rx, test->rx);
|
||||
ck_assert_int_eq(ry, test->ry);
|
||||
} else {
|
||||
ck_assert_int_eq(rx, 0xab);
|
||||
ck_assert_int_eq(ry, 0xcd);
|
||||
}
|
||||
|
||||
test++;
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
int main (int argc, char **argv) {
|
||||
litest_add_no_device("events:conversion", event_conversion_device_notify);
|
||||
litest_add_for_device("events:conversion", event_conversion_pointer, LITEST_MOUSE);
|
||||
|
|
@ -601,6 +659,7 @@ int main (int argc, char **argv) {
|
|||
litest_add_no_device("misc:ratelimit", ratelimit_helpers);
|
||||
litest_add_no_device("misc:dpi parser", dpi_parser);
|
||||
litest_add_no_device("misc:wheel click parser", wheel_click_parser);
|
||||
litest_add_no_device("misc:touchpad resolution parser", touchpad_resolution_parser);
|
||||
|
||||
return litest_run(argc, argv);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1817,11 +1817,10 @@ test_2fg_scroll(struct litest_device *dev, double dx, double dy, int want_sleep)
|
|||
{
|
||||
struct libinput *li = dev->libinput;
|
||||
|
||||
litest_touch_down(dev, 0, 47, 50);
|
||||
litest_touch_down(dev, 1, 53, 50);
|
||||
litest_touch_down(dev, 0, 49, 50);
|
||||
litest_touch_down(dev, 1, 51, 50);
|
||||
|
||||
litest_touch_move_to(dev, 0, 47, 50, 47 + dx, 50 + dy, 5, 0);
|
||||
litest_touch_move_to(dev, 1, 53, 50, 53 + dx, 50 + dy, 5, 0);
|
||||
litest_touch_move_two_touches(dev, 49, 50, 51, 50, dx, dy, 5, 0);
|
||||
|
||||
/* Avoid a small scroll being seen as a tap */
|
||||
if (want_sleep) {
|
||||
|
|
@ -1864,13 +1863,23 @@ START_TEST(touchpad_2fg_scroll_slow_distance)
|
|||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *event;
|
||||
struct libinput_event_pointer *ptrev;
|
||||
const struct input_absinfo *y;
|
||||
double y_move;
|
||||
|
||||
/* We want to move > 5 mm. */
|
||||
y = libevdev_get_abs_info(dev->evdev, ABS_Y);
|
||||
if (y->resolution) {
|
||||
y_move = 7.0 * y->resolution /
|
||||
(y->maximum - y->minimum) * 100;
|
||||
} else {
|
||||
y_move = 10.0;
|
||||
}
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_touch_down(dev, 0, 20, 30);
|
||||
litest_touch_down(dev, 1, 40, 30);
|
||||
litest_touch_move_to(dev, 0, 20, 30, 20, 40, 70, 10);
|
||||
litest_touch_move_to(dev, 1, 40, 30, 40, 40, 70, 10);
|
||||
litest_touch_down(dev, 0, 49, 50);
|
||||
litest_touch_down(dev, 1, 51, 50);
|
||||
litest_touch_move_two_touches(dev, 49, 50, 51, 50, 0, y_move, 70, 10);
|
||||
litest_touch_up(dev, 1);
|
||||
litest_touch_up(dev, 0);
|
||||
libinput_dispatch(li);
|
||||
|
|
@ -1935,26 +1944,24 @@ START_TEST(touchpad_2fg_scroll_return_to_motion)
|
|||
|
||||
/* start with motion */
|
||||
litest_touch_down(dev, 0, 70, 70);
|
||||
litest_touch_move_to(dev, 0, 70, 70, 47, 50, 10, 0);
|
||||
litest_touch_move_to(dev, 0, 70, 70, 49, 50, 10, 0);
|
||||
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
|
||||
|
||||
/* 2fg scroll */
|
||||
litest_touch_down(dev, 1, 53, 50);
|
||||
litest_touch_move_to(dev, 0, 47, 50, 47, 70, 5, 0);
|
||||
litest_touch_move_to(dev, 1, 53, 50, 53, 70, 5, 0);
|
||||
litest_touch_down(dev, 1, 51, 50);
|
||||
litest_touch_move_two_touches(dev, 49, 50, 51, 50, 0, 20, 5, 0);
|
||||
litest_touch_up(dev, 1);
|
||||
libinput_dispatch(li);
|
||||
litest_timeout_finger_switch();
|
||||
libinput_dispatch(li);
|
||||
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS);
|
||||
|
||||
litest_touch_move_to(dev, 0, 47, 70, 47, 50, 10, 0);
|
||||
litest_touch_move_to(dev, 0, 49, 70, 49, 50, 10, 0);
|
||||
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
|
||||
|
||||
/* back to 2fg scroll, lifting the other finger */
|
||||
litest_touch_down(dev, 1, 50, 50);
|
||||
litest_touch_move_to(dev, 0, 47, 50, 47, 70, 5, 0);
|
||||
litest_touch_move_to(dev, 1, 53, 50, 53, 70, 5, 0);
|
||||
litest_touch_down(dev, 1, 51, 50);
|
||||
litest_touch_move_two_touches(dev, 49, 50, 51, 50, 0, 20, 5, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
libinput_dispatch(li);
|
||||
litest_timeout_finger_switch();
|
||||
|
|
@ -1962,7 +1969,7 @@ START_TEST(touchpad_2fg_scroll_return_to_motion)
|
|||
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS);
|
||||
|
||||
/* move with second finger */
|
||||
litest_touch_move_to(dev, 1, 53, 70, 53, 50, 10, 0);
|
||||
litest_touch_move_to(dev, 1, 51, 70, 51, 50, 10, 0);
|
||||
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
|
||||
|
||||
litest_touch_up(dev, 1);
|
||||
|
|
@ -3260,10 +3267,9 @@ START_TEST(touchpad_trackpoint_buttons_2fg_scroll)
|
|||
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_touch_down(touchpad, 0, 40, 70);
|
||||
litest_touch_down(touchpad, 1, 60, 70);
|
||||
litest_touch_move_to(touchpad, 0, 40, 70, 40, 30, 10, 0);
|
||||
litest_touch_move_to(touchpad, 1, 60, 70, 60, 30, 10, 0);
|
||||
litest_touch_down(touchpad, 0, 49, 70);
|
||||
litest_touch_down(touchpad, 1, 51, 70);
|
||||
litest_touch_move_two_touches(touchpad, 49, 70, 51, 70, 0, -40, 10, 0);
|
||||
|
||||
libinput_dispatch(li);
|
||||
litest_wait_for_event(li);
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ print_device_notify(struct libinput_event *ev)
|
|||
struct libinput_seat *seat = libinput_device_get_seat(dev);
|
||||
struct libinput_device_group *group;
|
||||
double w, h;
|
||||
uint32_t scroll_methods;
|
||||
uint32_t scroll_methods, click_methods;
|
||||
static int next_group_id = 0;
|
||||
intptr_t group_id;
|
||||
|
||||
|
|
@ -187,6 +187,15 @@ print_device_notify(struct libinput_event *ev)
|
|||
printf("-button");
|
||||
}
|
||||
|
||||
click_methods = libinput_device_config_click_get_methods(dev);
|
||||
if (click_methods != LIBINPUT_CONFIG_CLICK_METHOD_NONE) {
|
||||
printf(" click");
|
||||
if (click_methods & LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS)
|
||||
printf("-buttonareas");
|
||||
if (click_methods & LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER)
|
||||
printf("-clickfinger");
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue