def _curses_screen_get_event(self, ): """ Check for an event without waiting. This monkey patch adds support for the mouse scroll """ import curses # Spin through notifications until we find something we want. key = 0 while key != -1: # Get the next key key = self.screen._screen.getch() if key == curses.KEY_RESIZE: # Handle screen resize self.screen._re_sized = True elif key == curses.KEY_MOUSE: # Handle a mouse event _, x, y, _, bstate = curses.getmouse() buttons = 0 # Some Linux modes only report clicks, so check for any # button down or click events. if (bstate & curses.BUTTON1_PRESSED != 0 or bstate & curses.BUTTON1_CLICKED != 0): buttons |= MouseEvent.LEFT_CLICK if (bstate & curses.BUTTON3_PRESSED != 0 or bstate & curses.BUTTON3_CLICKED != 0): buttons |= MouseEvent.RIGHT_CLICK if bstate & curses.BUTTON1_DOUBLE_CLICKED != 0: buttons |= MouseEvent.DOUBLE_CLICK if (bstate & curses.A_LOW != 0 or bstate & curses.A_LOW != 0): # scroll down buttons |= DOMMouseEvent.MOUSE_SCROLL_DOWN if (bstate & curses.BUTTON4_PRESSED != 0 or bstate & curses.BUTTON4_CLICKED != 0): # scroll up buttons |= DOMMouseEvent.MOUSE_SCROLL_UP return MouseEvent(x, y, buttons) elif key != -1: # Handle any byte streams first if self.screen._unicode_aware and key > 0: if key & 0xC0 == 0xC0: self.screen._bytes_to_return = struct.pack(b"B", key) self.screen._bytes_to_read = bin(key)[2:].index("0") - 1 continue elif self.screen._bytes_to_read > 0: self.screen._bytes_to_return += struct.pack(b"B", key) self.screen._bytes_to_read -= 1 if self.screen._bytes_to_read > 0: continue else: key = ord(self.screen._bytes_to_return.decode("utf-8")) # Handle a genuine key press. if key in self.screen._KEY_MAP: return KeyboardEvent(self.screen._KEY_MAP[key]) elif key != -1: return KeyboardEvent(key) return None
def my_get_event(self): """ Check for any event without waiting. """ # Look for a new event and consume it if there is one. key = 0 while key != -1: # Get the next key key = self._screen.getch() if key == curses.KEY_RESIZE: # Handle screen resize self._re_sized = True elif key == curses.KEY_MOUSE: # Translate into a MouseEvent object. _, x, y, _, bstate = curses.getmouse() buttons = 0 # Some Linux modes only report clicks, so check for any # button down or click events. if (bstate & curses.BUTTON1_PRESSED != 0 or bstate & curses.BUTTON1_CLICKED != 0): buttons = MouseEvent.LEFT_CLICK elif (bstate & curses.BUTTON3_PRESSED != 0 or bstate & curses.BUTTON3_CLICKED != 0): buttons = MouseEvent.RIGHT_CLICK elif bstate & curses.BUTTON1_DOUBLE_CLICKED != 0: buttons = MouseEvent.DOUBLE_CLICK buttons = (bstate if type(bstate) == int and buttons == 0 else buttons) buttons = 0 if buttons not in [0, 1, 2, 4] else buttons return MouseEvent(x, y, buttons) elif key != -1: # Handle any byte streams first logger.debug("Processing key: %x", key) if self._unicode_aware and key > 0: if key & 0xC0 == 0xC0: self._bytes_to_return = struct.pack(b"B", key) self._bytes_to_read = bin(key)[2:].index("0") - 1 logger.debug("Byte stream: %d bytes left", self._bytes_to_read) continue elif self._bytes_to_read > 0: self._bytes_to_return += struct.pack(b"B", key) self._bytes_to_read -= 1 if self._bytes_to_read > 0: continue else: key = ord(self._bytes_to_return.decode("utf-8")) # Handle a genuine key press. logger.debug("Returning key: %x", key) if key in self._KEY_MAP: return KeyboardEvent(self._KEY_MAP[key]) elif key != -1: return KeyboardEvent(key) # If we get here, we've fully processed the event queue and found # nothing interesting. return None
def internal_checks(screen): # Check for exit for char in ("X", "x", "Q", "q"): with self.assertRaises(StopApplication): event = KeyboardEvent(ord(char)) screen._unhandled_event_default(event) for char in (" ", "\n"): with self.assertRaises(NextScene): event = KeyboardEvent(ord(char)) screen._unhandled_event_default(event)
def process_keys(form, values, separator=None): """ Inject a set of key events separated by a common key separator. """ for new_value in values: if isinstance(new_value, int): form.process_event(KeyboardEvent(new_value)) else: for char in new_value: form.process_event(KeyboardEvent(ord(char))) if separator: form.process_event(KeyboardEvent(separator))
def test_keyboard_event(self): """ Check Keyboard event is consistent. """ code = 123 event = KeyboardEvent(code) self.assertEqual(event.key_code, code) self.assertIn(str(code), str(event))
def get_interface(patcher, api=None, events=None, append_q=True): if not events: events = [] if append_q: events.append(KeyboardEvent(ord("q"))) class MockedManagedScreen: def __enter__(self): return MockedScreen(events) def __exit__(self, exc_type, exc_val, exc_tb): pass patcher.setattr(tui, "ManagedScreen", MockedManagedScreen) return tui.Interface(api=api)
def test_empty_frame(self): """ Check empty Frames still work. """ screen = MagicMock(spec=Screen, colours=8, unicode_aware=False) canvas = Canvas(screen, 10, 40, 0, 0) scene = MagicMock(spec=Scene) form = TestFrame3(canvas) form.register_scene(scene) form.reset() # Check all keyboard events get swallowed self.assertIsNone(form.process_event(KeyboardEvent(ord("A")))) # Check Mouse events over the Frame are swallowed and others allowed # to bubble down the input stack. self.assertIsNone( form.process_event(MouseEvent(20, 5, MouseEvent.LEFT_CLICK))) self.assertIsNotNone( form.process_event(MouseEvent(5, 5, MouseEvent.LEFT_CLICK))) # Check form data is empty. form.save() self.assertEqual(form.data, {})
def hit(letter): return KeyboardEvent(ord(letter))
class Event: resize = SpecialEvent(SpecialEvent.RESIZE) pass_frame = SpecialEvent(SpecialEvent.PASS_N_FRAMES, 1) pass_tick = SpecialEvent(SpecialEvent.PASS_N_TICKS, 1) pass_half_tick = SpecialEvent(SpecialEvent.PASS_N_FRAMES, tui.Interface.frames / 2) pass_tick_and_a_half = SpecialEvent(SpecialEvent.PASS_N_FRAMES, tui.Interface.frames * 3 / 2) up = KeyboardEvent(Screen.KEY_UP) down = KeyboardEvent(Screen.KEY_DOWN) left = KeyboardEvent(Screen.KEY_LEFT) right = KeyboardEvent(Screen.KEY_RIGHT) delete = KeyboardEvent(Screen.KEY_DELETE) esc = KeyboardEvent(Screen.KEY_ESCAPE) f1 = KeyboardEvent(Screen.KEY_F1) f2 = KeyboardEvent(Screen.KEY_F2) f3 = KeyboardEvent(Screen.KEY_F3) f4 = KeyboardEvent(Screen.KEY_F4) f5 = KeyboardEvent(Screen.KEY_F5) f6 = KeyboardEvent(Screen.KEY_F6) f7 = KeyboardEvent(Screen.KEY_F7) f8 = KeyboardEvent(Screen.KEY_F8) f9 = KeyboardEvent(Screen.KEY_F9) f10 = KeyboardEvent(Screen.KEY_F10) f11 = KeyboardEvent(Screen.KEY_F11) f12 = KeyboardEvent(Screen.KEY_F12) enter = KeyboardEvent(ord("\n")) space = KeyboardEvent(ord(" ")) @staticmethod def hit(letter): return KeyboardEvent(ord(letter)) @staticmethod def exc(value): return SpecialEvent(SpecialEvent.RAISE, value) @staticmethod def pass_frames(value): return SpecialEvent(SpecialEvent.PASS_N_FRAMES, value) @staticmethod def pass_ticks(value): return SpecialEvent(SpecialEvent.PASS_N_TICKS, value)
def my_get_event(self): """ Check for any event without waiting. """ # Look for a new event and consume it if there is one. while len(self._stdin.PeekConsoleInput(1)) > 0: event = self._stdin.ReadConsoleInput(1)[0] if event.EventType == win32console.KEY_EVENT: # Pasting unicode text appears to just generate key-up # events (as if you had pressed the Alt keys plus the # keypad code for the character), but the rest of the # console input simply doesn't # work with key up events - e.g. misses keyboard repeats. # # We therefore allow any key press (i.e. KeyDown) event and # _any_ event that appears to have popped up from nowhere # as long as the Alt key is present. key_code = ord(event.Char) if (event.KeyDown or (key_code > 0 and key_code not in self._keys and event.VirtualKeyCode == win32con.VK_MENU)): # Record any keys that were pressed. if event.KeyDown: self._keys.add(key_code) # Translate keys into a KeyboardEvent object. if event.VirtualKeyCode in self._KEY_MAP: key_code = self._KEY_MAP[event.VirtualKeyCode] # Sadly, we are limited to Linux terminal input and so # can't return modifier states in a cross-platform way. # If the user decided not to be cross-platform, so be # it, otherwise map some standard bindings for extended # keys. if (self._map_all and event.VirtualKeyCode in self._EXTRA_KEY_MAP): key_code = self._EXTRA_KEY_MAP[event.VirtualKeyCode] else: if (event.VirtualKeyCode == win32con.VK_TAB and event.ControlKeyState & win32con.SHIFT_PRESSED): key_code = Screen.KEY_BACK_TAB # Don't return anything if we didn't have a valid # mapping. if key_code: return KeyboardEvent(key_code) else: # Tidy up any key that was previously pressed. At # start-up, we may be mid-key, so can't assume this must # always match up. if key_code in self._keys: self._keys.remove(key_code) elif event.EventType == win32console.MOUSE_EVENT: # Translate into a MouseEvent object. button = 0 print(event.ButtonState, end=" ") if event.EventFlags == 0: # Button pressed - translate it. if (event.ButtonState & win32con.FROM_LEFT_1ST_BUTTON_PRESSED != 0): button |= MouseEvent.LEFT_CLICK if (event.ButtonState & win32con.RIGHTMOST_BUTTON_PRESSED != 0): button |= MouseEvent.RIGHT_CLICK elif event.EventFlags & win32con.DOUBLE_CLICK != 0: button |= MouseEvent.DOUBLE_CLICK button = (event.ButtonState if type(event.ButtonState) == int and button == 0 else button) return MouseEvent(event.MousePosition.X, event.MousePosition.Y, button) # If we get here, we've fully processed the event queue and found # nothing interesting. return None
def _send_raw(self, code): self.instance.screen_manager.scene.process_event(KeyboardEvent(code))