1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-22 12:33:29 +00:00

Attempts to improve SDL key merging.

This commit is contained in:
Thomas Harte 2020-03-05 21:56:26 -05:00
parent 462a76dd96
commit 58b8dfb929
3 changed files with 51 additions and 16 deletions

View File

@ -80,7 +80,7 @@ class Machine: public KeyActions {
} }
// That having failed, if a symbol has been supplied then try typing it. // That having failed, if a symbol has been supplied then try typing it.
if(symbol && can_type(symbol)) { if(is_pressed && symbol && can_type(symbol)) {
char string[2] = { symbol, 0 }; char string[2] = { symbol, 0 };
type_string(string); type_string(string);
return true; return true;

View File

@ -31,7 +31,7 @@
</Testables> </Testables>
</TestAction> </TestAction>
<LaunchAction <LaunchAction
buildConfiguration = "Debug" buildConfiguration = "Release"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
disableMainThreadChecker = "YES" disableMainThreadChecker = "YES"
@ -58,7 +58,7 @@
</CommandLineArgument> </CommandLineArgument>
<CommandLineArgument <CommandLineArgument
argument = "&quot;/Users/thomasharte/Library/Mobile Documents/com~apple~CloudDocs/Desktop/Soft/ColecoVision/Galaxian (1983)(Atari).col&quot;" argument = "&quot;/Users/thomasharte/Library/Mobile Documents/com~apple~CloudDocs/Desktop/Soft/ColecoVision/Galaxian (1983)(Atari).col&quot;"
isEnabled = "YES"> isEnabled = "NO">
</CommandLineArgument> </CommandLineArgument>
<CommandLineArgument <CommandLineArgument
argument = "&quot;/Users/thomasharte/Library/Mobile Documents/com~apple~CloudDocs/Desktop/Soft/Master System/R-Type (NTSC).sms&quot;" argument = "&quot;/Users/thomasharte/Library/Mobile Documents/com~apple~CloudDocs/Desktop/Soft/Master System/R-Type (NTSC).sms&quot;"
@ -66,11 +66,11 @@
</CommandLineArgument> </CommandLineArgument>
<CommandLineArgument <CommandLineArgument
argument = "--logical-keyboard" argument = "--logical-keyboard"
isEnabled = "NO"> isEnabled = "YES">
</CommandLineArgument> </CommandLineArgument>
<CommandLineArgument <CommandLineArgument
argument = "&quot;/Users/thomasharte/Library/Mobile Documents/com~apple~CloudDocs/Desktop/Soft/Amstrad CPC/Amstrad CPC [TOSEC]/Amstrad CPC - Applications - [DSK] (TOSEC-v2011-08-31_CM)/Tasword (1984)(Tasman Software).dsk&quot;" argument = "&quot;/Users/thomasharte/Library/Mobile Documents/com~apple~CloudDocs/Desktop/Soft/Amstrad CPC/Amstrad CPC [TOSEC]/Amstrad CPC - Applications - [DSK] (TOSEC-v2011-08-31_CM)/Tasword (1984)(Tasman Software).dsk&quot;"
isEnabled = "NO"> isEnabled = "YES">
</CommandLineArgument> </CommandLineArgument>
<CommandLineArgument <CommandLineArgument
argument = "&quot;/Users/thomasharte/Library/Mobile Documents/com~apple~CloudDocs/Desktop/Soft/Amstrad CPC/Robocop.dsk&quot;" argument = "&quot;/Users/thomasharte/Library/Mobile Documents/com~apple~CloudDocs/Desktop/Soft/Amstrad CPC/Robocop.dsk&quot;"

View File

@ -16,7 +16,7 @@
#include <memory> #include <memory>
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#include <unordered_map> #include <map>
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
@ -773,7 +773,7 @@ int main(int argc, char *argv[]) {
std::string input; std::string input;
SDL_Scancode scancode = SDL_SCANCODE_UNKNOWN; SDL_Scancode scancode = SDL_SCANCODE_UNKNOWN;
}; };
std::unordered_map<uint32_t, KeyPress> keypresses; std::map<uint32_t, KeyPress> keypresses;
// Run the main event loop until the OS tells us to quit. // Run the main event loop until the OS tells us to quit.
const bool uses_mouse = !!machine->mouse_machine(); const bool uses_mouse = !!machine->mouse_machine();
@ -904,9 +904,8 @@ int main(int argc, char *argv[]) {
break; break;
} }
const bool is_pressed = event.type == SDL_KEYDOWN;
keypresses[event.text.timestamp].scancode = event.key.keysym.scancode; keypresses[event.text.timestamp].scancode = event.key.keysym.scancode;
keypresses[event.text.timestamp].is_down = is_pressed; keypresses[event.text.timestamp].is_down = event.type == SDL_KEYDOWN;
} break; } break;
case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONDOWN:
@ -938,14 +937,50 @@ int main(int argc, char *argv[]) {
} }
} }
// Look for potential keypress merges; SDL doesn't in any capacity guarantee that keypresses that produce
// symbols will be delivered with the same timestamp. So look for any pairs of recorded kepresses that are
// close together temporally and otherwise seem to match.
std::vector<KeyPress> matched_keypresses;
if(keypresses.size()) {
auto next_keypress = keypresses.begin();
while(next_keypress != keypresses.end()) {
auto keypress = next_keypress;
++next_keypress;
// If the two appear to pair off, push a combination and advance twice.
// Otherwise, keep just the first and advance once.
if(
next_keypress != keypresses.end() &&
keypress->first >= next_keypress->first - 5 &&
keypress->second.is_down && next_keypress->second.is_down &&
!keypress->second.input.size() != !next_keypress->second.input.size() &&
(keypress->second.scancode != SDL_SCANCODE_UNKNOWN) != (next_keypress->second.scancode != SDL_SCANCODE_UNKNOWN)) {
KeyPress combined_keypress;
if(keypress->second.scancode != SDL_SCANCODE_UNKNOWN) {
combined_keypress.scancode = keypress->second.scancode;
combined_keypress.input = std::move(next_keypress->second.input);
} else {
combined_keypress.scancode = next_keypress->second.scancode;
combined_keypress.input = std::move(keypress->second.input);
};
++next_keypress;
} else {
matched_keypresses.push_back(keypress->second);
}
}
}
// Handle accumulated key states. // Handle accumulated key states.
JoystickMachine::Machine *const joystick_machine = machine->joystick_machine(); JoystickMachine::Machine *const joystick_machine = machine->joystick_machine();
for (const auto &keypress: keypresses) { for (const auto &keypress: matched_keypresses) {
// Try to set this key on the keyboard first, if there is one. // Try to set this key on the keyboard first, if there is one.
if(keyboard_machine) { if(keyboard_machine) {
Inputs::Keyboard::Key key = Inputs::Keyboard::Key::Space; Inputs::Keyboard::Key key = Inputs::Keyboard::Key::Space;
if( KeyboardKeyForSDLScancode(keypress.second.scancode, key) && if( KeyboardKeyForSDLScancode(keypress.scancode, key) &&
keyboard_machine->apply_key(key, keypress.second.input.size() ? keypress.second.input[0] : 0, keypress.second.is_down, logical_keyboard)) { keyboard_machine->apply_key(key, keypress.input.size() ? keypress.input[0] : 0, keypress.is_down, logical_keyboard)) {
continue; continue;
} }
} }
@ -954,8 +989,8 @@ int main(int argc, char *argv[]) {
if(joystick_machine) { if(joystick_machine) {
auto &joysticks = joystick_machine->get_joysticks(); auto &joysticks = joystick_machine->get_joysticks();
if(!joysticks.empty()) { if(!joysticks.empty()) {
const bool is_pressed = keypress.second.is_down; const bool is_pressed = keypress.is_down;
switch(keypress.second.scancode) { switch(keypress.scancode) {
case SDL_SCANCODE_LEFT: joysticks[0]->set_input(Inputs::Joystick::Input::Left, is_pressed); break; case SDL_SCANCODE_LEFT: joysticks[0]->set_input(Inputs::Joystick::Input::Left, is_pressed); break;
case SDL_SCANCODE_RIGHT: joysticks[0]->set_input(Inputs::Joystick::Input::Right, is_pressed); break; case SDL_SCANCODE_RIGHT: joysticks[0]->set_input(Inputs::Joystick::Input::Right, is_pressed); break;
case SDL_SCANCODE_UP: joysticks[0]->set_input(Inputs::Joystick::Input::Up, is_pressed); break; case SDL_SCANCODE_UP: joysticks[0]->set_input(Inputs::Joystick::Input::Up, is_pressed); break;
@ -966,8 +1001,8 @@ int main(int argc, char *argv[]) {
case SDL_SCANCODE_D: joysticks[0]->set_input(Inputs::Joystick::Input(Inputs::Joystick::Input::Fire, 2), is_pressed); break; case SDL_SCANCODE_D: joysticks[0]->set_input(Inputs::Joystick::Input(Inputs::Joystick::Input::Fire, 2), is_pressed); break;
case SDL_SCANCODE_F: joysticks[0]->set_input(Inputs::Joystick::Input(Inputs::Joystick::Input::Fire, 3), is_pressed); break; case SDL_SCANCODE_F: joysticks[0]->set_input(Inputs::Joystick::Input(Inputs::Joystick::Input::Fire, 3), is_pressed); break;
default: { default: {
if(keypress.second.input.size()) { if(keypress.input.size()) {
joysticks[0]->set_input(Inputs::Joystick::Input(keypress.second.input[0]), is_pressed); joysticks[0]->set_input(Inputs::Joystick::Input(keypress.input[0]), is_pressed);
} }
} break; } break;
} }