mouse_client.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. #!/usr/bin/python3
  2. import dbus
  3. import dbus.service
  4. import dbus.mainloop.glib
  5. import time
  6. import evdev
  7. from evdev import *
  8. import logging
  9. from logging import debug, info, warning, error
  10. import os
  11. import sys
  12. from select import select
  13. import pyudev
  14. import re
  15. logging.basicConfig(level=logging.DEBUG)
  16. DBUS_OBJ_BTK_NAME = 'org.thanhle.btkbservice'
  17. DBUS_OBJ_BTK_PATH = '/org/thanhle/btkbservice'
  18. class InputDevice():
  19. inputs = []
  20. @staticmethod
  21. def init():
  22. context = pyudev.Context()
  23. devs = context.list_devices(subsystem="input")
  24. InputDevice.monitor = pyudev.Monitor.from_netlink(context)
  25. InputDevice.monitor.filter_by(subsystem='input')
  26. InputDevice.monitor.start()
  27. for d in [*devs]:
  28. InputDevice.add_device(d)
  29. @staticmethod
  30. def add_device(dev):
  31. if dev.device_node == None or not re.match(".*/event\\d+", dev.device_node):
  32. return
  33. try:
  34. if "ID_INPUT_MOUSE" in dev.properties:
  35. print("detected mouse: " + dev.device_node)
  36. InputDevice.inputs.append(MouseInput(dev.device_node))
  37. except OSError:
  38. error("Failed to connect to %s", dev.device_node)
  39. @staticmethod
  40. def remove_device(dev):
  41. if dev.device_node == None or not re.match(".*/event\\d+", dev.device_node):
  42. return
  43. InputDevice.inputs = list(
  44. filter(lambda i: i.device_node != dev.device_node, InputDevice.inputs))
  45. print("Disconnected %s", dev)
  46. @staticmethod
  47. def set_leds_all(ledvalue):
  48. for dev in InputDevice.inputs:
  49. dev.set_leds(ledvalue)
  50. @staticmethod
  51. def grab(on):
  52. if on:
  53. for dev in InputDevice.inputs:
  54. dev.device.grab()
  55. else:
  56. for dev in InputDevice.inputs:
  57. dev.device.ungrab()
  58. def __init__(self, device_node):
  59. self.device_node = device_node
  60. self.device = evdev.InputDevice(device_node)
  61. self.device.grab()
  62. info("Connected %s", self)
  63. def fileno(self):
  64. return self.device.fd
  65. def __str__(self):
  66. return "%s@%s (%s)" % (self.__class__.__name__, self.device_node, self.device.name)
  67. class MouseInput(InputDevice):
  68. def __init__(self, device_node):
  69. super().__init__(device_node)
  70. self.state = [0, 0, 0, 0]
  71. self.x = 0
  72. self.y = 0
  73. self.z = 0
  74. self.change = False
  75. self.last = 0
  76. self.bus = dbus.SystemBus()
  77. self.btkservice = self.bus.get_object(DBUS_OBJ_BTK_NAME, DBUS_OBJ_BTK_PATH)
  78. self.iface = dbus.Interface(self.btkservice, DBUS_OBJ_BTK_NAME)
  79. self.mouse_delay = 20 / 1000
  80. self.mouse_speed = 1
  81. def send_current(self, ir):
  82. try:
  83. self.iface.send_mouse(0, bytes(ir))
  84. except OSError as err:
  85. error(err)
  86. def change_state(self, event):
  87. if event.type == ecodes.EV_SYN:
  88. current = time.monotonic()
  89. diff = 20/1000
  90. if current - self.last < diff and not self.change:
  91. return
  92. self.last = current
  93. speed = 1
  94. self.state[1] = min(127, max(-127, int(self.x * speed))) & 255
  95. self.state[2] = min(127, max(-127, int(self.y * speed))) & 255
  96. self.state[3] = min(127, max(-127, self.z)) & 255
  97. self.x = 0
  98. self.y = 0
  99. self.z = 0
  100. self.change = False
  101. self.send_current(self.state)
  102. if event.type == ecodes.EV_KEY:
  103. debug("Key event %s %d", ecodes.BTN[event.code], event.value)
  104. self.change = True
  105. if event.code >= 272 and event.code <= 276 and event.value < 2:
  106. button_no = event.code - 272
  107. if event.value == 1:
  108. self.state[0] |= 1 << button_no
  109. else:
  110. self.state[0] &= ~(1 << button_no)
  111. if event.type == ecodes.EV_REL:
  112. if event.code == 0:
  113. self.x += event.value
  114. if event.code == 1:
  115. self.y += event.value
  116. if event.code == 8:
  117. self.z += event.value
  118. def get_info(self):
  119. print("hello")
  120. def set_leds(self, ledvalue):
  121. pass
  122. if __name__ == "__main__":
  123. InputDevice.init()
  124. while True:
  125. desctiptors = [*InputDevice.inputs, InputDevice.monitor]
  126. r = select(desctiptors, [], [])
  127. for i in InputDevice.inputs:
  128. try:
  129. for event in i.device.read():
  130. i.change_state(event)
  131. except OSError as err:
  132. warning(err)