8000 backend_wx.py: ReleaseMouse() when the capture is lost by newville · Pull Request #7652 · matplotlib/matplotlib · GitHub
[go: up one dir, main page]

Skip to content

backend_wx.py: ReleaseMouse() when the capture is lost #7652

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

Closed
wants to merge 30 commits into from
Closed

backend_wx.py: ReleaseMouse() when the capture is lost #7652

wants to merge 30 commits into from

Conversation

newville
Copy link
Contributor

This removes all calls to wxWindow.CaptureMouse(), wxWindow.ReleaseMouse() and wxWindow.HasCapture() for the wx backend.

This is intended to address C++ assertion errors as described in #7636 and which appear to happen when the window captures the mouse and then loses focus.

My view is that the window shouldn't be trying to capture the mouse (which is intended to prevent it transferring to other windows or apps) at all. I believe none of the other backends try to do this. More importantly, the capture of the mouse is not being handled properly, because the LoseFocus events are not being handled.

@tacaswell
Copy link
Member

@Kojoley Can you look at those pytest failures? It looks like it is missing saving a files someplace?

@tacaswell tacaswell added this to the 2.0 (style change major release) milestone Dec 21, 2016
@tacaswell
Copy link
Member

Test failures are un-related to this PR.

tacaswell
tacaswell previously approved these changes Dec 21, 2016
Copy link
Member
@tacaswell tacaswell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes look reasonable to me and I trust @newville that this works.

@tacaswell tacaswell changed the title backend_wx.py: remove all calls to CaptureMouse() and ReleaseMouse() [MRG+1]: backend_wx.py: remove all calls to CaptureMouse() and ReleaseMouse() Dec 21, 2016
@Kojoley
Copy link
Member
Kojoley commented Dec 21, 2016

@tacaswell appveyor failure (Permission denied) is not on pytest build. I have restarted travis pytest build and previous errors gone but other appeared (it looks like svg file was not flushed to disk)

Copy link
Member
@Kojoley Kojoley left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like self.CaptureMouse() call was related to "Capture button release off canvas" 8022cda.

@dhyams
Copy link
Contributor
dhyams commented Dec 22, 2016

This should not be merged. IIRC, capture is necessary to translate events, such as button_press_event, in matplotlib. e.g. what if a user presses the mouse button in a canvas, but drags outside before the button up happens?

This PR seems like a huge hammer to kill off the assertions. The assertions are an indication that some coding is wrong, but that should not mean that the baby gets thrown out with the bathwater.

8000

@newville
Copy link
Contributor Author

@dhyams

This should not be merged. IIRC, capture is necessary to translate events, such as button_press_event, in matplotlib. e.g. what if a user presses the mouse button in a canvas, but drags outside before the button up happens?

My understanding is that the button up event, say FigureCanvasWX._onLeftButtoUp(), will be called when the button up event happens if the corresponding button down event happened within the Canvas. It's entirely possible that this depends on OS and library versions but I can verify that this is in fact the case onMac OSX. For the code used to verify this, see https://gist.github.com/newville/5e1b55e85d130f49cbfd692dd42ad718 which places print funcitions for all the button up/down events in backend_wx.py, and allows one to easily toggle CaptureMouse() and ReleaseMouse().

I've had code that monkey-patches wxWindow.CaptureMouse() to be a null operation in parts of wxmplot (https://newville.github.io/wxmplot/) for a long time and have never had a problem with it. To be clear, this library relies on mouse events more aggressively than most matplotlib windows. The original issue (newville/wxmplot#25) was raised because this was being done only for OSX, not for Linux. (there seems to be no problems with CaptureMouse() on Windows).

So, I would guess I would turn your question around: Having CaptureMouse() clearly causes some problems on some systems.... when does it ever provide desirable behavior? My view is that, at best, it has no effect. Does this PR break some behavior for you?

Since wx.MouseCaptureLostEvent is not being handled, the current code is broken as per the wxPython API.

This PR seems like a huge hammer to kill off the assertions. The assertions are an indication that some coding is wrong, but that should not mean that the baby gets thrown out with the bathwater.

I believe backend_wx.py has been wrong for a very long time by capturing the mouse without a guarantee of it being released. I don't believe there are negative side effects ("baby") here, just negative behavior ("bathwater"). But, if there are unintended consequences, we should figure out how to solve them.

@newville
Copy link
Contributor Author

@tacaswell @dhyams OK, I tested this more thoroughly and Linux, Mac OSX, and Windows. Removing CaptureMouse() on Windows does have the effect that some mouse events loose connection when the mouse moves out of the window. That is, if LeftDown happens in the FigureCanvas / wx.Panel and then the mouse is moved out of the window and back in, the motion and left up events don't return when the window is re-entered. This appears to not happen on Linux or Mac OSX.

So, I changed backend_wxp.py to return to doing the CaptureMouse() on the Mouse-Down events, and doing the conditional ReleaseMouse() on the Mouse-Up events, and added handling of the MOUSE_CAPTURE_LOST and MOUSE_CAPTURE_CHANGED events, which is also just the conditional ReleaseMouse().

This works for me on all platforms, though I did not exhaustively test wxPython versions, and was testing with MPL 1.5.*. I do not see any C++ assertion errors on Linux or OSX with this code with some playing around with plotting and imaging panels. Since the problem was somewhat intermittent anyway, I'm not certain that this is completely fixed. The alternative would be to only capture/release the mouse on Windows.

@QuLogic
Copy link
Member
QuLogic commented Dec 22, 2016

Please rebase instead of merging master (and preferably just keep the one commit of new changes instead of delete and revert, if possible.)

@QuLogic QuLogic dismissed tacaswell’s stale review December 22, 2016 23:47

This PR now does the opposite of what you reviewed.

@QuLogic QuLogic changed the title [MRG+1]: backend_wx.py: remove all calls to CaptureMouse() and ReleaseMouse() backend_wx.py: ReleaseMouse() when the capture is lost Dec 22, 2016
@codecov-io
Copy link
codecov-io commented Dec 24, 2016

Current coverage is 62.06% (diff: 45.00%)

Merging #7652 into master will decrease coverage by <.01%

@@             master      #7652   diff @@
==========================================
  Files           174        174          
  Lines         56007      56027    +20   
  Methods           0          0          
  Messages          0          0          
  Branches          0          0          
==========================================
+ Hits          34765      34773     +8   
- Misses        21242      21254    +12   
  Partials          0          0          

Powered by Codecov. Last update c21d189...5302ff7

@tacaswell
Copy link
Member

Something has gone very funny here with git....

@QuLogic
Copy link
Member
QuLogic commented Dec 28, 2016

Probably due to using master instead of a feature branch. It can be easily rectified, though:

$ git status
# Check that there's nothing you want to keep.
$ git checkout master
$ git fetch upstream
$ git rebase -i upstream/master

@newville should get only the 3 commits you've originally added listed in your editor. Change the second two lines from pick to squash. Exit and let it rebase, then your editor should pop up again to clean up the message. Make that 9E88 something a bit more relevant, then:

$ git push --force origin master

(and in the future, make sure to check out a new branch before starting any work!)

@newville
Copy link
Contributor Author

@tacaswell @QuLogic Yes, sorry, the original changes and description for this PR were not sufficient to solve the problem described in #7636 and wxmplot/issue/25 and broke desirable behavior on Windows.

I've updated my branch a couple times as I've learned about the nuances of how wx mouse events differ across platforms (see also https://groups.google.com/forum/#!topic/wxpython-users/-NrlWBMNkwM). At this point, I believe I have a backend_wx.py that will work (supporting the desirable behavior while avoiding the C++ assertion errors) everywhere, but I will not be able to test sufficiently on all platforms until next week.

I'll close this PR and create another with a single commit on a freshly forked repo by the end of next week.

@newville newville closed this Dec 28, 2016
@tacaswell tacaswell modified the milestones: 2.0.1 (next bug fix release), 2.0 (style change major release) Jan 16, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants
0