WASD mouse control
'''
Move the mouse using the 'w', 'a', 's', 'd' directional keys.
'''
import map2
import time
import threading
map2.default(layout="us")
# an easy to use interval utility that allows running functions on a timer
class setInterval:
def __init__(self, interval, action):
self.interval = interval / 1000
self.action = action
self.stopEvent = threading.Event()
thread = threading.Thread(target=self.__setInterval)
thread.start()
def __setInterval(self):
nextTime = time.time() + self.interval
while not self.stopEvent.wait(nextTime - time.time()):
nextTime += self.interval
self.action()
def cancel(self):
self.stopEvent.set()
# read from keyboard
reader_kbd = map2.Reader(patterns=["/dev/input/by-id/example-keyboard"])
# to move the mouse programmatically, we need a mouse reader we can write into
reader_mouse = map2.Reader()
# add new virtual output devices
writer_kbd = map2.Writer(clone_from="/dev/input/by-id/example-keyboard")
writer_mouse = map2.Writer(capabilities={"rel": True, "buttons": True})
# add mapper
mapper_kbd = map2.Mapper()
# setup the event routing
map2.link([reader_kbd, mapper_kbd, writer_kbd])
map2.link([reader_mouse, writer_mouse])
# we keep a map of intervals that maps each key to the associated interval
intervals = {}
def mouse_ctrl(key, state, axis, multiplier):
def inner_fn():
# on key release, remove and cancel the corresponding interval
if state == 0:
if key in intervals:
intervals.pop(key).cancel()
return
# this function will move our mouse using the virtual reader
def send():
value = 15 * multiplier
reader_mouse.send("{{relative {} {}}}".format(axis, value))
# we call it once to move the mouse a bit immediately on key down
send()
# and register an interval that will continue to move it on a timer
intervals[key] = setInterval(20, send)
return inner_fn
# setup the key mappings
mapper_kbd.map("w up", mouse_ctrl("w", 0, "Y", -1))
mapper_kbd.map("w down", mouse_ctrl("w", 1, "Y", -1))
mapper_kbd.nop("w repeat")
mapper_kbd.map("a up", mouse_ctrl("a", 0, "X", -1))
mapper_kbd.map("a down", mouse_ctrl("a", 1, "X", -1))
mapper_kbd.nop("a repeat")
mapper_kbd.map("s up", mouse_ctrl("s", 0, "Y", 1))
mapper_kbd.map("s down", mouse_ctrl("s", 1, "Y", 1))
mapper_kbd.nop("s repeat")
mapper_kbd.map("d up", mouse_ctrl("d", 0, "X", 1))
mapper_kbd.map("d down", mouse_ctrl("d", 1, "X", 1))
mapper_kbd.nop("d repeat")
# Keep running forever
map2.wait()
Allows moving the mouse by binding the WASD directional keys to functions that emmit mouse move events.
This script uses a custom interval implementation to control how much the mouse
should be moved. An alternative approach would be binding the WASD repeat
state
to move the mouse every time a repeat
key event is received.