diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-06-25 16:26:53 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-06-25 16:26:53 +0300 |
commit | 5dbc85eaaa1bd0a0fc11dd76a75ece2efe763df5 (patch) | |
tree | 9721fb7aced603adb10b9bb3f3beb3f8d5fba973 /src/ui/touch.c | |
parent | 95c527db1484f7758a180c6de051d0182c3b2e81 (diff) | |
parent | f99a9111170f2ff28383fd3172fdaf4b9a1ba069 (diff) |
Merge branch 'work/v1.6' into work/serious-unicode
# Conflicts:
# res/fonts/SmolEmoji-Regular.ttf
Diffstat (limited to 'src/ui/touch.c')
-rw-r--r-- | src/ui/touch.c | 98 |
1 files changed, 70 insertions, 28 deletions
diff --git a/src/ui/touch.c b/src/ui/touch.c index 74a22baf..dac1152e 100644 --- a/src/ui/touch.c +++ b/src/ui/touch.c | |||
@@ -40,6 +40,10 @@ iDeclareType(TouchState) | |||
40 | #define numHistory_Touch_ 5 | 40 | #define numHistory_Touch_ 5 |
41 | #define lastIndex_Touch_ (numHistory_Touch_ - 1) | 41 | #define lastIndex_Touch_ (numHistory_Touch_ - 1) |
42 | 42 | ||
43 | static const uint32_t longPressSpanMs_ = 500; | ||
44 | static const uint32_t shortPressSpanMs_ = 250; | ||
45 | static const int tapRadiusPt_ = 10; | ||
46 | |||
43 | enum iTouchEdge { | 47 | enum iTouchEdge { |
44 | none_TouchEdge, | 48 | none_TouchEdge, |
45 | left_TouchEdge, | 49 | left_TouchEdge, |
@@ -55,12 +59,13 @@ enum iTouchAxis { | |||
55 | struct Impl_Touch { | 59 | struct Impl_Touch { |
56 | SDL_FingerID id; | 60 | SDL_FingerID id; |
57 | iWidget *affinity; /* widget on which the touch started */ | 61 | iWidget *affinity; /* widget on which the touch started */ |
58 | iWidget *edgeDragging; | 62 | // iWidget *edgeDragging; |
59 | iBool hasMoved; | 63 | iBool hasMoved; |
60 | iBool isTapBegun; | 64 | iBool isTapBegun; |
61 | iBool isLeftDown; | 65 | iBool isLeftDown; |
62 | iBool isTouchDrag; | 66 | iBool isTouchDrag; |
63 | iBool isTapAndHold; | 67 | iBool isTapAndHold; |
68 | iBool didPostEdgeMove; | ||
64 | iBool didBeginOnTouchDrag; | 69 | iBool didBeginOnTouchDrag; |
65 | int pinchId; | 70 | int pinchId; |
66 | enum iTouchEdge edge; | 71 | enum iTouchEdge edge; |
@@ -132,9 +137,6 @@ static iTouch *find_TouchState_(iTouchState *d, SDL_FingerID id) { | |||
132 | return NULL; | 137 | return NULL; |
133 | } | 138 | } |
134 | 139 | ||
135 | static const uint32_t longPressSpanMs_ = 500; | ||
136 | static const int tapRadiusPt_ = 10; | ||
137 | |||
138 | iLocalDef float distance_Touch_(const iTouch *d) { | 140 | iLocalDef float distance_Touch_(const iTouch *d) { |
139 | return length_F3(sub_F3(d->pos[0], d->startPos)); | 141 | return length_F3(sub_F3(d->pos[0], d->startPos)); |
140 | } | 142 | } |
@@ -246,6 +248,11 @@ iLocalDef double accurateTicks_(void) { | |||
246 | return 1000.0 * (double) count / (double) freq; | 248 | return 1000.0 * (double) count / (double) freq; |
247 | } | 249 | } |
248 | 250 | ||
251 | static iFloat3 gestureVector_Touch_(const iTouch *d) { | ||
252 | const size_t lastIndex = iMin(d->posCount - 1, lastIndex_Touch_); | ||
253 | return sub_F3(d->pos[0], d->pos[lastIndex]); | ||
254 | } | ||
255 | |||
249 | static void update_TouchState_(void *ptr) { | 256 | static void update_TouchState_(void *ptr) { |
250 | iTouchState *d = ptr; | 257 | iTouchState *d = ptr; |
251 | /* Check for long presses to simulate right clicks. */ | 258 | /* Check for long presses to simulate right clicks. */ |
@@ -255,6 +262,24 @@ static void update_TouchState_(void *ptr) { | |||
255 | if (touch->pinchId || touch->isTouchDrag) { | 262 | if (touch->pinchId || touch->isTouchDrag) { |
256 | continue; | 263 | continue; |
257 | } | 264 | } |
265 | if (touch->edge) { | ||
266 | const iFloat3 pos = touch->pos[0]; | ||
267 | /* Cancel the swipe if the finger doesn't move or moves mostly vertically. */ | ||
268 | const iFloat3 gestureVector = gestureVector_Touch_(touch); | ||
269 | if (fabsf(2 * x_F3(gestureVector)) < fabsf(y_F3(gestureVector)) || | ||
270 | (isStationary_Touch_(touch) && nowTime - touch->startTime > shortPressSpanMs_)) { | ||
271 | //const int swipeDir = x_F3(gestureVector) > 0 ? +1 : -1; | ||
272 | //dispatchClick_Touch_(touch, | ||
273 | // touch->edge == left_TouchEdge && swipeDir > 0 ? SDL_BUTTON_X1 : | ||
274 | // touch->edge == right_TouchEdge && swipeDir < 0 ? SDL_BUTTON_X2 : 0); | ||
275 | // setHover_Widget(NULL); | ||
276 | postCommandf_App("edgeswipe.ended abort:1 side:%d id:%llu", touch->edge, touch->id); | ||
277 | touch->edge = none_TouchEdge; | ||
278 | /* May be a regular drag along the edge so don't remove. */ | ||
279 | //remove_ArrayIterator(&i); | ||
280 | } | ||
281 | continue; | ||
282 | } | ||
258 | /* Holding a touch will reset previous momentum for this widget. */ | 283 | /* Holding a touch will reset previous momentum for this widget. */ |
259 | if (isStationary_Touch_(touch)) { | 284 | if (isStationary_Touch_(touch)) { |
260 | const int elapsed = nowTime - touch->startTime; | 285 | const int elapsed = nowTime - touch->startTime; |
@@ -340,6 +365,7 @@ static void update_TouchState_(void *ptr) { | |||
340 | } | 365 | } |
341 | } | 366 | } |
342 | 367 | ||
368 | #if 0 | ||
343 | static iWidget *findSlidePanel_Widget_(iWidget *d) { | 369 | static iWidget *findSlidePanel_Widget_(iWidget *d) { |
344 | for (iWidget *w = d; w; w = parent_Widget(w)) { | 370 | for (iWidget *w = d; w; w = parent_Widget(w)) { |
345 | if (isVisible_Widget(w) && flags_Widget(w) & edgeDraggable_WidgetFlag) { | 371 | if (isVisible_Widget(w) && flags_Widget(w) & edgeDraggable_WidgetFlag) { |
@@ -348,6 +374,7 @@ static iWidget *findSlidePanel_Widget_(iWidget *d) { | |||
348 | } | 374 | } |
349 | return NULL; | 375 | return NULL; |
350 | } | 376 | } |
377 | #endif | ||
351 | 378 | ||
352 | static void checkNewPinch_TouchState_(iTouchState *d, iTouch *newTouch) { | 379 | static void checkNewPinch_TouchState_(iTouchState *d, iTouch *newTouch) { |
353 | iWidget *affinity = newTouch->affinity; | 380 | iWidget *affinity = newTouch->affinity; |
@@ -365,6 +392,12 @@ static void checkNewPinch_TouchState_(iTouchState *d, iTouch *newTouch) { | |||
365 | pinch.touchIds[1] = other->id; | 392 | pinch.touchIds[1] = other->id; |
366 | newTouch->pinchId = other->pinchId = pinch.id; | 393 | newTouch->pinchId = other->pinchId = pinch.id; |
367 | clearWidgetMomentum_TouchState_(d, affinity); | 394 | clearWidgetMomentum_TouchState_(d, affinity); |
395 | if (other->edge && other->didPostEdgeMove) { | ||
396 | postCommandf_App("edgeswipe.ended abort:1 side:%d id:%llu", other->edge, other->id); | ||
397 | other->didPostEdgeMove = iFalse; | ||
398 | } | ||
399 | other->edge = none_TouchEdge; | ||
400 | newTouch->edge = none_TouchEdge; | ||
368 | /* Remember current positions to determine pinch amount. */ | 401 | /* Remember current positions to determine pinch amount. */ |
369 | newTouch->startPos = newTouch->pos[0]; | 402 | newTouch->startPos = newTouch->pos[0]; |
370 | other->startPos = other->pos[0]; | 403 | other->startPos = other->pos[0]; |
@@ -452,6 +485,7 @@ iBool processEvent_Touch(const SDL_Event *ev) { | |||
452 | edge = right_TouchEdge; | 485 | edge = right_TouchEdge; |
453 | } | 486 | } |
454 | iWidget *aff = hitChild_Window(window, init_I2(iRound(x), iRound(y_F3(pos)))); | 487 | iWidget *aff = hitChild_Window(window, init_I2(iRound(x), iRound(y_F3(pos)))); |
488 | #if 0 | ||
455 | if (edge == left_TouchEdge) { | 489 | if (edge == left_TouchEdge) { |
456 | dragging = findSlidePanel_Widget_(aff); | 490 | dragging = findSlidePanel_Widget_(aff); |
457 | if (dragging) { | 491 | if (dragging) { |
@@ -460,6 +494,7 @@ iBool processEvent_Touch(const SDL_Event *ev) { | |||
460 | setFlags_Widget(dragging, dragged_WidgetFlag, iTrue); | 494 | setFlags_Widget(dragging, dragged_WidgetFlag, iTrue); |
461 | } | 495 | } |
462 | } | 496 | } |
497 | #endif | ||
463 | /* TODO: We must retain a reference to the affinity widget, or otherwise it might | 498 | /* TODO: We must retain a reference to the affinity widget, or otherwise it might |
464 | be destroyed during the gesture. */ | 499 | be destroyed during the gesture. */ |
465 | // printf("aff:[%p] %s:'%s'\n", aff, aff ? class_Widget(aff)->name : "-", | 500 | // printf("aff:[%p] %s:'%s'\n", aff, aff ? class_Widget(aff)->name : "-", |
@@ -469,7 +504,7 @@ iBool processEvent_Touch(const SDL_Event *ev) { | |||
469 | iTouch newTouch = { | 504 | iTouch newTouch = { |
470 | .id = fing->fingerId, | 505 | .id = fing->fingerId, |
471 | .affinity = aff, | 506 | .affinity = aff, |
472 | .edgeDragging = dragging, | 507 | // .edgeDragging = dragging, |
473 | .didBeginOnTouchDrag = (flags_Widget(aff) & touchDrag_WidgetFlag) != 0, | 508 | .didBeginOnTouchDrag = (flags_Widget(aff) & touchDrag_WidgetFlag) != 0, |
474 | .edge = edge, | 509 | .edge = edge, |
475 | .startTime = nowTime, | 510 | .startTime = nowTime, |
@@ -487,6 +522,16 @@ iBool processEvent_Touch(const SDL_Event *ev) { | |||
487 | } | 522 | } |
488 | else if (ev->type == SDL_FINGERMOTION) { | 523 | else if (ev->type == SDL_FINGERMOTION) { |
489 | iTouch *touch = find_TouchState_(d, fing->fingerId); | 524 | iTouch *touch = find_TouchState_(d, fing->fingerId); |
525 | if (touch && touch->edge) { | ||
526 | clear_Array(d->moms); | ||
527 | pushPos_Touch_(touch, pos, nowTime); | ||
528 | postCommandf_App("edgeswipe.moved arg:%d side:%d id:%llu", | ||
529 | (int) (x_F3(pos) - x_F3(touch->startPos)), | ||
530 | touch->edge, | ||
531 | touch->id); | ||
532 | touch->didPostEdgeMove = iTrue; | ||
533 | return iTrue; | ||
534 | } | ||
490 | if (touch && touch->affinity) { | 535 | if (touch && touch->affinity) { |
491 | if (touch->isTouchDrag) { | 536 | if (touch->isTouchDrag) { |
492 | dispatchMotion_Touch_(pos, SDL_BUTTON_LMASK); | 537 | dispatchMotion_Touch_(pos, SDL_BUTTON_LMASK); |
@@ -556,36 +601,18 @@ iBool processEvent_Touch(const SDL_Event *ev) { | |||
556 | touch->axis = y_TouchAxis; | 601 | touch->axis = y_TouchAxis; |
557 | } | 602 | } |
558 | } | 603 | } |
559 | /* Edge swipe aborted? */ | 604 | iAssert(touch->edge == none_TouchEdge); |
560 | if (touch->edge == left_TouchEdge) { | ||
561 | if (fing->dx < 0 && x_F3(touch->pos[0]) < tapRadiusPt_ * window->pixelRatio) { | ||
562 | touch->edge = none_TouchEdge; | ||
563 | if (touch->edgeDragging) { | ||
564 | setFlags_Widget(touch->edgeDragging, dragged_WidgetFlag, iFalse); | ||
565 | setVisualOffset_Widget(touch->edgeDragging, 0, 200, easeOut_AnimFlag); | ||
566 | touch->edgeDragging = NULL; | ||
567 | } | ||
568 | } | ||
569 | else if (touch->edgeDragging) { | ||
570 | setVisualOffset_Widget(touch->edgeDragging, x_F3(pos) - x_F3(touch->startPos), 10, 0); | ||
571 | } | ||
572 | } | ||
573 | if (touch->edge == right_TouchEdge && fing->dx > 0) { | ||
574 | touch->edge = none_TouchEdge; | ||
575 | } | ||
576 | if (touch->edge) { | ||
577 | pixels.y = 0; | ||
578 | } | ||
579 | if (touch->axis == x_TouchAxis) { | 605 | if (touch->axis == x_TouchAxis) { |
580 | pixels.y = 0; | 606 | pixels.y = 0; |
581 | } | 607 | } |
582 | if (touch->axis == y_TouchAxis) { | 608 | if (touch->axis == y_TouchAxis) { |
583 | pixels.x = 0; | 609 | pixels.x = 0; |
584 | } | 610 | } |
585 | // printf("%p (%s) py: %i wy: %f acc: %f\n", | 611 | // printf("%p (%s) py: %i wy: %f acc: %f edge: %d\n", |
586 | // touch->affinity, | 612 | // touch->affinity, |
587 | // class_Widget(touch->affinity)->name, | 613 | // class_Widget(touch->affinity)->name, |
588 | // pixels.y, y_F3(amount), y_F3(touch->accum)); | 614 | // pixels.y, y_F3(amount), y_F3(touch->accum), |
615 | // touch->edge); | ||
589 | if (pixels.x || pixels.y) { | 616 | if (pixels.x || pixels.y) { |
590 | setFocus_Widget(NULL); | 617 | setFocus_Widget(NULL); |
591 | dispatchMotion_Touch_(touch->pos[0], 0); | 618 | dispatchMotion_Touch_(touch->pos[0], 0); |
@@ -612,9 +639,21 @@ iBool processEvent_Touch(const SDL_Event *ev) { | |||
612 | endPinch_TouchState_(d, touch->pinchId); | 639 | endPinch_TouchState_(d, touch->pinchId); |
613 | break; | 640 | break; |
614 | } | 641 | } |
642 | #if 0 | ||
615 | if (touch->edgeDragging) { | 643 | if (touch->edgeDragging) { |
616 | setFlags_Widget(touch->edgeDragging, dragged_WidgetFlag, iFalse); | 644 | setFlags_Widget(touch->edgeDragging, dragged_WidgetFlag, iFalse); |
617 | } | 645 | } |
646 | #endif | ||
647 | if (touch->edge && !isStationary_Touch_(touch)) { | ||
648 | const iFloat3 gesture = gestureVector_Touch_(touch); | ||
649 | const float pixel = window->pixelRatio; | ||
650 | const int moveDir = x_F3(gesture) < -pixel ? -1 : x_F3(gesture) > pixel ? +1 : 0; | ||
651 | const int didAbort = (touch->edge == left_TouchEdge && moveDir < 0) || | ||
652 | (touch->edge == right_TouchEdge && moveDir > 0); | ||
653 | postCommandf_App("edgeswipe.ended abort:%d side:%d id:%llu", didAbort, touch->edge, touch->id); | ||
654 | remove_ArrayIterator(&i); | ||
655 | continue; | ||
656 | } | ||
618 | if (flags_Widget(touch->affinity) & touchDrag_WidgetFlag) { | 657 | if (flags_Widget(touch->affinity) & touchDrag_WidgetFlag) { |
619 | if (!touch->isLeftDown && !touch->isTapAndHold) { | 658 | if (!touch->isLeftDown && !touch->isTapAndHold) { |
620 | /* This will be a click on a touchDrag widget. */ | 659 | /* This will be a click on a touchDrag widget. */ |
@@ -638,6 +677,7 @@ iBool processEvent_Touch(const SDL_Event *ev) { | |||
638 | const uint32_t duration = nowTime - touch->startTime; | 677 | const uint32_t duration = nowTime - touch->startTime; |
639 | const iFloat3 gestureVector = sub_F3(pos, touch->pos[lastIndex]); | 678 | const iFloat3 gestureVector = sub_F3(pos, touch->pos[lastIndex]); |
640 | iFloat3 velocity = zero_F3(); | 679 | iFloat3 velocity = zero_F3(); |
680 | #if 0 | ||
641 | if (touch->edge && fabsf(2 * x_F3(gestureVector)) > fabsf(y_F3(gestureVector)) && | 681 | if (touch->edge && fabsf(2 * x_F3(gestureVector)) > fabsf(y_F3(gestureVector)) && |
642 | !isStationary_Touch_(touch)) { | 682 | !isStationary_Touch_(touch)) { |
643 | const int swipeDir = x_F3(gestureVector) > 0 ? +1 : -1; | 683 | const int swipeDir = x_F3(gestureVector) > 0 ? +1 : -1; |
@@ -646,7 +686,9 @@ iBool processEvent_Touch(const SDL_Event *ev) { | |||
646 | touch->edge == right_TouchEdge && swipeDir < 0 ? SDL_BUTTON_X2 : 0); | 686 | touch->edge == right_TouchEdge && swipeDir < 0 ? SDL_BUTTON_X2 : 0); |
647 | setHover_Widget(NULL); | 687 | setHover_Widget(NULL); |
648 | } | 688 | } |
649 | else { | 689 | else |
690 | #endif | ||
691 | { | ||
650 | const uint32_t elapsed = fing->timestamp - touch->posTime[lastIndex]; | 692 | const uint32_t elapsed = fing->timestamp - touch->posTime[lastIndex]; |
651 | const float minVelocity = 400.0f; | 693 | const float minVelocity = 400.0f; |
652 | if (elapsed < 150) { | 694 | if (elapsed < 150) { |