remember resolution, mid commit

Signed-off-by: fufesou <shuanglongchen@yeah.net>
This commit is contained in:
fufesou
2023-05-18 21:25:48 +08:00
parent 07500013ff
commit c6ccee67aa
4 changed files with 165 additions and 93 deletions

View File

@@ -56,6 +56,10 @@ use windows_service::{
use winreg::enums::*;
use winreg::RegKey;
// This string is defined here.
// https://github.com/fufesou/RustDeskIddDriver/blob/b370aad3f50028b039aad211df60c8051c4a64d6/RustDeskIddDriver/RustDeskIddDriver.inf#LL73C1-L73C40
const IDD_DEVICE_STRING: &'static str = "RustDeskIddDriver Device\0";
pub fn get_cursor_pos() -> Option<(i32, i32)> {
unsafe {
#[allow(invalid_value)]
@@ -1831,21 +1835,25 @@ pub fn set_path_permission(dir: &PathBuf, permission: &str) -> ResultType<()> {
Ok(())
}
#[inline]
fn str_to_device_name(name: &str) -> [u16; 32] {
let mut device_name: Vec<u16> = wide_string(name);
if device_name.len() < 32 {
device_name.resize(32, 0);
}
let mut result = [0; 32];
result.copy_from_slice(&device_name[..32]);
result
}
pub fn resolutions(name: &str) -> Vec<Resolution> {
unsafe {
let mut dm: DEVMODEW = std::mem::zeroed();
let wname = wide_string(name);
let len = if wname.len() <= dm.dmDeviceName.len() {
wname.len()
} else {
dm.dmDeviceName.len()
};
std::ptr::copy_nonoverlapping(wname.as_ptr(), dm.dmDeviceName.as_mut_ptr(), len);
dm.dmSize = std::mem::size_of::<DEVMODEW>() as _;
let mut v = vec![];
let mut num = 0;
let device_name = str_to_device_name(name);
loop {
if EnumDisplaySettingsW(NULL as _, num, &mut dm) == 0 {
if EnumDisplaySettingsW(device_name.as_ptr(), num, &mut dm) == 0 {
break;
}
let r = Resolution {
@@ -1866,8 +1874,8 @@ pub fn current_resolution(name: &str) -> ResultType<Resolution> {
unsafe {
let mut dm: DEVMODEW = std::mem::zeroed();
dm.dmSize = std::mem::size_of::<DEVMODEW>() as _;
let wname = wide_string(name);
if EnumDisplaySettingsW(wname.as_ptr(), ENUM_CURRENT_SETTINGS, &mut dm) == 0 {
let device_name = str_to_device_name(name);
if EnumDisplaySettingsW(device_name.as_ptr(), ENUM_CURRENT_SETTINGS, &mut dm) == 0 {
bail!(
"failed to get currrent resolution, errno={}",
GetLastError()
@@ -1882,29 +1890,46 @@ pub fn current_resolution(name: &str) -> ResultType<Resolution> {
}
}
pub fn is_virtual_display(name: &str) -> ResultType<bool> {
let device_name = str_to_device_name(name);
let mut dd: DISPLAY_DEVICEW = unsafe { std::mem::zeroed() };
dd.cb = std::mem::size_of::<DISPLAY_DEVICEW>() as _;
let ok = unsafe { EnumDisplayDevicesW(device_name.as_ptr(), 0, &mut dd as _, 0) };
if ok == FALSE {
bail!(
"enumerate display devices with device name '{}', errno {}",
name,
unsafe { GetLastError() }
);
}
match std::string::String::from_utf16(&dd.DeviceString) {
Ok(s) => Ok(&s[..IDD_DEVICE_STRING.len()] == IDD_DEVICE_STRING),
Err(e) => bail!(
"convert the device string of '{}' to string: {}",
name,
e
),
}
}
pub fn change_resolution(name: &str, width: usize, height: usize) -> ResultType<()> {
let device_name = str_to_device_name(name);
unsafe {
let mut dm: DEVMODEW = std::mem::zeroed();
if FALSE == EnumDisplaySettingsW(NULL as _, ENUM_CURRENT_SETTINGS, &mut dm) {
if FALSE == EnumDisplaySettingsW(device_name.as_ptr() as _, ENUM_CURRENT_SETTINGS, &mut dm)
{
bail!("EnumDisplaySettingsW failed, errno={}", GetLastError());
}
// to-do: check if need change
println!("REMOVE ME ========================== dm ({},{}) to ({},{})", dm.dmPelsWidth, dm.dmPelsHeight, width, height);
let wname = wide_string(name);
let len = if wname.len() <= dm.dmDeviceName.len() {
wname.len()
} else {
dm.dmDeviceName.len()
};
std::ptr::copy_nonoverlapping(wname.as_ptr(), dm.dmDeviceName.as_mut_ptr(), len);
dm.dmSize = std::mem::size_of::<DEVMODEW>() as _;
// dmPelsWidth and dmPelsHeight is the same to width and height
// Because this process is running in dpi awareness mode.
if dm.dmPelsWidth == width as u32 && dm.dmPelsHeight == height as u32 {
return Ok(());
}
dm.dmPelsWidth = width as _;
dm.dmPelsHeight = height as _;
dm.dmFields = DM_PELSHEIGHT | DM_PELSWIDTH;
let res = ChangeDisplaySettingsExW(
wname.as_ptr(),
device_name.as_ptr(),
&mut dm,
NULL as _,
CDS_UPDATEREGISTRY | CDS_GLOBAL | CDS_RESET,