#6725 allow building of synergy without tests
Signed-off-by: Pieterjan Camerlynck <pieterjan.camerlynck@gmail.com> Signed-off-by: Jamie Newbon <jamie@symless.com>
This commit is contained in:
parent
9f7101139e
commit
16bccc2ed0
4 changed files with 432 additions and 424 deletions
|
|
@ -20,6 +20,7 @@ project (synergy-core C CXX)
|
||||||
option (SYNERGY_BUILD_LEGACY_GUI "Build the legacy GUI" ON)
|
option (SYNERGY_BUILD_LEGACY_GUI "Build the legacy GUI" ON)
|
||||||
option (SYNERGY_BUILD_LEGACY_SERVICE "Build the legacy service (synergyd)" ON)
|
option (SYNERGY_BUILD_LEGACY_SERVICE "Build the legacy service (synergyd)" ON)
|
||||||
option (SYNERGY_BUILD_LEGACY_INSTALLER "Build the legacy installer" ON)
|
option (SYNERGY_BUILD_LEGACY_INSTALLER "Build the legacy installer" ON)
|
||||||
|
option (BUILD_TESTS "Override building of tests" ON)
|
||||||
|
|
||||||
if (DEFINED ENV{SYNERGY_ENTERPRISE})
|
if (DEFINED ENV{SYNERGY_ENTERPRISE})
|
||||||
option (SYNERGY_ENTERPRISE "Build Enterprise" ON)
|
option (SYNERGY_ENTERPRISE "Build Enterprise" ON)
|
||||||
|
|
|
||||||
|
|
@ -23,4 +23,6 @@ if (SYNERGY_BUILD_LEGACY_GUI)
|
||||||
add_subdirectory(gui)
|
add_subdirectory(gui)
|
||||||
endif (SYNERGY_BUILD_LEGACY_GUI)
|
endif (SYNERGY_BUILD_LEGACY_GUI)
|
||||||
|
|
||||||
add_subdirectory(test)
|
if (BUILD_TESTS)
|
||||||
|
add_subdirectory(test)
|
||||||
|
endif()
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,9 @@
|
||||||
#include "common/stdset.h"
|
#include "common/stdset.h"
|
||||||
#include "common/stdvector.h"
|
#include "common/stdvector.h"
|
||||||
|
|
||||||
#include <gtest/gtest_prod.h>
|
#ifdef TEST_ENV
|
||||||
|
#include "gtest/gtest_prod.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace synergy {
|
namespace synergy {
|
||||||
|
|
||||||
|
|
@ -34,479 +36,480 @@ This class provides a keyboard mapping.
|
||||||
*/
|
*/
|
||||||
class KeyMap {
|
class KeyMap {
|
||||||
public:
|
public:
|
||||||
KeyMap();
|
KeyMap();
|
||||||
virtual ~KeyMap();
|
virtual ~KeyMap();
|
||||||
|
|
||||||
//! KeyID synthesis info
|
//! KeyID synthesis info
|
||||||
/*!
|
/*!
|
||||||
This structure contains the information necessary to synthesize a
|
This structure contains the information necessary to synthesize a
|
||||||
keystroke that generates a KeyID (stored elsewhere). \c m_sensitive
|
keystroke that generates a KeyID (stored elsewhere). \c m_sensitive
|
||||||
lists the modifiers that the key is affected by and must therefore
|
lists the modifiers that the key is affected by and must therefore
|
||||||
be in the correct state, which is listed in \c m_required. If the
|
be in the correct state, which is listed in \c m_required. If the
|
||||||
key is mapped to a modifier, that modifier is in \c m_generates and
|
key is mapped to a modifier, that modifier is in \c m_generates and
|
||||||
is not in \c m_sensitive.
|
is not in \c m_sensitive.
|
||||||
*/
|
*/
|
||||||
struct KeyItem {
|
struct KeyItem {
|
||||||
public:
|
public:
|
||||||
KeyID m_id; //!< KeyID
|
KeyID m_id; //!< KeyID
|
||||||
SInt32 m_group; //!< Group for key
|
SInt32 m_group; //!< Group for key
|
||||||
KeyButton m_button; //!< Button to generate KeyID
|
KeyButton m_button; //!< Button to generate KeyID
|
||||||
KeyModifierMask m_required; //!< Modifiers required for KeyID
|
KeyModifierMask m_required; //!< Modifiers required for KeyID
|
||||||
KeyModifierMask m_sensitive; //!< Modifiers key is sensitive to
|
KeyModifierMask m_sensitive; //!< Modifiers key is sensitive to
|
||||||
KeyModifierMask m_generates; //!< Modifiers key is mapped to
|
KeyModifierMask m_generates; //!< Modifiers key is mapped to
|
||||||
bool m_dead; //!< \c true if this is a dead KeyID
|
bool m_dead; //!< \c true if this is a dead KeyID
|
||||||
bool m_lock; //!< \c true if this locks a modifier
|
bool m_lock; //!< \c true if this locks a modifier
|
||||||
UInt32 m_client; //!< Client data
|
UInt32 m_client; //!< Client data
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool operator==(const KeyItem&) const;
|
bool operator==(const KeyItem&) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
//! The KeyButtons needed to synthesize a KeyID
|
//! The KeyButtons needed to synthesize a KeyID
|
||||||
/*!
|
/*!
|
||||||
An ordered list of \c KeyItems produces a particular KeyID. If
|
An ordered list of \c KeyItems produces a particular KeyID. If
|
||||||
the KeyID can be synthesized directly then there is one entry in
|
the KeyID can be synthesized directly then there is one entry in
|
||||||
the list. If dead keys are required then they're listed first.
|
the list. If dead keys are required then they're listed first.
|
||||||
A list is the minimal set of keystrokes necessary to synthesize
|
A list is the minimal set of keystrokes necessary to synthesize
|
||||||
the KeyID, so it doesn't include no-ops. A list does not include
|
the KeyID, so it doesn't include no-ops. A list does not include
|
||||||
any modifier keys unless the KeyID is a modifier, in which case
|
any modifier keys unless the KeyID is a modifier, in which case
|
||||||
it has exactly one KeyItem for the modifier itself.
|
it has exactly one KeyItem for the modifier itself.
|
||||||
*/
|
*/
|
||||||
typedef std::vector<KeyItem> KeyItemList;
|
typedef std::vector<KeyItem> KeyItemList;
|
||||||
|
|
||||||
//! A keystroke
|
//! A keystroke
|
||||||
class Keystroke {
|
class Keystroke {
|
||||||
public:
|
public:
|
||||||
enum EType {
|
enum EType {
|
||||||
kButton, //!< Synthesize button
|
kButton, //!< Synthesize button
|
||||||
kGroup //!< Set new group
|
kGroup //!< Set new group
|
||||||
};
|
};
|
||||||
|
|
||||||
Keystroke(KeyButton, bool press, bool repeat, UInt32 clientData);
|
Keystroke(KeyButton, bool press, bool repeat, UInt32 clientData);
|
||||||
Keystroke(SInt32 group, bool absolute, bool restore);
|
Keystroke(SInt32 group, bool absolute, bool restore);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct Button {
|
struct Button {
|
||||||
public:
|
public:
|
||||||
KeyButton m_button; //!< Button to synthesize
|
KeyButton m_button; //!< Button to synthesize
|
||||||
bool m_press; //!< \c true iff press
|
bool m_press; //!< \c true iff press
|
||||||
bool m_repeat; //!< \c true iff for an autorepeat
|
bool m_repeat; //!< \c true iff for an autorepeat
|
||||||
UInt32 m_client; //!< Client data
|
UInt32 m_client; //!< Client data
|
||||||
};
|
};
|
||||||
struct Group {
|
struct Group {
|
||||||
public:
|
public:
|
||||||
SInt32 m_group; //!< Group/offset to change to/by
|
SInt32 m_group; //!< Group/offset to change to/by
|
||||||
bool m_absolute; //!< \c true iff change to, else by
|
bool m_absolute; //!< \c true iff change to, else by
|
||||||
bool m_restore; //!< \c true iff for restoring state
|
bool m_restore; //!< \c true iff for restoring state
|
||||||
};
|
};
|
||||||
union Data {
|
union Data {
|
||||||
public:
|
public:
|
||||||
Button m_button;
|
Button m_button;
|
||||||
Group m_group;
|
Group m_group;
|
||||||
};
|
};
|
||||||
|
|
||||||
EType m_type;
|
EType m_type;
|
||||||
Data m_data;
|
Data m_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
//! A sequence of keystrokes
|
//! A sequence of keystrokes
|
||||||
typedef std::vector<Keystroke> Keystrokes;
|
typedef std::vector<Keystroke> Keystrokes;
|
||||||
|
|
||||||
//! A mapping of a modifier to keys for that modifier
|
//! A mapping of a modifier to keys for that modifier
|
||||||
typedef std::multimap<KeyModifierMask, KeyItem> ModifierToKeys;
|
typedef std::multimap<KeyModifierMask, KeyItem> ModifierToKeys;
|
||||||
|
|
||||||
//! A set of buttons
|
//! A set of buttons
|
||||||
typedef std::map<KeyButton, const KeyItem*> ButtonToKeyMap;
|
typedef std::map<KeyButton, const KeyItem*> ButtonToKeyMap;
|
||||||
|
|
||||||
//! Callback type for \c foreachKey
|
//! Callback type for \c foreachKey
|
||||||
typedef void (*ForeachKeyCallback)(KeyID, SInt32 group,
|
typedef void (*ForeachKeyCallback)(KeyID, SInt32 group,
|
||||||
KeyItem&, void* userData);
|
KeyItem&, void* userData);
|
||||||
|
|
||||||
//! @name manipulators
|
//! @name manipulators
|
||||||
//@{
|
//@{
|
||||||
|
|
||||||
//! Swap with another \c KeyMap
|
//! Swap with another \c KeyMap
|
||||||
virtual void swap(KeyMap&);
|
virtual void swap(KeyMap&);
|
||||||
|
|
||||||
//! Add a key entry
|
//! Add a key entry
|
||||||
/*!
|
/*!
|
||||||
Adds \p item to the entries for the item's id and group. The
|
Adds \p item to the entries for the item's id and group. The
|
||||||
\c m_dead member is set automatically.
|
\c m_dead member is set automatically.
|
||||||
*/
|
*/
|
||||||
void addKeyEntry(const KeyItem& item);
|
void addKeyEntry(const KeyItem& item);
|
||||||
|
|
||||||
//! Add an alias key entry
|
//! Add an alias key entry
|
||||||
/*!
|
/*!
|
||||||
If \p targetID with the modifiers given by \p targetRequired and
|
If \p targetID with the modifiers given by \p targetRequired and
|
||||||
\p targetSensitive is not available in group \p group then find an
|
\p targetSensitive is not available in group \p group then find an
|
||||||
entry for \p sourceID with modifiers given by \p sourceRequired and
|
entry for \p sourceID with modifiers given by \p sourceRequired and
|
||||||
\p sourceSensitive in any group with exactly one item and, if found,
|
\p sourceSensitive in any group with exactly one item and, if found,
|
||||||
add a new item just like it except using id \p targetID. This
|
add a new item just like it except using id \p targetID. This
|
||||||
effectively makes the \p sourceID an alias for \p targetID (i.e. we
|
effectively makes the \p sourceID an alias for \p targetID (i.e. we
|
||||||
can generate \p targetID using \p sourceID).
|
can generate \p targetID using \p sourceID).
|
||||||
*/
|
*/
|
||||||
void addKeyAliasEntry(KeyID targetID, SInt32 group,
|
void addKeyAliasEntry(KeyID targetID, SInt32 group,
|
||||||
KeyModifierMask targetRequired,
|
KeyModifierMask targetRequired,
|
||||||
KeyModifierMask targetSensitive,
|
KeyModifierMask targetSensitive,
|
||||||
KeyID sourceID,
|
KeyID sourceID,
|
||||||
KeyModifierMask sourceRequired,
|
KeyModifierMask sourceRequired,
|
||||||
KeyModifierMask sourceSensitive);
|
KeyModifierMask sourceSensitive);
|
||||||
|
|
||||||
//! Add a key sequence entry
|
//! Add a key sequence entry
|
||||||
/*!
|
/*!
|
||||||
Adds the sequence of keys \p keys (\p numKeys elements long) to
|
Adds the sequence of keys \p keys (\p numKeys elements long) to
|
||||||
synthesize key \p id in group \p group. This looks up in the
|
synthesize key \p id in group \p group. This looks up in the
|
||||||
map each key in \p keys. If all are found then each key is
|
map each key in \p keys. If all are found then each key is
|
||||||
converted to the button for that key and the buttons are added
|
converted to the button for that key and the buttons are added
|
||||||
as the entry for \p id. If \p id is already in the map or at
|
as the entry for \p id. If \p id is already in the map or at
|
||||||
least one key in \p keys is not in the map then nothing is added
|
least one key in \p keys is not in the map then nothing is added
|
||||||
and this returns \c false, otherwise it returns \c true.
|
and this returns \c false, otherwise it returns \c true.
|
||||||
*/
|
*/
|
||||||
bool addKeyCombinationEntry(KeyID id, SInt32 group,
|
bool addKeyCombinationEntry(KeyID id, SInt32 group,
|
||||||
const KeyID* keys, UInt32 numKeys);
|
const KeyID* keys, UInt32 numKeys);
|
||||||
|
|
||||||
//! Enable composition across groups
|
//! Enable composition across groups
|
||||||
/*!
|
/*!
|
||||||
If called then the keyboard map will allow switching between groups
|
If called then the keyboard map will allow switching between groups
|
||||||
during key composition. Not all systems allow that.
|
during key composition. Not all systems allow that.
|
||||||
*/
|
*/
|
||||||
void allowGroupSwitchDuringCompose();
|
void allowGroupSwitchDuringCompose();
|
||||||
|
|
||||||
//! Add a half-duplex button
|
//! Add a half-duplex button
|
||||||
/*!
|
/*!
|
||||||
Records that button \p button is a half-duplex key. This is called
|
Records that button \p button is a half-duplex key. This is called
|
||||||
when translating the system's keyboard map. It's independent of the
|
when translating the system's keyboard map. It's independent of the
|
||||||
half-duplex modifier calls.
|
half-duplex modifier calls.
|
||||||
*/
|
*/
|
||||||
void addHalfDuplexButton(KeyButton button);
|
void addHalfDuplexButton(KeyButton button);
|
||||||
|
|
||||||
//! Remove all half-duplex modifiers
|
//! Remove all half-duplex modifiers
|
||||||
/*!
|
/*!
|
||||||
Removes all half-duplex modifiers. This is called to set user
|
Removes all half-duplex modifiers. This is called to set user
|
||||||
configurable half-duplex settings.
|
configurable half-duplex settings.
|
||||||
*/
|
*/
|
||||||
void clearHalfDuplexModifiers();
|
void clearHalfDuplexModifiers();
|
||||||
|
|
||||||
//! Add a half-duplex modifier
|
//! Add a half-duplex modifier
|
||||||
/*!
|
/*!
|
||||||
Records that modifier key \p key is half-duplex. This is called to
|
Records that modifier key \p key is half-duplex. This is called to
|
||||||
set user configurable half-duplex settings.
|
set user configurable half-duplex settings.
|
||||||
*/
|
*/
|
||||||
virtual void addHalfDuplexModifier(KeyID key);
|
virtual void addHalfDuplexModifier(KeyID key);
|
||||||
|
|
||||||
//! Finish adding entries
|
//! Finish adding entries
|
||||||
/*!
|
/*!
|
||||||
Called after adding entries, this does some internal housekeeping.
|
Called after adding entries, this does some internal housekeeping.
|
||||||
*/
|
*/
|
||||||
virtual void finish();
|
virtual void finish();
|
||||||
|
|
||||||
//! Iterate over all added keys items
|
//! Iterate over all added keys items
|
||||||
/*!
|
/*!
|
||||||
Calls \p cb for every key item.
|
Calls \p cb for every key item.
|
||||||
*/
|
*/
|
||||||
virtual void foreachKey(ForeachKeyCallback cb, void* userData);
|
virtual void foreachKey(ForeachKeyCallback cb, void* userData);
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
//! @name accessors
|
//! @name accessors
|
||||||
//@{
|
//@{
|
||||||
|
|
||||||
//! Map key press/repeat to keystrokes.
|
//! Map key press/repeat to keystrokes.
|
||||||
/*!
|
/*!
|
||||||
Converts press/repeat of key \p id in group \p group with current
|
Converts press/repeat of key \p id in group \p group with current
|
||||||
modifiers as given in \p currentState and the desired modifiers in
|
modifiers as given in \p currentState and the desired modifiers in
|
||||||
\p desiredMask into the keystrokes necessary to synthesize that key
|
\p desiredMask into the keystrokes necessary to synthesize that key
|
||||||
event in \p keys. It returns the \c KeyItem of the key being
|
event in \p keys. It returns the \c KeyItem of the key being
|
||||||
pressed/repeated, or NULL if the key cannot be mapped.
|
pressed/repeated, or NULL if the key cannot be mapped.
|
||||||
*/
|
*/
|
||||||
virtual const KeyItem* mapKey(Keystrokes& keys, KeyID id, SInt32 group,
|
virtual const KeyItem* mapKey(Keystrokes& keys, KeyID id, SInt32 group,
|
||||||
ModifierToKeys& activeModifiers,
|
ModifierToKeys& activeModifiers,
|
||||||
KeyModifierMask& currentState,
|
KeyModifierMask& currentState,
|
||||||
KeyModifierMask desiredMask,
|
KeyModifierMask desiredMask,
|
||||||
bool isAutoRepeat) const;
|
bool isAutoRepeat) const;
|
||||||
|
|
||||||
//! Get number of groups
|
//! Get number of groups
|
||||||
/*!
|
/*!
|
||||||
Returns the number of keyboard groups (independent layouts) in the map.
|
Returns the number of keyboard groups (independent layouts) in the map.
|
||||||
*/
|
*/
|
||||||
SInt32 getNumGroups() const;
|
SInt32 getNumGroups() const;
|
||||||
|
|
||||||
//! Compute a group number
|
//! Compute a group number
|
||||||
/*!
|
/*!
|
||||||
Returns the number of the group \p offset groups after group \p group.
|
Returns the number of the group \p offset groups after group \p group.
|
||||||
*/
|
*/
|
||||||
SInt32 getEffectiveGroup(SInt32 group, SInt32 offset) const;
|
SInt32 getEffectiveGroup(SInt32 group, SInt32 offset) const;
|
||||||
|
|
||||||
//! Find key entry compatible with modifiers
|
//! Find key entry compatible with modifiers
|
||||||
/*!
|
/*!
|
||||||
Returns the \c KeyItemList for the first entry for \p id in group
|
Returns the \c KeyItemList for the first entry for \p id in group
|
||||||
\p group that is compatible with the given modifiers, or NULL
|
\p group that is compatible with the given modifiers, or NULL
|
||||||
if there isn't one. A button list is compatible with a modifiers
|
if there isn't one. A button list is compatible with a modifiers
|
||||||
if it is either insensitive to all modifiers in \p sensitive or
|
if it is either insensitive to all modifiers in \p sensitive or
|
||||||
it requires the modifiers to be in the state indicated by \p required
|
it requires the modifiers to be in the state indicated by \p required
|
||||||
for every modifier indicated by \p sensitive.
|
for every modifier indicated by \p sensitive.
|
||||||
*/
|
*/
|
||||||
const KeyItemList* findCompatibleKey(KeyID id, SInt32 group,
|
const KeyItemList* findCompatibleKey(KeyID id, SInt32 group,
|
||||||
KeyModifierMask required,
|
KeyModifierMask required,
|
||||||
KeyModifierMask sensitive) const;
|
KeyModifierMask sensitive) const;
|
||||||
|
|
||||||
//! Test if modifier is half-duplex
|
//! Test if modifier is half-duplex
|
||||||
/*!
|
/*!
|
||||||
Returns \c true iff modifier key \p key or button \p button is
|
Returns \c true iff modifier key \p key or button \p button is
|
||||||
half-duplex.
|
half-duplex.
|
||||||
*/
|
*/
|
||||||
virtual bool isHalfDuplex(KeyID key, KeyButton button) const;
|
virtual bool isHalfDuplex(KeyID key, KeyButton button) const;
|
||||||
|
|
||||||
//! Test if modifiers indicate a command
|
//! Test if modifiers indicate a command
|
||||||
/*!
|
/*!
|
||||||
Returns \c true iff the modifiers in \p mask contain any command
|
Returns \c true iff the modifiers in \p mask contain any command
|
||||||
modifiers. A command modifier is used for keyboard shortcuts and
|
modifiers. A command modifier is used for keyboard shortcuts and
|
||||||
hotkeys, Rather than trying to synthesize a character, a command
|
hotkeys, Rather than trying to synthesize a character, a command
|
||||||
is trying to synthesize a particular set of buttons. So it's not
|
is trying to synthesize a particular set of buttons. So it's not
|
||||||
important to match the shift or AltGr state to achieve a character
|
important to match the shift or AltGr state to achieve a character
|
||||||
but it is important to match the modifier state exactly.
|
but it is important to match the modifier state exactly.
|
||||||
*/
|
*/
|
||||||
bool isCommand(KeyModifierMask mask) const;
|
bool isCommand(KeyModifierMask mask) const;
|
||||||
|
|
||||||
// Get the modifiers that indicate a command
|
// Get the modifiers that indicate a command
|
||||||
/*!
|
/*!
|
||||||
Returns the modifiers that when combined with other keys indicate
|
Returns the modifiers that when combined with other keys indicate
|
||||||
a command (e.g. shortcut or hotkey).
|
a command (e.g. shortcut or hotkey).
|
||||||
*/
|
*/
|
||||||
KeyModifierMask getCommandModifiers() const;
|
KeyModifierMask getCommandModifiers() const;
|
||||||
|
|
||||||
//! Get buttons from modifier map
|
//! Get buttons from modifier map
|
||||||
/*!
|
/*!
|
||||||
Put all the keys in \p modifiers into \p keys.
|
Put all the keys in \p modifiers into \p keys.
|
||||||
*/
|
*/
|
||||||
static void collectButtons(const ModifierToKeys& modifiers,
|
static void collectButtons(const ModifierToKeys& modifiers,
|
||||||
ButtonToKeyMap& keys);
|
ButtonToKeyMap& keys);
|
||||||
|
|
||||||
//! Set modifier key state
|
//! Set modifier key state
|
||||||
/*!
|
/*!
|
||||||
Sets the modifier key state (\c m_generates and \c m_lock) in \p item
|
Sets the modifier key state (\c m_generates and \c m_lock) in \p item
|
||||||
based on the \c m_id in \p item.
|
based on the \c m_id in \p item.
|
||||||
*/
|
*/
|
||||||
static void initModifierKey(KeyItem& item);
|
static void initModifierKey(KeyItem& item);
|
||||||
|
|
||||||
//! Test for a dead key
|
//! Test for a dead key
|
||||||
/*!
|
/*!
|
||||||
Returns \c true if \p key is a dead key.
|
Returns \c true if \p key is a dead key.
|
||||||
*/
|
*/
|
||||||
static bool isDeadKey(KeyID key);
|
static bool isDeadKey(KeyID key);
|
||||||
|
|
||||||
//! Get corresponding dead key
|
//! Get corresponding dead key
|
||||||
/*!
|
/*!
|
||||||
Returns the dead key corresponding to \p key if one exists, otherwise
|
Returns the dead key corresponding to \p key if one exists, otherwise
|
||||||
return \c kKeyNone. This returns \p key if it's already a dead key.
|
return \c kKeyNone. This returns \p key if it's already a dead key.
|
||||||
*/
|
*/
|
||||||
static KeyID getDeadKey(KeyID key);
|
static KeyID getDeadKey(KeyID key);
|
||||||
|
|
||||||
//! Get string for a key and modifier mask
|
//! Get string for a key and modifier mask
|
||||||
/*!
|
/*!
|
||||||
Converts a key and modifier mask into a string representing the
|
Converts a key and modifier mask into a string representing the
|
||||||
combination.
|
combination.
|
||||||
*/
|
*/
|
||||||
static String formatKey(KeyID key, KeyModifierMask);
|
static String formatKey(KeyID key, KeyModifierMask);
|
||||||
|
|
||||||
//! Parse a string into a key
|
//! Parse a string into a key
|
||||||
/*!
|
/*!
|
||||||
Converts a string into a key. Returns \c true on success and \c false
|
Converts a string into a key. Returns \c true on success and \c false
|
||||||
if the string cannot be parsed.
|
if the string cannot be parsed.
|
||||||
*/
|
*/
|
||||||
static bool parseKey(const String&, KeyID&);
|
static bool parseKey(const String&, KeyID&);
|
||||||
|
|
||||||
//! Parse a string into a modifier mask
|
//! Parse a string into a modifier mask
|
||||||
/*!
|
/*!
|
||||||
Converts a string into a modifier mask. Returns \c true on success
|
Converts a string into a modifier mask. Returns \c true on success
|
||||||
and \c false if the string cannot be parsed. The modifiers plus any
|
and \c false if the string cannot be parsed. The modifiers plus any
|
||||||
remaining leading and trailing whitespace is stripped from the input
|
remaining leading and trailing whitespace is stripped from the input
|
||||||
string.
|
string.
|
||||||
*/
|
*/
|
||||||
static bool parseModifiers(String&, KeyModifierMask&);
|
static bool parseModifiers(String&, KeyModifierMask&);
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
|
#ifdef TEST_ENV
|
||||||
|
private:
|
||||||
|
FRIEND_TEST(KeyMapTests,
|
||||||
|
findBestKey_requiredDown_matchExactFirstItem);
|
||||||
|
FRIEND_TEST(KeyMapTests,
|
||||||
|
findBestKey_requiredAndExtraSensitiveDown_matchExactFirstItem);
|
||||||
|
FRIEND_TEST(KeyMapTests,
|
||||||
|
findBestKey_requiredAndExtraSensitiveDown_matchExactSecondItem);
|
||||||
|
FRIEND_TEST(KeyMapTests,
|
||||||
|
findBestKey_extraSensitiveDown_matchExactSecondItem);
|
||||||
|
FRIEND_TEST(KeyMapTests,
|
||||||
|
findBestKey_noRequiredDown_matchOneRequiredChangeItem);
|
||||||
|
FRIEND_TEST(KeyMapTests,
|
||||||
|
findBestKey_onlyOneRequiredDown_matchTwoRequiredChangesItem);
|
||||||
|
FRIEND_TEST(KeyMapTests, findBestKey_noRequiredDown_cannotMatch);
|
||||||
|
#endif
|
||||||
|
private:
|
||||||
|
//! Ways to synthesize a key
|
||||||
|
enum EKeystroke {
|
||||||
|
kKeystrokePress, //!< Synthesize a press
|
||||||
|
kKeystrokeRelease, //!< Synthesize a release
|
||||||
|
kKeystrokeRepeat, //!< Synthesize an autorepeat
|
||||||
|
kKeystrokeClick, //!< Synthesize a press and release
|
||||||
|
kKeystrokeModify, //!< Synthesize pressing a modifier
|
||||||
|
kKeystrokeUnmodify //!< Synthesize releasing a modifier
|
||||||
|
};
|
||||||
|
|
||||||
|
// A list of ways to synthesize a KeyID
|
||||||
|
typedef std::vector<KeyItemList> KeyEntryList;
|
||||||
|
|
||||||
|
// computes the number of groups
|
||||||
|
SInt32 findNumGroups() const;
|
||||||
|
|
||||||
|
// computes the map of modifiers to the keys that generate the modifiers
|
||||||
|
void setModifierKeys();
|
||||||
|
|
||||||
|
// maps a command key. a command key is a keyboard shortcut and we're
|
||||||
|
// trying to synthesize a button press with an exact sets of modifiers,
|
||||||
|
// not trying to synthesize a character. so we just need to find the
|
||||||
|
// right button and synthesize the requested modifiers without regard
|
||||||
|
// to what character they would synthesize. we disallow multikey
|
||||||
|
// entries since they don't make sense as hotkeys.
|
||||||
|
const KeyItem* mapCommandKey(Keystrokes& keys,
|
||||||
|
KeyID id, SInt32 group,
|
||||||
|
ModifierToKeys& activeModifiers,
|
||||||
|
KeyModifierMask& currentState,
|
||||||
|
KeyModifierMask desiredMask,
|
||||||
|
bool isAutoRepeat) const;
|
||||||
|
|
||||||
|
// maps a character key. a character key is trying to synthesize a
|
||||||
|
// particular KeyID and isn't entirely concerned with the modifiers
|
||||||
|
// used to do it.
|
||||||
|
const KeyItem* mapCharacterKey(Keystrokes& keys,
|
||||||
|
KeyID id, SInt32 group,
|
||||||
|
ModifierToKeys& activeModifiers,
|
||||||
|
KeyModifierMask& currentState,
|
||||||
|
KeyModifierMask desiredMask,
|
||||||
|
bool isAutoRepeat) const;
|
||||||
|
|
||||||
|
// maps a modifier key
|
||||||
|
const KeyItem* mapModifierKey(Keystrokes& keys,
|
||||||
|
KeyID id, SInt32 group,
|
||||||
|
ModifierToKeys& activeModifiers,
|
||||||
|
KeyModifierMask& currentState,
|
||||||
|
KeyModifierMask desiredMask,
|
||||||
|
bool isAutoRepeat) const;
|
||||||
|
|
||||||
|
// returns the index into \p entryList of the KeyItemList requiring
|
||||||
|
// the fewest modifier changes between \p currentState and
|
||||||
|
// \p desiredState.
|
||||||
|
SInt32 findBestKey(const KeyEntryList& entryList,
|
||||||
|
KeyModifierMask currentState,
|
||||||
|
KeyModifierMask desiredState) const;
|
||||||
|
|
||||||
|
// gets the \c KeyItem used to synthesize the modifier who's bit is
|
||||||
|
// given by \p modifierBit in group \p group and does not synthesize
|
||||||
|
// the key \p button.
|
||||||
|
const KeyItem* keyForModifier(KeyButton button, SInt32 group,
|
||||||
|
SInt32 modifierBit) const;
|
||||||
|
|
||||||
|
// fills \p keystrokes with the keys to synthesize the key in
|
||||||
|
// \p keyItem taking the modifiers into account. returns \c true
|
||||||
|
// iff successful and sets \p currentState to the
|
||||||
|
// resulting modifier state.
|
||||||
|
bool keysForKeyItem(const KeyItem& keyItem,
|
||||||
|
SInt32& group,
|
||||||
|
ModifierToKeys& activeModifiers,
|
||||||
|
KeyModifierMask& currentState,
|
||||||
|
KeyModifierMask desiredState,
|
||||||
|
KeyModifierMask overrideModifiers,
|
||||||
|
bool isAutoRepeat,
|
||||||
|
Keystrokes& keystrokes) const;
|
||||||
|
|
||||||
|
// fills \p keystrokes with the keys to synthesize the modifiers
|
||||||
|
// in \p desiredModifiers from the active modifiers listed in
|
||||||
|
// \p activeModifiers not including the key in \p keyItem.
|
||||||
|
// returns \c true iff successful.
|
||||||
|
bool keysToRestoreModifiers(const KeyItem& keyItem,
|
||||||
|
SInt32 group,
|
||||||
|
ModifierToKeys& activeModifiers,
|
||||||
|
KeyModifierMask& currentState,
|
||||||
|
const ModifierToKeys& desiredModifiers,
|
||||||
|
Keystrokes& keystrokes) const;
|
||||||
|
|
||||||
|
// fills \p keystrokes and \p undo with the keys to change the
|
||||||
|
// current modifier state in \p currentState to match the state in
|
||||||
|
// \p requiredState for each modifier indicated in \p sensitiveMask.
|
||||||
|
// returns \c true iff successful and sets \p currentState to the
|
||||||
|
// resulting modifier state.
|
||||||
|
bool keysForModifierState(KeyButton button, SInt32 group,
|
||||||
|
ModifierToKeys& activeModifiers,
|
||||||
|
KeyModifierMask& currentState,
|
||||||
|
KeyModifierMask requiredState,
|
||||||
|
KeyModifierMask sensitiveMask,
|
||||||
|
KeyModifierMask notRequiredMask,
|
||||||
|
Keystrokes& keystrokes) const;
|
||||||
|
|
||||||
|
// Adds keystrokes to synthesize key \p keyItem in mode \p type to
|
||||||
|
// \p keystrokes and to undo the synthesis to \p undo.
|
||||||
|
void addKeystrokes(EKeystroke type,
|
||||||
|
const KeyItem& keyItem,
|
||||||
|
ModifierToKeys& activeModifiers,
|
||||||
|
KeyModifierMask& currentState,
|
||||||
|
Keystrokes& keystrokes) const;
|
||||||
|
|
||||||
|
// Returns the number of modifiers indicated in \p state.
|
||||||
|
static SInt32 getNumModifiers(KeyModifierMask state);
|
||||||
|
|
||||||
|
// Initialize key name/id maps
|
||||||
|
static void initKeyNameMaps();
|
||||||
|
|
||||||
|
// not implemented
|
||||||
|
KeyMap(const KeyMap&);
|
||||||
|
KeyMap& operator=(const KeyMap&);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FRIEND_TEST(KeyMapTests,
|
// Ways to synthesize a KeyID over multiple keyboard groups
|
||||||
findBestKey_requiredDown_matchExactFirstItem);
|
typedef std::vector<KeyEntryList> KeyGroupTable;
|
||||||
FRIEND_TEST(KeyMapTests,
|
|
||||||
findBestKey_requiredAndExtraSensitiveDown_matchExactFirstItem);
|
|
||||||
FRIEND_TEST(KeyMapTests,
|
|
||||||
findBestKey_requiredAndExtraSensitiveDown_matchExactSecondItem);
|
|
||||||
FRIEND_TEST(KeyMapTests,
|
|
||||||
findBestKey_extraSensitiveDown_matchExactSecondItem);
|
|
||||||
FRIEND_TEST(KeyMapTests,
|
|
||||||
findBestKey_noRequiredDown_matchOneRequiredChangeItem);
|
|
||||||
FRIEND_TEST(KeyMapTests,
|
|
||||||
findBestKey_onlyOneRequiredDown_matchTwoRequiredChangesItem);
|
|
||||||
FRIEND_TEST(KeyMapTests, findBestKey_noRequiredDown_cannotMatch);
|
|
||||||
|
|
||||||
private:
|
// Table of KeyID to ways to synthesize that KeyID
|
||||||
//! Ways to synthesize a key
|
typedef std::map<KeyID, KeyGroupTable> KeyIDMap;
|
||||||
enum EKeystroke {
|
|
||||||
kKeystrokePress, //!< Synthesize a press
|
|
||||||
kKeystrokeRelease, //!< Synthesize a release
|
|
||||||
kKeystrokeRepeat, //!< Synthesize an autorepeat
|
|
||||||
kKeystrokeClick, //!< Synthesize a press and release
|
|
||||||
kKeystrokeModify, //!< Synthesize pressing a modifier
|
|
||||||
kKeystrokeUnmodify //!< Synthesize releasing a modifier
|
|
||||||
};
|
|
||||||
|
|
||||||
// A list of ways to synthesize a KeyID
|
// List of KeyItems that generate a particular modifier
|
||||||
typedef std::vector<KeyItemList> KeyEntryList;
|
typedef std::vector<const KeyItem*> ModifierKeyItemList;
|
||||||
|
|
||||||
// computes the number of groups
|
// Map a modifier to the KeyItems that synthesize that modifier
|
||||||
SInt32 findNumGroups() const;
|
typedef std::vector<ModifierKeyItemList> ModifierToKeyTable;
|
||||||
|
|
||||||
// computes the map of modifiers to the keys that generate the modifiers
|
// A set of keys
|
||||||
void setModifierKeys();
|
typedef std::set<KeyID> KeySet;
|
||||||
|
|
||||||
// maps a command key. a command key is a keyboard shortcut and we're
|
// A set of buttons
|
||||||
// trying to synthesize a button press with an exact sets of modifiers,
|
typedef std::set<KeyButton> KeyButtonSet;
|
||||||
// not trying to synthesize a character. so we just need to find the
|
|
||||||
// right button and synthesize the requested modifiers without regard
|
|
||||||
// to what character they would synthesize. we disallow multikey
|
|
||||||
// entries since they don't make sense as hotkeys.
|
|
||||||
const KeyItem* mapCommandKey(Keystrokes& keys,
|
|
||||||
KeyID id, SInt32 group,
|
|
||||||
ModifierToKeys& activeModifiers,
|
|
||||||
KeyModifierMask& currentState,
|
|
||||||
KeyModifierMask desiredMask,
|
|
||||||
bool isAutoRepeat) const;
|
|
||||||
|
|
||||||
// maps a character key. a character key is trying to synthesize a
|
// Key maps for parsing/formatting
|
||||||
// particular KeyID and isn't entirely concerned with the modifiers
|
typedef std::map<String, KeyID,
|
||||||
// used to do it.
|
synergy::string::CaselessCmp> NameToKeyMap;
|
||||||
const KeyItem* mapCharacterKey(Keystrokes& keys,
|
typedef std::map<String, KeyModifierMask,
|
||||||
KeyID id, SInt32 group,
|
synergy::string::CaselessCmp> NameToModifierMap;
|
||||||
ModifierToKeys& activeModifiers,
|
typedef std::map<KeyID, String> KeyToNameMap;
|
||||||
KeyModifierMask& currentState,
|
typedef std::map<KeyModifierMask, String> ModifierToNameMap;
|
||||||
KeyModifierMask desiredMask,
|
|
||||||
bool isAutoRepeat) const;
|
|
||||||
|
|
||||||
// maps a modifier key
|
// KeyID info
|
||||||
const KeyItem* mapModifierKey(Keystrokes& keys,
|
KeyIDMap m_keyIDMap;
|
||||||
KeyID id, SInt32 group,
|
SInt32 m_numGroups;
|
||||||
ModifierToKeys& activeModifiers,
|
ModifierToKeyTable m_modifierKeys;
|
||||||
KeyModifierMask& currentState,
|
|
||||||
KeyModifierMask desiredMask,
|
|
||||||
bool isAutoRepeat) const;
|
|
||||||
|
|
||||||
// returns the index into \p entryList of the KeyItemList requiring
|
// composition info
|
||||||
// the fewest modifier changes between \p currentState and
|
bool m_composeAcrossGroups;
|
||||||
// \p desiredState.
|
|
||||||
SInt32 findBestKey(const KeyEntryList& entryList,
|
|
||||||
KeyModifierMask currentState,
|
|
||||||
KeyModifierMask desiredState) const;
|
|
||||||
|
|
||||||
// gets the \c KeyItem used to synthesize the modifier who's bit is
|
// half-duplex info
|
||||||
// given by \p modifierBit in group \p group and does not synthesize
|
KeyButtonSet m_halfDuplex; // half-duplex set by synergy
|
||||||
// the key \p button.
|
KeySet m_halfDuplexMods; // half-duplex set by user
|
||||||
const KeyItem* keyForModifier(KeyButton button, SInt32 group,
|
|
||||||
SInt32 modifierBit) const;
|
|
||||||
|
|
||||||
// fills \p keystrokes with the keys to synthesize the key in
|
// dummy KeyItem for changing modifiers
|
||||||
// \p keyItem taking the modifiers into account. returns \c true
|
KeyItem m_modifierKeyItem;
|
||||||
// iff successful and sets \p currentState to the
|
|
||||||
// resulting modifier state.
|
|
||||||
bool keysForKeyItem(const KeyItem& keyItem,
|
|
||||||
SInt32& group,
|
|
||||||
ModifierToKeys& activeModifiers,
|
|
||||||
KeyModifierMask& currentState,
|
|
||||||
KeyModifierMask desiredState,
|
|
||||||
KeyModifierMask overrideModifiers,
|
|
||||||
bool isAutoRepeat,
|
|
||||||
Keystrokes& keystrokes) const;
|
|
||||||
|
|
||||||
// fills \p keystrokes with the keys to synthesize the modifiers
|
// parsing/formatting tables
|
||||||
// in \p desiredModifiers from the active modifiers listed in
|
static NameToKeyMap* s_nameToKeyMap;
|
||||||
// \p activeModifiers not including the key in \p keyItem.
|
static NameToModifierMap* s_nameToModifierMap;
|
||||||
// returns \c true iff successful.
|
static KeyToNameMap* s_keyToNameMap;
|
||||||
bool keysToRestoreModifiers(const KeyItem& keyItem,
|
static ModifierToNameMap* s_modifierToNameMap;
|
||||||
SInt32 group,
|
|
||||||
ModifierToKeys& activeModifiers,
|
|
||||||
KeyModifierMask& currentState,
|
|
||||||
const ModifierToKeys& desiredModifiers,
|
|
||||||
Keystrokes& keystrokes) const;
|
|
||||||
|
|
||||||
// fills \p keystrokes and \p undo with the keys to change the
|
|
||||||
// current modifier state in \p currentState to match the state in
|
|
||||||
// \p requiredState for each modifier indicated in \p sensitiveMask.
|
|
||||||
// returns \c true iff successful and sets \p currentState to the
|
|
||||||
// resulting modifier state.
|
|
||||||
bool keysForModifierState(KeyButton button, SInt32 group,
|
|
||||||
ModifierToKeys& activeModifiers,
|
|
||||||
KeyModifierMask& currentState,
|
|
||||||
KeyModifierMask requiredState,
|
|
||||||
KeyModifierMask sensitiveMask,
|
|
||||||
KeyModifierMask notRequiredMask,
|
|
||||||
Keystrokes& keystrokes) const;
|
|
||||||
|
|
||||||
// Adds keystrokes to synthesize key \p keyItem in mode \p type to
|
|
||||||
// \p keystrokes and to undo the synthesis to \p undo.
|
|
||||||
void addKeystrokes(EKeystroke type,
|
|
||||||
const KeyItem& keyItem,
|
|
||||||
ModifierToKeys& activeModifiers,
|
|
||||||
KeyModifierMask& currentState,
|
|
||||||
Keystrokes& keystrokes) const;
|
|
||||||
|
|
||||||
// Returns the number of modifiers indicated in \p state.
|
|
||||||
static SInt32 getNumModifiers(KeyModifierMask state);
|
|
||||||
|
|
||||||
// Initialize key name/id maps
|
|
||||||
static void initKeyNameMaps();
|
|
||||||
|
|
||||||
// not implemented
|
|
||||||
KeyMap(const KeyMap&);
|
|
||||||
KeyMap& operator=(const KeyMap&);
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Ways to synthesize a KeyID over multiple keyboard groups
|
|
||||||
typedef std::vector<KeyEntryList> KeyGroupTable;
|
|
||||||
|
|
||||||
// Table of KeyID to ways to synthesize that KeyID
|
|
||||||
typedef std::map<KeyID, KeyGroupTable> KeyIDMap;
|
|
||||||
|
|
||||||
// List of KeyItems that generate a particular modifier
|
|
||||||
typedef std::vector<const KeyItem*> ModifierKeyItemList;
|
|
||||||
|
|
||||||
// Map a modifier to the KeyItems that synthesize that modifier
|
|
||||||
typedef std::vector<ModifierKeyItemList> ModifierToKeyTable;
|
|
||||||
|
|
||||||
// A set of keys
|
|
||||||
typedef std::set<KeyID> KeySet;
|
|
||||||
|
|
||||||
// A set of buttons
|
|
||||||
typedef std::set<KeyButton> KeyButtonSet;
|
|
||||||
|
|
||||||
// Key maps for parsing/formatting
|
|
||||||
typedef std::map<String, KeyID,
|
|
||||||
synergy::string::CaselessCmp> NameToKeyMap;
|
|
||||||
typedef std::map<String, KeyModifierMask,
|
|
||||||
synergy::string::CaselessCmp> NameToModifierMap;
|
|
||||||
typedef std::map<KeyID, String> KeyToNameMap;
|
|
||||||
typedef std::map<KeyModifierMask, String> ModifierToNameMap;
|
|
||||||
|
|
||||||
// KeyID info
|
|
||||||
KeyIDMap m_keyIDMap;
|
|
||||||
SInt32 m_numGroups;
|
|
||||||
ModifierToKeyTable m_modifierKeys;
|
|
||||||
|
|
||||||
// composition info
|
|
||||||
bool m_composeAcrossGroups;
|
|
||||||
|
|
||||||
// half-duplex info
|
|
||||||
KeyButtonSet m_halfDuplex; // half-duplex set by synergy
|
|
||||||
KeySet m_halfDuplexMods; // half-duplex set by user
|
|
||||||
|
|
||||||
// dummy KeyItem for changing modifiers
|
|
||||||
KeyItem m_modifierKeyItem;
|
|
||||||
|
|
||||||
// parsing/formatting tables
|
|
||||||
static NameToKeyMap* s_nameToKeyMap;
|
|
||||||
static NameToModifierMap* s_nameToModifierMap;
|
|
||||||
static KeyToNameMap* s_keyToNameMap;
|
|
||||||
static ModifierToNameMap* s_modifierToNameMap;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,8 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define TEST_ENV
|
||||||
|
|
||||||
#include "synergy/KeyMap.h"
|
#include "synergy/KeyMap.h"
|
||||||
|
|
||||||
#include "test/global/gtest.h"
|
#include "test/global/gtest.h"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue