Add x11 autotype
This commit is contained in:
parent
f0773b5fd3
commit
e5779265c4
|
@ -1,14 +1,35 @@
|
||||||
{
|
{
|
||||||
"name": "python3-tendo",
|
"name": "python3-requirements",
|
||||||
"buildsystem": "simple",
|
"buildsystem": "simple",
|
||||||
"build-commands": [
|
"build-commands": [],
|
||||||
"pip3 install --verbose --exists-action=i --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} \"tendo==0.3.0\" --no-build-isolation"
|
"modules": [
|
||||||
],
|
|
||||||
"sources": [
|
|
||||||
{
|
{
|
||||||
"type": "file",
|
"name": "python3-tendo",
|
||||||
"url": "https://files.pythonhosted.org/packages/ce/3f/761077d55732b0b1a673b15d4fdaa947a7c1eb5c9a23b7142df557019823/tendo-0.3.0-py3-none-any.whl",
|
"buildsystem": "simple",
|
||||||
"sha256": "026b70b355ea4c9da7c2123fa2d5c280c8983c1b34e329ff49260e2e78b93be7"
|
"build-commands": [
|
||||||
|
"pip3 install --verbose --exists-action=i --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} \"tendo==0.3.0\" --no-build-isolation"
|
||||||
|
],
|
||||||
|
"sources": [
|
||||||
|
{
|
||||||
|
"type": "file",
|
||||||
|
"url": "https://files.pythonhosted.org/packages/ce/3f/761077d55732b0b1a673b15d4fdaa947a7c1eb5c9a23b7142df557019823/tendo-0.3.0-py3-none-any.whl",
|
||||||
|
"sha256": "026b70b355ea4c9da7c2123fa2d5c280c8983c1b34e329ff49260e2e78b93be7"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "python3-python3-xlib",
|
||||||
|
"buildsystem": "simple",
|
||||||
|
"build-commands": [
|
||||||
|
"pip3 install --verbose --exists-action=i --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} \"python3-xlib==0.15\" --no-build-isolation"
|
||||||
|
],
|
||||||
|
"sources": [
|
||||||
|
{
|
||||||
|
"type": "file",
|
||||||
|
"url": "https://files.pythonhosted.org/packages/ef/c6/2c5999de3bb1533521f1101e8fe56fd9c266732f4d48011c7c69b29d12ae/python3-xlib-0.15.tar.gz",
|
||||||
|
"sha256": "dc4245f3ae4aa5949c1d112ee4723901ade37a96721ba9645f2bfa56e5b383f8"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -1 +1,2 @@
|
||||||
tendo==0.3.0
|
tendo==0.3.0
|
||||||
|
python3-xlib==0.15
|
|
@ -5,10 +5,12 @@ is_linux = sys.platform == 'linux'
|
||||||
is_wayland = os.environ.get('XDG_SESSION_TYPE') == 'wayland'
|
is_wayland = os.environ.get('XDG_SESSION_TYPE') == 'wayland'
|
||||||
|
|
||||||
def autotype(text):
|
def autotype(text):
|
||||||
print("autotypeing, is_linux: {}, is_wayland: {}".format(is_linux, is_wayland))
|
|
||||||
if is_linux and is_wayland:
|
if is_linux and is_wayland:
|
||||||
from .libportal_autotype import autotype_libportal
|
from .libportal_autotype import autotype_libportal
|
||||||
autotype_libportal(text)
|
autotype_libportal(text)
|
||||||
|
elif is_linux:
|
||||||
from .pyautogui_autotype import autotype_pyautogui
|
from .x11autotype import type
|
||||||
autotype_pyautogui(text)
|
type(text)
|
||||||
|
else:
|
||||||
|
from .pyautogui_autotype import autotype_pyautogui
|
||||||
|
autotype_pyautogui(text)
|
|
@ -0,0 +1,107 @@
|
||||||
|
# https://github.com/gemdude46/autotype/blob/master/LICENSE
|
||||||
|
# MIT License
|
||||||
|
|
||||||
|
# Copyright (c) 2017 gemdude46
|
||||||
|
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
|
# in the Software without restriction, including without limitation the rights
|
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
# copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
# The above copyright notice and this permission notice shall be included in all
|
||||||
|
# copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
|
||||||
|
from Xlib.display import Display
|
||||||
|
from Xlib import X
|
||||||
|
from Xlib.ext.xtest import fake_input
|
||||||
|
|
||||||
|
_display = Display(os.environ['DISPLAY'])
|
||||||
|
|
||||||
|
def type(text, delay=0.03, down_for=0):
|
||||||
|
'''Fake key presses to type out text.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
text (str): The text to type out.
|
||||||
|
delay (float): The time to wait between presses. (In seconds)
|
||||||
|
down_for (float): How long to keep each key down. (In seconds)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
None
|
||||||
|
'''
|
||||||
|
|
||||||
|
# Save the users existing keyboard mapping
|
||||||
|
kbm_backup = _display.get_keyboard_mapping(8,246)
|
||||||
|
|
||||||
|
try:
|
||||||
|
|
||||||
|
text = text.replace('\n', '\r') # Because X
|
||||||
|
|
||||||
|
# Splits the text into blocks containing no more than 245 unique characters
|
||||||
|
# This is because there is a limited number of valid xmodmap keycodes
|
||||||
|
while text:
|
||||||
|
chars = set()
|
||||||
|
|
||||||
|
i = 0
|
||||||
|
while i < len(text) and len(chars) < 245:
|
||||||
|
char = ord(text[i])
|
||||||
|
chars.add(char)
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
block = text[:i]
|
||||||
|
text = text[i:]
|
||||||
|
|
||||||
|
_type_lt245(block, delay, down_for)
|
||||||
|
|
||||||
|
finally:
|
||||||
|
|
||||||
|
# Restore the keyboard layout to how it was originally
|
||||||
|
_display.change_keyboard_mapping(8, kbm_backup)
|
||||||
|
_display.sync()
|
||||||
|
|
||||||
|
def _type_lt245(text, delay, down_for):
|
||||||
|
|
||||||
|
xmm = ''
|
||||||
|
|
||||||
|
chars = []
|
||||||
|
|
||||||
|
keys = []
|
||||||
|
|
||||||
|
text = [(1 << 24) + ord(i) for i in text]
|
||||||
|
|
||||||
|
for char in text:
|
||||||
|
if char not in chars:
|
||||||
|
chars.append(char)
|
||||||
|
|
||||||
|
keys.append(chars.index(char) + 8)
|
||||||
|
|
||||||
|
for i in range(8, 255):
|
||||||
|
fake_input(_display, X.KeyRelease, i)
|
||||||
|
|
||||||
|
_display.change_keyboard_mapping(8, [(i, ) * 15 for i in chars])
|
||||||
|
_display.sync()
|
||||||
|
|
||||||
|
for key in keys:
|
||||||
|
|
||||||
|
fake_input(_display, X.KeyPress, key)
|
||||||
|
_display.sync()
|
||||||
|
|
||||||
|
time.sleep(down_for)
|
||||||
|
|
||||||
|
fake_input(_display, X.KeyRelease, key)
|
||||||
|
_display.sync()
|
||||||
|
|
||||||
|
time.sleep(delay)
|
||||||
|
|
Loading…
Reference in New Issue