use denise::{ElementState, InputEvent, Point};
use crate::keys;
use crate::types::{button, modifiers};
use crate::{
DENISE_ERR_INVALID, DENISE_ERR_NULL, DENISE_ERR_PANIC, DENISE_OK, DeniseUi, guard, handle,
};
unsafe fn send(ui: *mut DeniseUi, event: InputEvent) -> i32 {
guard(DENISE_ERR_PANIC, || {
let Some(handle) = (unsafe { handle(ui) }) else {
return DENISE_ERR_NULL;
};
handle.ui.handle(&[event]);
DENISE_OK
})
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn denise_ui_pointer_moved(ui: *mut DeniseUi, x: i32, y: i32) -> i32 {
unsafe {
send(
ui,
InputEvent::PointerMoved {
position: Point::new(x, y),
},
)
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn denise_ui_pointer_button(
ui: *mut DeniseUi,
button_value: u32,
down: bool,
x: i32,
y: i32,
modifier_bits: u32,
) -> i32 {
let Some(button) = button(button_value) else {
return DENISE_ERR_INVALID;
};
unsafe {
send(
ui,
InputEvent::PointerButton {
button,
state: state(down),
position: Point::new(x, y),
modifiers: modifiers(modifier_bits),
},
)
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn denise_ui_pointer_scroll(
ui: *mut DeniseUi,
delta_x: f32,
delta_y: f32,
x: i32,
y: i32,
) -> i32 {
unsafe {
send(
ui,
InputEvent::PointerScroll {
delta_x,
delta_y,
position: Point::new(x, y),
},
)
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn denise_ui_pointer_left(ui: *mut DeniseUi) -> i32 {
unsafe { send(ui, InputEvent::PointerLeft) }
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn denise_ui_touch(
ui: *mut DeniseUi,
id: u64,
phase: u32,
x: i32,
y: i32,
) -> i32 {
let position = Point::new(x, y);
let event = match phase {
DENISE_TOUCH_DOWN => InputEvent::TouchDown { id, position },
DENISE_TOUCH_MOVED => InputEvent::TouchMoved { id, position },
DENISE_TOUCH_UP => InputEvent::TouchUp {
id,
position,
cancelled: false,
},
DENISE_TOUCH_CANCELLED => InputEvent::TouchUp {
id,
position,
cancelled: true,
},
_ => return DENISE_ERR_INVALID,
};
unsafe { send(ui, event) }
}
pub const DENISE_TOUCH_DOWN: u32 = 0;
pub const DENISE_TOUCH_MOVED: u32 = 1;
pub const DENISE_TOUCH_UP: u32 = 2;
pub const DENISE_TOUCH_CANCELLED: u32 = 3;
#[unsafe(no_mangle)]
pub unsafe extern "C" fn denise_ui_key(
ui: *mut DeniseUi,
key: u32,
down: bool,
repeat: bool,
modifier_bits: u32,
) -> i32 {
let Some(code) = keys::from_abi(key) else {
return DENISE_ERR_INVALID;
};
unsafe {
send(
ui,
InputEvent::Key {
code,
state: state(down),
repeat,
modifiers: modifiers(modifier_bits),
},
)
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn denise_ui_text(ui: *mut DeniseUi, codepoint: u32) -> i32 {
let Some(ch) = char::from_u32(codepoint) else {
return DENISE_ERR_INVALID;
};
if ch.is_control() {
return DENISE_ERR_INVALID;
}
unsafe { send(ui, InputEvent::Text { ch }) }
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn denise_ui_tick(ui: *mut DeniseUi, now_ms: u64) -> i32 {
guard(DENISE_ERR_PANIC, || {
let Some(handle) = (unsafe { handle(ui) }) else {
return DENISE_ERR_NULL;
};
handle.ui.tick(now_ms);
DENISE_OK
})
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn denise_ui_next_wake_ms(ui: *mut DeniseUi) -> i64 {
guard(-1, || {
let Some(handle) = (unsafe { handle(ui) }) else {
return -1;
};
handle.ui.next_wake_ms().map_or(-1, |ms| ms as i64)
})
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn denise_ui_show_cursor(ui: *mut DeniseUi, visible: bool) -> i32 {
guard(DENISE_ERR_PANIC, || {
let Some(handle) = (unsafe { handle(ui) }) else {
return DENISE_ERR_NULL;
};
handle.ui.show_cursor(visible);
DENISE_OK
})
}
fn state(down: bool) -> ElementState {
if down {
ElementState::Down
} else {
ElementState::Up
}
}