diff --git a/plover/oslayer/linux/keyboardcontrol_x11.py b/plover/oslayer/linux/keyboardcontrol_x11.py index 5c01d824a..843361511 100644 --- a/plover/oslayer/linux/keyboardcontrol_x11.py +++ b/plover/oslayer/linux/keyboardcontrol_x11.py @@ -34,7 +34,7 @@ from plover import log from plover.key_combo import add_modifiers_aliases, parse_key_combo from plover.machine.keyboard_capture import Capture -from plover.output import Output +from plover.output.keyboard import GenericKeyboardEmulation # Enable support for media keys. @@ -1128,7 +1128,7 @@ def keysym_to_string(keysym): return chr(code) -class KeyboardEmulation(Output): +class KeyboardEmulation(GenericKeyboardEmulation): class Mapping: @@ -1158,7 +1158,6 @@ def __init__(self): super().__init__() self._display = Display() self._update_keymap() - self._key_press_delay = 0 def _update_keymap(self): '''Analyse keymap, build a mapping of keysym to (keycode + modifiers), @@ -1218,20 +1217,14 @@ def _update_keymap(self): # Get modifier mapping. self.modifier_mapping = self._display.get_modifier_mapping() - def set_key_press_delay(self, delay_ms): - self._key_press_delay = delay_ms - def send_backspaces(self, count): - for x in range(count): + for x in self.with_delay(range(count)): self._send_keycode(self._backspace_mapping.keycode, self._backspace_mapping.modifiers) self._display.sync() - if self._key_press_delay > 0: - sleep(self._key_press_delay / 1000) - def send_string(self, string): - for char in string: + for char in self.with_delay(string): keysym = uchr_to_keysym(char) # TODO: can we find mappings for multiple keys at a time? mapping = self._get_mapping(keysym, automatically_map=False) @@ -1240,9 +1233,6 @@ def send_string(self, string): mapping = self._get_mapping(keysym, automatically_map=True) if mapping is None: continue - if self._key_press_delay > 0: - self._display.sync() - sleep(self._key_press_delay / 2000) mapping_changed = True self._send_keycode(mapping.keycode, @@ -1250,12 +1240,6 @@ def send_string(self, string): self._display.sync() - if self._key_press_delay > 0: - if mapping_changed: - sleep(self._key_press_delay / 2000) - else: - sleep(self._key_press_delay / 1000) - def send_key_combination(self, combo): # Parse and validate combo. key_events = [ @@ -1263,13 +1247,10 @@ def send_key_combination(self, combo): in parse_key_combo(combo, self._get_keycode_from_keystring) ] # Emulate the key combination by sending key events. - for keycode, event_type in key_events: + for keycode, event_type in self.with_delay(key_events): xtest.fake_input(self._display, event_type, keycode) self._display.sync() - if self._key_press_delay > 0: - sleep(self._key_press_delay / 1000) - def _send_keycode(self, keycode, modifiers=0): """Emulate a key press and release. diff --git a/plover/oslayer/osx/keyboardcontrol.py b/plover/oslayer/osx/keyboardcontrol.py index 0b50eb088..644d1d1b4 100644 --- a/plover/oslayer/osx/keyboardcontrol.py +++ b/plover/oslayer/osx/keyboardcontrol.py @@ -46,7 +46,7 @@ from plover import log from plover.key_combo import add_modifiers_aliases, parse_key_combo, KEYNAME_TO_CHAR from plover.machine.keyboard_capture import Capture -from plover.output import Output +from plover.output.keyboard import GenericKeyboardEmulation from .keyboardlayout import KeyboardLayout @@ -302,28 +302,25 @@ def _run(self): self.key_down(key) -class KeyboardEmulation(Output): +class KeyboardEmulation(GenericKeyboardEmulation): RAW_PRESS, STRING_PRESS = range(2) def __init__(self): super().__init__() self._layout = KeyboardLayout() - self._key_press_delay = 0 def set_key_press_delay(self, delay_ms): self._key_press_delay = delay_ms def send_backspaces(self, count): - for _ in range(count): + for _ in self.with_delay(range(count)): backspace_down = CGEventCreateKeyboardEvent( OUTPUT_SOURCE, BACK_SPACE, True) backspace_up = CGEventCreateKeyboardEvent( OUTPUT_SOURCE, BACK_SPACE, False) CGEventPost(kCGSessionEventTap, backspace_down) CGEventPost(kCGSessionEventTap, backspace_up) - if self._key_press_delay > 0: - sleep(self._key_press_delay / 1000) def send_string(self, string): # Key plan will store the type of output @@ -366,15 +363,12 @@ def apply_raw(): apply_raw() # We have a key plan for the whole string, grouping modifiers. - for press_type, sequence in key_plan: + for press_type, sequence in self.with_delay(key_plan): if press_type is self.STRING_PRESS: self._send_string_press(sequence) elif press_type is self.RAW_PRESS: self._send_sequence(sequence) - if self._key_press_delay > 0: - sleep(self._key_press_delay / 1000) - @staticmethod def _send_string_press(c): event = CGEventCreateKeyboardEvent(OUTPUT_SOURCE, 0, True) @@ -405,9 +399,6 @@ def name_to_code(name): # Send events... self._send_sequence(key_events) - if self._key_press_delay > 0: - sleep(self._key_press_delay / 1000) - @staticmethod def _modifier_to_keycodes(modifier): keycodes = [] @@ -456,7 +447,7 @@ def _send_sequence(sequence): # If mods_flags is not zero at the end then bad things might happen. mods_flags = 0 - for keycode, key_down in sequence: + for keycode, key_down in self.with_delay(sequence): if keycode >= NX_KEY_OFFSET: # Handle media (NX) key. event = KeyboardEmulation._get_media_event( diff --git a/plover/oslayer/windows/keyboardcontrol.py b/plover/oslayer/windows/keyboardcontrol.py index f144e57d7..745afdfe6 100644 --- a/plover/oslayer/windows/keyboardcontrol.py +++ b/plover/oslayer/windows/keyboardcontrol.py @@ -27,7 +27,7 @@ from plover.key_combo import parse_key_combo from plover.machine.keyboard_capture import Capture from plover.misc import to_surrogate_pair -from plover.output import Output +from plover.output.keyboard import GenericKeyboardEmulation from .keyboardlayout import KeyboardLayout @@ -426,12 +426,11 @@ def suppress(self, suppressed_keys=()): self._proc.suppress(self._suppressed_keys) -class KeyboardEmulation(Output): +class KeyboardEmulation(GenericKeyboardEmulation): def __init__(self): super().__init__() self.keyboard_layout = KeyboardLayout() - self._key_press_delay = 0 # Sends input types to buffer @staticmethod @@ -499,19 +498,13 @@ def _key_unicode(self, char): for code in pairs] self._send_input(*inputs) - def set_key_press_delay(self, delay_ms): - self._key_press_delay = delay_ms - def send_backspaces(self, count): - for _ in range(count): + for _ in self.with_delay(range(count)): self._key_press('\x08') - if self._key_press_delay > 0: - sleep(self._key_press_delay / 1000) - def send_string(self, string): self._refresh_keyboard_layout() - for char in string: + for char in self.with_delay(string): if char in self.keyboard_layout.char_to_vk_ss: # We know how to simulate the character. self._key_press(char) @@ -519,17 +512,11 @@ def send_string(self, string): # Otherwise, we send it as a Unicode string. self._key_unicode(char) - if self._key_press_delay > 0: - sleep(self._key_press_delay / 1000) - def send_key_combination(self, combo): # Make sure keyboard layout is up-to-date. self._refresh_keyboard_layout() # Parse and validate combo. key_events = parse_key_combo(combo, self.keyboard_layout.keyname_to_vk.get) # Send events... - for keycode, pressed in key_events: + for keycode, pressed in self.with_delay(key_events): self._key_event(keycode, pressed) - - if self._key_press_delay > 0: - sleep(self._key_press_delay / 1000) diff --git a/plover/output/keyboard.py b/plover/output/keyboard.py new file mode 100644 index 000000000..316583755 --- /dev/null +++ b/plover/output/keyboard.py @@ -0,0 +1,19 @@ +from time import sleep + + +class GenericKeyboardEmulation(Output): + def __init__(self): + super().__init__() + self._key_press_delay_ms = 0 + + def set_key_press_delay(self, delay_ms): + self._key_press_delay_ms = delay_ms + + def delay(self): + if self._key_press_delay_ms > 0: + sleep(self._key_press_delay_ms / 1000) + + def with_delay(self, iterable): + for item in iterable: + yield item + self.delay()