/***************************************************************************** * * 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); }