From e7cb4ba670173d092aec72bd80d885774bde0096 Mon Sep 17 00:00:00 2001 From: Dmitry Lyzo Date: Tue, 23 May 2023 00:39:52 +0300 Subject: [PATCH 1/4] Don't show OSD for Fullscreen and Mute (cherry picked from commit 51bd2bef1a9c3e248167e337b87c592c4d091d9a) --- src/controllers/playback/video/index.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/controllers/playback/video/index.js b/src/controllers/playback/video/index.js index 4fd441975..5669fa24f 100644 --- a/src/controllers/playback/video/index.js +++ b/src/controllers/playback/video/index.js @@ -1230,12 +1230,10 @@ export default function (view) { case 'f': if (!e.ctrlKey && !e.metaKey) { playbackManager.toggleFullscreen(currentPlayer); - showOsd(); } break; case 'm': playbackManager.toggleMute(currentPlayer); - showOsd(); break; case 'p': case 'P': From 0381af80f1858643488d67d4ad1697cff182ee78 Mon Sep 17 00:00:00 2001 From: Dmitry Lyzo Date: Tue, 23 May 2023 00:40:37 +0300 Subject: [PATCH 2/4] Focus on corresponding button (cherry picked from commit 884ce171ea6056f7da0e856692ce87afcebd3bf7) --- src/controllers/playback/video/index.js | 33 ++++++++++++++++--------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/src/controllers/playback/video/index.js b/src/controllers/playback/video/index.js index 5669fa24f..d51148d3d 100644 --- a/src/controllers/playback/video/index.js +++ b/src/controllers/playback/video/index.js @@ -1,4 +1,5 @@ import escapeHtml from 'escape-html'; +import debounce from 'lodash-es/debounce'; import { playbackManager } from '../../../components/playback/playbackmanager'; import browser from '../../../scripts/browser'; import dom from '../../../scripts/dom'; @@ -258,9 +259,9 @@ export default function (view) { let mouseIsDown = false; - function showOsd() { + function showOsd(focusElement) { slideDownToShow(headerElement); - showMainOsdControls(); + showMainOsdControls(focusElement); resetIdle(); } @@ -313,7 +314,9 @@ export default function (view) { }); } - function showMainOsdControls() { + const _focus = debounce((focusElement) => focusManager.focus(focusElement), 50); + + function showMainOsdControls(focusElement) { if (!currentVisibleMenu) { const elem = osdBottomElement; currentVisibleMenu = 'osd'; @@ -321,12 +324,14 @@ export default function (view) { elem.classList.remove('hide'); elem.classList.remove('videoOsdBottom-hidden'); + focusElement ||= elem.querySelector('.btnPause'); + if (!layoutManager.mobile) { - setTimeout(function () { - focusManager.focus(elem.querySelector('.btnPause')); - }, 50); + _focus(focusElement); } toggleSubtitleSync(); + } else if (currentVisibleMenu === 'osd' && focusElement && !layoutManager.mobile) { + _focus(focusElement); } } @@ -1174,15 +1179,19 @@ export default function (view) { const key = keyboardnavigation.getKeyName(e); const isKeyModified = e.ctrlKey || e.altKey || e.metaKey; + const btnPlayPause = osdBottomElement.querySelector('.btnPause'); + if (e.keyCode === 32) { if (e.target.tagName !== 'BUTTON' || !layoutManager.tv) { playbackManager.playPause(currentPlayer); + showOsd(btnPlayPause); e.preventDefault(); e.stopPropagation(); // Trick Firefox with a null element to skip next click clickedElement = null; + } else { + showOsd(); } - showOsd(); return; } @@ -1205,7 +1214,7 @@ export default function (view) { break; case 'k': playbackManager.playPause(currentPlayer); - showOsd(); + showOsd(btnPlayPause); break; case 'ArrowUp': case 'Up': @@ -1219,13 +1228,13 @@ export default function (view) { case 'ArrowRight': case 'Right': playbackManager.fastForward(currentPlayer); - showOsd(); + showOsd(btnFastForward); break; case 'j': case 'ArrowLeft': case 'Left': playbackManager.rewind(currentPlayer); - showOsd(); + showOsd(btnRewind); break; case 'f': if (!e.ctrlKey && !e.metaKey) { @@ -1253,7 +1262,7 @@ export default function (view) { // Ignores gamepad events that are always triggered, even when not focused. if (document.hasFocus()) { /* eslint-disable-line compat/compat */ playbackManager.rewind(currentPlayer); - showOsd(); + showOsd(btnRewind); } break; case 'NavigationRight': @@ -1262,7 +1271,7 @@ export default function (view) { // Ignores gamepad events that are always triggered, even when not focused. if (document.hasFocus()) { /* eslint-disable-line compat/compat */ playbackManager.fastForward(currentPlayer); - showOsd(); + showOsd(btnFastForward); } break; case 'Home': From 8c8e24079243c69bfc7a707a3672a5690f1e1599 Mon Sep 17 00:00:00 2001 From: Dmitry Lyzo Date: Tue, 23 May 2023 00:41:35 +0300 Subject: [PATCH 3/4] Change behavior of arrow keys and Enter when OSD is hidden (cherry picked from commit 76c55116ce7a1edd41ea57f6d170ce7a6e19cb82) --- src/controllers/playback/video/index.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/controllers/playback/video/index.js b/src/controllers/playback/video/index.js index d51148d3d..2cb099856 100644 --- a/src/controllers/playback/video/index.js +++ b/src/controllers/playback/video/index.js @@ -1195,6 +1195,21 @@ export default function (view) { return; } + if (layoutManager.tv && !currentVisibleMenu) { + // Change the behavior of some keys when the OSD is hidden + switch (key) { + case 'ArrowLeft': + case 'ArrowRight': + showOsd(nowPlayingPositionSlider); + nowPlayingPositionSlider.dispatchEvent(new KeyboardEvent(e.type, e)); + return; + case 'Enter': + playbackManager.playPause(currentPlayer); + showOsd(btnPlayPause); + return; + } + } + if (layoutManager.tv && keyboardnavigation.isNavigationKey(key)) { showOsd(); return; From ab5c4949c3b4af3d1104524827ff68ad5ff9c7fc Mon Sep 17 00:00:00 2001 From: Dmitry Lyzo Date: Mon, 17 Jul 2023 21:47:31 +0300 Subject: [PATCH 4/4] Add KeyboardEvent constructor polyfill (cherry picked from commit 11ae2ff43ffe2fdd563bc39dac24f0cfb5f7c3d3) --- src/index.jsx | 1 + src/legacy/keyboardEvent.js | 48 +++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 src/legacy/keyboardEvent.js diff --git a/src/index.jsx b/src/index.jsx index 16f610931..cf0e6cafb 100644 --- a/src/index.jsx +++ b/src/index.jsx @@ -32,6 +32,7 @@ import './components/playback/playerSelectionMenu'; import './legacy/domParserTextHtml'; import './legacy/focusPreventScroll'; import './legacy/htmlMediaElement'; +import './legacy/keyboardEvent'; import './legacy/vendorStyles'; import { currentSettings } from './scripts/settings/userSettings'; import taskButton from './scripts/taskbutton'; diff --git a/src/legacy/keyboardEvent.js b/src/legacy/keyboardEvent.js new file mode 100644 index 000000000..8b40e617d --- /dev/null +++ b/src/legacy/keyboardEvent.js @@ -0,0 +1,48 @@ +/** + * Polyfill for KeyboardEvent + * - Constructor. + */ + +(function (window) { + 'use strict'; + + try { + new window.KeyboardEvent('event', { bubbles: true, cancelable: true }); + } catch (e) { + // We can't use `KeyboardEvent` in old WebKit because `initKeyboardEvent` + // doesn't seem to populate some properties (`keyCode`, `which`) that + // are read-only. + const KeyboardEventOriginal = window.Event; + + const KeyboardEvent = function (eventName, options) { + options = options || {}; + + const event = document.createEvent('Event'); + + event.initEvent(eventName, !!options.bubbles, !!options.cancelable); + + event.view = options.view || document.defaultView; + + event.key = options.key || options.keyIdentifier || ''; + event.keyCode = options.keyCode || 0; + event.code = options.code || ''; + event.charCode = options.charCode || 0; + event.char = options.char || ''; + event.which = options.which || 0; + + event.location = options.location || options.keyLocation || 0; + + event.ctrlKey = !!options.ctrlKey; + event.altKey = !!options.altKey; + event.shiftKey = !!options.shiftKey; + event.metaKey = !!options.metaKey; + + event.repeat = !!options.repeat; + + return event; + }; + + KeyboardEvent.prototype = KeyboardEventOriginal.prototype; + window.KeyboardEvent = KeyboardEvent; + } +}(window));