From c373457dff57e1656437cf4859bd917071a2ce47 Mon Sep 17 00:00:00 2001 From: Andrew Kay Date: Fri, 27 Dec 2019 20:14:30 -0600 Subject: [PATCH] Implement cursor blink and reverse toggle --- oec/controller.py | 19 +++++++++++--- oec/display.py | 9 +++++++ oec/keyboard.py | 3 +++ oec/terminal.py | 8 +++++- tests/test_controller.py | 56 +++++++++++++++++++++++++++++++++++++++- 5 files changed, 89 insertions(+), 6 deletions(-) diff --git a/oec/controller.py b/oec/controller.py index b08a4b3..f922bb0 100644 --- a/oec/controller.py +++ b/oec/controller.py @@ -5,8 +5,8 @@ oec.controller import time import logging -from coax import poll, poll_ack, PollAction, KeystrokePollResponse, ReceiveTimeout, \ - ReceiveError, ProtocolError +from coax import poll, poll_ack, load_control_register, PollAction, \ + KeystrokePollResponse, ReceiveTimeout, ReceiveError, ProtocolError from .terminal import Terminal, read_terminal_ids from .keyboard import Key @@ -156,8 +156,16 @@ class Controller: if not key: return - if key == Key.CLICKER: - self.terminal.keyboard.clicker = not self.terminal.keyboard.clicker + if key == Key.CURSOR_BLINK: + self.terminal.display.toggle_cursor_blink() + + self._load_control_register() + elif key == Key.ALT_CURSOR: + self.terminal.display.toggle_cursor_reverse() + + self._load_control_register() + elif key == Key.CLICKER: + self.terminal.keyboard.toggle_clicker() elif self.session: self.session.handle_key(key, modifiers, scan_code) @@ -198,3 +206,6 @@ class Controller: period = self.disconnected_poll_period return (self.last_poll_time + period) - current_time + + def _load_control_register(self): + load_control_register(self.interface, self.terminal.get_control_register()) diff --git a/oec/display.py b/oec/display.py index 6ac6cbf..5deae14 100644 --- a/oec/display.py +++ b/oec/display.py @@ -181,6 +181,9 @@ class Display: self.status_line = StatusLine(self.interface, columns) + self.cursor_reverse = False + self.cursor_blink = False + def move_cursor(self, index=None, row=None, column=None, force_load=False): """Load the address counter.""" address = self._calculate_address(index=index, row=row, column=column) @@ -239,6 +242,12 @@ class Display: self.move_cursor(row=0, column=0, force_load=True) + def toggle_cursor_blink(self): + self.cursor_blink = not self.cursor_blink + + def toggle_cursor_reverse(self): + self.cursor_reverse = not self.cursor_reverse + def _get_index(self, row, column): return (row * self.dimensions.columns) + column diff --git a/oec/keyboard.py b/oec/keyboard.py index 7c7c0c3..e6f31c4 100644 --- a/oec/keyboard.py +++ b/oec/keyboard.py @@ -333,6 +333,9 @@ class Keyboard: return (key, self.modifiers, False) + def toggle_clicker(self): + self.clicker = not self.clicker + def _apply_modifiers(self, scan_code, key): # TODO: Consider detection, in single modifier release mode, of entering # modififier release but the next keystroke not being a modifier... also diff --git a/oec/terminal.py b/oec/terminal.py index d8c1bd3..2436480 100644 --- a/oec/terminal.py +++ b/oec/terminal.py @@ -5,7 +5,7 @@ oec.terminal import time import logging -from coax import read_terminal_id, read_extended_id, PollAction, ReceiveError, \ +from coax import read_terminal_id, read_extended_id, PollAction, Control, ReceiveError, \ ProtocolError from .display import Dimensions, Display @@ -87,3 +87,9 @@ class Terminal: return PollAction.ENABLE_KEYBOARD_CLICKER if self.keyboard.clicker else PollAction.DISABLE_KEYBOARD_CLICKER return PollAction.NONE + + def get_control_register(self): + control = Control(cursor_reverse=self.display.cursor_reverse, + cursor_blink=self.display.cursor_blink) + + return control diff --git a/tests/test_controller.py b/tests/test_controller.py index 390c442..b756079 100644 --- a/tests/test_controller.py +++ b/tests/test_controller.py @@ -37,6 +37,10 @@ class RunLoopTestCase(unittest.TestCase): self.read_terminal_ids_mock.return_value = TERMINAL_IDS + patcher = patch('oec.controller.load_control_register') + + self.load_control_register_mock = patcher.start() + patcher = patch('oec.controller.time.perf_counter') self.perf_counter_mock = patcher.start() @@ -114,7 +118,57 @@ class RunLoopTestCase(unittest.TestCase): self.assertFalse(self.controller.terminal.alarm) - def test_clicker_toggle(self): + def test_toggle_cursor_blink(self): + self._assert_run_loop(0, PowerOnResetCompletePollResponse(0xa), 0, True) + + self.assertFalse(self.controller.terminal.display.cursor_blink) + + self._assert_run_loop(0, KeystrokePollResponse(0b0101010010), 0, True) + + self.assertTrue(self.controller.terminal.display.cursor_blink) + + self.load_control_register_mock.assert_called() + + self.assertTrue(self.load_control_register_mock.call_args[0][1].cursor_blink) + + self.load_control_register_mock.reset_mock() + + self._assert_run_loop(0, KeystrokePollResponse(0b0101010010), 0, True) + + self.assertFalse(self.controller.terminal.display.cursor_blink) + + self.load_control_register_mock.assert_called() + + self.assertFalse(self.load_control_register_mock.call_args[0][1].cursor_blink) + + def test_toggle_cursor_reverse(self): + self._assert_run_loop(0, PowerOnResetCompletePollResponse(0xa), 0, True) + + self.assertFalse(self.controller.terminal.display.cursor_reverse) + + self._assert_run_loop(0, KeystrokePollResponse(0b0100111110), 0, True) + self._assert_run_loop(0, KeystrokePollResponse(0b0101010010), 0, True) + self._assert_run_loop(0, KeystrokePollResponse(0b0100111110), 0, True) + + self.assertTrue(self.controller.terminal.display.cursor_reverse) + + self.load_control_register_mock.assert_called() + + self.assertTrue(self.load_control_register_mock.call_args[0][1].cursor_reverse) + + self.load_control_register_mock.reset_mock() + + self._assert_run_loop(0, KeystrokePollResponse(0b0100111110), 0, True) + self._assert_run_loop(0, KeystrokePollResponse(0b0101010010), 0, True) + self._assert_run_loop(0, KeystrokePollResponse(0b0100111110), 0, True) + + self.assertFalse(self.controller.terminal.display.cursor_reverse) + + self.load_control_register_mock.assert_called() + + self.assertFalse(self.load_control_register_mock.call_args[0][1].cursor_reverse) + + def test_toggle_clicker(self): self._assert_run_loop(0, PowerOnResetCompletePollResponse(0xa), 0, True) self.assertFalse(self.controller.terminal.keyboard.clicker)