Remove Mac OS support
[lsnes.git] / src / platform / wxwidgets / keyboard.cpp
blobbb79bfdc521b15efe1346b200e1e18350ea29009
1 #include <wx/wx.h>
2 #include <wx/event.h>
3 #include <wx/control.h>
4 #include <wx/combobox.h>
6 #include "library/keyboard.hpp"
7 #include "library/keyboard-mapper.hpp"
8 #include "core/instance.hpp"
9 #include "core/instance-map.hpp"
10 #include "core/queue.hpp"
11 #include "core/window.hpp"
12 #include "core/ui-services.hpp"
13 #include "platform/wxwidgets/platform.hpp"
15 #include <cstdint>
16 #include <map>
18 int wx_escape_count = 0;
20 namespace
22 //Modifier table.
23 struct modifier_entry
25 int mod;
26 const char* name;
27 const char* lname;
28 } modifiers[] = {
29 { wxMOD_ALT, "alt", NULL },
30 { wxMOD_CONTROL, "ctrl", NULL },
31 { wxMOD_SHIFT, "shift", NULL },
32 { wxMOD_META, "meta", NULL },
33 { 0, NULL, NULL }
36 struct key_entry
38 int keynum;
39 const char* name;
40 const char* clazz;
41 } keys[] = {
42 { WXK_BACK, "back", "editing" },
43 { WXK_TAB, "tab", "editing" },
44 { WXK_RETURN, "return", "editing" },
45 { WXK_ESCAPE, "escape", "editing" },
46 { WXK_SPACE, "space", "characters" },
47 { 33, "exclaim", "characters" },
48 { 34, "quotedbl", "characters" },
49 { 35, "hash", "characters" },
50 { 36, "dollar", "characters" },
51 { 37, "percent", "characters" },
52 { 38, "ampersand", "characters" },
53 { 39, "quote", "characters" },
54 { 40, "leftparen", "characters" },
55 { 41, "rightparen", "characters" },
56 { 42, "asterisk", "characters" },
57 { 43, "plus", "characters" },
58 { 44, "comma", "characters" },
59 { 45, "minus", "characters" },
60 { 46, "period", "characters" },
61 { 47, "slash", "characters" },
62 { 48, "0", "numeric" },
63 { 49, "1", "numeric" },
64 { 50, "2", "numeric" },
65 { 51, "3", "numeric" },
66 { 52, "4", "numeric" },
67 { 53, "5", "numeric" },
68 { 54, "6", "numeric" },
69 { 55, "7", "numeric" },
70 { 56, "8", "numeric" },
71 { 57, "9", "numeric" },
72 { 58, "colon", "characters" },
73 { 59, "semicolon", "characters" },
74 { 60, "less", "characters" },
75 { 61, "equals", "characters" },
76 { 62, "greater", "characters" },
77 { 63, "question", "characters" },
78 { 64, "at", "characters" },
79 { 65, "a", "alphabetic" },
80 { 66, "b", "alphabetic" },
81 { 67, "c", "alphabetic" },
82 { 68, "d", "alphabetic" },
83 { 69, "e", "alphabetic" },
84 { 70, "f", "alphabetic" },
85 { 71, "g", "alphabetic" },
86 { 72, "h", "alphabetic" },
87 { 73, "i", "alphabetic" },
88 { 74, "j", "alphabetic" },
89 { 75, "k", "alphabetic" },
90 { 76, "l", "alphabetic" },
91 { 77, "m", "alphabetic" },
92 { 78, "n", "alphabetic" },
93 { 79, "o", "alphabetic" },
94 { 80, "p", "alphabetic" },
95 { 81, "q", "alphabetic" },
96 { 82, "r", "alphabetic" },
97 { 83, "s", "alphabetic" },
98 { 84, "t", "alphabetic" },
99 { 85, "u", "alphabetic" },
100 { 86, "v", "alphabetic" },
101 { 87, "w", "alphabetic" },
102 { 88, "x", "alphabetic" },
103 { 89, "y", "alphabetic" },
104 { 90, "z", "alphabetic" },
105 { 91, "leftbracket", "characters" },
106 { 92, "backslash", "characters" },
107 { 93, "rightbracket", "characters" },
108 { 94, "caret", "characters" },
109 { 95, "underscore", "characters" },
110 { 96, "backquote", "characters" },
111 { 97, "a", "alphabetic" },
112 { 98, "b", "alphabetic" },
113 { 99, "c", "alphabetic" },
114 { 100, "d", "alphabetic" },
115 { 101, "e", "alphabetic" },
116 { 102, "f", "alphabetic" },
117 { 103, "g", "alphabetic" },
118 { 104, "h", "alphabetic" },
119 { 105, "i", "alphabetic" },
120 { 106, "j", "alphabetic" },
121 { 107, "k", "alphabetic" },
122 { 108, "l", "alphabetic" },
123 { 109, "m", "alphabetic" },
124 { 110, "n", "alphabetic" },
125 { 111, "o", "alphabetic" },
126 { 112, "p", "alphabetic" },
127 { 113, "q", "alphabetic" },
128 { 114, "r", "alphabetic" },
129 { 115, "s", "alphabetic" },
130 { 116, "t", "alphabetic" },
131 { 117, "u", "alphabetic" },
132 { 118, "v", "alphabetic" },
133 { 119, "w", "alphabetic" },
134 { 120, "x", "alphabetic" },
135 { 121, "y", "alphabetic" },
136 { 122, "z", "alphabetic" },
137 { 123, "leftcurly", "characters" },
138 { 124, "pipe", "characters" },
139 { 125, "rightcurly", "characters" },
140 { 126, "tilde", "characters" },
141 { WXK_DELETE, "delete", "editing" },
142 { WXK_START, "start", "special" },
143 { WXK_LBUTTON, "lbutton", "special" },
144 { WXK_RBUTTON, "rbutton", "special" },
145 { WXK_CANCEL, "cancel", "special" },
146 { WXK_MBUTTON, "mbutton", "special" },
147 { WXK_CLEAR, "clear", "editing" },
148 { WXK_SHIFT, "shift", "modifiers" },
149 { WXK_ALT, "alt", "modifiers" },
150 { WXK_CONTROL, "control", "modifiers" },
151 { WXK_MENU, "menu", "special" },
152 { WXK_PAUSE, "pause", "special" },
153 { WXK_CAPITAL, "capital", "locks" },
154 { WXK_END, "end", "editing" },
155 { WXK_HOME, "home", "editing" },
156 { WXK_LEFT, "lefT", "editing" },
157 { WXK_UP, "up", "editing" },
158 { WXK_RIGHT, "right", "editing" },
159 { WXK_DOWN, "down", "editing" },
160 { WXK_SELECT, "select", "special" },
161 { WXK_PRINT, "print", "special" },
162 { WXK_EXECUTE, "execute", "special" },
163 { WXK_SNAPSHOT, "snapshot", "special" },
164 { WXK_INSERT, "insert", "editing" },
165 { WXK_HELP, "help", "special" },
166 { WXK_NUMPAD0, "numpad0", "numeric" },
167 { WXK_NUMPAD1, "numpad1", "numeric" },
168 { WXK_NUMPAD2, "numpad2", "numeric" },
169 { WXK_NUMPAD3, "numpad3", "numeric" },
170 { WXK_NUMPAD4, "numpad4", "numeric" },
171 { WXK_NUMPAD5, "numpad5", "numeric" },
172 { WXK_NUMPAD6, "numpad6", "numeric" },
173 { WXK_NUMPAD7, "numpad7", "numeric" },
174 { WXK_NUMPAD8, "numpad8", "numeric" },
175 { WXK_NUMPAD9, "numpad9", "numeric" },
176 { WXK_MULTIPLY, "multiply", "characters" },
177 { WXK_ADD, "add", "characters" },
178 { WXK_SEPARATOR, "separator", "characters" },
179 { WXK_SUBTRACT, "subtract", "characters" },
180 { WXK_DECIMAL, "decimal", "characters" },
181 { WXK_DIVIDE, "divide", "characters" },
182 { WXK_F1, "f1", "F-keys" },
183 { WXK_F2, "f2", "F-keys" },
184 { WXK_F3, "f3", "F-keys" },
185 { WXK_F4, "f4", "F-keys" },
186 { WXK_F5, "f5", "F-keys" },
187 { WXK_F6, "f6", "F-keys" },
188 { WXK_F7, "f7", "F-keys" },
189 { WXK_F8, "f8", "F-keys" },
190 { WXK_F9, "f9", "F-keys" },
191 { WXK_F10, "f10", "F-keys" },
192 { WXK_F11, "f11", "F-keys" },
193 { WXK_F12, "f12", "F-keys" },
194 { WXK_F13, "f13", "F-keys" },
195 { WXK_F14, "f14", "F-keys" },
196 { WXK_F15, "f15", "F-keys" },
197 { WXK_F16, "f16", "F-keys" },
198 { WXK_F17, "f17", "F-keys" },
199 { WXK_F18, "f18", "F-keys" },
200 { WXK_F19, "f19", "F-keys" },
201 { WXK_F20, "f20", "F-keys" },
202 { WXK_F21, "f21", "F-keys" },
203 { WXK_F22, "f22", "F-keys" },
204 { WXK_F23, "f23", "F-keys" },
205 { WXK_F24, "f24", "F-keys" },
206 { WXK_NUMLOCK, "numlock", "locks" },
207 { WXK_SCROLL, "scroll", "locks" },
208 { WXK_PAGEUP, "pageup", "editing" },
209 { WXK_PAGEDOWN, "pagedown", "editing" },
210 { WXK_NUMPAD_SPACE, "numpad_space", "editing" },
211 { WXK_NUMPAD_TAB, "numpad_tab", "editing" },
212 { WXK_NUMPAD_ENTER, "numpad_enter", "editing" },
213 { WXK_NUMPAD_F1, "numpad_f1", "F-keys" },
214 { WXK_NUMPAD_F2, "numpad_f2", "F-keys" },
215 { WXK_NUMPAD_F3, "numpad_f3", "F-keys" },
216 { WXK_NUMPAD_F4, "numpad_f4", "F-keys" },
217 { WXK_NUMPAD_HOME, "numpad_home", "editing" },
218 { WXK_NUMPAD_LEFT, "numpad_left", "editing" },
219 { WXK_NUMPAD_UP, "numpad_up", "editing" },
220 { WXK_NUMPAD_RIGHT, "numpad_right", "editing" },
221 { WXK_NUMPAD_DOWN, "numpad_down", "editing" },
222 { WXK_NUMPAD_PAGEUP, "numpad_pageup", "editing" },
223 { WXK_NUMPAD_PAGEDOWN, "numpad_pagedown", "editing" },
224 { WXK_NUMPAD_END, "numpad_end", "editing" },
225 { WXK_NUMPAD_BEGIN, "numpad_begin", "editing" },
226 { WXK_NUMPAD_INSERT, "numpad_insert", "editing" },
227 { WXK_NUMPAD_DELETE, "numpad_delete", "editing" },
228 { WXK_NUMPAD_EQUAL, "numpad_equal", "characters" },
229 { WXK_NUMPAD_MULTIPLY, "numpad_multiply", "characters" },
230 { WXK_NUMPAD_ADD, "numpad_add", "characters" },
231 { WXK_NUMPAD_SEPARATOR, "numpad_separator", "characters" },
232 { WXK_NUMPAD_SUBTRACT, "numpad_subtract", "characters" },
233 { WXK_NUMPAD_DECIMAL, "numpad_decimal", "characters" },
234 { WXK_NUMPAD_DIVIDE, "numpad_divide", "characters" },
235 { WXK_WINDOWS_LEFT, "windows_left", "modifiers" },
236 { WXK_WINDOWS_RIGHT, "windows_right", "modifiers" },
237 { WXK_WINDOWS_MENU, "windows_menu", "modifiers" },
238 { WXK_COMMAND, "command", "special" },
239 { WXK_SPECIAL1, "special1", "special" },
240 { WXK_SPECIAL2, "special2", "special" },
241 { WXK_SPECIAL3, "special3", "special" },
242 { WXK_SPECIAL4, "special4", "special" },
243 { WXK_SPECIAL5, "special5", "special" },
244 { WXK_SPECIAL6, "special6", "special" },
245 { WXK_SPECIAL7, "special7", "special" },
246 { WXK_SPECIAL8, "special8", "special" },
247 { WXK_SPECIAL9, "special9", "special" },
248 { WXK_SPECIAL10, "special10", "special" },
249 { WXK_SPECIAL11, "special11", "special" },
250 { WXK_SPECIAL12, "special12", "special" },
251 { WXK_SPECIAL13, "special13", "special" },
252 { WXK_SPECIAL14, "special14", "special" },
253 { WXK_SPECIAL15, "special15", "special" },
254 { WXK_SPECIAL16, "special16", "special" },
255 { WXK_SPECIAL17, "special17", "special" },
256 { WXK_SPECIAL18, "special18", "special" },
257 { WXK_SPECIAL19, "special19", "special" },
258 { WXK_SPECIAL20, "special20", "special" },
259 { 167, "§", "characters" },
260 { 246, "ö", "alphabetic" },
261 { 228, "ä", "alphabetic" },
262 { 229, "å", "alphabetic" },
263 { 0, NULL, NULL }
266 struct keyboard_state
268 keyboard_state(emulator_instance& inst)
271 ~keyboard_state()
273 modifier_map.clear();
274 key_map.clear();
275 keys_allocated.clear();
276 keys_held.clear();
277 for(auto& m : mallocated)
278 delete m.second;
279 for(auto& k : kallocated)
280 delete k.second;
281 mallocated.clear();
282 kallocated.clear();
284 std::map<int, keyboard::modifier*> modifier_map;
285 std::map<int, keyboard::key_key*> key_map;
286 std::map<std::string, int> keys_allocated;
287 std::set<int> keys_held;
288 std::map<modifier_entry*, keyboard::modifier*> mallocated;
289 std::map<key_entry*, keyboard::key_key*> kallocated;
291 instance_map<keyboard_state> keyboard_states;
294 std::string map_keycode_to_key(int kcode)
296 key_entry* k = keys;
297 while(k->name) {
298 if(k->keynum == kcode)
299 return k->name;
300 k++;
302 std::cerr << "map_keycode_to_key: Unknown key " << kcode << std::endl;
303 return "";
306 void handle_wx_keyboard(emulator_instance& inst, wxKeyEvent& e, bool polarity)
308 CHECK_UI_THREAD;
309 auto s = keyboard_states.lookup(inst);
310 if(!s) return;
311 int mods = e.GetModifiers();
312 int keyc = e.GetKeyCode();
313 if(polarity) {
314 if(keyc == WXK_ESCAPE)
315 wx_escape_count++;
316 else
317 wx_escape_count = 0;
319 keyboard::modifier_set mset;
320 for(auto m : s->mallocated) {
321 if((mods & m.first->mod) == m.first->mod) {
322 mset.add(*m.second);
325 if(polarity) {
326 if(s->keys_held.count(keyc)) {
327 e.Skip();
328 return;
330 s->keys_held.insert(keyc);
331 } else
332 s->keys_held.erase(keyc);
333 keyboard::key_key* grp = NULL;
334 for(auto k : s->kallocated) {
335 if(k.first->keynum == keyc) {
336 grp = k.second;
337 break;
340 if(grp)
341 UI_do_keypress(inst, mset, *grp, polarity);
342 e.Skip();
345 void initialize_wx_keyboard(emulator_instance& inst)
347 if(keyboard_states.exists(inst))
348 return;
349 auto s = keyboard_states.create(inst);
350 modifier_entry* m = modifiers;
351 while(m->name) {
352 if(m->lname)
353 s->mallocated[m] = new keyboard::modifier(*inst.keyboard, m->name, m->lname);
354 else
355 s->mallocated[m] = new keyboard::modifier(*inst.keyboard, m->name);
356 s->modifier_map[m->mod] = s->mallocated[m];
357 m++;
359 key_entry* k = keys;
360 while(k->name) {
361 if(!s->keys_allocated.count(k->name)) {
362 s->kallocated[k] = new keyboard::key_key(*inst.keyboard, k->name, k->clazz);
363 s->key_map[k->keynum] = s->kallocated[k];
364 s->keys_allocated[k->name] = k->keynum;
365 } else
366 s->key_map[k->keynum] = s->key_map[s->keys_allocated[k->name]];
367 k++;
371 void deinitialize_wx_keyboard(emulator_instance& inst)
373 keyboard_states.destroy(inst);