mirror of
https://github.com/jtgans/g13gui.git
synced 2025-06-20 08:23:50 -04:00
input: Restructure to use GObject and io_watches
This isn't ideal, since opening all of the devices in /dev/input is slow, and this runs on the UI thread, but it works for now. Ultimately, InputReader should probably be restructured as a threading.Thread and use GLib.idle_add to send the signals out.
This commit is contained in:
parent
65c2580e45
commit
ce8a106ea3
@ -1,63 +1,94 @@
|
|||||||
import threading
|
|
||||||
import gi
|
import gi
|
||||||
import glob
|
import evdev
|
||||||
import asyncio
|
import threading
|
||||||
|
|
||||||
|
from evdev import InputDevice
|
||||||
|
from evdev import KeyEvent
|
||||||
|
from evdev import ecodes
|
||||||
|
|
||||||
gi.require_version('Gtk', '3.0')
|
gi.require_version('Gtk', '3.0')
|
||||||
from gi.repository import GObject
|
from gi.repository import GObject, GLib
|
||||||
|
|
||||||
import evdev
|
|
||||||
from evdev import InputDevice
|
|
||||||
from evdev import ecodes
|
|
||||||
from select import select
|
|
||||||
|
|
||||||
|
|
||||||
class InputReader(threading.Thread, GObject.GObject):
|
class InputReader(GObject.Object):
|
||||||
INPUT_PATH = '/dev/input'
|
INPUT_PATH = '/dev/input'
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
threading.Thread.__init__(self, daemon=True)
|
GObject.Object.__init__(self)
|
||||||
GObject.GObject.__init__(self)
|
|
||||||
self.reset()
|
|
||||||
|
|
||||||
def reset(self):
|
self._capturing = False
|
||||||
self._isRunning = False
|
self._watches = []
|
||||||
self._keyStates = {}
|
self._keyStates = {}
|
||||||
|
|
||||||
@GObject.Signal(name='evdev-key-released')
|
def capture(self):
|
||||||
def keyReleased(self, keyCode, time):
|
if self._capturing:
|
||||||
print('key released: %d')
|
return False
|
||||||
|
|
||||||
@GObject.Signal(name='evdev-key-pressed')
|
self._capturing = True
|
||||||
def keyPressed(self, keyCode, time):
|
|
||||||
print('key pressed: %d')
|
|
||||||
|
|
||||||
def run(self):
|
self._keyStates = {}
|
||||||
loop = asyncio.new_event_loop()
|
|
||||||
asyncio.set_event_loop(loop)
|
|
||||||
|
|
||||||
devices = [InputDevice(path) for path in evdev.list_devices()]
|
devices = [InputDevice(path) for path in evdev.list_devices()]
|
||||||
keyboards = [dev for dev in devices if ecodes.EV_KEY in dev.capabilities()]
|
self._keyboards = [dev for dev in devices
|
||||||
print('Have keyboards: %s' % (keyboards))
|
if ecodes.EV_KEY in dev.capabilities()]
|
||||||
|
self._keyboards = {dev.fd: dev for dev in self._keyboards}
|
||||||
|
self._watches = []
|
||||||
|
for fd, kbd in self._keyboards.items():
|
||||||
|
watch = GLib.io_add_watch(fd,
|
||||||
|
GLib.PRIORITY_HIGH,
|
||||||
|
GLib.IO_IN,
|
||||||
|
self.handleEvent)
|
||||||
|
self._watches.append(watch)
|
||||||
|
|
||||||
while self._isRunning:
|
return False
|
||||||
r, w, x = select(keyboards, [], [])
|
|
||||||
print('keyboards listening!')
|
|
||||||
for fd in r:
|
|
||||||
for event in keyboards[fd].read():
|
|
||||||
if event.type != ecodes.EV_KEY:
|
|
||||||
continue
|
|
||||||
|
|
||||||
keyCode = event.keycode
|
def stop(self):
|
||||||
keyDown = event.keystate == event.key_down
|
if not self._capturing:
|
||||||
lastKeyState = self._keystates.get(keyCode, False)
|
return False
|
||||||
|
|
||||||
if keyDown and not lastKeyState:
|
for i in self._watches:
|
||||||
self.emit('evdev-key-pressed',
|
GLib.source_remove(i)
|
||||||
keyCode, event.event.timestamp())
|
|
||||||
elif not keyDown and lastKeyState:
|
|
||||||
self.emit('evdev-key-released',
|
|
||||||
keyCode, event.event.timestamp())
|
|
||||||
|
|
||||||
def shutdown(self):
|
for fd, kbd in self._keyboards.items():
|
||||||
self._isRunning = False
|
del kbd
|
||||||
|
del fd
|
||||||
|
|
||||||
|
self._keyboards = None
|
||||||
|
self._watches = []
|
||||||
|
self._keyStates = {}
|
||||||
|
self._capturing = False
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
def handleEvent(self, fd, condition, *args):
|
||||||
|
for event in self._keyboards[fd].read():
|
||||||
|
if event.type != ecodes.EV_KEY:
|
||||||
|
continue
|
||||||
|
|
||||||
|
event = KeyEvent(event)
|
||||||
|
if 'BTN_MOUSE' in event.keycode:
|
||||||
|
continue
|
||||||
|
|
||||||
|
keyCode = event.scancode
|
||||||
|
keyDown = event.keystate in (
|
||||||
|
event.key_down, event.key_hold)
|
||||||
|
lastKeyState = self._keyStates.get(keyCode, False)
|
||||||
|
|
||||||
|
if keyDown and not lastKeyState:
|
||||||
|
self.emit('evdev-key-pressed',
|
||||||
|
keyCode, event.event.timestamp())
|
||||||
|
elif not keyDown and lastKeyState:
|
||||||
|
self.emit('evdev-key-released',
|
||||||
|
keyCode, event.event.timestamp())
|
||||||
|
|
||||||
|
self._keyStates[keyCode] = keyDown
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
@GObject.Signal(name='evdev-key-released', arg_types=[int, float])
|
||||||
|
def keyReleased(self, keyCode, time):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@GObject.Signal(name='evdev-key-pressed', arg_types=[int, float])
|
||||||
|
def keyPressed(self, keyCode, time):
|
||||||
|
pass
|
||||||
|
Loading…
Reference in New Issue
Block a user