summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHenrik Rydberg <rydberg@euromail.se>2011-01-02 11:00:52 +0100
committerHenrik Rydberg <rydberg@euromail.se>2011-01-02 12:39:07 +0100
commitc0666a895e7fe8e488332263fd106ced0ed7cab7 (patch)
treefca88fbee4aaed6e1eed050a749ce6246a7f1966
parent1e07054fbeab6e90f104c279d3246097dd838a17 (diff)
Replace touch logic with utouch frame engine
The original grail uses an internal touch framework and exports some touch information as extended attributes to gesture events. This was never quite the intention, but rather to expose gestures and touches on a similar footing, such that grail can be input agnostic. This patch starts off by replacing the internal touch framework with the utouch-frame engine. Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
-rw-r--r--INSTALL4
-rw-r--r--configure.ac4
-rw-r--r--include/grail-touch.h85
-rw-r--r--src/Makefile.am7
-rw-r--r--src/gebuf.h4
-rw-r--r--src/gestures-drag.c6
-rw-r--r--src/gestures-pinch.c6
-rw-r--r--src/gestures-rotate.c6
-rw-r--r--src/gestures-tapping.c4
-rw-r--r--src/grail-api.c280
-rw-r--r--src/grail-event.c33
-rw-r--r--src/grail-gestures.c38
-rw-r--r--src/grail-gestures.h16
-rw-r--r--src/grail-impl.h17
-rw-r--r--src/grail-inserter.c31
-rw-r--r--src/grail-inserter.h17
-rw-r--r--src/grail-recognizer.c3
-rw-r--r--src/grail-recognizer.h3
-rw-r--r--src/touch-caps.c117
-rw-r--r--src/touch-dev.c264
-rw-r--r--tools/Makefile.am2
21 files changed, 259 insertions, 688 deletions
diff --git a/INSTALL b/INSTALL
index caaad65..629f0b8 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,7 +1,7 @@
1grail - Gesture Recognition And Instantiation Library 1grail - Gesture Recognition And Instantiation Library
2 2
3To build, you need to have the autoconf, libtool and mtdev-dev packages 3To build, you need to have the autoconf, libtool, mtdev-dev,
4installed. Then, do 4libutouch-evemu-dev and libutouch-frame packages installed. Then, do
5 5
6 ./autogen.sh 6 ./autogen.sh
7 ./configure 7 ./configure
diff --git a/configure.ac b/configure.ac
index 0f75818..ceb9258 100644
--- a/configure.ac
+++ b/configure.ac
@@ -22,7 +22,9 @@ AC_PROG_LIBTOOL
22AC_PROG_CC 22AC_PROG_CC
23AC_PROG_INSTALL 23AC_PROG_INSTALL
24 24
25PKG_CHECK_MODULES([MTDEV], [mtdev >= 1.0]) 25PKG_CHECK_MODULES([MTDEV], [mtdev >= 1.1])
26PKG_CHECK_MODULES([EVEMU], [utouch-evemu >= 1.0])
27PKG_CHECK_MODULES([FRAME], [utouch-frame >= 1.0])
26 28
27AC_CONFIG_FILES([Makefile 29AC_CONFIG_FILES([Makefile
28 src/Makefile 30 src/Makefile
diff --git a/include/grail-touch.h b/include/grail-touch.h
deleted file mode 100644
index 9c63c80..0000000
--- a/include/grail-touch.h
+++ /dev/null
@@ -1,85 +0,0 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010 Canonical Ltd.
6 * Copyright (C) 2010 Henrik Rydberg <rydberg@bitmath.org>
7 *
8 * This program is free software: you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation, either version 3 of the License, or (at your
11 * option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program. If not, see <http://www.gnu.org/licenses/>.
20 *
21 ****************************************************************************/
22
23#ifndef _GRAIL_TOUCH_H
24#define _GRAIL_TOUCH_H
25
26#include <grail-bits.h>
27#include <mtdev.h>
28
29#define DIM_TOUCH 32
30#define DIM_TOUCH_BYTES ((DIM_TOUCH + 7) >> 3)
31
32typedef __u64 touch_time_t;
33
34struct touch {
35 int active;
36 int slot;
37 int id;
38 int tool_type;
39 int x, y;
40 int touch_major;
41 int touch_minor;
42 int width_major;
43 int width_minor;
44 int orientation;
45 int pressure;
46};
47
48struct touch_frame {
49 int nactive;
50 int ncreate, nmodify, ndestroy;
51 touch_time_t time;
52 grail_mask_t touches[DIM_TOUCH_BYTES];
53 struct touch *active[DIM_TOUCH];
54 struct touch touch[DIM_TOUCH];
55};
56
57struct touch_caps {
58 float min_x, max_x;
59 float min_y, max_y;
60 float min_orient, max_orient;
61 float min_press, max_press;
62};
63
64struct touch_dev {
65 void (*event)(struct touch_dev *dev, const struct input_event *ev);
66 void (*sync)(struct touch_dev *dev, const struct input_event *syn);
67 void *priv;
68 struct mtdev mtdev;
69 struct touch_frame frame;
70 struct touch_caps caps;
71 int slot;
72 int state;
73};
74
75int touch_caps_is_supported(struct touch_dev *dev, int fd);
76void touch_caps_init(struct touch_dev *dev);
77float touch_angle(const struct touch_dev *dev, int orientation);
78float touch_pressure(const struct touch_dev *dev, int pressure);
79
80int touch_dev_open(struct touch_dev *dev, int fd);
81int touch_dev_idle(struct touch_dev *dev, int fd, int ms);
82int touch_dev_pull(struct touch_dev *dev, int fd);
83void touch_dev_close(struct touch_dev *dev, int fd);
84
85#endif
diff --git a/src/Makefile.am b/src/Makefile.am
index dd2af2b..bb1c4c5 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -3,14 +3,14 @@ lib_LTLIBRARIES = libutouch-grail.la
3libutouch_grail_la_LDFLAGS = \ 3libutouch_grail_la_LDFLAGS = \
4 -version-info @LIB_VERSION@ \ 4 -version-info @LIB_VERSION@ \
5 -lm \ 5 -lm \
6 $(MTDEV_LIBS) 6 $(MTDEV_LIBS) \
7 $(EVEMU_LIBS) \
8 $(FRAME_LIBS)
7 9
8libutouch_grail_la_SOURCES = \ 10libutouch_grail_la_SOURCES = \
9 evbuf.h \ 11 evbuf.h \
10 gebuf.h \ 12 gebuf.h \
11 grailbuf.h \ 13 grailbuf.h \
12 touch-dev.c \
13 touch-caps.c \
14 grail-bits.c \ 14 grail-bits.c \
15 grail-inserter.c \ 15 grail-inserter.c \
16 grail-inserter.h \ 16 grail-inserter.h \
@@ -34,5 +34,4 @@ libutouch_grailincludedir = $(includedir)
34libutouch_grailinclude_HEADERS = \ 34libutouch_grailinclude_HEADERS = \
35 $(top_srcdir)/include/grail-bits.h \ 35 $(top_srcdir)/include/grail-bits.h \
36 $(top_srcdir)/include/grail-types.h \ 36 $(top_srcdir)/include/grail-types.h \
37 $(top_srcdir)/include/grail-touch.h \
38 $(top_srcdir)/include/grail.h 37 $(top_srcdir)/include/grail.h
diff --git a/src/gebuf.h b/src/gebuf.h
index 460e134..0cd9219 100644
--- a/src/gebuf.h
+++ b/src/gebuf.h
@@ -23,7 +23,7 @@
23#ifndef _GRAIL_GESTURE_BUFFER_H 23#ifndef _GRAIL_GESTURE_BUFFER_H
24#define _GRAIL_GESTURE_BUFFER_H 24#define _GRAIL_GESTURE_BUFFER_H
25 25
26#include <grail.h> 26#include "grail-impl.h"
27 27
28#define DIM_GESTURE_EVENTS 512 28#define DIM_GESTURE_EVENTS 512
29 29
@@ -31,7 +31,7 @@ struct gesture_event {
31 int status; 31 int status;
32 int ntouch; 32 int ntouch;
33 int nprop; 33 int nprop;
34 touch_time_t time; 34 utouch_frame_time_t time;
35 struct grail_coord pos; 35 struct grail_coord pos;
36 grail_prop_t prop[DIM_GRAIL_PROP]; 36 grail_prop_t prop[DIM_GRAIL_PROP];
37}; 37};
diff --git a/src/gestures-drag.c b/src/gestures-drag.c
index 2ced765..05272da 100644
--- a/src/gestures-drag.c
+++ b/src/gestures-drag.c
@@ -35,7 +35,7 @@ static const int getype[DIM_TOUCH + 1] = {
35 35
36static void set_props(const struct gesture_inserter *gin, 36static void set_props(const struct gesture_inserter *gin,
37 struct combo_model *s, const struct move_model *m, 37 struct combo_model *s, const struct move_model *m,
38 const struct touch_frame *frame) 38 const struct utouch_frame *frame)
39{ 39{
40 if (m->single) { 40 if (m->single) {
41 s->prop[GRAIL_PROP_DRAG_DX] = 41 s->prop[GRAIL_PROP_DRAG_DX] =
@@ -59,7 +59,7 @@ static void set_props(const struct gesture_inserter *gin,
59static const int fm_mask = 0x03; 59static const int fm_mask = 0x03;
60 60
61int gru_drag(struct grail *ge, 61int gru_drag(struct grail *ge,
62 const struct touch_frame *frame) 62 const struct utouch_frame *frame)
63{ 63{
64 struct gesture_recognizer *gru = ge->gru; 64 struct gesture_recognizer *gru = ge->gru;
65 struct combo_model *state = &gru->drag; 65 struct combo_model *state = &gru->drag;
@@ -89,7 +89,7 @@ int gru_drag(struct grail *ge,
89} 89}
90 90
91int gru_windrag(struct grail *ge, 91int gru_windrag(struct grail *ge,
92 const struct touch_frame *frame) 92 const struct utouch_frame *frame)
93{ 93{
94 struct gesture_recognizer *gru = ge->gru; 94 struct gesture_recognizer *gru = ge->gru;
95 struct combo_model *state = &gru->windrag; 95 struct combo_model *state = &gru->windrag;
diff --git a/src/gestures-pinch.c b/src/gestures-pinch.c
index 45f1cb3..fa8a626 100644
--- a/src/gestures-pinch.c
+++ b/src/gestures-pinch.c
@@ -38,7 +38,7 @@ static const int fm_mask = 0x04;
38static void set_props(const struct gesture_inserter *gin, 38static void set_props(const struct gesture_inserter *gin,
39 struct combo_model *s, 39 struct combo_model *s,
40 const struct move_model *m, 40 const struct move_model *m,
41 const struct touch_frame *frame) 41 const struct utouch_frame *frame)
42{ 42{
43 s->prop[GRAIL_PROP_PINCH_DR] = gin->scale_r * m->fm[FM_R].action_delta; 43 s->prop[GRAIL_PROP_PINCH_DR] = gin->scale_r * m->fm[FM_R].action_delta;
44 s->prop[GRAIL_PROP_PINCH_VR] = gin->scale_r * m->fm[FM_R].velocity; 44 s->prop[GRAIL_PROP_PINCH_VR] = gin->scale_r * m->fm[FM_R].velocity;
@@ -48,7 +48,7 @@ static void set_props(const struct gesture_inserter *gin,
48} 48}
49 49
50int gru_pinch(struct grail *ge, 50int gru_pinch(struct grail *ge,
51 const struct touch_frame *frame) 51 const struct utouch_frame *frame)
52{ 52{
53 struct gesture_recognizer *gru = ge->gru; 53 struct gesture_recognizer *gru = ge->gru;
54 struct combo_model *state = &gru->pinch; 54 struct combo_model *state = &gru->pinch;
@@ -79,7 +79,7 @@ int gru_pinch(struct grail *ge,
79} 79}
80 80
81int gru_winpinch(struct grail *ge, 81int gru_winpinch(struct grail *ge,
82 const struct touch_frame *frame) 82 const struct utouch_frame *frame)
83{ 83{
84 struct gesture_recognizer *gru = ge->gru; 84 struct gesture_recognizer *gru = ge->gru;
85 struct combo_model *state = &gru->winpinch; 85 struct combo_model *state = &gru->winpinch;
diff --git a/src/gestures-rotate.c b/src/gestures-rotate.c
index 8985257..fde0db8 100644
--- a/src/gestures-rotate.c
+++ b/src/gestures-rotate.c
@@ -37,7 +37,7 @@ static const int fm_mask = 0x08;
37 37
38static void set_props(const struct gesture_inserter *gin, 38static void set_props(const struct gesture_inserter *gin,
39 struct combo_model *s, const struct move_model *m, 39 struct combo_model *s, const struct move_model *m,
40 const struct touch_frame *frame) 40 const struct utouch_frame *frame)
41{ 41{
42 s->prop[GRAIL_PROP_ROTATE_DA] = m->fm[FM_A].action_delta; 42 s->prop[GRAIL_PROP_ROTATE_DA] = m->fm[FM_A].action_delta;
43 s->prop[GRAIL_PROP_ROTATE_VA] = m->fm[FM_A].velocity; 43 s->prop[GRAIL_PROP_ROTATE_VA] = m->fm[FM_A].velocity;
@@ -47,7 +47,7 @@ static void set_props(const struct gesture_inserter *gin,
47} 47}
48 48
49int gru_rotate(struct grail *ge, 49int gru_rotate(struct grail *ge,
50 const struct touch_frame *frame) 50 const struct utouch_frame *frame)
51{ 51{
52 struct gesture_recognizer *gru = ge->gru; 52 struct gesture_recognizer *gru = ge->gru;
53 struct combo_model *state = &gru->rotate; 53 struct combo_model *state = &gru->rotate;
@@ -78,7 +78,7 @@ int gru_rotate(struct grail *ge,
78} 78}
79 79
80int gru_winrotate(struct grail *ge, 80int gru_winrotate(struct grail *ge,
81 const struct touch_frame *frame) 81 const struct utouch_frame *frame)
82{ 82{
83 struct gesture_recognizer *gru = ge->gru; 83 struct gesture_recognizer *gru = ge->gru;
84 struct combo_model *state = &gru->winrotate; 84 struct combo_model *state = &gru->winrotate;
diff --git a/src/gestures-tapping.c b/src/gestures-tapping.c
index aa8e6d6..6d71642 100644
--- a/src/gestures-tapping.c
+++ b/src/gestures-tapping.c
@@ -30,7 +30,7 @@ static const int fm_mask = 0x07;
30 30
31static void set_props(const struct gesture_inserter *gin, 31static void set_props(const struct gesture_inserter *gin,
32 struct tapping_model *s, const struct move_model *m, 32 struct tapping_model *s, const struct move_model *m,
33 const struct touch_frame *frame) 33 const struct utouch_frame *frame)
34{ 34{
35 s->prop[GRAIL_PROP_TAP_DT] = m->time - s->start; 35 s->prop[GRAIL_PROP_TAP_DT] = m->time - s->start;
36 s->prop[GRAIL_PROP_TAP_X] = gin_prop_x(gin, m->fm[FM_X].value); 36 s->prop[GRAIL_PROP_TAP_X] = gin_prop_x(gin, m->fm[FM_X].value);
@@ -40,7 +40,7 @@ static void set_props(const struct gesture_inserter *gin,
40} 40}
41 41
42int gru_tapping(struct grail *ge, 42int gru_tapping(struct grail *ge,
43 const struct touch_frame *frame) 43 const struct utouch_frame *frame)
44{ 44{
45 struct gesture_recognizer *gru = ge->gru; 45 struct gesture_recognizer *gru = ge->gru;
46 struct tapping_model *state = &gru->tapping; 46 struct tapping_model *state = &gru->tapping;
diff --git a/src/grail-api.c b/src/grail-api.c
index f38ca18..3aca75d 100644
--- a/src/grail-api.c
+++ b/src/grail-api.c
@@ -30,27 +30,124 @@
30#include <malloc.h> 30#include <malloc.h>
31#include <errno.h> 31#include <errno.h>
32 32
33static void tp_event(struct touch_dev *dev, 33#define DIM_FRAMES 100
34 const struct input_event *ev) 34#define FRAME_RATE 100
35
36void grail_filter_abs_events(struct grail *ge, int usage)
35{ 37{
36 struct grail *ge = dev->priv;
37 struct grail_impl *x = ge->impl; 38 struct grail_impl *x = ge->impl;
38 if (ev->type == EV_ABS) { 39 x->filter_abs = usage;
39 return; 40}
41
42static void init_impl(struct grail_impl *x)
43{
44 int i;
45
46 if (evemu_has_event(x->evemu, EV_ABS, ABS_X)) {
47 x->emin_x = evemu_get_abs_minimum(x->evemu, ABS_X);
48 x->emin_y = evemu_get_abs_minimum(x->evemu, ABS_Y);
49 x->emax_x = evemu_get_abs_maximum(x->evemu, ABS_X);
50 x->emax_y = evemu_get_abs_maximum(x->evemu, ABS_Y);
51 } else {
52 struct utouch_surface *s = utouch_frame_get_surface(x->fh);
53 x->emin_x = s->min_x;
54 x->emin_y = s->min_y;
55 x->emax_x = s->max_x;
56 x->emax_y = s->max_y;
40 } 57 }
41 if (ev->type == EV_KEY) { 58}
42 switch (ev->code) { 59
43 case BTN_TOUCH: 60int grail_open(struct grail *ge, int fd)
44 case BTN_TOOL_FINGER: 61{
45 case BTN_TOOL_DOUBLETAP: 62 struct grail_impl *x;
46 case BTN_TOOL_TRIPLETAP: 63 int ret;
47 case BTN_TOOL_QUADTAP: 64 x = calloc(1, sizeof(*x));
48 return; 65 if (!x)
49 } 66 return -ENOMEM;
67
68 x->evemu = evemu_new(0);
69 if (!x->evemu) {
70 ret = -ENOMEM;
71 goto freemem;
50 } 72 }
51 evbuf_put(&x->evbuf, ev); 73 ret = evemu_extract(x->evemu, fd);
74 if (ret)
75 goto freemem;
76 if (!utouch_frame_is_supported_mtdev(x->evemu)) {
77 ret = -ENODEV;
78 goto freemem;
79 }
80 x->mtdev = mtdev_new_open(fd);
81 if (!x->mtdev) {
82 ret = -ENOMEM;
83 goto freemem;
84 }
85
86 x->fh = utouch_frame_new_engine(DIM_FRAMES, DIM_TOUCH, FRAME_RATE);
87 if (!x->fh) {
88 ret = -ENOMEM;
89 goto freedev;
90 }
91 ret = utouch_frame_init_mtdev(x->fh, x->evemu);
92 if (ret)
93 goto freeframe;
94
95 init_impl(x);
96 ge->impl = x;
97
98 ret = gin_init(ge);
99 if (ret)
100 goto freeframe;
101
102 ret = gru_init(ge);
103 if (ret)
104 goto freegin;
105
106 return 0;
107 freegin:
108 gin_destroy(ge);
109 freeframe:
110 utouch_frame_delete_engine(x->fh);
111 freedev:
112 mtdev_close_delete(x->mtdev);
113 freemem:
114 evemu_delete(x->evemu);
115 free(x);
116 ge->impl = 0;
117 return ret;
118}
119
120void grail_close(struct grail *ge, int fd)
121{
122 struct grail_impl *x = ge->impl;
123 void *status;
124 gru_destroy(ge);
125 gin_destroy(ge);
126 utouch_frame_delete_engine(x->fh);
127 mtdev_close_delete(x->mtdev);
128 evemu_delete(x->evemu);
129 free(x);
130 ge->impl = 0;
52} 131}
53 132
133int grail_idle(struct grail *ge, int fd, int ms)
134{
135 struct grail_impl *x = ge->impl;
136 return mtdev_idle(x->mtdev, fd, ms);
137}
138
139void grail_get_units(const struct grail *ge,
140 struct grail_coord *min, struct grail_coord *max)
141{
142 struct utouch_surface *s = utouch_frame_get_surface(ge->impl->fh);
143 min->x = s->min_x;
144 min->y = s->min_y;
145 max->x = s->max_x;
146 max->y = s->max_y;
147}
148
149// legacy glue below
150
54static void evput(struct grail_impl *x, struct timeval time, 151static void evput(struct grail_impl *x, struct timeval time,
55 unsigned type, unsigned code, int value) 152 unsigned type, unsigned code, int value)
56{ 153{
@@ -76,47 +173,19 @@ static void report_up(struct grail_impl *impl, const struct input_event *syn)
76 impl->report_status = 0; 173 impl->report_status = 0;
77} 174}
78 175
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) 176static void set_pointer(struct grail_impl *impl)
106{ 177{
107 struct touch_dev *dev = &impl->dev; 178 struct utouch_surface *s = utouch_frame_get_surface(impl->fh);
108 struct touch_caps *caps = &dev->caps; 179 const struct utouch_frame *frame = impl->frame;
109 struct touch_caps *emu = &impl->emu;
110 struct touch_frame *frame = &dev->frame;
111 int best_x, best_y, best_d = -1; 180 int best_x, best_y, best_d = -1;
112 int i; 181 int i;
113 182
114 for (i = 0; i < frame->nactive; i++) { 183 for (i = 0; i < frame->num_active; i++) {
115 struct touch *t = frame->active[i]; 184 const struct utouch_contact *t = frame->active[i];
116 float u = (t->x - caps->min_x) / (caps->max_x - caps->min_x); 185 float u = (t->x - s->min_x) / (s->max_x - s->min_x);
117 float v = (t->y - caps->min_y) / (caps->max_y - caps->min_y); 186 float v = (t->y - s->min_y) / (s->max_y - s->min_y);
118 int x = emu->min_x + u * (emu->max_x - emu->min_x); 187 int x = impl->emin_x + u * (impl->emax_x - impl->emin_x);
119 int y = emu->min_y + v * (emu->max_y - emu->min_y); 188 int y = impl->emin_y + v * (impl->emax_y - impl->emin_y);
120 int d = abs(x - impl->pointer_x) + abs(y - impl->pointer_y); 189 int d = abs(x - impl->pointer_x) + abs(y - impl->pointer_y);
121 if (best_d < 0 || d < best_d) { 190 if (best_d < 0 || d < best_d) {
122 best_x = x; 191 best_x = x;
@@ -181,15 +250,18 @@ static void handle_abs_events(struct grail *ge, const struct input_event *syn)
181 } 250 }
182} 251}
183 252
184static void tp_sync(struct touch_dev *dev, 253static void report_frame(struct grail *ge,
185 const struct input_event *syn) 254 const struct utouch_frame *frame,
255 const struct input_event *syn)
186{ 256{
187 struct grail *ge = dev->priv; 257
188 struct grail_impl *impl = ge->impl; 258 struct grail_impl *impl = ge->impl;
189 int head = impl->evbuf.head; 259 int head = impl->evbuf.head;
190 struct input_event iev; 260 struct input_event iev;
191 struct grail_event gev; 261 struct grail_event gev;
192 struct touch_frame *frame = &dev->frame; 262
263 ge->impl->frame = frame;
264
193 gin_frame_begin(ge, frame); 265 gin_frame_begin(ge, frame);
194 gru_recognize(ge, frame); 266 gru_recognize(ge, frame);
195 gin_frame_end(ge, frame); 267 gin_frame_end(ge, frame);
@@ -211,78 +283,42 @@ static void tp_sync(struct touch_dev *dev,
211 } 283 }
212} 284}
213 285
214void grail_filter_abs_events(struct grail *ge, int usage) 286static void grail_pump_mtdev(struct grail *ge, const struct input_event *ev)
215{
216 struct grail_impl *x = ge->impl;
217 x->filter_abs = usage;
218}
219
220int grail_open(struct grail *ge, int fd)
221{
222 struct grail_impl *x;
223 int ret;
224 x = calloc(1, sizeof(*x));
225 if (!x)
226 return -ENOMEM;
227 ge->impl = x;
228
229 ret = touch_dev_open(&x->dev, fd);
230 if (ret)
231 goto freemem;
232 set_emulation_caps(x, fd);
233 x->dev.event = tp_event;
234 x->dev.sync = tp_sync;
235 x->dev.priv = ge;
236
237 ret = gin_init(ge);
238 if (ret)
239 goto freedev;
240
241 ret = gru_init(ge);
242 if (ret)
243 goto freegin;
244
245 return 0;
246 freegin:
247 gin_destroy(ge);
248 freedev:
249 touch_dev_close(&x->dev, fd);
250 freemem:
251 free(x);
252 ge->impl = 0;
253 return ret;
254}
255
256void grail_close(struct grail *ge, int fd)
257{ 287{
258 struct grail_impl *x = ge->impl; 288 struct grail_impl *impl = ge->impl;
259 void *status; 289 const struct utouch_frame *frame;
260 gru_destroy(ge);
261 gin_destroy(ge);
262 touch_dev_close(&x->dev, fd);
263 free(ge->impl);
264 ge->impl = 0;
265}
266 290
267int grail_idle(struct grail *ge, int fd, int ms) 291 if (ev->type == EV_SYN || ev->type == EV_ABS) {
268{ 292 frame = utouch_frame_pump_mtdev(impl->fh, ev);
269 struct grail_impl *x = ge->impl; 293 if (frame)
270 return touch_dev_idle(&x->dev, fd, ms); 294 report_frame(ge, frame, ev);
295 } else if (ev->type == EV_KEY) {
296 switch (ev->code) {
297 case BTN_TOUCH:
298 case BTN_TOOL_FINGER:
299 case BTN_TOOL_DOUBLETAP:
300 case BTN_TOOL_TRIPLETAP:
301 case BTN_TOOL_QUADTAP:
302 break;
303 default:
304 evbuf_put(&impl->evbuf, ev);
305 break;
306 }
307 } else {
308 evbuf_put(&impl->evbuf, ev);
309 }
271} 310}
272 311
273int grail_pull(struct grail *ge, int fd) 312int grail_pull(struct grail *ge, int fd)
274{ 313{
275 struct grail_impl *x = ge->impl; 314 struct grail_impl *impl = ge->impl;
276 return touch_dev_pull(&x->dev, fd); 315 struct input_event ev;
277} 316 int ret, count = 0;
278 317
279void grail_get_units(const struct grail *ge, 318 while ((ret = mtdev_get(impl->mtdev, fd, &ev, 1)) > 0) {
280 struct grail_coord *min, struct grail_coord *max) 319 grail_pump_mtdev(ge, &ev);
281{ 320 count++;
282 const struct touch_caps *caps = &ge->impl->dev.caps; 321 }
283 min->x = caps->min_x;
284 min->y = caps->min_y;
285 max->x = caps->max_x;
286 max->y = caps->max_y;
287}
288 322
323 return count > 0 ? count : ret;
324}
diff --git a/src/grail-event.c b/src/grail-event.c
index 23fdbb3..9c0e437 100644
--- a/src/grail-event.c
+++ b/src/grail-event.c
@@ -28,17 +28,17 @@
28#include <math.h> 28#include <math.h>
29 29
30static void compute_bbox(struct grail_coord *min, struct grail_coord *max, 30static void compute_bbox(struct grail_coord *min, struct grail_coord *max,
31 const struct touch_frame *frame) 31 const struct utouch_frame *frame)
32{ 32{
33 float x, y; 33 float x, y;
34 int i; 34 int i;
35 if (frame->nactive < 1) 35 if (frame->num_active < 1)
36 return; 36 return;
37 x = frame->active[0]->x; 37 x = frame->active[0]->x;
38 y = frame->active[0]->y; 38 y = frame->active[0]->y;
39 min->x = max->x = x; 39 min->x = max->x = x;
40 min->y = max->y = y; 40 min->y = max->y = y;
41 for (i = 1; i < frame->nactive; i++) { 41 for (i = 1; i < frame->num_active; i++) {
42 x = frame->active[i]->x; 42 x = frame->active[i]->x;
43 y = frame->active[i]->y; 43 y = frame->active[i]->y;
44 if (x < min->x) 44 if (x < min->x)
@@ -53,10 +53,10 @@ static void compute_bbox(struct grail_coord *min, struct grail_coord *max,
53} 53}
54 54
55int gin_add_contact_props(const struct gesture_inserter *gin, 55int gin_add_contact_props(const struct gesture_inserter *gin,
56 grail_prop_t *prop, const struct touch_frame *frame) 56 grail_prop_t *prop, const struct utouch_frame *frame)
57{ 57{
58 struct grail_coord min, max; 58 struct grail_coord min, max;
59 int i, n = 0, ntouch = frame->nactive; 59 int i, n = 0, ntouch = frame->num_active;
60 if (!ntouch) 60 if (!ntouch)
61 return n; 61 return n;
62 if (ntouch > 5) 62 if (ntouch > 5)
@@ -67,7 +67,7 @@ int gin_add_contact_props(const struct gesture_inserter *gin,
67 prop[n++] = gin_prop_x(gin, max.x); 67 prop[n++] = gin_prop_x(gin, max.x);
68 prop[n++] = gin_prop_y(gin, max.y); 68 prop[n++] = gin_prop_y(gin, max.y);
69 for (i = 0; i < ntouch; i++) { 69 for (i = 0; i < ntouch; i++) {
70 const struct touch *ct = frame->active[i]; 70 const struct utouch_contact *ct = frame->active[i];
71 prop[n++] = ct->id; 71 prop[n++] = ct->id;
72 prop[n++] = gin_prop_x(gin, ct->x); 72 prop[n++] = gin_prop_x(gin, ct->x);
73 prop[n++] = gin_prop_y(gin, ct->y); 73 prop[n++] = gin_prop_y(gin, ct->y);
@@ -79,15 +79,15 @@ int gin_get_clients(struct grail *ge,
79 struct grail_client_info *info, int maxinfo, 79 struct grail_client_info *info, int maxinfo,
80 const grail_mask_t* types, int btypes, 80 const grail_mask_t* types, int btypes,
81 const grail_mask_t* span, int bspan, 81 const grail_mask_t* span, int bspan,
82 const struct touch_frame *frame) 82 const struct utouch_frame *frame)
83{ 83{
84 struct grail_coord pos[DIM_TOUCH]; 84 struct grail_coord pos[DIM_TOUCH];
85 int i, npos = 0; 85 int i, npos = 0;
86 if (!ge->get_clients) 86 if (!ge->get_clients)
87 return 0; 87 return 0;
88 grail_mask_foreach(i, span, bspan) { 88 grail_mask_foreach(i, span, bspan) {
89 pos[npos].x = gin_prop_x(ge->gin, frame->touch[i].x); 89 pos[npos].x = gin_prop_x(ge->gin, frame->slots[i]->x);
90 pos[npos].y = gin_prop_y(ge->gin, frame->touch[i].y); 90 pos[npos].y = gin_prop_y(ge->gin, frame->slots[i]->y);
91 npos++; 91 npos++;
92 } 92 }
93 return ge->get_clients(ge, info, maxinfo, pos, npos, types, btypes); 93 return ge->get_clients(ge, info, maxinfo, pos, npos, types, btypes);
@@ -95,7 +95,7 @@ int gin_get_clients(struct grail *ge,
95 95
96void gin_send_event(struct grail *ge, struct slot_state *s, 96void gin_send_event(struct grail *ge, struct slot_state *s,
97 const struct gesture_event *ev, 97 const struct gesture_event *ev,
98 const struct touch_frame *frame) 98 const struct utouch_frame *frame)
99{ 99{
100 struct grail_impl *impl = ge->impl; 100 struct grail_impl *impl = ge->impl;
101 const struct gesture_inserter *gin = ge->gin; 101 const struct gesture_inserter *gin = ge->gin;
@@ -121,15 +121,14 @@ void gin_send_event(struct grail *ge, struct slot_state *s,
121int grail_get_contacts(const struct grail *ge, 121int grail_get_contacts(const struct grail *ge,
122 struct grail_contact *touch, int max_touch) 122 struct grail_contact *touch, int max_touch)
123{ 123{
124 const struct touch_dev *dev = &ge->impl->dev;
125 const struct gesture_inserter *gin = ge->gin; 124 const struct gesture_inserter *gin = ge->gin;
126 const struct touch_frame *frame = &dev->frame; 125 const struct utouch_frame *frame = ge->impl->frame;
127 int i; 126 int i;
128 if (frame->nactive < max_touch) 127 if (frame->num_active < max_touch)
129 max_touch = frame->nactive; 128 max_touch = frame->num_active;
130 for (i = 0; i < max_touch; i++) { 129 for (i = 0; i < max_touch; i++) {
131 struct grail_contact *t = &touch[i]; 130 struct grail_contact *t = &touch[i];
132 const struct touch *ct = frame->active[i]; 131 const struct utouch_contact *ct = frame->active[i];
133 t->id = ct->id; 132 t->id = ct->id;
134 t->tool_type = ct->tool_type; 133 t->tool_type = ct->tool_type;
135 t->pos.x = gin_prop_x(gin, ct->x); 134 t->pos.x = gin_prop_x(gin, ct->x);
@@ -138,8 +137,8 @@ int grail_get_contacts(const struct grail *ge,
138 t->touch_minor = gin->scale_r * ct->touch_minor; 137 t->touch_minor = gin->scale_r * ct->touch_minor;
139 t->width_major = gin->scale_r * ct->width_major; 138 t->width_major = gin->scale_r * ct->width_major;
140 t->width_minor = gin->scale_r * ct->width_minor; 139 t->width_minor = gin->scale_r * ct->width_minor;
141 t->angle = touch_angle(dev, ct->orientation); 140 t->angle = ct->orientation;
142 t->pressure = touch_pressure(dev, ct->pressure); 141 t->pressure = ct->pressure;
143 } 142 }
144 return max_touch; 143 return max_touch;
145} 144}
diff --git a/src/grail-gestures.c b/src/grail-gestures.c
index ed937a4..035a199 100644
--- a/src/grail-gestures.c
+++ b/src/grail-gestures.c
@@ -31,15 +31,15 @@ static const grail_time_t SAMPLE_MS = 10;
31static const float EPS = 1e-3; 31static const float EPS = 1e-3;
32 32
33static void compute_position(float *x, float *y, 33static void compute_position(float *x, float *y,
34 const struct touch_frame *frame) 34 const struct utouch_frame *frame)
35{ 35{
36 int i, n = frame->nactive; 36 int i, n = frame->num_active;
37 *x = 0; 37 *x = 0;
38 *y = 0; 38 *y = 0;
39 if (n < 1) 39 if (n < 1)
40 return; 40 return;
41 for (i = 0; i < n; i++) { 41 for (i = 0; i < n; i++) {
42 const struct touch *t = frame->active[i]; 42 const struct utouch_contact *t = frame->active[i];
43 *x += t->x; 43 *x += t->x;
44 *y += t->y; 44 *y += t->y;
45 } 45 }
@@ -48,14 +48,14 @@ static void compute_position(float *x, float *y,
48} 48}
49 49
50static float compute_radius(float x, float y, 50static float compute_radius(float x, float y,
51 const struct touch_frame *frame) 51 const struct utouch_frame *frame)
52{ 52{
53 int i, n = frame->nactive; 53 int i, n = frame->num_active;
54 float r = 0, r2 = 0; 54 float r = 0, r2 = 0;
55 if (n < 2) 55 if (n < 2)
56 return r; 56 return r;
57 for (i = 0; i < n; i++) { 57 for (i = 0; i < n; i++) {
58 const struct touch *t = frame->active[i]; 58 const struct utouch_contact *t = frame->active[i];
59 float dx = t->x - x; 59 float dx = t->x - x;
60 float dy = t->y - y; 60 float dy = t->y - y;
61 r2 += dx * dx + dy * dy; 61 r2 += dx * dx + dy * dy;
@@ -66,16 +66,15 @@ static float compute_radius(float x, float y,
66} 66}
67 67
68static float compute_rotation(float x, float y, float r, 68static float compute_rotation(float x, float y, float r,
69 const struct touch_frame *prev, 69 const struct utouch_frame *frame)
70 const struct touch_frame *frame)
71{ 70{
72 int i, n = frame->nactive; 71 int i, n = frame->num_active;
73 float da = 0, darc2 = 0; 72 float da = 0, darc2 = 0;
74 if (n < 2) 73 if (n < 2)
75 return da; 74 return da;
76 for (i = 0; i < n; i++) { 75 for (i = 0; i < n; i++) {
77 const struct touch *t = frame->active[i]; 76 const struct utouch_contact *t = frame->active[i];
78 const struct touch *ot = &prev->touch[t->slot]; 77 const struct utouch_contact *ot = t->prev;
79 float dx = t->x - x; 78 float dx = t->x - x;
80 float dy = t->y - y; 79 float dy = t->y - y;
81 float mx = t->x - ot->x; 80 float mx = t->x - ot->x;
@@ -142,13 +141,13 @@ static void move_update(struct move_model *m, int i, float x, grail_time_t t)
142 141
143void gru_init_motion(struct grail *ge) 142void gru_init_motion(struct grail *ge)
144{ 143{
145 struct touch_caps *caps = &ge->impl->dev.caps; 144 struct utouch_surface *s = utouch_frame_get_surface(ge->impl->fh);
146 struct gesture_recognizer *gru = ge->gru; 145 struct gesture_recognizer *gru = ge->gru;
147 struct move_model *m = &gru->move; 146 struct move_model *m = &gru->move;
148 float D[DIM_FM]; 147 float D[DIM_FM];
149 int i; 148 int i;
150 D[FM_X] = caps->max_x - caps->min_x; 149 D[FM_X] = s->max_x - s->min_x;
151 D[FM_Y] = caps->max_y - caps->min_y; 150 D[FM_Y] = s->max_y - s->min_y;
152 D[FM_R] = sqrt(D[FM_X] * D[FM_X] + D[FM_Y] * D[FM_Y]); 151 D[FM_R] = sqrt(D[FM_X] * D[FM_X] + D[FM_Y] * D[FM_Y]);
153 D[FM_A] = 2 * M_PI; 152 D[FM_A] = 2 * M_PI;
154 for (i = 0; i < DIM_FM; i++) { 153 for (i = 0; i < DIM_FM; i++) {
@@ -159,14 +158,15 @@ void gru_init_motion(struct grail *ge)
159} 158}
160 159
161void gru_motion(struct grail *ge, 160void gru_motion(struct grail *ge,
162 const struct touch_frame *frame) 161 const struct utouch_frame *frame)
163{ 162{
164 struct gesture_recognizer *gru = ge->gru; 163 struct gesture_recognizer *gru = ge->gru;
165 struct move_model *m = &gru->move; 164 struct move_model *m = &gru->move;
166 grail_time_t t = frame->time; 165 grail_time_t t = frame->time;
167 float x, y, r, a; 166 float x, y, r, a;
167
168 compute_position(&x, &y, frame); 168 compute_position(&x, &y, frame);
169 if (frame->ncreate || frame->ndestroy) { 169 if (frame->prev->revision != frame->revision) {
170 r = compute_radius(x, y, frame); 170 r = compute_radius(x, y, frame);
171 a = 0; 171 a = 0;
172 move_reset(m, FM_X, x, t); 172 move_reset(m, FM_X, x, t);
@@ -175,7 +175,7 @@ void gru_motion(struct grail *ge,
175 move_reset(m, FM_A, a, t); 175 move_reset(m, FM_A, a, t);
176 m->single = 0; 176 m->single = 0;
177 m->multi = 0; 177 m->multi = 0;
178 } else if (frame->nactive < 2) { 178 } else if (frame->num_active < 2) {
179 r = 0; 179 r = 0;
180 a = 0; 180 a = 0;
181 move_update(m, FM_X, x, t); 181 move_update(m, FM_X, x, t);
@@ -190,7 +190,7 @@ void gru_motion(struct grail *ge,
190 r = compute_radius(x, y, frame); 190 r = compute_radius(x, y, frame);
191 r = move_filter(&m->fm[FM_R], r); 191 r = move_filter(&m->fm[FM_R], r);
192 a = m->fm[FM_A].value; 192 a = m->fm[FM_A].value;
193 a += compute_rotation(x, y, r, &gru->frame, frame); 193 a += compute_rotation(x, y, r, frame);
194 a = move_filter(&m->fm[FM_A], a); 194 a = move_filter(&m->fm[FM_A], a);
195 move_update(m, FM_X, x, t); 195 move_update(m, FM_X, x, t);
196 move_update(m, FM_Y, y, t); 196 move_update(m, FM_Y, y, t);
@@ -199,7 +199,7 @@ void gru_motion(struct grail *ge,
199 m->single = 0; 199 m->single = 0;
200 m->multi = 1; 200 m->multi = 1;
201 } 201 }
202 m->ntouch = frame->nactive; 202 m->ntouch = frame->num_active;
203 m->time = t; 203 m->time = t;
204} 204}
205 205
diff --git a/src/grail-gestures.h b/src/grail-gestures.h
index 27108e9..69dd7e4 100644
--- a/src/grail-gestures.h
+++ b/src/grail-gestures.h
@@ -61,7 +61,7 @@ struct move_model {
61 61
62void gru_init_motion(struct grail *ge); 62void gru_init_motion(struct grail *ge);
63void gru_motion(struct grail *ge, 63void gru_motion(struct grail *ge,
64 const struct touch_frame *frame); 64 const struct utouch_frame *frame);
65void gru_event(struct grail *ge, int gid, 65void gru_event(struct grail *ge, int gid,
66 const struct move_model *move, 66 const struct move_model *move,
67 const grail_prop_t *prop, int nprop); 67 const grail_prop_t *prop, int nprop);
@@ -77,11 +77,11 @@ struct combo_model {
77}; 77};
78 78
79int gru_drag(struct grail *ge, 79int gru_drag(struct grail *ge,
80 const struct touch_frame *frame); 80 const struct utouch_frame *frame);
81int gru_pinch(struct grail *ge, 81int gru_pinch(struct grail *ge,
82 const struct touch_frame *frame); 82 const struct utouch_frame *frame);
83int gru_rotate(struct grail *ge, 83int gru_rotate(struct grail *ge,
84 const struct touch_frame *frame); 84 const struct utouch_frame *frame);
85 85
86static inline int out_of_bounds(const struct combo_model *s, 86static inline int out_of_bounds(const struct combo_model *s,
87 const struct move_model *m) 87 const struct move_model *m)
@@ -90,11 +90,11 @@ static inline int out_of_bounds(const struct combo_model *s,
90} 90}
91 91
92int gru_windrag(struct grail *ge, 92int gru_windrag(struct grail *ge,
93 const struct touch_frame *frame); 93 const struct utouch_frame *frame);
94int gru_winpinch(struct grail *ge, 94int gru_winpinch(struct grail *ge,
95 const struct touch_frame *frame); 95 const struct utouch_frame *frame);
96int gru_winrotate(struct grail *ge, 96int gru_winrotate(struct grail *ge,
97 const struct touch_frame *frame); 97 const struct utouch_frame *frame);
98 98
99struct tapping_model { 99struct tapping_model {
100 grail_time_t start, end; 100 grail_time_t start, end;
@@ -105,7 +105,7 @@ struct tapping_model {
105}; 105};
106 106
107int gru_tapping(struct grail *ge, 107int gru_tapping(struct grail *ge,
108 const struct touch_frame *frame); 108 const struct utouch_frame *frame);
109 109
110#endif 110#endif
111 111
diff --git a/src/grail-impl.h b/src/grail-impl.h
index 2859186..dcbaedd 100644
--- a/src/grail-impl.h
+++ b/src/grail-impl.h
@@ -23,15 +23,26 @@
23#ifndef _GRAIL_IMPL_H 23#ifndef _GRAIL_IMPL_H
24#define _GRAIL_IMPL_H 24#define _GRAIL_IMPL_H
25 25
26#include <grail-touch.h> 26#define MTDEV_NO_LEGACY_API
27#define GRAIL_NO_LEGACY_API
28
29#include <grail.h>
30#include <utouch/frame-mtdev.h>
27#include "evbuf.h" 31#include "evbuf.h"
28#include "grailbuf.h" 32#include "grailbuf.h"
29 33
34#define DIM_TOUCH 32
35#define DIM_TOUCH_BYTES ((DIM_TOUCH + 7) >> 3)
36
30struct grail_impl { 37struct grail_impl {
31 struct touch_dev dev; 38 struct evemu_device *evemu;
32 struct touch_caps emu; 39 struct mtdev *mtdev;
40 utouch_frame_handle fh;
41 const struct utouch_frame *frame;
33 struct evbuf evbuf; 42 struct evbuf evbuf;
34 struct grailbuf gbuf; 43 struct grailbuf gbuf;
44 float emin_x, emin_y;
45 float emax_x, emax_y;
35 int filter_abs; 46 int filter_abs;
36 int pointer_status; 47 int pointer_status;
37 int pointer_x, pointer_y; 48 int pointer_x, pointer_y;
diff --git a/src/grail-inserter.c b/src/grail-inserter.c
index 847995a..6f9a034 100644
--- a/src/grail-inserter.c
+++ b/src/grail-inserter.c
@@ -40,7 +40,7 @@ static int find_gslot(const struct gesture_inserter *gin, int gid)
40 40
41// todo: spanning tree for multi-user case 41// todo: spanning tree for multi-user case
42static void setup_new_gestures(struct grail *ge, 42static void setup_new_gestures(struct grail *ge,
43 const struct touch_frame *frame) 43 const struct utouch_frame *frame)
44{ 44{
45 struct gesture_inserter *gin = ge->gin; 45 struct gesture_inserter *gin = ge->gin;
46 grail_mask_t types[DIM_GRAIL_TYPE_BYTES]; 46 grail_mask_t types[DIM_GRAIL_TYPE_BYTES];
@@ -100,14 +100,14 @@ void gin_destroy(struct grail *ge)
100 ge->gin = NULL; 100 ge->gin = NULL;
101} 101}
102 102
103void gin_frame_begin(struct grail *ge, const struct touch_frame *frame) 103void gin_frame_begin(struct grail *ge, const struct utouch_frame *frame)
104{ 104{
105 struct gesture_inserter *gin = ge->gin; 105 struct gesture_inserter *gin = ge->gin;
106 memset(gin->types, 0, sizeof(gin->types)); 106 memset(gin->types, 0, sizeof(gin->types));
107 gin->time = frame->time; 107 gin->time = frame->time;
108} 108}
109 109
110void gin_frame_end(struct grail *ge, const struct touch_frame *frame) 110void gin_frame_end(struct grail *ge, const struct utouch_frame *frame)
111{ 111{
112 struct gesture_inserter *gin = ge->gin; 112 struct gesture_inserter *gin = ge->gin;
113 int i, hold = 0, discard = 0; 113 int i, hold = 0, discard = 0;
@@ -151,11 +151,12 @@ void gin_frame_end(struct grail *ge, const struct touch_frame *frame)
151 } 151 }
152} 152}
153 153
154int gin_gid_begin_select(struct grail *ge, int type, int priority, 154int gin_gid_begin(struct grail *ge, int type, int priority,
155 const grail_mask_t *span, int nspan) 155 const struct utouch_frame *frame)
156{ 156{
157 struct gesture_inserter *gin = ge->gin; 157 struct gesture_inserter *gin = ge->gin;
158 struct slot_state *s; 158 struct slot_state *s;
159 int slot;
159 int i = grail_mask_get_first(gin->unused, sizeof(gin->unused)); 160 int i = grail_mask_get_first(gin->unused, sizeof(gin->unused));
160 if (i < 0) 161 if (i < 0)
161 return -1; 162 return -1;
@@ -165,7 +166,8 @@ int gin_gid_begin_select(struct grail *ge, int type, int priority,
165 s->id = gin->gestureid++ & MAX_GESTURE_ID; 166 s->id = gin->gestureid++ & MAX_GESTURE_ID;
166 s->status = GRAIL_STATUS_BEGIN; 167 s->status = GRAIL_STATUS_BEGIN;
167 s->nclient = 0; 168 s->nclient = 0;
168 memcpy(s->span, span, nspan); 169 for (slot = 0; slot < DIM_TOUCH; slot++)
170 grail_mask_modify(s->span, slot, frame->slots[slot]->active);
169 gebuf_clear(&s->buf); 171 gebuf_clear(&s->buf);
170 grail_mask_clear(gin->unused, i); 172 grail_mask_clear(gin->unused, i);
171 grail_mask_set(gin->fresh, i); 173 grail_mask_set(gin->fresh, i);
@@ -173,13 +175,6 @@ int gin_gid_begin_select(struct grail *ge, int type, int priority,
173 return s->id; 175 return s->id;
174} 176}
175 177
176int gin_gid_begin(struct grail *ge, int type, int priority,
177 const struct touch_frame *frame)
178{
179 return gin_gid_begin_select(ge, type, priority,
180 frame->touches, sizeof(frame->touches));
181}
182
183void gin_gid_discard(struct grail *ge, int gid) 178void gin_gid_discard(struct grail *ge, int gid)
184{ 179{
185 struct gesture_inserter *gin = ge->gin; 180 struct gesture_inserter *gin = ge->gin;
@@ -248,18 +243,18 @@ void grail_set_bbox(struct grail *ge,
248 const struct grail_coord *tmin, 243 const struct grail_coord *tmin,
249 const struct grail_coord *tmax) 244 const struct grail_coord *tmax)
250{ 245{
251 struct touch_caps *caps = &ge->impl->dev.caps; 246 struct utouch_surface *s = utouch_frame_get_surface(ge->impl->fh);
252 struct gesture_inserter *gin = ge->gin; 247 struct gesture_inserter *gin = ge->gin;
253 double tx, ty, dx, dy, sx, sy; 248 double tx, ty, dx, dy, sx, sy;
254 tx = tmax->x - tmin->x; 249 tx = tmax->x - tmin->x;
255 ty = tmax->y - tmin->y; 250 ty = tmax->y - tmin->y;
256 dx = caps->max_x - caps->min_x; 251 dx = s->max_x - s->min_x;
257 dy = caps->max_y - caps->min_y; 252 dy = s->max_y - s->min_y;
258 sx = tx / dx; 253 sx = tx / dx;
259 sy = ty / dy; 254 sy = ty / dy;
260 gin->scale_x = sx; 255 gin->scale_x = sx;
261 gin->scale_y = sy; 256 gin->scale_y = sy;
262 gin->scale_r = sqrt((tx * tx + ty * ty) / (dx * dx + dy * dy)); 257 gin->scale_r = sqrt((tx * tx + ty * ty) / (dx * dx + dy * dy));
263 gin->trans_x = tmin->x - caps->min_x * sx; 258 gin->trans_x = tmin->x - s->min_x * sx;
264 gin->trans_y = tmin->y - caps->min_y * sy; 259 gin->trans_y = tmin->y - s->min_y * sy;
265} 260}
diff --git a/src/grail-inserter.h b/src/grail-inserter.h
index 9baecb7..3b8cd77 100644
--- a/src/grail-inserter.h
+++ b/src/grail-inserter.h
@@ -23,8 +23,7 @@
23#ifndef _GRAIL_INSERTER_H 23#ifndef _GRAIL_INSERTER_H
24#define _GRAIL_INSERTER_H 24#define _GRAIL_INSERTER_H
25 25
26#include <grail-touch.h> 26#include "grail-impl.h"
27#include <grail.h>
28#include "gebuf.h" 27#include "gebuf.h"
29 28
30#define DIM_EV_TYPE EV_CNT 29#define DIM_EV_TYPE EV_CNT
@@ -69,27 +68,25 @@ static inline float gin_prop_y(const struct gesture_inserter *gin, float y)
69} 68}
70 69
71int gin_add_contact_props(const struct gesture_inserter *gin, 70int gin_add_contact_props(const struct gesture_inserter *gin,
72 grail_prop_t *prop, const struct touch_frame *frame); 71 grail_prop_t *prop, const struct utouch_frame *frame);
73 72
74int gin_get_clients(struct grail *ge, 73int gin_get_clients(struct grail *ge,
75 struct grail_client_info *info, int maxinfo, 74 struct grail_client_info *info, int maxinfo,
76 const grail_mask_t* types, int btypes, 75 const grail_mask_t* types, int btypes,
77 const grail_mask_t* span, int bspan, 76 const grail_mask_t* span, int bspan,
78 const struct touch_frame *frame); 77 const struct utouch_frame *frame);
79void gin_send_event(struct grail *ge, struct slot_state *s, 78void gin_send_event(struct grail *ge, struct slot_state *s,
80 const struct gesture_event *ev, 79 const struct gesture_event *ev,
81 const struct touch_frame *frame); 80 const struct utouch_frame *frame);
82 81
83int gin_init(struct grail *ge); 82int gin_init(struct grail *ge);
84void gin_destroy(struct grail *ge); 83void gin_destroy(struct grail *ge);
85 84
86void gin_frame_begin(struct grail *ge, const struct touch_frame *frame); 85void gin_frame_begin(struct grail *ge, const struct utouch_frame *frame);
87void gin_frame_end(struct grail *ge, const struct touch_frame *frame); 86void gin_frame_end(struct grail *ge, const struct utouch_frame *frame);
88 87
89int gin_gid_begin_select(struct grail *ge, int type, int priority,
90 const grail_mask_t *span, int nspan);
91int gin_gid_begin(struct grail *ge, int type, int priority, 88int gin_gid_begin(struct grail *ge, int type, int priority,
92 const struct touch_frame *frame); 89 const struct utouch_frame *frame);
93void gin_gid_discard(struct grail *ge, int gid); 90void gin_gid_discard(struct grail *ge, int gid);
94 91
95void gin_gid_event(struct grail *ge, int gid, 92void gin_gid_event(struct grail *ge, int gid,
diff --git a/src/grail-recognizer.c b/src/grail-recognizer.c
index 932f28a..fb0ae85 100644
--- a/src/grail-recognizer.c
+++ b/src/grail-recognizer.c
@@ -42,7 +42,7 @@ void gru_destroy(struct grail *ge)
42 ge->gru = NULL; 42 ge->gru = NULL;
43} 43}
44 44
45void gru_recognize(struct grail *ge, const struct touch_frame *frame) 45void gru_recognize(struct grail *ge, const struct utouch_frame *frame)
46{ 46{
47 if (!ge->gin || !ge->gru) 47 if (!ge->gin || !ge->gru)
48 return; 48 return;
@@ -54,5 +54,4 @@ void gru_recognize(struct grail *ge, const struct touch_frame *frame)
54 gru_winpinch(ge, frame); 54 gru_winpinch(ge, frame);
55 gru_winrotate(ge, frame); 55 gru_winrotate(ge, frame);
56 gru_tapping(ge, frame); 56 gru_tapping(ge, frame);
57 ge->gru->frame = *frame;
58} 57}
diff --git a/src/grail-recognizer.h b/src/grail-recognizer.h
index 1a9edd1..56e5b8d 100644
--- a/src/grail-recognizer.h
+++ b/src/grail-recognizer.h
@@ -26,7 +26,6 @@
26#include "grail-gestures.h" 26#include "grail-gestures.h"
27 27
28struct gesture_recognizer { 28struct gesture_recognizer {
29 struct touch_frame frame;
30 struct move_model move; 29 struct move_model move;
31 struct combo_model drag; 30 struct combo_model drag;
32 struct combo_model pinch; 31 struct combo_model pinch;
@@ -38,7 +37,7 @@ struct gesture_recognizer {
38}; 37};
39 38
40int gru_init(struct grail *ge); 39int gru_init(struct grail *ge);
41void gru_recognize(struct grail *ge, const struct touch_frame *frame); 40void gru_recognize(struct grail *ge, const struct utouch_frame *frame);
42void gru_destroy(struct grail *ge); 41void gru_destroy(struct grail *ge);
43 42
44#endif 43#endif
diff --git a/src/touch-caps.c b/src/touch-caps.c
deleted file mode 100644
index f99b0d7..0000000
--- a/src/touch-caps.c
+++ /dev/null
@@ -1,117 +0,0 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010 Canonical Ltd.
6 * Copyright (C) 2010 Henrik Rydberg <rydberg@bitmath.org>
7 *
8 * This program is free software: you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation, either version 3 of the License, or (at your
11 * option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program. If not, see <http://www.gnu.org/licenses/>.
20 *
21 ****************************************************************************/
22
23#include <grail-touch.h>
24#include <errno.h>
25#include <math.h>
26
27/* see mtdev-mapping.h */
28#define MTDEV_POSITION_X 5
29#define MTDEV_POSITION_Y 6
30#define MTDEV_ORIENTATION 4
31#define MTDEV_PRESSURE 10
32
33#define SYSCALL(call) while (((call) == -1) && (errno == EINTR))
34
35static const int bits_per_long = 8 * sizeof(long);
36
37static inline int nlongs(int nbit)
38{
39 return (nbit + bits_per_long - 1) / bits_per_long;
40}
41
42static inline int getbit(const unsigned long *map, int key)
43{
44 return (map[key / bits_per_long] >> (key % bits_per_long)) & 0x01;
45}
46
47int touch_caps_is_supported(struct touch_dev *dev, int fd)
48{
49 unsigned long keybits[nlongs(KEY_MAX)];
50 unsigned long absbits[nlongs(ABS_MAX)];
51 unsigned long relbits[nlongs(REL_CNT)];
52 int rc;
53
54 SYSCALL(rc = ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybits)), keybits));
55 if (rc < 0)
56 return 0;
57 SYSCALL(rc = ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbits)), absbits));
58 if (rc < 0)
59 return 0;
60 SYSCALL(rc = ioctl(fd, EVIOCGBIT(EV_REL, sizeof(relbits)), relbits));
61 if (rc < 0)
62 return 0;
63
64 /* only support pure absolute devices at this time */
65 if (getbit(relbits, REL_X) || getbit(relbits, REL_Y))
66 return 0;
67
68 if (dev->mtdev.caps.has_mtdata)
69 return 1;
70
71 return getbit(absbits, ABS_X) &&
72 getbit(absbits, ABS_Y) &&
73 getbit(keybits, BTN_TOUCH) &&
74 getbit(keybits, BTN_TOOL_DOUBLETAP);
75}
76
77void touch_caps_init(struct touch_dev *dev)
78{
79 const struct mtdev_caps *mt = &dev->mtdev.caps;
80 struct touch_caps *caps = &dev->caps;
81 caps->min_x = mt->abs[MTDEV_POSITION_X].minimum;
82 caps->max_x = mt->abs[MTDEV_POSITION_X].maximum;
83 caps->min_y = mt->abs[MTDEV_POSITION_Y].minimum;
84 caps->max_y = mt->abs[MTDEV_POSITION_Y].maximum;
85 caps->min_orient = mt->abs[MTDEV_ORIENTATION].minimum;
86 caps->max_orient = mt->abs[MTDEV_ORIENTATION].maximum;
87 caps->min_press = mt->abs[MTDEV_PRESSURE].minimum;
88 caps->max_press = mt->abs[MTDEV_PRESSURE].maximum;
89 if (caps->min_x == caps->max_x) {
90 caps->min_x = 0;
91 caps->max_x = 1024;
92 }
93 if (caps->min_y == caps->max_y) {
94 caps->min_y = 0;
95 caps->max_y = 768;
96 }
97 if (caps->min_orient == caps->max_orient)
98 caps->max_orient = 1;
99 if (caps->min_orient + caps->max_orient != 0)
100 caps->min_orient = -caps->max_orient;
101 if (caps->min_press == caps->max_press) {
102 caps->min_press = 0;
103 caps->max_press = 256;
104 }
105}
106
107float touch_angle(const struct touch_dev *dev, int orient)
108{
109 const struct touch_caps *caps = &dev->caps;
110 return orient / caps->max_orient * M_PI_2;
111}
112
113float touch_pressure(const struct touch_dev *dev, int press)
114{
115 const struct touch_caps *caps = &dev->caps;
116 return (press - caps->min_press) / (caps->max_press - caps->min_press);
117}
diff --git a/src/touch-dev.c b/src/touch-dev.c
deleted file mode 100644
index d8e192e..0000000
--- a/src/touch-dev.c
+++ /dev/null
@@ -1,264 +0,0 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010 Canonical Ltd.
6 * Copyright (C) 2010 Henrik Rydberg <rydberg@bitmath.org>
7 *
8 * This program is free software: you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation, either version 3 of the License, or (at your
11 * option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program. If not, see <http://www.gnu.org/licenses/>.
20 *
21 ****************************************************************************/
22
23#include <grail-touch.h>
24#include <malloc.h>
25#include <string.h>
26#include <errno.h>
27
28/* see mtdev-mapping.h */
29#define MTDEV_TOUCH_MINOR 1
30
31#define SET_PROP(name, value) \
32 if (t->name != value) { \
33 t->name = value; \
34 frame->nmodify++; \
35 }
36
37static void finish_touch(struct touch_dev *dev, struct touch_frame *frame)
38{
39 struct touch *t = &frame->touch[dev->slot];
40 if (t->touch_major && !t->touch_minor ||
41 !dev->mtdev.caps.has_abs[MTDEV_TOUCH_MINOR])
42 SET_PROP(touch_minor, t->touch_major);
43 if (dev->state > 0) {
44 t->active = 1;
45 grail_mask_set(frame->touches, dev->slot);
46 frame->ncreate++;
47 }
48 if (dev->state < 0) {
49 t->active = 0;
50 grail_mask_clear(frame->touches, dev->slot);
51 frame->ndestroy++;
52 }
53 dev->state = 0;
54}
55
56static void finish_legacy(struct touch_dev *dev, struct touch_frame *frame)
57{
58 static int trkid;
59 int i;
60 for (i = 0; i < frame->nactive; i++) {
61 struct touch *t = &frame->touch[i];
62 t->active = 1;
63 if (t->id < 0) {
64 t->id = trkid++ & 0xffff;
65 frame->ncreate++;
66 }
67 if (i > 0) {
68 SET_PROP(x, frame->touch[0].x);
69 SET_PROP(y, frame->touch[0].y);
70 SET_PROP(pressure, frame->touch[0].pressure);
71 }
72 grail_mask_set(frame->touches, i);
73 }
74 for (i = frame->nactive; i < DIM_TOUCH; i++) {
75 struct touch *t = &frame->touch[i];
76 t->active = 0;
77 if (t->id >= 0) {
78 t->id = -1;
79 frame->ndestroy++;
80 }
81 grail_mask_clear(frame->touches, i);
82 }
83}
84
85static void finish_packet(struct touch_dev *dev,
86 const struct input_event *syn)
87{
88 static const touch_time_t ms = 1000;
89 struct touch_frame *frame = &dev->frame;
90 int i, nslot = 0;
91 if (dev->mtdev.caps.has_mtdata)
92 finish_touch(dev, frame);
93 else
94 finish_legacy(dev, frame);
95 grail_mask_foreach(i, frame->touches, DIM_TOUCH_BYTES)
96 frame->active[nslot++] = &frame->touch[i];
97 frame->nactive = nslot;
98 frame->time = syn->time.tv_usec / ms + syn->time.tv_sec * ms;
99 if (dev->sync)
100 dev->sync(dev, syn);
101 frame->ncreate = 0;
102 frame->nmodify = 0;
103 frame->ndestroy = 0;
104}
105
106static int handle_abs_event(struct touch_dev *dev,
107 const struct input_event *ev)
108{
109 struct touch_frame *frame = &dev->frame;
110 struct touch *t = &frame->touch[dev->slot];
111 switch (ev->code) {
112 case ABS_X:
113 if (dev->mtdev.caps.has_mtdata)
114 return 0;
115 SET_PROP(x, ev->value);
116 return 0;
117 case ABS_Y:
118 if (dev->mtdev.caps.has_mtdata)
119 return 0;
120 SET_PROP(y, ev->value);
121 return 0;
122 case ABS_PRESSURE:
123 if (dev->mtdev.caps.has_mtdata)
124 return 0;
125 SET_PROP(pressure, ev->value);
126 return 0;
127 case ABS_MT_SLOT:
128 if (ev->value >= 0 && ev->value < DIM_TOUCH) {
129 if (dev->slot != ev->value)
130 finish_touch(dev, frame);
131 dev->slot = ev->value;
132 t = &frame->touch[dev->slot];
133 }
134 return 1;
135 case ABS_MT_POSITION_X:
136 SET_PROP(x, ev->value);
137 return 1;
138 case ABS_MT_POSITION_Y:
139 SET_PROP(y, ev->value);
140 return 1;
141 case ABS_MT_TOUCH_MAJOR:
142 SET_PROP(touch_major, ev->value);
143 return 1;
144 case ABS_MT_TOUCH_MINOR:
145 SET_PROP(touch_minor, ev->value);
146 return 1;
147 case ABS_MT_WIDTH_MAJOR:
148 SET_PROP(width_major, ev->value);
149 return 1;
150 case ABS_MT_WIDTH_MINOR:
151 SET_PROP(width_minor, ev->value);
152 return 1;
153 case ABS_MT_ORIENTATION:
154 SET_PROP(orientation, ev->value);
155 return 1;
156 case ABS_MT_PRESSURE:
157 SET_PROP(pressure, ev->value);
158 return 1;
159 case ABS_MT_TOOL_TYPE:
160 SET_PROP(tool_type, ev->value);
161 return 1;
162 case ABS_MT_TRACKING_ID:
163 if (t->id != ev->value) {
164 if (t->id != MT_ID_NULL) {
165 dev->state = -1;
166 finish_touch(dev, frame);
167 }
168 if (ev->value != MT_ID_NULL)
169 dev->state = 1;
170 t->id = ev->value;
171 }
172 return 1;
173 default:
174 return 0;
175 }
176}
177
178static int handle_key_event(struct touch_dev *dev,
179 const struct input_event *ev)
180{
181 struct touch_frame *frame = &dev->frame;
182 if (dev->mtdev.caps.has_mtdata)
183 return 0;
184 switch (ev->code) {
185 case BTN_TOUCH:
186 if (ev->value && !frame->nactive)
187 frame->nactive = 1;
188 else if (!ev->value && frame->nactive)
189 frame->nactive = 0;
190 return 0;
191 case BTN_TOOL_FINGER:
192 if (ev->value)
193 frame->nactive = 1;
194 return 0;
195 case BTN_TOOL_DOUBLETAP:
196 if (ev->value)
197 frame->nactive = 2;
198 return 0;
199 case BTN_TOOL_TRIPLETAP:
200 if (ev->value)
201 frame->nactive = 3;
202 return 0;
203 case BTN_TOOL_QUADTAP:
204 if (ev->value)
205 frame->nactive = 4;
206 return 0;
207 default:
208 return 0;
209 }
210}
211
212int touch_dev_open(struct touch_dev *dev, int fd)
213{
214 struct touch_frame *frame = &dev->frame;
215 int ret, i;
216 memset(dev, 0, sizeof(*dev));
217 for (i = 0; i < DIM_TOUCH; i++) {
218 struct touch *t = &frame->touch[i];
219 t->slot = i;
220 t->id = MT_ID_NULL;
221 }
222 ret = mtdev_open(&dev->mtdev, fd);
223 if (!ret && !touch_caps_is_supported(dev, fd))
224 ret = -ENODEV;
225 if (ret)
226 goto error;
227 touch_caps_init(dev);
228 return 0;
229 error:
230 return ret;
231}
232
233int touch_dev_idle(struct touch_dev *dev, int fd, int ms)
234{
235 return mtdev_idle(&dev->mtdev, fd, ms);
236}
237
238int touch_dev_pull(struct touch_dev *dev, int fd)
239{
240 struct input_event ev;
241 int ret, count = 0, consumed;
242 while ((ret = mtdev_get(&dev->mtdev, fd, &ev, 1)) > 0) {
243 consumed = 0;
244 if (ev.type == EV_SYN) {
245 if (ev.code == SYN_REPORT)
246 finish_packet(dev, &ev);
247 consumed++;
248 } else if (ev.type == EV_ABS) {
249 consumed += handle_abs_event(dev, &ev);
250 } else if (ev.type == EV_KEY) {
251 consumed += handle_key_event(dev, &ev);
252 }
253 if (!consumed && dev->event)
254 dev->event(dev, &ev);
255 count++;
256 }
257 return count > 0 ? count : ret;
258}
259
260void touch_dev_close(struct touch_dev *dev, int fd)
261{
262 mtdev_close(&dev->mtdev);
263 memset(dev, 0, sizeof(*dev));
264}
diff --git a/tools/Makefile.am b/tools/Makefile.am
index ae6866c..303f70d 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -4,4 +4,4 @@ INCLUDES=-I$(top_srcdir)/include/
4 4
5grail_gesture_SOURCES = grail-gesture.c 5grail_gesture_SOURCES = grail-gesture.c
6grail_gesture_LDFLAGS = -L$(top_builddir)/src/.libs/ \ 6grail_gesture_LDFLAGS = -L$(top_builddir)/src/.libs/ \
7 -lutouch-grail -lmtdev -lm 7 -lutouch-grail -lutouch-frame -lutouch-evemu -lmtdev -lm