use rustc_hash::FxHashMap;
pub type EventType = u32;
pub mod event_types {
use super::EventType;
pub const POINTER_DOWN: EventType = 1;
pub const POINTER_UP: EventType = 2;
pub const POINTER_MOVE: EventType = 3;
pub const POINTER_ENTER: EventType = 4;
pub const POINTER_LEAVE: EventType = 5;
pub const DRAG: EventType = 6;
pub const DRAG_END: EventType = 7;
pub const FOCUS: EventType = 10;
pub const BLUR: EventType = 11;
pub const KEY_DOWN: EventType = 20;
pub const KEY_UP: EventType = 21;
pub const TEXT_INPUT: EventType = 22;
pub const SCROLL: EventType = 30;
pub const SCROLL_END: EventType = 31;
pub const PINCH: EventType = 32;
pub const ROTATE: EventType = 33;
pub const DOUBLE_TAP: EventType = 34;
pub const RESIZE: EventType = 40;
pub const FILE_DRAG_OVER: EventType = 35;
pub const FILE_DROP: EventType = 36;
pub const FILE_DRAG_LEAVE: EventType = 37;
pub const WINDOW_FOCUS: EventType = 50;
pub const WINDOW_BLUR: EventType = 51;
pub const MOUNT: EventType = 60;
pub const UNMOUNT: EventType = 61;
pub const CUT: EventType = 70;
pub const COPY: EventType = 71;
pub const PASTE: EventType = 72;
pub const SELECT_ALL: EventType = 80;
}
#[derive(Clone, Debug)]
pub struct Event {
pub event_type: EventType,
pub target: u64, pub data: EventData,
pub timestamp: u64,
pub propagation_stopped: bool,
}
#[derive(Clone, Debug)]
pub enum EventData {
Pointer {
x: f32,
y: f32,
button: u8,
pressure: f32,
},
Key {
key: KeyCode,
modifiers: Modifiers,
repeat: bool,
},
TextInput {
text: String,
},
Clipboard {
text: String,
},
Scroll {
delta_x: f32,
delta_y: f32,
},
Resize {
width: u32,
height: u32,
},
None,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
pub struct KeyCode(pub u32);
impl KeyCode {
pub const A: KeyCode = KeyCode(0x41);
pub const B: KeyCode = KeyCode(0x42);
pub const C: KeyCode = KeyCode(0x43);
pub const D: KeyCode = KeyCode(0x44);
pub const E: KeyCode = KeyCode(0x45);
pub const F: KeyCode = KeyCode(0x46);
pub const G: KeyCode = KeyCode(0x47);
pub const H: KeyCode = KeyCode(0x48);
pub const I: KeyCode = KeyCode(0x49);
pub const J: KeyCode = KeyCode(0x4A);
pub const K: KeyCode = KeyCode(0x4B);
pub const L: KeyCode = KeyCode(0x4C);
pub const M: KeyCode = KeyCode(0x4D);
pub const N: KeyCode = KeyCode(0x4E);
pub const O: KeyCode = KeyCode(0x4F);
pub const P: KeyCode = KeyCode(0x50);
pub const Q: KeyCode = KeyCode(0x51);
pub const R: KeyCode = KeyCode(0x52);
pub const S: KeyCode = KeyCode(0x53);
pub const T: KeyCode = KeyCode(0x54);
pub const U: KeyCode = KeyCode(0x55);
pub const V: KeyCode = KeyCode(0x56);
pub const W: KeyCode = KeyCode(0x57);
pub const X: KeyCode = KeyCode(0x58);
pub const Y: KeyCode = KeyCode(0x59);
pub const Z: KeyCode = KeyCode(0x5A);
pub const KEY_0: KeyCode = KeyCode(0x30);
pub const KEY_1: KeyCode = KeyCode(0x31);
pub const KEY_2: KeyCode = KeyCode(0x32);
pub const KEY_3: KeyCode = KeyCode(0x33);
pub const KEY_4: KeyCode = KeyCode(0x34);
pub const KEY_5: KeyCode = KeyCode(0x35);
pub const KEY_6: KeyCode = KeyCode(0x36);
pub const KEY_7: KeyCode = KeyCode(0x37);
pub const KEY_8: KeyCode = KeyCode(0x38);
pub const KEY_9: KeyCode = KeyCode(0x39);
pub const BACKSPACE: KeyCode = KeyCode(0x08);
pub const TAB: KeyCode = KeyCode(0x09);
pub const ENTER: KeyCode = KeyCode(0x0D);
pub const ESCAPE: KeyCode = KeyCode(0x1B);
pub const SPACE: KeyCode = KeyCode(0x20);
pub const DELETE: KeyCode = KeyCode(0x7F);
pub const LEFT: KeyCode = KeyCode(0x25);
pub const UP: KeyCode = KeyCode(0x26);
pub const RIGHT: KeyCode = KeyCode(0x27);
pub const DOWN: KeyCode = KeyCode(0x28);
pub const HOME: KeyCode = KeyCode(0x24);
pub const END: KeyCode = KeyCode(0x23);
pub const PAGE_UP: KeyCode = KeyCode(0x21);
pub const PAGE_DOWN: KeyCode = KeyCode(0x22);
pub const UNKNOWN: KeyCode = KeyCode(0);
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct Modifiers {
bits: u8,
}
impl Modifiers {
pub const NONE: Modifiers = Modifiers { bits: 0 };
pub const SHIFT: u8 = 0b0001;
pub const CTRL: u8 = 0b0010;
pub const ALT: u8 = 0b0100;
pub const META: u8 = 0b1000;
pub const fn new(shift: bool, ctrl: bool, alt: bool, meta: bool) -> Self {
let mut bits = 0;
if shift {
bits |= Self::SHIFT;
}
if ctrl {
bits |= Self::CTRL;
}
if alt {
bits |= Self::ALT;
}
if meta {
bits |= Self::META;
}
Self { bits }
}
pub const fn from_bits(bits: u8) -> Self {
Self { bits }
}
pub const fn shift(&self) -> bool {
self.bits & Self::SHIFT != 0
}
pub const fn ctrl(&self) -> bool {
self.bits & Self::CTRL != 0
}
pub const fn alt(&self) -> bool {
self.bits & Self::ALT != 0
}
pub const fn meta(&self) -> bool {
self.bits & Self::META != 0
}
pub const fn any(&self) -> bool {
self.bits != 0
}
#[cfg(target_os = "macos")]
pub const fn command(&self) -> bool {
self.meta()
}
#[cfg(not(target_os = "macos"))]
pub const fn command(&self) -> bool {
self.ctrl()
}
}
impl Event {
pub fn stop_propagation(&mut self) {
self.propagation_stopped = true;
}
}
pub type EventHandler = Box<dyn Fn(&Event) + Send + Sync>;
pub struct EventDispatcher {
handlers: FxHashMap<(u64, EventType), Vec<EventHandler>>,
}
impl EventDispatcher {
pub fn new() -> Self {
Self {
handlers: FxHashMap::default(),
}
}
pub fn register<F>(&mut self, widget_id: u64, event_type: EventType, handler: F)
where
F: Fn(&Event) + Send + Sync + 'static,
{
self.handlers
.entry((widget_id, event_type))
.or_default()
.push(Box::new(handler));
}
pub fn dispatch(&self, event: &mut Event) {
if let Some(handlers) = self.handlers.get(&(event.target, event.event_type)) {
for handler in handlers {
if event.propagation_stopped {
break;
}
handler(event);
}
}
}
}
impl Default for EventDispatcher {
fn default() -> Self {
Self::new()
}
}