1 /******************************************************************************* 2 * Copyright (c) 2003, 2007 IBM Corporation and others. 3 * All rights reserved. This program and the accompanying materials 4 * are made available under the terms of the Eclipse Public License v1.0 5 * which accompanies this distribution, and is available at 6 * http://www.eclipse.org/legal/epl-v10.html 7 * 8 * Contributors: 9 * IBM Corporation - initial API and implementation 10 * Port to the D programming language: 11 * John Reimer <terminal.node@gmail.com> 12 *******************************************************************************/ 13 module org.eclipse.swt.browser.MozillaDelegate; 14 15 import java.lang.all; 16 17 version(Tango){ 18 import tango.io.Console; 19 } else { // Phobos 20 } 21 22 import org.eclipse.swt.SWT; 23 import org.eclipse.swt.internal.Converter; 24 import org.eclipse.swt.internal.gtk.OS; 25 import org.eclipse.swt.widgets.Display; 26 import org.eclipse.swt.widgets.Event; 27 import org.eclipse.swt.widgets.Listener; 28 import org.eclipse.swt.widgets.Widget; 29 30 import org.eclipse.swt.browser.Browser; 31 import org.eclipse.swt.browser.Mozilla; 32 33 //import org.eclipse.swt.internal.c.glib_object; 34 35 class MozillaDelegate { 36 Browser browser; 37 gpointer mozillaHandle; 38 GtkWidget* embedHandle; 39 bool hasFocus; 40 Listener listener; 41 //static Callback eventCallback; 42 // static ptrdiff_t eventProc; 43 static const gpointer STOP_PROPOGATE = cast(gpointer)1; 44 static bool IsLinux; 45 46 static this () { 47 String osName = System.getProperty ("os.name").toLowerCase(); //$NON-NLS-1$ 48 IsLinux = osName.startsWith("linux"); //$NON-NLS-1$ 49 } 50 51 this (Browser browser) { 52 //super (); 53 if (!IsLinux) { 54 browser.dispose (); 55 SWT.error (SWT.ERROR_NO_HANDLES, null, " [Unsupported platform]"); //$NON-NLS-1$ 56 } 57 this.browser = browser; 58 } 59 60 static extern(System) int eventProc (GtkWidget* handle, GdkEvent* gdkEvent, gpointer pointer) { 61 GtkWidget* parent = OS.gtk_widget_get_parent (handle); 62 parent = OS.gtk_widget_get_parent (parent); 63 if (parent is null) return 0; 64 Widget widget = Display.getCurrent ().findWidget (parent); 65 if (widget !is null && (cast(Browser)widget) !is null) { 66 return (cast(Mozilla)(cast(Browser)widget).webBrowser).mozDelegate.gtk_event (handle, gdkEvent, pointer); 67 } 68 return 0; 69 } 70 71 static Browser findBrowser (GtkWidget* handle) { 72 /* 73 * Note. On GTK, Mozilla is embedded into a GtkHBox handle 74 * and not directly into the parent Composite handle. 75 */ 76 GtkWidget* parent = OS.gtk_widget_get_parent (handle); 77 Display display = Display.getCurrent (); 78 return cast(Browser)display.findWidget (parent); 79 } 80 /* 81 static char[] mbcsToWcs (String codePage, byte [] buffer) { 82 return Converter.mbcsToWcs (codePage, buffer); 83 } 84 85 static byte[] wcsToMbcs (String codePage, String string, bool terminate) { 86 return Converter.wcsToMbcs (codePage, string, terminate); 87 } 88 */ 89 GtkWidget* getHandle () { 90 /* 91 * Bug in Mozilla Linux GTK. Embedding Mozilla into a GtkFixed 92 * handle causes problems with some Mozilla plug-ins. For some 93 * reason, the Flash plug-in causes the child of the GtkFixed 94 * handle to be resized to 1 when the Flash document is loaded. 95 * That could be due to gtk_container_resize_children being called 96 * by Mozilla - or one of its plug-ins - on the GtkFixed handle, 97 * causing the child of the GtkFixed handle to be resized to 1. 98 * The workaround is to embed Mozilla into a GtkHBox handle. 99 */ 100 embedHandle = OS.gtk_hbox_new (false, 0); 101 OS.gtk_container_add (browser.handle, embedHandle); 102 OS.gtk_widget_show (embedHandle); 103 return embedHandle; 104 } 105 106 String getLibraryName () { 107 return "libxpcom.so"; //$NON-NLS-1$ 108 } 109 110 /* 111 String getSWTInitLibraryName () { 112 return "swt-xpcominit"; //$NON-NLS-1$ 113 } 114 */ 115 116 int gtk_event (GtkWidget* handle, GdkEvent* event, gpointer pointer) { 117 if (event.type is OS.GDK_BUTTON_PRESS) { 118 if (!hasFocus) browser.setFocus (); 119 } 120 121 /* 122 * Stop the propagation of events that are not consumed by Mozilla, before 123 * they reach the parent embedder. These event have already been received. 124 */ 125 if (pointer is STOP_PROPOGATE) return 1; 126 return 0; 127 } 128 129 void handleFocus () { 130 if (hasFocus) return; 131 hasFocus = true; 132 listener = new class() Listener { 133 public void handleEvent (Event event) { 134 if (event.widget is browser) return; 135 (cast(Mozilla)(browser.webBrowser)).Deactivate (); 136 hasFocus = false; 137 browser.getDisplay ().removeFilter (SWT.FocusIn, this); 138 browser.getShell ().removeListener (SWT.Deactivate, this); 139 listener = null; 140 } 141 }; 142 browser.getDisplay ().addFilter (SWT.FocusIn, listener); 143 browser.getShell ().addListener (SWT.Deactivate, listener); 144 } 145 146 void handleMouseDown () { 147 int shellStyle = browser.getShell ().getStyle (); 148 if ((shellStyle & SWT.ON_TOP) !is 0 && (((shellStyle & SWT.NO_FOCUS) is 0) || ((browser.getStyle () & SWT.NO_FOCUS) is 0))) { 149 browser.getDisplay ().asyncExec (new class() Runnable { 150 public void run () { 151 if (browser is null || browser.isDisposed ()) return; 152 (cast(Mozilla)(browser.webBrowser)).Activate (); 153 } 154 }); 155 } 156 } 157 158 bool hookEnterExit () { 159 return false; 160 } 161 162 void init () { /* 163 if (eventCallback is null) { 164 eventCallback = new Callback (getClass (), "eventProc", 3); //$NON-NLS-1$ 165 eventProc = eventCallback.getAddress (); 166 if (eventProc is null) { 167 browser.dispose (); 168 Mozilla.error (SWT.ERROR_NO_MORE_CALLBACKS); 169 } 170 } */ 171 172 /* 173 * Feature in Mozilla. GtkEvents such as key down, key pressed may be consumed 174 * by Mozilla and never be received by the parent embedder. The workaround 175 * is to find the top Mozilla gtk widget that receives all the Mozilla GtkEvents, 176 * i.e. the first child of the parent embedder. Then hook event callbacks and 177 * forward the event to the parent embedder before Mozilla received and consumed 178 * them. 179 */ 180 GList* list = OS.gtk_container_get_children (embedHandle); 181 if (list !is null) { 182 mozillaHandle = OS.g_list_data (list); 183 OS.g_list_free (list); 184 185 if (mozillaHandle !is null) { 186 /* Note. Callback to get events before Mozilla receives and consumes them. */ 187 OS.g_signal_connect (mozillaHandle, OS.event.toStringz(), cast(GCallback)&eventProc, null); 188 189 /* 190 * Note. Callback to get the events not consumed by Mozilla - and to block 191 * them so that they don't get propagated to the parent handle twice. 192 * This hook is set after Mozilla and is therefore called after Mozilla's 193 * handler because GTK dispatches events in their order of registration. 194 */ 195 OS.g_signal_connect (mozillaHandle, OS.key_press_event.toStringz(), cast(GCallback)&eventProc, STOP_PROPOGATE); 196 OS.g_signal_connect (mozillaHandle, OS.key_release_event.toStringz(), cast(GCallback)&eventProc, STOP_PROPOGATE); 197 OS.g_signal_connect (mozillaHandle, OS.button_press_event.toStringz(), cast(GCallback)&eventProc, STOP_PROPOGATE); 198 } 199 } 200 } 201 202 bool needsSpinup () { 203 return true; 204 } 205 206 void onDispose (GtkWidget* embedHandle) { 207 if (listener !is null) { 208 browser.getDisplay ().removeFilter (SWT.FocusIn, listener); 209 browser.getShell ().removeListener (SWT.Deactivate, listener); 210 listener = null; 211 } 212 browser = null; 213 } 214 215 void setSize (GtkWidget* embedHandle, int width, int height) { 216 OS.gtk_widget_set_size_request (embedHandle, width, height); 217 } 218 219 }