1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "common/system.h"
24 #include "ags/events.h"
25 #include "ags/globals.h"
26
27 namespace AGS {
28
29 EventsManager *g_events;
30
EventsManager()31 EventsManager::EventsManager() {
32 g_events = this;
33 _keys.resize(Common::KEYCODE_LAST);
34 Common::fill(&_joystickAxis[0], &_joystickAxis[32], 0);
35 Common::fill(&_joystickButton[0], &_joystickButton[32], 0);
36 }
37
~EventsManager()38 EventsManager::~EventsManager() {
39 g_events = nullptr;
40 }
41
pollEvents()42 void EventsManager::pollEvents() {
43 Common::Event e;
44
45 while (g_system->getEventManager()->pollEvent(e)) {
46 switch (e.type) {
47 case Common::EVENT_QUIT:
48 case Common::EVENT_RETURN_TO_LAUNCHER:
49 _G(want_exit) = true;
50 _G(abort_engine) = true;
51 _G(check_dynamic_sprites_at_exit) = false;
52 return;
53
54 case Common::EVENT_JOYAXIS_MOTION:
55 assert(e.joystick.axis < 32);
56 _joystickAxis[e.joystick.axis] = e.joystick.position;
57 break;
58
59 case Common::EVENT_JOYBUTTON_DOWN:
60 assert(e.joystick.button < 32);
61 _joystickButton[e.joystick.button] = true;
62 break;
63
64 case Common::EVENT_JOYBUTTON_UP:
65 assert(e.joystick.button < 32);
66 _joystickButton[e.joystick.button] = false;
67 break;
68
69 case Common::EVENT_KEYDOWN:
70 updateKeys(e, true);
71 _keyEvents.push(e);
72 break;
73
74 case Common::EVENT_KEYUP:
75 updateKeys(e, false);
76 break;
77
78 default:
79 if (e.type == Common::EVENT_MOUSEMOVE)
80 _mousePos = Common::Point(e.mouse.x, e.mouse.y);
81
82 // Add other event types to the pending events queue. If the event is a
83 // mouse move and the prior one was also, then discard the prior one.
84 // This'll help prevent too many mouse move events accumulating
85 if (e.type == Common::EVENT_MOUSEMOVE && !_pendingEvents.empty() &&
86 _pendingEvents.back().type == Common::EVENT_MOUSEMOVE)
87 _pendingEvents.back() = e;
88 else
89 _pendingEvents.push(e);
90 break;
91 }
92 }
93 }
94
95 #if 0
96 bool EventsManager::keypressed() {
97 pollEvents();
98 return !_pendingKeys.empty();
99 }
100
101 #define EXTENDED_KEY_CODE ('\0')
102
103 Common::Event EventsManager::readKey() {
104 pollEvents();
105 return _pendingKeys.empty() ? Common::Event() : _pendingKeys.pop();
106 }
107 #endif
108
readEvent()109 Common::Event EventsManager::readEvent() {
110 pollEvents();
111 return _pendingEvents.empty() ? Common::Event() : _pendingEvents.pop();
112 }
113
warpMouse(const Common::Point & newPos)114 void EventsManager::warpMouse(const Common::Point &newPos) {
115 g_system->warpMouse(newPos.x, newPos.y);
116 }
117
isModifierKey(const Common::KeyCode & keycode) const118 bool EventsManager::isModifierKey(const Common::KeyCode &keycode) const {
119 return keycode == Common::KEYCODE_LCTRL || keycode == Common::KEYCODE_LALT
120 || keycode == Common::KEYCODE_RCTRL || keycode == Common::KEYCODE_RALT
121 || keycode == Common::KEYCODE_LSHIFT || keycode == Common::KEYCODE_RSHIFT
122 || keycode == Common::KEYCODE_LSUPER || keycode == Common::KEYCODE_RSUPER
123 || keycode == Common::KEYCODE_CAPSLOCK || keycode == Common::KEYCODE_NUMLOCK
124 || keycode == Common::KEYCODE_SCROLLOCK;
125 }
126
isExtendedKey(const Common::KeyCode & keycode) const127 bool EventsManager::isExtendedKey(const Common::KeyCode &keycode) const {
128 const Common::KeyCode EXTENDED_KEYS[] = {
129 Common::KEYCODE_F1, Common::KEYCODE_F2, Common::KEYCODE_F3,
130 Common::KEYCODE_F4, Common::KEYCODE_F5, Common::KEYCODE_F6,
131 Common::KEYCODE_F7, Common::KEYCODE_F8, Common::KEYCODE_F9,
132 Common::KEYCODE_F10, Common::KEYCODE_F11, Common::KEYCODE_F12,
133 Common::KEYCODE_KP0, Common::KEYCODE_KP1, Common::KEYCODE_KP2,
134 Common::KEYCODE_KP3, Common::KEYCODE_KP4, Common::KEYCODE_KP5,
135 Common::KEYCODE_KP6, Common::KEYCODE_KP7, Common::KEYCODE_KP8,
136 Common::KEYCODE_KP9, Common::KEYCODE_KP_PERIOD,
137 Common::KEYCODE_INSERT, Common::KEYCODE_DELETE,
138 Common::KEYCODE_HOME, Common::KEYCODE_END,
139 Common::KEYCODE_PAGEUP, Common::KEYCODE_PAGEDOWN,
140 Common::KEYCODE_LEFT, Common::KEYCODE_RIGHT,
141 Common::KEYCODE_UP, Common::KEYCODE_DOWN,
142 Common::KEYCODE_INVALID
143 };
144
145 for (const Common::KeyCode *kc = EXTENDED_KEYS;
146 *kc != Common::KEYCODE_INVALID; ++kc) {
147 if (keycode == *kc)
148 return true;
149 }
150
151 return false;
152 }
153
updateKeys(const Common::Event & event,bool isDown)154 void EventsManager::updateKeys(const Common::Event &event, bool isDown) {
155 _keyModifierFlags = event.kbd.flags;
156
157 _keys[event.kbd.keycode] = isDown;
158 }
159
isKeyPressed(AGS3::eAGSKeyCode key)160 bool EventsManager::isKeyPressed(AGS3::eAGSKeyCode key) {
161 pollEvents();
162
163 Common::KeyCode kc[3];
164 if (!ags_key_to_scancode(key, kc))
165 return false;
166
167 return (kc[0] != Common::KEYCODE_INVALID && _keys[kc[0]]) ||
168 (kc[1] != Common::KEYCODE_INVALID && _keys[kc[1]]) ||
169 (kc[2] != Common::KEYCODE_INVALID && _keys[kc[2]]);
170 }
171
ags_key_to_scancode(AGS3::eAGSKeyCode key,Common::KeyCode (& kc)[3])172 bool EventsManager::ags_key_to_scancode(AGS3::eAGSKeyCode key, Common::KeyCode(&kc)[3]) {
173 kc[0] = Common::KEYCODE_INVALID;
174 kc[1] = Common::KEYCODE_INVALID;
175 kc[2] = Common::KEYCODE_INVALID;
176 Common::KeyCode sym = Common::KEYCODE_INVALID;
177
178 // SDL sym codes happen to match small ASCII letters, so lowercase ours if necessary
179 if (key >= AGS3::eAGSKeyCodeA && key <= AGS3::eAGSKeyCodeZ) {
180 sym = static_cast<Common::KeyCode>(key - AGS3::eAGSKeyCodeA + Common::KEYCODE_a);
181 }
182 // Rest of the printable characters seem to match (and match ascii codes)
183 else if (key >= AGS3::eAGSKeyCodeSpace && key <= AGS3::eAGSKeyCodeBackquote) {
184 sym = static_cast<Common::KeyCode>(key);
185 }
186
187 if (sym != Common::KEYCODE_INVALID) {
188 kc[0] = sym;
189 return true;
190 }
191
192 // Other keys are mapped directly to scancode (based on [sonneveld]'s code)
193 switch (key) {
194 case AGS3::eAGSKeyCodeBackspace:
195 kc[0] = Common::KEYCODE_BACKSPACE;
196 return true;
197 case AGS3::eAGSKeyCodeTab:
198 kc[0] = Common::KEYCODE_TAB;
199 return true;
200 case AGS3::eAGSKeyCodeReturn:
201 kc[0] = Common::KEYCODE_RETURN;
202 kc[1] = Common::KEYCODE_KP_ENTER;
203 return true;
204 case AGS3::eAGSKeyCodeEscape:
205 kc[0] = Common::KEYCODE_ESCAPE;
206 return true;
207
208 case AGS3::eAGSKeyCodeF1:
209 kc[0] = Common::KEYCODE_F1;
210 return true;
211 case AGS3::eAGSKeyCodeF2:
212 kc[0] = Common::KEYCODE_F2;
213 return true;
214 case AGS3::eAGSKeyCodeF3:
215 kc[0] = Common::KEYCODE_F3;
216 return true;
217 case AGS3::eAGSKeyCodeF4:
218 kc[0] = Common::KEYCODE_F4;
219 return true;
220 case AGS3::eAGSKeyCodeF5:
221 kc[0] = Common::KEYCODE_F5;
222 return true;
223 case AGS3::eAGSKeyCodeF6:
224 kc[0] = Common::KEYCODE_F6;
225 return true;
226 case AGS3::eAGSKeyCodeF7:
227 kc[0] = Common::KEYCODE_F7;
228 return true;
229 case AGS3::eAGSKeyCodeF8:
230 kc[0] = Common::KEYCODE_F8;
231 return true;
232 case AGS3::eAGSKeyCodeF9:
233 kc[0] = Common::KEYCODE_F9;
234 return true;
235 case AGS3::eAGSKeyCodeF10:
236 kc[0] = Common::KEYCODE_F10;
237 return true;
238 case AGS3::eAGSKeyCodeF11:
239 kc[0] = Common::KEYCODE_F11;
240 return true;
241 case AGS3::eAGSKeyCodeF12:
242 kc[0] = Common::KEYCODE_F12;
243 return true;
244
245 case AGS3::eAGSKeyCodeHome:
246 kc[0] = Common::KEYCODE_KP7;
247 kc[1] = Common::KEYCODE_HOME;
248 return true;
249 case AGS3::eAGSKeyCodeUpArrow:
250 kc[0] = Common::KEYCODE_KP8;
251 kc[1] = Common::KEYCODE_UP;
252 return true;
253 case AGS3::eAGSKeyCodePageUp:
254 kc[0] = Common::KEYCODE_KP9;
255 kc[1] = Common::KEYCODE_PAGEUP;
256 return true;
257 case AGS3::eAGSKeyCodeLeftArrow:
258 kc[0] = Common::KEYCODE_KP4;
259 kc[1] = Common::KEYCODE_LEFT;
260 return true;
261 case AGS3::eAGSKeyCodeNumPad5:
262 kc[0] = Common::KEYCODE_KP5;
263 return true;
264 case AGS3::eAGSKeyCodeRightArrow:
265 kc[0] = Common::KEYCODE_KP6;
266 kc[1] = Common::KEYCODE_RIGHT;
267 return true;
268 case AGS3::eAGSKeyCodeEnd:
269 kc[0] = Common::KEYCODE_KP1;
270 kc[1] = Common::KEYCODE_END;
271 return true;
272 case AGS3::eAGSKeyCodeDownArrow:
273 kc[0] = Common::KEYCODE_KP2;
274 kc[1] = Common::KEYCODE_DOWN;
275 return true;
276 case AGS3::eAGSKeyCodePageDown:
277 kc[0] = Common::KEYCODE_KP3;
278 kc[1] = Common::KEYCODE_PAGEDOWN;
279 return true;
280 case AGS3::eAGSKeyCodeInsert:
281 kc[0] = Common::KEYCODE_KP0;
282 kc[1] = Common::KEYCODE_INSERT;
283 return true;
284 case AGS3::eAGSKeyCodeDelete:
285 kc[0] = Common::KEYCODE_KP_PERIOD;
286 kc[1] = Common::KEYCODE_DELETE;
287 return true;
288
289 case AGS3::eAGSKeyCodeLShift:
290 kc[0] = Common::KEYCODE_LSHIFT;
291 return true;
292 case AGS3::eAGSKeyCodeRShift:
293 kc[0] = Common::KEYCODE_RSHIFT;
294 return true;
295 case AGS3::eAGSKeyCodeLCtrl:
296 kc[0] = Common::KEYCODE_LCTRL;
297 return true;
298 case AGS3::eAGSKeyCodeRCtrl:
299 kc[0] = Common::KEYCODE_RCTRL;
300 return true;
301 case AGS3::eAGSKeyCodeLAlt:
302 kc[0] = Common::KEYCODE_LALT;
303 return true;
304 case AGS3::eAGSKeyCodeRAlt:
305 kc[0] = Common::KEYCODE_RALT;
306 return true;
307
308 default:
309 return false;
310 }
311 return false;
312 }
313
scummvm_key_to_ags_key(const Common::Event & event)314 AGS3::eAGSKeyCode EventsManager::scummvm_key_to_ags_key(const Common::Event &event) {
315 if (event.type != Common::EVENT_KEYDOWN)
316 return AGS3::eAGSKeyCodeNone;
317
318 const Common::KeyCode sym = event.kbd.keycode;
319 const uint16 mod = event.kbd.flags;
320
321 // Ctrl and Alt combinations realign the letter code to certain offset
322 if (sym >= Common::KEYCODE_a && sym <= Common::KEYCODE_z) {
323 if ((mod & Common::KBD_CTRL) != 0) // align letters to code 1
324 return static_cast<AGS3::eAGSKeyCode>(0 + (sym - Common::KEYCODE_a) + 1);
325 else if ((mod & Common::KBD_ALT) != 0) // align letters to code 301
326 return static_cast<AGS3::eAGSKeyCode>(AGS_EXT_KEY_SHIFT + (sym - Common::KEYCODE_a) + 1);
327 }
328
329 if (event.kbd.ascii >= 32 && event.kbd.ascii <= 127)
330 return static_cast<AGS3::eAGSKeyCode>(event.kbd.ascii);
331
332 // Remaining codes may match or not, but we use a big table anyway.
333 // TODO: this is code by [sonneveld],
334 // double check that we must use scan codes here, maybe can use sdl key (sym) too?
335 switch (sym) {
336 case Common::KEYCODE_BACKSPACE:
337 return AGS3::eAGSKeyCodeBackspace;
338 case Common::KEYCODE_TAB:
339 return AGS3::eAGSKeyCodeTab;
340 case Common::KEYCODE_RETURN:
341 case Common::KEYCODE_KP_ENTER:
342 return AGS3::eAGSKeyCodeReturn;
343 case Common::KEYCODE_ESCAPE:
344 return AGS3::eAGSKeyCodeEscape;
345
346 case Common::KEYCODE_F1:
347 return AGS3::eAGSKeyCodeF1;
348 case Common::KEYCODE_F2:
349 return AGS3::eAGSKeyCodeF2;
350 case Common::KEYCODE_F3:
351 return AGS3::eAGSKeyCodeF3;
352 case Common::KEYCODE_F4:
353 return AGS3::eAGSKeyCodeF4;
354 case Common::KEYCODE_F5:
355 return AGS3::eAGSKeyCodeF5;
356 case Common::KEYCODE_F6:
357 return AGS3::eAGSKeyCodeF6;
358 case Common::KEYCODE_F7:
359 return AGS3::eAGSKeyCodeF7;
360 case Common::KEYCODE_F8:
361 return AGS3::eAGSKeyCodeF8;
362 case Common::KEYCODE_F9:
363 return AGS3::eAGSKeyCodeF9;
364 case Common::KEYCODE_F10:
365 return AGS3::eAGSKeyCodeF10;
366 case Common::KEYCODE_F11:
367 return AGS3::eAGSKeyCodeF11;
368 case Common::KEYCODE_F12:
369 return AGS3::eAGSKeyCodeF12;
370
371 case Common::KEYCODE_KP7:
372 case Common::KEYCODE_HOME:
373 return AGS3::eAGSKeyCodeHome;
374 case Common::KEYCODE_KP8:
375 case Common::KEYCODE_UP:
376 return AGS3::eAGSKeyCodeUpArrow;
377 case Common::KEYCODE_KP9:
378 case Common::KEYCODE_PAGEUP:
379 return AGS3::eAGSKeyCodePageUp;
380 case Common::KEYCODE_KP4:
381 case Common::KEYCODE_LEFT:
382 return AGS3::eAGSKeyCodeLeftArrow;
383 case Common::KEYCODE_KP5:
384 return AGS3::eAGSKeyCodeNumPad5;
385 case Common::KEYCODE_KP6:
386 case Common::KEYCODE_RIGHT:
387 return AGS3::eAGSKeyCodeRightArrow;
388 case Common::KEYCODE_KP1:
389 case Common::KEYCODE_END:
390 return AGS3::eAGSKeyCodeEnd;
391 case Common::KEYCODE_KP2:
392 case Common::KEYCODE_DOWN:
393 return AGS3::eAGSKeyCodeDownArrow;
394 case Common::KEYCODE_KP3:
395 case Common::KEYCODE_PAGEDOWN:
396 return AGS3::eAGSKeyCodePageDown;
397 case Common::KEYCODE_KP0:
398 case Common::KEYCODE_INSERT:
399 return AGS3::eAGSKeyCodeInsert;
400 case Common::KEYCODE_KP_PERIOD:
401 case Common::KEYCODE_DELETE:
402 return AGS3::eAGSKeyCodeDelete;
403
404 default:
405 return AGS3::eAGSKeyCodeNone;
406 }
407
408 return AGS3::eAGSKeyCodeNone;
409 }
410
411 } // namespace AGS
412