Google Code Prettify

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 件のコメント:

久しぶりの投稿

かなり期間が空いてしまったが、ブログを再開してみようと思う。 2013年3月が直前の投稿だったが、頻繁に更新していた時期が 2011年11月までなので、8年間ぶりとなる。 8年間なにをしていたのかと言えば、2回転職して未だにIT技術者の職を得ている。 その...