Scroll to make the video element visible when exiting fullscreen.
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 6 Mar 2015 19:28:26 +0000 (19:28 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 6 Mar 2015 19:28:26 +0000 (19:28 +0000)
https://bugs.webkit.org/show_bug.cgi?id=141439

Patch by Jeremy Jones <jeremyj@apple.com> on 2015-03-06
Reviewed by Simon Fraser.

Source/WebCore:

This patch will scroll the element so it is visible when exiting fullscreen,
but only if the element is completely scrolled off screen.
Also update the element screen rect so exit animation goes to the correct location.

* dom/Element.cpp:
(WebCore::Element::scrollIntoViewIfNotVisible): Added.
* dom/Element.h: Add declaration for scrollIntoViewIfNotVisible.
* platform/ios/WebVideoFullscreenControllerAVKit.mm:
(-[WebVideoFullscreenController fullscreenMayReturnToInline]):
* platform/ios/WebVideoFullscreenInterfaceAVKit.h:
* platform/ios/WebVideoFullscreenInterfaceAVKit.mm:
(-[WebAVPlayerController playerViewController:restoreUserInterfaceForOptimizedFullscreenStopWithCompletionHandler:]):
(-[WebAVPlayerController playerViewControllerWillCancelOptimizedFullscree:]):
(WebVideoFullscreenInterfaceAVKit::setupFullscreen):
(WebVideoFullscreenInterfaceAVKit::setupFullscreenInternal):
(WebVideoFullscreenInterfaceAVKit::exitFullscreen):
(WebVideoFullscreenInterfaceAVKit::exitFullscreenInternal):
(WebVideoFullscreenInterfaceAVKit::preparedToReturnToInline):
(WebVideoFullscreenInterfaceAVKit::fullscreenMayReturnToInline):
* rendering/ScrollBehavior.cpp:
* rendering/ScrollBehavior.h:

Source/WebKit2:

This patch will restore interface state when exiting fullscreen.
Adds preparedToReturnToInline to continue exiting once the interface is updated.

* UIProcess/ios/WebVideoFullscreenManagerProxy.h:
* UIProcess/ios/WebVideoFullscreenManagerProxy.messages.in:
* UIProcess/ios/WebVideoFullscreenManagerProxy.mm:
(WebKit::WebVideoFullscreenManagerProxy::setupFullscreenWithID):
(WebKit::WebVideoFullscreenManagerProxy::fullscreenMayReturnToInline):
(WebKit::WebVideoFullscreenManagerProxy::preparedToReturnToInline): added.
* WebProcess/ios/WebVideoFullscreenManager.h:
* WebProcess/ios/WebVideoFullscreenManager.messages.in:
* WebProcess/ios/WebVideoFullscreenManager.mm:
(WebKit::WebVideoFullscreenManager::fullscreenMayReturnToInline):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@181173 268f45cc-cd09-0410-ab3c-d52691b4dbfc

15 files changed:
Source/WebCore/ChangeLog
Source/WebCore/dom/Element.cpp
Source/WebCore/dom/Element.h
Source/WebCore/platform/ios/WebVideoFullscreenControllerAVKit.mm
Source/WebCore/platform/ios/WebVideoFullscreenInterfaceAVKit.h
Source/WebCore/platform/ios/WebVideoFullscreenInterfaceAVKit.mm
Source/WebCore/rendering/ScrollBehavior.cpp
Source/WebCore/rendering/ScrollBehavior.h
Source/WebKit2/ChangeLog
Source/WebKit2/UIProcess/ios/WebVideoFullscreenManagerProxy.h
Source/WebKit2/UIProcess/ios/WebVideoFullscreenManagerProxy.messages.in
Source/WebKit2/UIProcess/ios/WebVideoFullscreenManagerProxy.mm
Source/WebKit2/WebProcess/ios/WebVideoFullscreenManager.h
Source/WebKit2/WebProcess/ios/WebVideoFullscreenManager.messages.in
Source/WebKit2/WebProcess/ios/WebVideoFullscreenManager.mm

index 77b054c..f7edd6a 100644 (file)
@@ -1,3 +1,32 @@
+2015-03-06  Jeremy Jones  <jeremyj@apple.com>
+
+        Scroll to make the video element visible when exiting fullscreen.
+        https://bugs.webkit.org/show_bug.cgi?id=141439
+
+        Reviewed by Simon Fraser.
+
+        This patch will scroll the element so it is visible when exiting fullscreen,
+        but only if the element is completely scrolled off screen.
+        Also update the element screen rect so exit animation goes to the correct location.
+
+        * dom/Element.cpp:
+        (WebCore::Element::scrollIntoViewIfNotVisible): Added.
+        * dom/Element.h: Add declaration for scrollIntoViewIfNotVisible.
+        * platform/ios/WebVideoFullscreenControllerAVKit.mm:
+        (-[WebVideoFullscreenController fullscreenMayReturnToInline]):
+        * platform/ios/WebVideoFullscreenInterfaceAVKit.h:
+        * platform/ios/WebVideoFullscreenInterfaceAVKit.mm:
+        (-[WebAVPlayerController playerViewController:restoreUserInterfaceForOptimizedFullscreenStopWithCompletionHandler:]):
+        (-[WebAVPlayerController playerViewControllerWillCancelOptimizedFullscree:]):
+        (WebVideoFullscreenInterfaceAVKit::setupFullscreen):
+        (WebVideoFullscreenInterfaceAVKit::setupFullscreenInternal):
+        (WebVideoFullscreenInterfaceAVKit::exitFullscreen):
+        (WebVideoFullscreenInterfaceAVKit::exitFullscreenInternal):
+        (WebVideoFullscreenInterfaceAVKit::preparedToReturnToInline):
+        (WebVideoFullscreenInterfaceAVKit::fullscreenMayReturnToInline):
+        * rendering/ScrollBehavior.cpp:
+        * rendering/ScrollBehavior.h:
+
 2015-03-06  Myles C. Maxfield  <mmaxfield@apple.com>
 
         Crash in -[WebCascadeList objectAtIndex:] + 195
index 22f1891..ddc40e2 100644 (file)
@@ -611,6 +611,20 @@ void Element::scrollIntoViewIfNeeded(bool centerIfNeeded)
         renderer()->scrollRectToVisible(bounds, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);
 }
 
+void Element::scrollIntoViewIfNotVisible(bool centerIfNotVisible)
+{
+    document().updateLayoutIgnorePendingStylesheets();
+    
+    if (!renderer())
+        return;
+    
+    LayoutRect bounds = renderer()->anchorRect();
+    if (centerIfNotVisible)
+        renderer()->scrollRectToVisible(bounds, ScrollAlignment::alignCenterIfNotVisible, ScrollAlignment::alignCenterIfNotVisible);
+    else
+        renderer()->scrollRectToVisible(bounds, ScrollAlignment::alignToEdgeIfNotVisible, ScrollAlignment::alignToEdgeIfNotVisible);
+}
+    
 void Element::scrollByUnits(int units, ScrollGranularity granularity)
 {
     document().updateLayoutIgnorePendingStylesheets();
index 62be968..3579c68 100644 (file)
@@ -122,6 +122,7 @@ public:
 
     void scrollIntoView(bool alignToTop = true);
     void scrollIntoViewIfNeeded(bool centerIfNeeded = true);
+    WEBCORE_EXPORT void scrollIntoViewIfNotVisible(bool centerIfNotVisible = true);
 
     void scrollByLines(int lines);
     void scrollByPages(int pages);
index 151a1c0..a865380 100644 (file)
@@ -183,6 +183,7 @@ public:
 
 - (void)fullscreenMayReturnToInline
 {
+    _interface->preparedToReturnToInline(true, _videoElement->clientRect());
 }
 
 @end
index 3d8241e..c95e90b 100644 (file)
@@ -84,24 +84,25 @@ public:
     WEBCORE_EXPORT virtual void setLegibleMediaSelectionOptions(const Vector<WTF::String>& options, uint64_t selectedIndex) override;
     WEBCORE_EXPORT virtual void setExternalPlayback(bool enabled, ExternalPlaybackTargetType, WTF::String localizedDeviceName) override;
     
-    WEBCORE_EXPORT virtual void setupFullscreen(PlatformLayer&, IntRect initialRect, UIView *, HTMLMediaElement::VideoFullscreenMode, bool allowOptimizedFullscreen);
+    WEBCORE_EXPORT virtual void setupFullscreen(PlatformLayer&, const IntRect& initialRect, UIView *, HTMLMediaElement::VideoFullscreenMode, bool allowOptimizedFullscreen);
     WEBCORE_EXPORT virtual void enterFullscreen();
-    WEBCORE_EXPORT virtual void exitFullscreen(IntRect finalRect);
+    WEBCORE_EXPORT virtual void exitFullscreen(const IntRect& finalRect);
     WEBCORE_EXPORT virtual void cleanupFullscreen();
     WEBCORE_EXPORT virtual void invalidate();
     WEBCORE_EXPORT virtual void requestHideAndExitFullscreen();
+    WEBCORE_EXPORT virtual void preparedToReturnToInline(bool visible, const IntRect& inlineRect);
 
     HTMLMediaElement::VideoFullscreenMode mode() const { return m_mode; }
     void setIsOptimized(bool);
     WEBCORE_EXPORT bool mayAutomaticallyShowVideoOptimized();
-    bool fullscreenMayReturnToInline();
+    void fullscreenMayReturnToInline();
 
 protected:
     void beginSession();
-    void setupFullscreenInternal(PlatformLayer&, IntRect initialRect, UIView *, HTMLMediaElement::VideoFullscreenMode, bool allowOptimizedFullscreen);
+    void setupFullscreenInternal(PlatformLayer&, const IntRect& initialRect, UIView *, HTMLMediaElement::VideoFullscreenMode, bool allowOptimizedFullscreen);
     void enterFullscreenOptimized();
     void enterFullscreenStandard();
-    void exitFullscreenInternal(IntRect finalRect);
+    void exitFullscreenInternal(const IntRect& finalRect);
     void cleanupFullscreenInternal();
 
     RetainPtr<WebAVPlayerController> m_playerController;
index e8c9445..c9fa41e 100644 (file)
@@ -115,6 +115,8 @@ SOFT_LINK_CLASS(UIKit, UIColor)
 @property AVPlayerControllerExternalPlaybackType externalPlaybackType;
 @property (retain) NSString *externalPlaybackAirPlayDeviceLocalizedName;
 
+@property (copy) void (^exitOptimizedCallback)(BOOL restored);
+
 - (BOOL)playerViewController:(AVPlayerViewController *)playerViewController shouldExitFullScreenWithReason:(AVPlayerViewControllerExitFullScreenReason)reason;
 @end
 
@@ -201,13 +203,15 @@ SOFT_LINK_CLASS(UIKit, UIColor)
 - (void)playerViewController:(AVPlayerViewController *)playerViewController restoreUserInterfaceForOptimizedFullscreenStopWithCompletionHandler:(void (^)(BOOL restored))completionHandler
 {
     UNUSED_PARAM(playerViewController);
-    completionHandler(self.fullscreenInterface->fullscreenMayReturnToInline());
+    self.exitOptimizedCallback = completionHandler;
+    self.fullscreenInterface->fullscreenMayReturnToInline();
 }
 
 - (void)playerViewControllerWillCancelOptimizedFullscree:(AVPlayerViewController *)playerViewController
 {
     UNUSED_PARAM(playerViewController);
-    ASSERT(self.delegate);
+    if (!self.delegate)
+        return
     self.delegate->requestExitFullscreen();
 }
 
@@ -844,7 +848,7 @@ void WebVideoFullscreenInterfaceAVKit::setExternalPlayback(bool enabled, Externa
     });
 }
 
-void WebVideoFullscreenInterfaceAVKit::setupFullscreen(PlatformLayer& videoLayer, WebCore::IntRect initialRect, UIView* parentView, HTMLMediaElement::VideoFullscreenMode mode, bool allowOptimizedFullscreen)
+void WebVideoFullscreenInterfaceAVKit::setupFullscreen(PlatformLayer& videoLayer, const WebCore::IntRect& initialRect, UIView* parentView, HTMLMediaElement::VideoFullscreenMode mode, bool allowOptimizedFullscreen)
 {
     RefPtr<WebVideoFullscreenInterfaceAVKit> strongThis(this);
 
@@ -858,7 +862,7 @@ void WebVideoFullscreenInterfaceAVKit::setupFullscreen(PlatformLayer& videoLayer
     });
 }
 
-void WebVideoFullscreenInterfaceAVKit::setupFullscreenInternal(PlatformLayer& videoLayer, WebCore::IntRect initialRect, UIView* parentView, HTMLMediaElement::VideoFullscreenMode mode, bool allowOptimizedFullscreen)
+void WebVideoFullscreenInterfaceAVKit::setupFullscreenInternal(PlatformLayer& videoLayer, const WebCore::IntRect& initialRect, UIView* parentView, HTMLMediaElement::VideoFullscreenMode mode, bool allowOptimizedFullscreen)
 {
     UNUSED_PARAM(videoLayer);
     UNUSED_PARAM(mode);
@@ -992,7 +996,7 @@ void WebVideoFullscreenInterfaceAVKit::enterFullscreenStandard()
     }];
 }
 
-void WebVideoFullscreenInterfaceAVKit::exitFullscreen(WebCore::IntRect finalRect)
+void WebVideoFullscreenInterfaceAVKit::exitFullscreen(const WebCore::IntRect& finalRect)
 {
     RefPtr<WebVideoFullscreenInterfaceAVKit> strongThis(this);
 
@@ -1012,7 +1016,7 @@ void WebVideoFullscreenInterfaceAVKit::exitFullscreen(WebCore::IntRect finalRect
     });
 }
 
-void WebVideoFullscreenInterfaceAVKit::exitFullscreenInternal(WebCore::IntRect finalRect)
+void WebVideoFullscreenInterfaceAVKit::exitFullscreenInternal(const WebCore::IntRect& finalRect)
 {
     [m_playerViewController setShowsPlaybackControls:NO];
     if (m_viewController)
@@ -1143,6 +1147,22 @@ void WebVideoFullscreenInterfaceAVKit::requestHideAndExitFullscreen()
         m_videoFullscreenModel->requestExitFullscreen();
 }
 
+void WebVideoFullscreenInterfaceAVKit::preparedToReturnToInline(bool visible, const IntRect& inlineRect)
+{
+    RefPtr<WebVideoFullscreenInterfaceAVKit> strongThis(this);
+    dispatch_async(dispatch_get_main_queue(), [strongThis, visible, inlineRect] {
+        if (strongThis->m_playerController.get().exitOptimizedCallback) {
+            
+            if (strongThis->m_viewController)
+                [strongThis->m_playerViewController view].frame = [strongThis->m_parentView convertRect:inlineRect toView:nil];
+            else
+                [strongThis->m_playerViewController view].frame = inlineRect;
+            
+            strongThis->m_playerController.get().exitOptimizedCallback(visible);
+        }
+    });
+}
+
 void WebVideoFullscreenInterfaceAVKit::setIsOptimized(bool active)
 {
     if (m_mode & HTMLMediaElement::VideoFullscreenModeStandard) {
@@ -1181,10 +1201,10 @@ bool WebVideoFullscreenInterfaceAVKit::mayAutomaticallyShowVideoOptimized()
     return [m_playerController isPlaying] && m_mode == HTMLMediaElement::VideoFullscreenModeStandard && wkIsOptimizedFullscreenSupported();
 }
 
-bool WebVideoFullscreenInterfaceAVKit::fullscreenMayReturnToInline()
+void WebVideoFullscreenInterfaceAVKit::fullscreenMayReturnToInline()
 {
-    m_fullscreenChangeObserver->fullscreenMayReturnToInline();
-    return true;
+    if (m_fullscreenChangeObserver)
+        m_fullscreenChangeObserver->fullscreenMayReturnToInline();
 }
 
 #endif
index b58b331..fd5df44 100644 (file)
@@ -46,6 +46,8 @@
 
 namespace WebCore {
 
+const ScrollAlignment ScrollAlignment::alignCenterIfNotVisible = { noScroll, alignCenter, noScroll };
+const ScrollAlignment ScrollAlignment::alignToEdgeIfNotVisible = { noScroll, alignToClosestEdge, noScroll };
 const ScrollAlignment ScrollAlignment::alignCenterIfNeeded = { noScroll, alignCenter, alignToClosestEdge };
 WEBCORE_EXPORT const ScrollAlignment ScrollAlignment::alignToEdgeIfNeeded = { noScroll, alignToClosestEdge, alignToClosestEdge };
 WEBCORE_EXPORT const ScrollAlignment ScrollAlignment::alignCenterAlways = { alignCenter, alignCenter, alignCenter };
index 9ce75ab..c9e1f05 100644 (file)
@@ -61,6 +61,8 @@ struct ScrollAlignment {
     static ScrollBehavior getPartialBehavior(const ScrollAlignment& s) { return s.m_rectPartial; }
     static ScrollBehavior getHiddenBehavior(const ScrollAlignment& s) { return s.m_rectHidden; }
 
+    static const ScrollAlignment alignCenterIfNotVisible;
+    static const ScrollAlignment alignToEdgeIfNotVisible;
     static const ScrollAlignment alignCenterIfNeeded;
     WEBCORE_EXPORT static const ScrollAlignment alignToEdgeIfNeeded;
     WEBCORE_EXPORT static const ScrollAlignment alignCenterAlways;
index 05427d9..06bb1f0 100644 (file)
@@ -1,3 +1,24 @@
+2015-03-06  Jeremy Jones  <jeremyj@apple.com>
+
+        Scroll to make the video element visible when exiting fullscreen.
+        https://bugs.webkit.org/show_bug.cgi?id=141439
+
+        Reviewed by Simon Fraser.
+
+        This patch will restore interface state when exiting fullscreen.
+        Adds preparedToReturnToInline to continue exiting once the interface is updated.
+
+        * UIProcess/ios/WebVideoFullscreenManagerProxy.h:
+        * UIProcess/ios/WebVideoFullscreenManagerProxy.messages.in:
+        * UIProcess/ios/WebVideoFullscreenManagerProxy.mm:
+        (WebKit::WebVideoFullscreenManagerProxy::setupFullscreenWithID):
+        (WebKit::WebVideoFullscreenManagerProxy::fullscreenMayReturnToInline):
+        (WebKit::WebVideoFullscreenManagerProxy::preparedToReturnToInline): added.
+        * WebProcess/ios/WebVideoFullscreenManager.h:
+        * WebProcess/ios/WebVideoFullscreenManager.messages.in:
+        * WebProcess/ios/WebVideoFullscreenManager.mm:
+        (WebKit::WebVideoFullscreenManager::fullscreenMayReturnToInline):
+
 2015-03-06  Antti Koivisto  <antti@apple.com>
 
         Rename NetworkCacheStorageCocoa.mm to NetworkCacheStorage.cpp
index a0cafcc..1d011f8 100644 (file)
@@ -55,11 +55,12 @@ private:
     virtual void didReceiveMessage(IPC::Connection&, IPC::MessageDecoder&) override;
 
     // Translate to FullscreenInterface
-    void setupFullscreenWithID(uint32_t, WebCore::IntRect initialRect, float hostingDeviceScaleFactor, WebCore::HTMLMediaElement::VideoFullscreenMode, bool allowOptimizedFullscreen);
+    void setupFullscreenWithID(uint32_t, const WebCore::IntRect& initialRect, float hostingDeviceScaleFactor, WebCore::HTMLMediaElement::VideoFullscreenMode, bool allowOptimizedFullscreen);
     void setSeekableRangesVector(const Vector<std::pair<double, double>>&);
     void setExternalPlaybackProperties(bool enabled, uint32_t targetType, String localizedDeviceName);
     void fullscreenModeChanged(WebCore::HTMLMediaElement::VideoFullscreenMode) override;
-    
+    void preparedToReturnToInline(bool visible, const WebCore::IntRect& inlineRect) override;
+
     // Fullscreen Observer
     virtual void didSetupFullscreen() override;
     virtual void didEnterFullscreen() override;
index b763b03..c728c0b 100644 (file)
@@ -36,5 +36,6 @@ messages -> WebVideoFullscreenManagerProxy {
     EnterFullscreen()
     ExitFullscreen(WebCore::IntRect finalRect)
     CleanupFullscreen()
+    PreparedToReturnToInline(bool visible, WebCore::IntRect inlineRect)
 }
 #endif
index 3cafac1..3677ea1 100644 (file)
@@ -75,7 +75,7 @@ void WebVideoFullscreenManagerProxy::invalidate()
     m_layerHost.clear();
 }
 
-void WebVideoFullscreenManagerProxy::setupFullscreenWithID(uint32_t videoLayerID, WebCore::IntRect initialRect, float hostingDeviceScaleFactor, HTMLMediaElement::VideoFullscreenMode videoFullscreenMode, bool allowOptimizedFullscreen)
+void WebVideoFullscreenManagerProxy::setupFullscreenWithID(uint32_t videoLayerID, const WebCore::IntRect& initialRect, float hostingDeviceScaleFactor, HTMLMediaElement::VideoFullscreenMode videoFullscreenMode, bool allowOptimizedFullscreen)
 {
     ASSERT(videoLayerID);
     m_layerHost = WKMakeRenderLayer(videoLayerID);
@@ -119,7 +119,14 @@ void WebVideoFullscreenManagerProxy::setExternalPlaybackProperties(bool enabled,
     
 void WebVideoFullscreenManagerProxy::fullscreenMayReturnToInline()
 {
+    bool isViewVisible = m_page->isViewVisible();
+    m_page->send(Messages::WebVideoFullscreenManager::FullscreenMayReturnToInline(isViewVisible), m_page->pageID());
+}
+    
+void WebVideoFullscreenManagerProxy::preparedToReturnToInline(bool visible, const WebCore::IntRect& inlineRect)
+{
     m_page->fullscreenMayReturnToInline();
+    WebVideoFullscreenInterfaceAVKit::preparedToReturnToInline(visible, inlineRect);
 }
 
 void WebVideoFullscreenManagerProxy::requestExitFullscreen()
index 4f536a6..334eaec 100644 (file)
@@ -86,6 +86,7 @@ protected:
     virtual void didExitFullscreen();
     virtual void didCleanupFullscreen();
     virtual void setVideoLayerGravityEnum(unsigned);
+    virtual void fullscreenMayReturnToInline(bool isPageVisible);
     void setVideoLayerFrameFenced(WebCore::FloatRect bounds, IPC::Attachment fencePort);
     
     WebPage* m_page;
index a9886fb..d3c68a3 100644 (file)
@@ -42,5 +42,6 @@ messages -> WebVideoFullscreenManager {
     SelectAudioMediaOption(uint64_t index)
     SelectLegibleMediaOption(uint64_t index)
     fullscreenModeChanged(WebCore::HTMLMediaElement::VideoFullscreenMode videoFullscreenMode)
+    FullscreenMayReturnToInline(bool isPageVisible)
 }
 #endif
index 04a4604..9ceeb8b 100644 (file)
@@ -258,6 +258,13 @@ void WebVideoFullscreenManager::setVideoLayerGravityEnum(unsigned gravity)
     setVideoLayerGravity((WebVideoFullscreenModel::VideoGravity)gravity);
 }
     
+void WebVideoFullscreenManager::fullscreenMayReturnToInline(bool isPageVisible)
+{
+    if (!isPageVisible)
+        m_videoElement->scrollIntoViewIfNotVisible(false);
+    m_page->send(Messages::WebVideoFullscreenManagerProxy::PreparedToReturnToInline(true, clientRectForElement(m_videoElement.get())), m_page->pageID());
+}
+    
 void WebVideoFullscreenManager::setVideoLayerFrameFenced(WebCore::FloatRect bounds, IPC::Attachment fencePort)
 {
     if (m_layerHostingContext)