diff --git a/src/platform/windows/virtual_display.cpp b/src/platform/windows/virtual_display.cpp index f11fa48f..b596a07e 100644 --- a/src/platform/windows/virtual_display.cpp +++ b/src/platform/windows/virtual_display.cpp @@ -36,6 +36,24 @@ LONG changeDisplaySettings(const wchar_t* deviceName, int width, int height, int return 0; } +std::wstring getPrimaryDisplay() { + DISPLAY_DEVICEW displayDevice; + displayDevice.cb = sizeof(DISPLAY_DEVICE); + + std::wstring primaryDeviceName; + + int deviceIndex = 0; + while (EnumDisplayDevicesW(NULL, deviceIndex, &displayDevice, 0)) { + if (displayDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) { + primaryDeviceName = displayDevice.DeviceName; + break; + } + deviceIndex++; + } + + return primaryDeviceName; +} + bool setPrimaryDisplay(const wchar_t* primaryDeviceName) { DEVMODEW primaryDevMode{}; if (!getDeviceSettings(primaryDeviceName, primaryDevMode)) { @@ -178,7 +196,7 @@ std::wstring createVirtualDisplay( retryInterval *= 2; } - wprintf(L"[SUDOVDA] Virtual display added successfully: %ws\n", deviceName); + wprintf(L"[SUDOVDA] Virtual display added successfully: %ls\n", deviceName); printf("[SUDOVDA] Configuration: W: %d, H: %d, FPS: %d\n", width, height, fps); return std::wstring(deviceName); diff --git a/src/platform/windows/virtual_display.h b/src/platform/windows/virtual_display.h index 5a1d7b9d..7a0010e9 100644 --- a/src/platform/windows/virtual_display.h +++ b/src/platform/windows/virtual_display.h @@ -13,6 +13,7 @@ namespace VDISPLAY { LONG getDeviceSettings(const wchar_t* deviceName, DEVMODEW& devMode); LONG changeDisplaySettings(const wchar_t* deviceName, int width, int height, int refresh_rate); + std::wstring getPrimaryDisplay(); bool setPrimaryDisplay(const wchar_t* primaryDeviceName); bool startPingThread(); diff --git a/src/process.cpp b/src/process.cpp index 6a5f1ec0..93c2bdc7 100644 --- a/src/process.cpp +++ b/src/process.cpp @@ -208,15 +208,15 @@ namespace proc { #ifdef _WIN32 if (launch_session->virtual_display || _app.virtual_display) { - // Mark as no vdisplay by default - launch_session->virtual_display = false; if (!vdisplayDriverInitialized) { // Try init driver again vdisplayDriverInitialized = VDISPLAY::openVDisplayDevice(); } if (vdisplayDriverInitialized) { - std::wstring vdisplay_name = VDISPLAY::createVirtualDisplay( + std::wstring prevPrimaryDisplayName = VDISPLAY::getPrimaryDisplay(); + + std::wstring vdisplayName = VDISPLAY::createVirtualDisplay( launch_session->unique_id.c_str(), launch_session->device_name.c_str(), _app.name.c_str(), @@ -225,11 +225,33 @@ namespace proc { launch_session->fps, launch_session->display_guid ); - // Set virtual_display to true when everything went fine - launch_session->virtual_display = true; - VDISPLAY::changeDisplaySettings(vdisplay_name.c_str(), launch_session->width, launch_session->height, launch_session->fps); - VDISPLAY::setPrimaryDisplay(vdisplay_name.c_str()); + std::wstring currentPrimaryDisplayName = VDISPLAY::getPrimaryDisplay(); + + // Apply display settings + VDISPLAY::changeDisplaySettings(vdisplayName.c_str(), launch_session->width, launch_session->height, launch_session->fps); + + // Determine if we need to set the virtual display as primary + bool shouldSetPrimary = false; + + if (launch_session->virtual_display || _app.virtual_display_primary) { + shouldSetPrimary = (currentPrimaryDisplayName != vdisplayName); + } else { + shouldSetPrimary = (currentPrimaryDisplayName != prevPrimaryDisplayName); + } + + // Set primary display if needed + if (shouldSetPrimary) { + VDISPLAY::setPrimaryDisplay( + (launch_session->virtual_display || _app.virtual_display_primary) + ? vdisplayName.c_str() + : prevPrimaryDisplayName.c_str() + ); + } + + // Set virtual_display to true when everything went fine + this->virtual_display = true; + this->display_name = platf::to_utf8(vdisplayName); } } #endif @@ -369,7 +391,7 @@ namespace proc { _pipe.reset(); #ifdef _WIN32 - if (vdisplayDriverInitialized && _launch_session && _launch_session->virtual_display) { + if (vdisplayDriverInitialized && _launch_session && this->virtual_display) { VDISPLAY::removeVirtualDisplay(_launch_session->display_guid); } #endif @@ -387,6 +409,7 @@ namespace proc { _app_id = -1; display_name.clear(); _launch_session.reset(); + virtual_display = false; } const std::vector & @@ -640,6 +663,7 @@ namespace proc { ctx.name = "Virtual Display"; ctx.image_path = parse_env_val(this_env, "virtual_desktop.png"); ctx.virtual_display = true; + ctx.virtual_display_primary = true; ctx.elevated = false; ctx.auto_detach = true; @@ -676,6 +700,7 @@ namespace proc { auto wait_all = app_node.get_optional("wait-all"s); auto exit_timeout = app_node.get_optional("exit-timeout"s); auto virtual_display = app_node.get_optional("virtual-display"); + auto virtual_display_primary = app_node.get_optional("virtual-display-primary"); std::vector prep_cmds; if (!exclude_global_prep.value_or(false)) { @@ -744,6 +769,7 @@ namespace proc { ctx.wait_all = wait_all.value_or(true); ctx.exit_timeout = std::chrono::seconds { exit_timeout.value_or(5) }; ctx.virtual_display = virtual_display.value_or(false); + ctx.virtual_display_primary = virtual_display_primary.value_or(true); auto possible_ids = calculate_app_id(name, ctx.image_path, i++); if (ids.count(std::get<0>(possible_ids)) == 0) { diff --git a/src/process.h b/src/process.h index 8044cc43..da696b66 100644 --- a/src/process.h +++ b/src/process.h @@ -65,6 +65,7 @@ namespace proc { bool auto_detach; bool wait_all; bool virtual_display; + bool virtual_display_primary; std::chrono::seconds exit_timeout; }; @@ -73,6 +74,7 @@ namespace proc { KITTY_DEFAULT_CONSTR_MOVE_THROW(proc_t) std::string display_name; + bool virtual_display; proc_t( boost::process::environment &&env, diff --git a/src/system_tray.cpp b/src/system_tray.cpp index 29f2c66e..d5a7cb85 100644 --- a/src/system_tray.cpp +++ b/src/system_tray.cpp @@ -249,8 +249,6 @@ namespace system_tray { return; } - printf("Tray playing: %s\n", app_name.c_str()); - tray.notification_title = NULL; tray.notification_text = NULL; tray.notification_cb = NULL; diff --git a/src_assets/common/assets/web/apps.html b/src_assets/common/assets/web/apps.html index f3452e0b..ecb78f67 100644 --- a/src_assets/common/assets/web/apps.html +++ b/src_assets/common/assets/web/apps.html @@ -229,12 +229,19 @@
{{ $t('apps.wait_all_desc') }}
-
+
{{ $t('apps.virtual_display_desc') }}
+ +
+ + +
{{ $t('apps.virtual_display_primary_desc') }}
+
@@ -373,11 +380,13 @@ import { createApp } from 'vue' import { initApp } from './init' import Navbar from './Navbar.vue' + import PlatformLayout from './PlatformLayout.vue' import { Dropdown } from 'bootstrap/dist/js/bootstrap' const app = createApp({ components: { - Navbar + Navbar, + PlatformLayout }, data() { return { @@ -417,7 +426,8 @@ "exit-timeout": 5, "prep-cmd": [], detached: [], - "image-path": "" + "image-path": "", + "virtual-display-primary": true }; this.editForm.index = -1; this.showEditForm = true; @@ -443,6 +453,9 @@ if (this.editForm["exit-timeout"] === undefined) { this.editForm["exit-timeout"] = 5; } + if (typeof this.editForm["virtual-display-primary"] === "undefined") { + this.editForm["virtual-display-primary"] = true; + } this.showEditForm = true; }, showDeleteForm(id) { 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 360922ac..da271bbc 100644 --- a/src_assets/common/assets/web/public/assets/locale/en.json +++ b/src_assets/common/assets/web/public/assets/locale/en.json @@ -81,7 +81,9 @@ "working_dir": "Working Directory", "working_dir_desc": "The working directory that should be passed to the process. For example, some applications use the working directory to search for configuration files. If not set, Apollo will default to the parent directory of the command", "virtual_display": "Use Virtual Display", - "virtual_display_desc": "Always use Virtual Display on this app, overriding client request." + "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_primary": "Set Virtual Display as Primary Display", + "virtual_display_primary_desc": "Automatically set the Virtual Display as Primary Display when the app starts. (Recommended to keep on)" }, "config": { "adapter_name": "Adapter Name",