osc: reevaluate mouse state after leaving never

currently mouse processing only happens on mouse movement which
causes cases where going from never -> auto does not show the
osc even though the cursor might be in proximity.

move mouse processing code to a function and refresh it when
leaving visibility never to avoid such issues.

Fixes: https://github.com/mpv-player/mpv/pull/17954#discussion_r3286015305
This commit is contained in:
NRK authored and Kacper Michajłow committed 2026-06-04 00:18:55 +02:00
1 parent 048c5ec351
commit 6d5c8591eb
1 file changed
+44 -25
+44 -25
View File
@@ -321,6 +321,7 @@ local state = {
screen_sizeX = nil, screen_sizeY = nil, -- last screen-resolution, to detect resolution changes to issue reINITs
initREQ = false, -- is a re-init request pending?
marginsREQ = false, -- is a margins update pending?
mouse_stateREQ = false, -- is a mouse state update pending?
last_mouseX = nil, last_mouseY = nil, -- last mouse position, to detect significant mouse movement
last_touchX = -1, last_touchY = -1, -- last touch position
mouse_in_window = false,
@@ -2805,6 +2806,41 @@ local function element_has_action(element, action)
element.eventresponder[action]
end
local function process_mouse_move(refresh)
if refresh then
state.mouse_in_window = recently_touched() or mp.get_property_bool("mouse-pos/hover")
if not state.mouse_in_window then
state.last_mouseX, state.last_mouseY = nil, nil
return
end
end
local mouseX, mouseY = get_virt_mouse_pos()
if refresh or user_opts.minmousemove == 0 or
((state.last_mouseX ~= nil and state.last_mouseY ~= nil) and
((math.abs(mouseX - state.last_mouseX) >= user_opts.minmousemove)
or (math.abs(mouseY - state.last_mouseY) >= user_opts.minmousemove)
)
) then
if window_controls_enabled() and user_opts.windowcontrols_independent then
if mouse_in_area("showhide_wc") then
show_wc()
elseif user_opts.visibility ~= "always" then
hide_wc()
end
if mouse_in_area("showhide") then
show_osc()
elseif user_opts.visibility ~= "always" then
hide_osc()
end
else
show_osc()
if window_controls_enabled() then show_wc() end
end
end
state.last_mouseX, state.last_mouseY = mouseX, mouseY
end
local function process_event(source, what)
local action = string.format("%s%s", source,
what and ("_" .. what) or "")
@@ -2855,31 +2891,7 @@ local function process_event(source, what)
elseif source == "mouse_move" then
state.mouse_in_window = true
local mouseX, mouseY = get_virt_mouse_pos()
if user_opts.minmousemove == 0 or
((state.last_mouseX ~= nil and state.last_mouseY ~= nil) and
((math.abs(mouseX - state.last_mouseX) >= user_opts.minmousemove)
or (math.abs(mouseY - state.last_mouseY) >= user_opts.minmousemove)
)
) then
if window_controls_enabled() and user_opts.windowcontrols_independent then
if mouse_in_area("showhide_wc") then
show_wc()
elseif user_opts.visibility ~= "always" then
hide_wc()
end
if mouse_in_area("showhide") then
show_osc()
elseif user_opts.visibility ~= "always" then
hide_osc()
end
else
show_osc()
if window_controls_enabled() then show_wc() end
end
end
state.last_mouseX, state.last_mouseY = mouseX, mouseY
process_mouse_move()
local n = state.active_element
if element_has_action(elements[n], action) then
@@ -2951,6 +2963,11 @@ local function render()
end
end
if state.mouse_stateREQ then
process_mouse_move(true)
state.mouse_stateREQ = false
end
-- fade animation
local function run_fade(anitype_key, anistart_key, animation_key, set_visible)
@@ -3310,6 +3327,7 @@ end
-- mode can be auto/always/never/cycle
-- the modes only affect internal variables and not stored on its own.
local function visibility_mode(mode, no_osd)
local old_vis = mp.get_property_native("user-data/osc/visibility") or user_opts.visibility
if mode == "cycle" then
for i, allowed_mode in ipairs(state.visibility_modes) do
if i == #state.visibility_modes then
@@ -3349,6 +3367,7 @@ local function visibility_mode(mode, no_osd)
mp.disable_key_bindings("window-controls")
state.input_enabled = false
state.mouse_stateREQ = old_vis == "never" and mode ~= "never"
update_margins()
request_tick()
end