2c5c158cbfd2542a6090cdda3e86db93be30123d
[WebKit-https.git] / Source / WebCore / platform / cocoa / WebVideoFullscreenModelVideoElement.mm
1 /*
2  * Copyright (C) 2014 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
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.
12  *
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.
24  */
25
26 #import "config.h"
27
28 #if PLATFORM(IOS) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
29 #import "WebVideoFullscreenModelVideoElement.h"
30
31 #import "DOMEventInternal.h"
32 #import "Logging.h"
33 #import "MediaControlsHost.h"
34 #import "WebPlaybackSessionModelMediaElement.h"
35 #import "WebVideoFullscreenInterface.h"
36 #import <QuartzCore/CoreAnimation.h>
37 #import <WebCore/DOMEventListener.h>
38 #import <WebCore/Event.h>
39 #import <WebCore/EventListener.h>
40 #import <WebCore/EventNames.h>
41 #import <WebCore/HTMLElement.h>
42 #import <WebCore/HTMLVideoElement.h>
43 #import <WebCore/Page.h>
44 #import <WebCore/PageGroup.h>
45 #import <WebCore/SoftLinking.h>
46 #import <WebCore/TextTrackList.h>
47 #import <WebCore/TimeRanges.h>
48 #import <wtf/NeverDestroyed.h>
49 #import <wtf/RetainPtr.h>
50
51
52 using namespace WebCore;
53
54 WebVideoFullscreenModelVideoElement::WebVideoFullscreenModelVideoElement(WebPlaybackSessionModelMediaElement& playbackSessionModel)
55     : EventListener(EventListener::CPPEventListenerType)
56     , m_playbackSessionModel(playbackSessionModel)
57 {
58 }
59
60 WebVideoFullscreenModelVideoElement::~WebVideoFullscreenModelVideoElement()
61 {
62 }
63
64 void WebVideoFullscreenModelVideoElement::setWebVideoFullscreenInterface(WebVideoFullscreenInterface* interface)
65 {
66     if (interface == m_videoFullscreenInterface)
67         return;
68
69     m_videoFullscreenInterface = interface;
70     m_playbackSessionModel->setWebPlaybackSessionInterface(interface);
71
72     if (m_videoFullscreenInterface && m_videoElement)
73         m_videoFullscreenInterface->setVideoDimensions(true, m_videoElement->videoWidth(), m_videoElement->videoHeight());
74 }
75
76 void WebVideoFullscreenModelVideoElement::setVideoElement(HTMLVideoElement* videoElement)
77 {
78     if (m_videoElement == videoElement)
79         return;
80
81     if (m_videoElement && m_videoElement->videoFullscreenLayer())
82         m_videoElement->setVideoFullscreenLayer(nullptr);
83
84     if (m_videoElement && m_isListening) {
85         for (auto& eventName : observedEventNames())
86             m_videoElement->removeEventListener(eventName, this, false);
87     }
88     m_isListening = false;
89
90     m_videoElement = videoElement;
91     m_playbackSessionModel->setMediaElement(videoElement);
92
93     if (!m_videoElement)
94         return;
95
96     for (auto& eventName : observedEventNames())
97         m_videoElement->addEventListener(eventName, this, false);
98     m_isListening = true;
99
100     updateForEventName(eventNameAll());
101
102     if (m_videoFullscreenInterface)
103         m_videoFullscreenInterface->setVideoDimensions(true, videoElement->videoWidth(), videoElement->videoHeight());
104 }
105
106 void WebVideoFullscreenModelVideoElement::handleEvent(WebCore::ScriptExecutionContext*, WebCore::Event* event)
107 {
108     updateForEventName(event->type());
109 }
110
111 void WebVideoFullscreenModelVideoElement::updateForEventName(const WTF::AtomicString& eventName)
112 {
113     if (!m_videoElement || !m_videoFullscreenInterface)
114         return;
115     
116     bool all = eventName == eventNameAll();
117
118     if (all
119         || eventName == eventNames().resizeEvent)
120         m_videoFullscreenInterface->setVideoDimensions(true, m_videoElement->videoWidth(), m_videoElement->videoHeight());
121 }
122
123 void WebVideoFullscreenModelVideoElement::setVideoFullscreenLayer(PlatformLayer* videoLayer)
124 {
125     if (m_videoFullscreenLayer == videoLayer)
126         return;
127     
128     m_videoFullscreenLayer = videoLayer;
129 #if PLATFORM(MAC)
130     [m_videoFullscreenLayer setAnchorPoint:CGPointMake(0, 0)];
131 #else
132     [m_videoFullscreenLayer setAnchorPoint:CGPointMake(0.5, 0.5)];
133 #endif
134     [m_videoFullscreenLayer setBounds:m_videoFrame];
135     
136     if (m_videoElement)
137         m_videoElement->setVideoFullscreenLayer(m_videoFullscreenLayer.get());
138 }
139
140 void WebVideoFullscreenModelVideoElement::requestFullscreenMode(HTMLMediaElementEnums::VideoFullscreenMode mode)
141 {
142     if (m_videoElement && m_videoElement->fullscreenMode() != mode)
143         m_videoElement->setFullscreenMode(mode);
144 }
145
146 void WebVideoFullscreenModelVideoElement::setVideoLayerFrame(FloatRect rect)
147 {
148     m_videoFrame = rect;
149     [m_videoFullscreenLayer setBounds:CGRect(rect)];
150     if (m_videoElement)
151         m_videoElement->setVideoFullscreenFrame(rect);
152 }
153
154 void WebVideoFullscreenModelVideoElement::setVideoLayerGravity(WebVideoFullscreenModel::VideoGravity gravity)
155 {
156     MediaPlayer::VideoGravity videoGravity = MediaPlayer::VideoGravityResizeAspect;
157     if (gravity == WebVideoFullscreenModel::VideoGravityResize)
158         videoGravity = MediaPlayer::VideoGravityResize;
159     else if (gravity == WebVideoFullscreenModel::VideoGravityResizeAspect)
160         videoGravity = MediaPlayer::VideoGravityResizeAspect;
161     else if (gravity == WebVideoFullscreenModel::VideoGravityResizeAspectFill)
162         videoGravity = MediaPlayer::VideoGravityResizeAspectFill;
163     else
164         ASSERT_NOT_REACHED();
165     
166     m_videoElement->setVideoFullscreenGravity(videoGravity);
167 }
168
169 const Vector<AtomicString>& WebVideoFullscreenModelVideoElement::observedEventNames()
170 {
171     static NeverDestroyed<Vector<AtomicString>> sEventNames;
172
173     if (!sEventNames.get().size())
174         sEventNames.get().append(eventNames().resizeEvent);
175     return sEventNames.get();
176 }
177
178 const AtomicString& WebVideoFullscreenModelVideoElement::eventNameAll()
179 {
180     static NeverDestroyed<AtomicString> sEventNameAll = "allEvents";
181     return sEventNameAll;
182 }
183
184 void WebVideoFullscreenModelVideoElement::fullscreenModeChanged(HTMLMediaElementEnums::VideoFullscreenMode videoFullscreenMode)
185 {
186     if (m_videoElement)
187         m_videoElement->fullscreenModeChanged(videoFullscreenMode);
188 }
189
190 bool WebVideoFullscreenModelVideoElement::isVisible() const
191 {
192     if (!m_videoElement)
193         return false;
194
195     if (Page* page = m_videoElement->document().page())
196         return page->isVisible();
197
198     return false;
199 }
200
201 #endif