From ecb72de43c2119139d87bef3da05819d3724c91a Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Mon, 22 Feb 2021 11:54:41 +0200 Subject: Touch: Improved tap-and-hold Clear gestures related to a widget if the widget is destroyed. --- src/ui/touch.c | 42 ++++++++++++++++++++++++++++++++++++++++-- src/ui/touch.h | 7 +++++-- src/ui/widget.c | 2 ++ 3 files changed, 47 insertions(+), 4 deletions(-) diff --git a/src/ui/touch.c b/src/ui/touch.c index eb5f4f7f..5bf1b87e 100644 --- a/src/ui/touch.c +++ b/src/ui/touch.c @@ -45,6 +45,7 @@ struct Impl_Touch { SDL_FingerID id; iWidget *affinity; /* widget on which the touch started */ iBool hasMoved; + iBool isTapAndHold; enum iTouchEdge edge; uint32_t startTime; iFloat3 startPos; @@ -155,9 +156,12 @@ static void update_TouchState_(void *ptr) { if (nowTime - touch->startTime > 25) { clearWidgetMomentum_TouchState_(d, touch->affinity); } - if (nowTime - touch->startTime >= longPressSpanMs_ && touch->affinity) { + if (!touch->isTapAndHold && nowTime - touch->startTime >= longPressSpanMs_ && + touch->affinity) { dispatchClick_Touch_(touch, SDL_BUTTON_RIGHT); - remove_ArrayIterator(&i); + touch->isTapAndHold = iTrue; + touch->hasMoved = iFalse; + touch->startPos = touch->pos[0]; } } } @@ -200,6 +204,22 @@ static void update_TouchState_(void *ptr) { } } +void widgetDestroyed_Touch(iWidget *widget) { + iTouchState *d = touchState_(); + iForEach(Array, i, d->touches) { + iTouch *touch = i.value; + if (touch->affinity == widget) { + remove_ArrayIterator(&i); + } + } + iForEach(Array, m, d->moms) { + iMomentum *mom = m.value; + if (mom->affinity == widget) { + remove_ArrayIterator(&m); + } + } +} + static void dispatchButtonUp_Touch_(iFloat3 pos) { dispatchEvent_Widget(get_Window()->root, (SDL_Event *) &(SDL_MouseButtonEvent){ .type = SDL_MOUSEBUTTONUP, @@ -268,6 +288,14 @@ iBool processEvent_Touch(const SDL_Event *ev) { else if (ev->type == SDL_FINGERMOTION) { iTouch *touch = find_TouchState_(d, fing->fingerId); if (touch && touch->affinity) { + if (touch->isTapAndHold) { + pushPos_Touch_(touch, pos, fing->timestamp); + if (!touch->hasMoved && !isStationary_Touch_(touch)) { + touch->hasMoved = iTrue; + } + dispatchMotion_Touch_(pos, 0); + return iTrue; + } if (flags_Widget(touch->affinity) & touchDrag_WidgetFlag) { dispatchMotion_Touch_(pos, SDL_BUTTON_LMASK); return iTrue; @@ -298,6 +326,7 @@ iBool processEvent_Touch(const SDL_Event *ev) { // class_Widget(touch->affinity)->name, // pixels.y, y_F3(amount), y_F3(touch->accum)); if (pixels.x || pixels.y) { + dispatchMotion_Touch_(pos, 0); dispatchEvent_Widget(touch->affinity, (SDL_Event *) &(SDL_MouseWheelEvent){ .type = SDL_MOUSEWHEEL, .timestamp = SDL_GetTicks(), @@ -305,6 +334,7 @@ iBool processEvent_Touch(const SDL_Event *ev) { .x = pixels.x, .y = pixels.y, }); + dispatchMotion_Touch_(zero_F3(), 0); /* TODO: Keep increasing movement if the direction is the same. */ clearWidgetMomentum_TouchState_(d, touch->affinity); } @@ -317,6 +347,13 @@ iBool processEvent_Touch(const SDL_Event *ev) { if (touch->id != fing->fingerId) { continue; } + if (touch->isTapAndHold) { + if (!isStationary_Touch_(touch)) { + dispatchClick_Touch_(touch, SDL_BUTTON_LEFT); + } + remove_ArrayIterator(&i); + continue; + } if (flags_Widget(touch->affinity) & touchDrag_WidgetFlag) { dispatchButtonUp_Touch_(pos); remove_ArrayIterator(&i); @@ -363,6 +400,7 @@ iBool processEvent_Touch(const SDL_Event *ev) { d->lastMomTime = nowTime; } pushBack_Array(d->moms, &mom); + dispatchMotion_Touch_(touch->startPos, 0); } else { dispatchButtonUp_Touch_(pos); diff --git a/src/ui/touch.h b/src/ui/touch.h index fb8ff555..39a059da 100644 --- a/src/ui/touch.h +++ b/src/ui/touch.h @@ -25,5 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include -iBool processEvent_Touch (const SDL_Event *); -void update_Touch (void); +iDeclareType(Widget) + +iBool processEvent_Touch (const SDL_Event *); +void update_Touch (void); +void widgetDestroyed_Touch (iWidget *widget); diff --git a/src/ui/widget.c b/src/ui/widget.c index 31544cf8..c0e2feda 100644 --- a/src/ui/widget.c +++ b/src/ui/widget.c @@ -23,6 +23,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "widget.h" #include "app.h" +#include "touch.h" #include "command.h" #include "paint.h" #include "util.h" @@ -91,6 +92,7 @@ void deinit_Widget(iWidget *d) { if (d->flags & keepOnTop_WidgetFlag) { removeAll_PtrArray(onTop_RootData_(), d); } + widgetDestroyed_Touch(d); } static void aboutToBeDestroyed_Widget_(iWidget *d) { -- cgit v1.2.3