Hesky Fisher
Hesky Fisher

Reputation: 1365

How to convert a string into a set of keystrokes in python on OSX

Given a string, I'd like to be able to send a set of keystrokes to type that string and I'd like to be able to do it in python on OSX (in python because it's part of a larger project already written in python, on OSX because I am trying to port it to OSX).

I'm able to do this now using pyobj like so (this is somewhat simplified):

from Quartz import *

CHAR_TO_SEQUENCE = {
    'a':[(0, True), (0, False)]
}

def send_string(string):
    for c in string:
        sequence = CHAR_TO_SEQUENCE[c]
        for keycode, key_down in sequence:
            CGEventPost(kCGSessionEventTap, CGEventCreateKeyboardEvent(None, keycode, key_down))

and I've fleshed out CHAR_TO_SEQUENCE to include most of what I can type on my keyboard, which took a while and was tedious.

The problems with this are:
- It only works while the keyboard has the ANSII standard layout. If someone uses a french keyboard, for example, it will type the wrong things.
- It requires this ridiculous table.

I found this general solution for OSX but couldn't figure out how to apply it to python: How to convert ASCII character to CGKeyCode?

The API mentioned there doesn't seem to be available via pyobj (or maybe I just couldn't figure out the import path).

I've seen some suggestions to set CGEventKeyboardSetUnicodeString to the desired string and not worry about the keycode. But I wasn't able to figure out how to call CGEventKeyboardSetUnicodeString from python (I can't get the arguments right) and it's not clear that this will work because the documentation says that applications can choose to ignore this in favor of the keycode.

Is there a way to do this in python on OSX?

Upvotes: 2

Views: 908

Answers (1)

abarnert
abarnert

Reputation: 365777

It looks like the Carbon modules don't wrap the TIS* functions, and neither does anything else.

You could extend PyObjC, but it's much simpler to just build a trivial extension module that wraps the two functions you actually need.

Since it was faster to just do it than to explain how to do it, you can get it from https://github.com/abarnert/pykeycode and just do the usual "python setup.py build_ext --inplace" or "sudo python setup.py install", then look at test.py to see how to use it.

Upvotes: 1

Related Questions