Fixed XDO not working

General cleanup in accordance with pep8
This commit is contained in:
NeoTheFox 2021-04-18 23:45:25 +03:00
parent 611621d4ab
commit 5d3f0778f1

View File

@ -31,6 +31,7 @@ BUTTON_BITS = {
0x80: 8, 0x80: 8,
} }
def main(): def main():
# Commandline arguments processing # Commandline arguments processing
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
@ -66,14 +67,13 @@ def main():
hidraw_path = get_tablet_hidraw(device_id) hidraw_path = get_tablet_hidraw(device_id)
if hidraw_path is not None: if hidraw_path is not None:
hidraw_paths = hidraw_paths + hidraw_path hidraw_paths = hidraw_paths + hidraw_path
if hidraw_paths: if hidraw_paths:
print("Found %s at %s" % (device_name, hidraw_paths)) print("Found %s at %s" % (device_name, hidraw_paths))
break break
elif not hidraw_paths: elif not hidraw_paths:
print("Could not find any tablet hidraw devices") print("Could not find any tablet hidraw devices")
time.sleep(2) time.sleep(2)
continue continue
threads = [] threads = []
for hidraw_path in hidraw_paths: for hidraw_path in hidraw_paths:
@ -85,14 +85,14 @@ def main():
for thread in threads: for thread in threads:
thread.join() thread.join()
class PollThread(threading.Thread): class PollThread(threading.Thread):
cycle_mode = None cycle_mode = None
scroll_state = None
hidraw_path = None hidraw_path = None
xdo = None xdo = None
SCROLL_STATE=None
def __init__(self, hidraw_path): def __init__(self, hidraw_path):
super(PollThread, self).__init__() super(PollThread, self).__init__()
self.xdo = lib.xdo_new(ffi.NULL) self.xdo = lib.xdo_new(ffi.NULL)
@ -111,7 +111,7 @@ class PollThread(threading.Thread):
time.sleep(5) time.sleep(5)
continue continue
while True: while True:
try: try:
btn = self.get_button_press(hidraw) btn = self.get_button_press(hidraw)
except OSError as e: except OSError as e:
@ -119,29 +119,27 @@ class PollThread(threading.Thread):
time.sleep(3) time.sleep(3)
break break
print("Got button %s" % (btn,)) print("Got button %s" % (btn,))
print(CYCLE_MODES)
print(self.cycle_mode)
if btn == CYCLE_BUTTON and CYCLE_BUTTON is not None: if btn == CYCLE_BUTTON and CYCLE_BUTTON is not None:
self.cycle_mode = self.cycle_mode + 1 self.cycle_mode = self.cycle_mode + 1
if self.cycle_mode > CYCLE_MODES: if self.cycle_mode > CYCLE_MODES:
self.cycle_mode = 1 self.cycle_mode = 1
print("Cycling to mode %s" % (self.cycle_mode,)) print("Cycling to mode %s" % (self.cycle_mode,))
elif self.cycle_mode in DIAL_MODES and btn in DIAL_MODES[self.cycle_mode]: elif self.cycle_mode in DIAL_MODES and btn in DIAL_MODES[self.cycle_mode]:
print("Sending %s from Mode %d" % (DIAL_MODES[self.cycle_mode][btn], self.cycle_mode),) print("Sending %s from Mode %d" % (DIAL_MODES[self.cycle_mode][btn], self.cycle_mode),)
lib.xdo_send_keysequence_window( lib.xdo_send_keysequence_window(
self.xdo, lib.CURRENTWINDOW, DIAL_MODES[self.cycle_mode][btn], 1000) self.xdo, lib.CURRENTWINDOW, DIAL_MODES[self.cycle_mode][btn], 1000)
elif btn in BUTTON_BINDINGS_HOLD: elif btn in BUTTON_BINDINGS_HOLD:
print("Pressing %s" % (BUTTON_BINDINGS_HOLD[btn],)) print("Pressing %s" % (BUTTON_BINDINGS_HOLD[btn],))
lib.xdo_send_keysequence_window_down(self.xdo, lib.CURRENTWINDOW, BUTTON_BINDINGS_HOLD[btn], 12000) lib.xdo_send_keysequence_window_down(self.xdo, lib.CURRENTWINDOW, BUTTON_BINDINGS_HOLD[btn], 12000)
self.get_button_release(hidraw) self.get_button_release(hidraw)
print("Releasing %s" % (BUTTON_BINDINGS_HOLD[btn],)) print("Releasing %s" % (BUTTON_BINDINGS_HOLD[btn],))
lib.xdo_send_keysequence_window_up(self.xdo, lib.CURRENTWINDOW, BUTTON_BINDINGS_HOLD[btn], 12000) lib.xdo_send_keysequence_window_up(self.xdo, lib.CURRENTWINDOW, BUTTON_BINDINGS_HOLD[btn], 12000)
elif btn in BUTTON_BINDINGS: elif btn in BUTTON_BINDINGS:
print("Sending %s" % (BUTTON_BINDINGS[btn],)) print("Sending %s" % (BUTTON_BINDINGS[btn],))
lib.xdo_send_keysequence_window( lib.xdo_send_keysequence_window(
self.xdo, lib.CURRENTWINDOW, BUTTON_BINDINGS[btn], 1000) self.xdo, lib.CURRENTWINDOW, BUTTON_BINDINGS[btn], 1000)
def get_button_press(self,hidraw): def get_button_press(self, hidraw):
while True: while True:
sequence = hidraw.read(12) sequence = hidraw.read(12)
# 0xf7 is what my Kamvas Pro 22 reads # 0xf7 is what my Kamvas Pro 22 reads
@ -149,7 +147,7 @@ class PollThread(threading.Thread):
# Q620M reads as 0xf9 # Q620M reads as 0xf9
if sequence[0] != 0xf7 and sequence[0] != 0x08 and sequence[0] != 0xf9: if sequence[0] != 0xf7 and sequence[0] != 0x08 and sequence[0] != 0xf9:
pass pass
if sequence[1] == 0xe0: # buttons if sequence[1] == 0xe0: # buttons
# doesn't seem like the tablet will let you push two buttons at once # doesn't seem like the tablet will let you push two buttons at once
if sequence[4] > 0: if sequence[4] > 0:
return BUTTON_BITS[sequence[4]] return BUTTON_BITS[sequence[4]]
@ -159,42 +157,43 @@ class PollThread(threading.Thread):
else: else:
# must be button release (all zeros) # must be button release (all zeros)
continue continue
elif sequence[1] == 0xf0: # scroll strip elif sequence[1] == 0xf0: # scroll strip
scroll_pos = sequence[5] scroll_pos = sequence[5]
if scroll_pos == 0: if scroll_pos == 0:
# reset scroll state after lifting finger off scroll strip # reset scroll state after lifting finger off scroll strip
self.SCROLL_STATE = None self.scroll_state = None
elif self.SCROLL_STATE is not None: elif self.scroll_state is not None:
# scroll strip is numbered from top to bottom so a greater new # scroll strip is numbered from top to bottom so a greater new
# value means they scrolled down # value means they scrolled down
if scroll_pos > self.SCROLL_STATE: if scroll_pos > self.scroll_state:
self.SCROLL_STATE = scroll_pos self.scroll_state = scroll_pos
return 'scroll_down' return 'scroll_down'
elif scroll_pos < self.SCROLL_STATE: elif scroll_pos < self.scroll_state:
self.SCROLL_STATE = scroll_pos self.scroll_state = scroll_pos
return 'scroll_up' return 'scroll_up'
else: else:
self.SCROLL_STATE = scroll_pos self.scroll_state = scroll_pos
continue continue
elif sequence[1] == 0xf1: # dial on Q620M, practically 2 buttons elif sequence[1] == 0xf1: # dial on Q620M, practically 2 buttons
if sequence[5] == 0x1: if sequence[5] == 0x1:
return 'dial_cw' return 'dial_cw'
elif sequence[5] == 0xff: elif sequence[5] == 0xff:
return 'dial_ccw' return 'dial_ccw'
else: else:
continue continue
def get_button_release(self,hidraw): def get_button_release(self, hidraw):
while True: while True:
sequence = hidraw.read(12) sequence = hidraw.read(12)
if sequence[1] == 0xe0 and sequence[4] == 0 and sequence[5] == 0: if sequence[1] == 0xe0 and sequence[4] == 0 and sequence[5] == 0:
return True return True
def get_tablet_hidraw(device_id): def get_tablet_hidraw(device_id):
"""Finds the /dev/hidrawX file or files that belong to the given device ID (in xxxx:xxxx format).""" """Finds the /dev/hidrawX file or files that belong to the given device ID (in xxxx:xxxx format)."""
# TODO: is this too fragile? # TODO: is this too fragile?
hidraws = os.listdir('/sys/class/hidraw') hidraws = os.listdir('/sys/class/hidraw')
inputs = []; inputs = []
for h in hidraws: for h in hidraws:
device_path = os.readlink(os.path.join('/sys/class/hidraw', h, 'device')) device_path = os.readlink(os.path.join('/sys/class/hidraw', h, 'device'))
if device_id.upper() in device_path: if device_id.upper() in device_path:
@ -215,7 +214,7 @@ def read_config(config_file):
# It is still better for performance to pre-encode these values # It is still better for performance to pre-encode these values
for binding in CONFIG['Bindings']: for binding in CONFIG['Bindings']:
if binding.isdigit(): if binding.isdigit():
# store button configs with their 1-indexed ID # store button configs with their 1-indexed ID
BUTTON_BINDINGS[int(binding)] = CONFIG['Bindings'][binding].encode('utf-8') BUTTON_BINDINGS[int(binding)] = CONFIG['Bindings'][binding].encode('utf-8')
elif binding == 'scroll_up': elif binding == 'scroll_up':
BUTTON_BINDINGS['scroll_up'] = CONFIG['Bindings'][binding].encode('utf-8') BUTTON_BINDINGS['scroll_up'] = CONFIG['Bindings'][binding].encode('utf-8')
@ -226,10 +225,10 @@ def read_config(config_file):
elif binding == 'dial_ccw': elif binding == 'dial_ccw':
BUTTON_BINDINGS['dial_ccw'] = CONFIG['Bindings'][binding].encode('utf-8') BUTTON_BINDINGS['dial_ccw'] = CONFIG['Bindings'][binding].encode('utf-8')
elif binding == '': elif binding == '':
continue # ignore empty line continue # ignore empty line
else: else:
print("[WARN] unrecognized regular binding '%s'" % (binding,)) print("[WARN] unrecognized regular binding '%s'" % (binding,))
#Same, but for buttons that should be held down # Same, but for buttons that should be held down
if 'Hold' in CONFIG: if 'Hold' in CONFIG:
for binding in CONFIG['Hold']: for binding in CONFIG['Hold']:
if binding.isdigit(): if binding.isdigit():
@ -237,26 +236,28 @@ def read_config(config_file):
elif binding == '': elif binding == '':
continue continue
else: else:
print ("[WARN] unrecognized hold binding '%s'" % (binding,)) print("[WARN] unrecognized hold binding '%s'" % (binding,))
# Assume that if cycle is assigned we have modes for now # Assume that if cycle is assigned we have modes for now
if 'Dial' in CONFIG: if 'Dial' in CONFIG:
CYCLE_BUTTON = int(CONFIG['Dial']['cycle']) CYCLE_BUTTON = int(CONFIG['Dial']['cycle'])
for key in CONFIG: for key in CONFIG:
if key.startswith("Mode"): if key.startswith("Mode"):
# Count the modes # Count the modes
mode = int(key.split(' ')[1]) mode = int(key.split(' ')[1])
if mode > CYCLE_MODES: if mode > CYCLE_MODES:
CYCLE_MODES = mode CYCLE_MODES = mode
DIAL_MODES[mode] = {} DIAL_MODES[mode] = {}
for binding in CONFIG[key]: for binding in CONFIG[key]:
DIAL_MODES[mode][binding] = CONFIG[key][binding].encode('utf-8') DIAL_MODES[mode][binding] = CONFIG[key][binding].encode('utf-8')
def make_rules(): def make_rules():
for device_name, device_id in TABLET_MODELS.items(): for device_name, device_id in TABLET_MODELS.items():
print("# %s" % (device_name, )) print("# %s" % (device_name, ))
VID, PID = device_id.split(':') VID, PID = device_id.split(':')
print('KERNEL=="hidraw*", ATTRS{idVendor}=="%s", ATTRS{idProduct}=="%s", MODE="0660", TAG+="uaccess"' % (VID, PID, )) print('KERNEL=="hidraw*", ATTRS{idVendor}=="%s", ATTRS{idProduct}=="%s", MODE="0660", TAG+="uaccess"' % (VID, PID, ))
def create_default_config(config_file): def create_default_config(config_file):
with open(config_file, 'w') as config: with open(config_file, 'w') as config:
config.write(""" config.write("""
@ -286,5 +287,6 @@ dial_cw=minus
dial_ccw=equal dial_ccw=equal
""") """)
if __name__ == "__main__": if __name__ == "__main__":
main() main()