mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 417534 - "XUL Tooltips keep windows alive until shutdown". r=enn, sr=peterv, a=blocking1.9+.
This commit is contained in:
parent
7f4e81ef91
commit
b3510107b1
@ -112,6 +112,8 @@ PRBool NS_SVGEnabled();
|
||||
#include "nsError.h"
|
||||
#include "nsTraceRefcnt.h"
|
||||
|
||||
#include "nsCycleCollector.h"
|
||||
|
||||
static nsrefcnt sLayoutStaticRefcnt;
|
||||
|
||||
nsresult
|
||||
@ -216,11 +218,13 @@ nsLayoutStatics::Initialize()
|
||||
return rv;
|
||||
}
|
||||
|
||||
#ifndef DEBUG_CC
|
||||
rv = nsCCUncollectableMarker::Init();
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_ERROR("Could not initialize nsCCUncollectableMarker");
|
||||
return rv;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
rv = nsXULPopupManager::Init();
|
||||
|
@ -101,8 +101,6 @@ nsXULTooltipListener::~nsXULTooltipListener()
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULTooltipListener)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(nsXULTooltipListener)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMMouseListener)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMMouseMotionListener)
|
||||
@ -110,23 +108,10 @@ NS_INTERFACE_MAP_BEGIN(nsXULTooltipListener)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMXULListener)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIDOMEventListener, nsIDOMMouseListener)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMMouseMotionListener)
|
||||
NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsXULTooltipListener)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXULTooltipListener)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXULTooltipListener)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXULTooltipListener)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mSourceNode)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTargetNode)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCurrentTooltip)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXULTooltipListener)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mSourceNode)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTargetNode)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mCurrentTooltip)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
NS_IMPL_ADDREF(nsXULTooltipListener)
|
||||
NS_IMPL_RELEASE(nsXULTooltipListener)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//// nsIDOMMouseListener
|
||||
@ -153,7 +138,8 @@ nsXULTooltipListener::MouseOut(nsIDOMEvent* aMouseEvent)
|
||||
// if the timer is running and no tooltip is shown, we
|
||||
// have to cancel the timer here so that it doesn't
|
||||
// show the tooltip if we move the mouse out of the window
|
||||
if (mTooltipTimer && !mCurrentTooltip) {
|
||||
nsCOMPtr<nsIContent> currentTooltip = do_QueryReferent(mCurrentTooltip);
|
||||
if (mTooltipTimer && !currentTooltip) {
|
||||
mTooltipTimer->Cancel();
|
||||
mTooltipTimer = nsnull;
|
||||
return NS_OK;
|
||||
@ -166,14 +152,14 @@ nsXULTooltipListener::MouseOut(nsIDOMEvent* aMouseEvent)
|
||||
|
||||
// check to see if the mouse left the targetNode, and if so,
|
||||
// hide the tooltip
|
||||
if (mCurrentTooltip) {
|
||||
if (currentTooltip) {
|
||||
// which node did the mouse leave?
|
||||
nsCOMPtr<nsIDOMEventTarget> eventTarget;
|
||||
aMouseEvent->GetTarget(getter_AddRefs(eventTarget));
|
||||
nsCOMPtr<nsIDOMNode> targetNode(do_QueryInterface(eventTarget));
|
||||
|
||||
// which node is our tooltip on?
|
||||
nsCOMPtr<nsIDOMXULDocument> xulDoc(do_QueryInterface(mCurrentTooltip->GetDocument()));
|
||||
nsCOMPtr<nsIDOMXULDocument> xulDoc(do_QueryInterface(currentTooltip->GetDocument()));
|
||||
if (!xulDoc) // remotely possible someone could have
|
||||
return NS_OK; // removed tooltip from dom while it was open
|
||||
nsCOMPtr<nsIDOMNode> tooltipNode;
|
||||
@ -220,9 +206,11 @@ nsXULTooltipListener::MouseMove(nsIDOMEvent* aMouseEvent)
|
||||
|
||||
nsCOMPtr<nsIDOMEventTarget> eventTarget;
|
||||
aMouseEvent->GetCurrentTarget(getter_AddRefs(eventTarget));
|
||||
mSourceNode = do_QueryInterface(eventTarget);
|
||||
|
||||
nsCOMPtr<nsIContent> sourceContent = do_QueryInterface(eventTarget);
|
||||
mSourceNode = do_GetWeakReference(sourceContent);
|
||||
#ifdef MOZ_XUL
|
||||
mIsSourceTree = mSourceNode->Tag() == nsGkAtoms::treechildren;
|
||||
mIsSourceTree = sourceContent->Tag() == nsGkAtoms::treechildren;
|
||||
if (mIsSourceTree)
|
||||
CheckTreeBodyMove(mouseEvent);
|
||||
#endif
|
||||
@ -235,12 +223,14 @@ nsXULTooltipListener::MouseMove(nsIDOMEvent* aMouseEvent)
|
||||
// If the mouse moves while the tooltip is up, don't do anything. We make it
|
||||
// go away only if it times out or leaves the target node. If nothing is
|
||||
// showing, though, we have to do the work.
|
||||
if (!mCurrentTooltip) {
|
||||
nsCOMPtr<nsIContent> currentTooltip = do_QueryReferent(mCurrentTooltip);
|
||||
if (!currentTooltip) {
|
||||
mTooltipTimer = do_CreateInstance("@mozilla.org/timer;1");
|
||||
if (mTooltipTimer) {
|
||||
aMouseEvent->GetTarget(getter_AddRefs(eventTarget));
|
||||
mTargetNode = do_QueryInterface(eventTarget);
|
||||
if (mTargetNode) {
|
||||
nsCOMPtr<nsIDOMNode> targetNode = do_QueryInterface(eventTarget);
|
||||
mTargetNode = do_GetWeakReference(targetNode);
|
||||
if (targetNode) {
|
||||
nsresult rv = mTooltipTimer->InitWithFuncCallback(sTooltipCallback, this,
|
||||
kTooltipShowTime, nsITimer::TYPE_ONE_SHOT);
|
||||
if (NS_FAILED(rv)) {
|
||||
@ -335,12 +325,13 @@ nsXULTooltipListener::RemoveTooltipSupport(nsIContent* aNode)
|
||||
void
|
||||
nsXULTooltipListener::CheckTreeBodyMove(nsIDOMMouseEvent* aMouseEvent)
|
||||
{
|
||||
if (!mSourceNode)
|
||||
nsCOMPtr<nsIContent> sourceNode = do_QueryReferent(mSourceNode);
|
||||
if (!sourceNode)
|
||||
return;
|
||||
|
||||
// get the boxObject of the documentElement of the document the tree is in
|
||||
nsCOMPtr<nsIBoxObject> bx;
|
||||
nsCOMPtr<nsIDOMDocument> doc(do_QueryInterface(mSourceNode->GetDocument()));
|
||||
nsCOMPtr<nsIDOMDocument> doc(do_QueryInterface(sourceNode->GetDocument()));
|
||||
if (doc) {
|
||||
nsCOMPtr<nsIDOMNSDocument> nsDoc(do_QueryInterface(doc));
|
||||
nsCOMPtr<nsIDOMElement> docElement;
|
||||
@ -377,7 +368,8 @@ nsXULTooltipListener::CheckTreeBodyMove(nsIDOMMouseEvent* aMouseEvent)
|
||||
obx->IsCellCropped(row, col, &mNeedTitletip);
|
||||
}
|
||||
|
||||
if (mCurrentTooltip && (row != mLastTreeRow || col != mLastTreeCol)) {
|
||||
nsCOMPtr<nsIContent> currentTooltip = do_QueryReferent(mCurrentTooltip);
|
||||
if (currentTooltip && (row != mLastTreeRow || col != mLastTreeCol)) {
|
||||
HideTooltip();
|
||||
}
|
||||
|
||||
@ -390,10 +382,12 @@ nsXULTooltipListener::CheckTreeBodyMove(nsIDOMMouseEvent* aMouseEvent)
|
||||
nsresult
|
||||
nsXULTooltipListener::ShowTooltip()
|
||||
{
|
||||
// get the tooltip content designated for the target node
|
||||
nsCOMPtr<nsIContent> sourceNode = do_QueryReferent(mSourceNode);
|
||||
|
||||
// get the tooltip content designated for the target node
|
||||
nsCOMPtr<nsIContent> tooltipNode;
|
||||
GetTooltipFor(mSourceNode, getter_AddRefs(tooltipNode));
|
||||
if (!tooltipNode || mSourceNode == tooltipNode)
|
||||
GetTooltipFor(sourceNode, getter_AddRefs(tooltipNode));
|
||||
if (!tooltipNode || sourceNode == tooltipNode)
|
||||
return NS_ERROR_FAILURE; // the target node doesn't need a tooltip
|
||||
|
||||
// set the node in the document that triggered the tooltip and show it
|
||||
@ -401,7 +395,7 @@ nsXULTooltipListener::ShowTooltip()
|
||||
if (xulDoc) {
|
||||
// Make sure the target node is still attached to some document.
|
||||
// It might have been deleted.
|
||||
if (mSourceNode->GetDocument()) {
|
||||
if (sourceNode->GetDocument()) {
|
||||
#ifdef MOZ_XUL
|
||||
if (!mIsSourceTree) {
|
||||
mLastTreeRow = -1;
|
||||
@ -409,28 +403,31 @@ nsXULTooltipListener::ShowTooltip()
|
||||
}
|
||||
#endif
|
||||
|
||||
xulDoc->SetTooltipNode(mTargetNode);
|
||||
mCurrentTooltip = tooltipNode;
|
||||
nsCOMPtr<nsIDOMNode> targetNode = do_QueryReferent(mTargetNode);
|
||||
xulDoc->SetTooltipNode(targetNode);
|
||||
mCurrentTooltip = do_GetWeakReference(tooltipNode);
|
||||
LaunchTooltip();
|
||||
mTargetNode = nsnull;
|
||||
if (!mCurrentTooltip)
|
||||
|
||||
nsCOMPtr<nsIContent> currentTooltip = do_QueryReferent(mCurrentTooltip);
|
||||
if (!currentTooltip)
|
||||
return NS_OK;
|
||||
|
||||
// at this point, |mCurrentTooltip| holds the content node of
|
||||
// at this point, |currentTooltip| holds the content node of
|
||||
// the tooltip. If there is an attribute on the popup telling us
|
||||
// not to create the auto-hide timer, don't.
|
||||
if (!mCurrentTooltip->AttrValueIs(kNameSpaceID_None, nsGkAtoms::noautohide,
|
||||
nsGkAtoms::_true, eCaseMatters))
|
||||
if (!currentTooltip->AttrValueIs(kNameSpaceID_None, nsGkAtoms::noautohide,
|
||||
nsGkAtoms::_true, eCaseMatters))
|
||||
CreateAutoHideTimer();
|
||||
|
||||
// listen for popuphidden on the tooltip node, so that we can
|
||||
// be sure DestroyPopup is called even if someone else closes the tooltip
|
||||
nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(mCurrentTooltip));
|
||||
nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(currentTooltip));
|
||||
evtTarget->AddEventListener(NS_LITERAL_STRING("popuphiding"),
|
||||
(nsIDOMMouseListener*)this, PR_FALSE);
|
||||
|
||||
// listen for mousedown, mouseup, keydown, and DOMMouseScroll events at document level
|
||||
nsIDocument* doc = mSourceNode->GetDocument();
|
||||
nsIDocument* doc = sourceNode->GetDocument();
|
||||
if (doc) {
|
||||
evtTarget = do_QueryInterface(doc);
|
||||
evtTarget->AddEventListener(NS_LITERAL_STRING("DOMMouseScroll"),
|
||||
@ -488,7 +485,8 @@ SetTitletipLabel(nsITreeBoxObject* aTreeBox, nsIContent* aTooltip,
|
||||
void
|
||||
nsXULTooltipListener::LaunchTooltip()
|
||||
{
|
||||
if (!mCurrentTooltip)
|
||||
nsCOMPtr<nsIContent> currentTooltip = do_QueryReferent(mCurrentTooltip);
|
||||
if (!currentTooltip)
|
||||
return;
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
@ -496,25 +494,25 @@ nsXULTooltipListener::LaunchTooltip()
|
||||
nsCOMPtr<nsITreeBoxObject> obx;
|
||||
GetSourceTreeBoxObject(getter_AddRefs(obx));
|
||||
|
||||
SetTitletipLabel(obx, mCurrentTooltip, mLastTreeRow, mLastTreeCol);
|
||||
if (!mCurrentTooltip) {
|
||||
// Because of mutation events, mCurrentTooltip can be null.
|
||||
SetTitletipLabel(obx, currentTooltip, mLastTreeRow, mLastTreeCol);
|
||||
if (!(currentTooltip = do_QueryReferent(mCurrentTooltip))) {
|
||||
// Because of mutation events, currentTooltip can be null.
|
||||
return;
|
||||
}
|
||||
mCurrentTooltip->SetAttr(nsnull, nsGkAtoms::titletip, NS_LITERAL_STRING("true"), PR_TRUE);
|
||||
currentTooltip->SetAttr(nsnull, nsGkAtoms::titletip, NS_LITERAL_STRING("true"), PR_TRUE);
|
||||
} else {
|
||||
mCurrentTooltip->UnsetAttr(nsnull, nsGkAtoms::titletip, PR_TRUE);
|
||||
currentTooltip->UnsetAttr(nsnull, nsGkAtoms::titletip, PR_TRUE);
|
||||
}
|
||||
if (!mCurrentTooltip) {
|
||||
// Because of mutation events, mCurrentTooltip can be null.
|
||||
if (!(currentTooltip = do_QueryReferent(mCurrentTooltip))) {
|
||||
// Because of mutation events, currentTooltip can be null.
|
||||
return;
|
||||
}
|
||||
|
||||
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
|
||||
if (pm) {
|
||||
pm->ShowPopupAtScreen(mCurrentTooltip, mMouseClientX, mMouseClientY, PR_FALSE, nsnull);
|
||||
pm->ShowPopupAtScreen(currentTooltip, mMouseClientX, mMouseClientY, PR_FALSE, nsnull);
|
||||
// Clear the current tooltip if the popup was not opened successfully.
|
||||
if (!pm->IsPopupOpen(mCurrentTooltip))
|
||||
if (!pm->IsPopupOpen(currentTooltip))
|
||||
mCurrentTooltip = nsnull;
|
||||
}
|
||||
#endif
|
||||
@ -525,10 +523,11 @@ nsresult
|
||||
nsXULTooltipListener::HideTooltip()
|
||||
{
|
||||
#ifdef MOZ_XUL
|
||||
if (mCurrentTooltip) {
|
||||
nsCOMPtr<nsIContent> currentTooltip = do_QueryReferent(mCurrentTooltip);
|
||||
if (currentTooltip) {
|
||||
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
|
||||
if (pm)
|
||||
pm->HidePopup(mCurrentTooltip, PR_FALSE, PR_FALSE, PR_FALSE);
|
||||
pm->HidePopup(currentTooltip, PR_FALSE, PR_FALSE, PR_FALSE);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -664,9 +663,10 @@ nsresult
|
||||
nsXULTooltipListener::DestroyTooltip()
|
||||
{
|
||||
nsCOMPtr<nsIDOMMouseListener> kungFuDeathGrip(this);
|
||||
if (mCurrentTooltip) {
|
||||
nsCOMPtr<nsIContent> currentTooltip = do_QueryReferent(mCurrentTooltip);
|
||||
if (currentTooltip) {
|
||||
// clear out the tooltip node on the document
|
||||
nsCOMPtr<nsIDocument> doc = mCurrentTooltip->GetDocument();
|
||||
nsCOMPtr<nsIDocument> doc = currentTooltip->GetDocument();
|
||||
if (doc) {
|
||||
nsCOMPtr<nsIDOMXULDocument> xulDoc(do_QueryInterface(doc));
|
||||
if (xulDoc)
|
||||
@ -681,7 +681,7 @@ nsXULTooltipListener::DestroyTooltip()
|
||||
}
|
||||
|
||||
// remove the popuphidden listener from tooltip
|
||||
nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(mCurrentTooltip));
|
||||
nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(currentTooltip));
|
||||
|
||||
// release tooltip before removing listener to prevent our destructor from
|
||||
// being called recursively (bug 120863)
|
||||
@ -750,8 +750,9 @@ nsXULTooltipListener::GetSourceTreeBoxObject(nsITreeBoxObject** aBoxObject)
|
||||
{
|
||||
*aBoxObject = nsnull;
|
||||
|
||||
if (mIsSourceTree && mSourceNode) {
|
||||
nsCOMPtr<nsIDOMXULElement> xulEl(do_QueryInterface(mSourceNode->GetParent()));
|
||||
nsCOMPtr<nsIContent> sourceNode = do_QueryReferent(mSourceNode);
|
||||
if (mIsSourceTree && sourceNode) {
|
||||
nsCOMPtr<nsIDOMXULElement> xulEl(do_QueryInterface(sourceNode->GetParent()));
|
||||
if (xulEl) {
|
||||
nsCOMPtr<nsIBoxObject> bx;
|
||||
xulEl->GetBoxObject(getter_AddRefs(bx));
|
||||
|
@ -38,7 +38,6 @@
|
||||
#ifndef nsXULTooltipListener_h__
|
||||
#define nsXULTooltipListener_h__
|
||||
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsIDOMMouseListener.h"
|
||||
#include "nsIDOMMouseMotionListener.h"
|
||||
#include "nsIDOMKeyListener.h"
|
||||
@ -53,6 +52,7 @@
|
||||
#include "nsITreeBoxObject.h"
|
||||
#include "nsITreeColumns.h"
|
||||
#endif
|
||||
#include "nsWeakPtr.h"
|
||||
|
||||
class nsXULTooltipListener : public nsIDOMMouseListener,
|
||||
public nsIDOMMouseMotionListener,
|
||||
@ -60,9 +60,7 @@ class nsXULTooltipListener : public nsIDOMMouseListener,
|
||||
public nsIDOMXULListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXULTooltipListener,
|
||||
nsIDOMMouseListener)
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIDOMMouseListener
|
||||
NS_IMETHOD MouseDown(nsIDOMEvent* aMouseEvent);
|
||||
@ -134,9 +132,9 @@ protected:
|
||||
static nsXULTooltipListener* mInstance;
|
||||
static int ToolbarTipsPrefChanged(const char *aPref, void *aClosure);
|
||||
|
||||
nsCOMPtr<nsIContent> mSourceNode;
|
||||
nsCOMPtr<nsIDOMNode> mTargetNode;
|
||||
nsCOMPtr<nsIContent> mCurrentTooltip;
|
||||
nsWeakPtr mSourceNode;
|
||||
nsWeakPtr mTargetNode;
|
||||
nsWeakPtr mCurrentTooltip;
|
||||
|
||||
// a timer for showing the tooltip
|
||||
nsCOMPtr<nsITimer> mTooltipTimer;
|
||||
|
Loading…
Reference in New Issue
Block a user