M input.conf => input.conf +2 -2
@@ 78,5 78,5 @@ MBTN_LEFT {image} script-binding gesture
MBTN_LEFT_DBL {image} ignore
MBTN_MID {image} script-binding align-to-cursor
MBTN_RIGHT {image} script-binding drag-to-pan
-WHEEL_UP {image} no-osd add video-zoom .1
-WHEEL_DOWN {image} no-osd add video-zoom -.1
+WHEEL_UP {image} script-message cursor-centric-zoom .1
+WHEEL_DOWN {image} script-message cursor-centric-zoom -.1
M scripts/image-keybindings.lua => scripts/image-keybindings.lua +27 -0
@@ 90,6 90,33 @@ mp.add_key_binding(nil, 'drag-to-pan', function (table)
end)
end, { complex = true })
+mp.register_script_message('cursor-centric-zoom', function (amount)
+ local mouse_pos = mp.get_property_native('mouse-pos')
+ local dims = mp.get_property_native('osd-dimensions')
+ local width = (dims.w - dims.ml - dims.mr) * 2^amount
+ local height = (dims.h - dims.mt - dims.mb) * 2^amount
+ local command = 'no-osd add video-zoom ' .. amount .. ';'
+
+ if width > dims.w then
+ local old_cursor_ml = dims.ml - mouse_pos.x
+ local cursor_ml = old_cursor_ml * 2^amount
+ local ml = cursor_ml + mouse_pos.x
+ -- from video/out/aspect.c:src_dst_split_scaling() we know that:
+ -- ml = (osd-width - width) * (video-align-x + 1) / 2
+ -- so video-align-x is:
+ local video_align_x = 2 * ml / (dims.w - width) - 1
+ command = command .. 'no-osd set video-align-x ' .. math.min(1, math.max(video_align_x, -1)) .. ';'
+ end
+
+ if height > dims.h then
+ local mt = (dims.mt - mouse_pos.y) * 2^amount + mouse_pos.y
+ local video_align_y = 2 * mt / (dims.h - height) - 1
+ command = command .. 'no-osd set video-align-y ' .. math.min(1, math.max(video_align_y, -1))
+ end
+
+ mp.command(command)
+end)
+
local is_intial_callback
local function undo_lavfi_complex()
if is_intial_callback then