Merge pull request #2205 from fufesou/feat_dylib_virtual_display
Feat dylib virtual display
This commit is contained in:
		
						commit
						d3f39f77a0
					
				
							
								
								
									
										17
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										17
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							| @ -1392,6 +1392,18 @@ version = "0.4.8" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "dylib_virtual_display" | ||||
| version = "0.1.0" | ||||
| dependencies = [ | ||||
|  "cc", | ||||
|  "hbb_common", | ||||
|  "lazy_static", | ||||
|  "serde 1.0.144", | ||||
|  "serde_derive", | ||||
|  "thiserror", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "ed25519" | ||||
| version = "1.5.2" | ||||
| @ -5555,12 +5567,9 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" | ||||
| name = "virtual_display" | ||||
| version = "0.1.0" | ||||
| dependencies = [ | ||||
|  "cc", | ||||
|  "hbb_common", | ||||
|  "lazy_static", | ||||
|  "serde 1.0.144", | ||||
|  "serde_derive", | ||||
|  "thiserror", | ||||
|  "libloading", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
|  | ||||
| @ -127,7 +127,7 @@ jni = "0.19" | ||||
| flutter_rust_bridge = { git = "https://github.com/SoLongAndThanksForAllThePizza/flutter_rust_bridge" } | ||||
| 
 | ||||
| [workspace] | ||||
| members = ["libs/scrap", "libs/hbb_common", "libs/enigo", "libs/clipboard", "libs/virtual_display", "libs/simple_rc", "libs/portable"] | ||||
| members = ["libs/scrap", "libs/hbb_common", "libs/enigo", "libs/clipboard", "libs/virtual_display", "libs/virtual_display/dylib", "libs/simple_rc", "libs/portable"] | ||||
| 
 | ||||
| [package.metadata.winres] | ||||
| LegalCopyright = "Copyright © 2022 Purslane, Inc." | ||||
|  | ||||
							
								
								
									
										6
									
								
								build.py
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								build.py
									
									
									
									
									
								
							| @ -288,6 +288,7 @@ def build_flutter_windows(version, features): | ||||
|     os.chdir('flutter') | ||||
|     os.system('flutter build windows --release') | ||||
|     os.chdir('..') | ||||
|     shutil.copy2('target/release/deps/dylib_virtual_display.dll', flutter_win_target_dir) | ||||
|     os.chdir('libs/portable') | ||||
|     os.system('pip3 install -r requirements.txt') | ||||
|     os.system( | ||||
| @ -323,6 +324,11 @@ def main(): | ||||
|     os.system('python3 res/inline-sciter.py') | ||||
|     portable = args.portable | ||||
|     if windows: | ||||
|         # build virtual display dynamic library | ||||
|         os.chdir('libs/virtual_display/dylib') | ||||
|         os.system('cargo build --release') | ||||
|         os.chdir('../../..') | ||||
| 
 | ||||
|         if flutter: | ||||
|             build_flutter_windows(version, features) | ||||
|             return | ||||
|  | ||||
| @ -18,7 +18,7 @@ fn build_c_impl() { | ||||
|     if build.get_compiler().is_like_msvc() { | ||||
|         build.define("WIN32", ""); | ||||
|         // build.define("_AMD64_", "");
 | ||||
|         build.flag("-Zi"); | ||||
|         build.flag("-Z7"); | ||||
|         build.flag("-GR-"); | ||||
|         // build.flag("-std:c++11");
 | ||||
|     } else { | ||||
|  | ||||
							
								
								
									
										1358
									
								
								libs/virtual_display/Cargo.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										1358
									
								
								libs/virtual_display/Cargo.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -5,12 +5,7 @@ edition = "2021" | ||||
| 
 | ||||
| # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||||
| 
 | ||||
| [build-dependencies] | ||||
| cc = "1.0" | ||||
| 
 | ||||
| [dependencies] | ||||
| thiserror = "1.0.30" | ||||
| lazy_static = "1.4" | ||||
| serde = "1.0" | ||||
| serde_derive = "1.0" | ||||
| libloading = "0.7" | ||||
| hbb_common = { path = "../hbb_common" } | ||||
|  | ||||
| @ -1,32 +1,3 @@ | ||||
| # virtual display | ||||
| 
 | ||||
| Virtual display may be used on computers that do not have a monitor. | ||||
| 
 | ||||
| [Development reference](https://github.com/pavlobu/deskreen/discussions/86) | ||||
| 
 | ||||
| ## windows | ||||
| 
 | ||||
| ### win10 | ||||
| 
 | ||||
| Win10 provides [Indirect Display Driver Model](https://msdn.microsoft.com/en-us/library/windows/hardware/mt761968(v=vs.85).aspx). | ||||
| 
 | ||||
| This lib uses [this project](https://github.com/fufesou/RustDeskIddDriver) as the driver. | ||||
| 
 | ||||
| 
 | ||||
| **NOTE**: Versions before Win10 1607. Try follow [this method](https://github.com/fanxiushu/xdisp_virt/tree/master/indirect_display). | ||||
| 
 | ||||
| 
 | ||||
| #### tested platforms | ||||
| 
 | ||||
| - [x] 19041 | ||||
| - [x] 19043 | ||||
| 
 | ||||
| ### win7 | ||||
| 
 | ||||
| TODO | ||||
| 
 | ||||
| [WDDM](https://docs.microsoft.com/en-us/windows-hardware/drivers/display/windows-vista-display-driver-model-design-guide). | ||||
| 
 | ||||
| ## X11 | ||||
| 
 | ||||
| ## OSX | ||||
| [doc](./dylib/README.md) | ||||
|  | ||||
							
								
								
									
										19
									
								
								libs/virtual_display/dylib/Cargo.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								libs/virtual_display/dylib/Cargo.toml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | ||||
| [package] | ||||
| name = "dylib_virtual_display" | ||||
| version = "0.1.0" | ||||
| edition = "2021" | ||||
| 
 | ||||
| [lib] | ||||
| crate-type = ["cdylib", "staticlib", "rlib"] | ||||
| 
 | ||||
| # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||||
| 
 | ||||
| [build-dependencies] | ||||
| cc = "1.0" | ||||
| 
 | ||||
| [dependencies] | ||||
| thiserror = "1.0.30" | ||||
| lazy_static = "1.4" | ||||
| serde = "1.0" | ||||
| serde_derive = "1.0" | ||||
| hbb_common = { path = "../../hbb_common" } | ||||
							
								
								
									
										32
									
								
								libs/virtual_display/dylib/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								libs/virtual_display/dylib/README.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,32 @@ | ||||
| # virtual display | ||||
| 
 | ||||
| Virtual display may be used on computers that do not have a monitor. | ||||
| 
 | ||||
| [Development reference](https://github.com/pavlobu/deskreen/discussions/86) | ||||
| 
 | ||||
| ## windows | ||||
| 
 | ||||
| ### win10 | ||||
| 
 | ||||
| Win10 provides [Indirect Display Driver Model](https://msdn.microsoft.com/en-us/library/windows/hardware/mt761968(v=vs.85).aspx). | ||||
| 
 | ||||
| This lib uses [this project](https://github.com/fufesou/RustDeskIddDriver) as the driver. | ||||
| 
 | ||||
| 
 | ||||
| **NOTE**: Versions before Win10 1607. Try follow [this method](https://github.com/fanxiushu/xdisp_virt/tree/master/indirect_display). | ||||
| 
 | ||||
| 
 | ||||
| #### tested platforms | ||||
| 
 | ||||
| - [x] 19041 | ||||
| - [x] 19043 | ||||
| 
 | ||||
| ### win7 | ||||
| 
 | ||||
| TODO | ||||
| 
 | ||||
| [WDDM](https://docs.microsoft.com/en-us/windows-hardware/drivers/display/windows-vista-display-driver-model-design-guide). | ||||
| 
 | ||||
| ## X11 | ||||
| 
 | ||||
| ## OSX | ||||
| @ -13,7 +13,7 @@ fn build_c_impl() { | ||||
| 
 | ||||
|     if build.get_compiler().is_like_msvc() { | ||||
|         build.define("WIN32", ""); | ||||
|         build.flag("-Zi"); | ||||
|         build.flag("-Z7"); | ||||
|         build.flag("-GR-"); | ||||
|         // build.flag("-std:c++11");
 | ||||
|     } else { | ||||
| @ -24,7 +24,7 @@ fn build_c_impl() { | ||||
|     } | ||||
| 
 | ||||
|     #[cfg(target_os = "windows")] | ||||
|     build.compile("xxx"); | ||||
|     build.compile("win_virtual_display"); | ||||
| 
 | ||||
|     #[cfg(target_os = "windows")] | ||||
|     println!("cargo:rerun-if-changed=src/win10/IddController.c"); | ||||
| @ -1,5 +1,5 @@ | ||||
| #[cfg(windows)] | ||||
| use virtual_display::win10::{idd, DRIVER_INSTALL_PATH}; | ||||
| use dylib_virtual_display::win10::{idd, DRIVER_INSTALL_PATH}; | ||||
| 
 | ||||
| #[cfg(windows)] | ||||
| use std::{ | ||||
							
								
								
									
										207
									
								
								libs/virtual_display/dylib/src/lib.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										207
									
								
								libs/virtual_display/dylib/src/lib.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,207 @@ | ||||
| #[cfg(windows)] | ||||
| pub mod win10; | ||||
| 
 | ||||
| use hbb_common::{bail, lazy_static, ResultType}; | ||||
| use std::{path::Path, sync::Mutex}; | ||||
| 
 | ||||
| lazy_static::lazy_static! { | ||||
|     // If device is uninstalled though "Device Manager" Window.
 | ||||
|     // Rustdesk is unable to handle device any more...
 | ||||
|     static ref H_SW_DEVICE: Mutex<u64> = Mutex::new(0); | ||||
|     static ref MONITOR_PLUGIN: Mutex<Vec<u32>> = Mutex::new(Vec::new()); | ||||
| } | ||||
| 
 | ||||
| #[no_mangle] | ||||
| #[cfg(windows)] | ||||
| pub fn get_dirver_install_path() -> &'static str { | ||||
|     win10::DRIVER_INSTALL_PATH | ||||
| } | ||||
| 
 | ||||
| #[no_mangle] | ||||
| pub fn download_driver() -> ResultType<()> { | ||||
|     #[cfg(windows)] | ||||
|     let _download_url = win10::DRIVER_DOWNLOAD_URL; | ||||
|     #[cfg(target_os = "linux")] | ||||
|     let _download_url = ""; | ||||
| 
 | ||||
|     // process download and report progress
 | ||||
| 
 | ||||
|     Ok(()) | ||||
| } | ||||
| 
 | ||||
| #[no_mangle] | ||||
| pub fn install_update_driver(_reboot_required: &mut bool) -> ResultType<()> { | ||||
|     #[cfg(windows)] | ||||
|     let install_path = win10::DRIVER_INSTALL_PATH; | ||||
|     #[cfg(not(windows))] | ||||
|     let install_path = ""; | ||||
| 
 | ||||
|     let abs_path = Path::new(install_path).canonicalize()?; | ||||
|     if !abs_path.exists() { | ||||
|         bail!("{} not exists", install_path) | ||||
|     } | ||||
| 
 | ||||
|     #[cfg(windows)] | ||||
|     unsafe { | ||||
|         { | ||||
|             // Device must be created before install driver.
 | ||||
|             // https://github.com/fufesou/RustDeskIddDriver/issues/1
 | ||||
|             if let Err(e) = create_device() { | ||||
|                 bail!("{}", e); | ||||
|             } | ||||
| 
 | ||||
|             let full_install_path: Vec<u16> = abs_path | ||||
|                 .to_string_lossy() | ||||
|                 .as_ref() | ||||
|                 .encode_utf16() | ||||
|                 .chain(Some(0).into_iter()) | ||||
|                 .collect(); | ||||
| 
 | ||||
|             let mut reboot_required_tmp = win10::idd::FALSE; | ||||
|             if win10::idd::InstallUpdate(full_install_path.as_ptr() as _, &mut reboot_required_tmp) | ||||
|                 == win10::idd::FALSE | ||||
|             { | ||||
|                 bail!("{}", win10::get_last_msg()?); | ||||
|             } | ||||
|             *_reboot_required = reboot_required_tmp == win10::idd::TRUE; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     Ok(()) | ||||
| } | ||||
| 
 | ||||
| #[no_mangle] | ||||
| pub fn uninstall_driver(_reboot_required: &mut bool) -> ResultType<()> { | ||||
|     #[cfg(windows)] | ||||
|     let install_path = win10::DRIVER_INSTALL_PATH; | ||||
|     #[cfg(not(windows))] | ||||
|     let install_path = ""; | ||||
| 
 | ||||
|     let abs_path = Path::new(install_path).canonicalize()?; | ||||
|     if !abs_path.exists() { | ||||
|         bail!("{} not exists", install_path) | ||||
|     } | ||||
| 
 | ||||
|     #[cfg(windows)] | ||||
|     unsafe { | ||||
|         { | ||||
|             let full_install_path: Vec<u16> = abs_path | ||||
|                 .to_string_lossy() | ||||
|                 .as_ref() | ||||
|                 .encode_utf16() | ||||
|                 .chain(Some(0).into_iter()) | ||||
|                 .collect(); | ||||
| 
 | ||||
|             let mut reboot_required_tmp = win10::idd::FALSE; | ||||
|             if win10::idd::Uninstall(full_install_path.as_ptr() as _, &mut reboot_required_tmp) | ||||
|                 == win10::idd::FALSE | ||||
|             { | ||||
|                 bail!("{}", win10::get_last_msg()?); | ||||
|             } | ||||
|             *_reboot_required = reboot_required_tmp == win10::idd::TRUE; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     Ok(()) | ||||
| } | ||||
| 
 | ||||
| #[no_mangle] | ||||
| pub fn is_device_created() -> bool { | ||||
|     #[cfg(windows)] | ||||
|     return *H_SW_DEVICE.lock().unwrap() != 0; | ||||
|     #[cfg(not(windows))] | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| #[no_mangle] | ||||
| pub fn create_device() -> ResultType<()> { | ||||
|     if is_device_created() { | ||||
|         return Ok(()); | ||||
|     } | ||||
|     #[cfg(windows)] | ||||
|     unsafe { | ||||
|         let mut lock_device = H_SW_DEVICE.lock().unwrap(); | ||||
|         let mut h_sw_device = *lock_device as win10::idd::HSWDEVICE; | ||||
|         if win10::idd::DeviceCreate(&mut h_sw_device) == win10::idd::FALSE { | ||||
|             bail!("{}", win10::get_last_msg()?); | ||||
|         } else { | ||||
|             *lock_device = h_sw_device as u64; | ||||
|         } | ||||
|     } | ||||
|     Ok(()) | ||||
| } | ||||
| 
 | ||||
| #[no_mangle] | ||||
| pub fn close_device() { | ||||
|     #[cfg(windows)] | ||||
|     unsafe { | ||||
|         win10::idd::DeviceClose(*H_SW_DEVICE.lock().unwrap() as win10::idd::HSWDEVICE); | ||||
|         *H_SW_DEVICE.lock().unwrap() = 0; | ||||
|         MONITOR_PLUGIN.lock().unwrap().clear(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[no_mangle] | ||||
| pub fn plug_in_monitor() -> ResultType<()> { | ||||
|     #[cfg(windows)] | ||||
|     unsafe { | ||||
|         let monitor_index = 0 as u32; | ||||
|         let mut plug_in_monitors = MONITOR_PLUGIN.lock().unwrap(); | ||||
|         for i in 0..plug_in_monitors.len() { | ||||
|             if let Some(d) = plug_in_monitors.get(i) { | ||||
|                 if *d == monitor_index { | ||||
|                     return Ok(()); | ||||
|                 } | ||||
|             }; | ||||
|         } | ||||
|         if win10::idd::MonitorPlugIn(monitor_index, 0, 30) == win10::idd::FALSE { | ||||
|             bail!("{}", win10::get_last_msg()?); | ||||
|         } | ||||
|         (*plug_in_monitors).push(monitor_index); | ||||
|     } | ||||
|     Ok(()) | ||||
| } | ||||
| 
 | ||||
| #[no_mangle] | ||||
| pub fn plug_out_monitor() -> ResultType<()> { | ||||
|     #[cfg(windows)] | ||||
|     unsafe { | ||||
|         let monitor_index = 0 as u32; | ||||
|         if win10::idd::MonitorPlugOut(monitor_index) == win10::idd::FALSE { | ||||
|             bail!("{}", win10::get_last_msg()?); | ||||
|         } | ||||
|         let mut plug_in_monitors = MONITOR_PLUGIN.lock().unwrap(); | ||||
|         for i in 0..plug_in_monitors.len() { | ||||
|             if let Some(d) = plug_in_monitors.get(i) { | ||||
|                 if *d == monitor_index { | ||||
|                     plug_in_monitors.remove(i); | ||||
|                     break; | ||||
|                 } | ||||
|             }; | ||||
|         } | ||||
|     } | ||||
|     Ok(()) | ||||
| } | ||||
| 
 | ||||
| #[no_mangle] | ||||
| pub fn update_monitor_modes() -> ResultType<()> { | ||||
|     #[cfg(windows)] | ||||
|     unsafe { | ||||
|         let monitor_index = 0 as u32; | ||||
|         let mut modes = vec![win10::idd::MonitorMode { | ||||
|             width: 1920, | ||||
|             height: 1080, | ||||
|             sync: 60, | ||||
|         }]; | ||||
|         if win10::idd::FALSE | ||||
|             == win10::idd::MonitorModesUpdate( | ||||
|                 monitor_index as win10::idd::UINT, | ||||
|                 modes.len() as win10::idd::UINT, | ||||
|                 modes.as_mut_ptr(), | ||||
|             ) | ||||
|         { | ||||
|             bail!("{}", win10::get_last_msg()?); | ||||
|         } | ||||
|     } | ||||
|     Ok(()) | ||||
| } | ||||
| @ -1,192 +1,125 @@ | ||||
| #[cfg(windows)] | ||||
| pub mod win10; | ||||
| use hbb_common::{bail, ResultType}; | ||||
| use std::sync::{Arc, Mutex}; | ||||
| 
 | ||||
| use hbb_common::{bail, lazy_static, ResultType}; | ||||
| use std::{path::Path, sync::Mutex}; | ||||
| const LIB_NAME_VIRTUAL_DISPLAY: &str = "dylib_virtual_display"; | ||||
| 
 | ||||
| lazy_static::lazy_static! { | ||||
|     // If device is uninstalled though "Device Manager" Window.
 | ||||
|     // Rustdesk is unable to handle device any more...
 | ||||
|     static ref H_SW_DEVICE: Mutex<u64> = Mutex::new(0); | ||||
|     static ref MONITOR_PLUGIN: Mutex<Vec<u32>> = Mutex::new(Vec::new()); | ||||
|     static ref LIB_VIRTUAL_DISPLAY: Arc<Mutex<Result<libloading::Library, libloading::Error>>> = { | ||||
|         Arc::new(Mutex::new(unsafe { libloading::Library::new(get_lib_name()) })) | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
| pub fn download_driver() -> ResultType<()> { | ||||
|     #[cfg(windows)] | ||||
|     let _download_url = win10::DRIVER_DOWNLOAD_URL; | ||||
|     #[cfg(target_os = "linux")] | ||||
|     let _download_url = ""; | ||||
| 
 | ||||
|     // process download and report progress
 | ||||
| 
 | ||||
|     Ok(()) | ||||
| #[cfg(target_os = "windows")] | ||||
| fn get_lib_name() -> String { | ||||
|     format!("{}.dll", LIB_NAME_VIRTUAL_DISPLAY) | ||||
| } | ||||
| 
 | ||||
| pub fn install_update_driver(_reboot_required: &mut bool) -> ResultType<()> { | ||||
|     #[cfg(windows)] | ||||
|     let install_path = win10::DRIVER_INSTALL_PATH; | ||||
|     #[cfg(not(windows))] | ||||
|     let install_path = ""; | ||||
| 
 | ||||
|     let abs_path = Path::new(install_path).canonicalize()?; | ||||
|     if !abs_path.exists() { | ||||
|         bail!("{} not exists", install_path) | ||||
|     } | ||||
| 
 | ||||
|     #[cfg(windows)] | ||||
|     unsafe { | ||||
|         { | ||||
|             // Device must be created before install driver.
 | ||||
|             // https://github.com/fufesou/RustDeskIddDriver/issues/1
 | ||||
|             if let Err(e) = create_device() { | ||||
|                 bail!("{}", e); | ||||
|             } | ||||
| 
 | ||||
|             let full_install_path: Vec<u16> = abs_path | ||||
|                 .to_string_lossy() | ||||
|                 .as_ref() | ||||
|                 .encode_utf16() | ||||
|                 .chain(Some(0).into_iter()) | ||||
|                 .collect(); | ||||
| 
 | ||||
|             let mut reboot_required_tmp = win10::idd::FALSE; | ||||
|             if win10::idd::InstallUpdate(full_install_path.as_ptr() as _, &mut reboot_required_tmp) | ||||
|                 == win10::idd::FALSE | ||||
|             { | ||||
|                 bail!("{}", win10::get_last_msg()?); | ||||
|             } | ||||
|             *_reboot_required = reboot_required_tmp == win10::idd::TRUE; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     Ok(()) | ||||
| #[cfg(target_os = "linux")] | ||||
| fn get_lib_name() -> String { | ||||
|     format!("lib{}.so", LIB_NAME_VIRTUAL_DISPLAY) | ||||
| } | ||||
| 
 | ||||
| pub fn uninstall_driver(_reboot_required: &mut bool) -> ResultType<()> { | ||||
|     #[cfg(windows)] | ||||
|     let install_path = win10::DRIVER_INSTALL_PATH; | ||||
|     #[cfg(not(windows))] | ||||
|     let install_path = ""; | ||||
| #[cfg(target_os = "macos")] | ||||
| fn get_lib_name() -> String { | ||||
|     format!("lib{}.dylib", LIB_NAME_VIRTUAL_DISPLAY) | ||||
| } | ||||
| 
 | ||||
|     let abs_path = Path::new(install_path).canonicalize()?; | ||||
|     if !abs_path.exists() { | ||||
|         bail!("{} not exists", install_path) | ||||
| fn try_reload_lib() { | ||||
|     let mut lock = LIB_VIRTUAL_DISPLAY.lock().unwrap(); | ||||
|     if lock.is_err() { | ||||
|         *lock = unsafe { libloading::Library::new(get_lib_name()) }; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|     #[cfg(windows)] | ||||
|     unsafe { | ||||
|         { | ||||
|             let full_install_path: Vec<u16> = abs_path | ||||
|                 .to_string_lossy() | ||||
|                 .as_ref() | ||||
|                 .encode_utf16() | ||||
|                 .chain(Some(0).into_iter()) | ||||
|                 .collect(); | ||||
| 
 | ||||
|             let mut reboot_required_tmp = win10::idd::FALSE; | ||||
|             if win10::idd::Uninstall(full_install_path.as_ptr() as _, &mut reboot_required_tmp) | ||||
|                 == win10::idd::FALSE | ||||
|             { | ||||
|                 bail!("{}", win10::get_last_msg()?); | ||||
| #[cfg(windows)] | ||||
| pub fn get_dirver_install_path() -> ResultType<&'static str> { | ||||
|     try_reload_lib(); | ||||
|     match &*LIB_VIRTUAL_DISPLAY.lock().unwrap() { | ||||
|         Ok(lib) => unsafe { | ||||
|             match lib.get::<libloading::Symbol<fn() -> &'static str>>(b"get_dirver_install_path") { | ||||
|                 Ok(func) => Ok(func()), | ||||
|                 Err(e) => bail!("Failed to load func get_dirver_install_path, {}", e), | ||||
|             } | ||||
|             *_reboot_required = reboot_required_tmp == win10::idd::TRUE; | ||||
|         } | ||||
|         }, | ||||
|         Err(e) => bail!("Failed to load library {}, {}", LIB_NAME_VIRTUAL_DISPLAY, e), | ||||
|     } | ||||
| 
 | ||||
|     Ok(()) | ||||
| } | ||||
| 
 | ||||
| pub fn is_device_created() -> bool { | ||||
|     #[cfg(windows)] | ||||
|     return *H_SW_DEVICE.lock().unwrap() != 0; | ||||
|     #[cfg(not(windows))] | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| pub fn create_device() -> ResultType<()> { | ||||
|     if is_device_created() { | ||||
|         return Ok(()); | ||||
|     try_reload_lib(); | ||||
|     match &*LIB_VIRTUAL_DISPLAY.lock().unwrap() { | ||||
|         Ok(lib) => unsafe { | ||||
|             match lib.get::<libloading::Symbol<fn() -> bool>>(b"is_device_created") { | ||||
|                 Ok(func) => func(), | ||||
|                 Err(..) => false, | ||||
|             } | ||||
|         }, | ||||
|         Err(..) => false, | ||||
|     } | ||||
|     #[cfg(windows)] | ||||
|     unsafe { | ||||
|         let mut lock_device = H_SW_DEVICE.lock().unwrap(); | ||||
|         let mut h_sw_device = *lock_device as win10::idd::HSWDEVICE; | ||||
|         if win10::idd::DeviceCreate(&mut h_sw_device) == win10::idd::FALSE { | ||||
|             bail!("{}", win10::get_last_msg()?); | ||||
|         } else { | ||||
|             *lock_device = h_sw_device as u64; | ||||
|         } | ||||
|     } | ||||
|     Ok(()) | ||||
| } | ||||
| 
 | ||||
| pub fn close_device() { | ||||
|     #[cfg(windows)] | ||||
|     unsafe { | ||||
|         win10::idd::DeviceClose(*H_SW_DEVICE.lock().unwrap() as win10::idd::HSWDEVICE); | ||||
|         *H_SW_DEVICE.lock().unwrap() = 0; | ||||
|         MONITOR_PLUGIN.lock().unwrap().clear(); | ||||
|     try_reload_lib(); | ||||
|     match &*LIB_VIRTUAL_DISPLAY.lock().unwrap() { | ||||
|         Ok(lib) => unsafe { | ||||
|             match lib.get::<libloading::Symbol<fn()>>(b"close_device") { | ||||
|                 Ok(func) => func(), | ||||
|                 Err(..) => {} | ||||
|             } | ||||
|         }, | ||||
|         Err(..) => {} | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub fn plug_in_monitor() -> ResultType<()> { | ||||
|     #[cfg(windows)] | ||||
|     unsafe { | ||||
|         let monitor_index = 0 as u32; | ||||
|         let mut plug_in_monitors = MONITOR_PLUGIN.lock().unwrap(); | ||||
|         for i in 0..plug_in_monitors.len() { | ||||
|             if let Some(d) = plug_in_monitors.get(i) { | ||||
|                 if *d == monitor_index { | ||||
|                     return Ok(()); | ||||
|                 } | ||||
|             }; | ||||
| macro_rules! def_func_result { | ||||
|     ($func:ident, $name: tt) => { | ||||
|         pub fn $func() -> ResultType<()> { | ||||
|             try_reload_lib(); | ||||
|             match &*LIB_VIRTUAL_DISPLAY.lock().unwrap() { | ||||
|                 Ok(lib) => unsafe { | ||||
|                     match lib.get::<libloading::Symbol<fn() -> ResultType<()>>>($name.as_bytes()) { | ||||
|                         Ok(func) => func(), | ||||
|                         Err(e) => bail!("Failed to load func {}, {}", $name, e), | ||||
|                     } | ||||
|                 }, | ||||
|                 Err(e) => bail!("Failed to load library {}, {}", LIB_NAME_VIRTUAL_DISPLAY, e), | ||||
|             } | ||||
|         } | ||||
|         if win10::idd::MonitorPlugIn(monitor_index, 0, 30) == win10::idd::FALSE { | ||||
|             bail!("{}", win10::get_last_msg()?); | ||||
|         } | ||||
|         (*plug_in_monitors).push(monitor_index); | ||||
|     } | ||||
|     Ok(()) | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
| pub fn plug_out_monitor() -> ResultType<()> { | ||||
|     #[cfg(windows)] | ||||
|     unsafe { | ||||
|         let monitor_index = 0 as u32; | ||||
|         if win10::idd::MonitorPlugOut(monitor_index) == win10::idd::FALSE { | ||||
|             bail!("{}", win10::get_last_msg()?); | ||||
|         } | ||||
|         let mut plug_in_monitors = MONITOR_PLUGIN.lock().unwrap(); | ||||
|         for i in 0..plug_in_monitors.len() { | ||||
|             if let Some(d) = plug_in_monitors.get(i) { | ||||
|                 if *d == monitor_index { | ||||
|                     plug_in_monitors.remove(i); | ||||
|                     break; | ||||
|                 } | ||||
|             }; | ||||
|         } | ||||
| pub fn install_update_driver(reboot_required: &mut bool) -> ResultType<()> { | ||||
|     try_reload_lib(); | ||||
|     match &*LIB_VIRTUAL_DISPLAY.lock().unwrap() { | ||||
|         Ok(lib) => unsafe { | ||||
|             match lib.get::<libloading::Symbol<fn(&mut bool) -> ResultType<()>>>( | ||||
|                 b"install_update_driver", | ||||
|             ) { | ||||
|                 Ok(func) => func(reboot_required), | ||||
|                 Err(e) => bail!("Failed to load func install_update_driver, {}", e), | ||||
|             } | ||||
|         }, | ||||
|         Err(e) => bail!("Failed to load library {}, {}", LIB_NAME_VIRTUAL_DISPLAY, e), | ||||
|     } | ||||
|     Ok(()) | ||||
| } | ||||
| 
 | ||||
| pub fn update_monitor_modes() -> ResultType<()> { | ||||
|     #[cfg(windows)] | ||||
|     unsafe { | ||||
|         let monitor_index = 0 as u32; | ||||
|         let mut modes = vec![win10::idd::MonitorMode { | ||||
|             width: 1920, | ||||
|             height: 1080, | ||||
|             sync: 60, | ||||
|         }]; | ||||
|         if win10::idd::FALSE | ||||
|             == win10::idd::MonitorModesUpdate( | ||||
|                 monitor_index as win10::idd::UINT, | ||||
|                 modes.len() as win10::idd::UINT, | ||||
|                 modes.as_mut_ptr(), | ||||
|             ) | ||||
|         { | ||||
|             bail!("{}", win10::get_last_msg()?); | ||||
|         } | ||||
| pub fn uninstall_driver(reboot_required: &mut bool) -> ResultType<()> { | ||||
|     try_reload_lib(); | ||||
|     match &*LIB_VIRTUAL_DISPLAY.lock().unwrap() { | ||||
|         Ok(lib) => unsafe { | ||||
|             match lib | ||||
|                 .get::<libloading::Symbol<fn(&mut bool) -> ResultType<()>>>(b"uninstall_driver") | ||||
|             { | ||||
|                 Ok(func) => func(reboot_required), | ||||
|                 Err(e) => bail!("Failed to load func uninstall_driver, {}", e), | ||||
|             } | ||||
|         }, | ||||
|         Err(e) => bail!("Failed to load library {}, {}", LIB_NAME_VIRTUAL_DISPLAY, e), | ||||
|     } | ||||
|     Ok(()) | ||||
| } | ||||
| 
 | ||||
| def_func_result!(download_driver, "download_driver"); | ||||
| def_func_result!(create_device, "create_device"); | ||||
| def_func_result!(plug_in_monitor, "plug_in_monitor"); | ||||
| def_func_result!(plug_out_monitor, "plug_out_monitor"); | ||||
| def_func_result!(update_monitor_modes, "update_monitor_modes"); | ||||
|  | ||||
| @ -1187,7 +1187,7 @@ impl<T: InvokeUiSession> Remote<T> { | ||||
|     #[cfg(windows)] | ||||
|     fn handle_cliprdr_msg(&self, clip: hbb_common::message_proto::Cliprdr) { | ||||
|         if !self.handler.lc.read().unwrap().disable_clipboard { | ||||
|             #[cfg(any(target_os = "android", target_os = "ios", feature = "flutter"))] | ||||
|             #[cfg(feature = "flutter")] | ||||
|             if let Some(hbb_common::message_proto::cliprdr::Union::FormatList(_)) = &clip.union { | ||||
|                 if self.client_conn_id | ||||
|                     != clipboard::get_client_conn_id(&crate::flutter::get_cur_session_id()) | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user