Bug 1460691 - Support tooltips in top level non-XUL windows. r=enndeakin+6102,mats+6102

Add an anonymous XUL tooltip node to toplevel non-XUL windows. Setup a
nsXULTooltipListener on non-XUL nsXULWindows. Make nsXULTooltipListener
always use the default tooltip in the non-XUL case.

MozReview-Commit-ID: Koe5m8PwMQM

--HG--
extra : rebase_source : 242180e957758b51c589452e35deadac5ab06d9e
This commit is contained in:
Brendan Dahl 2018-07-03 14:20:43 -07:00
parent 5935acc8f0
commit afd85398a2
6 changed files with 96 additions and 6 deletions

View File

@ -130,7 +130,7 @@ nsCanvasFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
}
// Create a popupgroup element for chrome privileged top level non-XUL
// documents to support context menus.
// documents to support context menus and tooltips.
if (PresContext()->IsChrome() && PresContext()->IsRoot() &&
doc->AllowXULXBL() && !doc->IsXULDocument()) {
nsNodeInfoManager* nodeInfoManager = doc->NodeInfoManager();
@ -144,6 +144,23 @@ nsCanvasFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
NS_ENSURE_SUCCESS(rv, rv);
aElements.AppendElement(mPopupgroupContent);
nodeInfo = nodeInfoManager->GetNodeInfo(nsGkAtoms::tooltip, nullptr,
kNameSpaceID_XUL,
nsINode::ELEMENT_NODE);
rv = NS_NewXULElement(getter_AddRefs(mTooltipContent), nodeInfo.forget(),
dom::NOT_FROM_PARSER);
NS_ENSURE_SUCCESS(rv, rv);
mTooltipContent->SetAttr(kNameSpaceID_None, nsGkAtoms::_default,
NS_LITERAL_STRING("true"), false);
// Set the page attribute so the XBL binding will find the text for the
// tooltip from the currently hovered element.
mTooltipContent->SetAttr(kNameSpaceID_None, nsGkAtoms::page,
NS_LITERAL_STRING("true"), false);
aElements.AppendElement(mTooltipContent);
}
return NS_OK;
@ -158,6 +175,9 @@ nsCanvasFrame::AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements, uint32
if (mPopupgroupContent) {
aElements.AppendElement(mPopupgroupContent);
}
if (mTooltipContent) {
aElements.AppendElement(mTooltipContent);
}
}
void
@ -188,6 +208,9 @@ nsCanvasFrame::DestroyFrom(nsIFrame* aDestructRoot, PostDestroyData& aPostDestro
if (mPopupgroupContent) {
aPostDestroyData.AddAnonymousContent(mPopupgroupContent.forget());
}
if (mTooltipContent) {
aPostDestroyData.AddAnonymousContent(mTooltipContent.forget());
}
MOZ_ASSERT(!mPopupSetFrame ||
nsLayoutUtils::IsProperAncestorFrame(this, mPopupSetFrame),
@ -307,15 +330,15 @@ nsCanvasFrame::SetPopupSetFrame(nsPopupSetFrame* aPopupSet)
Element*
nsCanvasFrame::GetDefaultTooltip()
{
NS_WARNING("GetDefaultTooltip not implemented");
return nullptr;
return mTooltipContent;
}
void
nsCanvasFrame::SetDefaultTooltip(Element* aTooltip)
{
NS_WARNING("SetDefaultTooltip not implemented");
return;
MOZ_ASSERT(!aTooltip || aTooltip == mTooltipContent,
"Default tooltip should be anonymous content tooltip.");
mTooltipContent = aTooltip;
}
void

View File

@ -135,6 +135,7 @@ protected:
private:
nsPopupSetFrame* mPopupSetFrame;
nsCOMPtr<mozilla::dom::Element> mPopupgroupContent;
nsCOMPtr<mozilla::dom::Element> mTooltipContent;
};
/**

View File

@ -28,6 +28,7 @@ EXPORTS += [
'nsPIBoxObject.h',
'nsPIListBoxObject.h',
'nsXULPopupManager.h',
'nsXULTooltipListener.h',
]
EXPORTS.mozilla.dom += [

View File

@ -400,7 +400,7 @@ nsXULTooltipListener::ShowTooltip()
// set the node in the document that triggered the tooltip and show it
if (tooltipNode->GetComposedDoc() &&
tooltipNode->GetComposedDoc()->IsXULDocument()) {
nsContentUtils::IsChromeDoc(tooltipNode->GetComposedDoc())) {
// Make sure the target node is still attached to some document.
// It might have been deleted.
if (sourceNode->IsInComposedDoc()) {
@ -578,6 +578,18 @@ nsXULTooltipListener::FindTooltip(nsIContent* aTarget, nsIContent** aTooltip)
return NS_OK;
}
// non-XUL documents should just use the default tooltip
if (!document->IsXULDocument()) {
nsIPopupContainer* popupContainer =
nsIPopupContainer::GetPopupContainer(document->GetShell());
NS_ENSURE_STATE(popupContainer);
if (RefPtr<Element> tooltip = popupContainer->GetDefaultTooltip()) {
tooltip.forget(aTooltip);
return NS_OK;
}
return NS_ERROR_FAILURE;
}
nsAutoString tooltipText;
if (aTarget->IsElement()) {
aTarget->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::tooltiptext, tooltipText);

View File

@ -49,6 +49,7 @@
#include "nsWebShellWindow.h" // get rid of this one, too...
#include "nsGlobalWindow.h"
#include "XULDocument.h"
#include "nsXULTooltipListener.h"
#include "prenv.h"
#include "mozilla/AutoRestore.h"
@ -517,6 +518,8 @@ NS_IMETHODIMP nsXULWindow::Destroy()
}
#endif
RemoveTooltipSupport();
mDOMWindow = nullptr;
if (mDocShell) {
nsCOMPtr<nsIBaseWindow> shellAsWin(do_QueryInterface(mDocShell));
@ -1127,6 +1130,7 @@ void nsXULWindow::OnChromeLoaded()
if (mShowAfterLoad) {
SetVisibility(true);
}
AddTooltipSupport();
}
// At this point the window may have been closed already during Show() or
// SyncAttributesToWidget(), so nsXULWindow::Destroy may already have been
@ -1135,6 +1139,50 @@ void nsXULWindow::OnChromeLoaded()
mPersistentAttributesMask |= PAD_POSITION | PAD_SIZE | PAD_MISC;
}
bool
nsXULWindow::NeedsTooltipListener()
{
nsCOMPtr<dom::Element> docShellElement = GetWindowDOMElement();
if (!docShellElement || docShellElement->IsXULElement()) {
// Tooltips in XUL are handled by each element.
return false;
}
// All other non-XUL document types need a tooltip listener.
return true;
}
void
nsXULWindow::AddTooltipSupport()
{
if (!NeedsTooltipListener()) {
return;
}
nsXULTooltipListener* listener = nsXULTooltipListener::GetInstance();
if (!listener) {
return;
}
nsCOMPtr<dom::Element> docShellElement = GetWindowDOMElement();
MOZ_ASSERT(docShellElement);
listener->AddTooltipSupport(docShellElement);
}
void
nsXULWindow::RemoveTooltipSupport()
{
if (!NeedsTooltipListener()) {
return;
}
nsXULTooltipListener* listener = nsXULTooltipListener::GetInstance();
if (!listener) {
return;
}
nsCOMPtr<dom::Element> docShellElement = GetWindowDOMElement();
MOZ_ASSERT(docShellElement);
listener->RemoveTooltipSupport(docShellElement);
}
// If aSpecWidth and/or aSpecHeight are > 0, we will use these CSS px sizes
// to fit to the screen when staggering windows; if they're negative,
// we use the window's current size instead.

View File

@ -43,6 +43,7 @@ class Element;
} // namespace mozilla
class nsAtom;
class nsXULTooltipListener;
// nsXULWindow
@ -108,6 +109,10 @@ protected:
void SyncAttributesToWidget();
NS_IMETHOD SavePersistentAttributes();
bool NeedsTooltipListener();
void AddTooltipSupport();
void RemoveTooltipSupport();
NS_IMETHOD GetWindowDOMWindow(mozIDOMWindowProxy** aDOMWindow);
mozilla::dom::Element* GetWindowDOMElement() const;