2011-08-25 3 views
7

코코아 플래그 변경 이벤트가 없기 때문에 IOHIDManager를 사용하려고합니다 (보도 자료/보도 자료가 구별하기 어려움, 둘 다 중단 된 경우 등). 여기서 관리자를 만들고 콜백을 등록하십시오.IOHIDManager를 사용하여 수정 자 키 이벤트 가져 오기

IOHIDManagerRef hidManager = IOHIDManagerCreate(kCFAllocatorDefault, 
     kIOHIDOptionsTypeNone); 
if (CFGetTypeID(hidManager) != IOHIDManagerGetTypeID()) 
    return 1; 

CFMutableDictionaryRef capsLock = 
    myCreateDeviceMatchingDictionary(0x07, 0x39); 
CFMutableDictionaryRef lctrl = 
    myCreateDeviceMatchingDictionary(0x07, 0xE0); 
CFMutableDictionaryRef lshift = 
    myCreateDeviceMatchingDictionary(0x07, 0xE1); 
CFMutableDictionaryRef lalt = 
    myCreateDeviceMatchingDictionary(0x07, 0xE2); 
CFMutableDictionaryRef lsuper = 
    myCreateDeviceMatchingDictionary(0x07, 0xE3); 
CFMutableDictionaryRef rctrl = 
    myCreateDeviceMatchingDictionary(0x07, 0xE4); 
CFMutableDictionaryRef rshift = 
    myCreateDeviceMatchingDictionary(0x07, 0xE5); 
CFMutableDictionaryRef ralt = 
    myCreateDeviceMatchingDictionary(0x07, 0xE6); 
CFMutableDictionaryRef rsuper = 
    myCreateDeviceMatchingDictionary(0x07, 0xE7); 

CFMutableDictionaryRef matchesList[] = { 
    capsLock, 
    lctrl, 
    lshift, 
    lalt, 
    lsuper, 
    rctrl, 
    rshift, 
    ralt, 
    rsuper 
}; 
CFArrayRef matches = CFArrayCreate(kCFAllocatorDefault, 
     (const void **)matchesList, 9, NULL); 
IOHIDManagerSetDeviceMatchingMultiple(hidManager, matches); 

IOHIDManagerRegisterInputValueCallback(hidManager, 
     myHandleModifiersCallback, NULL); 

IOHIDManagerScheduleWithRunLoop(hidManager, CFRunLoopGetMain(), 
     kCFRunLoopDefaultMode); 

IOHIDManagerOpen(hidManager, kIOHIDOptionsTypeNone); 

그러나 콜백은 절대로 실행되지 않습니다. 내가 놓친 게 있니?

HID 사용 페이지를 완전히 이해하지 못하기 때문에 키보드 사용 ID (06) 또는 키보드/키패드 페이지 (0x07)와 함께 일반 데스크톱 페이지 (0x01)를 사용할지 여부를 알지 못했습니다. 개별 키의 ID. 어쩌면 그것과 관련이있는 것일까 요?

답변

9

나는 그것을 알아 냈다. 이를 수행하는 방법은 IOHIDManagerSetDeviceMatchingMultiple과 함께 사용하기 위해 일반 데스크탑 페이지 (0x01) 키보드 (06) (및 키패드 (07))를 사용하고 입력 값 콜백이 키보드/키패드 사용 페이지 (0x07) 항목을 가져 오는 것입니다. 사람이 뭔가를 할 수있는 예를 들어

, 모든 키보드/키패드에 대한 설정에 HIDManager :

IOHIDManagerRef hidManager = IOHIDManagerCreate(kCFAllocatorDefault, 
     kIOHIDOptionsTypeNone); 

CFMutableDictionaryRef keyboard = 
    myCreateDeviceMatchingDictionary(0x01, 6); 
CFMutableDictionaryRef keypad = 
    myCreateDeviceMatchingDictionary(0x01, 7); 

CFMutableDictionaryRef matchesList[] = { 
    keyboard, 
    keypad, 
}; 
CFArrayRef matches = CFArrayCreate(kCFAllocatorDefault, 
     (const void **)matchesList, 2, NULL); 
IOHIDManagerSetDeviceMatchingMultiple(hidManager, matches); 

IOHIDManagerRegisterInputValueCallback(hidManager, 
     myHIDKeyboardCallback, NULL); 

IOHIDManagerScheduleWithRunLoop(hidManager, CFRunLoopGetMain(), 
     kCFRunLoopDefaultMode); 

IOHIDManagerOpen(hidManager, kIOHIDOptionsTypeNone); 

어디 myCreateDeviceMatchingDictionary 뭔가 같은 :

CFMutableDictionaryRef myCreateDeviceMatchingDictionary(UInt32 usagePage, 
     UInt32 usage) { 
    CFMutableDictionaryRef ret = CFDictionaryCreateMutable(kCFAllocatorDefault, 
      0, &kCFTypeDictionaryKeyCallBacks, 
      &kCFTypeDictionaryValueCallBacks); 
    if (!ret) 
     return NULL; 

    CFNumberRef pageNumberRef = CFNumberCreate(kCFAllocatorDefault, 
      kCFNumberIntType, &usagePage); 
    if (!pageNumberRef) { 
     CFRelease(ret); 
     return NULL; 
    } 

    CFDictionarySetValue(ret, CFSTR(kIOHIDDeviceUsagePageKey), pageNumberRef); 
    CFRelease(pageNumberRef); 

    CFNumberRef usageNumberRef = CFNumberCreate(kCFAllocatorDefault, 
      kCFNumberIntType, &usage); 
    if (!usageNumberRef) { 
     CFRelease(ret); 
     return NULL; 
    } 

    CFDictionarySetValue(ret, CFSTR(kIOHIDDeviceUsageKey), usageNumberRef); 
    CFRelease(usageNumberRef); 

    return ret; 
} 

그리고 myHIDKeyboardCallback이 같은 것을입니다 :

void myHIDKeyboardCallback(void *context, IOReturn result, void *sender, 
     IOHIDValueRef value) { 
    IOHIDElementRef elem = IOHIDValueGetElement(value); 
    if (IOHIDElementGetUsagePage(elem) != 0x07) 
     return; 
    uint32_t scancode = IOHIDElementGetUsage(elem); 
    if (scancode < 4 || scancode > 231) 
     return; 
    long pressed = IOHIDValueGetIntegerValue(value); 
    // ... Do something ... 
} 

콜백은 프레스 또는 릴리스 당 여러 번 호출되지만 사용 범위 ID가 정상 범위를 벗어나면 "if (scancode < 4 || 스캔 코드는> 231) "입니다. 귀하의 질문에 대한 답변을 제공하는

+0

콜백에서 'value'를 구문 분석하여 스캔 코드와 같은 정보를 얻는 방법에 대한 정보는 어디서 찾았습니까? 그것에 대한 (읽을 수있는) 참조가 있습니까? 아니면 어떻게 알아 냈습니까? – jalf

4

들으. 대신 스캔 코드 검사 myHIDKeyboardCallback의 경우 문의

< 당신이 IOHIDManagerSetInputValueMatching을 사용할 수 있습니다> (231) 4 스캔 코드.

// before IOHIDManagerOpen 
int usageMin = 4; 
CFNumberRef minNumberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usageMin); 
CFDictionarySetValue(inputValueFilter, CFSTR(kIOHIDElementUsageMinKey), minNumberRef); 
CFRelease(minNumberRef); 

int usageMax = 231; 
CFNumberRef maxNumberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usageMax); 
CFDictionarySetValue(inputValueFilter, CFSTR(kIOHIDElementUsageMaxKey), maxNumberRef); 
CFRelease(maxNumberRef); 

IOHIDManagerSetInputValueMatching(hidManager, inputValueFilter); 

는 더 LOC는 경우 문 간단하지만, 당신은 청소기 콜백으로 끝낼.

+0

잘 알고 있습니다. kIOHIDElementUsagePageKey를 사용하여 요소 사용 페이지를 0x07로 제한 할 수 있다고 상상해보십시오. 그래도 필요한거야? 키보드/키패드 장치가 비 0x07 요소를 생성합니까? 예를 들어, 트랙 패드 또는 조이스틱이 내장 된 외장 키보드가 있거나 뭔가있는 것이 가능하다고 생각합니다. – dostende

+0

아니요, 0x07이 아닌 사람이 한 명도 없었습니다. :) – Yevgeniy

+0

저는 이처럼 키보드를 사용한 적이 없었습니다 (즉, 조이스틱이나 유사한 빌드를 사용하여).하지만 두 번째 장치와 키보드에서 이벤트가 분리 될 것으로 예상됩니다. 그러나 나는 확실히 말할 수 없다. – Yevgeniy

관련 문제