def callback(proxy, event_type, event, reference): SUPPRESS_EVENT = None PASS_EVENT_THROUGH = event # Don't pass on meta events meant for this event tap. is_unexpected_event = event_type not in self._KEYBOARD_EVENTS if is_unexpected_event: if event_type == kCGEventTapDisabledByTimeout: # Re-enable the tap and hope we act faster next time CGEventTapEnable(self._tap, True) plover.log.warning( "Keystrokes may have been missed. " + "Keyboard event tap has been re-enabled. ") return SUPPRESS_EVENT # Don't intercept the event if it has modifiers, allow # Fn and Numeric flags so we can suppress the arrow and # extended (home, end, etc...) keys. suppressible_modifiers = (kCGEventFlagMaskNumericPad | kCGEventFlagMaskSecondaryFn | kCGEventFlagMaskNonCoalesced) has_nonsupressible_modifiers = \ CGEventGetFlags(event) & ~suppressible_modifiers if has_nonsupressible_modifiers: return PASS_EVENT_THROUGH keycode = CGEventGetIntegerValueField( event, kCGKeyboardEventKeycode) key = KEYCODE_TO_KEY.get(keycode) self._async_dispatch(key, event_type) if key in self._suppressed_keys: return SUPPRESS_EVENT return PASS_EVENT_THROUGH
def _send_sequence(self, sequence): # There is a bug in the event system that seems to cause inconsistent # modifiers on key events: # http://stackoverflow.com/questions/2008126/cgeventpost-possible-bug-when-simulating-keyboard-events # My solution is to manage the state myself. # I'm not sure how to deal with caps lock. # If mods_flags is not zero at the end then bad things might happen. mods_flags = 0 for keycode, key_down in sequence: if keycode >= NX_KEY_OFFSET: # Handle media (NX) key. event = KeyboardEmulation._get_media_event( keycode - NX_KEY_OFFSET, key_down) else: # Handle regular keycode. if not key_down and keycode in MODIFIER_KEYS_TO_MASKS: mods_flags &= ~MODIFIER_KEYS_TO_MASKS[keycode] if key_down and keycode_needs_fn_mask(keycode): mods_flags |= kCGEventFlagMaskSecondaryFn event = CGEventCreateKeyboardEvent( OUTPUT_SOURCE, keycode, key_down) if key_down and keycode not in MODIFIER_KEYS_TO_MASKS: event_flags = CGEventGetFlags(event) # Add wanted flags, remove unwanted flags. goal_flags = ((event_flags & ~KeyboardEmulation.MODS_MASK) | mods_flags) if event_flags != goal_flags: CGEventSetFlags(event, goal_flags) # Half millisecond pause after key down. sleep(0.0005) if key_down and keycode in MODIFIER_KEYS_TO_MASKS: mods_flags |= MODIFIER_KEYS_TO_MASKS[keycode] if not key_down and keycode_needs_fn_mask(keycode): mods_flags &= ~kCGEventFlagMaskSecondaryFn CGEventPost(kCGSessionEventTap, event) if self._time_between_key_presses != 0: sleep(self._time_between_key_presses / 1000)
def callback(proxy, event_type, event, reference): # Don't pass on meta events meant for this event tap. if event_type not in self._KEYBOARD_EVENTS: return None # Don't intercept events from this module. if (CGEventGetIntegerValueField(event, kCGEventSourceStateID) == MY_EVENT_SOURCE_ID): return event # Don't intercept the event if it has modifiers. if CGEventGetFlags(event) & ~kCGEventFlagMaskNonCoalesced: return event keycode = CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode) if keycode not in KEYCODE_TO_CHAR: return event char = KEYCODE_TO_CHAR[keycode] handler_name = 'key_up' if event_type == kCGEventKeyUp else 'key_down' handler = getattr(self, handler_name, lambda event: None) handler(KeyboardEvent(char)) return None if self.is_keyboard_suppressed() else event
def callback(proxy, event_type, event, reference): # Don't pass on meta events meant for this event tap. if event_type not in self._KEYBOARD_EVENTS: return None # Don't intercept the event if it has modifiers, allow # Fn and Numeric flags so we can suppress the arrow and # extended (home, end, etc...) keys. if CGEventGetFlags(event) & ~(kCGEventFlagMaskNumericPad | kCGEventFlagMaskSecondaryFn | kCGEventFlagMaskNonCoalesced): return event keycode = CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode) key = KEYCODE_TO_KEY.get(keycode) if key is not None: handler = self.key_up if event_type == kCGEventKeyUp else self.key_down handler(key) if key in self._suppressed_keys: # Suppress event. event = None return event