migrate mousemove to libevdev

This commit is contained in:
Keyvan Fatehi
2023-02-05 23:00:01 -08:00
parent 6b2c68017e
commit 762e071f64
3 changed files with 68 additions and 27 deletions

View File

@@ -1,41 +1,85 @@
import pyautogui
import numpy import numpy
import evdev
import keymap import keymap
import libevdev
pyautogui.FAILSAFE = False from libevdev import InputEvent, InputAbsInfo
class DesktopControlInterface(): class DesktopControlInterface():
def __init__(self, resolution): def __init__(self, resolution):
global uinput
self.resolution = resolution self.resolution = resolution
self.ui = evdev.UInput() self.dev = libevdev.Device()
self.valid_actions = ["keyboard", "click", "rightclick", "mousemove", "joystick", "paste"] self.dev.name = 'virtual mouse and keyboard'
x_info = InputAbsInfo(minimum=0, maximum=resolution.width, resolution=200)
self.dev.enable(libevdev.EV_ABS.ABS_X, data=x_info)
y_info = InputAbsInfo(minimum=0, maximum=resolution.height, resolution=200)
self.dev.enable(libevdev.EV_ABS.ABS_Y, data=y_info)
self.dev.enable(libevdev.EV_KEY.BTN_LEFT)
self.dev.enable(libevdev.EV_KEY.BTN_MIDDLE)
self.dev.enable(libevdev.EV_KEY.BTN_RIGHT)
self.uinput = self.dev.create_uinput_device()
def handle_action(self, action, data): def handle_action(self, action, data):
if action == "mousemove": if action == "mousemove":
x = numpy.interp(data["cursorPositionX"], (0, data["displayWidth"]), (0, self.resolution.width)) x = numpy.interp(data["cursorPositionX"], (0, data["displayWidth"]), (0, self.resolution.width))
y = numpy.interp(data["cursorPositionY"], (0, data["displayHeight"]), (0, self.resolution.height)) y = numpy.interp(data["cursorPositionY"], (0, data["displayHeight"]), (0, self.resolution.height))
pyautogui.moveTo(x, y, _pause=False) print(f"mousemove {x} {y}")
# elif action == "joystick": events = [InputEvent(libevdev.EV_ABS.ABS_X, int(x)),
# x = numpy.interp(data["x"], (-38, 38), (0, self.resolution.width)) InputEvent(libevdev.EV_ABS.ABS_Y, int(y)),
# y = numpy.interp(data["y"], (-38, 38), (self.resolution.height, 0)) InputEvent(libevdev.EV_SYN.SYN_REPORT, 0)]
# print(f'{data["y"]} {self.resolution.height} {y}') self.uinput.send_events(events)
# pyautogui.moveTo(x, y, _pause=False)
elif action == "click": elif action == "mousedown":
pyautogui.click() pass
elif action == "mouseup":
pass
elif action == "rightclick": elif action == "rightclick":
pyautogui.rightClick() pass
elif action == "keyboard": elif action == "keyboard":
try: try:
# keymap.reload() # keymap.reload()
osKey = keymap.iOStoLinux[data["key"]] osKey = keymap.iOStoLinux[data["key"]]
self.ui.write(evdev.ecodes.EV_KEY, osKey, data["direction"]) print(osKey)
self.ui.syn() # self.ui.write(e.EV_KEY, osKey, data["direction"])
# self.ui.syn()
except KeyError: except KeyError:
print(f"Unknown key: {data['key']}") print(f"Unknown key: {data['key']}")
elif action == "paste": elif action == "paste":
pass
# might as well support the secureput protocol completely # might as well support the secureput protocol completely
pyautogui.write(data["payload"]["string"]) # pyautogui.write(data["payload"]["string"])
def supports(self, action):
return action in ["keyboard", "click", "rightclick", "mousemove", "joystick", "paste"]
def stop(self): def stop(self):
self.ui.close() pass
# self.ui.close()
if __name__ == "__main__":
import time
import libevdev
from libevdev import InputEvent, InputAbsInfo
dev = libevdev.Device()
dev.name = 'some test device'
a = InputAbsInfo(minimum=0, maximum=1920, resolution=200)
dev.enable(libevdev.EV_ABS.ABS_X, data=a)
a = InputAbsInfo(minimum=0, maximum=1080, resolution=200)
dev.enable(libevdev.EV_ABS.ABS_Y, data=a)
dev.enable(libevdev.EV_KEY.BTN_LEFT)
dev.enable(libevdev.EV_KEY.BTN_MIDDLE)
dev.enable(libevdev.EV_KEY.BTN_RIGHT)
uinput = dev.create_uinput_device()
print("New device at {} ({})".format(uinput.devnode, uinput.syspath))
# Sleep for a bit so udev, libinput, Xorg, Wayland, ... all have had
# a chance to see the device and initialize it. Otherwise the event
# will be sent by the kernel but nothing is ready to listen to the
# device yet.
time.sleep(1)
events = [InputEvent(libevdev.EV_ABS.ABS_X, 1900),
InputEvent(libevdev.EV_ABS.ABS_Y, 1000),
InputEvent(libevdev.EV_SYN.SYN_REPORT, 0)]

View File

@@ -12,7 +12,7 @@ class DesktopStreamTrack(VideoStreamTrack):
def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.resolution = Xlib.display.Display(os.environ["DISPLAY"]).screen().root.get_geometry() self.resolution = Xlib.display.Display(os.environ["DISPLAY"]).screen().root.get_geometry()
self.control_interface = DesktopControlInterface(self.resolution) self.input = DesktopControlInterface(self.resolution)
options = { options = {
'draw_mouse': '1', 'draw_mouse': '1',
'i':':0.0+0,0', 'i':':0.0+0,0',
@@ -30,13 +30,10 @@ class DesktopStreamTrack(VideoStreamTrack):
frame.pts = pts frame.pts = pts
frame.time_base = time_base frame.time_base = time_base
return frame return frame
def handle_action(self, action, data):
self.control_interface.handle_action(action, data)
def stop(self) -> None: def stop(self) -> None:
super().stop() super().stop()
self.control_interface.stop() self.input.stop()
if __name__ == "__main__": if __name__ == "__main__":
from time import time_ns from time import time_ns

View File

@@ -164,8 +164,8 @@ async def signal(signaling):
print(data) print(data)
elif data["type"] == "joystick": elif data["type"] == "joystick":
webjoystick(data["x"], data["y"]) webjoystick(data["x"], data["y"])
elif desktop_track and data["type"] in desktop_track.control_interface.valid_actions: elif desktop_track and desktop_track.input.supports(data["type"]):
desktop_track.handle_action(data["type"], data) desktop_track.input.handle_action(data["type"], data)
else: else:
print("ignored message") print("ignored message")
print(data) print(data)