Skip to content

Comments

feat: 分离 VDD 模式的屏幕布局控制 (vdd_prep) 与普通模式的设备准备 (device_prep)#475

Open
ShadowLemoon wants to merge 5 commits intoqiin2333:masterfrom
ShadowLemoon:feat/separate-vdd-topo-mode
Open

feat: 分离 VDD 模式的屏幕布局控制 (vdd_prep) 与普通模式的设备准备 (device_prep)#475
ShadowLemoon wants to merge 5 commits intoqiin2333:masterfrom
ShadowLemoon:feat/separate-vdd-topo-mode

Conversation

@ShadowLemoon
Copy link
Collaborator

描述

背景

在虚拟显示器 (VDD) 模式下,原有的 device_prep(屏幕组合)设置不适用,因为:

  1. VDD 的添加/移除会导致 Windows 自动记忆并恢复屏幕拓扑
  2. 传统的"保存初始状态→修改→恢复"流程在 VDD 模式下意义不大
  3. VDD 模式需要独立的屏幕布局控制选项

主要改动

1. 新增 vdd_prep 配置选项

文件: parsed_config.h, parsed_config.cpp, config.h, config.cpp

新增 vdd_prep_e 枚举,提供以下选项:

  • no_operation - 保持当前布局
  • vdd_as_primary - 虚拟主屏 + 物理扩展
  • vdd_as_secondary - 物理主屏 + 虚拟扩展
  • display_off - 仅虚拟显示器(禁用物理屏)

2. VDD 模式下的拓扑处理分离

文件: settings.cpp, settings_topology.cpp, settings_topology.h

  • 新增 get_current_topology_metadata() 函数,用于 VDD 模式下只获取拓扑信息而不修改
  • apply_config 根据 is_vdd_mode 分别调用不同的拓扑处理逻辑:
    • VDD 模式: 调用 get_current_topology_metadata(),跳过拓扑修改逻辑
    • 普通模式: 调用原有的 handle_device_topology_configuration()

3. VDD 屏幕布局应用

文件: vdd_utils.cpp, vdd_utils.h, session.cpp

  • 新增 apply_vdd_prep() 函数,根据 vdd_prep 设置物理显示器布局
  • prepare_vdd() 中调用 apply_vdd_prep()ensure_vdd_extended_mode()

4. 前端 UI 更新

文件: DisplayDeviceOptions.vue, en.json, zh.json

  • 新增 isVddMode 计算属性,检测输出设备是否为 ZakoHDR
  • VDD 模式下隐藏 device_prep 下拉框,显示 vdd_prep 下拉框
  • 添加中英文翻译

逻辑流程

普通模式 (非 VDD):
┌─────────────────┐     ┌──────────────────────────────────┐     ┌─────────────────┐
│ make_parsed_    │ --> │ handle_device_topology_          │ --> │ 分辨率/刷新率/  │
│ config          │     │ configuration (device_prep)      │     │ HDR 设置        │
└─────────────────┘     └──────────────────────────────────┘     └─────────────────┘

VDD 模式:
┌─────────────────┐     ┌─────────────────┐     ┌──────────────────────────┐     ┌─────────────────┐
│ make_parsed_    │ --> │ prepare_vdd     │ --> │ get_current_topology_    │ --> │ 分辨率/刷新率/  │
│ config          │     │ (vdd_prep)      │     │ metadata (无拓扑修改)    │     │ HDR 设置        │
└─────────────────┘     └─────────────────┘     └──────────────────────────┘     └─────────────────┘

文件变更列表

文件 变更类型 说明
parsed_config.h 修改 添加 vdd_prep_e 枚举和 vdd_prep 成员
parsed_config.cpp 修改 添加 vdd_prep_from_view,设置 use_vdd 标记
config.h 修改 添加 vdd_prep 配置项
config.cpp 修改 添加 vdd_prep 解析
session.cpp 修改 调用 apply_vdd_prep
vdd_utils.h 修改 添加 apply_vdd_prep 声明
vdd_utils.cpp 修改 实现 apply_vdd_prep
settings.cpp 修改 VDD/普通模式分离处理
settings_topology.h 修改 添加 get_current_topology_metadata 声明
settings_topology.cpp 修改 实现 get_current_topology_metadata
DisplayDeviceOptions.vue 修改 条件渲染 vdd_prep/device_prep
en.json 修改 添加英文翻译
zh.json 修改 添加中文翻译

Copilot AI review requested due to automatic review settings February 3, 2026 15:43
@ShadowLemoon
Copy link
Collaborator Author

Moonlight端需要添加对应选项

Copy link

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 separates display topology control for Virtual Display Device (VDD) mode from normal mode device preparation. In VDD mode, Windows automatically manages topology when displays are added/removed, making the traditional "save→modify→restore" flow unnecessary. The PR introduces a new vdd_prep configuration option for controlling physical display layout when using VDD, while keeping the existing device_prep for normal mode.

Changes:

  • Added vdd_prep configuration option with four modes: no_operation, vdd_as_primary, vdd_as_secondary, and display_off
  • Implemented separate topology handling paths for VDD mode (read-only metadata via get_current_topology_metadata) vs normal mode (modifying topology via handle_device_topology_configuration)
  • Updated UI to conditionally show vdd_prep dropdown when VDD is selected and device_prep dropdown otherwise

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/display_device/parsed_config.h Defines vdd_prep_e enum with VDD display configuration options
src/display_device/parsed_config.cpp Implements vdd_prep_from_view() converter and sets use_vdd flag in make_parsed_config()
src/config.h Adds vdd_prep field to video configuration structure
src/config.cpp Adds default value and parsing for vdd_prep configuration option
src/platform/windows/display_device/settings_topology.h Declares get_current_topology_metadata() for VDD mode topology handling
src/platform/windows/display_device/settings_topology.cpp Implements get_current_topology_metadata() which returns current topology without modifications
src/platform/windows/display_device/settings.cpp Adds conditional logic to use get_current_topology_metadata() in VDD mode and handle_device_topology_configuration() in normal mode
src/display_device/vdd_utils.h Declares apply_vdd_prep() function for applying VDD display layout
src/display_device/vdd_utils.cpp Implements apply_vdd_prep() to configure physical display topology based on vdd_prep setting
src/display_device/session.cpp Integrates apply_vdd_prep() call in prepare_vdd() to apply display layout before other settings
src_assets/common/assets/web/configs/tabs/audiovideo/DisplayDeviceOptions.vue Adds conditional rendering to show vdd_prep dropdown in VDD mode and device_prep in normal mode
src_assets/common/assets/web/public/assets/locale/en.json Adds English translations for vdd_prep options
src_assets/common/assets/web/public/assets/locale/zh.json Adds Chinese translations for vdd_prep options

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


// 标记为VDD模式
// VDD模式下,vdd_prep 控制屏幕布局,apply_config 会根据 use_vdd 分别处理
// device_prep 保留原值但不会被使用(由 handle_topology_for_vdd_mode 处理)
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

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

The comment references a function handle_topology_for_vdd_mode that does not exist. Based on the actual implementation, VDD topology is handled by apply_vdd_prep in session.cpp (called from prepare_vdd) and get_current_topology_metadata in settings.cpp (called from apply_config). The comment should be updated to reflect the actual implementation.

Suggested change
// device_prep 保留原值但不会被使用(由 handle_topology_for_vdd_mode 处理
// device_prep 保留原值但不会被直接使用(由 apply_vdd_prep / get_current_topology_metadata 处理拓扑

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings February 4, 2026 12:50
Copy link

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

Copilot reviewed 17 out of 17 changed files in this pull request and generated 2 comments.


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

Comment on lines +538 to 544
else {
// No specific configuration, ensure VDD is in extended mode (default behavior)
if (vdd_utils::ensure_vdd_extended_mode(device_zako)) {
BOOST_LOG(info) << "已将VDD切换到扩展模式";
std::this_thread::sleep_for(500ms);
}
}
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

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

When vdd_prep is set to no_operation (meaning "Keep Current Layout"), the code still calls ensure_vdd_extended_mode. This seems inconsistent with the no_operation intent, which should preserve the current display topology without modification.

Consider removing the else block (lines 538-544) so that when vdd_prep is no_operation, no topology changes are made at all. The VDD should remain in whatever mode it's currently in.

Suggested change
else {
// No specific configuration, ensure VDD is in extended mode (default behavior)
if (vdd_utils::ensure_vdd_extended_mode(device_zako)) {
BOOST_LOG(info) << "已将VDD切换到扩展模式";
std::this_thread::sleep_for(500ms);
}
}

Copilot uses AI. Check for mistakes.
bool vdd_keep_enabled;
/** When true, after stream end if no display is found (headless), create Zako VDD automatically. Default false. */
bool vdd_headless_create_enabled;
/** When true, reuse existing VDD on client switch instead of destroying and recreating. Default true. */
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

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

The comment states "Default true" but the actual default value in config.cpp line 398 is false. This inconsistency between the comment and the implementation could be confusing.

Update the comment to match the actual default value: "Default false."

Suggested change
/** When true, reuse existing VDD on client switch instead of destroying and recreating. Default true. */
/** When true, reuse existing VDD on client switch instead of destroying and recreating. Default false. */

Copilot uses AI. Check for mistakes.
@qiin2333 qiin2333 force-pushed the master branch 2 times, most recently from 029ba99 to eba4145 Compare February 14, 2026 06:38
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.

1 participant