How to get key code or key text from an NSEvent in AppleScript with AppKit

475 Views Asked by At

I would like to be able to get either the key code or the characters/text from an NSEvent/KeyEvent. Absolutely no idea how to do this as the documentation I have found so far has been very limited.

My script is below. I am working on a speedrun macro for Minecraft.

This script is fully functioning as is, but currently all it does is check if the control key has been pressed via checking the modifier flags of NSEvent.

use framework "AppKit"
use scripting additions

global ca
set ca to current application

# you may change the following variables

global seed
set seed to "8398967436125155523"

to isModifierPressed(modifier)
    ((ca's NSEvent's modifierFlags()) / modifier as integer) mod 2 is equal to 1
end isModifierPressed

repeat
    if isModifierPressed(ca's NSEventModifierFlagControl) then execute()
    delay 0.01
end repeat

on execute()
    tell application "System Events"
        delay 0.1
        keystroke tab
        delay 0.02
        keystroke return
        delay 0.02
        repeat 3 times
            keystroke tab
            delay 0.02
        end repeat
        keystroke return
        delay 0.02
        repeat 2 times
            keystroke tab
            delay 0.02
        end repeat
        repeat 3 times
            keystroke return
            delay 0.02
        end repeat
        repeat 4 times
            keystroke tab
            delay 0.02
        end repeat
        keystroke return
        delay 0.02
        repeat 3 times
            keystroke tab
            delay 0.02
        end repeat
        keystroke seed
        delay 0.02
        repeat 6 times
            keystroke tab
            delay 0.02
        end repeat
        keystroke return
    end tell
end execute
1

There are 1 best solutions below

3
Ted Wrigley On

Getting the key code is is a bit of an ordeal. I wrote Objective-C code that handles it in this StackOverflow answer; basically this uses NSEvent to create a dictionary of all possible key-modifier combinations to back-reference from a given typed character. A bit of overkill, but you may find studying it helpful.

Of course, if you already have the NSEvent object, the you can use the following commands to get basic info:

NSEvent's characters()
NSEvent's charactersIgnoringModifiers()
NSEVent's modifierFlags()
NSEvent's keyCode()

You can create an NSEvent for a particular key code as follows:

use framework "AppKit"
use scripting additions

set ca to current application

set codeForGeneration to 40
set modFlags to 0

set keyEvent to ca's NSEvent's keyEventWithType:(ca's NSKeyDown) ¬
    location:(ca's NSMakePoint(1, 1)) ¬
    modifierFlags:0 ¬
    timestamp:0 ¬
    windowNumber:0 ¬
    context:(missing value) ¬
    |characters|:(missing value) ¬
    charactersIgnoringModifiers:(missing value) ¬
    isARepeat:false ¬
    keyCode:codeForGeneration

set outputCharacter to (keyEvent's charactersByApplyingModifiers:modFlags) as string

Line 6 (set keyEvent to...) creates a key event. You only need to concern yourself with first and last two options: keydown/keyup, repeat, keyCode. The others are dummies, unless you want to try to send a key event to a particular window or GUI element. Line 7 (set outputCharacter to...) extracts the characters from the event. This will produce a small 'k', because 40 is the key code for 'k' and no modifiers are used.

Modifiers are a little annoying to work with. you can use the ObjC constants individually (e.g., ca's NSEventModifierFlagShift or ca's NSEventModifierFlagOption), but to combine them you have to recognize that the flags are defined in terms of binary left-shifts: e.g., NSEventModifierFlagShift is defined as 1 << 17 and NSEventModifierFlagOption as 1 << 19, meaning a 1 bit shifted 17 or 19 bits left, respectively. So to create a shift-option-K event (the Apple logo), you have to set modFlags to 2^17+2^19.