summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPeter Hutterer <peter.hutterer@who-t.net>2016-04-04 10:06:36 +1000
committerPeter Hutterer <peter.hutterer@who-t.net>2016-04-05 10:13:56 +1000
commit886b5a2cd8c785e48ddf5ceb4a902cd1f518d2a9 (patch)
tree9d58b79a9f667db7bec18a1c633737c3df0947d6 /src
parent1ecf6d7a607c5f481eb9b3b6365d7b55a0f18c53 (diff)
touchpad: add a middle button software area
Middle button interaction is most commonly to paste and it is a single-event interaction (button press). We provided middle button in software button mode by emulating it with a two-finger press with L+R down at the same time. This is also what many touchpads are spectacularly bad at, it is very common to detect the physical button down event before the second finger registers, resulting in left or right clicks where a middle button should be triggered. Unless the fingers are resting on the touchpad for at least one scanout, the success rate for middle button emulation is only at 70% or so. This patch adds a 25%-width middle button area between the left and the right software button, everything else stays the same. To avoid immediate breakage, the middle button emulation remains but may be removed in the future. The doc is updated to only refer to the middle button area now. https://bugs.freedesktop.org/show_bug.cgi?id=94755 Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Diffstat (limited to 'src')
-rw-r--r--src/evdev-mt-touchpad-buttons.c31
-rw-r--r--src/evdev-mt-touchpad.h2
2 files changed, 32 insertions, 1 deletions
diff --git a/src/evdev-mt-touchpad-buttons.c b/src/evdev-mt-touchpad-buttons.c
index 076eab00..a9b75216 100644
--- a/src/evdev-mt-touchpad-buttons.c
+++ b/src/evdev-mt-touchpad-buttons.c
@@ -64,6 +64,7 @@ static inline const char*
button_event_to_str(enum button_event event) {
switch(event) {
CASE_RETURN_STRING(BUTTON_EVENT_IN_BOTTOM_R);
+ CASE_RETURN_STRING(BUTTON_EVENT_IN_BOTTOM_M);
CASE_RETURN_STRING(BUTTON_EVENT_IN_BOTTOM_L);
CASE_RETURN_STRING(BUTTON_EVENT_IN_TOP_R);
CASE_RETURN_STRING(BUTTON_EVENT_IN_TOP_M);
@@ -93,10 +94,20 @@ is_inside_bottom_right_area(const struct tp_dispatch *tp,
}
static inline bool
+is_inside_bottom_middle_area(const struct tp_dispatch *tp,
+ const struct tp_touch *t)
+{
+ return is_inside_bottom_button_area(tp, t) &&
+ !is_inside_bottom_right_area(tp, t) &&
+ t->point.x > tp->buttons.bottom_area.middlebutton_left_edge;
+}
+
+static inline bool
is_inside_bottom_left_area(const struct tp_dispatch *tp,
const struct tp_touch *t)
{
return is_inside_bottom_button_area(tp, t) &&
+ !is_inside_bottom_middle_area(tp, t) &&
!is_inside_bottom_right_area(tp, t);
}
@@ -192,6 +203,7 @@ tp_button_none_handle_event(struct tp_dispatch *tp,
{
switch (event) {
case BUTTON_EVENT_IN_BOTTOM_R:
+ case BUTTON_EVENT_IN_BOTTOM_M:
case BUTTON_EVENT_IN_BOTTOM_L:
tp_button_set_state(tp, t, BUTTON_STATE_BOTTOM, event);
break;
@@ -220,6 +232,7 @@ tp_button_area_handle_event(struct tp_dispatch *tp,
{
switch (event) {
case BUTTON_EVENT_IN_BOTTOM_R:
+ case BUTTON_EVENT_IN_BOTTOM_M:
case BUTTON_EVENT_IN_BOTTOM_L:
case BUTTON_EVENT_IN_TOP_R:
case BUTTON_EVENT_IN_TOP_M:
@@ -243,6 +256,7 @@ tp_button_bottom_handle_event(struct tp_dispatch *tp,
{
switch (event) {
case BUTTON_EVENT_IN_BOTTOM_R:
+ case BUTTON_EVENT_IN_BOTTOM_M:
case BUTTON_EVENT_IN_BOTTOM_L:
if (event != t->button.curr)
tp_button_set_state(tp,
@@ -273,6 +287,7 @@ tp_button_top_handle_event(struct tp_dispatch *tp,
{
switch (event) {
case BUTTON_EVENT_IN_BOTTOM_R:
+ case BUTTON_EVENT_IN_BOTTOM_M:
case BUTTON_EVENT_IN_BOTTOM_L:
tp_button_set_state(tp, t, BUTTON_STATE_TOP_TO_IGNORE, event);
break;
@@ -305,6 +320,7 @@ tp_button_top_new_handle_event(struct tp_dispatch *tp,
{
switch(event) {
case BUTTON_EVENT_IN_BOTTOM_R:
+ case BUTTON_EVENT_IN_BOTTOM_M:
case BUTTON_EVENT_IN_BOTTOM_L:
tp_button_set_state(tp, t, BUTTON_STATE_AREA, event);
break;
@@ -355,6 +371,7 @@ tp_button_top_to_ignore_handle_event(struct tp_dispatch *tp,
event);
break;
case BUTTON_EVENT_IN_BOTTOM_R:
+ case BUTTON_EVENT_IN_BOTTOM_M:
case BUTTON_EVENT_IN_BOTTOM_L:
case BUTTON_EVENT_IN_AREA:
break;
@@ -377,6 +394,7 @@ tp_button_ignore_handle_event(struct tp_dispatch *tp,
{
switch (event) {
case BUTTON_EVENT_IN_BOTTOM_R:
+ case BUTTON_EVENT_IN_BOTTOM_M:
case BUTTON_EVENT_IN_BOTTOM_L:
case BUTTON_EVENT_IN_TOP_R:
case BUTTON_EVENT_IN_TOP_M:
@@ -450,6 +468,8 @@ tp_button_handle_state(struct tp_dispatch *tp, uint64_t time)
if (is_inside_bottom_right_area(tp, t))
event = BUTTON_EVENT_IN_BOTTOM_R;
+ else if (is_inside_bottom_middle_area(tp, t))
+ event = BUTTON_EVENT_IN_BOTTOM_M;
else if (is_inside_bottom_left_area(tp, t))
event = BUTTON_EVENT_IN_BOTTOM_L;
else if (is_inside_top_right_area(tp, t))
@@ -543,7 +563,14 @@ tp_init_softbuttons(struct tp_dispatch *tp,
} else {
tp->buttons.bottom_area.top_edge = height * .85 + yoffset;
}
- tp->buttons.bottom_area.rightbutton_left_edge = width/2 + xoffset;
+
+ /* The middle button is 25% of the touchpad and centered. Many
+ * touchpads don't have markings for the middle button at all so we
+ * need to make it big enough to reliably hit it but not too big so
+ * it takes away all the space.
+ */
+ tp->buttons.bottom_area.middlebutton_left_edge = width * 0.375 + xoffset;
+ tp->buttons.bottom_area.rightbutton_left_edge = width * 0.625 + xoffset;
}
void
@@ -989,6 +1016,8 @@ tp_post_clickpadbutton_buttons(struct tp_dispatch *tp, uint64_t time)
break;
case BUTTON_EVENT_IN_TOP_M:
is_top = 1;
+ /* fallthrough */
+ case BUTTON_EVENT_IN_BOTTOM_M:
area |= MIDDLE;
break;
case BUTTON_EVENT_IN_TOP_R:
diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h
index 1f05a03e..7277726e 100644
--- a/src/evdev-mt-touchpad.h
+++ b/src/evdev-mt-touchpad.h
@@ -70,6 +70,7 @@ enum touch_palm_state {
enum button_event {
BUTTON_EVENT_IN_BOTTOM_R = 30,
+ BUTTON_EVENT_IN_BOTTOM_M,
BUTTON_EVENT_IN_BOTTOM_L,
BUTTON_EVENT_IN_TOP_R,
BUTTON_EVENT_IN_TOP_M,
@@ -283,6 +284,7 @@ struct tp_dispatch {
struct {
int32_t top_edge; /* in device coordinates */
int32_t rightbutton_left_edge; /* in device coordinates */
+ int32_t middlebutton_left_edge; /* in device coordinates */
} bottom_area;
struct {