MacOSX で Window マネージャー的なことをやりたい using Accessibility API
でもちょいマトモな方法として Accessibility API というのがあると。これはそもそも機能全体がデフォルトではオフになっていて、環境設定からユニバーサルアクセスかなんかをオンにしないと使えない。まぁ便利なのでオンにしたらいいんじゃないのと思う。
これ何する API かっていうと、要はウィンドウの情報取得や、ユーザーがマウスやキーボードで行えることをエミュレートする、っていう API らしい。たぶん Apple Event とかいうので通信する。んでたぶんかなり重い。 Apple Script っていうのはたぶんこの API のフロントエンド。 Apple Script 重いって言われてるけどたぶんこの層がそもそも重いんだと思う。ていうかなんでこんなに重いかは不明。使いかた間違ってるかも。特になんか取れない情報取ろうとするとすごいことになる。
でこれもまぁ全然情報無いんだよなー。便利なのに。そろそろ文章書くの飽きてきたので win.cc 参照! とかでいい気もする。んと、 C でこいう汎用的なデータのやりとりするの大変ね、という。 libdwarf とかのめんどくささに似てるか。まぁ少し書こう。
まず、
AXUIElementRef appRef = AXUIElementCreateApplication(pid);
なり
AXUIElementRef sysRef = AXUIElementCreateSystemWide();
なりで根っこのオブジェクトが取ってくる。目的のプロセスが定まってる場合は前者で pid 使って取ってくる。んであとは UI Inspector で適当に調べたいウィンドウとかがどの情報を取れるか調べて、ずるずると拾ってくる。んー例えば
AXUIElementRef winRef; AXUIElementCopyAttributeValue(app, kAXFocusedWindowAttribute, &winRef);
とかこんな感じで(castいるかも)、さっきのアプリの中でフォーカスのあたってるウィンドウを拾ってくる、とかができる。似たような感じで Window の中のタイトルを拾ってきたら Core Foundation の String がとってこれるし、 Window の中の最大化ボタンを拾ってきて、そのボタンを押したシミュレートをさせる、とかもできる。例えば今拾ってきた Window を上に持ってくるなら
AXUIElementPerformAction(winRef, kAXRaiseAction);
とかでマウスクリックした時のシミュレートになる。そんな感じ。たぶん。
このへんの API は Witch は知ってるはずだ…とか思って witchdaemon を nm してて気付いた。ていうか今回書いたような内容はほとんどばいなりー的な知識で仕入れた気がする。 ktrace&kdump で CoreGraphics.framework という名前を知ったし。まぁオブジェクトファイルがあったらとりあえず挨拶がてら nm しとけっていう話。あと ADC のドキュメントはなんか古いのかあってないので基本的な使い方わかったらヘッダ見るといい。
あと、
の OSX の内容もちょこっと書き足した。あと PBH からもリンクはったけど、 OSX でばいなりーな内容はこちらの方の記述が色々面白かったです。