diff options
| author | David Vazgenovich Shakaryan <dvshakaryan@gmail.com> | 2026-01-23 17:31:19 -0800 |
|---|---|---|
| committer | David Vazgenovich Shakaryan <dvshakaryan@gmail.com> | 2026-01-23 17:31:19 -0800 |
| commit | 6a2ac69f734b1efbf549857bf603c575f765a766 (patch) | |
| tree | ab53726a76a60658bd10c30fa25099e4005e5583 | |
| parent | a458d33711f83dfd45d0376a1cd66d28d6bed370 (diff) | |
| download | mpv-iptv-menu-6a2ac69f734b1efbf549857bf603c575f765a766.tar.gz mpv-iptv-menu-6a2ac69f734b1efbf549857bf603c575f765a766.tar.xz | |
add targeted mappings to input handler
| -rw-r--r-- | input.lua | 102 | ||||
| -rw-r--r-- | rt.lua | 65 |
2 files changed, 71 insertions, 96 deletions
@@ -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 = { @@ -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') |
