sf2xrniがひと段落ついた、というより公式フォーラムなどに投げてみても全く反応が無くてフィードバックも無いので、これ以上自分でバグ潰しするのは何か打ち込む時にしようと決めて、こっちは放置することにした。
というわけで、次はlemurもどきだ。月初にGUI設計をHTMLベースで記述する可能性について考えたわけだけど、今週は知人とも何となく相談してみたりなどして、これをもう少し具体的に検討してみた。なるべくcocoatouchでもandroidでも動くようなコードの共通化を実現したい。
まずWebページとバックエンドロジック(OSCの送信など)のinteropについて。webviewとGUIフレームワークなんて出来るのか分からんから、とりあえずHTTPサーバをローカルで立てて、ブラウザはそこを叩き、HTTPサーバがバックエンドのロジックを実行するのはアリだろうと考えた。HttpListenerがlocalhost:8080で動いていて、webページはそこをPOST先にする、といった感じだ。動くかもしれないけど、多少回りくどいので重いだろう。
それより、もう少し直接的に、Javascriptとネイティブオブジェクトのinteropが可能なのではないかと思って調べてみた。そうしたら、案の定出てきた。
CocoaTouchの場合: WebScriptObjectというプロクシを経由することで、Objective-Cの関数を呼び出せるようだ。webViewのwindowScriptObjectに、オブジェクトをプロパティとしてsetすることで、Javascript上でwindowオブジェクトのプロパティとしてアクセスできる。
- Androidの場合: WebViewクラスのaddJavaScriptInterface()を使うことで、Javaオブジェクトを変数にバインドできるようだ。
どちらもそれほど難しいものではなさそうだ。anowaveを作った時に使ったflashとjavascriptのinteropと、仕組みは類似している。SilverlightのRegisterScriptableObject()も同じようなものだと言えるだろう。
追記: SafariのJS proxyの情報は正しくないようだ。というのは、これはあくまでCocoaだけのもので、CocoaTouchでは使えないらしい。これは困った...まあHTTPサーバを裏で立てれば良い問題ではあるけど。
interopが実現出来そうだと分かったので、次はUIをどう記述するかが問題だ。先日はHTML Canvasを使えば良いと思っていたけど、やりたいことを考えれば、むしろSVGを使う方がずっと簡単ではないかと気がついた。
しかしそこで気になったのは、まずSVGツリーでタッチイベントを取得できるのかという問題だ。SVG DOMがHTML DOMとどこまで実装を共有しているかは分からないし、SVG DOMは少なくとも標準仕様としてはtouch UIを前提としていないので、サポートされていない可能性だってある。というわけで、ひとつテストケースを作ってみた。ちなみにtouchイベントの使い方はここで簡単に説明されているが、document.addEventListener("touchstart") などを利用する。iPhoneでアクセスしてみたところ、タッチイベントはSVGツリー上でも無事取得できているようだ。
問題はここからだ。まず、上記テストケースにAndroidのエミュレータ上からアクセスしてみたが、そもそもSVGが表示されない。調べてみると、どうやらAndroid上のWebKitはSVGをサポートしていないようだ。Safari上のWebKitはcairoを使っているが、Androidではgoogleが開発したskiaが使用されている。おそらくその関係で、SVGのサポートまでは手が回っていないのだろう。そもそも、cairoベースのwebkitにおけるSVGの実装自体、昨年あたりにexperimentalとして追加されたもので、SVGのテストを含むACID3を100%通過したのも最近のことのはずだ。この件について見つけられた情報は、半年くらい前にまだちゃんとビルドできないと書かれたものだった。
追記: これは違いそうだ。webkitがcairoを使っているというのは、むしろ一部のプラットフォームやビルドの話のようだ。ソースを見ての判断ではないけど、おそらく基本的にはskiaなのだろう。androidに含まれていない理由は、ビルドできなかったという以上のことは分からない。
次に、タッチイベントが取得できたといっても、今回のプロジェクトで本当に使いたいのは、シングルタッチではなくマルチタッチだ。先に紹介したページでも説明されているけど、iPhoneではマルチタッチのイベントはgesturestartなど別のイベント種別で定義されていて、これらはAndroid上では実装されていない。そもそもtouchstartなどはWebKitのソースに含まれているが、gesturestartなどは含まれていない。マルチタッチのイベント定義については、WebKitはMozillaとも異なるし、おそらくAppleが特許権を行使したりなどしているせいで、混沌としている状態だろう。
ただ、最近になってAndroidではマルチタッチをサポートするようになり(そのためAppleが特許権侵害を主張したりなどして騒ぎになっている)、その関係でWebKitでもマルチタッチがサポートされるようになっている。はずだ。今日詳しい知人から聞いたところでは、APIのレベルでも追加されているはずではないかとのことだった。ただ、androidのソース上では、それに対応するイベントは定義されていないようなので、Googleのeclairの独自ビルドに限定されているのかもしれない。
そもそもマルチタッチのイベントは実機(しかもnexusOneなど2.1対応のもの)が無いと拾えないので、確認のしようもない。そろそろ観念して実機を入手した方が良いかもしれない。
まあ、数ヶ月待てば、この辺りはだいぶ状況が変わりそうな気もするので、基本的にこの方向性で進めてみても良いのかもしれない。