Changes to support remapping modifier keys on clients.
This commit is contained in:
parent
dce445a83a
commit
5f164375d4
|
@ -39,6 +39,10 @@ CServerProxy::CServerProxy(IClient* client,
|
|||
assert(m_client != NULL);
|
||||
assert(m_input != NULL);
|
||||
assert(m_output != NULL);
|
||||
|
||||
// initialize modifier translation table
|
||||
for (KeyModifierID id = 0; id < kKeyModifierIDLast; ++id)
|
||||
m_modifierTranslationTable[id] = id;
|
||||
}
|
||||
|
||||
CServerProxy::~CServerProxy()
|
||||
|
@ -313,6 +317,110 @@ CServerProxy::sendInfo(const CClientInfo& info)
|
|||
info.m_mx, info.m_my);
|
||||
}
|
||||
|
||||
KeyID
|
||||
CServerProxy::translateKey(KeyID id) const
|
||||
{
|
||||
static const KeyID s_translationTable[kKeyModifierIDLast][2] = {
|
||||
{ kKeyNone, kKeyNone },
|
||||
{ kKeyShift_L, kKeyShift_R },
|
||||
{ kKeyControl_L, kKeyControl_R },
|
||||
{ kKeyAlt_L, kKeyAlt_R },
|
||||
{ kKeyMeta_L, kKeyMeta_R },
|
||||
{ kKeySuper_L, kKeySuper_R }
|
||||
};
|
||||
|
||||
KeyModifierID id2 = kKeyModifierIDNull;
|
||||
UInt32 side = 0;
|
||||
switch (id) {
|
||||
case kKeyShift_L:
|
||||
id2 = kKeyModifierIDShift;
|
||||
side = 0;
|
||||
break;
|
||||
|
||||
case kKeyShift_R:
|
||||
id2 = kKeyModifierIDShift;
|
||||
side = 1;
|
||||
break;
|
||||
|
||||
case kKeyControl_L:
|
||||
id2 = kKeyModifierIDControl;
|
||||
side = 0;
|
||||
break;
|
||||
|
||||
case kKeyControl_R:
|
||||
id2 = kKeyModifierIDControl;
|
||||
side = 1;
|
||||
break;
|
||||
|
||||
case kKeyAlt_L:
|
||||
id2 = kKeyModifierIDAlt;
|
||||
side = 0;
|
||||
break;
|
||||
|
||||
case kKeyAlt_R:
|
||||
id2 = kKeyModifierIDAlt;
|
||||
side = 1;
|
||||
break;
|
||||
|
||||
case kKeyMeta_L:
|
||||
id2 = kKeyModifierIDMeta;
|
||||
side = 0;
|
||||
break;
|
||||
|
||||
case kKeyMeta_R:
|
||||
id2 = kKeyModifierIDMeta;
|
||||
side = 1;
|
||||
break;
|
||||
|
||||
case kKeySuper_L:
|
||||
id2 = kKeyModifierIDSuper;
|
||||
side = 0;
|
||||
break;
|
||||
|
||||
case kKeySuper_R:
|
||||
id2 = kKeyModifierIDSuper;
|
||||
side = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (id2 != kKeyModifierIDNull) {
|
||||
return s_translationTable[m_modifierTranslationTable[id2]][side];
|
||||
}
|
||||
else {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
KeyModifierMask
|
||||
CServerProxy::translateModifierMask(KeyModifierMask mask) const
|
||||
{
|
||||
static const KeyModifierMask s_masks[kKeyModifierIDLast] = {
|
||||
0x0000,
|
||||
KeyModifierShift,
|
||||
KeyModifierControl,
|
||||
KeyModifierAlt,
|
||||
KeyModifierMeta,
|
||||
KeyModifierSuper
|
||||
};
|
||||
|
||||
KeyModifierMask newMask = 0;
|
||||
if ((mask & KeyModifierShift) != 0) {
|
||||
newMask |= s_masks[m_modifierTranslationTable[kKeyModifierIDShift]];
|
||||
}
|
||||
if ((mask & KeyModifierControl) != 0) {
|
||||
newMask |= s_masks[m_modifierTranslationTable[kKeyModifierIDControl]];
|
||||
}
|
||||
if ((mask & KeyModifierAlt) != 0) {
|
||||
newMask |= s_masks[m_modifierTranslationTable[kKeyModifierIDAlt]];
|
||||
}
|
||||
if ((mask & KeyModifierMeta) != 0) {
|
||||
newMask |= s_masks[m_modifierTranslationTable[kKeyModifierIDMeta]];
|
||||
}
|
||||
if ((mask & KeyModifierSuper) != 0) {
|
||||
newMask |= s_masks[m_modifierTranslationTable[kKeyModifierIDSuper]];
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CServerProxy::enter()
|
||||
{
|
||||
|
@ -397,9 +505,16 @@ CServerProxy::keyDown()
|
|||
CProtocolUtil::readf(getInputStream(), kMsgDKeyDown + 4, &id, &mask);
|
||||
LOG((CLOG_DEBUG1 "recv key down id=%d, mask=0x%04x", id, mask));
|
||||
|
||||
// forward
|
||||
getClient()->keyDown(static_cast<KeyID>(id),
|
||||
// translate
|
||||
KeyID id2 = translateKey(static_cast<KeyID>(id));
|
||||
KeyModifierMask mask2 = translateModifierMask(
|
||||
static_cast<KeyModifierMask>(mask));
|
||||
if (id2 != static_cast<KeyID>(id) ||
|
||||
mask2 != static_cast<KeyModifierMask>(mask))
|
||||
LOG((CLOG_DEBUG1 "key down translated to id=%d, mask=0x%04x", id2, mask2));
|
||||
|
||||
// forward
|
||||
getClient()->keyDown(id2, mask2);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -414,10 +529,16 @@ CServerProxy::keyRepeat()
|
|||
kMsgDKeyRepeat + 4, &id, &mask, &count);
|
||||
LOG((CLOG_DEBUG1 "recv key repeat id=%d, mask=0x%04x, count=%d", id, mask, count));
|
||||
|
||||
// translate
|
||||
KeyID id2 = translateKey(static_cast<KeyID>(id));
|
||||
KeyModifierMask mask2 = translateModifierMask(
|
||||
static_cast<KeyModifierMask>(mask));
|
||||
if (id2 != static_cast<KeyID>(id) ||
|
||||
mask2 != static_cast<KeyModifierMask>(mask))
|
||||
LOG((CLOG_DEBUG1 "key down translated to id=%d, mask=0x%04x", id2, mask2));
|
||||
|
||||
// forward
|
||||
getClient()->keyRepeat(static_cast<KeyID>(id),
|
||||
static_cast<KeyModifierMask>(mask),
|
||||
count);
|
||||
getClient()->keyRepeat(id2, mask2, count);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -431,9 +552,16 @@ CServerProxy::keyUp()
|
|||
CProtocolUtil::readf(getInputStream(), kMsgDKeyUp + 4, &id, &mask);
|
||||
LOG((CLOG_DEBUG1 "recv key up id=%d, mask=0x%04x", id, mask));
|
||||
|
||||
// forward
|
||||
getClient()->keyUp(static_cast<KeyID>(id),
|
||||
// translate
|
||||
KeyID id2 = translateKey(static_cast<KeyID>(id));
|
||||
KeyModifierMask mask2 = translateModifierMask(
|
||||
static_cast<KeyModifierMask>(mask));
|
||||
if (id2 != static_cast<KeyID>(id) ||
|
||||
mask2 != static_cast<KeyModifierMask>(mask))
|
||||
LOG((CLOG_DEBUG1 "key down translated to id=%d, mask=0x%04x", id2, mask2));
|
||||
|
||||
// forward
|
||||
getClient()->keyUp(id2, mask2);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -534,6 +662,10 @@ CServerProxy::resetOptions()
|
|||
|
||||
// forward
|
||||
getClient()->resetOptions();
|
||||
|
||||
// reset modifier translation table
|
||||
for (KeyModifierID id = 0; id < kKeyModifierIDLast; ++id)
|
||||
m_modifierTranslationTable[id] = id;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -546,6 +678,31 @@ CServerProxy::setOptions()
|
|||
|
||||
// forward
|
||||
getClient()->setOptions(options);
|
||||
|
||||
// update modifier table
|
||||
for (UInt32 i = 0, n = options.size(); i < n; i += 2) {
|
||||
KeyModifierID id = kKeyModifierIDNull;
|
||||
if (options[i] == kOptionModifierMapForShift) {
|
||||
id = kKeyModifierIDShift;
|
||||
}
|
||||
else if (options[i] == kOptionModifierMapForControl) {
|
||||
id = kKeyModifierIDControl;
|
||||
}
|
||||
else if (options[i] == kOptionModifierMapForAlt) {
|
||||
id = kKeyModifierIDAlt;
|
||||
}
|
||||
else if (options[i] == kOptionModifierMapForMeta) {
|
||||
id = kKeyModifierIDMeta;
|
||||
}
|
||||
else if (options[i] == kOptionModifierMapForSuper) {
|
||||
id = kKeyModifierIDSuper;
|
||||
}
|
||||
if (id != kKeyModifierIDNull) {
|
||||
m_modifierTranslationTable[id] =
|
||||
static_cast<KeyModifierID>(options[i + 1]);
|
||||
LOG((CLOG_DEBUG1 "modifier %d mapped to %d", id, m_modifierTranslationTable[id]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#define CSERVERPROXY_H
|
||||
|
||||
#include "IScreenReceiver.h"
|
||||
#include "KeyTypes.h"
|
||||
#include "CMutex.h"
|
||||
|
||||
class IClient;
|
||||
|
@ -92,6 +93,10 @@ private:
|
|||
|
||||
void sendInfo(const CClientInfo&);
|
||||
|
||||
// modifier key translation
|
||||
KeyID translateKey(KeyID) const;
|
||||
KeyModifierMask translateModifierMask(KeyModifierMask) const;
|
||||
|
||||
// message handlers
|
||||
void enter();
|
||||
void leave();
|
||||
|
@ -123,6 +128,8 @@ private:
|
|||
SInt32 m_xMouse, m_yMouse;
|
||||
|
||||
bool m_ignoreMouse;
|
||||
|
||||
KeyModifierID m_modifierTranslationTable[kKeyModifierIDLast];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
*/
|
||||
|
||||
#include "CConfig.h"
|
||||
#include "ProtocolTypes.h"
|
||||
#include "KeyTypes.h"
|
||||
#include "XSocket.h"
|
||||
#include "stdistream.h"
|
||||
#include "stdostream.h"
|
||||
|
@ -514,6 +514,24 @@ CConfig::parseBoolean(const CString& arg)
|
|||
throw XConfigRead("invalid argument");
|
||||
}
|
||||
|
||||
OptionValue
|
||||
CConfig::parseModifierKey(const CString& arg)
|
||||
{
|
||||
if (CStringUtil::CaselessCmp::equal(arg, "shift"))
|
||||
return static_cast<OptionValue>(kKeyModifierIDShift);
|
||||
if (CStringUtil::CaselessCmp::equal(arg, "ctrl"))
|
||||
return static_cast<OptionValue>(kKeyModifierIDControl);
|
||||
if (CStringUtil::CaselessCmp::equal(arg, "alt"))
|
||||
return static_cast<OptionValue>(kKeyModifierIDAlt);
|
||||
if (CStringUtil::CaselessCmp::equal(arg, "meta"))
|
||||
return static_cast<OptionValue>(kKeyModifierIDMeta);
|
||||
if (CStringUtil::CaselessCmp::equal(arg, "super"))
|
||||
return static_cast<OptionValue>(kKeyModifierIDSuper);
|
||||
if (CStringUtil::CaselessCmp::equal(arg, "none"))
|
||||
return static_cast<OptionValue>(kKeyModifierIDNull);
|
||||
throw XConfigRead("invalid argument");
|
||||
}
|
||||
|
||||
const char*
|
||||
CConfig::getOptionName(OptionID id)
|
||||
{
|
||||
|
@ -523,6 +541,21 @@ CConfig::getOptionName(OptionID id)
|
|||
if (id == kOptionHalfDuplexNumLock) {
|
||||
return "halfDuplexNumLock";
|
||||
}
|
||||
if (id == kOptionModifierMapForShift) {
|
||||
return "shift";
|
||||
}
|
||||
if (id == kOptionModifierMapForControl) {
|
||||
return "ctrl";
|
||||
}
|
||||
if (id == kOptionModifierMapForAlt) {
|
||||
return "alt";
|
||||
}
|
||||
if (id == kOptionModifierMapForMeta) {
|
||||
return "meta";
|
||||
}
|
||||
if (id == kOptionModifierMapForSuper) {
|
||||
return "super";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -533,6 +566,31 @@ CConfig::getOptionValue(OptionID id, OptionValue value)
|
|||
id == kOptionHalfDuplexNumLock) {
|
||||
return (value != 0) ? "true" : "false";
|
||||
}
|
||||
if (id == kOptionModifierMapForShift ||
|
||||
id == kOptionModifierMapForControl ||
|
||||
id == kOptionModifierMapForAlt ||
|
||||
id == kOptionModifierMapForMeta ||
|
||||
id == kOptionModifierMapForSuper) {
|
||||
switch (value) {
|
||||
case kKeyModifierIDShift:
|
||||
return "shift";
|
||||
|
||||
case kKeyModifierIDControl:
|
||||
return "ctrl";
|
||||
|
||||
case kKeyModifierIDAlt:
|
||||
return "alt";
|
||||
|
||||
case kKeyModifierIDMeta:
|
||||
return "meta";
|
||||
|
||||
case kKeyModifierIDSuper:
|
||||
return "super";
|
||||
|
||||
default:
|
||||
return "none";
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
@ -700,6 +758,26 @@ CConfig::readSectionScreens(std::istream& s)
|
|||
addOption(screen, kOptionHalfDuplexNumLock,
|
||||
parseBoolean(value));
|
||||
}
|
||||
else if (name == "shift") {
|
||||
addOption(screen, kOptionModifierMapForShift,
|
||||
parseModifierKey(value));
|
||||
}
|
||||
else if (name == "ctrl") {
|
||||
addOption(screen, kOptionModifierMapForControl,
|
||||
parseModifierKey(value));
|
||||
}
|
||||
else if (name == "alt") {
|
||||
addOption(screen, kOptionModifierMapForAlt,
|
||||
parseModifierKey(value));
|
||||
}
|
||||
else if (name == "meta") {
|
||||
addOption(screen, kOptionModifierMapForMeta,
|
||||
parseModifierKey(value));
|
||||
}
|
||||
else if (name == "super") {
|
||||
addOption(screen, kOptionModifierMapForSuper,
|
||||
parseModifierKey(value));
|
||||
}
|
||||
else {
|
||||
// unknown argument
|
||||
throw XConfigRead("unknown argument");
|
||||
|
|
|
@ -293,6 +293,7 @@ public:
|
|||
private:
|
||||
static bool readLine(std::istream&, CString&);
|
||||
static bool parseBoolean(const CString&);
|
||||
static OptionValue parseModifierKey(const CString&);
|
||||
static const char* getOptionName(OptionID);
|
||||
static const char* getOptionValue(OptionID, OptionValue);
|
||||
void readSection(std::istream&);
|
||||
|
|
|
@ -25,13 +25,19 @@ keys, function keys, modifier keys, etc).
|
|||
*/
|
||||
typedef UInt32 KeyID;
|
||||
|
||||
//! Modifier key ID
|
||||
//! Modifier key mask
|
||||
/*!
|
||||
Type to hold a bitmask of key modifiers (e.g. shift keys).
|
||||
*/
|
||||
typedef UInt32 KeyModifierMask;
|
||||
|
||||
//! @name Modifier key identifiers
|
||||
//! Modifier key ID
|
||||
/*!
|
||||
Type to hold the id of a key modifier (e.g. a shift key).
|
||||
*/
|
||||
typedef UInt32 KeyModifierID;
|
||||
|
||||
//! @name Modifier key masks
|
||||
//@{
|
||||
static const KeyModifierMask KeyModifierShift = 0x0001;
|
||||
static const KeyModifierMask KeyModifierControl = 0x0002;
|
||||
|
@ -44,6 +50,17 @@ static const KeyModifierMask KeyModifierNumLock = 0x2000;
|
|||
static const KeyModifierMask KeyModifierScrollLock = 0x4000;
|
||||
//@}
|
||||
|
||||
//! @name Modifier key identifiers
|
||||
//@{
|
||||
static const KeyModifierID kKeyModifierIDNull = 0;
|
||||
static const KeyModifierID kKeyModifierIDShift = 1;
|
||||
static const KeyModifierID kKeyModifierIDControl = 2;
|
||||
static const KeyModifierID kKeyModifierIDAlt = 3;
|
||||
static const KeyModifierID kKeyModifierIDMeta = 4;
|
||||
static const KeyModifierID kKeyModifierIDSuper = 5;
|
||||
static const KeyModifierID kKeyModifierIDLast = 6;
|
||||
//@}
|
||||
|
||||
//! @name Key identifiers
|
||||
//@{
|
||||
// all identifiers except kKeyNone are equal to the corresponding
|
||||
|
|
|
@ -42,9 +42,14 @@ typedef std::vector<UInt32> COptionsList;
|
|||
|
||||
//! @name Option identifiers
|
||||
//@{
|
||||
static const OptionID kOptionHalfDuplexCapsLock = OPTION_CODE("HDCL");
|
||||
static const OptionID kOptionHalfDuplexNumLock = OPTION_CODE("HDNL");
|
||||
static const OptionID kOptionHalfDuplexScrollLock = OPTION_CODE("HDSL");
|
||||
static const OptionID kOptionHalfDuplexCapsLock = OPTION_CODE("HDCL");
|
||||
static const OptionID kOptionHalfDuplexNumLock = OPTION_CODE("HDNL");
|
||||
static const OptionID kOptionHalfDuplexScrollLock = OPTION_CODE("HDSL");
|
||||
static const OptionID kOptionModifierMapForShift = OPTION_CODE("MMFS");
|
||||
static const OptionID kOptionModifierMapForControl = OPTION_CODE("MMFC");
|
||||
static const OptionID kOptionModifierMapForAlt = OPTION_CODE("MMFA");
|
||||
static const OptionID kOptionModifierMapForMeta = OPTION_CODE("MMFM");
|
||||
static const OptionID kOptionModifierMapForSuper = OPTION_CODE("MMFR");
|
||||
//@}
|
||||
|
||||
#undef OPTION_CODE
|
||||
|
|
Loading…
Reference in New Issue