Home > Net >  CGEventTapCreate detecting multiple keyboard inputs
CGEventTapCreate detecting multiple keyboard inputs

Time:01-24

I'm working on a macOS menubar app that locks any mouse events. What I'm trying to achieve is that after sending mouse events to the CGEventRef based callback, I cannot click anywhere (naturally) but the problem is I cannot quit the loop because of that.

Every time I need to close it, I'm switching to the Xcode app to stop the running app.

This is the main function and the events that I'm sending to the callback function;

void lockTrackpad(void) {
    // For keyboard inputs, I add CGEventMaskBit(kCGEventKeyUp)| CGEventMaskBit(kCGEventKeyDown)| CGEventMaskBit(NX_SYSDEFINED)
    CGEventMask mask = (
                        CGEventMaskBit(kCGEventMouseMoved)
                        | CGEventMaskBit(kCGEventLeftMouseUp)
                        | CGEventMaskBit(kCGEventLeftMouseDown)
                        | CGEventMaskBit(kCGEventRightMouseUp)
                        | CGEventMaskBit(kCGEventRightMouseDown)
                        | CGEventMaskBit(kCGEventScrollWheel)
                        );
    
    eventTap = CGEventTapCreate(kCGHIDEventTap, kCGHeadInsertEventTap, kCGEventTapOptionDefault, mask, CGEventCallback_r, nil);
    
    ...
}

And this is the callback function;

CGEventRef CGEventCallback_r(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) {
    CGKeyCode keycode = (CGKeyCode)CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode);
    printf("Event Tap: %d\n", keycode);

    if (keycode == 43) {
        printf("quit the application \n");
        exit(EXIT_SUCCESS);
    }
    
    return nil;
}

What I want is, for example when the loop is running, if press "control U L", I want to run some function to exit the loop. I believe in order to get the keyboard input, I should send the keyboard events as well but I couldn't figure out how to detect my keyboard shortcuts.

  • I added the keyboard bits to the mask.
  • The app is sandboxed.

I want to do something like this;

CGEventRef CGEventCallback_r(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) {
    CGKeyCode keycode = (CGKeyCode)CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode);

    // When pressing "control   U   L", call a function
    if (...) {
        printf("pressed control   U   L \n");
        doSomething();
    }

    return nil;
}

CodePudding user response:

I figured out like this;

CGEventRef CGEventCallback_r(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) {
    
    if (type == kCGEventKeyDown) {
        CGKeyCode keyCode = (CGKeyCode)CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode);
        
        if (CGEventGetFlags(event) & kCGEventFlagMaskControl) {
            // control key is pressed
            controlKeyPressed = true;
        }
        if (keyCode == kVK_ANSI_U) {
            // u key is pressed
            uKeyPressed = true;
        }
        if (keyCode == kVK_ANSI_L) {
            // l key is pressed
            lKeyPressed = true;
        }
        if (controlKeyPressed && uKeyPressed && lKeyPressed) {
            // doSomething();
        }
        return event;
    } else if (type == kCGEventKeyUp) {
        CGKeyCode keyCode = (CGKeyCode)CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode);
        // set the variable to false just like above.
    }
    
    if (keycode == 43) {
        printf("quit the application \n");
        exit(EXIT_SUCCESS);
    }
    
    return nil;
}

Also, don't forget to put your variables on a global scope.

  • Related