デスクトップ上にでかい透明ウィンドウをはりつけて、という方法しか思いつかなかったけれど、以前一度触れた「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 件のコメント:
コメントを投稿