|
6 | 6 | import sys
|
7 | 7 | import tkinter as Tk
|
8 | 8 | from tkinter.simpledialog import SimpleDialog
|
| 9 | +from contextlib import contextmanager |
9 | 10 |
|
10 | 11 | import numpy as np
|
11 | 12 |
|
12 | 13 | from . import _tkagg
|
13 |
| -from matplotlib.backends.backend_agg import FigureCanvasAgg |
14 |
| -import matplotlib.backends.windowing as windowing |
15 | 14 |
|
16 | 15 | import matplotlib
|
17 | 16 | from matplotlib import backend_tools, rcParams
|
|
23 | 22 | from matplotlib.figure import Figure
|
24 | 23 | from matplotlib.widgets import SubplotTool
|
25 | 24 |
|
| 25 | +try: |
| 26 | + from matplotlib._windowing import GetForegroundWindow, SetForegroundWindow |
| 27 | +except ImportError: |
| 28 | + @contextmanager |
| 29 | + def _restore_foreground_window_at_end(): |
| 30 | + yield |
| 31 | +else: |
| 32 | + @contextmanager |
| 33 | + def _restore_foreground_window_at_end(): |
| 34 | + foreground = GetForegroundWindow() |
| 35 | + try: |
| 36 | + yield |
| 37 | + finally: |
| 38 | + if rcParams['tk.window_focus']: |
| 39 | + SetForegroundWindow(foreground) |
| 40 | + |
26 | 41 |
|
27 | 42 | _log = logging.getLogger(__name__)
|
28 | 43 |
|
@@ -540,19 +555,19 @@ def show(self):
|
540 | 555 | this function doesn't segfault but causes the
|
541 | 556 | PyEval_RestoreThread: NULL state bug on win32
|
542 | 557 | """
|
543 |
| - _focus = windowing.FocusManager() |
544 |
| - if not self._shown: |
545 |
| - def destroy(*args): |
546 |
| - self.window = None |
547 |
| - Gcf.destroy(self._num) |
548 |
| - self.canvas._tkcanvas.bind("<Destroy>", destroy) |
549 |
| - self.window.deiconify() |
550 |
| - else: |
551 |
| - self.canvas.draw_idle() |
552 |
| - # Raise the new window. |
553 |
| - self.canvas.manager.window.attributes('-topmost', 1) |
554 |
| - self.canvas.manager.window.attributes('-topmost', 0) |
555 |
| - self._shown = True |
| 558 | + with _restore_foreground_window_at_end(): |
| 559 | + if not self._shown: |
| 560 | + def destroy(*args): |
| 561 | + self.window = None |
| 562 | + Gcf.destroy(self._num) |
| 563 | + self.canvas._tkcanvas.bind("<Destroy>", destroy) |
| 564 | + self.window.deiconify() |
| 565 | + else: |
| 566 | + self.canvas.draw_idle() |
| 567 | + # Raise the new window. |
| 568 | + self.canvas.manager.window.attributes('-topmost', 1) |
| 569 | + self.canvas.manager.window.attributes('-topmost', 0) |
| 570 | + self._shown = True |
556 | 571 |
|
557 | 572 | def destroy(self, *args):
|
558 | 573 | if self.window is not None:
|
@@ -716,9 +731,9 @@ def set_active(self, ind):
|
716 | 731 | self._active = [self._axes[i] for i in self._ind]
|
717 | 732 |
|
718 | 733 | def update(self):
|
719 |
| - _focus = windowing.FocusManager() |
720 | 734 | self._axes = self.canvas.figure.axes
|
721 |
| - NavigationToolbar2.update(self) |
| 735 | + with _restore_foreground_window_at_end(): |
| 736 | + NavigationToolbar2.update(self) |
722 | 737 |
|
723 | 738 |
|
724 | 739 | class ToolTip(object):
|
@@ -989,29 +1004,29 @@ def new_figure_manager_given_figure(cls, num, figure):
|
989 | 1004 | """
|
990 | 1005 | Create a new figure manager instance for the given figure.
|
991 | 1006 | """
|
992 |
| - _focus = windowing.FocusManager() |
993 |
| - window = Tk.Tk(className="matplotlib") |
994 |
| - window.withdraw() |
995 |
| - |
996 |
| - # Put a mpl icon on the window rather than the default tk icon. |
997 |
| - # Tkinter doesn't allow colour icons on linux systems, but tk>=8.5 has |
998 |
| - # a iconphoto command which we call directly. Source: |
999 |
| - # http://mail.python.org/pipermail/tkinter-discuss/2006-November/000954.html |
1000 |
| - icon_fname = os.path.join( |
1001 |
| - rcParams['datapath'], 'images', 'matplotlib.ppm') |
1002 |
| - icon_img = Tk.PhotoImage(file=icon_fname) |
1003 |
| - try: |
1004 |
| - window.tk.call('wm', 'iconphoto', window._w, icon_img) |
1005 |
| - except Exception as exc: |
1006 |
| - # log the failure (due e.g. to Tk version), but carry on |
1007 |
| - _log.info('Could not load matplotlib icon: %s', exc) |
1008 |
| - |
1009 |
| - canvas = cls.FigureCanvas(figure, master=window) |
1010 |
| - manager = cls.FigureManager(canvas, num, window) |
1011 |
| - if matplotlib.is_interactive(): |
1012 |
| - manager.show() |
1013 |
| - canvas.draw_idle() |
1014 |
| - return manager |
| 1007 | + with _restore_foreground_window_at_end(): |
| 1008 | + window = Tk.Tk(className="matplotlib") |
| 1009 | + window.withdraw() |
| 1010 | + |
| 1011 | + # Put a mpl icon on the window rather than the default tk icon. |
| 1012 | + # Tkinter doesn't allow colour icons on linux systems, but tk>=8.5 has |
| 1013 | + # a iconphoto command which we call directly. Source: |
| 1014 | + # http://mail.python.org/pipermail/tkinter-discuss/2006-November/000954.html |
| 1015 | + icon_fname = os.path.join( |
| 1016 | + rcParams['datapath'], 'images', 'matplotlib.ppm') |
| 1017 | + icon_img = Tk.PhotoImage(file=icon_fname) |
| 1018 | + try: |
| 1019 | + window.tk.call('wm', 'iconphoto', window._w, icon_img) |
| 1020 | + except Exception as exc: |
| 1021 | + # log the failure (due e.g. to Tk version), but carry on |
| 1022 | + _log.info('Could not load matplotlib icon: %s', exc) |
| 1023 | + |
| 1024 | + canvas = cls.FigureCanvas(figure, master=window) |
| 1025 | + manager = cls.FigureManager(canvas, num, window) |
| 1026 | + if matplotlib.is_interactive(): |
| 1027 | + manager.show() |
| 1028 | + canvas.draw_idle() |
| 1029 | + return manager |
1015 | 1030 |
|
1016 | 1031 | @staticmethod
|
1017 | 1032 | def trigger_manager_draw(manager):
|
|
0 commit comments