summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ui/mobile.c3
-rw-r--r--src/ui/touch.c78
-rw-r--r--src/ui/util.c1
-rw-r--r--src/ui/widget.c30
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
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,7 +59,7 @@ 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;
@@ -132,9 +136,6 @@ static iTouch *find_TouchState_(iTouchState *d, SDL_FingerID id) {
132 return NULL; 136 return NULL;
133} 137}
134 138
135static const uint32_t longPressSpanMs_ = 500;
136static const int tapRadiusPt_ = 10;
137
138iLocalDef float distance_Touch_(const iTouch *d) { 139iLocalDef 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
250static 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
249static void update_TouchState_(void *ptr) { 255static 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 }