diff options
Diffstat (limited to 'WebKit/chromium/src/WebScrollbarImpl.cpp')
-rw-r--r-- | WebKit/chromium/src/WebScrollbarImpl.cpp | 307 |
1 files changed, 307 insertions, 0 deletions
diff --git a/WebKit/chromium/src/WebScrollbarImpl.cpp b/WebKit/chromium/src/WebScrollbarImpl.cpp new file mode 100644 index 0000000..8b9e287 --- /dev/null +++ b/WebKit/chromium/src/WebScrollbarImpl.cpp @@ -0,0 +1,307 @@ +/* + * Copyright (C) 2010 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 "WebScrollbarImpl.h" + +#include "GraphicsContext.h" +#include "KeyboardCodes.h" +#include "PlatformContextSkia.h" +#include "Scrollbar.h" +#include "ScrollbarTheme.h" +#include "ScrollTypes.h" +#include "WebCanvas.h" +#include "WebInputEvent.h" +#include "WebInputEventConversion.h" +#include "WebRect.h" +#include "WebScrollbarClient.h" +#include "WebVector.h" +#include "WebViewImpl.h" + +using namespace std; +using namespace WebCore; + +namespace WebKit { + +WebScrollbar* WebScrollbar::create(WebScrollbarClient* client, Orientation orientation) +{ + return new WebScrollbarImpl(client, orientation); +} + +int WebScrollbar::defaultThickness() +{ + return ScrollbarTheme::nativeTheme()->scrollbarThickness(); +} + +WebScrollbarImpl::WebScrollbarImpl(WebScrollbarClient* client, Orientation orientation) + : m_client(client) +{ + m_scrollbar = Scrollbar::createNativeScrollbar( + static_cast<ScrollbarClient*>(this), + static_cast<ScrollbarOrientation>(orientation), + RegularScrollbar); +} + +WebScrollbarImpl::~WebScrollbarImpl() +{ +} + +void WebScrollbarImpl::setLocation(const WebRect& rect) +{ + WebCore::IntRect oldRect = m_scrollbar->frameRect(); + m_scrollbar->setFrameRect(rect); + if (WebRect(oldRect) != rect) + m_scrollbar->invalidate(); + + int length = m_scrollbar->orientation() == HorizontalScrollbar ? m_scrollbar->width() : m_scrollbar->height(); + int pageStep = max(max(static_cast<int>(static_cast<float>(length) * Scrollbar::minFractionToStepWhenPaging()), length - Scrollbar::maxOverlapBetweenPages()), 1); + m_scrollbar->setSteps(Scrollbar::pixelsPerLineStep(), pageStep); + m_scrollbar->setEnabled(m_scrollbar->totalSize() > length); + m_scrollbar->setProportion(length, m_scrollbar->totalSize()); +} + +int WebScrollbarImpl::value() const +{ + return m_scrollbar->value(); +} + +void WebScrollbarImpl::setValue(int position) +{ + m_scrollbar->setValue(position, Scrollbar::NotFromScrollAnimator); +} + +void WebScrollbarImpl::setDocumentSize(int size) +{ + int length = m_scrollbar->orientation() == HorizontalScrollbar ? m_scrollbar->width() : m_scrollbar->height(); + m_scrollbar->setEnabled(size > length); + m_scrollbar->setProportion(length, size); +} + +void WebScrollbarImpl::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier) +{ + WebCore::ScrollDirection dir; + bool horizontal = m_scrollbar->orientation() == HorizontalScrollbar; + if (direction == ScrollForward) + dir = horizontal ? ScrollRight : ScrollDown; + else + dir = horizontal ? ScrollLeft : ScrollUp; + m_scrollbar->scroll(dir, static_cast<WebCore::ScrollGranularity>(granularity), multiplier); +} + +void WebScrollbarImpl::paint(WebCanvas* canvas, const WebRect& rect) +{ +#if WEBKIT_USING_CG + GraphicsContext gc(canvas); +#elif WEBKIT_USING_SKIA + PlatformContextSkia context(canvas); + + // PlatformGraphicsContext is actually a pointer to PlatformContextSkia + GraphicsContext gc(reinterpret_cast<PlatformGraphicsContext*>(&context)); +#else + notImplemented(); +#endif + + m_scrollbar->paint(&gc, rect); +} + +bool WebScrollbarImpl::handleInputEvent(const WebInputEvent& event) +{ + switch (event.type) { + case WebInputEvent::MouseDown: + return onMouseDown(event); + case WebInputEvent::MouseUp: + return onMouseUp(event); + case WebInputEvent::MouseMove: + return onMouseMove(event); + case WebInputEvent::MouseLeave: + return onMouseLeave(event); + case WebInputEvent::MouseWheel: + return onMouseWheel(event); + case WebInputEvent::KeyDown: + return onKeyDown(event); + case WebInputEvent::Undefined: + case WebInputEvent::MouseEnter: + case WebInputEvent::RawKeyDown: + case WebInputEvent::KeyUp: + case WebInputEvent::Char: + case WebInputEvent::TouchStart: + case WebInputEvent::TouchMove: + case WebInputEvent::TouchEnd: + case WebInputEvent::TouchCancel: + default: + break; + } + return false; +} + +bool WebScrollbarImpl::onMouseDown(const WebInputEvent& event) +{ + WebMouseEvent mousedown = *static_cast<const WebMouseEvent*>(&event); + if (!m_scrollbar->frameRect().contains(mousedown.x, mousedown.y)) + return false; + + mousedown.x -= m_scrollbar->x(); + mousedown.y -= m_scrollbar->y(); + m_scrollbar->mouseDown(PlatformMouseEventBuilder(m_scrollbar.get(), mousedown)); + return true; + } + +bool WebScrollbarImpl::onMouseUp(const WebInputEvent& event) +{ + if (m_scrollbar->pressedPart() == NoPart) + return false; + + return m_scrollbar->mouseUp(); +} + +bool WebScrollbarImpl::onMouseMove(const WebInputEvent& event) +{ + WebMouseEvent mousemove = *static_cast<const WebMouseEvent*>(&event); + if (m_scrollbar->frameRect().contains(mousemove.x, mousemove.y) + || m_scrollbar->pressedPart() != NoPart) { + mousemove.x -= m_scrollbar->x(); + mousemove.y -= m_scrollbar->y(); + return m_scrollbar->mouseMoved(PlatformMouseEventBuilder(m_scrollbar.get(), mousemove)); + } + + if (m_scrollbar->hoveredPart() != NoPart) + m_scrollbar->mouseExited(); + return false; +} + +bool WebScrollbarImpl::onMouseLeave(const WebInputEvent& event) +{ + if (m_scrollbar->hoveredPart() == NoPart) + return false; + + return m_scrollbar->mouseExited(); +} + +bool WebScrollbarImpl::onMouseWheel(const WebInputEvent& event) +{ + // Same logic as in Scrollview.cpp. If we can move at all, we'll accept the event. + WebMouseWheelEvent mousewheel = *static_cast<const WebMouseWheelEvent*>(&event); + int maxScrollDelta = m_scrollbar->maximum() - m_scrollbar->value(); + float delta = m_scrollbar->orientation() == HorizontalScrollbar ? mousewheel.deltaX : mousewheel.deltaY; + if ((delta < 0 && maxScrollDelta > 0) || (delta > 0 && m_scrollbar->value() > 0)) { + if (mousewheel.scrollByPage) { + ASSERT(m_scrollbar->orientation() == VerticalScrollbar); + bool negative = delta < 0; + delta = max(max(static_cast<float>(m_scrollbar->visibleSize()) * Scrollbar::minFractionToStepWhenPaging(), static_cast<float>(m_scrollbar->visibleSize() - Scrollbar::maxOverlapBetweenPages())), 1.0f); + if (negative) + delta *= -1; + } + m_scrollbar->scroll((m_scrollbar->orientation() == HorizontalScrollbar) ? WebCore::ScrollLeft : WebCore::ScrollUp, WebCore::ScrollByPixel, delta); + return true; + } + + return false; + } + +bool WebScrollbarImpl::onKeyDown(const WebInputEvent& event) +{ + WebKeyboardEvent keyboard = *static_cast<const WebKeyboardEvent*>(&event); + int keyCode; + // We have to duplicate this logic from WebViewImpl because there it uses + // Char and RawKeyDown events, which don't exist at this point. + if (keyboard.windowsKeyCode == VKEY_SPACE) + keyCode = ((keyboard.modifiers & WebInputEvent::ShiftKey) ? VKEY_PRIOR : VKEY_NEXT); + else { + if (keyboard.modifiers == WebInputEvent::ControlKey) { + // Match FF behavior in the sense that Ctrl+home/end are the only Ctrl + // key combinations which affect scrolling. Safari is buggy in the + // sense that it scrolls the page for all Ctrl+scrolling key + // combinations. For e.g. Ctrl+pgup/pgdn/up/down, etc. + switch (keyboard.windowsKeyCode) { + case VKEY_HOME: + case VKEY_END: + break; + default: + return false; + } + } + + if (keyboard.isSystemKey || (keyboard.modifiers & WebInputEvent::ShiftKey)) + return false; + + keyCode = keyboard.windowsKeyCode; + } + WebCore::ScrollDirection scrollDirection; + WebCore::ScrollGranularity scrollGranularity; + if (WebViewImpl::mapKeyCodeForScroll(keyCode, &scrollDirection, &scrollGranularity)) { + // Will return false if scroll direction wasn't compatible with this scrollbar. + return m_scrollbar->scroll(scrollDirection, scrollGranularity); + } + return false; +} + +int WebScrollbarImpl::scrollSize(WebCore::ScrollbarOrientation orientation) const +{ + return (orientation == m_scrollbar->orientation()) ? (m_scrollbar->totalSize() - m_scrollbar->visibleSize()) : 0; +} + +void WebScrollbarImpl::setScrollOffsetFromAnimation(const WebCore::IntPoint& offset) +{ + m_scrollbar->setValue((m_scrollbar->orientation() == HorizontalScrollbar) ? offset.x() : offset.y(), Scrollbar::FromScrollAnimator); +} + +void WebScrollbarImpl::valueChanged(WebCore::Scrollbar*) +{ + m_client->valueChanged(this); +} + +void WebScrollbarImpl::invalidateScrollbarRect(WebCore::Scrollbar*, const WebCore::IntRect& rect) +{ + WebRect webrect(rect); + webrect.x += m_scrollbar->x(); + webrect.y += m_scrollbar->y(); + m_client->invalidateScrollbarRect(this, webrect); +} + +bool WebScrollbarImpl::isActive() const +{ + return true; +} + +bool WebScrollbarImpl::scrollbarCornerPresent() const +{ + return false; +} + +void WebScrollbarImpl::getTickmarks(Vector<WebCore::IntRect>& tickmarks) const +{ + WebVector<WebRect> ticks; + m_client->getTickmarks(const_cast<WebScrollbarImpl*>(this), &ticks); + tickmarks.resize(ticks.size()); + for (size_t i = 0; i < ticks.size(); ++i) + tickmarks[i] = ticks[i]; +} + +} // namespace WebKit |