Commit 13f02f88 authored by pkasting@chromium.org's avatar pkasting@chromium.org

2009-04-16 Peter Kasting <pkasting@google.com>

        Reviewed by David Hyatt.

        https://bugs.webkit.org/show_bug.cgi?id=25250
        Allow platforms to snap the scroll thumb back to the drag origin
        during a drag.  Implement functions for Safari/Win and Chromium/Win
        to do this snapping at distances approximating the native ones.

        * platform/Scrollbar.cpp:
        (WebCore::Scrollbar::Scrollbar):
        (WebCore::Scrollbar::setValue):
        (WebCore::Scrollbar::scroll):
        (WebCore::Scrollbar::moveThumb):
        (WebCore::Scrollbar::setCurrentPos):
        (WebCore::Scrollbar::mouseMoved):
        (WebCore::Scrollbar::mouseDown):
        * platform/Scrollbar.h:
        * platform/ScrollbarTheme.h:
        (WebCore::ScrollbarTheme::shouldSnapBackToDragOrigin):
        * platform/chromium/ScrollbarThemeChromium.h:
        * platform/chromium/ScrollbarThemeChromiumLinux.cpp:
        (WebCore::ScrollbarThemeChromium::shouldSnapBackToDragOrigin):
        * platform/chromium/ScrollbarThemeChromiumWin.cpp:
        (WebCore::ScrollbarThemeChromium::shouldSnapBackToDragOrigin):
        * platform/win/ScrollbarThemeWin.cpp:
        (WebCore::ScrollbarThemeWin::shouldCenterOnThumb):
        (WebCore::ScrollbarThemeWin::shouldSnapBackToDragOrigin):
        * platform/win/ScrollbarThemeWin.h:



git-svn-id: svn://svn.chromium.org/blink/trunk@42721 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent a791ab1c
2009-04-16 Peter Kasting <pkasting@google.com>
Reviewed by David Hyatt.
https://bugs.webkit.org/show_bug.cgi?id=25250
Allow platforms to snap the scroll thumb back to the drag origin
during a drag. Implement functions for Safari/Win and Chromium/Win
to do this snapping at distances approximating the native ones.
* platform/Scrollbar.cpp:
(WebCore::Scrollbar::Scrollbar):
(WebCore::Scrollbar::setValue):
(WebCore::Scrollbar::scroll):
(WebCore::Scrollbar::moveThumb):
(WebCore::Scrollbar::setCurrentPos):
(WebCore::Scrollbar::mouseMoved):
(WebCore::Scrollbar::mouseDown):
* platform/Scrollbar.h:
* platform/ScrollbarTheme.h:
(WebCore::ScrollbarTheme::shouldSnapBackToDragOrigin):
* platform/chromium/ScrollbarThemeChromium.h:
* platform/chromium/ScrollbarThemeChromiumLinux.cpp:
(WebCore::ScrollbarThemeChromium::shouldSnapBackToDragOrigin):
* platform/chromium/ScrollbarThemeChromiumWin.cpp:
(WebCore::ScrollbarThemeChromium::shouldSnapBackToDragOrigin):
* platform/win/ScrollbarThemeWin.cpp:
(WebCore::ScrollbarThemeWin::shouldCenterOnThumb):
(WebCore::ScrollbarThemeWin::shouldSnapBackToDragOrigin):
* platform/win/ScrollbarThemeWin.h:
2009-04-21 Adam Roben <aroben@apple.com>
Windows build fix
......@@ -57,6 +57,7 @@ Scrollbar::Scrollbar(ScrollbarClient* client, ScrollbarOrientation orientation,
, m_visibleSize(0)
, m_totalSize(0)
, m_currentPos(0)
, m_dragOrigin(0)
, m_lineStep(0)
, m_pageStep(0)
, m_pixelStep(1)
......@@ -92,13 +93,7 @@ bool Scrollbar::setValue(int v)
v = max(min(v, m_totalSize - m_visibleSize), 0);
if (value() == v)
return false; // Our value stayed the same.
m_currentPos = v;
updateThumbPosition();
if (client())
client()->valueChanged(this);
setCurrentPos(v);
return true;
}
......@@ -139,20 +134,7 @@ bool Scrollbar::scroll(ScrollDirection direction, ScrollGranularity granularity,
float newPos = m_currentPos + step * multiplier;
float maxPos = m_totalSize - m_visibleSize;
newPos = max(min(newPos, maxPos), 0.0f);
if (newPos == m_currentPos)
return false;
int oldValue = value();
m_currentPos = newPos;
updateThumbPosition();
if (value() != oldValue && client())
client()->valueChanged(this);
// return true even if the integer value did not change so that scroll event gets eaten
return true;
return setCurrentPos(max(min(newPos, maxPos), 0.0f));
}
void Scrollbar::updateThumbPosition()
......@@ -269,15 +251,30 @@ void Scrollbar::moveThumb(int pos)
int thumbLen = theme()->thumbLength(this);
int trackLen = theme()->trackLength(this);
int maxPos = trackLen - thumbLen;
int delta = pos - pressedPos();
int delta = pos - m_pressedPos;
if (delta > 0)
delta = min(maxPos - thumbPos, delta);
else if (delta < 0)
delta = max(-thumbPos, delta);
if (delta) {
setValue(static_cast<int>(static_cast<float>(thumbPos + delta) * maximum() / (trackLen - thumbLen)));
setPressedPos(pressedPos() + theme()->thumbPosition(this) - thumbPos);
}
if (delta)
setCurrentPos(static_cast<float>(thumbPos + delta) * maximum() / (trackLen - thumbLen));
}
bool Scrollbar::setCurrentPos(float pos)
{
if (pos == m_currentPos)
return false;
int oldValue = value();
int oldThumbPos = theme()->thumbPosition(this);
m_currentPos = pos;
updateThumbPosition();
if (m_pressedPart == ThumbPart)
setPressedPos(m_pressedPos + theme()->thumbPosition(this) - oldThumbPos);
if (value() != oldValue && client())
client()->valueChanged(this);
return true;
}
void Scrollbar::setHoveredPart(ScrollbarPart part)
......@@ -308,9 +305,13 @@ void Scrollbar::setPressedPart(ScrollbarPart part)
bool Scrollbar::mouseMoved(const PlatformMouseEvent& evt)
{
if (m_pressedPart == ThumbPart) {
moveThumb(m_orientation == HorizontalScrollbar ?
convertFromContainingWindow(evt.pos()).x() :
convertFromContainingWindow(evt.pos()).y());
if (theme()->shouldSnapBackToDragOrigin(this, evt))
setCurrentPos(m_dragOrigin);
else {
moveThumb(m_orientation == HorizontalScrollbar ?
convertFromContainingWindow(evt.pos()).x() :
convertFromContainingWindow(evt.pos()).y());
}
return true;
}
......@@ -366,9 +367,10 @@ bool Scrollbar::mouseDown(const PlatformMouseEvent& evt)
setPressedPart(theme()->hitTest(this, evt));
int pressedPos = (orientation() == HorizontalScrollbar ? convertFromContainingWindow(evt.pos()).x() : convertFromContainingWindow(evt.pos()).y());
if ((pressedPart() == BackTrackPart || pressedPart() == ForwardTrackPart) && theme()->shouldCenterOnThumb(this, evt)) {
if ((m_pressedPart == BackTrackPart || m_pressedPart == ForwardTrackPart) && theme()->shouldCenterOnThumb(this, evt)) {
setHoveredPart(ThumbPart);
setPressedPart(ThumbPart);
m_dragOrigin = m_currentPos;
int thumbLen = theme()->thumbLength(this);
int desiredPos = pressedPos;
// Set the pressed position to the middle of the thumb so that when we do the move, the delta
......@@ -376,7 +378,8 @@ bool Scrollbar::mouseDown(const PlatformMouseEvent& evt)
m_pressedPos = theme()->trackPosition(this) + theme()->thumbPosition(this) + thumbLen / 2;
moveThumb(desiredPos);
return true;
}
} else if (m_pressedPart == ThumbPart)
m_dragOrigin = m_currentPos;
m_pressedPos = pressedPos;
......
......@@ -137,6 +137,7 @@ protected:
ScrollGranularity pressedPartScrollGranularity();
void moveThumb(int pos);
bool setCurrentPos(float pos);
ScrollbarClient* m_client;
ScrollbarOrientation m_orientation;
......@@ -146,6 +147,7 @@ protected:
int m_visibleSize;
int m_totalSize;
float m_currentPos;
float m_dragOrigin;
int m_lineStep;
int m_pageStep;
float m_pixelStep;
......
......@@ -76,6 +76,7 @@ public:
virtual void paintScrollCorner(ScrollView*, GraphicsContext* context, const IntRect& cornerRect) { context->fillRect(cornerRect, Color::white); }
virtual bool shouldCenterOnThumb(Scrollbar*, const PlatformMouseEvent&) { return false; }
virtual bool shouldSnapBackToDragOrigin(Scrollbar*, const PlatformMouseEvent&) { return false; }
virtual int thumbPosition(Scrollbar*) { return 0; } // The position of the thumb relative to the track.
virtual int thumbLength(Scrollbar*) { return 0; } // The length of the thumb along the axis of the scrollbar.
virtual int trackPosition(Scrollbar*) { return 0; } // The position of the track relative to the scrollbar.
......
......@@ -63,6 +63,7 @@ namespace WebCore {
virtual void paintScrollCorner(ScrollView*, GraphicsContext*, const IntRect&);
virtual bool shouldCenterOnThumb(Scrollbar*, const PlatformMouseEvent&);
virtual bool shouldSnapBackToDragOrigin(Scrollbar*, const PlatformMouseEvent&);
virtual void paintTrackBackground(GraphicsContext*, Scrollbar*, const IntRect&);
virtual void paintTrackPiece(GraphicsContext*, Scrollbar*, const IntRect&, ScrollbarPart);
......
......@@ -72,6 +72,11 @@ static void drawBox(SkCanvas* canvas, const IntRect& rect, const SkPaint& paint)
drawVertLine(canvas, rect.x(), rect.y(), bottom, paint);
}
bool ScrollbarThemeChromium::shouldSnapBackToDragOrigin(Scrollbar*, const PlatformMouseEvent&)
{
return false;
}
void ScrollbarThemeChromium::paintTrackPiece(GraphicsContext* gc, Scrollbar* scrollbar,
const IntRect& rect, ScrollbarPart partType)
{
......
......@@ -44,6 +44,13 @@ namespace WebCore {
// Metrics obtained using [NSScroller scrollerWidthForControlSize:]
static const int kMacScrollbarSize[3] = { 15, 11, 15 };
// Constants used to figure the drag rect outside which we should snap the
// scrollbar thumb back to its origin. These calculations are based on
// observing the behavior of the MSVC8 main window scrollbar + some
// guessing/extrapolation.
static const int kOffEndMultiplier = 3;
static const int kOffSideMultiplier = 8;
int ScrollbarThemeChromium::scrollbarThickness(ScrollbarControlSize controlSize)
{
static int thickness;
......@@ -60,6 +67,24 @@ bool ScrollbarThemeChromium::invalidateOnMouseEnterExit()
return isVistaOrNewer();
}
bool ScrollbarThemeChromium::shouldSnapBackToDragOrigin(Scrollbar* scrollbar, const PlatformMouseEvent& evt)
{
// Find the rect within which we shouldn't snap, by expanding the track rect
// in both dimensions.
IntRect rect = trackRect(scrollbar);
const bool horz = scrollbar->orientation() == HorizontalScrollbar;
const int thickness = scrollbarThickness(scrollbar->controlSize());
rect.inflateX((horz ? kOffEndMultiplier : kOffSideMultiplier) * thickness);
rect.inflateY((horz ? kOffSideMultiplier : kOffEndMultiplier) * thickness);
// Convert the event to local coordinates.
IntPoint mousePosition = scrollbar->convertFromContainingWindow(evt.pos());
mousePosition.move(scrollbar->x(), scrollbar->y());
// We should snap iff the event is outside our calculated rect.
return !rect.contains(mousePosition);
}
void ScrollbarThemeChromium::paintTrackPiece(GraphicsContext* gc, Scrollbar* scrollbar, const IntRect& rect, ScrollbarPart partType)
{
bool horz = scrollbar->orientation() == HorizontalScrollbar;
......
......@@ -72,6 +72,13 @@ SOFT_LINK(uxtheme, DrawThemeBackground, HRESULT, WINAPI, (HANDLE hTheme, HDC hdc
SOFT_LINK(uxtheme, IsThemeActive, BOOL, WINAPI, (), ())
SOFT_LINK(uxtheme, IsThemeBackgroundPartiallyTransparent, BOOL, WINAPI, (HANDLE hTheme, int iPartId, int iStateId), (hTheme, iPartId, iStateId))
// Constants used to figure the drag rect outside which we should snap the
// scrollbar thumb back to its origin. These calculations are based on
// observing the behavior of the MSVC8 main window scrollbar + some
// guessing/extrapolation.
static const int kOffEndMultiplier = 3;
static const int kOffSideMultiplier = 8;
static void checkAndInitScrollbarTheme()
{
if (uxthemeLibrary() && !scrollbarTheme && IsThemeActive())
......@@ -180,6 +187,29 @@ IntRect ScrollbarThemeWin::trackRect(Scrollbar* scrollbar, bool)
return IntRect(scrollbar->x(), scrollbar->y() + thickness, thickness, scrollbar->height() - 2 * thickness);
}
bool ScrollbarThemeWin::shouldCenterOnThumb(Scrollbar*, const PlatformMouseEvent& evt)
{
return evt.shiftKey() && evt.button() == LeftButton;
}
bool ScrollbarThemeWin::shouldSnapBackToDragOrigin(Scrollbar* scrollbar, const PlatformMouseEvent& evt)
{
// Find the rect within which we shouldn't snap, by expanding the track rect
// in both dimensions.
IntRect rect = trackRect(scrollbar);
const bool horz = scrollbar->orientation() == HorizontalScrollbar;
const int thickness = scrollbarThickness(scrollbar->controlSize());
rect.inflateX((horz ? kOffEndMultiplier : kOffSideMultiplier) * thickness);
rect.inflateY((horz ? kOffSideMultiplier : kOffEndMultiplier) * thickness);
// Convert the event to local coordinates.
IntPoint mousePosition = scrollbar->convertFromContainingWindow(evt.pos());
mousePosition.move(scrollbar->x(), scrollbar->y());
// We should snap iff the event is outside our calculated rect.
return !rect.contains(mousePosition);
}
void ScrollbarThemeWin::paintTrackBackground(GraphicsContext* context, Scrollbar* scrollbar, const IntRect& rect)
{
// Just assume a forward track part. We only paint the track as a single piece when there is no thumb.
......@@ -340,10 +370,5 @@ void ScrollbarThemeWin::paintThumb(GraphicsContext* context, Scrollbar* scrollba
context->releaseWindowsContext(hdc, rect, alphaBlend);
}
bool ScrollbarThemeWin::shouldCenterOnThumb(Scrollbar*, const PlatformMouseEvent& evt)
{
return evt.shiftKey() && evt.button() == LeftButton;
}
}
......@@ -50,6 +50,7 @@ protected:
virtual IntRect trackRect(Scrollbar*, bool painting = false);
virtual bool shouldCenterOnThumb(Scrollbar*, const PlatformMouseEvent&);
virtual bool shouldSnapBackToDragOrigin(Scrollbar*, const PlatformMouseEvent&);
virtual void paintTrackBackground(GraphicsContext*, Scrollbar*, const IntRect&);
virtual void paintTrackPiece(GraphicsContext*, Scrollbar*, const IntRect&, ScrollbarPart);
......
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