fix: privacy mode 2, restore (#9141)
Signed-off-by: fufesou <linlong1266@gmail.com>
This commit is contained in:
		
							parent
							
								
									529e70910d
								
							
						
					
					
						commit
						fc607d6789
					
				@ -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 {
 | 
			
		||||
 | 
			
		||||
@ -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(())
 | 
			
		||||
        })?;
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user