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:
@@ -296,7 +296,31 @@ end
|
||||
--[[ STATE ]]
|
||||
|
||||
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 = {
|
||||
os = (function()
|
||||
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 ]]
|
||||
|
||||
-- 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.
|
||||
---@param name string
|
||||
---@param callback fun(event: table)
|
||||
|
@@ -23,19 +23,20 @@ function Button:init(id, props)
|
||||
end
|
||||
|
||||
function Button:on_coordinates() self.font_size = round((self.by - self.ay) * 0.7) end
|
||||
function Button:on_mbtn_left_down()
|
||||
-- Don't accept clicks while hidden.
|
||||
if self:get_visibility() <= 0 then return end
|
||||
function Button:handle_cursor_down()
|
||||
-- We delay the callback to next tick, otherwise we are risking race
|
||||
-- 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
|
||||
-- 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)
|
||||
end
|
||||
|
||||
function Button:render()
|
||||
local visibility = self:get_visibility()
|
||||
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 is_hover = self.proximity_raw == 0
|
||||
@@ -54,7 +55,6 @@ function Button:render()
|
||||
-- Tooltip on hover
|
||||
if is_hover and self.tooltip then ass:tooltip(self, self.tooltip) end
|
||||
|
||||
|
||||
-- Badge
|
||||
local icon_clip
|
||||
if self.badge then
|
||||
|
@@ -29,8 +29,6 @@ function Elements:remove(idOrElement)
|
||||
end
|
||||
|
||||
function Elements:update_proximities()
|
||||
local capture_mbtn_left = false
|
||||
local capture_wheel = false
|
||||
local menu_only = Elements.menu ~= nil
|
||||
local mouse_leave_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_only then
|
||||
if element.ignores_menu then
|
||||
capture_mbtn_left = true
|
||||
capture_wheel = true
|
||||
element:update_proximity()
|
||||
else
|
||||
element:reset_proximity()
|
||||
end
|
||||
if element.ignores_menu then element:update_proximity()
|
||||
else element:reset_proximity() end
|
||||
else
|
||||
element:update_proximity()
|
||||
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
|
||||
-- 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
|
||||
if previous_proximity_raw ~= 0 then
|
||||
mouse_enter_elements[#mouse_enter_elements + 1] = element
|
||||
@@ -75,10 +60,6 @@ function Elements:update_proximities()
|
||||
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
|
||||
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
|
||||
@@ -142,26 +123,4 @@ end
|
||||
function Elements:has(id) return self[id] ~= nil 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
|
||||
|
@@ -518,7 +518,7 @@ end
|
||||
function Menu:on_display() self:update_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
|
||||
self.drag_data = {{y = cursor.y, time = mp.get_time()}}
|
||||
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
|
||||
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
|
||||
self:select_item_below_cursor()
|
||||
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()
|
||||
end
|
||||
|
||||
function Menu:on_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_up() 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()
|
||||
local menu = self.current
|
||||
@@ -647,8 +647,8 @@ function Menu:create_modified_mbtn_left_handler(modifiers)
|
||||
return function()
|
||||
self.mouse_nav = true
|
||||
self.modifiers = modifiers
|
||||
self:on_global_mbtn_left_down()
|
||||
self:on_global_mbtn_left_up()
|
||||
self:handle_cursor_down()
|
||||
self:handle_cursor_up()
|
||||
self.modifiers = nil
|
||||
end
|
||||
end
|
||||
@@ -677,6 +677,13 @@ function Menu:render()
|
||||
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 opacity = options.menu_opacity * self.opacity
|
||||
local spacing = self.item_padding
|
||||
|
@@ -44,9 +44,7 @@ function Speed:speed_step(speed, up)
|
||||
end
|
||||
end
|
||||
|
||||
function Speed:on_mbtn_left_down()
|
||||
-- Don't accept clicks while hidden.
|
||||
if self:get_visibility() <= 0 then return end
|
||||
function Speed:handle_cursor_down()
|
||||
self:tween_stop() -- Stop and cleanup possible ongoing animations
|
||||
self.dragging = {
|
||||
start_time = mp.get_time(),
|
||||
@@ -87,14 +85,13 @@ function Speed:on_global_mouse_move()
|
||||
end
|
||||
end
|
||||
|
||||
function Speed:on_mbtn_left_up()
|
||||
-- Reset speed on short clicks
|
||||
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)
|
||||
function Speed:handle_cursor_up()
|
||||
if self.proximity_raw == 0 then
|
||||
-- Reset speed on short clicks
|
||||
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
|
||||
|
||||
function Speed:on_global_mbtn_left_up()
|
||||
self.dragging = nil
|
||||
request_render()
|
||||
end
|
||||
@@ -104,8 +101,8 @@ function Speed:on_global_mouse_leave()
|
||||
request_render()
|
||||
end
|
||||
|
||||
function Speed:on_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_up() mp.set_property_native('speed', self:speed_step(state.speed, true)) end
|
||||
function Speed:handle_wheel_down() mp.set_property_native('speed', self:speed_step(state.speed, false)) end
|
||||
|
||||
function Speed:render()
|
||||
local visibility = self:get_visibility()
|
||||
@@ -113,6 +110,18 @@ function Speed:render()
|
||||
|
||||
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()
|
||||
|
||||
-- Background
|
||||
|
@@ -6,6 +6,7 @@ local Timeline = class(Element)
|
||||
function Timeline:new() return Class.new(self) --[[@as Timeline]] end
|
||||
function Timeline:init()
|
||||
Element.init(self, 'timeline')
|
||||
---@type false|{pause: boolean}
|
||||
self.pressed = false
|
||||
self.obstructed = false
|
||||
self.size_max = 0
|
||||
@@ -13,7 +14,8 @@ function Timeline:init()
|
||||
self.size_min_override = options.timeline_start_hidden and 0 or nil
|
||||
self.font_size = 0
|
||||
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
|
||||
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
|
||||
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()
|
||||
if state.fullormaxed then
|
||||
@@ -91,41 +93,20 @@ function Timeline:set_from_cursor(fast)
|
||||
end
|
||||
function Timeline:clear_thumbnail() mp.commandv('script-message-to', 'thumbfast', 'clear') end
|
||||
|
||||
function Timeline:determine_chapter_click_handler()
|
||||
if self.hovered_chapter then
|
||||
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
|
||||
function Timeline:handle_cursor_down()
|
||||
self.pressed = {pause = state.pause}
|
||||
mp.set_property_native('pause', true)
|
||||
self:set_from_cursor()
|
||||
cursor.on_primary_up = function() self:handle_cursor_up() end
|
||||
end
|
||||
function Timeline:on_prop_duration() 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_fullormaxed() self:update_dimensions() end
|
||||
function Timeline:on_display() self:update_dimensions() end
|
||||
function Timeline:on_mouse_leave()
|
||||
if not self.hovered_chapter then self:clear_thumbnail() end
|
||||
end
|
||||
function Timeline:on_global_mbtn_left_up()
|
||||
function Timeline:handle_cursor_up()
|
||||
if self.pressed then
|
||||
mp.set_property_native('pause', self.pressed_pause)
|
||||
mp.set_property_native('pause', self.pressed.pause)
|
||||
self.pressed = false
|
||||
end
|
||||
self:clear_thumbnail()
|
||||
@@ -144,11 +125,12 @@ function Timeline:on_global_mouse_move()
|
||||
self.seek_timer:kill()
|
||||
self.seek_timer:resume()
|
||||
else self:set_from_cursor() end
|
||||
elseif self.has_thumbnail and self.proximity_raw > 0 then
|
||||
self:clear_thumbnail()
|
||||
end
|
||||
self:determine_chapter_click_handler()
|
||||
end
|
||||
function Timeline:on_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_up() mp.commandv('seek', options.timeline_step) end
|
||||
function Timeline:handle_wheel_down() mp.commandv('seek', -options.timeline_step) end
|
||||
|
||||
function Timeline:render()
|
||||
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 = self:get_effective_size()
|
||||
local visibility = self:get_visibility()
|
||||
self.is_hovered = false
|
||||
|
||||
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()
|
||||
|
||||
@@ -248,7 +240,7 @@ function Timeline:render()
|
||||
end
|
||||
|
||||
-- Chapters
|
||||
self.hovered_chapter = nil
|
||||
local hovered_chapter = nil
|
||||
if (options.timeline_chapters_opacity > 0
|
||||
and (#state.chapters > 0 or state.ab_loop_a or state.ab_loop_b)
|
||||
) then
|
||||
@@ -274,7 +266,7 @@ function Timeline:render()
|
||||
|
||||
if #state.chapters > 0 then
|
||||
-- Find hovered chapter indicator
|
||||
local hovered_chapter, closest_delta = nil, INFINITY
|
||||
local closest_delta = INFINITY
|
||||
|
||||
if self.proximity_raw < diamond_radius_hovered then
|
||||
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)
|
||||
if cursor_chapter_delta <= diamond_radius_hovered and cursor_chapter_delta < closest_delta then
|
||||
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
|
||||
@@ -291,11 +287,7 @@ function Timeline:render()
|
||||
end
|
||||
|
||||
-- Render hovered chapter above others
|
||||
if hovered_chapter then
|
||||
draw_chapter(hovered_chapter.time, diamond_radius_hovered)
|
||||
self.hovered_chapter = hovered_chapter
|
||||
self:determine_chapter_click_handler()
|
||||
end
|
||||
if hovered_chapter then draw_chapter(hovered_chapter.time, diamond_radius_hovered) end
|
||||
end
|
||||
|
||||
-- A-B loop indicators
|
||||
@@ -363,10 +355,10 @@ function Timeline:render()
|
||||
end
|
||||
|
||||
-- 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
|
||||
local cursor_x = self.hovered_chapter and t2x(self.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 cursor_x = hovered_chapter and t2x(hovered_chapter.time) or cursor.x
|
||||
local hovered_seconds = hovered_chapter and hovered_chapter.time or self:get_time_at_x(cursor.x)
|
||||
|
||||
-- Cursor line
|
||||
-- 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 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})
|
||||
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
|
||||
end
|
||||
|
||||
|
@@ -16,7 +16,7 @@ function TopBarButton:init(id, props)
|
||||
self.command = props.command
|
||||
end
|
||||
|
||||
function TopBarButton:on_mbtn_left_down()
|
||||
function TopBarButton:handle_cursor_down()
|
||||
mp.command(type(self.command) == 'function' and self.command() or self.command)
|
||||
end
|
||||
|
||||
@@ -28,6 +28,7 @@ function TopBarButton:render()
|
||||
-- Background on hover
|
||||
if self.proximity_raw == 0 then
|
||||
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
|
||||
|
||||
local width, height = self.bx - self.ax, self.by - self.ay
|
||||
@@ -151,10 +152,6 @@ function TopBar:on_prop_maximized()
|
||||
self:update_dimensions()
|
||||
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:render()
|
||||
@@ -193,6 +190,12 @@ function TopBar:render()
|
||||
}
|
||||
local bx = math.min(max_bx, title_ax + text_width(main_title, opts) + padding * 2)
|
||||
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, {
|
||||
color = bg, opacity = visibility * options.top_bar_title_opacity, radius = 2,
|
||||
})
|
||||
|
@@ -7,10 +7,12 @@ local MuteButton = class(Element)
|
||||
---@param props? ElementProps
|
||||
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:on_mbtn_left_down() mp.commandv('cycle', 'mute') end
|
||||
function MuteButton:render()
|
||||
local visibility = self:get_visibility()
|
||||
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 icon_name = state.mute and 'volume_off' or 'volume_up'
|
||||
local width = self.bx - self.ax
|
||||
@@ -58,17 +60,11 @@ function VolumeSlider:on_coordinates()
|
||||
self.spacing = round(width * 0.2)
|
||||
self.radius = math.max(2, (self.bx - self.ax) / 10)
|
||||
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()
|
||||
if self.pressed then self:set_from_cursor() end
|
||||
end
|
||||
function VolumeSlider:on_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_up() 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()
|
||||
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 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 nudge_y, nudge_size = self.draw_nudge and self.nudge_y or -INFINITY, self.nudge_size
|
||||
local volume_y = self.ay + options.volume_border +
|
||||
|
@@ -93,6 +93,11 @@ function get_point_to_rectangle_proximity(point, rect)
|
||||
return math.sqrt(dx * dx + dy * dy)
|
||||
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.
|
||||
---@param str string
|
||||
---@param res { [string] : boolean } | nil
|
||||
@@ -553,6 +558,8 @@ function render()
|
||||
if not display.initialized then return end
|
||||
state.render_last_time = mp.get_time()
|
||||
|
||||
cursor.reset_handlers()
|
||||
|
||||
-- Actual rendering
|
||||
local ass = assdraw.ass_new()
|
||||
|
||||
@@ -566,6 +573,8 @@ function render()
|
||||
end
|
||||
end
|
||||
|
||||
cursor.decide_keybinds()
|
||||
|
||||
-- submit
|
||||
if osd.res_x == display.width and osd.res_y == display.height and osd.data == ass.text then
|
||||
return
|
||||
|
Reference in New Issue
Block a user