WebKit/chromium/src/WebScrollbarImpl.cpp
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     1 /*
       
     2  * Copyright (C) 2010 Google Inc. All rights reserved.
       
     3  *
       
     4  * Redistribution and use in source and binary forms, with or without
       
     5  * modification, are permitted provided that the following conditions are
       
     6  * met:
       
     7  *
       
     8  *     * Redistributions of source code must retain the above copyright
       
     9  * notice, this list of conditions and the following disclaimer.
       
    10  *     * Redistributions in binary form must reproduce the above
       
    11  * copyright notice, this list of conditions and the following disclaimer
       
    12  * in the documentation and/or other materials provided with the
       
    13  * distribution.
       
    14  *     * Neither the name of Google Inc. nor the names of its
       
    15  * contributors may be used to endorse or promote products derived from
       
    16  * this software without specific prior written permission.
       
    17  *
       
    18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
       
    19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
       
    20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
       
    21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
       
    22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
       
    23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
       
    24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
       
    25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
       
    26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
       
    27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
       
    28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
       
    29  */
       
    30 
       
    31 #include "config.h"
       
    32 #include "WebScrollbarImpl.h"
       
    33 
       
    34 #include "GraphicsContext.h"
       
    35 #include "KeyboardCodes.h"
       
    36 #include "PlatformContextSkia.h"
       
    37 #include "Scrollbar.h"
       
    38 #include "ScrollbarTheme.h"
       
    39 #include "ScrollTypes.h"
       
    40 #include "WebCanvas.h"
       
    41 #include "WebInputEvent.h"
       
    42 #include "WebInputEventConversion.h"
       
    43 #include "WebRect.h"
       
    44 #include "WebScrollbarClient.h"
       
    45 #include "WebVector.h"
       
    46 #include "WebViewImpl.h"
       
    47 
       
    48 using namespace std;
       
    49 using namespace WebCore;
       
    50 
       
    51 namespace WebKit {
       
    52 
       
    53 WebScrollbar* WebScrollbar::create(WebScrollbarClient* client, Orientation orientation)
       
    54 {
       
    55     return new WebScrollbarImpl(client, orientation);
       
    56 }
       
    57 
       
    58 int WebScrollbar::defaultThickness()
       
    59 {
       
    60     return ScrollbarTheme::nativeTheme()->scrollbarThickness();
       
    61 }
       
    62 
       
    63 WebScrollbarImpl::WebScrollbarImpl(WebScrollbarClient* client, Orientation orientation)
       
    64     : m_client(client)
       
    65 {
       
    66     m_scrollbar = Scrollbar::createNativeScrollbar(
       
    67         static_cast<ScrollbarClient*>(this),
       
    68         static_cast<ScrollbarOrientation>(orientation),
       
    69         RegularScrollbar);
       
    70 }
       
    71 
       
    72 WebScrollbarImpl::~WebScrollbarImpl()
       
    73 {
       
    74 }
       
    75 
       
    76 void WebScrollbarImpl::setLocation(const WebRect& rect)
       
    77 {
       
    78     WebCore::IntRect oldRect = m_scrollbar->frameRect();
       
    79     m_scrollbar->setFrameRect(rect);
       
    80     if (WebRect(oldRect) != rect)
       
    81       m_scrollbar->invalidate();
       
    82 
       
    83     int length = m_scrollbar->orientation() == HorizontalScrollbar ? m_scrollbar->width() : m_scrollbar->height();
       
    84     int pageStep = max(max<int>(length * Scrollbar::minFractionToStepWhenPaging(), length - Scrollbar::maxOverlapBetweenPages()), 1);
       
    85     m_scrollbar->setSteps(Scrollbar::pixelsPerLineStep(), pageStep);
       
    86     m_scrollbar->setEnabled(m_scrollbar->totalSize() > length);
       
    87     m_scrollbar->setProportion(length, m_scrollbar->totalSize());
       
    88 }
       
    89 
       
    90 int WebScrollbarImpl::value() const
       
    91 {
       
    92     return m_scrollbar->value();
       
    93 }
       
    94 
       
    95 void WebScrollbarImpl::setValue(int position)
       
    96 {
       
    97     m_scrollbar->setValue(position);
       
    98 }
       
    99 
       
   100 void WebScrollbarImpl::setDocumentSize(int size)
       
   101 {
       
   102     int length = m_scrollbar->orientation() == HorizontalScrollbar ? m_scrollbar->width() : m_scrollbar->height();
       
   103     m_scrollbar->setEnabled(size > length);
       
   104     m_scrollbar->setProportion(length, size);
       
   105 }
       
   106 
       
   107 void WebScrollbarImpl::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier)
       
   108 {
       
   109     WebCore::ScrollDirection dir;
       
   110     bool horizontal = m_scrollbar->orientation() == HorizontalScrollbar;
       
   111     if (direction == ScrollForward)
       
   112         dir = horizontal ? ScrollRight : ScrollDown;
       
   113     else
       
   114         dir = horizontal ? ScrollLeft : ScrollUp;
       
   115     m_scrollbar->scroll(dir, static_cast<WebCore::ScrollGranularity>(granularity), multiplier);
       
   116 }
       
   117 
       
   118 void WebScrollbarImpl::paint(WebCanvas* canvas, const WebRect& rect)
       
   119 {
       
   120 #if WEBKIT_USING_CG
       
   121     GraphicsContext gc(canvas);
       
   122 #elif WEBKIT_USING_SKIA
       
   123     PlatformContextSkia context(canvas);
       
   124 
       
   125     // PlatformGraphicsContext is actually a pointer to PlatformContextSkia
       
   126     GraphicsContext gc(reinterpret_cast<PlatformGraphicsContext*>(&context));
       
   127 #else
       
   128     notImplemented();
       
   129 #endif
       
   130 
       
   131     m_scrollbar->paint(&gc, rect);
       
   132 }
       
   133 
       
   134 bool WebScrollbarImpl::handleInputEvent(const WebInputEvent& event)
       
   135 {
       
   136     switch (event.type) {
       
   137     case WebInputEvent::MouseDown:
       
   138         return onMouseDown(event);
       
   139     case WebInputEvent::MouseUp:
       
   140         return onMouseUp(event);
       
   141     case WebInputEvent::MouseMove:
       
   142         return onMouseMove(event);
       
   143     case WebInputEvent::MouseLeave:
       
   144         return onMouseLeave(event);
       
   145     case WebInputEvent::MouseWheel:
       
   146         return onMouseWheel(event);
       
   147     case WebInputEvent::KeyDown:
       
   148         return onKeyDown(event);
       
   149     case WebInputEvent::Undefined:
       
   150     case WebInputEvent::MouseEnter:
       
   151     case WebInputEvent::RawKeyDown:
       
   152     case WebInputEvent::KeyUp:
       
   153     case WebInputEvent::Char:
       
   154     case WebInputEvent::TouchStart:
       
   155     case WebInputEvent::TouchMove:
       
   156     case WebInputEvent::TouchEnd:
       
   157     case WebInputEvent::TouchCancel:
       
   158     default:
       
   159          break;
       
   160     }
       
   161     return false;
       
   162 }
       
   163 
       
   164 bool WebScrollbarImpl::onMouseDown(const WebInputEvent& event)
       
   165 {
       
   166     WebMouseEvent mousedown = *static_cast<const WebMouseEvent*>(&event);
       
   167     if (!m_scrollbar->frameRect().contains(mousedown.x, mousedown.y))
       
   168         return false;
       
   169 
       
   170             mousedown.x -= m_scrollbar->x();
       
   171             mousedown.y -= m_scrollbar->y();
       
   172             m_scrollbar->mouseDown(PlatformMouseEventBuilder(m_scrollbar.get(), mousedown));
       
   173             return true;
       
   174         }
       
   175 
       
   176 bool WebScrollbarImpl::onMouseUp(const WebInputEvent& event)
       
   177 {
       
   178     if (m_scrollbar->pressedPart() == NoPart)
       
   179         return false;
       
   180 
       
   181     return m_scrollbar->mouseUp();
       
   182 }
       
   183 
       
   184 bool WebScrollbarImpl::onMouseMove(const WebInputEvent& event)
       
   185 {
       
   186         WebMouseEvent mousemove = *static_cast<const WebMouseEvent*>(&event);
       
   187         if (m_scrollbar->frameRect().contains(mousemove.x, mousemove.y)
       
   188             || m_scrollbar->pressedPart() != NoPart) {
       
   189             mousemove.x -= m_scrollbar->x();
       
   190             mousemove.y -= m_scrollbar->y();
       
   191             return m_scrollbar->mouseMoved(PlatformMouseEventBuilder(m_scrollbar.get(), mousemove));
       
   192         }
       
   193 
       
   194         if (m_scrollbar->hoveredPart() != NoPart)
       
   195             m_scrollbar->mouseExited();
       
   196     return false;
       
   197 }
       
   198 
       
   199 bool WebScrollbarImpl::onMouseLeave(const WebInputEvent& event)
       
   200 {
       
   201     if (m_scrollbar->hoveredPart() == NoPart)
       
   202         return false;
       
   203 
       
   204     return m_scrollbar->mouseExited();
       
   205 }
       
   206 
       
   207 bool WebScrollbarImpl::onMouseWheel(const WebInputEvent& event)
       
   208 {
       
   209         // Same logic as in Scrollview.cpp.  If we can move at all, we'll accept the event.
       
   210         WebMouseWheelEvent mousewheel = *static_cast<const WebMouseWheelEvent*>(&event);
       
   211         int maxScrollDelta = m_scrollbar->maximum() - m_scrollbar->value();
       
   212         float delta = m_scrollbar->orientation() == HorizontalScrollbar ? mousewheel.deltaX : mousewheel.deltaY;
       
   213         if ((delta < 0 && maxScrollDelta > 0) || (delta > 0 && m_scrollbar->value() > 0)) {
       
   214             if (mousewheel.scrollByPage) {
       
   215                 ASSERT(m_scrollbar->orientation() == VerticalScrollbar);
       
   216                 bool negative = delta < 0;
       
   217                 delta = max(max<int>(m_scrollbar->visibleSize() * Scrollbar::minFractionToStepWhenPaging(), m_scrollbar->visibleSize() - Scrollbar::maxOverlapBetweenPages()), 1);
       
   218                 if (negative)
       
   219                     delta *= -1;
       
   220             }
       
   221             m_scrollbar->setValue(m_scrollbar->value() - delta);
       
   222             return true;
       
   223         }
       
   224 
       
   225     return false;
       
   226     }
       
   227 
       
   228 bool WebScrollbarImpl::onKeyDown(const WebInputEvent& event)
       
   229 {
       
   230         WebKeyboardEvent keyboard = *static_cast<const WebKeyboardEvent*>(&event);
       
   231         int keyCode;
       
   232         // We have to duplicate this logic from WebViewImpl because there it uses
       
   233         // Char and RawKeyDown events, which don't exist at this point.
       
   234         if (keyboard.windowsKeyCode == VKEY_SPACE)
       
   235             keyCode = ((keyboard.modifiers & WebInputEvent::ShiftKey) ? VKEY_PRIOR : VKEY_NEXT);
       
   236         else {
       
   237             if (keyboard.modifiers == WebInputEvent::ControlKey) {
       
   238                 // Match FF behavior in the sense that Ctrl+home/end are the only Ctrl
       
   239                 // key combinations which affect scrolling. Safari is buggy in the
       
   240                 // sense that it scrolls the page for all Ctrl+scrolling key
       
   241                 // combinations. For e.g. Ctrl+pgup/pgdn/up/down, etc.
       
   242                 switch (keyboard.windowsKeyCode) {
       
   243                 case VKEY_HOME:
       
   244                 case VKEY_END:
       
   245                     break;
       
   246                 default:
       
   247                     return false;
       
   248                 }
       
   249             }
       
   250 
       
   251             if (keyboard.isSystemKey || (keyboard.modifiers & WebInputEvent::ShiftKey))
       
   252                 return false;
       
   253 
       
   254             keyCode = keyboard.windowsKeyCode;
       
   255         }
       
   256         WebCore::ScrollDirection scrollDirection;
       
   257         WebCore::ScrollGranularity scrollGranularity;
       
   258         if (WebViewImpl::mapKeyCodeForScroll(keyCode, &scrollDirection, &scrollGranularity)) {
       
   259             // Will return false if scroll direction wasn't compatible with this scrollbar.
       
   260             return m_scrollbar->scroll(scrollDirection, scrollGranularity);
       
   261         }
       
   262     return false;
       
   263 }
       
   264 
       
   265 void WebScrollbarImpl::valueChanged(WebCore::Scrollbar*)
       
   266 {
       
   267     m_client->valueChanged(this);
       
   268 }
       
   269 
       
   270 void WebScrollbarImpl::invalidateScrollbarRect(WebCore::Scrollbar*, const WebCore::IntRect& rect)
       
   271 {
       
   272     WebRect webrect(rect);
       
   273     webrect.x += m_scrollbar->x();
       
   274     webrect.y += m_scrollbar->y();
       
   275     m_client->invalidateScrollbarRect(this, webrect);
       
   276 }
       
   277 
       
   278 bool WebScrollbarImpl::isActive() const
       
   279 {
       
   280     return true;
       
   281 }
       
   282 
       
   283 bool WebScrollbarImpl::scrollbarCornerPresent() const
       
   284 {
       
   285     return false;
       
   286 }
       
   287 
       
   288 void WebScrollbarImpl::getTickmarks(Vector<WebCore::IntRect>& tickmarks) const
       
   289 {
       
   290     WebVector<WebRect> ticks;
       
   291     m_client->getTickmarks(const_cast<WebScrollbarImpl*>(this), &ticks);
       
   292     tickmarks.resize(ticks.size());
       
   293     for (size_t i = 0; i < ticks.size(); ++i)
       
   294         tickmarks[i] = ticks[i];
       
   295 }
       
   296 
       
   297 } // namespace WebKit