Bug 376802 Use one global tooltip listener instead of creating one for each XUL element that needs one r=Smaug sr=jst

This commit is contained in:
neil@parkwaycc.co.uk 2007-04-12 13:59:01 -07:00
parent 61877955f2
commit af293ef660
5 changed files with 41 additions and 74 deletions

View File

@ -831,7 +831,6 @@ GK_ATOM(toolbarbutton, "toolbarbutton")
GK_ATOM(toolbaritem, "toolbaritem") GK_ATOM(toolbaritem, "toolbaritem")
GK_ATOM(toolbox, "toolbox") GK_ATOM(toolbox, "toolbox")
GK_ATOM(tooltip, "tooltip") GK_ATOM(tooltip, "tooltip")
GK_ATOM(tooltiplistener, "tooltiplistener")
GK_ATOM(tooltiptext, "tooltiptext") GK_ATOM(tooltiptext, "tooltiptext")
GK_ATOM(top, "top") GK_ATOM(top, "top")
GK_ATOM(topmargin, "topmargin") GK_ATOM(topmargin, "topmargin")

View File

@ -83,6 +83,7 @@
#include "nsXULContentUtils.h" #include "nsXULContentUtils.h"
#include "nsXULElement.h" #include "nsXULElement.h"
#include "nsXULPrototypeCache.h" #include "nsXULPrototypeCache.h"
#include "nsXULTooltipListener.h"
#endif #endif
#ifdef MOZ_MATHML #ifdef MOZ_MATHML
@ -241,6 +242,7 @@ nsLayoutStatics::Shutdown()
nsXULElement::ReleaseGlobals(); nsXULElement::ReleaseGlobals();
nsXULPrototypeCache::ReleaseGlobals(); nsXULPrototypeCache::ReleaseGlobals();
nsXULPrototypeElement::ReleaseGlobals(); nsXULPrototypeElement::ReleaseGlobals();
nsXULTooltipListener::ReleaseInstance();
nsSprocketLayout::Shutdown(); nsSprocketLayout::Shutdown();
#endif #endif

View File

@ -311,42 +311,16 @@ nsRootBoxFrame::SetDefaultTooltip(nsIContent* aTooltip)
mDefaultTooltip = aTooltip; mDefaultTooltip = aTooltip;
} }
static void
TooltipListenerPropertyDtor(void *aObject, nsIAtom *aPropertyName,
void *aPropertyValue, void *aData)
{
nsXULTooltipListener* listener =
NS_STATIC_CAST(nsXULTooltipListener*, aPropertyValue);
if (listener) {
listener->RemoveTooltipSupport(NS_STATIC_CAST(nsIContent*, aObject));
NS_RELEASE(listener);
}
}
nsresult nsresult
nsRootBoxFrame::AddTooltipSupport(nsIContent* aNode) nsRootBoxFrame::AddTooltipSupport(nsIContent* aNode)
{ {
NS_ENSURE_TRUE(aNode, NS_ERROR_NULL_POINTER); NS_ENSURE_TRUE(aNode, NS_ERROR_NULL_POINTER);
nsRefPtr<nsXULTooltipListener> listener =
NS_STATIC_CAST(nsXULTooltipListener*,
aNode->GetProperty(nsGkAtoms::tooltiplistener));
if (listener) {
// Tooltip listener is already installed.
return NS_OK;
}
listener = new nsXULTooltipListener(); nsXULTooltipListener *listener = nsXULTooltipListener::GetInstance();
if (!listener) if (!listener)
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
if (NS_SUCCEEDED(listener->Init(aNode))) { return listener->AddTooltipSupport(aNode);
nsresult rv = aNode->SetProperty(nsGkAtoms::tooltiplistener, listener,
TooltipListenerPropertyDtor, PR_TRUE);
NS_ENSURE_SUCCESS(rv, rv);
nsXULTooltipListener* listenerRef = listener;
NS_ADDREF(listenerRef);
}
return NS_OK;
} }
nsresult nsresult

View File

@ -61,6 +61,8 @@
#include "nsContentUtils.h" #include "nsContentUtils.h"
#include "nsIRootBox.h" #include "nsIRootBox.h"
nsXULTooltipListener* nsXULTooltipListener::mInstance = nsnull;
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
//// nsISupports //// nsISupports
@ -199,7 +201,11 @@ nsXULTooltipListener::MouseMove(nsIDOMEvent* aMouseEvent)
mMouseClientX = newMouseX; mMouseClientX = newMouseX;
mMouseClientY = newMouseY; mMouseClientY = newMouseY;
nsCOMPtr<nsIDOMEventTarget> eventTarget;
aMouseEvent->GetCurrentTarget(getter_AddRefs(eventTarget));
mSourceNode = do_QueryInterface(eventTarget);
#ifdef MOZ_XUL #ifdef MOZ_XUL
mIsSourceTree = mSourceNode->Tag() == nsGkAtoms::treechildren;
if (mIsSourceTree) if (mIsSourceTree)
CheckTreeBodyMove(mouseEvent); CheckTreeBodyMove(mouseEvent);
#endif #endif
@ -215,17 +221,15 @@ nsXULTooltipListener::MouseMove(nsIDOMEvent* aMouseEvent)
if (!mCurrentTooltip) { if (!mCurrentTooltip) {
mTooltipTimer = do_CreateInstance("@mozilla.org/timer;1"); mTooltipTimer = do_CreateInstance("@mozilla.org/timer;1");
if (mTooltipTimer) { if (mTooltipTimer) {
nsCOMPtr<nsIDOMEventTarget> eventTarget;
aMouseEvent->GetTarget(getter_AddRefs(eventTarget)); aMouseEvent->GetTarget(getter_AddRefs(eventTarget));
if (eventTarget) { mTargetNode = do_QueryInterface(eventTarget);
nsCOMPtr<nsIContent> targetContent(do_QueryInterface(eventTarget));
mTargetNode = targetContent;
}
if (mTargetNode) { if (mTargetNode) {
nsresult rv = mTooltipTimer->InitWithFuncCallback(sTooltipCallback, this, nsresult rv = mTooltipTimer->InitWithFuncCallback(sTooltipCallback, this,
kTooltipShowTime, nsITimer::TYPE_ONE_SHOT); kTooltipShowTime, nsITimer::TYPE_ONE_SHOT);
if (NS_FAILED(rv)) if (NS_FAILED(rv)) {
mTargetNode = nsnull; mTargetNode = nsnull;
mSourceNode = nsnull;
}
} }
} }
} }
@ -284,22 +288,6 @@ nsXULTooltipListener::PopupHiding(nsIDOMEvent* aEvent)
PRBool nsXULTooltipListener::sShowTooltips = PR_FALSE; PRBool nsXULTooltipListener::sShowTooltips = PR_FALSE;
PRUint32 nsXULTooltipListener::sTooltipListenerCount = 0; PRUint32 nsXULTooltipListener::sTooltipListenerCount = 0;
// XXX: This could all be done in the ctor.
nsresult
nsXULTooltipListener::Init(nsIContent* aSourceNode)
{
mSourceNode = aSourceNode;
AddTooltipSupport(aSourceNode);
#ifdef MOZ_XUL
// if the target is an treechildren, we may have some special
// case handling to do
mIsSourceTree = mSourceNode->Tag() == nsGkAtoms::treechildren;
#endif
return NS_OK;
}
nsresult nsresult
nsXULTooltipListener::AddTooltipSupport(nsIContent* aNode) nsXULTooltipListener::AddTooltipSupport(nsIContent* aNode)
{ {
@ -307,8 +295,8 @@ nsXULTooltipListener::AddTooltipSupport(nsIContent* aNode)
return NS_ERROR_NULL_POINTER; return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(aNode)); nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(aNode));
evtTarget->AddEventListener(NS_LITERAL_STRING("mouseout"), (nsIDOMMouseListener*)this, PR_TRUE); evtTarget->AddEventListener(NS_LITERAL_STRING("mouseout"), (nsIDOMMouseListener*)this, PR_FALSE);
evtTarget->AddEventListener(NS_LITERAL_STRING("mousemove"), (nsIDOMMouseListener*)this, PR_TRUE); evtTarget->AddEventListener(NS_LITERAL_STRING("mousemove"), (nsIDOMMouseListener*)this, PR_FALSE);
return NS_OK; return NS_OK;
} }
@ -320,8 +308,8 @@ nsXULTooltipListener::RemoveTooltipSupport(nsIContent* aNode)
return NS_ERROR_NULL_POINTER; return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(aNode)); nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(aNode));
evtTarget->RemoveEventListener(NS_LITERAL_STRING("mouseout"), (nsIDOMMouseListener*)this, PR_TRUE); evtTarget->RemoveEventListener(NS_LITERAL_STRING("mouseout"), (nsIDOMMouseListener*)this, PR_FALSE);
evtTarget->RemoveEventListener(NS_LITERAL_STRING("mousemove"), (nsIDOMMouseListener*)this, PR_TRUE); evtTarget->RemoveEventListener(NS_LITERAL_STRING("mousemove"), (nsIDOMMouseListener*)this, PR_FALSE);
return NS_OK; return NS_OK;
} }
@ -369,9 +357,7 @@ nsXULTooltipListener::CheckTreeBodyMove(nsIDOMMouseEvent* aMouseEvent)
// XXX check the disabletitletips attribute on the tree content // XXX check the disabletitletips attribute on the tree content
mNeedTitletip = PR_FALSE; mNeedTitletip = PR_FALSE;
if (row >= 0 && obj.EqualsLiteral("text")) { if (row >= 0 && obj.EqualsLiteral("text")) {
PRBool isCropped; obx->IsCellCropped(row, col, &mNeedTitletip);
obx->IsCellCropped(row, col, &isCropped);
mNeedTitletip = isCropped;
} }
if (mCurrentTooltip && (row != mLastTreeRow || col != mLastTreeCol)) { if (mCurrentTooltip && (row != mLastTreeRow || col != mLastTreeCol)) {
@ -405,8 +391,7 @@ nsXULTooltipListener::ShowTooltip()
} }
#endif #endif
nsCOMPtr<nsIDOMNode> targetNode(do_QueryInterface(mTargetNode)); xulDoc->SetTooltipNode(mTargetNode);
xulDoc->SetTooltipNode(targetNode);
LaunchTooltip(mSourceNode, mMouseClientX, mMouseClientY); LaunchTooltip(mSourceNode, mMouseClientX, mMouseClientY);
mTargetNode = nsnull; mTargetNode = nsnull;
@ -440,6 +425,7 @@ nsXULTooltipListener::ShowTooltip()
evtTarget->AddEventListener(NS_LITERAL_STRING("keydown"), evtTarget->AddEventListener(NS_LITERAL_STRING("keydown"),
(nsIDOMMouseListener*)this, PR_TRUE); (nsIDOMMouseListener*)this, PR_TRUE);
} }
mSourceNode = nsnull;
} }
} }
@ -699,6 +685,10 @@ nsXULTooltipListener::DestroyTooltip()
// kill any ongoing timers // kill any ongoing timers
KillTooltipTimer(); KillTooltipTimer();
mSourceNode = nsnull;
#ifdef MOZ_XUL
mLastTreeCol = nsnull;
#endif
if (mAutoHideTimer) { if (mAutoHideTimer) {
mAutoHideTimer->Cancel(); mAutoHideTimer->Cancel();
mAutoHideTimer = nsnull; mAutoHideTimer = nsnull;
@ -734,19 +724,15 @@ nsXULTooltipListener::CreateAutoHideTimer()
void void
nsXULTooltipListener::sTooltipCallback(nsITimer *aTimer, void *aListener) nsXULTooltipListener::sTooltipCallback(nsITimer *aTimer, void *aListener)
{ {
nsXULTooltipListener* self = NS_STATIC_CAST(nsXULTooltipListener*, aListener); if (mInstance)
if (self) mInstance->ShowTooltip();
self->ShowTooltip();
} }
void void
nsXULTooltipListener::sAutoHideCallback(nsITimer *aTimer, void* aListener) nsXULTooltipListener::sAutoHideCallback(nsITimer *aTimer, void* aListener)
{ {
nsXULTooltipListener* self = NS_STATIC_CAST(nsXULTooltipListener*, aListener); if (mInstance)
if (self) { mInstance->HideTooltip();
nsCOMPtr<nsIDOMMouseListener> kungFuDeathGrip(self);
self->HideTooltip();
}
} }
#ifdef MOZ_XUL #ifdef MOZ_XUL

View File

@ -60,9 +60,6 @@ class nsXULTooltipListener : public nsIDOMMouseListener,
{ {
public: public:
nsXULTooltipListener();
virtual ~nsXULTooltipListener();
// nsISupports // nsISupports
NS_DECL_ISUPPORTS NS_DECL_ISUPPORTS
@ -96,12 +93,20 @@ public:
// nsIDOMEventListener // nsIDOMEventListener
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent); NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
nsresult Init(nsIContent* aSourceNode);
nsresult AddTooltipSupport(nsIContent* aNode); nsresult AddTooltipSupport(nsIContent* aNode);
nsresult RemoveTooltipSupport(nsIContent* aNode); nsresult RemoveTooltipSupport(nsIContent* aNode);
static nsXULTooltipListener* GetInstance() {
if (!mInstance)
NS_IF_ADDREF(mInstance = new nsXULTooltipListener());
return mInstance;
}
static void ReleaseInstance() { NS_IF_RELEASE(mInstance); }
protected: protected:
nsXULTooltipListener();
~nsXULTooltipListener();
// pref callback for when the "show tooltips" pref changes // pref callback for when the "show tooltips" pref changes
static int sTooltipPrefChanged (const char* aPref, void* aData); static int sTooltipPrefChanged (const char* aPref, void* aData);
static PRBool sShowTooltips; static PRBool sShowTooltips;
@ -125,10 +130,11 @@ protected:
// can be really used (i.e. tooltip is not a menu). // can be really used (i.e. tooltip is not a menu).
nsresult GetTooltipFor(nsIContent* aTarget, nsIContent** aTooltip); nsresult GetTooltipFor(nsIContent* aTarget, nsIContent** aTooltip);
static nsXULTooltipListener* mInstance;
static int ToolbarTipsPrefChanged(const char *aPref, void *aClosure); static int ToolbarTipsPrefChanged(const char *aPref, void *aClosure);
nsIContent* mSourceNode; nsCOMPtr<nsIContent> mSourceNode;
nsCOMPtr<nsIContent> mTargetNode; nsCOMPtr<nsIDOMNode> mTargetNode;
nsCOMPtr<nsIContent> mCurrentTooltip; nsCOMPtr<nsIContent> mCurrentTooltip;
// a timer for showing the tooltip // a timer for showing the tooltip