Changes to support remapping modifier keys on clients.

This commit is contained in:
crs 2003-02-22 15:03:31 +00:00
parent dce445a83a
commit 5f164375d4
6 changed files with 278 additions and 13 deletions

View File

@ -39,6 +39,10 @@ CServerProxy::CServerProxy(IClient* client,
assert(m_client != NULL); assert(m_client != NULL);
assert(m_input != NULL); assert(m_input != NULL);
assert(m_output != NULL); assert(m_output != NULL);
// initialize modifier translation table
for (KeyModifierID id = 0; id < kKeyModifierIDLast; ++id)
m_modifierTranslationTable[id] = id;
} }
CServerProxy::~CServerProxy() CServerProxy::~CServerProxy()
@ -313,6 +317,110 @@ CServerProxy::sendInfo(const CClientInfo& info)
info.m_mx, info.m_my); 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 void
CServerProxy::enter() CServerProxy::enter()
{ {
@ -397,9 +505,16 @@ CServerProxy::keyDown()
CProtocolUtil::readf(getInputStream(), kMsgDKeyDown + 4, &id, &mask); CProtocolUtil::readf(getInputStream(), kMsgDKeyDown + 4, &id, &mask);
LOG((CLOG_DEBUG1 "recv key down id=%d, mask=0x%04x", id, mask)); LOG((CLOG_DEBUG1 "recv key down id=%d, mask=0x%04x", id, mask));
// forward // translate
getClient()->keyDown(static_cast<KeyID>(id), KeyID id2 = translateKey(static_cast<KeyID>(id));
KeyModifierMask mask2 = translateModifierMask(
static_cast<KeyModifierMask>(mask)); 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 void
@ -414,10 +529,16 @@ CServerProxy::keyRepeat()
kMsgDKeyRepeat + 4, &id, &mask, &count); kMsgDKeyRepeat + 4, &id, &mask, &count);
LOG((CLOG_DEBUG1 "recv key repeat id=%d, mask=0x%04x, count=%d", 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 // forward
getClient()->keyRepeat(static_cast<KeyID>(id), getClient()->keyRepeat(id2, mask2, count);
static_cast<KeyModifierMask>(mask),
count);
} }
void void
@ -431,9 +552,16 @@ CServerProxy::keyUp()
CProtocolUtil::readf(getInputStream(), kMsgDKeyUp + 4, &id, &mask); CProtocolUtil::readf(getInputStream(), kMsgDKeyUp + 4, &id, &mask);
LOG((CLOG_DEBUG1 "recv key up id=%d, mask=0x%04x", id, mask)); LOG((CLOG_DEBUG1 "recv key up id=%d, mask=0x%04x", id, mask));
// forward // translate
getClient()->keyUp(static_cast<KeyID>(id), KeyID id2 = translateKey(static_cast<KeyID>(id));
KeyModifierMask mask2 = translateModifierMask(
static_cast<KeyModifierMask>(mask)); 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 void
@ -534,6 +662,10 @@ CServerProxy::resetOptions()
// forward // forward
getClient()->resetOptions(); getClient()->resetOptions();
// reset modifier translation table
for (KeyModifierID id = 0; id < kKeyModifierIDLast; ++id)
m_modifierTranslationTable[id] = id;
} }
void void
@ -546,6 +678,31 @@ CServerProxy::setOptions()
// forward // forward
getClient()->setOptions(options); 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 void

View File

@ -16,6 +16,7 @@
#define CSERVERPROXY_H #define CSERVERPROXY_H
#include "IScreenReceiver.h" #include "IScreenReceiver.h"
#include "KeyTypes.h"
#include "CMutex.h" #include "CMutex.h"
class IClient; class IClient;
@ -92,6 +93,10 @@ private:
void sendInfo(const CClientInfo&); void sendInfo(const CClientInfo&);
// modifier key translation
KeyID translateKey(KeyID) const;
KeyModifierMask translateModifierMask(KeyModifierMask) const;
// message handlers // message handlers
void enter(); void enter();
void leave(); void leave();
@ -123,6 +128,8 @@ private:
SInt32 m_xMouse, m_yMouse; SInt32 m_xMouse, m_yMouse;
bool m_ignoreMouse; bool m_ignoreMouse;
KeyModifierID m_modifierTranslationTable[kKeyModifierIDLast];
}; };
#endif #endif

View File

@ -13,7 +13,7 @@
*/ */
#include "CConfig.h" #include "CConfig.h"
#include "ProtocolTypes.h" #include "KeyTypes.h"
#include "XSocket.h" #include "XSocket.h"
#include "stdistream.h" #include "stdistream.h"
#include "stdostream.h" #include "stdostream.h"
@ -514,6 +514,24 @@ CConfig::parseBoolean(const CString& arg)
throw XConfigRead("invalid argument"); 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* const char*
CConfig::getOptionName(OptionID id) CConfig::getOptionName(OptionID id)
{ {
@ -523,6 +541,21 @@ CConfig::getOptionName(OptionID id)
if (id == kOptionHalfDuplexNumLock) { if (id == kOptionHalfDuplexNumLock) {
return "halfDuplexNumLock"; 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; return NULL;
} }
@ -533,6 +566,31 @@ CConfig::getOptionValue(OptionID id, OptionValue value)
id == kOptionHalfDuplexNumLock) { id == kOptionHalfDuplexNumLock) {
return (value != 0) ? "true" : "false"; 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 ""; return "";
} }
@ -700,6 +758,26 @@ CConfig::readSectionScreens(std::istream& s)
addOption(screen, kOptionHalfDuplexNumLock, addOption(screen, kOptionHalfDuplexNumLock,
parseBoolean(value)); 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 { else {
// unknown argument // unknown argument
throw XConfigRead("unknown argument"); throw XConfigRead("unknown argument");

View File

@ -293,6 +293,7 @@ public:
private: private:
static bool readLine(std::istream&, CString&); static bool readLine(std::istream&, CString&);
static bool parseBoolean(const CString&); static bool parseBoolean(const CString&);
static OptionValue parseModifierKey(const CString&);
static const char* getOptionName(OptionID); static const char* getOptionName(OptionID);
static const char* getOptionValue(OptionID, OptionValue); static const char* getOptionValue(OptionID, OptionValue);
void readSection(std::istream&); void readSection(std::istream&);

View File

@ -25,13 +25,19 @@ keys, function keys, modifier keys, etc).
*/ */
typedef UInt32 KeyID; typedef UInt32 KeyID;
//! Modifier key ID //! Modifier key mask
/*! /*!
Type to hold a bitmask of key modifiers (e.g. shift keys). Type to hold a bitmask of key modifiers (e.g. shift keys).
*/ */
typedef UInt32 KeyModifierMask; 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 KeyModifierShift = 0x0001;
static const KeyModifierMask KeyModifierControl = 0x0002; static const KeyModifierMask KeyModifierControl = 0x0002;
@ -44,6 +50,17 @@ static const KeyModifierMask KeyModifierNumLock = 0x2000;
static const KeyModifierMask KeyModifierScrollLock = 0x4000; 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 //! @name Key identifiers
//@{ //@{
// all identifiers except kKeyNone are equal to the corresponding // all identifiers except kKeyNone are equal to the corresponding

View File

@ -42,9 +42,14 @@ typedef std::vector<UInt32> COptionsList;
//! @name Option identifiers //! @name Option identifiers
//@{ //@{
static const OptionID kOptionHalfDuplexCapsLock = OPTION_CODE("HDCL"); static const OptionID kOptionHalfDuplexCapsLock = OPTION_CODE("HDCL");
static const OptionID kOptionHalfDuplexNumLock = OPTION_CODE("HDNL"); static const OptionID kOptionHalfDuplexNumLock = OPTION_CODE("HDNL");
static const OptionID kOptionHalfDuplexScrollLock = OPTION_CODE("HDSL"); 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 #undef OPTION_CODE