Index: webkit/port/platform/PlatformScrollBarWin.cpp |
=================================================================== |
--- webkit/port/platform/PlatformScrollBarWin.cpp (revision 3423) |
+++ webkit/port/platform/PlatformScrollBarWin.cpp (working copy) |
@@ -1,796 +0,0 @@ |
-// Copyright (c) 2008, Google Inc. |
-// All rights reserved. |
-// |
-// Redistribution and use in source and binary forms, with or without |
-// modification, are permitted provided that the following conditions are |
-// met: |
-// |
-// * Redistributions of source code must retain the above copyright |
-// notice, this list of conditions and the following disclaimer. |
-// * Redistributions in binary form must reproduce the above |
-// copyright notice, this list of conditions and the following disclaimer |
-// in the documentation and/or other materials provided with the |
-// distribution. |
-// * Neither the name of Google Inc. nor the names of its |
-// contributors may be used to endorse or promote products derived from |
-// this software without specific prior written permission. |
-// |
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
- |
-#include "config.h" |
-#include <algorithm> |
-#include <windows.h> |
-#include <vsstyle.h> |
-#include "FrameView.h" |
-#include "GraphicsContext.h" |
-#include "IntRect.h" |
-#include "NativeImageSkia.h" |
-#include "PlatformMouseEvent.h" |
-#include "PlatformScrollBar.h" |
-#include "Range.h" |
-#include "ScrollView.h" |
-#include "WidgetClientWin.h" |
- |
-#include "graphics/SkiaUtils.h" |
- |
-#undef LOG |
-#include "base/gfx/native_theme.h" |
-#include "base/gfx/platform_canvas_win.h" |
-#include "base/win_util.h" |
-#include "webkit/glue/webframe_impl.h" |
-#include "webkit/glue/webkit_glue.h" |
- |
-namespace WebCore { |
- |
-const int PlatformScrollbar::kOffSideMultiplier = 8; |
-const int PlatformScrollbar::kOffEndMultiplier = 3; |
-const double PlatformScrollbar::kAutorepeatInitialDelay = 0.4; |
-const double PlatformScrollbar::kAutorepeatRepeatInterval = 1. / 15.; |
- |
-// The scrollbar size in DumpRenderTree on the Mac - so we can match their |
-// layout results. Entries are for regular, small, and mini scrollbars. |
-// Metrics obtained using [NSScroller scrollerWidthForControlSize:] |
-static const int kMacScrollbarSize[3] = {15, 11, 15}; |
- |
-// Scrollbar button and thumb sizes, for consistent layout results. The Mac |
-// value is not readily available, but it's not really needed, since these |
-// metrics only affect drawing within the scrollbar itself. These are the |
-// standard Windows values without Large Fonts. |
-static const int kLayoutTestScrollbarButtonGirth = 17; |
-static const int kLayoutTestScrollbarThumbGirth = 17; |
- |
- |
-/*static*/ void PlatformScrollbar::themeChanged() |
-{ |
- // TODO(darin): implement this |
-} |
- |
-/*static*/ int PlatformScrollbar::horizontalScrollbarHeight( |
- ScrollbarControlSize controlSize) |
-{ |
- return webkit_glue::IsLayoutTestMode() ? kMacScrollbarSize[controlSize] : |
- GetSystemMetrics(SM_CYHSCROLL); |
-} |
- |
-/*static*/ int PlatformScrollbar::verticalScrollbarWidth( |
- ScrollbarControlSize controlSize) |
-{ |
- return webkit_glue::IsLayoutTestMode() ? kMacScrollbarSize[controlSize] : |
- GetSystemMetrics(SM_CXVSCROLL); |
-} |
- |
-PlatformScrollbar::PlatformScrollbar(ScrollbarClient* client, |
- ScrollbarOrientation orientation, |
- ScrollbarControlSize controlSize) |
- : Scrollbar(client, orientation, controlSize) |
- , m_lastNativePos(-1, -1) // initialize to bogus values |
- , m_mouseOver(None) |
- , m_captureStart(None) |
-#pragma warning(suppress: 4355) // it's okay to pass |this| here! |
- , m_autorepeatTimer(this, &PlatformScrollbar::autoscrollTimerFired) |
- , m_enabled(true) |
- , m_needsLayout(true) |
-{ |
-} |
- |
-PlatformScrollbar::~PlatformScrollbar() |
-{ |
-} |
- |
-int PlatformScrollbar::width() const |
-{ |
- return orientation() == VerticalScrollbar ? |
- verticalScrollbarWidth(controlSize()) : Widget::width(); |
-} |
- |
-int PlatformScrollbar::height() const |
-{ |
- return orientation() == HorizontalScrollbar ? |
- horizontalScrollbarHeight(controlSize()) : Widget::height(); |
-} |
- |
-void PlatformScrollbar::setRect(const IntRect& rect) |
-{ |
- setFrameGeometry(rect); |
-} |
- |
-void PlatformScrollbar::setEnabled(bool enabled) |
-{ |
- if (m_enabled == enabled) |
- return; |
- |
- m_enabled = enabled; |
- invalidate(); |
-} |
- |
-void PlatformScrollbar::DrawTickmarks(GraphicsContext* context) const |
-{ |
- // We don't draw on the horizontal scrollbar. It is too confusing |
- // to have the tickmarks appear on both scrollbars. |
- const bool horz = orientation() == HorizontalScrollbar; |
- if (horz) |
- return; |
- |
- // We need to as the WidgetClientWin for the bitmap to use to draw. |
- WidgetClientWin* widget_client = static_cast<WidgetClientWin*>( |
- WebCore::Widget::client()); |
- if (!widget_client) |
- return; // Cannot draw without access to the bitmap. |
- |
- // Get the frame view this scroll bar belongs to. |
- FrameView* view = reinterpret_cast<FrameView*>(parent()); |
- ASSERT(view); |
- |
- // A frame can be null if this function is called for the scroll views |
- // used when drawing drop-down boxes. We don't need to draw anything in |
- // such cases. |
- if (!view->frame()) |
- return; |
- |
- // Find out if the frame has any tickmarks. |
- const Vector<RefPtr<Range> >& tickmarks = |
- WebFrameImpl::FromFrame(view->frame())->tickmarks(); |
- if (tickmarks.isEmpty()) |
- return; |
- |
- RECT track_area; |
- if (m_segmentRects[Track].left != -1) { |
- // Scroll bar is too small to draw a thumb. |
- track_area.left = m_segmentRects[Track].left; |
- track_area.top = m_segmentRects[Track].top; |
- track_area.right = m_segmentRects[Track].right - 1; |
- track_area.bottom = m_segmentRects[Track].bottom - 1; |
- } else { |
- // Find the area between the arrows of the scroll bar. |
- track_area.left = m_segmentRects[BeforeThumb].left; |
- track_area.top = m_segmentRects[BeforeThumb].top; |
- track_area.right = m_segmentRects[AfterThumb].right - 1; |
- track_area.bottom = m_segmentRects[AfterThumb].bottom - 1; |
- } |
- |
- // We now can figure out the actual height and width of the track. |
- const int track_height = track_area.bottom - track_area.top; |
- const int track_width = track_area.right - track_area.left; |
- |
- if (track_height <= 0 || track_width <= 0) |
- return; // nothing to draw on. |
- |
- // NOTE: We tolerate the platformContext() call here because the scrollbars |
- // will not be serialized, i.e. composition is done in the renderer and |
- // never in the browser. |
- // Prepare the bitmap for drawing the tickmarks on the scroll bar. |
- gfx::PlatformCanvas* canvas = context->platformContext()->canvas(); |
- |
- // Load the image for the tickmark. |
- static RefPtr<Image> dashImg = Image::loadPlatformResource("tickmarkDash"); |
- DCHECK(dashImg); |
- if (dashImg->isNull()) { |
- ASSERT_NOT_REACHED(); |
- return; |
- } |
- const NativeImageSkia* dash = dashImg->nativeImageForCurrentFrame(); |
- |
- for (Vector<RefPtr<Range> >::const_iterator i = |
- tickmarks.begin(); |
- i != tickmarks.end(); ++i) { |
- const RefPtr<Range> range = (*i); |
- |
- if (!WebFrameImpl::RangeShouldBeHighlighted(range.get())) |
- continue; |
- |
- const IntRect& bounds = range->boundingBox(); |
- |
- // Calculate how far down (in %) the tick-mark should appear. |
- const float percent = static_cast<float>(bounds.y()) / m_totalSize; |
- |
- // Calculate how far down (in pixels) the tick-mark should appear. |
- const int y_pos = track_area.top + (track_height * percent); |
- |
- // Draw the tick-mark as a rounded rect with a slightly curved edge. |
- canvas->drawBitmap(*dash, track_area.left, y_pos); |
- } |
-} |
- |
-// paint in the coordinate space of our parent's content area |
-void PlatformScrollbar::paint(GraphicsContext* gc, const IntRect& damageRect) |
-{ |
- if (gc->paintingDisabled()) |
- return; |
- |
- // Don't paint anything if the scrollbar doesn't intersect the damage rect. |
- if (!frameGeometry().intersects(damageRect)) |
- return; |
- |
- gc->save(); |
- gc->translate(x(), y()); |
- |
- layout(); |
- |
- HDC hdc = gc->getWindowsContext(damageRect); |
- const bool horz = orientation() == HorizontalScrollbar; |
- const PlatformContextSkia* const skia = gc->platformContext(); |
- const gfx::NativeTheme* const nativeTheme = skia->nativeTheme(); |
- gfx::PlatformCanvasWin* const canvas = skia->canvas(); |
- |
- // Draw the up/left arrow of the scroll bar. |
- nativeTheme->PaintScrollbarArrow(hdc, getThemeArrowState(Arrow1), |
- (horz ? DFCS_SCROLLLEFT : DFCS_SCROLLUP) | |
- getClassicThemeState(Arrow1), |
- &m_segmentRects[Arrow1]); |
- |
- if (m_segmentRects[Track].left != -1) { |
- // The scroll bar is too small to draw the thumb. Just draw a |
- // single track between the arrows. |
- nativeTheme->PaintScrollbarTrack(hdc, |
- horz ? SBP_UPPERTRACKHORZ : |
- SBP_UPPERTRACKVERT, |
- getThemeState(Track), |
- getClassicThemeState(Track), |
- &m_segmentRects[Track], |
- &m_segmentRects[Track], canvas); |
- DrawTickmarks(gc); |
- } else { |
- // Draw the track area before the thumb on the scroll bar. |
- nativeTheme->PaintScrollbarTrack(hdc, |
- horz ? SBP_UPPERTRACKHORZ : |
- SBP_UPPERTRACKVERT, |
- getThemeState(BeforeThumb), |
- getClassicThemeState(BeforeThumb), |
- &m_segmentRects[BeforeThumb], |
- &m_segmentRects[BeforeThumb], canvas); |
- |
- // Draw the track area after the thumb on the scroll bar. |
- nativeTheme->PaintScrollbarTrack(hdc, |
- horz ? SBP_LOWERTRACKHORZ : |
- SBP_LOWERTRACKVERT, |
- getThemeState(AfterThumb), |
- getClassicThemeState(AfterThumb), |
- &m_segmentRects[AfterThumb], |
- &m_segmentRects[BeforeThumb], canvas); |
- |
- // Draw the tick-marks on the scroll bar, if any tick-marks |
- // exist. Note: The thumb will be drawn on top of the tick-marks, |
- // which is desired. |
- DrawTickmarks(gc); |
- |
- // Draw the thumb (the box you drag in the scroll bar to scroll). |
- nativeTheme->PaintScrollbarThumb(hdc, |
- horz ? SBP_THUMBBTNHORZ : |
- SBP_THUMBBTNVERT, |
- getThemeState(Thumb), |
- getClassicThemeState(Thumb), |
- &m_segmentRects[Thumb]); |
- |
- // Draw the gripper (the three little lines on the thumb). |
- nativeTheme->PaintScrollbarThumb(hdc, |
- horz ? SBP_GRIPPERHORZ : |
- SBP_GRIPPERVERT, |
- getThemeState(Thumb), |
- getClassicThemeState(Thumb), |
- &m_segmentRects[Thumb]); |
- } |
- |
- // Draw the down/right arrow of the scroll bar. |
- nativeTheme->PaintScrollbarArrow(hdc, getThemeArrowState(Arrow2), |
- (horz ? |
- DFCS_SCROLLRIGHT : DFCS_SCROLLDOWN) | |
- getClassicThemeState(Arrow2), |
- &m_segmentRects[Arrow2]); |
- gc->releaseWindowsContext(hdc, damageRect); |
- |
- gc->restore(); |
-} |
- |
-void PlatformScrollbar::setFrameGeometry(const IntRect& rect) |
-{ |
- if (rect == frameGeometry()) |
- return; |
- |
- Widget::setFrameGeometry(rect); |
- m_needsLayout = true; |
- // NOTE: we assume that our caller will invalidate us |
-} |
- |
-bool PlatformScrollbar::handleMouseMoveEvent(const PlatformMouseEvent& e) |
-{ |
- if (!parent()) |
- return true; |
- |
- if (m_captureStart != None) { |
- handleMouseMoveEventWhenCapturing(e); |
- return true; |
- } |
- |
- IntPoint pos = convertFromContainingWindow(e.pos()); |
- updateMousePosition(pos.x(), pos.y()); |
- |
- // FIXME: Invalidate only the portions that actually changed |
- invalidate(); |
- return true; |
-} |
- |
-bool PlatformScrollbar::handleMouseOutEvent(const PlatformMouseEvent& e) |
-{ |
- if (!parent()) |
- return true; |
- |
- ASSERT(m_captureStart == None); |
- |
- // Pass bogus values that will never match real mouse coords. |
- updateMousePosition(-1, -1); |
- |
- // FIXME: Invalidate only the portions that actually changed |
- invalidate(); |
- return true; |
-} |
- |
-bool PlatformScrollbar::handleMouseReleaseEvent(const PlatformMouseEvent& e) |
-{ |
- ScrollView* parentView = parent(); |
- if (!parentView) |
- return true; |
- |
- IntPoint pos = convertFromContainingWindow(e.pos()); |
- updateMousePosition(pos.x(), pos.y()); |
- |
- setCapturingMouse(false); |
- |
- // FIXME: Invalidate only the portions that actually changed |
- invalidate(); |
- return true; |
-} |
- |
-bool PlatformScrollbar::handleMousePressEvent(const PlatformMouseEvent& e) |
-{ |
- if (!parent()) |
- return true; |
- |
- // TODO(pkasting): http://b/583875 Right-click should invoke a context menu |
- // (maybe this would be better handled elsewhere?) |
- if (!m_enabled || (e.button() != LeftButton)) { |
- return true; |
- } |
- |
- ASSERT(m_captureStart == None); |
- |
- IntPoint pos = convertFromContainingWindow(e.pos()); |
- |
- const bool horz = (orientation() == HorizontalScrollbar); |
- updateMousePosition(pos.x(), pos.y()); |
- switch (m_mouseOver) { |
- case Arrow1: |
- scroll(horz ? ScrollLeft : ScrollUp, ScrollByLine); |
- break; |
- case Track: |
- return true; |
- case BeforeThumb: |
- scroll(horz ? ScrollLeft : ScrollUp, ScrollByPage); |
- break; |
- case Thumb: |
- m_dragOrigin.thumbPos = horz ? pos.x() : pos.y(); |
- m_dragOrigin.scrollVal = value(); |
- break; |
- case AfterThumb: |
- scroll(horz ? ScrollRight : ScrollDown, ScrollByPage); |
- break; |
- case Arrow2: |
- scroll(horz ? ScrollRight : ScrollDown, ScrollByLine); |
- break; |
- default: |
- ASSERT_NOT_REACHED(); |
- } |
- |
- setCapturingMouse(true); |
- |
- // Kick off auto-repeat timer |
- if (m_mouseOver != Thumb) |
- m_autorepeatTimer.start(kAutorepeatInitialDelay, |
- kAutorepeatRepeatInterval); |
- |
- m_needsLayout = true; |
- // FIXME: Invalidate only the portions that actually changed |
- invalidate(); |
- |
- return true; |
-} |
- |
-void PlatformScrollbar::handleMouseMoveEventWhenCapturing(const PlatformMouseEvent& e) |
-{ |
- IntPoint pos = convertFromContainingWindow(e.pos()); |
- updateMousePosition(pos.x(), pos.y()); |
- |
- if (m_captureStart != Thumb) { |
- // FIXME: Invalidate only the portions that actually changed |
- invalidate(); |
- return; |
- } |
- |
- int xCancelDistance, yCancelDistance, backgroundSpan, thumbGirth, delta; |
- // NOTE: The cancel distance calculations are based on the behavior of the |
- // MSVC8 main window scrollbar + some guessing/extrapolation |
- if (orientation() == HorizontalScrollbar) { |
- xCancelDistance = kOffEndMultiplier * horizontalScrollbarHeight(); |
- yCancelDistance = kOffSideMultiplier * horizontalScrollbarHeight(); |
- backgroundSpan = m_segmentRects[AfterThumb].right - |
- m_segmentRects[BeforeThumb].left; |
- thumbGirth = m_segmentRects[Thumb].right - m_segmentRects[Thumb].left; |
- delta = pos.x() - m_dragOrigin.thumbPos; |
- } else { |
- xCancelDistance = kOffSideMultiplier * verticalScrollbarWidth(); |
- yCancelDistance = kOffEndMultiplier * verticalScrollbarWidth(); |
- backgroundSpan = m_segmentRects[AfterThumb].bottom - |
- m_segmentRects[BeforeThumb].top; |
- thumbGirth = m_segmentRects[Thumb].bottom - m_segmentRects[Thumb].top; |
- delta = pos.y() - m_dragOrigin.thumbPos; |
- } |
- |
- // Snap scrollbar back to drag origin if mouse gets too far away |
- if ((m_lastNativePos.x() < |
- (m_segmentRects[BeforeThumb].left - xCancelDistance)) || |
- (m_lastNativePos.x() > |
- (m_segmentRects[AfterThumb].right + xCancelDistance)) || |
- (m_lastNativePos.y() < |
- (m_segmentRects[BeforeThumb].top - yCancelDistance)) || |
- (m_lastNativePos.y() > |
- (m_segmentRects[AfterThumb].bottom + yCancelDistance))) |
- delta = 0; |
- |
- // Convert delta from pixel coords to scrollbar logical coords |
- if (backgroundSpan > thumbGirth) { |
- if (setValue(m_dragOrigin.scrollVal + (delta * |
- (m_totalSize - m_visibleSize) / (backgroundSpan - thumbGirth)))) { |
- m_needsLayout = true; |
- // FIXME: Invalidate only the portions that actually changed |
- invalidate(); |
- } |
- } |
-} |
- |
-IntRect PlatformScrollbar::windowClipRect() const |
-{ |
- if (m_client) |
- return m_client->windowClipRect(); |
- |
- return convertToContainingWindow(IntRect(0, 0, width(), height())); |
-} |
- |
-void PlatformScrollbar::updateThumbPosition() |
-{ |
- m_needsLayout = true; |
- // FIXME: Invalidate only the portions that actually changed |
- invalidate(); |
-} |
- |
-void PlatformScrollbar::updateThumbProportion() |
-{ |
- // RenderLayer::updateScrollInfoAfterLayout changes the enabled state when |
- // the style is OSCROLL, however it doesn't change it when the style is OAUTO. |
- // As a workaround we enable the scrollbar if the visible size is less than |
- // the total size |
- if (!m_enabled && m_visibleSize < m_totalSize) { |
- setEnabled(true); |
- } |
- |
- // If the thumb was at the end of the track and the scrollbar was resized |
- // smaller, we need to cap the value to the new maximum. |
- if (setValue(value())) |
- return; // updateThumbPosition() already invalidated as needed |
- |
- m_needsLayout = true; |
- // FIXME: Invalidate only the portions that actually changed |
- invalidate(); |
-} |
- |
-void PlatformScrollbar::autoscrollTimerFired(Timer<PlatformScrollbar>*) |
-{ |
- ASSERT((m_captureStart != None) && (m_mouseOver == m_captureStart)); |
- |
- const bool horz = (orientation() == HorizontalScrollbar); |
- switch (m_captureStart) { |
- case Arrow1: |
- scroll(horz ? ScrollLeft : ScrollUp, ScrollByLine); |
- break; |
- case BeforeThumb: |
- scroll(horz ? ScrollLeft : ScrollUp, ScrollByPage); |
- break; |
- case AfterThumb: |
- scroll(horz ? ScrollRight : ScrollDown, ScrollByPage); |
- break; |
- case Arrow2: |
- scroll(horz ? ScrollRight : ScrollDown, ScrollByLine); |
- break; |
- default: |
- ASSERT_NOT_REACHED(); |
- } |
-} |
- |
-void PlatformScrollbar::setCapturingMouse(bool capturing) |
-{ |
- if (capturing) { |
- m_captureStart = m_mouseOver; |
- } else { |
- m_captureStart = None; |
- m_autorepeatTimer.stop(); |
- } |
-} |
- |
-int PlatformScrollbar::scrollButtonGirth(int systemMetricsCode, int limit, |
- int* backgroundSpan) |
-{ |
- const int girth = webkit_glue::IsLayoutTestMode() ? |
- kLayoutTestScrollbarButtonGirth : GetSystemMetrics(systemMetricsCode); |
- *backgroundSpan = limit - 2 * girth; |
- if (*backgroundSpan < 0) { |
- *backgroundSpan = 0; |
- return limit / 2; |
- } |
- return girth; |
-} |
- |
-int PlatformScrollbar::scrollThumbGirth(int systemMetricsCode, |
- int backgroundSpan) |
-{ |
- const int minimumGirth = webkit_glue::IsLayoutTestMode() ? |
- kLayoutTestScrollbarThumbGirth : GetSystemMetrics(systemMetricsCode); |
- return std::max<int>(m_visibleSize * backgroundSpan / m_totalSize, |
- minimumGirth); |
-} |
- |
-void PlatformScrollbar::layout() |
-{ |
- if (!m_needsLayout) |
- return; |
- m_needsLayout = false; |
- |
- const RECT invalid = {-1, -1, -1, -1}; |
- if (m_totalSize <= 0) { |
- for (int i = 0; i < NumSegments; ++i) |
- m_segmentRects[i] = invalid; |
- return; |
- } |
- |
- int buttonGirth, backgroundSpan, thumbGirth; |
- RECT box = {0}; |
- LONG* changingCoord1, * changingCoord2; |
- // For both orientations, we allow the buttonGirth to determine the |
- // backgroundSpan directly, to avoid rounding errors. |
- if (orientation() == HorizontalScrollbar) { |
- buttonGirth = scrollButtonGirth(SM_CXHSCROLL, width(), &backgroundSpan); |
- thumbGirth = scrollThumbGirth(SM_CXHTHUMB, backgroundSpan); |
- box.bottom += horizontalScrollbarHeight(); |
- changingCoord1 = &box.left; |
- changingCoord2 = &box.right; |
- } else { |
- buttonGirth = scrollButtonGirth(SM_CYVSCROLL, height(), |
- &backgroundSpan); |
- thumbGirth = scrollThumbGirth(SM_CYVTHUMB, backgroundSpan); |
- box.right += verticalScrollbarWidth(); |
- changingCoord1 = &box.top; |
- changingCoord2 = &box.bottom; |
- } |
- |
- // Scrollbar: |<|--------|XXX|------|>| |
- // Start arrow: |<| |
- *changingCoord2 += buttonGirth; |
- m_segmentRects[Arrow1] = box; |
- |
- if (thumbGirth >= backgroundSpan) { |
- if (backgroundSpan == 0) { |
- m_segmentRects[Track] = invalid; |
- } else { |
- // Track: |-------------------| |
- *changingCoord1 = *changingCoord2; |
- *changingCoord2 += backgroundSpan; |
- m_segmentRects[Track] = box; |
- } |
- |
- m_segmentRects[BeforeThumb] = invalid; |
- m_segmentRects[Thumb] = invalid; |
- m_segmentRects[AfterThumb] = invalid; |
- } else { |
- m_segmentRects[Track] = invalid; |
- |
- const int thumbOffset = (m_totalSize <= m_visibleSize) ? 0 : (value() * |
- (backgroundSpan - thumbGirth) / (m_totalSize - m_visibleSize)); |
- // Before thumb: |--------| |
- *changingCoord1 = *changingCoord2; |
- *changingCoord2 += thumbOffset; |
- m_segmentRects[BeforeThumb] = box; |
- |
- // Thumb: |XXX| |
- *changingCoord1 = *changingCoord2; |
- *changingCoord2 += thumbGirth; |
- m_segmentRects[Thumb] = box; |
- |
- // After thumb: |------| |
- *changingCoord1 = *changingCoord2; |
- *changingCoord2 += backgroundSpan - (thumbOffset + thumbGirth); |
- m_segmentRects[AfterThumb] = box; |
- } |
- |
- // End arrow: |>| |
- *changingCoord1 = *changingCoord2; |
- *changingCoord2 += buttonGirth; |
- m_segmentRects[Arrow2] = box; |
- |
- // Changed layout, so need to update m_mouseOver and m_autorepeatTimer |
- updateMousePositionInternal(); |
- |
- // DO NOT invalidate() here. We already invalidate()d for this layout when |
- // setting m_needsLayout = true; by the time we reach this point, we're |
- // called by paint(), so invalidate() is not only unnecessary but will |
- // waste effort. |
-} |
- |
-void PlatformScrollbar::updateMousePosition(int x, int y) |
-{ |
- m_lastNativePos.setX(x); |
- m_lastNativePos.setY(y); |
- |
- if (m_needsLayout) |
- layout(); // Calls updateMousePositionInternal() |
- else |
- updateMousePositionInternal(); |
-} |
- |
-void PlatformScrollbar::updateMousePositionInternal() |
-{ |
- m_mouseOver = None; |
- for (int i = 0; i < NumSegments; ++i) { |
- if ((m_lastNativePos.x() >= m_segmentRects[i].left) && |
- (m_lastNativePos.x() < m_segmentRects[i].right) && |
- (m_lastNativePos.y() >= m_segmentRects[i].top) && |
- (m_lastNativePos.y() < m_segmentRects[i].bottom)) { |
- m_mouseOver = static_cast<Segment>(i); |
- break; |
- } |
- } |
- |
- // Start/stop autorepeat timer if capturing something other than the thumb. |
- if ((m_captureStart != None) && (m_captureStart != Thumb)) { |
- if (m_mouseOver != m_captureStart) |
- m_autorepeatTimer.stop(); // Safe to call when already stopped |
- else if (!m_autorepeatTimer.isActive()) |
- m_autorepeatTimer.startRepeating(kAutorepeatRepeatInterval); |
- } |
-} |
- |
-int PlatformScrollbar::getThemeState(Segment target) const |
-{ |
- // When dragging the thumb, draw thumb pressed and other segments normal |
- // regardless of where the cursor actually is. See also four places in |
- // getThemeArrowState(). |
- if (m_captureStart == Thumb) { |
- if (target == Thumb) |
- return SCRBS_PRESSED; |
- return (win_util::GetWinVersion() < win_util::WINVERSION_VISTA) ? |
- SCRBS_NORMAL : SCRBS_HOVER; |
- } |
- if (!m_enabled) |
- return SCRBS_DISABLED; |
- if ((m_mouseOver != target) || (target == Track)) { |
- return ((m_mouseOver == None) || |
- (win_util::GetWinVersion() < win_util::WINVERSION_VISTA)) ? |
- SCRBS_NORMAL : SCRBS_HOVER; |
- } |
- if (m_captureStart == None) |
- return SCRBS_HOT; |
- return (m_captureStart == target) ? SCRBS_PRESSED : SCRBS_NORMAL; |
-} |
- |
-int PlatformScrollbar::getThemeArrowState(Segment target) const |
-{ |
- // We could take advantage of knowing the values in the state enum to write |
- // some simpler code, but treating the state enum as a black box seems |
- // clearer and more future-proof. |
- if (target == Arrow1) { |
- if (orientation() == HorizontalScrollbar) { |
- if (m_captureStart == Thumb) { |
- return |
- (win_util::GetWinVersion() < win_util::WINVERSION_VISTA) ? |
- ABS_LEFTNORMAL : ABS_LEFTHOVER; |
- } |
- if (!m_enabled) |
- return ABS_LEFTDISABLED; |
- if (m_mouseOver != target) { |
- return ((m_mouseOver == None) || |
- (win_util::GetWinVersion() < win_util::WINVERSION_VISTA)) ? |
- ABS_LEFTNORMAL : ABS_LEFTHOVER; |
- } |
- if (m_captureStart == None) |
- return ABS_LEFTHOT; |
- return (m_captureStart == target) ? |
- ABS_LEFTPRESSED : ABS_LEFTNORMAL; |
- } |
- if (m_captureStart == Thumb) { |
- return (win_util::GetWinVersion() < win_util::WINVERSION_VISTA) ? |
- ABS_UPNORMAL : ABS_UPHOVER; |
- } |
- if (!m_enabled) |
- return ABS_UPDISABLED; |
- if (m_mouseOver != target) { |
- return ((m_mouseOver == None) || |
- (win_util::GetWinVersion() < win_util::WINVERSION_VISTA)) ? |
- ABS_UPNORMAL : ABS_UPHOVER; |
- } |
- if (m_captureStart == None) |
- return ABS_UPHOT; |
- return (m_captureStart == target) ? ABS_UPPRESSED : ABS_UPNORMAL; |
- } |
- if (orientation() == HorizontalScrollbar) { |
- if (m_captureStart == Thumb) { |
- return (win_util::GetWinVersion() < win_util::WINVERSION_VISTA) ? |
- ABS_RIGHTNORMAL : ABS_RIGHTHOVER; |
- } |
- if (!m_enabled) |
- return ABS_RIGHTDISABLED; |
- if (m_mouseOver != target) { |
- return ((m_mouseOver == None) || |
- (win_util::GetWinVersion() < win_util::WINVERSION_VISTA)) ? |
- ABS_RIGHTNORMAL : ABS_RIGHTHOVER; |
- } |
- if (m_captureStart == None) |
- return ABS_RIGHTHOT; |
- return (m_captureStart == target) ? ABS_RIGHTPRESSED : ABS_RIGHTNORMAL; |
- } |
- if (m_captureStart == Thumb) { |
- return (win_util::GetWinVersion() < win_util::WINVERSION_VISTA) ? |
- ABS_DOWNNORMAL : ABS_DOWNHOVER; |
- } |
- if (!m_enabled) |
- return ABS_DOWNDISABLED; |
- if (m_mouseOver != target) { |
- return ((m_mouseOver == None) || |
- (win_util::GetWinVersion() < win_util::WINVERSION_VISTA)) ? |
- ABS_DOWNNORMAL : ABS_DOWNHOVER; |
- } |
- if (m_captureStart == None) |
- return ABS_DOWNHOT; |
- return (m_captureStart == target) ? ABS_DOWNPRESSED : ABS_DOWNNORMAL; |
-} |
- |
-int PlatformScrollbar::getClassicThemeState(Segment target) const |
-{ |
- // When dragging the thumb, draw the buttons normal even when hovered. |
- if (m_captureStart == Thumb) |
- return 0; |
- if (!m_enabled) |
- return DFCS_INACTIVE; |
- if ((m_mouseOver != target) || (target == Track)) |
- return 0; |
- if (m_captureStart == None) |
- return DFCS_HOT; |
- return (m_captureStart == target) ? (DFCS_PUSHED | DFCS_FLAT) : 0; |
-} |
- |
-} // namespace WebCore |