2016-12-01 14 views
4

OS X 10.11の画面の特定の矩形領域にマウスの動きを制限したい。私はこれを行うにはMouseTools(下)からいくつかのコードを変更しましたが、画面の端にぶつかったときにはびっくりします。このジッタをどのように取り除くことができますか?ジッタのないOS Xの領域へのマウスの移動を制限する

// gcc -Wall constrain.cpp -framework ApplicationServices -o constrain 

#include <ApplicationServices/ApplicationServices.h> 

int main (int argc, const char * argv[]) { 
    if(argc != 5) { 
     printf("Usage: constrain left top right bottom\n"); 
     return 0; 
    } 
    int leftBound = strtol(argv[1], NULL, 10); 
    int topBound = strtol(argv[2], NULL, 10); 
    int rightBound = strtol(argv[3], NULL, 10); 
    int bottomBound = strtol(argv[4], NULL, 10); 
    CGEventTapLocation tapLocation = kCGHIDEventTap; 
    CGEventSourceRef sourceRef = CGEventSourceCreate(kCGEventSourceStatePrivate); 
    while(true) { 
     CGEventRef mouseEvent = CGEventCreate(NULL); 
     CGPoint mouseLoc = CGEventGetLocation(mouseEvent); 
     int x = mouseLoc.x, y = mouseLoc.y; 
     if(x < leftBound || x > rightBound || y < topBound || y > bottomBound) { 
      if(x < leftBound) x = leftBound; 
      if(x > rightBound) x = rightBound; 
      if(y < topBound) y = topBound; 
      if(y > bottomBound) y = bottomBound; 
      CGEventRef moveMouse = CGEventCreateMouseEvent(sourceRef, kCGEventMouseMoved, CGPointMake(x, y), 0); 
      CGEventPost(tapLocation, moveMouse); 
      CFRelease(moveMouse); 
     } 
     CFRelease(mouseEvent); 
     usleep(8*1000); // 8ms, ~120fps 
    } 
    CFRelease(sourceRef); 
    return 0; 
} 

は、ここに私が試した他のいくつかのものです:Receiving, Filtering, and Modifying Mouse EventsCGEventTapCreateを使用して、マウスの動きのためのコールバックを作成する方法を示しています。コードでは、「マウスイベントの側面を変更することができます。たとえば、CGEventSetLocation(event, newLocation)を使用できます。残念ながら、これは実際にはマウスの位置を変更しません(完全な例here)。マウスの位置を変更できる唯一の方法は、CGEventPostまたはCGWarpMouseCursorPositionです。またkCGSessionEventTapの代わりに kCGHIDEventTapを試してみましたが、私はスーパーユーザーのアクセス許可とアクセシビリティがアプリで有効になっていることを確認しました。それは正常に動作するmodifying key pressesの別の例があるので、うまくいくように思えます。 CGEventSetLocationの代わりにCGEventSetIntegerValueField(キーボードの例のような)を使ってxとyのデルタを0に設定しようとしましたが、これは何も変わりませんでした。

最後に、私もCGEventCallbackの中にCGEventPostCGWarpMouseCursorPositionを使ってみましたが、 "見えない境界"はまだ上記のコードよりもジッタがあります。

+0

問題の説明は冗長です。 AppleScriptプログラムで問題が発生しない限り、AppleScriptプログラムで何をしたかは誰も気にしません。 –

+1

@ElTomato私は、AppleScriptでの最初の試行を説明する2つの文章と私が持っていた問題を削除することで、問題をあまり詳しく説明しませんでした。このトピックについて何か知っているとすれば、私は更新された質問にあなたのご意見をお寄せください。ありがとう! –

+0

マウスの動きは誰に拘束されますか?あなたのコンピュータやあなたのアプリケーションのユーザーを使っている人は誰ですか? –

答えて

3

私はMacのドライバでWine用にこれを実装しました。それは少し複雑になる。

基本的には、CGAssociateMouseAndMouseCursorPosition(false)を呼び出してマウスカーソルの移動を無効にする方法があります。ここでは、制約のある矩形がカーソルの現在の位置で1x1の矩形である場合に必要なものが得られます。

さらに、イベントタップを使用してマウスの移動イベントを観察します。これらは位置を変えるものではなく、ユーザーが試みたもののデルタを持っています。次に、CGWarpMouseCursorPosition()を使用して、それらのデルタにしたがってカーソルを移動し、それらを渡す前にイベントを調整します。

マウスイベント内の位置情報は意味がありません。それは古くなります。イベントの中には、最後のワープの前にキューに入れられているものもあるため、古い場所があります。カーソルがどこにあるかを追跡する必要があります。それはあなたがそれをマウスから切り離し、あなたがそれを歪ませるたびに変化するときはいつでも始まります。デルタを(イベントの場所ではなく)それを追加し、制約のある矩形にクリップし、それをイベントとワープの新しい位置として使用します。次のイベントでは、この新しいポジションからスタートします。その他

余計なしわがあります。 CGWarpMouseCursorPosition()は、その後のマウス移動イベントのデルタ値に影響します。基本的には、カーソルをワープした距離が、ワープの後にキューに入れられた最初のマウス移動イベントに追加されます。チェックを外すと、これは暴走フィードバックループのためにイベントごとにユーザーのマウスの動きを効果的に倍増させ、カーソルは一方の極端に撃たれます。

したがって、実行したワープと、実行したときの位置と、その位置を変更した程度を記録しておく必要があります。次に、イベントがタップを介して来ると、彼らの時間をワープ時間と比較します。現在のイベントよりも前のワープについては、イベントのデルタからポジションの変更を差し引いてリストから削除します。

+0

Kenさん、ありがとうございます。あなたが説明していることは、最良の解決策のように聞こえる。 Wine for Macに関するおかげさまで、ありがとうございました! –

関連する問題