summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHenrik Rydberg <rydberg@euromail.se>2010-08-07 18:28:29 +0200
committerHenrik Rydberg <rydberg@euromail.se>2010-08-07 18:28:29 +0200
commitee4a0c6821a1b79c3d18c6ef6d7ed6d37df74755 (patch)
tree6516f6f92f572a60eca0fe6a43bc93a7f9570a2c /src
parent5b1126b08faa91bbe26d89c63e5c514911088a0a (diff)
gesture: Improved tickle/active logic
Reorganize the mode model to use bitmasks for tickle and active, and refine the tickle logic for each gesture.
Diffstat (limited to 'src')
-rw-r--r--src/gestures-combo.c17
-rw-r--r--src/gestures-pan.c11
-rw-r--r--src/gestures-pinch.c11
-rw-r--r--src/gestures-rotate.c9
-rw-r--r--src/gestures-tapping.c6
-rw-r--r--src/grail-gestures.c134
-rw-r--r--src/grail-gestures.h12
7 files changed, 107 insertions, 93 deletions
diff --git a/src/gestures-combo.c b/src/gestures-combo.c
index 0f4dd7e..6ce6197 100644
--- a/src/gestures-combo.c
+++ b/src/gestures-combo.c
@@ -33,6 +33,8 @@ static const int getype[DIM_TOUCH + 1] = {
33 GRAIL_TYPE_COMBO5, 33 GRAIL_TYPE_COMBO5,
34}; 34};
35 35
36static const int fm_mask = 0x0f;
37
36int gru_combo(struct grail *ge, 38int gru_combo(struct grail *ge,
37 const struct touch_frame *frame) 39 const struct touch_frame *frame)
38{ 40{
@@ -40,6 +42,7 @@ int gru_combo(struct grail *ge,
40 struct combo_model *state = &gru->combo; 42 struct combo_model *state = &gru->combo;
41 struct move_model *move = &gru->move; 43 struct move_model *move = &gru->move;
42 grail_prop_t prop[DIM_GRAIL_PROP]; 44 grail_prop_t prop[DIM_GRAIL_PROP];
45 int mask = state->active ? (move->active & fm_mask) : fm_mask;
43 if (!move->multi) { 46 if (!move->multi) {
44 if (state->active) { 47 if (state->active) {
45 gru_end(ge, state->gid, move); 48 gru_end(ge, state->gid, move);
@@ -47,8 +50,7 @@ int gru_combo(struct grail *ge,
47 } 50 }
48 return 0; 51 return 0;
49 } 52 }
50 if (!move->x.tickle && !move->y.tickle && 53 if (!(move->tickle & mask))
51 !move->r.tickle && !move->a.tickle)
52 return 0; 54 return 0;
53 if (!state->active) { 55 if (!state->active) {
54 int type = getype[move->ntouch]; 56 int type = getype[move->ntouch];
@@ -57,13 +59,12 @@ int gru_combo(struct grail *ge,
57 state->gid = gin_gid_begin(ge, type, PRIO_GESTURE, frame); 59 state->gid = gin_gid_begin(ge, type, PRIO_GESTURE, frame);
58 state->active = 1; 60 state->active = 1;
59 } 61 }
60 if (!move->x.active && !move->y.active && 62 if (!(move->active & fm_mask))
61 !move->r.active && !move->a.active)
62 return 0; 63 return 0;
63 prop[0] = move->x.active ? move->x.delta : 0; 64 prop[0] = move->fm[FM_X].delta;
64 prop[1] = move->y.active ? move->y.delta : 0; 65 prop[1] = move->fm[FM_Y].delta;
65 prop[2] = move->r.active ? move->r.delta : 0; 66 prop[2] = move->fm[FM_R].delta;
66 prop[3] = move->a.active ? move->a.delta : 0; 67 prop[3] = move->fm[FM_A].delta;
67 gru_event(ge, state->gid, move, prop, 4); 68 gru_event(ge, state->gid, move, prop, 4);
68 return 1; 69 return 1;
69} 70}
diff --git a/src/gestures-pan.c b/src/gestures-pan.c
index 320a987..a023122 100644
--- a/src/gestures-pan.c
+++ b/src/gestures-pan.c
@@ -33,6 +33,8 @@ static const int getype[DIM_TOUCH + 1] = {
33 GRAIL_TYPE_HAND, 33 GRAIL_TYPE_HAND,
34}; 34};
35 35
36static const int fm_mask = 0x03;
37
36int gru_pan(struct grail *ge, 38int gru_pan(struct grail *ge,
37 const struct touch_frame *frame) 39 const struct touch_frame *frame)
38{ 40{
@@ -40,6 +42,7 @@ int gru_pan(struct grail *ge,
40 struct combo_model *state = &gru->pan; 42 struct combo_model *state = &gru->pan;
41 struct move_model *move = &gru->move; 43 struct move_model *move = &gru->move;
42 grail_prop_t prop[DIM_GRAIL_PROP]; 44 grail_prop_t prop[DIM_GRAIL_PROP];
45 int mask = state->active ? (move->active & fm_mask) : fm_mask;
43 if (!move->multi) { 46 if (!move->multi) {
44 if (state->active) { 47 if (state->active) {
45 gru_end(ge, state->gid, move); 48 gru_end(ge, state->gid, move);
@@ -47,7 +50,7 @@ int gru_pan(struct grail *ge,
47 } 50 }
48 return 0; 51 return 0;
49 } 52 }
50 if (!move->x.tickle && !move->y.tickle) 53 if (!(move->tickle & mask))
51 return 0; 54 return 0;
52 if (!state->active) { 55 if (!state->active) {
53 int type = getype[move->ntouch]; 56 int type = getype[move->ntouch];
@@ -56,10 +59,10 @@ int gru_pan(struct grail *ge,
56 state->gid = gin_gid_begin(ge, type, PRIO_GESTURE, frame); 59 state->gid = gin_gid_begin(ge, type, PRIO_GESTURE, frame);
57 state->active = 1; 60 state->active = 1;
58 } 61 }
59 if (!move->x.active && !move->y.active) 62 if (!(move->active & fm_mask))
60 return 0; 63 return 0;
61 prop[0] = move->x.active ? move->x.delta : 0; 64 prop[0] = move->fm[FM_X].delta;
62 prop[1] = move->y.active ? move->y.delta : 0; 65 prop[1] = move->fm[FM_Y].delta;
63 gru_event(ge, state->gid, move, prop, 2); 66 gru_event(ge, state->gid, move, prop, 2);
64 return 1; 67 return 1;
65} 68}
diff --git a/src/gestures-pinch.c b/src/gestures-pinch.c
index c0d6a17..358718d 100644
--- a/src/gestures-pinch.c
+++ b/src/gestures-pinch.c
@@ -33,6 +33,8 @@ static const int getype[DIM_TOUCH + 1] = {
33 GRAIL_TYPE_GRAB, 33 GRAIL_TYPE_GRAB,
34}; 34};
35 35
36static const int fm_mask = 0x04;
37
36int gru_pinch(struct grail *ge, 38int gru_pinch(struct grail *ge,
37 const struct touch_frame *frame) 39 const struct touch_frame *frame)
38{ 40{
@@ -40,6 +42,7 @@ int gru_pinch(struct grail *ge,
40 struct combo_model *state = &gru->pinch; 42 struct combo_model *state = &gru->pinch;
41 struct move_model *move = &gru->move; 43 struct move_model *move = &gru->move;
42 grail_prop_t prop[DIM_GRAIL_PROP]; 44 grail_prop_t prop[DIM_GRAIL_PROP];
45 int mask = state->active ? (move->active & fm_mask) : fm_mask;
43 if (!move->multi) { 46 if (!move->multi) {
44 if (state->active) { 47 if (state->active) {
45 gru_end(ge, state->gid, move); 48 gru_end(ge, state->gid, move);
@@ -47,9 +50,7 @@ int gru_pinch(struct grail *ge,
47 } 50 }
48 return 0; 51 return 0;
49 } 52 }
50 if (!move->a.tickle) 53 if (!(move->tickle & mask))
51 return 0;
52 if (!move->r.tickle)
53 return 0; 54 return 0;
54 if (!state->active) { 55 if (!state->active) {
55 int type = getype[move->ntouch]; 56 int type = getype[move->ntouch];
@@ -58,9 +59,9 @@ int gru_pinch(struct grail *ge,
58 state->gid = gin_gid_begin(ge, type, PRIO_GESTURE, frame); 59 state->gid = gin_gid_begin(ge, type, PRIO_GESTURE, frame);
59 state->active = 1; 60 state->active = 1;
60 } 61 }
61 if (!move->r.active) 62 if (!(move->active & fm_mask))
62 return 0; 63 return 0;
63 prop[0] = move->r.delta; 64 prop[0] = move->fm[FM_R].delta;
64 gru_event(ge, state->gid, move, prop, 1); 65 gru_event(ge, state->gid, move, prop, 1);
65 return 1; 66 return 1;
66} 67}
diff --git a/src/gestures-rotate.c b/src/gestures-rotate.c
index 105340b..5db4228 100644
--- a/src/gestures-rotate.c
+++ b/src/gestures-rotate.c
@@ -33,6 +33,8 @@ static const int getype[DIM_TOUCH + 1] = {
33 GRAIL_TYPE_REVOLVE, 33 GRAIL_TYPE_REVOLVE,
34}; 34};
35 35
36static const int fm_mask = 0x08;
37
36int gru_rotate(struct grail *ge, 38int gru_rotate(struct grail *ge,
37 const struct touch_frame *frame) 39 const struct touch_frame *frame)
38{ 40{
@@ -40,6 +42,7 @@ int gru_rotate(struct grail *ge,
40 struct combo_model *state = &gru->rotate; 42 struct combo_model *state = &gru->rotate;
41 struct move_model *move = &gru->move; 43 struct move_model *move = &gru->move;
42 grail_prop_t prop[DIM_GRAIL_PROP]; 44 grail_prop_t prop[DIM_GRAIL_PROP];
45 int mask = state->active ? (move->active & fm_mask) : fm_mask;
43 if (!move->multi) { 46 if (!move->multi) {
44 if (state->active) { 47 if (state->active) {
45 gru_end(ge, state->gid, move); 48 gru_end(ge, state->gid, move);
@@ -47,7 +50,7 @@ int gru_rotate(struct grail *ge,
47 } 50 }
48 return 0; 51 return 0;
49 } 52 }
50 if (!move->a.tickle) 53 if (!(move->tickle & mask))
51 return 0; 54 return 0;
52 if (!state->active) { 55 if (!state->active) {
53 int type = getype[move->ntouch]; 56 int type = getype[move->ntouch];
@@ -56,9 +59,9 @@ int gru_rotate(struct grail *ge,
56 state->gid = gin_gid_begin(ge, type, PRIO_GESTURE, frame); 59 state->gid = gin_gid_begin(ge, type, PRIO_GESTURE, frame);
57 state->active = 1; 60 state->active = 1;
58 } 61 }
59 if (!move->a.active) 62 if (!(move->active & fm_mask))
60 return 0; 63 return 0;
61 prop[0] = move->a.delta; 64 prop[0] = move->fm[FM_A].delta;
62 gru_event(ge, state->gid, move, prop, 1); 65 gru_event(ge, state->gid, move, prop, 1);
63 return 1; 66 return 1;
64} 67}
diff --git a/src/gestures-tapping.c b/src/gestures-tapping.c
index a5357e4..1a02731 100644
--- a/src/gestures-tapping.c
+++ b/src/gestures-tapping.c
@@ -30,6 +30,8 @@ static const int TAP_CANCEL = 2;
30static const int TAP_MIN_GAP_MS = 25; 30static const int TAP_MIN_GAP_MS = 25;
31static const int TAP_MAX_GAP_MS = 300; 31static const int TAP_MAX_GAP_MS = 300;
32 32
33static const int fm_mask = 0x03;
34
33int gru_tapping(struct grail *ge, 35int gru_tapping(struct grail *ge,
34 const struct touch_frame *frame) 36 const struct touch_frame *frame)
35{ 37{
@@ -69,7 +71,7 @@ int gru_tapping(struct grail *ge,
69 if (state->status == TAP_END && 71 if (state->status == TAP_END &&
70 move->time - state->start < TAP_MIN_GAP_MS) 72 move->time - state->start < TAP_MIN_GAP_MS)
71 state->status = TAP_CANCEL; 73 state->status = TAP_CANCEL;
72 if (move->x.active || move->y.active) 74 if (move->active & fm_mask)
73 state->status = TAP_CANCEL; 75 state->status = TAP_CANCEL;
74 if (state->status == TAP_CANCEL) { 76 if (state->status == TAP_CANCEL) {
75 if (state->active) { 77 if (state->active) {
@@ -84,7 +86,7 @@ int gru_tapping(struct grail *ge,
84 return 0; 86 return 0;
85 prop[0] = move->time - state->start; 87 prop[0] = move->time - state->start;
86 gin_gid_event(ge, state->gid, 88 gin_gid_event(ge, state->gid,
87 move->x.val, move->y.val, state->ntouch, 89 move->fm[FM_X].val, move->fm[FM_Y].val, state->ntouch,
88 prop, 1, GRAIL_STATUS_END); 90 prop, 1, GRAIL_STATUS_END);
89 state->status = TAP_BEGIN; 91 state->status = TAP_BEGIN;
90 state->ntouch = 0; 92 state->ntouch = 0;
diff --git a/src/grail-gestures.c b/src/grail-gestures.c
index 3c95d6f..67ceacf 100644
--- a/src/grail-gestures.c
+++ b/src/grail-gestures.c
@@ -23,12 +23,8 @@
23#include "grail-recognizer.h" 23#include "grail-recognizer.h"
24#include <math.h> 24#include <math.h>
25 25
26static const float SN_MOVE = 200; 26static const float FM_SN[DIM_FM] = { 200, 200, 200, 1000 };
27static const float SN_ZOOM = 200; 27static const float FM_BAR[DIM_FM] = { 50, 50, 40, 50 };
28static const float SN_ROTATE = 200;
29static const float BAR_MOVE = 4;
30static const float BAR_ZOOM = 12;
31static const float BAR_ROTATE = 12;
32 28
33static void compute_position(float *x, float *y, 29static void compute_position(float *x, float *y,
34 const struct touch_frame *frame) 30 const struct touch_frame *frame)
@@ -98,105 +94,107 @@ static float move_filter(const struct filter_model *m, float val)
98 return val; 94 return val;
99} 95}
100 96
101static int move_reset(struct filter_model *m, float val) 97static void move_reset(struct move_model *m, int i, float val)
102{ 98{
103 m->delta = 0; 99 struct filter_model *fm = &m->fm[i];
104 m->tickle = 0; 100 fm->delta = 0;
105 m->active = 0; 101 fm->val = val;
106 m->val = val; 102 fm->orig = val;
107 m->orig = val; 103 m->tickle &= ~(1 << i);
104 m->active &= ~(1 << i);
108} 105}
109 106
110static int move_update(struct filter_model *m, float val) 107static void move_update(struct move_model *m, int i, float val)
111{ 108{
112 float dval = val - m->orig; 109 struct filter_model *fm = &m->fm[i];
113 m->delta = val - m->val; 110 fm->delta = val - fm->val;
114 m->tickle = fabs(m->delta) > 0.5; 111 fm->val = val;
115 m->val = val; 112 if (fabs(fm->delta) > 0.5)
116 if (!m->active) { 113 m->tickle |= (1 << i);
117 if (fabs(dval) > m->bar) 114 else
118 m->active = 1; 115 m->tickle &= ~(1 << i);
119 else 116 if (m->active & (1 << i))
120 m->delta = dval; 117 return;
121 } 118 fm->delta = val - fm->orig;
122 return m->active; 119 if (fabs(fm->delta) > fm->bar)
120 m->active |= (1 << i);
121 else
122 fm->delta = 0;
123} 123}
124 124
125void gru_init_motion(struct grail *ge) 125void gru_init_motion(struct grail *ge)
126{ 126{
127 struct gesture_recognizer *gru = ge->gru; 127 struct gesture_recognizer *gru = ge->gru;
128 struct move_model *state = &gru->move; 128 struct move_model *m = &gru->move;
129 struct grail_coord min, max; 129 struct grail_coord min, max;
130 float D[DIM_FM];
131 int i;
130 grail_get_units(&min, &max, ge); 132 grail_get_units(&min, &max, ge);
131 float x = max.x - min.x; 133 D[FM_X] = max.x - min.x;
132 float y = max.y - min.y; 134 D[FM_Y] = max.y - min.y;
133 float r = sqrt(x * x + y * y); 135 D[FM_R] = sqrt(D[FM_X] * D[FM_X] + D[FM_Y] * D[FM_Y]);
134 state->x.fuzz = x / SN_MOVE; 136 D[FM_A] = D[FM_R];
135 state->y.fuzz = y / SN_MOVE; 137 for (i = 0; i < DIM_FM; i++) {
136 state->r.fuzz = r / SN_ZOOM; 138 m->fm[i].fuzz = D[i] / FM_SN[i];
137 state->a.fuzz = r / SN_ROTATE; 139 m->fm[i].bar = D[i] / FM_BAR[i];
138 state->x.bar = BAR_MOVE * state->x.fuzz; 140 }
139 state->y.bar = BAR_MOVE * state->y.fuzz;
140 state->r.bar = BAR_ZOOM * state->r.fuzz;
141 state->a.bar = BAR_ROTATE * state->a.fuzz;
142 state->multi = 0;
143} 141}
144 142
145void gru_motion(struct grail *ge, 143void gru_motion(struct grail *ge,
146 const struct touch_frame *frame) 144 const struct touch_frame *frame)
147{ 145{
148 struct gesture_recognizer *gru = ge->gru; 146 struct gesture_recognizer *gru = ge->gru;
149 struct move_model *state = &gru->move; 147 struct move_model *m = &gru->move;
150 float x, y, r, a; 148 float x, y, r, a;
151 compute_position(&x, &y, frame); 149 compute_position(&x, &y, frame);
152 if (frame->ncreate || frame->ndestroy) { 150 if (frame->ncreate || frame->ndestroy) {
153 r = compute_radius(x, y, frame); 151 r = compute_radius(x, y, frame);
154 a = 0; 152 a = 0;
155 move_reset(&state->x, x); 153 move_reset(m, FM_X, x);
156 move_reset(&state->y, y); 154 move_reset(m, FM_Y, y);
157 move_reset(&state->r, r); 155 move_reset(m, FM_R, r);
158 move_reset(&state->a, a); 156 move_reset(m, FM_A, a);
159 state->single = 0; 157 m->single = 0;
160 state->multi = 0; 158 m->multi = 0;
161 } else if (frame->nactive < 2) { 159 } else if (frame->nactive < 2) {
162 r = 0; 160 r = 0;
163 a = 0; 161 a = 0;
164 move_update(&state->x, x); 162 move_update(m, FM_X, x);
165 move_update(&state->y, y); 163 move_update(m, FM_Y, y);
166 move_reset(&state->r, r); 164 move_reset(m, FM_R, r);
167 move_reset(&state->a, a); 165 move_reset(m, FM_A, a);
168 state->single = 1; 166 m->single = 1;
169 state->multi = 0; 167 m->multi = 0;
170 } else { 168 } else {
171 x = move_filter(&state->x, x); 169 x = move_filter(&m->fm[FM_X], x);
172 y = move_filter(&state->y, y); 170 y = move_filter(&m->fm[FM_Y], y);
173 r = compute_radius(x, y, frame); 171 r = compute_radius(x, y, frame);
174 r = move_filter(&state->r, r); 172 r = move_filter(&m->fm[FM_R], r);
175 a = state->a.val + compute_rotation(x, y, r, &gru->frame, frame); 173 a = m->fm[FM_A].val;
176 //a = move_filter(&state->a, a); 174 a += compute_rotation(x, y, r, &gru->frame, frame);
177 move_update(&state->x, x); 175 a = move_filter(&m->fm[FM_A], a);
178 move_update(&state->y, y); 176 move_update(m, FM_X, x);
179 move_update(&state->r, r); 177 move_update(m, FM_Y, y);
180 move_update(&state->a, a); 178 move_update(m, FM_R, r);
181 state->single = 0; 179 move_update(m, FM_A, a);
182 state->multi = 1; 180 m->single = 0;
181 m->multi = 1;
183 } 182 }
184 state->ntouch = frame->nactive; 183 m->ntouch = frame->nactive;
185 state->time = frame->time; 184 m->time = frame->time;
186} 185}
187 186
188void gru_event(struct grail *ge, int gid, 187void gru_event(struct grail *ge, int gid,
189 const struct move_model *move, 188 const struct move_model *m,
190 const grail_prop_t *prop, int nprop) 189 const grail_prop_t *prop, int nprop)
191{ 190{
192 gin_gid_event(ge, gid, 191 gin_gid_event(ge, gid, m->fm[FM_X].val, m->fm[FM_Y].val, m->ntouch,
193 move->x.val, move->y.val, move->ntouch,
194 prop, nprop, 192 prop, nprop,
195 GRAIL_STATUS_UPDATE); 193 GRAIL_STATUS_UPDATE);
196} 194}
197 195
198void gru_end(struct grail *ge, int gid, const struct move_model *move) 196void gru_end(struct grail *ge, int gid, const struct move_model *m)
199{ 197{
200 gin_gid_end(ge, gid, move->x.val, move->y.val, move->ntouch); 198 gin_gid_end(ge, gid, m->fm[FM_X].val, m->fm[FM_Y].val, m->ntouch);
201} 199}
202 200
diff --git a/src/grail-gestures.h b/src/grail-gestures.h
index 6ba6cf7..3ace580 100644
--- a/src/grail-gestures.h
+++ b/src/grail-gestures.h
@@ -29,15 +29,21 @@
29#define PRIO_GESTURE 2 29#define PRIO_GESTURE 2
30#define PRIO_TAP 3 30#define PRIO_TAP 3
31 31
32#define DIM_FM 4
33
34#define FM_X 0
35#define FM_Y 1
36#define FM_R 2
37#define FM_A 3
38
32struct filter_model { 39struct filter_model {
33 float delta, val, orig, fuzz, bar; 40 float delta, val, orig, fuzz, bar;
34 int tickle, active;
35}; 41};
36 42
37struct move_model { 43struct move_model {
38 struct filter_model x, y, r, a; 44 struct filter_model fm[DIM_FM];
45 int tickle, active;
39 int single, multi, ntouch; 46 int single, multi, ntouch;
40 float dx, dy, dr, da;
41 grail_time_t time; 47 grail_time_t time;
42}; 48};
43 49