Handling cocoa key events (keystrokes) with quick in console application

Ok, so I'm trying to log in to console output which keys are pressed. I just can't understand the structure of cocoa, neither with Obj-c nor fast. I am not a master in these two languages, but ... Well, here is my code:

import Cocoa import Foundation import AppKit var loop = true var idRegisterdEvent: AnyObject? = nil func handlerEvent(myEvent: (NSEvent!)) -> Void { print(myEvent.keyCode) } while loop { idRegisterdEvent = NSEvent.addGlobalMonitorForEventsMatchingMask(NSEventMask.KeyDownMask, handler: handlerEvent) } 

I know that everything is wrong, yes .. But man, these events, I can’t understand how they work.

+6
source share
2 answers

After spending a couple of hours on google, I eventually read a couple of github resources. It turns out that someone already understood this .

Basically, you need to create an NSApplicationDelegate that allows your application to listen for system events.

The required minimum code ( swift2 ) is shown below:

 func acquirePrivileges() -> Bool { let accessEnabled = AXIsProcessTrustedWithOptions( [kAXTrustedCheckOptionPrompt.takeUnretainedValue() as String: true]) if accessEnabled != true { print("You need to enable the keylogger in the System Preferences") } return accessEnabled == true } class ApplicationDelegate: NSObject, NSApplicationDelegate { func applicationDidFinishLaunching(notification: NSNotification?) { acquirePrivileges() // keyboard listeners NSEvent.addGlobalMonitorForEventsMatchingMask( NSEventMask.KeyDownMask, handler: {(event: NSEvent) in print(event) }) } } // preparing main loop let application = NSApplication.sharedApplication() let applicationDelegate = MyObserver() application.delegate = applicationDelegate application.activateIgnoringOtherApps(true) application.run() 

If you are only interested in exciting events without access (for example: NSWorkspaceDidActivateApplicationNotification ), you can leave with significantly fewer lines of code, since you only need NSRunLoop.mainRunLoop().run() . I added this example only after I saw your while true event while true , which will never let you listen to any system events, since it blocks the main thread.

 class MyObserver: NSObject { override init() { super.init() // app listeners NSWorkspace.sharedWorkspace().notificationCenter.addObserver(self, selector: "SwitchedApp:", name: NSWorkspaceDidActivateApplicationNotification, object: nil) } func SwitchedApp(notification: NSNotification!) { print(notification) } } let observer = MyObserver() // simply to keep the command line tool alive - as a daemon process NSRunLoop.mainRunLoop().run() 
+8
source

As a first step to the solution, I suggest making sure that the local version of the monitor is working:

 NSEvent.addLocalMonitorForEventsMatchingMask(NSEventMask.KeyDownMask, handler: {(evt: NSEvent!) -> NSEvent in NSLog("Local Keydown: " + evt.characters! + " (" + String(evt.keyCode) + ")"); return evt; }); 

If it works, go to the global version:

 NSEvent.addGlobalMonitorForEventsMatchingMask(NSEventMask.KeyDownMask, handler: {(evt: NSEvent!) -> Void in NSLog("Global Keydown: " + evt.characters! + " (" + String(evt.keyCode) + ")"); }); 

If the local one works, but the global one does not, it means that you did not include your application (or at the time of development, Xcode) in [System Preferences / Security and Privacy / Availability] to manage your computer.

If none of them work, maybe it doesn’t work with console applications at all ...

+2
source

Source: https://habr.com/ru/post/979557/


All Articles