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 }