~chasedouglas/grail/original-touch-state

« back to all changes in this revision

Viewing changes to src/touch-dev.c

  • Committer: Henrik Rydberg
  • Date: 2011-01-02 12:08:08 UTC
  • Revision ID: rydberg@bitmath.org-20110102120808-0nzbo3fcpp91sir5
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.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
 
37
 
static 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
 
 
56
 
static 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
 
 
85
 
static 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
 
 
106
 
static 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
 
 
178
 
static 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
 
 
212
 
int 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
 
 
233
 
int touch_dev_idle(struct touch_dev *dev, int fd, int ms)
234
 
{
235
 
        return mtdev_idle(&dev->mtdev, fd, ms);
236
 
}
237
 
 
238
 
int 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
 
 
260
 
void touch_dev_close(struct touch_dev *dev, int fd)
261
 
{
262
 
        mtdev_close(&dev->mtdev);
263
 
        memset(dev, 0, sizeof(*dev));
264
 
}