def _send_string_press(c): event = CGEventCreateKeyboardEvent(OUTPUT_SOURCE, 0, True) KeyboardEmulation._set_event_string(event, c) CGEventPost(kCGSessionEventTap, event) event = CGEventCreateKeyboardEvent(OUTPUT_SOURCE, 0, False) KeyboardEmulation._set_event_string(event, c) CGEventPost(kCGSessionEventTap, event)
def send_string(self, s): for c in characters(s): event = CGEventCreateKeyboardEvent(MY_EVENT_SOURCE, 0, True) set_string(event, c) CGEventPost(kCGSessionEventTap, event) event = CGEventCreateKeyboardEvent(MY_EVENT_SOURCE, 0, False) set_string(event, c) CGEventPost(kCGSessionEventTap, event)
def send_backspaces(number_of_backspaces): for _ in range(number_of_backspaces): backspace_down = CGEventCreateKeyboardEvent( OUTPUT_SOURCE, BACK_SPACE, True) backspace_up = CGEventCreateKeyboardEvent(OUTPUT_SOURCE, BACK_SPACE, False) CGEventPost(kCGSessionEventTap, backspace_down) CGEventPost(kCGSessionEventTap, backspace_up)
def send_backspaces(number_of_backspaces): for _ in xrange(number_of_backspaces): CGEventPost( kCGSessionEventTap, CGEventCreateKeyboardEvent(OUTPUT_SOURCE, BACK_SPACE, True)) CGEventPost( kCGSessionEventTap, CGEventCreateKeyboardEvent(OUTPUT_SOURCE, BACK_SPACE, False))
def _send_string_press(self, c): event = CGEventCreateKeyboardEvent(OUTPUT_SOURCE, 0, True) KeyboardEmulation._set_event_string(event, c) CGEventPost(kCGSessionEventTap, event) event = CGEventCreateKeyboardEvent(OUTPUT_SOURCE, 0, False) KeyboardEmulation._set_event_string(event, c) CGEventPost(kCGSessionEventTap, event) if self._time_between_key_presses != 0: sleep(self._time_between_key_presses / 1000)
def send_backspaces(self, number_of_backspaces): for _ in range(number_of_backspaces): backspace_down = CGEventCreateKeyboardEvent( OUTPUT_SOURCE, BACK_SPACE, True) backspace_up = CGEventCreateKeyboardEvent( OUTPUT_SOURCE, BACK_SPACE, False) CGEventPost(kCGSessionEventTap, backspace_down) CGEventPost(kCGSessionEventTap, backspace_up) if self._time_between_key_presses != 0: sleep(self._time_between_key_presses / 1000)
def netflix_keyboard(commands): commandList = dict(volup=([126], None, 1, False), voldown=([125], None, 1, False), pauseresume=([49], None, 1, False), forward=([124], None, 1, False), rewind=([123], None, 1, False), fullscreen=([3], None, 1, True), mute=([46], None, 1, False)) source = CGEventSourceCreate(kCGEventSourceStateCombinedSessionState) events = [] for cmd in commands: if cmd[1:] not in commandList: continue cmdProperties = commandList[cmd[1:]] if cmdProperties[3]: netflix_mouse(["c:640,400", "m:0,300"]) for i in range(cmdProperties[2]): for keyCode in cmdProperties[0]: down = CGEventCreateKeyboardEvent(source, keyCode, True) up = CGEventCreateKeyboardEvent(source, keyCode, False) flags = cmdProperties[1] if flags is not None: CGEventSetFlags(down, flags) events.append(down) events.append(up) for event in events: CGEventPost(kCGAnnotatedSessionEventTap, event)
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 event_mask is not zero at the end then bad things might happen. event_mask = 0 for keycode, key_down in sequence: if not key_down and keycode in MODIFIER_KEYS_TO_MASKS: event_mask &= ~MODIFIER_KEYS_TO_MASKS[keycode] event = CGEventCreateKeyboardEvent( MY_EVENT_SOURCE, keycode, key_down) CGEventSetFlags(event, event_mask) CGEventPost(kCGSessionEventTap, event) if key_down and keycode in MODIFIER_KEYS_TO_MASKS: event_mask |= MODIFIER_KEYS_TO_MASKS[keycode]
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 send_backspaces(self, number_of_backspaces): for _ in xrange(number_of_backspaces): CGEventPost(kCGSessionEventTap, CGEventCreateKeyboardEvent(MY_EVENT_SOURCE, 51, True)) CGEventPost(kCGSessionEventTap, CGEventCreateKeyboardEvent(MY_EVENT_SOURCE, 51, False))
def generatemouseevent(self, x, y, eventType="b1c", drag_button_override='drag_default_button'): """ Generate mouse event on x, y co-ordinates. @param x: X co-ordinate @type x: int @param y: Y co-ordinate @type y: int @param eventType: Mouse click type @type eventType: str @param drag_button_override: Any drag_xxx value Only relevant for movements, i.e. |type| = "abs" or "rel" Quartz is not fully compatible with windows, so for drags the drag button must be explicitly defined. generatemouseevent will remember the last button pressed by default, and drag that button, use this argument to override that. @type drag_button_override: str @return: 1 on success. @rtype: integer """ if drag_button_override not in mouse_click_override: raise ValueError('Unsupported drag_button_override type: %s' % \ drag_button_override) global drag_button_remembered point = (x, y) button = centre # Only matters for "other" buttons click_type = None if eventType == "abs" or eventType == "rel": if drag_button_override is not 'drag_default_button': events = [mouse_click_override[drag_button_override]] elif drag_button_remembered: events = [drag_button_remembered] else: events = [move] if eventType == "rel": point = CGEventGetLocation(CGEventCreate(None)) point.x += x point.y += y elif eventType == "b1p": events = [press_left] drag_button_remembered = drag_left elif eventType == "b1r": events = [release_left] drag_button_remembered = None elif eventType == "b1c": events = [press_left, release_left] elif eventType == "b1d": events = [press_left, release_left] click_type = double_click elif eventType == "b2p": events = [press_other] drag_button_remembered = drag_other elif eventType == "b2r": events = [release_other] drag_button_remembered = None elif eventType == "b2c": events = [press_other, release_other] elif eventType == "b2d": events = [press_other, release_other] click_type = double_click elif eventType == "b3p": events = [press_right] drag_button_remembered = drag_right elif eventType == "b3r": events = [release_right] drag_button_remembered = None elif eventType == "b3c": events = [press_right, release_right] elif eventType == "b3d": events = [press_right, release_right] click_type = double_click else: raise LdtpServerException(u"Mouse event '%s' not implemented" % eventType) for event in events: CG_event = CGEventCreateMouseEvent(None, event, point, button) if click_type: CGEventSetIntegerValueField(CG_event, kCGMouseEventClickState, click_type) CGEventPost(kCGHIDEventTap, CG_event) # Give the event time to happen time.sleep(0.01) return 1