diff --git a/src/fenrirscreenreader/commands/commands/forward_keypress.py b/src/fenrirscreenreader/commands/commands/forward_keypress.py index e22ff7c5..acc67228 100644 --- a/src/fenrirscreenreader/commands/commands/forward_keypress.py +++ b/src/fenrirscreenreader/commands/commands/forward_keypress.py @@ -22,7 +22,10 @@ class command: return _("sends the following keypress to the terminal or application") def run(self): - self.env["input"]["key_forward"] = 3 + if self.env["runtime"]["InputManager"].no_key_pressed(): + self.env["input"]["key_forward"] = 1 + else: + self.env["input"]["key_forward"] = -1 self.env["runtime"]["OutputManager"].present_text( _("Forward next keypress"), interrupt=True ) diff --git a/src/fenrirscreenreader/core/fenrirManager.py b/src/fenrirscreenreader/core/fenrirManager.py index d234fd53..21a6e1c6 100644 --- a/src/fenrirscreenreader/core/fenrirManager.py +++ b/src/fenrirscreenreader/core/fenrirManager.py @@ -126,8 +126,7 @@ class FenrirManager: self.environment["runtime"]["InputManager"].write_event_buffer() self.environment["runtime"]["InputManager"].handle_device_grab() - if self.environment["input"]["key_forward"] > 0: - self.environment["input"]["key_forward"] -= 1 + self.update_key_forward() self.environment["runtime"]["CommandManager"].execute_default_trigger( "onKeyInput" @@ -260,7 +259,7 @@ class FenrirManager: ) def detect_shortcut_command(self): - if self.environment["input"]["key_forward"] > 0: + if self.environment["input"]["key_forward"] != 0: return if len(self.environment["input"]["prev_input"]) > len( @@ -324,6 +323,14 @@ class FenrirManager: ) self.command = "" + def update_key_forward(self): + key_forward = self.environment["input"]["key_forward"] + input_manager = self.environment["runtime"]["InputManager"] + if key_forward == -1 and input_manager.no_key_pressed(): + self.environment["input"]["key_forward"] = 1 + elif key_forward == 1 and input_manager.no_key_pressed(): + self.environment["input"]["key_forward"] = 0 + def set_process_name(self, name="fenrir"): """Attempts to set the process name to 'fenrir'.""" try: diff --git a/tests/unit/test_forward_keypress.py b/tests/unit/test_forward_keypress.py new file mode 100644 index 00000000..40b668fd --- /dev/null +++ b/tests/unit/test_forward_keypress.py @@ -0,0 +1,76 @@ +from unittest.mock import Mock + +import pytest + +from fenrirscreenreader.commands.commands.forward_keypress import command +from fenrirscreenreader.core.fenrirManager import FenrirManager + + +@pytest.mark.unit +def test_forward_keypress_arms_when_command_keys_are_still_down(): + env = { + "input": {"key_forward": 0}, + "runtime": { + "InputManager": Mock(no_key_pressed=Mock(return_value=False)), + "OutputManager": Mock(present_text=Mock()), + }, + } + forward_command = command() + forward_command.initialize(env) + + forward_command.run() + + assert env["input"]["key_forward"] == -1 + + +@pytest.mark.unit +def test_forward_keypress_activates_immediately_when_keyboard_is_idle(): + env = { + "input": {"key_forward": 0}, + "runtime": { + "InputManager": Mock(no_key_pressed=Mock(return_value=True)), + "OutputManager": Mock(present_text=Mock()), + }, + } + forward_command = command() + forward_command.initialize(env) + + forward_command.run() + + assert env["input"]["key_forward"] == 1 + + +@pytest.mark.unit +def test_forward_keypress_waits_for_command_release_before_forwarding(): + input_manager = Mock(no_key_pressed=Mock(return_value=False)) + manager = FenrirManager.__new__(FenrirManager) + manager.environment = { + "input": {"key_forward": -1}, + "runtime": {"InputManager": input_manager}, + } + + manager.update_key_forward() + assert manager.environment["input"]["key_forward"] == -1 + + input_manager.no_key_pressed.return_value = True + manager.update_key_forward() + + assert manager.environment["input"]["key_forward"] == 1 + + +@pytest.mark.unit +def test_forward_keypress_stays_active_until_forwarded_key_release(): + input_manager = Mock(no_key_pressed=Mock(return_value=False)) + manager = FenrirManager.__new__(FenrirManager) + manager.environment = { + "input": {"key_forward": 1}, + "runtime": {"InputManager": input_manager}, + } + + manager.update_key_forward() + assert manager.environment["input"]["key_forward"] == 1 + + input_manager.no_key_pressed.return_value = True + manager.update_key_forward() + + assert manager.environment["input"]["key_forward"] == 0