mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-04-02 03:31:28 +03:00
fix, change display resolution
Signed-off-by: dignow <linlong1265@gmail.com>
This commit is contained in:
@@ -5,6 +5,12 @@ use crate::virtual_display_manager;
|
||||
use hbb_common::get_version_number;
|
||||
use hbb_common::protobuf::MessageField;
|
||||
use scrap::Display;
|
||||
#[cfg(target_os = "linux")]
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
// https://github.com/rustdesk/rustdesk/discussions/6042, avoiding dbus call
|
||||
#[cfg(target_os = "linux")]
|
||||
pub(super) static IS_X11: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
pub const NAME: &'static str = "display";
|
||||
|
||||
@@ -19,6 +25,59 @@ lazy_static::lazy_static! {
|
||||
// Initial primary display index.
|
||||
// It should only be updated when the rustdesk server is started, and should not be updated when displays changed.
|
||||
pub static ref PRIMARY_DISPLAY_IDX: usize = get_primary();
|
||||
static ref SYNC_DISPLAYS: Arc<Mutex<SyncDisplaysInfo>> = Default::default();
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct SyncDisplaysInfo {
|
||||
displays: Vec<DisplayInfo>,
|
||||
is_synced: bool,
|
||||
}
|
||||
|
||||
impl SyncDisplaysInfo {
|
||||
fn check_changed(&mut self, displays: Vec<DisplayInfo>) {
|
||||
if self.displays.len() != displays.len() {
|
||||
self.displays = displays;
|
||||
self.is_synced = false;
|
||||
return;
|
||||
}
|
||||
for (i, d) in displays.iter().enumerate() {
|
||||
if d != &self.displays[i] {
|
||||
self.displays = displays;
|
||||
self.is_synced = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_update_sync_displays(&mut self) -> Option<Vec<DisplayInfo>> {
|
||||
if self.is_synced {
|
||||
return None;
|
||||
}
|
||||
self.is_synced = true;
|
||||
Some(self.displays.clone())
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn check_display_changed(
|
||||
idx: usize,
|
||||
(x, y, w, h): (i32, i32, usize, usize),
|
||||
) -> Option<DisplayInfo> {
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
// wayland do not support changing display for now
|
||||
if !IS_X11.load(Ordering::SeqCst) {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
let lock = SYNC_DISPLAYS.lock().unwrap();
|
||||
let d = lock.displays.get(idx)?;
|
||||
if !(d.x == x && d.y == y && d.width == w as i32 && d.height == h as i32) {
|
||||
Some(d.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -74,45 +133,27 @@ pub fn is_privacy_mode_supported() -> bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct StateDisplay {
|
||||
synced_displays: Vec<DisplayInfo>,
|
||||
}
|
||||
|
||||
impl super::service::Reset for StateDisplay {
|
||||
fn reset(&mut self) {
|
||||
self.synced_displays.clear();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new() -> GenericService {
|
||||
let svc = EmptyExtraFieldService::new(NAME.to_owned(), false);
|
||||
GenericService::repeat::<StateDisplay, _, _>(&svc.clone(), 300, run);
|
||||
let svc = EmptyExtraFieldService::new(NAME.to_owned(), true);
|
||||
GenericService::run(&svc.clone(), run);
|
||||
svc.sp
|
||||
}
|
||||
|
||||
fn check_get_displays_changed_msg(last_synced_displays: &mut Vec<DisplayInfo>) -> Option<Message> {
|
||||
let displays = try_get_displays().ok()?;
|
||||
if displays.len() == last_synced_displays.len() {
|
||||
return None;
|
||||
}
|
||||
fn displays_to_msg(displays: Vec<DisplayInfo>) -> Message {
|
||||
let mut pi = PeerInfo {
|
||||
..Default::default()
|
||||
};
|
||||
pi.displays = displays.clone();
|
||||
pi.current_display = 0;
|
||||
let mut msg_out = Message::new();
|
||||
msg_out.set_peer_info(pi);
|
||||
msg_out
|
||||
}
|
||||
|
||||
// Display to DisplayInfo
|
||||
let displays = to_display_info(&displays);
|
||||
if last_synced_displays.len() == 0 {
|
||||
*last_synced_displays = displays;
|
||||
None
|
||||
} else {
|
||||
let mut pi = PeerInfo {
|
||||
..Default::default()
|
||||
};
|
||||
pi.displays = displays.clone();
|
||||
pi.current_display = 0;
|
||||
let mut msg_out = Message::new();
|
||||
msg_out.set_peer_info(pi);
|
||||
*last_synced_displays = displays;
|
||||
Some(msg_out)
|
||||
}
|
||||
fn check_get_displays_changed_msg() -> Option<Message> {
|
||||
check_update_displays(try_get_displays().ok()?);
|
||||
let displays = SYNC_DISPLAYS.lock().unwrap().get_update_sync_displays()?;
|
||||
Some(displays_to_msg(displays))
|
||||
}
|
||||
|
||||
#[cfg(all(windows, feature = "virtual_display_driver"))]
|
||||
@@ -120,11 +161,28 @@ pub fn try_plug_out_virtual_display() {
|
||||
let _res = virtual_display_manager::plug_out_headless();
|
||||
}
|
||||
|
||||
fn run(sp: EmptyExtraFieldService, state: &mut StateDisplay) -> ResultType<()> {
|
||||
if let Some(msg_out) = check_get_displays_changed_msg(&mut state.synced_displays) {
|
||||
sp.send(msg_out);
|
||||
log::info!("Displays changed");
|
||||
fn run(sp: EmptyExtraFieldService) -> ResultType<()> {
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
IS_X11.store(scrap::is_x11(), Ordering::SeqCst);
|
||||
}
|
||||
|
||||
while sp.ok() {
|
||||
sp.snapshot(|sps| {
|
||||
if sps.has_subscribes() {
|
||||
SYNC_DISPLAYS.lock().unwrap().is_synced = false;
|
||||
bail!("new subscriber");
|
||||
}
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
if let Some(msg_out) = check_get_displays_changed_msg() {
|
||||
sp.send(msg_out);
|
||||
log::info!("Displays changed");
|
||||
}
|
||||
std::thread::sleep(Duration::from_millis(300));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -167,8 +225,11 @@ pub(super) fn get_original_resolution(
|
||||
.into()
|
||||
}
|
||||
|
||||
pub fn to_display_info(all: &Vec<Display>) -> Vec<DisplayInfo> {
|
||||
all.iter()
|
||||
// Display to DisplayInfo
|
||||
// The DisplayInfo is be sent to the peer.
|
||||
fn check_update_displays(all: Vec<Display>) {
|
||||
let displays = all
|
||||
.iter()
|
||||
.map(|d| {
|
||||
let display_name = d.name();
|
||||
let original_resolution = get_original_resolution(&display_name, d.width(), d.height());
|
||||
@@ -184,32 +245,34 @@ pub fn to_display_info(all: &Vec<Display>) -> Vec<DisplayInfo> {
|
||||
..Default::default()
|
||||
}
|
||||
})
|
||||
.collect::<Vec<DisplayInfo>>()
|
||||
.collect::<Vec<DisplayInfo>>();
|
||||
SYNC_DISPLAYS.lock().unwrap().check_changed(displays);
|
||||
}
|
||||
|
||||
pub fn is_inited_msg() -> Option<Message> {
|
||||
#[cfg(target_os = "linux")]
|
||||
if !scrap::is_x11() {
|
||||
if !IS_X11.load(Ordering::SeqCst) {
|
||||
return super::wayland::is_inited();
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub async fn get_displays() -> ResultType<Vec<DisplayInfo>> {
|
||||
pub async fn update_get_sync_displays() -> ResultType<Vec<DisplayInfo>> {
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
if !scrap::is_x11() {
|
||||
if !IS_X11.load(Ordering::SeqCst) {
|
||||
return super::wayland::get_displays().await;
|
||||
}
|
||||
}
|
||||
Ok(to_display_info(&try_get_displays()?))
|
||||
check_update_displays(try_get_displays()?);
|
||||
Ok(SYNC_DISPLAYS.lock().unwrap().displays.clone())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_primary() -> usize {
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
if !scrap::is_x11() {
|
||||
if !IS_X11.load(Ordering::SeqCst) {
|
||||
return match super::wayland::get_primary() {
|
||||
Ok(n) => n,
|
||||
Err(_) => 0,
|
||||
|
||||
Reference in New Issue
Block a user