summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Martitz <kugel@rockbox.org>2012-04-08 13:15:39 +0200
committerThomas Martitz <kugel@rockbox.org>2012-04-08 13:16:54 +0200
commit688302a3b3cee640c268ba767b469fec5bfa2ca8 (patch)
tree33f8aecb42dc8e8adfa015f0e272faba344f2f96
parenta12b2a5df96233465a2811f9b056e15d7ff30ee2 (diff)
downloadrockbox-688302a3b3cee640c268ba767b469fec5bfa2ca8.tar.gz
rockbox-688302a3b3cee640c268ba767b469fec5bfa2ca8.zip
touchscreen: Rewrite kinetic scrolling using a state machine.
The old code was very confusing. The scrolling modes need to be handled differently, thus a state machine makes sense. Should fix numerious glitches and be easier to maintain. NOTE: Behavior is still a bit glitchy with an SBS in use, because the skin engine sees the touch events earlier than the list code. Change-Id: I4ccead359c81de0d0fc3dea636fe2cb3a28d1bc6
-rw-r--r--apps/gui/bitmap/list.c416
1 files changed, 213 insertions, 203 deletions
diff --git a/apps/gui/bitmap/list.c b/apps/gui/bitmap/list.c
index 2f13d8ba53..05a7f066af 100644
--- a/apps/gui/bitmap/list.c
+++ b/apps/gui/bitmap/list.c
@@ -48,17 +48,8 @@
48static struct viewport list_text[NB_SCREENS], title_text[NB_SCREENS]; 48static struct viewport list_text[NB_SCREENS], title_text[NB_SCREENS];
49 49
50#ifdef HAVE_TOUCHSCREEN 50#ifdef HAVE_TOUCHSCREEN
51/* difference in pixels between draws, above it means enough to start scrolling */
52#define SCROLL_BEGIN_THRESHOLD 3
53
54static enum {
55 SCROLL_NONE, /* no scrolling */
56 SCROLL_BAR, /* scroll by using the scrollbar */
57 SCROLL_SWIPE, /* scroll by wiping over the screen */
58 SCROLL_KINETIC, /* state after releasing swipe */
59} scroll_mode;
60
61static int y_offset; 51static int y_offset;
52static bool hide_selection = true;
62#endif 53#endif
63 54
64int gui_list_get_item_offset(struct gui_synclist * gui_list, int item_width, 55int gui_list_get_item_offset(struct gui_synclist * gui_list, int item_width,
@@ -90,6 +81,17 @@ void gui_synclist_scroll_stop(struct gui_synclist *lists)
90 Note: This image is flipped horizontally when the language is a 81 Note: This image is flipped horizontally when the language is a
91 right-to-left one (Hebrew, Arabic) 82 right-to-left one (Hebrew, Arabic)
92*/ 83*/
84
85static int list_icon_width(enum screen_type screen)
86{
87 return get_icon_width(screen) + ICON_PADDING * 2;
88}
89
90static int list_icon_height(enum screen_type screen)
91{
92 return get_icon_height(screen);
93}
94
93static bool draw_title(struct screen *display, struct gui_synclist *list) 95static bool draw_title(struct screen *display, struct gui_synclist *list)
94{ 96{
95 const int screen = display->screen_type; 97 const int screen = display->screen_type;
@@ -108,9 +110,9 @@ static bool draw_title(struct screen *display, struct gui_synclist *list)
108 { 110 {
109 struct viewport title_icon = *title_text_vp; 111 struct viewport title_icon = *title_text_vp;
110 112
111 title_icon.width = get_icon_width(screen) + ICON_PADDING * 2; 113 title_icon.width = list_icon_width(screen);
112 title_icon.y += (title_icon.height - get_icon_height(screen)) / 2; 114 title_icon.y += (title_icon.height - list_icon_height(screen)) / 2;
113 title_icon.height = get_icon_height(screen); 115 title_icon.height = list_icon_height(screen);
114 if (VP_IS_RTL(&title_icon)) 116 if (VP_IS_RTL(&title_icon))
115 { 117 {
116 title_icon.x += title_text_vp->width - title_icon.width; 118 title_icon.x += title_text_vp->width - title_icon.width;
@@ -141,7 +143,7 @@ void list_draw(struct screen *display, struct gui_synclist *list)
141 int start, end, line_height, style, item_offset, i; 143 int start, end, line_height, style, item_offset, i;
142 const int screen = display->screen_type; 144 const int screen = display->screen_type;
143 const int list_start_item = list->start_item[screen]; 145 const int list_start_item = list->start_item[screen];
144 const int icon_width = get_icon_width(screen) + ICON_PADDING; 146 const int icon_width = list_icon_width(screen);
145 const bool scrollbar_in_left = (global_settings.scrollbar == SCROLLBAR_LEFT); 147 const bool scrollbar_in_left = (global_settings.scrollbar == SCROLLBAR_LEFT);
146 const bool show_cursor = !global_settings.cursor_style && 148 const bool show_cursor = !global_settings.cursor_style &&
147 list->show_selection_marker; 149 list->show_selection_marker;
@@ -236,7 +238,7 @@ void list_draw(struct screen *display, struct gui_synclist *list)
236 list_icons.x += list_text_vp->width + ICON_PADDING; 238 list_icons.x += list_text_vp->width + ICON_PADDING;
237 else 239 else
238 list_text_vp->x += list_icons.width + ICON_PADDING; 240 list_text_vp->x += list_icons.width + ICON_PADDING;
239 icon_yoffset = (line_height - get_icon_height(screen)) / 2; 241 icon_yoffset = (line_height - list_icon_height(screen)) / 2;
240 } 242 }
241 243
242 for (i=start; i<end && i<list->nb_items; i++) 244 for (i=start; i<end && i<list->nb_items; i++)
@@ -274,7 +276,7 @@ void list_draw(struct screen *display, struct gui_synclist *list)
274 if( 276 if(
275#ifdef HAVE_TOUCHSCREEN 277#ifdef HAVE_TOUCHSCREEN
276 /* don't draw it during scrolling */ 278 /* don't draw it during scrolling */
277 scroll_mode == SCROLL_NONE && 279 !hide_selection &&
278#endif 280#endif
279 i >= list->selected_item 281 i >= list->selected_item
280 && i < list->selected_item + list->selected_size 282 && i < list->selected_item + list->selected_size
@@ -338,7 +340,7 @@ void list_draw(struct screen *display, struct gui_synclist *list)
338 display->set_viewport(&list_icons); 340 display->set_viewport(&list_icons);
339 if (list->callback_get_item_icon != NULL) 341 if (list->callback_get_item_icon != NULL)
340 { 342 {
341 int xoff = show_cursor ? get_icon_width(screen) + ICON_PADDING : 0; 343 int xoff = show_cursor ? list_icon_width(screen) : 0;
342 screen_put_iconxy(display, xoff, 344 screen_put_iconxy(display, xoff,
343 line*line_height + draw_offset + icon_yoffset, 345 line*line_height + draw_offset + icon_yoffset,
344 list->callback_get_item_icon(i, list->data)); 346 list->callback_get_item_icon(i, list->data));
@@ -360,13 +362,15 @@ void list_draw(struct screen *display, struct gui_synclist *list)
360#if defined(HAVE_TOUCHSCREEN) 362#if defined(HAVE_TOUCHSCREEN)
361/* This needs to be fixed if we ever get more than 1 touchscreen on a target. */ 363/* This needs to be fixed if we ever get more than 1 touchscreen on a target. */
362 364
363static bool released = false; 365/* difference in pixels between draws, above it means enough to start scrolling */
366#define SCROLL_BEGIN_THRESHOLD 3
364 367
365/* Used for kinetic scrolling as we need to know the last position to 368static enum {
366 * recognize the scroll direction. 369 SCROLL_NONE, /* no scrolling */
367 * This gets reset to 0 at the end of scrolling 370 SCROLL_BAR, /* scroll by using the scrollbar */
368 */ 371 SCROLL_SWIPE, /* scroll by wiping over the screen */
369static int last_position=0; 372 SCROLL_KINETIC, /* state after releasing swipe */
373} scroll_mode;
370 374
371static int scrollbar_scroll(struct gui_synclist * gui_list, 375static int scrollbar_scroll(struct gui_synclist * gui_list,
372 int y) 376 int y)
@@ -486,6 +490,7 @@ void _gui_synclist_stop_kinetic_scrolling(void)
486 if (scroll_mode == SCROLL_KINETIC) 490 if (scroll_mode == SCROLL_KINETIC)
487 kinetic_force_stop(); 491 kinetic_force_stop();
488 scroll_mode = SCROLL_NONE; 492 scroll_mode = SCROLL_NONE;
493 hide_selection = false;
489} 494}
490/* 495/*
491 * returns false if scrolling should be stopped entirely 496 * returns false if scrolling should be stopped entirely
@@ -497,11 +502,12 @@ void _gui_synclist_stop_kinetic_scrolling(void)
497 502
498static int scroll_begin_threshold; 503static int scroll_begin_threshold;
499static int threshold_accumulation; 504static int threshold_accumulation;
500static bool swipe_scroll(struct gui_synclist * gui_list, int line_height, int difference) 505static bool swipe_scroll(struct gui_synclist * gui_list, int difference)
501{ 506{
502 /* fixme */ 507 /* fixme */
503 const enum screen_type screen = screens[SCREEN_MAIN].screen_type; 508 const enum screen_type screen = screens[SCREEN_MAIN].screen_type;
504 const int nb_lines = viewport_get_nb_lines(&list_text[screen]); 509 const int nb_lines = viewport_get_nb_lines(&list_text[screen]);
510 const int line_height = gui_list->parent[0]->line_height;
505 511
506 if (UNLIKELY(scroll_begin_threshold == 0)) 512 if (UNLIKELY(scroll_begin_threshold == 0))
507 scroll_begin_threshold = touchscreen_get_scroll_threshold(); 513 scroll_begin_threshold = touchscreen_get_scroll_threshold();
@@ -566,13 +572,12 @@ static int kinetic_callback(struct timeout *tmo)
566 return 0; 572 return 0;
567 573
568 struct cb_data *data = (struct cb_data*)tmo->data; 574 struct cb_data *data = (struct cb_data*)tmo->data;
569 int line_height = data->list->parent[0]->line_height;
570 /* ds = v*dt */ 575 /* ds = v*dt */
571 int pixel_diff = data->velocity * RELOAD_INTERVAL / HZ; 576 int pixel_diff = data->velocity * RELOAD_INTERVAL / HZ;
572 /* remember signedness to detect stopping */ 577 /* remember signedness to detect stopping */
573 int old_sign = SIGN(data->velocity); 578 int old_sign = SIGN(data->velocity);
574 /* advance the list */ 579 /* advance the list */
575 if (!swipe_scroll(data->list, line_height, pixel_diff)) 580 if (!swipe_scroll(data->list, pixel_diff))
576 { 581 {
577 /* nothing to scroll? */ 582 /* nothing to scroll? */
578 data->velocity = 0; 583 data->velocity = 0;
@@ -587,6 +592,8 @@ static int kinetic_callback(struct timeout *tmo)
587 data->velocity = 0; 592 data->velocity = 0;
588 } 593 }
589 594
595 /* let get_action() timeout, which loads to a
596 * gui_synclist_draw() call from the main thread */
590 queue_post(&button_queue, BUTTON_REDRAW, 0); 597 queue_post(&button_queue, BUTTON_REDRAW, 0);
591 /* stop if the velocity hit or crossed zero */ 598 /* stop if the velocity hit or crossed zero */
592 if (!data->velocity) 599 if (!data->velocity)
@@ -594,8 +601,6 @@ static int kinetic_callback(struct timeout *tmo)
594 kinetic_stats_reset(); 601 kinetic_stats_reset();
595 return 0; 602 return 0;
596 } 603 }
597 /* let get_action() timeout, which loads to a
598 * gui_synclist_draw() call from the main thread */
599 return RELOAD_INTERVAL; /* cancel or reload */ 604 return RELOAD_INTERVAL; /* cancel or reload */
600} 605}
601 606
@@ -628,208 +633,213 @@ static bool kinetic_setup_scroll(struct gui_synclist *list)
628 return false; 633 return false;
629} 634}
630 635
631unsigned gui_synclist_do_touchscreen(struct gui_synclist * gui_list) 636#define OUTSIDE 0
632{ 637#define TITLE_TEXT (1<<0)
633 short x, y; 638#define TITLE_ICON (1<<1)
634 const enum screen_type screen = SCREEN_MAIN; 639#define SCROLLBAR (1<<2)
635 struct viewport *parent = gui_list->parent[screen]; 640#define LIST_TEXT (1<<3)
636 const int button = action_get_touchscreen_press_in_vp(&x, &y, parent); 641#define LIST_ICON (1<<4)
637 const int list_start_item = gui_list->start_item[screen];
638 const int line_height = gui_list->parent[screen]->line_height;
639 const struct viewport *list_text_vp = &list_text[screen];
640 const bool old_released = released;
641 const bool show_title = list_display_title(gui_list, screen);
642 const bool show_cursor = !global_settings.cursor_style &&
643 gui_list->show_selection_marker;
644 const bool on_title_clicked = show_title && y < line_height && (button&BUTTON_REL);
645 const bool cancelled_kinetic = (scroll_mode == SCROLL_KINETIC
646 && button != ACTION_NONE && button != ACTION_UNKNOWN
647 && !is_kinetic_over());
648 int icon_width = 0;
649 int line, list_width = list_text_vp->width;
650 642
651 released = (button&BUTTON_REL) != 0; 643#define TITLE (TITLE_TEXT|TITLE_ICON)
652 644#define LIST (LIST_TEXT|LIST_ICON)
653 if (button == ACTION_NONE || button == ACTION_UNKNOWN)
654 {
655 /* this happens when we hit edges of the list while kinetic scrolling,
656 * but not when manually cancelling */
657 if (scroll_mode == SCROLL_KINETIC)
658 return ACTION_REDRAW;
659 return ACTION_NONE;
660 }
661 645
662 /* x and y are relative to parent */ 646static int get_click_location(struct gui_synclist *list, int x, int y)
663 if (gui_list->callback_get_item_icon != NULL) 647{
664 icon_width += get_icon_width(screen); 648 int screen = SCREEN_MAIN;
665 if (show_cursor) 649 struct viewport *parent, *title, *text;
666 icon_width += get_icon_width(screen); 650 int retval = OUTSIDE;
667 651
668 if (on_title_clicked) 652 parent = list->parent[screen];
653 if (viewport_point_within_vp(parent, x, y))
669 { 654 {
670 if (scroll_mode == SCROLL_NONE || is_kinetic_over()) 655 /* see if the title was clicked */
656 title = &title_text[screen];
657 if (viewport_point_within_vp(title, x, y))
658 retval = TITLE_TEXT;
659 /* check the icon too */
660 if (list->title_icon != Icon_NOICON && global_settings.show_icons)
661 {
662 int width = list_icon_width(screen);
663 struct viewport vp = *title;
664 if (VP_IS_RTL(&vp))
665 vp.x += vp.width;
666 else
667 vp.x -= width;
668 vp.width = width;
669 if (viewport_point_within_vp(&vp, x, y))
670 retval = TITLE_ICON;
671 }
672 /* check scrollbar. assume it's shown, if it isn't it will be handled
673 * later */
674 if (retval == OUTSIDE)
671 { 675 {
672 if (x < icon_width) 676 bool on_scrollbar_clicked;
677 int adj_x = x - parent->x;
678 switch (global_settings.scrollbar)
673 { 679 {
674 /* Top left corner is GO_TO_ROOT */ 680 case SCROLLBAR_LEFT:
675 if (button == BUTTON_REL) 681 on_scrollbar_clicked = adj_x <= SCROLLBAR_WIDTH; break;
676 return ACTION_STD_MENU; 682 case SCROLLBAR_RIGHT:
677 else if (button == (BUTTON_REPEAT|BUTTON_REL)) 683 on_scrollbar_clicked = adj_x > (title->x + title->width - SCROLLBAR_WIDTH); break;
678 return ACTION_STD_CONTEXT; 684 default:
679 return ACTION_NONE; 685 on_scrollbar_clicked = false; break;
680 } 686 }
681 else /* click on title text is cancel */ 687 if (on_scrollbar_clicked)
682 if (button == BUTTON_REL) 688 retval = SCROLLBAR;
683 return ACTION_STD_CANCEL;
684 } 689 }
685 /* do this after the above so the scrolling stops without 690 if (retval == OUTSIDE)
686 * going back in the list with the same touch */
687 if (scroll_mode == SCROLL_KINETIC)
688 { 691 {
689 kinetic_force_stop(); 692 text = &list_text[screen];
690 scroll_mode = SCROLL_NONE; 693 if (viewport_point_within_vp(text, x, y))
694 retval = LIST_TEXT;
695 else /* if all fails, it must be on the list icons */
696 retval = LIST_ICON;
691 } 697 }
692 } 698 }
693 else /* list area clicked (or not released) */ 699 return retval;
694 { 700}
695 const int actual_y = y - (show_title ? line_height : 0);
696 bool on_scrollbar_clicked;
697 switch (global_settings.scrollbar)
698 {
699 case SCROLLBAR_LEFT:
700 on_scrollbar_clicked = x <= SCROLLBAR_WIDTH; break;
701 case SCROLLBAR_RIGHT:
702 on_scrollbar_clicked = x > (icon_width + list_width); break;
703 default:
704 on_scrollbar_clicked = false; break;
705 }
706 /* conditions for scrollbar scrolling:
707 * * pen is on the scrollbar
708 * AND scrollbar is on the right (left case is handled above)
709 * OR * pen is in the somewhere else but we did scrollbar scrolling before
710 *
711 * scrollbar scrolling must end if the pen is released
712 * scrollbar scrolling must not happen if we're currently scrolling
713 * via swiping the screen
714 **/
715
716 if (!released && scroll_mode != SCROLL_SWIPE &&
717 (on_scrollbar_clicked || scroll_mode == SCROLL_BAR))
718 {
719 if (scroll_mode == SCROLL_KINETIC)
720 kinetic_force_stop();
721 scroll_mode = SCROLL_BAR;
722 return scrollbar_scroll(gui_list, y);
723 }
724 701
725 /* |--------------------------------------------------------| 702unsigned gui_synclist_do_touchscreen(struct gui_synclist * list)
726 * | Description of the touchscreen list interface: | 703{
727 * |--------------------------------------------------------| 704 enum screen_type screen;
728 * | Pressing an item will select it and "enter" it. | 705 struct viewport *parent;
729 * | | 706 short x, y;
730 * | Pressing and holding your pen down will scroll through | 707 int action, adj_y, line, line_height, list_start_item;
731 * | the list of items. | 708 bool recurse;
732 * | | 709 static int last_y;
733 * | Pressing and holding your pen down on a single item | 710
734 * | will bring up the context menu of it. | 711 screen = SCREEN_MAIN;
735 * |--------------------------------------------------------| 712 parent = list->parent[screen];
736 */ 713 line_height = list->parent[screen]->line_height;
737 if (actual_y > 0 || button & BUTTON_REPEAT) 714 list_start_item = list->start_item[screen];
715 /* start with getting the action code and finding the click location */
716 action = action_get_touchscreen_press(&x, &y);
717 adj_y = y - parent->y;
718
719 /* selection needs to be corrected if items are only partially visible */
720 line = (adj_y - y_offset) / line_height;
721 if (list_display_title(list, screen))
722 line -= 1; /* adjust for the list title */
723
724 /* some defaults before running the state machine */
725 recurse = false;
726 hide_selection = true;
727
728 switch (scroll_mode)
729 {
730 case SCROLL_NONE:
738 { 731 {
739 /* selection needs to be corrected if an items are only 732 list->selected_item = list_start_item+line;
740 * partially visible */ 733 gui_synclist_speak_item(list);
741 line = (actual_y - y_offset) / line_height; 734 if (!last_y)
742 735 { /* first run. register adj_y and re-run (will then take the else case) */
743 if (cancelled_kinetic) 736 last_y = adj_y;
744 { 737 recurse = true;
745 kinetic_force_stop();
746 scroll_mode = SCROLL_SWIPE;
747 }
748
749 /* Pressed below the list*/
750 if (list_start_item + line >= gui_list->nb_items)
751 {
752 /* don't collect last_position outside of the list area
753 * it'd break selecting after such a situation */
754 last_position = 0;
755 return ACTION_NONE;
756 } 738 }
757 739 else
758 if (button & BUTTON_REPEAT && scroll_mode == SCROLL_NONE)
759 {
760 /* held a single line for a while, bring up the context menu */
761 gui_synclist_select_item(gui_list, list_start_item + line);
762 /* don't sent context repeatedly */
763 action_wait_for_release();
764 last_position = 0;
765 return ACTION_STD_CONTEXT;
766 }
767 if (released && !cancelled_kinetic)
768 { 740 {
769 /* Pen was released anywhere on the screen */ 741 int click_loc = get_click_location(list, x, y);
770 last_position = 0; 742 if (action == BUTTON_TOUCHSCREEN)
771 if (scroll_mode == SCROLL_NONE)
772 { 743 {
773 /* select current line */ 744 /* if not scrolling, the user is trying to select */
774 gui_synclist_select_item(gui_list, list_start_item + line); 745 int diff = adj_y - last_y;
775 return ACTION_STD_OK; 746 if ((click_loc & LIST) && swipe_scroll(list, diff))
747 scroll_mode = SCROLL_SWIPE;
748 else if (click_loc & SCROLLBAR)
749 scroll_mode = SCROLL_BAR;
750
751 hide_selection = click_loc & SCROLLBAR;
776 } 752 }
777 else 753 else if (action == BUTTON_REPEAT)
778 { 754 {
779 /* we were scrolling 755 if (click_loc & LIST)
780 * -> reset scrolling but do nothing else */
781 if (scroll_mode == SCROLL_SWIPE)
782 { 756 {
783 if (kinetic_setup_scroll(gui_list)) 757 /* held a single line for a while, bring up the context menu */
784 scroll_mode = SCROLL_KINETIC; 758 gui_synclist_select_item(list, list_start_item + line);
759 /* don't sent context repeatedly */
760 action_wait_for_release();
761 last_y = 0;
762 return ACTION_STD_CONTEXT;
785 } 763 }
786 if (scroll_mode != SCROLL_KINETIC)
787 scroll_mode = SCROLL_NONE;
788 return ACTION_NONE;
789 } 764 }
790 } 765 else if (action & BUTTON_REL)
791 else
792 { /* pen is on the screen */
793 bool redraw = false, result = false;
794 /* beginning of list interaction denoted by release in
795 * the previous call */
796 if (old_released || is_kinetic_over())
797 { 766 {
798 scroll_mode = SCROLL_NONE; 767 last_y = 0;
799 redraw = true; 768 if (click_loc & LIST)
800 } 769 { /* release on list item enters it */
801 770 gui_synclist_select_item(list, list_start_item + line);
802 /* select current item; gui_synclist_select_item() 771 return ACTION_STD_OK;
803 * is not called because it has side effects that 772 }
804 * disturb kinetic scrolling */ 773 else if (click_loc & TITLE_TEXT)
805 gui_list->selected_item = list_start_item+line; 774 { /* clicking the title goes one level up (cancel) */
806 gui_synclist_speak_item(gui_list); 775 return ACTION_STD_CANCEL;
807 if (last_position == 0) 776 }
808 { 777 else if (click_loc & TITLE_ICON)
809 redraw = true; 778 { /* clicking the title icon goes back to the root */
810 last_position = actual_y; 779 return ACTION_STD_MENU;
811 } 780 }
812 else
813 {
814 /* record speed data in case we do kinetic scrolling */
815 int diff = actual_y - last_position;
816 kinetic_stats_collect(diff);
817 result = swipe_scroll(gui_list, line_height, diff);
818 } 781 }
819 782 }
820 /* Start scrolling once the pen is moved without 783 break;
821 * releasing it inbetween */ 784 }
822 if (result) 785 case SCROLL_SWIPE:
786 {
787 /* when swipe scrolling, we accept outside presses as well and
788 * grab the entire screen (i.e. click_loc does not matter) */
789 int diff = adj_y - last_y;
790 kinetic_stats_collect(diff);
791 if (swipe_scroll(list, diff))
792 {
793 /* letting the pen go enters kinetic scrolling */
794 if ((action & BUTTON_REL))
823 { 795 {
824 redraw = true; 796 if (kinetic_setup_scroll(list))
825 scroll_mode = SCROLL_SWIPE; 797 scroll_mode = SCROLL_KINETIC;
798 else
799 scroll_mode = SCROLL_NONE;
826 } 800 }
827 last_position = actual_y;
828
829 return redraw ? ACTION_REDRAW:ACTION_NONE;
830 } 801 }
802 else if (action & BUTTON_REL)
803 {
804 scroll_mode = SCROLL_NONE;
805 }
806 break;
807 }
808 case SCROLL_KINETIC:
809 {
810 /* during kinetic scrolling we need to handle cancellation.
811 * This state is actually only entered upon end of it as this
812 * function is not called during the animation. */
813 if (!is_kinetic_over())
814 { /* a) the user touched the screen (manual cancellation) */
815 kinetic_force_stop();
816 scroll_mode = SCROLL_SWIPE;
817 }
818 else
819 { /* b) kinetic scrolling stopped on its own */
820 /* need to re-run this with SCROLL_NONE since otherwise
821 * the next touch is not detected correctly */
822 scroll_mode = SCROLL_NONE;
823 recurse = true;
824 }
825 break;
826 }
827 case SCROLL_BAR:
828 {
829 /* similarly to swipe scroll, using the scrollbar grabs
830 * focus so the click location is irrelevant */
831 scrollbar_scroll(list, adj_y);
832 if (action & BUTTON_REL)
833 scroll_mode = SCROLL_NONE;
834 break;
831 } 835 }
832 } 836 }
833 return ACTION_REDRAW; 837
838 /* register y position unless forcefully reset to 0 */
839 if (last_y)
840 last_y = adj_y;
841
842 return recurse ? gui_synclist_do_touchscreen(list) : ACTION_REDRAW;
834} 843}
844
835#endif 845#endif