1 | //============================================================================ |
2 | // |
3 | // SSSS tt lll lll |
4 | // SS SS tt ll ll |
5 | // SS tttttt eeee ll ll aaaa |
6 | // SSSS tt ee ee ll ll aa |
7 | // SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" |
8 | // SS SS tt ee ll ll aa aa |
9 | // SSSS ttt eeeee llll llll aaaaa |
10 | // |
11 | // Copyright (c) 1995-2019 by Bradford W. Mott, Stephen Anthony |
12 | // and the Stella Team |
13 | // |
14 | // See the file "License.txt" for information on usage and redistribution of |
15 | // this file, and for a DISCLAIMER OF ALL WARRANTIES. |
16 | //============================================================================ |
17 | |
18 | #ifndef KEYMAP_HXX |
19 | #define KEYMAP_HXX |
20 | |
21 | #include <unordered_map> |
22 | #include "Event.hxx" |
23 | #include "EventHandlerConstants.hxx" |
24 | |
25 | /** |
26 | This class handles keyboard mappings in Stella. |
27 | |
28 | @author Thomas Jentzsch |
29 | */ |
30 | class KeyMap |
31 | { |
32 | public: |
33 | |
34 | struct Mapping |
35 | { |
36 | EventMode mode; |
37 | StellaKey key; |
38 | StellaMod mod; |
39 | |
40 | Mapping() : mode(EventMode(0)), key(StellaKey(0)), mod(StellaMod(0)) { } |
41 | Mapping(const Mapping& m) : mode(m.mode), key(m.key), mod(m.mod) { } |
42 | explicit Mapping(EventMode c_mode, StellaKey c_key, StellaMod c_mod) |
43 | : mode(c_mode), key(c_key), mod(c_mod) { } |
44 | explicit Mapping(EventMode c_mode, int c_key, int c_mod) |
45 | : mode(c_mode), key(StellaKey(c_key)), mod(StellaMod(c_mod)) { } |
46 | |
47 | bool operator==(const Mapping& other) const |
48 | { |
49 | return (key == other.key |
50 | && mode == other.mode |
51 | && (((mod | other.mod) & KBDM_SHIFT) ? (mod & other.mod & KBDM_SHIFT) : true) |
52 | && (((mod | other.mod) & KBDM_CTRL ) ? (mod & other.mod & KBDM_CTRL ) : true) |
53 | && (((mod | other.mod) & KBDM_ALT ) ? (mod & other.mod & KBDM_ALT ) : true) |
54 | && (((mod | other.mod) & KBDM_GUI ) ? (mod & other.mod & KBDM_GUI ) : true) |
55 | ); |
56 | } |
57 | }; |
58 | using MappingArray = std::vector<Mapping>; |
59 | |
60 | KeyMap(); |
61 | virtual ~KeyMap() = default; |
62 | |
63 | /** Add new mapping for given event */ |
64 | void add(const Event::Type event, const Mapping& mapping); |
65 | void add(const Event::Type event, const EventMode mode, const int key, const int mod); |
66 | |
67 | /** Erase mapping */ |
68 | void erase(const Mapping& mapping); |
69 | void erase(const EventMode mode, const int key, const int mod); |
70 | |
71 | /** Get event for mapping */ |
72 | Event::Type get(const Mapping& mapping) const; |
73 | Event::Type get(const EventMode mode, const int key, const int mod) const; |
74 | |
75 | /** Check if a mapping exists */ |
76 | bool check(const Mapping& mapping) const; |
77 | bool check(const EventMode mode, const int key, const int mod) const; |
78 | |
79 | /** Get mapping description */ |
80 | string getDesc(const Mapping& mapping) const; |
81 | string getDesc(const EventMode mode, const int key, const int mod) const; |
82 | |
83 | /** Get the mapping description(s) for given event and mode */ |
84 | string getEventMappingDesc(const Event::Type event, const EventMode mode) const; |
85 | |
86 | MappingArray getEventMapping(const Event::Type event, const EventMode mode) const; |
87 | |
88 | string saveMapping(const EventMode mode) const; |
89 | int loadMapping(string& list, const EventMode mode); |
90 | |
91 | /** Erase all mappings for given mode */ |
92 | void eraseMode(const EventMode mode); |
93 | /** Erase given event's mapping for given mode */ |
94 | void eraseEvent(const Event::Type event, const EventMode mode); |
95 | /** clear all mappings for a modes */ |
96 | // void clear() { myMap.clear(); } |
97 | size_t size() { return myMap.size(); } |
98 | |
99 | bool& enableMod() { return myModEnabled; } |
100 | |
101 | private: |
102 | //** Convert modifiers */ |
103 | Mapping convertMod(const Mapping& mapping) const; |
104 | |
105 | struct KeyHash { |
106 | size_t operator()(const Mapping& m) const { |
107 | return std::hash<uInt64>()((uInt64(m.mode)) // 3 bits |
108 | + ((uInt64(m.key)) * 7) // 8 bits |
109 | + (((uInt64((m.mod & KBDM_SHIFT) != 0) << 0)) // 1 bit |
110 | | ((uInt64((m.mod & KBDM_ALT ) != 0) << 1)) // 1 bit |
111 | | ((uInt64((m.mod & KBDM_GUI ) != 0) << 2)) // 1 bit |
112 | | ((uInt64((m.mod & KBDM_CTRL ) != 0) << 3)) // 1 bit |
113 | ) * 2047 |
114 | ); |
115 | } |
116 | }; |
117 | |
118 | std::unordered_map<Mapping, Event::Type, KeyHash> myMap; |
119 | |
120 | // Indicates whether the key-combos tied to a modifier key are |
121 | // being used or not (e.g. Ctrl by default is the fire button, |
122 | // pressing it with a movement key could inadvertantly activate |
123 | // a Ctrl combo when it isn't wanted) |
124 | bool myModEnabled; |
125 | }; |
126 | |
127 | #endif |
128 | |