Last active
October 1, 2024 01:09
-
-
Save phranck/3ba8577be40cc61dbe02970519f89083 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Carbon.HIToolbox | |
import SwiftUI | |
/// Keyboard layout independent keycodes | |
public enum ViewKeyCode: UInt16 { | |
case Return = 0x24 | |
case Tab = 0x30 | |
case Space = 0x31 | |
case Delete = 0x33 | |
case Escape = 0x35 | |
case Command = 0x37 | |
case Shift = 0x38 | |
case CapsLock = 0x39 | |
case Option = 0x3A | |
case Control = 0x3B | |
case RightShift = 0x3C | |
case RightOption = 0x3D | |
case RightControl = 0x3E | |
case Function = 0x3F | |
case F17 = 0x40 | |
case VolumeUp = 0x48 | |
case VolumeDown = 0x49 | |
case Mute = 0x4A | |
case F18 = 0x4F | |
case F19 = 0x50 | |
case F20 = 0x5A | |
case F5 = 0x60 | |
case F6 = 0x61 | |
case F7 = 0x62 | |
case F3 = 0x63 | |
case F8 = 0x64 | |
case F9 = 0x65 | |
case F11 = 0x67 | |
case F13 = 0x69 | |
case F16 = 0x6A | |
case F14 = 0x6B | |
case F10 = 0x6D | |
case F12 = 0x6F | |
case F15 = 0x71 | |
case Help = 0x72 | |
case Home = 0x73 | |
case PageUp = 0x74 | |
case ForwardDelete = 0x75 | |
case F4 = 0x76 | |
case End = 0x77 | |
case F2 = 0x78 | |
case PageDown = 0x79 | |
case F1 = 0x7A | |
case LeftArrow = 0x7B | |
case RightArrow = 0x7C | |
case DownArrow = 0x7D | |
case UpArrow = 0x7E | |
} | |
public extension View { | |
func onKeyPress(_ keyCode: ViewKeyCode, action: @escaping () -> Void) -> some View { | |
modifier(KeyPressViewModifier(keyCode, action: action)) | |
} | |
} | |
// MARK: - Private API | |
private struct KeyPressViewModifier: ViewModifier { | |
let keyCode: ViewKeyCode | |
let action: () -> Void | |
init(_ keyCode: ViewKeyCode, action: @escaping () -> Void) { | |
self.keyCode = keyCode | |
self.action = action | |
} | |
func body(content: Content) -> some View { | |
content | |
.background { | |
KeyCodeView(keyCode: keyCode, action: action) | |
} | |
} | |
} | |
private struct KeyCodeView: NSViewRepresentable { | |
var keyCode: ViewKeyCode | |
var action: () -> Void | |
func makeNSView(context: Context) -> _KeyCodeView { | |
let view = _KeyCodeView() | |
view.keyCode = keyCode.rawValue | |
view.action = action | |
view.frame = .zero | |
return view | |
} | |
func updateNSView(_ view: _KeyCodeView, context: Context) {} | |
} | |
private extension KeyCodeView { | |
final class _KeyCodeView: NSView { | |
var keyCode: UInt16 = 0 | |
var action: (() -> Void) = {} | |
override func performKeyEquivalent(with event: NSEvent) -> Bool { | |
if event.keyCode == keyCode { | |
action() | |
return true | |
} | |
return super.performKeyEquivalent(with: event) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment