summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHenrik Rydberg <rydberg@bitmath.org>2010-07-29 15:54:31 +0200
committerHenrik Rydberg <rydberg@euromail.se>2010-08-05 22:48:38 +0200
commite0eb1015bf30fd0913db571b000ba6a83ea22660 (patch)
treea3d62152066cfb8521c80806596a4fb0fe322014
parentb76660d71e2ea77752025089bd71deffad64e325 (diff)
Split the code into recognizer and inserter
Refactor code to make more room for gesture recognition. Also simplify public headers. Signed-off-by: Henrik Rydberg <rydberg@bitmath.org>
-rw-r--r--.gitignore1
-rw-r--r--include/grail-gesture.h90
-rw-r--r--include/grail.h80
-rw-r--r--src/Makefile.am5
-rw-r--r--src/evbuf.h64
-rw-r--r--src/gebuf.h5
-rw-r--r--src/gesture-client.c113
-rw-r--r--src/gesture-dev.c105
-rw-r--r--src/grail-api.c133
-rw-r--r--src/grail-inserter.c184
-rw-r--r--src/grail-inserter.h69
-rw-r--r--src/grail-recognizer.c97
-rw-r--r--src/grail-recognizer.h34
-rw-r--r--test/Makefile.am5
-rw-r--r--test/evlink.c96
-rw-r--r--test/grail.c154
16 files changed, 597 insertions, 638 deletions
diff --git a/.gitignore b/.gitignore
index deec709..904dc45 100644
--- a/.gitignore
+++ b/.gitignore
@@ -78,7 +78,6 @@ core
78# 78#
79test/touch 79test/touch
80test/grail 80test/grail
81test/evlink
82patches 81patches
83.bzr 82.bzr
84.bzrignore 83.bzrignore
diff --git a/include/grail-gesture.h b/include/grail-gesture.h
deleted file mode 100644
index fe62b95..0000000
--- a/include/grail-gesture.h
+++ /dev/null
@@ -1,90 +0,0 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010 Canonical Ltd.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 * Authors:
21 * Henrik Rydberg <rydberg@bitmath.org>
22 *
23 ****************************************************************************/
24
25#ifndef _GRAIL_GESTURE_H
26#define _GRAIL_GESTURE_H
27
28#include <grail-touch.h>
29
30#define DIM_GESTURE_PROP 8
31typedef int gesture_prop_t;
32
33enum gesture_type {
34 GE_MOVE,
35 GE_VSCROLL,
36 DIM_GESTURE_TYPE
37};
38
39enum gesture_state {
40 GS_CANCEL,
41 GS_BEGIN,
42 GS_END
43};
44
45struct gesture_flag {
46 enum gesture_type type;
47 touch_time_t time;
48 enum gesture_state state;
49};
50
51struct gesture_event {
52 enum gesture_type type;
53 touch_time_t time;
54 gesture_prop_t prop[DIM_GESTURE_PROP];
55};
56
57struct gesture_dev {
58 struct gedev_impl *impl;
59 void *priv;
60};
61
62struct gesture_client {
63 void (*gesture)(struct gesture_client *client,
64 const struct gesture_event *ev);
65 int priority[DIM_GESTURE_TYPE];
66 struct client_impl *impl;
67 void *priv;
68};
69
70int client_init(struct gesture_client *client, void *priv);
71void client_flag(struct gesture_client *client,
72 const struct gesture_flag *flag);
73void client_event(struct gesture_client *client,
74 const struct gesture_event *ev);
75void client_sync(struct gesture_client *client);
76void client_destroy(struct gesture_client *client);
77
78int gedev_init(struct gesture_dev *dev, void *priv);
79int gedev_attach_client(struct gesture_dev *dev,
80 struct gesture_client *client);
81
82void gedev_flag(struct gesture_dev *dev, const struct gesture_flag *flag);
83void gedev_event(struct gesture_dev *dev, const struct gesture_event *ev);
84void gedev_sync(struct gesture_dev *dev);
85
86void gedev_detach_client(struct gesture_dev *dev,
87 struct gesture_client *client);
88void gedev_destroy(struct gesture_dev *dev);
89
90#endif
diff --git a/include/grail.h b/include/grail.h
index c390e22..de202b5 100644
--- a/include/grail.h
+++ b/include/grail.h
@@ -27,31 +27,82 @@
27 27
28#include <linux/input.h> 28#include <linux/input.h>
29 29
30#define DIM_GRAIL_PROP 8 30#define GRAIL_STATUS_BEGIN 0
31#define DIM_GRAIL_TYPE 64 31#define GRAIL_STATUS_UPDATE 1
32#define GRAIL_STATUS_END 2
32 33
34#define DIM_GRAIL_TYPE 64
35#define DIM_GRAIL_TYPE_BYTES (DIM_GRAIL_TYPE >> 3)
36
37#define GRAIL_TYPE_MOVE 0
38#define GRAIL_TYPE_VSCROLL 1
39#define GRAIL_TYPE_HSCROLL 2
40#define GRAIL_TYPE_SCROLL 3
41
42#define DIM_GRAIL_PROP 8
43
44static const int GRAIL_NPROP[] = {
45 2, /* MOVE */
46 1, /* VSCROLL */
47 1, /* HSCROLL */
48 2, /* SCROLL */
49};
50
51typedef unsigned char grail_mask_t;
33typedef int grail_prop_t; 52typedef int grail_prop_t;
34typedef __u64 grail_time_t; 53typedef __u64 grail_time_t;
35typedef unsigned long grail_clientid_t; 54
55static inline void grail_set_mask(grail_mask_t *mask, int i)
56{
57 mask[i >> 3] |= (1 << (i & 7));
58}
59
60static inline void grail_clear_mask(grail_mask_t *mask, int i)
61{
62 mask[i >> 3] &= ~(1 << (i & 7));
63}
64
65static inline int grail_get_mask(const grail_mask_t *mask, int i)
66{
67 return (mask[i >> 3] >> (i & 7)) & 1;
68}
69
70struct grail_coord {
71 int x, y;
72};
73
74struct grail_client_id {
75 int client;
76 int root, event, child;
77};
78
79struct grail_client_info {
80 struct grail_client_id id;
81 grail_mask_t mask[DIM_GRAIL_TYPE_BYTES];
82};
36 83
37struct grail_event { 84struct grail_event {
38 int type; 85 int type;
39 int id; 86 int id;
40 int x; 87 int status;
41 int y; 88 struct grail_coord pos;
42 int status; 89 struct grail_client_id client_id;
43 grail_time_t time; 90 grail_time_t time;
44 grail_prop_t prop[DIM_GRAIL_PROP]; 91 grail_prop_t prop[DIM_GRAIL_PROP];
45}; 92};
46 93
47struct grail { 94struct grail {
48 int (*get_clients)(int x, int y, int screen, 95 int (*get_clients)(struct grail *ge,
49 grail_clientid_t *clients, int nclients); 96 struct grail_client_info *client, int max_clients,
97 const struct grail_coord *coords, int num_coords,
98 const grail_mask_t *types);
50 void (*event)(struct grail *ge, 99 void (*event)(struct grail *ge,
51 const struct input_event *ev); 100 const struct input_event *ev);
52 void (*gesture)(struct grail *ge, 101 void (*gesture)(struct grail *ge,
53 const struct grail_event *ev); 102 const struct grail_event *ev);
54 struct grail_impl *impl; 103 struct grail_impl *impl;
104 struct gesture_inserter *gin;
105 struct gesture_recognizer *gru;
55 void *priv; 106 void *priv;
56}; 107};
57 108
@@ -60,9 +111,4 @@ int grail_idle(struct grail *ge, int fd, int ms);
60int grail_pull(struct grail *ge, int fd); 111int grail_pull(struct grail *ge, int fd);
61void grail_close(struct grail *ge, int fd); 112void grail_close(struct grail *ge, int fd);
62 113
63void grail_add_client(struct grail *ge, grail_clientid_t id,
64 const int *types, const int *priority, int ntypes);
65void grail_remove_client(struct grail *ge, grail_clientid_t id);
66
67
68#endif 114#endif
diff --git a/src/Makefile.am b/src/Makefile.am
index 50a5afd..67f930a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -7,8 +7,8 @@ libgrail_la_LDFLAGS = \
7libgrail_la_SOURCES = \ 7libgrail_la_SOURCES = \
8 touch-dev.c \ 8 touch-dev.c \
9 touch-engine.c \ 9 touch-engine.c \
10 gesture-client.c \ 10 grail-inserter.c \
11 gesture-dev.c \ 11 grail-recognizer.c \
12 grail-api.c 12 grail-api.c
13 13
14AM_CFLAGS = $(CWARNFLAGS) -std=c99 14AM_CFLAGS = $(CWARNFLAGS) -std=c99
@@ -18,5 +18,4 @@ INCLUDES = -I$(top_srcdir)/include/
18libgrailincludedir = $(includedir) 18libgrailincludedir = $(includedir)
19libgrailinclude_HEADERS = \ 19libgrailinclude_HEADERS = \
20 $(top_srcdir)/include/grail-touch.h \ 20 $(top_srcdir)/include/grail-touch.h \
21 $(top_srcdir)/include/grail-gesture.h \
22 $(top_srcdir)/include/grail.h 21 $(top_srcdir)/include/grail.h
diff --git a/src/evbuf.h b/src/evbuf.h
new file mode 100644
index 0000000..dc5ad1e
--- /dev/null
+++ b/src/evbuf.h
@@ -0,0 +1,64 @@
1/*****************************************************************************
2 *
3 * mtdev - Multitouch Protocol Translation Library (MIT license)
4 *
5 * Copyright (C) 2010 Henrik Rydberg <rydberg@bitmath.org>
6 * Copyright (C) 2010 Canonical Ltd.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
17 * Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 * DEALINGS IN THE SOFTWARE.
26 *
27 ****************************************************************************/
28
29#ifndef GRAIL_EVBUF_H
30#define GRAIL_EVBUF_H
31
32#define DIM_EVENTS 512
33
34struct evbuf {
35 int head;
36 int tail;
37 struct input_event buffer[DIM_EVENTS];
38};
39
40static inline void evbuf_clear(struct evbuf *evbuf)
41{
42 evbuf->head = evbuf->tail = 0;
43}
44
45static inline int evbuf_empty(const struct evbuf *evbuf)
46{
47 return evbuf->head == evbuf->tail;
48}
49
50static inline void evbuf_put(struct evbuf *evbuf,
51 const struct input_event *ev)
52{
53 evbuf->buffer[evbuf->head++] = *ev;
54 evbuf->head &= DIM_EVENTS - 1;
55}
56
57static inline void evbuf_get(struct evbuf *evbuf,
58 struct input_event *ev)
59{
60 *ev = evbuf->buffer[evbuf->tail++];
61 evbuf->tail &= DIM_EVENTS - 1;
62}
63
64#endif
diff --git a/src/gebuf.h b/src/gebuf.h
index e92431a..37e4a5c 100644
--- a/src/gebuf.h
+++ b/src/gebuf.h
@@ -29,6 +29,11 @@
29 29
30#define DIM_GESTURE_EVENTS 512 30#define DIM_GESTURE_EVENTS 512
31 31
32struct gesture_event {
33 touch_time_t time;
34 grail_prop_t prop[DIM_GRAIL_PROP];
35};
36
32struct gebuf { 37struct gebuf {
33 int head; 38 int head;
34 int tail; 39 int tail;
diff --git a/src/gesture-client.c b/src/gesture-client.c
deleted file mode 100644
index 91f1530..0000000
--- a/src/gesture-client.c
+++ /dev/null
@@ -1,113 +0,0 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010 Canonical Ltd.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 * Authors:
21 * Henrik Rydberg <rydberg@bitmath.org>
22 *
23 ****************************************************************************/
24
25#include <grail-gesture.h>
26#include <malloc.h>
27#include <string.h>
28#include <errno.h>
29#include "gebuf.h"
30
31#define GESTURE_GAP (1000 * 60 * 60)
32
33struct client_impl {
34 enum gesture_state state;
35 touch_time_t begin, end;
36 struct gebuf buf;
37};
38
39int client_init(struct gesture_client *client, void *priv)
40{
41 struct client_impl *x;
42 memset(client, 0, sizeof(*client));
43 x = calloc(DIM_GESTURE_TYPE, sizeof(*x));
44 if (!x)
45 return -ENOMEM;
46 client->impl = x;
47 client->priv = priv;
48 return 0;
49}
50
51void client_flag(struct gesture_client *client,
52 const struct gesture_flag *flag)
53{
54 if (client->priority[flag->type]) {
55 struct client_impl *x = &client->impl[flag->type];
56 switch(flag->state) {
57 case GS_BEGIN:
58 x->begin = flag->time;
59 x->end = flag->time + GESTURE_GAP;
60 break;
61 case GS_CANCEL:
62 x->end = x->begin;
63 break;
64 case GS_END:
65 x->end = flag->time;
66 break;
67 }
68 x->state = flag->state;
69 }
70}
71
72void client_event(struct gesture_client *client,
73 const struct gesture_event *ev)
74{
75 if (client->priority[ev->type]) {
76 struct client_impl *x = &client->impl[ev->type];
77 gebuf_put(&x->buf, ev);
78 }
79}
80
81void client_sync(struct gesture_client *client)
82{
83 struct gesture_event ev;
84 struct client_impl *x = client->impl;
85 int i, prio = 0;
86 for (i = 0; i < DIM_GESTURE_TYPE; i++) {
87 if (x[i].begin != x[i].end) {
88 if (client->priority[i] > prio)
89 prio = client->priority[i];
90 }
91 }
92 for (i = 0; i < DIM_GESTURE_TYPE; i++) {
93 if (client->priority[i] < prio) {
94 gebuf_clear(&x[i].buf);
95 } else if (prio && client->gesture) {
96 if (x[i].state == GS_END) {
97 while (!gebuf_empty(&x[i].buf)) {
98 gebuf_get(&x[i].buf, &ev);
99 client->gesture(client, &ev);
100 }
101 }
102 }
103 }
104 for (i = 0; i < DIM_GESTURE_TYPE; i++)
105 if (x[i].state == GS_END)
106 x[i].begin = x[i].end;
107}
108
109void client_destroy(struct gesture_client *client)
110{
111 free(client->impl);
112 memset(client, 0, sizeof(*client));
113}
diff --git a/src/gesture-dev.c b/src/gesture-dev.c
deleted file mode 100644
index 46c77d7..0000000
--- a/src/gesture-dev.c
+++ /dev/null
@@ -1,105 +0,0 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010 Canonical Ltd.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 * Authors:
21 * Henrik Rydberg <rydberg@bitmath.org>
22 *
23 ****************************************************************************/
24
25#include <grail-gesture.h>
26#include <malloc.h>
27#include <string.h>
28#include <errno.h>
29
30#define DIM_CLIENT 32
31
32struct gedev_impl {
33 int nclient;
34 struct gesture_client *client[DIM_CLIENT];
35};
36
37int gedev_init(struct gesture_dev *dev, void *priv)
38{
39 struct gedev_impl *x;
40 x = calloc(1, sizeof(*x));
41 if (!x)
42 return -ENOMEM;
43 dev->impl = x;
44 dev->priv = priv;
45 return 0;
46}
47
48int gedev_attach_client(struct gesture_dev *dev,
49 struct gesture_client *client)
50{
51 struct gedev_impl *x = dev->impl;
52 if (x->nclient >= DIM_CLIENT)
53 return -ENOMEM;
54 x->client[x->nclient++] = client;
55 return 0;
56}
57
58void gedev_flag(struct gesture_dev *dev,
59 const struct gesture_flag *flag)
60{
61 struct gedev_impl *x = dev->impl;
62 int i;
63 for (i = 0; i < x->nclient; i++)
64 client_flag(x->client[i], flag);
65}
66
67void gedev_event(struct gesture_dev *dev,
68 const struct gesture_event *ev)
69{
70 struct gedev_impl *x = dev->impl;
71 int i;
72 for (i = 0; i < x->nclient; i++)
73 client_event(x->client[i], ev);
74}
75
76void gedev_sync(struct gesture_dev *dev)
77{
78 struct gedev_impl *x = dev->impl;
79 int i;
80 for (i = 0; i < x->nclient; i++)
81 client_sync(x->client[i]);
82}
83
84void gedev_detach_client(struct gesture_dev *dev,
85 struct gesture_client *client)
86{
87 struct gedev_impl *x = dev->impl;
88 int i, j;
89 for (i = 0; i < x->nclient; i++)
90 if (x->client[i] == client)
91 break;
92 if (i >= x->nclient)
93 return;
94 x->nclient--;
95 for (j = i; j < x->nclient; j++)
96 x->client[j] = x->client[j + 1];
97 for (j = x->nclient; j < DIM_CLIENT; j++)
98 x->client[j] = 0;
99}
100
101void gedev_destroy(struct gesture_dev *dev)
102{
103 free(dev->impl);
104 memset(dev, 0, sizeof(*dev));
105}
diff --git a/src/grail-api.c b/src/grail-api.c
index dbe4977..19b66aa 100644
--- a/src/grail-api.c
+++ b/src/grail-api.c
@@ -1,4 +1,5 @@
1#include <grail-gesture.h> 1#include "grail-inserter.h"
2#include "grail-recognizer.h"
2#include <grail.h> 3#include <grail.h>
3#include <string.h> 4#include <string.h>
4#include <stdio.h> 5#include <stdio.h>
@@ -6,93 +7,46 @@
6#include <fcntl.h> 7#include <fcntl.h>
7#include <malloc.h> 8#include <malloc.h>
8#include <errno.h> 9#include <errno.h>
10#include "evbuf.h"
9 11
10struct grail_impl { 12struct grail_impl {
11 struct touch_dev dev; 13 struct touch_dev dev;
12 struct touch_engine engine; 14 struct touch_engine engine;
13 struct touch_frame frame; 15 struct evbuf evbuf;
14 struct gesture_dev gedev;
15 struct gesture_client client;
16 touch_time_t last_scroll;
17}; 16};
18 17
19static void gh_handle(struct grail_impl *gh,
20 const struct touch_frame *frame,
21 touch_time_t time)
22{
23#if 0
24 struct gesture_flag flag;
25 struct grail_event ev;
26 if (frame->ntouch == 1 || frame->ntouch == 2) {
27 flag.type = GE_MOVE;
28 flag.time = time;
29 flag.state = GS_BEGIN;
30 gedev_flag(&gh->dev, &flag);
31
32 ev.type = GE_MOVE;
33 ev.time = time;
34 ev.prop[0] =
35 frame->touch[0].prop[TP_POS_X] -
36 gh->frame.touch[0].prop[TP_POS_X];
37 ev.prop[1] =
38 frame->touch[0].prop[TP_POS_Y] -
39 gh->frame.touch[0].prop[TP_POS_Y];
40 if (ev.prop[0] || ev.prop[1])
41 gedev_event(&gh->dev, &ev);
42
43 flag.time = time + 1;
44 flag.state = GS_END;
45 gedev_flag(&gh->dev, &flag);
46 }
47 if (frame->ntouch == 2) {
48 flag.type = GE_VSCROLL;
49 flag.time = time;
50 flag.state = GS_BEGIN;
51 gedev_flag(&gh->dev, &flag);
52
53 ev.type = GE_VSCROLL;
54 ev.time = time;
55 ev.prop[0] =
56 frame->touch[0].prop[TP_POS_Y] -
57 gh->frame.touch[0].prop[TP_POS_Y];
58
59 if (ev.prop[0])
60 gedev_event(&gh->dev, &ev);
61
62 if (time > gh->last_scroll + 100) {
63 flag.time = time + 1;
64 flag.state = GS_END;
65 gedev_flag(&gh->dev, &flag);
66 gh->last_scroll = time;
67 }
68 } else {
69 flag.type = GE_VSCROLL;
70 flag.time = time;
71 flag.state = GS_CANCEL;
72 gedev_flag(&gh->dev, &flag);
73 }
74 gedev_sync(&gh->dev);
75 gh->frame = *frame;
76#endif
77}
78
79static void tp_event(struct touch_engine *engine, 18static void tp_event(struct touch_engine *engine,
80 const struct input_event *ev) 19 const struct input_event *ev)
81{ 20{
82 struct grail *ge = engine->priv; 21 struct grail *ge = engine->priv;
83 if (ge->event) 22 struct grail_impl *x = ge->impl;
84 ge->event(ge, ev); 23 evbuf_put(&x->evbuf, ev);
85} 24}
86 25
87static void tp_sync(struct touch_engine *engine, 26static void tp_sync(struct touch_engine *engine,
88 const struct input_event *syn) 27 const struct input_event *syn)
89{ 28{
29 struct input_event ev;
90 struct grail *ge = engine->priv; 30 struct grail *ge = engine->priv;
91#if 0 31 struct grail_impl *x = ge->impl;
92 struct touch_frame *frame = &engine->frame; 32 struct touch_frame *frame = &engine->frame;
93 gh_handle(ge, frame, frame->time); 33 grail_mask_t filtered[DIM_EV_TYPE_BYTES];
94#endif 34 int nevent = 0;
95 if (ge->event) 35 gin_frame_begin(ge, frame->time);
36 gru_recognize(ge, frame);
37 gin_frame_end(ge, filtered);
38 if (!ge->event) {
39 evbuf_clear(&x->evbuf);
40 return;
41 }
42 while (!evbuf_empty(&x->evbuf)) {
43 evbuf_get(&x->evbuf, &ev);
44 if (grail_get_mask(filtered, ev.type))
45 continue;
46 ge->event(ge, &ev);
47 nevent++;
48 }
49 if (nevent)
96 ge->event(ge, syn); 50 ge->event(ge, syn);
97} 51}
98 52
@@ -103,49 +57,48 @@ int grail_open(struct grail *ge, int fd)
103 x = calloc(1, sizeof(*x)); 57 x = calloc(1, sizeof(*x));
104 if (!x) 58 if (!x)
105 return -ENOMEM; 59 return -ENOMEM;
60 ret = gin_init(ge);
61 if (ret)
62 goto freemem;
63 ret = gru_init(ge);
64 if (ret)
65 goto freedev;
106 ret = touch_dev_open(&x->dev, fd); 66 ret = touch_dev_open(&x->dev, fd);
107 if (ret) 67 if (ret)
108 goto error; 68 goto freegru;
109 touch_engine_init(&x->engine, tp_event, tp_sync, ge); 69 touch_engine_init(&x->engine, tp_event, tp_sync, ge);
110 touch_engine_attach(&x->engine, &x->dev); 70 touch_engine_attach(&x->engine, &x->dev);
111 ge->impl = x; 71 ge->impl = x;
112 return 0; 72 return 0;
113 error: 73 freegru:
74 gru_destroy(ge);
75 freedev:
76 gin_destroy(ge);
77 freemem:
114 free(x); 78 free(x);
115 return ret; 79 return ret;
116} 80}
117 81
118int grail_idle(struct grail *ge, int fd, int ms)
119{
120 struct grail_impl *x = ge->impl;
121 return touch_dev_idle(&x->dev, fd, ms);
122}
123
124int grail_pull(struct grail *ge, int fd)
125{
126 struct grail_impl *x = ge->impl;
127 return touch_dev_pull(&x->dev, fd);
128}
129
130void grail_close(struct grail *ge, int fd) 82void grail_close(struct grail *ge, int fd)
131{ 83{
132 struct grail_impl *x = ge->impl; 84 struct grail_impl *x = ge->impl;
133 touch_engine_detach(&x->engine, &x->dev); 85 touch_engine_detach(&x->engine, &x->dev);
134 touch_dev_close(&x->dev, fd); 86 touch_dev_close(&x->dev, fd);
87 gru_destroy(ge);
88 gin_destroy(ge);
135 free(ge->impl); 89 free(ge->impl);
136 ge->impl = 0; 90 ge->impl = 0;
137} 91}
138 92
139void grail_add_client(struct grail *ge, grail_clientid_t id, 93int grail_idle(struct grail *ge, int fd, int ms)
140 const int *types, const int *priority, int ntypes)
141{ 94{
142 struct grail_impl *x = ge->impl; 95 struct grail_impl *x = ge->impl;
143 //gedev_attach_client(&x->dev, &x->client); 96 return touch_dev_idle(&x->dev, fd, ms);
144} 97}
145 98
146void grail_remove_client(struct grail *ge, grail_clientid_t id) 99int grail_pull(struct grail *ge, int fd)
147{ 100{
148 struct grail_impl *x = ge->impl; 101 struct grail_impl *x = ge->impl;
149 //gedev_detach_client(&x->dev, &x->client); 102 return touch_dev_pull(&x->dev, fd);
150} 103}
151 104
diff --git a/src/grail-inserter.c b/src/grail-inserter.c
new file mode 100644
index 0000000..b357e29
--- /dev/null
+++ b/src/grail-inserter.c
@@ -0,0 +1,184 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010 Canonical Ltd.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 * Authors:
21 * Henrik Rydberg <rydberg@bitmath.org>
22 *
23 ****************************************************************************/
24
25#include "grail-inserter.h"
26#include <malloc.h>
27#include <string.h>
28#include <errno.h>
29
30static const int MAX_GESTURE_ID = 0xfff;
31
32int gin_init(struct grail *ge)
33{
34 struct gesture_inserter *x;
35 x = calloc(1, sizeof(*x));
36 if (!x)
37 return -ENOMEM;
38 ge->gin = x;
39 return 0;
40}
41
42void gin_destroy(struct grail *ge)
43{
44 free(ge->gin);
45 ge->gin = NULL;
46}
47
48void gin_frame_begin(struct grail *ge, grail_time_t time)
49{
50 struct gesture_inserter *gin = ge->gin;
51 gin->time = time;
52}
53
54static void send_event(struct grail *ge, struct slot_state *s,
55 const struct gesture_event *ev)
56{
57 struct grail_event gev;
58 int i;
59 if (!ge->gesture)
60 return;
61 gev.type = s->type;
62 gev.id = s->id;
63 gev.status = s->status;
64 gev.pos.x = s->x;
65 gev.pos.y = s->x;
66 gev.time = ev->time;
67 memcpy(gev.prop, ev->prop, DIM_GRAIL_PROP * sizeof(gev.prop[0]));
68 for (i = 0; i < s->nclient; i++) {
69 gev.client_id = s->client_id[i];
70 ge->gesture(ge, &gev);
71 }
72}
73
74void gin_frame_end(struct grail *ge, grail_mask_t *filtered)
75{
76 struct gesture_inserter *gin = ge->gin;
77 struct gesture_event ev;
78 grail_mask_t span[DIM_SLOT_BYTES];
79 int i, slot, spanned = 0;
80 memset(filtered, 0, DIM_EV_TYPE_BYTES);
81 memset(span, 0, sizeof(span));
82 for (slot = 0; slot < DIM_SLOT; slot++) {
83 struct slot_state *s = &gin->state[slot];
84 if (!grail_get_mask(gin->used, slot))
85 continue;
86 if (!s->nclient)
87 gin_gesture_discard(gin, slot);
88 }
89 for (slot = 0; slot < DIM_SLOT; slot++) {
90 struct slot_state *s = &gin->state[slot];
91 if (!grail_get_mask(gin->used, slot))
92 continue;
93 for (i = 0; i < DIM_SLOT_BYTES; i++) {
94 span[i] |= s->span[i];
95 spanned += !!span[i];
96 }
97 while (!gebuf_empty(&s->buf)) {
98 gebuf_get(&s->buf, &ev);
99 send_event(ge, s, &ev);
100 }
101 if (s->status == GRAIL_STATUS_BEGIN)
102 s->status = GRAIL_STATUS_UPDATE;
103 }
104 if (spanned)
105 grail_set_mask(filtered, EV_ABS);
106}
107
108int gin_gesture_begin(struct grail *ge, const struct touch_frame *frame,
109 int type, int x, int y, const grail_mask_t *span)
110{
111 struct grail_client_info info[DIM_CLIENT];
112 struct grail_coord coord[DIM_CLIENT];
113 struct gesture_inserter *gin = ge->gin;
114 struct slot_state *s;
115 int i, slot, nc, ncoord = 0;
116 for (slot = 0; slot < DIM_SLOT; slot++)
117 if (!grail_get_mask(gin->used, slot))
118 break;
119 if (slot >= DIM_SLOT)
120 return -1;
121 s = &gin->state[slot];
122 s->type = type;
123 s->id = gin->gestureid++ & MAX_GESTURE_ID;
124 s->status = GRAIL_STATUS_BEGIN;
125 s->x = x;
126 s->y = y;
127 s->nclient = 0;
128 if (ge->get_clients) {
129 grail_mask_t tps[DIM_GRAIL_TYPE_BYTES];
130 memset(tps, 0, sizeof(tps));
131 grail_set_mask(tps, type);
132 for (i = 0; i < DIM_SLOT; i++) {
133 const struct touch *t = &frame->touch[i];
134 if (!grail_get_mask(span, i))
135 continue;
136 coord[ncoord].x = t->prop[TP_POS_X];
137 coord[ncoord].y = t->prop[TP_POS_Y];
138 ncoord++;
139 }
140 nc = ge->get_clients(ge, info, DIM_CLIENT, coord, ncoord, tps);
141 for (i = 0; i < nc; i++) {
142 if (!grail_get_mask(info[i].mask, type))
143 continue;
144 s->client_id[s->nclient] = info[i].id;
145 s->nclient++;
146 }
147 }
148 memcpy(s->span, span, sizeof(s->span));
149 gebuf_clear(&s->buf);
150 grail_set_mask(gin->used, slot);
151 return slot;
152}
153
154void gin_gesture_end(struct gesture_inserter *gin, int slot)
155{
156 struct slot_state *s = &gin->state[slot];
157 s->status = GRAIL_STATUS_END;
158 grail_clear_mask(gin->used, slot);
159}
160
161void gin_gesture_discard(struct gesture_inserter *gin, int slot)
162{
163 struct slot_state *s = &gin->state[slot];
164 gebuf_clear(&s->buf);
165 gin_gesture_end(gin, slot);
166}
167
168void gin_gesture_end_all(struct gesture_inserter *gin)
169{
170 int slot;
171 for (slot = 0; slot < DIM_SLOT; slot++)
172 gin_gesture_end(gin, slot);
173}
174
175void gin_gesture_event(struct gesture_inserter *gin, int slot,
176 const grail_prop_t *prop)
177{
178 struct slot_state *s = &gin->state[slot];
179 struct gesture_event ev;
180 ev.time = gin->time;
181 memcpy(ev.prop, prop, sizeof(ev.prop));
182 gebuf_put(&s->buf, &ev);
183}
184
diff --git a/src/grail-inserter.h b/src/grail-inserter.h
new file mode 100644
index 0000000..1e02d5f
--- /dev/null
+++ b/src/grail-inserter.h
@@ -0,0 +1,69 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010 Canonical Ltd.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 * Authors:
21 * Henrik Rydberg <rydberg@bitmath.org>
22 *
23 ****************************************************************************/
24
25#ifndef _GRAIL_GESTURE_H
26#define _GRAIL_GESTURE_H
27
28#include <grail-touch.h>
29#include <grail.h>
30#include "gebuf.h"
31
32#define DIM_EV_TYPE EV_CNT
33#define DIM_EV_TYPE_BYTES (DIM_EV_TYPE >> 3)
34
35#define DIM_SLOT 32
36#define DIM_SLOT_BYTES (DIM_SLOT >> 3)
37
38#define DIM_CLIENT 32
39
40struct slot_state {
41 int type, id, status, x, y, nclient;
42 struct grail_client_id client_id[DIM_CLIENT];
43 grail_mask_t span[DIM_SLOT_BYTES];
44 struct gebuf buf;
45};
46
47struct gesture_inserter {
48 struct slot_state state[DIM_SLOT];
49 grail_mask_t used[DIM_SLOT_BYTES];
50 grail_time_t time;
51 int gestureid;
52};
53
54int gin_init(struct grail *ge);
55void gin_destroy(struct grail *ge);
56
57void gin_frame_begin(struct grail *ge, grail_time_t time);
58void gin_frame_end(struct grail *ge, grail_mask_t *filtered);
59
60int gin_gesture_begin(struct grail *ge, const struct touch_frame *frame,
61 int type, int x, int y, const grail_mask_t *span);
62void gin_gesture_discard(struct gesture_inserter *gin, int slot);
63void gin_gesture_end(struct gesture_inserter *gin, int slot);
64void gin_gesture_end_all(struct gesture_inserter *gin);
65
66void gin_gesture_event(struct gesture_inserter *gin, int slot,
67 const grail_prop_t *prop);
68
69#endif
diff --git a/src/grail-recognizer.c b/src/grail-recognizer.c
new file mode 100644
index 0000000..9ede059
--- /dev/null
+++ b/src/grail-recognizer.c
@@ -0,0 +1,97 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010 Canonical Ltd.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 * Authors:
21 * Henrik Rydberg <rydberg@bitmath.org>
22 *
23 ****************************************************************************/
24
25#include "grail-inserter.h"
26#include <string.h>
27#include <malloc.h>
28#include <errno.h>
29
30struct gesture_recognizer {
31 struct touch_frame frame;
32 touch_time_t scroll_time;
33 int scroll_active;
34 int scroll_gslot;
35 int scroll_slots[2];
36};
37
38int gru_init(struct grail *ge)
39{
40 ge->gru = calloc(1, sizeof(struct gesture_recognizer));
41 if (!ge->gru)
42 return -ENOMEM;
43 return 0;
44}
45
46void gru_destroy(struct grail *ge)
47{
48 free(ge->gru);
49 ge->gru = NULL;
50}
51
52void gru_recognize(struct grail *ge, const struct touch_frame *frame)
53{
54 struct gesture_inserter *gin = ge->gin;
55 struct gesture_recognizer *gru = ge->gru;
56 grail_prop_t prop[DIM_GRAIL_PROP];
57 grail_mask_t span[16];
58 int slot, nslot, x, y, dx, dy;
59 if (!gru)
60 return;
61 if (frame->ncreate || frame->ndestroy) {
62 gin_gesture_end_all(gin);
63 gru->scroll_active = 0;
64 return;
65 }
66 if (frame->ntouch != 2)
67 return;
68 memset(span, 0, sizeof(span));
69 nslot = 0;
70 x = y = dx = dy = 0;
71 for (slot = frame->slot; slot >= 0; slot = next_slot(frame, slot)) {
72 struct touch *ot = &gru->frame.touch[slot];
73 const struct touch *t = &frame->touch[slot];
74 gru->scroll_slots[nslot] = slot;
75 grail_set_mask(span, slot);
76 x += t->prop[TP_POS_X];
77 y += t->prop[TP_POS_Y];
78 dx += t->prop[TP_POS_X] - ot->prop[TP_POS_X];
79 dy += t->prop[TP_POS_Y] - ot->prop[TP_POS_Y];
80 nslot++;
81 }
82 x /= nslot;
83 y /= nslot;
84 dx /= nslot;
85 dy /= nslot;
86 if (!dy)
87 return;
88 if (!gru->scroll_active) {
89 gru->scroll_gslot = gin_gesture_begin(ge, frame,
90 GRAIL_TYPE_VSCROLL,
91 x, y, span);
92 gru->scroll_active = 1;
93 }
94 prop[0] = dy;
95 gin_gesture_event(gin, gru->scroll_gslot, prop);
96 gru->frame = *frame;
97}
diff --git a/src/grail-recognizer.h b/src/grail-recognizer.h
new file mode 100644
index 0000000..8c47162
--- /dev/null
+++ b/src/grail-recognizer.h
@@ -0,0 +1,34 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010 Canonical Ltd.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 * Authors:
21 * Henrik Rydberg <rydberg@bitmath.org>
22 *
23 ****************************************************************************/
24
25#ifndef _GRAIL_RECOGNIZER_H
26#define _GRAIL_RECOGNIZER_H
27
28#include "grail-inserter.h"
29
30int gru_init(struct grail *ge);
31void gru_recognize(struct grail *ge, const struct touch_frame *frame);
32void gru_destroy(struct grail *ge);
33
34#endif
diff --git a/test/Makefile.am b/test/Makefile.am
index a24f615..c8404f8 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -1,4 +1,4 @@
1noinst_PROGRAMS = touch grail evlink 1noinst_PROGRAMS = touch grail
2 2
3INCLUDES=-I$(top_srcdir)/include/ 3INCLUDES=-I$(top_srcdir)/include/
4 4
@@ -7,6 +7,3 @@ touch_LDFLAGS = -L$(top_builddir)/src/.libs/ -lgrail -lmtdev
7 7
8grail_SOURCES = grail.c 8grail_SOURCES = grail.c
9grail_LDFLAGS = -L$(top_builddir)/src/.libs/ -lgrail -lmtdev 9grail_LDFLAGS = -L$(top_builddir)/src/.libs/ -lgrail -lmtdev
10
11evlink_SOURCES = evlink.c
12evlink_LDFLAGS = -L$(top_builddir)/src/.libs/ -lgrail -lmtdev
diff --git a/test/evlink.c b/test/evlink.c
deleted file mode 100644
index bef5e22..0000000
--- a/test/evlink.c
+++ /dev/null
@@ -1,96 +0,0 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010 Canonical Ltd.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 * Authors:
21 * Henrik Rydberg <rydberg@bitmath.org>
22 *
23 ****************************************************************************/
24
25#include <grail.h>
26#include <string.h>
27#include <stdio.h>
28#include <unistd.h>
29#include <fcntl.h>
30
31static int tp_get_clients(int x, int y, int screen,
32 grail_clientid_t *clients, int nclients)
33{
34 return 0;
35}
36
37static void tp_event(struct grail *ge, const struct input_event *ev)
38{
39 fprintf(stderr, "event %d %d %d\n", ev->type, ev->code, ev->value);
40}
41
42static void tp_gesture(struct grail *ge, const struct grail_event *ev)
43{
44 fprintf(stderr, "gesture %d %d\n", ev->type, ev->id);
45}
46
47static void loop_device(struct grail *ge, int fd)
48{
49 while (!grail_idle(ge, fd, 5000))
50 grail_pull(ge, fd);
51}
52
53#if 0
54void grail_add_client(struct grail *ge, grail_clientid_t id,
55 const int *types, const int *priority, int ntypes);
56void grail_remove_client(struct grail *ge, grail_clientid_t id);
57
58#endif
59
60
61int main(int argc, char *argv[])
62{
63 struct grail ge;
64 int fd;
65
66 if (argc < 2) {
67 fprintf(stderr, "Usage: %s <device>\n", argv[0]);
68 return -1;
69 }
70
71 memset(&ge, 0, sizeof(ge));
72 ge.get_clients = tp_get_clients;
73 ge.event = tp_event;
74 ge.gesture = tp_gesture;
75
76 fd = open(argv[1], O_RDONLY | O_NONBLOCK);
77 if (fd < 0) {
78 fprintf(stderr, "error: could not open device\n");
79 return -1;
80 }
81 if (ioctl(fd, EVIOCGRAB, 1)) {
82 fprintf(stderr, "error: could not grab the device\n");
83 return -1;
84 }
85
86 if (grail_open(&ge, fd)) {
87 fprintf(stderr, "error: could not open touch device\n");
88 return -1;
89 }
90 loop_device(&ge, fd);
91 grail_close(&ge, fd);
92
93 ioctl(fd, EVIOCGRAB, 0);
94 close(fd);
95 return 0;
96}
diff --git a/test/grail.c b/test/grail.c
index e22ffd8..85c5bd4 100644
--- a/test/grail.c
+++ b/test/grail.c
@@ -22,146 +22,60 @@
22 * 22 *
23 ****************************************************************************/ 23 ****************************************************************************/
24 24
25#include <grail-gesture.h> 25#include <grail.h>
26#include <string.h> 26#include <string.h>
27#include <stdio.h> 27#include <stdio.h>
28#include <unistd.h> 28#include <unistd.h>
29#include <fcntl.h> 29#include <fcntl.h>
30 30
31struct gesture_handler { 31static int tp_get_clients(struct grail *ge,
32 struct touch_frame frame; 32 struct grail_client_info *clients, int max_clients,
33 struct gesture_client client; 33 const struct grail_coord *coords, int num_coords,
34 struct gesture_dev dev; 34 const grail_mask_t *types)
35 touch_time_t last_scroll;
36};
37
38static void gh_gesture(struct gesture_client *client,
39 const struct gesture_event *ev)
40{
41 int i;
42 fprintf(stderr, "gesture %d %lld\n",
43 ev->type, ev->time);
44 switch (ev->type) {
45 case GE_MOVE:
46 fprintf(stderr, " %d\n", ev->prop[0]);
47 fprintf(stderr, " %d\n", ev->prop[1]);
48 break;
49 case GE_VSCROLL:
50 fprintf(stderr, " %d\n", ev->prop[0]);
51 break;
52 }
53}
54
55static void gh_init(struct gesture_handler *gh)
56{ 35{
57 memset(gh, 0, sizeof(*gh)); 36 memset(&clients[0], 0, sizeof(clients[0]));
58 gedev_init(&gh->dev, 0); 37 clients[0].id.client = 345;
59 client_init(&gh->client, gh); 38 clients[0].id.root = 1;
60 gh->client.gesture = gh_gesture; 39 clients[0].id.event = 2;
61 gh->client.priority[GE_MOVE] = 1; 40 clients[0].id.child = 3;
62 gh->client.priority[GE_VSCROLL] = 2; 41 clients[0].mask[0] = 3;
63 gedev_attach_client(&gh->dev, &gh->client); 42 return 1;
64} 43}
65 44
66static void gh_handle(struct gesture_handler *gh, 45static void tp_event(struct grail *ge, const struct input_event *ev)
67 const struct touch_frame *frame,
68 touch_time_t time)
69{ 46{
70 struct gesture_flag flag; 47 fprintf(stderr, "event %d %d %d\n", ev->type, ev->code, ev->value);
71 struct gesture_event ev;
72 if (frame->ntouch == 1 || frame->ntouch == 2) {
73 flag.type = GE_MOVE;
74 flag.time = time;
75 flag.state = GS_BEGIN;
76 gedev_flag(&gh->dev, &flag);
77
78 ev.type = GE_MOVE;
79 ev.time = time;
80 ev.prop[0] =
81 frame->touch[0].prop[TP_POS_X] -
82 gh->frame.touch[0].prop[TP_POS_X];
83 ev.prop[1] =
84 frame->touch[0].prop[TP_POS_Y] -
85 gh->frame.touch[0].prop[TP_POS_Y];
86 if (ev.prop[0] || ev.prop[1])
87 gedev_event(&gh->dev, &ev);
88
89 flag.time = time + 1;
90 flag.state = GS_END;
91 gedev_flag(&gh->dev, &flag);
92 }
93 if (frame->ntouch == 2) {
94 flag.type = GE_VSCROLL;
95 flag.time = time;
96 flag.state = GS_BEGIN;
97 gedev_flag(&gh->dev, &flag);
98
99 ev.type = GE_VSCROLL;
100 ev.time = time;
101 ev.prop[0] =
102 frame->touch[0].prop[TP_POS_Y] -
103 gh->frame.touch[0].prop[TP_POS_Y];
104
105 if (ev.prop[0])
106 gedev_event(&gh->dev, &ev);
107
108 if (time > gh->last_scroll + 100) {
109 flag.time = time + 1;
110 flag.state = GS_END;
111 gedev_flag(&gh->dev, &flag);
112 gh->last_scroll = time;
113 }
114 } else {
115 flag.type = GE_VSCROLL;
116 flag.time = time;
117 flag.state = GS_CANCEL;
118 gedev_flag(&gh->dev, &flag);
119 }
120 gedev_sync(&gh->dev);
121 gh->frame = *frame;
122} 48}
123 49
124static void gh_destroy(struct gesture_handler *gh) 50static void tp_gesture(struct grail *ge, const struct grail_event *ev)
125{ 51{
126 gedev_detach_client(&gh->dev, &gh->client); 52 fprintf(stderr, "gesture %d %d %d %d: %d %d\n",
127 client_destroy(&gh->client); 53 ev->type, ev->id,
128 gedev_destroy(&gh->dev); 54 ev->client_id.client, ev->client_id.event,
55 ev->prop[0], ev->prop[1]);
129} 56}
130 57
131static void tp_event(struct touch_engine *engine, 58static void loop_device(struct grail *ge, int fd)
132 const struct input_event *ev)
133{ 59{
134} 60 while (!grail_idle(ge, fd, 5000))
135 61 grail_pull(ge, fd);
136static void tp_sync(struct touch_engine *engine,
137 const struct input_event *syn)
138{
139 struct gesture_handler *gh = engine->priv;
140 struct touch_frame *frame = &engine->frame;
141 gh_handle(gh, frame, frame->time);
142}
143
144static void loop_device(struct touch_dev *dev, int fd)
145{
146 struct gesture_handler gh;
147 struct touch_engine engine;
148 gh_init(&gh);
149 touch_engine_init(&engine, tp_event, tp_sync, &gh);
150 touch_engine_attach(&engine, dev);
151 while (!touch_dev_idle(dev, fd, 5000))
152 touch_dev_pull(dev, fd);
153 touch_engine_detach(&engine, dev);
154 gh_destroy(&gh);
155} 62}
156 63
157int main(int argc, char *argv[]) 64int main(int argc, char *argv[])
158{ 65{
159 struct touch_dev dev; 66 struct grail ge;
160 int fd; 67 int fd;
68
161 if (argc < 2) { 69 if (argc < 2) {
162 fprintf(stderr, "Usage: %s <device>\n", argv[0]); 70 fprintf(stderr, "Usage: %s <device>\n", argv[0]);
163 return -1; 71 return -1;
164 } 72 }
73
74 memset(&ge, 0, sizeof(ge));
75 ge.get_clients = tp_get_clients;
76 ge.event = tp_event;
77 ge.gesture = tp_gesture;
78
165 fd = open(argv[1], O_RDONLY | O_NONBLOCK); 79 fd = open(argv[1], O_RDONLY | O_NONBLOCK);
166 if (fd < 0) { 80 if (fd < 0) {
167 fprintf(stderr, "error: could not open device\n"); 81 fprintf(stderr, "error: could not open device\n");
@@ -171,12 +85,14 @@ int main(int argc, char *argv[])
171 fprintf(stderr, "error: could not grab the device\n"); 85 fprintf(stderr, "error: could not grab the device\n");
172 return -1; 86 return -1;
173 } 87 }
174 if (touch_dev_open(&dev, fd)) { 88
89 if (grail_open(&ge, fd)) {
175 fprintf(stderr, "error: could not open touch device\n"); 90 fprintf(stderr, "error: could not open touch device\n");
176 return -1; 91 return -1;
177 } 92 }
178 loop_device(&dev, fd); 93 loop_device(&ge, fd);
179 touch_dev_close(&dev, fd); 94 grail_close(&ge, fd);
95
180 ioctl(fd, EVIOCGRAB, 0); 96 ioctl(fd, EVIOCGRAB, 0);
181 close(fd); 97 close(fd);
182 return 0; 98 return 0;