mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-04-08 23:31:28 +03:00
fix, change display resolution
Signed-off-by: dignow <linlong1265@gmail.com>
This commit is contained in:
@@ -18,7 +18,11 @@
|
||||
// to-do:
|
||||
// https://slhck.info/video/2017/03/01/rate-control.html
|
||||
|
||||
use super::{service::ServiceTmpl, video_qos::VideoQoS, *};
|
||||
#[cfg(target_os = "linux")]
|
||||
use super::display_service::IS_X11;
|
||||
use super::{display_service::check_display_changed, service::ServiceTmpl, video_qos::VideoQoS, *};
|
||||
#[cfg(target_os = "linux")]
|
||||
use crate::common::SimpleCallOnReturn;
|
||||
#[cfg(windows)]
|
||||
use crate::{platform::windows::is_process_consent_running, privacy_win_mag};
|
||||
use hbb_common::{
|
||||
@@ -38,7 +42,7 @@ use scrap::{
|
||||
CodecName, Display, TraitCapturer,
|
||||
};
|
||||
#[cfg(target_os = "linux")]
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::atomic::Ordering;
|
||||
#[cfg(windows)]
|
||||
use std::sync::Once;
|
||||
use std::{
|
||||
@@ -49,7 +53,6 @@ use std::{
|
||||
};
|
||||
|
||||
pub const NAME: &'static str = "video";
|
||||
pub const OPTION_DISPLAY_CHANGED: &'static str = "changed";
|
||||
pub const OPTION_REFRESH: &'static str = "refresh";
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
@@ -63,10 +66,6 @@ lazy_static::lazy_static! {
|
||||
pub static ref IS_FOREGROUND_WINDOW_ELEVATED: Arc<Mutex<bool>> = Default::default();
|
||||
}
|
||||
|
||||
// https://github.com/rustdesk/rustdesk/discussions/6042, avoiding dbus call
|
||||
#[cfg(target_os = "linux")]
|
||||
static IS_X11: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
#[inline]
|
||||
pub fn notify_video_frame_fetched(conn_id: i32, frame_tm: Option<Instant>) {
|
||||
FRAME_FETCHED_NOTIFIER.0.send((conn_id, frame_tm)).ok();
|
||||
@@ -165,35 +164,6 @@ pub fn new(idx: usize) -> GenericService {
|
||||
vs.sp
|
||||
}
|
||||
|
||||
fn check_display_changed(
|
||||
last_n: usize,
|
||||
last_current: usize,
|
||||
last_width: usize,
|
||||
last_height: usize,
|
||||
) -> bool {
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
// wayland do not support changing display for now
|
||||
if !IS_X11.load(Ordering::SeqCst) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
let displays = match try_get_displays() {
|
||||
Ok(d) => d,
|
||||
_ => return false,
|
||||
};
|
||||
|
||||
let n = displays.len();
|
||||
if n != last_n {
|
||||
return true;
|
||||
};
|
||||
match displays.get(last_current) {
|
||||
Some(d) => d.width() != last_width || d.height() != last_height,
|
||||
None => true,
|
||||
}
|
||||
}
|
||||
|
||||
// Capturer object is expensive, avoiding to create it frequently.
|
||||
fn create_capturer(
|
||||
privacy_mode_id: i32,
|
||||
@@ -327,7 +297,6 @@ pub(super) struct CapturerInfo {
|
||||
pub origin: (i32, i32),
|
||||
pub width: usize,
|
||||
pub height: usize,
|
||||
pub ndisplay: usize,
|
||||
pub current: usize,
|
||||
pub privacy_mode_id: i32,
|
||||
pub _capturer_privacy_mode_id: i32,
|
||||
@@ -419,7 +388,6 @@ fn get_capturer(
|
||||
origin,
|
||||
width,
|
||||
height,
|
||||
ndisplay,
|
||||
current,
|
||||
privacy_mode_id,
|
||||
_capturer_privacy_mode_id: capturer_privacy_mode_id,
|
||||
@@ -431,16 +399,21 @@ fn run(vs: VideoService) -> ResultType<()> {
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
let _wake_lock = get_wake_lock();
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
IS_X11.store(scrap::is_x11(), Ordering::SeqCst);
|
||||
}
|
||||
|
||||
// Wayland only support one video capturer for now. It is ok to call ensure_inited() here.
|
||||
//
|
||||
// ensure_inited() is needed because clear() may be called.
|
||||
// to-do: wayland ensure_inited should pass current display index.
|
||||
// But for now, we do not support multi-screen capture on wayland.
|
||||
#[cfg(target_os = "linux")]
|
||||
super::wayland::ensure_inited()?;
|
||||
#[cfg(target_os = "linux")]
|
||||
let wayland_call_on_ret = SimpleCallOnReturn {
|
||||
b: true,
|
||||
f: Box::new(|| {
|
||||
super::wayland::clear();
|
||||
}),
|
||||
};
|
||||
|
||||
#[cfg(windows)]
|
||||
let last_portable_service_running = crate::portable_service::client::running();
|
||||
#[cfg(not(windows))]
|
||||
@@ -471,16 +444,6 @@ fn run(vs: VideoService) -> ResultType<()> {
|
||||
c.set_use_yuv(encoder.use_yuv());
|
||||
VIDEO_QOS.lock().unwrap().store_bitrate(encoder.bitrate());
|
||||
|
||||
if sp.is_option_true(OPTION_DISPLAY_CHANGED) {
|
||||
log::debug!("Broadcasting display changed");
|
||||
broadcast_display_changed(
|
||||
display_idx,
|
||||
&sp,
|
||||
Some((c.name.clone(), c.origin.clone(), c.width, c.height)),
|
||||
);
|
||||
sp.set_option_bool(OPTION_DISPLAY_CHANGED, false);
|
||||
}
|
||||
|
||||
if sp.is_option_true(OPTION_REFRESH) {
|
||||
sp.set_option_bool(OPTION_REFRESH, false);
|
||||
}
|
||||
@@ -518,7 +481,7 @@ fn run(vs: VideoService) -> ResultType<()> {
|
||||
}
|
||||
drop(video_qos);
|
||||
|
||||
if sp.is_option_true(OPTION_DISPLAY_CHANGED) || sp.is_option_true(OPTION_REFRESH) {
|
||||
if sp.is_option_true(OPTION_REFRESH) {
|
||||
bail!("SWITCH");
|
||||
}
|
||||
if codec_name != Encoder::negotiated_codec() {
|
||||
@@ -540,12 +503,11 @@ fn run(vs: VideoService) -> ResultType<()> {
|
||||
let now = time::Instant::now();
|
||||
if last_check_displays.elapsed().as_millis() > 1000 {
|
||||
last_check_displays = now;
|
||||
|
||||
// Capturer on macos does not return Err event the solution is changed.
|
||||
#[cfg(target_os = "macos")]
|
||||
if check_display_changed(c.ndisplay, c.current, c.width, c.height) {
|
||||
sp.set_option_bool(OPTION_DISPLAY_CHANGED, true);
|
||||
log::info!("Displays changed");
|
||||
if let Some(display) =
|
||||
check_display_changed(c.current, (c.origin.0, c.origin.1, c.width, c.height))
|
||||
{
|
||||
log::info!("Display {} changed", display);
|
||||
broadcast_display_changed(display_idx, &sp, &c.name, display);
|
||||
bail!("SWITCH");
|
||||
}
|
||||
}
|
||||
@@ -624,21 +586,12 @@ fn run(vs: VideoService) -> ResultType<()> {
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
if check_display_changed(c.ndisplay, c.current, c.width, c.height) {
|
||||
log::info!("Displays changed");
|
||||
#[cfg(target_os = "linux")]
|
||||
super::wayland::clear();
|
||||
sp.set_option_bool(OPTION_DISPLAY_CHANGED, true);
|
||||
bail!("SWITCH");
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
if !c.is_gdi() {
|
||||
c.set_gdi();
|
||||
log::info!("dxgi error, fall back to gdi: {:?}", err);
|
||||
continue;
|
||||
}
|
||||
|
||||
return Err(err.into());
|
||||
}
|
||||
_ => {
|
||||
@@ -671,9 +624,6 @@ fn run(vs: VideoService) -> ResultType<()> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
super::wayland::clear();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -892,9 +842,10 @@ fn get_wake_lock() -> crate::platform::WakeLock {
|
||||
fn broadcast_display_changed(
|
||||
display_idx: usize,
|
||||
sp: &GenericService,
|
||||
display_meta: Option<(String, (i32, i32), usize, usize)>,
|
||||
name: &str,
|
||||
display: DisplayInfo,
|
||||
) {
|
||||
if let Some(msg_out) = make_display_changed_msg(display_idx, display_meta) {
|
||||
if let Some(msg_out) = make_display_changed_msg(display_idx, name, display) {
|
||||
sp.send(msg_out);
|
||||
}
|
||||
}
|
||||
@@ -913,34 +864,30 @@ fn get_display_info_simple_meta(display_idx: usize) -> Option<(String, (i32, i32
|
||||
}
|
||||
}
|
||||
|
||||
pub fn make_display_changed_msg(
|
||||
fn make_display_changed_msg(
|
||||
display_idx: usize,
|
||||
display_meta: Option<(String, (i32, i32), usize, usize)>,
|
||||
name: &str,
|
||||
display: DisplayInfo,
|
||||
) -> Option<Message> {
|
||||
let mut misc = Misc::new();
|
||||
let (name, origin, width, height) = match display_meta {
|
||||
Some(d) => d,
|
||||
None => get_display_info_simple_meta(display_idx)?,
|
||||
};
|
||||
let original_resolution = display_service::get_original_resolution(&name, width, height);
|
||||
misc.set_switch_display(SwitchDisplay {
|
||||
display: display_idx as _,
|
||||
x: origin.0,
|
||||
y: origin.1,
|
||||
width: width as _,
|
||||
height: height as _,
|
||||
x: display.x,
|
||||
y: display.y,
|
||||
width: display.width,
|
||||
height: display.height,
|
||||
cursor_embedded: display_service::capture_cursor_embedded(),
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
resolutions: Some(SupportedResolutions {
|
||||
resolutions: if name.is_empty() {
|
||||
vec![]
|
||||
} else {
|
||||
crate::platform::resolutions(&name)
|
||||
crate::platform::resolutions(name)
|
||||
},
|
||||
..SupportedResolutions::default()
|
||||
})
|
||||
.into(),
|
||||
original_resolution,
|
||||
original_resolution: display.original_resolution,
|
||||
..Default::default()
|
||||
});
|
||||
let mut msg_out = Message::new();
|
||||
|
||||
Reference in New Issue
Block a user