summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHenrik Rydberg <rydberg@euromail.se>2010-10-18 18:12:07 +0200
committerHenrik Rydberg <rydberg@euromail.se>2010-11-17 17:22:11 +0100
commit51236c2d264eababc9e1d16e206a6cc89ffb6d93 (patch)
treee3a3124257f090ae0cbe7c47d864e9308344bbfa /src
parentc91f21c9086374da1badd9026797ad29e3af63eb (diff)
Use a unified pointer emulation model
The existing kernel MT devices together use a handful of different pointer emulation strategies, each with its own subtlety. This creates a problem for grail, which needs to rebuild pointer emulation during gesture recognition; relying on the correct pointer information to be available at the right time becomes almost impossible. This patch implements a common pointer emulation model for grail, following a strategy recently discussed on LKML. This resolves the problems stemming from different emulation strategies, and results in a common pointer emulation experience for all devices. Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
Diffstat (limited to 'src')
-rw-r--r--src/grail-api.c60
-rw-r--r--src/grail-impl.h1
2 files changed, 57 insertions, 4 deletions
diff --git a/src/grail-api.c b/src/grail-api.c
index 9cc94df..f013aa3 100644
--- a/src/grail-api.c
+++ b/src/grail-api.c
@@ -36,10 +36,6 @@ static void tp_event(struct touch_dev *dev,
36 struct grail *ge = dev->priv; 36 struct grail *ge = dev->priv;
37 struct grail_impl *x = ge->impl; 37 struct grail_impl *x = ge->impl;
38 if (ev->type == EV_ABS) { 38 if (ev->type == EV_ABS) {
39 if (ev->code == ABS_X)
40 x->pointer_x = ev->value;
41 if (ev->code == ABS_Y)
42 x->pointer_y = ev->value;
43 return; 39 return;
44 } 40 }
45 if (ev->type == EV_KEY) { 41 if (ev->type == EV_KEY) {
@@ -80,6 +76,60 @@ static void report_up(struct grail_impl *impl, const struct input_event *syn)
80 impl->report_status = 0; 76 impl->report_status = 0;
81} 77}
82 78
79#define SYSCALL(call) while (((call) == -1) && (errno == EINTR))
80
81static int getabs(struct input_absinfo *abs, int key, int fd)
82{
83 int rc;
84 SYSCALL(rc = ioctl(fd, EVIOCGABS(key), abs));
85 return rc >= 0;
86}
87
88static void set_emulation_caps(struct grail_impl *impl, int fd)
89{
90 struct touch_caps *emu = &impl->emu;
91 struct input_absinfo info;
92
93 memset(emu, 0, sizeof(*emu));
94
95 if (getabs(&info, ABS_X, fd)) {
96 emu->min_x = info.minimum;
97 emu->max_x = info.maximum;
98 }
99 if (getabs(&info, ABS_Y, fd)) {
100 emu->min_y = info.minimum;
101 emu->max_y = info.maximum;
102 }
103}
104
105static void set_pointer(struct grail_impl *impl)
106{
107 struct touch_dev *dev = &impl->dev;
108 struct touch_caps *caps = &dev->caps;
109 struct touch_caps *emu = &impl->emu;
110 struct touch_frame *frame = &dev->frame;
111 int best_x, best_y, best_d = -1;
112 int i;
113
114 for (i = 0; i < frame->nactive; i++) {
115 struct touch *t = frame->active[i];
116 float u = (t->x - caps->min_x) / (caps->max_x - caps->min_x);
117 float v = (t->y - caps->min_y) / (caps->max_y - caps->min_y);
118 int x = emu->min_x + u * (emu->max_x - emu->min_x);
119 int y = emu->min_y + v * (emu->max_y - emu->min_y);
120 int d = abs(x - impl->pointer_x) + abs(y - impl->pointer_y);
121 if (best_d < 0 || d < best_d) {
122 best_x = x;
123 best_y = y;
124 best_d = d;
125 }
126 }
127 if (best_d >= 0) {
128 impl->pointer_x = best_x;
129 impl->pointer_y = best_y;
130 }
131}
132
83static void handle_abs_events(struct grail *ge, const struct input_event *syn) 133static void handle_abs_events(struct grail *ge, const struct input_event *syn)
84{ 134{
85 static const int fm_mask = 0x03; 135 static const int fm_mask = 0x03;
@@ -95,6 +145,7 @@ static void handle_abs_events(struct grail *ge, const struct input_event *syn)
95 int ishold = pointer && tap->active && !used_move; 145 int ishold = pointer && tap->active && !used_move;
96 int istap = gru->tapping.tap == 1 && !used_tap; 146 int istap = gru->tapping.tap == 1 && !used_tap;
97 147
148 set_pointer(impl);
98 if (!impl->pointer_status && pointer) { 149 if (!impl->pointer_status && pointer) {
99 impl->report_x = impl->pointer_x; 150 impl->report_x = impl->pointer_x;
100 impl->report_y = impl->pointer_y; 151 impl->report_y = impl->pointer_y;
@@ -175,6 +226,7 @@ int grail_open(struct grail *ge, int fd)
175 ret = touch_dev_open(&x->dev, fd); 226 ret = touch_dev_open(&x->dev, fd);
176 if (ret) 227 if (ret)
177 goto freemem; 228 goto freemem;
229 set_emulation_caps(x, fd);
178 x->dev.event = tp_event; 230 x->dev.event = tp_event;
179 x->dev.sync = tp_sync; 231 x->dev.sync = tp_sync;
180 x->dev.priv = ge; 232 x->dev.priv = ge;
diff --git a/src/grail-impl.h b/src/grail-impl.h
index 6093a0f..dc3b425 100644
--- a/src/grail-impl.h
+++ b/src/grail-impl.h
@@ -28,6 +28,7 @@
28 28
29struct grail_impl { 29struct grail_impl {
30 struct touch_dev dev; 30 struct touch_dev dev;
31 struct touch_caps emu;
31 struct evbuf evbuf; 32 struct evbuf evbuf;
32 int filter_abs; 33 int filter_abs;
33 int pointer_status; 34 int pointer_status;