diff options
author | Peter Hutterer <peter.hutterer@who-t.net> | 2011-11-07 10:47:51 +1000 |
---|---|---|
committer | Peter Hutterer <peter.hutterer@who-t.net> | 2011-11-07 10:48:01 +1000 |
commit | 60021af70471857ca7418a116b838120019ef65d (patch) | |
tree | cceea654a93b6d5a02db056e4be111f35ca7e35c | |
parent | 9b69359671a33c4f8184f9c3206a0da9a8dff417 (diff) |
Draw a line from the grab start point to the current one.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
-rw-r--r-- | multitouch.c | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/multitouch.c b/multitouch.c index 232fbe6..1e44c86 100644 --- a/multitouch.c +++ b/multitouch.c @@ -32,6 +32,13 @@ struct touchpoint { double x, y; /* last recorded x/y position */ }; +struct grabpoint { + enum TouchState state; + uint32_t touchid; + double startx, starty; /* x/y of TouchBegin */ + double x, y; /* last recorded x/y position */ +}; + struct multitouch { Display *dpy; int screen_no; @@ -50,11 +57,16 @@ struct multitouch { cairo_t *cr; cairo_t *cr_win; + cairo_t *cr_grabs; cairo_surface_t *surface; cairo_surface_t *surface_win; + cairo_surface_t *surface_grabs; struct touchpoint touches[MAX_TOUCHES]; int ntouches; + + struct grabpoint grabs[MAX_TOUCHES]; + size_t ngrabs; }; static void expose(struct multitouch *mt, int x1, int y1, int x2, int y2); @@ -281,10 +293,65 @@ static void paint_touch_end(struct multitouch *mt, XIDeviceEvent *event) } +static void handle_grabbed_event(struct multitouch *mt, XIDeviceEvent *event) +{ + struct grabpoint *grab = NULL; + const int radius = 50; + + int i; + for (i = 0; i < mt->ngrabs; i++) + { + grab = &mt->grabs[i]; + if (event->evtype == XI_TouchBegin && grab->state == TSTATE_END) + { + grab->state = TSTATE_BEGIN; + grab->touchid = event->detail; + grab->startx = event->event_x; + grab->starty = event->event_y; + break; + } else if (event->evtype != XI_TouchBegin) { + if (grab->state != TSTATE_END && grab->touchid == event->detail) + break; + } + } + if (!grab) { + error("oops, touchpoint for %d (touchid %d) not found\n", + event->evtype, event->detail); + return; + } + + /* clear the whole area */ + cairo_save(mt->cr_grabs); + cairo_save(mt->cr_grabs); + cairo_set_operator(mt->cr_grabs, CAIRO_OPERATOR_CLEAR); + cairo_paint(mt->cr_grabs); + cairo_restore(mt->cr_grabs); + + /* draw starting circle */ + cairo_set_source_rgba(mt->cr_grabs, 0, 0, 1, 1); + cairo_arc(mt->cr_grabs, grab->startx, grab->starty, radius, 0, 2 * M_PI); + cairo_stroke(mt->cr_grabs); + + grab->x = event->event_x; + grab->y = event->event_y; + + /* draw line to current point */ + cairo_set_source_rgba(mt->cr_grabs, 0, 0, 1, 1); + cairo_move_to(mt->cr_grabs, grab->startx, grab->starty); + cairo_line_to(mt->cr_grabs, grab->x, grab->y); + cairo_stroke(mt->cr_grabs); + cairo_restore(mt->cr_grabs); + + expose(mt, grab->startx, grab->starty, grab->x, grab->y); +} + static void paint_event(struct multitouch *mt, XIDeviceEvent *event) { if (event->event == mt->toolbar) + { + handle_grabbed_event(mt, event); return; + } switch(event->evtype) { @@ -313,6 +380,21 @@ static int init_cairo(struct multitouch *mt) mt->cr_win = cr; + /* grab drawing backbuffer */ + surface = cairo_surface_create_similar(surface, + CAIRO_CONTENT_COLOR_ALPHA, + mt->width, mt->height); + if (!surface) + return error("Failed to create cairo surface\n"); + + mt->surface_grabs = surface; + + cr = cairo_create(surface); + if (!cr) + return error("Failed to create cairo context\n"); + + mt->cr_grabs = cr; + /* backbuffer */ surface = cairo_surface_create_similar(surface, CAIRO_CONTENT_COLOR_ALPHA, @@ -345,6 +427,12 @@ static void expose(struct multitouch *mt, int x1, int y1, int x2, int y2) { cairo_set_source_surface(mt->cr_win, mt->surface, 0, 0); cairo_paint(mt->cr_win); + + cairo_save(mt->cr_win); + cairo_set_source_surface(mt->cr_win, mt->surface_grabs, 0, 0); + cairo_mask_surface(mt->cr_win, mt->surface_grabs, 0, 0); + cairo_restore(mt->cr_win); + } static int main_loop(struct multitouch *mt) @@ -390,6 +478,7 @@ static void init(struct multitouch *mt) memset(mt, 0, sizeof(*mt)); mt->ntouches = MAX_TOUCHES; + mt->ngrabs = MAX_TOUCHES; } int main(int argc, char **argv) |