Popup work.

This commit is contained in:
hyatt@netscape.com
1999-09-10 08:49:32 +00:00
parent c3c68995fb
commit 1933199861
5 changed files with 152 additions and 287 deletions

View File

@@ -2307,7 +2307,12 @@ RDFElementImpl::SetAttribute(PRInt32 aNameSpaceID,
// Add the popup as a listener on this element. // Add the popup as a listener on this element.
nsCOMPtr<nsIDOMEventListener> eventListener = do_QueryInterface(popupListener); nsCOMPtr<nsIDOMEventListener> eventListener = do_QueryInterface(popupListener);
AddEventListener("mousedown", eventListener, PR_FALSE);
if (popupType == eXULPopupType_tooltip) {
AddEventListener("mouseout", eventListener, PR_FALSE);
AddEventListener("mousemove", eventListener, PR_FALSE);
}
else AddEventListener("mousedown", eventListener, PR_FALSE);
NS_IF_RELEASE(popupListener); NS_IF_RELEASE(popupListener);
} }

View File

@@ -25,7 +25,7 @@
#include "nsIDOMElement.h" #include "nsIDOMElement.h"
#include "nsIXULPopupListener.h" #include "nsIXULPopupListener.h"
#include "nsIDOMMouseListener.h" #include "nsIDOMMouseListener.h"
#include "nsIDOMFocusListener.h" #include "nsIDOMMouseMotionListener.h"
#include "nsRDFCID.h" #include "nsRDFCID.h"
#include "nsIScriptGlobalObject.h" #include "nsIScriptGlobalObject.h"
@@ -55,7 +55,7 @@ static NS_DEFINE_IID(kIDomEventListenerIID, NS_IDOMEVENTLISTENER_IID);
// //
class XULPopupListenerImpl : public nsIXULPopupListener, class XULPopupListenerImpl : public nsIXULPopupListener,
public nsIDOMMouseListener, public nsIDOMMouseListener,
public nsIDOMFocusListener public nsIDOMMouseMotionListener
{ {
public: public:
XULPopupListenerImpl(void); XULPopupListenerImpl(void);
@@ -73,12 +73,12 @@ public:
virtual nsresult MouseUp(nsIDOMEvent* aMouseEvent) { return NS_OK; }; virtual nsresult MouseUp(nsIDOMEvent* aMouseEvent) { return NS_OK; };
virtual nsresult MouseClick(nsIDOMEvent* aMouseEvent) { return NS_OK; }; virtual nsresult MouseClick(nsIDOMEvent* aMouseEvent) { return NS_OK; };
virtual nsresult MouseDblClick(nsIDOMEvent* aMouseEvent) { return NS_OK; }; virtual nsresult MouseDblClick(nsIDOMEvent* aMouseEvent) { return NS_OK; };
virtual nsresult MouseOver(nsIDOMEvent* aMouseEvent) ; virtual nsresult MouseOver(nsIDOMEvent* aMouseEvent) { return NS_OK; };
virtual nsresult MouseOut(nsIDOMEvent* aMouseEvent) ; virtual nsresult MouseOut(nsIDOMEvent* aMouseEvent) ;
// nsIDOMFocusListener // nsIDOMMouseMotionListener
virtual nsresult Focus(nsIDOMEvent* aEvent) { return NS_OK; }; virtual nsresult MouseMove(nsIDOMEvent* aMouseEvent);
virtual nsresult Blur(nsIDOMEvent* aEvent); virtual nsresult DragMove(nsIDOMEvent* aMouseEvent) { return NS_OK; };
// nsIDOMEventListener // nsIDOMEventListener
virtual nsresult HandleEvent(nsIDOMEvent* anEvent) { return NS_OK; }; virtual nsresult HandleEvent(nsIDOMEvent* anEvent) { return NS_OK; };
@@ -86,26 +86,29 @@ public:
protected: protected:
virtual nsresult LaunchPopup(nsIDOMEvent* anEvent); virtual nsresult LaunchPopup(nsIDOMEvent* anEvent);
virtual nsresult LaunchPopup( nsIDOMElement* aElement, PRInt32 aScreenX, PRInt32 aScreenY, virtual nsresult LaunchPopup(nsIDOMElement* aElement, PRInt32 aClientX, PRInt32 aClientY) ;
PRInt32 aClientX, PRInt32 aClientY ) ;
nsresult FindDocumentForNode ( nsIDOMNode* inNode, nsIDOMXULDocument** outDoc ) ; nsresult FindDocumentForNode(nsIDOMNode* inNode, nsIDOMXULDocument** outDoc) ;
private: private:
// |mElement| is the node to which this listener is attached. // |mElement| is the node to which this listener is attached.
nsIDOMElement* mElement; // Weak ref. The element will go away first. nsIDOMElement* mElement; // Weak ref. The element will go away first.
// The popup that is getting shown on top of mElement.
nsIDOMElement* mPopupContent;
// The type of the popup
XULPopupType popupType; XULPopupType popupType;
nsCOMPtr<nsIDOMWindow> mPopup; // The popup. We are responsible for making it go away.
// The following members are not used unless |popupType| is tooltip. // The following members are not used unless |popupType| is tooltip.
// a timer for determining if a tooltip should be displayed. // a timer for determining if a tooltip should be displayed.
static void sTooltipCallback ( nsITimer *aTimer, void *aClosure ) ; static void sTooltipCallback ( nsITimer *aTimer, void *aClosure ) ;
nsCOMPtr<nsITimer> mTooltipTimer; nsCOMPtr<nsITimer> mTooltipTimer;
PRInt32 mMouseScreenX, mMouseScreenY; // mouse coordinates for tooltip event PRInt32 mMouseClientX, mMouseClientY; // mouse coordinates for tooltip event
PRInt32 mMouseClientX, mMouseClientY;
// The node hovered over that fired the timer. This may turn into the node that // 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. // triggered the tooltip, but only if the timer ever gets around to firing.
nsIDOMNode* mPossibleTooltipNode; // weak ref. nsIDOMNode* mPossibleTooltipNode; // weak ref.
}; };
@@ -113,8 +116,8 @@ private:
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
XULPopupListenerImpl::XULPopupListenerImpl(void) XULPopupListenerImpl::XULPopupListenerImpl(void)
: mElement(nsnull), mPossibleTooltipNode(nsnull), mMouseScreenX(0), : mElement(nsnull), mPopupContent(nsnull), mPossibleTooltipNode(nsnull), mMouseClientX(0),
mMouseScreenY(0), mMouseClientX(0), mMouseClientY(0) mMouseClientY(0)
{ {
NS_INIT_REFCNT(); NS_INIT_REFCNT();
@@ -124,9 +127,6 @@ XULPopupListenerImpl::~XULPopupListenerImpl(void)
{ {
//XXX do we need to close the popup here? Will we get the right events as //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? //XXX the topLevel window is going away when the closebox is pressed?
if ( mPopup )
mPopup->Close();
} }
NS_IMPL_ADDREF(XULPopupListenerImpl) NS_IMPL_ADDREF(XULPopupListenerImpl)
@@ -150,8 +150,8 @@ XULPopupListenerImpl::QueryInterface(REFNSIID iid, void** result)
NS_ADDREF_THIS(); NS_ADDREF_THIS();
return NS_OK; return NS_OK;
} }
else if (iid.Equals(nsIDOMFocusListener::GetIID())) { else if (iid.Equals(nsIDOMMouseMotionListener::GetIID())) {
*result = NS_STATIC_CAST(nsIDOMFocusListener*, this); *result = NS_STATIC_CAST(nsIDOMMouseMotionListener*, this);
NS_ADDREF_THIS(); NS_ADDREF_THIS();
return NS_OK; return NS_OK;
} }
@@ -201,9 +201,9 @@ XULPopupListenerImpl::MouseDown(nsIDOMEvent* aMouseEvent)
case eXULPopupType_context: case eXULPopupType_context:
#ifdef XP_MAC #ifdef XP_MAC
// XXX: Handle Mac (currently checks if CTRL key is down) // XXX: Handle Mac (currently checks if CTRL key is down)
PRBool ctrlKey = PR_FALSE; PRBool ctrlKey = PR_FALSE;
uiEvent->GetCtrlKey(&ctrlKey); uiEvent->GetCtrlKey(&ctrlKey);
if (ctrlKey == PR_TRUE) if (ctrlKey == PR_TRUE)
#else #else
// Check for right mouse button down // Check for right mouse button down
uiEvent->GetButton(&button); uiEvent->GetButton(&button);
@@ -226,55 +226,50 @@ XULPopupListenerImpl::MouseDown(nsIDOMEvent* aMouseEvent)
// //
// MouseOver // MouseMove
// //
// If we're a tooltip, fire off a timer to see if a tooltip should be shown. // If we're a tooltip, fire off a timer to see if a tooltip should be shown.
// //
nsresult nsresult
XULPopupListenerImpl::MouseOver(nsIDOMEvent* aMouseEvent) XULPopupListenerImpl::MouseMove(nsIDOMEvent* aMouseEvent)
{ {
nsresult rv = NS_OK; nsresult rv = NS_OK;
// make sure we're a tooltip. if not, bail. // make sure we're a tooltip. if not, bail.
if ( popupType != eXULPopupType_tooltip ) if ( popupType != eXULPopupType_tooltip )
return NS_OK; return NS_OK;
nsCOMPtr<nsIDOMUIEvent> uiEvent ( do_QueryInterface(aMouseEvent) );
if (!uiEvent)
return NS_OK;
// 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).
uiEvent->GetClientX(&mMouseClientX);
uiEvent->GetClientY(&mMouseClientY);
//XXX recognize when a popup is already up and immediately show the //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 tooltip for the new item if the dom element is different than
//XXX the element for which we are currently displaying the tip. //XXX the element for which we are currently displaying the tip.
//XXX //XXX
//XXX for now, just be stupid to get things working. //XXX for now, just be stupid to get things working.
if ( mPopup ) if (mPopupContent || mTooltipTimer)
return NS_OK; return NS_OK;
// Kill off an old timer and create a new one.
if ( mTooltipTimer ) {
mTooltipTimer->Cancel();
mTooltipTimer = nsnull;
}
NS_NewTimer ( getter_AddRefs(mTooltipTimer) ); NS_NewTimer ( getter_AddRefs(mTooltipTimer) );
if ( mTooltipTimer ) { if ( mTooltipTimer ) {
nsCOMPtr<nsIDOMUIEvent> uiEvent ( do_QueryInterface(aMouseEvent) ); nsCOMPtr<nsIDOMNode> eventTarget;
if ( uiEvent ) { aMouseEvent->GetTarget(getter_AddRefs(eventTarget));
// stash the coordinates of the event so that we can still get back to it from within the mPossibleTooltipNode = eventTarget.get();
// timer scallback. Also stash the node that started this so we can put it into the mTooltipTimer->Init(sTooltipCallback, this, 500); // 500 ms delay
// document later on (if the timer ever fires).
nsCOMPtr<nsIDOMNode> eventTarget;
aMouseEvent->GetTarget(getter_AddRefs(eventTarget));
mPossibleTooltipNode = eventTarget.get();
uiEvent->GetScreenX(&mMouseScreenX);
uiEvent->GetScreenY(&mMouseScreenY);
uiEvent->GetClientX(&mMouseClientX);
uiEvent->GetClientY(&mMouseClientY);
mTooltipTimer->Init(sTooltipCallback, this, 1000); // one second delay
}
} }
else else
NS_WARNING ( "Could not create a timer for tooltip tracking" ); NS_WARNING ( "Could not create a timer for tooltip tracking" );
return NS_OK; return NS_OK;
} // MouseOver } // MouseMove
// //
@@ -290,12 +285,16 @@ XULPopupListenerImpl::MouseOut(nsIDOMEvent* aMouseEvent)
if ( popupType != eXULPopupType_tooltip ) if ( popupType != eXULPopupType_tooltip )
return NS_OK; return NS_OK;
if ( mTooltipTimer ) if ( mTooltipTimer ) {
mTooltipTimer->Cancel(); mTooltipTimer->Cancel();
mTooltipTimer = nsnull;
}
if ( mPopup ) { if ( mPopupContent ) {
mPopup->Close(); // hide the popup mPopupContent->RemoveAttribute("menugenerated"); // hide the popup
mPopup = nsnull; // release the popup mPopupContent->RemoveAttribute("menuactive");
mPopupContent = nsnull; // release the popup
// clear out the tooltip node on the document // clear out the tooltip node on the document
nsCOMPtr<nsIDOMNode> eventTarget; nsCOMPtr<nsIDOMNode> eventTarget;
@@ -327,6 +326,9 @@ XULPopupListenerImpl :: FindDocumentForNode ( nsIDOMNode* inElement, nsIDOMXULDo
// get the document associated with this content element // get the document associated with this content element
nsCOMPtr<nsIDocument> document; nsCOMPtr<nsIDocument> document;
nsCOMPtr<nsIContent> content = do_QueryInterface(inElement); nsCOMPtr<nsIContent> content = do_QueryInterface(inElement);
if (!content)
return rv;
if (NS_FAILED(rv = content->GetDocument(*getter_AddRefs(document)))) { if (NS_FAILED(rv = content->GetDocument(*getter_AddRefs(document)))) {
NS_ERROR("Unable to retrieve the document."); NS_ERROR("Unable to retrieve the document.");
return rv; return rv;
@@ -361,14 +363,10 @@ XULPopupListenerImpl::LaunchPopup ( nsIDOMEvent* anEvent )
} }
PRInt32 xPos, yPos; PRInt32 xPos, yPos;
uiEvent->GetScreenX(&xPos); uiEvent->GetClientX(&xPos);
uiEvent->GetScreenY(&yPos); uiEvent->GetClientY(&yPos);
PRInt32 offsetX, offsetY; return LaunchPopup(mElement, xPos, yPos);
uiEvent->GetClientX(&offsetX);
uiEvent->GetClientY(&offsetY);
return LaunchPopup ( mElement, xPos, yPos, offsetX, offsetY );
} }
@@ -376,7 +374,7 @@ XULPopupListenerImpl::LaunchPopup ( nsIDOMEvent* anEvent )
// LaunchPopup // LaunchPopup
// //
// Given the element on which the event was triggered and the mouse locations in // 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 // Client and widget coordinates, popup a new window showing the appropriate
// content. // content.
// //
// This looks for an attribute on |aElement| of the appropriate popup type // This looks for an attribute on |aElement| of the appropriate popup type
@@ -384,14 +382,8 @@ XULPopupListenerImpl::LaunchPopup ( nsIDOMEvent* anEvent )
// the popup content in the document. // the popup content in the document.
// //
nsresult nsresult
XULPopupListenerImpl::LaunchPopup( nsIDOMElement* aElement, PRInt32 aScreenX, PRInt32 aScreenY, XULPopupListenerImpl::LaunchPopup(nsIDOMElement* aElement, PRInt32 aClientX, PRInt32 aClientY)
PRInt32 aOffsetX, PRInt32 aOffsetY )
{ {
#ifdef NS_DEBUG
printf("screen coords %ld %ld\n", aScreenX, aScreenY);
printf("client coords %ld %ld\n", aOffsetX, aOffsetY);
#endif
nsresult rv = NS_OK; nsresult rv = NS_OK;
nsAutoString type("popup"); nsAutoString type("popup");
@@ -454,22 +446,15 @@ printf("client coords %ld %ld\n", aOffsetX, aOffsetY);
// Set the popup in the document for the duration of this call. // Set the popup in the document for the duration of this call.
xulDocument->SetPopupElement(mElement); xulDocument->SetPopupElement(mElement);
// If we're anchored, we pass in client/screen offsets so that PRInt32 xPos = aClientX, yPos = aClientY;
// we can translate the frames corners to screen coords.
PRInt32 xPos = aScreenX, yPos = aScreenY; mPopupContent = popupContent.get();
if (anchorAlignment != "none") {
xPos -= aOffsetX; nsCOMPtr<nsIDOMWindow> uselessPopup; // XXX Should go away.
yPos -= aOffsetY;
}
printf("***creating XUL popup at %ld %ld\n", xPos, yPos);
domWindow->CreatePopup(mElement, popupContent, domWindow->CreatePopup(mElement, popupContent,
xPos, yPos, xPos, yPos,
type, anchorAlignment, popupAlignment, type, anchorAlignment, popupAlignment,
getter_AddRefs(mPopup)); getter_AddRefs(uselessPopup));
if ( popupType == eXULPopupType_popup && mPopup )
mPopup->Focus();
// XXX For menus only, clear the document.popup field.
} }
NS_RELEASE(global); NS_RELEASE(global);
} }
@@ -479,65 +464,6 @@ printf("***creating XUL popup at %ld %ld\n", xPos, yPos);
return NS_OK; return NS_OK;
} }
nsresult
XULPopupListenerImpl::Blur(nsIDOMEvent* aMouseEvent)
{
nsresult rv = NS_OK;
#if 0
// ONLY NEEDED BECAUSE HYATT WAS LAZY
// Try to find the popup content.
nsCOMPtr<nsIDocument> document;
nsCOMPtr<nsIContent> content = do_QueryInterface(mElement);
if (NS_FAILED(rv = content->GetDocument(*getter_AddRefs(document)))) {
NS_ERROR("Unable to retrieve the document.");
return rv;
}
// Blur events don't bubble, so this means our window lost focus.
// Let's check just to make sure.
nsCOMPtr<nsIDOMNode> eventTarget;
aMouseEvent->GetTarget(getter_AddRefs(eventTarget));
// We have some popup content. Obtain our window.
nsIScriptContextOwner* owner = document->GetScriptContextOwner();
nsCOMPtr<nsIScriptContext> context;
if (NS_OK == owner->GetScriptContext(getter_AddRefs(context))) {
nsIScriptGlobalObject* global = context->GetGlobalObject();
if (global) {
// Get the DOM window
nsCOMPtr<nsIDOMWindow> domWindow = do_QueryInterface(global);
// Close, but only if we are the same target.
nsCOMPtr<nsIDOMNode> windowNode = do_QueryInterface(domWindow);
if (windowNode.get() == eventTarget.get())
domWindow->Close();
}
}
#endif
// Blur events don't bubble, so this means our window lost focus.
// Let's check just to make sure.
nsCOMPtr<nsIDOMNode> eventTarget;
aMouseEvent->GetTarget(getter_AddRefs(eventTarget));
// Close, but only if we are the same target.
nsCOMPtr<nsIDOMNode> 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
// XXX Set document.popup to null in the parent document NOW.
// xulDocument->SetPopup(nsnull);
return rv;
}
// //
// sTooltipCallback // sTooltipCallback
// //
@@ -566,8 +492,7 @@ XULPopupListenerImpl :: sTooltipCallback (nsITimer *aTimer, void *aClosure)
element->GetAttribute ( "disabled", disabledState ); element->GetAttribute ( "disabled", disabledState );
if ( disabledState != "true" ) { if ( disabledState != "true" ) {
doc->SetTooltipElement ( element ); doc->SetTooltipElement ( element );
self->LaunchPopup ( element, self->mMouseScreenX, self->mMouseScreenY, self->LaunchPopup (element, self->mMouseClientX, self->mMouseClientY+16);
self->mMouseClientX, self->mMouseClientY );
} // if node enabled } // if node enabled
} }
} // if document } // if document

View File

@@ -2307,7 +2307,12 @@ RDFElementImpl::SetAttribute(PRInt32 aNameSpaceID,
// Add the popup as a listener on this element. // Add the popup as a listener on this element.
nsCOMPtr<nsIDOMEventListener> eventListener = do_QueryInterface(popupListener); nsCOMPtr<nsIDOMEventListener> eventListener = do_QueryInterface(popupListener);
AddEventListener("mousedown", eventListener, PR_FALSE);
if (popupType == eXULPopupType_tooltip) {
AddEventListener("mouseout", eventListener, PR_FALSE);
AddEventListener("mousemove", eventListener, PR_FALSE);
}
else AddEventListener("mousedown", eventListener, PR_FALSE);
NS_IF_RELEASE(popupListener); NS_IF_RELEASE(popupListener);
} }

View File

@@ -2307,7 +2307,12 @@ RDFElementImpl::SetAttribute(PRInt32 aNameSpaceID,
// Add the popup as a listener on this element. // Add the popup as a listener on this element.
nsCOMPtr<nsIDOMEventListener> eventListener = do_QueryInterface(popupListener); nsCOMPtr<nsIDOMEventListener> eventListener = do_QueryInterface(popupListener);
AddEventListener("mousedown", eventListener, PR_FALSE);
if (popupType == eXULPopupType_tooltip) {
AddEventListener("mouseout", eventListener, PR_FALSE);
AddEventListener("mousemove", eventListener, PR_FALSE);
}
else AddEventListener("mousedown", eventListener, PR_FALSE);
NS_IF_RELEASE(popupListener); NS_IF_RELEASE(popupListener);
} }

View File

@@ -25,7 +25,7 @@
#include "nsIDOMElement.h" #include "nsIDOMElement.h"
#include "nsIXULPopupListener.h" #include "nsIXULPopupListener.h"
#include "nsIDOMMouseListener.h" #include "nsIDOMMouseListener.h"
#include "nsIDOMFocusListener.h" #include "nsIDOMMouseMotionListener.h"
#include "nsRDFCID.h" #include "nsRDFCID.h"
#include "nsIScriptGlobalObject.h" #include "nsIScriptGlobalObject.h"
@@ -55,7 +55,7 @@ static NS_DEFINE_IID(kIDomEventListenerIID, NS_IDOMEVENTLISTENER_IID);
// //
class XULPopupListenerImpl : public nsIXULPopupListener, class XULPopupListenerImpl : public nsIXULPopupListener,
public nsIDOMMouseListener, public nsIDOMMouseListener,
public nsIDOMFocusListener public nsIDOMMouseMotionListener
{ {
public: public:
XULPopupListenerImpl(void); XULPopupListenerImpl(void);
@@ -73,12 +73,12 @@ public:
virtual nsresult MouseUp(nsIDOMEvent* aMouseEvent) { return NS_OK; }; virtual nsresult MouseUp(nsIDOMEvent* aMouseEvent) { return NS_OK; };
virtual nsresult MouseClick(nsIDOMEvent* aMouseEvent) { return NS_OK; }; virtual nsresult MouseClick(nsIDOMEvent* aMouseEvent) { return NS_OK; };
virtual nsresult MouseDblClick(nsIDOMEvent* aMouseEvent) { return NS_OK; }; virtual nsresult MouseDblClick(nsIDOMEvent* aMouseEvent) { return NS_OK; };
virtual nsresult MouseOver(nsIDOMEvent* aMouseEvent) ; virtual nsresult MouseOver(nsIDOMEvent* aMouseEvent) { return NS_OK; };
virtual nsresult MouseOut(nsIDOMEvent* aMouseEvent) ; virtual nsresult MouseOut(nsIDOMEvent* aMouseEvent) ;
// nsIDOMFocusListener // nsIDOMMouseMotionListener
virtual nsresult Focus(nsIDOMEvent* aEvent) { return NS_OK; }; virtual nsresult MouseMove(nsIDOMEvent* aMouseEvent);
virtual nsresult Blur(nsIDOMEvent* aEvent); virtual nsresult DragMove(nsIDOMEvent* aMouseEvent) { return NS_OK; };
// nsIDOMEventListener // nsIDOMEventListener
virtual nsresult HandleEvent(nsIDOMEvent* anEvent) { return NS_OK; }; virtual nsresult HandleEvent(nsIDOMEvent* anEvent) { return NS_OK; };
@@ -86,26 +86,29 @@ public:
protected: protected:
virtual nsresult LaunchPopup(nsIDOMEvent* anEvent); virtual nsresult LaunchPopup(nsIDOMEvent* anEvent);
virtual nsresult LaunchPopup( nsIDOMElement* aElement, PRInt32 aScreenX, PRInt32 aScreenY, virtual nsresult LaunchPopup(nsIDOMElement* aElement, PRInt32 aClientX, PRInt32 aClientY) ;
PRInt32 aClientX, PRInt32 aClientY ) ;
nsresult FindDocumentForNode ( nsIDOMNode* inNode, nsIDOMXULDocument** outDoc ) ; nsresult FindDocumentForNode(nsIDOMNode* inNode, nsIDOMXULDocument** outDoc) ;
private: private:
// |mElement| is the node to which this listener is attached. // |mElement| is the node to which this listener is attached.
nsIDOMElement* mElement; // Weak ref. The element will go away first. nsIDOMElement* mElement; // Weak ref. The element will go away first.
// The popup that is getting shown on top of mElement.
nsIDOMElement* mPopupContent;
// The type of the popup
XULPopupType popupType; XULPopupType popupType;
nsCOMPtr<nsIDOMWindow> mPopup; // The popup. We are responsible for making it go away.
// The following members are not used unless |popupType| is tooltip. // The following members are not used unless |popupType| is tooltip.
// a timer for determining if a tooltip should be displayed. // a timer for determining if a tooltip should be displayed.
static void sTooltipCallback ( nsITimer *aTimer, void *aClosure ) ; static void sTooltipCallback ( nsITimer *aTimer, void *aClosure ) ;
nsCOMPtr<nsITimer> mTooltipTimer; nsCOMPtr<nsITimer> mTooltipTimer;
PRInt32 mMouseScreenX, mMouseScreenY; // mouse coordinates for tooltip event PRInt32 mMouseClientX, mMouseClientY; // mouse coordinates for tooltip event
PRInt32 mMouseClientX, mMouseClientY;
// The node hovered over that fired the timer. This may turn into the node that // 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. // triggered the tooltip, but only if the timer ever gets around to firing.
nsIDOMNode* mPossibleTooltipNode; // weak ref. nsIDOMNode* mPossibleTooltipNode; // weak ref.
}; };
@@ -113,8 +116,8 @@ private:
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
XULPopupListenerImpl::XULPopupListenerImpl(void) XULPopupListenerImpl::XULPopupListenerImpl(void)
: mElement(nsnull), mPossibleTooltipNode(nsnull), mMouseScreenX(0), : mElement(nsnull), mPopupContent(nsnull), mPossibleTooltipNode(nsnull), mMouseClientX(0),
mMouseScreenY(0), mMouseClientX(0), mMouseClientY(0) mMouseClientY(0)
{ {
NS_INIT_REFCNT(); NS_INIT_REFCNT();
@@ -124,9 +127,6 @@ XULPopupListenerImpl::~XULPopupListenerImpl(void)
{ {
//XXX do we need to close the popup here? Will we get the right events as //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? //XXX the topLevel window is going away when the closebox is pressed?
if ( mPopup )
mPopup->Close();
} }
NS_IMPL_ADDREF(XULPopupListenerImpl) NS_IMPL_ADDREF(XULPopupListenerImpl)
@@ -150,8 +150,8 @@ XULPopupListenerImpl::QueryInterface(REFNSIID iid, void** result)
NS_ADDREF_THIS(); NS_ADDREF_THIS();
return NS_OK; return NS_OK;
} }
else if (iid.Equals(nsIDOMFocusListener::GetIID())) { else if (iid.Equals(nsIDOMMouseMotionListener::GetIID())) {
*result = NS_STATIC_CAST(nsIDOMFocusListener*, this); *result = NS_STATIC_CAST(nsIDOMMouseMotionListener*, this);
NS_ADDREF_THIS(); NS_ADDREF_THIS();
return NS_OK; return NS_OK;
} }
@@ -201,9 +201,9 @@ XULPopupListenerImpl::MouseDown(nsIDOMEvent* aMouseEvent)
case eXULPopupType_context: case eXULPopupType_context:
#ifdef XP_MAC #ifdef XP_MAC
// XXX: Handle Mac (currently checks if CTRL key is down) // XXX: Handle Mac (currently checks if CTRL key is down)
PRBool ctrlKey = PR_FALSE; PRBool ctrlKey = PR_FALSE;
uiEvent->GetCtrlKey(&ctrlKey); uiEvent->GetCtrlKey(&ctrlKey);
if (ctrlKey == PR_TRUE) if (ctrlKey == PR_TRUE)
#else #else
// Check for right mouse button down // Check for right mouse button down
uiEvent->GetButton(&button); uiEvent->GetButton(&button);
@@ -226,55 +226,50 @@ XULPopupListenerImpl::MouseDown(nsIDOMEvent* aMouseEvent)
// //
// MouseOver // MouseMove
// //
// If we're a tooltip, fire off a timer to see if a tooltip should be shown. // If we're a tooltip, fire off a timer to see if a tooltip should be shown.
// //
nsresult nsresult
XULPopupListenerImpl::MouseOver(nsIDOMEvent* aMouseEvent) XULPopupListenerImpl::MouseMove(nsIDOMEvent* aMouseEvent)
{ {
nsresult rv = NS_OK; nsresult rv = NS_OK;
// make sure we're a tooltip. if not, bail. // make sure we're a tooltip. if not, bail.
if ( popupType != eXULPopupType_tooltip ) if ( popupType != eXULPopupType_tooltip )
return NS_OK; return NS_OK;
nsCOMPtr<nsIDOMUIEvent> uiEvent ( do_QueryInterface(aMouseEvent) );
if (!uiEvent)
return NS_OK;
// 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).
uiEvent->GetClientX(&mMouseClientX);
uiEvent->GetClientY(&mMouseClientY);
//XXX recognize when a popup is already up and immediately show the //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 tooltip for the new item if the dom element is different than
//XXX the element for which we are currently displaying the tip. //XXX the element for which we are currently displaying the tip.
//XXX //XXX
//XXX for now, just be stupid to get things working. //XXX for now, just be stupid to get things working.
if ( mPopup ) if (mPopupContent || mTooltipTimer)
return NS_OK; return NS_OK;
// Kill off an old timer and create a new one.
if ( mTooltipTimer ) {
mTooltipTimer->Cancel();
mTooltipTimer = nsnull;
}
NS_NewTimer ( getter_AddRefs(mTooltipTimer) ); NS_NewTimer ( getter_AddRefs(mTooltipTimer) );
if ( mTooltipTimer ) { if ( mTooltipTimer ) {
nsCOMPtr<nsIDOMUIEvent> uiEvent ( do_QueryInterface(aMouseEvent) ); nsCOMPtr<nsIDOMNode> eventTarget;
if ( uiEvent ) { aMouseEvent->GetTarget(getter_AddRefs(eventTarget));
// stash the coordinates of the event so that we can still get back to it from within the mPossibleTooltipNode = eventTarget.get();
// timer scallback. Also stash the node that started this so we can put it into the mTooltipTimer->Init(sTooltipCallback, this, 500); // 500 ms delay
// document later on (if the timer ever fires).
nsCOMPtr<nsIDOMNode> eventTarget;
aMouseEvent->GetTarget(getter_AddRefs(eventTarget));
mPossibleTooltipNode = eventTarget.get();
uiEvent->GetScreenX(&mMouseScreenX);
uiEvent->GetScreenY(&mMouseScreenY);
uiEvent->GetClientX(&mMouseClientX);
uiEvent->GetClientY(&mMouseClientY);
mTooltipTimer->Init(sTooltipCallback, this, 1000); // one second delay
}
} }
else else
NS_WARNING ( "Could not create a timer for tooltip tracking" ); NS_WARNING ( "Could not create a timer for tooltip tracking" );
return NS_OK; return NS_OK;
} // MouseOver } // MouseMove
// //
@@ -290,12 +285,16 @@ XULPopupListenerImpl::MouseOut(nsIDOMEvent* aMouseEvent)
if ( popupType != eXULPopupType_tooltip ) if ( popupType != eXULPopupType_tooltip )
return NS_OK; return NS_OK;
if ( mTooltipTimer ) if ( mTooltipTimer ) {
mTooltipTimer->Cancel(); mTooltipTimer->Cancel();
mTooltipTimer = nsnull;
}
if ( mPopup ) { if ( mPopupContent ) {
mPopup->Close(); // hide the popup mPopupContent->RemoveAttribute("menugenerated"); // hide the popup
mPopup = nsnull; // release the popup mPopupContent->RemoveAttribute("menuactive");
mPopupContent = nsnull; // release the popup
// clear out the tooltip node on the document // clear out the tooltip node on the document
nsCOMPtr<nsIDOMNode> eventTarget; nsCOMPtr<nsIDOMNode> eventTarget;
@@ -327,6 +326,9 @@ XULPopupListenerImpl :: FindDocumentForNode ( nsIDOMNode* inElement, nsIDOMXULDo
// get the document associated with this content element // get the document associated with this content element
nsCOMPtr<nsIDocument> document; nsCOMPtr<nsIDocument> document;
nsCOMPtr<nsIContent> content = do_QueryInterface(inElement); nsCOMPtr<nsIContent> content = do_QueryInterface(inElement);
if (!content)
return rv;
if (NS_FAILED(rv = content->GetDocument(*getter_AddRefs(document)))) { if (NS_FAILED(rv = content->GetDocument(*getter_AddRefs(document)))) {
NS_ERROR("Unable to retrieve the document."); NS_ERROR("Unable to retrieve the document.");
return rv; return rv;
@@ -361,14 +363,10 @@ XULPopupListenerImpl::LaunchPopup ( nsIDOMEvent* anEvent )
} }
PRInt32 xPos, yPos; PRInt32 xPos, yPos;
uiEvent->GetScreenX(&xPos); uiEvent->GetClientX(&xPos);
uiEvent->GetScreenY(&yPos); uiEvent->GetClientY(&yPos);
PRInt32 offsetX, offsetY; return LaunchPopup(mElement, xPos, yPos);
uiEvent->GetClientX(&offsetX);
uiEvent->GetClientY(&offsetY);
return LaunchPopup ( mElement, xPos, yPos, offsetX, offsetY );
} }
@@ -376,7 +374,7 @@ XULPopupListenerImpl::LaunchPopup ( nsIDOMEvent* anEvent )
// LaunchPopup // LaunchPopup
// //
// Given the element on which the event was triggered and the mouse locations in // 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 // Client and widget coordinates, popup a new window showing the appropriate
// content. // content.
// //
// This looks for an attribute on |aElement| of the appropriate popup type // This looks for an attribute on |aElement| of the appropriate popup type
@@ -384,14 +382,8 @@ XULPopupListenerImpl::LaunchPopup ( nsIDOMEvent* anEvent )
// the popup content in the document. // the popup content in the document.
// //
nsresult nsresult
XULPopupListenerImpl::LaunchPopup( nsIDOMElement* aElement, PRInt32 aScreenX, PRInt32 aScreenY, XULPopupListenerImpl::LaunchPopup(nsIDOMElement* aElement, PRInt32 aClientX, PRInt32 aClientY)
PRInt32 aOffsetX, PRInt32 aOffsetY )
{ {
#ifdef NS_DEBUG
printf("screen coords %ld %ld\n", aScreenX, aScreenY);
printf("client coords %ld %ld\n", aOffsetX, aOffsetY);
#endif
nsresult rv = NS_OK; nsresult rv = NS_OK;
nsAutoString type("popup"); nsAutoString type("popup");
@@ -454,22 +446,15 @@ printf("client coords %ld %ld\n", aOffsetX, aOffsetY);
// Set the popup in the document for the duration of this call. // Set the popup in the document for the duration of this call.
xulDocument->SetPopupElement(mElement); xulDocument->SetPopupElement(mElement);
// If we're anchored, we pass in client/screen offsets so that PRInt32 xPos = aClientX, yPos = aClientY;
// we can translate the frames corners to screen coords.
PRInt32 xPos = aScreenX, yPos = aScreenY; mPopupContent = popupContent.get();
if (anchorAlignment != "none") {
xPos -= aOffsetX; nsCOMPtr<nsIDOMWindow> uselessPopup; // XXX Should go away.
yPos -= aOffsetY;
}
printf("***creating XUL popup at %ld %ld\n", xPos, yPos);
domWindow->CreatePopup(mElement, popupContent, domWindow->CreatePopup(mElement, popupContent,
xPos, yPos, xPos, yPos,
type, anchorAlignment, popupAlignment, type, anchorAlignment, popupAlignment,
getter_AddRefs(mPopup)); getter_AddRefs(uselessPopup));
if ( popupType == eXULPopupType_popup && mPopup )
mPopup->Focus();
// XXX For menus only, clear the document.popup field.
} }
NS_RELEASE(global); NS_RELEASE(global);
} }
@@ -479,65 +464,6 @@ printf("***creating XUL popup at %ld %ld\n", xPos, yPos);
return NS_OK; return NS_OK;
} }
nsresult
XULPopupListenerImpl::Blur(nsIDOMEvent* aMouseEvent)
{
nsresult rv = NS_OK;
#if 0
// ONLY NEEDED BECAUSE HYATT WAS LAZY
// Try to find the popup content.
nsCOMPtr<nsIDocument> document;
nsCOMPtr<nsIContent> content = do_QueryInterface(mElement);
if (NS_FAILED(rv = content->GetDocument(*getter_AddRefs(document)))) {
NS_ERROR("Unable to retrieve the document.");
return rv;
}
// Blur events don't bubble, so this means our window lost focus.
// Let's check just to make sure.
nsCOMPtr<nsIDOMNode> eventTarget;
aMouseEvent->GetTarget(getter_AddRefs(eventTarget));
// We have some popup content. Obtain our window.
nsIScriptContextOwner* owner = document->GetScriptContextOwner();
nsCOMPtr<nsIScriptContext> context;
if (NS_OK == owner->GetScriptContext(getter_AddRefs(context))) {
nsIScriptGlobalObject* global = context->GetGlobalObject();
if (global) {
// Get the DOM window
nsCOMPtr<nsIDOMWindow> domWindow = do_QueryInterface(global);
// Close, but only if we are the same target.
nsCOMPtr<nsIDOMNode> windowNode = do_QueryInterface(domWindow);
if (windowNode.get() == eventTarget.get())
domWindow->Close();
}
}
#endif
// Blur events don't bubble, so this means our window lost focus.
// Let's check just to make sure.
nsCOMPtr<nsIDOMNode> eventTarget;
aMouseEvent->GetTarget(getter_AddRefs(eventTarget));
// Close, but only if we are the same target.
nsCOMPtr<nsIDOMNode> 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
// XXX Set document.popup to null in the parent document NOW.
// xulDocument->SetPopup(nsnull);
return rv;
}
// //
// sTooltipCallback // sTooltipCallback
// //
@@ -566,8 +492,7 @@ XULPopupListenerImpl :: sTooltipCallback (nsITimer *aTimer, void *aClosure)
element->GetAttribute ( "disabled", disabledState ); element->GetAttribute ( "disabled", disabledState );
if ( disabledState != "true" ) { if ( disabledState != "true" ) {
doc->SetTooltipElement ( element ); doc->SetTooltipElement ( element );
self->LaunchPopup ( element, self->mMouseScreenX, self->mMouseScreenY, self->LaunchPopup (element, self->mMouseClientX, self->mMouseClientY+16);
self->mMouseClientX, self->mMouseClientY );
} // if node enabled } // if node enabled
} }
} // if document } // if document