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

Pymouse / PyMouseEvent .run() doesn't resume function after .stop() is called #117

Open
joaomamede opened this issue Nov 5, 2019 · 3 comments

Comments

@joaomamede
Copy link

This is a linux machine.
This was working 3/4 years ago when I wrote it and now it's buggy.

from pymouse import PyMouse
from pymouse import PyMouseEvent
from pykeyboard import PyKeyboard
import pyperclip
import numpy as np
m = PyMouse()
k = PyKeyboard()



class set_position(PyMouseEvent):
    def __init__(self):
        PyMouseEvent.__init__(self)

    def click(self,x,y,button,press):
        if button == 1:
            if press:
               self.value = m.position()
               print self.value
        else:
            print "aborted"
            self.stop()

Then in my main program:

This is how it was and it was running fine in previous versions.

    print "Please Click on a section without text"
    scan_button = set_position()
    scan_button.run()
    scan_x, scan_y = scan_button.value

When I clicked with button 1 it would set the value, correctly and when I clicked middle or button 2, it would resume the python script or, go back to prompt.

Now it gets stuck.
if I put prints on the "if button ==1" then and else. It does capture mouse events until I press any other button. But then it gets stuck until ctrl+c is pressed many many times.

if I switch to

    print "Please Click on a section without text"
    scan_button = set_position()
    scan_button.start()
    scan_x, scan_y = scan_button.value

It comes back to the python shell but value was never defined because it runs in the background and proceeds right away.

Am I doing something wrong that doesn't match most recent versions? Thanks

The example with clickonacci has the exact same problem, anything I can do?

@vkresch
Copy link

vkresch commented Dec 16, 2020

Same issue! Maybe xlib had some updates which broke pymouse. (Here the related issue) For some reason it gets stuck in the context manager. I'm currently not sure what display2 is needed for but commenting:

with display_manager(self.display2) as d:
    d.ungrab_pointer(X.CurrentTime)
    d.record_disable_context(self.ctx)

works. But if you are using a loop which reruns an already created PyMouseEvent object (when initializing from scratch then it works) I get the following error thrown:

  self.display2.record_enable_context(self.ctx, self.handler)
  File "python/lib/python3.8/site-packages/Xlib/ext/record.py", line 252, in enable_context
    EnableContext(
  File "python/lib/python3.8/site-packages/Xlib/ext/record.py", line 232, in __init__
    rq.ReplyRequest.__init__(self, *args, **keys)
  File "python/lib/python3.8/site-packages/Xlib/protocol/rq.py", line 1420, in __init__
    self.reply()
  File "python/lib/python3.8/site-packages/Xlib/protocol/rq.py", line 1440, in reply
    raise self._error
Xlib.error.XError: <class 'Xlib.error.XError'>: code = 154, resource_id = 98566144, sequence_number = 16, major_opcode = 146, minor_opcode = 5

Has maybe something to do with not closing display2 correctly. Any help would be appreciated. Thanks!

@mikeabbott10
Copy link

mikeabbott10 commented Feb 3, 2021

I faced a cpu-hungry behavior when stop() is called. This is due to being stucked in the while loop in reply function (line 1483 in Xlib/protocol/rq.py). The reason here is that we're not updating _data from the send_and_recv function we call at line 1493.
This problem disappear if we don't call display_manager(self.display2) and we call

   d.ungrab_pointer(X.CurrentTime)
   d.record_disable_context(self.ctx)

with self.display2 in place of d (the file here is pymouse/x11.py), but I actually don't know if it's safe to do this.

Btw the issue seems the display_manager(self.display2) call.
If you look at this function you can see that the display.sync() function takes us straight to the loop we were talking about.
But, the first time ( with display_manager(self.display) call ) I got the answer {'sequence_number': 11, 'accel_num': 2, 'accel_denom': 1, 'threshold': 4} to the request. The second time ( with display_manager(self.display2) call ) I don't get any answer and that's why we're stucked inside the loop. I don't know how this request-and-response system works here. I just hope that these information can help someone who already knows pymouse and Xlib better than me.

EDIT: From client side I can avoid this behavior overriding stop() like this:

class example(PyMouseEvent):
   def __init__(self):
       PyMouseEvent.__init__(self)

   def click(self,x,y,button,press):
       # do something
       pass

   def stop(self):
       self.state = False
       with x11.display_manager(self.display) as d:
           d.ungrab_pointer(X.CurrentTime)
           d.record_disable_context(self.ctx)
       #with display_manager(self.display2) as d:
           self.display2.ungrab_pointer(X.CurrentTime)
           self.display2.record_disable_context(self.ctx)

I have obviously to import the modules i need:

from pymouse import PyMouseEvent, x11
from Xlib import X

@mikeabbott10
Copy link

mikeabbott10 commented Feb 4, 2021

Same issue! Maybe xlib had some updates which broke pymouse. (Here the related issue) For some reason it gets stuck in the context manager. I'm currently not sure what display2 is needed for but commenting:

with display_manager(self.display2) as d:
    d.ungrab_pointer(X.CurrentTime)
    d.record_disable_context(self.ctx)

works. But if you are using a loop which reruns an already created PyMouseEvent object (when initializing from scratch then it works) I get the following error thrown:

  self.display2.record_enable_context(self.ctx, self.handler)
  File "python/lib/python3.8/site-packages/Xlib/ext/record.py", line 252, in enable_context
    EnableContext(
  File "python/lib/python3.8/site-packages/Xlib/ext/record.py", line 232, in __init__
    rq.ReplyRequest.__init__(self, *args, **keys)
  File "python/lib/python3.8/site-packages/Xlib/protocol/rq.py", line 1420, in __init__
    self.reply()
  File "python/lib/python3.8/site-packages/Xlib/protocol/rq.py", line 1440, in reply
    raise self._error
Xlib.error.XError: <class 'Xlib.error.XError'>: code = 154, resource_id = 98566144, sequence_number = 16, major_opcode = 146, minor_opcode = 5

Has maybe something to do with not closing display2 correctly. Any help would be appreciated. Thanks!

This project is no longer mainteined btw. Use https://github.com/moses-palmer/pynput instead

EDIT: just faced the same issue with pynput because this is a platform dependent problem.

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

3 participants