Chromium Mac: Rubber banding gutter drawing

https://bugs.webkit.org/show_bug.cgi?id=66226

Make ScrollView::paintOverhangAreas() use the ScrollbarTheme::nativeTheme() to
draw the overhang areas.
Move default implementation to ScrollbarThemeComposite::paintOverhangAreas().
Add a different implementation for Chromium Mac.

Patch by Alexei Svitkine <asvitkine@chromium.org> on 2011-08-16
Reviewed by Dimitri Glazkov.

No new tests since this is just refactoring code and adding a Chromium-specific path for overhang drawing.

* platform/ScrollView.cpp:
(WebCore::ScrollView::wheelEvent):
* platform/ScrollbarTheme.h:
(WebCore::ScrollbarTheme::paintOverhangAreas):
* platform/ScrollbarThemeComposite.cpp:
(WebCore::ScrollbarThemeComposite::paintOverhangAreas):
* platform/ScrollbarThemeComposite.h:
* platform/chromium/ScrollbarThemeChromiumMac.h:
* platform/chromium/ScrollbarThemeChromiumMac.mm:
(WebCore::ScrollbarThemeChromiumMac::ScrollbarThemeChromiumMac):
(WebCore::scrollbarStateToThemeState):
(WebCore::ScrollbarThemeChromiumMac::paintTickmarks):
(WebCore::ScrollbarThemeChromiumMac::paintOverhangAreas):

git-svn-id: svn://svn.chromium.org/blink/trunk@93136 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 0630225d
2011-08-16 Alexei Svitkine <asvitkine@chromium.org>
Chromium Mac: Rubber banding gutter drawing
https://bugs.webkit.org/show_bug.cgi?id=66226
Make ScrollView::paintOverhangAreas() use the ScrollbarTheme::nativeTheme() to
draw the overhang areas.
Move default implementation to ScrollbarThemeComposite::paintOverhangAreas().
Add a different implementation for Chromium Mac.
Reviewed by Dimitri Glazkov.
No new tests since this is just refactoring code and adding a Chromium-specific path for overhang drawing.
* platform/ScrollView.cpp:
(WebCore::ScrollView::wheelEvent):
* platform/ScrollbarTheme.h:
(WebCore::ScrollbarTheme::paintOverhangAreas):
* platform/ScrollbarThemeComposite.cpp:
(WebCore::ScrollbarThemeComposite::paintOverhangAreas):
* platform/ScrollbarThemeComposite.h:
* platform/chromium/ScrollbarThemeChromiumMac.h:
* platform/chromium/ScrollbarThemeChromiumMac.mm:
(WebCore::ScrollbarThemeChromiumMac::ScrollbarThemeChromiumMac):
(WebCore::scrollbarStateToThemeState):
(WebCore::ScrollbarThemeChromiumMac::paintTickmarks):
(WebCore::ScrollbarThemeChromiumMac::paintOverhangAreas):
2011-08-12 Wyatt Carss <wcarss@chromium.org> 2011-08-12 Wyatt Carss <wcarss@chromium.org>
Programmatically set selection should not have direction on Mac Programmatically set selection should not have direction on Mac
...@@ -1086,17 +1086,9 @@ void ScrollView::calculateOverhangAreasForPainting(IntRect& horizontalOverhangRe ...@@ -1086,17 +1086,9 @@ void ScrollView::calculateOverhangAreasForPainting(IntRect& horizontalOverhangRe
} }
} }
void ScrollView::paintOverhangAreas(GraphicsContext* context, const IntRect& horizontalOverhangRect, const IntRect& verticalOverhangRect, const IntRect&) void ScrollView::paintOverhangAreas(GraphicsContext* context, const IntRect& horizontalOverhangRect, const IntRect& verticalOverhangRect, const IntRect& dirtyRect)
{ {
// FIXME: This should be checking the dirty rect. ScrollbarTheme::nativeTheme()->paintOverhangAreas(this, context, horizontalOverhangRect, verticalOverhangRect, dirtyRect);
context->setFillColor(Color::white, ColorSpaceDeviceRGB);
if (!horizontalOverhangRect.isEmpty())
context->fillRect(horizontalOverhangRect);
context->setFillColor(Color::white, ColorSpaceDeviceRGB);
if (!verticalOverhangRect.isEmpty())
context->fillRect(verticalOverhangRect);
} }
bool ScrollView::isPointInScrollbarCorner(const IntPoint& windowPoint) bool ScrollView::isPointInScrollbarCorner(const IntPoint& windowPoint)
......
...@@ -82,6 +82,8 @@ public: ...@@ -82,6 +82,8 @@ public:
virtual void paintScrollCorner(ScrollView*, GraphicsContext* context, const IntRect& cornerRect) { defaultPaintScrollCorner(context, cornerRect); } virtual void paintScrollCorner(ScrollView*, GraphicsContext* context, const IntRect& cornerRect) { defaultPaintScrollCorner(context, cornerRect); }
static void defaultPaintScrollCorner(GraphicsContext* context, const IntRect& cornerRect) { context->fillRect(cornerRect, Color::white, ColorSpaceDeviceRGB); } static void defaultPaintScrollCorner(GraphicsContext* context, const IntRect& cornerRect) { context->fillRect(cornerRect, Color::white, ColorSpaceDeviceRGB); }
virtual void paintOverhangAreas(ScrollView*, GraphicsContext*, const IntRect&, const IntRect&, const IntRect&) { }
virtual bool shouldCenterOnThumb(Scrollbar*, const PlatformMouseEvent&) { return false; } virtual bool shouldCenterOnThumb(Scrollbar*, const PlatformMouseEvent&) { return false; }
virtual bool shouldSnapBackToDragOrigin(Scrollbar*, const PlatformMouseEvent&) { return false; } virtual bool shouldSnapBackToDragOrigin(Scrollbar*, const PlatformMouseEvent&) { return false; }
virtual bool shouldDragDocumentInsteadOfThumb(Scrollbar*, const PlatformMouseEvent&) { return false; } virtual bool shouldDragDocumentInsteadOfThumb(Scrollbar*, const PlatformMouseEvent&) { return false; }
......
...@@ -315,4 +315,15 @@ void ScrollbarThemeComposite::paintScrollCorner(ScrollView* view, GraphicsContex ...@@ -315,4 +315,15 @@ void ScrollbarThemeComposite::paintScrollCorner(ScrollView* view, GraphicsContex
context->fillRect(cornerRect, Color::white, ColorSpaceDeviceRGB); context->fillRect(cornerRect, Color::white, ColorSpaceDeviceRGB);
} }
void ScrollbarThemeComposite::paintOverhangAreas(ScrollView*, GraphicsContext* context, const IntRect& horizontalOverhangRect, const IntRect& verticalOverhangRect, const IntRect& dirtyRect)
{
context->setFillColor(Color::white, ColorSpaceDeviceRGB);
if (!horizontalOverhangRect.isEmpty())
context->fillRect(intersection(horizontalOverhangRect, dirtyRect));
context->setFillColor(Color::white, ColorSpaceDeviceRGB);
if (!verticalOverhangRect.isEmpty())
context->fillRect(intersection(verticalOverhangRect, dirtyRect));
}
} }
...@@ -44,6 +44,7 @@ public: ...@@ -44,6 +44,7 @@ public:
virtual int trackLength(Scrollbar*); virtual int trackLength(Scrollbar*);
virtual void paintScrollCorner(ScrollView*, GraphicsContext*, const IntRect& cornerRect); virtual void paintScrollCorner(ScrollView*, GraphicsContext*, const IntRect& cornerRect);
virtual void paintOverhangAreas(ScrollView*, GraphicsContext*, const IntRect& horizontalOverhangArea, const IntRect& verticalOverhangArea, const IntRect& dirtyRect);
protected: protected:
virtual bool hasButtons(Scrollbar*) = 0; virtual bool hasButtons(Scrollbar*) = 0;
......
...@@ -40,6 +40,8 @@ public: ...@@ -40,6 +40,8 @@ public:
ScrollbarThemeChromiumMac(); ScrollbarThemeChromiumMac();
virtual ~ScrollbarThemeChromiumMac(); virtual ~ScrollbarThemeChromiumMac();
void preferencesChanged();
virtual bool paint(Scrollbar*, GraphicsContext* context, const IntRect& damageRect); virtual bool paint(Scrollbar*, GraphicsContext* context, const IntRect& damageRect);
virtual int scrollbarThickness(ScrollbarControlSize = RegularScrollbar); virtual int scrollbarThickness(ScrollbarControlSize = RegularScrollbar);
...@@ -58,6 +60,8 @@ public: ...@@ -58,6 +60,8 @@ public:
void setNewPainterForScrollbar(Scrollbar*, WKScrollbarPainterRef); void setNewPainterForScrollbar(Scrollbar*, WKScrollbarPainterRef);
WKScrollbarPainterRef painterForScrollbar(Scrollbar*); WKScrollbarPainterRef painterForScrollbar(Scrollbar*);
virtual void paintOverhangAreas(ScrollView*, GraphicsContext*, const IntRect& horizontalOverhangArea, const IntRect& verticalOverhangArea, const IntRect& dirtyRect);
protected: protected:
virtual bool hasButtons(Scrollbar*); virtual bool hasButtons(Scrollbar*);
virtual bool hasThumb(Scrollbar*); virtual bool hasThumb(Scrollbar*);
...@@ -73,8 +77,8 @@ protected: ...@@ -73,8 +77,8 @@ protected:
virtual void paintTickmarks(GraphicsContext*, Scrollbar*, const IntRect&); virtual void paintTickmarks(GraphicsContext*, Scrollbar*, const IntRect&);
public: private:
void preferencesChanged(); RefPtr<Pattern> m_overhangPattern;
}; };
} }
......
...@@ -27,7 +27,9 @@ ...@@ -27,7 +27,9 @@
#include "config.h" #include "config.h"
#include "ScrollbarThemeChromiumMac.h" #include "ScrollbarThemeChromiumMac.h"
#include "BitmapImage.h"
#include "FrameView.h" #include "FrameView.h"
#include "Gradient.h"
#include "ImageBuffer.h" #include "ImageBuffer.h"
#include "LocalCurrentGraphicsContext.h" #include "LocalCurrentGraphicsContext.h"
#include "PlatformBridge.h" #include "PlatformBridge.h"
...@@ -44,6 +46,13 @@ ...@@ -44,6 +46,13 @@
#include "skia/ext/skia_utils_mac.h" #include "skia/ext/skia_utils_mac.h"
#endif #endif
// Undocumented Lion method to get the pattern for the over-scroll area.
@interface NSColor (LionSekretAPI)
+ (NSImage*)_linenPatternImage;
@end
// FIXME: There are repainting problems due to Aqua scroll bar buttons' visual overflow. // FIXME: There are repainting problems due to Aqua scroll bar buttons' visual overflow.
using namespace std; using namespace std;
...@@ -185,6 +194,21 @@ ScrollbarThemeChromiumMac::ScrollbarThemeChromiumMac() ...@@ -185,6 +194,21 @@ ScrollbarThemeChromiumMac::ScrollbarThemeChromiumMac()
static bool initialized; static bool initialized;
if (!initialized) { if (!initialized) {
initialized = true; initialized = true;
// Load the linen pattern image used for overhang drawing if available.
if ([NSColor respondsToSelector:@selector(_linenPatternImage)]) {
NSImage* image = [NSColor _linenPatternImage];
if (image) {
NSData* tiffData = [image TIFFRepresentation];
if (tiffData) {
CGImageSourceRef imageSource = CGImageSourceCreateWithData((CFDataRef)tiffData, NULL);
CGImageRef cgImage = CGImageSourceCreateImageAtIndex(imageSource, 0, NULL);
RefPtr<Image> patternImage = BitmapImage::create(cgImage);
m_overhangPattern = Pattern::create(patternImage, true, true);
}
}
}
[ScrollbarPrefsObserver registerAsObserver]; [ScrollbarPrefsObserver registerAsObserver];
preferencesChanged(); preferencesChanged();
} }
...@@ -436,7 +460,8 @@ static inline wkScrollerKnobStyle toScrollbarPainterKnobStyle(ScrollbarOverlaySt ...@@ -436,7 +460,8 @@ static inline wkScrollerKnobStyle toScrollbarPainterKnobStyle(ScrollbarOverlaySt
} }
} }
static PlatformBridge::ThemePaintState scrollbarStateToThemeState(Scrollbar* scrollbar) { static PlatformBridge::ThemePaintState scrollbarStateToThemeState(Scrollbar* scrollbar)
{
if (!scrollbar->enabled()) if (!scrollbar->enabled())
return PlatformBridge::StateDisabled; return PlatformBridge::StateDisabled;
if (!scrollbar->scrollableArea()->isActive()) if (!scrollbar->scrollableArea()->isActive())
...@@ -598,7 +623,8 @@ bool ScrollbarThemeChromiumMac::paint(Scrollbar* scrollbar, GraphicsContext* con ...@@ -598,7 +623,8 @@ bool ScrollbarThemeChromiumMac::paint(Scrollbar* scrollbar, GraphicsContext* con
return true; return true;
} }
void ScrollbarThemeChromiumMac::paintTickmarks(GraphicsContext* context, Scrollbar* scrollbar, const IntRect& rect) { void ScrollbarThemeChromiumMac::paintTickmarks(GraphicsContext* context, Scrollbar* scrollbar, const IntRect& rect)
{
if (scrollbar->orientation() != VerticalScrollbar) if (scrollbar->orientation() != VerticalScrollbar)
return; return;
...@@ -643,4 +669,99 @@ void ScrollbarThemeChromiumMac::paintTickmarks(GraphicsContext* context, Scrollb ...@@ -643,4 +669,99 @@ void ScrollbarThemeChromiumMac::paintTickmarks(GraphicsContext* context, Scrollb
context->restore(); context->restore();
} }
void ScrollbarThemeChromiumMac::paintOverhangAreas(ScrollView* view, GraphicsContext* context, const IntRect& horizontalOverhangRect, const IntRect& verticalOverhangRect, const IntRect& dirtyRect)
{
const int kShadowSize = 5;
const struct {
float stop;
Color color;
} kShadowColors[] = {
{ 0.0, Color(0, 0, 0, 141) },
{ 0.2, Color(0, 0, 0, 89) },
{ 0.6, Color(0, 0, 0, 30) },
{ 1.0, Color(0, 0, 0, 0) }
};
const unsigned kNumShadowColors = sizeof(kShadowColors)/sizeof(kShadowColors[0]);
bool hasHorizontalOverhang = !horizontalOverhangRect.isEmpty();
bool hasVerticalOverhang = !verticalOverhangRect.isEmpty();
context->save();
if (m_overhangPattern.get())
context->setFillPattern(m_overhangPattern);
else
context->setFillColor(Color::darkGray, ColorSpaceDeviceRGB);
if (hasHorizontalOverhang)
context->fillRect(intersection(horizontalOverhangRect, dirtyRect));
if (hasVerticalOverhang)
context->fillRect(intersection(verticalOverhangRect, dirtyRect));
IntSize scrollOffset = view->scrollOffset();
FloatPoint shadowCornerOrigin;
FloatPoint shadowCornerOffset;
// Draw the shadow for the horizontal overhang.
if (hasHorizontalOverhang) {
RefPtr<Gradient> gradient;
IntRect shadowRect = horizontalOverhangRect;
if (scrollOffset.height() < 0) {
shadowRect.setY(shadowRect.maxY() - kShadowSize);
shadowRect.setHeight(kShadowSize);
gradient = Gradient::create(FloatPoint(0, shadowRect.maxY()), FloatPoint(0, shadowRect.y()));
shadowCornerOrigin.setY(shadowRect.maxY());
shadowCornerOffset.setY(-kShadowSize);
} else {
shadowRect.setHeight(kShadowSize);
gradient = Gradient::create(FloatPoint(0, shadowRect.y()), FloatPoint(0, shadowRect.maxY()));
shadowCornerOrigin.setY(shadowRect.y());
}
if (hasHorizontalOverhang) {
shadowRect.setWidth(shadowRect.width() - verticalOverhangRect.width());
if (scrollOffset.width() < 0) {
shadowRect.setX(shadowRect.x() + verticalOverhangRect.width());
shadowCornerOrigin.setX(shadowRect.x());
shadowCornerOffset.setX(-kShadowSize);
} else {
shadowCornerOrigin.setX(shadowRect.maxX());
}
}
for (unsigned i = 0; i < kNumShadowColors; i++)
gradient->addColorStop(kShadowColors[i].stop, kShadowColors[i].color);
context->setFillGradient(gradient);
context->fillRect(intersection(shadowRect, dirtyRect));
}
// Draw the shadow for the vertical overhang.
if (hasVerticalOverhang) {
RefPtr<Gradient> gradient;
IntRect shadowRect = verticalOverhangRect;
if (scrollOffset.width() < 0) {
shadowRect.setX(shadowRect.maxX() - kShadowSize);
shadowRect.setWidth(kShadowSize);
gradient = Gradient::create(FloatPoint(shadowRect.maxX(), 0), FloatPoint(shadowRect.x(), 0));
} else {
shadowRect.setWidth(kShadowSize);
gradient = Gradient::create(FloatPoint(shadowRect.x(), 0), FloatPoint(shadowRect.maxX(), 0));
}
for (unsigned i = 0; i < kNumShadowColors; i++)
gradient->addColorStop(kShadowColors[i].stop, kShadowColors[i].color);
context->setFillGradient(gradient);
context->fillRect(intersection(shadowRect, dirtyRect));
}
// If both rectangles present, draw a radial gradient for the corner.
if (hasHorizontalOverhang && hasVerticalOverhang) {
RefPtr<Gradient> gradient = Gradient::create(shadowCornerOrigin, 0, shadowCornerOrigin, kShadowSize);
for (unsigned i = 0; i < kNumShadowColors; i++)
gradient->addColorStop(kShadowColors[i].stop, kShadowColors[i].color);
context->setFillGradient(gradient);
context->fillRect(FloatRect(shadowCornerOrigin.x() + shadowCornerOffset.x(), shadowCornerOrigin.y() + shadowCornerOffset.y(), kShadowSize, kShadowSize));
}
context->restore();
}
} }
...@@ -39,6 +39,8 @@ public: ...@@ -39,6 +39,8 @@ public:
ScrollbarThemeMac(); ScrollbarThemeMac();
virtual ~ScrollbarThemeMac(); virtual ~ScrollbarThemeMac();
void preferencesChanged();
virtual void updateEnabledState(Scrollbar*); virtual void updateEnabledState(Scrollbar*);
virtual bool paint(Scrollbar*, GraphicsContext* context, const IntRect& damageRect); virtual bool paint(Scrollbar*, GraphicsContext* context, const IntRect& damageRect);
...@@ -76,9 +78,6 @@ protected: ...@@ -76,9 +78,6 @@ protected:
virtual bool shouldCenterOnThumb(Scrollbar*, const PlatformMouseEvent&); virtual bool shouldCenterOnThumb(Scrollbar*, const PlatformMouseEvent&);
virtual bool shouldDragDocumentInsteadOfThumb(Scrollbar*, const PlatformMouseEvent&); virtual bool shouldDragDocumentInsteadOfThumb(Scrollbar*, const PlatformMouseEvent&);
public:
void preferencesChanged();
}; };
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment