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..c78a7e8c11a21753b5c6333df83d0d59a3c93430 |
| --- /dev/null |
| +++ b/third_party/WebKit/Source/core/html/MediaCustomControlsFullscreenDetector.cpp |
| @@ -0,0 +1,147 @@ |
| +// 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); |
| + |
| + // Video is not loaded yet. |
| + if (videoElement().getReadyState() < HTMLMediaElement::kHaveMetadata) |
| + return; |
| + |
| + if (!isVideoOrParentFullscreen()) { |
| + m_checkViewportIntersectionTimer.stop(); |
| + |
| + if (videoElement().webMediaPlayer()) { |
| + videoElement().webMediaPlayer()->setIsEffectivelyFullscreen(false); |
| + } |
|
mlamouri (slow - plz ping)
2017/02/27 18:04:55
style: remove { }
Zhiqiang Zhang (Slow)
2017/02/28 12:16:52
Done.
|
| + 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); |
| + } |
|
mlamouri (slow - plz ping)
2017/02/27 18:04:55
style: remove { }
Zhiqiang Zhang (Slow)
2017/02/28 12:16:52
Done.
|
| +} |
| + |
| +bool MediaCustomControlsFullscreenDetector::isVideoOrParentFullscreen() { |
| + Element* fullscreenElement = |
| + Fullscreen::currentFullScreenElementFrom(videoElement().document()); |
| + if (!fullscreenElement) |
| + return false; |
| + |
| + return fullscreenElement->contains(&videoElement()); |
| +} |
| + |
| +DEFINE_TRACE(MediaCustomControlsFullscreenDetector) { |
| + EventListener::trace(visitor); |
| + visitor->trace(m_videoElement); |
| +} |
| + |
| +} // namespace blink |