2011年1月20日木曜日

MacRuby・CoreGraphicsその3・CGSSetWorkspaceWithTransition(workspaceのCube風切替)

CoreGraphicsのプライベート関数を使ってSpaces.appのworkspaceを切り替えるシリーズ、3回目です。

1回目 MacRuby・いきなりダークサイドに突入・CGSGetWorkspace
2回目 Spaces.app・現在のworkspaceの総数を知る

CGSPrivate.hを読んでいくと、CGSSetWorkspaceWithTransitionというメソッド(・・・今まで関数って書いてましたが、メソッドの方が正確ですね。)があるのは当初から知っていた。このメソッドの前後に、視覚効果を列挙したenumが2つあって、その中にはCGSCube、なんてのもあって、ひょっとしてcompizの「デスクトップをキューブ化」みたいな効果を操作できるんだろうか、とは考えていた。

本日はそれを試した。結果から言えばCGSSetWorkspaceWithTransitionではできない。まだ単なるCGSSetWorkspaceと同じ動きしかしないようだ。しかし方法はある。CGSNewTransitionで視覚効果を有効にしてから、CGSSetWorkspaceでworkspaceを切り替えるとCube風の動きをする。

いちおう証拠のスクリーンキャスト。



workspaceの切替の速度が遅いのはわざとです。実用的な速さにするとスクリーンキャストしても動きがさっぱりわからないので。
iMacのドでかいデスクトップ全体はキャストできなかったが、なんとなくそれっぽい動きをしているのがわかるかと思う。

何も自分で考え出した方法ではなく、CGSSetWorkspaceWithTransitionでググったら一番最初に出てくるサイトに書いてあったんですけどね。(^^;)

A Brief Tutorial on Reverse Engineering OS X

DesktopManager
という、Spacesが標準添付となる前のOSXでよく使われていたvirtual desktop managerの作者さんのblogです。CGSSetWorkspaceWithTransitionはまだ使えない、だけどリバースエンジニアリングしてこんなことがわかったよ、というDEEPな話。結果的にこのお方、こうやればCube風効果ができる、でもおれはTigerだからだめだった、友達のLeopardなら動いたよ、と書いているようです。(訂正:よくよく前記の記事を読んだら、この機能をDesktopManagerに組み込んだらちゃんと動いているよ、という内容でした)

CGSConnectionRef cid;
int transitionHandle;
int transitionSpec[5];

cid = _CGSDefaultConnection();

/* Set up the transition specification */
memset(transitionSpec, 0, 20); /* 20 = 0x14 */
transitionSpec[1] = transition;
transitionSpec[2] = direction;

/* Set up the transition itself */
CGSNewTransition(cid, transitionSpec, &transitionHandle);
/* Switch desktop */
CGSSetWorkspace(cid, workspaceNumber);
/* A little pause to let the Window Server sort itself out ... */
usleep(10000); 
/* ... and fire off the transition */
CGSInvokeTransition(cid, transitionHandle, seconds);

このコードを多少改変してObjCのSpaces classに実装した。こんな感じ。
-(void)setSpaceNumberWithTransition:(NSInteger)space {
 CGSConnection cid;
 //CGSTransitionSpec spec;
 int transitionHandle;
 int transitionSpec[5];
 
 cid = _CGSDefaultConnection();
 
 /* Set up the transition specification */
 
 memset(transitionSpec, 0, 20); /* 20 = 0x14 */
 transitionSpec[1] = CGSCube;
 transitionSpec[2] = CGSBottomLeft;
 /* Set up the transition itself */
 CGSNewTransition(cid, transitionSpec, &transitionHandle);
 /* Switch desktop */
 CGSSetWorkspace(cid, space);
 /* A little pause to let the Window Server sort itself out ... */
 usleep(6000); 
 /* ... and fire off the transition */
 CGSInvokeTransition(cid, transitionHandle, 6);
}
CGSConnectionがわからない、と怒られるので、CGSPrivate.hをimportしている。


transitionSpec[1] = CGSCube;
 transitionSpec[2] = CGSBottomLeft;

ここで実際の視覚効果を設定しているが、CGSCubeを指定するとCGSTransitionOptionは何を設定しても同じ動きしかしないようだ。

そのかわりCGSWarpSwitchとかCGSFlipを指定すると非常に楽しい動きになる。明日辺りはこれらの設定をGUIで選べるようにして遊んでみよう。

先程のRich Wareham氏のコードが2005年、同じようなことをやっていて、1枚のWindowをCube化してグリングリン動かしている、

Xcode Animations and Transitions

このサイトの記述が2006年。うーん、もっと新しい研究成果がどこかにあるような気がする。調べ方が足りないか。それともアンタッチャブルな領域なのかな。

Tigerの時点で準備されていたメソッド群だから、近いうちにOSXで「派手な視覚効果のSpaces切替」が標準で用意されるのか。

0 件のコメント:

コメントを投稿