fix: privacy mode 2, restore (#9141)

Signed-off-by: fufesou <linlong1266@gmail.com>
This commit is contained in:
fufesou 2024-08-22 09:35:50 +08:00 committed by GitHub
parent 529e70910d
commit fc607d6789
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 64 additions and 14 deletions

View File

@ -34,7 +34,7 @@ const CONFIG_KEY_REG_RECOVERY: &str = "reg_recovery";
struct Display { struct Display {
dm: DEVMODEW, dm: DEVMODEW,
name: [WCHAR; 32], name: [WCHAR; 32],
_primary: bool, primary: bool,
} }
pub struct PrivacyModeImpl { pub struct PrivacyModeImpl {
@ -135,7 +135,7 @@ impl PrivacyModeImpl {
let display = Display { let display = Display {
dm, dm,
name: dd.DeviceName, name: dd.DeviceName,
_primary: primary, primary,
}; };
let ds = virtual_display_manager::get_cur_device_string(); let ds = virtual_display_manager::get_cur_device_string();
@ -357,6 +357,35 @@ impl PrivacyModeImpl {
} }
Ok(()) Ok(())
} }
fn restore(&mut self) {
Self::restore_displays(&self.displays);
Self::restore_displays(&self.virtual_displays);
allow_err!(Self::commit_change_display(0));
self.restore_plug_out_monitor();
self.displays.clear();
self.virtual_displays.clear();
}
fn restore_displays(displays: &[Display]) {
for display in displays {
unsafe {
let mut dm = display.dm.clone();
let flags = if display.primary {
CDS_NORESET | CDS_UPDATEREGISTRY | CDS_SET_PRIMARY
} else {
CDS_NORESET | CDS_UPDATEREGISTRY
};
ChangeDisplaySettingsExW(
display.name.as_ptr(),
&mut dm,
std::ptr::null_mut(),
flags,
std::ptr::null_mut(),
);
}
}
}
} }
impl PrivacyMode for PrivacyModeImpl { impl PrivacyMode for PrivacyModeImpl {
@ -431,14 +460,9 @@ impl PrivacyMode for PrivacyModeImpl {
) -> ResultType<()> { ) -> ResultType<()> {
self.check_off_conn_id(conn_id)?; self.check_off_conn_id(conn_id)?;
super::win_input::unhook()?; super::win_input::unhook()?;
let virtual_display_added = self.virtual_displays_added.len() > 0; let _tmp_ignore_changed_holder = crate::display_service::temp_ignore_displays_changed();
if virtual_display_added { self.restore();
self.restore_plug_out_monitor();
}
restore_reg_connectivity(false); restore_reg_connectivity(false);
if !virtual_display_added {
Self::commit_change_display(CDS_RESET)?;
}
if self.conn_id != INVALID_PRIVACY_MODE_CONN_ID { if self.conn_id != INVALID_PRIVACY_MODE_CONN_ID {
if let Some(state) = state { if let Some(state) = state {

View File

@ -1,4 +1,5 @@
use super::*; use super::*;
use crate::common::SimpleCallOnReturn;
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
use crate::platform::linux::is_x11; use crate::platform::linux::is_x11;
#[cfg(windows)] #[cfg(windows)]
@ -7,6 +8,7 @@ use crate::virtual_display_manager;
use hbb_common::get_version_number; use hbb_common::get_version_number;
use hbb_common::protobuf::MessageField; use hbb_common::protobuf::MessageField;
use scrap::Display; use scrap::Display;
use std::sync::atomic::{AtomicBool, Ordering};
// https://github.com/rustdesk/rustdesk/discussions/6042, avoiding dbus call // https://github.com/rustdesk/rustdesk/discussions/6042, avoiding dbus call
@ -29,6 +31,9 @@ lazy_static::lazy_static! {
static ref SYNC_DISPLAYS: Arc<Mutex<SyncDisplaysInfo>> = Default::default(); static ref SYNC_DISPLAYS: Arc<Mutex<SyncDisplaysInfo>> = Default::default();
} }
// https://github.com/rustdesk/rustdesk/pull/8537
static TEMP_IGNORE_DISPLAYS_CHANGED: AtomicBool = AtomicBool::new(false);
#[derive(Default)] #[derive(Default)]
struct SyncDisplaysInfo { struct SyncDisplaysInfo {
displays: Vec<DisplayInfo>, displays: Vec<DisplayInfo>,
@ -39,13 +44,17 @@ impl SyncDisplaysInfo {
fn check_changed(&mut self, displays: Vec<DisplayInfo>) { fn check_changed(&mut self, displays: Vec<DisplayInfo>) {
if self.displays.len() != displays.len() { if self.displays.len() != displays.len() {
self.displays = displays; self.displays = displays;
self.is_synced = false; if !TEMP_IGNORE_DISPLAYS_CHANGED.load(Ordering::Relaxed) {
self.is_synced = false;
}
return; return;
} }
for (i, d) in displays.iter().enumerate() { for (i, d) in displays.iter().enumerate() {
if d != &self.displays[i] { if d != &self.displays[i] {
self.displays = displays; self.displays = displays;
self.is_synced = false; if !TEMP_IGNORE_DISPLAYS_CHANGED.load(Ordering::Relaxed) {
self.is_synced = false;
}
return; return;
} }
} }
@ -60,6 +69,21 @@ impl SyncDisplaysInfo {
} }
} }
pub fn temp_ignore_displays_changed() -> SimpleCallOnReturn {
TEMP_IGNORE_DISPLAYS_CHANGED.store(true, std::sync::atomic::Ordering::Relaxed);
SimpleCallOnReturn {
b: true,
f: Box::new(move || {
// Wait for a while to make sure check_display_changed() is called
// after video service has sending its `SwitchDisplay` message(`try_broadcast_display_changed()`).
std::thread::sleep(Duration::from_millis(1000));
TEMP_IGNORE_DISPLAYS_CHANGED.store(false, Ordering::Relaxed);
// Trigger the display changed message.
SYNC_DISPLAYS.lock().unwrap().is_synced = false;
}),
}
}
// This function is really useful, though a duplicate check if display changed. // This function is really useful, though a duplicate check if display changed.
// The video server will then send the following messages to the client: // The video server will then send the following messages to the client:
// 1. the supported resolutions of the {idx} display // 1. the supported resolutions of the {idx} display
@ -204,9 +228,11 @@ fn get_displays_msg() -> Option<Message> {
fn run(sp: EmptyExtraFieldService) -> ResultType<()> { fn run(sp: EmptyExtraFieldService) -> ResultType<()> {
while sp.ok() { while sp.ok() {
sp.snapshot(|sps| { sp.snapshot(|sps| {
if sps.has_subscribes() { if !TEMP_IGNORE_DISPLAYS_CHANGED.load(Ordering::Relaxed) {
SYNC_DISPLAYS.lock().unwrap().is_synced = false; if sps.has_subscribes() {
bail!("new subscriber"); SYNC_DISPLAYS.lock().unwrap().is_synced = false;
bail!("new subscriber");
}
} }
Ok(()) Ok(())
})?; })?;