Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[NODRIVER] Port pypeter input #2019

Open
boludoz opened this issue Sep 13, 2024 · 7 comments
Open

[NODRIVER] Port pypeter input #2019

boludoz opened this issue Sep 13, 2024 · 7 comments

Comments

@boludoz
Copy link

boludoz commented Sep 13, 2024

add to utils:
from typing import Optional, List, Set, Union, Callable, Dict

"""Keyboard and Mouse module."""

"""US Keyboard Definition."""

key_definitions = {
    '0': {'keyCode': 48, 'key': '0', 'code': 'Digit0'},
    '1': {'keyCode': 49, 'key': '1', 'code': 'Digit1'},
    '2': {'keyCode': 50, 'key': '2', 'code': 'Digit2'},
    '3': {'keyCode': 51, 'key': '3', 'code': 'Digit3'},
    '4': {'keyCode': 52, 'key': '4', 'code': 'Digit4'},
    '5': {'keyCode': 53, 'key': '5', 'code': 'Digit5'},
    '6': {'keyCode': 54, 'key': '6', 'code': 'Digit6'},
    '7': {'keyCode': 55, 'key': '7', 'code': 'Digit7'},
    '8': {'keyCode': 56, 'key': '8', 'code': 'Digit8'},
    '9': {'keyCode': 57, 'key': '9', 'code': 'Digit9'},
    'Power': {'key': 'Power', 'code': 'Power'},
    'Eject': {'key': 'Eject', 'code': 'Eject'},
    'Abort': {'keyCode': 3, 'code': 'Abort', 'key': 'Cancel'},
    'Help': {'keyCode': 6, 'code': 'Help', 'key': 'Help'},
    'Backspace': {'keyCode': 8, 'code': 'Backspace', 'key': 'Backspace'},
    'Tab': {'keyCode': 9, 'code': 'Tab', 'key': 'Tab'},
    'Numpad5': {'keyCode': 12, 'shiftKeyCode': 101, 'key': 'Clear', 'code': 'Numpad5', 'shiftKey': '5', 'location': 3},
    'NumpadEnter': {'keyCode': 13, 'code': 'NumpadEnter', 'key': 'Enter', 'text': '\r', 'location': 3},
    'Enter': {'keyCode': 13, 'code': 'Enter', 'key': 'Enter', 'text': '\r'},
    '\r': {'keyCode': 13, 'code': 'Enter', 'key': 'Enter', 'text': '\r'},
    '\n': {'keyCode': 13, 'code': 'Enter', 'key': 'Enter', 'text': '\r'},
    'ShiftLeft': {'keyCode': 16, 'code': 'ShiftLeft', 'key': 'Shift', 'location': 1},
    'ShiftRight': {'keyCode': 16, 'code': 'ShiftRight', 'key': 'Shift', 'location': 2},
    'ControlLeft': {'keyCode': 17, 'code': 'ControlLeft', 'key': 'Control', 'location': 1},
    'ControlRight': {'keyCode': 17, 'code': 'ControlRight', 'key': 'Control', 'location': 2},
    'AltLeft': {'keyCode': 18, 'code': 'AltLeft', 'key': 'Alt', 'location': 1},
    'AltRight': {'keyCode': 18, 'code': 'AltRight', 'key': 'Alt', 'location': 2},
    'Pause': {'keyCode': 19, 'code': 'Pause', 'key': 'Pause'},
    'CapsLock': {'keyCode': 20, 'code': 'CapsLock', 'key': 'CapsLock'},
    'Escape': {'keyCode': 27, 'code': 'Escape', 'key': 'Escape'},
    'Convert': {'keyCode': 28, 'code': 'Convert', 'key': 'Convert'},
    'NonConvert': {'keyCode': 29, 'code': 'NonConvert', 'key': 'NonConvert'},
    'Space': {'keyCode': 32, 'code': 'Space', 'key': ' '},
    'Numpad9': {'keyCode': 33, 'shiftKeyCode': 105, 'key': 'PageUp', 'code': 'Numpad9', 'shiftKey': '9', 'location': 3},
    'PageUp': {'keyCode': 33, 'code': 'PageUp', 'key': 'PageUp'},
    'Numpad3': {'keyCode': 34, 'shiftKeyCode': 99, 'key': 'PageDown', 'code': 'Numpad3', 'shiftKey': '3', 'location': 3},
    'PageDown': {'keyCode': 34, 'code': 'PageDown', 'key': 'PageDown'},
    'End': {'keyCode': 35, 'code': 'End', 'key': 'End'},
    'Numpad1': {'keyCode': 35, 'shiftKeyCode': 97, 'key': 'End', 'code': 'Numpad1', 'shiftKey': '1', 'location': 3},
    'Home': {'keyCode': 36, 'code': 'Home', 'key': 'Home'},
    'Numpad7': {'keyCode': 36, 'shiftKeyCode': 103, 'key': 'Home', 'code': 'Numpad7', 'shiftKey': '7', 'location': 3},
    'ArrowLeft': {'keyCode': 37, 'code': 'ArrowLeft', 'key': 'ArrowLeft'},
    'Numpad4': {'keyCode': 37, 'shiftKeyCode': 100, 'key': 'ArrowLeft', 'code': 'Numpad4', 'shiftKey': '4', 'location': 3},
    'Numpad8': {'keyCode': 38, 'shiftKeyCode': 104, 'key': 'ArrowUp', 'code': 'Numpad8', 'shiftKey': '8', 'location': 3},
    'ArrowUp': {'keyCode': 38, 'code': 'ArrowUp', 'key': 'ArrowUp'},
    'ArrowRight': {'keyCode': 39, 'code': 'ArrowRight', 'key': 'ArrowRight'},
    'Numpad6': {'keyCode': 39, 'shiftKeyCode': 102, 'key': 'ArrowRight', 'code': 'Numpad6', 'shiftKey': '6', 'location': 3},
    'Numpad2': {'keyCode': 40, 'shiftKeyCode': 98, 'key': 'ArrowDown', 'code': 'Numpad2', 'shiftKey': '2', 'location': 3},
    'ArrowDown': {'keyCode': 40, 'code': 'ArrowDown', 'key': 'ArrowDown'},
    'Select': {'keyCode': 41, 'code': 'Select', 'key': 'Select'},
    'Open': {'keyCode': 43, 'code': 'Open', 'key': 'Execute'},
    'PrintScreen': {'keyCode': 44, 'code': 'PrintScreen', 'key': 'PrintScreen'},
    'Insert': {'keyCode': 45, 'code': 'Insert', 'key': 'Insert'},
    'Numpad0': {'keyCode': 45, 'shiftKeyCode': 96, 'key': 'Insert', 'code': 'Numpad0', 'shiftKey': '0', 'location': 3},
    'Delete': {'keyCode': 46, 'code': 'Delete', 'key': 'Delete'},
    'NumpadDecimal': {'keyCode': 46, 'shiftKeyCode': 110, 'code': 'NumpadDecimal', 'key': '\u0000', 'shiftKey': '.', 'location': 3},
    'Digit0': {'keyCode': 48, 'code': 'Digit0', 'shiftKey': ')', 'key': '0'},
    'Digit1': {'keyCode': 49, 'code': 'Digit1', 'shiftKey': '!', 'key': '1'},
    'Digit2': {'keyCode': 50, 'code': 'Digit2', 'shiftKey': '@', 'key': '2'},
    'Digit3': {'keyCode': 51, 'code': 'Digit3', 'shiftKey': '#', 'key': '3'},
    'Digit4': {'keyCode': 52, 'code': 'Digit4', 'shiftKey': '$', 'key': '4'},
    'Digit5': {'keyCode': 53, 'code': 'Digit5', 'shiftKey': '%', 'key': '5'},
    'Digit6': {'keyCode': 54, 'code': 'Digit6', 'shiftKey': '^', 'key': '6'},
    'Digit7': {'keyCode': 55, 'code': 'Digit7', 'shiftKey': '&', 'key': '7'},
    'Digit8': {'keyCode': 56, 'code': 'Digit8', 'shiftKey': '*', 'key': '8'},
    'Digit9': {'keyCode': 57, 'code': 'Digit9', 'shiftKey': '(', 'key': '9'},
    'KeyA': {'keyCode': 65, 'code': 'KeyA', 'shiftKey': 'A', 'key': 'a'},
    'KeyB': {'keyCode': 66, 'code': 'KeyB', 'shiftKey': 'B', 'key': 'b'},
    'KeyC': {'keyCode': 67, 'code': 'KeyC', 'shiftKey': 'C', 'key': 'c'},
    'KeyD': {'keyCode': 68, 'code': 'KeyD', 'shiftKey': 'D', 'key': 'd'},
    'KeyE': {'keyCode': 69, 'code': 'KeyE', 'shiftKey': 'E', 'key': 'e'},
    'KeyF': {'keyCode': 70, 'code': 'KeyF', 'shiftKey': 'F', 'key': 'f'},
    'KeyG': {'keyCode': 71, 'code': 'KeyG', 'shiftKey': 'G', 'key': 'g'},
    'KeyH': {'keyCode': 72, 'code': 'KeyH', 'shiftKey': 'H', 'key': 'h'},
    'KeyI': {'keyCode': 73, 'code': 'KeyI', 'shiftKey': 'I', 'key': 'i'},
    'KeyJ': {'keyCode': 74, 'code': 'KeyJ', 'shiftKey': 'J', 'key': 'j'},
    'KeyK': {'keyCode': 75, 'code': 'KeyK', 'shiftKey': 'K', 'key': 'k'},
    'KeyL': {'keyCode': 76, 'code': 'KeyL', 'shiftKey': 'L', 'key': 'l'},
    'KeyM': {'keyCode': 77, 'code': 'KeyM', 'shiftKey': 'M', 'key': 'm'},
    'KeyN': {'keyCode': 78, 'code': 'KeyN', 'shiftKey': 'N', 'key': 'n'},
    'KeyO': {'keyCode': 79, 'code': 'KeyO', 'shiftKey': 'O', 'key': 'o'},
    'KeyP': {'keyCode': 80, 'code': 'KeyP', 'shiftKey': 'P', 'key': 'p'},
    'KeyQ': {'keyCode': 81, 'code': 'KeyQ', 'shiftKey': 'Q', 'key': 'q'},
    'KeyR': {'keyCode': 82, 'code': 'KeyR', 'shiftKey': 'R', 'key': 'r'},
    'KeyS': {'keyCode': 83, 'code': 'KeyS', 'shiftKey': 'S', 'key': 's'},
    'KeyT': {'keyCode': 84, 'code': 'KeyT', 'shiftKey': 'T', 'key': 't'},
    'KeyU': {'keyCode': 85, 'code': 'KeyU', 'shiftKey': 'U', 'key': 'u'},
    'KeyV': {'keyCode': 86, 'code': 'KeyV', 'shiftKey': 'V', 'key': 'v'},
    'KeyW': {'keyCode': 87, 'code': 'KeyW', 'shiftKey': 'W', 'key': 'w'},
    'KeyX': {'keyCode': 88, 'code': 'KeyX', 'shiftKey': 'X', 'key': 'x'},
    'KeyY': {'keyCode': 89, 'code': 'KeyY', 'shiftKey': 'Y', 'key': 'y'},
    'KeyZ': {'keyCode': 90, 'code': 'KeyZ', 'shiftKey': 'Z', 'key': 'z'},
    'MetaLeft': {'keyCode': 91, 'code': 'MetaLeft', 'key': 'Meta'},
    'MetaRight': {'keyCode': 92, 'code': 'MetaRight', 'key': 'Meta'},
    'ContextMenu': {'keyCode': 93, 'code': 'ContextMenu', 'key': 'ContextMenu'},
    'NumpadMultiply': {'keyCode': 106, 'code': 'NumpadMultiply', 'key': '*', 'location': 3},
    'NumpadAdd': {'keyCode': 107, 'code': 'NumpadAdd', 'key': '+', 'location': 3},
    'NumpadSubtract': {'keyCode': 109, 'code': 'NumpadSubtract', 'key': '-', 'location': 3},
    'NumpadDivide': {'keyCode': 111, 'code': 'NumpadDivide', 'key': '/', 'location': 3},
    'F1': {'keyCode': 112, 'code': 'F1', 'key': 'F1'},
    'F2': {'keyCode': 113, 'code': 'F2', 'key': 'F2'},
    'F3': {'keyCode': 114, 'code': 'F3', 'key': 'F3'},
    'F4': {'keyCode': 115, 'code': 'F4', 'key': 'F4'},
    'F5': {'keyCode': 116, 'code': 'F5', 'key': 'F5'},
    'F6': {'keyCode': 117, 'code': 'F6', 'key': 'F6'},
    'F7': {'keyCode': 118, 'code': 'F7', 'key': 'F7'},
    'F8': {'keyCode': 119, 'code': 'F8', 'key': 'F8'},
    'F9': {'keyCode': 120, 'code': 'F9', 'key': 'F9'},
    'F10': {'keyCode': 121, 'code': 'F10', 'key': 'F10'},
    'F11': {'keyCode': 122, 'code': 'F11', 'key': 'F11'},
    'F12': {'keyCode': 123, 'code': 'F12', 'key': 'F12'},
    'F13': {'keyCode': 124, 'code': 'F13', 'key': 'F13'},
    'F14': {'keyCode': 125, 'code': 'F14', 'key': 'F14'},
    'F15': {'keyCode': 126, 'code': 'F15', 'key': 'F15'},
    'F16': {'keyCode': 127, 'code': 'F16', 'key': 'F16'},
    'F17': {'keyCode': 128, 'code': 'F17', 'key': 'F17'},
    'F18': {'keyCode': 129, 'code': 'F18', 'key': 'F18'},
    'F19': {'keyCode': 130, 'code': 'F19', 'key': 'F19'},
    'F20': {'keyCode': 131, 'code': 'F20', 'key': 'F20'},
    'F21': {'keyCode': 132, 'code': 'F21', 'key': 'F21'},
    'F22': {'keyCode': 133, 'code': 'F22', 'key': 'F22'},
    'F23': {'keyCode': 134, 'code': 'F23', 'key': 'F23'},
    'F24': {'keyCode': 135, 'code': 'F24', 'key': 'F24'},
    'NumLock': {'keyCode': 144, 'code': 'NumLock', 'key': 'NumLock'},
    'ScrollLock': {'keyCode': 145, 'code': 'ScrollLock', 'key': 'ScrollLock'},
    'AudioVolumeMute': {'keyCode': 173, 'code': 'AudioVolumeMute', 'key': 'AudioVolumeMute'},
    'AudioVolumeDown': {'keyCode': 174, 'code': 'AudioVolumeDown', 'key': 'AudioVolumeDown'},
    'AudioVolumeUp': {'keyCode': 175, 'code': 'AudioVolumeUp', 'key': 'AudioVolumeUp'},
    'MediaTrackNext': {'keyCode': 176, 'code': 'MediaTrackNext', 'key': 'MediaTrackNext'},
    'MediaTrackPrevious': {'keyCode': 177, 'code': 'MediaTrackPrevious', 'key': 'MediaTrackPrevious'},
    'MediaStop': {'keyCode': 178, 'code': 'MediaStop', 'key': 'MediaStop'},
    'MediaPlayPause': {'keyCode': 179, 'code': 'MediaPlayPause', 'key': 'MediaPlayPause'},
    'Semicolon': {'keyCode': 186, 'code': 'Semicolon', 'shiftKey': ':', 'key': ';'},
    'Equal': {'keyCode': 187, 'code': 'Equal', 'shiftKey': '+', 'key': '='},
    'NumpadEqual': {'keyCode': 187, 'code': 'NumpadEqual', 'key': '=', 'location': 3},
    'Comma': {'keyCode': 188, 'code': 'Comma', 'shiftKey': '<', 'key': ','},
    'Minus': {'keyCode': 189, 'code': 'Minus', 'shiftKey': '_', 'key': '-'},
    'Period': {'keyCode': 190, 'code': 'Period', 'shiftKey': '>', 'key': '.'},
    'Slash': {'keyCode': 191, 'code': 'Slash', 'shiftKey': '?', 'key': '/'},
    'Backquote': {'keyCode': 192, 'code': 'Backquote', 'shiftKey': '~', 'key': '`'},
    'BracketLeft': {'keyCode': 219, 'code': 'BracketLeft', 'shiftKey': '{', 'key': '['},
    'Backslash': {'keyCode': 220, 'code': 'Backslash', 'shiftKey': '|', 'key': '\\'},
    'BracketRight': {'keyCode': 221, 'code': 'BracketRight', 'shiftKey': '}', 'key': ']'},
    'Quote': {'keyCode': 222, 'code': 'Quote', 'shiftKey': '"', 'key': '\''},
    'AltGraph': {'keyCode': 225, 'code': 'AltGraph', 'key': 'AltGraph'},
    'Props': {'keyCode': 247, 'code': 'Props', 'key': 'CrSel'},
    'Cancel': {'keyCode': 3, 'key': 'Cancel', 'code': 'Abort'},
    'Clear': {'keyCode': 12, 'key': 'Clear', 'code': 'Numpad5', 'location': 3},
    'Shift': {'keyCode': 16, 'key': 'Shift', 'code': 'ShiftLeft'},
    'Control': {'keyCode': 17, 'key': 'Control', 'code': 'ControlLeft'},
    'Alt': {'keyCode': 18, 'key': 'Alt', 'code': 'AltLeft'},
    'Accept': {'keyCode': 30, 'key': 'Accept'},
    'ModeChange': {'keyCode': 31, 'key': 'ModeChange'},
    ' ': {'keyCode': 32, 'key': ' ', 'code': 'Space'},
    'Print': {'keyCode': 42, 'key': 'Print'},
    'Execute': {'keyCode': 43, 'key': 'Execute', 'code': 'Open'},
    '\u0000': {'keyCode': 46, 'key': '\u0000', 'code': 'NumpadDecimal', 'location': 3},
    'a': {'keyCode': 65, 'key': 'a', 'code': 'KeyA'},
    'b': {'keyCode': 66, 'key': 'b', 'code': 'KeyB'},
    'c': {'keyCode': 67, 'key': 'c', 'code': 'KeyC'},
    'd': {'keyCode': 68, 'key': 'd', 'code': 'KeyD'},
    'e': {'keyCode': 69, 'key': 'e', 'code': 'KeyE'},
    'f': {'keyCode': 70, 'key': 'f', 'code': 'KeyF'},
    'g': {'keyCode': 71, 'key': 'g', 'code': 'KeyG'},
    'h': {'keyCode': 72, 'key': 'h', 'code': 'KeyH'},
    'i': {'keyCode': 73, 'key': 'i', 'code': 'KeyI'},
    'j': {'keyCode': 74, 'key': 'j', 'code': 'KeyJ'},
    'k': {'keyCode': 75, 'key': 'k', 'code': 'KeyK'},
    'l': {'keyCode': 76, 'key': 'l', 'code': 'KeyL'},
    'm': {'keyCode': 77, 'key': 'm', 'code': 'KeyM'},
    'n': {'keyCode': 78, 'key': 'n', 'code': 'KeyN'},
    'o': {'keyCode': 79, 'key': 'o', 'code': 'KeyO'},
    'p': {'keyCode': 80, 'key': 'p', 'code': 'KeyP'},
    'q': {'keyCode': 81, 'key': 'q', 'code': 'KeyQ'},
    'r': {'keyCode': 82, 'key': 'r', 'code': 'KeyR'},
    's': {'keyCode': 83, 'key': 's', 'code': 'KeyS'},
    't': {'keyCode': 84, 'key': 't', 'code': 'KeyT'},
    'u': {'keyCode': 85, 'key': 'u', 'code': 'KeyU'},
    'v': {'keyCode': 86, 'key': 'v', 'code': 'KeyV'},
    'w': {'keyCode': 87, 'key': 'w', 'code': 'KeyW'},
    'x': {'keyCode': 88, 'key': 'x', 'code': 'KeyX'},
    'y': {'keyCode': 89, 'key': 'y', 'code': 'KeyY'},
    'z': {'keyCode': 90, 'key': 'z', 'code': 'KeyZ'},
    'Meta': {'keyCode': 91, 'key': 'Meta', 'code': 'MetaLeft'},
    '*': {'keyCode': 106, 'key': '*', 'code': 'NumpadMultiply', 'location': 3},
    '+': {'keyCode': 107, 'key': '+', 'code': 'NumpadAdd', 'location': 3},
    '-': {'keyCode': 109, 'key': '-', 'code': 'NumpadSubtract', 'location': 3},
    '/': {'keyCode': 111, 'key': '/', 'code': 'NumpadDivide', 'location': 3},
    ';': {'keyCode': 186, 'key': ';', 'code': 'Semicolon'},
    '=': {'keyCode': 187, 'key': '=', 'code': 'Equal'},
    ',': {'keyCode': 188, 'key': ',', 'code': 'Comma'},
    '.': {'keyCode': 190, 'key': '.', 'code': 'Period'},
    '`': {'keyCode': 192, 'key': '`', 'code': 'Backquote'},
    '[': {'keyCode': 219, 'key': '[', 'code': 'BracketLeft'},
    '\\': {'keyCode': 220, 'key': '\\', 'code': 'Backslash'},
    ']': {'keyCode': 221, 'key': ']', 'code': 'BracketRight'},
    '\'': {'keyCode': 222, 'key': '\'', 'code': 'Quote'},
    'Attn': {'keyCode': 246, 'key': 'Attn'},
    'CrSel': {'keyCode': 247, 'key': 'CrSel', 'code': 'Props'},
    'ExSel': {'keyCode': 248, 'key': 'ExSel'},
    'EraseEof': {'keyCode': 249, 'key': 'EraseEof'},
    'Play': {'keyCode': 250, 'key': 'Play'},
    'ZoomOut': {'keyCode': 251, 'key': 'ZoomOut'},
    ')': {'keyCode': 48, 'key': ')', 'code': 'Digit0'},
    '!': {'keyCode': 49, 'key': '!', 'code': 'Digit1'},
    '@': {'keyCode': 50, 'key': '@', 'code': 'Digit2'},
    '#': {'keyCode': 51, 'key': '#', 'code': 'Digit3'},
    '$': {'keyCode': 52, 'key': '$', 'code': 'Digit4'},
    '%': {'keyCode': 53, 'key': '%', 'code': 'Digit5'},
    '^': {'keyCode': 54, 'key': '^', 'code': 'Digit6'},
    '&': {'keyCode': 55, 'key': '&', 'code': 'Digit7'},
    '(': {'keyCode': 57, 'key': '(', 'code': 'Digit9'},
    'A': {'keyCode': 65, 'key': 'A', 'code': 'KeyA'},
    'B': {'keyCode': 66, 'key': 'B', 'code': 'KeyB'},
    'C': {'keyCode': 67, 'key': 'C', 'code': 'KeyC'},
    'D': {'keyCode': 68, 'key': 'D', 'code': 'KeyD'},
    'E': {'keyCode': 69, 'key': 'E', 'code': 'KeyE'},
    'F': {'keyCode': 70, 'key': 'F', 'code': 'KeyF'},
    'G': {'keyCode': 71, 'key': 'G', 'code': 'KeyG'},
    'H': {'keyCode': 72, 'key': 'H', 'code': 'KeyH'},
    'I': {'keyCode': 73, 'key': 'I', 'code': 'KeyI'},
    'J': {'keyCode': 74, 'key': 'J', 'code': 'KeyJ'},
    'K': {'keyCode': 75, 'key': 'K', 'code': 'KeyK'},
    'L': {'keyCode': 76, 'key': 'L', 'code': 'KeyL'},
    'M': {'keyCode': 77, 'key': 'M', 'code': 'KeyM'},
    'N': {'keyCode': 78, 'key': 'N', 'code': 'KeyN'},
    'O': {'keyCode': 79, 'key': 'O', 'code': 'KeyO'},
    'P': {'keyCode': 80, 'key': 'P', 'code': 'KeyP'},
    'Q': {'keyCode': 81, 'key': 'Q', 'code': 'KeyQ'},
    'R': {'keyCode': 82, 'key': 'R', 'code': 'KeyR'},
    'S': {'keyCode': 83, 'key': 'S', 'code': 'KeyS'},
    'T': {'keyCode': 84, 'key': 'T', 'code': 'KeyT'},
    'U': {'keyCode': 85, 'key': 'U', 'code': 'KeyU'},
    'V': {'keyCode': 86, 'key': 'V', 'code': 'KeyV'},
    'W': {'keyCode': 87, 'key': 'W', 'code': 'KeyW'},
    'X': {'keyCode': 88, 'key': 'X', 'code': 'KeyX'},
    'Y': {'keyCode': 89, 'key': 'Y', 'code': 'KeyY'},
    'Z': {'keyCode': 90, 'key': 'Z', 'code': 'KeyZ'},
    ':': {'keyCode': 186, 'key': ':', 'code': 'Semicolon'},
    '<': {'keyCode': 188, 'key': '<', 'code': 'Comma'},
    '_': {'keyCode': 189, 'key': '_', 'code': 'Minus'},
    '>': {'keyCode': 190, 'key': '>', 'code': 'Period'},
    '?': {'keyCode': 191, 'key': '?', 'code': 'Slash'},
    '~': {'keyCode': 192, 'key': '~', 'code': 'Backquote'},
    '{': {'keyCode': 219, 'key': '{', 'code': 'BracketLeft'},
    '|': {'keyCode': 220, 'key': '|', 'code': 'Backslash'},
    '}': {'keyCode': 221, 'key': '}', 'code': 'BracketRight'},
    '"': {'keyCode': 222, 'key': '"', 'code': 'Quote'},
}

def merge_dict(dict1: Optional[Dict], dict2: Optional[Dict]) -> Dict:
    """Merge two dictionaries into new one."""
    new_dict = {}
    if dict1:
        new_dict.update(dict1)
    if dict2:
        new_dict.update(dict2)
    return new_dict

@boludoz
Copy link
Author

boludoz commented Sep 13, 2024

There is still some work to be done.

@boludoz

This comment was marked as outdated.

@boludoz

This comment was marked as outdated.

@boludoz
Copy link
Author

boludoz commented Sep 13, 2024

Personally, this method disgusts me, I only did it for fun.

@boludoz
Copy link
Author

boludoz commented Sep 13, 2024

Modified tab.py file

from __future__ import annotations
import asyncio
import json
import logging
import pathlib
import typing
import warnings
from typing import List, Union, Optional, Tuple
from typing import Any, Dict, Optional, TYPE_CHECKING
if TYPE_CHECKING:
    from typing import Set

import nodriver.core.browser
from . import element
from . import util
from .util import merge_dict, key_definitions
from .config import PathLike
from .connection import Connection, ProtocolException
from .. import cdp
    def __init__(
        self,
        websocket_url: str,
        target: cdp.target.TargetInfo,
        browser: Optional["nodriver.Browser"] = None,
        **kwargs,
    ):
        super().__init__(websocket_url, target, browser, **kwargs)
        self.browser = browser
        self._dom = None
        self._window_id = None
        self.keyboard = self.Keyboard(self)
        self.touchscreen = self.Touchscreen(self)
        self.mouse = self.Mouse(self)

    class Keyboard:
        def __init__(self, tab: 'Tab') -> None:
            self.tab = tab
            self._modifiers = 0
            self._pressed_keys: Set[str] = set()

        def __enter__(self):
            return self

        def __exit__(self, exc_type, exc_val, exc_tb):
            pass

        async def down(self, key: str, options: dict = None, **kwargs: Any) -> None:
            """Dispatch a ``keydown`` event with ``key``."""
            options = merge_dict(options, kwargs)
    
            description = self._key_description_for_string(key)
            autoRepeat = description['code'] in self._pressed_keys
            self._pressed_keys.add(description['code'])
            self._modifiers |= self._modifier_bit(description['key'])
    
            text = options.get('text')
            if text is None:
                text = description['text']
                
            await self.tab.send(cdp.input_.dispatch_key_event(
                type_ = "keyDown" if text else "rawKeyDown",
                modifiers = self._modifiers,
                windows_virtual_key_code = description['keyCode'],
                code = description['code'],
                key = description['key'],
                text = text,
                unmodified_text = text,
                auto_repeat = autoRepeat,
                location = description['location'],
                is_keypad = description['location'] == 3,        
            ))
    
        def _modifier_bit(self, key: str) -> int:
            if key == 'Alt':
                return 1
            if key == 'Control':
                return 2
            if key == 'Meta':
                return 4
            if key == 'Shift':
                return 8
            return 0
    
        def _key_description_for_string(self, keyString: str) -> Dict:  # noqa: C901
            shift = self._modifiers & 8
            description = {
                'key': '',
                'keyCode': 0,
                'code': '',
                'text': '',
                'location': 0,
            }
    
            definition: Dict = key_definitions.get(keyString)  # type: ignore
            if not definition:
                raise Exception(f'Unknown key: {keyString}')
    
            if 'key' in definition:
                description['key'] = definition['key']
            if shift and definition.get('shiftKey'):
                description['key'] = definition['shiftKey']
    
            if 'keyCode' in definition:
                description['keyCode'] = definition['keyCode']
            if shift and definition.get('shiftKeyCode'):
                description['keyCode'] = definition['shiftKeyCode']
    
            if 'code' in definition:
                description['code'] = definition['code']
    
            if 'location' in definition:
                description['location'] = definition['location']
    
            if len(description['key']) == 1:  # type: ignore
                description['text'] = description['key']
    
            if 'text' in definition:
                description['text'] = definition['text']
            if shift and definition.get('shiftText'):
                description['text'] = definition['shiftText']
    
            if self._modifiers & ~8:
                description['text'] = ''
    
            return description
    
        async def up(self, key: str) -> None:
            """Dispatch a ``keyup`` event of the ``key``."""
            description = self._key_description_for_string(key)
    
            self._modifiers &= ~self._modifier_bit(description['key'])
            if description['code'] in self._pressed_keys:
                self._pressed_keys.remove(description['code'])
            await self.tab.send(cdp.input_.dispatch_key_event(
                type_ = "keyUp",
                modifiers = self._modifiers,
                key = description['key'],
                windows_virtual_key_code = description['keyCode'],
                code = description['code'],
                location = description['location'],       
            ))
    
        async def send_character(self, char: str) -> None:
            """Send character into the page."""
            await self.tab.send(cdp.input_.insert_text(char))
    
        async def type(self, text: str, options: Dict = None, **kwargs: Any) -> None:
            """Type characters into a focused element."""
            options = merge_dict(options, kwargs)
            delay = options.get('delay', 0)
            for char in text:
                if char in key_definitions:
                    await self.press(char, {'delay': delay})
                else:
                    await self.send_character(char)
                if delay:
                    await asyncio.sleep(delay / 1000)
    
        async def press(self, key: str, options: Dict = None, **kwargs: Any) -> None:
            """Press ``key``."""
            options = merge_dict(options, kwargs)
    
            await self.down(key, options)
            if 'delay' in options:
                await asyncio.sleep(options['delay'] / 1000)
            await self.up(key)

    class Mouse:
        """Mouse class.

        The :class:`Mouse` operates in main-frame CSS pixels relative to the
        top-left corner of the viewport.
        """

        def __init__(self, tab: 'Tab') -> None:
            self.tab = tab
            self._x = 0.0
            self._y = 0.0
            self._button = 'none'

        def __enter__(self):
            return self

        def __exit__(self, exc_type, exc_val, exc_tb):
            pass

        async def move(self, x: float, y: float, options: dict = None,
                    **kwargs: Any) -> None:
            """Move mouse cursor (dispatches a ``mousemove`` event).

            Options can accepts ``steps`` (int) field. If this ``steps`` option
            specified, Sends intermediate ``mousemove`` events. Defaults to 1.
            """
            options = merge_dict(options, kwargs)
            from_x = self._x
            from_y = self._y
            self._x = x
            self._y = y
            steps = options.get('steps', 1)
            for i in range(1, steps + 1):
                x = round(from_x + (self._x - from_x) * (i / steps))
                y = round(from_y + (self._y - from_y) * (i / steps))
                await self.tab.send(cdp.input_.dispatch_mouse_event(
                    type_ = 'mouseMoved',
                    x = x,
                    y = y,
                    modifiers = self.tab.keyboard._modifiers,
                    button = self._button,
                ))

        async def click(self, x: float, y: float, options: dict = None,
                        **kwargs: Any) -> None:
            """Click button at (``x``, ``y``).

            Shortcut to :meth:`move`, :meth:`down`, and :meth:`up`.

            This method accepts the following options:

            * ``button`` (str): ``left``, ``right``, or ``middle``, defaults to
            ``left``.
            * ``clickCount`` (int): defaults to 1.
            * ``delay`` (int|float): Time to wait between ``mousedown`` and
            ``mouseup`` in milliseconds. Defaults to 0.
            """
            options = merge_dict(options, kwargs)
            await self.move(x, y)
            await self.down(options)
            if options and options.get('delay'):
                await asyncio.sleep(options.get('delay', 0) / 1000)
            await self.up(options)

        async def down(self, options: dict = None, **kwargs: Any) -> None:
            """Press down button (dispatches ``mousedown`` event).

            This method accepts the following options:

            * ``button`` (str): ``left``, ``right``, or ``middle``, defaults to
            ``left``.
            * ``clickCount`` (int): defaults to 1.
            """
            options = merge_dict(options, kwargs)
            self._button = options.get('button', 'left')
            await self.tab.send(cdp.input_.dispatch_mouse_event(
                type_ = 'mousePressed',
                button = self._button,
                x = self._x,
                y = self._y,
                modifiers = self.tab.keyboard._modifiers,
                click_count = options.get('clickCount') or 1,
            ))

        async def up(self, options: dict = None, **kwargs: Any) -> None:
            """Release pressed button (dispatches ``mouseup`` event).

            This method accepts the following options:

            * ``button`` (str): ``left``, ``right``, or ``middle``, defaults to
            ``left``.
            * ``clickCount`` (int): defaults to 1.
            """
            options = merge_dict(options, kwargs)
            self._button = 'none'
            await self.tab.send(cdp.input_.dispatch_mouse_event(
                type_ = 'mouseReleased',
                button = options.get('button', 'left'),
                x = self._x,
                y = self._y,
                modifiers = self.tab.keyboard._modifiers,
                click_count = options.get('clickCount') or 1,
            ))

    class Touchscreen:
        """Touchscreen class."""

        def __init__(self, tab: 'Tab') -> None:
            """Make new touchscreen object."""
            self.tab = tab

        def __enter__(self):
            return self

        def __exit__(self, exc_type, exc_val, exc_tb):
            pass

        async def tap(self, x: float, y: float) -> None:
            """Tap (``x``, ``y``).

            Dispatches a ``touchstart`` and ``touchend`` event.
            """
            touch_points = [{'x': round(x), 'y': round(y)}]
            await self.tab.send(cdp.input_.dispatch_touch_event(
                type_ = 'touchStart',
                touch_points = touch_points,
                modifiers = self.tab.keyboard._modifiers,
            ))
            await self.tab.send(cdp.input_.dispatch_touch_event(
                type_ = 'touchEnd',
                touch_points = [],
                modifiers = self.tab.keyboard._modifiers,
            ))

usage:

import asyncio
import nodriver as uc

async def main():
    browser = await uc.start()
    tab_instance = await browser.get('https://www.google.com/')
    await asyncio.sleep(1)
    with tab_instance.keyboard as keyboard_instance:
        await (await tab_instance.find('//input[1]')).click()
        await keyboard_instance.type('Hello World!')
        await keyboard_instance.down('Enter')
        await asyncio.sleep(5)

if __name__ == '__main__':

    # since asyncio.run never worked (for me)
    uc.loop().run_until_complete(main())

@boludoz
Copy link
Author

boludoz commented Sep 13, 2024

nodriver.zip

@artcrespo
Copy link

Hi @boludoz is this in pull-request?

artcrespo added a commit to artcrespo/nodriver that referenced this issue Nov 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants