diff options
-rw-r--r-- | apps/gui/bitmap/list.c | 57 | ||||
-rw-r--r-- | apps/gui/list.c | 12 | ||||
-rw-r--r-- | apps/gui/list.h | 6 |
3 files changed, 47 insertions, 28 deletions
diff --git a/apps/gui/bitmap/list.c b/apps/gui/bitmap/list.c index db8e0504d7..ff0f5a29c1 100644 --- a/apps/gui/bitmap/list.c +++ b/apps/gui/bitmap/list.c | |||
@@ -50,7 +50,6 @@ | |||
50 | static struct viewport list_text[NB_SCREENS], title_text[NB_SCREENS]; | 50 | static struct viewport list_text[NB_SCREENS], title_text[NB_SCREENS]; |
51 | 51 | ||
52 | #ifdef HAVE_TOUCHSCREEN | 52 | #ifdef HAVE_TOUCHSCREEN |
53 | static int y_offset; | ||
54 | static bool hide_selection; | 53 | static bool hide_selection; |
55 | #endif | 54 | #endif |
56 | 55 | ||
@@ -170,12 +169,9 @@ void list_draw(struct screen *display, struct gui_synclist *list) | |||
170 | end = start + nb_lines; | 169 | end = start + nb_lines; |
171 | 170 | ||
172 | #ifdef HAVE_TOUCHSCREEN | 171 | #ifdef HAVE_TOUCHSCREEN |
173 | if (list->selected_item == 0 || (list->nb_items < nb_lines)) | 172 | int draw_offset = list_start_item * linedes.height - list->y_pos; |
174 | y_offset = 0; /* reset in case it's a new list */ | ||
175 | |||
176 | int draw_offset = y_offset; | ||
177 | /* draw some extra items to not have empty lines at the top and bottom */ | 173 | /* draw some extra items to not have empty lines at the top and bottom */ |
178 | if (y_offset > 0) | 174 | if (draw_offset > 0) |
179 | { | 175 | { |
180 | /* make it negative for more consistent apparence when switching | 176 | /* make it negative for more consistent apparence when switching |
181 | * directions */ | 177 | * directions */ |
@@ -183,7 +179,7 @@ void list_draw(struct screen *display, struct gui_synclist *list) | |||
183 | if (start > 0) | 179 | if (start > 0) |
184 | start--; | 180 | start--; |
185 | } | 181 | } |
186 | else if (y_offset < 0) | 182 | else if (draw_offset < 0) |
187 | end++; | 183 | end++; |
188 | #else | 184 | #else |
189 | #define draw_offset 0 | 185 | #define draw_offset 0 |
@@ -367,7 +363,6 @@ static int scrollbar_scroll(struct gui_synclist * gui_list, int y) | |||
367 | if (nb_lines < gui_list->nb_items) | 363 | if (nb_lines < gui_list->nb_items) |
368 | { | 364 | { |
369 | /* scrollbar scrolling is still line based */ | 365 | /* scrollbar scrolling is still line based */ |
370 | y_offset = 0; | ||
371 | int scrollbar_size = nb_lines * gui_list->line_height[screen]; | 366 | int scrollbar_size = nb_lines * gui_list->line_height[screen]; |
372 | int actual_y = y - list_text[screen].y; | 367 | int actual_y = y - list_text[screen].y; |
373 | int new_selection = (actual_y * gui_list->nb_items) / scrollbar_size; | 368 | int new_selection = (actual_y * gui_list->nb_items) / scrollbar_size; |
@@ -379,6 +374,7 @@ static int scrollbar_scroll(struct gui_synclist * gui_list, int y) | |||
379 | start_item = gui_list->nb_items - nb_lines; | 374 | start_item = gui_list->nb_items - nb_lines; |
380 | 375 | ||
381 | gui_list->start_item[screen] = start_item; | 376 | gui_list->start_item[screen] = start_item; |
377 | gui_list->y_pos = start_item * gui_list->line_height[screen]; | ||
382 | 378 | ||
383 | return ACTION_REDRAW; | 379 | return ACTION_REDRAW; |
384 | } | 380 | } |
@@ -468,9 +464,11 @@ static void kinetic_force_stop(void) | |||
468 | 464 | ||
469 | /* helper for gui/list.c to cancel scrolling if a normal button event comes | 465 | /* helper for gui/list.c to cancel scrolling if a normal button event comes |
470 | * through dpad or keyboard or whatever */ | 466 | * through dpad or keyboard or whatever */ |
471 | void _gui_synclist_stop_kinetic_scrolling(void) | 467 | void _gui_synclist_stop_kinetic_scrolling(struct gui_synclist * gui_list) |
472 | { | 468 | { |
473 | y_offset = 0; | 469 | const enum screen_type screen = screens[SCREEN_MAIN].screen_type; |
470 | gui_list->y_pos = gui_list->start_item[screen] * gui_list->line_height[screen]; | ||
471 | |||
474 | if (scroll_mode == SCROLL_KINETIC) | 472 | if (scroll_mode == SCROLL_KINETIC) |
475 | kinetic_force_stop(); | 473 | kinetic_force_stop(); |
476 | scroll_mode = SCROLL_NONE; | 474 | scroll_mode = SCROLL_NONE; |
@@ -512,22 +510,25 @@ static bool swipe_scroll(struct gui_synclist * gui_list, int difference) | |||
512 | int new_start_item = -1; | 510 | int new_start_item = -1; |
513 | int line_diff = 0; | 511 | int line_diff = 0; |
514 | 512 | ||
515 | /* don't scroll at the edges of the list */ | 513 | /* Track whether we hit the end of the list for sake of kinetic scroll */ |
516 | if ((old_start == 0 && difference > 0) | 514 | bool hit_end = true; |
517 | || (old_start == (gui_list->nb_items - nb_lines) && difference < 0)) | ||
518 | { | ||
519 | y_offset = 0; | ||
520 | gui_list->start_item[screen] = old_start; | ||
521 | return scroll_mode != SCROLL_KINETIC; /* stop kinetic at the edges */ | ||
522 | } | ||
523 | 515 | ||
524 | /* add up y_offset over time and translate to lines | 516 | /* Move the y position and clamp it (funny things happen otherwise...) */ |
525 | * if scrolled enough */ | 517 | gui_list->y_pos -= difference; |
526 | y_offset += difference; | 518 | if(gui_list->y_pos < 0) |
527 | if (abs(y_offset) > line_height) | 519 | gui_list->y_pos = 0; |
520 | else if(gui_list->y_pos > (gui_list->nb_items - nb_lines) * line_height) | ||
521 | gui_list->y_pos = (gui_list->nb_items - nb_lines) * line_height; | ||
522 | else | ||
523 | hit_end = false; | ||
524 | |||
525 | /* Get the list y position. When pos_y differs by a line height or more, | ||
526 | * we need to scroll the list by adjusting the start item accordingly */ | ||
527 | int cur_y = gui_list->start_item[screen] * line_height; | ||
528 | int diff_y = cur_y - gui_list->y_pos; | ||
529 | if (abs(diff_y) >= line_height) | ||
528 | { | 530 | { |
529 | line_diff = y_offset/line_height; | 531 | line_diff = diff_y/line_height; |
530 | y_offset -= line_diff * line_height; | ||
531 | } | 532 | } |
532 | 533 | ||
533 | if(line_diff != 0) | 534 | if(line_diff != 0) |
@@ -548,7 +549,10 @@ static bool swipe_scroll(struct gui_synclist * gui_list, int difference) | |||
548 | gui_list->selected_item -= (gui_list->selected_item % gui_list->selected_size); | 549 | gui_list->selected_item -= (gui_list->selected_item % gui_list->selected_size); |
549 | } | 550 | } |
550 | 551 | ||
551 | return true; | 552 | if(hit_end) |
553 | return scroll_mode != SCROLL_KINETIC; | ||
554 | else | ||
555 | return true; | ||
552 | } | 556 | } |
553 | 557 | ||
554 | static int kinetic_callback(struct timeout *tmo) | 558 | static int kinetic_callback(struct timeout *tmo) |
@@ -729,7 +733,8 @@ unsigned gui_synclist_do_touchscreen(struct gui_synclist * list) | |||
729 | if(!skinlist_get_item(&screens[screen], list, adj_x, adj_y, &line)) | 733 | if(!skinlist_get_item(&screens[screen], list, adj_x, adj_y, &line)) |
730 | { | 734 | { |
731 | /* selection needs to be corrected if items are only partially visible */ | 735 | /* selection needs to be corrected if items are only partially visible */ |
732 | line = (adj_y - y_offset) / line_height; | 736 | int cur_y = list->start_item[screen] * line_height; |
737 | line = (adj_y - (cur_y - list->y_pos)) / line_height; | ||
733 | if (list_display_title(list, screen)) | 738 | if (list_display_title(list, screen)) |
734 | line -= 1; /* adjust for the list title */ | 739 | line -= 1; /* adjust for the list title */ |
735 | } | 740 | } |
diff --git a/apps/gui/list.c b/apps/gui/list.c index 139dbaac18..13a850bd7b 100644 --- a/apps/gui/list.c +++ b/apps/gui/list.c | |||
@@ -152,6 +152,9 @@ void gui_synclist_init(struct gui_synclist * gui_list, | |||
152 | gui_list->callback_speak_item = NULL; | 152 | gui_list->callback_speak_item = NULL; |
153 | gui_list->nb_items = 0; | 153 | gui_list->nb_items = 0; |
154 | gui_list->selected_item = 0; | 154 | gui_list->selected_item = 0; |
155 | #ifdef HAVE_TOUCHSCREEN | ||
156 | gui_list->y_pos = 0; | ||
157 | #endif | ||
155 | FOR_NB_SCREENS(i) | 158 | FOR_NB_SCREENS(i) |
156 | { | 159 | { |
157 | gui_list->start_item[i] = 0; | 160 | gui_list->start_item[i] = 0; |
@@ -282,6 +285,9 @@ static void gui_list_put_selection_on_screen(struct gui_synclist * gui_list, | |||
282 | gui_list->start_item[screen] = bottom; | 285 | gui_list->start_item[screen] = bottom; |
283 | else | 286 | else |
284 | gui_list->start_item[screen] = new_start_item; | 287 | gui_list->start_item[screen] = new_start_item; |
288 | #ifdef HAVE_TOUCHSCREEN | ||
289 | gui_list->y_pos = gui_list->start_item[SCREEN_MAIN] * gui_list->line_height[SCREEN_MAIN]; | ||
290 | #endif | ||
285 | } | 291 | } |
286 | 292 | ||
287 | static void edge_beep(struct gui_synclist * gui_list, bool wrap) | 293 | static void edge_beep(struct gui_synclist * gui_list, bool wrap) |
@@ -417,6 +423,10 @@ static void gui_list_select_at_offset(struct gui_synclist * gui_list, | |||
417 | gui_list->selected_size); | 423 | gui_list->selected_size); |
418 | gui_list->selected_item = gui_list->start_item[i] + nb_lines; | 424 | gui_list->selected_item = gui_list->start_item[i] + nb_lines; |
419 | } | 425 | } |
426 | |||
427 | #ifdef HAVE_TOUCHSCREEN | ||
428 | gui_list->y_pos = gui_list->start_item[SCREEN_MAIN] * gui_list->line_height[SCREEN_MAIN]; | ||
429 | #endif | ||
420 | } | 430 | } |
421 | return; | 431 | return; |
422 | } | 432 | } |
@@ -667,7 +677,7 @@ bool gui_synclist_do_button(struct gui_synclist * lists, | |||
667 | action = *actionptr = gui_synclist_do_touchscreen(lists); | 677 | action = *actionptr = gui_synclist_do_touchscreen(lists); |
668 | else if (action > ACTION_TOUCHSCREEN_MODE) | 678 | else if (action > ACTION_TOUCHSCREEN_MODE) |
669 | /* cancel kinetic if we got a normal button event */ | 679 | /* cancel kinetic if we got a normal button event */ |
670 | _gui_synclist_stop_kinetic_scrolling(); | 680 | _gui_synclist_stop_kinetic_scrolling(lists); |
671 | #endif | 681 | #endif |
672 | 682 | ||
673 | /* Disable the skin redraw callback */ | 683 | /* Disable the skin redraw callback */ |
diff --git a/apps/gui/list.h b/apps/gui/list.h index 3a613d0a67..64ff3e3fdd 100644 --- a/apps/gui/list.h +++ b/apps/gui/list.h | |||
@@ -118,6 +118,10 @@ struct gui_synclist | |||
118 | bool scroll_all; | 118 | bool scroll_all; |
119 | int nb_items; | 119 | int nb_items; |
120 | int selected_item; | 120 | int selected_item; |
121 | #ifdef HAVE_TOUCHSCREEN | ||
122 | /* absolute Y coordinate, used for smooth scrolling */ | ||
123 | int y_pos; | ||
124 | #endif | ||
121 | int start_item[NB_SCREENS]; /* the item that is displayed at the top of the screen */ | 125 | int start_item[NB_SCREENS]; /* the item that is displayed at the top of the screen */ |
122 | /* the number of lines that are selected at the same time */ | 126 | /* the number of lines that are selected at the same time */ |
123 | int selected_size; | 127 | int selected_size; |
@@ -229,7 +233,7 @@ int skinlist_get_line_count(enum screen_type screen, struct gui_synclist *list); | |||
229 | /* this needs to be fixed if we ever get more than 1 touchscreen on a target */ | 233 | /* this needs to be fixed if we ever get more than 1 touchscreen on a target */ |
230 | extern unsigned gui_synclist_do_touchscreen(struct gui_synclist * gui_list); | 234 | extern unsigned gui_synclist_do_touchscreen(struct gui_synclist * gui_list); |
231 | /* only for private use in gui/list.c */ | 235 | /* only for private use in gui/list.c */ |
232 | extern void _gui_synclist_stop_kinetic_scrolling(void); | 236 | extern void _gui_synclist_stop_kinetic_scrolling(struct gui_synclist * gui_list); |
233 | #endif | 237 | #endif |
234 | 238 | ||
235 | /* If the list has a pending postponed scheduled announcement, that | 239 | /* If the list has a pending postponed scheduled announcement, that |