summaryrefslogtreecommitdiff
path: root/src/grail-inserter.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/grail-inserter.c')
-rw-r--r--src/grail-inserter.c184
1 files changed, 184 insertions, 0 deletions
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