blob: 4a696e9146eec984a7edbe6088a3e5b69e24c67b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2003, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.swt.browser;
import java.util.Hashtable;
import org.eclipse.swt.SWT;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.internal.*;
import org.eclipse.swt.internal.carbon.*;
import org.eclipse.swt.internal.cocoa.*;
import org.eclipse.swt.widgets.*;
class MozillaDelegate {
Browser browser;
Listener listener;
boolean hasFocus;
static Callback Callback3;
static Hashtable handles = new Hashtable ();
MozillaDelegate (Browser browser) {
super ();
this.browser = browser;
}
static Browser findBrowser (int handle) {
LONG value = (LONG)handles.get (new LONG (handle));
if (value != null) {
Display display = Display.getCurrent ();
return (Browser)display.findWidget (value.value);
}
return null;
}
static char[] mbcsToWcs (String codePage, byte [] buffer) {
int encoding = OS.CFStringGetSystemEncoding ();
int cfstring = OS.CFStringCreateWithBytes (OS.kCFAllocatorDefault, buffer, buffer.length, encoding, false);
char[] chars = null;
if (cfstring != 0) {
int length = OS.CFStringGetLength (cfstring);
chars = new char [length];
if (length != 0) {
CFRange range = new CFRange ();
range.length = length;
OS.CFStringGetCharacters (cfstring, range, chars);
}
OS.CFRelease (cfstring);
}
return chars;
}
static byte[] wcsToMbcs (String codePage, String string, boolean terminate) {
char[] chars = new char [string.length()];
string.getChars (0, chars.length, chars, 0);
int cfstring = OS.CFStringCreateWithCharacters (OS.kCFAllocatorDefault, chars, chars.length);
byte[] buffer = null;
if (cfstring != 0) {
CFRange range = new CFRange ();
range.length = chars.length;
int encoding = OS.CFStringGetSystemEncoding ();
int[] size = new int[1];
int numChars = OS.CFStringGetBytes (cfstring, range, encoding, (byte)'?', true, null, 0, size);
buffer = new byte [size[0] + (terminate ? 1 : 0)];
if (numChars != 0) {
numChars = OS.CFStringGetBytes (cfstring, range, encoding, (byte)'?', true, buffer, size[0], size);
}
OS.CFRelease (cfstring);
}
return buffer;
}
static int eventProc3 (int nextHandler, int theEvent, int userData) {
Widget widget = Display.getCurrent ().findWidget (userData);
if (widget instanceof Browser) {
Browser browser = (Browser) widget;
switch (OS.GetEventClass (theEvent)) {
case OS.kEventClassMouse:
browser.getShell ().forceActive ();
((Mozilla)browser.webBrowser).Activate ();
break;
case OS.kEventClassKeyboard:
/*
* Bug in Carbon. OSX crashes if a HICocoaView is disposed during a key event,
* presumably as a result of attempting to use it after its refcount has reached
* 0. The workaround is to temporarily add an extra ref to the view while the
* DOM listener is handling the event, in case the Browser gets disposed in a
* callback.
*/
int handle = browser.handle;
OS.CFRetain (handle);
int result = OS.CallNextEventHandler (nextHandler, theEvent);
OS.CFRelease (handle);
return result;
}
}
return OS.eventNotHandledErr;
}
int getHandle () {
int embedHandle = Cocoa.objc_msgSend (Cocoa.C_NSImageView, Cocoa.S_alloc);
if (embedHandle == 0) {
browser.dispose ();
SWT.error (SWT.ERROR_NO_HANDLES);
}
NSRect r = new NSRect ();
embedHandle = Cocoa.objc_msgSend (embedHandle, Cocoa.S_initWithFrame, r);
int rc;
int[] outControl = new int[1];
rc = Cocoa.HICocoaViewCreate (embedHandle, 0, outControl); /* OSX >= 10.5 */
if (rc == OS.noErr && outControl[0] != 0) {
Cocoa.objc_msgSend (embedHandle, Cocoa.S_release);
} else {
/* will succeed on OSX 10.4 with an updated vm containing HIJavaViewCreateWithCocoaView */
try {
System.loadLibrary ("frameembedding"); //$NON-NLS-1$
} catch (UnsatisfiedLinkError e) {}
rc = Cocoa.HIJavaViewCreateWithCocoaView (outControl, embedHandle);
if (!(rc == OS.noErr && outControl[0] != 0)) {
browser.dispose ();
SWT.error (SWT.ERROR_NO_HANDLES);
}
}
int subHIView = outControl[0];
HILayoutInfo newLayoutInfo = new HILayoutInfo ();
newLayoutInfo.version = 0;
OS.HIViewGetLayoutInfo (subHIView, newLayoutInfo);
HISideBinding biding = newLayoutInfo.binding.top;
biding.toView = 0;
biding.kind = OS.kHILayoutBindMin;
biding.offset = 0;
biding = newLayoutInfo.binding.left;
biding.toView = 0;
biding.kind = OS.kHILayoutBindMin;
biding.offset = 0;
biding = newLayoutInfo.binding.bottom;
biding.toView = 0;
biding.kind = OS.kHILayoutBindMax;
biding.offset = 0;
biding = newLayoutInfo.binding.right;
biding.toView = 0;
biding.kind = OS.kHILayoutBindMax;
biding.offset = 0;
OS.HIViewSetLayoutInfo (subHIView, newLayoutInfo);
OS.HIViewChangeFeatures (subHIView, OS.kHIViewFeatureIsOpaque, 0);
OS.HIViewSetVisible (subHIView, true);
int parentHandle = browser.handle;
OS.HIViewAddSubview (browser.handle, subHIView);
CGRect rect = new CGRect ();
OS.HIViewGetFrame (parentHandle, rect);
rect.x = rect.y = 0;
OS.HIViewSetFrame (subHIView, rect);
handles.put (new LONG (embedHandle), new LONG (browser.handle));
if (Callback3 == null) Callback3 = new Callback (this.getClass (), "eventProc3", 3); //$NON-NLS-1$
int callback3Address = Callback3.getAddress ();
if (callback3Address == 0) {
browser.dispose ();
SWT.error (SWT.ERROR_NO_MORE_CALLBACKS);
}
int [] mask = new int [] {
OS.kEventClassMouse, OS.kEventMouseDown,
OS.kEventClassKeyboard, OS.kEventRawKeyDown,
};
int controlTarget = OS.GetControlEventTarget (subHIView);
OS.InstallEventHandler (controlTarget, callback3Address, mask.length / 2, mask, browser.handle, null);
return embedHandle;
}
String getLibraryName () {
return "libxpcom.dylib"; //$NON-NLS-1$
}
String getSWTInitLibraryName () {
return "swt-xulrunner"; //$NON-NLS-1$
}
void handleFocus () {
if (hasFocus) return;
hasFocus = true;
((Mozilla)browser.webBrowser).Activate ();
browser.setFocus ();
listener = new Listener () {
public void handleEvent (Event event) {
if (event.widget == browser) return;
((Mozilla)browser.webBrowser).Deactivate ();
hasFocus = false;
browser.getDisplay ().removeFilter (SWT.FocusIn, this);
browser.getShell ().removeListener (SWT.Deactivate, this);
listener = null;
}
};
browser.getDisplay ().addFilter (SWT.FocusIn, listener);
browser.getShell ().addListener (SWT.Deactivate, listener);
}
void handleMouseDown () {
}
boolean hookEnterExit () {
return true;
}
void init () {
}
boolean needsSpinup () {
return false;
}
void onDispose (int embedHandle) {
handles.remove (new LONG (embedHandle));
if (listener != null) {
browser.getDisplay ().removeFilter (SWT.FocusIn, listener);
browser.getShell ().removeListener (SWT.Deactivate, listener);
listener = null;
}
browser = null;
}
void setSize (int embedHandle, int width, int height) {
// TODO
}
}