-
-
Save abock/30b40e937c9507ba2f59 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// ViewController.cs | |
// | |
// Author: | |
// Aaron Bockover <abock@xamarin.com> | |
// | |
// Copyright 2015 Xamarin Inc. All rights reserved. | |
using System; | |
using Foundation; | |
using JavaScriptCore; | |
using AppKit; | |
using WebKit; | |
namespace JSExportTest | |
{ | |
public partial class ViewController : NSViewController | |
{ | |
public ViewController (IntPtr handle) : base (handle) | |
{ | |
} | |
public override void ViewDidLoad () | |
{ | |
base.ViewDidLoad (); | |
// ideally we would subscribe to webView.JavaScriptContextCreated, but | |
// XM does not bind WebKit/JSC-ObjC bridge APIs: | |
// https://bugzilla.xamarin.com/show_bug.cgi?id=32975 | |
webView.FinishedLoad += (sender, e) => { | |
var doc = webView.MainFrameDocument; | |
AttachListener (doc.GetElementById ("broken-button"), new BrokenDomEventListener ()); | |
AttachListener (doc.GetElementById ("working-button"), new DomEventListener ()); | |
}; | |
webView.MainFrame.LoadHtmlString ( | |
@"<html><body> | |
<button id='broken-button'>Broken</button> | |
<button id='working-button'>Working</button> | |
</body></html>", | |
null); | |
} | |
void AttachListener (DomElement elem, NSObject listener) | |
{ | |
// should just be webView.MainFrame.JavaScriptContext (bug #32975) | |
var jsContext = JSContext.FromJSGlobalContextRef (webView.MainFrame.GlobalContext); | |
// should just be elem.JSValue (bug #32975) | |
var jsButton = JSValue.FromJSJSValueRef (elem.JSObject, jsContext); | |
jsButton.Invoke ("addEventListener", | |
JSValue.From ("click", jsContext), // event | |
JSValue.From (listener, jsContext), // listener | |
JSValue.From (true, jsContext) // useCapture | |
); | |
} | |
// The broken event listener's HandleEvent(JSValue) will not be invoked | |
// as it appears the XM runtime is blocking trying to convert the JSC | |
// value to a JSValue (or any NSObject...) | |
[Protocol] | |
interface IBrokenDomEventListener : IJSExport | |
{ | |
[Export ("handleEvent:")] | |
void HandleEvent (JSValue evnt); | |
} | |
class BrokenDomEventListener : NSObject, IBrokenDomEventListener | |
{ | |
public void HandleEvent (JSValue evnt) | |
{ | |
Console.WriteLine ("JS -> C# Event: {0}", evnt); | |
} | |
} | |
// Luckily a workaround is to export a method to JSC with no arguments | |
// and access the current invocation's arguments via JSContext | |
[Protocol] | |
interface IDomEventListener : IJSExport | |
{ | |
[Export ("handleEvent")] | |
void HandleEvent (); | |
} | |
class DomEventListener : NSObject, IDomEventListener | |
{ | |
public void HandleEvent () | |
{ | |
Console.WriteLine ("JS -> C# Event: {0}", JSContext.CurrentArguments [0]); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment