From 05af4656f8d84534e6a03a865be1b7e1a07cd09a Mon Sep 17 00:00:00 2001 From: tomasklaen Date: Tue, 3 Sep 2024 17:45:21 +0200 Subject: [PATCH] fix: fix active menu item indicator flickering during vertical cursor movement above actions ref #974 --- src/uosc/elements/Menu.lua | 46 +++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/src/uosc/elements/Menu.lua b/src/uosc/elements/Menu.lua index 0bdc251e..2261751f 100644 --- a/src/uosc/elements/Menu.lua +++ b/src/uosc/elements/Menu.lua @@ -1279,9 +1279,21 @@ function Menu:render() ax = item_ax, ay = math.max(item_ay, menu_rect.ay), bx = menu_rect.bx + (item.items and self.gap or -self.padding), -- to bridge the gap with cursor - by = math.min(item_by, menu_rect.by), + by = math.min(item_ay + self.scroll_step, menu_rect.by), } + -- Select hovered item + if is_current and self.mouse_nav 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 then + is_selected = true + request_render() + end + end + local has_background = is_selected or item.active local next_item = menu.items[index + 1] local next_is_active = next_item and next_item.active @@ -1314,16 +1326,6 @@ function Menu:render() opacity = highlight_opacity * menu_opacity, clip = item_clip, }) - - -- Selected item indicator line - if is_selected and not action then - local size = round(2 * state.scale) - local v_padding = math.min(state.radius, math.ceil(self.item_height / 3)) - ass:rect(ax + self.padding - size - 1, item_ay + v_padding, ax + self.padding - 1, - item_by - v_padding, { - radius = 1 * state.scale, color = fg, opacity = menu_opacity, clip = item_clip, - }) - end end local title_clip_bx = content_bx @@ -1371,7 +1373,7 @@ function Menu:render() }) -- Re-use rect as a hitbox by growing it so it bridges gaps to prevent flickering - rect.ay, rect.by, rect.bx = rect.ay - margin, rect.by + margin, rect.bx + margin + rect.ay, rect.by, rect.bx = item_ay, item_ay + self.scroll_step, rect.bx + margin -- Select action on cursor hover if self.mouse_nav and get_point_to_rectangle_proximity(cursor, rect) == 0 then @@ -1381,6 +1383,7 @@ function Menu:render() blur_action_index = false if not is_active then menu.action_index = action_index + selected_action = actions[action_index] request_render() end end @@ -1389,6 +1392,16 @@ function Menu:render() title_clip_bx = actions_rect.ax - self.gap * 2 end + -- Selected item indicator line + if is_selected and not selected_action then + local size = round(2 * state.scale) + local v_padding = math.min(state.radius, math.ceil(self.item_height / 3)) + ass:rect(ax + self.padding - size - 1, item_ay + v_padding, ax + self.padding - 1, + item_by - v_padding, { + radius = 1 * state.scale, color = fg, opacity = menu_opacity, clip = item_clip, + }) + end + -- Icon if item.icon then if not actions_rect or actions_rect.is_outside then @@ -1456,15 +1469,6 @@ function Menu:render() clip = clip, }) end - - -- Select hovered item - if is_current and self.mouse_nav 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 then request_render() end - end end -- Footnote / Selected action label