mirror of
https://github.com/rustdesk/rustdesk.git
synced 2024-12-18 05:27:53 +08:00
fix clipboard crash and https://github.com/rustdesk/rustdesk/issues/302
This commit is contained in:
parent
252d3cb797
commit
a30aaebc72
@ -9,8 +9,8 @@ extern "C" {
|
||||
src_stride_argb: c_int,
|
||||
dst_argb: *mut u8,
|
||||
dst_stride_argb: c_int,
|
||||
width: c_int,
|
||||
height: c_int,
|
||||
src_width: c_int,
|
||||
src_height: c_int,
|
||||
mode: c_int,
|
||||
) -> c_int;
|
||||
|
||||
|
@ -3,32 +3,20 @@ pub mod gdi;
|
||||
pub use gdi::CapturerGDI;
|
||||
|
||||
use winapi::{
|
||||
shared::dxgi::{
|
||||
CreateDXGIFactory1, IDXGIAdapter1, IDXGIFactory1, IDXGIResource, IDXGISurface,
|
||||
IID_IDXGIFactory1, IID_IDXGISurface, DXGI_MAP_READ, DXGI_OUTPUT_DESC,
|
||||
DXGI_RESOURCE_PRIORITY_MAXIMUM,
|
||||
shared::{
|
||||
dxgi::*,
|
||||
dxgi1_2::*,
|
||||
dxgitype::*,
|
||||
minwindef::{DWORD, FALSE, TRUE, UINT},
|
||||
ntdef::LONG,
|
||||
windef::HMONITOR,
|
||||
winerror::*,
|
||||
// dxgiformat::{DXGI_FORMAT, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_420_OPAQUE},
|
||||
},
|
||||
shared::dxgi1_2::IDXGIOutputDuplication,
|
||||
// shared::dxgiformat::{DXGI_FORMAT, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_420_OPAQUE},
|
||||
shared::dxgi1_2::{IDXGIOutput1, IID_IDXGIOutput1},
|
||||
shared::dxgitype::DXGI_MODE_ROTATION,
|
||||
shared::minwindef::{DWORD, FALSE, TRUE, UINT},
|
||||
shared::ntdef::LONG,
|
||||
shared::windef::HMONITOR,
|
||||
shared::winerror::{
|
||||
DXGI_ERROR_ACCESS_LOST, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_NOT_CURRENTLY_AVAILABLE,
|
||||
DXGI_ERROR_SESSION_DISCONNECTED, DXGI_ERROR_UNSUPPORTED, DXGI_ERROR_WAIT_TIMEOUT,
|
||||
E_ACCESSDENIED, E_INVALIDARG, S_OK,
|
||||
um::{
|
||||
d3d11::*, d3dcommon::D3D_DRIVER_TYPE_UNKNOWN, unknwnbase::IUnknown, wingdi::*,
|
||||
winnt::HRESULT, winuser::*,
|
||||
},
|
||||
um::d3d11::{
|
||||
D3D11CreateDevice, ID3D11Device, ID3D11DeviceContext, ID3D11Texture2D, IID_ID3D11Texture2D,
|
||||
D3D11_CPU_ACCESS_READ, D3D11_SDK_VERSION, D3D11_USAGE_STAGING,
|
||||
},
|
||||
um::d3dcommon::D3D_DRIVER_TYPE_UNKNOWN,
|
||||
um::unknwnbase::IUnknown,
|
||||
um::wingdi::*,
|
||||
um::winnt::HRESULT,
|
||||
um::winuser::*,
|
||||
};
|
||||
|
||||
pub struct ComPtr<T>(*mut T);
|
||||
@ -54,12 +42,11 @@ pub struct Capturer {
|
||||
duplication: ComPtr<IDXGIOutputDuplication>,
|
||||
fastlane: bool,
|
||||
surface: ComPtr<IDXGISurface>,
|
||||
data: *const u8,
|
||||
len: usize,
|
||||
width: usize,
|
||||
height: usize,
|
||||
use_yuv: bool,
|
||||
yuv: Vec<u8>,
|
||||
rotated: Vec<u8>,
|
||||
gdi_capturer: Option<CapturerGDI>,
|
||||
gdi_buffer: Vec<u8>,
|
||||
}
|
||||
@ -158,10 +145,9 @@ impl Capturer {
|
||||
width: display.width() as usize,
|
||||
height: display.height() as usize,
|
||||
display,
|
||||
data: ptr::null(),
|
||||
len: 0,
|
||||
use_yuv,
|
||||
yuv: Vec::new(),
|
||||
rotated: Vec::new(),
|
||||
gdi_capturer,
|
||||
gdi_buffer: Vec::new(),
|
||||
})
|
||||
@ -181,10 +167,9 @@ impl Capturer {
|
||||
self.gdi_capturer.take();
|
||||
}
|
||||
|
||||
unsafe fn load_frame(&mut self, timeout: UINT) -> io::Result<()> {
|
||||
unsafe fn load_frame(&mut self, timeout: UINT) -> io::Result<(*const u8, i32)> {
|
||||
let mut frame = ptr::null_mut();
|
||||
let mut info = mem::MaybeUninit::uninit().assume_init();
|
||||
self.data = ptr::null();
|
||||
|
||||
wrap_hresult((*self.duplication.0).AcquireNextFrame(timeout, &mut info, &mut frame))?;
|
||||
let frame = ComPtr(frame);
|
||||
@ -200,9 +185,7 @@ impl Capturer {
|
||||
self.surface = ComPtr(self.ohgodwhat(frame.0)?);
|
||||
wrap_hresult((*self.surface.0).Map(&mut rect, DXGI_MAP_READ))?;
|
||||
}
|
||||
self.data = rect.pBits;
|
||||
self.len = self.height * rect.Pitch as usize;
|
||||
Ok(())
|
||||
Ok((rect.pBits, rect.Pitch))
|
||||
}
|
||||
|
||||
// copy from GPU memory to system memory
|
||||
@ -257,8 +240,42 @@ impl Capturer {
|
||||
}
|
||||
} else {
|
||||
self.unmap();
|
||||
self.load_frame(timeout)?;
|
||||
slice::from_raw_parts(self.data, self.len)
|
||||
let r = self.load_frame(timeout)?;
|
||||
let rotate = match self.display.rotation() {
|
||||
DXGI_MODE_ROTATION_IDENTITY | DXGI_MODE_ROTATION_UNSPECIFIED => 0,
|
||||
DXGI_MODE_ROTATION_ROTATE90 => 90,
|
||||
DXGI_MODE_ROTATION_ROTATE180 => 180,
|
||||
DXGI_MODE_ROTATION_ROTATE270 => 270,
|
||||
_ => {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
"Unknown roration".to_string(),
|
||||
));
|
||||
}
|
||||
};
|
||||
if rotate == 0 {
|
||||
slice::from_raw_parts(r.0, r.1 as usize * self.height)
|
||||
} else {
|
||||
self.rotated.resize(self.width * self.height * 4, 0);
|
||||
crate::common::ARGBRotate(
|
||||
r.0,
|
||||
r.1,
|
||||
self.rotated.as_mut_ptr(),
|
||||
4 * self.width as i32,
|
||||
if rotate == 180 {
|
||||
self.width
|
||||
} else {
|
||||
self.height
|
||||
} as _,
|
||||
if rotate != 180 {
|
||||
self.width
|
||||
} else {
|
||||
self.height
|
||||
} as _,
|
||||
rotate,
|
||||
);
|
||||
&self.rotated[..]
|
||||
}
|
||||
}
|
||||
};
|
||||
Ok({
|
||||
@ -478,7 +495,10 @@ pub struct Display {
|
||||
gdi: bool,
|
||||
}
|
||||
|
||||
// https://github.com/dchapyshev/aspia/blob/59233c5d01a4d03ed6de19b03ce77d61a6facf79/source/base/desktop/win/screen_capture_utils.cc
|
||||
// optimized for updated region
|
||||
// https://github.com/dchapyshev/aspia/blob/master/source/base/desktop/win/dxgi_output_duplicator.cc
|
||||
// rotation
|
||||
// https://github.com/bryal/dxgcap-rs/blob/master/src/lib.rs
|
||||
|
||||
impl Display {
|
||||
pub fn width(&self) -> LONG {
|
||||
|
@ -95,7 +95,10 @@ pub fn update_clipboard(clipboard: Clipboard, old: Option<&Arc<Mutex<String>>>)
|
||||
let side = if old.is_none() { "host" } else { "client" };
|
||||
let old = if let Some(old) = old { old } else { &CONTENT };
|
||||
*old.lock().unwrap() = content.clone();
|
||||
allow_err!(ctx.set_text(content));
|
||||
if !content.is_empty() {
|
||||
// empty content make ctx.set_text crash
|
||||
allow_err!(ctx.set_text(content));
|
||||
}
|
||||
log::debug!("{} updated on {}", CLIPBOARD_NAME, side);
|
||||
}
|
||||
Err(err) => {
|
||||
@ -240,7 +243,8 @@ async fn test_nat_type_() -> ResultType<bool> {
|
||||
let rendezvous_server = get_rendezvous_server(100).await;
|
||||
let server1 = rendezvous_server;
|
||||
let mut server2 = server1;
|
||||
if server1.port() == 0 { // offline
|
||||
if server1.port() == 0 {
|
||||
// offline
|
||||
// avoid overflow crash
|
||||
bail!("Offline");
|
||||
}
|
||||
|
@ -97,8 +97,12 @@ mod listen {
|
||||
|
||||
fn trigger(ctx: &mut ClipboardContext) {
|
||||
let _ = match ctx.get_text() {
|
||||
Ok(text) => ctx.set_text(text),
|
||||
Err(_) => ctx.set_text(Default::default()),
|
||||
Ok(text) => {
|
||||
if !text.is_empty() {
|
||||
ctx.set_text(text).ok();
|
||||
}
|
||||
}
|
||||
Err(_) => {}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -220,7 +220,7 @@ fn run(sp: GenericService) -> ResultType<()> {
|
||||
let start = time::Instant::now();
|
||||
let mut last_check_displays = time::Instant::now();
|
||||
#[cfg(windows)]
|
||||
let mut try_gdi = true;
|
||||
let mut try_gdi = 1;
|
||||
#[cfg(windows)]
|
||||
log::info!("gdi: {}", c.is_gdi());
|
||||
while sp.ok() {
|
||||
@ -261,7 +261,7 @@ fn run(sp: GenericService) -> ResultType<()> {
|
||||
frame_controller.set_send(now, send_conn_ids);
|
||||
#[cfg(windows)]
|
||||
{
|
||||
try_gdi = false;
|
||||
try_gdi = 0;
|
||||
}
|
||||
}
|
||||
Err(ref e) if e.kind() == WouldBlock => {
|
||||
@ -271,10 +271,13 @@ fn run(sp: GenericService) -> ResultType<()> {
|
||||
wait = 0
|
||||
}
|
||||
#[cfg(windows)]
|
||||
if try_gdi && !c.is_gdi() {
|
||||
c.set_gdi();
|
||||
try_gdi = false;
|
||||
log::info!("No image, fall back to gdi");
|
||||
if try_gdi > 0 && !c.is_gdi() {
|
||||
if try_gdi > 3 {
|
||||
c.set_gdi();
|
||||
try_gdi = 0;
|
||||
log::info!("No image, fall back to gdi");
|
||||
}
|
||||
try_gdi += 1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user