/*****************************************************************************
*
* 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
#include
#include
#include
#include
struct gesture_handler {
struct touch_frame frame;
struct gesture_client client;
struct gesture_dev dev;
touch_time_t last_scroll;
};
static void gh_gesture(struct gesture_client *client,
const struct gesture_event *ev)
{
int i;
fprintf(stderr, "gesture %d %lld\n",
ev->type, ev->time);
switch (ev->type) {
case GE_MOVE:
fprintf(stderr, " %d\n", ev->prop[0]);
fprintf(stderr, " %d\n", ev->prop[1]);
break;
case GE_VSCROLL:
fprintf(stderr, " %d\n", ev->prop[0]);
break;
}
}
static void gh_init(struct gesture_handler *gh)
{
memset(gh, 0, sizeof(*gh));
gedev_init(&gh->dev, 0);
client_init(&gh->client, gh);
gh->client.gesture = gh_gesture;
gh->client.priority[GE_MOVE] = 1;
gh->client.priority[GE_VSCROLL] = 2;
gedev_attach_client(&gh->dev, &gh->client);
}
static void gh_handle(struct gesture_handler *gh,
const struct touch_frame *frame,
touch_time_t time)
{
struct gesture_flag flag;
struct gesture_event ev;
if (frame->ntouch == 1 || frame->ntouch == 2) {
flag.type = GE_MOVE;
flag.time = time;
flag.state = GS_BEGIN;
gedev_flag(&gh->dev, &flag);
ev.type = GE_MOVE;
ev.time = time;
ev.prop[0] =
frame->touch[0].prop[TP_POS_X] -
gh->frame.touch[0].prop[TP_POS_X];
ev.prop[1] =
frame->touch[0].prop[TP_POS_Y] -
gh->frame.touch[0].prop[TP_POS_Y];
if (ev.prop[0] || ev.prop[1])
gedev_event(&gh->dev, &ev);
flag.time = time + 1;
flag.state = GS_END;
gedev_flag(&gh->dev, &flag);
}
if (frame->ntouch == 2) {
flag.type = GE_VSCROLL;
flag.time = time;
flag.state = GS_BEGIN;
gedev_flag(&gh->dev, &flag);
ev.type = GE_VSCROLL;
ev.time = time;
ev.prop[0] =
frame->touch[0].prop[TP_POS_Y] -
gh->frame.touch[0].prop[TP_POS_Y];
if (ev.prop[0])
gedev_event(&gh->dev, &ev);
if (time > gh->last_scroll + 100) {
flag.time = time + 1;
flag.state = GS_END;
gedev_flag(&gh->dev, &flag);
gh->last_scroll = time;
}
} else {
flag.type = GE_VSCROLL;
flag.time = time;
flag.state = GS_CANCEL;
gedev_flag(&gh->dev, &flag);
}
gedev_sync(&gh->dev);
gh->frame = *frame;
}
static void gh_destroy(struct gesture_handler *gh)
{
gedev_detach_client(&gh->dev, &gh->client);
client_destroy(&gh->client);
gedev_destroy(&gh->dev);
}
static void tp_event(struct touch_engine *engine,
const struct input_event *ev)
{
}
static void tp_sync(struct touch_engine *engine,
const struct input_event *syn)
{
struct gesture_handler *gh = engine->priv;
struct touch_frame *frame = &engine->frame;
gh_handle(gh, frame, frame->time);
}
static void loop_device(struct touch_dev *dev, int fd)
{
struct gesture_handler gh;
struct touch_engine engine;
gh_init(&gh);
touch_engine_init(&engine, tp_event, tp_sync, &gh);
touch_engine_attach(&engine, dev);
while (!touch_dev_idle(dev, fd, 5000))
touch_dev_pull(dev, fd);
touch_engine_detach(&engine, dev);
gh_destroy(&gh);
}
int main(int argc, char *argv[])
{
struct touch_dev dev;
int fd;
if (argc < 2) {
fprintf(stderr, "Usage: %s \n", argv[0]);
return -1;
}
fd = open(argv[1], O_RDONLY | O_NONBLOCK);
if (fd < 0) {
fprintf(stderr, "error: could not open device\n");
return -1;
}
if (ioctl(fd, EVIOCGRAB, 1)) {
fprintf(stderr, "error: could not grab the device\n");
return -1;
}
if (touch_dev_open(&dev, fd)) {
fprintf(stderr, "error: could not open touch device\n");
return -1;
}
loop_device(&dev, fd);
touch_dev_close(&dev, fd);
ioctl(fd, EVIOCGRAB, 0);
close(fd);
return 0;
}