1
+ #include < stdexcept>
2
+
1
3
#ifdef _WIN32
2
4
#define WIN32_LEAN_AND_MEAN
3
5
// Windows 10, for latest HiDPI API support.
4
6
#define WINVER 0x0A00
5
7
#define _WIN32_WINNT 0x0A00
6
8
#endif
7
- #define PY_SSIZE_T_CLEAN
8
- #include < Python.h>
9
+ #include < pybind11/pybind11.h>
9
10
#ifdef __linux__
10
11
#include < dlfcn.h>
11
12
#endif
12
13
#ifdef _WIN32
13
14
#include < Objbase.h>
14
15
#include < Shobjidl.h>
15
16
#include < Windows.h>
17
+ #define UNUSED_ON_NON_WINDOWS (x ) x
18
+ #else
19
+ #define UNUSED_ON_NON_WINDOWS Py_UNUSED
16
20
#endif
17
21
18
- static PyObject*
19
- mpl_display_is_valid (PyObject* module)
22
+ namespace py = pybind11;
23
+
24
+ static bool
25
+ mpl_display_is_valid (void )
20
26
{
21
27
#ifdef __linux__
22
28
void * libX11;
@@ -34,11 +40,10 @@ mpl_display_is_valid(PyObject* module)
34
40
XCloseDisplay (display);
35
41
}
36
42
if (dlclose (libX11)) {
37
- PyErr_SetString (PyExc_RuntimeError, dlerror ());
38
- return NULL ;
43
+ throw std::runtime_error (dlerror ());
39
44
}
40
45
if (display) {
41
- Py_RETURN_TRUE ;
46
+ return true ;
42
47
}
43
48
}
44
49
void * libwayland_client;
@@ -56,84 +61,74 @@ mpl_display_is_valid(PyObject* module)
56
61
wl_display_disconnect (display);
57
62
}
58
63
if (dlclose (libwayland_client)) {
59
- PyErr_SetString (PyExc_RuntimeError, dlerror ());
60
- return NULL ;
64
+ throw std::runtime_error (dlerror ());
61
65
}
62
66
if (display) {
63
- Py_RETURN_TRUE ;
67
+ return true ;
64
68
}
65
69
}
66
- Py_RETURN_FALSE ;
70
+ return false ;
67
71
#else
68
- Py_RETURN_TRUE ;
72
+ return true ;
69
73
#endif
70
74
}
71
75
72
- static PyObject*
73
- mpl_GetCurrentProcessExplicitAppUserModelID (PyObject* module )
76
+ static py::object
77
+ mpl_GetCurrentProcessExplicitAppUserModelID (void )
74
78
{
75
79
#ifdef _WIN32
76
80
wchar_t * appid = NULL ;
77
81
HRESULT hr = GetCurrentProcessExplicitAppUserModelID (&appid);
78
82
if (FAILED (hr)) {
79
- return PyErr_SetFromWindowsErr (hr);
83
+ PyErr_SetFromWindowsErr (hr);
84
+ throw py::error_already_set ();
80
85
}
81
- PyObject* py_appid = PyUnicode_FromWideChar (appid, - 1 );
86
+ auto py_appid = py::cast (appid);
82
87
CoTaskMemFree (appid);
83
88
return py_appid;
84
89
#else
85
- Py_RETURN_NONE ;
90
+ return py::none () ;
86
91
#endif
87
92
}
88
93
89
- static PyObject*
90
- mpl_SetCurrentProcessExplicitAppUserModelID (PyObject* module, PyObject* arg )
94
+ static void
95
+ mpl_SetCurrentProcessExplicitAppUserModelID (const wchar_t * UNUSED_ON_NON_WINDOWS (appid) )
91
96
{
92
97
#ifdef _WIN32
93
- wchar_t * appid = PyUnicode_AsWideCharString (arg, NULL );
94
- if (!appid) {
95
- return NULL ;
96
- }
97
98
HRESULT hr = SetCurrentProcessExplicitAppUserModelID (appid);
98
- PyMem_Free (appid);
99
99
if (FAILED (hr)) {
100
- return PyErr_SetFromWindowsErr (hr);
100
+ PyErr_SetFromWindowsErr (hr);
101
+ throw py::error_already_set ();
101
102
}
102
- Py_RETURN_NONE;
103
- #else
104
- Py_RETURN_NONE;
105
103
#endif
106
104
}
107
105
108
- static PyObject*
109
- mpl_GetForegroundWindow (PyObject* module )
106
+ static py::object
107
+ mpl_GetForegroundWindow (void )
110
108
{
111
109
#ifdef _WIN32
112
- return PyLong_FromVoidPtr (GetForegroundWindow ());
110
+ return py::capsule (GetForegroundWindow (), " HWND " );
113
111
#else
114
- Py_RETURN_NONE ;
112
+ return py::none () ;
115
113
#endif
116
114
}
117
115
118
- static PyObject*
119
- mpl_SetForegroundWindow (PyObject* module, PyObject *arg )
116
+ static void
117
+ mpl_SetForegroundWindow (py::capsule UNUSED_ON_NON_WINDOWS (handle_p) )
120
118
{
121
119
#ifdef _WIN32
122
- HWND handle = PyLong_AsVoidPtr (arg);
123
- if (PyErr_Occurred ()) {
124
- return NULL ;
125
- }
126
- if (!SetForegroundWindow (handle)) {
127
- return PyErr_Format (PyExc_RuntimeError, " Error setting window" );
128
- }
129
- Py_RETURN_NONE;
130
- #else
131
- Py_RETURN_NONE;
120
+ if (handle_p.name () != " HWND" ) {
121
+ throw std::runtime_error (" Handle must be a value returned from Win32_GetForegroundWindow" );
122
+ }
123
+ HWND handle = static_cast <HWND>(handle_p.get_pointer ());
124
+ if (!SetForegroundWindow (handle)) {
125
+ throw std::runtime_error (" Error setting window" );
126
+ }
132
127
#endif
133
128
}
134
129
135
- static PyObject*
136
- mpl_SetProcessDpiAwareness_max (PyObject* module )
130
+ static void
131
+ mpl_SetProcessDpiAwareness_max (void )
137
132
{
138
133
#ifdef _WIN32
139
134
#ifdef _DPI_AWARENESS_CONTEXTS_
@@ -171,49 +166,52 @@ mpl_SetProcessDpiAwareness_max(PyObject* module)
171
166
SetProcessDPIAware ();
172
167
#endif
173
168
#endif
174
- Py_RETURN_NONE;
175
169
}
176
170
177
- static PyMethodDef functions[] = {
178
- {" display_is_valid" , (PyCFunction)mpl_display_is_valid, METH_NOARGS,
179
- " display_is_valid()\n --\n\n "
180
- " Check whether the current X11 or Wayland display is valid.\n\n "
181
- " On Linux, returns True if either $DISPLAY is set and XOpenDisplay(NULL)\n "
182
- " succeeds, or $WAYLAND_DISPLAY is set and wl_display_connect(NULL)\n "
183
- " succeeds.\n\n "
184
- " On other platforms, always returns True." },
185
- {" Win32_GetCurrentProcessExplicitAppUserModelID" ,
186
- (PyCFunction)mpl_GetCurrentProcessExplicitAppUserModelID, METH_NOARGS,
187
- " Win32_GetCurrentProcessExplicitAppUserModelID()\n --\n\n "
188
- " Wrapper for Windows's GetCurrentProcessExplicitAppUserModelID.\n\n "
189
- " On non-Windows platforms, always returns None." },
190
- {" Win32_SetCurrentProcessExplicitAppUserModelID" ,
191
- (PyCFunction)mpl_SetCurrentProcessExplicitAppUserModelID, METH_O,
192
- " Win32_SetCurrentProcessExplicitAppUserModelID(appid, /)\n --\n\n "
193
- " Wrapper for Windows's SetCurrentProcessExplicitAppUserModelID.\n\n "
194
- " On non-Windows platforms, does nothing." },
195
- {" Win32_GetForegroundWindow" ,
196
- (PyCFunction)mpl_GetForegroundWindow, METH_NOARGS,
197
- " Win32_GetForegroundWindow()\n --\n\n "
198
- " Wrapper for Windows' GetForegroundWindow.\n\n "
199
- " On non-Windows platforms, always returns None." },
200
- {" Win32_SetForegroundWindow" ,
201
- (PyCFunction)mpl_SetForegroundWindow, METH_O,
202
- " Win32_SetForegroundWindow(hwnd, /)\n --\n\n "
203
- " Wrapper for Windows' SetForegroundWindow.\n\n "
204
- " On non-Windows platforms, does nothing." },
205
- {" Win32_SetProcessDpiAwareness_max" ,
206
- (PyCFunction)mpl_SetProcessDpiAwareness_max, METH_NOARGS,
207
- " Win32_SetProcessDpiAwareness_max()\n --\n\n "
208
- " Set Windows' process DPI awareness to best option available.\n\n "
209
- " On non-Windows platforms, does nothing." },
210
- {NULL , NULL }}; // sentinel.
211
-<
7802
/span>static PyModuleDef util_module = {
212
- PyModuleDef_HEAD_INIT, " _c_internal_utils" , NULL , 0 , functions
213
- };
214
-
215
- #pragma GCC visibility push(default)
216
- PyMODINIT_FUNC PyInit__c_internal_utils (void )
171
+ PYBIND11_MODULE (_c_internal_utils, m)
217
172
{
218
- return PyModule_Create (&util_module);
173
+ m.def (
174
+ " display_is_valid" , &mpl_display_is_valid,
175
+ R"""( --
176
+ Check whether the current X11 or Wayland display is valid.
177
+
178
+ On Linux, returns True if either $DISPLAY is set and XOpenDisplay(NULL)
179
+ succeeds, or $WAYLAND_DISPLAY is set and wl_display_connect(NULL)
180
+ succeeds.
181
+
182
+ On other platforms, always returns True.)""" );
183
+ m.def (
184
+ " Win32_GetCurrentProcessExplicitAppUserModelID" ,
185
+ &mpl_GetCurrentProcessExplicitAppUserModelID,
186
+ R"""( --
187
+ Wrapper for Windows's GetCurrentProcessExplicitAppUserModelID.
188
+
189
+ On non-Windows platforms, always returns None.)""" );
190
+ m.def (
191
+ " Win32_SetCurrentProcessExplicitAppUserModelID" ,
192
+ &mpl_SetCurrentProcessExplicitAppUserModelID,
193
+ py::arg (" appid" ), py::pos_only (),
194
+ R"""( --
195
+ Wrapper for Windows's SetCurrentProcessExplicitAppUserModelID.
196
+
197
+ On non-Windows platforms, does nothing.)""" );
198
+ m.def (
199
+ " Win32_GetForegroundWindow" , &mpl_GetForegroundWindow,
200
+ R"""( --
201
+ Wrapper for Windows' GetForegroundWindow.
202
+
203
+ On non-Windows platforms, always returns None.)""" );
204
+ m.def (
205
+ " Win32_SetForegroundWindow" , &mpl_SetForegroundWindow,
206
+ py::arg (" hwnd" ),
207
+ R"""( --
208
+ Wrapper for Windows' SetForegroundWindow.
209
+
210
+ On non-Windows platforms, does nothing.)""" );
211
+ m.def (
212
+ " Win32_SetProcessDpiAwareness_max" , &mpl_SetProcessDpiAwareness_max,
213
+ R"""( --
214
+ Set Windows' process DPI awareness to best option available.
215
+
216
+ On non-Windows platforms, does nothing.)""" );
219
217
}
0 commit comments