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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
// SPDX-FileCopyrightText: Copyright (c) 2026 Mike Li/Mikewolfli/Wei Li(mikewolfli@163.com)
// SPDX-License-Identifier: MIT
//! Windows platform backend implementation.
/// Display (monitor) enumeration, over Win32's monitor API.
/// The Win32 common file dialogs, behind
/// [`Platform::choose_path`](crate::platform::Platform::choose_path).
///
/// # Which dialog, and why "choose a directory" is a different one
///
/// `GetOpenFileNameW`/`GetSaveFileNameW` (comdlg32) are the file dialogs: the places sidebar, the
/// filter list, and a **path** answer. Folder selection is not one of their modes on every Windows
/// this crate supports — `OFN_PICKFOLDERS` is a Vista-era flag that older comdlg32 ignores — so the
/// directory case uses `SHBrowseForFolderW`, the shell's own folder browser, which has existed
/// since Windows 95 and answers with an item id list rather than a path. That is the same split
/// the macOS backend makes with `NSSavePanel`/`NSOpenPanel`, for the same reason: the platform's
/// own vocabulary differs per purpose.
///
/// # Why this is its own file
///
/// The body is `winapi` calls, and a host without an MSVC toolchain cannot compile this crate for
/// `x86_64-pc-windows-msvc` (a C dependency in the graph needs a Windows SDK). Keeping the body
/// free of crate-internal names — it depends on `winapi` and on the two types
/// `super::super::{PathPurpose, PathPickerError}` and nothing else — is what lets the same file be
/// compiled on its own for the target (see `docs/log/log-20261014-1.md`, probe P-2), so the code is
/// verified by a compiler rather than by review.
pub
/// 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