mirror of
https://github.com/kunkundi/crossdesk.git
synced 2026-10-19 02:13:03 +08:00
[feat] add Windows screen capture method setting
This commit is contained in:
@@ -58,6 +58,14 @@ int ConfigCenter::Load() {
|
||||
video_frame_rate_ = static_cast<VIDEO_FRAME_RATE>(ini_.GetLongValue(
|
||||
section_, "video_frame_rate", static_cast<long>(video_frame_rate_)));
|
||||
|
||||
const long screen_capture_method_value = ini_.GetLongValue(
|
||||
section_, "screen_capture_method",
|
||||
static_cast<long>(ScreenCaptureMethod::Auto));
|
||||
screen_capture_method_ = IsValidScreenCaptureMethod(screen_capture_method_value)
|
||||
? static_cast<ScreenCaptureMethod>(
|
||||
screen_capture_method_value)
|
||||
: ScreenCaptureMethod::Auto;
|
||||
|
||||
const long video_adaptation_policy_value = ini_.GetLongValue(
|
||||
section_, "video_adaptation_policy",
|
||||
static_cast<long>(video_adaptation_policy_));
|
||||
@@ -147,6 +155,8 @@ int ConfigCenter::Save() {
|
||||
static_cast<long>(video_quality_));
|
||||
ini_.SetLongValue(section_, "video_frame_rate",
|
||||
static_cast<long>(video_frame_rate_));
|
||||
ini_.SetLongValue(section_, "screen_capture_method",
|
||||
static_cast<long>(screen_capture_method_));
|
||||
ini_.SetLongValue(section_, "video_adaptation_policy",
|
||||
static_cast<long>(video_adaptation_policy_));
|
||||
ini_.SetLongValue(section_, "video_encode_format",
|
||||
@@ -217,6 +227,20 @@ int ConfigCenter::SetVideoFrameRate(VIDEO_FRAME_RATE video_frame_rate) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ConfigCenter::SetScreenCaptureMethod(ScreenCaptureMethod method) {
|
||||
if (!IsValidScreenCaptureMethod(static_cast<long>(method))) {
|
||||
return -1;
|
||||
}
|
||||
ini_.SetLongValue(section_, "screen_capture_method", static_cast<long>(method));
|
||||
if (ini_.SaveFile(config_path_.c_str()) < 0) {
|
||||
ini_.SetLongValue(section_, "screen_capture_method",
|
||||
static_cast<long>(screen_capture_method_));
|
||||
return -1;
|
||||
}
|
||||
screen_capture_method_ = method;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ConfigCenter::SetVideoAdaptationPolicy(
|
||||
VIDEO_ADAPTATION_POLICY policy) {
|
||||
video_adaptation_policy_ = policy;
|
||||
@@ -413,6 +437,10 @@ ConfigCenter::VIDEO_FRAME_RATE ConfigCenter::GetVideoFrameRate() const {
|
||||
return video_frame_rate_;
|
||||
}
|
||||
|
||||
ScreenCaptureMethod ConfigCenter::GetScreenCaptureMethod() const {
|
||||
return screen_capture_method_;
|
||||
}
|
||||
|
||||
ConfigCenter::VIDEO_ADAPTATION_POLICY
|
||||
ConfigCenter::GetVideoAdaptationPolicy() const {
|
||||
return video_adaptation_policy_;
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <string>
|
||||
|
||||
#include "SimpleIni.h"
|
||||
#include "screen_capturer/screen_capture_method.h"
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
@@ -40,6 +41,7 @@ class ConfigCenter {
|
||||
int SetLanguage(LANGUAGE language);
|
||||
int SetVideoQuality(VIDEO_QUALITY video_quality);
|
||||
int SetVideoFrameRate(VIDEO_FRAME_RATE video_frame_rate);
|
||||
int SetScreenCaptureMethod(ScreenCaptureMethod method);
|
||||
int SetVideoAdaptationPolicy(VIDEO_ADAPTATION_POLICY policy);
|
||||
int SetVideoEncodeFormat(VIDEO_ENCODE_FORMAT video_encode_format);
|
||||
int SetHardwareVideoCodec(bool hardware_video_codec);
|
||||
@@ -60,6 +62,7 @@ class ConfigCenter {
|
||||
LANGUAGE GetLanguage() const;
|
||||
VIDEO_QUALITY GetVideoQuality() const;
|
||||
VIDEO_FRAME_RATE GetVideoFrameRate() const;
|
||||
ScreenCaptureMethod GetScreenCaptureMethod() const;
|
||||
VIDEO_ADAPTATION_POLICY GetVideoAdaptationPolicy() const;
|
||||
VIDEO_ENCODE_FORMAT GetVideoEncodeFormat() const;
|
||||
bool IsHardwareVideoCodec() const;
|
||||
@@ -88,6 +91,7 @@ class ConfigCenter {
|
||||
LANGUAGE language_ = LANGUAGE::CHINESE;
|
||||
VIDEO_QUALITY video_quality_ = VIDEO_QUALITY::HIGH;
|
||||
VIDEO_FRAME_RATE video_frame_rate_ = VIDEO_FRAME_RATE::FPS_60;
|
||||
ScreenCaptureMethod screen_capture_method_ = ScreenCaptureMethod::Auto;
|
||||
VIDEO_ADAPTATION_POLICY video_adaptation_policy_ =
|
||||
VIDEO_ADAPTATION_POLICY::QUALITY_PRIORITY;
|
||||
VIDEO_ENCODE_FORMAT video_encode_format_ = VIDEO_ENCODE_FORMAT::H264;
|
||||
|
||||
@@ -1231,6 +1231,9 @@ void GuiApplication::ResetSettingsUi() {
|
||||
ui_->main->set_autostart_enabled(enable_autostart_);
|
||||
ui_->main->set_daemon_enabled(enable_daemon_);
|
||||
#ifdef _WIN32
|
||||
ui_->main->set_capture_method_visible(true);
|
||||
ui_->main->set_capture_method_index(
|
||||
static_cast<int>(config_center_->GetScreenCaptureMethod()));
|
||||
ui_->main->set_privacy_setting_visible(true);
|
||||
ui_->main->set_privacy_on_connect_enabled(
|
||||
config_center_->IsEnablePrivacyScreen());
|
||||
@@ -3008,6 +3011,15 @@ void GuiApplication::SaveSettingsFromUi() {
|
||||
config_center_->SetAutostart(enable_autostart_);
|
||||
config_center_->SetDaemon(enable_daemon_);
|
||||
#ifdef _WIN32
|
||||
if (!HasActiveSession()) {
|
||||
const auto capture_method = static_cast<ScreenCaptureMethod>(
|
||||
std::clamp(main->get_capture_method_index(), 0, 3));
|
||||
if (config_center_->SetScreenCaptureMethod(capture_method) != 0) {
|
||||
LOG_ERROR("Failed to save screen capture method");
|
||||
}
|
||||
}
|
||||
main->set_capture_method_index(
|
||||
static_cast<int>(config_center_->GetScreenCaptureMethod()));
|
||||
if (config_center_->SetPrivacyScreen(main->get_privacy_on_connect_enabled()) !=
|
||||
0) {
|
||||
main->set_privacy_on_connect_enabled(
|
||||
|
||||
@@ -127,6 +127,9 @@ struct TranslationRow {
|
||||
u8"стола") \
|
||||
X(settings, u8"设置", "Settings", u8"Настройки") \
|
||||
X(language, u8"语言:", "Language:", u8"Язык:") \
|
||||
X(screen_capture_method, u8"采集方式:", "Capture Method:", \
|
||||
u8"Способ захвата:") \
|
||||
X(screen_capture_method_auto, u8"自动", "Auto", u8"Авто") \
|
||||
X(video_quality, u8"画面质量:", "Video Quality:", u8"Качество видео:") \
|
||||
X(video_frame_rate, u8"画面采集帧率:", \
|
||||
"Video Capture Frame Rate:", u8"Частота захвата видео:") \
|
||||
|
||||
@@ -78,11 +78,13 @@ int SessionDeviceManager::InitializeScreenCapturer() {
|
||||
if (!screen_capturer_) {
|
||||
screen_capturer_ =
|
||||
static_cast<ScreenCapturer *>(screen_capturer_factory_->Create());
|
||||
#ifdef _WIN32
|
||||
if (auto windows = dynamic_cast<ScreenCapturerWin*>(screen_capturer_))
|
||||
windows->SetPrivacyController(&owner_.privacy_);
|
||||
#endif
|
||||
}
|
||||
#ifdef _WIN32
|
||||
if (auto windows = dynamic_cast<ScreenCapturerWin*>(screen_capturer_)) {
|
||||
windows->SetPrivacyController(&owner_.privacy_);
|
||||
windows->SetCaptureMethod(owner_.config_center_->GetScreenCaptureMethod());
|
||||
}
|
||||
#endif
|
||||
|
||||
last_frame_time_ = {};
|
||||
next_frame_deadline_ = {};
|
||||
|
||||
@@ -39,6 +39,8 @@ export global UiStrings {
|
||||
in-out property <string> language: "Language";
|
||||
in-out property <string> video-quality: "Video quality";
|
||||
in-out property <string> frame-rate: "Frame rate";
|
||||
in-out property <string> capture-method: "Capture method";
|
||||
in-out property <string> capture-method-auto: "Auto";
|
||||
in-out property <string> adaptation-policy: "Video preference";
|
||||
in-out property <string> priority-frame-rate: "Frame rate";
|
||||
in-out property <string> priority-quality: "Quality";
|
||||
@@ -239,6 +241,8 @@ export component MainWindow inherits Window {
|
||||
in-out property <int> language-index: 0;
|
||||
in-out property <int> video-quality-index: 2;
|
||||
in-out property <int> frame-rate-index: 1;
|
||||
in property <bool> capture-method-visible: false;
|
||||
in-out property <int> capture-method-index: 0;
|
||||
in-out property <int> adaptation-policy-index: 1;
|
||||
in-out property <int> codec-index: 0;
|
||||
in-out property <bool> hardware-codec-enabled: true;
|
||||
@@ -1448,6 +1452,11 @@ export component MainWindow inherits Window {
|
||||
Text { x: 8px; y: 3px; width: root.compact-language ? 94px : 162px; height: 24px; text: UiStrings.language; font-size: ImGuiFontStyle.body; overflow: elide; vertical-alignment: center; }
|
||||
CompactComboBox { x: root.compact-language ? 106px : 174px; y: 2px; model: ["中文", "English", "Русский"]; current-index <=> root.language-index; }
|
||||
}
|
||||
if root.capture-method-visible: Rectangle {
|
||||
height: 30px;
|
||||
Text { x: 8px; y: 3px; width: root.compact-language ? 94px : 162px; height: 24px; text: UiStrings.capture-method; font-size: ImGuiFontStyle.body; overflow: elide; vertical-alignment: center; }
|
||||
CompactComboBox { x: root.compact-language ? 106px : 174px; y: 2px; enabled: !root.settings-session-active; model: [UiStrings.capture-method-auto, "DXGI", "WGC", "GDI"]; current-index <=> root.capture-method-index; }
|
||||
}
|
||||
if root.privacy-setting-visible: Rectangle {
|
||||
height: 30px;
|
||||
Text { x: 8px; y: 3px; width: root.compact-language ? 145px : 212px; height: 24px; text: UiStrings.privacy-on-connect; font-size: ImGuiFontStyle.body; overflow: elide; vertical-alignment: center; }
|
||||
|
||||
@@ -54,6 +54,9 @@ inline int ApplyMainWindowStrings(
|
||||
strings.set_language(Text(localization::language[language]));
|
||||
strings.set_video_quality(Text(localization::video_quality[language]));
|
||||
strings.set_frame_rate(Text(localization::video_frame_rate[language]));
|
||||
strings.set_capture_method(Text(localization::screen_capture_method[language]));
|
||||
strings.set_capture_method_auto(
|
||||
Text(localization::screen_capture_method_auto[language]));
|
||||
strings.set_adaptation_policy(
|
||||
Text(localization::video_adaptation_policy[language]));
|
||||
strings.set_priority_frame_rate(
|
||||
|
||||
@@ -439,9 +439,12 @@ int ScreenCapturerWin::Init(const int fps, cb_desktop_data cb) {
|
||||
return true;
|
||||
};
|
||||
// Short-circuiting also keeps the unused WGC plugin unloaded.
|
||||
if (try_init(std::make_unique<ScreenCapturerDxgi>()) ||
|
||||
try_init(WgcPluginCapturer::Create()) ||
|
||||
try_init(std::make_unique<ScreenCapturerGdi>())) {
|
||||
if ((IsBackendEnabled(ScreenCaptureMethod::Dxgi) &&
|
||||
try_init(std::make_unique<ScreenCapturerDxgi>())) ||
|
||||
(IsBackendEnabled(ScreenCaptureMethod::Wgc) &&
|
||||
try_init(WgcPluginCapturer::Create())) ||
|
||||
(IsBackendEnabled(ScreenCaptureMethod::Gdi) &&
|
||||
try_init(std::make_unique<ScreenCapturerGdi>()))) {
|
||||
LOG_INFO("Windows capturer: using {}", CaptureBackendName(impl_.get()));
|
||||
BuildCanonicalFromImpl();
|
||||
monitor_index_.store(0, std::memory_order_relaxed);
|
||||
@@ -449,7 +452,8 @@ int ScreenCapturerWin::Init(const int fps, cb_desktop_data cb) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOG_ERROR("Windows capturer: all implementations failed, ret={}", ret);
|
||||
LOG_ERROR("Windows capturer: selected capture method {} failed, ret={}",
|
||||
static_cast<int>(capture_method_), ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -576,6 +580,11 @@ int ScreenCapturerWin::Start(bool show_cursor) {
|
||||
}
|
||||
}
|
||||
if (ret != 0) {
|
||||
if (capture_method_ != ScreenCaptureMethod::Auto) {
|
||||
LOG_ERROR("Windows capturer: selected backend {} failed to start (ret={})",
|
||||
CaptureBackendName(impl_.get()), ret);
|
||||
return ret;
|
||||
}
|
||||
LOG_WARN("Windows capturer: refresh/start failed (ret={}), trying fallback",
|
||||
ret);
|
||||
|
||||
@@ -799,10 +808,12 @@ bool ScreenCapturerWin::RestartCaptureBackendAfterSecureDesktop() {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (TryStartBackend(std::make_unique<ScreenCapturerDxgi>(),
|
||||
current_monitor) ||
|
||||
TryStartBackend(WgcPluginCapturer::Create(), current_monitor) ||
|
||||
TryStartBackend(std::make_unique<ScreenCapturerGdi>(), current_monitor)) {
|
||||
if ((IsBackendEnabled(ScreenCaptureMethod::Dxgi) &&
|
||||
TryStartBackend(std::make_unique<ScreenCapturerDxgi>(), current_monitor)) ||
|
||||
(IsBackendEnabled(ScreenCaptureMethod::Wgc) &&
|
||||
TryStartBackend(WgcPluginCapturer::Create(), current_monitor)) ||
|
||||
(IsBackendEnabled(ScreenCaptureMethod::Gdi) &&
|
||||
TryStartBackend(std::make_unique<ScreenCapturerGdi>(), current_monitor))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "screen_capturer.h"
|
||||
#include "screen_capture_method.h"
|
||||
#include "privacy_controller.h"
|
||||
|
||||
namespace crossdesk {
|
||||
@@ -45,9 +46,16 @@ class ScreenCapturerWin : public ScreenCapturer {
|
||||
|
||||
std::vector<DisplayInfo> GetDisplayInfoList() override;
|
||||
void SetPrivacyController(PrivacyController* privacy) { privacy_ = privacy; }
|
||||
// Set before Init(), while capture is stopped.
|
||||
void SetCaptureMethod(ScreenCaptureMethod method) { capture_method_ = method; }
|
||||
|
||||
private:
|
||||
std::unique_ptr<ScreenCapturer> impl_;
|
||||
ScreenCaptureMethod capture_method_ = ScreenCaptureMethod::Auto;
|
||||
bool IsBackendEnabled(ScreenCaptureMethod method) const {
|
||||
return capture_method_ == ScreenCaptureMethod::Auto ||
|
||||
capture_method_ == method;
|
||||
}
|
||||
PrivacyController* privacy_ = nullptr;
|
||||
void NotifyPrivacyCapture(bool running);
|
||||
int fps_ = 60;
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* @Author: DI JUNKUN
|
||||
* @Date: 2026-09-11
|
||||
* Copyright (c) 2026 by DI JUNKUN, All Rights Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _SCREEN_CAPTURE_METHOD_H_
|
||||
#define _SCREEN_CAPTURE_METHOD_H_
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
// Persisted values; keep these in the same order as the settings choices.
|
||||
enum class ScreenCaptureMethod { Auto = 0, Dxgi = 1, Wgc = 2, Gdi = 3 };
|
||||
|
||||
inline bool IsValidScreenCaptureMethod(long value) {
|
||||
return value >= static_cast<long>(ScreenCaptureMethod::Auto) &&
|
||||
value <= static_cast<long>(ScreenCaptureMethod::Gdi);
|
||||
}
|
||||
|
||||
} // namespace crossdesk
|
||||
|
||||
#endif
|
||||
@@ -298,7 +298,8 @@ function setup_targets()
|
||||
set_kind("object")
|
||||
add_deps("rd_log", "autostart")
|
||||
add_files("apps/desktop/src/config_center/*.cpp")
|
||||
add_includedirs("apps/desktop/src/config_center", {public = true})
|
||||
add_includedirs("apps/desktop/src", "apps/desktop/src/config_center",
|
||||
{public = true})
|
||||
|
||||
target("assets")
|
||||
set_kind("headeronly")
|
||||
|
||||
Reference in New Issue
Block a user