From d07c43f9f19dc0ee38aaf44947cfc396f437490e Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Tue, 3 Aug 2010 15:01:50 +0200 Subject: Introduce zoom, rotate and combo gestures Introduce grail_mask bit functions, and add new gestures as separate functions, referring to the same move model. Signed-off-by: Henrik Rydberg --- src/grail-inserter.c | 248 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 151 insertions(+), 97 deletions(-) (limited to 'src/grail-inserter.c') diff --git a/src/grail-inserter.c b/src/grail-inserter.c index b357e29..3927875 100644 --- a/src/grail-inserter.c +++ b/src/grail-inserter.c @@ -29,28 +29,6 @@ static const int MAX_GESTURE_ID = 0xfff; -int gin_init(struct grail *ge) -{ - struct gesture_inserter *x; - x = calloc(1, sizeof(*x)); - if (!x) - return -ENOMEM; - ge->gin = x; - return 0; -} - -void gin_destroy(struct grail *ge) -{ - free(ge->gin); - ge->gin = NULL; -} - -void gin_frame_begin(struct grail *ge, grail_time_t time) -{ - struct gesture_inserter *gin = ge->gin; - gin->time = time; -} - static void send_event(struct grail *ge, struct slot_state *s, const struct gesture_event *ev) { @@ -61,124 +39,200 @@ static void send_event(struct grail *ge, struct slot_state *s, gev.type = s->type; gev.id = s->id; gev.status = s->status; - gev.pos.x = s->x; - gev.pos.y = s->x; + gev.ntouch = ev->ntouch; + gev.nprop = ev->nprop; gev.time = ev->time; - memcpy(gev.prop, ev->prop, DIM_GRAIL_PROP * sizeof(gev.prop[0])); + gev.pos = ev->pos; + memcpy(gev.prop, ev->prop, ev->nprop * sizeof(grail_prop_t)); for (i = 0; i < s->nclient; i++) { gev.client_id = s->client_id[i]; ge->gesture(ge, &gev); } } -void gin_frame_end(struct grail *ge, grail_mask_t *filtered) +// todo: spanning tree for multi-user case +static void setup_new_gestures(struct grail *ge, + const struct touch_frame *frame) { struct gesture_inserter *gin = ge->gin; - struct gesture_event ev; - grail_mask_t span[DIM_SLOT_BYTES]; - int i, slot, spanned = 0; - memset(filtered, 0, DIM_EV_TYPE_BYTES); + grail_mask_t types[DIM_GRAIL_TYPE_BYTES]; + grail_mask_t span[DIM_TOUCH_BYTES]; + struct grail_client_info info[DIM_CLIENT]; + int i, j, nclient = 0; + int nfresh = grail_mask_count(gin->fresh, sizeof(gin->fresh)); + if (!nfresh) + return; + + memset(types, 0, sizeof(types)); memset(span, 0, sizeof(span)); - for (slot = 0; slot < DIM_SLOT; slot++) { - struct slot_state *s = &gin->state[slot]; - if (!grail_get_mask(gin->used, slot)) - continue; + + grail_mask_foreach(i, gin->fresh, sizeof(gin->fresh)) { + struct slot_state *s = &gin->state[i]; + grail_mask_set(types, s->type); + grail_mask_set_mask(span, s->span, sizeof(span)); + } + + if (ge->get_clients) { + struct grail_coord coord[DIM_CLIENT]; + int ncoord = 0; + grail_mask_foreach(i, span, sizeof(span)) { + const struct touch *t = &frame->touch[i]; + coord[ncoord].x = t->prop[TP_POS_X]; + coord[ncoord].y = t->prop[TP_POS_Y]; + ncoord++; + } + nclient = ge->get_clients(ge, info, DIM_CLIENT, + coord, ncoord, types, sizeof(types)); + } + + grail_mask_foreach(i, gin->fresh, sizeof(gin->fresh)) { + struct slot_state *s = &gin->state[i]; + s->nclient = 0; + for (j = 0; j < nclient; j++) { + if (!grail_mask_get(info[j].mask, s->type)) + continue; + s->client_id[s->nclient++] = info[j].id; + } + } + + memset(gin->fresh, 0, sizeof(gin->fresh)); +} + +int gin_init(struct grail *ge) +{ + struct gesture_inserter *gin; + int i; + gin = calloc(1, sizeof(*gin)); + if (!gin) + return -ENOMEM; + for (i = 0; i < DIM_INSTANCE; i++) + grail_mask_set(gin->unused, i); + ge->gin = gin; + return 0; +} + +void gin_destroy(struct grail *ge) +{ + free(ge->gin); + ge->gin = NULL; +} + +void gin_frame_begin(struct grail *ge, const struct touch_frame *frame) +{ + struct gesture_inserter *gin = ge->gin; + gin->time = frame->time; +} + +void gin_frame_end(struct grail *ge, + grail_mask_t *filtered, int max_filtered, + const struct touch_frame *frame) +{ + struct gesture_inserter *gin = ge->gin; + grail_mask_t span[DIM_INSTANCE_BYTES]; + int i, hold = 0, discard = 0; + + memset(filtered, 0, max_filtered); + memset(span, 0, sizeof(span)); + + setup_new_gestures(ge, frame); + + grail_mask_foreach(i, gin->used, sizeof(gin->used)) { + struct slot_state *s = &gin->state[i]; if (!s->nclient) - gin_gesture_discard(gin, slot); + continue; + if (s->priority > hold) + hold = s->priority; + if (s->status == GRAIL_STATUS_BEGIN) + continue; + if (s->priority > discard) + discard = s->priority; } - for (slot = 0; slot < DIM_SLOT; slot++) { - struct slot_state *s = &gin->state[slot]; - if (!grail_get_mask(gin->used, slot)) + + grail_mask_foreach(i, gin->used, sizeof(gin->used)) { + struct slot_state *s = &gin->state[i]; + if (!s->nclient || s->priority < discard) + gin_gesture_discard(gin, i); + } + + grail_mask_foreach(i, gin->used, sizeof(gin->used)) { + struct slot_state *s = &gin->state[i]; + struct gesture_event ev; + grail_mask_set_mask(span, s->span, sizeof(span)); + if (s->priority < hold) continue; - for (i = 0; i < DIM_SLOT_BYTES; i++) { - span[i] |= s->span[i]; - spanned += !!span[i]; - } while (!gebuf_empty(&s->buf)) { gebuf_get(&s->buf, &ev); send_event(ge, s, &ev); } - if (s->status == GRAIL_STATUS_BEGIN) - s->status = GRAIL_STATUS_UPDATE; } - if (spanned) - grail_set_mask(filtered, EV_ABS); + + grail_mask_foreach(i, gin->used, sizeof(gin->used)) { + struct slot_state *s = &gin->state[i]; + if (s->status == GRAIL_STATUS_END) + gin_gesture_discard(gin, i); + } + + if (grail_mask_count(span, sizeof(span))) + grail_mask_set(filtered, EV_ABS); } -int gin_gesture_begin(struct grail *ge, const struct touch_frame *frame, - int type, int x, int y, const grail_mask_t *span) +int gin_gesture_begin(struct grail *ge, int type, int priority, + const grail_mask_t *span, int nspan) { - struct grail_client_info info[DIM_CLIENT]; - struct grail_coord coord[DIM_CLIENT]; struct gesture_inserter *gin = ge->gin; struct slot_state *s; - int i, slot, nc, ncoord = 0; - for (slot = 0; slot < DIM_SLOT; slot++) - if (!grail_get_mask(gin->used, slot)) - break; - if (slot >= DIM_SLOT) + int geslot = grail_mask_get_first(gin->unused, sizeof(gin->unused)); + if (geslot < 0) return -1; - s = &gin->state[slot]; + s = &gin->state[geslot]; s->type = type; + s->priority = priority; s->id = gin->gestureid++ & MAX_GESTURE_ID; s->status = GRAIL_STATUS_BEGIN; - s->x = x; - s->y = y; s->nclient = 0; - if (ge->get_clients) { - grail_mask_t tps[DIM_GRAIL_TYPE_BYTES]; - memset(tps, 0, sizeof(tps)); - grail_set_mask(tps, type); - for (i = 0; i < DIM_SLOT; i++) { - const struct touch *t = &frame->touch[i]; - if (!grail_get_mask(span, i)) - continue; - coord[ncoord].x = t->prop[TP_POS_X]; - coord[ncoord].y = t->prop[TP_POS_Y]; - ncoord++; - } - nc = ge->get_clients(ge, info, DIM_CLIENT, coord, ncoord, tps); - for (i = 0; i < nc; i++) { - if (!grail_get_mask(info[i].mask, type)) - continue; - s->client_id[s->nclient] = info[i].id; - s->nclient++; - } - } - memcpy(s->span, span, sizeof(s->span)); + memcpy(s->span, span, nspan); gebuf_clear(&s->buf); - grail_set_mask(gin->used, slot); - return slot; + grail_mask_clear(gin->unused, geslot); + grail_mask_set(gin->fresh, geslot); + grail_mask_set(gin->used, geslot); + return geslot; } -void gin_gesture_end(struct gesture_inserter *gin, int slot) +void gin_gesture_end(struct gesture_inserter *gin, int geslot) { - struct slot_state *s = &gin->state[slot]; - s->status = GRAIL_STATUS_END; - grail_clear_mask(gin->used, slot); + gin->state[geslot].status = GRAIL_STATUS_END; } -void gin_gesture_discard(struct gesture_inserter *gin, int slot) +void gin_gesture_discard(struct gesture_inserter *gin, int geslot) { - struct slot_state *s = &gin->state[slot]; - gebuf_clear(&s->buf); - gin_gesture_end(gin, slot); + gebuf_clear(&gin->state[geslot].buf); + gin_gesture_end(gin, geslot); + grail_mask_clear(gin->used, geslot); + grail_mask_set(gin->unused, geslot); } -void gin_gesture_end_all(struct gesture_inserter *gin) +void gin_gesture_discard_type(struct gesture_inserter *gin, int type) { - int slot; - for (slot = 0; slot < DIM_SLOT; slot++) - gin_gesture_end(gin, slot); + int i; + grail_mask_foreach(i, gin->used, sizeof(gin->used)) + if (gin->state[i].type == type) + gin_gesture_discard(gin, i); } -void gin_gesture_event(struct gesture_inserter *gin, int slot, - const grail_prop_t *prop) +void gin_gesture_event(struct gesture_inserter *gin, int geslot, + float x, float y, int ntouch, + const grail_prop_t *prop, int nprop) { - struct slot_state *s = &gin->state[slot]; + struct slot_state *s = &gin->state[geslot]; struct gesture_event ev; + ev.ntouch = ntouch; + ev.nprop = nprop; ev.time = gin->time; - memcpy(ev.prop, prop, sizeof(ev.prop)); + ev.pos.x = x; + ev.pos.y = y; + memcpy(ev.prop, prop, nprop * sizeof(grail_prop_t)); + if (s->status == GRAIL_STATUS_BEGIN) + s->status = GRAIL_STATUS_UPDATE; gebuf_put(&s->buf, &ev); } -- cgit v1.2.3