WebKit/chromium/src/WebScrollbarImpl.cpp
changeset 0 4f2f89ce4247
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WebKit/chromium/src/WebScrollbarImpl.cpp	Fri Sep 17 09:02:29 2010 +0300
@@ -0,0 +1,297 @@
+/*
+ * 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<int>(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);
+}
+
+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<int>(m_scrollbar->visibleSize() * Scrollbar::minFractionToStepWhenPaging(), m_scrollbar->visibleSize() - Scrollbar::maxOverlapBetweenPages()), 1);
+                if (negative)
+                    delta *= -1;
+            }
+            m_scrollbar->setValue(m_scrollbar->value() - 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;
+}
+
+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