diff options
Diffstat (limited to 'src/memory.c')
-rw-r--r-- | src/memory.c | 159 |
1 files changed, 159 insertions, 0 deletions
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); |