clean: simplify macOS hotkey mapping code
Some checks are pending
SonarCloud / Build and analyze (push) Waiting to run

This commit is contained in:
shenleban tongying 2024-11-12 07:33:28 -05:00 committed by GitHub
parent 8fc71c9586
commit 453948155a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -6,7 +6,9 @@
#include <QObject>
#include <QPushButton>
#include <QTimer>
#include <memory>
#include <vector>
#import <Appkit/Appkit.h>
@ -31,70 +33,63 @@ struct ReverseMapEntry {
UInt16 keyCode;
};
static struct ReverseMapEntry* mapping;
static int mapEntries = 0;
static std::vector<ReverseMapEntry> mapping;
/// References:
/// * https://github.com/libsdl-org/SDL/blob/fc12cc6dfd859a4e01376162a58f12208e539ac6/src/video/cocoa/SDL_cocoakeyboard.m#L345
/// * https://github.com/qt/qtbase/blob/922369844fcb75386237bca3eef59edd5093f58d/src/gui/platform/darwin/qapplekeymapper.mm#L449
///
/// Known possible flaws 1) UCKeyTranslate doesn't handle modifiers at all 2) Handling keyboard switching
void createMapping()
{
if (mapping == NULL) {
TISInputSourceRef inputSourceRef = TISCopyInputSourceForLanguage(CFSTR("en"));
if (!inputSourceRef) {
inputSourceRef = TISCopyCurrentKeyboardInputSource();
}
if (mapping.empty()) {
mapping.reserve(128);
TISInputSourceRef inputSourceRef = TISCopyCurrentKeyboardLayoutInputSource();
if (!inputSourceRef) {
return;
}
CFDataRef dataRef = (CFDataRef)TISGetInputSourceProperty(inputSourceRef,
kTISPropertyUnicodeKeyLayoutData);
// this method returns null under macos Japanese input method(and also Chinese), which causes cmd+C+C not to be registered as a hotkey
if (!dataRef) {
// solve the null value under Japanese keyboard
inputSourceRef = TISCopyCurrentKeyboardLayoutInputSource();
dataRef = static_cast<CFDataRef>((TISGetInputSourceProperty(inputSourceRef, kTISPropertyUnicodeKeyLayoutData)));
if (!dataRef) {
return;
}
CFDataRef uchrDataRef = (CFDataRef)TISGetInputSourceProperty(inputSourceRef, kTISPropertyUnicodeKeyLayoutData);
const UCKeyboardLayout* UCKeyboardLayoutPtr;
if (uchrDataRef) {
UCKeyboardLayoutPtr = (const UCKeyboardLayout*)CFDataGetBytePtr(uchrDataRef);
}
const UCKeyboardLayout* keyboardLayoutPtr = (const UCKeyboardLayout*)CFDataGetBytePtr(dataRef);
if (!keyboardLayoutPtr) {
if (!UCKeyboardLayoutPtr) {
return;
}
mapping = (struct ReverseMapEntry*)calloc(128, sizeof(struct ReverseMapEntry));
if (!mapping) {
return;
}
mapEntries = 0;
for (int i = 0; i < 128; i++) {
for (UInt16 i = 0; i < 128; i++) {
UInt32 theDeadKeyState = 0;
UniCharCount theLength = 0;
if (UCKeyTranslate(keyboardLayoutPtr, i, kUCKeyActionDisplay, 0, LMGetKbdType(),
UniChar temp_char_buf;
if (UCKeyTranslate(UCKeyboardLayoutPtr, i, kUCKeyActionDown, 0, LMGetKbdType(),
kUCKeyTranslateNoDeadKeysBit, &theDeadKeyState, 1, &theLength,
&mapping[mapEntries].character)
&temp_char_buf)
== noErr
&& theLength > 0) {
if (isprint(mapping[mapEntries].character)) {
mapping[mapEntries++].keyCode = i;
if (isprint(temp_char_buf)) {
mapping.emplace_back(ReverseMapEntry { temp_char_buf, i });
}
}
}
mapping.shrink_to_fit();
}
}
quint32 qtKeyToNativeKey(quint32 key)
quint32 qtKeyToNativeKey(UniChar key)
{
createMapping();
if (mapping == NULL) {
if (mapping.empty()) {
return 0;
}
for (int i = 0; i < mapEntries; i++) {
if (mapping[i].character == key) {
return mapping[i].keyCode;
for (auto& m : mapping) {
if (m.character == key) {
return m.keyCode;
}
}
@ -345,7 +340,7 @@ quint32 HotkeyWrapper::nativeKey(int key)
return 0x72;
default:;
}
return MacKeyMapping::qtKeyToNativeKey(QChar(key).toLower().toLatin1());
return MacKeyMapping::qtKeyToNativeKey(QChar(key).toLower().unicode());
}
void HotkeyWrapper::sendCmdC()