Merge branch 'bug/26304' into staging
authorphiln@webkit.org <philn@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 17 Dec 2009 19:13:42 +0000 (19:13 +0000)
committerphiln@webkit.org <philn@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 17 Dec 2009 19:13:42 +0000 (19:13 +0000)
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@52266 268f45cc-cd09-0410-ab3c-d52691b4dbfc

15 files changed:
LayoutTests/ChangeLog
LayoutTests/platform/gtk/Skipped
LayoutTests/platform/gtk/media/controls-after-reload-expected.txt [new file with mode: 0644]
LayoutTests/platform/gtk/media/controls-drag-timebar-expected.txt [new file with mode: 0644]
LayoutTests/platform/gtk/media/controls-strict-expected.txt [new file with mode: 0644]
LayoutTests/platform/gtk/media/controls-styling-expected.txt [new file with mode: 0644]
LayoutTests/platform/gtk/media/video-controls-rendering-expected.txt [new file with mode: 0644]
LayoutTests/platform/gtk/media/video-controls-visible-audio-only-expected.txt [new file with mode: 0644]
WebCore/ChangeLog
WebCore/GNUmakefile.am
WebCore/css/mediaControlsGtk.css [new file with mode: 0644]
WebCore/platform/graphics/Image.h
WebCore/platform/graphics/gtk/ImageGtk.cpp
WebCore/platform/gtk/RenderThemeGtk.cpp
WebCore/platform/gtk/RenderThemeGtk.h

index f28ff5617742d9d2c8db12d62be748302df9d32c..f84b94ea2c74268940e4cb8b987616367020c535 100644 (file)
@@ -1,3 +1,22 @@
+2009-12-07  Philippe Normand  <pnormand@igalia.com>
+
+        Reviewed by Xan Lopez.
+
+        [GTK] Add controls for playing html5 video.
+        https://bugs.webkit.org/show_bug.cgi?id=26304
+
+        Unskip some of the media tests related to the controls
+        UI. Generated results for the new ones, it will likely be needed
+        again when we add new features in the controls UI.
+
+        * platform/gtk/Skipped:
+        * platform/gtk/media/controls-after-reload-expected.txt: Added.
+        * platform/gtk/media/controls-drag-timebar-expected.txt: Added.
+        * platform/gtk/media/controls-strict-expected.txt: Added.
+        * platform/gtk/media/controls-styling-expected.txt: Added.
+        * platform/gtk/media/video-controls-rendering-expected.txt: Added.
+        * platform/gtk/media/video-controls-visible-audio-only-expected.txt: Copied from LayoutTests/platform/mac/media/video-controls-visible-audio-only-expected.txt.
+
 2009-12-17  Gustavo Noronha Silva  <gustavo.noronha@collabora.co.uk>
 
         Skipping one test that needs overriding of standard preferences,
index d57eadd3b979706240455ba8a6c122b1d7a636e5..2b9c717d1fbe6d640c0e7e570144d6f88bbcbc73 100644 (file)
@@ -3613,13 +3613,10 @@ media/restore-from-page-cache.html
 media/video-source-error.html
 
 #   Tests timing out
-media/controls-drag-timebar.html
 media/unsupported-rtsp.html
 #   Tests generating new results
 media/audio-controls-rendering.html
 media/video-aspect-ratio.html
-media/video-controls-rendering.html
-media/video-controls-visible-audio-only.html
 media/video-display-toggle.html
 media/video-empty-source.html
 media/video-layer-crash.html
@@ -5437,9 +5434,6 @@ fast/text/international/khmer-selection.html
 fast/text/shadow-translucent-fill.html
 fast/text/text-letter-spacing.html
 media/audio-no-installed-engines.html
-media/controls-after-reload.html
-media/controls-strict.html
-media/controls-styling.html
 svg/batik/filters/feTile.svg
 svg/custom/createImageElement.svg
 svg/custom/createImageElement2.xhtml
diff --git a/LayoutTests/platform/gtk/media/controls-after-reload-expected.txt b/LayoutTests/platform/gtk/media/controls-after-reload-expected.txt
new file mode 100644 (file)
index 0000000..08d9c92
--- /dev/null
@@ -0,0 +1,25 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  RenderBlock {HTML} at (0,0) size 800x600
+    RenderBody {BODY} at (8,8) size 784x584
+      RenderBlock {P} at (0,0) size 784x20
+        RenderText {#text} at (0,0) size 360x20
+          text run at (0,0) width 360: "Making sure the controller looks ok after a second load()."
+      RenderBlock (anonymous) at (0,36) size 784x240
+        RenderText {#text} at (0,0) size 0x0
+        RenderText {#text} at (0,0) size 0x0
+        RenderText {#text} at (0,0) size 0x0
+layer at (8,44) size 320x240
+  RenderVideo {VIDEO} at (0,0) size 320x240
+layer at (8,44) size 320x240
+  RenderBlock (relative positioned) {DIV} at (0,0) size 320x240
+layer at (8,264) size 320x20
+  RenderFlexibleBox (positioned) {DIV} at (0,220) size 320x20
+    RenderButton {INPUT} at (0,0) size 20x20
+    RenderFlexibleBox {DIV} at (20,0) size 240x20
+      RenderSlider {INPUT} at (0,0) size 240x20
+        RenderBlock {DIV} at (2,4) size 12x12
+    RenderButton {INPUT} at (260,0) size 20x20
+    RenderButton {INPUT} at (280,0) size 20x20
+    RenderButton {INPUT} at (300,0) size 20x20
diff --git a/LayoutTests/platform/gtk/media/controls-drag-timebar-expected.txt b/LayoutTests/platform/gtk/media/controls-drag-timebar-expected.txt
new file mode 100644 (file)
index 0000000..688b449
--- /dev/null
@@ -0,0 +1,13 @@
+Test that drag the timebar thumb causes seeks.
+
+RUN(video.autoplay = true)
+RUN(video.src = 'content/test.mp4')
+EVENT(playing)
+EVENT(seeked)
+Time: 2.2
+EVENT(seeked)
+Time: 2.7
+EVENT(seeked)
+Time: 3.2
+END OF TEST
+
diff --git a/LayoutTests/platform/gtk/media/controls-strict-expected.txt b/LayoutTests/platform/gtk/media/controls-strict-expected.txt
new file mode 100644 (file)
index 0000000..2508c1c
--- /dev/null
@@ -0,0 +1,25 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x305
+  RenderBlock {HTML} at (0,0) size 800x305
+    RenderBody {BODY} at (8,16) size 784x281
+      RenderBlock {P} at (0,0) size 784x20
+        RenderText {#text} at (0,0) size 226x20
+          text run at (0,0) width 226: "Drawing the controls in strict mode."
+      RenderBlock (anonymous) at (0,36) size 784x245
+        RenderText {#text} at (0,0) size 0x0
+        RenderText {#text} at (0,0) size 0x0
+        RenderText {#text} at (0,0) size 0x0
+layer at (8,52) size 320x240
+  RenderVideo {VIDEO} at (0,0) size 320x240
+layer at (8,52) size 320x240
+  RenderBlock (relative positioned) {DIV} at (0,0) size 320x240
+layer at (8,272) size 320x20
+  RenderFlexibleBox (positioned) {DIV} at (0,220) size 320x20
+    RenderButton {INPUT} at (0,0) size 20x20
+    RenderFlexibleBox {DIV} at (20,0) size 240x20
+      RenderSlider {INPUT} at (0,0) size 240x20
+        RenderBlock {DIV} at (2,4) size 12x12
+    RenderButton {INPUT} at (260,0) size 20x20
+    RenderButton {INPUT} at (280,0) size 20x20
+    RenderButton {INPUT} at (300,0) size 20x20
diff --git a/LayoutTests/platform/gtk/media/controls-styling-expected.txt b/LayoutTests/platform/gtk/media/controls-styling-expected.txt
new file mode 100644 (file)
index 0000000..7b97183
--- /dev/null
@@ -0,0 +1,40 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  RenderBlock {HTML} at (0,0) size 800x600
+    RenderBody {BODY} at (8,8) size 784x584
+      RenderBlock {P} at (0,0) size 784x20
+        RenderText {#text} at (0,0) size 274x20
+          text run at (0,0) width 274: "The look of the controls should not change."
+      RenderBlock {DIV} at (0,36) size 784x240 [color=#0000FF]
+        RenderText {#text} at (0,0) size 0x0
+      RenderBlock (anonymous) at (0,276) size 784x240
+        RenderText {#text} at (0,0) size 0x0
+        RenderText {#text} at (0,0) size 0x0
+        RenderText {#text} at (0,0) size 0x0
+layer at (18,44) size 320x240
+  RenderVideo {VIDEO} at (10,0) size 320x240
+layer at (8,284) size 320x240
+  RenderVideo {VIDEO} at (0,0) size 320x240
+layer at (18,44) size 320x240
+  RenderBlock (relative positioned) {DIV} at (0,0) size 320x240
+layer at (18,264) size 320x20
+  RenderFlexibleBox (positioned) {DIV} at (0,220) size 320x20
+    RenderButton {INPUT} at (0,0) size 20x20
+    RenderFlexibleBox {DIV} at (20,0) size 240x20
+      RenderSlider {INPUT} at (0,0) size 240x20
+        RenderBlock {DIV} at (2,4) size 12x12
+    RenderButton {INPUT} at (260,0) size 20x20
+    RenderButton {INPUT} at (280,0) size 20x20
+    RenderButton {INPUT} at (300,0) size 20x20
+layer at (8,284) size 320x240
+  RenderBlock (relative positioned) {DIV} at (0,0) size 320x240
+layer at (8,504) size 320x20
+  RenderFlexibleBox (positioned) {DIV} at (0,220) size 320x20
+    RenderButton {INPUT} at (0,0) size 20x20
+    RenderFlexibleBox {DIV} at (20,0) size 240x20
+      RenderSlider {INPUT} at (0,0) size 240x20
+        RenderBlock {DIV} at (2,4) size 12x12
+    RenderButton {INPUT} at (260,0) size 20x20
+    RenderButton {INPUT} at (280,0) size 20x20
+    RenderButton {INPUT} at (300,0) size 20x20
diff --git a/LayoutTests/platform/gtk/media/video-controls-rendering-expected.txt b/LayoutTests/platform/gtk/media/video-controls-rendering-expected.txt
new file mode 100644 (file)
index 0000000..add29fe
--- /dev/null
@@ -0,0 +1,52 @@
+layer at (0,0) size 781x764
+  RenderView at (0,0) size 781x600
+layer at (0,0) size 781x600
+  RenderBlock {HTML} at (0,0) size 781x600
+    RenderBody {BODY} at (8,8) size 765x584
+      RenderBlock {P} at (0,0) size 765x20
+        RenderText {#text} at (0,0) size 153x20
+          text run at (0,0) width 153: "Test controls placement."
+      RenderBlock {DIV} at (0,36) size 765x240
+        RenderText {#text} at (0,0) size 0x0
+      RenderBlock {DIV} at (0,276) size 765x240
+        RenderText {#text} at (0,0) size 0x0
+      RenderBlock {DIV} at (0,516) size 765x0
+layer at (8,44) size 320x240
+  RenderVideo {VIDEO} at (0,0) size 320x240
+layer at (8,284) size 320x240
+  RenderVideo {VIDEO} at (0,0) size 320x240
+layer at (8,44) size 320x240
+  RenderBlock (relative positioned) {DIV} at (0,0) size 320x240
+layer at (8,264) size 320x20
+  RenderFlexibleBox (positioned) {DIV} at (0,220) size 320x20
+    RenderButton {INPUT} at (0,0) size 20x20
+    RenderFlexibleBox {DIV} at (20,0) size 240x20
+      RenderSlider {INPUT} at (0,0) size 240x20
+        RenderBlock {DIV} at (2,4) size 12x12
+    RenderButton {INPUT} at (260,0) size 20x20
+    RenderButton {INPUT} at (280,0) size 20x20
+    RenderButton {INPUT} at (300,0) size 20x20
+layer at (8,284) size 320x240
+  RenderBlock (relative positioned) {DIV} at (0,0) size 320x240
+layer at (8,504) size 320x20
+  RenderFlexibleBox (positioned) {DIV} at (0,220) size 320x20
+    RenderButton {INPUT} at (0,0) size 20x20
+    RenderFlexibleBox {DIV} at (20,0) size 240x20
+      RenderSlider {INPUT} at (0,0) size 240x20
+        RenderBlock {DIV} at (2,4) size 12x12
+    RenderButton {INPUT} at (260,0) size 20x20
+    RenderButton {INPUT} at (280,0) size 20x20
+    RenderButton {INPUT} at (300,0) size 20x20
+layer at (8,524) size 320x240
+  RenderVideo {VIDEO} at (8,524) size 320x240
+layer at (8,524) size 320x240
+  RenderBlock (relative positioned) {DIV} at (0,0) size 320x240
+layer at (8,744) size 320x20
+  RenderFlexibleBox (positioned) {DIV} at (0,220) size 320x20
+    RenderButton {INPUT} at (0,0) size 20x20
+    RenderFlexibleBox {DIV} at (20,0) size 240x20
+      RenderSlider {INPUT} at (0,0) size 240x20
+        RenderBlock {DIV} at (2,4) size 12x12
+    RenderButton {INPUT} at (260,0) size 20x20
+    RenderButton {INPUT} at (280,0) size 20x20
+    RenderButton {INPUT} at (300,0) size 20x20
diff --git a/LayoutTests/platform/gtk/media/video-controls-visible-audio-only-expected.txt b/LayoutTests/platform/gtk/media/video-controls-visible-audio-only-expected.txt
new file mode 100644 (file)
index 0000000..ad66654
--- /dev/null
@@ -0,0 +1,11 @@
+Test video element control visibility when mouse is not over element.
+
+This test only runs in DRT!
+
+mouse parks here, am I blue?
+
+
+TEST(video.paused) OK
+TEST(!video.paused) OK
+
index c8b98df818799d9f3d2b09732ff332839e47ddeb..1f049bcae6bb8347e18c4b68ab0b0d5a459764a0 100644 (file)
@@ -1,3 +1,47 @@
+2009-12-10  Philippe Normand  <pnormand@igalia.com>
+
+        Reviewed by Xan Lopez.
+
+        [GTK] Add controls for playing html5 video.
+        https://bugs.webkit.org/show_bug.cgi?id=26304
+
+        Media controls UI, first step. This patch was written by Zan
+        Dobersek. In addition I fixed the compilation errors and
+        re-enabled some of the media tests involving the controls UI.
+
+        * GNUmakefile.am:
+        * css/mediaControlsGtk.css: Added.
+        * platform/graphics/Image.h:
+        * platform/graphics/gtk/ImageGtk.cpp:
+        (WebCore::getThemeIconFileName):
+        (WebCore::loadResourceSharedBuffer):
+        (WebCore::loadImageFromFile):
+        (WebCore::Image::loadPlatformResource):
+        (WebCore::Image::loadPlatformThemeIcon):
+        * platform/gtk/RenderThemeGtk.cpp:
+        (WebCore::getMediaElementFromRenderObject):
+        (WebCore::getIconNameForTextDirection):
+        (WebCore::RenderThemeGtk::initMediaStyling):
+        (WebCore::RenderThemeGtk::RenderThemeGtk):
+        (WebCore::RenderThemeGtk::~RenderThemeGtk):
+        (WebCore::supportsFocus):
+        (WebCore::RenderThemeGtk::baselinePosition):
+        (WebCore::paintMozWidget):
+        (WebCore::setToggleSize):
+        (WebCore::RenderThemeGtk::adjustSliderThumbSize):
+        (WebCore::RenderThemeGtk::gtkContainer):
+        (WebCore::RenderThemeGtk::platformColorsDidChange):
+        (WebCore::RenderThemeGtk::extraMediaControlsStyleSheet):
+        (WebCore::paintMediaButton):
+        (WebCore::RenderThemeGtk::paintMediaFullscreenButton):
+        (WebCore::RenderThemeGtk::paintMediaMuteButton):
+        (WebCore::RenderThemeGtk::paintMediaPlayButton):
+        (WebCore::RenderThemeGtk::paintMediaSeekBackButton):
+        (WebCore::RenderThemeGtk::paintMediaSeekForwardButton):
+        (WebCore::RenderThemeGtk::paintMediaSliderTrack):
+        (WebCore::RenderThemeGtk::paintMediaSliderThumb):
+        * platform/gtk/RenderThemeGtk.h:
+
 2009-12-17  Yael Aharon  <yael.aharon@nokia.com>
 
         Reviewed by Kenneth Rohde Christiansen.
index a5efdb77f812a26b8ac745d11752ae236d7b85e5..1e3a0e49f921118df30b257060515d1f009b5664 100644 (file)
@@ -3458,7 +3458,8 @@ USER_AGENT_STYLE_SHEETS = \
        $(WebCore)/css/view-source.css \
        $(WebCore)/css/svg.css \
        $(WebCore)/css/wml.css \
-       $(WebCore)/css/mediaControls.css
+       $(WebCore)/css/mediaControls.css \
+       $(WebCore)/css/mediaControlsGtk.css
 
 # new-style JavaScript bindings
 SCRIPTS_BINDINGS = \
@@ -3573,6 +3574,7 @@ webcore_dist += \
        WebCore/css/svg.css \
        WebCore/css/wml.css \
        WebCore/css/mediaControls.css \
+       WebCore/css/mediaControlsGtk.css \
        WebCore/css/CSSGrammar.y \
        WebCore/css/CSSValueKeywords.in \
        WebCore/css/SVGCSSPropertyNames.in \
diff --git a/WebCore/css/mediaControlsGtk.css b/WebCore/css/mediaControlsGtk.css
new file mode 100644 (file)
index 0000000..8e98ab1
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * WebKitGTK+ specific overrides for HTML5 media elements.
+ *
+ * Copyright (C) 2009 Zan Dobersek <zandobersek@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+audio {
+    height: 20px;
+    width: 300px;
+}
+
+audio::-webkit-media-controls-panel, video::-webkit-media-controls-panel {
+    height: 20px;
+}
+
+audio::-webkit-media-controls-mute-button, video::-webkit-media-controls-mute-button {
+    width: 20px;
+    height: 20px;
+}
+
+audio::-webkit-media-controls-play-button, video::-webkit-media-controls-play-button {
+    width: 20px;
+    height: 20px;
+}
+
+audio::-webkit-media-controls-timeline-container, video::-webkit-media-controls-timeline-container {
+    height: 20px;
+}
+
+audio::-webkit-media-controls-timeline, video::-webkit-media-controls-timeline {
+    height: 20px;
+}
+
+audio::-webkit-media-controls-seek-back-button, video::-webkit-media-controls-seek-back-button {
+    width: 20px;
+    height: 20px;
+}
+
+audio::-webkit-media-controls-seek-forward-button, video::-webkit-media-controls-seek-forward-button {
+    width: 20px;
+    height: 20px;
+}
+
+audio::-webkit-media-controls-fullscreen-button, video::-webkit-media-controls-fullscreen-button {
+    width: 20px;
+    height: 20px;
+}
index 90ebe4df8283138314136b491c78ce0275a3b844..1af3bf19c52c69cf68b62eccccaa16b30a3bd3aa 100644 (file)
@@ -150,6 +150,7 @@ public:
 
 #if PLATFORM(GTK)
     virtual GdkPixbuf* getGdkPixbuf() { return 0; }
+    static PassRefPtr<Image> loadPlatformThemeIcon(const char* name, int size);
 #endif
 
 protected:
index 38da70d1c672f2b59514604e7fe04492dd96fbbb..62635795f970715aba3fe3de6b85aac037eed165 100644 (file)
@@ -44,29 +44,24 @@ template <> void freeOwnedGPtr<GtkIconInfo>(GtkIconInfo* info)
 
 namespace WebCore {
 
-static CString getIconFileNameOrFallback(const char* name, const char* fallback)
+static CString getThemeIconFileName(const char* name, int size)
 {
-    GOwnPtr<GtkIconInfo> info(gtk_icon_theme_lookup_icon(gtk_icon_theme_get_default(),
-                                                         name, 16, GTK_ICON_LOOKUP_NO_SVG));
-    if (!info)
-        return String::format("%s/webkit-1.0/images/%s.png", DATA_DIR, fallback).utf8();
-
+    GtkIconInfo* iconInfo = gtk_icon_theme_lookup_icon(gtk_icon_theme_get_default(),
+                                                       name, size, GTK_ICON_LOOKUP_NO_SVG);
+    if (!iconInfo)
+        iconInfo = gtk_icon_theme_lookup_icon(gtk_icon_theme_get_default(),
+                                              GTK_STOCK_MISSING_IMAGE, size,
+                                              GTK_ICON_LOOKUP_NO_SVG);
+
+    GOwnPtr<GtkIconInfo> info(iconInfo);
     return CString(gtk_icon_info_get_filename(info.get()));
 }
 
-static PassRefPtr<SharedBuffer> loadResourceSharedBuffer(const char* name)
+static PassRefPtr<SharedBuffer> loadResourceSharedBuffer(CString name)
 {
-    CString fileName;
-
-    // Find the path for the image
-    if (strcmp("missingImage", name) == 0)
-        fileName = getIconFileNameOrFallback(GTK_STOCK_MISSING_IMAGE, "missingImage");
-    else
-        fileName = String::format("%s/webkit-1.0/images/%s.png", DATA_DIR, name).utf8();
-
     GOwnPtr<gchar> content;
     gsize length;
-    if (!g_file_get_contents(fileName.data(), &content.outPtr(), &length, 0))
+    if (!g_file_get_contents(name.data(), &content.outPtr(), &length, 0))
         return SharedBuffer::create();
 
     return SharedBuffer::create(content.get(), length);
@@ -80,14 +75,30 @@ void BitmapImage::invalidatePlatformData()
 {
 }
 
-PassRefPtr<Image> Image::loadPlatformResource(const char* name)
+PassRefPtr<Image> loadImageFromFile(CString fileName)
 {
     RefPtr<BitmapImage> img = BitmapImage::create();
-    RefPtr<SharedBuffer> buffer = loadResourceSharedBuffer(name);
+    RefPtr<SharedBuffer> buffer = loadResourceSharedBuffer(fileName);
     img->setData(buffer.release(), true);
     return img.release();
 }
 
+PassRefPtr<Image> Image::loadPlatformResource(const char* name)
+{
+    CString fileName;
+    if (!strcmp("missingImage", name))
+        fileName = getThemeIconFileName(GTK_STOCK_MISSING_IMAGE, 16);
+    if (fileName.isNull())
+        fileName = String::format("%s/webkit-1.0/images/%s.png", DATA_DIR, name).utf8();
+
+    return loadImageFromFile(fileName);
+}
+
+PassRefPtr<Image> Image::loadPlatformThemeIcon(const char* name, int size)
+{
+    return loadImageFromFile(getThemeIconFileName(name, size));
+}
+
 static inline unsigned char* getCairoSurfacePixel(unsigned char* data, uint x, uint y, uint rowStride)
 {
     return data + (y * rowStride) + x * 4;
index 4842d68c345dee0b08a9b63aed24382b9db7d6f5..3cc14f8d910784e7e4676ffffca9beffc5d02207 100644 (file)
 #include "config.h"
 #include "RenderThemeGtk.h"
 
-#include "TransformationMatrix.h"
+#include "CString.h"
+#include "GOwnPtr.h"
 #include "GraphicsContext.h"
+#include "HTMLMediaElement.h"
+#include "HTMLNames.h"
 #include "NotImplemented.h"
 #include "RenderBox.h"
 #include "RenderObject.h"
+#include "TransformationMatrix.h"
+#include "UserAgentStyleSheets.h"
 #include "gtkdrawing.h"
 
 #include <gdk/gdk.h>
 
 namespace WebCore {
 
+using namespace HTMLNames;
+
+#if ENABLE(VIDEO)
+static HTMLMediaElement* getMediaElementFromRenderObject(RenderObject* o)
+{
+    Node* node = o->node();
+    Node* mediaNode = node ? node->shadowAncestorNode() : 0;
+    if (!mediaNode || (!mediaNode->hasTagName(videoTag) && !mediaNode->hasTagName(audioTag)))
+        return 0;
+
+    return static_cast<HTMLMediaElement*>(mediaNode);
+}
+
+static gchar* getIconNameForTextDirection(const char* baseName)
+{
+    GString* nameWithDirection = g_string_new(baseName);
+    GtkTextDirection textDirection = gtk_widget_get_default_direction();
+
+    if (textDirection == GTK_TEXT_DIR_RTL)
+        g_string_append(nameWithDirection, "-rtl");
+    else if (textDirection == GTK_TEXT_DIR_LTR)
+        g_string_append(nameWithDirection, "-ltr");
+
+    return g_string_free(nameWithDirection, FALSE);
+}
+
+void RenderThemeGtk::initMediaStyling(GtkStyle* style, bool force)
+{
+    static bool stylingInitialized = false;
+
+    if (!stylingInitialized || force) {
+        m_panelColor = style->bg[GTK_STATE_NORMAL];
+        m_sliderColor = style->bg[GTK_STATE_ACTIVE];
+        m_sliderThumbColor = style->bg[GTK_STATE_SELECTED];
+
+        // Names of these icons can vary because of text direction.
+        gchar* playButtonIconName = getIconNameForTextDirection("gtk-media-play");
+        gchar* seekBackButtonIconName = getIconNameForTextDirection("gtk-media-rewind");
+        gchar* seekForwardButtonIconName = getIconNameForTextDirection("gtk-media-forward");
+
+        m_fullscreenButton.clear();
+        m_muteButton.clear();
+        m_unmuteButton.clear();
+        m_playButton.clear();
+        m_pauseButton.clear();
+        m_seekBackButton.clear();
+        m_seekForwardButton.clear();
+
+        m_fullscreenButton = Image::loadPlatformThemeIcon("gtk-fullscreen", m_mediaIconSize);
+        m_muteButton = Image::loadPlatformThemeIcon("audio-volume-muted", m_mediaIconSize);
+        m_unmuteButton = Image::loadPlatformThemeIcon("audio-volume-high", m_mediaIconSize);
+        m_playButton = Image::loadPlatformThemeIcon(reinterpret_cast<const char*>(playButtonIconName), m_mediaIconSize);
+        m_pauseButton = Image::loadPlatformThemeIcon("gtk-media-pause", m_mediaIconSize).releaseRef();
+        m_seekBackButton = Image::loadPlatformThemeIcon(reinterpret_cast<const char*>(seekBackButtonIconName), m_mediaIconSize);
+        m_seekForwardButton = Image::loadPlatformThemeIcon(reinterpret_cast<const char*>(seekForwardButtonIconName), m_mediaIconSize);
+
+        g_free(playButtonIconName);
+        g_free(seekBackButtonIconName);
+        g_free(seekForwardButtonIconName);
+        stylingInitialized = true;
+    }
+}
+#endif
+
 PassRefPtr<RenderTheme> RenderThemeGtk::create()
 {
     return adoptRef(new RenderThemeGtk());
@@ -53,11 +122,29 @@ RenderThemeGtk::RenderThemeGtk()
     , m_gtkContainer(0)
     , m_gtkEntry(0)
     , m_gtkTreeView(0)
+    , m_panelColor(Color::white)
+    , m_sliderColor(Color::white)
+    , m_sliderThumbColor(Color::white)
+    , m_mediaIconSize(16)
+    , m_mediaSliderHeight(14)
+    , m_mediaSliderThumbWidth(12)
+    , m_mediaSliderThumbHeight(12)
+    , m_fullscreenButton(0)
+    , m_muteButton(0)
+    , m_unmuteButton(0)
+    , m_playButton(0)
+    , m_pauseButton(0)
+    , m_seekBackButton(0)
+    , m_seekForwardButton(0)
 {
     if (!mozGtkRefCount)
         moz_gtk_init();
 
     ++mozGtkRefCount;
+
+#if ENABLE(VIDEO)
+    initMediaStyling(gtk_rc_get_style(GTK_WIDGET(gtkContainer())), false);
+#endif
 }
 
 RenderThemeGtk::~RenderThemeGtk()
@@ -66,22 +153,30 @@ RenderThemeGtk::~RenderThemeGtk()
 
     if (!mozGtkRefCount)
         moz_gtk_shutdown();
+
+    m_fullscreenButton.clear();
+    m_muteButton.clear();
+    m_unmuteButton.clear();
+    m_playButton.clear();
+    m_pauseButton.clear();
+    m_seekBackButton.clear();
+    m_seekForwardButton.clear();
 }
 
 static bool supportsFocus(ControlPart appearance)
 {
     switch (appearance) {
-        case PushButtonPart:
-        case ButtonPart:
-        case TextFieldPart:
-        case TextAreaPart:
-        case SearchFieldPart:
-        case MenulistPart:
-        case RadioPart:
-        case CheckboxPart:
-            return true;
-        default:
-            return false;
+    case PushButtonPart:
+    case ButtonPart:
+    case TextFieldPart:
+    case TextAreaPart:
+    case SearchFieldPart:
+    case MenulistPart:
+    case RadioPart:
+    case CheckboxPart:
+        return true;
+    default:
+        return false;
     }
 }
 
@@ -101,8 +196,8 @@ int RenderThemeGtk::baselinePosition(const RenderObject* o) const
         return 0;
 
     // FIXME: This strategy is possibly incorrect for the GTK+ port.
-    if (o->style()->appearance() == CheckboxPart ||
-        o->style()->appearance() == RadioPart) {
+    if (o->style()->appearance() == CheckboxPart
+        || o->style()->appearance() == RadioPart) {
         const RenderBox* box = toRenderBox(o);
         return box->marginTop() + box->height() - 2;
     }
@@ -170,16 +265,16 @@ static bool paintMozWidget(RenderTheme* theme, GtkThemeWidgetType type, RenderOb
 
     // We might want to make setting flags the caller's job at some point rather than doing it here.
     switch (type) {
-        case MOZ_GTK_BUTTON:
-            flags = GTK_RELIEF_NORMAL;
-            break;
-        case MOZ_GTK_CHECKBUTTON:
-        case MOZ_GTK_RADIOBUTTON:
-            flags = theme->isChecked(o);
-            break;
-        default:
-            flags = 0;
-            break;
+    case MOZ_GTK_BUTTON:
+        flags = GTK_RELIEF_NORMAL;
+        break;
+    case MOZ_GTK_CHECKBUTTON:
+    case MOZ_GTK_RADIOBUTTON:
+        flags = theme->isChecked(o);
+        break;
+    default:
+        flags = 0;
+        break;
     }
 
     TransformationMatrix ctm = i.context->getCTM();
@@ -189,7 +284,7 @@ static bool paintMozWidget(RenderTheme* theme, GtkThemeWidgetType type, RenderOb
     GtkTextDirection direction = gtkTextDirection(o->style()->direction());
 
     // Find the clip rectangle
-    cairo_t *cr = i.context->platformContext();
+    cairo_tcr = i.context->platformContext();
     double clipX1, clipX2, clipY1, clipY2;
     cairo_clip_extents(cr, &clipX1, &clipY1, &clipX2, &clipY2);
 
@@ -221,25 +316,25 @@ static void setToggleSize(RenderStyle* style, ControlPart appearance)
     if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
         return;
 
-    // FIXME: This is probably not correct use of indicator_size and indicator_spacing.
-    gint indicator_size, indicator_spacing;
+    // FIXME: This is probably not correct use of indicatorSize and indicatorSpacing.
+    gint indicatorSize, indicatorSpacing;
 
     switch (appearance) {
-        case CheckboxPart:
-            if (moz_gtk_checkbox_get_metrics(&indicator_size, &indicator_spacing) != MOZ_GTK_SUCCESS)
-                return;
-            break;
-        case RadioPart:
-            if (moz_gtk_radio_get_metrics(&indicator_size, &indicator_spacing) != MOZ_GTK_SUCCESS)
-                return;
-            break;
-        default:
+    case CheckboxPart:
+        if (moz_gtk_checkbox_get_metrics(&indicatorSize, &indicatorSpacing) != MOZ_GTK_SUCCESS)
+            return;
+        break;
+    case RadioPart:
+        if (moz_gtk_radio_get_metrics(&indicatorSize, &indicatorSpacing) != MOZ_GTK_SUCCESS)
             return;
+        break;
+    default:
+        return;
     }
 
     // Other ports hard-code this to 13, but GTK+ users tend to demand the native look.
     // It could be made a configuration option values other than 13 actually break site compatibility.
-    int length = indicator_size + indicator_spacing;
+    int length = indicatorSize + indicatorSpacing;
     if (style->width().isIntrinsicOrAuto())
         style->setWidth(Length(length, Fixed));
 
@@ -373,6 +468,16 @@ bool RenderThemeGtk::paintSearchField(RenderObject* o, const RenderObject::Paint
     return paintTextField(o, i, rect);
 }
 
+void RenderThemeGtk::adjustSliderThumbSize(RenderObject* o) const
+{
+#if ENABLE(VIDEO)
+    if (o->style()->appearance() == MediaSliderThumbPart) {
+        o->style()->setWidth(Length(m_mediaSliderThumbWidth, Fixed));
+        o->style()->setHeight(Length(m_mediaSliderThumbHeight, Fixed));
+    }
+#endif
+}
+
 Color RenderThemeGtk::platformActiveSelectionBackgroundColor() const
 {
     GtkWidget* widget = gtkEntry();
@@ -455,6 +560,7 @@ GtkContainer* RenderThemeGtk::gtkContainer() const
 
     m_gtkWindow = gtk_window_new(GTK_WINDOW_POPUP);
     m_gtkContainer = GTK_CONTAINER(gtk_fixed_new());
+    g_signal_connect(m_gtkWindow, "style-set", G_CALLBACK(gtkStyleSetCallback), const_cast<RenderThemeGtk*>(this));
     gtk_container_add(GTK_CONTAINER(m_gtkWindow), GTK_WIDGET(m_gtkContainer));
     gtk_widget_realize(m_gtkWindow);
 
@@ -487,4 +593,78 @@ GtkWidget* RenderThemeGtk::gtkTreeView() const
     return m_gtkTreeView;
 }
 
+void RenderThemeGtk::platformColorsDidChange()
+{
+#if ENABLE(VIDEO)
+    initMediaStyling(gtk_rc_get_style(GTK_WIDGET(gtkContainer())), true);
+#endif
+    RenderTheme::platformColorsDidChange();
+}
+
+#if ENABLE(VIDEO)
+String RenderThemeGtk::extraMediaControlsStyleSheet()
+{
+    return String(mediaControlsGtkUserAgentStyleSheet, sizeof(mediaControlsGtkUserAgentStyleSheet));
+}
+
+static inline bool paintMediaButton(GraphicsContext* context, const IntRect& r, Image* image, Color panelColor, int mediaIconSize)
+{
+    context->fillRect(FloatRect(r), panelColor, DeviceColorSpace);
+    context->drawImage(image, DeviceColorSpace,
+                       IntRect(r.x() + (r.width() - mediaIconSize) / 2,
+                               r.y() + (r.height() - mediaIconSize) / 2,
+                               mediaIconSize, mediaIconSize));
+
+    return false;
+}
+
+bool RenderThemeGtk::paintMediaFullscreenButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    return paintMediaButton(paintInfo.context, r, m_fullscreenButton.get(), m_panelColor, m_mediaIconSize);
+}
+
+bool RenderThemeGtk::paintMediaMuteButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    HTMLMediaElement* mediaElement = getMediaElementFromRenderObject(o);
+    if (!mediaElement)
+        return false;
+
+    return paintMediaButton(paintInfo.context, r, mediaElement->muted() ? m_unmuteButton.get() : m_muteButton.get(), m_panelColor, m_mediaIconSize);
+}
+
+bool RenderThemeGtk::paintMediaPlayButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    HTMLMediaElement* mediaElement = getMediaElementFromRenderObject(o);
+    if (!mediaElement)
+        return false;
+
+    return paintMediaButton(paintInfo.context, r, mediaElement->canPlay() ? m_playButton.get() : m_pauseButton.get(), m_panelColor, m_mediaIconSize);
+}
+
+bool RenderThemeGtk::paintMediaSeekBackButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    return paintMediaButton(paintInfo.context, r, m_seekBackButton.get(), m_panelColor, m_mediaIconSize);
+}
+
+bool RenderThemeGtk::paintMediaSeekForwardButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    return paintMediaButton(paintInfo.context, r, m_seekForwardButton.get(), m_panelColor, m_mediaIconSize);
+}
+
+bool RenderThemeGtk::paintMediaSliderTrack(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    paintInfo.context->fillRect(FloatRect(r), m_panelColor, DeviceColorSpace);
+    paintInfo.context->fillRect(FloatRect(IntRect(r.x(), r.y() + (r.height() - m_mediaSliderHeight) / 2,
+                                                  r.width(), m_mediaSliderHeight)), m_sliderColor, DeviceColorSpace);
+    return false;
+}
+
+bool RenderThemeGtk::paintMediaSliderThumb(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    // Make the thumb nicer with rounded corners.
+    paintInfo.context->fillRoundedRect(r, IntSize(3, 3), IntSize(3, 3), IntSize(3, 3), IntSize(3, 3), m_sliderThumbColor, DeviceColorSpace);
+    return false;
+}
+#endif
+
 }
index 13daaa2c091957d7a88942c252b366779301fbb9..6a154ad85579dd2e674f7f11666e49a5e88d7b40 100644 (file)
@@ -73,9 +73,15 @@ public:
 
     virtual double caretBlinkInterval() const;
 
+    virtual void platformColorsDidChange();
+
     // System fonts.
     virtual void systemFont(int propId, FontDescription&) const;
 
+#if ENABLE(VIDEO)
+    virtual String extraMediaControlsStyleSheet();
+#endif
+
 protected:
     virtual bool paintCheckbox(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r);
     virtual void setCheckboxSize(RenderStyle* style) const;
@@ -106,6 +112,18 @@ protected:
     virtual void adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
     virtual bool paintSearchFieldCancelButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
 
+    virtual void adjustSliderThumbSize(RenderObject*) const;
+
+#if ENABLE(VIDEO)
+    virtual void initMediaStyling(GtkStyle* style, bool force);
+    virtual bool paintMediaFullscreenButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+    virtual bool paintMediaPlayButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+    virtual bool paintMediaMuteButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+    virtual bool paintMediaSeekBackButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+    virtual bool paintMediaSeekForwardButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+    virtual bool paintMediaSliderTrack(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+    virtual bool paintMediaSliderThumb(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+#endif
 
 private:
     /*
@@ -125,6 +143,24 @@ private:
     mutable GtkContainer* m_gtkContainer;
     mutable GtkWidget* m_gtkEntry;
     mutable GtkWidget* m_gtkTreeView;
+
+    mutable Color m_panelColor;
+    mutable Color m_sliderColor;
+    mutable Color m_sliderThumbColor;
+
+    const int m_mediaIconSize;
+    const int m_mediaSliderHeight;
+    const int m_mediaSliderThumbWidth;
+    const int m_mediaSliderThumbHeight;
+
+    RefPtr<Image> m_fullscreenButton;
+    RefPtr<Image> m_muteButton;
+    RefPtr<Image> m_unmuteButton;
+    RefPtr<Image> m_playButton;
+    RefPtr<Image> m_pauseButton;
+    RefPtr<Image> m_seekBackButton;
+    RefPtr<Image> m_seekForwardButton;
+
 };
 
 }