Mouse_Keyboard/src/libs/pyautogui/_pyautogui_x11.py

302 lines
15 KiB
Python

# NOTE - It is a known issue that the keyboard-related functions don't work on Ubuntu VMs in Virtualbox.
# import pyautogui
import sys
import os
from . import LEFT, MIDDLE, RIGHT, KEY_NAMES, isShiftCharacter
# from pyautogui import LEFT, MIDDLE, RIGHT
from Xlib.display import Display
from Xlib import X
from Xlib.ext.xtest import fake_input
import Xlib.XK
BUTTON_NAME_MAPPING = {LEFT: 1, MIDDLE: 2, RIGHT: 3, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7}
if sys.platform in ('java', 'darwin', 'win32'):
raise Exception('The pyautogui_x11 module should only be loaded on a Unix system that supports X11.')
#from pyautogui import *
"""
Much of this code is based on information gleaned from Paul Barton's PyKeyboard in PyUserInput from 2013, itself derived from Akkana Peck's pykey in 2008 ( http://www.shallowsky.com/software/crikey/pykey-0.1 ), itself derived from her "Crikey" lib.
"""
def _position():
"""Returns the current xy coordinates of the mouse cursor as a two-integer
tuple.
Returns:
(x, y) tuple of the current xy coordinates of the mouse cursor.
"""
coord = _display.screen().root.query_pointer()._data
return coord["root_x"], coord["root_y"]
def _size():
return _display.screen().width_in_pixels, _display.screen().height_in_pixels
def _vscroll(clicks, x=None, y=None):
clicks = int(clicks)
if clicks == 0:
return
elif clicks > 0:
button = 4 # scroll up
else:
button = 5 # scroll down
for i in range(abs(clicks)):
_click(x, y, button=button)
def _hscroll(clicks, x=None, y=None):
clicks = int(clicks)
if clicks == 0:
return
elif clicks > 0:
button = 7 # scroll right
else:
button = 6 # scroll left
for i in range(abs(clicks)):
_click(x, y, button=button)
def _scroll(clicks, x=None, y=None):
return _vscroll(clicks, x, y)
def _click(x, y, button):
assert button in BUTTON_NAME_MAPPING.keys(), "button argument not in ('left', 'middle', 'right', 4, 5, 6, 7)"
button = BUTTON_NAME_MAPPING[button]
_mouseDown(x, y, button)
_mouseUp(x, y, button)
def _moveTo(x, y):
fake_input(_display, X.MotionNotify, x=x, y=y)
_display.sync()
def _mouseDown(x, y, button):
_moveTo(x, y)
assert button in BUTTON_NAME_MAPPING.keys(), "button argument not in ('left', 'middle', 'right', 4, 5, 6, 7)"
button = BUTTON_NAME_MAPPING[button]
fake_input(_display, X.ButtonPress, button)
_display.sync()
def _mouseUp(x, y, button):
_moveTo(x, y)
assert button in BUTTON_NAME_MAPPING.keys(), "button argument not in ('left', 'middle', 'right', 4, 5, 6, 7)"
button = BUTTON_NAME_MAPPING[button]
fake_input(_display, X.ButtonRelease, button)
_display.sync()
def _keyDown(key):
"""Performs a keyboard key press without the release. This will put that
key in a held down state.
NOTE: For some reason, this does not seem to cause key repeats like would
happen if a keyboard key was held down on a text field.
Args:
key (str): The key to be pressed down. The valid names are listed in
KEY_NAMES.
Returns:
None
"""
if key not in keyboardMapping or keyboardMapping[key] is None:
return
if type(key) == int:
fake_input(_display, X.KeyPress, key)
_display.sync()
return
needsShift = isShiftCharacter(key)
if needsShift:
fake_input(_display, X.KeyPress, keyboardMapping['shift'])
fake_input(_display, X.KeyPress, keyboardMapping[key])
if needsShift:
fake_input(_display, X.KeyRelease, keyboardMapping['shift'])
_display.sync()
def _keyUp(key):
"""Performs a keyboard key release (without the press down beforehand).
Args:
key (str): The key to be released up. The valid names are listed in
KEY_NAMES.
Returns:
None
"""
"""
Release a given character key. Also works with character keycodes as
integers, but not keysyms.
"""
if key not in keyboardMapping or keyboardMapping[key] is None:
return
if type(key) == int:
keycode = key
else:
keycode = keyboardMapping[key]
fake_input(_display, X.KeyRelease, keycode)
_display.sync()
# Taken from PyKeyboard's ctor function.
_display = Display(os.environ['DISPLAY'])
""" Information for keyboardMapping derived from PyKeyboard's special_key_assignment() function.
The *KB dictionaries in pyautogui map a string that can be passed to keyDown(),
keyUp(), or press() into the code used for the OS-specific keyboard function.
They should always be lowercase, and the same keys should be used across all OSes."""
keyboardMapping = dict([(key, None) for key in KEY_NAMES])
keyboardMapping.update({
'backspace': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('BackSpace')),
'\b': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('BackSpace')),
'tab': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Tab')),
'enter': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Return')),
'return': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Return')),
'shift': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Shift_L')),
'ctrl': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Control_L')),
'alt': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Alt_L')),
'pause': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Pause')),
'capslock': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Caps_Lock')),
'esc': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Escape')),
'escape': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Escape')),
'pgup': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Page_Up')),
'pgdn': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Page_Down')),
'pageup': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Page_Up')),
'pagedown': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Page_Down')),
'end': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('End')),
'home': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Home')),
'left': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Left')),
'up': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Up')),
'right': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Right')),
'down': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Down')),
'select': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Select')),
'print': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Print')),
'execute': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Execute')),
'prtsc': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Print')),
'prtscr': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Print')),
'prntscrn': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Print')),
'printscreen': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Print')),
'insert': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Insert')),
'del': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Delete')),
'delete': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Delete')),
'help': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Help')),
'win': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Super_L')),
'winleft': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Super_L')),
'winright': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Super_R')),
'apps': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Menu')),
'num0': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_0')),
'num1': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_1')),
'num2': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_2')),
'num3': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_3')),
'num4': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_4')),
'num5': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_5')),
'num6': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_6')),
'num7': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_7')),
'num8': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_8')),
'num9': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_9')),
'multiply': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_Multiply')),
'add': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_Add')),
'separator': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_Separator')),
'subtract': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_Subtract')),
'decimal': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_Decimal')),
'divide': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_Divide')),
'f1': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F1')),
'f2': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F2')),
'f3': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F3')),
'f4': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F4')),
'f5': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F5')),
'f6': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F6')),
'f7': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F7')),
'f8': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F8')),
'f9': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F9')),
'f10': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F10')),
'f11': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F11')),
'f12': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F12')),
'f13': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F13')),
'f14': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F14')),
'f15': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F15')),
'f16': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F16')),
'f17': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F17')),
'f18': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F18')),
'f19': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F19')),
'f20': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F20')),
'f21': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F21')),
'f22': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F22')),
'f23': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F23')),
'f24': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F24')),
'numlock': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Num_Lock')),
'scrolllock': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Scroll_Lock')),
'shiftleft': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Shift_L')),
'shiftright': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Shift_R')),
'ctrlleft': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Control_L')),
'ctrlright': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Control_R')),
'altleft': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Alt_L')),
'altright': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Alt_R')),
# These are added because unlike a-zA-Z0-9, the single characters do not have a
' ': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('space')),
'space': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('space')),
'\t': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Tab')),
'\n': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Return')), # for some reason this needs to be cr, not lf
'\r': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Return')),
'\e': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Escape')),
'!': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('exclam')),
'#': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('numbersign')),
'%': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('percent')),
'$': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('dollar')),
'&': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('ampersand')),
'"': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('quotedbl')),
"'": _display.keysym_to_keycode(Xlib.XK.string_to_keysym('apostrophe')),
'(': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('parenleft')),
')': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('parenright')),
'*': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('asterisk')),
'=': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('equal')),
'+': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('plus')),
',': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('comma')),
'-': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('minus')),
'.': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('period')),
'/': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('slash')),
':': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('colon')),
';': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('semicolon')),
'<': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('less')),
'>': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('greater')),
'?': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('question')),
'@': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('at')),
'[': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('bracketleft')),
']': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('bracketright')),
'\\': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('backslash')),
'^': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('asciicircum')),
'_': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('underscore')),
'`': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('grave')),
'{': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('braceleft')),
'|': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('bar')),
'}': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('braceright')),
'~': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('asciitilde')),
})
# Trading memory for time" populate winKB so we don't have to call VkKeyScanA each time.
for c in """abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890""":
keyboardMapping[c] = _display.keysym_to_keycode(Xlib.XK.string_to_keysym(c))