Skip to content

Instantly share code, notes, and snippets.

@typoman
Last active September 5, 2020 16:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save typoman/a316275f1316581d8e7bdb8f4a9c0242 to your computer and use it in GitHub Desktop.
Save typoman/a316275f1316581d8e7bdb8f4a9c0242 to your computer and use it in GitHub Desktop.
Finds currently availabe keyboard layout input sources in Mac OSX using pyobjc.
import ctypes
import ctypes.util
import objc
import CoreFoundation
"""
Find currently availabe keyboard layout input sources in Mac OSX using pyobjc. Based on:
https://gist.github.com/tiann/f85e89bef4b6e9b83f2a
"""
_Carbon = ctypes.cdll.LoadLibrary(ctypes.util.find_library('_Carbon'))
_objc = ctypes.PyDLL(objc._objc.__file__)
_objc.PyObjCObject_New.restype = ctypes.py_object
_objc.PyObjCObject_New.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_int]
def objcify(id):
return _objc.PyObjCObject_New(id, 0, 1)
kTISPropertyInputSourceLanguages_p = ctypes.c_void_p.in_dll(_Carbon, 'kTISPropertyInputSourceLanguages')
kTISPropertyInputSourceType_p = ctypes.c_void_p.in_dll(_Carbon, 'kTISPropertyInputSourceType')
kTISPropertyLocalizedName_p = ctypes.c_void_p.in_dll(_Carbon, 'kTISPropertyLocalizedName')
_Carbon.TISCreateInputSourceList.restype = ctypes.c_void_p
_Carbon.TISCreateInputSourceList.argtypes = [ctypes.c_void_p, ctypes.c_bool]
_Carbon.TISSelectInputSource.restype = ctypes.c_void_p
_Carbon.TISSelectInputSource.argtypes = [ctypes.c_void_p]
_Carbon.TISGetInputSourceProperty.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
_Carbon.TISGetInputSourceProperty.restype = ctypes.c_void_p
_Carbon.TISCopyInputSourceForLanguage.argtypes = [ctypes.c_void_p]
_Carbon.TISCopyInputSourceForLanguage.restype = ctypes.c_void_p
class keyboardInputSource():
def __init__(self, TISInputSource):
self._TISInputSource = TISInputSource
self._objcId = TISInputSource.__c_void_p__()
def getProperty(self, propertyName):
return objcify(_Carbon.TISGetInputSourceProperty(self._objcId, propertyName))
def getLocalizedName(self):
return str(self.getProperty(kTISPropertyLocalizedName_p))
def getDefaultLanguageName(self):
return self.getProperty(kTISPropertyInputSourceLanguages_p)[0]
def isKeyboardLayout(self):
return str(self.getProperty(kTISPropertyInputSourceType_p)) == "TISTypeKeyboardLayout"
def getAllKeyboardLayoutsMap():
result = {}
for o in objcify(_Carbon.TISCreateInputSourceList(None, 0)):
ins = keyboardInputSource(o)
if ins.isKeyboardLayout():
result[ins.getDefaultLanguageName()] = ins.getLocalizedName()
return result
def selectKeyboard(lang):
"""lang: 'en', 'fa', ..."""
cur = _Carbon.TISCopyInputSourceForLanguage(CoreFoundation.CFSTR(lang).__c_void_p__())
_Carbon.TISSelectInputSource(cur)
print(getAllKeyboardLayoutsMap())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment