/***************************************************************************** * * grail - Gesture Recognition And Instantiation Library * * Copyright (C) 2010 Canonical Ltd. * Copyright (C) 2010 Henrik Rydberg * * 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 . * ****************************************************************************/ #include "grail-inserter.h" #include "grail-recognizer.h" #include #include #include #include #include #include #include #include "evbuf.h" struct grail_impl { struct touch_dev dev; struct evbuf evbuf; int filter_abs; int hack_status; }; static void tp_event(struct touch_dev *dev, const struct input_event *ev) { struct grail *ge = dev->priv; struct grail_impl *x = ge->impl; evbuf_put(&x->evbuf, ev); } static int extra_filtered(const struct input_event *ev) { if (ev->type == EV_KEY) { switch (ev->code) { case BTN_TOUCH: case BTN_TOOL_FINGER: case BTN_TOOL_DOUBLETAP: case BTN_TOOL_TRIPLETAP: case BTN_TOOL_QUADTAP: return 1; } } return 0; } static void tp_sync(struct touch_dev *dev, const struct input_event *syn) { struct input_event ev; struct grail *ge = dev->priv; struct grail_impl *x = ge->impl; struct gesture_recognizer *gru = ge->gru; struct touch_frame *frame = &dev->frame; grail_mask_t filtered[DIM_EV_TYPE_BYTES]; int dofilt, hack, nevent = 0; gin_frame_begin(ge, frame); gru_recognize(ge, frame); gin_frame_end(ge, filtered, sizeof(filtered), frame); dofilt = gru->move.multi || gru->move.single && x->filter_abs; hack = gru->move.single; if (!ge->event) { evbuf_clear(&x->evbuf); return; } while (!evbuf_empty(&x->evbuf)) { evbuf_get(&x->evbuf, &ev); if (!hack && ev.type == EV_ABS) continue; if (dofilt && grail_mask_get(filtered, ev.type)) continue; if (extra_filtered(&ev)) continue; ge->event(ge, &ev); nevent++; } if (hack != x->hack_status) { ev = *syn; ev.type = EV_KEY; ev.code = BTN_TOUCH; ev.value = hack; ge->event(ge, &ev); x->hack_status = hack; nevent++; } if (nevent) ge->event(ge, syn); } void grail_filter_abs_events(struct grail *ge, int usage) { struct grail_impl *x = ge->impl; x->filter_abs = usage; } int grail_open(struct grail *ge, int fd) { struct grail_impl *x; int ret; x = calloc(1, sizeof(*x)); if (!x) return -ENOMEM; ge->impl = x; ret = touch_dev_open(&x->dev, fd); if (ret) goto freemem; x->dev.event = tp_event; x->dev.sync = tp_sync; x->dev.priv = ge; ret = gin_init(ge); if (ret) goto freedev; ret = gru_init(ge); if (ret) goto freegin; return 0; freegin: gin_destroy(ge); freedev: touch_dev_close(&x->dev, fd); freemem: free(x); ge->impl = 0; return ret; } void grail_close(struct grail *ge, int fd) { struct grail_impl *x = ge->impl; void *status; gru_destroy(ge); gin_destroy(ge); touch_dev_close(&x->dev, fd); free(ge->impl); ge->impl = 0; } int grail_idle(struct grail *ge, int fd, int ms) { struct grail_impl *x = ge->impl; return touch_dev_idle(&x->dev, fd, ms); } int grail_pull(struct grail *ge, int fd) { struct grail_impl *x = ge->impl; return touch_dev_pull(&x->dev, fd); } void grail_get_units(const struct grail *ge, struct grail_coord *min, struct grail_coord *max) { const struct touch_caps *caps = &ge->impl->dev.caps; min->x = caps->min_x; min->y = caps->min_y; max->x = caps->max_x; max->y = caps->max_y; }