Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to handle keyDown in NSResponder #760

Open
onmyway133 opened this issue Jan 21, 2021 · 0 comments
Open

How to handle keyDown in NSResponder #760

onmyway133 opened this issue Jan 21, 2021 · 0 comments

Comments

@onmyway133
Copy link
Owner

onmyway133 commented Jan 21, 2021

import AppKit
import Omnia

class MyWindow: NSWindow {
    override func keyDown(with event: NSEvent) {
        super.keyDown(with: event)

        if isKey(NSDeleteCharacter, event: event) {
            NotificationCenter.default.post(Notification(name: .didKeyboardDeleteItem))
        } else if isKey(NSUpArrowFunctionKey, event: event) {
            print("up")
        } else if isKey(NSDownArrowFunctionKey, event: event) {
            print("down")
        } else if isKey(NSLeftArrowFunctionKey, event: event) {
            print("left")
        } else if isKey(NSRightArrowFunctionKey, event: event) {
            print("right")
        }
    }

    private func isKey(_ key: Int, event: NSEvent) -> Bool {
        if let scalar = UnicodeScalar(key) {
            return event.characters == String(scalar)
        } else {
            return false
        }
    }
}

Another way is to listen to

NSEvent.addLocalMonitorForEvents(matching: .keyDown) { event in
       if handled(with: $0) {
          return nil
       }
       return event
    }

Or create our own inspector

class MyWindow: NSWindow {
    override func keyDown(with event: NSEvent) {
        if !EventService.shared.inspect(event) {
            super.keyDown(with: event)
        }
    }

    override var canBecomeKey: Bool  { true }
    override var canBecomeMain: Bool { true }
    override var acceptsFirstResponder: Bool { true }
    override func becomeFirstResponder() -> Bool { true }
}

import AppKit
import Omnia
import KeyboardShortcuts

final class EventService {
    static let shared = EventService()

    private var combos: [Combo] = []
    private let debouncer = Debouncer(delay: 0.1)

    func register(_ combo: Combo) {
        combos.append(combo)
    }

    func inspect(_ event: NSEvent) -> Bool {
        for combo in combos {
            if combo.match(event) {
                self.debouncer.run {
                    combo.action()
                }
                return true
            }
        }

        return false
    }
}

extension EventService {
    struct Combo {
        let modifier: NSEvent.ModifierFlags?
        let keyCode: KeyboardShortcuts.Key
        let action: () -> Void

        func match(_ event: NSEvent) -> Bool {
            if let modifier = modifier,
               !event.modifierFlags.contains(modifier) {
                return false
            }

            if event.keyCode != keyCode.rawValue {
                return false
            }

            return true
        }
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant