Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 31aa086

Browse files
authored
Merge pull request #17555 from anntzer/win32appusermodelid
Set Win32 AppUserModelId to fix taskbar icons.
2 parents 703cc5f + dbfbb44 commit 31aa086

File tree

7 files changed

+86
-0
lines changed

7 files changed

+86
-0
lines changed

lib/matplotlib/backends/_backend_tk.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -856,6 +856,8 @@ def new_figure_manager_given_figure(cls, num, figure):
856856
Create a new figure manager instance for the given figure.
857857
"""
858858
with _restore_foreground_window_at_end():
859+
if cbook._get_running_interactive_framework() is None:
860+
cbook._setup_new_guiapp()
859861
window = tk.Tk(className="matplotlib")
860862
window.withdraw()
861863

lib/matplotlib/backends/backend_gtk3.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -935,4 +935,5 @@ def trigger_manager_draw(manager):
935935
@staticmethod
936936
def mainloop():
937937
if Gtk.main_level() == 0:
938+
cbook._setup_new_guiapp()
938939
Gtk.main()

lib/matplotlib/backends/backend_qt5.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ def _create_qApp():
125125
pass
126126
qApp = QtWidgets.QApplication(["matplotlib"])
127127
qApp.lastWindowClosed.connect(qApp.quit)
128+
cbook._setup_new_guiapp()
128129
else:
129130
qApp = app
130131

lib/matplotlib/backends/backend_wx.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1674,6 +1674,7 @@ def new_figure_manager(cls, num, *args, **kwargs):
16741674
if wxapp is None:
16751675
wxapp = wx.App(False)
16761676
wxapp.SetExitOnFrameDelete(True)
1677+
cbook._setup_new_guiapp()
16771678
# Retain a reference to the app object so that it does not get
16781679
# garbage collected.
16791680
_BackendWx._theWxApp = wxapp

lib/matplotlib/cbook/__init__.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import numpy as np
2929

3030
import matplotlib
31+
from matplotlib import _c_internal_utils
3132
from .deprecation import (
3233
deprecated, warn_deprecated,
3334
_rename_parameter, _delete_parameter, _make_keyword_only,
@@ -2342,3 +2343,17 @@ def _backend_module_name(name):
23422343
"""
23432344
return (name[9:] if name.startswith("module://")
23442345
else "matplotlib.backends.backend_{}".format(name.lower()))
2346+
2347+
2348+
def _setup_new_guiapp():
2349+
"""
2350+
Perform OS-dependent setup when Matplotlib creates a new GUI application.
2351+
"""
2352+
# Windows: If not explicit app user model id has been set yet (so we're not
2353+
# already embedded), then set it to "matplotlib", so that taskbar icons are
2354+
# correct.
2355+
try:
2356+
_c_internal_utils.Win32_GetCurrentProcessExplicitAppUserModelID()
2357+
except OSError:
2358+
_c_internal_utils.Win32_SetCurrentProcessExplicitAppUserModelID(
2359+
"matplotlib")

setupext.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,11 @@ def get_extensions(self):
338338
add_libagg_flags_and_sources(ext)
339339
FreeType().add_flags(ext)
340340
yield ext
341+
# c_internal_utils
342+
ext = Extension(
343+
"matplotlib._c_internal_utils", ["src/_c_internal_utils.c"],
344+
libraries={"win32": ["ole32", "shell32"]}.get(sys.platform, []))
345+
yield ext
341346
# contour
342347
ext = Extension(
343348
"matplotlib._contour", [

src/_c_internal_utils.c

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#define PY_SSIZE_T_CLEAN
2+
#include <Python.h>
3+
#ifdef _WIN32
4+
#include <Objbase.h>
5+
#include <Shobjidl.h>
6+
#endif
7+
8+
static PyObject* mpl_GetCurrentProcessExplicitAppUserModelID(PyObject* module)
9+
{
10+
#ifdef _WIN32
11+
wchar_t* appid = NULL;
12+
HRESULT hr = GetCurrentProcessExplicitAppUserModelID(&appid);
13+
if (FAILED(hr)) {
14+
return PyErr_SetFromWindowsErr(hr);
15+
}
16+
PyObject* py_appid = PyUnicode_FromWideChar(appid, -1);
17+
CoTaskMemFree(appid);
18+
return py_appid;
19+
#else
20+
Py_RETURN_NONE;
21+
#endif
22+
}
23+
24+
static PyObject* mpl_SetCurrentProcessExplicitAppUserModelID(PyObject* module, PyObject* arg)
25+
{
26+
#ifdef _WIN32
27+
wchar_t* appid = PyUnicode_AsWideCharString(arg, NULL);
28+
if (!appid) {
29+
return NULL;
30+
}
31+
HRESULT hr = SetCurrentProcessExplicitAppUserModelID(appid);
32+
PyMem_Free(appid);
33+
if (FAILED(hr)) {
34+
return PyErr_SetFromWindowsErr(hr);
35+
}
36+
Py_RETURN_NONE;
37+
#else
38+
Py_RETURN_NONE;
39+
#endif
40+
}
41+
42+
static PyMethodDef functions[] = {
43+
{"Win32_GetCurrentProcessExplicitAppUserModelID",
44+
(PyCFunction)mpl_GetCurrentProcessExplicitAppUserModelID, METH_NOARGS,
45+
"Win32_GetCurrentProcessExplicitAppUserModelID()\n--\n\n"
46+
"Wrapper for Windows's GetCurrentProcessExplicitAppUserModelID. On \n"
47+
"non-Windows platforms, always returns None."},
48+
{"Win32_SetCurrentProcessExplicitAppUserModelID",
49+
(PyCFunction)mpl_SetCurrentProcessExplicitAppUserModelID, METH_O,
50+
"Win32_SetCurrentProcessExplicitAppUserModelID(appid, /)\n--\n\n"
51+
"Wrapper for Windows's SetCurrentProcessExplicitAppUserModelID. On \n"
52+
"non-Windows platforms, a no-op."},
53+
{NULL, NULL}}; // sentinel.
54+
static PyModuleDef util_module = {
55+
PyModuleDef_HEAD_INIT, "_c_internal_utils", "", 0, functions, NULL, NULL, NULL, NULL};
56+
57+
#pragma GCC visibility push(default)
58+
PyMODINIT_FUNC PyInit__c_internal_utils(void)
59+
{
60+
return PyModule_Create(&util_module);
61+
}

0 commit comments

Comments
 (0)