summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--multitouch.c167
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");
}
}