mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-23 03:29:04 +00:00
Indicate whether a keypress is a repeat. Treat appropriately in the Apple II.
This commit is contained in:
parent
74bee31a78
commit
9344f6a824
@ -56,10 +56,10 @@ MultiKeyboardMachine::MultiKeyboard::MultiKeyboard(const std::vector<::MachineTy
|
||||
}
|
||||
}
|
||||
|
||||
bool MultiKeyboardMachine::MultiKeyboard::set_key_pressed(Key key, char value, bool is_pressed) {
|
||||
bool MultiKeyboardMachine::MultiKeyboard::set_key_pressed(Key key, char value, bool is_pressed, bool is_repeat) {
|
||||
bool was_consumed = false;
|
||||
for(const auto &machine: machines_) {
|
||||
was_consumed |= machine->get_keyboard().set_key_pressed(key, value, is_pressed);
|
||||
was_consumed |= machine->get_keyboard().set_key_pressed(key, value, is_pressed, is_repeat);
|
||||
}
|
||||
return was_consumed;
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ class MultiKeyboardMachine: public MachineTypes::KeyboardMachine {
|
||||
public:
|
||||
MultiKeyboard(const std::vector<MachineTypes::KeyboardMachine *> &machines);
|
||||
|
||||
bool set_key_pressed(Key key, char value, bool is_pressed) final;
|
||||
bool set_key_pressed(Key key, char value, bool is_pressed, bool is_repeat) final;
|
||||
void reset_all_keys() final;
|
||||
const std::set<Key> &observed_keys() const final;
|
||||
bool is_exclusive() const final;
|
||||
|
@ -21,7 +21,7 @@ Keyboard::Keyboard(const std::set<Key> &essential_modifiers) : essential_modifie
|
||||
Keyboard::Keyboard(const std::set<Key> &observed_keys, const std::set<Key> &essential_modifiers) :
|
||||
observed_keys_(observed_keys), essential_modifiers_(essential_modifiers), is_exclusive_(false) {}
|
||||
|
||||
bool Keyboard::set_key_pressed(Key key, char, bool is_pressed) {
|
||||
bool Keyboard::set_key_pressed(Key key, char, bool is_pressed, bool) {
|
||||
const size_t key_offset = size_t(key);
|
||||
if(key_offset >= key_states_.size()) {
|
||||
key_states_.resize(key_offset+1, false);
|
||||
|
@ -51,7 +51,7 @@ class Keyboard {
|
||||
// Host interface.
|
||||
|
||||
/// @returns @c true if the key press affects the machine; @c false otherwise.
|
||||
virtual bool set_key_pressed(Key key, char value, bool is_pressed);
|
||||
virtual bool set_key_pressed(Key key, char value, bool is_pressed, bool is_repeat);
|
||||
virtual void reset_all_keys();
|
||||
|
||||
/// @returns a set of all Keys that this keyboard responds to.
|
||||
|
@ -279,7 +279,12 @@ template <Analyser::Static::AppleII::Target::Model model> class ConcreteMachine:
|
||||
open_apple_is_pressed = closed_apple_is_pressed = control_is_pressed = shift_is_pressed = key_is_down = false;
|
||||
}
|
||||
|
||||
bool set_key_pressed(Key key, char value, bool is_pressed) final {
|
||||
bool set_key_pressed(Key key, char value, bool is_pressed, bool is_repeat) final {
|
||||
// TODO: unless a repeat key is pressed or this is a IIe.
|
||||
if constexpr (!is_iie()) {
|
||||
if(is_repeat && !repeat_is_pressed) return true;
|
||||
}
|
||||
|
||||
// If no ASCII value is supplied, look for a few special cases.
|
||||
switch(key) {
|
||||
case Key::Left: value = 0x08; break;
|
||||
@ -333,7 +338,11 @@ template <Analyser::Static::AppleII::Target::Model model> class ConcreteMachine:
|
||||
|
||||
case Key::F1: case Key::F2: case Key::F3: case Key::F4:
|
||||
case Key::F5: case Key::F6: case Key::F7: case Key::F8:
|
||||
case Key::F9: case Key::F10: case Key::F11: case Key::F12:
|
||||
case Key::F9: case Key::F10: case Key::F11:
|
||||
repeat_is_pressed = is_pressed;
|
||||
return true;
|
||||
|
||||
case Key::F12:
|
||||
case Key::PrintScreen:
|
||||
case Key::ScrollLock:
|
||||
case Key::Pause:
|
||||
@ -402,6 +411,7 @@ template <Analyser::Static::AppleII::Target::Model model> class ConcreteMachine:
|
||||
}
|
||||
}
|
||||
|
||||
bool repeat_is_pressed = false;
|
||||
bool shift_is_pressed = false;
|
||||
bool control_is_pressed = false;
|
||||
// The IIe has three keys that are wired directly to the same input as the joystick buttons.
|
||||
|
@ -75,12 +75,12 @@ class KeyboardMachine: public KeyActions {
|
||||
(i) if @c symbol can be typed and this is a key down, @c type_string it;
|
||||
(ii) if @c symbol cannot be typed, set @c key as @c is_pressed
|
||||
*/
|
||||
bool apply_key(Inputs::Keyboard::Key key, char symbol, bool is_pressed, bool map_logically) {
|
||||
bool apply_key(Inputs::Keyboard::Key key, char symbol, bool is_pressed, bool is_repeat, bool map_logically) {
|
||||
Inputs::Keyboard &keyboard = get_keyboard();
|
||||
|
||||
if(!map_logically) {
|
||||
// Try a regular keypress first, and stop if that works.
|
||||
if(keyboard.set_key_pressed(key, symbol, is_pressed)) {
|
||||
if(keyboard.set_key_pressed(key, symbol, is_pressed, is_repeat)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -103,7 +103,7 @@ class KeyboardMachine: public KeyActions {
|
||||
// That didn't work. Forward as a keypress. As, either:
|
||||
// (i) this is a key down, but doesn't have a symbol, or is an untypeable symbol; or
|
||||
// (ii) this is a key up, which it won't be an issue to miscommunicate.
|
||||
return keyboard.set_key_pressed(key, symbol, is_pressed);
|
||||
return keyboard.set_key_pressed(key, symbol, is_pressed, is_repeat);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -345,14 +345,14 @@ class MachineDocument:
|
||||
/// Forwards key down events directly to the machine.
|
||||
func keyDown(_ event: NSEvent) {
|
||||
if let machine = self.machine {
|
||||
machine.setKey(event.keyCode, characters: event.characters, isPressed: true)
|
||||
machine.setKey(event.keyCode, characters: event.characters, isPressed: true, isRepeat: event.isARepeat)
|
||||
}
|
||||
}
|
||||
|
||||
/// Forwards key up events directly to the machine.
|
||||
func keyUp(_ event: NSEvent) {
|
||||
if let machine = self.machine {
|
||||
machine.setKey(event.keyCode, characters: event.characters, isPressed: false)
|
||||
machine.setKey(event.keyCode, characters: event.characters, isPressed: false, isRepeat: false)
|
||||
}
|
||||
}
|
||||
|
||||
@ -361,19 +361,19 @@ class MachineDocument:
|
||||
if let machine = self.machine {
|
||||
if newModifiers.modifierFlags.contains(.shift) != shiftIsDown {
|
||||
shiftIsDown = newModifiers.modifierFlags.contains(.shift)
|
||||
machine.setKey(VK_Shift, characters: nil, isPressed: shiftIsDown)
|
||||
machine.setKey(VK_Shift, characters: nil, isPressed: shiftIsDown, isRepeat: false)
|
||||
}
|
||||
if newModifiers.modifierFlags.contains(.control) != controlIsDown {
|
||||
controlIsDown = newModifiers.modifierFlags.contains(.control)
|
||||
machine.setKey(VK_Control, characters: nil, isPressed: controlIsDown)
|
||||
machine.setKey(VK_Control, characters: nil, isPressed: controlIsDown, isRepeat: false)
|
||||
}
|
||||
if newModifiers.modifierFlags.contains(.command) != commandIsDown {
|
||||
commandIsDown = newModifiers.modifierFlags.contains(.command)
|
||||
machine.setKey(VK_Command, characters: nil, isPressed: commandIsDown)
|
||||
machine.setKey(VK_Command, characters: nil, isPressed: commandIsDown, isRepeat: false)
|
||||
}
|
||||
if newModifiers.modifierFlags.contains(.option) != optionIsDown {
|
||||
optionIsDown = newModifiers.modifierFlags.contains(.option)
|
||||
machine.setKey(VK_Option, characters: nil, isPressed: optionIsDown)
|
||||
machine.setKey(VK_Option, characters: nil, isPressed: optionIsDown, isRepeat: false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ typedef NS_ENUM(NSInteger, CSMachineKeyboardInputMode) {
|
||||
- (void)start;
|
||||
- (void)stop;
|
||||
|
||||
- (void)setKey:(uint16_t)key characters:(nullable NSString *)characters isPressed:(BOOL)isPressed;
|
||||
- (void)setKey:(uint16_t)key characters:(nullable NSString *)characters isPressed:(BOOL)isPressed isRepeat:(BOOL)isRepeat;
|
||||
- (void)clearAllKeys;
|
||||
|
||||
- (void)setMouseButton:(int)button isPressed:(BOOL)isPressed;
|
||||
|
@ -366,7 +366,7 @@ struct ActivityObserver: public Activity::Observer {
|
||||
[self updateJoystickTimer];
|
||||
}
|
||||
|
||||
- (void)setKey:(uint16_t)key characters:(NSString *)characters isPressed:(BOOL)isPressed {
|
||||
- (void)setKey:(uint16_t)key characters:(NSString *)characters isPressed:(BOOL)isPressed isRepeat:(BOOL)isRepeat {
|
||||
[self applyInputEvent:^{
|
||||
auto keyboard_machine = self->_machine->keyboard_machine();
|
||||
if(keyboard_machine && (self.inputMode != CSMachineKeyboardInputModeJoystick || !keyboard_machine->get_keyboard().is_exclusive())) {
|
||||
@ -437,7 +437,13 @@ struct ActivityObserver: public Activity::Observer {
|
||||
}
|
||||
|
||||
@synchronized(self) {
|
||||
if(keyboard_machine->apply_key(mapped_key, pressedKey, isPressed, self.inputMode == CSMachineKeyboardInputModeKeyboardLogical)) {
|
||||
if(keyboard_machine->apply_key(
|
||||
mapped_key,
|
||||
pressedKey,
|
||||
isPressed,
|
||||
isRepeat,
|
||||
self.inputMode == CSMachineKeyboardInputModeKeyboardLogical)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -889,7 +889,7 @@ bool MainWindow::processEvent(QKeyEvent *event) {
|
||||
if(!keyboardMachine) return true;
|
||||
|
||||
auto &keyboard = keyboardMachine->get_keyboard();
|
||||
keyboard.set_key_pressed(*key, event->text().size() ? event->text()[0].toLatin1() : '\0', isPressed);
|
||||
keyboard.set_key_pressed(*key, event->text().size() ? event->text()[0].toLatin1() : '\0', isPressed, false);
|
||||
if(keyboard.is_exclusive() || keyboard.observed_keys().find(*key) != keyboard.observed_keys().end()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1214,14 +1214,15 @@ int main(int argc, char *argv[]) {
|
||||
// is sufficiently untested on SDL, and somewhat too reliant on empirical timestamp behaviour,
|
||||
// for it to be trustworthy enough otherwise to expose.
|
||||
if(logical_keyboard) {
|
||||
if(keyboard_machine->apply_key(key, keypress.input.size() ? keypress.input[0] : 0, keypress.is_down, logical_keyboard)) {
|
||||
// TODO: is_repeat.
|
||||
if(keyboard_machine->apply_key(key, keypress.input.size() ? keypress.input[0] : 0, keypress.is_down, keypress.repeat, logical_keyboard)) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
// This is a slightly terrible way of obtaining a symbol for the key, e.g. for letters it will always return
|
||||
// the capital letter version, at least empirically. But it'll have to do for now.
|
||||
const char *key_name = SDL_GetKeyName(keypress.keycode);
|
||||
if(keyboard_machine->get_keyboard().set_key_pressed(key, (strlen(key_name) == 1) ? key_name[0] : 0, keypress.is_down)) {
|
||||
if(keyboard_machine->get_keyboard().set_key_pressed(key, (strlen(key_name) == 1) ? key_name[0] : 0, keypress.is_down, keypress.repeat)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user