diff --git a/src/uosc/elements/Menu.lua b/src/uosc/elements/Menu.lua index 41c1347a..cc6db53d 100644 --- a/src/uosc/elements/Menu.lua +++ b/src/uosc/elements/Menu.lua @@ -1223,8 +1223,7 @@ function Menu:render() bx = bx, by = by + self.padding, } - local blur_selected_index = is_current and self.mouse_nav - local blur_action_index = is_current and self.mouse_nav + local cursor_is_moving = self.mouse_nav and cursor.distance > 10 -- Background ass:rect(menu_rect.ax, menu_rect.ay, menu_rect.bx, menu_rect.by, { @@ -1341,6 +1340,7 @@ function Menu:render() local title_clip_bx = content_bx -- Actions + local item_can_blur_action_index = false local actions_rect if is_selected and actions and #actions > 0 and not item.items then local place = item.actions_place or menu.item_actions_place @@ -1383,14 +1383,17 @@ function Menu:render() }) -- Select action on cursor hover - if self.mouse_nav and get_point_to_rectangle_proximity(cursor, rect) == 0 then - cursor:zone('primary_click', rect, self:create_action(function(shortcut) - self:activate_selected_item(shortcut) - end)) - blur_action_index = false - if not is_active then - menu.action_index = action_index - request_render() + if cursor_is_moving then + item_can_blur_action_index = menu.action_index ~= nil + if get_point_to_rectangle_proximity(cursor, rect) == 0 then + cursor:zone('primary_click', rect, self:create_action(function(shortcut) + self:activate_selected_item(shortcut) + end)) + item_can_blur_action_index = false + if not is_active then + menu.action_index = action_index + request_render() + end end end end @@ -1478,17 +1481,13 @@ function Menu:render() end -- Select hovered item - if is_current and self.mouse_nav and item.selectable ~= false then - if submenu_rect and cursor:direction_to_rectangle_distance(submenu_rect) - or actions_rect and actions_rect.is_outside and cursor:direction_to_rectangle_distance(actions_rect) then - blur_selected_index = false - else - if submenu_is_hovered or get_point_to_rectangle_proximity(cursor, item_rect_hitbox) == 0 then - blur_selected_index = false - menu.selected_index = index - if not is_selected then request_render() end - end - end + if is_current and cursor_is_moving and item.selectable ~= false + -- Do not select items if cursor is moving towards a submenu + and (not submenu_rect or not cursor:direction_to_rectangle_distance(submenu_rect)) + and (submenu_is_hovered or get_point_to_rectangle_proximity(cursor, item_rect_hitbox) == 0) then + menu.selected_index = index + if not is_selected or item_can_blur_action_index and menu.action_index then request_render() end + if item_can_blur_action_index then menu.action_index = nil end end end @@ -1599,14 +1598,6 @@ function Menu:render() ass:rect(sax, thumb_y, sbx, thumb_y + thumb_height, {color = fg, opacity = menu_opacity * 0.8}) end - -- We are in mouse nav and cursor isn't hovering any item - if blur_selected_index then - menu.selected_index = nil - end - if blur_action_index then - menu.action_index = nil - end - return menu_rect end diff --git a/src/uosc/lib/cursor.lua b/src/uosc/lib/cursor.lua index 90def37f..421f72ef 100644 --- a/src/uosc/lib/cursor.lua +++ b/src/uosc/lib/cursor.lua @@ -4,6 +4,7 @@ local cursor = { x = math.huge, y = math.huge, hidden = true, + distance = 0, -- Distance traveled during current move. Reset by `cursor.distance_reset_timer`. hover_raw = false, -- Event handlers that are only fired on zones defined during render loop. ---@type {event: string, hitbox: Hitbox; handler: CursorEventHandler}[] @@ -70,6 +71,12 @@ mp.observe_property('cursor-autohide', 'number', function(_, val) cursor.autohide_timer.timeout = (val or 1000) / 1000 end) +cursor.distance_reset_timer = mp.add_timeout(0.2, function() + cursor.distance = 0 + request_render() +end) +cursor.distance_reset_timer:kill() + -- Called at the beginning of each render function cursor:clear_zones() itable_clear(self.zones) @@ -259,7 +266,7 @@ function cursor:_find_history_sample() return self.history:tail() end --- Returns a table with current velocities in in pixels per second. +-- Returns the current velocity vector in pixels per second. ---@return Point function cursor:get_velocity() local snap = self:_find_history_sample() @@ -323,6 +330,16 @@ function cursor:move(x, y) Elements:trigger('global_mouse_enter') end + -- Update current move travel distance + -- `mp.get_time() - last.time < 0.5` check is there to ignore first event after long inactivity to + -- filter out big jumps due to window being repositioned/rescaled (e.g. opening a different file). + local last = self.last_event.move + if last and last.x < math.huge and last.y < math.huge and mp.get_time() - last.time < 0.5 then + self.distance = self.distance + get_point_to_point_proximity(cursor, last) + cursor.distance_reset_timer:kill() + cursor.distance_reset_timer:resume() + end + Elements:update_proximities() -- Update history self.history:insert({x = self.x, y = self.y, time = mp.get_time()})