Migrate virtual display config to new Display Device API
This commit is contained in:
@@ -417,8 +417,6 @@ namespace config {
|
|||||||
|
|
||||||
video_t video {
|
video_t video {
|
||||||
false, // headless_mode
|
false, // headless_mode
|
||||||
false, // follow_client_hdr
|
|
||||||
true, // set_vdisplay_primary
|
|
||||||
28, // qp
|
28, // qp
|
||||||
|
|
||||||
0, // hevc_mode
|
0, // hevc_mode
|
||||||
@@ -1091,8 +1089,6 @@ namespace config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool_f(vars, "headless_mode", video.headless_mode);
|
bool_f(vars, "headless_mode", video.headless_mode);
|
||||||
bool_f(vars, "follow_client_hdr", video.follow_client_hdr);
|
|
||||||
bool_f(vars, "set_vdisplay_primary", video.set_vdisplay_primary);
|
|
||||||
int_f(vars, "qp", video.qp);
|
int_f(vars, "qp", video.qp);
|
||||||
int_between_f(vars, "hevc_mode", video.hevc_mode, { 0, 3 });
|
int_between_f(vars, "hevc_mode", video.hevc_mode, { 0, 3 });
|
||||||
int_between_f(vars, "av1_mode", video.av1_mode, { 0, 3 });
|
int_between_f(vars, "av1_mode", video.av1_mode, { 0, 3 });
|
||||||
|
|||||||
@@ -16,8 +16,6 @@
|
|||||||
namespace config {
|
namespace config {
|
||||||
struct video_t {
|
struct video_t {
|
||||||
bool headless_mode;
|
bool headless_mode;
|
||||||
bool follow_client_hdr;
|
|
||||||
bool set_vdisplay_primary;
|
|
||||||
// ffmpeg params
|
// ffmpeg params
|
||||||
int qp; // higher == more compression and less quality
|
int qp; // higher == more compression and less quality
|
||||||
|
|
||||||
|
|||||||
@@ -738,6 +738,24 @@ namespace display_device {
|
|||||||
return DD_DATA.sm_instance->execute([&output_name](auto &settings_iface) { return settings_iface.getDisplayName(output_name); });
|
return DD_DATA.sm_instance->execute([&output_name](auto &settings_iface) { return settings_iface.getDisplayName(output_name); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
map_display_name(const std::string &display_name) {
|
||||||
|
std::lock_guard lock { DD_DATA.mutex };
|
||||||
|
if (!DD_DATA.sm_instance) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto available_devices { DD_DATA.sm_instance->execute([](auto &settings_iface) { return settings_iface.enumAvailableDevices(); }) };
|
||||||
|
|
||||||
|
for (auto &i : available_devices) {
|
||||||
|
if (i.m_display_name == display_name) {
|
||||||
|
return i.m_device_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
configure_display(const config::video_t &video_config, const rtsp_stream::launch_session_t &session) {
|
configure_display(const config::video_t &video_config, const rtsp_stream::launch_session_t &session) {
|
||||||
const auto result { parse_configuration(video_config, session) };
|
const auto result { parse_configuration(video_config, session) };
|
||||||
|
|||||||
@@ -48,6 +48,9 @@ namespace display_device {
|
|||||||
[[nodiscard]] std::string
|
[[nodiscard]] std::string
|
||||||
map_output_name(const std::string &output_name);
|
map_output_name(const std::string &output_name);
|
||||||
|
|
||||||
|
[[nodiscard]] std::string
|
||||||
|
map_display_name(const std::string &display_name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Configure the display device based on the user configuration and the session information.
|
* @brief Configure the display device based on the user configuration and the session information.
|
||||||
* @note This is a convenience method for calling similar method of a different signature.
|
* @note This is a convenience method for calling similar method of a different signature.
|
||||||
@@ -119,7 +122,7 @@ namespace display_device {
|
|||||||
* const auto result = reset_persistence();
|
* const auto result = reset_persistence();
|
||||||
* @examples_end
|
* @examples_end
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] bool
|
bool
|
||||||
reset_persistence();
|
reset_persistence();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
158
src/process.cpp
158
src/process.cpp
@@ -163,9 +163,6 @@ namespace proc {
|
|||||||
// Ensure starting from a clean slate
|
// Ensure starting from a clean slate
|
||||||
terminate();
|
terminate();
|
||||||
|
|
||||||
// Save the original output name in case we modify it temporary later
|
|
||||||
std::string output_name_orig = config::video.output_name;
|
|
||||||
|
|
||||||
_app = app;
|
_app = app;
|
||||||
_app_id = app_id;
|
_app_id = app_id;
|
||||||
_launch_session = launch_session;
|
_launch_session = launch_session;
|
||||||
@@ -191,17 +188,19 @@ namespace proc {
|
|||||||
render_height &= ~1;
|
render_height &= ~1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
launch_session->width = render_width;
|
||||||
|
launch_session->height = render_height;
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
bool create_virtual_display = config::video.headless_mode || launch_session->virtual_display || _app.virtual_display;
|
bool create_virtual_display = config::video.headless_mode || launch_session->virtual_display || _app.virtual_display;
|
||||||
|
|
||||||
|
this->initial_display = config::video.output_name;
|
||||||
// Executed when returning from function
|
// Executed when returning from function
|
||||||
auto fg = util::fail_guard([&]() {
|
auto fg = util::fail_guard([&]() {
|
||||||
// Restore to user defined output name
|
// Restore to user defined output name
|
||||||
config::video.output_name = output_name_orig;
|
config::video.output_name = this->initial_display;
|
||||||
terminate();
|
terminate();
|
||||||
if (!create_virtual_display) {
|
display_device::revert_configuration();
|
||||||
display_device::revert_configuration();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (create_virtual_display) {
|
if (create_virtual_display) {
|
||||||
@@ -211,8 +210,6 @@ namespace proc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (vDisplayDriverStatus == VDISPLAY::DRIVER_STATUS::OK) {
|
if (vDisplayDriverStatus == VDISPLAY::DRIVER_STATUS::OK) {
|
||||||
std::wstring prevPrimaryDisplayName = VDISPLAY::getPrimaryDisplay();
|
|
||||||
|
|
||||||
// Try set the render adapter matching the capture adapter if user has specified one
|
// Try set the render adapter matching the capture adapter if user has specified one
|
||||||
if (!config::video.adapter_name.empty()) {
|
if (!config::video.adapter_name.empty()) {
|
||||||
VDISPLAY::setRenderAdapterByName(platf::from_utf8(config::video.adapter_name));
|
VDISPLAY::setRenderAdapterByName(platf::from_utf8(config::video.adapter_name));
|
||||||
@@ -236,69 +233,26 @@ namespace proc {
|
|||||||
|
|
||||||
BOOST_LOG(info) << "Virtual Display created at " << vdisplayName;
|
BOOST_LOG(info) << "Virtual Display created at " << vdisplayName;
|
||||||
|
|
||||||
std::wstring currentPrimaryDisplayName = VDISPLAY::getPrimaryDisplay();
|
|
||||||
|
|
||||||
// Don't change display settings when no params are given
|
// Don't change display settings when no params are given
|
||||||
if (launch_session->width && launch_session->height && launch_session->fps) {
|
if (launch_session->width && launch_session->height && launch_session->fps) {
|
||||||
// Apply display settings
|
// Apply display settings
|
||||||
VDISPLAY::changeDisplaySettings(vdisplayName.c_str(), render_width, render_height, launch_session->fps);
|
VDISPLAY::changeDisplaySettings(vdisplayName.c_str(), render_width, render_height, launch_session->fps);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool shouldActuallySetPrimary = false;
|
|
||||||
|
|
||||||
// Determine if we need to set the virtual display as primary
|
|
||||||
// Client request overrides local config
|
|
||||||
bool shouldSetVDisplayPrimary = launch_session->virtual_display;
|
|
||||||
if (!shouldSetVDisplayPrimary) {
|
|
||||||
// App config overrides global config
|
|
||||||
if (_app.virtual_display) {
|
|
||||||
shouldSetVDisplayPrimary = _app.virtual_display_primary;
|
|
||||||
} else {
|
|
||||||
shouldSetVDisplayPrimary = config::video.set_vdisplay_primary;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shouldSetVDisplayPrimary) {
|
|
||||||
shouldActuallySetPrimary = (currentPrimaryDisplayName != vdisplayName);
|
|
||||||
} else {
|
|
||||||
shouldActuallySetPrimary = (currentPrimaryDisplayName != prevPrimaryDisplayName);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set primary display if needed
|
|
||||||
if (shouldActuallySetPrimary) {
|
|
||||||
auto disp = shouldSetVDisplayPrimary ? vdisplayName : prevPrimaryDisplayName;
|
|
||||||
BOOST_LOG(info) << "Setting display " << disp << " primary";
|
|
||||||
|
|
||||||
if (!VDISPLAY::setPrimaryDisplay(disp.c_str())) {
|
|
||||||
BOOST_LOG(info) << "Setting display " << disp << " primary failed! Are you using Windows 11 24H2?";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set virtual_display to true when everything went fine
|
// Set virtual_display to true when everything went fine
|
||||||
this->virtual_display = true;
|
this->virtual_display = true;
|
||||||
this->display_name = platf::to_utf8(vdisplayName);
|
this->display_name = platf::to_utf8(vdisplayName);
|
||||||
|
|
||||||
if (config::video.headless_mode) {
|
// When using virtual display, we don't care which display user configured to use.
|
||||||
// When using headless mode, we don't care which display user configured to use.
|
// So we always set output_name to the newly created virtual display as a workaround for
|
||||||
// So we always set output_name to the newly created virtual display as a workaround for
|
// empty name when probing graphics cards.
|
||||||
// empty name when probing graphics cards.
|
|
||||||
config::video.output_name = this->display_name;
|
config::video.output_name = display_device::map_display_name(this->display_name);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
display_device::configure_display(config::video, *launch_session);
|
|
||||||
}
|
}
|
||||||
#else
|
#endif
|
||||||
// Executed when returning from function
|
|
||||||
auto fg = util::fail_guard([&]() {
|
|
||||||
// Restore to user defined output name
|
|
||||||
config::video.output_name = output_name_orig;
|
|
||||||
terminate();
|
|
||||||
display_device::revert_configuration();
|
|
||||||
});
|
|
||||||
|
|
||||||
display_device::configure_display(config::video, *launch_session);
|
display_device::configure_display(config::video, *launch_session);
|
||||||
#endif
|
|
||||||
|
|
||||||
// Probe encoders again before streaming to ensure our chosen
|
// Probe encoders again before streaming to ensure our chosen
|
||||||
// encoder matches the active GPU (which could have changed
|
// encoder matches the active GPU (which could have changed
|
||||||
@@ -420,60 +374,8 @@ namespace proc {
|
|||||||
|
|
||||||
_app_launch_time = std::chrono::steady_clock::now();
|
_app_launch_time = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
auto resetHDRThread = std::thread([this, enable_hdr = launch_session->enable_hdr]{
|
|
||||||
// Windows doesn't seem to be able to set HDR correctly when a display is just connected / changed resolution,
|
|
||||||
// so we have tooggle HDR for the virtual display manually after a delay.
|
|
||||||
auto retryInterval = 200ms;
|
|
||||||
while (is_changing_settings_going_to_fail()) {
|
|
||||||
if (retryInterval > 2s) {
|
|
||||||
BOOST_LOG(warning) << "Restoring HDR settings failed due to retry timeout!";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
std::this_thread::sleep_for(retryInterval);
|
|
||||||
retryInterval *= 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We should have got the actual streaming display by now
|
|
||||||
std::string currentDisplay = this->display_name;
|
|
||||||
if (currentDisplay.empty()) {
|
|
||||||
BOOST_LOG(warning) << "Not getting current display in time! HDR will not be toggled.";
|
|
||||||
} else {
|
|
||||||
auto currentDisplayW = platf::from_utf8(currentDisplay).c_str();
|
|
||||||
|
|
||||||
this->initial_display = currentDisplay;
|
|
||||||
this->initial_hdr = VDISPLAY::getDisplayHDRByName(currentDisplayW);
|
|
||||||
|
|
||||||
if (config::video.follow_client_hdr) {
|
|
||||||
if (!VDISPLAY::setDisplayHDRByName(currentDisplayW, false)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (enable_hdr) {
|
|
||||||
if (VDISPLAY::setDisplayHDRByName(currentDisplayW, true)) {
|
|
||||||
BOOST_LOG(info) << "HDR enabled for display " << currentDisplay;
|
|
||||||
} else {
|
|
||||||
BOOST_LOG(info) << "HDR enable failed for display " << currentDisplay;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (this->initial_hdr) {
|
|
||||||
if (VDISPLAY::setDisplayHDRByName(currentDisplayW, false) && VDISPLAY::setDisplayHDRByName(currentDisplayW, true)) {
|
|
||||||
BOOST_LOG(info) << "HDR toggled successfully for display " << currentDisplay;
|
|
||||||
} else {
|
|
||||||
BOOST_LOG(info) << "HDR toggle failed for display " << currentDisplay;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
resetHDRThread.detach();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
fg.disable();
|
fg.disable();
|
||||||
|
|
||||||
// Restore to user defined output name
|
|
||||||
config::video.output_name = output_name_orig;
|
|
||||||
|
|
||||||
#if defined SUNSHINE_TRAY && SUNSHINE_TRAY >= 1
|
#if defined SUNSHINE_TRAY && SUNSHINE_TRAY >= 1
|
||||||
system_tray::update_tray_playing(_app.name);
|
system_tray::update_tray_playing(_app.name);
|
||||||
#endif
|
#endif
|
||||||
@@ -561,36 +463,39 @@ namespace proc {
|
|||||||
|
|
||||||
_pipe.reset();
|
_pipe.reset();
|
||||||
|
|
||||||
#ifdef _WIN32
|
bool has_run = _app_id > 0;
|
||||||
if (config::video.follow_client_hdr && !this->initial_display.empty()) {
|
|
||||||
if (VDISPLAY::setDisplayHDRByName(platf::from_utf8(this->initial_display).c_str(), this->initial_hdr)) {
|
|
||||||
BOOST_LOG(info) << "HDR restored successfully for display " << this->initial_display;
|
|
||||||
} else {
|
|
||||||
BOOST_LOG(info) << "HDR restore failed for display " << this->initial_display;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vDisplayDriverStatus == VDISPLAY::DRIVER_STATUS::OK && _launch_session && this->virtual_display) {
|
#ifdef _WIN32
|
||||||
|
bool used_virtual_display = vDisplayDriverStatus == VDISPLAY::DRIVER_STATUS::OK && _launch_session && this->virtual_display;
|
||||||
|
if (used_virtual_display) {
|
||||||
if (VDISPLAY::removeVirtualDisplay(_launch_session->display_guid)) {
|
if (VDISPLAY::removeVirtualDisplay(_launch_session->display_guid)) {
|
||||||
BOOST_LOG(info) << "Virtual Display removed successfully";
|
BOOST_LOG(info) << "Virtual Display removed successfully";
|
||||||
} else {
|
} else {
|
||||||
BOOST_LOG(info) << "Virtual Display remove failed";
|
BOOST_LOG(info) << "Virtual Display remove failed";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
bool has_run = _app_id > 0;
|
|
||||||
|
|
||||||
// Only show the Stopped notification if we actually have an app to stop
|
// Only show the Stopped notification if we actually have an app to stop
|
||||||
// Since terminate() is always run when a new app has started
|
// Since terminate() is always run when a new app has started
|
||||||
if (proc::proc.get_last_run_app_name().length() > 0 && has_run) {
|
if (proc::proc.get_last_run_app_name().length() > 0 && has_run) {
|
||||||
|
if (used_virtual_display) {
|
||||||
|
display_device::reset_persistence();
|
||||||
|
} else {
|
||||||
|
display_device::revert_configuration();
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (proc::proc.get_last_run_app_name().length() > 0 && has_run) {
|
||||||
|
display_device::revert_configuration();
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined SUNSHINE_TRAY && SUNSHINE_TRAY >= 1
|
#if defined SUNSHINE_TRAY && SUNSHINE_TRAY >= 1
|
||||||
system_tray::update_tray_stopped(proc::proc.get_last_run_app_name());
|
system_tray::update_tray_stopped(proc::proc.get_last_run_app_name());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
display_device::revert_configuration();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Restore output name to its original value
|
||||||
|
config::video.output_name = initial_display;
|
||||||
|
|
||||||
_app_id = -1;
|
_app_id = -1;
|
||||||
display_name.clear();
|
display_name.clear();
|
||||||
initial_hdr = false;
|
initial_hdr = false;
|
||||||
@@ -937,7 +842,6 @@ namespace proc {
|
|||||||
auto wait_all = app_node.get_optional<bool>("wait-all"s);
|
auto wait_all = app_node.get_optional<bool>("wait-all"s);
|
||||||
auto exit_timeout = app_node.get_optional<int>("exit-timeout"s);
|
auto exit_timeout = app_node.get_optional<int>("exit-timeout"s);
|
||||||
auto virtual_display = app_node.get_optional<bool>("virtual-display"s);
|
auto virtual_display = app_node.get_optional<bool>("virtual-display"s);
|
||||||
auto virtual_display_primary = app_node.get_optional<bool>("virtual-display-primary"s);
|
|
||||||
auto resolution_scale_factor = app_node.get_optional<int>("scale-factor"s);
|
auto resolution_scale_factor = app_node.get_optional<int>("scale-factor"s);
|
||||||
auto use_app_identity = app_node.get_optional<bool>("use-app-identity"s);
|
auto use_app_identity = app_node.get_optional<bool>("use-app-identity"s);
|
||||||
|
|
||||||
@@ -1012,7 +916,6 @@ namespace proc {
|
|||||||
ctx.wait_all = wait_all.value_or(true);
|
ctx.wait_all = wait_all.value_or(true);
|
||||||
ctx.exit_timeout = std::chrono::seconds { exit_timeout.value_or(5) };
|
ctx.exit_timeout = std::chrono::seconds { exit_timeout.value_or(5) };
|
||||||
ctx.virtual_display = virtual_display.value_or(false);
|
ctx.virtual_display = virtual_display.value_or(false);
|
||||||
ctx.virtual_display_primary = virtual_display_primary.value_or(true);
|
|
||||||
ctx.scale_factor = resolution_scale_factor.value_or(100);
|
ctx.scale_factor = resolution_scale_factor.value_or(100);
|
||||||
ctx.use_app_identity = use_app_identity.value_or(false);
|
ctx.use_app_identity = use_app_identity.value_or(false);
|
||||||
|
|
||||||
@@ -1041,7 +944,6 @@ namespace proc {
|
|||||||
ctx.name = "Virtual Display";
|
ctx.name = "Virtual Display";
|
||||||
ctx.image_path = parse_env_val(this_env, "virtual_desktop.png");
|
ctx.image_path = parse_env_val(this_env, "virtual_desktop.png");
|
||||||
ctx.virtual_display = true;
|
ctx.virtual_display = true;
|
||||||
ctx.virtual_display_primary = true;
|
|
||||||
ctx.scale_factor = 100;
|
ctx.scale_factor = 100;
|
||||||
ctx.use_app_identity = false;
|
ctx.use_app_identity = false;
|
||||||
|
|
||||||
|
|||||||
@@ -277,16 +277,9 @@
|
|||||||
id="virtualDisplay"
|
id="virtualDisplay"
|
||||||
label="apps.virtual_display"
|
label="apps.virtual_display"
|
||||||
desc="apps.virtual_display_desc"
|
desc="apps.virtual_display_desc"
|
||||||
v-model="editForm['exclude-global-prep-cmd']"
|
v-model="editForm['virtual-display']"
|
||||||
default="false"
|
default="false"
|
||||||
></Checkbox>
|
></Checkbox>
|
||||||
<!-- set virtual display to primary -->
|
|
||||||
<div class="mb-3 form-check" v-if="platform === 'windows' && editForm['virtual-display'] == 'true'">
|
|
||||||
<label for="virtualDisplayPrimary" class="form-check-label">{{ $t('apps.virtual_display_primary') }}</label>
|
|
||||||
<input type="checkbox" class="form-check-input" id="virtualDisplayPrimary" v-model="editForm['virtual-display-primary']"
|
|
||||||
true-value="true" false-value="false" />
|
|
||||||
<div class="form-text">{{ $t('apps.virtual_display_primary_desc') }}</div>
|
|
||||||
</div>
|
|
||||||
<!-- use app identity -->
|
<!-- use app identity -->
|
||||||
<div class="mb-3 form-check">
|
<div class="mb-3 form-check">
|
||||||
<label for="useAppIdentity" class="form-check-label">{{ $t('apps.use_app_identity') }}</label>
|
<label for="useAppIdentity" class="form-check-label">{{ $t('apps.use_app_identity') }}</label>
|
||||||
@@ -414,7 +407,6 @@
|
|||||||
"prep-cmd": [],
|
"prep-cmd": [],
|
||||||
detached: [],
|
detached: [],
|
||||||
"image-path": "",
|
"image-path": "",
|
||||||
"virtual-display-primary": true,
|
|
||||||
"scale-factor": "100",
|
"scale-factor": "100",
|
||||||
"use-app-identity": false
|
"use-app-identity": false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -183,9 +183,7 @@
|
|||||||
"auto_capture_sink": "enabled",
|
"auto_capture_sink": "enabled",
|
||||||
"adapter_name": "",
|
"adapter_name": "",
|
||||||
"output_name": "",
|
"output_name": "",
|
||||||
"headless_mode": "disabled",
|
|
||||||
"fallback_mode": "",
|
"fallback_mode": "",
|
||||||
"set_vdisplay_primary": "enabled",
|
|
||||||
"dd_configuration_option": "verify_only",
|
"dd_configuration_option": "verify_only",
|
||||||
"dd_resolution_option": "auto",
|
"dd_resolution_option": "auto",
|
||||||
"dd_manual_resolution": "",
|
"dd_manual_resolution": "",
|
||||||
|
|||||||
@@ -125,23 +125,17 @@ const validateFallbackMode = (event) => {
|
|||||||
<!-- Fallback Display Mode -->
|
<!-- Fallback Display Mode -->
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="fallback_mode" class="form-label">{{ $t('config.fallback_mode') }}</label>
|
<label for="fallback_mode" class="form-label">{{ $t('config.fallback_mode') }}</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
class="form-control"
|
class="form-control"
|
||||||
id="fallback_mode"
|
id="fallback_mode"
|
||||||
v-model="config.fallback_mode"
|
v-model="config.fallback_mode"
|
||||||
placeholder="1920x1080x60"
|
placeholder="1920x1080x60"
|
||||||
@input="validateFallbackMode"
|
@input="validateFallbackMode"
|
||||||
/>
|
/>
|
||||||
<div class="form-text">{{ $t('config.fallback_mode_desc') }}</div>
|
<div class="form-text">{{ $t('config.fallback_mode_desc') }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-3 form-check" v-if="platform === 'windows'">
|
|
||||||
<input type="checkbox" class="form-check-input" id="follow_client_hdr" v-model="config.follow_client_hdr" true-value="enabled" false-value="disabled"/>
|
|
||||||
<label for="follow_client_hdr" class="form-check-label">{{ $t('config.follow_client_hdr') }}</label>
|
|
||||||
<div class="form-text pre-wrap">{{ $t('config.follow_client_hdr_desc') }}</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Headless Mode -->
|
<!-- Headless Mode -->
|
||||||
<div class="mb-3 form-check" v-if="platform === 'windows'">
|
<div class="mb-3 form-check" v-if="platform === 'windows'">
|
||||||
<input type="checkbox" class="form-check-input" id="headless_mode" v-model="config.headless_mode" true-value="enabled" false-value="disabled"/>
|
<input type="checkbox" class="form-check-input" id="headless_mode" v-model="config.headless_mode" true-value="enabled" false-value="disabled"/>
|
||||||
@@ -149,13 +143,6 @@ const validateFallbackMode = (event) => {
|
|||||||
<div class="form-text">{{ $t('config.headless_mode_desc') }}</div>
|
<div class="form-text">{{ $t('config.headless_mode_desc') }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Set VDisplay Primary -->
|
|
||||||
<div class="mb-3 form-check" v-if="platform === 'windows'">
|
|
||||||
<input type="checkbox" class="form-check-input" id="set_vdisplay_primary" v-model="config.set_vdisplay_primary" true-value="enabled" false-value="disabled"/>
|
|
||||||
<label for="set_vdisplay_primary" class="form-check-label">{{ $t('config.set_vdisplay_primary') }}</label>
|
|
||||||
<div class="form-text">{{ $t('config.set_vdisplay_primary_desc') }}</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- SudoVDA Driver Status -->
|
<!-- SudoVDA Driver Status -->
|
||||||
<div class="alert" :class="[vdisplay === '0' ? 'alert-success' : 'alert-warning']" v-if="platform === 'windows'">
|
<div class="alert" :class="[vdisplay === '0' ? 'alert-success' : 'alert-warning']" v-if="platform === 'windows'">
|
||||||
<i class="fa-solid fa-xl fa-circle-info"></i> SudoVDA Driver status: {{currentDriverStatus}}
|
<i class="fa-solid fa-xl fa-circle-info"></i> SudoVDA Driver status: {{currentDriverStatus}}
|
||||||
|
|||||||
@@ -55,12 +55,15 @@ function addRemappingEntry() {
|
|||||||
<h2 class="accordion-header">
|
<h2 class="accordion-header">
|
||||||
<button class="accordion-button" type="button" data-bs-toggle="collapse"
|
<button class="accordion-button" type="button" data-bs-toggle="collapse"
|
||||||
data-bs-target="#panelsStayOpen-collapseOne">
|
data-bs-target="#panelsStayOpen-collapseOne">
|
||||||
{{ $t('config.dd_options_header') }} {{ $t('dd_options_header_vdd_na') }}
|
{{ $t('config.dd_options_header') }}
|
||||||
</button>
|
</button>
|
||||||
</h2>
|
</h2>
|
||||||
<div id="panelsStayOpen-collapseOne" class="accordion-collapse collapse show"
|
<div id="panelsStayOpen-collapseOne" class="accordion-collapse collapse show"
|
||||||
aria-labelledby="panelsStayOpen-headingOne">
|
aria-labelledby="panelsStayOpen-headingOne">
|
||||||
<div class="accordion-body">
|
<div class="accordion-body">
|
||||||
|
<div class="alert alert-info" v-if="platform === 'windows'">
|
||||||
|
<i class="fa-solid fa-xl fa-circle-info"></i>{{ $t('config.dd_resolution_option_vdisplay_desc') }}
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Configuration option -->
|
<!-- Configuration option -->
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
|
|||||||
Reference in New Issue
Block a user