addLocalMonitorForEventsMatchingMask 非主线程的替代方案

addLocalMonitorForEventsMatchingMask Alternative for Off-mainthread

我目前使用 addLocalMonitorForEventsMatchingMask 来监视鼠标事件,我从主线程调用它。它很好用。但是我现在想把它移到主线程之外。是否有替代方法,例如从线程创建隐藏的 window 并执行 NSRunLoop?

我阅读了文档:https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/EventOverview/MonitoringEvents/MonitoringEvents.html

The handlers are always called on the main thread. Both class methods return the monitor object, which the calling object does not own (and thus has no need to retain or release).

有没有我可以在主线程之外做的其他选择?

我无法从另一个线程在主线程上设置回调。我正在使用 FFI,但它现在无法使用。

这是我的代码以防它有帮助,但我希望有替代方案用于关闭主线程:

myHandler_js = function(c_arg1__self, objc_arg1__aNSEventPtr) {

    var cType = ostypes.API('objc_msgSend')(objc_arg1__aNSEventPtr, ostypes.HELPER.sel('type'));

    cType = ctypes.cast(cType, ostypes.TYPE.NSEventType);


    return objc_arg1__aNSEventPtr; // return null to block
};
myHandler_c = ostypes.TYPE.IMP_for_EventMonitorCallback.ptr(myHandler_js);
myBlock_c = ostypes.HELPER.createBlock(myHandler_c);


var rez_add = ostypes.API('objc_msgSend')(ostypes.HELPER.class('NSEvent'), ostypes.HELPER.sel('addLocalMonitorForEventsMatchingMask:handler:'), ostypes.TYPE.NSEventMask(ostypes.CONST.NSKeyDownMask), myBlock_c.address());

解决方法是使用CGEventTap.

这个有问题,但我会在准备好后立即更新它:

GetCurrentProcess(psn);

var mask =  1 << kCGEventLeftMouseDown | // CGEventMaskBit(kCGEventLeftMouseDown)
            1 << kCGEventLeftMouseUp | 
            1 << kCGEventRightMouseDown |
            1 << kCGEventRightMouseUp |
            1 << kCGEventOtherMouseDown |
            1 << kCGEventOtherMouseUp |
            1 << kCGEventScrollWheel;

mouseEventTap = CGEventTapCreateForPSN(&psn, kCGHeadInsertEventTap, kCGEventTapOptionDefault, mask, null);

if (!mouseEventTap.isNull()) {
      aRLS = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, mouseEventTap, 0);
      CFRelease(mouseEventTap);

      if (!aRLS.isNull()) {
            aLoop = CFRunLoopGetCurrent();

            CFRunLoopAddSource(aLoop, aRLS, kCFRunLoopCommonModes);

            CFRelease(aRLS);
            CFRelease(aLoop);

            rez = CFRunLoopRunInMode(ostypes.CONST.kCFRunLoopCommonModes, 10, false); // figure out how to make this run indefinitely
            // rez is 1 :(

      }

}