At long last, I have webclient running on Mac OSX. I only have a

PowerBook G4, so the only binary I can produce is for the PowerPC.
Perhaps someone lucky enough to own a MacBookPro can produce a binary
for me on that processor architecture.

Many thanks to the generous folks on #developers, in particular, timeless,
cbarrett, sdwilsh, and jhpedemonte.

Here are the changes.

SECTION: Changes

M dist/build.xml

- propogate clean on mac os x

- On mac os x, there is .jnilib and also .dylib

M dom/build.xml

- propogate make on mac os x

M webclient/build.xml

- new file for javah on mac

- propogate clobber_all on mac

M webclient/classes_spec/org/mozilla/webclient/BrowserControlCanvas.java

- get the tree lock before calling to native code to get the native window

A webclient/classes_spec/org/mozilla/webclient/impl/wrapper_native/CocoaAppKitThreadDelegatingNativeEventThread.java

- Allows running arbitrary code on the AppKit thread.  Prevents Thread
  Safety assertions.

M webclient/classes_spec/org/mozilla/webclient/impl/wrapper_native/CocoaBrowserControlCanvas.java

- adhere to informal protocol to create NativeEventThread

M webclient/classes_spec/org/mozilla/webclient/impl/wrapper_native/ImplObjectNative.java

- use NativeEventThread.instance.isNativeEventThread()

M webclient/classes_spec/org/mozilla/webclient/impl/wrapper_native/NativeEventThread.java

- implement isNativeEventThread()

M webclient/src_moz/Makefile.in

- turn on objc-exceptions on mac os x

M webclient/src_moz/NativeBrowserControl.cpp
M webclient/src_moz/NativeBrowserControl.h

- work with cocoa

M webclient/src_moz/NativeEventThread.cpp
M webclient/src_moz/cocoa/CocoaBrowserControlCanvas.h
M webclient/src_moz/cocoa/CocoaBrowserControlCanvasImpl.cpp

- two methods to run arbitrary code on the AppKit thread

M webclient/src_moz/cocoa/CocoaBrowserControlCanvas.mm
M webclient/test/manual/src/classes/org/mozilla/webclient/test/TestBrowser.java
This commit is contained in:
edburns%acm.org 2007-06-10 16:24:12 +00:00
Родитель 9274778899
Коммит ec2c4cca97
16 изменённых файлов: 489 добавлений и 185 удалений

21
java/dist/build.xml поставляемый
Просмотреть файл

@ -97,6 +97,25 @@
</target>
<target name="clean">
<condition property="platform" value="win32">
<and>
<os family="windows" />
</and>
</condition>
<condition property="platform" value="macosx-ppc">
<and>
<os name="Mac OS X" />
</and>
</condition>
<condition property="platform" value="linux">
<and>
<os family="unix" />
</and>
</condition>
<delete file="${objdir}/${name}_${version}_${platform}.zip" />
<delete dir="${dist.base}" />
</target>
@ -249,7 +268,7 @@
<copy todir="${dist.home}/bin"
file="${objdir}/java/dom/jni/${so.prefix}javadomjni.${jni.extension}" />
<copy todir="${dist.home}/bin"
file="${objdir}/java/webclient/src_moz/${so.prefix}${name}.${so.extension}" />
file="${objdir}/java/webclient/src_moz/${so.prefix}${name}.${jni.extension}" />
</target>

Просмотреть файл

@ -107,7 +107,7 @@
executable="make"/>
<exec os="Windows 2000" dir="${objdir.native.path}/jni" executable="make"
failonerror="yes"/>
<exec os="Mac OS X" dir="${objdir.native.path}/src" failonerror="yes"
<exec os="Mac OS X" dir="${objdir.native.path}/jni" failonerror="yes"
executable="make"/>
</target>
@ -176,6 +176,12 @@
<arg line="clobber_all"/>
</exec>
<exec os="Mac OS X" dir="${objdir.native.path}/jni" failonerror="yes"
executable="make">
<arg line="clobber_all"/>
</exec>
<delete>
<fileset dir="" includes="**/*.ilk"/>
</delete>

Просмотреть файл

@ -194,7 +194,7 @@
<mkdir dir="${objdir.native.path}/src_moz/cocoa" />
<javah destdir="${objdir.native.path}/src_moz/cocoa"
class="org.mozilla.webclient.impl.wrapper_native.CocoaBrowserControlCanvas">
class="org.mozilla.webclient.impl.wrapper_native.CocoaBrowserControlCanvas,org.mozilla.webclient.impl.wrapper_native.CocoaAppKitThreadDelegatingNativeEventThread">
<classpath refid="compile.classpath"/>
</javah>
@ -343,6 +343,12 @@ ${myenv.MOZ_JDKHOME}/bin/java ${debug.options} org.mozilla.webclient.test.Embedd
failonerror="yes">
<arg line="clobber_all"/>
</exec>
<exec os="Mac OS X" dir="${objdir.native.path}/src_moz" executable="make"
failonerror="yes">
<arg line="clobber_all"/>
</exec>
<exec os="Windows 2000" dir="${objdir.native.path}/src_ie" executable="make"
failonerror="yes">
<arg line="clobber_all"/>

Просмотреть файл

@ -53,7 +53,7 @@ import java.awt.event.*;
* See concrete subclasses for scope info.
* @version $Id: BrowserControlCanvas.java,v 1.9 2004-12-01 03:21:22 edburns%acm.org Exp $
* @version $Id: BrowserControlCanvas.java,v 1.10 2007-06-10 16:24:11 edburns%acm.org Exp $
* @see org.mozilla.webclient.win32.Win32BrowserControlCanvas
@ -141,25 +141,30 @@ public void addNotify ()
super.addNotify();
windowRelativeBounds = new Rectangle();
if (0 != nativeWindow) {
return;
}
synchronized (getTreeLock()) {
//Create the Native gtkWindow and it's container and
//get a handle to this widget
nativeWindow = getWindow();
//Create the Native gtkWindow and it's container and
//get a handle to this widget
nativeWindow = getWindow();
try {
Rectangle r = new Rectangle(getBoundsRelativeToWindow());
Assert.assert_it(null != webShell);
try {
Rectangle r = new Rectangle(getBoundsRelativeToWindow());
Assert.assert_it(null != webShell);
WindowControl wc = (WindowControl)
webShell.queryInterface(BrowserControl.WINDOW_CONTROL_NAME);
//This createWindow call sets in motion the creation of the
//nativeInitContext and the creation of the Mozilla embedded
//webBrowser
wc.createWindow(nativeWindow, r);
} catch (Exception e) {
System.out.println(e.toString());
return;
}
WindowControl wc = (WindowControl)
webShell.queryInterface(BrowserControl.WINDOW_CONTROL_NAME);
//This createWindow call sets in motion the creation of the
//nativeInitContext and the creation of the Mozilla embedded
//webBrowser
wc.createWindow(nativeWindow, r);
} catch (Exception e) {
System.out.println(e.toString());
return;
}
}
initializeOK = true;
webShellCount++;

Просмотреть файл

@ -0,0 +1,154 @@
/*
* 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 RaptorCanvas.
*
* The Initial Developer of the Original Code is Kirk Baker and
* Ian Wilkinson. Portions created by Kirk Baker and Ian Wilkinson are
* Copyright (C) 1999 Kirk Baker and Ian Wilkinson. All
* Rights Reserved.
*
* Contributor(s): Ed Burns <edburns@acm.org>
* Ashutosh Kulkarni <ashuk@eng.sun.com>
* Jason Mawdsley <jason@macadamian.com>
* Louis-Philippe Gagnon <louisphilippe@macadamian.com>
*/
package org.mozilla.webclient.impl.wrapper_native;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.mozilla.util.Log;
import org.mozilla.util.ReturnRunnable;
import org.mozilla.webclient.impl.WrapperFactory;
/**
*
* @author edburns
*/
public class CocoaAppKitThreadDelegatingNativeEventThread extends NativeEventThread {
public static final String LOG = "org.mozilla.webclient.impl.wrapper_native.CocoaAppKitThreadDelegatingNativeEventThread";
public static final Logger LOGGER = Log.getLogger(LOG);
Thread appKitThread = null;
/** Creates a new instance of CocoaAppKitThreadDelegatingNativeEventThread */
public CocoaAppKitThreadDelegatingNativeEventThread(String threadName,
WrapperFactory yourFactory) {
super(threadName, yourFactory);
instance = this;
}
public boolean isNativeEventThread() {
return (Thread.currentThread() == appKitThread);
}
public Object pushBlockingReturnRunnable(ReturnRunnable toInvoke) throws RuntimeException {
Object result = null;
if (isNativeEventThread()){
toInvoke.setResult(toInvoke.run());
result = toInvoke.getResult();
if (result instanceof RuntimeException) {
throw ((RuntimeException) result);
}
return result;
}
final ReturnRunnable finalToInvoke = toInvoke;
ReturnRunnable appKitToInvoke = new ReturnRunnable() {
public Object run() {
if (LOGGER.isLoggable(Level.FINEST)) {
LOGGER.finest("On NativeEventThread, blocking, about to call " +
finalToInvoke.toString() + " on AppKit Thread.");
}
Object result = CocoaAppKitThreadDelegatingNativeEventThread.this.
runReturnRunnableOnAppKitThread(finalToInvoke);
if (LOGGER.isLoggable(Level.FINEST)) {
LOGGER.finest("On NativeEventThread, blocking, returned from calling " +
finalToInvoke.toString() + " on AppKit Thread.");
}
return result;
}
public String toString() {
return finalToInvoke.toString();
}
};
result = super.pushBlockingReturnRunnable(appKitToInvoke);
return result;
}
public void pushRunnable(Runnable toInvoke) {
final Runnable finalToInvoke = toInvoke;
Runnable appKitToInvoke = new Runnable() {
public void run() {
if (LOGGER.isLoggable(Level.FINEST)) {
LOGGER.finest("On NativeEventThread, non-blocking, about to call " +
finalToInvoke.toString() + " on AppKit Thread.");
}
CocoaAppKitThreadDelegatingNativeEventThread.this.
runRunnableOnAppKitThread(finalToInvoke);
if (LOGGER.isLoggable(Level.FINEST)) {
LOGGER.finest("On NativeEventThread, non-blocking, returned from calling " +
finalToInvoke.toString() + " on AppKit Thread.");
}
}
public String toString() {
return finalToInvoke.toString();
}
};
super.pushRunnable(appKitToInvoke);
}
private Object doRunReturnRunnableOnAppKitThread(ReturnRunnable toInvoke) {
assert(-1 != Thread.currentThread().getName().indexOf("AppKit"));
if (null == appKitThread) {
appKitThread = Thread.currentThread();
}
if (LOGGER.isLoggable(Level.FINEST)) {
LOGGER.finest("On AppKitThread, blocking, about to call " +
toInvoke.toString() + ".");
}
Object result = toInvoke.run();
if (LOGGER.isLoggable(Level.FINEST)) {
LOGGER.finest("On AppKitThread, returned from calling " +
toInvoke.toString() + ".");
}
return result;
}
private void doRunRunnableOnAppKitThread(Runnable toInvoke) {
assert(-1 != Thread.currentThread().getName().indexOf("AppKit"));
if (null == appKitThread) {
appKitThread = Thread.currentThread();
}
if (LOGGER.isLoggable(Level.FINEST)) {
LOGGER.finest("On AppKitThread, non-blocking, about to call " +
toInvoke.toString() + ".");
}
toInvoke.run();
if (LOGGER.isLoggable(Level.FINEST)) {
LOGGER.finest("On AppKitThread, non-blocking, returned from calling " +
toInvoke.toString() + ".");
}
}
private native Object runReturnRunnableOnAppKitThread(ReturnRunnable toInvoke);
private native void runRunnableOnAppKitThread(Runnable toInvoke);
}

Просмотреть файл

@ -28,10 +28,11 @@ package org.mozilla.webclient.impl.wrapper_native;
import org.mozilla.webclient.BrowserControlCanvas;
import org.mozilla.util.ReturnRunnable;
import org.mozilla.webclient.impl.wrapper_native.NativeEventThread;
import java.awt.*;
import java.util.logging.Logger;
import org.mozilla.util.Log;
import org.mozilla.util.ReturnRunnable;
import org.mozilla.webclient.impl.WrapperFactory;
/**
*
@ -39,13 +40,20 @@ import java.awt.*;
*/
public class CocoaBrowserControlCanvas extends BrowserControlCanvas {
public static final String LOG = "org.mozilla.webclient.impl.wrapper_native.CocoaBrowserControlCanvas";
public static final Logger LOGGER = Log.getLogger(LOG);
/** Creates a new instance of CocoaBrowserControlCanvas */
public CocoaBrowserControlCanvas() {
}
//New method for obtaining access to the Native Peer handle
private native int getHandleToPeer();
private native void paintMe(Graphics g);
private boolean didGetWindow = false;
private int nativeView = 0;
/**
* Obtain the native window handle for this
@ -54,40 +62,29 @@ public class CocoaBrowserControlCanvas extends BrowserControlCanvas {
* @returns The native window handle.
*/
protected int getWindow() {
Integer result = (Integer)
NativeEventThread.instance.pushBlockingReturnRunnable(new ReturnRunnable(){
public Object run() {
Integer result =
new Integer(CocoaBrowserControlCanvas.this.getHandleToPeer());
return result;
}
public String toString() {
return "WCRunnable.getHandleToPeer";
}
if (!didGetWindow) {
Integer result = (Integer)
NativeEventThread.instance.pushBlockingReturnRunnable(new ReturnRunnable(){
public Object run() {
Integer result =
new Integer(CocoaBrowserControlCanvas.this.getHandleToPeer());
return result;
}
public String toString() {
return "WCRunnable.getHandleToPeer";
}
});
return result.intValue();
});
nativeView = result.intValue();
}
return nativeView;
}
public void paint(Graphics g) {
g.setColor(Color.green);
g.fillRect(0, 0, 100, 100);
g.setColor(Color.blue);
g.fillRect(5, 5, 90, 90);
// flush any outstanding graphics operations
Toolkit.getDefaultToolkit().sync();
// Call native code to render third (red) rect
paintMe(g);
g.setColor(Color.yellow);
g.fillRect(25, 25, 50, 50);
g.setColor(Color.black);
g.fillRect(40, 40, 20, 20);
public static NativeEventThread newNativeEventThread(WrapperFactory owner) {
NativeEventThread result = new CocoaAppKitThreadDelegatingNativeEventThread("WebclientEventThread",
owner);
return result;
}
}

Просмотреть файл

@ -100,7 +100,7 @@ protected int getNativeBrowserControl() {
}
protected boolean isNativeEventThread() {
return (Thread.currentThread() == NativeEventThread.instance);
return (NativeEventThread.instance.isNativeEventThread());
}

Просмотреть файл

@ -93,6 +93,10 @@ public class NativeEventThread extends Thread implements RunnableRunner {
runnables = new ConcurrentLinkedQueue<Runnable>();
}
public boolean isNativeEventThread() {
return (Thread.currentThread() == NativeEventThread.instance);
}
/**
*
* This is a very delicate method, and possibly subject to race
@ -146,6 +150,11 @@ public class NativeEventThread extends Thread implements RunnableRunner {
public void run()
{
// PENDING(edburns): On Mac OS X, the loading of native libraries
// should happen on the AppKit thread, at least in the case of embedding
// mozilla. To do this, you need to put the runOnAppKitThread functionality
// into its own native library, load that first, *then* on the AppKitThread
// load the other native libraries.
nativeWrapperFactory = wrapperFactory.loadNativeLibrariesIfNecessary();
// our owner must have put an event in the queue

Просмотреть файл

@ -142,9 +142,9 @@ else
ifeq ($(OS_ARCH),Darwin)
CMMSRCS = cocoa/CocoaBrowserControlCanvas.mm
CPPSRCS += cocoa/CocoaBrowserControlCanvasImpl.cpp
DLL_SUFFIX = .dylib
DLL_SUFFIX = .jnilib
#DSO_LDOPTS += -L/System/Library/Frameworks/JavaVM.Framework/Libraries -ljawt
DSO_LDOPTS += -framework JavaVM -framework AppKit -lobjc -L$(srcdir)/../src_share
DSO_LDOPTS += -framework JavaVM -framework AppKit -lobjc -L$(srcdir)/../src_share -framework Carbon
else
ifeq ($(OS_ARCH),WINNT)
CPPSRCS += \
@ -215,7 +215,8 @@ INCLUDES := -I$(MOZ_JDKHOME)/include -I$(MOZ_JDKHOME)/include/win32 $(INCLUDES)
-I$(srcdir)/../src_share -I../src_share -I. -I./win32
else
ifeq ($(OS_ARCH),Darwin)
INCLUDES := -I$(MOZ_JDKHOME)/include $(INCLUDES) -I$(srcdir)/../src_share -I../src_share -I. -I$(srcdir) -I$(srcdir)/cocoa -I./cocoa
INCLUDES := -I$(MOZ_JDKHOME)/include $(INCLUDES) -I$(srcdir)/../src_share -I../src_share -I. -I$(srcdir) -I$(srcdir)/cocoa -I./cocoa -I$(DIST)/include/plugin
CXXFLAGS += -fobjc-exceptions
else
INCLUDES := -I$(MOZ_JDKHOME)/include -I$(MOZ_JDKHOME)/include/solaris $(INCLUDES) \
-I$(DEPTH)/widget/src/gtk -I$(srcdir)/../src_share -I../src_share

Просмотреть файл

@ -37,6 +37,7 @@
#include "EmbedEventListener.h"
#include "NativeBrowserControl.h"
#include "ns_util.h"
#include "ns_globals.h"
// all of the crap that we need for event listeners
// and when chrome windows finish loading
@ -132,6 +133,10 @@ NativeBrowserControl::Realize(jobject javaBrowserControl,
void *parentWinPtr, PRBool *aAlreadyRealized,
PRUint32 width, PRUint32 height)
{
// parentWinPtr is whatever was returned from
// <platform>BrowserControlCanvas.getWindow().
nsresult rv = NS_OK;
mJavaBrowserControl = javaBrowserControl;
@ -147,10 +152,10 @@ NativeBrowserControl::Realize(jobject javaBrowserControl,
parentHWnd = ownerAsWidget;
width = ownerAsWidget->allocation.width;
height = ownerAsWidget->allocation.height;
#elif !defined(XP_MACOSX)
#elif defined(XP_PC)
parentHWnd = (HWND) parentWinPtr;
#else
parentHWnd = parentWinPtr;
#elif (defined(XP_MAC) || defined(XP_MACOSX)) && defined(MOZ_WIDGET_COCOA)
parentHWnd = (void *) parentWinPtr;
#endif
// create the window

Просмотреть файл

@ -108,9 +108,9 @@ public:
#if defined(XP_UNIX) &&!defined(XP_MACOSX)
GtkWidget * parentHWnd;
#elif defined(XP_MAC) || defined(XP_MACOSX)
#elif (defined(XP_MAC) || defined(XP_MACOSX))
void * parentHWnd;
#else !defined(XP_MACOSX)
#else
HWND parentHWnd;
#endif

Просмотреть файл

@ -41,6 +41,11 @@
#include <windows.h>
#endif
#if (defined(XP_MAC) || defined(XP_MACOSX)) && defined(MOZ_WIDGET_COCOA)
#include "CocoaBrowserControlCanvas.h"
#include "org_mozilla_webclient_impl_wrapper_0005fnative_CocoaAppKitThreadDelegatingNativeEventThread.h"
#endif
//#include "nsAppShellCIDs.h" // for NS_SESSIONHISTORY_CID
#include "nsCOMPtr.h" // to get nsIBaseWindow from webshell
//nsIDocShell is included in ns_util.h
@ -428,5 +433,43 @@ nsresult InitMozillaStuff (NativeBrowserControl * nativeBrowserControl)
return rv;
}
#if (defined(XP_MAC) || defined(XP_MACOSX)) && defined(MOZ_WIDGET_COCOA)
JNIEXPORT jobject JNICALL
Java_org_mozilla_webclient_impl_wrapper_1native_CocoaAppKitThreadDelegatingNativeEventThread_runReturnRunnableOnAppKitThread
(JNIEnv *env, jobject javaThis, jobject toInvoke)
{
jobject result = nsnull;
if (nsnull == javaThis || nsnull == toInvoke) {
::util_ThrowExceptionToJava(env, "CocoaAppKitThreadDelegatingNativeEventThread.runReturnRunnableOnAppKitThread: null arguments");
return;
}
result = CocoaBrowserControlCanvas::runReturnRunnableOnAppKitThread(env,
javaThis,
toInvoke);
return result;
}
JNIEXPORT void JNICALL
Java_org_mozilla_webclient_impl_wrapper_1native_CocoaAppKitThreadDelegatingNativeEventThread_runRunnableOnAppKitThread
(JNIEnv *env, jobject javaThis, jobject toInvoke)
{
// Store our pointer to the global vm
if (nsnull == gVm) { // declared in ../src_share/jni_util.h
::util_GetJavaVM(env, &gVm); // save this vm reference
}
if (nsnull == javaThis || nsnull == toInvoke) {
::util_ThrowExceptionToJava(env, "CocoaAppKitThreadDelegatingNativeEventThread.runReturnRunnableOnAppKitThread: null arguments");
return;
}
CocoaBrowserControlCanvas::runRunnableOnAppKitThread(env, javaThis,
toInvoke);
}
#endif

Просмотреть файл

@ -31,8 +31,11 @@ class CocoaBrowserControlCanvas {
public:
static jint cocoaGetHandleToPeer(JNIEnv *env, jobject canvas);
static void paintMe(JNIEnv *env, jobject canvas, jobject graphics);
static void cocoaPaint(JNIEnv *env, jobject canvas, jobject graphics);
static jobject runReturnRunnableOnAppKitThread(JNIEnv *env, jobject javaThis,
jobject toInvoke);
static void runRunnableOnAppKitThread(JNIEnv *env, jobject javaThis,
jobject toInvoke);
};
#endif

Просмотреть файл

@ -31,11 +31,85 @@
#import <Cocoa/Cocoa.h>
// #include <MacWindows.h>
#include "CocoaBrowserControlCanvas.h"
#include "jni_util.h" //for throwing Exceptions to Java
#include "nsIWidget.h"
#include "nsWidgetSupport.h"
jint CocoaBrowserControlCanvas::cocoaGetHandleToPeer(JNIEnv *env, jobject canvas) {
#include "jni_util.h" //for throwing Exceptions to Java
#include "ns_globals.h"
// #include "nsRect.h"
@interface RunOnAppKitThread : NSObject
-(void)runReturnRunnableOnAppKitThread:(NSMutableArray *) args;
-(void)doRunReturnRunnableOnAppKitThread:(NSMutableArray *) args;
-(void)runRunnableOnAppKitThread:(NSMutableArray *) args;
-(void)doRunRunnableOnAppKitThread:(NSMutableArray *) args;
@end
@implementation RunOnAppKitThread
-(void)runReturnRunnableOnAppKitThread:(NSMutableArray *)args {
[self performSelectorOnMainThread: @selector(doRunReturnRunnableOnAppKitThread:)
withObject: args
waitUntilDone: YES];
}
-(void)doRunReturnRunnableOnAppKitThread:(NSMutableArray *) args {
JNIEnv *env = (JNIEnv *) JNU_GetEnv(gVm, JNI_VERSION);
jobject
javaThis = (jobject) [[args objectAtIndex:0] pointerValue],
toInvoke = (jobject) [[args objectAtIndex:1] pointerValue],
result = nsnull;
NSValue *nsValue = nsnull;
jclass clazz = env->GetObjectClass(javaThis);
jmethodID mid = env->GetMethodID(clazz, "doRunReturnRunnableOnAppKitThread",
"(Lorg/mozilla/util/ReturnRunnable;)Ljava/lang/Object;");
result = env->CallObjectMethod(javaThis, mid, toInvoke);
if (env->ExceptionOccurred()) {
::util_ThrowExceptionToJava(env, "Cannot call back into Java");
}
nsValue = [NSValue value:&result withObjCType:@encode(jobject)];
[args addObject: nsValue];
return;
}
-(void)runRunnableOnAppKitThread:(NSMutableArray *)args {
[self performSelectorOnMainThread: @selector(doRunRunnableOnAppKitThread:)
withObject: args
waitUntilDone: YES];
}
-(void)doRunRunnableOnAppKitThread:(NSMutableArray *) args {
JNIEnv *env = (JNIEnv *) JNU_GetEnv(gVm, JNI_VERSION);
jobject
javaThis = (jobject) [[args objectAtIndex:0] pointerValue],
toInvoke = (jobject) [[args objectAtIndex:1] pointerValue];
jclass clazz = env->GetObjectClass(javaThis);
jmethodID mid = env->GetMethodID(clazz, "doRunRunnableOnAppKitThread",
"(Ljava/lang/Runnable;)V");
env->CallVoidMethod(javaThis, mid, toInvoke);
if (env->ExceptionOccurred()) {
::util_ThrowExceptionToJava(env, "Cannot call back into Java");
}
return;
}
@end
jint CocoaBrowserControlCanvas::cocoaGetHandleToPeer(JNIEnv *env, jobject canvas)
{
JAWT awt;
JAWT_DrawingSurface* ds = NULL;
JAWT_DrawingSurfaceInfo* dsi = NULL;
@ -43,14 +117,17 @@ jint CocoaBrowserControlCanvas::cocoaGetHandleToPeer(JNIEnv *env, jobject canvas
jboolean result = JNI_FALSE;
jint lock = 0;
NSView *view = NULL;
NSWindow *win = NULL;
void * windowPtr = NULL;
// get the AWT
awt.version = JAWT_VERSION_1_4;
result = JAWT_GetAWT(env, &awt);
if (JNI_FALSE == result) {
util_ThrowExceptionToJava(env, "CocoaBrowserControlCanvas: can't get JAWT");
}
// Get the drawing surface. This can be safely cached.
// Anything below the DS (DSI, contexts, etc)
// can possibly change/go away and should not be cached.
@ -78,18 +155,23 @@ jint CocoaBrowserControlCanvas::cocoaGetHandleToPeer(JNIEnv *env, jobject canvas
// Get the platform-specific drawing info
// We will use this to get at Cocoa and CoreGraphics
// See <JavaVM/jawt_md.h>
dsi_mac = (JAWT_MacOSXDrawingSurfaceInfo*)dsi->platformInfo;
if (NULL == dsi_mac) {
util_ThrowExceptionToJava(env, "CocoaBrowserControlCanvas: can't get DrawingSurfaceInfo");
util_ThrowExceptionToJava(env, "CocoaBrowserControlCanvas: can't get mac DrawingSurfaceInfo");
}
// Get the corresponding peer from the caller canvas
view = dsi_mac->cocoaViewRef;
win = [view window];
windowPtr = [win windowRef];
// Free the DrawingSurfaceInfo
ds->FreeDrawingSurfaceInfo(dsi);
}
else {
PR_LOG(prLogModuleInfo, PR_LOG_DEBUG,
("CocoaBrowserControlCanvas::cocoaGetHandleToPeer: can't get drawing surface info"));
}
// Unlock the drawing surface
// You must unlock EACH TIME when done drawing
@ -98,98 +180,71 @@ jint CocoaBrowserControlCanvas::cocoaGetHandleToPeer(JNIEnv *env, jobject canvas
// Free the drawing surface (if not caching it)
awt.FreeDrawingSurface(ds);
printf("debug: edburns: CocoaBC: winPtr: %p\n", windowPtr);
fflush(stdout);
return (jint) windowPtr;
return (jint) view;
}
jobject CocoaBrowserControlCanvas::runReturnRunnableOnAppKitThread(JNIEnv *env, jobject javaThis, jobject toInvoke)
{
PR_ASSERT(javaThis);
PR_ASSERT(toInvoke);
void CocoaBrowserControlCanvas::paintMe(JNIEnv *env, jobject canvas, jobject graphics) {
jobject result = 0;
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
JAWT awt;
JAWT_DrawingSurface* ds = NULL;
JAWT_DrawingSurfaceInfo* dsi = NULL;
JAWT_MacOSXDrawingSurfaceInfo* dsi_mac = NULL;
jboolean result = JNI_FALSE;
jint lock = 0;
jclass bcClass;
jmethodID mid;
// get the AWT
awt.version = JAWT_VERSION_1_4;
result = JAWT_GetAWT(env, &awt);
if (env->ExceptionOccurred()) {
env->ExceptionDescribe();
}
assert(result != JNI_FALSE);
// Get the drawing surface. This can be safely cached.
// Anything below the DS (DSI, contexts, etc)
// can possibly change/go away and should not be cached.
ds = awt.GetDrawingSurface(env, canvas);
if (env->ExceptionOccurred()) {
env->ExceptionDescribe();
}
assert(ds != NULL);
// Lock the drawing surface
// You must lock EACH TIME before drawing
lock = ds->Lock(ds);
if (env->ExceptionOccurred()) {
env->ExceptionDescribe();
}
assert((lock & JAWT_LOCK_ERROR) == 0);
// Get the drawing surface info
dsi = ds->GetDrawingSurfaceInfo(ds);
// Check DrawingSurfaceInfo. This can be NULL on Mac OS X
// if the windowing system is not ready
if (dsi != NULL) {
// Get the platform-specific drawing info
// We will use this to get at Cocoa and CoreGraphics
// See <JavaVM/jawt_md.h>
dsi_mac = (JAWT_MacOSXDrawingSurfaceInfo*)dsi->platformInfo;
if (env->ExceptionOccurred()) {
env->ExceptionDescribe();
}
// Get the corresponding peer from the caller canvas
NSView *view = dsi_mac->cocoaViewRef;
// Get the CoreGraphics context from the parent window.
// DO NOT CACHE NSGraphicsContexts -- they may go away.
NSWindow *window = [view window];
NSGraphicsContext *ctxt = [NSGraphicsContext graphicsContextWithWindow:window];
CGContextRef cg = [ctxt graphicsPort];
// Match Java's ctm
NSRect windowRect = [window frame];
CGContextConcatCTM(cg, CGAffineTransformMake(1, 0, 0, -1, dsi->bounds.x, windowRect.size.height-dsi->bounds.y));
// Draw a pattern using CoreGraphics
CGContextSetRGBFillColor(cg, 1.0f, 0.0f, 0.0f, 1.0f);
CGContextFillRect(cg, CGRectMake(15, 15, dsi->bounds.width-30, dsi->bounds.height-30));
// Free the DrawingSurfaceInfo
ds->FreeDrawingSurfaceInfo(dsi);
if (env->ExceptionOccurred()){
env->ExceptionDescribe();
RunOnAppKitThread *appKitThreadRunner = [[RunOnAppKitThread alloc] init];
NSMutableArray *args = [NSMutableArray arrayWithCapacity: 10];
NSValue
*inArg0 = [NSValue value:&javaThis withObjCType:@encode(jobject)],
*inArg1 = [NSValue value:&toInvoke withObjCType:@encode(jobject)],
*outArg0;
[args addObject: inArg0];
[args addObject: inArg1];
@try {
[appKitThreadRunner runReturnRunnableOnAppKitThread: args];
outArg0 = [args objectAtIndex:2];
if (outArg0) {
result = (jobject) [outArg0 pointerValue];
}
}
// Unlock the drawing surface
// You must unlock EACH TIME when done drawing
ds->Unlock(ds);
if (env->ExceptionOccurred()) {
env->ExceptionDescribe();
}
// Free the drawing surface (if not caching it)
awt.FreeDrawingSurface(ds);
if (env->ExceptionOccurred()) {
env->ExceptionDescribe();
@catch (NSException *e) {
NSString *reason = [e reason];
const char *cStringReason = [reason cStringUsingEncoding:
NSUTF8StringEncoding];
JNIEnv *env = (JNIEnv *) JNU_GetEnv(gVm, JNI_VERSION);
::util_ThrowExceptionToJava(env, cStringReason);
}
[pool release];
return result;
}
void CocoaBrowserControlCanvas::runRunnableOnAppKitThread(JNIEnv *env, jobject javaThis, jobject toInvoke)
{
PR_ASSERT(javaThis);
PR_ASSERT(toInvoke);
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
RunOnAppKitThread *appKitThreadRunner = [[RunOnAppKitThread alloc] init];
NSMutableArray *args = [NSMutableArray arrayWithCapacity: 10];
NSValue
*inArg0 = [NSValue value:&javaThis withObjCType:@encode(jobject)],
*inArg1 = [NSValue value:&toInvoke withObjCType:@encode(jobject)];
[args addObject: inArg0];
[args addObject: inArg1];
@try {
[appKitThreadRunner runRunnableOnAppKitThread: args];
}
@catch (NSException *e) {
NSString *reason = [e reason];
const char *cStringReason = [reason cStringUsingEncoding:
NSUTF8StringEncoding];
PR_LOG(prLogModuleInfo, PR_LOG_DEBUG,
("CocoaBrowserControlCanvas::runRunnableOnAppKitThread: Native Cocoa Exception occurred: %s", cStringReason));
JNIEnv *env = (JNIEnv *) JNU_GetEnv(gVm, JNI_VERSION);
::util_ThrowExceptionToJava(env, cStringReason);
}
[pool release];
}

Просмотреть файл

@ -44,7 +44,3 @@ JNIEXPORT jint JNICALL Java_org_mozilla_webclient_impl_wrapper_1native_CocoaBrow
result = CocoaBrowserControlCanvas::cocoaGetHandleToPeer(env, canvas);
return result;
}
JNIEXPORT void JNICALL Java_org_mozilla_webclient_impl_wrapper_1native_CocoaBrowserControlCanvas_paintMe(JNIEnv *env, jobject canvas, jobject graphics) {
CocoaBrowserControlCanvas::paintMe(env, canvas, graphics);
}

Просмотреть файл

@ -371,25 +371,29 @@ public class TestBrowser extends JPanel {
//System.out.println("Meta ");
}
Node domNode = (Node)
wcMouseEvent.getWebclientEvent().getSource();
Element element = (Element) domNode;
String
href = (String) eventProps.get("href"),
id = element.getAttribute("id"),
name = element.getAttribute("name"),
nodeName = domNode.getNodeName(),
value = domNode.getNodeValue(),
status = "";
if (null != href) {
// PENDING(edburns): take care of relative URL
status = href;
}
if (null != id || null != name || null != nodeName
|| null != value) {
status = status + " domNode: " + nodeName + " id: " + id
+ " name: " + name + " value: " + value;
updateStatusInfo(status);
Object source = wcMouseEvent.getWebclientEvent().getSource();
if (source instanceof Node) {
Node domNode = (Node) source;
Element element = (Element) domNode;
String
href = (String) eventProps.get("href"),
id = element.getAttribute("id"),
name = element.getAttribute("name"),
nodeName = domNode.getNodeName(),
value = domNode.getNodeValue(),
status = "";
if (null != href) {
// PENDING(edburns): take care of relative URL
status = href;
}
if (null != id || null != name || null != nodeName
|| null != value) {
status = status + " domNode: " + nodeName + " id: " + id
+ " name: " + name + " value: " + value;
updateStatusInfo(status);
}
}
}
}
@ -440,7 +444,8 @@ public class TestBrowser extends JPanel {
// Check if the text value starts with known protocols.
if (inputValue.toLowerCase().startsWith("http://")
|| inputValue.toLowerCase().startsWith("ftp://")
|| inputValue.toLowerCase().startsWith("gopher://")) {
|| inputValue.toLowerCase().startsWith("gopher://")
|| inputValue.toLowerCase().startsWith("file://")) {
curUrl = new URL(inputValue);
} else {
if (inputValue.toLowerCase().startsWith("ftp.")) {