diff --git a/src/app.rs b/src/app.rs index ae13f81b..84017d68 100644 --- a/src/app.rs +++ b/src/app.rs @@ -20,6 +20,7 @@ use crate::{ profiler::Profile, view::{IntoView, View}, window::WindowConfig, + AnyView, }; type AppEventCallback = dyn Fn(AppEvent); @@ -52,32 +53,10 @@ pub enum AppEvent { } pub(crate) enum UserEvent { + AppUpdate, Idle, QuitApp, - NewWindow { - view_fn: Box Box + Sync + Send>, - config: Option, - }, - CloseWindow { - window_id: WindowId, - }, - CaptureWindow { - window_id: WindowId, - capture: WriteSignal>>, - }, - ProfileWindow { - window_id: WindowId, - end_profile: Option>>>, - }, - RequestTimer { - timer: Timer, - }, - CancelTimer { - timer: TimerToken, - }, - GpuResourcesUpdate { - window_id: WindowId, - }, + GpuResourcesUpdate { window_id: WindowId }, } pub(crate) enum AppUpdateEvent { @@ -122,9 +101,10 @@ pub(crate) fn add_app_update_event(event: AppUpdateEvent) { /// This is the entry point of the application. pub struct Application { receiver: Receiver, - handle: Option, + handle: ApplicationHandle, event_listener: Option>, event_loop: Option, + initial_windows: Vec<(Box AnyView>, Option)>, } impl Default for Application { @@ -135,7 +115,10 @@ impl Default for Application { impl ApplicationHandler for Application { fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) { - todo!() + while let Some((view_fn, window_config)) = self.initial_windows.pop() { + self.handle + .new_window(event_loop, view_fn, window_config.unwrap_or_default()); + } } fn window_event( @@ -144,12 +127,20 @@ impl ApplicationHandler for Application { window_id: WindowId, event: WindowEvent, ) { - let handle = self.handle.as_mut().unwrap(); - handle.handle_window_event(window_id, event, event_loop); + self.handle + .handle_window_event(window_id, event, event_loop); } fn proxy_wake_up(&mut self, event_loop: &dyn ActiveEventLoop) { - for event in self.receiver.try_iter() {} + for event in self.receiver.try_iter() { + self.handle.handle_user_event(event_loop, event); + } + } + + fn exiting(&mut self, _event_loop: &dyn ActiveEventLoop) { + if let Some(action) = self.event_listener.as_ref() { + action(AppEvent::WillTerminate); + } } } @@ -165,9 +156,10 @@ impl Application { let handle = ApplicationHandle::new(); Self { receiver, - handle: Some(handle), + handle, event_listener: None, event_loop: Some(event_loop), + initial_windows: Vec::new(), } } @@ -188,11 +180,10 @@ impl Application { app_view: impl FnOnce(WindowId) -> V + 'static, config: Option, ) -> Self { - self.handle.as_mut().unwrap().new_window( - self.event_loop.as_ref().unwrap(), - Box::new(|window_id| app_view(window_id).into_any()), - config.unwrap_or_default(), - ); + self.initial_windows.push(( + Box::new(move |window_id: WindowId| app_view(window_id).into_any()), + config, + )); self } diff --git a/src/app_handle.rs b/src/app_handle.rs index 28faca82..3b264887 100644 --- a/src/app_handle.rs +++ b/src/app_handle.rs @@ -12,7 +12,7 @@ use std::{collections::HashMap, mem, rc::Rc}; use winit::{ dpi::{LogicalPosition, LogicalSize}, event::WindowEvent, - event_loop::{ActiveEventLoop, ControlFlow, EventLoopProxy}, + event_loop::{ActiveEventLoop, ControlFlow}, window::WindowId, }; @@ -41,15 +41,10 @@ impl ApplicationHandle { } } - pub(crate) fn handle_user_event( - &mut self, - event_loop: &ActiveEventLoop, - event_proxy: EventLoopProxy, - event: UserEvent, - ) { + pub(crate) fn handle_user_event(&mut self, event_loop: &dyn ActiveEventLoop, event: UserEvent) { match event { UserEvent::AppUpdate => { - self.handle_update_event(event_loop, event_proxy); + self.handle_update_event(event_loop); } UserEvent::Idle => { self.idle(); @@ -66,23 +61,16 @@ impl ApplicationHandle { } } - pub(crate) fn handle_update_event( - &mut self, - event_loop: &EventLoopWindowTarget, - event_proxy: EventLoopProxy, - ) { + pub(crate) fn handle_update_event(&mut self, event_loop: &dyn ActiveEventLoop) { let events = APP_UPDATE_EVENTS.with(|events| { let mut events = events.borrow_mut(); std::mem::take(&mut *events) }); for event in events { match event { - AppUpdateEvent::NewWindow { view_fn, config } => self.new_window( - event_loop, - event_proxy.clone(), - view_fn, - config.unwrap_or_default(), - ), + AppUpdateEvent::NewWindow { view_fn, config } => { + self.new_window(event_loop, view_fn, config.unwrap_or_default()) + } AppUpdateEvent::CloseWindow { window_id } => { self.close_window(window_id, event_loop); } @@ -140,7 +128,7 @@ impl ApplicationHandle { let start = window_handle.profile.is_some().then(|| { let name = match event { WindowEvent::ActivationTokenDone { .. } => "ActivationTokenDone", - WindowEvent::Resized(..) => "Resized", + WindowEvent::SurfaceResized(..) => "Resized", WindowEvent::Moved(..) => "Moved", WindowEvent::CloseRequested => "CloseRequested", WindowEvent::Destroyed => "Destroyed", @@ -151,22 +139,21 @@ impl ApplicationHandle { WindowEvent::KeyboardInput { .. } => "KeyboardInput", WindowEvent::ModifiersChanged(..) => "ModifiersChanged", WindowEvent::Ime(..) => "Ime", - WindowEvent::CursorMoved { .. } => "CursorMoved", - WindowEvent::CursorEntered { .. } => "CursorEntered", - WindowEvent::CursorLeft { .. } => "CursorLeft", + WindowEvent::PointerMoved { .. } => "PointerMoved", + WindowEvent::PointerEntered { .. } => "PointerEntered", + WindowEvent::PointerLeft { .. } => "PointerLeft", WindowEvent::MouseWheel { .. } => "MouseWheel", - WindowEvent::MouseInput { .. } => "MouseInput", - WindowEvent::TouchpadMagnify { .. } => "TouchpadMagnify", - WindowEvent::SmartMagnify { .. } => "SmartMagnify", - WindowEvent::TouchpadRotate { .. } => "TouchpadRotate", + WindowEvent::PointerButton { .. } => "PointerButton", WindowEvent::TouchpadPressure { .. } => "TouchpadPressure", - WindowEvent::AxisMotion { .. } => "AxisMotion", - WindowEvent::Touch(_) => "Touch", WindowEvent::ScaleFactorChanged { .. } => "ScaleFactorChanged", WindowEvent::ThemeChanged(..) => "ThemeChanged", WindowEvent::Occluded(..) => "Occluded", - WindowEvent::MenuAction(..) => "MenuAction", WindowEvent::RedrawRequested => "RedrawRequested", + WindowEvent::PinchGesture { .. } => "PinchGesture", + WindowEvent::PanGesture { .. } => "PanGesture", + WindowEvent::DoubleTapGesture { .. } => "DoubleTapGesture", + WindowEvent::RotationGesture { .. } => "RotationGesture", + // WindowEvent::MenuAction(..) => "MenuAction", }; ( name, @@ -177,7 +164,7 @@ impl ApplicationHandle { match event { WindowEvent::ActivationTokenDone { .. } => {} - WindowEvent::Resized(size) => { + WindowEvent::SurfaceResized(size) => { let size: LogicalSize = size.to_logical(window_handle.scale); let size = Size::new(size.width, size.height); window_handle.size(size); @@ -216,27 +203,22 @@ impl ApplicationHandle { WindowEvent::Ime(ime) => { window_handle.ime(ime); } - WindowEvent::CursorMoved { position, .. } => { + WindowEvent::PointerMoved { position, .. } => { let position: LogicalPosition = position.to_logical(window_handle.scale); let point = Point::new(position.x, position.y); window_handle.pointer_move(point); } - WindowEvent::CursorEntered { .. } => {} - WindowEvent::CursorLeft { .. } => { + WindowEvent::PointerEntered { .. } => {} + WindowEvent::PointerLeft { .. } => { window_handle.pointer_leave(); } WindowEvent::MouseWheel { delta, .. } => { window_handle.mouse_wheel(delta); } - WindowEvent::MouseInput { state, button, .. } => { - window_handle.mouse_input(button, state); + WindowEvent::PointerButton { state, button, .. } => { + window_handle.pointer_button(button, state); } - WindowEvent::TouchpadMagnify { .. } => {} - WindowEvent::SmartMagnify { .. } => {} - WindowEvent::TouchpadRotate { .. } => {} WindowEvent::TouchpadPressure { .. } => {} - WindowEvent::AxisMotion { .. } => {} - WindowEvent::Touch(_) => {} WindowEvent::ScaleFactorChanged { scale_factor, .. } => { window_handle.scale(scale_factor); } @@ -244,12 +226,11 @@ impl ApplicationHandle { window_handle.os_theme_changed(theme); } WindowEvent::Occluded(_) => {} - WindowEvent::MenuAction(id) => { - window_handle.menu_action(id); - } WindowEvent::RedrawRequested => { window_handle.render_frame(); - } + } // WindowEvent::MenuAction(id) => { + // window_handle.menu_action(id); + // } } if let Some((name, start, new_frame)) = start { diff --git a/src/pointer.rs b/src/pointer.rs index d87a13b7..b6d1ce1e 100644 --- a/src/pointer.rs +++ b/src/pointer.rs @@ -1,5 +1,9 @@ +use std::hash::{Hash, Hasher}; + +use winit::event::ButtonSource; +pub use winit::event::{FingerId, Force}; + use peniko::kurbo::{Point, Vec2}; -use winit::event::MouseButton; use crate::keyboard::Modifiers; @@ -10,8 +14,58 @@ pub struct PointerWheelEvent { pub modifiers: Modifiers, } -#[derive(Debug, Clone, PartialEq, Eq, Copy, Hash, Ord, PartialOrd)] +#[derive(Debug, Clone, PartialEq, Copy)] pub enum PointerButton { + Mouse(MouseButton), + Touch { + finger_id: FingerId, + force: Option, + }, + Unknown(u16), +} + +impl Eq for PointerButton {} + +impl Hash for PointerButton { + fn hash(&self, state: &mut H) { + match self { + PointerButton::Mouse(mouse_button) => mouse_button.hash(state), + PointerButton::Touch { finger_id, .. } => finger_id.hash(state), + PointerButton::Unknown(n) => n.hash(state), + } + } +} + +impl From for PointerButton { + fn from(value: ButtonSource) -> Self { + match value { + ButtonSource::Mouse(mouse_button) => PointerButton::Mouse(mouse_button.into()), + ButtonSource::Touch { finger_id, force } => PointerButton::Touch { finger_id, force }, + ButtonSource::Unknown(n) => PointerButton::Unknown(n), + } + } +} + +impl PointerButton { + pub fn is_primary(&self) -> bool { + if let PointerButton::Mouse(mouse) = self { + mouse.is_primary() + } else { + false + } + } + + pub fn is_secondary(&self) -> bool { + if let PointerButton::Mouse(mouse) = self { + mouse.is_secondary() + } else { + false + } + } +} + +#[derive(Debug, Clone, PartialEq, Eq, Copy, Hash, Ord, PartialOrd)] +pub enum MouseButton { Primary, Secondary, Auxiliary, @@ -20,38 +74,38 @@ pub enum PointerButton { None, } -impl From for PointerButton { - fn from(value: MouseButton) -> Self { +impl From for MouseButton { + fn from(value: winit::event::MouseButton) -> Self { match value { - MouseButton::Left => Self::Primary, - MouseButton::Right => Self::Secondary, - MouseButton::Middle => Self::Auxiliary, - MouseButton::Back => Self::X1, - MouseButton::Forward => Self::X2, - MouseButton::Other(_) => Self::None, + winit::event::MouseButton::Left => Self::Primary, + winit::event::MouseButton::Right => Self::Secondary, + winit::event::MouseButton::Middle => Self::Auxiliary, + winit::event::MouseButton::Back => Self::X1, + winit::event::MouseButton::Forward => Self::X2, + winit::event::MouseButton::Other(_) => Self::None, } } } -impl PointerButton { - pub fn is_primary(self) -> bool { - self == PointerButton::Primary +impl MouseButton { + pub fn is_primary(&self) -> bool { + self == &MouseButton::Primary } - pub fn is_secondary(self) -> bool { - self == PointerButton::Secondary + pub fn is_secondary(&self) -> bool { + self == &MouseButton::Secondary } - pub fn is_auxiliary(self) -> bool { - self == PointerButton::Auxiliary + pub fn is_auxiliary(&self) -> bool { + self == &MouseButton::Auxiliary } - pub fn is_x1(self) -> bool { - self == PointerButton::X1 + pub fn is_x1(&self) -> bool { + self == &MouseButton::X1 } - pub fn is_x2(self) -> bool { - self == PointerButton::X2 + pub fn is_x2(&self) -> bool { + self == &MouseButton::X2 } } diff --git a/src/views/drag_window_area.rs b/src/views/drag_window_area.rs index c75a3d27..1effe7d3 100644 --- a/src/views/drag_window_area.rs +++ b/src/views/drag_window_area.rs @@ -2,7 +2,6 @@ use crate::{ action::{drag_window, toggle_window_maximized}, event::{Event, EventListener}, id::ViewId, - pointer::PointerButton, view::{IntoView, View}, }; @@ -22,7 +21,7 @@ pub fn drag_window_area(child: V) -> DragWindowArea { DragWindowArea { id } .on_event_stop(EventListener::PointerDown, |e| { if let Event::PointerDown(input_event) = e { - if input_event.button == PointerButton::Primary { + if input_event.button.is_primary() { drag_window(); } } diff --git a/src/views/editor/keypress/key.rs b/src/views/editor/keypress/key.rs index b6e94106..cd794d6c 100644 --- a/src/views/editor/keypress/key.rs +++ b/src/views/editor/keypress/key.rs @@ -4,12 +4,15 @@ use std::{ str::FromStr, }; -use crate::keyboard::{Key, KeyCode, NativeKey, PhysicalKey}; +use crate::{ + keyboard::{Key, KeyCode, NativeKey, PhysicalKey}, + pointer::{MouseButton, PointerButton}, +}; #[derive(Clone, Debug, Eq)] pub enum KeyInput { Keyboard(crate::keyboard::Key, crate::keyboard::PhysicalKey), - Pointer(crate::pointer::PointerButton), + Pointer(PointerButton), } impl KeyInput { @@ -772,9 +775,11 @@ impl Display for KeyInput { PhysicalKey::Code(KeyCode::F35) => f.write_str("F35"), _ => f.write_str("Unidentified"), }, - Self::Pointer(B::Auxiliary) => f.write_str("MouseMiddle"), - Self::Pointer(B::X2) => f.write_str("MouseForward"), - Self::Pointer(B::X1) => f.write_str("MouseBackward"), + Self::Pointer(PointerButton::Mouse(MouseButton::Auxiliary)) => { + f.write_str("MouseMiddle") + } + Self::Pointer(PointerButton::Mouse(MouseButton::X2)) => f.write_str("MouseForward"), + Self::Pointer(PointerButton::Mouse(MouseButton::X1)) => f.write_str("MouseBackward"), Self::Pointer(_) => f.write_str("MouseUnimplemented"), } } @@ -798,7 +803,7 @@ impl Hash for KeyInput { match self { Self::Keyboard(_key, key_code) => key_code.hash(state), // TODO: Implement `Hash` for `druid::MouseButton` - Self::Pointer(btn) => (*btn as u8).hash(state), + Self::Pointer(btn) => btn.hash(state), } } } diff --git a/src/views/editor/mod.rs b/src/views/editor/mod.rs index 7ca4ac57..22bd3150 100644 --- a/src/views/editor/mod.rs +++ b/src/views/editor/mod.rs @@ -14,7 +14,7 @@ use crate::{ keyboard::Modifiers, kurbo::{Point, Rect, Vec2}, peniko::Color, - pointer::{PointerButton, PointerInputEvent, PointerMoveEvent}, + pointer::{MouseButton, PointerInputEvent, PointerMoveEvent}, prop, prop_extractor, reactive::{batch, untrack, ReadSignal, RwSignal, Scope}, style::{CursorColor, StylePropValue, TextColor}, @@ -484,15 +484,11 @@ impl Editor { /// Default handler for `PointerDown` event pub fn pointer_down(&self, pointer_event: &PointerInputEvent) { - match pointer_event.button { - PointerButton::Primary => { - self.active.set(true); - self.left_click(pointer_event); - } - PointerButton::Secondary => { - self.right_click(pointer_event); - } - _ => {} + if pointer_event.button.is_primary() { + self.active.set(true); + self.left_click(pointer_event); + } else if pointer_event.button.is_secondary() { + self.right_click(pointer_event); } } diff --git a/src/window_handle.rs b/src/window_handle.rs index 2562de34..1eb0ffc6 100644 --- a/src/window_handle.rs +++ b/src/window_handle.rs @@ -14,7 +14,7 @@ use floem_renderer::Renderer; use peniko::kurbo::{Affine, Point, Rect, Size, Vec2}; use winit::{ dpi::{LogicalPosition, LogicalSize}, - event::{ElementState, Ime, MouseButton, MouseScrollDelta}, + event::{ButtonSource, ElementState, Ime, MouseButton, MouseScrollDelta}, event_loop::EventLoopProxy, keyboard::{Key, ModifiersState, NamedKey}, window::{CursorIcon, Window, WindowId}, @@ -39,7 +39,7 @@ use crate::{ keyboard::{KeyEvent, Modifiers}, menu::Menu, nav::view_arrow_navigation, - pointer::{PointerButton, PointerInputEvent, PointerMoveEvent, PointerWheelEvent}, + pointer::{MouseButton, PointerButton, PointerInputEvent, PointerMoveEvent, PointerWheelEvent}, profiler::Profile, style::{CursorStyle, Style, StyleSelector}, theme::{default_theme, Theme}, @@ -494,7 +494,7 @@ impl WindowHandle { self.event(Event::PointerWheel(event)); } - pub(crate) fn mouse_input(&mut self, button: MouseButton, state: ElementState) { + pub(crate) fn pointer_button(&mut self, button: ButtonSource, state: ElementState) { let button: PointerButton = button.into(); let count = if state.is_pressed() && button.is_primary() { if let Some((count, last_pos, instant)) = self.last_pointer_down.as_mut() {