Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(32)

Side by Side Diff: Source/core/platform/Scrollbar.cpp

Issue 99103006: Moving GraphicsContext and dependencies from core to platform. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Final patch - fixes Android Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/core/platform/Scrollbar.h ('k') | Source/core/platform/ScrollbarTheme.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2004, 2006, 2008 Apple 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 COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #include "config.h"
27 #include "core/platform/Scrollbar.h"
28
29 #include <algorithm>
30 #include "core/platform/ScrollAnimator.h"
31 #include "core/platform/ScrollView.h"
32 #include "core/platform/ScrollableArea.h"
33 #include "core/platform/ScrollbarTheme.h"
34 #include "core/platform/graphics/GraphicsContext.h"
35
36 #include "platform/PlatformGestureEvent.h"
37 #include "platform/PlatformMouseEvent.h"
38
39 using namespace std;
40
41 #if OS(POSIX) && !OS(MACOSX)
42 // The position of the scrollbar thumb affects the appearance of the steppers, s o
43 // when the thumb moves, we have to invalidate them for painting.
44 #define THUMB_POSITION_AFFECTS_BUTTONS
45 #endif
46
47 namespace WebCore {
48
49 PassRefPtr<Scrollbar> Scrollbar::create(ScrollableArea* scrollableArea, Scrollba rOrientation orientation, ScrollbarControlSize size)
50 {
51 return adoptRef(new Scrollbar(scrollableArea, orientation, size));
52 }
53
54 Scrollbar::Scrollbar(ScrollableArea* scrollableArea, ScrollbarOrientation orient ation, ScrollbarControlSize controlSize, ScrollbarTheme* theme)
55 : m_scrollableArea(scrollableArea)
56 , m_orientation(orientation)
57 , m_controlSize(controlSize)
58 , m_theme(theme)
59 , m_visibleSize(0)
60 , m_totalSize(0)
61 , m_currentPos(0)
62 , m_dragOrigin(0)
63 , m_hoveredPart(NoPart)
64 , m_pressedPart(NoPart)
65 , m_pressedPos(0)
66 , m_scrollPos(0)
67 , m_draggingDocument(false)
68 , m_documentDragPos(0)
69 , m_enabled(true)
70 , m_scrollTimer(this, &Scrollbar::autoscrollTimerFired)
71 , m_overlapsResizer(false)
72 , m_suppressInvalidation(false)
73 , m_isAlphaLocked(false)
74 {
75 if (!m_theme)
76 m_theme = ScrollbarTheme::theme();
77
78 m_theme->registerScrollbar(this);
79
80 // FIXME: This is ugly and would not be necessary if we fix cross-platform c ode to actually query for
81 // scrollbar thickness and use it when sizing scrollbars (rather than leavin g one dimension of the scrollbar
82 // alone when sizing).
83 int thickness = m_theme->scrollbarThickness(controlSize);
84 Widget::setFrameRect(IntRect(0, 0, thickness, thickness));
85
86 m_currentPos = scrollableAreaCurrentPos();
87 }
88
89 Scrollbar::~Scrollbar()
90 {
91 stopTimerIfNeeded();
92
93 m_theme->unregisterScrollbar(this);
94 }
95
96 void Scrollbar::removeFromParent()
97 {
98 if (parent())
99 toScrollView(parent())->removeChild(this);
100 }
101
102 ScrollView* Scrollbar::parentScrollView() const
103 {
104 return toScrollView(parent());
105 }
106
107 ScrollView* Scrollbar::rootScrollView() const
108 {
109 return toScrollView(root());
110 }
111
112 ScrollbarOverlayStyle Scrollbar::scrollbarOverlayStyle() const
113 {
114 return m_scrollableArea ? m_scrollableArea->scrollbarOverlayStyle() : Scroll barOverlayStyleDefault;
115 }
116
117 void Scrollbar::getTickmarks(Vector<IntRect>& tickmarks) const
118 {
119 if (m_scrollableArea)
120 m_scrollableArea->getTickmarks(tickmarks);
121 }
122
123 bool Scrollbar::isScrollableAreaActive() const
124 {
125 return m_scrollableArea && m_scrollableArea->isActive();
126 }
127
128 bool Scrollbar::isScrollViewScrollbar() const
129 {
130 return parent() && parent()->isFrameView() && toScrollView(parent())->isScro llViewScrollbar(this);
131 }
132
133 bool Scrollbar::isLeftSideVerticalScrollbar() const
134 {
135 if (m_orientation == VerticalScrollbar && m_scrollableArea)
136 return m_scrollableArea->shouldPlaceVerticalScrollbarOnLeft();
137 return false;
138 }
139
140 void Scrollbar::offsetDidChange()
141 {
142 ASSERT(m_scrollableArea);
143
144 float position = scrollableAreaCurrentPos();
145 if (position == m_currentPos)
146 return;
147
148 int oldThumbPosition = theme()->thumbPosition(this);
149 m_currentPos = position;
150 updateThumbPosition();
151 if (m_pressedPart == ThumbPart)
152 setPressedPos(m_pressedPos + theme()->thumbPosition(this) - oldThumbPosi tion);
153 }
154
155 void Scrollbar::setProportion(int visibleSize, int totalSize)
156 {
157 if (visibleSize == m_visibleSize && totalSize == m_totalSize)
158 return;
159
160 m_visibleSize = visibleSize;
161 m_totalSize = totalSize;
162
163 updateThumbProportion();
164 }
165
166 void Scrollbar::updateThumb()
167 {
168 #ifdef THUMB_POSITION_AFFECTS_BUTTONS
169 invalidate();
170 #else
171 theme()->invalidateParts(this, ForwardTrackPart | BackTrackPart | ThumbPart) ;
172 #endif
173 }
174
175 void Scrollbar::updateThumbPosition()
176 {
177 updateThumb();
178 }
179
180 void Scrollbar::updateThumbProportion()
181 {
182 updateThumb();
183 }
184
185 void Scrollbar::paint(GraphicsContext* context, const IntRect& damageRect)
186 {
187 if (context->updatingControlTints() && theme()->supportsControlTints()) {
188 invalidate();
189 return;
190 }
191
192 if (context->paintingDisabled() || !frameRect().intersects(damageRect))
193 return;
194
195 if (!theme()->paint(this, context, damageRect))
196 Widget::paint(context, damageRect);
197 }
198
199 void Scrollbar::autoscrollTimerFired(Timer<Scrollbar>*)
200 {
201 autoscrollPressedPart(theme()->autoscrollTimerDelay());
202 }
203
204 static bool thumbUnderMouse(Scrollbar* scrollbar)
205 {
206 int thumbPos = scrollbar->theme()->trackPosition(scrollbar) + scrollbar->the me()->thumbPosition(scrollbar);
207 int thumbLength = scrollbar->theme()->thumbLength(scrollbar);
208 return scrollbar->pressedPos() >= thumbPos && scrollbar->pressedPos() < thum bPos + thumbLength;
209 }
210
211 void Scrollbar::autoscrollPressedPart(double delay)
212 {
213 // Don't do anything for the thumb or if nothing was pressed.
214 if (m_pressedPart == ThumbPart || m_pressedPart == NoPart)
215 return;
216
217 // Handle the track.
218 if ((m_pressedPart == BackTrackPart || m_pressedPart == ForwardTrackPart) && thumbUnderMouse(this)) {
219 theme()->invalidatePart(this, m_pressedPart);
220 setHoveredPart(ThumbPart);
221 return;
222 }
223
224 // Handle the arrows and track.
225 if (m_scrollableArea && m_scrollableArea->scroll(pressedPartScrollDirection( ), pressedPartScrollGranularity()))
226 startTimerIfNeeded(delay);
227 }
228
229 void Scrollbar::startTimerIfNeeded(double delay)
230 {
231 // Don't do anything for the thumb.
232 if (m_pressedPart == ThumbPart)
233 return;
234
235 // Handle the track. We halt track scrolling once the thumb is level
236 // with us.
237 if ((m_pressedPart == BackTrackPart || m_pressedPart == ForwardTrackPart) && thumbUnderMouse(this)) {
238 theme()->invalidatePart(this, m_pressedPart);
239 setHoveredPart(ThumbPart);
240 return;
241 }
242
243 // We can't scroll if we've hit the beginning or end.
244 ScrollDirection dir = pressedPartScrollDirection();
245 if (dir == ScrollUp || dir == ScrollLeft) {
246 if (m_currentPos == 0)
247 return;
248 } else {
249 if (m_currentPos == maximum())
250 return;
251 }
252
253 m_scrollTimer.startOneShot(delay);
254 }
255
256 void Scrollbar::stopTimerIfNeeded()
257 {
258 if (m_scrollTimer.isActive())
259 m_scrollTimer.stop();
260 }
261
262 ScrollDirection Scrollbar::pressedPartScrollDirection()
263 {
264 if (m_orientation == HorizontalScrollbar) {
265 if (m_pressedPart == BackButtonStartPart || m_pressedPart == BackButtonE ndPart || m_pressedPart == BackTrackPart)
266 return ScrollLeft;
267 return ScrollRight;
268 } else {
269 if (m_pressedPart == BackButtonStartPart || m_pressedPart == BackButtonE ndPart || m_pressedPart == BackTrackPart)
270 return ScrollUp;
271 return ScrollDown;
272 }
273 }
274
275 ScrollGranularity Scrollbar::pressedPartScrollGranularity()
276 {
277 if (m_pressedPart == BackButtonStartPart || m_pressedPart == BackButtonEndPa rt || m_pressedPart == ForwardButtonStartPart || m_pressedPart == ForwardButton EndPart)
278 return ScrollByLine;
279 return ScrollByPage;
280 }
281
282 void Scrollbar::moveThumb(int pos, bool draggingDocument)
283 {
284 if (!m_scrollableArea)
285 return;
286
287 int delta = pos - m_pressedPos;
288
289 if (draggingDocument) {
290 if (m_draggingDocument)
291 delta = pos - m_documentDragPos;
292 m_draggingDocument = true;
293 FloatPoint currentPosition = m_scrollableArea->scrollAnimator()->current Position();
294 float destinationPosition = (m_orientation == HorizontalScrollbar ? curr entPosition.x() : currentPosition.y()) + delta;
295 destinationPosition = m_scrollableArea->clampScrollPosition(m_orientatio n, destinationPosition);
296 m_scrollableArea->scrollToOffsetWithoutAnimation(m_orientation, destinat ionPosition);
297 m_documentDragPos = pos;
298 return;
299 }
300
301 if (m_draggingDocument) {
302 delta += m_pressedPos - m_documentDragPos;
303 m_draggingDocument = false;
304 }
305
306 // Drag the thumb.
307 int thumbPos = theme()->thumbPosition(this);
308 int thumbLen = theme()->thumbLength(this);
309 int trackLen = theme()->trackLength(this);
310 if (delta > 0)
311 delta = min(trackLen - thumbLen - thumbPos, delta);
312 else if (delta < 0)
313 delta = max(-thumbPos, delta);
314
315 float minPos = m_scrollableArea->minimumScrollPosition(m_orientation);
316 float maxPos = m_scrollableArea->maximumScrollPosition(m_orientation);
317 if (delta) {
318 float newPosition = static_cast<float>(thumbPos + delta) * (maxPos - min Pos) / (trackLen - thumbLen) + minPos;
319 m_scrollableArea->scrollToOffsetWithoutAnimation(m_orientation, newPosit ion);
320 }
321 }
322
323 void Scrollbar::setHoveredPart(ScrollbarPart part)
324 {
325 if (part == m_hoveredPart)
326 return;
327
328 if ((m_hoveredPart == NoPart || part == NoPart) && theme()->invalidateOnMous eEnterExit())
329 invalidate(); // Just invalidate the whole scrollbar, since the buttons at either end change anyway.
330 else if (m_pressedPart == NoPart) { // When there's a pressed part, we don' t draw a hovered state, so there's no reason to invalidate.
331 theme()->invalidatePart(this, part);
332 theme()->invalidatePart(this, m_hoveredPart);
333 }
334 m_hoveredPart = part;
335 }
336
337 void Scrollbar::setPressedPart(ScrollbarPart part)
338 {
339 if (m_pressedPart != NoPart)
340 theme()->invalidatePart(this, m_pressedPart);
341 m_pressedPart = part;
342 if (m_pressedPart != NoPart)
343 theme()->invalidatePart(this, m_pressedPart);
344 else if (m_hoveredPart != NoPart) // When we no longer have a pressed part, we can start drawing a hovered state on the hovered part.
345 theme()->invalidatePart(this, m_hoveredPart);
346 }
347
348 bool Scrollbar::gestureEvent(const PlatformGestureEvent& evt)
349 {
350 bool handled = false;
351 switch (evt.type()) {
352 case PlatformEvent::GestureShowPress:
353 setPressedPart(theme()->hitTest(this, evt.position()));
354 m_pressedPos = orientation() == HorizontalScrollbar ? convertFromContain ingWindow(evt.position()).x() : convertFromContainingWindow(evt.position()).y();
355 return true;
356 case PlatformEvent::GestureTapDownCancel:
357 case PlatformEvent::GestureScrollBegin:
358 if (m_pressedPart == ThumbPart) {
359 m_scrollPos = m_pressedPos;
360 return true;
361 }
362 break;
363 case PlatformEvent::GestureScrollUpdate:
364 case PlatformEvent::GestureScrollUpdateWithoutPropagation:
365 if (m_pressedPart == ThumbPart) {
366 m_scrollPos += orientation() == HorizontalScrollbar ? evt.deltaX() : evt.deltaY();
367 moveThumb(m_scrollPos, false);
368 return true;
369 }
370 break;
371 case PlatformEvent::GestureScrollEnd:
372 m_scrollPos = 0;
373 break;
374 case PlatformEvent::GestureTap:
375 if (m_pressedPart != ThumbPart && m_pressedPart != NoPart)
376 handled = m_scrollableArea && m_scrollableArea->scroll(pressedPartSc rollDirection(), pressedPartScrollGranularity());
377 break;
378 default:
379 break;
380 }
381 setPressedPart(NoPart);
382 m_pressedPos = 0;
383 return handled;
384 }
385
386 void Scrollbar::mouseMoved(const PlatformMouseEvent& evt)
387 {
388 if (m_pressedPart == ThumbPart) {
389 if (theme()->shouldSnapBackToDragOrigin(this, evt)) {
390 if (m_scrollableArea)
391 m_scrollableArea->scrollToOffsetWithoutAnimation(m_orientation, m_dragOrigin);
392 } else {
393 moveThumb(m_orientation == HorizontalScrollbar ?
394 convertFromContainingWindow(evt.position()).x() :
395 convertFromContainingWindow(evt.position()).y(), theme()-> shouldDragDocumentInsteadOfThumb(this, evt));
396 }
397 return;
398 }
399
400 if (m_pressedPart != NoPart)
401 m_pressedPos = orientation() == HorizontalScrollbar ? convertFromContain ingWindow(evt.position()).x() : convertFromContainingWindow(evt.position()).y();
402
403 ScrollbarPart part = theme()->hitTest(this, evt.position());
404 if (part != m_hoveredPart) {
405 if (m_pressedPart != NoPart) {
406 if (part == m_pressedPart) {
407 // The mouse is moving back over the pressed part. We
408 // need to start up the timer action again.
409 startTimerIfNeeded(theme()->autoscrollTimerDelay());
410 theme()->invalidatePart(this, m_pressedPart);
411 } else if (m_hoveredPart == m_pressedPart) {
412 // The mouse is leaving the pressed part. Kill our timer
413 // if needed.
414 stopTimerIfNeeded();
415 theme()->invalidatePart(this, m_pressedPart);
416 }
417 }
418
419 setHoveredPart(part);
420 }
421
422 return;
423 }
424
425 void Scrollbar::mouseEntered()
426 {
427 if (m_scrollableArea)
428 m_scrollableArea->mouseEnteredScrollbar(this);
429 }
430
431 void Scrollbar::mouseExited()
432 {
433 if (m_scrollableArea)
434 m_scrollableArea->mouseExitedScrollbar(this);
435 setHoveredPart(NoPart);
436 }
437
438 void Scrollbar::mouseUp(const PlatformMouseEvent& mouseEvent)
439 {
440 setPressedPart(NoPart);
441 m_pressedPos = 0;
442 m_draggingDocument = false;
443 stopTimerIfNeeded();
444
445 if (m_scrollableArea) {
446 // m_hoveredPart won't be updated until the next mouseMoved or mouseDown , so we have to hit test
447 // to really know if the mouse has exited the scrollbar on a mouseUp.
448 ScrollbarPart part = theme()->hitTest(this, mouseEvent.position());
449 if (part == NoPart)
450 m_scrollableArea->mouseExitedScrollbar(this);
451 }
452 }
453
454 void Scrollbar::mouseDown(const PlatformMouseEvent& evt)
455 {
456 // Early exit for right click
457 if (evt.button() == RightButton)
458 return;
459
460 setPressedPart(theme()->hitTest(this, evt.position()));
461 int pressedPos = orientation() == HorizontalScrollbar ? convertFromContainin gWindow(evt.position()).x() : convertFromContainingWindow(evt.position()).y();
462
463 if ((m_pressedPart == BackTrackPart || m_pressedPart == ForwardTrackPart) && theme()->shouldCenterOnThumb(this, evt)) {
464 setHoveredPart(ThumbPart);
465 setPressedPart(ThumbPart);
466 m_dragOrigin = m_currentPos;
467 int thumbLen = theme()->thumbLength(this);
468 int desiredPos = pressedPos;
469 // Set the pressed position to the middle of the thumb so that when we d o the move, the delta
470 // will be from the current pixel position of the thumb to the new desir ed position for the thumb.
471 m_pressedPos = theme()->trackPosition(this) + theme()->thumbPosition(thi s) + thumbLen / 2;
472 moveThumb(desiredPos);
473 return;
474 } else if (m_pressedPart == ThumbPart)
475 m_dragOrigin = m_currentPos;
476
477 m_pressedPos = pressedPos;
478
479 autoscrollPressedPart(theme()->initialAutoscrollTimerDelay());
480 }
481
482 void Scrollbar::setFrameRect(const IntRect& rect)
483 {
484 // Get our window resizer rect and see if we overlap. Adjust to avoid the ov erlap
485 // if necessary.
486 IntRect adjustedRect(rect);
487 bool overlapsResizer = false;
488 ScrollView* view = parentScrollView();
489 if (view && !rect.isEmpty() && !view->windowResizerRect().isEmpty()) {
490 IntRect resizerRect = view->convertFromContainingWindow(view->windowResi zerRect());
491 if (rect.intersects(resizerRect)) {
492 if (orientation() == HorizontalScrollbar) {
493 int overlap = rect.maxX() - resizerRect.x();
494 if (overlap > 0 && resizerRect.maxX() >= rect.maxX()) {
495 adjustedRect.setWidth(rect.width() - overlap);
496 overlapsResizer = true;
497 }
498 } else {
499 int overlap = rect.maxY() - resizerRect.y();
500 if (overlap > 0 && resizerRect.maxY() >= rect.maxY()) {
501 adjustedRect.setHeight(rect.height() - overlap);
502 overlapsResizer = true;
503 }
504 }
505 }
506 }
507 if (overlapsResizer != m_overlapsResizer) {
508 m_overlapsResizer = overlapsResizer;
509 if (view)
510 view->adjustScrollbarsAvoidingResizerCount(m_overlapsResizer ? 1 : - 1);
511 }
512
513 Widget::setFrameRect(adjustedRect);
514 }
515
516 void Scrollbar::setParent(Widget* parentView)
517 {
518 if (!parentView && m_overlapsResizer && parentScrollView())
519 parentScrollView()->adjustScrollbarsAvoidingResizerCount(-1);
520 Widget::setParent(parentView);
521 }
522
523 void Scrollbar::setEnabled(bool e)
524 {
525 if (m_enabled == e)
526 return;
527 m_enabled = e;
528 theme()->updateEnabledState(this);
529 invalidate();
530 }
531
532 bool Scrollbar::isOverlayScrollbar() const
533 {
534 return m_theme->usesOverlayScrollbars();
535 }
536
537 bool Scrollbar::shouldParticipateInHitTesting()
538 {
539 // Non-overlay scrollbars should always participate in hit testing.
540 if (!isOverlayScrollbar())
541 return true;
542 return m_scrollableArea->scrollAnimator()->shouldScrollbarParticipateInHitTe sting(this);
543 }
544
545 bool Scrollbar::isWindowActive() const
546 {
547 return m_scrollableArea && m_scrollableArea->isActive();
548 }
549
550 void Scrollbar::invalidateRect(const IntRect& rect)
551 {
552 if (suppressInvalidation())
553 return;
554
555 if (m_scrollableArea)
556 m_scrollableArea->invalidateScrollbar(this, rect);
557 }
558
559 IntRect Scrollbar::convertToContainingView(const IntRect& localRect) const
560 {
561 if (m_scrollableArea)
562 return m_scrollableArea->convertFromScrollbarToContainingView(this, loca lRect);
563
564 return Widget::convertToContainingView(localRect);
565 }
566
567 IntRect Scrollbar::convertFromContainingView(const IntRect& parentRect) const
568 {
569 if (m_scrollableArea)
570 return m_scrollableArea->convertFromContainingViewToScrollbar(this, pare ntRect);
571
572 return Widget::convertFromContainingView(parentRect);
573 }
574
575 IntPoint Scrollbar::convertToContainingView(const IntPoint& localPoint) const
576 {
577 if (m_scrollableArea)
578 return m_scrollableArea->convertFromScrollbarToContainingView(this, loca lPoint);
579
580 return Widget::convertToContainingView(localPoint);
581 }
582
583 IntPoint Scrollbar::convertFromContainingView(const IntPoint& parentPoint) const
584 {
585 if (m_scrollableArea)
586 return m_scrollableArea->convertFromContainingViewToScrollbar(this, pare ntPoint);
587
588 return Widget::convertFromContainingView(parentPoint);
589 }
590
591 float Scrollbar::scrollableAreaCurrentPos() const
592 {
593 if (!m_scrollableArea)
594 return 0;
595
596 if (m_orientation == HorizontalScrollbar)
597 return m_scrollableArea->scrollPosition().x() - m_scrollableArea->minimu mScrollPosition().x();
598
599 return m_scrollableArea->scrollPosition().y() - m_scrollableArea->minimumScr ollPosition().y();
600 }
601
602 } // namespace WebCore
OLDNEW
« no previous file with comments | « Source/core/platform/Scrollbar.h ('k') | Source/core/platform/ScrollbarTheme.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698