OSX:用C读取原始键盘输入

时间:2014-11-30 22:41:02

标签: c macos input keyboard driver

我正在玩一个便宜的图形平板电脑的改装。平板电脑上有热键,不能按我的意愿工作,我想修改它们。

即:其中一个热键输出“+”(加号),另一个输出“ - ”(减号)等。

我的目标是读取特定“键盘”的输入(不是全局用户输入),检查值并发布自定义CGEventCreateKeyboardEvent。

我成功通过CGEventCreateMouseEvent控制鼠标移动平板电脑。

到目前为止我的理论:

1。用hidapi访问键盘

  • 直接从键盘阅读
  • 检查十六进制值
  • 做一些c-code
  • 问题在于:原始hid-output中没有热键

2。访问全局用户输入

  • 阅读用户级别的任何输入
  • 检查输入源(即:mac-keyboard,cheap-keyboard)
  • 做一些c-code

1 个答案:

答案 0 :(得分:3)

解决了! 在本指南的帮助下:https://github.com/sdegutis/mjolnir/issues/9

基本上你需要做的是:

  • 在RunLoop中创建一个EventTap,为事件创建一个回退函数
  • 在您的普通键盘和键盘上输入您要入侵的内容
  • 您应该会看到每个键盘的唯一编号
  • 将此值用于您的情况
MY_DEBUGGED_KEYBOARD 44
int keyboard = 0;

CGEventRef
myCGEventCallback(CGEventTapProxy proxy, CGEventType type,
    CGEventRef event, void *refcon) {
// Paranoid sanity check.
if ((type != kCGEventKeyDown) && (type != kCGEventKeyUp))
    return event;

keyboard = CGEventGetIntegerValueField(event, kCGKeyboardEventKeyboardType);

// if you found your keyboard-value...
if (keyboard != MY_DEBUGGED_KEYBOARD) {
    return event;
}


// ... you can proceed with your stuff... i.e. remap input, etc.

printf("%d\n", keyboard);


// Set the modified keycode field in the event.
CGEventSetIntegerValueField(event, kCGKeyboardEventKeycode, (int64_t) keycode);

// We must return the event for it to be useful.
return event;
}

int main(int argc, char* argv[]) {
CFMachPortRef      eventTap;
CGEventMask        eventMask;
CFRunLoopSourceRef runLoopSource;

// Create an event tap. We are interested in key presses.
eventMask = ((1 << kCGEventKeyDown) | (1 << kCGEventKeyUp));
eventTap = CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap, 0,
        eventMask, myCGEventCallback, NULL);
if (!eventTap) {
    fprintf(stderr, "failed to create event tap\n");
    exit(1);
}

// Create a run loop source.
runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0);

// Add to the current run loop.
CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes);

// Enable the event tap.
CGEventTapEnable(eventTap, true);

// Set it all running.
CFRunLoopRun();
return 0;
}