[71] | 1 | #!/usr/bin/python |
---|
| 2 | from rgbkbd.core import Keyboard |
---|
| 3 | from rgbkbd.geometry import Keys |
---|
| 4 | |
---|
| 5 | # Keyboard Modes |
---|
| 6 | from rgbkbd.modes.basicmodes import StaticMode |
---|
| 7 | from rgbkbd.modes.commandmode import CommandMode |
---|
| 8 | |
---|
| 9 | |
---|
| 10 | class KeyboardManager(object): |
---|
| 11 | def __init__(self, device): |
---|
| 12 | self.keyboard = Keyboard(device=device) |
---|
| 13 | |
---|
| 14 | self.active_modes = [] |
---|
| 15 | # Initialize variables for key chord tracking |
---|
| 16 | self.key_state = {} |
---|
| 17 | self.chord = [] |
---|
| 18 | |
---|
| 19 | self.notifier_number, notify_filename = self.keyboard.alloc_notify() |
---|
| 20 | self.notifier = open(notify_filename) |
---|
| 21 | |
---|
| 22 | # CommandMode is always the last thing available |
---|
| 23 | self.mode_start(CommandMode(self, self.keyboard)) |
---|
| 24 | # Setup default keyboard mode and start it. |
---|
| 25 | self.mode_start(StaticMode(self, self.keyboard)) |
---|
| 26 | |
---|
| 27 | def shutdown(self): |
---|
| 28 | # Set the keyboard to a reasonable default mode |
---|
| 29 | self.mode_start(StaticMode(self, self.keyboard)) |
---|
| 30 | self.keyboard.free_notify(self.notifier_number) |
---|
| 31 | |
---|
| 32 | def mode_return(self): |
---|
| 33 | """Discards the currently active KeyboardMode mode and initializes the |
---|
| 34 | previously active mode. |
---|
| 35 | """ |
---|
| 36 | prev_mode = self.active_modes.pop() |
---|
| 37 | self.current_mode().start(prev_mode) |
---|
| 38 | |
---|
| 39 | def mode_start(self, mode): |
---|
| 40 | """Makes the given mode the current mode and initializes it""" |
---|
| 41 | self.active_modes.append(mode) |
---|
| 42 | self.current_mode().start() |
---|
| 43 | |
---|
| 44 | def current_mode(self): |
---|
| 45 | """Returns the currently active KeyboardMode object""" |
---|
| 46 | # Never goes empty because the CommandMode doesn't go away |
---|
| 47 | return self.active_modes[-1] |
---|
| 48 | |
---|
| 49 | def key_event(self, key, state): |
---|
| 50 | """Dispatches key up, key down, and chord events to the current mode. |
---|
| 51 | """ |
---|
| 52 | #print key, state # DEBUG |
---|
| 53 | # Directly pass on up/down key events |
---|
| 54 | self.current_mode().event(key, state) |
---|
| 55 | |
---|
| 56 | # Then track key chords. (Individual typed keys count as a single-key |
---|
| 57 | # chord.) |
---|
| 58 | self.key_state[key] = state |
---|
| 59 | if state == '+': # key down |
---|
| 60 | self.chord.append(key) |
---|
| 61 | else: # key up |
---|
| 62 | if set(self.key_state.values()) != set('-'): |
---|
| 63 | # There are still keys that are being held down, so this is an |
---|
| 64 | # incomplete chord |
---|
| 65 | return |
---|
| 66 | # All keys are up |
---|
| 67 | chord = self.chord |
---|
| 68 | self.chord = [] |
---|
| 69 | self.current_mode().chord_event(chord) |
---|
| 70 | |
---|
| 71 | def tick_rate(self): |
---|
| 72 | return self.current_mode().tick_rate |
---|