[SCM] WebKit Debian packaging branch, webkit-1.1, updated. upstream/1.1.15.1-1414-gc69ee75

simon.fraser at apple.com simon.fraser at apple.com
Thu Oct 29 20:39:34 UTC 2009


The following commit has been merged in the webkit-1.1 branch:
commit e29cbe6fb801dd1df3d21000814fc553e167464b
Author: simon.fraser at apple.com <simon.fraser at apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Tue Oct 6 00:24:47 2009 +0000

    2009-10-05  Pierre d'Herbemont  <pdherbemont at 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.
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@49136 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 3d6afeb..643e1b9 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,65 @@
+2009-10-05  Pierre d'Herbemont  <pdherbemont at 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 at apple.com>
 
         Export a few more methods from Settings.h
diff --git a/WebCore/DerivedSources.make b/WebCore/DerivedSources.make
index ab794eb..157b01a 100644
--- a/WebCore/DerivedSources.make
+++ b/WebCore/DerivedSources.make
@@ -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
index 0000000..596fb4b
--- /dev/null
+++ b/WebCore/WebCore.Video.exp
@@ -0,0 +1,12 @@
+__ZN7WebCore16HTMLMediaElement4playEv
+__ZN7WebCore16HTMLMediaElement5pauseEv
+__ZNK7WebCore16HTMLMediaElement6volumeEv
+__ZNK7WebCore16HTMLMediaElement7canPlayEv
+__ZNK7WebCore16HTMLMediaElement8durationEv
+__ZN7WebCore16HTMLMediaElement9setVolumeEfRi
+__ZN7WebCore16HTMLMediaElement6rewindEf
+__ZN7WebCore16HTMLMediaElement10screenRectEv
+__ZNK7WebCore16HTMLMediaElement11currentTimeEv
+__ZNK7WebCore16HTMLMediaElement13platformMediaEv
+__ZN7WebCore16HTMLMediaElement14setCurrentTimeEfRi
+__ZN7WebCore16HTMLMediaElement14exitFullscreenEv
diff --git a/WebCore/WebCore.base.exp b/WebCore/WebCore.base.exp
index fccb26e..abd1309 100644
--- a/WebCore/WebCore.base.exp
+++ b/WebCore/WebCore.base.exp
@@ -719,6 +719,7 @@ __ZN7WebCore9HTMLNames7srcAttrE
 __ZN7WebCore9HTMLNames8frameTagE
 __ZN7WebCore9HTMLNames8hrefAttrE
 __ZN7WebCore9HTMLNames8inputTagE
+__ZN7WebCore9HTMLNames8videoTagE
 __ZN7WebCore9HTMLNames9iframeTagE
 __ZN7WebCore9HTMLNames9scriptTagE
 __ZN7WebCore9PageCache11setCapacityEi
diff --git a/WebCore/WebCore.xcodeproj/project.pbxproj b/WebCore/WebCore.xcodeproj/project.pbxproj
index 1c29133..23c58d4 100644
--- a/WebCore/WebCore.xcodeproj/project.pbxproj
+++ b/WebCore/WebCore.xcodeproj/project.pbxproj
@@ -6335,6 +6335,7 @@
 		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>"; };
@@ -10510,6 +10511,7 @@
 				449195970FBE17D700D9F824 /* WebCore.SVG.Filters.exp */,
 				449195960FBE17D700D9F824 /* WebCore.SVG.ForeignObject.exp */,
 				449195950FBE17D700D9F824 /* WebCore.Tiger.exp */,
+				63F371CD100E790000BBA87A /* WebCore.Video.exp */,
 				449195940FBE17D700D9F824 /* WebCore.VideoProxy.exp */,
 			);
 			name = Exports;
diff --git a/WebCore/html/HTMLMediaElement.cpp b/WebCore/html/HTMLMediaElement.cpp
index 2409d37..6768d5e 100644
--- a/WebCore/html/HTMLMediaElement.cpp
+++ b/WebCore/html/HTMLMediaElement.cpp
@@ -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
diff --git a/WebCore/html/HTMLMediaElement.h b/WebCore/html/HTMLMediaElement.h
index aa8d5f7..2b0ce32 100644
--- a/WebCore/html/HTMLMediaElement.h
+++ b/WebCore/html/HTMLMediaElement.h
@@ -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
diff --git a/WebCore/html/HTMLVideoElement.cpp b/WebCore/html/HTMLVideoElement.cpp
index ecd74e7..5bbc167 100644
--- a/WebCore/html/HTMLVideoElement.cpp
+++ b/WebCore/html/HTMLVideoElement.cpp
@@ -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)
diff --git a/WebCore/html/HTMLVideoElement.h b/WebCore/html/HTMLVideoElement.h
index dc9714a..096eb53 100644
--- a/WebCore/html/HTMLVideoElement.h
+++ b/WebCore/html/HTMLVideoElement.h
@@ -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;
 
diff --git a/WebCore/page/ChromeClient.h b/WebCore/page/ChromeClient.h
index 2d11275..5231603 100644
--- a/WebCore/page/ChromeClient.h
+++ b/WebCore/page/ChromeClient.h
@@ -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; }
 
diff --git a/WebCore/platform/graphics/MediaPlayer.cpp b/WebCore/platform/graphics/MediaPlayer.cpp
index 23410b2..03dff91 100644
--- a/WebCore/platform/graphics/MediaPlayer.cpp
+++ b/WebCore/platform/graphics/MediaPlayer.cpp
@@ -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();
diff --git a/WebCore/platform/graphics/MediaPlayer.h b/WebCore/platform/graphics/MediaPlayer.h
index 4c5ee5b..95efeb0 100644
--- a/WebCore/platform/graphics/MediaPlayer.h
+++ b/WebCore/platform/graphics/MediaPlayer.h
@@ -38,8 +38,24 @@
 #include <wtf/OwnPtr.h>
 #include <wtf/Noncopyable.h>
 
+#ifdef __OBJC__
+ at 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;
diff --git a/WebCore/platform/graphics/MediaPlayerPrivate.h b/WebCore/platform/graphics/MediaPlayerPrivate.h
index 9cc89c5..2f220b1 100644
--- a/WebCore/platform/graphics/MediaPlayerPrivate.h
+++ b/WebCore/platform/graphics/MediaPlayerPrivate.h
@@ -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;    
 
diff --git a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h
index bfaba9a..0a63626 100644
--- a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h
+++ b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h
@@ -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();
diff --git a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm
index 5a5c031..30d0c82 100644
--- a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm
+++ b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm
@@ -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)
diff --git a/WebCore/rendering/MediaControlElements.cpp b/WebCore/rendering/MediaControlElements.cpp
index 29e2e57..a17dc0e 100644
--- a/WebCore/rendering/MediaControlElements.cpp
+++ b/WebCore/rendering/MediaControlElements.cpp
@@ -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)
diff --git a/WebCore/rendering/RenderThemeMac.h b/WebCore/rendering/RenderThemeMac.h
index 85f141f..1d68c63 100644
--- a/WebCore/rendering/RenderThemeMac.h
+++ b/WebCore/rendering/RenderThemeMac.h
@@ -132,6 +132,8 @@ protected:
 
     // Media controls
     virtual String extraMediaControlsStyleSheet();
+
+    virtual bool shouldRenderMediaControlPart(ControlPart, Element*);
 #endif
 
 private:
diff --git a/WebCore/rendering/RenderThemeMac.mm b/WebCore/rendering/RenderThemeMac.mm
index eaf7cc4..ee9f41d 100644
--- a/WebCore/rendering/RenderThemeMac.mm
+++ b/WebCore/rendering/RenderThemeMac.mm
@@ -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
 {
diff --git a/WebKit/ChangeLog b/WebKit/ChangeLog
index 9b0b8b8..2693633 100644
--- a/WebKit/ChangeLog
+++ b/WebKit/ChangeLog
@@ -1,3 +1,14 @@
+2009-10-05  Pierre d'Herbemont  <pdherbemont at 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 at chromium.org>
 
         Reviewed by Timothy Hatcher.
diff --git a/WebKit/WebKit.xcodeproj/project.pbxproj b/WebKit/WebKit.xcodeproj/project.pbxproj
index 4d7a720..f1518d1 100644
--- a/WebKit/WebKit.xcodeproj/project.pbxproj
+++ b/WebKit/WebKit.xcodeproj/project.pbxproj
@@ -15,6 +15,12 @@
 		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 */; };
@@ -349,6 +355,12 @@
 		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>"; };
@@ -1118,12 +1130,18 @@
 				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;
@@ -1482,6 +1500,9 @@
 				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;
 		};
@@ -1817,6 +1838,9 @@
 				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;
 		};
diff --git a/WebKit/mac/ChangeLog b/WebKit/mac/ChangeLog
index 64baf97..d52b130 100644
--- a/WebKit/mac/ChangeLog
+++ b/WebKit/mac/ChangeLog
@@ -1,3 +1,57 @@
+2009-10-05  Pierre d'Herbemont  <pdherbemont at 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 at apple.com>
 
         Reviewed by Kevin Decker.
diff --git a/WebKit/mac/WebCoreSupport/WebChromeClient.h b/WebKit/mac/WebCoreSupport/WebChromeClient.h
index 1f83eff..a8f22f6 100644
--- a/WebKit/mac/WebCoreSupport/WebChromeClient.h
+++ b/WebKit/mac/WebCoreSupport/WebChromeClient.h
@@ -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:
diff --git a/WebKit/mac/WebCoreSupport/WebChromeClient.mm b/WebKit/mac/WebCoreSupport/WebChromeClient.mm
index c1d562e..58127bf 100644
--- a/WebKit/mac/WebCoreSupport/WebChromeClient.mm
+++ b/WebKit/mac/WebCoreSupport/WebChromeClient.mm
@@ -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
index 0000000..bb6a083
--- /dev/null
+++ b/WebKit/mac/WebView/WebVideoFullscreenController.h
@@ -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>
+
+ at protocol WebVideoFullscreenControllerDelegate;
+ at class WebVideoFullscreenHUDWindowController;
+ at class WebWindowFadeAnimation;
+
+ at interface WebVideoFullscreenController : NSWindowController
+{
+ at 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;
+
+ at end
+
+#endif
+
diff --git a/WebKit/mac/WebView/WebVideoFullscreenController.mm b/WebKit/mac/WebView/WebVideoFullscreenController.mm
new file mode 100644
index 0000000..ab1f114
--- /dev/null
+++ b/WebKit/mac/WebView/WebVideoFullscreenController.mm
@@ -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)
+
+
+ at 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;
+ at end
+
+ at interface WebVideoFullscreenController () <WebVideoFullscreenHUDWindowControllerDelegate>
+ at end
+
+ at 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];
+}
+ at end
+
+ at 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];
+}
+ at end
+
+#endif /* ENABLE(VIDEO) */
diff --git a/WebKit/mac/WebView/WebVideoFullscreenHUDWindowController.h b/WebKit/mac/WebView/WebVideoFullscreenHUDWindowController.h
new file mode 100644
index 0000000..c0dbac2
--- /dev/null
+++ b/WebKit/mac/WebView/WebVideoFullscreenHUDWindowController.h
@@ -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>
+
+ at protocol WebVideoFullscreenHUDWindowControllerDelegate;
+
+ at interface WebVideoFullscreenHUDWindowController : NSWindowController {
+ at 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;
+
+ at end
+
+ at protocol WebVideoFullscreenHUDWindowControllerDelegate <NSObject>
+- (void)requestExitFullscreen;
+- (WebCore::HTMLMediaElement*)mediaElement;
+ at end
+
+#endif
diff --git a/WebKit/mac/WebView/WebVideoFullscreenHUDWindowController.mm b/WebKit/mac/WebView/WebVideoFullscreenHUDWindowController.mm
new file mode 100644
index 0000000..824d292
--- /dev/null
+++ b/WebKit/mac/WebView/WebVideoFullscreenHUDWindowController.mm
@@ -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))
+
+ at 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;
+ at end
+
+
+//
+// HUD Window
+//
+
+ at interface WebVideoFullscreenHUDWindow : NSWindow
+ at end
+
+ at 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];
+}
+
+ at end
+
+//
+// HUD Window Controller
+//
+
+static const CGFloat windowHeight = 59;
+static const CGFloat windowWidth = 438;
+
+static const NSTimeInterval HUDWindowFadeOutDelay = 3;
+
+ at 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];
+}
+
+ at end
+
+#endif
diff --git a/WebKit/mac/WebView/WebView.mm b/WebKit/mac/WebView/WebView.mm
index 4d31557..a1eaac9 100644
--- a/WebKit/mac/WebView/WebView.mm
+++ b/WebKit/mac/WebView/WebView.mm
@@ -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
diff --git a/WebKit/mac/WebView/WebViewData.h b/WebKit/mac/WebView/WebViewData.h
index a346e66..6ec94a7 100644
--- a/WebKit/mac/WebView/WebViewData.h
+++ b/WebKit/mac/WebView/WebViewData.h
@@ -43,6 +43,9 @@ namespace WebCore {
 @class WebPreferences;
 @class WebTextCompletionController;
 @protocol WebFormDelegate;
+#if ENABLE(VIDEO)
+ at 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
diff --git a/WebKit/mac/WebView/WebViewData.mm b/WebKit/mac/WebView/WebViewData.mm
index 6a83532..835f46e 100644
--- a/WebKit/mac/WebView/WebViewData.mm
+++ b/WebKit/mac/WebView/WebViewData.mm
@@ -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];
 }
diff --git a/WebKit/mac/WebView/WebViewInternal.h b/WebKit/mac/WebView/WebViewInternal.h
index be923f7..521aeee 100644
--- a/WebKit/mac/WebView/WebViewInternal.h
+++ b/WebKit/mac/WebView/WebViewInternal.h
@@ -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
index 0000000..c73dcce
--- /dev/null
+++ b/WebKit/mac/WebView/WebWindowAnimation.h
@@ -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>
+
+ at interface WebWindowScaleAnimation : NSAnimation {
+ at 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;
+ at end
+
+
+ at interface WebWindowFadeAnimation : NSAnimation {
+ at 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;
+ at end
diff --git a/WebKit/mac/WebView/WebWindowAnimation.m b/WebKit/mac/WebView/WebWindowAnimation.m
new file mode 100644
index 0000000..8e56321
--- /dev/null
+++ b/WebKit/mac/WebView/WebWindowAnimation.m
@@ -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;
+}
+
+ at 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];
+}
+ at end
+
+ at 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];
+}
+
+ at end
+
diff --git a/WebKitLibraries/ChangeLog b/WebKitLibraries/ChangeLog
index fc880ac..6ad863d 100644
--- a/WebKitLibraries/ChangeLog
+++ b/WebKitLibraries/ChangeLog
@@ -1,3 +1,17 @@
+2009-10-05  Pierre d'Herbemont  <pdherbemont at 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 at apple.com>
 
         Windows build fix.
diff --git a/WebKitLibraries/WebKitSystemInterface.h b/WebKitLibraries/WebKitSystemInterface.h
index 2c31cf9..a97e635 100644
--- a/WebKitLibraries/WebKitSystemInterface.h
+++ b/WebKitLibraries/WebKitSystemInterface.h
@@ -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
 }
diff --git a/WebKitLibraries/libWebKitSystemInterfaceLeopard.a b/WebKitLibraries/libWebKitSystemInterfaceLeopard.a
index 1e9e637..60c8017 100644
Binary files a/WebKitLibraries/libWebKitSystemInterfaceLeopard.a and b/WebKitLibraries/libWebKitSystemInterfaceLeopard.a differ
diff --git a/WebKitLibraries/libWebKitSystemInterfaceSnowLeopard.a b/WebKitLibraries/libWebKitSystemInterfaceSnowLeopard.a
index 61daf46..a4b8ae7 100644
Binary files a/WebKitLibraries/libWebKitSystemInterfaceSnowLeopard.a and b/WebKitLibraries/libWebKitSystemInterfaceSnowLeopard.a differ
diff --git a/WebKitLibraries/libWebKitSystemInterfaceTiger.a b/WebKitLibraries/libWebKitSystemInterfaceTiger.a
index 83fa4dc..9ef1695 100644
Binary files a/WebKitLibraries/libWebKitSystemInterfaceTiger.a and b/WebKitLibraries/libWebKitSystemInterfaceTiger.a differ

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list