winrt-Microsoft.Web.WebView2.Interop 4!1.0.4314.35.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (18) hide show
  1. winrt_microsoft_web_webview2_interop-4!1.0.4314.35.1/LICENSE +22 -0
  2. winrt_microsoft_web_webview2_interop-4!1.0.4314.35.1/MANIFEST.in +3 -0
  3. winrt_microsoft_web_webview2_interop-4!1.0.4314.35.1/PKG-INFO +42 -0
  4. winrt_microsoft_web_webview2_interop-4!1.0.4314.35.1/README.md +16 -0
  5. winrt_microsoft_web_webview2_interop-4!1.0.4314.35.1/interop.h +191 -0
  6. winrt_microsoft_web_webview2_interop-4!1.0.4314.35.1/py.Microsoft.Web.WebView2.Interop.cpp +271 -0
  7. winrt_microsoft_web_webview2_interop-4!1.0.4314.35.1/pyproject.toml +54 -0
  8. winrt_microsoft_web_webview2_interop-4!1.0.4314.35.1/requirements.txt +4 -0
  9. winrt_microsoft_web_webview2_interop-4!1.0.4314.35.1/setup.cfg +4 -0
  10. winrt_microsoft_web_webview2_interop-4!1.0.4314.35.1/setup.py +123 -0
  11. winrt_microsoft_web_webview2_interop-4!1.0.4314.35.1/winrt/_winrt_microsoft_web_webview2_interop.pyi +4 -0
  12. winrt_microsoft_web_webview2_interop-4!1.0.4314.35.1/winrt/microsoft/web/webview2/interop/__init__.py +62 -0
  13. winrt_microsoft_web_webview2_interop-4!1.0.4314.35.1/winrt/microsoft/web/webview2/interop/py.typed +0 -0
  14. winrt_microsoft_web_webview2_interop-4!1.0.4314.35.1/winrt_Microsoft.Web.WebView2.Interop.egg-info/PKG-INFO +42 -0
  15. winrt_microsoft_web_webview2_interop-4!1.0.4314.35.1/winrt_Microsoft.Web.WebView2.Interop.egg-info/SOURCES.txt +16 -0
  16. winrt_microsoft_web_webview2_interop-4!1.0.4314.35.1/winrt_Microsoft.Web.WebView2.Interop.egg-info/dependency_links.txt +1 -0
  17. winrt_microsoft_web_webview2_interop-4!1.0.4314.35.1/winrt_Microsoft.Web.WebView2.Interop.egg-info/requires.txt +2 -0
  18. winrt_microsoft_web_webview2_interop-4!1.0.4314.35.1/winrt_Microsoft.Web.WebView2.Interop.egg-info/top_level.txt +1 -0
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) Microsoft Corporation. All rights reserved.
4
+ Copyright (c) 2021-2026 David Lechner <david@pybricks.com>
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE
@@ -0,0 +1,3 @@
1
+ # WARNING: Please don't edit this file. It was automatically generated.
2
+
3
+ include interop.h
@@ -0,0 +1,42 @@
1
+ Metadata-Version: 2.4
2
+ Name: winrt-Microsoft.Web.WebView2.Interop
3
+ Version: 4!1.0.4314.35.1
4
+ Summary: Lets a visually hosted WebView2 take the files dropped on its window, as an OLE drop target.
5
+ License-Expression: MIT
6
+ Project-URL: Documentation, https://pywinrt.readthedocs.io
7
+ Project-URL: Repository, https://github.com/pywinrt/pywinrt
8
+ Project-URL: Changelog, https://github.com/pywinrt/pywinrt/blob/main/projection/webview2/CHANGELOG.md
9
+ Classifier: Operating System :: Microsoft :: Windows
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Programming Language :: Python :: 3.13
14
+ Classifier: Programming Language :: Python :: 3.14
15
+ Classifier: Programming Language :: Python :: 3.15
16
+ Classifier: Programming Language :: Python :: Implementation :: CPython
17
+ Classifier: Intended Audience :: Developers
18
+ Classifier: Programming Language :: Python :: Free Threading :: 2 - Beta
19
+ Classifier: Typing :: Typed
20
+ Requires-Python: >=3.11
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Requires-Dist: winrt-runtime<5,>=4.0.0
24
+ Requires-Dist: winrt-Microsoft.Web.WebView2>=4!1.0.4314.35
25
+ Dynamic: license-file
26
+
27
+ <!-- warning: Please don't edit this file. It was automatically generated. -->
28
+
29
+ # winrt-Microsoft.Web.WebView2.Interop
30
+
31
+ Lets a visually hosted WebView2 take the files dropped on its window, as an OLE drop target.
32
+
33
+ This package provides the `winrt.microsoft.web.webview2.interop` module.
34
+
35
+ It is built against version 1.0.4314.35 of the `Microsoft.Web.WebView2`
36
+ NuGet package.
37
+
38
+ ```
39
+ pip install winrt-Microsoft.Web.WebView2.Interop
40
+ ```
41
+
42
+ installs it with `winrt-Microsoft.Web.WebView2`.
@@ -0,0 +1,16 @@
1
+ <!-- warning: Please don't edit this file. It was automatically generated. -->
2
+
3
+ # winrt-Microsoft.Web.WebView2.Interop
4
+
5
+ Lets a visually hosted WebView2 take the files dropped on its window, as an OLE drop target.
6
+
7
+ This package provides the `winrt.microsoft.web.webview2.interop` module.
8
+
9
+ It is built against version 1.0.4314.35 of the `Microsoft.Web.WebView2`
10
+ NuGet package.
11
+
12
+ ```
13
+ pip install winrt-Microsoft.Web.WebView2.Interop
14
+ ```
15
+
16
+ installs it with `winrt-Microsoft.Web.WebView2`.
@@ -0,0 +1,191 @@
1
+ // WARNING: Please don't edit this file. It was copied from interop/interop.h
2
+ // by scripts/generate-pyproject.py.
3
+
4
+ // What an interop module needs to exchange WinRT objects and errors with
5
+ // winrt-runtime.
6
+ //
7
+ // An interop module shares no C ABI with the runtime and includes none of its
8
+ // headers. A WinRT object crosses as an interface pointer capsule, which
9
+ // winrt.runtime.interop.as_interface() makes from a projected object and
10
+ // winrt.runtime.interop.wrap_interface() makes a projected object from, and a
11
+ // failed call raises the exception that winrt.runtime.interop.hresult_error()
12
+ // builds. The capsule's name and those three functions are the whole
13
+ // contract, so this header can change freely.
14
+ //
15
+ // scripts/generate-pyproject.py copies this file into each interop package,
16
+ // so that its source distribution builds on its own.
17
+
18
+ #pragma once
19
+
20
+ #include <Python.h>
21
+
22
+ #include <windows.h>
23
+
24
+ #include <oleauto.h>
25
+
26
+ #include <cstddef>
27
+
28
+ // The version of the Python C API a module is compiled against: the stable
29
+ // ABI's where it is built for that, and otherwise that of the Python it is
30
+ // built for. Nothing newer is there to call.
31
+ #ifdef Py_LIMITED_API
32
+ #define INTEROP_PY_API_VERSION Py_LIMITED_API
33
+ #else
34
+ #define INTEROP_PY_API_VERSION PY_VERSION_HEX
35
+ #endif
36
+
37
+ namespace interop
38
+ {
39
+ /// The name every interface pointer capsule carries, in the runtime and in
40
+ /// every interop module alike. One holds a reference to a COM interface,
41
+ /// which its destructor releases.
42
+ inline constexpr char interface_capsule_name[] = "winrt.interface";
43
+
44
+ /// Releases the GIL for as long as it is in scope.
45
+ ///
46
+ /// A call into an object in another apartment, or one that sends a window
47
+ /// on another thread a message, waits for that thread, which may itself
48
+ /// be waiting for the GIL to run a Python handler.
49
+ class gil_released
50
+ {
51
+ public:
52
+ gil_released() noexcept : state{PyEval_SaveThread()}
53
+ {
54
+ }
55
+
56
+ gil_released(gil_released const&) = delete;
57
+ gil_released& operator=(gil_released const&) = delete;
58
+
59
+ ~gil_released() noexcept
60
+ {
61
+ PyEval_RestoreThread(state);
62
+ }
63
+
64
+ private:
65
+ PyThreadState* state;
66
+ };
67
+
68
+ /// The destructor of an interface pointer capsule this module made, which
69
+ /// may hold the last reference to the object.
70
+ inline void release_interface(PyObject* capsule) noexcept
71
+ {
72
+ auto const abi = PyCapsule_GetPointer(capsule, interface_capsule_name);
73
+ if (!abi)
74
+ {
75
+ PyErr_WriteUnraisable(capsule);
76
+ return;
77
+ }
78
+
79
+ gil_released const guard;
80
+ static_cast<IUnknown*>(abi)->Release();
81
+ }
82
+
83
+ /// Hands @p abi, and the reference that comes with it, to a new interface
84
+ /// pointer capsule. The reference is released if that fails.
85
+ inline PyObject* new_interface_capsule(IUnknown* abi) noexcept
86
+ {
87
+ auto const capsule
88
+ = PyCapsule_New(abi, interface_capsule_name, release_interface);
89
+ if (!capsule)
90
+ {
91
+ abi->Release();
92
+ }
93
+
94
+ return capsule;
95
+ }
96
+
97
+ /// Raises what winrt.runtime.interop.hresult_error() makes of @p hr and
98
+ /// @p info, the error info of the call that failed with it, which may be
99
+ /// @c nullptr. The reference to @p info moves in.
100
+ /// @returns nullptr, for the caller to return.
101
+ inline PyObject* set_hresult_error(HRESULT hr, IErrorInfo* info) noexcept
102
+ {
103
+ auto const capsule = info ? new_interface_capsule(info) : Py_NewRef(Py_None);
104
+ if (!capsule)
105
+ {
106
+ return nullptr;
107
+ }
108
+
109
+ auto const runtime = PyImport_ImportModule("winrt.runtime.interop");
110
+ if (!runtime)
111
+ {
112
+ Py_DECREF(capsule);
113
+ return nullptr;
114
+ }
115
+
116
+ auto const error = PyObject_CallMethod(
117
+ runtime, "hresult_error", "lO", static_cast<long>(hr), capsule);
118
+ Py_DECREF(runtime);
119
+ Py_DECREF(capsule);
120
+ if (!error)
121
+ {
122
+ return nullptr;
123
+ }
124
+
125
+ PyErr_SetObject(reinterpret_cast<PyObject*>(Py_TYPE(error)), error);
126
+ Py_DECREF(error);
127
+
128
+ return nullptr;
129
+ }
130
+
131
+ /// Raises what winrt.runtime.interop.hresult_error() makes of @p hr and of
132
+ /// the error info that the call that just failed with it left on this
133
+ /// thread.
134
+ /// @returns nullptr, for the caller to return.
135
+ inline PyObject* set_hresult_error(HRESULT hr) noexcept
136
+ {
137
+ // The error info belongs to the thread and the next failure replaces
138
+ // it, so it is taken before anything else can fail.
139
+ IErrorInfo* info{};
140
+ if (GetErrorInfo(0, &info) != S_OK)
141
+ {
142
+ info = nullptr;
143
+ }
144
+
145
+ return set_hresult_error(hr, info);
146
+ }
147
+
148
+ /// The @p I interface of what the interface pointer capsule @p capsule
149
+ /// holds, which the caller owns a reference to.
150
+ /// @returns false with a Python exception set when @p capsule is not one
151
+ /// or what it holds does not implement @p I.
152
+ template<typename I>
153
+ bool query_capsule(PyObject* capsule, I** result) noexcept
154
+ {
155
+ auto const abi = PyCapsule_GetPointer(capsule, interface_capsule_name);
156
+ if (!abi)
157
+ {
158
+ return false;
159
+ }
160
+
161
+ auto const hr = static_cast<IUnknown*>(abi)->QueryInterface(
162
+ __uuidof(I), reinterpret_cast<void**>(result));
163
+ if (FAILED(hr))
164
+ {
165
+ set_hresult_error(hr);
166
+ return false;
167
+ }
168
+
169
+ return true;
170
+ }
171
+
172
+ /// The slots of an interop module that has nothing to set up when it is
173
+ /// executed. It keeps no state, but it exchanges objects and errors with
174
+ /// winrt-runtime, which refuses any interpreter but the main one, so it
175
+ /// says the same where it can. The stable ABI of Python 3.11, which its
176
+ /// wheels are built for, has neither slot: there CPython refuses the
177
+ /// module in an interpreter with a GIL of its own anyway, winrt-runtime
178
+ /// refuses the rest, and a free-threaded build, which is what Py_mod_gil
179
+ /// is for, is never a stable ABI one.
180
+ ///
181
+ /// Each slot is looked for by its value: from 3.15 the headers name every
182
+ /// slot whatever the API, but give the values only to an API that has it.
183
+ inline PyModuleDef_Slot module_slots[]{
184
+ #ifdef Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED
185
+ {Py_mod_multiple_interpreters, Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED},
186
+ #endif
187
+ #ifdef Py_MOD_GIL_NOT_USED
188
+ {Py_mod_gil, Py_MOD_GIL_NOT_USED},
189
+ #endif
190
+ {}};
191
+ } // namespace interop
@@ -0,0 +1,271 @@
1
+ #include "interop.h"
2
+
3
+ #include <ole2.h>
4
+
5
+ #include <WebView2Interop.h>
6
+
7
+ #include <atomic>
8
+ #include <new>
9
+
10
+ // The WebView2 headers are made by MIDL, whose MIDL_INTERFACE names the IID
11
+ // with __declspec(uuid), which GCC does not have.
12
+ #ifdef __CRT_UUID_DECL
13
+ __CRT_UUID_DECL(
14
+ ICoreWebView2CompositionControllerInterop2,
15
+ // clang-format off
16
+ 0x6b47bbe1, 0x2480, 0x4ff8, 0xa5, 0xba, 0x69, 0xc2, 0xf0, 0xb8, 0x68, 0xb3
17
+ // clang-format on
18
+ )
19
+ #endif
20
+
21
+ // https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/winrt/interop/
22
+
23
+ namespace
24
+ {
25
+ /// An OLE drop target for a window that shows a visually hosted WebView2.
26
+ /// It hands each call to the WebView's composition controller, with the
27
+ /// point in the window's client coordinates, which is where the WebView
28
+ /// is drawn from.
29
+ ///
30
+ /// OLE calls it on the thread that registered it, from that thread's
31
+ /// message loop, and it calls nothing but the controller, so it needs no
32
+ /// GIL.
33
+ class drop_target final : public IDropTarget
34
+ {
35
+ public:
36
+ /// The reference to @p controller moves in.
37
+ drop_target(
38
+ ICoreWebView2CompositionControllerInterop2* controller, HWND hwnd) noexcept
39
+ : controller{controller}, hwnd{hwnd}
40
+ {
41
+ }
42
+
43
+ drop_target(drop_target const&) = delete;
44
+ drop_target& operator=(drop_target const&) = delete;
45
+
46
+ HRESULT STDMETHODCALLTYPE
47
+ QueryInterface(REFIID iid, void** result) noexcept override
48
+ {
49
+ if (!result)
50
+ {
51
+ return E_POINTER;
52
+ }
53
+
54
+ if (iid != __uuidof(IUnknown) && iid != __uuidof(IDropTarget))
55
+ {
56
+ *result = nullptr;
57
+ return E_NOINTERFACE;
58
+ }
59
+
60
+ AddRef();
61
+ *result = static_cast<IDropTarget*>(this);
62
+
63
+ return S_OK;
64
+ }
65
+
66
+ ULONG STDMETHODCALLTYPE AddRef() noexcept override
67
+ {
68
+ return ++references;
69
+ }
70
+
71
+ ULONG STDMETHODCALLTYPE Release() noexcept override
72
+ {
73
+ auto const remaining = --references;
74
+ if (remaining == 0)
75
+ {
76
+ delete this;
77
+ }
78
+
79
+ return remaining;
80
+ }
81
+
82
+ HRESULT STDMETHODCALLTYPE DragEnter(
83
+ IDataObject* data_object,
84
+ DWORD key_state,
85
+ POINTL point,
86
+ DWORD* effect) noexcept override
87
+ {
88
+ return controller->DragEnter(
89
+ data_object, key_state, to_client(point), effect);
90
+ }
91
+
92
+ HRESULT STDMETHODCALLTYPE
93
+ DragOver(DWORD key_state, POINTL point, DWORD* effect) noexcept override
94
+ {
95
+ return controller->DragOver(key_state, to_client(point), effect);
96
+ }
97
+
98
+ HRESULT STDMETHODCALLTYPE DragLeave() noexcept override
99
+ {
100
+ return controller->DragLeave();
101
+ }
102
+
103
+ HRESULT STDMETHODCALLTYPE Drop(
104
+ IDataObject* data_object,
105
+ DWORD key_state,
106
+ POINTL point,
107
+ DWORD* effect) noexcept override
108
+ {
109
+ return controller->Drop(data_object, key_state, to_client(point), effect);
110
+ }
111
+
112
+ private:
113
+ ~drop_target()
114
+ {
115
+ controller->Release();
116
+ }
117
+
118
+ /// OLE gives the point in screen coordinates.
119
+ POINT to_client(POINTL point) const noexcept
120
+ {
121
+ POINT client{point.x, point.y};
122
+ ScreenToClient(hwnd, &client);
123
+
124
+ return client;
125
+ }
126
+
127
+ std::atomic<ULONG> references{1};
128
+ ICoreWebView2CompositionControllerInterop2* const controller;
129
+ HWND const hwnd;
130
+ };
131
+
132
+ /// Parses a window handle.
133
+ /// @returns false with a Python exception set when @p obj is not one.
134
+ bool parse_hwnd(PyObject* obj, HWND* hwnd) noexcept
135
+ {
136
+ auto const handle = PyLong_AsVoidPtr(obj);
137
+ if (!handle && PyErr_Occurred())
138
+ {
139
+ return false;
140
+ }
141
+
142
+ *hwnd = static_cast<HWND>(handle);
143
+
144
+ return true;
145
+ }
146
+
147
+ /// OLE registers and revokes a window's drop target on the thread that
148
+ /// owns the window, and calls it there.
149
+ /// @returns false with a Python exception set when @p hwnd is not a
150
+ /// window of the calling thread.
151
+ bool check_window_thread(HWND hwnd) noexcept
152
+ {
153
+ if (GetWindowThreadProcessId(hwnd, nullptr) != GetCurrentThreadId())
154
+ {
155
+ PyErr_SetString(PyExc_ValueError, "hwnd is not a window of this thread");
156
+ return false;
157
+ }
158
+
159
+ return true;
160
+ }
161
+
162
+ PyObject* register_drop_target(PyObject* /*unused*/, PyObject* args) noexcept
163
+ {
164
+ PyObject* controller_capsule;
165
+ PyObject* hwnd_obj;
166
+
167
+ if (!PyArg_ParseTuple(args, "OO", &controller_capsule, &hwnd_obj))
168
+ {
169
+ return nullptr;
170
+ }
171
+
172
+ HWND hwnd;
173
+ if (!parse_hwnd(hwnd_obj, &hwnd))
174
+ {
175
+ return nullptr;
176
+ }
177
+
178
+ if (!check_window_thread(hwnd))
179
+ {
180
+ return nullptr;
181
+ }
182
+
183
+ ICoreWebView2CompositionControllerInterop2* controller{};
184
+ if (!interop::query_capsule(controller_capsule, &controller))
185
+ {
186
+ return nullptr;
187
+ }
188
+
189
+ // RegisterDragDrop needs OLE, not only COM, and revoke_drop_target()
190
+ // balances this.
191
+ auto hr = OleInitialize(nullptr);
192
+ if (FAILED(hr))
193
+ {
194
+ controller->Release();
195
+ return interop::set_hresult_error(hr);
196
+ }
197
+
198
+ auto const target = new (std::nothrow) drop_target{controller, hwnd};
199
+ if (!target)
200
+ {
201
+ controller->Release();
202
+ OleUninitialize();
203
+ return PyErr_NoMemory();
204
+ }
205
+
206
+ // On success, OLE holds a reference of its own until the window's
207
+ // drop target is revoked.
208
+ hr = RegisterDragDrop(hwnd, target);
209
+ target->Release();
210
+ if (FAILED(hr))
211
+ {
212
+ auto const error = interop::set_hresult_error(hr);
213
+ OleUninitialize();
214
+ return error;
215
+ }
216
+
217
+ Py_RETURN_NONE;
218
+ }
219
+
220
+ PyObject* revoke_drop_target(PyObject* /*unused*/, PyObject* hwnd_obj) noexcept
221
+ {
222
+ HWND hwnd;
223
+ if (!parse_hwnd(hwnd_obj, &hwnd))
224
+ {
225
+ return nullptr;
226
+ }
227
+
228
+ if (!check_window_thread(hwnd))
229
+ {
230
+ return nullptr;
231
+ }
232
+
233
+ HRESULT hr;
234
+ {
235
+ // OLE's reference may be the last one to the drop target, which
236
+ // holds the controller.
237
+ interop::gil_released const guard;
238
+ hr = RevokeDragDrop(hwnd);
239
+ }
240
+
241
+ if (FAILED(hr))
242
+ {
243
+ return interop::set_hresult_error(hr);
244
+ }
245
+
246
+ OleUninitialize();
247
+
248
+ Py_RETURN_NONE;
249
+ }
250
+
251
+ PyMethodDef module_methods[]{
252
+ {"register_drop_target", register_drop_target, METH_VARARGS, nullptr},
253
+ {"revoke_drop_target", revoke_drop_target, METH_O, nullptr},
254
+ {}};
255
+
256
+ PyModuleDef module_def
257
+ = {PyModuleDef_HEAD_INIT,
258
+ "_winrt_microsoft_web_webview2_interop",
259
+ nullptr,
260
+ 0,
261
+ module_methods,
262
+ interop::module_slots,
263
+ nullptr,
264
+ nullptr,
265
+ nullptr};
266
+ } // namespace
267
+
268
+ PyMODINIT_FUNC PyInit__winrt_microsoft_web_webview2_interop(void) noexcept
269
+ {
270
+ return PyModuleDef_Init(&module_def);
271
+ }
@@ -0,0 +1,54 @@
1
+ # WARNING: Please don't edit this file. It was automatically generated.
2
+
3
+ [build-system]
4
+ requires = ["setuptools>=78"]
5
+ build-backend = "setuptools.build_meta"
6
+
7
+ [project]
8
+ name = "winrt-Microsoft.Web.WebView2.Interop"
9
+ version = "4!1.0.4314.35.1"
10
+ description = "Lets a visually hosted WebView2 take the files dropped on its window, as an OLE drop target."
11
+ readme = "README.md"
12
+ license = "MIT"
13
+ license-files = ["LICENSE"]
14
+ classifiers = [
15
+ "Operating System :: Microsoft :: Windows",
16
+ "Programming Language :: Python :: 3",
17
+ "Programming Language :: Python :: 3.11",
18
+ "Programming Language :: Python :: 3.12",
19
+ "Programming Language :: Python :: 3.13",
20
+ "Programming Language :: Python :: 3.14",
21
+ "Programming Language :: Python :: 3.15",
22
+ "Programming Language :: Python :: Implementation :: CPython",
23
+ "Intended Audience :: Developers",
24
+ "Programming Language :: Python :: Free Threading :: 2 - Beta",
25
+ "Typing :: Typed",
26
+ ]
27
+ dynamic = ["dependencies"]
28
+ requires-python = ">=3.11"
29
+
30
+ [project.urls]
31
+ Documentation = "https://pywinrt.readthedocs.io"
32
+ Repository = "https://github.com/pywinrt/pywinrt"
33
+ Changelog = "https://github.com/pywinrt/pywinrt/blob/main/projection/webview2/CHANGELOG.md"
34
+
35
+ [tool.setuptools.dynamic]
36
+ dependencies = { file = "requirements.txt" }
37
+
38
+ [tool.setuptools.packages.find]
39
+ include = ["winrt*"]
40
+
41
+ [tool.setuptools.package-data]
42
+ "*" = ["*.pyi", "py.typed"]
43
+
44
+ [tool.cibuildwheel]
45
+ # don't build for PyPy
46
+ skip = "pp*"
47
+ # suppress warnings about ARM64 testing
48
+ test-skip = "*-win_arm64"
49
+ test-command = "python -c \"import winrt._winrt_microsoft_web_webview2_interop\""
50
+
51
+ [tool.cibuildwheel.windows]
52
+ archs = ["x86", "AMD64", "ARM64"]
53
+ # nothing here is copied in after the build, so there is no repair step
54
+ repair-wheel-command = ""
@@ -0,0 +1,4 @@
1
+ # This file is generated by scripts/generate-pyproject.py
2
+
3
+ winrt-runtime>=4.0.0,<5
4
+ winrt-Microsoft.Web.WebView2>=4!1.0.4314.35
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,123 @@
1
+ # WARNING: Please don't edit this file. It was automatically generated.
2
+ # setuptools does not annotate the build_ext methods this file overrides.
3
+ # pyright: reportUnknownMemberType=false
4
+
5
+ import hashlib
6
+ import io
7
+ import os
8
+ import pathlib
9
+ import shutil
10
+ import sysconfig
11
+ import urllib.request
12
+ import zipfile
13
+
14
+ from setuptools import Extension, setup
15
+ from setuptools.command.build_ext import build_ext
16
+
17
+ INCLUDE_DIRS: list[str] = []
18
+
19
+ # Each NuGet package the module compiles against, named by the environment
20
+ # variable that points at an unpacked copy of it: what it is unpacked as, where
21
+ # nuget.org serves it, what it has to hash to and where in it the headers are.
22
+ NUGET_PACKAGES = {
23
+ "WEBVIEW2_PATH": (
24
+ "Microsoft.Web.WebView2.1.0.4314.35",
25
+ "https://api.nuget.org/v3-flatcontainer/microsoft.web.webview2/1.0.4314.35/microsoft.web.webview2.1.0.4314.35.nupkg",
26
+ "90778deb1b77e36292828b4b5833c9255c27533f40e0ddd55891ae718944edc4",
27
+ ["build/native/include", "build/native/include-winrt"],
28
+ ),
29
+ }
30
+
31
+
32
+ def unpack_nuget_package(env: str) -> pathlib.Path:
33
+ """
34
+ Where the package named by @p env is unpacked: the copy the environment
35
+ variable points at, or else one downloaded from nuget.org into build/.
36
+ """
37
+ if env in os.environ:
38
+ return pathlib.Path(os.environ[env]).resolve()
39
+
40
+ name, url, sha256, _ = NUGET_PACKAGES[env]
41
+ path = pathlib.Path(__file__).parent.resolve() / "build" / "nuget" / name
42
+
43
+ if path.is_dir():
44
+ return path
45
+
46
+ try:
47
+ with urllib.request.urlopen(url, timeout=120) as response:
48
+ data = response.read()
49
+ except OSError as error:
50
+ raise RuntimeError(
51
+ f"could not download {url}: {error}. Set {env} to an unpacked"
52
+ f" copy of {name} to build without reaching the network."
53
+ ) from error
54
+
55
+ digest = hashlib.sha256(data).hexdigest()
56
+
57
+ if digest != sha256:
58
+ raise RuntimeError(f"{url} hashes to {digest} and not to {sha256}")
59
+
60
+ # Unpacked beside where it goes and then moved there, so that a build
61
+ # stopped halfway leaves nothing the next one would take for unpacked.
62
+ partial = path.with_name(path.name + ".partial")
63
+ shutil.rmtree(partial, ignore_errors=True)
64
+
65
+ with zipfile.ZipFile(io.BytesIO(data)) as package:
66
+ package.extractall(partial)
67
+
68
+ partial.rename(path)
69
+
70
+ return path
71
+
72
+
73
+ NUGET_PATHS: dict[str, pathlib.Path] = {}
74
+
75
+ for name, (_, _, _, include_dirs) in NUGET_PACKAGES.items():
76
+ NUGET_PATHS[name] = unpack_nuget_package(name)
77
+ print(f"Using {name} from {NUGET_PATHS[name]}")
78
+ INCLUDE_DIRS.extend(os.fspath(NUGET_PATHS[name] / d) for d in include_dirs)
79
+
80
+ # compiled against the stable ABI of Python 3.11, except where the interpreter
81
+ # is free-threaded, which has none, or MSYS2's, whose modules link against the
82
+ # version's own DLL
83
+ STABLE_ABI = not (
84
+ sysconfig.get_config_var("Py_GIL_DISABLED")
85
+ or sysconfig.get_platform().startswith("mingw")
86
+ )
87
+
88
+
89
+ class build_ext_ex(build_ext):
90
+ def build_extension(self, ext: Extension) -> None:
91
+ # nothing in the projection uses dynamic_cast or typeid, so disabling
92
+ # RTTI costs nothing and makes the module about 15% smaller
93
+ if self.compiler.compiler_type == "msvc":
94
+ ext.extra_compile_args = ["/std:c++20", "/permissive-", "/GR-"]
95
+ elif self.compiler.compiler_type == "mingw32":
96
+ ext.extra_compile_args = [
97
+ "-std=c++20",
98
+ "-fno-rtti",
99
+ "-D_WIN32_WINNT=_WIN32_WINNT_WIN10",
100
+ ]
101
+ # GCC 15 complains about some things that it didn't in the past
102
+ ext.extra_compile_args += ["-Wno-strict-aliasing", "-Wno-template-body"]
103
+ ext.extra_link_args = ["-loleaut32"]
104
+ else:
105
+ raise ValueError(f"Unsupported compiler: {self.compiler.compiler_type}")
106
+
107
+ build_ext.build_extension(self, ext)
108
+
109
+
110
+ setup(
111
+ cmdclass={"build_ext": build_ext_ex},
112
+ ext_modules=[
113
+ Extension(
114
+ "winrt._winrt_microsoft_web_webview2_interop",
115
+ sources=["py.Microsoft.Web.WebView2.Interop.cpp"],
116
+ include_dirs=INCLUDE_DIRS,
117
+ libraries=["windowsapp", "ole32", "user32"],
118
+ define_macros=[("Py_LIMITED_API", "0x030B0000")] if STABLE_ABI else [],
119
+ py_limited_api=STABLE_ABI,
120
+ )
121
+ ],
122
+ options={"bdist_wheel": {"py_limited_api": "cp311"}} if STABLE_ABI else {},
123
+ )
@@ -0,0 +1,4 @@
1
+ from winrt.runtime.interop import InterfaceCapsule
2
+
3
+ def register_drop_target(controller: InterfaceCapsule, hwnd: int, /) -> None: ...
4
+ def revoke_drop_target(hwnd: int, /) -> None: ...
@@ -0,0 +1,62 @@
1
+ import typing as _typing
2
+
3
+ import winrt.runtime.interop as _runtime
4
+ import winrt._winrt_microsoft_web_webview2_interop as _native
5
+ import winrt.microsoft.web.webview2.core as _core
6
+
7
+ __all__ = ["DropTarget", "register_drop_target"]
8
+
9
+
10
+ @_typing.final
11
+ class DropTarget:
12
+ """
13
+ A window registered as the OLE drop target of a visually hosted WebView2,
14
+ which register_drop_target() returns.
15
+ """
16
+
17
+ __slots__ = ("_hwnd",)
18
+
19
+ _hwnd: int | None
20
+
21
+ def __init__(self) -> None:
22
+ raise TypeError("DropTarget is made by register_drop_target()")
23
+
24
+ def close(self) -> None:
25
+ """
26
+ Revokes the registration, on the thread that owns the window and before
27
+ the window is destroyed. Calling it again does nothing.
28
+ """
29
+ if self._hwnd is None:
30
+ return
31
+
32
+ _native.revoke_drop_target(self._hwnd)
33
+ self._hwnd = None
34
+
35
+ def __enter__(self) -> _typing.Self:
36
+ return self
37
+
38
+ def __exit__(self, *args: object) -> None:
39
+ self.close()
40
+
41
+
42
+ def register_drop_target(
43
+ controller: _core.CoreWebView2CompositionController, hwnd: int, /
44
+ ) -> DropTarget:
45
+ """
46
+ Registers the window hwnd as an OLE drop target that hands what is dragged
47
+ over it to the WebView that controller controls, which is drawn from the
48
+ top left corner of the window's client area.
49
+
50
+ It has to be called on the thread that owns the window, which it
51
+ initializes OLE on. The WebView takes a drop only while the controller's
52
+ allow_external_drop is true.
53
+ """
54
+ _native.register_drop_target(
55
+ _runtime.as_interface(controller, _core.CoreWebView2CompositionController),
56
+ hwnd,
57
+ )
58
+
59
+ target = object.__new__(DropTarget)
60
+ target._hwnd = hwnd # pyright: ignore[reportPrivateUsage]
61
+
62
+ return target
@@ -0,0 +1,42 @@
1
+ Metadata-Version: 2.4
2
+ Name: winrt-Microsoft.Web.WebView2.Interop
3
+ Version: 4!1.0.4314.35.1
4
+ Summary: Lets a visually hosted WebView2 take the files dropped on its window, as an OLE drop target.
5
+ License-Expression: MIT
6
+ Project-URL: Documentation, https://pywinrt.readthedocs.io
7
+ Project-URL: Repository, https://github.com/pywinrt/pywinrt
8
+ Project-URL: Changelog, https://github.com/pywinrt/pywinrt/blob/main/projection/webview2/CHANGELOG.md
9
+ Classifier: Operating System :: Microsoft :: Windows
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Programming Language :: Python :: 3.13
14
+ Classifier: Programming Language :: Python :: 3.14
15
+ Classifier: Programming Language :: Python :: 3.15
16
+ Classifier: Programming Language :: Python :: Implementation :: CPython
17
+ Classifier: Intended Audience :: Developers
18
+ Classifier: Programming Language :: Python :: Free Threading :: 2 - Beta
19
+ Classifier: Typing :: Typed
20
+ Requires-Python: >=3.11
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Requires-Dist: winrt-runtime<5,>=4.0.0
24
+ Requires-Dist: winrt-Microsoft.Web.WebView2>=4!1.0.4314.35
25
+ Dynamic: license-file
26
+
27
+ <!-- warning: Please don't edit this file. It was automatically generated. -->
28
+
29
+ # winrt-Microsoft.Web.WebView2.Interop
30
+
31
+ Lets a visually hosted WebView2 take the files dropped on its window, as an OLE drop target.
32
+
33
+ This package provides the `winrt.microsoft.web.webview2.interop` module.
34
+
35
+ It is built against version 1.0.4314.35 of the `Microsoft.Web.WebView2`
36
+ NuGet package.
37
+
38
+ ```
39
+ pip install winrt-Microsoft.Web.WebView2.Interop
40
+ ```
41
+
42
+ installs it with `winrt-Microsoft.Web.WebView2`.
@@ -0,0 +1,16 @@
1
+ LICENSE
2
+ MANIFEST.in
3
+ README.md
4
+ interop.h
5
+ py.Microsoft.Web.WebView2.Interop.cpp
6
+ pyproject.toml
7
+ requirements.txt
8
+ setup.py
9
+ winrt/_winrt_microsoft_web_webview2_interop.pyi
10
+ winrt/microsoft/web/webview2/interop/__init__.py
11
+ winrt/microsoft/web/webview2/interop/py.typed
12
+ winrt_Microsoft.Web.WebView2.Interop.egg-info/PKG-INFO
13
+ winrt_Microsoft.Web.WebView2.Interop.egg-info/SOURCES.txt
14
+ winrt_Microsoft.Web.WebView2.Interop.egg-info/dependency_links.txt
15
+ winrt_Microsoft.Web.WebView2.Interop.egg-info/requires.txt
16
+ winrt_Microsoft.Web.WebView2.Interop.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ winrt-runtime<5,>=4.0.0
2
+ winrt-Microsoft.Web.WebView2>=4!1.0.4314.35