diff options
author | Peter Hutterer <peter.hutterer@who-t.net> | 2011-12-09 23:20:39 +1000 |
---|---|---|
committer | Peter Hutterer <peter.hutterer@who-t.net> | 2011-12-09 23:20:39 +1000 |
commit | a6e53fb5e224b29b7c44fe82f0b80b895078998c (patch) | |
tree | 5dc0bd40ca2dcbf7643a758975d508fca7a93e2d | |
parent | 5304220887d278157a72569f44721650d5d13cb3 (diff) |
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
-rw-r--r-- | multitouch.c | 167 |
1 files changed, 157 insertions, 10 deletions
diff --git a/multitouch.c b/multitouch.c index 5799a49..3d63079 100644 --- a/multitouch.c +++ b/multitouch.c @@ -22,13 +22,13 @@ #include <X11/extensions/XInput2.h> #define MAX_TOUCHES 10 -#define NWINDOWS 6 /* 6 windows on sidebar */ +#define NWINDOWS 8 /* windows on sidebar */ #define POINTER_TOUCHID 0xFFFFFFFF static void usage(void) { - printf("Usage: %s [--with-ownership|--pointer-events]\n", program_invocation_short_name); - printf(" Grey window: normal touch surface, with or without ownership (or pointer events)\n"); + printf("Usage: %s [--with-ownership|--pointer-events|--core-events]\n", program_invocation_short_name); + printf(" Grey window: normal touch surface, with or without ownership (or XI2 pointer/core events)\n"); printf(" Upper black bar left: grabs the touchpoint, no ownership, accepts\n"); printf(" Upper White bar left: grabs the touchpoint, no ownership, rejects\n"); printf(" Lower black bar left: grabs the touchpoint, with ownership, accepts\n"); @@ -38,7 +38,8 @@ static void usage(void) enum Mode { MODE_DEFAULT, /* touch events, no ownership */ MODE_OWNERSHIP, /* touch events, with ownership */ - MODE_POINTER, /* pointer events */ + MODE_POINTER, /* XI2 pointer events */ + MODE_CORE, /* core events */ }; enum TouchState { @@ -78,8 +79,10 @@ struct multitouch { Window whitebar; Window blackbar_os; /* with ownership */ Window whitebar_os; /* with ownership */ - Window whitebar_ptr; /* pointer grab async */ - Window blackbar_ptr; /* pointer grab sync + replay */ + Window whitebar_ptr; /* XI2 pointer grab async */ + Window blackbar_ptr; /* XI2 pointer grab sync + replay */ + Window whitebar_core; /* core grab async */ + Window blackbar_core; /* core grab sync + replay */ GC gc; Visual *visual; int xi_opcode; @@ -167,6 +170,10 @@ static void init_windows(struct multitouch *mt, enum Mode mode) yoff += h; mt->whitebar_ptr = XCreateSimpleWindow(mt->dpy, win, xoff, yoff, w, h, 0, 0, white); yoff += h; + mt->blackbar_core = XCreateSimpleWindow(mt->dpy, win, xoff, yoff, w, h, 0, 0, black); + yoff += h; + mt->whitebar_core = XCreateSimpleWindow(mt->dpy, win, xoff, yoff, w, h, 0, 0, white); + yoff += h; XSelectInput(mt->dpy, win, ExposureMask); XMapSubwindows(mt->dpy, win); @@ -184,15 +191,17 @@ static void init_windows(struct multitouch *mt, enum Mode mode) XISetMask(mask, XI_ButtonPress); XISetMask(mask, XI_Motion); XISetMask(mask, XI_ButtonRelease); - } else { + XISelectEvents(mt->dpy, win, &evmask, 1); + + } else if (mode == MODE_DEFAULT || mode == MODE_OWNERSHIP) { XISetMask(mask, XI_TouchBegin); XISetMask(mask, XI_TouchUpdate); XISetMask(mask, XI_TouchEnd); if (mode == MODE_OWNERSHIP) XISetMask(mask, XI_TouchOwnership); - } - - XISelectEvents(mt->dpy, win, &evmask, 1); + XISelectEvents(mt->dpy, win, &evmask, 1); + } else if (mode == MODE_CORE) + XSelectInput(mt->dpy, win, ButtonPressMask|PointerMotionMask|ButtonReleaseMask); memset(mask, 0, sizeof(mask)); XISetMask(mask, XI_TouchBegin); @@ -235,6 +244,16 @@ static void init_windows(struct multitouch *mt, enum Mode mode) &evmask, 1, &modifiers) != 0) error("Failed to establish button grab on whitebar_ptr\n"); + if (!XGrabButton(mt->dpy, 1, AnyModifier, mt->blackbar_core, False, + ButtonPressMask|PointerMotionMask|ButtonReleaseMask, + GrabModeAsync, GrabModeAsync, None, None)) + error("Failed to establish core grab on blackbar_core\n"); + + if (!XGrabButton(mt->dpy, 1, AnyModifier, mt->whitebar_core, False, + ButtonPressMask|PointerMotionMask|ButtonReleaseMask, + GrabModeSync, GrabModeSync, None, None)) + error("Failed to establish core grab on whitebar_core\n"); + XSync(mt->dpy, False); } @@ -314,6 +333,10 @@ static const char* window_to_name(struct multitouch *mt, Window win) windowname = "whitebar_ptr"; else if (win == mt->blackbar_ptr) windowname = "blackbar_ptr"; + else if (win == mt->whitebar_core) + windowname = "whitebar_core"; + else if (win == mt->blackbar_core) + windowname = "blackbar_core"; else if (win == mt->win) windowname = "window"; else @@ -360,6 +383,22 @@ static void print_event(struct multitouch *mt, XIDeviceEvent* event) } } +static void print_core_event(struct multitouch *mt, XButtonEvent *event) +{ + const char *type; + switch(event->type) + { + case ButtonPress: type = "ButtonPress"; break; + case ButtonRelease: type = "ButtonRelease"; break; + case MotionNotify: type = "MotionNotify"; break; + } + msg("Event: core %s\n", type); + msg("\t%d/%d (%d/%d)\n", event->x, event->y, event->x_root, event->y_root); + if (event->type == ButtonPress || event->type == ButtonRelease) + msg("\tbutton: %d\n", event->button); + msg("\ton %s\n", window_to_name(mt, event->window)); +} + static void paint_touch_begin(struct multitouch *mt, XIDeviceEvent *event) { int i; @@ -499,6 +538,14 @@ static void paint_grabs(struct multitouch *mt) { r = 0; g = 0.5; b = 0; offset = 5 * mt->height/NWINDOWS; + } else if (grab->grab_window == mt->blackbar_core) + { + r = 0; g = 0.3; b = 0.3; + offset = 6 * mt->height/NWINDOWS; + } else if (grab->grab_window == mt->whitebar_core) + { + r = 0.7; g = 0.8; b = 0.3; + offset = 7 * mt->height/NWINDOWS; } else error("invalid grab window: %#x\n", grab->grab_window); @@ -644,6 +691,98 @@ static void handle_grabbed_pointer_event(struct multitouch *mt, XIDeviceEvent *e } } +static void handle_grabbed_core_event(struct multitouch *mt, XButtonEvent *event) +{ + struct grabpoint *grab = NULL; + + if (event->type == ButtonPress) + { + grab = find_unused_grab(mt); + grab->state = TSTATE_BEGIN; + grab->touchid = POINTER_TOUCHID; + grab->startx = event->x; + grab->starty = event->y; + grab->grab_window = event->window; + grab->nevents = 0; + grab->flags = 0; + } else + grab = find_grab(mt, POINTER_TOUCHID); + + grab->x = event->x; + grab->y = event->y; + grab->nevents++; + + paint_grabs(mt); + expose(mt, 0, 0, mt->width, mt->height); + + if (event->type == MotionNotify) + grab->state = TSTATE_UPDATE; + else if (event->type == ButtonRelease) + grab->state = TSTATE_END; + + if (event->window == mt->whitebar_core) + { + msg("replay core\n"); + XAllowEvents(mt->dpy, ReplayPointer, CurrentTime); + grab->state = TSTATE_END; + } +} + +static void paint_core_event(struct multitouch *mt, XButtonEvent *event) +{ + const int xsize = 40; + + if (event->window == mt->blackbar_core || + event->window == mt->whitebar_core) + { + handle_grabbed_core_event(mt, event); + return; + } + + + if (event->type == MotionNotify) + { + if (!(event->state & Button1Mask)) + goto out; + } + + cairo_save(mt->cr); + cairo_set_source_rgba(mt->cr, 1, 0.3, 0.3, 1); + if (mt->last_x != -1 && mt->last_y != -1) + { + cairo_move_to(mt->cr, mt->last_x, mt->last_y); + cairo_line_to(mt->cr, event->x, event->y); + cairo_stroke(mt->cr); + expose(mt, mt->last_x, mt->last_y, event->x, event->y); + } + + if (event->type != MotionNotify) + { + if (event->type == ButtonPress) + { + cairo_move_to(mt->cr, event->x - xsize/2, event->y - xsize/2); + cairo_line_to(mt->cr, event->x + xsize/2, event->y + xsize/2); + cairo_move_to(mt->cr, event->x + xsize/2, event->y - xsize/2); + cairo_line_to(mt->cr, event->x - xsize/2, event->y + xsize/2); + } else { + cairo_move_to(mt->cr, event->x, event->y - xsize/2); + cairo_line_to(mt->cr, event->x, event->y + xsize/2); + cairo_move_to(mt->cr, event->x + xsize/2, event->y); + cairo_line_to(mt->cr, event->x - xsize/2, event->y); + } + cairo_stroke(mt->cr); + expose(mt, event->x - xsize/2, event->x - xsize/2, + event->x + xsize/2, event->x + xsize/2); + } + + cairo_restore(mt->cr); + + +out: + mt->last_x = event->x; + mt->last_y = event->y; +} + static void handle_ownership(struct multitouch *mt, XITouchOwnershipEvent *event) { @@ -839,6 +978,10 @@ static int main_loop(struct multitouch *mt) { print_event(mt, cookie->data); paint_event(mt, cookie->data); + } else if (ev.type >= ButtonPress && ev.type <= MotionNotify) + { + print_core_event(mt, &ev.xbutton); + paint_core_event(mt, &ev.xbutton); } XFreeEventData(mt->dpy, cookie); @@ -877,6 +1020,10 @@ int main(int argc, char **argv) { mode = MODE_POINTER; msg("pointer events selected\n"); + } else if (strcmp(argv[1], "--core-events") == 0) + { + mode = MODE_CORE; + msg("core events selected\n"); } } |