Skip to content

Instantly share code, notes, and snippets.

@pudquick

pudquick/input_sources.py

Last active Oct 3, 2019
Embed
What would you like to do?
Using python and pyobjc to enumerate and inspect input sources (keyboard layouts, input modes) on macOS
# Useful for com.apple.HIToolbox.plist for configuration of input types, amongst other things
from Foundation import NSBundle
import objc
HIToolbox_bundle = NSBundle.bundleWithIdentifier_("com.apple.HIToolbox")
HIT_functions = [
('TISCreateInputSourceList','@@B'),
('TISGetInputSourceProperty', '@@@'),
]
HIT_constants = [
('kTISPropertyInputSourceType', '@'),
('kTISTypeKeyboardLayout', '@'),
('kTISTypeKeyboardInputMode', '@'),
('kTISPropertyLocalizedName', '@'),
('kTISPropertyBundleID', '@'),
('kTISPropertyInputModeID', '@'),
('kTISPropertyInputSourceID', '@'),
('kTISPropertyLocale', '@'),
('kTISPropertyKeyLayoutNumber', '@'),
('kTISPropertyScriptCode', '@'),
]
objc.loadBundleFunctions(HIToolbox_bundle, globals(), HIT_functions)
# Yes, I know it's amusing that loadBundleVariables is loading constants - ... oh, so it's just me then? k
objc.loadBundleVariables(HIToolbox_bundle, globals(), HIT_constants)
# Can't figure out the constant names for these ones, so we'll make 'em up
kTISPropertyKind = u'TSMInputSourcePropertyKind'
# get the list of keyboard layouts
keyboard_layouts = TISCreateInputSourceList({kTISPropertyInputSourceType: kTISTypeKeyboardLayout}, True)
# (
# "<TSMInputSource 0x7ff8e9f2cc00> KB Layout: U.S. (id=0)",
# "<TSMInputSource 0x7ff8e9f2c5f0> KB Layout: Czech - QWERTY (id=30778)",
# "<TSMInputSource 0x7ff8e9f2b8c0> KB Layout: Czech (id=30776)",
# [...]
# get the list of input modes
input_modes = TISCreateInputSourceList({kTISPropertyInputSourceType: kTISTypeKeyboardInputMode}, True)
# (
# "<TSMInputSource 0x7ff8e9d857a0> Input Mode: com.apple.inputmethod.Japanese (Parent = com.apple.inputmethod.Kotoeri)",
# "<TSMInputSource 0x7ff8e9d85570> Input Mode: com.apple.inputmethod.Roman (Parent = com.apple.inputmethod.Kotoeri)",
# "<TSMInputSource 0x7ff8e9d855e0> Input Mode: com.apple.inputmethod.Japanese.Katakana (Parent = com.apple.inputmethod.Kotoeri)",
# "<TSMInputSource 0x7ff8e9d85600> Input Mode: com.apple.inputmethod.SCIM.ITABC (Parent = com.apple.inputmethod.SCIM)",
# [...]
# Example inspection of arbitrary sources
k1 = keyboard_layouts[1]
# <TSMInputSource 0x7ff8e9f2c5f0> KB Layout: Czech - QWERTY (id=30778)
k1_kind = TISGetInputSourceProperty(k1, kTISPropertyKind)
# u'TSMInputSourceKindKeyboardLayout'
k1_name = TISGetInputSourceProperty(k1, kTISPropertyLocalizedName)
# u'Czech - QWERTY'
k1_id = TISGetInputSourceProperty(k1, kTISPropertyKeyLayoutNumber)
# 30778
k1_script = TISGetInputSourceProperty(k1, kTISPropertyScriptCode)
# 29
k1_sid = TISGetInputSourceProperty(k1, kTISPropertyInputSourceID)
# u'com.apple.keylayout.Czech-QWERTY'
k1_locale = TISGetInputSourceProperty(k1, kTISPropertyLocale)
# u'cs'
i1 = input_modes[1]
# <TSMInputSource 0x7ff8e9d85570> Input Mode: com.apple.inputmethod.Roman (Parent = com.apple.inputmethod.Kotoeri)
i1_kind = TISGetInputSourceProperty(i1, kTISPropertyKind)
# u'TSMInputSourceKindKeyboardInputMode'
i1_name = TISGetInputSourceProperty(i1, kTISPropertyLocalizedName)
# u'Romaji'
i1_bundle = TISGetInputSourceProperty(i1, kTISPropertyBundleID)
# u'com.apple.inputmethod.Kotoeri'
i1_mode = TISGetInputSourceProperty(i1, kTISPropertyInputModeID)
# u'com.apple.inputmethod.Roman'
i1_sid = TISGetInputSourceProperty(i1, kTISPropertyInputSourceID)
# u'com.apple.inputmethod.Kotoeri.Roman'
i1_locale = TISGetInputSourceProperty(i1, kTISPropertyLocale)
# u'en'
# Need to come back and revisit the keyboard layout casting mentioned here ... http://stackoverflow.com/questions/35110663/getting-key-names-for-keyboard-codes-in-swift
@callmekohei

This comment has been minimized.

Copy link

@callmekohei callmekohei commented Aug 15, 2018

Hi! It's very very Great! :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.