Skip to content

feat: 重构新版VDD模式#530

Merged
Yundi339 merged 13 commits intomasterfrom
fix_vddcheckcheck
Mar 16, 2026
Merged

feat: 重构新版VDD模式#530
Yundi339 merged 13 commits intomasterfrom
fix_vddcheckcheck

Conversation

@Yundi339
Copy link
Copy Markdown
Collaborator

@Yundi339 Yundi339 commented Mar 15, 2026

后端 C++(已完成)

文件 变更内容
src/display_device/parsed_config.h device_prep_e 枚举新增 ensure_secondary(4);新增 to_vdd_prep() / to_physical_device_prep()
src/display_device/parsed_config.cpp device_prep_from_view 支持新值;make_parsed_config 统一映射;移除 custom_vdd_screen_mode
src/config.h 移除 video_t::vdd_prep 字段
src/config.cpp 移除 vdd_prep 默认值和解析
src/display_device/session.h 无额外变更
src/display_device/session.cpp restore_state_impl 直接销毁 VDD 并恢复拓扑;configure_display 保持 VDD 存在时的 client_id 检查和 pending_restore 处理;析构函数使用 destroy_vdd_monitor_nolog() 兜底清理
src/display_device/vdd_utils.h 新增 destroy_vdd_monitor_nolog() 声明
src/display_device/vdd_utils.cpp 新增 destroy_vdd_monitor_nolog() 实现(shutdown-safe,纯 Win32 API)
src/rtsp.h 移除 custom_vdd_screen_mode 字段
src/nvhttp.cpp 移除 customVddScreenMode 解析和环境变量
src/process.cpp 移除 SUNSHINE_CLIENT_CUSTOM_VDD_SCREEN_MODE 环境变量

前端(已完成)

文件 变更内容
DisplayDeviceOptions.vue 统一 <select> 5 选项,移除 VDD/物理分支
SetupWizard.vue 统一 5 卡片,删除 vddPrep,统一保存
useConfig.js 删除 vdd_prep 默认值
20 个 locale JSON 删除 vdd_prep_*,新增 ensure_secondary,统一文案

关键设计决策

Q1:为什么不区分 VDD/物理模式的选项?

用户不需要理解 VDD 是什么。"主屏串流"在物理模式下是"设该显示器为主屏",在 VDD 模式下是"VDD 作为主屏 + 物理扩展",语义一致。后端自动处理差异。

Q2:为什么新增 ensure_secondary 而不是复用 ensure_active

ensure_active 的原始语义是"仅激活,不修改拓扑"。在 VDD 模式下等效于 no_operation
ensure_secondary 的语义是"副屏串流",在 VDD 模式下映射到 vdd_as_secondary(物理主屏 + VDD 副屏)。
两者在 VDD 模式下行为不同,不能合并。

Q3:vdd_prep 需要迁移吗?

不需要。vdd_prep 尚未正式上线发布,无线上用户配置需要迁移。直接废弃即可。

Q4:custom_screen_mode 客户端 override 如何支持?

custom_screen_mode 扩展支持新增的整数值(4 对应 ensure_secondary)。
custom_vdd_screen_mode 直接移除(未上线,无需兼容)。

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors the Windows “VDD mode” flow by unifying display preparation options (VDD + physical) under display_device_prep, adding a new ensure_secondary mode, and introducing a grace-period mechanism to keep VDD alive briefly for same-client reuse. It also updates the web UI + translations accordingly and adds/updates bundled Windows VDD driver assets.

Changes:

  • Unify VDD/physical display preparation into display_device_prep (remove vdd_prep and custom_vdd_screen_mode plumbing).
  • Add VDD deferred-restore (“grace period”) logic and mapping helpers between unified prep and internal VDD/physical behaviors.
  • Update web UI (Setup Wizard + Display Device Options) and i18n strings; add driver catalog/INF assets.

Reviewed changes

Copilot reviewed 32 out of 36 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
src_assets/windows/misc/vdd/driver/zakovdd.cat Adds driver catalog asset for ZakoVDD package.
src_assets/windows/misc/vdd/driver/ZakoVDD.inf Adds driver INF describing UMDF display adapter install.
src_assets/common/assets/web/public/assets/locale/zh_TW.json Update display prep strings; remove legacy VDD layout strings.
src_assets/common/assets/web/public/assets/locale/zh.json Update display prep strings and VDD reuse description; remove legacy VDD layout strings.
src_assets/common/assets/web/public/assets/locale/uk.json Update display prep strings; remove legacy VDD layout strings.
src_assets/common/assets/web/public/assets/locale/tr.json Update display prep strings; remove legacy VDD layout strings.
src_assets/common/assets/web/public/assets/locale/sv.json Update display prep strings; remove legacy VDD layout strings.
src_assets/common/assets/web/public/assets/locale/ru.json Update display prep strings; remove legacy VDD layout strings.
src_assets/common/assets/web/public/assets/locale/pt_BR.json Update display prep strings; remove legacy VDD layout strings.
src_assets/common/assets/web/public/assets/locale/pt.json Update display prep strings; remove legacy VDD layout strings.
src_assets/common/assets/web/public/assets/locale/pl.json Update display prep strings; remove legacy VDD layout strings.
src_assets/common/assets/web/public/assets/locale/ko.json Update display prep strings; remove legacy VDD layout strings.
src_assets/common/assets/web/public/assets/locale/ja.json Update display prep strings; remove legacy VDD layout strings.
src_assets/common/assets/web/public/assets/locale/it.json Update display prep strings; remove legacy VDD layout strings.
src_assets/common/assets/web/public/assets/locale/fr.json Update display prep strings; remove legacy VDD layout strings.
src_assets/common/assets/web/public/assets/locale/es.json Update display prep strings; remove legacy VDD layout strings.
src_assets/common/assets/web/public/assets/locale/en_US.json Update display prep strings; remove legacy VDD layout strings.
src_assets/common/assets/web/public/assets/locale/en_GB.json Update display prep strings; remove legacy VDD layout strings.
src_assets/common/assets/web/public/assets/locale/en.json Update display prep strings; remove legacy VDD layout strings.
src_assets/common/assets/web/public/assets/locale/de.json Update display prep strings; remove legacy VDD layout strings.
src_assets/common/assets/web/public/assets/locale/cs.json Update display prep strings; remove legacy VDD layout strings.
src_assets/common/assets/web/public/assets/locale/bg.json Update display prep strings; remove legacy VDD layout strings.
src_assets/common/assets/web/configs/tabs/audiovideo/DisplayDeviceOptions.vue Remove VDD-specific UI split; add unified prep + ensure_secondary and dynamic descriptions.
src_assets/common/assets/web/composables/useConfig.js Remove default vdd_prep from web config defaults.
src_assets/common/assets/web/components/SetupWizard.vue Reorder steps and unify display prep selection UI (add ensure_secondary).
src/rtsp.h Remove custom_vdd_screen_mode from launch session struct.
src/process.cpp Remove SUNSHINE_CLIENT_CUSTOM_VDD_SCREEN_MODE env propagation.
src/nvhttp.cpp Remove parsing/export of customVddScreenMode and related env.
src/display_device/session.h Add deferred restore state and new execute_deferred_restore() declaration.
src/display_device/session.cpp Implement grace-period deferred restore + unified prep mapping in restore flow; add shutdown VDD cleanup.
src/display_device/parsed_config.h Add ensure_secondary and mapping helpers declarations.
src/display_device/parsed_config.cpp Implement unified prep → VDD/physical mapping; remove vdd_prep config usage.
src/config.h Remove vdd_prep from video config struct.
src/config.cpp Remove vdd_prep default + parsing from config loader.
.gitignore Remove _dev_notes/ ignore entry.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment thread src/display_device/session.cpp Outdated
Comment on lines +135 to +142
// 兜底:退出时如果 VDD 仍存在且 vdd_keep_enabled=false,直接销毁
// 不调用完整的 restore_state(),因为析构时 boost::log/timer 可能已被销毁
// 仅执行 VDD 销毁(写管道命令,不依赖日志和定时器)
if (!config::video.vdd_keep_enabled) {
auto vdd_id = display_device::find_device_by_friendlyname(ZAKO_NAME);
if (!vdd_id.empty()) {
vdd_utils::destroy_vdd_monitor();
}
Comment on lines 54 to 58
<div
id="panelsStayOpen-collapseOne"
class="accordion-collapse collapse"
class="accordion-collapse collapse show"
aria-labelledby="panelsStayOpen-headingOne"
>
Comment thread src/nvhttp.cpp
@@ -400,7 +400,6 @@ namespace nvhttp {
launch_session->enable_hdr = util::from_view(get_arg(args, "hdrMode", "0"));
launch_session->use_vdd = util::from_view(get_arg(args, "useVdd", "0"));
launch_session->custom_screen_mode = util::from_view(get_arg(args, "customScreenMode", "-1"));
Comment thread src/display_device/session.cpp Outdated
Comment on lines +339 to +341
if (vdd_already_exists) {
execute_deferred_restore(deferred_restore_reason_);
}
Comment thread src/display_device/session.cpp Outdated
Comment on lines +702 to +716
if (!vdd_id.empty() && !is_keep_enabled && is_vdd_mode && has_persistent) {
BOOST_LOG(info) << "VDD 延迟恢复:启动 grace period,等待可能的同客户端新串流复用 VDD";
deferred_restore_ = true;
deferred_restore_reason_ = reason;
deferred_client_id_ = current_vdd_client_id;

timer->setup_timer([this]() {
// Grace period 到期,没有新的 configure_display 到来,执行真正的 restore
BOOST_LOG(info) << "VDD grace period 到期,执行延迟恢复";
deferred_restore_ = false;
deferred_client_id_.clear();
execute_deferred_restore(deferred_restore_reason_);
return true; // 一次性执行,不重试
});
return;
Comment thread src/config.cpp
@@ -1195,7 +1194,6 @@ namespace config {
}
#endif
Comment thread src/process.cpp
@@ -188,7 +188,6 @@ namespace proc {
_env["SUNSHINE_CLIENT_ENABLE_SOPS"] = launch_session->enable_sops ? "true" : "false";
_env["SUNSHINE_CLIENT_ENABLE_MIC"] = launch_session->enable_mic ? "true" : "false";
_env["SUNSHINE_CLIENT_CUSTOM_SCREEN_MODE"] = std::to_string(launch_session->custom_screen_mode);
Comment on lines +574 to +579
switch (unified) {
case device_prep_e::ensure_secondary:
return device_prep_e::ensure_active; // In physical mode, activate as secondary
default:
return unified; // All other values map 1:1
}
} else if (this.currentStep === 2) {
return this.selectedDisplay !== null
} else if (this.currentStep === 3) {
return this.selectedAdapter !== null
qiin2333 and others added 5 commits March 15, 2026 17:33
* feat: add QR code pairing support

Backend:
- Add preset PIN mechanism to nvhttp (set/get/clear_preset_pin)
- Auto-use preset PIN during getservercert pairing phase
- Add POST /api/qr-pair endpoint that generates random 4-digit PIN,
  sets it as preset, and returns moonlight:// URL for QR encoding

Frontend:
- Add qrcode npm dependency for client-side QR generation
- Create useQrPair.js composable (API call, QR generation, countdown)
- Add QR code pairing card to Pin.vue with generate/refresh/cancel
- Add i18n keys for en and zh locales

The QR code encodes a moonlight://pair URL containing host, port,
PIN and server name. The preset PIN expires after 120 seconds.

* fix: remove non-ASCII filenames that break CPack ZIP packaging

CPack ZIP uses CP437 encoding which cannot handle Chinese characters
in filenames. These 4 icon files (图标_45.png, 播放_45.png, 暂停_45.png,
锁_45.png) are not referenced by any code and have equivalent
English-named counterparts already present in the same directory.

* feat: desktop UI 系统 + 子模块更新

- 更新 sunshine-control-panel 子模块 (桌面 UI 完整系统)
- confighttp/nvhttp: QR配对相关改动
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors the Windows VDD (virtual display) “prep/layout” flow by consolidating VDD/physical display preparation into a unified display_device_prep path, updating the Web UI (config + setup wizard) and i18n strings accordingly, and removing legacy VDD-specific config/session fields.

Changes:

  • Unify display preparation into display_device_prep (adds ensure_secondary) and remove vdd_prep / custom_vdd_screen_mode plumbing.
  • Update Windows display device restore/cleanup logic and setup wizard flow to match the unified preparation model.
  • Add/update Windows VDD driver assets and update locale strings across all shipped languages.

Reviewed changes

Copilot reviewed 31 out of 35 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src_assets/windows/misc/vdd/driver/zakovdd.cat Adds catalog file for the VDD driver package.
src_assets/windows/misc/vdd/driver/ZakoVDD.inf Adds INF for the VDD driver package.
src_assets/common/assets/web/public/assets/locale/zh_TW.json Updates display-prep and wizard strings (adds unified descriptions + ensure_secondary).
src_assets/common/assets/web/public/assets/locale/zh.json Updates display-prep and wizard strings; removes old VDD-prep strings.
src_assets/common/assets/web/public/assets/locale/uk.json Updates display-prep and wizard strings (adds ensure_secondary).
src_assets/common/assets/web/public/assets/locale/tr.json Updates display-prep and wizard strings (adds ensure_secondary).
src_assets/common/assets/web/public/assets/locale/sv.json Updates display-prep and wizard strings (adds ensure_secondary).
src_assets/common/assets/web/public/assets/locale/ru.json Updates display-prep and wizard strings (adds ensure_secondary).
src_assets/common/assets/web/public/assets/locale/pt_BR.json Updates display-prep and wizard strings (adds ensure_secondary).
src_assets/common/assets/web/public/assets/locale/pt.json Updates display-prep and wizard strings (adds ensure_secondary).
src_assets/common/assets/web/public/assets/locale/pl.json Updates display-prep and wizard strings (adds ensure_secondary).
src_assets/common/assets/web/public/assets/locale/ko.json Updates display-prep and wizard strings (adds ensure_secondary).
src_assets/common/assets/web/public/assets/locale/ja.json Updates display-prep and wizard strings (adds ensure_secondary).
src_assets/common/assets/web/public/assets/locale/it.json Updates display-prep and wizard strings (adds ensure_secondary).
src_assets/common/assets/web/public/assets/locale/fr.json Updates display-prep and wizard strings (adds ensure_secondary).
src_assets/common/assets/web/public/assets/locale/es.json Updates display-prep and wizard strings (adds ensure_secondary).
src_assets/common/assets/web/public/assets/locale/en_US.json Updates display-prep and wizard strings (adds ensure_secondary).
src_assets/common/assets/web/public/assets/locale/en_GB.json Updates display-prep and wizard strings (adds ensure_secondary).
src_assets/common/assets/web/public/assets/locale/en.json Updates unified display-prep labels/descriptions; removes old VDD-prep strings.
src_assets/common/assets/web/public/assets/locale/de.json Updates display-prep and wizard strings (adds ensure_secondary).
src_assets/common/assets/web/public/assets/locale/cs.json Updates display-prep and wizard strings (adds ensure_secondary).
src_assets/common/assets/web/public/assets/locale/bg.json Updates display-prep and wizard strings (adds ensure_secondary).
src_assets/common/assets/web/configs/tabs/audiovideo/DisplayDeviceOptions.vue Removes VDD-only UI branch; uses unified display prep with per-option descriptions.
src_assets/common/assets/web/composables/useConfig.js Drops vdd_prep default from UI config model.
src_assets/common/assets/web/components/SetupWizard.vue Reorders steps (GPU before display), unifies display-prep strategy selection, updates telemetry fields.
src/rtsp.h Removes custom_vdd_screen_mode from session struct.
src/process.cpp Removes SUNSHINE_CLIENT_CUSTOM_VDD_SCREEN_MODE env export.
src/nvhttp.cpp Removes customVddScreenMode parsing and env export.
src/display_device/session.cpp Adjusts shutdown/restore handling; maps unified prep to VDD/physical behaviors; adds VDD cleanup paths.
src/display_device/parsed_config.h Adds ensure_secondary and mapping helpers for unified prep -> VDD/physical modes.
src/display_device/parsed_config.cpp Implements unified prep mapping, removes client VDD-specific override handling.
src/config.h Removes vdd_prep from config struct.
src/config.cpp Removes vdd_prep parsing/default initialization.
.gitignore Stops ignoring _dev_notes/.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment thread src/display_device/session.cpp Outdated
Comment on lines +135 to +142
// 兜底:退出时如果 VDD 仍存在且 vdd_keep_enabled=false,直接销毁
// 不调用完整的 restore_state(),因为析构时 boost::log/timer 可能已被销毁
// 仅执行 VDD 销毁(写管道命令,不依赖日志和定时器)
if (!config::video.vdd_keep_enabled) {
auto vdd_id = display_device::find_device_by_friendlyname(ZAKO_NAME);
if (!vdd_id.empty()) {
vdd_utils::destroy_vdd_monitor();
}
parsed_config_t::to_physical_device_prep(device_prep_e unified) {
switch (unified) {
case device_prep_e::ensure_secondary:
return device_prep_e::ensure_active; // In physical mode, activate as secondary
Comment on lines 74 to 85
<select id="display_device_prep" class="form-select" v-model="config.display_device_prep">
<option value="no_operation">{{ $tp('config.display_device_prep_no_operation') }}</option>
<option value="ensure_active">{{ $tp('config.display_device_prep_ensure_active') }}</option>
<option value="ensure_primary">{{ $tp('config.display_device_prep_ensure_primary') }}</option>
<option value="ensure_secondary">{{ $tp('config.display_device_prep_ensure_secondary') }}</option>
<option value="ensure_only_display">
{{ $tp('config.display_device_prep_ensure_only_display') }}
</option>
</select>
</div>

<!-- VDD mode: Physical display preparation (only shown in VDD mode) -->
<div class="mb-3" v-if="isVddMode">
<label for="vdd_prep" class="form-label">
{{ $tp('config.vdd_prep') }}
</label>
<select id="vdd_prep" class="form-select" v-model="config.vdd_prep">
<option value="no_operation">{{ $tp('config.vdd_prep_no_operation') }}</option>
<option value="vdd_as_primary">{{ $tp('config.vdd_prep_vdd_as_primary') }}</option>
<option value="vdd_as_secondary">{{ $tp('config.vdd_prep_vdd_as_secondary') }}</option>
<option value="display_off">{{ $tp('config.vdd_prep_display_off') }}</option>
</select>
<div class="form-text">
<p style="white-space: pre-line">{{ $tp('config.vdd_prep_desc') }}</p>
<div class="form-text" v-if="config.display_device_prep">
{{ $tp('config.display_device_prep_' + config.display_device_prep + '_desc') }}
</div>
Comment thread src/config.cpp
@@ -1195,7 +1194,6 @@ namespace config {
}
#endif
} else if (this.currentStep === 2) {
return this.selectedDisplay !== null
} else if (this.currentStep === 3) {
return this.selectedAdapter !== null
Comment on lines 44 to 57
@@ -58,7 +53,7 @@ function addRemapping(type) {
</h2>
<div
id="panelsStayOpen-collapseOne"
class="accordion-collapse collapse"
class="accordion-collapse collapse show"
aria-labelledby="panelsStayOpen-headingOne"
@Yundi339 Yundi339 marked this pull request as ready for review March 16, 2026 03:08
@Yundi339 Yundi339 merged commit 11942f0 into master Mar 16, 2026
3 checks passed
@Yundi339 Yundi339 deleted the fix_vddcheckcheck branch April 6, 2026 13:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants