summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gestures-drag.c34
-rw-r--r--src/gestures-pinch.c16
-rw-r--r--src/gestures-rotate.c16
-rw-r--r--src/gestures-tapping.c2
-rw-r--r--src/grail-gestures.c60
-rw-r--r--src/grail-gestures.h8
-rw-r--r--src/grail-inserter.c6
-rw-r--r--src/grail-inserter.h3
8 files changed, 98 insertions, 47 deletions
diff --git a/src/gestures-drag.c b/src/gestures-drag.c
index 3f21041..a02943e 100644
--- a/src/gestures-drag.c
+++ b/src/gestures-drag.c
@@ -33,6 +33,22 @@ static const int getype[DIM_TOUCH + 1] = {
33 GRAIL_TYPE_DRAG5, 33 GRAIL_TYPE_DRAG5,
34}; 34};
35 35
36static void set_props(struct combo_model *s, const struct move_model *m)
37{
38 if (m->single) {
39 s->prop[GRAIL_PROP_DRAG_DX] = m->fm[FM_X].raw_delta;
40 s->prop[GRAIL_PROP_DRAG_DY] = m->fm[FM_Y].raw_delta;
41 } else {
42 s->prop[GRAIL_PROP_DRAG_DX] = m->fm[FM_X].action_delta;
43 s->prop[GRAIL_PROP_DRAG_DY] = m->fm[FM_Y].action_delta;
44 }
45 s->prop[GRAIL_PROP_DRAG_VX] = m->fm[FM_X].velocity;
46 s->prop[GRAIL_PROP_DRAG_VY] = m->fm[FM_Y].velocity;
47 s->prop[GRAIL_PROP_DRAG_X] = m->fm[FM_X].value;
48 s->prop[GRAIL_PROP_DRAG_Y] = m->fm[FM_Y].value;
49 s->nprop = 6;
50}
51
36static const int fm_mask = 0x03; 52static const int fm_mask = 0x03;
37 53
38int gru_drag(struct grail *ge, 54int gru_drag(struct grail *ge,
@@ -41,11 +57,11 @@ int gru_drag(struct grail *ge,
41 struct gesture_recognizer *gru = ge->gru; 57 struct gesture_recognizer *gru = ge->gru;
42 struct combo_model *state = &gru->drag; 58 struct combo_model *state = &gru->drag;
43 struct move_model *move = &gru->move; 59 struct move_model *move = &gru->move;
44 grail_prop_t prop[DIM_GRAIL_PROP];
45 int mask = state->active ? (move->active & fm_mask) : fm_mask; 60 int mask = state->active ? (move->active & fm_mask) : fm_mask;
46 if (!move->multi && (!gru->pointer_gesture || !move->single)) { 61 if (!move->multi && (!gru->pointer_gesture || !move->single)) {
47 if (state->active) { 62 if (state->active) {
48 gru_end(ge, state->gid, move); 63 gru_end(ge, state->gid, move,
64 state->prop, state->nprop);
49 state->active = 0; 65 state->active = 0;
50 } 66 }
51 return 0; 67 return 0;
@@ -59,16 +75,10 @@ int gru_drag(struct grail *ge,
59 state->gid = gin_gid_begin(ge, type, PRIO_GESTURE, frame); 75 state->gid = gin_gid_begin(ge, type, PRIO_GESTURE, frame);
60 state->active = 1; 76 state->active = 1;
61 } 77 }
62 if (move->single) { 78 if (!move->single && !(move->active & fm_mask))
63 prop[0] = move->fm[FM_X].raw_delta; 79 return 0;
64 prop[1] = move->fm[FM_Y].raw_delta; 80 set_props(state, move);
65 } else { 81 gru_event(ge, state->gid, move, state->prop, state->nprop);
66 if (!(move->active & fm_mask))
67 return 0;
68 prop[0] = move->fm[FM_X].action_delta;
69 prop[1] = move->fm[FM_Y].action_delta;
70 }
71 gru_event(ge, state->gid, move, prop, 2);
72 return 1; 82 return 1;
73} 83}
74 84
diff --git a/src/gestures-pinch.c b/src/gestures-pinch.c
index 3b94a66..18007de 100644
--- a/src/gestures-pinch.c
+++ b/src/gestures-pinch.c
@@ -35,17 +35,25 @@ static const int getype[DIM_TOUCH + 1] = {
35 35
36static const int fm_mask = 0x04; 36static const int fm_mask = 0x04;
37 37
38static void set_props(struct combo_model *s, const struct move_model *m)
39{
40 s->prop[GRAIL_PROP_PINCH_DR] = m->fm[FM_R].action_delta;
41 s->prop[GRAIL_PROP_PINCH_VR] = m->fm[FM_R].velocity;
42 s->prop[GRAIL_PROP_PINCH_R] = m->fm[FM_R].value;
43 s->nprop = 3;
44}
45
38int gru_pinch(struct grail *ge, 46int gru_pinch(struct grail *ge,
39 const struct touch_frame *frame) 47 const struct touch_frame *frame)
40{ 48{
41 struct gesture_recognizer *gru = ge->gru; 49 struct gesture_recognizer *gru = ge->gru;
42 struct combo_model *state = &gru->pinch; 50 struct combo_model *state = &gru->pinch;
43 struct move_model *move = &gru->move; 51 struct move_model *move = &gru->move;
44 grail_prop_t prop[DIM_GRAIL_PROP];
45 int mask = state->active ? (move->active & fm_mask) : fm_mask; 52 int mask = state->active ? (move->active & fm_mask) : fm_mask;
46 if (!move->multi) { 53 if (!move->multi) {
47 if (state->active) { 54 if (state->active) {
48 gru_end(ge, state->gid, move); 55 gru_end(ge, state->gid, move,
56 state->prop, state->nprop);
49 state->active = 0; 57 state->active = 0;
50 } 58 }
51 return 0; 59 return 0;
@@ -61,7 +69,7 @@ int gru_pinch(struct grail *ge,
61 } 69 }
62 if (!(move->active & fm_mask)) 70 if (!(move->active & fm_mask))
63 return 0; 71 return 0;
64 prop[0] = move->fm[FM_R].action_delta; 72 set_props(state, move);
65 gru_event(ge, state->gid, move, prop, 1); 73 gru_event(ge, state->gid, move, state->prop, state->nprop);
66 return 1; 74 return 1;
67} 75}
diff --git a/src/gestures-rotate.c b/src/gestures-rotate.c
index ebab6d3..52b5004 100644
--- a/src/gestures-rotate.c
+++ b/src/gestures-rotate.c
@@ -35,17 +35,25 @@ static const int getype[DIM_TOUCH + 1] = {
35 35
36static const int fm_mask = 0x08; 36static const int fm_mask = 0x08;
37 37
38static void set_props(struct combo_model *s, const struct move_model *m)
39{
40 s->prop[GRAIL_PROP_ROTATE_DA] = m->fm[FM_A].action_delta;
41 s->prop[GRAIL_PROP_ROTATE_VA] = m->fm[FM_A].velocity;
42 s->prop[GRAIL_PROP_ROTATE_A] = m->fm[FM_A].value;
43 s->nprop = 3;
44}
45
38int gru_rotate(struct grail *ge, 46int gru_rotate(struct grail *ge,
39 const struct touch_frame *frame) 47 const struct touch_frame *frame)
40{ 48{
41 struct gesture_recognizer *gru = ge->gru; 49 struct gesture_recognizer *gru = ge->gru;
42 struct combo_model *state = &gru->rotate; 50 struct combo_model *state = &gru->rotate;
43 struct move_model *move = &gru->move; 51 struct move_model *move = &gru->move;
44 grail_prop_t prop[DIM_GRAIL_PROP];
45 int mask = state->active ? (move->active & fm_mask) : fm_mask; 52 int mask = state->active ? (move->active & fm_mask) : fm_mask;
46 if (!move->multi) { 53 if (!move->multi) {
47 if (state->active) { 54 if (state->active) {
48 gru_end(ge, state->gid, move); 55 gru_end(ge, state->gid, move,
56 state->prop, state->nprop);
49 state->active = 0; 57 state->active = 0;
50 } 58 }
51 return 0; 59 return 0;
@@ -61,7 +69,7 @@ int gru_rotate(struct grail *ge,
61 } 69 }
62 if (!(move->active & fm_mask)) 70 if (!(move->active & fm_mask))
63 return 0; 71 return 0;
64 prop[0] = move->fm[FM_A].action_delta; 72 set_props(state, move);
65 gru_event(ge, state->gid, move, prop, 1); 73 gru_event(ge, state->gid, move, state->prop, state->nprop);
66 return 1; 74 return 1;
67} 75}
diff --git a/src/gestures-tapping.c b/src/gestures-tapping.c
index ab86c0f..d8a580f 100644
--- a/src/gestures-tapping.c
+++ b/src/gestures-tapping.c
@@ -84,7 +84,7 @@ int gru_tapping(struct grail *ge,
84 if (state->status != TAP_END || 84 if (state->status != TAP_END ||
85 move->time - state->start < TAP_MIN_GAP_MS) 85 move->time - state->start < TAP_MIN_GAP_MS)
86 return 0; 86 return 0;
87 prop[0] = move->time - state->start; 87 prop[GRAIL_PROP_TAP_DT] = move->time - state->start;
88 gin_gid_event(ge, state->gid, 88 gin_gid_event(ge, state->gid,
89 move->fm[FM_X].value, move->fm[FM_Y].value, state->ntouch, 89 move->fm[FM_X].value, move->fm[FM_Y].value, state->ntouch,
90 prop, 1, 1); 90 prop, 1, 1);
diff --git a/src/grail-gestures.c b/src/grail-gestures.c
index 04ff976..c743544 100644
--- a/src/grail-gestures.c
+++ b/src/grail-gestures.c
@@ -25,6 +25,8 @@
25 25
26static const float FM_SN[DIM_FM] = { 1000, 1000, 200, 1000 }; 26static const float FM_SN[DIM_FM] = { 1000, 1000, 200, 1000 };
27static const float FM_BAR[DIM_FM] = { 50, 50, 30, 50 }; 27static const float FM_BAR[DIM_FM] = { 50, 50, 30, 50 };
28static const grail_time_t SAMPLE_MS = 10;
29static const float EPS = 1e-5;
28 30
29static void compute_position(float *x, float *y, 31static void compute_position(float *x, float *y,
30 const struct touch_frame *frame) 32 const struct touch_frame *frame)
@@ -95,30 +97,39 @@ static float move_filter(const struct filter_model *m, float val)
95 return val; 97 return val;
96} 98}
97 99
98static void move_reset(struct move_model *m, int i, float val) 100static void move_reset(struct move_model *m, int i, float x, grail_time_t t)
99{ 101{
100 struct filter_model *fm = &m->fm[i]; 102 struct filter_model *fm = &m->fm[i];
101 fm->raw_delta = 0; 103 fm->raw_delta = 0;
102 fm->action_delta = 0; 104 fm->action_delta = 0;
103 fm->value = val; 105 fm->velocity = 0;
104 fm->original = val; 106 fm->value = x;
107 fm->original = x;
108 fm->sample = x;
109 fm->sample_ms = t;
105 m->tickle &= ~(1 << i); 110 m->tickle &= ~(1 << i);
106 m->active &= ~(1 << i); 111 m->active &= ~(1 << i);
107} 112}
108 113
109static void move_update(struct move_model *m, int i, float val) 114static void move_update(struct move_model *m, int i, float x, grail_time_t t)
110{ 115{
111 struct filter_model *fm = &m->fm[i]; 116 struct filter_model *fm = &m->fm[i];
112 fm->raw_delta = val - fm->value; 117 float dt = t - fm->sample_ms;
118 fm->raw_delta = x - fm->value;
113 fm->action_delta = fm->raw_delta; 119 fm->action_delta = fm->raw_delta;
114 fm->value = val; 120 fm->velocity = dt > EPS ? (x - fm->sample) / dt : 0;
115 if (fabs(fm->raw_delta) > 0.5) 121 fm->value = x;
122 if (dt > SAMPLE_MS) {
123 fm->sample = x;
124 fm->sample_ms = t;
125 }
126 if (fabs(fm->raw_delta) > EPS)
116 m->tickle |= (1 << i); 127 m->tickle |= (1 << i);
117 else 128 else
118 m->tickle &= ~(1 << i); 129 m->tickle &= ~(1 << i);
119 if (m->active & (1 << i)) 130 if (m->active & (1 << i))
120 return; 131 return;
121 fm->action_delta = val - fm->original; 132 fm->action_delta = x - fm->original;
122 if (fabs(fm->action_delta) > fm->bar) 133 if (fabs(fm->action_delta) > fm->bar)
123 m->active |= (1 << i); 134 m->active |= (1 << i);
124 else 135 else
@@ -148,24 +159,25 @@ void gru_motion(struct grail *ge,
148{ 159{
149 struct gesture_recognizer *gru = ge->gru; 160 struct gesture_recognizer *gru = ge->gru;
150 struct move_model *m = &gru->move; 161 struct move_model *m = &gru->move;
162 grail_time_t t = frame->time;
151 float x, y, r, a; 163 float x, y, r, a;
152 compute_position(&x, &y, frame); 164 compute_position(&x, &y, frame);
153 if (frame->ncreate || frame->ndestroy) { 165 if (frame->ncreate || frame->ndestroy) {
154 r = compute_radius(x, y, frame); 166 r = compute_radius(x, y, frame);
155 a = 0; 167 a = 0;
156 move_reset(m, FM_X, x); 168 move_reset(m, FM_X, x, t);
157 move_reset(m, FM_Y, y); 169 move_reset(m, FM_Y, y, t);
158 move_reset(m, FM_R, r); 170 move_reset(m, FM_R, r, t);
159 move_reset(m, FM_A, a); 171 move_reset(m, FM_A, a, t);
160 m->single = 0; 172 m->single = 0;
161 m->multi = 0; 173 m->multi = 0;
162 } else if (frame->nactive < 2) { 174 } else if (frame->nactive < 2) {
163 r = 0; 175 r = 0;
164 a = 0; 176 a = 0;
165 move_update(m, FM_X, x); 177 move_update(m, FM_X, x, t);
166 move_update(m, FM_Y, y); 178 move_update(m, FM_Y, y, t);
167 move_reset(m, FM_R, r); 179 move_reset(m, FM_R, r, t);
168 move_reset(m, FM_A, a); 180 move_reset(m, FM_A, a, t);
169 m->single = 1; 181 m->single = 1;
170 m->multi = 0; 182 m->multi = 0;
171 } else { 183 } else {
@@ -176,15 +188,15 @@ void gru_motion(struct grail *ge,
176 a = m->fm[FM_A].value; 188 a = m->fm[FM_A].value;
177 a += compute_rotation(x, y, r, &gru->frame, frame); 189 a += compute_rotation(x, y, r, &gru->frame, frame);
178 a = move_filter(&m->fm[FM_A], a); 190 a = move_filter(&m->fm[FM_A], a);
179 move_update(m, FM_X, x); 191 move_update(m, FM_X, x, t);
180 move_update(m, FM_Y, y); 192 move_update(m, FM_Y, y, t);
181 move_update(m, FM_R, r); 193 move_update(m, FM_R, r, t);
182 move_update(m, FM_A, a); 194 move_update(m, FM_A, a, t);
183 m->single = 0; 195 m->single = 0;
184 m->multi = 1; 196 m->multi = 1;
185 } 197 }
186 m->ntouch = frame->nactive; 198 m->ntouch = frame->nactive;
187 m->time = frame->time; 199 m->time = t;
188} 200}
189 201
190void gru_event(struct grail *ge, int gid, 202void gru_event(struct grail *ge, int gid,
@@ -195,8 +207,10 @@ void gru_event(struct grail *ge, int gid,
195 prop, nprop, 0); 207 prop, nprop, 0);
196} 208}
197 209
198void gru_end(struct grail *ge, int gid, const struct move_model *m) 210void gru_end(struct grail *ge, int gid, const struct move_model *m,
211 const grail_prop_t *prop, int nprop)
199{ 212{
200 gin_gid_end(ge, gid, m->fm[FM_X].value, m->fm[FM_Y].value, m->ntouch); 213 gin_gid_end(ge, gid, m->fm[FM_X].value, m->fm[FM_Y].value, m->ntouch,
214 prop, nprop);
201} 215}
202 216
diff --git a/src/grail-gestures.h b/src/grail-gestures.h
index 6846ed0..658b548 100644
--- a/src/grail-gestures.h
+++ b/src/grail-gestures.h
@@ -39,10 +39,13 @@
39struct filter_model { 39struct filter_model {
40 float raw_delta; 40 float raw_delta;
41 float action_delta; 41 float action_delta;
42 float velocity;
42 float value; 43 float value;
43 float original; 44 float original;
44 float fuzz; 45 float fuzz;
45 float bar; 46 float bar;
47 float sample;
48 grail_time_t sample_ms;
46}; 49};
47 50
48struct move_model { 51struct move_model {
@@ -58,9 +61,14 @@ void gru_motion(struct grail *ge,
58void gru_event(struct grail *ge, int gid, 61void gru_event(struct grail *ge, int gid,
59 const struct move_model *move, 62 const struct move_model *move,
60 const grail_prop_t *prop, int nprop); 63 const grail_prop_t *prop, int nprop);
64void gru_end(struct grail *ge, int gid,
65 const struct move_model *move,
66 const grail_prop_t *prop, int nprop);
61 67
62struct combo_model { 68struct combo_model {
63 int active, gid; 69 int active, gid;
70 int nprop;
71 grail_prop_t prop[DIM_GRAIL_PROP];
64}; 72};
65 73
66int gru_drag(struct grail *ge, 74int gru_drag(struct grail *ge,
diff --git a/src/grail-inserter.c b/src/grail-inserter.c
index 6ba9662..d982808 100644
--- a/src/grail-inserter.c
+++ b/src/grail-inserter.c
@@ -262,7 +262,8 @@ void gin_gid_event(struct grail *ge, int gid,
262} 262}
263 263
264void gin_gid_end(struct grail *ge, int gid, 264void gin_gid_end(struct grail *ge, int gid,
265 float x, float y, int ntouch) 265 float x, float y, int ntouch,
266 const grail_prop_t *prop, int nprop)
266{ 267{
267 struct gesture_inserter *gin = ge->gin; 268 struct gesture_inserter *gin = ge->gin;
268 struct gesture_event ev; 269 struct gesture_event ev;
@@ -274,10 +275,11 @@ void gin_gid_end(struct grail *ge, int gid,
274 if (s->status != GRAIL_STATUS_BEGIN) { 275 if (s->status != GRAIL_STATUS_BEGIN) {
275 ev.status = GRAIL_STATUS_END; 276 ev.status = GRAIL_STATUS_END;
276 ev.ntouch = ntouch; 277 ev.ntouch = ntouch;
277 ev.nprop = 0; 278 ev.nprop = nprop;
278 ev.time = gin->time; 279 ev.time = gin->time;
279 ev.pos.x = x; 280 ev.pos.x = x;
280 ev.pos.y = y; 281 ev.pos.y = y;
282 memcpy(ev.prop, prop, nprop * sizeof(grail_prop_t));
281 gebuf_put(&s->buf, &ev); 283 gebuf_put(&s->buf, &ev);
282 } 284 }
283 s->status = GRAIL_STATUS_END; 285 s->status = GRAIL_STATUS_END;
diff --git a/src/grail-inserter.h b/src/grail-inserter.h
index 04626af..a81e431 100644
--- a/src/grail-inserter.h
+++ b/src/grail-inserter.h
@@ -64,6 +64,7 @@ void gin_gid_event(struct grail *ge, int gid,
64 const grail_prop_t *prop, int nprop, 64 const grail_prop_t *prop, int nprop,
65 int transient); 65 int transient);
66void gin_gid_end(struct grail *ge, int gid, 66void gin_gid_end(struct grail *ge, int gid,
67 float x, float y, int ntouch); 67 float x, float y, int ntouch,
68 const grail_prop_t *prop, int nprop);
68 69
69#endif 70#endif