Bumping manifests a=b2g-bump
[gecko.git] / layout / xul / nsXULTooltipListener.cpp
blob24c8b22ebb6a2ef0fe8be853f8380ae087953d02
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "nsXULTooltipListener.h"
8 #include "nsIDOMMouseEvent.h"
9 #include "nsIDOMXULDocument.h"
10 #include "nsIDOMXULElement.h"
11 #include "nsIDocument.h"
12 #include "nsGkAtoms.h"
13 #include "nsIPopupBoxObject.h"
14 #include "nsMenuPopupFrame.h"
15 #include "nsIServiceManager.h"
16 #include "nsIDragService.h"
17 #include "nsIDragSession.h"
18 #ifdef MOZ_XUL
19 #include "nsITreeView.h"
20 #endif
21 #include "nsIScriptContext.h"
22 #include "nsPIDOMWindow.h"
23 #ifdef MOZ_XUL
24 #include "nsXULPopupManager.h"
25 #endif
26 #include "nsIRootBox.h"
27 #include "nsIBoxObject.h"
28 #include "mozilla/Preferences.h"
29 #include "mozilla/LookAndFeel.h"
30 #include "mozilla/dom/Element.h"
31 #include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent()
33 using namespace mozilla;
34 using namespace mozilla::dom;
36 nsXULTooltipListener* nsXULTooltipListener::mInstance = nullptr;
38 //////////////////////////////////////////////////////////////////////////
39 //// nsISupports
41 nsXULTooltipListener::nsXULTooltipListener()
42 : mMouseScreenX(0)
43 , mMouseScreenY(0)
44 , mTooltipShownOnce(false)
45 #ifdef MOZ_XUL
46 , mIsSourceTree(false)
47 , mNeedTitletip(false)
48 , mLastTreeRow(-1)
49 #endif
51 if (sTooltipListenerCount++ == 0) {
52 // register the callback so we get notified of updates
53 Preferences::RegisterCallback(ToolbarTipsPrefChanged,
54 "browser.chrome.toolbar_tips");
56 // Call the pref callback to initialize our state.
57 ToolbarTipsPrefChanged("browser.chrome.toolbar_tips", nullptr);
61 nsXULTooltipListener::~nsXULTooltipListener()
63 if (nsXULTooltipListener::mInstance == this) {
64 ClearTooltipCache();
66 HideTooltip();
68 if (--sTooltipListenerCount == 0) {
69 // Unregister our pref observer
70 Preferences::UnregisterCallback(ToolbarTipsPrefChanged,
71 "browser.chrome.toolbar_tips");
75 NS_IMPL_ISUPPORTS(nsXULTooltipListener, nsIDOMEventListener)
77 void
78 nsXULTooltipListener::MouseOut(nsIDOMEvent* aEvent)
80 // reset flag so that tooltip will display on the next MouseMove
81 mTooltipShownOnce = false;
83 // if the timer is running and no tooltip is shown, we
84 // have to cancel the timer here so that it doesn't
85 // show the tooltip if we move the mouse out of the window
86 nsCOMPtr<nsIContent> currentTooltip = do_QueryReferent(mCurrentTooltip);
87 if (mTooltipTimer && !currentTooltip) {
88 mTooltipTimer->Cancel();
89 mTooltipTimer = nullptr;
90 return;
93 #ifdef DEBUG_crap
94 if (mNeedTitletip)
95 return;
96 #endif
98 #ifdef MOZ_XUL
99 // check to see if the mouse left the targetNode, and if so,
100 // hide the tooltip
101 if (currentTooltip) {
102 // which node did the mouse leave?
103 nsCOMPtr<nsIDOMNode> targetNode = do_QueryInterface(
104 aEvent->InternalDOMEvent()->GetTarget());
106 nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
107 if (pm) {
108 nsCOMPtr<nsIDOMNode> tooltipNode =
109 pm->GetLastTriggerTooltipNode(currentTooltip->GetCurrentDoc());
110 if (tooltipNode == targetNode) {
111 // if the target node is the current tooltip target node, the mouse
112 // left the node the tooltip appeared on, so close the tooltip.
113 HideTooltip();
114 // reset special tree tracking
115 if (mIsSourceTree) {
116 mLastTreeRow = -1;
117 mLastTreeCol = nullptr;
122 #endif
125 void
126 nsXULTooltipListener::MouseMove(nsIDOMEvent* aEvent)
128 if (!sShowTooltips)
129 return;
131 // stash the coordinates of the event so that we can still get back to it from within the
132 // timer callback. On win32, we'll get a MouseMove event even when a popup goes away --
133 // even when the mouse doesn't change position! To get around this, we make sure the
134 // mouse has really moved before proceeding.
135 nsCOMPtr<nsIDOMMouseEvent> mouseEvent(do_QueryInterface(aEvent));
136 if (!mouseEvent)
137 return;
138 int32_t newMouseX, newMouseY;
139 mouseEvent->GetScreenX(&newMouseX);
140 mouseEvent->GetScreenY(&newMouseY);
142 // filter out false win32 MouseMove event
143 if (mMouseScreenX == newMouseX && mMouseScreenY == newMouseY)
144 return;
146 // filter out minor movements due to crappy optical mice and shaky hands
147 // to prevent tooltips from hiding prematurely.
148 nsCOMPtr<nsIContent> currentTooltip = do_QueryReferent(mCurrentTooltip);
150 if ((currentTooltip) &&
151 (abs(mMouseScreenX - newMouseX) <= kTooltipMouseMoveTolerance) &&
152 (abs(mMouseScreenY - newMouseY) <= kTooltipMouseMoveTolerance))
153 return;
154 mMouseScreenX = newMouseX;
155 mMouseScreenY = newMouseY;
157 nsCOMPtr<nsIContent> sourceContent = do_QueryInterface(
158 aEvent->InternalDOMEvent()->GetCurrentTarget());
159 mSourceNode = do_GetWeakReference(sourceContent);
160 #ifdef MOZ_XUL
161 mIsSourceTree = sourceContent->Tag() == nsGkAtoms::treechildren;
162 if (mIsSourceTree)
163 CheckTreeBodyMove(mouseEvent);
164 #endif
166 // as the mouse moves, we want to make sure we reset the timer to show it,
167 // so that the delay is from when the mouse stops moving, not when it enters
168 // the node.
169 KillTooltipTimer();
171 // If the mouse moves while the tooltip is up, hide it. If nothing is
172 // showing and the tooltip hasn't been displayed since the mouse entered
173 // the node, then start the timer to show the tooltip.
174 if (!currentTooltip && !mTooltipShownOnce) {
175 nsCOMPtr<EventTarget> eventTarget = aEvent->InternalDOMEvent()->GetTarget();
177 // don't show tooltips attached to elements outside of a menu popup
178 // when hovering over an element inside it. The popupsinherittooltip
179 // attribute may be used to disable this behaviour, which is useful for
180 // large menu hierarchies such as bookmarks.
181 if (!sourceContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::popupsinherittooltip,
182 nsGkAtoms::_true, eCaseMatters)) {
183 nsCOMPtr<nsIContent> targetContent = do_QueryInterface(eventTarget);
184 while (targetContent && targetContent != sourceContent) {
185 nsIAtom* tag = targetContent->Tag();
186 if (targetContent->GetNameSpaceID() == kNameSpaceID_XUL &&
187 (tag == nsGkAtoms::menupopup ||
188 tag == nsGkAtoms::panel ||
189 tag == nsGkAtoms::tooltip)) {
190 mSourceNode = nullptr;
191 return;
194 targetContent = targetContent->GetParent();
198 mTooltipTimer = do_CreateInstance("@mozilla.org/timer;1");
199 if (mTooltipTimer) {
200 mTargetNode = do_GetWeakReference(eventTarget);
201 if (mTargetNode) {
202 nsresult rv =
203 mTooltipTimer->InitWithFuncCallback(sTooltipCallback, this,
204 LookAndFeel::GetInt(LookAndFeel::eIntID_TooltipDelay, 500),
205 nsITimer::TYPE_ONE_SHOT);
206 if (NS_FAILED(rv)) {
207 mTargetNode = nullptr;
208 mSourceNode = nullptr;
212 return;
215 #ifdef MOZ_XUL
216 if (mIsSourceTree)
217 return;
218 #endif
220 HideTooltip();
221 // set a flag so that the tooltip is only displayed once until the mouse
222 // leaves the node
223 mTooltipShownOnce = true;
226 NS_IMETHODIMP
227 nsXULTooltipListener::HandleEvent(nsIDOMEvent* aEvent)
229 nsAutoString type;
230 aEvent->GetType(type);
231 if (type.EqualsLiteral("DOMMouseScroll") ||
232 type.EqualsLiteral("keydown") ||
233 type.EqualsLiteral("mousedown") ||
234 type.EqualsLiteral("mouseup") ||
235 type.EqualsLiteral("dragstart")) {
236 HideTooltip();
237 return NS_OK;
240 if (type.EqualsLiteral("popuphiding")) {
241 DestroyTooltip();
242 return NS_OK;
245 // Note that mousemove, mouseover and mouseout might be
246 // fired even during dragging due to widget's bug.
247 nsCOMPtr<nsIDragService> dragService =
248 do_GetService("@mozilla.org/widget/dragservice;1");
249 NS_ENSURE_TRUE(dragService, NS_OK);
250 nsCOMPtr<nsIDragSession> dragSession;
251 dragService->GetCurrentSession(getter_AddRefs(dragSession));
252 if (dragSession) {
253 return NS_OK;
256 // Not dragging.
258 if (type.EqualsLiteral("mousemove")) {
259 MouseMove(aEvent);
260 return NS_OK;
263 if (type.EqualsLiteral("mouseout")) {
264 MouseOut(aEvent);
265 return NS_OK;
268 return NS_OK;
271 //////////////////////////////////////////////////////////////////////////
272 //// nsXULTooltipListener
274 // static
275 void
276 nsXULTooltipListener::ToolbarTipsPrefChanged(const char *aPref,
277 void *aClosure)
279 sShowTooltips =
280 Preferences::GetBool("browser.chrome.toolbar_tips", sShowTooltips);
283 //////////////////////////////////////////////////////////////////////////
284 //// nsXULTooltipListener
286 bool nsXULTooltipListener::sShowTooltips = false;
287 uint32_t nsXULTooltipListener::sTooltipListenerCount = 0;
289 nsresult
290 nsXULTooltipListener::AddTooltipSupport(nsIContent* aNode)
292 if (!aNode)
293 return NS_ERROR_NULL_POINTER;
295 aNode->AddSystemEventListener(NS_LITERAL_STRING("mouseout"), this,
296 false, false);
297 aNode->AddSystemEventListener(NS_LITERAL_STRING("mousemove"), this,
298 false, false);
299 aNode->AddSystemEventListener(NS_LITERAL_STRING("mousedown"), this,
300 false, false);
301 aNode->AddSystemEventListener(NS_LITERAL_STRING("mouseup"), this,
302 false, false);
303 aNode->AddSystemEventListener(NS_LITERAL_STRING("dragstart"), this,
304 true, false);
306 return NS_OK;
309 nsresult
310 nsXULTooltipListener::RemoveTooltipSupport(nsIContent* aNode)
312 if (!aNode)
313 return NS_ERROR_NULL_POINTER;
315 aNode->RemoveSystemEventListener(NS_LITERAL_STRING("mouseout"), this, false);
316 aNode->RemoveSystemEventListener(NS_LITERAL_STRING("mousemove"), this, false);
317 aNode->RemoveSystemEventListener(NS_LITERAL_STRING("mousedown"), this, false);
318 aNode->RemoveSystemEventListener(NS_LITERAL_STRING("mouseup"), this, false);
319 aNode->RemoveSystemEventListener(NS_LITERAL_STRING("dragstart"), this, true);
321 return NS_OK;
324 #ifdef MOZ_XUL
325 void
326 nsXULTooltipListener::CheckTreeBodyMove(nsIDOMMouseEvent* aMouseEvent)
328 nsCOMPtr<nsIContent> sourceNode = do_QueryReferent(mSourceNode);
329 if (!sourceNode)
330 return;
332 // get the boxObject of the documentElement of the document the tree is in
333 nsCOMPtr<nsIBoxObject> bx;
334 nsIDocument* doc = sourceNode->GetComposedDoc();
335 if (doc) {
336 ErrorResult ignored;
337 bx = doc->GetBoxObjectFor(doc->GetRootElement(), ignored);
340 nsCOMPtr<nsITreeBoxObject> obx;
341 GetSourceTreeBoxObject(getter_AddRefs(obx));
342 if (bx && obx) {
343 int32_t x, y;
344 aMouseEvent->GetScreenX(&x);
345 aMouseEvent->GetScreenY(&y);
347 int32_t row;
348 nsCOMPtr<nsITreeColumn> col;
349 nsAutoCString obj;
351 // subtract off the documentElement's boxObject
352 int32_t boxX, boxY;
353 bx->GetScreenX(&boxX);
354 bx->GetScreenY(&boxY);
355 x -= boxX;
356 y -= boxY;
358 obx->GetCellAt(x, y, &row, getter_AddRefs(col), obj);
360 // determine if we are going to need a titletip
361 // XXX check the disabletitletips attribute on the tree content
362 mNeedTitletip = false;
363 if (row >= 0 && obj.EqualsLiteral("text")) {
364 obx->IsCellCropped(row, col, &mNeedTitletip);
367 nsCOMPtr<nsIContent> currentTooltip = do_QueryReferent(mCurrentTooltip);
368 if (currentTooltip && (row != mLastTreeRow || col != mLastTreeCol)) {
369 HideTooltip();
372 mLastTreeRow = row;
373 mLastTreeCol = col;
376 #endif
378 nsresult
379 nsXULTooltipListener::ShowTooltip()
381 nsCOMPtr<nsIContent> sourceNode = do_QueryReferent(mSourceNode);
383 // get the tooltip content designated for the target node
384 nsCOMPtr<nsIContent> tooltipNode;
385 GetTooltipFor(sourceNode, getter_AddRefs(tooltipNode));
386 if (!tooltipNode || sourceNode == tooltipNode)
387 return NS_ERROR_FAILURE; // the target node doesn't need a tooltip
389 // set the node in the document that triggered the tooltip and show it
390 nsCOMPtr<nsIDOMXULDocument> xulDoc =
391 do_QueryInterface(tooltipNode->GetComposedDoc());
392 if (xulDoc) {
393 // Make sure the target node is still attached to some document.
394 // It might have been deleted.
395 if (sourceNode->IsInComposedDoc()) {
396 #ifdef MOZ_XUL
397 if (!mIsSourceTree) {
398 mLastTreeRow = -1;
399 mLastTreeCol = nullptr;
401 #endif
403 mCurrentTooltip = do_GetWeakReference(tooltipNode);
404 LaunchTooltip();
405 mTargetNode = nullptr;
407 nsCOMPtr<nsIContent> currentTooltip = do_QueryReferent(mCurrentTooltip);
408 if (!currentTooltip)
409 return NS_OK;
411 // listen for popuphidden on the tooltip node, so that we can
412 // be sure DestroyPopup is called even if someone else closes the tooltip
413 currentTooltip->AddSystemEventListener(NS_LITERAL_STRING("popuphiding"),
414 this, false, false);
416 // listen for mousedown, mouseup, keydown, and DOMMouseScroll events at document level
417 nsIDocument* doc = sourceNode->GetComposedDoc();
418 if (doc) {
419 // Probably, we should listen to untrusted events for hiding tooltips
420 // on content since tooltips might disturb something of web
421 // applications. If we don't specify the aWantsUntrusted of
422 // AddSystemEventListener(), the event target sets it to TRUE if the
423 // target is in content.
424 doc->AddSystemEventListener(NS_LITERAL_STRING("DOMMouseScroll"),
425 this, true);
426 doc->AddSystemEventListener(NS_LITERAL_STRING("mousedown"),
427 this, true);
428 doc->AddSystemEventListener(NS_LITERAL_STRING("mouseup"),
429 this, true);
430 doc->AddSystemEventListener(NS_LITERAL_STRING("keydown"),
431 this, true);
433 mSourceNode = nullptr;
437 return NS_OK;
440 #ifdef MOZ_XUL
441 // XXX: "This stuff inside DEBUG_crap could be used to make tree tooltips work
442 // in the future."
443 #ifdef DEBUG_crap
444 static void
445 GetTreeCellCoords(nsITreeBoxObject* aTreeBox, nsIContent* aSourceNode,
446 int32_t aRow, nsITreeColumn* aCol, int32_t* aX, int32_t* aY)
448 int32_t junk;
449 aTreeBox->GetCoordsForCellItem(aRow, aCol, EmptyCString(), aX, aY, &junk, &junk);
450 nsCOMPtr<nsIDOMXULElement> xulEl(do_QueryInterface(aSourceNode));
451 nsCOMPtr<nsIBoxObject> bx;
452 xulEl->GetBoxObject(getter_AddRefs(bx));
453 int32_t myX, myY;
454 bx->GetX(&myX);
455 bx->GetY(&myY);
456 *aX += myX;
457 *aY += myY;
459 #endif
461 static void
462 SetTitletipLabel(nsITreeBoxObject* aTreeBox, nsIContent* aTooltip,
463 int32_t aRow, nsITreeColumn* aCol)
465 nsCOMPtr<nsITreeView> view;
466 aTreeBox->GetView(getter_AddRefs(view));
467 if (view) {
468 nsAutoString label;
469 #ifdef DEBUG
470 nsresult rv =
471 #endif
472 view->GetCellText(aRow, aCol, label);
473 NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Couldn't get the cell text!");
474 aTooltip->SetAttr(kNameSpaceID_None, nsGkAtoms::label, label, true);
477 #endif
479 void
480 nsXULTooltipListener::LaunchTooltip()
482 nsCOMPtr<nsIContent> currentTooltip = do_QueryReferent(mCurrentTooltip);
483 if (!currentTooltip)
484 return;
486 #ifdef MOZ_XUL
487 if (mIsSourceTree && mNeedTitletip) {
488 nsCOMPtr<nsITreeBoxObject> obx;
489 GetSourceTreeBoxObject(getter_AddRefs(obx));
491 SetTitletipLabel(obx, currentTooltip, mLastTreeRow, mLastTreeCol);
492 if (!(currentTooltip = do_QueryReferent(mCurrentTooltip))) {
493 // Because of mutation events, currentTooltip can be null.
494 return;
496 currentTooltip->SetAttr(kNameSpaceID_None, nsGkAtoms::titletip, NS_LITERAL_STRING("true"), true);
497 } else {
498 currentTooltip->UnsetAttr(kNameSpaceID_None, nsGkAtoms::titletip, true);
500 if (!(currentTooltip = do_QueryReferent(mCurrentTooltip))) {
501 // Because of mutation events, currentTooltip can be null.
502 return;
505 nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
506 if (pm) {
507 nsCOMPtr<nsIContent> target = do_QueryReferent(mTargetNode);
508 pm->ShowTooltipAtScreen(currentTooltip, target, mMouseScreenX, mMouseScreenY);
510 // Clear the current tooltip if the popup was not opened successfully.
511 if (!pm->IsPopupOpen(currentTooltip))
512 mCurrentTooltip = nullptr;
514 #endif
518 nsresult
519 nsXULTooltipListener::HideTooltip()
521 #ifdef MOZ_XUL
522 nsCOMPtr<nsIContent> currentTooltip = do_QueryReferent(mCurrentTooltip);
523 if (currentTooltip) {
524 nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
525 if (pm)
526 pm->HidePopup(currentTooltip, false, false, false, false);
528 #endif
530 DestroyTooltip();
531 return NS_OK;
534 static void
535 GetImmediateChild(nsIContent* aContent, nsIAtom *aTag, nsIContent** aResult)
537 *aResult = nullptr;
538 uint32_t childCount = aContent->GetChildCount();
539 for (uint32_t i = 0; i < childCount; i++) {
540 nsIContent *child = aContent->GetChildAt(i);
542 if (child->Tag() == aTag) {
543 *aResult = child;
544 NS_ADDREF(*aResult);
545 return;
549 return;
552 nsresult
553 nsXULTooltipListener::FindTooltip(nsIContent* aTarget, nsIContent** aTooltip)
555 if (!aTarget)
556 return NS_ERROR_NULL_POINTER;
558 // before we go on, make sure that target node still has a window
559 nsIDocument *document = aTarget->GetComposedDoc();
560 if (!document) {
561 NS_WARNING("Unable to retrieve the tooltip node document.");
562 return NS_ERROR_FAILURE;
564 nsPIDOMWindow *window = document->GetWindow();
565 if (!window) {
566 return NS_OK;
569 bool closed;
570 window->GetClosed(&closed);
572 if (closed) {
573 return NS_OK;
576 nsAutoString tooltipText;
577 aTarget->GetAttr(kNameSpaceID_None, nsGkAtoms::tooltiptext, tooltipText);
578 if (!tooltipText.IsEmpty()) {
579 // specifying tooltiptext means we will always use the default tooltip
580 nsIRootBox* rootBox = nsIRootBox::GetRootBox(document->GetShell());
581 NS_ENSURE_STATE(rootBox);
582 *aTooltip = rootBox->GetDefaultTooltip();
583 if (*aTooltip) {
584 NS_ADDREF(*aTooltip);
585 (*aTooltip)->SetAttr(kNameSpaceID_None, nsGkAtoms::label, tooltipText, true);
587 return NS_OK;
590 nsAutoString tooltipId;
591 aTarget->GetAttr(kNameSpaceID_None, nsGkAtoms::tooltip, tooltipId);
593 // if tooltip == _child, look for first <tooltip> child
594 if (tooltipId.EqualsLiteral("_child")) {
595 GetImmediateChild(aTarget, nsGkAtoms::tooltip, aTooltip);
596 return NS_OK;
599 if (!tooltipId.IsEmpty() && aTarget->IsInUncomposedDoc()) {
600 // tooltip must be an id, use getElementById to find it
601 //XXXsmaug If aTarget is in shadow dom, should we use
602 // ShadowRoot::GetElementById()?
603 nsCOMPtr<nsIContent> tooltipEl = document->GetElementById(tooltipId);
605 if (tooltipEl) {
606 #ifdef MOZ_XUL
607 mNeedTitletip = false;
608 #endif
609 tooltipEl.forget(aTooltip);
610 return NS_OK;
614 #ifdef MOZ_XUL
615 // titletips should just use the default tooltip
616 if (mIsSourceTree && mNeedTitletip) {
617 nsIRootBox* rootBox = nsIRootBox::GetRootBox(document->GetShell());
618 NS_ENSURE_STATE(rootBox);
619 NS_IF_ADDREF(*aTooltip = rootBox->GetDefaultTooltip());
621 #endif
623 return NS_OK;
627 nsresult
628 nsXULTooltipListener::GetTooltipFor(nsIContent* aTarget, nsIContent** aTooltip)
630 *aTooltip = nullptr;
631 nsCOMPtr<nsIContent> tooltip;
632 nsresult rv = FindTooltip(aTarget, getter_AddRefs(tooltip));
633 if (NS_FAILED(rv) || !tooltip) {
634 return rv;
637 #ifdef MOZ_XUL
638 // Submenus can't be used as tooltips, see bug 288763.
639 nsIContent* parent = tooltip->GetParent();
640 if (parent) {
641 nsMenuFrame* menu = do_QueryFrame(parent->GetPrimaryFrame());
642 if (menu) {
643 NS_WARNING("Menu cannot be used as a tooltip");
644 return NS_ERROR_FAILURE;
647 #endif
649 tooltip.swap(*aTooltip);
650 return rv;
653 nsresult
654 nsXULTooltipListener::DestroyTooltip()
656 nsCOMPtr<nsIDOMEventListener> kungFuDeathGrip(this);
657 nsCOMPtr<nsIContent> currentTooltip = do_QueryReferent(mCurrentTooltip);
658 if (currentTooltip) {
659 // release tooltip before removing listener to prevent our destructor from
660 // being called recursively (bug 120863)
661 mCurrentTooltip = nullptr;
663 // clear out the tooltip node on the document
664 nsCOMPtr<nsIDocument> doc = currentTooltip->GetComposedDoc();
665 if (doc) {
666 // remove the mousedown and keydown listener from document
667 doc->RemoveSystemEventListener(NS_LITERAL_STRING("DOMMouseScroll"), this,
668 true);
669 doc->RemoveSystemEventListener(NS_LITERAL_STRING("mousedown"), this,
670 true);
671 doc->RemoveSystemEventListener(NS_LITERAL_STRING("mouseup"), this, true);
672 doc->RemoveSystemEventListener(NS_LITERAL_STRING("keydown"), this, true);
675 // remove the popuphidden listener from tooltip
676 currentTooltip->RemoveSystemEventListener(NS_LITERAL_STRING("popuphiding"), this, false);
679 // kill any ongoing timers
680 KillTooltipTimer();
681 mSourceNode = nullptr;
682 #ifdef MOZ_XUL
683 mLastTreeCol = nullptr;
684 #endif
686 return NS_OK;
689 void
690 nsXULTooltipListener::KillTooltipTimer()
692 if (mTooltipTimer) {
693 mTooltipTimer->Cancel();
694 mTooltipTimer = nullptr;
695 mTargetNode = nullptr;
699 void
700 nsXULTooltipListener::sTooltipCallback(nsITimer *aTimer, void *aListener)
702 nsRefPtr<nsXULTooltipListener> instance = mInstance;
703 if (instance)
704 instance->ShowTooltip();
707 #ifdef MOZ_XUL
708 nsresult
709 nsXULTooltipListener::GetSourceTreeBoxObject(nsITreeBoxObject** aBoxObject)
711 *aBoxObject = nullptr;
713 nsCOMPtr<nsIContent> sourceNode = do_QueryReferent(mSourceNode);
714 if (mIsSourceTree && sourceNode) {
715 nsCOMPtr<nsIDOMXULElement> xulEl(do_QueryInterface(sourceNode->GetParent()));
716 if (xulEl) {
717 nsCOMPtr<nsIBoxObject> bx;
718 xulEl->GetBoxObject(getter_AddRefs(bx));
719 nsCOMPtr<nsITreeBoxObject> obx(do_QueryInterface(bx));
720 if (obx) {
721 *aBoxObject = obx;
722 NS_ADDREF(*aBoxObject);
723 return NS_OK;
727 return NS_ERROR_FAILURE;
729 #endif