Cannot read property 'keyCode' 'character' Assertion failure when detect modifier key + numeric key
To enable AXIsProcessTrusted()
in your app you need to go to your macOS system preferences, open Security and Privacy
, click on Accessibility
, click on the plus sign to add your app to the list off apps that can control your computer. You might need to click at the padlock and type your password to unlock your settings.
import Cocoa
class ViewController: NSViewController {
override func viewDidLoad() {
super.viewDidLoad()
print("AXIsProcessTrusted:",AXIsProcessTrusted())
NSEvent.addGlobalMonitorForEvents(matching: .keyDown) {
self.keyDown(with: $0)
}
}
override func keyDown(with event: NSEvent) {
switch event.modifierFlags.intersection(.deviceIndependentFlagsMask) {
case [.command] where event.characters == "1", [.command, .shift] where event.characters == "1":
print("command+1 or command+shift+1")
default:
break
}
}
}
Global modifier key press detection in Swift
You can add Global Monitor For Events matching .flagsChanged
to your view controller so you can check its modifierFlags intersection with deviceIndependentFlagsMask and check the resulting keys.
Declaration
class func addGlobalMonitorForEvents(matching mask: NSEventMask, handler block: @escaping (NSEvent) -> Void) -> Any?
installs an event monitor that receives copies of events posted to
other applications. Events are delivered asynchronously to your app
and you can only observe the event; you cannot modify or otherwise
prevent the event from being delivered to its original target
application. Key-related events may only be monitored if accessibility
is enabled or if your application is trusted for accessibility access
(see AXIsProcessTrusted()). Note that your handler will not be called
for events that are sent to your own application.
import Cocoa
class ViewController: NSViewController {
override func viewDidLoad() {
super.viewDidLoad()
NSEvent.addGlobalMonitorForEvents(matching: .flagsChanged) {
switch $0.modifierFlags.intersection(.deviceIndependentFlagsMask) {
case [.shift]:
print("shift key is pressed")
case [.control]:
print("control key is pressed")
case [.option] :
print("option key is pressed")
case [.command]:
print("Command key is pressed")
case [.control, .shift]:
print("control-shift keys are pressed")
case [.option, .shift]:
print("option-shift keys are pressed")
case [.command, .shift]:
print("command-shift keys are pressed")
case [.control, .option]:
print("control-option keys are pressed")
case [.control, .command]:
print("control-command keys are pressed")
case [.option, .command]:
print("option-command keys are pressed")
case [.shift, .control, .option]:
print("shift-control-option keys are pressed")
case [.shift, .control, .command]:
print("shift-control-command keys are pressed")
case [.control, .option, .command]:
print("control-option-command keys are pressed")
case [.shift, .command, .option]:
print("shift-command-option keys are pressed")
case [.shift, .control, .option, .command]:
print("shift-control-option-command keys are pressed")
default:
print("no modifier keys are pressed")
}
}
}
}
Prevent error funk sound in event monitor OS X
I ended up using MASShortcut as a workaround solution to this issue.
Swift - Capture keydown from NSViewController
Xcode 8.2.1 • Swift 3.0.2
import Cocoa
class ViewController: NSViewController {
@IBOutlet var textField: NSTextField!
override func viewDidLoad() {
super.viewDidLoad()
NSEvent.addLocalMonitorForEvents(matching: .flagsChanged) {
self.flagsChanged(with: $0)
return $0
}
NSEvent.addLocalMonitorForEvents(matching: .keyDown) {
self.keyDown(with: $0)
return $0
}
}
override func keyDown(with event: NSEvent) {
switch event.modifierFlags.intersection(.deviceIndependentFlagsMask) {
case [.command] where event.characters == "l",
[.command, .shift] where event.characters == "l":
print("command-l or command-shift-l")
default:
break
}
textField.stringValue = "key = " + (event.charactersIgnoringModifiers
?? "")
textField.stringValue += "\ncharacter = " + (event.characters ?? "")
}
override func flagsChanged(with event: NSEvent) {
switch event.modifierFlags.intersection(.deviceIndependentFlagsMask) {
case [.shift]:
print("shift key is pressed")
case [.control]:
print("control key is pressed")
case [.option] :
print("option key is pressed")
case [.command]:
print("Command key is pressed")
case [.control, .shift]:
print("control-shift keys are pressed")
case [.option, .shift]:
print("option-shift keys are pressed")
case [.command, .shift]:
print("command-shift keys are pressed")
case [.control, .option]:
print("control-option keys are pressed")
case [.control, .command]:
print("control-command keys are pressed")
case [.option, .command]:
print("option-command keys are pressed")
case [.shift, .control, .option]:
print("shift-control-option keys are pressed")
case [.shift, .control, .command]:
print("shift-control-command keys are pressed")
case [.control, .option, .command]:
print("control-option-command keys are pressed")
case [.shift, .command, .option]:
print("shift-command-option keys are pressed")
case [.shift, .control, .option, .command]:
print("shift-control-option-command keys are pressed")
default:
print("no modifier keys are pressed")
}
}
}
To get rid of the purr sound when pressing the character keys you need to subclass your view, override the method performKeyEquivalent and return true.
import Cocoa
class View: NSView {
override func performKeyEquivalent(with event: NSEvent) -> Bool {
return true
}
}
Sample Project
Why is this functionKey selected when I press F1, F2, etc?
Apple's documentation isn't what is used to be.
If the documentation doesn't help, check the header. Copied from NSEvents.h:
NSEventModifierFlagFunction = 1 << 23, // Set if any function key is pressed.
NSEventModifierFlagFunction
was NSFunctionKeyMask
, documentation:
NSFunctionKeyMask
Set if any function key is pressed. The function keys include the F keys at the top of most keyboards (F1, F2, and so on) and the navigation keys in the center of most keyboards (Help, Forward Delete, Home, End, Page Up, Page Down, and the arrow keys).
Apparently the .function
flag is also set when the fn-key is pressed (on my Apple keyboard, my Logitech keyboard handles the fn-key internally).
Emulate / send Modifier Key (Cntrl, Alt, fn, Shift) in OSx
All you have to do is create an event tap and set the mask.
Sample:
@interface AppDelegate ()
@property (assign) CFMachPortRef myEventTap;
@property (assign) CFRunLoopSourceRef myRunLoopSource;
@end
@implementation AppDelegate
CGEventRef MyEventTapCallBack(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) {
CGEventSetFlags(event, kCGEventFlagMaskShift);
return event;
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
self.myEventTap = CGEventTapCreate(kCGHIDEventTap,
kCGHeadInsertEventTap,
kCGEventTapOptionDefault,
CGEventMaskBit(kCGEventKeyDown) | CGEventMaskBit(kCGEventKeyUp) | CGEventMaskBit(kCGEventFlagsChanged),
MyEventTapCallBack,
(__bridge void *)self);
if (self.myEventTap) {
self.myRunLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, self.myEventTap, 0);
if (self.myRunLoopSource)
CFRunLoopAddSource(CFRunLoopGetMain(), self.myRunLoopSource, kCFRunLoopCommonModes);
}
}
- (void)applicationWillTerminate:(NSNotification *)aNotification {
if (self.myRunLoopSource) {
CFRunLoopSourceInvalidate(self.myRunLoopSource);
CFRelease(self.myRunLoopSource);
}
if (self.myEventTap)
CFRelease(self.myEventTap);
}
@end
How to monitor global modifier key state (in any application)?
One option is to use EventTaps. This lets you monitor all keyboard events. See:
http://developer.apple.com/mac/library/documentation/Carbon/Reference/QuartzEventServicesRef/Reference/reference.html#//apple_ref/c/func/CGEventTapCreate
Unfortunately event taps will stop working if an application is requesting secure input. For example Quicken.
Related Topics
"Ambiguous Use of 'Children'" When Trying to Use Nstreecontroller.Arrangedobjects in Swift 3.0
Tableview Accessories Don't Load Correctly
Self. in Trailing Swift Closures, Meaning and Purpose
Printed Double Value Differs from Originally Set Value
Firestore Security Rules Breaking with Update Rule
Unexpectedly Found Nil While Unwrapping an Optional Value While Reading from Ds with Fromcstring
Uicollectionviewcell Not Forcing Cell Size
Ibeacon: Get Advertisement Package Faster
Fetch an Email Body in Mailcore2 Osx with Swift
Simple Swift Class Does Not Compile
Parse.Com Pfquery Order by Time (Swift)
Swift Generics and Protocols Not Working on Uikit [Possible Bug]
Nsurl from String Gets Truncated, Dots on the Uivideoeditorcontroller's Video Path Swift 2 iOS 8
Avaudioplayer.Play() Works But Avaudioplayernode.Play() Fails
Does _Arraytype or _Arrayprotocol Not Available in Swift 3.1