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