Mercurial > projects > dwt-mac
comparison dwt/browser/Safari.d @ 0:380af2bdd8e5
Upload of whole dwt tree
author | Jacob Carlborg <doob@me.com> <jacob.carlborg@gmail.com> |
---|---|
date | Sat, 09 Aug 2008 17:00:02 +0200 |
parents | |
children | f565d3a95c0a |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:380af2bdd8e5 |
---|---|
1 /******************************************************************************* | |
2 * Copyright (c) 2000, 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 * | |
11 * Port to the D Programming language: | |
12 * Jacob Carlborg <jacob.carlborg@gmail.com> | |
13 *******************************************************************************/ | |
14 module dwt.browser.Safari; | |
15 | |
16 import dwt.DWT; | |
17 import dwt.browser.LocationEvent; | |
18 import dwt.browser.ProgressEvent; | |
19 import dwt.browser.ProgressListener; | |
20 import dwt.browser.StatusTextEvent; | |
21 import dwt.browser.TitleEvent; | |
22 import dwt.browser.TitleListener; | |
23 import dwt.browser.WebBrowser; | |
24 import dwt.dwthelper.utils; | |
25 import dwt.graphics.Point; | |
26 import dwt.graphics.Rectangle; | |
27 import dwt.internal.Callback; | |
28 import dwt.internal.cocoa.DOMDocument; | |
29 import dwt.internal.cocoa.DOMEvent; | |
30 import dwt.internal.cocoa.DOMKeyboardEvent; | |
31 import dwt.internal.cocoa.DOMMouseEvent; | |
32 import dwt.internal.cocoa.DOMWheelEvent; | |
33 import dwt.internal.cocoa.NSArray; | |
34 import dwt.internal.cocoa.NSDictionary; | |
35 import dwt.internal.cocoa.NSHTTPCookie; | |
36 import dwt.internal.cocoa.NSHTTPCookieStorage; | |
37 import dwt.internal.cocoa.NSNotificationCenter; | |
38 import dwt.internal.cocoa.NSNumber; | |
39 import dwt.internal.cocoa.NSPrintInfo; | |
40 import dwt.internal.cocoa.NSPrintOperation; | |
41 import dwt.internal.cocoa.NSString; | |
42 import dwt.internal.cocoa.NSURL; | |
43 import dwt.internal.cocoa.NSURLDownload; | |
44 import dwt.internal.cocoa.NSURLRequest; | |
45 import dwt.internal.cocoa.OS; | |
46 import dwt.internal.cocoa.DWTWebViewDelegate; | |
47 import dwt.internal.cocoa.WebDataSource; | |
48 import dwt.internal.cocoa.WebDocumentRepresentation; | |
49 import dwt.internal.cocoa.WebFrame; | |
50 import dwt.internal.cocoa.WebFrameView; | |
51 import dwt.internal.cocoa.WebOpenPanelResultListener; | |
52 import dwt.internal.cocoa.WebPolicyDecisionListener; | |
53 import dwt.internal.cocoa.WebPreferences; | |
54 import dwt.internal.cocoa.WebView; | |
55 import dwt.internal.cocoa.id; | |
56 | |
57 import dwt.widgets.Composite; | |
58 import dwt.widgets.Display; | |
59 import dwt.widgets.Event; | |
60 import dwt.widgets.FileDialog; | |
61 import dwt.widgets.Listener; | |
62 import dwt.widgets.Menu; | |
63 import dwt.widgets.MessageBox; | |
64 import dwt.widgets.Shell; | |
65 | |
66 import Math = tango.math.Math; | |
67 | |
68 import dwt.dwthelper.Runnable; | |
69 | |
70 class Safari : WebBrowser | |
71 { | |
72 WebView webView; | |
73 DWTWebViewDelegate delegatee; | |
74 int jniRef; | |
75 bool changingLocation; | |
76 String lastHoveredLinkURL; | |
77 String html; | |
78 int identifier; | |
79 int resourceCount; | |
80 String url = ""; | |
81 Point location; | |
82 Point size; | |
83 bool statusBar = true, toolBar = true, ignoreDispose; | |
84 int lastMouseMoveX, lastMouseMoveY; | |
85 //TEMPORARY CODE | |
86 // bool doit; | |
87 | |
88 static bool Initialized; | |
89 static Callback Callback2, Callback3, Callback4, Callback5, Callback6, Callback7; | |
90 | |
91 static const int MIN_SIZE = 16; | |
92 static const int MAX_PROGRESS = 100; | |
93 static const String WebElementLinkURLKey = "WebElementLinkURL"; //$NON-NLS-1$ | |
94 static const String AGENT_STRING = "Safari/unknown"; //$NON-NLS-1$ | |
95 static const String URI_FROMMEMORY = "file:///"; //$NON-NLS-1$ | |
96 static const String PROTOCOL_FILE = "file:"; //$NON-NLS-1$ | |
97 static const String PROTOCOL_HTTP = "http:"; //$NON-NLS-1$ | |
98 static const String ABOUT_BLANK = "about:blank"; //$NON-NLS-1$ | |
99 static const String SAFARI_EVENTS_FIX_KEY = "dwt.internal.safariEventsFix"; //$NON-NLS-1$ | |
100 | |
101 /* event Strings */ | |
102 static const String DOMEVENT_KEYUP = "keyup"; //$NON-NLS-1$ | |
103 static const String DOMEVENT_KEYDOWN = "keydown"; //$NON-NLS-1$ | |
104 static const String DOMEVENT_MOUSEDOWN = "mousedown"; //$NON-NLS-1$ | |
105 static const String DOMEVENT_MOUSEUP = "mouseup"; //$NON-NLS-1$ | |
106 static const String DOMEVENT_MOUSEMOVE = "mousemove"; //$NON-NLS-1$ | |
107 static const String DOMEVENT_MOUSEWHEEL = "mousewheel"; //$NON-NLS-1$ | |
108 | |
109 static this () | |
110 { | |
111 NativeClearSessions = new class Runnable | |
112 { | |
113 public void run () | |
114 { | |
115 NSHTTPCookieStorage storage = NSHTTPCookieStorage.sharedHTTPCookieStorage(); | |
116 NSArray cookies = storage.cookies(); | |
117 int count = cookies.count(); | |
118 | |
119 for (int i = 0; i < count; i++) | |
120 { | |
121 NSHTTPCookie cookie = new NSHTTPCookie(cookies.objectAtIndex(i)); | |
122 if (cookie.isSessionOnly()) | |
123 { | |
124 storage.deleteCookie(cookie); | |
125 } | |
126 } | |
127 } | |
128 }; | |
129 } | |
130 | |
131 public void create (Composite parent, int style) | |
132 { | |
133 | |
134 String className = "DWTWebViewDelegate"; | |
135 if (OS.objc_lookUpClass(className) == 0) | |
136 { | |
137 ClassInfo safaryClass = this.classinfo; | |
138 Callback2 = new Callback(safaryClass, "browserProc", 2); | |
139 int proc2 = Callback2.getAddress(); | |
140 if (proc2 is 0) | |
141 DWT.error(DWT.ERROR_NO_MORE_CALLBACKS); | |
142 Callback3 = new Callback(safaryClass, "browserProc", 3); | |
143 int proc3 = Callback3.getAddress(); | |
144 if (proc3 is 0) | |
145 DWT.error(DWT.ERROR_NO_MORE_CALLBACKS); | |
146 Callback4 = new Callback(safaryClass, "browserProc", 4); | |
147 int proc4 = Callback4.getAddress(); | |
148 if (proc4 is 0) | |
149 DWT.error(DWT.ERROR_NO_MORE_CALLBACKS); | |
150 Callback5 = new Callback(safaryClass, "browserProc", 5); | |
151 int proc5 = Callback5.getAddress(); | |
152 if (proc5 is 0) | |
153 DWT.error(DWT.ERROR_NO_MORE_CALLBACKS); | |
154 Callback6 = new Callback(safaryClass, "browserProc", 6); | |
155 int proc6 = Callback6.getAddress(); | |
156 if (proc6 is 0) | |
157 DWT.error(DWT.ERROR_NO_MORE_CALLBACKS); | |
158 Callback7 = new Callback(safaryClass, "browserProc", 7); | |
159 int proc7 = Callback7.getAddress(); | |
160 if (proc7 is 0) | |
161 DWT.error(DWT.ERROR_NO_MORE_CALLBACKS); | |
162 | |
163 int cls = OS.objc_allocateClassPair(OS.class_WebView, className, 0); | |
164 OS.class_addIvar(cls, "tag", OS.PTR_SIZEOF, cast(byte) (Math.log(OS.PTR_SIZEOF) / Math.log(2)), "i"); | |
165 OS.class_addMethod(cls, OS.sel_tag, proc2, "@:"); | |
166 OS.class_addMethod(cls, OS.sel_setTag_1, proc3, "@:i"); | |
167 OS.class_addMethod(cls, OS.sel_webView_1didChangeLocationWithinPageForFrame_1, proc4, "@:@@"); | |
168 OS.class_addMethod(cls, OS.sel_webView_1didFailProvisionalLoadWithError_1forFrame_1, proc5, "@:@@@"); | |
169 OS.class_addMethod(cls, OS.sel_webView_1didFinishLoadForFrame_1, proc4, "@:@@"); | |
170 OS.class_addMethod(cls, OS.sel_webView_1didReceiveTitle_1forFrame_1, proc5, "@:@@@"); | |
171 OS.class_addMethod(cls, OS.sel_webView_1didStartProvisionalLoadForFrame_1, proc4, "@:@@"); | |
172 OS.class_addMethod(cls, OS.sel_webView_1didCommitLoadForFrame_1, proc4, "@:@@"); | |
173 OS.class_addMethod(cls, OS.sel_webView_1resource_1didFinishLoadingFromDataSource_1, proc5, "@:@@@"); | |
174 OS.class_addMethod(cls, OS.sel_webView_1resource_1didFailLoadingWithError_1fromDataSource_1, proc6, "@:@@@@"); | |
175 OS.class_addMethod(cls, OS.sel_webView_1identifierForInitialRequest_1fromDataSource_1, proc5, "@:@@@"); | |
176 OS.class_addMethod(cls, OS.sel_webView_1resource_1willSendRequest_1redirectResponse_1fromDataSource_1, proc7, "@:@@@@@"); | |
177 OS.class_addMethod(cls, OS.sel_handleNotification_1, proc3, "@:@"); | |
178 OS.class_addMethod(cls, OS.sel_webView_1createWebViewWithRequest_1, proc4, "@:@@"); | |
179 OS.class_addMethod(cls, OS.sel_webViewShow_1, proc3, "@:@"); | |
180 OS.class_addMethod(cls, OS.sel_webView_1setFrame_1, proc4, "@:@@"); | |
181 OS.class_addMethod(cls, OS.sel_webViewClose_1, proc3, "@:@"); | |
182 OS.class_addMethod(cls, OS.sel_webView_1contextMenuItemsForElement_1defaultMenuItems_1, proc5, "@:@@@"); | |
183 OS.class_addMethod(cls, OS.sel_webView_1setStatusBarVisible_1, proc4, "@:@B"); | |
184 OS.class_addMethod(cls, OS.sel_webView_1setResizable_1, proc4, "@:@B"); | |
185 OS.class_addMethod(cls, OS.sel_webView_1setToolbarsVisible_1, proc4, "@:@B"); | |
186 OS.class_addMethod(cls, OS.sel_webView_1setStatusText_1, proc4, "@:@@"); | |
187 OS.class_addMethod(cls, OS.sel_webViewFocus_1, proc3, "@:@"); | |
188 OS.class_addMethod(cls, OS.sel_webViewUnfocus_1, proc3, "@:@"); | |
189 OS.class_addMethod(cls, OS.sel_webView_1runJavaScriptAlertPanelWithMessage_1, proc4, "@:@@"); | |
190 OS.class_addMethod(cls, OS.sel_webView_1runJavaScriptConfirmPanelWithMessage_1, proc4, "@:@@"); | |
191 OS.class_addMethod(cls, OS.sel_webView_1runOpenPanelForFileButtonWithResultListener_1, proc4, "@:@@"); | |
192 OS.class_addMethod(cls, OS.sel_webView_1mouseDidMoveOverElement_1modifierFlags_1, proc5, "@:@@I"); | |
193 OS.class_addMethod(cls, OS.sel_webView_1printFrameView_1, proc4, "@:@@"); | |
194 OS.class_addMethod(cls, OS.sel_webView_1decidePolicyForMIMEType_1request_1frame_1decisionListener_1, proc7, "@:@@@@@"); | |
195 OS.class_addMethod(cls, OS.sel_webView_1decidePolicyForNavigationAction_1request_1frame_1decisionListener_1, proc7, "@:@@@@@"); | |
196 OS.class_addMethod(cls, OS.sel_webView_1decidePolicyForNewWindowAction_1request_1newFrameName_1decisionListener_1, proc7, "@:@@@@@"); | |
197 OS.class_addMethod(cls, OS.sel_webView_1unableToImplementPolicyWithError_1frame_1, proc5, "@:@@@"); | |
198 OS.class_addMethod(cls, OS.sel_download_1decideDestinationWithSuggestedFilename_1, proc4, "@:@@"); | |
199 OS.class_addMethod(cls, OS.sel_handleEvent_1, proc3, "@:@"); | |
200 OS.objc_registerClassPair(cls); | |
201 } | |
202 | |
203 /* | |
204 * Override the default event mechanism to not send key events so | |
205 * that the browser can send them by listening to the DOM instead. | |
206 */ | |
207 browser.setData(SAFARI_EVENTS_FIX_KEY); | |
208 | |
209 WebView webView = cast(WebView) (new WebView()).alloc(); | |
210 if (webView is null) | |
211 DWT.error(DWT.ERROR_NO_HANDLES); | |
212 webView.initWithFrame(browser.view.frame(), null, null); | |
213 webView.setAutoresizingMask(OS.NSViewWidthSizable | OS.NSViewHeightSizable); | |
214 jniRef = OS.NewGlobalRef(this); | |
215 if (jniRef is 0) | |
216 DWT.error(DWT.ERROR_NO_HANDLES); | |
217 const DWTWebViewDelegate delegatee = cast(DWTWebViewDelegate) (new DWTWebViewDelegate()).alloc().init(); | |
218 delegatee.setTag(jniRef); | |
219 this.delegatee = delegatee; | |
220 this.webView = webView; | |
221 browser.view.addSubview_(webView); | |
222 | |
223 const NSNotificationCenter notificationCenter = NSNotificationCenter.defaultCenter(); | |
224 | |
225 Listener listener = new class (notificationCenter) Listener | |
226 { | |
227 NSNotificationCenter notificationCenter; | |
228 | |
229 this (NSNotificationCenter notificationCenter) | |
230 { | |
231 this.notificationCenter = notificationCenter; | |
232 } | |
233 | |
234 public void handleEvent (Event e) | |
235 { | |
236 switch (e.type) | |
237 { | |
238 case DWT.Dispose: | |
239 { | |
240 /* make this handler run after other dispose listeners */ | |
241 if (ignoreDispose) | |
242 { | |
243 ignoreDispose = false; | |
244 break; | |
245 } | |
246 ignoreDispose = true; | |
247 browser.notifyListeners(e.type, e); | |
248 e.type = DWT.NONE; | |
249 | |
250 webView.setFrameLoadDelegate(null); | |
251 webView.setResourceLoadDelegate(null); | |
252 webView.setUIDelegate(null); | |
253 webView.setPolicyDelegate(null); | |
254 webView.setDownloadDelegate(null); | |
255 notificationCenter.removeObserver(delegatee); | |
256 | |
257 webView.release(); | |
258 webView = null; | |
259 delegatee.release(); | |
260 delegatee = null; | |
261 OS.DeleteGlobalRef(jniRef); | |
262 jniRef = 0; | |
263 html = null; | |
264 lastHoveredLinkURL = null; | |
265 break; | |
266 } | |
267 } | |
268 } | |
269 }; | |
270 browser.addListener(DWT.Dispose, listener); | |
271 | |
272 webView.setFrameLoadDelegate(delegatee); | |
273 webView.setResourceLoadDelegate(delegatee); | |
274 webView.setUIDelegate(delegatee); | |
275 notificationCenter.addObserver(delegatee, OS.sel_handleNotification_1, null, webView); | |
276 webView.setPolicyDelegate(delegatee); | |
277 webView.setDownloadDelegate(delegatee); | |
278 webView.setApplicationNameForUserAgent(NSString.StringWith(AGENT_STRING)); | |
279 | |
280 if (!Initialized) | |
281 { | |
282 Initialized = true; | |
283 /* disable applets */ | |
284 WebPreferences.standardPreferences().setJavaEnabled(false); | |
285 } | |
286 } | |
287 | |
288 public bool back () | |
289 { | |
290 html = null; | |
291 return webView.goBack(); | |
292 } | |
293 | |
294 static int browserProc (int delegatee, int sel) | |
295 { | |
296 if (sel is OS.sel_tag) | |
297 { | |
298 int[] tag = new int[1]; | |
299 OS.object_getInstanceVariable(delegatee, "tag", tag); | |
300 return tag[0]; | |
301 } | |
302 return 0; | |
303 } | |
304 | |
305 static int browserProc (int id, int sel, int arg0) | |
306 { | |
307 if (sel is OS.sel_setTag_1) | |
308 { | |
309 OS.object_setInstanceVariable(id, "tag", arg0); | |
310 return 0; | |
311 } | |
312 int jniRef = OS.objc_msgSend(id, OS.sel_tag); | |
313 if (jniRef is 0 || jniRef is -1) | |
314 return 0; | |
315 Safari widget = cast(Safari) OS.JNIGetObject(jniRef); | |
316 if (widget is null) | |
317 return 0; | |
318 if (sel is OS.sel_handleNotification_1) | |
319 { | |
320 widget.handleNotification(arg0); | |
321 } | |
322 else if (sel is OS.sel_webViewShow_1) | |
323 { | |
324 widget.webViewShow(arg0); | |
325 } | |
326 else if (sel is OS.sel_webViewClose_1) | |
327 { | |
328 widget.webViewClose(arg0); | |
329 } | |
330 else if (sel is OS.sel_webViewFocus_1) | |
331 { | |
332 widget.webViewFocus(arg0); | |
333 } | |
334 else if (sel is OS.sel_webViewUnfocus_1) | |
335 { | |
336 widget.webViewUnfocus(arg0); | |
337 } | |
338 else if (sel is OS.sel_handleEvent_1) | |
339 { | |
340 widget.handleEvent(arg0); | |
341 } | |
342 return 0; | |
343 } | |
344 | |
345 static int browserProc (int id, int sel, int arg0, int arg1) | |
346 { | |
347 if (sel is OS.sel_setTag_1) | |
348 { | |
349 OS.object_setInstanceVariable(id, "tag", arg0); | |
350 return 0; | |
351 } | |
352 int jniRef = OS.objc_msgSend(id, OS.sel_tag); | |
353 if (jniRef is 0 || jniRef is -1) | |
354 return 0; | |
355 Safari widget = cast(Safari) OS.JNIGetObject(jniRef); | |
356 if (widget is null) | |
357 return 0; | |
358 if (sel is OS.sel_webView_1didChangeLocationWithinPageForFrame_1) | |
359 { | |
360 widget.webView_didChangeLocationWithinPageForFrame(arg0, arg1); | |
361 } | |
362 else if (sel is OS.sel_webView_1didFinishLoadForFrame_1) | |
363 { | |
364 widget.webView_didFinishLoadForFrame(arg0, arg1); | |
365 } | |
366 else if (sel is OS.sel_webView_1didStartProvisionalLoadForFrame_1) | |
367 { | |
368 widget.webView_didStartProvisionalLoadForFrame(arg0, arg1); | |
369 } | |
370 else if (sel is OS.sel_webView_1didCommitLoadForFrame_1) | |
371 { | |
372 widget.webView_didCommitLoadForFrame(arg0, arg1); | |
373 } | |
374 else if (sel is OS.sel_webView_1setFrame_1) | |
375 { | |
376 widget.webView_setFrame(arg0, arg1); | |
377 } | |
378 else if (sel is OS.sel_webView_1createWebViewWithRequest_1) | |
379 { | |
380 return widget.webView_createWebViewWithRequest(arg0, arg1); | |
381 } | |
382 else if (sel is OS.sel_webView_1setStatusBarVisible_1) | |
383 { | |
384 widget.webView_setStatusBarVisible(arg0, arg1); | |
385 } | |
386 else if (sel is OS.sel_webView_1setResizable_1) | |
387 { | |
388 widget.webView_setResizable(arg0, arg1); | |
389 } | |
390 else if (sel is OS.sel_webView_1setStatusText_1) | |
391 { | |
392 widget.webView_setStatusText(arg0, arg1); | |
393 } | |
394 else if (sel is OS.sel_webView_1setToolbarsVisible_1) | |
395 { | |
396 widget.webView_setToolbarsVisible(arg0, arg1); | |
397 } | |
398 else if (sel is OS.sel_webView_1runJavaScriptAlertPanelWithMessage_1) | |
399 { | |
400 widget.webView_runJavaScriptAlertPanelWithMessage(arg0, arg1); | |
401 } | |
402 else if (sel is OS.sel_webView_1runJavaScriptConfirmPanelWithMessage_1) | |
403 { | |
404 return widget.webView_runJavaScriptConfirmPanelWithMessage(arg0, arg1); | |
405 } | |
406 else if (sel is OS.sel_webView_1runOpenPanelForFileButtonWithResultListener_1) | |
407 { | |
408 widget.webView_runOpenPanelForFileButtonWithResultListener(arg0, arg1); | |
409 } | |
410 else if (sel is OS.sel_download_1decideDestinationWithSuggestedFilename_1) | |
411 { | |
412 widget.download_decideDestinationWithSuggestedFilename(arg0, arg1); | |
413 } | |
414 else if (sel is OS.sel_webView_1printFrameView_1) | |
415 { | |
416 widget.webView_printFrameView(arg0, arg1); | |
417 } | |
418 return 0; | |
419 } | |
420 | |
421 static int browserProc (int id, int sel, int arg0, int arg1, int arg2) | |
422 { | |
423 int jniRef = OS.objc_msgSend(id, OS.sel_tag); | |
424 if (jniRef is 0 || jniRef is -1) | |
425 return 0; | |
426 Safari widget = cast(Safari) OS.JNIGetObject(jniRef); | |
427 if (widget is null) | |
428 return 0; | |
429 if (sel is OS.sel_webView_1didFailProvisionalLoadWithError_1forFrame_1) | |
430 { | |
431 widget.webView_didFailProvisionalLoadWithError_forFrame(arg0, arg1, arg2); | |
432 } | |
433 else if (sel is OS.sel_webView_1didReceiveTitle_1forFrame_1) | |
434 { | |
435 widget.webView_didReceiveTitle_forFrame(arg0, arg1, arg2); | |
436 } | |
437 else if (sel is OS.sel_webView_1resource_1didFinishLoadingFromDataSource_1) | |
438 { | |
439 widget.webView_resource_didFinishLoadingFromDataSource(arg0, arg1, arg2); | |
440 } | |
441 else if (sel is OS.sel_webView_1identifierForInitialRequest_1fromDataSource_1) | |
442 { | |
443 return widget.webView_identifierForInitialRequest_fromDataSource(arg0, arg1, arg2); | |
444 } | |
445 else if (sel is OS.sel_webView_1contextMenuItemsForElement_1defaultMenuItems_1) | |
446 { | |
447 return widget.webView_contextMenuItemsForElement_defaultMenuItems(arg0, arg1, arg2); | |
448 } | |
449 else if (sel is OS.sel_webView_1mouseDidMoveOverElement_1modifierFlags_1) | |
450 { | |
451 widget.webView_mouseDidMoveOverElement_modifierFlags(arg0, arg1, arg2); | |
452 } | |
453 else if (sel is OS.sel_webView_1unableToImplementPolicyWithError_1frame_1) | |
454 { | |
455 widget.webView_unableToImplementPolicyWithError_frame(arg0, arg1, arg2); | |
456 } | |
457 return 0; | |
458 } | |
459 | |
460 static int browserProc (int id, int sel, int arg0, int arg1, int arg2, int arg3) | |
461 { | |
462 int jniRef = OS.objc_msgSend(id, OS.sel_tag); | |
463 if (jniRef is 0 || jniRef is -1) | |
464 return 0; | |
465 Safari widget = cast(Safari) OS.JNIGetObject(jniRef); | |
466 if (widget is null) | |
467 return 0; | |
468 if (sel is OS.sel_webView_1resource_1didFailLoadingWithError_1fromDataSource_1) | |
469 { | |
470 widget.webView_resource_didFailLoadingWithError_fromDataSource(arg0, arg1, arg2, arg3); | |
471 } | |
472 return 0; | |
473 } | |
474 | |
475 static int browserProc (int id, int sel, int arg0, int arg1, int arg2, int arg3, int arg4) | |
476 { | |
477 int jniRef = OS.objc_msgSend(id, OS.sel_tag); | |
478 if (jniRef is 0 || jniRef is -1) | |
479 return 0; | |
480 Safari widget = cast(Safari) OS.JNIGetObject(jniRef); | |
481 if (widget is null) | |
482 return 0; | |
483 if (sel is OS.sel_webView_1resource_1willSendRequest_1redirectResponse_1fromDataSource_1) | |
484 { | |
485 return widget.webView_resource_willSendRequest_redirectResponse_fromDataSource(arg0, arg1, arg2, arg3, arg4); | |
486 } | |
487 else if (sel is OS.sel_webView_1decidePolicyForMIMEType_1request_1frame_1decisionListener_1) | |
488 { | |
489 widget.webView_decidePolicyForMIMEType_request_frame_decisionListener(arg0, arg1, arg2, arg3, arg4); | |
490 } | |
491 else if (sel is OS.sel_webView_1decidePolicyForNavigationAction_1request_1frame_1decisionListener_1) | |
492 { | |
493 widget.webView_decidePolicyForNavigationAction_request_frame_decisionListener(arg0, arg1, arg2, arg3, arg4); | |
494 } | |
495 else if (sel is OS.sel_webView_1decidePolicyForNewWindowAction_1request_1newFrameName_1decisionListener_1) | |
496 { | |
497 widget.webView_decidePolicyForNewWindowAction_request_newFrameName_decisionListener(arg0, arg1, arg2, arg3, arg4); | |
498 } | |
499 return 0; | |
500 } | |
501 | |
502 public bool execute (String script) | |
503 { | |
504 return webView.StringByEvaluatingJavaScriptFromString(NSString.StringWith(script)) !is null; | |
505 } | |
506 | |
507 public bool forward () | |
508 { | |
509 html = null; | |
510 return webView.goForward(); | |
511 } | |
512 | |
513 public String getText () | |
514 { | |
515 WebFrame mainFrame = webView.mainFrame(); | |
516 WebDataSource dataSource = mainFrame.dataSource(); | |
517 if (dataSource is null) | |
518 return ""; //$NON-NLS-1$ | |
519 WebDocumentRepresentation representation = dataSource.representation(); | |
520 if (representation is null) | |
521 return ""; //$NON-NLS-1$ | |
522 NSString source = representation.documentSource(); | |
523 if (source is null) | |
524 return ""; //$NON-NLS-1$ | |
525 char[] buffer = new char[source.length()]; | |
526 source.getCharacters_(buffer); | |
527 return new String(buffer); | |
528 } | |
529 | |
530 public String getUrl () | |
531 { | |
532 return url; | |
533 } | |
534 | |
535 public bool isBackEnabled () | |
536 { | |
537 return webView.canGoBack(); | |
538 } | |
539 | |
540 public bool isForwardEnabled () | |
541 { | |
542 return webView.canGoForward(); | |
543 } | |
544 | |
545 public void refresh () | |
546 { | |
547 webView.reload(null); | |
548 } | |
549 | |
550 public bool setText (String html) | |
551 { | |
552 /* | |
553 * Bug in Safari. The web view segment faults in some circumstances | |
554 * when the text changes during the location changing callback. The | |
555 * fix is to defer the work until the callback is done. | |
556 */ | |
557 if (changingLocation) | |
558 { | |
559 this.html = html; | |
560 } | |
561 else | |
562 { | |
563 _setText(html); | |
564 } | |
565 return true; | |
566 } | |
567 | |
568 void _setText (String html) | |
569 { | |
570 NSString String = NSString.StringWith(html); | |
571 NSString URLString = NSString.StringWith(URI_FROMMEMORY); | |
572 NSURL URL = NSURL.static_URLWithString_(URLString); | |
573 WebFrame mainFrame = webView.mainFrame(); | |
574 mainFrame.loadHTMLString(String, URL); | |
575 } | |
576 | |
577 public bool setUrl (String url) | |
578 { | |
579 html = null; | |
580 | |
581 NSURL inURL; | |
582 if (url.startsWith(PROTOCOL_FILE)) | |
583 { | |
584 url = url.substring(PROTOCOL_FILE.length()); | |
585 } | |
586 bool isHttpURL = url.indexOf('/') !is 0; | |
587 if (isHttpURL) | |
588 { | |
589 if (url.indexOf(':') is -1) | |
590 { | |
591 url = PROTOCOL_HTTP + "//" + url; //$NON-NLS-1$ | |
592 } | |
593 inURL = NSURL.static_URLWithString_(NSString.StringWith(url.toString())); | |
594 } | |
595 else | |
596 { | |
597 inURL = NSURL.static_fileURLWithPath_(NSString.StringWith(url.toString())); | |
598 } | |
599 if (inURL is null) | |
600 return false; | |
601 | |
602 NSURLRequest request = NSURLRequest.static_requestWithURL_(inURL); | |
603 WebFrame mainFrame = webView.mainFrame(); | |
604 mainFrame.loadRequest(request); | |
605 return true; | |
606 } | |
607 | |
608 public void stop () | |
609 { | |
610 html = null; | |
611 webView.stopLoading(null); | |
612 } | |
613 | |
614 /* WebFrameLoadDelegate */ | |
615 | |
616 void webView_didChangeLocationWithinPageForFrame (int sender, int frameID) | |
617 { | |
618 WebFrame frame = new WebFrame(frameID); | |
619 WebDataSource dataSource = frame.dataSource(); | |
620 NSURLRequest request = dataSource.request(); | |
621 NSURL url = request.URL(); | |
622 NSString s = url.absoluteString(); | |
623 int length = s.length(); | |
624 if (length is 0) | |
625 return; | |
626 char[] buffer = new char[length]; | |
627 s.getCharacters_(buffer); | |
628 String url2 = new String(buffer); | |
629 /* | |
630 * If the URI indicates that the page is being rendered from memory | |
631 * (via setText()) then set it to about:blank to be consistent with IE. | |
632 */ | |
633 if (url2.opEquals(URI_FROMMEMORY)) | |
634 url2 = ABOUT_BLANK; | |
635 | |
636 const Display display = browser.getDisplay(); | |
637 bool top = frameID is webView.mainFrame().id; | |
638 if (top) | |
639 { | |
640 StatusTextEvent statusText = new StatusTextEvent(browser); | |
641 statusText.display = display; | |
642 statusText.widget = browser; | |
643 statusText.text = url2; | |
644 for (int i = 0; i < statusTextListeners.length; i++) | |
645 { | |
646 statusTextListeners[i].changed(statusText); | |
647 } | |
648 } | |
649 | |
650 LocationEvent location = new LocationEvent(browser); | |
651 location.display = display; | |
652 location.widget = browser; | |
653 location.location = url2; | |
654 location.top = top; | |
655 for (int i = 0; i < locationListeners.length; i++) | |
656 { | |
657 locationListeners[i].changed(location); | |
658 } | |
659 } | |
660 | |
661 void webView_didFailProvisionalLoadWithError_forFrame (int sender, int error, int frame) | |
662 { | |
663 if (frame is webView.mainFrame().id) | |
664 { | |
665 /* | |
666 * Feature on Safari. The identifier is used here as a marker for the events | |
667 * related to the top frame and the URL changes related to that top frame as | |
668 * they should appear on the location bar of a browser. It is expected to reset | |
669 * the identifier to 0 when the event didFinishLoadingFromDataSource related to | |
670 * the identifierForInitialRequest event is received. However, Safari fires | |
671 * the didFinishLoadingFromDataSource event before the entire content of the | |
672 * top frame is loaded. It is possible to receive multiple willSendRequest | |
673 * events in this interval, causing the Browser widget to send unwanted | |
674 * Location.changing events. For this reason, the identifier is reset to 0 | |
675 * when the top frame has either finished loading (didFinishLoadForFrame | |
676 * event) or failed (didFailProvisionalLoadWithError). | |
677 */ | |
678 identifier = 0; | |
679 } | |
680 } | |
681 | |
682 void webView_didFinishLoadForFrame (int sender, int frameID) | |
683 { | |
684 hookDOMMouseListeners(frameID); | |
685 if (frameID is webView.mainFrame().id) | |
686 { | |
687 hookDOMKeyListeners(frameID); | |
688 | |
689 const Display display = browser.getDisplay(); | |
690 /* | |
691 * To be consistent with other platforms a title event should be fired when a | |
692 * page has completed loading. A page with a <title> tag will do this | |
693 * automatically when the didReceiveTitle callback is received. However a page | |
694 * without a <title> tag will not do this by default, so fire the event | |
695 * here with the page's url as the title. | |
696 */ | |
697 WebFrame frame = new WebFrame(frameID); | |
698 WebDataSource dataSource = frame.dataSource(); | |
699 if (dataSource !is null) | |
700 { | |
701 NSString title = dataSource.pageTitle(); | |
702 if (title is null) | |
703 { /* page has no title */ | |
704 const TitleEvent newEvent = new TitleEvent(browser); | |
705 newEvent.display = display; | |
706 newEvent.widget = browser; | |
707 newEvent.title = url; | |
708 for (int i = 0; i < titleListeners.length; i++) | |
709 { | |
710 const TitleListener listener = titleListeners[i]; | |
711 /* | |
712 * Note on WebKit. Running the event loop from a Browser | |
713 * delegatee callback breaks the WebKit (stop loading or | |
714 * crash). The workaround is to invoke Display.asyncExec() | |
715 * so that the Browser does not crash if this is attempted. | |
716 */ | |
717 display.asyncExec(new class (display, listener) Runnable | |
718 { | |
719 Display display; | |
720 TitleListener listener; | |
721 | |
722 this (Display display, TitleListener listener) | |
723 { | |
724 this.display = display; | |
725 this.listener = listener; | |
726 } | |
727 | |
728 public void run () | |
729 { | |
730 if (!display.isDisposed() && !browser.isDisposed()) | |
731 { | |
732 listener.changed(newEvent); | |
733 } | |
734 } | |
735 }); | |
736 } | |
737 } | |
738 } | |
739 const ProgressEvent progress = new ProgressEvent(browser); | |
740 progress.display = display; | |
741 progress.widget = browser; | |
742 progress.current = MAX_PROGRESS; | |
743 progress.total = MAX_PROGRESS; | |
744 for (int i = 0; i < progressListeners.length; i++) | |
745 { | |
746 const ProgressListener listener = progressListeners[i]; | |
747 /* | |
748 * Note on WebKit. Running the event loop from a Browser | |
749 * delegatee callback breaks the WebKit (stop loading or | |
750 * crash). The ProgressBar widget currently touches the | |
751 * event loop every time the method setSelection is called. | |
752 * The workaround is to invoke Display.asyncExec() so that | |
753 * the Browser does not crash when the user updates the | |
754 * selection of the ProgressBar. | |
755 */ | |
756 display.asyncExec(new class (display, listener) Runnable | |
757 { | |
758 Display display; | |
759 ProgressListener listener; | |
760 | |
761 this (Display display, ProgressListener listener) | |
762 { | |
763 this.display = display; | |
764 this.listener = listener; | |
765 } | |
766 | |
767 public void run () | |
768 { | |
769 if (!display.isDisposed() && !browser.isDisposed()) | |
770 { | |
771 listener.completed(progress); | |
772 } | |
773 } | |
774 }); | |
775 } | |
776 /* | |
777 * Feature on Safari. The identifier is used here as a marker for the events | |
778 * related to the top frame and the URL changes related to that top frame as | |
779 * they should appear on the location bar of a browser. It is expected to reset | |
780 * the identifier to 0 when the event didFinishLoadingFromDataSource related to | |
781 * the identifierForInitialRequest event is received. However, Safari fires | |
782 * the didFinishLoadingFromDataSource event before the entire content of the | |
783 * top frame is loaded. It is possible to receive multiple willSendRequest | |
784 * events in this interval, causing the Browser widget to send unwanted | |
785 * Location.changing events. For this reason, the identifier is reset to 0 | |
786 * when the top frame has either finished loading (didFinishLoadForFrame | |
787 * event) or failed (didFailProvisionalLoadWithError). | |
788 */ | |
789 identifier = 0; | |
790 } | |
791 } | |
792 | |
793 void hookDOMKeyListeners (int frameID) | |
794 { | |
795 WebFrame frame = new WebFrame(frameID); | |
796 DOMDocument document = frame.DOMDocument(); | |
797 | |
798 NSString type = NSString.StringWith(DOMEVENT_KEYDOWN); | |
799 document.addEventListener_listener_useCapture(type, delegatee, false); | |
800 | |
801 type = NSString.StringWith(DOMEVENT_KEYUP); | |
802 document.addEventListener_listener_useCapture(type, delegatee, false); | |
803 } | |
804 | |
805 void hookDOMMouseListeners (int frameID) | |
806 { | |
807 WebFrame frame = new WebFrame(frameID); | |
808 DOMDocument document = frame.DOMDocument(); | |
809 | |
810 NSString type = NSString.StringWith(DOMEVENT_MOUSEDOWN); | |
811 document.addEventListener_listener_useCapture(type, delegatee, false); | |
812 | |
813 type = NSString.StringWith(DOMEVENT_MOUSEUP); | |
814 document.addEventListener_listener_useCapture(type, delegatee, false); | |
815 | |
816 type = NSString.StringWith(DOMEVENT_MOUSEMOVE); | |
817 document.addEventListener_listener_useCapture(type, delegatee, false); | |
818 | |
819 type = NSString.StringWith(DOMEVENT_MOUSEWHEEL); | |
820 document.addEventListener_listener_useCapture(type, delegatee, false); | |
821 } | |
822 | |
823 void webView_didReceiveTitle_forFrame (int sender, int titleID, int frameID) | |
824 { | |
825 if (frameID is webView.mainFrame().id) | |
826 { | |
827 NSString title = new NSString(titleID); | |
828 char[] buffer = new char[title.length()]; | |
829 title.getCharacters_(buffer); | |
830 String newTitle = new String(buffer); | |
831 TitleEvent newEvent = new TitleEvent(browser); | |
832 newEvent.display = browser.getDisplay(); | |
833 newEvent.widget = browser; | |
834 newEvent.title = newTitle; | |
835 for (int i = 0; i < titleListeners.length; i++) | |
836 { | |
837 titleListeners[i].changed(newEvent); | |
838 } | |
839 } | |
840 } | |
841 | |
842 void webView_didStartProvisionalLoadForFrame (int sender, int frameID) | |
843 { | |
844 /* | |
845 * This code is intentionally commented. WebFrameLoadDelegate:didStartProvisionalLoadForFrame is | |
846 * called before WebResourceLoadDelegate:willSendRequest and | |
847 * WebFrameLoadDelegate:didCommitLoadForFrame. The resource count is reset when didCommitLoadForFrame | |
848 * is received for the top frame. | |
849 */ | |
850 // if (frameID is webView.mainFrame().id) { | |
851 // /* reset resource status variables */ | |
852 // resourceCount= 0; | |
853 // } | |
854 } | |
855 | |
856 void webView_didCommitLoadForFrame (int sender, int frameID) | |
857 { | |
858 WebFrame frame = new WebFrame(frameID); | |
859 WebDataSource dataSource = frame.dataSource(); | |
860 NSURLRequest request = dataSource.request(); | |
861 NSURL url = request.URL(); | |
862 NSString s = url.absoluteString(); | |
863 int length = s.length(); | |
864 if (length is 0) | |
865 return; | |
866 char[] buffer = new char[length]; | |
867 s.getCharacters_(buffer); | |
868 String url2 = new String(buffer); | |
869 /* | |
870 * If the URI indicates that the page is being rendered from memory | |
871 * (via setText()) then set it to about:blank to be consistent with IE. | |
872 */ | |
873 if (url2.opEquals(URI_FROMMEMORY)) | |
874 url2 = ABOUT_BLANK; | |
875 | |
876 const Display display = browser.getDisplay(); | |
877 bool top = frameID is webView.mainFrame().id; | |
878 if (top) | |
879 { | |
880 /* reset resource status variables */ | |
881 resourceCount = 0; | |
882 this.url = url2; | |
883 | |
884 const ProgressEvent progress = new ProgressEvent(browser); | |
885 progress.display = display; | |
886 progress.widget = browser; | |
887 progress.current = 1; | |
888 progress.total = MAX_PROGRESS; | |
889 for (int i = 0; i < progressListeners.length; i++) | |
890 { | |
891 const ProgressListener listener = progressListeners[i]; | |
892 /* | |
893 * Note on WebKit. Running the event loop from a Browser | |
894 * delegatee callback breaks the WebKit (stop loading or | |
895 * crash). The widget ProgressBar currently touches the | |
896 * event loop every time the method setSelection is called. | |
897 * The workaround is to invoke Display.asyncexec so that | |
898 * the Browser does not crash when the user updates the | |
899 * selection of the ProgressBar. | |
900 */ | |
901 display.asyncExec(new class (display, listener) Runnable | |
902 { | |
903 Display display; | |
904 ProgressListener listener; | |
905 | |
906 this (Display display, ProgressListener listener) | |
907 { | |
908 this.display = display; | |
909 this.listener = listener; | |
910 } | |
911 | |
912 public void run () | |
913 { | |
914 if (!display.isDisposed() && !browser.isDisposed()) | |
915 listener.changed(progress); | |
916 } | |
917 }); | |
918 } | |
919 | |
920 StatusTextEvent statusText = new StatusTextEvent(browser); | |
921 statusText.display = display; | |
922 statusText.widget = browser; | |
923 statusText.text = url2; | |
924 for (int i = 0; i < statusTextListeners.length; i++) | |
925 { | |
926 statusTextListeners[i].changed(statusText); | |
927 } | |
928 } | |
929 LocationEvent location = new LocationEvent(browser); | |
930 location.display = display; | |
931 location.widget = browser; | |
932 location.location = url2; | |
933 location.top = top; | |
934 for (int i = 0; i < locationListeners.length; i++) | |
935 { | |
936 locationListeners[i].changed(location); | |
937 } | |
938 } | |
939 | |
940 /* WebResourceLoadDelegate */ | |
941 | |
942 void webView_resource_didFinishLoadingFromDataSource (int sender, int identifier, int dataSource) | |
943 { | |
944 /* | |
945 * Feature on Safari. The identifier is used here as a marker for the events | |
946 * related to the top frame and the URL changes related to that top frame as | |
947 * they should appear on the location bar of a browser. It is expected to reset | |
948 * the identifier to 0 when the event didFinishLoadingFromDataSource related to | |
949 * the identifierForInitialRequest event is received. However, Safari fires | |
950 * the didFinishLoadingFromDataSource event before the entire content of the | |
951 * top frame is loaded. It is possible to receive multiple willSendRequest | |
952 * events in this interval, causing the Browser widget to send unwanted | |
953 * Location.changing events. For this reason, the identifier is reset to 0 | |
954 * when the top frame has either finished loading (didFinishLoadForFrame | |
955 * event) or failed (didFailProvisionalLoadWithError). | |
956 */ | |
957 // this code is intentionally commented | |
958 //if (this.identifier is identifier) this.identifier = 0; | |
959 } | |
960 | |
961 void webView_resource_didFailLoadingWithError_fromDataSource (int sender, int identifier, int error, int dataSource) | |
962 { | |
963 /* | |
964 * Feature on Safari. The identifier is used here as a marker for the events | |
965 * related to the top frame and the URL changes related to that top frame as | |
966 * they should appear on the location bar of a browser. It is expected to reset | |
967 * the identifier to 0 when the event didFinishLoadingFromDataSource related to | |
968 * the identifierForInitialRequest event is received. However, Safari fires | |
969 * the didFinishLoadingFromDataSource event before the entire content of the | |
970 * top frame is loaded. It is possible to receive multiple willSendRequest | |
971 * events in this interval, causing the Browser widget to send unwanted | |
972 * Location.changing events. For this reason, the identifier is reset to 0 | |
973 * when the top frame has either finished loading (didFinishLoadForFrame | |
974 * event) or failed (didFailProvisionalLoadWithError). | |
975 */ | |
976 // this code is intentionally commented | |
977 //if (this.identifier is identifier) this.identifier = 0; | |
978 } | |
979 | |
980 int webView_identifierForInitialRequest_fromDataSource (int sender, int request, int dataSourceID) | |
981 { | |
982 const Display display = browser.getDisplay(); | |
983 const ProgressEvent progress = new ProgressEvent(browser); | |
984 progress.display = display; | |
985 progress.widget = browser; | |
986 progress.current = resourceCount; | |
987 progress.total = Math.max(resourceCount, MAX_PROGRESS); | |
988 for (int i = 0; i < progressListeners.length; i++) | |
989 { | |
990 const ProgressListener listener = progressListeners[i]; | |
991 /* | |
992 * Note on WebKit. Running the event loop from a Browser | |
993 * delegatee callback breaks the WebKit (stop loading or | |
994 * crash). The widget ProgressBar currently touches the | |
995 * event loop every time the method setSelection is called. | |
996 * The workaround is to invoke Display.asyncexec so that | |
997 * the Browser does not crash when the user updates the | |
998 * selection of the ProgressBar. | |
999 */ | |
1000 display.asyncExec(new class (display, listener) Runnable | |
1001 { | |
1002 Display display; | |
1003 ProgressListener listener; | |
1004 | |
1005 this (Display display, ProgressListener listener) | |
1006 { | |
1007 this.display = display; | |
1008 this.listener = listener; | |
1009 } | |
1010 | |
1011 public void run () | |
1012 { | |
1013 if (!display.isDisposed() && !browser.isDisposed()) | |
1014 listener.changed(progress); | |
1015 } | |
1016 }); | |
1017 } | |
1018 | |
1019 NSNumber identifier = NSNumber.numberWithInt(resourceCount++); | |
1020 if (this.identifier is 0) | |
1021 { | |
1022 WebDataSource dataSource = new WebDataSource(dataSourceID); | |
1023 WebFrame frame = dataSource.webFrame(); | |
1024 if (frame.id is webView.mainFrame().id) | |
1025 this.identifier = identifier.id; | |
1026 } | |
1027 return identifier.id; | |
1028 | |
1029 } | |
1030 | |
1031 int webView_resource_willSendRequest_redirectResponse_fromDataSource (int sender, int identifier, int request, int redirectResponse, | |
1032 int dataSource) | |
1033 { | |
1034 return request; | |
1035 } | |
1036 | |
1037 /* handleNotification */ | |
1038 | |
1039 void handleNotification (int notification) | |
1040 { | |
1041 } | |
1042 | |
1043 /* UIDelegate */ | |
1044 int webView_createWebViewWithRequest (int sender, int request) | |
1045 { | |
1046 WindowEvent newEvent = new WindowEvent(browser); | |
1047 newEvent.display = browser.getDisplay(); | |
1048 newEvent.widget = browser; | |
1049 newEvent.required = true; | |
1050 if (openWindowListeners !is null) | |
1051 { | |
1052 for (int i = 0; i < openWindowListeners.length; i++) | |
1053 { | |
1054 openWindowListeners[i].open(newEvent); | |
1055 } | |
1056 } | |
1057 Browser browser = null; | |
1058 if (newEvent.browser !is null && cast(Safari) newEvent.browser.webBrowser) | |
1059 { | |
1060 browser = newEvent.browser; | |
1061 } | |
1062 if (browser !is null && !browser.isDisposed()) | |
1063 { | |
1064 if (request !is 0) | |
1065 { | |
1066 WebFrame mainFrame = webView.mainFrame(); | |
1067 mainFrame.loadRequest(new NSURLRequest(request)); | |
1068 } | |
1069 } | |
1070 return webView.id; | |
1071 } | |
1072 | |
1073 void webViewShow (int sender) | |
1074 { | |
1075 /* | |
1076 * Feature on WebKit. The Safari WebKit expects the application | |
1077 * to create a new Window using the Objective C Cocoa API in response | |
1078 * to UIDelegate.createWebViewWithRequest. The application is then | |
1079 * expected to use Objective C Cocoa API to make this window visible | |
1080 * when receiving the UIDelegate.webViewShow message. For some reason, | |
1081 * a window created with the Carbon API hosting the new browser instance | |
1082 * does not redraw until it has been resized. The fix is to increase the | |
1083 * size of the Shell and restore it to its initial size. | |
1084 */ | |
1085 Shell parent = browser.getShell(); | |
1086 Point pt = parent.getSize(); | |
1087 parent.setSize(pt.x + 1, pt.y); | |
1088 parent.setSize(pt.x, pt.y); | |
1089 WindowEvent newEvent = new WindowEvent(browser); | |
1090 newEvent.display = browser.getDisplay(); | |
1091 newEvent.widget = browser; | |
1092 if (location !is null) | |
1093 newEvent.location = location; | |
1094 if (size !is null) | |
1095 newEvent.size = size; | |
1096 /* | |
1097 * Feature in Safari. Safari's tool bar contains | |
1098 * the address bar. The address bar is displayed | |
1099 * if the tool bar is displayed. There is no separate | |
1100 * notification for the address bar. | |
1101 * Feature in Safari. The menu bar is always | |
1102 * displayed. There is no notification to hide | |
1103 * the menu bar. | |
1104 */ | |
1105 newEvent.addressBar = toolBar; | |
1106 newEvent.menuBar = true; | |
1107 newEvent.statusBar = statusBar; | |
1108 newEvent.toolBar = toolBar; | |
1109 for (int i = 0; i < visibilityWindowListeners.length; i++) | |
1110 { | |
1111 visibilityWindowListeners[i].show(newEvent); | |
1112 } | |
1113 location = null; | |
1114 size = null; | |
1115 } | |
1116 | |
1117 void webView_setFrame (int sender, int frame) | |
1118 { | |
1119 float[] dest = new float[4]; | |
1120 OS.memmove(dest, frame, 16); | |
1121 /* convert to DWT system coordinates */ | |
1122 Rectangle bounds = browser.getDisplay().getBounds(); | |
1123 location = new Point(cast(int) dest[0], bounds.height - cast(int) dest[1] - cast(int) dest[3]); | |
1124 size = new Point(cast(int) dest[2], cast(int) dest[3]); | |
1125 } | |
1126 | |
1127 void webViewFocus (int sender) | |
1128 { | |
1129 } | |
1130 | |
1131 void webViewUnfocus (int sender) | |
1132 { | |
1133 } | |
1134 | |
1135 void webView_runJavaScriptAlertPanelWithMessage (int sender, int messageID) | |
1136 { | |
1137 NSString message = new NSString(messageID); | |
1138 char[] buffer = new char[message.length()]; | |
1139 message.getCharacters_(buffer); | |
1140 String text = new String(buffer); | |
1141 | |
1142 MessageBox messageBox = new MessageBox(browser.getShell(), DWT.OK | DWT.ICON_WARNING); | |
1143 messageBox.setText("Javascript"); //$NON-NLS-1$ | |
1144 messageBox.setMessage(text); | |
1145 messageBox.open(); | |
1146 } | |
1147 | |
1148 int webView_runJavaScriptConfirmPanelWithMessage (int sender, int messageID) | |
1149 { | |
1150 NSString message = new NSString(messageID); | |
1151 char[] buffer = new char[message.length()]; | |
1152 message.getCharacters_(buffer); | |
1153 String text = new String(buffer); | |
1154 | |
1155 MessageBox messageBox = new MessageBox(browser.getShell(), DWT.OK | DWT.CANCEL | DWT.ICON_QUESTION); | |
1156 messageBox.setText("Javascript"); //$NON-NLS-1$ | |
1157 messageBox.setMessage(text); | |
1158 return messageBox.open() is DWT.OK ? 1 : 0; | |
1159 } | |
1160 | |
1161 void webView_runOpenPanelForFileButtonWithResultListener (int sender, int resultListenerID) | |
1162 { | |
1163 FileDialog dialog = new FileDialog(browser.getShell(), DWT.NONE); | |
1164 String result = dialog.open(); | |
1165 WebOpenPanelResultListener resultListener = new WebOpenPanelResultListener(resultListenerID); | |
1166 if (result is null) | |
1167 { | |
1168 resultListener.cancel(); | |
1169 return; | |
1170 } | |
1171 resultListener.chooseFilename(NSString.StringWith(result)); | |
1172 } | |
1173 | |
1174 void webViewClose (int sender) | |
1175 { | |
1176 Shell parent = browser.getShell(); | |
1177 WindowEvent newEvent = new WindowEvent(browser); | |
1178 newEvent.display = browser.getDisplay(); | |
1179 newEvent.widget = browser; | |
1180 for (int i = 0; i < closeWindowListeners.length; i++) | |
1181 { | |
1182 closeWindowListeners[i].close(newEvent); | |
1183 } | |
1184 browser.dispose(); | |
1185 if (parent.isDisposed()) | |
1186 return; | |
1187 /* | |
1188 * Feature on WebKit. The Safari WebKit expects the application | |
1189 * to create a new Window using the Objective C Cocoa API in response | |
1190 * to UIDelegate.createWebViewWithRequest. The application is then | |
1191 * expected to use Objective C Cocoa API to make this window visible | |
1192 * when receiving the UIDelegate.webViewShow message. For some reason, | |
1193 * a window created with the Carbon API hosting the new browser instance | |
1194 * does not redraw until it has been resized. The fix is to increase the | |
1195 * size of the Shell and restore it to its initial size. | |
1196 */ | |
1197 Point pt = parent.getSize(); | |
1198 parent.setSize(pt.x + 1, pt.y); | |
1199 parent.setSize(pt.x, pt.y); | |
1200 } | |
1201 | |
1202 int webView_contextMenuItemsForElement_defaultMenuItems (int sender, int element, int defaultMenuItems) | |
1203 { | |
1204 Point pt = browser.getDisplay().getCursorLocation(); | |
1205 Event event = new Event(); | |
1206 event.x = pt.x; | |
1207 event.y = pt.y; | |
1208 browser.notifyListeners(DWT.MenuDetect, event); | |
1209 Menu menu = browser.getMenu(); | |
1210 if (!event.doit) | |
1211 return 0; | |
1212 if (menu !is null && !menu.isDisposed()) | |
1213 { | |
1214 if (event.x !is pt.x || event.y !is pt.y) | |
1215 { | |
1216 menu.setLocation(event.x, event.y); | |
1217 } | |
1218 menu.setVisible(true); | |
1219 return 0; | |
1220 } | |
1221 return defaultMenuItems; | |
1222 } | |
1223 | |
1224 void webView_setStatusBarVisible (int sender, int visible) | |
1225 { | |
1226 /* Note. Webkit only emits the notification when the status bar should be hidden. */ | |
1227 statusBar = visible !is 0; | |
1228 } | |
1229 | |
1230 void webView_setStatusText (int sender, int textID) | |
1231 { | |
1232 NSString text = new NSString(textID); | |
1233 int length = text.length(); | |
1234 if (length is 0) | |
1235 return; | |
1236 char[] buffer = new char[length]; | |
1237 text.getCharacters_(buffer); | |
1238 | |
1239 StatusTextEvent statusText = new StatusTextEvent(browser); | |
1240 statusText.display = browser.getDisplay(); | |
1241 statusText.widget = browser; | |
1242 statusText.text = new String(buffer); | |
1243 for (int i = 0; i < statusTextListeners.length; i++) | |
1244 { | |
1245 statusTextListeners[i].changed(statusText); | |
1246 } | |
1247 } | |
1248 | |
1249 void webView_setResizable (int sender, int visible) | |
1250 { | |
1251 } | |
1252 | |
1253 void webView_setToolbarsVisible (int sender, int visible) | |
1254 { | |
1255 /* Note. Webkit only emits the notification when the tool bar should be hidden. */ | |
1256 toolBar = visible !is 0; | |
1257 } | |
1258 | |
1259 void webView_mouseDidMoveOverElement_modifierFlags (int sender, int elementInformationID, int modifierFlags) | |
1260 { | |
1261 if (elementInformationID is 0) | |
1262 return; | |
1263 | |
1264 NSString key = NSString.StringWith(WebElementLinkURLKey); | |
1265 NSDictionary elementInformation = new NSDictionary(elementInformationID); | |
1266 id value = elementInformation.valueForKey(key); | |
1267 if (value is null) | |
1268 { | |
1269 /* not currently over a link */ | |
1270 if (lastHoveredLinkURL is null) | |
1271 return; | |
1272 lastHoveredLinkURL = null; | |
1273 StatusTextEvent statusText = new StatusTextEvent(browser); | |
1274 statusText.display = browser.getDisplay(); | |
1275 statusText.widget = browser; | |
1276 statusText.text = ""; //$NON-NLS-1$ | |
1277 for (int i = 0; i < statusTextListeners.length; i++) | |
1278 { | |
1279 statusTextListeners[i].changed(statusText); | |
1280 } | |
1281 return; | |
1282 } | |
1283 | |
1284 NSString url = (new NSURL(value.id)).absoluteString(); | |
1285 int length = url.length(); | |
1286 String urlString; | |
1287 if (length is 0) | |
1288 { | |
1289 urlString = ""; //$NON-NLS-1$ | |
1290 } | |
1291 else | |
1292 { | |
1293 char[] buffer = new char[length]; | |
1294 url.getCharacters_(buffer); | |
1295 urlString = new String(buffer); | |
1296 } | |
1297 if (urlString.opEquals(lastHoveredLinkURL)) | |
1298 return; | |
1299 | |
1300 lastHoveredLinkURL = urlString; | |
1301 StatusTextEvent statusText = new StatusTextEvent(browser); | |
1302 statusText.display = browser.getDisplay(); | |
1303 statusText.widget = browser; | |
1304 statusText.text = urlString; | |
1305 for (int i = 0; i < statusTextListeners.length; i++) | |
1306 { | |
1307 statusTextListeners[i].changed(statusText); | |
1308 } | |
1309 } | |
1310 | |
1311 void webView_printFrameView (int sender, int frameViewID) | |
1312 { | |
1313 WebFrameView view = new WebFrameView(frameViewID); | |
1314 bool viewPrint = view.documentViewShouldHandlePrint(); | |
1315 if (viewPrint) | |
1316 { | |
1317 view.printDocumentView(); | |
1318 return; | |
1319 } | |
1320 NSPrintInfo info = NSPrintInfo.sharedPrintInfo(); | |
1321 NSPrintOperation operation = view.printOperationWithPrintInfo(info); | |
1322 if (operation !is null) | |
1323 operation.runOperation(); | |
1324 } | |
1325 | |
1326 /* PolicyDelegate */ | |
1327 | |
1328 void webView_decidePolicyForMIMEType_request_frame_decisionListener (int sender, int type, int request, int frame, int listenerID) | |
1329 { | |
1330 bool canShow = WebView.canShowMIMEType(new NSString(type)); | |
1331 WebPolicyDecisionListener listener = new WebPolicyDecisionListener(listenerID); | |
1332 if (canShow) | |
1333 { | |
1334 listener.use(); | |
1335 } | |
1336 else | |
1337 { | |
1338 listener.download(); | |
1339 } | |
1340 } | |
1341 | |
1342 void webView_decidePolicyForNavigationAction_request_frame_decisionListener (int sender, int actionInformation, int request, int frame, | |
1343 int listenerID) | |
1344 { | |
1345 NSURL url = (new NSURLRequest(request)).URL(); | |
1346 WebPolicyDecisionListener listener = new WebPolicyDecisionListener(listenerID); | |
1347 if (url is null) | |
1348 { | |
1349 /* indicates that a URL with an invalid format was specified */ | |
1350 listener.ignore(); | |
1351 return; | |
1352 } | |
1353 NSString s = url.absoluteString(); | |
1354 char[] buffer = new char[s.length()]; | |
1355 s.getCharacters_(buffer); | |
1356 String url2 = new String(buffer); | |
1357 /* | |
1358 * If the URI indicates that the page is being rendered from memory | |
1359 * (via setText()) then set it to about:blank to be consistent with IE. | |
1360 */ | |
1361 if (url2.opEquals(URI_FROMMEMORY)) | |
1362 url2 = ABOUT_BLANK; | |
1363 | |
1364 LocationEvent newEvent = new LocationEvent(browser); | |
1365 newEvent.display = browser.getDisplay(); | |
1366 newEvent.widget = browser; | |
1367 newEvent.location = url2; | |
1368 newEvent.doit = true; | |
1369 if (locationListeners !is null) | |
1370 { | |
1371 changingLocation = true; | |
1372 for (int i = 0; i < locationListeners.length; i++) | |
1373 { | |
1374 locationListeners[i].changing(newEvent); | |
1375 } | |
1376 changingLocation = false; | |
1377 } | |
1378 if (newEvent.doit) | |
1379 { | |
1380 listener.use(); | |
1381 } | |
1382 else | |
1383 { | |
1384 listener.ignore(); | |
1385 } | |
1386 if (html !is null && !browser.isDisposed()) | |
1387 { | |
1388 String html = this.html; | |
1389 this.html = null; | |
1390 _setText(html); | |
1391 } | |
1392 } | |
1393 | |
1394 void webView_decidePolicyForNewWindowAction_request_newFrameName_decisionListener (int sender, int actionInformation, int request, int frameName, | |
1395 int listenerID) | |
1396 { | |
1397 WebPolicyDecisionListener listener = new WebPolicyDecisionListener(listenerID); | |
1398 listener.use(); | |
1399 } | |
1400 | |
1401 void webView_unableToImplementPolicyWithError_frame (int sender, int error, int frame) | |
1402 { | |
1403 } | |
1404 | |
1405 /* WebDownload */ | |
1406 | |
1407 void download_decideDestinationWithSuggestedFilename (int downloadId, int filename) | |
1408 { | |
1409 NSString String = new NSString(filename); | |
1410 char[] buffer = new char[String.length()]; | |
1411 String.getCharacters_(buffer); | |
1412 String name = new String(buffer); | |
1413 FileDialog dialog = new FileDialog(browser.getShell(), DWT.SAVE); | |
1414 dialog.setText(DWT.getMessage("DWT_FileDownload")); //$NON-NLS-1$ | |
1415 dialog.setFileName(name); | |
1416 String path = dialog.open(); | |
1417 NSURLDownload download = new NSURLDownload(downloadId); | |
1418 if (path is null) | |
1419 { | |
1420 /* cancel pressed */ | |
1421 download.cancel(); | |
1422 return; | |
1423 } | |
1424 download.setDestination(NSString.StringWith(path), true); | |
1425 } | |
1426 | |
1427 /* DOMEventListener */ | |
1428 | |
1429 void handleEvent (int evtId) | |
1430 { | |
1431 DOMEvent evt = new DOMEvent(evtId); | |
1432 NSString String = evt.type(); | |
1433 char[] buffer = new char[String.length()]; | |
1434 String.getCharacters_(buffer); | |
1435 String type = new String(buffer); | |
1436 | |
1437 if (DOMEVENT_KEYDOWN.opEquals(type) || DOMEVENT_KEYUP.opEquals(type)) | |
1438 { | |
1439 DOMKeyboardEvent event = new DOMKeyboardEvent(evtId); | |
1440 | |
1441 bool ctrl = event.ctrlKey(); | |
1442 bool shift = event.shiftKey(); | |
1443 bool alt = event.altKey(); | |
1444 bool meta = event.metaKey(); | |
1445 int keyCode = event.keyCode(); | |
1446 int charCode = event.charCode(); | |
1447 | |
1448 Event keyEvent = new Event(); | |
1449 keyEvent.widget = browser; | |
1450 if (DOMEVENT_KEYDOWN.opEquals(type)) | |
1451 { | |
1452 keyEvent.type = DWT.KeyDown; | |
1453 } | |
1454 else | |
1455 { | |
1456 keyEvent.type = DWT.KeyUp; | |
1457 } | |
1458 keyEvent.keyCode = translateKey(keyCode); | |
1459 keyEvent.character = cast(char) charCode; | |
1460 keyEvent.stateMask = (alt ? DWT.ALT : 0) | (ctrl ? DWT.CTRL : 0) | (shift ? DWT.SHIFT : 0) | (meta ? DWT.COMMAND : 0); | |
1461 browser.notifyListeners(keyEvent.type, keyEvent); | |
1462 if (!keyEvent.doit) | |
1463 { | |
1464 event.preventDefault(); | |
1465 } | |
1466 return; | |
1467 } | |
1468 | |
1469 if (DOMEVENT_MOUSEWHEEL.opEquals(type)) | |
1470 { | |
1471 DOMWheelEvent event = new DOMWheelEvent(evtId); | |
1472 int clientX = event.clientX(); | |
1473 int clientY = event.clientY(); | |
1474 int delta = event.wheelDelta(); | |
1475 bool ctrl = event.ctrlKey(); | |
1476 bool shift = event.shiftKey(); | |
1477 bool alt = event.altKey(); | |
1478 bool meta = event.metaKey(); | |
1479 Event mouseEvent = new Event(); | |
1480 mouseEvent.type = DWT.MouseWheel; | |
1481 mouseEvent.widget = browser; | |
1482 mouseEvent.x = clientX; | |
1483 mouseEvent.y = clientY; | |
1484 mouseEvent.count = delta / 120; | |
1485 mouseEvent.stateMask = (alt ? DWT.ALT : 0) | (ctrl ? DWT.CTRL : 0) | (shift ? DWT.SHIFT : 0) | (meta ? DWT.COMMAND : 0); | |
1486 browser.notifyListeners(mouseEvent.type, mouseEvent); | |
1487 return; | |
1488 } | |
1489 | |
1490 /* mouse event */ | |
1491 | |
1492 DOMMouseEvent event = new DOMMouseEvent(evtId); | |
1493 | |
1494 int clientX = event.clientX(); | |
1495 int clientY = event.clientY(); | |
1496 int detail = event.detail(); | |
1497 int button = event.button(); | |
1498 bool ctrl = event.ctrlKey(); | |
1499 bool shift = event.shiftKey(); | |
1500 bool alt = event.altKey(); | |
1501 bool meta = event.metaKey(); | |
1502 | |
1503 Event mouseEvent = new Event(); | |
1504 mouseEvent.widget = browser; | |
1505 mouseEvent.x = clientX; | |
1506 mouseEvent.y = clientY; | |
1507 mouseEvent.stateMask = (alt ? DWT.ALT : 0) | (ctrl ? DWT.CTRL : 0) | (shift ? DWT.SHIFT : 0) | (meta ? DWT.COMMAND : 0); | |
1508 if (DOMEVENT_MOUSEDOWN.opEquals(type)) | |
1509 { | |
1510 mouseEvent.type = DWT.MouseDown; | |
1511 mouseEvent.button = button + 1; | |
1512 mouseEvent.count = detail; | |
1513 } | |
1514 else if (DOMEVENT_MOUSEUP.opEquals(type)) | |
1515 { | |
1516 mouseEvent.type = DWT.MouseUp; | |
1517 mouseEvent.button = button + 1; | |
1518 mouseEvent.count = detail; | |
1519 switch (mouseEvent.button) | |
1520 { | |
1521 case 1: | |
1522 mouseEvent.stateMask |= DWT.BUTTON1; | |
1523 break; | |
1524 case 2: | |
1525 mouseEvent.stateMask |= DWT.BUTTON2; | |
1526 break; | |
1527 case 3: | |
1528 mouseEvent.stateMask |= DWT.BUTTON3; | |
1529 break; | |
1530 case 4: | |
1531 mouseEvent.stateMask |= DWT.BUTTON4; | |
1532 break; | |
1533 case 5: | |
1534 mouseEvent.stateMask |= DWT.BUTTON5; | |
1535 break; | |
1536 } | |
1537 } | |
1538 else if (DOMEVENT_MOUSEMOVE.opEquals(type)) | |
1539 { | |
1540 /* | |
1541 * Bug in Safari. Spurious and redundant mousemove events are received in | |
1542 * various contexts, including following every MouseUp. The workaround is | |
1543 * to not fire MouseMove events whose x and y values match the last MouseMove | |
1544 */ | |
1545 if (mouseEvent.x is lastMouseMoveX && mouseEvent.y is lastMouseMoveY) | |
1546 return; | |
1547 mouseEvent.type = DWT.MouseMove; | |
1548 lastMouseMoveX = mouseEvent.x; | |
1549 lastMouseMoveY = mouseEvent.y; | |
1550 } | |
1551 | |
1552 browser.notifyListeners(mouseEvent.type, mouseEvent); | |
1553 if (detail is 2 && DOMEVENT_MOUSEDOWN.opEquals(type)) | |
1554 { | |
1555 mouseEvent = new Event(); | |
1556 mouseEvent.widget = browser; | |
1557 mouseEvent.x = clientX; | |
1558 mouseEvent.y = clientY; | |
1559 mouseEvent.stateMask = (alt ? DWT.ALT : 0) | (ctrl ? DWT.CTRL : 0) | (shift ? DWT.SHIFT : 0) | (meta ? DWT.COMMAND : 0); | |
1560 mouseEvent.type = DWT.MouseDoubleClick; | |
1561 mouseEvent.button = button + 1; | |
1562 mouseEvent.count = detail; | |
1563 browser.notifyListeners(mouseEvent.type, mouseEvent); | |
1564 } | |
1565 } | |
1566 } |