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