From 91c364d87b88a89dc991f9effbf4d537ca19192a Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Tue, 15 Feb 2011 18:56:17 +0100 Subject: Optional XI2.1 support This patch adds XI2.1 support to mtview. Several instances of the the program can be open simultaneously, each one being a window into the device, which is mapped onto the whole screen. On a touchscreen, paiting can occur simultaneously in each window. The device mapping is automatically modified in multi-head setups, and xinput set-prop can be used to map the device to a portion of the screen. Thanks to Chase Douglas for fixing this. Signed-off-by: Henrik Rydberg --- tools/mtview.c | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 116 insertions(+), 1 deletion(-) (limited to 'tools/mtview.c') diff --git a/tools/mtview.c b/tools/mtview.c index 7d6fdc6..1096070 100644 --- a/tools/mtview.c +++ b/tools/mtview.c @@ -1,7 +1,11 @@ +#include "config.h" #include #include #include #include +#if HAVE_XI +#include +#endif #include #include #include @@ -236,6 +240,114 @@ static int run_mtdev(const char *name) return 0; } +#if HAVE_XI +static void handle_event_xi2(struct windata *w, + utouch_frame_handle fh, + XEvent *ev) +{ + XConfigureEvent *cev = (XConfigureEvent *)ev; + XGenericEventCookie *gev = &ev->xcookie; + const struct utouch_frame *frame; + + switch(ev->type) { + case ConfigureNotify: + if (cev->window == XDefaultRootWindow(cev->display)) { + utouch_frame_configure_xi2(fh, cev); + } else { + w->off_x = cev->x; + w->off_y = cev->y; + } + break; + case GenericEvent: + if (!XGetEventData(w->dsp, gev)) + break; + if (gev->type == GenericEvent && gev->extension == opcode) { + frame = utouch_frame_pump_xi2(fh, gev->data); + if (frame) + report_frame(fh, frame, w); + } + XFreeEventData(w->dsp, gev); + break; + } +} + +static void run_window_xi2(struct windata *w, + utouch_frame_handle fh, + XIDeviceInfo *dev) +{ + const struct utouch_frame *frame; + XIEventMask mask; + + fprintf(stderr, "xi2 running\n"); + + XSelectInput(w->dsp, w->win, StructureNotifyMask); + XSelectInput(w->dsp, XDefaultRootWindow(w->dsp), StructureNotifyMask); + + mask.deviceid = dev->deviceid; + mask.mask_len = XIMaskLen(XI_TouchMotion); + mask.mask = calloc(mask.mask_len, sizeof(char)); + + XISetMask(mask.mask, XI_PropertyEvent); + XISetMask(mask.mask, XI_TouchBegin); + XISetMask(mask.mask, XI_TouchMotion); + XISetMask(mask.mask, XI_TouchEnd); + XISelectEvents(w->dsp, w->win, &mask, 1); + + while (1) { + XEvent ev; + XNextEvent(w->dsp, &ev); + handle_event_xi2(w, fh, &ev); + } +} + +static int run_xi2(int id) +{ + struct windata w; + XIDeviceInfo *info, *dev; + utouch_frame_handle fh; + int ndevice; + int i; + + if (init_window(&w)) { + fprintf(stderr, "error: could not init window\n"); + return -1; + } + + info = XIQueryDevice(w.dsp, XIAllDevices, &ndevice); + dev = 0; + for (i = 0; i < ndevice; i++) + if (info[i].deviceid == id) + dev = &info[i]; + if (!dev) + return -1; + + if (!utouch_frame_is_supported_xi2(w.dsp, dev)) { + fprintf(stderr, "error: unsupported device\n"); + return -1; + } + + fh = utouch_frame_new_engine(100, 32, 100); + if (!fh || utouch_frame_init_xi2(fh, w.dsp, dev)) { + fprintf(stderr, "error: could not init frame\n"); + return -1; + } + + run_window_xi2(&w, fh, dev); + + utouch_frame_delete_engine(fh); + XIFreeDeviceInfo(info); + term_window(&w); + + return 0; +} +#else +static int run_xi2(int id) +{ + fprintf(stderr, "XI2.1 not supported\n"); + return 0; +} +#endif + int main(int argc, char *argv[]) { int id, ret; @@ -246,7 +358,10 @@ int main(int argc, char *argv[]) } id = atoi(argv[1]); - ret = run_mtdev(argv[1]); + if (id) + ret = run_xi2(id); + else + ret = run_mtdev(argv[1]); return ret; } -- cgit v1.2.3