diff options
-rw-r--r-- | src/ui/mobile.c | 3 | ||||
-rw-r--r-- | src/ui/touch.c | 78 | ||||
-rw-r--r-- | src/ui/util.c | 1 | ||||
-rw-r--r-- | src/ui/widget.c | 30 |
4 files changed, 96 insertions, 16 deletions
diff --git a/src/ui/mobile.c b/src/ui/mobile.c index 580cc355..7794d686 100644 --- a/src/ui/mobile.c +++ b/src/ui/mobile.c | |||
@@ -150,8 +150,7 @@ static iBool topPanelHandler_(iWidget *topPanel, const char *cmd) { | |||
150 | setFlags_Widget(button, selected_WidgetFlag, iTrue); | 150 | setFlags_Widget(button, selected_WidgetFlag, iTrue); |
151 | return iTrue; | 151 | return iTrue; |
152 | } | 152 | } |
153 | if (equal_Command(cmd, "mouse.clicked") && arg_Command(cmd) && | 153 | if (equal_Command(cmd, "swipe.back")) { |
154 | argLabel_Command(cmd, "button") == SDL_BUTTON_X1) { | ||
155 | postCommand_App("panel.close"); | 154 | postCommand_App("panel.close"); |
156 | return iTrue; | 155 | return iTrue; |
157 | } | 156 | } |
diff --git a/src/ui/touch.c b/src/ui/touch.c index 74a22baf..c7c5a410 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,7 +59,7 @@ 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; |
@@ -132,9 +136,6 @@ static iTouch *find_TouchState_(iTouchState *d, SDL_FingerID id) { | |||
132 | return NULL; | 136 | return NULL; |
133 | } | 137 | } |
134 | 138 | ||
135 | static const uint32_t longPressSpanMs_ = 500; | ||
136 | static const int tapRadiusPt_ = 10; | ||
137 | |||
138 | iLocalDef float distance_Touch_(const iTouch *d) { | 139 | iLocalDef float distance_Touch_(const iTouch *d) { |
139 | return length_F3(sub_F3(d->pos[0], d->startPos)); | 140 | return length_F3(sub_F3(d->pos[0], d->startPos)); |
140 | } | 141 | } |
@@ -246,6 +247,11 @@ iLocalDef double accurateTicks_(void) { | |||
246 | return 1000.0 * (double) count / (double) freq; | 247 | return 1000.0 * (double) count / (double) freq; |
247 | } | 248 | } |
248 | 249 | ||
250 | static iFloat3 gestureVector_Touch_(const iTouch *d) { | ||
251 | const size_t lastIndex = iMin(d->posCount - 1, lastIndex_Touch_); | ||
252 | return sub_F3(d->pos[0], d->pos[lastIndex]); | ||
253 | } | ||
254 | |||
249 | static void update_TouchState_(void *ptr) { | 255 | static void update_TouchState_(void *ptr) { |
250 | iTouchState *d = ptr; | 256 | iTouchState *d = ptr; |
251 | /* Check for long presses to simulate right clicks. */ | 257 | /* Check for long presses to simulate right clicks. */ |
@@ -255,6 +261,22 @@ static void update_TouchState_(void *ptr) { | |||
255 | if (touch->pinchId || touch->isTouchDrag) { | 261 | if (touch->pinchId || touch->isTouchDrag) { |
256 | continue; | 262 | continue; |
257 | } | 263 | } |
264 | if (touch->edge) { | ||
265 | const iFloat3 pos = touch->pos[0]; | ||
266 | /* Cancel the swipe if the finger doesn't move or moves mostly vertically. */ | ||
267 | const iFloat3 gestureVector = gestureVector_Touch_(touch); | ||
268 | if (fabsf(2 * x_F3(gestureVector)) < fabsf(y_F3(gestureVector)) || | ||
269 | (isStationary_Touch_(touch) && nowTime - touch->startTime > shortPressSpanMs_)) { | ||
270 | //const int swipeDir = x_F3(gestureVector) > 0 ? +1 : -1; | ||
271 | //dispatchClick_Touch_(touch, | ||
272 | // touch->edge == left_TouchEdge && swipeDir > 0 ? SDL_BUTTON_X1 : | ||
273 | // touch->edge == right_TouchEdge && swipeDir < 0 ? SDL_BUTTON_X2 : 0); | ||
274 | // setHover_Widget(NULL); | ||
275 | postCommandf_App("edgeswipe.ended abort:1 side:%d id:%llu", touch->edge, touch->id); | ||
276 | touch->edge = none_TouchEdge; | ||
277 | } | ||
278 | else continue; | ||
279 | } | ||
258 | /* Holding a touch will reset previous momentum for this widget. */ | 280 | /* Holding a touch will reset previous momentum for this widget. */ |
259 | if (isStationary_Touch_(touch)) { | 281 | if (isStationary_Touch_(touch)) { |
260 | const int elapsed = nowTime - touch->startTime; | 282 | const int elapsed = nowTime - touch->startTime; |
@@ -450,8 +472,10 @@ iBool processEvent_Touch(const SDL_Event *ev) { | |||
450 | } | 472 | } |
451 | else if (x > rootSize.x - edgeWidth) { | 473 | else if (x > rootSize.x - edgeWidth) { |
452 | edge = right_TouchEdge; | 474 | edge = right_TouchEdge; |
475 | // puts("DOWN on right edge"); | ||
453 | } | 476 | } |
454 | iWidget *aff = hitChild_Window(window, init_I2(iRound(x), iRound(y_F3(pos)))); | 477 | iWidget *aff = hitChild_Window(window, init_I2(iRound(x), iRound(y_F3(pos)))); |
478 | #if 0 | ||
455 | if (edge == left_TouchEdge) { | 479 | if (edge == left_TouchEdge) { |
456 | dragging = findSlidePanel_Widget_(aff); | 480 | dragging = findSlidePanel_Widget_(aff); |
457 | if (dragging) { | 481 | if (dragging) { |
@@ -460,6 +484,7 @@ iBool processEvent_Touch(const SDL_Event *ev) { | |||
460 | setFlags_Widget(dragging, dragged_WidgetFlag, iTrue); | 484 | setFlags_Widget(dragging, dragged_WidgetFlag, iTrue); |
461 | } | 485 | } |
462 | } | 486 | } |
487 | #endif | ||
463 | /* TODO: We must retain a reference to the affinity widget, or otherwise it might | 488 | /* TODO: We must retain a reference to the affinity widget, or otherwise it might |
464 | be destroyed during the gesture. */ | 489 | be destroyed during the gesture. */ |
465 | // printf("aff:[%p] %s:'%s'\n", aff, aff ? class_Widget(aff)->name : "-", | 490 | // printf("aff:[%p] %s:'%s'\n", aff, aff ? class_Widget(aff)->name : "-", |
@@ -469,7 +494,7 @@ iBool processEvent_Touch(const SDL_Event *ev) { | |||
469 | iTouch newTouch = { | 494 | iTouch newTouch = { |
470 | .id = fing->fingerId, | 495 | .id = fing->fingerId, |
471 | .affinity = aff, | 496 | .affinity = aff, |
472 | .edgeDragging = dragging, | 497 | // .edgeDragging = dragging, |
473 | .didBeginOnTouchDrag = (flags_Widget(aff) & touchDrag_WidgetFlag) != 0, | 498 | .didBeginOnTouchDrag = (flags_Widget(aff) & touchDrag_WidgetFlag) != 0, |
474 | .edge = edge, | 499 | .edge = edge, |
475 | .startTime = nowTime, | 500 | .startTime = nowTime, |
@@ -487,6 +512,14 @@ iBool processEvent_Touch(const SDL_Event *ev) { | |||
487 | } | 512 | } |
488 | else if (ev->type == SDL_FINGERMOTION) { | 513 | else if (ev->type == SDL_FINGERMOTION) { |
489 | iTouch *touch = find_TouchState_(d, fing->fingerId); | 514 | iTouch *touch = find_TouchState_(d, fing->fingerId); |
515 | if (touch && touch->edge) { | ||
516 | pushPos_Touch_(touch, pos, nowTime); | ||
517 | postCommandf_App("edgeswipe.moved arg:%d side:%d id:%llu", | ||
518 | (int) (x_F3(pos) - x_F3(touch->startPos)), | ||
519 | touch->edge, | ||
520 | touch->id); | ||
521 | return iTrue; | ||
522 | } | ||
490 | if (touch && touch->affinity) { | 523 | if (touch && touch->affinity) { |
491 | if (touch->isTouchDrag) { | 524 | if (touch->isTouchDrag) { |
492 | dispatchMotion_Touch_(pos, SDL_BUTTON_LMASK); | 525 | dispatchMotion_Touch_(pos, SDL_BUTTON_LMASK); |
@@ -556,6 +589,8 @@ iBool processEvent_Touch(const SDL_Event *ev) { | |||
556 | touch->axis = y_TouchAxis; | 589 | touch->axis = y_TouchAxis; |
557 | } | 590 | } |
558 | } | 591 | } |
592 | iAssert(touch->edge == none_TouchEdge); | ||
593 | #if 0 | ||
559 | /* Edge swipe aborted? */ | 594 | /* Edge swipe aborted? */ |
560 | if (touch->edge == left_TouchEdge) { | 595 | if (touch->edge == left_TouchEdge) { |
561 | if (fing->dx < 0 && x_F3(touch->pos[0]) < tapRadiusPt_ * window->pixelRatio) { | 596 | if (fing->dx < 0 && x_F3(touch->pos[0]) < tapRadiusPt_ * window->pixelRatio) { |
@@ -570,22 +605,35 @@ iBool processEvent_Touch(const SDL_Event *ev) { | |||
570 | setVisualOffset_Widget(touch->edgeDragging, x_F3(pos) - x_F3(touch->startPos), 10, 0); | 605 | setVisualOffset_Widget(touch->edgeDragging, x_F3(pos) - x_F3(touch->startPos), 10, 0); |
571 | } | 606 | } |
572 | } | 607 | } |
573 | if (touch->edge == right_TouchEdge && fing->dx > 0) { | 608 | if (touch->edge == right_TouchEdge) { |
574 | touch->edge = none_TouchEdge; | 609 | if (fing->dx > 0 && x_F3(touch->pos[0]) > window->size.x - tapRadiusPt_ * window->pixelRatio) { |
610 | puts("touch->edge==right returned to right edge, aborted"); | ||
611 | touch->edge = none_TouchEdge; | ||
612 | if (touch->edgeDragging) { | ||
613 | setFlags_Widget(touch->edgeDragging, dragged_WidgetFlag, iFalse); | ||
614 | setVisualOffset_Widget(touch->edgeDragging, 0, 200, easeOut_AnimFlag); | ||
615 | touch->edgeDragging = NULL; | ||
616 | } | ||
617 | } | ||
618 | else if (touch->edgeDragging) { | ||
619 | setVisualOffset_Widget(touch->edgeDragging, x_F3(pos) - x_F3(touch->startPos), 10, 0); | ||
620 | } | ||
575 | } | 621 | } |
576 | if (touch->edge) { | 622 | if (touch->edge) { |
577 | pixels.y = 0; | 623 | pixels.y = 0; |
578 | } | 624 | } |
625 | #endif | ||
579 | if (touch->axis == x_TouchAxis) { | 626 | if (touch->axis == x_TouchAxis) { |
580 | pixels.y = 0; | 627 | pixels.y = 0; |
581 | } | 628 | } |
582 | if (touch->axis == y_TouchAxis) { | 629 | if (touch->axis == y_TouchAxis) { |
583 | pixels.x = 0; | 630 | pixels.x = 0; |
584 | } | 631 | } |
585 | // printf("%p (%s) py: %i wy: %f acc: %f\n", | 632 | // printf("%p (%s) py: %i wy: %f acc: %f edge: %d\n", |
586 | // touch->affinity, | 633 | // touch->affinity, |
587 | // class_Widget(touch->affinity)->name, | 634 | // class_Widget(touch->affinity)->name, |
588 | // pixels.y, y_F3(amount), y_F3(touch->accum)); | 635 | // pixels.y, y_F3(amount), y_F3(touch->accum), |
636 | // touch->edge); | ||
589 | if (pixels.x || pixels.y) { | 637 | if (pixels.x || pixels.y) { |
590 | setFocus_Widget(NULL); | 638 | setFocus_Widget(NULL); |
591 | dispatchMotion_Touch_(touch->pos[0], 0); | 639 | dispatchMotion_Touch_(touch->pos[0], 0); |
@@ -612,9 +660,16 @@ iBool processEvent_Touch(const SDL_Event *ev) { | |||
612 | endPinch_TouchState_(d, touch->pinchId); | 660 | endPinch_TouchState_(d, touch->pinchId); |
613 | break; | 661 | break; |
614 | } | 662 | } |
663 | #if 0 | ||
615 | if (touch->edgeDragging) { | 664 | if (touch->edgeDragging) { |
616 | setFlags_Widget(touch->edgeDragging, dragged_WidgetFlag, iFalse); | 665 | setFlags_Widget(touch->edgeDragging, dragged_WidgetFlag, iFalse); |
617 | } | 666 | } |
667 | #endif | ||
668 | if (touch->edge && !isStationary_Touch_(touch)) { | ||
669 | postCommandf_App("edgeswipe.ended side:%d id:%llu", touch->edge, touch->id); | ||
670 | remove_ArrayIterator(&i); | ||
671 | continue; | ||
672 | } | ||
618 | if (flags_Widget(touch->affinity) & touchDrag_WidgetFlag) { | 673 | if (flags_Widget(touch->affinity) & touchDrag_WidgetFlag) { |
619 | if (!touch->isLeftDown && !touch->isTapAndHold) { | 674 | if (!touch->isLeftDown && !touch->isTapAndHold) { |
620 | /* This will be a click on a touchDrag widget. */ | 675 | /* This will be a click on a touchDrag widget. */ |
@@ -638,6 +693,7 @@ iBool processEvent_Touch(const SDL_Event *ev) { | |||
638 | const uint32_t duration = nowTime - touch->startTime; | 693 | const uint32_t duration = nowTime - touch->startTime; |
639 | const iFloat3 gestureVector = sub_F3(pos, touch->pos[lastIndex]); | 694 | const iFloat3 gestureVector = sub_F3(pos, touch->pos[lastIndex]); |
640 | iFloat3 velocity = zero_F3(); | 695 | iFloat3 velocity = zero_F3(); |
696 | #if 0 | ||
641 | if (touch->edge && fabsf(2 * x_F3(gestureVector)) > fabsf(y_F3(gestureVector)) && | 697 | if (touch->edge && fabsf(2 * x_F3(gestureVector)) > fabsf(y_F3(gestureVector)) && |
642 | !isStationary_Touch_(touch)) { | 698 | !isStationary_Touch_(touch)) { |
643 | const int swipeDir = x_F3(gestureVector) > 0 ? +1 : -1; | 699 | const int swipeDir = x_F3(gestureVector) > 0 ? +1 : -1; |
@@ -646,7 +702,9 @@ iBool processEvent_Touch(const SDL_Event *ev) { | |||
646 | touch->edge == right_TouchEdge && swipeDir < 0 ? SDL_BUTTON_X2 : 0); | 702 | touch->edge == right_TouchEdge && swipeDir < 0 ? SDL_BUTTON_X2 : 0); |
647 | setHover_Widget(NULL); | 703 | setHover_Widget(NULL); |
648 | } | 704 | } |
649 | else { | 705 | else |
706 | #endif | ||
707 | { | ||
650 | const uint32_t elapsed = fing->timestamp - touch->posTime[lastIndex]; | 708 | const uint32_t elapsed = fing->timestamp - touch->posTime[lastIndex]; |
651 | const float minVelocity = 400.0f; | 709 | const float minVelocity = 400.0f; |
652 | if (elapsed < 150) { | 710 | if (elapsed < 150) { |
diff --git a/src/ui/util.c b/src/ui/util.c index 6c6e62a5..9cc848de 100644 --- a/src/ui/util.c +++ b/src/ui/util.c | |||
@@ -1326,6 +1326,7 @@ static iBool messageHandler_(iWidget *msg, const char *cmd) { | |||
1326 | equal_Command(cmd, "document.request.updated") || | 1326 | equal_Command(cmd, "document.request.updated") || |
1327 | equal_Command(cmd, "scrollbar.fade") || | 1327 | equal_Command(cmd, "scrollbar.fade") || |
1328 | equal_Command(cmd, "widget.overflow") || | 1328 | equal_Command(cmd, "widget.overflow") || |
1329 | equal_Command(cmd, "edgeswipe.ended") || | ||
1329 | startsWith_CStr(cmd, "window."))) { | 1330 | startsWith_CStr(cmd, "window."))) { |
1330 | setupSheetTransition_Mobile(msg, iFalse); | 1331 | setupSheetTransition_Mobile(msg, iFalse); |
1331 | destroy_Widget(msg); | 1332 | destroy_Widget(msg); |
diff --git a/src/ui/widget.c b/src/ui/widget.c index 4eac7ecf..bedcb146 100644 --- a/src/ui/widget.c +++ b/src/ui/widget.c | |||
@@ -1056,10 +1056,32 @@ iBool processEvent_Widget(iWidget *d, const SDL_Event *ev) { | |||
1056 | isCommand_UserEvent(ev, "widget.overflow")) { | 1056 | isCommand_UserEvent(ev, "widget.overflow")) { |
1057 | scrollOverflow_Widget(d, 0); /* check bounds */ | 1057 | scrollOverflow_Widget(d, 0); /* check bounds */ |
1058 | } | 1058 | } |
1059 | if (ev->user.code == command_UserEventCode && d->commandHandler && | 1059 | if (ev->user.code == command_UserEventCode) { |
1060 | d->commandHandler(d, ev->user.data1)) { | 1060 | const char *cmd = command_UserEvent(ev); |
1061 | iAssert(get_Root() == d->root); | 1061 | if (d->flags & edgeDraggable_WidgetFlag && |
1062 | return iTrue; | 1062 | isVisible_Widget(d) && |
1063 | ~d->flags & disabled_WidgetFlag && | ||
1064 | equal_Command(cmd, "edgeswipe.moved")) { | ||
1065 | if (~d->flags & dragged_WidgetFlag) { | ||
1066 | setFlags_Widget(d, dragged_WidgetFlag, iTrue); | ||
1067 | } | ||
1068 | setVisualOffset_Widget(d, arg_Command(command_UserEvent(ev)), 10, 0); | ||
1069 | return iTrue; | ||
1070 | } | ||
1071 | if (d->flags & dragged_WidgetFlag && equal_Command(cmd, "edgeswipe.ended")) { | ||
1072 | if (argLabel_Command(cmd, "abort")) { | ||
1073 | setVisualOffset_Widget(d, 0, 200, easeOut_AnimFlag); | ||
1074 | setFlags_Widget(d, dragged_WidgetFlag, iFalse); | ||
1075 | } | ||
1076 | else { | ||
1077 | postCommand_Widget( | ||
1078 | d, argLabel_Command(cmd, "side") == 1 ? "swipe.back" : "swipe.forward"); | ||
1079 | } | ||
1080 | } | ||
1081 | if (d->commandHandler && d->commandHandler(d, ev->user.data1)) { | ||
1082 | iAssert(get_Root() == d->root); | ||
1083 | return iTrue; | ||
1084 | } | ||
1063 | } | 1085 | } |
1064 | break; | 1086 | break; |
1065 | } | 1087 | } |