summaryrefslogtreecommitdiff
path: root/main.lua
diff options
context:
space:
mode:
Diffstat (limited to 'main.lua')
-rw-r--r--main.lua127
1 files changed, 60 insertions, 67 deletions
diff --git a/main.lua b/main.lua
index f36e50a..7e5346c 100644
--- a/main.lua
+++ b/main.lua
@@ -16,7 +16,7 @@ local script_name = mp.get_script_name()
local state = _state.new()
local binding_state = {mappings = {}, active = {}}
-local click_state = {}
+local mouse_state = {click = {}}
local osc_visibility
local downloader = _downloader.new({limit = 5})
@@ -995,78 +995,61 @@ local function mouse_has_drifted(x1, y1, x2, y2)
math.abs(y1 - y2) > config.click_max_drift
end
--- mpv normally sends a cancel event when the mouse drifts before a click is
--- released, but only for a first click and not for the second click of what
--- mpv internally considers a double-click. this replicates that drift
--- detection behaviour, allowing for consistency on double-clicks.
-local function handle_mouse_drift(_, mpos)
- local s = click_state
- if not mpos or not s.ct then
- return
- end
-
- if mouse_has_drifted(mpos.x, mpos.y, s.cx, s.cy) then
- click_state = {}
- mp.unobserve_property(handle_mouse_drift)
- end
-end
-
-- when mpv registers a double-click, the second click triggers both
-- double-click and click events. instead of identifying and ignoring this
-- second click event, we can implement double-click detection ourselves for
-- more control and to bypass some mpv inconsistencies.
-local function handle_mouse_click(ev, mpos, id)
- mp.unobserve_property(handle_mouse_drift)
+local function handle_mouse_click(ev, id)
+ local ms = mouse_state
if ev.canceled then
- click_state = {}
+ ms.click = {}
return
end
- local s = click_state
local time = mp.get_time()
+ local clk = ms.click
+ local mpos = ms.pos
if ev.event == 'down' then
- s.ct, s.ck = time, ev.key_name
- s.cx, s.cy, s.ci = mpos.x, mpos.y, id
- mp.observe_property('mouse-pos', 'native', handle_mouse_drift)
+ clk.ct, clk.ck = time, ev.key_name
+ clk.cx, clk.cy, clk.ci = mpos.x, mpos.y, id
return
end
- if ev.event ~= 'up' or not s.ct then
+ if ev.event ~= 'up' or not clk.ct then
return
end
- if time - s.ct > config.click_timeout or
- s.ck ~= ev.key_name or s.ci ~= id or
- mouse_has_drifted(mpos.x, mpos.y, s.cx, s.cy) then
- click_state = {}
+ if time - clk.ct > config.click_timeout or
+ clk.ck ~= ev.key_name or clk.ci ~= id or
+ mouse_has_drifted(mpos.x, mpos.y, clk.cx, clk.cy) then
+ ms.click = {}
return
end
- local dbl = s.pt and s.ct - s.pt <= config.click_dbl_time and
- s.pk == ev.key_name and s.pi == id and
- not mouse_has_drifted(s.cx, s.cy, s.px, s.py)
- click_state = dbl and {} or
+ local dbl = clk.pt and clk.ct - clk.pt <= config.click_dbl_time and
+ clk.pk == ev.key_name and clk.pi == id and
+ not mouse_has_drifted(clk.cx, clk.cy, clk.px, clk.py)
+ ms.click = dbl and {} or
{
- pt = s.ct, pk = ev.key_name,
- px = s.cx, py = s.cy, pi = id,
+ pt = clk.ct, pk = ev.key_name,
+ px = clk.cx, py = clk.cy, pi = id,
}
return ev.key_name, dbl
end
local function process_mouse_click(ev)
- local mpos = mp.get_property_native('mouse-pos')
- if not mpos then
+ if not mouse_state.pos then
return
end
- local line = osd:get_mouse_line(mpos)
+ local line = osd:get_mouse_line(mouse_state.pos)
if line then
line = line - (osd.lines - osd:menu_lines(state))
end
- local key, dbl = handle_mouse_click(ev, mpos, line)
+ local key, dbl = handle_mouse_click(ev, line)
return key, dbl, line
end
@@ -1281,15 +1264,13 @@ mp.set_key_bindings({
{'MBTN_LEFT', toggle_menu},
{'MBTN_LEFT_DBL'},
}, 'menu_button', 'force')
-local mouse_pos_time
-local mouse_over_button_area = false
-local mouse_over_menu_button = false
-local mouse_timer; mouse_timer = mp.add_periodic_timer(0.1, function()
- if mouse_pos_time and
- mp.get_time() - mouse_pos_time >
+local menu_button_timer
+menu_button_timer = mp.add_periodic_timer(0.1, function()
+ if mouse_state.pos and
+ mp.get_time() - mouse_state.pos_time >
config.menu_button_timeout then
osd:show_menu_button(false)
- mouse_timer:kill()
+ menu_button_timer:kill()
end
end, true) -- disabled
mp.observe_property('mouse-pos', 'native', function(_, mpos)
@@ -1297,36 +1278,49 @@ mp.observe_property('mouse-pos', 'native', function(_, mpos)
return
end
+ local ms = mouse_state
+
-- mpv sends (0, 0) on startup if the mouse hasn't moved yet. don't
-- trigger display of the button until the mouse has actually moved.
- if not mouse_pos_time and mpos.x == 0 and mpos.y == 0 then
+ if not ms.pos and mpos.x == 0 and mpos.y == 0 then
return
end
- mouse_pos_time = mp.get_time()
+ ms.pos = mpos
+ ms.pos_time = mp.get_time()
+
+ -- mpv normally sends a cancel event when the mouse drifts before a
+ -- click is released, but only for a first click and not for the second
+ -- click of what mpv internally considers a double-click. this
+ -- replicates that drift detection behaviour, allowing for consistency
+ -- on double-clicks.
+ local clk = ms.click
+ if clk.ct and mouse_has_drifted(mpos.x, mpos.y, clk.cx, clk.cy) then
+ ms.click = {}
+ end
- local is_over = osd:mouse_over_button_area(mpos)
- if is_over ~= mouse_over_button_area then
- mouse_over_button_area = is_over
- osd:show_menu_button(mouse_over_button_area)
- elseif mouse_over_button_area and osd.menu_button.hidden then
+ local over_button_area = osd:mouse_over_button_area(mpos)
+ if not over_button_area ~= not ms.over_button_area then
+ ms.over_button_area = over_button_area
+ osd:show_menu_button(over_button_area)
+ elseif over_button_area and osd.menu_button.hidden then
osd:show_menu_button(true)
end
- local is_over = osd:mouse_over_menu_button(mpos)
- if is_over ~= mouse_over_menu_button then
- mouse_over_menu_button = is_over
- if mouse_over_menu_button then
+ local over_menu_button = osd:mouse_over_menu_button(mpos)
+ if not over_menu_button ~= not ms.over_menu_button then
+ ms.over_menu_button = over_menu_button
+ if over_menu_button then
mp.enable_key_bindings('menu_button')
else
mp.disable_key_bindings('menu_button')
end
end
- if mouse_over_button_area and not mouse_over_menu_button then
- mouse_timer:resume()
+ if over_button_area and not over_menu_button then
+ menu_button_timer:resume()
else
- mouse_timer:kill()
+ menu_button_timer:kill()
end
end)
@@ -1341,15 +1335,14 @@ mp.observe_property('osd-dimensions', 'native', function(_, val)
osd:redraw(state)
-- after a resize, mpv does not update the mouse coordinates until the
- -- mouse is moved. if the mouse was previously over the button and we
- -- do nothing, a click would trigger the button regardless of mouse
- -- position. since we cannot get the new mouse position, we instead
- -- treat all resizes as moving the mouse off the button.
+ -- mouse is moved. if the mouse was previously over a clickable element
+ -- and we do nothing, a click would trigger that element regardless of
+ -- mouse position. since we cannot get the new position, we instead
+ -- wipe mouse state on resize, clearing it until the next move.
osd:show_menu_button(false)
- mouse_over_button_area = false
- mouse_over_menu_button = false
+ mouse_state = {click = {}}
mp.disable_key_bindings('menu_button')
- mouse_timer:kill()
+ menu_button_timer:kill()
end)
mp.register_event('start-file', function()