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 }