mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-14 21:59:17 +00:00
ae0609ae51
From upstream 8c456d2e4b3c9e24f883522b59b4c73d422e4c28 Not sure if this will actually do so, since there may be other places in the ScummVM event handler where event polling may be done.
437 lines
13 KiB
C++
437 lines
13 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include "common/system.h"
|
|
#include "ags/events.h"
|
|
#include "ags/globals.h"
|
|
#include "ags/shared/ac/keycode.h"
|
|
|
|
namespace AGS {
|
|
|
|
EventsManager *g_events;
|
|
|
|
EventsManager::EventsManager() {
|
|
g_events = this;
|
|
_keys.resize(Common::KEYCODE_LAST);
|
|
Common::fill(&_joystickAxis[0], &_joystickAxis[32], 0);
|
|
Common::fill(&_joystickButton[0], &_joystickButton[32], 0);
|
|
}
|
|
|
|
EventsManager::~EventsManager() {
|
|
g_events = nullptr;
|
|
}
|
|
|
|
void EventsManager::pollEvents() {
|
|
Common::Event e;
|
|
|
|
while (g_system->getEventManager()->pollEvent(e)) {
|
|
switch (e.type) {
|
|
case Common::EVENT_QUIT:
|
|
case Common::EVENT_RETURN_TO_LAUNCHER:
|
|
_G(want_exit) = true;
|
|
_G(abort_engine) = true;
|
|
_G(check_dynamic_sprites_at_exit) = false;
|
|
return;
|
|
|
|
case Common::EVENT_JOYAXIS_MOTION:
|
|
assert(e.joystick.axis < 32);
|
|
_joystickAxis[e.joystick.axis] = e.joystick.position;
|
|
break;
|
|
|
|
case Common::EVENT_JOYBUTTON_DOWN:
|
|
assert(e.joystick.button < 32);
|
|
_joystickButton[e.joystick.button] = true;
|
|
break;
|
|
|
|
case Common::EVENT_JOYBUTTON_UP:
|
|
assert(e.joystick.button < 32);
|
|
_joystickButton[e.joystick.button] = false;
|
|
break;
|
|
|
|
case Common::EVENT_KEYDOWN:
|
|
updateKeys(e, true);
|
|
_keyEvents.push(e);
|
|
break;
|
|
|
|
case Common::EVENT_KEYUP:
|
|
updateKeys(e, false);
|
|
break;
|
|
|
|
default:
|
|
if (e.type == Common::EVENT_MOUSEMOVE)
|
|
_mousePos = Common::Point(e.mouse.x, e.mouse.y);
|
|
|
|
// Add other event types to the pending events queue. If the event is a
|
|
// mouse move and the prior one was also, then discard the prior one.
|
|
// This'll help prevent too many mouse move events accumulating
|
|
if (e.type == Common::EVENT_MOUSEMOVE && !_pendingEvents.empty() &&
|
|
_pendingEvents.back().type == Common::EVENT_MOUSEMOVE)
|
|
_pendingEvents.back() = e;
|
|
else
|
|
_pendingEvents.push(e);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
bool EventsManager::keypressed() {
|
|
pollEvents();
|
|
return !_pendingKeys.empty();
|
|
}
|
|
|
|
#define EXTENDED_KEY_CODE ('\0')
|
|
|
|
Common::Event EventsManager::readKey() {
|
|
pollEvents();
|
|
return _pendingKeys.empty() ? Common::Event() : _pendingKeys.pop();
|
|
}
|
|
#endif
|
|
|
|
Common::Event EventsManager::readEvent() {
|
|
pollEvents();
|
|
return _pendingEvents.empty() ? Common::Event() : _pendingEvents.pop();
|
|
}
|
|
|
|
void EventsManager::warpMouse(const Common::Point &newPos) {
|
|
g_system->warpMouse(newPos.x, newPos.y);
|
|
}
|
|
|
|
bool EventsManager::isModifierKey(const Common::KeyCode &keycode) const {
|
|
return keycode == Common::KEYCODE_LCTRL || keycode == Common::KEYCODE_LALT
|
|
|| keycode == Common::KEYCODE_RCTRL || keycode == Common::KEYCODE_RALT
|
|
|| keycode == Common::KEYCODE_LSHIFT || keycode == Common::KEYCODE_RSHIFT
|
|
|| keycode == Common::KEYCODE_LSUPER || keycode == Common::KEYCODE_RSUPER
|
|
|| keycode == Common::KEYCODE_CAPSLOCK || keycode == Common::KEYCODE_NUMLOCK
|
|
|| keycode == Common::KEYCODE_SCROLLOCK;
|
|
}
|
|
|
|
bool EventsManager::isExtendedKey(const Common::KeyCode &keycode) const {
|
|
const Common::KeyCode EXTENDED_KEYS[] = {
|
|
Common::KEYCODE_F1, Common::KEYCODE_F2, Common::KEYCODE_F3,
|
|
Common::KEYCODE_F4, Common::KEYCODE_F5, Common::KEYCODE_F6,
|
|
Common::KEYCODE_F7, Common::KEYCODE_F8, Common::KEYCODE_F9,
|
|
Common::KEYCODE_F10, Common::KEYCODE_F11, Common::KEYCODE_F12,
|
|
Common::KEYCODE_KP0, Common::KEYCODE_KP1, Common::KEYCODE_KP2,
|
|
Common::KEYCODE_KP3, Common::KEYCODE_KP4, Common::KEYCODE_KP5,
|
|
Common::KEYCODE_KP6, Common::KEYCODE_KP7, Common::KEYCODE_KP8,
|
|
Common::KEYCODE_KP9, Common::KEYCODE_KP_PERIOD,
|
|
Common::KEYCODE_INSERT, Common::KEYCODE_DELETE,
|
|
Common::KEYCODE_HOME, Common::KEYCODE_END,
|
|
Common::KEYCODE_PAGEUP, Common::KEYCODE_PAGEDOWN,
|
|
Common::KEYCODE_LEFT, Common::KEYCODE_RIGHT,
|
|
Common::KEYCODE_UP, Common::KEYCODE_DOWN,
|
|
Common::KEYCODE_INVALID
|
|
};
|
|
|
|
for (const Common::KeyCode *kc = EXTENDED_KEYS;
|
|
*kc != Common::KEYCODE_INVALID; ++kc) {
|
|
if (keycode == *kc)
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void EventsManager::updateKeys(const Common::Event &event, bool isDown) {
|
|
_keyModifierFlags = event.kbd.flags;
|
|
|
|
_keys[event.kbd.keycode] = isDown;
|
|
}
|
|
|
|
bool EventsManager::isKeyPressed(AGS3::eAGSKeyCode key, bool poll) {
|
|
if (poll)
|
|
pollEvents();
|
|
|
|
Common::KeyCode kc[3];
|
|
if (!ags_key_to_scancode(key, kc))
|
|
return false;
|
|
|
|
return (kc[0] != Common::KEYCODE_INVALID && _keys[kc[0]]) ||
|
|
(kc[1] != Common::KEYCODE_INVALID && _keys[kc[1]]) ||
|
|
(kc[2] != Common::KEYCODE_INVALID && _keys[kc[2]]);
|
|
}
|
|
|
|
bool EventsManager::ags_key_to_scancode(AGS3::eAGSKeyCode key, Common::KeyCode(&kc)[3]) {
|
|
kc[0] = Common::KEYCODE_INVALID;
|
|
kc[1] = Common::KEYCODE_INVALID;
|
|
kc[2] = Common::KEYCODE_INVALID;
|
|
Common::KeyCode sym = Common::KEYCODE_INVALID;
|
|
|
|
// SDL sym codes happen to match small ASCII letters, so lowercase ours if necessary
|
|
if (key >= AGS3::eAGSKeyCodeA && key <= AGS3::eAGSKeyCodeZ) {
|
|
sym = static_cast<Common::KeyCode>(key - AGS3::eAGSKeyCodeA + Common::KEYCODE_a);
|
|
}
|
|
// Rest of the printable characters seem to match (and match ascii codes)
|
|
else if (key >= AGS3::eAGSKeyCodeSpace && key <= AGS3::eAGSKeyCodeBackquote) {
|
|
sym = static_cast<Common::KeyCode>(key);
|
|
}
|
|
|
|
if (sym != Common::KEYCODE_INVALID) {
|
|
kc[0] = sym;
|
|
return true;
|
|
}
|
|
|
|
// Other keys are mapped directly to scancode (based on [sonneveld]'s code)
|
|
switch (key) {
|
|
case AGS3::eAGSKeyCodeBackspace:
|
|
kc[0] = Common::KEYCODE_BACKSPACE;
|
|
return true;
|
|
case AGS3::eAGSKeyCodeTab:
|
|
kc[0] = Common::KEYCODE_TAB;
|
|
return true;
|
|
case AGS3::eAGSKeyCodeReturn:
|
|
kc[0] = Common::KEYCODE_RETURN;
|
|
kc[1] = Common::KEYCODE_KP_ENTER;
|
|
return true;
|
|
case AGS3::eAGSKeyCodeEscape:
|
|
kc[0] = Common::KEYCODE_ESCAPE;
|
|
return true;
|
|
|
|
case AGS3::eAGSKeyCodeF1:
|
|
kc[0] = Common::KEYCODE_F1;
|
|
return true;
|
|
case AGS3::eAGSKeyCodeF2:
|
|
kc[0] = Common::KEYCODE_F2;
|
|
return true;
|
|
case AGS3::eAGSKeyCodeF3:
|
|
kc[0] = Common::KEYCODE_F3;
|
|
return true;
|
|
case AGS3::eAGSKeyCodeF4:
|
|
kc[0] = Common::KEYCODE_F4;
|
|
return true;
|
|
case AGS3::eAGSKeyCodeF5:
|
|
kc[0] = Common::KEYCODE_F5;
|
|
return true;
|
|
case AGS3::eAGSKeyCodeF6:
|
|
kc[0] = Common::KEYCODE_F6;
|
|
return true;
|
|
case AGS3::eAGSKeyCodeF7:
|
|
kc[0] = Common::KEYCODE_F7;
|
|
return true;
|
|
case AGS3::eAGSKeyCodeF8:
|
|
kc[0] = Common::KEYCODE_F8;
|
|
return true;
|
|
case AGS3::eAGSKeyCodeF9:
|
|
kc[0] = Common::KEYCODE_F9;
|
|
return true;
|
|
case AGS3::eAGSKeyCodeF10:
|
|
kc[0] = Common::KEYCODE_F10;
|
|
return true;
|
|
case AGS3::eAGSKeyCodeF11:
|
|
kc[0] = Common::KEYCODE_F11;
|
|
return true;
|
|
case AGS3::eAGSKeyCodeF12:
|
|
kc[0] = Common::KEYCODE_F12;
|
|
return true;
|
|
|
|
case AGS3::eAGSKeyCodeHome:
|
|
kc[0] = Common::KEYCODE_KP7;
|
|
kc[1] = Common::KEYCODE_HOME;
|
|
return true;
|
|
case AGS3::eAGSKeyCodeUpArrow:
|
|
kc[0] = Common::KEYCODE_KP8;
|
|
kc[1] = Common::KEYCODE_UP;
|
|
return true;
|
|
case AGS3::eAGSKeyCodePageUp:
|
|
kc[0] = Common::KEYCODE_KP9;
|
|
kc[1] = Common::KEYCODE_PAGEUP;
|
|
return true;
|
|
case AGS3::eAGSKeyCodeLeftArrow:
|
|
kc[0] = Common::KEYCODE_KP4;
|
|
kc[1] = Common::KEYCODE_LEFT;
|
|
return true;
|
|
case AGS3::eAGSKeyCodeNumPad5:
|
|
kc[0] = Common::KEYCODE_KP5;
|
|
return true;
|
|
case AGS3::eAGSKeyCodeRightArrow:
|
|
kc[0] = Common::KEYCODE_KP6;
|
|
kc[1] = Common::KEYCODE_RIGHT;
|
|
return true;
|
|
case AGS3::eAGSKeyCodeEnd:
|
|
kc[0] = Common::KEYCODE_KP1;
|
|
kc[1] = Common::KEYCODE_END;
|
|
return true;
|
|
case AGS3::eAGSKeyCodeDownArrow:
|
|
kc[0] = Common::KEYCODE_KP2;
|
|
kc[1] = Common::KEYCODE_DOWN;
|
|
return true;
|
|
case AGS3::eAGSKeyCodePageDown:
|
|
kc[0] = Common::KEYCODE_KP3;
|
|
kc[1] = Common::KEYCODE_PAGEDOWN;
|
|
return true;
|
|
case AGS3::eAGSKeyCodeInsert:
|
|
kc[0] = Common::KEYCODE_KP0;
|
|
kc[1] = Common::KEYCODE_INSERT;
|
|
return true;
|
|
case AGS3::eAGSKeyCodeDelete:
|
|
kc[0] = Common::KEYCODE_KP_PERIOD;
|
|
kc[1] = Common::KEYCODE_DELETE;
|
|
return true;
|
|
|
|
case AGS3::eAGSKeyCodeLShift:
|
|
kc[0] = Common::KEYCODE_LSHIFT;
|
|
return true;
|
|
case AGS3::eAGSKeyCodeRShift:
|
|
kc[0] = Common::KEYCODE_RSHIFT;
|
|
return true;
|
|
case AGS3::eAGSKeyCodeLCtrl:
|
|
kc[0] = Common::KEYCODE_LCTRL;
|
|
return true;
|
|
case AGS3::eAGSKeyCodeRCtrl:
|
|
kc[0] = Common::KEYCODE_RCTRL;
|
|
return true;
|
|
case AGS3::eAGSKeyCodeLAlt:
|
|
kc[0] = Common::KEYCODE_LALT;
|
|
return true;
|
|
case AGS3::eAGSKeyCodeRAlt:
|
|
kc[0] = Common::KEYCODE_RALT;
|
|
return true;
|
|
|
|
default:
|
|
return false;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
AGS3::eAGSKeyCode EventsManager::scummvm_key_to_ags_key(const Common::Event &event, int &ags_mod, bool old_keyhandle) {
|
|
if (event.type != Common::EVENT_KEYDOWN)
|
|
return AGS3::eAGSKeyCodeNone;
|
|
|
|
const Common::KeyCode sym = event.kbd.keycode;
|
|
const uint16 mod = event.kbd.flags;
|
|
|
|
// First handle the mods, - these are straightforward
|
|
ags_mod = 0;
|
|
if (mod & Common::KBD_SHIFT) ags_mod |= AGS3::eAGSModLShift;
|
|
if (mod & Common::KBD_CTRL) ags_mod |= AGS3::eAGSModLCtrl;
|
|
if (mod & Common::KBD_ALT) ags_mod |= AGS3::eAGSModLAlt;
|
|
if (mod & Common::KBD_NUM) ags_mod |= AGS3::eAGSModNum;
|
|
if (mod & Common::KBD_CAPS) ags_mod |= AGS3::eAGSModCaps;
|
|
|
|
// Old mode: Ctrl and Alt combinations realign the letter code to certain offset
|
|
if (old_keyhandle && (sym >= Common::KEYCODE_a && sym <= Common::KEYCODE_z)) {
|
|
if ((mod & Common::KBD_CTRL) != 0) // align letters to code 1
|
|
return static_cast<AGS3::eAGSKeyCode>(0 + (sym - Common::KEYCODE_a) + 1);
|
|
else if ((mod & Common::KBD_ALT) != 0) // align letters to code 301
|
|
return static_cast<AGS3::eAGSKeyCode>(AGS_EXT_KEY_SHIFT + (sym - Common::KEYCODE_a) + 1);
|
|
}
|
|
// New mode: also handle common key range
|
|
else if (!old_keyhandle && (sym >= Common::KEYCODE_SPACE && sym <= Common::KEYCODE_z)) {
|
|
return static_cast<AGS3::eAGSKeyCode>(sym);
|
|
}
|
|
|
|
if (event.kbd.ascii >= 32 && event.kbd.ascii <= 127)
|
|
return static_cast<AGS3::eAGSKeyCode>(event.kbd.ascii);
|
|
|
|
// Remaining codes may match or not, but we use a big table anyway.
|
|
// TODO: this is code by [sonneveld],
|
|
// double check that we must use scan codes here, maybe can use sdl key (sym) too?
|
|
switch (sym) {
|
|
case Common::KEYCODE_BACKSPACE:
|
|
return AGS3::eAGSKeyCodeBackspace;
|
|
case Common::KEYCODE_TAB:
|
|
return AGS3::eAGSKeyCodeTab;
|
|
case Common::KEYCODE_RETURN:
|
|
case Common::KEYCODE_KP_ENTER:
|
|
return AGS3::eAGSKeyCodeReturn;
|
|
case Common::KEYCODE_ESCAPE:
|
|
return AGS3::eAGSKeyCodeEscape;
|
|
|
|
case Common::KEYCODE_F1:
|
|
return AGS3::eAGSKeyCodeF1;
|
|
case Common::KEYCODE_F2:
|
|
return AGS3::eAGSKeyCodeF2;
|
|
case Common::KEYCODE_F3:
|
|
return AGS3::eAGSKeyCodeF3;
|
|
case Common::KEYCODE_F4:
|
|
return AGS3::eAGSKeyCodeF4;
|
|
case Common::KEYCODE_F5:
|
|
return AGS3::eAGSKeyCodeF5;
|
|
case Common::KEYCODE_F6:
|
|
return AGS3::eAGSKeyCodeF6;
|
|
case Common::KEYCODE_F7:
|
|
return AGS3::eAGSKeyCodeF7;
|
|
case Common::KEYCODE_F8:
|
|
return AGS3::eAGSKeyCodeF8;
|
|
case Common::KEYCODE_F9:
|
|
return AGS3::eAGSKeyCodeF9;
|
|
case Common::KEYCODE_F10:
|
|
return AGS3::eAGSKeyCodeF10;
|
|
case Common::KEYCODE_F11:
|
|
return AGS3::eAGSKeyCodeF11;
|
|
case Common::KEYCODE_F12:
|
|
return AGS3::eAGSKeyCodeF12;
|
|
|
|
case Common::KEYCODE_KP7:
|
|
case Common::KEYCODE_HOME:
|
|
return AGS3::eAGSKeyCodeHome;
|
|
case Common::KEYCODE_KP8:
|
|
case Common::KEYCODE_UP:
|
|
return AGS3::eAGSKeyCodeUpArrow;
|
|
case Common::KEYCODE_KP9:
|
|
case Common::KEYCODE_PAGEUP:
|
|
return AGS3::eAGSKeyCodePageUp;
|
|
case Common::KEYCODE_KP4:
|
|
case Common::KEYCODE_LEFT:
|
|
return AGS3::eAGSKeyCodeLeftArrow;
|
|
case Common::KEYCODE_KP5:
|
|
return AGS3::eAGSKeyCodeNumPad5;
|
|
case Common::KEYCODE_KP6:
|
|
case Common::KEYCODE_RIGHT:
|
|
return AGS3::eAGSKeyCodeRightArrow;
|
|
case Common::KEYCODE_KP1:
|
|
case Common::KEYCODE_END:
|
|
return AGS3::eAGSKeyCodeEnd;
|
|
case Common::KEYCODE_KP2:
|
|
case Common::KEYCODE_DOWN:
|
|
return AGS3::eAGSKeyCodeDownArrow;
|
|
case Common::KEYCODE_KP3:
|
|
case Common::KEYCODE_PAGEDOWN:
|
|
return AGS3::eAGSKeyCodePageDown;
|
|
case Common::KEYCODE_KP0:
|
|
case Common::KEYCODE_INSERT:
|
|
return AGS3::eAGSKeyCodeInsert;
|
|
case Common::KEYCODE_KP_PERIOD:
|
|
case Common::KEYCODE_DELETE:
|
|
return AGS3::eAGSKeyCodeDelete;
|
|
case Common::KEYCODE_LSHIFT:
|
|
return AGS3::eAGSKeyCodeLShift;
|
|
case Common::KEYCODE_RSHIFT:
|
|
return AGS3::eAGSKeyCodeRShift;
|
|
case Common::KEYCODE_LCTRL:
|
|
return AGS3::eAGSKeyCodeLCtrl;
|
|
case Common::KEYCODE_RCTRL:
|
|
return AGS3::eAGSKeyCodeRCtrl;
|
|
case Common::KEYCODE_LALT:
|
|
return AGS3::eAGSKeyCodeLAlt;
|
|
case Common::KEYCODE_RALT:
|
|
return AGS3::eAGSKeyCodeRAlt;
|
|
|
|
default:
|
|
return AGS3::eAGSKeyCodeNone;
|
|
}
|
|
|
|
return AGS3::eAGSKeyCodeNone;
|
|
}
|
|
|
|
} // namespace AGS
|