2009-10-05 Pierre d'Herbemont <pdherbemont@webkit.org>
authorsimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 6 Oct 2009 00:24:47 +0000 (00:24 +0000)
committersimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 6 Oct 2009 00:24:47 +0000 (00:24 +0000)
        Reviewed by Simon Fraser

        Support fullscreen in MediaPlayer (Mac)
        https://bugs.webkit.org/show_bug.cgi?id=26742

        Add a fullscreen button to the <video> controller if the media engine,
        and the theme have support for fullscreen, and can show appropriate controls.
        Clicking the button calls through the ChromeClient to the WebVideoFullscreenController
        in WebKit to do a nice animation to fullscreen, with a custom controller.

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

38 files changed:
WebCore/ChangeLog
WebCore/DerivedSources.make
WebCore/WebCore.Video.exp [new file with mode: 0644]
WebCore/WebCore.base.exp
WebCore/WebCore.xcodeproj/project.pbxproj
WebCore/html/HTMLMediaElement.cpp
WebCore/html/HTMLMediaElement.h
WebCore/html/HTMLVideoElement.cpp
WebCore/html/HTMLVideoElement.h
WebCore/page/ChromeClient.h
WebCore/platform/graphics/MediaPlayer.cpp
WebCore/platform/graphics/MediaPlayer.h
WebCore/platform/graphics/MediaPlayerPrivate.h
WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h
WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm
WebCore/rendering/MediaControlElements.cpp
WebCore/rendering/RenderThemeMac.h
WebCore/rendering/RenderThemeMac.mm
WebKit/ChangeLog
WebKit/WebKit.xcodeproj/project.pbxproj
WebKit/mac/ChangeLog
WebKit/mac/WebCoreSupport/WebChromeClient.h
WebKit/mac/WebCoreSupport/WebChromeClient.mm
WebKit/mac/WebView/WebVideoFullscreenController.h [new file with mode: 0644]
WebKit/mac/WebView/WebVideoFullscreenController.mm [new file with mode: 0644]
WebKit/mac/WebView/WebVideoFullscreenHUDWindowController.h [new file with mode: 0644]
WebKit/mac/WebView/WebVideoFullscreenHUDWindowController.mm [new file with mode: 0644]
WebKit/mac/WebView/WebView.mm
WebKit/mac/WebView/WebViewData.h
WebKit/mac/WebView/WebViewData.mm
WebKit/mac/WebView/WebViewInternal.h
WebKit/mac/WebView/WebWindowAnimation.h [new file with mode: 0644]
WebKit/mac/WebView/WebWindowAnimation.m [new file with mode: 0644]
WebKitLibraries/ChangeLog
WebKitLibraries/WebKitSystemInterface.h
WebKitLibraries/libWebKitSystemInterfaceLeopard.a
WebKitLibraries/libWebKitSystemInterfaceSnowLeopard.a
WebKitLibraries/libWebKitSystemInterfaceTiger.a

index 3d6afeb5a43661da487e6cf71fd5840f235e53b5..643e1b997e46de58ebdfa7193c805bef305bdbd3 100644 (file)
@@ -1,3 +1,65 @@
+2009-10-05  Pierre d'Herbemont  <pdherbemont@webkit.org>
+
+        Reviewed by Simon Fraser
+        
+        Support fullscreen in MediaPlayer (Mac)
+        https://bugs.webkit.org/show_bug.cgi?id=26742
+
+        Add a fullscreen button to the <video> controller if the media engine,
+        and the theme have support for fullscreen, and can show appropriate controls.
+        Clicking the button calls through the ChromeClient to the WebVideoFullscreenController
+        in WebKit to do a nice animation to fullscreen, with a custom controller.
+
+        * DerivedSources.make:
+        * WebCore.Video.exp: Added.
+        New export file for when VIDEO is enabled.
+        
+        * WebCore.base.exp: Export WebCore::HTMLNames::videoTag
+        * WebCore.xcodeproj/project.pbxproj: New files
+        
+        * html/HTMLMediaElement.h:
+        * html/HTMLMediaElement.cpp:
+        (WebCore::HTMLMediaElement::HTMLMediaElement):
+        (WebCore::HTMLMediaElement::willRemove):
+        (WebCore::HTMLMediaElement::screenRect):
+        (WebCore::HTMLMediaElement::enterFullscreen):
+        (WebCore::HTMLMediaElement::exitFullscreen):
+        (WebCore::HTMLMediaElement::platformMedia):
+        Add fullscreen logic. platformMedia returns a pointer to platform-specific playback data
+        used for fullscreen.
+        
+        * html/HTMLVideoElement.h:
+        * html/HTMLVideoElement.cpp:
+        (WebCore::HTMLVideoElement::supportsFullscreen): Check with both the player and the ChromeClient
+        to see if it's possile to enter fullscreen for this element.
+        
+        * page/ChromeClient.h:
+        (WebCore::ChromeClient::supportsFullscreenForNode):
+        (WebCore::ChromeClient::enterFullscreenForNode):
+        (WebCore::ChromeClient::exitFullscreenForNode):
+        New methods
+        
+        * platform/graphics/MediaPlayer.h:
+        * platform/graphics/MediaPlayer.cpp:
+        (WebCore::NullMediaPlayerPrivate::platformMedia):
+        (WebCore::MediaPlayer::platformMedia):
+        * platform/graphics/MediaPlayerPrivate.h:
+        (WebCore::MediaPlayerPrivateInterface::platformMedia):
+        * platform/graphics/mac/MediaPlayerPrivateQTKit.h:
+        * platform/graphics/mac/MediaPlayerPrivateQTKit.mm:
+        (WebCore::MediaPlayerPrivate::platformMedia):
+        (WebCore::MediaPlayerPrivate::supportsFullscreen):
+        New methods to return platform-specific playback data for fullscreen.
+        
+        * rendering/MediaControlElements.cpp:
+        (WebCore::MediaControlFullscreenButtonElement::defaultEventHandler):
+        Hook up the fullscreen button.
+        * rendering/RenderThemeMac.h:
+        * rendering/RenderThemeMac.mm:
+        (WebCore::RenderThemeMac::shouldRenderMediaControlPart):
+        Allow the RenderThemeMac to make a decision about the availability of fullscreen based
+        on the QuickTime version, since this affects what controls are availabl.e
+
 2009-10-05  Kevin Decker  <kdecker@apple.com>
 
         Export a few more methods from Settings.h
index ab794eb26d9bb837a30fb82e2033d13d8b0c0cf6..157b01ac909541c941438f6c7e2a0281b24d9375 100644 (file)
@@ -839,6 +839,10 @@ ifeq ($(findstring ENABLE_PLUGIN_PROXY_FOR_VIDEO,$(FEATURE_DEFINES)), ENABLE_PLU
      WEBCORE_EXPORT_DEPENDENCIES := $(WEBCORE_EXPORT_DEPENDENCIES) WebCore.VideoProxy.exp
 endif
 
+ifeq ($(findstring ENABLE_VIDEO,$(FEATURE_DEFINES)), ENABLE_VIDEO)
+     WEBCORE_EXPORT_DEPENDENCIES := $(WEBCORE_EXPORT_DEPENDENCIES) WebCore.Video.exp
+endif
+
 WebCore.exp : WebCore.base.exp $(WEBCORE_EXPORT_DEPENDENCIES)
        cat $^ > $@
 
diff --git a/WebCore/WebCore.Video.exp b/WebCore/WebCore.Video.exp
new file mode 100644 (file)
index 0000000..596fb4b
--- /dev/null
@@ -0,0 +1,12 @@
+__ZN7WebCore16HTMLMediaElement4playEv
+__ZN7WebCore16HTMLMediaElement5pauseEv
+__ZNK7WebCore16HTMLMediaElement6volumeEv
+__ZNK7WebCore16HTMLMediaElement7canPlayEv
+__ZNK7WebCore16HTMLMediaElement8durationEv
+__ZN7WebCore16HTMLMediaElement9setVolumeEfRi
+__ZN7WebCore16HTMLMediaElement6rewindEf
+__ZN7WebCore16HTMLMediaElement10screenRectEv
+__ZNK7WebCore16HTMLMediaElement11currentTimeEv
+__ZNK7WebCore16HTMLMediaElement13platformMediaEv
+__ZN7WebCore16HTMLMediaElement14setCurrentTimeEfRi
+__ZN7WebCore16HTMLMediaElement14exitFullscreenEv
index fccb26e0aa9b4f1e9239aeb8bc89fc197be4630a..abd1309487da2b0ee9c87420806ff8ea3caf82b2 100644 (file)
@@ -719,6 +719,7 @@ __ZN7WebCore9HTMLNames7srcAttrE
 __ZN7WebCore9HTMLNames8frameTagE
 __ZN7WebCore9HTMLNames8hrefAttrE
 __ZN7WebCore9HTMLNames8inputTagE
+__ZN7WebCore9HTMLNames8videoTagE
 __ZN7WebCore9HTMLNames9iframeTagE
 __ZN7WebCore9HTMLNames9scriptTagE
 __ZN7WebCore9PageCache11setCapacityEi
index 1c29133e7544140582e8b8a4243bc4cdb27fdee9..23c58d42161edb075b26ddb8de3b75c3f2c468b0 100644 (file)
                63189AE20E83A33300012E41 /* NodeRareData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NodeRareData.h; sourceTree = "<group>"; };
                637B7ADE0E8767B800E32194 /* ElementRareData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ElementRareData.h; sourceTree = "<group>"; };
                63D7B32C0E78CD3F00F7617C /* NodeRenderStyle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NodeRenderStyle.h; sourceTree = "<group>"; };
+               63F371CD100E790000BBA87A /* WebCore.Video.exp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.exports; path = WebCore.Video.exp; sourceTree = "<group>"; };
                650F53DB09D15DDA00C9B0C8 /* CSSGrammar.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CSSGrammar.h; sourceTree = "<group>"; };
                650FBF270D9AF046008FC292 /* SVGHKernElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SVGHKernElement.cpp; sourceTree = "<group>"; };
                650FBF280D9AF047008FC292 /* SVGHKernElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGHKernElement.h; sourceTree = "<group>"; };
                                449195970FBE17D700D9F824 /* WebCore.SVG.Filters.exp */,
                                449195960FBE17D700D9F824 /* WebCore.SVG.ForeignObject.exp */,
                                449195950FBE17D700D9F824 /* WebCore.Tiger.exp */,
+                               63F371CD100E790000BBA87A /* WebCore.Video.exp */,
                                449195940FBE17D700D9F824 /* WebCore.VideoProxy.exp */,
                        );
                        name = Exports;
index 2409d3702d2a20f486ef6c5cfc8d285aff4da6f5..6768d5e053f9933745ac78527f535cbcd86b2c7b 100644 (file)
@@ -28,6 +28,7 @@
 #if ENABLE(VIDEO)
 #include "HTMLMediaElement.h"
 
+#include "ChromeClient.h"
 #include "CSSHelper.h"
 #include "CSSPropertyNames.h"
 #include "CSSValueKeywords.h"
@@ -55,6 +56,8 @@
 #include "RenderVideo.h"
 #include "ScriptEventListener.h"
 #include "TimeRanges.h"
+#include "ClientRect.h"
+#include "ClientRectList.h"
 #include <limits>
 #include <wtf/CurrentTime.h>
 #include <wtf/MathExtras.h>
@@ -111,6 +114,7 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document* doc)
     , m_sentEndEvent(false)
     , m_pausedInternal(false)
     , m_sendProgressEvents(true)
+    , m_isFullscreen(false)
 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
     , m_needWidgetUpdate(false)
 #endif
@@ -241,6 +245,12 @@ void HTMLMediaElement::insertedIntoDocument()
         scheduleLoad();
 }
 
+void HTMLMediaElement::willRemove()
+{
+    if (m_isFullscreen)
+        exitFullscreen();
+    HTMLElement::willRemove();
+}
 void HTMLMediaElement::removedFromDocument()
 {
     if (m_networkState > NETWORK_EMPTY)
@@ -1696,6 +1706,14 @@ void HTMLMediaElement::mediaVolumeDidChange()
     updateVolume();
 }
 
+const IntRect HTMLMediaElement::screenRect()
+{
+    IntRect elementRect;
+    if (renderer())
+        elementRect = renderer()->view()->frameView()->contentsToScreen(renderer()->absoluteBoundingBoxRect());
+    return elementRect;
+}
+    
 void HTMLMediaElement::defaultEventHandler(Event* event)
 {
 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
@@ -1768,6 +1786,28 @@ void HTMLMediaElement::finishParsingChildren()
 
 #endif
 
+void HTMLMediaElement::enterFullscreen()
+{
+    ASSERT(!m_isFullscreen);
+    if (!renderer())
+        return;
+    if (document() && document()->page())
+        document()->page()->chrome()->client()->enterFullscreenForNode(this);
+    m_isFullscreen = true;
+}
+
+void HTMLMediaElement::exitFullscreen()
+{
+    ASSERT(m_isFullscreen);
+    if (document() && document()->page())
+        document()->page()->chrome()->client()->exitFullscreenForNode(this);
+    m_isFullscreen = false;
+}
+
+PlatformMedia HTMLMediaElement::platformMedia() const
+{
+    return m_player ? m_player->platformMedia() : NoPlatformMedia;
+}        
 }
 
 #endif
index aa8d5f72a9aaa9d5c60725e8a579c9f654c239a7..2b0ce32ea23946c7220ac5f7aee08ae0741c68c7 100644 (file)
@@ -43,7 +43,7 @@ class HTMLSourceElement;
 class MediaError;
 class KURL;
 class TimeRanges;
-    
+
 class HTMLMediaElement : public HTMLElement, public MediaPlayerClient {
 public:
     HTMLMediaElement(const QualifiedName&, Document*);
@@ -57,6 +57,7 @@ public:
     virtual bool rendererIsNeeded(RenderStyle*);
     virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
     virtual void insertedIntoDocument();
+    virtual void willRemove();
     virtual void removedFromDocument();
     virtual void attach();
     virtual void recalcStyle(StyleChange);
@@ -73,6 +74,8 @@ public:
     // Eventually overloaded in HTMLVideoElement
     virtual bool supportsFullscreen() const { return false; };
     virtual bool supportsSave() const;
+    
+    PlatformMedia platformMedia() const;
 
     void scheduleLoad();
     
@@ -141,6 +144,8 @@ public:
     void beginScrubbing();
     void endScrubbing();
 
+    const IntRect screenRect();
+
     bool canPlay() const;
 
     float percentLoaded() const;
@@ -154,6 +159,9 @@ public:
 #endif
 
     bool hasSingleSecurityOrigin() const { return !m_player || m_player->hasSingleSecurityOrigin(); }
+    
+    void enterFullscreen();
+    void exitFullscreen();
 
 protected:
     float getTimeOffsetAttribute(const QualifiedName&, float valueOnError) const;
@@ -310,6 +318,8 @@ protected:
     // support progress events so setting m_sendProgressEvents disables them 
     bool m_sendProgressEvents : 1;
 
+    bool m_isFullscreen : 1;
+
 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
     bool m_needWidgetUpdate : 1;
 #endif
index ecd74e74829a2d02df6621e58b9fd72dd1d1191e..5bbc16747efd5290760298a9618b1d7384f730ce 100644 (file)
@@ -28,6 +28,7 @@
 #if ENABLE(VIDEO)
 #include "HTMLVideoElement.h"
 
+#include "ChromeClient.h"
 #include "CSSHelper.h"
 #include "CSSPropertyNames.h"
 #include "Document.h"
@@ -112,6 +113,18 @@ void HTMLVideoElement::parseMappedAttribute(MappedAttribute* attr)
         HTMLMediaElement::parseMappedAttribute(attr);
 }
 
+bool HTMLVideoElement::supportsFullscreen() const
+{
+    Page* page = document() ? document()->page() : 0;
+    if (!page) 
+        return false;
+
+    if (!m_player || !m_player->supportsFullscreen())
+        return false;
+    
+    return page->chrome()->client()->supportsFullscreenForNode(this);
+}
+
 unsigned HTMLVideoElement::videoWidth() const
 {
     if (!m_player)
index dc9714a3df16840a1affcca4988ff7c400bcd4fb..096eb539ad4acd640c72823eb25f32ae3365d80e 100644 (file)
@@ -49,7 +49,7 @@ public:
     virtual void parseMappedAttribute(MappedAttribute* attr);
     virtual bool isVideo() const { return true; }
     virtual bool hasVideo() const { return player() && player()->hasVideo(); }
-    virtual bool supportsFullscreen() const { return player() && player()->supportsFullscreen(); }
+    virtual bool supportsFullscreen() const;
     virtual bool isURLAttribute(Attribute*) const;
     virtual const QualifiedName& imageSourceAttributeName() const;
 
index 2d112753f3a3941b5b28afb69bea0efc2d28f06d..5231603586667bdb279a7c790872b9b1d5b42696 100644 (file)
@@ -203,6 +203,10 @@ namespace WebCore {
         virtual void scheduleCompositingLayerSync() = 0;
 #endif
 
+        virtual bool supportsFullscreenForNode(const Node*) { return false; }
+        virtual void enterFullscreenForNode(Node*) { }
+        virtual void exitFullscreenForNode(Node*) { }
+        
 #if PLATFORM(MAC)
         virtual KeyboardUIMode keyboardUIMode() { return KeyboardAccessDefault; }
 
index 23410b2ec4c0a05ce314fe60bfc4223e50fcf176..03dff9198d2c59693bbb3b408871d64fba4c5e67 100644 (file)
@@ -65,7 +65,7 @@ public:
     virtual void play() { }
     virtual void pause() { }    
 
-    virtual bool supportsFullscreen() const { return false; }
+    virtual PlatformMedia platformMedia() const { return NoPlatformMedia; }
 
     virtual IntSize naturalSize() const { return IntSize(0, 0); }
 
@@ -338,6 +338,11 @@ bool MediaPlayer::inMediaDocument()
     return document && document->isMediaDocument();
 }
 
+PlatformMedia MediaPlayer::platformMedia() const
+{
+    return m_private->platformMedia();
+}
+
 MediaPlayer::NetworkState MediaPlayer::networkState()
 {
     return m_private->networkState();
index 4c5ee5b0ba6fa8e6db87d0076672c46cbf5f1289..95efeb09a1d7fe028d48d6097c573d4f8d2d578e 100644 (file)
 #include <wtf/OwnPtr.h>
 #include <wtf/Noncopyable.h>
 
+#ifdef __OBJC__
+@class QTMovie;
+#else
+class QTMovie;
+#endif
+
 namespace WebCore {
 
+// Structure that will hold every native
+// types supported by the current media player.
+// We have to do that has multiple media players
+// backend can live at runtime.
+typedef struct PlatformMedia {
+    QTMovie* qtMovie;
+} PlatformMedia;
+
+static const PlatformMedia NoPlatformMedia = { 0 };
+
 class ContentType;
 class FrameView;
 class GraphicsContext;
@@ -110,6 +126,8 @@ public:
 
     bool supportsFullscreen() const;
     bool supportsSave() const;
+    PlatformMedia platformMedia() const;
+
     IntSize naturalSize();
     bool hasVideo() const;
     bool hasAudio() const;
index 9cc89c5230a55d3069905236acb4274dce852eba..2f220b1dd1d2c4f09378a7d254ba24bf752f8cad 100644 (file)
@@ -43,6 +43,8 @@ public:
     virtual void load(const String& url) = 0;
     virtual void cancelLoad() = 0;
     
+    virtual PlatformMedia platformMedia() const { return NoPlatformMedia; }
+
     virtual void play() = 0;
     virtual void pause() = 0;    
 
index bfaba9af5e75271f7d4c579b9c346ccbd71756c0..0a636269e04ce742297dbb2231d663f5c879358b 100644 (file)
@@ -77,9 +77,12 @@ private:
     static MediaPlayer::SupportsType supportsType(const String& type, const String& codecs);
     static bool isAvailable();
 
+    PlatformMedia platformMedia() const;
+
     IntSize naturalSize() const;
     bool hasVideo() const;
     bool hasAudio() const;
+    bool supportsFullscreen() const;
     
     void load(const String& url);
     void cancelLoad();
index 5a5c0315bd899de97eb0f83cb1a7407876bd6f37..30d0c828d182d95b7f69c1d17a078fa69e583bb1 100644 (file)
@@ -565,6 +565,12 @@ void MediaPlayerPrivate::load(const String& url)
     [m_objcObserver.get() setDelayCallbacks:NO];
 }
 
+PlatformMedia MediaPlayerPrivate::platformMedia() const
+{
+    PlatformMedia plaftformMedia = { m_qtMovie.get() };
+    return plaftformMedia;
+}
+
 void MediaPlayerPrivate::play()
 {
     if (!metaDataAvailable())
@@ -729,6 +735,11 @@ bool MediaPlayerPrivate::hasAudio() const
     return [[m_qtMovie.get() attributeForKey:QTMovieHasAudioAttribute] boolValue];
 }
 
+bool MediaPlayerPrivate::supportsFullscreen() const
+{   
+    return true;
+}
+
 void MediaPlayerPrivate::setVolume(float volume)
 {
     if (m_qtMovie)
index 29e2e5761f24a81bc8c277a408491b641f35a998..a17dc0eb60d829d4a39ef7efb5eedd8c4aa3d7a9 100644 (file)
@@ -646,12 +646,12 @@ MediaControlFullscreenButtonElement::MediaControlFullscreenButtonElement(Documen
 void MediaControlFullscreenButtonElement::defaultEventHandler(Event* event)
 {
     if (event->type() == eventNames().clickEvent) {
+        m_mediaElement->enterFullscreen();
         event->setDefaultHandled();
     }
     HTMLInputElement::defaultEventHandler(event);
 }
 
-
 // ----------------------------
 
 MediaControlTimeDisplayElement::MediaControlTimeDisplayElement(Document* document, PseudoId pseudo, HTMLMediaElement* element)
index 85f141f609333a852424fe37249aed552d6812bb..1d68c630c9afa2f3f891591d3a043492bffaf535 100644 (file)
@@ -132,6 +132,8 @@ protected:
 
     // Media controls
     virtual String extraMediaControlsStyleSheet();
+
+    virtual bool shouldRenderMediaControlPart(ControlPart, Element*);
 #endif
 
 private:
index eaf7cc435f63aa063ca5bcedb9f3ef30573e6d6e..ee9f41dfc67cf2f2e8d954ca0571eafe0b99cf64 100644 (file)
@@ -1697,7 +1697,16 @@ String RenderThemeMac::extraMediaControlsStyleSheet()
     else
         return String();
 }
-#endif
+
+bool RenderThemeMac::shouldRenderMediaControlPart(ControlPart part, Element* e)
+{
+    if (part == MediaFullscreenButtonPart)
+        return mediaControllerTheme() == MediaControllerThemeQT;
+
+    return RenderTheme::shouldRenderMediaControlPart(part, e);
+}
+
+#endif // ENABLE(VIDEO)
 
 NSPopUpButtonCell* RenderThemeMac::popupButton() const
 {
index 9b0b8b85887a45361a9e772f6f22f3098024aeec..2693633bbbd8e473aadd67b3f42fdbf57ce45b1b 100644 (file)
@@ -1,3 +1,14 @@
+2009-10-05  Pierre d'Herbemont  <pdherbemont@webkit.org>
+
+        Reviewed by Simon Fraser
+        
+        Support fullscreen in MediaPlayer (Mac)
+        https://bugs.webkit.org/show_bug.cgi?id=26742
+
+        Add new files for video fullscreen.
+
+        * WebKit.xcodeproj/project.pbxproj:
+
 2009-10-05  Pavel Feldman  <pfeldman@chromium.org>
 
         Reviewed by Timothy Hatcher.
index 4d7a7203ad8b9ddd6048365618b659e1c3c2e95c..f1518d1ff7527272b30308b5f2ca84726a12317f 100644 (file)
                0AB752380FA2E4DB00D7CBB1 /* WebNetscapeContainerCheckContextInfo.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0AB752360FA2E4DB00D7CBB1 /* WebNetscapeContainerCheckContextInfo.mm */; };
                0AEBFF630F9FA8BE000D486B /* WebNetscapeContainerCheckPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 0AEBFF610F9FA8BE000D486B /* WebNetscapeContainerCheckPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0AEBFF640F9FA8BE000D486B /* WebNetscapeContainerCheckPrivate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0AEBFF620F9FA8BE000D486B /* WebNetscapeContainerCheckPrivate.mm */; };
+               0FD3B0F21076C3E900039B96 /* WebVideoFullscreenController.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD3B0EE1076C3E900039B96 /* WebVideoFullscreenController.h */; };
+               0FD3B0F31076C3E900039B96 /* WebVideoFullscreenController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0FD3B0EF1076C3E900039B96 /* WebVideoFullscreenController.mm */; };
+               0FD3B0F41076C3E900039B96 /* WebVideoFullscreenHUDWindowController.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD3B0F01076C3E900039B96 /* WebVideoFullscreenHUDWindowController.h */; };
+               0FD3B0F51076C3E900039B96 /* WebVideoFullscreenHUDWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0FD3B0F11076C3E900039B96 /* WebVideoFullscreenHUDWindowController.mm */; };
+               0FD3B0F81076C3F700039B96 /* WebWindowAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD3B0F61076C3F700039B96 /* WebWindowAnimation.h */; };
+               0FD3B0F91076C3F700039B96 /* WebWindowAnimation.m in Sources */ = {isa = PBXBuildFile; fileRef = 0FD3B0F71076C3F700039B96 /* WebWindowAnimation.m */; };
                14D8252F0AF955090004F057 /* WebChromeClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 14D8252D0AF955090004F057 /* WebChromeClient.h */; };
                14D825300AF955090004F057 /* WebChromeClient.mm in Sources */ = {isa = PBXBuildFile; fileRef = 14D8252E0AF955090004F057 /* WebChromeClient.mm */; };
                1A20D08B0ED384F20043FA9F /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A20D08A0ED384F20043FA9F /* QuartzCore.framework */; };
                0AB752360FA2E4DB00D7CBB1 /* WebNetscapeContainerCheckContextInfo.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebNetscapeContainerCheckContextInfo.mm; sourceTree = "<group>"; };
                0AEBFF610F9FA8BE000D486B /* WebNetscapeContainerCheckPrivate.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; path = WebNetscapeContainerCheckPrivate.h; sourceTree = "<group>"; };
                0AEBFF620F9FA8BE000D486B /* WebNetscapeContainerCheckPrivate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebNetscapeContainerCheckPrivate.mm; sourceTree = "<group>"; };
+               0FD3B0EE1076C3E900039B96 /* WebVideoFullscreenController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebVideoFullscreenController.h; sourceTree = "<group>"; };
+               0FD3B0EF1076C3E900039B96 /* WebVideoFullscreenController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebVideoFullscreenController.mm; sourceTree = "<group>"; };
+               0FD3B0F01076C3E900039B96 /* WebVideoFullscreenHUDWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebVideoFullscreenHUDWindowController.h; sourceTree = "<group>"; };
+               0FD3B0F11076C3E900039B96 /* WebVideoFullscreenHUDWindowController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebVideoFullscreenHUDWindowController.mm; sourceTree = "<group>"; };
+               0FD3B0F61076C3F700039B96 /* WebWindowAnimation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebWindowAnimation.h; sourceTree = "<group>"; };
+               0FD3B0F71076C3F700039B96 /* WebWindowAnimation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebWindowAnimation.m; sourceTree = "<group>"; };
                14D8252D0AF955090004F057 /* WebChromeClient.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = WebChromeClient.h; sourceTree = "<group>"; };
                14D8252E0AF955090004F057 /* WebChromeClient.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; path = WebChromeClient.mm; sourceTree = "<group>"; };
                1A20D08A0ED384F20043FA9F /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = /System/Library/Frameworks/QuartzCore.framework; sourceTree = "<absolute>"; };
                                F834AAD60E64B1C700E2737C /* WebTextIterator.mm */,
                                515E27CC0458C86500CA2D3A /* WebUIDelegate.h */,
                                65A7D44A0568AB2600E70EF6 /* WebUIDelegatePrivate.h */,
+                               0FD3B0EE1076C3E900039B96 /* WebVideoFullscreenController.h */,
+                               0FD3B0EF1076C3E900039B96 /* WebVideoFullscreenController.mm */,
+                               0FD3B0F01076C3E900039B96 /* WebVideoFullscreenHUDWindowController.h */,
+                               0FD3B0F11076C3E900039B96 /* WebVideoFullscreenHUDWindowController.mm */,
                                51A8B579042834F700CA2D3A /* WebView.h */,
                                51A8B57A042834F700CA2D3A /* WebView.mm */,
                                BC2E464B0FD8A96800A9D9DE /* WebViewData.h */,
                                BC2E464C0FD8A96800A9D9DE /* WebViewData.mm */,
                                930D02BB06275F640076701E /* WebViewInternal.h */,
                                51A8B57D0428353A00CA2D3A /* WebViewPrivate.h */,
+                               0FD3B0F61076C3F700039B96 /* WebWindowAnimation.h */,
+                               0FD3B0F71076C3F700039B96 /* WebWindowAnimation.m */,
                        );
                        name = WebView;
                        path = mac/WebView;
                                37D1DCA81065928C0068F7EF /* WebJSPDFDoc.h in Headers */,
                                5158F6EF106D862A00AF457C /* WebHistoryDelegate.h in Headers */,
                                5185F62610712B80007AA393 /* WebNavigationData.h in Headers */,
+                               0FD3B0F21076C3E900039B96 /* WebVideoFullscreenController.h in Headers */,
+                               0FD3B0F41076C3E900039B96 /* WebVideoFullscreenHUDWindowController.h in Headers */,
+                               0FD3B0F81076C3F700039B96 /* WebWindowAnimation.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                37B6FB4F1063530C000FDB3B /* WebPDFDocumentExtras.mm in Sources */,
                                37D1DCA91065928C0068F7EF /* WebJSPDFDoc.mm in Sources */,
                                5185F62810712B97007AA393 /* WebNavigationData.mm in Sources */,
+                               0FD3B0F31076C3E900039B96 /* WebVideoFullscreenController.mm in Sources */,
+                               0FD3B0F51076C3E900039B96 /* WebVideoFullscreenHUDWindowController.mm in Sources */,
+                               0FD3B0F91076C3F700039B96 /* WebWindowAnimation.m in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index 64baf9768e71274f2f8484d2cdbdbc8efbb832f7..d52b130dfdf78350c586a420259d1671237e5f17 100644 (file)
@@ -1,3 +1,57 @@
+2009-10-05  Pierre d'Herbemont  <pdherbemont@webkit.org>
+
+        Reviewed by Simon Fraser
+        
+        Support fullscreen in MediaPlayer (Mac)
+        https://bugs.webkit.org/show_bug.cgi?id=26742
+
+        Add a fullscreen button to the <video> controller if the media engine,
+        and the theme have support for fullscreen, and can show appropriate controls.
+        Clicking the button calls through the ChromeClient to the WebVideoFullscreenController
+        in WebKit to do a nice animation to fullscreen, with a custom controller.
+
+        * WebCoreSupport/WebChromeClient.h:
+        * WebCoreSupport/WebChromeClient.mm:
+        (WebChromeClient::supportsFullscreenForNode):
+        (WebChromeClient::enterFullscreenForNode):
+        (WebChromeClient::exitFullscreenForNode):
+        New methods to ask whether fullscreen is possible for a given node, and
+        notifications on enterying and exiting fullscreen.
+        
+        * WebView/WebVideoFullscreenController.h: Added.
+        * WebView/WebVideoFullscreenController.mm: Added.
+        WebVideoFullscreenController is responsible for creating the fullscreen window,
+        and coordinating the various animations when going fullscreen.
+
+        * WebView/WebVideoFullscreenHUDWindowController.h: Added.
+        * WebView/WebVideoFullscreenHUDWindowController.mm: Added.
+        This class manages the heads-up display (HUD) control bar.
+
+        * WebView/WebView.mm:
+        (-[WebView _close]):
+        Make sure we come out of fullscreen if the WebView is torn down (e.g. if
+        you close a background window).
+
+        (-[WebView _enterFullscreenForNode:WebCore::]):
+        Make a WebVideoFullscreenController and tell is to start to go fullscreen.
+        
+        (-[WebView _exitFullscreen]):
+        Tell the WebVideoFullscreenController to come out of fullscreen, and clean up.
+        
+        * WebView/WebViewData.h:
+        * WebView/WebViewData.mm:
+        (-[WebViewPrivate dealloc]):
+        (-[WebViewPrivate finalize]):
+        * WebView/WebViewInternal.h:
+        Keep a pointer to the WebVideoFullscreenController.
+        
+        * WebView/WebWindowAnimation.h: Added.
+        * WebView/WebWindowAnimation.m: Added.
+        (WebWindowAnimationDurationFromDuration):
+        (scaledRect):
+        (squaredDistance):
+        Handle the animations used during the transitition to fullscreen.
+
 2009-10-05  Anders Carlsson  <andersca@apple.com>
 
         Reviewed by Kevin Decker.
index 1f83efff303607d57c5fe15b66395217d7242f9e..a8f22f6c80dc68ae176da7b30c919fa882dfdc44 100644 (file)
@@ -150,6 +150,10 @@ public:
     virtual void scheduleCompositingLayerSync();
 #endif
 
+    virtual bool supportsFullscreenForNode(const WebCore::Node*);
+    virtual void enterFullscreenForNode(WebCore::Node*);
+    virtual void exitFullscreenForNode(WebCore::Node*);
+
     virtual void requestGeolocationPermissionForFrame(WebCore::Frame*, WebCore::Geolocation*);
 
 private:
index c1d562e27a0abe6f13dfce85d8ebfd0685de1d3c..58127bf67909b62b5b5034f0cdde345253595398 100644 (file)
@@ -55,6 +55,7 @@
 #import <WebCore/FrameLoadRequest.h>
 #import <WebCore/Geolocation.h>
 #import <WebCore/HitTestResult.h>
+#import <WebCore/HTMLNames.h>
 #import <WebCore/IntRect.h>
 #import <WebCore/Page.h>
 #import <WebCore/PlatformScreen.h>
@@ -715,6 +716,29 @@ void WebChromeClient::scheduleCompositingLayerSync()
 
 #endif
 
+#if ENABLE(VIDEO)
+
+bool WebChromeClient::supportsFullscreenForNode(const Node* node)
+{
+    return node->hasTagName(WebCore::HTMLNames::videoTag);
+}
+
+void WebChromeClient::enterFullscreenForNode(Node* node)
+{
+    BEGIN_BLOCK_OBJC_EXCEPTIONS;
+    [m_webView _enterFullscreenForNode:node];
+    END_BLOCK_OBJC_EXCEPTIONS;
+}
+
+void WebChromeClient::exitFullscreenForNode(Node*)
+{
+    BEGIN_BLOCK_OBJC_EXCEPTIONS;
+    [m_webView _exitFullscreen];
+    END_BLOCK_OBJC_EXCEPTIONS;    
+}
+
+#endif
+
 void WebChromeClient::requestGeolocationPermissionForFrame(Frame* frame, Geolocation* geolocation)
 {
     BEGIN_BLOCK_OBJC_EXCEPTIONS;
diff --git a/WebKit/mac/WebView/WebVideoFullscreenController.h b/WebKit/mac/WebView/WebVideoFullscreenController.h
new file mode 100644 (file)
index 0000000..bb6a083
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#if ENABLE(VIDEO)
+
+#import <Cocoa/Cocoa.h>
+#import <wtf/RefPtr.h>
+#import <WebCore/HTMLMediaElement.h>
+
+@protocol WebVideoFullscreenControllerDelegate;
+@class WebVideoFullscreenHUDWindowController;
+@class WebWindowFadeAnimation;
+
+@interface WebVideoFullscreenController : NSWindowController
+{
+@private
+    RefPtr<WebCore::HTMLMediaElement> _mediaElement; // (retain)
+    id<WebVideoFullscreenControllerDelegate> _delegate; // (assign)
+
+    NSWindow *_backgroundFullscreenWindow; // (retain)
+    WebVideoFullscreenHUDWindowController* _hudController; // (retain)
+
+    WebWindowFadeAnimation *_fadeAnimation; // (retain)
+
+    BOOL _isEndingFullscreen;
+    BOOL _isWindowLoaded;
+    BOOL _forceDisableAnimation;
+}
+
+- (id<WebVideoFullscreenControllerDelegate>)delegate;
+- (void)setDelegate:(id<WebVideoFullscreenControllerDelegate>)delegate;
+
+- (void)setMediaElement:(WebCore::HTMLMediaElement*)mediaElement;
+- (WebCore::HTMLMediaElement*)mediaElement;
+
+- (void)enterFullscreen:(NSScreen *)screen;
+- (void)exitFullscreen;
+
+@end
+
+#endif
+
diff --git a/WebKit/mac/WebView/WebVideoFullscreenController.mm b/WebKit/mac/WebView/WebVideoFullscreenController.mm
new file mode 100644 (file)
index 0000000..ab1f114
--- /dev/null
@@ -0,0 +1,444 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#if ENABLE(VIDEO)
+
+#import <QTKit/QTKit.h>
+#import <objc/objc-runtime.h>
+#import <HIToolbox/HIToolbox.h>
+
+#import <wtf/UnusedParam.h>
+#import <WebCore/SoftLinking.h>
+#import <WebCore/IntRect.h>
+
+#import "WebVideoFullscreenController.h"
+#import "WebVideoFullscreenHUDWindowController.h"
+#import "WebKitSystemInterface.h"
+#import "WebWindowAnimation.h"
+
+SOFT_LINK_FRAMEWORK(QTKit)
+
+
+SOFT_LINK_CLASS(QTKit, QTMovieView)
+
+
+@interface WebVideoFullscreenWindow : NSWindow
+#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_TIGER)
+<NSAnimationDelegate>
+#endif
+{
+    SEL _controllerActionOnAnimationEnd;
+    WebWindowScaleAnimation *_fullscreenAnimation; // (retain)
+    QTMovieView *_movieView; // (retain)
+}
+- (void)animateFromRect:(NSRect)startRect toRect:(NSRect)endRect withSubAnimation:(NSAnimation *)subAnimation controllerAction:(SEL)controllerAction;
+- (QTMovieView *)movieView;
+- (void)setMovieView:(QTMovieView *)movieView;
+@end
+
+@interface WebVideoFullscreenController () <WebVideoFullscreenHUDWindowControllerDelegate>
+@end
+
+@implementation WebVideoFullscreenController
+- (id)init
+{
+    // Do not defer window creation, to make sure -windowNumber is created (needed by WebWindowScaleAnimation).
+    NSWindow *window = [[WebVideoFullscreenWindow alloc] initWithContentRect:NSZeroRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO];
+    self = [super initWithWindow:window];
+    [window release];
+    if (!self)
+        return nil;
+    [self windowDidLoad];
+    return self;
+    
+}
+- (void)dealloc
+{
+    ASSERT(!_backgroundFullscreenWindow);
+    ASSERT(!_fadeAnimation);
+    [super dealloc];
+}
+
+- (WebVideoFullscreenWindow *)fullscreenWindow
+{
+    return (WebVideoFullscreenWindow *)[super window];
+}
+
+- (void)windowDidLoad
+{
+    WebVideoFullscreenWindow *window = [self fullscreenWindow];
+    QTMovieView *view = [[getQTMovieViewClass() alloc] init];
+    [view setFillColor:[NSColor clearColor]];
+    [window setMovieView:view];
+    [view setControllerVisible:NO];
+    [view setPreservesAspectRatio:YES];
+    if (_mediaElement)
+        [view setMovie:_mediaElement->platformMedia().qtMovie];
+    [window setHasShadow:YES]; // This is nicer with a shadow.
+    [window setLevel:NSPopUpMenuWindowLevel-1];
+    [view release];
+}
+
+- (WebCore::HTMLMediaElement*)mediaElement;
+{
+    return _mediaElement.get();
+}
+
+- (void)setMediaElement:(WebCore::HTMLMediaElement*)mediaElement;
+{
+    _mediaElement = mediaElement;
+    if ([self isWindowLoaded]) {
+        QTMovieView *movieView = [[self fullscreenWindow] movieView];
+        [movieView setMovie:_mediaElement->platformMedia().qtMovie];
+    }
+}
+
+- (id<WebVideoFullscreenControllerDelegate>)delegate
+{
+    return _delegate;
+}
+
+- (void)setDelegate:(id<WebVideoFullscreenControllerDelegate>)delegate;
+{
+    _delegate = delegate;
+}
+
+- (CGFloat)clearFadeAnimation
+{
+    [_fadeAnimation stopAnimation];
+    CGFloat previousAlpha = [_fadeAnimation currentAlpha];
+    [_fadeAnimation setWindow:nil];
+    [_fadeAnimation release];
+    _fadeAnimation = nil;
+    return previousAlpha;
+}
+
+- (void)windowDidExitFullscreen
+{
+    [self clearFadeAnimation];
+    [[self window] close];
+    [self setWindow:nil];
+    SetSystemUIMode(kUIModeNormal, 0);
+    [_hudController setDelegate:nil];
+    [_hudController release];
+    _hudController = nil;
+    [_backgroundFullscreenWindow close];
+    [_backgroundFullscreenWindow release];
+    _backgroundFullscreenWindow = nil;
+    
+    [self autorelease]; // Associated -retain is in -exitFullscreen.
+    _isEndingFullscreen = NO;
+}
+
+- (void)windowDidEnterFullscreen
+{
+    [self clearFadeAnimation];
+
+    ASSERT(!_hudController);
+    _hudController = [[WebVideoFullscreenHUDWindowController alloc] init];
+    [_hudController setDelegate:self];
+
+    SetSystemUIMode(kUIModeAllSuppressed , 0);
+    [NSCursor setHiddenUntilMouseMoves:YES];
+    
+    // Give the HUD keyboard focus initially
+    [_hudController fadeWindowIn];
+}
+
+- (NSRect)mediaElementRect
+{
+    return _mediaElement->screenRect();
+}
+
+#pragma mark -
+#pragma mark Exposed Interface
+
+static void constrainFrameToRatioOfFrame(NSRect *frameToConstrain, const NSRect *frame)
+{
+    // Keep a constrained aspect ratio for the destination window
+    double originalRatio = frame->size.width / frame->size.height;
+    double newRatio = frameToConstrain->size.width / frameToConstrain->size.height;
+    if (newRatio > originalRatio) {
+        double newWidth = originalRatio * frameToConstrain->size.height;
+        double diff = frameToConstrain->size.width - newWidth;
+        frameToConstrain->size.width = newWidth;
+        frameToConstrain->origin.x += diff / 2;
+    } else {
+        double newHeight = frameToConstrain->size.width / originalRatio;
+        double diff = frameToConstrain->size.height - newHeight;
+        frameToConstrain->size.height = newHeight;
+        frameToConstrain->origin.y += diff / 2;
+    }    
+}
+
+static NSWindow *createBackgroundFullscreenWindow(NSRect frame, int level)
+{
+    NSWindow *window = [[NSWindow alloc] initWithContentRect:frame styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO];
+    [window setOpaque:YES];
+    [window setBackgroundColor:[NSColor blackColor]];
+    [window setLevel:level];
+    [window setHidesOnDeactivate:YES];
+    [window setReleasedWhenClosed:NO];
+    return window;
+}
+
+- (void)setupFadeAnimationIfNeededAndFadeIn:(BOOL)fadeIn
+{
+    CGFloat initialAlpha = fadeIn ? 0 : 1;
+    if (_fadeAnimation) {
+        // Make sure we support queuing animation if the previous one isn't over yet
+        initialAlpha = [self clearFadeAnimation];
+    }
+    if (!_forceDisableAnimation)
+        _fadeAnimation = [[WebWindowFadeAnimation alloc] initWithDuration:0.2 window:_backgroundFullscreenWindow initialAlpha:initialAlpha finalAlpha:fadeIn ? 1 : 0];
+}
+
+- (void)enterFullscreen:(NSScreen *)screen;
+{
+    if (!screen)
+        screen = [NSScreen mainScreen];
+
+    NSRect frame = [self mediaElementRect];
+    NSRect endFrame = [screen frame];
+    constrainFrameToRatioOfFrame(&endFrame, &frame);
+
+    // Create a black window if needed
+    if (!_backgroundFullscreenWindow)
+        _backgroundFullscreenWindow = createBackgroundFullscreenWindow([screen frame], [[self window] level]-1);
+    else
+        [_backgroundFullscreenWindow setFrame:[screen frame] display:NO];
+
+    [self setupFadeAnimationIfNeededAndFadeIn:YES];
+    if (_forceDisableAnimation) {
+        // This will disable scale animation
+        frame = NSZeroRect;
+    }
+    [[self fullscreenWindow] animateFromRect:frame toRect:endFrame withSubAnimation:_fadeAnimation controllerAction:@selector(windowDidEnterFullscreen)];
+
+    [_backgroundFullscreenWindow orderWindow:NSWindowBelow relativeTo:[[self fullscreenWindow] windowNumber]];
+}
+
+- (void)exitFullscreen
+{
+    if (_isEndingFullscreen)
+        return;
+    _isEndingFullscreen = YES;
+    [_hudController closeWindow];
+
+    NSRect endFrame = [self mediaElementRect];
+
+    [self setupFadeAnimationIfNeededAndFadeIn:NO];
+    if (_forceDisableAnimation) {
+        // This will disable scale animation
+        endFrame = NSZeroRect;
+    }
+    
+    // We have to retain ourselves because we want to be alive for the end of the animation.
+    // If our owner releases us we could crash if this is not the case.
+    // Balanced in windowDidExitFullscreen
+    [self retain];    
+    
+    [[self fullscreenWindow] animateFromRect:[[self window] frame] toRect:endFrame withSubAnimation:_fadeAnimation controllerAction:@selector(windowDidExitFullscreen)];
+}
+
+#pragma mark -
+#pragma mark Window callback
+
+- (void)requestExitFullscreenWithAnimation:(BOOL)animation
+{
+    if (_isEndingFullscreen)
+        return;
+
+    _forceDisableAnimation = !animation;
+    _mediaElement->exitFullscreen();
+    _forceDisableAnimation = NO;
+}
+
+- (void)requestExitFullscreen
+{
+    [self requestExitFullscreenWithAnimation:YES];
+}
+
+- (void)fadeHUDIn
+{
+    [_hudController fadeWindowIn];
+}
+@end
+
+@implementation WebVideoFullscreenWindow
+
+- (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)aStyle backing:(NSBackingStoreType)bufferingType defer:(BOOL)flag
+{
+    UNUSED_PARAM(aStyle);
+    self = [super initWithContentRect:contentRect styleMask:NSBorderlessWindowMask backing:bufferingType defer:flag];
+    if (!self)
+        return nil;
+    [self setOpaque:NO];
+    [self setBackgroundColor:[NSColor clearColor]];
+    [self setHidesOnDeactivate:YES];
+    [self setIgnoresMouseEvents:NO];
+    [self setAcceptsMouseMovedEvents:YES];
+    return self;
+}
+
+- (void)dealloc
+{
+    ASSERT(!_fullscreenAnimation);
+    [super dealloc];
+}
+
+- (QTMovieView *)movieView
+{
+    return _movieView;
+}
+
+- (void)setMovieView:(QTMovieView *)movieView
+{
+    if (_movieView == movieView)
+        return;
+    [_movieView release];
+    _movieView = [movieView retain];
+    [self setContentView:_movieView];
+}
+
+- (BOOL)resignFirstResponder
+{
+    return NO;
+}
+
+- (BOOL)canBecomeKeyWindow
+{
+    return NO;
+}
+
+- (void)mouseDown:(NSEvent *)theEvent
+{
+    UNUSED_PARAM(theEvent);
+}
+
+- (void)cancelOperation:(id)sender
+{
+    UNUSED_PARAM(sender);
+    [[self windowController] requestExitFullscreen];
+}
+
+- (void)animatedResizeDidEnd
+{
+    // Call our windowController.
+    if (_controllerActionOnAnimationEnd)
+        [[self windowController] performSelector:_controllerActionOnAnimationEnd];
+    _controllerActionOnAnimationEnd = NULL;
+}
+
+//
+// This function will animate a change of frame rectangle
+// We support queuing animation, that means that we'll correctly
+// interrupt the running animation, and queue the next one.
+//
+- (void)animateFromRect:(NSRect)startRect toRect:(NSRect)endRect withSubAnimation:(NSAnimation *)subAnimation controllerAction:(SEL)controllerAction
+{
+    _controllerActionOnAnimationEnd = controllerAction;
+
+    BOOL wasAnimating = NO;
+    if (_fullscreenAnimation) {
+        wasAnimating = YES;
+
+        // Interrupt any running animation.
+        [_fullscreenAnimation stopAnimation];
+
+        // Save the current rect to ensure a smooth transition.
+        startRect = [_fullscreenAnimation currentFrame];
+        [_fullscreenAnimation release];
+        _fullscreenAnimation = nil;
+    }
+    
+    if (NSIsEmptyRect(startRect) || NSIsEmptyRect(endRect)) {
+        // Fakely end the subanimation.
+        [subAnimation setCurrentProgress:1.0];
+        // And remove the weak link to the window.
+        [subAnimation stopAnimation];
+
+        [self setFrame:endRect display:NO];
+        [self makeKeyAndOrderFront:self];
+        [self animatedResizeDidEnd];
+        return;
+    }
+
+    if (!wasAnimating) {
+        // We'll downscale the window during the animation based on the higher resolution rect
+        BOOL higherResolutionIsEndRect = startRect.size.width < endRect.size.width && startRect.size.height < endRect.size.height;
+        [self setFrame:higherResolutionIsEndRect ? endRect : startRect display:NO];        
+    }
+    
+    ASSERT(!_fullscreenAnimation);
+    _fullscreenAnimation = [[WebWindowScaleAnimation alloc] initWithHintedDuration:0.2 window:self initalFrame:startRect finalFrame:endRect];
+    [_fullscreenAnimation setSubAnimation:subAnimation];
+    [_fullscreenAnimation setDelegate:self];
+    
+    // Make sure the animation has scaled the window before showing it.
+    [_fullscreenAnimation setCurrentProgress:0];
+    [self makeKeyAndOrderFront:self];
+
+    [_fullscreenAnimation startAnimation];
+}
+
+- (void)animationDidEnd:(NSAnimation *)animation
+{
+    if (![NSThread isMainThread]) {
+        [self performSelectorOnMainThread:@selector(animationDidEnd:) withObject:animation waitUntilDone:NO];
+        return;
+    }
+    if (animation != _fullscreenAnimation)
+        return;
+
+    // The animation is not really over and was interrupted
+    // Don't send completion events.
+    if ([animation currentProgress] < 1.0)
+        return;
+
+    // Ensure that animation (and subanimation) don't keep
+    // the weak reference to the window ivar that may be destroyed from
+    // now on.
+    [_fullscreenAnimation setWindow:nil];
+
+    [_fullscreenAnimation autorelease];
+    _fullscreenAnimation = nil;
+
+    [self animatedResizeDidEnd];
+}
+
+- (void)mouseMoved:(NSEvent *)theEvent
+{
+    [[self windowController] fadeHUDIn];
+}
+
+- (void)resignKeyWindow
+{
+    [super resignKeyWindow];
+    [[self windowController] requestExitFullscreenWithAnimation:NO];
+}
+@end
+
+#endif /* ENABLE(VIDEO) */
diff --git a/WebKit/mac/WebView/WebVideoFullscreenHUDWindowController.h b/WebKit/mac/WebView/WebVideoFullscreenHUDWindowController.h
new file mode 100644 (file)
index 0000000..c0dbac2
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#if ENABLE(VIDEO)
+
+#import <Cocoa/Cocoa.h>
+#import <WebCore/HTMLMediaElement.h>
+
+@protocol WebVideoFullscreenHUDWindowControllerDelegate;
+
+@interface WebVideoFullscreenHUDWindowController : NSWindowController {
+@private
+    id<WebVideoFullscreenHUDWindowControllerDelegate> _delegate;
+    NSTimer *_timelineUpdateTimer;
+    NSTrackingArea *_area;
+    BOOL _mouseIsInHUD;
+
+    NSControl *_timeline;
+    NSTextField *_remainingTimeText;
+    NSTextField *_elapsedTimeText;
+    NSControl *_volumeSlider;
+    NSControl *_playButton;
+}
+- (id<WebVideoFullscreenHUDWindowControllerDelegate>)delegate;
+- (void)setDelegate:(id<WebVideoFullscreenHUDWindowControllerDelegate>)delegate;
+- (void)fadeWindowIn;
+- (void)fadeWindowOut;
+- (void)closeWindow;
+
+@end
+
+@protocol WebVideoFullscreenHUDWindowControllerDelegate <NSObject>
+- (void)requestExitFullscreen;
+- (WebCore::HTMLMediaElement*)mediaElement;
+@end
+
+#endif
diff --git a/WebKit/mac/WebView/WebVideoFullscreenHUDWindowController.mm b/WebKit/mac/WebView/WebVideoFullscreenHUDWindowController.mm
new file mode 100644 (file)
index 0000000..824d292
--- /dev/null
@@ -0,0 +1,562 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#if ENABLE(VIDEO)
+
+#import "WebVideoFullscreenHUDWindowController.h"
+
+#import <QTKit/QTKit.h>
+#import "WebKitSystemInterface.h"
+#import <wtf/RetainPtr.h>
+
+#define HAVE_MEDIA_CONTROL (!defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD))
+
+@interface WebVideoFullscreenHUDWindowController (Private) <NSWindowDelegate>
+
+- (void)updateTime;
+- (void)timelinePositionChanged:(id)sender;
+- (float)currentTime;
+- (void)setCurrentTime:(float)currentTime;
+- (double)duration;
+
+- (double)maxVolume;
+- (void)volumeChanged:(id)sender;
+- (double)volume;
+- (void)setVolume:(double)volume;
+
+- (void)playingChanged:(id)sender;
+- (BOOL)playing;
+- (void)setPlaying:(BOOL)playing;
+
+- (void)rewind:(id)sender;
+- (void)fastForward:(id)sender;
+
+- (NSString *)remainingTimeText;
+- (NSString *)elapsedTimeText;
+
+- (void)exitFullscreen:(id)sender;
+@end
+
+
+//
+// HUD Window
+//
+
+@interface WebVideoFullscreenHUDWindow : NSWindow
+@end
+
+@implementation WebVideoFullscreenHUDWindow
+
+- (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)aStyle backing:(NSBackingStoreType)bufferingType defer:(BOOL)flag
+{
+    UNUSED_PARAM(aStyle);
+    self = [super initWithContentRect:contentRect styleMask:NSBorderlessWindowMask backing:bufferingType defer:flag];
+    if (!self)
+        return nil;
+
+    [self setOpaque:NO];
+    [self setBackgroundColor:[NSColor clearColor]];
+    [self setLevel:NSPopUpMenuWindowLevel];
+    [self setAcceptsMouseMovedEvents:YES];
+    [self setIgnoresMouseEvents:NO];
+    [self setMovableByWindowBackground:YES];
+    [self setHidesOnDeactivate:YES];
+
+    return self;
+}
+
+- (BOOL)canBecomeKeyWindow
+{
+    return YES;
+}
+
+- (void)cancelOperation:(id)sender
+{
+    [[self windowController] exitFullscreen:self];
+}
+
+- (void)center
+{
+    NSRect hudFrame = [self frame];
+    NSRect screenFrame = [[NSScreen mainScreen] frame];
+    [self setFrameTopLeftPoint:NSMakePoint(screenFrame.origin.x + (screenFrame.size.width - hudFrame.size.width) / 2,
+                                           screenFrame.origin.y + (screenFrame.size.height - hudFrame.size.height) / 6)];
+}
+
+- (void)keyDown:(NSEvent *)event
+{
+    [super keyDown:event];
+    [[self windowController] fadeWindowIn];
+}
+
+@end
+
+//
+// HUD Window Controller
+//
+
+static const CGFloat windowHeight = 59;
+static const CGFloat windowWidth = 438;
+
+static const NSTimeInterval HUDWindowFadeOutDelay = 3;
+
+@implementation WebVideoFullscreenHUDWindowController
+
+- (id)init
+{
+    NSWindow* window = [[WebVideoFullscreenHUDWindow alloc] initWithContentRect:NSMakeRect(0, 0, windowWidth, windowHeight)
+                            styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO];
+    self = [super initWithWindow:window];
+    [window setDelegate:self];
+    [window release];
+    if (!self)
+        return nil;
+    [self windowDidLoad];
+    return self;
+}
+
+- (void)dealloc
+{
+    ASSERT(!_timelineUpdateTimer);
+    ASSERT(!_area);
+    [_timeline release];
+    [_remainingTimeText release];
+    [_elapsedTimeText release];
+    [_volumeSlider release];
+    [_playButton release];
+    [super dealloc];
+}
+
+- (void)setArea:(NSTrackingArea *)area
+{
+    if (area == _area)
+        return;
+    [_area release];
+    _area = [area retain];
+}
+
+- (id<WebVideoFullscreenHUDWindowControllerDelegate>)delegate
+{
+    return _delegate;
+}
+     
+- (void)setDelegate:(id<WebVideoFullscreenHUDWindowControllerDelegate>)delegate
+{
+    _delegate = delegate;
+}
+
+- (void)scheduleTimeUpdate
+{
+    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(unscheduleTimeUpdate) object:self];
+
+    // First, update right away, then schedule future update
+    [self updateTime];
+
+    [_timelineUpdateTimer invalidate];
+    [_timelineUpdateTimer release];
+
+    // Note that this creates a retain cycle between the window and us.
+    _timelineUpdateTimer = [[NSTimer timerWithTimeInterval:0.25 target:self selector:@selector(updateTime) userInfo:nil repeats:YES] retain];
+    [[NSRunLoop currentRunLoop] addTimer:_timelineUpdateTimer forMode:NSRunLoopCommonModes];
+}
+
+- (void)unscheduleTimeUpdate
+{
+    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(unscheduleTimeUpdate) object:nil];
+
+    [_timelineUpdateTimer invalidate];
+    [_timelineUpdateTimer release];
+    _timelineUpdateTimer = nil;
+}
+
+- (void)fadeWindowIn
+{
+    NSWindow *window = [self window];
+    if (![window isVisible])
+        [window setAlphaValue:0];
+
+    [window makeKeyAndOrderFront:self];
+    [[window animator] setAlphaValue:1];
+    [self scheduleTimeUpdate];
+
+    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(fadeWindowOut) object:nil];
+    if (!_mouseIsInHUD && [self playing])   // Don't fade out when paused.
+        [self performSelector:@selector(fadeWindowOut) withObject:nil afterDelay:HUDWindowFadeOutDelay];
+}
+
+- (void)fadeWindowOut
+{
+    [NSCursor setHiddenUntilMouseMoves:YES];
+    [[[self window] animator] setAlphaValue:0];
+    [self performSelector:@selector(unscheduleTimeUpdate) withObject:nil afterDelay:1];
+}
+
+- (void)closeWindow
+{
+    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(fadeWindowOut) object:nil];
+    [self unscheduleTimeUpdate];
+    NSWindow *window = [self window];
+    [[window contentView] removeTrackingArea:_area];
+    [self setArea:nil];
+    [window close];
+    [window setDelegate:nil];
+    [self setWindow:nil];
+}
+
+#ifndef HAVE_MEDIA_CONTROL
+enum {
+    WKMediaUIControlPlayPauseButton,
+    WKMediaUIControlRewindButton,
+    WKMediaUIControlFastForwardButton,
+    WKMediaUIControlExitFullscreenButton,
+    WKMediaUIControlVolumeDownButton,
+    WKMediaUIControlSlider,
+    WKMediaUIControlVolumeUpButton,
+    WKMediaUIControlTimeline
+};
+#endif
+
+static NSControl *createControlWithMediaUIControlType(int controlType, NSRect frame)
+{
+#ifdef HAVE_MEDIA_CONTROL
+    NSControl *control = WKCreateMediaUIControl(controlType);
+    [control setFrame:frame];
+    return control;
+#else
+    if (controlType == WKMediaUIControlSlider)
+        return [[NSSlider alloc] initWithFrame:frame];
+    return [[NSControl alloc] initWithFrame:frame];
+#endif
+}
+
+static NSTextField *createTimeTextField(NSRect frame)
+{
+    NSTextField *textField = [[NSTextField alloc] initWithFrame:frame];
+    [textField setTextColor:[NSColor whiteColor]];
+    [textField setBordered:NO];
+    [textField setFont:[NSFont systemFontOfSize:10]];
+    [textField setDrawsBackground:NO];
+    [textField setBezeled:NO];
+    [textField setEditable:NO];
+    [textField setSelectable:NO];
+    return textField;
+}
+
+- (void)windowDidLoad
+{
+    static const CGFloat kMargin = 9;
+    static const CGFloat kMarginTop = 9;
+    static const CGFloat kButtonSize = 25;
+    static const CGFloat kButtonMiniSize = 16;
+
+    NSWindow *window = [self window];
+    ASSERT(window);
+
+#ifdef HAVE_MEDIA_CONTROL
+    NSView *background = WKCreateMediaUIBackgroundView();
+#else
+    NSView *background = [[NSView alloc] init];
+#endif
+    [window setContentView:background];
+    _area = [[NSTrackingArea alloc] initWithRect:[background bounds] options:NSTrackingMouseEnteredAndExited|NSTrackingActiveAlways owner:self userInfo:nil];
+    [background addTrackingArea:_area];
+    [background release];    
+
+    NSView *contentView = [[self window] contentView];
+
+    CGFloat top = windowHeight - kMarginTop;
+    CGFloat center = (windowWidth - kButtonSize) / 2;
+    _playButton = createControlWithMediaUIControlType(WKMediaUIControlPlayPauseButton, NSMakeRect(center, top - kButtonSize, kButtonSize, kButtonSize));
+    [_playButton setTarget:self];
+    [_playButton setAction:@selector(playingChanged:)];
+    [contentView addSubview:_playButton];
+
+    CGFloat closeToRight = windowWidth - 2 * kMargin - kButtonMiniSize;
+    NSControl *exitFullscreenButton = createControlWithMediaUIControlType(WKMediaUIControlExitFullscreenButton, NSMakeRect(closeToRight, top - kButtonSize / 2 - kButtonMiniSize / 2, kButtonMiniSize, kButtonMiniSize));
+    [exitFullscreenButton setAction:@selector(exitFullscreen:)];
+    [exitFullscreenButton setTarget:self];
+    [contentView addSubview:exitFullscreenButton];
+    [exitFullscreenButton release];
+    
+    CGFloat left = kMargin;
+    NSControl *volumeDownButton = createControlWithMediaUIControlType(WKMediaUIControlVolumeDownButton, NSMakeRect(left, top - kButtonSize / 2 - kButtonMiniSize / 2, kButtonMiniSize, kButtonMiniSize));
+    [contentView addSubview:volumeDownButton];
+    [volumeDownButton release];
+
+    static const int volumeSliderWidth = 50;
+
+    left = kMargin + kButtonMiniSize;
+    _volumeSlider = createControlWithMediaUIControlType(WKMediaUIControlSlider, NSMakeRect(left, top - kButtonSize / 2 - kButtonMiniSize / 2, volumeSliderWidth, kButtonMiniSize));
+    [_volumeSlider setValue:[NSNumber numberWithDouble:[self maxVolume]] forKey:@"maxValue"];
+    [_volumeSlider setTarget:self];
+    [_volumeSlider setAction:@selector(volumeChanged:)];
+    [contentView addSubview:_volumeSlider];
+
+    left = kMargin + kButtonMiniSize + volumeSliderWidth + kButtonMiniSize / 2;
+    NSControl *button = createControlWithMediaUIControlType(WKMediaUIControlVolumeUpButton, NSMakeRect(left, top - kButtonSize / 2 - kButtonMiniSize / 2, kButtonMiniSize, kButtonMiniSize));
+    [contentView addSubview:button];
+    [button release];
+    
+    static const int timeTextWidth = 50;
+    static const int sliderHeight = 13;
+    static const int sliderMarginFixup = 4;
+
+#ifdef HAVE_MEDIA_CONTROL
+    _timeline = WKCreateMediaUIControl(WKMediaUIControlTimeline);
+#else
+    _timeline = [[NSSlider alloc] init];
+#endif
+    [_timeline setTarget:self];
+    [_timeline setAction:@selector(timelinePositionChanged:)];
+    [_timeline setFrame:NSMakeRect(kMargin + timeTextWidth + kMargin/2, kMargin - sliderMarginFixup, windowWidth - 2 * (kMargin - sliderMarginFixup) - kMargin * 2 - 2 * timeTextWidth, sliderHeight)];
+    [contentView addSubview:_timeline];
+
+    static const int timeTextHeight = 11;
+
+    _elapsedTimeText = createTimeTextField(NSMakeRect(kMargin, kMargin, timeTextWidth, timeTextHeight));
+    [contentView addSubview:_elapsedTimeText];
+
+    _remainingTimeText = createTimeTextField(NSMakeRect(windowWidth - kMargin - timeTextWidth, kMargin, timeTextWidth, timeTextHeight));
+    [contentView addSubview:_remainingTimeText];
+    
+    [window recalculateKeyViewLoop];
+    [window setInitialFirstResponder:_playButton];
+    [window center];
+}
+                                
+/*
+ *  Bindings
+ *
+ */
+
+- (void)updateVolume
+{
+    [_volumeSlider setDoubleValue:[self volume]];
+}
+
+- (void)updateTime
+{
+    [self updateVolume];
+
+    [_timeline setFloatValue:[self currentTime]];
+    [(NSSlider*)_timeline setMaxValue:[self duration]];
+
+    [_remainingTimeText setStringValue:[self remainingTimeText]];
+    [_elapsedTimeText setStringValue:[self elapsedTimeText]];
+}
+
+- (void)fastForward
+{
+}
+
+- (void)timelinePositionChanged:(id)sender
+{
+    [self setCurrentTime:[_timeline floatValue]];
+}
+
+- (float)currentTime
+{
+    return [_delegate mediaElement] ? [_delegate mediaElement]->currentTime() : 0;
+}
+
+- (void)setCurrentTime:(float)currentTime
+{
+    if (![_delegate mediaElement])
+        return;
+    WebCore::ExceptionCode e;
+    [_delegate mediaElement]->setCurrentTime(currentTime, e);
+}
+
+- (double)duration
+{
+    return [_delegate mediaElement] ? [_delegate mediaElement]->duration() : 0;
+}
+
+- (double)maxVolume
+{
+    // Set the volume slider resolution
+    return 100;
+}
+
+- (void)volumeChanged:(id)sender
+{
+    [self setVolume:[_volumeSlider doubleValue]];
+}
+
+- (double)volume
+{
+    return [_delegate mediaElement] ? [_delegate mediaElement]->volume() * [self maxVolume] : 0;
+}
+
+- (void)setVolume:(double)volume
+{
+    if (![_delegate mediaElement])
+        return;
+    WebCore::ExceptionCode e;
+    [_delegate mediaElement]->setVolume(volume / [self maxVolume], e);
+}
+
+- (void)playingChanged:(id)sender
+{
+    [self setPlaying:![self playing]];
+    
+    // Keep HUD visible when paused
+    if (![self playing])
+        [self fadeWindowIn];
+    else if (!_mouseIsInHUD) {
+        [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(fadeWindowOut) object:nil];
+        [self performSelector:@selector(fadeWindowOut) withObject:nil afterDelay:HUDWindowFadeOutDelay];
+    }
+}
+
+- (BOOL)playing
+{
+    if (![_delegate mediaElement])
+        return false;
+    return ![_delegate mediaElement]->canPlay();
+}
+
+- (void)setPlaying:(BOOL)playing
+{
+    if (![_delegate mediaElement])
+        return;
+
+    if (playing)
+        [_delegate mediaElement]->play();
+    else
+        [_delegate mediaElement]->pause();
+}
+
+static NSString *timeToString(double time)
+{
+    if (!isfinite(time))
+        time = 0;
+    int seconds = (int)fabsf(time); 
+    int hours = seconds / (60 * 60);
+    int minutes = (seconds / 60) % 60;
+    seconds %= 60;
+    if (hours) {
+        if (hours > 9)
+            return [NSString stringWithFormat:@"%s%02d:%02d:%02d", (time < 0 ? "-" : ""), hours, minutes, seconds];
+        else
+            return [NSString stringWithFormat:@"%s%01d:%02d:%02d", (time < 0 ? "-" : ""), hours, minutes, seconds];
+    }
+    else
+        return [NSString stringWithFormat:@"%s%02d:%02d", (time < 0 ? "-" : ""), minutes, seconds];
+    
+}
+
+static NSString *stringToTimeTextAttributed(NSString *string, NSTextAlignment align)
+{
+    NSShadow *blackShadow = [[NSShadow alloc] init];
+    [blackShadow setShadowColor:[NSColor blackColor]];
+    [blackShadow setShadowBlurRadius:0];
+    [blackShadow setShadowOffset:NSMakeSize(0, -1)];
+    NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
+    [style setAlignment:align];
+    NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:blackShadow, NSShadowAttributeName, style, NSParagraphStyleAttributeName, nil];
+    [style release];
+    [blackShadow release];
+
+    NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:string attributes:dict];
+    return [attrString autorelease];    
+}
+
+- (NSString *)remainingTimeText
+{
+    if (![_delegate mediaElement])
+        return @"";
+
+    // Negative number
+    return stringToTimeTextAttributed(timeToString([_delegate mediaElement]->currentTime() - [_delegate mediaElement]->duration()), NSLeftTextAlignment);
+}
+
+- (NSString *)elapsedTimeText
+{
+    if (![_delegate mediaElement])
+        return @"";
+
+    return stringToTimeTextAttributed(timeToString([_delegate mediaElement]->currentTime()), NSRightTextAlignment);
+}
+
+/*
+ *  Tracking area callbacks
+ *
+ */
+
+- (void)mouseEntered:(NSEvent *)theEvent
+{
+    // Make sure the HUD won't be hidden from now
+    _mouseIsInHUD = YES;
+    [self fadeWindowIn];
+}
+
+- (void)mouseExited:(NSEvent *)theEvent
+{
+    _mouseIsInHUD = NO;
+    [self fadeWindowIn];
+}
+
+/*
+ *  Other Interface callbacks
+ *
+ */
+
+- (void)rewind:(id)sender
+{
+    if (![_delegate mediaElement])
+        return;
+    [_delegate mediaElement]->rewind(30);
+}
+
+- (void)fastForward:(id)sender
+{
+    if (![_delegate mediaElement])
+        return;
+}
+
+- (void)exitFullscreen:(id)sender
+{
+    [_delegate requestExitFullscreen]; 
+}
+
+/*
+ *  Window callback
+ *
+ */
+
+- (void)windowDidExpose:(NSNotification *)notification
+{
+    [self scheduleTimeUpdate];
+}
+
+- (void)windowDidClose:(NSNotification *)notification
+{
+    [self unscheduleTimeUpdate];
+}
+
+@end
+
+#endif
index 4d31557af773a2cc63a953a78e1874e8f53f0ee6..a1eaac958822c765990f35d61f8e9072b68eca05 100644 (file)
@@ -93,6 +93,7 @@
 #import "WebTextIterator.h"
 #import "WebUIDelegate.h"
 #import "WebUIDelegatePrivate.h"
+#import "WebVideoFullscreenController.h"
 #import <CoreFoundation/CFSet.h>
 #import <Foundation/NSURLConnection.h>
 #import <WebCore/ApplicationCacheStorage.h>
@@ -997,6 +998,8 @@ static bool fastDocumentTeardownEnabled()
         return;
     }
 
+    [self _exitFullscreen];
+
     if (Frame* mainFrame = [self _mainCoreFrame])
         mainFrame->loader()->detachFromParent();
 
@@ -5614,6 +5617,45 @@ static void layerSyncRunLoopObserverCallBack(CFRunLoopObserverRef, CFRunLoopActi
 
 #endif
 
+#if ENABLE(VIDEO)
+
+- (void)_enterFullscreenForNode:(WebCore::Node*)node
+{
+    ASSERT(node->hasTagName(WebCore::HTMLNames::videoTag));
+    HTMLMediaElement* videoElement = static_cast<HTMLMediaElement*>(node);
+
+    if (_private->fullscreenController) {
+        if ([_private->fullscreenController mediaElement] == videoElement) {
+            // The backend may just warn us that the underlaying plaftormMovie()
+            // has changed. Just force an update.
+            [_private->fullscreenController setMediaElement:videoElement];
+            return; // No more to do.
+        }
+
+        // First exit Fullscreen for the old mediaElement.
+        [_private->fullscreenController mediaElement]->exitFullscreen();
+        // This previous call has to trigger _exitFullscreen,
+        // which has to clear _private->fullscreenController.
+        ASSERT(!_private->fullscreenController);
+    }
+    if (!_private->fullscreenController) {
+        _private->fullscreenController = [[WebVideoFullscreenController alloc] init];
+        [_private->fullscreenController setMediaElement:videoElement];
+        [_private->fullscreenController enterFullscreen:[[self window] screen]];        
+    }
+    else
+        [_private->fullscreenController setMediaElement:videoElement];
+}
+
+- (void)_exitFullscreen
+{
+    [_private->fullscreenController exitFullscreen];
+    [_private->fullscreenController release];
+    _private->fullscreenController = nil;
+}
+
+#endif
+
 @end
 
 #ifdef BUILDING_ON_LEOPARD
index a346e663e8fc7f2d386c9174de068eed221adc5f..6ec94a7405ccf35321c5043b5c4fc82c138d3993 100644 (file)
@@ -43,6 +43,9 @@ namespace WebCore {
 @class WebPreferences;
 @class WebTextCompletionController;
 @protocol WebFormDelegate;
+#if ENABLE(VIDEO)
+@class WebVideoFullscreenController;
+#endif
 
 extern BOOL applicationIsTerminating;
 extern int pluginDatabaseClientCount;
@@ -160,5 +163,8 @@ extern int pluginDatabaseClientCount;
     NSEvent *autoscrollTriggerEvent;
 
     CFRunLoopTimerRef updateMouseoverTimer;
+#if ENABLE(VIDEO)
+    WebVideoFullscreenController *fullscreenController;
+#endif
 }
 @end
index 6a8353287ffae6d44f8f1f5898ab3d3d373f2ee9..835f46eb1981cdf966a6737ac4483557f565b8fe 100644 (file)
@@ -81,6 +81,7 @@ int pluginDatabaseClientCount = 0;
     ASSERT(applicationIsTerminating || !page);
     ASSERT(applicationIsTerminating || !preferences);
     ASSERT(!insertionPasteboard);
+    ASSERT(!fullscreenController);
 
     [applicationNameForUserAgent release];
     [backgroundColor release];
@@ -100,6 +101,7 @@ int pluginDatabaseClientCount = 0;
 {
     ASSERT_MAIN_THREAD();
     ASSERT(!insertionPasteboard);
+    ASSERT(!fullscreenController);
 
     [super finalize];
 }
index be923f7b6334db8f4901921b6621ad3763600290..521aeee1eb7ae58742d85e8f4a55b60a1c6d51ac 100644 (file)
@@ -41,6 +41,7 @@ namespace WebCore {
     class KURL;
     class KeyboardEvent;
     class Page;
+    class Node;
 }
 #endif
 
@@ -163,4 +164,9 @@ namespace WebCore {
 
 - (void)_setInsertionPasteboard:(NSPasteboard *)pasteboard;
 
+#if ENABLE(VIDEO) && defined(__cplusplus)
+- (void)_enterFullscreenForNode:(WebCore::Node*)node;
+- (void)_exitFullscreen;
+#endif
+
 @end
diff --git a/WebKit/mac/WebView/WebWindowAnimation.h b/WebKit/mac/WebView/WebWindowAnimation.h
new file mode 100644 (file)
index 0000000..c73dcce
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#import <Cocoa/Cocoa.h>
+
+@interface WebWindowScaleAnimation : NSAnimation {
+@private
+    NSRect _initialFrame, _finalFrame, _realFrame;
+    NSWindow *_window; // (assign)
+    NSAnimation *_subAnimation; // (retain)
+    NSTimeInterval _hintedDuration;
+}
+- (id)initWithHintedDuration:(NSTimeInterval)duration window:(NSWindow *)window initalFrame:(NSRect)initialFrame finalFrame:(NSRect)finalFrame;
+
+- (void)setSubAnimation:(NSAnimation *)animation;
+
+- (NSRect)currentFrame;
+
+// Be sure to call setWindow:nil to clear the weak link _window when appropriate
+- (void)setWindow:(NSWindow *)window;
+@end
+
+
+@interface WebWindowFadeAnimation : NSAnimation {
+@private
+    CGFloat _initialAlpha, _finalAlpha;
+    NSWindow *_window; // (retain)
+    BOOL _isStopped;
+    
+}
+- (id)initWithDuration:(NSTimeInterval)duration window:(NSWindow *)window initialAlpha:(CGFloat)initialAlpha finalAlpha:(CGFloat)finalAlpha;
+
+- (CGFloat)currentAlpha;
+
+// Be sure to call setWindow:nil to clear the weak link _window when appropriate
+- (void)setWindow:(NSWindow *)window;
+@end
diff --git a/WebKit/mac/WebView/WebWindowAnimation.m b/WebKit/mac/WebView/WebWindowAnimation.m
new file mode 100644 (file)
index 0000000..8e56321
--- /dev/null
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#import "WebWindowAnimation.h"
+#import "WebKitSystemInterface.h"
+#import <wtf/Assertions.h>
+
+static const CGFloat slowMotionFactor = 10.;
+
+static NSTimeInterval WebWindowAnimationDurationFromDuration(NSTimeInterval duration)
+{
+    return ([[NSApp currentEvent] modifierFlags] & NSShiftKeyMask) ? duration * slowMotionFactor : duration;        
+}
+
+static NSRect scaledRect(NSRect _initialFrame, NSRect _finalFrame, double factor)
+{
+    NSRect currentRect = _initialFrame;
+    currentRect.origin.x += (NSMinX(_finalFrame) - NSMinX(_initialFrame)) * factor;
+    currentRect.origin.y += (NSMinY(_finalFrame) - NSMinY(_initialFrame)) * factor;
+    currentRect.size.width += (NSWidth(_finalFrame) - NSWidth(_initialFrame)) * factor;
+    currentRect.size.height += (NSHeight(_finalFrame) - NSHeight(_initialFrame)) * factor;
+    return currentRect;
+}
+
+static CGFloat squaredDistance(NSPoint point1, NSPoint point2)
+{
+    CGFloat deltaX = point1.x - point2.x;
+    CGFloat deltaY = point1.y - point2.y;
+    return deltaX * deltaX + deltaY * deltaY;
+}
+
+@implementation WebWindowScaleAnimation
+- (id)init
+{
+    self = [super init];
+    if (!self)
+        return nil;
+#ifndef BUILDING_ON_TIGER
+    [self setAnimationBlockingMode:NSAnimationNonblockingThreaded];
+#endif
+    [self setFrameRate:60.];
+    return self;
+}
+
+- (id)initWithHintedDuration:(NSTimeInterval)duration window:(NSWindow *)window initalFrame:(NSRect)initialFrame finalFrame:(NSRect)finalFrame
+{
+    self = [self init];
+    if (!self)
+        return nil;
+    _hintedDuration = duration;
+    _window = window;
+    _initialFrame = initialFrame;
+    _finalFrame = finalFrame;
+    _realFrame = [window frame];
+    return self;
+}
+
+- (void) dealloc
+{
+    [_window release];
+    [_subAnimation release];
+    [super dealloc];
+}
+
+- (void)setDuration:(NSTimeInterval)duration
+{
+    [super setDuration:WebWindowAnimationDurationFromDuration(duration)];
+}
+
+- (void)setWindow:(NSWindow *)window
+{
+    _window = window;
+}
+
+- (float)currentValue
+{
+    return 0.5 - 0.5 * cos(M_PI * (1 - [self currentProgress]));
+}
+
+- (NSRect)currentFrame
+{
+    return scaledRect(_finalFrame, _initialFrame, [self currentValue]);
+}
+
+- (void)setCurrentProgress:(NSAnimationProgress)progress
+{
+    if (!_window)
+        return;
+
+    [super setCurrentProgress:progress];
+
+    NSRect currentRect = [self currentFrame];
+#ifndef BUILDING_ON_TIGER
+    WKWindowSetScaledFrame(_window, currentRect, _realFrame);
+#else
+    [_window setFrame:currentRect display:YES];
+#endif
+    [_subAnimation setCurrentProgress:progress];
+}
+
+- (void)setSubAnimation:(NSAnimation *)animation
+{
+    id oldAnimation = _subAnimation;
+    _subAnimation = [animation retain];
+    [oldAnimation release];
+}
+
+- (NSTimeInterval)additionalDurationNeededToReachFinalFrame
+{
+    static const CGFloat maxAdditionalDuration = 1.0;
+    static const CGFloat speedFactor = 0.0001;
+    
+    CGFloat maxDist = squaredDistance(_initialFrame.origin, _finalFrame.origin);
+    CGFloat dist;
+    
+    dist = squaredDistance(NSMakePoint(NSMaxX(_initialFrame), NSMinY(_initialFrame)), NSMakePoint(NSMaxX(_finalFrame), NSMinY(_finalFrame)));
+    if (dist > maxDist)
+        maxDist = dist;
+    
+    dist = squaredDistance(NSMakePoint(NSMaxX(_initialFrame), NSMaxY(_initialFrame)), NSMakePoint(NSMaxX(_finalFrame), NSMaxY(_finalFrame)));
+    if (dist > maxDist)
+        maxDist = dist;
+    
+    dist = squaredDistance(NSMakePoint(NSMinX(_initialFrame), NSMinY(_initialFrame)), NSMakePoint(NSMinX(_finalFrame), NSMinY(_finalFrame)));
+    if (dist > maxDist)
+        maxDist = dist;
+    
+    return MIN(sqrt(maxDist) * speedFactor, maxAdditionalDuration);    
+}
+
+- (void)startAnimation
+{
+    // Compute extra time
+    if (_hintedDuration)
+        [self setDuration:_hintedDuration + [self additionalDurationNeededToReachFinalFrame]];
+    [super startAnimation];
+}
+
+- (void)stopAnimation
+{
+    _window = nil;
+    [super stopAnimation];
+    [_subAnimation stopAnimation];
+}
+@end
+
+@implementation WebWindowFadeAnimation
+- (id)init
+{
+    self = [super init];
+    if (!self)
+        return nil;
+#ifndef BUILDING_ON_TIGER
+    [self setAnimationBlockingMode:NSAnimationNonblockingThreaded];
+#endif
+    [self setFrameRate:60];
+    [self setAnimationCurve:NSAnimationEaseInOut];
+    return self;
+}
+
+- (id)initWithDuration:(NSTimeInterval)duration window:(NSWindow *)window initialAlpha:(CGFloat)initialAlpha finalAlpha:(CGFloat)finalAlpha
+{
+    self = [self init];
+    if (!self)
+        return nil;    
+    _window = window;
+    _initialAlpha = initialAlpha;
+    _finalAlpha = finalAlpha;
+    return self;
+}
+
+- (void)setDuration:(NSTimeInterval)duration
+{
+    [super setDuration:WebWindowAnimationDurationFromDuration(duration)];
+}
+
+- (CGFloat)currentAlpha
+{
+    return MAX(0.0, MIN(1.0, _initialAlpha + [self currentValue] * (_finalAlpha - _initialAlpha)));
+}
+
+- (void)setCurrentProgress:(NSAnimationProgress)progress
+{
+    if (_isStopped)
+        return;
+
+    ASSERT(_window);
+    [super setCurrentProgress:progress];
+
+#ifndef BUILDING_ON_TIGER
+    WKWindowSetAlpha(_window, [self currentAlpha]);
+#else
+    [_window setAlphaValue:[self currentAlpha]];
+#endif
+}
+
+- (void)setWindow:(NSWindow*)window
+{
+    _window = window;
+}
+
+- (void)stopAnimation
+{
+    // This is relevant when we are a sub animation of a scale animation.
+    // In this case we are hosted in the animated thread of the parent
+    // and even after [super stopAnimation], the parent might call
+    // setCurrrentProgress.
+    _isStopped = YES;
+
+    [super stopAnimation];
+}
+
+@end
+
index fc880ac541ee69afa66bb13577a40f18c7951274..6ad863dfb5749e2813feebebbd1990a2e71ee435 100644 (file)
@@ -1,3 +1,17 @@
+2009-10-05  Pierre d'Herbemont  <pdherbemont@webkit.org>
+
+        Reviewed by Simon Fraser
+        
+        Support fullscreen in MediaPlayer (Mac)
+        https://bugs.webkit.org/show_bug.cgi?id=26742
+        
+        New methods required for video fullscreen.
+
+        * WebKitSystemInterface.h:
+        * libWebKitSystemInterfaceLeopard.a:
+        * libWebKitSystemInterfaceSnowLeopard.a:
+        * libWebKitSystemInterfaceTiger.a:
+
 2009-10-02  Steve Falkenburg  <sfalken@apple.com>
 
         Windows build fix.
index 2c31cf90b46be55d56049334dc8cd5f5ac08b8c2..a97e6353cda32d1e705b3a3a1fcf8cab336c5de0 100644 (file)
@@ -229,6 +229,21 @@ BOOL WKHitTestMediaUIPart(int part, int themeStyle, CGRect bounds, CGPoint point
 void WKMeasureMediaUIPart(int part, int themeStyle, CGRect *bounds, CGSize *naturalSize);
 void WKDrawMediaUIPart(int part, int themeStyle, CGContextRef context, CGRect rect, unsigned state);
 void WKDrawMediaSliderTrack(int themeStyle, CGContextRef context, CGRect rect, float timeLoaded, float currentTime, float duration, unsigned state);
+NSView *WKCreateMediaUIBackgroundView(void);
+
+typedef enum {
+    WKMediaUIControlTimeline,
+    WKMediaUIControlSlider,
+    WKMediaUIControlPlayPauseButton,
+    WKMediaUIControlExitFullscreenButton,
+    WKMediaUIControlRewindButton,
+    WKMediaUIControlFastForwardButton,
+    WKMediaUIControlVolumeUpButton,
+    WKMediaUIControlVolumeDownButton
+
+} WKMediaUIControlType;
+    
+NSControl *WKCreateMediaUIControl(int controlType);
 
 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && defined(__x86_64__)
 mach_port_t WKInitializeRenderServer(void);
@@ -259,6 +274,11 @@ void WKSetCAAnimationValueFunction(CAPropertyAnimation*, NSString* function);
 unsigned WKInitializeMaximumHTTPConnectionCountPerHost(unsigned preferredConnectionCount);
 
 BOOL WKIsLatchingWheelEvent(NSEvent *);
+
+#ifndef BUILDING_ON_TIGER
+void WKWindowSetAlpha(NSWindow *window, float alphaValue);
+void WKWindowSetScaledFrame(NSWindow *window, NSRect scaleFrame, NSRect nonScaledFrame);
+#endif
     
 #ifdef __cplusplus
 }
index 1e9e637d22e97c7faf0c0e49e01b944785a56a06..60c801773b064cf29960046a81ab635dff24e9f6 100644 (file)
Binary files a/WebKitLibraries/libWebKitSystemInterfaceLeopard.a and b/WebKitLibraries/libWebKitSystemInterfaceLeopard.a differ
index 61daf461a44b5aec93e719bc96b9930b6e641526..a4b8ae73d81ad41bad6fc4523e33270f7a6e7a7e 100644 (file)
Binary files a/WebKitLibraries/libWebKitSystemInterfaceSnowLeopard.a and b/WebKitLibraries/libWebKitSystemInterfaceSnowLeopard.a differ
index 83fa4dc4dd6a653c2ead9ba07bc9e6b13cc03e13..9ef1695d59829d1ac44f5ce4e3dfcdca13ed1279 100644 (file)
Binary files a/WebKitLibraries/libWebKitSystemInterfaceTiger.a and b/WebKitLibraries/libWebKitSystemInterfaceTiger.a differ