From 9ea803e364a14267cffa1dcd71ff76c18211cc3c Mon Sep 17 00:00:00 2001 From: "locka%iol.ie" Date: Wed, 16 Aug 2000 08:51:58 +0000 Subject: [PATCH] Added mouse DOM listener to listen for context menu events and notify the embedding client. b=48270 a=valeski --- .../webBrowser/nsDocShellTreeOwner.cpp | 250 ++++++++++++++++-- .../browser/webBrowser/nsDocShellTreeOwner.h | 61 ++++- 2 files changed, 281 insertions(+), 30 deletions(-) diff --git a/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp b/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp index fb98143e5b56..7f0614f9c130 100644 --- a/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp +++ b/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp @@ -1,4 +1,4 @@ -/* -*- Mode: C++; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 2 -*- +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file @@ -30,8 +30,18 @@ #include "nsHTMLReflowState.h" // Interfaces needed to be included +#include "nsIContextMenuListener.h" +#include "nsIDOMNode.h" +#include "nsIDOMNodeList.h" #include "nsIDOMDocument.h" +#include "nsIDOMDocumentType.h" #include "nsIDOMElement.h" +#include "nsIDOMEvent.h" +#include "nsIDOMEventReceiver.h" +#include "nsIDOMMouseEvent.h" +#include "nsIDOMEventReceiver.h" +#include "nsIDOMNamedNodeMap.h" +#include "nsIDOMHTMLElement.h" #include "nsIPresShell.h" // CIDs @@ -40,7 +50,8 @@ //*** nsDocShellTreeOwner: Object Management //***************************************************************************** -nsDocShellTreeOwner::nsDocShellTreeOwner() : mWebBrowser(nsnull), +nsDocShellTreeOwner::nsDocShellTreeOwner() : + mWebBrowser(nsnull), mTreeOwner(nsnull), mPrimaryContentShell(nsnull), mWebBrowserChrome(nsnull), @@ -63,11 +74,14 @@ NS_IMPL_ADDREF(nsDocShellTreeOwner) NS_IMPL_RELEASE(nsDocShellTreeOwner) NS_INTERFACE_MAP_BEGIN(nsDocShellTreeOwner) - NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDocShellTreeOwner) - NS_INTERFACE_MAP_ENTRY(nsIDocShellTreeOwner) - NS_INTERFACE_MAP_ENTRY(nsIBaseWindow) - NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor) - NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDocShellTreeOwner) + NS_INTERFACE_MAP_ENTRY(nsIDocShellTreeOwner) + NS_INTERFACE_MAP_ENTRY(nsIBaseWindow) + NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor) + NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener) + NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener) + NS_INTERFACE_MAP_ENTRY(nsIDOMMouseListener) + NS_INTERFACE_MAP_ENTRY(nsICDocShellTreeOwner) NS_INTERFACE_MAP_END //***************************************************************************** @@ -138,9 +152,9 @@ NS_IMETHODIMP nsDocShellTreeOwner::GetPrimaryContentShell(nsIDocShellTreeItem** { NS_ENSURE_ARG_POINTER(aShell); - if (mTreeOwner) + if(mTreeOwner) return mTreeOwner->GetPrimaryContentShell(aShell); - + *aShell = (mPrimaryContentShell ? mPrimaryContentShell : mWebBrowser->mDocShellAsItem.get()); NS_IF_ADDREF(*aShell); @@ -426,15 +440,20 @@ nsDocShellTreeOwner::OnProgressChange(nsIWebProgress* aProgress, PRInt32 aCurTotalProgress, PRInt32 aMaxTotalProgress) { - if(!mOwnerProgressListener) - return NS_OK; + // In the absence of DOM document creation event, this method is the + // most convenient place to install the mouse listener on the + // DOM document. + AddMouseListener(); + + if(!mOwnerProgressListener) + return NS_OK; - return mOwnerProgressListener->OnProgressChange(aProgress, - aRequest, - aCurSelfProgress, - aMaxSelfProgress, - aCurTotalProgress, - aMaxTotalProgress); + return mOwnerProgressListener->OnProgressChange(aProgress, + aRequest, + aCurSelfProgress, + aMaxSelfProgress, + aCurTotalProgress, + aMaxTotalProgress); } NS_IMETHODIMP @@ -484,7 +503,7 @@ nsDocShellTreeOwner::OnStatusChange(nsIWebProgress* aWebProgress, void nsDocShellTreeOwner::WebBrowser(nsWebBrowser* aWebBrowser) { - mWebBrowser = aWebBrowser; + mWebBrowser = aWebBrowser; } nsWebBrowser* nsDocShellTreeOwner::WebBrowser() @@ -536,3 +555,198 @@ NS_IMETHODIMP nsDocShellTreeOwner::SetWebBrowserChrome(nsIWebBrowserChrome* aWeb } return NS_OK; } + +/////////////////////////////////////////////////////////////////////////////// + +NS_IMETHODIMP nsDocShellTreeOwner::AddMouseListener() +{ + // Clear out the old listener + RemoveMouseListener(); + + NS_ENSURE_TRUE(mWebBrowser, NS_ERROR_FAILURE); + + // Get the DOM document + nsCOMPtr domDocument; + mWebBrowser->GetDocument(getter_AddRefs(domDocument)); + if (domDocument == nsnull) + { + return NS_ERROR_FAILURE; + } + + // Subscribe to mouse events + nsCOMPtr eventReceiver; + domDocument->QueryInterface(NS_GET_IID(nsIDOMEventReceiver), getter_AddRefs(eventReceiver)); + if (eventReceiver) + { + nsIDOMMouseListener *pListener = NS_STATIC_CAST(nsIDOMMouseListener *, this); + eventReceiver->AddEventListenerByIID(pListener, NS_GET_IID(nsIDOMMouseListener)); + } + mLastDOMDocument = domDocument; + + return NS_OK; +} + + +NS_IMETHODIMP nsDocShellTreeOwner::RemoveMouseListener() +{ + // Unsubscribe from mouse events + if (mLastDOMDocument) + { + nsCOMPtr eventReceiver; + mLastDOMDocument->QueryInterface(NS_GET_IID(nsIDOMEventReceiver), getter_AddRefs(eventReceiver)); + if (eventReceiver) + { + nsIDOMMouseListener *pListener = NS_STATIC_CAST(nsIDOMMouseListener *, this); + eventReceiver->RemoveEventListenerByIID(pListener, NS_GET_IID(nsIDOMMouseListener)); + } + mLastDOMDocument = nsnull; + } + + return NS_OK; +} + + +nsresult nsDocShellTreeOwner::HandleEvent(nsIDOMEvent* aEvent) +{ + return NS_OK; +} + + +nsresult nsDocShellTreeOwner::MouseDown(nsIDOMEvent* aMouseEvent) +{ + // Don't bother going any further if no one is interested in context menu events + nsCOMPtr menuListener(do_QueryInterface(mTreeOwner)); + if (!menuListener) + { + return NS_OK; + } + + nsCOMPtr mouseEvent (do_QueryInterface(aMouseEvent)); + if (!mouseEvent) + { + return NS_OK; + } + + // Test for right mouse button click + PRUint16 buttonNumber; + nsresult res = mouseEvent->GetButton(&buttonNumber); + if (NS_FAILED(res)) + { + return res; + } + if (buttonNumber != 3) // 3 is the magic number + { + return NS_OK; + } + + nsCOMPtr targetNode; + res = aMouseEvent->GetTarget(getter_AddRefs(targetNode)); + if (NS_FAILED(res)) + { + return res; + } + if (!targetNode) + { + return NS_ERROR_NULL_POINTER; + } + + nsCOMPtr node = do_QueryInterface(targetNode); + if (!node) + { + return NS_OK; + } + + // Find the first node to be an element starting with this node and + // working up through its parents. + + PRUint32 flags = nsIContextMenuListener::CONTEXT_NONE; + nsCOMPtr element; + do { + PRUint16 type; + node->GetNodeType(&type); + + // XXX test for selected text + + element = do_QueryInterface(node); + if (element) + { + nsAutoString tag; + element->GetTagName(tag); + + // Test what kind of element we're dealing with here + if (tag.EqualsWithConversion("input", PR_TRUE)) + { + // INPUT element - button, combo, checkbox, text etc. + flags |= nsIContextMenuListener::CONTEXT_INPUT; + } + else if (tag.EqualsWithConversion("img", PR_TRUE)) + { + // IMG element + flags |= nsIContextMenuListener::CONTEXT_IMAGE; + } + else + { + // Something else + flags |= nsIContextMenuListener::CONTEXT_OTHER; + } + + // Test if the element has an associated link + nsCOMPtr attributes; + node->GetAttributes(getter_AddRefs(attributes)); + if (attributes) + { + nsCOMPtr hrefNode; + nsAutoString href; href.AssignWithConversion("href"); + attributes->GetNamedItem(href, getter_AddRefs(hrefNode)); + if (hrefNode) + { + flags |= nsIContextMenuListener::CONTEXT_LINK; + break; + } + } + } + nsCOMPtr parentNode; + node->GetParentNode(getter_AddRefs(parentNode)); + + // Test if we're at the top of the document + if (!parentNode) + { + node = nsnull; + flags |= nsIContextMenuListener::CONTEXT_DOCUMENT; + break; + } + node = parentNode; + } while (node); + + // Tell the listener all about the event + menuListener->OnShowContextMenu(flags, aMouseEvent, node); + + return NS_OK; +} + +nsresult nsDocShellTreeOwner::MouseUp(nsIDOMEvent* aMouseEvent) +{ + return NS_OK; +} + +nsresult nsDocShellTreeOwner::MouseClick(nsIDOMEvent* aMouseEvent) +{ + return NS_OK; +} + + +nsresult nsDocShellTreeOwner::MouseDblClick(nsIDOMEvent* aMouseEvent) +{ + return NS_OK; +} + +nsresult nsDocShellTreeOwner::MouseOver(nsIDOMEvent* aMouseEvent) +{ + return NS_OK; +} + + +nsresult nsDocShellTreeOwner::MouseOut(nsIDOMEvent* aMouseEvent) +{ + return NS_OK; +} diff --git a/embedding/browser/webBrowser/nsDocShellTreeOwner.h b/embedding/browser/webBrowser/nsDocShellTreeOwner.h index 42ba1c4fabc4..22e263283bc9 100644 --- a/embedding/browser/webBrowser/nsDocShellTreeOwner.h +++ b/embedding/browser/webBrowser/nsDocShellTreeOwner.h @@ -33,32 +33,69 @@ #include "nsIInterfaceRequestor.h" #include "nsIWebBrowserChrome.h" #include "nsIWebProgressListener.h" +#include "nsIDOMMouseListener.h" +#include "nsIDOMDocument.h" + +#include "nsCommandHandler.h" class nsWebBrowser; +// {6D10C180-6888-11d4-952B-0020183BF181} +#define NS_ICDOCSHELLTREEOWNER_IID \ +{ 0x6d10c180, 0x6888, 0x11d4, { 0x95, 0x2b, 0x0, 0x20, 0x18, 0x3b, 0xf1, 0x81 } } + +/* + * This is a fake 'hidden' interface that nsDocShellTreeOwner implements. + * Classes such as nsCommandHandler can QI for this interface to be + * sure that they're dealing with a valid nsDocShellTreeOwner and not some + * other object that implements nsIDocShellTreeOwner. + */ +class nsICDocShellTreeOwner : public nsISupports +{ +public: + NS_DEFINE_STATIC_IID_ACCESSOR(NS_ICDOCSHELLTREEOWNER_IID) +}; + + class nsDocShellTreeOwner : public nsIDocShellTreeOwner, public nsIBaseWindow, public nsIInterfaceRequestor, - public nsIWebProgressListener + public nsIWebProgressListener, + public nsIDOMMouseListener, + public nsICDocShellTreeOwner { friend class nsWebBrowser; +friend class nsCommandHandler; public: - NS_DECL_ISUPPORTS + NS_DECL_ISUPPORTS - NS_DECL_NSIBASEWINDOW - NS_DECL_NSIDOCSHELLTREEOWNER - NS_DECL_NSIINTERFACEREQUESTOR - NS_DECL_NSIWEBPROGRESSLISTENER + NS_DECL_NSIBASEWINDOW + NS_DECL_NSIDOCSHELLTREEOWNER + NS_DECL_NSIINTERFACEREQUESTOR + NS_DECL_NSIWEBPROGRESSLISTENER + + // nsIDOMMouseListener + virtual nsresult HandleEvent(nsIDOMEvent* aEvent); + virtual nsresult MouseDown(nsIDOMEvent* aMouseEvent); + virtual nsresult MouseUp(nsIDOMEvent* aMouseEvent); + virtual nsresult MouseClick(nsIDOMEvent* aMouseEvent); + virtual nsresult MouseDblClick(nsIDOMEvent* aMouseEvent); + virtual nsresult MouseOver(nsIDOMEvent* aMouseEvent); + virtual nsresult MouseOut(nsIDOMEvent* aMouseEvent); protected: - nsDocShellTreeOwner(); - virtual ~nsDocShellTreeOwner(); + nsDocShellTreeOwner(); + virtual ~nsDocShellTreeOwner(); - void WebBrowser(nsWebBrowser* aWebBrowser); - nsWebBrowser* WebBrowser(); - NS_IMETHOD SetTreeOwner(nsIDocShellTreeOwner* aTreeOwner); - NS_IMETHOD SetWebBrowserChrome(nsIWebBrowserChrome* aWebBrowserChrome); + void WebBrowser(nsWebBrowser* aWebBrowser); + nsWebBrowser* WebBrowser(); + NS_IMETHOD SetTreeOwner(nsIDocShellTreeOwner* aTreeOwner); + NS_IMETHOD SetWebBrowserChrome(nsIWebBrowserChrome* aWebBrowserChrome); + + nsCOMPtr mLastDOMDocument; + NS_IMETHOD AddMouseListener(); + NS_IMETHOD RemoveMouseListener(); protected: