2010-12-23 118 views
5

我試圖添加事件陷阱來啓用/禁用來自我的觸控板的事件。我認爲這會很簡單,即註冊一個事件陷阱,並在需要時通過返回NULL來放棄該事件。這個想法是使用pad來處理一些特定的,耗時的數據輸入,輸入數據的應用程序是第三方的,所以我不能只是添加代碼來達到我想要的目的。所以我想我會監視系統事件,然後通過一堆CGEventCreateKeyboardEvent s發送所需的輸入。使用事件觸發消耗OSX鼠標/觸控板事件

問題是返回null似乎沒有放棄事件,多一點調查表明,這不限於那些來自觸控板,但也是我的默認USB鼠標。

我的代碼如下。如果我改變(A)使用kCGEventScrollWheelkCGEventLeftMouseDragged,那麼事件將被消耗,即滾動或左側btn拖動不會發生,因此我預計不能移動鼠標。這是否意味着並非所有事件都可以被丟棄?但願我只是缺少明顯的東西在這裏

#define case_print(a) case a: printf("%s - %d\n",#a,a); break; 


    CGEventRef eventOccurred(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void* refcon) { 
    int subType = CGEventGetIntegerValueField(event, kCGMouseEventSubtype); 
    if (type == NSEventTypeGesture || subType == NX_SUBTYPE_MOUSE_TOUCH) { 
     printf("touchpad\n"); 

     switch(type) { 
       case_print(kCGEventNull) 
       case_print(kCGEventLeftMouseDown) 
       case_print(kCGEventLeftMouseUp) 
       case_print(kCGEventRightMouseDown) 
       case_print(kCGEventRightMouseUp) 
       case_print(kCGEventMouseMoved) 
       case_print(kCGEventLeftMouseDragged) 
       case_print(kCGEventRightMouseDragged) 
       case_print(kCGEventScrollWheel) 
       case_print(kCGEventOtherMouseDown) 
       case_print(kCGEventOtherMouseUp) 
       case_print(kCGEventOtherMouseDragged) 
       case_print(kCGEventTapDisabledByTimeout) 
       case_print(kCGEventTapDisabledByUserInput) 
       case_print(NSEventTypeGesture) 
       case_print(NSEventTypeMagnify) 
       case_print(NSEventTypeSwipe) 
       case_print(NSEventTypeRotate) 
       case_print(NSEventTypeBeginGesture) 
       case_print(NSEventTypeEndGesture) 
      default: 
       printf("default: %d\n",type); 
       break;  
     } 

     event = NULL; 
    } else { 
     if (type == kCGEventMouseMoved) { // (A) 
      printf("discarding mouse event"); 
      event = NULL; 
     } 
    } 

    return event; 
} 


CFMachPortRef createEventTap() { 
    CGEventMask eventMask = NSAnyEventMask; 

    if (!AXAPIEnabled() && !AXIsProcessTrusted()) { 
     printf("axapi not enabled"); 
    } 

    return CGEventTapCreate(kCGHIDEventTap, 
          kCGHeadInsertEventTap, 
          kCGEventTapOptionDefault, 
          eventMask, 
          eventOccurred, 
          NULL); 
} 

int main (int argc, const char * argv[]) { 
    CFMachPortRef tap = createEventTap(); 

    if (tap) { 
     CFRunLoopSourceRef rl = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, tap, 0); 
     CFRunLoopAddSource(CFRunLoopGetMain(), rl, kCFRunLoopCommonModes); 
     CGEventTapEnable(tap, true); 
     CFRunLoopRun(); 

     printf("Tap created.\n"); 
     sleep(-1); 
    } else { 
     printf("failed!\n"); 
    } 

    return 0; 
} 

注意,「未啓用axapi」不輸出雖然我不認爲輔助功能選項將影響任何東西,但鍵盤事件。

順便說一句,我已經看到了一些類似的帖子,關於如何從觸摸板獲取事件,只是沒有適用於丟棄它們(除了返回null應該工作)。

回答

1

如果您的抽頭是被動的,返回NULL將不會影響事件流。從CGEventTapCallBack參考文檔:

「如果事件水龍頭是一個被動 聽衆,你的回調函數可以 返回傳遞中,或 NULL事件在任何一種情況下,事件流 不影響「。

但是,它看起來像您的水龍頭活躍。因此,您返回的NULL應該刪除該事件。你有沒有考慮修改事件以使操作無效?

另請注意,調用CGEventTapCreate需要root用戶權限才能截取所有事件。你的進程是以root身份運行的嗎?

+0

爲什麼這個標記爲答案嗎?你是否能夠阻止處理鼠標事件?我可以停止按鍵事件,但不能移動鼠標...... – cksubs 2012-03-23 22:29:40

4

我認爲atm不可能簡單地放棄這些事件。從CGEventTypes.h頭文件:

「傳遞給回調的事件是 由調用代碼保留下來,是 發佈的回調函數返回 並將數據傳回 事件後系統。如果不同的事件通過回調函數返回 , 那麼該事件將被 與 原始事件一起調用代碼發佈, 已傳回事件 系統中的事件數據後「。

我已經玩了一會兒,看起來在回調返回後,窗口服務器再次主動檢查你對事件做了什麼。它只允許刪除關鍵事件和鼠標上/下事件,但正如它忽略刪除鼠標移動的事件(好吧,鼠標渲染在別處處理,我猜),它似乎忽略刪除(即您的回調返回NULL)爲鼠標手勢。

數字,考慮到手勢的輕敲沒有在文檔中具體說明(在此級別沒有定義的類型)。

我試着返回一個不同的事件(一個按鍵),然後這個處理額外處理原始手勢。在回調中釋放事件並不會執行此操作,當然,這隻會導致異常。

我沒有嘗試的唯一方法是直接操縱傳遞的CGEvent的內部數據,至少讓手勢什麼都不做(刪除所有的動作等),但這很難,因爲沒有定義特定的方法來做那。不過,我很確定所需的信息是通過CGEventSet *方法訪問的各個字段中的某處。

我向下看IOLLEvent.h來找出他們的數據結構,但這對我的口味來說太難看了,無法深入挖掘。讓我們希望Lion提供一些有關CF級別上的手勢類型的事件。

+1

這將是CGEventSetIntegerValueField(event,kCGMouseEventDeltaX,0);和CGEventSetIntegerValueField(event,kCGMouseEventDeltaY,0);但也被忽略。 – valexa 2011-04-29 11:53:23

3

我可以證實,在10.6上,以下兩種方法都無法成功實現此目的。

1-返回NULL

2-返回新的鼠標事件與前一光標位置

3-返回與它傳遞的活動的kCGMouseEventDelta的改變爲0

我不能10.7說話但讓我們只是說我不會讓我的希望。

然而,有一件事你可以做,而不是放棄運動,使用CGWarpMouseCursorPosition將它移回到之前的位置,實際上光標將停止移動,只有第一個稍微改變。

+0

我的經驗是一樣的......不能返回null或修改delta以防止鼠標移動。我將光標移回,但光標仍在原始位置閃爍。希望能夠阻止這裏:http://stackoverflow.com/questions/9899534/prevent-mousemovedevent-callback-from-processing-the-movement-or-globally-hid – cksubs 2012-03-28 01:27:35