fix(mac): protect TIS API calls with a mutex (they are not thread safe)
This commit is contained in:
parent
44c5c15082
commit
426b43fc09
4 changed files with 73 additions and 17 deletions
|
|
@ -56,11 +56,19 @@ std::vector<std::string> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "platform/IOSXKeyResource.h"
|
||||
|
||||
#include "platform/OSXAutoTypes.h"
|
||||
#include <Carbon/Carbon.h>
|
||||
|
||||
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<std::mutex> 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);
|
||||
|
|
|
|||
|
|
@ -7,8 +7,11 @@
|
|||
|
||||
#include <Carbon/Carbon.h>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
using CFDeallocator = decltype(&CFRelease);
|
||||
using AutoCFArray = std::unique_ptr<const __CFArray, CFDeallocator>;
|
||||
using AutoCFDictionary = std::unique_ptr<const __CFDictionary, CFDeallocator>;
|
||||
using AutoTISInputSourceRef = std::unique_ptr<__TISInputSource, CFDeallocator>;
|
||||
|
||||
inline std::mutex g_tisMutex;
|
||||
|
|
|
|||
|
|
@ -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<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> lock(g_tisMutex);
|
||||
kbds = AutoCFArray(TISCreateInputSourceList(dict.get(), false), CFRelease);
|
||||
}
|
||||
|
||||
if (CFArrayGetCount(kbds.get()) > 0) {
|
||||
groups = std::move(kbds);
|
||||
|
|
@ -872,16 +896,24 @@ 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<std::mutex> 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;
|
||||
}
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(g_tisMutex);
|
||||
if (TISSelectInputSource(keyboardLayout) != noErr) {
|
||||
LOG_WARN("failed to set needed keyboard layout");
|
||||
}
|
||||
}
|
||||
|
||||
LOG_DEBUG1("keyboard layout change to %d", group);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue