2010年5月26日

Cocoa Emacs のフレームをSpaces のワークスペースの上下左右に飛ばす。

個人的な使い方の問題だろうが、emacs に凝っていた頃は仮想ディスクトップ毎にフレームを置いた使い方をしていた。

この使い方の要は、elisp からフレームを任意の位置、任意のワークスペースに移動できる事であった。

既に MacOSX では仮想ディスクトップが Spaces としてサポートされている。 位置移動はできるようだが、ワークスペースの移動はどうもわからない。。。

マウスでチマチマ動かすのは、ちょっといただけない。。。

どうしたもんだろう?

Quartz のなんか

MacOSX の仮想ディスクトップは Leopard で初めてお目見えしたが、 結構前から Window Server (Quartz Compositor/Core Graphics Services/Quartz Window Services...一体いくつの名称があるんだか。。。)には実装されていたそうである。 Tiger の時代から仮想ディスクトップがサードパーティのものがあったのはそういう訳らしい。

で、コイツのAPIのほとんどが今でも非公開になっている。。。断片的には、スクリーンキャプチャ用途レベルのものが公開されている。。。なんとも厄介。

先人が調べ尽くした結果として、最後のリンクの先の内容が、 特定のウィンドウを任意のワークスペースに移動する方法らしい。

模式コードは次のようになる。(CGSPrivate.hは一番目のリンク先にあるもの)

#import <CGSPrivate.h>
...
NSWindow *win = ...;
CGSConnection cid = _CGSDefaultConnection();
CGSWindow wid = [win windowNumber]; // ?
CGSMoveWorkspaceWindowList(cid, &wid, 1, workspace);

CGSを解析した作られた CGSPrivate.h でのCGSWindow と Appleから出ているドキュメントに出てくる CGWindowID とは window server 内で割り振られた番号で同じ実体と思われるが、 NSWindow の windowNumber のドキュメントには、それとは違うと書かれている。 混ぜても動いたから多分良いかと思われるが、、、ここいらはぼかしたい内容なのかなぁ。。。分からんなぁ林檎は。

まぁ、ここまで分かれば、出来たも同然〜。

で、適当にコマンドを作ってみた。

cgsutil.m

Emacs.appの改造

(frame-parameters)には window-id があるから、Cocoa Emacs では多分コイツがフレームウィンドウの CGWindowID のはずで、コイツと飛ばしたい workspace 番号を適当に作ったコマンドに渡して、お仕舞いかなぁ。

わぁーい。らくちん。

はぅ。。。

Cocoa Emacs では window-id の値は、1から単調増になるように割り振った全く意味の無い番号でした。

仕様が無いので、次の追加機能を付けるパッチ(emacs-23-cgs-workspace.diff) を作ってみた。

  • フレームパラメータns-window-idに、CGWindowIDと思われる値
  • フレームパラメータns-workspace-idに、フレームのworkspace番号
  • フレームを指定のworkspaceに移動する関数 (set-frame-ns-workspace FRAME WORKSPACE)

まぁ、最初の一つだけで十分だが、後二つは組込まなくてもいいかも。

まとめ

上のパッチを適用した Emacs.app に適当な elispを書くと、1コマンドで複数のフレームを特定のワークスペース/特定の位置に開く事が出来るようになった。

screenshot-2010-05-26 17.54.51

うん〜〜。快適じゃ。

はぅ。。。

Cocoa Emacs で8フレームも開くと、キー入力が引っ掛かるようになり、Emacsプロセス自体のCPU利用率もイマイチ高い。イベント処理方法にまだ難があるのかなぁ。

4フレームくらいで抑えないとスムーズに使えないかなぁ。。。

追記 (2010/06/16)

複数のフレームを開いたときCPU利用率が高くなるのは、本パッチ内のframe-paramaters にワークスペース番号を追加するのが原因だった。。。frame-parameters の取得は不随に起きるらしくのでどうも軽くなくては行けない。

なので、workspace番号は取得関数から得るように変更し、workspace 絡みの部分を分けたパッチにしてみた。

  1. emacs-23-cg-window-id.diff
    • フレームパラメータns-window-idに、CGWindowIDと思われる値
  2. emacs-23-cgs-workspace.diff
    • 指定フレームのworkspaceを取得する関数 (frame-ns-workspace FRAME)
    • フレームを指定のworkspaceに移動する関数 (set-frame-ns-workspace FRAME WORKSPACE)

ふむ。
8フレームを開いても、キー入力が引っ掛かる症状は無くなった!!
すごく快適〜ん。

パッチを切ったり張ったり入れ替えたりする(1)のに、git rebase -i は極めて便利。git 優秀だなぁ

0 件のコメント: