/** * @file utouch.cpp * @brief Public interface implementation for the uTouch compiz plugin. * * Copyright 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, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "utouch.h" COMPIZ_PLUGIN_20090315(utouch, UtouchVTable); bool UtouchVTable::init() { compLogMessage ("utouch", CompLogLevelInfo, "init"); return true; } UtouchScreen::UtouchScreen(CompScreen* s) : PluginClassHandler(s) , screen(s) { int ret, event, error; XIEventMask mask; ret = XQueryExtension(screen->dpy(), "XInputExtension", &opcode, &event, &error); compLogMessage ("utouch", CompLogLevelInfo, "ctor %d", ret); mask.deviceid = XIAllMasterDevices; mask.mask_len = XIMaskLen(XI_LASTEVENT); mask.mask = (unsigned char *)calloc(mask.mask_len, sizeof(char)); XISetMask(mask.mask, XI_TouchBegin); XISetMask(mask.mask, XI_TouchUpdate); XISetMask(mask.mask, XI_TouchEnd); XISetMask(mask.mask, XI_TouchOwnership); XISetMask(mask.mask, XI_TouchUpdateUnowned); XISetMask(mask.mask, XI_DeviceChanged); XISetMask(mask.mask, XI_PropertyEvent); //XISelectEvents(screen->dpy(), screen->root(), &mask, 1); XIGrabModifiers mods = { XIAnyModifier, 0 }; XIGrabTouchBegin(screen->dpy(), XIAllMasterDevices, screen->root(), False, &mask, 1, &mods); ScreenInterface::setHandler(screen); } UtouchScreen::~UtouchScreen() { for (dev_map::iterator p = devices.begin(); p != devices.end(); ++p) utouch_frame_delete_engine(p->second); devices.clear(); } utouch_frame_handle UtouchScreen::createDevice(int devid) const { utouch_frame_handle fh; XIDeviceInfo *info; int ndevices; info = XIQueryDevice(screen->dpy(), devid, &ndevices); if (!info) { compLogMessage ("utouch", CompLogLevelError, "no info for device: %d", devid); return 0; } fh = utouch_frame_new_engine(100, 32, 100); if (fh && utouch_frame_init_xi2(fh, screen->dpy(), info)) { compLogMessage ("utouch", CompLogLevelError, "bad device: %d", devid); utouch_frame_delete_engine(fh); fh = 0; } XIFreeDeviceInfo(info); return fh; } static void report_device_caps(const struct utouch_surface *s) { 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) { int i; for (i = 0; i < (int)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\n", frame->num_active, frame->time, frame->sequence_id, frame->revision, frame->slot_revision); } void UtouchScreen::handleDeviceEvent(const XIDeviceEvent *ev) { utouch_frame_handle fh; const struct utouch_frame *frame; switch(ev->evtype) { case XI_TouchOwnership: compLogMessage ("utouch", CompLogLevelInfo, "touch owner %d", ev->detail); XIAllowTouchEvents(ev->display, ev->sourceid, ev->detail, XITouchOwnerRejectContinue); compLogMessage ("utouch", CompLogLevelInfo, "rejected: %d %d %d %d", ev->evtype, ev->deviceid, ev->sourceid, ev->detail); break; case XI_TouchUpdateUnowned: compLogMessage ("utouch", CompLogLevelInfo, "touch motion unowned"); break; case XI_DeviceChanged: compLogMessage ("utouch", CompLogLevelInfo, "touch device changed"); break; case XI_PropertyEvent: compLogMessage ("utouch", CompLogLevelInfo, "touch property changed"); break; case XI_TouchBegin: case XI_TouchUpdate: case XI_TouchEnd: compLogMessage ("utouch", CompLogLevelInfo, "touch: %d %d %d %d", ev->evtype, ev->deviceid, ev->sourceid, ev->detail); fh = devices[ev->sourceid]; if (!fh) { fh = createDevice(ev->sourceid); if (!fh) return; compLogMessage ("utouch", CompLogLevelInfo, "new device: %d", ev->sourceid); report_device_caps(utouch_frame_get_surface(fh)); devices[ev->sourceid] = fh; } // update on property changes here? // update on device going away here? frame = utouch_frame_pump_xi2(fh, ev); if (frame) report_frame(frame); break; } } void UtouchScreen::handleEvent(XEvent *ev) { XGenericEventCookie *gev = &ev->xcookie; if (XGetEventData(screen->dpy(), gev)) { if (gev->type == GenericEvent && gev->extension == opcode) handleDeviceEvent((XIDeviceEvent *)gev->data); XFreeEventData(screen->dpy(), gev); } screen->handleEvent(ev); }