Bug 344228. Fix up some naughty uses of nsIScrollbarMediator. r=enndeakin,sr=bzbarsky

This commit is contained in:
roc+%cs.cmu.edu 2006-12-07 19:53:41 +00:00
Родитель 6720414ade
Коммит 361de71875
10 изменённых файлов: 144 добавлений и 85 удалений

Просмотреть файл

@ -2584,11 +2584,11 @@ nsGfxScrollFrameInner::SetScrollbarVisibility(nsIBox* aScrollbar, PRBool aVisibl
if (!aScrollbar)
return;
nsCOMPtr<nsIScrollbarFrame> scrollbar(do_QueryInterface(aScrollbar));
nsIScrollbarFrame* scrollbar;
CallQueryInterface(aScrollbar, &scrollbar);
if (scrollbar) {
// See if we have a mediator.
nsCOMPtr<nsIScrollbarMediator> mediator;
scrollbar->GetScrollbarMediator(getter_AddRefs(mediator));
nsIScrollbarMediator* mediator = scrollbar->GetScrollbarMediator();
if (mediator) {
// Inform the mediator of the visibility change.
mediator->VisibilityChanged(scrollbar, aVisible);
@ -2688,12 +2688,14 @@ nsGfxScrollFrameInner::SaveState(nsIStatefulFrame::SpecialStateID aStateID)
if (mIsRoot && aStateID == nsIStatefulFrame::eNoID) {
return nsnull;
}
// XXX can this actually get hit? I don't think so
nsCOMPtr<nsIScrollbarMediator> mediator;
nsIFrame* first = GetScrolledFrame();
mediator = do_QueryInterface(first);
if (mediator) {
// Child manages its own scrolling. Bail.
NS_ERROR("This code shouldn't be hit; alert robert@ocallahan.org");
return nsnull;
}

Просмотреть файл

@ -39,9 +39,9 @@
#ifndef nsIScrollbarFrame_h___
#define nsIScrollbarFrame_h___
// {9A6B0416-4A5D-4550-BEB5-C94D18A69A94}
// {660e5ed6-1cf7-47ff-b094-c588c21986e8}
#define NS_ISCROLLBARFRAME_IID \
{ 0x9a6b0416, 0x4a5d, 0x4550, { 0xbe, 0xb5, 0xc9, 0x4d, 0x18, 0xa6, 0x9a, 0x94 } }
{ 0x660e5ed6, 0x1cf7, 0x47ff, { 0xb0, 0x94, 0xc5, 0x88, 0xc2, 0x19, 0x86, 0xe8 } }
static NS_DEFINE_IID(kIScrollbarFrameIID, NS_ISCROLLBARFRAME_IID);
@ -52,11 +52,14 @@ class nsIScrollbarFrame : public nsISupports {
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISCROLLBARFRAME_IID)
NS_IMETHOD GetScrollbarMediator(nsIScrollbarMediator** aResult) = 0;
NS_IMETHOD SetScrollbarMediator(nsIScrollbarMediator* aMediator) = 0;
// Sets the scrollbar mediator content. We will try to get its primary frame
// and then QI that to nsIScrollbarMediator as necessary.
virtual void SetScrollbarMediatorContent(nsIContent* aMediator) = 0;
// Do NOT hold on to this.
virtual nsIScrollbarMediator* GetScrollbarMediator() = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIScrollbarFrame, NS_ISCROLLBARFRAME_IID)
#endif

Просмотреть файл

@ -257,7 +257,7 @@ nsListBoxBodyFrame::Init(nsIContent* aContent,
}
nsCOMPtr<nsIScrollbarFrame> scrollbarFrame(do_QueryInterface(verticalScrollbar));
scrollbarFrame->SetScrollbarMediator(this);
scrollbarFrame->SetScrollbarMediatorContent(GetContent());
nsBoxLayoutState boxLayoutState(presContext);

Просмотреть файл

@ -64,19 +64,19 @@ NS_NewNativeScrollbarFrame (nsIPresShell* aPresShell, nsStyleContext* aContext)
//
// QueryInterface
//
NS_INTERFACE_MAP_BEGIN(nsNativeScrollbarFrame)
NS_INTERFACE_MAP_END_INHERITING(nsBoxFrame)
nsNativeScrollbarFrame::~nsNativeScrollbarFrame ( )
NS_IMETHODIMP
nsNativeScrollbarFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr)
{
// frame is going away, unhook the native scrollbar from
// the content node just to be safe about lifetime issues
nsCOMPtr<nsINativeScrollbar> scrollbar ( do_QueryInterface(mScrollbar) );
if ( scrollbar )
scrollbar->SetContent(nsnull, nsnull, nsnull);
if (!aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
if (aIID.Equals(NS_GET_IID(nsIScrollbarMediator))) {
*aInstancePtr = (void*) ((nsIScrollbarMediator*) this);
return NS_OK;
}
return nsBoxFrame::QueryInterface(aIID, aInstancePtr);
}
//
// Init
//
@ -119,37 +119,41 @@ nsNativeScrollbarFrame::Init(nsIContent* aContent,
return rv;
}
void
nsNativeScrollbarFrame::Destroy()
{
nsCOMPtr<nsINativeScrollbar> scrollbar(do_QueryInterface(mScrollbar));
if (scrollbar) {
// frame is going away, unhook the native scrollbar from
// the content node just to be safe about lifetime issues
scrollbar->SetContent(nsnull, nsnull, nsnull);
}
}
//
// FindScrollbar
// FindParts
//
// Walk up the parent frame tree and find the content node of the frame
// with the tag "scrollbar". This is the content node that the GFX Scroll Frame
// is watching for attribute changes.
// is watching for attribute changes. We return the associated frame and
// any mediator.
//
nsresult
nsNativeScrollbarFrame::FindScrollbar(nsIFrame* start, nsIFrame** outFrame,
nsIContent** outContent)
nsNativeScrollbarFrame::Parts
nsNativeScrollbarFrame::FindParts()
{
*outContent = nsnull;
*outFrame = nsnull;
while ( start ) {
start = start->GetParent();
if ( start ) {
// get the content node
nsIContent* currContent = start->GetContent();
nsIFrame* f;
for (f = GetParent(); f; f = f->GetParent()) {
nsIContent* currContent = f->GetContent();
if (currContent && currContent->Tag() == nsXULAtoms::scrollbar) {
*outContent = currContent;
*outFrame = start;
NS_ADDREF(*outContent);
return NS_OK;
}
if (currContent && currContent->Tag() == nsXULAtoms::scrollbar) {
nsIScrollbarFrame* sb;
CallQueryInterface(f, &sb);
if (sb)
return Parts(f, sb, sb->GetScrollbarMediator());
}
}
return NS_OK;
return Parts(nsnull, nsnull, nsnull);
}
NS_IMETHODIMP
@ -213,20 +217,15 @@ nsNativeScrollbarFrame::AttributeChanged(PRInt32 aNameSpaceID,
PRInt32 oldPosition = (PRInt32)current;
PRInt32 curPosition = maxValue;
nsCOMPtr<nsIContent> scrollbarContent;
nsIFrame* sbFrame = nsnull;
FindScrollbar(this, &sbFrame, getter_AddRefs(scrollbarContent));
nsCOMPtr<nsIScrollbarFrame> scrollbarFrame(do_QueryInterface(sbFrame));
if (scrollbarFrame) {
nsCOMPtr<nsIScrollbarMediator> mediator;
scrollbarFrame->GetScrollbarMediator(getter_AddRefs(mediator));
if (mediator)
mediator->PositionChanged(scrollbarFrame, oldPosition, /* inout */ curPosition);
Parts parts = FindParts();
if (parts.mMediator) {
parts.mMediator->PositionChanged(parts.mIScrollbarFrame, oldPosition, /* inout */ curPosition);
}
nsAutoString currentStr;
currentStr.AppendInt(curPosition);
scrollbarContent->SetAttr(kNameSpaceID_None, nsXULAtoms::curpos, currentStr, PR_TRUE);
parts.mScrollbarFrame->GetContent()->
SetAttr(kNameSpaceID_None, nsXULAtoms::curpos, currentStr, PR_TRUE);
}
}
@ -290,25 +289,18 @@ nsNativeScrollbarFrame::Hookup()
if (!mScrollbarNeedsContent)
return;
nsCOMPtr<nsIContent> scrollbarContent;
nsIFrame* scrollbarFrame = nsnull;
FindScrollbar(this, &scrollbarFrame, getter_AddRefs(scrollbarContent));
nsCOMPtr<nsIScrollbarMediator> mediator;
nsCOMPtr<nsIScrollbarFrame> sb(do_QueryInterface(scrollbarFrame));
if (!sb) {
NS_WARNING("ScrollbarFrame doesn't implement nsIScrollbarFrame");
return;
}
sb->GetScrollbarMediator(getter_AddRefs(mediator));
nsCOMPtr<nsINativeScrollbar> scrollbar(do_QueryInterface(mScrollbar));
if (!mScrollbar) {
if (!scrollbar) {
NS_WARNING("Native scrollbar widget doesn't implement nsINativeScrollbar");
return;
}
scrollbar->SetContent(scrollbarContent, sb, mediator);
Parts parts = FindParts();
// We can't just pass 'mediator' to the widget, because 'mediator' might go away.
// So pass a pointer to us. When we go away, we can tell the widget.
nsIContent* scrollbarContent = parts.mScrollbarFrame->GetContent();
scrollbar->SetContent(scrollbarContent,
parts.mIScrollbarFrame, parts.mMediator ? this : nsnull);
mScrollbarNeedsContent = PR_FALSE;
if (!scrollbarContent)
@ -328,3 +320,29 @@ nsNativeScrollbarFrame::Hookup()
scrollbar->SetPosition(curpos);
}
NS_IMETHODIMP
nsNativeScrollbarFrame::PositionChanged(nsISupports* aScrollbar, PRInt32 aOldIndex, PRInt32& aNewIndex)
{
Parts parts = FindParts();
if (!parts.mMediator)
return NS_OK;
return parts.mMediator->PositionChanged(aScrollbar, aOldIndex, aNewIndex);
}
NS_IMETHODIMP
nsNativeScrollbarFrame::ScrollbarButtonPressed(nsISupports* aScrollbar, PRInt32 aOldIndex, PRInt32 aNewIndex)
{
Parts parts = FindParts();
if (!parts.mMediator)
return NS_OK;
return parts.mMediator->ScrollbarButtonPressed(aScrollbar, aOldIndex, aNewIndex);
}
NS_IMETHODIMP
nsNativeScrollbarFrame::VisibilityChanged(nsISupports* aScrollbar, PRBool aVisible)
{
Parts parts = FindParts();
if (!parts.mMediator)
return NS_OK;
return parts.mMediator->VisibilityChanged(aScrollbar, aVisible);
}

Просмотреть файл

@ -49,6 +49,7 @@
#include "nsScrollbarFrame.h"
#include "nsIWidget.h"
#include "nsIScrollbarMediator.h"
class nsISupportsArray;
class nsIPresShell;
@ -58,12 +59,11 @@ class nsStyleContext;
nsIFrame* NS_NewNativeScrollbarFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
class nsNativeScrollbarFrame : public nsBoxFrame
class nsNativeScrollbarFrame : public nsBoxFrame, public nsIScrollbarMediator
{
public:
nsNativeScrollbarFrame(nsIPresShell* aShell, nsStyleContext* aContext):
nsBoxFrame(aShell, aContext), mScrollbarNeedsContent(PR_TRUE) {}
virtual ~nsNativeScrollbarFrame ( ) ;
#ifdef DEBUG
NS_IMETHOD GetFrameName(nsAString& aResult) const {
@ -88,15 +88,30 @@ public:
nsReflowStatus& aStatus);
NS_IMETHOD GetPrefSize(nsBoxLayoutState& aState, nsSize& aSize);
virtual void Destroy();
// nsIScrollbarMediator forwarding
NS_IMETHOD PositionChanged(nsISupports* aScrollbar, PRInt32 aOldIndex, PRInt32& aNewIndex);
NS_IMETHOD ScrollbarButtonPressed(nsISupports* aScrollbar, PRInt32 aOldIndex, PRInt32 aNewIndex);
NS_IMETHOD VisibilityChanged(nsISupports* aScrollbar, PRBool aVisible);
protected:
void Hookup();
nsresult FindScrollbar(nsIFrame* start, nsIFrame** outFrame, nsIContent** outContent);
struct Parts {
nsIFrame* mScrollbarFrame;
nsIScrollbarFrame* mIScrollbarFrame;
nsIScrollbarMediator* mMediator;
Parts(nsIFrame* aFrame, nsIScrollbarFrame* aIScrollbarFrame, nsIScrollbarMediator* aMediator) :
mScrollbarFrame(aFrame), mIScrollbarFrame(aIScrollbarFrame), mMediator(aMediator) {}
};
Parts FindParts();
PRBool IsVertical() const { return mIsVertical; }
private:
PRPackedBool mIsVertical;

Просмотреть файл

@ -253,10 +253,10 @@ nsScrollbarButtonFrame::DoButtonAction(PRBool aSmoothScroll)
else if (curpos > maxpos)
curpos = maxpos;
nsCOMPtr<nsIScrollbarFrame> sb(do_QueryInterface(scrollbar));
nsIScrollbarFrame* sb;
CallQueryInterface(scrollbar, &sb);
if (sb) {
nsCOMPtr<nsIScrollbarMediator> m;
sb->GetScrollbarMediator(getter_AddRefs(m));
nsIScrollbarMediator* m = sb->GetScrollbarMediator();
if (m) {
m->ScrollbarButtonPressed(sb, oldpos, curpos);
return;

Просмотреть файл

@ -48,7 +48,7 @@
#include "nsIScrollableFrame.h"
#include "nsIView.h"
#include "nsIViewManager.h"
#include "nsIScrollbarMediator.h"
//
// NS_NewToolbarFrame
@ -176,3 +176,22 @@ nsScrollbarFrame::HandleRelease(nsPresContext* aPresContext,
return NS_OK;
}
void
nsScrollbarFrame::SetScrollbarMediatorContent(nsIContent* aMediator)
{
mScrollbarMediator = aMediator;
}
nsIScrollbarMediator*
nsScrollbarFrame::GetScrollbarMediator()
{
if (!mScrollbarMediator)
return nsnull;
nsIFrame* f =
GetPresContext()->PresShell()->GetPrimaryFrameFor(mScrollbarMediator);
if (!f)
return nsnull;
nsIScrollbarMediator* sbm;
CallQueryInterface(f, &sbm);
return sbm;
}

Просмотреть файл

@ -100,8 +100,8 @@ public:
virtual PRBool IsContainingBlock() const;
// nsIScrollbarFrame
NS_IMETHOD SetScrollbarMediator(nsIScrollbarMediator* aMediator) { mScrollbarMediator = aMediator; return NS_OK; };
NS_IMETHOD GetScrollbarMediator(nsIScrollbarMediator** aResult) { *aResult = mScrollbarMediator; return NS_OK; };
virtual void SetScrollbarMediatorContent(nsIContent* aMediator);
virtual nsIScrollbarMediator* GetScrollbarMediator();
// nsBox methods
@ -113,8 +113,9 @@ public:
* hide the children too.
*/
virtual PRBool DoesClipChildren() { return PR_TRUE; }
private:
nsIScrollbarMediator* mScrollbarMediator;
nsCOMPtr<nsIContent> mScrollbarMediator;
}; // class nsScrollbarFrame
#endif

Просмотреть файл

@ -252,10 +252,10 @@ nsSliderFrame::AttributeChanged(PRInt32 aNameSpaceID,
current = max;
// set the new position and notify observers
nsCOMPtr<nsIScrollbarFrame> scrollbarFrame(do_QueryInterface(scrollbarBox));
nsIScrollbarFrame* scrollbarFrame;
CallQueryInterface(scrollbarBox, &scrollbarFrame);
if (scrollbarFrame) {
nsCOMPtr<nsIScrollbarMediator> mediator;
scrollbarFrame->GetScrollbarMediator(getter_AddRefs(mediator));
nsIScrollbarMediator* mediator = scrollbarFrame->GetScrollbarMediator();
if (mediator) {
mediator->PositionChanged(scrollbarFrame, GetCurrentPosition(scrollbar), current);
}
@ -738,14 +738,15 @@ nsSliderFrame::SetCurrentPosition(nsIContent* scrollbar, nsIFrame* aThumbFrame,
newpos = maxpos;
nsIBox* scrollbarBox = GetScrollbar();
nsCOMPtr<nsIScrollbarFrame> scrollbarFrame(do_QueryInterface(scrollbarBox));
nsIScrollbarFrame* scrollbarFrame;
CallQueryInterface(scrollbarBox, &scrollbarFrame);
if (scrollbarFrame) {
// See if we have a mediator.
nsCOMPtr<nsIScrollbarMediator> mediator;
scrollbarFrame->GetScrollbarMediator(getter_AddRefs(mediator));
nsIScrollbarMediator* mediator = scrollbarFrame->GetScrollbarMediator();
if (mediator) {
mediator->PositionChanged(scrollbarFrame, GetCurrentPosition(scrollbar), newpos);
// 'mediator' might be dangling now...
UpdateAttribute(scrollbar, newpos, PR_FALSE, aIsSmooth);
CurrentPositionChanged(GetPresContext());
return;

Просмотреть файл

@ -779,13 +779,13 @@ nsTreeBodyFrame::ScrollParts nsTreeBodyFrame::GetScrollParts()
// dumb! We should know where these frames are.
FindScrollParts(treeFrame, &result);
if (result.mHScrollbar) {
result.mHScrollbar->SetScrollbarMediator(this);
result.mHScrollbar->SetScrollbarMediatorContent(GetContent());
nsIFrame* f;
CallQueryInterface(result.mHScrollbar, &f);
result.mHScrollbarContent = f->GetContent();
}
if (result.mVScrollbar) {
result.mVScrollbar->SetScrollbarMediator(this);
result.mVScrollbar->SetScrollbarMediatorContent(GetContent());
nsIFrame* f;
CallQueryInterface(result.mVScrollbar, &f);
result.mVScrollbarContent = f->GetContent();