Commit c5b7a7d2 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] Input: smooth out mouse jitter

From: Dmitry Torokhov <dtor_core@ameritech.net>

When calculating deltas for touchpads that generate absolute events use
average over the last 3 packets to remove jitter
parent a15092bd
......@@ -553,16 +553,19 @@ static void synaptics_process_packet(struct psmouse *psmouse)
finger_width = 0;
}
/* Post events */
/* Post events
* BTN_TOUCH has to be first as mousedev relies on it when doing
* absolute -> relative conversion
*/
if (hw.z > 30) input_report_key(dev, BTN_TOUCH, 1);
if (hw.z < 25) input_report_key(dev, BTN_TOUCH, 0);
if (hw.z > 0) {
input_report_abs(dev, ABS_X, hw.x);
input_report_abs(dev, ABS_Y, YMAX_NOMINAL + YMIN_NOMINAL - hw.y);
}
input_report_abs(dev, ABS_PRESSURE, hw.z);
if (hw.z > 30) input_report_key(dev, BTN_TOUCH, 1);
if (hw.z < 25) input_report_key(dev, BTN_TOUCH, 0);
input_report_abs(dev, ABS_TOOL_WIDTH, finger_width);
input_report_key(dev, BTN_TOOL_FINGER, num_fingers == 1);
input_report_key(dev, BTN_TOOL_DOUBLETAP, num_fingers == 2);
......
......@@ -53,12 +53,14 @@ struct mousedev_list {
struct fasync_struct *fasync;
struct mousedev *mousedev;
struct list_head node;
int dx, dy, dz, oldx, oldy;
signed char ps2[6];
int dx, dy, dz;
int old_x[4], old_y[4];
unsigned long buttons;
signed char ps2[6];
unsigned char ready, buffer, bufsiz;
unsigned char mode, imexseq, impsseq;
int finger;
unsigned int pkt_count;
unsigned char touch;
};
#define MOUSEDEV_SEQ_LEN 6
......@@ -74,49 +76,49 @@ static struct mousedev mousedev_mix;
static int xres = CONFIG_INPUT_MOUSEDEV_SCREEN_X;
static int yres = CONFIG_INPUT_MOUSEDEV_SCREEN_Y;
#define fx(i) (list->old_x[(list->pkt_count - (i)) & 03])
#define fy(i) (list->old_y[(list->pkt_count - (i)) & 03])
static void mousedev_abs_event(struct input_handle *handle, struct mousedev_list *list, unsigned int code, int value)
{
int size;
int touchpad;
/* Ignore joysticks */
if (test_bit(BTN_TRIGGER, handle->dev->keybit))
return;
/* Handle touchpad data */
if (test_bit(BTN_TOOL_FINGER, handle->dev->keybit)) {
if (list->finger && list->finger < 3)
list->finger++;
switch (code) {
case ABS_X:
if (list->finger == 3)
list->dx += (value - list->oldx) / 8;
list->oldx = value;
return;
case ABS_Y:
if (list->finger == 3)
list->dy -= (value - list->oldy) / 8;
list->oldy = value;
return;
}
return;
}
touchpad = test_bit(BTN_TOOL_FINGER, handle->dev->keybit);
/* Handle tablet data */
switch (code) {
case ABS_X:
size = handle->dev->absmax[ABS_X] - handle->dev->absmin[ABS_X];
if (size == 0) size = xres;
list->dx += (value * xres - list->oldx) / size;
list->oldx += list->dx * size;
return;
if (touchpad) {
if (list->touch) {
fx(0) = value;
if (list->pkt_count >= 2)
list->dx = ((fx(0) - fx(1)) / 2 + (fx(1) - fx(2)) / 2) / 8;
}
} else {
size = handle->dev->absmax[ABS_X] - handle->dev->absmin[ABS_X];
if (size == 0) size = xres;
list->dx += (value * xres - list->old_x[0]) / size;
list->old_x[0] += list->dx * size;
}
break;
case ABS_Y:
size = handle->dev->absmax[ABS_Y] - handle->dev->absmin[ABS_Y];
if (size == 0) size = yres;
list->dy -= (value * yres - list->oldy) / size;
list->oldy -= list->dy * size;
return;
if (touchpad) {
if (list->touch) {
fy(0) = value;
if (list->pkt_count >= 2)
list->dy = -((fy(0) - fy(1)) / 2 + (fy(1) - fy(2)) / 2) / 8;
}
} else {
size = handle->dev->absmax[ABS_Y] - handle->dev->absmin[ABS_Y];
if (size == 0) size = yres;
list->dy -= (value * yres - list->old_y[0]) / size;
list->old_y[0] -= list->dy * size;
}
break;
}
}
......@@ -149,7 +151,9 @@ static void mousedev_event(struct input_handle *handle, unsigned int type, unsig
switch (code) {
case BTN_TOUCH: /* Handle touchpad data */
if (test_bit(BTN_TOOL_FINGER, handle->dev->keybit)) {
list->finger = value;
list->touch = value;
if (!list->touch)
list->pkt_count = 0;
return;
}
case BTN_0:
......@@ -178,6 +182,16 @@ static void mousedev_event(struct input_handle *handle, unsigned int type, unsig
case EV_SYN:
switch (code) {
case SYN_REPORT:
if (list->touch) {
list->pkt_count++;
/* Input system eats duplicate events,
* but we need all of them to do correct
* averaging so apply present one forward
*/
fx(0) = fx(1);
fy(0) = fy(1);
}
list->ready = 1;
kill_fasync(&list->fasync, SIGIO, POLL_IN);
wake = 1;
......
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