1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-26 10:29:31 +00:00

Further improvement: if in physical mode, but pressing an unrecognised key, attempt to 'type' it.

This commit is contained in:
Thomas Harte 2020-03-02 22:08:54 -05:00
parent dc47a2b7d7
commit 1f41d9c5f5
9 changed files with 53 additions and 25 deletions

View File

@ -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_) { 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() { void MultiKeyboardMachine::MultiKeyboard::reset_all_keys() {

View File

@ -32,7 +32,7 @@ class MultiKeyboardMachine: public KeyboardMachine::Machine {
public: public:
MultiKeyboard(const std::vector<::KeyboardMachine::Machine *> &machines); 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; void reset_all_keys() final;
const std::set<Key> &observed_keys() final; const std::set<Key> &observed_keys() final;
bool is_exclusive() final; bool is_exclusive() final;

View File

@ -19,14 +19,15 @@ Keyboard::Keyboard(const std::set<Key> &essential_modifiers) : essential_modifie
Keyboard::Keyboard(const std::set<Key> &observed_keys, const std::set<Key> &essential_modifiers) : 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) {} 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<std::size_t>(key); std::size_t key_offset = static_cast<std::size_t>(key);
if(key_offset >= key_states_.size()) { if(key_offset >= key_states_.size()) {
key_states_.resize(key_offset+1, false); key_states_.resize(key_offset+1, false);
} }
key_states_[key_offset] = is_pressed; 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<Inputs::Keyboard::Key> &Keyboard::get_essential_modifiers() { const std::set<Inputs::Keyboard::Key> &Keyboard::get_essential_modifiers() {

View File

@ -45,7 +45,9 @@ class Keyboard {
Keyboard(const std::set<Key> &observed_keys, const std::set<Key> &essential_modifiers); Keyboard(const std::set<Key> &observed_keys, const std::set<Key> &essential_modifiers);
// Host interface. // 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(); virtual void reset_all_keys();
/// @returns a set of all Keys that this keyboard responds to. /// @returns a set of all Keys that this keyboard responds to.
@ -68,7 +70,7 @@ class Keyboard {
// Delegate interface. // Delegate interface.
struct Delegate { 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; virtual void reset_all_keys(Keyboard *keyboard) = 0;
}; };
void set_delegate(Delegate *delegate); void set_delegate(Delegate *delegate);

View File

@ -811,18 +811,18 @@ template <Analyser::Static::AppleII::Target::Model model> class ConcreteMachine:
open_apple_is_pressed_ = closed_apple_is_pressed_ = key_is_down_ = false; 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) { switch(key) {
default: break; default: break;
case Key::F12: case Key::F12:
m6502_.set_reset_line(is_pressed); m6502_.set_reset_line(is_pressed);
return; return true;
case Key::LeftOption: case Key::LeftOption:
open_apple_is_pressed_ = is_pressed; open_apple_is_pressed_ = is_pressed;
return; return true;
case Key::RightOption: case Key::RightOption:
closed_apple_is_pressed_ = is_pressed; closed_apple_is_pressed_ = is_pressed;
return; return true;
} }
// If no ASCII value is supplied, look for a few special cases. // If no ASCII value is supplied, look for a few special cases.
@ -833,7 +833,7 @@ template <Analyser::Static::AppleII::Target::Model model> class ConcreteMachine:
case Key::Down: value = 0x0a; break; case Key::Down: value = 0x0a; break;
case Key::Up: value = 0x0b; break; case Key::Up: value = 0x0b; break;
case Key::Backspace: value = 0x7f; break; case Key::Backspace: value = 0x7f; break;
default: return; default: return false;
} }
} }
@ -848,6 +848,8 @@ template <Analyser::Static::AppleII::Target::Model model> class ConcreteMachine:
key_is_down_ = false; key_is_down_ = false;
} }
} }
return true;
} }
Inputs::Keyboard &get_keyboard() final { Inputs::Keyboard &get_keyboard() final {

View File

@ -14,9 +14,11 @@ MappedMachine::MappedMachine(const std::set<Inputs::Keyboard::Key> &essential_mo
keyboard_.set_delegate(this); 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); 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) { void MappedMachine::reset_all_keys(Inputs::Keyboard *keyboard) {

View File

@ -95,7 +95,7 @@ class MappedMachine: public Inputs::Keyboard::Delegate, public Machine {
virtual Inputs::Keyboard &get_keyboard() override; virtual Inputs::Keyboard &get_keyboard() override;
private: 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; void reset_all_keys(Inputs::Keyboard *keyboard) override;
Inputs::Keyboard keyboard_; Inputs::Keyboard keyboard_;
}; };

View File

@ -355,12 +355,18 @@ class ConcreteMachine:
return keyboard_; 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) { if(key == Inputs::Keyboard::Key::Enter) {
pause_is_pressed_ = is_pressed; pause_is_pressed_ = is_pressed;
} else if(key == Inputs::Keyboard::Key::Escape) { return true;
reset_is_pressed_ = is_pressed;
} }
if(key == Inputs::Keyboard::Key::Escape) {
reset_is_pressed_ = is_pressed;
return true;
}
return false;
} }
void reset_all_keys(Inputs::Keyboard *) final { void reset_all_keys(Inputs::Keyboard *) final {

View File

@ -504,10 +504,21 @@ struct ActivityObserver: public Activity::Observer {
} }
} }
// If this is logical mode and this key maps to a symbol, supply it // Decide whether to try to 'type' (in the logical mapping sense) in the first instance.
// as something to type. If this isn't logical mode, or this key doesn't bool shouldTryToType = self.inputMode == CSMachineKeyboardInputModeKeyboardLogical;
// map to a symbol, pass it along as a standard press.
if(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) { @synchronized(self) {
if(pressedKey && keyboard_machine->can_type(pressedKey)) { if(pressedKey && keyboard_machine->can_type(pressedKey)) {
if(isPressed) { if(isPressed) {
@ -517,10 +528,12 @@ struct ActivityObserver: public Activity::Observer {
return; return;
} }
} }
}
@synchronized(self) { // Okay, so at this point either: set_key_pressed was already tried but will fail anyway,
keyboard.set_key_pressed(mapped_key, pressedKey, isPressed); // 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; return;