From 70d26c2744058cfc922527ef994126c6c840848b Mon Sep 17 00:00:00 2001 From: Ben Bridle Date: Thu, 3 Jul 2025 15:09:19 +1200 Subject: Tidy event code and add support for hover events --- src/phosphor.rs | 207 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 107 insertions(+), 100 deletions(-) (limited to 'src/phosphor.rs') diff --git a/src/phosphor.rs b/src/phosphor.rs index 34d5be5..122f36f 100644 --- a/src/phosphor.rs +++ b/src/phosphor.rs @@ -1,4 +1,5 @@ use crate::*; +use window::{PhosphorWindow, PointerState}; use winit::application::ApplicationHandler; use winit::dpi::{PhysicalPosition, PhysicalSize}; @@ -20,16 +21,13 @@ pub struct Phosphor { impl Phosphor { pub fn new() -> Result { if let Ok(event_loop) = EventLoop::new() { - Ok( Self { - event_loop, - builders: Vec::new(), - } ) + Ok( Self { event_loop, builders: Vec::new() } ) } else { Err(()) } } - pub fn create_window(&mut self, window: WindowBuilder) { + pub fn add_window(&mut self, window: WindowBuilder) { self.builders.push(window); } @@ -56,6 +54,7 @@ impl PhosphorApplication { let mut marked_ids = Vec::new(); for (id, window) in &mut self.windows { if window.marked_for_destruction { + // Allow marked windows to create new windows. window.handle_requests(&mut self.builders); marked_ids.push(id.clone()); } @@ -81,109 +80,117 @@ impl PhosphorApplication { } pub fn handle_window_event(&mut self, event: WindowEvent, id: WindowId) { - let window = match self.windows.get_mut(&id) { - Some(w) => w, - None => return, - }; - macro_rules! handle { ($event:expr) => { - window.program.handle_event($event, &mut window.requests.as_writer()) - }; } - - match event { - WindowEvent::Resized( PhysicalSize { width, height } ) => { - window.update_buffer_size(Dimensions::new(width, height)); - } - WindowEvent::CloseRequested => { - handle!(Event::CloseRequest); - } - WindowEvent::Destroyed => { - handle!(Event::Close); - } - WindowEvent::DroppedFile(path) => { - handle!(Event::FileDrop(path)); - } - WindowEvent::Focused(focused) => { - handle!(Event::FocusChange(focused)); - } - WindowEvent::KeyboardInput { event, .. } => { - if let Some(smol_str) = event.text { - if event.state.is_pressed() { - for c in smol_str.chars() { - handle!(Event::CharacterInput(c)); - } - } - } - if let PhysicalKey::Code(code) = event.physical_key { - handle!(Event::KeyboardInput { - key: code, - action: event.state.into(), - }); + if let Some(window) = self.windows.get_mut(&id) { + macro_rules! writer { () => { &mut window.requests.as_writer() } } + match event { + WindowEvent::RedrawRequested => + window.redraw(), + WindowEvent::CloseRequested => + window.program.handle_event(Event::CloseRequest, writer!()), + WindowEvent::Destroyed => + window.program.handle_event(Event::Close, writer!()), + WindowEvent::Resized( PhysicalSize { width, height } ) => + window.update_buffer_size(Dimensions::new(width, height)), + WindowEvent::Focused(focused) => + window.program.handle_event(Event::FocusChange(focused), writer!()), + WindowEvent::CursorEntered { .. } => { + window.pointer_state = PointerState::In; + window.program.handle_event(Event::CursorEnter, writer!()); } - } - WindowEvent::ModifiersChanged(modifiers) => { - handle!(Event::ModifierChange(modifiers.state())); - } - WindowEvent::CursorMoved { position, .. } => { - let pointer = Position::new( - position.x as i32 / window.scale() as i32, - position.y as i32 / window.scale() as i32, - ); - if window.pointer != Some(pointer) { - window.pointer = Some(pointer); - handle!(Event::CursorMove(pointer)); + WindowEvent::CursorLeft { .. } => { + if window.mouse_buttons.iter().all(|b| !b) { + window.pointer_state = PointerState::Out; + window.program.handle_event(Event::CursorExit, writer!()); + } else { + window.pointer_state = PointerState::PendingOut; + } } - } - WindowEvent::CursorEntered { .. } => { - window.pointer_state = PointerState::In; - handle!(Event::CursorEnter); - } - WindowEvent::CursorLeft { .. } => { - if window.mouse_buttons.iter().all(|b| !b) { - window.pointer_state = PointerState::Out; - handle!(Event::CursorExit); - } else { - window.pointer_state = PointerState::PendingOut; + WindowEvent::CursorMoved { position, .. } => { + let pointer = Position::new( + position.x as i32 / window.scale() as i32, + position.y as i32 / window.scale() as i32, + ); + if window.pointer != Some(pointer) { + window.pointer = Some(pointer); + window.program.handle_event(Event::CursorMove(pointer), writer!()); + } } - } - WindowEvent::MouseWheel { delta, .. } => match delta { - MouseScrollDelta::LineDelta(x, y) => { - if x != 0.0 { handle!(Event::ScrollLines { axis: Axis::Horizontal, distance: -x }); } - if y != 0.0 { handle!(Event::ScrollLines { axis: Axis::Vertical, distance: -y }); } + WindowEvent::MouseWheel { delta, .. } => match delta { + MouseScrollDelta::LineDelta(x, y) => { + if x != 0.0 { + let axis = Axis::Horizontal; let distance = -x; + window.program.handle_event(Event::ScrollLines { axis, distance }, writer!()); + } + if y != 0.0 { + let axis = Axis::Vertical; let distance = -y; + window.program.handle_event(Event::ScrollLines { axis, distance }, writer!()); + } + } + MouseScrollDelta::PixelDelta(PhysicalPosition {x, y}) => { + if x != 0.0 { + let axis = Axis::Horizontal; let distance = -x as f32; + window.program.handle_event(Event::ScrollPixels { axis, distance }, writer!()); + } + if y != 0.0 { + let axis = Axis::Vertical; let distance = -y as f32; + window.program.handle_event(Event::ScrollPixels { axis, distance }, writer!()); + } + } } - MouseScrollDelta::PixelDelta(PhysicalPosition {x, y}) => { - if x != 0.0 { handle!(Event::ScrollPixels { axis: Axis::Horizontal, distance: -x as f32 }); } - if y != 0.0 { handle!(Event::ScrollPixels { axis: Axis::Vertical, distance: -y as f32 }); } + WindowEvent::MouseInput { state, button, .. } => { + let action = state.into(); + match button { + WinitMouseButton::Left => + window.program.handle_event(Event::MouseButton { button: MouseButton::Left, action }, writer!()), + WinitMouseButton::Middle => + window.program.handle_event(Event::MouseButton { button: MouseButton::Middle, action }, writer!()), + WinitMouseButton::Right => + window.program.handle_event(Event::MouseButton { button: MouseButton::Right, action }, writer!()), + WinitMouseButton::Back => + window.program.handle_event(Event::MouseButton { button: MouseButton::Back, action }, writer!()), + WinitMouseButton::Forward => + window.program.handle_event(Event::MouseButton { button: MouseButton::Forward, action }, writer!()), + _ => (), + } + // Record mouse button hold states, and mark cursor as out when all are released. + let button_index = match button { + WinitMouseButton::Left => 0, + WinitMouseButton::Middle => 1, + WinitMouseButton::Right => 2, + WinitMouseButton::Back => 3, + WinitMouseButton::Forward => 4, + _ => return, + }; + window.mouse_buttons[button_index] = action.is_pressed(); + if window.pointer_state == PointerState::PendingOut && window.mouse_buttons.iter().all(|b| !b) { + window.pointer_state = PointerState::Out; + window.program.handle_event(Event::CursorExit, writer!()); + } } - } - WindowEvent::MouseInput { state, button, .. } => { - let action = state.into(); - match button { - WinitMouseButton::Left => handle!(Event::MouseButton { button: MouseButton::Left, action }), - WinitMouseButton::Middle => handle!(Event::MouseButton { button: MouseButton::Middle, action }), - WinitMouseButton::Right => handle!(Event::MouseButton { button: MouseButton::Right, action }), - WinitMouseButton::Back => handle!(Event::MouseButton { button: MouseButton::Back, action }), - WinitMouseButton::Forward => handle!(Event::MouseButton { button: MouseButton::Forward, action }), - _ => (), + WindowEvent::KeyboardInput { event, .. } => { + if let Some(smol_str) = event.text { + if event.state.is_pressed() { + for c in smol_str.chars() { + window.program.handle_event(Event::CharacterInput(c), writer!()); + } + } + } + if let PhysicalKey::Code(code) = event.physical_key { + let key = code; let action = event.state.into(); + window.program.handle_event(Event::KeyboardInput { key, action }, writer!()); + } } - // Keep track of mouse button hold states, and mark cursor as out when all are released. - let button_index = match button { - WinitMouseButton::Left => 0, - WinitMouseButton::Middle => 1, - WinitMouseButton::Right => 2, - WinitMouseButton::Back => 3, - WinitMouseButton::Forward => 4, - _ => return, - }; - window.mouse_buttons[button_index] = action.is_pressed(); - if window.pointer_state == PointerState::PendingOut && window.mouse_buttons.iter().all(|b| !b) { - window.pointer_state = PointerState::Out; - handle!(Event::CursorExit); + WindowEvent::ModifiersChanged(modifiers) => { + window.program.handle_event(Event::ModifierChange(modifiers.state()), writer!()); } + WindowEvent::DroppedFile(path) => + window.program.handle_event(Event::DropFile(path), writer!()), + WindowEvent::HoveredFile(path) => + window.program.handle_event(Event::HoverFile(path), writer!()), + WindowEvent::HoveredFileCancelled => + window.program.handle_event(Event::HoverFileCancel, writer!()), + _ => (), } - WindowEvent::RedrawRequested => { - window.redraw(); - }, - _ => (), } } } -- cgit v1.2.3-70-g09d2