pyglass-qt 0.2.0__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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 neomosh8
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,199 @@
1
+ Metadata-Version: 2.4
2
+ Name: pyglass-qt
3
+ Version: 0.2.0
4
+ Summary: Physically-grounded refractive glass widgets for PyQt6 — real refraction, chromatic dispersion, Fresnel reflection and frost.
5
+ Author-email: neomosh8 <mosh@neocore.tech>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/neomosh8/pyglass
8
+ Project-URL: Repository, https://github.com/neomosh8/pyglass
9
+ Project-URL: Issues, https://github.com/neomosh8/pyglass/issues
10
+ Keywords: pyqt6,qt,glass,glassmorphism,refraction,dispersion,ui,widgets
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Environment :: X11 Applications :: Qt
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Topic :: Multimedia :: Graphics
23
+ Classifier: Topic :: Software Development :: User Interfaces
24
+ Requires-Python: >=3.9
25
+ Description-Content-Type: text/markdown
26
+ License-File: LICENSE
27
+ Requires-Dist: PyQt6>=6.6
28
+ Requires-Dist: numpy>=1.24
29
+ Dynamic: license-file
30
+
31
+ # PyGlass
32
+
33
+ Physically-grounded refractive **glass** for **PyQt6** — drop it onto any app.
34
+
35
+ PyGlass renders glass the way glass behaves: refraction through a beveled slab,
36
+ chromatic dispersion, Fresnel reflectance, an iridescent rim and an optional
37
+ frosted (rough-surface) blur. It ships as a reusable package with two layers —
38
+ a one-line widget for the common case, and the raw engine for custom widgets.
39
+
40
+ ## Install
41
+
42
+ ```bash
43
+ pip install pyglass-qt # from PyPI
44
+ # or straight from GitHub:
45
+ pip install "git+https://github.com/neomosh8/pyglass.git"
46
+ ```
47
+
48
+ > The distribution is **`pyglass-qt`** (the name `pyglass` was taken on PyPI), but
49
+ > you still `import pyglass`. Only PyQt6 + numpy are pulled in.
50
+
51
+ To run the demos from a clone instead:
52
+
53
+ ```bash
54
+ python3 -m venv .venv
55
+ .venv/bin/python -m pip install -r requirements.txt # PyQt6 + numpy
56
+ .venv/bin/python main.py
57
+ ```
58
+
59
+ ## Use it in your app
60
+
61
+ **High level — `GlassPane`.** A frameless glass widget. Give it a parent and it
62
+ becomes an in-app modal/panel that refracts your app; leave it parentless and it
63
+ becomes a top-level window that refracts the live desktop. Draggable, with live
64
+ dials built in.
65
+
66
+ ```python
67
+ from pyglass import GlassPane, GlassMaterial
68
+ from PyQt6.QtWidgets import QVBoxLayout, QLabel
69
+
70
+ # A glass modal over your existing window — refracts whatever's behind it.
71
+ pane = GlassPane(my_window, material=GlassMaterial(thickness=0.6, frost=0.3))
72
+ QVBoxLayout(pane.content).addWidget(QLabel("Hello from glass"))
73
+ pane.show()
74
+
75
+ # …or a glass window over the live desktop:
76
+ desk = GlassPane(material=GlassMaterial(thickness=0.7, frost=0.15))
77
+ desk.show()
78
+ ```
79
+
80
+ Put your widgets in `pane.content`. The pane captures its parent (with itself
81
+ hidden) for the backdrop, so **no cooperation from the host is needed** — it
82
+ works on any widget. See [`examples/`](examples/).
83
+
84
+ **Low level — compose it yourself.** Build the glass inside your own
85
+ `paintEvent` with the engine pieces: a backdrop provider →
86
+ [`GlassRenderer`](pyglass/effect.py) (backdrop array → refracted pixmap) →
87
+ [`paint_glass`](pyglass/effect.py) (shadow + refraction + tint + rim). See
88
+ [`pyglass/glass.py`](pyglass/glass.py) (`GlassPopup`) for a full worked example
89
+ with a scrim and an open/close animation.
90
+
91
+ ```python
92
+ from pyglass import GlassRenderer, paint_glass, WidgetBackdrop, GlassMaterial
93
+
94
+ backdrop = WidgetBackdrop(host) # or ScreenBackdrop(window)
95
+ renderer = GlassRenderer(GlassMaterial(), w, h, radius)
96
+ backdrop.changed.connect(lambda: self.update())
97
+ # in paintEvent:
98
+ pm = renderer.refract(backdrop.array(), origin, backdrop.dpr())
99
+ paint_glass(painter, panel_rect, radius, pm)
100
+ ```
101
+
102
+ ## The two dials
103
+
104
+ The entire look is driven by [`GlassMaterial`](pyglass/refract.py) — two
105
+ perceptual dials in `[0, 1]` that re-derive a dozen physical parameters so the
106
+ pane always reads as one coherent piece of glass. The neutral pair
107
+ (`thickness=0.5, frost=0`) reproduces the tuned baseline exactly.
108
+
109
+ | Dial | What it means | What it drives |
110
+ | --- | --- | --- |
111
+ | **`thickness`** | perceived slab depth / mass (optical path length) | displacement (`strength`), the curved lens-wrap width (`bevel`), the IOR range / rim bend, chromatic dispersion (`chroma`), the spectral rim-line width, and the capture margin so the wrap never clamps |
112
+ | **`frost`** | surface roughness (ground / milk glass) | a transmission blur (scatter), a milky multiple-scatter haze, and a softened dispersion line — transmission-side only, so `frost=0` is byte-for-byte the sharp look |
113
+
114
+ `thickness` is a single scalar standing in for *T*: a thicker slab bends light
115
+ more, has a bigger rounded edge, disperses colour more (longer optical path) and
116
+ casts a thicker rim — all slaved together. `frost` is microfacet roughness: a
117
+ rough face scatters transmitted light into a cone that projects to a blur, plus
118
+ a faint milky veil.
119
+
120
+ `GlassStyle` separately tunes the non-physical chrome (shadow, tint, sheen, rim).
121
+
122
+ ## Run the demos
123
+
124
+ ```bash
125
+ .venv/bin/python main.py # in-app frosted refractive modal
126
+ .venv/bin/python main.py --desktop # glass window over your live desktop
127
+ .venv/bin/python examples/in_app_modal.py
128
+ .venv/bin/python examples/desktop_window.py
129
+ ```
130
+
131
+ In any of them: **drag** the panel; **`[`** / **`]`** adjust thickness;
132
+ **`-`** / **`=`** adjust frost; **`R`** refreshes the backdrop; on the desktop
133
+ pane **`L`** toggles live auto-refresh; **`Esc`** closes.
134
+
135
+ ## Desktop mode — glass over your real screen
136
+
137
+ A parentless `GlassPane` (or `python main.py --desktop`) floats over your **live**
138
+ desktop and refracts whatever is behind it — all your windows, not just the
139
+ wallpaper.
140
+
141
+ * **macOS:** it shells out to the system **`screencapture`** (which, unlike Qt's
142
+ `grabWindow`, returns the full screen with every window) and excludes *itself*
143
+ from capture via `NSWindowSharingNone`. Because the window is excluded, the
144
+ backdrop **auto-refreshes live** with no hide/flicker, and dragging stays
145
+ smooth (it re-slices the last capture each frame).
146
+
147
+ > Needs Screen Recording permission (System Settings → Privacy & Security →
148
+ > Screen Recording) for the terminal/app running Python. If only the wallpaper
149
+ > shows, grant it and relaunch.
150
+
151
+ * **Windows / Linux:** Qt's `grabWindow` can't be told to exclude the window, so
152
+ a periodic re-grab would flicker. PyGlass therefore captures **once and stays
153
+ paused** (press **`R`** to refresh) — no flicker. The dials still work live
154
+ against the cached frame.
155
+
156
+ ## Platform support
157
+
158
+ Cross-platform — **macOS, Windows, Linux**. PyQt6 + numpy only. The in-app glass
159
+ reads the app's *own* rendered scene (no OS screen-capture permission needed);
160
+ fonts fall back gracefully (SF Pro → Segoe UI → Arial) and device-pixel-ratio is
161
+ handled, so it renders correctly on Windows HiDPI and Retina alike.
162
+
163
+ ## Render a preview without a display
164
+
165
+ ```bash
166
+ QT_QPA_PLATFORM=offscreen .venv/bin/python scripts/render_preview.py preview.png
167
+ ```
168
+
169
+ ## Layout
170
+
171
+ | File | Purpose |
172
+ | --- | --- |
173
+ | [`pyglass/refract.py`](pyglass/refract.py) | Engine — `GlassKernel` (refraction + Fresnel over a beveled SDF) and `GlassMaterial` (the two dials) |
174
+ | [`pyglass/effect.py`](pyglass/effect.py) | `GlassRenderer`, `paint_glass`, `GlassStyle` — the reusable rendering core |
175
+ | [`pyglass/backdrop.py`](pyglass/backdrop.py) | `WidgetBackdrop` / `ScreenBackdrop` — *what* the glass refracts |
176
+ | [`pyglass/pane.py`](pyglass/pane.py) | `GlassPane` — the drop-in glass widget (+ `ui_font`) |
177
+ | [`pyglass/glass.py`](pyglass/glass.py) | `GlassPopup` — in-app modal demo built on the low-level core |
178
+ | [`pyglass/desktop.py`](pyglass/desktop.py) | `DesktopGlass` — desktop-window demo, a thin `GlassPane` subclass |
179
+ | [`pyglass/demo.py`](pyglass/demo.py) | `DemoBackground` — colourful host scene + launch button |
180
+ | [`examples/`](examples/) | Standalone third-party usage of `GlassPane` |
181
+ | [`main.py`](main.py) | Entry point (`--desktop` for desktop mode) |
182
+
183
+ ## How the refraction works
184
+
185
+ The panel is a **beveled glass slab** over a rounded-rectangle signed distance
186
+ field. The flat centre passes light straight through; the rim is a quarter-circle
187
+ **roundover** whose slope grows toward the edge. The vertical incident ray is
188
+ refracted there with **Snell's law** and projected through the glass thickness,
189
+ so the `1/(-T_z)` term curls the background into a curved lens-*wrap* (not a flat
190
+ shift). Each colour channel uses its own IOR → a **chromatic-dispersion** fringe.
191
+ The Schlick–**Fresnel** term rises from ~`F0` at the centre to ~1 at the grazing
192
+ rim, where the surface reflects a virtual environment (horizon ambient + a warm
193
+ key and cool fill light). A lightened **iridescent** spectral line is added along
194
+ the border. Frost adds a fast separable blur of the transmitted background.
195
+
196
+ All geometry-dependent work (normals, per-channel sample coordinates, Fresnel
197
+ weight, reflected environment) is precomputed once into a `GlassKernel`; each
198
+ frame only runs the bilinear gather (+ the box blur when frosted), so dragging
199
+ stays smooth.
@@ -0,0 +1,169 @@
1
+ # PyGlass
2
+
3
+ Physically-grounded refractive **glass** for **PyQt6** — drop it onto any app.
4
+
5
+ PyGlass renders glass the way glass behaves: refraction through a beveled slab,
6
+ chromatic dispersion, Fresnel reflectance, an iridescent rim and an optional
7
+ frosted (rough-surface) blur. It ships as a reusable package with two layers —
8
+ a one-line widget for the common case, and the raw engine for custom widgets.
9
+
10
+ ## Install
11
+
12
+ ```bash
13
+ pip install pyglass-qt # from PyPI
14
+ # or straight from GitHub:
15
+ pip install "git+https://github.com/neomosh8/pyglass.git"
16
+ ```
17
+
18
+ > The distribution is **`pyglass-qt`** (the name `pyglass` was taken on PyPI), but
19
+ > you still `import pyglass`. Only PyQt6 + numpy are pulled in.
20
+
21
+ To run the demos from a clone instead:
22
+
23
+ ```bash
24
+ python3 -m venv .venv
25
+ .venv/bin/python -m pip install -r requirements.txt # PyQt6 + numpy
26
+ .venv/bin/python main.py
27
+ ```
28
+
29
+ ## Use it in your app
30
+
31
+ **High level — `GlassPane`.** A frameless glass widget. Give it a parent and it
32
+ becomes an in-app modal/panel that refracts your app; leave it parentless and it
33
+ becomes a top-level window that refracts the live desktop. Draggable, with live
34
+ dials built in.
35
+
36
+ ```python
37
+ from pyglass import GlassPane, GlassMaterial
38
+ from PyQt6.QtWidgets import QVBoxLayout, QLabel
39
+
40
+ # A glass modal over your existing window — refracts whatever's behind it.
41
+ pane = GlassPane(my_window, material=GlassMaterial(thickness=0.6, frost=0.3))
42
+ QVBoxLayout(pane.content).addWidget(QLabel("Hello from glass"))
43
+ pane.show()
44
+
45
+ # …or a glass window over the live desktop:
46
+ desk = GlassPane(material=GlassMaterial(thickness=0.7, frost=0.15))
47
+ desk.show()
48
+ ```
49
+
50
+ Put your widgets in `pane.content`. The pane captures its parent (with itself
51
+ hidden) for the backdrop, so **no cooperation from the host is needed** — it
52
+ works on any widget. See [`examples/`](examples/).
53
+
54
+ **Low level — compose it yourself.** Build the glass inside your own
55
+ `paintEvent` with the engine pieces: a backdrop provider →
56
+ [`GlassRenderer`](pyglass/effect.py) (backdrop array → refracted pixmap) →
57
+ [`paint_glass`](pyglass/effect.py) (shadow + refraction + tint + rim). See
58
+ [`pyglass/glass.py`](pyglass/glass.py) (`GlassPopup`) for a full worked example
59
+ with a scrim and an open/close animation.
60
+
61
+ ```python
62
+ from pyglass import GlassRenderer, paint_glass, WidgetBackdrop, GlassMaterial
63
+
64
+ backdrop = WidgetBackdrop(host) # or ScreenBackdrop(window)
65
+ renderer = GlassRenderer(GlassMaterial(), w, h, radius)
66
+ backdrop.changed.connect(lambda: self.update())
67
+ # in paintEvent:
68
+ pm = renderer.refract(backdrop.array(), origin, backdrop.dpr())
69
+ paint_glass(painter, panel_rect, radius, pm)
70
+ ```
71
+
72
+ ## The two dials
73
+
74
+ The entire look is driven by [`GlassMaterial`](pyglass/refract.py) — two
75
+ perceptual dials in `[0, 1]` that re-derive a dozen physical parameters so the
76
+ pane always reads as one coherent piece of glass. The neutral pair
77
+ (`thickness=0.5, frost=0`) reproduces the tuned baseline exactly.
78
+
79
+ | Dial | What it means | What it drives |
80
+ | --- | --- | --- |
81
+ | **`thickness`** | perceived slab depth / mass (optical path length) | displacement (`strength`), the curved lens-wrap width (`bevel`), the IOR range / rim bend, chromatic dispersion (`chroma`), the spectral rim-line width, and the capture margin so the wrap never clamps |
82
+ | **`frost`** | surface roughness (ground / milk glass) | a transmission blur (scatter), a milky multiple-scatter haze, and a softened dispersion line — transmission-side only, so `frost=0` is byte-for-byte the sharp look |
83
+
84
+ `thickness` is a single scalar standing in for *T*: a thicker slab bends light
85
+ more, has a bigger rounded edge, disperses colour more (longer optical path) and
86
+ casts a thicker rim — all slaved together. `frost` is microfacet roughness: a
87
+ rough face scatters transmitted light into a cone that projects to a blur, plus
88
+ a faint milky veil.
89
+
90
+ `GlassStyle` separately tunes the non-physical chrome (shadow, tint, sheen, rim).
91
+
92
+ ## Run the demos
93
+
94
+ ```bash
95
+ .venv/bin/python main.py # in-app frosted refractive modal
96
+ .venv/bin/python main.py --desktop # glass window over your live desktop
97
+ .venv/bin/python examples/in_app_modal.py
98
+ .venv/bin/python examples/desktop_window.py
99
+ ```
100
+
101
+ In any of them: **drag** the panel; **`[`** / **`]`** adjust thickness;
102
+ **`-`** / **`=`** adjust frost; **`R`** refreshes the backdrop; on the desktop
103
+ pane **`L`** toggles live auto-refresh; **`Esc`** closes.
104
+
105
+ ## Desktop mode — glass over your real screen
106
+
107
+ A parentless `GlassPane` (or `python main.py --desktop`) floats over your **live**
108
+ desktop and refracts whatever is behind it — all your windows, not just the
109
+ wallpaper.
110
+
111
+ * **macOS:** it shells out to the system **`screencapture`** (which, unlike Qt's
112
+ `grabWindow`, returns the full screen with every window) and excludes *itself*
113
+ from capture via `NSWindowSharingNone`. Because the window is excluded, the
114
+ backdrop **auto-refreshes live** with no hide/flicker, and dragging stays
115
+ smooth (it re-slices the last capture each frame).
116
+
117
+ > Needs Screen Recording permission (System Settings → Privacy & Security →
118
+ > Screen Recording) for the terminal/app running Python. If only the wallpaper
119
+ > shows, grant it and relaunch.
120
+
121
+ * **Windows / Linux:** Qt's `grabWindow` can't be told to exclude the window, so
122
+ a periodic re-grab would flicker. PyGlass therefore captures **once and stays
123
+ paused** (press **`R`** to refresh) — no flicker. The dials still work live
124
+ against the cached frame.
125
+
126
+ ## Platform support
127
+
128
+ Cross-platform — **macOS, Windows, Linux**. PyQt6 + numpy only. The in-app glass
129
+ reads the app's *own* rendered scene (no OS screen-capture permission needed);
130
+ fonts fall back gracefully (SF Pro → Segoe UI → Arial) and device-pixel-ratio is
131
+ handled, so it renders correctly on Windows HiDPI and Retina alike.
132
+
133
+ ## Render a preview without a display
134
+
135
+ ```bash
136
+ QT_QPA_PLATFORM=offscreen .venv/bin/python scripts/render_preview.py preview.png
137
+ ```
138
+
139
+ ## Layout
140
+
141
+ | File | Purpose |
142
+ | --- | --- |
143
+ | [`pyglass/refract.py`](pyglass/refract.py) | Engine — `GlassKernel` (refraction + Fresnel over a beveled SDF) and `GlassMaterial` (the two dials) |
144
+ | [`pyglass/effect.py`](pyglass/effect.py) | `GlassRenderer`, `paint_glass`, `GlassStyle` — the reusable rendering core |
145
+ | [`pyglass/backdrop.py`](pyglass/backdrop.py) | `WidgetBackdrop` / `ScreenBackdrop` — *what* the glass refracts |
146
+ | [`pyglass/pane.py`](pyglass/pane.py) | `GlassPane` — the drop-in glass widget (+ `ui_font`) |
147
+ | [`pyglass/glass.py`](pyglass/glass.py) | `GlassPopup` — in-app modal demo built on the low-level core |
148
+ | [`pyglass/desktop.py`](pyglass/desktop.py) | `DesktopGlass` — desktop-window demo, a thin `GlassPane` subclass |
149
+ | [`pyglass/demo.py`](pyglass/demo.py) | `DemoBackground` — colourful host scene + launch button |
150
+ | [`examples/`](examples/) | Standalone third-party usage of `GlassPane` |
151
+ | [`main.py`](main.py) | Entry point (`--desktop` for desktop mode) |
152
+
153
+ ## How the refraction works
154
+
155
+ The panel is a **beveled glass slab** over a rounded-rectangle signed distance
156
+ field. The flat centre passes light straight through; the rim is a quarter-circle
157
+ **roundover** whose slope grows toward the edge. The vertical incident ray is
158
+ refracted there with **Snell's law** and projected through the glass thickness,
159
+ so the `1/(-T_z)` term curls the background into a curved lens-*wrap* (not a flat
160
+ shift). Each colour channel uses its own IOR → a **chromatic-dispersion** fringe.
161
+ The Schlick–**Fresnel** term rises from ~`F0` at the centre to ~1 at the grazing
162
+ rim, where the surface reflects a virtual environment (horizon ambient + a warm
163
+ key and cool fill light). A lightened **iridescent** spectral line is added along
164
+ the border. Frost adds a fast separable blur of the transmitted background.
165
+
166
+ All geometry-dependent work (normals, per-channel sample coordinates, Fresnel
167
+ weight, reflected environment) is precomputed once into a `GlassKernel`; each
168
+ frame only runs the bilinear gather (+ the box blur when frosted), so dragging
169
+ stays smooth.
@@ -0,0 +1,62 @@
1
+ """PyGlass — physically-grounded refractive glass for PyQt6.
2
+
3
+ Two layers, use whichever fits:
4
+
5
+ * **High-level** — :class:`GlassPane`: a drop-in frameless glass widget. As a
6
+ child it's an in-app modal/panel that refracts your app; parentless it's a
7
+ top-level window that refracts the live desktop. Draggable, with live
8
+ ``thickness`` / ``frost`` dials.
9
+
10
+ from pyglass import GlassPane, GlassMaterial
11
+ pane = GlassPane(parent=my_window, material=GlassMaterial(thickness=0.6, frost=0.3))
12
+ pane.show()
13
+
14
+ * **Low-level** — compose the engine yourself inside any ``paintEvent``:
15
+ :class:`GlassRenderer` (backdrop → refracted pixmap), :func:`paint_glass`
16
+ (compositing), and the :mod:`~pyglass.backdrop` providers. See
17
+ :class:`pyglass.glass.GlassPopup` for a worked example.
18
+
19
+ The look is driven by :class:`GlassMaterial`'s two dials — ``thickness`` (slab
20
+ depth/mass) and ``frost`` (surface roughness) — over the physical
21
+ :class:`GlassKernel`. :class:`GlassStyle` tunes the non-physical chrome.
22
+ """
23
+
24
+ from __future__ import annotations
25
+
26
+ __version__ = "0.2.0"
27
+
28
+ from .backdrop import Backdrop, ScreenBackdrop, WidgetBackdrop, exclude_from_capture
29
+ from .effect import GlassRenderer, GlassStyle, paint_glass
30
+ from .glass import GlassPopup
31
+ from .pane import GlassPane, ui_font
32
+ from .refract import (
33
+ GlassKernel,
34
+ GlassMaterial,
35
+ array_to_qimage,
36
+ compute_glass,
37
+ qimage_to_array,
38
+ )
39
+
40
+ __all__ = [
41
+ "__version__",
42
+ # high-level widget
43
+ "GlassPane",
44
+ "GlassPopup",
45
+ # material / physics
46
+ "GlassMaterial",
47
+ "GlassKernel",
48
+ "compute_glass",
49
+ # rendering core
50
+ "GlassRenderer",
51
+ "GlassStyle",
52
+ "paint_glass",
53
+ # backdrops
54
+ "Backdrop",
55
+ "WidgetBackdrop",
56
+ "ScreenBackdrop",
57
+ "exclude_from_capture",
58
+ # helpers
59
+ "ui_font",
60
+ "qimage_to_array",
61
+ "array_to_qimage",
62
+ ]