Bug 957445: Part 1 - Scrolling moved from nsScrollbarButtonFrame and nsSliderFrame into nsIScrollbarMediator, r=mats

This commit is contained in:
Miranda Emery 2014-02-05 14:30:34 +13:00
parent edcad2a7e9
commit 43c4d9fdf2
11 changed files with 402 additions and 171 deletions

View File

@ -7,6 +7,7 @@
#define nsIScrollbarMediator_h___
#include "nsQueryFrame.h"
#include "nsCoord.h"
class nsScrollbarFrame;
@ -15,11 +16,35 @@ class nsIScrollbarMediator
public:
NS_DECL_QUERYFRAME_TARGET(nsIScrollbarMediator)
// The aScrollbar argument denotes the scrollbar that's firing the notification.
NS_IMETHOD PositionChanged(nsScrollbarFrame* aScrollbar, int32_t aOldIndex, int32_t& aNewIndex) = 0;
NS_IMETHOD ScrollbarButtonPressed(nsScrollbarFrame* aScrollbar, int32_t aOldIndex, int32_t aNewIndex) = 0;
/**
* The aScrollbar argument denotes the scrollbar that's firing the notification.
* aScrollbar is never null.
* aDirection is either -1, 0, or 1.
*/
NS_IMETHOD VisibilityChanged(bool aVisible) = 0;
/**
* One of the following three methods is called when the scrollbar's button is
* clicked.
* @note These methods might destroy the frame, pres shell, and other objects.
*/
virtual void ScrollByPage(nsScrollbarFrame* aScrollbar, int32_t aDirection) = 0;
virtual void ScrollByWhole(nsScrollbarFrame* aScrollbar, int32_t aDirection) = 0;
virtual void ScrollByLine(nsScrollbarFrame* aScrollbar, int32_t aDirection) = 0;
/**
* RepeatButtonScroll is called when the scrollbar's button is held down. When the
* button is first clicked the increment is set; RepeatButtonScroll adds this
* increment to the current position.
* @note This method might destroy the frame, pres shell, and other objects.
*/
virtual void RepeatButtonScroll(nsScrollbarFrame* aScrollbar) = 0;
/**
* aOldPos and aNewPos are scroll positions.
* @note This method might destroy the frame, pres shell, and other objects.
*/
virtual void ThumbMoved(nsScrollbarFrame* aScrollbar,
nscoord aOldPos,
nscoord aNewPos) = 0;
virtual void VisibilityChanged(bool aVisible) = 0;
};
#endif

View File

@ -324,16 +324,56 @@ nsListBoxBodyFrame::GetPrefSize(nsBoxLayoutState& aBoxLayoutState)
///////////// nsIScrollbarMediator ///////////////
NS_IMETHODIMP
nsListBoxBodyFrame::PositionChanged(nsScrollbarFrame* aScrollbar, int32_t aOldIndex, int32_t& aNewIndex)
void
nsListBoxBodyFrame::ScrollByPage(nsScrollbarFrame* aScrollbar, int32_t aDirection)
{
MOZ_ASSERT(aScrollbar != nullptr);
UpdateIndex(aDirection);
aScrollbar->SetIncrementToPage(aDirection);
aScrollbar->MoveToNewPosition();
}
void
nsListBoxBodyFrame::ScrollByWhole(nsScrollbarFrame* aScrollbar, int32_t aDirection)
{
MOZ_ASSERT(aScrollbar != nullptr);
UpdateIndex(aDirection);
aScrollbar->SetIncrementToWhole(aDirection);
aScrollbar->MoveToNewPosition();
}
void
nsListBoxBodyFrame::ScrollByLine(nsScrollbarFrame* aScrollbar, int32_t aDirection)
{
MOZ_ASSERT(aScrollbar != nullptr);
UpdateIndex(aDirection);
aScrollbar->SetIncrementToLine(aDirection);
aScrollbar->MoveToNewPosition();
}
void
nsListBoxBodyFrame::RepeatButtonScroll(nsScrollbarFrame* aScrollbar)
{
int32_t increment = aScrollbar->GetIncrement();
if (increment < 0) {
UpdateIndex(-1);
} else if (increment > 0) {
UpdateIndex(1);
}
aScrollbar->MoveToNewPosition();
}
void
nsListBoxBodyFrame::ThumbMoved(nsScrollbarFrame* aScrollbar,
nscoord aOldPos,
nscoord aNewPos)
{
if (mScrolling || mRowHeight == 0)
return NS_OK;
return;
nscoord oldTwipIndex, newTwipIndex;
nscoord oldTwipIndex;
oldTwipIndex = mCurrentIndex*mRowHeight;
newTwipIndex = nsPresContext::CSSPixelsToAppUnits(aNewIndex);
int32_t twipDelta = newTwipIndex > oldTwipIndex ? newTwipIndex - oldTwipIndex : oldTwipIndex - newTwipIndex;
int32_t twipDelta = aNewPos > oldTwipIndex ? aNewPos - oldTwipIndex : oldTwipIndex - aNewPos;
int32_t rowDelta = twipDelta / mRowHeight;
int32_t remainder = twipDelta % mRowHeight;
@ -341,11 +381,11 @@ nsListBoxBodyFrame::PositionChanged(nsScrollbarFrame* aScrollbar, int32_t aOldIn
rowDelta++;
if (rowDelta == 0)
return NS_OK;
return;
// update the position to be row based.
int32_t newIndex = newTwipIndex > oldTwipIndex ? mCurrentIndex + rowDelta : mCurrentIndex - rowDelta;
int32_t newIndex = aNewPos > oldTwipIndex ? mCurrentIndex + rowDelta : mCurrentIndex - rowDelta;
//aNewIndex = newIndex*mRowHeight/mOnePixel;
nsListScrollSmoother* smoother = GetSmoother();
@ -356,11 +396,11 @@ nsListBoxBodyFrame::PositionChanged(nsScrollbarFrame* aScrollbar, int32_t aOldIn
smoother->Stop();
smoother->mDelta = newTwipIndex > oldTwipIndex ? rowDelta : -rowDelta;
smoother->mDelta = aNewPos > oldTwipIndex ? rowDelta : -rowDelta;
smoother->Start();
return NS_OK;
return;
}
smoother->Stop();
@ -370,17 +410,16 @@ nsListBoxBodyFrame::PositionChanged(nsScrollbarFrame* aScrollbar, int32_t aOldIn
if (mCurrentIndex < 0) {
mCurrentIndex = 0;
return NS_OK;
return;
}
return InternalPositionChanged(newTwipIndex < oldTwipIndex, rowDelta);
InternalPositionChanged(aNewPos < oldTwipIndex, rowDelta);
}
NS_IMETHODIMP
void
nsListBoxBodyFrame::VisibilityChanged(bool aVisible)
{
if (mRowHeight == 0)
return NS_OK;
return;
int32_t lastPageTopRow = GetRowCount() - (GetAvailableHeight() / mRowHeight);
if (lastPageTopRow < 0)
@ -390,27 +429,23 @@ nsListBoxBodyFrame::VisibilityChanged(bool aVisible)
mCurrentIndex = lastPageTopRow;
InternalPositionChanged(true, delta);
}
return NS_OK;
}
NS_IMETHODIMP
nsListBoxBodyFrame::ScrollbarButtonPressed(nsScrollbarFrame* aScrollbar, int32_t aOldIndex, int32_t aNewIndex)
void
nsListBoxBodyFrame::UpdateIndex(int32_t aDirection)
{
if (aOldIndex == aNewIndex)
return NS_OK;
if (aNewIndex < aOldIndex)
if (aDirection == 0)
return;
if (aDirection < 0)
mCurrentIndex--;
else mCurrentIndex++;
if (mCurrentIndex < 0) {
mCurrentIndex = 0;
return NS_OK;
return;
}
InternalPositionChanged(aNewIndex < aOldIndex, 1);
return NS_OK;
InternalPositionChanged(aDirection < 0, 1);
}
///////////// nsIReflowCallback ///////////////
bool

View File

@ -56,9 +56,15 @@ public:
virtual nsresult AttributeChanged(int32_t aNameSpaceID, nsIAtom* aAttribute, int32_t aModType) MOZ_OVERRIDE;
// nsIScrollbarMediator
NS_IMETHOD PositionChanged(nsScrollbarFrame* aScrollbar, int32_t aOldIndex, int32_t& aNewIndex) MOZ_OVERRIDE;
NS_IMETHOD ScrollbarButtonPressed(nsScrollbarFrame* aScrollbar, int32_t aOldIndex, int32_t aNewIndex) MOZ_OVERRIDE;
NS_IMETHOD VisibilityChanged(bool aVisible) MOZ_OVERRIDE;
virtual void ScrollByPage(nsScrollbarFrame* aScrollbar, int32_t aDirection) MOZ_OVERRIDE;
virtual void ScrollByWhole(nsScrollbarFrame* aScrollbar, int32_t aDirection) MOZ_OVERRIDE;
virtual void ScrollByLine(nsScrollbarFrame* aScrollbar, int32_t aDirection) MOZ_OVERRIDE;
virtual void RepeatButtonScroll(nsScrollbarFrame* aScrollbar) MOZ_OVERRIDE;
virtual void ThumbMoved(nsScrollbarFrame* aScrollbar,
int32_t aOldPos,
int32_t aNewPos) MOZ_OVERRIDE;
virtual void VisibilityChanged(bool aVisible) MOZ_OVERRIDE;
// nsIReflowCallback
virtual bool ReflowFinished() MOZ_OVERRIDE;
@ -89,6 +95,7 @@ public:
nsresult DoInternalPositionChanged(bool aUp, int32_t aDelta);
nsListScrollSmoother* GetSmoother();
void VerticalScroll(int32_t aDelta);
void UpdateIndex(int32_t aDirection);
// frames
nsIFrame* GetFirstFrame();

View File

@ -78,7 +78,6 @@ nsScrollbarButtonFrame::HandleEvent(nsPresContext* aPresContext,
return nsButtonBoxFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
}
bool
nsScrollbarButtonFrame::HandleButtonPress(nsPresContext* aPresContext,
WidgetGUIEvent* aEvent,
@ -109,10 +108,7 @@ nsScrollbarButtonFrame::HandleButtonPress(nsPresContext* aPresContext,
if (scrollbar == nullptr)
return false;
// get the scrollbars content node
nsIContent* content = scrollbar->GetContent();
static nsIContent::AttrValuesArray strings[] = { &nsGkAtoms::increment,
&nsGkAtoms::decrement,
nullptr };
@ -120,51 +116,65 @@ nsScrollbarButtonFrame::HandleButtonPress(nsPresContext* aPresContext,
nsGkAtoms::type,
strings, eCaseMatters);
int32_t direction;
if (index == 0)
if (index == 0)
direction = 1;
else if (index == 1)
direction = -1;
else
return false;
// Whether or not to repeat the click action.
bool repeat = true;
// Use smooth scrolling by default.
bool smoothScroll = true;
switch (pressedButtonAction) {
case 0:
mIncrement = direction * nsSliderFrame::GetIncrement(content);
break;
case 1:
mIncrement = direction * nsSliderFrame::GetPageIncrement(content);
break;
case 2:
if (direction == -1)
mIncrement = -nsSliderFrame::GetCurrentPosition(content);
else
mIncrement = nsSliderFrame::GetMaxPosition(content) -
nsSliderFrame::GetCurrentPosition(content);
// Don't repeat or use smooth scrolling if scrolling to beginning or end
// of a page.
repeat = smoothScroll = false;
break;
case 3:
default:
// We were told to ignore this click, or someone assigned a non-standard
// value to the button's action.
return false;
}
bool repeat = pressedButtonAction != 2;
// set this attribute so we can style it later
nsWeakFrame weakFrame(this);
mContent->SetAttr(kNameSpaceID_None, nsGkAtoms::active, NS_LITERAL_STRING("true"), true);
nsIPresShell::SetCapturingContent(mContent, CAPTURE_IGNOREALLOWED);
if (weakFrame.IsAlive()) {
DoButtonAction(smoothScroll);
if (!weakFrame.IsAlive()) {
return false;
}
if (repeat)
nsScrollbarFrame* sb = do_QueryFrame(scrollbar);
if (sb) {
nsIScrollbarMediator* m = sb->GetScrollbarMediator();
switch (pressedButtonAction) {
case 0:
sb->SetIncrementToLine(direction);
if (m) {
m->ScrollByLine(sb, direction);
}
break;
case 1:
sb->SetIncrementToPage(direction);
if (m) {
m->ScrollByPage(sb, direction);
}
break;
case 2:
sb->SetIncrementToWhole(direction);
if (m) {
m->ScrollByWhole(sb, direction);
}
break;
case 3:
default:
// We were told to ignore this click, or someone assigned a non-standard
// value to the button's action.
return false;
}
if (!weakFrame.IsAlive()) {
return false;
}
if (!m) {
sb->MoveToNewPosition();
if (!weakFrame.IsAlive()) {
return false;
}
}
}
if (repeat) {
StartRepeat();
}
return true;
}
@ -182,12 +192,21 @@ nsScrollbarButtonFrame::HandleRelease(nsPresContext* aPresContext,
void nsScrollbarButtonFrame::Notify()
{
// Since this is only going to get called if we're scrolling a page length
// or a line increment, we will always use smooth scrolling.
if (mCursorOnThis ||
LookAndFeel::GetInt(
LookAndFeel::eIntID_ScrollbarButtonAutoRepeatBehavior, 0)) {
DoButtonAction(true);
// get the scrollbar control
nsIFrame* scrollbar;
GetParentWithTag(nsGkAtoms::scrollbar, this, scrollbar);
nsScrollbarFrame* sb = do_QueryFrame(scrollbar);
if (sb) {
nsIScrollbarMediator* m = sb->GetScrollbarMediator();
if (m) {
m->RepeatButtonScroll(sb);
} else {
sb->MoveToNewPosition();
}
}
}
}
@ -199,56 +218,6 @@ nsScrollbarButtonFrame::MouseClicked(nsPresContext* aPresContext,
//MouseClicked();
}
void
nsScrollbarButtonFrame::DoButtonAction(bool aSmoothScroll)
{
// get the scrollbar control
nsIFrame* scrollbar;
GetParentWithTag(nsGkAtoms::scrollbar, this, scrollbar);
if (scrollbar == nullptr)
return;
// get the scrollbars content node
nsCOMPtr<nsIContent> content = scrollbar->GetContent();
// get the current pos
int32_t curpos = nsSliderFrame::GetCurrentPosition(content);
int32_t oldpos = curpos;
// get the max pos
int32_t maxpos = nsSliderFrame::GetMaxPosition(content);
// increment the given amount
if (mIncrement)
curpos += mIncrement;
// make sure the current position is between the current and max positions
if (curpos < 0)
curpos = 0;
else if (curpos > maxpos)
curpos = maxpos;
nsScrollbarFrame* sb = do_QueryFrame(scrollbar);
if (sb) {
nsIScrollbarMediator* m = sb->GetScrollbarMediator();
if (m) {
m->ScrollbarButtonPressed(sb, oldpos, curpos);
return;
}
}
// set the current position of the slider.
nsAutoString curposStr;
curposStr.AppendInt(curpos);
if (aSmoothScroll)
content->SetAttr(kNameSpaceID_None, nsGkAtoms::smooth, NS_LITERAL_STRING("true"), false);
content->SetAttr(kNameSpaceID_None, nsGkAtoms::curpos, curposStr, true);
if (aSmoothScroll)
content->UnsetAttr(kNameSpaceID_None, nsGkAtoms::smooth, false);
}
nsresult
nsScrollbarButtonFrame::GetChildWithTag(nsPresContext* aPresContext,
nsIAtom* atom, nsIFrame* start,

View File

@ -67,7 +67,6 @@ public:
protected:
virtual void MouseClicked(nsPresContext* aPresContext,
mozilla::WidgetGUIEvent* aEvent) MOZ_OVERRIDE;
void DoButtonAction(bool aSmoothScroll);
void StartRepeat() {
nsRepeatService::GetInstance()->Start(Notify, this);
@ -80,7 +79,6 @@ protected:
static_cast<nsScrollbarButtonFrame*>(aData)->Notify();
}
int32_t mIncrement;
bool mCursorOnThis;
};

View File

@ -11,6 +11,7 @@
//
#include "nsScrollbarFrame.h"
#include "nsSliderFrame.h"
#include "nsScrollbarButtonFrame.h"
#include "nsGkAtoms.h"
#include "nsIScrollableFrame.h"
@ -19,6 +20,7 @@
#include "nsThemeConstants.h"
#include "nsRenderingContext.h"
#include "nsIContent.h"
#include "nsIDOMMutationEvent.h"
using namespace mozilla;
@ -186,3 +188,103 @@ nsScrollbarFrame::GetMargin(nsMargin& aMargin)
return nsBox::GetMargin(aMargin);
}
void
nsScrollbarFrame::SetIncrementToLine(int32_t aDirection)
{
// get the scrollbar's content node
nsIContent* content = GetContent();
mSmoothScroll = true;
mIncrement = aDirection * nsSliderFrame::GetIncrement(content);
}
void
nsScrollbarFrame::SetIncrementToPage(int32_t aDirection)
{
// get the scrollbar's content node
nsIContent* content = GetContent();
mSmoothScroll = true;
mIncrement = aDirection * nsSliderFrame::GetPageIncrement(content);
}
void
nsScrollbarFrame::SetIncrementToWhole(int32_t aDirection)
{
// get the scrollbar's content node
nsIContent* content = GetContent();
if (aDirection == -1)
mIncrement = -nsSliderFrame::GetCurrentPosition(content);
else
mIncrement = nsSliderFrame::GetMaxPosition(content) -
nsSliderFrame::GetCurrentPosition(content);
// Don't repeat or use smooth scrolling if scrolling to beginning or end
// of a page.
mSmoothScroll = false;
}
int32_t
nsScrollbarFrame::MoveToNewPosition()
{
// get the scrollbar's content node
nsCOMPtr<nsIContent> content = GetContent();
// get the current pos
int32_t curpos = nsSliderFrame::GetCurrentPosition(content);
// get the max pos
int32_t maxpos = nsSliderFrame::GetMaxPosition(content);
// increment the given amount
if (mIncrement) {
curpos += mIncrement;
}
// make sure the current position is between the current and max positions
if (curpos < 0) {
curpos = 0;
} else if (curpos > maxpos) {
curpos = maxpos;
}
// set the current position of the slider.
nsAutoString curposStr;
curposStr.AppendInt(curpos);
nsWeakFrame weakFrame(this);
if (mSmoothScroll) {
content->SetAttr(kNameSpaceID_None, nsGkAtoms::smooth, NS_LITERAL_STRING("true"), false);
}
content->SetAttr(kNameSpaceID_None, nsGkAtoms::curpos, curposStr, false);
// notify the nsScrollbarFrame of the change
AttributeChanged(kNameSpaceID_None, nsGkAtoms::curpos, nsIDOMMutationEvent::MODIFICATION);
if (!weakFrame.IsAlive()) {
return curpos;
}
// notify all nsSliderFrames of the change
nsIFrame::ChildListIterator childLists(this);
for (; !childLists.IsDone(); childLists.Next()) {
nsFrameList::Enumerator childFrames(childLists.CurrentList());
for (; !childFrames.AtEnd(); childFrames.Next()) {
nsIFrame* f = childFrames.get();
nsSliderFrame* sliderFrame = do_QueryFrame(f);
if (sliderFrame) {
sliderFrame->AttributeChanged(kNameSpaceID_None, nsGkAtoms::curpos, nsIDOMMutationEvent::MODIFICATION);
if (!weakFrame.IsAlive()) {
return curpos;
}
}
}
}
// See if we have appearance information for a theme.
const nsStyleDisplay* disp = StyleDisplay();
nsPresContext* presContext = PresContext();
if (disp->mAppearance) {
nsITheme *theme = presContext->GetTheme();
if (theme && theme->ThemeSupportsWidget(presContext, this, disp->mAppearance)) {
bool repaint;
theme->WidgetStateChanged(this, disp->mAppearance, nsGkAtoms::curpos, &repaint);
}
}
content->UnsetAttr(kNameSpaceID_None, nsGkAtoms::smooth, false);
return curpos;
}

View File

@ -83,6 +83,25 @@ public:
virtual nsresult GetMargin(nsMargin& aMargin) MOZ_OVERRIDE;
/**
* The following three methods set the value of mIncrement when a
* scrollbar button is pressed.
*/
void SetIncrementToLine(int32_t aDirection);
void SetIncrementToPage(int32_t aDirection);
void SetIncrementToWhole(int32_t aDirection);
/**
* MoveToNewPosition() adds mIncrement to the current position and
* updates the curpos attribute.
* @note This method might destroy the frame, pres shell, and other objects.
*/
int32_t MoveToNewPosition();
int32_t GetIncrement() { return mIncrement; }
protected:
int32_t mIncrement; // Amount to scroll, in CSSPixels
bool mSmoothScroll;
private:
nsCOMPtr<nsIContent> mScrollbarMediator;
}; // class nsScrollbarFrame

View File

@ -60,6 +60,10 @@ NS_NewSliderFrame (nsIPresShell* aPresShell, nsStyleContext* aContext)
NS_IMPL_FRAMEARENA_HELPERS(nsSliderFrame)
NS_QUERYFRAME_HEAD(nsSliderFrame)
NS_QUERYFRAME_ENTRY(nsSliderFrame)
NS_QUERYFRAME_TAIL_INHERITING(nsBoxFrame)
nsSliderFrame::nsSliderFrame(nsIPresShell* aPresShell, nsStyleContext* aContext):
nsBoxFrame(aPresShell, aContext),
mCurPos(0),
@ -245,19 +249,25 @@ nsSliderFrame::AttributeChanged(int32_t aNameSpaceID,
if (current < min || current > max)
{
if (current < min || max < min)
current = min;
else if (current > max)
current = max;
int32_t direction = 0;
if (current < min || max < min) {
current = min;
direction = -1;
} else if (current > max) {
current = max;
direction = 1;
}
// set the new position and notify observers
nsScrollbarFrame* scrollbarFrame = do_QueryFrame(scrollbarBox);
if (scrollbarFrame) {
nsIScrollbarMediator* mediator = scrollbarFrame->GetScrollbarMediator();
scrollbarFrame->SetIncrementToWhole(direction);
if (mediator) {
mediator->PositionChanged(scrollbarFrame, GetCurrentPosition(scrollbar), current);
mediator->ScrollByWhole(scrollbarFrame, direction);
}
}
// 'this' might be destroyed here
nsContentUtils::AddScriptRunner(
new nsSetAttrRunnable(scrollbar, nsGkAtoms::curpos, current));
@ -619,10 +629,6 @@ nsSliderFrame::PageUpDown(nscoord change)
nsCOMPtr<nsIContent> scrollbar;
scrollbar = GetContentOfBox(scrollbarBox);
if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::dir,
nsGkAtoms::reverse, eCaseMatters))
change = -change;
nscoord pageIncrement = GetPageIncrement(scrollbar);
int32_t curpos = GetCurrentPosition(scrollbar);
int32_t minpos = GetMinPosition(scrollbar);
@ -776,6 +782,7 @@ nsSliderFrame::SetCurrentPositionInternal(nsIContent* aScrollbar, int32_t aNewPo
{
nsCOMPtr<nsIContent> scrollbar = aScrollbar;
nsIFrame* scrollbarBox = GetScrollbar();
nsWeakFrame weakFrame(this);
mUserChanged = true;
@ -784,21 +791,23 @@ nsSliderFrame::SetCurrentPositionInternal(nsIContent* aScrollbar, int32_t aNewPo
// See if we have a mediator.
nsIScrollbarMediator* mediator = scrollbarFrame->GetScrollbarMediator();
if (mediator) {
nsRefPtr<nsPresContext> context = PresContext();
nsCOMPtr<nsIContent> content = GetContent();
mediator->PositionChanged(scrollbarFrame, GetCurrentPosition(scrollbar), aNewPos);
// 'mediator' might be dangling now...
UpdateAttribute(scrollbar, aNewPos, false, aIsSmooth);
nsIFrame* frame = content->GetPrimaryFrame();
if (frame && frame->GetType() == nsGkAtoms::sliderFrame) {
static_cast<nsSliderFrame*>(frame)->CurrentPositionChanged();
nscoord oldPos = nsPresContext::CSSPixelsToAppUnits(GetCurrentPosition(scrollbar));
nscoord newPos = nsPresContext::CSSPixelsToAppUnits(aNewPos);
mediator->ThumbMoved(scrollbarFrame, oldPos, newPos);
if (!weakFrame.IsAlive()) {
return;
}
CurrentPositionChanged();
mUserChanged = false;
return;
}
}
UpdateAttribute(scrollbar, aNewPos, true, aIsSmooth);
if (!weakFrame.IsAlive()) {
return;
}
mUserChanged = false;
#ifdef DEBUG_SLIDER
@ -1124,7 +1133,8 @@ nsSliderFrame::HandlePress(nsPresContext* aPresContext,
mDestinationPoint = eventPoint;
#endif
StartRepeat();
PageUpDown(change);
PageScroll(change);
return NS_OK;
}
@ -1188,7 +1198,8 @@ nsSliderFrame::EnsureOrient()
}
void nsSliderFrame::Notify(void)
void
nsSliderFrame::Notify(void)
{
bool stop = false;
@ -1225,9 +1236,29 @@ void nsSliderFrame::Notify(void)
if (stop) {
StopRepeat();
} else {
PageUpDown(mChange);
PageScroll(mChange);
}
}
void
nsSliderFrame::PageScroll(nscoord aChange)
{
if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::dir,
nsGkAtoms::reverse, eCaseMatters)) {
aChange = -aChange;
}
nsIFrame* scrollbar = GetScrollbar();
nsScrollbarFrame* sb = do_QueryFrame(scrollbar);
if (sb) {
nsIScrollbarMediator* m = sb->GetScrollbarMediator();
sb->SetIncrementToPage(aChange);
if (m) {
m->ScrollByPage(sb, aChange);
return;
}
}
PageUpDown(aChange);
}
NS_IMPL_ISUPPORTS(nsSliderMediator,
nsIDOMEventListener)

View File

@ -42,6 +42,8 @@ class nsSliderFrame : public nsBoxFrame
{
public:
NS_DECL_FRAMEARENA_HELPERS
NS_DECL_QUERYFRAME_TARGET(nsSliderFrame)
NS_DECL_QUERYFRAME
friend class nsSliderMediator;
@ -161,6 +163,7 @@ private:
static void Notify(void* aData) {
(static_cast<nsSliderFrame*>(aData))->Notify();
}
void PageScroll(nscoord aChange);
nsPoint mDestinationPoint;
nsRefPtr<nsSliderMediator> mMediator;

View File

@ -4155,48 +4155,85 @@ nsTreeBodyFrame::ScrollHorzInternal(const ScrollParts& aParts, int32_t aPosition
return NS_OK;
}
NS_IMETHODIMP
nsTreeBodyFrame::ScrollbarButtonPressed(nsScrollbarFrame* aScrollbar, int32_t aOldIndex, int32_t aNewIndex)
void
nsTreeBodyFrame::ScrollByPage(nsScrollbarFrame* aScrollbar, int32_t aDirection)
{
MOZ_ASSERT(aScrollbar != nullptr);
ScrollByPages(aDirection);
}
void
nsTreeBodyFrame::ScrollByWhole(nsScrollbarFrame* aScrollbar, int32_t aDirection)
{
MOZ_ASSERT(aScrollbar != nullptr);
int32_t newIndex = aDirection < 0 ? 0 : mTopRowIndex;
ScrollToRow(newIndex);
}
void
nsTreeBodyFrame::ScrollByLine(nsScrollbarFrame* aScrollbar, int32_t aDirection)
{
MOZ_ASSERT(aScrollbar != nullptr);
ScrollByLines(aDirection);
}
void
nsTreeBodyFrame::RepeatButtonScroll(nsScrollbarFrame* aScrollbar)
{
ScrollParts parts = GetScrollParts();
int32_t increment = aScrollbar->GetIncrement();
int32_t direction = 0;
if (increment < 0) {
direction = -1;
} else if (increment > 0) {
direction = 1;
}
bool isHorizontal = aScrollbar->IsHorizontal();
if (aScrollbar == parts.mVScrollbar) {
if (aNewIndex > aOldIndex)
ScrollToRowInternal(parts, mTopRowIndex+1);
else if (aNewIndex < aOldIndex)
ScrollToRowInternal(parts, mTopRowIndex-1);
nsWeakFrame weakFrame(this);
if (isHorizontal) {
int32_t curpos = aScrollbar->MoveToNewPosition();
if (weakFrame.IsAlive()) {
ScrollHorzInternal(parts, curpos);
}
} else {
nsresult rv = ScrollHorzInternal(parts, aNewIndex);
if (NS_FAILED(rv)) return rv;
ScrollToRowInternal(parts, mTopRowIndex+direction);
}
UpdateScrollbars(parts);
return NS_OK;
if (weakFrame.IsAlive() && mScrollbarActivity) {
mScrollbarActivity->ActivityOccurred();
}
if (weakFrame.IsAlive()) {
UpdateScrollbars(parts);
}
}
NS_IMETHODIMP
nsTreeBodyFrame::PositionChanged(nsScrollbarFrame* aScrollbar, int32_t aOldIndex, int32_t& aNewIndex)
void
nsTreeBodyFrame::ThumbMoved(nsScrollbarFrame* aScrollbar,
nscoord aOldPos,
nscoord aNewPos)
{
ScrollParts parts = GetScrollParts();
if (aOldIndex == aNewIndex)
return NS_OK;
if (aOldPos == aNewPos)
return;
nsWeakFrame weakFrame(this);
// Vertical Scrollbar
if (parts.mVScrollbar == aScrollbar) {
nscoord rh = nsPresContext::AppUnitsToIntCSSPixels(mRowHeight);
nscoord newrow = aNewIndex/rh;
nscoord newIndex = nsPresContext::AppUnitsToIntCSSPixels(aNewPos);
nscoord newrow = newIndex/rh;
ScrollInternal(parts, newrow);
// Horizontal Scrollbar
} else if (parts.mHScrollbar == aScrollbar) {
nsresult rv = ScrollHorzInternal(parts, aNewIndex);
if (NS_FAILED(rv)) return rv;
int32_t newIndex = nsPresContext::AppUnitsToIntCSSPixels(aNewPos);
ScrollHorzInternal(parts, newIndex);
}
if (weakFrame.IsAlive()) {
UpdateScrollbars(parts);
}
UpdateScrollbars(parts);
return NS_OK;
}
// The style cache.

View File

@ -134,9 +134,14 @@ public:
virtual bool PseudoMatches(nsCSSSelector* aSelector) MOZ_OVERRIDE;
// nsIScrollbarMediator
NS_IMETHOD PositionChanged(nsScrollbarFrame* aScrollbar, int32_t aOldIndex, int32_t& aNewIndex) MOZ_OVERRIDE;
NS_IMETHOD ScrollbarButtonPressed(nsScrollbarFrame* aScrollbar, int32_t aOldIndex, int32_t aNewIndex) MOZ_OVERRIDE;
NS_IMETHOD VisibilityChanged(bool aVisible) MOZ_OVERRIDE { Invalidate(); return NS_OK; }
virtual void ScrollByPage(nsScrollbarFrame* aScrollbar, int32_t aDirection) MOZ_OVERRIDE;
virtual void ScrollByWhole(nsScrollbarFrame* aScrollbar, int32_t aDirection) MOZ_OVERRIDE;
virtual void ScrollByLine(nsScrollbarFrame* aScrollbar, int32_t aDirection) MOZ_OVERRIDE;
virtual void RepeatButtonScroll(nsScrollbarFrame* aScrollbar) MOZ_OVERRIDE;
virtual void ThumbMoved(nsScrollbarFrame* aScrollbar,
nscoord aOldPos,
nscoord aNewPos) MOZ_OVERRIDE;
virtual void VisibilityChanged(bool aVisible) MOZ_OVERRIDE { Invalidate(); }
// nsIScrollbarOwner
virtual nsIFrame* GetScrollbarBox(bool aVertical) MOZ_OVERRIDE {