From f2628528380090408d354c75b9b1763b06ec2b0a Mon Sep 17 00:00:00 2001 From: Yukino Song Date: Thu, 5 Jun 2025 16:32:13 +0800 Subject: [PATCH] Add always use virtual display option for clients --- src/confighttp.cpp | 4 +++- src/crypto.h | 1 + src/nvhttp.cpp | 12 +++++++--- src/nvhttp.h | 8 +++++-- src_assets/common/assets/web/pin.html | 24 ++++++++++++++++++- .../assets/web/public/assets/locale/en.json | 6 +++-- .../assets/web/public/assets/locale/zh.json | 6 +++-- 7 files changed, 50 insertions(+), 11 deletions(-) diff --git a/src/confighttp.cpp b/src/confighttp.cpp index 05188b1f..00aedf69 100644 --- a/src/confighttp.cpp +++ b/src/confighttp.cpp @@ -869,6 +869,7 @@ namespace confighttp { std::string display_mode = input_tree.value("display_mode", ""); bool enable_legacy_ordering = input_tree.value("enable_legacy_ordering", true); bool allow_client_commands = input_tree.value("allow_client_commands", true); + bool always_use_virtual_display = input_tree.value("always_use_virtual_display", false); auto do_cmds = nvhttp::extract_command_entries(input_tree, "do"); auto undo_cmds = nvhttp::extract_command_entries(input_tree, "undo"); auto perm = static_cast(input_tree.value("perm", static_cast(crypto::PERM::_no)) & static_cast(crypto::PERM::_all)); @@ -880,7 +881,8 @@ namespace confighttp { undo_cmds, perm, enable_legacy_ordering, - allow_client_commands + allow_client_commands, + always_use_virtual_display ); send_response(response, output_tree); } catch (std::exception &e) { diff --git a/src/crypto.h b/src/crypto.h index 3cff172c..350bb5cc 100644 --- a/src/crypto.h +++ b/src/crypto.h @@ -106,6 +106,7 @@ namespace crypto { PERM perm; bool enable_legacy_ordering; bool allow_client_commands; + bool always_use_virtual_display; }; using p_named_cert_t = std::shared_ptr; diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index e000b255..e6df1c0b 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -250,7 +250,7 @@ namespace nvhttp { named_cert_node["perm"] = static_cast(named_cert_p->perm); named_cert_node["enable_legacy_ordering"] = named_cert_p->enable_legacy_ordering; named_cert_node["allow_client_commands"] = named_cert_p->allow_client_commands; - + named_cert_node["always_use_virtual_display"] = named_cert_p->always_use_virtual_display; // Add "do" commands if available. if (!named_cert_p->do_cmds.empty()) { @@ -329,6 +329,7 @@ namespace nvhttp { named_cert_p->perm = PERM::_all; named_cert_p->enable_legacy_ordering = true; named_cert_p->allow_client_commands = true; + named_cert_p->always_use_virtual_display = false; client.named_devices.emplace_back(named_cert_p); } } @@ -346,6 +347,7 @@ namespace nvhttp { named_cert_p->perm = (PERM)(util::get_non_string_json_value(el, "perm", (uint32_t)PERM::_all)) & PERM::_all; named_cert_p->enable_legacy_ordering = el.value("enable_legacy_ordering", true); named_cert_p->allow_client_commands = el.value("allow_client_commands", true); + named_cert_p->always_use_virtual_display = el.value("always_use_virtual_display", false); // Load command entries for "do" and "undo" keys. named_cert_p->do_cmds = extract_command_entries(el, "do"); named_cert_p->undo_cmds = extract_command_entries(el, "undo"); @@ -456,7 +458,7 @@ namespace nvhttp { launch_session->surround_params = (get_arg(args, "surroundParams", "")); launch_session->gcmap = util::from_view(get_arg(args, "gcmap", "0")); launch_session->enable_hdr = util::from_view(get_arg(args, "hdrMode", "0")); - launch_session->virtual_display = util::from_view(get_arg(args, "virtualDisplay", "0")); + launch_session->virtual_display = util::from_view(get_arg(args, "virtualDisplay", "0")) || named_cert_p->always_use_virtual_display; launch_session->scale_factor = util::from_view(get_arg(args, "scaleFactor", "100")); launch_session->client_do_cmds = named_cert_p->do_cmds; @@ -631,6 +633,7 @@ namespace nvhttp { named_cert_p->enable_legacy_ordering = true; named_cert_p->allow_client_commands = true; + named_cert_p->always_use_virtual_display = false; auto it = map_id_sess.find(client.uniqueID); map_id_sess.erase(it); @@ -1021,6 +1024,7 @@ namespace nvhttp { named_cert_node["perm"] = static_cast(named_cert->perm); named_cert_node["enable_legacy_ordering"] = named_cert->enable_legacy_ordering; named_cert_node["allow_client_commands"] = named_cert->allow_client_commands; + named_cert_node["always_use_virtual_display"] = named_cert->always_use_virtual_display; // Add "do" commands if available if (!named_cert->do_cmds.empty()) { @@ -1809,7 +1813,8 @@ namespace nvhttp { const cmd_list_t& undo_cmds, const crypto::PERM newPerm, const bool enable_legacy_ordering, - const bool allow_client_commands + const bool allow_client_commands, + const bool always_use_virtual_display ) { find_and_udpate_session_info(uuid, name, newPerm); @@ -1825,6 +1830,7 @@ namespace nvhttp { named_cert_p->undo_cmds = undo_cmds; named_cert_p->enable_legacy_ordering = enable_legacy_ordering; named_cert_p->allow_client_commands = allow_client_commands; + named_cert_p->always_use_virtual_display = always_use_virtual_display; save_state(); return true; } diff --git a/src/nvhttp.h b/src/nvhttp.h index fc71ff73..6d2c6e06 100644 --- a/src/nvhttp.h +++ b/src/nvhttp.h @@ -265,7 +265,10 @@ namespace nvhttp { * @param[in] do_cmds The do commands * @param[in] undo_cmds The undo commands * @param[in] newPerm New permission - * + * @param[in] enable_legacy_ordering Enable legacy ordering + * @param[in] allow_client_commands Allow client commands + * @param[in] always_use_virtual_display Always use virtual display + * * @return Whether the update is successful */ bool update_device_info( @@ -276,6 +279,7 @@ namespace nvhttp { const cmd_list_t& undo_cmds, const crypto::PERM newPerm, const bool enable_legacy_ordering, - const bool allow_client_commands + const bool allow_client_commands, + const bool always_use_virtual_display ); } // namespace nvhttp diff --git a/src_assets/common/assets/web/pin.html b/src_assets/common/assets/web/pin.html index 9806856e..524ce6cc 100644 --- a/src_assets/common/assets/web/pin.html +++ b/src_assets/common/assets/web/pin.html @@ -114,6 +114,15 @@ default="true" > + +
@@ -522,6 +531,7 @@ client.editName = client.name; client.editAllowClientCommands = client.allow_client_commands; client.editEnableLegacyOrdering = client.enable_legacy_ordering; + client.editAlwaysUseVirtualDisplay = client.always_use_virtual_display; client.editDisplayMode = client.display_mode; client.edit_do = JSON.parse(JSON.stringify(client.do || [])); client.edit_undo = JSON.parse(JSON.stringify(client.undo || [])); @@ -537,6 +547,7 @@ client.editDisplayMode = client.display_mode; client.editAllowClientCommands = client.allow_client_commands; client.editEnableLegacyOrdering = client.enable_legacy_ordering; + client.editAlwaysUseVirtualDisplay = client.always_use_virtual_display; }, saveClient(client) { client.editing = false; @@ -547,6 +558,7 @@ display_mode: client.editDisplayMode.trim(), allow_client_commands: client.editAllowClientCommands, enable_legacy_ordering: client.editEnableLegacyOrdering, + always_use_virtual_display: client.editAlwaysUseVirtualDisplay, perm: client.editPerm & permissionMapping._all, do: client.edit_do.reduce((filtered, {cmd: _cmd, elevated}) => { const cmd = _cmd.trim() @@ -577,6 +589,14 @@ method: 'POST', body: JSON.stringify(editedClient) }) + .then(resp => resp.json()) + .then(resp => { + if (resp.status) { + this.refreshClients(); + } else { + throw new Error(resp.message); + } + }) .catch(err => { alert(this.i18n.t('pin.save_client_error') + err); }) @@ -678,6 +698,7 @@ do: _do, undo, allow_client_commands, + always_use_virtual_display, enable_legacy_ordering }) => { const permInt = parseInt(perm, 10); @@ -691,7 +712,8 @@ do: _do, undo, allow_client_commands, - enable_legacy_ordering + enable_legacy_ordering, + always_use_virtual_display } }) currentEditingClient = null; diff --git a/src_assets/common/assets/web/public/assets/locale/en.json b/src_assets/common/assets/web/public/assets/locale/en.json index 641d5bd6..1f69972d 100644 --- a/src_assets/common/assets/web/public/assets/locale/en.json +++ b/src_assets/common/assets/web/public/assets/locale/en.json @@ -114,8 +114,8 @@ "terminate_on_pause_desc": "Terminate the app when all clients are disconnected.", "use_app_identity": "Use App Identity", "use_app_identity_desc": "Use the app's own identity while creating virtual displays instead of client's. This is useful when you want display configuration for each APP separately.", - "virtual_display": "Always use Virtual Display", - "virtual_display_desc": "Always use virtual display on this app, overriding client request. Please make sure the SudoVDA driver is installed and enabled.", + "virtual_display": "Always create Virtual Display", + "virtual_display_desc": "Always create a virtual display when starting this app, overriding client request. Please make sure the SudoVDA driver is installed and enabled.", "virtual_display_primary": "Enforce Virtual Display Primary", "virtual_display_primary_desc": "Automatically set the virtual display as primary display when the app starts. Virtual display will always be set to primary when client requests to use virtual display. (Recommended to keep on) [Broken on Windows 11 24H2]", "wait_all": "Continue streaming until all app processes exit", @@ -508,6 +508,8 @@ "pin": { "allow_client_commands": "Allow client commands", "allow_client_commands_desc": "Allow client commands to be executed when connecting to this device.", + "always_use_virtual_display": "Always create virtual display", + "always_use_virtual_display_desc": "Always create a virtual display when connecting from this device.", "client_do_cmd": "Client connect commands", "client_do_cmd_desc": "Commands to be executed when client connects. All of the commands are executed detached.", "client_undo_cmd": "Client disconnect commands", diff --git a/src_assets/common/assets/web/public/assets/locale/zh.json b/src_assets/common/assets/web/public/assets/locale/zh.json index 75c72b74..61b14500 100644 --- a/src_assets/common/assets/web/public/assets/locale/zh.json +++ b/src_assets/common/assets/web/public/assets/locale/zh.json @@ -115,8 +115,8 @@ "terminate_on_pause_desc": "当所有客户端断开连接时终止此 APP。", "use_app_identity": "使用 App 身份", "use_app_identity_desc": "在创建虚拟显示器时使用 App 自身的身份,而非客户端的。这样可以针对 APP 进行单独的显示器组合配置。", - "virtual_display": "总是使用虚拟显示器", - "virtual_display_desc": "在使用这个 App 的时候总是使用虚拟显示器,覆盖客户端请求。请确保 SudoVDA 虚拟显示器驱动已安装并启用。", + "virtual_display": "总是创建虚拟显示器", + "virtual_display_desc": "在启动这个 App 的时候总是创建虚拟显示器,覆盖客户端请求。请确保 SudoVDA 虚拟显示器驱动已安装并启用。", "wait_all": "继续串流直到所有应用进程退出", "wait_all_desc": "这将继续串流直到应用程序启动的所有进程终止。 当未选中时,串流将在初始应用进程终止时停止,即使其他应用进程仍在运行。", "working_dir": "工作目录", @@ -501,6 +501,8 @@ "pin": { "allow_client_commands": "允许客户端命令", "allow_client_commands_desc": "允许客户端命令在运行此应用时执行。", + "always_use_virtual_display": "总是创建虚拟显示器", + "always_use_virtual_display_desc": "此设备连接时总是创建虚拟显示器。", "client_do_cmd": "客户端连入命令", "client_do_cmd_desc": "当此客户端连接时执行的命令。所有命令都以后台模式允许。", "client_undo_cmd": "客户端断开命令",