Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Usage, manipulating mouse input #22

Closed
Awarua- opened this issue Apr 18, 2017 · 2 comments
Closed

Usage, manipulating mouse input #22

Awarua- opened this issue Apr 18, 2017 · 2 comments

Comments

@Awarua-
Copy link

Awarua- commented Apr 18, 2017

Hi,

I was wondering if someone would be able to help me with a problem I am facing.

The code below is meant to intercept the mouse input and translate it by a factor of 2.
However, it stops working after intercepting the first two on_move mouse events and locks up the mouse.
I suspect it is something to do with concurrency and the listener but am unsure.
Any help would be appreciated 😄

from pynput import mouse


class PassingMouseListenerException(Exception): pass


class Mouse:
    def __init__(self):
        self.control_display_gain = 2
        self.last_position = None
        self.mouse = mouse.Controller()

    def on_move(self, x, y):
        if self.last_position is None:
            self.last_position = (x, y)
        else:
            x_difference = (x - self.last_position[0]) * self.control_display_gain
            y_difference = (y - self.last_position[1]) * self.control_display_gain
            pos = (x_difference + self.last_position[0], y_difference + self.last_position[1])
            print("difference: {0}, {1}".format(x_difference, y_difference))
            print("old position: {0}, {1} captured position: {2}, {3} new position: {4}, {5}".format(self.last_position[0], self.last_position[1], x, y, pos[0], pos[1]))
            self.mouse.move(x_difference, y_difference)
            self.last_position = pos

    def on_click(self, x, y, button, pressed):
        print("I clicked")

    def on_scroll(self, x, y, dx, dy):
        pass

    def run(self):
        self.last_position = self.mouse.position
        with mouse.Listener(
                on_move=self.on_move,
                on_click=self.on_click,
                on_scroll=self.on_scroll) as listener:

            try:
                listener.join()
            except Exception as e:
                print("listener died: {}".format(e))

if __name__ == "__main__":
    program = Mouse()
    program.run()
@moses-palmer
Copy link
Owner

Hi,

Sorry for the late response.

I have tested your application, and it does indeed crash for me with the message short format requires (-0x7fff - 1) <= number <= 0x7fff when running under XWayland. This is caused by by the values passed to self.mouse.move: Xlib requires short integers, that is signed 16 bit values.

Now, whether this should be handled by pynput is a difficult question---one solution would be to wrap the error in a generic ValueError and mark the method as raising that particular exception, another would be to cap the input values.

The root cause, however, is in your algorithm. pynput.mouse.Listener.on_move will be called when you call self.mouse.move, thus triggering another call to move the pointer, eventually leading to an overflow. You will need to react only to user triggered move callbacks.

@moses-palmer
Copy link
Owner

As of commit e17bb06, I consider this issue to be solved. If you disagree, please re-open this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants