Desktop: Support cursor icon change (#3223)

* browser console message forwarding

* replace target to make it easy to identify browser console messages

* use warn as per review comment

* cursor icon change

* fix win build
This commit is contained in:
Timon 2025-09-25 11:23:19 +00:00 committed by GitHub
parent b4be616de0
commit 04a2452333
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 94 additions and 12 deletions

View File

@ -305,6 +305,11 @@ impl App {
self.cef_schedule = Some(instant);
}
}
AppEvent::CursorChange(cursor) => {
if let Some(window) = &self.window {
window.set_cursor(cursor);
}
}
AppEvent::CloseWindow => {
// TODO: Implement graceful shutdown

View File

@ -44,6 +44,7 @@ pub(crate) trait CefEventHandler: Clone + Send + Sync + 'static {
#[cfg(feature = "accelerated_paint")]
fn draw_gpu(&self, shared_texture: SharedTextureHandle);
fn load_resource(&self, path: PathBuf) -> Option<Resource>;
fn cursor_change(&self, cursor: winit::cursor::Cursor);
/// Schedule the main event loop to run the CEF event loop after the timeout.
/// See [`_cef_browser_process_handler_t::on_schedule_message_pump_work`] for more documentation.
fn schedule_cef_message_loop_work(&self, scheduled_time: Instant);
@ -224,6 +225,10 @@ impl CefEventHandler for CefHandler {
None
}
fn cursor_change(&self, cursor: winit::cursor::Cursor) {
self.app_event_scheduler.schedule(AppEvent::CursorChange(cursor));
}
fn schedule_cef_message_loop_work(&self, scheduled_time: std::time::Instant) {
self.app_event_scheduler.schedule(AppEvent::ScheduleBrowserWork(scheduled_time));
}

View File

@ -19,8 +19,8 @@ impl<H: CefEventHandler> BrowserProcessClientImpl<H> {
Self {
object: std::ptr::null_mut(),
render_handler,
event_handler,
display_handler: DisplayHandler::new(DisplayHandlerImpl::new()),
event_handler: event_handler.clone(),
display_handler: DisplayHandler::new(DisplayHandlerImpl::new(event_handler)),
}
}
}

View File

@ -1,18 +1,86 @@
use cef::rc::{Rc, RcImpl};
use cef::sys::{_cef_display_handler_t, cef_base_ref_counted_t, cef_log_severity_t::*};
use cef::sys::{_cef_display_handler_t, cef_base_ref_counted_t, cef_cursor_type_t::*, cef_log_severity_t::*};
use cef::{CefString, ImplDisplayHandler, WrapDisplayHandler};
use winit::cursor::CursorIcon;
pub(crate) struct DisplayHandlerImpl {
use crate::cef::CefEventHandler;
pub(crate) struct DisplayHandlerImpl<H: CefEventHandler> {
object: *mut RcImpl<_cef_display_handler_t, Self>,
event_handler: H,
}
impl DisplayHandlerImpl {
pub fn new() -> Self {
Self { object: std::ptr::null_mut() }
impl<H: CefEventHandler> DisplayHandlerImpl<H> {
pub fn new(event_handler: H) -> Self {
Self {
object: std::ptr::null_mut(),
event_handler,
}
}
}
impl ImplDisplayHandler for DisplayHandlerImpl {
impl<H: CefEventHandler> ImplDisplayHandler for DisplayHandlerImpl<H> {
fn on_cursor_change(&self, _browser: Option<&mut cef::Browser>, _cursor: cef::CursorHandle, cursor_type: cef::CursorType, _custom_cursor_info: Option<&cef::CursorInfo>) -> ::std::os::raw::c_int {
let cursor = match cursor_type.into() {
CT_POINTER => CursorIcon::Default,
CT_CROSS => CursorIcon::Crosshair,
CT_HAND => CursorIcon::Pointer,
CT_IBEAM => CursorIcon::Text,
CT_WAIT => CursorIcon::Wait,
CT_HELP => CursorIcon::Help,
CT_EASTRESIZE => CursorIcon::EResize,
CT_NORTHRESIZE => CursorIcon::NResize,
CT_NORTHEASTRESIZE => CursorIcon::NeResize,
CT_NORTHWESTRESIZE => CursorIcon::NwResize,
CT_SOUTHRESIZE => CursorIcon::SResize,
CT_SOUTHEASTRESIZE => CursorIcon::SeResize,
CT_SOUTHWESTRESIZE => CursorIcon::SwResize,
CT_WESTRESIZE => CursorIcon::WResize,
CT_NORTHSOUTHRESIZE => CursorIcon::NsResize,
CT_EASTWESTRESIZE => CursorIcon::EwResize,
CT_NORTHEASTSOUTHWESTRESIZE => CursorIcon::NeswResize,
CT_NORTHWESTSOUTHEASTRESIZE => CursorIcon::NwseResize,
CT_COLUMNRESIZE => CursorIcon::ColResize,
CT_ROWRESIZE => CursorIcon::RowResize,
CT_MIDDLEPANNING => CursorIcon::AllScroll,
CT_EASTPANNING => CursorIcon::AllScroll,
CT_NORTHPANNING => CursorIcon::AllScroll,
CT_NORTHEASTPANNING => CursorIcon::AllScroll,
CT_NORTHWESTPANNING => CursorIcon::AllScroll,
CT_SOUTHPANNING => CursorIcon::AllScroll,
CT_SOUTHEASTPANNING => CursorIcon::AllScroll,
CT_SOUTHWESTPANNING => CursorIcon::AllScroll,
CT_WESTPANNING => CursorIcon::AllScroll,
CT_MOVE => CursorIcon::Move,
CT_VERTICALTEXT => CursorIcon::VerticalText,
CT_CELL => CursorIcon::Cell,
CT_CONTEXTMENU => CursorIcon::ContextMenu,
CT_ALIAS => CursorIcon::Alias,
CT_PROGRESS => CursorIcon::Progress,
CT_NODROP => CursorIcon::NoDrop,
CT_COPY => CursorIcon::Copy,
CT_NONE => CursorIcon::Default,
CT_NOTALLOWED => CursorIcon::NotAllowed,
CT_ZOOMIN => CursorIcon::ZoomIn,
CT_ZOOMOUT => CursorIcon::ZoomOut,
CT_GRAB => CursorIcon::Grab,
CT_GRABBING => CursorIcon::Grabbing,
CT_MIDDLE_PANNING_VERTICAL => CursorIcon::AllScroll,
CT_MIDDLE_PANNING_HORIZONTAL => CursorIcon::AllScroll,
CT_CUSTOM => CursorIcon::Default,
CT_DND_NONE => CursorIcon::Default,
CT_DND_MOVE => CursorIcon::Move,
CT_DND_COPY => CursorIcon::Copy,
CT_DND_LINK => CursorIcon::Alias,
CT_NUM_VALUES => CursorIcon::Default,
_ => CursorIcon::Default,
};
self.event_handler.cursor_change(cursor.into());
1 // We handled the cursor change.
}
fn on_console_message(
&self,
_browser: Option<&mut cef::Browser>,
@ -41,16 +109,19 @@ impl ImplDisplayHandler for DisplayHandlerImpl {
}
}
impl Clone for DisplayHandlerImpl {
impl<H: CefEventHandler> Clone for DisplayHandlerImpl<H> {
fn clone(&self) -> Self {
unsafe {
let rc_impl = &mut *self.object;
rc_impl.interface.add_ref();
}
Self { object: self.object }
Self {
object: self.object,
event_handler: self.event_handler.clone(),
}
}
}
impl Rc for DisplayHandlerImpl {
impl<H: CefEventHandler> Rc for DisplayHandlerImpl<H> {
fn as_base(&self) -> &cef_base_ref_counted_t {
unsafe {
let base = &*self.object;
@ -58,7 +129,7 @@ impl Rc for DisplayHandlerImpl {
}
}
}
impl WrapDisplayHandler for DisplayHandlerImpl {
impl<H: CefEventHandler> WrapDisplayHandler for DisplayHandlerImpl<H> {
fn wrap_rc(&mut self, object: *mut RcImpl<_cef_display_handler_t, Self>) {
self.object = object;
}

View File

@ -3,6 +3,7 @@ use graphite_desktop_wrapper::messages::DesktopWrapperMessage;
pub(crate) enum AppEvent {
UiUpdate(wgpu::Texture),
CursorChange(winit::cursor::Cursor),
ScheduleBrowserWork(std::time::Instant),
WebCommunicationInitialized,
DesktopWrapperMessage(DesktopWrapperMessage),