0

In my Mac App, I listen to key press events and pass them on to the internal client, depending on modifiers and key code.

Currently, I'm facing the problem, that I can't get a hold of the "Ctrl+Tab" event. It seems that the "App" itself tries to handle this, which makes sense for tab based applications. So I disabled the Tabbingmode, but still, the Ctrl+Tab never fires the KeyDown event. Any other combination of key code and modifier seems to pass just fine.

Any suggestions on how to get the key down event fired for Ctrl+Tab?

Steve
  • 174
  • 4
  • 15

2 Answers2

1

In my testing, NSView's -keyDown: method does not seem to get called on NSView subclasses for control-tab key events. However, you can intercept them at the application level with an NSApplication subclass:

@interface MyApplication: NSApplication
@end

@implementation MyApplication

- (void)sendEvent:(NSEvent *)event {
    if (event.type == NSEventTypeKeyDown &&
        [event.charactersIgnoringModifiers isEqualToString:@"\t"] &&
        (event.modifierFlags & NSEventModifierFlagDeviceIndependentFlagsMask) == NSEventModifierFlagControl) {
        NSLog(@"ctrl-tab");
    }

    [super sendEvent:event];
}

@end
Charles Srstka
  • 16,665
  • 3
  • 34
  • 60
  • That would be a horribly bad idea unless you want the key event anywhere on top of the concerned view object. – El Tomato Aug 29 '17 at 03:05
  • You'd need to add code to check for the correct conditions when the event should be handled, and call super's implementation the rest of the time, yes. It's crude, but it's the only way I've found to capture the keystroke the OP wants to capture. – Charles Srstka Aug 29 '17 at 03:11
  • Thank you for this solution. It pointed me into the right direction. The funny thing is, I had to override NSWindow too to get the keyDown event in my NSView which is actually the NSWindowDelegate in my case. Seems like all instances in the chain try to avoid the Ctrl+Tab. – Steve Aug 29 '17 at 08:51
  • Which combination would be necessary to grab Ctrl+Shift+Tab? – Steve Sep 11 '17 at 07:45
0

Use

override func viewDidLoad() {
    super.viewDidLoad()

    NSEvent.addLocalMonitorForEvents(matching: .keyDown) {
        if self.myKeyDown(with: $0) {
            return nil
        } else {
            return $0
        }
    }
}

and

func myKeyDown(with event: NSEvent) -> Bool {
    // handle keyDown only if current window has focus, i.e. is keyWindow
    guard let locWindow = self.view.window,
          NSApplication.shared.keyWindow === locWindow else {
        return false
    }

    switch event.specialKey {

    case NSEvent.SpecialKey.tab:
        // your event for tab action
        return true
    default:
        break
    }
    return false
}

if you need shortcut keys

func myKeyDown(with event: NSEvent) -> Bool {
    // handle keyDown only if current window has focus, i.e. is keyWindow
    guard let locWindow = self.view.window,
          NSApplication.shared.keyWindow === locWindow else {
        return false
    }

    switch event.specialKey {
    case NSEvent.SpecialKey.tab:
        // your code for tab action
        return true
    default:
        break
    }

    switch event.modifierFlags.intersection(.deviceIndependentFlagsMask) {
    case [.command]:
        switch event.charactersIgnoringModifiers! {
        case "w":
            // your code for cmd+w action (example)
            break
        default:
            break
        }
    }
    return false
}
Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
arts
  • 118
  • 4