summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHenrik Rydberg <rydberg@euromail.se>2010-05-14 01:29:05 +0200
committerHenrik Rydberg <rydberg@euromail.se>2010-05-14 01:41:39 +0200
commitbfd266660d69e13263e3895fb059040b65255a72 (patch)
tree0ee0737f58307e345f9db2ebdd3de87e01febea6 /src
parent8ced3667a30e00bd2368d4b5417f1f07cc86d290 (diff)
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 <rydberg@euromail.se>
Diffstat (limited to 'src')
-rw-r--r--src/gestures.c174
-rw-r--r--src/memory.c159
-rw-r--r--src/memory.h24
-rw-r--r--src/mtouch.c4
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 @@
25 25
26#include "gestures.h" 26#include "gestures.h"
27 27
28#define DELTA_CUT(x) (0.2 * (x)) 28/**
29 29 * extract_buttons
30/* timer for cursor stability on finger touch/release */ 30 *
31static const int FINGER_ATTACK_MS = 70; 31 * Set the button gesture.
32static const int FINGER_DECAY_MS = 120; 32 *
33 33 * Reset memory after use.
34inline int dxval(const struct MTFinger *a, const struct MTFinger *b) 34 *
35{ 35 */
36 return a->hw.position_x - b->hw.position_x;
37}
38inline int dyval(const struct MTFinger *a, const struct MTFinger *b)
39{
40 return a->hw.position_y - b->hw.position_y;
41}
42
43static void extract_finger_configuration(struct Gestures *gs, struct MTouch* mt)
44{
45 const struct MTFinger *f = mt->state.finger;
46 int i, same = mt->state.nfinger == mt->prev_state.nfinger;
47 for (i = 0; i < mt->state.nfinger; i++)
48 same = same && find_finger(&mt->prev_state, f[i].id);
49 gs->same_fingers = same;
50}
51
52static void extract_pointers(struct Gestures *gs, struct MTouch* mt)
53{
54 const struct MTFinger *f = mt->state.finger;
55 int i;
56
57 if (mt->state.nfinger < 2) {
58 mt->mem.pointing = mt->state.nfinger;
59 mt->mem.ybar = mt->caps.abs_position_y.maximum;
60 return;
61 }
62
63 if (gs->same_fingers) {
64 for (i = 0; i < mt->state.nfinger; i++) {
65 if (GETBIT(mt->mem.pointing, i))
66 continue;
67 if (f[i].hw.position_y <= mt->mem.ybar) {
68 mt->mem.pointing = BITONES(mt->state.nfinger);
69 return;
70 }
71 }
72 return;
73 }
74
75 mt->mem.pointing = 0;
76 mt->mem.ybar = mt->caps.yclick;
77 for (i = 0; i < mt->state.nfinger; i++) {
78 if (f[i].hw.position_y > mt->caps.yclick)
79 continue;
80 if (!mt->mem.pointing || f[i].hw.position_y > mt->mem.ybar)
81 mt->mem.ybar = f[i].hw.position_y;
82 SETBIT(mt->mem.pointing, i);
83 }
84
85}
86
87static void extract_movement(struct Gestures *gs, struct MTouch* mt)
88{
89 const struct MTFinger *prev, *f = mt->state.finger;
90 int i, x = 0, y = 0;
91 int dx, dy, xcut, ycut, xmax = 0, ymax = 0;
92
93 mt->mem.moving = 0;
94
95 if (mt->state.nfinger == 0)
96 return;
97
98 if (!gs->same_fingers) {
99 mt->mem.move_time = mt->state.evtime;
100 if (mt->state.nfinger > mt->prev_state.nfinger)
101 mt->mem.move_time += FINGER_ATTACK_MS;
102 else
103 mt->mem.move_time += FINGER_DECAY_MS;
104 memset(mt->mem.dx, 0, sizeof(mt->mem.dx));
105 memset(mt->mem.dy, 0, sizeof(mt->mem.dy));
106 } else {
107 for (i = 0; i < mt->state.nfinger; i++) {
108 if (!GETBIT(mt->mem.pointing, i))
109 continue;
110 prev = find_finger(&mt->prev_state, f[i].id);
111 dx = dxval(&f[i], prev);
112 dy = dyval(&f[i], prev);
113 mt->mem.dx[i] += dx;
114 mt->mem.dy[i] += dy;
115 xmax = maxval(xmax, abs(mt->mem.dx[i]));
116 ymax = maxval(ymax, abs(mt->mem.dy[i]));
117 }
118 xcut = DELTA_CUT(xmax);
119 ycut = DELTA_CUT(ymax);
120 for (i = 0; i < mt->state.nfinger; i++) {
121 if (!GETBIT(mt->mem.pointing, i))
122 continue;
123 if (abs(mt->mem.dx[i]) > xcut ||
124 abs(mt->mem.dy[i]) > ycut)
125 SETBIT(mt->mem.moving, i);
126 }
127
128 /* accumulate all movement during delay */
129 if (mt->mem.moving && mt->state.evtime >= mt->mem.move_time) {
130 int nmove = bitcount(mt->mem.moving);
131 for (i = 0; i < mt->state.nfinger; i++) {
132 if (GETBIT(mt->mem.moving, i)) {
133 gs->dx += mt->mem.dx[i];
134 gs->dy += mt->mem.dy[i];
135 }
136 }
137 gs->dx /= nmove;
138 gs->dy /= nmove;
139 memset(mt->mem.dx, 0, sizeof(mt->mem.dx));
140 memset(mt->mem.dy, 0, sizeof(mt->mem.dy));
141 }
142 }
143}
144
145static void extract_buttons(struct Gestures *gs, struct MTouch* mt) 36static void extract_buttons(struct Gestures *gs, struct MTouch* mt)
146{ 37{
147 unsigned btdata = mt->state.button & BITONES(DIM_BUTTON); 38 unsigned btdata = mt->state.button & BITONES(DIM_BUTTON);
@@ -157,15 +48,35 @@ static void extract_buttons(struct Gestures *gs, struct MTouch* mt)
157 gs->btdata = btdata; 48 gs->btdata = btdata;
158 mt->mem.btdata = btdata; 49 mt->mem.btdata = btdata;
159 } 50 }
51 if (gs->btmask)
52 SETBIT(gs->type, GS_BUTTON);
160} 53}
161 54
162/******************************************************/ 55/**
163 56 * extract_movement
164static void extract_type(struct Gestures *gs, struct MTouch* mt) 57 *
58 * Set the movement gesture.
59 *
60 * Reset memory after use.
61 *
62 */
63static void extract_movement(struct Gestures *gs, struct MTouch* mt)
165{ 64{
166 int npoint = bitcount(mt->mem.pointing); 65 int npoint = bitcount(mt->mem.pointing);
167 if (gs->btmask) 66 int nmove = bitcount(mt->mem.moving);
168 SETBIT(gs->type, GS_BUTTON); 67 int i;
68 if (nmove && mt->state.evtime >= mt->mem.move_time) {
69 for (i = 0; i < mt->state.nfinger; i++) {
70 if (GETBIT(mt->mem.moving, i)) {
71 gs->dx += mt->mem.dx[i];
72 gs->dy += mt->mem.dy[i];
73 }
74 }
75 gs->dx /= nmove;
76 gs->dy /= nmove;
77 memset(mt->mem.dx, 0, sizeof(mt->mem.dx));
78 memset(mt->mem.dy, 0, sizeof(mt->mem.dy));
79 }
169 if (gs->dx || gs->dy) { 80 if (gs->dx || gs->dy) {
170 if (npoint == 1) 81 if (npoint == 1)
171 SETBIT(gs->type, GS_MOVE); 82 SETBIT(gs->type, GS_MOVE);
@@ -184,19 +95,20 @@ static void extract_type(struct Gestures *gs, struct MTouch* mt)
184 } 95 }
185} 96}
186 97
187/******************************************************/ 98/**
188 99 * extract_gestures
100 *
101 * Extract the gestures.
102 *
103 * Reset memory after use.
104 *
105 */
189void extract_gestures(struct Gestures *gs, struct MTouch* mt) 106void extract_gestures(struct Gestures *gs, struct MTouch* mt)
190{ 107{
191 memset(gs, 0, sizeof(struct Gestures)); 108 memset(gs, 0, sizeof(struct Gestures));
192 extract_finger_configuration(gs, mt); 109 gs->same_fingers = mt->mem.same;
193 extract_pointers(gs, mt);
194 extract_movement(gs, mt);
195 extract_buttons(gs, mt); 110 extract_buttons(gs, mt);
196 extract_type(gs, mt); 111 extract_movement(gs, mt);
197 mt->prev_state = mt->state; 112 mt->prev_state = mt->state;
198#if 0
199 output_memory(&mt->mem);
200#endif
201} 113}
202 114
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 @@
21 21
22#include "memory.h" 22#include "memory.h"
23 23
24/* fraction of max movement threshold */
25#define DELTA_CUT(x) (0.2 * (x))
26
27/* timer for cursor stability on finger touch/release */
28static const int FINGER_ATTACK_MS = 70;
29static const int FINGER_DECAY_MS = 120;
30
31static inline int dxval(const struct MTFinger *a, const struct MTFinger *b)
32{
33 return a->hw.position_x - b->hw.position_x;
34}
35static inline int dyval(const struct MTFinger *a, const struct MTFinger *b)
36{
37 return a->hw.position_y - b->hw.position_y;
38}
39
24void init_memory(struct Memory *mem) 40void init_memory(struct Memory *mem)
25{ 41{
26 memset(mem, 0, sizeof(struct Memory)); 42 memset(mem, 0, sizeof(struct Memory));
27} 43}
28 44
45/**
46 * update_configuration
47 *
48 * Update the same, fingers, added memory variables.
49 *
50 * Precondition: none
51 *
52 * Postcondition: same, fingers, added are set
53 *
54 */
55static void update_configuration(struct Memory *m,
56 const struct MTState *prev_state,
57 const struct MTState *state)
58{
59 const struct MTFinger *f = state->finger;
60 int i;
61 m->same = state->nfinger == prev_state->nfinger;
62 for (i = 0; i < state->nfinger; i++)
63 m->same = m->same && find_finger(prev_state, f[i].id);
64}
65
66/**
67 * update_pointers
68 *
69 * Update the pointing and ybar memory variables.
70 *
71 * Precondition: fingers, added are set
72 *
73 * Postcondition: pointing, ybar are set
74 *
75 */
76static void update_pointers(struct Memory *m,
77 const struct MTState *state,
78 const struct Capabilities *caps)
79{
80 const struct MTFinger *f = state->finger;
81 int i;
82
83 if (state->nfinger < 2) {
84 m->pointing = state->nfinger;
85 m->ybar = caps->abs_position_y.maximum;
86 return;
87 }
88
89 if (m->same) {
90 for (i = 0; i < state->nfinger; i++) {
91 if (GETBIT(m->pointing, i))
92 continue;
93 if (f[i].hw.position_y <= m->ybar) {
94 m->pointing = BITONES(state->nfinger);
95 return;
96 }
97 }
98 return;
99 }
100
101 m->pointing = 0;
102 m->ybar = caps->yclick;
103 for (i = 0; i < state->nfinger; i++) {
104 if (f[i].hw.position_y > caps->yclick)
105 continue;
106 if (!m->pointing || f[i].hw.position_y > m->ybar)
107 m->ybar = f[i].hw.position_y;
108 SETBIT(m->pointing, i);
109 }
110
111}
112
113/**
114 * update_movement
115 *
116 * Update the pending, moving, mvhold, mvforget, dx and dy memory variables.
117 *
118 * When moving is nonzero, gestures can be extracted from the dx and dy
119 * variables. These variables should be cleared after use.
120 *
121 * Precondition: fingers, added, pointing are set
122 *
123 * Postcondition: pending, moving, mvhold, mvforget, dx, dy are set
124 *
125 */
126static void update_movement(struct Memory *m,
127 const struct MTState *prev_state,
128 const struct MTState *state,
129 const struct Capabilities *caps)
130{
131 const struct MTFinger *prev, *f = state->finger;
132 int i, x = 0, y = 0;
133 int dx, dy, xcut, ycut, xmax = 0, ymax = 0;
134
135 m->pending = 0;
136 m->moving = 0;
137
138 if (state->nfinger == 0)
139 return;
140
141 if (!m->same) {
142 m->move_time = state->evtime;
143 if (state->nfinger > prev_state->nfinger)
144 m->move_time += FINGER_ATTACK_MS;
145 else
146 m->move_time += FINGER_DECAY_MS;
147 memset(m->dx, 0, sizeof(m->dx));
148 memset(m->dy, 0, sizeof(m->dy));
149 } else {
150 for (i = 0; i < state->nfinger; i++) {
151 if (!GETBIT(m->pointing, i))
152 continue;
153 prev = find_finger(prev_state, f[i].id);
154 dx = dxval(&f[i], prev);
155 dy = dyval(&f[i], prev);
156 m->dx[i] += dx;
157 m->dy[i] += dy;
158 xmax = maxval(xmax, abs(m->dx[i]));
159 ymax = maxval(ymax, abs(m->dy[i]));
160 }
161 xcut = DELTA_CUT(xmax);
162 ycut = DELTA_CUT(ymax);
163 for (i = 0; i < state->nfinger; i++) {
164 if (!GETBIT(m->pointing, i))
165 continue;
166 if (abs(m->dx[i]) > xcut ||
167 abs(m->dy[i]) > ycut)
168 SETBIT(m->pending, i);
169 }
170
171 /* accumulate all movement during delay */
172 if (m->pending && state->evtime >= m->move_time)
173 m->moving = m->pending;
174 }
175}
176
177void refresh_memory(struct Memory *m,
178 const struct MTState *prev_state,
179 const struct MTState *state,
180 const struct Capabilities *caps)
181{
182 update_configuration(m, prev_state, state);
183 update_pointers(m, state, caps);
184 update_movement(m, prev_state, state, caps);
185}
186
29void output_memory(const struct Memory *m) 187void output_memory(const struct Memory *m)
30{ 188{
31 int i; 189 int i;
32 xf86Msg(X_INFO, "btdata: %04x\n", m->btdata); 190 xf86Msg(X_INFO, "btdata: %04x\n", m->btdata);
33 xf86Msg(X_INFO, "pointing: %04x\n", m->pointing); 191 xf86Msg(X_INFO, "pointing: %04x\n", m->pointing);
192 xf86Msg(X_INFO, "pending: %04x\n", m->pending);
34 xf86Msg(X_INFO, "moving: %04x\n", m->moving); 193 xf86Msg(X_INFO, "moving: %04x\n", m->moving);
35 xf86Msg(X_INFO, "ybar: %d\n", m->ybar); 194 xf86Msg(X_INFO, "ybar: %d\n", m->ybar);
36 xf86Msg(X_INFO, "move_time: %lld\n", m->move_time); 195 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 @@
24 24
25#include "mtstate.h" 25#include "mtstate.h"
26 26
27/**
28 * struct Memory - parsing state
29 *
30 * @btdata: logical finger state
31 * @same: true if the finger configuration is unchanged
32 * @pointing: bitmask of pointing fingers
33 * @pending: bitmask of tentatively moving fingers
34 * @moving: bitmask of moving fingers
35 * @ybar: vertical position on pad marking the clicking area
36 * @move_time: movement before this point in time is accumulated
37 * @dx: array of accumulated horiontal movement per finger
38 * @dy: array of accumulated vertical movement per finger
39 *
40 */
27struct Memory { 41struct Memory {
28 unsigned btdata, pointing, moving; 42 unsigned btdata, same;
43 unsigned pointing, pending, moving;
29 int ybar; 44 int ybar;
30 mstime_t move_time; 45 mstime_t move_time;
31 int dx[DIM_FINGER], dy[DIM_FINGER]; 46 int dx[DIM_FINGER], dy[DIM_FINGER];
32
33
34
35}; 47};
36 48
37void init_memory(struct Memory *mem); 49void init_memory(struct Memory *mem);
50void refresh_memory(struct Memory *m,
51 const struct MTState *prev_state,
52 const struct MTState *state,
53 const struct Capabilities *caps);
38void output_memory(const struct Memory *m); 54void output_memory(const struct Memory *m);
39 55
40#endif 56#endif
diff --git a/src/mtouch.c b/src/mtouch.c
index 44b4376..ad077b7 100644
--- a/src/mtouch.c
+++ b/src/mtouch.c
@@ -66,4 +66,8 @@ void parse_event(struct MTouch *mt)
66#if 0 66#if 0
67 output_mtstate(&mt->state); 67 output_mtstate(&mt->state);
68#endif 68#endif
69 refresh_memory(&mt->mem, &mt->prev_state, &mt->state, &mt->caps);
70#if 0
71 output_memory(&mt->mem);
72#endif
69} 73}