mirror of
https://github.com/Rockbox/rockbox.git
synced 2026-01-22 09:40:35 -05:00
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
This commit is contained in:
parent
a12b2a5df9
commit
688302a3b3
1 changed files with 221 additions and 211 deletions
|
|
@ -48,17 +48,8 @@
|
|||
static struct viewport list_text[NB_SCREENS], title_text[NB_SCREENS];
|
||||
|
||||
#ifdef HAVE_TOUCHSCREEN
|
||||
/* difference in pixels between draws, above it means enough to start scrolling */
|
||||
#define SCROLL_BEGIN_THRESHOLD 3
|
||||
|
||||
static enum {
|
||||
SCROLL_NONE, /* no scrolling */
|
||||
SCROLL_BAR, /* scroll by using the scrollbar */
|
||||
SCROLL_SWIPE, /* scroll by wiping over the screen */
|
||||
SCROLL_KINETIC, /* state after releasing swipe */
|
||||
} scroll_mode;
|
||||
|
||||
static int y_offset;
|
||||
static bool hide_selection = true;
|
||||
#endif
|
||||
|
||||
int 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)
|
|||
Note: This image is flipped horizontally when the language is a
|
||||
right-to-left one (Hebrew, Arabic)
|
||||
*/
|
||||
|
||||
static int list_icon_width(enum screen_type screen)
|
||||
{
|
||||
return get_icon_width(screen) + ICON_PADDING * 2;
|
||||
}
|
||||
|
||||
static int list_icon_height(enum screen_type screen)
|
||||
{
|
||||
return get_icon_height(screen);
|
||||
}
|
||||
|
||||
static bool draw_title(struct screen *display, struct gui_synclist *list)
|
||||
{
|
||||
const int screen = display->screen_type;
|
||||
|
|
@ -108,9 +110,9 @@ static bool draw_title(struct screen *display, struct gui_synclist *list)
|
|||
{
|
||||
struct viewport title_icon = *title_text_vp;
|
||||
|
||||
title_icon.width = get_icon_width(screen) + ICON_PADDING * 2;
|
||||
title_icon.y += (title_icon.height - get_icon_height(screen)) / 2;
|
||||
title_icon.height = get_icon_height(screen);
|
||||
title_icon.width = list_icon_width(screen);
|
||||
title_icon.y += (title_icon.height - list_icon_height(screen)) / 2;
|
||||
title_icon.height = list_icon_height(screen);
|
||||
if (VP_IS_RTL(&title_icon))
|
||||
{
|
||||
title_icon.x += title_text_vp->width - title_icon.width;
|
||||
|
|
@ -141,7 +143,7 @@ void list_draw(struct screen *display, struct gui_synclist *list)
|
|||
int start, end, line_height, style, item_offset, i;
|
||||
const int screen = display->screen_type;
|
||||
const int list_start_item = list->start_item[screen];
|
||||
const int icon_width = get_icon_width(screen) + ICON_PADDING;
|
||||
const int icon_width = list_icon_width(screen);
|
||||
const bool scrollbar_in_left = (global_settings.scrollbar == SCROLLBAR_LEFT);
|
||||
const bool show_cursor = !global_settings.cursor_style &&
|
||||
list->show_selection_marker;
|
||||
|
|
@ -236,7 +238,7 @@ void list_draw(struct screen *display, struct gui_synclist *list)
|
|||
list_icons.x += list_text_vp->width + ICON_PADDING;
|
||||
else
|
||||
list_text_vp->x += list_icons.width + ICON_PADDING;
|
||||
icon_yoffset = (line_height - get_icon_height(screen)) / 2;
|
||||
icon_yoffset = (line_height - list_icon_height(screen)) / 2;
|
||||
}
|
||||
|
||||
for (i=start; i<end && i<list->nb_items; i++)
|
||||
|
|
@ -274,7 +276,7 @@ void list_draw(struct screen *display, struct gui_synclist *list)
|
|||
if(
|
||||
#ifdef HAVE_TOUCHSCREEN
|
||||
/* don't draw it during scrolling */
|
||||
scroll_mode == SCROLL_NONE &&
|
||||
!hide_selection &&
|
||||
#endif
|
||||
i >= list->selected_item
|
||||
&& i < list->selected_item + list->selected_size
|
||||
|
|
@ -338,7 +340,7 @@ void list_draw(struct screen *display, struct gui_synclist *list)
|
|||
display->set_viewport(&list_icons);
|
||||
if (list->callback_get_item_icon != NULL)
|
||||
{
|
||||
int xoff = show_cursor ? get_icon_width(screen) + ICON_PADDING : 0;
|
||||
int xoff = show_cursor ? list_icon_width(screen) : 0;
|
||||
screen_put_iconxy(display, xoff,
|
||||
line*line_height + draw_offset + icon_yoffset,
|
||||
list->callback_get_item_icon(i, list->data));
|
||||
|
|
@ -360,13 +362,15 @@ void list_draw(struct screen *display, struct gui_synclist *list)
|
|||
#if defined(HAVE_TOUCHSCREEN)
|
||||
/* This needs to be fixed if we ever get more than 1 touchscreen on a target. */
|
||||
|
||||
static bool released = false;
|
||||
/* difference in pixels between draws, above it means enough to start scrolling */
|
||||
#define SCROLL_BEGIN_THRESHOLD 3
|
||||
|
||||
/* Used for kinetic scrolling as we need to know the last position to
|
||||
* recognize the scroll direction.
|
||||
* This gets reset to 0 at the end of scrolling
|
||||
*/
|
||||
static int last_position=0;
|
||||
static enum {
|
||||
SCROLL_NONE, /* no scrolling */
|
||||
SCROLL_BAR, /* scroll by using the scrollbar */
|
||||
SCROLL_SWIPE, /* scroll by wiping over the screen */
|
||||
SCROLL_KINETIC, /* state after releasing swipe */
|
||||
} scroll_mode;
|
||||
|
||||
static int scrollbar_scroll(struct gui_synclist * gui_list,
|
||||
int y)
|
||||
|
|
@ -486,6 +490,7 @@ void _gui_synclist_stop_kinetic_scrolling(void)
|
|||
if (scroll_mode == SCROLL_KINETIC)
|
||||
kinetic_force_stop();
|
||||
scroll_mode = SCROLL_NONE;
|
||||
hide_selection = false;
|
||||
}
|
||||
/*
|
||||
* returns false if scrolling should be stopped entirely
|
||||
|
|
@ -497,11 +502,12 @@ void _gui_synclist_stop_kinetic_scrolling(void)
|
|||
|
||||
static int scroll_begin_threshold;
|
||||
static int threshold_accumulation;
|
||||
static bool swipe_scroll(struct gui_synclist * gui_list, int line_height, int difference)
|
||||
static bool swipe_scroll(struct gui_synclist * gui_list, int difference)
|
||||
{
|
||||
/* fixme */
|
||||
const enum screen_type screen = screens[SCREEN_MAIN].screen_type;
|
||||
const int nb_lines = viewport_get_nb_lines(&list_text[screen]);
|
||||
const int line_height = gui_list->parent[0]->line_height;
|
||||
|
||||
if (UNLIKELY(scroll_begin_threshold == 0))
|
||||
scroll_begin_threshold = touchscreen_get_scroll_threshold();
|
||||
|
|
@ -566,13 +572,12 @@ static int kinetic_callback(struct timeout *tmo)
|
|||
return 0;
|
||||
|
||||
struct cb_data *data = (struct cb_data*)tmo->data;
|
||||
int line_height = data->list->parent[0]->line_height;
|
||||
/* ds = v*dt */
|
||||
int pixel_diff = data->velocity * RELOAD_INTERVAL / HZ;
|
||||
/* remember signedness to detect stopping */
|
||||
int old_sign = SIGN(data->velocity);
|
||||
/* advance the list */
|
||||
if (!swipe_scroll(data->list, line_height, pixel_diff))
|
||||
if (!swipe_scroll(data->list, pixel_diff))
|
||||
{
|
||||
/* nothing to scroll? */
|
||||
data->velocity = 0;
|
||||
|
|
@ -587,6 +592,8 @@ static int kinetic_callback(struct timeout *tmo)
|
|||
data->velocity = 0;
|
||||
}
|
||||
|
||||
/* let get_action() timeout, which loads to a
|
||||
* gui_synclist_draw() call from the main thread */
|
||||
queue_post(&button_queue, BUTTON_REDRAW, 0);
|
||||
/* stop if the velocity hit or crossed zero */
|
||||
if (!data->velocity)
|
||||
|
|
@ -594,8 +601,6 @@ static int kinetic_callback(struct timeout *tmo)
|
|||
kinetic_stats_reset();
|
||||
return 0;
|
||||
}
|
||||
/* let get_action() timeout, which loads to a
|
||||
* gui_synclist_draw() call from the main thread */
|
||||
return RELOAD_INTERVAL; /* cancel or reload */
|
||||
}
|
||||
|
||||
|
|
@ -628,208 +633,213 @@ static bool kinetic_setup_scroll(struct gui_synclist *list)
|
|||
return false;
|
||||
}
|
||||
|
||||
unsigned gui_synclist_do_touchscreen(struct gui_synclist * gui_list)
|
||||
#define OUTSIDE 0
|
||||
#define TITLE_TEXT (1<<0)
|
||||
#define TITLE_ICON (1<<1)
|
||||
#define SCROLLBAR (1<<2)
|
||||
#define LIST_TEXT (1<<3)
|
||||
#define LIST_ICON (1<<4)
|
||||
|
||||
#define TITLE (TITLE_TEXT|TITLE_ICON)
|
||||
#define LIST (LIST_TEXT|LIST_ICON)
|
||||
|
||||
static int get_click_location(struct gui_synclist *list, int x, int y)
|
||||
{
|
||||
short x, y;
|
||||
const enum screen_type screen = SCREEN_MAIN;
|
||||
struct viewport *parent = gui_list->parent[screen];
|
||||
const int button = action_get_touchscreen_press_in_vp(&x, &y, parent);
|
||||
const int list_start_item = gui_list->start_item[screen];
|
||||
const int line_height = gui_list->parent[screen]->line_height;
|
||||
const struct viewport *list_text_vp = &list_text[screen];
|
||||
const bool old_released = released;
|
||||
const bool show_title = list_display_title(gui_list, screen);
|
||||
const bool show_cursor = !global_settings.cursor_style &&
|
||||
gui_list->show_selection_marker;
|
||||
const bool on_title_clicked = show_title && y < line_height && (button&BUTTON_REL);
|
||||
const bool cancelled_kinetic = (scroll_mode == SCROLL_KINETIC
|
||||
&& button != ACTION_NONE && button != ACTION_UNKNOWN
|
||||
&& !is_kinetic_over());
|
||||
int icon_width = 0;
|
||||
int line, list_width = list_text_vp->width;
|
||||
int screen = SCREEN_MAIN;
|
||||
struct viewport *parent, *title, *text;
|
||||
int retval = OUTSIDE;
|
||||
|
||||
released = (button&BUTTON_REL) != 0;
|
||||
|
||||
if (button == ACTION_NONE || button == ACTION_UNKNOWN)
|
||||
parent = list->parent[screen];
|
||||
if (viewport_point_within_vp(parent, x, y))
|
||||
{
|
||||
/* this happens when we hit edges of the list while kinetic scrolling,
|
||||
* but not when manually cancelling */
|
||||
if (scroll_mode == SCROLL_KINETIC)
|
||||
return ACTION_REDRAW;
|
||||
return ACTION_NONE;
|
||||
}
|
||||
|
||||
/* x and y are relative to parent */
|
||||
if (gui_list->callback_get_item_icon != NULL)
|
||||
icon_width += get_icon_width(screen);
|
||||
if (show_cursor)
|
||||
icon_width += get_icon_width(screen);
|
||||
|
||||
if (on_title_clicked)
|
||||
{
|
||||
if (scroll_mode == SCROLL_NONE || is_kinetic_over())
|
||||
/* see if the title was clicked */
|
||||
title = &title_text[screen];
|
||||
if (viewport_point_within_vp(title, x, y))
|
||||
retval = TITLE_TEXT;
|
||||
/* check the icon too */
|
||||
if (list->title_icon != Icon_NOICON && global_settings.show_icons)
|
||||
{
|
||||
if (x < icon_width)
|
||||
int width = list_icon_width(screen);
|
||||
struct viewport vp = *title;
|
||||
if (VP_IS_RTL(&vp))
|
||||
vp.x += vp.width;
|
||||
else
|
||||
vp.x -= width;
|
||||
vp.width = width;
|
||||
if (viewport_point_within_vp(&vp, x, y))
|
||||
retval = TITLE_ICON;
|
||||
}
|
||||
/* check scrollbar. assume it's shown, if it isn't it will be handled
|
||||
* later */
|
||||
if (retval == OUTSIDE)
|
||||
{
|
||||
bool on_scrollbar_clicked;
|
||||
int adj_x = x - parent->x;
|
||||
switch (global_settings.scrollbar)
|
||||
{
|
||||
/* Top left corner is GO_TO_ROOT */
|
||||
if (button == BUTTON_REL)
|
||||
return ACTION_STD_MENU;
|
||||
else if (button == (BUTTON_REPEAT|BUTTON_REL))
|
||||
return ACTION_STD_CONTEXT;
|
||||
return ACTION_NONE;
|
||||
case SCROLLBAR_LEFT:
|
||||
on_scrollbar_clicked = adj_x <= SCROLLBAR_WIDTH; break;
|
||||
case SCROLLBAR_RIGHT:
|
||||
on_scrollbar_clicked = adj_x > (title->x + title->width - SCROLLBAR_WIDTH); break;
|
||||
default:
|
||||
on_scrollbar_clicked = false; break;
|
||||
}
|
||||
else /* click on title text is cancel */
|
||||
if (button == BUTTON_REL)
|
||||
return ACTION_STD_CANCEL;
|
||||
if (on_scrollbar_clicked)
|
||||
retval = SCROLLBAR;
|
||||
}
|
||||
/* do this after the above so the scrolling stops without
|
||||
* going back in the list with the same touch */
|
||||
if (scroll_mode == SCROLL_KINETIC)
|
||||
if (retval == OUTSIDE)
|
||||
{
|
||||
kinetic_force_stop();
|
||||
scroll_mode = SCROLL_NONE;
|
||||
text = &list_text[screen];
|
||||
if (viewport_point_within_vp(text, x, y))
|
||||
retval = LIST_TEXT;
|
||||
else /* if all fails, it must be on the list icons */
|
||||
retval = LIST_ICON;
|
||||
}
|
||||
}
|
||||
else /* list area clicked (or not released) */
|
||||
return retval;
|
||||
}
|
||||
|
||||
unsigned gui_synclist_do_touchscreen(struct gui_synclist * list)
|
||||
{
|
||||
enum screen_type screen;
|
||||
struct viewport *parent;
|
||||
short x, y;
|
||||
int action, adj_y, line, line_height, list_start_item;
|
||||
bool recurse;
|
||||
static int last_y;
|
||||
|
||||
screen = SCREEN_MAIN;
|
||||
parent = list->parent[screen];
|
||||
line_height = list->parent[screen]->line_height;
|
||||
list_start_item = list->start_item[screen];
|
||||
/* start with getting the action code and finding the click location */
|
||||
action = action_get_touchscreen_press(&x, &y);
|
||||
adj_y = y - parent->y;
|
||||
|
||||
/* selection needs to be corrected if items are only partially visible */
|
||||
line = (adj_y - y_offset) / line_height;
|
||||
if (list_display_title(list, screen))
|
||||
line -= 1; /* adjust for the list title */
|
||||
|
||||
/* some defaults before running the state machine */
|
||||
recurse = false;
|
||||
hide_selection = true;
|
||||
|
||||
switch (scroll_mode)
|
||||
{
|
||||
const int actual_y = y - (show_title ? line_height : 0);
|
||||
bool on_scrollbar_clicked;
|
||||
switch (global_settings.scrollbar)
|
||||
case SCROLL_NONE:
|
||||
{
|
||||
case SCROLLBAR_LEFT:
|
||||
on_scrollbar_clicked = x <= SCROLLBAR_WIDTH; break;
|
||||
case SCROLLBAR_RIGHT:
|
||||
on_scrollbar_clicked = x > (icon_width + list_width); break;
|
||||
default:
|
||||
on_scrollbar_clicked = false; break;
|
||||
}
|
||||
/* conditions for scrollbar scrolling:
|
||||
* * pen is on the scrollbar
|
||||
* AND scrollbar is on the right (left case is handled above)
|
||||
* OR * pen is in the somewhere else but we did scrollbar scrolling before
|
||||
*
|
||||
* scrollbar scrolling must end if the pen is released
|
||||
* scrollbar scrolling must not happen if we're currently scrolling
|
||||
* via swiping the screen
|
||||
**/
|
||||
|
||||
if (!released && scroll_mode != SCROLL_SWIPE &&
|
||||
(on_scrollbar_clicked || scroll_mode == SCROLL_BAR))
|
||||
{
|
||||
if (scroll_mode == SCROLL_KINETIC)
|
||||
kinetic_force_stop();
|
||||
scroll_mode = SCROLL_BAR;
|
||||
return scrollbar_scroll(gui_list, y);
|
||||
}
|
||||
|
||||
/* |--------------------------------------------------------|
|
||||
* | Description of the touchscreen list interface: |
|
||||
* |--------------------------------------------------------|
|
||||
* | Pressing an item will select it and "enter" it. |
|
||||
* | |
|
||||
* | Pressing and holding your pen down will scroll through |
|
||||
* | the list of items. |
|
||||
* | |
|
||||
* | Pressing and holding your pen down on a single item |
|
||||
* | will bring up the context menu of it. |
|
||||
* |--------------------------------------------------------|
|
||||
*/
|
||||
if (actual_y > 0 || button & BUTTON_REPEAT)
|
||||
{
|
||||
/* selection needs to be corrected if an items are only
|
||||
* partially visible */
|
||||
line = (actual_y - y_offset) / line_height;
|
||||
|
||||
if (cancelled_kinetic)
|
||||
list->selected_item = list_start_item+line;
|
||||
gui_synclist_speak_item(list);
|
||||
if (!last_y)
|
||||
{ /* first run. register adj_y and re-run (will then take the else case) */
|
||||
last_y = adj_y;
|
||||
recurse = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
int click_loc = get_click_location(list, x, y);
|
||||
if (action == BUTTON_TOUCHSCREEN)
|
||||
{
|
||||
/* if not scrolling, the user is trying to select */
|
||||
int diff = adj_y - last_y;
|
||||
if ((click_loc & LIST) && swipe_scroll(list, diff))
|
||||
scroll_mode = SCROLL_SWIPE;
|
||||
else if (click_loc & SCROLLBAR)
|
||||
scroll_mode = SCROLL_BAR;
|
||||
|
||||
hide_selection = click_loc & SCROLLBAR;
|
||||
}
|
||||
else if (action == BUTTON_REPEAT)
|
||||
{
|
||||
if (click_loc & LIST)
|
||||
{
|
||||
/* held a single line for a while, bring up the context menu */
|
||||
gui_synclist_select_item(list, list_start_item + line);
|
||||
/* don't sent context repeatedly */
|
||||
action_wait_for_release();
|
||||
last_y = 0;
|
||||
return ACTION_STD_CONTEXT;
|
||||
}
|
||||
}
|
||||
else if (action & BUTTON_REL)
|
||||
{
|
||||
last_y = 0;
|
||||
if (click_loc & LIST)
|
||||
{ /* release on list item enters it */
|
||||
gui_synclist_select_item(list, list_start_item + line);
|
||||
return ACTION_STD_OK;
|
||||
}
|
||||
else if (click_loc & TITLE_TEXT)
|
||||
{ /* clicking the title goes one level up (cancel) */
|
||||
return ACTION_STD_CANCEL;
|
||||
}
|
||||
else if (click_loc & TITLE_ICON)
|
||||
{ /* clicking the title icon goes back to the root */
|
||||
return ACTION_STD_MENU;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SCROLL_SWIPE:
|
||||
{
|
||||
/* when swipe scrolling, we accept outside presses as well and
|
||||
* grab the entire screen (i.e. click_loc does not matter) */
|
||||
int diff = adj_y - last_y;
|
||||
kinetic_stats_collect(diff);
|
||||
if (swipe_scroll(list, diff))
|
||||
{
|
||||
/* letting the pen go enters kinetic scrolling */
|
||||
if ((action & BUTTON_REL))
|
||||
{
|
||||
if (kinetic_setup_scroll(list))
|
||||
scroll_mode = SCROLL_KINETIC;
|
||||
else
|
||||
scroll_mode = SCROLL_NONE;
|
||||
}
|
||||
}
|
||||
else if (action & BUTTON_REL)
|
||||
{
|
||||
scroll_mode = SCROLL_NONE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SCROLL_KINETIC:
|
||||
{
|
||||
/* during kinetic scrolling we need to handle cancellation.
|
||||
* This state is actually only entered upon end of it as this
|
||||
* function is not called during the animation. */
|
||||
if (!is_kinetic_over())
|
||||
{ /* a) the user touched the screen (manual cancellation) */
|
||||
kinetic_force_stop();
|
||||
scroll_mode = SCROLL_SWIPE;
|
||||
}
|
||||
|
||||
/* Pressed below the list*/
|
||||
if (list_start_item + line >= gui_list->nb_items)
|
||||
{
|
||||
/* don't collect last_position outside of the list area
|
||||
* it'd break selecting after such a situation */
|
||||
last_position = 0;
|
||||
return ACTION_NONE;
|
||||
}
|
||||
|
||||
if (button & BUTTON_REPEAT && scroll_mode == SCROLL_NONE)
|
||||
{
|
||||
/* held a single line for a while, bring up the context menu */
|
||||
gui_synclist_select_item(gui_list, list_start_item + line);
|
||||
/* don't sent context repeatedly */
|
||||
action_wait_for_release();
|
||||
last_position = 0;
|
||||
return ACTION_STD_CONTEXT;
|
||||
}
|
||||
if (released && !cancelled_kinetic)
|
||||
{
|
||||
/* Pen was released anywhere on the screen */
|
||||
last_position = 0;
|
||||
if (scroll_mode == SCROLL_NONE)
|
||||
{
|
||||
/* select current line */
|
||||
gui_synclist_select_item(gui_list, list_start_item + line);
|
||||
return ACTION_STD_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* we were scrolling
|
||||
* -> reset scrolling but do nothing else */
|
||||
if (scroll_mode == SCROLL_SWIPE)
|
||||
{
|
||||
if (kinetic_setup_scroll(gui_list))
|
||||
scroll_mode = SCROLL_KINETIC;
|
||||
}
|
||||
if (scroll_mode != SCROLL_KINETIC)
|
||||
scroll_mode = SCROLL_NONE;
|
||||
return ACTION_NONE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* pen is on the screen */
|
||||
bool redraw = false, result = false;
|
||||
/* beginning of list interaction denoted by release in
|
||||
* the previous call */
|
||||
if (old_released || is_kinetic_over())
|
||||
{
|
||||
scroll_mode = SCROLL_NONE;
|
||||
redraw = true;
|
||||
}
|
||||
|
||||
/* select current item; gui_synclist_select_item()
|
||||
* is not called because it has side effects that
|
||||
* disturb kinetic scrolling */
|
||||
gui_list->selected_item = list_start_item+line;
|
||||
gui_synclist_speak_item(gui_list);
|
||||
if (last_position == 0)
|
||||
{
|
||||
redraw = true;
|
||||
last_position = actual_y;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* record speed data in case we do kinetic scrolling */
|
||||
int diff = actual_y - last_position;
|
||||
kinetic_stats_collect(diff);
|
||||
result = swipe_scroll(gui_list, line_height, diff);
|
||||
}
|
||||
|
||||
/* Start scrolling once the pen is moved without
|
||||
* releasing it inbetween */
|
||||
if (result)
|
||||
{
|
||||
redraw = true;
|
||||
scroll_mode = SCROLL_SWIPE;
|
||||
}
|
||||
last_position = actual_y;
|
||||
|
||||
return redraw ? ACTION_REDRAW:ACTION_NONE;
|
||||
{ /* b) kinetic scrolling stopped on its own */
|
||||
/* need to re-run this with SCROLL_NONE since otherwise
|
||||
* the next touch is not detected correctly */
|
||||
scroll_mode = SCROLL_NONE;
|
||||
recurse = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SCROLL_BAR:
|
||||
{
|
||||
/* similarly to swipe scroll, using the scrollbar grabs
|
||||
* focus so the click location is irrelevant */
|
||||
scrollbar_scroll(list, adj_y);
|
||||
if (action & BUTTON_REL)
|
||||
scroll_mode = SCROLL_NONE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ACTION_REDRAW;
|
||||
|
||||
/* register y position unless forcefully reset to 0 */
|
||||
if (last_y)
|
||||
last_y = adj_y;
|
||||
|
||||
return recurse ? gui_synclist_do_touchscreen(list) : ACTION_REDRAW;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue