I've started a SwiftUI project (it is a macOS tray application) that relies on global keyboard events (even when my application is minimized). Specifically i care about the F3 and F4 keys. While the keyboard events are registered correctly and my application is fully functional it is always playing that error "funk" sound when a key is pressed. Does anyone know how to fix this?
MyApp.swift
import SwiftUI
@main
struct MyApp: App {
@NSApplicationDelegateAdaptor(AppDelegate.self) var delegate;
var body: some Scene {
Settings {
ContentView()
}
}
}
class AppDelegate: NSObject,NSApplicationDelegate {
var statusItem: NSStatusItem!
var popOver: NSPopover!
func applicationDidFinishLaunching(_ notification: Notification){
let contentView = ContentView()
let popOver = NSPopover();
popOver.behavior = .transient
popOver.animates = true
popOver.contentViewController = NSHostingController(rootView: contentView)
popOver.setValue(true, forKeyPath: "shouldHideAnchor")
self.popOver = popOver
self.statusItem = NSStatusBar.system.statusItem(withLength: CGFloat(NSStatusItem.variableLength))
let options: NSDictionary = [kAXTrustedCheckOptionPrompt.takeUnretainedValue() as String : true]
let accessEnabled = AXIsProcessTrustedWithOptions(options)
if !accessEnabled {
print("Access Not Enabled")
}
// Here is where the global keypress event is registered
NSEvent.addGlobalMonitorForEvents(matching: .keyDown) { (event) in
if (event.keyCode == 99) {
// do smth
}else if (event.keyCode == 118) {
// do smth else
}
}
}
if let MenuButton = self.statusItem.button {
MenuButton.image = NSImage(systemSymbolName: "display.2", accessibilityDescription: nil)
MenuButton.action = #selector(MenuButtonToggle)
}
}
@objc func MenuButtonToggle(_ sender: AnyObject){
if let button = self.statusItem.button {
if self.popOver.isShown{
self.popOver.performClose(sender)
}else {
self.popOver.show(relativeTo: button.bounds, of: button, preferredEdge: NSRectEdge.minY)
self.popOver.contentViewController?.view.window?.makeKey()
}
}
}
}
It looks like you can achieve this by assigning the keys through the view directly at least, perhaps this can work on your AppDelegate also but you need to override.
Here is a working example:
According to Documentation: "When you call
super.keyDown(with: event), the event goes up through the responder chain and if no other responders process it, causes beep sound." Good Luck!