From 91dfc84b6eeed59031d8fbbd6789734fc171f9ea Mon Sep 17 00:00:00 2001 From: "edburns%acm.org" Date: Sat, 23 Oct 2004 05:26:08 +0000 Subject: [PATCH] This checkin enables the mozilla side of mouse and key listener behavior. Next step is to enable the java side in test-first design fashion. A webclient/src_moz/EmbedEventListener.cpp A webclient/src_moz/EmbedEventListener.h - carried over directly from GtkMozEmbed, minus GTK code. M webclient/src_moz/EmbedProgress.cpp - call to NativeBrowserControl::ContentStateChange() to hook up listeners. M webclient/src_moz/Makefile.in - add new EmbedEventListener.cpp file M webclient/src_moz/NativeBrowserControl.cpp M webclient/src_moz/NativeBrowserControl.h - new methods for hooking up listeners. --- java/webclient/src_moz/EmbedEventListener.cpp | 266 ++++++++++++++++++ java/webclient/src_moz/EmbedEventListener.h | 66 +++++ java/webclient/src_moz/EmbedProgress.cpp | 2 + java/webclient/src_moz/Makefile.in | 1 + .../src_moz/NativeBrowserControl.cpp | 161 ++++++++++- java/webclient/src_moz/NativeBrowserControl.h | 26 ++ 6 files changed, 521 insertions(+), 1 deletion(-) create mode 100644 java/webclient/src_moz/EmbedEventListener.cpp create mode 100644 java/webclient/src_moz/EmbedEventListener.h diff --git a/java/webclient/src_moz/EmbedEventListener.cpp b/java/webclient/src_moz/EmbedEventListener.cpp new file mode 100644 index 00000000000..479a7166a94 --- /dev/null +++ b/java/webclient/src_moz/EmbedEventListener.cpp @@ -0,0 +1,266 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is Christopher Blizzard. + * Portions created by Christopher Blizzard are Copyright (C) + * Christopher Blizzard. All Rights Reserved. + * + * Contributor(s): + * Christopher Blizzard + */ + +#include +#include + +#include "nsIDOMKeyEvent.h" + +#include "EmbedEventListener.h" +#include "NativeBrowserControl.h" + +#include "ns_globals.h" // for prLogModuleInfo + +EmbedEventListener::EmbedEventListener(void) +{ + mOwner = nsnull; +} + +EmbedEventListener::~EmbedEventListener() +{ +} + +NS_IMPL_ADDREF(EmbedEventListener) +NS_IMPL_RELEASE(EmbedEventListener) +NS_INTERFACE_MAP_BEGIN(EmbedEventListener) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMKeyListener) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIDOMEventListener, nsIDOMKeyListener) + NS_INTERFACE_MAP_ENTRY(nsIDOMKeyListener) + NS_INTERFACE_MAP_ENTRY(nsIDOMMouseListener) +NS_INTERFACE_MAP_END + +nsresult +EmbedEventListener::Init(NativeBrowserControl *aOwner) +{ + mOwner = aOwner; + return NS_OK; +} + +// All of the event listeners below return NS_OK to indicate that the +// event should not be consumed in the default case. + +NS_IMETHODIMP +EmbedEventListener::HandleEvent(nsIDOMEvent* aDOMEvent) +{ + return NS_OK; +} + +NS_IMETHODIMP +EmbedEventListener::KeyDown(nsIDOMEvent* aDOMEvent) +{ + nsCOMPtr keyEvent; + keyEvent = do_QueryInterface(aDOMEvent); + if (!keyEvent) + return NS_OK; + // Return FALSE to this function to mark the event as not + // consumed... + PRBool return_val = PR_FALSE; + /************ + gtk_signal_emit(GTK_OBJECT(mOwner->mOwningWidget), + moz_embed_signals[DOM_KEY_DOWN], + (void *)keyEvent, &return_val); + **********/ + if (return_val) { + aDOMEvent->StopPropagation(); + aDOMEvent->PreventDefault(); + } + return NS_OK; +} + +NS_IMETHODIMP +EmbedEventListener::KeyUp(nsIDOMEvent* aDOMEvent) +{ + nsCOMPtr keyEvent; + keyEvent = do_QueryInterface(aDOMEvent); + if (!keyEvent) + return NS_OK; + // return FALSE to this function to mark this event as not + // consumed... + PRBool return_val = PR_FALSE; + /*************** + gtk_signal_emit(GTK_OBJECT(mOwner->mOwningWidget), + moz_embed_signals[DOM_KEY_UP], + (void *)keyEvent, &return_val); + ****************/ + if (return_val) { + aDOMEvent->StopPropagation(); + aDOMEvent->PreventDefault(); + } + return NS_OK; +} + +NS_IMETHODIMP +EmbedEventListener::KeyPress(nsIDOMEvent* aDOMEvent) +{ + nsCOMPtr keyEvent; + keyEvent = do_QueryInterface(aDOMEvent); + if (!keyEvent) + return NS_OK; + // return FALSE to this function to mark this event as not + // consumed... + PRBool return_val = PR_FALSE; + /*********** + gtk_signal_emit(GTK_OBJECT(mOwner->mOwningWidget), + moz_embed_signals[DOM_KEY_PRESS], + (void *)keyEvent, &return_val); + ************/ + if (return_val) { + aDOMEvent->StopPropagation(); + aDOMEvent->PreventDefault(); + } + return NS_OK; +} + +NS_IMETHODIMP +EmbedEventListener::MouseDown(nsIDOMEvent* aDOMEvent) +{ + nsCOMPtr mouseEvent; + mouseEvent = do_QueryInterface(aDOMEvent); + if (!mouseEvent) + return NS_OK; + // return FALSE to this function to mark this event as not + // consumed... + PRBool return_val = PR_FALSE; + /************** + gtk_signal_emit(GTK_OBJECT(mOwner->mOwningWidget), + moz_embed_signals[DOM_MOUSE_DOWN], + (void *)mouseEvent, &return_val); + ***********/ + if (return_val) { + aDOMEvent->StopPropagation(); + aDOMEvent->PreventDefault(); + } + return NS_OK; +} + +NS_IMETHODIMP +EmbedEventListener::MouseUp(nsIDOMEvent* aDOMEvent) +{ + nsCOMPtr mouseEvent; + mouseEvent = do_QueryInterface(aDOMEvent); + if (!mouseEvent) + return NS_OK; + // Return FALSE to this function to mark the event as not + // consumed... + PRBool return_val = PR_FALSE; + /************** + gtk_signal_emit(GTK_OBJECT(mOwner->mOwningWidget), + moz_embed_signals[DOM_MOUSE_UP], + (void *)mouseEvent, &return_val); + *************/ + if (return_val) { + aDOMEvent->StopPropagation(); + aDOMEvent->PreventDefault(); + } + return NS_OK; +} + +NS_IMETHODIMP +EmbedEventListener::MouseClick(nsIDOMEvent* aDOMEvent) +{ + nsCOMPtr mouseEvent; + mouseEvent = do_QueryInterface(aDOMEvent); + if (!mouseEvent) + return NS_OK; + // Return FALSE to this function to mark the event as not + // consumed... + PRBool return_val = FALSE; + /**************** + gtk_signal_emit(GTK_OBJECT(mOwner->mOwningWidget), + moz_embed_signals[DOM_MOUSE_CLICK], + (void *)mouseEvent, &return_val); + ***********/ + if (return_val) { + aDOMEvent->StopPropagation(); + aDOMEvent->PreventDefault(); + } + return NS_OK; +} + +NS_IMETHODIMP +EmbedEventListener::MouseDblClick(nsIDOMEvent* aDOMEvent) +{ + nsCOMPtr mouseEvent; + mouseEvent = do_QueryInterface(aDOMEvent); + if (!mouseEvent) + return NS_OK; + // return FALSE to this function to mark this event as not + // consumed... + PRBool return_val = PR_FALSE; + /*************** + gtk_signal_emit(GTK_OBJECT(mOwner->mOwningWidget), + moz_embed_signals[DOM_MOUSE_DBL_CLICK], + (void *)mouseEvent, &return_val); + **********/ + if (return_val) { + aDOMEvent->StopPropagation(); + aDOMEvent->PreventDefault(); + } + return NS_OK; +} + +NS_IMETHODIMP +EmbedEventListener::MouseOver(nsIDOMEvent* aDOMEvent) +{ + nsCOMPtr mouseEvent; + mouseEvent = do_QueryInterface(aDOMEvent); + if (!mouseEvent) + return NS_OK; + // return FALSE to this function to mark this event as not + // consumed... + PRBool return_val = PR_FALSE; + + PR_LOG(prLogModuleInfo, PR_LOG_DEBUG, + ("EmbedEventListener::MouseOver: \n")); + + /************* + gtk_signal_emit(GTK_OBJECT(mOwner->mOwningWidget), + moz_embed_signals[DOM_MOUSE_OVER], + (void *)mouseEvent, &return_val); + **********/ + if (return_val) { + aDOMEvent->StopPropagation(); + aDOMEvent->PreventDefault(); + } + return NS_OK; +} + +NS_IMETHODIMP +EmbedEventListener::MouseOut(nsIDOMEvent* aDOMEvent) +{ + nsCOMPtr mouseEvent; + mouseEvent = do_QueryInterface(aDOMEvent); + if (!mouseEvent) + return NS_OK; + // return FALSE to this function to mark this event as not + // consumed... + PRBool return_val = PR_FALSE; + /************ + gtk_signal_emit(GTK_OBJECT(mOwner->mOwningWidget), + moz_embed_signals[DOM_MOUSE_OUT], + (void *)mouseEvent, &return_val); + ***********/ + if (return_val) { + aDOMEvent->StopPropagation(); + aDOMEvent->PreventDefault(); + } + return NS_OK; +} diff --git a/java/webclient/src_moz/EmbedEventListener.h b/java/webclient/src_moz/EmbedEventListener.h new file mode 100644 index 00000000000..46188eacc3b --- /dev/null +++ b/java/webclient/src_moz/EmbedEventListener.h @@ -0,0 +1,66 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is Christopher Blizzard. + * Portions created by Christopher Blizzard are Copyright (C) + * Christopher Blizzard. All Rights Reserved. + * + * Contributor(s): + * Christopher Blizzard + */ + +#ifndef __EmbedEventListener_h +#define __EmbedEventListener_h + +#include +#include + +class NativeBrowserControl; + +class EmbedEventListener : public nsIDOMKeyListener, + public nsIDOMMouseListener +{ + public: + + EmbedEventListener(); + virtual ~EmbedEventListener(); + + nsresult Init(NativeBrowserControl *aOwner); + + NS_DECL_ISUPPORTS + + // nsIDOMEventListener + + NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent); + + // nsIDOMKeyListener + + NS_IMETHOD KeyDown(nsIDOMEvent* aDOMEvent); + NS_IMETHOD KeyUp(nsIDOMEvent* aDOMEvent); + NS_IMETHOD KeyPress(nsIDOMEvent* aDOMEvent); + + // nsIDOMMouseListener + + NS_IMETHOD MouseDown(nsIDOMEvent* aDOMEvent); + NS_IMETHOD MouseUp(nsIDOMEvent* aDOMEvent); + NS_IMETHOD MouseClick(nsIDOMEvent* aDOMEvent); + NS_IMETHOD MouseDblClick(nsIDOMEvent* aDOMEvent); + NS_IMETHOD MouseOver(nsIDOMEvent* aDOMEvent); + NS_IMETHOD MouseOut(nsIDOMEvent* aDOMEvent); + + private: + + NativeBrowserControl *mOwner; +}; + +#endif /* __EmbedEventListener_h */ diff --git a/java/webclient/src_moz/EmbedProgress.cpp b/java/webclient/src_moz/EmbedProgress.cpp index 6d0427c77ef..273b411c34d 100644 --- a/java/webclient/src_moz/EmbedProgress.cpp +++ b/java/webclient/src_moz/EmbedProgress.cpp @@ -99,6 +99,8 @@ EmbedProgress::OnStateChange(nsIWebProgress *aWebProgress, PRUint32 aStateFlags, nsresult aStatus) { + // hook up listeners for this request. + mOwner->ContentStateChange(); JNIEnv *env = (JNIEnv *) JNU_GetEnv(gVm, JNI_VERSION); nsXPIDLCString uriString; RequestToURIString(aRequest, getter_Copies(uriString)); diff --git a/java/webclient/src_moz/Makefile.in b/java/webclient/src_moz/Makefile.in index 070234e8276..37f8536b722 100644 --- a/java/webclient/src_moz/Makefile.in +++ b/java/webclient/src_moz/Makefile.in @@ -105,6 +105,7 @@ CPPSRCS = \ NativeWrapperFactory.cpp \ EmbedWindow.cpp \ EmbedProgress.cpp \ + EmbedEventListener.cpp \ EventRegistrationImpl.cpp \ HttpHeaderVisitorImpl.cpp \ NativeEventThread.cpp \ diff --git a/java/webclient/src_moz/NativeBrowserControl.cpp b/java/webclient/src_moz/NativeBrowserControl.cpp index 560378f4505..1c758380deb 100644 --- a/java/webclient/src_moz/NativeBrowserControl.cpp +++ b/java/webclient/src_moz/NativeBrowserControl.cpp @@ -34,9 +34,16 @@ #include "EmbedWindow.h" #include "WindowCreator.h" #include "EmbedProgress.h" +#include "EmbedEventListener.h" #include "NativeBrowserControl.h" #include "ns_util.h" +// all of the crap that we need for event listeners +// and when chrome windows finish loading +#include +#include +#include +#include NativeBrowserControl::NativeBrowserControl(void) { @@ -49,6 +56,7 @@ NativeBrowserControl::NativeBrowserControl(void) mIsChrome = PR_FALSE; mChromeLoaded = PR_FALSE; mIsDestroyed = PR_FALSE; + mListenersAttached = PR_FALSE; } NativeBrowserControl::~NativeBrowserControl() @@ -85,7 +93,14 @@ NativeBrowserControl::Init(NativeWrapperFactory *yourWrapperFactory) mProgress); mProgress->Init(this); - + // Create our key listener object and initialize it. It is assumed + // that this will be destroyed before we go out of scope. + mEventListener = new EmbedEventListener(); + mEventListenerGuard = + NS_STATIC_CAST(nsISupports *, NS_STATIC_CAST(nsIDOMKeyListener *, + mEventListener)); + mEventListener->Init(this); + nsCOMPtr webBrowser; mWindow->GetWebBrowser(getter_AddRefs(webBrowser)); @@ -211,6 +226,11 @@ NativeBrowserControl::Destroy(void) // Get the nsIWebBrowser object for our embedded window. nsCOMPtr webBrowser; mWindow->GetWebBrowser(getter_AddRefs(webBrowser)); + + // detach our event listeners and release the event receiver + DetachListeners(); + if (mEventReceiver) + mEventReceiver = nsnull; // destroy our child window mWindow->ReleaseChildren(); @@ -263,4 +283,143 @@ jobject NativeBrowserControl::QueryInterfaceJava(WEBCLIENT_INTERFACES interface) ::util_DeleteStringUTF(env, interfaceJStr); return result; +} + +void +NativeBrowserControl::ContentStateChange(void) +{ + // we don't attach listeners to chrome + if (mListenersAttached && !mIsChrome) { + return; + } + + GetListener(); + + if (!mEventReceiver) { + return; + } + + AttachListeners(); + } + +void +NativeBrowserControl::GetListener() +{ + if (mEventReceiver) { + return; + } + + nsCOMPtr piWin; + GetPIDOMWindow(getter_AddRefs(piWin)); + + if (!piWin) { + return; + } + + nsCOMPtr chromeHandler; + piWin->GetChromeEventHandler(getter_AddRefs(chromeHandler)); + + mEventReceiver = do_QueryInterface(chromeHandler); + +} + +void +NativeBrowserControl::AttachListeners() +{ + if (!mEventReceiver || mListenersAttached) { + return; + } + + nsIDOMEventListener *eventListener = + NS_STATIC_CAST(nsIDOMEventListener *, + NS_STATIC_CAST(nsIDOMKeyListener *, mEventListener)); + + // add the key listener + nsresult rv; + rv = mEventReceiver->AddEventListenerByIID(eventListener, + NS_GET_IID(nsIDOMKeyListener)); + if (NS_FAILED(rv)) { + NS_WARNING("Failed to add key listener\n"); + return; + } + + rv = mEventReceiver->AddEventListenerByIID(eventListener, + NS_GET_IID(nsIDOMMouseListener)); + if (NS_FAILED(rv)) { + NS_WARNING("Failed to add mouse listener\n"); + return; + } + + // ok, all set. + mListenersAttached = PR_TRUE; +} + +void +NativeBrowserControl::DetachListeners() +{ + if (!mListenersAttached || !mEventReceiver) { + return; + } + + nsIDOMEventListener *eventListener = + NS_STATIC_CAST(nsIDOMEventListener *, + NS_STATIC_CAST(nsIDOMKeyListener *, mEventListener)); + + nsresult rv; + rv = mEventReceiver->RemoveEventListenerByIID(eventListener, + NS_GET_IID(nsIDOMKeyListener)); + if (NS_FAILED(rv)) { + NS_WARNING("Failed to remove key listener\n"); + return; + } + + rv = + mEventReceiver->RemoveEventListenerByIID(eventListener, + NS_GET_IID(nsIDOMMouseListener)); + if (NS_FAILED(rv)) { + NS_WARNING("Failed to remove mouse listener\n"); + return; + } + + mListenersAttached = PR_FALSE; + +} + +nsresult +NativeBrowserControl::GetPIDOMWindow(nsPIDOMWindow **aPIWin) +{ + *aPIWin = nsnull; + + // get the web browser + nsCOMPtr webBrowser; + mWindow->GetWebBrowser(getter_AddRefs(webBrowser)); + + // get the content DOM window for that web browser + nsCOMPtr domWindow; + webBrowser->GetContentDOMWindow(getter_AddRefs(domWindow)); + if (!domWindow) { + return NS_ERROR_FAILURE; + } + + // get the private DOM window + nsCOMPtr domWindowPrivate = do_QueryInterface(domWindow); + // and the root window for that DOM window + nsCOMPtr rootWindow; + domWindowPrivate->GetPrivateRoot(getter_AddRefs(rootWindow)); + + nsCOMPtr chromeHandler; + nsCOMPtr piWin(do_QueryInterface(rootWindow)); + + *aPIWin = piWin.get(); + + if (*aPIWin) { + NS_ADDREF(*aPIWin); + return NS_OK; + } + + return NS_ERROR_FAILURE; + +} + + diff --git a/java/webclient/src_moz/NativeBrowserControl.h b/java/webclient/src_moz/NativeBrowserControl.h index e70d99313ca..1dfb44df17d 100644 --- a/java/webclient/src_moz/NativeBrowserControl.h +++ b/java/webclient/src_moz/NativeBrowserControl.h @@ -42,7 +42,10 @@ class EmbedProgress; class EmbedWindow; +class EmbedEventListener; class NativeWrapperFactory; +class nsPIDOMWindow; + /** *

Native analog to BrowserControl. Hosts per-window things. Maps @@ -77,6 +80,22 @@ public: jobject QueryInterfaceJava(WEBCLIENT_INTERFACES interface); + // This is an upcall that will come from the progress listener + // whenever there is a content state change. We need this so we can + // attach event listeners. + void ContentStateChange (void); + +private: + + void GetListener (void); + + void AttachListeners(void); + void DetachListeners(void); + + // this will get the PIDOMWindow for this widget + nsresult GetPIDOMWindow (nsPIDOMWindow **aPIWin); + +public: // // Relationship ivars @@ -91,10 +110,15 @@ public: nsCOMPtr mNavigation; nsCOMPtr mSessionHistory; + // our event receiver + nsCOMPtr mEventReceiver; + EmbedWindow * mWindow; nsCOMPtr mWindowGuard; EmbedProgress * mProgress; nsCOMPtr mProgressGuard; + EmbedEventListener *mEventListener; + nsCOMPtr mEventListenerGuard; ShareInitContext mShareContext; // chrome mask @@ -105,6 +129,8 @@ public: PRBool mChromeLoaded; // has someone called Destroy() on us? PRBool mIsDestroyed; + // is the chrome listener attached yet? + PRBool mListenersAttached; jobject mJavaBrowserControl;