Created
December 2, 2015 06:51
-
-
Save tiann/f85e89bef4b6e9b83f2a to your computer and use it in GitHub Desktop.
auto switch keyboard to english in specific applications
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /usr/bin/env python | |
# coding: utf-8 | |
''' | |
auto switch keyboard between different applications | |
if you want to change the app list, modify the var 'ignore_list' | |
''' | |
from AppKit import NSWorkspace, NSWorkspaceDidActivateApplicationNotification, NSWorkspaceApplicationKey | |
from Foundation import NSObject | |
from PyObjCTools import AppHelper | |
import ctypes | |
import ctypes.util | |
import objc | |
import CoreFoundation | |
# add your custom apps here, check the bundle id in /Application/xx.app/Contents/info.plist | |
ignore_list = [ | |
"com.googlecode.iterm2", | |
"com.runningwithcrayons.Alfred-2", | |
"com.jetbrains.intellij.ce-EAP" | |
] | |
carbon = ctypes.cdll.LoadLibrary(ctypes.util.find_library('Carbon')) | |
_objc = ctypes.PyDLL(objc._objc.__file__) | |
# PyObject *PyObjCObject_New(id objc_object, int flags, int retain) | |
_objc.PyObjCObject_New.restype = ctypes.py_object | |
_objc.PyObjCObject_New.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_int] | |
def objc_object(id): | |
return _objc.PyObjCObject_New(id, 0, 1) | |
# kTISPropertyLocalizedName | |
kTISPropertyUnicodeKeyLayoutData_p = ctypes.c_void_p.in_dll(carbon, 'kTISPropertyInputSourceIsEnabled') | |
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') | |
# kTISPropertyInputSourceLanguages_p = ctypes.c_void_p.in_dll(carbon, 'kTISPropertyInputSourceLanguages') | |
kTISPropertyInputSourceCategory = objc_object(ctypes.c_void_p.in_dll(carbon, 'kTISPropertyInputSourceCategory')) | |
kTISCategoryKeyboardInputSource = objc_object(ctypes.c_void_p.in_dll(carbon, 'kTISCategoryKeyboardInputSource')) | |
# TISCreateInputSourceList | |
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.TISCopyCurrentKeyboardLayoutInputSource.argtypes = [] | |
# carbon.TISCopyCurrentKeyboardLayoutInputSource.restype = ctypes.c_void_p | |
carbon.TISCopyInputSourceForLanguage.argtypes = [ctypes.c_void_p] | |
carbon.TISCopyInputSourceForLanguage.restype = ctypes.c_void_p | |
def get_avaliable_languages(): | |
single_langs = filter(lambda x: x.count() == 1, \ | |
map(lambda x: objc_object(carbon.TISGetInputSourceProperty(CoreFoundation.CFArrayGetValueAtIndex(objc_object(s), x).__c_void_p__(), kTISPropertyInputSourceLanguages_p)), \ | |
range(CoreFoundation.CFArrayGetCount(objc_object(carbon.TISCreateInputSourceList(None, 0)))))) | |
res = set() | |
map(lambda y: res.add(y[0]), single_langs) | |
return res | |
def select_kb(lang): | |
cur = carbon.TISCopyInputSourceForLanguage(CoreFoundation.CFSTR(lang).__c_void_p__()) | |
carbon.TISSelectInputSource(cur) | |
class Observer(NSObject): | |
def handle_(self, noti): | |
info = noti.userInfo().objectForKey_(NSWorkspaceApplicationKey) | |
bundleIdentifier = info.bundleIdentifier() | |
if bundleIdentifier in ignore_list: | |
print "found: %s active" % bundleIdentifier | |
select_kb(u'en') | |
def main(): | |
nc = NSWorkspace.sharedWorkspace().notificationCenter() | |
observer = Observer.new() | |
nc.addObserver_selector_name_object_( | |
observer, | |
"handle:", | |
NSWorkspaceDidActivateApplicationNotification, | |
None | |
) | |
AppHelper.runConsoleEventLoop(installInterrupt=True) | |
main() |
It used to work but it has stopped with new OSX (12.5.). Gives this error:
Traceback (most recent call last):
File "tmp.py", line 32, in <module>
_objc.PyObjCObject_New.restype = ctypes.py_object
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/ctypes/__init__.py", line 387, in __getattr__
func = self.__getitem__(name)
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/ctypes/__init__.py", line 392, in __getitem__
func = self._FuncPtr((name_or_ordinal, self))
AttributeError: dlsym(0x210f6b5c0, PyObjCObject_New): symbol not found
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
确实有这样的功能的话会很方便。有这么个软件:https://showyedge.pqrs.org/
是把输入法的状态显示在了窗口最上面。感觉不是很方便。