デスクトップ上にでかい透明ウィンドウをはりつけて、という方法しか思いつかなかったけれど、以前一度触れた「NSEvent addGlobalMonitorForEventsMatchingMask:handler:」を使えばけっこう簡単に実現できる。
[NSEvent addGlobalMonitorForEventsMatchingMask:NSScrollWheelMask
handler:^(NSEvent* event) {[self isDeskTop:event];}];
てな感じでイベントハンドラを指定しておけば、とりあえずどこで起ころうとscrollWheelイベントは拾うことができる。あとはeventの中から、scrollWheelが起きた場所なりウィンドウIDなりを取り出せば、それがデスクトップで起きたかどうか分かるはず。こういう時はCGSPrivate.hの中の
extern CGError CGSGetWorkspaceWindowCount(const CGSConnection cid, CGSWorkspace workspaceNumber, int *outCount); extern CGError CGSGetWorkspaceWindowList(const CGSConnection cid, CGSWorkspace workspaceNumber, int count, int* list, int* outCount);この2つを使えばなんとかなるはずなのでさっそくググって調べてみた。(もちろんxcatsan師匠ご推奨のCGWindowListCopyWindowInfoという手もあるわけだが、こっちは「全部のワークスペースのWindow」が拾えてしまうのでかえってloopに時間がかかりそう)
蛇の道は蛇、ちゃんとこの2つのプライベート関数を使って「現在のワークスペースにあるWindowを取得する」方法がまんまネット上に落ちていた。
Paste number 31828: leet
便利そうなコードをコピペしておいておく、というサイトなのかしらん。
ここに載っていたコードはWindowのID、領域のRect、タイトルを取得しているのだが、デスクトップで起きたかどうかはwindowIDさえあればいいようなので多少編集して、次のようにしてみた。
int err;
CGSConnection connection;
int workspace;
int numberOfWindows;
int *windowList;
BOOL notDeskTop=NO;
connection = _CGSDefaultConnection();
CGSGetWorkspace(connection, &workspace);
CGSGetWorkspaceWindowCount(connection, workspace, &numberOfWindows);
if (numberOfWindows>0) {
windowList = (int*)malloc(sizeof(int) * numberOfWindows);
err = CGSGetWorkspaceWindowList(connection, workspace, numberOfWindows,
windowList, &numberOfWindows);
//NSLog(@"There are %d windows", numberOfWindows);
if( err != 0)
NSLog(@"Couldn't get window list, err=%d", err);
else
{
//NSLog(@"Got window list!");
int windowId;
for(int i = 0; i < numberOfWindows; ++i)
{
windowId = windowList[i];
if (windowId==[event windowNumber] ) {
notDeskTop=YES;
}
}
}
}
if (notDeskTop==NO) {
[self scrollWheel:event];
}
if (numberOfWindows>0)を入れないとウィンドウなしのWorkspaceだと必ずエラーが出る、と。「notDesktop」などというダサいflagはもちろん私が入れた豚野郎コードでありますな。もう少しなんとか書き直そう。とりあえず動けばいい、というコードなんで。CGSGetWorkspaceWindowListで得られるwindowIDはeventのwindowNumberと同じなので、どのwindow上のeventかの判断か簡単にできる。Workspace上のどのウィンドウ上でもなければデスクトップと判断して、マウスイベントハンドラを呼び出している。
これだけでデスクトップ上、どこでマウスホィールを回してもWorkspaceが切り替えられた。うむ、いいぞ。
む?書き終わって気づいたんだけど、デスクトップにウィンドウをもっていないアプリの上でホイール回しても切り替わってしまいますな。Dockの上とかMenuバーの上とか。ま、いいか。
0 件のコメント:
コメントを投稿