Deskflow 1.22.0.197
Keyboard and mouse sharing utility
Loading...
Searching...
No Matches
KeyMap.h
Go to the documentation of this file.
1/*
2 * Deskflow -- mouse and keyboard sharing utility
3 * SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
4 * SPDX-FileCopyrightText: (C) 2005 Chris Schoeneman
5 * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
6 */
7
8#pragma once
9
10#include "base/String.h"
11#include "deskflow/KeyTypes.h"
12
13#include <map>
14#include <set>
15#include <vector>
16
17namespace deskflow {
18
20
23class KeyMap
24{
25public:
26 // Class used for testing
27 friend class KeyMapTests;
28
29 KeyMap();
30 virtual ~KeyMap() = default;
31
33
41 struct KeyItem
42 {
43 public:
45 int32_t m_group{};
50 bool m_dead{};
51 bool m_lock{};
52 uint32_t m_client{};
53
54 public:
55 bool operator==(const KeyItem &) const;
56 };
57
59
68 using KeyItemList = std::vector<KeyItem>;
69
72 {
73 public:
74 enum EType
75 {
78 };
79
80 Keystroke(KeyButton, bool press, bool repeat, uint32_t clientData);
81 Keystroke(int32_t group, bool absolute, bool restore);
82
83 public:
84 struct Button
85 {
86 public:
88 bool m_press{};
89 bool m_repeat{};
90 uint32_t m_client{};
91 };
92 struct Group
93 {
94 public:
95 int32_t m_group{};
96 bool m_absolute{};
97 bool m_restore{};
98 };
99 union Data
100 {
101 public:
104 };
105
108 };
109
111 using Keystrokes = std::vector<Keystroke>;
112
114 using ModifierToKeys = std::multimap<KeyModifierMask, KeyItem>;
115
117 using ButtonToKeyMap = std::map<KeyButton, const KeyItem *>;
118
120 using ForeachKeyCallback = void (*)(KeyID, int32_t group, KeyItem &, void *userData);
121
123
124
126 virtual void swap(KeyMap &) noexcept;
127
129
133 void addKeyEntry(const KeyItem &item);
134
136
145 void addKeyAliasEntry(
146 KeyID targetID, int32_t group, KeyModifierMask targetRequired, KeyModifierMask targetSensitive, KeyID sourceID,
147 KeyModifierMask sourceRequired, KeyModifierMask sourceSensitive
148 );
149
151
160 bool addKeyCombinationEntry(KeyID id, int32_t group, const KeyID *keys, uint32_t numKeys);
161
163
168
170
175 void addHalfDuplexButton(KeyButton button);
176
178
183
185
189 virtual void addHalfDuplexModifier(KeyID key);
190
192
195 virtual void finish();
196
198
201 virtual void foreachKey(ForeachKeyCallback cb, void *userData);
202
204
206
208
215 virtual const KeyItem *mapKey(
216 Keystrokes &keys, KeyID id, int32_t group, ModifierToKeys &activeModifiers, KeyModifierMask &currentState,
217 KeyModifierMask desiredMask, bool isAutoRepeat, const std::string &lang
218 ) const;
219
220 void setLanguageData(std::vector<std::string> layouts);
221
223
226 int32_t getNumGroups() const;
227
229
232 int32_t getEffectiveGroup(int32_t group, int32_t offset) const;
233
235
243 const KeyItemList *
244 findCompatibleKey(KeyID id, int32_t group, KeyModifierMask required, KeyModifierMask sensitive) const;
245
247
251 virtual bool isHalfDuplex(KeyID key, KeyButton button) const;
252
254
262 bool isCommand(KeyModifierMask mask) const;
263
264 // Get the modifiers that indicate a command
270
272
275 static void collectButtons(const ModifierToKeys &modifiers, ButtonToKeyMap &keys);
276
278
282 static void initModifierKey(KeyItem &item);
283
285
288 static bool isDeadKey(KeyID key);
289
291
295 static KeyID getDeadKey(KeyID key);
296
298
302 static std::string formatKey(KeyID key, KeyModifierMask);
303
305
309 static bool parseKey(const std::string &, KeyID &);
310
312
318 static bool parseModifiers(std::string &, KeyModifierMask &);
319
321
322private:
324 enum EKeystroke
325 {
326 kKeystrokePress,
327 kKeystrokeRelease,
328 kKeystrokeRepeat,
329 kKeystrokeClick,
330 kKeystrokeModify,
331 kKeystrokeUnmodify
332 };
333
334 // A list of ways to synthesize a KeyID
335 using KeyEntryList = std::vector<KeyItemList>;
336
337 // computes the number of groups
338 int32_t findNumGroups() const;
339
340 // computes the map of modifiers to the keys that generate the modifiers
341 void setModifierKeys();
342
343 // maps a command key. a command key is a keyboard shortcut and we're
344 // trying to synthesize a button press with an exact sets of modifiers,
345 // not trying to synthesize a character. so we just need to find the
346 // right button and synthesize the requested modifiers without regard
347 // to what character they would synthesize. we disallow multikey
348 // entries since they don't make sense as hotkeys.
349 const KeyItem *mapCommandKey(
350 Keystrokes &keys, KeyID id, int32_t group, ModifierToKeys &activeModifiers, KeyModifierMask &currentState,
351 KeyModifierMask desiredMask, bool isAutoRepeat, const std::string &lang
352 ) const;
353
354 // maps a character key. a character key is trying to synthesize a
355 // particular KeyID and isn't entirely concerned with the modifiers
356 // used to do it.
357 const KeyItem *mapCharacterKey(
358 Keystrokes &keys, KeyID id, int32_t group, ModifierToKeys &activeModifiers, KeyModifierMask &currentState,
359 KeyModifierMask desiredMask, bool isAutoRepeat, const std::string &lang
360 ) const;
361
362 // maps a modifier key
363 const KeyItem *mapModifierKey(
364 Keystrokes &keys, KeyID id, int32_t group, ModifierToKeys &activeModifiers, KeyModifierMask &currentState,
365 KeyModifierMask desiredMask, bool isAutoRepeat, const std::string &lang
366 ) const;
367
368 // returns the index into \p entryList of the KeyItemList requiring
369 // the fewest modifier changes between \p currentState and
370 // \p desiredState.
371 int32_t findBestKey(const KeyEntryList &entryList, KeyModifierMask desiredState) const;
372
373 // gets the \c KeyItem used to synthesize the modifier who's bit is
374 // given by \p modifierBit in group \p group and does not synthesize
375 // the key \p button.
376 const KeyItem *keyForModifier(KeyButton button, int32_t group, int32_t modifierBit) const;
377
378 // fills \p keystrokes with the keys to synthesize the key in
379 // \p keyItem taking the modifiers into account. returns \c true
380 // iff successful and sets \p currentState to the
381 // resulting modifier state.
382 bool keysForKeyItem(
383 const KeyItem &keyItem, int32_t &group, ModifierToKeys &activeModifiers, KeyModifierMask &currentState,
384 KeyModifierMask desiredState, KeyModifierMask overrideModifiers, bool isAutoRepeat, Keystrokes &keystrokes,
385 const std::string &lang
386 ) const;
387
388 // fills \p keystrokes with the keys to synthesize the modifiers
389 // in \p desiredModifiers from the active modifiers listed in
390 // \p activeModifiers not including the key in \p keyItem.
391 // returns \c true iff successful.
392 bool keysToRestoreModifiers(
393 const KeyItem &keyItem, int32_t group, ModifierToKeys &activeModifiers, KeyModifierMask &currentState,
394 const ModifierToKeys &desiredModifiers, Keystrokes &keystrokes
395 ) const;
396
397 // fills \p keystrokes and \p undo with the keys to change the
398 // current modifier state in \p currentState to match the state in
399 // \p requiredState for each modifier indicated in \p sensitiveMask.
400 // returns \c true iff successful and sets \p currentState to the
401 // resulting modifier state.
402 bool keysForModifierState(
403 KeyButton button, int32_t group, ModifierToKeys &activeModifiers, KeyModifierMask &currentState,
404 KeyModifierMask requiredState, KeyModifierMask sensitiveMask, KeyModifierMask notRequiredMask,
405 Keystrokes &keystrokes
406 ) const;
407
408 // Adds keystrokes to synthesize key \p keyItem in mode \p type to
409 // \p keystrokes and to undo the synthesis to \p undo.
410 void addKeystrokes(
411 EKeystroke type, const KeyItem &keyItem, ModifierToKeys &activeModifiers, KeyModifierMask &currentState,
412 Keystrokes &keystrokes
413 ) const;
414
415 // Returns the number of modifiers indicated in \p state.
416 static int32_t getNumModifiers(KeyModifierMask state);
417
418 // Initialize key name/id maps
419 static void initKeyNameMaps();
420
421 // Ways to synthesize a KeyID over multiple keyboard groups
422 using KeyGroupTable = std::vector<KeyEntryList>;
423
424 void addGroupToKeystroke(Keystrokes &keys, int32_t &group, const std::string &lang) const;
425
426 int32_t getLanguageGroupID(int32_t group, const std::string &lang) const;
427 const KeyItemList *
428 getKeyItemList(const KeyGroupTable &keyGroupTable, int32_t group, KeyModifierMask desiredMask) const;
429
430 // not implemented
431 KeyMap(const KeyMap &);
432 KeyMap &operator=(const KeyMap &);
433
434private:
435 // Table of KeyID to ways to synthesize that KeyID
436 using KeyIDMap = std::map<KeyID, KeyGroupTable>;
437
438 // List of KeyItems that generate a particular modifier
439 using ModifierKeyItemList = std::vector<const KeyItem *>;
440
441 // Map a modifier to the KeyItems that synthesize that modifier
442 using ModifierToKeyTable = std::vector<ModifierKeyItemList>;
443
444 // A set of keys
445 using KeySet = std::set<KeyID>;
446
447 // A set of buttons
448 using KeyButtonSet = std::set<KeyButton>;
449
450 // Key maps for parsing/formatting
451 using NameToKeyMap = std::map<std::string, KeyID, deskflow::string::CaselessCmp>;
452 using NameToModifierMap = std::map<std::string, KeyModifierMask, deskflow::string::CaselessCmp>;
453 using KeyToNameMap = std::map<KeyID, std::string>;
454 using ModifierToNameMap = std::map<KeyModifierMask, std::string>;
455
456 // KeyID info
457 KeyIDMap m_keyIDMap;
458 int32_t m_numGroups;
459 ModifierToKeyTable m_modifierKeys;
460
461 // composition info
462 bool m_composeAcrossGroups;
463
464 // half-duplex info
465 KeyButtonSet m_halfDuplex; // half-duplex set by deskflow
466 KeySet m_halfDuplexMods; // half-duplex set by user
467
468 // dummy KeyItem for changing modifiers
469 KeyItem m_modifierKeyItem;
470
471 // Language sync data
472 std::vector<std::string> m_keyboardLayouts;
473
474 // parsing/formatting tables
475 static NameToKeyMap *s_nameToKeyMap;
476 static NameToModifierMap *s_nameToModifierMap;
477 static KeyToNameMap *s_keyToNameMap;
478 static ModifierToNameMap *s_modifierToNameMap;
479};
480
481} // namespace deskflow
static int type
Definition ArchNetworkWinsock.cpp:44
int key
Definition KeySequence.cpp:15
uint32_t KeyID
Key ID.
Definition KeyTypes.h:22
uint16_t KeyButton
Key Code.
Definition KeyTypes.h:35
uint32_t KeyModifierMask
Modifier key mask.
Definition KeyTypes.h:45
EType
Definition KeyMap.h:75
@ kGroup
Set new group.
Definition KeyMap.h:77
@ kButton
Synthesize button.
Definition KeyMap.h:76
Data m_data
Definition KeyMap.h:107
Keystroke(KeyButton, bool press, bool repeat, uint32_t clientData)
Definition KeyMap.cpp:1234
EType m_type
Definition KeyMap.h:106
Key map.
Definition KeyMap.h:24
virtual void foreachKey(ForeachKeyCallback cb, void *userData)
Iterate over all added keys items.
Definition KeyMap.cpp:212
void addKeyAliasEntry(KeyID targetID, int32_t group, KeyModifierMask targetRequired, KeyModifierMask targetSensitive, KeyID sourceID, KeyModifierMask sourceRequired, KeyModifierMask sourceSensitive)
Add an alias key entry.
Definition KeyMap.cpp:96
virtual const KeyItem * mapKey(Keystrokes &keys, KeyID id, int32_t group, ModifierToKeys &activeModifiers, KeyModifierMask &currentState, KeyModifierMask desiredMask, bool isAutoRepeat, const std::string &lang) const
Map key press/repeat to keystrokes.
Definition KeyMap.cpp:228
static std::string formatKey(KeyID key, KeyModifierMask)
Get string for a key and modifier mask.
Definition KeyMap.cpp:1079
void allowGroupSwitchDuringCompose()
Enable composition across groups.
Definition KeyMap.cpp:179
static KeyID getDeadKey(KeyID key)
Get corresponding dead key.
Definition KeyMap.cpp:1021
std::map< KeyButton, const KeyItem * > ButtonToKeyMap
A set of buttons.
Definition KeyMap.h:117
static bool isDeadKey(KeyID key)
Test for a dead key.
Definition KeyMap.cpp:1016
std::multimap< KeyModifierMask, KeyItem > ModifierToKeys
A mapping of a modifier to keys for that modifier.
Definition KeyMap.h:114
void clearHalfDuplexModifiers()
Remove all half-duplex modifiers.
Definition KeyMap.cpp:189
virtual void swap(KeyMap &) noexcept
Swap with another KeyMap.
Definition KeyMap.cpp:38
void(*)(KeyID, int32_t group, KeyItem &, void *userData) ForeachKeyCallback
Callback type for foreachKey.
Definition KeyMap.h:120
std::vector< Keystroke > Keystrokes
A sequence of keystrokes.
Definition KeyMap.h:111
static void collectButtons(const ModifierToKeys &modifiers, ButtonToKeyMap &keys)
Get buttons from modifier map.
Definition KeyMap.cpp:365
static bool parseModifiers(std::string &, KeyModifierMask &)
Parse a string into a modifier mask.
Definition KeyMap.cpp:1141
void setLanguageData(std::vector< std::string > layouts)
Definition KeyMap.cpp:297
static bool parseKey(const std::string &, KeyID &)
Parse a string into a key.
Definition KeyMap.cpp:1109
std::vector< KeyItem > KeyItemList
The KeyButtons needed to synthesize a KeyID.
Definition KeyMap.h:68
void addHalfDuplexButton(KeyButton button)
Add a half-duplex button.
Definition KeyMap.cpp:184
friend class KeyMapTests
Definition KeyMap.h:27
static void initModifierKey(KeyItem &item)
Set modifier key state.
Definition KeyMap.cpp:373
void addKeyEntry(const KeyItem &item)
Add a key entry.
Definition KeyMap.cpp:52
bool addKeyCombinationEntry(KeyID id, int32_t group, const KeyID *keys, uint32_t numKeys)
Add a key sequence entry.
Definition KeyMap.cpp:120
KeyMap()
Definition KeyMap.cpp:25
bool isCommand(KeyModifierMask mask) const
Test if modifiers indicate a command.
Definition KeyMap.cpp:352
virtual void addHalfDuplexModifier(KeyID key)
Add a half-duplex modifier.
Definition KeyMap.cpp:194
virtual ~KeyMap()=default
virtual bool isHalfDuplex(KeyID key, KeyButton button) const
Test if modifier is half-duplex.
Definition KeyMap.cpp:347
virtual void finish()
Finish adding entries.
Definition KeyMap.cpp:199
KeyModifierMask getCommandModifiers() const
Definition KeyMap.cpp:357
int32_t getNumGroups() const
Get number of groups.
Definition KeyMap.cpp:316
const KeyItemList * findCompatibleKey(KeyID id, int32_t group, KeyModifierMask required, KeyModifierMask sensitive) const
Find key entry compatible with modifiers.
Definition KeyMap.cpp:327
int32_t getEffectiveGroup(int32_t group, int32_t offset) const
Compute a group number.
Definition KeyMap.cpp:321
Definition EventTypes.h:11
KeyID synthesis info.
Definition KeyMap.h:42
int32_t m_group
Group for key.
Definition KeyMap.h:45
KeyModifierMask m_generates
Modifiers key is mapped to.
Definition KeyMap.h:49
uint32_t m_client
Client data.
Definition KeyMap.h:52
bool m_lock
true if this locks a modifier
Definition KeyMap.h:51
KeyModifierMask m_sensitive
Modifiers key is sensitive to.
Definition KeyMap.h:48
KeyButton m_button
Button to generate KeyID.
Definition KeyMap.h:46
bool operator==(const KeyItem &) const
Definition KeyMap.cpp:1221
KeyModifierMask m_required
Modifiers required for KeyID.
Definition KeyMap.h:47
bool m_dead
true if this is a dead KeyID
Definition KeyMap.h:50
KeyID m_id
KeyID.
Definition KeyMap.h:44
uint32_t m_client
Client data.
Definition KeyMap.h:90
bool m_repeat
true iff for an autorepeat
Definition KeyMap.h:89
bool m_press
true iff press
Definition KeyMap.h:88
KeyButton m_button
Button to synthesize.
Definition KeyMap.h:87
int32_t m_group
Group/offset to change to/by.
Definition KeyMap.h:95
bool m_absolute
true iff change to, else by
Definition KeyMap.h:96
bool m_restore
true iff for restoring state
Definition KeyMap.h:97
Definition KeyMap.h:100
Button m_button
Definition KeyMap.h:102
Group m_group
Definition KeyMap.h:103