#include <errno.h>
#include <limits.h>
-#include <time.h>
#include <math.h>
#include <string.h>
#include <unistd.h>
-#include <linux/input.h>
-#include <sys/timerfd.h>
+#include "linux/input.h"
#include "evdev-mt-touchpad.h"
CASE_RETURN_STRING(BUTTON_STATE_NONE);
CASE_RETURN_STRING(BUTTON_STATE_AREA);
CASE_RETURN_STRING(BUTTON_STATE_BOTTOM);
- CASE_RETURN_STRING(BUTTON_STATE_BOTTOM_NEW);
- CASE_RETURN_STRING(BUTTON_STATE_BOTTOM_TO_AREA);
+ CASE_RETURN_STRING(BUTTON_STATE_TOP);
+ CASE_RETURN_STRING(BUTTON_STATE_TOP_NEW);
+ CASE_RETURN_STRING(BUTTON_STATE_TOP_TO_IGNORE);
+ CASE_RETURN_STRING(BUTTON_STATE_IGNORE);
}
return NULL;
}
switch(event) {
CASE_RETURN_STRING(BUTTON_EVENT_IN_BOTTOM_R);
CASE_RETURN_STRING(BUTTON_EVENT_IN_BOTTOM_L);
+ CASE_RETURN_STRING(BUTTON_EVENT_IN_TOP_R);
+ CASE_RETURN_STRING(BUTTON_EVENT_IN_TOP_M);
+ CASE_RETURN_STRING(BUTTON_EVENT_IN_TOP_L);
CASE_RETURN_STRING(BUTTON_EVENT_IN_AREA);
CASE_RETURN_STRING(BUTTON_EVENT_UP);
CASE_RETURN_STRING(BUTTON_EVENT_PRESS);
}
static inline bool
-is_inside_button_area(struct tp_dispatch *tp, struct tp_touch *t)
+is_inside_bottom_button_area(struct tp_dispatch *tp, struct tp_touch *t)
{
- return t->y >= tp->buttons.area.top_edge;
+ return t->y >= tp->buttons.bottom_area.top_edge;
}
static inline bool
-is_inside_right_area(struct tp_dispatch *tp, struct tp_touch *t)
+is_inside_bottom_right_area(struct tp_dispatch *tp, struct tp_touch *t)
{
- return is_inside_button_area(tp, t) &&
- t->x > tp->buttons.area.rightbutton_left_edge;
+ return is_inside_bottom_button_area(tp, t) &&
+ t->x > tp->buttons.bottom_area.rightbutton_left_edge;
}
static inline bool
-is_inside_left_area(struct tp_dispatch *tp, struct tp_touch *t)
+is_inside_bottom_left_area(struct tp_dispatch *tp, struct tp_touch *t)
{
- return is_inside_button_area(tp, t) &&
- !is_inside_right_area(tp, t);
+ return is_inside_bottom_button_area(tp, t) &&
+ !is_inside_bottom_right_area(tp, t);
}
-static void
-tp_button_set_timer(struct tp_dispatch *tp, uint64_t timeout)
+static inline bool
+is_inside_top_button_area(struct tp_dispatch *tp, struct tp_touch *t)
{
- struct itimerspec its;
- its.it_interval.tv_sec = 0;
- its.it_interval.tv_nsec = 0;
- its.it_value.tv_sec = timeout / 1000;
- its.it_value.tv_nsec = (timeout % 1000) * 1000 * 1000;
- timerfd_settime(tp->buttons.timer_fd, TFD_TIMER_ABSTIME, &its, NULL);
+ return t->y <= tp->buttons.top_area.bottom_edge;
}
-static void
-tp_button_set_enter_timer(struct tp_dispatch *tp, struct tp_touch *t)
+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;
+}
+
+static inline bool
+is_inside_top_left_area(struct tp_dispatch *tp, struct tp_touch *t)
{
- t->button.timeout = t->millis + DEFAULT_BUTTON_ENTER_TIMEOUT;
- tp_button_set_timer(tp, t->button.timeout);
+ return is_inside_top_button_area(tp, t) &&
+ t->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;
}
static void
-tp_button_set_leave_timer(struct tp_dispatch *tp, struct tp_touch *t)
+tp_button_set_enter_timer(struct tp_dispatch *tp, struct tp_touch *t)
{
- t->button.timeout = t->millis + DEFAULT_BUTTON_LEAVE_TIMEOUT;
- tp_button_set_timer(tp, t->button.timeout);
+ libinput_timer_set(&t->button.timer,
+ t->millis + DEFAULT_BUTTON_ENTER_TIMEOUT);
}
static void
-tp_button_clear_timer(struct tp_dispatch *tp, struct tp_touch *t)
+tp_button_set_leave_timer(struct tp_dispatch *tp, struct tp_touch *t)
{
- t->button.timeout = 0;
+ libinput_timer_set(&t->button.timer,
+ t->millis + DEFAULT_BUTTON_LEAVE_TIMEOUT);
}
/*
tp_button_set_state(struct tp_dispatch *tp, struct tp_touch *t,
enum button_state new_state, enum button_event event)
{
- tp_button_clear_timer(tp, t);
+ libinput_timer_cancel(&t->button.timer);
t->button.state = new_state;
switch (t->button.state) {
tp_set_pointer(tp, t);
break;
case BUTTON_STATE_BOTTOM:
+ t->button.curr = event;
+ break;
+ case BUTTON_STATE_TOP:
break;
- case BUTTON_STATE_BOTTOM_NEW:
+ case BUTTON_STATE_TOP_NEW:
t->button.curr = event;
tp_button_set_enter_timer(tp, t);
break;
- case BUTTON_STATE_BOTTOM_TO_AREA:
+ case BUTTON_STATE_TOP_TO_IGNORE:
tp_button_set_leave_timer(tp, t);
break;
+ case BUTTON_STATE_IGNORE:
+ t->button.curr = 0;
+ break;
}
}
switch (event) {
case BUTTON_EVENT_IN_BOTTOM_R:
case BUTTON_EVENT_IN_BOTTOM_L:
- tp_button_set_state(tp, t, BUTTON_STATE_BOTTOM_NEW, event);
+ tp_button_set_state(tp, t, BUTTON_STATE_BOTTOM, event);
+ break;
+ case BUTTON_EVENT_IN_TOP_R:
+ case BUTTON_EVENT_IN_TOP_M:
+ case BUTTON_EVENT_IN_TOP_L:
+ tp_button_set_state(tp, t, BUTTON_STATE_TOP_NEW, event);
break;
case BUTTON_EVENT_IN_AREA:
tp_button_set_state(tp, t, BUTTON_STATE_AREA, event);
switch (event) {
case BUTTON_EVENT_IN_BOTTOM_R:
case BUTTON_EVENT_IN_BOTTOM_L:
+ case BUTTON_EVENT_IN_TOP_R:
+ case BUTTON_EVENT_IN_TOP_M:
+ case BUTTON_EVENT_IN_TOP_L:
case BUTTON_EVENT_IN_AREA:
break;
case BUTTON_EVENT_UP:
static void
tp_button_bottom_handle_event(struct tp_dispatch *tp,
+ struct tp_touch *t,
+ enum button_event event)
+{
+ switch (event) {
+ case BUTTON_EVENT_IN_BOTTOM_R:
+ case BUTTON_EVENT_IN_BOTTOM_L:
+ if (event != t->button.curr)
+ tp_button_set_state(tp, t, BUTTON_STATE_BOTTOM,
+ event);
+ break;
+ case BUTTON_EVENT_IN_TOP_R:
+ case BUTTON_EVENT_IN_TOP_M:
+ case BUTTON_EVENT_IN_TOP_L:
+ case BUTTON_EVENT_IN_AREA:
+ tp_button_set_state(tp, t, BUTTON_STATE_AREA, event);
+ break;
+ case BUTTON_EVENT_UP:
+ tp_button_set_state(tp, t, BUTTON_STATE_NONE, event);
+ break;
+ case BUTTON_EVENT_PRESS:
+ case BUTTON_EVENT_RELEASE:
+ case BUTTON_EVENT_TIMEOUT:
+ break;
+ }
+}
+
+static void
+tp_button_top_handle_event(struct tp_dispatch *tp,
struct tp_touch *t,
enum button_event event)
{
switch (event) {
case BUTTON_EVENT_IN_BOTTOM_R:
case BUTTON_EVENT_IN_BOTTOM_L:
+ tp_button_set_state(tp, t, BUTTON_STATE_TOP_TO_IGNORE, event);
+ break;
+ case BUTTON_EVENT_IN_TOP_R:
+ case BUTTON_EVENT_IN_TOP_M:
+ case BUTTON_EVENT_IN_TOP_L:
if (event != t->button.curr)
- tp_button_set_state(tp, t, BUTTON_STATE_BOTTOM_NEW,
+ tp_button_set_state(tp, t, BUTTON_STATE_TOP_NEW,
event);
break;
case BUTTON_EVENT_IN_AREA:
- tp_button_set_state(tp, t, BUTTON_STATE_BOTTOM_TO_AREA, event);
+ tp_button_set_state(tp, t, BUTTON_STATE_TOP_TO_IGNORE, event);
break;
case BUTTON_EVENT_UP:
tp_button_set_state(tp, t, BUTTON_STATE_NONE, event);
}
static void
-tp_button_bottom_new_handle_event(struct tp_dispatch *tp,
+tp_button_top_new_handle_event(struct tp_dispatch *tp,
struct tp_touch *t,
enum button_event event)
{
switch(event) {
case BUTTON_EVENT_IN_BOTTOM_R:
case BUTTON_EVENT_IN_BOTTOM_L:
+ tp_button_set_state(tp, t, BUTTON_STATE_AREA, event);
+ break;
+ case BUTTON_EVENT_IN_TOP_R:
+ case BUTTON_EVENT_IN_TOP_M:
+ case BUTTON_EVENT_IN_TOP_L:
if (event != t->button.curr)
- tp_button_set_state(tp, t, BUTTON_STATE_BOTTOM_NEW,
+ tp_button_set_state(tp, t, BUTTON_STATE_TOP_NEW,
event);
break;
case BUTTON_EVENT_IN_AREA:
tp_button_set_state(tp, t, BUTTON_STATE_NONE, event);
break;
case BUTTON_EVENT_PRESS:
- tp_button_set_state(tp, t, BUTTON_STATE_BOTTOM, event);
+ tp_button_set_state(tp, t, BUTTON_STATE_TOP, event);
break;
case BUTTON_EVENT_RELEASE:
break;
case BUTTON_EVENT_TIMEOUT:
- tp_button_set_state(tp, t, BUTTON_STATE_BOTTOM, event);
+ tp_button_set_state(tp, t, BUTTON_STATE_TOP, event);
break;
}
}
static void
-tp_button_bottom_to_area_handle_event(struct tp_dispatch *tp,
+tp_button_top_to_ignore_handle_event(struct tp_dispatch *tp,
struct tp_touch *t,
enum button_event event)
{
switch(event) {
- case BUTTON_EVENT_IN_BOTTOM_R:
- case BUTTON_EVENT_IN_BOTTOM_L:
+ case BUTTON_EVENT_IN_TOP_R:
+ case BUTTON_EVENT_IN_TOP_M:
+ case BUTTON_EVENT_IN_TOP_L:
if (event == t->button.curr)
- tp_button_set_state(tp, t, BUTTON_STATE_BOTTOM,
+ tp_button_set_state(tp, t, BUTTON_STATE_TOP,
event);
else
- tp_button_set_state(tp, t, BUTTON_STATE_BOTTOM_NEW,
+ tp_button_set_state(tp, t, BUTTON_STATE_TOP_NEW,
event);
break;
+ case BUTTON_EVENT_IN_BOTTOM_R:
+ case BUTTON_EVENT_IN_BOTTOM_L:
case BUTTON_EVENT_IN_AREA:
break;
case BUTTON_EVENT_UP:
case BUTTON_EVENT_RELEASE:
break;
case BUTTON_EVENT_TIMEOUT:
- tp_button_set_state(tp, t, BUTTON_STATE_AREA, event);
+ tp_button_set_state(tp, t, BUTTON_STATE_IGNORE, event);
+ break;
+ }
+}
+
+static void
+tp_button_ignore_handle_event(struct tp_dispatch *tp,
+ struct tp_touch *t,
+ enum button_event event)
+{
+ switch (event) {
+ case BUTTON_EVENT_IN_BOTTOM_R:
+ case BUTTON_EVENT_IN_BOTTOM_L:
+ case BUTTON_EVENT_IN_TOP_R:
+ case BUTTON_EVENT_IN_TOP_M:
+ case BUTTON_EVENT_IN_TOP_L:
+ case BUTTON_EVENT_IN_AREA:
+ break;
+ case BUTTON_EVENT_UP:
+ tp_button_set_state(tp, t, BUTTON_STATE_NONE, event);
+ break;
+ case BUTTON_EVENT_PRESS:
+ case BUTTON_EVENT_RELEASE:
+ case BUTTON_EVENT_TIMEOUT:
break;
}
}
enum button_event event,
uint64_t time)
{
+ struct libinput *libinput = tp->device->base.seat->libinput;
enum button_state current = t->button.state;
switch(t->button.state) {
case BUTTON_STATE_BOTTOM:
tp_button_bottom_handle_event(tp, t, event);
break;
- case BUTTON_STATE_BOTTOM_NEW:
- tp_button_bottom_new_handle_event(tp, t, event);
+ case BUTTON_STATE_TOP:
+ tp_button_top_handle_event(tp, t, event);
+ break;
+ case BUTTON_STATE_TOP_NEW:
+ tp_button_top_new_handle_event(tp, t, event);
+ break;
+ case BUTTON_STATE_TOP_TO_IGNORE:
+ tp_button_top_to_ignore_handle_event(tp, t, event);
break;
- case BUTTON_STATE_BOTTOM_TO_AREA:
- tp_button_bottom_to_area_handle_event(tp, t, event);
+ case BUTTON_STATE_IGNORE:
+ tp_button_ignore_handle_event(tp, t, event);
break;
}
if (current != t->button.state)
- log_debug("button state: from %s, event %s to %s\n",
+ log_debug(libinput,
+ "button state: from %s, event %s to %s\n",
button_state_to_str(current),
button_event_to_str(event),
button_state_to_str(t->button.state));
if (t->state == TOUCH_END) {
tp_button_handle_event(tp, t, BUTTON_EVENT_UP, time);
} else if (t->dirty) {
- if (is_inside_right_area(tp, t))
+ if (is_inside_bottom_right_area(tp, t))
tp_button_handle_event(tp, t, BUTTON_EVENT_IN_BOTTOM_R, time);
- else if (is_inside_left_area(tp, t))
+ else if (is_inside_bottom_left_area(tp, t))
tp_button_handle_event(tp, t, BUTTON_EVENT_IN_BOTTOM_L, time);
+ else if (is_inside_top_right_area(tp, t))
+ tp_button_handle_event(tp, t, BUTTON_EVENT_IN_TOP_R, time);
+ else if (is_inside_top_middle_area(tp, t))
+ tp_button_handle_event(tp, t, BUTTON_EVENT_IN_TOP_M, time);
+ else if (is_inside_top_left_area(tp, t))
+ tp_button_handle_event(tp, t, BUTTON_EVENT_IN_TOP_L, time);
else
tp_button_handle_event(tp, t, BUTTON_EVENT_IN_AREA, time);
}
}
static void
-tp_button_handle_timeout(struct tp_dispatch *tp, uint64_t now)
+tp_button_handle_timeout(uint64_t now, void *data)
{
- struct tp_touch *t;
+ struct tp_touch *t = data;
- tp_for_each_touch(tp, t) {
- if (t->button.timeout != 0 && t->button.timeout <= now) {
- tp_button_clear_timer(tp, t);
- tp_button_handle_event(tp, t, BUTTON_EVENT_TIMEOUT, now);
- }
- }
+ tp_button_handle_event(t->tp, t, BUTTON_EVENT_TIMEOUT, now);
}
int
const struct input_event *e,
uint64_t time)
{
+ struct libinput *libinput = tp->device->base.seat->libinput;
uint32_t mask = 1 << (e->code - BTN_LEFT);
/* Ignore other buttons on clickpads */
if (tp->buttons.is_clickpad && e->code != BTN_LEFT) {
- log_bug("received %s button event on a clickpad (kernel bug?)\n",
- libevdev_event_code_get_name(EV_KEY, e->code));
+ log_bug_kernel(libinput,
+ "received %s button event on a clickpad\n",
+ libevdev_event_code_get_name(EV_KEY, e->code));
return 0;
}
return 0;
}
-static void
-tp_button_timeout_handler(void *data)
-{
- struct tp_dispatch *tp = data;
- uint64_t expires;
- int len;
- struct timespec ts;
- uint64_t now;
-
- len = read(tp->buttons.timer_fd, &expires, sizeof expires);
- if (len != sizeof expires)
- /* This will only happen if the application made the fd
- * non-blocking, but this function should only be called
- * upon the timeout, so lets continue anyway. */
- log_error("timerfd read error: %s\n", strerror(errno));
-
- clock_gettime(CLOCK_MONOTONIC, &ts);
- now = ts.tv_sec * 1000ULL + ts.tv_nsec / 1000000;
-
- tp_button_handle_timeout(tp, now);
-}
-
int
tp_init_buttons(struct tp_dispatch *tp,
struct evdev_device *device)
{
+ struct libinput *libinput = tp->device->base.seat->libinput;
+ struct tp_touch *t;
int width, height;
double diagonal;
+ const struct input_absinfo *absinfo_x, *absinfo_y;
tp->buttons.is_clickpad = libevdev_has_property(device->evdev,
INPUT_PROP_BUTTONPAD);
+ tp->buttons.has_topbuttons = libevdev_has_property(device->evdev,
+ INPUT_PROP_TOPBUTTONPAD);
if (libevdev_has_event_code(device->evdev, EV_KEY, BTN_MIDDLE) ||
libevdev_has_event_code(device->evdev, EV_KEY, BTN_RIGHT)) {
if (tp->buttons.is_clickpad)
- log_bug("clickpad advertising right button (kernel bug?)\n");
+ log_bug_kernel(libinput,
+ "%s: clickpad advertising right button\n",
+ device->sysname);
} else {
if (!tp->buttons.is_clickpad)
- log_bug("non clickpad without right button (kernel bug)?\n");
+ log_bug_kernel(libinput,
+ "%s: non clickpad without right button?\n",
+ device->sysname);
}
- width = abs(device->abs.max_x - device->abs.min_x);
- height = abs(device->abs.max_y - device->abs.min_y);
+ absinfo_x = device->abs.absinfo_x;
+ absinfo_y = device->abs.absinfo_y;
+
+ width = abs(absinfo_x->maximum - absinfo_x->minimum);
+ height = abs(absinfo_y->maximum - absinfo_y->minimum);
diagonal = sqrt(width*width + height*height);
tp->buttons.motion_dist = diagonal * DEFAULT_BUTTON_MOTION_THRESHOLD;
- if (libevdev_get_id_vendor(device->evdev) == 0x5ac) /* Apple */
+ if (libevdev_get_id_vendor(device->evdev) == VENDOR_ID_APPLE)
tp->buttons.use_clickfinger = true;
if (tp->buttons.is_clickpad && !tp->buttons.use_clickfinger) {
- tp->buttons.area.top_edge = height * .8 + device->abs.min_y;
- tp->buttons.area.rightbutton_left_edge = width/2 + device->abs.min_x;
- tp->buttons.timer_fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
-
- if (tp->buttons.timer_fd == -1)
- return -1;
-
- tp->buttons.source =
- libinput_add_fd(tp->device->base.seat->libinput,
- tp->buttons.timer_fd,
- tp_button_timeout_handler,
- tp);
- if (tp->buttons.source == NULL)
- return -1;
+ int xoffset = absinfo_x->minimum,
+ yoffset = absinfo_y->minimum;
+ int yres = absinfo_y->resolution;
+
+ /* button height: 10mm or 15% of the touchpad height,
+ whichever is smaller */
+ if (yres > 1 && (height * 0.15/yres) > 10) {
+ tp->buttons.bottom_area.top_edge =
+ absinfo_y->maximum - 10 * yres;
+ } else {
+ tp->buttons.bottom_area.top_edge = height * .85 + yoffset;
+ }
+
+ tp->buttons.bottom_area.rightbutton_left_edge = width/2 + xoffset;
+
+ if (tp->buttons.has_topbuttons) {
+ /* T440s has the top button line 5mm from the top,
+ make the buttons 6mm high */
+ if (yres > 1) {
+ tp->buttons.top_area.bottom_edge =
+ yoffset + 6 * yres;
+ } else {
+ tp->buttons.top_area.bottom_edge = height * .08 + yoffset;
+ }
+ tp->buttons.top_area.rightbutton_left_edge = width * .58 + xoffset;
+ tp->buttons.top_area.leftbutton_right_edge = width * .42 + xoffset;
+ } else {
+ tp->buttons.top_area.bottom_edge = INT_MIN;
+ }
} else {
- tp->buttons.area.top_edge = INT_MAX;
+ tp->buttons.bottom_area.top_edge = INT_MAX;
+ tp->buttons.top_area.bottom_edge = INT_MIN;
+ }
+
+ tp_for_each_touch(tp, t) {
+ t->button.state = BUTTON_STATE_NONE;
+ libinput_timer_init(&t->button.timer,
+ tp->device->base.seat->libinput,
+ tp_button_handle_timeout, t);
}
return 0;
void
tp_destroy_buttons(struct tp_dispatch *tp)
{
- if (tp->buttons.source) {
- libinput_remove_source(tp->device->base.seat->libinput,
- tp->buttons.source);
- tp->buttons.source = NULL;
- }
- if (tp->buttons.timer_fd > -1) {
- close(tp->buttons.timer_fd);
- tp->buttons.timer_fd = -1;
- }
+ struct tp_touch *t;
+
+ tp_for_each_touch(tp, t)
+ libinput_timer_cancel(&t->button.timer);
}
static int
tp_post_clickfinger_buttons(struct tp_dispatch *tp, uint64_t time)
{
uint32_t current, old, button;
- enum libinput_pointer_button_state state;
+ enum libinput_button_state state;
current = tp->buttons.state;
old = tp->buttons.old_state;
return 0;
}
tp->buttons.active = button;
- state = LIBINPUT_POINTER_BUTTON_STATE_PRESSED;
+ state = LIBINPUT_BUTTON_STATE_PRESSED;
} else {
button = tp->buttons.active;
tp->buttons.active = 0;
- state = LIBINPUT_POINTER_BUTTON_STATE_RELEASED;
+ state = LIBINPUT_BUTTON_STATE_RELEASED;
}
if (button)
button = BTN_LEFT;
while (current || old) {
- enum libinput_pointer_button_state state;
+ enum libinput_button_state state;
if ((current & 0x1) ^ (old & 0x1)) {
if (!!(current & 0x1))
- state = LIBINPUT_POINTER_BUTTON_STATE_PRESSED;
+ state = LIBINPUT_BUTTON_STATE_PRESSED;
else
- state = LIBINPUT_POINTER_BUTTON_STATE_RELEASED;
+ state = LIBINPUT_BUTTON_STATE_RELEASED;
pointer_notify_button(&tp->device->base,
time,
tp_post_softbutton_buttons(struct tp_dispatch *tp, uint64_t time)
{
uint32_t current, old, button;
- enum libinput_pointer_button_state state;
- enum { AREA = 0x01, LEFT = 0x02, RIGHT = 0x04 };
+ enum libinput_button_state state;
+ enum { AREA = 0x01, LEFT = 0x02, MIDDLE = 0x04, RIGHT = 0x08 };
current = tp->buttons.state;
old = tp->buttons.old_state;
button |= AREA;
break;
case BUTTON_EVENT_IN_BOTTOM_L:
+ case BUTTON_EVENT_IN_TOP_L:
button |= LEFT;
break;
+ case BUTTON_EVENT_IN_TOP_M:
+ button |= MIDDLE;
+ break;
case BUTTON_EVENT_IN_BOTTOM_R:
+ case BUTTON_EVENT_IN_TOP_R:
button |= RIGHT;
break;
default:
}
}
- switch (button) {
- case 0:
+ if (button == 0) {
/* No touches, wait for a touch before processing */
tp->buttons.click_pending = true;
return 0;
- case RIGHT:
- case RIGHT | AREA:
- /* Some touches in right, no touches in left */
- button = BTN_RIGHT;
- break;
- case LEFT | RIGHT:
- case LEFT | RIGHT | AREA:
- /* Some touches in left and some in right */
+ }
+
+ if ((button & MIDDLE) || ((button & LEFT) && (button & RIGHT)))
button = BTN_MIDDLE;
- break;
- default:
+ else if (button & RIGHT)
+ button = BTN_RIGHT;
+ else
button = BTN_LEFT;
- }
tp->buttons.active = button;
- state = LIBINPUT_POINTER_BUTTON_STATE_PRESSED;
+ state = LIBINPUT_BUTTON_STATE_PRESSED;
} else {
button = tp->buttons.active;
tp->buttons.active = 0;
- state = LIBINPUT_POINTER_BUTTON_STATE_RELEASED;
+ state = LIBINPUT_BUTTON_STATE_RELEASED;
}
tp->buttons.click_pending = false;
{
return t->button.state == BUTTON_STATE_AREA;
}
+
+bool
+tp_button_is_inside_softbutton_area(struct tp_dispatch *tp, struct tp_touch *t)
+{
+ return is_inside_top_button_area(tp, t) || is_inside_bottom_button_area(tp, t);
+}