summaryrefslogtreecommitdiffstats
path: root/webkit/port/platform/chromium/ScrollbarThemeChromiumWin.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'webkit/port/platform/chromium/ScrollbarThemeChromiumWin.cpp')
-rw-r--r--webkit/port/platform/chromium/ScrollbarThemeChromiumWin.cpp361
1 files changed, 361 insertions, 0 deletions
diff --git a/webkit/port/platform/chromium/ScrollbarThemeChromiumWin.cpp b/webkit/port/platform/chromium/ScrollbarThemeChromiumWin.cpp
new file mode 100644
index 0000000..e887d59
--- /dev/null
+++ b/webkit/port/platform/chromium/ScrollbarThemeChromiumWin.cpp
@@ -0,0 +1,361 @@
+/*
+ * Copyright (C) 2008 Apple 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:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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 "ScrollbarThemeChromiumWin.h"
+
+#include <windows.h>
+#include <vsstyle.h>
+
+#include "GraphicsContext.h"
+#include "PlatformContextSkia.h"
+#include "PlatformMouseEvent.h"
+#include "Scrollbar.h"
+
+#include "base/gfx/native_theme.h"
+#include "base/win_util.h"
+#include "webkit/glue/webkit_glue.h"
+
+namespace WebCore {
+
+// 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 };
+
+static bool runningVista()
+{
+ return win_util::GetWinVersion() >= win_util::WINVERSION_VISTA;
+}
+
+static RECT toRECT(const IntRect& input)
+{
+ RECT output;
+ output.left = input.x();
+ output.right = input.right();
+ output.top = input.y();
+ output.bottom = input.bottom();
+ return output;
+}
+
+ScrollbarTheme* ScrollbarTheme::nativeTheme()
+{
+ static ScrollbarThemeChromiumWin theme;
+ return &theme;
+}
+
+ScrollbarThemeChromiumWin::ScrollbarThemeChromiumWin()
+{
+}
+
+ScrollbarThemeChromiumWin::~ScrollbarThemeChromiumWin()
+{
+}
+
+int ScrollbarThemeChromiumWin::scrollbarThickness(ScrollbarControlSize controlSize)
+{
+ static int thickness;
+ if (!thickness) {
+ if (webkit_glue::IsLayoutTestMode())
+ return kMacScrollbarSize[controlSize];
+ thickness = GetSystemMetrics(SM_CXVSCROLL);
+ }
+ return thickness;
+}
+
+void ScrollbarThemeChromiumWin::themeChanged()
+{
+}
+
+bool ScrollbarThemeChromiumWin::invalidateOnMouseEnterExit()
+{
+ return runningVista();
+}
+
+bool ScrollbarThemeChromiumWin::hasThumb(Scrollbar* scrollbar)
+{
+ // This method is just called as a paint-time optimization to see if
+ // painting the thumb can be skipped. We don't have to be exact here.
+ return thumbLength(scrollbar) > 0;
+}
+
+IntRect ScrollbarThemeChromiumWin::backButtonRect(Scrollbar* scrollbar, ScrollbarPart part, bool)
+{
+ // Windows just has single arrows.
+ if (part == BackButtonEndPart)
+ return IntRect();
+
+ IntSize size = buttonSize(scrollbar);
+ return IntRect(scrollbar->x(), scrollbar->y(), size.width(), size.height());
+}
+
+IntRect ScrollbarThemeChromiumWin::forwardButtonRect(Scrollbar* scrollbar, ScrollbarPart part, bool)
+{
+ // Windows just has single arrows.
+ if (part == ForwardButtonStartPart)
+ return IntRect();
+
+ IntSize size = buttonSize(scrollbar);
+ int x, y;
+ if (scrollbar->orientation() == HorizontalScrollbar) {
+ x = scrollbar->x() + scrollbar->width() - size.width();
+ y = scrollbar->y();
+ } else {
+ x = scrollbar->x();
+ y = scrollbar->y() + scrollbar->height() - size.height();
+ }
+ return IntRect(x, y, size.width(), size.height());
+}
+
+IntRect ScrollbarThemeChromiumWin::trackRect(Scrollbar* scrollbar, bool)
+{
+ IntSize bs = buttonSize(scrollbar);
+ int thickness = scrollbarThickness();
+ if (scrollbar->orientation() == HorizontalScrollbar) {
+ if (scrollbar->width() < 2 * thickness)
+ return IntRect();
+ return IntRect(scrollbar->x() + bs.width(), scrollbar->y(), scrollbar->width() - 2 * bs.width(), thickness);
+ }
+ if (scrollbar->height() < 2 * thickness)
+ return IntRect();
+ return IntRect(scrollbar->x(), scrollbar->y() + bs.height(), thickness, scrollbar->height() - 2 * bs.height());
+}
+
+void ScrollbarThemeChromiumWin::paintTrackBackground(GraphicsContext* context, Scrollbar* scrollbar, const IntRect& rect)
+{
+ // Just assume a forward track part. We only paint the track as a single piece when there is no thumb.
+ if (!hasThumb(scrollbar))
+ paintTrackPiece(context, scrollbar, rect, ForwardTrackPart);
+}
+
+void ScrollbarThemeChromiumWin::paintTrackPiece(GraphicsContext* gc, Scrollbar* scrollbar, const IntRect& rect, ScrollbarPart partType)
+{
+ bool horz = scrollbar->orientation() == HorizontalScrollbar;
+
+ gfx::PlatformCanvasWin* canvas = gc->platformContext()->canvas();
+ HDC hdc = canvas->beginPlatformPaint();
+
+ RECT paintRect = toRECT(rect);
+
+ int partId;
+ if (partType == BackTrackPart) {
+ partId = horz ? SBP_UPPERTRACKHORZ : SBP_UPPERTRACKVERT;
+ } else {
+ partId = horz ? SBP_LOWERTRACKHORZ : SBP_LOWERTRACKVERT;
+ }
+
+ RECT alignRect = toRECT(trackRect(scrollbar, false));
+
+ // Draw the track area before/after the thumb on the scroll bar.
+ gfx::NativeTheme::instance()->PaintScrollbarTrack(
+ hdc,
+ partId,
+ getThemeState(scrollbar, partType),
+ getClassicThemeState(scrollbar, partType),
+ &paintRect,
+ &alignRect,
+ gc->platformContext()->canvas());
+
+ canvas->endPlatformPaint();
+}
+
+void ScrollbarThemeChromiumWin::paintButton(GraphicsContext* gc, Scrollbar* scrollbar, const IntRect& rect, ScrollbarPart part)
+{
+ bool horz = scrollbar->orientation() == HorizontalScrollbar;
+
+ gfx::PlatformCanvasWin* canvas = gc->platformContext()->canvas();
+ HDC hdc = canvas->beginPlatformPaint();
+
+ RECT paintRect = toRECT(rect);
+
+ int partId;
+ if (part == BackButtonStartPart || part == ForwardButtonStartPart) {
+ partId = horz ? DFCS_SCROLLLEFT : DFCS_SCROLLUP;
+ } else {
+ partId = horz ? DFCS_SCROLLRIGHT : DFCS_SCROLLDOWN;
+ }
+
+ // Draw the thumb (the box you drag in the scroll bar to scroll).
+ gfx::NativeTheme::instance()->PaintScrollbarArrow(
+ hdc,
+ getThemeArrowState(scrollbar, part),
+ partId | getClassicThemeState(scrollbar, part),
+ &paintRect);
+
+ canvas->endPlatformPaint();
+}
+
+void ScrollbarThemeChromiumWin::paintThumb(GraphicsContext* gc, Scrollbar* scrollbar, const IntRect& rect)
+{
+ bool horz = scrollbar->orientation() == HorizontalScrollbar;
+
+ gfx::PlatformCanvasWin* canvas = gc->platformContext()->canvas();
+ HDC hdc = canvas->beginPlatformPaint();
+
+ RECT paintRect = toRECT(rect);
+
+ // Draw the thumb (the box you drag in the scroll bar to scroll).
+ gfx::NativeTheme::instance()->PaintScrollbarThumb(
+ hdc,
+ horz ? SBP_THUMBBTNHORZ : SBP_THUMBBTNVERT,
+ getThemeState(scrollbar, ThumbPart),
+ getClassicThemeState(scrollbar, ThumbPart),
+ &paintRect);
+
+ // Draw the gripper (the three little lines on the thumb).
+ gfx::NativeTheme::instance()->PaintScrollbarThumb(
+ hdc,
+ horz ? SBP_GRIPPERHORZ : SBP_GRIPPERVERT,
+ getThemeState(scrollbar, ThumbPart),
+ getClassicThemeState(scrollbar, ThumbPart),
+ &paintRect);
+
+ canvas->endPlatformPaint();
+}
+
+void ScrollbarThemeChromiumWin::paintScrollCorner(ScrollView* view, GraphicsContext* context, const IntRect& cornerRect)
+{
+ // ScrollbarThemeComposite::paintScrollCorner incorrectly assumes that the
+ // ScrollView is a FrameView (see FramelessScrollView), so we cannot let
+ // that code run. For FrameView's this is correct since we don't do custom
+ // scrollbar corner rendering, which ScrollbarThemeComposite supports.
+ ScrollbarTheme::paintScrollCorner(view, context, cornerRect);
+}
+
+bool ScrollbarThemeChromiumWin::shouldCenterOnThumb(Scrollbar*, const PlatformMouseEvent& evt)
+{
+ return evt.shiftKey() && evt.button() == LeftButton;
+}
+
+IntSize ScrollbarThemeChromiumWin::buttonSize(Scrollbar* scrollbar)
+{
+ // Our desired rect is essentially thickness by thickness.
+
+ // Our actual rect will shrink to half the available space when we have < 2
+ // times thickness pixels left. This allows the scrollbar to scale down
+ // and function even at tiny sizes.
+
+ // In layout test mode, we force the button "girth" (i.e., the length of
+ // the button along the axis of the scrollbar) to be a fixed size.
+ // FIXME: This is retarded! scrollbarThickness is already fixed in layout
+ // test mode so that should be enough to result in repeatable results, but
+ // preserving this hack avoids having to rebaseline pixel tests.
+ const int kLayoutTestModeGirth = 17;
+
+ int thickness = scrollbarThickness();
+ int girth = webkit_glue::IsLayoutTestMode() ? kLayoutTestModeGirth : thickness;
+ if (scrollbar->orientation() == HorizontalScrollbar) {
+ int width = scrollbar->width() < 2 * girth ? scrollbar->width() / 2 : girth;
+ return IntSize(width, thickness);
+ }
+
+ int height = scrollbar->height() < 2 * girth ? scrollbar->height() / 2 : girth;
+ return IntSize(thickness, height);
+}
+
+int ScrollbarThemeChromiumWin::getThemeState(Scrollbar* scrollbar, ScrollbarPart part) 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 (scrollbar->pressedPart() == ThumbPart) {
+ if (part == ThumbPart)
+ return SCRBS_PRESSED;
+ return runningVista() ? SCRBS_HOVER : SCRBS_NORMAL;
+ }
+ if (!scrollbar->enabled())
+ return SCRBS_DISABLED;
+ if (scrollbar->hoveredPart() != part || part == BackTrackPart || part == ForwardTrackPart)
+ return (scrollbar->hoveredPart() == NoPart || !runningVista()) ? SCRBS_NORMAL : SCRBS_HOVER;
+ if (scrollbar->pressedPart() == NoPart)
+ return SCRBS_HOT;
+ return (scrollbar->pressedPart() == part) ? SCRBS_PRESSED : SCRBS_NORMAL;
+}
+
+int ScrollbarThemeChromiumWin::getThemeArrowState(Scrollbar* scrollbar, ScrollbarPart part) 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 (part == BackButtonStartPart || part == ForwardButtonStartPart) {
+ if (scrollbar->orientation() == HorizontalScrollbar) {
+ if (scrollbar->pressedPart() == ThumbPart)
+ return !runningVista() ? ABS_LEFTNORMAL : ABS_LEFTHOVER;
+ if (!scrollbar->enabled())
+ return ABS_LEFTDISABLED;
+ if (scrollbar->hoveredPart() != part)
+ return ((scrollbar->hoveredPart() == NoPart) || !runningVista()) ? ABS_LEFTNORMAL : ABS_LEFTHOVER;
+ if (scrollbar->pressedPart() == NoPart)
+ return ABS_LEFTHOT;
+ return (scrollbar->pressedPart() == part) ?
+ ABS_LEFTPRESSED : ABS_LEFTNORMAL;
+ }
+ if (scrollbar->pressedPart() == ThumbPart)
+ return !runningVista() ? ABS_UPNORMAL : ABS_UPHOVER;
+ if (!scrollbar->enabled())
+ return ABS_UPDISABLED;
+ if (scrollbar->hoveredPart() != part)
+ return ((scrollbar->hoveredPart() == NoPart) || !runningVista()) ? ABS_UPNORMAL : ABS_UPHOVER;
+ if (scrollbar->pressedPart() == NoPart)
+ return ABS_UPHOT;
+ return (scrollbar->pressedPart() == part) ? ABS_UPPRESSED : ABS_UPNORMAL;
+ }
+ if (scrollbar->orientation() == HorizontalScrollbar) {
+ if (scrollbar->pressedPart() == ThumbPart)
+ return !runningVista() ? ABS_RIGHTNORMAL : ABS_RIGHTHOVER;
+ if (!scrollbar->enabled())
+ return ABS_RIGHTDISABLED;
+ if (scrollbar->hoveredPart() != part)
+ return ((scrollbar->hoveredPart() == NoPart) || !runningVista()) ? ABS_RIGHTNORMAL : ABS_RIGHTHOVER;
+ if (scrollbar->pressedPart() == NoPart)
+ return ABS_RIGHTHOT;
+ return (scrollbar->pressedPart() == part) ? ABS_RIGHTPRESSED : ABS_RIGHTNORMAL;
+ }
+ if (scrollbar->pressedPart() == ThumbPart)
+ return !runningVista() ? ABS_DOWNNORMAL : ABS_DOWNHOVER;
+ if (!scrollbar->enabled())
+ return ABS_DOWNDISABLED;
+ if (scrollbar->hoveredPart() != part)
+ return ((scrollbar->hoveredPart() == NoPart) || !runningVista()) ? ABS_DOWNNORMAL : ABS_DOWNHOVER;
+ if (scrollbar->pressedPart() == NoPart)
+ return ABS_DOWNHOT;
+ return (scrollbar->pressedPart() == part) ? ABS_DOWNPRESSED : ABS_DOWNNORMAL;
+}
+
+int ScrollbarThemeChromiumWin::getClassicThemeState(Scrollbar* scrollbar, ScrollbarPart part) const
+{
+ // When dragging the thumb, draw the buttons normal even when hovered.
+ if (scrollbar->pressedPart() == ThumbPart)
+ return 0;
+ if (!scrollbar->enabled())
+ return DFCS_INACTIVE;
+ if (scrollbar->hoveredPart() != part || part == BackTrackPart || part == ForwardTrackPart)
+ return 0;
+ if (scrollbar->pressedPart() == NoPart)
+ return DFCS_HOT;
+ return (scrollbar->pressedPart() == part) ? (DFCS_PUSHED | DFCS_FLAT) : 0;
+}
+
+}