Input: appletouch - fix jumps when additional fingers are detected
authorClinton Sprain <clintonsprain@gmail.com>
Mon, 31 Mar 2014 06:37:05 +0000 (23:37 -0700)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Mon, 31 Mar 2014 06:44:17 +0000 (23:44 -0700)
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>
drivers/input/mouse/appletouch.c

index 2dbf7a0f0537f2b56f6f3a56bf8aede646927961..ef234c9b2f2f5cce7e365951df37cef4bc8b08e4 100644 (file)
@@ -218,6 +218,7 @@ struct atp {
        bool                    valid;          /* are the samples valid? */
        bool                    size_detect_done;
        bool                    overflow_warned;
+       int                     fingers_old;    /* last reported finger count */
        int                     x_old;          /* last reported x/y, */
        int                     y_old;          /* used for smoothing */
        signed char             xy_cur[ATP_XSENSORS + ATP_YSENSORS];
@@ -528,7 +529,7 @@ static void atp_complete_geyser_1_2(struct urb *urb)
 {
        int x, y, x_z, y_z, x_f, y_f;
        int retval, i, j;
-       int key;
+       int key, fingers;
        struct atp *dev = urb->context;
        int status = atp_status_check(urb);
 
@@ -611,7 +612,9 @@ static void atp_complete_geyser_1_2(struct urb *urb)
                              dev->info->yfact, &y_z, &y_f);
        key = dev->data[dev->info->datalen - 1] & ATP_STATUS_BUTTON;
 
-       if (x && y) {
+       fingers = max(x_f, y_f);
+
+       if (x && y && fingers == dev->fingers_old) {
                if (dev->x_old != -1) {
                        x = (dev->x_old * 7 + x) >> 3;
                        y = (dev->y_old * 7 + y) >> 3;
@@ -628,7 +631,7 @@ static void atp_complete_geyser_1_2(struct urb *urb)
                        input_report_abs(dev->input, ABS_Y, y);
                        input_report_abs(dev->input, ABS_PRESSURE,
                                         min(ATP_PRESSURE, x_z + y_z));
-                       atp_report_fingers(dev->input, max(x_f, y_f));
+                       atp_report_fingers(dev->input, fingers);
                }
                dev->x_old = x;
                dev->y_old = y;
@@ -636,6 +639,7 @@ static void atp_complete_geyser_1_2(struct urb *urb)
        } else if (!x && !y) {
 
                dev->x_old = dev->y_old = -1;
+               dev->fingers_old = 0;
                input_report_key(dev->input, BTN_TOUCH, 0);
                input_report_abs(dev->input, ABS_PRESSURE, 0);
                atp_report_fingers(dev->input, 0);
@@ -644,6 +648,10 @@ static void atp_complete_geyser_1_2(struct urb *urb)
                memset(dev->xy_acc, 0, sizeof(dev->xy_acc));
        }
 
+       if (fingers != dev->fingers_old)
+               dev->x_old = dev->y_old = -1;
+       dev->fingers_old = fingers;
+
        input_report_key(dev->input, BTN_LEFT, key);
        input_sync(dev->input);
 
@@ -661,7 +669,7 @@ static void atp_complete_geyser_3_4(struct urb *urb)
 {
        int x, y, x_z, y_z, x_f, y_f;
        int retval, i, j;
-       int key;
+       int key, fingers;
        struct atp *dev = urb->context;
        int status = atp_status_check(urb);
 
@@ -724,7 +732,9 @@ static void atp_complete_geyser_3_4(struct urb *urb)
 
        key = dev->data[dev->info->datalen - 1] & ATP_STATUS_BUTTON;
 
-       if (x && y) {
+       fingers = max(x_f, y_f);
+
+       if (x && y && fingers == dev->fingers_old) {
                if (dev->x_old != -1) {
                        x = (dev->x_old * 7 + x) >> 3;
                        y = (dev->y_old * 7 + y) >> 3;
@@ -741,7 +751,7 @@ static void atp_complete_geyser_3_4(struct urb *urb)
                        input_report_abs(dev->input, ABS_Y, y);
                        input_report_abs(dev->input, ABS_PRESSURE,
                                         min(ATP_PRESSURE, x_z + y_z));
-                       atp_report_fingers(dev->input, max(x_f, y_f));
+                       atp_report_fingers(dev->input, fingers);
                }
                dev->x_old = x;
                dev->y_old = y;
@@ -749,6 +759,7 @@ static void atp_complete_geyser_3_4(struct urb *urb)
        } else if (!x && !y) {
 
                dev->x_old = dev->y_old = -1;
+               dev->fingers_old = 0;
                input_report_key(dev->input, BTN_TOUCH, 0);
                input_report_abs(dev->input, ABS_PRESSURE, 0);
                atp_report_fingers(dev->input, 0);
@@ -757,6 +768,10 @@ static void atp_complete_geyser_3_4(struct urb *urb)
                memset(dev->xy_acc, 0, sizeof(dev->xy_acc));
        }
 
+       if (fingers != dev->fingers_old)
+               dev->x_old = dev->y_old = -1;
+       dev->fingers_old = fingers;
+
        input_report_key(dev->input, BTN_LEFT, key);
        input_sync(dev->input);