From bfd266660d69e13263e3895fb059040b65255a72 Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Fri, 14 May 2010 01:29:05 +0200 Subject: janitor: Split gesture code into memory refresh and parse Split the gesture code into a lexical part, which updates the filtered motion state, and a parsing part, which translates the motion state to gestures. Signed-off-by: Henrik Rydberg --- src/gestures.c | 174 ++++++++++++++------------------------------------------- src/memory.c | 159 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/memory.h | 24 ++++++-- src/mtouch.c | 4 ++ 4 files changed, 226 insertions(+), 135 deletions(-) diff --git a/src/gestures.c b/src/gestures.c index 9426226..f5244aa 100644 --- a/src/gestures.c +++ b/src/gestures.c @@ -25,123 +25,14 @@ #include "gestures.h" -#define DELTA_CUT(x) (0.2 * (x)) - -/* timer for cursor stability on finger touch/release */ -static const int FINGER_ATTACK_MS = 70; -static const int FINGER_DECAY_MS = 120; - -inline int dxval(const struct MTFinger *a, const struct MTFinger *b) -{ - return a->hw.position_x - b->hw.position_x; -} -inline int dyval(const struct MTFinger *a, const struct MTFinger *b) -{ - return a->hw.position_y - b->hw.position_y; -} - -static void extract_finger_configuration(struct Gestures *gs, struct MTouch* mt) -{ - const struct MTFinger *f = mt->state.finger; - int i, same = mt->state.nfinger == mt->prev_state.nfinger; - for (i = 0; i < mt->state.nfinger; i++) - same = same && find_finger(&mt->prev_state, f[i].id); - gs->same_fingers = same; -} - -static void extract_pointers(struct Gestures *gs, struct MTouch* mt) -{ - const struct MTFinger *f = mt->state.finger; - int i; - - if (mt->state.nfinger < 2) { - mt->mem.pointing = mt->state.nfinger; - mt->mem.ybar = mt->caps.abs_position_y.maximum; - return; - } - - if (gs->same_fingers) { - for (i = 0; i < mt->state.nfinger; i++) { - if (GETBIT(mt->mem.pointing, i)) - continue; - if (f[i].hw.position_y <= mt->mem.ybar) { - mt->mem.pointing = BITONES(mt->state.nfinger); - return; - } - } - return; - } - - mt->mem.pointing = 0; - mt->mem.ybar = mt->caps.yclick; - for (i = 0; i < mt->state.nfinger; i++) { - if (f[i].hw.position_y > mt->caps.yclick) - continue; - if (!mt->mem.pointing || f[i].hw.position_y > mt->mem.ybar) - mt->mem.ybar = f[i].hw.position_y; - SETBIT(mt->mem.pointing, i); - } - -} - -static void extract_movement(struct Gestures *gs, struct MTouch* mt) -{ - const struct MTFinger *prev, *f = mt->state.finger; - int i, x = 0, y = 0; - int dx, dy, xcut, ycut, xmax = 0, ymax = 0; - - mt->mem.moving = 0; - - if (mt->state.nfinger == 0) - return; - - if (!gs->same_fingers) { - mt->mem.move_time = mt->state.evtime; - if (mt->state.nfinger > mt->prev_state.nfinger) - mt->mem.move_time += FINGER_ATTACK_MS; - else - mt->mem.move_time += FINGER_DECAY_MS; - memset(mt->mem.dx, 0, sizeof(mt->mem.dx)); - memset(mt->mem.dy, 0, sizeof(mt->mem.dy)); - } else { - for (i = 0; i < mt->state.nfinger; i++) { - if (!GETBIT(mt->mem.pointing, i)) - continue; - prev = find_finger(&mt->prev_state, f[i].id); - dx = dxval(&f[i], prev); - dy = dyval(&f[i], prev); - mt->mem.dx[i] += dx; - mt->mem.dy[i] += dy; - xmax = maxval(xmax, abs(mt->mem.dx[i])); - ymax = maxval(ymax, abs(mt->mem.dy[i])); - } - xcut = DELTA_CUT(xmax); - ycut = DELTA_CUT(ymax); - for (i = 0; i < mt->state.nfinger; i++) { - if (!GETBIT(mt->mem.pointing, i)) - continue; - if (abs(mt->mem.dx[i]) > xcut || - abs(mt->mem.dy[i]) > ycut) - SETBIT(mt->mem.moving, i); - } - - /* accumulate all movement during delay */ - if (mt->mem.moving && mt->state.evtime >= mt->mem.move_time) { - int nmove = bitcount(mt->mem.moving); - for (i = 0; i < mt->state.nfinger; i++) { - if (GETBIT(mt->mem.moving, i)) { - gs->dx += mt->mem.dx[i]; - gs->dy += mt->mem.dy[i]; - } - } - gs->dx /= nmove; - gs->dy /= nmove; - memset(mt->mem.dx, 0, sizeof(mt->mem.dx)); - memset(mt->mem.dy, 0, sizeof(mt->mem.dy)); - } - } -} - +/** + * extract_buttons + * + * Set the button gesture. + * + * Reset memory after use. + * + */ static void extract_buttons(struct Gestures *gs, struct MTouch* mt) { unsigned btdata = mt->state.button & BITONES(DIM_BUTTON); @@ -157,15 +48,35 @@ static void extract_buttons(struct Gestures *gs, struct MTouch* mt) gs->btdata = btdata; mt->mem.btdata = btdata; } + if (gs->btmask) + SETBIT(gs->type, GS_BUTTON); } -/******************************************************/ - -static void extract_type(struct Gestures *gs, struct MTouch* mt) +/** + * extract_movement + * + * Set the movement gesture. + * + * Reset memory after use. + * + */ +static void extract_movement(struct Gestures *gs, struct MTouch* mt) { int npoint = bitcount(mt->mem.pointing); - if (gs->btmask) - SETBIT(gs->type, GS_BUTTON); + int nmove = bitcount(mt->mem.moving); + int i; + if (nmove && mt->state.evtime >= mt->mem.move_time) { + for (i = 0; i < mt->state.nfinger; i++) { + if (GETBIT(mt->mem.moving, i)) { + gs->dx += mt->mem.dx[i]; + gs->dy += mt->mem.dy[i]; + } + } + gs->dx /= nmove; + gs->dy /= nmove; + memset(mt->mem.dx, 0, sizeof(mt->mem.dx)); + memset(mt->mem.dy, 0, sizeof(mt->mem.dy)); + } if (gs->dx || gs->dy) { if (npoint == 1) SETBIT(gs->type, GS_MOVE); @@ -184,19 +95,20 @@ static void extract_type(struct Gestures *gs, struct MTouch* mt) } } -/******************************************************/ - +/** + * extract_gestures + * + * Extract the gestures. + * + * Reset memory after use. + * + */ void extract_gestures(struct Gestures *gs, struct MTouch* mt) { memset(gs, 0, sizeof(struct Gestures)); - extract_finger_configuration(gs, mt); - extract_pointers(gs, mt); - extract_movement(gs, mt); + gs->same_fingers = mt->mem.same; extract_buttons(gs, mt); - extract_type(gs, mt); + extract_movement(gs, mt); mt->prev_state = mt->state; -#if 0 - output_memory(&mt->mem); -#endif } diff --git a/src/memory.c b/src/memory.c index 0e2edba..a09eadb 100644 --- a/src/memory.c +++ b/src/memory.c @@ -21,16 +21,175 @@ #include "memory.h" +/* fraction of max movement threshold */ +#define DELTA_CUT(x) (0.2 * (x)) + +/* timer for cursor stability on finger touch/release */ +static const int FINGER_ATTACK_MS = 70; +static const int FINGER_DECAY_MS = 120; + +static inline int dxval(const struct MTFinger *a, const struct MTFinger *b) +{ + return a->hw.position_x - b->hw.position_x; +} +static inline int dyval(const struct MTFinger *a, const struct MTFinger *b) +{ + return a->hw.position_y - b->hw.position_y; +} + void init_memory(struct Memory *mem) { memset(mem, 0, sizeof(struct Memory)); } +/** + * update_configuration + * + * Update the same, fingers, added memory variables. + * + * Precondition: none + * + * Postcondition: same, fingers, added are set + * + */ +static void update_configuration(struct Memory *m, + const struct MTState *prev_state, + const struct MTState *state) +{ + const struct MTFinger *f = state->finger; + int i; + m->same = state->nfinger == prev_state->nfinger; + for (i = 0; i < state->nfinger; i++) + m->same = m->same && find_finger(prev_state, f[i].id); +} + +/** + * update_pointers + * + * Update the pointing and ybar memory variables. + * + * Precondition: fingers, added are set + * + * Postcondition: pointing, ybar are set + * + */ +static void update_pointers(struct Memory *m, + const struct MTState *state, + const struct Capabilities *caps) +{ + const struct MTFinger *f = state->finger; + int i; + + if (state->nfinger < 2) { + m->pointing = state->nfinger; + m->ybar = caps->abs_position_y.maximum; + return; + } + + if (m->same) { + for (i = 0; i < state->nfinger; i++) { + if (GETBIT(m->pointing, i)) + continue; + if (f[i].hw.position_y <= m->ybar) { + m->pointing = BITONES(state->nfinger); + return; + } + } + return; + } + + m->pointing = 0; + m->ybar = caps->yclick; + for (i = 0; i < state->nfinger; i++) { + if (f[i].hw.position_y > caps->yclick) + continue; + if (!m->pointing || f[i].hw.position_y > m->ybar) + m->ybar = f[i].hw.position_y; + SETBIT(m->pointing, i); + } + +} + +/** + * update_movement + * + * Update the pending, moving, mvhold, mvforget, dx and dy memory variables. + * + * When moving is nonzero, gestures can be extracted from the dx and dy + * variables. These variables should be cleared after use. + * + * Precondition: fingers, added, pointing are set + * + * Postcondition: pending, moving, mvhold, mvforget, dx, dy are set + * + */ +static void update_movement(struct Memory *m, + const struct MTState *prev_state, + const struct MTState *state, + const struct Capabilities *caps) +{ + const struct MTFinger *prev, *f = state->finger; + int i, x = 0, y = 0; + int dx, dy, xcut, ycut, xmax = 0, ymax = 0; + + m->pending = 0; + m->moving = 0; + + if (state->nfinger == 0) + return; + + if (!m->same) { + m->move_time = state->evtime; + if (state->nfinger > prev_state->nfinger) + m->move_time += FINGER_ATTACK_MS; + else + m->move_time += FINGER_DECAY_MS; + memset(m->dx, 0, sizeof(m->dx)); + memset(m->dy, 0, sizeof(m->dy)); + } else { + for (i = 0; i < state->nfinger; i++) { + if (!GETBIT(m->pointing, i)) + continue; + prev = find_finger(prev_state, f[i].id); + dx = dxval(&f[i], prev); + dy = dyval(&f[i], prev); + m->dx[i] += dx; + m->dy[i] += dy; + xmax = maxval(xmax, abs(m->dx[i])); + ymax = maxval(ymax, abs(m->dy[i])); + } + xcut = DELTA_CUT(xmax); + ycut = DELTA_CUT(ymax); + for (i = 0; i < state->nfinger; i++) { + if (!GETBIT(m->pointing, i)) + continue; + if (abs(m->dx[i]) > xcut || + abs(m->dy[i]) > ycut) + SETBIT(m->pending, i); + } + + /* accumulate all movement during delay */ + if (m->pending && state->evtime >= m->move_time) + m->moving = m->pending; + } +} + +void refresh_memory(struct Memory *m, + const struct MTState *prev_state, + const struct MTState *state, + const struct Capabilities *caps) +{ + update_configuration(m, prev_state, state); + update_pointers(m, state, caps); + update_movement(m, prev_state, state, caps); +} + void output_memory(const struct Memory *m) { int i; xf86Msg(X_INFO, "btdata: %04x\n", m->btdata); xf86Msg(X_INFO, "pointing: %04x\n", m->pointing); + xf86Msg(X_INFO, "pending: %04x\n", m->pending); xf86Msg(X_INFO, "moving: %04x\n", m->moving); xf86Msg(X_INFO, "ybar: %d\n", m->ybar); xf86Msg(X_INFO, "move_time: %lld\n", m->move_time); diff --git a/src/memory.h b/src/memory.h index 23d2ce6..9810b81 100644 --- a/src/memory.h +++ b/src/memory.h @@ -24,17 +24,33 @@ #include "mtstate.h" +/** + * struct Memory - parsing state + * + * @btdata: logical finger state + * @same: true if the finger configuration is unchanged + * @pointing: bitmask of pointing fingers + * @pending: bitmask of tentatively moving fingers + * @moving: bitmask of moving fingers + * @ybar: vertical position on pad marking the clicking area + * @move_time: movement before this point in time is accumulated + * @dx: array of accumulated horiontal movement per finger + * @dy: array of accumulated vertical movement per finger + * + */ struct Memory { - unsigned btdata, pointing, moving; + unsigned btdata, same; + unsigned pointing, pending, moving; int ybar; mstime_t move_time; int dx[DIM_FINGER], dy[DIM_FINGER]; - - - }; void init_memory(struct Memory *mem); +void refresh_memory(struct Memory *m, + const struct MTState *prev_state, + const struct MTState *state, + const struct Capabilities *caps); void output_memory(const struct Memory *m); #endif diff --git a/src/mtouch.c b/src/mtouch.c index 44b4376..ad077b7 100644 --- a/src/mtouch.c +++ b/src/mtouch.c @@ -65,5 +65,9 @@ void parse_event(struct MTouch *mt) extract_mtstate(&mt->state, &mt->hs, &mt->caps); #if 0 output_mtstate(&mt->state); +#endif + refresh_memory(&mt->mem, &mt->prev_state, &mt->state, &mt->caps); +#if 0 + output_memory(&mt->mem); #endif } -- cgit v1.2.3