diff options
author | Clinton Sprain <clintonsprain@gmail.com> | 2014-03-31 02:37:05 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2014-03-31 02:44:17 -0400 |
commit | 7bbdba56ba9e01e610f7455c0375f9bbef84f3b1 (patch) | |
tree | 32544e69b278ab1650639afd9ba451d20c1869c1 /drivers/input | |
parent | 739204bc957750ca47254114b8ee49b00edfc18d (diff) |
Input: appletouch - fix jumps when additional fingers are detected
Addresses issues related to when a second finger enters or leaves the
field, causing the cursor to jump or the page to scroll unexpectedly; now,
we discard any movement change that happens at the exact moment we detect a
change in the number of fingers touching the trackpad. This doesn't
completely resolve the issue but does greatly mitigate it.
Signed-off-by: Clinton Sprain <clintonsprain@gmail.com>
Reviewed-by: Henrik Rydberg <rydberg@euromail.se>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers/input')
-rw-r--r-- | drivers/input/mouse/appletouch.c | 27 |
1 files changed, 21 insertions, 6 deletions
diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c index 2dbf7a0f0537..ef234c9b2f2f 100644 --- a/drivers/input/mouse/appletouch.c +++ b/drivers/input/mouse/appletouch.c | |||
@@ -218,6 +218,7 @@ struct atp { | |||
218 | bool valid; /* are the samples valid? */ | 218 | bool valid; /* are the samples valid? */ |
219 | bool size_detect_done; | 219 | bool size_detect_done; |
220 | bool overflow_warned; | 220 | bool overflow_warned; |
221 | int fingers_old; /* last reported finger count */ | ||
221 | int x_old; /* last reported x/y, */ | 222 | int x_old; /* last reported x/y, */ |
222 | int y_old; /* used for smoothing */ | 223 | int y_old; /* used for smoothing */ |
223 | signed char xy_cur[ATP_XSENSORS + ATP_YSENSORS]; | 224 | signed char xy_cur[ATP_XSENSORS + ATP_YSENSORS]; |
@@ -528,7 +529,7 @@ static void atp_complete_geyser_1_2(struct urb *urb) | |||
528 | { | 529 | { |
529 | int x, y, x_z, y_z, x_f, y_f; | 530 | int x, y, x_z, y_z, x_f, y_f; |
530 | int retval, i, j; | 531 | int retval, i, j; |
531 | int key; | 532 | int key, fingers; |
532 | struct atp *dev = urb->context; | 533 | struct atp *dev = urb->context; |
533 | int status = atp_status_check(urb); | 534 | int status = atp_status_check(urb); |
534 | 535 | ||
@@ -611,7 +612,9 @@ static void atp_complete_geyser_1_2(struct urb *urb) | |||
611 | dev->info->yfact, &y_z, &y_f); | 612 | dev->info->yfact, &y_z, &y_f); |
612 | key = dev->data[dev->info->datalen - 1] & ATP_STATUS_BUTTON; | 613 | key = dev->data[dev->info->datalen - 1] & ATP_STATUS_BUTTON; |
613 | 614 | ||
614 | if (x && y) { | 615 | fingers = max(x_f, y_f); |
616 | |||
617 | if (x && y && fingers == dev->fingers_old) { | ||
615 | if (dev->x_old != -1) { | 618 | if (dev->x_old != -1) { |
616 | x = (dev->x_old * 7 + x) >> 3; | 619 | x = (dev->x_old * 7 + x) >> 3; |
617 | y = (dev->y_old * 7 + y) >> 3; | 620 | y = (dev->y_old * 7 + y) >> 3; |
@@ -628,7 +631,7 @@ static void atp_complete_geyser_1_2(struct urb *urb) | |||
628 | input_report_abs(dev->input, ABS_Y, y); | 631 | input_report_abs(dev->input, ABS_Y, y); |
629 | input_report_abs(dev->input, ABS_PRESSURE, | 632 | input_report_abs(dev->input, ABS_PRESSURE, |
630 | min(ATP_PRESSURE, x_z + y_z)); | 633 | min(ATP_PRESSURE, x_z + y_z)); |
631 | atp_report_fingers(dev->input, max(x_f, y_f)); | 634 | atp_report_fingers(dev->input, fingers); |
632 | } | 635 | } |
633 | dev->x_old = x; | 636 | dev->x_old = x; |
634 | dev->y_old = y; | 637 | dev->y_old = y; |
@@ -636,6 +639,7 @@ static void atp_complete_geyser_1_2(struct urb *urb) | |||
636 | } else if (!x && !y) { | 639 | } else if (!x && !y) { |
637 | 640 | ||
638 | dev->x_old = dev->y_old = -1; | 641 | dev->x_old = dev->y_old = -1; |
642 | dev->fingers_old = 0; | ||
639 | input_report_key(dev->input, BTN_TOUCH, 0); | 643 | input_report_key(dev->input, BTN_TOUCH, 0); |
640 | input_report_abs(dev->input, ABS_PRESSURE, 0); | 644 | input_report_abs(dev->input, ABS_PRESSURE, 0); |
641 | atp_report_fingers(dev->input, 0); | 645 | atp_report_fingers(dev->input, 0); |
@@ -644,6 +648,10 @@ static void atp_complete_geyser_1_2(struct urb *urb) | |||
644 | memset(dev->xy_acc, 0, sizeof(dev->xy_acc)); | 648 | memset(dev->xy_acc, 0, sizeof(dev->xy_acc)); |
645 | } | 649 | } |
646 | 650 | ||
651 | if (fingers != dev->fingers_old) | ||
652 | dev->x_old = dev->y_old = -1; | ||
653 | dev->fingers_old = fingers; | ||
654 | |||
647 | input_report_key(dev->input, BTN_LEFT, key); | 655 | input_report_key(dev->input, BTN_LEFT, key); |
648 | input_sync(dev->input); | 656 | input_sync(dev->input); |
649 | 657 | ||
@@ -661,7 +669,7 @@ static void atp_complete_geyser_3_4(struct urb *urb) | |||
661 | { | 669 | { |
662 | int x, y, x_z, y_z, x_f, y_f; | 670 | int x, y, x_z, y_z, x_f, y_f; |
663 | int retval, i, j; | 671 | int retval, i, j; |
664 | int key; | 672 | int key, fingers; |
665 | struct atp *dev = urb->context; | 673 | struct atp *dev = urb->context; |
666 | int status = atp_status_check(urb); | 674 | int status = atp_status_check(urb); |
667 | 675 | ||
@@ -724,7 +732,9 @@ static void atp_complete_geyser_3_4(struct urb *urb) | |||
724 | 732 | ||
725 | key = dev->data[dev->info->datalen - 1] & ATP_STATUS_BUTTON; | 733 | key = dev->data[dev->info->datalen - 1] & ATP_STATUS_BUTTON; |
726 | 734 | ||
727 | if (x && y) { | 735 | fingers = max(x_f, y_f); |
736 | |||
737 | if (x && y && fingers == dev->fingers_old) { | ||
728 | if (dev->x_old != -1) { | 738 | if (dev->x_old != -1) { |
729 | x = (dev->x_old * 7 + x) >> 3; | 739 | x = (dev->x_old * 7 + x) >> 3; |
730 | y = (dev->y_old * 7 + y) >> 3; | 740 | y = (dev->y_old * 7 + y) >> 3; |
@@ -741,7 +751,7 @@ static void atp_complete_geyser_3_4(struct urb *urb) | |||
741 | input_report_abs(dev->input, ABS_Y, y); | 751 | input_report_abs(dev->input, ABS_Y, y); |
742 | input_report_abs(dev->input, ABS_PRESSURE, | 752 | input_report_abs(dev->input, ABS_PRESSURE, |
743 | min(ATP_PRESSURE, x_z + y_z)); | 753 | min(ATP_PRESSURE, x_z + y_z)); |
744 | atp_report_fingers(dev->input, max(x_f, y_f)); | 754 | atp_report_fingers(dev->input, fingers); |
745 | } | 755 | } |
746 | dev->x_old = x; | 756 | dev->x_old = x; |
747 | dev->y_old = y; | 757 | dev->y_old = y; |
@@ -749,6 +759,7 @@ static void atp_complete_geyser_3_4(struct urb *urb) | |||
749 | } else if (!x && !y) { | 759 | } else if (!x && !y) { |
750 | 760 | ||
751 | dev->x_old = dev->y_old = -1; | 761 | dev->x_old = dev->y_old = -1; |
762 | dev->fingers_old = 0; | ||
752 | input_report_key(dev->input, BTN_TOUCH, 0); | 763 | input_report_key(dev->input, BTN_TOUCH, 0); |
753 | input_report_abs(dev->input, ABS_PRESSURE, 0); | 764 | input_report_abs(dev->input, ABS_PRESSURE, 0); |
754 | atp_report_fingers(dev->input, 0); | 765 | atp_report_fingers(dev->input, 0); |
@@ -757,6 +768,10 @@ static void atp_complete_geyser_3_4(struct urb *urb) | |||
757 | memset(dev->xy_acc, 0, sizeof(dev->xy_acc)); | 768 | memset(dev->xy_acc, 0, sizeof(dev->xy_acc)); |
758 | } | 769 | } |
759 | 770 | ||
771 | if (fingers != dev->fingers_old) | ||
772 | dev->x_old = dev->y_old = -1; | ||
773 | dev->fingers_old = fingers; | ||
774 | |||
760 | input_report_key(dev->input, BTN_LEFT, key); | 775 | input_report_key(dev->input, BTN_LEFT, key); |
761 | input_sync(dev->input); | 776 | input_sync(dev->input); |
762 | 777 | ||