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

Side by Side Diff: webkit/port/platform/PlatformScrollBarWin.cpp

Issue 7419: Move many files that were suffixed Win.cpp to Chromium.cpp, and place them in... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 12 years, 2 months 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 | « webkit/port/platform/PlatformScrollBar.h ('k') | webkit/port/platform/PopupMenuWin.cpp » ('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 // Copyright (c) 2008, Google Inc.
2 // 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 #include "config.h"
31 #include <algorithm>
32 #include <windows.h>
33 #include <vsstyle.h>
34 #include "FrameView.h"
35 #include "GraphicsContext.h"
36 #include "IntRect.h"
37 #include "NativeImageSkia.h"
38 #include "PlatformMouseEvent.h"
39 #include "PlatformScrollBar.h"
40 #include "Range.h"
41 #include "ScrollView.h"
42 #include "WidgetClientWin.h"
43
44 #include "graphics/SkiaUtils.h"
45
46 #undef LOG
47 #include "base/gfx/native_theme.h"
48 #include "base/gfx/platform_canvas_win.h"
49 #include "base/win_util.h"
50 #include "webkit/glue/webframe_impl.h"
51 #include "webkit/glue/webkit_glue.h"
52
53 namespace WebCore {
54
55 const int PlatformScrollbar::kOffSideMultiplier = 8;
56 const int PlatformScrollbar::kOffEndMultiplier = 3;
57 const double PlatformScrollbar::kAutorepeatInitialDelay = 0.4;
58 const double PlatformScrollbar::kAutorepeatRepeatInterval = 1. / 15.;
59
60 // The scrollbar size in DumpRenderTree on the Mac - so we can match their
61 // layout results. Entries are for regular, small, and mini scrollbars.
62 // Metrics obtained using [NSScroller scrollerWidthForControlSize:]
63 static const int kMacScrollbarSize[3] = {15, 11, 15};
64
65 // Scrollbar button and thumb sizes, for consistent layout results. The Mac
66 // value is not readily available, but it's not really needed, since these
67 // metrics only affect drawing within the scrollbar itself. These are the
68 // standard Windows values without Large Fonts.
69 static const int kLayoutTestScrollbarButtonGirth = 17;
70 static const int kLayoutTestScrollbarThumbGirth = 17;
71
72
73 /*static*/ void PlatformScrollbar::themeChanged()
74 {
75 // TODO(darin): implement this
76 }
77
78 /*static*/ int PlatformScrollbar::horizontalScrollbarHeight(
79 ScrollbarControlSize controlSize)
80 {
81 return webkit_glue::IsLayoutTestMode() ? kMacScrollbarSize[controlSize] :
82 GetSystemMetrics(SM_CYHSCROLL);
83 }
84
85 /*static*/ int PlatformScrollbar::verticalScrollbarWidth(
86 ScrollbarControlSize controlSize)
87 {
88 return webkit_glue::IsLayoutTestMode() ? kMacScrollbarSize[controlSize] :
89 GetSystemMetrics(SM_CXVSCROLL);
90 }
91
92 PlatformScrollbar::PlatformScrollbar(ScrollbarClient* client,
93 ScrollbarOrientation orientation,
94 ScrollbarControlSize controlSize)
95 : Scrollbar(client, orientation, controlSize)
96 , m_lastNativePos(-1, -1) // initialize to bogus values
97 , m_mouseOver(None)
98 , m_captureStart(None)
99 #pragma warning(suppress: 4355) // it's okay to pass |this| here!
100 , m_autorepeatTimer(this, &PlatformScrollbar::autoscrollTimerFired)
101 , m_enabled(true)
102 , m_needsLayout(true)
103 {
104 }
105
106 PlatformScrollbar::~PlatformScrollbar()
107 {
108 }
109
110 int PlatformScrollbar::width() const
111 {
112 return orientation() == VerticalScrollbar ?
113 verticalScrollbarWidth(controlSize()) : Widget::width();
114 }
115
116 int PlatformScrollbar::height() const
117 {
118 return orientation() == HorizontalScrollbar ?
119 horizontalScrollbarHeight(controlSize()) : Widget::height();
120 }
121
122 void PlatformScrollbar::setRect(const IntRect& rect)
123 {
124 setFrameGeometry(rect);
125 }
126
127 void PlatformScrollbar::setEnabled(bool enabled)
128 {
129 if (m_enabled == enabled)
130 return;
131
132 m_enabled = enabled;
133 invalidate();
134 }
135
136 void PlatformScrollbar::DrawTickmarks(GraphicsContext* context) const
137 {
138 // We don't draw on the horizontal scrollbar. It is too confusing
139 // to have the tickmarks appear on both scrollbars.
140 const bool horz = orientation() == HorizontalScrollbar;
141 if (horz)
142 return;
143
144 // We need to as the WidgetClientWin for the bitmap to use to draw.
145 WidgetClientWin* widget_client = static_cast<WidgetClientWin*>(
146 WebCore::Widget::client());
147 if (!widget_client)
148 return; // Cannot draw without access to the bitmap.
149
150 // Get the frame view this scroll bar belongs to.
151 FrameView* view = reinterpret_cast<FrameView*>(parent());
152 ASSERT(view);
153
154 // A frame can be null if this function is called for the scroll views
155 // used when drawing drop-down boxes. We don't need to draw anything in
156 // such cases.
157 if (!view->frame())
158 return;
159
160 // Find out if the frame has any tickmarks.
161 const Vector<RefPtr<Range> >& tickmarks =
162 WebFrameImpl::FromFrame(view->frame())->tickmarks();
163 if (tickmarks.isEmpty())
164 return;
165
166 RECT track_area;
167 if (m_segmentRects[Track].left != -1) {
168 // Scroll bar is too small to draw a thumb.
169 track_area.left = m_segmentRects[Track].left;
170 track_area.top = m_segmentRects[Track].top;
171 track_area.right = m_segmentRects[Track].right - 1;
172 track_area.bottom = m_segmentRects[Track].bottom - 1;
173 } else {
174 // Find the area between the arrows of the scroll bar.
175 track_area.left = m_segmentRects[BeforeThumb].left;
176 track_area.top = m_segmentRects[BeforeThumb].top;
177 track_area.right = m_segmentRects[AfterThumb].right - 1;
178 track_area.bottom = m_segmentRects[AfterThumb].bottom - 1;
179 }
180
181 // We now can figure out the actual height and width of the track.
182 const int track_height = track_area.bottom - track_area.top;
183 const int track_width = track_area.right - track_area.left;
184
185 if (track_height <= 0 || track_width <= 0)
186 return; // nothing to draw on.
187
188 // NOTE: We tolerate the platformContext() call here because the scrollbars
189 // will not be serialized, i.e. composition is done in the renderer and
190 // never in the browser.
191 // Prepare the bitmap for drawing the tickmarks on the scroll bar.
192 gfx::PlatformCanvas* canvas = context->platformContext()->canvas();
193
194 // Load the image for the tickmark.
195 static RefPtr<Image> dashImg = Image::loadPlatformResource("tickmarkDash");
196 DCHECK(dashImg);
197 if (dashImg->isNull()) {
198 ASSERT_NOT_REACHED();
199 return;
200 }
201 const NativeImageSkia* dash = dashImg->nativeImageForCurrentFrame();
202
203 for (Vector<RefPtr<Range> >::const_iterator i =
204 tickmarks.begin();
205 i != tickmarks.end(); ++i) {
206 const RefPtr<Range> range = (*i);
207
208 if (!WebFrameImpl::RangeShouldBeHighlighted(range.get()))
209 continue;
210
211 const IntRect& bounds = range->boundingBox();
212
213 // Calculate how far down (in %) the tick-mark should appear.
214 const float percent = static_cast<float>(bounds.y()) / m_totalSize;
215
216 // Calculate how far down (in pixels) the tick-mark should appear.
217 const int y_pos = track_area.top + (track_height * percent);
218
219 // Draw the tick-mark as a rounded rect with a slightly curved edge.
220 canvas->drawBitmap(*dash, track_area.left, y_pos);
221 }
222 }
223
224 // paint in the coordinate space of our parent's content area
225 void PlatformScrollbar::paint(GraphicsContext* gc, const IntRect& damageRect)
226 {
227 if (gc->paintingDisabled())
228 return;
229
230 // Don't paint anything if the scrollbar doesn't intersect the damage rect.
231 if (!frameGeometry().intersects(damageRect))
232 return;
233
234 gc->save();
235 gc->translate(x(), y());
236
237 layout();
238
239 HDC hdc = gc->getWindowsContext(damageRect);
240 const bool horz = orientation() == HorizontalScrollbar;
241 const PlatformContextSkia* const skia = gc->platformContext();
242 const gfx::NativeTheme* const nativeTheme = skia->nativeTheme();
243 gfx::PlatformCanvasWin* const canvas = skia->canvas();
244
245 // Draw the up/left arrow of the scroll bar.
246 nativeTheme->PaintScrollbarArrow(hdc, getThemeArrowState(Arrow1),
247 (horz ? DFCS_SCROLLLEFT : DFCS_SCROLLUP) |
248 getClassicThemeState(Arrow1),
249 &m_segmentRects[Arrow1]);
250
251 if (m_segmentRects[Track].left != -1) {
252 // The scroll bar is too small to draw the thumb. Just draw a
253 // single track between the arrows.
254 nativeTheme->PaintScrollbarTrack(hdc,
255 horz ? SBP_UPPERTRACKHORZ :
256 SBP_UPPERTRACKVERT,
257 getThemeState(Track),
258 getClassicThemeState(Track),
259 &m_segmentRects[Track],
260 &m_segmentRects[Track], canvas);
261 DrawTickmarks(gc);
262 } else {
263 // Draw the track area before the thumb on the scroll bar.
264 nativeTheme->PaintScrollbarTrack(hdc,
265 horz ? SBP_UPPERTRACKHORZ :
266 SBP_UPPERTRACKVERT,
267 getThemeState(BeforeThumb),
268 getClassicThemeState(BeforeThumb),
269 &m_segmentRects[BeforeThumb],
270 &m_segmentRects[BeforeThumb], canvas);
271
272 // Draw the track area after the thumb on the scroll bar.
273 nativeTheme->PaintScrollbarTrack(hdc,
274 horz ? SBP_LOWERTRACKHORZ :
275 SBP_LOWERTRACKVERT,
276 getThemeState(AfterThumb),
277 getClassicThemeState(AfterThumb),
278 &m_segmentRects[AfterThumb],
279 &m_segmentRects[BeforeThumb], canvas);
280
281 // Draw the tick-marks on the scroll bar, if any tick-marks
282 // exist. Note: The thumb will be drawn on top of the tick-marks,
283 // which is desired.
284 DrawTickmarks(gc);
285
286 // Draw the thumb (the box you drag in the scroll bar to scroll).
287 nativeTheme->PaintScrollbarThumb(hdc,
288 horz ? SBP_THUMBBTNHORZ :
289 SBP_THUMBBTNVERT,
290 getThemeState(Thumb),
291 getClassicThemeState(Thumb),
292 &m_segmentRects[Thumb]);
293
294 // Draw the gripper (the three little lines on the thumb).
295 nativeTheme->PaintScrollbarThumb(hdc,
296 horz ? SBP_GRIPPERHORZ :
297 SBP_GRIPPERVERT,
298 getThemeState(Thumb),
299 getClassicThemeState(Thumb),
300 &m_segmentRects[Thumb]);
301 }
302
303 // Draw the down/right arrow of the scroll bar.
304 nativeTheme->PaintScrollbarArrow(hdc, getThemeArrowState(Arrow2),
305 (horz ?
306 DFCS_SCROLLRIGHT : DFCS_SCROLLDOWN) |
307 getClassicThemeState(Arrow2),
308 &m_segmentRects[Arrow2]);
309 gc->releaseWindowsContext(hdc, damageRect);
310
311 gc->restore();
312 }
313
314 void PlatformScrollbar::setFrameGeometry(const IntRect& rect)
315 {
316 if (rect == frameGeometry())
317 return;
318
319 Widget::setFrameGeometry(rect);
320 m_needsLayout = true;
321 // NOTE: we assume that our caller will invalidate us
322 }
323
324 bool PlatformScrollbar::handleMouseMoveEvent(const PlatformMouseEvent& e)
325 {
326 if (!parent())
327 return true;
328
329 if (m_captureStart != None) {
330 handleMouseMoveEventWhenCapturing(e);
331 return true;
332 }
333
334 IntPoint pos = convertFromContainingWindow(e.pos());
335 updateMousePosition(pos.x(), pos.y());
336
337 // FIXME: Invalidate only the portions that actually changed
338 invalidate();
339 return true;
340 }
341
342 bool PlatformScrollbar::handleMouseOutEvent(const PlatformMouseEvent& e)
343 {
344 if (!parent())
345 return true;
346
347 ASSERT(m_captureStart == None);
348
349 // Pass bogus values that will never match real mouse coords.
350 updateMousePosition(-1, -1);
351
352 // FIXME: Invalidate only the portions that actually changed
353 invalidate();
354 return true;
355 }
356
357 bool PlatformScrollbar::handleMouseReleaseEvent(const PlatformMouseEvent& e)
358 {
359 ScrollView* parentView = parent();
360 if (!parentView)
361 return true;
362
363 IntPoint pos = convertFromContainingWindow(e.pos());
364 updateMousePosition(pos.x(), pos.y());
365
366 setCapturingMouse(false);
367
368 // FIXME: Invalidate only the portions that actually changed
369 invalidate();
370 return true;
371 }
372
373 bool PlatformScrollbar::handleMousePressEvent(const PlatformMouseEvent& e)
374 {
375 if (!parent())
376 return true;
377
378 // TODO(pkasting): http://b/583875 Right-click should invoke a context menu
379 // (maybe this would be better handled elsewhere?)
380 if (!m_enabled || (e.button() != LeftButton)) {
381 return true;
382 }
383
384 ASSERT(m_captureStart == None);
385
386 IntPoint pos = convertFromContainingWindow(e.pos());
387
388 const bool horz = (orientation() == HorizontalScrollbar);
389 updateMousePosition(pos.x(), pos.y());
390 switch (m_mouseOver) {
391 case Arrow1:
392 scroll(horz ? ScrollLeft : ScrollUp, ScrollByLine);
393 break;
394 case Track:
395 return true;
396 case BeforeThumb:
397 scroll(horz ? ScrollLeft : ScrollUp, ScrollByPage);
398 break;
399 case Thumb:
400 m_dragOrigin.thumbPos = horz ? pos.x() : pos.y();
401 m_dragOrigin.scrollVal = value();
402 break;
403 case AfterThumb:
404 scroll(horz ? ScrollRight : ScrollDown, ScrollByPage);
405 break;
406 case Arrow2:
407 scroll(horz ? ScrollRight : ScrollDown, ScrollByLine);
408 break;
409 default:
410 ASSERT_NOT_REACHED();
411 }
412
413 setCapturingMouse(true);
414
415 // Kick off auto-repeat timer
416 if (m_mouseOver != Thumb)
417 m_autorepeatTimer.start(kAutorepeatInitialDelay,
418 kAutorepeatRepeatInterval);
419
420 m_needsLayout = true;
421 // FIXME: Invalidate only the portions that actually changed
422 invalidate();
423
424 return true;
425 }
426
427 void PlatformScrollbar::handleMouseMoveEventWhenCapturing(const PlatformMouseEve nt& e)
428 {
429 IntPoint pos = convertFromContainingWindow(e.pos());
430 updateMousePosition(pos.x(), pos.y());
431
432 if (m_captureStart != Thumb) {
433 // FIXME: Invalidate only the portions that actually changed
434 invalidate();
435 return;
436 }
437
438 int xCancelDistance, yCancelDistance, backgroundSpan, thumbGirth, delta;
439 // NOTE: The cancel distance calculations are based on the behavior of the
440 // MSVC8 main window scrollbar + some guessing/extrapolation
441 if (orientation() == HorizontalScrollbar) {
442 xCancelDistance = kOffEndMultiplier * horizontalScrollbarHeight();
443 yCancelDistance = kOffSideMultiplier * horizontalScrollbarHeight();
444 backgroundSpan = m_segmentRects[AfterThumb].right -
445 m_segmentRects[BeforeThumb].left;
446 thumbGirth = m_segmentRects[Thumb].right - m_segmentRects[Thumb].left;
447 delta = pos.x() - m_dragOrigin.thumbPos;
448 } else {
449 xCancelDistance = kOffSideMultiplier * verticalScrollbarWidth();
450 yCancelDistance = kOffEndMultiplier * verticalScrollbarWidth();
451 backgroundSpan = m_segmentRects[AfterThumb].bottom -
452 m_segmentRects[BeforeThumb].top;
453 thumbGirth = m_segmentRects[Thumb].bottom - m_segmentRects[Thumb].top;
454 delta = pos.y() - m_dragOrigin.thumbPos;
455 }
456
457 // Snap scrollbar back to drag origin if mouse gets too far away
458 if ((m_lastNativePos.x() <
459 (m_segmentRects[BeforeThumb].left - xCancelDistance)) ||
460 (m_lastNativePos.x() >
461 (m_segmentRects[AfterThumb].right + xCancelDistance)) ||
462 (m_lastNativePos.y() <
463 (m_segmentRects[BeforeThumb].top - yCancelDistance)) ||
464 (m_lastNativePos.y() >
465 (m_segmentRects[AfterThumb].bottom + yCancelDistance)))
466 delta = 0;
467
468 // Convert delta from pixel coords to scrollbar logical coords
469 if (backgroundSpan > thumbGirth) {
470 if (setValue(m_dragOrigin.scrollVal + (delta *
471 (m_totalSize - m_visibleSize) / (backgroundSpan - thumbGirth)))) {
472 m_needsLayout = true;
473 // FIXME: Invalidate only the portions that actually changed
474 invalidate();
475 }
476 }
477 }
478
479 IntRect PlatformScrollbar::windowClipRect() const
480 {
481 if (m_client)
482 return m_client->windowClipRect();
483
484 return convertToContainingWindow(IntRect(0, 0, width(), height()));
485 }
486
487 void PlatformScrollbar::updateThumbPosition()
488 {
489 m_needsLayout = true;
490 // FIXME: Invalidate only the portions that actually changed
491 invalidate();
492 }
493
494 void PlatformScrollbar::updateThumbProportion()
495 {
496 // RenderLayer::updateScrollInfoAfterLayout changes the enabled state when
497 // the style is OSCROLL, however it doesn't change it when the style is OAUT O.
498 // As a workaround we enable the scrollbar if the visible size is less than
499 // the total size
500 if (!m_enabled && m_visibleSize < m_totalSize) {
501 setEnabled(true);
502 }
503
504 // If the thumb was at the end of the track and the scrollbar was resized
505 // smaller, we need to cap the value to the new maximum.
506 if (setValue(value()))
507 return; // updateThumbPosition() already invalidated as needed
508
509 m_needsLayout = true;
510 // FIXME: Invalidate only the portions that actually changed
511 invalidate();
512 }
513
514 void PlatformScrollbar::autoscrollTimerFired(Timer<PlatformScrollbar>*)
515 {
516 ASSERT((m_captureStart != None) && (m_mouseOver == m_captureStart));
517
518 const bool horz = (orientation() == HorizontalScrollbar);
519 switch (m_captureStart) {
520 case Arrow1:
521 scroll(horz ? ScrollLeft : ScrollUp, ScrollByLine);
522 break;
523 case BeforeThumb:
524 scroll(horz ? ScrollLeft : ScrollUp, ScrollByPage);
525 break;
526 case AfterThumb:
527 scroll(horz ? ScrollRight : ScrollDown, ScrollByPage);
528 break;
529 case Arrow2:
530 scroll(horz ? ScrollRight : ScrollDown, ScrollByLine);
531 break;
532 default:
533 ASSERT_NOT_REACHED();
534 }
535 }
536
537 void PlatformScrollbar::setCapturingMouse(bool capturing)
538 {
539 if (capturing) {
540 m_captureStart = m_mouseOver;
541 } else {
542 m_captureStart = None;
543 m_autorepeatTimer.stop();
544 }
545 }
546
547 int PlatformScrollbar::scrollButtonGirth(int systemMetricsCode, int limit,
548 int* backgroundSpan)
549 {
550 const int girth = webkit_glue::IsLayoutTestMode() ?
551 kLayoutTestScrollbarButtonGirth : GetSystemMetrics(systemMetricsCode);
552 *backgroundSpan = limit - 2 * girth;
553 if (*backgroundSpan < 0) {
554 *backgroundSpan = 0;
555 return limit / 2;
556 }
557 return girth;
558 }
559
560 int PlatformScrollbar::scrollThumbGirth(int systemMetricsCode,
561 int backgroundSpan)
562 {
563 const int minimumGirth = webkit_glue::IsLayoutTestMode() ?
564 kLayoutTestScrollbarThumbGirth : GetSystemMetrics(systemMetricsCode);
565 return std::max<int>(m_visibleSize * backgroundSpan / m_totalSize,
566 minimumGirth);
567 }
568
569 void PlatformScrollbar::layout()
570 {
571 if (!m_needsLayout)
572 return;
573 m_needsLayout = false;
574
575 const RECT invalid = {-1, -1, -1, -1};
576 if (m_totalSize <= 0) {
577 for (int i = 0; i < NumSegments; ++i)
578 m_segmentRects[i] = invalid;
579 return;
580 }
581
582 int buttonGirth, backgroundSpan, thumbGirth;
583 RECT box = {0};
584 LONG* changingCoord1, * changingCoord2;
585 // For both orientations, we allow the buttonGirth to determine the
586 // backgroundSpan directly, to avoid rounding errors.
587 if (orientation() == HorizontalScrollbar) {
588 buttonGirth = scrollButtonGirth(SM_CXHSCROLL, width(), &backgroundSpan);
589 thumbGirth = scrollThumbGirth(SM_CXHTHUMB, backgroundSpan);
590 box.bottom += horizontalScrollbarHeight();
591 changingCoord1 = &box.left;
592 changingCoord2 = &box.right;
593 } else {
594 buttonGirth = scrollButtonGirth(SM_CYVSCROLL, height(),
595 &backgroundSpan);
596 thumbGirth = scrollThumbGirth(SM_CYVTHUMB, backgroundSpan);
597 box.right += verticalScrollbarWidth();
598 changingCoord1 = &box.top;
599 changingCoord2 = &box.bottom;
600 }
601
602 // Scrollbar: |<|--------|XXX|------|>|
603 // Start arrow: |<|
604 *changingCoord2 += buttonGirth;
605 m_segmentRects[Arrow1] = box;
606
607 if (thumbGirth >= backgroundSpan) {
608 if (backgroundSpan == 0) {
609 m_segmentRects[Track] = invalid;
610 } else {
611 // Track: |-------------------|
612 *changingCoord1 = *changingCoord2;
613 *changingCoord2 += backgroundSpan;
614 m_segmentRects[Track] = box;
615 }
616
617 m_segmentRects[BeforeThumb] = invalid;
618 m_segmentRects[Thumb] = invalid;
619 m_segmentRects[AfterThumb] = invalid;
620 } else {
621 m_segmentRects[Track] = invalid;
622
623 const int thumbOffset = (m_totalSize <= m_visibleSize) ? 0 : (value() *
624 (backgroundSpan - thumbGirth) / (m_totalSize - m_visibleSize));
625 // Before thumb: |--------|
626 *changingCoord1 = *changingCoord2;
627 *changingCoord2 += thumbOffset;
628 m_segmentRects[BeforeThumb] = box;
629
630 // Thumb: |XXX|
631 *changingCoord1 = *changingCoord2;
632 *changingCoord2 += thumbGirth;
633 m_segmentRects[Thumb] = box;
634
635 // After thumb: |------|
636 *changingCoord1 = *changingCoord2;
637 *changingCoord2 += backgroundSpan - (thumbOffset + thumbGirth);
638 m_segmentRects[AfterThumb] = box;
639 }
640
641 // End arrow: |>|
642 *changingCoord1 = *changingCoord2;
643 *changingCoord2 += buttonGirth;
644 m_segmentRects[Arrow2] = box;
645
646 // Changed layout, so need to update m_mouseOver and m_autorepeatTimer
647 updateMousePositionInternal();
648
649 // DO NOT invalidate() here. We already invalidate()d for this layout when
650 // setting m_needsLayout = true; by the time we reach this point, we're
651 // called by paint(), so invalidate() is not only unnecessary but will
652 // waste effort.
653 }
654
655 void PlatformScrollbar::updateMousePosition(int x, int y)
656 {
657 m_lastNativePos.setX(x);
658 m_lastNativePos.setY(y);
659
660 if (m_needsLayout)
661 layout(); // Calls updateMousePositionInternal()
662 else
663 updateMousePositionInternal();
664 }
665
666 void PlatformScrollbar::updateMousePositionInternal()
667 {
668 m_mouseOver = None;
669 for (int i = 0; i < NumSegments; ++i) {
670 if ((m_lastNativePos.x() >= m_segmentRects[i].left) &&
671 (m_lastNativePos.x() < m_segmentRects[i].right) &&
672 (m_lastNativePos.y() >= m_segmentRects[i].top) &&
673 (m_lastNativePos.y() < m_segmentRects[i].bottom)) {
674 m_mouseOver = static_cast<Segment>(i);
675 break;
676 }
677 }
678
679 // Start/stop autorepeat timer if capturing something other than the thumb.
680 if ((m_captureStart != None) && (m_captureStart != Thumb)) {
681 if (m_mouseOver != m_captureStart)
682 m_autorepeatTimer.stop(); // Safe to call when already stopped
683 else if (!m_autorepeatTimer.isActive())
684 m_autorepeatTimer.startRepeating(kAutorepeatRepeatInterval);
685 }
686 }
687
688 int PlatformScrollbar::getThemeState(Segment target) const
689 {
690 // When dragging the thumb, draw thumb pressed and other segments normal
691 // regardless of where the cursor actually is. See also four places in
692 // getThemeArrowState().
693 if (m_captureStart == Thumb) {
694 if (target == Thumb)
695 return SCRBS_PRESSED;
696 return (win_util::GetWinVersion() < win_util::WINVERSION_VISTA) ?
697 SCRBS_NORMAL : SCRBS_HOVER;
698 }
699 if (!m_enabled)
700 return SCRBS_DISABLED;
701 if ((m_mouseOver != target) || (target == Track)) {
702 return ((m_mouseOver == None) ||
703 (win_util::GetWinVersion() < win_util::WINVERSION_VISTA)) ?
704 SCRBS_NORMAL : SCRBS_HOVER;
705 }
706 if (m_captureStart == None)
707 return SCRBS_HOT;
708 return (m_captureStart == target) ? SCRBS_PRESSED : SCRBS_NORMAL;
709 }
710
711 int PlatformScrollbar::getThemeArrowState(Segment target) const
712 {
713 // We could take advantage of knowing the values in the state enum to write
714 // some simpler code, but treating the state enum as a black box seems
715 // clearer and more future-proof.
716 if (target == Arrow1) {
717 if (orientation() == HorizontalScrollbar) {
718 if (m_captureStart == Thumb) {
719 return
720 (win_util::GetWinVersion() < win_util::WINVERSION_VISTA) ?
721 ABS_LEFTNORMAL : ABS_LEFTHOVER;
722 }
723 if (!m_enabled)
724 return ABS_LEFTDISABLED;
725 if (m_mouseOver != target) {
726 return ((m_mouseOver == None) ||
727 (win_util::GetWinVersion() < win_util::WINVERSION_VISTA)) ?
728 ABS_LEFTNORMAL : ABS_LEFTHOVER;
729 }
730 if (m_captureStart == None)
731 return ABS_LEFTHOT;
732 return (m_captureStart == target) ?
733 ABS_LEFTPRESSED : ABS_LEFTNORMAL;
734 }
735 if (m_captureStart == Thumb) {
736 return (win_util::GetWinVersion() < win_util::WINVERSION_VISTA) ?
737 ABS_UPNORMAL : ABS_UPHOVER;
738 }
739 if (!m_enabled)
740 return ABS_UPDISABLED;
741 if (m_mouseOver != target) {
742 return ((m_mouseOver == None) ||
743 (win_util::GetWinVersion() < win_util::WINVERSION_VISTA)) ?
744 ABS_UPNORMAL : ABS_UPHOVER;
745 }
746 if (m_captureStart == None)
747 return ABS_UPHOT;
748 return (m_captureStart == target) ? ABS_UPPRESSED : ABS_UPNORMAL;
749 }
750 if (orientation() == HorizontalScrollbar) {
751 if (m_captureStart == Thumb) {
752 return (win_util::GetWinVersion() < win_util::WINVERSION_VISTA) ?
753 ABS_RIGHTNORMAL : ABS_RIGHTHOVER;
754 }
755 if (!m_enabled)
756 return ABS_RIGHTDISABLED;
757 if (m_mouseOver != target) {
758 return ((m_mouseOver == None) ||
759 (win_util::GetWinVersion() < win_util::WINVERSION_VISTA)) ?
760 ABS_RIGHTNORMAL : ABS_RIGHTHOVER;
761 }
762 if (m_captureStart == None)
763 return ABS_RIGHTHOT;
764 return (m_captureStart == target) ? ABS_RIGHTPRESSED : ABS_RIGHTNORMAL;
765 }
766 if (m_captureStart == Thumb) {
767 return (win_util::GetWinVersion() < win_util::WINVERSION_VISTA) ?
768 ABS_DOWNNORMAL : ABS_DOWNHOVER;
769 }
770 if (!m_enabled)
771 return ABS_DOWNDISABLED;
772 if (m_mouseOver != target) {
773 return ((m_mouseOver == None) ||
774 (win_util::GetWinVersion() < win_util::WINVERSION_VISTA)) ?
775 ABS_DOWNNORMAL : ABS_DOWNHOVER;
776 }
777 if (m_captureStart == None)
778 return ABS_DOWNHOT;
779 return (m_captureStart == target) ? ABS_DOWNPRESSED : ABS_DOWNNORMAL;
780 }
781
782 int PlatformScrollbar::getClassicThemeState(Segment target) const
783 {
784 // When dragging the thumb, draw the buttons normal even when hovered.
785 if (m_captureStart == Thumb)
786 return 0;
787 if (!m_enabled)
788 return DFCS_INACTIVE;
789 if ((m_mouseOver != target) || (target == Track))
790 return 0;
791 if (m_captureStart == None)
792 return DFCS_HOT;
793 return (m_captureStart == target) ? (DFCS_PUSHED | DFCS_FLAT) : 0;
794 }
795
796 } // namespace WebCore
OLDNEW
« no previous file with comments | « webkit/port/platform/PlatformScrollBar.h ('k') | webkit/port/platform/PopupMenuWin.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698