summaryrefslogtreecommitdiff
path: root/src/ui/touch.c
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-06-25 16:26:53 +0300
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-06-25 16:26:53 +0300
commit5dbc85eaaa1bd0a0fc11dd76a75ece2efe763df5 (patch)
tree9721fb7aced603adb10b9bb3f3beb3f8d5fba973 /src/ui/touch.c
parent95c527db1484f7758a180c6de051d0182c3b2e81 (diff)
parentf99a9111170f2ff28383fd3172fdaf4b9a1ba069 (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.c98
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
43static const uint32_t longPressSpanMs_ = 500;
44static const uint32_t shortPressSpanMs_ = 250;
45static const int tapRadiusPt_ = 10;
46
43enum iTouchEdge { 47enum iTouchEdge {
44 none_TouchEdge, 48 none_TouchEdge,
45 left_TouchEdge, 49 left_TouchEdge,
@@ -55,12 +59,13 @@ enum iTouchAxis {
55struct Impl_Touch { 59struct 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
135static const uint32_t longPressSpanMs_ = 500;
136static const int tapRadiusPt_ = 10;
137
138iLocalDef float distance_Touch_(const iTouch *d) { 140iLocalDef 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
251static 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
249static void update_TouchState_(void *ptr) { 256static 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
343static iWidget *findSlidePanel_Widget_(iWidget *d) { 369static 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
352static void checkNewPinch_TouchState_(iTouchState *d, iTouch *newTouch) { 379static 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) {