diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-04-10 13:43:41 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-04-10 13:43:41 +0300 |
commit | 22f1d02ff1d9c7ee89a80969f2122968b9b5e1fe (patch) | |
tree | ccf0174fbd9b2a57589731ac0e30765b445b6032 | |
parent | 4e8977f5734663956613caac058849273c4e5ac0 (diff) |
Touch: Improved hover behavior
Scrolling must prevent the hover state from being updated both in documents and lists.
-rw-r--r-- | src/ui/documentwidget.c | 6 | ||||
-rw-r--r-- | src/ui/listwidget.c | 34 | ||||
-rw-r--r-- | src/ui/touch.c | 1 |
3 files changed, 29 insertions, 12 deletions
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index c3a6d40d..e18d5283 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -2585,7 +2585,7 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e | |||
2585 | return iTrue; | 2585 | return iTrue; |
2586 | } | 2586 | } |
2587 | else if (ev->type == SDL_MOUSEMOTION) { | 2587 | else if (ev->type == SDL_MOUSEMOTION) { |
2588 | if (deviceType_App() == desktop_AppDeviceType) { | 2588 | if (ev->motion.which != SDL_TOUCH_MOUSEID) { |
2589 | iChangeFlags(d->flags, noHoverWhileScrolling_DocumentWidgetFlag, iFalse); | 2589 | iChangeFlags(d->flags, noHoverWhileScrolling_DocumentWidgetFlag, iFalse); |
2590 | } | 2590 | } |
2591 | const iInt2 mpos = init_I2(ev->motion.x, ev->motion.y); | 2591 | const iInt2 mpos = init_I2(ev->motion.x, ev->motion.y); |
@@ -2763,6 +2763,10 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e | |||
2763 | if (d->grabbedPlayer) { | 2763 | if (d->grabbedPlayer) { |
2764 | return iTrue; | 2764 | return iTrue; |
2765 | } | 2765 | } |
2766 | if (d->flags & noHoverWhileScrolling_DocumentWidgetFlag) { | ||
2767 | d->flags &= ~noHoverWhileScrolling_DocumentWidgetFlag; | ||
2768 | updateHover_DocumentWidget_(d, mouseCoord_Window(get_Window())); | ||
2769 | } | ||
2766 | iChangeFlags(d->flags, selecting_DocumentWidgetFlag, iFalse); | 2770 | iChangeFlags(d->flags, selecting_DocumentWidgetFlag, iFalse); |
2767 | iChangeFlags(d->flags, selectWords_DocumentWidgetFlag, d->click.count == 2); | 2771 | iChangeFlags(d->flags, selectWords_DocumentWidgetFlag, d->click.count == 2); |
2768 | iChangeFlags(d->flags, selectLines_DocumentWidgetFlag, d->click.count >= 3); | 2772 | iChangeFlags(d->flags, selectLines_DocumentWidgetFlag, d->click.count >= 3); |
diff --git a/src/ui/listwidget.c b/src/ui/listwidget.c index dbd8e540..daf22bda 100644 --- a/src/ui/listwidget.c +++ b/src/ui/listwidget.c | |||
@@ -57,6 +57,7 @@ struct Impl_ListWidget { | |||
57 | iClick click; | 57 | iClick click; |
58 | iIntSet invalidItems; | 58 | iIntSet invalidItems; |
59 | iVisBuf *visBuf; | 59 | iVisBuf *visBuf; |
60 | iBool noHoverWhileScrolling; | ||
60 | }; | 61 | }; |
61 | 62 | ||
62 | void init_ListWidget(iListWidget *d) { | 63 | void init_ListWidget(iListWidget *d) { |
@@ -69,6 +70,7 @@ void init_ListWidget(iListWidget *d) { | |||
69 | setThumb_ScrollWidget(d->scroll, 0, 0); | 70 | setThumb_ScrollWidget(d->scroll, 0, 0); |
70 | d->scrollY = 0; | 71 | d->scrollY = 0; |
71 | d->itemHeight = 0; | 72 | d->itemHeight = 0; |
73 | d->noHoverWhileScrolling = iFalse; | ||
72 | init_PtrArray(&d->items); | 74 | init_PtrArray(&d->items); |
73 | d->hoverItem = iInvalidPos; | 75 | d->hoverItem = iInvalidPos; |
74 | init_Click(&d->click, d, SDL_BUTTON_LEFT); | 76 | init_Click(&d->click, d, SDL_BUTTON_LEFT); |
@@ -173,6 +175,7 @@ iBool scrollOffset_ListWidget(iListWidget *d, int offset) { | |||
173 | } | 175 | } |
174 | const int scrollMax = scrollMax_ListWidget_(d); | 176 | const int scrollMax = scrollMax_ListWidget_(d); |
175 | d->scrollY = iMin(d->scrollY, scrollMax); | 177 | d->scrollY = iMin(d->scrollY, scrollMax); |
178 | d->noHoverWhileScrolling = iTrue; | ||
176 | if (oldScroll != d->scrollY) { | 179 | if (oldScroll != d->scrollY) { |
177 | if (d->hoverItem != iInvalidPos) { | 180 | if (d->hoverItem != iInvalidPos) { |
178 | invalidateItem_ListWidget(d, d->hoverItem); | 181 | invalidateItem_ListWidget(d, d->hoverItem); |
@@ -256,10 +259,8 @@ static void setHoverItem_ListWidget_(iListWidget *d, size_t index) { | |||
256 | } | 259 | } |
257 | } | 260 | } |
258 | if (d->hoverItem != index) { | 261 | if (d->hoverItem != index) { |
259 | if (deviceType_App() == desktop_AppDeviceType || numFingers_Touch()) { | 262 | insert_IntSet(&d->invalidItems, d->hoverItem); |
260 | insert_IntSet(&d->invalidItems, d->hoverItem); | 263 | insert_IntSet(&d->invalidItems, index); |
261 | insert_IntSet(&d->invalidItems, index); | ||
262 | } | ||
263 | d->hoverItem = index; | 264 | d->hoverItem = index; |
264 | refresh_Widget(as_Widget(d)); | 265 | refresh_Widget(as_Widget(d)); |
265 | } | 266 | } |
@@ -284,6 +285,16 @@ static void sizeChanged_ListWidget_(iListWidget *d) { | |||
284 | invalidate_ListWidget(d); | 285 | invalidate_ListWidget(d); |
285 | } | 286 | } |
286 | 287 | ||
288 | static void updateHover_ListWidget_(iListWidget *d, const iInt2 mouse) { | ||
289 | size_t hover = iInvalidPos; | ||
290 | if (!d->noHoverWhileScrolling && | ||
291 | !contains_Widget(constAs_Widget(d->scroll), mouse) && | ||
292 | contains_Widget(constAs_Widget(d), mouse)) { | ||
293 | hover = itemIndex_ListWidget(d, mouse); | ||
294 | } | ||
295 | setHoverItem_ListWidget_(d, hover); | ||
296 | } | ||
297 | |||
287 | static iBool processEvent_ListWidget_(iListWidget *d, const SDL_Event *ev) { | 298 | static iBool processEvent_ListWidget_(iListWidget *d, const SDL_Event *ev) { |
288 | iWidget *w = as_Widget(d); | 299 | iWidget *w = as_Widget(d); |
289 | if (isMetricsChange_UserEvent(ev)) { | 300 | if (isMetricsChange_UserEvent(ev)) { |
@@ -299,14 +310,14 @@ static iBool processEvent_ListWidget_(iListWidget *d, const SDL_Event *ev) { | |||
299 | return iTrue; | 310 | return iTrue; |
300 | } | 311 | } |
301 | } | 312 | } |
313 | else if (ev->type == SDL_USEREVENT && ev->user.code == widgetTapBegins_UserEventCode) { | ||
314 | d->noHoverWhileScrolling = iFalse; | ||
315 | } | ||
302 | if (ev->type == SDL_MOUSEMOTION) { | 316 | if (ev->type == SDL_MOUSEMOTION) { |
303 | const iInt2 mouse = init_I2(ev->motion.x, ev->motion.y); | 317 | if (ev->motion.which != SDL_TOUCH_MOUSEID) { |
304 | size_t hover = iInvalidPos; | 318 | d->noHoverWhileScrolling = iFalse; |
305 | if (!contains_Widget(constAs_Widget(d->scroll), mouse) && | ||
306 | contains_Widget(w, mouse)) { | ||
307 | hover = itemIndex_ListWidget(d, mouse); | ||
308 | } | 319 | } |
309 | setHoverItem_ListWidget_(d, hover); | 320 | updateHover_ListWidget_(d, init_I2(ev->motion.x, ev->motion.y)); |
310 | } | 321 | } |
311 | if (ev->type == SDL_MOUSEWHEEL && isHover_Widget(w)) { | 322 | if (ev->type == SDL_MOUSEWHEEL && isHover_Widget(w)) { |
312 | int amount = -ev->wheel.y; | 323 | int amount = -ev->wheel.y; |
@@ -318,13 +329,14 @@ static iBool processEvent_ListWidget_(iListWidget *d, const SDL_Event *ev) { | |||
318 | } | 329 | } |
319 | switch (processEvent_Click(&d->click, ev)) { | 330 | switch (processEvent_Click(&d->click, ev)) { |
320 | case started_ClickResult: | 331 | case started_ClickResult: |
332 | d->noHoverWhileScrolling = iFalse; | ||
333 | updateHover_ListWidget_(d, mouseCoord_Window(get_Window())); | ||
321 | redrawHoverItem_ListWidget_(d); | 334 | redrawHoverItem_ListWidget_(d); |
322 | return iTrue; | 335 | return iTrue; |
323 | case aborted_ClickResult: | 336 | case aborted_ClickResult: |
324 | redrawHoverItem_ListWidget_(d); | 337 | redrawHoverItem_ListWidget_(d); |
325 | break; | 338 | break; |
326 | case finished_ClickResult: | 339 | case finished_ClickResult: |
327 | // case double_ClickResult: | ||
328 | redrawHoverItem_ListWidget_(d); | 340 | redrawHoverItem_ListWidget_(d); |
329 | if (contains_Rect(innerBounds_Widget(w), pos_Click(&d->click)) && | 341 | if (contains_Rect(innerBounds_Widget(w), pos_Click(&d->click)) && |
330 | d->hoverItem != iInvalidSize) { | 342 | d->hoverItem != iInvalidSize) { |
diff --git a/src/ui/touch.c b/src/ui/touch.c index bf217301..87bb7478 100644 --- a/src/ui/touch.c +++ b/src/ui/touch.c | |||
@@ -234,6 +234,7 @@ static void update_TouchState_(void *ptr) { | |||
234 | const int elapsed = nowTime - touch->startTime; | 234 | const int elapsed = nowTime - touch->startTime; |
235 | if (elapsed > 25) { | 235 | if (elapsed > 25) { |
236 | clearWidgetMomentum_TouchState_(d, touch->affinity); | 236 | clearWidgetMomentum_TouchState_(d, touch->affinity); |
237 | clear_Array(d->moms); /* stop all ongoing momentum */ | ||
237 | } | 238 | } |
238 | if (elapsed > 50 && !touch->isTapBegun) { | 239 | if (elapsed > 50 && !touch->isTapBegun) { |
239 | /* Looks like a possible tap. */ | 240 | /* Looks like a possible tap. */ |