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 {
dm: DEVMODEW,
name: [WCHAR; 32],
_primary: bool,
primary: bool,
}
pub struct PrivacyModeImpl {
@ -135,7 +135,7 @@ impl PrivacyModeImpl {
let display = Display {
dm,
name: dd.DeviceName,
_primary: primary,
primary,
};
let ds = virtual_display_manager::get_cur_device_string();
@ -357,6 +357,35 @@ impl PrivacyModeImpl {
}
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 {
@ -431,14 +460,9 @@ impl PrivacyMode for PrivacyModeImpl {
) -> ResultType<()> {
self.check_off_conn_id(conn_id)?;
super::win_input::unhook()?;
let virtual_display_added = self.virtual_displays_added.len() > 0;
if virtual_display_added {
self.restore_plug_out_monitor();
}
let _tmp_ignore_changed_holder = crate::display_service::temp_ignore_displays_changed();
self.restore();
restore_reg_connectivity(false);
if !virtual_display_added {
Self::commit_change_display(CDS_RESET)?;
}
if self.conn_id != INVALID_PRIVACY_MODE_CONN_ID {
if let Some(state) = state {

View File

@ -1,4 +1,5 @@
use super::*;
use crate::common::SimpleCallOnReturn;
#[cfg(target_os = "linux")]
use crate::platform::linux::is_x11;
#[cfg(windows)]
@ -7,6 +8,7 @@ use crate::virtual_display_manager;
use hbb_common::get_version_number;
use hbb_common::protobuf::MessageField;
use scrap::Display;
use std::sync::atomic::{AtomicBool, Ordering};
// 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();
}
// https://github.com/rustdesk/rustdesk/pull/8537
static TEMP_IGNORE_DISPLAYS_CHANGED: AtomicBool = AtomicBool::new(false);
#[derive(Default)]
struct SyncDisplaysInfo {
displays: Vec<DisplayInfo>,
@ -39,13 +44,17 @@ impl SyncDisplaysInfo {
fn check_changed(&mut self, displays: Vec<DisplayInfo>) {
if self.displays.len() != displays.len() {
self.displays = displays;
self.is_synced = false;
if !TEMP_IGNORE_DISPLAYS_CHANGED.load(Ordering::Relaxed) {
self.is_synced = false;
}
return;
}
for (i, d) in displays.iter().enumerate() {
if d != &self.displays[i] {
self.displays = displays;
self.is_synced = false;
if !TEMP_IGNORE_DISPLAYS_CHANGED.load(Ordering::Relaxed) {
self.is_synced = false;
}
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.
// The video server will then send the following messages to the client:
// 1. the supported resolutions of the {idx} display
@ -204,9 +228,11 @@ fn get_displays_msg() -> Option<Message> {
fn run(sp: EmptyExtraFieldService) -> ResultType<()> {
while sp.ok() {
sp.snapshot(|sps| {
if sps.has_subscribes() {
SYNC_DISPLAYS.lock().unwrap().is_synced = false;
bail!("new subscriber");
if !TEMP_IGNORE_DISPLAYS_CHANGED.load(Ordering::Relaxed) {
if sps.has_subscribes() {
SYNC_DISPLAYS.lock().unwrap().is_synced = false;
bail!("new subscriber");
}
}
Ok(())
})?;