远程 IDD 的 IddCx 1.4 更新
IddCx 版本 1.4 的以下更新仅适用于远程间接显示驱动程序 (IDD) 。
远程 IDD 开发人员还应看到 主机的 IddCx 1.4 更新,并查看远程 IDD 以获取其他更新。
声明远程会话的远程 IDD
IDD 声明它想要通过在IDDCX_ADAPTER_CAPS中设置IDDCX_ADAPTER_FLAGS_REMOTE_SESSION_DRIVER位来创建远程 ID 适配器。调用 IddCxAdapterInitAsync 时的标志字段。 OS 跟踪 IDD 是否由于远程桌面堆栈连接到远程会话而加载,并在以下两种情况下 IddCxAdapterInitAsync 调用失败:
- IDD 未为 OS 远程桌面堆栈为远程会话创建的设备设置IDDCX_ADAPTER_FLAGS_REMOTE_SESSION_DRIVER
- 非 OS 远程桌面堆栈创建的设备的 IDD 集IDDCX_ADAPTER_FLAGS_REMOTE_SESSION_DRIVER
远程 IDD 的安装建议
UMDF 允许驱动程序使用 UmdfHostProcessSharing 和 DeviceGroupId 等指令控制其 INF 文件中的设备池选项。 由于某些锁争用问题,强烈建议远程 IDD 将 UmdfHostProcessSharing 指令设置为 ProcessSharingDisabled 并删除任何 DeviceGroupId 指令。 此设置将为每个会话配置远程 IDD,使其位于其自己的进程中。
对远程 IDD 的现有 IddCx 功能的其他限制
需要远程 ID 才能在 IDDCX_ADAPTER_CAPS 中设置 IDDCX_ADAPTER_FLAGS_USE_SMALLEST_MODE。标志 字段。 这可确保不使用虚拟模式,因此交换链大小将始终与桌面分辨率匹配。 如果未设置此标志,IddCxAdapterInitAsync 将失败。
远程 IDD 仅支持渐进式目标模式,因此 IDDCX_TARGET_MODE。TargetVideoSignalInfo.targetVideoSignalInfo.scanLineOrdering 必须设置为 DISPLAYCONFIG_SCANLINE_ORDERING_PROGRESSIVE。 如果未设置此值,IddCxMonitorArrival 将失败。
设置远程会话的显示配置
由于远程 IDD 控制远程会话中的所有监视器,并且远程会话显示配置应镜像客户端的显示配置,因此远程 IDD 需要能够指定 OS 将在远程会话中设置的显示配置。 当会话创建为远程会话或转换为远程会话时,需要设置此显示配置。
远程 IDD 可以在远程会话期间将显示配置更新为:
- 更改当前监视器的设置 (例如,更改桌面位置、方向、物理大小或 DPI)
- 通过调用 IddCxMonitorArrival/IddCxMonitorDeparture 在添加/删除监视器后设置桌面配置。 远程 IDD 使用 IddCxMonitorArrival 和 IddCxMonitorDeparture 的方式与控制台 IDD 相同,以通知 OS 有关监视器到达和离开的信息。
下面是 OS 用于处理监视器到达、离开和桌面配置更改的逻辑。 对于每个远程会话,OS 将存储远程 IDD 提供的单个当前桌面配置。 此桌面配置将启动为空,并在每次远程 IDD 成功调用 IddCxDisplayConfigUpdate 时更新。
驱动程序收到新的显示配置时
If all monitors in the new display configuration are present in the system
If new display configuration is supported by driver (eg resolutions)
Store new display configuration
Set new display configuration (this will disable any active monitors
that are not part of new configuration)
If all monitors in the new display config are not currently present in the system
Store new display configuration
Disable all active paths and wait for the correct set of monitors to arrive
删除监视器时
If removed monitor is not in the current display configuration
Remove the monitor and do not change the current desktop configuration
If removed monitor is part of the current display configuration
Remove the monitor
Disable all active paths and wait for the correct set of monitors to arrive
监视器到达时
If added monitor is not part of current display configuration
Do not change the display configuration
If added monitor is part of the current display configuration
If now all the monitors in the current display configurations are present
Set the new display configuration
下面是一些简单方案,用于说明如何使用 IddCxDisplayConfigUpdate 。
方案 1:新会话从连接的两台监视器开始
驱动程序操作 | 当前显示拓扑 | 当前连接的监视器 | 当前活动的监视器 | 说明 |
---|---|---|---|---|
无 | 无 | 无 | 会话启动配置 | |
IddCxMonitorArrival (Mon1) | 无 | 星期一 | 无 | 没有活动显示配置,因此没有任何更改 |
IddCxMonitorArrival (Mon2) | 无 | Mon1、Mon2 | 无 | 显示配置中仍然没有更改 |
IddCxDisplayConfigUpdate | Mon1、Mon2 | Mon1、Mon2 | Mon1、Mon2 | 当所有监视器都已连接时,请设置配置 |
注意:在为相同结果添加监视器之前,驱动程序可能已调用 IddCxDisplayConfigUpdate 。
方案 2:将第三个监视器添加到方案 1 并使其处于活动状态
驱动程序操作 | 当前显示拓扑 | 当前连接的监视器 | 当前活动的监视器 | 备注 |
---|---|---|---|---|
IddCxMonitorArrival (Mon3) | Mon1、Mon2 | Mon1、Mon2、Mon3 | Mon1、Mon2 | 显示配置没有更改 |
IddCxDisplayConfigUpdate | Mon1、Mon2、Mon3 | Mon1、Mon2、Mon3 | Mon1、Mon2、Mon3 | 新配置集 |
方案 3:从活动配置中删除监视器
驱动程序操作 | 当前显示拓扑 | 当前连接的监视器 | 当前活动的监视器 | 备注 |
---|---|---|---|---|
Mon1、Mon2 | Mon1、Mon2 | Mon1、Mon2 | 正在启动配置 | |
IddCxDisplayConfigUpdate () | 星期一 | Mon1、Mon2 | 星期一 | 将配置更改为仅先使用 Mon1 |
IddCxMonitorDeparture (Mon2) | 星期一 | 星期一 | 星期一 |
方案 4:当驱动程序仅支持单个模式时更改路径的模式
驱动程序操作 | 当前显示拓扑 | 当前连接的监视器 | 当前处于活动状态的监视器 | 备注 |
---|---|---|---|---|
Mon1 10x7、Mon2 19x10 | Mon1、Mon2 | Mon1、Mon2 | 正在启动配置 | |
IddCxMonitorUpdateModes (Mon1 支持 16x9) | 无 | Mon1、Mon2 | 无 | 已将 Mon1 的模式列表更新为 16x9 |
IddCxDisplayConfigUpdate () | Mon1 16x9、Mon2 19x10 | Mon1、Mon2 | Mon1、Mon2 | 将 Mon1 的配置设置为 16x9 |
处理 IddCxDisplayConfigUpdate 错误
远程驱动程序需要处理 来自 IddCxDisplayConfigUpdate 的错误。 预期会出现一些错误;例如,当连接使用临时会话时。
在初始配置中出现意外情况时,驱动程序具有如下选项:
- 调用 IddCxReportCriticalError 以终止驱动程序进程并断开用户会话的连接。 建议驱动程序使用唯一的主要/次要组合,以便在崩溃和 Watson 报告中识别这些情况。
- 如果它是暂时性错误,请重试配置。
- 尝试其他配置。
远程驱动程序可能会确定会话期间配置更改失败不如初始配置失败严重,因此可能永远不会在会话中调用 IddCxReportCriticalError 。
如果 IddCxDisplayConfigUpdate 返回STATUS_GRAPHICS_INDIRECT_DISPLAY_DEVICE_STOPPED,则驱动程序不应调用 IddCxReportCriticalError,因为 OS 检测到目标会话正在断开连接或该会话的 IddCx 适配器正在停止,因为这是预期的。
间接显示远程会话中的显示 API 更改
在远程 XDDM 会话中,OS 显示控制面板不会为用户提供任何用于更改显示配置的控件。 这主要是因为远程会话桌面配置由连接的客户端系统控制,而不是由会话中运行的应用程序控制。 例如,在远程会话中,支持 Win+P 投影用户界面没有意义。
远程 ID 会话的一般情况:
- 显示枚举 API 工作,包括 QueryDisplayConfig
- 显示设置 API 不起作用。 例如,远程会话中运行的应用程序不需要调用 ChangeDisplaySettings/SetDisplayConfig 来更改桌面配置 (例如,更改桌面位置或拓扑) 。
有趣的是,远程 XDDM 解决方案使用 ChangeDisplaySetting 来更改模式和桌面位置,因为这是应用来自客户端的更改的唯一方法。 由于远程 ID 解决方案具有 IddCxDisplayConfigUpdate 功能,因此不再需要在远程 ID 会话中运行 ChangeDisplaySetting 。
下表显示了 XDDM 远程会话和 WDDM 远程会话中 (CPL) 功能的 API 和显示控制面板。
API/CPL | XDDM 远程会话 | WDDM 远程会话 |
---|---|---|
显示 CPL | 不会显示任何信息,并发出一条消息,指出“无法从远程会话更改显示设置”。 | 行为与 XDDM 远程会话相同。 |
Win+P UI 和功能 | UI 不显示,API 失败。 | 行为与 XDDM 远程会话相同。 |
旧版显示枚举 API (,例如 EnumDisplaySettings & EnumDisplayDevices) | API 按预期工作并返回相关信息。 | 行为与 XDDM 远程会话相同。 |
旧版 ChangeDisplaySetting | 工作,用于反映来自客户端的桌面更改。 | 出于应用程序兼容性原因返回成功,但忽略调用,并且不会更改任何显示配置。 IDD 将使用 IddCxDisplayConfigUpdate 更改桌面配置。 |
QueryDisplayConfig | 失败。 | 按预期工作。 |
DisplayConfigGetDeviceInfo | 失败。 | 工作和报告预期信息。 |
SetDisplayConfig 和 DisplayConfigSetDeviceInfo | 失败。 | 行为与 XDDM 远程会话相同。 |
监视 ID 远程会话中的空闲行为
当协议堆栈调用 IWRdsProtocolConnectionCallback::StopScreenUpdates 以停止更新客户端屏幕时,OS 会销毁交换链并使该会话的所有路径处于非活动状态,从而导致调用 IDD 的EVT_IDD_CX_ADAPTER_COMMIT_MODES回调,并在IDDCX_PATH中设置IDDCX_PATH_FLAGS_NONE。所有路径的标志。
当协议堆栈调用 IWRdsProtocolConnectionCallback::RedrawWindow 以再次启用更新时,OS 将使用 IDD 的 EVT_IDD_CX_ADAPTER_COMMIT_MODES 回调设置新的活动路径,并创建新的交换链。
ID 远程会话中的断开连接行为
当用户与远程会话断开连接时,OS 会销毁托管该会话的远程 ID 设备的 devnode,从而导致该会话的远程 ID 适配器被 PnpStopped。 UMDF 将调用远程 IDD 的 EVT_WDF_DEVICE_D0_EXIT 回调。
如果会话再次远程连接到,OS 将为该会话的远程 IDD 创建新的开发节点。 远程 IDD 应再次执行正常启动序列,初始化适配器,然后添加监视器等。