feat: cursor, linux (#12822)

* feat: cursor, linux

Signed-off-by: fufesou <linlong1266@gmail.com>

* refact: cursor, text, white background

Signed-off-by: fufesou <linlong1266@gmail.com>

---------

Signed-off-by: fufesou <linlong1266@gmail.com>
This commit is contained in:
fufesou
2025-09-06 12:11:43 +08:00
committed by GitHub
parent f933f46283
commit 6c949a9602
14 changed files with 1153 additions and 209 deletions

View File

@@ -1,29 +1,43 @@
use super::{create_event_loop, CustomEvent};
use super::CustomEvent;
use crate::ipc::{new_listener, Connection, Data};
#[cfg(any(target_os = "windows", target_os = "macos"))]
use hbb_common::tokio::sync::mpsc::unbounded_channel;
#[cfg(any(target_os = "windows", target_os = "linux"))]
use hbb_common::ResultType;
use hbb_common::{
allow_err, log,
tokio::{
self,
sync::mpsc::{unbounded_channel, UnboundedReceiver},
},
tokio::{self, sync::mpsc::UnboundedReceiver},
};
use lazy_static::lazy_static;
use std::sync::RwLock;
use std::time::{Duration, Instant};
#[cfg(any(target_os = "windows", target_os = "macos"))]
use tao::event_loop::EventLoopProxy;
#[cfg(target_os = "linux")]
use winit::event_loop::EventLoopProxy;
lazy_static! {
pub(super) static ref EVENT_PROXY: RwLock<Option<EventLoopProxy<(String, CustomEvent)>>> =
RwLock::new(None);
}
const RIPPLE_DURATION: Duration = Duration::from_millis(500);
#[cfg(target_os = "macos")]
type RippleFloat = f64;
#[cfg(any(target_os = "windows", target_os = "linux"))]
type RippleFloat = f32;
#[cfg(target_os = "linux")]
pub use super::linux::run;
#[cfg(any(target_os = "windows", target_os = "macos"))]
pub fn run() {
let (tx_exit, rx_exit) = unbounded_channel();
std::thread::spawn(move || {
start_ipc(rx_exit);
});
if let Err(e) = create_event_loop() {
if let Err(e) = super::create_event_loop() {
log::error!("Failed to create event loop: {}", e);
tx_exit.send(()).ok();
return;
@@ -31,7 +45,7 @@ pub fn run() {
}
#[tokio::main(flavor = "current_thread")]
async fn start_ipc(mut rx_exit: UnboundedReceiver<()>) {
pub(super) async fn start_ipc(mut rx_exit: UnboundedReceiver<()>) {
match new_listener("_whiteboard").await {
Ok(mut incoming) => loop {
tokio::select! {
@@ -82,9 +96,7 @@ async fn handle_new_stream(mut conn: Connection) {
});
}
}
_ => {
}
_ => {}
}
}
Ok(None) => {
@@ -120,3 +132,40 @@ pub(super) fn get_displays_rect() -> ResultType<(i32, i32, u32, u32)> {
let (w, h) = ((max_x - min_x) as u32, (max_y - min_y) as u32);
Ok((x, y, w, h))
}
#[inline]
pub(super) fn argb_to_rgba(argb: u32) -> (u8, u8, u8, u8) {
(
(argb >> 16 & 0xFF) as u8,
(argb >> 8 & 0xFF) as u8,
(argb & 0xFF) as u8,
(argb >> 24 & 0xFF) as u8,
)
}
pub(super) struct Ripple {
pub x: RippleFloat,
pub y: RippleFloat,
pub start_time: Instant,
}
impl Ripple {
#[inline]
pub fn retain_active(ripples: &mut Vec<Ripple>) {
ripples.retain(|r| r.start_time.elapsed() < RIPPLE_DURATION);
}
pub fn get_radius_alpha(&self) -> (RippleFloat, RippleFloat) {
let elapsed = self.start_time.elapsed();
#[cfg(target_os = "macos")]
let progress = (elapsed.as_secs_f64() / RIPPLE_DURATION.as_secs_f64()).min(1.0);
#[cfg(any(target_os = "windows", target_os = "linux"))]
let progress = (elapsed.as_secs_f32() / RIPPLE_DURATION.as_secs_f32()).min(1.0);
#[cfg(target_os = "macos")]
let radius = 25.0 * progress;
#[cfg(any(target_os = "windows", target_os = "linux"))]
let radius = 45.0 * progress;
let alpha = 1.0 - progress;
(radius, alpha)
}
}