static WidgetTriggerActionResult scrollbar_trigger_action ( widget *wid, MouseBindingMouseDefaultAction action, G_GNUC_UNUSED gint x, gint y, G_GNUC_UNUSED void *user_data ) { scrollbar *sb = (scrollbar *) wid; switch ( action ) { case MOUSE_CLICK_DOWN: return WIDGET_TRIGGER_ACTION_RESULT_GRAB_MOTION_BEGIN; case MOUSE_CLICK_UP: scrollbar_scroll ( sb, y ); return WIDGET_TRIGGER_ACTION_RESULT_GRAB_MOTION_END; case MOUSE_DCLICK_DOWN: case MOUSE_DCLICK_UP: break; } return FALSE; }
unsigned gui_synclist_do_touchscreen(struct gui_synclist * gui_list) { short x, y; const enum screen_type screen = SCREEN_MAIN; struct viewport *info_vp = sb_skin_get_info_vp(screen); const int button = action_get_touchscreen_press_in_vp(&x, &y, info_vp); const int list_start_item = gui_list->start_item[screen]; const int line_height = font_get(gui_list->parent[screen]->font)->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; released = (button&BUTTON_REL) != 0; if (button == ACTION_NONE || button == ACTION_UNKNOWN) { /* 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 info_vp */ 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()) { if (x < icon_width) { /* 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; } else /* click on title text is cancel */ if (button == BUTTON_REL) return ACTION_STD_CANCEL; } /* do this after the above so the scrolling stops without * going back in the list with the same touch */ if (scroll_mode == SCROLL_KINETIC) { kinetic_force_stop(); scroll_mode = SCROLL_NONE; } } else /* list area clicked (or not released) */ { const int actual_y = y - (show_title ? line_height : 0); bool on_scrollbar_clicked; switch (global_settings.scrollbar) { 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) { 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; } } } return ACTION_REDRAW; }
static gboolean scrollbar_motion_notify ( widget *wid, G_GNUC_UNUSED gint x, gint y ) { scrollbar *sb = (scrollbar *) wid; scrollbar_scroll ( sb, y ); return TRUE; }