|
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