93358390ac76de9d632b2a946105093a8d4bbe7e
[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 namespace blink {
45
46 WebPluginScrollbar* 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
54 int WebPluginScrollbar::defaultThickness()
55 {
56     return ScrollbarTheme::theme()->scrollbarThickness();
57 }
58
59 WebPluginScrollbarImpl::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
73 WebPluginScrollbarImpl::~WebPluginScrollbarImpl()
74 {
75     m_group->scrollbarDestroyed(this);
76 }
77
78 void WebPluginScrollbarImpl::setScrollOffset(int scrollOffset)
79 {
80     m_scrollOffset = scrollOffset;
81     m_client->valueChanged(this);
82 }
83
84 void 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
92 void 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
101 IntPoint 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
107 void WebPluginScrollbarImpl::scrollbarStyleChanged()
108 {
109     m_client->overlayChanged(this);
110 }
111
112 bool WebPluginScrollbarImpl::isOverlay() const
113 {
114     return m_scrollbar->isOverlayScrollbar();
115 }
116
117 int WebPluginScrollbarImpl::value() const
118 {
119     return m_scrollOffset;
120 }
121
122 WebPoint WebPluginScrollbarImpl::location() const
123 {
124     return m_scrollbar->frameRect().location();
125 }
126
127 WebSize WebPluginScrollbarImpl::size() const
128 {
129     return m_scrollbar->frameRect().size();
130 }
131
132 bool WebPluginScrollbarImpl::enabled() const
133 {
134     return m_scrollbar->enabled();
135 }
136
137 int WebPluginScrollbarImpl::maximum() const
138 {
139     return m_scrollbar->maximum();
140 }
141
142 int WebPluginScrollbarImpl::totalSize() const
143 {
144     return m_scrollbar->totalSize();
145 }
146
147 bool WebPluginScrollbarImpl::isScrollViewScrollbar() const
148 {
149     return m_scrollbar->isScrollViewScrollbar();
150 }
151
152 bool WebPluginScrollbarImpl::isScrollableAreaActive() const
153 {
154     return m_scrollbar->isScrollableAreaActive();
155 }
156
157 void WebPluginScrollbarImpl::getTickmarks(WebVector<WebRect>& tickmarks) const
158 {
159     m_client->getTickmarks(const_cast<WebPluginScrollbarImpl*>(this), &tickmarks);
160 }
161
162 WebScrollbar::ScrollbarControlSize WebPluginScrollbarImpl::controlSize() const
163 {
164     return static_cast<WebScrollbar::ScrollbarControlSize>(m_scrollbar->controlSize());
165 }
166
167 WebScrollbar::ScrollbarPart WebPluginScrollbarImpl::pressedPart() const
168 {
169     return static_cast<WebScrollbar::ScrollbarPart>(m_scrollbar->pressedPart());
170 }
171
172 WebScrollbar::ScrollbarPart WebPluginScrollbarImpl::hoveredPart() const
173 {
174     return static_cast<WebScrollbar::ScrollbarPart>(m_scrollbar->hoveredPart());
175 }
176
177 WebScrollbar::ScrollbarOverlayStyle WebPluginScrollbarImpl::scrollbarOverlayStyle() const
178 {
179     return static_cast<WebScrollbar::ScrollbarOverlayStyle>(m_scrollbar->scrollbarOverlayStyle());
180 }
181
182 WebScrollbar::Orientation WebPluginScrollbarImpl::orientation() const
183 {
184     if (m_scrollbar->orientation() == HorizontalScrollbar)
185         return WebScrollbar::Horizontal;
186     return WebScrollbar::Vertical;
187 }
188
189 bool WebPluginScrollbarImpl::isLeftSideVerticalScrollbar() const
190 {
191     return false;
192 }
193
194 bool WebPluginScrollbarImpl::isCustomScrollbar() const
195 {
196     return m_scrollbar->isCustomScrollbar();
197 }
198
199 void 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
211 void WebPluginScrollbarImpl::setValue(int position)
212 {
213     m_group->scrollToOffsetWithoutAnimation(m_scrollbar->orientation(), static_cast<float>(position));
214 }
215
216 void 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
223 void 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
235 void WebPluginScrollbarImpl::paint(WebCanvas* canvas, const WebRect& rect)
236 {
237     GraphicsContext context(canvas);
238     m_scrollbar->paint(&context, rect);
239 }
240
241 bool 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
271 bool WebPluginScrollbarImpl::isAlphaLocked() const
272 {
273     return m_scrollbar->isAlphaLocked();
274 }
275
276 void WebPluginScrollbarImpl::setIsAlphaLocked(bool flag)
277 {
278     return m_scrollbar->setIsAlphaLocked(flag);
279 }
280
281 bool 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
293 bool 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
303 bool 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
319 bool WebPluginScrollbarImpl::onMouseLeave(const WebInputEvent& event)
320 {
321     if (m_scrollbar->hoveredPart() != blink::NoPart)
322         m_scrollbar->mouseExited();
323
324     return false;
325 }
326
327 bool 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
334 bool 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