I want to create a tool which will allow me to use some of the Vim-style commands in an application (Scrivener) that does not support it.
For example, if
- the current mode is
Command
mode and - the user presses the button
w
,
then, the caret should move one character to the right. Instead of the w
character, Scrivener should receive the "right arrow" signal.
To implement this, I wrote the following code (based on these 2 answers: 1, 2):
from pynput.keyboard import Key, Listener, Controller
from typing import Optional
from ctypes import wintypes, windll, create_unicode_buffer
def getForegroundWindowTitle() -> Optional[str]:
hWnd = windll.user32.GetForegroundWindow()
length = windll.user32.GetWindowTextLengthW(hWnd)
buf = create_unicode_buffer(length + 1)
windll.user32.GetWindowTextW(hWnd, buf, length + 1)
if buf.value:
return buf.value
else:
return None
class State:
def __init__(self):
self.mode = "Command"
state = State()
keyboard = Controller()
def on_press(key):
pass
def on_release(key):
if key == Key.f12:
return False
window_title = getForegroundWindowTitle()
if not window_title.endswith("Scrivener"):
return
print("Mode: " + state.mode)
print('{0} release'.format(
key))
if state.mode == "Command":
print("1")
if str(key) == "'w'":
print("2")
print("w released in command mode")
# Press the backspace button to delete the w letter
keyboard.press(Key.backspace)
# Press the right arrow button
keyboard.press(Key.right)
if key == Key.insert:
if state.mode == "Command":
state.mode = "Insert"
else:
state.mode = "Command"
# Collect events until released
print("Press F12 to exit")
with Listener(
on_press=on_press,
on_release=on_release) as listener:
listener.join()
Whenever I press the button w
in Scrivener in Command mode, two keystrokes are sent to Scrivener:
- Backspace to delete the already typed
w
character. - Right arrow to move the caret.
This kinda works, but you can see the w
character being displayed and deleted again (see this video).
How can I make sure that the keystroke with w
does not reach Scrivener at all, if the mode is Command
and currently focused window is the Scrivener application?