-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Use a GtkApplication in GTK backend. #20284
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
|
||
_application.run() # Quits when all added windows close. | ||
# Running after quit is undefined, so create a new one next time. | ||
_application = None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Somewhat of an edge case, but say someone sets up their own GtkApplication and this gets picked up by _create_application(), and then the application quits, and then we somehow reach again mainloop(). If I understand correctly, we need to set up a new GtkApplication in that case, because the old one will be invalid? If Gtk provides no builtin way to know whether a GtkApplication has already been run, should _create_application e.g. connect to the shutdown
signal to add a flag to the application when it shuts down? Then the whole logic of whether new GtkApplications need to be created can be encapsulated in _create_application.
(Or I may have understood everything wrong...)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, we add the windows to the GtkApplication
, so if we create a new one here, it'd just exit immediately without windows attached. So they'd have to create a new window, and that would create a new application, I think? We could also exit early here if there's no application; is that needed if plt.show
is called without any windows?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think(?) you missed my point (which upon reading again my message was somewhat unclear), which is mostly that you cannot tell a priori whether _application
(if returned by Gio.Application.get_default()) is a fresh GtkApplication or an already used one (i.e. one on which run() has already been called and exited). Or perhaps you can?
(Looking at it again, the point about shutdown
was kind of a tangent.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, I don't think you can tell that.
That's also why I only put _create_application
in FigureManager
, because I thought that'd only be called if we're managing the mainloop entirely. Checking for a default was a copy from Qt, but in this way, I think that it can't even happen?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In that case (also re: #20284 (comment)), does that mean this part (resetting _application to None so that a later call to _create_application() creates a new one) can/should be removed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If all windows are closed, then this (and thus pyplot.show
) returns, so we still need to set it to None
so we can get a new application for any subsequent windows. Otherwise, re-using a previously-run application will crash, as noted below.
I did some testing, and while you can create multiple applications, you can only register one. And you can only add windows after the application has been registered. So we can't just create our own application 'just in case'. Also, if you add a window to an application that has already been run, it might crash, so we want to avoid that. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't really follow everything re: the GtkApplication life cycle, but this seems reasonable enough...
To clarify,
As implemented, this:
All our embedding examples use |
Thanks for the detailed writeup. My concerns were about GtkApplications that (in embedding situations) may exist before matplotlib is even started (and may or may not have run yet) or that will be instantiated after matplotlib has exited (a gtk event loop), but if I understand correctly we can't do much about them anyways. |
I think we mostly don't have to worry about that. If you embed in the way we suggest, you'd have a If you instead use If you also use If there's an existing application that was already run, but not cleaned up, then we have no way to check that, I think, so not much we can do there. |
Also, stop using `gtk_main*` functions; these were deprecated in GTK3, and no longer exist in GTK4. The lower level GLib functions have always been there, and won't go away.
How does this integrate with the command line input hook functionality? https://github.com/ipython/ipython/blob/master/IPython/terminal/pt_inputhooks/gtk3.py is how it works with gtk3, but if you can not re-run an application and you need to attach each window to the application, we are going to have to do something fancier here... |
It mostly works, you can open and close multiple windows with There is a bug if you are in |
OK, I think I figured it out. If you Ctrl+C out of This now works in IPython with |
PR Summary
Also, stop using
gtk_main*
functions; these were deprecated in GTK3, and no longer exist in GTK4. The lower level GLib functions have always been there, and won't go away.PR Checklist
pytest
passes).flake8
on changed files to check).flake8-docstrings
and runflake8 --docstring-convention=all
).doc/users/next_whats_new/
(follow instructions in README.rst there).doc/api/next_api_changes/
(follow instructions in README.rst there).