Refactor KeyResource into own files #2765
This commit is contained in:
parent
ed0888880c
commit
7f786cc884
|
@ -18,6 +18,7 @@
|
||||||
#ifndef COMMANDTHREAD_H
|
#ifndef COMMANDTHREAD_H
|
||||||
#define COMMANDTHREAD_H
|
#define COMMANDTHREAD_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
|
||||||
class CommandProcess : public QObject
|
class CommandProcess : public QObject
|
||||||
|
|
|
@ -18,8 +18,8 @@ if (WIN32)
|
||||||
file(GLOB headers "MSWindows*.h")
|
file(GLOB headers "MSWindows*.h")
|
||||||
file(GLOB sources "MSWindows*.cpp")
|
file(GLOB sources "MSWindows*.cpp")
|
||||||
elseif (APPLE)
|
elseif (APPLE)
|
||||||
file(GLOB headers "OSX*.h")
|
file(GLOB headers "OSX*.h" "*KeyResource.h")
|
||||||
file(GLOB sources "OSX*.cpp" "OSX*.m")
|
file(GLOB sources "OSX*.cpp" "OSX*.m" "*KeyResource.cpp")
|
||||||
elseif (UNIX)
|
elseif (UNIX)
|
||||||
file(GLOB headers "XWindows*.h")
|
file(GLOB headers "XWindows*.h")
|
||||||
file(GLOB sources "XWindows*.cpp")
|
file(GLOB sources "XWindows*.cpp")
|
||||||
|
|
|
@ -0,0 +1,193 @@
|
||||||
|
/*
|
||||||
|
* synergy -- mouse and keyboard sharing utility
|
||||||
|
* Copyright (C) 2016 Symless Ltd.
|
||||||
|
*
|
||||||
|
* This package is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* found in the file LICENSE that should have accompanied this file.
|
||||||
|
*
|
||||||
|
* This package is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "platform/IKeyResource.h"
|
||||||
|
|
||||||
|
#include <Carbon/Carbon.h>
|
||||||
|
|
||||||
|
//
|
||||||
|
// OSXKeyState::KeyResource
|
||||||
|
//
|
||||||
|
|
||||||
|
KeyID
|
||||||
|
IKeyResource::getKeyID(UInt8 c)
|
||||||
|
{
|
||||||
|
if (c == 0) {
|
||||||
|
return kKeyNone;
|
||||||
|
}
|
||||||
|
else if (c >= 32 && c < 127) {
|
||||||
|
// ASCII
|
||||||
|
return static_cast<KeyID>(c);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// handle special keys
|
||||||
|
switch (c) {
|
||||||
|
case 0x01:
|
||||||
|
return kKeyHome;
|
||||||
|
|
||||||
|
case 0x02:
|
||||||
|
return kKeyKP_Enter;
|
||||||
|
|
||||||
|
case 0x03:
|
||||||
|
return kKeyKP_Enter;
|
||||||
|
|
||||||
|
case 0x04:
|
||||||
|
return kKeyEnd;
|
||||||
|
|
||||||
|
case 0x05:
|
||||||
|
return kKeyHelp;
|
||||||
|
|
||||||
|
case 0x08:
|
||||||
|
return kKeyBackSpace;
|
||||||
|
|
||||||
|
case 0x09:
|
||||||
|
return kKeyTab;
|
||||||
|
|
||||||
|
case 0x0b:
|
||||||
|
return kKeyPageUp;
|
||||||
|
|
||||||
|
case 0x0c:
|
||||||
|
return kKeyPageDown;
|
||||||
|
|
||||||
|
case 0x0d:
|
||||||
|
return kKeyReturn;
|
||||||
|
|
||||||
|
case 0x10:
|
||||||
|
// OS X maps all the function keys (F1, etc) to this one key.
|
||||||
|
// we can't determine the right key here so we have to do it
|
||||||
|
// some other way.
|
||||||
|
return kKeyNone;
|
||||||
|
|
||||||
|
case 0x1b:
|
||||||
|
return kKeyEscape;
|
||||||
|
|
||||||
|
case 0x1c:
|
||||||
|
return kKeyLeft;
|
||||||
|
|
||||||
|
case 0x1d:
|
||||||
|
return kKeyRight;
|
||||||
|
|
||||||
|
case 0x1e:
|
||||||
|
return kKeyUp;
|
||||||
|
|
||||||
|
case 0x1f:
|
||||||
|
return kKeyDown;
|
||||||
|
|
||||||
|
case 0x7f:
|
||||||
|
return kKeyDelete;
|
||||||
|
|
||||||
|
case 0x06:
|
||||||
|
case 0x07:
|
||||||
|
case 0x0a:
|
||||||
|
case 0x0e:
|
||||||
|
case 0x0f:
|
||||||
|
case 0x11:
|
||||||
|
case 0x12:
|
||||||
|
case 0x13:
|
||||||
|
case 0x14:
|
||||||
|
case 0x15:
|
||||||
|
case 0x16:
|
||||||
|
case 0x17:
|
||||||
|
case 0x18:
|
||||||
|
case 0x19:
|
||||||
|
case 0x1a:
|
||||||
|
// discard other control characters
|
||||||
|
return kKeyNone;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// not special or unknown
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create string with character
|
||||||
|
char str[2];
|
||||||
|
str[0] = static_cast<char>(c);
|
||||||
|
str[1] = 0;
|
||||||
|
|
||||||
|
// get current keyboard script
|
||||||
|
TISInputSourceRef isref = TISCopyCurrentKeyboardInputSource();
|
||||||
|
CFArrayRef langs = (CFArrayRef) TISGetInputSourceProperty(isref, kTISPropertyInputSourceLanguages);
|
||||||
|
CFStringEncoding encoding = CFStringConvertIANACharSetNameToEncoding(
|
||||||
|
(CFStringRef)CFArrayGetValueAtIndex(langs, 0));
|
||||||
|
// convert to unicode
|
||||||
|
CFStringRef cfString =
|
||||||
|
CFStringCreateWithCStringNoCopy(
|
||||||
|
kCFAllocatorDefault, str, encoding, kCFAllocatorNull);
|
||||||
|
|
||||||
|
// sometimes CFStringCreate...() returns NULL (e.g. Apple Korean
|
||||||
|
// encoding with char value 214). if it did then make no key,
|
||||||
|
// otherwise CFStringCreateMutableCopy() will crash.
|
||||||
|
if (cfString == NULL) {
|
||||||
|
return kKeyNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert to precomposed
|
||||||
|
CFMutableStringRef mcfString =
|
||||||
|
CFStringCreateMutableCopy(kCFAllocatorDefault, 0, cfString);
|
||||||
|
CFRelease(cfString);
|
||||||
|
CFStringNormalize(mcfString, kCFStringNormalizationFormC);
|
||||||
|
|
||||||
|
// check result
|
||||||
|
int unicodeLength = CFStringGetLength(mcfString);
|
||||||
|
if (unicodeLength == 0) {
|
||||||
|
CFRelease(mcfString);
|
||||||
|
return kKeyNone;
|
||||||
|
}
|
||||||
|
if (unicodeLength > 1) {
|
||||||
|
// FIXME -- more than one character, we should handle this
|
||||||
|
CFRelease(mcfString);
|
||||||
|
return kKeyNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get unicode character
|
||||||
|
UniChar uc = CFStringGetCharacterAtIndex(mcfString, 0);
|
||||||
|
CFRelease(mcfString);
|
||||||
|
|
||||||
|
// convert to KeyID
|
||||||
|
return static_cast<KeyID>(uc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyID
|
||||||
|
IKeyResource::unicharToKeyID(UniChar c)
|
||||||
|
{
|
||||||
|
switch (c) {
|
||||||
|
case 3:
|
||||||
|
return kKeyKP_Enter;
|
||||||
|
|
||||||
|
case 8:
|
||||||
|
return kKeyBackSpace;
|
||||||
|
|
||||||
|
case 9:
|
||||||
|
return kKeyTab;
|
||||||
|
|
||||||
|
case 13:
|
||||||
|
return kKeyReturn;
|
||||||
|
|
||||||
|
case 27:
|
||||||
|
return kKeyEscape;
|
||||||
|
|
||||||
|
case 127:
|
||||||
|
return kKeyDelete;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (c < 32) {
|
||||||
|
return kKeyNone;
|
||||||
|
}
|
||||||
|
return static_cast<KeyID>(c);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* synergy -- mouse and keyboard sharing utility
|
||||||
|
* Copyright (C) 2016 Symless Ltd.
|
||||||
|
*
|
||||||
|
* This package is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* found in the file LICENSE that should have accompanied this file.
|
||||||
|
*
|
||||||
|
* This package is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "synergy/KeyState.h"
|
||||||
|
|
||||||
|
class IKeyResource : public IInterface {
|
||||||
|
public:
|
||||||
|
virtual bool isValid() const = 0;
|
||||||
|
virtual UInt32 getNumModifierCombinations() const = 0;
|
||||||
|
virtual UInt32 getNumTables() const = 0;
|
||||||
|
virtual UInt32 getNumButtons() const = 0;
|
||||||
|
virtual UInt32 getTableForModifier(UInt32 mask) const = 0;
|
||||||
|
virtual KeyID getKey(UInt32 table, UInt32 button) const = 0;
|
||||||
|
|
||||||
|
// Convert a character in the current script to the equivalent KeyID
|
||||||
|
static KeyID getKeyID(UInt8);
|
||||||
|
|
||||||
|
// Convert a unicode character to the equivalent KeyID.
|
||||||
|
static KeyID unicharToKeyID(UniChar);
|
||||||
|
};
|
|
@ -17,6 +17,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "platform/OSXKeyState.h"
|
#include "platform/OSXKeyState.h"
|
||||||
|
#include "platform/UchrKeyResource.h"
|
||||||
#include "arch/Arch.h"
|
#include "arch/Arch.h"
|
||||||
#include "base/Log.h"
|
#include "base/Log.h"
|
||||||
|
|
||||||
|
@ -296,7 +297,7 @@ OSXKeyState::mapKeyFromEvent(KeyIDs& ids,
|
||||||
if (count != 0 || m_deadKeyState == 0) {
|
if (count != 0 || m_deadKeyState == 0) {
|
||||||
m_deadKeyState = 0;
|
m_deadKeyState = 0;
|
||||||
for (UniCharCount i = 0; i < count; ++i) {
|
for (UniCharCount i = 0; i < count; ++i) {
|
||||||
ids.push_back(KeyResource::unicharToKeyID(chars[i]));
|
ids.push_back(IKeyResource::unicharToKeyID(chars[i]));
|
||||||
}
|
}
|
||||||
adjustAltGrModifier(ids, maskOut, isCommand);
|
adjustAltGrModifier(ids, maskOut, isCommand);
|
||||||
return mapVirtualKeyToKeyButton(vkCode);
|
return mapVirtualKeyToKeyButton(vkCode);
|
||||||
|
@ -576,7 +577,7 @@ OSXKeyState::getKeyMapForSpecialKeys(synergy::KeyMap& keyMap, SInt32 group) cons
|
||||||
|
|
||||||
bool
|
bool
|
||||||
OSXKeyState::getKeyMap(synergy::KeyMap& keyMap,
|
OSXKeyState::getKeyMap(synergy::KeyMap& keyMap,
|
||||||
SInt32 group, const KeyResource& r) const
|
SInt32 group, const IKeyResource& r) const
|
||||||
{
|
{
|
||||||
if (!r.isValid()) {
|
if (!r.isValid()) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -850,454 +851,3 @@ OSXKeyState::mapKeyButtonToVirtualKey(KeyButton keyButton)
|
||||||
{
|
{
|
||||||
return static_cast<UInt32>(keyButton - KeyButtonOffset);
|
return static_cast<UInt32>(keyButton - KeyButtonOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// OSXKeyState::KeyResource
|
|
||||||
//
|
|
||||||
|
|
||||||
KeyID
|
|
||||||
OSXKeyState::KeyResource::getKeyID(UInt8 c)
|
|
||||||
{
|
|
||||||
if (c == 0) {
|
|
||||||
return kKeyNone;
|
|
||||||
}
|
|
||||||
else if (c >= 32 && c < 127) {
|
|
||||||
// ASCII
|
|
||||||
return static_cast<KeyID>(c);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// handle special keys
|
|
||||||
switch (c) {
|
|
||||||
case 0x01:
|
|
||||||
return kKeyHome;
|
|
||||||
|
|
||||||
case 0x02:
|
|
||||||
return kKeyKP_Enter;
|
|
||||||
|
|
||||||
case 0x03:
|
|
||||||
return kKeyKP_Enter;
|
|
||||||
|
|
||||||
case 0x04:
|
|
||||||
return kKeyEnd;
|
|
||||||
|
|
||||||
case 0x05:
|
|
||||||
return kKeyHelp;
|
|
||||||
|
|
||||||
case 0x08:
|
|
||||||
return kKeyBackSpace;
|
|
||||||
|
|
||||||
case 0x09:
|
|
||||||
return kKeyTab;
|
|
||||||
|
|
||||||
case 0x0b:
|
|
||||||
return kKeyPageUp;
|
|
||||||
|
|
||||||
case 0x0c:
|
|
||||||
return kKeyPageDown;
|
|
||||||
|
|
||||||
case 0x0d:
|
|
||||||
return kKeyReturn;
|
|
||||||
|
|
||||||
case 0x10:
|
|
||||||
// OS X maps all the function keys (F1, etc) to this one key.
|
|
||||||
// we can't determine the right key here so we have to do it
|
|
||||||
// some other way.
|
|
||||||
return kKeyNone;
|
|
||||||
|
|
||||||
case 0x1b:
|
|
||||||
return kKeyEscape;
|
|
||||||
|
|
||||||
case 0x1c:
|
|
||||||
return kKeyLeft;
|
|
||||||
|
|
||||||
case 0x1d:
|
|
||||||
return kKeyRight;
|
|
||||||
|
|
||||||
case 0x1e:
|
|
||||||
return kKeyUp;
|
|
||||||
|
|
||||||
case 0x1f:
|
|
||||||
return kKeyDown;
|
|
||||||
|
|
||||||
case 0x7f:
|
|
||||||
return kKeyDelete;
|
|
||||||
|
|
||||||
case 0x06:
|
|
||||||
case 0x07:
|
|
||||||
case 0x0a:
|
|
||||||
case 0x0e:
|
|
||||||
case 0x0f:
|
|
||||||
case 0x11:
|
|
||||||
case 0x12:
|
|
||||||
case 0x13:
|
|
||||||
case 0x14:
|
|
||||||
case 0x15:
|
|
||||||
case 0x16:
|
|
||||||
case 0x17:
|
|
||||||
case 0x18:
|
|
||||||
case 0x19:
|
|
||||||
case 0x1a:
|
|
||||||
// discard other control characters
|
|
||||||
return kKeyNone;
|
|
||||||
|
|
||||||
default:
|
|
||||||
// not special or unknown
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// create string with character
|
|
||||||
char str[2];
|
|
||||||
str[0] = static_cast<char>(c);
|
|
||||||
str[1] = 0;
|
|
||||||
|
|
||||||
// get current keyboard script
|
|
||||||
TISInputSourceRef isref = TISCopyCurrentKeyboardInputSource();
|
|
||||||
CFArrayRef langs = (CFArrayRef) TISGetInputSourceProperty(isref, kTISPropertyInputSourceLanguages);
|
|
||||||
CFStringEncoding encoding = CFStringConvertIANACharSetNameToEncoding(
|
|
||||||
(CFStringRef)CFArrayGetValueAtIndex(langs, 0));
|
|
||||||
// convert to unicode
|
|
||||||
CFStringRef cfString =
|
|
||||||
CFStringCreateWithCStringNoCopy(
|
|
||||||
kCFAllocatorDefault, str, encoding, kCFAllocatorNull);
|
|
||||||
|
|
||||||
// sometimes CFStringCreate...() returns NULL (e.g. Apple Korean
|
|
||||||
// encoding with char value 214). if it did then make no key,
|
|
||||||
// otherwise CFStringCreateMutableCopy() will crash.
|
|
||||||
if (cfString == NULL) {
|
|
||||||
return kKeyNone;
|
|
||||||
}
|
|
||||||
|
|
||||||
// convert to precomposed
|
|
||||||
CFMutableStringRef mcfString =
|
|
||||||
CFStringCreateMutableCopy(kCFAllocatorDefault, 0, cfString);
|
|
||||||
CFRelease(cfString);
|
|
||||||
CFStringNormalize(mcfString, kCFStringNormalizationFormC);
|
|
||||||
|
|
||||||
// check result
|
|
||||||
int unicodeLength = CFStringGetLength(mcfString);
|
|
||||||
if (unicodeLength == 0) {
|
|
||||||
CFRelease(mcfString);
|
|
||||||
return kKeyNone;
|
|
||||||
}
|
|
||||||
if (unicodeLength > 1) {
|
|
||||||
// FIXME -- more than one character, we should handle this
|
|
||||||
CFRelease(mcfString);
|
|
||||||
return kKeyNone;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get unicode character
|
|
||||||
UniChar uc = CFStringGetCharacterAtIndex(mcfString, 0);
|
|
||||||
CFRelease(mcfString);
|
|
||||||
|
|
||||||
// convert to KeyID
|
|
||||||
return static_cast<KeyID>(uc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
KeyID
|
|
||||||
OSXKeyState::KeyResource::unicharToKeyID(UniChar c)
|
|
||||||
{
|
|
||||||
switch (c) {
|
|
||||||
case 3:
|
|
||||||
return kKeyKP_Enter;
|
|
||||||
|
|
||||||
case 8:
|
|
||||||
return kKeyBackSpace;
|
|
||||||
|
|
||||||
case 9:
|
|
||||||
return kKeyTab;
|
|
||||||
|
|
||||||
case 13:
|
|
||||||
return kKeyReturn;
|
|
||||||
|
|
||||||
case 27:
|
|
||||||
return kKeyEscape;
|
|
||||||
|
|
||||||
case 127:
|
|
||||||
return kKeyDelete;
|
|
||||||
|
|
||||||
default:
|
|
||||||
if (c < 32) {
|
|
||||||
return kKeyNone;
|
|
||||||
}
|
|
||||||
return static_cast<KeyID>(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// OSXKeyState::UchrKeyResource
|
|
||||||
//
|
|
||||||
|
|
||||||
OSXKeyState::UchrKeyResource::UchrKeyResource(const void* resource,
|
|
||||||
UInt32 keyboardType) :
|
|
||||||
m_m(NULL),
|
|
||||||
m_cti(NULL),
|
|
||||||
m_sdi(NULL),
|
|
||||||
m_sri(NULL),
|
|
||||||
m_st(NULL)
|
|
||||||
{
|
|
||||||
m_resource = reinterpret_cast<const UCKeyboardLayout*>(resource);
|
|
||||||
if (m_resource == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// find the keyboard info for the current keyboard type
|
|
||||||
const UCKeyboardTypeHeader* th = NULL;
|
|
||||||
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 == NULL) {
|
|
||||||
// cannot find a suitable keyboard type
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get tables for keyboard type
|
|
||||||
const UInt8* base = reinterpret_cast<const UInt8*>(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 table = getTableForModifier(0);
|
|
||||||
for (UInt32 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
|
|
||||||
OSXKeyState::UchrKeyResource::isValid() const
|
|
||||||
{
|
|
||||||
return (m_m != NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
UInt32
|
|
||||||
OSXKeyState::UchrKeyResource::getNumModifierCombinations() const
|
|
||||||
{
|
|
||||||
// only 32 (not 256) because the righthanded modifier bits are ignored
|
|
||||||
return 32;
|
|
||||||
}
|
|
||||||
|
|
||||||
UInt32
|
|
||||||
OSXKeyState::UchrKeyResource::getNumTables() const
|
|
||||||
{
|
|
||||||
return m_cti->keyToCharTableCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
UInt32
|
|
||||||
OSXKeyState::UchrKeyResource::getNumButtons() const
|
|
||||||
{
|
|
||||||
return m_cti->keyToCharTableSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
UInt32
|
|
||||||
OSXKeyState::UchrKeyResource::getTableForModifier(UInt32 mask) const
|
|
||||||
{
|
|
||||||
if (mask >= m_m->modifiersCount) {
|
|
||||||
return m_m->defaultTableNum;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return m_m->tableNum[mask];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
KeyID
|
|
||||||
OSXKeyState::UchrKeyResource::getKey(UInt32 table, UInt32 button) const
|
|
||||||
{
|
|
||||||
assert(table < getNumTables());
|
|
||||||
assert(button < getNumButtons());
|
|
||||||
|
|
||||||
const UInt8* base = reinterpret_cast<const UInt8*>(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
|
|
||||||
OSXKeyState::UchrKeyResource::getDeadKey(
|
|
||||||
KeySequence& keys, UInt16 index) const
|
|
||||||
{
|
|
||||||
if (m_sri == NULL || index >= m_sri->keyStateRecordCount) {
|
|
||||||
// XXX -- should we be using some other fallback?
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
UInt16 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 = synergy::KeyMap::getDeadKey(*i);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
OSXKeyState::UchrKeyResource::getKeyRecord(
|
|
||||||
KeySequence& keys, UInt16 index, UInt16& state) const
|
|
||||||
{
|
|
||||||
const UInt8* base = reinterpret_cast<const UInt8*>(m_resource);
|
|
||||||
const UCKeyStateRecord* sr =
|
|
||||||
reinterpret_cast<const UCKeyStateRecord*>(base +
|
|
||||||
m_sri->keyStateRecordOffsets[index]);
|
|
||||||
const UCKeyStateEntryTerminal* kset =
|
|
||||||
reinterpret_cast<const UCKeyStateEntryTerminal*>(sr->stateEntryData);
|
|
||||||
|
|
||||||
UInt16 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 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 != NULL && 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
|
|
||||||
OSXKeyState::UchrKeyResource::addSequence(
|
|
||||||
KeySequence& keys, UCKeyCharSeq c) const
|
|
||||||
{
|
|
||||||
if ((c & kUCKeyOutputTestForIndexMask) == kUCKeyOutputSequenceIndexMask) {
|
|
||||||
UInt16 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;
|
|
||||||
}
|
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <Carbon/Carbon.h>
|
#include <Carbon/Carbon.h>
|
||||||
|
|
||||||
typedef TISInputSourceRef KeyLayout;
|
typedef TISInputSourceRef KeyLayout;
|
||||||
|
class IKeyResource;
|
||||||
|
|
||||||
//! OS X key state
|
//! OS X key state
|
||||||
/*!
|
/*!
|
||||||
|
@ -112,7 +113,7 @@ private:
|
||||||
|
|
||||||
// Convert keyboard resource to a key map
|
// Convert keyboard resource to a key map
|
||||||
bool getKeyMap(synergy::KeyMap& keyMap,
|
bool getKeyMap(synergy::KeyMap& keyMap,
|
||||||
SInt32 group, const KeyResource& r) const;
|
SInt32 group, const IKeyResource& r) const;
|
||||||
|
|
||||||
// Get the available keyboard groups
|
// Get the available keyboard groups
|
||||||
bool getGroups(GroupList&) const;
|
bool getGroups(GroupList&) const;
|
||||||
|
@ -149,53 +150,6 @@ private:
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class KeyResource : public IInterface {
|
|
||||||
public:
|
|
||||||
virtual bool isValid() const = 0;
|
|
||||||
virtual UInt32 getNumModifierCombinations() const = 0;
|
|
||||||
virtual UInt32 getNumTables() const = 0;
|
|
||||||
virtual UInt32 getNumButtons() const = 0;
|
|
||||||
virtual UInt32 getTableForModifier(UInt32 mask) const = 0;
|
|
||||||
virtual KeyID getKey(UInt32 table, UInt32 button) const = 0;
|
|
||||||
|
|
||||||
// Convert a character in the current script to the equivalent KeyID
|
|
||||||
static KeyID getKeyID(UInt8);
|
|
||||||
|
|
||||||
// Convert a unicode character to the equivalent KeyID.
|
|
||||||
static KeyID unicharToKeyID(UniChar);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class UchrKeyResource : public KeyResource {
|
|
||||||
public:
|
|
||||||
UchrKeyResource(const void*, UInt32 keyboardType);
|
|
||||||
|
|
||||||
// KeyResource overrides
|
|
||||||
virtual bool isValid() const;
|
|
||||||
virtual UInt32 getNumModifierCombinations() const;
|
|
||||||
virtual UInt32 getNumTables() const;
|
|
||||||
virtual UInt32 getNumButtons() const;
|
|
||||||
virtual UInt32 getTableForModifier(UInt32 mask) const;
|
|
||||||
virtual KeyID getKey(UInt32 table, UInt32 button) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
typedef std::vector<KeyID> KeySequence;
|
|
||||||
|
|
||||||
bool getDeadKey(KeySequence& keys, UInt16 index) const;
|
|
||||||
bool getKeyRecord(KeySequence& keys,
|
|
||||||
UInt16 index, UInt16& 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 m_spaceOutput;
|
|
||||||
};
|
|
||||||
|
|
||||||
// OS X uses a physical key if 0 for the 'A' key. synergy reserves
|
// OS X uses a physical key if 0 for the 'A' key. synergy reserves
|
||||||
// KeyButton 0 so we offset all OS X physical key ids by this much
|
// KeyButton 0 so we offset all OS X physical key ids by this much
|
||||||
// when used as a KeyButton and by minus this much to map a KeyButton
|
// when used as a KeyButton and by minus this much to map a KeyButton
|
||||||
|
|
|
@ -0,0 +1,296 @@
|
||||||
|
/*
|
||||||
|
* synergy -- mouse and keyboard sharing utility
|
||||||
|
* Copyright (C) 2016 Symless Ltd.
|
||||||
|
*
|
||||||
|
* This package is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* found in the file LICENSE that should have accompanied this file.
|
||||||
|
*
|
||||||
|
* This package is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "platform/UchrKeyResource.h"
|
||||||
|
|
||||||
|
#include <Carbon/Carbon.h>
|
||||||
|
|
||||||
|
//
|
||||||
|
// OSXKeyState::UchrKeyResource
|
||||||
|
//
|
||||||
|
|
||||||
|
UchrKeyResource::UchrKeyResource(const void* resource,
|
||||||
|
UInt32 keyboardType) :
|
||||||
|
m_m(NULL),
|
||||||
|
m_cti(NULL),
|
||||||
|
m_sdi(NULL),
|
||||||
|
m_sri(NULL),
|
||||||
|
m_st(NULL)
|
||||||
|
{
|
||||||
|
m_resource = reinterpret_cast<const UCKeyboardLayout*>(resource);
|
||||||
|
if (m_resource == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// find the keyboard info for the current keyboard type
|
||||||
|
const UCKeyboardTypeHeader* th = NULL;
|
||||||
|
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 == NULL) {
|
||||||
|
// cannot find a suitable keyboard type
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get tables for keyboard type
|
||||||
|
const UInt8* base = reinterpret_cast<const UInt8*>(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 table = getTableForModifier(0);
|
||||||
|
for (UInt32 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
|
||||||
|
UchrKeyResource::isValid() const
|
||||||
|
{
|
||||||
|
return (m_m != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt32
|
||||||
|
UchrKeyResource::getNumModifierCombinations() const
|
||||||
|
{
|
||||||
|
// only 32 (not 256) because the righthanded modifier bits are ignored
|
||||||
|
return 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt32
|
||||||
|
UchrKeyResource::getNumTables() const
|
||||||
|
{
|
||||||
|
return m_cti->keyToCharTableCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt32
|
||||||
|
UchrKeyResource::getNumButtons() const
|
||||||
|
{
|
||||||
|
return m_cti->keyToCharTableSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt32
|
||||||
|
UchrKeyResource::getTableForModifier(UInt32 mask) const
|
||||||
|
{
|
||||||
|
if (mask >= m_m->modifiersCount) {
|
||||||
|
return m_m->defaultTableNum;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return m_m->tableNum[mask];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyID
|
||||||
|
UchrKeyResource::getKey(UInt32 table, UInt32 button) const
|
||||||
|
{
|
||||||
|
assert(table < getNumTables());
|
||||||
|
assert(button < getNumButtons());
|
||||||
|
|
||||||
|
const UInt8* base = reinterpret_cast<const UInt8*>(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
|
||||||
|
UchrKeyResource::getDeadKey(
|
||||||
|
KeySequence& keys, UInt16 index) const
|
||||||
|
{
|
||||||
|
if (m_sri == NULL || index >= m_sri->keyStateRecordCount) {
|
||||||
|
// XXX -- should we be using some other fallback?
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt16 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 = synergy::KeyMap::getDeadKey(*i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
UchrKeyResource::getKeyRecord(
|
||||||
|
KeySequence& keys, UInt16 index, UInt16& state) const
|
||||||
|
{
|
||||||
|
const UInt8* base = reinterpret_cast<const UInt8*>(m_resource);
|
||||||
|
const UCKeyStateRecord* sr =
|
||||||
|
reinterpret_cast<const UCKeyStateRecord*>(base +
|
||||||
|
m_sri->keyStateRecordOffsets[index]);
|
||||||
|
const UCKeyStateEntryTerminal* kset =
|
||||||
|
reinterpret_cast<const UCKeyStateEntryTerminal*>(sr->stateEntryData);
|
||||||
|
|
||||||
|
UInt16 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 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 != NULL && 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
|
||||||
|
UchrKeyResource::addSequence(
|
||||||
|
KeySequence& keys, UCKeyCharSeq c) const
|
||||||
|
{
|
||||||
|
if ((c & kUCKeyOutputTestForIndexMask) == kUCKeyOutputSequenceIndexMask) {
|
||||||
|
UInt16 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;
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* synergy -- mouse and keyboard sharing utility
|
||||||
|
* Copyright (C) 2016 Symless Ltd.
|
||||||
|
*
|
||||||
|
* This package is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* found in the file LICENSE that should have accompanied this file.
|
||||||
|
*
|
||||||
|
* This package is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "synergy/KeyState.h"
|
||||||
|
#include "platform/IKeyResource.h"
|
||||||
|
|
||||||
|
#include <Carbon/Carbon.h>
|
||||||
|
|
||||||
|
typedef TISInputSourceRef KeyLayout;
|
||||||
|
|
||||||
|
class UchrKeyResource : public IKeyResource {
|
||||||
|
public:
|
||||||
|
UchrKeyResource(const void*, UInt32 keyboardType);
|
||||||
|
|
||||||
|
// KeyResource overrides
|
||||||
|
virtual bool isValid() const;
|
||||||
|
virtual UInt32 getNumModifierCombinations() const;
|
||||||
|
virtual UInt32 getNumTables() const;
|
||||||
|
virtual UInt32 getNumButtons() const;
|
||||||
|
virtual UInt32 getTableForModifier(UInt32 mask) const;
|
||||||
|
virtual KeyID getKey(UInt32 table, UInt32 button) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef std::vector<KeyID> KeySequence;
|
||||||
|
|
||||||
|
bool getDeadKey(KeySequence& keys, UInt16 index) const;
|
||||||
|
bool getKeyRecord(KeySequence& keys,
|
||||||
|
UInt16 index, UInt16& 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 m_spaceOutput;
|
||||||
|
};
|
Loading…
Reference in New Issue