diff --git a/java/webclient/src/BrowserControlMozillaShim.cpp b/java/webclient/src/BrowserControlMozillaShim.cpp index 5753cb80a1e..ea302e257ca 100644 --- a/java/webclient/src/BrowserControlMozillaShim.cpp +++ b/java/webclient/src/BrowserControlMozillaShim.cpp @@ -54,6 +54,7 @@ nsMacMessageSink gMessageSink; #ifdef XP_UNIX #include +#include "motif/MozillaEventThread.h" #endif #include "nsActions.h" @@ -234,7 +235,7 @@ EmbeddedEventHandler (void * arg) { #ifndef NECKO NS_InitINetService(); #endif - // HACK(mark): EmbeddedThread isn't set until after this method returns!! + // HACK(mark): On Unix, embeddedThread isn't set until after this method returns!! initContext->embeddedThread = PR_GetCurrentThread(); // Create the action queue @@ -302,14 +303,19 @@ EmbeddedEventHandler (void * arg) { #if DEBUG_RAPTOR_CANVAS printf("EmbeddedEventHandler(%lx): enter event loop\n", initContext); #endif - + + // Don't loop here. The looping will be handled by a Java Thread + // (see org.mozilla.webclient.motif.MozillaEventThread). +#ifndef XP_UNIX do { if (!processEventLoop(initContext)) { -#ifndef XP_UNIX break; -#endif } } while (PR_TRUE); +#else + // Just need to loop once for Unix + processEventLoop(initContext); +#endif } // It appears the current thread (belonging to Java) is assumed to be @@ -333,6 +339,9 @@ InitEmbeddedEventHandler (WebShellInitContext* initContext) #if DEBUG_RAPTOR_CANVAS printf("InitEmbeddedEventHandler(%lx): Creating embedded thread...\n", initContext); #endif + // Don't create a NSPR Thread on Unix, because we will use a Java Thread instead. + // (see org.mozilla.webclient.motif.MozillaEventThread). +#ifndef XP_UNIX initContext->embeddedThread = ::PR_CreateThread(PR_SYSTEM_THREAD, EmbeddedEventHandler, (void*)initContext, @@ -340,6 +349,9 @@ InitEmbeddedEventHandler (WebShellInitContext* initContext) PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 0); +#else + EmbeddedEventHandler((void *) initContext); +#endif #if DEBUG_RAPTOR_CANVAS printf("InitEmbeddedEventHandler(%lx): Embedded Thread created...\n", initContext); #endif @@ -352,15 +364,8 @@ InitEmbeddedEventHandler (WebShellInitContext* initContext) return; } } -#ifdef XP_UNIX - // PENDING(mark): HACK! Sleep for 3 seconds just to make sure everything - // starts up correctly. Not sure why this helps yet. - ::PR_Sleep(PR_SecondsToInterval(3)); -#endif } - - static nsEventStatus PR_CALLBACK HandleRaptorEvent (nsGUIEvent *) { @@ -1089,7 +1094,50 @@ Java_org_mozilla_webclient_BrowserControlMozillaShim_nativeWebShellCreate ( initContext->w = width; initContext->h = height; +#ifdef XP_UNIX + // This probably needs some explaining... + // On Unix, instead of using a NSPR thread to manage our Mozilla event loop, we + // use a Java Thread (for reasons I won't go into now, see + // org.mozilla.webclient.motif.MozillaEventThread for more details). This java thread will + // process any pending native events in + // org.mozilla.webclient.motif.MozillaEventThread.processNativeEventQueue() + // (see below). However, when processNativeEventQueue() gets called, it needs access to it's associated + // WebShellInitContext structure in order to process any GTK / Mozilla related events. So what we + // do is we keep a static Hashtable inside the class MozillaEventThread to store mappings of + // gtkWindowID's to WebShellInitContext's (since there is one WebShellInitContext to one GTK Window). + // This is what this part of the code does: + // + // 1) It first accesses the class org.mozilla.webclient.motif.MozillaEventThread + // 2) It then accesses a static method in this class called "storeContext()" which takes as + // arguments, a GTK window pointer and a WebShellInitContext pointer + // 3) Then it invokes the method + // 4) Inside MozillaEventThread.run(), you can see the code which fetches the appropriate + // WebShellInitContext and then calls processNativeEventQueue() with it below. + + // PENDING(mark): Should we cache this? Probably.... + jclass mozillaEventThreadClass = env->FindClass("org/mozilla/webclient/motif/MozillaEventThread"); + + if (mozillaEventThreadClass == NULL) { + printf("Error: Cannot find class org.mozilla.webclient.motif.MozillaEventThread!\n"); + + ThrowExceptionToJava(env, "Error: Cannot find class org.mozilla.webclient.motif.MozillaEventThread!"); + return 0; + } + + jmethodID storeMethodID = env->GetStaticMethodID(mozillaEventThreadClass, "storeContext", "(II)V"); + + if (storeMethodID == NULL) { + printf("Error: Cannot get static method storeContext(int, int) from MozillaEventThread!\n"); + + ThrowExceptionToJava(env, "Error: Cannot get static method storeContext(int, int) from MozillaEventThread!"); + return 0; + } + + // PENDING(mark): How do I catch this if there's an exception? + env->CallStaticVoidMethod(mozillaEventThreadClass, storeMethodID, windowPtr, (int) initContext); +#else InitEmbeddedEventHandler(initContext); +#endif return (jint) initContext; } // Java_org_mozilla_webclient_BrowserControlMozillaShim_nativeWebShellCreate() @@ -1740,6 +1788,29 @@ Java_org_mozilla_webclient_BrowserControlMozillaShim_nativeWebShellGetURL ( return urlString; } // Java_org_mozilla_webclient_BrowserControlMozillaShim_nativeWebShellGetURL() + +#ifdef XP_UNIX +/* + * Class: org_mozilla_webclient_motif_MotifMozillaEventQueue + * Method: processNativeEventQueue + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_org_mozilla_webclient_motif_MozillaEventThread_processNativeEventQueue + (JNIEnv * env, jobject obj, jint webShellInitContextPtr) { + // Given a WebShellInitContext pointer, process any pending Mozilla / GTK events + WebShellInitContext * initContext = (WebShellInitContext *) webShellInitContextPtr; + + // Initialize the WebShellInitContext if it's hasn't been already + if (initContext->initComplete == FALSE) { + InitEmbeddedEventHandler(initContext); + } + + // Process any pending events... + processEventLoop(initContext); +} +#endif + + #ifdef XP_UNIX }// End extern "C" #endif diff --git a/java/webclient/src/motif/BrowserControlMozillaShimStub.cpp b/java/webclient/src/motif/BrowserControlMozillaShimStub.cpp index c6ba6d10e04..980869e8e7e 100644 --- a/java/webclient/src/motif/BrowserControlMozillaShimStub.cpp +++ b/java/webclient/src/motif/BrowserControlMozillaShimStub.cpp @@ -20,11 +20,20 @@ * BrowserControlMozillaShimStub.cpp */ -#include -#include -#include "../BrowserControlMozillaShim.h" +// PENDING(mark): I suppose this is where I need to go into my explaination of why +// this file is needed... -void * mozWebShellDll; +// For loading DLL +#include +// JNI...yada, yada, yada +#include +// JNI Header +#include "../BrowserControlMozillaShim.h" +// JNI Header +#include "MozillaEventThread.h" + +// Global reference to webclient dll +void * webClientDll; extern void locateMotifBrowserControlStubFunctions(void *); @@ -62,6 +71,8 @@ jboolean (* nativeWebShellGoTo) (JNIEnv *, jobject, jint, jint); jint (* nativeWebShellGetHistoryLength) (JNIEnv *, jobject, jint); jint (* nativeWebShellGetHistoryIndex) (JNIEnv *, jobject, jint); jstring (* nativeWebShellGetURL) (JNIEnv *, jobject, jint, jint); +void (* processNativeEventQueue) (JNIEnv *, jobject, jint); + void locateBrowserControlStubFunctions(void * dll) { nativeInitialize = (void (*) (JNIEnv *, jobject)) dlsym(dll, "Java_org_mozilla_webclient_BrowserControlMozillaShim_nativeInitialize"); @@ -200,6 +211,20 @@ void locateBrowserControlStubFunctions(void * dll) { if (!nativeWebShellGetURL) { printf("got dlsym error %s\n", dlerror()); } + processNativeEventQueue = (void (*) (JNIEnv *, jobject, jint)) dlsym(dll, "Java_org_mozilla_webclient_motif_MozillaEventThread_processNativeEventQueue"); + if (!processNativeEventQueue) { + printf("got dlsym error %s\n", dlerror()); + } +} + +/* + * Class: org_mozilla_webclient_motif_MotifMozillaEventQueue + * Method: processNativeEventQueue + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_org_mozilla_webclient_motif_MozillaEventThread_processNativeEventQueue + (JNIEnv * env, jobject obj, jint gtkWinPtr) { + (* processNativeEventQueue) (env, obj, gtkWinPtr); } @@ -213,11 +238,11 @@ Java_org_mozilla_webclient_BrowserControlMozillaShim_nativeInitialize ( JNIEnv * env, jobject obj) { - mozWebShellDll = dlopen("libwebclient.so", RTLD_LAZY | RTLD_GLOBAL); + webClientDll = dlopen("libwebclient.so", RTLD_LAZY | RTLD_GLOBAL); - if (mozWebShellDll) { - locateBrowserControlStubFunctions(mozWebShellDll); - locateMotifBrowserControlStubFunctions(mozWebShellDll); + if (webClientDll) { + locateBrowserControlStubFunctions(webClientDll); + locateMotifBrowserControlStubFunctions(webClientDll); (* nativeInitialize) (env, obj); } else { diff --git a/java/webclient/src/motif/MotifBrowserControlCanvasStub.cpp b/java/webclient/src/motif/MotifBrowserControlCanvasStub.cpp index 5c3d62e7344..7bccce2bac3 100644 --- a/java/webclient/src/motif/MotifBrowserControlCanvasStub.cpp +++ b/java/webclient/src/motif/MotifBrowserControlCanvasStub.cpp @@ -21,6 +21,9 @@ * MotifBrowserControlCanvasStub.cpp */ +// PENDING(mark): I suppose this is where I need to go into my explaination of why +// this file is needed... + #include #include "MotifBrowserControlCanvas.h"