Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / web / WebPluginScrollbarImpl.cpp
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 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 = toWebPluginContainerImpl(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