/*****************************************************************************
*
* utouch-frame - Touch Frame Library
*
* Copyright (C) 2010-2011 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
*
****************************************************************************/
#define MTDEV_NO_LEGACY_API
#include
#include
#include
#include
#include
#include
static int opcode;
struct frame_test {
Display *display;
Window root, win;
XIDeviceInfo *info, *dev;
utouch_frame_handle fh;
};
static int init_xi2(struct frame_test *test, int id)
{
Display *dpy;
int ndevices, i;
int event, error;
dpy = XOpenDisplay(NULL);
if (!dpy)
return -1;
if (!XQueryExtension(dpy, "XInputExtension", &opcode, &event, &error))
return -1;
test->display = dpy;
test->info = XIQueryDevice(dpy, XIAllDevices, &ndevices);
test->dev = 0;
for (i = 0; i < ndevices; i++)
if (test->info[i].deviceid == id)
test->dev = &test->info[i];
if (!test->dev)
return -1;
test->root = DefaultRootWindow(dpy);
test->win = XCreateSimpleWindow(dpy, test->root,
0, 0, 400, 400, 0,
BlackPixel(dpy, 0),
WhitePixel(dpy, 0));
XMapWindow(test->display, test->win);
XFlush(test->display);
return 0;
}
static int init_frame(struct frame_test *test)
{
test->fh = utouch_frame_new_engine(100, 32, 100);
if (!test->fh)
return -1;
return utouch_frame_init_xi2(test->fh, test->display, test->dev);
}
static void destroy_all(struct frame_test *test)
{
utouch_frame_delete_engine(test->fh);
XIFreeDeviceInfo(test->info);
XDestroyWindow(test->display, test->win);
XCloseDisplay(test->display);
memset(test, 0, sizeof(*test));
}
static void report_device_caps(struct frame_test *test)
{
struct utouch_surface *s = utouch_frame_get_surface(test->fh);
fprintf(stderr, "device props:\n");
if (s->needs_pointer)
fprintf(stderr, "\tpointer\n");
if (s->is_direct)
fprintf(stderr, "\tdirect\n");
if (s->is_buttonpad)
fprintf(stderr, "\tbuttonpad\n");
if (s->is_semi_mt)
fprintf(stderr, "\tsemi_mt\n");
fprintf(stderr, "device mt events:\n");
if (s->use_touch_major)
fprintf(stderr, "\ttouch_major\n");
if (s->use_touch_minor)
fprintf(stderr, "\ttouch_minor\n");
if (s->use_width_major)
fprintf(stderr, "\twidth_major\n");
if (s->use_width_minor)
fprintf(stderr, "\twidth_minor\n");
if (s->use_orientation)
fprintf(stderr, "\torientation\n");
if (s->use_pressure)
fprintf(stderr, "\tpressure\n");
if (s->use_distance)
fprintf(stderr, "\tdistance\n");
}
static void report_frame(const struct utouch_frame *frame,
const XIDeviceEvent *ev)
{
int i;
for (i = 0; i < frame->num_active; i++) {
const struct utouch_contact *t = frame->active[i];
fprintf(stderr, "touch %d\n", i);
fprintf(stderr, " slot: %d\n", t->slot);
fprintf(stderr, " id: %d\n", t->id);
fprintf(stderr, " tool_type: %d\n", t->tool_type);
fprintf(stderr, " x: %f\n", t->x);
fprintf(stderr, " y: %f\n", t->y);
fprintf(stderr, " touch_major: %f\n", t->touch_major);
fprintf(stderr, " touch_minor: %f\n", t->touch_minor);
fprintf(stderr, " width_major: %f\n", t->width_major);
fprintf(stderr, " width_minor: %f\n", t->width_minor);
fprintf(stderr, " angle: %f\n", t->orientation);
fprintf(stderr, " pressure: %f\n", t->pressure);
fprintf(stderr, " distance: %f\n", t->distance);
}
fprintf(stderr, "sync %d %ld %d %d %d %f %f\n",
frame->num_active,
frame->time,
frame->sequence_id,
frame->revision,
frame->slot_revision,
ev->root_x,
ev->root_y);
}
static void handle_event(struct frame_test *test, XEvent *ev)
{
XGenericEventCookie *gev = &ev->xcookie;
const struct utouch_frame *frame;
XConfigureEvent *cev;
XIDeviceEvent *dev;
switch(ev->type) {
case ConfigureNotify:
cev = (XConfigureEvent *)ev;
if (cev->window == XDefaultRootWindow(cev->display))
utouch_frame_configure_xi2(test->fh, cev);
break;
case GenericEvent:
if (!XGetEventData(test->display, gev))
break;
dev = gev->data;
/* null for some requests, quite odd */
dev->display = ev->xany.display;
if (gev->type == GenericEvent && gev->extension == opcode) {
frame = utouch_frame_pump_xi2(test->fh, dev);
if (frame)
report_frame(frame, dev);
}
XFreeEventData(test->display, gev);
break;
}
}
static void loop_device(struct frame_test *test)
{
XIEventMask mask;
mask.deviceid = XIAllDevices;
mask.mask_len = XIMaskLen(XI_TouchMotion);
mask.mask = calloc(mask.mask_len, sizeof(char));
XISetMask(mask.mask, XI_TouchBegin);
XISetMask(mask.mask, XI_TouchMotion);
XISetMask(mask.mask, XI_TouchEnd);
XISetMask(mask.mask, XI_PropertyEvent);
XISelectEvents(test->display, test->win, &mask, 1);
XSelectInput(test->display, test->root, StructureNotifyMask);
while (1) {
XEvent ev;
XNextEvent(test->display, &ev);
handle_event(test, &ev);
}
}
int main(int argc, char *argv[])
{
struct frame_test test;
int id;
if (argc < 2) {
fprintf(stderr, "Usage: %s \n", argv[0]);
return -1;
}
id = atoi(argv[1]);
if (init_xi2(&test, id)) {
fprintf(stderr, "error: could not describe device\n");
return -1;
}
if (!utouch_frame_is_supported_xi2(test.display, test.dev)) {
fprintf(stderr, "error: unsupported device\n");
return -1;
}
if (init_frame(&test)) {
fprintf(stderr, "error: could not init frame\n");
return -1;
}
report_device_caps(&test);
loop_device(&test);
destroy_all(&test);
return 0;
}