From 19f8e2d3b8d93071603b964cebf5e2cd6bc06fe4 Mon Sep 17 00:00:00 2001 From: "pinkerton%netscape.com" Date: Thu, 1 Jul 1999 00:07:41 +0000 Subject: [PATCH] Changing CreatePopup to return the popup. Adding a bunch of stuff for tooltips to the popup code. Fixing some bugs in webshell with loading malformed popups. Renamed "popup" to "popupElement" in the document and added "tooltipElement" as well. git-svn-id: svn://10.0.0.236/trunk@37587 18797224-902f-48f8-a5cc-f745e15eee43 --- .../xul/content/src/nsXULPopupListener.cpp | 315 +++++++++++++++--- .../xul/document/src/nsXULDocument.cpp | 39 ++- mozilla/docshell/base/nsWebShell.cpp | 6 +- mozilla/dom/public/base/nsIDOMWindow.h | 6 +- mozilla/dom/public/idl/base/Window.idl | 10 +- mozilla/dom/public/idl/xul/XULDocument.idl | 4 +- mozilla/dom/public/xul/nsIDOMXULDocument.h | 19 +- mozilla/dom/src/base/nsGlobalWindow.cpp | 5 +- mozilla/dom/src/base/nsGlobalWindow.h | 2 +- mozilla/dom/src/base/nsJSWindow.cpp | 5 +- mozilla/dom/src/xul/nsJSXULDocument.cpp | 163 ++++++++- .../rdf/content/public/idl/XULDocument.idl | 4 +- .../rdf/content/public/nsIDOMXULDocument.h | 19 +- mozilla/rdf/content/src/nsJSXULDocument.cpp | 163 ++++++++- mozilla/rdf/content/src/nsXULDocument.cpp | 39 ++- .../rdf/content/src/nsXULPopupListener.cpp | 315 +++++++++++++++--- mozilla/webshell/public/nsIWebShell.h | 2 +- mozilla/webshell/src/nsWebShell.cpp | 6 +- .../webshell/tests/viewer/nsBrowserWindow.cpp | 2 +- .../webshell/tests/viewer/nsBrowserWindow.h | 2 +- .../webshell/tests/viewer/nsXPBaseWindow.cpp | 2 +- .../webshell/tests/viewer/nsXPBaseWindow.h | 2 +- .../xpfe/appshell/src/nsWebShellWindow.cpp | 29 +- mozilla/xpfe/appshell/src/nsWebShellWindow.h | 2 +- 24 files changed, 975 insertions(+), 186 deletions(-) diff --git a/mozilla/content/xul/content/src/nsXULPopupListener.cpp b/mozilla/content/xul/content/src/nsXULPopupListener.cpp index 9fb9805375a..bc6f2483400 100644 --- a/mozilla/content/xul/content/src/nsXULPopupListener.cpp +++ b/mozilla/content/xul/content/src/nsXULPopupListener.cpp @@ -34,6 +34,8 @@ #include "nsIDocument.h" #include "nsIContent.h" #include "nsIDOMUIEvent.h" +#include "nsITimer.h" + //////////////////////////////////////////////////////////////////////// @@ -41,10 +43,6 @@ static NS_DEFINE_IID(kXULPopupListenerCID, NS_XULPOPUPLISTENER_CID); static NS_DEFINE_IID(kIXULPopupListenerIID, NS_IXULPOPUPLISTENER_IID); static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); -static NS_DEFINE_IID(kIDomNodeIID, NS_IDOMNODE_IID); -static NS_DEFINE_IID(kIDomElementIID, NS_IDOMELEMENT_IID); -static NS_DEFINE_IID(kIDomEventListenerIID, NS_IDOMEVENTLISTENER_IID); - //////////////////////////////////////////////////////////////////////// // PopupListenerImpl // @@ -71,8 +69,8 @@ public: virtual nsresult MouseUp(nsIDOMEvent* aMouseEvent) { return NS_OK; }; virtual nsresult MouseClick(nsIDOMEvent* aMouseEvent) { return NS_OK; }; virtual nsresult MouseDblClick(nsIDOMEvent* aMouseEvent) { return NS_OK; }; - virtual nsresult MouseOver(nsIDOMEvent* aMouseEvent) { return NS_OK; }; - virtual nsresult MouseOut(nsIDOMEvent* aMouseEvent) { return NS_OK; }; + virtual nsresult MouseOver(nsIDOMEvent* aMouseEvent) ; + virtual nsresult MouseOut(nsIDOMEvent* aMouseEvent) ; // nsIDOMFocusListener virtual nsresult Focus(nsIDOMEvent* aEvent) { return NS_OK; }; @@ -82,16 +80,35 @@ public: virtual nsresult HandleEvent(nsIDOMEvent* anEvent) { return NS_OK; }; protected: + virtual nsresult LaunchPopup(nsIDOMEvent* anEvent); + virtual nsresult LaunchPopup( nsIDOMElement* aElement, PRInt32 aScreenX, PRInt32 aScreenY, + PRInt32 aClientX, PRInt32 aClientY ) ; + + nsresult FindDocumentForNode ( nsIDOMNode* inNode, nsIDOMXULDocument** outDoc ) ; private: - nsIDOMElement* element; // Weak reference. The element will go away first. + // |mElement| is the node to which this listener is attached. + nsIDOMElement* mElement; // Weak ref. The element will go away first. XULPopupType popupType; + nsCOMPtr mPopup; // The popup. We are responsible for making it go away. + + // The following members are not used unless |popupType| is tooltip. + + // a timer for determining if a tooltip should be displayed. + static void sTooltipCallback ( nsITimer *aTimer, void *aClosure ) ; + nsCOMPtr mTooltipTimer; + PRInt32 mMouseLocX, mMouseLocY; // mouse coordinates for tooltip event + // The node hovered over that fired the timer. This may turn into the node that + // triggered the tooltip, but only if the timer ever gets around to firing. + nsIDOMNode* mPossibleTooltipNode; // weak ref. + }; //////////////////////////////////////////////////////////////////////// XULPopupListenerImpl::XULPopupListenerImpl(void) + : mElement(nsnull), mPossibleTooltipNode(nsnull), mMouseLocX(0), mMouseLocY(0) { NS_INIT_REFCNT(); @@ -99,6 +116,11 @@ XULPopupListenerImpl::XULPopupListenerImpl(void) XULPopupListenerImpl::~XULPopupListenerImpl(void) { + //XXX do we need to close the popup here? Will we get the right events as + //XXX the topLevel window is going away when the closebox is pressed? + if ( mPopup ) + mPopup->Close(); + } NS_IMPL_ADDREF(XULPopupListenerImpl) @@ -126,7 +148,7 @@ XULPopupListenerImpl::QueryInterface(REFNSIID iid, void** result) NS_ADDREF_THIS(); return NS_OK; } - else if (iid.Equals(kIDomEventListenerIID)) { + else if (iid.Equals(nsIDOMEventListener::GetIID())) { *result = (nsIDOMEventListener*)(nsIDOMMouseListener*)this; NS_ADDREF_THIS(); return NS_OK; @@ -138,7 +160,7 @@ XULPopupListenerImpl::QueryInterface(REFNSIID iid, void** result) NS_IMETHODIMP XULPopupListenerImpl::Init(nsIDOMElement* aElement, const XULPopupType& popup) { - element = aElement; // Weak reference. Don't addref it. + mElement = aElement; // Weak reference. Don't addref it. popupType = popup; return NS_OK; } @@ -187,24 +209,186 @@ XULPopupListenerImpl::MouseDown(nsIDOMEvent* aMouseEvent) return NS_OK; } + +// +// MouseOver +// +// If we're a tooltip, fire off a timer to see if a tooltip should be shown. +// nsresult -XULPopupListenerImpl::LaunchPopup(nsIDOMEvent* anEvent) +XULPopupListenerImpl::MouseOver(nsIDOMEvent* aMouseEvent) +{ + nsresult rv = NS_OK; + + // make sure we're a tooltip. if not, bail. + if ( popupType != eXULPopupType_tooltip ) + return NS_OK; + + //XXX recognize when a popup is already up and immediately show the + //XXX tooltip for the new item if the dom element is different than + //XXX the element for which we are currently displaying the tip. + //XXX + //XXX for now, just be stupid to get things working. + + // Kill off an old timer and create a new one. + if ( mTooltipTimer ) { + mTooltipTimer->Cancel(); + mTooltipTimer = nsnull; + } + NS_NewTimer ( getter_AddRefs(mTooltipTimer) ); + if ( mTooltipTimer ) { + nsCOMPtr uiEvent ( do_QueryInterface(aMouseEvent) ); + if ( uiEvent ) { + // stash the coordinates of the event so that we can still get back to it from within the + // timer scallback. Also stash the node that started this so we can put it into the + // document later on (if the timer ever fires). + nsCOMPtr eventTarget; + aMouseEvent->GetTarget(getter_AddRefs(eventTarget)); + mPossibleTooltipNode = eventTarget.get(); +// BUG: 8598, widget and mouse coords not set for MouseOver events. +// uiEvent->GetScreenX(&mMouseLocX); +// uiEvent->GetScreenY(&mMouseLocY); + mMouseLocX = 50; mMouseLocY = 50; // XXX until bug 8598 fixed + mTooltipTimer->Init(sTooltipCallback, this, 1000); // one second delay + } + } + else + NS_WARNING ( "Could not create a timer for tooltip tracking" ); + + return NS_OK; + +} // MouseOver + + +// +// MouseOut +// +// If we're a tooltip, hide any tip that might be showing and remove any +// timer that is pending since the mouse is no longer over this area. +// +nsresult +XULPopupListenerImpl::MouseOut(nsIDOMEvent* aMouseEvent) +{ + // make sure we're a tooltip. if not, bail. + if ( popupType != eXULPopupType_tooltip ) + return NS_OK; + + if ( mTooltipTimer ) + mTooltipTimer->Cancel(); + + if ( mPopup ) { + mPopup->Close(); // hide the popup + mPopup = nsnull; // release the popup + + // clear out the tooltip node on the document + nsCOMPtr eventTarget; + aMouseEvent->GetTarget(getter_AddRefs(eventTarget)); + nsCOMPtr doc; + FindDocumentForNode ( eventTarget, getter_AddRefs(doc) ); + if ( doc ) + doc->SetTooltipElement(nsnull); + } + + return NS_OK; + +} // MouseOut + + +// +// FindDocumentForNode +// +// Given a DOM content node, finds the XUL document associated with it +// +nsresult +XULPopupListenerImpl :: FindDocumentForNode ( nsIDOMNode* inElement, nsIDOMXULDocument** outDoc ) +{ + nsresult rv = NS_OK; + + if ( !outDoc || !inElement ) + return NS_ERROR_INVALID_ARG; + + // get the document associated with this content element + nsCOMPtr document; + nsCOMPtr content = do_QueryInterface(inElement); + if (NS_FAILED(rv = content->GetDocument(*getter_AddRefs(document)))) { + NS_ERROR("Unable to retrieve the document."); + return rv; + } + + // Turn the document into a XUL document so we can use getElementById + nsCOMPtr xulDocument = do_QueryInterface(document); + if (xulDocument == nsnull) { + NS_ERROR("Popup attached to an element that isn't in XUL!"); + return NS_ERROR_FAILURE; + } + + *outDoc = xulDocument; + NS_ADDREF ( *outDoc ); + + return rv; + +} // FindDocumentForNode + + +// +// LaunchPopup +// +nsresult +XULPopupListenerImpl::LaunchPopup ( nsIDOMEvent* anEvent ) +{ + // Retrieve our x and y position. + nsCOMPtr uiEvent ( do_QueryInterface(anEvent) ); + if (!uiEvent) { + //non-ui event passed in. bad things. + return NS_OK; + } + + PRInt32 xPos, yPos; + uiEvent->GetScreenX(&xPos); + uiEvent->GetScreenY(&yPos); + + PRInt32 offsetX, offsetY; + uiEvent->GetClientX(&offsetX); + uiEvent->GetClientY(&offsetY); + + return LaunchPopup ( mElement, xPos, yPos, offsetX, offsetY ); +} + + +// +// LaunchPopup +// +// Given the element on which the event was triggered and the mouse locations in +// screen and widget coordinates, popup a new window showing the appropriate +// content. +// +// This looks for an attribute on |aElement| of the appropriate popup type +// (popup, context, tooltip) and uses that attribute's value as an ID for +// the popup content in the document. +// +nsresult +XULPopupListenerImpl::LaunchPopup( nsIDOMElement* aElement, PRInt32 aScreenX, PRInt32 aScreenY, + PRInt32 aOffsetX, PRInt32 aOffsetY ) { nsresult rv = NS_OK; nsAutoString type("popup"); - if (eXULPopupType_context == popupType) + if ( popupType == eXULPopupType_context ) type = "context"; + else if ( popupType == eXULPopupType_tooltip ) + type = "tooltip"; nsAutoString identifier; - element->GetAttribute(type, identifier); + mElement->GetAttribute(type, identifier); if (identifier == "") return rv; - // Try to find the popup content. + // Try to find the popup content and the document. We don't use FindDocumentForNode() + // in this case because we need the nsIDocument interface anyway for the script + // context. nsCOMPtr document; - nsCOMPtr content = do_QueryInterface(element); + nsCOMPtr content = do_QueryInterface(mElement); if (NS_FAILED(rv = content->GetDocument(*getter_AddRefs(document)))) { NS_ERROR("Unable to retrieve the document."); return rv; @@ -219,17 +403,15 @@ XULPopupListenerImpl::LaunchPopup(nsIDOMEvent* anEvent) // XXX Handle the _child case for popups and context menus! - // Use getElementById to obtain the popup content. + // Use getElementById to obtain the popup content and gracefully fail if + // we didn't find any popup content in the document. nsCOMPtr popupContent; if (NS_FAILED(rv = xulDocument->GetElementById(identifier, getter_AddRefs(popupContent)))) { NS_ERROR("GetElementById had some kind of spasm."); return rv; } - - if (popupContent == nsnull) { - // Gracefully fail in this case. + if ( !popupContent ) return NS_OK; - } // We have some popup content. Obtain our window. nsIScriptContextOwner* owner = document->GetScriptContextOwner(); @@ -242,42 +424,30 @@ XULPopupListenerImpl::LaunchPopup(nsIDOMEvent* anEvent) if (domWindow != nsnull) { // Find out if we're anchored. nsAutoString anchorAlignment("none"); - element->GetAttribute("popupanchor", anchorAlignment); + mElement->GetAttribute("popupanchor", anchorAlignment); nsAutoString popupAlignment("topleft"); - element->GetAttribute("popupalign", popupAlignment); + mElement->GetAttribute("popupalign", popupAlignment); - // Set the popup in the document for the duration of this call. - xulDocument->SetPopup(element); + // Set the popup in the document for the duration of this call. + xulDocument->SetPopupElement(mElement); - // Retrieve our x and y position. - nsCOMPtruiEvent; - uiEvent = do_QueryInterface(anEvent); - if (!uiEvent) { - //non-ui event passed in. bad things. - return NS_OK; - } - - PRInt32 xPos, yPos; - uiEvent->GetScreenX(&xPos); - uiEvent->GetScreenY(&yPos); - // If we're anchored, we pass in client/screen offsets so that - // we can translate the frames corners to screen coords. + // we can translate the frames corners to screen coords. + PRInt32 xPos = aScreenX, yPos = aScreenY; if (anchorAlignment != "none") { - PRInt32 offsetX, offsetY; - uiEvent->GetClientX(&offsetX); - uiEvent->GetClientY(&offsetY); - xPos = xPos-offsetX; - yPos = yPos-offsetY; + xPos -= aOffsetX; + yPos -= aOffsetY; } - - domWindow->CreatePopup(element, popupContent, - xPos, yPos, - type, anchorAlignment, popupAlignment); + domWindow->CreatePopup(mElement, popupContent, + xPos, yPos, + type, anchorAlignment, popupAlignment, + getter_AddRefs(mPopup)); + if ( popupType == eXULPopupType_popup && mPopup ) + mPopup->Focus(); // XXX For menus only, clear the document.popup field. - } + } NS_RELEASE(global); } } @@ -290,10 +460,12 @@ nsresult XULPopupListenerImpl::Blur(nsIDOMEvent* aMouseEvent) { nsresult rv = NS_OK; - + +#if 0 +// ONLY NEEDED BECAUSE HYATT WAS LAZY // Try to find the popup content. nsCOMPtr document; - nsCOMPtr content = do_QueryInterface(element); + nsCOMPtr content = do_QueryInterface(mElement); if (NS_FAILED(rv = content->GetDocument(*getter_AddRefs(document)))) { NS_ERROR("Unable to retrieve the document."); return rv; @@ -319,7 +491,20 @@ XULPopupListenerImpl::Blur(nsIDOMEvent* aMouseEvent) domWindow->Close(); } } +#endif + // Blur events don't bubble, so this means our window lost focus. + // Let's check just to make sure. + nsCOMPtr eventTarget; + aMouseEvent->GetTarget(getter_AddRefs(eventTarget)); + + // Close, but only if we are the same target. + nsCOMPtr windowNode = do_QueryInterface(mPopup); + if (windowNode.get() == eventTarget.get()) { + mPopup->Close(); + mPopup = nsnull; + } + // XXX Figure out how to fire the DESTROY event for the // arbitrary XUL case @@ -329,6 +514,40 @@ XULPopupListenerImpl::Blur(nsIDOMEvent* aMouseEvent) return rv; } + +// +// sTooltipCallback +// +// A timer callback, fired when the mouse has hovered inside of a frame for the +// appropriate amount of time. Getting to this point means that we should show the +// toolip. +// +// This relies on certain things being cached into the |aClosure| object passed to +// us by the timer: +// -- the x/y coordinates of the mouse +// -- the dom node the user hovered over +// +void +XULPopupListenerImpl :: sTooltipCallback (nsITimer *aTimer, void *aClosure) +{ + XULPopupListenerImpl* self = NS_STATIC_CAST(XULPopupListenerImpl*, aClosure); + if ( self ) { + // set the node in the document that triggered the tooltip and show it + nsCOMPtr doc; + self->FindDocumentForNode ( self->mPossibleTooltipNode, getter_AddRefs(doc) ); + if ( doc ) { + nsCOMPtr element ( do_QueryInterface(self->mPossibleTooltipNode) ); + if ( element ) { + doc->SetTooltipElement ( element ); + self->LaunchPopup ( element, self->mMouseLocX, self->mMouseLocY, 0, 0 ); + } + } // if document + } // if "self" data valid + +} // sTimerCallback + + + //////////////////////////////////////////////////////////////// nsresult NS_NewXULPopupListener(nsIXULPopupListener** pop) diff --git a/mozilla/content/xul/document/src/nsXULDocument.cpp b/mozilla/content/xul/document/src/nsXULDocument.cpp index 7c547b879da..3c07b0ae45d 100644 --- a/mozilla/content/xul/document/src/nsXULDocument.cpp +++ b/mozilla/content/xul/document/src/nsXULDocument.cpp @@ -782,10 +782,20 @@ protected: nsString mCommand; nsCOMPtr mFragmentRoot; // [OWNER] nsVoidArray mSubDocuments; // [OWNER] of subelements - nsCOMPtr mPopup; // [OWNER] of this popup element in the doc PRBool mIsPopup; nsCOMPtr mHiddenForm; // [OWNER] of this content element nsCOMPtr mFocusTracker; // [OWNER] of the focus tracker + + // The following are pointers into the content model which provide access to + // the objects triggering either a popup or a tooltip. These are marked as + // [OWNER] only because someone could, through DOM calls, delete the object from the + // content model while the popup/tooltip was visible. If we didn't have a reference + // to it, the object would go away and we'd be left pointing to garbage. This + // does not introduce cycles into the ownership model because this is still + // parent/child ownership. Just wanted the reader to know hyatt and I had thought about + // this (pinkerton). + nsCOMPtr mPopupElement; // [OWNER] element triggering the popup + nsCOMPtr mTooltipElement; // [OWNER] element triggering the tooltip }; PRInt32 XULDocumentImpl::gRefCnt = 0; @@ -2902,20 +2912,37 @@ XULDocumentImpl::CreateRange(nsIDOMRange** aRange) // nsIDOMXULDocument interface NS_IMETHODIMP -XULDocumentImpl::GetPopup(nsIDOMElement** anElement) +XULDocumentImpl::GetPopupElement(nsIDOMElement** anElement) { - *anElement = mPopup; + *anElement = mPopupElement; NS_IF_ADDREF(*anElement); return NS_OK; } NS_IMETHODIMP -XULDocumentImpl::SetPopup(nsIDOMElement* anElement) +XULDocumentImpl::SetPopupElement(nsIDOMElement* anElement) { - mPopup = dont_QueryInterface(anElement); + mPopupElement = dont_QueryInterface(anElement); return NS_OK; } + +NS_IMETHODIMP +XULDocumentImpl::GetTooltipElement(nsIDOMElement** anElement) +{ + *anElement = mTooltipElement; + NS_IF_ADDREF(*anElement); + return NS_OK; +} + +NS_IMETHODIMP +XULDocumentImpl::SetTooltipElement(nsIDOMElement* anElement) +{ + mTooltipElement = dont_QueryInterface(anElement); + return NS_OK; +} + + NS_IMETHODIMP XULDocumentImpl::GetFocus(nsIDOMXULFocusTracker** aTracker) { @@ -3128,7 +3155,7 @@ XULDocumentImpl::CreatePopupDocument(nsIContent* aPopupElement, nsIDocument** aR popupDoc->mNameSpaceManager = mNameSpaceManager; // We share the mPopup - popupDoc->mPopup = mPopup; + popupDoc->mPopupElement = mPopupElement; // Suck all of the root's content into our document. // We need to make the XUL builder instantiate this node. diff --git a/mozilla/docshell/base/nsWebShell.cpp b/mozilla/docshell/base/nsWebShell.cpp index 6f90cffc07a..58fde3d4957 100644 --- a/mozilla/docshell/base/nsWebShell.cpp +++ b/mozilla/docshell/base/nsWebShell.cpp @@ -266,7 +266,7 @@ public: PRInt32 aXPos, PRInt32 aYPos, const nsString& aPopupType, const nsString& anAnchorAlignment, const nsString& aPopupAlignment, - nsIDOMWindow* aWindow); + nsIDOMWindow* aWindow, nsIDOMWindow** outPopup); NS_IMETHOD FindWebShellWithName(const PRUnichar* aName, nsIWebShell*& aResult); NS_IMETHOD FocusAvailable(nsIWebShell* aFocusedWebShell, PRBool& aFocusTaken); @@ -2198,12 +2198,12 @@ nsWebShell::CreatePopup(nsIDOMElement* aElement, nsIDOMElement* aPopupContent, PRInt32 aXPos, PRInt32 aYPos, const nsString& aPopupType, const nsString& anAnchorAlignment, const nsString& aPopupAlignment, - nsIDOMWindow* aWindow) + nsIDOMWindow* aWindow, nsIDOMWindow** outPopup) { if (nsnull != mContainer) { return mContainer->CreatePopup(aElement, aPopupContent, aXPos, aYPos, aPopupType, anAnchorAlignment, aPopupAlignment, - aWindow); + aWindow, outPopup); } return NS_OK; } diff --git a/mozilla/dom/public/base/nsIDOMWindow.h b/mozilla/dom/public/base/nsIDOMWindow.h index 568c9e62df1..a08250e271e 100644 --- a/mozilla/dom/public/base/nsIDOMWindow.h +++ b/mozilla/dom/public/base/nsIDOMWindow.h @@ -158,7 +158,7 @@ public: NS_IMETHOD SetInterval(JSContext *cx, jsval *argv, PRUint32 argc, PRInt32* aReturn)=0; - NS_IMETHOD CreatePopup(nsIDOMElement* aElement, nsIDOMElement* aPopupContent, PRInt32 aXPos, PRInt32 aYPos, const nsString& aPopupType, const nsString& aAnchorAlignment, const nsString& aPopupAlignment)=0; + NS_IMETHOD CreatePopup(nsIDOMElement* aElement, nsIDOMElement* aPopupContent, PRInt32 aXPos, PRInt32 aYPos, const nsString& aPopupType, const nsString& aAnchorAlignment, const nsString& aPopupAlignment, nsIDOMWindow** aReturn)=0; NS_IMETHOD Open(JSContext *cx, jsval *argv, PRUint32 argc, nsIDOMWindow** aReturn)=0; @@ -231,7 +231,7 @@ public: NS_IMETHOD ClearInterval(PRInt32 aTimerID); \ NS_IMETHOD SetTimeout(JSContext *cx, jsval *argv, PRUint32 argc, PRInt32* aReturn); \ NS_IMETHOD SetInterval(JSContext *cx, jsval *argv, PRUint32 argc, PRInt32* aReturn); \ - NS_IMETHOD CreatePopup(nsIDOMElement* aElement, nsIDOMElement* aPopupContent, PRInt32 aXPos, PRInt32 aYPos, const nsString& aPopupType, const nsString& aAnchorAlignment, const nsString& aPopupAlignment); \ + NS_IMETHOD CreatePopup(nsIDOMElement* aElement, nsIDOMElement* aPopupContent, PRInt32 aXPos, PRInt32 aYPos, const nsString& aPopupType, const nsString& aAnchorAlignment, const nsString& aPopupAlignment, nsIDOMWindow** aReturn); \ NS_IMETHOD Open(JSContext *cx, jsval *argv, PRUint32 argc, nsIDOMWindow** aReturn); \ NS_IMETHOD OpenDialog(JSContext *cx, jsval *argv, PRUint32 argc, nsIDOMWindow** aReturn); \ @@ -302,7 +302,7 @@ public: NS_IMETHOD ClearInterval(PRInt32 aTimerID) { return _to ClearInterval(aTimerID); } \ NS_IMETHOD SetTimeout(JSContext *cx, jsval *argv, PRUint32 argc, PRInt32* aReturn) { return _to SetTimeout(cx, argv, argc, aReturn); } \ NS_IMETHOD SetInterval(JSContext *cx, jsval *argv, PRUint32 argc, PRInt32* aReturn) { return _to SetInterval(cx, argv, argc, aReturn); } \ - NS_IMETHOD CreatePopup(nsIDOMElement* aElement, nsIDOMElement* aPopupContent, PRInt32 aXPos, PRInt32 aYPos, const nsString& aPopupType, const nsString& aAnchorAlignment, const nsString& aPopupAlignment) { return _to CreatePopup(aElement, aPopupContent, aXPos, aYPos, aPopupType, aAnchorAlignment, aPopupAlignment); } \ + NS_IMETHOD CreatePopup(nsIDOMElement* aElement, nsIDOMElement* aPopupContent, PRInt32 aXPos, PRInt32 aYPos, const nsString& aPopupType, const nsString& aAnchorAlignment, const nsString& aPopupAlignment, nsIDOMWindow** aReturn) { return _to CreatePopup(aElement, aPopupContent, aXPos, aYPos, aPopupType, aAnchorAlignment, aPopupAlignment, aReturn); } \ NS_IMETHOD Open(JSContext *cx, jsval *argv, PRUint32 argc, nsIDOMWindow** aReturn) { return _to Open(cx, argv, argc, aReturn); } \ NS_IMETHOD OpenDialog(JSContext *cx, jsval *argv, PRUint32 argc, nsIDOMWindow** aReturn) { return _to OpenDialog(cx, argv, argc, aReturn); } \ diff --git a/mozilla/dom/public/idl/base/Window.idl b/mozilla/dom/public/idl/base/Window.idl index 41de63e6ebd..41dff8e9ade 100644 --- a/mozilla/dom/public/idl/base/Window.idl +++ b/mozilla/dom/public/idl/base/Window.idl @@ -57,11 +57,11 @@ long setTimeout(/* ... */); long setInterval(/* ... */); - void createPopup(in Element element, in Element popupContent, - in long xPos, in long yPos, - in DOMString popupType, in DOMString anchorAlignment, - in DOMString popupAlignment); - + Window createPopup(in Element element, in Element popupContent, + in long xPos, in long yPos, + in DOMString popupType, in DOMString anchorAlignment, + in DOMString popupAlignment); + Window open(/* ... */); Window openDialog(/* ... */); }; diff --git a/mozilla/dom/public/idl/xul/XULDocument.idl b/mozilla/dom/public/idl/xul/XULDocument.idl index 4384235a701..c9ade622132 100644 --- a/mozilla/dom/public/idl/xul/XULDocument.idl +++ b/mozilla/dom/public/idl/xul/XULDocument.idl @@ -3,7 +3,9 @@ interface XULDocument : Document { /* IID: { 0x17ddd8c0, 0xc5f8, 0x11d2, \ { 0xa6, 0xae, 0x0, 0x10, 0x4b, 0xde, 0x60, 0x48 } } */ - attribute Element popup; + attribute Element popupElement; + attribute Element tooltipElement; + readonly attribute XULFocusTracker focus; Element getElementById(in DOMString id); diff --git a/mozilla/dom/public/xul/nsIDOMXULDocument.h b/mozilla/dom/public/xul/nsIDOMXULDocument.h index 3f20070c2c0..22da40adc3d 100644 --- a/mozilla/dom/public/xul/nsIDOMXULDocument.h +++ b/mozilla/dom/public/xul/nsIDOMXULDocument.h @@ -37,8 +37,11 @@ class nsIDOMXULDocument : public nsIDOMDocument { public: static const nsIID& GetIID() { static nsIID iid = NS_IDOMXULDOCUMENT_IID; return iid; } - NS_IMETHOD GetPopup(nsIDOMElement** aPopup)=0; - NS_IMETHOD SetPopup(nsIDOMElement* aPopup)=0; + NS_IMETHOD GetPopupElement(nsIDOMElement** aPopupElement)=0; + NS_IMETHOD SetPopupElement(nsIDOMElement* aPopupElement)=0; + + NS_IMETHOD GetTooltipElement(nsIDOMElement** aTooltipElement)=0; + NS_IMETHOD SetTooltipElement(nsIDOMElement* aTooltipElement)=0; NS_IMETHOD GetFocus(nsIDOMXULFocusTracker** aFocus)=0; @@ -49,8 +52,10 @@ public: #define NS_DECL_IDOMXULDOCUMENT \ - NS_IMETHOD GetPopup(nsIDOMElement** aPopup); \ - NS_IMETHOD SetPopup(nsIDOMElement* aPopup); \ + NS_IMETHOD GetPopupElement(nsIDOMElement** aPopupElement); \ + NS_IMETHOD SetPopupElement(nsIDOMElement* aPopupElement); \ + NS_IMETHOD GetTooltipElement(nsIDOMElement** aTooltipElement); \ + NS_IMETHOD SetTooltipElement(nsIDOMElement* aTooltipElement); \ NS_IMETHOD GetFocus(nsIDOMXULFocusTracker** aFocus); \ NS_IMETHOD GetElementById(const nsString& aId, nsIDOMElement** aReturn); \ NS_IMETHOD GetElementsByAttribute(const nsString& aName, const nsString& aValue, nsIDOMNodeList** aReturn); \ @@ -58,8 +63,10 @@ public: #define NS_FORWARD_IDOMXULDOCUMENT(_to) \ - NS_IMETHOD GetPopup(nsIDOMElement** aPopup) { return _to GetPopup(aPopup); } \ - NS_IMETHOD SetPopup(nsIDOMElement* aPopup) { return _to SetPopup(aPopup); } \ + NS_IMETHOD GetPopupElement(nsIDOMElement** aPopupElement) { return _to GetPopupElement(aPopupElement); } \ + NS_IMETHOD SetPopupElement(nsIDOMElement* aPopupElement) { return _to SetPopupElement(aPopupElement); } \ + NS_IMETHOD GetTooltipElement(nsIDOMElement** aTooltipElement) { return _to GetTooltipElement(aTooltipElement); } \ + NS_IMETHOD SetTooltipElement(nsIDOMElement* aTooltipElement) { return _to SetTooltipElement(aTooltipElement); } \ NS_IMETHOD GetFocus(nsIDOMXULFocusTracker** aFocus) { return _to GetFocus(aFocus); } \ NS_IMETHOD GetElementById(const nsString& aId, nsIDOMElement** aReturn) { return _to GetElementById(aId, aReturn); } \ NS_IMETHOD GetElementsByAttribute(const nsString& aName, const nsString& aValue, nsIDOMNodeList** aReturn) { return _to GetElementsByAttribute(aName, aValue, aReturn); } \ diff --git a/mozilla/dom/src/base/nsGlobalWindow.cpp b/mozilla/dom/src/base/nsGlobalWindow.cpp index a4a3eef53d0..73d267bc27f 100644 --- a/mozilla/dom/src/base/nsGlobalWindow.cpp +++ b/mozilla/dom/src/base/nsGlobalWindow.cpp @@ -2079,14 +2079,15 @@ NS_IMETHODIMP GlobalWindowImpl::CreatePopup(nsIDOMElement* aElement, nsIDOMElement* aPopupContent, PRInt32 aXPos, PRInt32 aYPos, const nsString& aPopupType, - const nsString& anAnchorAlignment, const nsString& aPopupAlignment) + const nsString& anAnchorAlignment, const nsString& aPopupAlignment, + nsIDOMWindow** outPopup) { if (nsnull != mWebShell) { // Pass this off to the parent. nsCOMPtr webShellContainer = do_QueryInterface(mWebShell); if (webShellContainer) { webShellContainer->CreatePopup(aElement, aPopupContent, aXPos, aYPos, aPopupType, - anAnchorAlignment, aPopupAlignment, this); + anAnchorAlignment, aPopupAlignment, this, outPopup); } } return NS_OK; diff --git a/mozilla/dom/src/base/nsGlobalWindow.h b/mozilla/dom/src/base/nsGlobalWindow.h index af2487b7257..b633b1e7c2c 100644 --- a/mozilla/dom/src/base/nsGlobalWindow.h +++ b/mozilla/dom/src/base/nsGlobalWindow.h @@ -165,7 +165,7 @@ public: NS_IMETHOD CreatePopup(nsIDOMElement* aElement, nsIDOMElement* aPopupContent, PRInt32 aXPos, PRInt32 aYPos, const nsString& aPopupType, const nsString& anAnchorAlignment, - const nsString& aPopupAlignment); + const nsString& aPopupAlignment, nsIDOMWindow** outPopup); // nsIDOMEventCapturer interface NS_IMETHOD CaptureEvent(const nsString& aType); diff --git a/mozilla/dom/src/base/nsJSWindow.cpp b/mozilla/dom/src/base/nsJSWindow.cpp index 94fe3b5b469..c9ceee3f883 100644 --- a/mozilla/dom/src/base/nsJSWindow.cpp +++ b/mozilla/dom/src/base/nsJSWindow.cpp @@ -2083,6 +2083,7 @@ WindowCreatePopup(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval * { nsIDOMWindow *nativeThis = (nsIDOMWindow*)nsJSUtils::nsGetNativeThis(cx, obj); JSBool rBool = JS_FALSE; + nsIDOMWindow* nativeRet; nsIDOMElementPtr b0; nsIDOMElementPtr b1; PRInt32 b2; @@ -2147,11 +2148,11 @@ WindowCreatePopup(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval * nsJSUtils::nsConvertJSValToString(b6, cx, argv[6]); - if (NS_OK != nativeThis->CreatePopup(b0, b1, b2, b3, b4, b5, b6)) { + if (NS_OK != nativeThis->CreatePopup(b0, b1, b2, b3, b4, b5, b6, &nativeRet)) { return JS_FALSE; } - *rval = JSVAL_VOID; + nsJSUtils::nsConvertObjectToJSVal(nativeRet, cx, rval); } else { JS_ReportError(cx, "Function createPopup requires 7 parameters"); diff --git a/mozilla/dom/src/xul/nsJSXULDocument.cpp b/mozilla/dom/src/xul/nsJSXULDocument.cpp index 9bb0833dabc..8912f0ab0d7 100644 --- a/mozilla/dom/src/xul/nsJSXULDocument.cpp +++ b/mozilla/dom/src/xul/nsJSXULDocument.cpp @@ -50,8 +50,12 @@ NS_DEF_PTR(nsIDOMNodeList); // XULDocument property ids // enum XULDocument_slots { - XULDOCUMENT_POPUP = -1, - XULDOCUMENT_FOCUS = -2 + XULDOCUMENT_POPUPELEMENT = -1, + + XULDOCUMENT_TOOLTIPELEMENT = -2, + + XULDOCUMENT_FOCUS = -3 + }; /***********************************************************************/ @@ -61,30 +65,88 @@ enum XULDocument_slots { PR_STATIC_CALLBACK(JSBool) GetXULDocumentProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) { - nsIDOMXULDocument *a = (nsIDOMXULDocument*)JS_GetPrivate(cx, obj); + nsIDOMXULDocument *a = (nsIDOMXULDocument*)nsJSUtils::nsGetNativeThis(cx, obj); + + // If there's no private data, this must be the prototype, so ignore + if (nsnull == a) { + return JS_TRUE; + } + + if (JSVAL_IS_INT(id)) { + nsIScriptContext *scriptCX = (nsIScriptContext *)JS_GetContextPrivate(cx); + nsIScriptSecurityManager *secMan; - PRBool ok; + + PRBool ok = PR_FALSE; + if (NS_OK != scriptCX->GetSecurityManager(&secMan)) { + return JS_FALSE; + } + switch(JSVAL_TO_INT(id)) { - case XULDOCUMENT_POPUP: + + case XULDOCUMENT_POPUPELEMENT: + { - secMan->CheckScriptAccess(scriptCX, obj, "xuldocument.popup", &ok); + + secMan->CheckScriptAccess(scriptCX, obj, "xuldocument.popupelement", &ok); + if (!ok) { + //Need to throw error here + return JS_FALSE; + } + nsIDOMElement* prop; - if (NS_OK == a->GetPopup(&prop)) { + + if (NS_OK == a->GetPopupElement(&prop)) { + + // get the js object + + nsJSUtils::nsConvertObjectToJSVal((nsISupports *)prop, cx, vp); + + } + + else { + + return JS_FALSE; + + } + + break; + + } + + case XULDOCUMENT_TOOLTIPELEMENT: + + { + + secMan->CheckScriptAccess(scriptCX, obj, "xuldocument.tooltipelement", &ok); + + if (!ok) { + + //Need to throw error here + + return JS_FALSE; + + } + + nsIDOMElement* prop; + + if (NS_OK == a->GetTooltipElement(&prop)) { + // get the js object nsJSUtils::nsConvertObjectToJSVal((nsISupports *)prop, cx, vp); } @@ -129,36 +191,102 @@ GetXULDocumentProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) PR_STATIC_CALLBACK(JSBool) SetXULDocumentProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) { - nsIDOMXULDocument *a = (nsIDOMXULDocument*)JS_GetPrivate(cx, obj); + nsIDOMXULDocument *a = (nsIDOMXULDocument*)nsJSUtils::nsGetNativeThis(cx, obj); + + // If there's no private data, this must be the prototype, so ignore + if (nsnull == a) { + return JS_TRUE; + } + + if (JSVAL_IS_INT(id)) { + nsIScriptContext *scriptCX = (nsIScriptContext *)JS_GetContextPrivate(cx); + nsIScriptSecurityManager *secMan; - PRBool ok; + + PRBool ok = PR_FALSE; + if (NS_OK != scriptCX->GetSecurityManager(&secMan)) { + return JS_FALSE; + } + switch(JSVAL_TO_INT(id)) { - case XULDOCUMENT_POPUP: + + case XULDOCUMENT_POPUPELEMENT: + { - secMan->CheckScriptAccess(scriptCX, obj, "xuldocument.popup", &ok); + + secMan->CheckScriptAccess(scriptCX, obj, "xuldocument.popupelement", &ok); + if (!ok) { + //Need to throw error here + return JS_FALSE; + } + nsIDOMElement* prop; + if (PR_FALSE == nsJSUtils::nsConvertJSValToObject((nsISupports **)&prop, + kIElementIID, "Element", + cx, *vp)) { + return JS_FALSE; + } + - a->SetPopup(prop); + + a->SetPopupElement(prop); + + NS_IF_RELEASE(prop); + + break; + + } + + case XULDOCUMENT_TOOLTIPELEMENT: + + { + + secMan->CheckScriptAccess(scriptCX, obj, "xuldocument.tooltipelement", &ok); + + if (!ok) { + + //Need to throw error here + + return JS_FALSE; + + } + + nsIDOMElement* prop; + + if (PR_FALSE == nsJSUtils::nsConvertJSValToObject((nsISupports **)&prop, + + kIElementIID, "Element", + + cx, *vp)) { + + return JS_FALSE; + + } + + + + a->SetTooltipElement(prop); + NS_IF_RELEASE(prop); break; } @@ -211,7 +339,8 @@ ResolveXULDocument(JSContext *cx, JSObject *obj, jsval id) PR_STATIC_CALLBACK(JSBool) XULDocumentGetElementById(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { - nsIDOMXULDocument *nativeThis = (nsIDOMXULDocument*)JS_GetPrivate(cx, obj); + nsIDOMXULDocument *nativeThis = (nsIDOMXULDocument*)nsJSUtils::nsGetNativeThis(cx, obj); + JSBool rBool = JS_FALSE; nsIDOMElement* nativeRet; nsAutoString b0; @@ -263,7 +392,8 @@ XULDocumentGetElementById(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, PR_STATIC_CALLBACK(JSBool) XULDocumentGetElementsByAttribute(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { - nsIDOMXULDocument *nativeThis = (nsIDOMXULDocument*)JS_GetPrivate(cx, obj); + nsIDOMXULDocument *nativeThis = (nsIDOMXULDocument*)nsJSUtils::nsGetNativeThis(cx, obj); + JSBool rBool = JS_FALSE; nsIDOMNodeList* nativeRet; nsAutoString b0; @@ -335,7 +465,10 @@ JSClass XULDocumentClass = { // static JSPropertySpec XULDocumentProperties[] = { - {"popup", XULDOCUMENT_POPUP, JSPROP_ENUMERATE}, + {"popupElement", XULDOCUMENT_POPUPELEMENT, JSPROP_ENUMERATE}, + + {"tooltipElement", XULDOCUMENT_TOOLTIPELEMENT, JSPROP_ENUMERATE}, + {"focus", XULDOCUMENT_FOCUS, JSPROP_ENUMERATE | JSPROP_READONLY}, {0} }; diff --git a/mozilla/rdf/content/public/idl/XULDocument.idl b/mozilla/rdf/content/public/idl/XULDocument.idl index 4384235a701..c9ade622132 100644 --- a/mozilla/rdf/content/public/idl/XULDocument.idl +++ b/mozilla/rdf/content/public/idl/XULDocument.idl @@ -3,7 +3,9 @@ interface XULDocument : Document { /* IID: { 0x17ddd8c0, 0xc5f8, 0x11d2, \ { 0xa6, 0xae, 0x0, 0x10, 0x4b, 0xde, 0x60, 0x48 } } */ - attribute Element popup; + attribute Element popupElement; + attribute Element tooltipElement; + readonly attribute XULFocusTracker focus; Element getElementById(in DOMString id); diff --git a/mozilla/rdf/content/public/nsIDOMXULDocument.h b/mozilla/rdf/content/public/nsIDOMXULDocument.h index 3f20070c2c0..22da40adc3d 100644 --- a/mozilla/rdf/content/public/nsIDOMXULDocument.h +++ b/mozilla/rdf/content/public/nsIDOMXULDocument.h @@ -37,8 +37,11 @@ class nsIDOMXULDocument : public nsIDOMDocument { public: static const nsIID& GetIID() { static nsIID iid = NS_IDOMXULDOCUMENT_IID; return iid; } - NS_IMETHOD GetPopup(nsIDOMElement** aPopup)=0; - NS_IMETHOD SetPopup(nsIDOMElement* aPopup)=0; + NS_IMETHOD GetPopupElement(nsIDOMElement** aPopupElement)=0; + NS_IMETHOD SetPopupElement(nsIDOMElement* aPopupElement)=0; + + NS_IMETHOD GetTooltipElement(nsIDOMElement** aTooltipElement)=0; + NS_IMETHOD SetTooltipElement(nsIDOMElement* aTooltipElement)=0; NS_IMETHOD GetFocus(nsIDOMXULFocusTracker** aFocus)=0; @@ -49,8 +52,10 @@ public: #define NS_DECL_IDOMXULDOCUMENT \ - NS_IMETHOD GetPopup(nsIDOMElement** aPopup); \ - NS_IMETHOD SetPopup(nsIDOMElement* aPopup); \ + NS_IMETHOD GetPopupElement(nsIDOMElement** aPopupElement); \ + NS_IMETHOD SetPopupElement(nsIDOMElement* aPopupElement); \ + NS_IMETHOD GetTooltipElement(nsIDOMElement** aTooltipElement); \ + NS_IMETHOD SetTooltipElement(nsIDOMElement* aTooltipElement); \ NS_IMETHOD GetFocus(nsIDOMXULFocusTracker** aFocus); \ NS_IMETHOD GetElementById(const nsString& aId, nsIDOMElement** aReturn); \ NS_IMETHOD GetElementsByAttribute(const nsString& aName, const nsString& aValue, nsIDOMNodeList** aReturn); \ @@ -58,8 +63,10 @@ public: #define NS_FORWARD_IDOMXULDOCUMENT(_to) \ - NS_IMETHOD GetPopup(nsIDOMElement** aPopup) { return _to GetPopup(aPopup); } \ - NS_IMETHOD SetPopup(nsIDOMElement* aPopup) { return _to SetPopup(aPopup); } \ + NS_IMETHOD GetPopupElement(nsIDOMElement** aPopupElement) { return _to GetPopupElement(aPopupElement); } \ + NS_IMETHOD SetPopupElement(nsIDOMElement* aPopupElement) { return _to SetPopupElement(aPopupElement); } \ + NS_IMETHOD GetTooltipElement(nsIDOMElement** aTooltipElement) { return _to GetTooltipElement(aTooltipElement); } \ + NS_IMETHOD SetTooltipElement(nsIDOMElement* aTooltipElement) { return _to SetTooltipElement(aTooltipElement); } \ NS_IMETHOD GetFocus(nsIDOMXULFocusTracker** aFocus) { return _to GetFocus(aFocus); } \ NS_IMETHOD GetElementById(const nsString& aId, nsIDOMElement** aReturn) { return _to GetElementById(aId, aReturn); } \ NS_IMETHOD GetElementsByAttribute(const nsString& aName, const nsString& aValue, nsIDOMNodeList** aReturn) { return _to GetElementsByAttribute(aName, aValue, aReturn); } \ diff --git a/mozilla/rdf/content/src/nsJSXULDocument.cpp b/mozilla/rdf/content/src/nsJSXULDocument.cpp index 9bb0833dabc..8912f0ab0d7 100644 --- a/mozilla/rdf/content/src/nsJSXULDocument.cpp +++ b/mozilla/rdf/content/src/nsJSXULDocument.cpp @@ -50,8 +50,12 @@ NS_DEF_PTR(nsIDOMNodeList); // XULDocument property ids // enum XULDocument_slots { - XULDOCUMENT_POPUP = -1, - XULDOCUMENT_FOCUS = -2 + XULDOCUMENT_POPUPELEMENT = -1, + + XULDOCUMENT_TOOLTIPELEMENT = -2, + + XULDOCUMENT_FOCUS = -3 + }; /***********************************************************************/ @@ -61,30 +65,88 @@ enum XULDocument_slots { PR_STATIC_CALLBACK(JSBool) GetXULDocumentProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) { - nsIDOMXULDocument *a = (nsIDOMXULDocument*)JS_GetPrivate(cx, obj); + nsIDOMXULDocument *a = (nsIDOMXULDocument*)nsJSUtils::nsGetNativeThis(cx, obj); + + // If there's no private data, this must be the prototype, so ignore + if (nsnull == a) { + return JS_TRUE; + } + + if (JSVAL_IS_INT(id)) { + nsIScriptContext *scriptCX = (nsIScriptContext *)JS_GetContextPrivate(cx); + nsIScriptSecurityManager *secMan; - PRBool ok; + + PRBool ok = PR_FALSE; + if (NS_OK != scriptCX->GetSecurityManager(&secMan)) { + return JS_FALSE; + } + switch(JSVAL_TO_INT(id)) { - case XULDOCUMENT_POPUP: + + case XULDOCUMENT_POPUPELEMENT: + { - secMan->CheckScriptAccess(scriptCX, obj, "xuldocument.popup", &ok); + + secMan->CheckScriptAccess(scriptCX, obj, "xuldocument.popupelement", &ok); + if (!ok) { + //Need to throw error here + return JS_FALSE; + } + nsIDOMElement* prop; - if (NS_OK == a->GetPopup(&prop)) { + + if (NS_OK == a->GetPopupElement(&prop)) { + + // get the js object + + nsJSUtils::nsConvertObjectToJSVal((nsISupports *)prop, cx, vp); + + } + + else { + + return JS_FALSE; + + } + + break; + + } + + case XULDOCUMENT_TOOLTIPELEMENT: + + { + + secMan->CheckScriptAccess(scriptCX, obj, "xuldocument.tooltipelement", &ok); + + if (!ok) { + + //Need to throw error here + + return JS_FALSE; + + } + + nsIDOMElement* prop; + + if (NS_OK == a->GetTooltipElement(&prop)) { + // get the js object nsJSUtils::nsConvertObjectToJSVal((nsISupports *)prop, cx, vp); } @@ -129,36 +191,102 @@ GetXULDocumentProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) PR_STATIC_CALLBACK(JSBool) SetXULDocumentProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) { - nsIDOMXULDocument *a = (nsIDOMXULDocument*)JS_GetPrivate(cx, obj); + nsIDOMXULDocument *a = (nsIDOMXULDocument*)nsJSUtils::nsGetNativeThis(cx, obj); + + // If there's no private data, this must be the prototype, so ignore + if (nsnull == a) { + return JS_TRUE; + } + + if (JSVAL_IS_INT(id)) { + nsIScriptContext *scriptCX = (nsIScriptContext *)JS_GetContextPrivate(cx); + nsIScriptSecurityManager *secMan; - PRBool ok; + + PRBool ok = PR_FALSE; + if (NS_OK != scriptCX->GetSecurityManager(&secMan)) { + return JS_FALSE; + } + switch(JSVAL_TO_INT(id)) { - case XULDOCUMENT_POPUP: + + case XULDOCUMENT_POPUPELEMENT: + { - secMan->CheckScriptAccess(scriptCX, obj, "xuldocument.popup", &ok); + + secMan->CheckScriptAccess(scriptCX, obj, "xuldocument.popupelement", &ok); + if (!ok) { + //Need to throw error here + return JS_FALSE; + } + nsIDOMElement* prop; + if (PR_FALSE == nsJSUtils::nsConvertJSValToObject((nsISupports **)&prop, + kIElementIID, "Element", + cx, *vp)) { + return JS_FALSE; + } + - a->SetPopup(prop); + + a->SetPopupElement(prop); + + NS_IF_RELEASE(prop); + + break; + + } + + case XULDOCUMENT_TOOLTIPELEMENT: + + { + + secMan->CheckScriptAccess(scriptCX, obj, "xuldocument.tooltipelement", &ok); + + if (!ok) { + + //Need to throw error here + + return JS_FALSE; + + } + + nsIDOMElement* prop; + + if (PR_FALSE == nsJSUtils::nsConvertJSValToObject((nsISupports **)&prop, + + kIElementIID, "Element", + + cx, *vp)) { + + return JS_FALSE; + + } + + + + a->SetTooltipElement(prop); + NS_IF_RELEASE(prop); break; } @@ -211,7 +339,8 @@ ResolveXULDocument(JSContext *cx, JSObject *obj, jsval id) PR_STATIC_CALLBACK(JSBool) XULDocumentGetElementById(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { - nsIDOMXULDocument *nativeThis = (nsIDOMXULDocument*)JS_GetPrivate(cx, obj); + nsIDOMXULDocument *nativeThis = (nsIDOMXULDocument*)nsJSUtils::nsGetNativeThis(cx, obj); + JSBool rBool = JS_FALSE; nsIDOMElement* nativeRet; nsAutoString b0; @@ -263,7 +392,8 @@ XULDocumentGetElementById(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, PR_STATIC_CALLBACK(JSBool) XULDocumentGetElementsByAttribute(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { - nsIDOMXULDocument *nativeThis = (nsIDOMXULDocument*)JS_GetPrivate(cx, obj); + nsIDOMXULDocument *nativeThis = (nsIDOMXULDocument*)nsJSUtils::nsGetNativeThis(cx, obj); + JSBool rBool = JS_FALSE; nsIDOMNodeList* nativeRet; nsAutoString b0; @@ -335,7 +465,10 @@ JSClass XULDocumentClass = { // static JSPropertySpec XULDocumentProperties[] = { - {"popup", XULDOCUMENT_POPUP, JSPROP_ENUMERATE}, + {"popupElement", XULDOCUMENT_POPUPELEMENT, JSPROP_ENUMERATE}, + + {"tooltipElement", XULDOCUMENT_TOOLTIPELEMENT, JSPROP_ENUMERATE}, + {"focus", XULDOCUMENT_FOCUS, JSPROP_ENUMERATE | JSPROP_READONLY}, {0} }; diff --git a/mozilla/rdf/content/src/nsXULDocument.cpp b/mozilla/rdf/content/src/nsXULDocument.cpp index 7c547b879da..3c07b0ae45d 100644 --- a/mozilla/rdf/content/src/nsXULDocument.cpp +++ b/mozilla/rdf/content/src/nsXULDocument.cpp @@ -782,10 +782,20 @@ protected: nsString mCommand; nsCOMPtr mFragmentRoot; // [OWNER] nsVoidArray mSubDocuments; // [OWNER] of subelements - nsCOMPtr mPopup; // [OWNER] of this popup element in the doc PRBool mIsPopup; nsCOMPtr mHiddenForm; // [OWNER] of this content element nsCOMPtr mFocusTracker; // [OWNER] of the focus tracker + + // The following are pointers into the content model which provide access to + // the objects triggering either a popup or a tooltip. These are marked as + // [OWNER] only because someone could, through DOM calls, delete the object from the + // content model while the popup/tooltip was visible. If we didn't have a reference + // to it, the object would go away and we'd be left pointing to garbage. This + // does not introduce cycles into the ownership model because this is still + // parent/child ownership. Just wanted the reader to know hyatt and I had thought about + // this (pinkerton). + nsCOMPtr mPopupElement; // [OWNER] element triggering the popup + nsCOMPtr mTooltipElement; // [OWNER] element triggering the tooltip }; PRInt32 XULDocumentImpl::gRefCnt = 0; @@ -2902,20 +2912,37 @@ XULDocumentImpl::CreateRange(nsIDOMRange** aRange) // nsIDOMXULDocument interface NS_IMETHODIMP -XULDocumentImpl::GetPopup(nsIDOMElement** anElement) +XULDocumentImpl::GetPopupElement(nsIDOMElement** anElement) { - *anElement = mPopup; + *anElement = mPopupElement; NS_IF_ADDREF(*anElement); return NS_OK; } NS_IMETHODIMP -XULDocumentImpl::SetPopup(nsIDOMElement* anElement) +XULDocumentImpl::SetPopupElement(nsIDOMElement* anElement) { - mPopup = dont_QueryInterface(anElement); + mPopupElement = dont_QueryInterface(anElement); return NS_OK; } + +NS_IMETHODIMP +XULDocumentImpl::GetTooltipElement(nsIDOMElement** anElement) +{ + *anElement = mTooltipElement; + NS_IF_ADDREF(*anElement); + return NS_OK; +} + +NS_IMETHODIMP +XULDocumentImpl::SetTooltipElement(nsIDOMElement* anElement) +{ + mTooltipElement = dont_QueryInterface(anElement); + return NS_OK; +} + + NS_IMETHODIMP XULDocumentImpl::GetFocus(nsIDOMXULFocusTracker** aTracker) { @@ -3128,7 +3155,7 @@ XULDocumentImpl::CreatePopupDocument(nsIContent* aPopupElement, nsIDocument** aR popupDoc->mNameSpaceManager = mNameSpaceManager; // We share the mPopup - popupDoc->mPopup = mPopup; + popupDoc->mPopupElement = mPopupElement; // Suck all of the root's content into our document. // We need to make the XUL builder instantiate this node. diff --git a/mozilla/rdf/content/src/nsXULPopupListener.cpp b/mozilla/rdf/content/src/nsXULPopupListener.cpp index 9fb9805375a..bc6f2483400 100644 --- a/mozilla/rdf/content/src/nsXULPopupListener.cpp +++ b/mozilla/rdf/content/src/nsXULPopupListener.cpp @@ -34,6 +34,8 @@ #include "nsIDocument.h" #include "nsIContent.h" #include "nsIDOMUIEvent.h" +#include "nsITimer.h" + //////////////////////////////////////////////////////////////////////// @@ -41,10 +43,6 @@ static NS_DEFINE_IID(kXULPopupListenerCID, NS_XULPOPUPLISTENER_CID); static NS_DEFINE_IID(kIXULPopupListenerIID, NS_IXULPOPUPLISTENER_IID); static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); -static NS_DEFINE_IID(kIDomNodeIID, NS_IDOMNODE_IID); -static NS_DEFINE_IID(kIDomElementIID, NS_IDOMELEMENT_IID); -static NS_DEFINE_IID(kIDomEventListenerIID, NS_IDOMEVENTLISTENER_IID); - //////////////////////////////////////////////////////////////////////// // PopupListenerImpl // @@ -71,8 +69,8 @@ public: virtual nsresult MouseUp(nsIDOMEvent* aMouseEvent) { return NS_OK; }; virtual nsresult MouseClick(nsIDOMEvent* aMouseEvent) { return NS_OK; }; virtual nsresult MouseDblClick(nsIDOMEvent* aMouseEvent) { return NS_OK; }; - virtual nsresult MouseOver(nsIDOMEvent* aMouseEvent) { return NS_OK; }; - virtual nsresult MouseOut(nsIDOMEvent* aMouseEvent) { return NS_OK; }; + virtual nsresult MouseOver(nsIDOMEvent* aMouseEvent) ; + virtual nsresult MouseOut(nsIDOMEvent* aMouseEvent) ; // nsIDOMFocusListener virtual nsresult Focus(nsIDOMEvent* aEvent) { return NS_OK; }; @@ -82,16 +80,35 @@ public: virtual nsresult HandleEvent(nsIDOMEvent* anEvent) { return NS_OK; }; protected: + virtual nsresult LaunchPopup(nsIDOMEvent* anEvent); + virtual nsresult LaunchPopup( nsIDOMElement* aElement, PRInt32 aScreenX, PRInt32 aScreenY, + PRInt32 aClientX, PRInt32 aClientY ) ; + + nsresult FindDocumentForNode ( nsIDOMNode* inNode, nsIDOMXULDocument** outDoc ) ; private: - nsIDOMElement* element; // Weak reference. The element will go away first. + // |mElement| is the node to which this listener is attached. + nsIDOMElement* mElement; // Weak ref. The element will go away first. XULPopupType popupType; + nsCOMPtr mPopup; // The popup. We are responsible for making it go away. + + // The following members are not used unless |popupType| is tooltip. + + // a timer for determining if a tooltip should be displayed. + static void sTooltipCallback ( nsITimer *aTimer, void *aClosure ) ; + nsCOMPtr mTooltipTimer; + PRInt32 mMouseLocX, mMouseLocY; // mouse coordinates for tooltip event + // The node hovered over that fired the timer. This may turn into the node that + // triggered the tooltip, but only if the timer ever gets around to firing. + nsIDOMNode* mPossibleTooltipNode; // weak ref. + }; //////////////////////////////////////////////////////////////////////// XULPopupListenerImpl::XULPopupListenerImpl(void) + : mElement(nsnull), mPossibleTooltipNode(nsnull), mMouseLocX(0), mMouseLocY(0) { NS_INIT_REFCNT(); @@ -99,6 +116,11 @@ XULPopupListenerImpl::XULPopupListenerImpl(void) XULPopupListenerImpl::~XULPopupListenerImpl(void) { + //XXX do we need to close the popup here? Will we get the right events as + //XXX the topLevel window is going away when the closebox is pressed? + if ( mPopup ) + mPopup->Close(); + } NS_IMPL_ADDREF(XULPopupListenerImpl) @@ -126,7 +148,7 @@ XULPopupListenerImpl::QueryInterface(REFNSIID iid, void** result) NS_ADDREF_THIS(); return NS_OK; } - else if (iid.Equals(kIDomEventListenerIID)) { + else if (iid.Equals(nsIDOMEventListener::GetIID())) { *result = (nsIDOMEventListener*)(nsIDOMMouseListener*)this; NS_ADDREF_THIS(); return NS_OK; @@ -138,7 +160,7 @@ XULPopupListenerImpl::QueryInterface(REFNSIID iid, void** result) NS_IMETHODIMP XULPopupListenerImpl::Init(nsIDOMElement* aElement, const XULPopupType& popup) { - element = aElement; // Weak reference. Don't addref it. + mElement = aElement; // Weak reference. Don't addref it. popupType = popup; return NS_OK; } @@ -187,24 +209,186 @@ XULPopupListenerImpl::MouseDown(nsIDOMEvent* aMouseEvent) return NS_OK; } + +// +// MouseOver +// +// If we're a tooltip, fire off a timer to see if a tooltip should be shown. +// nsresult -XULPopupListenerImpl::LaunchPopup(nsIDOMEvent* anEvent) +XULPopupListenerImpl::MouseOver(nsIDOMEvent* aMouseEvent) +{ + nsresult rv = NS_OK; + + // make sure we're a tooltip. if not, bail. + if ( popupType != eXULPopupType_tooltip ) + return NS_OK; + + //XXX recognize when a popup is already up and immediately show the + //XXX tooltip for the new item if the dom element is different than + //XXX the element for which we are currently displaying the tip. + //XXX + //XXX for now, just be stupid to get things working. + + // Kill off an old timer and create a new one. + if ( mTooltipTimer ) { + mTooltipTimer->Cancel(); + mTooltipTimer = nsnull; + } + NS_NewTimer ( getter_AddRefs(mTooltipTimer) ); + if ( mTooltipTimer ) { + nsCOMPtr uiEvent ( do_QueryInterface(aMouseEvent) ); + if ( uiEvent ) { + // stash the coordinates of the event so that we can still get back to it from within the + // timer scallback. Also stash the node that started this so we can put it into the + // document later on (if the timer ever fires). + nsCOMPtr eventTarget; + aMouseEvent->GetTarget(getter_AddRefs(eventTarget)); + mPossibleTooltipNode = eventTarget.get(); +// BUG: 8598, widget and mouse coords not set for MouseOver events. +// uiEvent->GetScreenX(&mMouseLocX); +// uiEvent->GetScreenY(&mMouseLocY); + mMouseLocX = 50; mMouseLocY = 50; // XXX until bug 8598 fixed + mTooltipTimer->Init(sTooltipCallback, this, 1000); // one second delay + } + } + else + NS_WARNING ( "Could not create a timer for tooltip tracking" ); + + return NS_OK; + +} // MouseOver + + +// +// MouseOut +// +// If we're a tooltip, hide any tip that might be showing and remove any +// timer that is pending since the mouse is no longer over this area. +// +nsresult +XULPopupListenerImpl::MouseOut(nsIDOMEvent* aMouseEvent) +{ + // make sure we're a tooltip. if not, bail. + if ( popupType != eXULPopupType_tooltip ) + return NS_OK; + + if ( mTooltipTimer ) + mTooltipTimer->Cancel(); + + if ( mPopup ) { + mPopup->Close(); // hide the popup + mPopup = nsnull; // release the popup + + // clear out the tooltip node on the document + nsCOMPtr eventTarget; + aMouseEvent->GetTarget(getter_AddRefs(eventTarget)); + nsCOMPtr doc; + FindDocumentForNode ( eventTarget, getter_AddRefs(doc) ); + if ( doc ) + doc->SetTooltipElement(nsnull); + } + + return NS_OK; + +} // MouseOut + + +// +// FindDocumentForNode +// +// Given a DOM content node, finds the XUL document associated with it +// +nsresult +XULPopupListenerImpl :: FindDocumentForNode ( nsIDOMNode* inElement, nsIDOMXULDocument** outDoc ) +{ + nsresult rv = NS_OK; + + if ( !outDoc || !inElement ) + return NS_ERROR_INVALID_ARG; + + // get the document associated with this content element + nsCOMPtr document; + nsCOMPtr content = do_QueryInterface(inElement); + if (NS_FAILED(rv = content->GetDocument(*getter_AddRefs(document)))) { + NS_ERROR("Unable to retrieve the document."); + return rv; + } + + // Turn the document into a XUL document so we can use getElementById + nsCOMPtr xulDocument = do_QueryInterface(document); + if (xulDocument == nsnull) { + NS_ERROR("Popup attached to an element that isn't in XUL!"); + return NS_ERROR_FAILURE; + } + + *outDoc = xulDocument; + NS_ADDREF ( *outDoc ); + + return rv; + +} // FindDocumentForNode + + +// +// LaunchPopup +// +nsresult +XULPopupListenerImpl::LaunchPopup ( nsIDOMEvent* anEvent ) +{ + // Retrieve our x and y position. + nsCOMPtr uiEvent ( do_QueryInterface(anEvent) ); + if (!uiEvent) { + //non-ui event passed in. bad things. + return NS_OK; + } + + PRInt32 xPos, yPos; + uiEvent->GetScreenX(&xPos); + uiEvent->GetScreenY(&yPos); + + PRInt32 offsetX, offsetY; + uiEvent->GetClientX(&offsetX); + uiEvent->GetClientY(&offsetY); + + return LaunchPopup ( mElement, xPos, yPos, offsetX, offsetY ); +} + + +// +// LaunchPopup +// +// Given the element on which the event was triggered and the mouse locations in +// screen and widget coordinates, popup a new window showing the appropriate +// content. +// +// This looks for an attribute on |aElement| of the appropriate popup type +// (popup, context, tooltip) and uses that attribute's value as an ID for +// the popup content in the document. +// +nsresult +XULPopupListenerImpl::LaunchPopup( nsIDOMElement* aElement, PRInt32 aScreenX, PRInt32 aScreenY, + PRInt32 aOffsetX, PRInt32 aOffsetY ) { nsresult rv = NS_OK; nsAutoString type("popup"); - if (eXULPopupType_context == popupType) + if ( popupType == eXULPopupType_context ) type = "context"; + else if ( popupType == eXULPopupType_tooltip ) + type = "tooltip"; nsAutoString identifier; - element->GetAttribute(type, identifier); + mElement->GetAttribute(type, identifier); if (identifier == "") return rv; - // Try to find the popup content. + // Try to find the popup content and the document. We don't use FindDocumentForNode() + // in this case because we need the nsIDocument interface anyway for the script + // context. nsCOMPtr document; - nsCOMPtr content = do_QueryInterface(element); + nsCOMPtr content = do_QueryInterface(mElement); if (NS_FAILED(rv = content->GetDocument(*getter_AddRefs(document)))) { NS_ERROR("Unable to retrieve the document."); return rv; @@ -219,17 +403,15 @@ XULPopupListenerImpl::LaunchPopup(nsIDOMEvent* anEvent) // XXX Handle the _child case for popups and context menus! - // Use getElementById to obtain the popup content. + // Use getElementById to obtain the popup content and gracefully fail if + // we didn't find any popup content in the document. nsCOMPtr popupContent; if (NS_FAILED(rv = xulDocument->GetElementById(identifier, getter_AddRefs(popupContent)))) { NS_ERROR("GetElementById had some kind of spasm."); return rv; } - - if (popupContent == nsnull) { - // Gracefully fail in this case. + if ( !popupContent ) return NS_OK; - } // We have some popup content. Obtain our window. nsIScriptContextOwner* owner = document->GetScriptContextOwner(); @@ -242,42 +424,30 @@ XULPopupListenerImpl::LaunchPopup(nsIDOMEvent* anEvent) if (domWindow != nsnull) { // Find out if we're anchored. nsAutoString anchorAlignment("none"); - element->GetAttribute("popupanchor", anchorAlignment); + mElement->GetAttribute("popupanchor", anchorAlignment); nsAutoString popupAlignment("topleft"); - element->GetAttribute("popupalign", popupAlignment); + mElement->GetAttribute("popupalign", popupAlignment); - // Set the popup in the document for the duration of this call. - xulDocument->SetPopup(element); + // Set the popup in the document for the duration of this call. + xulDocument->SetPopupElement(mElement); - // Retrieve our x and y position. - nsCOMPtruiEvent; - uiEvent = do_QueryInterface(anEvent); - if (!uiEvent) { - //non-ui event passed in. bad things. - return NS_OK; - } - - PRInt32 xPos, yPos; - uiEvent->GetScreenX(&xPos); - uiEvent->GetScreenY(&yPos); - // If we're anchored, we pass in client/screen offsets so that - // we can translate the frames corners to screen coords. + // we can translate the frames corners to screen coords. + PRInt32 xPos = aScreenX, yPos = aScreenY; if (anchorAlignment != "none") { - PRInt32 offsetX, offsetY; - uiEvent->GetClientX(&offsetX); - uiEvent->GetClientY(&offsetY); - xPos = xPos-offsetX; - yPos = yPos-offsetY; + xPos -= aOffsetX; + yPos -= aOffsetY; } - - domWindow->CreatePopup(element, popupContent, - xPos, yPos, - type, anchorAlignment, popupAlignment); + domWindow->CreatePopup(mElement, popupContent, + xPos, yPos, + type, anchorAlignment, popupAlignment, + getter_AddRefs(mPopup)); + if ( popupType == eXULPopupType_popup && mPopup ) + mPopup->Focus(); // XXX For menus only, clear the document.popup field. - } + } NS_RELEASE(global); } } @@ -290,10 +460,12 @@ nsresult XULPopupListenerImpl::Blur(nsIDOMEvent* aMouseEvent) { nsresult rv = NS_OK; - + +#if 0 +// ONLY NEEDED BECAUSE HYATT WAS LAZY // Try to find the popup content. nsCOMPtr document; - nsCOMPtr content = do_QueryInterface(element); + nsCOMPtr content = do_QueryInterface(mElement); if (NS_FAILED(rv = content->GetDocument(*getter_AddRefs(document)))) { NS_ERROR("Unable to retrieve the document."); return rv; @@ -319,7 +491,20 @@ XULPopupListenerImpl::Blur(nsIDOMEvent* aMouseEvent) domWindow->Close(); } } +#endif + // Blur events don't bubble, so this means our window lost focus. + // Let's check just to make sure. + nsCOMPtr eventTarget; + aMouseEvent->GetTarget(getter_AddRefs(eventTarget)); + + // Close, but only if we are the same target. + nsCOMPtr windowNode = do_QueryInterface(mPopup); + if (windowNode.get() == eventTarget.get()) { + mPopup->Close(); + mPopup = nsnull; + } + // XXX Figure out how to fire the DESTROY event for the // arbitrary XUL case @@ -329,6 +514,40 @@ XULPopupListenerImpl::Blur(nsIDOMEvent* aMouseEvent) return rv; } + +// +// sTooltipCallback +// +// A timer callback, fired when the mouse has hovered inside of a frame for the +// appropriate amount of time. Getting to this point means that we should show the +// toolip. +// +// This relies on certain things being cached into the |aClosure| object passed to +// us by the timer: +// -- the x/y coordinates of the mouse +// -- the dom node the user hovered over +// +void +XULPopupListenerImpl :: sTooltipCallback (nsITimer *aTimer, void *aClosure) +{ + XULPopupListenerImpl* self = NS_STATIC_CAST(XULPopupListenerImpl*, aClosure); + if ( self ) { + // set the node in the document that triggered the tooltip and show it + nsCOMPtr doc; + self->FindDocumentForNode ( self->mPossibleTooltipNode, getter_AddRefs(doc) ); + if ( doc ) { + nsCOMPtr element ( do_QueryInterface(self->mPossibleTooltipNode) ); + if ( element ) { + doc->SetTooltipElement ( element ); + self->LaunchPopup ( element, self->mMouseLocX, self->mMouseLocY, 0, 0 ); + } + } // if document + } // if "self" data valid + +} // sTimerCallback + + + //////////////////////////////////////////////////////////////// nsresult NS_NewXULPopupListener(nsIXULPopupListener** pop) diff --git a/mozilla/webshell/public/nsIWebShell.h b/mozilla/webshell/public/nsIWebShell.h index dd46adf4573..77f9b42bb65 100644 --- a/mozilla/webshell/public/nsIWebShell.h +++ b/mozilla/webshell/public/nsIWebShell.h @@ -111,7 +111,7 @@ public: PRInt32 aXPos, PRInt32 aYPos, const nsString& aPopupType, const nsString& anAnchorAlignment, const nsString& aPopupAlignment, - nsIDOMWindow* aWindow) = 0; + nsIDOMWindow* aWindow, nsIDOMWindow** outPopup) = 0; /** * Notify the WebShellContainer that a contained webshell is diff --git a/mozilla/webshell/src/nsWebShell.cpp b/mozilla/webshell/src/nsWebShell.cpp index 6f90cffc07a..58fde3d4957 100644 --- a/mozilla/webshell/src/nsWebShell.cpp +++ b/mozilla/webshell/src/nsWebShell.cpp @@ -266,7 +266,7 @@ public: PRInt32 aXPos, PRInt32 aYPos, const nsString& aPopupType, const nsString& anAnchorAlignment, const nsString& aPopupAlignment, - nsIDOMWindow* aWindow); + nsIDOMWindow* aWindow, nsIDOMWindow** outPopup); NS_IMETHOD FindWebShellWithName(const PRUnichar* aName, nsIWebShell*& aResult); NS_IMETHOD FocusAvailable(nsIWebShell* aFocusedWebShell, PRBool& aFocusTaken); @@ -2198,12 +2198,12 @@ nsWebShell::CreatePopup(nsIDOMElement* aElement, nsIDOMElement* aPopupContent, PRInt32 aXPos, PRInt32 aYPos, const nsString& aPopupType, const nsString& anAnchorAlignment, const nsString& aPopupAlignment, - nsIDOMWindow* aWindow) + nsIDOMWindow* aWindow, nsIDOMWindow** outPopup) { if (nsnull != mContainer) { return mContainer->CreatePopup(aElement, aPopupContent, aXPos, aYPos, aPopupType, anAnchorAlignment, aPopupAlignment, - aWindow); + aWindow, outPopup); } return NS_OK; } diff --git a/mozilla/webshell/tests/viewer/nsBrowserWindow.cpp b/mozilla/webshell/tests/viewer/nsBrowserWindow.cpp index d04588356f6..971e8f56b49 100644 --- a/mozilla/webshell/tests/viewer/nsBrowserWindow.cpp +++ b/mozilla/webshell/tests/viewer/nsBrowserWindow.cpp @@ -1807,7 +1807,7 @@ nsBrowserWindow::CreatePopup(nsIDOMElement* aElement, nsIDOMElement* aPopupConte PRInt32 aXPos, PRInt32 aYPos, const nsString& aPopupType, const nsString& anAnchorAlignment, const nsString& aPopupAlignment, - nsIDOMWindow* aWindow) + nsIDOMWindow* aWindow, nsIDOMWindow** outPopup) { return NS_OK; } diff --git a/mozilla/webshell/tests/viewer/nsBrowserWindow.h b/mozilla/webshell/tests/viewer/nsBrowserWindow.h index bb9d8cf2a4c..0e9fe2aad86 100644 --- a/mozilla/webshell/tests/viewer/nsBrowserWindow.h +++ b/mozilla/webshell/tests/viewer/nsBrowserWindow.h @@ -137,7 +137,7 @@ public: PRInt32 aXPos, PRInt32 aYPos, const nsString& aPopupType, const nsString& anAnchorAlignment, const nsString& aPopupAlignment, - nsIDOMWindow* aWindow); + nsIDOMWindow* aWindow, nsIDOMWindow** outPopup); NS_IMETHOD FindWebShellWithName(const PRUnichar* aName, nsIWebShell*& aResult); NS_IMETHOD FocusAvailable(nsIWebShell* aFocusedWebShell, PRBool& aFocusTaken); diff --git a/mozilla/webshell/tests/viewer/nsXPBaseWindow.cpp b/mozilla/webshell/tests/viewer/nsXPBaseWindow.cpp index bb88f2dca5b..4976e080081 100644 --- a/mozilla/webshell/tests/viewer/nsXPBaseWindow.cpp +++ b/mozilla/webshell/tests/viewer/nsXPBaseWindow.cpp @@ -575,7 +575,7 @@ nsXPBaseWindow::CreatePopup(nsIDOMElement* aElement, nsIDOMElement* aPopupConten PRInt32 aXPos, PRInt32 aYPos, const nsString& aPopupType, const nsString& anAnchorAlignment, const nsString& aPopupAlignment, - nsIDOMWindow* aWindow) + nsIDOMWindow* aWindow, nsIDOMWindow** outPopup) { return NS_OK; } diff --git a/mozilla/webshell/tests/viewer/nsXPBaseWindow.h b/mozilla/webshell/tests/viewer/nsXPBaseWindow.h index d0630b4cab6..da09fb73d83 100644 --- a/mozilla/webshell/tests/viewer/nsXPBaseWindow.h +++ b/mozilla/webshell/tests/viewer/nsXPBaseWindow.h @@ -118,7 +118,7 @@ public: PRInt32 aXPos, PRInt32 aYPos, const nsString& aPopupType, const nsString& anAnchorAlignment, const nsString& aPopupAlignment, - nsIDOMWindow* aWindow); + nsIDOMWindow* aWindow, nsIDOMWindow** outPopup); NS_IMETHOD FindWebShellWithName(const PRUnichar* aName, nsIWebShell*& aResult); NS_IMETHOD FocusAvailable(nsIWebShell* aFocusedWebShell, PRBool& aFocusTaken); diff --git a/mozilla/xpfe/appshell/src/nsWebShellWindow.cpp b/mozilla/xpfe/appshell/src/nsWebShellWindow.cpp index fb6ff3106fd..3f4d55f2c37 100644 --- a/mozilla/xpfe/appshell/src/nsWebShellWindow.cpp +++ b/mozilla/xpfe/appshell/src/nsWebShellWindow.cpp @@ -1004,9 +1004,17 @@ nsWebShellWindow::CreatePopup(nsIDOMElement* aElement, nsIDOMElement* aPopupCont PRInt32 aXPos, PRInt32 aYPos, const nsString& aPopupType, const nsString& anAnchorAlignment, const nsString& aPopupAlignment, - nsIDOMWindow* aWindow) + nsIDOMWindow* aWindow, nsIDOMWindow** outPopup) { nsresult rv = NS_OK; + + // clear out result param up front. It's an error if a legal place to + // stick the result isn't provided. + if ( !outPopup ) { + NS_ERROR ( "Invalid param -- need to provide a place for result" ); + return NS_ERROR_INVALID_ARG; + } + *outPopup = nsnull; nsCOMPtr contentViewerContainer; contentViewerContainer = do_QueryInterface(mWebShell); @@ -1082,6 +1090,8 @@ nsWebShellWindow::CreatePopup(nsIDOMElement* aElement, nsIDOMElement* aPopupCont } nsCOMPtr popupContent = do_QueryInterface(aPopupContent); + if ( !popupContent ) + return NS_OK; // It's ok. Really. // Fire the CONSTRUCT DOM event to give JS/C++ a chance to build the popup // dynamically. @@ -1090,7 +1100,7 @@ nsWebShellWindow::CreatePopup(nsIDOMElement* aElement, nsIDOMElement* aPopupCont event.eventStructType = NS_EVENT; event.message = NS_POPUP_CONSTRUCT; rv = popupContent->HandleDOMEvent(*presContext, &event, nsnull, NS_EVENT_FLAG_INIT, status); - if (rv != NS_OK) + if ( NS_FAILED(rv) ) return rv; // Find out if we're a menu. @@ -1103,10 +1113,9 @@ nsWebShellWindow::CreatePopup(nsIDOMElement* aElement, nsIDOMElement* aPopupCont if (NS_FAILED(popupContent->ChildAt(0, *getter_AddRefs(rootContent)))) return NS_OK; // Doesn't matter. Don't report it. - nsCOMPtr rootElement = do_QueryInterface(rootContent); - nsString tagName; - if (NS_FAILED(rootElement->GetTagName(tagName))) + nsCOMPtr rootElement = do_QueryInterface(rootContent); + if ( !rootElement || NS_FAILED(rootElement->GetTagName(tagName))) return NS_OK; // It's ok. Really. if (tagName == "menu") { @@ -1223,16 +1232,18 @@ nsWebShellWindow::CreatePopup(nsIDOMElement* aElement, nsIDOMElement* aPopupCont // (8) Set up the opener property domWindow->SetOpener(aWindow); - // (9) Show the window, and give the window the focus. + // (9) Show the window. Don't give the focus yet because we may not want to. + // For example, popup windows want focus, but tooltips do not. newWindow->Show(PR_TRUE); - domWindow->Focus(); // (10) Do some layout. nsCOMPtr popupChild = do_QueryInterface(popupDocument); popupChild->LayoutPopupDocument(); - // XXX Do we return the popup document? Might want to, since it's kind of like - // a sick and twisted distortion of a window.open call. + // return the popup. + *outPopup = domWindow; + NS_ADDREF(*outPopup); + return rv; } diff --git a/mozilla/xpfe/appshell/src/nsWebShellWindow.h b/mozilla/xpfe/appshell/src/nsWebShellWindow.h index 6e88bda4765..15c50c6640d 100644 --- a/mozilla/xpfe/appshell/src/nsWebShellWindow.h +++ b/mozilla/xpfe/appshell/src/nsWebShellWindow.h @@ -88,7 +88,7 @@ public: PRInt32 aXPos, PRInt32 aYPos, const nsString& aPopupType, const nsString& anAnchorAlignment, const nsString& aPopupAlignment, - nsIDOMWindow* aWindow); + nsIDOMWindow* aWindow, nsIDOMWindow** outPopup); NS_IMETHOD ContentShellAdded(nsIWebShell* aChildShell, nsIContent* frameNode);