Refactor painting of the native windows scrollbar and prepare for code sharing with the Aqua windows scrollbar.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@36428 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 54a2963..16dd28c 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,55 @@
+2008-09-14 Dave Hyatt <hyatt@apple.com>
+
+ Refactor PlatformScrollbarWin's painting so that it is now done by ScrollbarThemeWin. PlatformScrollbarSafari
+ is still painting itself (a subsequent patch will move its painting into ScrollbarThemeSafari).
+
+ Reviewed by Sam Weinig
+
+ * platform/ScrollBar.h:
+ (WebCore::Scrollbar::client):
+ (WebCore::Scrollbar::currentPos):
+ (WebCore::Scrollbar::totalSize):
+ * platform/ScrollbarTheme.h:
+ * platform/ScrollbarThemeComposite.cpp:
+ (WebCore::pageForScrollView):
+ (WebCore::ScrollbarThemeComposite::paint):
+ * platform/ScrollbarThemeComposite.h:
+ (WebCore::ScrollbarThemeComposite::trackIsSinglePiece):
+ * platform/win/PlatformScrollBar.h:
+ * platform/win/PlatformScrollBarSafari.cpp:
+ * platform/win/PlatformScrollBarWin.cpp:
+ * platform/win/ScrollbarThemeSafari.h:
+ (WebCore::ScrollbarThemeSafari::hasButtons):
+ (WebCore::ScrollbarThemeSafari::hasThumb):
+ (WebCore::ScrollbarThemeSafari::backButtonRect):
+ (WebCore::ScrollbarThemeSafari::forwardButtonRect):
+ (WebCore::ScrollbarThemeSafari::trackRect):
+ (WebCore::ScrollbarThemeSafari::splitTrack):
+ (WebCore::ScrollbarThemeSafari::paintTrack):
+ (WebCore::ScrollbarThemeSafari::paintButton):
+ (WebCore::ScrollbarThemeSafari::paintThumb):
+ * platform/win/ScrollbarThemeWin.cpp:
+ (WebCore::isRunningOnVistaOrLater):
+ (WebCore::checkAndInitScrollbarTheme):
+ (WebCore::ScrollbarThemeWin::ScrollbarThemeWin):
+ (WebCore::ScrollbarThemeWin::themeChanged):
+ (WebCore::ScrollbarThemeWin::hasThumb):
+ (WebCore::ScrollbarThemeWin::backButtonRect):
+ (WebCore::ScrollbarThemeWin::forwardButtonRect):
+ (WebCore::ScrollbarThemeWin::trackRect):
+ (WebCore::ScrollbarThemeWin::splitTrack):
+ (WebCore::ScrollbarThemeWin::paintTrack):
+ (WebCore::ScrollbarThemeWin::paintButton):
+ (WebCore::gripperRect):
+ (WebCore::paintGripper):
+ (WebCore::ScrollbarThemeWin::paintThumb):
+ (WebCore::ScrollbarThemeWin::thumbPosition):
+ (WebCore::ScrollbarThemeWin::thumbLength):
+ (WebCore::ScrollbarThemeWin::trackLength):
+ * platform/win/ScrollbarThemeWin.h:
+ (WebCore::ScrollbarThemeWin::hasButtons):
+ (WebCore::ScrollbarThemeWin::trackIsSinglePiece):
+
2008-09-14 Anthony Ricaud <rik24d@gmail.com>
Moving all resource graphs under the same container for future scalable feature.
diff --git a/WebCore/platform/ScrollBar.h b/WebCore/platform/ScrollBar.h
index d5d1d3e..c7a0a46 100644
--- a/WebCore/platform/ScrollBar.h
+++ b/WebCore/platform/ScrollBar.h
@@ -52,11 +52,14 @@
virtual ~Scrollbar();
void setClient(ScrollbarClient* client) { m_client = client; }
+ ScrollbarClient* client() const { return m_client; }
ScrollbarOrientation orientation() const { return m_orientation; }
int value() const { return lroundf(m_currentPos); }
+ float currentPos() const { return m_currentPos; }
int visibleSize() const { return m_visibleSize; }
+ int totalSize() const { return m_totalSize; }
int maximum() const { return m_totalSize - m_visibleSize; }
ScrollbarControlSize controlSize() const { return m_controlSize; }
@@ -110,8 +113,6 @@
ScrollDirection pressedPartScrollDirection();
ScrollGranularity pressedPartScrollGranularity();
- ScrollbarClient* client() const { return m_client; }
-
ScrollbarClient* m_client;
ScrollbarOrientation m_orientation;
ScrollbarControlSize m_controlSize;
diff --git a/WebCore/platform/ScrollbarTheme.h b/WebCore/platform/ScrollbarTheme.h
index ff20a49..f74e9b0 100755
--- a/WebCore/platform/ScrollbarTheme.h
+++ b/WebCore/platform/ScrollbarTheme.h
@@ -46,7 +46,7 @@
virtual void themeChanged() {}
- static ScrollbarTheme* nativeTheme(); // Must be implemented by the theme subclass.
+ static ScrollbarTheme* nativeTheme(); // Must be implemented to return the correct theme subclass.
};
}
diff --git a/WebCore/platform/ScrollbarThemeComposite.cpp b/WebCore/platform/ScrollbarThemeComposite.cpp
index a45b692..4cdf173 100755
--- a/WebCore/platform/ScrollbarThemeComposite.cpp
+++ b/WebCore/platform/ScrollbarThemeComposite.cpp
@@ -26,11 +26,121 @@
#include "config.h"
#include "ScrollbarThemeComposite.h"
+#include "ChromeClient.h"
+#include "Frame.h"
+#include "FrameView.h"
+#include "GraphicsContext.h"
+#include "Page.h"
+#include "Scrollbar.h"
+#include "ScrollbarClient.h"
+#include "Settings.h"
+
namespace WebCore {
-bool ScrollbarThemeComposite::paint(Scrollbar*, GraphicsContext* context, const IntRect& damageRect)
+static Page* pageForScrollView(ScrollView* view)
{
- return false;
+ if (!view)
+ return 0;
+ if (!view->isFrameView())
+ return 0;
+ FrameView* frameView = static_cast<FrameView*>(view);
+ if (!frameView->frame())
+ return 0;
+ return frameView->frame()->page();
+}
+
+bool ScrollbarThemeComposite::paint(Scrollbar* scrollbar, GraphicsContext* graphicsContext, const IntRect& damageRect)
+{
+ // Create the ScrollbarControlPartMask based on the damageRect
+ ScrollbarControlPartMask scrollMask = NoPart;
+
+ IntRect backButtonPaintRect;
+ IntRect forwardButtonPaintRect;
+ if (hasButtons(scrollbar)) {
+ backButtonPaintRect = backButtonRect(scrollbar, true);
+ if (damageRect.intersects(backButtonPaintRect))
+ scrollMask |= BackButtonPart;
+ forwardButtonPaintRect = forwardButtonRect(scrollbar, true);
+ if (damageRect.intersects(forwardButtonPaintRect))
+ scrollMask |= ForwardButtonPart;
+ }
+
+ IntRect startTrackRect;
+ IntRect thumbRect;
+ IntRect endTrackRect;
+ IntRect trackPaintRect = trackRect(scrollbar, true);
+ bool thumbPresent = hasThumb(scrollbar);
+ if (thumbPresent) {
+ IntRect track = trackRect(scrollbar);
+ splitTrack(scrollbar, track, startTrackRect, thumbRect, endTrackRect);
+ if (damageRect.intersects(thumbRect)) {
+ scrollMask |= ThumbPart;
+ if (trackIsSinglePiece()) {
+ // The track is a single strip that paints under the thumb.
+ // Add both components of the track to the mask.
+ scrollMask |= BackTrackPart;
+ scrollMask |= ForwardTrackPart;
+ }
+ }
+ if (damageRect.intersects(startTrackRect))
+ scrollMask |= BackTrackPart;
+ if (damageRect.intersects(endTrackRect))
+ scrollMask |= ForwardTrackPart;
+ } else if (damageRect.intersects(trackPaintRect)) {
+ scrollMask |= BackTrackPart;
+ scrollMask |= ForwardTrackPart;
+ }
+
+ // FIXME: This API makes the assumption that the custom scrollbar's metrics will match
+ // the theme's metrics. This is not a valid assumption. The ability for a client to paint
+ // custom scrollbars should be removed once scrollbars can be styled via CSS.
+ if (Page* page = pageForScrollView(scrollbar->parent())) {
+ if (page->settings()->shouldPaintCustomScrollbars()) {
+ float proportion = static_cast<float>(scrollbar->visibleSize()) / scrollbar->totalSize();
+ float value = scrollbar->currentPos() / static_cast<float>(scrollbar->maximum());
+ ScrollbarControlState s = 0;
+ if (scrollbar->client()->isActive())
+ s |= ActiveScrollbarState;
+ if (scrollbar->isEnabled())
+ s |= EnabledScrollbarState;
+ if (scrollbar->pressedPart() != NoPart)
+ s |= PressedScrollbarState;
+ if (page->chrome()->client()->paintCustomScrollbar(graphicsContext,
+ scrollbar->frameGeometry(),
+ scrollbar->controlSize(),
+ s,
+ scrollbar->pressedPart(),
+ scrollbar->orientation() == VerticalScrollbar,
+ value,
+ proportion,
+ scrollMask))
+ return true;
+ }
+ }
+
+ // Paint the track.
+ if ((scrollMask & ForwardTrackPart) || (scrollMask & BackTrackPart)) {
+ if (!thumbPresent || trackIsSinglePiece())
+ paintTrack(graphicsContext, scrollbar, trackPaintRect, ForwardTrackPart | BackTrackPart);
+ else {
+ if (scrollMask & BackTrackPart)
+ paintTrack(graphicsContext, scrollbar, startTrackRect, BackTrackPart);
+ if (scrollMask & ForwardTrackPart)
+ paintTrack(graphicsContext, scrollbar, endTrackRect, ForwardTrackPart);
+ }
+ }
+
+ // Paint the back and forward buttons.
+ if (scrollMask & BackButtonPart)
+ paintButton(graphicsContext, scrollbar, backButtonPaintRect, BackButtonPart);
+ if (scrollMask & ForwardButtonPart)
+ paintButton(graphicsContext, scrollbar, forwardButtonPaintRect, ForwardButtonPart);
+
+ // Paint the thumb.
+ if (scrollMask & ThumbPart)
+ paintThumb(graphicsContext, scrollbar, thumbRect);
+
+ return true;
}
}
diff --git a/WebCore/platform/ScrollbarThemeComposite.h b/WebCore/platform/ScrollbarThemeComposite.h
index f8249e4..ae6c010 100755
--- a/WebCore/platform/ScrollbarThemeComposite.h
+++ b/WebCore/platform/ScrollbarThemeComposite.h
@@ -33,6 +33,23 @@
class ScrollbarThemeComposite : public ScrollbarTheme {
public:
virtual bool paint(Scrollbar*, GraphicsContext* context, const IntRect& damageRect);
+
+protected:
+ virtual bool hasButtons(Scrollbar*) = 0;
+ virtual bool hasThumb(Scrollbar*) = 0;
+
+ virtual IntRect backButtonRect(Scrollbar*, bool painting = false) = 0;
+ virtual IntRect forwardButtonRect(Scrollbar*, bool painting = false) = 0;
+ virtual IntRect trackRect(Scrollbar*, bool painting = false) = 0;
+
+ virtual void splitTrack(Scrollbar*, const IntRect& track, IntRect& startTrack, IntRect& thumb, IntRect& endTrack) = 0;
+
+ // Assume the track is a single piece by default.
+ virtual bool trackIsSinglePiece() { return true; }
+
+ virtual void paintTrack(GraphicsContext*, Scrollbar*, const IntRect&, ScrollbarControlPartMask) = 0;
+ virtual void paintButton(GraphicsContext*, Scrollbar*, const IntRect&, ScrollbarControlPartMask) = 0;
+ virtual void paintThumb(GraphicsContext*, Scrollbar*, const IntRect&) = 0;
};
}
diff --git a/WebCore/platform/win/PlatformScrollBar.h b/WebCore/platform/win/PlatformScrollBar.h
index c748794..04f1ac7 100644
--- a/WebCore/platform/win/PlatformScrollBar.h
+++ b/WebCore/platform/win/PlatformScrollBar.h
@@ -68,18 +68,12 @@
IntRect forwardButtonRect() const;
IntRect trackRect() const;
IntRect thumbRect() const;
- IntRect gripperRect(const IntRect& thumbRect) const;
void splitTrack(const IntRect& trackRect, IntRect& beforeThumbRect, IntRect& thumbRect, IntRect& afterThumbRect) const;
int thumbPosition() const;
int thumbLength() const;
int trackLength() const;
-
- void paintButton(GraphicsContext*, const IntRect& buttonRect, bool start, const IntRect& damageRect) const;
- void paintTrack(GraphicsContext*, const IntRect& trackRect, bool start, const IntRect& damageRect) const;
- void paintThumb(GraphicsContext*, const IntRect& thumbRect, const IntRect& damageRect) const;
- void paintGripper(HDC, const IntRect& gripperRect) const;
-
+
ScrollbarPart hitTest(const PlatformMouseEvent&);
bool thumbUnderMouse();
diff --git a/WebCore/platform/win/PlatformScrollBarSafari.cpp b/WebCore/platform/win/PlatformScrollBarSafari.cpp
index a9d706d..f0c8a5f 100644
--- a/WebCore/platform/win/PlatformScrollBarSafari.cpp
+++ b/WebCore/platform/win/PlatformScrollBarSafari.cpp
@@ -551,15 +551,6 @@
return clipRect;
}
-void PlatformScrollbar::paintGripper(HDC hdc, const IntRect& rect) const
-{
-}
-
-IntRect PlatformScrollbar::gripperRect(const IntRect& thumbRect) const
-{
- return IntRect();
-}
-
}
#endif // USE(SAFARI_THEME)
diff --git a/WebCore/platform/win/PlatformScrollBarWin.cpp b/WebCore/platform/win/PlatformScrollBarWin.cpp
index fe0c75f..27dab8e 100644
--- a/WebCore/platform/win/PlatformScrollBarWin.cpp
+++ b/WebCore/platform/win/PlatformScrollBarWin.cpp
@@ -230,39 +230,6 @@
Widget::setParent(parentView);
}
-void PlatformScrollbar::paint(GraphicsContext* graphicsContext, const IntRect& damageRect)
-{
- checkAndInitScrollbarTheme();
-
- // A Windows scrollbar consists of six components:
- // An arrow button, a track piece, a thumb, a gripper inside the thumb, another track piece, and another arrow button.
- // Paint each piece if it intersects the damage rect.
-
- // (1) The first arrow button
- paintButton(graphicsContext, backButtonRect(), true, damageRect);
-
- IntRect rect;
- if (damageRect.intersects(rect = trackRect())) {
- if (isEnabled()) {
- IntRect startTrackRect, thumbRect, endTrackRect;
- splitTrack(rect, startTrackRect, thumbRect, endTrackRect);
-
- // (2) The first track piece
- paintTrack(graphicsContext, startTrackRect, true, damageRect);
-
- // (3) The thumb
- paintThumb(graphicsContext, thumbRect, damageRect);
-
- // (4) The second track piece
- paintTrack(graphicsContext, endTrackRect, false, damageRect);
- } else
- // Just paint a disabled track throughout the track rect.
- paintTrack(graphicsContext, rect, true, damageRect);
- }
-
- // (5) The second arrow button
- paintButton(graphicsContext, forwardButtonRect(), false, damageRect);
-}
bool PlatformScrollbar::hasButtons() const
{
@@ -323,14 +290,6 @@
return thumbRect;
}
-IntRect PlatformScrollbar::gripperRect(const IntRect& thumbRect) const
-{
- // Center in the thumb.
- return IntRect(thumbRect.x() + (thumbRect.width() - cGripperWidth) / 2,
- thumbRect.y() + (thumbRect.height() - cGripperHeight) / 2,
- cGripperWidth, cGripperHeight);
-}
-
void PlatformScrollbar::splitTrack(const IntRect& trackRect, IntRect& beforeThumbRect, IntRect& thumbRect, IntRect& afterThumbRect) const
{
// This function won't even get called unless we're big enough to have some combination of these three rects where at least
@@ -374,153 +333,6 @@
return (m_orientation == HorizontalScrollbar) ? trackRect().width() : trackRect().height();
}
-void PlatformScrollbar::paintButton(GraphicsContext* context, const IntRect& rect, bool start, const IntRect& damageRect) const
-{
- if (!damageRect.intersects(rect))
- return;
-
- int xpState = 0;
- int classicState = 0;
- if (m_orientation == HorizontalScrollbar)
- xpState = start ? TS_LEFT_BUTTON : TS_RIGHT_BUTTON;
- else
- xpState = start ? TS_UP_BUTTON : TS_DOWN_BUTTON;
- classicState = xpState / 4;
-
- if (!isEnabled()) {
- xpState += TS_DISABLED;
- classicState |= DFCS_INACTIVE;
- } else if ((m_hoveredPart == BackButtonPart && start) ||
- (m_hoveredPart == ForwardButtonPart && !start)) {
- if (m_pressedPart == m_hoveredPart) {
- xpState += TS_ACTIVE;
- classicState |= DFCS_PUSHED | DFCS_FLAT;
- } else
- xpState += TS_HOVER;
- } else {
- if (m_hoveredPart == NoPart || !runningVista)
- xpState += TS_NORMAL;
- else {
- if (m_orientation == HorizontalScrollbar)
- xpState = start ? TS_LEFT_BUTTON_HOVER : TS_RIGHT_BUTTON_HOVER;
- else
- xpState = start ? TS_UP_BUTTON_HOVER : TS_DOWN_BUTTON_HOVER;
- }
- }
-
- bool alphaBlend = false;
- if (scrollbarTheme)
- alphaBlend = IsThemeBackgroundPartiallyTransparent(scrollbarTheme, SP_BUTTON, xpState);
- HDC hdc = context->getWindowsContext(rect, alphaBlend);
-
- RECT themeRect(rect);
- if (scrollbarTheme)
- DrawThemeBackground(scrollbarTheme, hdc, SP_BUTTON, xpState, &themeRect, 0);
- else
- ::DrawFrameControl(hdc, &themeRect, DFC_SCROLL, classicState);
- context->releaseWindowsContext(hdc, rect, alphaBlend);
-}
-
-void PlatformScrollbar::paintTrack(GraphicsContext* context, const IntRect& rect, bool start, const IntRect& damageRect) const
-{
- if (!damageRect.intersects(rect))
- return;
-
- int part;
- if (m_orientation == HorizontalScrollbar)
- part = start ? SP_TRACKSTARTHOR : SP_TRACKENDHOR;
- else
- part = start ? SP_TRACKSTARTVERT : SP_TRACKENDVERT;
-
- int state;
- if (!isEnabled())
- state = TS_DISABLED;
- else if ((m_hoveredPart == BackTrackPart && start) ||
- (m_hoveredPart == ForwardTrackPart && !start))
- state = (m_pressedPart == m_hoveredPart ? TS_ACTIVE : TS_HOVER);
- else
- state = TS_NORMAL;
-
- bool alphaBlend = false;
- if (scrollbarTheme)
- alphaBlend = IsThemeBackgroundPartiallyTransparent(scrollbarTheme, part, state);
- HDC hdc = context->getWindowsContext(rect, alphaBlend);
- RECT themeRect(rect);
- if (scrollbarTheme)
- DrawThemeBackground(scrollbarTheme, hdc, part, state, &themeRect, 0);
- else {
- DWORD color3DFace = ::GetSysColor(COLOR_3DFACE);
- DWORD colorScrollbar = ::GetSysColor(COLOR_SCROLLBAR);
- DWORD colorWindow = ::GetSysColor(COLOR_WINDOW);
- if ((color3DFace != colorScrollbar) && (colorWindow != colorScrollbar))
- ::FillRect(hdc, &themeRect, HBRUSH(COLOR_SCROLLBAR+1));
- else {
- static WORD patternBits[8] = { 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55 };
- HBITMAP patternBitmap = ::CreateBitmap(8, 8, 1, 1, patternBits);
- HBRUSH brush = ::CreatePatternBrush(patternBitmap);
- SaveDC(hdc);
- ::SetTextColor(hdc, ::GetSysColor(COLOR_3DHILIGHT));
- ::SetBkColor(hdc, ::GetSysColor(COLOR_3DFACE));
- ::SetBrushOrgEx(hdc, rect.x(), rect.y(), NULL);
- ::SelectObject(hdc, brush);
- ::FillRect(hdc, &themeRect, brush);
- ::RestoreDC(hdc, -1);
- ::DeleteObject(brush);
- ::DeleteObject(patternBitmap);
- }
- }
- context->releaseWindowsContext(hdc, rect, alphaBlend);
-}
-
-void PlatformScrollbar::paintThumb(GraphicsContext* context, const IntRect& rect, const IntRect& damageRect) const
-{
- if (!damageRect.intersects(rect))
- return;
-
- int state;
- if (!isEnabled())
- state = TS_DISABLED;
- else if (m_pressedPart == ThumbPart)
- state = TS_ACTIVE; // Thumb always stays active once pressed.
- else if (m_hoveredPart == ThumbPart)
- state = TS_HOVER;
- else
- state = TS_NORMAL;
-
- bool alphaBlend = false;
- if (scrollbarTheme)
- alphaBlend = IsThemeBackgroundPartiallyTransparent(scrollbarTheme, m_orientation == HorizontalScrollbar ? SP_THUMBHOR : SP_THUMBVERT, state);
- HDC hdc = context->getWindowsContext(rect, alphaBlend);
- RECT themeRect(rect);
- if (scrollbarTheme) {
- DrawThemeBackground(scrollbarTheme, hdc, m_orientation == HorizontalScrollbar ? SP_THUMBHOR : SP_THUMBVERT, state, &themeRect, 0);
- IntRect gripper;
- if (damageRect.intersects(gripper = gripperRect(rect)))
- paintGripper(hdc, gripper);
- } else
- ::DrawEdge(hdc, &themeRect, EDGE_RAISED, BF_RECT | BF_MIDDLE);
- context->releaseWindowsContext(hdc, rect, alphaBlend);
-}
-
-void PlatformScrollbar::paintGripper(HDC hdc, const IntRect& rect) const
-{
- if (!scrollbarTheme)
- return; // Classic look has no gripper.
-
- int state;
- if (!isEnabled())
- state = TS_DISABLED;
- else if (m_pressedPart == ThumbPart)
- state = TS_ACTIVE; // Thumb always stays active once pressed.
- else if (m_hoveredPart == ThumbPart)
- state = TS_HOVER;
- else
- state = TS_NORMAL;
-
- RECT themeRect(rect);
- DrawThemeBackground(scrollbarTheme, hdc, m_orientation == HorizontalScrollbar ? SP_GRIPPERHOR : SP_GRIPPERVERT, state, &themeRect, 0);
-}
-
ScrollbarPart PlatformScrollbar::hitTest(const PlatformMouseEvent& evt)
{
ScrollbarPart result = NoPart;
diff --git a/WebCore/platform/win/ScrollbarThemeSafari.h b/WebCore/platform/win/ScrollbarThemeSafari.h
index 5dc52ab..263dc2a 100755
--- a/WebCore/platform/win/ScrollbarThemeSafari.h
+++ b/WebCore/platform/win/ScrollbarThemeSafari.h
@@ -26,6 +26,8 @@
#ifndef ScrollbarThemeSafari_h
#define ScrollbarThemeSafari_h
+#if USE(SAFARI_THEME)
+
#include "ScrollbarThemeComposite.h"
namespace WebCore {
@@ -37,7 +39,24 @@
virtual int scrollbarThickness(ScrollbarControlSize = RegularScrollbar);
virtual bool supportsControlTints() const { return true; }
+
+protected:
+ // FIXME: Implement the following functions to complete the theme.
+ virtual bool hasButtons(Scrollbar*) { return true; }
+ virtual bool hasThumb(Scrollbar*) { return true; }
+
+ virtual IntRect backButtonRect(Scrollbar*, bool painting = false) { return IntRect(); }
+ virtual IntRect forwardButtonRect(Scrollbar*, bool painting = false) { return IntRect(); }
+ virtual IntRect trackRect(Scrollbar*, bool painting = false) { return IntRect(); }
+
+ virtual void splitTrack(Scrollbar*, const IntRect& track, IntRect& startTrack, IntRect& thumb, IntRect& endTrack) {};
+
+ virtual void paintTrack(GraphicsContext*, Scrollbar*, const IntRect&, ScrollbarControlPartMask) {};
+ virtual void paintButton(GraphicsContext*, Scrollbar*, const IntRect&, ScrollbarControlPartMask) {};
+ virtual void paintThumb(GraphicsContext*, Scrollbar*, const IntRect&) {};
};
}
#endif
+
+#endif
diff --git a/WebCore/platform/win/ScrollbarThemeWin.cpp b/WebCore/platform/win/ScrollbarThemeWin.cpp
index 7c18093..b596b35 100755
--- a/WebCore/platform/win/ScrollbarThemeWin.cpp
+++ b/WebCore/platform/win/ScrollbarThemeWin.cpp
@@ -26,8 +26,74 @@
#include "config.h"
#include "ScrollbarThemeWin.h"
+#include "GraphicsContext.h"
+#include "ScrollBar.h"
+#include "SoftLinking.h"
+
+// Generic state constants
+#define TS_NORMAL 1
+#define TS_HOVER 2
+#define TS_ACTIVE 3
+#define TS_DISABLED 4
+
+#define SP_BUTTON 1
+#define SP_THUMBHOR 2
+#define SP_THUMBVERT 3
+#define SP_TRACKSTARTHOR 4
+#define SP_TRACKENDHOR 5
+#define SP_TRACKSTARTVERT 6
+#define SP_TRACKENDVERT 7
+#define SP_GRIPPERHOR 8
+#define SP_GRIPPERVERT 9
+
+#define TS_UP_BUTTON 0
+#define TS_DOWN_BUTTON 4
+#define TS_LEFT_BUTTON 8
+#define TS_RIGHT_BUTTON 12
+#define TS_UP_BUTTON_HOVER 17
+#define TS_DOWN_BUTTON_HOVER 18
+#define TS_LEFT_BUTTON_HOVER 19
+#define TS_RIGHT_BUTTON_HOVER 20
+
+using namespace std;
+
namespace WebCore {
-
+
+static HANDLE scrollbarTheme;
+static bool haveTheme;
+static bool runningVista;
+
+// FIXME: Refactor the soft-linking code so that it can be shared with RenderThemeWin
+SOFT_LINK_LIBRARY(uxtheme)
+SOFT_LINK(uxtheme, OpenThemeData, HANDLE, WINAPI, (HWND hwnd, LPCWSTR pszClassList), (hwnd, pszClassList))
+SOFT_LINK(uxtheme, CloseThemeData, HRESULT, WINAPI, (HANDLE hTheme), (hTheme))
+SOFT_LINK(uxtheme, DrawThemeBackground, HRESULT, WINAPI, (HANDLE hTheme, HDC hdc, int iPartId, int iStateId, const RECT* pRect, const RECT* pClipRect), (hTheme, hdc, iPartId, iStateId, pRect, pClipRect))
+SOFT_LINK(uxtheme, IsThemeActive, BOOL, WINAPI, (), ())
+SOFT_LINK(uxtheme, IsThemeBackgroundPartiallyTransparent, BOOL, WINAPI, (HANDLE hTheme, int iPartId, int iStateId), (hTheme, iPartId, iStateId))
+
+static bool isRunningOnVistaOrLater()
+{
+ static bool os = false;
+ static bool initialized = false;
+ if (!initialized) {
+ OSVERSIONINFOEX vi = {sizeof(vi), 0};
+ GetVersionEx((OSVERSIONINFO*)&vi);
+
+ // NOTE: This does not work under a debugger - Vista shims Visual Studio,
+ // making it believe it is xpsp2, which is inherited by debugged applications
+ os = vi.dwMajorVersion >= 6;
+ initialized = true;
+ }
+ return os;
+}
+
+static void checkAndInitScrollbarTheme()
+{
+ if (uxthemeLibrary() && !scrollbarTheme)
+ scrollbarTheme = OpenThemeData(0, L"Scrollbar");
+ haveTheme = scrollbarTheme && IsThemeActive();
+}
+
#if !USE(SAFARI_THEME)
ScrollbarTheme* ScrollbarTheme::nativeTheme()
{
@@ -36,6 +102,16 @@
}
#endif
+ScrollbarThemeWin::ScrollbarThemeWin()
+{
+ static bool initialized;
+ if (!initialized) {
+ initialized = true;
+ checkAndInitScrollbarTheme();
+ runningVista = isRunningOnVistaOrLater();
+ }
+}
+
ScrollbarThemeWin::~ScrollbarThemeWin()
{
}
@@ -50,6 +126,254 @@
void ScrollbarThemeWin::themeChanged()
{
+ if (haveTheme)
+ CloseThemeData(scrollbarTheme);
+}
+
+bool ScrollbarThemeWin::hasThumb(Scrollbar* scrollbar)
+{
+ return thumbLength(scrollbar) > 0;
+}
+
+IntRect ScrollbarThemeWin::backButtonRect(Scrollbar* scrollbar, bool)
+{
+ // Our desired rect is essentially 17x17.
+
+ // Our actual rect will shrink to half the available space when
+ // we have < 34 pixels left. This allows the scrollbar
+ // to scale down and function even at tiny sizes.
+ int thickness = scrollbarThickness();
+ if (scrollbar->orientation() == HorizontalScrollbar)
+ return IntRect(scrollbar->x(), scrollbar->y(),
+ scrollbar->width() < 2 * thickness ? scrollbar->width() / 2 : thickness, thickness);
+ return IntRect(scrollbar->x(), scrollbar->y(),
+ thickness, scrollbar->height() < 2 * thickness ? scrollbar->height() / 2 : thickness);
+}
+
+IntRect ScrollbarThemeWin::forwardButtonRect(Scrollbar* scrollbar, bool)
+{
+ // Our desired rect is essentially 17x17.
+
+ // Our actual rect will shrink to half the available space when
+ // we have < 34 pixels left. This allows the scrollbar
+ // to scale down and function even at tiny sizes.
+ int thickness = scrollbarThickness();
+ if (scrollbar->orientation() == HorizontalScrollbar) {
+ int w = scrollbar->width() < 2 * thickness ? scrollbar->width() / 2 : thickness;
+ return IntRect(scrollbar->x() + scrollbar->width() - w, scrollbar->y(), w, thickness);
+ }
+
+ int h = scrollbar->height() < 2 * thickness ? scrollbar->height() / 2 : thickness;
+ return IntRect(scrollbar->x(), scrollbar->y() + scrollbar->height() - h, thickness, h);
+}
+
+IntRect ScrollbarThemeWin::trackRect(Scrollbar* scrollbar, bool)
+{
+ int thickness = scrollbarThickness();
+ if (scrollbar->orientation() == HorizontalScrollbar) {
+ if (scrollbar->width() < 2 * thickness)
+ return IntRect();
+ return IntRect(scrollbar->x() + thickness, scrollbar->y(), scrollbar->width() - 2 * thickness, thickness);
+ }
+ if (scrollbar->height() < 2 * thickness)
+ return IntRect();
+ return IntRect(scrollbar->x(), scrollbar->y() + thickness, thickness, scrollbar->height() - 2 * thickness);
+}
+
+void ScrollbarThemeWin::splitTrack(Scrollbar* scrollbar, const IntRect& trackRect, IntRect& beforeThumbRect, IntRect& thumbRect, IntRect& afterThumbRect)
+{
+ // This function won't even get called unless we're big enough to have some combination of these three rects where at least
+ // one of them is non-empty.
+ int thickness = scrollbarThickness();
+ int thumbPos = thumbPosition(scrollbar);
+ if (scrollbar->orientation() == HorizontalScrollbar) {
+ thumbRect = IntRect(trackRect.x() + thumbPos, trackRect.y() + (trackRect.height() - thickness) / 2, thumbLength(scrollbar), thickness);
+ beforeThumbRect = IntRect(trackRect.x(), trackRect.y(), thumbPos, trackRect.height());
+ afterThumbRect = IntRect(thumbRect.x() + thumbRect.width(), trackRect.y(), trackRect.right() - thumbRect.right(), trackRect.height());
+ } else {
+ thumbRect = IntRect(trackRect.x() + (trackRect.width() - thickness) / 2, trackRect.y() + thumbPos, thickness, thumbLength(scrollbar));
+ beforeThumbRect = IntRect(trackRect.x(), trackRect.y(), trackRect.width(), thumbPos);
+ afterThumbRect = IntRect(trackRect.x(), thumbRect.y() + thumbRect.height(), trackRect.width(), trackRect.bottom() - thumbRect.bottom());
+ }
+}
+
+void ScrollbarThemeWin::paintTrack(GraphicsContext* context, Scrollbar* scrollbar, const IntRect& rect, ScrollbarControlPartMask mask)
+{
+ checkAndInitScrollbarTheme();
+
+ bool start = mask & BackTrackPart;
+ int part;
+ if (scrollbar->orientation() == HorizontalScrollbar)
+ part = start ? SP_TRACKSTARTHOR : SP_TRACKENDHOR;
+ else
+ part = start ? SP_TRACKSTARTVERT : SP_TRACKENDVERT;
+
+ int state;
+ if (!scrollbar->isEnabled())
+ state = TS_DISABLED;
+ else if ((scrollbar->hoveredPart() == BackTrackPart && start) ||
+ (scrollbar->hoveredPart() == ForwardTrackPart && !start))
+ state = (scrollbar->pressedPart() == scrollbar->hoveredPart() ? TS_ACTIVE : TS_HOVER);
+ else
+ state = TS_NORMAL;
+
+ bool alphaBlend = false;
+ if (scrollbarTheme)
+ alphaBlend = IsThemeBackgroundPartiallyTransparent(scrollbarTheme, part, state);
+ HDC hdc = context->getWindowsContext(rect, alphaBlend);
+ RECT themeRect(rect);
+ if (scrollbarTheme)
+ DrawThemeBackground(scrollbarTheme, hdc, part, state, &themeRect, 0);
+ else {
+ DWORD color3DFace = ::GetSysColor(COLOR_3DFACE);
+ DWORD colorScrollbar = ::GetSysColor(COLOR_SCROLLBAR);
+ DWORD colorWindow = ::GetSysColor(COLOR_WINDOW);
+ if ((color3DFace != colorScrollbar) && (colorWindow != colorScrollbar))
+ ::FillRect(hdc, &themeRect, HBRUSH(COLOR_SCROLLBAR+1));
+ else {
+ static WORD patternBits[8] = { 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55 };
+ HBITMAP patternBitmap = ::CreateBitmap(8, 8, 1, 1, patternBits);
+ HBRUSH brush = ::CreatePatternBrush(patternBitmap);
+ SaveDC(hdc);
+ ::SetTextColor(hdc, ::GetSysColor(COLOR_3DHILIGHT));
+ ::SetBkColor(hdc, ::GetSysColor(COLOR_3DFACE));
+ ::SetBrushOrgEx(hdc, rect.x(), rect.y(), NULL);
+ ::SelectObject(hdc, brush);
+ ::FillRect(hdc, &themeRect, brush);
+ ::RestoreDC(hdc, -1);
+ ::DeleteObject(brush);
+ ::DeleteObject(patternBitmap);
+ }
+ }
+ context->releaseWindowsContext(hdc, rect, alphaBlend);
+}
+
+void ScrollbarThemeWin::paintButton(GraphicsContext* context, Scrollbar* scrollbar, const IntRect& rect, ScrollbarControlPartMask mask)
+{
+ checkAndInitScrollbarTheme();
+
+ bool start = mask & BackButtonPart;
+ int xpState = 0;
+ int classicState = 0;
+ if (scrollbar->orientation() == HorizontalScrollbar)
+ xpState = start ? TS_LEFT_BUTTON : TS_RIGHT_BUTTON;
+ else
+ xpState = start ? TS_UP_BUTTON : TS_DOWN_BUTTON;
+ classicState = xpState / 4;
+
+ if (!scrollbar->isEnabled()) {
+ xpState += TS_DISABLED;
+ classicState |= DFCS_INACTIVE;
+ } else if ((scrollbar->hoveredPart() == BackButtonPart && start) ||
+ (scrollbar->hoveredPart() == ForwardButtonPart && !start)) {
+ if (scrollbar->pressedPart() == scrollbar->hoveredPart()) {
+ xpState += TS_ACTIVE;
+ classicState |= DFCS_PUSHED | DFCS_FLAT;
+ } else
+ xpState += TS_HOVER;
+ } else {
+ if (scrollbar->hoveredPart() == NoPart || !runningVista)
+ xpState += TS_NORMAL;
+ else {
+ if (scrollbar->orientation() == HorizontalScrollbar)
+ xpState = start ? TS_LEFT_BUTTON_HOVER : TS_RIGHT_BUTTON_HOVER;
+ else
+ xpState = start ? TS_UP_BUTTON_HOVER : TS_DOWN_BUTTON_HOVER;
+ }
+ }
+
+ bool alphaBlend = false;
+ if (scrollbarTheme)
+ alphaBlend = IsThemeBackgroundPartiallyTransparent(scrollbarTheme, SP_BUTTON, xpState);
+ HDC hdc = context->getWindowsContext(rect, alphaBlend);
+
+ RECT themeRect(rect);
+ if (scrollbarTheme)
+ DrawThemeBackground(scrollbarTheme, hdc, SP_BUTTON, xpState, &themeRect, 0);
+ else
+ ::DrawFrameControl(hdc, &themeRect, DFC_SCROLL, classicState);
+ context->releaseWindowsContext(hdc, rect, alphaBlend);
+}
+
+static IntRect gripperRect(int thickness, const IntRect& thumbRect)
+{
+ // Center in the thumb.
+ int gripperThickness = thickness / 2;
+ return IntRect(thumbRect.x() + (thumbRect.width() - gripperThickness) / 2,
+ thumbRect.y() + (thumbRect.height() - gripperThickness) / 2,
+ gripperThickness, gripperThickness);
+}
+
+static void paintGripper(Scrollbar* scrollbar, HDC hdc, const IntRect& rect)
+{
+ if (!scrollbarTheme)
+ return; // Classic look has no gripper.
+
+ int state;
+ if (!scrollbar->isEnabled())
+ state = TS_DISABLED;
+ else if (scrollbar->pressedPart() == ThumbPart)
+ state = TS_ACTIVE; // Thumb always stays active once pressed.
+ else if (scrollbar->hoveredPart() == ThumbPart)
+ state = TS_HOVER;
+ else
+ state = TS_NORMAL;
+
+ RECT themeRect(rect);
+ DrawThemeBackground(scrollbarTheme, hdc, scrollbar->orientation() == HorizontalScrollbar ? SP_GRIPPERHOR : SP_GRIPPERVERT, state, &themeRect, 0);
+}
+
+void ScrollbarThemeWin::paintThumb(GraphicsContext* context, Scrollbar* scrollbar, const IntRect& rect)
+{
+ checkAndInitScrollbarTheme();
+
+ int state;
+ if (!scrollbar->isEnabled())
+ state = TS_DISABLED;
+ else if (scrollbar->pressedPart() == ThumbPart)
+ state = TS_ACTIVE; // Thumb always stays active once pressed.
+ else if (scrollbar->hoveredPart() == ThumbPart)
+ state = TS_HOVER;
+ else
+ state = TS_NORMAL;
+
+ bool alphaBlend = false;
+ if (scrollbarTheme)
+ alphaBlend = IsThemeBackgroundPartiallyTransparent(scrollbarTheme, scrollbar->orientation() == HorizontalScrollbar ? SP_THUMBHOR : SP_THUMBVERT, state);
+ HDC hdc = context->getWindowsContext(rect, alphaBlend);
+ RECT themeRect(rect);
+ if (scrollbarTheme) {
+ DrawThemeBackground(scrollbarTheme, hdc, scrollbar->orientation() == HorizontalScrollbar ? SP_THUMBHOR : SP_THUMBVERT, state, &themeRect, 0);
+ paintGripper(scrollbar, hdc, gripperRect(scrollbarThickness(), rect));
+ } else
+ ::DrawEdge(hdc, &themeRect, EDGE_RAISED, BF_RECT | BF_MIDDLE);
+ context->releaseWindowsContext(hdc, rect, alphaBlend);
+}
+
+int ScrollbarThemeWin::thumbPosition(Scrollbar* scrollbar)
+{
+ if (scrollbar->isEnabled())
+ return scrollbar->currentPos() * (trackLength(scrollbar) - thumbLength(scrollbar)) / scrollbar->maximum();
+ return 0;
+}
+
+int ScrollbarThemeWin::thumbLength(Scrollbar* scrollbar)
+{
+ if (!scrollbar->isEnabled())
+ return 0;
+ float proportion = (float)(scrollbar->visibleSize()) / scrollbar->totalSize();
+ int trackLen = trackLength(scrollbar);
+ int length = proportion * trackLen;
+ int minLength = (scrollbar->orientation() == HorizontalScrollbar) ? scrollbarThickness() : scrollbarThickness();
+ length = max(length, minLength);
+ if (length > trackLen)
+ length = 0; // Once the thumb is below the track length, it just goes away (to make more room for the track).
+ return length;
+}
+
+int ScrollbarThemeWin::trackLength(Scrollbar* scrollbar)
+{
+ return (scrollbar->orientation() == HorizontalScrollbar) ? trackRect(scrollbar).width() : trackRect(scrollbar).height();
}
}
diff --git a/WebCore/platform/win/ScrollbarThemeWin.h b/WebCore/platform/win/ScrollbarThemeWin.h
index 372235c..d99c2d4 100755
--- a/WebCore/platform/win/ScrollbarThemeWin.h
+++ b/WebCore/platform/win/ScrollbarThemeWin.h
@@ -32,11 +32,34 @@
class ScrollbarThemeWin : public ScrollbarThemeComposite {
public:
+ ScrollbarThemeWin();
virtual ~ScrollbarThemeWin();
virtual int scrollbarThickness(ScrollbarControlSize = RegularScrollbar);
virtual void themeChanged();
+
+protected:
+ virtual bool hasButtons(Scrollbar*) { return true; }
+ virtual bool hasThumb(Scrollbar*);
+
+ virtual IntRect backButtonRect(Scrollbar*, bool painting = false);
+ virtual IntRect forwardButtonRect(Scrollbar*, bool painting = false);
+ virtual IntRect trackRect(Scrollbar*, bool painting = false);
+
+ virtual void splitTrack(Scrollbar*, const IntRect& track, IntRect& startTrack, IntRect& thumb, IntRect& endTrack);
+
+ virtual bool trackIsSinglePiece() { return false; }
+
+ virtual void paintTrack(GraphicsContext*, Scrollbar*, const IntRect&, ScrollbarControlPartMask);
+ virtual void paintButton(GraphicsContext*, Scrollbar*, const IntRect&, ScrollbarControlPartMask);
+ virtual void paintThumb(GraphicsContext*, Scrollbar*, const IntRect&);
+
+private:
+ int thumbPosition(Scrollbar*);
+ int thumbLength(Scrollbar*);
+ int trackLength(Scrollbar*);
+
};
}