簡體   English   中英

可可事件水龍頭

[英]Cocoa Event Taps

我正在嘗試在 OS X 上使用 Quartz 事件服務,特別是事件點擊來捕獲由連接到剝離鍵盤 PCB 的被動紅外傳感器生成的模擬按鍵。 從理論上講,通過事件點擊,我可以選擇吞下並忽略按鍵,只需使用鍵盤輸入來“喚醒”計算機。 我還可以使用事件點擊(只連接一個“鍵”,因此運動檢測器始終發送“0”)來修改任意鍵或組合鍵的輸入,進而調用主機上的任意功能. 更復雜的是,最終主機是舊的 G4 Powerbook (PPC),它不能真正運行 OS X 10.4 以外的任何東西,而我目前的開發機器是運行 10.9 並使用 Xcode 5.1 的更新的基於 Intel 的 iMac。 1.

我從這里的答案中找到了以下代碼,看起來很完美。 如果我在 Cocoa 中創建一個終端應用程序,我基本上可以按原樣使用代碼。 我還嘗試創建一個基於窗口的 Cocoa 應用程序,以防萬一這是將應用程序添加到可以在安全/隱私首選項下“控制”計算機的輔助功能應用程序列表中所必需的(在 Mavericks 中不推薦使用“啟用輔助設備訪問”)。 兩種應用程序類型都不能完全正常工作。 我能夠實現的最好方法是讓程序識別修飾鍵(命令、選項、shift、ctl 等)的按鍵,但是我無法從“常規”鍵盤鍵的按鍵中得到任何響應,並且我似乎無法實際更改捕獲的關鍵事件。 此外,似乎鼠標事件,特別是鼠標點擊,注冊為 KeyUp 和 KeyDown 事件——即使我將事件掩碼從“AllEvents”更改為“KeyUp”或“KeyDown”。

這是我對原始代碼稍加修改的版本,該版本適合嘗試符合 Xcode 5 約定。 正如您所看到的,繁重的工作在 applicationDidFinishLaunching 方法中,而不是在原始方法中的 main() 中。 顯然,我必須在 AppDelegate.h 文件中創建一個方法聲明,它也不屬於原始代碼的一部分。

#import "AppDelegate.h"
#import <Cocoa/Cocoa.h>
#import <ApplicationServices/ApplicationServices.h>
#include <Carbon/Carbon.h>


@implementation AppDelegate

CGEventRef myCGEventCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) {
    NSLog(@"In the callback");
    //0x0b is the virtual keycode for "b"
    //0x09 is the virtual keycode for "v"
    if ((type != kCGEventKeyDown) && (type != kCGEventKeyUp))
        NSLog(@"event: %@", event);
    if (CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode) == kVK_ANSI_S) {
        NSLog(@"event matched");
        CGEventSetIntegerValueField(event, kCGKeyboardEventKeycode, kVK_ANSI_1);
    }

    return event;
}

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    NSLog(@"Hello?");

    CFRunLoopSourceRef runLoopSource;

    CFMachPortRef eventTap = CGEventTapCreate(kCGHIDEventTap, kCGHeadInsertEventTap, kCGEventTapOptionDefault, kCGEventMaskForAllEvents, myCGEventCallback, NULL);

    if (!eventTap) {
        NSLog(@"Couldn't create event tap!");
        exit(1);
    }

    runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0);

    CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes);

    CGEventTapEnable(eventTap, true);

    CFRunLoopRun();

    CFRelease(eventTap);
    CFRelease(runLoopSource);

    NSLog(@"goodbye");
}

@end

在這一點上,在嘗試向后移植到 10.4 兼容性之前,我只是想在 10.9 上做一些工作作為概念證明。 抱歉,帖子太長了。 第一次在這里尋求幫助,只是想做到徹底。 在此先感謝您的任何回復!

好的,所以我對解決方案的追求使我看到了這篇關於堆棧溢出的帖子。 特別有趣的是下面突出顯示的代碼。

NSDictionary *options = @{(id)kAXTrustedCheckOptionPrompt: @YES};
BOOL accessibilityEnabled = AXIsProcessTrustedWithOptions((CFDictionaryRef)options);

這是 10.9 Mavericks 中新 API 的一部分。 將此添加到組合中會導致出現 Sys Pref/Deny 提示,最終,Xcode 本身被添加到列表中,而不是我正在處理的已編譯應用程序(這從來沒有想過我)。 即使在注釋掉這段代碼之后,它仍然有效,很明顯,因為 Xcode 現在在白名單中,這只需要做一次。 所以概念證明就在袋子里。

它似乎也適用於 10.4。 有幾個錯誤。 我不確定這部分是否必要,但我在 Powerbook 上下載並安裝了 Xcode 2.5,並直接在主機上創建和編譯了應用程序。 有兩個問題似乎與常量有關。 來自 CGEventTapCreate 函數的 kCGEventTapOptionDefault 常量(似乎它可以很容易地是一個 BOOL 而不是 uINT)在 10.4 框架頭文件中沒有定義,所以除非你將它更改為 0 或 1,否則會出現錯誤。 這似乎同樣適用於在較新系統上的 Carbon 頭文件中定義的 kVC 虛擬鍵代碼常量。 相反,我只是堅持使用十六進制值。 最后,請不要犯錯誤,試圖讓遠程桌面按鍵在遠程系統上注冊為 KeyUp 或 KeyDown 事件。 它不起作用,所以最后我有了一個聰明的主意,走到 G4 並插入鍵盤(G4 向后彎成兩半並掛在牆上,所以從前面看,它看起來只是一個安裝在上面的 LCD牆)。 瞧。 完美的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM