add virtual display
Signed-off-by: fufesou <shuanglongchen@yeah.net>
This commit is contained in:
parent
e6bf858ae1
commit
b734e8aee9
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -4186,6 +4186,7 @@ name = "virtual_display"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"hbb_common",
|
||||
"lazy_static",
|
||||
"serde 1.0.136",
|
||||
"serde_derive",
|
||||
|
@ -27,13 +27,14 @@ pub use anyhow::{self, bail};
|
||||
pub use futures_util;
|
||||
pub mod config;
|
||||
pub mod fs;
|
||||
pub use lazy_static;
|
||||
pub use mac_address;
|
||||
pub use rand;
|
||||
pub use regex;
|
||||
pub use sodiumoxide;
|
||||
pub use tokio_socks;
|
||||
pub use tokio_socks::IntoTargetAddr;
|
||||
pub use tokio_socks::TargetAddr;
|
||||
pub use mac_address;
|
||||
|
||||
#[cfg(feature = "quic")]
|
||||
pub type Stream = quic::Connection;
|
||||
|
@ -13,3 +13,4 @@ thiserror = "1.0.30"
|
||||
lazy_static = "1.4"
|
||||
serde = "1.0"
|
||||
serde_derive = "1.0"
|
||||
hbb_common = { path = "../hbb_common" }
|
@ -1,5 +1,5 @@
|
||||
#[cfg(windows)]
|
||||
use virtual_display::win10::idd;
|
||||
use virtual_display::win10::{idd, DRIVER_INSTALL_PATH};
|
||||
|
||||
use std::{
|
||||
ffi::{CStr, CString},
|
||||
@ -24,9 +24,9 @@ fn prompt_input() -> u8 {
|
||||
.unwrap_or(0)
|
||||
}
|
||||
|
||||
unsafe fn plug_in(index: idd::UINT) {
|
||||
unsafe fn plug_in(index: idd::UINT, edid: idd::UINT) {
|
||||
println!("Plug in monitor begin");
|
||||
if idd::FALSE == idd::MonitorPlugIn(index, 25) {
|
||||
if idd::FALSE == idd::MonitorPlugIn(index, edid, 25) {
|
||||
println!("{}", CStr::from_ptr(idd::GetLastMsg()).to_str().unwrap());
|
||||
} else {
|
||||
println!("Plug in monitor done");
|
||||
@ -58,8 +58,7 @@ unsafe fn plug_out(index: idd::UINT) {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let relative_path = "RustDeskIddDriver/RustDeskIddDriver.inf";
|
||||
let abs_path = Path::new(relative_path).canonicalize().unwrap();
|
||||
let abs_path = Path::new(DRIVER_INSTALL_PATH).canonicalize().unwrap();
|
||||
let full_inf_path = abs_path.to_str().unwrap();
|
||||
|
||||
unsafe {
|
||||
@ -121,9 +120,9 @@ fn main() {
|
||||
h_sw_device = invalid_device;
|
||||
println!("Close device done");
|
||||
}
|
||||
'1' => plug_in(0),
|
||||
'2' => plug_in(1),
|
||||
'3' => plug_in(2),
|
||||
'1' => plug_in(0, 0),
|
||||
'2' => plug_in(1, 0),
|
||||
'3' => plug_in(2, 0),
|
||||
'4' => plug_out(0),
|
||||
'5' => plug_out(1),
|
||||
'6' => plug_out(2),
|
||||
@ -133,5 +132,7 @@ fn main() {
|
||||
if !full_inf_path.is_null() {
|
||||
let _ = CString::from_raw(full_inf_path);
|
||||
}
|
||||
|
||||
idd::DeviceClose(h_sw_device);
|
||||
}
|
||||
}
|
||||
|
@ -1,2 +1,103 @@
|
||||
#[cfg(windows)]
|
||||
pub mod win10;
|
||||
|
||||
use hbb_common::{bail, lazy_static, ResultType};
|
||||
use std::{
|
||||
ffi::{CStr, CString},
|
||||
path::Path,
|
||||
sync::Mutex,
|
||||
};
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
#[cfg(windows)]
|
||||
static ref H_SW_DEVICE: Mutex<u64> = Mutex::new(0);
|
||||
}
|
||||
|
||||
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(())
|
||||
}
|
||||
|
||||
pub fn install_update_driver() -> 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)
|
||||
}
|
||||
|
||||
let full_install_path = match abs_path.to_str() {
|
||||
Some(p) => CString::new(p)?.into_raw(),
|
||||
None => bail!("{} not exists", install_path),
|
||||
};
|
||||
|
||||
unsafe {
|
||||
#[cfg(windows)]
|
||||
{
|
||||
let mut reboot_required = win10::idd::FALSE;
|
||||
if win10::idd::InstallUpdate(full_install_path, &mut reboot_required)
|
||||
== win10::idd::FALSE
|
||||
{
|
||||
bail!("{}", CStr::from_ptr(win10::idd::GetLastMsg()).to_str()?);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn is_device_created() -> bool {
|
||||
#[cfg(windows)]
|
||||
return *H_SW_DEVICE.lock().unwrap() != 0;
|
||||
#[cfg(not(windows))]
|
||||
return false;
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
pub fn create_device() -> ResultType<()> {
|
||||
unsafe {
|
||||
let mut h_sw_device = *H_SW_DEVICE.lock().unwrap() as win10::idd::HSWDEVICE;
|
||||
if win10::idd::DeviceCreate(&mut h_sw_device) == win10::idd::FALSE {
|
||||
bail!("{}", CStr::from_ptr(win10::idd::GetLastMsg()).to_str()?);
|
||||
} else {
|
||||
*H_SW_DEVICE.lock().unwrap() = h_sw_device as u64;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
pub fn close_device() {
|
||||
unsafe {
|
||||
win10::idd::DeviceClose(*H_SW_DEVICE.lock().unwrap() as win10::idd::HSWDEVICE);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
pub fn plug_in_monitor() -> ResultType<()> {
|
||||
unsafe {
|
||||
if win10::idd::MonitorPlugIn(0, 0, 30) == win10::idd::FALSE {
|
||||
bail!("{}", CStr::from_ptr(win10::idd::GetLastMsg()).to_str()?);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
pub fn plug_out_monitor() -> ResultType<()> {
|
||||
unsafe {
|
||||
if win10::idd::MonitorPlugOut(0) == win10::idd::FALSE {
|
||||
bail!("{}", CStr::from_ptr(win10::idd::GetLastMsg()).to_str()?);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -282,7 +282,7 @@ VOID DeviceClose(HSWDEVICE hSwDevice)
|
||||
}
|
||||
}
|
||||
|
||||
BOOL MonitorPlugIn(UINT index, INT retries)
|
||||
BOOL MonitorPlugIn(UINT index, UINT edid, INT retries)
|
||||
{
|
||||
SetLastMsg("Sucess");
|
||||
|
||||
@ -315,6 +315,7 @@ BOOL MonitorPlugIn(UINT index, INT retries)
|
||||
DWORD junk = 0;
|
||||
CtlPlugIn plugIn;
|
||||
plugIn.ConnectorIndex = index;
|
||||
plugIn.MonitorEDID = edid;
|
||||
HRESULT hr = CoCreateGuid(&plugIn.ContainerId);
|
||||
if (!SUCCEEDED(hr))
|
||||
{
|
||||
|
@ -70,6 +70,9 @@ VOID DeviceClose(HSWDEVICE hSwDevice);
|
||||
* @brief Plug in monitor.
|
||||
*
|
||||
* @param index [in] Monitor index, should be 0, 1, 2.
|
||||
* @param edid [in] Monitor edid.
|
||||
* 0 Modified EDID from Dell S2719DGF
|
||||
* 1 Modified EDID from Lenovo Y27fA
|
||||
* @param retries [in] Retry times. Retry 1 time / sec. 25~30 seconds may be good choices.
|
||||
* -1 is invalid.
|
||||
* 0 means doing once and no retries.
|
||||
@ -83,7 +86,7 @@ VOID DeviceClose(HSWDEVICE hSwDevice);
|
||||
* System need some time to prepare the device.
|
||||
*
|
||||
*/
|
||||
BOOL MonitorPlugIn(UINT index, INT retries);
|
||||
BOOL MonitorPlugIn(UINT index, UINT edid, INT retries);
|
||||
|
||||
/**
|
||||
* @brief Plug out monitor.
|
||||
|
@ -26,8 +26,12 @@
|
||||
#define STATUS_ERROR_MONITOR_INVALID_PARAM (3 << 30) + 53
|
||||
#define STATUS_ERROR_MONITOR_OOM (3 << 30) + 54
|
||||
|
||||
#define MONITOR_EDID_MOD_DELL_S2719DGF 0
|
||||
#define MONITOR_EDID_MOD_LENOVO_Y27fA 1
|
||||
|
||||
typedef struct _CtlPlugIn {
|
||||
UINT ConnectorIndex;
|
||||
UINT MonitorEDID;
|
||||
GUID ContainerId;
|
||||
} CtlPlugIn, *PCtlPlugIn;
|
||||
|
||||
|
@ -206,7 +206,7 @@ extern "C" {
|
||||
|
||||
extern "C" {
|
||||
pub fn Uninstall(fullInfPath: LPCTSTR, rebootRequired: PBOOL) -> BOOL;
|
||||
pub fn MonitorPlugIn(index: UINT, retries: INT) -> BOOL;
|
||||
pub fn MonitorPlugIn(index: UINT, edid: UINT, retries: INT) -> BOOL;
|
||||
pub fn MonitorPlugOut(index: UINT) -> BOOL;
|
||||
pub fn MonitorModesUpdate(index: UINT, modeCount: UINT, modes: PMonitorMode) -> BOOL;
|
||||
|
||||
|
@ -1 +1,4 @@
|
||||
pub mod idd;
|
||||
pub mod idd;
|
||||
|
||||
pub const DRIVER_INSTALL_PATH: &str = "RustDeskIddDriver/RustDeskIddDriver.inf";
|
||||
pub const DRIVER_DOWNLOAD_URL: &str = "";
|
||||
|
@ -32,6 +32,7 @@ use std::{
|
||||
io::ErrorKind::WouldBlock,
|
||||
time::{self, Duration, Instant},
|
||||
};
|
||||
use virtual_display;
|
||||
|
||||
const WAIT_BASE: i32 = 17;
|
||||
pub const NAME: &'static str = "video";
|
||||
@ -446,6 +447,12 @@ fn get_current_display() -> ResultType<(usize, usize, Display)> {
|
||||
let mut current = *CURRENT_DISPLAY.lock().unwrap() as usize;
|
||||
let mut displays = Display::all()?;
|
||||
if displays.len() == 0 {
|
||||
// try plugin monitor
|
||||
if virtual_display::is_device_created() {
|
||||
if let Err(e) = virtual_display::plug_in_monitor() {
|
||||
log::error!("plug in monitor failed {}", e)
|
||||
}
|
||||
}
|
||||
bail!("No displays");
|
||||
}
|
||||
let n = displays.len();
|
||||
|
14
src/ui.rs
14
src/ui.rs
@ -19,6 +19,7 @@ use std::{
|
||||
process::Child,
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
use virtual_display;
|
||||
|
||||
pub type Childs = Arc<Mutex<(bool, HashMap<(String, String), Child>)>>;
|
||||
|
||||
@ -364,6 +365,18 @@ impl UI {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: ui prompt
|
||||
fn install_virtual_display(&self) {
|
||||
match virtual_display::install_update_driver() {
|
||||
Ok(_) => {
|
||||
log::info!("Virtual Display: install virtual display done");
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("Virtual Display: install virtual display failed {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn install_path(&mut self) -> String {
|
||||
#[cfg(windows)]
|
||||
return crate::platform::windows::get_install_info().1;
|
||||
@ -690,6 +703,7 @@ impl sciter::EventHandler for UI {
|
||||
fn get_sound_inputs();
|
||||
fn set_options(Value);
|
||||
fn set_option(String, String);
|
||||
fn install_virtual_display();
|
||||
fn get_software_update_url();
|
||||
fn get_new_version();
|
||||
fn get_version();
|
||||
|
@ -168,6 +168,7 @@ class MyIdMenu: Reactor.Component {
|
||||
<li #custom-server>{translate('ID/Relay Server')}</li>
|
||||
<li #whitelist title={translate('whitelist_tip')}>{translate('IP Whitelisting')}</li>
|
||||
<li #socks5-server>{translate('Socks5 Proxy')}</li>
|
||||
{is_win ? <li #install-virtual-display>Install virtual display</li> : ""}
|
||||
<div .separator />
|
||||
<li #stop-service class={service_stopped ? "line-through" : "selected"}><span>{svg_checkmark}</span>{translate("Enable Service")}</li>
|
||||
<DirectServer />
|
||||
@ -268,6 +269,8 @@ class MyIdMenu: Reactor.Component {
|
||||
}
|
||||
handler.set_socks(proxy, username, password);
|
||||
}, 240);
|
||||
} else if (me.id == "install-virtual-display") {
|
||||
handler.install_virtual_display();
|
||||
} else if (me.id == "stop-service") {
|
||||
handler.set_option("stop-service", service_stopped ? "" : "Y");
|
||||
} else if (me.id == "about") {
|
||||
|
Loading…
Reference in New Issue
Block a user