use dear_imgui_rs::Context;
use dear_imgui_rs::input::MouseSource;
use winit::event::{DeviceEvent, ElementState, Ime, KeyEvent, MouseScrollDelta, TouchPhase};
use std::cell::RefCell;
use winit::window::Window;
use crate::input::{to_imgui_mouse_button, winit_key_to_imgui_key};
pub fn handle_keyboard_input(event: &KeyEvent, imgui_ctx: &mut Context) -> bool {
let io = imgui_ctx.io_mut();
if event.state.is_pressed()
&& let Some(txt) = &event.text
{
for ch in txt.chars() {
if ch != '\u{7f}' {
io.add_input_character(ch);
}
}
}
if let Some(imgui_key) = winit_key_to_imgui_key(&event.logical_key, event.location) {
let pressed = event.state == ElementState::Pressed;
io.add_key_event(imgui_key, pressed);
return io.want_capture_keyboard();
}
false
}
pub fn handle_mouse_wheel(delta: MouseScrollDelta, imgui_ctx: &mut Context) -> bool {
let io = imgui_ctx.io_mut();
io.add_mouse_source_event(MouseSource::Mouse);
match delta {
MouseScrollDelta::LineDelta(h, v) => io.add_mouse_wheel_event([h, v]),
MouseScrollDelta::PixelDelta(pos) => {
let h = match pos.x.partial_cmp(&0.0) {
Some(std::cmp::Ordering::Greater) => 1.0,
Some(std::cmp::Ordering::Less) => -1.0,
_ => 0.0,
};
let v = match pos.y.partial_cmp(&0.0) {
Some(std::cmp::Ordering::Greater) => 1.0,
Some(std::cmp::Ordering::Less) => -1.0,
_ => 0.0,
};
io.add_mouse_wheel_event([h, v]);
}
}
io.want_capture_mouse()
}
pub fn handle_mouse_button(
button: winit::event::MouseButton,
state: ElementState,
imgui_ctx: &mut Context,
) -> bool {
if let Some(imgui_button) = to_imgui_mouse_button(button) {
let pressed = state == ElementState::Pressed;
{
let io = imgui_ctx.io_mut();
io.add_mouse_source_event(MouseSource::Mouse);
io.add_mouse_button_event(imgui_button, pressed);
}
return imgui_ctx.io().want_capture_mouse();
}
false
}
pub fn handle_cursor_moved(position: [f64; 2], imgui_ctx: &mut Context) -> bool {
{
let io = imgui_ctx.io_mut();
io.add_mouse_source_event(MouseSource::Mouse);
io.add_mouse_pos_event([position[0] as f32, position[1] as f32]);
}
imgui_ctx.io().want_capture_mouse()
}
pub fn handle_modifiers_changed(modifiers: &winit::event::Modifiers, imgui_ctx: &mut Context) {
let io = imgui_ctx.io_mut();
let state = modifiers.state();
io.add_key_event(dear_imgui_rs::Key::ModShift, state.shift_key());
io.add_key_event(dear_imgui_rs::Key::LeftShift, state.shift_key());
io.add_key_event(dear_imgui_rs::Key::RightShift, state.shift_key());
io.add_key_event(dear_imgui_rs::Key::ModCtrl, state.control_key());
io.add_key_event(dear_imgui_rs::Key::LeftCtrl, state.control_key());
io.add_key_event(dear_imgui_rs::Key::RightCtrl, state.control_key());
io.add_key_event(dear_imgui_rs::Key::ModAlt, state.alt_key());
io.add_key_event(dear_imgui_rs::Key::LeftAlt, state.alt_key());
io.add_key_event(dear_imgui_rs::Key::RightAlt, state.alt_key());
io.add_key_event(dear_imgui_rs::Key::ModSuper, state.super_key());
io.add_key_event(dear_imgui_rs::Key::LeftSuper, state.super_key());
io.add_key_event(dear_imgui_rs::Key::RightSuper, state.super_key());
}
pub fn handle_ime_event(ime: &Ime, imgui_ctx: &mut Context) {
match ime {
Ime::Preedit(_text, _cursor_range) => {
}
Ime::Commit(text) => {
for ch in text.chars() {
if !ch.is_control() {
imgui_ctx.io_mut().add_input_character(ch);
}
}
}
Ime::Enabled => {
}
Ime::Disabled => {
}
}
}
pub fn handle_touch_event(touch: &winit::event::Touch, _window: &Window, _imgui_ctx: &mut Context) {
thread_local! {
static ACTIVE_TOUCH: RefCell<Option<u64>> = const { RefCell::new(None) };
}
ACTIVE_TOUCH.with(|active| {
let active_id = *active.borrow();
let id = touch.id;
match touch.phase {
TouchPhase::Started => {
if active_id.is_none() {
*active.borrow_mut() = Some(id);
let pos = touch.location.to_logical::<f64>(_window.scale_factor());
let io = _imgui_ctx.io_mut();
io.add_mouse_source_event(MouseSource::TouchScreen);
io.add_mouse_pos_event([pos.x as f32, pos.y as f32]);
io.add_mouse_button_event(dear_imgui_rs::input::MouseButton::Left, true);
}
}
TouchPhase::Moved => {
if active_id == Some(id) {
let pos = touch.location.to_logical::<f64>(_window.scale_factor());
let io = _imgui_ctx.io_mut();
io.add_mouse_source_event(MouseSource::TouchScreen);
io.add_mouse_pos_event([pos.x as f32, pos.y as f32]);
}
}
TouchPhase::Ended | TouchPhase::Cancelled => {
if active_id == Some(id) {
let pos = touch.location.to_logical::<f64>(_window.scale_factor());
let io = _imgui_ctx.io_mut();
io.add_mouse_source_event(MouseSource::TouchScreen);
io.add_mouse_pos_event([pos.x as f32, pos.y as f32]);
io.add_mouse_button_event(dear_imgui_rs::input::MouseButton::Left, false);
*active.borrow_mut() = None;
}
}
}
});
}
pub fn handle_device_event(_event: &DeviceEvent) {
}
pub fn handle_focused(focused: bool, imgui_ctx: &mut Context) -> bool {
imgui_ctx.io_mut().add_focus_event(focused);
false
}
#[cfg(test)]
mod tests {
use super::*;
use crate::test_util::test_sync::lock_context;
use dear_imgui_rs::Context;
use winit::event::{ElementState, MouseButton};
use winit::keyboard::ModifiersState;
#[test]
fn test_keyboard_input_handling() {
}
#[test]
fn test_mouse_button_handling() {
let _guard = lock_context();
let mut ctx = Context::create();
let handled = handle_mouse_button(MouseButton::Left, ElementState::Pressed, &mut ctx);
let _ = handled; }
#[test]
fn test_cursor_moved() {
let _guard = lock_context();
let mut ctx = Context::create();
let handled = handle_cursor_moved([100.0, 200.0], &mut ctx);
let _ = handled; }
#[test]
fn test_modifiers_changed_updates_key_mods() {
let _guard = lock_context();
let mut ctx = Context::create();
let io = ctx.io_mut();
io.set_display_size([1.0, 1.0]);
io.set_backend_flags(
io.backend_flags() | dear_imgui_rs::BackendFlags::RENDERER_HAS_TEXTURES,
);
ctx.fonts().build();
let modifiers: winit::event::Modifiers = ModifiersState::CONTROL.into();
handle_modifiers_changed(&modifiers, &mut ctx);
let ui = ctx.frame();
assert!(ui.io().key_ctrl());
assert!(!ui.io().key_shift());
assert!(!ui.io().key_alt());
assert!(!ui.io().key_super());
}
}