diff options
| author | Henrik Rydberg <rydberg@euromail.se> | 2010-10-18 18:12:07 +0200 |
|---|---|---|
| committer | Henrik Rydberg <rydberg@euromail.se> | 2010-11-17 17:22:11 +0100 |
| commit | 51236c2d264eababc9e1d16e206a6cc89ffb6d93 (patch) | |
| tree | e3a3124257f090ae0cbe7c47d864e9308344bbfa | |
| parent | c91f21c9086374da1badd9026797ad29e3af63eb (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>
| -rw-r--r-- | src/grail-api.c | 60 | ||||
| -rw-r--r-- | src/grail-impl.h | 1 |
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 | |||
| 81 | static 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 | |||
| 88 | static 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 | |||
| 105 | static 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 | |||
| 83 | static void handle_abs_events(struct grail *ge, const struct input_event *syn) | 133 | static 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 | ||
| 29 | struct grail_impl { | 29 | struct 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; |
