fix(macos): build key map with UCKeyTranslate to honor keyboard type
This commit is contained in:
parent
abcd4278fe
commit
a074de1b7c
6 changed files with 135 additions and 309 deletions
|
|
@ -84,6 +84,8 @@ elseif(APPLE)
|
||||||
OSXCocoaApp.m
|
OSXCocoaApp.m
|
||||||
OSXEventQueueBuffer.cpp
|
OSXEventQueueBuffer.cpp
|
||||||
OSXEventQueueBuffer.h
|
OSXEventQueueBuffer.h
|
||||||
|
OSXKeyLayoutResource.cpp
|
||||||
|
OSXKeyLayoutResource.h
|
||||||
OSXKeyState.cpp
|
OSXKeyState.cpp
|
||||||
OSXKeyState.h
|
OSXKeyState.h
|
||||||
OSXMediaKeySupport.h
|
OSXMediaKeySupport.h
|
||||||
|
|
@ -99,8 +101,6 @@ elseif(APPLE)
|
||||||
OSXScreenSaverControl.h
|
OSXScreenSaverControl.h
|
||||||
OSXScreenSaverUtil.h
|
OSXScreenSaverUtil.h
|
||||||
OSXScreenSaverUtil.m
|
OSXScreenSaverUtil.m
|
||||||
OSXUchrKeyResource.cpp
|
|
||||||
OSXUchrKeyResource.h
|
|
||||||
)
|
)
|
||||||
elseif(UNIX)
|
elseif(UNIX)
|
||||||
set(PLATFORM_SOURCES
|
set(PLATFORM_SOURCES
|
||||||
|
|
|
||||||
93
src/lib/platform/OSXKeyLayoutResource.cpp
Normal file
93
src/lib/platform/OSXKeyLayoutResource.cpp
Normal file
|
|
@ -0,0 +1,93 @@
|
||||||
|
/*
|
||||||
|
* Deskflow -- mouse and keyboard sharing utility
|
||||||
|
* SPDX-FileCopyrightText: (C) 2026 Deskflow Developers
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "platform/OSXKeyLayoutResource.h"
|
||||||
|
|
||||||
|
// there are 128 virtual key codes and 32 modifier combinations (the
|
||||||
|
// right-handed modifier bits are ignored, matching the uchr parser).
|
||||||
|
static const uint32_t s_numButtons = 128;
|
||||||
|
static const uint32_t s_numModifierCombinations = 32;
|
||||||
|
|
||||||
|
OSXKeyLayoutResource::OSXKeyLayoutResource(const void *resource, uint32_t keyboardType)
|
||||||
|
: m_layout(static_cast<const UCKeyboardLayout *>(resource)),
|
||||||
|
m_keyboardType(keyboardType)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OSXKeyLayoutResource::isValid() const
|
||||||
|
{
|
||||||
|
return m_layout != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t OSXKeyLayoutResource::getNumModifierCombinations() const
|
||||||
|
{
|
||||||
|
return s_numModifierCombinations;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t OSXKeyLayoutResource::getNumTables() const
|
||||||
|
{
|
||||||
|
// one table per modifier combination
|
||||||
|
return s_numModifierCombinations;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t OSXKeyLayoutResource::getNumButtons() const
|
||||||
|
{
|
||||||
|
return s_numButtons;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t OSXKeyLayoutResource::getTableForModifier(uint32_t mask) const
|
||||||
|
{
|
||||||
|
// the modifier combination is the table
|
||||||
|
return (mask < s_numModifierCombinations) ? mask : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyID OSXKeyLayoutResource::getKey(uint32_t table, uint32_t button) const
|
||||||
|
{
|
||||||
|
if (m_layout == nullptr || button >= s_numButtons) {
|
||||||
|
return kKeyNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
// UCKeyTranslate's modifier key state uses the same low five bits as our
|
||||||
|
// table index (cmd, shift, caps, option, control).
|
||||||
|
const UInt32 modifierState = table;
|
||||||
|
|
||||||
|
UInt32 deadKeyState = 0;
|
||||||
|
UniChar chars[4] = {0};
|
||||||
|
UniCharCount count = 0;
|
||||||
|
OSStatus status = UCKeyTranslate(
|
||||||
|
m_layout, static_cast<UInt16>(button), kUCKeyActionDown, modifierState, m_keyboardType, 0, &deadKeyState,
|
||||||
|
sizeof(chars) / sizeof(chars[0]), &count, chars
|
||||||
|
);
|
||||||
|
if (status != noErr) {
|
||||||
|
return kKeyNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count == 0) {
|
||||||
|
// no output. a non-zero dead-key state means this is a dead key: resolve
|
||||||
|
// it to its spacing character by following it with a space, then convert
|
||||||
|
// to the dead KeyID.
|
||||||
|
if (deadKeyState == 0) {
|
||||||
|
return kKeyNone;
|
||||||
|
}
|
||||||
|
UniChar spaceChars[4] = {0};
|
||||||
|
UniCharCount spaceCount = 0;
|
||||||
|
status = UCKeyTranslate(
|
||||||
|
m_layout, kVK_Space, kUCKeyActionDown, 0, m_keyboardType, 0, &deadKeyState,
|
||||||
|
sizeof(spaceChars) / sizeof(spaceChars[0]), &spaceCount, spaceChars
|
||||||
|
);
|
||||||
|
if (status != noErr || spaceCount != 1) {
|
||||||
|
return kKeyNone;
|
||||||
|
}
|
||||||
|
return deskflow::KeyMap::getDeadKey(unicharToKeyID(spaceChars[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// no support for multi-character output (matches the uchr parser).
|
||||||
|
if (count != 1) {
|
||||||
|
return kKeyNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
return unicharToKeyID(chars[0]);
|
||||||
|
}
|
||||||
34
src/lib/platform/OSXKeyLayoutResource.h
Normal file
34
src/lib/platform/OSXKeyLayoutResource.h
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* Deskflow -- mouse and keyboard sharing utility
|
||||||
|
* SPDX-FileCopyrightText: (C) 2026 Deskflow Developers
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "platform/IOSXKeyResource.h"
|
||||||
|
|
||||||
|
#include <Carbon/Carbon.h>
|
||||||
|
|
||||||
|
//! Key resource for a keyboard layout, backed by UCKeyTranslate
|
||||||
|
/*!
|
||||||
|
Builds the key map for a keyboard layout using UCKeyTranslate. Each modifier
|
||||||
|
combination is treated as its own table.
|
||||||
|
*/
|
||||||
|
class OSXKeyLayoutResource : public IOSXKeyResource
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
OSXKeyLayoutResource(const void *resource, uint32_t keyboardType);
|
||||||
|
|
||||||
|
// IOSXKeyResource overrides
|
||||||
|
bool isValid() const override;
|
||||||
|
uint32_t getNumModifierCombinations() const override;
|
||||||
|
uint32_t getNumTables() const override;
|
||||||
|
uint32_t getNumButtons() const override;
|
||||||
|
uint32_t getTableForModifier(uint32_t mask) const override;
|
||||||
|
KeyID getKey(uint32_t table, uint32_t button) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const UCKeyboardLayout *m_layout;
|
||||||
|
uint32_t m_keyboardType;
|
||||||
|
};
|
||||||
|
|
@ -8,8 +8,8 @@
|
||||||
#include "platform/OSXKeyState.h"
|
#include "platform/OSXKeyState.h"
|
||||||
#include "arch/Arch.h"
|
#include "arch/Arch.h"
|
||||||
#include "base/Log.h"
|
#include "base/Log.h"
|
||||||
|
#include "platform/OSXKeyLayoutResource.h"
|
||||||
#include "platform/OSXMediaKeySupport.h"
|
#include "platform/OSXMediaKeySupport.h"
|
||||||
#include "platform/OSXUchrKeyResource.h"
|
|
||||||
|
|
||||||
#include <Carbon/Carbon.h>
|
#include <Carbon/Carbon.h>
|
||||||
#include <IOKit/hidsystem/IOHIDLib.h>
|
#include <IOKit/hidsystem/IOHIDLib.h>
|
||||||
|
|
@ -527,8 +527,7 @@ void OSXKeyState::getKeyMap(deskflow::KeyMap &keyMap)
|
||||||
const void *resource;
|
const void *resource;
|
||||||
bool layoutValid = false;
|
bool layoutValid = false;
|
||||||
|
|
||||||
// add regular keys
|
// add regular keys from the layout's key data
|
||||||
// try uchr resource first
|
|
||||||
TISInputSourceRef keyboardLayout = (TISInputSourceRef)CFArrayGetValueAtIndex(m_groups.get(), g);
|
TISInputSourceRef keyboardLayout = (TISInputSourceRef)CFArrayGetValueAtIndex(m_groups.get(), g);
|
||||||
CFDataRef resourceRef = nullptr;
|
CFDataRef resourceRef = nullptr;
|
||||||
{
|
{
|
||||||
|
|
@ -541,10 +540,10 @@ void OSXKeyState::getKeyMap(deskflow::KeyMap &keyMap)
|
||||||
resource = CFDataGetBytePtr(resourceRef);
|
resource = CFDataGetBytePtr(resourceRef);
|
||||||
|
|
||||||
if (layoutValid) {
|
if (layoutValid) {
|
||||||
OSXUchrKeyResource uchr(resource, keyboardType);
|
OSXKeyLayoutResource keyResource(resource, keyboardType);
|
||||||
if (uchr.isValid()) {
|
if (keyResource.isValid()) {
|
||||||
LOG_VERBOSE("using uchr resource for group %d", g);
|
LOG_VERBOSE("using key layout for group %d", g);
|
||||||
getKeyMap(keyMap, g, uchr);
|
getKeyMap(keyMap, g, keyResource);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,257 +0,0 @@
|
||||||
/*
|
|
||||||
* Deskflow -- mouse and keyboard sharing utility
|
|
||||||
* SPDX-FileCopyrightText: (C) 2016 Synergy App Ltd
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "platform/OSXUchrKeyResource.h"
|
|
||||||
|
|
||||||
#include <Carbon/Carbon.h>
|
|
||||||
|
|
||||||
//
|
|
||||||
// OSXUchrKeyResource
|
|
||||||
//
|
|
||||||
|
|
||||||
OSXUchrKeyResource::OSXUchrKeyResource(const void *resource, uint32_t keyboardType)
|
|
||||||
: m_m(nullptr),
|
|
||||||
m_cti(nullptr),
|
|
||||||
m_sdi(nullptr),
|
|
||||||
m_sri(nullptr),
|
|
||||||
m_st(nullptr)
|
|
||||||
{
|
|
||||||
m_resource = static_cast<const UCKeyboardLayout *>(resource);
|
|
||||||
if (m_resource == nullptr) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// find the keyboard info for the current keyboard type
|
|
||||||
const UCKeyboardTypeHeader *th = nullptr;
|
|
||||||
const UCKeyboardLayout *r = m_resource;
|
|
||||||
for (ItemCount i = 0; i < r->keyboardTypeCount; ++i) {
|
|
||||||
if (keyboardType >= r->keyboardTypeList[i].keyboardTypeFirst &&
|
|
||||||
keyboardType <= r->keyboardTypeList[i].keyboardTypeLast) {
|
|
||||||
th = r->keyboardTypeList + i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (r->keyboardTypeList[i].keyboardTypeFirst == 0) {
|
|
||||||
// found the default. use it unless we find a match.
|
|
||||||
th = r->keyboardTypeList + i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (th == nullptr) {
|
|
||||||
// cannot find a suitable keyboard type
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get tables for keyboard type
|
|
||||||
const uint8_t *const base = reinterpret_cast<const uint8_t *>(m_resource);
|
|
||||||
m_m = reinterpret_cast<const UCKeyModifiersToTableNum *>(base + th->keyModifiersToTableNumOffset);
|
|
||||||
m_cti = reinterpret_cast<const UCKeyToCharTableIndex *>(base + th->keyToCharTableIndexOffset);
|
|
||||||
m_sdi = reinterpret_cast<const UCKeySequenceDataIndex *>(base + th->keySequenceDataIndexOffset);
|
|
||||||
if (th->keyStateRecordsIndexOffset != 0) {
|
|
||||||
m_sri = reinterpret_cast<const UCKeyStateRecordsIndex *>(base + th->keyStateRecordsIndexOffset);
|
|
||||||
}
|
|
||||||
if (th->keyStateTerminatorsOffset != 0) {
|
|
||||||
m_st = reinterpret_cast<const UCKeyStateTerminators *>(base + th->keyStateTerminatorsOffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
// find the space key, but only if it can combine with dead keys.
|
|
||||||
// a dead key followed by a space yields the non-dead version of
|
|
||||||
// the dead key.
|
|
||||||
m_spaceOutput = 0xffffu;
|
|
||||||
uint32_t table = getTableForModifier(0);
|
|
||||||
for (uint32_t button = 0, n = getNumButtons(); button < n; ++button) {
|
|
||||||
KeyID id = getKey(table, button);
|
|
||||||
if (id == 0x20) {
|
|
||||||
UCKeyOutput c = reinterpret_cast<const UCKeyOutput *>(base + m_cti->keyToCharTableOffsets[table])[button];
|
|
||||||
if ((c & kUCKeyOutputTestForIndexMask) == kUCKeyOutputStateIndexMask) {
|
|
||||||
m_spaceOutput = (c & kUCKeyOutputGetIndexMask);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OSXUchrKeyResource::isValid() const
|
|
||||||
{
|
|
||||||
return (m_m != nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t OSXUchrKeyResource::getNumModifierCombinations() const
|
|
||||||
{
|
|
||||||
// only 32 (not 256) because the righthanded modifier bits are ignored
|
|
||||||
return 32;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t OSXUchrKeyResource::getNumTables() const
|
|
||||||
{
|
|
||||||
return m_cti->keyToCharTableCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t OSXUchrKeyResource::getNumButtons() const
|
|
||||||
{
|
|
||||||
return m_cti->keyToCharTableSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t OSXUchrKeyResource::getTableForModifier(uint32_t mask) const
|
|
||||||
{
|
|
||||||
if (mask >= m_m->modifiersCount) {
|
|
||||||
return m_m->defaultTableNum;
|
|
||||||
} else {
|
|
||||||
return m_m->tableNum[mask];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
KeyID OSXUchrKeyResource::getKey(uint32_t table, uint32_t button) const
|
|
||||||
{
|
|
||||||
assert(table < getNumTables());
|
|
||||||
assert(button < getNumButtons());
|
|
||||||
|
|
||||||
const uint8_t *const base = reinterpret_cast<const uint8_t *>(m_resource);
|
|
||||||
const UCKeyOutput *cPtr = reinterpret_cast<const UCKeyOutput *>(base + m_cti->keyToCharTableOffsets[table]);
|
|
||||||
|
|
||||||
const UCKeyOutput c = cPtr[button];
|
|
||||||
|
|
||||||
KeySequence keys;
|
|
||||||
switch (c & kUCKeyOutputTestForIndexMask) {
|
|
||||||
case kUCKeyOutputStateIndexMask:
|
|
||||||
if (!getDeadKey(keys, c & kUCKeyOutputGetIndexMask)) {
|
|
||||||
return kKeyNone;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case kUCKeyOutputSequenceIndexMask:
|
|
||||||
default:
|
|
||||||
if (!addSequence(keys, c)) {
|
|
||||||
return kKeyNone;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// XXX -- no support for multiple characters
|
|
||||||
if (keys.size() != 1) {
|
|
||||||
return kKeyNone;
|
|
||||||
}
|
|
||||||
|
|
||||||
return keys.front();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OSXUchrKeyResource::getDeadKey(KeySequence &keys, uint16_t index) const
|
|
||||||
{
|
|
||||||
if (m_sri == nullptr || index >= m_sri->keyStateRecordCount) {
|
|
||||||
// XXX -- should we be using some other fallback?
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t state = 0;
|
|
||||||
if (!getKeyRecord(keys, index, state)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (state == 0) {
|
|
||||||
// not a dead key
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// no dead keys if we couldn't find the space key
|
|
||||||
if (m_spaceOutput == 0xffffu) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// the dead key should not have put anything in the key list
|
|
||||||
if (!keys.empty()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the character generated by pressing the space key after the
|
|
||||||
// dead key. if we're still in a compose state afterwards then we're
|
|
||||||
// confused so we bail.
|
|
||||||
if (!getKeyRecord(keys, m_spaceOutput, state) || state != 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// convert keys to their dead counterparts
|
|
||||||
for (KeySequence::iterator i = keys.begin(); i != keys.end(); ++i) {
|
|
||||||
*i = deskflow::KeyMap::getDeadKey(*i);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OSXUchrKeyResource::getKeyRecord(KeySequence &keys, uint16_t index, uint16_t &state) const
|
|
||||||
{
|
|
||||||
const uint8_t *const base = reinterpret_cast<const uint8_t *>(m_resource);
|
|
||||||
const UCKeyStateRecord *sr = reinterpret_cast<const UCKeyStateRecord *>(base + m_sri->keyStateRecordOffsets[index]);
|
|
||||||
const UCKeyStateEntryTerminal *kset = reinterpret_cast<const UCKeyStateEntryTerminal *>(sr->stateEntryData);
|
|
||||||
|
|
||||||
uint16_t nextState = 0;
|
|
||||||
bool found = false;
|
|
||||||
if (state == 0) {
|
|
||||||
found = true;
|
|
||||||
nextState = sr->stateZeroNextState;
|
|
||||||
if (!addSequence(keys, sr->stateZeroCharData)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// we have a next entry
|
|
||||||
switch (sr->stateEntryFormat) {
|
|
||||||
case kUCKeyStateEntryTerminalFormat:
|
|
||||||
for (uint16_t j = 0; j < sr->stateEntryCount; ++j) {
|
|
||||||
if (kset[j].curState == state) {
|
|
||||||
if (!addSequence(keys, kset[j].charData)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
nextState = 0;
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case kUCKeyStateEntryRangeFormat:
|
|
||||||
// XXX -- not supported yet
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
// XXX -- unknown format
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!found) {
|
|
||||||
// use a terminator
|
|
||||||
if (m_st != nullptr && state < m_st->keyStateTerminatorCount) {
|
|
||||||
if (!addSequence(keys, m_st->keyStateTerminators[state - 1])) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nextState = sr->stateZeroNextState;
|
|
||||||
if (!addSequence(keys, sr->stateZeroCharData)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// next
|
|
||||||
state = nextState;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OSXUchrKeyResource::addSequence(KeySequence &keys, UCKeyCharSeq c) const
|
|
||||||
{
|
|
||||||
if ((c & kUCKeyOutputTestForIndexMask) == kUCKeyOutputSequenceIndexMask) {
|
|
||||||
uint16_t index = (c & kUCKeyOutputGetIndexMask);
|
|
||||||
if (index < m_sdi->charSequenceCount &&
|
|
||||||
m_sdi->charSequenceOffsets[index] != m_sdi->charSequenceOffsets[index + 1]) {
|
|
||||||
// XXX -- sequences not supported yet
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c != 0xfffe && c != 0xffff) {
|
|
||||||
KeyID id = unicharToKeyID(c);
|
|
||||||
if (id != kKeyNone) {
|
|
||||||
keys.push_back(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
||||||
/*
|
|
||||||
* Deskflow -- mouse and keyboard sharing utility
|
|
||||||
* SPDX-FileCopyrightText: (C) 2016 Synergy App Ltd
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "platform/IOSXKeyResource.h"
|
|
||||||
|
|
||||||
#include <Carbon/Carbon.h>
|
|
||||||
|
|
||||||
using KeyLayout = TISInputSourceRef;
|
|
||||||
|
|
||||||
class OSXUchrKeyResource : public IOSXKeyResource
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
OSXUchrKeyResource(const void *, uint32_t keyboardType);
|
|
||||||
|
|
||||||
// KeyResource overrides
|
|
||||||
bool isValid() const override;
|
|
||||||
uint32_t getNumModifierCombinations() const override;
|
|
||||||
uint32_t getNumTables() const override;
|
|
||||||
uint32_t getNumButtons() const override;
|
|
||||||
uint32_t getTableForModifier(uint32_t mask) const override;
|
|
||||||
KeyID getKey(uint32_t table, uint32_t button) const override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
using KeySequence = std::vector<KeyID>;
|
|
||||||
|
|
||||||
bool getDeadKey(KeySequence &keys, uint16_t index) const;
|
|
||||||
bool getKeyRecord(KeySequence &keys, uint16_t index, uint16_t &state) const;
|
|
||||||
bool addSequence(KeySequence &keys, UCKeyCharSeq c) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
const UCKeyboardLayout *m_resource;
|
|
||||||
const UCKeyModifiersToTableNum *m_m;
|
|
||||||
const UCKeyToCharTableIndex *m_cti;
|
|
||||||
const UCKeySequenceDataIndex *m_sdi;
|
|
||||||
const UCKeyStateRecordsIndex *m_sri;
|
|
||||||
const UCKeyStateTerminators *m_st;
|
|
||||||
uint16_t m_spaceOutput;
|
|
||||||
};
|
|
||||||
Loading…
Reference in a new issue