Merge pull request #10139 from jdgleaver/ozone-pointer

(Ozone) Add rudimentary pointer support
This commit is contained in:
Twinaphex 2020-02-21 19:46:30 +01:00 committed by GitHub
commit cee58b354d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 644 additions and 70 deletions

View File

@ -264,6 +264,11 @@ static void *ozone_init(void **userdata, bool video_is_threaded)
ozone->animations.scroll_y = 0.0f;
ozone->animations.scroll_y_sidebar = 0.0f;
ozone->first_onscreen_entry = 0;
ozone->last_onscreen_entry = 0;
ozone->first_onscreen_category = 0;
ozone->last_onscreen_category = 0;
/* Assets path */
fill_pathname_join(
ozone->assets_path,
@ -517,6 +522,11 @@ static void ozone_set_layout(ozone_handle_t *ozone, bool is_threaded)
ozone->dimensions.spacer_3px = (unsigned)((scale_factor * 3.0f) + 0.5f);
ozone->dimensions.spacer_5px = (unsigned)((scale_factor * 5.0f) + 0.5f);
/* Determine movement delta size for activating
* pointer input (note: not a dimension as such,
* so not included in the 'dimensions' struct) */
ozone->pointer_active_delta = CURSOR_ACTIVE_DELTA * scale_factor;
/* Initialise fonts */
/* > Free existing */
@ -1089,13 +1099,17 @@ static void ozone_list_free(file_list_t *list, size_t a, size_t b)
ozone_list_clear(list);
}
/* Forward declaration */
static void ozone_set_thumbnail_content(void *data, const char *s);
static void ozone_render(void *data,
unsigned width, unsigned height,
bool is_idle)
{
size_t i;
float scale_factor;
unsigned end = (unsigned)menu_entries_get_size();
unsigned entries_end = (unsigned)menu_entries_get_size();
bool pointer_enabled = false;
ozone_handle_t *ozone = (ozone_handle_t*)data;
if (!ozone)
return;
@ -1126,11 +1140,323 @@ static void ozone_render(void *data,
ozone->selection = menu_navigation_get_selection();
/* TODO: Handle pointer & mouse */
/* Need to update this each frame, otherwise touchscreen
* input breaks when changing orientation */
gfx_display_set_width(width);
gfx_display_set_height(height);
/* Read pointer state */
menu_input_get_pointer_state(&ozone->pointer);
/* Check whether pointer is enabled */
if (ozone->pointer.type != MENU_POINTER_DISABLED)
{
/* When using a mouse, entry under pointer is
* automatically selected
* > Must therefore filter out small movements,
* otherwise scrolling with the mouse wheel
* becomes impossible... */
if (ozone->pointer.type == MENU_POINTER_MOUSE)
{
int16_t cursor_x_delta = ozone->pointer.x - ozone->cursor_x_old;
int16_t cursor_y_delta = ozone->pointer.y - ozone->cursor_y_old;
if ((cursor_x_delta > ozone->pointer_active_delta) ||
(cursor_x_delta < -ozone->pointer_active_delta) ||
(cursor_y_delta > ozone->pointer_active_delta) ||
(cursor_y_delta < -ozone->pointer_active_delta))
ozone->cursor_mode = true;
}
/* On touchscreens, just check for any movement */
else
{
if ((ozone->pointer.x != ozone->cursor_x_old) ||
(ozone->pointer.y != ozone->cursor_y_old))
ozone->cursor_mode = true;
}
}
ozone->cursor_x_old = ozone->pointer.x;
ozone->cursor_y_old = ozone->pointer.y;
pointer_enabled = ozone->cursor_mode && !ozone->show_fullscreen_thumbnails;
/* Process pointer input, if required */
if (pointer_enabled)
{
file_list_t *selection_buf = menu_entries_get_selection_buf_ptr(0);
gfx_animation_ctx_tag animation_tag = (uintptr_t)selection_buf;
int entry_padding = (ozone->depth == 1) ?
ozone->dimensions.entry_padding_horizontal_half :
ozone->dimensions.entry_padding_horizontal_full;
float entry_x = ozone->dimensions.sidebar_width +
ozone->sidebar_offset + entry_padding;
float entry_width = width - ozone->dimensions.sidebar_width -
ozone->sidebar_offset - entry_padding * 2 -
ozone->animations.thumbnail_bar_position;
bool first_entry_found = false;
bool last_entry_found = false;
unsigned horizontal_list_size = ozone->horizontal_list ?
(unsigned)ozone->horizontal_list->size : 0;
float category_height = ozone->dimensions.sidebar_entry_height +
ozone->dimensions.sidebar_entry_padding_vertical;
bool first_category_found = false;
bool last_category_found = false;
/* Check whether pointer is operating on entries
* or sidebar
* > Note: Since touchscreens effectively 'lose their
* place' when a touch is released, we can only perform
* this this check if the pointer is currently
* pressed - i.e. we must preserve the values set the
* last time the screen was touched.
* With mouse input we have a permanent cursor, so this
* is not an issue */
ozone->last_pointer_in_sidebar = ozone->pointer_in_sidebar;
if ((ozone->pointer.type == MENU_POINTER_MOUSE) ||
ozone->pointer.pressed)
ozone->pointer_in_sidebar = ozone->pointer.x <
ozone->dimensions.sidebar_width + ozone->sidebar_offset;
/* If pointer has switched from entries to sidebar
* or vice versa, must reset pointer acceleration */
if (ozone->pointer_in_sidebar != ozone->last_pointer_in_sidebar)
{
menu_input_set_pointer_y_accel(0.0f);
ozone->pointer.y_accel = 0.0f;
}
/* If pointer is a mouse, then automatically follow
* mouse focus from entries to sidebar (and vice versa) */
if (ozone->pointer.type == MENU_POINTER_MOUSE)
{
if (ozone->pointer_in_sidebar &&
!ozone->last_pointer_in_sidebar &&
!ozone->cursor_in_sidebar)
ozone_go_to_sidebar(ozone, animation_tag);
else if (!ozone->pointer_in_sidebar &&
ozone->last_pointer_in_sidebar &&
ozone->cursor_in_sidebar)
ozone_leave_sidebar(ozone, animation_tag);
}
/* Update scrolling - must be done first, otherwise
* cannot determine entry/category positions
* > Entries */
if (!ozone->pointer_in_sidebar)
{
float entry_bottom_boundary = height - ozone->dimensions.header_height -
ozone->dimensions.spacer_1px - ozone->dimensions.footer_height -
ozone->dimensions.entry_padding_vertical * 2;
ozone->animations.scroll_y += ozone->pointer.y_accel;
if (ozone->animations.scroll_y + ozone->entries_height < entry_bottom_boundary)
ozone->animations.scroll_y = entry_bottom_boundary - ozone->entries_height;
if (ozone->animations.scroll_y > 0.0f)
ozone->animations.scroll_y = 0.0f;
}
/* > Sidebar
* Only process sidebar input here if the
* cursor is currently *in* the sidebar */
else if (ozone->cursor_in_sidebar)
{
float sidebar_bottom_boundary = height -
(ozone->dimensions.header_height + ozone->dimensions.spacer_1px) -
ozone->dimensions.footer_height -
ozone->dimensions.sidebar_padding_vertical;
float sidebar_height = ozone_get_sidebar_height(ozone);
ozone->animations.scroll_y_sidebar += ozone->pointer.y_accel;
if (ozone->animations.scroll_y_sidebar + sidebar_height < sidebar_bottom_boundary)
ozone->animations.scroll_y_sidebar = sidebar_bottom_boundary - sidebar_height;
if (ozone->animations.scroll_y_sidebar > 0.0f)
ozone->animations.scroll_y_sidebar = 0.0f;
}
/* Regardless of pointer location, have to process
* all entries/categories in order to determine
* the indices of the first and last entries/categories
* displayed on screen
* > Needed so we can determine proper cursor positions
* when mixing pointer + gamepad/keyboard input */
/* >> Loop over all entries */
ozone->first_onscreen_entry = 0;
ozone->last_onscreen_entry = (entries_end > 0) ? entries_end - 1 : 0;
for (i = 0; i < entries_end; i++)
{
ozone_node_t *node = (ozone_node_t*)
file_list_get_userdata_at_offset(selection_buf, i);
float entry_y;
/* Sanity check */
if (!node)
break;
/* Get current entry y position */
entry_y = ozone->dimensions.header_height + ozone->dimensions.spacer_1px +
ozone->dimensions.entry_padding_vertical + ozone->animations.scroll_y +
node->position_y;
/* Check whether this is the first on screen entry */
if (!first_entry_found)
{
if ((entry_y + node->height) > ozone->dimensions.header_height)
{
ozone->first_onscreen_entry = i;
first_entry_found = true;
}
}
/* Check whether this is the last on screen entry */
else if (!last_entry_found)
{
if (entry_y > (height - ozone->dimensions.footer_height))
{
/* Current entry is off screen - get index
* of previous entry */
if (i > 0)
{
ozone->last_onscreen_entry = i - 1;
last_entry_found = true;
}
}
}
/* Track pointer input, if required */
if (!ozone->pointer_in_sidebar &&
first_entry_found &&
!last_entry_found)
{
/* Check whether pointer is within the bounds
* of the current entry */
if ((ozone->pointer.x > entry_x) &&
(ozone->pointer.x < entry_x + entry_width) &&
(ozone->pointer.y > entry_y) &&
(ozone->pointer.y < entry_y + node->height))
{
/* Pointer selection is always updated */
menu_input_set_pointer_selection(i);
/* If pointer is a mouse, then automatically
* select entry under cursor */
if (ozone->pointer.type == MENU_POINTER_MOUSE)
{
/* Note the fudge factor - cannot auto select
* items while drag-scrolling the entry list,
* so have to wait until pointer acceleration
* drops below a 'sensible' level... */
if (!ozone->cursor_in_sidebar &&
(i != ozone->selection) &&
(ozone->pointer.y_accel < ozone->last_scale_factor) &&
(ozone->pointer.y_accel > -ozone->last_scale_factor))
{
menu_navigation_set_selection(i);
/* If this is a playlist, must update thumbnails */
if (ozone->is_playlist && (ozone->depth == 1))
{
ozone_set_thumbnail_content(ozone, "");
ozone_update_thumbnail_image(ozone);
}
}
}
/* If pointer is pressed and stationary, and
* if pointer has been held for at least
* MENU_INPUT_PRESS_TIME_SHORT ms, automatically
* select current entry */
if (ozone->pointer.pressed &&
!ozone->pointer.dragged &&
(ozone->pointer.press_duration >= MENU_INPUT_PRESS_TIME_SHORT) &&
(i != ozone->selection))
{
menu_navigation_set_selection(i);
/* If we are currently in the sidebar, leave it */
if (ozone->cursor_in_sidebar)
{
ozone_leave_sidebar(ozone, animation_tag);
}
/* If this is a playlist, must update thumbnails */
else if (ozone->is_playlist && (ozone->depth == 1))
{
ozone_set_thumbnail_content(ozone, "");
ozone_update_thumbnail_image(ozone);
}
}
}
}
if (last_entry_found)
break;
}
/* >> Loop over all categories */
ozone->first_onscreen_category = 0;
ozone->last_onscreen_category = ozone->system_tab_end + horizontal_list_size;
for (i = 0; i < ozone->system_tab_end + horizontal_list_size + 1; i++)
{
/* Get current category y position */
float category_y = ozone->dimensions.header_height + ozone->dimensions.spacer_1px +
ozone->dimensions.sidebar_padding_vertical + (category_height * i) +
((i > ozone->system_tab_end) ?
(ozone->dimensions.sidebar_entry_padding_vertical + ozone->dimensions.spacer_1px) : 0) +
ozone->animations.scroll_y_sidebar;
/* Check whether this is the first on screen category */
if (!first_category_found)
{
if ((category_y + category_height) > ozone->dimensions.header_height)
{
ozone->first_onscreen_category = i;
first_category_found = true;
}
}
/* Check whether this is the last on screen category */
else if (!last_category_found)
{
if (category_y > (height - ozone->dimensions.footer_height))
{
/* Current category is off screen - get index
* of previous category */
if (i > 0)
{
ozone->last_onscreen_category = i - 1;
last_category_found = true;
}
}
}
/* Track pointer input, if required */
if (ozone->pointer_in_sidebar &&
ozone->cursor_in_sidebar &&
first_category_found &&
!last_category_found)
{
/* If pointer is within the bounds of the
* current category, cache category index
* (for use in next 'pointer up' event) */
if ((ozone->pointer.y > category_y) &&
(ozone->pointer.y < category_y + category_height))
ozone->pointer_categories_selection = i;
}
if (last_category_found)
break;
}
}
menu_entries_ctl(MENU_ENTRIES_CTL_START_GET, &i);
if (i >= end)
if (i >= entries_end)
{
i = 0;
menu_entries_ctl(MENU_ENTRIES_CTL_SET_START, &i);
@ -1687,11 +2013,10 @@ static void ozone_frame(void *data, video_frame_info_t *video_info)
if (ozone->first_frame)
{
menu_input_pointer_t pointer;
menu_input_get_pointer_state(&pointer);
menu_input_get_pointer_state(&ozone->pointer);
ozone->cursor_x_old = pointer.x;
ozone->cursor_y_old = pointer.y;
ozone->cursor_x_old = ozone->pointer.x;
ozone->cursor_y_old = ozone->pointer.y;
ozone->first_frame = false;
}
@ -1874,19 +2199,16 @@ static void ozone_frame(void *data, video_frame_info_t *video_info)
font_driver_flush(video_info->width, video_info->height, ozone->fonts.entries_label, video_info);
/* Cursor */
if (ozone->show_cursor)
if (ozone->show_cursor && (ozone->pointer.type != MENU_POINTER_DISABLED))
{
menu_input_pointer_t pointer;
menu_input_get_pointer_state(&pointer);
gfx_display_set_alpha(ozone_pure_white, 1.0f);
gfx_display_draw_cursor(
video_info,
ozone_pure_white,
ozone->dimensions.cursor_size,
ozone->icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_POINTER],
pointer.x,
pointer.y,
ozone->pointer.x,
ozone->pointer.y,
video_info->width,
video_info->height
);
@ -1991,6 +2313,9 @@ static void ozone_populate_entries(void *data, const char *path, const char *lab
ozone->need_compute = true;
ozone->first_onscreen_entry = 0;
ozone->last_onscreen_entry = 0;
new_depth = (int)ozone_list_get_size(ozone, MENU_LIST_PLAIN);
animate = new_depth != ozone->depth;
@ -2396,7 +2721,9 @@ void ozone_show_fullscreen_thumbnails(ozone_handle_t *ozone)
menu_entry_t selected_entry;
gfx_animation_ctx_entry_t animation_entry;
const char *thumbnail_label = NULL;
file_list_t *selection_buf = menu_entries_get_selection_buf_ptr(0);
gfx_animation_ctx_tag alpha_tag = (uintptr_t)&ozone->animations.fullscreen_thumbnail_alpha;
gfx_animation_ctx_tag scroll_tag = (uintptr_t)selection_buf;
/* Before showing fullscreen thumbnails, must
* ensure that any existing fullscreen thumbnail
@ -2441,6 +2768,13 @@ void ozone_show_fullscreen_thumbnails(ozone_handle_t *ozone)
return;
}
/* Menu list must be stationary while fullscreen
* thumbnails are shown
* > Kill any existing scroll animations and
* reset scroll acceleration */
gfx_animation_kill_by_tag(&scroll_tag);
menu_input_set_pointer_y_accel(0.0f);
/* Cache selected entry label
* (used as title when fullscreen thumbnails
* are shown) */
@ -2480,14 +2814,24 @@ void ozone_show_fullscreen_thumbnails(ozone_handle_t *ozone)
ozone->show_fullscreen_thumbnails = true;
}
/* Forward declaration */
static int ozone_menu_entry_action(
void *userdata, menu_entry_t *entry,
size_t i, enum menu_action action);
static int ozone_pointer_up(void *userdata,
unsigned x, unsigned y, unsigned ptr,
enum menu_input_pointer_gesture gesture,
menu_file_list_cbs_t *cbs,
menu_entry_t *entry, unsigned action)
{
ozone_handle_t *ozone = (ozone_handle_t*)userdata;
size_t selection = menu_navigation_get_selection();
ozone_handle_t *ozone = (ozone_handle_t*)userdata;
file_list_t *selection_buf = menu_entries_get_selection_buf_ptr(0);
gfx_animation_ctx_tag sidebar_tag = (uintptr_t)selection_buf;
size_t selection = menu_navigation_get_selection();
size_t entries_end = menu_entries_get_size();
unsigned width;
unsigned height;
if (!ozone)
return -1;
@ -2497,27 +2841,123 @@ static int ozone_pointer_up(void *userdata,
* be ignored */
if (ozone->show_fullscreen_thumbnails)
{
/* Must reset scroll acceleration, in case
* user performed a swipe (don't want menu
* list to 'drift' after hiding fullscreen
* thumbnails...) */
menu_input_set_pointer_y_accel(0.0f);
ozone_hide_fullscreen_thumbnails(ozone, true);
return 0;
}
video_driver_get_size(&width, &height);
switch (gesture)
{
case MENU_INPUT_GESTURE_TAP:
case MENU_INPUT_GESTURE_SHORT_PRESS:
/* Normal pointer input */
if (ptr == selection)
return menu_entry_action(entry, selection, MENU_ACTION_SELECT);
/* Tap/press header or footer: Menu back/cancel */
if ((y < ozone->dimensions.header_height) ||
(y > height - ozone->dimensions.footer_height))
return ozone_menu_entry_action(ozone, entry, selection, MENU_ACTION_CANCEL);
/* Tap/press entries: Activate and/or select item */
else if ((ptr < entries_end) &&
(x > ozone->dimensions.sidebar_width + ozone->sidebar_offset) &&
(x < width - ozone->animations.thumbnail_bar_position))
{
if (gesture == MENU_INPUT_GESTURE_TAP)
{
/* A 'tap' always produces a menu action */
menu_navigation_set_selection(ptr);
menu_driver_navigation_set(false);
/* If current 'pointer' item is not active,
* activate it immediately */
if (ptr != selection)
menu_navigation_set_selection(ptr);
/* If we are currently in the sidebar, leave it */
if (ozone->cursor_in_sidebar)
ozone_leave_sidebar(ozone, sidebar_tag);
/* Otherwise perform a MENU_ACTION_SELECT on currently
* active item
* NOTE: Cannot perform a 'leave sidebar' operation
* and a MENU_ACTION_SELECT at the same time... */
else
return ozone_menu_entry_action(ozone, entry, (size_t)ptr, MENU_ACTION_SELECT);
}
else
{
/* A 'short' press is used only to activate (highlight)
* an item - it does not invoke a MENU_ACTION_SELECT
* action */
menu_input_set_pointer_y_accel(0.0f);
if (ptr != selection)
menu_navigation_set_selection(ptr);
/* If we are currently in the sidebar, leave it */
if (ozone->cursor_in_sidebar)
ozone_leave_sidebar(ozone, sidebar_tag);
/* If this is a playlist and the selection
* has changed, must update thumbnails */
else if (ozone->is_playlist &&
(ozone->depth == 1) &&
(ptr != selection))
{
ozone_set_thumbnail_content(ozone, "");
ozone_update_thumbnail_image(ozone);
}
}
}
/* Tap/press sidebar: return to sidebar or select
* category */
else if (ozone->pointer_in_sidebar)
{
/* If cursor is not in sidebar, return to sidebar */
if (!ozone->cursor_in_sidebar)
ozone_go_to_sidebar(ozone, sidebar_tag);
/* Otherwise, select current category */
else if (ozone->pointer_categories_selection != ozone->categories_selection_ptr)
{
unsigned horizontal_list_size = (ozone->horizontal_list) ?
(unsigned)ozone->horizontal_list->size : 0;
/* Ensure that current category is valid */
if (ozone->pointer_categories_selection <= ozone->system_tab_end + horizontal_list_size)
ozone_sidebar_goto(ozone, ozone->pointer_categories_selection);
}
}
break;
case MENU_INPUT_GESTURE_LONG_PRESS:
/* 'Reset to default' action */
if ((ptr <= (menu_entries_get_size() - 1)) &&
(ptr == selection))
if ((y > ozone->dimensions.header_height) &&
(y < height - ozone->dimensions.footer_height) &&
(ptr < entries_end) &&
(ptr == selection) &&
(x > ozone->dimensions.sidebar_width + ozone->sidebar_offset) &&
(x < width - ozone->animations.thumbnail_bar_position))
return menu_entry_action(entry, selection, MENU_ACTION_START);
break;
case MENU_INPUT_GESTURE_SWIPE_LEFT:
/* If this is a playlist, descend alphabet
* > Note: Can only do this if we are not using
* a mouse, since it conflicts with auto selection
* of entry under cursor */
if ((ozone->pointer.type != MENU_POINTER_MOUSE) &&
ozone->is_playlist &&
(ozone->depth == 1))
return ozone_menu_entry_action(ozone, entry, (size_t)ptr, MENU_ACTION_SCROLL_UP);
break;
case MENU_INPUT_GESTURE_SWIPE_RIGHT:
/* If this is a playlist, ascend alphabet
* > Note: Can only do this if we are not using
* a mouse, since it conflicts with auto selection
* of entry under cursor */
if ((ozone->pointer.type != MENU_POINTER_MOUSE) &&
ozone->is_playlist &&
(ozone->depth == 1))
return ozone_menu_entry_action(ozone, entry, (size_t)ptr, MENU_ACTION_SCROLL_DOWN);
break;
default:
/* Ignore input */
break;
@ -2526,6 +2966,73 @@ static int ozone_pointer_up(void *userdata,
return 0;
}
/* Returns true if specified entry is currently
* displayed on screen */
static bool INLINE ozone_entry_onscreen(
ozone_handle_t *ozone, size_t idx)
{
return (idx >= ozone->first_onscreen_entry) &&
(idx <= ozone->last_onscreen_entry);
}
/* If currently selected entry is off screen,
* moves selection to specified on screen target
* > Does nothing if currently selected item is
* already on screen */
static void ozone_auto_select_onscreen_entry(
ozone_handle_t *ozone,
enum ozone_onscreen_entry_position_type target_entry)
{
size_t selection = menu_navigation_get_selection();
/* Check whether selected item is already on screen */
if (ozone_entry_onscreen(ozone, selection))
return;
/* Update selection index */
switch (target_entry)
{
case OZONE_ONSCREEN_ENTRY_FIRST:
selection = ozone->first_onscreen_entry;
break;
case OZONE_ONSCREEN_ENTRY_LAST:
selection = ozone->last_onscreen_entry;
break;
case OZONE_ONSCREEN_ENTRY_CENTRE:
default:
selection = (ozone->first_onscreen_entry >> 1) +
(ozone->last_onscreen_entry >> 1);
break;
}
/* Apply new selection */
menu_navigation_set_selection(selection);
}
/* Returns true if specified category is currently
* displayed on screen */
static bool INLINE ozone_category_onscreen(
ozone_handle_t *ozone, size_t idx)
{
return (idx >= ozone->first_onscreen_category) &&
(idx <= ozone->last_onscreen_category);
}
/* If current category is on screen, returns its
* index. If current category is off screen, returns
* index of centremost on screen category. */
static size_t ozone_get_onscreen_category_selection(
ozone_handle_t *ozone)
{
/* Check whether selected category is already on screen */
if (ozone_category_onscreen(ozone, ozone->categories_selection_ptr))
return ozone->categories_selection_ptr;
/* Return index of centremost category */
return (ozone->first_onscreen_category >> 1) +
(ozone->last_onscreen_category >> 1);
}
static enum menu_action ozone_parse_menu_entry_action(
ozone_handle_t *ozone, enum menu_action action)
{
@ -2579,6 +3086,7 @@ static enum menu_action ozone_parse_menu_entry_action(
switch (action)
{
case MENU_ACTION_START:
ozone->cursor_mode = false;
/* If this is a menu with thumbnails and cursor
* is not in the sidebar, attempt to show
* fullscreen thumbnail view */
@ -2590,32 +3098,58 @@ static enum menu_action ozone_parse_menu_entry_action(
}
break;
case MENU_ACTION_DOWN:
ozone->cursor_mode = false;
if (!ozone->cursor_in_sidebar)
if (ozone->cursor_in_sidebar)
{
/* If cursor is active, ensure we target
* an on screen category */
size_t selection = (ozone->cursor_mode) ?
ozone_get_onscreen_category_selection(ozone) : ozone->categories_selection_ptr;
new_selection = (int)(selection + 1);
if (new_selection >= (int)(ozone->system_tab_end + horizontal_list_size + 1))
new_selection = 0;
ozone_sidebar_goto(ozone, new_selection);
new_action = MENU_ACTION_NOOP;
ozone->cursor_mode = false;
break;
}
new_selection = (int)(ozone->categories_selection_ptr + 1);
/* If pointer is active and current selection
* is off screen, auto select *centre* item */
if (ozone->cursor_mode)
ozone_auto_select_onscreen_entry(ozone, OZONE_ONSCREEN_ENTRY_CENTRE);
if (new_selection >= (int)(ozone->system_tab_end + horizontal_list_size + 1))
new_selection = 0;
ozone_sidebar_goto(ozone, new_selection);
new_action = MENU_ACTION_NOOP;
ozone->cursor_mode = false;
break;
case MENU_ACTION_UP:
ozone->cursor_mode = false;
if (!ozone->cursor_in_sidebar)
if (ozone->cursor_in_sidebar)
{
/* If cursor is active, ensure we target
* an on screen category */
size_t selection = (ozone->cursor_mode) ?
ozone_get_onscreen_category_selection(ozone) : ozone->categories_selection_ptr;
new_selection = (int)selection - 1;
if (new_selection < 0)
new_selection = horizontal_list_size + ozone->system_tab_end;
ozone_sidebar_goto(ozone, new_selection);
new_action = MENU_ACTION_NOOP;
ozone->cursor_mode = false;
break;
}
new_selection = (int)ozone->categories_selection_ptr - 1;
/* If pointer is active and current selection
* is off screen, auto select *centre* item */
if (ozone->cursor_mode)
ozone_auto_select_onscreen_entry(ozone, OZONE_ONSCREEN_ENTRY_CENTRE);
if (new_selection < 0)
new_selection = horizontal_list_size + ozone->system_tab_end;
ozone_sidebar_goto(ozone, new_selection);
new_action = MENU_ACTION_NOOP;
ozone->cursor_mode = false;
break;
case MENU_ACTION_LEFT:
ozone->cursor_mode = false;
@ -2671,6 +3205,41 @@ static enum menu_action ozone_parse_menu_entry_action(
new_action = MENU_ACTION_NOOP;
}
break;
case MENU_ACTION_SCROLL_UP:
/* Descend alphabet (Z towards A) */
/* Ignore if cursor is in sidebar */
if (ozone->cursor_in_sidebar)
{
new_action = MENU_ACTION_NOOP;
break;
}
/* If pointer is active and current selection
* is off screen, auto select *last* item */
if (ozone->cursor_mode)
ozone_auto_select_onscreen_entry(ozone, OZONE_ONSCREEN_ENTRY_LAST);
ozone->cursor_mode = false;
break;
case MENU_ACTION_SCROLL_DOWN:
/* Ascend alphabet (A towards Z) */
/* > Ignore if cursor is in sidebar */
if (ozone->cursor_in_sidebar)
{
new_action = MENU_ACTION_NOOP;
break;
}
/* If pointer is active and current selection
* is off screen, auto select *first* item */
if (ozone->cursor_mode)
ozone_auto_select_onscreen_entry(ozone, OZONE_ONSCREEN_ENTRY_FIRST);
ozone->cursor_mode = false;
break;
default:
/* In all other cases, pass through input
* menu action without intervention */

View File

@ -66,6 +66,10 @@ typedef struct ozone_handle ozone_handle_t;
#define FULLSCREEN_THUMBNAIL_PADDING 48
#define CURSOR_SIZE 64
/* Cursor becomes active when it moves more
* than CURSOR_ACTIVE_DELTA pixels (adjusted
* by current scale factor) */
#define CURSOR_ACTIVE_DELTA 3
#define INTERVAL_OSK_CURSOR (0.5f * 1000000)
@ -78,6 +82,13 @@ typedef struct ozone_handle ozone_handle_t;
#define OZONE_TICKER_SPACER "\xE2\x80\x83\xE2\x80\xA2\xE2\x80\x83"
#endif
enum ozone_onscreen_entry_position_type
{
OZONE_ONSCREEN_ENTRY_FIRST = 0,
OZONE_ONSCREEN_ENTRY_LAST,
OZONE_ONSCREEN_ENTRY_CENTRE
};
struct ozone_handle
{
struct
@ -241,6 +252,16 @@ struct ozone_handle
int spacer_5px;
} dimensions;
menu_input_pointer_t pointer;
int16_t pointer_active_delta;
bool pointer_in_sidebar;
bool last_pointer_in_sidebar;
size_t pointer_categories_selection;
size_t first_onscreen_entry;
size_t last_onscreen_entry;
size_t first_onscreen_category;
size_t last_onscreen_category;
bool show_cursor;
bool cursor_mode;

View File

@ -157,6 +157,14 @@ void ozone_update_scroll(ozone_handle_t *ozone, bool allow_animation, ozone_node
if (new_scroll > 0)
new_scroll = 0;
/* Kill any existing scroll animation */
gfx_animation_kill_by_tag(&tag);
/* ozone->animations.scroll_y will be modified
* > Set scroll acceleration to zero to minimise
* potential conflicts */
menu_input_set_pointer_y_accel(0.0f);
if (allow_animation)
{
/* Cursor animation */
@ -352,7 +360,6 @@ void ozone_draw_entries(ozone_handle_t *ozone, video_frame_info_t *video_info,
size_t i, y, entries_end;
float sidebar_offset, bottom_boundary, invert, alpha_anim;
unsigned video_info_height, video_info_width, entry_width, button_height;
menu_input_pointer_t pointer;
settings_t *settings = config_get_ptr();
bool old_list = selection_buf == ozone->selection_buf_old;
@ -361,30 +368,8 @@ void ozone_draw_entries(ozone_handle_t *ozone, video_frame_info_t *video_info,
size_t old_selection_y = 0;
int entry_padding = ozone_get_entries_padding(ozone, old_list);
int16_t cursor_x = 0;
int16_t cursor_y = 0;
float scale_factor = ozone->last_scale_factor;
menu_input_get_pointer_state(&pointer);
if (pointer.type != MENU_POINTER_DISABLED)
{
cursor_x = pointer.x;
cursor_y = pointer.y;
/* Not sure why it's done like this - best to leave well alone for now... */
if (settings->bools.menu_mouse_enable && !ozone->cursor_mode && (cursor_x != ozone->cursor_x_old || cursor_y != ozone->cursor_y_old))
ozone->cursor_mode = true;
else if (!settings->bools.menu_mouse_enable)
ozone->cursor_mode = false; /* we need to disable it on the fly */
}
else
ozone->cursor_mode = false;
ozone->cursor_x_old = cursor_x;
ozone->cursor_y_old = cursor_y;
menu_entries_ctl(MENU_ENTRIES_CTL_START_GET, &i);
entries_end = file_list_get_size(selection_buf);
@ -451,12 +436,6 @@ void ozone_draw_entries(ozone_handle_t *ozone, video_frame_info_t *video_info,
gfx_display_draw_quad(video_info, border_start_x,
border_start_y + button_height, entry_width, ozone->dimensions.spacer_1px, video_info->width, video_info->height, ozone->theme_dynamic.entries_border);
/* Cursor */
if (!old_list && ozone->cursor_mode)
if ( cursor_x >= border_start_x && (cursor_x <= border_start_x + (int)entry_width) &&
cursor_y >= border_start_y && (cursor_y <= border_start_y + (int)button_height))
menu_input_set_pointer_selection(i);
border_iterate:
if (node)
y += node->height;

View File

@ -146,7 +146,7 @@ void ozone_draw_sidebar(ozone_handle_t *ozone, video_frame_info_t *video_info)
if (ozone->horizontal_list)
horizontal_list_size = (unsigned)ozone->horizontal_list->size;
gfx_display_scissor_begin(video_info, 0, ozone->dimensions.header_height, (unsigned) ozone->dimensions.sidebar_width, video_info->height - ozone->dimensions.header_height - ozone->dimensions.footer_height);
gfx_display_scissor_begin(video_info, 0, ozone->dimensions.header_height + ozone->dimensions.spacer_1px, (unsigned) ozone->dimensions.sidebar_width, video_info->height - ozone->dimensions.header_height - ozone->dimensions.footer_height - ozone->dimensions.spacer_1px);
/* Background */
sidebar_height = video_info->height - ozone->dimensions.header_height - ozone->dimensions.sidebar_gradient_height * 2 - ozone->dimensions.footer_height;
@ -486,6 +486,11 @@ void ozone_sidebar_goto(ozone_handle_t *ozone, unsigned new_selection)
gfx_animation_kill_by_tag(&tag);
}
/* ozone->animations.scroll_y_sidebar will be modified
* > Set scroll acceleration to zero to minimise
* potential conflicts */
menu_input_set_pointer_y_accel(0.0f);
/* Cursor animation */
ozone->animations.cursor_alpha = 0.0f;