1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
// SPDX-FileCopyrightText: Copyright (c) 2026 Mike Li/Mikewolfli/Wei Li(mikewolfli@163.com)
// SPDX-License-Identifier: MIT
//! Windows platform backend implementation.
/// Native surface for self-drawn widgets (Windows).
///
/// Compiled out for `mini`/`embedded`: those profiles have no `widget::runtime`,
/// which this module is built on.
pub
pub use crate*;
/// The toplevel `HWND` that draws the widget-registry id `id`, if this backend owns one.
///
/// # Why this translation exists, and why it is two hops
///
/// The widget registry and this backend name the same window differently: the registry keys
/// the tree by a **registry** id (the id `WidgetHandle::raw_id` reports), while the backend's
/// handle table is keyed by the **platform** id `Platform::create_window` returned. A caller
/// holding a registry id — `invalidate_surface`, and through it every repaint request — cannot
/// index the handle table with it, and doing so answered `None` for a window the backend had
/// plainly created.
///
/// The association between the two ids is recorded on the widget side, so the first hop asks
/// [`crate::widget::runtime::host_window_for`]. A widget that is **already** a host window id
/// (the painter's case: Win32 hands it the `HWND` it once passed to `create_window`) resolves
/// on the second hop without the first.
///
/// Returning `None` is the honest answer for a widget this backend draws no window for — an
/// ordinary control with no surface of its own, or an id that is not mounted at all.
///
/// # Why the fallback is guarded rather than `unwrap_or(id)`
///
/// The second hop exists for exactly one caller shape: the painter, which Win32 hands an
/// `HWND` it once passed to `create_window`. That caller re-derives the id from the handle
/// (`widget_id_by_native_handle`), so the fallback is needed — but *only* for an id the
/// backend actually minted.
///
/// It used to fall back unconditionally:
///
/// ```ignore
/// let platform_id = crate::widget::runtime::host_window_for(id).unwrap_or(id);
/// ```
///
/// The handle table is **shared** between toplevels and canvas child windows
/// (`bind_native_handle` records both), so an unassociated registry id that happened to
/// equal a live canvas's platform id resolved to *that canvas's* `HWND`. `invalidate_surface`
/// then returned `true` having invalidated a different window, and the window that needed
/// the repaint never received one — a blank window reporting success at every level, which
/// is the failure mode this whole translation exists to remove.
///
/// Both id spaces are allocated from small integers, so a collision is ordinary rather than
/// exotic. The fallback is therefore taken only when the backend can confirm the id is one
/// of its own (`state.kind_of(id)` answers for every widget `create_*` minted), and anything
/// else is reported instead of silently resolving to a stranger.
pub