0

I am trying to catch a KeyDown event in a SwiftUI View deep in my MacOS app. However, I'm having trouble even getting one to fire in the AppDelegate.

Here is what I am trying now:

import Cocoa import SwiftUI @NSApplicationMain class AppDelegate: NSObject, NSApplicationDelegate { var window: NSWindow! var settings = UserSettings() func keyDown(theEvent: NSEvent) { if (theEvent.keyCode == 1){ print("test") } } func applicationDidFinishLaunching(_ aNotification: Notification) { // Create the SwiftUI view that provides the window contents. let contentView = ContentView().environmentObject(settings) // Create the window and set the content view. window = NSWindow( contentRect: NSRect(x: 0, y: 0, width: 480, height: 300), styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView], backing: .buffered, defer: false) window.center() window.setFrameAutosaveName("Main Window") window.contentView = NSHostingView(rootView: contentView) window.makeKeyAndOrderFront(nil) } func applicationWillTerminate(_ aNotification: Notification) { // Insert code here to tear down your application } } 

How else can I approach this?

9
  • 1
    That's not a job for the app delegate... you should be implementing keyDown in one of your VCs. Commented Feb 12, 2020 at 21:34
  • 1
    @Alexander-ReinstateMonica Not necessarily. You might not even have a window stackoverflow.com/a/59592581/2303865 Commented Feb 12, 2020 at 21:55
  • @LeoDabus Is the app delegate in the responder chain? Commented Feb 12, 2020 at 23:47
  • @Willeke developer.apple.com/library/archive/documentation/Cocoa/… Commented Feb 12, 2020 at 23:58
  • @LeoDabus See Responder Chain for Event Messages "The first responder is typically the “selected” view object within the window, and its next responder is its containing view (also called its superview), and so on up to the NSWindow object. If an NSWindowController object is managing the window, it becomes the final next responder.". Where is the app delegate? Commented Feb 13, 2020 at 0:34

1 Answer 1

2

You can "install" your own handler (see window.trackEvents ...)

import Cocoa import SwiftUI @NSApplicationMain class AppDelegate: NSObject, NSApplicationDelegate { var window: NSWindow! func applicationDidFinishLaunching(_ aNotification: Notification) { // Create the SwiftUI view that provides the window contents. let contentView = ContentView() // Create the window and set the content view. window = NSWindow( contentRect: NSRect(x: 0, y: 0, width: 480, height: 300), styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView], backing: .buffered, defer: false) window.center() window.setFrameAutosaveName("Main Window") window.contentView = NSHostingView(rootView: contentView) window.makeKeyAndOrderFront(nil) window.trackEvents(matching: .keyDown, timeout: .infinity, mode: RunLoop.Mode.default) { (event, _) in print(event) } } func applicationWillTerminate(_ aNotification: Notification) { // Insert code here to tear down your application } } 

here is some printing example

Optional(NSEvent: type=KeyDown loc=(116.223,179.594) time=38176.8 flags=0x100 win=0x11b830710 winNum=2404 ctxt=0x0 chars="h" unmodchars="h" repeat=0 keyCode=4) Optional(NSEvent: type=KeyDown loc=(116.223,179.594) time=38178.2 flags=0x100 win=0x11b830710 winNum=2404 ctxt=0x0 chars="j" unmodchars="j" repeat=0 keyCode=38) Optional(NSEvent: type=KeyDown loc=(116.223,179.594) time=38178.9 flags=0x100 win=0x11b830710 winNum=2404 ctxt=0x0 chars="h" unmodchars="h" repeat=0 keyCode=4) Optional(NSEvent: type=KeyDown loc=(116.223,179.594) time=38179.4 flags=0x100 win=0x11b830710 winNum=2404 ctxt=0x0 chars="g" unmodchars="g" repeat=0 keyCode=5) Optional(NSEvent: type=KeyDown loc=(116.223,179.594) time=38179.9 flags=0x100 win=0x11b830710 winNum=2404 ctxt=0x0 chars="h" unmodchars="h" repeat=0 keyCode=4) Optional(NSEvent: type=KeyDown loc=(108.574,-175.18) time=38184.5 flags=0x100 win=0x11b830710 winNum=2404 ctxt=0x0 chars="m" unmodchars="m" repeat=0 keyCode=46) Optional(NSEvent: type=KeyDown loc=(108.574,-175.18) time=38184.8 flags=0x100 win=0x11b830710 winNum=2404 ctxt=0x0 chars="," unmodchars="," repeat=0 keyCode=43) Optional(NSEvent: type=KeyDown loc=(108.574,-175.18) time=38185.1 flags=0x100 win=0x11b830710 winNum=2404 ctxt=0x0 chars="." unmodchars="." repeat=0 keyCode=47) 

BE WORRY!! This is the simplest example, in real application your handler must handle ALL keyDown events!! As done in this example, the default actions (menu ... etc.) will not react. You even have to stop the app from your Xcode (or terminal), or force to quit it from system menu

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.