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