为什么将CFRunLoopRun()移入方法会导致点击回调无法触发?

时间:2019-07-06 14:16:00

标签: macos cgeventtap cfrunloop

当我尝试将CFRunLoopRun();移回main.m时,以下代码(很少)失败:

// main.m
int main(int argc, const char * argv[])
{
    @autoreleasepool {
        Remapper* remapper = [Remapper new];
        [remapper run];

        // CFRunLoopRun(); // <-- (1) If this is HERE ...
    }

    return 0;
}


@implementation Remapper
- (void) run {
    Intercept* intercept = [Intercept new];
    [intercept setup];

    CFRunLoopRun(); // (3) but if I put it here, tap_callback now DOES hit.
}


@implementation Intercept
- (void) setup {
    [self tapEvents];
    [self listen];
}

- (bool) tapEvents {
    modifiers = [NSEvent modifierFlags];

    if ( ! eventTap )
        eventTap = CGEventTapCreate( kCGHIDEventTap, ..., tap_callback, ... );

    CGEventTapEnable( eventTap, true );

    return CGEventTapIsEnabled( eventTap ); // (4) Note return value is always `true`
}

- (void) listen {
    if( ! runLoopSource ) {
        runLoopSource = CFMachPortCreateRunLoopSource( kCFAllocatorDefault, eventTap, 0 );

        CFRunLoopAddSource( CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes );
    }
}

CGEventRef tap_callback(...)
{
    // (2) This now won't hit! 
}

请检查(1)到(4)。

现在,无论CFRunLoopRun()是在[remapper run]方法的末尾执行还是在呼叫站点的下一行执行,这可能有什么不同?我看不到任何线程问题的机会。

我只是无法理解。

0 个答案:

没有答案