Skip to content

Use rcParams to control default "raise window" behavior (Qt,Gtk,Tk,Wx) #15440

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

Conversation

immaxchen
Copy link
Contributor

@immaxchen immaxchen commented Oct 18, 2019

PR Summary

Address Issue #8692

A new rcParms entry have been added: "figure.raise_window"
Now it is possible to disable the default "raise GUI window" behavior
This change apply to & tested on Qt4, Qt5, Gtk3, Tk and Wx backends (OS: CentOS7, Win7)
Has document it in the 'whats new' section

Known Issue:
Gtk3 have to use a small trick to force the screen update, better solutions welcome
Qt4 "raise window" pop-out "Figure is ready", have to click the notification manually

Side Note:
Wx backend didn't implement the "raise window" behavior before
Don't have a Mac to work on macosx backend
Manually tested with the attached python script

test_raise_window.txt

PR Checklist

  • Has Pytest style unit tests
  • Code is Flake 8 compliant
  • New features are documented, with examples if plot related
  • Documentation is sphinx and numpydoc compliant
  • Added an entry to doc/users/next_whats_new/ if major new feature (follow instructions in README.rst there)
  • Documented in doc/api/api_changes.rst if API changed in a backward-incompatible way

@immaxchen
Copy link
Contributor Author

Struggled with the Gtk3 a bit & now find the right way of doing it, so simple. 😳

@immaxchen
Copy link
Contributor Author

Also tested on Windows7, working as expected.

Copy link
Member

@timhoffm timhoffm left a comment

Choose a reason for hiding this comment

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

Thanks! Looks good apart from the what's new message 👍.

Could you sqash your commits if possible? - Otherwise we'll do it before merging.

Comment on lines 5 to 7
A new rcParms entry have been added: with the ``figure.raise_window`` option
now it is possible to disable the default "raise GUI window" behavior when
calling ``plt.show`` or ``plt.pause`` methods.
Copy link
Member

Choose a reason for hiding this comment

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

The new config option rcParams['figure.raise_window'] allows to disable
raising the plot window when calling plt.show or plt.pause methods.

Should be sufficient and more straight forward.

… (Qt,Gtk,Tk,Wx)

A new rcParms entry have been added: "figure.raise_window"
Now it is possible to disable the default "raise GUI window" behavior
This change apply to & tested on Qt, Gtk, Tk and Wx backends (CentOS7 & Win7)
Has document it in the 'whats new' section
@immaxchen immaxchen force-pushed the add-rcparams-to-control-raise-window-behavior-gh8692 branch from 5e76728 to 1b4c4ad Compare October 24, 2019 13:02
@immaxchen
Copy link
Contributor Author

immaxchen commented Oct 24, 2019

Great thanks for the help on the message, i'm not a native speaker. 😂
Have tried to rebase it, am i doing it right?

Copy link
Member

@timhoffm timhoffm left a comment

Choose a reason for hiding this comment

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

Rebase is correct 👍

What do you mean by: Qt4 "raise window" pop-out "Figure is ready", have to click the notification manually.

@@ -411,7 +411,9 @@ def destroy(self, *args):
def show(self):
# show the figure window
self.window.show()
self.window.present()
self.canvas.draw()
Copy link
Member

Choose a reason for hiding this comment

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

Why does GTK3 need a draw now?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

When I am testing with Gtk3 and turn off the "raise window", I encountered a strange behavior, that the GUI window is reluctant to update, and the whole program get stuck, loop is not running, until I move/switch the GUI window or moving my mouse cursor on the canvas, it can continue to run/update.
After debug and tracing, I found the program is stuck inside the Gtk.main_iteration() here:

    def flush_events(self):
        # docstring inherited
        Gdk.threads_enter()
        while Gtk.events_pending():
            Gtk.main_iteration()
        Gdk.flush()
        Gdk.threads_leave()

By looking into the doc, it says if there is no event queued, main_iteration will block until the next event is noticed, but that's very strange since we have already checked with events_pending, if there is no event it should not go into the while-loop. Nevertheless, I changed using Gtk.gtk_main_iteration_do(False) which the doc states that it won't block, however, that's not working, the program still get stuck inside gtk_main_iteration_do. Finally, I come up with a solution: to call window.queue_draw() right after window.show() and successfully I don't have to waving my mouse cursor over the canvas any more. And I found that this is exactly what canvas.draw() is doing, and the same approach is also used in the backend_wx.py, so I suppose this is the right way to do it? I am not familiar with the GUI stuff so I have no idea what's happening, please feel free to correct me.
This is the full report, HaHa!! Thank you so much for your patience reading this mumbo jumbo!! 😜

Copy link
Member

Choose a reason for hiding this comment

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

Could you test with draw_idle instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

tested, won't update, need stick to draw

@immaxchen
Copy link
Contributor Author

immaxchen commented Oct 25, 2019

image

This is what I saw when I'm testing on my machine using pyqt=4 (cannot actually "raise" to top automatically, instead, have to click on the notification to bring up the window)
But using qt5 can actually bring the window to the top as expected

@timhoffm
Copy link
Member

So instead of the window, a "Figure 1 is ready" message is popping to the front?

@immaxchen
Copy link
Contributor Author

Yes! and it is exactly the one shown in the top-right corner of my attached image.

@timhoffm
Copy link
Member

timhoffm commented Oct 26, 2019

Hm, I don't find any related "... is ready" text in our code base. So who is generating that message? You are seeing this only in Qt4, not Qt5, and you are on master?

@QuLogic
Copy link
Member

QuLogic commented Oct 27, 2019

The message is triggered by your window manager, which isn't allowing focus stealing.

@immaxchen
Copy link
Contributor Author

Yes! only in Qt4, not Qt5, and on master.
It is not generated by mpl, it's a Gnome thing (related post: here and here)
But don't know why only Qt4 is suffering this.

@timhoffm
Copy link
Member

Given that Qt4 is end of life and major distributions are defaulting to Qt5, I wouldn‘t wollt too much if we can‘t get this fixed for Qt4.

@immaxchen
Copy link
Contributor Author

Sure, so is there anything else I need to do?

@timhoffm
Copy link
Member

I don‘t think so. I still want to take a closer look at the GTK redraw.

@immaxchen
Copy link
Contributor Author

OK, thanks!

@anntzer
Copy link
Contributor

anntzer commented Dec 7, 2019

In general this looks nice.
How does this interact with rcParams["tk.window_focus"]? If they are overlapping in functionality should tk.window_focus be deprecated?

@efiring
Copy link
Member

efiring commented Dec 10, 2019

This looks very helpful (based on a quick scan).

One thought occurs to me: would it make sense to have this controlled by an optional keyword argument to plt.show? That way it could be controlled locally instead of only globally. It would require adding the keyword argument to the intermediate Figure.show and each Backend.show as well. I think the setting of the default by rcParam could stay in the backends.

@immaxchen
Copy link
Contributor Author

Thanks for the advice, seems reasonable to me. But they could be discussed & handled in separated issue & PR, IMHO.

@carlosgmartin
Copy link

Any update on this?

Copy link
Member

@efiring efiring left a comment

Choose a reason for hiding this comment

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

I think we should get this in ASAP. I don't see how it can do any real harm, and it is an important feature requiring minimal code.

@anntzer
Copy link
Contributor

anntzer commented Jan 13, 2020

I think the whatsnew should at least mention that this doesn't work on the macos backend (which is fine); clarifying (as above) the interaction with the tk.window_focus rc would be nice as well.

@efiring
Copy link
Member

efiring commented Jan 13, 2020

@anntzer Good points. If this goes in, will you want to support the rcParam in your mplcairo backend?

@anntzer
Copy link
Contributor

anntzer commented Jan 13, 2020

I haven't actually checked, but I'm almost certain mplcairo will work just fine with it because it just inherits the show() methods from the various backend-dependent but renderer-independent base classes (similarly, you can see that here the changes are in qt5.py wx.py etc. and not qt5agg.py/qt5cairo.py wxagg.py/wxcairo.py etc.).

@efiring efiring added this to the v3.3.0 milestone Jan 13, 2020
@immaxchen
Copy link
Contributor Author

I think this functionality is not exactly identical to the rcParams["tk.window_focus"].
According to the information from SO, the code used here only displays the window above all other windows (set attributes topmost as True), not necessarily steal the focus from another window.
On the other hand, rcParams["tk.window_focus"] tries to steal focus by using Win32 API.

@immaxchen
Copy link
Contributor Author

Add this to whatsnew?

MacOSX backend is currently not supported.
To control the focus stealing behavior for Tk backends, use rcParams["tk.window_focus"] instead.

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.

conditional on adding a note about OSX not being supported (or explicitly listing the backends that are supported).

@immaxchen
Copy link
Contributor Author

done~

@jklymak jklymak merged commit 01e267c into matplotlib:master Jan 28, 2020
@jklymak
Copy link
Member

jklymak commented Jan 28, 2020

Thanks @immaxchen

@carlosgmartin
Copy link

Is there a fix for OSX?

@pczhang-tony
Copy link

pczhang-tony commented Jun 10, 2021

Hello, changing rcParams figure.raise_window keyword to False gives inconsistent behavior.

Here's a simple example:

import matplotlib
from matplotlib import pyplot as plt

matplotlib.use('qt5agg')

if matplotlib.rcParams['figure.raise_window']:
    matplotlib.rcParams['figure.raise_window'] = False

plt.plot([1,2,3],[3,4,5],'.')
plt.show()

When I run the example code in Spyder, the initial run works as intended: the new plot window does not "rise above" the console window. However, subsequent runs of the same code do not behave the same way: the new plot window still rises above the console window, even when the keyword is set to False.

Moreover, running the code in the command prompt also does not produce the desired effect: the new plot window always rises above the command prompt window.

I am using Windows 10, Python 3.7.6, Matplotlib 3.4.2, and Spyder 5.0.0

I am commenting here in hopes that the original developer(s) of this feature can see this.

Thanks.

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.

10 participants