summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/chromium
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2009-12-15 10:12:09 +0000
committerSteve Block <steveblock@google.com>2009-12-17 17:41:10 +0000
commit643ca7872b450ea4efacab6188849e5aac2ba161 (patch)
tree6982576c228bcd1a7efe98afed544d840751094c /WebCore/platform/chromium
parentd026980fde6eb3b01c1fe49441174e89cd1be298 (diff)
downloadexternal_webkit-643ca7872b450ea4efacab6188849e5aac2ba161.zip
external_webkit-643ca7872b450ea4efacab6188849e5aac2ba161.tar.gz
external_webkit-643ca7872b450ea4efacab6188849e5aac2ba161.tar.bz2
Merge webkit.org at r51976 : Initial merge by git.
Change-Id: Ib0e7e2f0fb4bee5a186610272edf3186f0986b43
Diffstat (limited to 'WebCore/platform/chromium')
-rw-r--r--WebCore/platform/chromium/ChromiumBridge.h21
-rw-r--r--WebCore/platform/chromium/ClipboardChromium.cpp2
-rw-r--r--WebCore/platform/chromium/ContextMenuChromium.cpp14
-rw-r--r--WebCore/platform/chromium/ContextMenuItemChromium.cpp31
-rw-r--r--WebCore/platform/chromium/GeolocationServiceChromium.cpp55
-rw-r--r--WebCore/platform/chromium/MIMETypeRegistryChromium.cpp6
-rw-r--r--WebCore/platform/chromium/PasteboardChromium.cpp7
-rw-r--r--WebCore/platform/chromium/PopupMenuChromium.cpp18
-rw-r--r--WebCore/platform/chromium/ScrollbarThemeChromium.cpp2
-rw-r--r--WebCore/platform/chromium/ScrollbarThemeChromiumLinux.cpp87
-rw-r--r--WebCore/platform/chromium/ScrollbarThemeChromiumMac.h74
-rw-r--r--WebCore/platform/chromium/ScrollbarThemeChromiumMac.mm463
12 files changed, 733 insertions, 47 deletions
diff --git a/WebCore/platform/chromium/ChromiumBridge.h b/WebCore/platform/chromium/ChromiumBridge.h
index 0c80636..3709f7c 100644
--- a/WebCore/platform/chromium/ChromiumBridge.h
+++ b/WebCore/platform/chromium/ChromiumBridge.h
@@ -37,6 +37,8 @@
#include "PassRefPtr.h"
#include "PasteboardPrivate.h"
+#include <wtf/Vector.h>
+
typedef struct NPObject NPObject;
typedef struct _NPP NPP_t;
typedef NPP_t* NPP;
@@ -58,6 +60,7 @@ namespace WebCore {
class String;
class Widget;
+ struct Cookie;
struct PluginInfo;
// An interface to the embedding layer, which has the ability to answer
@@ -82,6 +85,8 @@ namespace WebCore {
// Cookies ------------------------------------------------------------
static void setCookies(const KURL& url, const KURL& firstPartyForCookies, const String& value);
static String cookies(const KURL& url, const KURL& firstPartyForCookies);
+ static bool rawCookies(const KURL& url, const KURL& firstPartyForCookies, Vector<Cookie>*);
+ static void deleteCookie(const KURL& url, const String& cookieName);
// DNS ----------------------------------------------------------------
static void prefetchDNS(const String& hostname);
@@ -113,13 +118,13 @@ namespace WebCore {
// HTML5 DB -----------------------------------------------------------
#if ENABLE(DATABASE)
// Returns a handle to the DB file and ooptionally a handle to its containing directory
- static PlatformFileHandle databaseOpenFile(const String& fileName, int desiredFlags, PlatformFileHandle* dirHandle = 0);
+ static PlatformFileHandle databaseOpenFile(const String& vfsFleName, int desiredFlags, PlatformFileHandle* dirHandle = 0);
// Returns a SQLite code (SQLITE_OK = 0, on success)
- static int databaseDeleteFile(const String& fileName, bool syncDir = false);
+ static int databaseDeleteFile(const String& vfsFileName, bool syncDir = false);
// Returns the attributes of the DB file
- static long databaseGetFileAttributes(const String& fileName);
+ static long databaseGetFileAttributes(const String& vfsFileName);
// Returns the size of the DB file
- static long long databaseGetFileSize(const String& fileName);
+ static long long databaseGetFileSize(const String& vfsFileName);
#endif
// JavaScript ---------------------------------------------------------
@@ -135,6 +140,11 @@ namespace WebCore {
// LayoutTestMode -----------------------------------------------------
static bool layoutTestMode();
+ // Memory -------------------------------------------------------------
+ // Returns the current space allocated for the pagefile, in MB.
+ // That is committed size for Windows and virtual memory size for POSIX
+ static int memoryUsageMB();
+
// MimeType -----------------------------------------------------------
static bool isSupportedImageMIMEType(const String& mimeType);
static bool isSupportedJavaScriptMIMEType(const String& mimeType);
@@ -148,9 +158,6 @@ namespace WebCore {
static NPObject* pluginScriptableObject(Widget*);
static bool popupsAllowed(NPP);
- // Protocol -----------------------------------------------------------
- static String uiResourceProtocol(); // deprecated
-
// Resources ----------------------------------------------------------
static PassRefPtr<Image> loadPlatformImageResource(const char* name);
diff --git a/WebCore/platform/chromium/ClipboardChromium.cpp b/WebCore/platform/chromium/ClipboardChromium.cpp
index d330d3b..1a2caa4 100644
--- a/WebCore/platform/chromium/ClipboardChromium.cpp
+++ b/WebCore/platform/chromium/ClipboardChromium.cpp
@@ -354,7 +354,7 @@ void ClipboardChromium::writeRange(Range* selectedRange, Frame* frame)
m_dataObject->textHtml = createMarkup(selectedRange, 0,
AnnotateForInterchange);
#if PLATFORM(DARWIN)
- m_dataObject->textHtml = String("<meta charset='utf-8'>") + m_dataObject->textHtml;
+ m_dataObject->textHtml = String("<meta charset='utf-8' id='webkit-interchange-charset'>") + m_dataObject->textHtml;
#endif
m_dataObject->htmlBaseUrl = frame->document()->url();
diff --git a/WebCore/platform/chromium/ContextMenuChromium.cpp b/WebCore/platform/chromium/ContextMenuChromium.cpp
index 0614e3e..93c0ec4 100644
--- a/WebCore/platform/chromium/ContextMenuChromium.cpp
+++ b/WebCore/platform/chromium/ContextMenuChromium.cpp
@@ -38,13 +38,11 @@ namespace WebCore {
ContextMenu::ContextMenu(const HitTestResult& result)
: m_hitTestResult(result)
- , m_platformDescription(0)
{
}
ContextMenu::ContextMenu(const HitTestResult& result, const PlatformMenuDescription menu)
: m_hitTestResult(result)
- , m_platformDescription(0)
{
}
@@ -54,25 +52,31 @@ ContextMenu::~ContextMenu()
unsigned ContextMenu::itemCount() const
{
- return 0;
+ return m_items.size();
}
void ContextMenu::insertItem(unsigned position, ContextMenuItem& item)
{
+ m_items.insert(position, item);
}
void ContextMenu::appendItem(ContextMenuItem& item)
{
+ m_items.append(item);
}
ContextMenuItem* ContextMenu::itemWithAction(unsigned action)
{
+ for (size_t i = 0; i < m_items.size(); ++i) {
+ if (m_items[i].action() == static_cast<ContextMenuAction>(action))
+ return &m_items[i];
+ }
return 0;
}
ContextMenuItem* ContextMenu::itemAtIndex(unsigned index, const PlatformMenuDescription platformDescription)
{
- return 0;
+ return &m_items[index];
}
void ContextMenu::setPlatformDescription(PlatformMenuDescription menu)
@@ -81,7 +85,7 @@ void ContextMenu::setPlatformDescription(PlatformMenuDescription menu)
PlatformMenuDescription ContextMenu::platformDescription() const
{
- return m_platformDescription;
+ return 0;
}
PlatformMenuDescription ContextMenu::releasePlatformDescription()
diff --git a/WebCore/platform/chromium/ContextMenuItemChromium.cpp b/WebCore/platform/chromium/ContextMenuItemChromium.cpp
index f34ea23..6a0d657 100644
--- a/WebCore/platform/chromium/ContextMenuItemChromium.cpp
+++ b/WebCore/platform/chromium/ContextMenuItemChromium.cpp
@@ -46,6 +46,9 @@ ContextMenuItem::ContextMenuItem(ContextMenu* subMenu)
ContextMenuItem::ContextMenuItem(ContextMenuItemType type, ContextMenuAction action, const String& title, ContextMenu* subMenu)
{
+ m_platformDescription.type = type;
+ m_platformDescription.action = action;
+ m_platformDescription.title = title;
}
ContextMenuItem::~ContextMenuItem()
@@ -54,22 +57,32 @@ ContextMenuItem::~ContextMenuItem()
PlatformMenuItemDescription ContextMenuItem::releasePlatformDescription()
{
- return PlatformMenuItemDescription();
+ return m_platformDescription;
}
ContextMenuItemType ContextMenuItem::type() const
{
- return ContextMenuItemType();
+ return m_platformDescription.type;
}
ContextMenuAction ContextMenuItem::action() const
{
- return ContextMenuAction();
+ return m_platformDescription.action;
}
String ContextMenuItem::title() const
{
- return String();
+ return m_platformDescription.title;
+}
+
+bool ContextMenuItem::checked() const
+{
+ return m_platformDescription.checked;
+}
+
+bool ContextMenuItem::enabled() const
+{
+ return m_platformDescription.enabled;
}
PlatformMenuDescription ContextMenuItem::platformSubMenu() const
@@ -79,14 +92,17 @@ PlatformMenuDescription ContextMenuItem::platformSubMenu() const
void ContextMenuItem::setType(ContextMenuItemType type)
{
+ m_platformDescription.type = type;
}
void ContextMenuItem::setAction(ContextMenuAction action)
{
+ m_platformDescription.action = action;
}
void ContextMenuItem::setTitle(const String& title)
{
+ m_platformDescription.title = title;
}
void ContextMenuItem::setSubMenu(ContextMenu* subMenu)
@@ -95,15 +111,12 @@ void ContextMenuItem::setSubMenu(ContextMenu* subMenu)
void ContextMenuItem::setChecked(bool checked)
{
+ m_platformDescription.checked = checked;
}
void ContextMenuItem::setEnabled(bool enabled)
{
-}
-
-bool ContextMenuItem::enabled() const
-{
- return false;
+ m_platformDescription.enabled = enabled;
}
} // namespace WebCore
diff --git a/WebCore/platform/chromium/GeolocationServiceChromium.cpp b/WebCore/platform/chromium/GeolocationServiceChromium.cpp
new file mode 100644
index 0000000..65886b0
--- /dev/null
+++ b/WebCore/platform/chromium/GeolocationServiceChromium.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2009, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "GeolocationService.h"
+
+namespace WebCore {
+
+class GeolocationServiceChromium : public GeolocationService {
+public:
+ GeolocationServiceChromium(GeolocationServiceClient* c)
+ : GeolocationService(c)
+ {
+ }
+ // FIXME: Implement. https://bugs.webkit.org/show_bug.cgi?id=32068
+};
+
+// This guard is the counterpart of the one in WebCore/platform/GeolocationService.cpp
+#if ENABLE(GEOLOCATION)
+static GeolocationService* createGeolocationService(GeolocationServiceClient* c)
+{
+ return new GeolocationServiceChromium(c);
+}
+
+GeolocationService::FactoryFunction* GeolocationService::s_factoryFunction = &createGeolocationService;
+#endif
+
+} // namespace WebCore
diff --git a/WebCore/platform/chromium/MIMETypeRegistryChromium.cpp b/WebCore/platform/chromium/MIMETypeRegistryChromium.cpp
index 51bff80..ff0be82 100644
--- a/WebCore/platform/chromium/MIMETypeRegistryChromium.cpp
+++ b/WebCore/platform/chromium/MIMETypeRegistryChromium.cpp
@@ -34,6 +34,7 @@
#include "ChromiumBridge.h"
#include "CString.h"
#include "MediaPlayer.h"
+#include "PluginDataChromium.h"
// NOTE: Unlike other ports, we don't use the shared implementation bits in
// MIMETypeRegistry.cpp. Instead, we need to route most functions via the
@@ -41,11 +42,6 @@
namespace WebCore {
-// Checks if any of the plugins handle this extension, and if so returns the
-// plugin's mime type for this extension. Otherwise returns an empty string.
-// See PluginsChromium.cpp for the implementation of this function.
-String getPluginMimeTypeFromExtension(const String& extension);
-
String MIMETypeRegistry::getMIMETypeForExtension(const String &ext)
{
return ChromiumBridge::mimeTypeForExtension(ext);
diff --git a/WebCore/platform/chromium/PasteboardChromium.cpp b/WebCore/platform/chromium/PasteboardChromium.cpp
index 4929eb8..ce06e55 100644
--- a/WebCore/platform/chromium/PasteboardChromium.cpp
+++ b/WebCore/platform/chromium/PasteboardChromium.cpp
@@ -83,7 +83,7 @@ void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete,
{
String html = createMarkup(selectedRange, 0, AnnotateForInterchange);
#if PLATFORM(DARWIN)
- html = String("<meta charset='utf-8'>") + html;
+ html = String("<meta charset='utf-8' id='webkit-interchange-charset'>") + html;
#endif
ExceptionCode ec = 0;
KURL url = selectedRange->startContainer(ec)->document()->url();
@@ -170,6 +170,11 @@ PassRefPtr<DocumentFragment> Pasteboard::documentFragment(Frame* frame, PassRefP
String markup;
KURL srcURL;
ChromiumBridge::clipboardReadHTML(buffer, &markup, &srcURL);
+#if PLATFORM(DARWIN)
+ DEFINE_STATIC_LOCAL(const String, forceUtf8String, ("<meta charset='utf-8' id='webkit-interchange-charset'>"));
+ if (markup.startsWith(forceUtf8String))
+ markup = markup.substring(forceUtf8String.length());
+#endif
RefPtr<DocumentFragment> fragment =
createFragmentFromMarkup(frame->document(), markup, srcURL);
diff --git a/WebCore/platform/chromium/PopupMenuChromium.cpp b/WebCore/platform/chromium/PopupMenuChromium.cpp
index d6f895d..5abd364 100644
--- a/WebCore/platform/chromium/PopupMenuChromium.cpp
+++ b/WebCore/platform/chromium/PopupMenuChromium.cpp
@@ -370,6 +370,12 @@ void PopupContainer::showExternal(const IntRect& rect, FrameView* v, int index)
ChromeClientChromium* client = static_cast<ChromeClientChromium*>(
v->frame()->page()->chrome()->client());
client->popupOpened(this, popupRect, true, true);
+
+ // The popup sends its "closed" notification through its parent. Set the
+ // parent, even though external popups have no real on-screen widget but a
+ // native menu (see |PopupListBox::hidePopup()|);
+ if (!m_listBox->parent())
+ addChild(m_listBox.get());
}
void PopupContainer::hidePopup()
@@ -446,7 +452,7 @@ void PopupContainer::paintBorder(GraphicsContext* gc, const IntRect& rect)
Color borderColor(127, 157, 185);
gc->setStrokeStyle(NoStroke);
- gc->setFillColor(borderColor);
+ gc->setFillColor(borderColor, DeviceColorSpace);
int tx = x();
int ty = y();
@@ -772,7 +778,7 @@ void PopupListBox::paint(GraphicsContext* gc, const IntRect& rect)
// Special case for an empty popup.
if (numItems() == 0)
- gc->fillRect(r, Color::white);
+ gc->fillRect(r, Color::white, DeviceColorSpace);
gc->restore();
@@ -805,23 +811,23 @@ void PopupListBox::paintRow(GraphicsContext* gc, const IntRect& rect, int rowInd
// If we have a transparent background, make sure it has a color to blend
// against.
if (backColor.hasAlpha())
- gc->fillRect(rowRect, Color::white);
+ gc->fillRect(rowRect, Color::white, DeviceColorSpace);
- gc->fillRect(rowRect, backColor);
+ gc->fillRect(rowRect, backColor, DeviceColorSpace);
if (m_popupClient->itemIsSeparator(rowIndex)) {
IntRect separatorRect(
rowRect.x() + separatorPadding,
rowRect.y() + (rowRect.height() - separatorHeight) / 2,
rowRect.width() - 2 * separatorPadding, separatorHeight);
- gc->fillRect(separatorRect, textColor);
+ gc->fillRect(separatorRect, textColor, DeviceColorSpace);
return;
}
if (!style.isVisible())
return;
- gc->setFillColor(textColor);
+ gc->setFillColor(textColor, DeviceColorSpace);
Font itemFont = getRowFont(rowIndex);
// FIXME: http://crbug.com/19872 We should get the padding of individual option
diff --git a/WebCore/platform/chromium/ScrollbarThemeChromium.cpp b/WebCore/platform/chromium/ScrollbarThemeChromium.cpp
index 725de10..a6720a1 100644
--- a/WebCore/platform/chromium/ScrollbarThemeChromium.cpp
+++ b/WebCore/platform/chromium/ScrollbarThemeChromium.cpp
@@ -113,7 +113,7 @@ void ScrollbarThemeChromium::paintTickmarks(GraphicsContext* context, Scrollbar*
const int yPos = rect.topLeft().y() + (rect.height() * percent);
IntPoint tick(scrollbar->x(), yPos);
- context->drawImage(dash.get(), tick);
+ context->drawImage(dash.get(), DeviceColorSpace, tick);
}
context->restore();
diff --git a/WebCore/platform/chromium/ScrollbarThemeChromiumLinux.cpp b/WebCore/platform/chromium/ScrollbarThemeChromiumLinux.cpp
index 64f58c4..3a1a652 100644
--- a/WebCore/platform/chromium/ScrollbarThemeChromiumLinux.cpp
+++ b/WebCore/platform/chromium/ScrollbarThemeChromiumLinux.cpp
@@ -33,6 +33,8 @@
#include "PlatformContextSkia.h"
#include "PlatformMouseEvent.h"
+#include "RenderTheme.h"
+#include "RenderThemeChromiumLinux.h"
#include "Scrollbar.h"
#include "TransformationMatrix.h"
@@ -73,6 +75,60 @@ static void drawBox(SkCanvas* canvas, const IntRect& rect, const SkPaint& paint)
drawVertLine(canvas, rect.x(), rect.y(), bottom, paint);
}
+static SkScalar clamp(SkScalar value, SkScalar min, SkScalar max)
+{
+ return std::min(std::max(value, min), max);
+}
+
+static SkColor saturateAndBrighten(SkScalar* hsv,
+ SkScalar saturateAmount,
+ SkScalar brightenAmount)
+{
+ SkScalar color[3];
+ color[0] = hsv[0];
+ color[1] = clamp(hsv[1] + saturateAmount, 0.0, 1.0);
+ color[2] = clamp(hsv[2] + brightenAmount, 0.0, 1.0);
+ return SkHSVToColor(color);
+}
+
+static SkColor outlineColor(SkScalar* hsv1, SkScalar* hsv2)
+{
+ // GTK Theme engines have way too much control over the layout of
+ // the scrollbar. We might be able to more closely approximate its
+ // look-and-feel, if we sent whole images instead of just colors
+ // from the browser to the renderer. But even then, some themes
+ // would just break.
+ //
+ // So, instead, we don't even try to 100% replicate the look of
+ // the native scrollbar. We render our own version, but we make
+ // sure to pick colors that blend in nicely with the system GTK
+ // theme. In most cases, we can just sample a couple of pixels
+ // from the system scrollbar and use those colors to draw our
+ // scrollbar.
+ //
+ // This works fine for the track color and the overall thumb
+ // color. But it fails spectacularly for the outline color used
+ // around the thumb piece. Not all themes have a clearly defined
+ // outline. For some of them it is partially transparent, and for
+ // others the thickness is very unpredictable.
+ //
+ // So, instead of trying to approximate the system theme, we
+ // instead try to compute a reasonable looking choice based on the
+ // known color of the track and the thumb piece. This is difficult
+ // when trying to deal both with high- and low-contrast themes,
+ // and both with positive and inverted themes.
+ //
+ // The following code has been tested to look OK with all of the
+ // default GTK themes.
+ SkScalar minDiff = clamp((hsv1[1] + hsv2[1]) * 1.2, 0.2, 0.5);
+ SkScalar diff = clamp(fabs(hsv1[2] - hsv2[2]) / 2, minDiff, 0.5);
+
+ if (hsv1[2] + hsv2[2] > 1.0)
+ diff = -diff;
+
+ return saturateAndBrighten(hsv2, -0.2, diff);
+}
+
IntRect ScrollbarThemeChromium::trackRect(Scrollbar* scrollbar, bool)
{
IntSize bs = buttonSize(scrollbar);
@@ -89,10 +145,16 @@ void ScrollbarThemeChromiumLinux::paintTrackPiece(GraphicsContext* gc, Scrollbar
SkIRect skrect;
skrect.set(rect.x(), rect.y(), rect.x() + rect.width(), rect.y() + rect.height());
- paint.setARGB(0xff, 0xe3, 0xdd, 0xd8);
+ SkScalar track_hsv[3];
+ SkColorToHSV(RenderThemeChromiumLinux::trackColor(), track_hsv);
+ paint.setColor(saturateAndBrighten(track_hsv, 0, 0));
canvas->drawIRect(skrect, paint);
- paint.setARGB(0xff, 0xc5, 0xba, 0xb0);
+ SkScalar thumb_hsv[3];
+ SkColorToHSV(RenderThemeChromiumLinux::thumbInactiveColor(),
+ thumb_hsv);
+
+ paint.setColor(outlineColor(track_hsv, thumb_hsv));
drawBox(canvas, rect, paint);
}
@@ -109,11 +171,14 @@ void ScrollbarThemeChromiumLinux::paintThumb(GraphicsContext* gc, Scrollbar* scr
const bool vertical = scrollbar->orientation() == VerticalScrollbar;
SkCanvas* const canvas = gc->platformContext()->canvas();
+ SkScalar thumb[3];
+ SkColorToHSV(hovered
+ ? RenderThemeChromiumLinux::thumbActiveColor()
+ : RenderThemeChromiumLinux::thumbInactiveColor(),
+ thumb);
+
SkPaint paint;
- if (hovered)
- paint.setARGB(0xff, 0xff, 0xff, 0xff);
- else
- paint.setARGB(0xff, 0xf4, 0xf2, 0xef);
+ paint.setColor(saturateAndBrighten(thumb, 0, 0.02));
SkIRect skrect;
if (vertical)
@@ -123,10 +188,7 @@ void ScrollbarThemeChromiumLinux::paintThumb(GraphicsContext* gc, Scrollbar* scr
canvas->drawIRect(skrect, paint);
- if (hovered)
- paint.setARGB(0xff, 0xf4, 0xf2, 0xef);
- else
- paint.setARGB(0xff, 0xea, 0xe5, 0xe0);
+ paint.setColor(saturateAndBrighten(thumb, 0, -0.02));
if (vertical)
skrect.set(midx + 1, rect.y(), rect.x() + rect.width(), rect.y() + rect.height());
@@ -135,11 +197,12 @@ void ScrollbarThemeChromiumLinux::paintThumb(GraphicsContext* gc, Scrollbar* scr
canvas->drawIRect(skrect, paint);
- paint.setARGB(0xff, 0x9d, 0x96, 0x8e);
+ SkScalar track[3];
+ SkColorToHSV(RenderThemeChromiumLinux::trackColor(), track);
+ paint.setColor(outlineColor(track, thumb));
drawBox(canvas, rect, paint);
if (rect.height() > 10 && rect.width() > 10) {
- paint.setARGB(0xff, 0x9d, 0x96, 0x8e);
const int grippyHalfWidth = 2;
const int interGrippyOffset = 3;
if (vertical) {
diff --git a/WebCore/platform/chromium/ScrollbarThemeChromiumMac.h b/WebCore/platform/chromium/ScrollbarThemeChromiumMac.h
new file mode 100644
index 0000000..1ab2f18
--- /dev/null
+++ b/WebCore/platform/chromium/ScrollbarThemeChromiumMac.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2009 Google Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ScrollbarThemeChromiumMac_h
+#define ScrollbarThemeChromiumMac_h
+
+#include "ScrollbarThemeComposite.h"
+
+// This file (and its associated .mm file) is a clone of ScrollbarThemeMac.h.
+// See the .mm file for details.
+
+namespace WebCore {
+
+class ScrollbarThemeChromiumMac : public ScrollbarThemeComposite {
+public:
+ ScrollbarThemeChromiumMac();
+ virtual ~ScrollbarThemeChromiumMac();
+
+ virtual bool paint(Scrollbar*, GraphicsContext* context, const IntRect& damageRect);
+
+ virtual int scrollbarThickness(ScrollbarControlSize = RegularScrollbar);
+
+ virtual bool supportsControlTints() const { return true; }
+
+ virtual double initialAutoscrollTimerDelay();
+ virtual double autoscrollTimerDelay();
+
+ virtual ScrollbarButtonsPlacement buttonsPlacement() const;
+
+ virtual void registerScrollbar(Scrollbar*);
+ virtual void unregisterScrollbar(Scrollbar*);
+
+protected:
+ virtual bool hasButtons(Scrollbar*);
+ virtual bool hasThumb(Scrollbar*);
+
+ virtual IntRect backButtonRect(Scrollbar*, ScrollbarPart, bool painting = false);
+ virtual IntRect forwardButtonRect(Scrollbar*, ScrollbarPart, bool painting = false);
+ virtual IntRect trackRect(Scrollbar*, bool painting = false);
+
+ virtual int minimumThumbLength(Scrollbar*);
+
+ virtual bool shouldCenterOnThumb(Scrollbar*, const PlatformMouseEvent&);
+
+public:
+ void preferencesChanged();
+};
+
+}
+
+#endif // ScrollbarThemeChromiumMac_h
diff --git a/WebCore/platform/chromium/ScrollbarThemeChromiumMac.mm b/WebCore/platform/chromium/ScrollbarThemeChromiumMac.mm
new file mode 100644
index 0000000..b4ebaf6
--- /dev/null
+++ b/WebCore/platform/chromium/ScrollbarThemeChromiumMac.mm
@@ -0,0 +1,463 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2009 Google Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ScrollbarThemeChromiumMac.h"
+
+#include "ImageBuffer.h"
+#include "PlatformMouseEvent.h"
+#include "ScrollView.h"
+#include <Carbon/Carbon.h>
+#include <wtf/StdLibExtras.h>
+#include <wtf/UnusedParam.h>
+
+// FIXME: There are repainting problems due to Aqua scroll bar buttons' visual overflow.
+
+using namespace std;
+using namespace WebCore;
+
+// This file (and its associated .h file) is a clone of ScrollbarThemeMac.mm.
+// Because we want to draw tickmarks in the scrollbar, we must maintain a fork.
+// Please maintain this file by performing parallel changes to it.
+//
+// The only changes from ScrollbarThemeMac should be:
+// - The classname change from ScrollbarThemeMac to ScrollbarThemeChromiumMac.
+// - In paint() the code to paint the track, tickmarks, and thumb separately.
+//
+// For all other differences, if it was introduced in this file, then the
+// maintainer forgot to include it in the list; otherwise it is an update that
+// should have been applied to this file but was not.
+
+static HashSet<Scrollbar*>* gScrollbars;
+
+@interface ScrollbarPrefsObserver : NSObject
+{
+
+}
+
++ (void)registerAsObserver;
++ (void)appearancePrefsChanged:(NSNotification*)theNotification;
++ (void)behaviorPrefsChanged:(NSNotification*)theNotification;
+
+@end
+
+@implementation ScrollbarPrefsObserver
+
++ (void)appearancePrefsChanged:(NSNotification*)unusedNotification
+{
+ UNUSED_PARAM(unusedNotification);
+
+ static_cast<ScrollbarThemeChromiumMac*>(ScrollbarTheme::nativeTheme())->preferencesChanged();
+ if (!gScrollbars)
+ return;
+ HashSet<Scrollbar*>::iterator end = gScrollbars->end();
+ for (HashSet<Scrollbar*>::iterator it = gScrollbars->begin(); it != end; ++it) {
+ (*it)->styleChanged();
+ (*it)->invalidate();
+ }
+}
+
++ (void)behaviorPrefsChanged:(NSNotification*)unusedNotification
+{
+ UNUSED_PARAM(unusedNotification);
+
+ static_cast<ScrollbarThemeChromiumMac*>(ScrollbarTheme::nativeTheme())->preferencesChanged();
+}
+
++ (void)registerAsObserver
+{
+ [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(appearancePrefsChanged:) name:@"AppleAquaScrollBarVariantChanged" object:nil suspensionBehavior:NSNotificationSuspensionBehaviorDeliverImmediately];
+ [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(behaviorPrefsChanged:) name:@"AppleNoRedisplayAppearancePreferenceChanged" object:nil suspensionBehavior:NSNotificationSuspensionBehaviorCoalesce];
+}
+
+@end
+
+namespace WebCore {
+
+ScrollbarTheme* ScrollbarTheme::nativeTheme()
+{
+ DEFINE_STATIC_LOCAL(ScrollbarThemeChromiumMac, theme, ());
+ return &theme;
+}
+
+// FIXME: Get these numbers from CoreUI.
+static int cScrollbarThickness[] = { 15, 11 };
+static int cRealButtonLength[] = { 28, 21 };
+static int cButtonInset[] = { 14, 11 };
+static int cButtonHitInset[] = { 3, 2 };
+// cRealButtonLength - cButtonInset
+static int cButtonLength[] = { 14, 10 };
+static int cThumbMinLength[] = { 26, 20 };
+
+static int cOuterButtonLength[] = { 16, 14 }; // The outer button in a double button pair is a bit bigger.
+static int cOuterButtonOverlap = 2;
+
+static float gInitialButtonDelay = 0.5f;
+static float gAutoscrollButtonDelay = 0.05f;
+static bool gJumpOnTrackClick = false;
+static ScrollbarButtonsPlacement gButtonPlacement = ScrollbarButtonsDoubleEnd;
+
+static void updateArrowPlacement()
+{
+ NSString *buttonPlacement = [[NSUserDefaults standardUserDefaults] objectForKey:@"AppleScrollBarVariant"];
+ if ([buttonPlacement isEqualToString:@"Single"])
+ gButtonPlacement = ScrollbarButtonsSingle;
+ else if ([buttonPlacement isEqualToString:@"DoubleMin"])
+ gButtonPlacement = ScrollbarButtonsDoubleStart;
+ else if ([buttonPlacement isEqualToString:@"DoubleBoth"])
+ gButtonPlacement = ScrollbarButtonsDoubleBoth;
+ else
+ gButtonPlacement = ScrollbarButtonsDoubleEnd; // The default is ScrollbarButtonsDoubleEnd.
+}
+
+void ScrollbarThemeChromiumMac::registerScrollbar(Scrollbar* scrollbar)
+{
+ if (!gScrollbars)
+ gScrollbars = new HashSet<Scrollbar*>;
+ gScrollbars->add(scrollbar);
+}
+
+void ScrollbarThemeChromiumMac::unregisterScrollbar(Scrollbar* scrollbar)
+{
+ gScrollbars->remove(scrollbar);
+ if (gScrollbars->isEmpty()) {
+ delete gScrollbars;
+ gScrollbars = 0;
+ }
+}
+
+ScrollbarThemeChromiumMac::ScrollbarThemeChromiumMac()
+{
+ static bool initialized;
+ if (!initialized) {
+ initialized = true;
+ [ScrollbarPrefsObserver registerAsObserver];
+ preferencesChanged();
+ }
+}
+
+ScrollbarThemeChromiumMac::~ScrollbarThemeChromiumMac()
+{
+}
+
+void ScrollbarThemeChromiumMac::preferencesChanged()
+{
+ NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
+ [defaults synchronize];
+ updateArrowPlacement();
+ gInitialButtonDelay = [defaults floatForKey:@"NSScrollerButtonDelay"];
+ gAutoscrollButtonDelay = [defaults floatForKey:@"NSScrollerButtonPeriod"];
+ gJumpOnTrackClick = [defaults boolForKey:@"AppleScrollerPagingBehavior"];
+}
+
+int ScrollbarThemeChromiumMac::scrollbarThickness(ScrollbarControlSize controlSize)
+{
+ return cScrollbarThickness[controlSize];
+}
+
+double ScrollbarThemeChromiumMac::initialAutoscrollTimerDelay()
+{
+ return gInitialButtonDelay;
+}
+
+double ScrollbarThemeChromiumMac::autoscrollTimerDelay()
+{
+ return gAutoscrollButtonDelay;
+}
+
+ScrollbarButtonsPlacement ScrollbarThemeChromiumMac::buttonsPlacement() const
+{
+ return gButtonPlacement;
+}
+
+bool ScrollbarThemeChromiumMac::hasButtons(Scrollbar* scrollbar)
+{
+ return scrollbar->enabled() && (scrollbar->orientation() == HorizontalScrollbar ?
+ scrollbar->width() :
+ scrollbar->height()) >= 2 * (cRealButtonLength[scrollbar->controlSize()] - cButtonHitInset[scrollbar->controlSize()]);
+}
+
+bool ScrollbarThemeChromiumMac::hasThumb(Scrollbar* scrollbar)
+{
+ return scrollbar->enabled() && (scrollbar->orientation() == HorizontalScrollbar ?
+ scrollbar->width() :
+ scrollbar->height()) >= 2 * cButtonInset[scrollbar->controlSize()] + cThumbMinLength[scrollbar->controlSize()] + 1;
+}
+
+static IntRect buttonRepaintRect(const IntRect& buttonRect, ScrollbarOrientation orientation, ScrollbarControlSize controlSize, bool start)
+{
+ IntRect paintRect(buttonRect);
+ if (orientation == HorizontalScrollbar) {
+ paintRect.setWidth(cRealButtonLength[controlSize]);
+ if (!start)
+ paintRect.setX(buttonRect.x() - (cRealButtonLength[controlSize] - buttonRect.width()));
+ } else {
+ paintRect.setHeight(cRealButtonLength[controlSize]);
+ if (!start)
+ paintRect.setY(buttonRect.y() - (cRealButtonLength[controlSize] - buttonRect.height()));
+ }
+
+ return paintRect;
+}
+
+IntRect ScrollbarThemeChromiumMac::backButtonRect(Scrollbar* scrollbar, ScrollbarPart part, bool painting)
+{
+ IntRect result;
+
+ if (part == BackButtonStartPart && (buttonsPlacement() == ScrollbarButtonsNone || buttonsPlacement() == ScrollbarButtonsDoubleEnd))
+ return result;
+
+ if (part == BackButtonEndPart && (buttonsPlacement() == ScrollbarButtonsNone || buttonsPlacement() == ScrollbarButtonsDoubleStart || buttonsPlacement() == ScrollbarButtonsSingle))
+ return result;
+
+ int thickness = scrollbarThickness(scrollbar->controlSize());
+ bool outerButton = part == BackButtonStartPart && (buttonsPlacement() == ScrollbarButtonsDoubleStart || buttonsPlacement() == ScrollbarButtonsDoubleBoth);
+ if (outerButton) {
+ if (scrollbar->orientation() == HorizontalScrollbar)
+ result = IntRect(scrollbar->x(), scrollbar->y(), cOuterButtonLength[scrollbar->controlSize()] + painting ? cOuterButtonOverlap : 0, thickness);
+ else
+ result = IntRect(scrollbar->x(), scrollbar->y(), thickness, cOuterButtonLength[scrollbar->controlSize()] + painting ? cOuterButtonOverlap : 0);
+ return result;
+ }
+
+ // Our repaint rect is slightly larger, since we are a button that is adjacent to the track.
+ if (scrollbar->orientation() == HorizontalScrollbar) {
+ int start = part == BackButtonStartPart ? scrollbar->x() : scrollbar->x() + scrollbar->width() - cOuterButtonLength[scrollbar->controlSize()] - cButtonLength[scrollbar->controlSize()];
+ result = IntRect(start, scrollbar->y(), cButtonLength[scrollbar->controlSize()], thickness);
+ } else {
+ int start = part == BackButtonStartPart ? scrollbar->y() : scrollbar->y() + scrollbar->height() - cOuterButtonLength[scrollbar->controlSize()] - cButtonLength[scrollbar->controlSize()];
+ result = IntRect(scrollbar->x(), start, thickness, cButtonLength[scrollbar->controlSize()]);
+ }
+
+ if (painting)
+ return buttonRepaintRect(result, scrollbar->orientation(), scrollbar->controlSize(), part == BackButtonStartPart);
+ return result;
+}
+
+IntRect ScrollbarThemeChromiumMac::forwardButtonRect(Scrollbar* scrollbar, ScrollbarPart part, bool painting)
+{
+ IntRect result;
+
+ if (part == ForwardButtonEndPart && (buttonsPlacement() == ScrollbarButtonsNone || buttonsPlacement() == ScrollbarButtonsDoubleStart))
+ return result;
+
+ if (part == ForwardButtonStartPart && (buttonsPlacement() == ScrollbarButtonsNone || buttonsPlacement() == ScrollbarButtonsDoubleEnd || buttonsPlacement() == ScrollbarButtonsSingle))
+ return result;
+
+ int thickness = scrollbarThickness(scrollbar->controlSize());
+ int outerButtonLength = cOuterButtonLength[scrollbar->controlSize()];
+ int buttonLength = cButtonLength[scrollbar->controlSize()];
+
+ bool outerButton = part == ForwardButtonEndPart && (buttonsPlacement() == ScrollbarButtonsDoubleEnd || buttonsPlacement() == ScrollbarButtonsDoubleBoth);
+ if (outerButton) {
+ if (scrollbar->orientation() == HorizontalScrollbar) {
+ result = IntRect(scrollbar->x() + scrollbar->width() - outerButtonLength, scrollbar->y(), outerButtonLength, thickness);
+ if (painting)
+ result.inflateX(cOuterButtonOverlap);
+ } else {
+ result = IntRect(scrollbar->x(), scrollbar->y() + scrollbar->height() - outerButtonLength, thickness, outerButtonLength);
+ if (painting)
+ result.inflateY(cOuterButtonOverlap);
+ }
+ return result;
+ }
+
+ if (scrollbar->orientation() == HorizontalScrollbar) {
+ int start = part == ForwardButtonEndPart ? scrollbar->x() + scrollbar->width() - buttonLength : scrollbar->x() + outerButtonLength;
+ result = IntRect(start, scrollbar->y(), buttonLength, thickness);
+ } else {
+ int start = part == ForwardButtonEndPart ? scrollbar->y() + scrollbar->height() - buttonLength : scrollbar->y() + outerButtonLength;
+ result = IntRect(scrollbar->x(), start, thickness, buttonLength);
+ }
+ if (painting)
+ return buttonRepaintRect(result, scrollbar->orientation(), scrollbar->controlSize(), part == ForwardButtonStartPart);
+ return result;
+}
+
+IntRect ScrollbarThemeChromiumMac::trackRect(Scrollbar* scrollbar, bool painting)
+{
+ if (painting || !hasButtons(scrollbar))
+ return scrollbar->frameRect();
+
+ IntRect result;
+ int thickness = scrollbarThickness(scrollbar->controlSize());
+ int startWidth = 0;
+ int endWidth = 0;
+ int outerButtonLength = cOuterButtonLength[scrollbar->controlSize()];
+ int buttonLength = cButtonLength[scrollbar->controlSize()];
+ int doubleButtonLength = outerButtonLength + buttonLength;
+ switch (buttonsPlacement()) {
+ case ScrollbarButtonsSingle:
+ startWidth = buttonLength;
+ endWidth = buttonLength;
+ break;
+ case ScrollbarButtonsDoubleStart:
+ startWidth = doubleButtonLength;
+ break;
+ case ScrollbarButtonsDoubleEnd:
+ endWidth = doubleButtonLength;
+ break;
+ case ScrollbarButtonsDoubleBoth:
+ startWidth = doubleButtonLength;
+ endWidth = doubleButtonLength;
+ break;
+ default:
+ break;
+ }
+
+ int totalWidth = startWidth + endWidth;
+ if (scrollbar->orientation() == HorizontalScrollbar)
+ return IntRect(scrollbar->x() + startWidth, scrollbar->y(), scrollbar->width() - totalWidth, thickness);
+ return IntRect(scrollbar->x(), scrollbar->y() + startWidth, thickness, scrollbar->height() - totalWidth);
+}
+
+int ScrollbarThemeChromiumMac::minimumThumbLength(Scrollbar* scrollbar)
+{
+ return cThumbMinLength[scrollbar->controlSize()];
+}
+
+bool ScrollbarThemeChromiumMac::shouldCenterOnThumb(Scrollbar*, const PlatformMouseEvent& evt)
+{
+ if (evt.button() != LeftButton)
+ return false;
+ if (gJumpOnTrackClick)
+ return !evt.altKey();
+ return evt.altKey();
+}
+
+static int scrollbarPartToHIPressedState(ScrollbarPart part)
+{
+ switch (part) {
+ case BackButtonStartPart:
+ return kThemeTopOutsideArrowPressed;
+ case BackButtonEndPart:
+ return kThemeTopOutsideArrowPressed; // This does not make much sense. For some reason the outside constant is required.
+ case ForwardButtonStartPart:
+ return kThemeTopInsideArrowPressed;
+ case ForwardButtonEndPart:
+ return kThemeBottomOutsideArrowPressed;
+ case ThumbPart:
+ return kThemeThumbPressed;
+ default:
+ return 0;
+ }
+}
+
+bool ScrollbarThemeChromiumMac::paint(Scrollbar* scrollbar, GraphicsContext* context, const IntRect& damageRect)
+{
+ HIThemeTrackDrawInfo trackInfo;
+ trackInfo.version = 0;
+ trackInfo.kind = scrollbar->controlSize() == RegularScrollbar ? kThemeMediumScrollBar : kThemeSmallScrollBar;
+ trackInfo.bounds = scrollbar->frameRect();
+ trackInfo.min = 0;
+ trackInfo.max = scrollbar->maximum();
+ trackInfo.value = scrollbar->currentPos();
+ trackInfo.trackInfo.scrollbar.viewsize = scrollbar->pageStep();
+ trackInfo.attributes = 0;
+ if (scrollbar->orientation() == HorizontalScrollbar)
+ trackInfo.attributes |= kThemeTrackHorizontal;
+
+ if (!scrollbar->enabled())
+ trackInfo.enableState = kThemeTrackDisabled;
+ else
+ trackInfo.enableState = scrollbar->client()->isActive() ? kThemeTrackActive : kThemeTrackInactive;
+
+ if (!hasButtons(scrollbar))
+ trackInfo.enableState = kThemeTrackNothingToScroll;
+ trackInfo.trackInfo.scrollbar.pressState = scrollbarPartToHIPressedState(scrollbar->pressedPart());
+
+ CGAffineTransform currentCTM = CGContextGetCTM(context->platformContext());
+
+ // The Aqua scrollbar is buggy when rotated and scaled. We will just draw into a bitmap if we detect a scale or rotation.
+ bool canDrawDirectly = currentCTM.a == 1.0f && currentCTM.b == 0.0f && currentCTM.c == 0.0f && (currentCTM.d == 1.0f || currentCTM.d == -1.0f);
+ GraphicsContext* drawingContext = context;
+ OwnPtr<ImageBuffer> imageBuffer;
+ if (!canDrawDirectly) {
+ trackInfo.bounds = IntRect(IntPoint(), scrollbar->frameRect().size());
+
+ IntRect bufferRect(scrollbar->frameRect());
+ bufferRect.intersect(damageRect);
+ bufferRect.move(-scrollbar->frameRect().x(), -scrollbar->frameRect().y());
+
+ imageBuffer = ImageBuffer::create(bufferRect.size());
+ if (!imageBuffer)
+ return true;
+
+ drawingContext = imageBuffer->context();
+ }
+
+ // Draw thumbless.
+ HIThemeDrawTrack(&trackInfo, 0, drawingContext->platformContext(), kHIThemeOrientationNormal);
+
+ Vector<IntRect> tickmarks;
+ scrollbar->client()->getTickmarks(tickmarks);
+ if (scrollbar->orientation() == VerticalScrollbar && tickmarks.size()) {
+ drawingContext->save();
+ drawingContext->setShouldAntialias(false);
+ drawingContext->setStrokeColor(Color(0xCC, 0xAA, 0x00, 0xFF), DeviceColorSpace);
+ drawingContext->setFillColor(Color(0xFF, 0xDD, 0x00, 0xFF), DeviceColorSpace);
+
+ IntRect thumbArea = trackRect(scrollbar, false);
+ if (!canDrawDirectly) {
+ thumbArea.setX(0);
+ thumbArea.setY(0);
+ }
+ // The ends are rounded and the thumb doesn't go there.
+ thumbArea.inflateY(-thumbArea.width());
+
+ for (Vector<IntRect>::const_iterator i = tickmarks.begin(); i != tickmarks.end(); ++i) {
+ // Calculate how far down (in %) the tick-mark should appear.
+ const float percent = static_cast<float>(i->y()) / scrollbar->totalSize();
+ if (percent < 0.0 || percent > 1.0)
+ continue;
+
+ // Calculate how far down (in pixels) the tick-mark should appear.
+ const int yPos = static_cast<int>((thumbArea.topLeft().y() + (thumbArea.height() * percent))) & ~1;
+
+ // Paint.
+ const int indent = 2;
+ FloatRect tickRect(thumbArea.topLeft().x() + indent, yPos, thumbArea.width() - 2 * indent - 1, 2);
+ drawingContext->fillRect(tickRect);
+ drawingContext->strokeRect(tickRect, 1);
+ }
+
+ drawingContext->restore();
+ }
+
+ if (hasThumb(scrollbar)) {
+ trackInfo.attributes |= (kThemeTrackShowThumb | kThemeTrackHideTrack);
+ HIThemeDrawTrack(&trackInfo, 0, drawingContext->platformContext(), kHIThemeOrientationNormal);
+ }
+
+ if (!canDrawDirectly) {
+ context->drawImage(imageBuffer->image(), DeviceColorSpace, scrollbar->frameRect().location());
+ }
+
+ return true;
+}
+
+}
+