Commit 7bbdba56 authored by Clinton Sprain's avatar Clinton Sprain Committed by Dmitry Torokhov

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: default avatarClinton Sprain <clintonsprain@gmail.com>
Reviewed-by: default avatarHenrik Rydberg <rydberg@euromail.se>
Signed-off-by: default avatarDmitry Torokhov <dmitry.torokhov@gmail.com>
parent 739204bc
...@@ -218,6 +218,7 @@ struct atp { ...@@ -218,6 +218,7 @@ struct atp {
bool valid; /* are the samples valid? */ bool valid; /* are the samples valid? */
bool size_detect_done; bool size_detect_done;
bool overflow_warned; bool overflow_warned;
int fingers_old; /* last reported finger count */
int x_old; /* last reported x/y, */ int x_old; /* last reported x/y, */
int y_old; /* used for smoothing */ int y_old; /* used for smoothing */
signed char xy_cur[ATP_XSENSORS + ATP_YSENSORS]; signed char xy_cur[ATP_XSENSORS + ATP_YSENSORS];
...@@ -528,7 +529,7 @@ static void atp_complete_geyser_1_2(struct urb *urb) ...@@ -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 x, y, x_z, y_z, x_f, y_f;
int retval, i, j; int retval, i, j;
int key; int key, fingers;
struct atp *dev = urb->context; struct atp *dev = urb->context;
int status = atp_status_check(urb); int status = atp_status_check(urb);
...@@ -611,7 +612,9 @@ static void atp_complete_geyser_1_2(struct urb *urb) ...@@ -611,7 +612,9 @@ static void atp_complete_geyser_1_2(struct urb *urb)
dev->info->yfact, &y_z, &y_f); dev->info->yfact, &y_z, &y_f);
key = dev->data[dev->info->datalen - 1] & ATP_STATUS_BUTTON; 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) { if (dev->x_old != -1) {
x = (dev->x_old * 7 + x) >> 3; x = (dev->x_old * 7 + x) >> 3;
y = (dev->y_old * 7 + y) >> 3; y = (dev->y_old * 7 + y) >> 3;
...@@ -628,7 +631,7 @@ static void atp_complete_geyser_1_2(struct urb *urb) ...@@ -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_Y, y);
input_report_abs(dev->input, ABS_PRESSURE, input_report_abs(dev->input, ABS_PRESSURE,
min(ATP_PRESSURE, x_z + y_z)); 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->x_old = x;
dev->y_old = y; dev->y_old = y;
...@@ -636,6 +639,7 @@ static void atp_complete_geyser_1_2(struct urb *urb) ...@@ -636,6 +639,7 @@ static void atp_complete_geyser_1_2(struct urb *urb)
} else if (!x && !y) { } else if (!x && !y) {
dev->x_old = dev->y_old = -1; dev->x_old = dev->y_old = -1;
dev->fingers_old = 0;
input_report_key(dev->input, BTN_TOUCH, 0); input_report_key(dev->input, BTN_TOUCH, 0);
input_report_abs(dev->input, ABS_PRESSURE, 0); input_report_abs(dev->input, ABS_PRESSURE, 0);
atp_report_fingers(dev->input, 0); atp_report_fingers(dev->input, 0);
...@@ -644,6 +648,10 @@ static void atp_complete_geyser_1_2(struct urb *urb) ...@@ -644,6 +648,10 @@ static void atp_complete_geyser_1_2(struct urb *urb)
memset(dev->xy_acc, 0, sizeof(dev->xy_acc)); 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_report_key(dev->input, BTN_LEFT, key);
input_sync(dev->input); input_sync(dev->input);
...@@ -661,7 +669,7 @@ static void atp_complete_geyser_3_4(struct urb *urb) ...@@ -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 x, y, x_z, y_z, x_f, y_f;
int retval, i, j; int retval, i, j;
int key; int key, fingers;
struct atp *dev = urb->context; struct atp *dev = urb->context;
int status = atp_status_check(urb); int status = atp_status_check(urb);
...@@ -724,7 +732,9 @@ static void atp_complete_geyser_3_4(struct urb *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; 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) { if (dev->x_old != -1) {
x = (dev->x_old * 7 + x) >> 3; x = (dev->x_old * 7 + x) >> 3;
y = (dev->y_old * 7 + y) >> 3; y = (dev->y_old * 7 + y) >> 3;
...@@ -741,7 +751,7 @@ static void atp_complete_geyser_3_4(struct urb *urb) ...@@ -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_Y, y);
input_report_abs(dev->input, ABS_PRESSURE, input_report_abs(dev->input, ABS_PRESSURE,
min(ATP_PRESSURE, x_z + y_z)); 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->x_old = x;
dev->y_old = y; dev->y_old = y;
...@@ -749,6 +759,7 @@ static void atp_complete_geyser_3_4(struct urb *urb) ...@@ -749,6 +759,7 @@ static void atp_complete_geyser_3_4(struct urb *urb)
} else if (!x && !y) { } else if (!x && !y) {
dev->x_old = dev->y_old = -1; dev->x_old = dev->y_old = -1;
dev->fingers_old = 0;
input_report_key(dev->input, BTN_TOUCH, 0); input_report_key(dev->input, BTN_TOUCH, 0);
input_report_abs(dev->input, ABS_PRESSURE, 0); input_report_abs(dev->input, ABS_PRESSURE, 0);
atp_report_fingers(dev->input, 0); atp_report_fingers(dev->input, 0);
...@@ -757,6 +768,10 @@ static void atp_complete_geyser_3_4(struct urb *urb) ...@@ -757,6 +768,10 @@ static void atp_complete_geyser_3_4(struct urb *urb)
memset(dev->xy_acc, 0, sizeof(dev->xy_acc)); 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_report_key(dev->input, BTN_LEFT, key);
input_sync(dev->input); input_sync(dev->input);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment