diff --git a/Analyser/Dynamic/MultiMachine/Implementation/MultiKeyboardMachine.cpp b/Analyser/Dynamic/MultiMachine/Implementation/MultiKeyboardMachine.cpp index 42d0c0835..c27794e76 100644 --- a/Analyser/Dynamic/MultiMachine/Implementation/MultiKeyboardMachine.cpp +++ b/Analyser/Dynamic/MultiMachine/Implementation/MultiKeyboardMachine.cpp @@ -56,10 +56,12 @@ MultiKeyboardMachine::MultiKeyboard::MultiKeyboard(const std::vector<::KeyboardM } } -void 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 was_consumed = false; for(const auto &machine: machines_) { - machine->get_keyboard().set_key_pressed(key, value, is_pressed); + was_consumed |= machine->get_keyboard().set_key_pressed(key, value, is_pressed); } + return was_consumed; } void MultiKeyboardMachine::MultiKeyboard::reset_all_keys() { diff --git a/Analyser/Dynamic/MultiMachine/Implementation/MultiKeyboardMachine.hpp b/Analyser/Dynamic/MultiMachine/Implementation/MultiKeyboardMachine.hpp index a828546fe..bc0803d83 100644 --- a/Analyser/Dynamic/MultiMachine/Implementation/MultiKeyboardMachine.hpp +++ b/Analyser/Dynamic/MultiMachine/Implementation/MultiKeyboardMachine.hpp @@ -32,7 +32,7 @@ class MultiKeyboardMachine: public KeyboardMachine::Machine { public: MultiKeyboard(const std::vector<::KeyboardMachine::Machine *> &machines); - void set_key_pressed(Key key, char value, bool is_pressed) final; + bool set_key_pressed(Key key, char value, bool is_pressed) final; void reset_all_keys() final; const std::set &observed_keys() final; bool is_exclusive() final; diff --git a/Inputs/Keyboard.cpp b/Inputs/Keyboard.cpp index 6193a5ff8..7c9ff819d 100644 --- a/Inputs/Keyboard.cpp +++ b/Inputs/Keyboard.cpp @@ -19,14 +19,15 @@ Keyboard::Keyboard(const std::set &essential_modifiers) : essential_modifie Keyboard::Keyboard(const std::set &observed_keys, const std::set &essential_modifiers) : observed_keys_(observed_keys), essential_modifiers_(essential_modifiers), is_exclusive_(false) {} -void Keyboard::set_key_pressed(Key key, char value, bool is_pressed) { +bool Keyboard::set_key_pressed(Key key, char value, bool is_pressed) { std::size_t key_offset = static_cast(key); if(key_offset >= key_states_.size()) { key_states_.resize(key_offset+1, false); } key_states_[key_offset] = is_pressed; - if(delegate_) delegate_->keyboard_did_change_key(this, key, is_pressed); + if(delegate_) return delegate_->keyboard_did_change_key(this, key, is_pressed); + return false; } const std::set &Keyboard::get_essential_modifiers() { diff --git a/Inputs/Keyboard.hpp b/Inputs/Keyboard.hpp index 28e5054f1..3011ed826 100644 --- a/Inputs/Keyboard.hpp +++ b/Inputs/Keyboard.hpp @@ -45,7 +45,9 @@ class Keyboard { Keyboard(const std::set &observed_keys, const std::set &essential_modifiers); // Host interface. - virtual void set_key_pressed(Key key, char value, bool is_pressed); + + /// @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 void reset_all_keys(); /// @returns a set of all Keys that this keyboard responds to. @@ -68,7 +70,7 @@ class Keyboard { // Delegate interface. struct Delegate { - virtual void keyboard_did_change_key(Keyboard *keyboard, Key key, bool is_pressed) = 0; + virtual bool keyboard_did_change_key(Keyboard *keyboard, Key key, bool is_pressed) = 0; virtual void reset_all_keys(Keyboard *keyboard) = 0; }; void set_delegate(Delegate *delegate); diff --git a/Machines/Apple/AppleII/AppleII.cpp b/Machines/Apple/AppleII/AppleII.cpp index 0e1a3c037..3c6c25c44 100644 --- a/Machines/Apple/AppleII/AppleII.cpp +++ b/Machines/Apple/AppleII/AppleII.cpp @@ -811,18 +811,18 @@ template class ConcreteMachine: open_apple_is_pressed_ = closed_apple_is_pressed_ = key_is_down_ = false; } - void set_key_pressed(Key key, char value, bool is_pressed) final { + bool set_key_pressed(Key key, char value, bool is_pressed) final { switch(key) { default: break; case Key::F12: m6502_.set_reset_line(is_pressed); - return; + return true; case Key::LeftOption: open_apple_is_pressed_ = is_pressed; - return; + return true; case Key::RightOption: closed_apple_is_pressed_ = is_pressed; - return; + return true; } // If no ASCII value is supplied, look for a few special cases. @@ -833,7 +833,7 @@ template class ConcreteMachine: case Key::Down: value = 0x0a; break; case Key::Up: value = 0x0b; break; case Key::Backspace: value = 0x7f; break; - default: return; + default: return false; } } @@ -848,6 +848,8 @@ template class ConcreteMachine: key_is_down_ = false; } } + + return true; } Inputs::Keyboard &get_keyboard() final { diff --git a/Machines/KeyboardMachine.cpp b/Machines/KeyboardMachine.cpp index 0d79387ee..1a60103d6 100644 --- a/Machines/KeyboardMachine.cpp +++ b/Machines/KeyboardMachine.cpp @@ -14,9 +14,11 @@ MappedMachine::MappedMachine(const std::set &essential_mo keyboard_.set_delegate(this); } -void MappedMachine::keyboard_did_change_key(Inputs::Keyboard *keyboard, Inputs::Keyboard::Key key, bool is_pressed) { +bool MappedMachine::keyboard_did_change_key(Inputs::Keyboard *keyboard, Inputs::Keyboard::Key key, bool is_pressed) { uint16_t mapped_key = get_keyboard_mapper()->mapped_key_for_key(key); - if(mapped_key != KeyNotMapped) set_key_state(mapped_key, is_pressed); + if(mapped_key == KeyNotMapped) return false; + set_key_state(mapped_key, is_pressed); + return true; } void MappedMachine::reset_all_keys(Inputs::Keyboard *keyboard) { diff --git a/Machines/KeyboardMachine.hpp b/Machines/KeyboardMachine.hpp index e4af3adb1..a84f53fb0 100644 --- a/Machines/KeyboardMachine.hpp +++ b/Machines/KeyboardMachine.hpp @@ -95,7 +95,7 @@ class MappedMachine: public Inputs::Keyboard::Delegate, public Machine { virtual Inputs::Keyboard &get_keyboard() override; private: - void keyboard_did_change_key(Inputs::Keyboard *keyboard, Inputs::Keyboard::Key key, bool is_pressed) override; + bool keyboard_did_change_key(Inputs::Keyboard *keyboard, Inputs::Keyboard::Key key, bool is_pressed) override; void reset_all_keys(Inputs::Keyboard *keyboard) override; Inputs::Keyboard keyboard_; }; diff --git a/Machines/MasterSystem/MasterSystem.cpp b/Machines/MasterSystem/MasterSystem.cpp index ce98a0bf8..ea4d46cfb 100644 --- a/Machines/MasterSystem/MasterSystem.cpp +++ b/Machines/MasterSystem/MasterSystem.cpp @@ -355,12 +355,18 @@ class ConcreteMachine: return keyboard_; } - void keyboard_did_change_key(Inputs::Keyboard *, Inputs::Keyboard::Key key, bool is_pressed) final { + bool keyboard_did_change_key(Inputs::Keyboard *, Inputs::Keyboard::Key key, bool is_pressed) final { if(key == Inputs::Keyboard::Key::Enter) { pause_is_pressed_ = is_pressed; - } else if(key == Inputs::Keyboard::Key::Escape) { - reset_is_pressed_ = is_pressed; + return true; } + + if(key == Inputs::Keyboard::Key::Escape) { + reset_is_pressed_ = is_pressed; + return true; + } + + return false; } void reset_all_keys(Inputs::Keyboard *) final { diff --git a/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm b/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm index 35f5dfb81..5992b9fae 100644 --- a/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm +++ b/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm @@ -504,10 +504,21 @@ struct ActivityObserver: public Activity::Observer { } } - // If this is logical mode and this key maps to a symbol, supply it - // as something to type. If this isn't logical mode, or this key doesn't - // map to a symbol, pass it along as a standard press. - if(self.inputMode == CSMachineKeyboardInputModeKeyboardLogical) { + // Decide whether to try to 'type' (in the logical mapping sense) in the first instance. + bool shouldTryToType = self.inputMode == CSMachineKeyboardInputModeKeyboardLogical; + + // Even if the default wasn't to try to type, have a go anyway if the key wasn't + // recognised directly. E.g. if the user hits their square bracket key on a machine that + // doesn't have a correspondingly-placed key, then try to type a square bracket. + if(!shouldTryToType) { + @synchronized(self) { + shouldTryToType = !keyboard.set_key_pressed(mapped_key, pressedKey, isPressed); + } + } + + // If this should try to type, give that a go. But typing may fail, e.g. because the user + // has pressed something like the cursor keys, which don't actually map to a typeable symbol. + if(shouldTryToType) { @synchronized(self) { if(pressedKey && keyboard_machine->can_type(pressedKey)) { if(isPressed) { @@ -517,10 +528,12 @@ struct ActivityObserver: public Activity::Observer { return; } } - } - @synchronized(self) { - keyboard.set_key_pressed(mapped_key, pressedKey, isPressed); + // Okay, so at this point either: set_key_pressed was already tried but will fail anyway, + // or else it hasn't been tried yet and is worth a go. + @synchronized(self) { + shouldTryToType = !keyboard.set_key_pressed(mapped_key, pressedKey, isPressed); + } } return;