chore(client): the windows-rs pin moves a month forward, onto the SDK-metadata bindings
The July 2026 windows-rs brings a reconciler keyed-child-order fix (#4728), widget validation (#4727), a DPI collision fix (#4751), icon elements (#4736), multi-window support (#4730) and scroll virtualization (#4710) — the re-render fixes the Windows client has been working around at the architecture level. All three pinned deps (windows-reactor, windows, windows-reactor-setup) move together so windows-core stays unified across the swap-chain hand-off, and pf-client-core moves with them. The bulk of the diff is #4689: windows/windows-sys now generate straight from the Windows SDK, so the `Win32_*` namespace features became one feature per SDK header (winuser, dxgi, d3d11, …), the PascalCase namespace modules became header-named modules, struct-returning COM methods take explicit out-params and return HRESULT, Win32 functions return their raw BOOL/HANDLE instead of Result, and flag constants are plain integers. Both crates' Win32 code is rewritten to that shape; behaviour is unchanged on every path. Riding along, all already stale before the bump: the README and the three Windows workflows stop claiming windows-reactor's build.rs needs CARGO_WORKSPACE_DIR (that build.rs no longer exists — staging moved to windows-reactor-setup via OUT_DIR); the README layout section stops describing modules that moved into the session binary long ago and gains the manual smoke checklist; the notices generator learns the SPDX for crates that ship license files without a `license` field, which turns windows-reactor-setup's UNKNOWN into MIT OR Apache-2.0; and the crate records its real rust-version (1.96) instead of inheriting the workspace's 1.82. Verified: cargo check/clippy/fmt clean on punktfunk-client-windows, pf-client-core and punktfunk-client-session; both bins build; --discover finds the LAN hosts; the GUI shell comes up (WinAppSDK bootstrap intact under the new reactor-setup). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -123,10 +123,9 @@ jobs:
|
||||
shell: pwsh
|
||||
run: |
|
||||
# CARGO_TARGET_DIR=C:\t dodges the MAX_PATH wall in the CMake-from-source crates (aws-lc,
|
||||
# opus) the host pulls; CARGO_WORKSPACE_DIR mirrors the client workflows. Both via GITHUB_ENV
|
||||
# (pwsh Out-File utf8 = no BOM, unlike Windows PowerShell 5.1 — keeps the first line clean).
|
||||
# opus) the host pulls; via GITHUB_ENV (pwsh Out-File utf8 = no BOM, unlike Windows
|
||||
# PowerShell 5.1 — keeps the first line clean).
|
||||
"CARGO_TARGET_DIR=C:\t" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
|
||||
"CARGO_WORKSPACE_DIR=$env:GITHUB_WORKSPACE" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
|
||||
# audiopus_sys' vendored opus declares cmake_minimum_required < 3.5, which CMake 4.x
|
||||
# refuses outright. Green runs today only survive on the cached configure output — a
|
||||
# target-dir purge (the runner's disk-cleanup task) would fail the fresh configure, as
|
||||
|
||||
@@ -92,11 +92,9 @@ jobs:
|
||||
- name: Configure + version
|
||||
shell: pwsh
|
||||
run: |
|
||||
# windows-reactor's build.rs unwraps CARGO_WORKSPACE_DIR; CARGO_TARGET_DIR (per-arch, short)
|
||||
# dodges the MAX_PATH wall in the CMake-from-source crates (see windows.yml). FFMPEG_DIR
|
||||
# selects the arch's import libs + is read by pack-msix.ps1 for the runtime DLLs. All via
|
||||
# GITHUB_ENV.
|
||||
"CARGO_WORKSPACE_DIR=$env:GITHUB_WORKSPACE" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
|
||||
# CARGO_TARGET_DIR (per-arch, short) dodges the MAX_PATH wall in the CMake-from-source
|
||||
# crates (see windows.yml). FFMPEG_DIR selects the arch's import libs + is read by
|
||||
# pack-msix.ps1 for the runtime DLLs. All via GITHUB_ENV.
|
||||
"CARGO_TARGET_DIR=${{ matrix.td }}" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
|
||||
"FFMPEG_DIR=${{ matrix.ffmpeg }}" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
|
||||
# pf-ffvk's bindgen needs Vulkan headers (arch-independent; provisioned alongside FFmpeg).
|
||||
|
||||
@@ -22,8 +22,6 @@
|
||||
# The MSVC/WinUI/FFmpeg toolchain (cargo/rustup on ASCII paths, NASM, CMake, LLVM, the x64 FFmpeg,
|
||||
# CARGO_HOME, CMAKE_POLICY_VERSION_MINIMUM, …) is baked into the runner's daemon env. Per-checkout
|
||||
# / per-arch vars are set in a step:
|
||||
# - CARGO_WORKSPACE_DIR windows-reactor's build.rs unwraps it + stages the Win App SDK
|
||||
# NuGets/winmd under it (from GITHUB_WORKSPACE).
|
||||
# - CARGO_TARGET_DIR=C:\t… the runner's host workdir is buried deep under
|
||||
# C:\Windows\System32\config\systemprofile\.cache\act\<hash>\hostexecutor\,
|
||||
# so the default target\ path blows past Windows' MAX_PATH (260) inside the
|
||||
@@ -34,8 +32,8 @@
|
||||
# - FFMPEG_DIR per-arch FFmpeg import libs (x64 vs arm64 tree).
|
||||
#
|
||||
# Steps use `shell: pwsh` (PowerShell 7) deliberately: Windows PowerShell 5.1's
|
||||
# `Out-File -Encoding utf8` prepends a UTF-8 BOM that corrupts the first GITHUB_ENV line (the
|
||||
# CARGO_WORKSPACE_DIR var silently never gets set -> reactor build.rs panics). pwsh writes no BOM.
|
||||
# `Out-File -Encoding utf8` prepends a UTF-8 BOM that corrupts the first GITHUB_ENV line (that
|
||||
# var silently never gets set). pwsh writes no BOM.
|
||||
# The runner's daemon wrapper puts C:\Program Files\PowerShell\7 on PATH so the job finds pwsh.
|
||||
name: windows
|
||||
# One pending run per workflow+ref: a newer push supersedes the queued/running one and cancels
|
||||
@@ -105,7 +103,6 @@ jobs:
|
||||
- name: Configure + toolchain versions
|
||||
shell: pwsh
|
||||
run: |
|
||||
"CARGO_WORKSPACE_DIR=$env:GITHUB_WORKSPACE" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
|
||||
# Per-arch short target root (dodges MAX_PATH; keeps the two legs from sharing target\).
|
||||
$td = if ('${{ matrix.target }}' -eq 'aarch64-pc-windows-msvc') { 'C:\t-a64' } else { 'C:\t' }
|
||||
"CARGO_TARGET_DIR=$td" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
|
||||
|
||||
Generated
+55
-43
@@ -2890,7 +2890,7 @@ dependencies = [
|
||||
"tracing",
|
||||
"ureq",
|
||||
"wasapi",
|
||||
"windows 0.62.2 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)",
|
||||
"windows 0.62.2 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3376,7 +3376,7 @@ dependencies = [
|
||||
"serde_json",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
"windows 0.62.2 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)",
|
||||
"windows 0.62.2 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)",
|
||||
"windows-reactor",
|
||||
"windows-reactor-setup",
|
||||
"winresource",
|
||||
@@ -5420,12 +5420,12 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.62.2"
|
||||
source = "git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f#a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f"
|
||||
source = "git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc#acb5a1a7441033d9312b16842af02eb0c2b403dc"
|
||||
dependencies = [
|
||||
"windows-collections 0.3.2 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)",
|
||||
"windows-core 0.62.2 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)",
|
||||
"windows-future 0.3.2 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)",
|
||||
"windows-numerics 0.3.1 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)",
|
||||
"windows-collections 0.3.2 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)",
|
||||
"windows-core 0.62.2 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)",
|
||||
"windows-future 0.3.2 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)",
|
||||
"windows-numerics 0.3.1 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)",
|
||||
"windows-reference",
|
||||
"windows-time",
|
||||
]
|
||||
@@ -5442,9 +5442,20 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "windows-collections"
|
||||
version = "0.3.2"
|
||||
source = "git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f#a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f"
|
||||
source = "git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc#acb5a1a7441033d9312b16842af02eb0c2b403dc"
|
||||
dependencies = [
|
||||
"windows-core 0.62.2 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)",
|
||||
"windows-core 0.62.2 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-composition"
|
||||
version = "0.0.0"
|
||||
source = "git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc#acb5a1a7441033d9312b16842af02eb0c2b403dc"
|
||||
dependencies = [
|
||||
"windows-collections 0.3.2 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)",
|
||||
"windows-core 0.62.2 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)",
|
||||
"windows-numerics 0.3.1 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)",
|
||||
"windows-time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5463,13 +5474,13 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.62.2"
|
||||
source = "git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f#a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f"
|
||||
source = "git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc#acb5a1a7441033d9312b16842af02eb0c2b403dc"
|
||||
dependencies = [
|
||||
"windows-implement 0.60.2 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)",
|
||||
"windows-interface 0.59.3 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)",
|
||||
"windows-link 0.2.1 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)",
|
||||
"windows-result 0.4.1 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)",
|
||||
"windows-strings 0.5.1 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)",
|
||||
"windows-implement 0.60.2 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)",
|
||||
"windows-interface 0.59.3 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)",
|
||||
"windows-link 0.2.1 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)",
|
||||
"windows-result 0.4.1 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)",
|
||||
"windows-strings 0.5.1 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5486,11 +5497,11 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "windows-future"
|
||||
version = "0.3.2"
|
||||
source = "git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f#a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f"
|
||||
source = "git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc#acb5a1a7441033d9312b16842af02eb0c2b403dc"
|
||||
dependencies = [
|
||||
"windows-core 0.62.2 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)",
|
||||
"windows-link 0.2.1 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)",
|
||||
"windows-threading 0.2.1 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)",
|
||||
"windows-core 0.62.2 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)",
|
||||
"windows-link 0.2.1 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)",
|
||||
"windows-threading 0.2.1 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5507,7 +5518,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "windows-implement"
|
||||
version = "0.60.2"
|
||||
source = "git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f#a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f"
|
||||
source = "git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc#acb5a1a7441033d9312b16842af02eb0c2b403dc"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -5528,7 +5539,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "windows-interface"
|
||||
version = "0.59.3"
|
||||
source = "git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f#a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f"
|
||||
source = "git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc#acb5a1a7441033d9312b16842af02eb0c2b403dc"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -5544,7 +5555,7 @@ checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.2.1"
|
||||
source = "git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f#a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f"
|
||||
source = "git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc#acb5a1a7441033d9312b16842af02eb0c2b403dc"
|
||||
|
||||
[[package]]
|
||||
name = "windows-numerics"
|
||||
@@ -5559,38 +5570,39 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "windows-numerics"
|
||||
version = "0.3.1"
|
||||
source = "git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f#a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f"
|
||||
source = "git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc#acb5a1a7441033d9312b16842af02eb0c2b403dc"
|
||||
dependencies = [
|
||||
"windows-core 0.62.2 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)",
|
||||
"windows-link 0.2.1 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)",
|
||||
"windows-core 0.62.2 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)",
|
||||
"windows-link 0.2.1 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-reactor"
|
||||
version = "0.0.0"
|
||||
source = "git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f#a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f"
|
||||
source = "git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc#acb5a1a7441033d9312b16842af02eb0c2b403dc"
|
||||
dependencies = [
|
||||
"rustc-hash",
|
||||
"windows-collections 0.3.2 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)",
|
||||
"windows-core 0.62.2 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)",
|
||||
"windows-future 0.3.2 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)",
|
||||
"windows-numerics 0.3.1 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)",
|
||||
"windows-collections 0.3.2 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)",
|
||||
"windows-composition",
|
||||
"windows-core 0.62.2 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)",
|
||||
"windows-future 0.3.2 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)",
|
||||
"windows-numerics 0.3.1 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)",
|
||||
"windows-reference",
|
||||
"windows-threading 0.2.1 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)",
|
||||
"windows-threading 0.2.1 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)",
|
||||
"windows-time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-reactor-setup"
|
||||
version = "0.0.0"
|
||||
source = "git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f#a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f"
|
||||
source = "git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc#acb5a1a7441033d9312b16842af02eb0c2b403dc"
|
||||
|
||||
[[package]]
|
||||
name = "windows-reference"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f#a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f"
|
||||
source = "git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc#acb5a1a7441033d9312b16842af02eb0c2b403dc"
|
||||
dependencies = [
|
||||
"windows-core 0.62.2 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)",
|
||||
"windows-core 0.62.2 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)",
|
||||
"windows-time",
|
||||
]
|
||||
|
||||
@@ -5606,9 +5618,9 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.4.1"
|
||||
source = "git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f#a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f"
|
||||
source = "git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc#acb5a1a7441033d9312b16842af02eb0c2b403dc"
|
||||
dependencies = [
|
||||
"windows-link 0.2.1 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)",
|
||||
"windows-link 0.2.1 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5634,9 +5646,9 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "windows-strings"
|
||||
version = "0.5.1"
|
||||
source = "git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f#a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f"
|
||||
source = "git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc#acb5a1a7441033d9312b16842af02eb0c2b403dc"
|
||||
dependencies = [
|
||||
"windows-link 0.2.1 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)",
|
||||
"windows-link 0.2.1 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5744,18 +5756,18 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "windows-threading"
|
||||
version = "0.2.1"
|
||||
source = "git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f#a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f"
|
||||
source = "git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc#acb5a1a7441033d9312b16842af02eb0c2b403dc"
|
||||
dependencies = [
|
||||
"windows-link 0.2.1 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)",
|
||||
"windows-link 0.2.1 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-time"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f#a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f"
|
||||
source = "git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc#acb5a1a7441033d9312b16842af02eb0c2b403dc"
|
||||
dependencies = [
|
||||
"windows-core 0.62.2 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)",
|
||||
"windows-link 0.2.1 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)",
|
||||
"windows-core 0.62.2 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)",
|
||||
"windows-link 0.2.1 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -7,7 +7,11 @@ below. Each is distributed under its own permissive license; the full license te
|
||||
follow the manifest. This file is generated by scripts/gen-third-party-notices.py
|
||||
(or `cargo about`, see about.toml) — do not edit by hand.
|
||||
|
||||
<<<<<<< HEAD
|
||||
Total third-party crates: 561
|
||||
=======
|
||||
Total third-party crates: 562
|
||||
>>>>>>> d0c7bae1 (chore(client): the windows-rs pin moves a month forward, onto the SDK-metadata bindings)
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
VENDORED THIRD-PARTY SOURCE (inside first-party crates)
|
||||
@@ -497,6 +501,7 @@ MANIFEST (crate version — SPDX license — source)
|
||||
windows 0.62.2 — MIT OR Apache-2.0 — https://github.com/microsoft/windows-rs
|
||||
windows-collections 0.3.2 — MIT OR Apache-2.0 — https://github.com/microsoft/windows-rs
|
||||
windows-collections 0.3.2 — MIT OR Apache-2.0 — https://github.com/microsoft/windows-rs
|
||||
windows-composition 0.0.0 — MIT OR Apache-2.0 — https://github.com/microsoft/windows-rs
|
||||
windows-core 0.62.2 — MIT OR Apache-2.0 — https://github.com/microsoft/windows-rs
|
||||
windows-core 0.62.2 — MIT OR Apache-2.0 — https://github.com/microsoft/windows-rs
|
||||
windows-future 0.3.2 — MIT OR Apache-2.0 — https://github.com/microsoft/windows-rs
|
||||
@@ -510,7 +515,7 @@ MANIFEST (crate version — SPDX license — source)
|
||||
windows-numerics 0.3.1 — MIT OR Apache-2.0 — https://github.com/microsoft/windows-rs
|
||||
windows-numerics 0.3.1 — MIT OR Apache-2.0 — https://github.com/microsoft/windows-rs
|
||||
windows-reactor 0.0.0 — MIT OR Apache-2.0 — https://github.com/microsoft/windows-rs
|
||||
windows-reactor-setup 0.0.0 — UNKNOWN
|
||||
windows-reactor-setup 0.0.0 — MIT OR Apache-2.0
|
||||
windows-reference 0.1.0 — MIT OR Apache-2.0 — https://github.com/microsoft/windows-rs
|
||||
windows-result 0.4.1 — MIT OR Apache-2.0 — https://github.com/microsoft/windows-rs
|
||||
windows-result 0.4.1 — MIT OR Apache-2.0 — https://github.com/microsoft/windows-rs
|
||||
@@ -15197,7 +15202,7 @@ SOFTWARE.
|
||||
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
The following license (license-apache-2.0) applies to: windows 0.62.2, windows-collections 0.3.2, windows-core 0.62.2, windows-future 0.3.2, windows-implement 0.60.2, windows-interface 0.59.3, windows-link 0.2.1, windows-numerics 0.3.1, windows-reactor 0.0.0, windows-reactor-setup 0.0.0, windows-reference 0.1.0, windows-result 0.4.1, windows-strings 0.5.1, windows-sys 0.45.0, windows-sys 0.52.0, windows-sys 0.59.0, windows-sys 0.60.2, windows-sys 0.61.2, windows-targets 0.42.2, windows-targets 0.52.6, windows-targets 0.53.5, windows-threading 0.2.1, windows-time 0.1.0, windows_aarch64_gnullvm 0.42.2, windows_aarch64_gnullvm 0.52.6, windows_aarch64_gnullvm 0.53.1, windows_aarch64_msvc 0.42.2, windows_aarch64_msvc 0.52.6, windows_aarch64_msvc 0.53.1, windows_i686_gnu 0.42.2, windows_i686_gnu 0.52.6, windows_i686_gnu 0.53.1, windows_i686_gnullvm 0.52.6, windows_i686_gnullvm 0.53.1, windows_i686_msvc 0.42.2, windows_i686_msvc 0.52.6, windows_i686_msvc 0.53.1, windows_x86_64_gnu 0.42.2, windows_x86_64_gnu 0.52.6, windows_x86_64_gnu 0.53.1, windows_x86_64_gnullvm 0.42.2, windows_x86_64_gnullvm 0.52.6, windows_x86_64_gnullvm 0.53.1, windows_x86_64_msvc 0.42.2, windows_x86_64_msvc 0.52.6, windows_x86_64_msvc 0.53.1
|
||||
The following license (license-apache-2.0) applies to: windows 0.62.2, windows-collections 0.3.2, windows-composition 0.0.0, windows-core 0.62.2, windows-future 0.3.2, windows-implement 0.60.2, windows-interface 0.59.3, windows-link 0.2.1, windows-numerics 0.3.1, windows-reactor 0.0.0, windows-reactor-setup 0.0.0, windows-reference 0.1.0, windows-result 0.4.1, windows-strings 0.5.1, windows-sys 0.45.0, windows-sys 0.52.0, windows-sys 0.59.0, windows-sys 0.60.2, windows-sys 0.61.2, windows-targets 0.42.2, windows-targets 0.52.6, windows-targets 0.53.5, windows-threading 0.2.1, windows-time 0.1.0, windows_aarch64_gnullvm 0.42.2, windows_aarch64_gnullvm 0.52.6, windows_aarch64_gnullvm 0.53.1, windows_aarch64_msvc 0.42.2, windows_aarch64_msvc 0.52.6, windows_aarch64_msvc 0.53.1, windows_i686_gnu 0.42.2, windows_i686_gnu 0.52.6, windows_i686_gnu 0.53.1, windows_i686_gnullvm 0.52.6, windows_i686_gnullvm 0.53.1, windows_i686_msvc 0.42.2, windows_i686_msvc 0.52.6, windows_i686_msvc 0.53.1, windows_x86_64_gnu 0.42.2, windows_x86_64_gnu 0.52.6, windows_x86_64_gnu 0.53.1, windows_x86_64_gnullvm 0.42.2, windows_x86_64_gnullvm 0.52.6, windows_x86_64_gnullvm 0.53.1, windows_x86_64_msvc 0.42.2, windows_x86_64_msvc 0.52.6, windows_x86_64_msvc 0.53.1
|
||||
----------------------------------------------------------------------------
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
@@ -15403,7 +15408,7 @@ Apache License
|
||||
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
The following license (license-mit) applies to: windows 0.62.2, windows-collections 0.3.2, windows-core 0.62.2, windows-future 0.3.2, windows-implement 0.60.2, windows-interface 0.59.3, windows-link 0.2.1, windows-numerics 0.3.1, windows-reactor 0.0.0, windows-reactor-setup 0.0.0, windows-reference 0.1.0, windows-result 0.4.1, windows-strings 0.5.1, windows-sys 0.45.0, windows-sys 0.52.0, windows-sys 0.59.0, windows-sys 0.60.2, windows-sys 0.61.2, windows-targets 0.42.2, windows-targets 0.52.6, windows-targets 0.53.5, windows-threading 0.2.1, windows-time 0.1.0, windows_aarch64_gnullvm 0.42.2, windows_aarch64_gnullvm 0.52.6, windows_aarch64_gnullvm 0.53.1, windows_aarch64_msvc 0.42.2, windows_aarch64_msvc 0.52.6, windows_aarch64_msvc 0.53.1, windows_i686_gnu 0.42.2, windows_i686_gnu 0.52.6, windows_i686_gnu 0.53.1, windows_i686_gnullvm 0.52.6, windows_i686_gnullvm 0.53.1, windows_i686_msvc 0.42.2, windows_i686_msvc 0.52.6, windows_i686_msvc 0.53.1, windows_x86_64_gnu 0.42.2, windows_x86_64_gnu 0.52.6, windows_x86_64_gnu 0.53.1, windows_x86_64_gnullvm 0.42.2, windows_x86_64_gnullvm 0.52.6, windows_x86_64_gnullvm 0.53.1, windows_x86_64_msvc 0.42.2, windows_x86_64_msvc 0.52.6, windows_x86_64_msvc 0.53.1
|
||||
The following license (license-mit) applies to: windows 0.62.2, windows-collections 0.3.2, windows-composition 0.0.0, windows-core 0.62.2, windows-future 0.3.2, windows-implement 0.60.2, windows-interface 0.59.3, windows-link 0.2.1, windows-numerics 0.3.1, windows-reactor 0.0.0, windows-reactor-setup 0.0.0, windows-reference 0.1.0, windows-result 0.4.1, windows-strings 0.5.1, windows-sys 0.45.0, windows-sys 0.52.0, windows-sys 0.59.0, windows-sys 0.60.2, windows-sys 0.61.2, windows-targets 0.42.2, windows-targets 0.52.6, windows-targets 0.53.5, windows-threading 0.2.1, windows-time 0.1.0, windows_aarch64_gnullvm 0.42.2, windows_aarch64_gnullvm 0.52.6, windows_aarch64_gnullvm 0.53.1, windows_aarch64_msvc 0.42.2, windows_aarch64_msvc 0.52.6, windows_aarch64_msvc 0.53.1, windows_i686_gnu 0.42.2, windows_i686_gnu 0.52.6, windows_i686_gnu 0.53.1, windows_i686_gnullvm 0.52.6, windows_i686_gnullvm 0.53.1, windows_i686_msvc 0.42.2, windows_i686_msvc 0.52.6, windows_i686_msvc 0.53.1, windows_x86_64_gnu 0.42.2, windows_x86_64_gnu 0.52.6, windows_x86_64_gnu 0.53.1, windows_x86_64_gnullvm 0.42.2, windows_x86_64_gnullvm 0.52.6, windows_x86_64_gnullvm 0.53.1, windows_x86_64_msvc 0.42.2, windows_x86_64_msvc 0.52.6, windows_x86_64_msvc 0.53.1
|
||||
----------------------------------------------------------------------------
|
||||
MIT License
|
||||
|
||||
|
||||
+33
-32
@@ -3,7 +3,9 @@ name = "punktfunk-client-windows"
|
||||
description = "Native Windows punktfunk/1 client — WinUI 3 (windows-reactor) shell, SDL3 gamepads; streaming runs in the spawned punktfunk-session binary"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
# Not workspace-inherited (1.82): windows-reactor at the pinned rev declares rust-version 1.95+
|
||||
# and edition 2024. rust-toolchain.toml pins 1.96, so this records reality rather than raising it.
|
||||
rust-version = "1.96"
|
||||
license.workspace = true
|
||||
authors.workspace = true
|
||||
repository.workspace = true
|
||||
@@ -41,40 +43,39 @@ punktfunk-core = { path = "../../crates/punktfunk-core", features = ["quic"] }
|
||||
# nothing enables it and the C++ is never compiled.
|
||||
pf-client-core = { path = "../../crates/pf-client-core", default-features = false }
|
||||
|
||||
# WinUI 3 UI via windows-reactor (a declarative React-like framework backed by WinUI). Its
|
||||
# `build.rs` downloads the Windows App SDK NuGets and stages the bootstrap DLL + resources.pri
|
||||
# next to the exe; it requires `CARGO_WORKSPACE_DIR` to be set in the build env. Unpublished
|
||||
# (version 0.0.0) and fast-moving, so pinned to a verified commit.
|
||||
windows-reactor = { git = "https://github.com/microsoft/windows-rs", rev = "a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f" }
|
||||
# Win32 / Direct3D11 / DXGI for the SwapChainPanel composition swapchain. Pulled from the SAME
|
||||
# WinUI 3 UI via windows-reactor (a declarative React-like framework backed by WinUI).
|
||||
# Unpublished (version 0.0.0) and fast-moving, so pinned to a verified commit. Pin bumped
|
||||
# 2026-07-29 (from the 2026-07-01 rev) for: reconciler keyed-child-order fix (#4728), widget
|
||||
# validation (#4727), DPI collision fix (#4751), icon elements (#4736), multi-window (#4730),
|
||||
# scroll virtualization (#4710). All three windows-rs deps here MUST share this rev, and it
|
||||
# must match pf-client-core's `windows` pin, so the workspace builds ONE windows-rs.
|
||||
windows-reactor = { git = "https://github.com/microsoft/windows-rs", rev = "acb5a1a7441033d9312b16842af02eb0c2b403dc" }
|
||||
# Win32 / DXGI for the GPU picker and the shell's window plumbing. Pulled from the SAME
|
||||
# windows-rs commit as windows-reactor so their `windows-core` unifies — the `IDXGISwapChain1`
|
||||
# we hand to `SwapChainPanelHandle::set_swap_chain` must satisfy reactor's `windows_core::Interface`.
|
||||
windows = { git = "https://github.com/microsoft/windows-rs", rev = "a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f", features = [
|
||||
"Win32_Foundation",
|
||||
"Win32_Graphics_Dxgi",
|
||||
"Win32_Graphics_Dxgi_Common",
|
||||
# Features are header-named since the in-house-metadata rework (#4689) — one feature per SDK
|
||||
# header, replacing the old `Win32_*` namespace features.
|
||||
windows = { git = "https://github.com/microsoft/windows-rs", rev = "acb5a1a7441033d9312b16842af02eb0c2b403dc", features = [
|
||||
# GetCurrentPackageFullName — the packaged-run probe guarding the explicit
|
||||
# AppUserModelID (main.rs; MSIX identity must win over the dev-run tag).
|
||||
"Win32_Storage_Packaging_Appx",
|
||||
"Win32_Graphics_Direct3D",
|
||||
"Win32_Graphics_Direct3D11",
|
||||
"Win32_Graphics_Direct3D_Fxc",
|
||||
"Win32_Graphics_Gdi",
|
||||
# IShellLinkW + IPersistFile for the "Create shortcut" writer, and COPYDATASTRUCT for the
|
||||
# link hand-off between instances (deeplink.rs).
|
||||
"Win32_System_Com",
|
||||
"Win32_System_DataExchange",
|
||||
"Win32_System_Console",
|
||||
"Win32_System_LibraryLoader",
|
||||
"Win32_System_Threading",
|
||||
"Win32_UI_HiDpi",
|
||||
"Win32_UI_Input_KeyboardAndMouse",
|
||||
# Win32 window subclassing (SetWindowSubclass/DefSubclassProc) — the stream input hooks
|
||||
# subclass the WinUI window + its content-island children to swallow WM_SETCURSOR so the
|
||||
# local cursor stays hidden while the pointer is locked (WinUI otherwise re-asserts the arrow
|
||||
# on every pointer move, defeating a one-shot ShowCursor(false)).
|
||||
"Win32_UI_Shell",
|
||||
"Win32_UI_WindowsAndMessaging",
|
||||
"appmodel",
|
||||
# CoCreateInstance/CoInitializeEx (+ objbase/objidl/wtypesbase below) for the
|
||||
# "Create shortcut" writer (deeplink.rs).
|
||||
"combaseapi",
|
||||
# SetWindowSubclass/DefSubclassProc — the deep-link WM_COPYDATA subclass hook.
|
||||
"commctrl",
|
||||
"consoleapi",
|
||||
"dxgi",
|
||||
"errhandlingapi",
|
||||
"libloaderapi",
|
||||
"objbase",
|
||||
"objidl",
|
||||
# SetCurrentProcessExplicitAppUserModelID + ShellLink/IShellLinkW.
|
||||
"shobjidl_core",
|
||||
"synchapi",
|
||||
"winerror",
|
||||
# Windowing, messages, icons — and COPYDATASTRUCT, which lives in winuser now too.
|
||||
"winuser",
|
||||
] }
|
||||
|
||||
# FFmpeg — used only to enumerate which codecs this client can decode (probe::decodable_codecs),
|
||||
@@ -98,7 +99,7 @@ tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
# to the exe — the new-model replacement for the old windows-reactor build.rs; same pinned rev.
|
||||
[target.'cfg(windows)'.build-dependencies]
|
||||
winresource = "0.1"
|
||||
windows-reactor-setup = { git = "https://github.com/microsoft/windows-rs", rev = "a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f" }
|
||||
windows-reactor-setup = { git = "https://github.com/microsoft/windows-rs", rev = "acb5a1a7441033d9312b16842af02eb0c2b403dc" }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
@@ -42,8 +42,9 @@ A stock [Moonlight](https://moonlight-stream.org/) client also works over GameSt
|
||||
## Build from source
|
||||
|
||||
Windows-only (the crate builds as a stub on other platforms so the workspace stays green). You need
|
||||
the MSVC toolchain, an `FFMPEG_DIR` FFmpeg tree, and CMake (SDL3 builds from source). windows-reactor's
|
||||
`build.rs` downloads the Windows App SDK NuGets and needs `CARGO_WORKSPACE_DIR` set.
|
||||
the MSVC toolchain, an `FFMPEG_DIR` FFmpeg tree, and CMake (SDL3 builds from source). The Windows
|
||||
App SDK runtime bootstrap is staged next to the exe by `windows-reactor-setup` from this crate's
|
||||
own `build.rs` — no extra environment needed.
|
||||
|
||||
```sh
|
||||
cargo build -p punktfunk-client-windows --target x86_64-pc-windows-msvc
|
||||
@@ -59,22 +60,43 @@ punktfunk-client --headless --speed-test --connect host[:port] # probe burst
|
||||
|
||||
## Layout
|
||||
|
||||
Decode/present/input live in the spawned `punktfunk-session` binary (`clients/session`), not here —
|
||||
this crate is the shell that discovers, pairs, and launches it.
|
||||
|
||||
```
|
||||
src/
|
||||
main.rs entry point + CLI paths (--discover · --headless · --speed-test)
|
||||
bin/punktfunk-console.rs the couch/HTPC Start-menu entry (re-execs with --console)
|
||||
app/ WinUI 3 shell (windows-reactor), one module per screen:
|
||||
mod (root/router) · hosts · connect · pair · speed · settings ·
|
||||
licenses · stream · style (shared cards/pills/monograms)
|
||||
present.rs · gpu.rs SwapChainPanel D3D11 composition swapchain; shared D3D11 device
|
||||
video.rs FFmpeg HEVC decode (D3D11VA zero-copy + software fallback)
|
||||
audio.rs WASAPI render + mic capture
|
||||
gamepad.rs SDL3 controllers + rumble/lightbar/DualSense feedback
|
||||
input.rs Win32 low-level hooks → host input (pointer lock · click-to-capture)
|
||||
session.rs session lifecycle over the NativeClient connector (+ speed probe)
|
||||
library · help · licenses · stream · style (shared cards/pills)
|
||||
deeplink.rs punktfunk:// activation, single-instance hand-off, shortcut writer
|
||||
spawn.rs punktfunk-session child process + its stdout event contract
|
||||
shell_window.rs hide/restore the shell HWND around a session
|
||||
gpu.rs DXGI adapter enumeration for the GPU picker
|
||||
trust.rs · discovery.rs persistent identity, TOFU/PIN pairing, mDNS browse
|
||||
probe.rs · wol.rs speed probe · Wake-on-LAN
|
||||
logfile.rs log tee to %LOCALAPPDATA%
|
||||
packaging/ MSIX manifest, signing, pack script
|
||||
```
|
||||
|
||||
## Manual smoke checklist
|
||||
|
||||
The windows-reactor pin is a moving target and WinUI regressions rarely show up in `cargo check` —
|
||||
walk this after a reactor bump or a change to the render/state architecture:
|
||||
|
||||
- **Hosts** — discovery populates tiles; tile hover fill; "…" menu → Forget and Rename;
|
||||
add-host modal connects; WOL wait screen cancels.
|
||||
- **Settings** — every section renders; combos still show their selection after a section
|
||||
switch AND a scope switch (the historic blank-combo reconciler bug); profile create /
|
||||
rename / delete (with confirm); colour swatches repaint; the Overridden marker appears on
|
||||
edit and clears on Reset; GPU combo lists adapters.
|
||||
- **Pair** — PIN entry pairs (the typed PIN must reach the Connect click — `use_ref` mirror path).
|
||||
- **Session** — connect → session spawns → HUD stats tick; Ctrl+Alt+Shift+Q releases the pointer;
|
||||
shell window restores on exit.
|
||||
- **Shell** — speed test completes; library grid loads; `punktfunk://` deep link routes (second
|
||||
instance hands off and exits); window icon appears; screen-entrance animations play.
|
||||
|
||||
## Related
|
||||
|
||||
- **[Documentation](https://docs.punktfunk.unom.io)** — quick start, pairing, troubleshooting
|
||||
|
||||
@@ -190,9 +190,9 @@ pub fn run(identity: (String, String), gamepad: GamepadService) -> windows_react
|
||||
/// window icon-less and exposes no handle before `App::render` blocks, so a short background
|
||||
/// poll finds our own window by its (unique) title.
|
||||
fn apply_window_icon_when_ready() {
|
||||
use windows::Win32::Foundation::{LPARAM, WPARAM};
|
||||
use windows::Win32::System::LibraryLoader::GetModuleHandleW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::{
|
||||
use windows::Win32::libloaderapi::GetModuleHandleW;
|
||||
use windows::Win32::minwindef::{LPARAM, WPARAM};
|
||||
use windows::Win32::winuser::{
|
||||
FindWindowW, GetSystemMetrics, LoadImageW, SendMessageW, ICON_BIG, ICON_SMALL, IMAGE_ICON,
|
||||
LR_DEFAULTCOLOR, SM_CXICON, SM_CXSMICON, WM_SETICON,
|
||||
};
|
||||
@@ -203,27 +203,35 @@ fn apply_window_icon_when_ready() {
|
||||
// of them dereference caller memory, and the loop gives up after 100 tries.
|
||||
.spawn(|| unsafe {
|
||||
for _ in 0..100 {
|
||||
if let Ok(hwnd) = FindWindowW(None, windows::core::w!("Punktfunk")) {
|
||||
let Ok(module) = GetModuleHandleW(None) else {
|
||||
let hwnd = FindWindowW(None, windows::core::w!("Punktfunk"));
|
||||
if !hwnd.0.is_null() {
|
||||
let module = GetModuleHandleW(None);
|
||||
if module.0.is_null() {
|
||||
return;
|
||||
};
|
||||
}
|
||||
// Small (title bar) and big (Alt-Tab) at their native metrics, both from
|
||||
// the multi-size .ico so nothing is scaled at draw time.
|
||||
// MAKEINTRESOURCE(1): the "pointer" IS the resource ordinal — not a
|
||||
// dangling pointer, and `ptr::dangling()` (an alignment-based address)
|
||||
// would name a different resource.
|
||||
#[allow(clippy::manual_dangling_ptr)]
|
||||
let ordinal_1 = windows::core::PCWSTR(1 as *const u16);
|
||||
for (which, metric) in [(ICON_SMALL, SM_CXSMICON), (ICON_BIG, SM_CXICON)] {
|
||||
let px = GetSystemMetrics(metric);
|
||||
if let Ok(icon) = LoadImageW(
|
||||
Some(module.into()),
|
||||
windows::core::PCWSTR(1 as *const u16),
|
||||
IMAGE_ICON,
|
||||
let icon = LoadImageW(
|
||||
Some(module),
|
||||
ordinal_1,
|
||||
IMAGE_ICON as u32,
|
||||
px,
|
||||
px,
|
||||
LR_DEFAULTCOLOR,
|
||||
) {
|
||||
LR_DEFAULTCOLOR as u32,
|
||||
);
|
||||
if !icon.0.is_null() {
|
||||
SendMessageW(
|
||||
hwnd,
|
||||
WM_SETICON,
|
||||
Some(WPARAM(which as usize)),
|
||||
Some(LPARAM(icon.0 as isize)),
|
||||
WM_SETICON as u32,
|
||||
WPARAM(which as usize),
|
||||
LPARAM(icon.0 as isize),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,12 +13,11 @@
|
||||
|
||||
use std::sync::atomic::{AtomicIsize, Ordering};
|
||||
use std::sync::Mutex;
|
||||
use windows::Win32::Foundation::{HWND, LPARAM, LRESULT, WPARAM};
|
||||
use windows::Win32::System::Threading::{CreateMutexW, ReleaseMutex};
|
||||
use windows::Win32::UI::Shell::{DefSubclassProc, SetWindowSubclass};
|
||||
// COPYDATASTRUCT lives with the other data-exchange types, not with the message constant.
|
||||
use windows::Win32::System::DataExchange::COPYDATASTRUCT;
|
||||
use windows::Win32::UI::WindowsAndMessaging::{FindWindowW, SendMessageW, WM_COPYDATA};
|
||||
use windows::Win32::commctrl::{DefSubclassProc, SetWindowSubclass};
|
||||
use windows::Win32::minwindef::{LPARAM, LRESULT, WPARAM};
|
||||
use windows::Win32::synchapi::{CreateMutexW, ReleaseMutex};
|
||||
use windows::Win32::windef::HWND;
|
||||
use windows::Win32::winuser::{FindWindowW, SendMessageW, COPYDATASTRUCT, WM_COPYDATA};
|
||||
|
||||
/// The single-instance mutex. Named per the design; deliberately not `Global\` — one shell per
|
||||
/// user session is the rule, and a second desktop user gets their own.
|
||||
@@ -59,19 +58,18 @@ pub(crate) fn claim_primary() -> bool {
|
||||
// SAFETY: `CreateMutexW` takes a static wide name literal and no pointer we own; the handle it
|
||||
// returns is stored in `MUTEX` and released once in `release_primary`.
|
||||
unsafe {
|
||||
let handle = match CreateMutexW(None, true, MUTEX_NAME) {
|
||||
Ok(h) => h,
|
||||
// Without the mutex we cannot tell primary from secondary; behaving as primary is
|
||||
// the safe answer — a second window is a nuisance, a dropped launch is a bug.
|
||||
Err(e) => {
|
||||
tracing::warn!(error = %e, "single instance mutex; continuing as primary");
|
||||
return true;
|
||||
}
|
||||
};
|
||||
let handle = CreateMutexW(None, true, MUTEX_NAME);
|
||||
// Without the mutex we cannot tell primary from secondary; behaving as primary is
|
||||
// the safe answer — a second window is a nuisance, a dropped launch is a bug.
|
||||
if handle.0.is_null() {
|
||||
let e = windows::Win32::errhandlingapi::GetLastError();
|
||||
tracing::warn!(error = e, "single instance mutex; continuing as primary");
|
||||
return true;
|
||||
}
|
||||
// ERROR_ALREADY_EXISTS means someone else created it first — `CreateMutexW` still
|
||||
// hands back a valid handle, so ask the OS what actually happened.
|
||||
let already = windows::Win32::Foundation::GetLastError()
|
||||
== windows::Win32::Foundation::ERROR_ALREADY_EXISTS;
|
||||
let already = windows::Win32::errhandlingapi::GetLastError()
|
||||
== windows::Win32::winerror::ERROR_ALREADY_EXISTS as u32;
|
||||
if already {
|
||||
return false;
|
||||
}
|
||||
@@ -87,7 +85,7 @@ pub(crate) fn release_primary() {
|
||||
// SAFETY: `raw` is the handle `claim_primary` stored, taken out of the atomic by `swap` so
|
||||
// this runs at most once even if two threads race here.
|
||||
unsafe {
|
||||
let _ = ReleaseMutex(windows::Win32::Foundation::HANDLE(raw as *mut _));
|
||||
let _ = ReleaseMutex(windows::Win32::winnt::HANDLE(raw as *mut _));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -104,7 +102,8 @@ pub(crate) fn forward_to_primary(url: &str) -> bool {
|
||||
// local that outlives the call because `SendMessage` is synchronous — the receiver has
|
||||
// finished with the buffer before it returns, which is precisely why this is not `Post`.
|
||||
unsafe {
|
||||
if let Ok(hwnd) = FindWindowW(None, windows::core::w!("Punktfunk")) {
|
||||
let hwnd = FindWindowW(None, windows::core::w!("Punktfunk"));
|
||||
if !hwnd.0.is_null() {
|
||||
let data = COPYDATASTRUCT {
|
||||
dwData: COPYDATA_URL,
|
||||
cbData: (wide.len() * 2) as u32,
|
||||
@@ -114,9 +113,9 @@ pub(crate) fn forward_to_primary(url: &str) -> bool {
|
||||
// copied it, which only a synchronous send guarantees.
|
||||
SendMessageW(
|
||||
hwnd,
|
||||
WM_COPYDATA,
|
||||
Some(WPARAM(0)),
|
||||
Some(LPARAM(&data as *const _ as isize)),
|
||||
WM_COPYDATA as u32,
|
||||
WPARAM(0),
|
||||
LPARAM(&data as *const _ as isize),
|
||||
);
|
||||
tracing::info!(attempt, "handed the link to the running shell");
|
||||
return true;
|
||||
@@ -138,7 +137,8 @@ pub(crate) fn install_receiver() {
|
||||
// SAFETY: `FindWindowW` takes static literals, and `SetWindowSubclass` is given
|
||||
// our own `wnd_proc` plus a plain id; the window handle is one the OS just returned.
|
||||
unsafe {
|
||||
if let Ok(hwnd) = FindWindowW(None, windows::core::w!("Punktfunk")) {
|
||||
let hwnd = FindWindowW(None, windows::core::w!("Punktfunk"));
|
||||
if !hwnd.0.is_null() {
|
||||
// Subclassing (rather than replacing the window proc) is what lets the
|
||||
// WinUI window keep behaving as itself; the same mechanism the stream
|
||||
// input hooks already use.
|
||||
@@ -162,7 +162,7 @@ unsafe extern "system" fn wnd_proc(
|
||||
_id: usize,
|
||||
_data: usize,
|
||||
) -> LRESULT {
|
||||
if msg == WM_COPYDATA {
|
||||
if msg == WM_COPYDATA as u32 {
|
||||
// SAFETY: for `WM_COPYDATA` the OS marshals the sender's `COPYDATASTRUCT` and its buffer
|
||||
// into THIS process and keeps both valid for the duration of the handler — that is the
|
||||
// guarantee this relies on, not the sender's honesty, which is why a hostile sender can at
|
||||
@@ -207,11 +207,11 @@ pub(crate) fn queue(url: String) {
|
||||
/// it valid across updates, since the install path changes and the alias doesn't.
|
||||
pub(crate) fn write_shortcut(label: &str, url: &str) -> Result<std::path::PathBuf, String> {
|
||||
use windows::core::{Interface, HSTRING};
|
||||
use windows::Win32::System::Com::{
|
||||
CoCreateInstance, CoInitializeEx, IPersistFile, CLSCTX_INPROC_SERVER,
|
||||
COINIT_APARTMENTTHREADED,
|
||||
};
|
||||
use windows::Win32::UI::Shell::{IShellLinkW, ShellLink};
|
||||
use windows::Win32::combaseapi::{CoCreateInstance, CoInitializeEx};
|
||||
use windows::Win32::objbase::COINIT_APARTMENTTHREADED;
|
||||
use windows::Win32::objidl::IPersistFile;
|
||||
use windows::Win32::shobjidl_core::{IShellLinkW, ShellLink};
|
||||
use windows::Win32::wtypesbase::CLSCTX_INPROC_SERVER;
|
||||
|
||||
let desktop = std::env::var("USERPROFILE")
|
||||
.map(|p| std::path::PathBuf::from(p).join("Desktop"))
|
||||
@@ -224,20 +224,24 @@ pub(crate) fn write_shortcut(label: &str, url: &str) -> Result<std::path::PathBu
|
||||
// The UI thread is already apartment-threaded; this is belt and braces for the case
|
||||
// where a caller ever moves this off it. An already-initialised apartment returns
|
||||
// S_FALSE, which is not an error.
|
||||
let _ = CoInitializeEx(None, COINIT_APARTMENTTHREADED);
|
||||
let _ = CoInitializeEx(None, COINIT_APARTMENTTHREADED as u32);
|
||||
let link: IShellLinkW = CoCreateInstance(&ShellLink, None, CLSCTX_INPROC_SERVER)
|
||||
.map_err(|e| format!("shell link: {e}"))?;
|
||||
link.SetPath(&HSTRING::from("punktfunk-client.exe"))
|
||||
.ok()
|
||||
.map_err(|e| format!("shortcut target: {e}"))?;
|
||||
link.SetArguments(&HSTRING::from(url))
|
||||
.ok()
|
||||
.map_err(|e| format!("shortcut argument: {e}"))?;
|
||||
link.SetDescription(&HSTRING::from(format!("Stream from {label}")))
|
||||
.ok()
|
||||
.map_err(|e| format!("shortcut description: {e}"))?;
|
||||
let persist: IPersistFile = link.cast().map_err(|e| format!("shortcut save: {e}"))?;
|
||||
// `to_string_lossy` rather than the OsStr: HSTRING is UTF-16 and the path came from an
|
||||
// env var plus our own sanitised name, so there is nothing lossy left to lose.
|
||||
persist
|
||||
.Save(&HSTRING::from(path.to_string_lossy().as_ref()), true)
|
||||
.ok()
|
||||
.map_err(|e| format!("{}: {e}", path.display()))?;
|
||||
}
|
||||
Ok(path)
|
||||
|
||||
+20
-15
@@ -6,21 +6,22 @@
|
||||
//! by the session child at connect (`PUNKTFUNK_ADAPTER` remains the session binary's env override).
|
||||
|
||||
use windows::core::Interface;
|
||||
use windows::Win32::Graphics::Dxgi::{CreateDXGIFactory1, IDXGIAdapter, IDXGIFactory1};
|
||||
use windows::Win32::dxgi::{CreateDXGIFactory1, IDXGIAdapter, IDXGIFactory1};
|
||||
|
||||
/// The adapter's human-readable description.
|
||||
fn adapter_name(adapter: &IDXGIAdapter) -> String {
|
||||
// SAFETY: a read-only COM call on the live `adapter` borrow, filling a descriptor returned by
|
||||
// value; `&IDXGIAdapter` is a reference-counted wrapper, so the borrow IS the liveness.
|
||||
// SAFETY: a read-only COM call on the live `adapter` borrow, filling a zeroed local
|
||||
// descriptor through the out-param, checked before the descriptor is read; `&IDXGIAdapter`
|
||||
// is a reference-counted wrapper, so the borrow IS the liveness.
|
||||
unsafe {
|
||||
adapter
|
||||
.GetDesc()
|
||||
.map(|d| {
|
||||
String::from_utf16_lossy(&d.Description)
|
||||
.trim_end_matches('\0')
|
||||
.to_string()
|
||||
})
|
||||
.unwrap_or_else(|_| "<unknown adapter>".into())
|
||||
let mut d: windows::Win32::dxgi::DXGI_ADAPTER_DESC = std::mem::zeroed();
|
||||
if adapter.GetDesc(&mut d).is_ok() {
|
||||
String::from_utf16_lossy(&d.Description)
|
||||
.trim_end_matches('\0')
|
||||
.to_string()
|
||||
} else {
|
||||
"<unknown adapter>".into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,10 +60,14 @@ pub fn adapter_names() -> Vec<String> {
|
||||
let mut names: Vec<String> = Vec::new();
|
||||
for a in all_adapters() {
|
||||
let desc1 = a
|
||||
.cast::<windows::Win32::Graphics::Dxgi::IDXGIAdapter1>()
|
||||
// SAFETY: a read-only COM call on the adapter just cast, filling a descriptor by value.
|
||||
.and_then(|a1| unsafe { a1.GetDesc1() })
|
||||
.ok();
|
||||
.cast::<windows::Win32::dxgi::IDXGIAdapter1>()
|
||||
.ok()
|
||||
// SAFETY: a read-only COM call on the adapter just cast, filling a zeroed local
|
||||
// descriptor through the out-param, discarded unless the call reports success.
|
||||
.and_then(|a1| unsafe {
|
||||
let mut d: windows::Win32::dxgi::DXGI_ADAPTER_DESC1 = std::mem::zeroed();
|
||||
a1.GetDesc1(&mut d).is_ok().then_some(d)
|
||||
});
|
||||
let name = adapter_name(&a);
|
||||
// Forensics for the next duplicate/oddity report — which adapters DXGI actually
|
||||
// returned, and whether the repeats share a LUID (one adapter enumerated twice)
|
||||
|
||||
@@ -55,7 +55,7 @@ fn main() {
|
||||
// parent console; it allocates nothing and dereferences no caller memory, and failure (no parent
|
||||
// console) is ignored by design.
|
||||
unsafe {
|
||||
use windows::Win32::System::Console::{AttachConsole, ATTACH_PARENT_PROCESS};
|
||||
use windows::Win32::consoleapi::{AttachConsole, ATTACH_PARENT_PROCESS};
|
||||
let _ = AttachConsole(ATTACH_PARENT_PROCESS);
|
||||
}
|
||||
set_app_user_model_id();
|
||||
@@ -172,9 +172,9 @@ fn main() {
|
||||
/// processes are left alone. Must run before any window exists.
|
||||
#[cfg(windows)]
|
||||
fn set_app_user_model_id() {
|
||||
use windows::Win32::Foundation::APPMODEL_ERROR_NO_PACKAGE;
|
||||
use windows::Win32::Storage::Packaging::Appx::GetCurrentPackageFullName;
|
||||
use windows::Win32::UI::Shell::SetCurrentProcessExplicitAppUserModelID;
|
||||
use windows::Win32::appmodel::GetCurrentPackageFullName;
|
||||
use windows::Win32::shobjidl_core::SetCurrentProcessExplicitAppUserModelID;
|
||||
use windows::Win32::winerror::APPMODEL_ERROR_NO_PACKAGE;
|
||||
// SAFETY: `GetCurrentPackageFullName` is called with `len = 0` and no buffer, which is the
|
||||
// documented identity PROBE — it writes nothing and only reports whether this process is
|
||||
// packaged; `SetCurrentProcessExplicitAppUserModelID` takes a static wide literal.
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
//! `stream::window_dpi`.
|
||||
|
||||
use std::sync::atomic::{AtomicIsize, Ordering};
|
||||
use windows::Win32::Foundation::{HWND, RECT};
|
||||
use windows::Win32::UI::WindowsAndMessaging::{
|
||||
use windows::Win32::windef::{HWND, RECT};
|
||||
use windows::Win32::winuser::{
|
||||
FindWindowW, GetWindowRect, IsWindow, SetForegroundWindow, ShowWindow, SW_HIDE, SW_SHOW,
|
||||
};
|
||||
|
||||
@@ -29,7 +29,10 @@ fn shell_hwnd() -> Option<HWND> {
|
||||
return Some(h);
|
||||
}
|
||||
}
|
||||
let h = FindWindowW(None, windows::core::w!("Punktfunk")).ok()?;
|
||||
let h = FindWindowW(None, windows::core::w!("Punktfunk"));
|
||||
if h.0.is_null() {
|
||||
return None;
|
||||
}
|
||||
SHELL_HWND.store(h.0 as isize, Ordering::Relaxed);
|
||||
Some(h)
|
||||
}
|
||||
@@ -68,6 +71,8 @@ pub(crate) fn position() -> Option<(i32, i32)> {
|
||||
let h = shell_hwnd()?;
|
||||
let mut r = RECT::default();
|
||||
// SAFETY: `h` is the validated shell window handle and `r` is a live local the call fills.
|
||||
unsafe { GetWindowRect(h, &mut r).ok()? };
|
||||
if !unsafe { GetWindowRect(h, &mut r) }.as_bool() {
|
||||
return None;
|
||||
}
|
||||
Some((r.left, r.top))
|
||||
}
|
||||
|
||||
@@ -58,19 +58,20 @@ sdl3 = { version = "0.18", features = ["hidapi", "build-from-source"] }
|
||||
# D3D11VA decode (video_d3d11.rs): device/adapter selection, DXVA probes, and the shared
|
||||
# NT-handle hand-off ring. Same pinned rev as clients/windows so the workspace builds ONE
|
||||
# windows-rs.
|
||||
windows = { git = "https://github.com/microsoft/windows-rs", rev = "a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f", features = [
|
||||
"Win32_Foundation",
|
||||
"Win32_Graphics_Direct3D",
|
||||
"Win32_Graphics_Direct3D11",
|
||||
"Win32_Graphics_Dxgi",
|
||||
"Win32_Graphics_Dxgi_Common",
|
||||
# IDXGIResource1::CreateSharedHandle takes an optional SECURITY_ATTRIBUTES — the
|
||||
# method itself is feature-gated behind this.
|
||||
"Win32_Security",
|
||||
windows = { git = "https://github.com/microsoft/windows-rs", rev = "acb5a1a7441033d9312b16842af02eb0c2b403dc", features = [
|
||||
# Features are header-named since windows-rs generates from the SDK headers directly
|
||||
# (#4689) — one feature per header, replacing the old `Win32_*` namespace features.
|
||||
"d3d11",
|
||||
"d3dcommon",
|
||||
"dxgi",
|
||||
"handleapi",
|
||||
# IDXGIResource1::CreateSharedHandle takes an optional SECURITY_ATTRIBUTES.
|
||||
"minwinbase",
|
||||
# The GlobalAlloc block the clipboard takes ownership of (clipboard.rs).
|
||||
"winbase",
|
||||
# The OS-clipboard bridge (clipboard.rs): Open/Get/SetClipboardData + the sequence
|
||||
# number, and the GlobalAlloc block the clipboard takes ownership of.
|
||||
"Win32_System_DataExchange",
|
||||
"Win32_System_Memory",
|
||||
# number — all in winuser now.
|
||||
"winuser",
|
||||
] }
|
||||
|
||||
[features]
|
||||
|
||||
@@ -278,14 +278,14 @@ mod os {
|
||||
use super::{MIME_PNG, MIME_TEXT};
|
||||
use anyhow::{anyhow, bail, Result};
|
||||
use windows::core::PCWSTR;
|
||||
use windows::Win32::Foundation::{HANDLE, HGLOBAL};
|
||||
use windows::Win32::System::DataExchange::{
|
||||
use windows::Win32::minwindef::HGLOBAL;
|
||||
use windows::Win32::winbase::{
|
||||
GlobalAlloc, GlobalLock, GlobalSize, GlobalUnlock, GMEM_MOVEABLE,
|
||||
};
|
||||
use windows::Win32::winuser::{
|
||||
CloseClipboard, EmptyClipboard, GetClipboardData, GetClipboardSequenceNumber,
|
||||
IsClipboardFormatAvailable, OpenClipboard, RegisterClipboardFormatW, SetClipboardData,
|
||||
};
|
||||
use windows::Win32::System::Memory::{
|
||||
GlobalAlloc, GlobalLock, GlobalSize, GlobalUnlock, GMEM_MOVEABLE,
|
||||
};
|
||||
|
||||
const CF_UNICODETEXT: u32 = 13;
|
||||
|
||||
@@ -307,7 +307,7 @@ mod os {
|
||||
// A retry loop: another app can hold the clipboard for a moment.
|
||||
for _ in 0..10 {
|
||||
// SAFETY: takes no pointer; `None` is the documented "associate with no window" argument.
|
||||
if unsafe { OpenClipboard(None) }.is_ok() {
|
||||
if unsafe { OpenClipboard(None) }.as_bool() {
|
||||
return Ok(Clip);
|
||||
}
|
||||
std::thread::sleep(std::time::Duration::from_millis(10));
|
||||
@@ -331,18 +331,18 @@ mod os {
|
||||
pub fn is_concealed() -> bool {
|
||||
let fmt = registered("ExcludeClipboardContentFromMonitorProcessing");
|
||||
// SAFETY: a scalar format id in, a status out; reads nothing through a pointer.
|
||||
unsafe { IsClipboardFormatAvailable(fmt) }.is_ok()
|
||||
unsafe { IsClipboardFormatAvailable(fmt) }.as_bool()
|
||||
}
|
||||
|
||||
/// The wire kinds the current clipboard can supply, with size hints where they're free.
|
||||
pub fn available_kinds() -> Vec<(&'static str, u64)> {
|
||||
let mut out = Vec::new();
|
||||
// SAFETY: as above — a scalar format id, status out.
|
||||
if unsafe { IsClipboardFormatAvailable(CF_UNICODETEXT) }.is_ok() {
|
||||
if unsafe { IsClipboardFormatAvailable(CF_UNICODETEXT) }.as_bool() {
|
||||
out.push((MIME_TEXT, 0));
|
||||
}
|
||||
// SAFETY: as above — a scalar format id, status out.
|
||||
if unsafe { IsClipboardFormatAvailable(png_format()) }.is_ok() {
|
||||
if unsafe { IsClipboardFormatAvailable(png_format()) }.as_bool() {
|
||||
out.push((MIME_PNG, 0));
|
||||
}
|
||||
out
|
||||
@@ -354,8 +354,10 @@ mod os {
|
||||
match mime {
|
||||
MIME_TEXT => {
|
||||
// SAFETY: the clipboard is open (the `Clip` guard); the handle returned is BORROWED from the clipboard and stays valid while it is open, so it is never freed here.
|
||||
let h = unsafe { GetClipboardData(CF_UNICODETEXT) }?;
|
||||
let g = HGLOBAL(h.0);
|
||||
let g: HGLOBAL = unsafe { GetClipboardData(CF_UNICODETEXT) };
|
||||
if g.0.is_null() {
|
||||
bail!("clipboard text unavailable");
|
||||
}
|
||||
// SAFETY: `g` is that borrowed clipboard handle; `GlobalLock` yields a pointer valid until the matching `GlobalUnlock` below.
|
||||
let p = unsafe { GlobalLock(g) } as *const u16;
|
||||
if p.is_null() {
|
||||
@@ -378,8 +380,10 @@ mod os {
|
||||
}
|
||||
MIME_PNG => {
|
||||
// SAFETY: as the text path — the handle is borrowed from the open clipboard, never freed here.
|
||||
let h = unsafe { GetClipboardData(png_format()) }?;
|
||||
let g = HGLOBAL(h.0);
|
||||
let g: HGLOBAL = unsafe { GetClipboardData(png_format()) };
|
||||
if g.0.is_null() {
|
||||
bail!("clipboard png unavailable");
|
||||
}
|
||||
// SAFETY: `g` is that borrowed handle; the pointer is valid until the matching unlock.
|
||||
let p = unsafe { GlobalLock(g) } as *const u8;
|
||||
if p.is_null() {
|
||||
@@ -411,10 +415,15 @@ mod os {
|
||||
};
|
||||
let _clip = Clip::open()?;
|
||||
// SAFETY: no arguments; the clipboard is open and owned by this thread via the `Clip` guard.
|
||||
unsafe { EmptyClipboard() }?;
|
||||
if !unsafe { EmptyClipboard() }.as_bool() {
|
||||
bail!("clipboard clear failed");
|
||||
}
|
||||
// The clipboard OWNS this block once SetClipboardData succeeds — do not free it.
|
||||
// SAFETY: a size in, an owned moveable handle out — ownership passes to the clipboard at `SetClipboardData` below.
|
||||
let g = unsafe { GlobalAlloc(GMEM_MOVEABLE, payload.len()) }?;
|
||||
let g = unsafe { GlobalAlloc(GMEM_MOVEABLE as u32, payload.len()) };
|
||||
if g.0.is_null() {
|
||||
bail!("clipboard alloc failed");
|
||||
}
|
||||
// SAFETY: `g` is the handle just allocated; the pointer is valid until the matching unlock.
|
||||
let p = unsafe { GlobalLock(g) } as *mut u8;
|
||||
if p.is_null() {
|
||||
@@ -425,7 +434,9 @@ mod os {
|
||||
// SAFETY: releases the lock taken above, before the handle is handed to the clipboard.
|
||||
let _ = unsafe { GlobalUnlock(g) };
|
||||
// SAFETY: ownership of `g` transfers to the clipboard here, which is why nothing frees it afterwards.
|
||||
unsafe { SetClipboardData(fmt, Some(HANDLE(g.0))) }?;
|
||||
if unsafe { SetClipboardData(fmt, Some(g)) }.0.is_null() {
|
||||
bail!("clipboard set failed");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,9 +43,7 @@ use ffmpeg_next as ffmpeg;
|
||||
use std::ffi::c_void;
|
||||
use std::ptr;
|
||||
use windows::core::{Interface, GUID};
|
||||
use windows::Win32::Foundation::{HANDLE, RECT};
|
||||
use windows::Win32::Graphics::Direct3D::{D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_11_1};
|
||||
use windows::Win32::Graphics::Direct3D11::{
|
||||
use windows::Win32::d3d11::{
|
||||
D3D11CreateDevice, ID3D11Device, ID3D11DeviceContext, ID3D11Multithread, ID3D11Texture2D,
|
||||
ID3D11VideoContext1, ID3D11VideoDevice, ID3D11VideoProcessor, ID3D11VideoProcessorEnumerator,
|
||||
ID3D11VideoProcessorOutputView, D3D11_BIND_RENDER_TARGET, D3D11_BIND_SHADER_RESOURCE,
|
||||
@@ -57,19 +55,20 @@ use windows::Win32::Graphics::Direct3D11::{
|
||||
D3D11_VIDEO_USAGE_PLAYBACK_NORMAL, D3D11_VPIV_DIMENSION_TEXTURE2D,
|
||||
D3D11_VPOV_DIMENSION_TEXTURE2D,
|
||||
};
|
||||
use windows::Win32::Graphics::Dxgi::Common::{
|
||||
DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020, DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709,
|
||||
DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P2020, DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P601,
|
||||
DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P709, DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_LEFT_P2020,
|
||||
DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P2020, DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P601,
|
||||
DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709, DXGI_FORMAT, DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
DXGI_FORMAT_NV12, DXGI_FORMAT_P010, DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_RATIONAL,
|
||||
DXGI_SAMPLE_DESC,
|
||||
};
|
||||
use windows::Win32::Graphics::Dxgi::{
|
||||
use windows::Win32::d3dcommon::{D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_11_1};
|
||||
use windows::Win32::dxgi::{
|
||||
CreateDXGIFactory1, IDXGIAdapter1, IDXGIFactory1, IDXGIKeyedMutex, IDXGIResource1,
|
||||
DXGI_ADAPTER_FLAG_SOFTWARE, DXGI_SHARED_RESOURCE_READ, DXGI_SHARED_RESOURCE_WRITE,
|
||||
DXGI_ADAPTER_DESC1, DXGI_ADAPTER_FLAG_SOFTWARE, DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020,
|
||||
DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709, DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P2020,
|
||||
DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P601, DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P709,
|
||||
DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_LEFT_P2020, DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P2020,
|
||||
DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P601, DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709,
|
||||
DXGI_FORMAT, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_NV12, DXGI_FORMAT_P010,
|
||||
DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_RATIONAL, DXGI_SAMPLE_DESC, DXGI_SHARED_RESOURCE_READ,
|
||||
DXGI_SHARED_RESOURCE_WRITE,
|
||||
};
|
||||
use windows::Win32::windef::RECT;
|
||||
use windows::Win32::winnt::HANDLE;
|
||||
|
||||
/// Ring of shareable hand-off textures. Bounds how many decoded-but-unpresented frames can
|
||||
/// exist without a slot being rewritten under an in-flight older frame: the pump's decoded
|
||||
@@ -298,12 +297,14 @@ fn create_device(luid: Option<[u8; 8]>) -> Result<(ID3D11Device, ID3D11DeviceCon
|
||||
let Ok(adapter) = (unsafe { factory.EnumAdapters1(i) }) else {
|
||||
break;
|
||||
};
|
||||
// SAFETY: a COM call on the adapter just enumerated, filling a descriptor returned by
|
||||
// value.
|
||||
let Ok(desc) = (unsafe { adapter.GetDesc1() }) else {
|
||||
// SAFETY: `DXGI_ADAPTER_DESC1` is plain-old-data, so all-zeroes is a valid value.
|
||||
let mut desc: DXGI_ADAPTER_DESC1 = unsafe { std::mem::zeroed() };
|
||||
// SAFETY: a COM call on the adapter just enumerated, filling the zeroed local descriptor
|
||||
// through the out-param; checked before the descriptor is read.
|
||||
if unsafe { adapter.GetDesc1(&mut desc) }.is_err() {
|
||||
continue;
|
||||
};
|
||||
if desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE.0 as u32 != 0 {
|
||||
}
|
||||
if desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE as u32 != 0 {
|
||||
continue; // WARP can't hardware-decode; software decode covers that box anyway
|
||||
}
|
||||
if fallback.is_none() {
|
||||
@@ -334,16 +335,17 @@ fn create_device(luid: Option<[u8; 8]>) -> Result<(ID3D11Device, ID3D11DeviceCon
|
||||
unsafe {
|
||||
D3D11CreateDevice(
|
||||
&adapter,
|
||||
windows::Win32::Graphics::Direct3D::D3D_DRIVER_TYPE_UNKNOWN,
|
||||
None,
|
||||
D3D11_CREATE_DEVICE_VIDEO_SUPPORT | D3D11_CREATE_DEVICE_BGRA_SUPPORT,
|
||||
windows::Win32::d3dcommon::D3D_DRIVER_TYPE_UNKNOWN,
|
||||
windows::Win32::minwindef::HINSTANCE(std::ptr::null_mut()),
|
||||
(D3D11_CREATE_DEVICE_VIDEO_SUPPORT | D3D11_CREATE_DEVICE_BGRA_SUPPORT) as u32,
|
||||
Some(&[D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0]),
|
||||
D3D11_SDK_VERSION,
|
||||
D3D11_SDK_VERSION as u32,
|
||||
Some(&mut device),
|
||||
None,
|
||||
Some(&mut context),
|
||||
)
|
||||
}
|
||||
.ok()
|
||||
.context("D3D11CreateDevice")?;
|
||||
let device = device.ok_or_else(|| anyhow!("D3D11CreateDevice returned no device"))?;
|
||||
let context = context.ok_or_else(|| anyhow!("D3D11CreateDevice returned no context"))?;
|
||||
@@ -376,7 +378,7 @@ impl Drop for Slot {
|
||||
// SAFETY: `self.handle` is the shared-texture NT handle this slot owns; `Drop` runs once,
|
||||
// so it is closed exactly once and never used after.
|
||||
unsafe {
|
||||
let _ = windows::Win32::Foundation::CloseHandle(self.handle);
|
||||
let _ = windows::Win32::handleapi::CloseHandle(self.handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -451,10 +453,10 @@ impl SharedRing {
|
||||
},
|
||||
Usage: D3D11_USAGE_DEFAULT,
|
||||
// RENDER_TARGET: the video processor's output view renders into it.
|
||||
BindFlags: (D3D11_BIND_SHADER_RESOURCE.0 | D3D11_BIND_RENDER_TARGET.0) as u32,
|
||||
BindFlags: (D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET) as u32,
|
||||
CPUAccessFlags: 0,
|
||||
MiscFlags: (D3D11_RESOURCE_MISC_SHARED_NTHANDLE.0
|
||||
| D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX.0) as u32,
|
||||
MiscFlags: (D3D11_RESOURCE_MISC_SHARED_NTHANDLE | D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX)
|
||||
as u32,
|
||||
};
|
||||
let mut slots = Vec::with_capacity(RING_SLOTS);
|
||||
for _ in 0..RING_SLOTS {
|
||||
@@ -462,6 +464,7 @@ impl SharedRing {
|
||||
// SAFETY: a `?`-checked `CreateTexture2D` on the live device, over a fully-initialized
|
||||
// stack descriptor and a live `Option` out-param.
|
||||
unsafe { device.CreateTexture2D(&desc, None, Some(&mut tex)) }
|
||||
.ok()
|
||||
.context("create shared hand-off texture")?;
|
||||
let tex: ID3D11Texture2D = tex.expect("CreateTexture2D succeeded");
|
||||
let mutex: IDXGIKeyedMutex =
|
||||
@@ -473,7 +476,7 @@ impl SharedRing {
|
||||
let handle = unsafe {
|
||||
resource.CreateSharedHandle(
|
||||
None,
|
||||
(DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE).0,
|
||||
DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE as u32,
|
||||
None,
|
||||
)
|
||||
}
|
||||
@@ -494,6 +497,7 @@ impl SharedRing {
|
||||
Some(&mut out_view),
|
||||
)
|
||||
}
|
||||
.ok()
|
||||
.context("CreateVideoProcessorOutputView")?;
|
||||
let out_view = out_view.expect("output view created");
|
||||
slots.push(Slot {
|
||||
@@ -735,6 +739,7 @@ impl D3d11vaDecoder {
|
||||
let mut in_view = None;
|
||||
video_device
|
||||
.CreateVideoProcessorInputView(&src, &ring.enumerator, &iv_desc, Some(&mut in_view))
|
||||
.ok()
|
||||
.context("CreateVideoProcessorInputView")?;
|
||||
let in_view = in_view.expect("input view created");
|
||||
|
||||
|
||||
@@ -45,6 +45,13 @@ def find_license_files(pkg_dir):
|
||||
return out
|
||||
|
||||
|
||||
# Crates that ship license-mit/license-apache-2.0 files but omit the `license` field in
|
||||
# their Cargo.toml (publish = false upstream), so `cargo metadata` reports no SPDX for them.
|
||||
LICENSE_OVERRIDES = {
|
||||
"windows-reactor-setup": "MIT OR Apache-2.0",
|
||||
}
|
||||
|
||||
|
||||
# Third-party source trees VENDORED inside first-party workspace crates — the
|
||||
# workspace-member skip in main() hides them from `cargo metadata`, so they are listed
|
||||
# here explicitly: (label, license file relative to the repo root, source URL).
|
||||
@@ -146,7 +153,7 @@ def main():
|
||||
w("MANIFEST (crate version — SPDX license — source)")
|
||||
w("-" * 76)
|
||||
for p in pkgs:
|
||||
lic = p.get("license") or (("file: " + p["license_file"]) if p.get("license_file") else "UNKNOWN")
|
||||
lic = p.get("license") or LICENSE_OVERRIDES.get(p["name"]) or (("file: " + p["license_file"]) if p.get("license_file") else "UNKNOWN")
|
||||
repo = p.get("repository") or ""
|
||||
w(f' {p["name"]} {p["version"]} — {lic}' + (f' — {repo}' if repo else ""))
|
||||
w("")
|
||||
@@ -156,7 +163,7 @@ def main():
|
||||
w("Crates whose package did not embed a license file (SPDX + source only)")
|
||||
w("-" * 76)
|
||||
for p in no_text:
|
||||
lic = p.get("license") or "UNKNOWN"
|
||||
lic = p.get("license") or LICENSE_OVERRIDES.get(p["name"]) or "UNKNOWN"
|
||||
repo = p.get("repository") or ""
|
||||
w(f' {p["name"]} {p["version"]} — {lic}' + (f' — {repo}' if repo else ""))
|
||||
w("")
|
||||
|
||||
Reference in New Issue
Block a user