From e0eb1015bf30fd0913db571b000ba6a83ea22660 Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Thu, 29 Jul 2010 15:54:31 +0200 Subject: 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 --- src/grail-inserter.c | 184 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 src/grail-inserter.c (limited to 'src/grail-inserter.c') 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 @@ +/***************************************************************************** + * + * grail - Gesture Recognition And Instantiation Library + * + * Copyright (C) 2010 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Authors: + * Henrik Rydberg + * + ****************************************************************************/ + +#include "grail-inserter.h" +#include +#include +#include + +static const int MAX_GESTURE_ID = 0xfff; + +int gin_init(struct grail *ge) +{ + struct gesture_inserter *x; + x = calloc(1, sizeof(*x)); + if (!x) + return -ENOMEM; + ge->gin = x; + return 0; +} + +void gin_destroy(struct grail *ge) +{ + free(ge->gin); + ge->gin = NULL; +} + +void gin_frame_begin(struct grail *ge, grail_time_t time) +{ + struct gesture_inserter *gin = ge->gin; + gin->time = time; +} + +static void send_event(struct grail *ge, struct slot_state *s, + const struct gesture_event *ev) +{ + struct grail_event gev; + int i; + if (!ge->gesture) + return; + gev.type = s->type; + gev.id = s->id; + gev.status = s->status; + gev.pos.x = s->x; + gev.pos.y = s->x; + gev.time = ev->time; + memcpy(gev.prop, ev->prop, DIM_GRAIL_PROP * sizeof(gev.prop[0])); + for (i = 0; i < s->nclient; i++) { + gev.client_id = s->client_id[i]; + ge->gesture(ge, &gev); + } +} + +void gin_frame_end(struct grail *ge, grail_mask_t *filtered) +{ + struct gesture_inserter *gin = ge->gin; + struct gesture_event ev; + grail_mask_t span[DIM_SLOT_BYTES]; + int i, slot, spanned = 0; + memset(filtered, 0, DIM_EV_TYPE_BYTES); + memset(span, 0, sizeof(span)); + for (slot = 0; slot < DIM_SLOT; slot++) { + struct slot_state *s = &gin->state[slot]; + if (!grail_get_mask(gin->used, slot)) + continue; + if (!s->nclient) + gin_gesture_discard(gin, slot); + } + for (slot = 0; slot < DIM_SLOT; slot++) { + struct slot_state *s = &gin->state[slot]; + if (!grail_get_mask(gin->used, slot)) + continue; + for (i = 0; i < DIM_SLOT_BYTES; i++) { + span[i] |= s->span[i]; + spanned += !!span[i]; + } + while (!gebuf_empty(&s->buf)) { + gebuf_get(&s->buf, &ev); + send_event(ge, s, &ev); + } + if (s->status == GRAIL_STATUS_BEGIN) + s->status = GRAIL_STATUS_UPDATE; + } + if (spanned) + grail_set_mask(filtered, EV_ABS); +} + +int gin_gesture_begin(struct grail *ge, const struct touch_frame *frame, + int type, int x, int y, const grail_mask_t *span) +{ + struct grail_client_info info[DIM_CLIENT]; + struct grail_coord coord[DIM_CLIENT]; + struct gesture_inserter *gin = ge->gin; + struct slot_state *s; + int i, slot, nc, ncoord = 0; + for (slot = 0; slot < DIM_SLOT; slot++) + if (!grail_get_mask(gin->used, slot)) + break; + if (slot >= DIM_SLOT) + return -1; + s = &gin->state[slot]; + s->type = type; + s->id = gin->gestureid++ & MAX_GESTURE_ID; + s->status = GRAIL_STATUS_BEGIN; + s->x = x; + s->y = y; + s->nclient = 0; + if (ge->get_clients) { + grail_mask_t tps[DIM_GRAIL_TYPE_BYTES]; + memset(tps, 0, sizeof(tps)); + grail_set_mask(tps, type); + for (i = 0; i < DIM_SLOT; i++) { + const struct touch *t = &frame->touch[i]; + if (!grail_get_mask(span, i)) + continue; + coord[ncoord].x = t->prop[TP_POS_X]; + coord[ncoord].y = t->prop[TP_POS_Y]; + ncoord++; + } + nc = ge->get_clients(ge, info, DIM_CLIENT, coord, ncoord, tps); + for (i = 0; i < nc; i++) { + if (!grail_get_mask(info[i].mask, type)) + continue; + s->client_id[s->nclient] = info[i].id; + s->nclient++; + } + } + memcpy(s->span, span, sizeof(s->span)); + gebuf_clear(&s->buf); + grail_set_mask(gin->used, slot); + return slot; +} + +void gin_gesture_end(struct gesture_inserter *gin, int slot) +{ + struct slot_state *s = &gin->state[slot]; + s->status = GRAIL_STATUS_END; + grail_clear_mask(gin->used, slot); +} + +void gin_gesture_discard(struct gesture_inserter *gin, int slot) +{ + struct slot_state *s = &gin->state[slot]; + gebuf_clear(&s->buf); + gin_gesture_end(gin, slot); +} + +void gin_gesture_end_all(struct gesture_inserter *gin) +{ + int slot; + for (slot = 0; slot < DIM_SLOT; slot++) + gin_gesture_end(gin, slot); +} + +void gin_gesture_event(struct gesture_inserter *gin, int slot, + const grail_prop_t *prop) +{ + struct slot_state *s = &gin->state[slot]; + struct gesture_event ev; + ev.time = gin->time; + memcpy(ev.prop, prop, sizeof(ev.prop)); + gebuf_put(&s->buf, &ev); +} + -- cgit v1.2.3