mirror of
https://github.com/weyne85/rustdesk.git
synced 2025-10-29 17:00:05 +00:00
linux_wayland_support: refactor
Signed-off-by: fufesou <shuanglongchen@yeah.net>
This commit is contained in:
@@ -31,6 +31,7 @@ use scrap::{
|
||||
use std::{
|
||||
collections::HashSet,
|
||||
io::{ErrorKind::WouldBlock, Result},
|
||||
ops::{Deref, DerefMut},
|
||||
time::{self, Duration, Instant},
|
||||
};
|
||||
#[cfg(windows)]
|
||||
@@ -127,7 +128,7 @@ impl VideoFrameController {
|
||||
}
|
||||
}
|
||||
|
||||
trait TraitCapturer {
|
||||
pub(super) trait TraitCapturer {
|
||||
fn frame<'a>(&'a mut self, timeout: Duration) -> Result<Frame<'a>>;
|
||||
|
||||
fn set_use_yuv(&mut self, use_yuv: bool);
|
||||
@@ -340,22 +341,36 @@ fn check_uac_switch(privacy_mode_id: i32, captuerer_privacy_mode_id: i32) -> Res
|
||||
Ok(())
|
||||
}
|
||||
|
||||
struct CapturerInfo {
|
||||
origin: (i32, i32),
|
||||
width: usize,
|
||||
height: usize,
|
||||
ndisplay: usize,
|
||||
current: usize,
|
||||
privacy_mode_id: i32,
|
||||
_captuerer_privacy_mode_id: i32,
|
||||
capturer: Box<dyn TraitCapturer>,
|
||||
pub(super) struct CapturerInfo {
|
||||
pub origin: (i32, i32),
|
||||
pub width: usize,
|
||||
pub height: usize,
|
||||
pub ndisplay: usize,
|
||||
pub current: usize,
|
||||
pub privacy_mode_id: i32,
|
||||
pub _captuerer_privacy_mode_id: i32,
|
||||
pub capturer: Box<dyn TraitCapturer>,
|
||||
}
|
||||
|
||||
impl Deref for CapturerInfo {
|
||||
type Target = Box<dyn TraitCapturer>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.capturer
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for CapturerInfo {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.capturer
|
||||
}
|
||||
}
|
||||
|
||||
fn get_capturer(use_yuv: bool) -> ResultType<CapturerInfo> {
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
if scrap::is_wayland() {
|
||||
return wayland_support::get_capturer();
|
||||
return super::wayland::get_capturer();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -441,7 +456,7 @@ fn run(sp: GenericService) -> ResultType<()> {
|
||||
Ok(x) => encoder = x,
|
||||
Err(err) => bail!("Failed to create encoder: {}", err),
|
||||
}
|
||||
c.capturer.set_use_yuv(encoder.use_yuv());
|
||||
c.set_use_yuv(encoder.use_yuv());
|
||||
|
||||
if *SWITCH.lock().unwrap() {
|
||||
log::debug!("Broadcasting display switch");
|
||||
@@ -467,7 +482,7 @@ fn run(sp: GenericService) -> ResultType<()> {
|
||||
#[cfg(windows)]
|
||||
let mut try_gdi = 1;
|
||||
#[cfg(windows)]
|
||||
log::info!("gdi: {}", c.capturer.is_gdi());
|
||||
log::info!("gdi: {}", c.is_gdi());
|
||||
|
||||
while sp.ok() {
|
||||
#[cfg(windows)]
|
||||
@@ -515,7 +530,7 @@ fn run(sp: GenericService) -> ResultType<()> {
|
||||
frame_controller.reset();
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "ios"))]
|
||||
let res = match (*c.capturer).frame(spf) {
|
||||
let res = match c.frame(spf) {
|
||||
Ok(frame) => {
|
||||
let time = now - start;
|
||||
let ms = (time.as_secs() * 1000 + time.subsec_millis() as u64) as i64;
|
||||
@@ -538,7 +553,7 @@ fn run(sp: GenericService) -> ResultType<()> {
|
||||
};
|
||||
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
let res = match (*c.capturer).frame(spf) {
|
||||
let res = match c.frame(spf) {
|
||||
Ok(frame) => {
|
||||
let time = now - start;
|
||||
let ms = (time.as_secs() * 1000 + time.subsec_millis() as u64) as i64;
|
||||
@@ -557,9 +572,9 @@ fn run(sp: GenericService) -> ResultType<()> {
|
||||
Err(ref e) if e.kind() == WouldBlock =>
|
||||
{
|
||||
#[cfg(windows)]
|
||||
if try_gdi > 0 && !c.capturer.is_gdi() {
|
||||
if try_gdi > 0 && !c.is_gdi() {
|
||||
if try_gdi > 3 {
|
||||
c.capturer.set_gdi();
|
||||
c.set_gdi();
|
||||
try_gdi = 0;
|
||||
log::info!("No image, fall back to gdi");
|
||||
}
|
||||
@@ -574,8 +589,8 @@ fn run(sp: GenericService) -> ResultType<()> {
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
if !c.capturer.is_gdi() {
|
||||
c.capturer.set_gdi();
|
||||
if !c.is_gdi() {
|
||||
c.set_gdi();
|
||||
log::info!("dxgi error, fall back to gdi: {:?}", err);
|
||||
continue;
|
||||
}
|
||||
@@ -688,7 +703,7 @@ fn get_display_num() -> usize {
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
if scrap::is_wayland() {
|
||||
return if let Ok(n) = wayland_support::get_display_num() {
|
||||
return if let Ok(n) = super::wayland::get_display_num() {
|
||||
n
|
||||
} else {
|
||||
0
|
||||
@@ -703,7 +718,7 @@ fn get_display_num() -> usize {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_displays_2(all: &Vec<Display>) -> (usize, Vec<DisplayInfo>) {
|
||||
pub(super) fn get_displays_2(all: &Vec<Display>) -> (usize, Vec<DisplayInfo>) {
|
||||
let mut displays = Vec::new();
|
||||
let mut primary = 0;
|
||||
for (i, d) in all.iter().enumerate() {
|
||||
@@ -731,7 +746,7 @@ pub async fn get_displays() -> ResultType<(usize, Vec<DisplayInfo>)> {
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
if scrap::is_wayland() {
|
||||
return wayland_support::get_displays().await;
|
||||
return super::wayland::get_displays().await;
|
||||
}
|
||||
}
|
||||
// switch to primary display if long time (30 seconds) no users
|
||||
@@ -760,7 +775,7 @@ fn get_primary() -> usize {
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
if scrap::is_wayland() {
|
||||
return match wayland_support::get_primary() {
|
||||
return match super::wayland::get_primary() {
|
||||
Ok(n) => n,
|
||||
Err(_) => 0,
|
||||
};
|
||||
@@ -816,7 +831,7 @@ fn try_get_displays() -> ResultType<Vec<Display>> {
|
||||
Ok(displays)
|
||||
}
|
||||
|
||||
fn get_current_display_2(mut all: Vec<Display>) -> ResultType<(usize, usize, Display)> {
|
||||
pub(super) fn get_current_display_2(mut all: Vec<Display>) -> ResultType<(usize, usize, Display)> {
|
||||
let mut current = *CURRENT_DISPLAY.lock().unwrap() as usize;
|
||||
if all.len() == 0 {
|
||||
bail!("No displays");
|
||||
@@ -838,185 +853,3 @@ fn get_current_display_2(mut all: Vec<Display>) -> ResultType<(usize, usize, Dis
|
||||
fn get_current_display() -> ResultType<(usize, usize, Display)> {
|
||||
get_current_display_2(try_get_displays()?)
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub mod wayland_support {
|
||||
use super::*;
|
||||
use hbb_common::allow_err;
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref CAP_DISPLAY_INFO: RwLock<u64> = RwLock::new(0);
|
||||
}
|
||||
struct CapDisplayInfo {
|
||||
rects: Vec<((i32, i32), usize, usize)>,
|
||||
displays: Vec<DisplayInfo>,
|
||||
num: usize,
|
||||
primary: usize,
|
||||
current: usize,
|
||||
capturer: *mut Capturer,
|
||||
}
|
||||
|
||||
impl TraitCapturer for *mut Capturer {
|
||||
fn frame<'a>(&'a mut self, timeout: Duration) -> Result<Frame<'a>> {
|
||||
unsafe { (**self).frame(timeout) }
|
||||
}
|
||||
|
||||
fn set_use_yuv(&mut self, use_yuv: bool) {
|
||||
unsafe {
|
||||
(**self).set_use_yuv(use_yuv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn check_init() -> ResultType<()> {
|
||||
if scrap::is_wayland() {
|
||||
let mut minx = 0;
|
||||
let mut maxx = 0;
|
||||
let mut miny = 0;
|
||||
let mut maxy = 0;
|
||||
|
||||
if *CAP_DISPLAY_INFO.read().unwrap() == 0 {
|
||||
let mut lock = CAP_DISPLAY_INFO.write().unwrap();
|
||||
if *lock == 0 {
|
||||
let all = Display::all()?;
|
||||
let num = all.len();
|
||||
let (primary, displays) = get_displays_2(&all);
|
||||
|
||||
let mut rects: Vec<((i32, i32), usize, usize)> = Vec::new();
|
||||
for d in &all {
|
||||
rects.push((d.origin(), d.width(), d.height()));
|
||||
}
|
||||
|
||||
let (ndisplay, current, display) = get_current_display_2(all)?;
|
||||
let (origin, width, height) =
|
||||
(display.origin(), display.width(), display.height());
|
||||
log::debug!(
|
||||
"#displays={}, current={}, origin: {:?}, width={}, height={}, cpus={}/{}",
|
||||
ndisplay,
|
||||
current,
|
||||
&origin,
|
||||
width,
|
||||
height,
|
||||
num_cpus::get_physical(),
|
||||
num_cpus::get(),
|
||||
);
|
||||
|
||||
minx = origin.0;
|
||||
maxx = origin.0 + width as i32;
|
||||
miny = origin.1;
|
||||
maxy = origin.1 + height as i32;
|
||||
|
||||
let capturer = Box::into_raw(Box::new(
|
||||
Capturer::new(display, true)
|
||||
.with_context(|| "Failed to create capturer")?,
|
||||
));
|
||||
let cap_display_info = Box::into_raw(Box::new(CapDisplayInfo {
|
||||
rects,
|
||||
displays,
|
||||
num,
|
||||
primary,
|
||||
current,
|
||||
capturer,
|
||||
}));
|
||||
*lock = cap_display_info as _;
|
||||
}
|
||||
}
|
||||
|
||||
if minx != maxx && miny != maxy {
|
||||
log::info!(
|
||||
"send uinput resolution: ({}, {}), ({}, {})",
|
||||
minx,
|
||||
maxx,
|
||||
miny,
|
||||
maxy
|
||||
);
|
||||
allow_err!(input_service::set_uinput_resolution(minx, maxx, miny, maxy).await);
|
||||
allow_err!(input_service::set_uinput().await);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn clear() {
|
||||
if !scrap::is_wayland() {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut lock = CAP_DISPLAY_INFO.write().unwrap();
|
||||
if *lock != 0 {
|
||||
unsafe {
|
||||
let cap_display_info = Box::from_raw(*lock as *mut CapDisplayInfo);
|
||||
let _ = Box::from_raw(cap_display_info.capturer);
|
||||
}
|
||||
*lock = 0;
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) async fn get_displays() -> ResultType<(usize, Vec<DisplayInfo>)> {
|
||||
check_init().await?;
|
||||
let addr = *CAP_DISPLAY_INFO.read().unwrap();
|
||||
if addr != 0 {
|
||||
let cap_display_info: *const CapDisplayInfo = addr as _;
|
||||
unsafe {
|
||||
let cap_display_info = &*cap_display_info;
|
||||
let primary = cap_display_info.primary;
|
||||
let displays = cap_display_info.displays.clone();
|
||||
Ok((primary, displays))
|
||||
}
|
||||
} else {
|
||||
bail!("Failed to get capturer display info");
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn get_primary() -> ResultType<usize> {
|
||||
let addr = *CAP_DISPLAY_INFO.read().unwrap();
|
||||
if addr != 0 {
|
||||
let cap_display_info: *const CapDisplayInfo = addr as _;
|
||||
unsafe {
|
||||
let cap_display_info = &*cap_display_info;
|
||||
Ok(cap_display_info.primary)
|
||||
}
|
||||
} else {
|
||||
bail!("Failed to get capturer display info");
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn get_display_num() -> ResultType<usize> {
|
||||
let addr = *CAP_DISPLAY_INFO.read().unwrap();
|
||||
if addr != 0 {
|
||||
let cap_display_info: *const CapDisplayInfo = addr as _;
|
||||
unsafe {
|
||||
let cap_display_info = &*cap_display_info;
|
||||
Ok(cap_display_info.num)
|
||||
}
|
||||
} else {
|
||||
bail!("Failed to get capturer display info");
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn get_capturer() -> ResultType<CapturerInfo> {
|
||||
if !scrap::is_wayland() {
|
||||
bail!("Do not call this function if not wayland");
|
||||
}
|
||||
let addr = *CAP_DISPLAY_INFO.read().unwrap();
|
||||
if addr != 0 {
|
||||
let cap_display_info: *const CapDisplayInfo = addr as _;
|
||||
unsafe {
|
||||
let cap_display_info = &*cap_display_info;
|
||||
let rect = cap_display_info.rects[cap_display_info.current];
|
||||
Ok(CapturerInfo {
|
||||
origin: rect.0,
|
||||
width: rect.1,
|
||||
height: rect.2,
|
||||
ndisplay: cap_display_info.num,
|
||||
current: cap_display_info.current,
|
||||
privacy_mode_id: 0,
|
||||
_captuerer_privacy_mode_id: 0,
|
||||
capturer: Box::new(cap_display_info.capturer),
|
||||
})
|
||||
}
|
||||
} else {
|
||||
bail!("Failed to get capturer display info");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user