Source code for pi3d.event.EventHandler

import threading

from pi3d.event.Constants import *
from pi3d.event.EventStream import EventStream

[docs]class EventHandler(object): """ A class to handle events. Four types of events are handled: REL (mouse movement), KEY (keybaord keys and other device buttons), ABS (joysticks and gamepad analogue sticks) and SYN (delimits simultaneous events such as mouse movements) """ def __init__(self, keyHandler=None, relHandler=None, absHandler=None, synHandler=None): self.buttons = dict() self.relHandler = relHandler self.keyHandler = keyHandler self.absHandler = absHandler self.synHandler = synHandler self.mutex = threading.Lock() self.absx = [0.0]*16 self.absy = [0.0]*16 self.absz = [0.0]*16 self.absx2 = [0.0]*16 self.absy2 = [0.0]*16 self.absz2 = [0.0]*16 self.abshatx = [0.0]*16 self.abshaty = [0.0]*16 self.relx = [0]*16 self.rely = [0]*16 self.relv = [0]*16 self.relh = [0]*16 self.reld = [0]*16
[docs] def event(self, event): """ Handles the given event. If the event is passed to a handler or otherwise handled then returns None, else returns the event. All handlers are optional. All key events are handled by putting them in the self.buttons dict, and optionally by calling the supplied handler. REL X, Y and wheel V and H events are all accumulated internally and also optionally passed to the supplied handler. All these events are handled. ABS X, Y, Z, RX, RY, RZ, Hat0X, Hat0Y are all accumulated internally and also optionally passed to the supplied handler. Other ABS events are not handled. All SYN events are passed to the supplied handler. There are several ABS events that we do not handle. In particular: THROTTLE, RUDDER, WHEEL, GAS, BRAKE, HAT1, HAT2, HAT3, PRESSURE, DISTANCE, TILT, TOOL_WIDTH. Implementing these is left as an exercise for the interested reader. Likewise, since one handler is handling all events for all devices, we may get the situation where two devices return the same button. The only way to handle that would seem to be to have a key dict for every device, which seems needlessly profligate for a situation that may never arise. """ ret = event self.mutex.acquire() try: Handled = False if event.eventType == EV_SYN: if self.synHandler: self.synHandler(event.stream.deviceType, event.stream.deviceIndex, event.eventCode, event.eventValue) ret = None elif event.eventType == EV_KEY: if event.stream.grabbed == False and event.eventValue != 0: ret = None self.buttons[event.eventCode] = event.eventValue if self.keyHandler: self.keyHandler(event.stream.deviceType, event.stream.deviceIndex, event.eventCode, event.eventValue) ret = None elif event.eventType == EV_REL: if event.eventCode == REL_X: self.relx[event.stream.deviceIndex] += event.eventValue if self.relHandler: self.relHandler(event.stream.deviceType, event.stream.deviceIndex, event.eventValue, 0, 0, 0) ret = None elif event.eventCode == REL_Y: self.rely[event.stream.deviceIndex] += event.eventValue if self.relHandler: self.relHandler(event.stream.deviceType, event.stream.deviceIndex, 0, event.eventValue, 0, 0) ret = None elif event.eventCode == REL_WHEEL: self.relv[event.stream.deviceIndex] += event.eventValue if self.relHandler: self.relHandler(event.stream.deviceType, event.stream.deviceIndex, 0, 0, event.eventValue, 0) ret = None elif event.eventCode == REL_HWHEEL: self.relh[event.stream.deviceIndex] += event.eventValue if self.relHandler: self.relHandler(event.stream.deviceType, event.stream.deviceIndex, 0, 0, 0, event.eventValue) elif event.eventCode == REL_DIAL: self.relh[event.stream.deviceIndex] += event.eventValue if self.relHandler: self.relHandler(event.stream.deviceType, event.stream.deviceIndex, 0 ,0, 0, event.eventValue) ret = None elif event.eventType == EV_ABS: if event.eventCode == ABS_X: Handled = True self.absx[event.stream.deviceIndex] = event.stream.scale(EventStream.axisX, event.eventValue) elif event.eventCode == ABS_Y: Handled = True self.absy[event.stream.deviceIndex] = event.stream.scale(EventStream.axisY, event.eventValue) elif event.eventCode == ABS_Z: Handled = True self.absz[event.stream.deviceIndex] = event.stream.scale(EventStream.axisZ, event.eventValue) elif event.eventCode == ABS_RX: Handled = True self.absx2[event.stream.deviceIndex] = event.stream.scale(EventStream.axisRX, event.eventValue) elif event.eventCode == ABS_RY: Handled = True self.absy2[event.stream.deviceIndex] = event.stream.scale(EventStream.axisRY, event.eventValue) elif event.eventCode == ABS_RZ: Handled = True self.absz2[event.stream.deviceIndex] = event.stream.scale(EventStream.axisRZ, event.eventValue) elif event.eventCode == ABS_HAT0X: Handled = True self.abshatx[event.stream.deviceIndex] = event.stream.scale(EventStream.axisHat0X, event.eventValue) elif event.eventCode == ABS_HAT0Y: Handled = True self.abshaty[event.stream.deviceIndex] = event.stream.scale(EventStream.axisHat0Y, event.eventValue) if Handled: if self.absHandler: self.absHandler(event.stream.deviceType, event.stream.deviceIndex, self.absx[event.stream.deviceIndex], self.absy[event.stream.deviceIndex], self.absz[event.stream.deviceIndex], self.absx2[event.stream.deviceIndex], self.absy2[event.stream.deviceIndex], self.absz2[event.stream.deviceIndex], self.abshatx[event.stream.deviceIndex], self.abshaty[event.stream.deviceIndex]) ret = None finally: self.mutex.release() return ret
[docs] def get_rel_movement(self, index): """ Returns the accumulated REL (mouse or other relative device) movements since the last call. The returned value is a tuple: (X, Y, WHEEL, H-WHEEL, DIAL) """ self.mutex.acquire() try: ret = (self.relx[index], self.rely[index], self.relv[index], self.relh[index], self.reld[index]) self.relx[index] = 0 self.rely[index] = 0 self.relv[index] = 0 self.relh[index] = 0 self.reld[index] = 0 finally: self.mutex.release() return ret
[docs] def key_state(self, buttonCode): """ Returns the last event value for the given key code. Key names can be converted to key codes using codeOf[str]. If the key is pressed the returned value will be 1 (pressed) or 2 (held). If the key is not pressed, the returned value will be 0. """ try: return self.buttons[buttonCode] except KeyError: return 0
[docs] def clear_key(self, buttonCode): """ Clears the event value for the given key code. Key names can be converted to key codes using codeOf[str]. This emulates a key-up but does not generate any events. """ try: self.buttons[buttonCode] = 0 except KeyError: pass
[docs] def get_keys(self): """ Returns the first of whichever keys have been pressed. Key names can be converted to key codes using codeOf[str]. This emulates a key-up but does not generate any events. """ k_list = [] try: for k in self.buttons: if self.buttons[k] != 0: k_list.append(k) return k_list except KeyError: pass return k_list