summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/gtk
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/platform/gtk')
-rw-r--r--WebCore/platform/gtk/ClipboardGtk.h2
-rw-r--r--WebCore/platform/gtk/DataObjectGtk.h4
-rw-r--r--WebCore/platform/gtk/FileSystemGtk.cpp3
-rw-r--r--WebCore/platform/gtk/GOwnPtrGtk.h3
-rw-r--r--WebCore/platform/gtk/GRefPtrGtk.h3
-rw-r--r--WebCore/platform/gtk/GtkVersioning.c (renamed from WebCore/platform/gtk/GtkVersioning.cpp)21
-rw-r--r--WebCore/platform/gtk/GtkVersioning.h11
-rw-r--r--WebCore/platform/gtk/PasteboardHelper.h7
-rw-r--r--WebCore/platform/gtk/PopupMenuGtk.h4
-rw-r--r--WebCore/platform/gtk/RenderThemeGtk.cpp164
-rw-r--r--WebCore/platform/gtk/RenderThemeGtk.h21
-rw-r--r--WebCore/platform/gtk/ScrollbarGtk.h2
-rw-r--r--WebCore/platform/gtk/ScrollbarThemeGtk.cpp323
-rw-r--r--WebCore/platform/gtk/ScrollbarThemeGtk.h44
-rw-r--r--WebCore/platform/gtk/gtk2drawing.c3
15 files changed, 483 insertions, 132 deletions
diff --git a/WebCore/platform/gtk/ClipboardGtk.h b/WebCore/platform/gtk/ClipboardGtk.h
index 8b8ee38..f0af318 100644
--- a/WebCore/platform/gtk/ClipboardGtk.h
+++ b/WebCore/platform/gtk/ClipboardGtk.h
@@ -31,8 +31,6 @@
#include "Clipboard.h"
#include "DataObjectGtk.h"
-typedef struct _GtkClipboard GtkClipboard;
-
namespace WebCore {
class CachedImage;
class Frame;
diff --git a/WebCore/platform/gtk/DataObjectGtk.h b/WebCore/platform/gtk/DataObjectGtk.h
index 6f7149c..e6095da 100644
--- a/WebCore/platform/gtk/DataObjectGtk.h
+++ b/WebCore/platform/gtk/DataObjectGtk.h
@@ -27,10 +27,6 @@
#include <wtf/text/CString.h>
#include <wtf/text/StringHash.h>
-typedef struct _GdkPixbuf GdkPixbuf;
-typedef struct _GdkDragContext GdkDragContext;
-typedef struct _GtkClipboard GtkClipboard;
-
namespace WebCore {
class DataObjectGtk : public RefCounted<DataObjectGtk> {
diff --git a/WebCore/platform/gtk/FileSystemGtk.cpp b/WebCore/platform/gtk/FileSystemGtk.cpp
index 7ad2a39..6f3fa19 100644
--- a/WebCore/platform/gtk/FileSystemGtk.cpp
+++ b/WebCore/platform/gtk/FileSystemGtk.cpp
@@ -187,8 +187,7 @@ String pathGetFileName(const String& pathName)
String directoryName(const String& path)
{
/* No null checking needed */
- GOwnPtr<char> tmpFilename(const_cast<char*>(fileSystemRepresentation(path).data()));
- GOwnPtr<char> dirname(g_path_get_dirname(tmpFilename.get()));
+ GOwnPtr<char> dirname(g_path_get_dirname(fileSystemRepresentation(path).data()));
return String::fromUTF8(dirname.get());
}
diff --git a/WebCore/platform/gtk/GOwnPtrGtk.h b/WebCore/platform/gtk/GOwnPtrGtk.h
index 8341661..c5d9cdc 100644
--- a/WebCore/platform/gtk/GOwnPtrGtk.h
+++ b/WebCore/platform/gtk/GOwnPtrGtk.h
@@ -22,9 +22,6 @@
#include "GOwnPtr.h"
-typedef union _GdkEvent GdkEvent;
-typedef struct _GtkIconInfo GtkIconInfo;
-
namespace WTF {
template <> void freeOwnedGPtr<GdkEvent>(GdkEvent*);
diff --git a/WebCore/platform/gtk/GRefPtrGtk.h b/WebCore/platform/gtk/GRefPtrGtk.h
index ea1b089..5e6ab78 100644
--- a/WebCore/platform/gtk/GRefPtrGtk.h
+++ b/WebCore/platform/gtk/GRefPtrGtk.h
@@ -23,9 +23,6 @@
#include "GRefPtr.h"
-typedef struct _GtkTargetList GtkTargetList;
-typedef struct _GdkCursor GdkCursor;
-
namespace WTF {
template <> GtkTargetList* refPlatformPtr(GtkTargetList* ptr);
diff --git a/WebCore/platform/gtk/GtkVersioning.cpp b/WebCore/platform/gtk/GtkVersioning.c
index e7734a8..7dd601e 100644
--- a/WebCore/platform/gtk/GtkVersioning.cpp
+++ b/WebCore/platform/gtk/GtkVersioning.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2010 Collabora Ltd.
+ * Copyright (C) 2010 Igalia, S.L.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -17,7 +18,6 @@
* Boston, MA 02110-1301, USA.
*/
-#include "config.h"
#include "GtkVersioning.h"
#include <gtk/gtk.h>
@@ -48,3 +48,22 @@ void gtk_adjustment_configure(GtkAdjustment* adjustment, gdouble value, gdouble
gtk_adjustment_value_changed(adjustment);
}
#endif
+
+GdkDevice *getDefaultGDKPointerDevice(GdkWindow* window)
+{
+#ifndef GTK_API_VERSION_2
+ GdkDeviceManager *manager = gdk_display_get_device_manager(gdk_drawable_get_display(window));
+ return gdk_device_manager_get_client_pointer(manager);
+#else
+ return gdk_device_get_core_pointer();
+#endif // GTK_API_VERSION_2
+}
+
+#if !GTK_CHECK_VERSION(2, 17, 3)
+static void gdk_window_get_root_coords(GdkWindow* window, gint x, gint y, gint* rootX, gint* rootY)
+{
+ gdk_window_get_root_origin(window, rootX, rootY);
+ *rootX = *rootX + x;
+ *rootY = *rootY + y;
+}
+#endif
diff --git a/WebCore/platform/gtk/GtkVersioning.h b/WebCore/platform/gtk/GtkVersioning.h
index 34e6081..eac3cb5 100644
--- a/WebCore/platform/gtk/GtkVersioning.h
+++ b/WebCore/platform/gtk/GtkVersioning.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2010 Collabora Ltd.
+ * Copyright (C) 2010 Igalia, S.L.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -22,6 +23,8 @@
#include <gtk/gtk.h>
+G_BEGIN_DECLS
+
// Macros to avoid deprecation checking churn
#if !GTK_CHECK_VERSION(2, 21, 2)
#define gdk_visual_get_depth(visual) (visual)->depth
@@ -51,6 +54,10 @@
#define gtk_widget_set_allocation(widget, alloc) ((widget)->allocation = *(alloc))
#endif // GTK_CHECK_VERSION(2, 18, 0)
+#if !GTK_CHECK_VERSION(2, 17, 3)
+static void gdk_window_get_root_coords(GdkWindow* window, gint x, gint y, gint* rootX, gint* rootY);
+#endif //GTK_CHECK_VERSION(2, 17, 3)
+
#if !GTK_CHECK_VERSION(2, 14, 0)
#define gtk_widget_get_window(widget) (widget)->window
#define gtk_adjustment_get_value(adj) (adj)->value
@@ -67,4 +74,8 @@ void gtk_adjustment_configure(GtkAdjustment* adjustment, gdouble value, gdouble
void gtk_adjustment_set_value(GtkAdjustment* adjusment, gdouble value);
#endif // GTK_CHECK_VERSION(2, 14, 0)
+GdkDevice* getDefaultGDKPointerDevice(GdkWindow* window);
+
+G_END_DECLS
+
#endif // GtkVersioning_h
diff --git a/WebCore/platform/gtk/PasteboardHelper.h b/WebCore/platform/gtk/PasteboardHelper.h
index 33be1a8..bb1b580 100644
--- a/WebCore/platform/gtk/PasteboardHelper.h
+++ b/WebCore/platform/gtk/PasteboardHelper.h
@@ -32,13 +32,6 @@
#include "Frame.h"
-typedef struct _GtkClipboard GtkClipboard;
-typedef struct _GtkTargetList GtkTargetList;
-typedef struct _GtkWidget GtkWidget;
-typedef struct _GtkSelectionData GtkSelectionData;
-typedef struct _GdkDragContext GdkDragContext;
-typedef struct _GdkAtom* GdkAtom;
-
namespace WebCore {
class DataObjectGtk;
diff --git a/WebCore/platform/gtk/PopupMenuGtk.h b/WebCore/platform/gtk/PopupMenuGtk.h
index d63e6d9..8848e06 100644
--- a/WebCore/platform/gtk/PopupMenuGtk.h
+++ b/WebCore/platform/gtk/PopupMenuGtk.h
@@ -29,10 +29,6 @@
#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
-typedef struct _GtkMenu GtkMenu;
-typedef struct _GtkMenuItem GtkMenuItem;
-typedef struct _GtkWidget GtkWidget;
-
namespace WebCore {
class FrameView;
diff --git a/WebCore/platform/gtk/RenderThemeGtk.cpp b/WebCore/platform/gtk/RenderThemeGtk.cpp
index 5019f35..9329179 100644
--- a/WebCore/platform/gtk/RenderThemeGtk.cpp
+++ b/WebCore/platform/gtk/RenderThemeGtk.cpp
@@ -34,8 +34,11 @@
#include "HTMLNames.h"
#include "MediaControlElements.h"
#include "NotImplemented.h"
+#include "PlatformMouseEvent.h"
#include "RenderBox.h"
#include "RenderObject.h"
+#include "Scrollbar.h"
+#include "TimeRanges.h"
#include "UserAgentStyleSheets.h"
#include "gtkdrawing.h"
#include <gdk/gdk.h>
@@ -281,55 +284,24 @@ static void adjustMozillaStyle(const RenderThemeGtk* theme, RenderStyle* style,
style->setPaddingBottom(Length(ypadding + bottom, Fixed));
}
-static void setMozillaState(const RenderTheme* theme, GtkThemeWidgetType type, RenderObject* o, GtkWidgetState* state)
-{
- state->active = theme->isPressed(o);
- state->focused = theme->isFocused(o);
- state->inHover = theme->isHovered(o);
- // FIXME: Disabled does not always give the correct appearance for ReadOnly
- state->disabled = !theme->isEnabled(o) || theme->isReadOnlyControl(o);
- state->isDefault = false;
- state->canDefault = false;
-
-
- // FIXME: The depressed value should probably apply for other theme parts too.
- // It must be used for range thumbs, because otherwise when the thumb is pressed,
- // the rendering is incorrect.
- if (type == MOZ_GTK_SCALE_THUMB_HORIZONTAL || type == MOZ_GTK_SCALE_THUMB_VERTICAL)
- state->depressed = theme->isPressed(o);
- else
- state->depressed = false;
-}
-
-static bool paintMozillaGtkWidget(const RenderThemeGtk* theme, GtkThemeWidgetType type, RenderObject* o, const PaintInfo& i, const IntRect& rect)
+bool RenderThemeGtk::paintMozillaGtkWidget(GtkThemeWidgetType type, GraphicsContext* context, const IntRect& rect, GtkWidgetState* widgetState, int flags, GtkTextDirection textDirection)
{
// Painting is disabled so just claim to have succeeded
- if (i.context->paintingDisabled())
+ if (context->paintingDisabled())
return false;
- GtkWidgetState widgetState;
- setMozillaState(theme, type, o, &widgetState);
-
- // We might want to make setting flags the caller's job at some point rather than doing it here.
- int flags = 0;
- if (type == MOZ_GTK_BUTTON)
- flags = GTK_RELIEF_NORMAL;
- else if (type == MOZ_GTK_CHECKBUTTON || type == MOZ_GTK_RADIOBUTTON)
- flags = theme->isChecked(o);
-
- PlatformRefPtr<GdkDrawable> drawable(i.context->gdkDrawable());
+ PlatformRefPtr<GdkDrawable> drawable(context->gdkDrawable());
GdkRectangle paintRect, clipRect;
if (drawable) {
- AffineTransform ctm = i.context->getCTM();
+ AffineTransform ctm = context->getCTM();
IntPoint pos = ctm.mapPoint(rect.location());
paintRect = IntRect(pos.x(), pos.y(), rect.width(), rect.height());
// Intersect the cairo rectangle with the target widget region. This will
// prevent the theme drawing code from drawing into regions that cairo will
// clip anyway.
- cairo_t* cr = i.context->platformContext();
double clipX1, clipX2, clipY1, clipY2;
- cairo_clip_extents(cr, &clipX1, &clipY1, &clipX2, &clipY2);
+ cairo_clip_extents(context->platformContext(), &clipX1, &clipY1, &clipX2, &clipY2);
IntPoint clipPos = ctm.mapPoint(IntPoint(clipX1, clipY1));
clipRect.width = clipX2 - clipX1;
@@ -346,13 +318,13 @@ static bool paintMozillaGtkWidget(const RenderThemeGtk* theme, GtkThemeWidgetTyp
paintRect = clipRect = IntRect(0, 0, rect.width(), rect.height());
}
- moz_gtk_use_theme_parts(theme->partsForDrawable(drawable.get()));
- bool success = moz_gtk_widget_paint(type, drawable.get(), &paintRect, &clipRect, &widgetState, flags, gtkTextDirection(o->style()->direction())) == MOZ_GTK_SUCCESS;
+ moz_gtk_use_theme_parts(partsForDrawable(drawable.get()));
+ bool success = moz_gtk_widget_paint(type, drawable.get(), &paintRect, &clipRect, widgetState, flags, textDirection) == MOZ_GTK_SUCCESS;
// If the drawing was successful and we rendered onto a pixmap, copy the
// results back to the original GraphicsContext.
- if (success && !i.context->gdkDrawable()) {
- cairo_t* cairoContext = i.context->platformContext();
+ if (success && !context->gdkDrawable()) {
+ cairo_t* cairoContext = context->platformContext();
cairo_save(cairoContext);
gdk_cairo_set_source_pixmap(cairoContext, drawable.get(), rect.x(), rect.y());
cairo_paint(cairoContext);
@@ -362,6 +334,34 @@ static bool paintMozillaGtkWidget(const RenderThemeGtk* theme, GtkThemeWidgetTyp
return !success;
}
+bool RenderThemeGtk::paintRenderObject(GtkThemeWidgetType type, RenderObject* renderObject, GraphicsContext* context, const IntRect& rect, int flags)
+{
+ // Painting is disabled so just claim to have succeeded
+ if (context->paintingDisabled())
+ return false;
+
+ GtkWidgetState widgetState;
+ widgetState.active = isPressed(renderObject);
+ widgetState.focused = isFocused(renderObject);
+ widgetState.inHover = isHovered(renderObject);
+
+ // FIXME: Disabled does not always give the correct appearance for ReadOnly
+ widgetState.disabled = !isEnabled(renderObject) || isReadOnlyControl(renderObject);
+ widgetState.isDefault = false;
+ widgetState.canDefault = false;
+
+ // FIXME: The depressed value should probably apply for other theme parts too.
+ // It must be used for range thumbs, because otherwise when the thumb is pressed,
+ // the rendering is incorrect.
+ if (type == MOZ_GTK_SCALE_THUMB_HORIZONTAL || type == MOZ_GTK_SCALE_THUMB_VERTICAL)
+ widgetState.depressed = isPressed(renderObject);
+ else
+ widgetState.depressed = false;
+
+ GtkTextDirection textDirection = gtkTextDirection(renderObject->style()->direction());
+ return paintMozillaGtkWidget(type, context, rect, &widgetState, flags, textDirection);
+}
+
static void setButtonPadding(RenderStyle* style)
{
// FIXME: This looks incorrect.
@@ -411,7 +411,7 @@ void RenderThemeGtk::setCheckboxSize(RenderStyle* style) const
bool RenderThemeGtk::paintCheckbox(RenderObject* o, const PaintInfo& i, const IntRect& rect)
{
- return paintMozillaGtkWidget(this, MOZ_GTK_CHECKBUTTON, o, i, rect);
+ return paintRenderObject(MOZ_GTK_CHECKBUTTON, o, i.context, rect, isChecked(o));
}
void RenderThemeGtk::setRadioSize(RenderStyle* style) const
@@ -421,7 +421,7 @@ void RenderThemeGtk::setRadioSize(RenderStyle* style) const
bool RenderThemeGtk::paintRadio(RenderObject* o, const PaintInfo& i, const IntRect& rect)
{
- return paintMozillaGtkWidget(this, MOZ_GTK_RADIOBUTTON, o, i, rect);
+ return paintRenderObject(MOZ_GTK_RADIOBUTTON, o, i.context, rect, isChecked(o));
}
void RenderThemeGtk::adjustButtonStyle(CSSStyleSelector* selector, RenderStyle* style, WebCore::Element* e) const
@@ -442,7 +442,7 @@ void RenderThemeGtk::adjustButtonStyle(CSSStyleSelector* selector, RenderStyle*
bool RenderThemeGtk::paintButton(RenderObject* o, const PaintInfo& i, const IntRect& rect)
{
- return paintMozillaGtkWidget(this, MOZ_GTK_BUTTON, o, i, rect);
+ return paintRenderObject(MOZ_GTK_BUTTON, o, i.context, rect, GTK_RELIEF_NORMAL);
}
void RenderThemeGtk::adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, WebCore::Element* e) const
@@ -456,7 +456,7 @@ void RenderThemeGtk::adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle
bool RenderThemeGtk::paintMenuList(RenderObject* o, const PaintInfo& i, const IntRect& rect)
{
- return paintMozillaGtkWidget(this, MOZ_GTK_DROPDOWN, o, i, rect);
+ return paintRenderObject(MOZ_GTK_DROPDOWN, o, i.context, rect);
}
void RenderThemeGtk::adjustTextFieldStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
@@ -470,7 +470,7 @@ void RenderThemeGtk::adjustTextFieldStyle(CSSStyleSelector* selector, RenderStyl
bool RenderThemeGtk::paintTextField(RenderObject* o, const PaintInfo& i, const IntRect& rect)
{
- return paintMozillaGtkWidget(this, MOZ_GTK_ENTRY, o, i, rect);
+ return paintRenderObject(MOZ_GTK_ENTRY, o, i.context, rect);
}
bool RenderThemeGtk::paintTextArea(RenderObject* o, const PaintInfo& i, const IntRect& r)
@@ -550,7 +550,7 @@ bool RenderThemeGtk::paintSliderTrack(RenderObject* object, const PaintInfo& inf
if (part == SliderVerticalPart)
gtkPart = MOZ_GTK_SCALE_VERTICAL;
- return paintMozillaGtkWidget(this, gtkPart, object, info, rect);
+ return paintRenderObject(gtkPart, object, info.context, rect);
}
void RenderThemeGtk::adjustSliderTrackStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
@@ -567,7 +567,7 @@ bool RenderThemeGtk::paintSliderThumb(RenderObject* object, const PaintInfo& inf
if (part == SliderThumbVerticalPart)
gtkPart = MOZ_GTK_SCALE_THUMB_VERTICAL;
- return paintMozillaGtkWidget(this, gtkPart, object, info, rect);
+ return paintRenderObject(gtkPart, object, info.context, rect);
}
void RenderThemeGtk::adjustSliderThumbStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
@@ -732,6 +732,11 @@ GtkWidget* RenderThemeGtk::gtkTreeView() const
return m_gtkTreeView;
}
+GtkWidget* RenderThemeGtk::gtkScrollbar()
+{
+ return moz_gtk_get_scrollbar_widget();
+}
+
void RenderThemeGtk::platformColorsDidChange()
{
#if ENABLE(VIDEO)
@@ -806,33 +811,48 @@ bool RenderThemeGtk::paintMediaSliderTrack(RenderObject* o, const PaintInfo& pai
return false;
// Draw the buffered ranges. This code is highly inspired from
- // Chrome.
- // FIXME: Draw multiple ranges if there are multiple buffered
- // ranges. The current implementation of the player is always
- // buffering a single range anyway.
- IntRect bufferedRect = r;
- bufferedRect.inflate(-style->borderLeftWidth());
- bufferedRect.setWidth((bufferedRect.width() * mediaElement->percentLoaded()));
-
- // Don't bother drawing an empty area.
- if (bufferedRect.isEmpty())
- return false;
-
- IntPoint sliderTopLeft = bufferedRect.location();
- IntPoint sliderTopRight = sliderTopLeft;
- sliderTopRight.move(0, bufferedRect.height());
-
- RefPtr<Gradient> gradient = Gradient::create(sliderTopLeft, sliderTopRight);
- Color startColor = m_panelColor;
- gradient->addColorStop(0.0, startColor);
- gradient->addColorStop(1.0, Color(startColor.red() / 2, startColor.green() / 2, startColor.blue() / 2, startColor.alpha()));
+ // Chrome for the gradient code.
+ float mediaDuration = mediaElement->duration();
+ RefPtr<TimeRanges> timeRanges = mediaElement->buffered();
+ IntRect trackRect = r;
+ int totalWidth = trackRect.width();
+ trackRect.inflate(-style->borderLeftWidth());
context->save();
context->setStrokeStyle(NoStroke);
- context->setFillGradient(gradient);
- context->fillRect(bufferedRect);
- context->restore();
+ for (unsigned index = 0; index < timeRanges->length(); ++index) {
+ ExceptionCode ignoredException;
+ float start = timeRanges->start(index, ignoredException);
+ float end = timeRanges->end(index, ignoredException);
+ int width = ((end - start) * totalWidth) / mediaDuration;
+ IntRect rangeRect;
+ if (!index) {
+ rangeRect = trackRect;
+ rangeRect.setWidth(width);
+ } else {
+ rangeRect.setLocation(IntPoint((start * totalWidth) / mediaDuration, trackRect.y()));
+ rangeRect.setSize(IntSize(width, trackRect.height()));
+ }
+
+ // Don't bother drawing empty range.
+ if (rangeRect.isEmpty())
+ continue;
+
+ IntPoint sliderTopLeft = rangeRect.location();
+ IntPoint sliderTopRight = sliderTopLeft;
+ sliderTopRight.move(0, rangeRect.height());
+
+ RefPtr<Gradient> gradient = Gradient::create(sliderTopLeft, sliderTopRight);
+ Color startColor = m_panelColor;
+ gradient->addColorStop(0.0, startColor);
+ gradient->addColorStop(1.0, Color(startColor.red() / 2, startColor.green() / 2, startColor.blue() / 2, startColor.alpha()));
+
+ context->setFillGradient(gradient);
+ context->fillRect(rangeRect);
+ }
+
+ context->restore();
return false;
}
@@ -873,7 +893,7 @@ bool RenderThemeGtk::paintProgressBar(RenderObject* renderObject, const PaintInf
if (!progressBarWidget)
return true;
- if (paintMozillaGtkWidget(this, MOZ_GTK_PROGRESSBAR, renderObject, paintInfo, rect))
+ if (paintRenderObject(MOZ_GTK_PROGRESSBAR, renderObject, paintInfo.context, rect))
return true;
IntRect chunkRect(rect);
@@ -888,7 +908,7 @@ bool RenderThemeGtk::paintProgressBar(RenderObject* renderObject, const PaintInf
else
chunkRect.setX(chunkRect.x() + style->xthickness);
- return paintMozillaGtkWidget(this, MOZ_GTK_PROGRESS_CHUNK, renderObject, paintInfo, chunkRect);
+ return paintRenderObject(MOZ_GTK_PROGRESS_CHUNK, renderObject, paintInfo.context, chunkRect);
}
#endif
diff --git a/WebCore/platform/gtk/RenderThemeGtk.h b/WebCore/platform/gtk/RenderThemeGtk.h
index b9c076d..4e24c97 100644
--- a/WebCore/platform/gtk/RenderThemeGtk.h
+++ b/WebCore/platform/gtk/RenderThemeGtk.h
@@ -29,21 +29,9 @@
#define RenderThemeGtk_h
#include "GRefPtr.h"
+#include "gtkdrawing.h"
#include "RenderTheme.h"
-typedef struct _GtkWidget GtkWidget;
-typedef struct _GtkStyle GtkStyle;
-typedef struct _GtkContainer GtkContainer;
-#ifdef GTK_API_VERSION_2
-typedef struct _GdkRectangle GdkRectangle;
-#else
-typedef struct _cairo_rectangle_int cairo_rectangle_int_t;
-typedef cairo_rectangle_int_t GdkRectangle;
-#endif
-typedef struct _GdkDrawable GdkDrawable;
-typedef struct _GtkBorder GtkBorder;
-typedef struct _GtkThemeParts GtkThemeParts;
-
namespace WebCore {
class RenderThemeGtk : public RenderTheme {
@@ -95,7 +83,9 @@ public:
virtual String extraMediaControlsStyleSheet();
#endif
- GtkThemeParts* partsForDrawable(GdkDrawable*) const;
+ bool paintMozillaGtkWidget(GtkThemeWidgetType, GraphicsContext*, const IntRect&, GtkWidgetState*, int flags, GtkTextDirection = GTK_TEXT_DIR_NONE);
+
+ GtkWidget* gtkScrollbar();
protected:
virtual bool paintCheckbox(RenderObject* o, const PaintInfo& i, const IntRect& r);
@@ -167,6 +157,9 @@ private:
*/
GtkContainer* gtkContainer() const;
+ bool paintRenderObject(GtkThemeWidgetType, RenderObject*, GraphicsContext*, const IntRect& rect, int flags = 0);
+ GtkThemeParts* partsForDrawable(GdkDrawable*) const;
+
mutable GtkWidget* m_gtkWindow;
mutable GtkContainer* m_gtkContainer;
mutable GtkWidget* m_gtkButton;
diff --git a/WebCore/platform/gtk/ScrollbarGtk.h b/WebCore/platform/gtk/ScrollbarGtk.h
index e02bb50..1a078c9 100644
--- a/WebCore/platform/gtk/ScrollbarGtk.h
+++ b/WebCore/platform/gtk/ScrollbarGtk.h
@@ -29,8 +29,6 @@
#include "Scrollbar.h"
#include <wtf/PassRefPtr.h>
-typedef struct _GtkAdjustment GtkAdjustment;
-
namespace WebCore {
class ScrollbarGtk : public Scrollbar {
diff --git a/WebCore/platform/gtk/ScrollbarThemeGtk.cpp b/WebCore/platform/gtk/ScrollbarThemeGtk.cpp
index fee2c70..b6efe54 100644
--- a/WebCore/platform/gtk/ScrollbarThemeGtk.cpp
+++ b/WebCore/platform/gtk/ScrollbarThemeGtk.cpp
@@ -26,30 +26,339 @@
#include "config.h"
#include "ScrollbarThemeGtk.h"
+#include "PlatformMouseEvent.h"
+#include "RenderThemeGtk.h"
+#include "ScrollView.h"
+#include "Scrollbar.h"
#include "gtkdrawing.h"
#include <gtk/gtk.h>
namespace WebCore {
+static HashSet<Scrollbar*>* gScrollbars;
+static void gtkStyleSetCallback(GtkWidget*, GtkStyle*, ScrollbarThemeGtk*);
+
ScrollbarTheme* ScrollbarTheme::nativeTheme()
{
static ScrollbarThemeGtk theme;
return &theme;
}
+ScrollbarThemeGtk::ScrollbarThemeGtk()
+{
+ updateThemeProperties();
+ g_signal_connect(static_cast<RenderThemeGtk*>(RenderTheme::defaultTheme().get())->gtkScrollbar(),
+ "style-set", G_CALLBACK(gtkStyleSetCallback), this);
+}
+
ScrollbarThemeGtk::~ScrollbarThemeGtk()
{
}
-int ScrollbarThemeGtk::scrollbarThickness(ScrollbarControlSize controlSize)
+void ScrollbarThemeGtk::registerScrollbar(Scrollbar* scrollbar)
+{
+ if (!gScrollbars)
+ gScrollbars = new HashSet<Scrollbar*>;
+ gScrollbars->add(scrollbar);
+}
+
+void ScrollbarThemeGtk::unregisterScrollbar(Scrollbar* scrollbar)
+{
+ gScrollbars->remove(scrollbar);
+ if (gScrollbars->isEmpty()) {
+ delete gScrollbars;
+ gScrollbars = 0;
+ }
+}
+
+void ScrollbarThemeGtk::updateThemeProperties()
+{
+ MozGtkScrollbarMetrics metrics;
+ moz_gtk_get_scrollbar_metrics(&metrics);
+
+ m_thumbFatness = metrics.slider_width;
+ m_troughBorderWidth = metrics.trough_border;
+ m_stepperSize = metrics.stepper_size;
+ m_stepperSpacing = metrics.stepper_spacing;
+ m_minThumbLength = metrics.min_slider_size;
+ m_troughUnderSteppers = metrics.trough_under_steppers;
+
+ if (!gScrollbars)
+ return;
+
+ // Update the thickness of every interior frame scrollbar widget. The
+ // platform-independent scrollbar them code isn't yet smart enough to get
+ // this information when it paints.
+ HashSet<Scrollbar*>::iterator end = gScrollbars->end();
+ for (HashSet<Scrollbar*>::iterator it = gScrollbars->begin(); it != end; ++it) {
+ Scrollbar* scrollbar = (*it);
+
+ // Top-level scrollbar i.e. scrollbars who have a parent ScrollView
+ // with no parent are native, and thus do not need to be resized.
+ if (!scrollbar->parent() || !scrollbar->parent()->parent())
+ return;
+
+ int thickness = scrollbarThickness(scrollbar->controlSize());
+ if (scrollbar->orientation() == HorizontalScrollbar)
+ scrollbar->setFrameRect(IntRect(0, scrollbar->parent()->height() - thickness, scrollbar->width(), thickness));
+ else
+ scrollbar->setFrameRect(IntRect(scrollbar->parent()->width() - thickness, 0, thickness, scrollbar->height()));
+ }
+}
+
+static void gtkStyleSetCallback(GtkWidget* widget, GtkStyle* previous, ScrollbarThemeGtk* scrollbarTheme)
+{
+ scrollbarTheme->updateThemeProperties();
+}
+
+bool ScrollbarThemeGtk::hasThumb(Scrollbar* scrollbar)
+{
+ // This method is just called as a paint-time optimization to see if
+ // painting the thumb can be skipped. We don't have to be exact here.
+ return thumbLength(scrollbar) > 0;
+}
+
+IntRect ScrollbarThemeGtk::backButtonRect(Scrollbar* scrollbar, ScrollbarPart part, bool)
+{
+ // We do not support multiple steppers per end yet.
+ if (part == BackButtonEndPart)
+ return IntRect();
+
+ IntSize size = buttonSize(scrollbar);
+ return IntRect(scrollbar->x() + m_troughBorderWidth, scrollbar->y() + m_troughBorderWidth, size.width(), size.height());
+}
+
+IntRect ScrollbarThemeGtk::forwardButtonRect(Scrollbar* scrollbar, ScrollbarPart part, bool)
+{
+ // We do not support multiple steppers per end yet.
+ if (part == ForwardButtonStartPart)
+ return IntRect();
+
+ IntSize size = buttonSize(scrollbar);
+ int x, y;
+ if (scrollbar->orientation() == HorizontalScrollbar) {
+ x = scrollbar->x() + scrollbar->width() - size.width() - m_troughBorderWidth;
+ y = scrollbar->y() + m_troughBorderWidth;
+ } else {
+ x = scrollbar->x() + m_troughBorderWidth;
+ y = scrollbar->y() + scrollbar->height() - size.height() - m_troughBorderWidth;
+ }
+ return IntRect(x, y, size.width(), size.height());
+}
+
+IntRect ScrollbarThemeGtk::trackRect(Scrollbar* scrollbar, bool)
+{
+ // The padding along the thumb movement axis (from outside to in)
+ // is the size of trough border plus the size of the stepper (button)
+ // plus the size of stepper spacing (the space between the stepper and
+ // the place where the thumb stops). There is often no stepper spacing.
+ int movementAxisPadding = m_troughBorderWidth + m_stepperSize + m_stepperSpacing;
+
+ // The fatness of the scrollbar on the non-movement axis.
+ int thickness = scrollbarThickness(scrollbar->controlSize());
+
+ if (scrollbar->orientation() == HorizontalScrollbar) {
+ // Once the scrollbar becomes smaller than the natural size of the
+ // two buttons, the track disappears.
+ if (scrollbar->width() < 2 * thickness)
+ return IntRect();
+ return IntRect(scrollbar->x() + movementAxisPadding, scrollbar->y(), scrollbar->width() - (2 * movementAxisPadding), thickness);
+ }
+
+ if (scrollbar->height() < 2 * thickness)
+ return IntRect();
+ return IntRect(scrollbar->x(), scrollbar->y() + movementAxisPadding, thickness, scrollbar->height() - (2 * movementAxisPadding));
+}
+
+void ScrollbarThemeGtk::paintTrackBackground(GraphicsContext* context, Scrollbar* scrollbar, const IntRect& rect)
+{
+ GtkWidgetState state;
+ state.focused = FALSE;
+ state.isDefault = FALSE;
+ state.canDefault = FALSE;
+ state.disabled = FALSE;
+ state.active = FALSE;
+ state.inHover = FALSE;
+
+ // Paint the track background. If the trough-under-steppers property is true, this
+ // should be the full size of the scrollbar, but if is false, it should only be the
+ // track rect.
+ IntRect fullScrollbarRect = rect;
+ if (m_troughUnderSteppers)
+ fullScrollbarRect = IntRect(scrollbar->x(), scrollbar->y(), scrollbar->width(), scrollbar->height());
+
+ GtkThemeWidgetType type = scrollbar->orientation() == VerticalScrollbar ? MOZ_GTK_SCROLLBAR_TRACK_VERTICAL : MOZ_GTK_SCROLLBAR_TRACK_HORIZONTAL;
+ static_cast<RenderThemeGtk*>(RenderTheme::defaultTheme().get())->paintMozillaGtkWidget(type, context, fullScrollbarRect, &state, 0);
+}
+
+void ScrollbarThemeGtk::paintScrollbarBackground(GraphicsContext* context, Scrollbar* scrollbar)
+{
+ GtkWidgetState state;
+ state.focused = FALSE;
+ state.isDefault = FALSE;
+ state.canDefault = FALSE;
+ state.disabled = FALSE;
+ state.active = TRUE;
+ state.inHover = FALSE;
+
+ IntRect fullScrollbarRect = IntRect(scrollbar->x(), scrollbar->y(), scrollbar->width(), scrollbar->height());
+ static_cast<RenderThemeGtk*>(RenderTheme::defaultTheme().get())->paintMozillaGtkWidget(MOZ_GTK_SCROLLED_WINDOW, context, fullScrollbarRect, &state, 0);
+}
+
+void ScrollbarThemeGtk::paintThumb(GraphicsContext* context, Scrollbar* scrollbar, const IntRect& rect)
+{
+ GtkWidgetState state;
+ state.focused = FALSE;
+ state.isDefault = FALSE;
+ state.canDefault = FALSE;
+ state.disabled = FALSE;
+ state.active = scrollbar->pressedPart() == ThumbPart;
+ state.inHover = scrollbar->hoveredPart() == ThumbPart;
+ state.maxpos = scrollbar->maximum();
+ state.curpos = scrollbar->currentPos();
+
+ GtkThemeWidgetType type = scrollbar->orientation() == VerticalScrollbar ? MOZ_GTK_SCROLLBAR_THUMB_VERTICAL : MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL;
+ static_cast<RenderThemeGtk*>(RenderTheme::defaultTheme().get())->paintMozillaGtkWidget(type, context, rect, &state, 0);
+}
+
+IntRect ScrollbarThemeGtk::thumbRect(Scrollbar* scrollbar, const IntRect& unconstrainedTrackRect)
+{
+ IntRect trackRect = constrainTrackRectToTrackPieces(scrollbar, unconstrainedTrackRect);
+ int thumbPos = thumbPosition(scrollbar);
+ if (scrollbar->orientation() == HorizontalScrollbar)
+ return IntRect(trackRect.x() + thumbPos, trackRect.y() + (trackRect.height() - m_thumbFatness) / 2, thumbLength(scrollbar), m_thumbFatness);
+
+ // VerticalScrollbar
+ return IntRect(trackRect.x() + (trackRect.width() - m_thumbFatness) / 2, trackRect.y() + thumbPos, m_thumbFatness, thumbLength(scrollbar));
+}
+
+bool ScrollbarThemeGtk::paint(Scrollbar* scrollbar, GraphicsContext* graphicsContext, const IntRect& damageRect)
{
- static int size;
- if (!size) {
- MozGtkScrollbarMetrics metrics;
- moz_gtk_get_scrollbar_metrics(&metrics);
- size = metrics.slider_width;
+ // Create the ScrollbarControlPartMask based on the damageRect
+ ScrollbarControlPartMask scrollMask = NoPart;
+
+ IntRect backButtonStartPaintRect;
+ IntRect backButtonEndPaintRect;
+ IntRect forwardButtonStartPaintRect;
+ IntRect forwardButtonEndPaintRect;
+ if (hasButtons(scrollbar)) {
+ backButtonStartPaintRect = backButtonRect(scrollbar, BackButtonStartPart, true);
+ if (damageRect.intersects(backButtonStartPaintRect))
+ scrollMask |= BackButtonStartPart;
+ backButtonEndPaintRect = backButtonRect(scrollbar, BackButtonEndPart, true);
+ if (damageRect.intersects(backButtonEndPaintRect))
+ scrollMask |= BackButtonEndPart;
+ forwardButtonStartPaintRect = forwardButtonRect(scrollbar, ForwardButtonStartPart, true);
+ if (damageRect.intersects(forwardButtonStartPaintRect))
+ scrollMask |= ForwardButtonStartPart;
+ forwardButtonEndPaintRect = forwardButtonRect(scrollbar, ForwardButtonEndPart, true);
+ if (damageRect.intersects(forwardButtonEndPaintRect))
+ scrollMask |= ForwardButtonEndPart;
+ }
+
+ IntRect trackPaintRect = trackRect(scrollbar, true);
+ if (damageRect.intersects(trackPaintRect))
+ scrollMask |= TrackBGPart;
+
+ if (m_troughUnderSteppers && (scrollMask & BackButtonStartPart
+ || scrollMask & BackButtonEndPart
+ || scrollMask & ForwardButtonStartPart
+ || scrollMask & ForwardButtonEndPart))
+ scrollMask |= TrackBGPart;
+
+ bool thumbPresent = hasThumb(scrollbar);
+ IntRect currentThumbRect;
+ if (thumbPresent) {
+ IntRect track = trackRect(scrollbar, false);
+ currentThumbRect = thumbRect(scrollbar, track);
+ if (damageRect.intersects(currentThumbRect))
+ scrollMask |= ThumbPart;
}
- return size;
+
+ // Paint the scrollbar background (only used by custom CSS scrollbars).
+ paintScrollbarBackground(graphicsContext, scrollbar);
+
+ if (scrollMask & TrackBGPart)
+ paintTrackBackground(graphicsContext, scrollbar, trackPaintRect);
+
+ // Paint the back and forward buttons.
+ if (scrollMask & BackButtonStartPart)
+ paintButton(graphicsContext, scrollbar, backButtonStartPaintRect, BackButtonStartPart);
+ if (scrollMask & BackButtonEndPart)
+ paintButton(graphicsContext, scrollbar, backButtonEndPaintRect, BackButtonEndPart);
+ if (scrollMask & ForwardButtonStartPart)
+ paintButton(graphicsContext, scrollbar, forwardButtonStartPaintRect, ForwardButtonStartPart);
+ if (scrollMask & ForwardButtonEndPart)
+ paintButton(graphicsContext, scrollbar, forwardButtonEndPaintRect, ForwardButtonEndPart);
+
+ // Paint the thumb.
+ if (scrollMask & ThumbPart)
+ paintThumb(graphicsContext, scrollbar, currentThumbRect);
+
+ return true;
+}
+
+void ScrollbarThemeGtk::paintButton(GraphicsContext* context, Scrollbar* scrollbar, const IntRect& rect, ScrollbarPart part)
+{
+ int flags = 0;
+ if (scrollbar->orientation() == VerticalScrollbar)
+ flags |= MOZ_GTK_STEPPER_VERTICAL;
+
+ if (part == ForwardButtonEndPart) {
+ flags |= MOZ_GTK_STEPPER_DOWN;
+ flags |= MOZ_GTK_STEPPER_BOTTOM;
+ }
+
+ GtkWidgetState state;
+ state.focused = TRUE;
+ state.isDefault = TRUE;
+ state.canDefault = TRUE;
+
+ if ((BackButtonStartPart == part && scrollbar->currentPos())
+ || (ForwardButtonEndPart == part && scrollbar->currentPos() != scrollbar->maximum())) {
+ state.disabled = FALSE;
+ state.active = part == scrollbar->pressedPart();
+ state.inHover = part == scrollbar->hoveredPart();
+ } else {
+ state.disabled = TRUE;
+ state.active = FALSE;
+ state.inHover = FALSE;
+ }
+
+ static_cast<RenderThemeGtk*>(RenderTheme::defaultTheme().get())->paintMozillaGtkWidget(MOZ_GTK_SCROLLBAR_BUTTON, context, rect, &state, flags);
+}
+
+void ScrollbarThemeGtk::paintScrollCorner(ScrollView* view, GraphicsContext* context, const IntRect& cornerRect)
+{
+ // ScrollbarThemeComposite::paintScrollCorner incorrectly assumes that the
+ // ScrollView is a FrameView (see FramelessScrollView), so we cannot let
+ // that code run. For FrameView's this is correct since we don't do custom
+ // scrollbar corner rendering, which ScrollbarThemeComposite supports.
+ ScrollbarTheme::paintScrollCorner(view, context, cornerRect);
+}
+
+bool ScrollbarThemeGtk::shouldCenterOnThumb(Scrollbar*, const PlatformMouseEvent& event)
+{
+ return (event.shiftKey() && event.button() == LeftButton) || (event.button() == MiddleButton);
+}
+
+int ScrollbarThemeGtk::scrollbarThickness(ScrollbarControlSize)
+{
+ return m_thumbFatness + (m_troughBorderWidth * 2);
+}
+
+IntSize ScrollbarThemeGtk::buttonSize(Scrollbar* scrollbar)
+{
+ if (scrollbar->orientation() == VerticalScrollbar)
+ return IntSize(m_thumbFatness, m_stepperSize);
+
+ // HorizontalScrollbar
+ return IntSize(m_stepperSize, m_thumbFatness);
+}
+
+int ScrollbarThemeGtk::minimumThumbLength(Scrollbar* scrollbar)
+{
+ return m_minThumbLength;
}
}
diff --git a/WebCore/platform/gtk/ScrollbarThemeGtk.h b/WebCore/platform/gtk/ScrollbarThemeGtk.h
index 618da35..eff2fee 100644
--- a/WebCore/platform/gtk/ScrollbarThemeGtk.h
+++ b/WebCore/platform/gtk/ScrollbarThemeGtk.h
@@ -26,20 +26,48 @@
#ifndef ScrollbarThemeGtk_h
#define ScrollbarThemeGtk_h
-#include "ScrollbarTheme.h"
-
-typedef struct _GtkWidget GtkWidget;
-typedef struct _GtkStyle GtkStyle;
-typedef struct _GtkContainer GtkContainer;
-typedef struct _GtkBorder GtkBorder;
+#include "ScrollbarThemeComposite.h"
namespace WebCore {
-class ScrollbarThemeGtk : public ScrollbarTheme {
+class Scrollbar;
+
+class ScrollbarThemeGtk : public ScrollbarThemeComposite {
public:
+ ScrollbarThemeGtk();
virtual ~ScrollbarThemeGtk();
- virtual int scrollbarThickness(ScrollbarControlSize = RegularScrollbar);
+ virtual bool hasButtons(Scrollbar*) { return true; }
+ virtual bool hasThumb(Scrollbar*);
+ virtual IntRect backButtonRect(Scrollbar*, ScrollbarPart, bool);
+ virtual IntRect forwardButtonRect(Scrollbar*, ScrollbarPart, bool);
+ virtual IntRect trackRect(Scrollbar*, bool);
+ IntRect thumbRect(Scrollbar*, const IntRect& unconstrainedTrackRect);
+ bool paint(Scrollbar*, GraphicsContext*, const IntRect& damageRect);
+ void paintScrollbarBackground(GraphicsContext*, Scrollbar*);
+ void paintTrackBackground(GraphicsContext*, Scrollbar*, const IntRect&);
+ void paintThumb(GraphicsContext*, Scrollbar*, const IntRect&);
+ virtual void paintButton(GraphicsContext*, Scrollbar*, const IntRect&, ScrollbarPart);
+ virtual void paintScrollCorner(ScrollView*, GraphicsContext*, const IntRect&);
+ virtual bool shouldCenterOnThumb(Scrollbar*, const PlatformMouseEvent&);
+ virtual int scrollbarThickness(ScrollbarControlSize);
+ virtual IntSize buttonSize(Scrollbar*);
+ virtual int minimumThumbLength(Scrollbar*);
+
+ // TODO: These are the default GTK+ values. At some point we should pull these from the theme itself.
+ virtual double initialAutoscrollTimerDelay() { return 0.20; }
+ virtual double autoscrollTimerDelay() { return 0.02; }
+ void updateThemeProperties();
+ void registerScrollbar(Scrollbar*);
+ void unregisterScrollbar(Scrollbar*);
+
+protected:
+ int m_thumbFatness;
+ int m_troughBorderWidth;
+ int m_stepperSize;
+ int m_stepperSpacing;
+ int m_minThumbLength;
+ bool m_troughUnderSteppers;
};
}
diff --git a/WebCore/platform/gtk/gtk2drawing.c b/WebCore/platform/gtk/gtk2drawing.c
index 349bde0..b33fb1f 100644
--- a/WebCore/platform/gtk/gtk2drawing.c
+++ b/WebCore/platform/gtk/gtk2drawing.c
@@ -46,10 +46,7 @@
#include <gdk/gdkprivate.h>
#include "gtkdrawing.h"
-
-#include "Assertions.h"
#include "GtkVersioning.h"
-
#include <math.h>
#include <string.h>