diff --git a/src/lib/deskflow/unix/AppUtilUnix.cpp b/src/lib/deskflow/unix/AppUtilUnix.cpp index 3a21aae63..0f1c3cc09 100644 --- a/src/lib/deskflow/unix/AppUtilUnix.cpp +++ b/src/lib/deskflow/unix/AppUtilUnix.cpp @@ -56,11 +56,19 @@ std::vector AppUtilUnix::getKeyboardLayoutList() AutoCFDictionary dict( CFDictionaryCreate(nullptr, (const void **)keys, (const void **)values, 1, nullptr, nullptr), CFRelease ); - AutoCFArray kbds(TISCreateInputSourceList(dict.get(), false), CFRelease); + AutoCFArray kbds(nullptr, CFRelease); + { + std::lock_guard lock(g_tisMutex); + kbds = AutoCFArray(TISCreateInputSourceList(dict.get(), false), CFRelease); + } for (CFIndex i = 0; i < CFArrayGetCount(kbds.get()); ++i) { TISInputSourceRef keyboardLayout = (TISInputSourceRef)CFArrayGetValueAtIndex(kbds.get(), i); - auto layoutLanguages = (CFArrayRef)TISGetInputSourceProperty(keyboardLayout, kTISPropertyInputSourceLanguages); + CFArrayRef layoutLanguages = nullptr; + { + std::lock_guard lock(g_tisMutex); + layoutLanguages = (CFArrayRef)TISGetInputSourceProperty(keyboardLayout, kTISPropertyInputSourceLanguages); + } char temporaryCString[128] = {0}; for (CFIndex index = 0; index < CFArrayGetCount(layoutLanguages) && layoutLanguages; index++) { auto languageCode = (CFStringRef)CFArrayGetValueAtIndex(layoutLanguages, index); @@ -135,8 +143,14 @@ std::string AppUtilUnix::getCurrentLanguageCode() result = X11LayoutsParser::convertLayoutToISO(m_evdev, result); #elif defined(Q_OS_MAC) - auto layoutLanguages = - (CFArrayRef)TISGetInputSourceProperty(TISCopyCurrentKeyboardInputSource(), kTISPropertyInputSourceLanguages); + AutoTISInputSourceRef source(nullptr, CFRelease); + CFArrayRef layoutLanguages = nullptr; + { + std::lock_guard lock(g_tisMutex); + source = AutoTISInputSourceRef(TISCopyCurrentKeyboardInputSource(), CFRelease); + if (source) + layoutLanguages = (CFArrayRef)TISGetInputSourceProperty(source.get(), kTISPropertyInputSourceLanguages); + } char temporaryCString[128] = {0}; for (CFIndex index = 0; index < CFArrayGetCount(layoutLanguages) && layoutLanguages; index++) { auto languageCode = (CFStringRef)CFArrayGetValueAtIndex(layoutLanguages, index); diff --git a/src/lib/platform/IOSXKeyResource.cpp b/src/lib/platform/IOSXKeyResource.cpp index 0e3dc6b4f..6c90c52dd 100644 --- a/src/lib/platform/IOSXKeyResource.cpp +++ b/src/lib/platform/IOSXKeyResource.cpp @@ -6,6 +6,7 @@ #include "platform/IOSXKeyResource.h" +#include "platform/OSXAutoTypes.h" #include KeyID IOSXKeyResource::getKeyID(uint8_t c) @@ -101,8 +102,14 @@ KeyID IOSXKeyResource::getKeyID(uint8_t c) str[1] = 0; // get current keyboard script - TISInputSourceRef isref = TISCopyCurrentKeyboardInputSource(); - CFArrayRef langs = (CFArrayRef)TISGetInputSourceProperty(isref, kTISPropertyInputSourceLanguages); + AutoTISInputSourceRef isref(nullptr, CFRelease); + CFArrayRef langs = nullptr; + { + std::lock_guard lock(g_tisMutex); + isref = AutoTISInputSourceRef(TISCopyCurrentKeyboardInputSource(), CFRelease); + if (isref) + langs = (CFArrayRef)TISGetInputSourceProperty(isref.get(), kTISPropertyInputSourceLanguages); + } CFStringEncoding encoding = CFStringConvertIANACharSetNameToEncoding((CFStringRef)CFArrayGetValueAtIndex(langs, 0)); // convert to unicode CFStringRef cfString = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, str, encoding, kCFAllocatorNull); diff --git a/src/lib/platform/OSXAutoTypes.h b/src/lib/platform/OSXAutoTypes.h index 2de172d5e..1cf8750fb 100644 --- a/src/lib/platform/OSXAutoTypes.h +++ b/src/lib/platform/OSXAutoTypes.h @@ -7,8 +7,11 @@ #include #include +#include using CFDeallocator = decltype(&CFRelease); using AutoCFArray = std::unique_ptr; using AutoCFDictionary = std::unique_ptr; using AutoTISInputSourceRef = std::unique_ptr<__TISInputSource, CFDeallocator>; + +inline std::mutex g_tisMutex; diff --git a/src/lib/platform/OSXKeyState.cpp b/src/lib/platform/OSXKeyState.cpp index 29c50e4c8..ade788e7f 100644 --- a/src/lib/platform/OSXKeyState.cpp +++ b/src/lib/platform/OSXKeyState.cpp @@ -293,7 +293,14 @@ KeyButton OSXKeyState::mapKeyFromEvent(KeyIDs &ids, KeyModifierMask *maskOut, CG } // get keyboard info - AutoTISInputSourceRef currentKeyboardLayout(TISCopyCurrentKeyboardLayoutInputSource(), CFRelease); + AutoTISInputSourceRef currentKeyboardLayout(nullptr, CFRelease); + CFDataRef ref = nullptr; + { + std::lock_guard lock(g_tisMutex); + currentKeyboardLayout = AutoTISInputSourceRef(TISCopyCurrentKeyboardLayoutInputSource(), CFRelease); + if (currentKeyboardLayout) + ref = (CFDataRef)TISGetInputSourceProperty(currentKeyboardLayout.get(), kTISPropertyUnicodeKeyLayoutData); + } if (!currentKeyboardLayout) { return kKeyNone; @@ -325,7 +332,6 @@ KeyButton OSXKeyState::mapKeyFromEvent(KeyIDs &ids, KeyModifierMask *maskOut, CG } // translate via uchr resource - CFDataRef ref = (CFDataRef)TISGetInputSourceProperty(currentKeyboardLayout.get(), kTISPropertyUnicodeKeyLayoutData); const UCKeyboardLayout *layout = (const UCKeyboardLayout *)CFDataGetBytePtr(ref); const bool layoutValid = (layout != nullptr); @@ -427,8 +433,14 @@ KeyModifierMask OSXKeyState::pollActiveModifiers() const int32_t OSXKeyState::pollActiveGroup() const { - AutoTISInputSourceRef keyboardLayout(TISCopyCurrentKeyboardLayoutInputSource(), CFRelease); - CFDataRef id = (CFDataRef)TISGetInputSourceProperty(keyboardLayout.get(), kTISPropertyInputSourceID); + AutoTISInputSourceRef keyboardLayout(nullptr, CFRelease); + CFDataRef id = nullptr; + { + std::lock_guard lock(g_tisMutex); + keyboardLayout = AutoTISInputSourceRef(TISCopyCurrentKeyboardLayoutInputSource(), CFRelease); + if (keyboardLayout) + id = (CFDataRef)TISGetInputSourceProperty(keyboardLayout.get(), kTISPropertyInputSourceID); + } GroupMap::const_iterator i = m_groupMap.find(id); if (i != m_groupMap.end()) { @@ -463,7 +475,11 @@ void OSXKeyState::getKeyMap(deskflow::KeyMap &keyMap) numGroups = CFArrayGetCount(m_groups.get()); for (int32_t g = 0; g < numGroups; ++g) { TISInputSourceRef keyboardLayout = (TISInputSourceRef)CFArrayGetValueAtIndex(m_groups.get(), g); - CFDataRef id = (CFDataRef)TISGetInputSourceProperty(keyboardLayout, kTISPropertyInputSourceID); + CFDataRef id = nullptr; + { + std::lock_guard lock(g_tisMutex); + id = (CFDataRef)TISGetInputSourceProperty(keyboardLayout, kTISPropertyInputSourceID); + } m_groupMap[id] = g; } } @@ -479,7 +495,11 @@ void OSXKeyState::getKeyMap(deskflow::KeyMap &keyMap) // add regular keys // try uchr resource first TISInputSourceRef keyboardLayout = (TISInputSourceRef)CFArrayGetValueAtIndex(m_groups.get(), g); - CFDataRef resourceRef = (CFDataRef)TISGetInputSourceProperty(keyboardLayout, kTISPropertyUnicodeKeyLayoutData); + CFDataRef resourceRef = nullptr; + { + std::lock_guard lock(g_tisMutex); + resourceRef = (CFDataRef)TISGetInputSourceProperty(keyboardLayout, kTISPropertyUnicodeKeyLayoutData); + } layoutValid = resourceRef != nullptr; if (layoutValid) @@ -853,7 +873,11 @@ bool OSXKeyState::getGroups(AutoCFArray &groups) const AutoCFDictionary dict( CFDictionaryCreate(nullptr, (const void **)keys, (const void **)values, 1, nullptr, nullptr), CFRelease ); - AutoCFArray kbds(TISCreateInputSourceList(dict.get(), false), CFRelease); + AutoCFArray kbds(nullptr, CFRelease); + { + std::lock_guard lock(g_tisMutex); + kbds = AutoCFArray(TISCreateInputSourceList(dict.get(), false), CFRelease); + } if (CFArrayGetCount(kbds.get()) > 0) { groups = std::move(kbds); @@ -872,15 +896,23 @@ void OSXKeyState::setGroup(int32_t group) LOG_WARN("needed keyboard layout is null"); return; } - auto canBeSetted = (CFBooleanRef - )TISGetInputSourceProperty(TISCopyCurrentKeyboardInputSource(), kTISPropertyInputSourceIsEnableCapable); + CFBooleanRef canBeSetted = nullptr; + { + std::lock_guard lock(g_tisMutex); + AutoTISInputSourceRef source(TISCopyCurrentKeyboardInputSource(), CFRelease); + if (source) + canBeSetted = (CFBooleanRef)TISGetInputSourceProperty(source.get(), kTISPropertyInputSourceIsEnableCapable); + } if (!canBeSetted) { LOG_WARN("needed keyboard layout is disabled for programmatically selection"); return; } - if (TISSelectInputSource(keyboardLayout) != noErr) { - LOG_WARN("failed to set needed keyboard layout"); + { + std::lock_guard lock(g_tisMutex); + if (TISSelectInputSource(keyboardLayout) != noErr) { + LOG_WARN("failed to set needed keyboard layout"); + } } LOG_DEBUG1("keyboard layout change to %d", group);