【问题标题】:Stop Intercepting Keyboard Input While App Running - CGEventTap在应用程序运行时停止拦截键盘输入 - CGEventTap
【发布时间】:2013-02-08 16:39:53
【问题描述】:

使用 CGEventTap 停止观看键盘事件点击的正确方法是什么?

我正在构建一个简单的后台应用程序,用于转换特定键的输出。感谢this excellent post on CGEventTap,我已经能够启用密钥转换。不幸的是,我似乎无法阻止它而不是杀死该应用程序。

当用户切换复选框以打开或关闭功能时,将调用以下方法。切换 ON 立即发生。切换关闭可能需要一分钟或更长时间才能生效。我通过日志看到“已禁用。停止转换水龙头。”被检测到。但关键转换仍在继续。我不明白为什么。

- (void)watchEventTap
{    
        @autoreleasepool
        {
            CFRunLoopSourceRef runLoopSource = NULL;
            CFMachPortRef eventTap = CGEventTapCreate(kCGHIDEventTap, kCGHeadInsertEventTap, kCGEventTapOptionDefault, CGEventMaskBit(kCGEventKeyUp) | CGEventMaskBit(kCGEventKeyDown) | CGEventMaskBit(NX_SYSDEFINED), myCGEventCallback, NULL);
            runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0);

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

            if (self.shortcutEnabled) // User default toggled ON
            {
                NSLog(@"Enabled. Convert taps.");
                CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes);
                CGEventTapEnable(eventTap, true);
                // CFRunLoopRun(); // This blocks rest of app from executing
            }
            else // User default toggled OFF
            {
                NSLog(@"Disabled. Stop converting taps.");
                CFRunLoopRemoveSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes);
                CGEventTapEnable(eventTap, false);
                // Clean up the event tap and source after ourselves.
                CFMachPortInvalidate(eventTap);
                CFRunLoopSourceInvalidate(runLoopSource);
                CFRelease(eventTap);
                CFRelease(runLoopSource);
                eventTap = NULL;
                runLoopSource = NULL;
            }
        }
//        exit(0);  // This blocks rest of app from executing
}

感谢您的任何建议。我是新构建 Mac OS X 应用程序,所以如果我做了一些无知的事情,请原谅我。

【问题讨论】:

    标签: macos cocoa keyboard keyboard-events cgeventtap


    【解决方案1】:

    感谢一位经验丰富的 Mac 开发人员,我的问题得到了解决。每次调用该方法时,我都会创建一个新的 runLoopsSource。

    现在我已经为 tapEvent 和 runLoop 创建了实例变量。只需一行即可停止 eventTap。修改方法如下:

    - (void)watchEventTap
    {
    
        @autoreleasepool
        {
    
            if ( [[NSUserDefaults standardUserDefaults] isEnabledNumLockDV] == YES ) // User default toggled ON
            {
                _runLoopSource = NULL;
                 _eventTap = CGEventTapCreate(kCGHIDEventTap, kCGHeadInsertEventTap, kCGEventTapOptionDefault, CGEventMaskBit(kCGEventKeyUp) | CGEventMaskBit(kCGEventKeyDown) | CGEventMaskBit(NX_SYSDEFINED), myCGEventCallback, NULL);
                _runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, _eventTap, 0);
    
                if (!_eventTap)
                {
                    NSLog(@"Couldn't create event tap!");
                    exit(1);
                }
    
                NSLog(@"Enabled. Convert taps.");
                CFRunLoopAddSource(CFRunLoopGetCurrent(), _runLoopSource, kCFRunLoopCommonModes);
                CGEventTapEnable(_eventTap, true);
            }
            else if ( [[NSUserDefaults standardUserDefaults] isEnabledNumLockDV] == NO ) // User default toggled OFF
            {
                NSLog(@"Disabled. Stop converting taps.");
                CGEventTapEnable(_eventTap, false);
            }
    
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-12-23
      • 1970-01-01
      • 2018-07-02
      • 2023-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多