Skip to content

fix: cursor/controls linger after seek when 'hide controls when paused' is enabled (#3634)#3635

Open
stakeswky wants to merge 4 commits intocode-charity:masterfrom
stakeswky:fix/hide-controls-cursor-delay-after-seek
Open

fix: cursor/controls linger after seek when 'hide controls when paused' is enabled (#3634)#3635
stakeswky wants to merge 4 commits intocode-charity:masterfrom
stakeswky:fix/hide-controls-cursor-delay-after-seek

Conversation

@stakeswky
Copy link

Problem

Fixes #3634

When the "Hide controls when paused" setting is enabled, after the user interacts with the progress bar (e.g. seeks to a new position), the mouse cursor and control bar take a long time to disappear — or never disappear until the mouse is moved away.

Root cause

In playerControls(), the onmousestop callback checks .ytp-progress-bar:hover before hiding controls. After a seek click, the progress bar remains in a :hover state, so onmousestop keeps rescheduling itself in a 1-second loop indefinitely — the controls never hide.

Fix

Attach a mouseup listener on the player element. When the user releases the mouse button after a seek, it schedules a clean 1-second hide timer that bypasses the hover guard. The listener is properly cleaned up when the feature is disabled or the video resumes playing.

// After a seek/click interaction, force-hide controls once the
// mouse button is released — regardless of progress-bar hover state.
player._it_mouseup_handler = function () {
    scheduleHide(); // clears existing timer, hides after 1s
};
player.addEventListener('mouseup', player._it_mouseup_handler);

Testing

  1. Enable Settings → Player → Hide controls when paused
  2. Pause a video
  3. Click the progress bar to seek
  4. Keep the mouse still over the progress bar
  5. ✅ Controls and cursor now disappear after ~1 second
  6. Previously: controls would stay visible indefinitely

…y#3634)

When 'hide controls when paused' is enabled, after the user interacts
with the progress bar (e.g. seeks), the onmousestop loop kept
rescheduling itself indefinitely while .ytp-progress-bar:hover was
true — so the cursor/controls never hid until the mouse moved away.

Fix: attach a 'mouseup' listener on the player element that schedules
a clean 1-second hide timer (bypassing the hover guard) once the user
releases the mouse button after a seek interaction. The listener is
cleaned up when the feature is disabled or the video is no longer paused.
@anuragc0des
Copy link

I tested this PR locally on Brave (Windows 11) with “Hide controls when paused” enabled.

After seeking with the progress bar and releasing the mouse button (without moving the cursor), the controls still remain visible.

It seems the mouseup event might not always fire on the player element during progress bar interactions.

Possibly the listener needs to be attached higher or directly to the progress bar element?

YouTube's progress bar stops mouseup event propagation, so the handler
on the player element never fires when seeking via the progress bar.

Move the listener to document with a guard that only triggers when the
mouseup target is inside the player or progress bar.
@stakeswky
Copy link
Author

Thanks for testing! You're right — YouTube's progress bar likely calls stopPropagation() on mouseup, so the event never reaches the player element.

I've pushed a fix: the mouseup listener now attaches to document instead of the player, with a guard to only trigger when the target is inside the player or progress bar. This should catch the seek-and-release case on all browsers.

scheduleHide() defers by 1s and onmousestop re-checks .ytp-progress-bar:hover,
which keeps controls visible when the cursor rests on the scrubber after seeking.
Instead, clear the timer and call hideControls() directly on mouseup so controls
disappear immediately when the user releases the mouse after a seek.
@stakeswky
Copy link
Author

Thanks for testing on Brave! Good diagnosis — the root cause was that scheduleHide() defers by 1s, and onmousestop keeps re-checking .ytp-progress-bar:hover, so when the cursor rests on the scrubber after a seek the controls never actually hide.

Fixed in the latest push: on mouseup we now call clearTimeout(thread) + player.hideControls() directly, bypassing the hover check entirely. Controls should disappear immediately when you release the mouse after seeking, regardless of where the cursor lands.

@stakeswky
Copy link
Author

Good catch! The root issue was that even though mouseup fired on document, calling hideControls() immediately was undone by the subsequent onmousemove event — which re-showed controls and then onmousestop kept rescheduling because .ytp-progress-bar:hover was still true.

The fix: instead of calling hideControls() directly on mouseup, I now set a seekingDone flag and call scheduleHide() (1 s delay). The onmousestop loop now checks seekingDone — if set, it skips the progress-bar hover check and hides unconditionally, then resets the flag. This way the controls disappear after 1 s regardless of whether the cursor is still resting on the scrubber.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

🐞Bug using the setting to hide the control bar when paused; after using the bar, the mouse takes a while to disappear

2 participants