blob: 5ed34b87cff8ecc07d966699728e0e4644d1257f [file] [log] [blame]
Torne (Richard Coles)5c87bf82012-11-14 11:46:17 +00001/*
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
Torne (Richard Coles)5c87bf82012-11-14 11:46:17 +000028#include "ScrollbarGroup.h"
Torne (Richard Coles)5c87bf82012-11-14 11:46:17 +000029#include "WebInputEvent.h"
30#include "WebInputEventConversion.h"
31#include "WebPluginContainerImpl.h"
32#include "WebPluginScrollbarClient.h"
33#include "WebViewImpl.h"
Torne (Richard Coles)09380292014-02-21 12:17:33 +000034#include "platform/KeyboardCodes.h"
Torne (Richard Coles)a854de02013-12-18 16:25:25 +000035#include "platform/scroll/ScrollAnimator.h"
36#include "platform/scroll/Scrollbar.h"
37#include "platform/scroll/ScrollbarTheme.h"
Torne (Richard Coles)a854de02013-12-18 16:25:25 +000038#include "platform/graphics/GraphicsContext.h"
Torne (Richard Coles)1e202182013-10-18 15:46:42 +010039#include "platform/scroll/ScrollTypes.h"
Torne (Richard Coles)5267f702013-06-11 10:57:24 +010040#include "public/platform/WebCanvas.h"
41#include "public/platform/WebRect.h"
42#include "public/platform/WebVector.h"
Torne (Richard Coles)5c87bf82012-11-14 11:46:17 +000043
44using namespace std;
45using namespace WebCore;
46
Torne (Richard Coles)51b29062013-11-28 11:56:03 +000047namespace blink {
Torne (Richard Coles)5c87bf82012-11-14 11:46:17 +000048
49WebPluginScrollbar* WebPluginScrollbar::createForPlugin(Orientation orientation,
50 WebPluginContainer* pluginContainer,
51 WebPluginScrollbarClient* client)
52{
Torne (Richard Coles)09380292014-02-21 12:17:33 +000053 WebPluginContainerImpl* plugin = toWebPluginContainerImpl(pluginContainer);
Torne (Richard Coles)5c87bf82012-11-14 11:46:17 +000054 return new WebPluginScrollbarImpl(orientation, plugin->scrollbarGroup(), client);
55}
56
57int WebPluginScrollbar::defaultThickness()
58{
59 return ScrollbarTheme::theme()->scrollbarThickness();
60}
61
62WebPluginScrollbarImpl::WebPluginScrollbarImpl(Orientation orientation,
63 ScrollbarGroup* group,
64 WebPluginScrollbarClient* client)
65 : m_group(group)
66 , m_client(client)
67 , m_scrollOffset(0)
68{
Torne (Richard Coles)8abfc582013-09-12 12:10:38 +010069 m_scrollbar = Scrollbar::create(
Torne (Richard Coles)5c87bf82012-11-14 11:46:17 +000070 static_cast<ScrollableArea*>(m_group),
71 static_cast<WebCore::ScrollbarOrientation>(orientation),
72 WebCore::RegularScrollbar);
73 m_group->scrollbarCreated(this);
74}
75
76WebPluginScrollbarImpl::~WebPluginScrollbarImpl()
77{
78 m_group->scrollbarDestroyed(this);
79}
80
81void WebPluginScrollbarImpl::setScrollOffset(int scrollOffset)
82{
83 m_scrollOffset = scrollOffset;
84 m_client->valueChanged(this);
85}
86
87void 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
95void 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
104IntPoint 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
110void WebPluginScrollbarImpl::scrollbarStyleChanged()
111{
112 m_client->overlayChanged(this);
113}
114
115bool WebPluginScrollbarImpl::isOverlay() const
116{
117 return m_scrollbar->isOverlayScrollbar();
118}
119
120int WebPluginScrollbarImpl::value() const
121{
122 return m_scrollOffset;
123}
124
125WebPoint WebPluginScrollbarImpl::location() const
126{
127 return m_scrollbar->frameRect().location();
128}
129
130WebSize WebPluginScrollbarImpl::size() const
131{
132 return m_scrollbar->frameRect().size();
133}
134
135bool WebPluginScrollbarImpl::enabled() const
136{
137 return m_scrollbar->enabled();
138}
139
140int WebPluginScrollbarImpl::maximum() const
141{
142 return m_scrollbar->maximum();
143}
144
145int WebPluginScrollbarImpl::totalSize() const
146{
147 return m_scrollbar->totalSize();
148}
149
150bool WebPluginScrollbarImpl::isScrollViewScrollbar() const
151{
152 return m_scrollbar->isScrollViewScrollbar();
153}
154
155bool WebPluginScrollbarImpl::isScrollableAreaActive() const
156{
157 return m_scrollbar->isScrollableAreaActive();
158}
159
160void WebPluginScrollbarImpl::getTickmarks(WebVector<WebRect>& tickmarks) const
161{
162 m_client->getTickmarks(const_cast<WebPluginScrollbarImpl*>(this), &tickmarks);
163}
164
165WebScrollbar::ScrollbarControlSize WebPluginScrollbarImpl::controlSize() const
166{
167 return static_cast<WebScrollbar::ScrollbarControlSize>(m_scrollbar->controlSize());
168}
169
170WebScrollbar::ScrollbarPart WebPluginScrollbarImpl::pressedPart() const
171{
172 return static_cast<WebScrollbar::ScrollbarPart>(m_scrollbar->pressedPart());
173}
174
175WebScrollbar::ScrollbarPart WebPluginScrollbarImpl::hoveredPart() const
176{
177 return static_cast<WebScrollbar::ScrollbarPart>(m_scrollbar->hoveredPart());
178}
179
180WebScrollbar::ScrollbarOverlayStyle WebPluginScrollbarImpl::scrollbarOverlayStyle() const
181{
182 return static_cast<WebScrollbar::ScrollbarOverlayStyle>(m_scrollbar->scrollbarOverlayStyle());
183}
184
185WebScrollbar::Orientation WebPluginScrollbarImpl::orientation() const
186{
187 if (m_scrollbar->orientation() == WebCore::HorizontalScrollbar)
188 return WebScrollbar::Horizontal;
189 return WebScrollbar::Vertical;
190}
191
Torne (Richard Coles)8abfc582013-09-12 12:10:38 +0100192bool WebPluginScrollbarImpl::isLeftSideVerticalScrollbar() const
Torne (Richard Coles)c0e19a62013-08-30 15:15:11 +0100193{
194 return false;
195}
196
Torne (Richard Coles)5c87bf82012-11-14 11:46:17 +0000197bool WebPluginScrollbarImpl::isCustomScrollbar() const
198{
199 return m_scrollbar->isCustomScrollbar();
200}
201
202void 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();
Torne (Richard Coles)5c87bf82012-11-14 11:46:17 +0000210 m_scrollbar->setEnabled(m_scrollbar->totalSize() > length);
211 m_scrollbar->setProportion(length, m_scrollbar->totalSize());
212}
213
214void WebPluginScrollbarImpl::setValue(int position)
215{
216 m_group->scrollToOffsetWithoutAnimation(m_scrollbar->orientation(), static_cast<float>(position));
217}
218
219void 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
226void 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
238void WebPluginScrollbarImpl::paint(WebCanvas* canvas, const WebRect& rect)
239{
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100240 GraphicsContext context(canvas);
241 m_scrollbar->paint(&context, rect);
Torne (Richard Coles)5c87bf82012-11-14 11:46:17 +0000242}
243
244bool 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
274bool WebPluginScrollbarImpl::isAlphaLocked() const
275{
276 return m_scrollbar->isAlphaLocked();
277}
278
279void WebPluginScrollbarImpl::setIsAlphaLocked(bool flag)
280{
281 return m_scrollbar->setIsAlphaLocked(flag);
282}
283
284bool 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
296bool 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
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100302 m_scrollbar->mouseUp(PlatformMouseEventBuilder(m_scrollbar.get(), mouseup));
303 return true;
Torne (Richard Coles)5c87bf82012-11-14 11:46:17 +0000304}
305
306bool 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();
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100313 m_scrollbar->mouseMoved(PlatformMouseEventBuilder(m_scrollbar.get(), mousemove));
314 return true;
Torne (Richard Coles)5c87bf82012-11-14 11:46:17 +0000315 }
316
317 if (m_scrollbar->hoveredPart() != WebCore::NoPart && !m_scrollbar->isOverlayScrollbar())
318 m_scrollbar->mouseExited();
319 return false;
320}
321
322bool WebPluginScrollbarImpl::onMouseLeave(const WebInputEvent& event)
323{
324 if (m_scrollbar->hoveredPart() != WebCore::NoPart)
325 m_scrollbar->mouseExited();
326
327 return false;
328}
329
330bool 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
337bool 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
Torne (Richard Coles)51b29062013-11-28 11:56:03 +0000374} // namespace blink