Skip to content

Commit 69a01a6

Browse files
committed
Set Windows DPI awareness to best possible setting.
1 parent ffe4530 commit 69a01a6

File tree

2 files changed

+39
-7
lines changed

2 files changed

+39
-7
lines changed

lib/matplotlib/backends/_backend_tk.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -854,7 +854,7 @@ def new_figure_manager_given_figure(cls, num, figure):
854854
with _restore_foreground_window_at_end():
855855
if cbook._get_running_interactive_framework() is None:
856856
cbook._setup_new_guiapp()
857-
_c_internal_utils.Win32_SetDpiAwareness()
857+
_c_internal_utils.Win32_SetProcessDpiAwareness_max()
858858
window = tk.Tk(className="matplotlib")
859859
window.withdraw()
860860

src/_c_internal_utils.c

+38-6
Original file line numberDiff line numberDiff line change
@@ -125,10 +125,42 @@ mpl_SetForegroundWindow(PyObject* module, PyObject *arg)
125125
}
126126

127127
static PyObject*
128-
mpl_SetDpiAwareness(PyObject* module)
128+
mpl_SetProcessDpiAwareness_max(PyObject* module)
129129
{
130130
#ifdef _WIN32
131+
#ifdef _DPI_AWARENESS_CONTEXTS_
132+
// These functions and options were added in later Windows 10 updates, so
133+
// must be loaded dynamically.
134+
typedef BOOL (WINAPI *IsValidDpiAwarenessContext_t)(DPI_AWARENESS_CONTEXT);
135+
typedef BOOL (WINAPI *SetProcessDpiAwarenessContext_t)(DPI_AWARENESS_CONTEXT);
136+
137+
HMODULE user32 = LoadLibrary("user32.dll");
138+
IsValidDpiAwarenessContext_t IsValidDpiAwarenessContextPtr =
139+
(IsValidDpiAwarenessContext_t)GetProcAddress(
140+
user32, "IsValidDpiAwarenessContext");
141+
SetProcessDpiAwarenessContext_t SetProcessDpiAwarenessContextPtr =
142+
(SetProcessDpiAwarenessContext_t)GetProcAddress(
143+
user32, "SetProcessDpiAwarenessContext");
144+
if (IsValidDpiAwarenessContextPtr != NULL && SetProcessDpiAwarenessContextPtr != NULL) {
145+
if (IsValidDpiAwarenessContextPtr(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2)) {
146+
// Added in Creators Update of Windows 10.
147+
SetProcessDpiAwarenessContextPtr(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
148+
} else if (IsValidDpiAwarenessContextPtr(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE)) {
149+
// Added in Windows 10.
150+
SetProcessDpiAwarenessContextPtr(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE);
151+
} else if (IsValidDpiAwarenessContextPtr(DPI_AWARENESS_CONTEXT_SYSTEM_AWARE)) {
152+
// Added in Windows 10.
153+
SetProcessDpiAwarenessContextPtr(DPI_AWARENESS_CONTEXT_SYSTEM_AWARE);
154+
}
155+
} else {
156+
// Added in Windows Vista.
157+
SetProcessDPIAware();
158+
}
159+
FreeLibrary(user32);
160+
#else
161+
// Added in Windows Vista.
131162
SetProcessDPIAware();
163+
#endif
132164
#endif
133165
Py_RETURN_NONE;
134166
}
@@ -160,11 +192,11 @@ static PyMethodDef functions[] = {
160192
"Win32_SetForegroundWindow(hwnd, /)\n--\n\n"
161193
"Wrapper for Windows' SetForegroundWindow. On non-Windows platforms, \n"
162194
"a no-op."},
163-
{"Win32_SetDpiAwareness",
164-
(PyCFunction)mpl_SetDpiAwareness, METH_NOARGS,
165-
"Win32_SetDpiAwareness()\n--\n\n"
166-
"Set Windows' process DPI awareness to be enabled. On non-Windows\n"
167-
"platforms, does nothing."},
195+
{"Win32_SetProcessDpiAwareness_max",
196+
(PyCFunction)mpl_SetProcessDpiAwareness_max, METH_NOARGS,
197+
"Win32_SetProcessDpiAwareness_max()\n--\n\n"
198+
"Set Windows' process DPI awareness to best option available.\n"
199+
"On non-Windows platforms, does nothing."},
168200
{NULL, NULL}}; // sentinel.
169201
static PyModuleDef util_module = {
170202
PyModuleDef_HEAD_INIT, "_c_internal_utils", "", 0, functions, NULL, NULL, NULL, NULL};

0 commit comments

Comments
 (0)