[Bug] Randomly after changing video quality, control bar and mouse cursor no longer auto-hide
nyanpasu64 opened this issue · comments
Describe the bug
After changing the video resolution in Invidious, sometimes the seek bar and mouse cursor no longer auto-hide after inactivity.
Steps to Reproduce
- Load a video.
- Hover the gear to switch video resolutions.
- Move the mouse cursor up and down the list, click a resolution, etc.
Logs
According to #3011, Invidious is running an outdated video.js 7.12.1. I cloned that version locally to help debug.
I've traced the bug to player.js, functions userActive(bool)
and listenForUserActivity_()
. The latter function registers handlers for when the mouse enters and exits the control bar. When the mouse enters controlBar.on('mouseenter'
, the code sets this.player().options_.inactivityTimeout = 0
, and when it exits controlBar.on('mouseleave'
, the code restores the original value using this.player().options_.inactivityTimeout = this.player().cache_.inactivityTimeout
.
- Sidenote: this will cause problems if you try programmatically changing the inactivity timeout while the mouse is over the control bar. I don't know if this is allowed by the API, and if not it's not a bug.
The problem occurs when the mouseenter
event fires multiple times in succession without a mouseleave
event in between, or mouseleave
fails to fire when exiting the control bar. In the first case, this.player().cache_.inactivityTimeout
gets overwritten a second time with this.player().options_.inactivityTimeout
(which is now zero). In the second case, this.player().options_.inactivityTimeout
never gets restored (and when you mouse over the control bar again, the cached value gets overwritten with 0). Either way, the control bar no longer auto-hides after 2 seconds (the vjs-user-active
class is stuck on and vjs-user-inactive
never gets set).
You can test this by pasting the following JS snippet into F12 console, then playing with the quality menu:
gLevel = 0;
player.controlBar.on('mouseenter', () => {
console.log(".".repeat(gLevel) + "{")
gLevel++;
});
player.controlBar.on('mouseleave', () => {
gLevel--;
console.log(".".repeat(gLevel) + "}")
});
mouseleave
does not trigger when moving the mouse from the control bar's bounding box onto the video quality menu, but only when moving the mouse out of the quality menu.- Sometimes when clicking a quality setting,
mouseleave
does not fire. - Sometimes when moving the mouse up and down the control bar and video quality menu,
mouseenter
fires twice in a row.- Whenever this happens, my script prints leading periods before the braces, indicating that
mouseenter
has fired reentrantly.
- Whenever this happens, my script prints leading periods before the braces, indicating that
I do not know if this bug occurs because the browser fires multiple mouseenter
events or fails to fire mouseleave
, or because video.js's Component system is dropping events.
Assuming it's a broken browser behavior that cannot be worked around, to fix this bug, on mouseenter
I would avoid overwriting this.player().cache_.inactivityTimeout
if it's already set (or a separate flag is set), and on mouseleave
I would clear its value (or a separate "is cached" flag).
- Upstream, a related fix was implemented in videojs/video.js#7383 (they check that the current value is nonzero before writing it into cache).
Additional context
- Browser (if applicable): Windows 7 with Waterfox and Supermium, Windows 11 with Firefox (replicated on fresh profile)
Looking at the video.js PR, it seems this was already reported in #1263 (but I did not find it through search), but still not fixed.