Skip to content

Instantly share code, notes, and snippets.

@benoit-pierre
Created March 1, 2017 18:59
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save benoit-pierre/9b430fa63a158079a2de708a5df3f7ec to your computer and use it in GitHub Desktop.
Save benoit-pierre/9b430fa63a158079a2de708a5df3f7ec to your computer and use it in GitHub Desktop.
Analyse the output of `xinput test-xi2 --root` for key press/release events
#!/usr/bin/env python3
import itertools
import re
import sys
try:
from plover.oslayer.xkeyboardcontrol import KEYCODE_TO_KEY
except ImportError:
print('error: could not import plover.oslayer.xkeyboardcontrol.KEYCODE_TO_KEY, '
'will print raw key codes instead of key names', file=sys.stderr)
KEYCODE_TO_KEY = {}
class LogAnalyser(object):
def __init__(self, input_device_name=None):
self.keys = set()
self.event = {}
self.input_device_id = set()
self.input_device_name = input_device_name
self.xtest_keyboard_id = None
def process_event(self):
if not self.event:
return
event_type = self.event.get('type')
if event_type not in ('KeyPress', 'KeyRelease'):
return
event_device_id = self.event['device'].split()[0]
if event_device_id == self.xtest_keyboard_id:
return
if event_device_id != (self.input_device_id or event_device_id):
return
event_detail = self.event['detail']
key_name = KEYCODE_TO_KEY.get(int(event_detail), event_detail)
if event_type == 'KeyPress':
event_type = 'press'
self.keys.add(key_name)
else:
event_type = 'release'
self.keys.discard(key_name)
print('%-10s %-10s %s' % (event_type, key_name, '+'.join(sorted(self.keys))))
def analyze(self, input):
self.keys = set()
self.event = {}
for line in itertools.chain(input, ['']):
line = line.strip()
m = re.search('↳ (.*)\s+id=(\d+)', line)
if m is not None:
device_name = m.group(1).strip()
device_id = m.group(2)
if device_name == 'Virtual core XTEST keyboard':
print('XTEST keyboard device:', device_id)
self.xtest_keyboard_id = device_id
elif device_name == self.input_device_name:
print(self.input_device_name + ':', device_id)
self.input_device_id.add(device_id)
m = re.match('^EVENT .* \((\w+)\)$', line)
if m is not None:
self.process_event()
self.event = {'type': m.group(1)}
continue
if not line:
self.process_event()
self.event = {}
continue
m = re.match('^(\w+):(.*)$', line)
if m is not None:
self.event[m.group(1)] = m.group(2).strip()
continue
if __name__ == '__main__':
if len(sys.argv) > 1:
input_filename = sys.argv[1]
else:
input_filename = '-'
if input_filename == '-':
input = sys.stdin
else:
input = open(input_filename)
if len(sys.argv) > 2:
input_device_name = sys.argv[2]
else:
input_device_name = None
analyser = LogAnalyser(input_device_name)
analyser.analyze(input)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment