summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Vazgenovich Shakaryan <dvshakaryan@gmail.com>2026-01-23 17:31:19 -0800
committerDavid Vazgenovich Shakaryan <dvshakaryan@gmail.com>2026-01-23 17:31:19 -0800
commit6a2ac69f734b1efbf549857bf603c575f765a766 (patch)
treeab53726a76a60658bd10c30fa25099e4005e5583
parenta458d33711f83dfd45d0376a1cd66d28d6bed370 (diff)
downloadmpv-iptv-menu-6a2ac69f734b1efbf549857bf603c575f765a766.tar.gz
mpv-iptv-menu-6a2ac69f734b1efbf549857bf603c575f765a766.tar.xz
add targeted mappings to input handler
-rw-r--r--input.lua102
-rw-r--r--rt.lua65
2 files changed, 71 insertions, 96 deletions
diff --git a/input.lua b/input.lua
index 7d4ea57..62fe9b1 100644
--- a/input.lua
+++ b/input.lua
@@ -9,7 +9,7 @@ local mappings = {}
local active_mapping = {}
local mapping_bound = false
-local click_state = {}
+local clk = {}
local state
local osd
@@ -28,9 +28,9 @@ end
-- 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, id)
+local function handle_mbtn(ev, id)
if ev.canceled then
- click_state = {}
+ clk = {}
return
end
@@ -40,7 +40,6 @@ local function handle_mouse_click(ev, id)
end
local time = mp.get_time()
- local clk = click_state
if ev.event == 'down' then
clk.ct, clk.ck = time, ev.key_name
@@ -55,55 +54,19 @@ local function handle_mouse_click(ev, id)
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
- click_state = {}
+ clk = {}
return
end
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)
- click_state = dbl and {} or
+ clk = dbl and {} or
{
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 ms = osd.mstate
- if not ms then
- return
- end
-
- local area
- local val
- if ms.target == 'scrollbar' then
- area = 'scrollbar'
- val = ms.ratio
- elseif ms.target == 'menu' then
- area = 'menu'
- val = ms.option_line
- end
-
- local key, dbl = handle_mouse_click(ev, ms.hitbox)
- return key, dbl, area, val
-end
-
-local function mouse_click(ev)
- local key, dbl, area, val = process_mouse_click(ev)
- if not key then
- return
- end
-
- local f
- if key == 'MBTN_LEFT' then
- f = rt.mouse_click_left
- elseif key == 'MBTN_RIGHT' then
- f = rt.mouse_click_right
- end
-
- f(dbl, area, val)
+ return dbl and ev.key_name .. '_DBL' or ev.key_name
end
-- mpv does not process key-binding changes requested by script functions until
@@ -120,20 +83,38 @@ end
-- leaving our keys bound to a common function and building our own logic to
-- route keys per the current state.
local function handle_key(ev)
- local t = active_mapping[ev.key_name]
- if not t and ev.key_text then
- t = active_mapping['ANY_UNICODE']
+ local k = ev.key_name
+ local mbtn = k:find('MBTN_')
+ if mbtn then
+ -- ignore double-click events from mpv as we have our own
+ -- detection logic
+ if k:find('_DBL') then
+ return
+ end
+
+ k = handle_mbtn(ev)
+ if not k then
+ return
+ end
end
+ local target_mapping = osd.mstate.target and
+ active_mapping._targets and
+ active_mapping._targets[osd.mstate.target]
+ local t = target_mapping and
+ (target_mapping[k] or
+ ev.key_text and target_mapping['ANY_UNICODE']) or
+ (active_mapping[k] or
+ ev.key_text and active_mapping['ANY_UNICODE'])
+
-- ev.is_mouse is false for some mouse events
- local k = ev.key_name
- if k:find('MOUSE_') or k:find('MBTN_') or k:find('WHEEL_') then
+ if mbtn or k:find('MOUSE_') or k:find('WHEEL_') then
if not osd.mactive then
osd:set_mactive(true)
end
elseif osd.mactive then
osd:set_mactive(false)
- click_state = {}
+ clk = {}
end
local f = t and t[1]
@@ -143,7 +124,7 @@ local function handle_key(ev)
if t[2] == 'complex' then
f(ev)
- elseif ev.event == 'down' or
+ elseif mbtn or ev.event == 'down' or
(ev.event == 'repeat' and t[2] == 'repeat') then
f()
end
@@ -187,7 +168,7 @@ local function bind_click(f)
mp.command_native({'enable-section', 'click-nodrag'})
mp.add_forced_key_binding(
'MBTN_LEFT', 'click', function(ev)
- if process_mouse_click(ev) then
+ if handle_mbtn(ev) then
f()
end
end, {complex = true})
@@ -226,9 +207,8 @@ function input.update_mpos(mpos)
-- click of what mpv internally considers a double-click. this
-- replicates that drift detection behaviour, allowing for consistency
-- on double-clicks.
- local clk = click_state
if clk.ct and mouse_has_drifted(mpos.x, mpos.y, clk.cx, clk.cy) then
- click_state = {}
+ clk = {}
end
if not ms.over_btn_area ~= not ps.over_btn_area then
@@ -262,7 +242,7 @@ end
function input.on_resize()
osd:show_menu_btn(false)
osd:set_mpos(nil)
- click_state = {}
+ clk = {}
unbind_click()
btn_timer:kill()
end
@@ -280,9 +260,6 @@ mappings.MENU = {
['?'] = {rt.open_option_info},
['Ctrl+p'] = {rt.goto_playing},
- ['MBTN_LEFT'] = {mouse_click, 'complex'},
- ['MBTN_RIGHT'] = {mouse_click, 'complex'},
-
['k'] = {rt.cursor_up, 'repeat'},
['j'] = {rt.cursor_down, 'repeat'},
['K'] = {rt.cursor_page_up, 'repeat'},
@@ -316,6 +293,17 @@ mappings.MENU = {
['Alt+WHEEL_DOWN'] = {rt.move_option_wheel_down, 'repeat'},
['Shift+Alt+WHEEL_UP'] = {rt.move_option_wheel_page_up, 'repeat'},
['Shift+Alt+WHEEL_DOWN'] = {rt.move_option_wheel_page_down, 'repeat'},
+
+ _targets = {
+ scrollbar = {
+ ['MBTN_LEFT_DBL'] = {rt.dbl_click_scrollbar},
+ },
+ menu = {
+ ['MBTN_LEFT'] = {rt.click_menu},
+ ['MBTN_LEFT_DBL'] = {rt.dbl_click_menu},
+ ['MBTN_RIGHT_DBL'] = {rt.dbl_right_click_menu},
+ },
+ },
}
mappings.SEARCH = {
diff --git a/rt.lua b/rt.lua
index 785a5c7..e937dbc 100644
--- a/rt.lua
+++ b/rt.lua
@@ -951,17 +951,29 @@ function rt.toggle_menu_sort()
osd:dirty()
end
-local function mouse_click_left_menu(dbl, line)
+function rt.click_menu()
+ local line = osd.mstate.option_line
+ if line < 1 then
+ return
+ end
+
+ local menu = state:menu()
+ local pos = menu.view_top + line - 1
+ if pos > #menu.options then
+ return
+ end
+
+ rt.set_cursor(pos)
+end
+
+function rt.dbl_click_menu()
+ local line = osd.mstate.option_line
if line == 0 then
return
end
-- title
if line < 0 then
- if not dbl then
- return
- end
-
if line == -1 then
rt.set_cursor(1)
else
@@ -973,34 +985,23 @@ local function mouse_click_left_menu(dbl, line)
local menu = state:menu()
local pos = menu.view_top + line - 1
- if dbl then
- if pos ~= menu.cursor then
- return
- end
-
- rt.select_option()
- else
- if pos > #menu.options then
- return
- end
-
- rt.set_cursor(pos)
- end
-end
-
-local function mouse_click_left_scrollbar(dbl, ratio)
- if not dbl then
+ if pos ~= menu.cursor then
return
end
+ rt.select_option()
+end
+
+function rt.dbl_click_scrollbar()
-- set_cursor handles out-of-bounds moves (when ratio == 1)
rt.set_cursor(
- math.floor(ratio * #state:menu().options) + 1,
+ math.floor(osd.mstate.ratio * #state:menu().options) + 1,
{centre = true})
end
-local function mouse_click_right_menu(dbl, line)
- if not dbl or line < 1 then
+function rt.dbl_right_click_menu()
+ local line = osd.mstate.option_line
+ if line < 1 then
return
end
@@ -1013,20 +1014,6 @@ local function mouse_click_right_menu(dbl, line)
rt.open_option_info(menu.options[pos])
end
-function rt.mouse_click_left(dbl, area, val)
- if area == 'menu' then
- return mouse_click_left_menu(dbl, val)
- elseif area == 'scrollbar' then
- return mouse_click_left_scrollbar(dbl, val)
- end
-end
-
-function rt.mouse_click_right(dbl, area, val)
- if area == 'menu' then
- return mouse_click_right_menu(dbl, val)
- end
-end
-
function rt.reload_data()
if state.depth > 1 then
osd:flash_error('Can only reload data from root menu')