• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 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 are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include "config.h"
32 #include "WebScrollbarImpl.h"
33 
34 #include "GraphicsContext.h"
35 #include "KeyboardCodes.h"
36 #include "painting/GraphicsContextBuilder.h"
37 #include "Scrollbar.h"
38 #include "ScrollbarTheme.h"
39 #include "ScrollTypes.h"
40 #include "WebCanvas.h"
41 #include "WebInputEvent.h"
42 #include "WebInputEventConversion.h"
43 #include "WebRect.h"
44 #include "WebScrollbarClient.h"
45 #include "WebVector.h"
46 #include "WebViewImpl.h"
47 
48 using namespace std;
49 using namespace WebCore;
50 
51 namespace WebKit {
52 
create(WebScrollbarClient * client,Orientation orientation)53 WebScrollbar* WebScrollbar::create(WebScrollbarClient* client, Orientation orientation)
54 {
55     return new WebScrollbarImpl(client, orientation);
56 }
57 
defaultThickness()58 int WebScrollbar::defaultThickness()
59 {
60     return ScrollbarTheme::nativeTheme()->scrollbarThickness();
61 }
62 
WebScrollbarImpl(WebScrollbarClient * client,Orientation orientation)63 WebScrollbarImpl::WebScrollbarImpl(WebScrollbarClient* client, Orientation orientation)
64     : m_client(client)
65     , m_scrollOffset(0)
66 {
67     m_scrollbar = Scrollbar::createNativeScrollbar(
68         static_cast<ScrollableArea*>(this),
69         static_cast<ScrollbarOrientation>(orientation),
70         RegularScrollbar);
71 }
72 
~WebScrollbarImpl()73 WebScrollbarImpl::~WebScrollbarImpl()
74 {
75 }
76 
setLocation(const WebRect & rect)77 void WebScrollbarImpl::setLocation(const WebRect& rect)
78 {
79     IntRect oldRect = m_scrollbar->frameRect();
80     m_scrollbar->setFrameRect(rect);
81     if (WebRect(oldRect) != rect)
82       m_scrollbar->invalidate();
83 
84     int length = m_scrollbar->orientation() == HorizontalScrollbar ? m_scrollbar->width() : m_scrollbar->height();
85     int pageStep = max(max(static_cast<int>(static_cast<float>(length) * Scrollbar::minFractionToStepWhenPaging()), length - Scrollbar::maxOverlapBetweenPages()), 1);
86     m_scrollbar->setSteps(Scrollbar::pixelsPerLineStep(), pageStep);
87     m_scrollbar->setEnabled(m_scrollbar->totalSize() > length);
88     m_scrollbar->setProportion(length, m_scrollbar->totalSize());
89 }
90 
value() const91 int WebScrollbarImpl::value() const
92 {
93     return m_scrollOffset;
94 }
95 
setValue(int position)96 void WebScrollbarImpl::setValue(int position)
97 {
98     ScrollableArea::scrollToOffsetWithoutAnimation(m_scrollbar->orientation(), static_cast<float>(position));
99 }
100 
setDocumentSize(int size)101 void WebScrollbarImpl::setDocumentSize(int size)
102 {
103     int length = m_scrollbar->orientation() == HorizontalScrollbar ? m_scrollbar->width() : m_scrollbar->height();
104     m_scrollbar->setEnabled(size > length);
105     m_scrollbar->setProportion(length, size);
106 }
107 
scroll(ScrollDirection direction,ScrollGranularity granularity,float multiplier)108 void WebScrollbarImpl::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier)
109 {
110     WebCore::ScrollDirection dir;
111     bool horizontal = m_scrollbar->orientation() == HorizontalScrollbar;
112     if (direction == ScrollForward)
113         dir = horizontal ? ScrollRight : ScrollDown;
114     else
115         dir = horizontal ? ScrollLeft : ScrollUp;
116 
117     WebCore::ScrollableArea::scroll(dir, static_cast<WebCore::ScrollGranularity>(granularity), multiplier);
118 }
119 
paint(WebCanvas * canvas,const WebRect & rect)120 void WebScrollbarImpl::paint(WebCanvas* canvas, const WebRect& rect)
121 {
122     m_scrollbar->paint(&GraphicsContextBuilder(canvas).context(), rect);
123 }
124 
handleInputEvent(const WebInputEvent & event)125 bool WebScrollbarImpl::handleInputEvent(const WebInputEvent& event)
126 {
127     switch (event.type) {
128     case WebInputEvent::MouseDown:
129         return onMouseDown(event);
130     case WebInputEvent::MouseUp:
131         return onMouseUp(event);
132     case WebInputEvent::MouseMove:
133         return onMouseMove(event);
134     case WebInputEvent::MouseLeave:
135         return onMouseLeave(event);
136     case WebInputEvent::MouseWheel:
137         return onMouseWheel(event);
138     case WebInputEvent::KeyDown:
139         return onKeyDown(event);
140     case WebInputEvent::Undefined:
141     case WebInputEvent::MouseEnter:
142     case WebInputEvent::RawKeyDown:
143     case WebInputEvent::KeyUp:
144     case WebInputEvent::Char:
145     case WebInputEvent::TouchStart:
146     case WebInputEvent::TouchMove:
147     case WebInputEvent::TouchEnd:
148     case WebInputEvent::TouchCancel:
149     default:
150          break;
151     }
152     return false;
153 }
154 
onMouseDown(const WebInputEvent & event)155 bool WebScrollbarImpl::onMouseDown(const WebInputEvent& event)
156 {
157     WebMouseEvent mousedown = *static_cast<const WebMouseEvent*>(&event);
158     if (!m_scrollbar->frameRect().contains(mousedown.x, mousedown.y))
159         return false;
160 
161     mousedown.x -= m_scrollbar->x();
162     mousedown.y -= m_scrollbar->y();
163     m_scrollbar->mouseDown(PlatformMouseEventBuilder(m_scrollbar.get(), mousedown));
164     return true;
165 }
166 
onMouseUp(const WebInputEvent & event)167 bool WebScrollbarImpl::onMouseUp(const WebInputEvent& event)
168 {
169     if (m_scrollbar->pressedPart() == NoPart)
170         return false;
171 
172     return m_scrollbar->mouseUp();
173 }
174 
onMouseMove(const WebInputEvent & event)175 bool WebScrollbarImpl::onMouseMove(const WebInputEvent& event)
176 {
177     WebMouseEvent mousemove = *static_cast<const WebMouseEvent*>(&event);
178     if (m_scrollbar->frameRect().contains(mousemove.x, mousemove.y)
179         || m_scrollbar->pressedPart() != NoPart) {
180         mousemove.x -= m_scrollbar->x();
181         mousemove.y -= m_scrollbar->y();
182         return m_scrollbar->mouseMoved(PlatformMouseEventBuilder(m_scrollbar.get(), mousemove));
183     }
184 
185     if (m_scrollbar->hoveredPart() != NoPart)
186         m_scrollbar->mouseExited();
187     return false;
188 }
189 
onMouseLeave(const WebInputEvent & event)190 bool WebScrollbarImpl::onMouseLeave(const WebInputEvent& event)
191 {
192     if (m_scrollbar->hoveredPart() == NoPart)
193         return false;
194 
195     return m_scrollbar->mouseExited();
196 }
197 
onMouseWheel(const WebInputEvent & event)198 bool WebScrollbarImpl::onMouseWheel(const WebInputEvent& event)
199 {
200     // Same logic as in Scrollview.cpp.  If we can move at all, we'll accept the event.
201     WebMouseWheelEvent mousewheel = *static_cast<const WebMouseWheelEvent*>(&event);
202     int maxScrollDelta = m_scrollbar->maximum() - m_scrollbar->value();
203     float delta = m_scrollbar->orientation() == HorizontalScrollbar ? mousewheel.deltaX : mousewheel.deltaY;
204     if ((delta < 0 && maxScrollDelta > 0) || (delta > 0 && m_scrollbar->value() > 0)) {
205         if (mousewheel.scrollByPage) {
206             ASSERT(m_scrollbar->orientation() == VerticalScrollbar);
207             bool negative = delta < 0;
208             delta = max(max(static_cast<float>(m_scrollbar->visibleSize()) * Scrollbar::minFractionToStepWhenPaging(), static_cast<float>(m_scrollbar->visibleSize() - Scrollbar::maxOverlapBetweenPages())), 1.0f);
209             if (negative)
210                 delta *= -1;
211         }
212         ScrollableArea::scroll((m_scrollbar->orientation() == HorizontalScrollbar) ? WebCore::ScrollLeft : WebCore::ScrollUp, WebCore::ScrollByPixel, delta);
213         return true;
214     }
215 
216     return false;
217     }
218 
onKeyDown(const WebInputEvent & event)219 bool WebScrollbarImpl::onKeyDown(const WebInputEvent& event)
220 {
221     WebKeyboardEvent keyboard = *static_cast<const WebKeyboardEvent*>(&event);
222     int keyCode;
223     // We have to duplicate this logic from WebViewImpl because there it uses
224     // Char and RawKeyDown events, which don't exist at this point.
225     if (keyboard.windowsKeyCode == VKEY_SPACE)
226         keyCode = ((keyboard.modifiers & WebInputEvent::ShiftKey) ? VKEY_PRIOR : VKEY_NEXT);
227     else {
228         if (keyboard.modifiers == WebInputEvent::ControlKey) {
229             // Match FF behavior in the sense that Ctrl+home/end are the only Ctrl
230             // key combinations which affect scrolling. Safari is buggy in the
231             // sense that it scrolls the page for all Ctrl+scrolling key
232             // combinations. For e.g. Ctrl+pgup/pgdn/up/down, etc.
233             switch (keyboard.windowsKeyCode) {
234             case VKEY_HOME:
235             case VKEY_END:
236                 break;
237             default:
238                 return false;
239             }
240         }
241 
242         if (keyboard.isSystemKey || (keyboard.modifiers & WebInputEvent::ShiftKey))
243             return false;
244 
245         keyCode = keyboard.windowsKeyCode;
246     }
247     WebCore::ScrollDirection scrollDirection;
248     WebCore::ScrollGranularity scrollGranularity;
249     if (WebViewImpl::mapKeyCodeForScroll(keyCode, &scrollDirection, &scrollGranularity)) {
250         // Will return false if scroll direction wasn't compatible with this scrollbar.
251         return ScrollableArea::scroll(scrollDirection, scrollGranularity);
252     }
253     return false;
254 }
255 
scrollSize(WebCore::ScrollbarOrientation orientation) const256 int WebScrollbarImpl::scrollSize(WebCore::ScrollbarOrientation orientation) const
257 {
258     return (orientation == m_scrollbar->orientation()) ? (m_scrollbar->totalSize() - m_scrollbar->visibleSize()) : 0;
259 }
260 
scrollPosition(Scrollbar *) const261 int WebScrollbarImpl::scrollPosition(Scrollbar*) const
262 {
263     return m_scrollOffset;
264 }
265 
setScrollOffset(const IntPoint & offset)266 void WebScrollbarImpl::setScrollOffset(const IntPoint& offset)
267 {
268     if (m_scrollbar->orientation() == HorizontalScrollbar)
269         m_scrollOffset = offset.x();
270     else
271         m_scrollOffset = offset.y();
272 
273     m_client->valueChanged(this);
274 }
275 
invalidateScrollbarRect(Scrollbar *,const IntRect & rect)276 void WebScrollbarImpl::invalidateScrollbarRect(Scrollbar*, const IntRect& rect)
277 {
278     WebRect webrect(rect);
279     webrect.x += m_scrollbar->x();
280     webrect.y += m_scrollbar->y();
281     m_client->invalidateScrollbarRect(this, webrect);
282 }
283 
invalidateScrollCornerRect(const IntRect &)284 void WebScrollbarImpl::invalidateScrollCornerRect(const IntRect&)
285 {
286 }
287 
isActive() const288 bool WebScrollbarImpl::isActive() const
289 {
290     return true;
291 }
292 
isScrollCornerVisible() const293 bool WebScrollbarImpl::isScrollCornerVisible() const
294 {
295     return false;
296 }
297 
getTickmarks(Vector<IntRect> & tickmarks) const298 void WebScrollbarImpl::getTickmarks(Vector<IntRect>& tickmarks) const
299 {
300     WebVector<WebRect> ticks;
301     m_client->getTickmarks(const_cast<WebScrollbarImpl*>(this), &ticks);
302     tickmarks.resize(ticks.size());
303     for (size_t i = 0; i < ticks.size(); ++i)
304         tickmarks[i] = ticks[i];
305 }
306 
horizontalScrollbar() const307 Scrollbar* WebScrollbarImpl::horizontalScrollbar() const
308 {
309     return m_scrollbar->orientation() == HorizontalScrollbar ? m_scrollbar.get() : 0;
310 }
311 
verticalScrollbar() const312 Scrollbar* WebScrollbarImpl::verticalScrollbar() const
313 {
314     return m_scrollbar->orientation() == VerticalScrollbar ? m_scrollbar.get() : 0;
315 }
316 
317 } // namespace WebKit
318