Ejemplo n.º 1
0
 def default_click(click_info: Click):
     """Perform ``click_function`` according to the context."""
     with FrozenEyeMouse():
         # Backdating clicks is a good default for arbitrary pointing
         # devices.
         actions.mouse_move(*click_info.position_at)
         click_info.function(click_info.modifiers)
         # Sleep for enough time for the click to complete.
         time.sleep(0.1)
Ejemplo n.º 2
0
    def end_zoom() -> Point2d:
        """Terminate the zoom.

        Mouse will be moved to the user's gaze position.

        :returns: the final position

        """
        # TODO: Will this be reactive enough, or should we make this accessible
        #   anywhere in the zoom mouse?
        _, origin = eye_zoom_mouse.zoom_mouse.get_pos()
        if origin:
            eye_zoom_mouse.zoom_mouse.cancel()
            actions.mouse_move(origin.x, origin.y)
        return origin
Ejemplo n.º 3
0
    def spline_mouse(x: int, y: int, seconds: float = 1.0) -> None:
        """Move mouse gradually to point `(x, y)`."""
        FRAME_PAUSE = 0.016
        # Use a defined number of moves (not time) so movement is smooth.
        n_steps = min(int(seconds // FRAME_PAUSE), 1)

        start_x = actions.mouse_x()
        start_y = actions.mouse_y()
        delta_x = (x - start_x) / n_steps
        delta_y = (y - start_y) / n_steps
        for i in range(n_steps):
            actions.mouse_move(start_x + (i * delta_x),
                               start_y + (i * delta_y))
            time.sleep(FRAME_PAUSE)
        actions.mouse_move()
Ejemplo n.º 4
0
def edge_mouse_scroll(north, south, east, west):
    """Map scroller that moves the mouse to the edge of the screen."""
    screen = eye_mouse.main_screen.rect
    if east:
        x = 0
    elif west:
        x = screen.width
    else:
        x = round(screen.width / 2)
    if north:
        y = 0
    elif south:
        y = screen.height
    else:
        y = round(screen.height / 2)
    # TODO: Maybe figure out a way of not hammering this
    actions.mouse_move(x, y)
Ejemplo n.º 5
0
    def telector_select(anchor1: str, anchor2: str):
        """
        Selects the text indicated by the given anchors
        """

        global labels_ui

        rect1 = labels_ui.find_rect(anchor1)
        rect2 = labels_ui.find_rect(anchor2)

        if rect1 is None or rect2 is None:
            # Couldn't find them, quit
            return

        init_mouse_x = actions.mouse_x()
        init_mouse_y = actions.mouse_y()

        actions.mouse_move(
            rect1.x,
            rect1.y + rect1.height / 2,
        )
        actions.mouse_drag(0)
        time.sleep(0.1)
        actions.mouse_move(
            # The bounding box looks fine in a screenshot but +2 helps to get
            # the whole word with my terminal and seems to work OK elsewhere.
            # Guess it's up to the application how it responds.
            rect2.x + rect2.width + 2,
            rect2.y + rect2.height / 2)
        time.sleep(0.1)
        actions.mouse_release(0)

        actions.mouse_move(init_mouse_x, init_mouse_y)
Ejemplo n.º 6
0
    def telector_click(anchor: str, button: int = 0):
        """
        Clicks the given anchor
        """

        global labels_ui

        rect = labels_ui.find_rect(anchor)

        if rect is None:
            # Couldn't find them, quit
            return

        init_mouse_x = actions.mouse_x()
        init_mouse_y = actions.mouse_y()

        actions.mouse_move(
            rect.x + rect.width / 2,
            rect.y + rect.height / 2,
        )
        actions.mouse_click(button)
        time.sleep(0.1)

        actions.mouse_move(init_mouse_x, init_mouse_y)
Ejemplo n.º 7
0
    def shake_mouse(seconds: float = 0.1, allowed_deviation: int = 5):
        """Briefly shake the cursor around its current position.

        Can be used to compensate for instantaneous mouse movement not being
        detected as a drag, e.g. when clicking + dragging Firefox tabs.

        """
        FRAME_PAUSE = 0.016  # In secs
        PIXEL_RANGE = 5
        # Use a defined number of moves (not time) so behaviour is predictable.
        n_moves = max(int(seconds // FRAME_PAUSE), 1)

        start_x = actions.mouse_x()
        # Technically a race condition, but never going to come up
        start_y = actions.mouse_y()
        for i in range(n_moves):
            # NOTE: This will move in a square pattern, not a circle. That's
            #   probably fine.
            actions.mouse_move(
                start_x + randint(-PIXEL_RANGE, PIXEL_RANGE),
                start_y + randint(-PIXEL_RANGE, PIXEL_RANGE),
            )
            time.sleep(FRAME_PAUSE)
        actions.mouse_move(start_x, start_y)
Ejemplo n.º 8
0
 def do_action(position):
     """Perform the queued action at `position`."""
     nonlocal function
     LOGGER.debug(f"Performing queued zoom function `{function}` at {position}")
     actions.mouse_move(position.x, position.y)
     function()
Ejemplo n.º 9
0
 def corner_hover(position: Corner) -> None:
     """Move mouse to a specific position, relative to a corner."""
     corner = Corner.absolute_position(position.corner)
     x = corner[0] + position.x
     y = corner[1] + position.y
     actions.mouse_move(x, y)
Ejemplo n.º 10
0
 def eu4_hover_notification(number: int) -> None:
     """Move mouse over a specific notification."""
     assert number >= 1
     # TODO: Second row of notifications
     x = Buttons.FIRST_NOTIFICATION.x + NOTIFICATION_WIDTH * (number - 1)
     actions.mouse_move(x, Buttons.FIRST_NOTIFICATION.y)
Ejemplo n.º 11
0
 def center_mouse() -> None:
     """Move the mouse to the center of the active window."""
     rect = ui.active_window().rect
     center = (rect.x + round(rect.width / 2),
               rect.y + round(rect.height / 2))
     actions.mouse_move(*center)