summaryrefslogtreecommitdiff
path: root/src/ui
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-03-04 13:48:24 +0200
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-03-04 22:24:43 +0200
commit92dd2e36482beb8f9d651f8f3956950f173ff8a7 (patch)
tree9dadc4019dfef49a74ad74e21aeb8df62b648328 /src/ui
parenta66a6731e79248b859e364178c2d962355cba3ea (diff)
Touch: Tuning holding and swiping
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/touch.c70
1 files changed, 56 insertions, 14 deletions
diff --git a/src/ui/touch.c b/src/ui/touch.c
index 5bf1b87e..83641ad4 100644
--- a/src/ui/touch.c
+++ b/src/ui/touch.c
@@ -32,7 +32,7 @@ iDeclareType(Touch)
32iDeclareType(TouchState) 32iDeclareType(TouchState)
33iDeclareType(Momentum) 33iDeclareType(Momentum)
34 34
35#define numHistory_Touch_ 3 35#define numHistory_Touch_ 5
36#define lastIndex_Touch_ (numHistory_Touch_ - 1) 36#define lastIndex_Touch_ (numHistory_Touch_ - 1)
37 37
38enum iTouchEdge { 38enum iTouchEdge {
@@ -41,6 +41,12 @@ enum iTouchEdge {
41 right_TouchEdge, 41 right_TouchEdge,
42}; 42};
43 43
44enum iTouchAxis {
45 none_TouchAxis,
46 x_TouchAxis,
47 y_TouchAxis
48};
49
44struct Impl_Touch { 50struct Impl_Touch {
45 SDL_FingerID id; 51 SDL_FingerID id;
46 iWidget *affinity; /* widget on which the touch started */ 52 iWidget *affinity; /* widget on which the touch started */
@@ -49,8 +55,10 @@ struct Impl_Touch {
49 enum iTouchEdge edge; 55 enum iTouchEdge edge;
50 uint32_t startTime; 56 uint32_t startTime;
51 iFloat3 startPos; 57 iFloat3 startPos;
58 enum iTouchAxis axis;
52 uint32_t posTime[numHistory_Touch_]; 59 uint32_t posTime[numHistory_Touch_];
53 iFloat3 pos[numHistory_Touch_]; 60 iFloat3 pos[numHistory_Touch_];
61 size_t posCount;
54 iFloat3 accum; 62 iFloat3 accum;
55}; 63};
56 64
@@ -59,6 +67,7 @@ iLocalDef void pushPos_Touch_(iTouch *d, const iFloat3 pos, uint32_t time) {
59 memmove(d->pos + 1, d->pos, (numHistory_Touch_ - 1) * sizeof(d->pos[0])); 67 memmove(d->pos + 1, d->pos, (numHistory_Touch_ - 1) * sizeof(d->pos[0]));
60 d->posTime[0] = time; 68 d->posTime[0] = time;
61 d->pos[0] = pos; 69 d->pos[0] = pos;
70 d->posCount++;
62} 71}
63 72
64struct Impl_Momentum { 73struct Impl_Momentum {
@@ -96,11 +105,14 @@ static iTouch *find_TouchState_(iTouchState *d, SDL_FingerID id) {
96} 105}
97 106
98static const uint32_t longPressSpanMs_ = 425; 107static const uint32_t longPressSpanMs_ = 425;
99static const int tapRadiusPt_ = 15; 108static const int tapRadiusPt_ = 5;
109
110iLocalDef float distance_Touch_(const iTouch *d) {
111 return length_F3(sub_F3(d->pos[0], d->startPos));
112}
100 113
101static iBool isStationary_Touch_(const iTouch *d) { 114static iBool isStationary_Touch_(const iTouch *d) {
102 return !d->hasMoved && 115 return !d->hasMoved && distance_Touch_(d) < tapRadiusPt_ * get_Window()->pixelRatio;
103 length_F3(sub_F3(d->pos[0], d->startPos)) < tapRadiusPt_ * get_Window()->pixelRatio;
104} 116}
105 117
106static void dispatchMotion_Touch_(iFloat3 pos, int buttonState) { 118static void dispatchMotion_Touch_(iFloat3 pos, int buttonState) {
@@ -272,15 +284,16 @@ iBool processEvent_Touch(const SDL_Event *ev) {
272 }); 284 });
273 edge = none_TouchEdge; 285 edge = none_TouchEdge;
274 } 286 }
275 pushBack_Array(d->touches, &(iTouch){ 287 iTouch newTouch = {
276 .id = fing->fingerId, 288 .id = fing->fingerId,
277 .affinity = aff, 289 .affinity = aff,
278 .hasMoved = (flags_Widget(aff) & touchDrag_WidgetFlag) != 0, 290 .hasMoved = (flags_Widget(aff) & touchDrag_WidgetFlag) != 0,
279 .edge = edge, 291 .edge = edge,
280 .startTime = nowTime, 292 .startTime = nowTime,
281 .startPos = pos, 293 .startPos = pos,
282 .pos = pos 294 };
283 }); 295 pushPos_Touch_(&newTouch, pos, fing->timestamp);
296 pushBack_Array(d->touches, &newTouch);
284 /* Some widgets rely on hover state. */ 297 /* Some widgets rely on hover state. */
285 dispatchMotion_Touch_(pos, 0); 298 dispatchMotion_Touch_(pos, 0);
286 addTicker_App(update_TouchState_, d); 299 addTicker_App(update_TouchState_, d);
@@ -308,8 +321,30 @@ iBool processEvent_Touch(const SDL_Event *ev) {
308 iInt2 pixels = initF3_I2(touch->accum); 321 iInt2 pixels = initF3_I2(touch->accum);
309 /* We're reporting scrolling as full points, so keep track of the precise distance. */ 322 /* We're reporting scrolling as full points, so keep track of the precise distance. */
310 subv_F3(&touch->accum, initI2_F3(pixels)); 323 subv_F3(&touch->accum, initI2_F3(pixels));
311 if (!touch->hasMoved && !isStationary_Touch_(touch)) { 324 if (!touch->hasMoved) {
312 touch->hasMoved = iTrue; 325 if (!isStationary_Touch_(touch)) {
326 touch->hasMoved = iTrue;
327 /* The first FINGERMOTION seems to be larger than the subsequence ones.
328 Maybe SDL does its own stationary threshold? We'll counter by reducing
329 the first one. */
330 divvf_F3(&touch->accum, 3);
331 divfv_I2(&pixels, 3);
332 }
333 else {
334 touch->accum = zero_F3();
335 pixels = zero_I2();
336 }
337 }
338 else if (!touch->axis &&
339 distance_Touch_(touch) > tapRadiusPt_ * 3 * window->pixelRatio) {
340 /* Lock swipe direction to an axis. */
341 if (iAbs(x_F3(touch->startPos) - x_F3(pos)) >
342 iAbs(y_F3(touch->startPos) - y_F3(pos)) * 1.5f) {
343 touch->axis = x_TouchAxis;
344 }
345 else {
346 touch->axis = y_TouchAxis;
347 }
313 } 348 }
314 /* Edge swipe aborted? */ 349 /* Edge swipe aborted? */
315 if (touch->edge == left_TouchEdge && fing->dx < 0) { 350 if (touch->edge == left_TouchEdge && fing->dx < 0) {
@@ -321,6 +356,12 @@ iBool processEvent_Touch(const SDL_Event *ev) {
321 if (touch->edge) { 356 if (touch->edge) {
322 pixels.y = 0; 357 pixels.y = 0;
323 } 358 }
359 if (touch->axis == x_TouchAxis) {
360 pixels.y = 0;
361 }
362 if (touch->axis == y_TouchAxis) {
363 pixels.x = 0;
364 }
324// printf("%p (%s) py: %i wy: %f acc: %f\n", 365// printf("%p (%s) py: %i wy: %f acc: %f\n",
325// touch->affinity, 366// touch->affinity,
326// class_Widget(touch->affinity)->name, 367// class_Widget(touch->affinity)->name,
@@ -369,15 +410,16 @@ iBool processEvent_Touch(const SDL_Event *ev) {
369 : SDL_BUTTON_X2); 410 : SDL_BUTTON_X2);
370 } 411 }
371 else { 412 else {
372 const uint32_t elapsed = fing->timestamp - touch->posTime[lastIndex_Touch_]; 413 const size_t lastIndex = iMin(touch->posCount - 1, lastIndex_Touch_);
414 const uint32_t elapsed = fing->timestamp - touch->posTime[lastIndex];
373 const float minVelocity = 400.0f; 415 const float minVelocity = 400.0f;
374 if (elapsed < 75) { 416 if (elapsed < 85) {
375 velocity = divf_F3(sub_F3(pos, touch->pos[lastIndex_Touch_]), 417 velocity = divf_F3(sub_F3(pos, touch->pos[lastIndex]),
376 (float) elapsed / 1000.0f); 418 (float) elapsed / 1000.0f);
377 if (fabsf(x_F3(velocity)) < minVelocity) { 419 if (touch->axis == y_TouchAxis || fabsf(x_F3(velocity)) < minVelocity) {
378 setX_F3(&velocity, 0.0f); 420 setX_F3(&velocity, 0.0f);
379 } 421 }
380 if (fabsf(y_F3(velocity)) < minVelocity) { 422 if (touch->axis == x_TouchAxis || fabsf(y_F3(velocity)) < minVelocity) {
381 setY_F3(&velocity, 0.0f); 423 setY_F3(&velocity, 0.0f);
382 } 424 }
383 } 425 }