[SCM] WebKit Debian packaging branch, webkit-1.2, updated. upstream/1.1.90-6072-g9a69373

cmarrin at apple.com cmarrin at apple.com
Thu Apr 8 00:58:37 UTC 2010


The following commit has been merged in the webkit-1.2 branch:
commit 4382d62ff82c80321ce0d4b819a90940a5346f65
Author: cmarrin at apple.com <cmarrin at apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Fri Jan 8 19:23:40 2010 +0000

            Implement full-screen video for Windows
            https://bugs.webkit.org/show_bug.cgi?id=31318
    
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@52998 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 1619601..effa7fb 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,29 @@
+2010-01-08  Chris Marrin  <cmarrin at apple.com>
+
+        Reviewed by Adam Roben.
+
+        Implement full-screen video for Windows
+        https://bugs.webkit.org/show_bug.cgi?id=31318
+        
+        This is mostly support logic for taking video
+        into and out of full-screen. It also contains the
+        QTMovieWin piece which adds support for the actual
+        full-screen window itself. Events from the window
+        are sent to the FullscreenVideosController for handling.
+
+        * loader/FrameLoader.cpp:
+        (WebCore::FrameLoader::addData):
+        * platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h:
+        (WebCore::MediaPlayerPrivate::supportsFullscreen):
+        (WebCore::MediaPlayerPrivate::platformMedia):
+        * platform/graphics/win/QTMovieWin.cpp:
+        (QTMovieWinPrivate::QTMovieWinPrivate):
+        (QTMovieWin::initializeQuickTime):
+        (QTMovieWin::_handleMessages):
+        (QTMovieWin::enterFullscreen):
+        (QTMovieWin::exitFullscreen):
+        * platform/graphics/win/QTMovieWin.h:
+
 2010-01-08  Matt Perry  <mpcomplete at chromium.org>
 
         Reviewed by Adam Barth.
diff --git a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp
index a5beea1..7f20418 100644
--- a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp
+++ b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp
@@ -88,6 +88,18 @@ MediaPlayerPrivate::~MediaPlayerPrivate()
 {
 }
 
+bool MediaPlayerPrivate::supportsFullscreen() const
+{
+    return true;
+}
+
+PlatformMedia MediaPlayerPrivate::platformMedia() const
+{
+    PlatformMedia p;
+    p.qtMovie = reinterpret_cast<QTMovie*>(m_qtMovie.get());
+    return p;
+}
+
 class TaskTimer : TimerBase {
 public:
     static void initialize();
diff --git a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h
index 2bccbbf..c035bf1 100644
--- a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h
+++ b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h
@@ -53,6 +53,9 @@ public:
 private:
     MediaPlayerPrivate(MediaPlayer*);
 
+    virtual bool supportsFullscreen() const;
+    virtual PlatformMedia platformMedia() const;
+
     IntSize naturalSize() const;
     bool hasVideo() const;
     bool hasAudio() const;
diff --git a/WebCore/platform/graphics/win/QTMovieWin.cpp b/WebCore/platform/graphics/win/QTMovieWin.cpp
index 2d4c2ea..c7aad39 100644
--- a/WebCore/platform/graphics/win/QTMovieWin.cpp
+++ b/WebCore/platform/graphics/win/QTMovieWin.cpp
@@ -24,18 +24,15 @@
  */
 #include "config.h"
 
-#include <windows.h>
-
 #include "QTMovieWin.h"
 
 // Put Movies.h first so build failures here point clearly to QuickTime
 #include <Movies.h>
-#include <QuickTimeComponents.h>
-#include <GXMath.h>
-#include <QTML.h>
 
 #include "QTMovieWinTimer.h"
-
+#include <GXMath.h>
+#include <QTML.h>
+#include <QuickTimeComponents.h>
 #include <wtf/Assertions.h>
 #include <wtf/HashSet.h>
 #include <wtf/Noncopyable.h>
@@ -50,6 +47,7 @@ static const long subTitleTrackType = 'sbtl';
 static const long mpeg4ObjectDescriptionTrackType = 'odsm';
 static const long mpeg4SceneDescriptionTrackType = 'sdsm';
 static const long closedCaptionDisplayPropertyID = 'disp';
+static LPCTSTR fullscreenQTMovieWinPointerProp = TEXT("fullscreenQTMovieWinPointer");
 
 // Resizing GWorlds is slow, give them a minimum size so size of small 
 // videos can be animated smoothly
@@ -130,6 +128,11 @@ public:
 #if !ASSERT_DISABLED
     bool m_scaleCached;
 #endif
+    WindowPtr m_fullscreenWindow;
+    GWorldPtr m_fullscreenOrigGWorld;
+    Rect m_fullscreenRect;
+    QTMovieWinFullscreenClient* m_fullscreenClient;
+    char* m_fullscreenRestoreState;
 };
 
 QTMovieWinPrivate::QTMovieWinPrivate()
@@ -159,11 +162,19 @@ QTMovieWinPrivate::QTMovieWinPrivate()
 #if !ASSERT_DISABLED
     , m_scaleCached(false)
 #endif
+    , m_fullscreenWindow(0)
+    , m_fullscreenOrigGWorld(0)
+    , m_fullscreenClient(0)
+    , m_fullscreenRestoreState(0)
 {
+    Rect rect = { 0, 0, 0, 0 };
+    m_fullscreenRect = rect;
 }
 
 QTMovieWinPrivate::~QTMovieWinPrivate()
 {
+    ASSERT(!m_fullscreenWindow);
+
     endTask();
     if (m_gWorld)
         deleteGWorld();
@@ -359,7 +370,7 @@ void QTMovieWinPrivate::createGWorld()
     bounds.left = 0; 
     bounds.right = m_gWorldWidth;
     bounds.bottom = m_gWorldHeight;
-    OSErr err = QTNewGWorld(&m_gWorld, k32BGRAPixelFormat, &bounds, NULL, NULL, NULL); 
+    OSErr err = QTNewGWorld(&m_gWorld, k32BGRAPixelFormat, &bounds, 0, 0, 0); 
     if (err) 
         return;
     GetMovieGWorld(m_movie, &m_savedGWorld, 0);
@@ -729,7 +740,7 @@ void QTMovieWin::load(CFURLRef url, bool preservesPitch)
     moviePropCount++; 
 
     ASSERT(moviePropCount <= sizeof(movieProps)/sizeof(movieProps[0]));
-    m_private->m_loadError = NewMovieFromProperties(moviePropCount, movieProps, 0, NULL, &m_private->m_movie);
+    m_private->m_loadError = NewMovieFromProperties(moviePropCount, movieProps, 0, 0, &m_private->m_movie);
 
 end:
     m_private->startTask();
@@ -953,7 +964,7 @@ static void initializeSupportedTypes()
                 continue;
             if (!(infoCD.componentFlags & hasMovieImportMIMEList))
                 continue;
-            QTAtomContainer mimeList = NULL;
+            QTAtomContainer mimeList = 0;
             err = MovieImportGetMIMETypeList((ComponentInstance)comp, &mimeList);
             if (err || !mimeList)
                 continue;
@@ -962,7 +973,7 @@ static void initializeSupportedTypes()
             QTLockContainer(mimeList);
             int typeCount = QTCountChildrenOfType(mimeList, kParentAtomIsContainer, kMimeInfoMimeTypeTag);
             for (int typeIndex = 1; typeIndex <= typeCount; typeIndex++) {
-                QTAtom mimeTag = QTFindChildByIndex(mimeList, 0, kMimeInfoMimeTypeTag, typeIndex, NULL);
+                QTAtom mimeTag = QTFindChildByIndex(mimeList, 0, kMimeInfoMimeTypeTag, typeIndex, 0);
                 if (!mimeTag)
                     continue;
                 char* atomData;
@@ -980,7 +991,7 @@ static void initializeSupportedTypes()
                 if (strncmp(typeBuffer, "audio/", 6) && strncmp(typeBuffer, "video/", 6))
                     continue;
 
-                CFStringRef cfMimeType = CFStringCreateWithCString(NULL, typeBuffer, kCFStringEncodingUTF8);
+                CFStringRef cfMimeType = CFStringCreateWithCString(0, typeBuffer, kCFStringEncodingUTF8);
                 if (!cfMimeType)
                     continue;
 
@@ -1040,7 +1051,7 @@ bool QTMovieWin::initializeQuickTime()
     if (!initialized) {
         initialized = true;
         // Initialize and check QuickTime version
-        OSErr result = InitializeQTML(0);
+        OSErr result = InitializeQTML(kInitializeQTMLEnableDoubleBufferedSurface);
         if (result == noErr)
             result = Gestalt(gestaltQuickTime, &quickTimeVersion);
         if (result != noErr) {
@@ -1058,15 +1069,80 @@ bool QTMovieWin::initializeQuickTime()
     return initializationSucceeded;
 }
 
+LRESULT QTMovieWin::fullscreenWndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+    QTMovieWin* movie = static_cast<QTMovieWin*>(GetProp(wnd, fullscreenQTMovieWinPointerProp));
+
+    if (message == WM_DESTROY)
+        RemoveProp(wnd, fullscreenQTMovieWinPointerProp);
+
+    if (!movie)
+        return DefWindowProc(wnd, message, wParam, lParam);
+
+    return movie->m_private->m_fullscreenClient->fullscreenClientWndProc(wnd, message, wParam, lParam);
+}
+
+HWND QTMovieWin::enterFullscreen(QTMovieWinFullscreenClient* client)
+{
+    m_private->m_fullscreenClient = client;
+    
+    BeginFullScreen(&m_private->m_fullscreenRestoreState, 0, 0, 0, &m_private->m_fullscreenWindow, 0, fullScreenAllowEvents); 
+    QTMLSetWindowWndProc(m_private->m_fullscreenWindow, fullscreenWndProc);
+    CreatePortAssociation(GetPortNativeWindow(m_private->m_fullscreenWindow), 0, 0);
+
+    GetMovieBox(m_private->m_movie, &m_private->m_fullscreenRect);
+    GetMovieGWorld(m_private->m_movie, &m_private->m_fullscreenOrigGWorld, 0);
+    SetMovieGWorld(m_private->m_movie, reinterpret_cast<CGrafPtr>(m_private->m_fullscreenWindow), GetGWorldDevice(reinterpret_cast<CGrafPtr>(m_private->m_fullscreenWindow)));
+
+    // Set the size of the box to preserve aspect ratio
+    Rect rect = m_private->m_fullscreenWindow->portRect;
+
+    float movieRatio = static_cast<float>(m_private->m_width) / m_private->m_height;
+    int windowWidth =  rect.right - rect.left;
+    int windowHeight = rect.bottom - rect.top;
+    float windowRatio = static_cast<float>(windowWidth) / windowHeight;
+    int actualWidth = (windowRatio > movieRatio) ? (windowHeight * movieRatio) : windowWidth;
+    int actualHeight = (windowRatio < movieRatio) ? (windowWidth / movieRatio) : windowHeight;
+    int offsetX = (windowWidth - actualWidth) / 2;
+    int offsetY = (windowHeight - actualHeight) / 2;
+
+    rect.left = offsetX;
+    rect.right = offsetX + actualWidth;
+    rect.top = offsetY;
+    rect.bottom = offsetY + actualHeight;
+
+    SetMovieBox(m_private->m_movie, &rect);
+    ShowHideTaskBar(true);
+
+    // Set the 'this' pointer on the HWND
+    HWND wnd = static_cast<HWND>(GetPortNativeWindow(m_private->m_fullscreenWindow));
+    SetProp(wnd, fullscreenQTMovieWinPointerProp, static_cast<HANDLE>(this));
+
+    return wnd;
+}
+
+void QTMovieWin::exitFullscreen()
+{
+    if (!m_private->m_fullscreenWindow)
+        return;
+
+    HWND wnd = static_cast<HWND>(GetPortNativeWindow(m_private->m_fullscreenWindow));
+    DestroyPortAssociation(reinterpret_cast<CGrafPtr>(m_private->m_fullscreenWindow));
+    SetMovieGWorld(m_private->m_movie, m_private->m_fullscreenOrigGWorld, 0);
+    EndFullScreen(m_private->m_fullscreenRestoreState, 0L);
+    SetMovieBox(m_private->m_movie, &m_private->m_fullscreenRect);
+    m_private->m_fullscreenWindow = 0;
+}
+
 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
 {
     switch (fdwReason) {
-        case DLL_PROCESS_ATTACH:
-            return TRUE;
-        case DLL_PROCESS_DETACH:
-        case DLL_THREAD_ATTACH:
-        case DLL_THREAD_DETACH:
-            return FALSE;
+    case DLL_PROCESS_ATTACH:
+        return TRUE;
+    case DLL_PROCESS_DETACH:
+    case DLL_THREAD_ATTACH:
+    case DLL_THREAD_DETACH:
+        return FALSE;
     }
     ASSERT_NOT_REACHED();
     return FALSE;
diff --git a/WebCore/platform/graphics/win/QTMovieWin.h b/WebCore/platform/graphics/win/QTMovieWin.h
index 778f9aa..796b756 100644
--- a/WebCore/platform/graphics/win/QTMovieWin.h
+++ b/WebCore/platform/graphics/win/QTMovieWin.h
@@ -27,6 +27,7 @@
 #define QTMovieWin_h
 
 #include <Unicode.h>
+#include <windows.h>
 
 #ifdef QTMOVIEWIN_EXPORTS
 #define QTMOVIEWIN_API __declspec(dllexport)
@@ -45,6 +46,11 @@ public:
     virtual void movieNewImageAvailable(QTMovieWin*) = 0;
 };
 
+class QTMovieWinFullscreenClient {
+public:
+    virtual LRESULT fullscreenClientWndProc(HWND, UINT message, WPARAM, LPARAM) = 0;
+};
+
 enum {
     QTMovieLoadStateError = -1L,
     QTMovieLoadStateLoaded  = 2000L,
@@ -104,8 +110,13 @@ public:
     static unsigned countSupportedTypes();
     static void getSupportedType(unsigned index, const UChar*& str, unsigned& len);
 
+    // Returns the full-screen window created
+    HWND enterFullscreen(QTMovieWinFullscreenClient*);
+    void exitFullscreen();
+
 private:
     void load(CFURLRef, bool preservesPitch);
+    static LRESULT fullscreenWndProc(HWND, UINT message, WPARAM, LPARAM);
 
     QTMovieWinPrivate* m_private;
     bool m_disabled;
diff --git a/WebKit/win/ChangeLog b/WebKit/win/ChangeLog
index 283a8a0..78b924f 100644
--- a/WebKit/win/ChangeLog
+++ b/WebKit/win/ChangeLog
@@ -1,3 +1,45 @@
+2010-01-08  Chris Marrin  <cmarrin at apple.com>
+
+        Reviewed by Adam Roben.
+
+        Implement full-screen video for Windows
+        https://bugs.webkit.org/show_bug.cgi?id=31318
+        
+        This adds a full-screen controller, FullscreenVideoController, 
+        which manages going in and out of full-screen. The actual 
+        full-screen window is created and managed by logic added 
+        to QTMovieWin. FullscreenVideoController also creates and
+        manages a HUD. The HUD renders and manages events to
+        control the playing video. Movie controller events go to 
+        FullscreenVideoController which then sends them to HTMLMediaElement, 
+        which is passed to the controller by WebView, which gets the call 
+        to go into full-screen mode from HTMLMediaElement via 
+        ChromeClient.
+        
+        I've also updated the icons so the related sets (Play/Pause and
+        volume high/volume low/exit fullscreen) are the same size. This 
+        allows me to position them using common code.
+
+        * WebCoreSupport/WebChromeClient.cpp:
+        (WebChromeClient::supportsFullscreenForNode):
+        (WebChromeClient::enterFullscreenForNode):
+        (WebChromeClient::exitFullscreenForNode):
+        * WebCoreSupport/WebChromeClient.h:
+        * WebKit.vcproj/WebKit.vcproj:
+        * WebKit.vcproj/fsVideoAudioVolumeHigh.png:
+        * WebKit.vcproj/fsVideoAudioVolumeLow.png:
+        * WebKit.vcproj/fsVideoExitFullscreen.png:
+        * WebKit.vcproj/fsVideoPause.png:
+        * WebKit.vcproj/fsVideoPlay.png:
+        * WebKitDLL.cpp:
+        (loadResourceIntoBuffer):
+        * FullscreenVideoController.cpp: Added.
+        * FullscreenVideoController.h: Added.
+        * WebView.cpp:
+        (WebView::enterFullscreenForNode):
+        (WebView::exitFullscreen):
+        * WebView.h:
+
 2010-01-08  Brent Fulgham  <bfulgham at webkit.org>
 
         Unreviewed correction. 
diff --git a/WebKit/win/FullscreenVideoController.cpp b/WebKit/win/FullscreenVideoController.cpp
new file mode 100644
index 0000000..6b8e5ac
--- /dev/null
+++ b/WebKit/win/FullscreenVideoController.cpp
@@ -0,0 +1,615 @@
+/*
+ * Copyright (C) 2010 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. 
+ */
+
+#include "config.h"
+
+#if ENABLE(VIDEO)
+
+#include "FullscreenVideoController.h"
+
+#include "WebKitDLL.h"
+#include <ApplicationServices/ApplicationServices.h>
+#include <WebCore/BitmapInfo.h>
+#include <WebCore/Font.h>
+#include <WebCore/FontSelector.h>
+#include <WebCore/GraphicsContext.h>
+#include <WebCore/TextRun.h>
+#include <WebKitSystemInterface/WebKitSystemInterface.h>
+#include <windowsx.h>
+#include <wtf/StdLibExtras.h>
+
+using namespace std;
+using namespace WebCore;
+
+static const float timerInterval = 0.033;
+
+// HUD Size
+static const int windowHeight = 59;
+static const int windowWidth = 438;
+
+// Margins and button sizes
+static const int margin = 9;
+static const int marginTop = 9;
+static const int buttonSize = 25;
+static const int buttonMiniSize = 16;
+static const int volumeSliderWidth = 50;
+static const int timeSliderWidth = 310;
+static const int sliderHeight = 8;
+static const int volumeSliderButtonSize = 10;
+static const int timeSliderButtonSize = 8;
+static const int textSize = 11;
+static const float initialHUDPositionY = 0.9; // Initial Y position of HUD in percentage from top of screen
+
+// Background values
+static const int borderRadius = 12;
+static const int borderThickness = 2;
+
+// Colors
+static const unsigned int backgroundColor = 0xA0202020;
+static const unsigned int borderColor = 0xFFA0A0A0;
+static const unsigned int sliderGutterColor = 0xFF141414;
+static const unsigned int sliderButtonColor = 0xFF808080;
+static const unsigned int textColor = 0xFFFFFFFF;
+
+HUDButton::HUDButton(HUDButtonType type, const IntPoint& position)
+    : HUDWidget(IntRect(position, IntSize()))
+    , m_type(type)
+    , m_showAltButton(false)
+{
+    const char* buttonResource = 0;
+    const char* buttonResourceAlt = 0;
+    switch (m_type) {
+    case PlayPauseButton:
+        buttonResource = "fsVideoPlay";
+        buttonResourceAlt = "fsVideoPause";
+        break;
+    case TimeSliderButton:
+        break;
+    case VolumeUpButton:
+        buttonResource = "fsVideoAudioVolumeHigh";
+        break;
+    case VolumeSliderButton:
+        break;
+    case VolumeDownButton:
+        buttonResource = "fsVideoAudioVolumeLow";
+        break;
+    case ExitFullscreenButton:
+        buttonResource = "fsVideoExitFullscreen";
+        break;
+    }
+
+    if (buttonResource) {
+        m_buttonImage = Image::loadPlatformResource(buttonResource);
+        m_rect.setWidth(m_buttonImage->width());
+        m_rect.setHeight(m_buttonImage->height());
+    }
+    if (buttonResourceAlt)
+        m_buttonImageAlt = Image::loadPlatformResource(buttonResourceAlt);
+}
+
+void HUDButton::draw(GraphicsContext& context)
+{
+    Image* image = (m_showAltButton && m_buttonImageAlt) ? m_buttonImageAlt.get() : m_buttonImage.get();
+    context.drawImage(image, DeviceColorSpace, m_rect.location());
+}
+
+HUDSlider::HUDSlider(HUDSliderButtonShape shape, int buttonSize, const IntRect& rect)
+    : HUDWidget(rect)
+    , m_buttonShape(shape)
+    , m_buttonSize(buttonSize)
+    , m_buttonPosition(0)
+    , m_dragStartOffset(0)
+{
+}
+
+void HUDSlider::draw(GraphicsContext& context)
+{
+    // Draw gutter
+    IntSize radius(m_rect.height() / 2, m_rect.height() / 2);
+    context.fillRoundedRect(m_rect, radius, radius, radius, radius, Color(sliderGutterColor), DeviceColorSpace);
+
+    // Draw button
+    context.setStrokeColor(Color(sliderButtonColor), DeviceColorSpace);
+    context.setFillColor(Color(sliderButtonColor), DeviceColorSpace);
+
+    if (m_buttonShape == RoundButton) {
+        context.drawEllipse(IntRect(m_rect.location().x() + m_buttonPosition, m_rect.location().y() - (m_buttonSize - m_rect.height()) / 2, m_buttonSize, m_buttonSize));
+        return;
+    }
+
+    // Draw a diamond
+    FloatPoint points[4];
+    float half = static_cast<float>(m_buttonSize) / 2;
+    points[0].setX(m_rect.location().x() + m_buttonPosition + half);
+    points[0].setY(m_rect.location().y());
+    points[1].setX(m_rect.location().x() + m_buttonPosition + m_buttonSize);
+    points[1].setY(m_rect.location().y() + half);
+    points[2].setX(m_rect.location().x() + m_buttonPosition + half);
+    points[2].setY(m_rect.location().y() + m_buttonSize);
+    points[3].setX(m_rect.location().x() + m_buttonPosition);
+    points[3].setY(m_rect.location().y() + half);
+    context.drawConvexPolygon(4, points, true);
+}
+
+void HUDSlider::drag(const IntPoint& point, bool start)
+{
+    if (start) {
+        // When we start, we need to snap the slider position to the x position if we clicked the gutter.
+        // But if we click the button, we need to drag relative to where we clicked down. We only need
+        // to check X because we would not even get here unless Y were already inside.
+        int relativeX = point.x() - m_rect.location().x();
+        if (relativeX >= m_buttonPosition && relativeX <= m_buttonPosition + m_buttonSize)
+            m_dragStartOffset = point.x() - m_buttonPosition;
+        else
+            m_dragStartOffset = m_rect.location().x() + m_buttonSize / 2;
+    }
+
+    m_buttonPosition = max(0, min(m_rect.width() - m_buttonSize, point.x() - m_dragStartOffset));
+}
+
+FullscreenVideoController::FullscreenVideoController()
+    : m_hudWindow(0)
+    , m_videoWindow(0)
+    , m_playPauseButton(HUDButton::PlayPauseButton, IntPoint((windowWidth - buttonSize) / 2, marginTop))
+    , m_timeSliderButton(HUDButton::TimeSliderButton, IntPoint(0, 0))
+    , m_volumeUpButton(HUDButton::VolumeUpButton, IntPoint(margin + buttonMiniSize + volumeSliderWidth + buttonMiniSize / 2, marginTop + (buttonSize - buttonMiniSize) / 2))
+    , m_volumeSliderButton(HUDButton::VolumeSliderButton, IntPoint(0, 0))
+    , m_volumeDownButton(HUDButton::VolumeDownButton, IntPoint(margin, marginTop + (buttonSize - buttonMiniSize) / 2))
+    , m_exitFullscreenButton(HUDButton::ExitFullscreenButton, IntPoint(windowWidth - 2 * margin - buttonMiniSize, marginTop + (buttonSize - buttonMiniSize) / 2))
+    , m_volumeSlider(HUDSlider::RoundButton, volumeSliderButtonSize, IntRect(IntPoint(margin + buttonMiniSize, marginTop + (buttonSize - buttonMiniSize) / 2 + buttonMiniSize / 2 - sliderHeight / 2), IntSize(volumeSliderWidth, sliderHeight)))
+    , m_timeSlider(HUDSlider::DiamondButton, timeSliderButtonSize, IntRect(IntPoint(windowWidth / 2 - timeSliderWidth / 2, windowHeight - margin - sliderHeight), IntSize(timeSliderWidth, sliderHeight)))
+    , m_hitWidget(0)
+    , m_movingWindow(false)
+    , m_timer(this, &FullscreenVideoController::timerFired)
+{
+}
+
+FullscreenVideoController::~FullscreenVideoController()
+{
+    if (movie())
+        movie()->exitFullscreen();
+}
+
+QTMovieWin* FullscreenVideoController::movie() const
+{
+    return m_mediaElement ? reinterpret_cast<QTMovieWin*>(m_mediaElement->platformMedia().qtMovie) : 0;
+}
+
+void FullscreenVideoController::setMediaElement(HTMLMediaElement* mediaElement)
+{
+    if (mediaElement == m_mediaElement)
+        return;
+
+    m_mediaElement = mediaElement;
+    if (!m_mediaElement) {
+        // Can't do full-screen, just get out
+        exitFullscreen();
+    }
+}
+
+void FullscreenVideoController::enterFullscreen()
+{
+    if (!movie())
+        return;
+
+    m_videoWindow = movie()->enterFullscreen(this);
+
+    RECT windowRect;
+    GetClientRect(m_videoWindow, &windowRect);
+    m_fullscreenSize.setWidth(windowRect.right - windowRect.left);
+    m_fullscreenSize.setHeight(windowRect.bottom - windowRect.top);
+
+    createHUDWindow();
+}
+
+void FullscreenVideoController::exitFullscreen()
+{
+    if (movie())
+        movie()->exitFullscreen();
+
+    m_videoWindow = 0;
+    SetWindowLongPtr(m_hudWindow, 0, 0);
+    DestroyWindow(m_hudWindow);
+    m_hudWindow = 0;
+}
+
+bool FullscreenVideoController::canPlay() const
+{
+    return m_mediaElement && m_mediaElement->canPlay();
+}
+
+void FullscreenVideoController::play()
+{
+    if (m_mediaElement)
+        m_mediaElement->play();
+}
+
+void FullscreenVideoController::pause()
+{
+    if (m_mediaElement)
+        m_mediaElement->pause();
+}
+
+float FullscreenVideoController::volume() const
+{
+    return m_mediaElement ? m_mediaElement->volume() : 0;
+}
+
+void FullscreenVideoController::setVolume(float volume)
+{
+    if (m_mediaElement) {
+        ExceptionCode ec;
+        m_mediaElement->setVolume(volume, ec);
+    }
+}
+
+float FullscreenVideoController::currentTime() const
+{
+    return m_mediaElement ? m_mediaElement->currentTime() : 0;
+}
+
+void FullscreenVideoController::setCurrentTime(float value)
+{
+    if (m_mediaElement) {
+        ExceptionCode ec;
+        m_mediaElement->setCurrentTime(value, ec);
+    }
+}
+
+float FullscreenVideoController::duration() const
+{
+    return m_mediaElement ? m_mediaElement->duration() : 0;
+}
+
+void FullscreenVideoController::beginScrubbing()
+{
+    if (m_mediaElement) 
+        m_mediaElement->beginScrubbing();
+}
+
+void FullscreenVideoController::endScrubbing()
+{
+    if (m_mediaElement) 
+        m_mediaElement->endScrubbing();
+}
+
+LRESULT FullscreenVideoController::fullscreenClientWndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+    switch (message) {
+    case WM_CHAR:
+        onChar(wParam);
+        break;
+    case WM_LBUTTONDOWN:
+        onMouseDown(IntPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
+        break;
+    case WM_MOUSEMOVE:
+        onMouseMove(IntPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
+        break;
+    case WM_LBUTTONUP:
+        onMouseUp(IntPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
+        break;
+    }
+
+    return DefWindowProc(wnd, message, wParam, lParam);
+}
+
+static const LPCWSTR fullscreenVideeoHUDWindowClassName = L"fullscreenVideeoHUDWindowClass";
+
+void FullscreenVideoController::registerHUDWindowClass()
+{
+    static bool haveRegisteredHUDWindowClass;
+    if (haveRegisteredHUDWindowClass)
+        return;
+
+    haveRegisteredHUDWindowClass = true;
+
+    WNDCLASSEX wcex;
+
+    wcex.cbSize = sizeof(WNDCLASSEX);
+
+    wcex.style = CS_HREDRAW | CS_VREDRAW;
+    wcex.lpfnWndProc = hudWndProc;
+    wcex.cbClsExtra = 0;
+    wcex.cbWndExtra = 4;
+    wcex.hInstance = gInstance;
+    wcex.hIcon = 0;
+    wcex.hCursor = LoadCursor(0, IDC_ARROW);
+    wcex.hbrBackground = 0;
+    wcex.lpszMenuName = 0;
+    wcex.lpszClassName = fullscreenVideeoHUDWindowClassName;
+    wcex.hIconSm = 0;
+
+    RegisterClassEx(&wcex);
+}
+
+void FullscreenVideoController::createHUDWindow()
+{
+    m_hudPosition.setX((m_fullscreenSize.width() - windowWidth) / 2);
+    m_hudPosition.setY(m_fullscreenSize.height() * initialHUDPositionY - windowHeight / 2);
+
+    // Local variable that will hold the returned pixels. No need to cleanup this value. It
+    // will get cleaned up when m_bitmap is destroyed in the dtor
+    void* pixels;
+    BitmapInfo bitmapInfo = BitmapInfo::createBottomUp(IntSize(windowWidth, windowHeight));
+    m_bitmap.set(::CreateDIBSection(0, &bitmapInfo, DIB_RGB_COLORS, &pixels, 0, 0));
+    
+    // Dirty the window so the HUD draws
+    RECT clearRect = { m_hudPosition.x(), m_hudPosition.y(), m_hudPosition.x() + windowWidth, m_hudPosition.y() + windowHeight };
+    InvalidateRect(m_videoWindow, &clearRect, true);
+
+    m_playPauseButton.setShowAltButton(!canPlay());
+    m_volumeSlider.setValue(volume());
+    m_timeSlider.setValue(currentTime() / duration());
+
+    if (!canPlay())
+        m_timer.startRepeating(timerInterval);
+
+    registerHUDWindowClass();
+
+    m_hudWindow = CreateWindowEx(WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOPMOST | WS_EX_TOOLWINDOW, 
+        fullscreenVideeoHUDWindowClassName, 0, WS_POPUP | WS_VISIBLE,
+        m_hudPosition.x(), m_hudPosition.y(), 0, 0, 0, 0, gInstance, 0);
+    ASSERT(::IsWindow(m_hudWindow));
+    SetWindowLongPtr(m_hudWindow, 0, reinterpret_cast<LONG_PTR>(this));
+
+    draw();
+}
+
+static String timeToString(float time)
+{
+    if (!isfinite(time))
+        time = 0;
+    int seconds = fabsf(time); 
+    int hours = seconds / (60 * 60);
+    int minutes = (seconds / 60) % 60;
+    seconds %= 60;
+
+    if (hours) {
+        if (hours > 9)
+            return String::format("%s%02d:%02d:%02d", (time < 0 ? "-" : ""), hours, minutes, seconds);
+        return String::format("%s%01d:%02d:%02d", (time < 0 ? "-" : ""), hours, minutes, seconds);
+    }
+
+    return String::format("%s%02d:%02d", (time < 0 ? "-" : ""), minutes, seconds);
+}
+
+void FullscreenVideoController::draw()
+{
+    HDC windowDC = GetDC(m_hudWindow);
+    HDC bitmapDC = CreateCompatibleDC(windowDC);
+    ::ReleaseDC(m_hudWindow, windowDC);
+    SelectObject(bitmapDC, m_bitmap.get());
+
+    GraphicsContext context(bitmapDC, true);
+
+    context.save();
+
+    // Draw the background
+    IntSize outerRadius(borderRadius, borderRadius);
+    IntRect outerRect(0, 0, windowWidth, windowHeight);
+    IntSize innerRadius(borderRadius - borderThickness, borderRadius - borderThickness);
+    IntRect innerRect(borderThickness, borderThickness, windowWidth - borderThickness * 2, windowHeight - borderThickness * 2);
+
+    context.fillRoundedRect(outerRect, outerRadius, outerRadius, outerRadius, outerRadius, Color(borderColor), DeviceColorSpace);
+    context.setCompositeOperation(CompositeCopy);
+    context.fillRoundedRect(innerRect, innerRadius, innerRadius, innerRadius, innerRadius, Color(backgroundColor), DeviceColorSpace);
+
+    // Draw the widgets
+    m_playPauseButton.draw(context);
+    m_volumeUpButton.draw(context);
+    m_volumeSliderButton.draw(context);
+    m_volumeDownButton.draw(context);
+    m_timeSliderButton.draw(context);
+    m_exitFullscreenButton.draw(context);
+    m_volumeSlider.draw(context);
+    m_timeSlider.draw(context);
+
+    // Draw the text strings
+    FontDescription desc;
+
+    NONCLIENTMETRICS metrics;
+    metrics.cbSize = sizeof(metrics);
+    SystemParametersInfo(SPI_GETNONCLIENTMETRICS, metrics.cbSize, &metrics, 0);
+    FontFamily family;
+    family.setFamily(metrics.lfSmCaptionFont.lfFaceName);
+    desc.setFamily(family);
+
+    desc.setComputedSize(textSize);
+    Font font = Font(desc, 0, 0);
+    font.update(0);
+
+    String s;
+
+    // The y positioning of these two text strings is tricky because they are so small. They
+    // are currently positioned relative to the center of the slider and then down the font
+    // height / 4 (which is actually half of font height /2), which positions the center of
+    // the text at the center of the slider.
+    // Left string
+    s = timeToString(currentTime());
+    TextRun leftText(s);
+    context.setFillColor(Color(textColor), DeviceColorSpace);
+    context.drawText(font, leftText, IntPoint(windowWidth / 2 - timeSliderWidth / 2 - margin - font.width(leftText), windowHeight - margin - sliderHeight / 2 + font.height() / 4));
+
+    // Right string
+    s = timeToString(currentTime() - duration());
+    TextRun rightText(s);
+    context.setFillColor(Color(textColor), DeviceColorSpace);
+    context.drawText(font, rightText, IntPoint(windowWidth / 2 + timeSliderWidth / 2 + margin, windowHeight - margin - sliderHeight / 2 + font.height() / 4));
+
+    // Copy to the window
+    BLENDFUNCTION blendFunction = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA};
+    SIZE size = { windowWidth, windowHeight };
+    POINT sourcePoint = {0, 0};
+    POINT destPoint = { m_hudPosition.x(), m_hudPosition.y() };
+    BOOL result = UpdateLayeredWindow(m_hudWindow, 0, &destPoint, &size, bitmapDC, &sourcePoint, 0, &blendFunction, ULW_ALPHA);
+
+    context.restore();
+
+    ::DeleteDC(bitmapDC);
+}
+
+LRESULT FullscreenVideoController::hudWndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+    LONG_PTR longPtr = GetWindowLongPtr(wnd, 0);
+    FullscreenVideoController* controller = reinterpret_cast<FullscreenVideoController*>(longPtr);
+    if (!controller)
+        return DefWindowProc(wnd, message, wParam, lParam);
+
+    switch (message) {
+    case WM_CHAR:
+        controller->onChar(wParam);
+        break;
+    case WM_LBUTTONDOWN:
+        controller->onMouseDown(IntPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
+        break;
+    case WM_MOUSEMOVE:
+        controller->onMouseMove(IntPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
+        break;
+    case WM_LBUTTONUP:
+        controller->onMouseUp(IntPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
+        break;
+    }
+
+    return DefWindowProc(wnd, message, wParam, lParam);
+}
+
+void FullscreenVideoController::onChar(int c)
+{
+    if (c == VK_ESCAPE) {
+        if (m_mediaElement)
+            m_mediaElement->exitFullscreen();
+    } else if (c == VK_SPACE)
+        togglePlay();
+}
+
+void FullscreenVideoController::timerFired(Timer<FullscreenVideoController>*)
+{
+    // Update the time slider
+    m_timeSlider.setValue(currentTime() / duration());
+    draw();
+}
+
+void FullscreenVideoController::onMouseDown(const IntPoint& point)
+{
+    IntPoint convertedPoint(fullScreenToHUDCoordinates(point));
+
+    // Don't bother hit testing if we're outside the bounds of the window
+    if (convertedPoint.x() < 0 || convertedPoint.x() >= windowWidth || convertedPoint.y() < 0 || convertedPoint.y() >= windowHeight)
+        return;
+
+    m_hitWidget = 0;
+    m_movingWindow = false;
+
+    if (m_playPauseButton.hitTest(convertedPoint))
+        m_hitWidget = &m_playPauseButton;
+    else if (m_exitFullscreenButton.hitTest(convertedPoint))
+        m_hitWidget = &m_exitFullscreenButton;
+    else if (m_volumeUpButton.hitTest(convertedPoint))
+        m_hitWidget = &m_volumeUpButton;
+    else if (m_volumeDownButton.hitTest(convertedPoint))
+        m_hitWidget = &m_volumeDownButton;
+    else if (m_volumeSlider.hitTest(convertedPoint)) {
+        m_hitWidget = &m_volumeSlider;
+        m_volumeSlider.drag(convertedPoint, true);
+        setVolume(m_volumeSlider.value());
+    } else if (m_timeSlider.hitTest(convertedPoint)) {
+        m_hitWidget = &m_timeSlider;
+        m_timeSlider.drag(convertedPoint, true);
+        beginScrubbing();
+        setCurrentTime(m_timeSlider.value() * duration());
+    }
+
+    // If we did not pick any of our widgets we are starting a window move
+    if (!m_hitWidget) {
+        m_moveOffset = convertedPoint;
+        m_movingWindow = true;
+    }
+
+    draw();
+}
+
+void FullscreenVideoController::onMouseMove(const IntPoint& point)
+{
+    IntPoint convertedPoint(fullScreenToHUDCoordinates(point));
+
+    if (m_hitWidget) {
+        m_hitWidget->drag(convertedPoint, false);
+        if (m_hitWidget == &m_volumeSlider)
+            setVolume(m_volumeSlider.value());
+        else if (m_hitWidget == &m_timeSlider)
+            setCurrentTime(m_timeSlider.value() * duration());
+        draw();
+    } else if (m_movingWindow)
+        m_hudPosition.move(convertedPoint.x() - m_moveOffset.x(), convertedPoint.y() - m_moveOffset.y());
+}
+
+void FullscreenVideoController::onMouseUp(const IntPoint& point)
+{
+    IntPoint convertedPoint(fullScreenToHUDCoordinates(point));
+    m_movingWindow = false;
+
+    if (m_hitWidget) {
+        if (m_hitWidget == &m_playPauseButton && m_playPauseButton.hitTest(convertedPoint))
+            togglePlay();
+        else if (m_hitWidget == &m_volumeUpButton && m_volumeUpButton.hitTest(convertedPoint)) {
+            setVolume(1);
+            m_volumeSlider.setValue(1);
+        } else if (m_hitWidget == &m_volumeDownButton && m_volumeDownButton.hitTest(convertedPoint)) {
+            setVolume(0);
+            m_volumeSlider.setValue(0);
+        } else if (m_hitWidget == &m_timeSlider)
+            endScrubbing();
+        else if (m_hitWidget == &m_exitFullscreenButton && m_exitFullscreenButton.hitTest(convertedPoint)) {
+            m_hitWidget = 0;
+            if (m_mediaElement)
+                m_mediaElement->exitFullscreen();
+            return;
+        }
+    }
+
+    m_hitWidget = 0;
+    draw();
+}
+
+void FullscreenVideoController::togglePlay()
+{
+    if (canPlay())
+        play();
+    else
+        pause();
+
+    m_playPauseButton.setShowAltButton(!canPlay());
+
+    // Run a timer while the video is playing so we can keep the time
+    // slider and time values up to date.
+    if (!canPlay())
+        m_timer.startRepeating(timerInterval);
+    else
+        m_timer.stop();
+
+    draw();
+}
+
+#endif
diff --git a/WebKit/win/FullscreenVideoController.h b/WebKit/win/FullscreenVideoController.h
new file mode 100644
index 0000000..b39e30c
--- /dev/null
+++ b/WebKit/win/FullscreenVideoController.h
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2010 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. 
+ */
+
+#ifndef FullscreenVideoController_h
+#define FullscreenVideoController_h
+
+#if ENABLE(VIDEO)
+
+#include "QTMovieWin.h"
+
+#include <WebCore/HTMLMediaElement.h>
+#include <WebCore/Image.h>
+#include <WebCore/IntPoint.h>
+#include <WebCore/IntSize.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+class GraphicsContext;
+}
+
+class HUDWidget {
+public:
+    HUDWidget(const WebCore::IntRect& rect) : m_rect(rect) { }
+    
+    virtual ~HUDWidget() { }
+
+    virtual void draw(WebCore::GraphicsContext&) = 0;
+    virtual void drag(const WebCore::IntPoint&, bool start) = 0;
+    bool hitTest(const WebCore::IntPoint& point) const { return m_rect.contains(point); }
+
+protected:
+    WebCore::IntRect m_rect;
+};
+
+class HUDButton : public HUDWidget {
+public:
+    enum HUDButtonType {
+        NoButton,
+        PlayPauseButton,
+        TimeSliderButton,
+        VolumeUpButton,
+        VolumeSliderButton,
+        VolumeDownButton,
+        ExitFullscreenButton
+    };
+
+    HUDButton(HUDButtonType, const WebCore::IntPoint&);
+    ~HUDButton() { }
+
+    virtual void draw(WebCore::GraphicsContext&);
+    virtual void drag(const WebCore::IntPoint&, bool start) { }
+    void setShowAltButton(bool b)  { m_showAltButton = b; }
+
+private:
+    RefPtr<WebCore::Image> m_buttonImage;
+    RefPtr<WebCore::Image> m_buttonImageAlt;
+    HUDButtonType m_type;
+    bool m_showAltButton;
+};
+
+class HUDSlider : public HUDWidget {
+public:
+    enum HUDSliderButtonShape { RoundButton, DiamondButton };
+
+    HUDSlider(HUDSliderButtonShape, int buttonSize, const WebCore::IntRect& rect);
+    ~HUDSlider() { }
+
+    virtual void draw(WebCore::GraphicsContext&);
+    virtual void drag(const WebCore::IntPoint&, bool start);
+    float value() const { return static_cast<float>(m_buttonPosition) / (m_rect.width() - m_buttonSize); }
+    void setValue(float value) { m_buttonPosition = static_cast<int>(value * (m_rect.width() - m_buttonSize)); }
+
+private:
+    HUDSliderButtonShape m_buttonShape;
+    int m_buttonSize;
+    int m_buttonPosition;
+    int m_dragStartOffset;
+};
+
+class FullscreenVideoController : QTMovieWinFullscreenClient, public Noncopyable {
+public:
+    FullscreenVideoController();
+    virtual ~FullscreenVideoController();
+
+    void setMediaElement(WebCore::HTMLMediaElement*);
+    WebCore::HTMLMediaElement* mediaElement() const { return m_mediaElement.get(); }
+
+    void enterFullscreen();
+    void exitFullscreen();
+
+private:
+    // QTMovieWinFullscreenClient
+    virtual LRESULT fullscreenClientWndProc(HWND, UINT message, WPARAM, LPARAM);
+
+    void ensureWindow();
+    QTMovieWin* movie() const;
+
+    bool canPlay() const;
+    void play();
+    void pause();
+    float volume() const;
+    void setVolume(float);
+    float currentTime() const;
+    void setCurrentTime(float);
+    float duration() const;
+    void beginScrubbing();
+    void endScrubbing();
+
+    WebCore::IntPoint fullScreenToHUDCoordinates(const WebCore::IntPoint& point) const
+    {
+        return WebCore::IntPoint(point.x()- m_hudPosition.x(), point.y() - m_hudPosition.y());
+    }
+
+    static void registerHUDWindowClass();
+    static LRESULT CALLBACK hudWndProc(HWND, UINT message, WPARAM, LPARAM);
+    void createHUDWindow();
+    void timerFired(WebCore::Timer<FullscreenVideoController>*);
+
+    void togglePlay();
+    void draw();
+
+    void onChar(int c);
+    void onMouseDown(const WebCore::IntPoint&);
+    void onMouseMove(const WebCore::IntPoint&);
+    void onMouseUp(const WebCore::IntPoint&);
+
+    RefPtr<WebCore::HTMLMediaElement> m_mediaElement;
+
+    HWND m_hudWindow, m_videoWindow;
+    OwnPtr<HBITMAP> m_bitmap;
+    WebCore::IntSize m_fullscreenSize;
+    WebCore::IntPoint m_hudPosition;
+
+    HUDButton m_playPauseButton;
+    HUDButton m_timeSliderButton;
+    HUDButton m_volumeUpButton;
+    HUDButton m_volumeSliderButton;
+    HUDButton m_volumeDownButton;
+    HUDButton m_exitFullscreenButton;
+    HUDSlider m_volumeSlider;
+    HUDSlider m_timeSlider;
+
+    HUDWidget* m_hitWidget;
+    WebCore::IntPoint m_moveOffset;
+    bool m_movingWindow;
+    WebCore::Timer<FullscreenVideoController> m_timer;
+};
+
+#endif
+
+#endif // FullscreenVideoController_h
diff --git a/WebKit/win/WebCoreSupport/WebChromeClient.cpp b/WebKit/win/WebCoreSupport/WebChromeClient.cpp
index 6e82caf..002a629 100644
--- a/WebKit/win/WebCoreSupport/WebChromeClient.cpp
+++ b/WebKit/win/WebCoreSupport/WebChromeClient.cpp
@@ -44,6 +44,7 @@
 #include <WebCore/FloatRect.h>
 #include <WebCore/FrameLoadRequest.h>
 #include <WebCore/FrameView.h>
+#include <WebCore/HTMLNames.h>
 #include <WebCore/LocalizedStrings.h>
 #include <WebCore/NotImplemented.h>
 #include <WebCore/Page.h>
@@ -773,3 +774,23 @@ COMPtr<IWebUIDelegate> WebChromeClient::uiDelegate()
     m_webView->uiDelegate(&delegate);
     return delegate;
 }
+
+#if ENABLE(VIDEO)
+
+bool WebChromeClient::supportsFullscreenForNode(const Node* node)
+{
+    return node->hasTagName(HTMLNames::videoTag);
+}
+
+void WebChromeClient::enterFullscreenForNode(Node* node)
+{
+    m_webView->enterFullscreenForNode(node);
+}
+
+void WebChromeClient::exitFullscreenForNode(Node*)
+{
+    m_webView->exitFullscreen();
+}
+
+#endif
+
diff --git a/WebKit/win/WebCoreSupport/WebChromeClient.h b/WebKit/win/WebCoreSupport/WebChromeClient.h
index e0c59ae..5198e7c 100644
--- a/WebKit/win/WebCoreSupport/WebChromeClient.h
+++ b/WebKit/win/WebCoreSupport/WebChromeClient.h
@@ -147,6 +147,12 @@ public:
 
     virtual void requestGeolocationPermissionForFrame(WebCore::Frame*, WebCore::Geolocation*);
 
+#if ENABLE(VIDEO)
+    virtual bool supportsFullscreenForNode(const WebCore::Node*);
+    virtual void enterFullscreenForNode(WebCore::Node*);
+    virtual void exitFullscreenForNode(WebCore::Node*);
+#endif
+
 #if ENABLE(NOTIFICATIONS)
     virtual WebCore::NotificationPresenter* notificationPresenter() const { return reinterpret_cast<WebCore::NotificationPresenter*>(m_notificationsDelegate.get()); }
 #endif
diff --git a/WebKit/win/WebKit.vcproj/WebKit.vcproj b/WebKit/win/WebKit.vcproj/WebKit.vcproj
index 8259a6a..eee7b8a 100644
--- a/WebKit/win/WebKit.vcproj/WebKit.vcproj
+++ b/WebKit/win/WebKit.vcproj/WebKit.vcproj
@@ -582,6 +582,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\FullscreenVideoController.h"
+				>
+			</File>
+			<File
 				RelativePath="..\MarshallingHelpers.h"
 				>
 			</File>
@@ -894,6 +898,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\FullscreenVideoController.cpp"
+				>
+			</File>
+			<File
 				RelativePath="..\MemoryStream.cpp"
 				>
 			</File>
diff --git a/WebKit/win/WebKit.vcproj/fsVideoAudioVolumeHigh.png b/WebKit/win/WebKit.vcproj/fsVideoAudioVolumeHigh.png
index 713669e..d04df37 100755
Binary files a/WebKit/win/WebKit.vcproj/fsVideoAudioVolumeHigh.png and b/WebKit/win/WebKit.vcproj/fsVideoAudioVolumeHigh.png differ
diff --git a/WebKit/win/WebKit.vcproj/fsVideoAudioVolumeLow.png b/WebKit/win/WebKit.vcproj/fsVideoAudioVolumeLow.png
index 3b0c70e..e824a21 100755
Binary files a/WebKit/win/WebKit.vcproj/fsVideoAudioVolumeLow.png and b/WebKit/win/WebKit.vcproj/fsVideoAudioVolumeLow.png differ
diff --git a/WebKit/win/WebKit.vcproj/fsVideoExitFullscreen.png b/WebKit/win/WebKit.vcproj/fsVideoExitFullscreen.png
index b6e0df6..01ce692 100755
Binary files a/WebKit/win/WebKit.vcproj/fsVideoExitFullscreen.png and b/WebKit/win/WebKit.vcproj/fsVideoExitFullscreen.png differ
diff --git a/WebKit/win/WebKit.vcproj/fsVideoPause.png b/WebKit/win/WebKit.vcproj/fsVideoPause.png
index 004520d..b98fb36 100755
Binary files a/WebKit/win/WebKit.vcproj/fsVideoPause.png and b/WebKit/win/WebKit.vcproj/fsVideoPause.png differ
diff --git a/WebKit/win/WebKit.vcproj/fsVideoPlay.png b/WebKit/win/WebKit.vcproj/fsVideoPlay.png
index fb44f87..035aeb2 100755
Binary files a/WebKit/win/WebKit.vcproj/fsVideoPlay.png and b/WebKit/win/WebKit.vcproj/fsVideoPlay.png differ
diff --git a/WebKit/win/WebKitDLL.cpp b/WebKit/win/WebKitDLL.cpp
index c34fe4b..9f4eaeb 100644
--- a/WebKit/win/WebKitDLL.cpp
+++ b/WebKit/win/WebKitDLL.cpp
@@ -179,6 +179,16 @@ PassRefPtr<WebCore::SharedBuffer> loadResourceIntoBuffer(const char* name)
         idr = IDR_ZOOM_OUT_CURSOR;
     else if (!strcmp(name, "verticalTextCursor"))
         idr = IDR_VERTICAL_TEXT_CURSOR;
+    else if (!strcmp(name, "fsVideoAudioVolumeHigh"))
+        idr = IDR_FS_VIDEO_AUDIO_VOLUME_HIGH;
+    else if (!strcmp(name, "fsVideoAudioVolumeLow"))
+        idr = IDR_FS_VIDEO_AUDIO_VOLUME_LOW;
+    else if (!strcmp(name, "fsVideoExitFullscreen"))
+        idr = IDR_FS_VIDEO_EXIT_FULLSCREEN;
+    else if (!strcmp(name, "fsVideoPause"))
+        idr = IDR_FS_VIDEO_PAUSE;
+    else if (!strcmp(name, "fsVideoPlay"))
+        idr = IDR_FS_VIDEO_PLAY;
     else
         return 0;
 
diff --git a/WebKit/win/WebView.cpp b/WebKit/win/WebView.cpp
index da6772a..3f28c5b 100644
--- a/WebKit/win/WebView.cpp
+++ b/WebKit/win/WebView.cpp
@@ -24,11 +24,12 @@
  */
 
 #include "config.h"
-#include "WebKitDLL.h"
+
 #include "WebView.h"
 
 #include "CFDictionaryPropertyBag.h"
 #include "DOMCoreClasses.h"
+#include "FullscreenVideoController.h"
 #include "MarshallingHelpers.h"
 #include "SoftLinking.h"
 #include "WebBackForwardList.h"
@@ -46,6 +47,7 @@
 #include "WebInspector.h"
 #include "WebInspectorClient.h"
 #include "WebKit.h"
+#include "WebKitDLL.h"
 #include "WebKitLogging.h"
 #include "WebKitStatisticsPrivate.h"
 #include "WebKitSystemBits.h"
@@ -58,17 +60,17 @@
 #include <JavaScriptCore/InitializeThreading.h>
 #include <JavaScriptCore/JSLock.h>
 #include <JavaScriptCore/JSValue.h>
-#include <WebCore/ApplicationCacheStorage.h>
 #include <WebCore/AXObjectCache.h>
+#include <WebCore/ApplicationCacheStorage.h>
+#include <WebCore/BString.h>
 #include <WebCore/BackForwardList.h>
 #include <WebCore/BitmapInfo.h>
-#include <WebCore/BString.h>
+#include <WebCore/CString.h>
 #include <WebCore/Cache.h>
 #include <WebCore/Chrome.h>
 #include <WebCore/ContextMenu.h>
 #include <WebCore/ContextMenuController.h>
 #include <WebCore/CookieStorageWin.h>
-#include <WebCore/CString.h>
 #include <WebCore/Cursor.h>
 #include <WebCore/Document.h>
 #include <WebCore/DragController.h>
@@ -77,14 +79,16 @@
 #include <WebCore/EventHandler.h>
 #include <WebCore/EventNames.h>
 #include <WebCore/FileSystem.h>
-#include <WebCore/FocusController.h>
 #include <WebCore/FloatQuad.h>
+#include <WebCore/FocusController.h>
 #include <WebCore/FrameLoader.h>
 #include <WebCore/FrameTree.h>
 #include <WebCore/FrameView.h>
 #include <WebCore/FrameWin.h>
 #include <WebCore/GDIObjectCounter.h>
 #include <WebCore/GraphicsContext.h>
+#include <WebCore/HTMLMediaElement.h>
+#include <WebCore/HTMLNames.h>
 #include <WebCore/HistoryItem.h>
 #include <WebCore/HitTestRequest.h>
 #include <WebCore/HitTestResult.h>
@@ -133,13 +137,13 @@
 #include <WebKitSystemInterface/WebKitSystemInterface.h> 
 #endif
 
-#include <wtf/HashSet.h>
+#include <ShlObj.h>
 #include <comutil.h>
 #include <dimm.h>
 #include <oleacc.h>
-#include <ShlObj.h>
 #include <tchar.h>
 #include <windowsx.h>
+#include <wtf/HashSet.h>
 
 // Soft link functions for gestures and panning feedback
 SOFT_LINK_LIBRARY(USER32);
@@ -5656,6 +5660,40 @@ static KURL toKURL(BSTR bstr)
     return KURL(KURL(), toString(bstr));
 }
 
+void WebView::enterFullscreenForNode(Node* node)
+{
+    if (!node->hasTagName(HTMLNames::videoTag))
+        return;
+
+    HTMLMediaElement* videoElement = static_cast<HTMLMediaElement*>(node);
+
+    if (m_fullscreenController) {
+        if (m_fullscreenController->mediaElement() == videoElement) {
+            // The backend may just warn us that the underlaying plaftormMovie()
+            // has changed. Just force an update.
+            m_fullscreenController->setMediaElement(videoElement);
+            return; // No more to do.
+        }
+
+        // First exit Fullscreen for the old mediaElement.
+        m_fullscreenController->mediaElement()->exitFullscreen();
+        // This previous call has to trigger exitFullscreen,
+        // which has to clear m_fullscreenController.
+        ASSERT(!m_fullscreenController);
+    }
+
+    m_fullscreenController = new FullscreenVideoController;
+    m_fullscreenController->setMediaElement(videoElement);
+    m_fullscreenController->enterFullscreen();        
+}
+
+void WebView::exitFullscreen()
+{
+    if (m_fullscreenController)
+        m_fullscreenController->exitFullscreen();
+    m_fullscreenController = 0;
+}
+
 static PassOwnPtr<Vector<String> > toStringVector(unsigned patternsCount, BSTR* patterns)
 {
     // Convert the patterns into a Vector.
diff --git a/WebKit/win/WebView.h b/WebKit/win/WebView.h
index 9522ed3..88f656b 100644
--- a/WebKit/win/WebView.h
+++ b/WebKit/win/WebView.h
@@ -39,8 +39,9 @@
 #include <wtf/HashSet.h>
 #include <wtf/OwnPtr.h>
 
-class WebFrame;
+class FullscreenVideoController;
 class WebBackForwardList;
+class WebFrame;
 class WebInspector;
 class WebInspectorClient;
 
@@ -868,6 +869,9 @@ public:
     void setRootChildLayer(WebCore::PlatformLayer* layer);
 #endif
 
+    void enterFullscreenForNode(WebCore::Node*);
+    void exitFullscreen();
+
 private:
     void setZoomMultiplier(float multiplier, bool isTextOnly);
     float zoomMultiplier(bool isTextOnly);
@@ -984,6 +988,8 @@ protected:
     long m_xOverpan;
     long m_yOverpan;
 
+    OwnPtr<FullscreenVideoController> m_fullscreenController;
+
 #if USE(ACCELERATED_COMPOSITING)
     bool isAcceleratedCompositing() const { return m_isAcceleratedCompositing; }
     void setAcceleratedCompositing(bool);

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list