2019-02-12 10:30:24 +00:00
|
|
|
/*
|
|
|
|
Copyright 2019 flyinghead
|
|
|
|
|
|
|
|
This file is part of reicast.
|
|
|
|
|
|
|
|
reicast 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 2 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
reicast 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 reicast. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
#include "types.h"
|
2020-03-28 16:58:01 +00:00
|
|
|
|
|
|
|
#include <memory>
|
2019-02-12 10:30:24 +00:00
|
|
|
|
|
|
|
class KeyboardDevice
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
virtual const char* name() = 0;
|
|
|
|
int maple_port() { return _maple_port; }
|
2019-02-24 11:53:49 +00:00
|
|
|
void keyboard_character(char c);
|
|
|
|
std::string get_character_input();
|
2019-02-12 10:30:24 +00:00
|
|
|
virtual ~KeyboardDevice() {}
|
|
|
|
|
2019-02-24 11:53:49 +00:00
|
|
|
static KeyboardDevice *GetInstance() { return _instance; }
|
|
|
|
|
2019-02-12 10:30:24 +00:00
|
|
|
protected:
|
2019-02-24 11:53:49 +00:00
|
|
|
KeyboardDevice(int maple_port) : _maple_port(maple_port) { _instance = this; }
|
2019-02-12 10:30:24 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
int _maple_port;
|
2019-02-24 11:53:49 +00:00
|
|
|
std::string char_input;
|
|
|
|
static KeyboardDevice *_instance;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename Keycode>
|
|
|
|
class KeyboardDeviceTemplate : public KeyboardDevice
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
virtual void keyboard_input(Keycode keycode, bool pressed, int modifier_keys = 0);
|
|
|
|
|
|
|
|
protected:
|
2020-03-12 15:09:05 +00:00
|
|
|
KeyboardDeviceTemplate(int maple_port) : KeyboardDevice(maple_port), _modifier_keys(0), _kb_used(0) {}
|
2019-02-24 11:53:49 +00:00
|
|
|
virtual u8 convert_keycode(Keycode keycode) = 0;
|
|
|
|
|
|
|
|
private:
|
2019-02-12 10:30:24 +00:00
|
|
|
int _modifier_keys;
|
2020-03-12 15:09:05 +00:00
|
|
|
u32 _kb_used;
|
2019-02-12 10:30:24 +00:00
|
|
|
};
|
|
|
|
|
2021-02-24 16:28:58 +00:00
|
|
|
enum DCKeyboardModifiers {
|
|
|
|
DC_KBMOD_LEFTCTRL = 0x01,
|
|
|
|
DC_KBMOD_LEFTSHIFT = 0x02,
|
|
|
|
DC_KBMOD_LEFTALT = 0x04,
|
|
|
|
DC_KBMOD_LEFTGUI = 0x08,
|
|
|
|
DC_KBMOD_RIGHTCTRL = 0x10,
|
|
|
|
DC_KBMOD_RIGHTSHIFT = 0x20,
|
|
|
|
DC_KBMOD_RIGHTALT = 0x40,
|
|
|
|
DC_KBMOD_S2 = 0x80,
|
|
|
|
};
|
|
|
|
|
2019-02-12 10:30:24 +00:00
|
|
|
extern u8 kb_key[6]; // normal keys pressed
|
2021-02-24 16:28:58 +00:00
|
|
|
extern u8 kb_shift; // modifier keys pressed (bitmask)
|
|
|
|
|
|
|
|
static inline void setFlag(int& v, u32 bitmask, bool set)
|
|
|
|
{
|
|
|
|
if (set)
|
|
|
|
v |= bitmask;
|
|
|
|
else
|
|
|
|
v &= ~bitmask;
|
|
|
|
}
|
2019-02-12 10:30:24 +00:00
|
|
|
|
|
|
|
template <typename Keycode>
|
2019-02-24 11:53:49 +00:00
|
|
|
void KeyboardDeviceTemplate<Keycode>::keyboard_input(Keycode keycode, bool pressed, int modifier_keys)
|
2019-02-12 10:30:24 +00:00
|
|
|
{
|
|
|
|
u8 dc_keycode = convert_keycode(keycode);
|
2021-03-02 17:45:18 +00:00
|
|
|
// Some OSes (Mac OS) don't distinguish left and right modifier keys to we set them both.
|
|
|
|
// But not for Alt since Right Alt is used as a special modifier keys on some international
|
|
|
|
// keyboards.
|
2021-02-24 16:28:58 +00:00
|
|
|
switch (dc_keycode)
|
2019-02-12 10:30:24 +00:00
|
|
|
{
|
2021-02-24 16:28:58 +00:00
|
|
|
case 0xE1: // Left Shift
|
|
|
|
case 0xE5: // Right Shift
|
|
|
|
setFlag(_modifier_keys, DC_KBMOD_LEFTSHIFT | DC_KBMOD_RIGHTSHIFT, pressed);
|
|
|
|
break;
|
|
|
|
case 0xE0: // Left Ctrl
|
|
|
|
case 0xE4: // Right Ctrl
|
|
|
|
setFlag(_modifier_keys, DC_KBMOD_LEFTCTRL | DC_KBMOD_RIGHTCTRL, pressed);
|
|
|
|
break;
|
|
|
|
case 0xE2: // Left Alt
|
2021-03-02 17:45:18 +00:00
|
|
|
setFlag(_modifier_keys, DC_KBMOD_LEFTALT, pressed);
|
|
|
|
break;
|
2021-02-24 16:28:58 +00:00
|
|
|
case 0xE6: // Right Alt
|
2021-03-02 17:45:18 +00:00
|
|
|
setFlag(_modifier_keys, DC_KBMOD_RIGHTALT, pressed);
|
2021-02-24 16:28:58 +00:00
|
|
|
break;
|
2021-03-02 17:45:18 +00:00
|
|
|
case 0xE7: // S2 special key
|
2021-02-24 16:28:58 +00:00
|
|
|
setFlag(_modifier_keys, DC_KBMOD_S2, pressed);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
2019-02-12 10:30:24 +00:00
|
|
|
}
|
2021-03-02 17:45:18 +00:00
|
|
|
kb_shift = _modifier_keys;
|
2021-02-24 16:28:58 +00:00
|
|
|
|
2021-03-02 17:45:18 +00:00
|
|
|
if (dc_keycode != 0 && dc_keycode < 0xE0)
|
2019-02-12 10:30:24 +00:00
|
|
|
{
|
|
|
|
if (pressed)
|
|
|
|
{
|
|
|
|
if (_kb_used < ARRAY_SIZE(kb_key))
|
|
|
|
{
|
|
|
|
bool found = false;
|
2020-03-12 15:09:05 +00:00
|
|
|
for (u32 i = 0; !found && i < _kb_used; i++)
|
2019-02-12 10:30:24 +00:00
|
|
|
{
|
|
|
|
if (kb_key[i] == dc_keycode)
|
|
|
|
found = true;
|
|
|
|
}
|
|
|
|
if (!found)
|
|
|
|
kb_key[_kb_used++] = dc_keycode;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-03-12 15:09:05 +00:00
|
|
|
for (u32 i = 0; i < _kb_used; i++)
|
2019-02-12 10:30:24 +00:00
|
|
|
{
|
|
|
|
if (kb_key[i] == dc_keycode)
|
|
|
|
{
|
|
|
|
_kb_used--;
|
2020-03-12 15:09:05 +00:00
|
|
|
for (u32 j = i; j < ARRAY_SIZE(kb_key) - 1; j++)
|
2019-02-12 10:30:24 +00:00
|
|
|
kb_key[j] = kb_key[j + 1];
|
|
|
|
kb_key[ARRAY_SIZE(kb_key) - 1] = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-03-02 17:45:18 +00:00
|
|
|
kb_shift |= modifier_keys;
|
2019-02-12 10:30:24 +00:00
|
|
|
}
|
|
|
|
}
|
2019-02-24 11:53:49 +00:00
|
|
|
|
|
|
|
inline void KeyboardDevice::keyboard_character(char c) {
|
|
|
|
char_input.push_back(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline std::string KeyboardDevice::get_character_input() {
|
|
|
|
std::string input = char_input;
|
|
|
|
char_input.clear();
|
|
|
|
return input;
|
|
|
|
}
|