2 * Copyright (C) 2014 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #if PLATFORM(IOS) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
29 #import "VideoFullscreenModelVideoElement.h"
34 #import "MediaControlsHost.h"
35 #import "PlaybackSessionModelMediaElement.h"
36 #import <QuartzCore/CoreAnimation.h>
37 #import <WebCore/Event.h>
38 #import <WebCore/EventListener.h>
39 #import <WebCore/EventNames.h>
40 #import <WebCore/HTMLElement.h>
41 #import <WebCore/HTMLVideoElement.h>
42 #import <WebCore/Page.h>
43 #import <WebCore/TextTrackList.h>
44 #import <WebCore/TimeRanges.h>
45 #import <wtf/NeverDestroyed.h>
46 #import <wtf/SoftLinking.h>
48 using namespace WebCore;
50 VideoFullscreenModelVideoElement::VideoFullscreenModelVideoElement()
51 : EventListener(EventListener::CPPEventListenerType)
53 LOG(Fullscreen, "VideoFullscreenModelVideoElement %p ctor", this);
56 VideoFullscreenModelVideoElement::~VideoFullscreenModelVideoElement()
58 LOG(Fullscreen, "VideoFullscreenModelVideoElement %p dtor", this);
61 void VideoFullscreenModelVideoElement::setVideoElement(HTMLVideoElement* videoElement)
63 if (m_videoElement == videoElement)
66 LOG(Fullscreen, "VideoFullscreenModelVideoElement %p setVideoElement(%p)", this, videoElement);
68 if (m_videoElement && m_videoElement->videoFullscreenLayer())
69 m_videoElement->setVideoFullscreenLayer(nullptr);
71 if (m_videoElement && m_isListening) {
72 for (auto& eventName : observedEventNames())
73 m_videoElement->removeEventListener(eventName, *this, false);
75 m_isListening = false;
77 m_videoElement = videoElement;
80 for (auto& eventName : observedEventNames())
81 m_videoElement->addEventListener(eventName, *this, false);
85 updateForEventName(eventNameAll());
88 void VideoFullscreenModelVideoElement::handleEvent(WebCore::ScriptExecutionContext&, WebCore::Event& event)
90 updateForEventName(event.type());
93 void VideoFullscreenModelVideoElement::updateForEventName(const WTF::AtomicString& eventName)
95 if (m_clients.isEmpty())
98 bool all = eventName == eventNameAll();
101 || eventName == eventNames().resizeEvent) {
102 setHasVideo(m_videoElement);
103 setVideoDimensions(m_videoElement ? FloatSize(m_videoElement->videoWidth(), m_videoElement->videoHeight()) : FloatSize());
107 void VideoFullscreenModelVideoElement::willExitFullscreen()
110 m_videoElement->willExitFullscreen();
113 void VideoFullscreenModelVideoElement::setVideoFullscreenLayer(PlatformLayer* videoLayer, WTF::Function<void()>&& completionHandler)
115 if (m_videoFullscreenLayer == videoLayer) {
120 m_videoFullscreenLayer = videoLayer;
122 [m_videoFullscreenLayer setAnchorPoint:CGPointMake(0, 0)];
124 [m_videoFullscreenLayer setAnchorPoint:CGPointMake(0.5, 0.5)];
126 [m_videoFullscreenLayer setBounds:m_videoFrame];
128 if (!m_videoElement) {
133 m_videoElement->setVideoFullscreenLayer(m_videoFullscreenLayer.get(), WTFMove(completionHandler));
136 void VideoFullscreenModelVideoElement::waitForPreparedForInlineThen(WTF::Function<void()>&& completionHandler)
138 if (!m_videoElement) {
143 m_videoElement->waitForPreparedForInlineThen(WTFMove(completionHandler));
146 void VideoFullscreenModelVideoElement::requestFullscreenMode(HTMLMediaElementEnums::VideoFullscreenMode mode, bool finishedWithMedia)
148 if (m_videoElement && m_videoElement->fullscreenMode() != mode)
149 m_videoElement->setFullscreenMode(mode);
151 if (m_videoElement && finishedWithMedia && mode == MediaPlayerEnums::VideoFullscreenModeNone) {
152 if (m_videoElement->document().isMediaDocument()) {
153 if (DOMWindow* window = m_videoElement->document().domWindow()) {
154 if (History* history = window->history())
161 void VideoFullscreenModelVideoElement::setVideoLayerFrame(FloatRect rect)
164 [m_videoFullscreenLayer setBounds:CGRect(rect)];
166 m_videoElement->setVideoFullscreenFrame(rect);
169 void VideoFullscreenModelVideoElement::setVideoLayerGravity(VideoFullscreenModel::VideoGravity gravity)
171 MediaPlayer::VideoGravity videoGravity = MediaPlayer::VideoGravityResizeAspect;
172 if (gravity == VideoFullscreenModel::VideoGravityResize)
173 videoGravity = MediaPlayer::VideoGravityResize;
174 else if (gravity == VideoFullscreenModel::VideoGravityResizeAspect)
175 videoGravity = MediaPlayer::VideoGravityResizeAspect;
176 else if (gravity == VideoFullscreenModel::VideoGravityResizeAspectFill)
177 videoGravity = MediaPlayer::VideoGravityResizeAspectFill;
179 ASSERT_NOT_REACHED();
181 m_videoElement->setVideoFullscreenGravity(videoGravity);
184 const Vector<AtomicString>& VideoFullscreenModelVideoElement::observedEventNames()
186 static const auto names = makeNeverDestroyed(Vector<AtomicString> { eventNames().resizeEvent });
190 const AtomicString& VideoFullscreenModelVideoElement::eventNameAll()
192 static NeverDestroyed<AtomicString> sEventNameAll = "allEvents";
193 return sEventNameAll;
196 void VideoFullscreenModelVideoElement::fullscreenModeChanged(HTMLMediaElementEnums::VideoFullscreenMode videoFullscreenMode)
199 m_videoElement->fullscreenModeChanged(videoFullscreenMode);
202 void VideoFullscreenModelVideoElement::addClient(VideoFullscreenModelClient& client)
204 ASSERT(!m_clients.contains(&client));
205 m_clients.add(&client);
208 void VideoFullscreenModelVideoElement::removeClient(VideoFullscreenModelClient& client)
210 ASSERT(m_clients.contains(&client));
211 m_clients.remove(&client);
214 bool VideoFullscreenModelVideoElement::isVisible() const
219 if (Page* page = m_videoElement->document().page())
220 return page->isVisible();
225 void VideoFullscreenModelVideoElement::setHasVideo(bool hasVideo)
227 if (hasVideo == m_hasVideo)
230 m_hasVideo = hasVideo;
232 for (auto& client : m_clients)
233 client->hasVideoChanged(m_hasVideo);
236 void VideoFullscreenModelVideoElement::setVideoDimensions(const FloatSize& videoDimensions)
238 if (m_videoDimensions == videoDimensions)
241 m_videoDimensions = videoDimensions;
243 for (auto& client : m_clients)
244 client->videoDimensionsChanged(m_videoDimensions);
247 void VideoFullscreenModelVideoElement::willEnterPictureInPicture()
249 for (auto& client : m_clients)
250 client->willEnterPictureInPicture();
253 void VideoFullscreenModelVideoElement::didEnterPictureInPicture()
255 for (auto& client : m_clients)
256 client->didEnterPictureInPicture();
259 void VideoFullscreenModelVideoElement::failedToEnterPictureInPicture()
261 for (auto& client : m_clients)
262 client->failedToEnterPictureInPicture();
265 void VideoFullscreenModelVideoElement::willExitPictureInPicture()
267 for (auto& client : m_clients)
268 client->willExitPictureInPicture();
271 void VideoFullscreenModelVideoElement::didExitPictureInPicture()
273 for (auto& client : m_clients)
274 client->didExitPictureInPicture();