jbrowser.ui.backdrop
Generated from the source code of JBrowser 2.0.2.
One owner for a top-level window's Windows 11 look: the system material behind it and its light/dark mode.
Windows keeps that state per native window, and more than one party touches it: JBrowser, and Qt, which re-applies its own idea of light/dark to every window frame when the application palette or colour scheme changes. Earlier versions applied the state from several places, read it back, rebuilt the material when it looked wrong and changed JBrowser's whole look when Windows reported a failure. On some PCs those reactions fed each other: pale windows behind dark text, a stale rectangle after maximising, a caption that stopped dragging, a window that flashed black or white and stopped responding.
So, per window, one Backdrop:
- applies the material and the mode when they change (once for each new native window, and with the same values again when the window comes back from the taskbar), and never reads anything back from Windows;
- after anything that can reset the mode (palette or theme changes, activation, window state changes, Windows settings broadcasts), sets the mode again. Setting the same value is free and changes nothing on screen, so nothing can loop;
- never rebuilds the material, never forces a frame refresh and never restyles the application.
JBrowser also paints its own base colour under its content (Theme.backdrop_layers), so the window
stays readable whatever Windows draws behind it. When Windows isn't drawing the material at all, or draws
the wrong one, LookGuard makes that base opaque (Theme.see_through).
Backdrop#
class Backdrop(QObject)source
Backdrop(window: QWidget, kind: str='window')
Keeps window's system backdrop and light/dark mode in step with the theme.
kind is "window" (a frameless JBrowser window with a material), "popup" (a borderless
popup: Acrylic over the whole window) or "frame" (a dialog with a native title bar: only the
mode and the caption colours).
Attributes
| Name | Value |
|---|---|
CLOAK_MS |
120 |
Backdrop.schedule#
schedule() -> Nonesource
Apply soon, once, after the current event (Qt's own handling of it comes first).
Backdrop.apply#
apply(showing: bool=False) -> Nonesource
Qt overrides: eventFilter
WindowTransitions#
class WindowTransitions(QObject)source
WindowTransitions(window: QWidget, native: 'win.NativeFrame', repaint=None)
Minimise, maximise and restore without the colour warp.
Windows animates these with a snapshot of the window. On some PCs the see-through parts of that
snapshot come out in the wrong colours (pale, dark or tinted) until something repaints. So the
window paints itself opaque just before the change (Theme.hold_opaque), stays opaque while
Windows animates, then repaints normally. Commands from Windows itself (taskbar, Win+arrow keys,
double-clicking the caption) arrive as WM_SYSCOMMAND: the window takes them over, paints, and sends
them again (NativeFrame.on_transition).
Attributes
| Name | Value |
|---|---|
PAINT_MS |
40 |
HOLD_MS |
420 |
WindowTransitions.run#
run(action) -> Nonesource
Qt overrides: eventFilter
LookGuard#
class LookGuard(QObject)source
LookGuard(parent: QObject | None)
Decides whether Windows is really drawing Mica / Acrylic behind JBrowser (Theme.see_through).
When it isn't, the see-through parts of JBrowser's windows show whatever Windows draws instead: a flat grey, white or black fill that needn't match the theme. JBrowser then paints an opaque base of its own, so its windows look like the Solid material, and goes back to see-through when it can. It learns this from:
- Windows settings that turn materials off (transparency effects, energy saver, high contrast, Remote Desktop): checked every few seconds and whenever Windows broadcasts a change;
- Qt saying that the graphics driver can't give windows see-through pixels (note_qt_message);
- the screen itself. After a window appears, the theme changes, Windows changes a setting, or now and then on activation, JBrowser leaves a tiny spot at the top edge of the active window unpainted for one frame and reads what Windows composited there: the bare material. Black means see-through pixels don't work on this PC; a light material behind a dark JBrowser (or a dark one behind a light JBrowser) means Windows draws the wrong one. Two readings in a row must agree.
Attributes
| Name | Value |
|---|---|
POLL_MS |
3000 |
SETTLE_MS |
160 |
CONFIRM_MS |
450 |
LookGuard.instance#
class method instance() -> 'LookGuard'source
LookGuard.watch#
watch(window: QWidget, background: QWidget, spot: Callable[[], QPoint | None]) -> Nonesource
Probe window when it's the active window. background paints its backdrop layers (and
calls paint_probe_hole); spot() is a point in background where nothing else paints, or None
when there is none right now.
LookGuard.system_changed#
system_changed() -> Nonesource
Windows broadcast a settings, theme, power or display change (NativeFrame.on_system_change).
LookGuard.check#
check() -> Nonesource
Windows settings that turn materials off, and Qt's graphics messages.
LookGuard.probe_soon#
probe_soon(ms: int) -> Nonesource
Qt overrides: eventFilter
Functions#
note_qt_message#
note_qt_message(text: str) -> Nonesource
Called with every Qt message (app.py). Remembers one saying that the graphics driver can't give windows see-through pixels (no Direct Composition): Windows would show them black.
paint_probe_hole#
paint_probe_hole(p: QPainter, widget: QWidget) -> Nonesource
Leave LookGuard's probe spot unpainted (call last in the paintEvent that draws widget's backdrop
layers). Only for the one frame LookGuard reads back; otherwise does nothing.
look_guard#
look_guard() -> LookGuardsource
caption_hit#
caption_hit(window: QWidget, local: QPoint, max_button: QWidget | None) -> intsource
The hit-test code for a point in a frameless JBrowser window: the caption (drag), the maximise button (Snap Layouts) or ordinary client area. Never raises: an error here used to make the window procedure fall back to "client area", and the window stopped dragging.