Chromium Code Reviews| Index: third_party/WebKit/Source/core/html/MediaCustomControlsFullscreenDetector.cpp |
| diff --git a/third_party/WebKit/Source/core/html/MediaCustomControlsFullscreenDetector.cpp b/third_party/WebKit/Source/core/html/MediaCustomControlsFullscreenDetector.cpp |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..86ab35a2cf2f65a10a406c2f9c3b24bd2cb4791c |
| --- /dev/null |
| +++ b/third_party/WebKit/Source/core/html/MediaCustomControlsFullscreenDetector.cpp |
| @@ -0,0 +1,155 @@ |
| +// Copyright 2017 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "core/html/MediaCustomControlsFullscreenDetector.h" |
| + |
| +#include "core/dom/Fullscreen.h" |
| +#include "core/dom/TaskRunnerHelper.h" |
| +#include "core/events/Event.h" |
| +#include "core/html/HTMLVideoElement.h" |
| +#include "core/layout/IntersectionGeometry.h" |
| + |
| +namespace blink { |
| + |
| +namespace { |
| + |
| +constexpr double kCheckFullscreenIntervalSeconds = 1.0f; |
| +constexpr float kMostlyFillViewportThresholdOfOccupationProportion = 0.85f; |
| +constexpr float kMostlyFillViewportThresholdOfVisibleProportion = 0.75f; |
| + |
| +} // anonymous namespace |
| + |
| +MediaCustomControlsFullscreenDetector::MediaCustomControlsFullscreenDetector( |
| + HTMLVideoElement& video) |
| + : EventListener(CPPEventListenerType), |
| + m_videoElement(video), |
| + m_checkViewportIntersectionTimer( |
| + TaskRunnerHelper::get(TaskType::Unthrottled, &video.document()), |
| + this, |
| + &MediaCustomControlsFullscreenDetector:: |
| + onCheckViewportIntersectionTimerFired) { |
| + videoElement().document().addEventListener( |
| + EventTypeNames::webkitfullscreenchange, this, true); |
| + videoElement().document().addEventListener(EventTypeNames::fullscreenchange, |
| + this, true); |
| + |
| + videoElement().addEventListener(EventTypeNames::loadedmetadata, this, true); |
| +} |
| + |
| +bool MediaCustomControlsFullscreenDetector::operator==( |
| + const EventListener& other) const { |
| + return this == &other; |
| +} |
| + |
| +void MediaCustomControlsFullscreenDetector::didMoveToNewDocument( |
| + Document& oldDocument) { |
| + oldDocument.removeEventListener(EventTypeNames::webkitfullscreenchange, this, |
| + true); |
| + oldDocument.removeEventListener(EventTypeNames::fullscreenchange, this, true); |
| + |
| + videoElement().document().addEventListener( |
| + EventTypeNames::webkitfullscreenchange, this, true); |
| + videoElement().document().addEventListener(EventTypeNames::fullscreenchange, |
| + this, true); |
| +} |
| + |
| +bool MediaCustomControlsFullscreenDetector::computeIsDominantVideo( |
| + const IntRect& targetRect, |
| + const IntRect& rootRect, |
| + const IntRect& intersectionRect) { |
| + if (targetRect.isEmpty() || rootRect.isEmpty()) |
| + return false; |
| + |
| + const float xOccupationProportion = |
| + 1.0f * intersectionRect.width() / rootRect.width(); |
| + const float yOccupationProportion = |
| + 1.0f * intersectionRect.height() / rootRect.height(); |
| + |
| + // If the viewport is mostly occupied by the video, return true. |
| + if (std::min(xOccupationProportion, yOccupationProportion) >= |
| + kMostlyFillViewportThresholdOfOccupationProportion) { |
| + return true; |
| + } |
| + |
| + // If neither of the dimensions of the viewport is mostly occupied by the |
| + // video, return false. |
| + if (std::max(xOccupationProportion, yOccupationProportion) < |
| + kMostlyFillViewportThresholdOfOccupationProportion) { |
| + return false; |
| + } |
| + |
| + // If the video is mostly visible in the indominant dimension, return true. |
| + // Otherwise return false. |
| + if (xOccupationProportion > yOccupationProportion) { |
| + return targetRect.height() * |
| + kMostlyFillViewportThresholdOfVisibleProportion < |
| + intersectionRect.height(); |
| + } |
| + return targetRect.width() * kMostlyFillViewportThresholdOfVisibleProportion < |
| + intersectionRect.width(); |
| +} |
| + |
| +void MediaCustomControlsFullscreenDetector::handleEvent( |
| + ExecutionContext* context, |
| + Event* event) { |
| + DCHECK(event->type() == EventTypeNames::fullscreenchange || |
| + event->type() == EventTypeNames::webkitfullscreenchange || |
| + event->type() == EventTypeNames::loadedmetadata); |
|
xjz
2017/02/25 00:49:12
Do you also want to listen to the resize event of
Zhiqiang Zhang (Slow)
2017/02/25 18:48:27
Not for now. We are counting on the page to resize
|
| + |
| + // Video is not loaded yet. |
| + if (videoElement().getReadyState() < HTMLMediaElement::kHaveMetadata) |
| + return; |
| + |
| + if (!isVideoOrParentFullscreen()) { |
| + m_checkViewportIntersectionTimer.stop(); |
| + |
| + if (videoElement().webMediaPlayer()) { |
| + videoElement().webMediaPlayer()->setIsEffectivelyFullscreen(false); |
| + } |
| + return; |
| + } |
| + |
| + m_checkViewportIntersectionTimer.startOneShot(kCheckFullscreenIntervalSeconds, |
| + BLINK_FROM_HERE); |
| +} |
| + |
| +void MediaCustomControlsFullscreenDetector:: |
| + onCheckViewportIntersectionTimerFired(TimerBase*) { |
| + DCHECK(isVideoOrParentFullscreen()); |
| + IntersectionGeometry geometry(nullptr, videoElement(), Vector<Length>(), |
| + true); |
| + geometry.computeGeometry(); |
| + |
| + bool isDominant = |
| + computeIsDominantVideo(geometry.targetIntRect(), geometry.rootIntRect(), |
| + geometry.intersectionIntRect()); |
| + |
| + if (videoElement().webMediaPlayer()) { |
| + videoElement().webMediaPlayer()->setIsEffectivelyFullscreen(isDominant); |
| + } |
| +} |
| + |
| +bool MediaCustomControlsFullscreenDetector::isVideoOrParentFullscreen() { |
| + Element* fullscreenElement = |
| + Fullscreen::currentFullScreenElementFrom(videoElement().document()); |
| + if (!fullscreenElement) |
| + return false; |
| + |
| + Element* currentElement = &videoElement(); |
|
miu
2017/02/24 22:44:39
IIRC, there's some kind of isAncestorOf() utility
Zhiqiang Zhang (Slow)
2017/02/25 18:48:27
Yes, Node.contains(). Done :)
|
| + while (currentElement) { |
| + if (fullscreenElement == currentElement) |
| + return true; |
| + |
| + currentElement = currentElement->parentElement(); |
| + } |
| + |
| + return false; |
| +} |
| + |
| +DEFINE_TRACE(MediaCustomControlsFullscreenDetector) { |
| + EventListener::trace(visitor); |
| + visitor->trace(m_videoElement); |
| +} |
| + |
| +} // namespace blink |