Backed out changeset 1840b15583fd (bug 636564) for bustage.

CLOSED TREE
This commit is contained in:
Ryan VanderMeulen 2013-05-02 08:33:54 -04:00
parent a446620df6
commit a213f7964d
21 changed files with 147 additions and 689 deletions

View File

@ -27,7 +27,7 @@
style="margin: 0; padding: 0; border: 0;"/>
</vbox>
<vbox id="scrollbox-test">
<scrollbar orient="vertical" style="border: 0; padding: 0;"/>
<scrollbar orient="vertical" style="margin: 0; border: 0; padding: 0;"/>
</vbox>
</hbox>
</vbox>

View File

@ -4,260 +4,35 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ScrollbarActivity.h"
#include "nsIScrollbarOwner.h"
#include "nsIDOMEvent.h"
#include "nsIDOMNSEvent.h"
#include "nsIDOMElementCSSInlineStyle.h"
#include "nsIDOMCSSStyleDeclaration.h"
#include "nsIFrame.h"
#include "nsContentUtils.h"
#include "nsAString.h"
#include "nsQueryFrame.h"
#include "nsIFrame.h"
#include "nsIScrollableFrame.h"
#include "nsComponentManagerUtils.h"
namespace mozilla {
namespace layout {
NS_IMPL_ISUPPORTS1(ScrollbarActivity, nsIDOMEventListener)
void
ScrollbarActivity::Destroy()
ScrollbarActivity::~ScrollbarActivity()
{
StopListeningForEvents();
UnregisterFromRefreshDriver();
CancelFadeBeginTimer();
CancelActivityFinishedTimer();
}
void
ScrollbarActivity::ActivityOccurred()
{
ActivityStarted();
ActivityStopped();
}
CancelActivityFinishedTimer();
StartActivityFinishedTimer();
void
ScrollbarActivity::ActivityStarted()
{
mNestedActivityCounter++;
CancelFadeBeginTimer();
SetIsFading(false);
UnregisterFromRefreshDriver();
StartListeningForEvents();
SetIsActive(true);
NS_ASSERTION(mIsActive, "need to be active during activity");
NS_ASSERTION(!mIsFading, "must not be fading during activity");
NS_ASSERTION(!mFadeBeginTimer, "fade begin timer shouldn't be running");
}
void
ScrollbarActivity::ActivityStopped()
ScrollbarActivity::ActivityFinished()
{
NS_ASSERTION(IsActivityOngoing(), "activity stopped while none was going on");
NS_ASSERTION(mIsActive, "need to be active during activity");
NS_ASSERTION(!mIsFading, "must not be fading during ongoing activity");
NS_ASSERTION(!mFadeBeginTimer, "must not be waiting for fade during ongoing activity");
mNestedActivityCounter--;
if (!IsActivityOngoing()) {
StartFadeBeginTimer();
NS_ASSERTION(mIsActive, "need to be active right after activity");
NS_ASSERTION(!mIsFading, "must not be fading right after activity");
NS_ASSERTION(mFadeBeginTimer, "fade begin timer should be running");
}
}
NS_IMETHODIMP
ScrollbarActivity::HandleEvent(nsIDOMEvent* aEvent)
{
if (!mIsActive)
return NS_OK;
nsAutoString type;
aEvent->GetType(type);
if (type.EqualsLiteral("mousemove")) {
// Mouse motions anywhere in the scrollable frame should keep the
// scrollbars visible.
ActivityOccurred();
return NS_OK;
}
nsCOMPtr<nsIDOMEventTarget> target;
aEvent->GetOriginalTarget(getter_AddRefs(target));
nsCOMPtr<nsIContent> targetContent = do_QueryInterface(target);
HandleEventForScrollbar(type, targetContent, GetHorizontalScrollbar(),
&mHScrollbarHovered);
HandleEventForScrollbar(type, targetContent, GetVerticalScrollbar(),
&mVScrollbarHovered);
return NS_OK;
}
void
ScrollbarActivity::WillRefresh(TimeStamp aTime)
{
NS_ASSERTION(mIsActive, "should only fade while scrollbars are visible");
NS_ASSERTION(!IsActivityOngoing(), "why weren't we unregistered from the refresh driver when scrollbar activity started?");
NS_ASSERTION(mIsFading, "should only animate fading during fade");
UpdateOpacity(aTime);
if (!IsStillFading(aTime)) {
EndFade();
}
}
bool
ScrollbarActivity::IsStillFading(TimeStamp aTime)
{
return !mFadeBeginTime.IsNull() && (aTime - mFadeBeginTime < FadeDuration());
}
void
ScrollbarActivity::HandleEventForScrollbar(const nsAString& aType,
nsIContent* aTarget,
nsIContent* aScrollbar,
bool* aStoredHoverState)
{
if (!aTarget || !aScrollbar ||
!nsContentUtils::ContentIsDescendantOf(aTarget, aScrollbar))
return;
if (aType.EqualsLiteral("mousedown")) {
ActivityStarted();
} else if (aType.EqualsLiteral("mouseup")) {
ActivityStopped();
} else if (aType.EqualsLiteral("mouseover") ||
aType.EqualsLiteral("mouseout")) {
bool newHoveredState = aType.EqualsLiteral("mouseover");
if (newHoveredState && !*aStoredHoverState) {
ActivityStarted();
HoveredScrollbar(aScrollbar);
} else if (*aStoredHoverState && !newHoveredState) {
ActivityStopped();
// Don't call HoveredScrollbar(nullptr) here because we want the hover
// attribute to stick until the scrollbars are hidden.
}
*aStoredHoverState = newHoveredState;
}
}
void
ScrollbarActivity::StartListeningForEvents()
{
if (mListeningForEvents)
return;
nsIFrame* scrollArea = do_QueryFrame(mScrollableFrame);
nsCOMPtr<nsIDOMEventTarget> scrollAreaTarget = do_QueryInterface(
scrollArea->GetContent());
mHorizontalScrollbar = do_QueryInterface(GetHorizontalScrollbar());
mVerticalScrollbar = do_QueryInterface(GetVerticalScrollbar());
if (scrollAreaTarget) {
scrollAreaTarget->AddEventListener(NS_LITERAL_STRING("mousemove"), this,
true);
}
StartListeningForEventsOnScrollbar(mHorizontalScrollbar);
StartListeningForEventsOnScrollbar(mVerticalScrollbar);
mListeningForEvents = true;
}
void
ScrollbarActivity::StartListeningForEventsOnScrollbar(nsIDOMEventTarget* aScrollbar)
{
if (aScrollbar) {
aScrollbar->AddEventListener(NS_LITERAL_STRING("mousedown"), this, true);
aScrollbar->AddEventListener(NS_LITERAL_STRING("mouseup"), this, true);
aScrollbar->AddEventListener(NS_LITERAL_STRING("mouseover"), this, true);
aScrollbar->AddEventListener(NS_LITERAL_STRING("mouseout"), this, true);
}
}
void
ScrollbarActivity::StopListeningForEvents()
{
if (!mListeningForEvents)
return;
nsIFrame* scrollArea = do_QueryFrame(mScrollableFrame);
nsCOMPtr<nsIDOMEventTarget> scrollAreaTarget = do_QueryInterface(scrollArea->GetContent());
if (scrollAreaTarget) {
scrollAreaTarget->RemoveEventListener(NS_LITERAL_STRING("mousemove"), this, true);
}
StopListeningForEventsOnScrollbar(mHorizontalScrollbar);
StopListeningForEventsOnScrollbar(mVerticalScrollbar);
mHorizontalScrollbar = nullptr;
mVerticalScrollbar = nullptr;
mListeningForEvents = false;
}
void
ScrollbarActivity::StopListeningForEventsOnScrollbar(nsIDOMEventTarget* aScrollbar)
{
if (aScrollbar) {
aScrollbar->RemoveEventListener(NS_LITERAL_STRING("mousedown"), this, true);
aScrollbar->RemoveEventListener(NS_LITERAL_STRING("mouseup"), this, true);
aScrollbar->RemoveEventListener(NS_LITERAL_STRING("mouseover"), this, true);
aScrollbar->RemoveEventListener(NS_LITERAL_STRING("mouseout"), this, true);
}
}
void
ScrollbarActivity::BeginFade()
{
NS_ASSERTION(mIsActive, "can't begin fade when we're already inactive");
NS_ASSERTION(!IsActivityOngoing(), "why wasn't the fade begin timer cancelled when scrollbar activity started?");
NS_ASSERTION(!mIsFading, "shouldn't be fading just yet");
CancelFadeBeginTimer();
mFadeBeginTime = TimeStamp::Now();
SetIsFading(true);
RegisterWithRefreshDriver();
NS_ASSERTION(mIsActive, "only fade while scrollbars are visible");
NS_ASSERTION(mIsFading, "should be fading now");
}
void
ScrollbarActivity::EndFade()
{
NS_ASSERTION(mIsActive, "still need to be active at this point");
NS_ASSERTION(!IsActivityOngoing(), "why wasn't the fade end timer cancelled when scrollbar activity started?");
SetIsFading(false);
SetIsActive(false);
UnregisterFromRefreshDriver();
StopListeningForEvents();
NS_ASSERTION(!mIsActive, "should have gone inactive after fade end");
NS_ASSERTION(!mIsFading, "shouldn't be fading anymore");
NS_ASSERTION(!mFadeBeginTimer, "fade begin timer shouldn't be running");
NS_ASSERTION(!mIsActive, "need to be unactive once activity is finished");
}
void
ScrollbarActivity::RegisterWithRefreshDriver()
{
nsRefreshDriver* refreshDriver = GetRefreshDriver();
if (refreshDriver) {
refreshDriver->AddRefreshObserver(this, Flush_Style);
}
}
void
ScrollbarActivity::UnregisterFromRefreshDriver()
{
nsRefreshDriver* refreshDriver = GetRefreshDriver();
if (refreshDriver) {
refreshDriver->RemoveRefreshObserver(this, Flush_Style);
}
}
static void
SetBooleanAttribute(nsIContent* aContent, nsIAtom* aAttribute, bool aValue)
@ -277,114 +52,38 @@ ScrollbarActivity::SetIsActive(bool aNewActive)
{
if (mIsActive == aNewActive)
return;
mIsActive = aNewActive;
if (!mIsActive) {
// Clear sticky scrollbar hover status.
HoveredScrollbar(nullptr);
}
SetBooleanAttribute(GetHorizontalScrollbar(), nsGkAtoms::active, mIsActive);
SetBooleanAttribute(GetVerticalScrollbar(), nsGkAtoms::active, mIsActive);
}
static void
SetOpacityOnElement(nsIContent* aContent, double aOpacity)
void
ScrollbarActivity::StartActivityFinishedTimer()
{
nsCOMPtr<nsIDOMElementCSSInlineStyle> inlineStyleContent =
do_QueryInterface(aContent);
if (inlineStyleContent) {
nsCOMPtr<nsIDOMCSSStyleDeclaration> decl;
inlineStyleContent->GetStyle(getter_AddRefs(decl));
if (decl) {
nsAutoString str;
str.AppendFloat(aOpacity);
decl->SetProperty(NS_LITERAL_STRING("opacity"), str, EmptyString());
}
}
NS_ASSERTION(!mActivityFinishedTimer, "timer already alive!");
mActivityFinishedTimer = do_CreateInstance("@mozilla.org/timer;1");
mActivityFinishedTimer->InitWithFuncCallback(ActivityFinishedTimerFired, this,
kScrollbarActivityFinishedDelay,
nsITimer::TYPE_ONE_SHOT);
}
void
ScrollbarActivity::UpdateOpacity(TimeStamp aTime)
ScrollbarActivity::CancelActivityFinishedTimer()
{
double progress = (aTime - mFadeBeginTime) / FadeDuration();
double opacity = 1.0 - std::max(0.0, std::min(1.0, progress));
SetOpacityOnElement(GetHorizontalScrollbar(), opacity);
SetOpacityOnElement(GetVerticalScrollbar(), opacity);
}
static void
UnsetOpacityOnElement(nsIContent* aContent)
{
nsCOMPtr<nsIDOMElementCSSInlineStyle> inlineStyleContent =
do_QueryInterface(aContent);
if (inlineStyleContent) {
nsCOMPtr<nsIDOMCSSStyleDeclaration> decl;
inlineStyleContent->GetStyle(getter_AddRefs(decl));
if (decl) {
nsAutoString dummy;
decl->RemoveProperty(NS_LITERAL_STRING("opacity"), dummy);
}
if (mActivityFinishedTimer) {
mActivityFinishedTimer->Cancel();
mActivityFinishedTimer = nullptr;
}
}
void
ScrollbarActivity::SetIsFading(bool aNewFading)
{
if (mIsFading == aNewFading)
return;
mIsFading = aNewFading;
if (!mIsFading) {
mFadeBeginTime = TimeStamp();
UnsetOpacityOnElement(GetHorizontalScrollbar());
UnsetOpacityOnElement(GetVerticalScrollbar());
}
}
void
ScrollbarActivity::StartFadeBeginTimer()
{
NS_ASSERTION(!mFadeBeginTimer, "timer already alive!");
mFadeBeginTimer = do_CreateInstance("@mozilla.org/timer;1");
mFadeBeginTimer->InitWithFuncCallback(FadeBeginTimerFired, this,
kScrollbarFadeBeginDelay,
nsITimer::TYPE_ONE_SHOT);
}
void
ScrollbarActivity::CancelFadeBeginTimer()
{
if (mFadeBeginTimer) {
mFadeBeginTimer->Cancel();
mFadeBeginTimer = nullptr;
}
}
void
ScrollbarActivity::HoveredScrollbar(nsIContent* aScrollbar)
{
SetBooleanAttribute(GetHorizontalScrollbar(), nsGkAtoms::hover, false);
SetBooleanAttribute(GetVerticalScrollbar(), nsGkAtoms::hover, false);
SetBooleanAttribute(aScrollbar, nsGkAtoms::hover, true);
}
nsRefreshDriver*
ScrollbarActivity::GetRefreshDriver()
{
nsIFrame* box = mScrollableFrame->GetScrollbarBox(false);
if (!box) {
box = mScrollableFrame->GetScrollbarBox(true);
}
return box ? box->PresContext()->RefreshDriver() : nullptr;
}
nsIContent*
ScrollbarActivity::GetScrollbarContent(bool aVertical)
{
nsIFrame* box = mScrollableFrame->GetScrollbarBox(aVertical);
return box ? box->GetContent() : nullptr;
return nullptr;
}
} // namespace layout
} // namespace mozilla

View File

@ -7,138 +7,82 @@
#define ScrollbarActivity_h___
#include "nsCOMPtr.h"
#include "nsIDOMEventListener.h"
#include "mozilla/TimeStamp.h"
#include "nsRefreshDriver.h"
class nsIContent;
class nsIScrollbarOwner;
class nsITimer;
class nsIAtom;
class nsIScrollableFrame;
namespace mozilla {
namespace layout {
/**
* ScrollbarActivity
*
* This class manages scrollbar behavior that imitates the native Mac OS X
* Lion overlay scrollbar behavior: Scrollbars are only shown while "scrollbar
* activity" occurs, and they're hidden with a fade animation after a short
* delay.
* This class manages scrollbar active state. When some activity occured
* the 'active' attribute of the both the horizontal scrollbar and vertical
* scrollbar is set.
* After a small amount of time of inactivity this attribute is unset from
* both scrollbars.
* Some css specific rules can affect the scrollbar, like showing/hiding it
* with a fade transition.
*
* Scrollbar activity has these states:
* - inactive:
* Scrollbars are hidden.
* - ongoing activity:
* Scrollbars are visible and being operated on in some way, for example
* because they're hovered or pressed.
* - active, but waiting for fade out
* Scrollbars are still completely visible but are about to fade away.
* - fading out
* Scrollbars are subject to a fade-out animation.
*
* Initial scrollbar activity needs to be reported by the scrollbar holder that
* Initial scrollbar activity needs to be reported by the scrollbar frame that
* owns the ScrollbarActivity instance. This needs to happen via a call to
* ActivityOccurred(), for example when the current scroll position or the size
* of the scroll area changes.
*
* As soon as scrollbars are visible, the ScrollbarActivity class manages the
* rest of the activity behavior: It ensures that mouse motions inside the
* scroll area keep the scrollbars visible, and that scrollbars don't fade away
* while they're being hovered / dragged. It also sets a sticky hover attribute
* on the most recently hovered scrollbar.
*
* ScrollbarActivity falls into hibernation after the scrollbars have faded
* out. It only starts acting after the next call to ActivityOccurred() /
* ActivityStarted().
* ScrollbarActivity then wait until a timeout has expired or a new call to
* ActivityOccured() has been made. When the timeout expires ActivityFinished()
* is call and reset the active state.
*/
class ScrollbarActivity : public nsIDOMEventListener,
public nsARefreshObserver {
class ScrollbarActivity {
public:
ScrollbarActivity(nsIScrollbarOwner* aScrollableFrame)
: mScrollableFrame(aScrollableFrame)
, mNestedActivityCounter(0)
, mIsActive(false)
, mIsFading(false)
, mListeningForEvents(false)
, mHScrollbarHovered(false)
, mVScrollbarHovered(false)
ScrollbarActivity(nsIScrollableFrame* aScrollableFrame)
: mIsActive(false)
, mScrollableFrame(aScrollableFrame)
{}
NS_DECL_ISUPPORTS
NS_DECL_NSIDOMEVENTLISTENER
virtual ~ScrollbarActivity() {}
void Destroy();
void ActivityOccurred();
void ActivityStarted();
void ActivityStopped();
virtual void WillRefresh(TimeStamp aTime);
static void FadeBeginTimerFired(nsITimer* aTimer, void* aSelf) {
reinterpret_cast<ScrollbarActivity*>(aSelf)->BeginFade();
}
static const uint32_t kScrollbarFadeBeginDelay = 450; // milliseconds
static const uint32_t kScrollbarFadeDuration = 200; // milliseconds
void ActivityFinished();
~ScrollbarActivity();
protected:
/*
* mIsActive is true once any type of activity occurent on the scrollable
* frame and until kScrollbarActivityFinishedDelay has expired.
* This does not reflect the value of the 'active' attributes on scrollbars.
*/
bool mIsActive;
bool IsActivityOngoing()
{ return mNestedActivityCounter > 0; }
bool IsStillFading(TimeStamp aTime);
/*
* Hold a reference to the scrollable frame in order to retrieve the
* horizontal and vertical scrollbar boxes where to set the 'active'
* attribute.
*/
nsIScrollableFrame* mScrollableFrame;
void HandleEventForScrollbar(const nsAString& aType,
nsIContent* aTarget,
nsIContent* aScrollbar,
bool* aStoredHoverState);
nsCOMPtr<nsITimer> mActivityFinishedTimer;
void SetIsActive(bool aNewActive);
void SetIsFading(bool aNewFading);
void BeginFade();
void EndFade();
void StartFadeBeginTimer();
void CancelFadeBeginTimer();
void StartListeningForEvents();
void StartListeningForEventsOnScrollbar(nsIDOMEventTarget* aScrollbar);
void StopListeningForEvents();
void StopListeningForEventsOnScrollbar(nsIDOMEventTarget* aScrollbar);
void RegisterWithRefreshDriver();
void UnregisterFromRefreshDriver();
void UpdateOpacity(TimeStamp aTime);
void HoveredScrollbar(nsIContent* aScrollbar);
nsRefreshDriver* GetRefreshDriver();
nsIContent* GetScrollbarContent(bool aVertical);
nsIContent* GetHorizontalScrollbar() { return GetScrollbarContent(false); }
nsIContent* GetVerticalScrollbar() { return GetScrollbarContent(true); }
static const TimeDuration FadeDuration() {
return TimeDuration::FromMilliseconds(kScrollbarFadeDuration);
enum { kScrollbarActivityFinishedDelay = 450 }; // milliseconds
static void ActivityFinishedTimerFired(nsITimer* aTimer, void* aSelf) {
reinterpret_cast<ScrollbarActivity*>(aSelf)->ActivityFinished();
}
void StartActivityFinishedTimer();
void CancelActivityFinishedTimer();
nsIScrollbarOwner* mScrollableFrame;
TimeStamp mFadeBeginTime;
nsCOMPtr<nsITimer> mFadeBeginTimer;
nsCOMPtr<nsIDOMEventTarget> mHorizontalScrollbar; // null while inactive
nsCOMPtr<nsIDOMEventTarget> mVerticalScrollbar; // null while inactive
int mNestedActivityCounter;
bool mIsActive;
bool mIsFading;
bool mListeningForEvents;
bool mHScrollbarHovered;
bool mVScrollbarHovered;
nsIContent* GetScrollbarContent(bool aVertical);
nsIContent* GetHorizontalScrollbar() {
return GetScrollbarContent(false);
}
nsIContent* GetVerticalScrollbar() {
return GetScrollbarContent(true);
}
};
} // namespace layout
} // namespace mozilla
#endif /* ScrollbarActivity_h___ */

View File

@ -25,7 +25,6 @@ EXPORTS += [
'nsIObjectFrame.h',
'nsIPageSequenceFrame.h',
'nsIScrollableFrame.h',
'nsIScrollbarOwner.h',
'nsIStatefulFrame.h',
'nsObjectFrame.h',
'nsQueryFrame.h',

View File

@ -55,7 +55,6 @@ FRAME_ID(nsISVGGlyphFragmentNode)
FRAME_ID(nsISVGSVGFrame)
FRAME_ID(nsIScrollableFrame)
FRAME_ID(nsIScrollbarMediator)
FRAME_ID(nsIScrollbarOwner)
FRAME_ID(nsISelectControlFrame)
FRAME_ID(nsIStatefulFrame)
FRAME_ID(nsITableCellLayout)

View File

@ -60,7 +60,6 @@
using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::layout;
//----------------------------------------------------------------------
@ -226,23 +225,11 @@ GetScrollbarMetrics(nsBoxLayoutState& aState, nsIFrame* aBox, nsSize* aMin,
if (aMin) {
*aMin = aBox->GetMinSize(aState);
nsBox::AddMargin(aBox, *aMin);
if (aMin->width < 0) {
aMin->width = 0;
}
if (aMin->height < 0) {
aMin->height = 0;
}
}
if (aPref) {
*aPref = aBox->GetPrefSize(aState);
nsBox::AddMargin(aBox, *aPref);
if (aPref->width < 0) {
aPref->width = 0;
}
if (aPref->height < 0) {
aPref->height = 0;
}
}
}
@ -881,7 +868,6 @@ nsHTMLScrollFrame::AccessibleType()
NS_QUERYFRAME_HEAD(nsHTMLScrollFrame)
NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator)
NS_QUERYFRAME_ENTRY(nsIScrollbarOwner)
NS_QUERYFRAME_ENTRY(nsIScrollableFrame)
NS_QUERYFRAME_ENTRY(nsIStatefulFrame)
NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
@ -1129,7 +1115,6 @@ nsXULScrollFrame::DoLayout(nsBoxLayoutState& aState)
NS_QUERYFRAME_HEAD(nsXULScrollFrame)
NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator)
NS_QUERYFRAME_ENTRY(nsIScrollbarOwner)
NS_QUERYFRAME_ENTRY(nsIScrollableFrame)
NS_QUERYFRAME_ENTRY(nsIStatefulFrame)
NS_QUERYFRAME_TAIL_INHERITING(nsBoxFrame)
@ -1482,7 +1467,7 @@ nsGfxScrollFrameInner::nsGfxScrollFrameInner(nsContainerFrame* aOuter,
{
mScrollingActive = IsAlwaysActive();
if (LookAndFeel::GetInt(LookAndFeel::eIntID_UseOverlayScrollbars) != 0) {
if (LookAndFeel::GetInt(LookAndFeel::eIntID_ShowHideScrollbars) != 0) {
mScrollbarActivity = new ScrollbarActivity(do_QueryFrame(aOuter));
}
}
@ -2836,7 +2821,6 @@ void
nsGfxScrollFrameInner::Destroy()
{
if (mScrollbarActivity) {
mScrollbarActivity->Destroy();
mScrollbarActivity = nullptr;
}
@ -3618,26 +3602,6 @@ nsGfxScrollFrameInner::AdjustScrollbarRectForResizer(
aRect.width = std::max(0, resizerRect.x - aRect.x);
}
static void
AdjustOverlappingScrollbars(nsRect& aVRect, nsRect& aHRect)
{
if (aVRect.IsEmpty() || aHRect.IsEmpty())
return;
const nsRect oldVRect = aVRect;
const nsRect oldHRect = aHRect;
if (oldVRect.Contains(oldHRect.BottomRight() - nsPoint(1, 1))) {
aHRect.width = std::max(0, oldVRect.x - oldHRect.x);
} else if (oldVRect.Contains(oldHRect.BottomLeft() - nsPoint(0, 1))) {
nscoord overlap = std::min(oldHRect.width, oldVRect.XMost() - oldHRect.x);
aHRect.x += overlap;
aHRect.width -= overlap;
}
if (oldHRect.Contains(oldVRect.BottomRight() - nsPoint(1, 1))) {
aVRect.height = std::max(0, oldHRect.y - oldVRect.y);
}
}
void
nsGfxScrollFrameInner::LayoutScrollbars(nsBoxLayoutState& aState,
const nsRect& aContentArea,
@ -3680,21 +3644,22 @@ nsGfxScrollFrameInner::LayoutScrollbars(nsBoxLayoutState& aState,
if (hasResizer) {
// if a resizer is present, get its size. Assume a default size of 15 pixels.
nsSize resizerSize;
nscoord defaultSize = nsPresContext::CSSPixelsToAppUnits(15);
nsSize resizerMinSize = mResizerBox->GetMinSize(aState);
nscoord vScrollbarWidth = mVScrollbarBox ?
resizerSize.width = mVScrollbarBox ?
mVScrollbarBox->GetPrefSize(aState).width : defaultSize;
r.width = std::max(std::max(r.width, vScrollbarWidth), resizerMinSize.width);
if (aContentArea.x == mScrollPort.x && !scrollbarOnLeft) {
r.x = aContentArea.XMost() - r.width;
if (resizerSize.width > r.width) {
r.width = resizerSize.width;
if (aContentArea.x == mScrollPort.x && !scrollbarOnLeft)
r.x = aContentArea.XMost() - r.width;
}
nscoord hScrollbarHeight = mHScrollbarBox ?
resizerSize.height = mHScrollbarBox ?
mHScrollbarBox->GetPrefSize(aState).height : defaultSize;
r.height = std::max(std::max(r.height, hScrollbarHeight), resizerMinSize.height);
if (aContentArea.y == mScrollPort.y) {
r.y = aContentArea.YMost() - r.height;
if (resizerSize.height > r.height) {
r.height = resizerSize.height;
if (aContentArea.y == mScrollPort.y)
r.y = aContentArea.YMost() - r.height;
}
nsBoxFrame::LayoutChildAt(aState, mResizerBox, r);
@ -3706,10 +3671,9 @@ nsGfxScrollFrameInner::LayoutScrollbars(nsBoxLayoutState& aState,
}
nsPresContext* presContext = mScrolledFrame->PresContext();
nsRect vRect;
if (mVScrollbarBox) {
NS_PRECONDITION(mVScrollbarBox->IsBoxFrame(), "Must be a box frame!");
vRect = mScrollPort;
nsRect vRect(mScrollPort);
vRect.width = aContentArea.width - mScrollPort.width;
vRect.x = scrollbarOnLeft ? aContentArea.x : mScrollPort.XMost();
if (mHasVerticalScrollbar) {
@ -3718,12 +3682,12 @@ nsGfxScrollFrameInner::LayoutScrollbars(nsBoxLayoutState& aState,
vRect.Deflate(margin);
}
AdjustScrollbarRectForResizer(mOuter, presContext, vRect, hasResizer, true);
nsBoxFrame::LayoutChildAt(aState, mVScrollbarBox, vRect);
}
nsRect hRect;
if (mHScrollbarBox) {
NS_PRECONDITION(mHScrollbarBox->IsBoxFrame(), "Must be a box frame!");
hRect = mScrollPort;
nsRect hRect(mScrollPort);
hRect.height = aContentArea.height - mScrollPort.height;
hRect.y = true ? mScrollPort.YMost() : aContentArea.y;
if (mHasHorizontalScrollbar) {
@ -3732,13 +3696,6 @@ nsGfxScrollFrameInner::LayoutScrollbars(nsBoxLayoutState& aState,
hRect.Deflate(margin);
}
AdjustScrollbarRectForResizer(mOuter, presContext, hRect, hasResizer, false);
}
AdjustOverlappingScrollbars(vRect, hRect);
if (mVScrollbarBox) {
nsBoxFrame::LayoutChildAt(aState, mVScrollbarBox, vRect);
}
if (mHScrollbarBox) {
nsBoxFrame::LayoutChildAt(aState, mHScrollbarBox, hRect);
}

View File

@ -34,10 +34,8 @@ class nsPresState;
struct ScrollReflowState;
namespace mozilla {
namespace layout {
class ScrollbarActivity;
}
}
// When set, the next scroll operation on the scrollframe will invalidate its
// entire contents. Useful for text-overflow.
@ -48,7 +46,6 @@ class ScrollbarActivity;
class nsGfxScrollFrameInner : public nsIReflowCallback {
public:
typedef mozilla::gfx::Point Point;
typedef mozilla::layout::ScrollbarActivity ScrollbarActivity;
class AsyncScroll;
@ -284,7 +281,7 @@ public:
nsIFrame* mResizerBox;
nsContainerFrame* mOuter;
nsRefPtr<AsyncScroll> mAsyncScroll;
nsCOMPtr<ScrollbarActivity> mScrollbarActivity;
nsAutoPtr<mozilla::ScrollbarActivity> mScrollbarActivity;
nsTArray<nsIScrollPositionListener*> mListeners;
nsRect mScrollPort;
// Where we're currently scrolling to, if we're scrolling asynchronously.
@ -460,11 +457,6 @@ public:
virtual void AppendAnonymousContentTo(nsBaseContentList& aElements,
uint32_t aFilter) MOZ_OVERRIDE;
// nsIScrollbarOwner
virtual nsIFrame* GetScrollbarBox(bool aVertical) MOZ_OVERRIDE {
return mInner.GetScrollbarBox(aVertical);
}
// nsIScrollableFrame
virtual nsIFrame* GetScrolledFrame() const {
return mInner.GetScrolledFrame();
@ -533,6 +525,9 @@ public:
virtual void RemoveScrollPositionListener(nsIScrollPositionListener* aListener) MOZ_OVERRIDE {
mInner.RemoveScrollPositionListener(aListener);
}
virtual nsIFrame* GetScrollbarBox(bool aVertical) MOZ_OVERRIDE {
return mInner.GetScrollbarBox(aVertical);
}
virtual void CurPosAttributeChanged(nsIContent* aChild) MOZ_OVERRIDE {
mInner.CurPosAttributeChanged(aChild);
}
@ -718,11 +713,6 @@ public:
static void AdjustReflowStateForPrintPreview(nsBoxLayoutState& aState, bool& aSetBack);
static void AdjustReflowStateBack(nsBoxLayoutState& aState, bool aSetBack);
// nsIScrollbarOwner
virtual nsIFrame* GetScrollbarBox(bool aVertical) MOZ_OVERRIDE {
return mInner.GetScrollbarBox(aVertical);
}
// nsIScrollableFrame
virtual nsIFrame* GetScrolledFrame() const {
return mInner.GetScrolledFrame();
@ -791,6 +781,9 @@ public:
virtual void RemoveScrollPositionListener(nsIScrollPositionListener* aListener) MOZ_OVERRIDE {
mInner.RemoveScrollPositionListener(aListener);
}
virtual nsIFrame* GetScrollbarBox(bool aVertical) MOZ_OVERRIDE {
return mInner.GetScrollbarBox(aVertical);
}
virtual void CurPosAttributeChanged(nsIContent* aChild) MOZ_OVERRIDE {
mInner.CurPosAttributeChanged(aChild);
}

View File

@ -14,7 +14,6 @@
#include "nsCoord.h"
#include "nsPresContext.h"
#include "mozilla/gfx/Point.h"
#include "nsIScrollbarOwner.h"
#define NS_DEFAULT_VERTICAL_SCROLL_DISTANCE 3
#define NS_DEFAULT_HORIZONTAL_SCROLL_DISTANCE 5
@ -28,7 +27,7 @@ class nsIFrame;
* APIs for examining scroll state, observing changes to scroll state,
* and triggering scrolling.
*/
class nsIScrollableFrame : public nsIScrollbarOwner {
class nsIScrollableFrame : public nsQueryFrame {
public:
typedef mozilla::gfx::Point Point;
@ -203,6 +202,14 @@ public:
*/
virtual void RemoveScrollPositionListener(nsIScrollPositionListener* aListener) = 0;
/**
* Obtain the XUL box for the horizontal or vertical scrollbar, or null
* if there is no such box. Avoid using this, but may be useful for
* setting up a scrollbar mediator if you want to redirect scrollbar
* input.
*/
virtual nsIFrame* GetScrollbarBox(bool aVertical) = 0;
/**
* Internal method used by scrollbars to notify their scrolling
* container of changes.

View File

@ -1,28 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsIScrollbarOwner_h___
#define nsIScrollbarOwner_h___
#include "nsQueryFrame.h"
class nsIDOMEventTarget;
class nsIFrame;
/**
* An interface that represents a frame which manages scrollbars.
*/
class nsIScrollbarOwner : public nsQueryFrame {
public:
NS_DECL_QUERYFRAME_TARGET(nsIScrollbarOwner)
/**
* Obtain the frame for the horizontal or vertical scrollbar, or null
* if there is no such box.
*/
virtual nsIFrame* GetScrollbarBox(bool aVertical) = 0;
};
#endif

View File

@ -168,18 +168,18 @@ skip-if(B2G) == 192767-26.xul 192767-36.xul
skip-if(B2G) == 192767-27.xul 192767-37.xul
!= 192767-01.xul 192767-21.xul
!= 192767-02.xul 192767-22.xul
skip-if(B2G) fails-if(Android) != 192767-03.xul 192767-23.xul
fails-if(Android) != 192767-03.xul 192767-23.xul
!= 192767-04.xul 192767-24.xul
!= 192767-05.xul 192767-25.xul
skip-if(B2G) fails-if(Android) != 192767-06.xul 192767-26.xul
skip-if(B2G) fails-if(Android) != 192767-07.xul 192767-27.xul
fails-if(Android) != 192767-06.xul 192767-26.xul
fails-if(Android) != 192767-07.xul 192767-27.xul
!= 192767-11.xul 192767-31.xul
!= 192767-12.xul 192767-32.xul
skip-if(B2G) fails-if(Android) != 192767-13.xul 192767-33.xul
fails-if(Android) != 192767-13.xul 192767-33.xul
!= 192767-14.xul 192767-34.xul
!= 192767-15.xul 192767-35.xul
skip-if(B2G) fails-if(Android) != 192767-16.xul 192767-36.xul
skip-if(B2G) fails-if(Android) != 192767-17.xul 192767-37.xul
fails-if(Android) != 192767-16.xul 192767-36.xul
fails-if(Android) != 192767-17.xul 192767-37.xul
!= 200774-1.html about:blank
== 201215-1.html 201215-1-ref.html
== 201293-1a.html 201293-1-ref.html

View File

@ -60,7 +60,6 @@
#include "nsRenderingContext.h"
#include "nsIScriptableRegion.h"
#include <algorithm>
#include "ScrollbarActivity.h"
#ifdef ACCESSIBILITY
#include "nsAccessibilityService.h"
@ -70,7 +69,6 @@
#endif
using namespace mozilla;
using namespace mozilla::layout;
// Enumeration function that cancels all the image requests in our cache
static PLDHashOperator
@ -104,7 +102,6 @@ NS_IMPL_FRAMEARENA_HELPERS(nsTreeBodyFrame)
NS_QUERYFRAME_HEAD(nsTreeBodyFrame)
NS_QUERYFRAME_ENTRY(nsIScrollbarMediator)
NS_QUERYFRAME_ENTRY(nsIScrollbarOwner)
NS_QUERYFRAME_ENTRY(nsTreeBodyFrame)
NS_QUERYFRAME_TAIL_INHERITING(nsLeafBoxFrame)
@ -172,11 +169,6 @@ nsTreeBodyFrame::Init(nsIContent* aContent,
mImageCache.Init(16);
EnsureBoxObject();
if (LookAndFeel::GetInt(LookAndFeel::eIntID_UseOverlayScrollbars) != 0) {
mScrollbarActivity = new ScrollbarActivity(
static_cast<nsIScrollbarOwner*>(this));
}
}
nsSize
@ -274,11 +266,6 @@ nsTreeBodyFrame::CalcMaxRowWidth()
void
nsTreeBodyFrame::DestroyFrom(nsIFrame* aDestructRoot)
{
if (mScrollbarActivity) {
mScrollbarActivity->Destroy();
mScrollbarActivity = nullptr;
}
mScrollEvent.Revoke();
// Make sure we cancel any posted callbacks.
if (mReflowCallbackPosted) {
@ -850,13 +837,15 @@ nsTreeBodyFrame::UpdateScrollbars(const ScrollParts& aParts)
{
nscoord rowHeightAsPixels = nsPresContext::AppUnitsToIntCSSPixels(mRowHeight);
nsWeakFrame weakFrame(this);
if (aParts.mVScrollbar) {
nsWeakFrame self(this);
nsAutoString curPos;
curPos.AppendInt(mTopRowIndex*rowHeightAsPixels);
aParts.mVScrollbarContent->
SetAttr(kNameSpaceID_None, nsGkAtoms::curpos, curPos, true);
if (!self.IsAlive()) {
return;
}
}
if (aParts.mHScrollbar) {
@ -866,10 +855,6 @@ nsTreeBodyFrame::UpdateScrollbars(const ScrollParts& aParts)
SetAttr(kNameSpaceID_None, nsGkAtoms::curpos, curPos, true);
// 'this' might be deleted here
}
if (weakFrame.IsAlive() && mScrollbarActivity) {
mScrollbarActivity->ActivityOccurred();
}
}
void
@ -972,10 +957,6 @@ nsTreeBodyFrame::InvalidateScrollbars(const ScrollParts& aParts, nsWeakFrame& aW
aParts.mHScrollbarContent->
SetAttr(kNameSpaceID_None, nsGkAtoms::increment, pageStr, true);
}
if (mScrollbarActivity) {
mScrollbarActivity->ActivityOccurred();
}
}
// Takes client x/y in pixels, converts them to appunits, and converts into

View File

@ -24,17 +24,10 @@
#include "nsScrollbarFrame.h"
#include "nsThreadUtils.h"
#include "mozilla/LookAndFeel.h"
#include "nsIScrollbarOwner.h"
class nsOverflowChecker;
class nsTreeImageListener;
namespace mozilla {
namespace layout {
class ScrollbarActivity;
}
}
// An entry in the tree's image cache
struct nsTreeImageCacheEntry
{
@ -52,11 +45,8 @@ class nsTreeBodyFrame MOZ_FINAL
, public nsICSSPseudoComparator
, public nsIScrollbarMediator
, public nsIReflowCallback
, public nsIScrollbarOwner
{
public:
typedef mozilla::layout::ScrollbarActivity ScrollbarActivity;
nsTreeBodyFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
~nsTreeBodyFrame();
@ -136,12 +126,6 @@ public:
NS_IMETHOD ScrollbarButtonPressed(nsScrollbarFrame* aScrollbar, int32_t aOldIndex, int32_t aNewIndex) MOZ_OVERRIDE;
NS_IMETHOD VisibilityChanged(bool aVisible) MOZ_OVERRIDE { Invalidate(); return NS_OK; }
// nsIScrollbarOwner
virtual nsIFrame* GetScrollbarBox(bool aVertical) MOZ_OVERRIDE {
ScrollParts parts = GetScrollParts();
return aVertical ? parts.mVScrollbar : parts.mHScrollbar;
}
// Overridden from nsIFrame to cache our pres context.
virtual void Init(nsIContent* aContent,
nsIFrame* aParent,
@ -541,8 +525,6 @@ protected: // Data Members
nsRevocableEventPtr<ScrollEvent> mScrollEvent;
nsCOMPtr<ScrollbarActivity> mScrollbarActivity;
// The cached box object parent.
nsCOMPtr<nsITreeBoxObject> mTreeBoxObject;

View File

@ -80,7 +80,7 @@ function test()
<select id="f" style="width: 100px; height: 100px;"><option>a</option><option>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</option><option>a</option>\
<option>a</option><option>a</option><option>a</option><option>a</option><option>a</option><option>a</option><option>a</option>\
<option>a</option><option>a</option><option>a</option><option>a</option><option>a</option><option>a</option><option>a</option></select>\
<div id="g" style="width: 99px; height: 99px; border: 10px solid black; margin: 10px; overflow: auto;"><div style="width: 100px; height: 100px;"></div></div>\
<div id="g" style="width: 99px; height: 99px; padding: 10px; border: 10px solid black; margin: 10px; overflow: auto;"><div style="width: 100px; height: 100px; margin: 10px;"></div></div>\
<div id="h" style="width: 100px; height: 100px; overflow: -moz-hidden-unscrollable;"><div style="width: 200px; height: 200px;"></div></div>\
<iframe id="iframe" style="display: none;"></iframe>\
</body>';

View File

@ -98,13 +98,11 @@ function testListbox()
var id = "listbox";
var listbox = document.getElementById(id);
if (!window.matchMedia("(-moz-overlay-scrollbars)").matches) {
// Check that a scrollbar is visible by comparing the width of the listitem
// with the width of the listbox. This is a simple way to do this without
// checking the anonymous content.
ok(listbox.firstChild.getBoundingClientRect().width < listbox.getBoundingClientRect().width - 10,
id + ": Scrollbar visible");
}
// Check that a scrollbar is visible by comparing the width of the listitem
// with the width of the listbox. This is a simple way to do this without
// checking the anonymous content.
ok(listbox.firstChild.getBoundingClientRect().width < listbox.getBoundingClientRect().width - 10,
id + ": Scrollbar visible");
var rowHeight = listbox.firstChild.getBoundingClientRect().height;

View File

@ -88,8 +88,7 @@ function differentPressed()
list.open = true;
is(list.getBoundingClientRect().width, list.firstChild.getBoundingClientRect().width,
"menu and popup width match");
var minScrollbarWidth = window.matchMedia("(-moz-overlay-scrollbars)").matches ? 0 : 3;
ok(list.getBoundingClientRect().width >= list.getItemAtIndex(0).getBoundingClientRect().width + minScrollbarWidth,
ok(list.getBoundingClientRect().width > list.getItemAtIndex(0).getBoundingClientRect().width + 2,
"menuitem width accounts for scrollbar");
list.open = false;

View File

@ -18,8 +18,7 @@
curpos="0"
maxpos="600"
pageincrement="400"
width="500"
style="margin:0"/>
width="500"/>
</hbox>
<!-- test code goes here -->

View File

@ -925,7 +925,7 @@ grippy {
/********** scrollbar **********/
/* Scrollbars are never flipped even if BiDI kicks in. */
scrollbar[orient="horizontal"] {
scrollbar {
direction: ltr;
}

View File

@ -17,26 +17,6 @@ html|select[multiple] > scrollbar {
-moz-appearance: scrollbar-small;
}
@media all and (-moz-overlay-scrollbars) {
scrollbar {
position: relative;
z-index: 2147483647;
}
scrollbar:not([active="true"]),
scrollbar[disabled="true"] {
visibility: hidden;
}
scrollbar[orient="vertical"] {
-moz-margin-start: -16px;
}
scrollbar[orient="horizontal"] {
margin-top: -16px;
}
}
/* ..... track ..... */
slider {

View File

@ -9,9 +9,7 @@ resizer {
background: url("chrome://global/skin/icons/resizer.png") no-repeat;
background-size: 100% 100%;
cursor: se-resize;
min-width: 15px;
width: 15px;
min-height: 15px;
height: 15px;
}
@media (min-resolution: 2dppx) {

View File

@ -26,7 +26,6 @@
#include "nsIScrollableFrame.h"
#include "nsIDOMHTMLMeterElement.h"
#include "mozilla/dom/Element.h"
#include "nsLookAndFeel.h"
#include "gfxContext.h"
#include "gfxQuartzSurface.h"
@ -2285,73 +2284,34 @@ nsNativeThemeCocoa::DrawWidgetBackground(nsRenderingContext* aContext,
}
case NS_THEME_SCROLLBAR_SMALL:
case NS_THEME_SCROLLBAR:
if (!nsLookAndFeel::UseOverlayScrollbars()) {
DrawScrollbar(cgContext, macRect, aFrame);
}
case NS_THEME_SCROLLBAR: {
DrawScrollbar(cgContext, macRect, aFrame);
}
break;
case NS_THEME_SCROLLBAR_THUMB_VERTICAL:
case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL:
if (nsLookAndFeel::UseOverlayScrollbars()) {
BOOL isHorizontal = (aWidgetType == NS_THEME_SCROLLBAR_THUMB_HORIZONTAL);
BOOL isRolledOver = CheckBooleanAttr(GetParentScrollbarFrame(aFrame),
nsGkAtoms::hover);
if (!isRolledOver) {
if (isHorizontal) {
macRect.origin.y += 4;
macRect.size.height -= 4;
} else {
macRect.origin.x += 4;
macRect.size.width -= 4;
}
}
const BOOL isOnTopOfBrightBackground = YES; // TODO: detect this properly
CUIDraw([NSWindow coreUIRenderer], macRect, cgContext,
(CFDictionaryRef)[NSDictionary dictionaryWithObjectsAndKeys:
@"kCUIWidgetOverlayScrollBar", @"widget",
@"regular", @"size",
(isRolledOver ? @"rollover" : @""), @"state",
(isHorizontal ? @"kCUIOrientHorizontal" : @"kCUIOrientVertical"), @"kCUIOrientationKey",
(isOnTopOfBrightBackground ? @"" : @"kCUIVariantWhite"), @"kCUIVariantKey",
[NSNumber numberWithBool:YES], @"indiconly",
[NSNumber numberWithBool:YES], @"kCUIThumbProportionKey",
[NSNumber numberWithBool:YES], @"is.flipped",
nil],
nil);
}
break;
#if SCROLLBARS_VISUAL_DEBUG
CGContextSetRGBFillColor(cgContext, 1.0, 1.0, 0, 0.6);
CGContextFillRect(cgContext, macRect);
break;
#endif
case NS_THEME_SCROLLBAR_BUTTON_UP:
case NS_THEME_SCROLLBAR_BUTTON_LEFT:
#if SCROLLBARS_VISUAL_DEBUG
CGContextSetRGBFillColor(cgContext, 1.0, 0, 0, 0.6);
CGContextFillRect(cgContext, macRect);
#endif
break;
#endif
case NS_THEME_SCROLLBAR_BUTTON_DOWN:
case NS_THEME_SCROLLBAR_BUTTON_RIGHT:
#if SCROLLBARS_VISUAL_DEBUG
CGContextSetRGBFillColor(cgContext, 0, 1.0, 0, 0.6);
CGContextFillRect(cgContext, macRect);
break;
#endif
break;
case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
if (nsLookAndFeel::UseOverlayScrollbars() &&
CheckBooleanAttr(GetParentScrollbarFrame(aFrame), nsGkAtoms::hover)) {
BOOL isHorizontal = (aWidgetType == NS_THEME_SCROLLBAR_TRACK_HORIZONTAL);
const BOOL isOnTopOfBrightBackground = YES; // TODO: detect this properly
CUIDraw([NSWindow coreUIRenderer], macRect, cgContext,
(CFDictionaryRef)[NSDictionary dictionaryWithObjectsAndKeys:
@"kCUIWidgetOverlayScrollBar", @"widget",
@"regular", @"size",
(isHorizontal ? @"kCUIOrientHorizontal" : @"kCUIOrientVertical"), @"kCUIOrientationKey",
(isOnTopOfBrightBackground ? @"" : @"kCUIVariantWhite"), @"kCUIVariantKey",
[NSNumber numberWithBool:YES], @"noindicator",
[NSNumber numberWithBool:YES], @"kCUIThumbProportionKey",
[NSNumber numberWithBool:YES], @"is.flipped",
nil],
nil);
}
// do nothing, drawn by scrollbar
break;
case NS_THEME_TEXTFIELD_MULTILINE: {
@ -2523,13 +2483,13 @@ nsNativeThemeCocoa::GetWidgetBorder(nsDeviceContext* aContext,
case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
{
bool isHorizontal = (aWidgetType == NS_THEME_SCROLLBAR_TRACK_HORIZONTAL);
// On Lion and later, scrollbars have no arrows.
if (!nsCocoaFeatures::OnLionOrLater()) {
// There's only an endcap to worry about when both arrows are on the bottom
NSString *buttonPlacement = [[NSUserDefaults standardUserDefaults] objectForKey:@"AppleScrollBarVariant"];
if (!buttonPlacement || [buttonPlacement isEqualToString:@"DoubleMax"]) {
bool isHorizontal = (aWidgetType == NS_THEME_SCROLLBAR_TRACK_HORIZONTAL);
nsIFrame *scrollbarFrame = GetParentScrollbarFrame(aFrame);
if (!scrollbarFrame) return NS_ERROR_FAILURE;
bool isSmall = (scrollbarFrame->StyleDisplay()->mAppearance == NS_THEME_SCROLLBAR_SMALL);
@ -2544,15 +2504,6 @@ nsNativeThemeCocoa::GetWidgetBorder(nsDeviceContext* aContext,
aResult->SizeTo(endcapSize, 0, 0, 0);
}
}
if (nsLookAndFeel::UseOverlayScrollbars()) {
if (isHorizontal) {
aResult->SizeTo(1, 2, 1, 1);
} else {
aResult->SizeTo(2, 1, 1, 1);
}
}
break;
}
@ -2639,7 +2590,7 @@ nsNativeThemeCocoa::GetWidgetOverflow(nsDeviceContext* aContext, nsIFrame* aFram
return false;
}
static const int32_t kRegularScrollbarThumbMinSize = 26;
static const int32_t kRegularScrollbarThumbMinSize = 22;
static const int32_t kSmallScrollbarThumbMinSize = 19;
NS_IMETHODIMP
@ -2778,6 +2729,15 @@ nsNativeThemeCocoa::GetMinimumWidgetSize(nsRenderingContext* aContext,
*aIsOverridable = false;
break;
}
case NS_THEME_SCROLLBAR_SMALL:
{
SInt32 scrollbarWidth = 0;
::GetThemeMetric(kThemeMetricSmallScrollBarWidth, &scrollbarWidth);
aResult->SizeTo(scrollbarWidth, scrollbarWidth);
*aIsOverridable = false;
break;
}
case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL:
case NS_THEME_SCROLLBAR_THUMB_VERTICAL:
@ -2796,17 +2756,9 @@ nsNativeThemeCocoa::GetMinimumWidgetSize(nsRenderingContext* aContext,
}
case NS_THEME_SCROLLBAR:
case NS_THEME_SCROLLBAR_SMALL:
case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
{
*aIsOverridable = false;
if (nsLookAndFeel::UseOverlayScrollbars()) {
aResult->SizeTo(16, 16);
break;
}
// yeah, i know i'm cheating a little here, but i figure that it
// really doesn't matter if the scrollbar is vertical or horizontal
// and the width metric is a really good metric for every piece
@ -2821,6 +2773,7 @@ nsNativeThemeCocoa::GetMinimumWidgetSize(nsRenderingContext* aContext,
SInt32 scrollbarWidth = 0;
::GetThemeMetric(themeMetric, &scrollbarWidth);
aResult->SizeTo(scrollbarWidth, scrollbarWidth);
*aIsOverridable = false;
break;
}
@ -2882,6 +2835,8 @@ nsNativeThemeCocoa::WidgetStateChanged(nsIFrame* aFrame, uint8_t aWidgetType,
case NS_THEME_TOOLBOX:
case NS_THEME_TOOLBAR:
case NS_THEME_MOZ_MAC_UNIFIED_TOOLBAR:
case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
case NS_THEME_STATUSBAR:
case NS_THEME_STATUSBAR_PANEL:
case NS_THEME_STATUSBAR_RESIZER_PANEL:
@ -2918,8 +2873,7 @@ nsNativeThemeCocoa::WidgetStateChanged(nsIFrame* aFrame, uint8_t aWidgetType,
aAttribute == nsGkAtoms::sortDirection ||
aAttribute == nsGkAtoms::focused ||
aAttribute == nsGkAtoms::_default ||
aAttribute == nsGkAtoms::open ||
aAttribute == nsGkAtoms::hover)
aAttribute == nsGkAtoms::open)
*aShouldRepaint = true;
}
@ -3031,12 +2985,11 @@ nsNativeThemeCocoa::ThemeSupportsWidget(nsPresContext* aPresContext, nsIFrame* a
// Note that IsWidgetStyled is not called for resizers on Mac. This is
// because for scrollable containers, the native resizer looks better
// when (non-overlay) scrollbars are present even when the style is
// overriden, and the custom transparent resizer looks better when
// scrollbars are not present.
// when scrollbars are present even when the style is overriden, and the
// custom transparent resizer looks better when scrollbars are not
// present.
nsIScrollableFrame* scrollFrame = do_QueryFrame(parentFrame);
return (!nsLookAndFeel::UseOverlayScrollbars() &&
scrollFrame && scrollFrame->GetScrollbarVisibility());
return (scrollFrame && scrollFrame->GetScrollbarVisibility());
break;
}
}
@ -3091,8 +3044,6 @@ nsNativeThemeCocoa::GetWidgetTransparency(nsIFrame* aFrame, uint8_t aWidgetType)
case NS_THEME_SCROLLBAR_SMALL:
case NS_THEME_SCROLLBAR:
return nsLookAndFeel::UseOverlayScrollbars() ? eTransparent : eOpaque;
case NS_THEME_STATUSBAR:
// Knowing that scrollbars and statusbars are opaque improves
// performance, because we create layers for them.

View File

@ -58,7 +58,7 @@ function runTest() {
var elem = document.getElementById(orient + size);
var thumbRect = document.getAnonymousElementByAttribute(elem, 'sbattr', 'scrollbar-thumb').getBoundingClientRect();
var sizeToCheck = orient == "horizontal" ? "width" : "height";
var expectedSize = size == "Small" ? 19 : 26;
var expectedSize = size == "Small" ? 19 : 22;
is(thumbRect[sizeToCheck], expectedSize, size + " scrollbar has wrong minimum " + sizeToCheck);
});
});