blog icon indicating copy to clipboard operation
blog copied to clipboard

How to handle keyDown in SwiftUI for macOS

Open onmyway133 opened this issue 4 years ago • 4 comments

Use a custom KeyAwareView that uses an NSView that checks for keyDown method. In case we can't handle certain keys, call super.keyDown(with: event)

import SwiftUI
import KeyboardShortcuts

struct KeyAwareView: NSViewRepresentable {
    let onEvent: (Event) -> Void

    func makeNSView(context: Context) -> NSView {
        let view = KeyView()
        view.onEvent = onEvent
        DispatchQueue.main.async {
            view.window?.makeFirstResponder(view)
        }
        return view
    }

    func updateNSView(_ nsView: NSView, context: Context) {}
}

extension KeyAwareView {
    enum Event {
        case upArrow
        case downArrow
        case leftArrow
        case rightArrow
        case space
        case delete
        case cmdC
    }
}

private class KeyView: NSView {
    var onEvent: (KeyAwareView.Event) -> Void = { _ in }

    override var acceptsFirstResponder: Bool { true }
    override func keyDown(with event: NSEvent) {
        switch Int(event.keyCode) {
        case KeyboardShortcuts.Key.delete.rawValue:
            onEvent(.delete)
        case KeyboardShortcuts.Key.upArrow.rawValue:
            onEvent(.upArrow)
        case KeyboardShortcuts.Key.downArrow.rawValue:
            onEvent(.downArrow)
        case KeyboardShortcuts.Key.leftArrow.rawValue:
            onEvent(.leftArrow)
        case KeyboardShortcuts.Key.rightArrow.rawValue:
            onEvent(.rightArrow)
        case KeyboardShortcuts.Key.space.rawValue:
            onEvent(.space)
        case KeyboardShortcuts.Key.c.rawValue where event.modifierFlags.contains(.command):
            onEvent(.cmdC)
        default:
            super.keyDown(with: event)
        }
    }
}

Then we can place this as a background

LazyVStack {

}
.background(KeyAwareView(onEvent: {}))

onmyway133 avatar Jan 29 '21 20:01 onmyway133

import KeyboardShortcuts Where is KeyboardShoretcuts to import?

wynnbwynnb avatar Jan 16 '22 22:01 wynnbwynnb

@wynnbwynnb I believe that's sindresorhus/KeyboardShortcuts.

ashchan avatar Jan 17 '22 01:01 ashchan

Got it, thanks!

On Sun, Jan 16, 2022 at 5:24 PM Jianming Chen (James) < @.***> wrote:

@wynnbwynnb https://github.com/wynnbwynnb I believe that's sindresorhus/KeyboardShortcuts https://github.com/sindresorhus/KeyboardShortcuts.

— Reply to this email directly, view it on GitHub https://github.com/onmyway133/blog/issues/764#issuecomment-1014052427, or unsubscribe https://github.com/notifications/unsubscribe-auth/AIZY6DIKSZQV2TSVWCFKPOTUWNVTRANCNFSM4WZQDXWA . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.

You are receiving this because you were mentioned.Message ID: @.***>

-- -Wynn

wynnbwynnb avatar Jan 17 '22 01:01 wynnbwynnb

I made a version of this in a single file and wrapped in a viewmodifier.

.onKeyPress(key: KeyboardKey, callback: (KeyAwareView.Event) -> Void)

Thank you for the snippet, super useful!

https://gist.github.com/StefKors/1e63834f62c1ea7dd720532eaee35f01

StefKors avatar Sep 04 '23 11:09 StefKors