Commit 6d8b790a authored by Becca Hughes's avatar Becca Hughes Committed by Commit Bot

Media Controls: Double tap on either side to jump

Add double tap gesture recognition to MediaControlOverlayPlayButton so
it can detect double tap gestures on the side and jump accordingly. Adds
LayoutTests as a virtual test suite so they are tested with the modern
media controls flag on.

BUG=779989

Change-Id: I6e62f88bc51794b21132ec0532cdbd8c5ccbb677
Reviewed-on: https://chromium-review.googlesource.com/757138
Commit-Queue: Becca Hughes <beccahughes@chromium.org>
Reviewed-by: default avatarJeremy Roman <jbroman@chromium.org>
Reviewed-by: default avatarMounir Lamouri <mlamouri@chromium.org>
Reviewed-by: default avatarTommy Steimel <steimel@chromium.org>
Cr-Commit-Position: refs/heads/master@{#517839}
parent fdb31883
...@@ -1827,3 +1827,7 @@ virtual/mojo-loading/http/tests/ManualTests/ [ WontFix ] ...@@ -1827,3 +1827,7 @@ virtual/mojo-loading/http/tests/ManualTests/ [ WontFix ]
# in testing, whereas otherwise we do not do so if the composited layer has a # in testing, whereas otherwise we do not do so if the composited layer has a
# direct compositing reason (for performance). Only applies to SPv1. # direct compositing reason (for performance). Only applies to SPv1.
paint/invalidation/compositing/subpixel-offset-scaled-transform-composited.html [ WontFix ] paint/invalidation/compositing/subpixel-offset-scaled-transform-composited.html [ WontFix ]
# These tests should always fail because the modern media controls are not yet enabled
crbug.com/761305 media/controls/modern/ [ WontFix ]
crbug.com/761306 virtual/new-remote-playback-pipeline/media/controls/modern/ [ WontFix ]
...@@ -4112,3 +4112,14 @@ crbug.com/785980 [ Win10 ] http/tests/devtools/network/network-xhr-same-url-as-m ...@@ -4112,3 +4112,14 @@ crbug.com/785980 [ Win10 ] http/tests/devtools/network/network-xhr-same-url-as-m
crbug.com/786235 http/tests/misc/resource-timing-sizes-tags.html [ Failure Pass ] crbug.com/786235 http/tests/misc/resource-timing-sizes-tags.html [ Failure Pass ]
crbug.com/786235 virtual/mojo-loading/http/tests/misc/resource-timing-sizes-tags.html [ Failure Pass ] crbug.com/786235 virtual/mojo-loading/http/tests/misc/resource-timing-sizes-tags.html [ Failure Pass ]
crbug.com/786348 [ Win7 ] virtual/mojo-loading/http/tests/devtools/console/console-link-to-snippet.js [ Failure Pass ] crbug.com/786348 [ Win7 ] virtual/mojo-loading/http/tests/devtools/console/console-link-to-snippet.js [ Failure Pass ]
# Double tap on modern media controls is a bit more complicated on Mac but
# since we are not targeting Mac yet we can come back and fix this later.
crbug.com/783154 [ Mac ] virtual/modern-media-controls/media/controls/modern/doubletap-to-jump-backwards.html [ Skip ]
crbug.com/783154 [ Mac ] virtual/modern-media-controls/media/controls/modern/doubletap-to-jump-forwards.html [ Skip ]
crbug.com/783154 [ Mac ] virtual/modern-media-controls/media/controls/modern/doubletap-to-jump-forwards-too-short.html [ Skip ]
crbug.com/783154 [ Mac ] virtual/modern-media-controls/media/controls/modern/doubletap-on-play-button.html [ Skip ]
crbug.com/783154 [ Mac ] virtual/modern-media-controls/media/controls/modern/doubletap-to-toggle-fullscreen.html [ Skip ]
crbug.com/783154 [ Mac ] virtual/modern-media-controls/media/controls/modern/singletap-on-outside.html [ Skip ]
crbug.com/783154 [ Mac ] virtual/modern-media-controls/media/controls/modern/singletap-on-play-button.html [ Skip ]
crbug.com/783154 [ Mac ] virtual/modern-media-controls/media/controls/modern/slow-doubletap.html [ Skip ]
...@@ -606,5 +606,10 @@ ...@@ -606,5 +606,10 @@
"prefix": "incremental-shadow-dom", "prefix": "incremental-shadow-dom",
"base": "shadow-dom", "base": "shadow-dom",
"args": ["--enable-blink-features=IncrementalShadowDOM"] "args": ["--enable-blink-features=IncrementalShadowDOM"]
},
{
"prefix": "modern-media-controls",
"base": "media/controls/modern",
"args": ["--enable-features=UseModernMediaControls"]
} }
] ]
<!DOCTYPE html>
<html>
<title>Test that player will play then pause if double tapped on the play button.</title>
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
<script src="../../media-controls.js"></script>
<video controls width=400 src="../../content/60_sec_video.webm"></video>
<script>
async_test(t => {
const video = document.querySelector('video');
let didPause = false;
video.onplaying = t.step_func(() => {
if (didPause) {
t.done();
} else {
const coordinates =
elementCoordinates(mediaControlsOverlayPlayButtonInternal(video));
doubleTapAtCoordinates(coordinates[0], coordinates[1]);
}
});
video.addEventListener('pause', t.step_func(() => {
didPause = true;
}), { once: true });
video.play();
});
</script>
</html>
<!DOCTYPE html>
<html>
<title>Test that player will jump to the beginning if it's in the first 10 seconds.</title>
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
<script src="../../media-controls.js"></script>
<video controls width=400 src="../../content/60_sec_video.webm"></video>
<script>
async_test(t => {
enableDoubleTapToJumpForTest(t);
const video = document.querySelector('video');
let count = 0;
video.addEventListener('playing', t.step_func(() => {
// Double tap in the top left hand corner
const coordinates =
coordinatesOutsideElement(mediaControlsOverlayPlayButton(video));
doubleTapAtCoordinates(coordinates[0] + 1, coordinates[1] + 1);
}), { once: true });
video.ontimeupdate = t.step_func(() => {
// The time should reach 0 seconds twice, the first time when playing and
// the second because of tapping.
if (Math.round(video.currentTime) == 0) {
count++;
if (count == 2)
t.done();
}
});
video.play();
});
</script>
</html></script>
</html>
<!DOCTYPE html>
<html>
<title>Test that player will jump backwards 10 seconds if double tapped on the left hand side.</title>
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
<script src="../../media-controls.js"></script>
<video controls width=400 src="../../content/60_sec_video.webm"></video>
<script>
async_test(t => {
enableDoubleTapToJumpForTest(t);
const video = document.querySelector('video');
let time = 0;
video.addEventListener('playing', t.step_func(() => {
// Seek the video to the middle
video.currentTime = 30;
}), { once: true });
video.ontimeupdate = t.step_func(() => {
// The time should never reach 25 seconds as we skipped over it
assert_not_equals(Math.round(video.currentTime), 25);
});
video.onseeked = t.step_func(() => {
const currentTime = Math.round(video.currentTime);
if (currentTime == 30) {
// Double tap in the top left hand corner
time = currentTime;
const coordinates =
coordinatesOutsideElement(mediaControlsOverlayPlayButton(video));
doubleTapAtCoordinates(coordinates[0] + 1, coordinates[1] + 1);
} else if (time > 0) {
// Check the video went back 10 seconds
assert_greater_than(time, 0);
assert_equals(currentTime, time - 10);
t.done();
}
});
video.play();
});
</script>
</html>
<!DOCTYPE html>
<html>
<title>Test that player will jump to the end if less than 10 seconds remaining.</title>
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
<script src="../../media-controls.js"></script>
<video controls width=400 src="../../content/60_sec_video.webm"></video>
<script>
async_test(t => {
enableDoubleTapToJumpForTest(t);
const video = document.querySelector('video');
video.addEventListener('playing', () => {
// Seek the video to the end
if (video.currentTime < 55) {
video.currentTime = 55;
// Double tap in the top right hand corner
const coordinates =
coordinatesOutsideElement(mediaControlsOverlayPlayButton(video));
doubleTapAtCoordinates(coordinates[0] + video.width, coordinates[1] + 1);
}
}, { once: true });
video.ontimeupdate = t.step_func(() => {
// The time should never reach 57 seconds as we skipped over it
assert_not_equals(57, Math.round(video.currentTime));
});
video.addEventListener('ended', t.step_func_done(), { once: true });
video.play();
});
</script>
</html></script>
</html>
<!DOCTYPE html>
<html>
<title>Test that player will jump forwards 10 seconds if double tapped.</title>
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
<script src="../../media-controls.js"></script>
<video controls width=400 src="../../content/60_sec_video.webm"></video>
<script>
async_test(t => {
enableDoubleTapToJumpForTest(t);
const video = document.querySelector('video');
let time = 0;
video.addEventListener('playing', t.step_func(() => {
// Double tap in the top right hand corner
time = Math.round(video.currentTime);
const coordinates =
coordinatesOutsideElement(mediaControlsOverlayPlayButton(video));
doubleTapAtCoordinates(coordinates[0] + video.width, coordinates[1] + 1);
}), { once: true });
video.ontimeupdate = t.step_func(() => {
// The time should never be 5 seconds as we skipped over it
assert_not_equals(Math.round(video.currentTime), 5);
});
video.addEventListener('seeked', t.step_func_done(() => {
// Check the video advanced 10 seconds
assert_equals(Math.round(video.currentTime), time + 10);
}), { once: true });
video.play();
});
</script>
</html>
<!DOCTYPE html>
<html>
<title>Test that player will enter fullscreen if double tapped.</title>
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
<script src="../../media-controls.js"></script>
<video controls width=400 src="../../content/60_sec_video.webm"></video>
<script>
async_test(t => {
const video = document.querySelector('video');
video.addEventListener('playing', () => {
// Double tap in the top left hand corner
const coordinates =
coordinatesOutsideElement(mediaControlsOverlayPlayButton(video));
doubleTapAtCoordinates(coordinates[0] + 1, coordinates[1] + 1);
}, { once: true });
video.addEventListener('webkitfullscreenchange', t.step_func(() => {
assert_equals(video, document.fullscreenElement);
// We are now fullscreen, update the event handler and doubletap to exit
video.addEventListener('webkitfullscreenchange',
t.step_func_done(), { once: true });
const coordinates =
coordinatesOutsideElement(mediaControlsOverlayPlayButton(video));
doubleTapAtCoordinates(coordinates[0] + 1, coordinates[1] + 1);
}), { once: true });
video.play();
});
</script>
</html>
<!DOCTYPE html>
<html>
<title>Test that the player pauses if single taped in the outer region.</title>
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
<script src="../../media-controls.js"></script>
<video controls width=400 src="../../content/60_sec_video.webm"></video>
<script>
async_test(t => {
const video = document.querySelector('video');
video.addEventListener('playing', t.step_func(() => {
// Single tap in the top right hand corner
const coordinates =
coordinatesOutsideElement(mediaControlsOverlayPlayButtonInternal(video));
singleTapAtCoordinates(coordinates[0] + 1, coordinates[1] + 1);
}), { once: true });
video.addEventListener('pause', t.step_func_done(), { once: true });
video.play();
});
</script>
</html>
<!DOCTYPE html>
<html>
<title>Test that the player pauses if single tapped on the play button.</title>
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
<script src="../../media-controls.js"></script>
<video controls width=400 src="../../content/60_sec_video.webm"></video>
<script>
async_test(t => {
const video = document.querySelector('video');
video.addEventListener('playing', t.step_func(() => {
// Single tap in the middle of the button.
const coordinates =
elementCoordinates(mediaControlsOverlayPlayButtonInternal(video));
singleTapAtCoordinates(coordinates[0], coordinates[1]);
}), { once: true });
video.addEventListener('pause', t.step_func_done(), { once: true });
video.play();
});
</script>
</html>
<!DOCTYPE html>
<html>
<title>Test that player will not jump if the tap is too slow.</title>
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
<script src="../../media-controls.js"></script>
<video controls width=400 src="../../content/60_sec_video.webm"></video>
<script>
async_test(t => {
const video = document.querySelector('video');
let didPause = false;
video.onplaying = t.step_func(() => {
if (didPause) {
t.done();
} else {
// Double tap in the top right hand corner
const coordinates =
coordinatesOutsideElement(mediaControlsOverlayPlayButton(video));
doubleTapAtCoordinates(coordinates[0] + 1, coordinates[1] + 1, 400);
}
});
video.addEventListener('pause', t.step_func(() => {
didPause = true;
}), { once: true });
video.play();
});
</script>
</html>
...@@ -286,3 +286,51 @@ function checkButtonNotHasClass(button, className) { ...@@ -286,3 +286,51 @@ function checkButtonNotHasClass(button, className) {
function checkControlsClassName(videoElement, className) { function checkControlsClassName(videoElement, className) {
assert_equals(window.internals.shadowRoot(videoElement).firstChild.className, className); assert_equals(window.internals.shadowRoot(videoElement).firstChild.className, className);
} }
function mediaControlsOverlayPlayButton(videoElement) {
return mediaControlsButton(videoElement, 'overlay-play-button');
}
function mediaControlsOverlayPlayButtonInternal(videoElement) {
var controlID = '-internal-media-controls-overlay-play-button-internal';
var element = mediaControlsElement(
window.internals.shadowRoot(
mediaControlsOverlayPlayButton(videoElement)).firstChild, controlID);
if (!element)
throw 'Failed to find the internal overlay play button';
return element;
}
function doubleTapAtCoordinates(x, y, timeout) {
if (timeout == undefined)
timeout = 100;
singleTapAtCoordinates(x, y);
setTimeout(() => {
singleTapAtCoordinates(x, y);
}, timeout);
}
function singleTapAtCoordinates(xPos, yPos) {
chrome.gpuBenchmarking.pointerActionSequence([
{
source: 'touch',
actions: [
{ name: 'pointerDown', x: xPos, y: yPos },
{ name: 'pointerUp' }
]
}
]);
}
function enableDoubleTapToJumpForTest(t) {
var doubleTapToJumpOnVideoEnabledValue =
internals.runtimeFlags.doubleTapToJumpOnVideoEnabled;
internals.runtimeFlags.doubleTapToJumpOnVideoEnabled = true;
t.add_cleanup(() => {
internals.runtimeFlags.doubleTapToJumpOnVideoEnabled =
doubleTapToJumpOnVideoEnabledValue;
});
}
These are tests specific to the modern media controls. As such they should be
run with the modern media controls enabled.
...@@ -6,13 +6,17 @@ ...@@ -6,13 +6,17 @@
#include "core/dom/ElementShadow.h" #include "core/dom/ElementShadow.h"
#include "core/dom/events/Event.h" #include "core/dom/events/Event.h"
#include "core/events/MouseEvent.h"
#include "core/geometry/DOMRect.h"
#include "core/html/media/HTMLMediaElement.h" #include "core/html/media/HTMLMediaElement.h"
#include "core/html/media/HTMLMediaSource.h" #include "core/html/media/HTMLMediaSource.h"
#include "core/input_type_names.h" #include "core/input_type_names.h"
#include "modules/media_controls/MediaControlsImpl.h" #include "modules/media_controls/MediaControlsImpl.h"
#include "modules/media_controls/elements/MediaControlElementsHelper.h" #include "modules/media_controls/elements/MediaControlElementsHelper.h"
#include "platform/runtime_enabled_features.h" #include "platform/runtime_enabled_features.h"
#include "platform/wtf/Time.h"
#include "public/platform/Platform.h" #include "public/platform/Platform.h"
#include "public/platform/TaskType.h"
#include "public/platform/WebSize.h" #include "public/platform/WebSize.h"
namespace { namespace {
...@@ -20,6 +24,24 @@ namespace { ...@@ -20,6 +24,24 @@ namespace {
// The size of the inner circle button in pixels. // The size of the inner circle button in pixels.
constexpr int kInnerButtonSize = 56; constexpr int kInnerButtonSize = 56;
// The touch padding of the inner circle button in pixels.
constexpr int kInnerButtonTouchPaddingSize = 20;
// Check if a point is based within the boundary of a DOMRect with a margin.
bool IsPointInRect(blink::DOMRect& rect, int margin, int x, int y) {
return ((x >= (rect.left() - margin)) && (x <= (rect.right() + margin)) &&
(y >= (rect.top() - margin)) && (y <= (rect.bottom() + margin)));
}
// The delay if a touch is outside the internal button.
constexpr WTF::TimeDelta kOutsideTouchDelay = TimeDelta::FromMilliseconds(300);
// The delay if a touch is inside the internal button.
constexpr WTF::TimeDelta kInsideTouchDelay = TimeDelta::FromMilliseconds(0);
// The number of seconds to jump when double tapping.
constexpr int kNumberOfSecondsToJump = 10;
} // namespace. } // namespace.
namespace blink { namespace blink {
...@@ -34,6 +56,9 @@ namespace blink { ...@@ -34,6 +56,9 @@ namespace blink {
MediaControlOverlayPlayButtonElement::MediaControlOverlayPlayButtonElement( MediaControlOverlayPlayButtonElement::MediaControlOverlayPlayButtonElement(
MediaControlsImpl& media_controls) MediaControlsImpl& media_controls)
: MediaControlInputElement(media_controls, kMediaOverlayPlayButton), : MediaControlInputElement(media_controls, kMediaOverlayPlayButton),
tap_timer_(GetDocument().GetTaskRunner(TaskType::kMediaElementEvent),
this,
&MediaControlOverlayPlayButtonElement::TapTimerFired),
internal_button_(nullptr) { internal_button_(nullptr) {
EnsureUserAgentShadowRoot(); EnsureUserAgentShadowRoot();
setType(InputTypeNames::button); setType(InputTypeNames::button);
...@@ -56,29 +81,99 @@ const char* MediaControlOverlayPlayButtonElement::GetNameForHistograms() const { ...@@ -56,29 +81,99 @@ const char* MediaControlOverlayPlayButtonElement::GetNameForHistograms() const {
return "PlayOverlayButton"; return "PlayOverlayButton";
} }
void MediaControlOverlayPlayButtonElement::MaybePlayPause() {
if (MediaElement().paused()) {
Platform::Current()->RecordAction(
UserMetricsAction("Media.Controls.PlayOverlay"));
} else {
Platform::Current()->RecordAction(
UserMetricsAction("Media.Controls.PauseOverlay"));
}
// Allow play attempts for plain src= media to force a reload in the error
// state. This allows potential recovery for transient network and decoder
// resource issues.
const String& url = MediaElement().currentSrc().GetString();
if (MediaElement().error() && !HTMLMediaElement::IsMediaStreamURL(url) &&
!HTMLMediaSource::Lookup(url)) {
MediaElement().load();
}
MediaElement().TogglePlayState();
MaybeRecordInteracted();
UpdateDisplayType();
}
void MediaControlOverlayPlayButtonElement::MaybeJump(int seconds) {
double new_time = std::max(0.0, MediaElement().currentTime() + seconds);
new_time = std::min(new_time, MediaElement().duration());
MediaElement().setCurrentTime(new_time);
}
void MediaControlOverlayPlayButtonElement::HandlePlayPauseEvent(
Event* event,
WTF::TimeDelta delay) {
event->SetDefaultHandled();
if (tap_timer_.IsActive())
return;
tap_timer_.StartOneShot(delay, BLINK_FROM_HERE);
}
void MediaControlOverlayPlayButtonElement::DefaultEventHandler(Event* event) { void MediaControlOverlayPlayButtonElement::DefaultEventHandler(Event* event) {
if (event->type() == EventTypeNames::click) { if (event->type() == EventTypeNames::click) {
if (MediaElement().paused()) { // Double tap to navigate should only be available on modern controls.
Platform::Current()->RecordAction( if (!MediaControlsImpl::IsModern() || !event->IsMouseEvent()) {
UserMetricsAction("Media.Controls.PlayOverlay")); HandlePlayPauseEvent(event, kInsideTouchDelay);
} else { return;
Platform::Current()->RecordAction(
UserMetricsAction("Media.Controls.PauseOverlay"));
} }
// Allow play attempts for plain src= media to force a reload in the error // If the event doesn't have position data we should just default to
// state. This allows potential recovery for transient network and decoder // play/pause.
// resource issues. // TODO(beccahughes): Move to PointerEvent.
const String& url = MediaElement().currentSrc().GetString(); MouseEvent* mouse_event = ToMouseEvent(event);
if (MediaElement().error() && !HTMLMediaElement::IsMediaStreamURL(url) && if (!mouse_event->HasPosition()) {
!HTMLMediaSource::Lookup(url)) { HandlePlayPauseEvent(event, kInsideTouchDelay);
MediaElement().load(); return;
} }
MediaElement().TogglePlayState(); // If the click happened on the internal button or a margin around it then
UpdateDisplayType(); // we should play/pause.
MaybeRecordInteracted(); if (IsPointInRect(*internal_button_->getBoundingClientRect(),
event->SetDefaultHandled(); kInnerButtonTouchPaddingSize, mouse_event->clientX(),
mouse_event->clientY())) {
HandlePlayPauseEvent(event, kInsideTouchDelay);
} else if (!tap_timer_.IsActive()) {
// If there was not a previous touch and this was outside of the button
// then we should play/pause but with a small unnoticeable delay to allow
// for a secondary tap.
HandlePlayPauseEvent(event, kOutsideTouchDelay);
} else {
// Cancel the play pause event.
tap_timer_.Stop();
if (RuntimeEnabledFeatures::DoubleTapToJumpOnVideoEnabled()) {
// Jump forwards or backwards based on the position of the tap.
WebSize element_size =
MediaControlElementsHelper::GetSizeOrDefault(*this, WebSize(0, 0));
if (mouse_event->clientX() >= element_size.width / 2) {
MaybeJump(kNumberOfSecondsToJump);
} else {
MaybeJump(kNumberOfSecondsToJump * -1);
}
} else {
// Enter or exit fullscreen.
if (MediaElement().IsFullscreen())
GetMediaControls().ExitFullscreen();
else
GetMediaControls().EnterFullscreen();
}
event->SetDefaultHandled();
}
} }
// TODO(mlamouri): should call MediaControlInputElement::DefaultEventHandler. // TODO(mlamouri): should call MediaControlInputElement::DefaultEventHandler.
...@@ -95,6 +190,14 @@ WebSize MediaControlOverlayPlayButtonElement::GetSizeOrDefault() const { ...@@ -95,6 +190,14 @@ WebSize MediaControlOverlayPlayButtonElement::GetSizeOrDefault() const {
*internal_button_, WebSize(kInnerButtonSize, kInnerButtonSize)); *internal_button_, WebSize(kInnerButtonSize, kInnerButtonSize));
} }
void MediaControlOverlayPlayButtonElement::TapTimerFired(TimerBase*) {
std::unique_ptr<UserGestureIndicator> user_gesture_scope =
Frame::NotifyUserActivation(GetDocument().GetFrame(),
UserGestureToken::kNewGesture);
MaybePlayPause();
}
void MediaControlOverlayPlayButtonElement::Trace(blink::Visitor* visitor) { void MediaControlOverlayPlayButtonElement::Trace(blink::Visitor* visitor) {
MediaControlInputElement::Trace(visitor); MediaControlInputElement::Trace(visitor);
visitor->Trace(internal_button_); visitor->Trace(internal_button_);
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define MediaControlOverlayPlayButtonElement_h #define MediaControlOverlayPlayButtonElement_h
#include "modules/media_controls/elements/MediaControlInputElement.h" #include "modules/media_controls/elements/MediaControlInputElement.h"
#include "platform/Timer.h"
namespace blink { namespace blink {
...@@ -29,9 +30,18 @@ class MediaControlOverlayPlayButtonElement final ...@@ -29,9 +30,18 @@ class MediaControlOverlayPlayButtonElement final
const char* GetNameForHistograms() const override; const char* GetNameForHistograms() const override;
private: private:
void TapTimerFired(TimerBase*);
void DefaultEventHandler(Event*) override; void DefaultEventHandler(Event*) override;
bool KeepEventInNode(Event*) override; bool KeepEventInNode(Event*) override;
void MaybePlayPause();
void MaybeJump(int);
void HandlePlayPauseEvent(Event*, WTF::TimeDelta);
TaskRunnerTimer<MediaControlOverlayPlayButtonElement> tap_timer_;
Member<HTMLDivElement> internal_button_; Member<HTMLDivElement> internal_button_;
}; };
......
...@@ -354,6 +354,10 @@ ...@@ -354,6 +354,10 @@
{ {
name: "DocumentWrite", name: "DocumentWrite",
}, },
{
name: "DoubleTapToJumpOnVideo",
settable_from_internals: true
},
{ {
name: "EmbedderCSPEnforcement", name: "EmbedderCSPEnforcement",
status: "stable", status: "stable",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment