refactor: cursor events consolidated into one interface (#483)

`mbtn_left` and `wheel` events are now only fired on a `cursor.on_{event}` object, which resets at the beginning of each frame, so elements need to bind these listeners in their render functions. These properties are overwritable which allows elements to take over cursor event handling from their parents if necessary.
This commit is contained in:
Tomas Klaen
2023-03-29 09:08:18 +02:00
committed by GitHub
parent 9839e7b726
commit f635df18f7
9 changed files with 155 additions and 123 deletions

View File

@@ -296,7 +296,31 @@ end
--[[ STATE ]] --[[ STATE ]]
display = {width = 1280, height = 720, scale_x = 1, scale_y = 1, initialized = false} display = {width = 1280, height = 720, scale_x = 1, scale_y = 1, initialized = false}
cursor = {hidden = true, hover_raw = false, x = 0, y = 0} cursor = {
x = 0,
y = 0,
hidden = true,
hover_raw = false,
-- Event handlers that are only fired on cursor, bound during render loop. Guidelines:
-- - element activations (clicks) go to `mbtn_left_down` handler
-- - `mbtn_button_up` is only for clearing dragging/swiping
on_primary_down = nil,
on_primary_up = nil,
on_wheel_down = nil,
on_wheel_up = nil,
-- Called at the beginning of each render
reset_handlers = function()
cursor.on_primary_down, cursor.on_primary_up = nil, nil
cursor.on_wheel_down, cursor.on_wheel_up = nil, nil
end,
-- Enables pointer key group captures needed by handlers (called at the end of each render)
decide_keybinds = function()
local mbtn_left_decision = (cursor.on_primary_down or cursor.on_primary_up) and 'enable' or 'disable'
local wheel_decision = (cursor.on_wheel_down or cursor.on_wheel_up) and 'enable' or 'disable'
mp[mbtn_left_decision .. '_key_bindings']('mbtn_left')
mp[wheel_decision .. '_key_bindings']('wheel')
end
}
state = { state = {
os = (function() os = (function()
if os.getenv('windir') ~= nil then return 'windows' end if os.getenv('windir') ~= nil then return 'windows' end
@@ -771,6 +795,23 @@ mp.observe_property('core-idle', 'native', create_state_setter('core_idle'))
--[[ KEY BINDS ]] --[[ KEY BINDS ]]
-- Pointer related binding groups
mp.set_key_bindings({
{
'mbtn_left',
function(...) call_maybe(cursor.on_primary_up, ...) end,
function(...)
update_mouse_pos(nil, mp.get_property_native('mouse-pos'))
call_maybe(cursor.on_primary_down, ...)
end,
},
{'mbtn_left_dbl', 'ignore'},
}, 'mbtn_left', 'force')
mp.set_key_bindings({
{'wheel_up', function(...) call_maybe(cursor.on_wheel_up, ...) end},
{'wheel_down', function(...) call_maybe(cursor.on_wheel_down, ...) end},
}, 'wheel', 'force')
-- Adds a key binding that respects rerouting set by `key_binding_overwrites` table. -- Adds a key binding that respects rerouting set by `key_binding_overwrites` table.
---@param name string ---@param name string
---@param callback fun(event: table) ---@param callback fun(event: table)

View File

@@ -23,19 +23,20 @@ function Button:init(id, props)
end end
function Button:on_coordinates() self.font_size = round((self.by - self.ay) * 0.7) end function Button:on_coordinates() self.font_size = round((self.by - self.ay) * 0.7) end
function Button:on_mbtn_left_down() function Button:handle_cursor_down()
-- Don't accept clicks while hidden.
if self:get_visibility() <= 0 then return end
-- We delay the callback to next tick, otherwise we are risking race -- We delay the callback to next tick, otherwise we are risking race
-- conditions as we are in the middle of event dispatching. -- conditions as we are in the middle of event dispatching.
-- For example, handler might add a menu to the end of the element stack, and that -- For example, handler might add a menu to the end of the element stack, and that
-- than picks up this click even we are in right now, and instantly closes itself. -- than picks up this click event we are in right now, and instantly closes itself.
mp.add_timeout(0.01, self.on_click) mp.add_timeout(0.01, self.on_click)
end end
function Button:render() function Button:render()
local visibility = self:get_visibility() local visibility = self:get_visibility()
if visibility <= 0 then return end if visibility <= 0 then return end
if self.proximity_raw == 0 then
cursor.on_primary_down = function() self:handle_cursor_down() end
end
local ass = assdraw.ass_new() local ass = assdraw.ass_new()
local is_hover = self.proximity_raw == 0 local is_hover = self.proximity_raw == 0
@@ -54,7 +55,6 @@ function Button:render()
-- Tooltip on hover -- Tooltip on hover
if is_hover and self.tooltip then ass:tooltip(self, self.tooltip) end if is_hover and self.tooltip then ass:tooltip(self, self.tooltip) end
-- Badge -- Badge
local icon_clip local icon_clip
if self.badge then if self.badge then

View File

@@ -29,8 +29,6 @@ function Elements:remove(idOrElement)
end end
function Elements:update_proximities() function Elements:update_proximities()
local capture_mbtn_left = false
local capture_wheel = false
local menu_only = Elements.menu ~= nil local menu_only = Elements.menu ~= nil
local mouse_leave_elements = {} local mouse_leave_elements = {}
local mouse_enter_elements = {} local mouse_enter_elements = {}
@@ -42,26 +40,13 @@ function Elements:update_proximities()
-- If menu is open, all other elements have to be disabled -- If menu is open, all other elements have to be disabled
if menu_only then if menu_only then
if element.ignores_menu then if element.ignores_menu then element:update_proximity()
capture_mbtn_left = true else element:reset_proximity() end
capture_wheel = true
element:update_proximity()
else
element:reset_proximity()
end
else else
element:update_proximity() element:update_proximity()
end end
-- Element has global forced key listeners
if element.on_global_mbtn_left_down then capture_mbtn_left = true end
if element.on_global_wheel_up or element.on_global_wheel_down then capture_wheel = true end
if element.proximity_raw == 0 then if element.proximity_raw == 0 then
-- Element has local forced key listeners
if element.on_mbtn_left_down then capture_mbtn_left = true end
if element.on_wheel_up or element.on_wheel_up then capture_wheel = true end
-- Mouse entered element area -- Mouse entered element area
if previous_proximity_raw ~= 0 then if previous_proximity_raw ~= 0 then
mouse_enter_elements[#mouse_enter_elements + 1] = element mouse_enter_elements[#mouse_enter_elements + 1] = element
@@ -75,10 +60,6 @@ function Elements:update_proximities()
end end
end end
-- Enable key group captures requested by elements
mp[capture_mbtn_left and 'enable_key_bindings' or 'disable_key_bindings']('mbtn_left')
mp[capture_wheel and 'enable_key_bindings' or 'disable_key_bindings']('wheel')
-- Trigger `mouse_leave` and `mouse_enter` events -- Trigger `mouse_leave` and `mouse_enter` events
for _, element in ipairs(mouse_leave_elements) do element:trigger('mouse_leave') end for _, element in ipairs(mouse_leave_elements) do element:trigger('mouse_leave') end
for _, element in ipairs(mouse_enter_elements) do element:trigger('mouse_enter') end for _, element in ipairs(mouse_enter_elements) do element:trigger('mouse_enter') end
@@ -142,26 +123,4 @@ end
function Elements:has(id) return self[id] ~= nil end function Elements:has(id) return self[id] ~= nil end
function Elements:ipairs() return ipairs(self.itable) end function Elements:ipairs() return ipairs(self.itable) end
---@param name string Event name.
function Elements:create_proximity_dispatcher(name)
return function(...) self:proximity_trigger(name, ...) end
end
mp.set_key_bindings({
{
'mbtn_left',
Elements:create_proximity_dispatcher('mbtn_left_up'),
function(...)
update_mouse_pos(nil, mp.get_property_native('mouse-pos'))
Elements:proximity_trigger('mbtn_left_down', ...)
end,
},
{'mbtn_left_dbl', 'ignore'},
}, 'mbtn_left', 'force')
mp.set_key_bindings({
{'wheel_up', Elements:create_proximity_dispatcher('wheel_up')},
{'wheel_down', Elements:create_proximity_dispatcher('wheel_down')},
}, 'wheel', 'force')
return Elements return Elements

View File

@@ -518,7 +518,7 @@ end
function Menu:on_display() self:update_dimensions() end function Menu:on_display() self:update_dimensions() end
function Menu:on_prop_fullormaxed() self:update_content_dimensions() end function Menu:on_prop_fullormaxed() self:update_content_dimensions() end
function Menu:on_global_mbtn_left_down() function Menu:handle_cursor_down()
if self.proximity_raw == 0 then if self.proximity_raw == 0 then
self.drag_data = {{y = cursor.y, time = mp.get_time()}} self.drag_data = {{y = cursor.y, time = mp.get_time()}}
self.current.fling = nil self.current.fling = nil
@@ -538,7 +538,7 @@ function Menu:fling_distance()
return #self.drag_data < 2 and 0 or ((first.y - last.y) / ((first.time - last.time) / 0.03)) * 10 return #self.drag_data < 2 and 0 or ((first.y - last.y) / ((first.time - last.time) / 0.03)) * 10
end end
function Menu:on_global_mbtn_left_up() function Menu:handle_cursor_up()
if self.proximity_raw == 0 and self.drag_data and not self.is_dragging then if self.proximity_raw == 0 and self.drag_data and not self.is_dragging then
self:select_item_below_cursor() self:select_item_below_cursor()
self:open_selected_item({preselect_submenu_item = false, keep_open = self.modifiers and self.modifiers.shift}) self:open_selected_item({preselect_submenu_item = false, keep_open = self.modifiers and self.modifiers.shift})
@@ -570,8 +570,8 @@ function Menu:on_global_mouse_move()
request_render() request_render()
end end
function Menu:on_wheel_up() self:scroll_by(self.scroll_step * -3, nil, {update_cursor = true}) end function Menu:handle_wheel_up() self:scroll_by(self.scroll_step * -3, nil, {update_cursor = true}) end
function Menu:on_wheel_down() self:scroll_by(self.scroll_step * 3, nil, {update_cursor = true}) end function Menu:handle_wheel_down() self:scroll_by(self.scroll_step * 3, nil, {update_cursor = true}) end
function Menu:on_pgup() function Menu:on_pgup()
local menu = self.current local menu = self.current
@@ -647,8 +647,8 @@ function Menu:create_modified_mbtn_left_handler(modifiers)
return function() return function()
self.mouse_nav = true self.mouse_nav = true
self.modifiers = modifiers self.modifiers = modifiers
self:on_global_mbtn_left_down() self:handle_cursor_down()
self:on_global_mbtn_left_up() self:handle_cursor_up()
self.modifiers = nil self.modifiers = nil
end end
end end
@@ -677,6 +677,13 @@ function Menu:render()
end end
if update_cursor then self:select_item_below_cursor() end if update_cursor then self:select_item_below_cursor() end
cursor.on_primary_down = function() self:handle_cursor_down() end
cursor.on_primary_up = function() self:handle_cursor_up() end
if self.proximity_raw == 0 then
cursor.on_wheel_down = function() self:handle_wheel_down() end
cursor.on_wheel_up = function() self:handle_wheel_up() end
end
local ass = assdraw.ass_new() local ass = assdraw.ass_new()
local opacity = options.menu_opacity * self.opacity local opacity = options.menu_opacity * self.opacity
local spacing = self.item_padding local spacing = self.item_padding

View File

@@ -44,9 +44,7 @@ function Speed:speed_step(speed, up)
end end
end end
function Speed:on_mbtn_left_down() function Speed:handle_cursor_down()
-- Don't accept clicks while hidden.
if self:get_visibility() <= 0 then return end
self:tween_stop() -- Stop and cleanup possible ongoing animations self:tween_stop() -- Stop and cleanup possible ongoing animations
self.dragging = { self.dragging = {
start_time = mp.get_time(), start_time = mp.get_time(),
@@ -87,14 +85,13 @@ function Speed:on_global_mouse_move()
end end
end end
function Speed:on_mbtn_left_up() function Speed:handle_cursor_up()
-- Reset speed on short clicks if self.proximity_raw == 0 then
if self.dragging and math.abs(self.dragging.distance) < 6 and mp.get_time() - self.dragging.start_time < 0.15 then -- Reset speed on short clicks
mp.set_property_native('speed', 1) if self.dragging and math.abs(self.dragging.distance) < 6 and mp.get_time() - self.dragging.start_time < 0.15 then
mp.set_property_native('speed', 1)
end
end end
end
function Speed:on_global_mbtn_left_up()
self.dragging = nil self.dragging = nil
request_render() request_render()
end end
@@ -104,8 +101,8 @@ function Speed:on_global_mouse_leave()
request_render() request_render()
end end
function Speed:on_wheel_up() mp.set_property_native('speed', self:speed_step(state.speed, true)) end function Speed:handle_wheel_up() mp.set_property_native('speed', self:speed_step(state.speed, true)) end
function Speed:on_wheel_down() mp.set_property_native('speed', self:speed_step(state.speed, false)) end function Speed:handle_wheel_down() mp.set_property_native('speed', self:speed_step(state.speed, false)) end
function Speed:render() function Speed:render()
local visibility = self:get_visibility() local visibility = self:get_visibility()
@@ -113,6 +110,18 @@ function Speed:render()
if opacity <= 0 then return end if opacity <= 0 then return end
if self.proximity_raw == 0 then
cursor.on_primary_down = function()
self:handle_cursor_down()
cursor.on_primary_up = function() self:handle_cursor_up() end
end
cursor.on_wheel_down = function() self:handle_wheel_down() end
cursor.on_wheel_up = function() self:handle_wheel_up() end
end
if self.dragging then
cursor.on_primary_up = function() self:handle_cursor_up() end
end
local ass = assdraw.ass_new() local ass = assdraw.ass_new()
-- Background -- Background

View File

@@ -6,6 +6,7 @@ local Timeline = class(Element)
function Timeline:new() return Class.new(self) --[[@as Timeline]] end function Timeline:new() return Class.new(self) --[[@as Timeline]] end
function Timeline:init() function Timeline:init()
Element.init(self, 'timeline') Element.init(self, 'timeline')
---@type false|{pause: boolean}
self.pressed = false self.pressed = false
self.obstructed = false self.obstructed = false
self.size_max = 0 self.size_max = 0
@@ -13,7 +14,8 @@ function Timeline:init()
self.size_min_override = options.timeline_start_hidden and 0 or nil self.size_min_override = options.timeline_start_hidden and 0 or nil
self.font_size = 0 self.font_size = 0
self.top_border = options.timeline_border self.top_border = options.timeline_border
self.hovered_chapter = nil self.is_hovered = false
self.has_thumbnail = false
-- Release any dragging when file gets unloaded -- Release any dragging when file gets unloaded
mp.register_event('end-file', function() self.pressed = false end) mp.register_event('end-file', function() self.pressed = false end)
@@ -44,7 +46,7 @@ function Timeline:get_effective_line_width()
return state.fullormaxed and options.timeline_line_width_fullscreen or options.timeline_line_width return state.fullormaxed and options.timeline_line_width_fullscreen or options.timeline_line_width
end end
function Timeline:get_is_hovered() return self.enabled and (self.proximity_raw == 0 or self.hovered_chapter ~= nil) end function Timeline:get_is_hovered() return self.enabled and self.is_hovered end
function Timeline:update_dimensions() function Timeline:update_dimensions()
if state.fullormaxed then if state.fullormaxed then
@@ -91,41 +93,20 @@ function Timeline:set_from_cursor(fast)
end end
function Timeline:clear_thumbnail() mp.commandv('script-message-to', 'thumbfast', 'clear') end function Timeline:clear_thumbnail() mp.commandv('script-message-to', 'thumbfast', 'clear') end
function Timeline:determine_chapter_click_handler() function Timeline:handle_cursor_down()
if self.hovered_chapter then self.pressed = {pause = state.pause}
if not self.on_global_mbtn_left_down then
self.on_global_mbtn_left_down = function()
if self.hovered_chapter then mp.commandv('seek', self.hovered_chapter.time, 'absolute+exact') end
end
end
else
if self.on_global_mbtn_left_down then
self.on_global_mbtn_left_down = nil
if self.proximity_raw ~= 0 then self:clear_thumbnail() end
end
end
end
function Timeline:on_mbtn_left_down()
-- `self.on_global_mbtn_left_down` has precedent
if self.on_global_mbtn_left_down then return end
self.pressed = true
self.pressed_pause = state.pause
mp.set_property_native('pause', true) mp.set_property_native('pause', true)
self:set_from_cursor() self:set_from_cursor()
cursor.on_primary_up = function() self:handle_cursor_up() end
end end
function Timeline:on_prop_duration() self:decide_enabled() end function Timeline:on_prop_duration() self:decide_enabled() end
function Timeline:on_prop_time() self:decide_enabled() end function Timeline:on_prop_time() self:decide_enabled() end
function Timeline:on_prop_border() self:update_dimensions() end function Timeline:on_prop_border() self:update_dimensions() end
function Timeline:on_prop_fullormaxed() self:update_dimensions() end function Timeline:on_prop_fullormaxed() self:update_dimensions() end
function Timeline:on_display() self:update_dimensions() end function Timeline:on_display() self:update_dimensions() end
function Timeline:on_mouse_leave() function Timeline:handle_cursor_up()
if not self.hovered_chapter then self:clear_thumbnail() end
end
function Timeline:on_global_mbtn_left_up()
if self.pressed then if self.pressed then
mp.set_property_native('pause', self.pressed_pause) mp.set_property_native('pause', self.pressed.pause)
self.pressed = false self.pressed = false
end end
self:clear_thumbnail() self:clear_thumbnail()
@@ -144,11 +125,12 @@ function Timeline:on_global_mouse_move()
self.seek_timer:kill() self.seek_timer:kill()
self.seek_timer:resume() self.seek_timer:resume()
else self:set_from_cursor() end else self:set_from_cursor() end
elseif self.has_thumbnail and self.proximity_raw > 0 then
self:clear_thumbnail()
end end
self:determine_chapter_click_handler()
end end
function Timeline:on_wheel_up() mp.commandv('seek', options.timeline_step) end function Timeline:handle_wheel_up() mp.commandv('seek', options.timeline_step) end
function Timeline:on_wheel_down() mp.commandv('seek', -options.timeline_step) end function Timeline:handle_wheel_down() mp.commandv('seek', -options.timeline_step) end
function Timeline:render() function Timeline:render()
if self.size_max == 0 then return end if self.size_max == 0 then return end
@@ -156,8 +138,18 @@ function Timeline:render()
local size_min = self:get_effective_size_min() local size_min = self:get_effective_size_min()
local size = self:get_effective_size() local size = self:get_effective_size()
local visibility = self:get_visibility() local visibility = self:get_visibility()
self.is_hovered = false
if size < 1 then return end if size < 1 then return end
if self.proximity_raw == 0 then
self.is_hovered = true
cursor.on_primary_down = function() self:handle_cursor_down() end
cursor.on_wheel_down = function() self:handle_wheel_down() end
cursor.on_wheel_up = function() self:handle_wheel_up() end
end
if self.pressed then
cursor.on_primary_up = function() self:handle_cursor_up() end
end
local ass = assdraw.ass_new() local ass = assdraw.ass_new()
@@ -248,7 +240,7 @@ function Timeline:render()
end end
-- Chapters -- Chapters
self.hovered_chapter = nil local hovered_chapter = nil
if (options.timeline_chapters_opacity > 0 if (options.timeline_chapters_opacity > 0
and (#state.chapters > 0 or state.ab_loop_a or state.ab_loop_b) and (#state.chapters > 0 or state.ab_loop_a or state.ab_loop_b)
) then ) then
@@ -274,7 +266,7 @@ function Timeline:render()
if #state.chapters > 0 then if #state.chapters > 0 then
-- Find hovered chapter indicator -- Find hovered chapter indicator
local hovered_chapter, closest_delta = nil, INFINITY local closest_delta = INFINITY
if self.proximity_raw < diamond_radius_hovered then if self.proximity_raw < diamond_radius_hovered then
for i, chapter in ipairs(state.chapters) do for i, chapter in ipairs(state.chapters) do
@@ -282,6 +274,10 @@ function Timeline:render()
local cursor_chapter_delta = math.sqrt((cursor.x - chapter_x) ^ 2 + (cursor.y - chapter_y) ^ 2) local cursor_chapter_delta = math.sqrt((cursor.x - chapter_x) ^ 2 + (cursor.y - chapter_y) ^ 2)
if cursor_chapter_delta <= diamond_radius_hovered and cursor_chapter_delta < closest_delta then if cursor_chapter_delta <= diamond_radius_hovered and cursor_chapter_delta < closest_delta then
hovered_chapter, closest_delta = chapter, cursor_chapter_delta hovered_chapter, closest_delta = chapter, cursor_chapter_delta
self.is_hovered = true
cursor.on_primary_down = function()
mp.commandv('seek', hovered_chapter.time, 'absolute+exact')
end
end end
end end
end end
@@ -291,11 +287,7 @@ function Timeline:render()
end end
-- Render hovered chapter above others -- Render hovered chapter above others
if hovered_chapter then if hovered_chapter then draw_chapter(hovered_chapter.time, diamond_radius_hovered) end
draw_chapter(hovered_chapter.time, diamond_radius_hovered)
self.hovered_chapter = hovered_chapter
self:determine_chapter_click_handler()
end
end end
-- A-B loop indicators -- A-B loop indicators
@@ -363,10 +355,10 @@ function Timeline:render()
end end
-- Hovered time and chapter -- Hovered time and chapter
if (self.proximity_raw == 0 or self.pressed or self.hovered_chapter) and if (self.proximity_raw == 0 or self.pressed or hovered_chapter) and
not (Elements.speed and Elements.speed.dragging) then not (Elements.speed and Elements.speed.dragging) then
local cursor_x = self.hovered_chapter and t2x(self.hovered_chapter.time) or cursor.x local cursor_x = hovered_chapter and t2x(hovered_chapter.time) or cursor.x
local hovered_seconds = self.hovered_chapter and self.hovered_chapter.time or self:get_time_at_x(cursor.x) local hovered_seconds = hovered_chapter and hovered_chapter.time or self:get_time_at_x(cursor.x)
-- Cursor line -- Cursor line
-- 0.5 to switch when the pixel is half filled in -- 0.5 to switch when the pixel is half filled in
@@ -397,7 +389,10 @@ function Timeline:render()
local ax, ay = (thumb_x - border) / scale_x, (thumb_y - border) / scale_y local ax, ay = (thumb_x - border) / scale_x, (thumb_y - border) / scale_y
local bx, by = (thumb_x + thumb_width + border) / scale_x, (thumb_y + thumb_height + border) / scale_y local bx, by = (thumb_x + thumb_width + border) / scale_x, (thumb_y + thumb_height + border) / scale_y
ass:rect(ax, ay, bx, by, {color = bg, border = 1, border_color = fg, border_opacity = 0.08, radius = 2}) ass:rect(ax, ay, bx, by, {color = bg, border = 1, border_color = fg, border_opacity = 0.08, radius = 2})
mp.commandv('script-message-to', 'thumbfast', 'thumb', hovered_seconds, thumb_x, thumb_y) if not self.pressed then
mp.commandv('script-message-to', 'thumbfast', 'thumb', hovered_seconds, thumb_x, thumb_y)
self.has_thumbnail = true
end
tooltip_anchor.ax, tooltip_anchor.bx, tooltip_anchor.ay = ax, bx, ay tooltip_anchor.ax, tooltip_anchor.bx, tooltip_anchor.ay = ax, bx, ay
end end

View File

@@ -16,7 +16,7 @@ function TopBarButton:init(id, props)
self.command = props.command self.command = props.command
end end
function TopBarButton:on_mbtn_left_down() function TopBarButton:handle_cursor_down()
mp.command(type(self.command) == 'function' and self.command() or self.command) mp.command(type(self.command) == 'function' and self.command() or self.command)
end end
@@ -28,6 +28,7 @@ function TopBarButton:render()
-- Background on hover -- Background on hover
if self.proximity_raw == 0 then if self.proximity_raw == 0 then
ass:rect(self.ax, self.ay, self.bx, self.by, {color = self.background, opacity = visibility}) ass:rect(self.ax, self.ay, self.bx, self.by, {color = self.background, opacity = visibility})
cursor.on_primary_down = function() self:handle_cursor_down() end
end end
local width, height = self.bx - self.ax, self.by - self.ay local width, height = self.bx - self.ax, self.by - self.ay
@@ -151,10 +152,6 @@ function TopBar:on_prop_maximized()
self:update_dimensions() self:update_dimensions()
end end
function TopBar:on_mbtn_left_down()
if cursor.x < self.title_bx then self:toggle_title() end
end
function TopBar:on_display() self:update_dimensions() end function TopBar:on_display() self:update_dimensions() end
function TopBar:render() function TopBar:render()
@@ -193,6 +190,12 @@ function TopBar:render()
} }
local bx = math.min(max_bx, title_ax + text_width(main_title, opts) + padding * 2) local bx = math.min(max_bx, title_ax + text_width(main_title, opts) + padding * 2)
local by = self.by - bg_margin local by = self.by - bg_margin
local rect = {ax = title_ax, ay = self.ay, bx = bx, by = self.by}
if get_point_to_rectangle_proximity(cursor, rect) == 0 then
cursor.on_primary_down = function() self:toggle_title() end
end
ass:rect(title_ax, title_ay, bx, by, { ass:rect(title_ax, title_ay, bx, by, {
color = bg, opacity = visibility * options.top_bar_title_opacity, radius = 2, color = bg, opacity = visibility * options.top_bar_title_opacity, radius = 2,
}) })

View File

@@ -7,10 +7,12 @@ local MuteButton = class(Element)
---@param props? ElementProps ---@param props? ElementProps
function MuteButton:new(props) return Class.new(self, 'volume_mute', props) --[[@as MuteButton]] end function MuteButton:new(props) return Class.new(self, 'volume_mute', props) --[[@as MuteButton]] end
function MuteButton:get_visibility() return Elements.volume:get_visibility(self) end function MuteButton:get_visibility() return Elements.volume:get_visibility(self) end
function MuteButton:on_mbtn_left_down() mp.commandv('cycle', 'mute') end
function MuteButton:render() function MuteButton:render()
local visibility = self:get_visibility() local visibility = self:get_visibility()
if visibility <= 0 then return end if visibility <= 0 then return end
if self.proximity_raw == 0 then
cursor.on_primary_down = function() mp.commandv('cycle', 'mute') end
end
local ass = assdraw.ass_new() local ass = assdraw.ass_new()
local icon_name = state.mute and 'volume_off' or 'volume_up' local icon_name = state.mute and 'volume_off' or 'volume_up'
local width = self.bx - self.ax local width = self.bx - self.ax
@@ -58,17 +60,11 @@ function VolumeSlider:on_coordinates()
self.spacing = round(width * 0.2) self.spacing = round(width * 0.2)
self.radius = math.max(2, (self.bx - self.ax) / 10) self.radius = math.max(2, (self.bx - self.ax) / 10)
end end
function VolumeSlider:on_mbtn_left_down()
self.pressed = true
self:set_from_cursor()
end
function VolumeSlider:on_global_mbtn_left_up() self.pressed = false end
function VolumeSlider:on_global_mouse_leave() self.pressed = false end
function VolumeSlider:on_global_mouse_move() function VolumeSlider:on_global_mouse_move()
if self.pressed then self:set_from_cursor() end if self.pressed then self:set_from_cursor() end
end end
function VolumeSlider:on_wheel_up() self:set_volume(state.volume + options.volume_step) end function VolumeSlider:handle_wheel_up() self:set_volume(state.volume + options.volume_step) end
function VolumeSlider:on_wheel_down() self:set_volume(state.volume - options.volume_step) end function VolumeSlider:handle_wheel_down() self:set_volume(state.volume - options.volume_step) end
function VolumeSlider:render() function VolumeSlider:render()
local visibility = self:get_visibility() local visibility = self:get_visibility()
@@ -77,6 +73,19 @@ function VolumeSlider:render()
if width <= 0 or height <= 0 or visibility <= 0 then return end if width <= 0 or height <= 0 or visibility <= 0 then return end
if self.proximity_raw == 0 then
cursor.on_primary_down = function()
self.pressed = true
self:set_from_cursor()
cursor.on_primary_up = function() self.pressed = false end
end
cursor.on_wheel_down = function() self:handle_wheel_down() end
cursor.on_wheel_up = function() self:handle_wheel_up() end
end
if self.pressed then cursor.on_primary_up = function()
self.pressed = false end
end
local ass = assdraw.ass_new() local ass = assdraw.ass_new()
local nudge_y, nudge_size = self.draw_nudge and self.nudge_y or -INFINITY, self.nudge_size local nudge_y, nudge_size = self.draw_nudge and self.nudge_y or -INFINITY, self.nudge_size
local volume_y = self.ay + options.volume_border + local volume_y = self.ay + options.volume_border +

View File

@@ -93,6 +93,11 @@ function get_point_to_rectangle_proximity(point, rect)
return math.sqrt(dx * dx + dy * dy) return math.sqrt(dx * dx + dy * dy)
end end
-- Call function with args if it exists
function call_maybe(fn, ...)
if type(fn) == 'function' then fn(...) end
end
-- Extracts the properties used by property expansion of that string. -- Extracts the properties used by property expansion of that string.
---@param str string ---@param str string
---@param res { [string] : boolean } | nil ---@param res { [string] : boolean } | nil
@@ -553,6 +558,8 @@ function render()
if not display.initialized then return end if not display.initialized then return end
state.render_last_time = mp.get_time() state.render_last_time = mp.get_time()
cursor.reset_handlers()
-- Actual rendering -- Actual rendering
local ass = assdraw.ass_new() local ass = assdraw.ass_new()
@@ -566,6 +573,8 @@ function render()
end end
end end
cursor.decide_keybinds()
-- submit -- submit
if osd.res_x == display.width and osd.res_y == display.height and osd.data == ass.text then if osd.res_x == display.width and osd.res_y == display.height and osd.data == ass.text then
return return