Created
February 23, 2026 21:54
-
-
Save linktohack/3a754330adccb659aef9c3350693471f to your computer and use it in GitHub Desktop.
Type into (Qemu) VNC session
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env -S uv run --with vncdotool | |
| # /// script | |
| # requires-python = ">=3.12" | |
| # dependencies = ["vncdotool"] | |
| # /// | |
| """Type stdin text into a VNC session. | |
| Usage: | |
| echo "hello" | uv run vnc_type.py [host] [options] | |
| pbpaste | uv run vnc_type.py 127.0.0.1:9 --caps | |
| host format: host:display (e.g. 127.0.0.1:9) or host::port (e.g. 127.0.0.1::5909) | |
| Default: 127.0.0.1::5909 | |
| Options: | |
| --caps Invert shift key up/down (use when caps lock is stuck) | |
| """ | |
| import sys | |
| import argparse | |
| import time | |
| import os | |
| from vncdotool import api | |
| DELAY = 0.02 | |
| SHIFT_MAP = { | |
| '~': '`', '!': '1', '@': '2', '#': '3', '$': '4', '%': '5', | |
| '^': '6', '&': '7', '*': '8', '(': '9', ')': '0', '_': '-', | |
| '+': '=', '{': '[', '}': ']', '|': '\\', ':': ';', '"': "'", | |
| '<': ',', '>': '.', '?': '/', | |
| } | |
| SPECIAL = { | |
| '\n': 'enter', | |
| '\t': 'tab', | |
| ' ': 'space', | |
| } | |
| parser = argparse.ArgumentParser(description="Type stdin into VNC") | |
| parser.add_argument("host", nargs="?", default="127.0.0.1::5909", | |
| help="host:display or host::port (default: 127.0.0.1::5909)") | |
| parser.add_argument("--caps", action="store_true", | |
| help="Invert shift key up/down (use when caps lock is stuck)") | |
| args = parser.parse_args() | |
| text = sys.stdin.read() | |
| client = api.connect(args.host) | |
| # reset modifier keys | |
| client.keyUp('shift') | |
| client.keyUp('ctrl') | |
| client.keyUp('alt') | |
| time.sleep(0.05) | |
| def shift_on(): | |
| if args.caps: | |
| client.keyUp('shift') | |
| else: | |
| client.keyDown('shift') | |
| def shift_off(): | |
| if args.caps: | |
| client.keyDown('shift') | |
| else: | |
| client.keyUp('shift') | |
| for ch in text: | |
| if ch in SPECIAL: | |
| client.keyPress(SPECIAL[ch]) | |
| elif ch == '\r': | |
| continue | |
| elif ch in SHIFT_MAP: | |
| shift_on() | |
| time.sleep(DELAY) | |
| client.keyPress(SHIFT_MAP[ch]) | |
| time.sleep(DELAY) | |
| shift_off() | |
| elif ch.isupper(): | |
| shift_on() | |
| time.sleep(DELAY) | |
| client.keyPress(ch) | |
| time.sleep(DELAY) | |
| shift_off() | |
| else: | |
| client.keyPress(ch) | |
| time.sleep(DELAY) | |
| client.disconnect() | |
| os._exit(0) |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
If typefile is working fine for you, use that!