2011-08-15
Safari 5.1 WebKit2 WKView の Client 関数を置き換える
WebView にあった各種 delegate は Cocoa の流儀で実装されていたのでやりやすかったのだけど WKView ではそれがなくなってしまい、泣いてました。これができるかどうかが SafariStand にとって死活問題。
WebKit2 では delegate ではなく WKPageXxxClient という呼び方になっている。Objective-C クラスではなく関数をまとめた構造体。setter はあるが getter がないため元の値を取っておくのが難しい。WebKit2 側の保存場所をつきとめるか、Safari 側の呼び出しを捉えるか。で、前者が見つかったので対応してみる。
WKView → WKViewData → webPageProxy と辿ると、Client の構造体を捕まえられる。この関数ポインタを自前のものと置き換えればOKのようだった。Objective-C クラスとは違ってメソッドが存在しているかどうかなどのチェックを動的に行えないので、けっこう危険な橋なんだけどとにかく渡る。具体的なソースコードはこちらから。
WebKit2 WKView client hook for Safari 5.1 ― Gist
パッチをするタイミングだが、[TabContentView initWithFrame:(CGRect) andBrowserWKView:(id)] の引数に WKView が渡されるのでここで捕まえた。また現行 SIMBL の仕様により、ロード時点で生成済みの WKView も存在するので、ウインドウを巡回するなどして既存の WKView にパッチする必要がある。
コンテキストメニューもこれでいじれるとは思うが、
SIMBL プラグインで Safari 5.1 のコンテキストメニューに項目を追加する - Yarukidenized:ヤルキデナイズド
の方が NSMenu を扱えるから楽だろう。ちなみに文字列を選択しているかどうかの判別など追加した版はこちら。
