Home | History | Annotate | Download | only in web
      1 /*
      2  * Copyright (C) 2012 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
      6  * are met:
      7  * 1.  Redistributions of source code must retain the above copyright
      8  *     notice, this list of conditions and the following disclaimer.
      9  * 2.  Redistributions in binary form must reproduce the above copyright
     10  *     notice, this list of conditions and the following disclaimer in the
     11  *     documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     16  * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     18  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     19  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
     20  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     22  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     23  */
     24 
     25 #include "config.h"
     26 #include "WebPluginScrollbarImpl.h"
     27 
     28 #include "ScrollbarGroup.h"
     29 #include "WebInputEvent.h"
     30 #include "WebInputEventConversion.h"
     31 #include "WebPluginContainerImpl.h"
     32 #include "WebPluginScrollbarClient.h"
     33 #include "WebViewImpl.h"
     34 #include "platform/KeyboardCodes.h"
     35 #include "platform/scroll/ScrollAnimator.h"
     36 #include "platform/scroll/Scrollbar.h"
     37 #include "platform/scroll/ScrollbarTheme.h"
     38 #include "platform/graphics/GraphicsContext.h"
     39 #include "platform/scroll/ScrollTypes.h"
     40 #include "public/platform/WebCanvas.h"
     41 #include "public/platform/WebRect.h"
     42 #include "public/platform/WebVector.h"
     43 
     44 using namespace std;
     45 using namespace WebCore;
     46 
     47 namespace blink {
     48 
     49 WebPluginScrollbar* WebPluginScrollbar::createForPlugin(Orientation orientation,
     50                                                         WebPluginContainer* pluginContainer,
     51                                                         WebPluginScrollbarClient* client)
     52 {
     53     WebPluginContainerImpl* plugin = toPluginContainerImpl(pluginContainer);
     54     return new WebPluginScrollbarImpl(orientation, plugin->scrollbarGroup(), client);
     55 }
     56 
     57 int WebPluginScrollbar::defaultThickness()
     58 {
     59     return ScrollbarTheme::theme()->scrollbarThickness();
     60 }
     61 
     62 WebPluginScrollbarImpl::WebPluginScrollbarImpl(Orientation orientation,
     63                                    ScrollbarGroup* group,
     64                                    WebPluginScrollbarClient* client)
     65     : m_group(group)
     66     , m_client(client)
     67     , m_scrollOffset(0)
     68 {
     69     m_scrollbar = Scrollbar::create(
     70         static_cast<ScrollableArea*>(m_group),
     71         static_cast<WebCore::ScrollbarOrientation>(orientation),
     72         WebCore::RegularScrollbar);
     73     m_group->scrollbarCreated(this);
     74 }
     75 
     76 WebPluginScrollbarImpl::~WebPluginScrollbarImpl()
     77 {
     78     m_group->scrollbarDestroyed(this);
     79 }
     80 
     81 void WebPluginScrollbarImpl::setScrollOffset(int scrollOffset)
     82 {
     83     m_scrollOffset = scrollOffset;
     84     m_client->valueChanged(this);
     85 }
     86 
     87 void WebPluginScrollbarImpl::invalidateScrollbarRect(const IntRect& rect)
     88 {
     89     WebRect webrect(rect);
     90     webrect.x += m_scrollbar->x();
     91     webrect.y += m_scrollbar->y();
     92     m_client->invalidateScrollbarRect(this, webrect);
     93 }
     94 
     95 void WebPluginScrollbarImpl::getTickmarks(Vector<IntRect>& tickmarks) const
     96 {
     97     WebVector<WebRect> ticks;
     98     m_client->getTickmarks(const_cast<WebPluginScrollbarImpl*>(this), &ticks);
     99     tickmarks.resize(ticks.size());
    100     for (size_t i = 0; i < ticks.size(); ++i)
    101         tickmarks[i] = ticks[i];
    102 }
    103 
    104 IntPoint WebPluginScrollbarImpl::convertFromContainingViewToScrollbar(const IntPoint& parentPoint) const
    105 {
    106     IntPoint offset(parentPoint.x() - m_scrollbar->x(), parentPoint.y() - m_scrollbar->y());
    107     return m_scrollbar->Widget::convertFromContainingView(offset);
    108 }
    109 
    110 void WebPluginScrollbarImpl::scrollbarStyleChanged()
    111 {
    112     m_client->overlayChanged(this);
    113 }
    114 
    115 bool WebPluginScrollbarImpl::isOverlay() const
    116 {
    117     return m_scrollbar->isOverlayScrollbar();
    118 }
    119 
    120 int WebPluginScrollbarImpl::value() const
    121 {
    122     return m_scrollOffset;
    123 }
    124 
    125 WebPoint WebPluginScrollbarImpl::location() const
    126 {
    127     return m_scrollbar->frameRect().location();
    128 }
    129 
    130 WebSize WebPluginScrollbarImpl::size() const
    131 {
    132     return m_scrollbar->frameRect().size();
    133 }
    134 
    135 bool WebPluginScrollbarImpl::enabled() const
    136 {
    137     return m_scrollbar->enabled();
    138 }
    139 
    140 int WebPluginScrollbarImpl::maximum() const
    141 {
    142     return m_scrollbar->maximum();
    143 }
    144 
    145 int WebPluginScrollbarImpl::totalSize() const
    146 {
    147     return m_scrollbar->totalSize();
    148 }
    149 
    150 bool WebPluginScrollbarImpl::isScrollViewScrollbar() const
    151 {
    152     return m_scrollbar->isScrollViewScrollbar();
    153 }
    154 
    155 bool WebPluginScrollbarImpl::isScrollableAreaActive() const
    156 {
    157     return m_scrollbar->isScrollableAreaActive();
    158 }
    159 
    160 void WebPluginScrollbarImpl::getTickmarks(WebVector<WebRect>& tickmarks) const
    161 {
    162     m_client->getTickmarks(const_cast<WebPluginScrollbarImpl*>(this), &tickmarks);
    163 }
    164 
    165 WebScrollbar::ScrollbarControlSize WebPluginScrollbarImpl::controlSize() const
    166 {
    167     return static_cast<WebScrollbar::ScrollbarControlSize>(m_scrollbar->controlSize());
    168 }
    169 
    170 WebScrollbar::ScrollbarPart WebPluginScrollbarImpl::pressedPart() const
    171 {
    172     return static_cast<WebScrollbar::ScrollbarPart>(m_scrollbar->pressedPart());
    173 }
    174 
    175 WebScrollbar::ScrollbarPart WebPluginScrollbarImpl::hoveredPart() const
    176 {
    177     return static_cast<WebScrollbar::ScrollbarPart>(m_scrollbar->hoveredPart());
    178 }
    179 
    180 WebScrollbar::ScrollbarOverlayStyle WebPluginScrollbarImpl::scrollbarOverlayStyle() const
    181 {
    182     return static_cast<WebScrollbar::ScrollbarOverlayStyle>(m_scrollbar->scrollbarOverlayStyle());
    183 }
    184 
    185 WebScrollbar::Orientation WebPluginScrollbarImpl::orientation() const
    186 {
    187     if (m_scrollbar->orientation() == WebCore::HorizontalScrollbar)
    188         return WebScrollbar::Horizontal;
    189     return WebScrollbar::Vertical;
    190 }
    191 
    192 bool WebPluginScrollbarImpl::isLeftSideVerticalScrollbar() const
    193 {
    194     return false;
    195 }
    196 
    197 bool WebPluginScrollbarImpl::isCustomScrollbar() const
    198 {
    199     return m_scrollbar->isCustomScrollbar();
    200 }
    201 
    202 void WebPluginScrollbarImpl::setLocation(const WebRect& rect)
    203 {
    204     IntRect oldRect = m_scrollbar->frameRect();
    205     m_scrollbar->setFrameRect(rect);
    206     if (WebRect(oldRect) != rect)
    207       m_scrollbar->invalidate();
    208 
    209     int length = m_scrollbar->orientation() == HorizontalScrollbar ? m_scrollbar->width() : m_scrollbar->height();
    210     m_scrollbar->setEnabled(m_scrollbar->totalSize() > length);
    211     m_scrollbar->setProportion(length, m_scrollbar->totalSize());
    212 }
    213 
    214 void WebPluginScrollbarImpl::setValue(int position)
    215 {
    216     m_group->scrollToOffsetWithoutAnimation(m_scrollbar->orientation(), static_cast<float>(position));
    217 }
    218 
    219 void WebPluginScrollbarImpl::setDocumentSize(int size)
    220 {
    221     int length = m_scrollbar->orientation() == HorizontalScrollbar ? m_scrollbar->width() : m_scrollbar->height();
    222     m_scrollbar->setEnabled(size > length);
    223     m_scrollbar->setProportion(length, size);
    224 }
    225 
    226 void WebPluginScrollbarImpl::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier)
    227 {
    228     WebCore::ScrollDirection dir;
    229     bool horizontal = m_scrollbar->orientation() == HorizontalScrollbar;
    230     if (direction == ScrollForward)
    231         dir = horizontal ? ScrollRight : ScrollDown;
    232     else
    233         dir = horizontal ? ScrollLeft : ScrollUp;
    234 
    235     m_group->scroll(dir, static_cast<WebCore::ScrollGranularity>(granularity), multiplier);
    236 }
    237 
    238 void WebPluginScrollbarImpl::paint(WebCanvas* canvas, const WebRect& rect)
    239 {
    240     GraphicsContext context(canvas);
    241     m_scrollbar->paint(&context, rect);
    242 }
    243 
    244 bool WebPluginScrollbarImpl::handleInputEvent(const WebInputEvent& event)
    245 {
    246     switch (event.type) {
    247     case WebInputEvent::MouseDown:
    248         return onMouseDown(event);
    249     case WebInputEvent::MouseUp:
    250         return onMouseUp(event);
    251     case WebInputEvent::MouseMove:
    252         return onMouseMove(event);
    253     case WebInputEvent::MouseLeave:
    254         return onMouseLeave(event);
    255     case WebInputEvent::MouseWheel:
    256         return onMouseWheel(event);
    257     case WebInputEvent::KeyDown:
    258         return onKeyDown(event);
    259     case WebInputEvent::Undefined:
    260     case WebInputEvent::MouseEnter:
    261     case WebInputEvent::RawKeyDown:
    262     case WebInputEvent::KeyUp:
    263     case WebInputEvent::Char:
    264     case WebInputEvent::TouchStart:
    265     case WebInputEvent::TouchMove:
    266     case WebInputEvent::TouchEnd:
    267     case WebInputEvent::TouchCancel:
    268     default:
    269          break;
    270     }
    271     return false;
    272 }
    273 
    274 bool WebPluginScrollbarImpl::isAlphaLocked() const
    275 {
    276     return m_scrollbar->isAlphaLocked();
    277 }
    278 
    279 void WebPluginScrollbarImpl::setIsAlphaLocked(bool flag)
    280 {
    281     return m_scrollbar->setIsAlphaLocked(flag);
    282 }
    283 
    284 bool WebPluginScrollbarImpl::onMouseDown(const WebInputEvent& event)
    285 {
    286     WebMouseEvent mousedown = *static_cast<const WebMouseEvent*>(&event);
    287     if (!m_scrollbar->frameRect().contains(mousedown.x, mousedown.y))
    288         return false;
    289 
    290     mousedown.x -= m_scrollbar->x();
    291     mousedown.y -= m_scrollbar->y();
    292     m_scrollbar->mouseDown(PlatformMouseEventBuilder(m_scrollbar.get(), mousedown));
    293     return true;
    294 }
    295 
    296 bool WebPluginScrollbarImpl::onMouseUp(const WebInputEvent& event)
    297 {
    298     WebMouseEvent mouseup = *static_cast<const WebMouseEvent*>(&event);
    299     if (m_scrollbar->pressedPart() == WebCore::NoPart)
    300         return false;
    301 
    302     m_scrollbar->mouseUp(PlatformMouseEventBuilder(m_scrollbar.get(), mouseup));
    303     return true;
    304 }
    305 
    306 bool WebPluginScrollbarImpl::onMouseMove(const WebInputEvent& event)
    307 {
    308     WebMouseEvent mousemove = *static_cast<const WebMouseEvent*>(&event);
    309     if (m_scrollbar->frameRect().contains(mousemove.x, mousemove.y)
    310         || m_scrollbar->pressedPart() != WebCore::NoPart) {
    311         mousemove.x -= m_scrollbar->x();
    312         mousemove.y -= m_scrollbar->y();
    313         m_scrollbar->mouseMoved(PlatformMouseEventBuilder(m_scrollbar.get(), mousemove));
    314         return true;
    315     }
    316 
    317     if (m_scrollbar->hoveredPart() != WebCore::NoPart && !m_scrollbar->isOverlayScrollbar())
    318         m_scrollbar->mouseExited();
    319     return false;
    320 }
    321 
    322 bool WebPluginScrollbarImpl::onMouseLeave(const WebInputEvent& event)
    323 {
    324     if (m_scrollbar->hoveredPart() != WebCore::NoPart)
    325         m_scrollbar->mouseExited();
    326 
    327     return false;
    328 }
    329 
    330 bool WebPluginScrollbarImpl::onMouseWheel(const WebInputEvent& event)
    331 {
    332     WebMouseWheelEvent mousewheel = *static_cast<const WebMouseWheelEvent*>(&event);
    333     PlatformWheelEventBuilder platformEvent(m_scrollbar.get(), mousewheel);
    334     return m_group->handleWheelEvent(platformEvent);
    335 }
    336 
    337 bool WebPluginScrollbarImpl::onKeyDown(const WebInputEvent& event)
    338 {
    339     WebKeyboardEvent keyboard = *static_cast<const WebKeyboardEvent*>(&event);
    340     int keyCode;
    341     // We have to duplicate this logic from WebViewImpl because there it uses
    342     // Char and RawKeyDown events, which don't exist at this point.
    343     if (keyboard.windowsKeyCode == VKEY_SPACE)
    344         keyCode = ((keyboard.modifiers & WebInputEvent::ShiftKey) ? VKEY_PRIOR : VKEY_NEXT);
    345     else {
    346         if (keyboard.modifiers == WebInputEvent::ControlKey) {
    347             // Match FF behavior in the sense that Ctrl+home/end are the only Ctrl
    348             // key combinations which affect scrolling. Safari is buggy in the
    349             // sense that it scrolls the page for all Ctrl+scrolling key
    350             // combinations. For e.g. Ctrl+pgup/pgdn/up/down, etc.
    351             switch (keyboard.windowsKeyCode) {
    352             case VKEY_HOME:
    353             case VKEY_END:
    354                 break;
    355             default:
    356                 return false;
    357             }
    358         }
    359 
    360         if (keyboard.isSystemKey || (keyboard.modifiers & WebInputEvent::ShiftKey))
    361             return false;
    362 
    363         keyCode = keyboard.windowsKeyCode;
    364     }
    365     WebCore::ScrollDirection scrollDirection;
    366     WebCore::ScrollGranularity scrollGranularity;
    367     if (WebViewImpl::mapKeyCodeForScroll(keyCode, &scrollDirection, &scrollGranularity)) {
    368         // Will return false if scroll direction wasn't compatible with this scrollbar.
    369         return m_group->scroll(scrollDirection, scrollGranularity);
    370     }
    371     return false;
    372 }
    373 
    374 } // namespace blink
    375