mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-02-17 14:07:28 +08:00
fix: cursor, macos, text (#12794)
Signed-off-by: fufesou <linlong1266@gmail.com>
This commit is contained in:
@@ -3,11 +3,11 @@ use core_graphics::context::CGContextRef;
|
|||||||
use foreign_types::ForeignTypeRef;
|
use foreign_types::ForeignTypeRef;
|
||||||
use hbb_common::{bail, log, ResultType};
|
use hbb_common::{bail, log, ResultType};
|
||||||
use objc::{class, msg_send, runtime::Object, sel, sel_impl};
|
use objc::{class, msg_send, runtime::Object, sel, sel_impl};
|
||||||
use piet::{kurbo::BezPath, RenderContext};
|
use piet::{kurbo::BezPath, FontFamily, RenderContext, Text, TextLayoutBuilder};
|
||||||
use piet_coregraphics::CoreGraphicsContext;
|
use piet_coregraphics::{CoreGraphicsContext, CoreGraphicsTextLayout};
|
||||||
use std::{collections::HashMap, sync::Arc, time::Instant};
|
use std::{collections::HashMap, sync::Arc, time::Instant};
|
||||||
use tao::{
|
use tao::{
|
||||||
dpi::{LogicalSize, PhysicalPosition, PhysicalSize},
|
dpi::{LogicalSize, PhysicalPosition},
|
||||||
event::{Event, StartCause, WindowEvent},
|
event::{Event, StartCause, WindowEvent},
|
||||||
event_loop::{ControlFlow, EventLoop, EventLoopBuilder},
|
event_loop::{ControlFlow, EventLoop, EventLoopBuilder},
|
||||||
platform::macos::MonitorHandleExtMacOS,
|
platform::macos::MonitorHandleExtMacOS,
|
||||||
@@ -16,6 +16,8 @@ use tao::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
const MAXIMUM_WINDOW_LEVEL: i64 = 2147483647;
|
const MAXIMUM_WINDOW_LEVEL: i64 = 2147483647;
|
||||||
|
const CURSOR_TEXT_FONT_SIZE: f64 = 14.0;
|
||||||
|
const CURSOR_TEXT_OFFSET: f64 = 20.0;
|
||||||
|
|
||||||
struct WindowState {
|
struct WindowState {
|
||||||
window: Arc<Window>,
|
window: Arc<Window>,
|
||||||
@@ -31,6 +33,12 @@ struct Ripple {
|
|||||||
start_time: Instant,
|
start_time: Instant,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct CursorInfo {
|
||||||
|
window_id: WindowId,
|
||||||
|
text_key: (String, u32),
|
||||||
|
cursor: Cursor,
|
||||||
|
}
|
||||||
|
|
||||||
fn set_window_properties(window: &Arc<Window>) -> ResultType<()> {
|
fn set_window_properties(window: &Arc<Window>) -> ResultType<()> {
|
||||||
let handle = window.window_handle()?;
|
let handle = window.window_handle()?;
|
||||||
if let RawWindowHandle::AppKit(appkit_handle) = handle.as_raw() {
|
if let RawWindowHandle::AppKit(appkit_handle) = handle.as_raw() {
|
||||||
@@ -108,7 +116,8 @@ fn draw_cursors(
|
|||||||
windows: &Vec<WindowState>,
|
windows: &Vec<WindowState>,
|
||||||
window_id: WindowId,
|
window_id: WindowId,
|
||||||
window_ripples: &mut HashMap<WindowId, Vec<Ripple>>,
|
window_ripples: &mut HashMap<WindowId, Vec<Ripple>>,
|
||||||
last_cursors: &HashMap<String, (WindowId, Cursor)>,
|
last_cursors: &HashMap<String, CursorInfo>,
|
||||||
|
map_cursor_text: &mut HashMap<(String, u32), CoreGraphicsTextLayout>,
|
||||||
) {
|
) {
|
||||||
for window in windows.iter() {
|
for window in windows.iter() {
|
||||||
if window.window.id() != window_id {
|
if window.window.id() != window_id {
|
||||||
@@ -154,10 +163,11 @@ fn draw_cursors(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
for (wid, cursor) in last_cursors.values() {
|
for info in last_cursors.values() {
|
||||||
if *wid != window.window.id() {
|
if info.window_id != window.window.id() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
let cursor = &info.cursor;
|
||||||
|
|
||||||
let (x, y) = (cursor.x as f64, cursor.y as f64);
|
let (x, y) = (cursor.x as f64, cursor.y as f64);
|
||||||
let size = 1.0;
|
let size = 1.0;
|
||||||
@@ -178,6 +188,23 @@ fn draw_cursors(
|
|||||||
(cursor.argb >> 24 & 0xFF) as u8,
|
(cursor.argb >> 24 & 0xFF) as u8,
|
||||||
);
|
);
|
||||||
context.fill(pb, &color);
|
context.fill(pb, &color);
|
||||||
|
|
||||||
|
let pos =
|
||||||
|
(x + CURSOR_TEXT_OFFSET * size, y + CURSOR_TEXT_OFFSET * size);
|
||||||
|
if let Some(layout) = map_cursor_text.get(&info.text_key) {
|
||||||
|
context.draw_text(layout, pos);
|
||||||
|
} else {
|
||||||
|
let text = context.text();
|
||||||
|
if let Ok(layout) = text
|
||||||
|
.new_text_layout(cursor.text.clone())
|
||||||
|
.font(FontFamily::SYSTEM_UI, CURSOR_TEXT_FONT_SIZE)
|
||||||
|
.text_color(color)
|
||||||
|
.build()
|
||||||
|
{
|
||||||
|
context.draw_text(&layout, pos);
|
||||||
|
map_cursor_text.insert(info.text_key.clone(), layout);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if let Err(e) = context.finish() {
|
if let Err(e) = context.finish() {
|
||||||
log::error!("Failed to draw cursor: {}", e);
|
log::error!("Failed to draw cursor: {}", e);
|
||||||
@@ -209,7 +236,8 @@ pub(super) fn create_event_loop() -> ResultType<()> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let mut window_ripples: HashMap<WindowId, Vec<Ripple>> = HashMap::new();
|
let mut window_ripples: HashMap<WindowId, Vec<Ripple>> = HashMap::new();
|
||||||
let mut last_cursors: HashMap<String, (WindowId, Cursor)> = HashMap::new();
|
let mut last_cursors: HashMap<String, CursorInfo> = HashMap::new();
|
||||||
|
let mut map_cursor_text: HashMap<(String, u32), CoreGraphicsTextLayout> = HashMap::new();
|
||||||
|
|
||||||
event_loop.run(move |event, _, control_flow| {
|
event_loop.run(move |event, _, control_flow| {
|
||||||
*control_flow = ControlFlow::Poll;
|
*control_flow = ControlFlow::Poll;
|
||||||
@@ -229,7 +257,13 @@ pub(super) fn create_event_loop() -> ResultType<()> {
|
|||||||
_ => {}
|
_ => {}
|
||||||
},
|
},
|
||||||
Event::RedrawRequested(window_id) => {
|
Event::RedrawRequested(window_id) => {
|
||||||
draw_cursors(&windows, window_id, &mut window_ripples, &last_cursors);
|
draw_cursors(
|
||||||
|
&windows,
|
||||||
|
window_id,
|
||||||
|
&mut window_ripples,
|
||||||
|
&last_cursors,
|
||||||
|
&mut map_cursor_text,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
Event::MainEventsCleared => {
|
Event::MainEventsCleared => {
|
||||||
for window in windows.iter() {
|
for window in windows.iter() {
|
||||||
@@ -268,14 +302,15 @@ pub(super) fn create_event_loop() -> ResultType<()> {
|
|||||||
}
|
}
|
||||||
last_cursors.insert(
|
last_cursors.insert(
|
||||||
k,
|
k,
|
||||||
(
|
CursorInfo {
|
||||||
window.window.id(),
|
window_id: window.window.id(),
|
||||||
Cursor {
|
text_key: (cursor.text.clone(), cursor.argb),
|
||||||
|
cursor: Cursor {
|
||||||
x: (cursor.x - window.display_origin.0 as f32),
|
x: (cursor.x - window.display_origin.0 as f32),
|
||||||
y: (cursor.y - window.display_origin.1 as f32),
|
y: (cursor.y - window.display_origin.1 as f32),
|
||||||
..cursor
|
..cursor
|
||||||
},
|
},
|
||||||
),
|
},
|
||||||
);
|
);
|
||||||
window.window.request_redraw();
|
window.window.request_redraw();
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
use super::{create_event_loop, CustomEvent};
|
use super::{create_event_loop, CustomEvent};
|
||||||
use crate::ipc::{new_listener, Connection, Data};
|
use crate::ipc::{new_listener, Connection, Data};
|
||||||
|
#[cfg(any(target_os = "windows", target_os = "linux"))]
|
||||||
|
use hbb_common::ResultType;
|
||||||
use hbb_common::{
|
use hbb_common::{
|
||||||
allow_err, log,
|
allow_err, log,
|
||||||
tokio::{
|
tokio::{
|
||||||
self,
|
self,
|
||||||
sync::mpsc::{unbounded_channel, UnboundedReceiver},
|
sync::mpsc::{unbounded_channel, UnboundedReceiver},
|
||||||
},
|
},
|
||||||
ResultType,
|
|
||||||
};
|
};
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use std::sync::RwLock;
|
use std::sync::RwLock;
|
||||||
@@ -99,6 +100,7 @@ async fn handle_new_stream(mut conn: Connection) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(target_os = "windows", target_os = "linux"))]
|
||||||
pub(super) fn get_displays_rect() -> ResultType<(i32, i32, u32, u32)> {
|
pub(super) fn get_displays_rect() -> ResultType<(i32, i32, u32, u32)> {
|
||||||
let displays = crate::server::display_service::try_get_displays()?;
|
let displays = crate::server::display_service::try_get_displays()?;
|
||||||
let mut min_x = i32::MAX;
|
let mut min_x = i32::MAX;
|
||||||
|
|||||||
Reference in New Issue
Block a user