From af293ef660ca1298d7a893f06a5671221eb30ae2 Mon Sep 17 00:00:00 2001 From: "neil@parkwaycc.co.uk" Date: Thu, 12 Apr 2007 13:59:01 -0700 Subject: [PATCH] Bug 376802 Use one global tooltip listener instead of creating one for each XUL element that needs one r=Smaug sr=jst --- content/base/src/nsGkAtomList.h | 1 - layout/build/nsLayoutStatics.cpp | 2 + layout/xul/base/src/nsRootBoxFrame.cpp | 30 +-------- layout/xul/base/src/nsXULTooltipListener.cpp | 64 ++++++++------------ layout/xul/base/src/nsXULTooltipListener.h | 18 ++++-- 5 files changed, 41 insertions(+), 74 deletions(-) diff --git a/content/base/src/nsGkAtomList.h b/content/base/src/nsGkAtomList.h index 82648b88771d..0d1d785db658 100755 --- a/content/base/src/nsGkAtomList.h +++ b/content/base/src/nsGkAtomList.h @@ -831,7 +831,6 @@ GK_ATOM(toolbarbutton, "toolbarbutton") GK_ATOM(toolbaritem, "toolbaritem") GK_ATOM(toolbox, "toolbox") GK_ATOM(tooltip, "tooltip") -GK_ATOM(tooltiplistener, "tooltiplistener") GK_ATOM(tooltiptext, "tooltiptext") GK_ATOM(top, "top") GK_ATOM(topmargin, "topmargin") diff --git a/layout/build/nsLayoutStatics.cpp b/layout/build/nsLayoutStatics.cpp index 3e9af008c602..b84238d2b85e 100644 --- a/layout/build/nsLayoutStatics.cpp +++ b/layout/build/nsLayoutStatics.cpp @@ -83,6 +83,7 @@ #include "nsXULContentUtils.h" #include "nsXULElement.h" #include "nsXULPrototypeCache.h" +#include "nsXULTooltipListener.h" #endif #ifdef MOZ_MATHML @@ -241,6 +242,7 @@ nsLayoutStatics::Shutdown() nsXULElement::ReleaseGlobals(); nsXULPrototypeCache::ReleaseGlobals(); nsXULPrototypeElement::ReleaseGlobals(); + nsXULTooltipListener::ReleaseInstance(); nsSprocketLayout::Shutdown(); #endif diff --git a/layout/xul/base/src/nsRootBoxFrame.cpp b/layout/xul/base/src/nsRootBoxFrame.cpp index 88a26c2c89b7..302c8158e86d 100644 --- a/layout/xul/base/src/nsRootBoxFrame.cpp +++ b/layout/xul/base/src/nsRootBoxFrame.cpp @@ -311,42 +311,16 @@ nsRootBoxFrame::SetDefaultTooltip(nsIContent* 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 nsRootBoxFrame::AddTooltipSupport(nsIContent* aNode) { NS_ENSURE_TRUE(aNode, NS_ERROR_NULL_POINTER); - nsRefPtr 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) return NS_ERROR_OUT_OF_MEMORY; - if (NS_SUCCEEDED(listener->Init(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; + return listener->AddTooltipSupport(aNode); } nsresult diff --git a/layout/xul/base/src/nsXULTooltipListener.cpp b/layout/xul/base/src/nsXULTooltipListener.cpp index 6f2640d5b417..12f5eb1dc076 100644 --- a/layout/xul/base/src/nsXULTooltipListener.cpp +++ b/layout/xul/base/src/nsXULTooltipListener.cpp @@ -61,6 +61,8 @@ #include "nsContentUtils.h" #include "nsIRootBox.h" +nsXULTooltipListener* nsXULTooltipListener::mInstance = nsnull; + ////////////////////////////////////////////////////////////////////////// //// nsISupports @@ -199,7 +201,11 @@ nsXULTooltipListener::MouseMove(nsIDOMEvent* aMouseEvent) mMouseClientX = newMouseX; mMouseClientY = newMouseY; + nsCOMPtr eventTarget; + aMouseEvent->GetCurrentTarget(getter_AddRefs(eventTarget)); + mSourceNode = do_QueryInterface(eventTarget); #ifdef MOZ_XUL + mIsSourceTree = mSourceNode->Tag() == nsGkAtoms::treechildren; if (mIsSourceTree) CheckTreeBodyMove(mouseEvent); #endif @@ -215,17 +221,15 @@ nsXULTooltipListener::MouseMove(nsIDOMEvent* aMouseEvent) if (!mCurrentTooltip) { mTooltipTimer = do_CreateInstance("@mozilla.org/timer;1"); if (mTooltipTimer) { - nsCOMPtr eventTarget; aMouseEvent->GetTarget(getter_AddRefs(eventTarget)); - if (eventTarget) { - nsCOMPtr targetContent(do_QueryInterface(eventTarget)); - mTargetNode = targetContent; - } + mTargetNode = do_QueryInterface(eventTarget); if (mTargetNode) { nsresult rv = mTooltipTimer->InitWithFuncCallback(sTooltipCallback, this, kTooltipShowTime, nsITimer::TYPE_ONE_SHOT); - if (NS_FAILED(rv)) + if (NS_FAILED(rv)) { mTargetNode = nsnull; + mSourceNode = nsnull; + } } } } @@ -284,22 +288,6 @@ nsXULTooltipListener::PopupHiding(nsIDOMEvent* aEvent) PRBool nsXULTooltipListener::sShowTooltips = PR_FALSE; 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 nsXULTooltipListener::AddTooltipSupport(nsIContent* aNode) { @@ -307,8 +295,8 @@ nsXULTooltipListener::AddTooltipSupport(nsIContent* aNode) return NS_ERROR_NULL_POINTER; nsCOMPtr evtTarget(do_QueryInterface(aNode)); - evtTarget->AddEventListener(NS_LITERAL_STRING("mouseout"), (nsIDOMMouseListener*)this, PR_TRUE); - evtTarget->AddEventListener(NS_LITERAL_STRING("mousemove"), (nsIDOMMouseListener*)this, PR_TRUE); + evtTarget->AddEventListener(NS_LITERAL_STRING("mouseout"), (nsIDOMMouseListener*)this, PR_FALSE); + evtTarget->AddEventListener(NS_LITERAL_STRING("mousemove"), (nsIDOMMouseListener*)this, PR_FALSE); return NS_OK; } @@ -320,8 +308,8 @@ nsXULTooltipListener::RemoveTooltipSupport(nsIContent* aNode) return NS_ERROR_NULL_POINTER; nsCOMPtr evtTarget(do_QueryInterface(aNode)); - evtTarget->RemoveEventListener(NS_LITERAL_STRING("mouseout"), (nsIDOMMouseListener*)this, PR_TRUE); - evtTarget->RemoveEventListener(NS_LITERAL_STRING("mousemove"), (nsIDOMMouseListener*)this, PR_TRUE); + evtTarget->RemoveEventListener(NS_LITERAL_STRING("mouseout"), (nsIDOMMouseListener*)this, PR_FALSE); + evtTarget->RemoveEventListener(NS_LITERAL_STRING("mousemove"), (nsIDOMMouseListener*)this, PR_FALSE); return NS_OK; } @@ -369,9 +357,7 @@ nsXULTooltipListener::CheckTreeBodyMove(nsIDOMMouseEvent* aMouseEvent) // XXX check the disabletitletips attribute on the tree content mNeedTitletip = PR_FALSE; if (row >= 0 && obj.EqualsLiteral("text")) { - PRBool isCropped; - obx->IsCellCropped(row, col, &isCropped); - mNeedTitletip = isCropped; + obx->IsCellCropped(row, col, &mNeedTitletip); } if (mCurrentTooltip && (row != mLastTreeRow || col != mLastTreeCol)) { @@ -405,8 +391,7 @@ nsXULTooltipListener::ShowTooltip() } #endif - nsCOMPtr targetNode(do_QueryInterface(mTargetNode)); - xulDoc->SetTooltipNode(targetNode); + xulDoc->SetTooltipNode(mTargetNode); LaunchTooltip(mSourceNode, mMouseClientX, mMouseClientY); mTargetNode = nsnull; @@ -440,6 +425,7 @@ nsXULTooltipListener::ShowTooltip() evtTarget->AddEventListener(NS_LITERAL_STRING("keydown"), (nsIDOMMouseListener*)this, PR_TRUE); } + mSourceNode = nsnull; } } @@ -699,6 +685,10 @@ nsXULTooltipListener::DestroyTooltip() // kill any ongoing timers KillTooltipTimer(); + mSourceNode = nsnull; +#ifdef MOZ_XUL + mLastTreeCol = nsnull; +#endif if (mAutoHideTimer) { mAutoHideTimer->Cancel(); mAutoHideTimer = nsnull; @@ -734,19 +724,15 @@ nsXULTooltipListener::CreateAutoHideTimer() void nsXULTooltipListener::sTooltipCallback(nsITimer *aTimer, void *aListener) { - nsXULTooltipListener* self = NS_STATIC_CAST(nsXULTooltipListener*, aListener); - if (self) - self->ShowTooltip(); + if (mInstance) + mInstance->ShowTooltip(); } void nsXULTooltipListener::sAutoHideCallback(nsITimer *aTimer, void* aListener) { - nsXULTooltipListener* self = NS_STATIC_CAST(nsXULTooltipListener*, aListener); - if (self) { - nsCOMPtr kungFuDeathGrip(self); - self->HideTooltip(); - } + if (mInstance) + mInstance->HideTooltip(); } #ifdef MOZ_XUL diff --git a/layout/xul/base/src/nsXULTooltipListener.h b/layout/xul/base/src/nsXULTooltipListener.h index 2e9113f6992c..81be425dfd13 100644 --- a/layout/xul/base/src/nsXULTooltipListener.h +++ b/layout/xul/base/src/nsXULTooltipListener.h @@ -60,9 +60,6 @@ class nsXULTooltipListener : public nsIDOMMouseListener, { public: - nsXULTooltipListener(); - virtual ~nsXULTooltipListener(); - // nsISupports NS_DECL_ISUPPORTS @@ -96,12 +93,20 @@ public: // nsIDOMEventListener NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent); - nsresult Init(nsIContent* aSourceNode); nsresult AddTooltipSupport(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: + nsXULTooltipListener(); + ~nsXULTooltipListener(); + // pref callback for when the "show tooltips" pref changes static int sTooltipPrefChanged (const char* aPref, void* aData); static PRBool sShowTooltips; @@ -125,10 +130,11 @@ protected: // can be really used (i.e. tooltip is not a menu). nsresult GetTooltipFor(nsIContent* aTarget, nsIContent** aTooltip); + static nsXULTooltipListener* mInstance; static int ToolbarTipsPrefChanged(const char *aPref, void *aClosure); - nsIContent* mSourceNode; - nsCOMPtr mTargetNode; + nsCOMPtr mSourceNode; + nsCOMPtr mTargetNode; nsCOMPtr mCurrentTooltip; // a timer for showing the tooltip