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:
2026-07-29 18:31:47 +02:00
co-authored by Claude Fable 5
parent ddd0e5cc5d
commit 35c61fee64
16 changed files with 306 additions and 226 deletions
+2 -3
View File
@@ -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
+3 -5
View File
@@ -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).
+2 -5
View File
@@ -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
View File
@@ -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]]
+8 -3
View File
@@ -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
View File
@@ -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
+31 -9
View File
@@ -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
+23 -15
View File
@@ -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),
);
}
}
+34 -30
View File
@@ -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
View File
@@ -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)
+4 -4
View File
@@ -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.
+9 -4
View File
@@ -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))
}
+13 -12
View File
@@ -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]
+27 -16
View File
@@ -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(())
}
}
+33 -28
View File
@@ -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");
+9 -2
View File
@@ -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("")