diff --git a/crates/processing_ffi/src/lib.rs b/crates/processing_ffi/src/lib.rs index f7eac79..f2a98a8 100644 --- a/crates/processing_ffi/src/lib.rs +++ b/crates/processing_ffi/src/lib.rs @@ -2939,6 +2939,43 @@ pub extern "C" fn processing_input_focus(surface_id: u64, focused: bool) { error::check(|| input_set_focus(Entity::from_bits(surface_id), focused)); } +pub const PROCESSING_CURSOR_ARROW: u8 = 0; +pub const PROCESSING_CURSOR_CROSS: u8 = 1; +pub const PROCESSING_CURSOR_HAND: u8 = 2; +pub const PROCESSING_CURSOR_MOVE: u8 = 3; +pub const PROCESSING_CURSOR_TEXT: u8 = 4; +pub const PROCESSING_CURSOR_WAIT: u8 = 5; + +fn cursor_icon(kind: u8) -> bevy::window::SystemCursorIcon { + use bevy::window::SystemCursorIcon; + match kind { + PROCESSING_CURSOR_CROSS => SystemCursorIcon::Crosshair, + PROCESSING_CURSOR_HAND => SystemCursorIcon::Pointer, + PROCESSING_CURSOR_MOVE => SystemCursorIcon::Move, + PROCESSING_CURSOR_TEXT => SystemCursorIcon::Text, + PROCESSING_CURSOR_WAIT => SystemCursorIcon::Wait, + _ => SystemCursorIcon::Default, + } +} + +/// Show the mouse cursor with the given system type (PROCESSING_CURSOR_*). +#[unsafe(no_mangle)] +pub extern "C" fn processing_cursor(surface_id: u64, kind: u8) { + error::clear_error(); + let surface = Entity::from_bits(surface_id); + error::check(|| { + input_set_cursor_visible(surface, true)?; + input_set_cursor_icon(surface, cursor_icon(kind)) + }); +} + +/// Hide the mouse cursor. +#[unsafe(no_mangle)] +pub extern "C" fn processing_no_cursor(surface_id: u64) { + error::clear_error(); + error::check(|| input_set_cursor_visible(Entity::from_bits(surface_id), false)); +} + #[unsafe(no_mangle)] pub extern "C" fn processing_input_flush() { error::clear_error(); diff --git a/crates/processing_input/src/lib.rs b/crates/processing_input/src/lib.rs index 98d715c..d5a62e7 100644 --- a/crates/processing_input/src/lib.rs +++ b/crates/processing_input/src/lib.rs @@ -177,6 +177,27 @@ pub fn input_cursor_visible(surface: Entity) -> error::Result { }) } +pub fn input_set_cursor_visible(surface: Entity, visible: bool) -> error::Result<()> { + app_mut(|app| { + if let Some(mut cursor) = app.world_mut().get_mut::(surface) { + cursor.visible = visible; + } + Ok(()) + }) +} + +pub fn input_set_cursor_icon( + surface: Entity, + icon: bevy::window::SystemCursorIcon, +) -> error::Result<()> { + app_mut(|app| { + if let Ok(mut entity) = app.world_mut().get_entity_mut(surface) { + entity.insert(bevy::window::CursorIcon::System(icon)); + } + Ok(()) + }) +} + /// Flushes the input state by running the relevant schedules. This is required to ensure that /// Bevy's bookkeeping of input state is up to date after manually sending input events. /// It should be called after sending any input events and before querying input state