OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2011 Apple Inc. All Rights Reserved. | 2 * Copyright (C) 2011 Apple Inc. All Rights Reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
11 * documentation and/or other materials provided with the distribution. | 11 * documentation and/or other materials provided with the distribution. |
12 * | 12 * |
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY | 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR | 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
24 */ | 24 */ |
25 | 25 |
26 #include "config.h" | 26 #include "config.h" |
27 #include "platform/scroll/ScrollbarTheme.h" | 27 #include "platform/scroll/ScrollbarTheme.h" |
28 | 28 |
29 #include "RuntimeEnabledFeatures.h" | 29 #include "RuntimeEnabledFeatures.h" |
| 30 #include "platform/PlatformMouseEvent.h" |
30 #include "platform/scroll/ScrollbarThemeClient.h" | 31 #include "platform/scroll/ScrollbarThemeClient.h" |
31 #include "platform/scroll/ScrollbarThemeMock.h" | 32 #include "platform/scroll/ScrollbarThemeMock.h" |
32 #include "platform/scroll/ScrollbarThemeOverlayMock.h" | 33 #include "platform/scroll/ScrollbarThemeOverlayMock.h" |
| 34 #include "public/platform/Platform.h" |
| 35 #include "public/platform/WebPoint.h" |
| 36 #include "public/platform/WebScrollbarBehavior.h" |
33 | 37 |
34 #if !OS(MACOSX) | 38 #if !OS(MACOSX) |
35 #include "public/platform/Platform.h" | |
36 #include "public/platform/WebRect.h" | 39 #include "public/platform/WebRect.h" |
37 #include "public/platform/WebThemeEngine.h" | 40 #include "public/platform/WebThemeEngine.h" |
38 #endif | 41 #endif |
39 | 42 |
40 namespace WebCore { | 43 namespace WebCore { |
41 | 44 |
42 ScrollbarTheme* ScrollbarTheme::theme() | |
43 { | |
44 if (ScrollbarTheme::mockScrollbarsEnabled()) { | |
45 if (RuntimeEnabledFeatures::overlayScrollbarsEnabled()) { | |
46 DEFINE_STATIC_LOCAL(ScrollbarThemeOverlayMock, overlayMockTheme, ())
; | |
47 return &overlayMockTheme; | |
48 } | |
49 | |
50 DEFINE_STATIC_LOCAL(ScrollbarThemeMock, mockTheme, ()); | |
51 return &mockTheme; | |
52 } | |
53 return nativeTheme(); | |
54 } | |
55 | |
56 bool ScrollbarTheme::gMockScrollbarsEnabled = false; | 45 bool ScrollbarTheme::gMockScrollbarsEnabled = false; |
57 | 46 |
58 void ScrollbarTheme::setMockScrollbarsEnabled(bool flag) | |
59 { | |
60 gMockScrollbarsEnabled = flag; | |
61 } | |
62 | |
63 bool ScrollbarTheme::mockScrollbarsEnabled() | |
64 { | |
65 return gMockScrollbarsEnabled; | |
66 } | |
67 | |
68 bool ScrollbarTheme::paint(ScrollbarThemeClient* scrollbar, GraphicsContext* gra
phicsContext, const IntRect& damageRect) | 47 bool ScrollbarTheme::paint(ScrollbarThemeClient* scrollbar, GraphicsContext* gra
phicsContext, const IntRect& damageRect) |
69 { | 48 { |
70 // Create the ScrollbarControlPartMask based on the damageRect | 49 // Create the ScrollbarControlPartMask based on the damageRect |
71 ScrollbarControlPartMask scrollMask = NoPart; | 50 ScrollbarControlPartMask scrollMask = NoPart; |
72 | 51 |
73 IntRect backButtonStartPaintRect; | 52 IntRect backButtonStartPaintRect; |
74 IntRect backButtonEndPaintRect; | 53 IntRect backButtonEndPaintRect; |
75 IntRect forwardButtonStartPaintRect; | 54 IntRect forwardButtonStartPaintRect; |
76 IntRect forwardButtonEndPaintRect; | 55 IntRect forwardButtonEndPaintRect; |
77 if (hasButtons(scrollbar)) { | 56 if (hasButtons(scrollbar)) { |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
213 else if (part == ForwardTrackPart) | 192 else if (part == ForwardTrackPart) |
214 result = afterThumbRect; | 193 result = afterThumbRect; |
215 else | 194 else |
216 result = thumbRect; | 195 result = thumbRect; |
217 } | 196 } |
218 } | 197 } |
219 result.moveBy(-scrollbar->location()); | 198 result.moveBy(-scrollbar->location()); |
220 scrollbar->invalidateRect(result); | 199 scrollbar->invalidateRect(result); |
221 } | 200 } |
222 | 201 |
223 void ScrollbarTheme::splitTrack(ScrollbarThemeClient* scrollbar, const IntRect&
unconstrainedTrackRect, IntRect& beforeThumbRect, IntRect& thumbRect, IntRect& a
fterThumbRect) | 202 void ScrollbarTheme::paintScrollCorner(GraphicsContext* context, const IntRect&
cornerRect) |
224 { | 203 { |
225 // This function won't even get called unless we're big enough to have some
combination of these three rects where at least | 204 if (cornerRect.isEmpty()) |
226 // one of them is non-empty. | 205 return; |
227 IntRect trackRect = constrainTrackRectToTrackPieces(scrollbar, unconstrained
TrackRect); | 206 |
228 int thumbPos = thumbPosition(scrollbar); | 207 #if OS(MACOSX) |
229 if (scrollbar->orientation() == HorizontalScrollbar) { | 208 context->fillRect(cornerRect, Color::white); |
230 thumbRect = IntRect(trackRect.x() + thumbPos, trackRect.y(), thumbLength
(scrollbar), scrollbar->height()); | 209 #else |
231 beforeThumbRect = IntRect(trackRect.x(), trackRect.y(), thumbPos + thumb
Rect.width() / 2, trackRect.height()); | 210 blink::Platform::current()->themeEngine()->paint(context->canvas(), blink::W
ebThemeEngine::PartScrollbarCorner, blink::WebThemeEngine::StateNormal, blink::W
ebRect(cornerRect), 0); |
232 afterThumbRect = IntRect(trackRect.x() + beforeThumbRect.width(), trackR
ect.y(), trackRect.maxX() - beforeThumbRect.maxX(), trackRect.height()); | 211 #endif |
233 } else { | 212 } |
234 thumbRect = IntRect(trackRect.x(), trackRect.y() + thumbPos, scrollbar->
width(), thumbLength(scrollbar)); | 213 |
235 beforeThumbRect = IntRect(trackRect.x(), trackRect.y(), trackRect.width(
), thumbPos + thumbRect.height() / 2); | 214 void ScrollbarTheme::paintOverhangBackground(GraphicsContext* context, const Int
Rect& horizontalOverhangRect, const IntRect& verticalOverhangRect, const IntRect
& dirtyRect) |
236 afterThumbRect = IntRect(trackRect.x(), trackRect.y() + beforeThumbRect.
height(), trackRect.width(), trackRect.maxY() - beforeThumbRect.maxY()); | 215 { |
237 } | 216 context->setFillColor(Color::white); |
| 217 if (!horizontalOverhangRect.isEmpty()) |
| 218 context->fillRect(intersection(horizontalOverhangRect, dirtyRect)); |
| 219 if (!verticalOverhangRect.isEmpty()) |
| 220 context->fillRect(intersection(verticalOverhangRect, dirtyRect)); |
| 221 } |
| 222 |
| 223 bool ScrollbarTheme::shouldCenterOnThumb(ScrollbarThemeClient* scrollbar, const
PlatformMouseEvent& evt) |
| 224 { |
| 225 return blink::Platform::current()->scrollbarBehavior()->shouldCenterOnThumb(
static_cast<blink::WebScrollbarBehavior::Button>(evt.button()), evt.shiftKey(),
evt.altKey()); |
| 226 } |
| 227 |
| 228 bool ScrollbarTheme::shouldSnapBackToDragOrigin(ScrollbarThemeClient* scrollbar,
const PlatformMouseEvent& evt) |
| 229 { |
| 230 IntPoint mousePosition = scrollbar->convertFromContainingWindow(evt.position
()); |
| 231 mousePosition.move(scrollbar->x(), scrollbar->y()); |
| 232 return blink::Platform::current()->scrollbarBehavior()->shouldSnapBackToDrag
Origin(mousePosition, trackRect(scrollbar), scrollbar->orientation() == Horizont
alScrollbar); |
238 } | 233 } |
239 | 234 |
240 // Returns the size represented by track taking into account scrolling past | 235 // Returns the size represented by track taking into account scrolling past |
241 // the end of the document. | 236 // the end of the document. |
242 static float usedTotalSize(ScrollbarThemeClient* scrollbar) | 237 static float usedTotalSize(ScrollbarThemeClient* scrollbar) |
243 { | 238 { |
244 float overhangAtStart = -scrollbar->currentPos(); | 239 float overhangAtStart = -scrollbar->currentPos(); |
245 float overhangAtEnd = scrollbar->currentPos() + scrollbar->visibleSize() - s
crollbar->totalSize(); | 240 float overhangAtEnd = scrollbar->currentPos() + scrollbar->visibleSize() - s
crollbar->totalSize(); |
246 float overhang = std::max(0.0f, std::max(overhangAtStart, overhangAtEnd)); | 241 float overhang = std::max(0.0f, std::max(overhangAtStart, overhangAtEnd)); |
247 return scrollbar->totalSize() + overhang; | 242 return scrollbar->totalSize() + overhang; |
(...skipping 24 matching lines...) Expand all Loading... |
272 overhang = scrollbar->currentPos() + scrollbar->visibleSize() - scrollba
r->totalSize(); | 267 overhang = scrollbar->currentPos() + scrollbar->visibleSize() - scrollba
r->totalSize(); |
273 float proportion = (scrollbar->visibleSize() - overhang) / usedTotalSize(scr
ollbar); | 268 float proportion = (scrollbar->visibleSize() - overhang) / usedTotalSize(scr
ollbar); |
274 int trackLen = trackLength(scrollbar); | 269 int trackLen = trackLength(scrollbar); |
275 int length = round(proportion * trackLen); | 270 int length = round(proportion * trackLen); |
276 length = std::max(length, minimumThumbLength(scrollbar)); | 271 length = std::max(length, minimumThumbLength(scrollbar)); |
277 if (length > trackLen) | 272 if (length > trackLen) |
278 length = 0; // Once the thumb is below the track length, it just goes aw
ay (to make more room for the track). | 273 length = 0; // Once the thumb is below the track length, it just goes aw
ay (to make more room for the track). |
279 return length; | 274 return length; |
280 } | 275 } |
281 | 276 |
282 int ScrollbarTheme::minimumThumbLength(ScrollbarThemeClient* scrollbar) | |
283 { | |
284 return scrollbarThickness(scrollbar->controlSize()); | |
285 } | |
286 | |
287 int ScrollbarTheme::trackPosition(ScrollbarThemeClient* scrollbar) | 277 int ScrollbarTheme::trackPosition(ScrollbarThemeClient* scrollbar) |
288 { | 278 { |
289 IntRect constrainedTrackRect = constrainTrackRectToTrackPieces(scrollbar, tr
ackRect(scrollbar)); | 279 IntRect constrainedTrackRect = constrainTrackRectToTrackPieces(scrollbar, tr
ackRect(scrollbar)); |
290 return (scrollbar->orientation() == HorizontalScrollbar) ? constrainedTrackR
ect.x() - scrollbar->x() : constrainedTrackRect.y() - scrollbar->y(); | 280 return (scrollbar->orientation() == HorizontalScrollbar) ? constrainedTrackR
ect.x() - scrollbar->x() : constrainedTrackRect.y() - scrollbar->y(); |
291 } | 281 } |
292 | 282 |
293 int ScrollbarTheme::trackLength(ScrollbarThemeClient* scrollbar) | 283 int ScrollbarTheme::trackLength(ScrollbarThemeClient* scrollbar) |
294 { | 284 { |
295 IntRect constrainedTrackRect = constrainTrackRectToTrackPieces(scrollbar, tr
ackRect(scrollbar)); | 285 IntRect constrainedTrackRect = constrainTrackRectToTrackPieces(scrollbar, tr
ackRect(scrollbar)); |
296 return (scrollbar->orientation() == HorizontalScrollbar) ? constrainedTrackR
ect.width() : constrainedTrackRect.height(); | 286 return (scrollbar->orientation() == HorizontalScrollbar) ? constrainedTrackR
ect.width() : constrainedTrackRect.height(); |
297 } | 287 } |
298 | 288 |
299 void ScrollbarTheme::paintScrollCorner(GraphicsContext* context, const IntRect&
cornerRect) | |
300 { | |
301 if (cornerRect.isEmpty()) | |
302 return; | |
303 | |
304 #if OS(MACOSX) | |
305 context->fillRect(cornerRect, Color::white); | |
306 #else | |
307 blink::Platform::current()->themeEngine()->paint(context->canvas(), blink::W
ebThemeEngine::PartScrollbarCorner, blink::WebThemeEngine::StateNormal, blink::W
ebRect(cornerRect), 0); | |
308 #endif | |
309 } | |
310 | |
311 IntRect ScrollbarTheme::thumbRect(ScrollbarThemeClient* scrollbar) | 289 IntRect ScrollbarTheme::thumbRect(ScrollbarThemeClient* scrollbar) |
312 { | 290 { |
313 if (!hasThumb(scrollbar)) | 291 if (!hasThumb(scrollbar)) |
314 return IntRect(); | 292 return IntRect(); |
315 | 293 |
316 IntRect track = trackRect(scrollbar); | 294 IntRect track = trackRect(scrollbar); |
317 IntRect startTrackRect; | 295 IntRect startTrackRect; |
318 IntRect thumbRect; | 296 IntRect thumbRect; |
319 IntRect endTrackRect; | 297 IntRect endTrackRect; |
320 splitTrack(scrollbar, track, startTrackRect, thumbRect, endTrackRect); | 298 splitTrack(scrollbar, track, startTrackRect, thumbRect, endTrackRect); |
321 | 299 |
322 return thumbRect; | 300 return thumbRect; |
323 } | 301 } |
324 | 302 |
325 int ScrollbarTheme::thumbThickness(ScrollbarThemeClient* scrollbar) | 303 int ScrollbarTheme::thumbThickness(ScrollbarThemeClient* scrollbar) |
326 { | 304 { |
327 IntRect track = trackRect(scrollbar); | 305 IntRect track = trackRect(scrollbar); |
328 return scrollbar->orientation() == HorizontalScrollbar ? track.height() : tr
ack.width(); | 306 return scrollbar->orientation() == HorizontalScrollbar ? track.height() : tr
ack.width(); |
329 } | 307 } |
330 | 308 |
331 void ScrollbarTheme::paintOverhangBackground(GraphicsContext* context, const Int
Rect& horizontalOverhangRect, const IntRect& verticalOverhangRect, const IntRect
& dirtyRect) | 309 int ScrollbarTheme::minimumThumbLength(ScrollbarThemeClient* scrollbar) |
332 { | 310 { |
333 context->setFillColor(Color::white); | 311 return scrollbarThickness(scrollbar->controlSize()); |
334 if (!horizontalOverhangRect.isEmpty()) | 312 } |
335 context->fillRect(intersection(horizontalOverhangRect, dirtyRect)); | 313 |
336 if (!verticalOverhangRect.isEmpty()) | 314 void ScrollbarTheme::splitTrack(ScrollbarThemeClient* scrollbar, const IntRect&
unconstrainedTrackRect, IntRect& beforeThumbRect, IntRect& thumbRect, IntRect& a
fterThumbRect) |
337 context->fillRect(intersection(verticalOverhangRect, dirtyRect)); | 315 { |
| 316 // This function won't even get called unless we're big enough to have some
combination of these three rects where at least |
| 317 // one of them is non-empty. |
| 318 IntRect trackRect = constrainTrackRectToTrackPieces(scrollbar, unconstrained
TrackRect); |
| 319 int thumbPos = thumbPosition(scrollbar); |
| 320 if (scrollbar->orientation() == HorizontalScrollbar) { |
| 321 thumbRect = IntRect(trackRect.x() + thumbPos, trackRect.y(), thumbLength
(scrollbar), scrollbar->height()); |
| 322 beforeThumbRect = IntRect(trackRect.x(), trackRect.y(), thumbPos + thumb
Rect.width() / 2, trackRect.height()); |
| 323 afterThumbRect = IntRect(trackRect.x() + beforeThumbRect.width(), trackR
ect.y(), trackRect.maxX() - beforeThumbRect.maxX(), trackRect.height()); |
| 324 } else { |
| 325 thumbRect = IntRect(trackRect.x(), trackRect.y() + thumbPos, scrollbar->
width(), thumbLength(scrollbar)); |
| 326 beforeThumbRect = IntRect(trackRect.x(), trackRect.y(), trackRect.width(
), thumbPos + thumbRect.height() / 2); |
| 327 afterThumbRect = IntRect(trackRect.x(), trackRect.y() + beforeThumbRect.
height(), trackRect.width(), trackRect.maxY() - beforeThumbRect.maxY()); |
| 328 } |
| 329 } |
| 330 |
| 331 ScrollbarTheme* ScrollbarTheme::theme() |
| 332 { |
| 333 if (ScrollbarTheme::mockScrollbarsEnabled()) { |
| 334 if (RuntimeEnabledFeatures::overlayScrollbarsEnabled()) { |
| 335 DEFINE_STATIC_LOCAL(ScrollbarThemeOverlayMock, overlayMockTheme, ())
; |
| 336 return &overlayMockTheme; |
| 337 } |
| 338 |
| 339 DEFINE_STATIC_LOCAL(ScrollbarThemeMock, mockTheme, ()); |
| 340 return &mockTheme; |
| 341 } |
| 342 return nativeTheme(); |
| 343 } |
| 344 |
| 345 void ScrollbarTheme::setMockScrollbarsEnabled(bool flag) |
| 346 { |
| 347 gMockScrollbarsEnabled = flag; |
| 348 } |
| 349 |
| 350 bool ScrollbarTheme::mockScrollbarsEnabled() |
| 351 { |
| 352 return gMockScrollbarsEnabled; |
338 } | 353 } |
339 | 354 |
340 } | 355 } |
OLD | NEW |