diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-02-22 11:54:41 +0200 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-02-22 11:54:41 +0200 |
commit | ecb72de43c2119139d87bef3da05819d3724c91a (patch) | |
tree | 35b7337e43c9f82baa3bfd10fc0a352d2b455e82 /src/ui | |
parent | a042332c14d4710009638d83c87088fbc44c2ab4 (diff) |
Touch: Improved tap-and-hold
Clear gestures related to a widget if the widget is destroyed.
Diffstat (limited to 'src/ui')
-rw-r--r-- | src/ui/touch.c | 42 | ||||
-rw-r--r-- | src/ui/touch.h | 7 | ||||
-rw-r--r-- | 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 { | |||
45 | SDL_FingerID id; | 45 | SDL_FingerID id; |
46 | iWidget *affinity; /* widget on which the touch started */ | 46 | iWidget *affinity; /* widget on which the touch started */ |
47 | iBool hasMoved; | 47 | iBool hasMoved; |
48 | iBool isTapAndHold; | ||
48 | enum iTouchEdge edge; | 49 | enum iTouchEdge edge; |
49 | uint32_t startTime; | 50 | uint32_t startTime; |
50 | iFloat3 startPos; | 51 | iFloat3 startPos; |
@@ -155,9 +156,12 @@ static void update_TouchState_(void *ptr) { | |||
155 | if (nowTime - touch->startTime > 25) { | 156 | if (nowTime - touch->startTime > 25) { |
156 | clearWidgetMomentum_TouchState_(d, touch->affinity); | 157 | clearWidgetMomentum_TouchState_(d, touch->affinity); |
157 | } | 158 | } |
158 | if (nowTime - touch->startTime >= longPressSpanMs_ && touch->affinity) { | 159 | if (!touch->isTapAndHold && nowTime - touch->startTime >= longPressSpanMs_ && |
160 | touch->affinity) { | ||
159 | dispatchClick_Touch_(touch, SDL_BUTTON_RIGHT); | 161 | dispatchClick_Touch_(touch, SDL_BUTTON_RIGHT); |
160 | remove_ArrayIterator(&i); | 162 | touch->isTapAndHold = iTrue; |
163 | touch->hasMoved = iFalse; | ||
164 | touch->startPos = touch->pos[0]; | ||
161 | } | 165 | } |
162 | } | 166 | } |
163 | } | 167 | } |
@@ -200,6 +204,22 @@ static void update_TouchState_(void *ptr) { | |||
200 | } | 204 | } |
201 | } | 205 | } |
202 | 206 | ||
207 | void widgetDestroyed_Touch(iWidget *widget) { | ||
208 | iTouchState *d = touchState_(); | ||
209 | iForEach(Array, i, d->touches) { | ||
210 | iTouch *touch = i.value; | ||
211 | if (touch->affinity == widget) { | ||
212 | remove_ArrayIterator(&i); | ||
213 | } | ||
214 | } | ||
215 | iForEach(Array, m, d->moms) { | ||
216 | iMomentum *mom = m.value; | ||
217 | if (mom->affinity == widget) { | ||
218 | remove_ArrayIterator(&m); | ||
219 | } | ||
220 | } | ||
221 | } | ||
222 | |||
203 | static void dispatchButtonUp_Touch_(iFloat3 pos) { | 223 | static void dispatchButtonUp_Touch_(iFloat3 pos) { |
204 | dispatchEvent_Widget(get_Window()->root, (SDL_Event *) &(SDL_MouseButtonEvent){ | 224 | dispatchEvent_Widget(get_Window()->root, (SDL_Event *) &(SDL_MouseButtonEvent){ |
205 | .type = SDL_MOUSEBUTTONUP, | 225 | .type = SDL_MOUSEBUTTONUP, |
@@ -268,6 +288,14 @@ iBool processEvent_Touch(const SDL_Event *ev) { | |||
268 | else if (ev->type == SDL_FINGERMOTION) { | 288 | else if (ev->type == SDL_FINGERMOTION) { |
269 | iTouch *touch = find_TouchState_(d, fing->fingerId); | 289 | iTouch *touch = find_TouchState_(d, fing->fingerId); |
270 | if (touch && touch->affinity) { | 290 | if (touch && touch->affinity) { |
291 | if (touch->isTapAndHold) { | ||
292 | pushPos_Touch_(touch, pos, fing->timestamp); | ||
293 | if (!touch->hasMoved && !isStationary_Touch_(touch)) { | ||
294 | touch->hasMoved = iTrue; | ||
295 | } | ||
296 | dispatchMotion_Touch_(pos, 0); | ||
297 | return iTrue; | ||
298 | } | ||
271 | if (flags_Widget(touch->affinity) & touchDrag_WidgetFlag) { | 299 | if (flags_Widget(touch->affinity) & touchDrag_WidgetFlag) { |
272 | dispatchMotion_Touch_(pos, SDL_BUTTON_LMASK); | 300 | dispatchMotion_Touch_(pos, SDL_BUTTON_LMASK); |
273 | return iTrue; | 301 | return iTrue; |
@@ -298,6 +326,7 @@ iBool processEvent_Touch(const SDL_Event *ev) { | |||
298 | // class_Widget(touch->affinity)->name, | 326 | // class_Widget(touch->affinity)->name, |
299 | // pixels.y, y_F3(amount), y_F3(touch->accum)); | 327 | // pixels.y, y_F3(amount), y_F3(touch->accum)); |
300 | if (pixels.x || pixels.y) { | 328 | if (pixels.x || pixels.y) { |
329 | dispatchMotion_Touch_(pos, 0); | ||
301 | dispatchEvent_Widget(touch->affinity, (SDL_Event *) &(SDL_MouseWheelEvent){ | 330 | dispatchEvent_Widget(touch->affinity, (SDL_Event *) &(SDL_MouseWheelEvent){ |
302 | .type = SDL_MOUSEWHEEL, | 331 | .type = SDL_MOUSEWHEEL, |
303 | .timestamp = SDL_GetTicks(), | 332 | .timestamp = SDL_GetTicks(), |
@@ -305,6 +334,7 @@ iBool processEvent_Touch(const SDL_Event *ev) { | |||
305 | .x = pixels.x, | 334 | .x = pixels.x, |
306 | .y = pixels.y, | 335 | .y = pixels.y, |
307 | }); | 336 | }); |
337 | dispatchMotion_Touch_(zero_F3(), 0); | ||
308 | /* TODO: Keep increasing movement if the direction is the same. */ | 338 | /* TODO: Keep increasing movement if the direction is the same. */ |
309 | clearWidgetMomentum_TouchState_(d, touch->affinity); | 339 | clearWidgetMomentum_TouchState_(d, touch->affinity); |
310 | } | 340 | } |
@@ -317,6 +347,13 @@ iBool processEvent_Touch(const SDL_Event *ev) { | |||
317 | if (touch->id != fing->fingerId) { | 347 | if (touch->id != fing->fingerId) { |
318 | continue; | 348 | continue; |
319 | } | 349 | } |
350 | if (touch->isTapAndHold) { | ||
351 | if (!isStationary_Touch_(touch)) { | ||
352 | dispatchClick_Touch_(touch, SDL_BUTTON_LEFT); | ||
353 | } | ||
354 | remove_ArrayIterator(&i); | ||
355 | continue; | ||
356 | } | ||
320 | if (flags_Widget(touch->affinity) & touchDrag_WidgetFlag) { | 357 | if (flags_Widget(touch->affinity) & touchDrag_WidgetFlag) { |
321 | dispatchButtonUp_Touch_(pos); | 358 | dispatchButtonUp_Touch_(pos); |
322 | remove_ArrayIterator(&i); | 359 | remove_ArrayIterator(&i); |
@@ -363,6 +400,7 @@ iBool processEvent_Touch(const SDL_Event *ev) { | |||
363 | d->lastMomTime = nowTime; | 400 | d->lastMomTime = nowTime; |
364 | } | 401 | } |
365 | pushBack_Array(d->moms, &mom); | 402 | pushBack_Array(d->moms, &mom); |
403 | dispatchMotion_Touch_(touch->startPos, 0); | ||
366 | } | 404 | } |
367 | else { | 405 | else { |
368 | dispatchButtonUp_Touch_(pos); | 406 | 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. */ | |||
25 | #include <the_Foundation/defs.h> | 25 | #include <the_Foundation/defs.h> |
26 | #include <SDL_events.h> | 26 | #include <SDL_events.h> |
27 | 27 | ||
28 | iBool processEvent_Touch (const SDL_Event *); | 28 | iDeclareType(Widget) |
29 | void update_Touch (void); | 29 | |
30 | iBool processEvent_Touch (const SDL_Event *); | ||
31 | void update_Touch (void); | ||
32 | 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. */ | |||
23 | #include "widget.h" | 23 | #include "widget.h" |
24 | 24 | ||
25 | #include "app.h" | 25 | #include "app.h" |
26 | #include "touch.h" | ||
26 | #include "command.h" | 27 | #include "command.h" |
27 | #include "paint.h" | 28 | #include "paint.h" |
28 | #include "util.h" | 29 | #include "util.h" |
@@ -91,6 +92,7 @@ void deinit_Widget(iWidget *d) { | |||
91 | if (d->flags & keepOnTop_WidgetFlag) { | 92 | if (d->flags & keepOnTop_WidgetFlag) { |
92 | removeAll_PtrArray(onTop_RootData_(), d); | 93 | removeAll_PtrArray(onTop_RootData_(), d); |
93 | } | 94 | } |
95 | widgetDestroyed_Touch(d); | ||
94 | } | 96 | } |
95 | 97 | ||
96 | static void aboutToBeDestroyed_Widget_(iWidget *d) { | 98 | static void aboutToBeDestroyed_Widget_(iWidget *d) { |