1d0825bca7fe65beaee391d30da42e937db621564Steve Block/*
2d0825bca7fe65beaee391d30da42e937db621564Steve Block * Copyright (C) 2010 Apple Inc. All rights reserved.
3d0825bca7fe65beaee391d30da42e937db621564Steve Block *
4d0825bca7fe65beaee391d30da42e937db621564Steve Block * Redistribution and use in source and binary forms, with or without
5d0825bca7fe65beaee391d30da42e937db621564Steve Block * modification, are permitted provided that the following conditions
6d0825bca7fe65beaee391d30da42e937db621564Steve Block * are met:
7d0825bca7fe65beaee391d30da42e937db621564Steve Block * 1. Redistributions of source code must retain the above copyright
8d0825bca7fe65beaee391d30da42e937db621564Steve Block *    notice, this list of conditions and the following disclaimer.
9d0825bca7fe65beaee391d30da42e937db621564Steve Block * 2. Redistributions in binary form must reproduce the above copyright
10d0825bca7fe65beaee391d30da42e937db621564Steve Block *    notice, this list of conditions and the following disclaimer in the
11d0825bca7fe65beaee391d30da42e937db621564Steve Block *    documentation and/or other materials provided with the distribution.
12d0825bca7fe65beaee391d30da42e937db621564Steve Block *
13d0825bca7fe65beaee391d30da42e937db621564Steve Block * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14d0825bca7fe65beaee391d30da42e937db621564Steve Block * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15d0825bca7fe65beaee391d30da42e937db621564Steve Block * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16d0825bca7fe65beaee391d30da42e937db621564Steve Block * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17d0825bca7fe65beaee391d30da42e937db621564Steve Block * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18d0825bca7fe65beaee391d30da42e937db621564Steve Block * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19d0825bca7fe65beaee391d30da42e937db621564Steve Block * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20d0825bca7fe65beaee391d30da42e937db621564Steve Block * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21d0825bca7fe65beaee391d30da42e937db621564Steve Block * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22d0825bca7fe65beaee391d30da42e937db621564Steve Block * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23d0825bca7fe65beaee391d30da42e937db621564Steve Block * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24d0825bca7fe65beaee391d30da42e937db621564Steve Block */
25d0825bca7fe65beaee391d30da42e937db621564Steve Block
26d0825bca7fe65beaee391d30da42e937db621564Steve Block#include "config.h"
27d0825bca7fe65beaee391d30da42e937db621564Steve Block
28d0825bca7fe65beaee391d30da42e937db621564Steve Block#if ENABLE(VIDEO)
29d0825bca7fe65beaee391d30da42e937db621564Steve Block
30d0825bca7fe65beaee391d30da42e937db621564Steve Block#include "FullscreenVideoController.h"
31d0825bca7fe65beaee391d30da42e937db621564Steve Block
32d0825bca7fe65beaee391d30da42e937db621564Steve Block#include "WebKitDLL.h"
335af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke#include "WebView.h"
34d0825bca7fe65beaee391d30da42e937db621564Steve Block#include <ApplicationServices/ApplicationServices.h>
35d0825bca7fe65beaee391d30da42e937db621564Steve Block#include <WebCore/BitmapInfo.h>
365af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke#include <WebCore/Chrome.h>
37d0825bca7fe65beaee391d30da42e937db621564Steve Block#include <WebCore/Font.h>
38d0825bca7fe65beaee391d30da42e937db621564Steve Block#include <WebCore/FontSelector.h>
39d0825bca7fe65beaee391d30da42e937db621564Steve Block#include <WebCore/GraphicsContext.h>
405af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke#include <WebCore/Page.h>
41cad810f21b803229eb11403f9209855525a25d57Steve Block#include <WebCore/PlatformCALayer.h>
42d0825bca7fe65beaee391d30da42e937db621564Steve Block#include <WebCore/TextRun.h>
43d0825bca7fe65beaee391d30da42e937db621564Steve Block#include <WebKitSystemInterface/WebKitSystemInterface.h>
44d0825bca7fe65beaee391d30da42e937db621564Steve Block#include <windowsx.h>
45d0825bca7fe65beaee391d30da42e937db621564Steve Block#include <wtf/StdLibExtras.h>
46d0825bca7fe65beaee391d30da42e937db621564Steve Block
47d0825bca7fe65beaee391d30da42e937db621564Steve Blockusing namespace std;
48d0825bca7fe65beaee391d30da42e937db621564Steve Blockusing namespace WebCore;
49d0825bca7fe65beaee391d30da42e937db621564Steve Block
50d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic const float timerInterval = 0.033;
51d0825bca7fe65beaee391d30da42e937db621564Steve Block
52d0825bca7fe65beaee391d30da42e937db621564Steve Block// HUD Size
53d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic const int windowHeight = 59;
54d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic const int windowWidth = 438;
55d0825bca7fe65beaee391d30da42e937db621564Steve Block
56d0825bca7fe65beaee391d30da42e937db621564Steve Block// Margins and button sizes
57d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic const int margin = 9;
58d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic const int marginTop = 9;
59d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic const int buttonSize = 25;
60d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic const int buttonMiniSize = 16;
61d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic const int volumeSliderWidth = 50;
62d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic const int timeSliderWidth = 310;
63d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic const int sliderHeight = 8;
64d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic const int volumeSliderButtonSize = 10;
65d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic const int timeSliderButtonSize = 8;
66d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic const int textSize = 11;
67d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic const float initialHUDPositionY = 0.9; // Initial Y position of HUD in percentage from top of screen
68d0825bca7fe65beaee391d30da42e937db621564Steve Block
69d0825bca7fe65beaee391d30da42e937db621564Steve Block// Background values
70d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic const int borderRadius = 12;
71d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic const int borderThickness = 2;
72d0825bca7fe65beaee391d30da42e937db621564Steve Block
73d0825bca7fe65beaee391d30da42e937db621564Steve Block// Colors
74d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic const unsigned int backgroundColor = 0xA0202020;
75d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic const unsigned int borderColor = 0xFFA0A0A0;
76d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic const unsigned int sliderGutterColor = 0xFF141414;
77d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic const unsigned int sliderButtonColor = 0xFF808080;
78d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic const unsigned int textColor = 0xFFFFFFFF;
79d0825bca7fe65beaee391d30da42e937db621564Steve Block
80d0825bca7fe65beaee391d30da42e937db621564Steve BlockHUDButton::HUDButton(HUDButtonType type, const IntPoint& position)
81d0825bca7fe65beaee391d30da42e937db621564Steve Block    : HUDWidget(IntRect(position, IntSize()))
82d0825bca7fe65beaee391d30da42e937db621564Steve Block    , m_type(type)
83d0825bca7fe65beaee391d30da42e937db621564Steve Block    , m_showAltButton(false)
84d0825bca7fe65beaee391d30da42e937db621564Steve Block{
85d0825bca7fe65beaee391d30da42e937db621564Steve Block    const char* buttonResource = 0;
86d0825bca7fe65beaee391d30da42e937db621564Steve Block    const char* buttonResourceAlt = 0;
87d0825bca7fe65beaee391d30da42e937db621564Steve Block    switch (m_type) {
88d0825bca7fe65beaee391d30da42e937db621564Steve Block    case PlayPauseButton:
89d0825bca7fe65beaee391d30da42e937db621564Steve Block        buttonResource = "fsVideoPlay";
90d0825bca7fe65beaee391d30da42e937db621564Steve Block        buttonResourceAlt = "fsVideoPause";
91d0825bca7fe65beaee391d30da42e937db621564Steve Block        break;
92d0825bca7fe65beaee391d30da42e937db621564Steve Block    case TimeSliderButton:
93d0825bca7fe65beaee391d30da42e937db621564Steve Block        break;
94d0825bca7fe65beaee391d30da42e937db621564Steve Block    case VolumeUpButton:
95d0825bca7fe65beaee391d30da42e937db621564Steve Block        buttonResource = "fsVideoAudioVolumeHigh";
96d0825bca7fe65beaee391d30da42e937db621564Steve Block        break;
97d0825bca7fe65beaee391d30da42e937db621564Steve Block    case VolumeSliderButton:
98d0825bca7fe65beaee391d30da42e937db621564Steve Block        break;
99d0825bca7fe65beaee391d30da42e937db621564Steve Block    case VolumeDownButton:
100d0825bca7fe65beaee391d30da42e937db621564Steve Block        buttonResource = "fsVideoAudioVolumeLow";
101d0825bca7fe65beaee391d30da42e937db621564Steve Block        break;
102d0825bca7fe65beaee391d30da42e937db621564Steve Block    case ExitFullscreenButton:
103d0825bca7fe65beaee391d30da42e937db621564Steve Block        buttonResource = "fsVideoExitFullscreen";
104d0825bca7fe65beaee391d30da42e937db621564Steve Block        break;
105d0825bca7fe65beaee391d30da42e937db621564Steve Block    }
106d0825bca7fe65beaee391d30da42e937db621564Steve Block
107d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (buttonResource) {
108d0825bca7fe65beaee391d30da42e937db621564Steve Block        m_buttonImage = Image::loadPlatformResource(buttonResource);
109d0825bca7fe65beaee391d30da42e937db621564Steve Block        m_rect.setWidth(m_buttonImage->width());
110d0825bca7fe65beaee391d30da42e937db621564Steve Block        m_rect.setHeight(m_buttonImage->height());
111d0825bca7fe65beaee391d30da42e937db621564Steve Block    }
112d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (buttonResourceAlt)
113d0825bca7fe65beaee391d30da42e937db621564Steve Block        m_buttonImageAlt = Image::loadPlatformResource(buttonResourceAlt);
114d0825bca7fe65beaee391d30da42e937db621564Steve Block}
115d0825bca7fe65beaee391d30da42e937db621564Steve Block
116d0825bca7fe65beaee391d30da42e937db621564Steve Blockvoid HUDButton::draw(GraphicsContext& context)
117d0825bca7fe65beaee391d30da42e937db621564Steve Block{
118d0825bca7fe65beaee391d30da42e937db621564Steve Block    Image* image = (m_showAltButton && m_buttonImageAlt) ? m_buttonImageAlt.get() : m_buttonImage.get();
119a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    context.drawImage(image, ColorSpaceDeviceRGB, m_rect.location());
120d0825bca7fe65beaee391d30da42e937db621564Steve Block}
121d0825bca7fe65beaee391d30da42e937db621564Steve Block
122d0825bca7fe65beaee391d30da42e937db621564Steve BlockHUDSlider::HUDSlider(HUDSliderButtonShape shape, int buttonSize, const IntRect& rect)
123d0825bca7fe65beaee391d30da42e937db621564Steve Block    : HUDWidget(rect)
124d0825bca7fe65beaee391d30da42e937db621564Steve Block    , m_buttonShape(shape)
125d0825bca7fe65beaee391d30da42e937db621564Steve Block    , m_buttonSize(buttonSize)
126d0825bca7fe65beaee391d30da42e937db621564Steve Block    , m_buttonPosition(0)
127d0825bca7fe65beaee391d30da42e937db621564Steve Block    , m_dragStartOffset(0)
128d0825bca7fe65beaee391d30da42e937db621564Steve Block{
129d0825bca7fe65beaee391d30da42e937db621564Steve Block}
130d0825bca7fe65beaee391d30da42e937db621564Steve Block
131d0825bca7fe65beaee391d30da42e937db621564Steve Blockvoid HUDSlider::draw(GraphicsContext& context)
132d0825bca7fe65beaee391d30da42e937db621564Steve Block{
133d0825bca7fe65beaee391d30da42e937db621564Steve Block    // Draw gutter
134d0825bca7fe65beaee391d30da42e937db621564Steve Block    IntSize radius(m_rect.height() / 2, m_rect.height() / 2);
135a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    context.fillRoundedRect(m_rect, radius, radius, radius, radius, Color(sliderGutterColor), ColorSpaceDeviceRGB);
136d0825bca7fe65beaee391d30da42e937db621564Steve Block
137d0825bca7fe65beaee391d30da42e937db621564Steve Block    // Draw button
138a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    context.setStrokeColor(Color(sliderButtonColor), ColorSpaceDeviceRGB);
139a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    context.setFillColor(Color(sliderButtonColor), ColorSpaceDeviceRGB);
140d0825bca7fe65beaee391d30da42e937db621564Steve Block
141d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (m_buttonShape == RoundButton) {
142d0825bca7fe65beaee391d30da42e937db621564Steve Block        context.drawEllipse(IntRect(m_rect.location().x() + m_buttonPosition, m_rect.location().y() - (m_buttonSize - m_rect.height()) / 2, m_buttonSize, m_buttonSize));
143d0825bca7fe65beaee391d30da42e937db621564Steve Block        return;
144d0825bca7fe65beaee391d30da42e937db621564Steve Block    }
145d0825bca7fe65beaee391d30da42e937db621564Steve Block
146d0825bca7fe65beaee391d30da42e937db621564Steve Block    // Draw a diamond
147d0825bca7fe65beaee391d30da42e937db621564Steve Block    FloatPoint points[4];
148d0825bca7fe65beaee391d30da42e937db621564Steve Block    float half = static_cast<float>(m_buttonSize) / 2;
149d0825bca7fe65beaee391d30da42e937db621564Steve Block    points[0].setX(m_rect.location().x() + m_buttonPosition + half);
150d0825bca7fe65beaee391d30da42e937db621564Steve Block    points[0].setY(m_rect.location().y());
151d0825bca7fe65beaee391d30da42e937db621564Steve Block    points[1].setX(m_rect.location().x() + m_buttonPosition + m_buttonSize);
152d0825bca7fe65beaee391d30da42e937db621564Steve Block    points[1].setY(m_rect.location().y() + half);
153d0825bca7fe65beaee391d30da42e937db621564Steve Block    points[2].setX(m_rect.location().x() + m_buttonPosition + half);
154d0825bca7fe65beaee391d30da42e937db621564Steve Block    points[2].setY(m_rect.location().y() + m_buttonSize);
155d0825bca7fe65beaee391d30da42e937db621564Steve Block    points[3].setX(m_rect.location().x() + m_buttonPosition);
156d0825bca7fe65beaee391d30da42e937db621564Steve Block    points[3].setY(m_rect.location().y() + half);
157d0825bca7fe65beaee391d30da42e937db621564Steve Block    context.drawConvexPolygon(4, points, true);
158d0825bca7fe65beaee391d30da42e937db621564Steve Block}
159d0825bca7fe65beaee391d30da42e937db621564Steve Block
160d0825bca7fe65beaee391d30da42e937db621564Steve Blockvoid HUDSlider::drag(const IntPoint& point, bool start)
161d0825bca7fe65beaee391d30da42e937db621564Steve Block{
162d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (start) {
163d0825bca7fe65beaee391d30da42e937db621564Steve Block        // When we start, we need to snap the slider position to the x position if we clicked the gutter.
164d0825bca7fe65beaee391d30da42e937db621564Steve Block        // But if we click the button, we need to drag relative to where we clicked down. We only need
165d0825bca7fe65beaee391d30da42e937db621564Steve Block        // to check X because we would not even get here unless Y were already inside.
166d0825bca7fe65beaee391d30da42e937db621564Steve Block        int relativeX = point.x() - m_rect.location().x();
167d0825bca7fe65beaee391d30da42e937db621564Steve Block        if (relativeX >= m_buttonPosition && relativeX <= m_buttonPosition + m_buttonSize)
168d0825bca7fe65beaee391d30da42e937db621564Steve Block            m_dragStartOffset = point.x() - m_buttonPosition;
169d0825bca7fe65beaee391d30da42e937db621564Steve Block        else
170d0825bca7fe65beaee391d30da42e937db621564Steve Block            m_dragStartOffset = m_rect.location().x() + m_buttonSize / 2;
171d0825bca7fe65beaee391d30da42e937db621564Steve Block    }
172d0825bca7fe65beaee391d30da42e937db621564Steve Block
173d0825bca7fe65beaee391d30da42e937db621564Steve Block    m_buttonPosition = max(0, min(m_rect.width() - m_buttonSize, point.x() - m_dragStartOffset));
174d0825bca7fe65beaee391d30da42e937db621564Steve Block}
175d0825bca7fe65beaee391d30da42e937db621564Steve Block
1765af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke#if USE(ACCELERATED_COMPOSITING)
177cad810f21b803229eb11403f9209855525a25d57Steve Blockclass FullscreenVideoController::LayerClient : public WebCore::PlatformCALayerClient {
1785af96e2c7b73ebc627c6894727826a7576d31758Leon Clarkepublic:
179cad810f21b803229eb11403f9209855525a25d57Steve Block    LayerClient(FullscreenVideoController* parent) : m_parent(parent) { }
180cad810f21b803229eb11403f9209855525a25d57Steve Block
181cad810f21b803229eb11403f9209855525a25d57Steve Blockprivate:
182cad810f21b803229eb11403f9209855525a25d57Steve Block    virtual void platformCALayerLayoutSublayersOfLayer(PlatformCALayer*);
183cad810f21b803229eb11403f9209855525a25d57Steve Block    virtual bool platformCALayerRespondsToLayoutChanges() const { return true; }
184cad810f21b803229eb11403f9209855525a25d57Steve Block
185cad810f21b803229eb11403f9209855525a25d57Steve Block    virtual void platformCALayerAnimationStarted(CFTimeInterval beginTime) { }
186cad810f21b803229eb11403f9209855525a25d57Steve Block    virtual GraphicsLayer::CompositingCoordinatesOrientation platformCALayerContentsOrientation() const { return GraphicsLayer::CompositingCoordinatesBottomUp; }
187cad810f21b803229eb11403f9209855525a25d57Steve Block    virtual void platformCALayerPaintContents(GraphicsContext&, const IntRect& inClip) { }
188cad810f21b803229eb11403f9209855525a25d57Steve Block    virtual bool platformCALayerShowDebugBorders() const { return false; }
189cad810f21b803229eb11403f9209855525a25d57Steve Block    virtual bool platformCALayerShowRepaintCounter() const { return false; }
190cad810f21b803229eb11403f9209855525a25d57Steve Block    virtual int platformCALayerIncrementRepaintCount() { return 0; }
191cad810f21b803229eb11403f9209855525a25d57Steve Block
192cad810f21b803229eb11403f9209855525a25d57Steve Block    virtual bool platformCALayerContentsOpaque() const { return false; }
193cad810f21b803229eb11403f9209855525a25d57Steve Block    virtual bool platformCALayerDrawsContent() const { return false; }
194cad810f21b803229eb11403f9209855525a25d57Steve Block    virtual void platformCALayerLayerDidDisplay(PlatformLayer*) { }
1955af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke
1965af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    FullscreenVideoController* m_parent;
1975af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke};
1985af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke
199cad810f21b803229eb11403f9209855525a25d57Steve Blockvoid FullscreenVideoController::LayerClient::platformCALayerLayoutSublayersOfLayer(PlatformCALayer* layer)
2005af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke{
2015af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    ASSERT_ARG(layer, layer == m_parent->m_rootChild);
2025af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke
2035af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    HTMLMediaElement* mediaElement = m_parent->m_mediaElement.get();
2045af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    if (!mediaElement)
2055af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke        return;
2065af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke
207cad810f21b803229eb11403f9209855525a25d57Steve Block
208cad810f21b803229eb11403f9209855525a25d57Steve Block    PlatformCALayer* videoLayer = PlatformCALayer::platformCALayer(mediaElement->platformLayer());
2095af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    if (!videoLayer || videoLayer->superlayer() != layer)
2105af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke        return;
2115af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke
2125af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    FloatRect layerBounds = layer->bounds();
2135af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke
2145af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    FloatSize videoSize = mediaElement->player()->naturalSize();
2155af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    float scaleFactor;
2165af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    if (videoSize.aspectRatio() > layerBounds.size().aspectRatio())
2175af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke        scaleFactor = layerBounds.width() / videoSize.width();
2185af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    else
2195af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke        scaleFactor = layerBounds.height() / videoSize.height();
2205af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    videoSize.scale(scaleFactor);
2215af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke
2225af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    // Calculate the centered position based on the videoBounds and layerBounds:
2235af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    FloatPoint videoPosition;
2245af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    FloatPoint videoOrigin;
2255af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    videoOrigin.setX((layerBounds.width() - videoSize.width()) * 0.5);
2265af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    videoOrigin.setY((layerBounds.height() - videoSize.height()) * 0.5);
2275af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    videoLayer->setFrame(FloatRect(videoOrigin, videoSize));
2285af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke}
2295af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke#endif
2305af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke
231d0825bca7fe65beaee391d30da42e937db621564Steve BlockFullscreenVideoController::FullscreenVideoController()
232d0825bca7fe65beaee391d30da42e937db621564Steve Block    : m_hudWindow(0)
233d0825bca7fe65beaee391d30da42e937db621564Steve Block    , m_playPauseButton(HUDButton::PlayPauseButton, IntPoint((windowWidth - buttonSize) / 2, marginTop))
234d0825bca7fe65beaee391d30da42e937db621564Steve Block    , m_timeSliderButton(HUDButton::TimeSliderButton, IntPoint(0, 0))
235d0825bca7fe65beaee391d30da42e937db621564Steve Block    , m_volumeUpButton(HUDButton::VolumeUpButton, IntPoint(margin + buttonMiniSize + volumeSliderWidth + buttonMiniSize / 2, marginTop + (buttonSize - buttonMiniSize) / 2))
236d0825bca7fe65beaee391d30da42e937db621564Steve Block    , m_volumeSliderButton(HUDButton::VolumeSliderButton, IntPoint(0, 0))
237d0825bca7fe65beaee391d30da42e937db621564Steve Block    , m_volumeDownButton(HUDButton::VolumeDownButton, IntPoint(margin, marginTop + (buttonSize - buttonMiniSize) / 2))
238d0825bca7fe65beaee391d30da42e937db621564Steve Block    , m_exitFullscreenButton(HUDButton::ExitFullscreenButton, IntPoint(windowWidth - 2 * margin - buttonMiniSize, marginTop + (buttonSize - buttonMiniSize) / 2))
239d0825bca7fe65beaee391d30da42e937db621564Steve Block    , m_volumeSlider(HUDSlider::RoundButton, volumeSliderButtonSize, IntRect(IntPoint(margin + buttonMiniSize, marginTop + (buttonSize - buttonMiniSize) / 2 + buttonMiniSize / 2 - sliderHeight / 2), IntSize(volumeSliderWidth, sliderHeight)))
240d0825bca7fe65beaee391d30da42e937db621564Steve Block    , m_timeSlider(HUDSlider::DiamondButton, timeSliderButtonSize, IntRect(IntPoint(windowWidth / 2 - timeSliderWidth / 2, windowHeight - margin - sliderHeight), IntSize(timeSliderWidth, sliderHeight)))
241d0825bca7fe65beaee391d30da42e937db621564Steve Block    , m_hitWidget(0)
242d0825bca7fe65beaee391d30da42e937db621564Steve Block    , m_movingWindow(false)
243d0825bca7fe65beaee391d30da42e937db621564Steve Block    , m_timer(this, &FullscreenVideoController::timerFired)
2445af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke#if USE(ACCELERATED_COMPOSITING)
245cad810f21b803229eb11403f9209855525a25d57Steve Block    , m_layerClient(new LayerClient(this))
246cad810f21b803229eb11403f9209855525a25d57Steve Block    , m_rootChild(PlatformCALayer::create(PlatformCALayer::LayerTypeLayer, m_layerClient.get()))
2475af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke#endif
2485af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    , m_fullscreenWindow(new MediaPlayerPrivateFullscreenWindow(this))
249d0825bca7fe65beaee391d30da42e937db621564Steve Block{
250d0825bca7fe65beaee391d30da42e937db621564Steve Block}
251d0825bca7fe65beaee391d30da42e937db621564Steve Block
252d0825bca7fe65beaee391d30da42e937db621564Steve BlockFullscreenVideoController::~FullscreenVideoController()
253d0825bca7fe65beaee391d30da42e937db621564Steve Block{
2545af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke#if USE(ACCELERATED_COMPOSITING)
255cad810f21b803229eb11403f9209855525a25d57Steve Block    m_rootChild->setOwner(0);
2565af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke#endif
257d0825bca7fe65beaee391d30da42e937db621564Steve Block}
258d0825bca7fe65beaee391d30da42e937db621564Steve Block
259d0825bca7fe65beaee391d30da42e937db621564Steve Blockvoid FullscreenVideoController::setMediaElement(HTMLMediaElement* mediaElement)
260d0825bca7fe65beaee391d30da42e937db621564Steve Block{
261d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (mediaElement == m_mediaElement)
262d0825bca7fe65beaee391d30da42e937db621564Steve Block        return;
263d0825bca7fe65beaee391d30da42e937db621564Steve Block
264d0825bca7fe65beaee391d30da42e937db621564Steve Block    m_mediaElement = mediaElement;
265d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (!m_mediaElement) {
266d0825bca7fe65beaee391d30da42e937db621564Steve Block        // Can't do full-screen, just get out
267d0825bca7fe65beaee391d30da42e937db621564Steve Block        exitFullscreen();
268d0825bca7fe65beaee391d30da42e937db621564Steve Block    }
269d0825bca7fe65beaee391d30da42e937db621564Steve Block}
270d0825bca7fe65beaee391d30da42e937db621564Steve Block
271d0825bca7fe65beaee391d30da42e937db621564Steve Blockvoid FullscreenVideoController::enterFullscreen()
272d0825bca7fe65beaee391d30da42e937db621564Steve Block{
2735af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    if (!m_mediaElement)
274d0825bca7fe65beaee391d30da42e937db621564Steve Block        return;
275d0825bca7fe65beaee391d30da42e937db621564Steve Block
2765af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    WebView* webView = kit(m_mediaElement->document()->page());
2775af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    HWND parentHwnd = webView ? webView->viewWindow() : 0;
2785af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke
2795af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    m_fullscreenWindow->createWindow(parentHwnd);
2805af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke#if USE(ACCELERATED_COMPOSITING)
2815af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    m_fullscreenWindow->setRootChildLayer(m_rootChild);
2825af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke
283cad810f21b803229eb11403f9209855525a25d57Steve Block    PlatformCALayer* videoLayer = PlatformCALayer::platformCALayer(m_mediaElement->platformLayer());
284cad810f21b803229eb11403f9209855525a25d57Steve Block    m_rootChild->appendSublayer(videoLayer);
2855af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    m_rootChild->setNeedsLayout();
28668513a70bcd92384395513322f1b801e7bf9c729Steve Block    m_rootChild->setGeometryFlipped(1);
2875af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke#endif
288d0825bca7fe65beaee391d30da42e937db621564Steve Block
289d0825bca7fe65beaee391d30da42e937db621564Steve Block    RECT windowRect;
2905af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    GetClientRect(m_fullscreenWindow->hwnd(), &windowRect);
291d0825bca7fe65beaee391d30da42e937db621564Steve Block    m_fullscreenSize.setWidth(windowRect.right - windowRect.left);
292d0825bca7fe65beaee391d30da42e937db621564Steve Block    m_fullscreenSize.setHeight(windowRect.bottom - windowRect.top);
293d0825bca7fe65beaee391d30da42e937db621564Steve Block
294d0825bca7fe65beaee391d30da42e937db621564Steve Block    createHUDWindow();
295d0825bca7fe65beaee391d30da42e937db621564Steve Block}
296d0825bca7fe65beaee391d30da42e937db621564Steve Block
297d0825bca7fe65beaee391d30da42e937db621564Steve Blockvoid FullscreenVideoController::exitFullscreen()
298d0825bca7fe65beaee391d30da42e937db621564Steve Block{
299dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    SetWindowLongPtr(m_hudWindow, 0, 0);
3005af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke
3015af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    if (m_fullscreenWindow)
3025af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke        m_fullscreenWindow = 0;
303d0825bca7fe65beaee391d30da42e937db621564Steve Block
304dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    ASSERT(!IsWindow(m_hudWindow));
305d0825bca7fe65beaee391d30da42e937db621564Steve Block    m_hudWindow = 0;
3065af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke
3075af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    // We previously ripped the mediaElement's platform layer out
3085af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    // of its orginial layer tree to display it in our fullscreen
3095af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    // window.  Now, we need to get the layer back in its original
3105af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    // tree.
3115af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    //
3125af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    // As a side effect of setting the player to invisible/visible,
3135af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    // the player's layer will be recreated, and will be picked up
3145af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    // the next time the layer tree is synched.
3155af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    m_mediaElement->player()->setVisible(0);
3165af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    m_mediaElement->player()->setVisible(1);
317d0825bca7fe65beaee391d30da42e937db621564Steve Block}
318d0825bca7fe65beaee391d30da42e937db621564Steve Block
319d0825bca7fe65beaee391d30da42e937db621564Steve Blockbool FullscreenVideoController::canPlay() const
320d0825bca7fe65beaee391d30da42e937db621564Steve Block{
321d0825bca7fe65beaee391d30da42e937db621564Steve Block    return m_mediaElement && m_mediaElement->canPlay();
322d0825bca7fe65beaee391d30da42e937db621564Steve Block}
323d0825bca7fe65beaee391d30da42e937db621564Steve Block
324d0825bca7fe65beaee391d30da42e937db621564Steve Blockvoid FullscreenVideoController::play()
325d0825bca7fe65beaee391d30da42e937db621564Steve Block{
326d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (m_mediaElement)
3275e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        m_mediaElement->play(m_mediaElement->processingUserGesture());
328d0825bca7fe65beaee391d30da42e937db621564Steve Block}
329d0825bca7fe65beaee391d30da42e937db621564Steve Block
330d0825bca7fe65beaee391d30da42e937db621564Steve Blockvoid FullscreenVideoController::pause()
331d0825bca7fe65beaee391d30da42e937db621564Steve Block{
332d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (m_mediaElement)
3335e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        m_mediaElement->pause(m_mediaElement->processingUserGesture());
334d0825bca7fe65beaee391d30da42e937db621564Steve Block}
335d0825bca7fe65beaee391d30da42e937db621564Steve Block
336d0825bca7fe65beaee391d30da42e937db621564Steve Blockfloat FullscreenVideoController::volume() const
337d0825bca7fe65beaee391d30da42e937db621564Steve Block{
338d0825bca7fe65beaee391d30da42e937db621564Steve Block    return m_mediaElement ? m_mediaElement->volume() : 0;
339d0825bca7fe65beaee391d30da42e937db621564Steve Block}
340d0825bca7fe65beaee391d30da42e937db621564Steve Block
341d0825bca7fe65beaee391d30da42e937db621564Steve Blockvoid FullscreenVideoController::setVolume(float volume)
342d0825bca7fe65beaee391d30da42e937db621564Steve Block{
343d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (m_mediaElement) {
344d0825bca7fe65beaee391d30da42e937db621564Steve Block        ExceptionCode ec;
345d0825bca7fe65beaee391d30da42e937db621564Steve Block        m_mediaElement->setVolume(volume, ec);
346d0825bca7fe65beaee391d30da42e937db621564Steve Block    }
347d0825bca7fe65beaee391d30da42e937db621564Steve Block}
348d0825bca7fe65beaee391d30da42e937db621564Steve Block
349d0825bca7fe65beaee391d30da42e937db621564Steve Blockfloat FullscreenVideoController::currentTime() const
350d0825bca7fe65beaee391d30da42e937db621564Steve Block{
351d0825bca7fe65beaee391d30da42e937db621564Steve Block    return m_mediaElement ? m_mediaElement->currentTime() : 0;
352d0825bca7fe65beaee391d30da42e937db621564Steve Block}
353d0825bca7fe65beaee391d30da42e937db621564Steve Block
354d0825bca7fe65beaee391d30da42e937db621564Steve Blockvoid FullscreenVideoController::setCurrentTime(float value)
355d0825bca7fe65beaee391d30da42e937db621564Steve Block{
356d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (m_mediaElement) {
357d0825bca7fe65beaee391d30da42e937db621564Steve Block        ExceptionCode ec;
358d0825bca7fe65beaee391d30da42e937db621564Steve Block        m_mediaElement->setCurrentTime(value, ec);
359d0825bca7fe65beaee391d30da42e937db621564Steve Block    }
360d0825bca7fe65beaee391d30da42e937db621564Steve Block}
361d0825bca7fe65beaee391d30da42e937db621564Steve Block
362d0825bca7fe65beaee391d30da42e937db621564Steve Blockfloat FullscreenVideoController::duration() const
363d0825bca7fe65beaee391d30da42e937db621564Steve Block{
364d0825bca7fe65beaee391d30da42e937db621564Steve Block    return m_mediaElement ? m_mediaElement->duration() : 0;
365d0825bca7fe65beaee391d30da42e937db621564Steve Block}
366d0825bca7fe65beaee391d30da42e937db621564Steve Block
367d0825bca7fe65beaee391d30da42e937db621564Steve Blockvoid FullscreenVideoController::beginScrubbing()
368d0825bca7fe65beaee391d30da42e937db621564Steve Block{
369d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (m_mediaElement)
370d0825bca7fe65beaee391d30da42e937db621564Steve Block        m_mediaElement->beginScrubbing();
371d0825bca7fe65beaee391d30da42e937db621564Steve Block}
372d0825bca7fe65beaee391d30da42e937db621564Steve Block
373d0825bca7fe65beaee391d30da42e937db621564Steve Blockvoid FullscreenVideoController::endScrubbing()
374d0825bca7fe65beaee391d30da42e937db621564Steve Block{
375d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (m_mediaElement)
376d0825bca7fe65beaee391d30da42e937db621564Steve Block        m_mediaElement->endScrubbing();
377d0825bca7fe65beaee391d30da42e937db621564Steve Block}
378d0825bca7fe65beaee391d30da42e937db621564Steve Block
379d0825bca7fe65beaee391d30da42e937db621564Steve BlockLRESULT FullscreenVideoController::fullscreenClientWndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lParam)
380d0825bca7fe65beaee391d30da42e937db621564Steve Block{
381d0825bca7fe65beaee391d30da42e937db621564Steve Block    switch (message) {
382d0825bca7fe65beaee391d30da42e937db621564Steve Block    case WM_CHAR:
383d0825bca7fe65beaee391d30da42e937db621564Steve Block        onChar(wParam);
384d0825bca7fe65beaee391d30da42e937db621564Steve Block        break;
3855af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    case WM_KEYDOWN:
3865af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke        onKeyDown(wParam);
3875af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke        break;
388d0825bca7fe65beaee391d30da42e937db621564Steve Block    case WM_LBUTTONDOWN:
389d0825bca7fe65beaee391d30da42e937db621564Steve Block        onMouseDown(IntPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
390d0825bca7fe65beaee391d30da42e937db621564Steve Block        break;
391d0825bca7fe65beaee391d30da42e937db621564Steve Block    case WM_MOUSEMOVE:
392d0825bca7fe65beaee391d30da42e937db621564Steve Block        onMouseMove(IntPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
393d0825bca7fe65beaee391d30da42e937db621564Steve Block        break;
394d0825bca7fe65beaee391d30da42e937db621564Steve Block    case WM_LBUTTONUP:
395d0825bca7fe65beaee391d30da42e937db621564Steve Block        onMouseUp(IntPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
396d0825bca7fe65beaee391d30da42e937db621564Steve Block        break;
397d0825bca7fe65beaee391d30da42e937db621564Steve Block    }
398d0825bca7fe65beaee391d30da42e937db621564Steve Block
399d0825bca7fe65beaee391d30da42e937db621564Steve Block    return DefWindowProc(wnd, message, wParam, lParam);
400d0825bca7fe65beaee391d30da42e937db621564Steve Block}
401d0825bca7fe65beaee391d30da42e937db621564Steve Block
402d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic const LPCWSTR fullscreenVideeoHUDWindowClassName = L"fullscreenVideeoHUDWindowClass";
403d0825bca7fe65beaee391d30da42e937db621564Steve Block
404d0825bca7fe65beaee391d30da42e937db621564Steve Blockvoid FullscreenVideoController::registerHUDWindowClass()
405d0825bca7fe65beaee391d30da42e937db621564Steve Block{
406d0825bca7fe65beaee391d30da42e937db621564Steve Block    static bool haveRegisteredHUDWindowClass;
407d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (haveRegisteredHUDWindowClass)
408d0825bca7fe65beaee391d30da42e937db621564Steve Block        return;
409d0825bca7fe65beaee391d30da42e937db621564Steve Block
410d0825bca7fe65beaee391d30da42e937db621564Steve Block    haveRegisteredHUDWindowClass = true;
411d0825bca7fe65beaee391d30da42e937db621564Steve Block
412d0825bca7fe65beaee391d30da42e937db621564Steve Block    WNDCLASSEX wcex;
413d0825bca7fe65beaee391d30da42e937db621564Steve Block
414d0825bca7fe65beaee391d30da42e937db621564Steve Block    wcex.cbSize = sizeof(WNDCLASSEX);
415d0825bca7fe65beaee391d30da42e937db621564Steve Block
416d0825bca7fe65beaee391d30da42e937db621564Steve Block    wcex.style = CS_HREDRAW | CS_VREDRAW;
417d0825bca7fe65beaee391d30da42e937db621564Steve Block    wcex.lpfnWndProc = hudWndProc;
418d0825bca7fe65beaee391d30da42e937db621564Steve Block    wcex.cbClsExtra = 0;
419d0825bca7fe65beaee391d30da42e937db621564Steve Block    wcex.cbWndExtra = 4;
420d0825bca7fe65beaee391d30da42e937db621564Steve Block    wcex.hInstance = gInstance;
421d0825bca7fe65beaee391d30da42e937db621564Steve Block    wcex.hIcon = 0;
422d0825bca7fe65beaee391d30da42e937db621564Steve Block    wcex.hCursor = LoadCursor(0, IDC_ARROW);
423d0825bca7fe65beaee391d30da42e937db621564Steve Block    wcex.hbrBackground = 0;
424d0825bca7fe65beaee391d30da42e937db621564Steve Block    wcex.lpszMenuName = 0;
425d0825bca7fe65beaee391d30da42e937db621564Steve Block    wcex.lpszClassName = fullscreenVideeoHUDWindowClassName;
426d0825bca7fe65beaee391d30da42e937db621564Steve Block    wcex.hIconSm = 0;
427d0825bca7fe65beaee391d30da42e937db621564Steve Block
428d0825bca7fe65beaee391d30da42e937db621564Steve Block    RegisterClassEx(&wcex);
429d0825bca7fe65beaee391d30da42e937db621564Steve Block}
430d0825bca7fe65beaee391d30da42e937db621564Steve Block
431d0825bca7fe65beaee391d30da42e937db621564Steve Blockvoid FullscreenVideoController::createHUDWindow()
432d0825bca7fe65beaee391d30da42e937db621564Steve Block{
433d0825bca7fe65beaee391d30da42e937db621564Steve Block    m_hudPosition.setX((m_fullscreenSize.width() - windowWidth) / 2);
434d0825bca7fe65beaee391d30da42e937db621564Steve Block    m_hudPosition.setY(m_fullscreenSize.height() * initialHUDPositionY - windowHeight / 2);
435d0825bca7fe65beaee391d30da42e937db621564Steve Block
436d0825bca7fe65beaee391d30da42e937db621564Steve Block    // Local variable that will hold the returned pixels. No need to cleanup this value. It
437d0825bca7fe65beaee391d30da42e937db621564Steve Block    // will get cleaned up when m_bitmap is destroyed in the dtor
438d0825bca7fe65beaee391d30da42e937db621564Steve Block    void* pixels;
439d0825bca7fe65beaee391d30da42e937db621564Steve Block    BitmapInfo bitmapInfo = BitmapInfo::createBottomUp(IntSize(windowWidth, windowHeight));
440d0825bca7fe65beaee391d30da42e937db621564Steve Block    m_bitmap.set(::CreateDIBSection(0, &bitmapInfo, DIB_RGB_COLORS, &pixels, 0, 0));
441d0825bca7fe65beaee391d30da42e937db621564Steve Block
442d0825bca7fe65beaee391d30da42e937db621564Steve Block    // Dirty the window so the HUD draws
443d0825bca7fe65beaee391d30da42e937db621564Steve Block    RECT clearRect = { m_hudPosition.x(), m_hudPosition.y(), m_hudPosition.x() + windowWidth, m_hudPosition.y() + windowHeight };
4445af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    InvalidateRect(m_fullscreenWindow->hwnd(), &clearRect, true);
445d0825bca7fe65beaee391d30da42e937db621564Steve Block
446d0825bca7fe65beaee391d30da42e937db621564Steve Block    m_playPauseButton.setShowAltButton(!canPlay());
447d0825bca7fe65beaee391d30da42e937db621564Steve Block    m_volumeSlider.setValue(volume());
448d0825bca7fe65beaee391d30da42e937db621564Steve Block    m_timeSlider.setValue(currentTime() / duration());
449d0825bca7fe65beaee391d30da42e937db621564Steve Block
450d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (!canPlay())
451d0825bca7fe65beaee391d30da42e937db621564Steve Block        m_timer.startRepeating(timerInterval);
452d0825bca7fe65beaee391d30da42e937db621564Steve Block
453d0825bca7fe65beaee391d30da42e937db621564Steve Block    registerHUDWindowClass();
454d0825bca7fe65beaee391d30da42e937db621564Steve Block
455dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    m_hudWindow = CreateWindowEx(WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOOLWINDOW,
456d0825bca7fe65beaee391d30da42e937db621564Steve Block        fullscreenVideeoHUDWindowClassName, 0, WS_POPUP | WS_VISIBLE,
4575af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke        m_hudPosition.x(), m_hudPosition.y(), 0, 0, m_fullscreenWindow->hwnd(), 0, gInstance, 0);
458d0825bca7fe65beaee391d30da42e937db621564Steve Block    ASSERT(::IsWindow(m_hudWindow));
459d0825bca7fe65beaee391d30da42e937db621564Steve Block    SetWindowLongPtr(m_hudWindow, 0, reinterpret_cast<LONG_PTR>(this));
460d0825bca7fe65beaee391d30da42e937db621564Steve Block
461d0825bca7fe65beaee391d30da42e937db621564Steve Block    draw();
462d0825bca7fe65beaee391d30da42e937db621564Steve Block}
463d0825bca7fe65beaee391d30da42e937db621564Steve Block
464d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic String timeToString(float time)
465d0825bca7fe65beaee391d30da42e937db621564Steve Block{
466d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (!isfinite(time))
467d0825bca7fe65beaee391d30da42e937db621564Steve Block        time = 0;
468d0825bca7fe65beaee391d30da42e937db621564Steve Block    int seconds = fabsf(time);
469d0825bca7fe65beaee391d30da42e937db621564Steve Block    int hours = seconds / (60 * 60);
470d0825bca7fe65beaee391d30da42e937db621564Steve Block    int minutes = (seconds / 60) % 60;
471d0825bca7fe65beaee391d30da42e937db621564Steve Block    seconds %= 60;
472d0825bca7fe65beaee391d30da42e937db621564Steve Block
473d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (hours) {
474d0825bca7fe65beaee391d30da42e937db621564Steve Block        if (hours > 9)
475d0825bca7fe65beaee391d30da42e937db621564Steve Block            return String::format("%s%02d:%02d:%02d", (time < 0 ? "-" : ""), hours, minutes, seconds);
476d0825bca7fe65beaee391d30da42e937db621564Steve Block        return String::format("%s%01d:%02d:%02d", (time < 0 ? "-" : ""), hours, minutes, seconds);
477d0825bca7fe65beaee391d30da42e937db621564Steve Block    }
478d0825bca7fe65beaee391d30da42e937db621564Steve Block
479d0825bca7fe65beaee391d30da42e937db621564Steve Block    return String::format("%s%02d:%02d", (time < 0 ? "-" : ""), minutes, seconds);
480d0825bca7fe65beaee391d30da42e937db621564Steve Block}
481d0825bca7fe65beaee391d30da42e937db621564Steve Block
482d0825bca7fe65beaee391d30da42e937db621564Steve Blockvoid FullscreenVideoController::draw()
483d0825bca7fe65beaee391d30da42e937db621564Steve Block{
484d0825bca7fe65beaee391d30da42e937db621564Steve Block    HDC windowDC = GetDC(m_hudWindow);
485d0825bca7fe65beaee391d30da42e937db621564Steve Block    HDC bitmapDC = CreateCompatibleDC(windowDC);
486d0825bca7fe65beaee391d30da42e937db621564Steve Block    ::ReleaseDC(m_hudWindow, windowDC);
4875abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    HGDIOBJ oldBitmap = SelectObject(bitmapDC, m_bitmap.get());
488d0825bca7fe65beaee391d30da42e937db621564Steve Block
489d0825bca7fe65beaee391d30da42e937db621564Steve Block    GraphicsContext context(bitmapDC, true);
490d0825bca7fe65beaee391d30da42e937db621564Steve Block
491d0825bca7fe65beaee391d30da42e937db621564Steve Block    context.save();
492d0825bca7fe65beaee391d30da42e937db621564Steve Block
493d0825bca7fe65beaee391d30da42e937db621564Steve Block    // Draw the background
494d0825bca7fe65beaee391d30da42e937db621564Steve Block    IntSize outerRadius(borderRadius, borderRadius);
495d0825bca7fe65beaee391d30da42e937db621564Steve Block    IntRect outerRect(0, 0, windowWidth, windowHeight);
496d0825bca7fe65beaee391d30da42e937db621564Steve Block    IntSize innerRadius(borderRadius - borderThickness, borderRadius - borderThickness);
497d0825bca7fe65beaee391d30da42e937db621564Steve Block    IntRect innerRect(borderThickness, borderThickness, windowWidth - borderThickness * 2, windowHeight - borderThickness * 2);
498d0825bca7fe65beaee391d30da42e937db621564Steve Block
499a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    context.fillRoundedRect(outerRect, outerRadius, outerRadius, outerRadius, outerRadius, Color(borderColor), ColorSpaceDeviceRGB);
500d0825bca7fe65beaee391d30da42e937db621564Steve Block    context.setCompositeOperation(CompositeCopy);
501a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    context.fillRoundedRect(innerRect, innerRadius, innerRadius, innerRadius, innerRadius, Color(backgroundColor), ColorSpaceDeviceRGB);
502d0825bca7fe65beaee391d30da42e937db621564Steve Block
503d0825bca7fe65beaee391d30da42e937db621564Steve Block    // Draw the widgets
504d0825bca7fe65beaee391d30da42e937db621564Steve Block    m_playPauseButton.draw(context);
505d0825bca7fe65beaee391d30da42e937db621564Steve Block    m_volumeUpButton.draw(context);
506d0825bca7fe65beaee391d30da42e937db621564Steve Block    m_volumeSliderButton.draw(context);
507d0825bca7fe65beaee391d30da42e937db621564Steve Block    m_volumeDownButton.draw(context);
508d0825bca7fe65beaee391d30da42e937db621564Steve Block    m_timeSliderButton.draw(context);
509d0825bca7fe65beaee391d30da42e937db621564Steve Block    m_exitFullscreenButton.draw(context);
510d0825bca7fe65beaee391d30da42e937db621564Steve Block    m_volumeSlider.draw(context);
511d0825bca7fe65beaee391d30da42e937db621564Steve Block    m_timeSlider.draw(context);
512d0825bca7fe65beaee391d30da42e937db621564Steve Block
513d0825bca7fe65beaee391d30da42e937db621564Steve Block    // Draw the text strings
514d0825bca7fe65beaee391d30da42e937db621564Steve Block    FontDescription desc;
515d0825bca7fe65beaee391d30da42e937db621564Steve Block
516d0825bca7fe65beaee391d30da42e937db621564Steve Block    NONCLIENTMETRICS metrics;
517d0825bca7fe65beaee391d30da42e937db621564Steve Block    metrics.cbSize = sizeof(metrics);
518d0825bca7fe65beaee391d30da42e937db621564Steve Block    SystemParametersInfo(SPI_GETNONCLIENTMETRICS, metrics.cbSize, &metrics, 0);
519d0825bca7fe65beaee391d30da42e937db621564Steve Block    FontFamily family;
520d0825bca7fe65beaee391d30da42e937db621564Steve Block    family.setFamily(metrics.lfSmCaptionFont.lfFaceName);
521d0825bca7fe65beaee391d30da42e937db621564Steve Block    desc.setFamily(family);
522d0825bca7fe65beaee391d30da42e937db621564Steve Block
523d0825bca7fe65beaee391d30da42e937db621564Steve Block    desc.setComputedSize(textSize);
524d0825bca7fe65beaee391d30da42e937db621564Steve Block    Font font = Font(desc, 0, 0);
525d0825bca7fe65beaee391d30da42e937db621564Steve Block    font.update(0);
526d0825bca7fe65beaee391d30da42e937db621564Steve Block
527d0825bca7fe65beaee391d30da42e937db621564Steve Block    String s;
528d0825bca7fe65beaee391d30da42e937db621564Steve Block
529d0825bca7fe65beaee391d30da42e937db621564Steve Block    // The y positioning of these two text strings is tricky because they are so small. They
530d0825bca7fe65beaee391d30da42e937db621564Steve Block    // are currently positioned relative to the center of the slider and then down the font
531d0825bca7fe65beaee391d30da42e937db621564Steve Block    // height / 4 (which is actually half of font height /2), which positions the center of
532d0825bca7fe65beaee391d30da42e937db621564Steve Block    // the text at the center of the slider.
533d0825bca7fe65beaee391d30da42e937db621564Steve Block    // Left string
534d0825bca7fe65beaee391d30da42e937db621564Steve Block    s = timeToString(currentTime());
5352fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    int fontHeight = font.fontMetrics().height();
536d0825bca7fe65beaee391d30da42e937db621564Steve Block    TextRun leftText(s);
537a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    context.setFillColor(Color(textColor), ColorSpaceDeviceRGB);
5382fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    context.drawText(font, leftText, IntPoint(windowWidth / 2 - timeSliderWidth / 2 - margin - font.width(leftText), windowHeight - margin - sliderHeight / 2 + fontHeight / 4));
539d0825bca7fe65beaee391d30da42e937db621564Steve Block
540d0825bca7fe65beaee391d30da42e937db621564Steve Block    // Right string
541d0825bca7fe65beaee391d30da42e937db621564Steve Block    s = timeToString(currentTime() - duration());
542d0825bca7fe65beaee391d30da42e937db621564Steve Block    TextRun rightText(s);
543a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    context.setFillColor(Color(textColor), ColorSpaceDeviceRGB);
5442fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    context.drawText(font, rightText, IntPoint(windowWidth / 2 + timeSliderWidth / 2 + margin, windowHeight - margin - sliderHeight / 2 + fontHeight / 4));
545d0825bca7fe65beaee391d30da42e937db621564Steve Block
546d0825bca7fe65beaee391d30da42e937db621564Steve Block    // Copy to the window
547d0825bca7fe65beaee391d30da42e937db621564Steve Block    BLENDFUNCTION blendFunction = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA};
548d0825bca7fe65beaee391d30da42e937db621564Steve Block    SIZE size = { windowWidth, windowHeight };
549d0825bca7fe65beaee391d30da42e937db621564Steve Block    POINT sourcePoint = {0, 0};
550d0825bca7fe65beaee391d30da42e937db621564Steve Block    POINT destPoint = { m_hudPosition.x(), m_hudPosition.y() };
551d0825bca7fe65beaee391d30da42e937db621564Steve Block    BOOL result = UpdateLayeredWindow(m_hudWindow, 0, &destPoint, &size, bitmapDC, &sourcePoint, 0, &blendFunction, ULW_ALPHA);
552d0825bca7fe65beaee391d30da42e937db621564Steve Block
553d0825bca7fe65beaee391d30da42e937db621564Steve Block    context.restore();
554d0825bca7fe65beaee391d30da42e937db621564Steve Block
5555abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    ::SelectObject(bitmapDC, oldBitmap);
556d0825bca7fe65beaee391d30da42e937db621564Steve Block    ::DeleteDC(bitmapDC);
557d0825bca7fe65beaee391d30da42e937db621564Steve Block}
558d0825bca7fe65beaee391d30da42e937db621564Steve Block
559d0825bca7fe65beaee391d30da42e937db621564Steve BlockLRESULT FullscreenVideoController::hudWndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lParam)
560d0825bca7fe65beaee391d30da42e937db621564Steve Block{
561d0825bca7fe65beaee391d30da42e937db621564Steve Block    LONG_PTR longPtr = GetWindowLongPtr(wnd, 0);
562d0825bca7fe65beaee391d30da42e937db621564Steve Block    FullscreenVideoController* controller = reinterpret_cast<FullscreenVideoController*>(longPtr);
563d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (!controller)
564d0825bca7fe65beaee391d30da42e937db621564Steve Block        return DefWindowProc(wnd, message, wParam, lParam);
565d0825bca7fe65beaee391d30da42e937db621564Steve Block
566d0825bca7fe65beaee391d30da42e937db621564Steve Block    switch (message) {
567d0825bca7fe65beaee391d30da42e937db621564Steve Block    case WM_CHAR:
568d0825bca7fe65beaee391d30da42e937db621564Steve Block        controller->onChar(wParam);
569d0825bca7fe65beaee391d30da42e937db621564Steve Block        break;
5705af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    case WM_KEYDOWN:
5715af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke        controller->onKeyDown(wParam);
5725af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke        break;
573d0825bca7fe65beaee391d30da42e937db621564Steve Block    case WM_LBUTTONDOWN:
574d0825bca7fe65beaee391d30da42e937db621564Steve Block        controller->onMouseDown(IntPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
575d0825bca7fe65beaee391d30da42e937db621564Steve Block        break;
576d0825bca7fe65beaee391d30da42e937db621564Steve Block    case WM_MOUSEMOVE:
577d0825bca7fe65beaee391d30da42e937db621564Steve Block        controller->onMouseMove(IntPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
578d0825bca7fe65beaee391d30da42e937db621564Steve Block        break;
579d0825bca7fe65beaee391d30da42e937db621564Steve Block    case WM_LBUTTONUP:
580d0825bca7fe65beaee391d30da42e937db621564Steve Block        controller->onMouseUp(IntPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
581d0825bca7fe65beaee391d30da42e937db621564Steve Block        break;
582d0825bca7fe65beaee391d30da42e937db621564Steve Block    }
583d0825bca7fe65beaee391d30da42e937db621564Steve Block
584d0825bca7fe65beaee391d30da42e937db621564Steve Block    return DefWindowProc(wnd, message, wParam, lParam);
585d0825bca7fe65beaee391d30da42e937db621564Steve Block}
586d0825bca7fe65beaee391d30da42e937db621564Steve Block
587d0825bca7fe65beaee391d30da42e937db621564Steve Blockvoid FullscreenVideoController::onChar(int c)
588d0825bca7fe65beaee391d30da42e937db621564Steve Block{
589d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (c == VK_ESCAPE) {
590d0825bca7fe65beaee391d30da42e937db621564Steve Block        if (m_mediaElement)
591d0825bca7fe65beaee391d30da42e937db621564Steve Block            m_mediaElement->exitFullscreen();
592d0825bca7fe65beaee391d30da42e937db621564Steve Block    } else if (c == VK_SPACE)
593d0825bca7fe65beaee391d30da42e937db621564Steve Block        togglePlay();
594d0825bca7fe65beaee391d30da42e937db621564Steve Block}
595d0825bca7fe65beaee391d30da42e937db621564Steve Block
5965af96e2c7b73ebc627c6894727826a7576d31758Leon Clarkevoid FullscreenVideoController::onKeyDown(int virtualKey)
5975af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke{
5985af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    if (virtualKey == VK_ESCAPE) {
5995af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke        if (m_mediaElement)
6005af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke            m_mediaElement->exitFullscreen();
6015af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    }
6025af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke}
6035af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke
604d0825bca7fe65beaee391d30da42e937db621564Steve Blockvoid FullscreenVideoController::timerFired(Timer<FullscreenVideoController>*)
605d0825bca7fe65beaee391d30da42e937db621564Steve Block{
606d0825bca7fe65beaee391d30da42e937db621564Steve Block    // Update the time slider
607d0825bca7fe65beaee391d30da42e937db621564Steve Block    m_timeSlider.setValue(currentTime() / duration());
608d0825bca7fe65beaee391d30da42e937db621564Steve Block    draw();
609d0825bca7fe65beaee391d30da42e937db621564Steve Block}
610d0825bca7fe65beaee391d30da42e937db621564Steve Block
611d0825bca7fe65beaee391d30da42e937db621564Steve Blockvoid FullscreenVideoController::onMouseDown(const IntPoint& point)
612d0825bca7fe65beaee391d30da42e937db621564Steve Block{
613dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    IntPoint convertedPoint(fullscreenToHUDCoordinates(point));
614d0825bca7fe65beaee391d30da42e937db621564Steve Block
615d0825bca7fe65beaee391d30da42e937db621564Steve Block    // Don't bother hit testing if we're outside the bounds of the window
616d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (convertedPoint.x() < 0 || convertedPoint.x() >= windowWidth || convertedPoint.y() < 0 || convertedPoint.y() >= windowHeight)
617d0825bca7fe65beaee391d30da42e937db621564Steve Block        return;
618d0825bca7fe65beaee391d30da42e937db621564Steve Block
619d0825bca7fe65beaee391d30da42e937db621564Steve Block    m_hitWidget = 0;
620d0825bca7fe65beaee391d30da42e937db621564Steve Block    m_movingWindow = false;
621d0825bca7fe65beaee391d30da42e937db621564Steve Block
622d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (m_playPauseButton.hitTest(convertedPoint))
623d0825bca7fe65beaee391d30da42e937db621564Steve Block        m_hitWidget = &m_playPauseButton;
624d0825bca7fe65beaee391d30da42e937db621564Steve Block    else if (m_exitFullscreenButton.hitTest(convertedPoint))
625d0825bca7fe65beaee391d30da42e937db621564Steve Block        m_hitWidget = &m_exitFullscreenButton;
626d0825bca7fe65beaee391d30da42e937db621564Steve Block    else if (m_volumeUpButton.hitTest(convertedPoint))
627d0825bca7fe65beaee391d30da42e937db621564Steve Block        m_hitWidget = &m_volumeUpButton;
628d0825bca7fe65beaee391d30da42e937db621564Steve Block    else if (m_volumeDownButton.hitTest(convertedPoint))
629d0825bca7fe65beaee391d30da42e937db621564Steve Block        m_hitWidget = &m_volumeDownButton;
630d0825bca7fe65beaee391d30da42e937db621564Steve Block    else if (m_volumeSlider.hitTest(convertedPoint)) {
631d0825bca7fe65beaee391d30da42e937db621564Steve Block        m_hitWidget = &m_volumeSlider;
632d0825bca7fe65beaee391d30da42e937db621564Steve Block        m_volumeSlider.drag(convertedPoint, true);
633d0825bca7fe65beaee391d30da42e937db621564Steve Block        setVolume(m_volumeSlider.value());
634d0825bca7fe65beaee391d30da42e937db621564Steve Block    } else if (m_timeSlider.hitTest(convertedPoint)) {
635d0825bca7fe65beaee391d30da42e937db621564Steve Block        m_hitWidget = &m_timeSlider;
636d0825bca7fe65beaee391d30da42e937db621564Steve Block        m_timeSlider.drag(convertedPoint, true);
637d0825bca7fe65beaee391d30da42e937db621564Steve Block        beginScrubbing();
638d0825bca7fe65beaee391d30da42e937db621564Steve Block        setCurrentTime(m_timeSlider.value() * duration());
639d0825bca7fe65beaee391d30da42e937db621564Steve Block    }
640d0825bca7fe65beaee391d30da42e937db621564Steve Block
641d0825bca7fe65beaee391d30da42e937db621564Steve Block    // If we did not pick any of our widgets we are starting a window move
642d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (!m_hitWidget) {
643d0825bca7fe65beaee391d30da42e937db621564Steve Block        m_moveOffset = convertedPoint;
644d0825bca7fe65beaee391d30da42e937db621564Steve Block        m_movingWindow = true;
645d0825bca7fe65beaee391d30da42e937db621564Steve Block    }
646d0825bca7fe65beaee391d30da42e937db621564Steve Block
647d0825bca7fe65beaee391d30da42e937db621564Steve Block    draw();
648d0825bca7fe65beaee391d30da42e937db621564Steve Block}
649d0825bca7fe65beaee391d30da42e937db621564Steve Block
650d0825bca7fe65beaee391d30da42e937db621564Steve Blockvoid FullscreenVideoController::onMouseMove(const IntPoint& point)
651d0825bca7fe65beaee391d30da42e937db621564Steve Block{
652dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    IntPoint convertedPoint(fullscreenToHUDCoordinates(point));
653d0825bca7fe65beaee391d30da42e937db621564Steve Block
654d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (m_hitWidget) {
655d0825bca7fe65beaee391d30da42e937db621564Steve Block        m_hitWidget->drag(convertedPoint, false);
656d0825bca7fe65beaee391d30da42e937db621564Steve Block        if (m_hitWidget == &m_volumeSlider)
657d0825bca7fe65beaee391d30da42e937db621564Steve Block            setVolume(m_volumeSlider.value());
658d0825bca7fe65beaee391d30da42e937db621564Steve Block        else if (m_hitWidget == &m_timeSlider)
659d0825bca7fe65beaee391d30da42e937db621564Steve Block            setCurrentTime(m_timeSlider.value() * duration());
660d0825bca7fe65beaee391d30da42e937db621564Steve Block        draw();
661d0825bca7fe65beaee391d30da42e937db621564Steve Block    } else if (m_movingWindow)
662d0825bca7fe65beaee391d30da42e937db621564Steve Block        m_hudPosition.move(convertedPoint.x() - m_moveOffset.x(), convertedPoint.y() - m_moveOffset.y());
663d0825bca7fe65beaee391d30da42e937db621564Steve Block}
664d0825bca7fe65beaee391d30da42e937db621564Steve Block
665d0825bca7fe65beaee391d30da42e937db621564Steve Blockvoid FullscreenVideoController::onMouseUp(const IntPoint& point)
666d0825bca7fe65beaee391d30da42e937db621564Steve Block{
667dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    IntPoint convertedPoint(fullscreenToHUDCoordinates(point));
668d0825bca7fe65beaee391d30da42e937db621564Steve Block    m_movingWindow = false;
669d0825bca7fe65beaee391d30da42e937db621564Steve Block
670d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (m_hitWidget) {
671d0825bca7fe65beaee391d30da42e937db621564Steve Block        if (m_hitWidget == &m_playPauseButton && m_playPauseButton.hitTest(convertedPoint))
672d0825bca7fe65beaee391d30da42e937db621564Steve Block            togglePlay();
673d0825bca7fe65beaee391d30da42e937db621564Steve Block        else if (m_hitWidget == &m_volumeUpButton && m_volumeUpButton.hitTest(convertedPoint)) {
674d0825bca7fe65beaee391d30da42e937db621564Steve Block            setVolume(1);
675d0825bca7fe65beaee391d30da42e937db621564Steve Block            m_volumeSlider.setValue(1);
676d0825bca7fe65beaee391d30da42e937db621564Steve Block        } else if (m_hitWidget == &m_volumeDownButton && m_volumeDownButton.hitTest(convertedPoint)) {
677d0825bca7fe65beaee391d30da42e937db621564Steve Block            setVolume(0);
678d0825bca7fe65beaee391d30da42e937db621564Steve Block            m_volumeSlider.setValue(0);
679d0825bca7fe65beaee391d30da42e937db621564Steve Block        } else if (m_hitWidget == &m_timeSlider)
680d0825bca7fe65beaee391d30da42e937db621564Steve Block            endScrubbing();
681d0825bca7fe65beaee391d30da42e937db621564Steve Block        else if (m_hitWidget == &m_exitFullscreenButton && m_exitFullscreenButton.hitTest(convertedPoint)) {
682d0825bca7fe65beaee391d30da42e937db621564Steve Block            m_hitWidget = 0;
683d0825bca7fe65beaee391d30da42e937db621564Steve Block            if (m_mediaElement)
684d0825bca7fe65beaee391d30da42e937db621564Steve Block                m_mediaElement->exitFullscreen();
685d0825bca7fe65beaee391d30da42e937db621564Steve Block            return;
686d0825bca7fe65beaee391d30da42e937db621564Steve Block        }
687d0825bca7fe65beaee391d30da42e937db621564Steve Block    }
688d0825bca7fe65beaee391d30da42e937db621564Steve Block
689d0825bca7fe65beaee391d30da42e937db621564Steve Block    m_hitWidget = 0;
690d0825bca7fe65beaee391d30da42e937db621564Steve Block    draw();
691d0825bca7fe65beaee391d30da42e937db621564Steve Block}
692d0825bca7fe65beaee391d30da42e937db621564Steve Block
693d0825bca7fe65beaee391d30da42e937db621564Steve Blockvoid FullscreenVideoController::togglePlay()
694d0825bca7fe65beaee391d30da42e937db621564Steve Block{
695d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (canPlay())
696d0825bca7fe65beaee391d30da42e937db621564Steve Block        play();
697d0825bca7fe65beaee391d30da42e937db621564Steve Block    else
698d0825bca7fe65beaee391d30da42e937db621564Steve Block        pause();
699d0825bca7fe65beaee391d30da42e937db621564Steve Block
700d0825bca7fe65beaee391d30da42e937db621564Steve Block    m_playPauseButton.setShowAltButton(!canPlay());
701d0825bca7fe65beaee391d30da42e937db621564Steve Block
702d0825bca7fe65beaee391d30da42e937db621564Steve Block    // Run a timer while the video is playing so we can keep the time
703d0825bca7fe65beaee391d30da42e937db621564Steve Block    // slider and time values up to date.
704d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (!canPlay())
705d0825bca7fe65beaee391d30da42e937db621564Steve Block        m_timer.startRepeating(timerInterval);
706d0825bca7fe65beaee391d30da42e937db621564Steve Block    else
707d0825bca7fe65beaee391d30da42e937db621564Steve Block        m_timer.stop();
708d0825bca7fe65beaee391d30da42e937db621564Steve Block
709d0825bca7fe65beaee391d30da42e937db621564Steve Block    draw();
710d0825bca7fe65beaee391d30da42e937db621564Steve Block}
711d0825bca7fe65beaee391d30da42e937db621564Steve Block
712d0825bca7fe65beaee391d30da42e937db621564Steve Block#endif
713