Last active
October 26, 2018 23:19
-
-
Save sakurai-youhei/9f8d7bb46d5357f3367a6d46228603ed to your computer and use it in GitHub Desktop.
Python wrapper for xte command
This file contains 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
""" | |
xte v1.09 | |
Generates fake input using the XTest extension, more reliable than xse | |
Author: Steve Slaven - http://hoopajoo.net | |
usage: xte [-h] [-i xinputid] [-x display] [arg ..] | |
-h this help | |
-i XInput2 device to use. List devices with 'xinput list' | |
-x send commands to remote X server. Note that some commands | |
may not work correctly unless the display is on the console, | |
e.g. the display is currently controlled by the keyboard and | |
mouse and not in the background. This seems to be a limitation | |
of the XTest extension. | |
arg args instructing the little man on what to do (see below) | |
if no args are passed, commands are read from stdin separated | |
by newlines, to allow a batch mode | |
Commands: | |
key k Press and release key k | |
keydown k Press key k down | |
keyup k Release key k | |
str string Do a bunch of key X events for each char in string | |
mouseclick i Click mouse button i | |
mousemove x y Move mouse to screen position x,y | |
mousermove x y Move mouse relative from current location by x,y | |
mousedown i Press mouse button i down | |
mouseup i Release mouse button i | |
sleep x Sleep x seconds | |
usleep x uSleep x microseconds | |
Some useful keys (case sensitive) | |
Home | |
Left | |
Up | |
Right | |
Down | |
Page_Up | |
Page_Down | |
End | |
Return | |
BackSpace | |
Tab | |
Escape | |
Delete | |
Shift_L | |
Shift_R | |
Control_L | |
Control_R | |
Meta_L | |
Meta_R | |
Alt_L | |
Alt_R | |
Multi_key | |
Depending on your keyboard layout, the "Windows" key may be one of the | |
Super_ keys or the Meta_ keys. | |
Sample, drag from 100,100 to 200,200 using mouse1: | |
xte 'mousemove 100 100' 'mousedown 1' 'mousemove 200 200' 'mouseup 1' | |
""" | |
from enum import Enum | |
from os import getenv | |
from subprocess import PIPE | |
from subprocess import Popen | |
from typing import Union | |
__all__ = ("Key", "Xte") | |
Key = Enum("Key", {k: k for k in map(str.strip, """\ | |
Home | |
Left | |
Up | |
Right | |
Down | |
Page_Up | |
Page_Down | |
End | |
Return | |
BackSpace | |
Tab | |
Escape | |
Delete | |
Shift_L | |
Shift_R | |
Control_L | |
Control_R | |
Meta_L | |
Meta_R | |
Alt_L | |
Alt_R | |
Multi_key | |
""".splitlines())}) | |
class Xte(Popen): | |
def __init__(self, *xinputid: int, server: str=getenv("DISPLAY", ""), | |
encoding: str="ascii", errors: str="ignore", | |
stdin: int=PIPE, **kwargs) -> None: | |
cmd = ["xte"] | |
for device in xinputid: | |
cmd += ["-i", str(device)] | |
if server: | |
cmd += ["-x", server] | |
Popen.__init__(self, cmd, stdin=stdin, encoding=encoding, | |
errors=errors, **kwargs) | |
def emit(self, *cmds: str) -> None: | |
print(*cmds, sep="\n", file=self.stdin, flush=True) | |
def key(self, k: Union[str, Key]) -> None: | |
"""Press and release key k""" | |
self.emit("key %s" % k) | |
def keydown(self, k: Union[str, Key]) -> None: | |
"""Press key k down""" | |
self.emit("keydown %s" % k) | |
def keyup(self, k: Union[str, Key]) -> None: | |
"""Release key k""" | |
self.emit("keyup %s" % k) | |
def __str(self, string: str) -> None: | |
"""Do a bunch of key X events for each char in string""" | |
self.emit("str %s" % string) | |
def mouseclick(self, i: int) -> None: | |
"""Click mouse button i""" | |
self.emit("mouseclick %d" % i) | |
def mousemove(self, x: int, y: int) -> None: | |
"""Move mouse to screen position x,y""" | |
self.emit("mousemove %d %d" % (x, y)) | |
def mousermove(self, x: int, y: int) -> None: | |
"""Move mouse relative from current location by x,y""" | |
self.emit("mousermove %d %d" % (x, y)) | |
def mousedown(self, i: int) -> None: | |
"""Press mouse button i down""" | |
self.emit("mousedown %d" % i) | |
def mouseup(self, i: int) -> None: | |
"""Release mouse button i""" | |
self.emit("mouseup %d" % i) | |
def sleep(self, x: int) -> None: | |
"""Sleep x seconds""" | |
self.emit("sleep %d" % x) | |
def usleep(self, x: int) -> None: | |
"""uSleep x microseconds""" | |
self.emit("usleep %d" % x) | |
str = __str | |
""" | |
Sample, drag from 100,100 to 200,200 using mouse1: | |
xte 'mousemove 100 100' 'mousedown 1' 'mousemove 200 200' 'mouseup 1' | |
""" | |
if __name__ == "__main__": | |
with Xte() as xte: | |
xte.mousemove(100, 100) | |
xte.mousedown(1) | |
xte.mousemove(200, 200) | |
xte.mouseup(1) | |
# Or xte.emit('mousemove 100 100', | |
# 'mousedown 1', | |
# 'mousemove 200 200', | |
# 'mouseup 1') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment