Exemplo n.º 1
0
        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
Exemplo n.º 2
0
    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)
Exemplo n.º 3
0
 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
Exemplo n.º 4
0
 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