From e51b650bfe8de092dab84950eb4caa678695c8f0 Mon Sep 17 00:00:00 2001 From: Guenter Zoechbauer Date: Mon, 13 Mar 2023 13:12:47 +0100 Subject: [PATCH 1/9] WrappedMutPhysicalSize almost working except of static lifetime --- Cargo.toml | 9 +- app/Cargo.toml | 9 + app/src/event_loop.rs | 1 + app/src/lib.rs | 2 + app/src/shell_window.rs | 1 + core/Cargo.toml | 3 +- core/src/builtin_widgets.rs | 2 +- core/src/builtin_widgets/cursor.rs | 14 +- core/src/builtin_widgets/scrollable.rs | 5 +- core/src/context/event_context.rs | 5 +- core/src/cursor_icon.rs | 58 ++++ core/src/events.rs | 4 +- core/src/events/character.rs | 2 +- core/src/events/dispatcher.rs | 167 ++++------ core/src/events/event.rs | 226 +++++++++++++ core/src/events/keyboard.rs | 249 +++++++++++++- core/src/events/pointers.rs | 60 +++- core/src/events/pointers/from_mouse.rs | 44 --- core/src/events/pointers/pointer_event.rs | 33 ++ core/src/events/wheel.rs | 6 +- core/src/lib.rs | 13 +- core/src/window.rs | 347 +++++++++++--------- geometry/Cargo.toml | 9 + geometry/src/lib.rs | 28 ++ painter/Cargo.toml | 1 + painter/src/lib.rs | 26 +- winit/Cargo.toml | 13 + {core => winit}/src/application.rs | 4 +- winit/src/from_cursor_icon.rs | 106 ++++++ winit/src/from_device_id.rs | 56 ++++ winit/src/from_element_state.rs | 31 ++ winit/src/from_event.rs | 157 +++++++++ winit/src/from_keyboard_input.rs | 69 ++++ winit/src/from_modifiers.rs | 72 +++++ winit/src/from_mouse.rs | 45 +++ winit/src/from_mouse_scroll_delta.rs | 41 +++ winit/src/from_size.rs | 170 ++++++++++ winit/src/from_touch_phase.rs | 35 ++ winit/src/from_virtual_key_code.rs | 375 ++++++++++++++++++++++ winit/src/from_window.rs | 112 +++++++ winit/src/from_window_id.rs | 56 ++++ winit/src/lib.rs | 44 +++ 42 files changed, 2333 insertions(+), 377 deletions(-) create mode 100644 app/Cargo.toml create mode 100644 app/src/event_loop.rs create mode 100644 app/src/lib.rs create mode 100644 app/src/shell_window.rs create mode 100644 core/src/cursor_icon.rs create mode 100644 core/src/events/event.rs delete mode 100644 core/src/events/pointers/from_mouse.rs create mode 100644 core/src/events/pointers/pointer_event.rs create mode 100644 geometry/Cargo.toml create mode 100644 geometry/src/lib.rs create mode 100644 winit/Cargo.toml rename {core => winit}/src/application.rs (97%) create mode 100644 winit/src/from_cursor_icon.rs create mode 100644 winit/src/from_device_id.rs create mode 100644 winit/src/from_element_state.rs create mode 100644 winit/src/from_event.rs create mode 100644 winit/src/from_keyboard_input.rs create mode 100644 winit/src/from_modifiers.rs create mode 100644 winit/src/from_mouse.rs create mode 100644 winit/src/from_mouse_scroll_delta.rs create mode 100644 winit/src/from_size.rs create mode 100644 winit/src/from_touch_phase.rs create mode 100644 winit/src/from_virtual_key_code.rs create mode 100644 winit/src/from_window.rs create mode 100644 winit/src/from_window_id.rs create mode 100644 winit/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index 9ea8863b1..fffe70a60 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,14 +1,17 @@ [workspace] members = [ + "algo", + "app", "core", + "geometry", "gpu", - "painter", "macros", "macros/builtin", - "algo", + "painter", + "ribir", "text", "widgets", - "ribir", + "winit", ] resolver = "2" diff --git a/app/Cargo.toml b/app/Cargo.toml new file mode 100644 index 000000000..6266df4cf --- /dev/null +++ b/app/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "ribir_app" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +ribir_core = { path = "../core" } diff --git a/app/src/event_loop.rs b/app/src/event_loop.rs new file mode 100644 index 000000000..4f6960987 --- /dev/null +++ b/app/src/event_loop.rs @@ -0,0 +1 @@ +pub trait EventLoop {} diff --git a/app/src/lib.rs b/app/src/lib.rs new file mode 100644 index 000000000..2eef88ff1 --- /dev/null +++ b/app/src/lib.rs @@ -0,0 +1,2 @@ +pub mod event_loop; +pub mod shell_window; diff --git a/app/src/shell_window.rs b/app/src/shell_window.rs new file mode 100644 index 000000000..63c6b2b38 --- /dev/null +++ b/app/src/shell_window.rs @@ -0,0 +1 @@ +pub trait ShellWindow {} diff --git a/core/Cargo.toml b/core/Cargo.toml index 4d5b89122..8e883f046 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -24,7 +24,7 @@ ribir_text = {path = "../text"} rxrust = "1.0.0-beta.1" smallvec = "1.8.0" -winit = "0.28.1" +# winit = "0.28.1" [dependencies.blake3] features = ["rayon"] @@ -38,3 +38,4 @@ thread-pool = [ [dev-dependencies] colored = "2.0.0" +# winit = "0.28.1" diff --git a/core/src/builtin_widgets.rs b/core/src/builtin_widgets.rs index 466b2090d..5e17aeb8f 100644 --- a/core/src/builtin_widgets.rs +++ b/core/src/builtin_widgets.rs @@ -3,8 +3,8 @@ pub use key::{Key, KeyWidget}; mod theme; pub use theme::*; mod cursor; +pub use crate::cursor_icon::CursorIcon; pub use cursor::Cursor; -pub use winit::window::CursorIcon; mod margin; pub use margin::*; mod padding; diff --git a/core/src/builtin_widgets/cursor.rs b/core/src/builtin_widgets/cursor.rs index 41d2319d2..df1c85a14 100644 --- a/core/src/builtin_widgets/cursor.rs +++ b/core/src/builtin_widgets/cursor.rs @@ -1,9 +1,7 @@ use crate::prelude::*; use std::{cell::Cell, rc::Rc}; -use winit::window::CursorIcon; /// `Cursor` is an attribute to assign an `cursor` to a widget. - #[derive(Declare, Debug)] pub struct Cursor { #[declare(convert=custom, builtin, default)] @@ -91,7 +89,7 @@ impl Default for Cursor { mod tests { use super::*; use crate::test::*; - use winit::event::{DeviceId, WindowEvent}; + // use winit::event::{DeviceId, WindowEvent}; #[test] fn tree_down_up() { @@ -117,7 +115,7 @@ mod tests { wnd.draw_frame(); let tree = &mut wnd.widget_tree; - let device_id = unsafe { DeviceId::dummy() }; + let device_id = DummyPointerId::dummy(); let dispatcher = &mut wnd.dispatcher; dispatcher.dispatch( WindowEvent::CursorMoved { @@ -130,7 +128,7 @@ mod tests { ); assert_eq!(dispatcher.take_cursor_icon(), Some(CursorIcon::Help)); - let device_id = unsafe { DeviceId::dummy() }; + let device_id = DummyPointerId::dummy(); dispatcher.dispatch( WindowEvent::CursorMoved { device_id, @@ -142,7 +140,7 @@ mod tests { ); assert_eq!(dispatcher.take_cursor_icon(), Some(CursorIcon::Hand)); - let device_id = unsafe { DeviceId::dummy() }; + let device_id = DummyPointerId::dummy(); dispatcher.dispatch( WindowEvent::CursorMoved { device_id, @@ -154,7 +152,7 @@ mod tests { ); assert_eq!(dispatcher.take_cursor_icon(), Some(CursorIcon::AllScroll)); - let device_id = unsafe { DeviceId::dummy() }; + let device_id = DummyPointerId::dummy(); dispatcher.dispatch( WindowEvent::CursorMoved { device_id, @@ -166,7 +164,7 @@ mod tests { ); assert_eq!(dispatcher.take_cursor_icon(), Some(CursorIcon::Hand)); - let device_id = unsafe { DeviceId::dummy() }; + let device_id = DummyPointerId::dummy(); dispatcher.dispatch( WindowEvent::CursorMoved { device_id, diff --git a/core/src/builtin_widgets/scrollable.rs b/core/src/builtin_widgets/scrollable.rs index eb094f1d4..bce7a6f3f 100644 --- a/core/src/builtin_widgets/scrollable.rs +++ b/core/src/builtin_widgets/scrollable.rs @@ -110,7 +110,8 @@ mod tests { use crate::test::{layout_info_by_path, MockBox}; use super::*; - use winit::event::{DeviceId, ModifiersState, MouseScrollDelta, TouchPhase, WindowEvent}; + // use winit::event::{DeviceId, ModifiersState, MouseScrollDelta, TouchPhase, + // WindowEvent}; fn test_assert(scrollable: Scrollable, delta_x: f32, delta_y: f32, expect_x: f32, expect_y: f32) { let w = widget! { @@ -124,7 +125,7 @@ mod tests { wnd.draw_frame(); - let device_id = unsafe { DeviceId::dummy() }; + let device_id = DummyPointerId::dummy(); wnd.processes_native_event(WindowEvent::MouseWheel { device_id, delta: MouseScrollDelta::PixelDelta((delta_x, delta_y).into()), diff --git a/core/src/context/event_context.rs b/core/src/context/event_context.rs index bb71b1bb6..b78dd88ad 100644 --- a/core/src/context/event_context.rs +++ b/core/src/context/event_context.rs @@ -1,10 +1,11 @@ use super::{define_widget_context, WidgetCtxImpl, WindowCtx}; use crate::{ - events::dispatcher::DispatchInfo, + cursor_icon::CursorIcon, + events::{dispatcher::DispatchInfo, ModifiersState}, widget::{LayoutStore, TreeArena}, widget_tree::WidgetId, }; -use winit::{event::ModifiersState, window::CursorIcon}; +// use winit::{event::ModifiersState, window::CursorIcon}; define_widget_context!(EventCtx, info: &'a mut DispatchInfo); diff --git a/core/src/cursor_icon.rs b/core/src/cursor_icon.rs new file mode 100644 index 000000000..af60f4aed --- /dev/null +++ b/core/src/cursor_icon.rs @@ -0,0 +1,58 @@ +/// Describes the appearance of the mouse cursor. +#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum CursorIcon { + /// The platform-dependent default cursor. + #[default] + Default, + /// A simple crosshair. + Crosshair, + /// A hand (often used to indicate links in web browsers). + Hand, + /// Self explanatory. + Arrow, + /// Indicates something is to be moved. + Move, + /// Indicates text that may be selected or edited. + Text, + /// Program busy indicator. + Wait, + /// Help indicator (often rendered as a "?") + Help, + /// Progress indicator. Shows that processing is being done. But in contrast + /// with "Wait" the user may still interact with the program. Often rendered + /// as a spinning beach ball, or an arrow with a watch or hourglass. + Progress, + + /// Cursor showing that something cannot be done. + NotAllowed, + ContextMenu, + Cell, + VerticalText, + Alias, + Copy, + NoDrop, + /// Indicates something can be grabbed. + Grab, + /// Indicates something is grabbed. + Grabbing, + AllScroll, + ZoomIn, + ZoomOut, + + /// Indicate that some edge is to be moved. For example, the 'SeResize' cursor + /// is used when the movement starts from the south-east corner of the box. + EResize, + NResize, + NeResize, + NwResize, + SResize, + SeResize, + SwResize, + WResize, + EwResize, + NsResize, + NeswResize, + NwseResize, + ColResize, + RowResize, +} diff --git a/core/src/events.rs b/core/src/events.rs index db4470264..df4a2bde0 100644 --- a/core/src/events.rs +++ b/core/src/events.rs @@ -5,10 +5,12 @@ use crate::{ use std::ptr::NonNull; pub(crate) mod dispatcher; +mod event; +pub use event::*; mod pointers; pub use pointers::*; use ribir_painter::Point; -pub use winit::event::{ModifiersState, ScanCode, VirtualKeyCode}; +// pub use winit::event::{ModifiersState, ScanCode, VirtualKeyCode}; mod focus; pub use focus::*; mod keyboard; diff --git a/core/src/events/character.rs b/core/src/events/character.rs index 5d1bf68a3..52cbbeb2d 100644 --- a/core/src/events/character.rs +++ b/core/src/events/character.rs @@ -56,7 +56,7 @@ mod tests { use crate::test::*; use std::{cell::RefCell, rc::Rc}; - use winit::event::WindowEvent; + // use winit::event::WindowEvent; #[test] fn smoke() { diff --git a/core/src/events/dispatcher.rs b/core/src/events/dispatcher.rs index 0bc6952ec..1784636bd 100644 --- a/core/src/events/dispatcher.rs +++ b/core/src/events/dispatcher.rs @@ -1,8 +1,9 @@ use std::{cell::RefCell, rc::Rc}; use crate::{prelude::*, widget_tree::WidgetTree}; -use ::ribir_text::PIXELS_PER_EM; -use winit::event::{DeviceId, ElementState, MouseButton, MouseScrollDelta, WindowEvent}; +use ribir_text::PIXELS_PER_EM; +// use winit::event::{DeviceId, ElementState, MouseButton, MouseScrollDelta, +// WindowEvent}; use super::focus_mgr::FocusManager; @@ -28,7 +29,7 @@ impl Dispatcher { #[derive(Default)] pub(crate) struct DispatchInfo { /// The current state of mouse button press state. - mouse_button: (Option, MouseButtons), + mouse_button: (Option>, MouseButtons), /// The current global position (relative to window) of mouse cursor_pos: Point, /// Cursor icon try to set to window. @@ -43,8 +44,9 @@ impl Dispatcher { match event { WindowEvent::ModifiersChanged(s) => self.info.modifiers = s, WindowEvent::CursorMoved { position, .. } => { - let pos = position.to_logical::(wnd_factor); - self.cursor_move_to(Point::new(pos.x, pos.y), tree) + let logical_pos = ScaleToLogic::new(wnd_factor as f32).transform_point(position.cast()); + + self.cursor_move_to(Point::new(logical_pos.x, logical_pos.y), tree) } WindowEvent::CursorLeft { .. } => self.on_cursor_left(tree), WindowEvent::MouseInput { state, button, device_id, .. } => { @@ -63,7 +65,7 @@ impl Dispatcher { pub fn dispatch_keyboard_input( &mut self, - input: winit::event::KeyboardInput, + input: /* winit::event:: */ KeyboardInput, tree: &mut WidgetTree, ) { if let Some(key) = input.virtual_keycode { @@ -128,23 +130,29 @@ impl Dispatcher { pub fn dispatch_mouse_input( &mut self, - device_id: DeviceId, + device_id: Box, state: ElementState, - button: MouseButton, + button: MouseButtons, tree: &mut WidgetTree, ) -> Option<()> { // A mouse press/release emit during another mouse's press will ignored. - if self.info.mouse_button.0.get_or_insert(device_id) == &device_id { + if self + .info + .mouse_button + .0 + .get_or_insert(device_id.clone()) + .eq(device_id.as_ref()) + { match state { ElementState::Pressed => { - self.info.mouse_button.1 |= button.into(); + self.info.mouse_button.1 |= button; // only the first button press emit event. - if self.info.mouse_button.1 == button.into() { + if self.info.mouse_button.1 == button { self.bubble_mouse_down(tree); } } ElementState::Released => { - self.info.mouse_button.1.remove(button.into()); + self.info.mouse_button.1.remove(button); // only the last button release emit event. if self.info.mouse_button.1.is_empty() { self.info.mouse_button.0 = None; @@ -155,7 +163,8 @@ impl Dispatcher { .pointer_down_uid .take()? .lowest_common_ancestor(release_event.target(), &tree.arena)?; - let mut tap_event = PointerEvent::from_mouse(tap_on, tree, &self.info); + let mut tap_event = + PointerEvent::from_mouse(Box::new(DummyPointerId::dummy()), tap_on, tree, &self.info); tree.bubble_event::(&mut tap_event); } @@ -175,8 +184,8 @@ impl Dispatcher { let (delta_x, delta_y) = match delta { MouseScrollDelta::LineDelta(x, y) => (x * PIXELS_PER_EM, y * PIXELS_PER_EM), MouseScrollDelta::PixelDelta(delta) => { - let winit::dpi::LogicalPosition { x, y } = delta.to_logical(wnd_factor); - (x, y) + let logical_delta = ScaleToLogic::new(wnd_factor as f32).transform_point(delta.cast()); + (logical_delta.x, logical_delta.y) } }; @@ -231,7 +240,8 @@ impl Dispatcher { .iter() .filter(|w| !w.is_dropped(arena)) .for_each(|l| { - let mut event = PointerEvent::from_mouse(*l, tree, &self.info); + let mut event = + PointerEvent::from_mouse(Box::new(DummyPointerId::dummy()), *l, tree, &self.info); l.assert_get(arena).query_all_type( |pointer: &PointerLeaveListener| { pointer.dispatch(&mut event); @@ -263,7 +273,8 @@ impl Dispatcher { self.entered_widgets.iter().rev().for_each(|w| { let obj = w.assert_get(arena); if obj.contain_type::() { - let mut event = PointerEvent::from_mouse(*w, tree, &self.info); + let mut event = + PointerEvent::from_mouse(Box::new(DummyPointerId::dummy()), *w, tree, &self.info); obj.query_all_type( |pointer: &PointerEnterListener| { pointer.dispatch(&mut event); @@ -308,9 +319,9 @@ impl Dispatcher { } fn pointer_event_for_hit_widget(&mut self, tree: &WidgetTree) -> Option { - self - .hit_widget(tree) - .map(|target| PointerEvent::from_mouse(target, tree, &self.info)) + self.hit_widget(tree).map(|target| { + PointerEvent::from_mouse(Box::new(DummyPointerId::dummy()), target, tree, &self.info) + }) } } @@ -373,8 +384,8 @@ mod tests { use super::*; use crate::test::*; use std::{cell::RefCell, rc::Rc}; - use winit::event::WindowEvent; - use winit::event::{DeviceId, ElementState, ModifiersState, MouseButton}; + // use winit::event::WindowEvent; + // use winit::event::{DeviceId, ElementState, ModifiersState, MouseButton}; struct Info { pos: Point, @@ -417,12 +428,8 @@ mod tests { let mut wnd = Window::default_mock(root, None); wnd.draw_frame(); - let device_id = unsafe { DeviceId::dummy() }; - wnd.processes_native_event(WindowEvent::CursorMoved { - device_id, - position: (1., 1.).into(), - modifiers: ModifiersState::default(), - }); + let device_id = unsafe { PointerId::dummy() }; + wnd.processes_native_event(WindowEvent::CursorMoved { device_id, position: (1., 1.).into() }); { let mut records = event_record.borrow_mut(); @@ -434,8 +441,7 @@ mod tests { wnd.processes_native_event(WindowEvent::MouseInput { device_id, state: ElementState::Pressed, - button: MouseButton::Left, - modifiers: ModifiersState::default(), + button: MouseButtons::Left, }); let mut records = event_record.borrow_mut(); @@ -454,39 +460,31 @@ mod tests { let mut wnd = Window::default_mock(root, None); wnd.draw_frame(); - let device_id = unsafe { DeviceId::dummy() }; + let device_id = unsafe { PointerId::dummy() }; wnd.processes_native_event(WindowEvent::MouseInput { device_id, state: ElementState::Pressed, - button: MouseButton::Left, - modifiers: ModifiersState::default(), + button: MouseButtons::Left, }); wnd.processes_native_event(WindowEvent::MouseInput { device_id, state: ElementState::Pressed, - button: MouseButton::Right, - modifiers: ModifiersState::default(), + button: MouseButtons::Right, }); - wnd.processes_native_event(WindowEvent::CursorMoved { - device_id, - position: (1, 1).into(), - modifiers: ModifiersState::default(), - }); + wnd.processes_native_event(WindowEvent::CursorMoved { device_id, position: (1, 1).into() }); wnd.processes_native_event(WindowEvent::MouseInput { device_id, state: ElementState::Released, - button: MouseButton::Left, - modifiers: ModifiersState::default(), + button: MouseButtons::Left, }); wnd.processes_native_event(WindowEvent::MouseInput { device_id, state: ElementState::Released, - button: MouseButton::Right, - modifiers: ModifiersState::default(), + button: MouseButtons::Right, }); let records = event_record.borrow(); @@ -512,41 +510,37 @@ mod tests { let mut wnd = Window::default_mock(root, None); wnd.draw_frame(); - let device_id = unsafe { DeviceId::dummy() }; + let device_id = unsafe { PointerId::dummy() }; wnd.processes_native_event(WindowEvent::MouseInput { device_id, state: ElementState::Pressed, - button: MouseButton::Left, - modifiers: ModifiersState::default(), + button: MouseButtons::Left, }); assert_eq!(event_record.borrow().len(), 1); // A mouse press/release emit during another mouse's press will be ignored. let device_id_2 = unsafe { - let mut id = DeviceId::dummy(); - (&mut id as *mut DeviceId).write_bytes(1, 1); + let mut id = PointerId::dummy(); + (&mut id as *mut PointerId).write_bytes(1, 1); id }; wnd.processes_native_event(WindowEvent::MouseInput { device_id: device_id_2, state: ElementState::Pressed, - button: MouseButton::Left, - modifiers: ModifiersState::default(), + button: MouseButtons::Left, }); wnd.processes_native_event(WindowEvent::MouseInput { device_id: device_id_2, state: ElementState::Released, - button: MouseButton::Left, - modifiers: ModifiersState::default(), + button: MouseButtons::Left, }); assert_eq!(event_record.borrow().len(), 1); wnd.processes_native_event(WindowEvent::CursorMoved { device_id: device_id_2, position: (1, 1).into(), - modifiers: ModifiersState::default(), }); // but cursor move processed. @@ -557,8 +551,7 @@ mod tests { wnd.processes_native_event(WindowEvent::MouseInput { device_id, state: ElementState::Released, - button: MouseButton::Left, - modifiers: ModifiersState::default(), + button: MouseButtons::Left, }); assert_eq!(event_record.borrow().len(), 3); @@ -595,10 +588,9 @@ mod tests { wnd.draw_frame(); wnd.processes_native_event(WindowEvent::MouseInput { - device_id: unsafe { DeviceId::dummy() }, + device_id: unsafe { PointerId::dummy() }, state: ElementState::Pressed, - button: MouseButton::Left, - modifiers: ModifiersState::default(), + button: MouseButtons::Left, }); assert_eq!(event_record.borrow().len(), 1); @@ -638,30 +630,18 @@ mod tests { let mut wnd = Window::default_mock(w.into_widget(), Some(Size::new(100., 100.))); wnd.draw_frame(); - let device_id = unsafe { DeviceId::dummy() }; + let device_id = unsafe { PointerId::dummy() }; - wnd.processes_native_event(WindowEvent::CursorMoved { - device_id, - position: (10, 10).into(), - modifiers: ModifiersState::default(), - }); + wnd.processes_native_event(WindowEvent::CursorMoved { device_id, position: (10, 10).into() }); assert_eq!(&*enter_event.borrow(), &[2, 1]); // leave to parent - wnd.processes_native_event(WindowEvent::CursorMoved { - device_id, - position: (99, 99).into(), - modifiers: ModifiersState::default(), - }); + wnd.processes_native_event(WindowEvent::CursorMoved { device_id, position: (99, 99).into() }); assert_eq!(&*leave_event.borrow(), &[1]); // move in same widget, // check if duplicate event fired. - wnd.processes_native_event(WindowEvent::CursorMoved { - device_id, - position: (99, 99).into(), - modifiers: ModifiersState::default(), - }); + wnd.processes_native_event(WindowEvent::CursorMoved { device_id, position: (99, 99).into() }); assert_eq!(&*enter_event.borrow(), &[2, 1]); assert_eq!(&*leave_event.borrow(), &[1]); @@ -669,18 +649,13 @@ mod tests { wnd.processes_native_event(WindowEvent::CursorMoved { device_id, position: (999, 999).into(), - modifiers: ModifiersState::default(), }); assert_eq!(&*leave_event.borrow(), &[1, 2]); // leave event trigger by window left. leave_event.borrow_mut().clear(); - wnd.processes_native_event(WindowEvent::CursorMoved { - device_id, - position: (10, 10).into(), - modifiers: ModifiersState::default(), - }); + wnd.processes_native_event(WindowEvent::CursorMoved { device_id, position: (10, 10).into() }); wnd.processes_native_event(WindowEvent::CursorLeft { device_id }); assert_eq!(&*leave_event.borrow(), &[1, 2]); } @@ -704,25 +679,22 @@ mod tests { let mut wnd = Window::default_mock(w, Some(Size::new(400., 400.))); wnd.draw_frame(); - let device_id = unsafe { DeviceId::dummy() }; + let device_id = unsafe { PointerId::dummy() }; let modifiers = ModifiersState::default(); wnd.processes_native_event(WindowEvent::CursorMoved { device_id, position: (50f64, 50f64).into(), - modifiers, }); wnd.processes_native_event(WindowEvent::MouseInput { device_id, state: ElementState::Pressed, - button: MouseButton::Left, - modifiers, + button: MouseButtons::Left, }); wnd.processes_native_event(WindowEvent::MouseInput { device_id, state: ElementState::Released, - button: MouseButton::Left, - modifiers, + button: MouseButtons::Left, }); { @@ -734,24 +706,20 @@ mod tests { wnd.processes_native_event(WindowEvent::CursorMoved { device_id, position: (50f64, 50f64).into(), - modifiers, }); wnd.processes_native_event(WindowEvent::MouseInput { device_id, state: ElementState::Pressed, - button: MouseButton::Left, - modifiers, + button: MouseButtons::Left, }); wnd.processes_native_event(WindowEvent::CursorMoved { device_id, position: (50f64, 150f64).into(), - modifiers, }); wnd.processes_native_event(WindowEvent::MouseInput { device_id, state: ElementState::Released, - button: MouseButton::Left, - modifiers, + button: MouseButtons::Left, }); { @@ -776,18 +744,16 @@ mod tests { let mut wnd = Window::default_mock(w, Some(Size::new(100., 100.))); wnd.draw_frame(); - let device_id = unsafe { DeviceId::dummy() }; + let device_id = unsafe { PointerId::dummy() }; let modifiers = ModifiersState::default(); wnd.processes_native_event(WindowEvent::CursorMoved { device_id, position: (45f64, 45f64).into(), - modifiers, }); wnd.processes_native_event(WindowEvent::MouseInput { device_id, state: ElementState::Pressed, - button: MouseButton::Left, - modifiers, + button: MouseButtons::Left, }); // point down on a focus widget @@ -796,19 +762,16 @@ mod tests { wnd.processes_native_event(WindowEvent::MouseInput { device_id, state: ElementState::Released, - button: MouseButton::Left, - modifiers, + button: MouseButtons::Left, }); wnd.processes_native_event(WindowEvent::CursorMoved { device_id, position: (80f64, 80f64).into(), - modifiers, }); wnd.processes_native_event(WindowEvent::MouseInput { device_id, state: ElementState::Pressed, - button: MouseButton::Left, - modifiers, + button: MouseButtons::Left, }); assert!(wnd.dispatcher.focusing().is_none()); diff --git a/core/src/events/event.rs b/core/src/events/event.rs new file mode 100644 index 000000000..7b9c91505 --- /dev/null +++ b/core/src/events/event.rs @@ -0,0 +1,226 @@ +use ribir_painter::{DevicePoint, DeviceSize}; +use std::{any::Any, fmt::Debug}; + +use super::{ModifiersState, MouseButtons, PointerId, ScanCode, VirtualKeyCode}; + +#[derive(Debug)] +pub enum WindowEvent { + Unsupported, + Resized(DeviceSize), + + /// The window received a unicode character. + /// + /// See also the [`Ime`](Self::Ime) event for more complex character + /// sequences. + ReceivedCharacter(char), + + /// An event from the keyboard has been received. + KeyboardInput { + device_id: Box, + input: KeyboardInput, + /// If `true`, the event was generated synthetically by winit + /// in one of the following circumstances: + /// + /// * Synthetic key press events are generated for all keys pressed when a + /// window gains focus. Likewise, synthetic key release events are + /// generated for all keys pressed when a window goes out of focus. + /// ***Currently, this is only functional on X11 and Windows*** + /// + /// Otherwise, this value is always `false`. + is_synthetic: bool, + }, + + ModifiersChanged(ModifiersState), + CursorMoved { + device_id: Box, + + /// (x,y) coords in pixels relative to the top-left corner of the window. + /// Because the range of this data is limited by the display area and it + /// may have been transformed by the OS to implement effects such as cursor + /// acceleration, it should not be used to implement non-cursor-like + /// interactions such as 3D camera control. + position: DevicePoint, + }, + + /// The cursor has left the window. + CursorLeft { + device_id: Box, + }, + + /// A mouse wheel movement or touchpad scroll occurred. + MouseWheel { + device_id: Box, + delta: MouseScrollDelta, + phase: TouchPhase, + }, + + /// An mouse button press has been received. + MouseInput { + device_id: Box, + state: ElementState, + button: MouseButtons, + }, + + /// The window's scale factor has changed. + /// + /// The following user actions can cause DPI changes: + /// + /// * Changing the display's resolution. + /// * Changing the display's scale factor (e.g. in Control Panel on Windows). + /// * Moving the window to a display with a different scale factor. + /// + /// After this event callback has been processed, the window will be resized + /// to whatever value is pointed to by the `new_inner_size` reference. By + /// default, this will contain the size suggested by the OS, but it can be + /// changed to any value. + /// + /// For more information about DPI in general, see the [`dpi`](crate::dpi) + /// module. + ScaleFactorChanged { + scale_factor: f64, + new_inner_size: Box, + }, +} + +pub trait MutDeviceSize: Debug { + fn value(&self) -> DeviceSize; + fn set_value(&mut self, size: DeviceSize); + fn as_any(self: Box) -> Box; +} + +impl PartialEq for WindowEvent { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (Self::Resized(l0), Self::Resized(r0)) => l0 == r0, + (Self::ReceivedCharacter(l0), Self::ReceivedCharacter(r0)) => l0 == r0, + ( + Self::KeyboardInput { + device_id: l_device_id, + input: l_input, + is_synthetic: l_is_synthetic, + }, + Self::KeyboardInput { + device_id: r_device_id, + input: r_input, + is_synthetic: r_is_synthetic, + }, + ) => { + l_device_id.eq(r_device_id.as_ref()) + && l_input == r_input + && l_is_synthetic == r_is_synthetic + } + (Self::ModifiersChanged(l0), Self::ModifiersChanged(r0)) => l0 == r0, + ( + Self::CursorMoved { + device_id: l_device_id, + position: l_position, + }, + Self::CursorMoved { + device_id: r_device_id, + position: r_position, + }, + ) => l_device_id.eq(r_device_id.as_ref()) && l_position == r_position, + ( + Self::CursorLeft { device_id: l_device_id }, + Self::CursorLeft { device_id: r_device_id }, + ) => l_device_id.eq(r_device_id.as_ref()), + ( + Self::MouseWheel { + device_id: l_device_id, + delta: l_delta, + phase: l_phase, + }, + Self::MouseWheel { + device_id: r_device_id, + delta: r_delta, + phase: r_phase, + }, + ) => l_device_id.eq(r_device_id.as_ref()) && l_delta == r_delta && l_phase == r_phase, + ( + Self::MouseInput { + device_id: l_device_id, + state: l_state, + button: l_button, + }, + Self::MouseInput { + device_id: r_device_id, + state: r_state, + button: r_button, + }, + ) => l_device_id.eq(r_device_id.as_ref()) && l_state == r_state && l_button == r_button, + ( + Self::ScaleFactorChanged { + scale_factor: l_scale_factor, + new_inner_size: l_new_inner_size, + }, + Self::ScaleFactorChanged { + scale_factor: r_scale_factor, + new_inner_size: r_new_inner_size, + }, + ) => l_scale_factor == r_scale_factor && l_new_inner_size.value() == r_new_inner_size.value(), + _ => false, + } + } +} + +#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)] +pub enum ElementState { + Pressed, + Released, +} + +/// Describes a difference in the mouse scroll wheel state. +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum MouseScrollDelta { + /// Amount in lines or rows to scroll in the horizontal + /// and vertical directions. + /// + /// Positive values indicate that the content that is being scrolled should + /// move right and down (revealing more content left and up). + LineDelta(f32, f32), + + /// Amount in pixels to scroll in the horizontal and + /// vertical direction. + /// + /// Scroll events are expressed as a `PixelDelta` if + /// supported by the device (eg. a touchpad) and + /// platform. + /// + /// Positive values indicate that the content being scrolled should + /// move right/down. + /// + /// For a 'natural scrolling' touch pad (that acts like a touch screen) + /// this means moving your fingers right and down should give positive values, + /// and move the content right and down (to reveal more things left and up). + PixelDelta(DevicePoint), +} + +/// Describes touch-screen input state. +#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)] +pub enum TouchPhase { + Started, + Moved, + Ended, + Cancelled, +} + +/// Describes a keyboard input event. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct KeyboardInput { + /// Identifies the physical key pressed + /// + /// This should not change if the user adjusts the host's keyboard map. Use + /// when the physical location of the key is more important than the key's + /// host GUI semantics, such as for movement controls in a first-person + /// game. + pub scancode: ScanCode, + + pub state: ElementState, + + /// Identifies the semantic meaning of the key + /// + /// Use when the semantics of the key are more important than the physical + /// location of the key, such as when implementing appropriate behavior for + /// "page up." + pub virtual_keycode: Option, +} diff --git a/core/src/events/keyboard.rs b/core/src/events/keyboard.rs index d228c2b2c..7894fa2ab 100644 --- a/core/src/events/keyboard.rs +++ b/core/src/events/keyboard.rs @@ -68,22 +68,263 @@ impl std::ops::DerefMut for KeyboardEvent { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.common } } +/// Symbolic name for a keyboard key. +#[derive(Debug, Hash, Ord, PartialOrd, PartialEq, Eq, Clone, Copy)] +#[repr(u32)] +pub enum VirtualKeyCode { + /// The '1' key over the letters. + Key1, + /// The '2' key over the letters. + Key2, + /// The '3' key over the letters. + Key3, + /// The '4' key over the letters. + Key4, + /// The '5' key over the letters. + Key5, + /// The '6' key over the letters. + Key6, + /// The '7' key over the letters. + Key7, + /// The '8' key over the letters. + Key8, + /// The '9' key over the letters. + Key9, + /// The '0' key over the 'O' and 'P' keys. + Key0, + + A, + B, + C, + D, + E, + F, + G, + H, + I, + J, + K, + L, + M, + N, + O, + P, + Q, + R, + S, + T, + U, + V, + W, + X, + Y, + Z, + + /// The Escape key, next to F1. + Escape, + + F1, + F2, + F3, + F4, + F5, + F6, + F7, + F8, + F9, + F10, + F11, + F12, + F13, + F14, + F15, + F16, + F17, + F18, + F19, + F20, + F21, + F22, + F23, + F24, + + /// Print Screen/SysRq. + Snapshot, + /// Scroll Lock. + Scroll, + /// Pause/Break key, next to Scroll lock. + Pause, + + /// `Insert`, next to Backspace. + Insert, + Home, + Delete, + End, + PageDown, + PageUp, + + Left, + Up, + Right, + Down, + + /// The Backspace key, right over Enter. + // TODO: rename + Back, + /// The Enter key. + Return, + /// The space bar. + Space, + + /// The "Compose" key on Linux. + Compose, + + Caret, + + Numlock, + Numpad0, + Numpad1, + Numpad2, + Numpad3, + Numpad4, + Numpad5, + Numpad6, + Numpad7, + Numpad8, + Numpad9, + NumpadAdd, + NumpadDivide, + NumpadDecimal, + NumpadComma, + NumpadEnter, + NumpadEquals, + NumpadMultiply, + NumpadSubtract, + + AbntC1, + AbntC2, + Apostrophe, + Apps, + Asterisk, + At, + Ax, + Backslash, + Calculator, + Capital, + Colon, + Comma, + Convert, + Equals, + Grave, + Kana, + Kanji, + LAlt, + LBracket, + LControl, + LShift, + LWin, + Mail, + MediaSelect, + MediaStop, + Minus, + Mute, + MyComputer, + // also called "Next" + NavigateForward, + // also called "Prior" + NavigateBackward, + NextTrack, + NoConvert, + OEM102, + Period, + PlayPause, + Plus, + Power, + PrevTrack, + RAlt, + RBracket, + RControl, + RShift, + RWin, + Semicolon, + Slash, + Sleep, + Stop, + Sysrq, + Tab, + Underline, + Unlabeled, + VolumeDown, + VolumeUp, + Wake, + WebBack, + WebFavorites, + WebForward, + WebHome, + WebRefresh, + WebSearch, + WebStop, + Yen, + Copy, + Paste, + Cut, +} + +pub type ScanCode = u32; + +bitflags! { + /// Represents the current state of the keyboard modifiers + /// + /// Each flag represents a modifier and is set if this modifier is active. + #[derive(Default)] + pub struct ModifiersState: u32 { + // left and right modifiers are currently commented out, but we should be able to support + // them in a future release + /// The "shift" key. + const SHIFT = 0b100; + // const LSHIFT = 0b010; + // const RSHIFT = 0b001; + /// The "control" key. + const CTRL = 0b100 << 3; + // const LCTRL = 0b010 << 3; + // const RCTRL = 0b001 << 3; + /// The "alt" key. + const ALT = 0b100 << 6; + // const LALT = 0b010 << 6; + // const RALT = 0b001 << 6; + /// This is the "windows" key on PC and "command" key on Mac. + const LOGO = 0b100 << 9; + // const LLOGO = 0b010 << 9; + // const RLOGO = 0b001 << 9; + } +} + +impl ModifiersState { + /// Returns `true` if the shift key is pressed. + pub fn shift(&self) -> bool { self.intersects(Self::SHIFT) } + /// Returns `true` if the control key is pressed. + pub fn ctrl(&self) -> bool { self.intersects(Self::CTRL) } + /// Returns `true` if the alt key is pressed. + pub fn alt(&self) -> bool { self.intersects(Self::ALT) } + /// Returns `true` if the logo key is pressed. + pub fn logo(&self) -> bool { self.intersects(Self::LOGO) } +} + #[cfg(test)] mod tests { use super::*; use crate::test::*; use std::{cell::RefCell, rc::Rc}; - use winit::event::{DeviceId, ElementState, KeyboardInput, WindowEvent}; + // use winit::event::{DeviceId, ElementState, KeyboardInput, WindowEvent}; - fn new_key_event(key: VirtualKeyCode, state: ElementState) -> WindowEvent<'static> { + fn new_key_event(key: VirtualKeyCode, state: ElementState) -> WindowEvent /*<'static>*/ { #[allow(deprecated)] WindowEvent::KeyboardInput { - device_id: unsafe { DeviceId::dummy() }, + device_id: Box::new(DummyPointerId::dummy()), input: KeyboardInput { scancode: 0, virtual_keycode: Some(key), state, - modifiers: ModifiersState::default(), }, is_synthetic: false, } diff --git a/core/src/events/pointers.rs b/core/src/events/pointers.rs index 36e431ffe..3bfe87f54 100644 --- a/core/src/events/pointers.rs +++ b/core/src/events/pointers.rs @@ -7,13 +7,40 @@ use crate::{ }; use std::{ convert::Infallible, + fmt::Debug, time::{Duration, Instant}, }; -mod from_mouse; +mod pointer_event; const MULTI_TAP_DURATION: Duration = Duration::from_millis(250); -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct PointerId(usize); + +pub trait PointerId: Debug { + fn as_any(&self) -> &dyn Any; + fn eq(&self, other: &dyn PointerId) -> bool; + fn box_clone(&self) -> Box; + // fn debug(&self) -> String; +} + +impl Clone for Box { + fn clone(&self) -> Self { self.box_clone() } +} + +#[derive(Debug, Copy, Clone)] +pub struct DummyPointerId(usize); + +impl DummyPointerId { + pub fn dummy() -> DummyPointerId { DummyPointerId(0) } +} + +impl PointerId for DummyPointerId { + fn as_any(&self) -> &dyn Any { &self.0 } + + fn eq(&self, other: &dyn PointerId) -> bool { + self.0 == other.as_any().downcast_ref::().unwrap().0 + } + + fn box_clone(&self) -> Box { Box::new(*self) } +} /// The pointer is a hardware-agnostic device that can target a specific set of /// screen coordinates. Having a single event model for pointers can simplify @@ -25,7 +52,7 @@ pub struct PointerId(usize); #[derive(Debug, Clone)] pub struct PointerEvent { /// A unique identifier for the pointer causing the event. - pub id: PointerId, + pub id: Box, /// The width (magnitude on the X axis), in pixels, of the contact geometry of /// the pointer. pub width: f32, @@ -287,7 +314,7 @@ fn x_times_tap_map_filter( ) -> impl FnMut(&mut PointerEvent) -> Option<&mut PointerEvent> { assert!(x > 0); struct TapInfo { - pointer_id: PointerId, + pointer_id: Box, stamps: Vec, } @@ -295,7 +322,7 @@ fn x_times_tap_map_filter( move |e: &mut PointerEvent| { let now = Instant::now(); match &mut type_info { - Some(info) if info.pointer_id == e.id => { + Some(info) if info.pointer_id.eq(&*e.id) => { if info.stamps.len() + 1 == x { if now.duration_since(info.stamps[0]) <= dur { // emit x-tap event and reset the tap info @@ -313,7 +340,10 @@ fn x_times_tap_map_filter( } } _ => { - type_info = Some(TapInfo { pointer_id: e.id, stamps: vec![now] }); + type_info = Some(TapInfo { + pointer_id: e.id.clone(), + stamps: vec![now], + }); None } } @@ -340,7 +370,8 @@ mod tests { use crate::test::MockBox; use futures::executor::LocalPool; use std::{cell::RefCell, rc::Rc}; - use winit::event::{DeviceId, ElementState, ModifiersState, MouseButton, WindowEvent}; + // use winit::event::{DeviceId, ElementState, ModifiersState, MouseButton, + // WindowEvent}; fn env(times: usize) -> (Window, Rc>) { let size = Size::new(400., 400.); @@ -363,7 +394,7 @@ mod tests { let (mut wnd, count) = env(2); let mut local_pool = LocalPool::new(); - let device_id = unsafe { DeviceId::dummy() }; + let device_id = Box::new(DummyPointerId::dummy()); observable::interval(Duration::from_millis(10), local_pool.spawner()) .take(8) .subscribe(move |i| { @@ -374,8 +405,7 @@ mod tests { } else { ElementState::Released }, - button: MouseButton::Left, - modifiers: ModifiersState::default(), + button: MouseButtons::Left, }); }); @@ -394,8 +424,7 @@ mod tests { } else { ElementState::Released }, - button: MouseButton::Left, - modifiers: ModifiersState::default(), + button: MouseButtons::Left, }); }); @@ -408,7 +437,7 @@ mod tests { let (mut wnd, count) = env(3); let mut local_pool = LocalPool::new(); - let device_id = unsafe { DeviceId::dummy() }; + let device_id = DummyPointerId::dummy(); observable::interval(Duration::from_millis(10), local_pool.spawner()) .take(12) .subscribe(move |i| { @@ -419,8 +448,7 @@ mod tests { } else { ElementState::Released }, - button: MouseButton::Left, - modifiers: ModifiersState::default(), + button: MouseButtons::Left, }); }); diff --git a/core/src/events/pointers/from_mouse.rs b/core/src/events/pointers/from_mouse.rs deleted file mode 100644 index 17c5b1252..000000000 --- a/core/src/events/pointers/from_mouse.rs +++ /dev/null @@ -1,44 +0,0 @@ -use super::PointerId; -use crate::{ - prelude::{dispatcher::DispatchInfo, *}, - widget_tree::WidgetTree, -}; -use winit::event::MouseButton; - -impl PointerEvent { - pub(crate) fn from_mouse(target: WidgetId, tree: &WidgetTree, info: &DispatchInfo) -> Self { - PointerEvent { - // todo: how to generate pointer id ? - id: PointerId(0), - width: 1.0, - height: 1.0, - pressure: if info.mouse_buttons().is_empty() { - 0. - } else { - 0.5 - }, - tilt_x: 90., - tilt_y: 90., - twist: 0., - point_type: PointerType::Mouse, - is_primary: true, - common: EventCommon::new(target, tree, info), - } - } -} - -impl From for MouseButtons { - fn from(btns: MouseButton) -> Self { - match btns { - MouseButton::Left => MouseButtons::PRIMARY, - MouseButton::Right => MouseButtons::SECONDARY, - MouseButton::Middle => MouseButtons::AUXILIARY, - MouseButton::Other(1) => MouseButtons::FOURTH, - MouseButton::Other(2) => MouseButtons::FIFTH, - MouseButton::Other(v) => { - log::warn!("Not support the mouse button {} now", v); - MouseButtons::default() - } - } - } -} diff --git a/core/src/events/pointers/pointer_event.rs b/core/src/events/pointers/pointer_event.rs new file mode 100644 index 000000000..af0669516 --- /dev/null +++ b/core/src/events/pointers/pointer_event.rs @@ -0,0 +1,33 @@ +use super::PointerId; +use crate::{ + prelude::{dispatcher::DispatchInfo, *}, + widget_tree::WidgetTree, +}; +// use winit::event::MouseButton; + +impl PointerEvent { + pub(crate) fn from_mouse( + pointer_id: Box, + target: WidgetId, + tree: &WidgetTree, + info: &DispatchInfo, + ) -> Self { + PointerEvent { + // todo: how to generate pointer id ? + id: pointer_id, /* PointerId(0) */ + width: 1.0, + height: 1.0, + pressure: if info.mouse_buttons().is_empty() { + 0. + } else { + 0.5 + }, + tilt_x: 90., + tilt_y: 90., + twist: 0., + point_type: PointerType::Mouse, + is_primary: true, + common: EventCommon::new(target, tree, info), + } + } +} diff --git a/core/src/events/wheel.rs b/core/src/events/wheel.rs index 31125f290..5eba1a945 100644 --- a/core/src/events/wheel.rs +++ b/core/src/events/wheel.rs @@ -55,7 +55,8 @@ mod tests { use super::*; use crate::test::MockBox; use std::{cell::RefCell, rc::Rc}; - use winit::event::{DeviceId, ModifiersState, MouseScrollDelta, TouchPhase, WindowEvent}; + // use winit::event::{DeviceId, ModifiersState, MouseScrollDelta, TouchPhase, + // WindowEvent}; #[test] fn smoke() { @@ -73,12 +74,11 @@ mod tests { let mut wnd = Window::default_mock(widget, Some(Size::new(100., 100.))); wnd.draw_frame(); - let device_id = unsafe { DeviceId::dummy() }; + let device_id = Box::new(DummyPointerId::dummy()); wnd.processes_native_event(WindowEvent::MouseWheel { device_id, delta: MouseScrollDelta::PixelDelta((1.0, 1.0).into()), phase: TouchPhase::Started, - modifiers: ModifiersState::default(), }); assert_eq!(*receive.borrow(), (1., 1.)); diff --git a/core/src/lib.rs b/core/src/lib.rs index 0b06df9f0..3f9430e65 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -1,11 +1,11 @@ -#![feature(test, decl_macro)] +#![feature(test, decl_macro, box_into_inner)] #[macro_use] extern crate bitflags; extern crate lazy_static; pub mod animation; -mod application; +// mod application; pub mod builtin_widgets; mod context; pub mod data_widget; @@ -13,6 +13,7 @@ mod state; pub(crate) mod widget_tree; pub mod assign_observable; +pub mod cursor_icon; pub mod declare; pub mod dynamic_widget; pub mod enum_widget; @@ -23,14 +24,16 @@ pub mod widget_children; pub mod window; pub mod prelude { pub use crate::animation::*; - #[doc(no_inline)] - pub use crate::application::Application; + // #[doc(no_inline)] + // pub use crate::application::Application; pub use crate::assign_observable::AssignObservable; #[doc(no_inline)] pub use crate::builtin_widgets::*; #[doc(no_inline)] pub use crate::context::*; #[doc(no_inline)] + pub use crate::cursor_icon::*; + #[doc(no_inline)] pub use crate::data_widget::{ compose_child_as_data_widget, widget_attach_data, AnonymousData, DataWidget, }; @@ -52,7 +55,7 @@ pub mod prelude { #[doc(no_inline)] pub use crate::widget_tree::{BoxClamp, LayoutInfo, Layouter, WidgetId}; #[doc(no_inline)] - pub use crate::window::{Window, WindowBuilder}; + pub use crate::window::Window; #[doc(no_inline)] pub use ::ribir_painter::*; pub use log; diff --git a/core/src/window.rs b/core/src/window.rs index dae56cf54..b7695fb3c 100644 --- a/core/src/window.rs +++ b/core/src/window.rs @@ -4,8 +4,18 @@ use crate::{ context::AppContext, events::dispatcher::Dispatcher, prelude::*, widget_tree::WidgetTree, }; -pub use winit::window::CursorIcon; -use winit::{event::WindowEvent, window::WindowId}; +pub trait WindowId { + fn as_any(&self) -> &dyn Any; + fn eq(&self, other: &dyn WindowId) -> bool; + fn box_clone(&self) -> Box; +} + +impl Clone for Box { + fn clone(&self) -> Self { self.box_clone() } +} + +// pub use winit::window::CursorIcon; +// use winit::{event::WindowEvent, window::WindowId}; pub trait RawWindow { fn inner_size(&self) -> Size; @@ -13,164 +23,167 @@ pub trait RawWindow { fn outer_size(&self) -> Size; fn inner_position(&self) -> Point; fn outer_position(&self) -> Point; - fn id(&self) -> WindowId; + fn id(&self) -> Box; fn request_redraw(&self); /// Modify the native window if cursor modified. fn set_cursor(&mut self, cursor: CursorIcon); fn scale_factor(&self) -> f64; + fn as_any(&self) -> &dyn Any; } -impl RawWindow for winit::window::Window { - fn inner_size(&self) -> Size { - let size = self.inner_size().to_logical(self.scale_factor()); - Size::new(size.width, size.height) - } - - fn set_inner_size(&mut self, size: Size) { - let size = winit::dpi::LogicalSize::new(size.width, size.height); - winit::window::Window::set_inner_size(self, size) - } - - fn outer_size(&self) -> Size { - let size = self.outer_size().to_logical(self.scale_factor()); - Size::new(size.width, size.height) - } - - fn inner_position(&self) -> Point { - let pos = self - .inner_position() - .expect(" Can only be called on the main thread") - .to_logical(self.scale_factor()); - - Point::new(pos.x, pos.y) - } - #[inline] - fn id(&self) -> WindowId { self.id() } - - fn outer_position(&self) -> Point { - let pos = self - .outer_position() - .expect(" Can only be called on the main thread") - .to_logical(self.scale_factor()); - Point::new(pos.x, pos.y) - } - - #[inline] - fn request_redraw(&self) { winit::window::Window::request_redraw(self) } - - fn set_cursor(&mut self, cursor: CursorIcon) { self.set_cursor_icon(cursor) } - - #[inline] - fn scale_factor(&self) -> f64 { winit::window::Window::scale_factor(self) } -} - -pub struct WindowBuilder { - inner_builder: winit::window::WindowBuilder, - root: Widget, -} - -impl WindowBuilder { - #[inline] - pub fn build(self, app: &Application) -> Window { - let native_wnd = self.inner_builder.build(app.event_loop()).unwrap(); - let size = native_wnd.inner_size(); - let ctx = app.context().clone(); - let p_backend = AppContext::wait_future(ribir_gpu::wgpu_backend_with_wnd( - &native_wnd, - DeviceSize::new(size.width, size.height), - None, - None, - ctx.shaper.clone(), - )); - Window::new(native_wnd, p_backend, self.root, ctx) - } - - /// Requests the window to be of specific dimensions. - #[inline] - pub fn with_inner_size(mut self, size: Size) -> Self { - let size = winit::dpi::LogicalSize::new(size.width, size.height); - self.inner_builder = self.inner_builder.with_inner_size(size); - self - } - - /// Sets a minimum dimension size for the window. - #[inline] - pub fn with_min_inner_size(mut self, min_size: Size) -> Self { - let size = winit::dpi::LogicalSize::new(min_size.width, min_size.height); - self.inner_builder = self.inner_builder.with_min_inner_size(size); - self - } - - /// Sets a maximum dimension size for the window. - #[inline] - pub fn with_max_inner_size(mut self, max_size: Size) -> Self { - let size = winit::dpi::LogicalSize::new(max_size.width, max_size.height); - self.inner_builder = self.inner_builder.with_max_inner_size(size); - self - } - - /// Sets a desired initial position for the window. - #[inline] - pub fn with_position(mut self, position: Point) -> Self { - let position = winit::dpi::LogicalPosition::new(position.x, position.y); - self.inner_builder = self.inner_builder.with_position(position); - self - } - - /// Sets whether the window is resizable or not. - #[inline] - pub fn with_resizable(mut self, resizable: bool) -> Self { - self.inner_builder = self.inner_builder.with_resizable(resizable); - self - } - - /// Requests a specific title for the window. - #[inline] - pub fn with_title>(mut self, title: T) -> Self { - self.inner_builder = self.inner_builder.with_title(title); - self - } - - /// Requests maximized mode. - #[inline] - pub fn with_maximized(mut self, maximized: bool) -> Self { - self.inner_builder = self.inner_builder.with_maximized(maximized); - self - } - - /// Sets whether the window will be initially hidden or visible. - #[inline] - pub fn with_visible(mut self, visible: bool) -> Self { - self.inner_builder = self.inner_builder.with_visible(visible); - self - } - - /// Sets whether the background of the window should be transparent. - #[inline] - pub fn with_transparent(mut self, transparent: bool) -> Self { - self.inner_builder = self.inner_builder.with_transparent(transparent); - self - } - - /// Sets whether the window should have a border, a title bar, etc. - #[inline] - pub fn with_decorations(mut self, decorations: bool) -> Self { - self.inner_builder = self.inner_builder.with_decorations(decorations); - self - } - - // /// Sets the window icon. - // #[inline] - // pub fn with_window_icon(mut self, window_icon: Option) - // -> Self { self.inner_builder = - // self.inner_builder.with_window_icon(window_icon); self - // } -} +// impl RawWindow for winit::window::Window { +// fn inner_size(&self) -> Size { +// let size = self.inner_size().to_logical(self.scale_factor()); +// Size::new(size.width, size.height) +// } + +// fn set_inner_size(&mut self, size: Size) { +// let size = winit::dpi::LogicalSize::new(size.width, size.height); +// winit::window::Window::set_inner_size(self, size) +// } + +// fn outer_size(&self) -> Size { +// let size = self.outer_size().to_logical(self.scale_factor()); +// Size::new(size.width, size.height) +// } + +// fn inner_position(&self) -> Point { +// let pos = self +// .inner_position() +// .expect(" Can only be called on the main thread") +// .to_logical(self.scale_factor()); + +// Point::new(pos.x, pos.y) +// } +// #[inline] +// fn id(&self) -> WindowId { self.id() } + +// fn outer_position(&self) -> Point { +// let pos = self +// .outer_position() +// .expect(" Can only be called on the main thread") +// .to_logical(self.scale_factor()); +// Point::new(pos.x, pos.y) +// } + +// #[inline] +// fn request_redraw(&self) { winit::window::Window::request_redraw(self) } + +// fn set_cursor(&mut self, cursor: CursorIcon) { self.set_cursor_icon(cursor) +// } + +// #[inline] +// fn scale_factor(&self) -> f64 { winit::window::Window::scale_factor(self) } +// } + +// pub struct WindowBuilder { +// inner_builder: winit::window::WindowBuilder, +// root: Widget, +// } + +// impl WindowBuilder { +// #[inline] +// pub fn build(self, app: &Application) -> Window { +// let native_wnd = self.inner_builder.build(app.event_loop()).unwrap(); +// let size = native_wnd.inner_size(); +// let ctx = app.context().clone(); +// let p_backend = AppContext::wait_future(ribir_gpu::wgpu_backend_with_wnd( +// &native_wnd, +// DeviceSize::new(size.width, size.height), +// None, +// None, +// ctx.shaper.clone(), +// )); +// Window::new(native_wnd, p_backend, self.root, ctx) +// } + +// /// Requests the window to be of specific dimensions. +// #[inline] +// pub fn with_inner_size(mut self, size: Size) -> Self { +// let size = winit::dpi::LogicalSize::new(size.width, size.height); +// self.inner_builder = self.inner_builder.with_inner_size(size); +// self +// } + +// /// Sets a minimum dimension size for the window. +// #[inline] +// pub fn with_min_inner_size(mut self, min_size: Size) -> Self { +// let size = winit::dpi::LogicalSize::new(min_size.width, min_size.height); +// self.inner_builder = self.inner_builder.with_min_inner_size(size); +// self +// } + +// /// Sets a maximum dimension size for the window. +// #[inline] +// pub fn with_max_inner_size(mut self, max_size: Size) -> Self { +// let size = winit::dpi::LogicalSize::new(max_size.width, max_size.height); +// self.inner_builder = self.inner_builder.with_max_inner_size(size); +// self +// } + +// /// Sets a desired initial position for the window. +// #[inline] +// pub fn with_position(mut self, position: Point) -> Self { +// let position = winit::dpi::LogicalPosition::new(position.x, position.y); +// self.inner_builder = self.inner_builder.with_position(position); +// self +// } + +// /// Sets whether the window is resizable or not. +// #[inline] +// pub fn with_resizable(mut self, resizable: bool) -> Self { +// self.inner_builder = self.inner_builder.with_resizable(resizable); +// self +// } + +// /// Requests a specific title for the window. +// #[inline] +// pub fn with_title>(mut self, title: T) -> Self { +// self.inner_builder = self.inner_builder.with_title(title); +// self +// } + +// /// Requests maximized mode. +// #[inline] +// pub fn with_maximized(mut self, maximized: bool) -> Self { +// self.inner_builder = self.inner_builder.with_maximized(maximized); +// self +// } + +// /// Sets whether the window will be initially hidden or visible. +// #[inline] +// pub fn with_visible(mut self, visible: bool) -> Self { +// self.inner_builder = self.inner_builder.with_visible(visible); +// self +// } + +// /// Sets whether the background of the window should be transparent. +// #[inline] +// pub fn with_transparent(mut self, transparent: bool) -> Self { +// self.inner_builder = self.inner_builder.with_transparent(transparent); +// self +// } + +// /// Sets whether the window should have a border, a title bar, etc. +// #[inline] +// pub fn with_decorations(mut self, decorations: bool) -> Self { +// self.inner_builder = self.inner_builder.with_decorations(decorations); +// self +// } + +// // /// Sets the window icon. +// // #[inline] +// // pub fn with_window_icon(mut self, window_icon: +// Option) // -> Self { self.inner_builder = +// // self.inner_builder.with_window_icon(window_icon); self +// // } +// } /// A rx scheduler pool that block until all task finished before every frame /// end. struct FramePool(FuturesLocalSchedulerPool); + /// Window is the root to represent. pub struct Window { pub raw_window: Box, @@ -185,13 +198,13 @@ pub struct Window { } impl Window { - #[inline] - pub fn builder(root: Widget) -> WindowBuilder { - WindowBuilder { - root, - inner_builder: winit::window::WindowBuilder::default(), - } - } + // #[inline] + // pub fn builder(root: Widget) -> WindowBuilder { + // WindowBuilder { + // root, + // inner_builder: winit::window::WindowBuilder::default(), + // } + // } /// processes native events from this native window #[inline] @@ -201,7 +214,7 @@ impl Window { self.on_resize(DeviceSize::new(size.width, size.height)); } WindowEvent::ScaleFactorChanged { new_inner_size, scale_factor } => { - self.on_resize(DeviceSize::new(new_inner_size.width, new_inner_size.height)); + self.on_resize(new_inner_size.value()); let factor = scale_factor as f32; self.painter.reset(Some(factor)); } @@ -374,16 +387,34 @@ impl PainterBackend for MockBackend { } } +#[derive(Debug, Copy, Clone)] +pub struct MockWindowId(usize); + +impl MockWindowId { + fn dummy() -> MockWindowId { MockWindowId(0) } +} + +impl WindowId for MockWindowId { + fn as_any(&self) -> &dyn Any { &self.0 } + + fn eq(&self, other: &dyn WindowId) -> bool { + self.0 == other.as_any().downcast_ref::().unwrap().0 + } + + fn box_clone(&self) -> Box { Box::new(*self) } +} + impl RawWindow for MockRawWindow { fn inner_size(&self) -> Size { self.size } fn set_inner_size(&mut self, size: Size) { self.size = size; } fn outer_size(&self) -> Size { self.size } fn inner_position(&self) -> Point { Point::zero() } fn outer_position(&self) -> Point { Point::zero() } - fn id(&self) -> WindowId { unsafe { WindowId::dummy() } } + fn id(&self) -> Box { Box::new(MockWindowId::dummy()) } fn set_cursor(&mut self, cursor: CursorIcon) { self.cursor = Some(cursor); } fn request_redraw(&self) {} fn scale_factor(&self) -> f64 { 1. } + fn as_any(&self) -> &dyn Any { self } } impl Window { diff --git a/geometry/Cargo.toml b/geometry/Cargo.toml new file mode 100644 index 000000000..eb2614ee7 --- /dev/null +++ b/geometry/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "ribir_geometry" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +euclid = "0.22.6" diff --git a/geometry/src/lib.rs b/geometry/src/lib.rs new file mode 100644 index 000000000..7b60c0114 --- /dev/null +++ b/geometry/src/lib.rs @@ -0,0 +1,28 @@ +/// The tag for device unit system to prevent mixing values from different +/// system. +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct PhysicUnit; + +/// The tag for logic unit system to prevent mixing values from different +/// system. +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct LogicUnit; + +pub type Rect = euclid::Rect; +pub type Point = euclid::Point2D; +pub type Size = euclid::Size2D; +pub type Transform = euclid::Transform2D; +pub type ScaleToPhysic = euclid::Scale; +pub type ScaleToLogic = euclid::Scale; + +pub type Vector = euclid::Vector2D; +pub type Angle = euclid::Angle; +pub type Box2D = euclid::Box2D; + +pub type DeviceRect = euclid::Rect; +pub type DevicePoint = euclid::Point2D; +pub type DeviceSize = euclid::Size2D; +pub type DeviceVector = euclid::Vector2D; + +pub const INFINITY_SIZE: Size = Size::new(f32::INFINITY, f32::INFINITY); +pub const ZERO_SIZE: Size = Size::new(0., 0.); diff --git a/painter/Cargo.toml b/painter/Cargo.toml index 3b6b13357..015341860 100644 --- a/painter/Cargo.toml +++ b/painter/Cargo.toml @@ -15,5 +15,6 @@ lyon_tessellation = {version = "1.0.1", features = ["serialization"]} palette = {version = "0.6.1", features = ["serializing"]} serde = {version = "1.0", features = ["rc"]} serde_json = "1.0.82" +ribir_geometry = {path = "../geometry"} ribir_text = {path = "../text"} usvg = {version = "0.23.0", features = ["text"]} diff --git a/painter/src/lib.rs b/painter/src/lib.rs index 16dd999c2..906b3861e 100644 --- a/painter/src/lib.rs +++ b/painter/src/lib.rs @@ -17,32 +17,8 @@ pub use ribir_text; pub use ribir_text::{typography::Overflow, *}; pub use svg_parser::SvgPaths; -/// The tag for device unit system to prevent mixing values from different -/// system. -#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct PhysicUnit; - -/// The tag for logic unit system to prevent mixing values from different -/// system. -#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct LogicUnit; - -pub type Rect = euclid::Rect; -pub type Point = euclid::Point2D; -pub type Size = euclid::Size2D; -pub type Transform = euclid::Transform2D; -pub type Vector = euclid::Vector2D; -pub type Angle = euclid::Angle; -pub type Box2D = euclid::Box2D; - -pub type DeviceRect = euclid::Rect; -pub type DevicePoint = euclid::Point2D; -pub type DeviceSize = euclid::Size2D; -pub type DeviceVector = euclid::Vector2D; - pub use euclid::Transform2D; pub use lyon_tessellation::{LineCap, LineJoin, StrokeOptions}; -pub const INFINITY_SIZE: Size = Size::new(f32::INFINITY, f32::INFINITY); -pub const ZERO_SIZE: Size = Size::new(0., 0.); +pub use ribir_geometry::*; diff --git a/winit/Cargo.toml b/winit/Cargo.toml new file mode 100644 index 000000000..c22a7047f --- /dev/null +++ b/winit/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "ribir_winit" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +log = "0.4.8" +ribir_app = { path = "../app" } +ribir_core = { path = "../core" } +ribir_geometry = { path = "../geometry" } +winit = "0.28.1" diff --git a/core/src/application.rs b/winit/src/application.rs similarity index 97% rename from core/src/application.rs rename to winit/src/application.rs index 2c8b67fa1..4928bf8a9 100644 --- a/core/src/application.rs +++ b/winit/src/application.rs @@ -1,4 +1,6 @@ -use crate::prelude::*; +use ribir_core::prelude::*; +use ribir_app::shell_window::ShellWindow; + use std::{collections::HashMap, rc::Rc}; pub use winit::window::WindowId; use winit::{ diff --git a/winit/src/from_cursor_icon.rs b/winit/src/from_cursor_icon.rs new file mode 100644 index 000000000..cfbc3f955 --- /dev/null +++ b/winit/src/from_cursor_icon.rs @@ -0,0 +1,106 @@ +use ribir_core::prelude::CursorIcon as RibirCursorIcon; +use winit::window::CursorIcon as WinitCursorIcon; + +pub struct WrappedCursorIcon(WinitCursorIcon); + +impl From for WrappedCursorIcon { + fn from(value: WinitCursorIcon) -> Self { WrappedCursorIcon(value) } +} + +impl From for WinitCursorIcon { + fn from(val: WrappedCursorIcon) -> Self { val.0 } +} + +impl From for RibirCursorIcon { + fn from(val: WrappedCursorIcon) -> Self { + match val.0 { + WinitCursorIcon::Default => RibirCursorIcon::Default, + WinitCursorIcon::Crosshair => RibirCursorIcon::Crosshair, + WinitCursorIcon::Hand => RibirCursorIcon::Hand, + WinitCursorIcon::Arrow => RibirCursorIcon::Arrow, + WinitCursorIcon::Move => RibirCursorIcon::Move, + WinitCursorIcon::Text => RibirCursorIcon::Text, + WinitCursorIcon::Wait => RibirCursorIcon::Wait, + WinitCursorIcon::Help => RibirCursorIcon::Help, + WinitCursorIcon::Progress => RibirCursorIcon::Progress, + WinitCursorIcon::NotAllowed => RibirCursorIcon::NotAllowed, + WinitCursorIcon::ContextMenu => RibirCursorIcon::ContextMenu, + WinitCursorIcon::Cell => RibirCursorIcon::Cell, + WinitCursorIcon::VerticalText => RibirCursorIcon::VerticalText, + WinitCursorIcon::Alias => RibirCursorIcon::Alias, + WinitCursorIcon::Copy => RibirCursorIcon::Copy, + WinitCursorIcon::NoDrop => RibirCursorIcon::NoDrop, + WinitCursorIcon::Grab => RibirCursorIcon::Grab, + WinitCursorIcon::Grabbing => RibirCursorIcon::Grabbing, + WinitCursorIcon::AllScroll => RibirCursorIcon::AllScroll, + WinitCursorIcon::ZoomIn => RibirCursorIcon::ZoomIn, + WinitCursorIcon::ZoomOut => RibirCursorIcon::ZoomOut, + WinitCursorIcon::EResize => RibirCursorIcon::EResize, + WinitCursorIcon::NResize => RibirCursorIcon::NResize, + WinitCursorIcon::NeResize => RibirCursorIcon::NeResize, + WinitCursorIcon::NwResize => RibirCursorIcon::NwResize, + WinitCursorIcon::SResize => RibirCursorIcon::SResize, + WinitCursorIcon::SeResize => RibirCursorIcon::SeResize, + WinitCursorIcon::SwResize => RibirCursorIcon::SwResize, + WinitCursorIcon::WResize => RibirCursorIcon::WResize, + WinitCursorIcon::EwResize => RibirCursorIcon::EwResize, + WinitCursorIcon::NsResize => RibirCursorIcon::NsResize, + WinitCursorIcon::NeswResize => RibirCursorIcon::NeswResize, + WinitCursorIcon::NwseResize => RibirCursorIcon::NwseResize, + WinitCursorIcon::ColResize => RibirCursorIcon::ColResize, + WinitCursorIcon::RowResize => RibirCursorIcon::RowResize, + } + } +} + +impl From for WrappedCursorIcon { + fn from(value: RibirCursorIcon) -> WrappedCursorIcon { + let w_icon = match value { + RibirCursorIcon::Default => WinitCursorIcon::Default, + RibirCursorIcon::Crosshair => WinitCursorIcon::Crosshair, + RibirCursorIcon::Hand => WinitCursorIcon::Hand, + RibirCursorIcon::Arrow => WinitCursorIcon::Arrow, + RibirCursorIcon::Move => WinitCursorIcon::Move, + RibirCursorIcon::Text => WinitCursorIcon::Text, + RibirCursorIcon::Wait => WinitCursorIcon::Wait, + RibirCursorIcon::Help => WinitCursorIcon::Help, + RibirCursorIcon::Progress => WinitCursorIcon::Progress, + RibirCursorIcon::NotAllowed => WinitCursorIcon::NotAllowed, + RibirCursorIcon::ContextMenu => WinitCursorIcon::ContextMenu, + RibirCursorIcon::Cell => WinitCursorIcon::Cell, + RibirCursorIcon::VerticalText => WinitCursorIcon::VerticalText, + RibirCursorIcon::Alias => WinitCursorIcon::Alias, + RibirCursorIcon::Copy => WinitCursorIcon::Copy, + RibirCursorIcon::NoDrop => WinitCursorIcon::NoDrop, + RibirCursorIcon::Grab => WinitCursorIcon::Grab, + RibirCursorIcon::Grabbing => WinitCursorIcon::Grabbing, + RibirCursorIcon::AllScroll => WinitCursorIcon::AllScroll, + RibirCursorIcon::ZoomIn => WinitCursorIcon::ZoomIn, + RibirCursorIcon::ZoomOut => WinitCursorIcon::ZoomOut, + RibirCursorIcon::EResize => WinitCursorIcon::EResize, + RibirCursorIcon::NResize => WinitCursorIcon::NResize, + RibirCursorIcon::NeResize => WinitCursorIcon::NeResize, + RibirCursorIcon::NwResize => WinitCursorIcon::NwResize, + RibirCursorIcon::SResize => WinitCursorIcon::SResize, + RibirCursorIcon::SeResize => WinitCursorIcon::SeResize, + RibirCursorIcon::SwResize => WinitCursorIcon::SwResize, + RibirCursorIcon::WResize => WinitCursorIcon::WResize, + RibirCursorIcon::EwResize => WinitCursorIcon::EwResize, + RibirCursorIcon::NsResize => WinitCursorIcon::NsResize, + RibirCursorIcon::NeswResize => WinitCursorIcon::NeswResize, + RibirCursorIcon::NwseResize => WinitCursorIcon::NwseResize, + RibirCursorIcon::ColResize => WinitCursorIcon::ColResize, + RibirCursorIcon::RowResize => WinitCursorIcon::RowResize, + }; + w_icon.into() + } +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn from_winit() { let x = WinitCursorIcon::Alias; } +} diff --git a/winit/src/from_device_id.rs b/winit/src/from_device_id.rs new file mode 100644 index 000000000..8f179263e --- /dev/null +++ b/winit/src/from_device_id.rs @@ -0,0 +1,56 @@ +use std::any::Any; + +use ribir_core::events::PointerId as RibirPointerId; +use winit::event::DeviceId as WinitDeviceId; + +#[derive(PartialEq, Clone, Eq, Debug)] +pub struct WrappedPointerId(WinitDeviceId); + +impl RibirPointerId for WrappedPointerId { + fn as_any(&self) -> &dyn Any { self } + fn eq(&self, other: &dyn RibirPointerId) -> bool { self.0 == WrappedPointerId::from(other).0 } + fn box_clone(&self) -> Box { Box::new(self.clone()) } +} + +impl From for WrappedPointerId { + fn from(value: WinitDeviceId) -> Self { WrappedPointerId(value) } +} + +impl From for WinitDeviceId { + fn from(val: WrappedPointerId) -> Self { val.0 } +} + +impl From> for WrappedPointerId { + fn from(value: Box) -> Self { + let x = value + .as_ref() + .as_any() + .downcast_ref::() + .map(|v| v.to_owned()) + .unwrap(); + x.into() + } +} + +impl From<&Box> for WrappedPointerId { + fn from(value: &Box) -> Self { + let x = value + .as_ref() + .as_any() + .downcast_ref::() + .map(|v| v.to_owned()) + .unwrap(); + x.into() + } +} + +impl From<&dyn RibirPointerId> for WrappedPointerId { + fn from(value: &dyn RibirPointerId) -> Self { + let x = value + .as_any() + .downcast_ref::() + .map(|v| v.to_owned()) + .unwrap(); + x.into() + } +} diff --git a/winit/src/from_element_state.rs b/winit/src/from_element_state.rs new file mode 100644 index 000000000..64f0ae20b --- /dev/null +++ b/winit/src/from_element_state.rs @@ -0,0 +1,31 @@ +use ribir_core::prelude::ElementState as RibirElementState; +use winit::event::ElementState as WinitElementState; + +pub struct WrappedElementState(WinitElementState); + +impl From for WrappedElementState { + fn from(value: WinitElementState) -> Self { WrappedElementState(value) } +} + +impl From for WinitElementState { + fn from(val: WrappedElementState) -> Self { val.0 } +} + +impl From for RibirElementState { + fn from(val: WrappedElementState) -> Self { + match val.0 { + WinitElementState::Pressed => RibirElementState::Pressed, + WinitElementState::Released => RibirElementState::Released, + } + } +} + +impl From for WrappedElementState { + fn from(value: RibirElementState) -> WrappedElementState { + let es = match value { + RibirElementState::Pressed => WinitElementState::Pressed, + RibirElementState::Released => WinitElementState::Released, + }; + es.into() + } +} diff --git a/winit/src/from_event.rs b/winit/src/from_event.rs new file mode 100644 index 000000000..765b910ca --- /dev/null +++ b/winit/src/from_event.rs @@ -0,0 +1,157 @@ +use std::any::Any; + +use crate::{ + from_device_id::WrappedPointerId, + from_element_state::WrappedElementState, + from_keyboard_input::WrappedKeyboardInput, + from_modifiers::WrappedModifiersState, + from_mouse::WrappedMouseButton, + from_size::{WrappedPhysicalPosition, WrappedPhysicalSize}, + from_touch_phase::WrappedTouchPhase, + prelude::{WrappedMouseScrollDelta, WrappedMutPhysicalSize}, +}; +use ribir_core::prelude::WindowEvent as RibirWindowEvent; +use winit::event::{ModifiersState as WinitModifiersState, WindowEvent as WinitWindowEvent}; + +pub struct WrappedWindowEvent<'a>(WinitWindowEvent<'a>); + +impl<'a> From> for WrappedWindowEvent<'a> { + fn from(value: WinitWindowEvent<'a>) -> Self { WrappedWindowEvent(value) } +} + +impl<'a> From> for WinitWindowEvent<'a> { + fn from(val: WrappedWindowEvent<'a>) -> Self { val.0 } +} + +impl<'a> From> for RibirWindowEvent { + fn from(val: WrappedWindowEvent<'a>) -> Self { + match val.0 { + WinitWindowEvent::Resized(size) => { + RibirWindowEvent::Resized(WrappedPhysicalSize::from(size).into()) + } + WinitWindowEvent::ReceivedCharacter(char) => RibirWindowEvent::ReceivedCharacter(char), + WinitWindowEvent::KeyboardInput { device_id, input, is_synthetic } => { + RibirWindowEvent::KeyboardInput { + device_id: Box::new(WrappedPointerId::from(device_id)), + input: WrappedKeyboardInput::from(input).into(), + is_synthetic, + } + } + WinitWindowEvent::ModifiersChanged(modifiers) => { + RibirWindowEvent::ModifiersChanged(WrappedModifiersState::from(modifiers).into()) + } + #[allow(deprecated)] + WinitWindowEvent::CursorMoved { device_id, position, modifiers: _ } => { + RibirWindowEvent::CursorMoved { + device_id: Box::new(WrappedPointerId::from(device_id)), + position: WrappedPhysicalPosition::::from(position).into(), + } + } + WinitWindowEvent::CursorLeft { device_id } => RibirWindowEvent::CursorLeft { + device_id: Box::new(WrappedPointerId::from(device_id)), + }, + #[allow(deprecated)] + WinitWindowEvent::MouseWheel { + device_id, + delta, + phase, + modifiers: _, + } => RibirWindowEvent::MouseWheel { + device_id: Box::new(WrappedPointerId::from(device_id)), + delta: WrappedMouseScrollDelta::from(delta).into(), + phase: WrappedTouchPhase::from(phase).into(), + }, + #[allow(deprecated)] + WinitWindowEvent::MouseInput { + device_id, + state, + button, + modifiers: _, + } => RibirWindowEvent::MouseInput { + device_id: Box::new(WrappedPointerId::from(device_id)), + state: WrappedElementState::from(state).into(), + button: WrappedMouseButton::from(button).into(), + }, + WinitWindowEvent::ScaleFactorChanged { scale_factor, new_inner_size } => { + RibirWindowEvent::ScaleFactorChanged { + scale_factor, + new_inner_size: Box::new(WrappedMutPhysicalSize::::from(new_inner_size)), + } + } + _ => RibirWindowEvent::Unsupported, + } + } +} + +impl<'a> From for WrappedWindowEvent<'a> { + fn from(value: RibirWindowEvent) -> WrappedWindowEvent<'a> { + let w_event = match value { + RibirWindowEvent::Resized(size) => { + WinitWindowEvent::Resized(WrappedPhysicalSize::from(size).into()) + } + RibirWindowEvent::ReceivedCharacter(char) => WinitWindowEvent::ReceivedCharacter(char), + RibirWindowEvent::KeyboardInput { device_id, input, is_synthetic } => { + WinitWindowEvent::KeyboardInput { + device_id: WrappedPointerId::from(device_id).into(), + input: WrappedKeyboardInput::from(input).into(), + is_synthetic, + } + } + RibirWindowEvent::ModifiersChanged(modifiers) => { + WinitWindowEvent::ModifiersChanged(WrappedModifiersState::from(modifiers).into()) + } + + RibirWindowEvent::CursorMoved { device_id, position } => WinitWindowEvent::CursorMoved { + device_id: WrappedPointerId::from(device_id).into(), + position: WrappedPhysicalPosition::::from(position).into(), + modifiers: WinitModifiersState::default(), + }, + RibirWindowEvent::CursorLeft { device_id } => WinitWindowEvent::CursorLeft { + device_id: WrappedPointerId::from(device_id).into(), + }, + + RibirWindowEvent::MouseWheel { device_id, delta, phase } => WinitWindowEvent::MouseWheel { + device_id: WrappedPointerId::from(device_id).into(), + delta: WrappedMouseScrollDelta::from(delta).into(), + phase: WrappedTouchPhase::from(phase).into(), + modifiers: WinitModifiersState::default(), + }, + + RibirWindowEvent::MouseInput { device_id, state, button } => WinitWindowEvent::MouseInput { + device_id: WrappedPointerId::from(device_id).into(), + state: WrappedElementState::from(state).into(), + button: WrappedMouseButton::from(button).into(), + modifiers: WinitModifiersState::default(), + }, + RibirWindowEvent::ScaleFactorChanged { scale_factor, new_inner_size } => { + let new_inner_size: Box = new_inner_size.as_any(); + let new_inner_size = new_inner_size + .downcast::>() + .unwrap(); + // let new_inner_size = new_inner_size.as_ref() + // .to_boxed_any() + // .downcast::>() + // .unwrap(); + + WinitWindowEvent::ScaleFactorChanged { + scale_factor, + new_inner_size: Box::into_inner(new_inner_size).into(), + } + } + other => { + panic!("Unimplemented: \"{other:?}\""); + } + }; + w_event.into() + } +} + +#[cfg(test)] +mod tests { + + use super::*; + use crate::from_size::WinitPhysicalSize; + + #[test] + fn from_winit() { WinitWindowEvent::Resized(WinitPhysicalSize:: { width: 5, height: 3 }); } +} diff --git a/winit/src/from_keyboard_input.rs b/winit/src/from_keyboard_input.rs new file mode 100644 index 000000000..e6a5fc8f4 --- /dev/null +++ b/winit/src/from_keyboard_input.rs @@ -0,0 +1,69 @@ +use ribir_core::prelude::KeyboardInput as RibirKeyboardInput; +use winit::{ + event::KeyboardInput as WinitKeyboardInput, event::ModifiersState as WinitModifiersState, +}; + +use crate::prelude::{WrappedElementState, WrappedVirtualKeyCode}; + +pub struct WrappedKeyboardInput(WinitKeyboardInput); + +impl From for WrappedKeyboardInput { + fn from(value: WinitKeyboardInput) -> Self { WrappedKeyboardInput(value) } +} + +impl From for WinitKeyboardInput { + fn from(val: WrappedKeyboardInput) -> Self { val.0 } +} + +impl From for RibirKeyboardInput { + fn from(val: WrappedKeyboardInput) -> Self { + RibirKeyboardInput { + scancode: val.0.scancode, + state: WrappedElementState::from(val.0.state).into(), + virtual_keycode: val + .0 + .virtual_keycode + .map(|v| WrappedVirtualKeyCode::from(v).into()), + } + } +} + +impl From for WrappedKeyboardInput { + #[allow(deprecated)] + fn from(value: RibirKeyboardInput) -> WrappedKeyboardInput { + WrappedKeyboardInput::from(WinitKeyboardInput { + scancode: value.scancode, + state: WrappedElementState::from(value.state).into(), + virtual_keycode: value + .virtual_keycode + .map(|v| WrappedVirtualKeyCode::from(v).into()), + modifiers: WinitModifiersState::default(), + }) + .into() + } +} + +#[cfg(test)] +mod tests { + use super::*; + use winit::{ + event::ElementState as WinitElementState, event::KeyboardInput as WinitKeyboardInput, + event::VirtualKeyCode as WinitVirtualKeyCode, + }; + + #[test] + fn from_winit() { + #[allow(deprecated)] + let w = WrappedKeyboardInput::from(WinitKeyboardInput { + scancode: 64, + state: WinitElementState::Pressed, + virtual_keycode: Some(WinitVirtualKeyCode::A), + + modifiers: WinitModifiersState::default(), + }); + let ribir: RibirKeyboardInput = w.into(); + let winit: RibirKeyboardInput = w.into(); + assert_eq!(ribir.scancode, 64); + assert_eq!(winit.scancode, 64); + } +} diff --git a/winit/src/from_modifiers.rs b/winit/src/from_modifiers.rs new file mode 100644 index 000000000..c2a359074 --- /dev/null +++ b/winit/src/from_modifiers.rs @@ -0,0 +1,72 @@ +use ribir_core::events::ModifiersState as RibirModifiersState; +use winit::event::ModifiersState as WinitModifiersState; + +pub struct WrappedModifiersState(WinitModifiersState); + +impl From for WrappedModifiersState { + fn from(value: WinitModifiersState) -> Self { WrappedModifiersState(value) } +} + +impl From for WinitModifiersState { + fn from(val: WrappedModifiersState) -> Self { val.0 } +} + +impl From for RibirModifiersState { + fn from(val: WrappedModifiersState) -> Self { + let shift = if val.0.shift() { + RibirModifiersState::SHIFT + } else { + RibirModifiersState::empty() + }; + + let ctrl = if val.0.ctrl() { + RibirModifiersState::CTRL + } else { + RibirModifiersState::empty() + }; + + let alt = if val.0.alt() { + RibirModifiersState::ALT + } else { + RibirModifiersState::empty() + }; + + let logo = if val.0.logo() { + RibirModifiersState::LOGO + } else { + RibirModifiersState::empty() + }; + + shift | ctrl | alt | logo + } +} + +impl From for WrappedModifiersState { + fn from(value: RibirModifiersState) -> WrappedModifiersState { + let shift: WinitModifiersState = if value.shift() { + WinitModifiersState::SHIFT + } else { + WinitModifiersState::empty() + }; + + let ctrl: WinitModifiersState = if value.ctrl() { + WinitModifiersState::CTRL + } else { + WinitModifiersState::empty() + }; + + let alt: WinitModifiersState = if value.alt() { + WinitModifiersState::ALT + } else { + WinitModifiersState::empty() + }; + + let logo: WinitModifiersState = if value.logo() { + WinitModifiersState::LOGO + } else { + WinitModifiersState::empty() + }; + + (shift | ctrl | alt | logo).into() + } +} diff --git a/winit/src/from_mouse.rs b/winit/src/from_mouse.rs new file mode 100644 index 000000000..9df33d876 --- /dev/null +++ b/winit/src/from_mouse.rs @@ -0,0 +1,45 @@ +use winit::event::MouseButton as WinitMouseButton; + +use ribir_core::events::MouseButtons as RibirMouseButton; + +pub struct WrappedMouseButton(WinitMouseButton); + +impl From for WrappedMouseButton { + fn from(value: WinitMouseButton) -> Self { WrappedMouseButton(value) } +} + +impl From for WinitMouseButton { + fn from(val: WrappedMouseButton) -> Self { val.0 } +} + +impl From for WrappedMouseButton { + fn from(value: RibirMouseButton) -> Self { + match value { + RibirMouseButton::PRIMARY => WrappedMouseButton(WinitMouseButton::Left), + RibirMouseButton::SECONDARY => WrappedMouseButton(WinitMouseButton::Right), + RibirMouseButton::AUXILIARY => WrappedMouseButton(WinitMouseButton::Middle), + RibirMouseButton::FOURTH => WrappedMouseButton(WinitMouseButton::Other(1)), + RibirMouseButton::FIFTH => WrappedMouseButton(WinitMouseButton::Other(2)), + v => { + log::warn!("The mouse button {v:?} is not supported."); + WrappedMouseButton(WinitMouseButton::Other(0)) + } + } + } +} + +impl From for RibirMouseButton { + fn from(val: WrappedMouseButton) -> Self { + match val.0 { + WinitMouseButton::Left => RibirMouseButton::PRIMARY, + WinitMouseButton::Right => RibirMouseButton::SECONDARY, + WinitMouseButton::Middle => RibirMouseButton::AUXILIARY, + WinitMouseButton::Other(1) => RibirMouseButton::FOURTH, + WinitMouseButton::Other(2) => RibirMouseButton::FIFTH, + WinitMouseButton::Other(v) => { + log::warn!("The mouse button {} is not supported.", v); + RibirMouseButton::default() + } + } + } +} diff --git a/winit/src/from_mouse_scroll_delta.rs b/winit/src/from_mouse_scroll_delta.rs new file mode 100644 index 000000000..51c9ffe86 --- /dev/null +++ b/winit/src/from_mouse_scroll_delta.rs @@ -0,0 +1,41 @@ +use ribir_core::events::MouseScrollDelta as RibirMouseScrollDelta; +use winit::event::MouseScrollDelta as WinitMouseScrollDelta; + +use crate::prelude::WrappedPhysicalPosition; + +pub struct WrappedMouseScrollDelta(WinitMouseScrollDelta); + +impl From for WrappedMouseScrollDelta { + fn from(value: WinitMouseScrollDelta) -> Self { WrappedMouseScrollDelta(value) } +} + +impl From for WinitMouseScrollDelta { + fn from(val: WrappedMouseScrollDelta) -> Self { val.0 } +} + +impl From for RibirMouseScrollDelta { + fn from(val: WrappedMouseScrollDelta) -> Self { + match val.0 { + WinitMouseScrollDelta::LineDelta(right, down) => { + RibirMouseScrollDelta::LineDelta(right, down) + } + WinitMouseScrollDelta::PixelDelta(pos) => { + RibirMouseScrollDelta::PixelDelta(WrappedPhysicalPosition::from(pos).into()) + } + } + } +} + +impl From for WrappedMouseScrollDelta { + fn from(value: RibirMouseScrollDelta) -> WrappedMouseScrollDelta { + let es = match value { + RibirMouseScrollDelta::LineDelta(right, down) => { + WinitMouseScrollDelta::LineDelta(right, down) + } + RibirMouseScrollDelta::PixelDelta(pos) => { + WinitMouseScrollDelta::PixelDelta(WrappedPhysicalPosition::from(pos).into()) + } + }; + es.into() + } +} diff --git a/winit/src/from_size.rs b/winit/src/from_size.rs new file mode 100644 index 000000000..4d3986fea --- /dev/null +++ b/winit/src/from_size.rs @@ -0,0 +1,170 @@ +use ribir_geometry::{ + DevicePoint as RibirPhysicalPosition, DeviceSize as RibirPhysicalSize, + Point as RibirLogicalPosition, Size as RibirLogicalSize, +}; + +use std::any::Any; +use std::borrow::Borrow; +use std::fmt::Debug; +use winit::dpi::Pixel; + +pub use winit::dpi::LogicalPosition as WinitLogicalPosition; +pub use winit::dpi::LogicalSize as WinitLogicalSize; +pub use winit::dpi::PhysicalPosition as WinitPhysicalPosition; +pub use winit::dpi::PhysicalSize as WinitPhysicalSize; + +use ribir_core::prelude::MutDeviceSize; + +#[derive(Debug)] +pub struct WrappedPhysicalSize(WinitPhysicalSize); + +impl From> for WrappedPhysicalSize { + fn from(value: WinitPhysicalSize) -> Self { WrappedPhysicalSize(value) } +} + +impl From> for WinitPhysicalSize { + fn from(value: WrappedPhysicalSize) -> Self { value.0 } +} + +impl From> for RibirPhysicalSize { + fn from(value: WrappedPhysicalSize) -> Self { + RibirPhysicalSize::new(value.0.width.cast(), value.0.height.cast()) + } +} + +impl From for WrappedPhysicalSize { + fn from(value: RibirPhysicalSize) -> Self { + WrappedPhysicalSize::::from(WinitPhysicalSize::::new( + value.width.cast(), + value.height.cast(), + )) + } +} + +#[derive(Debug)] +pub struct WrappedMutPhysicalSize<'a, T: Pixel>(&'a mut WinitPhysicalSize); + +impl<'a: 'static, T: Pixel + Debug> MutDeviceSize for WrappedMutPhysicalSize<'a, T> { + fn value(&self) -> RibirPhysicalSize { WrappedPhysicalSize::from(*(self.0)).into() } + + fn set_value(&mut self, size: RibirPhysicalSize) { + let val: WinitPhysicalSize = WrappedPhysicalSize::::from(size).into(); + self.0.width = val.width; + self.0.height = val.height; + } + + fn as_any(self: Box) -> Box { self } +} + +impl<'a, T: Pixel> From<&'a mut WinitPhysicalSize> for WrappedMutPhysicalSize<'a, T> { + fn from(value: &'a mut WinitPhysicalSize) -> Self { WrappedMutPhysicalSize(value) } +} + +impl<'a, T: Pixel> From> for &'a mut WinitPhysicalSize { + fn from(value: WrappedMutPhysicalSize<'a, T>) -> Self { value.0 } +} + +impl<'a, T: Pixel> From> for WinitPhysicalSize { + fn from(value: WrappedMutPhysicalSize) -> Self { *value.0.borrow() } +} + +// impl<'a, T: Pixel> From<&'a mut WinitPhysicalSize> for +// WrappedPhysicalSize { fn from(value: &'a mut WinitPhysicalSize) -> +// Self { WrappedPhysicalSize::from(value).into() } } + +// impl<'a, T: Pixel> From> for +// WrappedMutPhysicalSize<'a, T> { fn from(value: Box) -> +// Self { todo!() } } + +pub struct WrappedLogicalSize(WinitLogicalSize); + +impl From> for WrappedLogicalSize { + fn from(value: WinitLogicalSize) -> Self { WrappedLogicalSize(value) } +} + +impl From> for WinitLogicalSize { + fn from(value: WrappedLogicalSize) -> Self { value.0 } +} + +impl From> for RibirLogicalSize { + fn from(value: WrappedLogicalSize) -> Self { + RibirLogicalSize::new(value.0.width.cast(), value.0.height.cast()) + } +} + +impl From for WrappedLogicalSize { + fn from(value: RibirLogicalSize) -> Self { + WinitLogicalSize::new( + Pixel::from_f64(value.width as f64), + Pixel::from_f64(value.height as f64), + ) + .into() + } +} + +pub struct WrappedPhysicalPosition(WinitPhysicalPosition); + +impl From> for WrappedPhysicalPosition { + fn from(value: WinitPhysicalPosition) -> Self { WrappedPhysicalPosition(value) } +} + +impl From> for WinitPhysicalPosition { + fn from(value: WrappedPhysicalPosition) -> Self { value.0 } +} + +impl From> for RibirPhysicalPosition { + fn from(value: WrappedPhysicalPosition) -> Self { + RibirPhysicalPosition::new(value.0.x.cast(), value.0.y.cast()) + } +} + +impl From for WrappedPhysicalPosition { + fn from(value: RibirPhysicalPosition) -> Self { + WinitPhysicalPosition::new( + Pixel::from_f64(value.x as f64), + Pixel::from_f64(value.y as f64), + ) + .into() + } +} + +pub struct WrappedLogicalPosition(WinitLogicalPosition); + +impl From> for WrappedLogicalPosition { + fn from(value: WinitLogicalPosition) -> Self { WrappedLogicalPosition(value) } +} + +impl From> for WinitLogicalPosition { + fn from(value: WrappedLogicalPosition) -> Self { value.0 } +} + +impl From> for RibirLogicalPosition { + fn from(value: WrappedLogicalPosition) -> Self { + RibirLogicalPosition::new(value.0.x.cast(), value.0.y.cast()) + } +} + +impl From for WrappedLogicalPosition { + fn from(value: RibirLogicalPosition) -> Self { + WinitLogicalPosition::new( + Pixel::from_f64(value.x as f64), + Pixel::from_f64(value.y as f64), + ) + .into() + } +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn from_winit() { + let width = 3; + let height = 4; + let winit_phy_size = WinitPhysicalSize::new(width, height); + assert_eq!(winit_phy_size.width, width); + assert_eq!(winit_phy_size.height, height); + } +} diff --git a/winit/src/from_touch_phase.rs b/winit/src/from_touch_phase.rs new file mode 100644 index 000000000..c09f06727 --- /dev/null +++ b/winit/src/from_touch_phase.rs @@ -0,0 +1,35 @@ +use ribir_core::events::TouchPhase as RibirTouchPhase; +use winit::event::TouchPhase as WinitTouchPhase; + +pub struct WrappedTouchPhase(WinitTouchPhase); + +impl From for WrappedTouchPhase { + fn from(value: WinitTouchPhase) -> Self { WrappedTouchPhase(value) } +} + +impl From for WinitTouchPhase { + fn from(val: WrappedTouchPhase) -> Self { val.0 } +} + +impl From for RibirTouchPhase { + fn from(val: WrappedTouchPhase) -> Self { + match val.0 { + WinitTouchPhase::Started => RibirTouchPhase::Started, + WinitTouchPhase::Moved => RibirTouchPhase::Moved, + WinitTouchPhase::Ended => RibirTouchPhase::Ended, + WinitTouchPhase::Cancelled => RibirTouchPhase::Cancelled, + } + } +} + +impl From for WrappedTouchPhase { + fn from(value: RibirTouchPhase) -> WrappedTouchPhase { + let tb = match value { + RibirTouchPhase::Started => WinitTouchPhase::Started, + RibirTouchPhase::Moved => WinitTouchPhase::Moved, + RibirTouchPhase::Ended => WinitTouchPhase::Ended, + RibirTouchPhase::Cancelled => WinitTouchPhase::Cancelled, + }; + tb.into() + } +} diff --git a/winit/src/from_virtual_key_code.rs b/winit/src/from_virtual_key_code.rs new file mode 100644 index 000000000..a5dc26a20 --- /dev/null +++ b/winit/src/from_virtual_key_code.rs @@ -0,0 +1,375 @@ +use ribir_core::prelude::VirtualKeyCode as RibirVirtualKeyCode; +use winit::event::VirtualKeyCode as WinitVirtualKeyCode; + +pub struct WrappedVirtualKeyCode(WinitVirtualKeyCode); + +impl From for WrappedVirtualKeyCode { + fn from(value: WinitVirtualKeyCode) -> Self { WrappedVirtualKeyCode(value) } +} + +impl From for WinitVirtualKeyCode { + fn from(val: WrappedVirtualKeyCode) -> Self { val.0 } +} + +impl From for RibirVirtualKeyCode { + fn from(val: WrappedVirtualKeyCode) -> Self { + match val.0 { + WinitVirtualKeyCode::Key1 => RibirVirtualKeyCode::Key1, + WinitVirtualKeyCode::Key2 => RibirVirtualKeyCode::Key2, + WinitVirtualKeyCode::Key3 => RibirVirtualKeyCode::Key3, + WinitVirtualKeyCode::Key4 => RibirVirtualKeyCode::Key4, + WinitVirtualKeyCode::Key5 => RibirVirtualKeyCode::Key5, + WinitVirtualKeyCode::Key6 => RibirVirtualKeyCode::Key6, + WinitVirtualKeyCode::Key7 => RibirVirtualKeyCode::Key7, + WinitVirtualKeyCode::Key8 => RibirVirtualKeyCode::Key8, + WinitVirtualKeyCode::Key9 => RibirVirtualKeyCode::Key9, + WinitVirtualKeyCode::Key0 => RibirVirtualKeyCode::Key0, + + WinitVirtualKeyCode::A => RibirVirtualKeyCode::A, + WinitVirtualKeyCode::B => RibirVirtualKeyCode::B, + WinitVirtualKeyCode::C => RibirVirtualKeyCode::C, + WinitVirtualKeyCode::D => RibirVirtualKeyCode::D, + WinitVirtualKeyCode::E => RibirVirtualKeyCode::E, + WinitVirtualKeyCode::F => RibirVirtualKeyCode::F, + WinitVirtualKeyCode::G => RibirVirtualKeyCode::G, + WinitVirtualKeyCode::H => RibirVirtualKeyCode::H, + WinitVirtualKeyCode::I => RibirVirtualKeyCode::I, + WinitVirtualKeyCode::J => RibirVirtualKeyCode::J, + WinitVirtualKeyCode::K => RibirVirtualKeyCode::K, + WinitVirtualKeyCode::L => RibirVirtualKeyCode::L, + WinitVirtualKeyCode::M => RibirVirtualKeyCode::M, + WinitVirtualKeyCode::N => RibirVirtualKeyCode::N, + WinitVirtualKeyCode::O => RibirVirtualKeyCode::O, + WinitVirtualKeyCode::P => RibirVirtualKeyCode::P, + WinitVirtualKeyCode::Q => RibirVirtualKeyCode::Q, + WinitVirtualKeyCode::R => RibirVirtualKeyCode::R, + WinitVirtualKeyCode::S => RibirVirtualKeyCode::S, + WinitVirtualKeyCode::T => RibirVirtualKeyCode::T, + WinitVirtualKeyCode::U => RibirVirtualKeyCode::U, + WinitVirtualKeyCode::V => RibirVirtualKeyCode::V, + WinitVirtualKeyCode::W => RibirVirtualKeyCode::W, + WinitVirtualKeyCode::X => RibirVirtualKeyCode::X, + WinitVirtualKeyCode::Y => RibirVirtualKeyCode::Y, + WinitVirtualKeyCode::Z => RibirVirtualKeyCode::Z, + + WinitVirtualKeyCode::Escape => RibirVirtualKeyCode::Escape, + + WinitVirtualKeyCode::F1 => RibirVirtualKeyCode::F1, + WinitVirtualKeyCode::F2 => RibirVirtualKeyCode::F2, + WinitVirtualKeyCode::F3 => RibirVirtualKeyCode::F3, + WinitVirtualKeyCode::F4 => RibirVirtualKeyCode::F4, + WinitVirtualKeyCode::F5 => RibirVirtualKeyCode::F5, + WinitVirtualKeyCode::F6 => RibirVirtualKeyCode::F6, + WinitVirtualKeyCode::F7 => RibirVirtualKeyCode::F7, + WinitVirtualKeyCode::F8 => RibirVirtualKeyCode::F8, + WinitVirtualKeyCode::F9 => RibirVirtualKeyCode::F9, + WinitVirtualKeyCode::F10 => RibirVirtualKeyCode::F10, + WinitVirtualKeyCode::F11 => RibirVirtualKeyCode::F11, + WinitVirtualKeyCode::F12 => RibirVirtualKeyCode::F12, + WinitVirtualKeyCode::F13 => RibirVirtualKeyCode::F13, + WinitVirtualKeyCode::F14 => RibirVirtualKeyCode::F14, + WinitVirtualKeyCode::F15 => RibirVirtualKeyCode::F15, + WinitVirtualKeyCode::F16 => RibirVirtualKeyCode::F16, + WinitVirtualKeyCode::F17 => RibirVirtualKeyCode::F17, + WinitVirtualKeyCode::F18 => RibirVirtualKeyCode::F18, + WinitVirtualKeyCode::F19 => RibirVirtualKeyCode::F19, + WinitVirtualKeyCode::F20 => RibirVirtualKeyCode::F20, + WinitVirtualKeyCode::F21 => RibirVirtualKeyCode::F21, + WinitVirtualKeyCode::F22 => RibirVirtualKeyCode::F22, + WinitVirtualKeyCode::F23 => RibirVirtualKeyCode::F23, + WinitVirtualKeyCode::F24 => RibirVirtualKeyCode::F24, + + WinitVirtualKeyCode::Snapshot => RibirVirtualKeyCode::Snapshot, + WinitVirtualKeyCode::Scroll => RibirVirtualKeyCode::Scroll, + WinitVirtualKeyCode::Pause => RibirVirtualKeyCode::Pause, + + WinitVirtualKeyCode::Insert => RibirVirtualKeyCode::Insert, + WinitVirtualKeyCode::Home => RibirVirtualKeyCode::Home, + WinitVirtualKeyCode::Delete => RibirVirtualKeyCode::Delete, + WinitVirtualKeyCode::End => RibirVirtualKeyCode::End, + WinitVirtualKeyCode::PageDown => RibirVirtualKeyCode::PageDown, + WinitVirtualKeyCode::PageUp => RibirVirtualKeyCode::PageUp, + + WinitVirtualKeyCode::Left => RibirVirtualKeyCode::Left, + WinitVirtualKeyCode::Up => RibirVirtualKeyCode::Up, + WinitVirtualKeyCode::Right => RibirVirtualKeyCode::Right, + WinitVirtualKeyCode::Down => RibirVirtualKeyCode::Down, + + WinitVirtualKeyCode::Back => RibirVirtualKeyCode::Back, + WinitVirtualKeyCode::Return => RibirVirtualKeyCode::Return, + WinitVirtualKeyCode::Space => RibirVirtualKeyCode::Space, + + WinitVirtualKeyCode::Compose => RibirVirtualKeyCode::Compose, + + WinitVirtualKeyCode::Caret => RibirVirtualKeyCode::Caret, + + WinitVirtualKeyCode::Numlock => RibirVirtualKeyCode::Numlock, + WinitVirtualKeyCode::Numpad0 => RibirVirtualKeyCode::Numpad0, + WinitVirtualKeyCode::Numpad1 => RibirVirtualKeyCode::Numpad1, + WinitVirtualKeyCode::Numpad2 => RibirVirtualKeyCode::Numpad2, + WinitVirtualKeyCode::Numpad3 => RibirVirtualKeyCode::Numpad3, + WinitVirtualKeyCode::Numpad4 => RibirVirtualKeyCode::Numpad4, + WinitVirtualKeyCode::Numpad5 => RibirVirtualKeyCode::Numpad5, + WinitVirtualKeyCode::Numpad6 => RibirVirtualKeyCode::Numpad6, + WinitVirtualKeyCode::Numpad7 => RibirVirtualKeyCode::Numpad7, + WinitVirtualKeyCode::Numpad8 => RibirVirtualKeyCode::Numpad8, + WinitVirtualKeyCode::Numpad9 => RibirVirtualKeyCode::Numpad9, + WinitVirtualKeyCode::NumpadAdd => RibirVirtualKeyCode::NumpadAdd, + WinitVirtualKeyCode::NumpadDivide => RibirVirtualKeyCode::NumpadDivide, + WinitVirtualKeyCode::NumpadDecimal => RibirVirtualKeyCode::NumpadDecimal, + WinitVirtualKeyCode::NumpadComma => RibirVirtualKeyCode::NumpadComma, + WinitVirtualKeyCode::NumpadEnter => RibirVirtualKeyCode::NumpadEnter, + WinitVirtualKeyCode::NumpadEquals => RibirVirtualKeyCode::NumpadEquals, + WinitVirtualKeyCode::NumpadMultiply => RibirVirtualKeyCode::NumpadMultiply, + WinitVirtualKeyCode::NumpadSubtract => RibirVirtualKeyCode::NumpadSubtract, + + WinitVirtualKeyCode::AbntC1 => RibirVirtualKeyCode::AbntC1, + WinitVirtualKeyCode::AbntC2 => RibirVirtualKeyCode::AbntC2, + WinitVirtualKeyCode::Apostrophe => RibirVirtualKeyCode::Apostrophe, + WinitVirtualKeyCode::Apps => RibirVirtualKeyCode::Apps, + WinitVirtualKeyCode::Asterisk => RibirVirtualKeyCode::Asterisk, + WinitVirtualKeyCode::At => RibirVirtualKeyCode::At, + WinitVirtualKeyCode::Ax => RibirVirtualKeyCode::Ax, + WinitVirtualKeyCode::Backslash => RibirVirtualKeyCode::Backslash, + WinitVirtualKeyCode::Calculator => RibirVirtualKeyCode::Calculator, + WinitVirtualKeyCode::Capital => RibirVirtualKeyCode::Capital, + WinitVirtualKeyCode::Colon => RibirVirtualKeyCode::Colon, + WinitVirtualKeyCode::Comma => RibirVirtualKeyCode::Comma, + WinitVirtualKeyCode::Convert => RibirVirtualKeyCode::Convert, + WinitVirtualKeyCode::Equals => RibirVirtualKeyCode::Equals, + WinitVirtualKeyCode::Grave => RibirVirtualKeyCode::Grave, + WinitVirtualKeyCode::Kana => RibirVirtualKeyCode::Kana, + WinitVirtualKeyCode::Kanji => RibirVirtualKeyCode::Kanji, + WinitVirtualKeyCode::LAlt => RibirVirtualKeyCode::LAlt, + WinitVirtualKeyCode::LBracket => RibirVirtualKeyCode::LBracket, + WinitVirtualKeyCode::LControl => RibirVirtualKeyCode::LControl, + WinitVirtualKeyCode::LShift => RibirVirtualKeyCode::LShift, + WinitVirtualKeyCode::LWin => RibirVirtualKeyCode::LWin, + WinitVirtualKeyCode::Mail => RibirVirtualKeyCode::Mail, + WinitVirtualKeyCode::MediaSelect => RibirVirtualKeyCode::MediaSelect, + WinitVirtualKeyCode::MediaStop => RibirVirtualKeyCode::MediaStop, + WinitVirtualKeyCode::Minus => RibirVirtualKeyCode::Minus, + WinitVirtualKeyCode::Mute => RibirVirtualKeyCode::Mute, + WinitVirtualKeyCode::MyComputer => RibirVirtualKeyCode::MyComputer, + WinitVirtualKeyCode::NavigateForward => RibirVirtualKeyCode::NavigateForward, + WinitVirtualKeyCode::NavigateBackward => RibirVirtualKeyCode::NavigateBackward, + WinitVirtualKeyCode::NextTrack => RibirVirtualKeyCode::NextTrack, + WinitVirtualKeyCode::NoConvert => RibirVirtualKeyCode::NoConvert, + WinitVirtualKeyCode::OEM102 => RibirVirtualKeyCode::OEM102, + WinitVirtualKeyCode::Period => RibirVirtualKeyCode::Period, + WinitVirtualKeyCode::PlayPause => RibirVirtualKeyCode::PlayPause, + WinitVirtualKeyCode::Plus => RibirVirtualKeyCode::Plus, + WinitVirtualKeyCode::Power => RibirVirtualKeyCode::Power, + WinitVirtualKeyCode::PrevTrack => RibirVirtualKeyCode::PrevTrack, + WinitVirtualKeyCode::RAlt => RibirVirtualKeyCode::RAlt, + WinitVirtualKeyCode::RBracket => RibirVirtualKeyCode::RBracket, + WinitVirtualKeyCode::RControl => RibirVirtualKeyCode::RControl, + WinitVirtualKeyCode::RShift => RibirVirtualKeyCode::RShift, + WinitVirtualKeyCode::RWin => RibirVirtualKeyCode::RWin, + WinitVirtualKeyCode::Semicolon => RibirVirtualKeyCode::Semicolon, + WinitVirtualKeyCode::Slash => RibirVirtualKeyCode::Slash, + WinitVirtualKeyCode::Sleep => RibirVirtualKeyCode::Sleep, + WinitVirtualKeyCode::Stop => RibirVirtualKeyCode::Stop, + WinitVirtualKeyCode::Sysrq => RibirVirtualKeyCode::Sysrq, + WinitVirtualKeyCode::Tab => RibirVirtualKeyCode::Tab, + WinitVirtualKeyCode::Underline => RibirVirtualKeyCode::Underline, + WinitVirtualKeyCode::Unlabeled => RibirVirtualKeyCode::Unlabeled, + WinitVirtualKeyCode::VolumeDown => RibirVirtualKeyCode::VolumeDown, + WinitVirtualKeyCode::VolumeUp => RibirVirtualKeyCode::VolumeUp, + WinitVirtualKeyCode::Wake => RibirVirtualKeyCode::Wake, + WinitVirtualKeyCode::WebBack => RibirVirtualKeyCode::WebBack, + WinitVirtualKeyCode::WebFavorites => RibirVirtualKeyCode::WebFavorites, + WinitVirtualKeyCode::WebForward => RibirVirtualKeyCode::WebForward, + WinitVirtualKeyCode::WebHome => RibirVirtualKeyCode::WebHome, + WinitVirtualKeyCode::WebRefresh => RibirVirtualKeyCode::WebRefresh, + WinitVirtualKeyCode::WebSearch => RibirVirtualKeyCode::WebSearch, + WinitVirtualKeyCode::WebStop => RibirVirtualKeyCode::WebStop, + WinitVirtualKeyCode::Yen => RibirVirtualKeyCode::Yen, + WinitVirtualKeyCode::Copy => RibirVirtualKeyCode::Copy, + WinitVirtualKeyCode::Paste => RibirVirtualKeyCode::Paste, + WinitVirtualKeyCode::Cut => RibirVirtualKeyCode::Cut, + } + } +} + +impl From for WrappedVirtualKeyCode { + fn from(value: RibirVirtualKeyCode) -> WrappedVirtualKeyCode { + let kc = match value { + RibirVirtualKeyCode::Key1 => WinitVirtualKeyCode::Key1, + RibirVirtualKeyCode::Key2 => WinitVirtualKeyCode::Key2, + RibirVirtualKeyCode::Key3 => WinitVirtualKeyCode::Key3, + RibirVirtualKeyCode::Key4 => WinitVirtualKeyCode::Key4, + RibirVirtualKeyCode::Key5 => WinitVirtualKeyCode::Key5, + RibirVirtualKeyCode::Key6 => WinitVirtualKeyCode::Key6, + RibirVirtualKeyCode::Key7 => WinitVirtualKeyCode::Key7, + RibirVirtualKeyCode::Key8 => WinitVirtualKeyCode::Key8, + RibirVirtualKeyCode::Key9 => WinitVirtualKeyCode::Key9, + RibirVirtualKeyCode::Key0 => WinitVirtualKeyCode::Key0, + + RibirVirtualKeyCode::A => WinitVirtualKeyCode::A, + RibirVirtualKeyCode::B => WinitVirtualKeyCode::B, + RibirVirtualKeyCode::C => WinitVirtualKeyCode::C, + RibirVirtualKeyCode::D => WinitVirtualKeyCode::D, + RibirVirtualKeyCode::E => WinitVirtualKeyCode::E, + RibirVirtualKeyCode::F => WinitVirtualKeyCode::F, + RibirVirtualKeyCode::G => WinitVirtualKeyCode::G, + RibirVirtualKeyCode::H => WinitVirtualKeyCode::H, + RibirVirtualKeyCode::I => WinitVirtualKeyCode::I, + RibirVirtualKeyCode::J => WinitVirtualKeyCode::J, + RibirVirtualKeyCode::K => WinitVirtualKeyCode::K, + RibirVirtualKeyCode::L => WinitVirtualKeyCode::L, + RibirVirtualKeyCode::M => WinitVirtualKeyCode::M, + RibirVirtualKeyCode::N => WinitVirtualKeyCode::N, + RibirVirtualKeyCode::O => WinitVirtualKeyCode::O, + RibirVirtualKeyCode::P => WinitVirtualKeyCode::P, + RibirVirtualKeyCode::Q => WinitVirtualKeyCode::Q, + RibirVirtualKeyCode::R => WinitVirtualKeyCode::R, + RibirVirtualKeyCode::S => WinitVirtualKeyCode::S, + RibirVirtualKeyCode::T => WinitVirtualKeyCode::T, + RibirVirtualKeyCode::U => WinitVirtualKeyCode::U, + RibirVirtualKeyCode::V => WinitVirtualKeyCode::V, + RibirVirtualKeyCode::W => WinitVirtualKeyCode::W, + RibirVirtualKeyCode::X => WinitVirtualKeyCode::X, + RibirVirtualKeyCode::Y => WinitVirtualKeyCode::Y, + RibirVirtualKeyCode::Z => WinitVirtualKeyCode::Z, + + RibirVirtualKeyCode::Escape => WinitVirtualKeyCode::Escape, + + RibirVirtualKeyCode::F1 => WinitVirtualKeyCode::F1, + RibirVirtualKeyCode::F2 => WinitVirtualKeyCode::F2, + RibirVirtualKeyCode::F3 => WinitVirtualKeyCode::F3, + RibirVirtualKeyCode::F4 => WinitVirtualKeyCode::F4, + RibirVirtualKeyCode::F5 => WinitVirtualKeyCode::F5, + RibirVirtualKeyCode::F6 => WinitVirtualKeyCode::F6, + RibirVirtualKeyCode::F7 => WinitVirtualKeyCode::F7, + RibirVirtualKeyCode::F8 => WinitVirtualKeyCode::F8, + RibirVirtualKeyCode::F9 => WinitVirtualKeyCode::F9, + RibirVirtualKeyCode::F10 => WinitVirtualKeyCode::F10, + RibirVirtualKeyCode::F11 => WinitVirtualKeyCode::F11, + RibirVirtualKeyCode::F12 => WinitVirtualKeyCode::F12, + RibirVirtualKeyCode::F13 => WinitVirtualKeyCode::F13, + RibirVirtualKeyCode::F14 => WinitVirtualKeyCode::F14, + RibirVirtualKeyCode::F15 => WinitVirtualKeyCode::F15, + RibirVirtualKeyCode::F16 => WinitVirtualKeyCode::F16, + RibirVirtualKeyCode::F17 => WinitVirtualKeyCode::F17, + RibirVirtualKeyCode::F18 => WinitVirtualKeyCode::F18, + RibirVirtualKeyCode::F19 => WinitVirtualKeyCode::F19, + RibirVirtualKeyCode::F20 => WinitVirtualKeyCode::F20, + RibirVirtualKeyCode::F21 => WinitVirtualKeyCode::F21, + RibirVirtualKeyCode::F22 => WinitVirtualKeyCode::F22, + RibirVirtualKeyCode::F23 => WinitVirtualKeyCode::F23, + RibirVirtualKeyCode::F24 => WinitVirtualKeyCode::F24, + + RibirVirtualKeyCode::Snapshot => WinitVirtualKeyCode::Snapshot, + RibirVirtualKeyCode::Scroll => WinitVirtualKeyCode::Scroll, + RibirVirtualKeyCode::Pause => WinitVirtualKeyCode::Pause, + + RibirVirtualKeyCode::Insert => WinitVirtualKeyCode::Insert, + RibirVirtualKeyCode::Home => WinitVirtualKeyCode::Home, + RibirVirtualKeyCode::Delete => WinitVirtualKeyCode::Delete, + RibirVirtualKeyCode::End => WinitVirtualKeyCode::End, + RibirVirtualKeyCode::PageDown => WinitVirtualKeyCode::PageDown, + RibirVirtualKeyCode::PageUp => WinitVirtualKeyCode::PageUp, + + RibirVirtualKeyCode::Left => WinitVirtualKeyCode::Left, + RibirVirtualKeyCode::Up => WinitVirtualKeyCode::Up, + RibirVirtualKeyCode::Right => WinitVirtualKeyCode::Right, + RibirVirtualKeyCode::Down => WinitVirtualKeyCode::Down, + + RibirVirtualKeyCode::Back => WinitVirtualKeyCode::Back, + RibirVirtualKeyCode::Return => WinitVirtualKeyCode::Return, + RibirVirtualKeyCode::Space => WinitVirtualKeyCode::Space, + + RibirVirtualKeyCode::Compose => WinitVirtualKeyCode::Compose, + + RibirVirtualKeyCode::Caret => WinitVirtualKeyCode::Caret, + + RibirVirtualKeyCode::Numlock => WinitVirtualKeyCode::Numlock, + RibirVirtualKeyCode::Numpad0 => WinitVirtualKeyCode::Numpad0, + RibirVirtualKeyCode::Numpad1 => WinitVirtualKeyCode::Numpad1, + RibirVirtualKeyCode::Numpad2 => WinitVirtualKeyCode::Numpad2, + RibirVirtualKeyCode::Numpad3 => WinitVirtualKeyCode::Numpad3, + RibirVirtualKeyCode::Numpad4 => WinitVirtualKeyCode::Numpad4, + RibirVirtualKeyCode::Numpad5 => WinitVirtualKeyCode::Numpad5, + RibirVirtualKeyCode::Numpad6 => WinitVirtualKeyCode::Numpad6, + RibirVirtualKeyCode::Numpad7 => WinitVirtualKeyCode::Numpad7, + RibirVirtualKeyCode::Numpad8 => WinitVirtualKeyCode::Numpad8, + RibirVirtualKeyCode::Numpad9 => WinitVirtualKeyCode::Numpad9, + RibirVirtualKeyCode::NumpadAdd => WinitVirtualKeyCode::NumpadAdd, + RibirVirtualKeyCode::NumpadDivide => WinitVirtualKeyCode::NumpadDivide, + RibirVirtualKeyCode::NumpadDecimal => WinitVirtualKeyCode::NumpadDecimal, + RibirVirtualKeyCode::NumpadComma => WinitVirtualKeyCode::NumpadComma, + RibirVirtualKeyCode::NumpadEnter => WinitVirtualKeyCode::NumpadEnter, + RibirVirtualKeyCode::NumpadEquals => WinitVirtualKeyCode::NumpadEquals, + RibirVirtualKeyCode::NumpadMultiply => WinitVirtualKeyCode::NumpadMultiply, + RibirVirtualKeyCode::NumpadSubtract => WinitVirtualKeyCode::NumpadSubtract, + + RibirVirtualKeyCode::AbntC1 => WinitVirtualKeyCode::AbntC1, + RibirVirtualKeyCode::AbntC2 => WinitVirtualKeyCode::AbntC2, + RibirVirtualKeyCode::Apostrophe => WinitVirtualKeyCode::Apostrophe, + RibirVirtualKeyCode::Apps => WinitVirtualKeyCode::Apps, + RibirVirtualKeyCode::Asterisk => WinitVirtualKeyCode::Asterisk, + RibirVirtualKeyCode::At => WinitVirtualKeyCode::At, + RibirVirtualKeyCode::Ax => WinitVirtualKeyCode::Ax, + RibirVirtualKeyCode::Backslash => WinitVirtualKeyCode::Backslash, + RibirVirtualKeyCode::Calculator => WinitVirtualKeyCode::Calculator, + RibirVirtualKeyCode::Capital => WinitVirtualKeyCode::Capital, + RibirVirtualKeyCode::Colon => WinitVirtualKeyCode::Colon, + RibirVirtualKeyCode::Comma => WinitVirtualKeyCode::Comma, + RibirVirtualKeyCode::Convert => WinitVirtualKeyCode::Convert, + RibirVirtualKeyCode::Equals => WinitVirtualKeyCode::Equals, + RibirVirtualKeyCode::Grave => WinitVirtualKeyCode::Grave, + RibirVirtualKeyCode::Kana => WinitVirtualKeyCode::Kana, + RibirVirtualKeyCode::Kanji => WinitVirtualKeyCode::Kanji, + RibirVirtualKeyCode::LAlt => WinitVirtualKeyCode::LAlt, + RibirVirtualKeyCode::LBracket => WinitVirtualKeyCode::LBracket, + RibirVirtualKeyCode::LControl => WinitVirtualKeyCode::LControl, + RibirVirtualKeyCode::LShift => WinitVirtualKeyCode::LShift, + RibirVirtualKeyCode::LWin => WinitVirtualKeyCode::LWin, + RibirVirtualKeyCode::Mail => WinitVirtualKeyCode::Mail, + RibirVirtualKeyCode::MediaSelect => WinitVirtualKeyCode::MediaSelect, + RibirVirtualKeyCode::MediaStop => WinitVirtualKeyCode::MediaStop, + RibirVirtualKeyCode::Minus => WinitVirtualKeyCode::Minus, + RibirVirtualKeyCode::Mute => WinitVirtualKeyCode::Mute, + RibirVirtualKeyCode::MyComputer => WinitVirtualKeyCode::MyComputer, + RibirVirtualKeyCode::NavigateForward => WinitVirtualKeyCode::NavigateForward, + RibirVirtualKeyCode::NavigateBackward => WinitVirtualKeyCode::NavigateBackward, + RibirVirtualKeyCode::NextTrack => WinitVirtualKeyCode::NextTrack, + RibirVirtualKeyCode::NoConvert => WinitVirtualKeyCode::NoConvert, + RibirVirtualKeyCode::OEM102 => WinitVirtualKeyCode::OEM102, + RibirVirtualKeyCode::Period => WinitVirtualKeyCode::Period, + RibirVirtualKeyCode::PlayPause => WinitVirtualKeyCode::PlayPause, + RibirVirtualKeyCode::Plus => WinitVirtualKeyCode::Plus, + RibirVirtualKeyCode::Power => WinitVirtualKeyCode::Power, + RibirVirtualKeyCode::PrevTrack => WinitVirtualKeyCode::PrevTrack, + RibirVirtualKeyCode::RAlt => WinitVirtualKeyCode::RAlt, + RibirVirtualKeyCode::RBracket => WinitVirtualKeyCode::RBracket, + RibirVirtualKeyCode::RControl => WinitVirtualKeyCode::RControl, + RibirVirtualKeyCode::RShift => WinitVirtualKeyCode::RShift, + RibirVirtualKeyCode::RWin => WinitVirtualKeyCode::RWin, + RibirVirtualKeyCode::Semicolon => WinitVirtualKeyCode::Semicolon, + RibirVirtualKeyCode::Slash => WinitVirtualKeyCode::Slash, + RibirVirtualKeyCode::Sleep => WinitVirtualKeyCode::Sleep, + RibirVirtualKeyCode::Stop => WinitVirtualKeyCode::Stop, + RibirVirtualKeyCode::Sysrq => WinitVirtualKeyCode::Sysrq, + RibirVirtualKeyCode::Tab => WinitVirtualKeyCode::Tab, + RibirVirtualKeyCode::Underline => WinitVirtualKeyCode::Underline, + RibirVirtualKeyCode::Unlabeled => WinitVirtualKeyCode::Unlabeled, + RibirVirtualKeyCode::VolumeDown => WinitVirtualKeyCode::VolumeDown, + RibirVirtualKeyCode::VolumeUp => WinitVirtualKeyCode::VolumeUp, + RibirVirtualKeyCode::Wake => WinitVirtualKeyCode::Wake, + RibirVirtualKeyCode::WebBack => WinitVirtualKeyCode::WebBack, + RibirVirtualKeyCode::WebFavorites => WinitVirtualKeyCode::WebFavorites, + RibirVirtualKeyCode::WebForward => WinitVirtualKeyCode::WebForward, + RibirVirtualKeyCode::WebHome => WinitVirtualKeyCode::WebHome, + RibirVirtualKeyCode::WebRefresh => WinitVirtualKeyCode::WebRefresh, + RibirVirtualKeyCode::WebSearch => WinitVirtualKeyCode::WebSearch, + RibirVirtualKeyCode::WebStop => WinitVirtualKeyCode::WebStop, + RibirVirtualKeyCode::Yen => WinitVirtualKeyCode::Yen, + RibirVirtualKeyCode::Copy => WinitVirtualKeyCode::Copy, + RibirVirtualKeyCode::Paste => WinitVirtualKeyCode::Paste, + RibirVirtualKeyCode::Cut => WinitVirtualKeyCode::Cut, + }; + kc.into() + } +} diff --git a/winit/src/from_window.rs b/winit/src/from_window.rs new file mode 100644 index 000000000..fd176c3d7 --- /dev/null +++ b/winit/src/from_window.rs @@ -0,0 +1,112 @@ +use std::any::Any; + +use ribir_core::{ + prelude::{CursorIcon, Point, Size}, + window::{RawWindow as CoreWindow, WindowId}, +}; +use winit::{dpi::Pixel, window::Window as WinitWindow}; + +use crate::{ + from_cursor_icon::WrappedCursorIcon, + from_size::{WinitLogicalSize, WrappedLogicalPosition, WrappedLogicalSize}, + prelude::WrappedWindowId, +}; + +// #[derive(PartialEq, Eq)] +pub struct WrappedWindow(WinitWindow); + +impl CoreWindow for WrappedWindow { + fn inner_size(&self) -> Size { + WrappedLogicalSize::::from(self.0.inner_size().to_logical(self.scale_factor())).into() + } + + fn set_inner_size(&mut self, size: Size) { + self.0.set_inner_size( + WinitLogicalSize::::new(size.width.cast(), size.height.cast()) + .to_physical::(self.scale_factor()), + ); + } + + fn outer_size(&self) -> Size { + WrappedLogicalSize::::from(self.0.outer_size().to_logical(self.scale_factor())).into() + } + + fn inner_position(&self) -> Point { + WrappedLogicalPosition::::from( + self + .0 + .inner_position() + .expect(" Can only be called on the main thread") + .to_logical(self.scale_factor()), + ) + .into() + } + + fn outer_position(&self) -> Point { + WrappedLogicalPosition::::from( + self + .0 + .outer_position() + .expect(" Can only be called on the main thread") + .to_logical(self.scale_factor()), + ) + .into() + } + + fn id(&self) -> Box { Box::new(WrappedWindowId::from(self.0.id())) } + + fn request_redraw(&self) { self.0.request_redraw(); } + + fn set_cursor(&mut self, cursor: CursorIcon) { + self + .0 + .set_cursor_icon(WrappedCursorIcon::from(cursor).into()); + } + + fn scale_factor(&self) -> f64 { self.0.scale_factor() } + + fn as_any(&self) -> &dyn Any { self } +} + +impl From for WrappedWindow { + fn from(value: WinitWindow) -> Self { WrappedWindow(value) } +} + +impl From for WinitWindow { + fn from(val: WrappedWindow) -> Self { val.0 } +} + +// impl From> for WrappedWindow { +// fn from(value: Box) -> Self { +// let core_window = value +// .as_ref() +// .as_any() +// .downcast_ref::() +// .map(|v| v) +// .unwrap(); +// (*core_window).into() +// } +// } + +// impl From<&Box> for WrappedWindow { +// fn from(value: &Box) -> Self { +// let winit_window = value +// .as_ref() +// .as_any() +// .downcast_ref::() +// .map(|v| *(v.to_owned())) +// .unwrap(); +// winit_window.into() +// } +// } + +// impl From<&dyn CoreWindow> for WrappedWindow { +// fn from(value: &dyn CoreWindow) -> Self { +// let winit_window = value +// .as_any() +// .downcast_ref::() +// .map(|v| *(v.to_owned())) +// .unwrap(); +// winit_window.into() +// } +// } diff --git a/winit/src/from_window_id.rs b/winit/src/from_window_id.rs new file mode 100644 index 000000000..48d9ad086 --- /dev/null +++ b/winit/src/from_window_id.rs @@ -0,0 +1,56 @@ +use std::any::Any; + +use ribir_core::window::WindowId as RibirWindowId; +use winit::window::WindowId as WinitWindowId; + +#[derive(PartialEq, Clone, Eq, Debug)] +pub struct WrappedWindowId(WinitWindowId); + +impl RibirWindowId for WrappedWindowId { + fn as_any(&self) -> &dyn Any { self } + fn eq(&self, other: &dyn RibirWindowId) -> bool { self.0 == WrappedWindowId::from(other).0 } + fn box_clone(&self) -> Box { Box::new(self.clone()) } +} + +impl From for WrappedWindowId { + fn from(value: WinitWindowId) -> Self { WrappedWindowId(value) } +} + +impl From for WinitWindowId { + fn from(val: WrappedWindowId) -> Self { val.0 } +} + +impl From> for WrappedWindowId { + fn from(value: Box) -> Self { + let x = value + .as_ref() + .as_any() + .downcast_ref::() + .map(|v| v.to_owned()) + .unwrap(); + x.into() + } +} + +impl From<&Box> for WrappedWindowId { + fn from(value: &Box) -> Self { + let x = value + .as_ref() + .as_any() + .downcast_ref::() + .map(|v| v.to_owned()) + .unwrap(); + x.into() + } +} + +impl From<&dyn RibirWindowId> for WrappedWindowId { + fn from(value: &dyn RibirWindowId) -> Self { + let x = value + .as_any() + .downcast_ref::() + .map(|v| v.to_owned()) + .unwrap(); + x.into() + } +} diff --git a/winit/src/lib.rs b/winit/src/lib.rs new file mode 100644 index 000000000..9f7d6384c --- /dev/null +++ b/winit/src/lib.rs @@ -0,0 +1,44 @@ +#![feature(test, decl_macro, box_into_inner)] + +mod from_cursor_icon; +mod from_device_id; +mod from_element_state; +mod from_event; +mod from_keyboard_input; +mod from_modifiers; +mod from_mouse; +mod from_mouse_scroll_delta; +mod from_size; +mod from_touch_phase; +mod from_virtual_key_code; +mod from_window; +mod from_window_id; + +pub mod prelude { + #[doc(no_inline)] + pub use crate::from_cursor_icon::*; + #[doc(no_inline)] + pub use crate::from_device_id::*; + #[doc(no_inline)] + pub use crate::from_element_state::*; + #[doc(no_inline)] + pub use crate::from_event::*; + #[doc(no_inline)] + pub use crate::from_keyboard_input::*; + #[doc(no_inline)] + pub use crate::from_modifiers::*; + #[doc(no_inline)] + pub use crate::from_mouse::*; + #[doc(no_inline)] + pub use crate::from_mouse_scroll_delta::*; + #[doc(no_inline)] + pub use crate::from_size::*; + #[doc(no_inline)] + pub use crate::from_touch_phase::*; + #[doc(no_inline)] + pub use crate::from_virtual_key_code::*; + #[doc(no_inline)] + pub use crate::from_window::*; + #[doc(no_inline)] + pub use crate::from_window_id::*; +} From f58de75c677a2d0ac35bc6826db2e6727c828c01 Mon Sep 17 00:00:00 2001 From: Guenter Zoechbauer Date: Mon, 13 Mar 2023 13:54:25 +0100 Subject: [PATCH 2/9] Drop converting WrappedMutPhysicalSize back to winit enum except of static lifetime --- core/src/events/event.rs | 12 +++--------- core/src/window.rs | 2 +- winit/src/from_event.rs | 35 +++++++++++++---------------------- winit/src/from_size.rs | 31 ------------------------------- 4 files changed, 17 insertions(+), 63 deletions(-) diff --git a/core/src/events/event.rs b/core/src/events/event.rs index 7b9c91505..ca568caa7 100644 --- a/core/src/events/event.rs +++ b/core/src/events/event.rs @@ -1,5 +1,5 @@ use ribir_painter::{DevicePoint, DeviceSize}; -use std::{any::Any, fmt::Debug}; +use std::fmt::Debug; use super::{ModifiersState, MouseButtons, PointerId, ScanCode, VirtualKeyCode}; @@ -78,16 +78,10 @@ pub enum WindowEvent { /// module. ScaleFactorChanged { scale_factor: f64, - new_inner_size: Box, + new_inner_size: DeviceSize }, } -pub trait MutDeviceSize: Debug { - fn value(&self) -> DeviceSize; - fn set_value(&mut self, size: DeviceSize); - fn as_any(self: Box) -> Box; -} - impl PartialEq for WindowEvent { fn eq(&self, other: &Self) -> bool { match (self, other) { @@ -157,7 +151,7 @@ impl PartialEq for WindowEvent { scale_factor: r_scale_factor, new_inner_size: r_new_inner_size, }, - ) => l_scale_factor == r_scale_factor && l_new_inner_size.value() == r_new_inner_size.value(), + ) => l_scale_factor == r_scale_factor && l_new_inner_size == r_new_inner_size, _ => false, } } diff --git a/core/src/window.rs b/core/src/window.rs index b7695fb3c..9504b16b6 100644 --- a/core/src/window.rs +++ b/core/src/window.rs @@ -214,7 +214,7 @@ impl Window { self.on_resize(DeviceSize::new(size.width, size.height)); } WindowEvent::ScaleFactorChanged { new_inner_size, scale_factor } => { - self.on_resize(new_inner_size.value()); + self.on_resize(new_inner_size); let factor = scale_factor as f32; self.painter.reset(Some(factor)); } diff --git a/winit/src/from_event.rs b/winit/src/from_event.rs index 765b910ca..9c8600ef3 100644 --- a/winit/src/from_event.rs +++ b/winit/src/from_event.rs @@ -1,4 +1,3 @@ -use std::any::Any; use crate::{ from_device_id::WrappedPointerId, @@ -8,7 +7,7 @@ use crate::{ from_mouse::WrappedMouseButton, from_size::{WrappedPhysicalPosition, WrappedPhysicalSize}, from_touch_phase::WrappedTouchPhase, - prelude::{WrappedMouseScrollDelta, WrappedMutPhysicalSize}, + prelude::WrappedMouseScrollDelta, }; use ribir_core::prelude::WindowEvent as RibirWindowEvent; use winit::event::{ModifiersState as WinitModifiersState, WindowEvent as WinitWindowEvent}; @@ -72,12 +71,12 @@ impl<'a> From> for RibirWindowEvent { state: WrappedElementState::from(state).into(), button: WrappedMouseButton::from(button).into(), }, - WinitWindowEvent::ScaleFactorChanged { scale_factor, new_inner_size } => { - RibirWindowEvent::ScaleFactorChanged { - scale_factor, - new_inner_size: Box::new(WrappedMutPhysicalSize::::from(new_inner_size)), - } - } + // WinitWindowEvent::ScaleFactorChanged { scale_factor, new_inner_size } => { + // RibirWindowEvent::ScaleFactorChanged { + // scale_factor, + // new_inner_size: WrappedPhysicalSize::::from(new_inner_size).into(), + // } + // } _ => RibirWindowEvent::Unsupported, } } @@ -123,20 +122,12 @@ impl<'a> From for WrappedWindowEvent<'a> { button: WrappedMouseButton::from(button).into(), modifiers: WinitModifiersState::default(), }, - RibirWindowEvent::ScaleFactorChanged { scale_factor, new_inner_size } => { - let new_inner_size: Box = new_inner_size.as_any(); - let new_inner_size = new_inner_size - .downcast::>() - .unwrap(); - // let new_inner_size = new_inner_size.as_ref() - // .to_boxed_any() - // .downcast::>() - // .unwrap(); - - WinitWindowEvent::ScaleFactorChanged { - scale_factor, - new_inner_size: Box::into_inner(new_inner_size).into(), - } + RibirWindowEvent::ScaleFactorChanged { scale_factor:_, new_inner_size:_ } => { + // WinitWindowEvent::ScaleFactorChanged { + // scale_factor, + // new_inner_size: WrappedPhysicalSize::::from(new_inner_size).into(), + // } + panic!("Unimplemented: \"{value:?}\" can not be converted to winit enum."); } other => { panic!("Unimplemented: \"{other:?}\""); diff --git a/winit/src/from_size.rs b/winit/src/from_size.rs index 4d3986fea..f1e19366b 100644 --- a/winit/src/from_size.rs +++ b/winit/src/from_size.rs @@ -3,8 +3,6 @@ use ribir_geometry::{ Point as RibirLogicalPosition, Size as RibirLogicalSize, }; -use std::any::Any; -use std::borrow::Borrow; use std::fmt::Debug; use winit::dpi::Pixel; @@ -13,8 +11,6 @@ pub use winit::dpi::LogicalSize as WinitLogicalSize; pub use winit::dpi::PhysicalPosition as WinitPhysicalPosition; pub use winit::dpi::PhysicalSize as WinitPhysicalSize; -use ribir_core::prelude::MutDeviceSize; - #[derive(Debug)] pub struct WrappedPhysicalSize(WinitPhysicalSize); @@ -41,33 +37,6 @@ impl From for WrappedPhysicalSize { } } -#[derive(Debug)] -pub struct WrappedMutPhysicalSize<'a, T: Pixel>(&'a mut WinitPhysicalSize); - -impl<'a: 'static, T: Pixel + Debug> MutDeviceSize for WrappedMutPhysicalSize<'a, T> { - fn value(&self) -> RibirPhysicalSize { WrappedPhysicalSize::from(*(self.0)).into() } - - fn set_value(&mut self, size: RibirPhysicalSize) { - let val: WinitPhysicalSize = WrappedPhysicalSize::::from(size).into(); - self.0.width = val.width; - self.0.height = val.height; - } - - fn as_any(self: Box) -> Box { self } -} - -impl<'a, T: Pixel> From<&'a mut WinitPhysicalSize> for WrappedMutPhysicalSize<'a, T> { - fn from(value: &'a mut WinitPhysicalSize) -> Self { WrappedMutPhysicalSize(value) } -} - -impl<'a, T: Pixel> From> for &'a mut WinitPhysicalSize { - fn from(value: WrappedMutPhysicalSize<'a, T>) -> Self { value.0 } -} - -impl<'a, T: Pixel> From> for WinitPhysicalSize { - fn from(value: WrappedMutPhysicalSize) -> Self { *value.0.borrow() } -} - // impl<'a, T: Pixel> From<&'a mut WinitPhysicalSize> for // WrappedPhysicalSize { fn from(value: &'a mut WinitPhysicalSize) -> // Self { WrappedPhysicalSize::from(value).into() } } From 5c2b984a4bd1633c2b8b0860b1747234135d1638 Mon Sep 17 00:00:00 2001 From: Guenter Zoechbauer Date: Wed, 15 Mar 2023 07:04:24 +0100 Subject: [PATCH 3/9] All tests pass --- app/src/application.rs | 1 + app/src/lib.rs | 4 + core/Cargo.toml | 2 +- core/src/builtin_widgets/cursor.rs | 25 ++-- core/src/builtin_widgets/scrollable.rs | 30 ++--- core/src/events/dispatcher.rs | 153 +++++++++++++------------ core/src/events/event.rs | 20 ++-- core/src/events/keyboard.rs | 2 +- core/src/events/pointers.rs | 47 ++++---- core/src/events/wheel.rs | 4 +- core/src/window.rs | 25 ++-- geometry/src/lib.rs | 18 +++ macros/Cargo.toml | 1 + macros/tests/animations_syntax_test.rs | 6 +- macros/tests/code_gen_test.rs | 25 ++-- macros/tests/path_child_test.rs | 2 +- ribir/Cargo.toml | 3 + ribir/examples/todo_mvp.rs | 9 +- ribir/src/lib.rs | 15 ++- winit/Cargo.toml | 6 + winit/src/application.rs | 28 +++-- winit/src/from_device_id.rs | 50 ++++---- winit/src/from_event.rs | 3 +- winit/src/from_keyboard_input.rs | 4 +- winit/src/from_mouse_scroll_delta.rs | 2 +- winit/src/from_size.rs | 10 +- winit/src/from_window.rs | 4 +- winit/src/from_window_id.rs | 72 +++++++----- winit/src/lib.rs | 6 + winit/src/window_builder.rs | 117 +++++++++++++++++++ 30 files changed, 446 insertions(+), 248 deletions(-) create mode 100644 app/src/application.rs create mode 100644 winit/src/window_builder.rs diff --git a/app/src/application.rs b/app/src/application.rs new file mode 100644 index 000000000..0f8c8ed52 --- /dev/null +++ b/app/src/application.rs @@ -0,0 +1 @@ +pub trait Application {} diff --git a/app/src/lib.rs b/app/src/lib.rs index 2eef88ff1..d5a4ff7e6 100644 --- a/app/src/lib.rs +++ b/app/src/lib.rs @@ -1,2 +1,6 @@ +pub mod application; pub mod event_loop; pub mod shell_window; +pub mod prelude { + pub use crate::application::*; +} diff --git a/core/Cargo.toml b/core/Cargo.toml index 8e883f046..a6b3f4122 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -17,7 +17,7 @@ lyon_algorithms = "1.0.1" lyon_geom = "1.0.1" png = {version = "0.17.3", optional = true} ribir_algo = {path = "../algo"} -ribir_gpu = {path = "../gpu"} +# ribir_gpu = {path = "../gpu"} ribir_macros = {path = "../macros"} ribir_painter = {path = "../painter", version = "*"} ribir_text = {path = "../text"} diff --git a/core/src/builtin_widgets/cursor.rs b/core/src/builtin_widgets/cursor.rs index df1c85a14..412d516d1 100644 --- a/core/src/builtin_widgets/cursor.rs +++ b/core/src/builtin_widgets/cursor.rs @@ -115,61 +115,56 @@ mod tests { wnd.draw_frame(); let tree = &mut wnd.widget_tree; - let device_id = DummyPointerId::dummy(); + let device_id = MockPointerId::zero(); let dispatcher = &mut wnd.dispatcher; dispatcher.dispatch( WindowEvent::CursorMoved { device_id, - position: (1f64, 1.).into(), - modifiers: ModifiersState::default(), + position: DevicePoint::new(1, 1), }, tree, 1., ); assert_eq!(dispatcher.take_cursor_icon(), Some(CursorIcon::Help)); - let device_id = DummyPointerId::dummy(); + let device_id = MockPointerId::zero(); dispatcher.dispatch( WindowEvent::CursorMoved { device_id, - position: (101f64, 1.).into(), - modifiers: ModifiersState::default(), + position: DevicePoint::new(101, 1), }, tree, 1., ); assert_eq!(dispatcher.take_cursor_icon(), Some(CursorIcon::Hand)); - let device_id = DummyPointerId::dummy(); + let device_id = MockPointerId::zero(); dispatcher.dispatch( WindowEvent::CursorMoved { device_id, - position: (201f64, 1.).into(), - modifiers: ModifiersState::default(), + position: DevicePoint::new(201, 1), }, tree, 1., ); assert_eq!(dispatcher.take_cursor_icon(), Some(CursorIcon::AllScroll)); - let device_id = DummyPointerId::dummy(); + let device_id = MockPointerId::zero(); dispatcher.dispatch( WindowEvent::CursorMoved { device_id, - position: (101f64, 1.).into(), - modifiers: ModifiersState::default(), + position: DevicePoint::new(101, 1), }, tree, 1., ); assert_eq!(dispatcher.take_cursor_icon(), Some(CursorIcon::Hand)); - let device_id = DummyPointerId::dummy(); + let device_id = MockPointerId::zero(); dispatcher.dispatch( WindowEvent::CursorMoved { device_id, - position: (1f64, 1.).into(), - modifiers: ModifiersState::default(), + position: DevicePoint::new(1, 1), }, tree, 1., diff --git a/core/src/builtin_widgets/scrollable.rs b/core/src/builtin_widgets/scrollable.rs index bce7a6f3f..7071b36e8 100644 --- a/core/src/builtin_widgets/scrollable.rs +++ b/core/src/builtin_widgets/scrollable.rs @@ -113,7 +113,7 @@ mod tests { // use winit::event::{DeviceId, ModifiersState, MouseScrollDelta, TouchPhase, // WindowEvent}; - fn test_assert(scrollable: Scrollable, delta_x: f32, delta_y: f32, expect_x: f32, expect_y: f32) { + fn test_assert(scrollable: Scrollable, delta_x: i32, delta_y: i32, expect_x: i32, expect_y: i32) { let w = widget! { MockBox { size: Size::new(1000., 1000.), @@ -125,39 +125,39 @@ mod tests { wnd.draw_frame(); - let device_id = DummyPointerId::dummy(); + let device_id = MockPointerId::zero(); wnd.processes_native_event(WindowEvent::MouseWheel { device_id, - delta: MouseScrollDelta::PixelDelta((delta_x, delta_y).into()), + delta: MouseScrollDelta::PixelDelta(DeviceOffset::new(delta_x, delta_y).into()), phase: TouchPhase::Started, - modifiers: ModifiersState::default(), }); wnd.layout(); - let rect = layout_info_by_path(&wnd, &[0, 0, 0, 0]); + let scale = ScaleOffsetToPhysic::new(1); + let rect = scale.transform_rect(&layout_info_by_path(&wnd, &[0, 0, 0, 0]).cast()); assert_eq!(rect.origin.y, expect_y); - let rect = layout_info_by_path(&wnd, &[0, 0, 0, 0, 0]); + let rect = scale.transform_rect(&layout_info_by_path(&wnd, &[0, 0, 0, 0, 0]).cast()); assert_eq!(rect.origin.x, expect_x); } #[test] fn x_scroll() { - test_assert(Scrollable::X, -10., -10., -10., 0.); - test_assert(Scrollable::X, -10000., -10., -900., 0.); - test_assert(Scrollable::X, 100., -10., 0., 0.); + test_assert(Scrollable::X, -10, -10, -10, 0); + test_assert(Scrollable::X, -10000, -10, -900, 0); + test_assert(Scrollable::X, 100, -10, 0, 0); } #[test] fn y_scroll() { - test_assert(Scrollable::Y, -10., -10., 0., -10.); - test_assert(Scrollable::Y, -10., -10000., 0., -900.); - test_assert(Scrollable::Y, 10., 100., 0., 0.); + test_assert(Scrollable::Y, -10, -10, 0, -10); + test_assert(Scrollable::Y, -10, -10000, 0, -900); + test_assert(Scrollable::Y, 10, 100, 0, 0); } #[test] fn both_scroll() { - test_assert(Scrollable::Both, -10., -10., -10., -10.); - test_assert(Scrollable::Both, -10000., -10000., -900., -900.); - test_assert(Scrollable::Both, 100., 100., 0., 0.); + test_assert(Scrollable::Both, -10, -10, -10, -10); + test_assert(Scrollable::Both, -10000, -10000, -900, -900); + test_assert(Scrollable::Both, 100, 100, 0, 0); } } diff --git a/core/src/events/dispatcher.rs b/core/src/events/dispatcher.rs index 1784636bd..8544a4266 100644 --- a/core/src/events/dispatcher.rs +++ b/core/src/events/dispatcher.rs @@ -141,7 +141,7 @@ impl Dispatcher { .mouse_button .0 .get_or_insert(device_id.clone()) - .eq(device_id.as_ref()) + .eq(&device_id) { match state { ElementState::Pressed => { @@ -164,7 +164,7 @@ impl Dispatcher { .take()? .lowest_common_ancestor(release_event.target(), &tree.arena)?; let mut tap_event = - PointerEvent::from_mouse(Box::new(DummyPointerId::dummy()), tap_on, tree, &self.info); + PointerEvent::from_mouse(MockPointerId::zero(), tap_on, tree, &self.info); tree.bubble_event::(&mut tap_event); } @@ -240,8 +240,7 @@ impl Dispatcher { .iter() .filter(|w| !w.is_dropped(arena)) .for_each(|l| { - let mut event = - PointerEvent::from_mouse(Box::new(DummyPointerId::dummy()), *l, tree, &self.info); + let mut event = PointerEvent::from_mouse(MockPointerId::zero(), *l, tree, &self.info); l.assert_get(arena).query_all_type( |pointer: &PointerLeaveListener| { pointer.dispatch(&mut event); @@ -273,8 +272,7 @@ impl Dispatcher { self.entered_widgets.iter().rev().for_each(|w| { let obj = w.assert_get(arena); if obj.contain_type::() { - let mut event = - PointerEvent::from_mouse(Box::new(DummyPointerId::dummy()), *w, tree, &self.info); + let mut event = PointerEvent::from_mouse(MockPointerId::zero(), *w, tree, &self.info); obj.query_all_type( |pointer: &PointerEnterListener| { pointer.dispatch(&mut event); @@ -319,9 +317,9 @@ impl Dispatcher { } fn pointer_event_for_hit_widget(&mut self, tree: &WidgetTree) -> Option { - self.hit_widget(tree).map(|target| { - PointerEvent::from_mouse(Box::new(DummyPointerId::dummy()), target, tree, &self.info) - }) + self + .hit_widget(tree) + .map(|target| PointerEvent::from_mouse(MockPointerId::zero(), target, tree, &self.info)) } } @@ -428,8 +426,10 @@ mod tests { let mut wnd = Window::default_mock(root, None); wnd.draw_frame(); - let device_id = unsafe { PointerId::dummy() }; - wnd.processes_native_event(WindowEvent::CursorMoved { device_id, position: (1., 1.).into() }); + wnd.processes_native_event(WindowEvent::CursorMoved { + device_id: MockPointerId::zero(), + position: DevicePoint::new(1, 1), + }); { let mut records = event_record.borrow_mut(); @@ -439,9 +439,9 @@ mod tests { } wnd.processes_native_event(WindowEvent::MouseInput { - device_id, + device_id: MockPointerId::zero(), state: ElementState::Pressed, - button: MouseButtons::Left, + button: MouseButtons::PRIMARY, }); let mut records = event_record.borrow_mut(); @@ -460,31 +460,33 @@ mod tests { let mut wnd = Window::default_mock(root, None); wnd.draw_frame(); - let device_id = unsafe { PointerId::dummy() }; wnd.processes_native_event(WindowEvent::MouseInput { - device_id, + device_id: MockPointerId::zero(), state: ElementState::Pressed, - button: MouseButtons::Left, + button: MouseButtons::PRIMARY, }); wnd.processes_native_event(WindowEvent::MouseInput { - device_id, + device_id: MockPointerId::zero(), state: ElementState::Pressed, - button: MouseButtons::Right, + button: MouseButtons::SECONDARY, }); - wnd.processes_native_event(WindowEvent::CursorMoved { device_id, position: (1, 1).into() }); + wnd.processes_native_event(WindowEvent::CursorMoved { + device_id: MockPointerId::zero(), + position: (1, 1).into(), + }); wnd.processes_native_event(WindowEvent::MouseInput { - device_id, + device_id: MockPointerId::zero(), state: ElementState::Released, - button: MouseButtons::Left, + button: MouseButtons::PRIMARY, }); wnd.processes_native_event(WindowEvent::MouseInput { - device_id, + device_id: MockPointerId::zero(), state: ElementState::Released, - button: MouseButtons::Right, + button: MouseButtons::SECONDARY, }); let records = event_record.borrow(); @@ -510,31 +512,26 @@ mod tests { let mut wnd = Window::default_mock(root, None); wnd.draw_frame(); - let device_id = unsafe { PointerId::dummy() }; wnd.processes_native_event(WindowEvent::MouseInput { - device_id, + device_id: MockPointerId::zero(), state: ElementState::Pressed, - button: MouseButtons::Left, + button: MouseButtons::PRIMARY, }); assert_eq!(event_record.borrow().len(), 1); // A mouse press/release emit during another mouse's press will be ignored. - let device_id_2 = unsafe { - let mut id = PointerId::dummy(); - (&mut id as *mut PointerId).write_bytes(1, 1); - id - }; + let device_id_2 = MockPointerId::new(1); wnd.processes_native_event(WindowEvent::MouseInput { - device_id: device_id_2, + device_id: device_id_2.clone(), state: ElementState::Pressed, - button: MouseButtons::Left, + button: MouseButtons::PRIMARY, }); wnd.processes_native_event(WindowEvent::MouseInput { - device_id: device_id_2, + device_id: device_id_2.clone(), state: ElementState::Released, - button: MouseButtons::Left, + button: MouseButtons::PRIMARY, }); assert_eq!(event_record.borrow().len(), 1); @@ -549,9 +546,9 @@ mod tests { assert_eq!(event_record.borrow()[1].btns, MouseButtons::PRIMARY); wnd.processes_native_event(WindowEvent::MouseInput { - device_id, + device_id: MockPointerId::zero(), state: ElementState::Released, - button: MouseButtons::Left, + button: MouseButtons::PRIMARY, }); assert_eq!(event_record.borrow().len(), 3); @@ -588,9 +585,9 @@ mod tests { wnd.draw_frame(); wnd.processes_native_event(WindowEvent::MouseInput { - device_id: unsafe { PointerId::dummy() }, + device_id: MockPointerId::zero(), state: ElementState::Pressed, - button: MouseButtons::Left, + button: MouseButtons::PRIMARY, }); assert_eq!(event_record.borrow().len(), 1); @@ -630,24 +627,31 @@ mod tests { let mut wnd = Window::default_mock(w.into_widget(), Some(Size::new(100., 100.))); wnd.draw_frame(); - let device_id = unsafe { PointerId::dummy() }; - - wnd.processes_native_event(WindowEvent::CursorMoved { device_id, position: (10, 10).into() }); + wnd.processes_native_event(WindowEvent::CursorMoved { + device_id: MockPointerId::zero(), + position: (10, 10).into(), + }); assert_eq!(&*enter_event.borrow(), &[2, 1]); // leave to parent - wnd.processes_native_event(WindowEvent::CursorMoved { device_id, position: (99, 99).into() }); + wnd.processes_native_event(WindowEvent::CursorMoved { + device_id: MockPointerId::zero(), + position: (99, 99).into(), + }); assert_eq!(&*leave_event.borrow(), &[1]); // move in same widget, // check if duplicate event fired. - wnd.processes_native_event(WindowEvent::CursorMoved { device_id, position: (99, 99).into() }); + wnd.processes_native_event(WindowEvent::CursorMoved { + device_id: MockPointerId::zero(), + position: (99, 99).into(), + }); assert_eq!(&*enter_event.borrow(), &[2, 1]); assert_eq!(&*leave_event.borrow(), &[1]); // leave all wnd.processes_native_event(WindowEvent::CursorMoved { - device_id, + device_id: MockPointerId::zero(), position: (999, 999).into(), }); @@ -655,8 +659,11 @@ mod tests { // leave event trigger by window left. leave_event.borrow_mut().clear(); - wnd.processes_native_event(WindowEvent::CursorMoved { device_id, position: (10, 10).into() }); - wnd.processes_native_event(WindowEvent::CursorLeft { device_id }); + wnd.processes_native_event(WindowEvent::CursorMoved { + device_id: MockPointerId::zero(), + position: (10, 10).into(), + }); + wnd.processes_native_event(WindowEvent::CursorLeft { device_id: MockPointerId::zero() }); assert_eq!(&*leave_event.borrow(), &[1, 2]); } @@ -679,22 +686,19 @@ mod tests { let mut wnd = Window::default_mock(w, Some(Size::new(400., 400.))); wnd.draw_frame(); - let device_id = unsafe { PointerId::dummy() }; - let modifiers = ModifiersState::default(); - wnd.processes_native_event(WindowEvent::CursorMoved { - device_id, - position: (50f64, 50f64).into(), + device_id: MockPointerId::zero(), + position: DevicePoint::new(50, 50), }); wnd.processes_native_event(WindowEvent::MouseInput { - device_id, + device_id: MockPointerId::zero(), state: ElementState::Pressed, - button: MouseButtons::Left, + button: MouseButtons::PRIMARY, }); wnd.processes_native_event(WindowEvent::MouseInput { - device_id, + device_id: MockPointerId::zero(), state: ElementState::Released, - button: MouseButtons::Left, + button: MouseButtons::PRIMARY, }); { @@ -704,22 +708,22 @@ mod tests { } wnd.processes_native_event(WindowEvent::CursorMoved { - device_id, - position: (50f64, 50f64).into(), + device_id: MockPointerId::zero(), + position: DevicePoint::new(50, 50), }); wnd.processes_native_event(WindowEvent::MouseInput { - device_id, + device_id: MockPointerId::zero(), state: ElementState::Pressed, - button: MouseButtons::Left, + button: MouseButtons::PRIMARY, }); wnd.processes_native_event(WindowEvent::CursorMoved { - device_id, - position: (50f64, 150f64).into(), + device_id: MockPointerId::zero(), + position: DevicePoint::new(50, 150), }); wnd.processes_native_event(WindowEvent::MouseInput { - device_id, + device_id: MockPointerId::zero(), state: ElementState::Released, - button: MouseButtons::Left, + button: MouseButtons::PRIMARY, }); { @@ -744,34 +748,33 @@ mod tests { let mut wnd = Window::default_mock(w, Some(Size::new(100., 100.))); wnd.draw_frame(); - let device_id = unsafe { PointerId::dummy() }; - let modifiers = ModifiersState::default(); + let device_id = MockPointerId::zero(); wnd.processes_native_event(WindowEvent::CursorMoved { - device_id, - position: (45f64, 45f64).into(), + device_id: device_id.clone(), + position: DevicePoint::new(45, 45), }); wnd.processes_native_event(WindowEvent::MouseInput { - device_id, + device_id: device_id.clone(), state: ElementState::Pressed, - button: MouseButtons::Left, + button: MouseButtons::PRIMARY, }); // point down on a focus widget assert!(wnd.dispatcher.focusing().is_some()); wnd.processes_native_event(WindowEvent::MouseInput { - device_id, + device_id: device_id.clone(), state: ElementState::Released, - button: MouseButtons::Left, + button: MouseButtons::PRIMARY, }); wnd.processes_native_event(WindowEvent::CursorMoved { - device_id, - position: (80f64, 80f64).into(), + device_id: device_id.clone(), + position: DevicePoint::new(80, 80), }); wnd.processes_native_event(WindowEvent::MouseInput { device_id, state: ElementState::Pressed, - button: MouseButtons::Left, + button: MouseButtons::PRIMARY, }); assert!(wnd.dispatcher.focusing().is_none()); diff --git a/core/src/events/event.rs b/core/src/events/event.rs index ca568caa7..11f0d6b96 100644 --- a/core/src/events/event.rs +++ b/core/src/events/event.rs @@ -1,4 +1,4 @@ -use ribir_painter::{DevicePoint, DeviceSize}; +use ribir_painter::{DeviceOffset, DevicePoint, DeviceSize}; use std::fmt::Debug; use super::{ModifiersState, MouseButtons, PointerId, ScanCode, VirtualKeyCode}; @@ -78,7 +78,7 @@ pub enum WindowEvent { /// module. ScaleFactorChanged { scale_factor: f64, - new_inner_size: DeviceSize + new_inner_size: DeviceSize, }, } @@ -98,11 +98,7 @@ impl PartialEq for WindowEvent { input: r_input, is_synthetic: r_is_synthetic, }, - ) => { - l_device_id.eq(r_device_id.as_ref()) - && l_input == r_input - && l_is_synthetic == r_is_synthetic - } + ) => l_device_id.eq(r_device_id) && l_input == r_input && l_is_synthetic == r_is_synthetic, (Self::ModifiersChanged(l0), Self::ModifiersChanged(r0)) => l0 == r0, ( Self::CursorMoved { @@ -113,11 +109,11 @@ impl PartialEq for WindowEvent { device_id: r_device_id, position: r_position, }, - ) => l_device_id.eq(r_device_id.as_ref()) && l_position == r_position, + ) => l_device_id.eq(r_device_id) && l_position == r_position, ( Self::CursorLeft { device_id: l_device_id }, Self::CursorLeft { device_id: r_device_id }, - ) => l_device_id.eq(r_device_id.as_ref()), + ) => l_device_id.eq(r_device_id), ( Self::MouseWheel { device_id: l_device_id, @@ -129,7 +125,7 @@ impl PartialEq for WindowEvent { delta: r_delta, phase: r_phase, }, - ) => l_device_id.eq(r_device_id.as_ref()) && l_delta == r_delta && l_phase == r_phase, + ) => l_device_id.eq(r_device_id) && l_delta == r_delta && l_phase == r_phase, ( Self::MouseInput { device_id: l_device_id, @@ -141,7 +137,7 @@ impl PartialEq for WindowEvent { state: r_state, button: r_button, }, - ) => l_device_id.eq(r_device_id.as_ref()) && l_state == r_state && l_button == r_button, + ) => l_device_id.eq(r_device_id) && l_state == r_state && l_button == r_button, ( Self::ScaleFactorChanged { scale_factor: l_scale_factor, @@ -186,7 +182,7 @@ pub enum MouseScrollDelta { /// For a 'natural scrolling' touch pad (that acts like a touch screen) /// this means moving your fingers right and down should give positive values, /// and move the content right and down (to reveal more things left and up). - PixelDelta(DevicePoint), + PixelDelta(DeviceOffset), } /// Describes touch-screen input state. diff --git a/core/src/events/keyboard.rs b/core/src/events/keyboard.rs index 7894fa2ab..8512ba6a9 100644 --- a/core/src/events/keyboard.rs +++ b/core/src/events/keyboard.rs @@ -320,7 +320,7 @@ mod tests { fn new_key_event(key: VirtualKeyCode, state: ElementState) -> WindowEvent /*<'static>*/ { #[allow(deprecated)] WindowEvent::KeyboardInput { - device_id: Box::new(DummyPointerId::dummy()), + device_id: MockPointerId::zero(), input: KeyboardInput { scancode: 0, virtual_keycode: Some(key), diff --git a/core/src/events/pointers.rs b/core/src/events/pointers.rs index 3bfe87f54..147cf09ae 100644 --- a/core/src/events/pointers.rs +++ b/core/src/events/pointers.rs @@ -15,8 +15,8 @@ mod pointer_event; const MULTI_TAP_DURATION: Duration = Duration::from_millis(250); pub trait PointerId: Debug { - fn as_any(&self) -> &dyn Any; - fn eq(&self, other: &dyn PointerId) -> bool; + fn into_any(self: Box) -> Box; + fn eq(&self, other: &Box) -> bool; fn box_clone(&self) -> Box; // fn debug(&self) -> String; } @@ -25,18 +25,25 @@ impl Clone for Box { fn clone(&self) -> Self { self.box_clone() } } -#[derive(Debug, Copy, Clone)] -pub struct DummyPointerId(usize); +#[derive(Default, Debug, Copy, Clone)] +pub struct MockPointerId(usize); -impl DummyPointerId { - pub fn dummy() -> DummyPointerId { DummyPointerId(0) } +impl MockPointerId { + pub fn new(value: usize) -> Box { Box::new(MockPointerId(value)) } + pub fn zero() -> Box { MockPointerId::new(0) } } -impl PointerId for DummyPointerId { - fn as_any(&self) -> &dyn Any { &self.0 } - - fn eq(&self, other: &dyn PointerId) -> bool { - self.0 == other.as_any().downcast_ref::().unwrap().0 +impl PointerId for MockPointerId { + fn into_any(self: Box) -> Box { self } + + fn eq(&self, other: &Box) -> bool { + self.0 + == other + .box_clone() + .into_any() + .downcast::() + .unwrap() + .0 } fn box_clone(&self) -> Box { Box::new(*self) } @@ -322,7 +329,7 @@ fn x_times_tap_map_filter( move |e: &mut PointerEvent| { let now = Instant::now(); match &mut type_info { - Some(info) if info.pointer_id.eq(&*e.id) => { + Some(info) if info.pointer_id.eq(&e.id) => { if info.stamps.len() + 1 == x { if now.duration_since(info.stamps[0]) <= dur { // emit x-tap event and reset the tap info @@ -394,18 +401,18 @@ mod tests { let (mut wnd, count) = env(2); let mut local_pool = LocalPool::new(); - let device_id = Box::new(DummyPointerId::dummy()); + observable::interval(Duration::from_millis(10), local_pool.spawner()) .take(8) .subscribe(move |i| { wnd.processes_native_event(WindowEvent::MouseInput { - device_id, + device_id: MockPointerId::zero(), state: if i % 2 == 0 { ElementState::Pressed } else { ElementState::Released }, - button: MouseButtons::Left, + button: MouseButtons::PRIMARY, }); }); @@ -418,13 +425,13 @@ mod tests { .take(8) .subscribe(move |i| { wnd.processes_native_event(WindowEvent::MouseInput { - device_id, + device_id: MockPointerId::zero(), state: if i % 2 == 0 { ElementState::Pressed } else { ElementState::Released }, - button: MouseButtons::Left, + button: MouseButtons::PRIMARY, }); }); @@ -437,18 +444,18 @@ mod tests { let (mut wnd, count) = env(3); let mut local_pool = LocalPool::new(); - let device_id = DummyPointerId::dummy(); + // let device_id = MockPointerId::zero(); observable::interval(Duration::from_millis(10), local_pool.spawner()) .take(12) .subscribe(move |i| { wnd.processes_native_event(WindowEvent::MouseInput { - device_id, + device_id: MockPointerId::zero(), state: if i % 2 == 0 { ElementState::Pressed } else { ElementState::Released }, - button: MouseButtons::Left, + button: MouseButtons::PRIMARY, }); }); diff --git a/core/src/events/wheel.rs b/core/src/events/wheel.rs index 5eba1a945..0126cfc59 100644 --- a/core/src/events/wheel.rs +++ b/core/src/events/wheel.rs @@ -74,10 +74,10 @@ mod tests { let mut wnd = Window::default_mock(widget, Some(Size::new(100., 100.))); wnd.draw_frame(); - let device_id = Box::new(DummyPointerId::dummy()); + let device_id = MockPointerId::zero(); wnd.processes_native_event(WindowEvent::MouseWheel { device_id, - delta: MouseScrollDelta::PixelDelta((1.0, 1.0).into()), + delta: MouseScrollDelta::PixelDelta(DeviceOffset::new(1, 1).into()), phase: TouchPhase::Started, }); diff --git a/core/src/window.rs b/core/src/window.rs index 9504b16b6..88494508c 100644 --- a/core/src/window.rs +++ b/core/src/window.rs @@ -4,9 +4,10 @@ use crate::{ context::AppContext, events::dispatcher::Dispatcher, prelude::*, widget_tree::WidgetTree, }; -pub trait WindowId { - fn as_any(&self) -> &dyn Any; - fn eq(&self, other: &dyn WindowId) -> bool; +pub trait WindowId: std::fmt::Debug { + // fn as_any(&self) -> &dyn Any; + fn into_any(self: Box) -> Box; + fn equals(&self, other: &Box) -> bool; fn box_clone(&self) -> Box; } @@ -260,7 +261,7 @@ impl Window { self.context.layout_ready(); } - pub(crate) fn need_draw(&self) -> bool { + pub fn need_draw(&self) -> bool { self.widget_tree.is_dirty() || self.context.has_actived_animate() } @@ -298,7 +299,7 @@ impl Window { /// Emits a `WindowEvent::RedrawRequested` event in the associated event loop /// after all OS events have been processed by the event loop. #[inline] - pub(crate) fn request_redraw(&self) { self.raw_window.request_redraw(); } + pub fn request_redraw(&self) { self.raw_window.request_redraw(); } pub fn capture_image(&mut self, image_data_callback: F) -> Result<(), Box> where @@ -395,10 +396,16 @@ impl MockWindowId { } impl WindowId for MockWindowId { - fn as_any(&self) -> &dyn Any { &self.0 } - - fn eq(&self, other: &dyn WindowId) -> bool { - self.0 == other.as_any().downcast_ref::().unwrap().0 + fn into_any(self: Box) -> Box { self } + // fn as_boxed_any(self: Box) -> Box { self } + fn equals(&self, other: &Box) -> bool { + self.0 + == other + .box_clone() + .into_any() + .downcast_ref::() + .unwrap() + .0 } fn box_clone(&self) -> Box { Box::new(*self) } diff --git a/geometry/src/lib.rs b/geometry/src/lib.rs index 7b60c0114..00a329383 100644 --- a/geometry/src/lib.rs +++ b/geometry/src/lib.rs @@ -24,5 +24,23 @@ pub type DevicePoint = euclid::Point2D; pub type DeviceSize = euclid::Size2D; pub type DeviceVector = euclid::Vector2D; +pub type DeviceOffset = euclid::Point2D; +pub type ScaleOffsetToPhysic = euclid::Scale; +pub type ScaleOffsetToLogic = euclid::Scale; + pub const INFINITY_SIZE: Size = Size::new(f32::INFINITY, f32::INFINITY); pub const ZERO_SIZE: Size = Size::new(0., 0.); + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test() { + let logic_rect = Rect::new(Point::new(1., 1.), Size::new(3., 4.)); + let physic_rect = ScaleToPhysic::new(1).transform_rect(&logic_rect.cast()); + assert_eq!(logic_rect.origin.x as u32, physic_rect.origin.x); + assert_eq!(logic_rect.origin.y as u32, physic_rect.origin.y); + assert_eq!(logic_rect.width() as u32, physic_rect.width()); + assert_eq!(logic_rect.height() as u32, physic_rect.height()); + } +} diff --git a/macros/Cargo.toml b/macros/Cargo.toml index 840c587f4..84f422ac3 100644 --- a/macros/Cargo.toml +++ b/macros/Cargo.toml @@ -22,6 +22,7 @@ smallvec = "1.8.0" [dev-dependencies] ribir = {path = "../ribir"} +ribir_core = {path = "../core"} trybuild = "1.0.77" winit = "0.28.1" diff --git a/macros/tests/animations_syntax_test.rs b/macros/tests/animations_syntax_test.rs index c15fe92b3..cef206603 100644 --- a/macros/tests/animations_syntax_test.rs +++ b/macros/tests/animations_syntax_test.rs @@ -1,17 +1,17 @@ use ribir::prelude::*; use std::{cell::Cell, rc::Rc, time::Duration}; -use winit::event::{DeviceId, MouseScrollDelta, TouchPhase, WindowEvent}; +// use winit::event::{DeviceId, MouseScrollDelta, TouchPhase, WindowEvent}; fn wheel_widget(w: Widget) -> Window { let mut wnd = Window::default_mock(w, None); wnd.draw_frame(); - let device_id = unsafe { DeviceId::dummy() }; + let device_id = MockPointerId::zero() ; wnd.processes_native_event(WindowEvent::MouseWheel { device_id, delta: MouseScrollDelta::LineDelta(1.0, 1.0), phase: TouchPhase::Started, - modifiers: ModifiersState::default(), + // modifiers: ModifiersState::default(), }); wnd } diff --git a/macros/tests/code_gen_test.rs b/macros/tests/code_gen_test.rs index bd4895e0b..23fb6bc1a 100644 --- a/macros/tests/code_gen_test.rs +++ b/macros/tests/code_gen_test.rs @@ -1,6 +1,7 @@ -use ribir::{core::test::*, prelude::*}; +use ribir::prelude::*; +use ribir_core::test::*; use std::{cell::Cell, rc::Rc}; -use winit::event::{DeviceId, ElementState, MouseButton, WindowEvent}; +// use winit::event::{DeviceId, ElementState, MouseButton, WindowEvent}; #[test] fn declare_smoke() { @@ -269,26 +270,20 @@ fn builtin_bind_to_self() { assert_eq!(icon_track.get(), CursorIcon::Help); } -fn tap_at(wnd: &mut Window, pos: (i32, i32)) { - let device_id = unsafe { DeviceId::dummy() }; - let modifiers = ModifiersState::default(); - +fn tap_at(wnd: &mut Window, pos: (u32, u32)) { wnd.processes_native_event(WindowEvent::CursorMoved { - device_id, - position: pos.into(), - modifiers, + device_id: MockPointerId::zero(), + position: DevicePoint::new(pos.0, pos.1), }); wnd.processes_native_event(WindowEvent::MouseInput { - device_id, + device_id: MockPointerId::zero(), state: ElementState::Pressed, - button: MouseButton::Left, - modifiers, + button: MouseButtons::PRIMARY, }); wnd.processes_native_event(WindowEvent::MouseInput { - device_id, + device_id: MockPointerId::zero(), state: ElementState::Released, - button: MouseButton::Left, - modifiers, + button: MouseButtons::PRIMARY, }); } diff --git a/macros/tests/path_child_test.rs b/macros/tests/path_child_test.rs index 527d15cff..abb1a2241 100644 --- a/macros/tests/path_child_test.rs +++ b/macros/tests/path_child_test.rs @@ -1,4 +1,4 @@ -use ribir::core::test::*; +use ribir_core::test::*; use ribir::prelude::*; enum AB { A, diff --git a/ribir/Cargo.toml b/ribir/Cargo.toml index 729d31c24..af0574303 100644 --- a/ribir/Cargo.toml +++ b/ribir/Cargo.toml @@ -7,12 +7,15 @@ version = "0.1.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +ribir_app = {path = "../app", version = "*"} ribir_gpu = {path = "../gpu", version = "*"} ribir_core = {path = "../core"} ribir_widgets = {path = "../widgets"} +ribir_winit = {path = "../winit"} lyon_algorithms = "1.0.1" lyon_path = "1.0.1" + [dev-dependencies] env_logger = "0.7.1" diff --git a/ribir/examples/todo_mvp.rs b/ribir/examples/todo_mvp.rs index 33bd87a99..f845c47eb 100644 --- a/ribir/examples/todo_mvp.rs +++ b/ribir/examples/todo_mvp.rs @@ -1,4 +1,7 @@ -use ribir::prelude::{svgs, *}; +use ribir::{ + prelude::{svgs, *}, + WindowBuilder, WinitApplication, +}; use std::time::Duration; #[derive(Debug, Clone, PartialEq)] @@ -180,8 +183,8 @@ fn main() { ], }; - let app = Application::new(material::purple::light()); - let wnd = Window::builder(todo.into_widget()) + let app = WinitApplication::new(material::purple::light()); + let wnd = WindowBuilder::new(todo.into_widget()) .with_inner_size(Size::new(400., 640.)) .with_title("todo") .build(&app); diff --git a/ribir/src/lib.rs b/ribir/src/lib.rs index ecebad5e0..501aeac32 100644 --- a/ribir/src/lib.rs +++ b/ribir/src/lib.rs @@ -1,4 +1,7 @@ -pub use ribir_core as core; +// pub use ribir_core as core; +pub use ribir_app::prelude::*; +pub use ribir_winit::prelude::*; + pub use ribir_widgets as widgets; pub mod prelude { pub use ribir_core::prelude::*; @@ -8,14 +11,18 @@ pub mod prelude { #[cfg(feature = "wgpu_gl")] pub fn run(root: super::Widget) { - let app = super::Application::new(super::material::purple::light()); - let wnd = Window::builder(root).build(&app); + use ribir_winit::prelude::{WindowBuilder, WinitApplication}; + + let app = WinitApplication::new(super::material::purple::light()); + let wnd = WindowBuilder::new(root).build(&app); run_with_window(app, wnd); } #[cfg(feature = "wgpu_gl")] - pub fn run_with_window(mut app: super::Application, wnd: Window) { + pub fn run_with_window(mut app: ribir_winit::prelude::WinitApplication, wnd: Window) { + println!("WindowId: {:?}", wnd.raw_window.id()); let wnd_id = app.add_window(wnd); + println!("WindowId: {wnd_id:?}"); app.exec(wnd_id); } } diff --git a/winit/Cargo.toml b/winit/Cargo.toml index c22a7047f..1a0b6c9c9 100644 --- a/winit/Cargo.toml +++ b/winit/Cargo.toml @@ -10,4 +10,10 @@ log = "0.4.8" ribir_app = { path = "../app" } ribir_core = { path = "../core" } ribir_geometry = { path = "../geometry" } +ribir_gpu = {path = "../gpu"} +ribir_text = {path = "../text"} winit = "0.28.1" + +[features] +default = ["wgpu_gl"] +wgpu_gl = ["ribir_gpu/wgpu_gl"] diff --git a/winit/src/application.rs b/winit/src/application.rs index 4928bf8a9..baafa8906 100644 --- a/winit/src/application.rs +++ b/winit/src/application.rs @@ -1,5 +1,4 @@ use ribir_core::prelude::*; -use ribir_app::shell_window::ShellWindow; use std::{collections::HashMap, rc::Rc}; pub use winit::window::WindowId; @@ -9,15 +8,18 @@ use winit::{ platform::run_return::EventLoopExtRunReturn, }; -pub struct Application { +use crate::{from_event::WrappedWindowEvent, prelude::WrappedWindowId}; +use ribir_core::window::WindowId as RibirWindowId; + +pub struct WinitApplication { windows: HashMap, ctx: AppContext, event_loop: EventLoop<()>, } -impl Application { +impl WinitApplication { #[inline] - pub fn new(theme: Theme) -> Application { + pub fn new(theme: Theme) -> Self { // todo: theme can provide fonts to load. let ctx = AppContext { app_theme: Rc::new(theme), @@ -27,7 +29,7 @@ impl Application { } #[inline] - pub fn with_theme(mut self, theme: Theme) -> Application { + pub fn with_theme(mut self, theme: Theme) -> Self { self.ctx.app_theme = Rc::new(theme); self } @@ -37,8 +39,8 @@ impl Application { pub fn event_loop(&self) -> &EventLoop<()> { &self.event_loop } - pub fn exec(mut self, wnd_id: WindowId) { - if let Some(wnd) = self.windows.get_mut(&wnd_id) { + pub fn exec(mut self, wnd_id: Box) { + if let Some(wnd) = self.windows.get_mut(&WrappedWindowId::from(wnd_id).into()) { wnd.draw_frame(); } else { panic!("application at least have one window"); @@ -57,7 +59,7 @@ impl Application { *control = ControlFlow::Exit; } } else if let Some(wnd) = windows.get_mut(&window_id) { - wnd.processes_native_event(event); + wnd.processes_native_event(WrappedWindowEvent::from(event).into()); } } Event::MainEventsCleared => windows.iter_mut().for_each(|(_, wnd)| { @@ -80,15 +82,17 @@ impl Application { }); } - pub fn add_window(&mut self, wnd: Window) -> WindowId { + pub fn add_window(&mut self, wnd: Window) -> Box { let id = wnd.raw_window.id(); - self.windows.insert(id, wnd); + self + .windows + .insert(WrappedWindowId::from(id.clone()).into(), wnd); id } } -impl Default for Application { +impl Default for WinitApplication { fn default() -> Self { Self { windows: Default::default(), @@ -97,3 +101,5 @@ impl Default for Application { } } } + +// impl Application for WinitApplication {} diff --git a/winit/src/from_device_id.rs b/winit/src/from_device_id.rs index 8f179263e..1824ada14 100644 --- a/winit/src/from_device_id.rs +++ b/winit/src/from_device_id.rs @@ -7,8 +7,10 @@ use winit::event::DeviceId as WinitDeviceId; pub struct WrappedPointerId(WinitDeviceId); impl RibirPointerId for WrappedPointerId { - fn as_any(&self) -> &dyn Any { self } - fn eq(&self, other: &dyn RibirPointerId) -> bool { self.0 == WrappedPointerId::from(other).0 } + fn into_any(self: Box) -> Box { self } + fn eq(&self, other: &Box) -> bool { + self.0 == WrappedPointerId::from(other).0 + } fn box_clone(&self) -> Box { Box::new(self.clone()) } } @@ -22,35 +24,31 @@ impl From for WinitDeviceId { impl From> for WrappedPointerId { fn from(value: Box) -> Self { - let x = value - .as_ref() - .as_any() - .downcast_ref::() - .map(|v| v.to_owned()) - .unwrap(); - x.into() + *value + .box_clone() + .into_any() + .downcast::() + .unwrap() } } impl From<&Box> for WrappedPointerId { fn from(value: &Box) -> Self { - let x = value - .as_ref() - .as_any() - .downcast_ref::() - .map(|v| v.to_owned()) - .unwrap(); - x.into() + *(value + .box_clone() + .into_any() + .downcast::() + .unwrap()) } } -impl From<&dyn RibirPointerId> for WrappedPointerId { - fn from(value: &dyn RibirPointerId) -> Self { - let x = value - .as_any() - .downcast_ref::() - .map(|v| v.to_owned()) - .unwrap(); - x.into() - } -} +// impl From<&dyn RibirPointerId> for WrappedPointerId { +// fn from(value: &dyn RibirPointerId) -> Self { +// let x = value +// .as_any() +// .downcast_ref::() +// .map(|v| v.to_owned()) +// .unwrap(); +// x.into() +// } +// } diff --git a/winit/src/from_event.rs b/winit/src/from_event.rs index 9c8600ef3..1c155b655 100644 --- a/winit/src/from_event.rs +++ b/winit/src/from_event.rs @@ -1,4 +1,3 @@ - use crate::{ from_device_id::WrappedPointerId, from_element_state::WrappedElementState, @@ -122,7 +121,7 @@ impl<'a> From for WrappedWindowEvent<'a> { button: WrappedMouseButton::from(button).into(), modifiers: WinitModifiersState::default(), }, - RibirWindowEvent::ScaleFactorChanged { scale_factor:_, new_inner_size:_ } => { + RibirWindowEvent::ScaleFactorChanged { scale_factor: _, new_inner_size: _ } => { // WinitWindowEvent::ScaleFactorChanged { // scale_factor, // new_inner_size: WrappedPhysicalSize::::from(new_inner_size).into(), diff --git a/winit/src/from_keyboard_input.rs b/winit/src/from_keyboard_input.rs index e6a5fc8f4..ad7cb7546 100644 --- a/winit/src/from_keyboard_input.rs +++ b/winit/src/from_keyboard_input.rs @@ -5,6 +5,7 @@ use winit::{ use crate::prelude::{WrappedElementState, WrappedVirtualKeyCode}; +#[derive(Clone)] pub struct WrappedKeyboardInput(WinitKeyboardInput); impl From for WrappedKeyboardInput { @@ -39,7 +40,6 @@ impl From for WrappedKeyboardInput { .map(|v| WrappedVirtualKeyCode::from(v).into()), modifiers: WinitModifiersState::default(), }) - .into() } } @@ -61,7 +61,7 @@ mod tests { modifiers: WinitModifiersState::default(), }); - let ribir: RibirKeyboardInput = w.into(); + let ribir: RibirKeyboardInput = w.clone().into(); let winit: RibirKeyboardInput = w.into(); assert_eq!(ribir.scancode, 64); assert_eq!(winit.scancode, 64); diff --git a/winit/src/from_mouse_scroll_delta.rs b/winit/src/from_mouse_scroll_delta.rs index 51c9ffe86..b164ea139 100644 --- a/winit/src/from_mouse_scroll_delta.rs +++ b/winit/src/from_mouse_scroll_delta.rs @@ -33,7 +33,7 @@ impl From for WrappedMouseScrollDelta { WinitMouseScrollDelta::LineDelta(right, down) } RibirMouseScrollDelta::PixelDelta(pos) => { - WinitMouseScrollDelta::PixelDelta(WrappedPhysicalPosition::from(pos).into()) + WinitMouseScrollDelta::PixelDelta(WrappedPhysicalPosition::from(pos.cast()).into()) } }; es.into() diff --git a/winit/src/from_size.rs b/winit/src/from_size.rs index f1e19366b..1006982b5 100644 --- a/winit/src/from_size.rs +++ b/winit/src/from_size.rs @@ -1,6 +1,7 @@ use ribir_geometry::{ DevicePoint as RibirPhysicalPosition, DeviceSize as RibirPhysicalSize, - Point as RibirLogicalPosition, Size as RibirLogicalSize, + Point as RibirLogicalPosition, Size as RibirLogicalSize, + DeviceOffset as RibirPhysicalOffset }; use std::fmt::Debug; @@ -87,6 +88,12 @@ impl From> for RibirPhysicalPosition { } } +impl From> for RibirPhysicalOffset { + fn from(value: WrappedPhysicalPosition) -> Self { + RibirPhysicalOffset::new(value.0.x.cast(), value.0.y.cast()) + } +} + impl From for WrappedPhysicalPosition { fn from(value: RibirPhysicalPosition) -> Self { WinitPhysicalPosition::new( @@ -97,6 +104,7 @@ impl From for WrappedPhysicalPosition { } } + pub struct WrappedLogicalPosition(WinitLogicalPosition); impl From> for WrappedLogicalPosition { diff --git a/winit/src/from_window.rs b/winit/src/from_window.rs index fd176c3d7..c3d5c5089 100644 --- a/winit/src/from_window.rs +++ b/winit/src/from_window.rs @@ -2,7 +2,7 @@ use std::any::Any; use ribir_core::{ prelude::{CursorIcon, Point, Size}, - window::{RawWindow as CoreWindow, WindowId}, + window::{RawWindow as RibirRawWindow, WindowId}, }; use winit::{dpi::Pixel, window::Window as WinitWindow}; @@ -15,7 +15,7 @@ use crate::{ // #[derive(PartialEq, Eq)] pub struct WrappedWindow(WinitWindow); -impl CoreWindow for WrappedWindow { +impl RibirRawWindow for WrappedWindow { fn inner_size(&self) -> Size { WrappedLogicalSize::::from(self.0.inner_size().to_logical(self.scale_factor())).into() } diff --git a/winit/src/from_window_id.rs b/winit/src/from_window_id.rs index 48d9ad086..26d7168aa 100644 --- a/winit/src/from_window_id.rs +++ b/winit/src/from_window_id.rs @@ -7,8 +7,18 @@ use winit::window::WindowId as WinitWindowId; pub struct WrappedWindowId(WinitWindowId); impl RibirWindowId for WrappedWindowId { - fn as_any(&self) -> &dyn Any { self } - fn eq(&self, other: &dyn RibirWindowId) -> bool { self.0 == WrappedWindowId::from(other).0 } + // fn as_any(&self) -> &dyn Any { self } + fn into_any(self: Box) -> Box { self } + + fn equals(&self, other: &Box) -> bool { + self.0 + == other + .box_clone() + .into_any() + .downcast::() + .unwrap() + .0 + } fn box_clone(&self) -> Box { Box::new(self.clone()) } } @@ -22,35 +32,43 @@ impl From for WinitWindowId { impl From> for WrappedWindowId { fn from(value: Box) -> Self { - let x = value - .as_ref() - .as_any() - .downcast_ref::() - .map(|v| v.to_owned()) - .unwrap(); - x.into() + *value.into_any().downcast::().unwrap() } } -impl From<&Box> for WrappedWindowId { - fn from(value: &Box) -> Self { - let x = value - .as_ref() - .as_any() - .downcast_ref::() - .map(|v| v.to_owned()) - .unwrap(); - x.into() - } +impl From for Box { + fn from(value: WrappedWindowId) -> Self { Box::new(value) } } -impl From<&dyn RibirWindowId> for WrappedWindowId { - fn from(value: &dyn RibirWindowId) -> Self { - let x = value - .as_any() - .downcast_ref::() - .map(|v| v.to_owned()) - .unwrap(); - x.into() +// impl From<&Box> for WrappedWindowId { +// fn from(value: &Box) -> Self { +// // let x = *value; +// value.as_boxed_any().downcast_ref::().unwrap() +// } +// } + +// impl From> for WrappedWindowId { +// fn from(value: Box) -> Self { +// value +// .into_any() +// .downcast::() +// .unwrap() +// } +// } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_ribir_window_id_into_wrapped() { + let d1: WinitWindowId = 3_u64.into(); + let d2: WinitWindowId = 3_u64.into(); + assert_eq!(d1, d2); + let winit_window_id = unsafe { WinitWindowId::dummy() }; + let wrapped = WrappedWindowId::from(winit_window_id); + let boxed_ribir_window_id: Box = Box::new(wrapped.clone()); + let wrapped2: WrappedWindowId = boxed_ribir_window_id.into(); + assert!(wrapped2.equals(&wrapped.into())); } } diff --git a/winit/src/lib.rs b/winit/src/lib.rs index 9f7d6384c..c32e116b8 100644 --- a/winit/src/lib.rs +++ b/winit/src/lib.rs @@ -1,5 +1,6 @@ #![feature(test, decl_macro, box_into_inner)] +mod application; mod from_cursor_icon; mod from_device_id; mod from_element_state; @@ -13,8 +14,11 @@ mod from_touch_phase; mod from_virtual_key_code; mod from_window; mod from_window_id; +mod window_builder; pub mod prelude { + #[doc(no_inline)] + pub use crate::application::*; #[doc(no_inline)] pub use crate::from_cursor_icon::*; #[doc(no_inline)] @@ -41,4 +45,6 @@ pub mod prelude { pub use crate::from_window::*; #[doc(no_inline)] pub use crate::from_window_id::*; + #[doc(no_inline)] + pub use crate::window_builder::*; } diff --git a/winit/src/window_builder.rs b/winit/src/window_builder.rs new file mode 100644 index 000000000..149c63e55 --- /dev/null +++ b/winit/src/window_builder.rs @@ -0,0 +1,117 @@ +use ribir_core::{prelude::AppContext, widget::Widget, window::Window as RibirWindow}; +use ribir_geometry::{DeviceSize, Point, Size}; + +use crate::{ + application::WinitApplication, + prelude::{WrappedPhysicalSize, WrappedWindow}, +}; + +pub struct WindowBuilder { + inner_builder: winit::window::WindowBuilder, + root: Widget, +} + +impl WindowBuilder { + #[inline] + pub fn new(root: Widget) -> WindowBuilder { + WindowBuilder { + root, + inner_builder: winit::window::WindowBuilder::default(), + } + } + + #[inline] + pub fn build(self, app: &WinitApplication) -> RibirWindow { + let native_wnd = self.inner_builder.build(app.event_loop()).unwrap(); + let size: DeviceSize = WrappedPhysicalSize::::from(native_wnd.inner_size()).into(); + let ctx = app.context().clone(); + let p_backend = AppContext::wait_future(ribir_gpu::wgpu_backend_with_wnd( + &native_wnd, + size, + None, + None, + ctx.shaper.clone(), + )); + RibirWindow::new(WrappedWindow::from(native_wnd), p_backend, self.root, ctx) + } + + /// Requests the window to be of specific dimensions. + #[inline] + pub fn with_inner_size(mut self, size: Size) -> Self { + let size = winit::dpi::LogicalSize::new(size.width, size.height); + self.inner_builder = self.inner_builder.with_inner_size(size); + self + } + + /// Sets a minimum dimension size for the window. + #[inline] + pub fn with_min_inner_size(mut self, min_size: Size) -> Self { + let size = winit::dpi::LogicalSize::new(min_size.width, min_size.height); + self.inner_builder = self.inner_builder.with_min_inner_size(size); + self + } + + /// Sets a maximum dimension size for the window. + #[inline] + pub fn with_max_inner_size(mut self, max_size: Size) -> Self { + let size = winit::dpi::LogicalSize::new(max_size.width, max_size.height); + self.inner_builder = self.inner_builder.with_max_inner_size(size); + self + } + + /// Sets a desired initial position for the window. + #[inline] + pub fn with_position(mut self, position: Point) -> Self { + let position = winit::dpi::LogicalPosition::new(position.x, position.y); + self.inner_builder = self.inner_builder.with_position(position); + self + } + + /// Sets whether the window is resizable or not. + #[inline] + pub fn with_resizable(mut self, resizable: bool) -> Self { + self.inner_builder = self.inner_builder.with_resizable(resizable); + self + } + + /// Requests a specific title for the window. + #[inline] + pub fn with_title>(mut self, title: T) -> Self { + self.inner_builder = self.inner_builder.with_title(title); + self + } + + /// Requests maximized mode. + #[inline] + pub fn with_maximized(mut self, maximized: bool) -> Self { + self.inner_builder = self.inner_builder.with_maximized(maximized); + self + } + + /// Sets whether the window will be initially hidden or visible. + #[inline] + pub fn with_visible(mut self, visible: bool) -> Self { + self.inner_builder = self.inner_builder.with_visible(visible); + self + } + + /// Sets whether the background of the window should be transparent. + #[inline] + pub fn with_transparent(mut self, transparent: bool) -> Self { + self.inner_builder = self.inner_builder.with_transparent(transparent); + self + } + + /// Sets whether the window should have a border, a title bar, etc. + #[inline] + pub fn with_decorations(mut self, decorations: bool) -> Self { + self.inner_builder = self.inner_builder.with_decorations(decorations); + self + } + + // /// Sets the window icon. + // #[inline] + // pub fn with_window_icon(mut self, window_icon:Option) + // // -> Self { self.inner_builder = self.inner_builder. + // with_window_icon(window_icon); self } +} From c62b0cda5765e4a611bdc8b33bf0b8a0bce96118 Mon Sep 17 00:00:00 2001 From: Guenter Zoechbauer Date: Wed, 15 Mar 2023 13:13:57 +0100 Subject: [PATCH 4/9] Fix from physical to logical geometry conversion --- core/src/builtin_widgets/scrollable.rs | 2 +- core/src/events/dispatcher.rs | 11 ++++++----- core/src/events/wheel.rs | 2 +- geometry/src/lib.rs | 25 +++++++++++++++++-------- macros/tests/animations_syntax_test.rs | 2 +- macros/tests/path_child_test.rs | 2 +- winit/src/from_size.rs | 6 ++---- 7 files changed, 29 insertions(+), 21 deletions(-) diff --git a/core/src/builtin_widgets/scrollable.rs b/core/src/builtin_widgets/scrollable.rs index 7071b36e8..9b1402ee3 100644 --- a/core/src/builtin_widgets/scrollable.rs +++ b/core/src/builtin_widgets/scrollable.rs @@ -128,7 +128,7 @@ mod tests { let device_id = MockPointerId::zero(); wnd.processes_native_event(WindowEvent::MouseWheel { device_id, - delta: MouseScrollDelta::PixelDelta(DeviceOffset::new(delta_x, delta_y).into()), + delta: MouseScrollDelta::PixelDelta(DeviceOffset::new(delta_x, delta_y)), phase: TouchPhase::Started, }); diff --git a/core/src/events/dispatcher.rs b/core/src/events/dispatcher.rs index 8544a4266..f8ba83182 100644 --- a/core/src/events/dispatcher.rs +++ b/core/src/events/dispatcher.rs @@ -44,9 +44,9 @@ impl Dispatcher { match event { WindowEvent::ModifiersChanged(s) => self.info.modifiers = s, WindowEvent::CursorMoved { position, .. } => { - let logical_pos = ScaleToLogic::new(wnd_factor as f32).transform_point(position.cast()); - - self.cursor_move_to(Point::new(logical_pos.x, logical_pos.y), tree) + let logical_pos = + ScaleToLogic::new(1.0 / wnd_factor as f32).transform_point(position.cast()); + self.cursor_move_to(logical_pos, tree) } WindowEvent::CursorLeft { .. } => self.on_cursor_left(tree), WindowEvent::MouseInput { state, button, device_id, .. } => { @@ -59,7 +59,7 @@ impl Dispatcher { self.dispatch_received_char(c, tree); } WindowEvent::MouseWheel { delta, .. } => self.dispatch_wheel(delta, tree, wnd_factor), - _ => log::info!("not processed event {:?}", event), + _ => log::info!("Not processed event {:?}", event), } } @@ -184,7 +184,8 @@ impl Dispatcher { let (delta_x, delta_y) = match delta { MouseScrollDelta::LineDelta(x, y) => (x * PIXELS_PER_EM, y * PIXELS_PER_EM), MouseScrollDelta::PixelDelta(delta) => { - let logical_delta = ScaleToLogic::new(wnd_factor as f32).transform_point(delta.cast()); + let logical_delta = + ScaleToLogic::new(1.0 / wnd_factor as f32).transform_point(delta.cast()); (logical_delta.x, logical_delta.y) } }; diff --git a/core/src/events/wheel.rs b/core/src/events/wheel.rs index 0126cfc59..b95d983eb 100644 --- a/core/src/events/wheel.rs +++ b/core/src/events/wheel.rs @@ -77,7 +77,7 @@ mod tests { let device_id = MockPointerId::zero(); wnd.processes_native_event(WindowEvent::MouseWheel { device_id, - delta: MouseScrollDelta::PixelDelta(DeviceOffset::new(1, 1).into()), + delta: MouseScrollDelta::PixelDelta(DeviceOffset::new(1, 1)), phase: TouchPhase::Started, }); diff --git a/geometry/src/lib.rs b/geometry/src/lib.rs index 00a329383..90cb41b03 100644 --- a/geometry/src/lib.rs +++ b/geometry/src/lib.rs @@ -12,7 +12,7 @@ pub type Rect = euclid::Rect; pub type Point = euclid::Point2D; pub type Size = euclid::Size2D; pub type Transform = euclid::Transform2D; -pub type ScaleToPhysic = euclid::Scale; +pub type ScaleToPhysic = euclid::Scale; pub type ScaleToLogic = euclid::Scale; pub type Vector = euclid::Vector2D; @@ -35,12 +35,21 @@ pub const ZERO_SIZE: Size = Size::new(0., 0.); mod tests { use super::*; #[test] - fn test() { - let logic_rect = Rect::new(Point::new(1., 1.), Size::new(3., 4.)); - let physic_rect = ScaleToPhysic::new(1).transform_rect(&logic_rect.cast()); - assert_eq!(logic_rect.origin.x as u32, physic_rect.origin.x); - assert_eq!(logic_rect.origin.y as u32, physic_rect.origin.y); - assert_eq!(logic_rect.width() as u32, physic_rect.width()); - assert_eq!(logic_rect.height() as u32, physic_rect.height()); + fn scale_from_physics_rect_to_logic_rect_and_back() { + let physic_rect = DeviceRect::new(DevicePoint::new(1, 1), DeviceSize::new(3, 4)); + let factor = 1.3; + let logic_rect: Rect = ScaleToLogic::new(factor) + .transform_rect(&physic_rect.cast()) + .cast(); + + assert!((logic_rect.origin.x - 1.3).abs() < f32::EPSILON); + assert!((logic_rect.origin.y - 1.3).abs() < f32::EPSILON); + assert!((logic_rect.width() - 3.8999999).abs() < f32::EPSILON); + assert!((logic_rect.height() - 5.2).abs() < f32::EPSILON); + + let physic_rect2: DeviceRect = ScaleToPhysic::new(1.0 / factor) + .transform_rect(&logic_rect.cast()) + .cast(); + assert_eq!(physic_rect, physic_rect2) } } diff --git a/macros/tests/animations_syntax_test.rs b/macros/tests/animations_syntax_test.rs index cef206603..c4e9a2913 100644 --- a/macros/tests/animations_syntax_test.rs +++ b/macros/tests/animations_syntax_test.rs @@ -6,7 +6,7 @@ fn wheel_widget(w: Widget) -> Window { let mut wnd = Window::default_mock(w, None); wnd.draw_frame(); - let device_id = MockPointerId::zero() ; + let device_id = MockPointerId::zero(); wnd.processes_native_event(WindowEvent::MouseWheel { device_id, delta: MouseScrollDelta::LineDelta(1.0, 1.0), diff --git a/macros/tests/path_child_test.rs b/macros/tests/path_child_test.rs index abb1a2241..a85d81903 100644 --- a/macros/tests/path_child_test.rs +++ b/macros/tests/path_child_test.rs @@ -1,5 +1,5 @@ -use ribir_core::test::*; use ribir::prelude::*; +use ribir_core::test::*; enum AB { A, B, diff --git a/winit/src/from_size.rs b/winit/src/from_size.rs index 1006982b5..741035838 100644 --- a/winit/src/from_size.rs +++ b/winit/src/from_size.rs @@ -1,7 +1,6 @@ use ribir_geometry::{ - DevicePoint as RibirPhysicalPosition, DeviceSize as RibirPhysicalSize, - Point as RibirLogicalPosition, Size as RibirLogicalSize, - DeviceOffset as RibirPhysicalOffset + DeviceOffset as RibirPhysicalOffset, DevicePoint as RibirPhysicalPosition, + DeviceSize as RibirPhysicalSize, Point as RibirLogicalPosition, Size as RibirLogicalSize, }; use std::fmt::Debug; @@ -104,7 +103,6 @@ impl From for WrappedPhysicalPosition { } } - pub struct WrappedLogicalPosition(WinitLogicalPosition); impl From> for WrappedLogicalPosition { From 9ae6289e03b2549860eea1027f6ed7762311ace4 Mon Sep 17 00:00:00 2001 From: Guenter Zoechbauer Date: Wed, 15 Mar 2023 13:16:15 +0100 Subject: [PATCH 5/9] First attempt at Traits for WindowBuilder and Application --- app/src/application.rs | 19 ++++++++++++++++- app/src/window_builder.rs | 41 +++++++++++++++++++++++++++++++++++++ winit/src/application.rs | 16 ++++++++------- winit/src/window_builder.rs | 28 +++++++++++++------------ 4 files changed, 83 insertions(+), 21 deletions(-) create mode 100644 app/src/window_builder.rs diff --git a/app/src/application.rs b/app/src/application.rs index 0f8c8ed52..d3944f1a9 100644 --- a/app/src/application.rs +++ b/app/src/application.rs @@ -1 +1,18 @@ -pub trait Application {} +use ribir_core::{ + prelude::{AppContext, Theme}, + window::{Window, WindowId}, +}; + +use crate::event_loop::EventLoop; + +pub trait Application { + fn with_theme(self, theme: Theme) -> Self; + + fn context(&self) -> &AppContext; + + fn event_loop(&self) -> &EventLoop<()>; + + fn exec(self, wnd_id: Box); + + fn add_window(&mut self, wnd: Window) -> Box; +} diff --git a/app/src/window_builder.rs b/app/src/window_builder.rs new file mode 100644 index 000000000..19419d7b5 --- /dev/null +++ b/app/src/window_builder.rs @@ -0,0 +1,41 @@ +use ribir_app::prelude::Application; +use ribir_core::{prelude::AppContext, widget::Widget, window::Window as RibirWindow}; +use ribir_geometry::{DeviceSize, Point, Size}; + +pub trait WindowBuilder { + fn build(self, app: dyn Application) -> RibirWindow; + + /// Requests the window to be of specific dimensions. + fn with_inner_size(self, size: Size) -> Self; + + /// Sets a minimum dimension size for the window. + fn with_min_inner_size( self, min_size: Size) -> Self; + + /// Sets a maximum dimension size for the window. + fn with_max_inner_size( self, max_size: Size) -> Self; + + /// Sets a desired initial position for the window. + fn with_position(self, position: Point) -> Self; + + /// Sets whether the window is resizable or not. + fn with_resizable( self, resizable: bool) -> Self; + + /// Requests a specific title for the window. + fn with_title>( self, title: T) -> Self; + + /// Requests maximized mode. + fn with_maximized( self, maximized: bool) -> Self; + + /// Sets whether the window will be initially hidden or visible. + fn with_visible( self, visible: bool) -> Self; + + /// Sets whether the background of the window should be transparent. + fn with_transparent( self, transparent: bool) -> Self; + + /// Sets whether the window should have a border, a title bar, etc. + + fn with_decorations( self, decorations: bool) -> Self; + + /// Sets the window icon. + // fn with_window_icon( self, window_icon: WindowIcon>) -> Self; +} diff --git a/winit/src/application.rs b/winit/src/application.rs index baafa8906..2e996dc8c 100644 --- a/winit/src/application.rs +++ b/winit/src/application.rs @@ -1,3 +1,4 @@ +use ribir_app::prelude::Application; use ribir_core::prelude::*; use std::{collections::HashMap, rc::Rc}; @@ -19,7 +20,7 @@ pub struct WinitApplication { impl WinitApplication { #[inline] - pub fn new(theme: Theme) -> Self { + fn new(theme: Theme) -> Self { // todo: theme can provide fonts to load. let ctx = AppContext { app_theme: Rc::new(theme), @@ -27,19 +28,20 @@ impl WinitApplication { }; Self { ctx, ..Default::default() } } - +} +impl Application for WinitApplication { #[inline] - pub fn with_theme(mut self, theme: Theme) -> Self { + fn with_theme(mut self, theme: Theme) -> Self { self.ctx.app_theme = Rc::new(theme); self } #[inline] - pub fn context(&self) -> &AppContext { &self.ctx } + fn context(&self) -> &AppContext { &self.ctx } - pub fn event_loop(&self) -> &EventLoop<()> { &self.event_loop } + fn event_loop(&self) -> &EventLoop<()> { &self.event_loop } - pub fn exec(mut self, wnd_id: Box) { + fn exec(mut self, wnd_id: Box) { if let Some(wnd) = self.windows.get_mut(&WrappedWindowId::from(wnd_id).into()) { wnd.draw_frame(); } else { @@ -82,7 +84,7 @@ impl WinitApplication { }); } - pub fn add_window(&mut self, wnd: Window) -> Box { + fn add_window(&mut self, wnd: Window) -> Box { let id = wnd.raw_window.id(); self .windows diff --git a/winit/src/window_builder.rs b/winit/src/window_builder.rs index 149c63e55..3ff3b2054 100644 --- a/winit/src/window_builder.rs +++ b/winit/src/window_builder.rs @@ -6,12 +6,12 @@ use crate::{ prelude::{WrappedPhysicalSize, WrappedWindow}, }; -pub struct WindowBuilder { +pub struct WinitWindowBuilder { inner_builder: winit::window::WindowBuilder, root: Widget, } -impl WindowBuilder { +impl WinitWindowBuilder { #[inline] pub fn new(root: Widget) -> WindowBuilder { WindowBuilder { @@ -19,9 +19,11 @@ impl WindowBuilder { inner_builder: winit::window::WindowBuilder::default(), } } +} +impl WindowBuilder for WinitWindowBuilder { #[inline] - pub fn build(self, app: &WinitApplication) -> RibirWindow { + fn build(self, app: &WinitApplication) -> RibirWindow { let native_wnd = self.inner_builder.build(app.event_loop()).unwrap(); let size: DeviceSize = WrappedPhysicalSize::::from(native_wnd.inner_size()).into(); let ctx = app.context().clone(); @@ -37,7 +39,7 @@ impl WindowBuilder { /// Requests the window to be of specific dimensions. #[inline] - pub fn with_inner_size(mut self, size: Size) -> Self { + fn with_inner_size(mut self, size: Size) -> Self { let size = winit::dpi::LogicalSize::new(size.width, size.height); self.inner_builder = self.inner_builder.with_inner_size(size); self @@ -45,7 +47,7 @@ impl WindowBuilder { /// Sets a minimum dimension size for the window. #[inline] - pub fn with_min_inner_size(mut self, min_size: Size) -> Self { + fn with_min_inner_size(mut self, min_size: Size) -> Self { let size = winit::dpi::LogicalSize::new(min_size.width, min_size.height); self.inner_builder = self.inner_builder.with_min_inner_size(size); self @@ -53,7 +55,7 @@ impl WindowBuilder { /// Sets a maximum dimension size for the window. #[inline] - pub fn with_max_inner_size(mut self, max_size: Size) -> Self { + fn with_max_inner_size(mut self, max_size: Size) -> Self { let size = winit::dpi::LogicalSize::new(max_size.width, max_size.height); self.inner_builder = self.inner_builder.with_max_inner_size(size); self @@ -61,7 +63,7 @@ impl WindowBuilder { /// Sets a desired initial position for the window. #[inline] - pub fn with_position(mut self, position: Point) -> Self { + fn with_position(mut self, position: Point) -> Self { let position = winit::dpi::LogicalPosition::new(position.x, position.y); self.inner_builder = self.inner_builder.with_position(position); self @@ -69,42 +71,42 @@ impl WindowBuilder { /// Sets whether the window is resizable or not. #[inline] - pub fn with_resizable(mut self, resizable: bool) -> Self { + fn with_resizable(mut self, resizable: bool) -> Self { self.inner_builder = self.inner_builder.with_resizable(resizable); self } /// Requests a specific title for the window. #[inline] - pub fn with_title>(mut self, title: T) -> Self { + fn with_title>(mut self, title: T) -> Self { self.inner_builder = self.inner_builder.with_title(title); self } /// Requests maximized mode. #[inline] - pub fn with_maximized(mut self, maximized: bool) -> Self { + fn with_maximized(mut self, maximized: bool) -> Self { self.inner_builder = self.inner_builder.with_maximized(maximized); self } /// Sets whether the window will be initially hidden or visible. #[inline] - pub fn with_visible(mut self, visible: bool) -> Self { + fn with_visible(mut self, visible: bool) -> Self { self.inner_builder = self.inner_builder.with_visible(visible); self } /// Sets whether the background of the window should be transparent. #[inline] - pub fn with_transparent(mut self, transparent: bool) -> Self { + fn with_transparent(mut self, transparent: bool) -> Self { self.inner_builder = self.inner_builder.with_transparent(transparent); self } /// Sets whether the window should have a border, a title bar, etc. #[inline] - pub fn with_decorations(mut self, decorations: bool) -> Self { + fn with_decorations(mut self, decorations: bool) -> Self { self.inner_builder = self.inner_builder.with_decorations(decorations); self } From 1bef68f699bde0a435cfeaeb6735538e5e6f8c04 Mon Sep 17 00:00:00 2001 From: Guenter Zoechbauer Date: Wed, 15 Mar 2023 17:50:56 +0100 Subject: [PATCH 6/9] Delete commented-out code, move MockPointerId to tests.rs and implement PartialEq for PointerId --- core/src/builtin_widgets/cursor.rs | 1 - core/src/builtin_widgets/scrollable.rs | 4 +- core/src/context/event_context.rs | 1 - core/src/events.rs | 1 - core/src/events/character.rs | 1 - core/src/events/dispatcher.rs | 12 +- core/src/events/event.rs | 10 +- core/src/events/pointers.rs | 33 +---- core/src/events/pointers/pointer_event.rs | 4 +- core/src/events/wheel.rs | 2 +- core/src/test.rs | 27 +++- core/src/window.rs | 153 +--------------------- tests/animations_syntax_test.rs | 1 + winit/src/from_device_id.rs | 2 +- 14 files changed, 47 insertions(+), 205 deletions(-) diff --git a/core/src/builtin_widgets/cursor.rs b/core/src/builtin_widgets/cursor.rs index 412d516d1..6b20b99dc 100644 --- a/core/src/builtin_widgets/cursor.rs +++ b/core/src/builtin_widgets/cursor.rs @@ -89,7 +89,6 @@ impl Default for Cursor { mod tests { use super::*; use crate::test::*; - // use winit::event::{DeviceId, WindowEvent}; #[test] fn tree_down_up() { diff --git a/core/src/builtin_widgets/scrollable.rs b/core/src/builtin_widgets/scrollable.rs index e99747d62..091b10bc2 100644 --- a/core/src/builtin_widgets/scrollable.rs +++ b/core/src/builtin_widgets/scrollable.rs @@ -107,11 +107,9 @@ impl ScrollableWidget { #[cfg(test)] mod tests { - use crate::test::{layout_position_by_path, MockBox}; + use crate::test::{layout_position_by_path, MockBox, MockPointerId}; use super::*; - // use winit::event::{DeviceId, ModifiersState, MouseScrollDelta, TouchPhase, - // WindowEvent}; fn test_assert(scrollable: Scrollable, delta_x: i32, delta_y: i32, expect_x: i32, expect_y: i32) { let w = widget! { diff --git a/core/src/context/event_context.rs b/core/src/context/event_context.rs index b78dd88ad..d2c725c1b 100644 --- a/core/src/context/event_context.rs +++ b/core/src/context/event_context.rs @@ -5,7 +5,6 @@ use crate::{ widget::{LayoutStore, TreeArena}, widget_tree::WidgetId, }; -// use winit::{event::ModifiersState, window::CursorIcon}; define_widget_context!(EventCtx, info: &'a mut DispatchInfo); diff --git a/core/src/events.rs b/core/src/events.rs index df4a2bde0..9b1951c16 100644 --- a/core/src/events.rs +++ b/core/src/events.rs @@ -10,7 +10,6 @@ pub use event::*; mod pointers; pub use pointers::*; use ribir_painter::Point; -// pub use winit::event::{ModifiersState, ScanCode, VirtualKeyCode}; mod focus; pub use focus::*; mod keyboard; diff --git a/core/src/events/character.rs b/core/src/events/character.rs index 52cbbeb2d..18ca8694b 100644 --- a/core/src/events/character.rs +++ b/core/src/events/character.rs @@ -56,7 +56,6 @@ mod tests { use crate::test::*; use std::{cell::RefCell, rc::Rc}; - // use winit::event::WindowEvent; #[test] fn smoke() { diff --git a/core/src/events/dispatcher.rs b/core/src/events/dispatcher.rs index f8ba83182..587f94f9c 100644 --- a/core/src/events/dispatcher.rs +++ b/core/src/events/dispatcher.rs @@ -1,9 +1,7 @@ use std::{cell::RefCell, rc::Rc}; -use crate::{prelude::*, widget_tree::WidgetTree}; +use crate::{prelude::*, test::MockPointerId, widget_tree::WidgetTree}; use ribir_text::PIXELS_PER_EM; -// use winit::event::{DeviceId, ElementState, MouseButton, MouseScrollDelta, -// WindowEvent}; use super::focus_mgr::FocusManager; @@ -136,13 +134,7 @@ impl Dispatcher { tree: &mut WidgetTree, ) -> Option<()> { // A mouse press/release emit during another mouse's press will ignored. - if self - .info - .mouse_button - .0 - .get_or_insert(device_id.clone()) - .eq(&device_id) - { + if self.info.mouse_button.0.get_or_insert(device_id.clone()) == &device_id { match state { ElementState::Pressed => { self.info.mouse_button.1 |= button; diff --git a/core/src/events/event.rs b/core/src/events/event.rs index 11f0d6b96..303de6b71 100644 --- a/core/src/events/event.rs +++ b/core/src/events/event.rs @@ -98,7 +98,7 @@ impl PartialEq for WindowEvent { input: r_input, is_synthetic: r_is_synthetic, }, - ) => l_device_id.eq(r_device_id) && l_input == r_input && l_is_synthetic == r_is_synthetic, + ) => l_device_id == r_device_id && l_input == r_input && l_is_synthetic == r_is_synthetic, (Self::ModifiersChanged(l0), Self::ModifiersChanged(r0)) => l0 == r0, ( Self::CursorMoved { @@ -109,11 +109,11 @@ impl PartialEq for WindowEvent { device_id: r_device_id, position: r_position, }, - ) => l_device_id.eq(r_device_id) && l_position == r_position, + ) => l_device_id == r_device_id && l_position == r_position, ( Self::CursorLeft { device_id: l_device_id }, Self::CursorLeft { device_id: r_device_id }, - ) => l_device_id.eq(r_device_id), + ) => l_device_id == r_device_id, ( Self::MouseWheel { device_id: l_device_id, @@ -125,7 +125,7 @@ impl PartialEq for WindowEvent { delta: r_delta, phase: r_phase, }, - ) => l_device_id.eq(r_device_id) && l_delta == r_delta && l_phase == r_phase, + ) => l_device_id == r_device_id && l_delta == r_delta && l_phase == r_phase, ( Self::MouseInput { device_id: l_device_id, @@ -137,7 +137,7 @@ impl PartialEq for WindowEvent { state: r_state, button: r_button, }, - ) => l_device_id.eq(r_device_id) && l_state == r_state && l_button == r_button, + ) => l_device_id == r_device_id && l_state == r_state && l_button == r_button, ( Self::ScaleFactorChanged { scale_factor: l_scale_factor, diff --git a/core/src/events/pointers.rs b/core/src/events/pointers.rs index 147cf09ae..419d8ca0e 100644 --- a/core/src/events/pointers.rs +++ b/core/src/events/pointers.rs @@ -16,37 +16,16 @@ const MULTI_TAP_DURATION: Duration = Duration::from_millis(250); pub trait PointerId: Debug { fn into_any(self: Box) -> Box; - fn eq(&self, other: &Box) -> bool; + fn equals(&self, other: &Box) -> bool; fn box_clone(&self) -> Box; - // fn debug(&self) -> String; } impl Clone for Box { fn clone(&self) -> Self { self.box_clone() } } -#[derive(Default, Debug, Copy, Clone)] -pub struct MockPointerId(usize); - -impl MockPointerId { - pub fn new(value: usize) -> Box { Box::new(MockPointerId(value)) } - pub fn zero() -> Box { MockPointerId::new(0) } -} - -impl PointerId for MockPointerId { - fn into_any(self: Box) -> Box { self } - - fn eq(&self, other: &Box) -> bool { - self.0 - == other - .box_clone() - .into_any() - .downcast::() - .unwrap() - .0 - } - - fn box_clone(&self) -> Box { Box::new(*self) } +impl PartialEq for Box { + fn eq(&self, other: &Self) -> bool { self.equals(other) } } /// The pointer is a hardware-agnostic device that can target a specific set of @@ -329,7 +308,7 @@ fn x_times_tap_map_filter( move |e: &mut PointerEvent| { let now = Instant::now(); match &mut type_info { - Some(info) if info.pointer_id.eq(&e.id) => { + Some(info) if info.pointer_id == e.id.clone() => { if info.stamps.len() + 1 == x { if now.duration_since(info.stamps[0]) <= dur { // emit x-tap event and reset the tap info @@ -374,11 +353,9 @@ impl ComposeChild for TapListener { #[cfg(test)] mod tests { use super::*; - use crate::test::MockBox; + use crate::test::{MockBox, MockPointerId}; use futures::executor::LocalPool; use std::{cell::RefCell, rc::Rc}; - // use winit::event::{DeviceId, ElementState, ModifiersState, MouseButton, - // WindowEvent}; fn env(times: usize) -> (Window, Rc>) { let size = Size::new(400., 400.); diff --git a/core/src/events/pointers/pointer_event.rs b/core/src/events/pointers/pointer_event.rs index af0669516..fb9b7b66d 100644 --- a/core/src/events/pointers/pointer_event.rs +++ b/core/src/events/pointers/pointer_event.rs @@ -3,7 +3,6 @@ use crate::{ prelude::{dispatcher::DispatchInfo, *}, widget_tree::WidgetTree, }; -// use winit::event::MouseButton; impl PointerEvent { pub(crate) fn from_mouse( @@ -13,8 +12,7 @@ impl PointerEvent { info: &DispatchInfo, ) -> Self { PointerEvent { - // todo: how to generate pointer id ? - id: pointer_id, /* PointerId(0) */ + id: pointer_id, width: 1.0, height: 1.0, pressure: if info.mouse_buttons().is_empty() { diff --git a/core/src/events/wheel.rs b/core/src/events/wheel.rs index b95d983eb..fcc35dff2 100644 --- a/core/src/events/wheel.rs +++ b/core/src/events/wheel.rs @@ -53,7 +53,7 @@ impl std::ops::DerefMut for WheelEvent { #[cfg(test)] mod tests { use super::*; - use crate::test::MockBox; + use crate::test::{MockBox, MockPointerId}; use std::{cell::RefCell, rc::Rc}; // use winit::event::{DeviceId, ModifiersState, MouseScrollDelta, TouchPhase, // WindowEvent}; diff --git a/core/src/test.rs b/core/src/test.rs index cf9f12e72..0aa376fc1 100644 --- a/core/src/test.rs +++ b/core/src/test.rs @@ -257,4 +257,29 @@ pub macro unit_test_describe($(run_unit_test($name: path);)* ) {{ if let Result::Err(err) = res { std::panic::resume_unwind(err); } -}} +} +} + +#[derive(Default, Debug, Copy, Clone)] +pub struct MockPointerId(usize); + +impl MockPointerId { + pub fn new(value: usize) -> Box { Box::new(MockPointerId(value)) } + pub fn zero() -> Box { MockPointerId::new(0) } +} + +impl PointerId for MockPointerId { + fn into_any(self: Box) -> Box { self } + + fn equals(&self, other: &Box) -> bool { + self.0 + == other + .box_clone() + .into_any() + .downcast::() + .unwrap() + .0 + } + + fn box_clone(&self) -> Box { Box::new(*self) } +} diff --git a/core/src/window.rs b/core/src/window.rs index 88494508c..79c83de61 100644 --- a/core/src/window.rs +++ b/core/src/window.rs @@ -5,7 +5,6 @@ use crate::{ }; pub trait WindowId: std::fmt::Debug { - // fn as_any(&self) -> &dyn Any; fn into_any(self: Box) -> Box; fn equals(&self, other: &Box) -> bool; fn box_clone(&self) -> Box; @@ -15,6 +14,10 @@ impl Clone for Box { fn clone(&self) -> Self { self.box_clone() } } +impl PartialEq for Box { + fn eq(&self, other: &Self) -> bool { self.equals(other) } +} + // pub use winit::window::CursorIcon; // use winit::{event::WindowEvent, window::WindowId}; @@ -33,154 +36,6 @@ pub trait RawWindow { fn as_any(&self) -> &dyn Any; } -// impl RawWindow for winit::window::Window { -// fn inner_size(&self) -> Size { -// let size = self.inner_size().to_logical(self.scale_factor()); -// Size::new(size.width, size.height) -// } - -// fn set_inner_size(&mut self, size: Size) { -// let size = winit::dpi::LogicalSize::new(size.width, size.height); -// winit::window::Window::set_inner_size(self, size) -// } - -// fn outer_size(&self) -> Size { -// let size = self.outer_size().to_logical(self.scale_factor()); -// Size::new(size.width, size.height) -// } - -// fn inner_position(&self) -> Point { -// let pos = self -// .inner_position() -// .expect(" Can only be called on the main thread") -// .to_logical(self.scale_factor()); - -// Point::new(pos.x, pos.y) -// } -// #[inline] -// fn id(&self) -> WindowId { self.id() } - -// fn outer_position(&self) -> Point { -// let pos = self -// .outer_position() -// .expect(" Can only be called on the main thread") -// .to_logical(self.scale_factor()); -// Point::new(pos.x, pos.y) -// } - -// #[inline] -// fn request_redraw(&self) { winit::window::Window::request_redraw(self) } - -// fn set_cursor(&mut self, cursor: CursorIcon) { self.set_cursor_icon(cursor) -// } - -// #[inline] -// fn scale_factor(&self) -> f64 { winit::window::Window::scale_factor(self) } -// } - -// pub struct WindowBuilder { -// inner_builder: winit::window::WindowBuilder, -// root: Widget, -// } - -// impl WindowBuilder { -// #[inline] -// pub fn build(self, app: &Application) -> Window { -// let native_wnd = self.inner_builder.build(app.event_loop()).unwrap(); -// let size = native_wnd.inner_size(); -// let ctx = app.context().clone(); -// let p_backend = AppContext::wait_future(ribir_gpu::wgpu_backend_with_wnd( -// &native_wnd, -// DeviceSize::new(size.width, size.height), -// None, -// None, -// ctx.shaper.clone(), -// )); -// Window::new(native_wnd, p_backend, self.root, ctx) -// } - -// /// Requests the window to be of specific dimensions. -// #[inline] -// pub fn with_inner_size(mut self, size: Size) -> Self { -// let size = winit::dpi::LogicalSize::new(size.width, size.height); -// self.inner_builder = self.inner_builder.with_inner_size(size); -// self -// } - -// /// Sets a minimum dimension size for the window. -// #[inline] -// pub fn with_min_inner_size(mut self, min_size: Size) -> Self { -// let size = winit::dpi::LogicalSize::new(min_size.width, min_size.height); -// self.inner_builder = self.inner_builder.with_min_inner_size(size); -// self -// } - -// /// Sets a maximum dimension size for the window. -// #[inline] -// pub fn with_max_inner_size(mut self, max_size: Size) -> Self { -// let size = winit::dpi::LogicalSize::new(max_size.width, max_size.height); -// self.inner_builder = self.inner_builder.with_max_inner_size(size); -// self -// } - -// /// Sets a desired initial position for the window. -// #[inline] -// pub fn with_position(mut self, position: Point) -> Self { -// let position = winit::dpi::LogicalPosition::new(position.x, position.y); -// self.inner_builder = self.inner_builder.with_position(position); -// self -// } - -// /// Sets whether the window is resizable or not. -// #[inline] -// pub fn with_resizable(mut self, resizable: bool) -> Self { -// self.inner_builder = self.inner_builder.with_resizable(resizable); -// self -// } - -// /// Requests a specific title for the window. -// #[inline] -// pub fn with_title>(mut self, title: T) -> Self { -// self.inner_builder = self.inner_builder.with_title(title); -// self -// } - -// /// Requests maximized mode. -// #[inline] -// pub fn with_maximized(mut self, maximized: bool) -> Self { -// self.inner_builder = self.inner_builder.with_maximized(maximized); -// self -// } - -// /// Sets whether the window will be initially hidden or visible. -// #[inline] -// pub fn with_visible(mut self, visible: bool) -> Self { -// self.inner_builder = self.inner_builder.with_visible(visible); -// self -// } - -// /// Sets whether the background of the window should be transparent. -// #[inline] -// pub fn with_transparent(mut self, transparent: bool) -> Self { -// self.inner_builder = self.inner_builder.with_transparent(transparent); -// self -// } - -// /// Sets whether the window should have a border, a title bar, etc. -// #[inline] -// pub fn with_decorations(mut self, decorations: bool) -> Self { -// self.inner_builder = self.inner_builder.with_decorations(decorations); -// self -// } - -// // /// Sets the window icon. -// // #[inline] -// // pub fn with_window_icon(mut self, window_icon: -// Option) // -> Self { self.inner_builder = -// // self.inner_builder.with_window_icon(window_icon); self -// // } -// } - /// A rx scheduler pool that block until all task finished before every frame /// end. struct FramePool(FuturesLocalSchedulerPool); diff --git a/tests/animations_syntax_test.rs b/tests/animations_syntax_test.rs index c4e9a2913..10228f062 100644 --- a/tests/animations_syntax_test.rs +++ b/tests/animations_syntax_test.rs @@ -1,4 +1,5 @@ use ribir::prelude::*; +use ribir_core::test::MockPointerId; use std::{cell::Cell, rc::Rc, time::Duration}; // use winit::event::{DeviceId, MouseScrollDelta, TouchPhase, WindowEvent}; diff --git a/winit/src/from_device_id.rs b/winit/src/from_device_id.rs index 1824ada14..d057d7bc4 100644 --- a/winit/src/from_device_id.rs +++ b/winit/src/from_device_id.rs @@ -8,7 +8,7 @@ pub struct WrappedPointerId(WinitDeviceId); impl RibirPointerId for WrappedPointerId { fn into_any(self: Box) -> Box { self } - fn eq(&self, other: &Box) -> bool { + fn equals(&self, other: &Box) -> bool { self.0 == WrappedPointerId::from(other).0 } fn box_clone(&self) -> Box { Box::new(self.clone()) } From d1f378ede545c472362bdc0f88c29a49da38f580 Mon Sep 17 00:00:00 2001 From: Guenter Zoechbauer Date: Wed, 15 Mar 2023 18:02:54 +0100 Subject: [PATCH 7/9] Remove more deleted code --- core/src/events/pointers.rs | 1 - core/src/events/wheel.rs | 2 -- core/src/window.rs | 3 --- tests/animations_syntax_test.rs | 2 -- tests/code_gen_test.rs | 1 - 5 files changed, 9 deletions(-) diff --git a/core/src/events/pointers.rs b/core/src/events/pointers.rs index 419d8ca0e..f5d39dabc 100644 --- a/core/src/events/pointers.rs +++ b/core/src/events/pointers.rs @@ -421,7 +421,6 @@ mod tests { let (mut wnd, count) = env(3); let mut local_pool = LocalPool::new(); - // let device_id = MockPointerId::zero(); observable::interval(Duration::from_millis(10), local_pool.spawner()) .take(12) .subscribe(move |i| { diff --git a/core/src/events/wheel.rs b/core/src/events/wheel.rs index fcc35dff2..af09be7a5 100644 --- a/core/src/events/wheel.rs +++ b/core/src/events/wheel.rs @@ -55,8 +55,6 @@ mod tests { use super::*; use crate::test::{MockBox, MockPointerId}; use std::{cell::RefCell, rc::Rc}; - // use winit::event::{DeviceId, ModifiersState, MouseScrollDelta, TouchPhase, - // WindowEvent}; #[test] fn smoke() { diff --git a/core/src/window.rs b/core/src/window.rs index 79c83de61..6e8bcfc1b 100644 --- a/core/src/window.rs +++ b/core/src/window.rs @@ -18,9 +18,6 @@ impl PartialEq for Box { fn eq(&self, other: &Self) -> bool { self.equals(other) } } -// pub use winit::window::CursorIcon; -// use winit::{event::WindowEvent, window::WindowId}; - pub trait RawWindow { fn inner_size(&self) -> Size; fn set_inner_size(&mut self, size: Size); diff --git a/tests/animations_syntax_test.rs b/tests/animations_syntax_test.rs index 10228f062..500ab781c 100644 --- a/tests/animations_syntax_test.rs +++ b/tests/animations_syntax_test.rs @@ -1,7 +1,6 @@ use ribir::prelude::*; use ribir_core::test::MockPointerId; use std::{cell::Cell, rc::Rc, time::Duration}; -// use winit::event::{DeviceId, MouseScrollDelta, TouchPhase, WindowEvent}; fn wheel_widget(w: Widget) -> Window { let mut wnd = Window::default_mock(w, None); @@ -12,7 +11,6 @@ fn wheel_widget(w: Widget) -> Window { device_id, delta: MouseScrollDelta::LineDelta(1.0, 1.0), phase: TouchPhase::Started, - // modifiers: ModifiersState::default(), }); wnd } diff --git a/tests/code_gen_test.rs b/tests/code_gen_test.rs index 12bc23761..2f11c8061 100644 --- a/tests/code_gen_test.rs +++ b/tests/code_gen_test.rs @@ -1,7 +1,6 @@ use ribir::prelude::*; use ribir_core::test::*; use std::{cell::Cell, rc::Rc}; -// use winit::event::{DeviceId, ElementState, MouseButton, WindowEvent}; #[test] fn declare_smoke() { From dc38224683836f55d00ce4fef8557b347fc108b7 Mon Sep 17 00:00:00 2001 From: Guenter Zoechbauer Date: Tue, 21 Mar 2023 15:05:52 +0100 Subject: [PATCH 8/9] Allow switching between platforms using feature flags cd ribir cargo run --example todo_mvp -F winit,wgpu_gl or cd ribir cargo run --example todo_mvp -F crossterm --- Cargo.toml | 3 +- app/Cargo.toml | 9 +- app/src/application.rs | 49 ++- app/src/event_loop.rs | 1 - app/src/lib.rs | 13 +- app/src/shell_window.rs | 1 - app/src/window_builder.rs | 41 --- core/src/builtin_widgets/box_decoration.rs | 2 +- core/src/events/pointers.rs | 1 + core/src/lib.rs | 5 +- core/src/test.rs | 81 ++++- core/src/window.rs | 133 +++----- crossterm/Cargo.toml | 21 ++ crossterm/src/from_device_id.rs | 25 ++ crossterm/src/from_element_state.rs | 32 ++ crossterm/src/from_event.rs | 115 +++++++ crossterm/src/from_keyboard_input.rs | 59 ++++ crossterm/src/from_modifiers.rs | 47 +++ crossterm/src/from_mouse.rs | 22 ++ crossterm/src/from_virtual_key_code.rs | 285 ++++++++++++++++++ crossterm/src/from_window.rs | 121 ++++++++ crossterm/src/from_window_id.rs | 31 ++ crossterm/src/lib.rs | 51 ++++ crossterm/src/shell_window.rs | 151 ++++++++++ crossterm/src/window_builder.rs | 97 ++++++ painter/src/painter.rs | 8 +- ribir/Cargo.toml | 4 +- ribir/examples/todo_mvp.rs | 35 ++- ribir/src/lib.rs | 41 --- winit/Cargo.toml | 3 +- winit/src/from_device_id.rs | 11 - winit/src/from_window.rs | 2 +- winit/src/lib.rs | 6 +- winit/src/{application.rs => shell_window.rs} | 32 +- winit/src/window_builder.rs | 165 +++++----- 35 files changed, 1379 insertions(+), 324 deletions(-) delete mode 100644 app/src/event_loop.rs delete mode 100644 app/src/shell_window.rs delete mode 100644 app/src/window_builder.rs create mode 100644 crossterm/Cargo.toml create mode 100644 crossterm/src/from_device_id.rs create mode 100644 crossterm/src/from_element_state.rs create mode 100644 crossterm/src/from_event.rs create mode 100644 crossterm/src/from_keyboard_input.rs create mode 100644 crossterm/src/from_modifiers.rs create mode 100644 crossterm/src/from_mouse.rs create mode 100644 crossterm/src/from_virtual_key_code.rs create mode 100644 crossterm/src/from_window.rs create mode 100644 crossterm/src/from_window_id.rs create mode 100644 crossterm/src/lib.rs create mode 100644 crossterm/src/shell_window.rs create mode 100644 crossterm/src/window_builder.rs rename winit/src/{application.rs => shell_window.rs} (83%) diff --git a/Cargo.toml b/Cargo.toml index 0cd9e5ed3..923124586 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,14 +3,15 @@ members = [ "algo", "app", "core", + "crossterm", "geometry", "gpu", "macros", "macros/builtin", "painter", "ribir", - "text", "tests", + "text", "widgets", "winit", ] diff --git a/app/Cargo.toml b/app/Cargo.toml index 6266df4cf..7baf25ecb 100644 --- a/app/Cargo.toml +++ b/app/Cargo.toml @@ -1,9 +1,16 @@ [package] name = "ribir_app" -version = "0.1.0" +version = "0.0.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] ribir_core = { path = "../core" } +ribir_winit = { path = "../winit", optional = true } +ribir_crossterm = { path = "../crossterm", optional = true } + +[features] +wgpu_gl = ["ribir_winit/wgpu_gl"] +winit = ["ribir_winit"] +crossterm = ["ribir_crossterm"] diff --git a/app/src/application.rs b/app/src/application.rs index d89e0679f..1b1cb00fd 100644 --- a/app/src/application.rs +++ b/app/src/application.rs @@ -1,18 +1,43 @@ -// use ribir_core::{ -// prelude::{AppContext, Theme}, -// window::{Window, WindowId}, -// }; +use ribir_core::{ + prelude::{ShellWindow, Theme}, + widget::Widget, + window::{WindowConfig, WindowId}, +}; -// use crate::event_loop::EventLoop; +use ribir_platform::prelude::{PlatformShellWindow, WindowBuilder}; -// pub trait Application { -// fn with_theme(self, theme: Theme) -> Self; +pub struct Application { + shell_window: T, +} -// fn context(&self) -> &AppContext; +/// Application for platform implementations provided by Ribir +#[cfg(any(feature = "crossterm", feature = "winit"))] +impl Application { + pub fn new(theme: Theme) -> Application { + let shell_window = PlatformShellWindow::new(theme); + Application { shell_window } + } -// fn event_loop(&self) -> &EventLoop<()>; + pub fn window_builder(&self, root: Widget, config: WindowConfig) -> WindowBuilder { + WindowBuilder::new(root, config) + } -// fn exec(self, wnd_id: Box); + pub fn build_window(&mut self, window_builder: WindowBuilder) -> Box { + let window = window_builder.build(&self.shell_window); + let window_id = window.raw_window.id().box_clone(); + self.shell_window.add_window(window); + window_id + } -// fn add_window(&mut self, wnd: Window) -> Box; -// } + pub fn exec(self, wnd_id: Box) { self.shell_window.exec(wnd_id) } +} + +/// Application for platform implementations not provided by Ribir +#[cfg(not(any(feature = "crossterm", feature = "winit")))] +impl Application { + pub fn new(shell_window: T, /* , painter_backend: Box */) -> Application { + Application { shell_window } + } + + pub fn add_window(mut self, window: Window) { self.shell_window.add_window(window); } +} diff --git a/app/src/event_loop.rs b/app/src/event_loop.rs deleted file mode 100644 index 4f6960987..000000000 --- a/app/src/event_loop.rs +++ /dev/null @@ -1 +0,0 @@ -pub trait EventLoop {} diff --git a/app/src/lib.rs b/app/src/lib.rs index d5a4ff7e6..ad8431caa 100644 --- a/app/src/lib.rs +++ b/app/src/lib.rs @@ -1,6 +1,15 @@ +#[cfg(all(feature = "crossterm", not(feature = "winit")))] +extern crate ribir_crossterm as ribir_platform; + +#[cfg(all(feature = "winit", not(feature = "crossterm")))] +extern crate ribir_winit as ribir_platform; + +#[cfg(all(feature = "winit", feature = "crossterm"))] +compile_error!("feature \"winit\" and feature \"crossterm\" cannot be enabled at the same time"); + pub mod application; -pub mod event_loop; -pub mod shell_window; pub mod prelude { pub use crate::application::*; + pub use ribir_core::prelude::*; + pub use ribir_platform::prelude::*; } diff --git a/app/src/shell_window.rs b/app/src/shell_window.rs deleted file mode 100644 index 63c6b2b38..000000000 --- a/app/src/shell_window.rs +++ /dev/null @@ -1 +0,0 @@ -pub trait ShellWindow {} diff --git a/app/src/window_builder.rs b/app/src/window_builder.rs deleted file mode 100644 index 89c69ed06..000000000 --- a/app/src/window_builder.rs +++ /dev/null @@ -1,41 +0,0 @@ -// use ribir_app::prelude::Application; -// use ribir_core::{prelude::AppContext, widget::Widget, window::Window as RibirWindow}; -// use ribir_geometry::{DeviceSize, Point, Size}; - -// pub trait WindowBuilder { -// fn build(self, app: dyn Application) -> RibirWindow; - -// /// Requests the window to be of specific dimensions. -// fn with_inner_size(self, size: Size) -> Self; - -// /// Sets a minimum dimension size for the window. -// fn with_min_inner_size( self, min_size: Size) -> Self; - -// /// Sets a maximum dimension size for the window. -// fn with_max_inner_size( self, max_size: Size) -> Self; - -// /// Sets a desired initial position for the window. -// fn with_position(self, position: Point) -> Self; - -// /// Sets whether the window is resizable or not. -// fn with_resizable( self, resizable: bool) -> Self; - -// /// Requests a specific title for the window. -// fn with_title>( self, title: T) -> Self; - -// /// Requests maximized mode. -// fn with_maximized( self, maximized: bool) -> Self; - -// /// Sets whether the window will be initially hidden or visible. -// fn with_visible( self, visible: bool) -> Self; - -// /// Sets whether the background of the window should be transparent. -// fn with_transparent( self, transparent: bool) -> Self; - -// /// Sets whether the window should have a border, a title bar, etc. - -// fn with_decorations( self, decorations: bool) -> Self; - -// /// Sets the window icon. -// // fn with_window_icon( self, window_icon: WindowIcon>) -> Self; -// } diff --git a/core/src/builtin_widgets/box_decoration.rs b/core/src/builtin_widgets/box_decoration.rs index 2bed72cfb..9667f11a2 100644 --- a/core/src/builtin_widgets/box_decoration.rs +++ b/core/src/builtin_widgets/box_decoration.rs @@ -125,7 +125,7 @@ impl BoxDecoration { ) { assert!( self.is_border_uniform(), - "radius can't be setted with different border" + "radius can't be used with with different borders" ); let width_half = border.left.width / 2.; let min_x = content_rect.min_x() - width_half; diff --git a/core/src/events/pointers.rs b/core/src/events/pointers.rs index f5d39dabc..f24dee6a5 100644 --- a/core/src/events/pointers.rs +++ b/core/src/events/pointers.rs @@ -16,6 +16,7 @@ const MULTI_TAP_DURATION: Duration = Duration::from_millis(250); pub trait PointerId: Debug { fn into_any(self: Box) -> Box; + #[allow(clippy::borrowed_box)] // to make downcast work fn equals(&self, other: &Box) -> bool; fn box_clone(&self) -> Box; } diff --git a/core/src/lib.rs b/core/src/lib.rs index 72bb4a858..981ce6255 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -5,7 +5,6 @@ extern crate bitflags; extern crate lazy_static; pub mod animation; -// mod application; pub mod builtin_widgets; mod context; pub mod data_widget; @@ -25,8 +24,6 @@ pub mod widget_children; pub mod window; pub mod prelude { pub use crate::animation::*; - // #[doc(no_inline)] - // pub use crate::application::Application; pub use crate::assign_observable::AssignObservable; #[doc(no_inline)] pub use crate::builtin_widgets::*; @@ -57,7 +54,7 @@ pub mod prelude { #[doc(no_inline)] pub use crate::widget_tree::{BoxClamp, LayoutInfo, Layouter, WidgetId}; #[doc(no_inline)] - pub use crate::window::Window; + pub use crate::window::{ShellWindow, Window}; #[doc(no_inline)] pub use ::ribir_painter::*; pub use log; diff --git a/core/src/test.rs b/core/src/test.rs index 0aa376fc1..7e5c90716 100644 --- a/core/src/test.rs +++ b/core/src/test.rs @@ -1,4 +1,10 @@ -use crate::{impl_query_self_only, prelude::*}; +use std::error::Error; + +use crate::{ + impl_query_self_only, + prelude::*, + window::{RawWindow, WindowId}, +}; #[derive(Default, Clone, Copy)] pub struct ExpectRect { @@ -283,3 +289,76 @@ impl PointerId for MockPointerId { fn box_clone(&self) -> Box { Box::new(*self) } } + +pub struct MockBackend; + +#[derive(Default)] +pub struct MockRawWindow { + pub size: Size, + pub cursor: Option, +} + +impl PainterBackend for MockBackend { + fn submit<'a>(&mut self, _: Vec) {} + + fn resize(&mut self, _: DeviceSize) {} + + fn commands_to_image( + &mut self, + _: Vec, + _: CaptureCallback, + ) -> Result<(), Box> { + Ok(()) + } +} + +#[derive(Debug, Copy, Clone)] +pub struct MockWindowId(usize); + +impl MockWindowId { + fn dummy() -> MockWindowId { MockWindowId(0) } +} + +impl WindowId for MockWindowId { + fn into_any(self: Box) -> Box { self } + fn equals(&self, other: &Box) -> bool { + self.0 + == other + .box_clone() + .into_any() + .downcast::() + .unwrap() + .0 + } + + fn box_clone(&self) -> Box { Box::new(*self) } +} + +impl RawWindow for MockRawWindow { + fn inner_size(&self) -> Size { self.size } + fn set_inner_size(&mut self, size: Size) { self.size = size; } + fn outer_size(&self) -> Size { self.size } + fn inner_position(&self) -> Point { Point::zero() } + fn outer_position(&self) -> Point { Point::zero() } + fn id(&self) -> Box { Box::new(MockWindowId::dummy()) } + fn set_cursor(&mut self, cursor: CursorIcon) { self.cursor = Some(cursor); } + fn request_redraw(&self) {} + fn scale_factor(&self) -> f64 { 1. } + fn into_any(self: Box) -> Box { self } +} + +impl Window { + pub fn default_mock(root: Widget, size: Option) -> Self { + let size = size.unwrap_or_else(|| Size::new(1024., 1024.)); + Self::mock_window(root, size, <_>::default()) + } + + pub fn mock_window(root: Widget, size: Size, ctx: AppContext) -> Self { + Self::new( + MockRawWindow { size, ..Default::default() }, + MockBackend, + root, + ctx, + ) + } +} diff --git a/core/src/window.rs b/core/src/window.rs index 6e8bcfc1b..0f2d3f674 100644 --- a/core/src/window.rs +++ b/core/src/window.rs @@ -4,8 +4,56 @@ use crate::{ context::AppContext, events::dispatcher::Dispatcher, prelude::*, widget_tree::WidgetTree, }; +pub trait ShellWindow { + fn set_theme(self, theme: Theme); + + fn context(&self) -> &AppContext; + + // fn event_loop(&self) -> &EventLoop<()>; + + fn exec(self, wnd_id: Box); + + fn add_window(&mut self, wnd: Window) -> Box; +} + +#[derive(Debug, Clone, Default)] +pub struct WindowConfig { + // Requests the window to be of specific dimensions. + pub inner_size: Option, + + /// Sets a minimum dimension size for the window. + pub min_inner_size: Option, + + /// Sets a maximum dimension size for the window. + pub max_inner_size: Option, + + /// Sets a desired initial position for the window. + pub position: Option, + + /// Sets whether the window is resizable or not. + pub resizable: Option, + + /// Requests a specific title for the window. + pub title: Option, + + /// Requests maximized mode. + pub maximized: Option, + + /// Sets whether the window will be initially hidden or visible. + pub visible: Option, + + /// Sets whether the background of the window should be transparent. + pub transparent: Option, + + /// Sets whether the window should have a border, a title bar, etc. + pub decorations: Option, + // /// Sets the window icon. + // pub window_icon:Option, +} + pub trait WindowId: std::fmt::Debug { fn into_any(self: Box) -> Box; + #[allow(clippy::borrowed_box)] // to make downcast work fn equals(&self, other: &Box) -> bool; fn box_clone(&self) -> Box; } @@ -30,7 +78,8 @@ pub trait RawWindow { /// Modify the native window if cursor modified. fn set_cursor(&mut self, cursor: CursorIcon); fn scale_factor(&self) -> f64; - fn as_any(&self) -> &dyn Any; + // fn as_any(&self) -> &dyn Any; + fn into_any(self: Box) -> Box; } /// A rx scheduler pool that block until all task finished before every frame @@ -51,14 +100,6 @@ pub struct Window { } impl Window { - // #[inline] - // pub fn builder(root: Widget) -> WindowBuilder { - // WindowBuilder { - // root, - // inner_builder: winit::window::WindowBuilder::default(), - // } - // } - /// processes native events from this native window #[inline] pub fn processes_native_event(&mut self, event: WindowEvent) { @@ -218,80 +259,6 @@ impl Window { } } -pub struct MockBackend; - -#[derive(Default)] -pub struct MockRawWindow { - pub size: Size, - pub cursor: Option, -} - -impl PainterBackend for MockBackend { - fn submit<'a>(&mut self, _: Vec) {} - - fn resize(&mut self, _: DeviceSize) {} - - fn commands_to_image( - &mut self, - _: Vec, - _: CaptureCallback, - ) -> Result<(), Box> { - Ok(()) - } -} - -#[derive(Debug, Copy, Clone)] -pub struct MockWindowId(usize); - -impl MockWindowId { - fn dummy() -> MockWindowId { MockWindowId(0) } -} - -impl WindowId for MockWindowId { - fn into_any(self: Box) -> Box { self } - // fn as_boxed_any(self: Box) -> Box { self } - fn equals(&self, other: &Box) -> bool { - self.0 - == other - .box_clone() - .into_any() - .downcast_ref::() - .unwrap() - .0 - } - - fn box_clone(&self) -> Box { Box::new(*self) } -} - -impl RawWindow for MockRawWindow { - fn inner_size(&self) -> Size { self.size } - fn set_inner_size(&mut self, size: Size) { self.size = size; } - fn outer_size(&self) -> Size { self.size } - fn inner_position(&self) -> Point { Point::zero() } - fn outer_position(&self) -> Point { Point::zero() } - fn id(&self) -> Box { Box::new(MockWindowId::dummy()) } - fn set_cursor(&mut self, cursor: CursorIcon) { self.cursor = Some(cursor); } - fn request_redraw(&self) {} - fn scale_factor(&self) -> f64 { 1. } - fn as_any(&self) -> &dyn Any { self } -} - -impl Window { - pub fn default_mock(root: Widget, size: Option) -> Self { - let size = size.unwrap_or_else(|| Size::new(1024., 1024.)); - Self::mock_window(root, size, <_>::default()) - } - - pub fn mock_window(root: Widget, size: Size, ctx: AppContext) -> Self { - Self::new( - MockRawWindow { size, ..Default::default() }, - MockBackend, - root, - ctx, - ) - } -} - #[cfg(test)] mod tests { use super::*; diff --git a/crossterm/Cargo.toml b/crossterm/Cargo.toml new file mode 100644 index 000000000..ab546c88a --- /dev/null +++ b/crossterm/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "ribir_crossterm" +version = "0.0.0" +edition = "2021" + +[dependencies] +crossterm = "0.26.1" +log = "0.4.8" +ribir_core = { path = "../core" } +ribir_geometry = { path = "../geometry" } +ribir_painter = {path = "../painter"} +ribir_text = {path = "../text"} + +# [dev-dpendencies] +env_logger = "0.7.1" +ribir_widgets = {path = "../widgets"} + +[features] +default = ["bracketed-paste"] +bracketed-paste = ["crossterm/bracketed-paste"] + diff --git a/crossterm/src/from_device_id.rs b/crossterm/src/from_device_id.rs new file mode 100644 index 000000000..05f351a76 --- /dev/null +++ b/crossterm/src/from_device_id.rs @@ -0,0 +1,25 @@ +use std::any::Any; + +use ribir_core::events::PointerId as RibirPointerId; + +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] +pub struct CrosstermPointerId(usize); + +impl CrosstermPointerId { + pub fn zero() -> CrosstermPointerId { CrosstermPointerId(0) } +} + +impl RibirPointerId for CrosstermPointerId { + fn into_any(self: Box) -> Box { self } + fn equals(&self, other: &Box) -> bool { + self.0 + == other + .box_clone() + .into_any() + .downcast::() + .unwrap() + .0 + } + + fn box_clone(&self) -> Box { Box::new(*self) } +} diff --git a/crossterm/src/from_element_state.rs b/crossterm/src/from_element_state.rs new file mode 100644 index 000000000..ce495a503 --- /dev/null +++ b/crossterm/src/from_element_state.rs @@ -0,0 +1,32 @@ +use crossterm::event::KeyEventKind as CrosstermElementState; +use ribir_core::prelude::ElementState as RibirElementState; + +pub struct WrappedElementState(CrosstermElementState); + +impl From for WrappedElementState { + fn from(value: CrosstermElementState) -> Self { WrappedElementState(value) } +} + +impl From for CrosstermElementState { + fn from(val: WrappedElementState) -> Self { val.0 } +} + +impl From for RibirElementState { + fn from(val: WrappedElementState) -> Self { + match val.0 { + CrosstermElementState::Press => RibirElementState::Pressed, + CrosstermElementState::Release => RibirElementState::Released, + CrosstermElementState::Repeat => RibirElementState::Pressed, + } + } +} + +// impl From for WrappedElementState { +// fn from(value: RibirElementState) -> WrappedElementState { +// let es = match value { +// RibirElementState::Pressed => CrosstermElementState::Pressed, +// RibirElementState::Released => CrosstermElementState::Released, +// }; +// es.into() +// } +// } diff --git a/crossterm/src/from_event.rs b/crossterm/src/from_event.rs new file mode 100644 index 000000000..ce59ca613 --- /dev/null +++ b/crossterm/src/from_event.rs @@ -0,0 +1,115 @@ +use crate::{ + from_device_id::CrosstermPointerId, from_keyboard_input::WrappedKeyboardInput, + from_mouse::WrappedMouseButton, +}; +use crossterm::event::{Event as CrosstermWindowEvent, MouseEventKind}; +use ribir_core::prelude::{ + ElementState, MouseScrollDelta, TouchPhase, WindowEvent as RibirWindowEvent, +}; +use ribir_geometry::{DevicePoint, DeviceSize}; + +pub struct WrappedWindowEvent(CrosstermWindowEvent); + +impl From for WrappedWindowEvent { + fn from(value: CrosstermWindowEvent) -> Self { WrappedWindowEvent(value) } +} + +impl From for CrosstermWindowEvent { + fn from(val: WrappedWindowEvent) -> Self { val.0 } +} + +impl From for RibirWindowEvent { + fn from(val: WrappedWindowEvent) -> Self { + match val.0 { + CrosstermWindowEvent::FocusGained => RibirWindowEvent::Unsupported, + CrosstermWindowEvent::FocusLost => RibirWindowEvent::CursorLeft { + device_id: Box::new(CrosstermPointerId::zero()), + }, + CrosstermWindowEvent::Key(event) => RibirWindowEvent::KeyboardInput { + device_id: Box::new(CrosstermPointerId::zero()), + input: WrappedKeyboardInput::from(event).into(), + is_synthetic: false, + }, + CrosstermWindowEvent::Mouse(event) => match event.kind { + MouseEventKind::Down(button) => RibirWindowEvent::MouseInput { + device_id: Box::new(CrosstermPointerId::zero()), + state: ElementState::Pressed, + button: WrappedMouseButton::from(button).into(), + }, + MouseEventKind::Up(button) => RibirWindowEvent::MouseInput { + device_id: Box::new(CrosstermPointerId::zero()), + state: ElementState::Released, + button: WrappedMouseButton::from(button).into(), + }, + MouseEventKind::Drag(_) => RibirWindowEvent::Unsupported, + MouseEventKind::Moved => RibirWindowEvent::CursorMoved { + device_id: Box::new(CrosstermPointerId::zero()), + position: DevicePoint::new(event.column as u32, event.row as u32), + }, + MouseEventKind::ScrollDown => RibirWindowEvent::MouseWheel { + device_id: Box::new(CrosstermPointerId::zero()), + delta: MouseScrollDelta::LineDelta(0., 1.), + phase: TouchPhase::Moved, + }, + MouseEventKind::ScrollUp => RibirWindowEvent::MouseWheel { + device_id: Box::new(CrosstermPointerId::zero()), + delta: MouseScrollDelta::LineDelta(0., -1.), + phase: TouchPhase::Moved, + }, + }, + #[cfg(feature = "bracketed-paste")] + CrosstermWindowEvent::Paste(_data) => RibirWindowEvent::Unsupported, + CrosstermWindowEvent::Resize(width, height) => { + RibirWindowEvent::Resized(DeviceSize::new(width as u32, height as u32)) + } /* CrosstermWindowEvent::ReceivedCharacter(char) => + * RibirWindowEvent::ReceivedCharacter(char), CrosstermWindowEvent::KeyboardInput + * { device_id, input, is_synthetic } => { RibirWindowEvent::KeyboardInput { + * device_id: Box::new(CrosstermPointerId::from(device_id)), + * input: WrappedKeyboardInput::from(input).into(), + * is_synthetic, + * } + * } + * CrosstermWindowEvent::ModifiersChanged(modifiers) => { + * RibirWindowEvent::ModifiersChanged(WrappedModifiersState::from(modifiers).into()) + * } + * #[allow(deprecated)] + * CrosstermWindowEvent::CursorMoved { device_id, position, modifiers: _ } => { + * RibirWindowEvent::CursorMoved { + * device_id: Box::new(CrosstermPointerId::from(device_id)), + * position, + * } + * } + * CrosstermWindowEvent::CursorLeft { device_id } => RibirWindowEvent::CursorLeft { + * device_id: Box::new(CrosstermPointerId::from(device_id)), + * }, + * #[allow(deprecated)] + * CrosstermWindowEvent::MouseWheel { + * device_id, + * delta, + * phase, + * modifiers: _, + * } => RibirWindowEvent::MouseWheel { + * device_id: Box::new(CrosstermPointerId::from(device_id)), + * delta: WrappedMouseScrollDelta::from(delta).into(), + * phase: WrappedTouchPhase::from(phase).into(), + * }, + * #[allow(deprecated)] + * CrosstermWindowEvent::MouseInput { + * device_id, + * state, + * button, + * modifiers: _, + * } => RibirWindowEvent::MouseInput { + * device_id: Box::new(CrosstermPointerId::from(device_id)), + * state: WrappedElementState::from(state).into(), + * button: WrappedMouseButton::from(button).into(), + * }, + * CrosstermWindowEvent::ScaleFactorChanged { scale_factor, new_inner_size } => { + * RibirWindowEvent::ScaleFactorChanged { + * scale_factor, + * new_inner_size: WrappedPhysicalSize::::from(new_inner_size).into(), + * } + * } */ + } + } +} diff --git a/crossterm/src/from_keyboard_input.rs b/crossterm/src/from_keyboard_input.rs new file mode 100644 index 000000000..07d11983f --- /dev/null +++ b/crossterm/src/from_keyboard_input.rs @@ -0,0 +1,59 @@ +use crossterm::event::KeyEvent as CrosstermKeyboardInput; +use ribir_core::prelude::KeyboardInput as RibirKeyboardInput; + +use crate::{from_element_state::WrappedElementState, prelude::WrappedVirtualKeyCode}; + +#[derive(Clone)] +pub struct WrappedKeyboardInput(CrosstermKeyboardInput); + +impl From for WrappedKeyboardInput { + fn from(value: CrosstermKeyboardInput) -> Self { WrappedKeyboardInput(value) } +} + +impl From for CrosstermKeyboardInput { + fn from(val: WrappedKeyboardInput) -> Self { val.0 } +} + +impl From for RibirKeyboardInput { + fn from(val: WrappedKeyboardInput) -> Self { + RibirKeyboardInput { + scancode: 0, + state: WrappedElementState::from(val.0.kind).into(), + virtual_keycode: WrappedVirtualKeyCode::from(val.0.code).try_into().ok(), + } + } +} + +// impl From for WrappedKeyboardInput { +// #[allow(deprecated)] +// fn from(value: RibirKeyboardInput) -> WrappedKeyboardInput { +// WrappedKeyboardInput::from(CrosstermKeyboardInput { +// scancode: value.scancode, +// state: WrappedElementState::from(value.state).into(), +// virtual_keycode: value +// .virtual_keycode +// .map(|v| WrappedVirtualKeyCode::from(v).into()), +// modifiers: CrosstermModifiersState::default(), +// }) +// } +// } + +#[cfg(test)] +mod tests { + // use super::*; + + #[test] + fn from_crossterm() { + + // let w = WrappedKeyboardInput::from(CrosstermKeyboardInput { + // scancode: 64, + // state: CrosstermElementState::Pressed, + // virtual_keycode: Some(CrosstermVirtualKeyCode::A), + // modifiers: CrosstermModifiersState::default(), + // }); + // let ribir: RibirKeyboardInput = w.clone().into(); + // let winit: RibirKeyboardInput = w.into(); + // assert_eq!(ribir.scancode, 64); + // assert_eq!(winit.scancode, 64); + } +} diff --git a/crossterm/src/from_modifiers.rs b/crossterm/src/from_modifiers.rs new file mode 100644 index 000000000..8c95cc05b --- /dev/null +++ b/crossterm/src/from_modifiers.rs @@ -0,0 +1,47 @@ +use ribir_core::events::ModifiersState as RibirModifiersState; +// use winit::event::ModifiersState as CrosstermModifiersState; + +use crossterm::event::KeyModifiers as CrosstermKeyModifiers; + +pub struct WrappedModifiersState(CrosstermKeyModifiers); + +impl From for WrappedModifiersState { + fn from(value: CrosstermKeyModifiers) -> Self { WrappedModifiersState(value) } +} + +impl From for CrosstermKeyModifiers { + fn from(val: WrappedModifiersState) -> Self { val.0 } +} + +impl From for RibirModifiersState { + fn from(val: WrappedModifiersState) -> Self { + let shift = if val.0.contains(CrosstermKeyModifiers::SHIFT) { + RibirModifiersState::SHIFT + } else { + RibirModifiersState::empty() + }; + + let ctrl = if val.0.contains(CrosstermKeyModifiers::CONTROL) { + RibirModifiersState::CTRL + } else { + RibirModifiersState::empty() + }; + + let alt = if val + .0 + .contains(CrosstermKeyModifiers::META | CrosstermKeyModifiers::ALT) + { + RibirModifiersState::ALT + } else { + RibirModifiersState::empty() + }; + + let logo = if val.0.contains(CrosstermKeyModifiers::SUPER) { + RibirModifiersState::LOGO + } else { + RibirModifiersState::empty() + }; + + shift | ctrl | alt | logo + } +} diff --git a/crossterm/src/from_mouse.rs b/crossterm/src/from_mouse.rs new file mode 100644 index 000000000..e4f1a7bf8 --- /dev/null +++ b/crossterm/src/from_mouse.rs @@ -0,0 +1,22 @@ +use crossterm::event::MouseButton as CrosstermMouseButton; +use ribir_core::events::MouseButtons as RibirMouseButton; + +pub struct WrappedMouseButton(CrosstermMouseButton); + +impl From for WrappedMouseButton { + fn from(value: CrosstermMouseButton) -> Self { WrappedMouseButton(value) } +} + +// impl From for CrosstermMouseButton { +// fn from(val: WrappedMouseButton) -> Self { val.0 } +// } + +impl From for RibirMouseButton { + fn from(val: WrappedMouseButton) -> Self { + match val.0 { + CrosstermMouseButton::Left => RibirMouseButton::PRIMARY, + CrosstermMouseButton::Right => RibirMouseButton::SECONDARY, + CrosstermMouseButton::Middle => RibirMouseButton::AUXILIARY, + } + } +} diff --git a/crossterm/src/from_virtual_key_code.rs b/crossterm/src/from_virtual_key_code.rs new file mode 100644 index 000000000..7acd6a57a --- /dev/null +++ b/crossterm/src/from_virtual_key_code.rs @@ -0,0 +1,285 @@ +use crossterm::event::KeyCode as CrosstermVirtualKeyCode; +use ribir_core::prelude::VirtualKeyCode as RibirVirtualKeyCode; + +pub struct WrappedVirtualKeyCode(CrosstermVirtualKeyCode); + +impl From for WrappedVirtualKeyCode { + fn from(value: CrosstermVirtualKeyCode) -> Self { WrappedVirtualKeyCode(value) } +} + +impl From for CrosstermVirtualKeyCode { + fn from(val: WrappedVirtualKeyCode) -> Self { val.0 } +} + +impl TryFrom for RibirVirtualKeyCode { + type Error = String; + + fn try_from(value: WrappedVirtualKeyCode) -> Result { + match value.0 { + CrosstermVirtualKeyCode::Insert => Ok(RibirVirtualKeyCode::Insert), + CrosstermVirtualKeyCode::Home => Ok(RibirVirtualKeyCode::Home), + CrosstermVirtualKeyCode::Delete => Ok(RibirVirtualKeyCode::Delete), + CrosstermVirtualKeyCode::End => Ok(RibirVirtualKeyCode::End), + CrosstermVirtualKeyCode::PageDown => Ok(RibirVirtualKeyCode::PageDown), + CrosstermVirtualKeyCode::PageUp => Ok(RibirVirtualKeyCode::PageUp), + + CrosstermVirtualKeyCode::Left => Ok(RibirVirtualKeyCode::Left), + CrosstermVirtualKeyCode::Up => Ok(RibirVirtualKeyCode::Up), + CrosstermVirtualKeyCode::Right => Ok(RibirVirtualKeyCode::Right), + CrosstermVirtualKeyCode::Down => Ok(RibirVirtualKeyCode::Down), + + CrosstermVirtualKeyCode::Backspace => Ok(RibirVirtualKeyCode::Back), + CrosstermVirtualKeyCode::Esc => Ok(RibirVirtualKeyCode::Escape), + CrosstermVirtualKeyCode::Enter => Ok(RibirVirtualKeyCode::Return), + CrosstermVirtualKeyCode::Tab => Ok(RibirVirtualKeyCode::Tab), + + CrosstermVirtualKeyCode::BackTab => { + Err("BackTab not implemented in VirtualKeyCode".to_owned()) + } + CrosstermVirtualKeyCode::F(f) => match f { + 1 => Ok(RibirVirtualKeyCode::F1), + 2 => Ok(RibirVirtualKeyCode::F2), + 3 => Ok(RibirVirtualKeyCode::F3), + 4 => Ok(RibirVirtualKeyCode::F4), + 5 => Ok(RibirVirtualKeyCode::F5), + 6 => Ok(RibirVirtualKeyCode::F6), + 7 => Ok(RibirVirtualKeyCode::F7), + 8 => Ok(RibirVirtualKeyCode::F8), + 9 => Ok(RibirVirtualKeyCode::F9), + 10 => Ok(RibirVirtualKeyCode::F10), + 11 => Ok(RibirVirtualKeyCode::F11), + 12 => Ok(RibirVirtualKeyCode::F12), + other => Err(format!("Unsupported event code {other:?}")), + // CrosstermVirtualKeyCode::F13 => RibirVirtualKeyCode::F13, + // CrosstermVirtualKeyCode::F14 => RibirVirtualKeyCode::F14, + // CrosstermVirtualKeyCode::F15 => RibirVirtualKeyCode::F15, + // CrosstermVirtualKeyCode::F16 => RibirVirtualKeyCode::F16, + // CrosstermVirtualKeyCode::F17 => RibirVirtualKeyCode::F17, + // CrosstermVirtualKeyCode::F18 => RibirVirtualKeyCode::F18, + // CrosstermVirtualKeyCode::F19 => RibirVirtualKeyCode::F19, + // CrosstermVirtualKeyCode::F20 => RibirVirtualKeyCode::F20, + // CrosstermVirtualKeyCode::F21 => RibirVirtualKeyCode::F21, + // CrosstermVirtualKeyCode::F22 => RibirVirtualKeyCode::F22, + // CrosstermVirtualKeyCode::F23 => RibirVirtualKeyCode::F23, + // CrosstermVirtualKeyCode::F24 => RibirVirtualKeyCode::F24, + }, + + // CrosstermVirtualKeyCode::Alt(c) => Err("Not yet implemented: Alt {c:?}"), + // CrosstermVirtualKeyCode::Ctrl(c) => Err("Not yet implemented: Ctrl {c:?}"), + CrosstermVirtualKeyCode::Null => Err("Not yet implemented (Null)".to_owned()), + + CrosstermVirtualKeyCode::Char(c) => match c { + // '\x00' => RibirVirtualKeyCode::A, Null + // '\x01' => RibirVirtualKeyCode::A, // Start of Heading + // '\x02' => RibirVirtualKeyCode::A, // Start of Text + // '\x03' => RibirVirtualKeyCode::A, // End of Text + // '\x04' => RibirVirtualKeyCode::A, // End of Transmission + // '\x05' => RibirVirtualKeyCode::A, // Enquiry + // '\x06' => RibirVirtualKeyCode::A, // Acknowledgement + // '\x07' => RibirVirtualKeyCode::A, // Bell + // '\x08' => RibirVirtualKeyCode::A, // Backspace + // '\x09' => RibirVirtualKeyCode::A, // Horizontlal Tab + // '\x0A' => RibirVirtualKeyCode::A, // Linefeed + // '\x0B' => RibirVirtualKeyCode::A, // Vertial Tab + // '\x0C' => RibirVirtualKeyCode::A, // Form Feed + // '\x0D' => RibirVirtualKeyCode::A, // Carriage Return + // '\x0E' => RibirVirtualKeyCode::A, // Shift Out + // '\x0F' => RibirVirtualKeyCode::A, // Shift In + // '\x10' => RibirVirtualKeyCode::A, // Data Link Escape + // '\x11' => RibirVirtualKeyCode::A, // Device Control 1 + // '\x12' => RibirVirtualKeyCode::A, // Device Control 2 + // '\x13' => RibirVirtualKeyCode::A, // Device Control 3 + // '\x14' => RibirVirtualKeyCode::A, // Device Control 4 + // '\x15' => RibirVirtualKeyCode::A, // Negative Acknowledgement + // '\x16' => RibirVirtualKeyCode::A, // Synchronous Idle + // '\x17' => RibirVirtualKeyCode::A, // End of Transmission Block + // '\x18' => RibirVirtualKeyCode::A, // Cancel + // '\x19' => RibirVirtualKeyCode::A, // End of Medium + // '\x1A' => RibirVirtualKeyCode::A, // Substitute + + // '\x1C' => RibirVirtualKeyCode::A, // File Separator + // '\x1D' => RibirVirtualKeyCode::A, // Group Separator + // '\x1E' => RibirVirtualKeyCode::A, // Record Separator + // '\x1F' => RibirVirtualKeyCode::A, // Unit Separator + '\x20' => Ok(RibirVirtualKeyCode::Space), // Space + // '\x21' => RibirVirtualKeyCode::A, // ! + // '\x22' => RibirVirtualKeyCode::A, // " + // '\x23' => RibirVirtualKeyCode::A, // # + // '\x24' => RibirVirtualKeyCode::A, // $ + // '\x25' => RibirVirtualKeyCode::A, // % + // '\x26' => RibirVirtualKeyCode::A, // & + '\x27' => Ok(RibirVirtualKeyCode::Apostrophe), // ' + // '\x28' => RibirVirtualKeyCode::A, // ( + // '\x29' => RibirVirtualKeyCode::A, // ) + '\x2A' => Ok(RibirVirtualKeyCode::Asterisk), // * + '\x2B' => Ok(RibirVirtualKeyCode::Plus), // + + '\x2C' => Ok(RibirVirtualKeyCode::Comma), // , + '\x2D' => Ok(RibirVirtualKeyCode::Minus), // - + // '\x2E' => RibirVirtualKeyCode::A, // . + '\x2F' => Ok(RibirVirtualKeyCode::Slash), // / + '\x30' => Ok(RibirVirtualKeyCode::Key0), // 0 + + '\x31' => Ok(RibirVirtualKeyCode::Key1), // 1 + '\x32' => Ok(RibirVirtualKeyCode::Key2), // 2 + '\x33' => Ok(RibirVirtualKeyCode::Key3), // 3 + '\x34' => Ok(RibirVirtualKeyCode::Key4), // 4 + '\x35' => Ok(RibirVirtualKeyCode::Key5), // 5 + '\x36' => Ok(RibirVirtualKeyCode::Key6), // 6 + '\x37' => Ok(RibirVirtualKeyCode::Key7), // 7 + '\x38' => Ok(RibirVirtualKeyCode::Key8), // 8 + '\x39' => Ok(RibirVirtualKeyCode::Key9), // 9 + '\x3A' => Ok(RibirVirtualKeyCode::Colon), // : + '\x3B' => Ok(RibirVirtualKeyCode::Semicolon), // ; + // '\x3C' => RibirVirtualKeyCode::A, // < + '\x3D' => Ok(RibirVirtualKeyCode::Equals), // = + // '\x3E' => RibirVirtualKeyCode::A, // > + // '\x3F' => RibirVirtualKeyCode::A, // ? + '\x40' => Ok(RibirVirtualKeyCode::Grave), // ` | @ + '\x41' => Ok(RibirVirtualKeyCode::A), // A + '\x42' => Ok(RibirVirtualKeyCode::B), // B + '\x43' => Ok(RibirVirtualKeyCode::C), // C + '\x44' => Ok(RibirVirtualKeyCode::D), // D + '\x45' => Ok(RibirVirtualKeyCode::E), // E + '\x46' => Ok(RibirVirtualKeyCode::F), // F + '\x47' => Ok(RibirVirtualKeyCode::G), // G + '\x48' => Ok(RibirVirtualKeyCode::H), // H + '\x49' => Ok(RibirVirtualKeyCode::I), // I + '\x4A' => Ok(RibirVirtualKeyCode::J), // J + '\x4B' => Ok(RibirVirtualKeyCode::K), // K + '\x4C' => Ok(RibirVirtualKeyCode::L), // L + '\x4D' => Ok(RibirVirtualKeyCode::M), // M + '\x4E' => Ok(RibirVirtualKeyCode::N), // N + '\x4F' => Ok(RibirVirtualKeyCode::O), // O + + '\x50' => Ok(RibirVirtualKeyCode::P), // P + '\x51' => Ok(RibirVirtualKeyCode::Q), // Q + '\x52' => Ok(RibirVirtualKeyCode::R), // R + '\x53' => Ok(RibirVirtualKeyCode::S), // S + '\x54' => Ok(RibirVirtualKeyCode::T), // T + '\x55' => Ok(RibirVirtualKeyCode::U), // U + '\x56' => Ok(RibirVirtualKeyCode::V), // V + '\x57' => Ok(RibirVirtualKeyCode::W), // W + '\x58' => Ok(RibirVirtualKeyCode::X), // X + '\x59' => Ok(RibirVirtualKeyCode::Y), // Y + '\x5A' => Ok(RibirVirtualKeyCode::Z), // Z + '\x5B' => Ok(RibirVirtualKeyCode::LBracket), // [ + '\x5C' => Ok(RibirVirtualKeyCode::Backslash), // \ + '\x5D' => Ok(RibirVirtualKeyCode::RBracket), // ] + '\x5E' => Ok(RibirVirtualKeyCode::Caret), // ^ + '\x5F' => Ok(RibirVirtualKeyCode::Underline), // _ + + '\x60' => Ok(RibirVirtualKeyCode::At), // @ | ` + '\x61' => Ok(RibirVirtualKeyCode::A), // a + '\x62' => Ok(RibirVirtualKeyCode::B), // b + '\x63' => Ok(RibirVirtualKeyCode::C), // c + '\x64' => Ok(RibirVirtualKeyCode::D), // d + '\x65' => Ok(RibirVirtualKeyCode::E), // e + '\x66' => Ok(RibirVirtualKeyCode::F), // f + '\x67' => Ok(RibirVirtualKeyCode::G), // g + '\x68' => Ok(RibirVirtualKeyCode::H), // h + '\x69' => Ok(RibirVirtualKeyCode::I), // i + '\x6A' => Ok(RibirVirtualKeyCode::J), // j + '\x6B' => Ok(RibirVirtualKeyCode::K), // k + '\x6C' => Ok(RibirVirtualKeyCode::L), // l + '\x6D' => Ok(RibirVirtualKeyCode::M), // m + '\x6E' => Ok(RibirVirtualKeyCode::N), // n + '\x6F' => Ok(RibirVirtualKeyCode::O), // o + + '\x70' => Ok(RibirVirtualKeyCode::P), // p + '\x71' => Ok(RibirVirtualKeyCode::Q), // q + '\x72' => Ok(RibirVirtualKeyCode::R), // r + '\x73' => Ok(RibirVirtualKeyCode::S), // s + '\x74' => Ok(RibirVirtualKeyCode::T), // t + '\x75' => Ok(RibirVirtualKeyCode::U), // u + '\x76' => Ok(RibirVirtualKeyCode::V), // v + '\x77' => Ok(RibirVirtualKeyCode::W), // w + '\x78' => Ok(RibirVirtualKeyCode::X), // x + '\x79' => Ok(RibirVirtualKeyCode::Y), // y + '\x7A' => Ok(RibirVirtualKeyCode::Z), // z + '\x7B' => Ok(RibirVirtualKeyCode::A), // { + '\x7C' => Ok(RibirVirtualKeyCode::A), // | + '\x7D' => Ok(RibirVirtualKeyCode::A), // } + '\x7E' => Ok(RibirVirtualKeyCode::A), // ~ + + other => Err(format!("Unsupported event code {other:?}")), + }, + + // CrosstermVirtualKeyCode::Snapshot => RibirVirtualKeyCode::Snapshot, + // CrosstermVirtualKeyCode::Scroll => RibirVirtualKeyCode::Scroll, + CrosstermVirtualKeyCode::Pause => Ok(RibirVirtualKeyCode::Pause), + + // CrosstermVirtualKeyCode::Compose => RibirVirtualKeyCode::Compose, + CrosstermVirtualKeyCode::NumLock => Ok(RibirVirtualKeyCode::Numlock), + // CrosstermVirtualKeyCode::Numpad0 => RibirVirtualKeyCode::Numpad0, + // CrosstermVirtualKeyCode::Numpad1 => RibirVirtualKeyCode::Numpad1, + // CrosstermVirtualKeyCode::Numpad2 => RibirVirtualKeyCode::Numpad2, + // CrosstermVirtualKeyCode::Numpad3 => RibirVirtualKeyCode::Numpad3, + // CrosstermVirtualKeyCode::Numpad4 => RibirVirtualKeyCode::Numpad4, + // CrosstermVirtualKeyCode::Numpad5 => RibirVirtualKeyCode::Numpad5, + // CrosstermVirtualKeyCode::Numpad6 => RibirVirtualKeyCode::Numpad6, + // CrosstermVirtualKeyCode::Numpad7 => RibirVirtualKeyCode::Numpad7, + // CrosstermVirtualKeyCode::Numpad8 => RibirVirtualKeyCode::Numpad8, + // CrosstermVirtualKeyCode::Numpad9 => RibirVirtualKeyCode::Numpad9, + // CrosstermVirtualKeyCode::NumpadAdd => RibirVirtualKeyCode::NumpadAdd, + // CrosstermVirtualKeyCode::NumpadDivide => RibirVirtualKeyCode::NumpadDivide, + // CrosstermVirtualKeyCode::NumpadDecimal => RibirVirtualKeyCode::NumpadDecimal, + // CrosstermVirtualKeyCode::NumpadComma => RibirVirtualKeyCode::NumpadComma, + // CrosstermVirtualKeyCode::NumpadEnter => RibirVirtualKeyCode::NumpadEnter, + // CrosstermVirtualKeyCode::NumpadEquals => RibirVirtualKeyCode::NumpadEquals, + // CrosstermVirtualKeyCode::NumpadMultiply => RibirVirtualKeyCode::NumpadMultiply, + // CrosstermVirtualKeyCode::NumpadSubtract => RibirVirtualKeyCode::NumpadSubtract, + + // CrosstermVirtualKeyCode::AbntC1 => RibirVirtualKeyCode::AbntC1, + // CrosstermVirtualKeyCode::AbntC2 => RibirVirtualKeyCode::AbntC2, + // CrosstermVirtualKeyCode::Apps => RibirVirtualKeyCode::Apps, + // CrosstermVirtualKeyCode::Ax => RibirVirtualKeyCode::Ax, + // CrosstermVirtualKeyCode::Calculator => RibirVirtualKeyCode::Calculator, + // CrosstermVirtualKeyCode::Capital => RibirVirtualKeyCode::Capital, + // CrosstermVirtualKeyCode::Convert => RibirVirtualKeyCode::Convert, + // CrosstermVirtualKeyCode::Kana => RibirVirtualKeyCode::Kana, + // CrosstermVirtualKeyCode::Kanji => RibirVirtualKeyCode::Kanji, + // CrosstermVirtualKeyCode::LAlt => RibirVirtualKeyCode::LAlt, + // CrosstermVirtualKeyCode::LControl => RibirVirtualKeyCode::LControl, + // CrosstermVirtualKeyCode::LShift => RibirVirtualKeyCode::LShift, + // CrosstermVirtualKeyCode::LWin => RibirVirtualKeyCode::LWin, + // CrosstermVirtualKeyCode::Mail => RibirVirtualKeyCode::Mail, + // CrosstermVirtualKeyCode::MediaSelect => RibirVirtualKeyCode::MediaSelect, + // CrosstermVirtualKeyCode::MediaStop => RibirVirtualKeyCode::MediaStop, + // CrosstermVirtualKeyCode::Mute => RibirVirtualKeyCode::Mute, + // CrosstermVirtualKeyCode::MyComputer => RibirVirtualKeyCode::MyComputer, + // CrosstermVirtualKeyCode::NavigateForward => RibirVirtualKeyCode::NavigateForward, + // CrosstermVirtualKeyCode::NavigateBackward => RibirVirtualKeyCode::NavigateBackward, + // CrosstermVirtualKeyCode::NextTrack => RibirVirtualKeyCode::NextTrack, + // CrosstermVirtualKeyCode::NoConvert => RibirVirtualKeyCode::NoConvert, + // CrosstermVirtualKeyCode::OEM102 => RibirVirtualKeyCode::OEM102, + // CrosstermVirtualKeyCode::Period => RibirVirtualKeyCode::Period, + // CrosstermVirtualKeyCode::PlayPause => RibirVirtualKeyCode::PlayPause, + // CrosstermVirtualKeyCode::Power => RibirVirtualKeyCode::Power, + // CrosstermVirtualKeyCode::PrevTrack => RibirVirtualKeyCode::PrevTrack, + // CrosstermVirtualKeyCode::RAlt => RibirVirtualKeyCode::RAlt, + // CrosstermVirtualKeyCode::RControl => RibirVirtualKeyCode::RControl, + // CrosstermVirtualKeyCode::RShift => RibirVirtualKeyCode::RShift, + // CrosstermVirtualKeyCode::RWin => RibirVirtualKeyCode::RWin, + // CrosstermVirtualKeyCode::Sleep => RibirVirtualKeyCode::Sleep, + // CrosstermVirtualKeyCode::Stop => RibirVirtualKeyCode::Stop, + // CrosstermVirtualKeyCode::Sysrq => RibirVirtualKeyCode::Sysrq, + + // CrosstermVirtualKeyCode::Unlabeled => RibirVirtualKeyCode::Unlabeled, + // CrosstermVirtualKeyCode::VolumeDown => RibirVirtualKeyCode::VolumeDown, + // CrosstermVirtualKeyCode::VolumeUp => RibirVirtualKeyCode::VolumeUp, + // CrosstermVirtualKeyCode::Wake => RibirVirtualKeyCode::Wake, + // CrosstermVirtualKeyCode::WebBack => RibirVirtualKeyCode::WebBack, + // CrosstermVirtualKeyCode::WebFavorites => RibirVirtualKeyCode::WebFavorites, + // CrosstermVirtualKeyCode::WebForward => RibirVirtualKeyCode::WebForward, + // CrosstermVirtualKeyCode::WebHome => RibirVirtualKeyCode::WebHome, + // CrosstermVirtualKeyCode::WebRefresh => RibirVirtualKeyCode::WebRefresh, + // CrosstermVirtualKeyCode::WebSearch => RibirVirtualKeyCode::WebSearch, + // CrosstermVirtualKeyCode::WebStop => RibirVirtualKeyCode::WebStop, + // CrosstermVirtualKeyCode::Yen => RibirVirtualKeyCode::Yen, + // CrosstermVirtualKeyCode::Copy => RibirVirtualKeyCode::Copy, + // CrosstermVirtualKeyCode::Paste => RibirVirtualKeyCode::Paste, + // CrosstermVirtualKeyCode::Cut => RibirVirtualKeyCode::Cut, + other => Err(format!("Unsupported event code {other:?}")), + } + } +} diff --git a/crossterm/src/from_window.rs b/crossterm/src/from_window.rs new file mode 100644 index 000000000..3d5647681 --- /dev/null +++ b/crossterm/src/from_window.rs @@ -0,0 +1,121 @@ +use std::any::Any; + +use ribir_core::{ + prelude::{CursorIcon, Point, Size}, + window::{RawWindow as RibirRawWindow, WindowId}, +}; + +use crate::prelude::CrosstermWindowId; + +pub struct CrosstermWindow { + id: CrosstermWindowId, +} + +impl CrosstermWindow { + pub fn new(id: CrosstermWindowId) -> Self { Self { id } } + + pub fn request_redraw(&self) { + println!("request_redraw"); + } + + pub fn id(&self) -> CrosstermWindowId { self.id } +} + +// #[derive(PartialEq, Eq)] +// pub struct WrappedWindow(CrosstermWindow); + +impl RibirRawWindow for CrosstermWindow { + fn inner_size(&self) -> Size { + // WrappedLogicalSize::::from(self.0.inner_size().to_logical(self. + // scale_factor())).into() + Size::new(100., 100.) + // let size = ScreenBuffer::current()?.info()?.terminal_size(); + } + + fn set_inner_size(&mut self, _size: Size) { + // self.0.set_inner_size( + // CrosstermLogicalSize::::new(size.width.cast(), size.height.cast()) + // .to_physical::(self.scale_factor()), + // ); + } + + fn outer_size(&self) -> Size { + // WrappedLogicalSize::::from(self.0.outer_size().to_logical(self. + // scale_factor())).into() + Size::new(0., 0.) + } + + fn inner_position(&self) -> Point { + // WrappedLogicalPosition::::from( + // self + // .0 + // .inner_position() + // .expect(" Can only be called on the main thread") + // .to_logical(self.scale_factor()), + // ) + // .into() + Point::new(0., 0.) + } + + fn outer_position(&self) -> Point { + // WrappedLogicalPosition::::from( + // self + // .0 + // .outer_position() + // .expect(" Can only be called on the main thread") + // .to_logical(self.scale_factor()), + // ) + // .into() + Point::new(0., 0.) + } + + fn id(&self) -> Box { Box::new(self.id()) } + + fn request_redraw(&self) { self.request_redraw(); } + + fn set_cursor(&mut self, _cursor: CursorIcon) { + // self + // .0 + // .set_cursor_icon(WrappedCursorIcon::from(cursor).into()); + } + + fn scale_factor(&self) -> f64 { + // self.0.scale_factor() + 1.0 + } + + fn into_any(self: Box) -> Box { self } +} + +// impl From for CrosstermWindow { +// fn from(value: CrosstermWindow) -> Self { WrappedWindow(value) } +// } + +// impl From for CrosstermWindow { +// fn from(val: WrappedWindow) -> Self { val.0 } +// } + +impl From> for CrosstermWindow { + fn from(value: Box) -> Self { + *value.into_any().downcast::().unwrap() + } +} + +#[cfg(test)] +mod tests { + // use std::io::stdout; + + // use crate::prelude::CrosstermWindowId; + + // use super::CrosstermWindow; + + #[test] + fn boxed_raw_window_into_crossterm_window() { + // let boxed_raw_window = CrosstermWindow::new( + // CrosstermWindowId::zero(), + // // Box::new(stdout()), //.into_raw_mode().unwrap(), + // ); + + // let crossterm_window: CrosstermWindow = boxed_raw_window.into(); + } +} diff --git a/crossterm/src/from_window_id.rs b/crossterm/src/from_window_id.rs new file mode 100644 index 000000000..349b0883a --- /dev/null +++ b/crossterm/src/from_window_id.rs @@ -0,0 +1,31 @@ +use std::any::Any; + +use ribir_core::window::WindowId as RibirWindowId; + +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] +pub struct CrosstermWindowId(usize); + +impl CrosstermWindowId { + pub fn zero() -> CrosstermWindowId { CrosstermWindowId(0) } +} + +impl RibirWindowId for CrosstermWindowId { + fn into_any(self: Box) -> Box { self } + fn equals(&self, other: &Box) -> bool { + self.0 + == other + .box_clone() + .into_any() + .downcast::() + .unwrap() + .0 + } + + fn box_clone(&self) -> Box { Box::new(*self) } +} + +impl From> for CrosstermWindowId { + fn from(value: Box) -> Self { + *value.into_any().downcast::().unwrap() + } +} diff --git a/crossterm/src/lib.rs b/crossterm/src/lib.rs new file mode 100644 index 000000000..3c41001c7 --- /dev/null +++ b/crossterm/src/lib.rs @@ -0,0 +1,51 @@ +#![feature(test, decl_macro, box_into_inner)] + +// mod from_cursor_icon; +mod from_device_id; +mod from_element_state; +mod from_event; +mod from_keyboard_input; +mod from_modifiers; +mod from_mouse; +// mod from_mouse_scroll_delta; +// mod from_size; +// mod from_touch_phase; +mod from_virtual_key_code; +mod from_window; +mod from_window_id; +mod shell_window; +mod window_builder; + +pub mod prelude { + #[doc(no_inline)] + // #[doc(no_inline)] + // pub use crate::from_cursor_icon::*; + #[doc(no_inline)] + pub use crate::from_device_id::*; + #[doc(no_inline)] + pub use crate::from_element_state::*; + #[doc(no_inline)] + pub use crate::from_event::*; + #[doc(no_inline)] + pub use crate::from_keyboard_input::*; + #[doc(no_inline)] + pub use crate::from_modifiers::*; + #[doc(no_inline)] + pub use crate::from_mouse::*; + // #[doc(no_inline)] + // pub use crate::from_mouse_scroll_delta::*; + // #[doc(no_inline)] + // pub use crate::from_size::*; + // #[doc(no_inline)] + // pub use crate::from_touch_phase::*; + #[doc(no_inline)] + pub use crate::from_virtual_key_code::*; + #[doc(no_inline)] + pub use crate::from_window::*; + #[doc(no_inline)] + pub use crate::from_window_id::*; + #[doc(no_inline)] + pub use crate::shell_window::*; + #[doc(no_inline)] + pub use crate::window_builder::*; +} diff --git a/crossterm/src/shell_window.rs b/crossterm/src/shell_window.rs new file mode 100644 index 000000000..cc75065e5 --- /dev/null +++ b/crossterm/src/shell_window.rs @@ -0,0 +1,151 @@ +use crossterm::event::{poll, read}; + +use crate::{from_window_id::CrosstermWindowId, prelude::WrappedWindowEvent}; + +use ribir_core::{ + prelude::{AppContext, Theme}, + window::{ShellWindow, Window, WindowId as RibirWindowId}, +}; + +use std::{collections::HashMap, marker::PhantomData, rc::Rc, time::Duration}; + +#[derive(Default)] +pub struct EventLoop { + _pd: PhantomData, +} + +impl EventLoop { + fn new() -> Self { EventLoop::default() } +} + +// struct ControlFlow {} + +pub struct PlatformShellWindow { + windows: HashMap, + ctx: AppContext, + event_loop: EventLoop<()>, +} + +impl PlatformShellWindow { + #[inline] + pub fn new(theme: Theme) -> Self { + // todo: theme can provide fonts to load. + let ctx = AppContext { + app_theme: Rc::new(theme), + ..Default::default() + }; + Self { ctx, ..Default::default() } + } + + pub fn context(&self) -> &AppContext { &self.ctx } + + #[inline] + pub fn event_loop(&self) -> &EventLoop<()> { &self.event_loop } +} + +impl ShellWindow for PlatformShellWindow { + #[inline] + fn set_theme(mut self, theme: Theme) { self.ctx.app_theme = Rc::new(theme); } + + #[inline] + fn context(&self) -> &AppContext { &self.ctx } + + fn exec(self, wnd_id: Box) { + println!("exec"); + let Self { mut windows /* event_loop, */, .. } = self; + + if let Some(wnd) = windows.get_mut(&CrosstermWindowId::from(wnd_id.clone())) { + wnd.draw_frame(); + } + + loop { + // `poll()` waits for an `Event` for a given time period + match poll(Duration::from_millis(100)) { + Ok(true) => { + // println!("poll"); + // It's guaranteed that the `read()` won't block when the `poll()` + // function returns `true` + if let Ok(event) = read() { + let evt = CrosstermWindowId::from(wnd_id.clone()); + // println!("Event {evt:?}"); + if let Some(wnd) = windows.get_mut(&evt) { + // println!("=== process event {event:?} ==="); + wnd.processes_native_event(WrappedWindowEvent::from(event).into()); + wnd.draw_frame(); + } else { + println!("process event no window"); + } + } + } + Ok(false) => { + // if let Some(wnd) = + // windows.get_mut(&CrosstermWindowId::from(wnd_id.clone())) { + // wnd.draw_frame(); + // } + } + _ => {} + } + } + + // event_loop.run_return(move |event, _event_loop, control: &mut + // ControlFlow| { *control = ControlFlow::Wait; + + // match event { + // Event::WindowEvent { event, window_id } => { + // if event == WindowEvent::CloseRequested { + // windows.remove(&window_id); + // } else if event == WindowEvent::Destroyed { + // if windows.is_empty() { + // *control = ControlFlow::Exit; + // } + // } else if let Some(wnd) = windows.get_mut(&window_id) { + // wnd.processes_native_event(WrappedWindowEvent::from(event). + // into()); } + // } + // Event::MainEventsCleared => windows.iter_mut().for_each(|(_, wnd)| { + // if wnd.need_draw() { + // wnd.request_redraw(); + // } + // }), + // Event::RedrawRequested(id) => { + // if let Some(wnd) = windows.get_mut(&id) { + // wnd.draw_frame(); + // } + // } + // Event::RedrawEventsCleared => { + // if windows.iter_mut().any(|(_, wnd)| wnd.need_draw()) { + // *control = ControlFlow::Poll; + // } + // } + // _ => (), + // } + // }); + } + + fn add_window(&mut self, wnd: Window) -> Box { + let id = wnd.raw_window.id(); + self + .windows + .insert(CrosstermWindowId::from(id.clone()), wnd); + + id + } +} + +impl Default for PlatformShellWindow { + fn default() -> Self { + Self { + windows: Default::default(), + event_loop: EventLoop::new(), + ctx: <_>::default(), + } + } +} + +#[cfg(test)] +mod tests { + #[test] + fn test() { + // let x = WinitApplication::new(); + } +} diff --git a/crossterm/src/window_builder.rs b/crossterm/src/window_builder.rs new file mode 100644 index 000000000..f979799ea --- /dev/null +++ b/crossterm/src/window_builder.rs @@ -0,0 +1,97 @@ +use crossterm::{ + cursor::{Hide, MoveTo, Show}, + event::EnableMouseCapture, + execute, queue, + style::Print, + terminal::{self, EnterAlternateScreen, LeaveAlternateScreen}, +}; +use ribir_core::{ + widget::Widget, + window::{Window as RibirWindow, WindowConfig}, +}; +use ribir_painter::PainterBackend; +use std::io::{stdout, Write}; + +use ribir_geometry::DeviceSize; + +use crate::from_window::CrosstermWindow; +use crate::prelude::{CrosstermWindowId, PlatformShellWindow}; + +struct CrosstermBackend { + write: Box, +} + +impl CrosstermBackend { + fn new(mut write: Box) -> Self { + let _ = execute!(write, EnterAlternateScreen, Hide); //"PainterBackend commands_to_image"); + let _ = execute!(write, EnableMouseCapture); + let _ = terminal::enable_raw_mode(); + CrosstermBackend { write } + } +} + +impl Drop for CrosstermBackend { + fn drop(&mut self) { + println!("CrosstermBackend dropped"); + let _ = execute!(self.write, Show, LeaveAlternateScreen); // restore the cursor and leave the alternate screen + let _ = terminal::disable_raw_mode(); + } +} + +impl PainterBackend for CrosstermBackend { + fn submit(&mut self, commands: Vec) { + if !commands.is_empty() { + println!("PainterBackend submit {:?}", commands.len()); + for c in commands { + println!("Command {c:?}"); + } + } + match self.write.flush() { + Ok(()) => (), + Err(err) => println!("PainterBackend submit {err:?}"), + } + } + + fn commands_to_image( + &mut self, + commands: Vec, + _capture: ribir_painter::CaptureCallback, + ) -> Result<(), Box> { + println!("PainterBackend commands_to_image {:?}", commands.len()); + queue!(self.write, EnterAlternateScreen, Hide)?; //"PainterBackend commands_to_image"); + queue!( + self.write, + MoveTo(1, 1), + Print("PainterBackend commands_to_image") + )?; //"PainterBackend commands_to_image"); + println!("PainterBackend commands_to_image"); + Ok(()) + } + + fn resize(&mut self, size: DeviceSize) { + println!("PainterBackend resize {size:?}"); + } +} + +pub struct WindowBuilder { + root: Widget, +} + +impl WindowBuilder { + #[inline] + pub fn new(root: Widget, _config: WindowConfig) -> WindowBuilder { + WindowBuilder { + root, + // inner_builder: winit::window::WindowBuilder::default(), + } + // TODO(zoechi) apply config + } + + #[inline] + pub fn build(self, shell_window: &PlatformShellWindow) -> RibirWindow { + let native_wnd = CrosstermWindow::new(CrosstermWindowId::zero()); + let ctx = shell_window.context().clone(); + let p_backend = CrosstermBackend::new(Box::new(stdout())); + RibirWindow::new(native_wnd, p_backend, self.root, ctx) + } +} diff --git a/painter/src/painter.rs b/painter/src/painter.rs index 0583f9202..2b9395b04 100644 --- a/painter/src/painter.rs +++ b/painter/src/painter.rs @@ -42,7 +42,7 @@ pub trait PainterBackend { fn resize(&mut self, size: DeviceSize); } -#[derive(Clone)] +#[derive(Debug, Clone)] pub enum PaintPath { Path(Resource), Text { @@ -54,7 +54,7 @@ pub enum PaintPath { // todo: need a way to batch commands as a single resource. so we can cache // their vertexes as a whole. useful for svg, animation and paint layers. -#[derive(Clone)] +#[derive(Debug, Clone)] pub struct PaintInstruct { pub opacity: f32, pub path: PaintPath, @@ -62,13 +62,13 @@ pub struct PaintInstruct { pub brush: Brush, } -#[derive(Clone)] +#[derive(Debug, Clone)] pub struct ClipInstruct { pub path: PaintPath, pub transform: Transform, } -#[derive(Clone)] +#[derive(Debug, Clone)] pub enum PaintCommand { Paint(PaintInstruct), PushClip(ClipInstruct), diff --git a/ribir/Cargo.toml b/ribir/Cargo.toml index 6a97cbfe4..41551058c 100644 --- a/ribir/Cargo.toml +++ b/ribir/Cargo.toml @@ -27,5 +27,7 @@ ribir_winit = {path = "../winit", version = "*"} env_logger = "0.7.1" [features] -default = ["wgpu_gl"] +# default = ["winit", "wgpu_gl"] wgpu_gl = ["ribir_gpu/wgpu_gl"] +winit = ["ribir_app/winit"] +crossterm = ["ribir_app/crossterm"] diff --git a/ribir/examples/todo_mvp.rs b/ribir/examples/todo_mvp.rs index f73e2eebf..4126d693f 100644 --- a/ribir/examples/todo_mvp.rs +++ b/ribir/examples/todo_mvp.rs @@ -1,7 +1,4 @@ -use ribir::{ - prelude::{svgs, *}, - WindowBuilder, WinitApplication, -}; +use ribir::prelude::{svgs, *}; use std::time::Duration; #[derive(Debug, Clone, PartialEq)] @@ -160,7 +157,11 @@ impl TodoMVP { } } +#[cfg(any(feature = "crossterm", feature = "winit"))] fn main() { + use ribir::Application; + use ribir_core::window::WindowConfig; + env_logger::init(); let todo = TodoMVP { @@ -183,10 +184,24 @@ fn main() { ], }; - let app = WinitApplication::new(material::purple::light()); - let wnd = WindowBuilder::new(todo.into_widget()) - .with_inner_size(Size::new(400., 640.)) - .with_title("todo") - .build(&app); - app::run_with_window(app, wnd); + let mut app = Application::new(material::purple::light()); + + let window_builder = app.window_builder( + todo.into_widget(), + WindowConfig { + inner_size: Some(Size::new(400., 640.)), + title: Some("todo".to_owned()), + ..Default::default() + }, + ); + + let window_id = app.build_window(window_builder); + app.exec(window_id); +} + +#[cfg(all(not(feature = "crossterm"), not(feature = "winit")))] +fn main() { + println!( + "The todo_mvp example is currently only implemented for the Winit and Crossterm platform" + ); } diff --git a/ribir/src/lib.rs b/ribir/src/lib.rs index 501aeac32..eef11796e 100644 --- a/ribir/src/lib.rs +++ b/ribir/src/lib.rs @@ -1,4 +1,3 @@ -// pub use ribir_core as core; pub use ribir_app::prelude::*; pub use ribir_winit::prelude::*; @@ -6,44 +5,4 @@ pub use ribir_widgets as widgets; pub mod prelude { pub use ribir_core::prelude::*; pub use ribir_widgets::prelude::*; - pub mod app { - use ribir_core::window::Window; - - #[cfg(feature = "wgpu_gl")] - pub fn run(root: super::Widget) { - use ribir_winit::prelude::{WindowBuilder, WinitApplication}; - - let app = WinitApplication::new(super::material::purple::light()); - let wnd = WindowBuilder::new(root).build(&app); - run_with_window(app, wnd); - } - - #[cfg(feature = "wgpu_gl")] - pub fn run_with_window(mut app: ribir_winit::prelude::WinitApplication, wnd: Window) { - println!("WindowId: {:?}", wnd.raw_window.id()); - let wnd_id = app.add_window(wnd); - println!("WindowId: {wnd_id:?}"); - app.exec(wnd_id); - } - } -} - -use prelude::*; -#[cfg(feature = "wgpu_gl")] -pub fn wgpu_headless_wnd(root: Widget, ctx: AppContext, size: DeviceSize) -> Window { - let p_backend = AppContext::wait_future(ribir_gpu::wgpu_backend_headless( - size, - None, - None, - ctx.shaper.clone(), - )); - Window::new( - ribir_core::window::MockRawWindow { - size: Size::from_untyped(size.to_f32().to_untyped()), - ..Default::default() - }, - p_backend, - root, - ctx, - ) } diff --git a/winit/Cargo.toml b/winit/Cargo.toml index 1a0b6c9c9..1f0a68b4e 100644 --- a/winit/Cargo.toml +++ b/winit/Cargo.toml @@ -1,13 +1,12 @@ [package] name = "ribir_winit" -version = "0.1.0" +version = "0.0.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] log = "0.4.8" -ribir_app = { path = "../app" } ribir_core = { path = "../core" } ribir_geometry = { path = "../geometry" } ribir_gpu = {path = "../gpu"} diff --git a/winit/src/from_device_id.rs b/winit/src/from_device_id.rs index d057d7bc4..07171ea1d 100644 --- a/winit/src/from_device_id.rs +++ b/winit/src/from_device_id.rs @@ -41,14 +41,3 @@ impl From<&Box> for WrappedPointerId { .unwrap()) } } - -// impl From<&dyn RibirPointerId> for WrappedPointerId { -// fn from(value: &dyn RibirPointerId) -> Self { -// let x = value -// .as_any() -// .downcast_ref::() -// .map(|v| v.to_owned()) -// .unwrap(); -// x.into() -// } -// } diff --git a/winit/src/from_window.rs b/winit/src/from_window.rs index c3d5c5089..d074f0ded 100644 --- a/winit/src/from_window.rs +++ b/winit/src/from_window.rs @@ -65,7 +65,7 @@ impl RibirRawWindow for WrappedWindow { fn scale_factor(&self) -> f64 { self.0.scale_factor() } - fn as_any(&self) -> &dyn Any { self } + fn into_any(self: Box) -> Box { self } } impl From for WrappedWindow { diff --git a/winit/src/lib.rs b/winit/src/lib.rs index c32e116b8..4f0761c0e 100644 --- a/winit/src/lib.rs +++ b/winit/src/lib.rs @@ -1,6 +1,5 @@ #![feature(test, decl_macro, box_into_inner)] -mod application; mod from_cursor_icon; mod from_device_id; mod from_element_state; @@ -14,11 +13,10 @@ mod from_touch_phase; mod from_virtual_key_code; mod from_window; mod from_window_id; +mod shell_window; mod window_builder; pub mod prelude { - #[doc(no_inline)] - pub use crate::application::*; #[doc(no_inline)] pub use crate::from_cursor_icon::*; #[doc(no_inline)] @@ -46,5 +44,7 @@ pub mod prelude { #[doc(no_inline)] pub use crate::from_window_id::*; #[doc(no_inline)] + pub use crate::shell_window::*; + #[doc(no_inline)] pub use crate::window_builder::*; } diff --git a/winit/src/application.rs b/winit/src/shell_window.rs similarity index 83% rename from winit/src/application.rs rename to winit/src/shell_window.rs index 061ff92b3..b3813a7bf 100644 --- a/winit/src/application.rs +++ b/winit/src/shell_window.rs @@ -1,4 +1,3 @@ -// use ribir_app::prelude::*; use ribir_core::prelude::*; use std::{collections::HashMap, rc::Rc}; @@ -12,13 +11,13 @@ use winit::{ use crate::{from_event::WrappedWindowEvent, prelude::WrappedWindowId}; use ribir_core::window::WindowId as RibirWindowId; -pub struct WinitApplication { +pub struct PlatformShellWindow { windows: HashMap, ctx: AppContext, event_loop: EventLoop<()>, } -impl WinitApplication { +impl PlatformShellWindow { #[inline] pub fn new(theme: Theme) -> Self { // todo: theme can provide fonts to load. @@ -29,18 +28,17 @@ impl WinitApplication { Self { ctx, ..Default::default() } } - #[inline] - pub fn with_theme(mut self, theme: Theme) -> Self { - self.ctx.app_theme = Rc::new(theme); - self - } + pub fn event_loop(&self) -> &EventLoop<()> { &self.event_loop } +} +impl ShellWindow for PlatformShellWindow { #[inline] - pub fn context(&self) -> &AppContext { &self.ctx } + fn set_theme(mut self, theme: Theme) { self.ctx.app_theme = Rc::new(theme); } - pub fn event_loop(&self) -> &EventLoop<()> { &self.event_loop } + #[inline] + fn context(&self) -> &AppContext { &self.ctx } - pub fn exec(mut self, wnd_id: Box) { + fn exec(mut self, wnd_id: Box) { if let Some(wnd) = self.windows.get_mut(&WrappedWindowId::from(wnd_id).into()) { wnd.draw_frame(); } else { @@ -83,7 +81,7 @@ impl WinitApplication { }); } - pub fn add_window(&mut self, wnd: Window) -> Box { + fn add_window(&mut self, wnd: Window) -> Box { let id = wnd.raw_window.id(); self .windows @@ -93,7 +91,7 @@ impl WinitApplication { } } -impl Default for WinitApplication { +impl Default for PlatformShellWindow { fn default() -> Self { Self { windows: Default::default(), @@ -103,4 +101,10 @@ impl Default for WinitApplication { } } -// impl Application for WinitApplication {} +#[cfg(test)] +mod tests { + #[test] + fn test() { + // let x = WinitApplication::new(); + } +} diff --git a/winit/src/window_builder.rs b/winit/src/window_builder.rs index 149c63e55..31e60c050 100644 --- a/winit/src/window_builder.rs +++ b/winit/src/window_builder.rs @@ -1,9 +1,14 @@ -use ribir_core::{prelude::AppContext, widget::Widget, window::Window as RibirWindow}; -use ribir_geometry::{DeviceSize, Point, Size}; +use ribir_core::{ + prelude::AppContext, + widget::Widget, + window::WindowConfig, + window::{ShellWindow, Window as RibirWindow}, +}; +use ribir_geometry::DeviceSize; use crate::{ - application::WinitApplication, - prelude::{WrappedPhysicalSize, WrappedWindow}, + prelude::{WrappedLogicalPosition, WrappedLogicalSize, WrappedPhysicalSize, WrappedWindow}, + shell_window::PlatformShellWindow, }; pub struct WindowBuilder { @@ -13,105 +18,87 @@ pub struct WindowBuilder { impl WindowBuilder { #[inline] - pub fn new(root: Widget) -> WindowBuilder { - WindowBuilder { - root, - inner_builder: winit::window::WindowBuilder::default(), + pub fn new(root_widget: Widget, config: WindowConfig) -> WindowBuilder { + let mut inner_builder = winit::window::WindowBuilder::default(); + + if let Some(size) = config.inner_size { + let size: winit::dpi::LogicalSize = WrappedLogicalSize::from(size).into(); + inner_builder = inner_builder.with_inner_size(size); } - } - #[inline] - pub fn build(self, app: &WinitApplication) -> RibirWindow { - let native_wnd = self.inner_builder.build(app.event_loop()).unwrap(); - let size: DeviceSize = WrappedPhysicalSize::::from(native_wnd.inner_size()).into(); - let ctx = app.context().clone(); - let p_backend = AppContext::wait_future(ribir_gpu::wgpu_backend_with_wnd( - &native_wnd, - size, - None, - None, - ctx.shaper.clone(), - )); - RibirWindow::new(WrappedWindow::from(native_wnd), p_backend, self.root, ctx) - } + if let Some(size) = config.min_inner_size { + let size: winit::dpi::LogicalSize = WrappedLogicalSize::from(size).into(); + inner_builder = inner_builder.with_min_inner_size(size); + } - /// Requests the window to be of specific dimensions. - #[inline] - pub fn with_inner_size(mut self, size: Size) -> Self { - let size = winit::dpi::LogicalSize::new(size.width, size.height); - self.inner_builder = self.inner_builder.with_inner_size(size); - self - } + if let Some(size) = config.max_inner_size { + let size: winit::dpi::LogicalSize = WrappedLogicalSize::from(size).into(); + inner_builder = inner_builder.with_max_inner_size(size); + } - /// Sets a minimum dimension size for the window. - #[inline] - pub fn with_min_inner_size(mut self, min_size: Size) -> Self { - let size = winit::dpi::LogicalSize::new(min_size.width, min_size.height); - self.inner_builder = self.inner_builder.with_min_inner_size(size); - self - } + if let Some(position) = config.position { + let position: winit::dpi::LogicalPosition = + WrappedLogicalPosition::from(position).into(); + inner_builder = inner_builder.with_position(position); + } - /// Sets a maximum dimension size for the window. - #[inline] - pub fn with_max_inner_size(mut self, max_size: Size) -> Self { - let size = winit::dpi::LogicalSize::new(max_size.width, max_size.height); - self.inner_builder = self.inner_builder.with_max_inner_size(size); - self - } + if let Some(resizable) = config.resizable { + inner_builder = inner_builder.with_resizable(resizable); + } - /// Sets a desired initial position for the window. - #[inline] - pub fn with_position(mut self, position: Point) -> Self { - let position = winit::dpi::LogicalPosition::new(position.x, position.y); - self.inner_builder = self.inner_builder.with_position(position); - self - } + if let Some(title) = config.title { + inner_builder = inner_builder.with_title(title); + } - /// Sets whether the window is resizable or not. - #[inline] - pub fn with_resizable(mut self, resizable: bool) -> Self { - self.inner_builder = self.inner_builder.with_resizable(resizable); - self - } + if let Some(maximized) = config.resizable { + inner_builder = inner_builder.with_maximized(maximized); + } - /// Requests a specific title for the window. - #[inline] - pub fn with_title>(mut self, title: T) -> Self { - self.inner_builder = self.inner_builder.with_title(title); - self - } + if let Some(visible) = config.resizable { + inner_builder = inner_builder.with_visible(visible); + } - /// Requests maximized mode. - #[inline] - pub fn with_maximized(mut self, maximized: bool) -> Self { - self.inner_builder = self.inner_builder.with_maximized(maximized); - self - } + if let Some(transparent) = config.transparent { + inner_builder = inner_builder.with_visible(transparent); + } - /// Sets whether the window will be initially hidden or visible. - #[inline] - pub fn with_visible(mut self, visible: bool) -> Self { - self.inner_builder = self.inner_builder.with_visible(visible); - self + if let Some(decorations) = config.decorations { + inner_builder = inner_builder.with_visible(decorations); + } + + // if let Some(window_icon) = config.window_icon { + // inner_builder = inner_builder.with_window_icon(window_icon); + // } + + WindowBuilder { root: root_widget, inner_builder } } - /// Sets whether the background of the window should be transparent. - #[inline] - pub fn with_transparent(mut self, transparent: bool) -> Self { - self.inner_builder = self.inner_builder.with_transparent(transparent); - self + pub fn build(self, shell_window: &PlatformShellWindow) -> RibirWindow { + let native_wnd = self.inner_builder.build(shell_window.event_loop()).unwrap(); + let size: DeviceSize = WrappedPhysicalSize::::from(native_wnd.inner_size()).into(); + let ctx = shell_window.context().clone(); + let p_backend = AppContext::wait_future(ribir_gpu::wgpu_backend_with_wnd( + &native_wnd, + size, + None, + None, + ctx.shaper.clone(), + )); + RibirWindow::new(WrappedWindow::from(native_wnd), p_backend, self.root, ctx) } - /// Sets whether the window should have a border, a title bar, etc. + #[cfg(feature = "wgpu_gl")] #[inline] - pub fn with_decorations(mut self, decorations: bool) -> Self { - self.inner_builder = self.inner_builder.with_decorations(decorations); - self + pub fn build_headless(self, shell_window: &PlatformShellWindow, size: DeviceSize) -> RibirWindow { + let native_wnd = self.inner_builder.build(shell_window.event_loop()).unwrap(); + let ctx = shell_window.context().clone(); + let p_backend = AppContext::wait_future(ribir_gpu::wgpu_backend_with_wnd( + &native_wnd, + size, + None, + None, + ctx.shaper.clone(), + )); + RibirWindow::new(WrappedWindow::from(native_wnd), p_backend, self.root, ctx) } - - // /// Sets the window icon. - // #[inline] - // pub fn with_window_icon(mut self, window_icon:Option) - // // -> Self { self.inner_builder = self.inner_builder. - // with_window_icon(window_icon); self } } From 1310d86de90bdc43f5d587537a90b16e82ca5da8 Mon Sep 17 00:00:00 2001 From: Guenter Zoechbauer Date: Wed, 22 Mar 2023 09:03:42 +0100 Subject: [PATCH 9/9] Fix build errors and some cleanup --- app/src/application.rs | 9 +- core/Cargo.toml | 6 +- core/src/builtin_widgets/cursor.rs | 21 +-- core/src/builtin_widgets/scrollable.rs | 22 +-- core/src/events/dispatcher.rs | 49 +++---- core/src/events/event.rs | 11 +- core/src/events/wheel.rs | 2 +- core/src/window.rs | 18 ++- crossterm/src/from_event.rs | 59 +------- crossterm/src/from_keyboard_input.rs | 14 -- crossterm/src/from_modifiers.rs | 4 - crossterm/src/from_mouse.rs | 4 - crossterm/src/from_window.rs | 62 +-------- crossterm/src/shell_window.rs | 37 ----- crossterm/src/window_builder.rs | 4 + geometry/Cargo.toml | 13 +- geometry/src/lib.rs | 15 +- painter/Cargo_BACKUP_877261.toml | 33 ----- painter/Cargo_BASE_877261.toml | 28 ---- painter/Cargo_LOCAL_877261.toml | 29 ---- painter/Cargo_REMOTE_877261.toml | 29 ---- ribir/examples/animation_demo.rs | 22 ++- ribir/examples/counter.rs | 19 ++- ribir/examples/greet.rs | 18 ++- ribir/examples/todo_mvp.rs | 8 +- ribir/examples/widget_examples.rs | 37 +++-- tests/code_gen_test.rs | 20 +-- winit/src/from_cursor_icon.rs | 12 +- winit/src/from_element_state.rs | 14 -- winit/src/from_event.rs | 88 +++--------- winit/src/from_keyboard_input.rs | 24 +--- winit/src/from_modifiers.rs | 34 ----- winit/src/from_mouse_scroll_delta.rs | 34 ++--- winit/src/from_touch_phase.rs | 16 --- winit/src/from_virtual_key_code.rs | 186 ------------------------- winit/src/from_window.rs | 39 ------ winit/src/from_window_id.rs | 17 --- winit/src/shell_window.rs | 4 +- winit/src/window_builder.rs | 16 ++- 39 files changed, 238 insertions(+), 839 deletions(-) delete mode 100644 painter/Cargo_BACKUP_877261.toml delete mode 100644 painter/Cargo_BASE_877261.toml delete mode 100644 painter/Cargo_LOCAL_877261.toml delete mode 100644 painter/Cargo_REMOTE_877261.toml diff --git a/app/src/application.rs b/app/src/application.rs index 84a142f11..43af70f55 100644 --- a/app/src/application.rs +++ b/app/src/application.rs @@ -2,7 +2,7 @@ use ribir_core::{ prelude::{ShellWindow, Theme}, widget::Widget, - window::{WindowConfig, WindowId, Window}, + window::{Window, WindowConfig, WindowId}, }; #[cfg(any(feature = "crossterm", feature = "winit"))] @@ -31,6 +31,13 @@ impl Application { window_id } + pub fn build_headless_window(&mut self, window_builder: WindowBuilder) -> Box { + let window = window_builder.build_headless(&self.shell_window); + let window_id = window.raw_window.id().box_clone(); + self.shell_window.add_window(window); + window_id + } + pub fn exec(self, wnd_id: Box) { self.shell_window.exec(wnd_id) } } diff --git a/core/Cargo.toml b/core/Cargo.toml index 1b4c065ce..71b894d14 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -12,8 +12,6 @@ readme = "README.md" repository = "https://github.com/RibirX/Ribir/algo" version = "0.0.0" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [dependencies] ahash = "0.8.3" bitflags = "2.0.0" @@ -25,14 +23,12 @@ lyon_algorithms = "1.0.1" lyon_geom = "1.0.1" png = {version = "0.17.3", optional = true} ribir_algo = {path = "../algo", version = "0.0.0"} -#ribir_gpu = {path = "../gpu", version = "0.0.0", features = ["wgpu_gl"]} +ribir_geometry = {path = "../geometry", version = "0.0.0"} ribir_macros = {path = "../macros", version = "0.0.0"} ribir_painter = {path = "../painter", version = "0.0.0"} ribir_text = {path = "../text", version = "0.0.0"} rxrust = "1.0.0-beta.1" - smallvec = "1.8.0" -# winit = "0.28.1" [dependencies.blake3] features = ["rayon"] diff --git a/core/src/builtin_widgets/cursor.rs b/core/src/builtin_widgets/cursor.rs index 6b20b99dc..6d66c8cfb 100644 --- a/core/src/builtin_widgets/cursor.rs +++ b/core/src/builtin_widgets/cursor.rs @@ -117,12 +117,8 @@ mod tests { let device_id = MockPointerId::zero(); let dispatcher = &mut wnd.dispatcher; dispatcher.dispatch( - WindowEvent::CursorMoved { - device_id, - position: DevicePoint::new(1, 1), - }, + WindowEvent::CursorMoved { device_id, position: (1., 1.).into() }, tree, - 1., ); assert_eq!(dispatcher.take_cursor_icon(), Some(CursorIcon::Help)); @@ -130,10 +126,9 @@ mod tests { dispatcher.dispatch( WindowEvent::CursorMoved { device_id, - position: DevicePoint::new(101, 1), + position: (101., 1.).into(), }, tree, - 1., ); assert_eq!(dispatcher.take_cursor_icon(), Some(CursorIcon::Hand)); @@ -141,10 +136,9 @@ mod tests { dispatcher.dispatch( WindowEvent::CursorMoved { device_id, - position: DevicePoint::new(201, 1), + position: (201., 1.).into(), }, tree, - 1., ); assert_eq!(dispatcher.take_cursor_icon(), Some(CursorIcon::AllScroll)); @@ -152,21 +146,16 @@ mod tests { dispatcher.dispatch( WindowEvent::CursorMoved { device_id, - position: DevicePoint::new(101, 1), + position: (101., 1.).into(), }, tree, - 1., ); assert_eq!(dispatcher.take_cursor_icon(), Some(CursorIcon::Hand)); let device_id = MockPointerId::zero(); dispatcher.dispatch( - WindowEvent::CursorMoved { - device_id, - position: DevicePoint::new(1, 1), - }, + WindowEvent::CursorMoved { device_id, position: (1., 1.).into() }, tree, - 1., ); assert_eq!(dispatcher.take_cursor_icon(), Some(CursorIcon::Help)); } diff --git a/core/src/builtin_widgets/scrollable.rs b/core/src/builtin_widgets/scrollable.rs index 091b10bc2..5e979dae7 100644 --- a/core/src/builtin_widgets/scrollable.rs +++ b/core/src/builtin_widgets/scrollable.rs @@ -111,7 +111,7 @@ mod tests { use super::*; - fn test_assert(scrollable: Scrollable, delta_x: i32, delta_y: i32, expect_x: i32, expect_y: i32) { + fn test_assert(scrollable: Scrollable, delta_x: f32, delta_y: f32, expect_x: i32, expect_y: i32) { let w = widget! { MockBox { size: Size::new(1000., 1000.), @@ -126,7 +126,7 @@ mod tests { let device_id = MockPointerId::zero(); wnd.processes_native_event(WindowEvent::MouseWheel { device_id, - delta: MouseScrollDelta::PixelDelta(DeviceOffset::new(delta_x, delta_y)), + delta: MouseScrollDelta::PixelDelta((delta_x, delta_y).into()), phase: TouchPhase::Started, }); @@ -145,22 +145,22 @@ mod tests { #[test] fn x_scroll() { - test_assert(Scrollable::X, -10, -10, -10, 0); - test_assert(Scrollable::X, -10000, -10, -900, 0); - test_assert(Scrollable::X, 100, -10, 0, 0); + test_assert(Scrollable::X, -10., -10., -10, 0); + test_assert(Scrollable::X, -10000., -10., -900, 0); + test_assert(Scrollable::X, 100., -10., 0, 0); } #[test] fn y_scroll() { - test_assert(Scrollable::Y, -10, -10, 0, -10); - test_assert(Scrollable::Y, -10, -10000, 0, -900); - test_assert(Scrollable::Y, 10, 100, 0, 0); + test_assert(Scrollable::Y, -10., -10., 0, -10); + test_assert(Scrollable::Y, -10., -10000., 0, -900); + test_assert(Scrollable::Y, 10., 100., 0, 0); } #[test] fn both_scroll() { - test_assert(Scrollable::Both, -10, -10, -10, -10); - test_assert(Scrollable::Both, -10000, -10000, -900, -900); - test_assert(Scrollable::Both, 100, 100, 0, 0); + test_assert(Scrollable::Both, -10., -10., -10, -10); + test_assert(Scrollable::Both, -10000., -10000., -900, -900); + test_assert(Scrollable::Both, 100., 100., 0, 0); } } diff --git a/core/src/events/dispatcher.rs b/core/src/events/dispatcher.rs index 587f94f9c..11a6244c5 100644 --- a/core/src/events/dispatcher.rs +++ b/core/src/events/dispatcher.rs @@ -37,14 +37,14 @@ pub(crate) struct DispatchInfo { } impl Dispatcher { - pub fn dispatch(&mut self, event: WindowEvent, tree: &mut WidgetTree, wnd_factor: f64) { + pub fn dispatch(&mut self, event: WindowEvent, tree: &mut WidgetTree) { log::info!("Dispatch winit event {:?}", event); match event { WindowEvent::ModifiersChanged(s) => self.info.modifiers = s, WindowEvent::CursorMoved { position, .. } => { - let logical_pos = - ScaleToLogic::new(1.0 / wnd_factor as f32).transform_point(position.cast()); - self.cursor_move_to(logical_pos, tree) + // let logical_pos = + // ScaleToLogic::new(1.0 / wnd_factor as f32).transform_point(position); + self.cursor_move_to(position, tree) } WindowEvent::CursorLeft { .. } => self.on_cursor_left(tree), WindowEvent::MouseInput { state, button, device_id, .. } => { @@ -56,7 +56,7 @@ impl Dispatcher { WindowEvent::ReceivedCharacter(c) => { self.dispatch_received_char(c, tree); } - WindowEvent::MouseWheel { delta, .. } => self.dispatch_wheel(delta, tree, wnd_factor), + WindowEvent::MouseWheel { delta, .. } => self.dispatch_wheel(delta, tree), _ => log::info!("Not processed event {:?}", event), } } @@ -166,19 +166,14 @@ impl Dispatcher { Some(()) } - pub fn dispatch_wheel( - &mut self, - delta: MouseScrollDelta, - tree: &mut WidgetTree, - wnd_factor: f64, - ) { + pub fn dispatch_wheel(&mut self, delta: MouseScrollDelta, tree: &mut WidgetTree) { if let Some(wid) = self.hit_widget(tree) { let (delta_x, delta_y) = match delta { MouseScrollDelta::LineDelta(x, y) => (x * PIXELS_PER_EM, y * PIXELS_PER_EM), MouseScrollDelta::PixelDelta(delta) => { - let logical_delta = - ScaleToLogic::new(1.0 / wnd_factor as f32).transform_point(delta.cast()); - (logical_delta.x, logical_delta.y) + // let logical_delta = + // ScaleToLogic::new(1.0 / wnd_factor as f32).transform_point(delta.cast()); + (delta.x, delta.y) } }; @@ -421,7 +416,7 @@ mod tests { wnd.processes_native_event(WindowEvent::CursorMoved { device_id: MockPointerId::zero(), - position: DevicePoint::new(1, 1), + position: (1., 1.).into(), }); { @@ -467,7 +462,7 @@ mod tests { wnd.processes_native_event(WindowEvent::CursorMoved { device_id: MockPointerId::zero(), - position: (1, 1).into(), + position: (1., 1.).into(), }); wnd.processes_native_event(WindowEvent::MouseInput { @@ -530,7 +525,7 @@ mod tests { wnd.processes_native_event(WindowEvent::CursorMoved { device_id: device_id_2, - position: (1, 1).into(), + position: (1., 1.).into(), }); // but cursor move processed. @@ -622,14 +617,14 @@ mod tests { wnd.processes_native_event(WindowEvent::CursorMoved { device_id: MockPointerId::zero(), - position: (10, 10).into(), + position: (10., 10.).into(), }); assert_eq!(&*enter_event.borrow(), &[2, 1]); // leave to parent wnd.processes_native_event(WindowEvent::CursorMoved { device_id: MockPointerId::zero(), - position: (99, 99).into(), + position: (99., 99.).into(), }); assert_eq!(&*leave_event.borrow(), &[1]); @@ -637,7 +632,7 @@ mod tests { // check if duplicate event fired. wnd.processes_native_event(WindowEvent::CursorMoved { device_id: MockPointerId::zero(), - position: (99, 99).into(), + position: (99., 99.).into(), }); assert_eq!(&*enter_event.borrow(), &[2, 1]); assert_eq!(&*leave_event.borrow(), &[1]); @@ -645,7 +640,7 @@ mod tests { // leave all wnd.processes_native_event(WindowEvent::CursorMoved { device_id: MockPointerId::zero(), - position: (999, 999).into(), + position: (999., 999.).into(), }); assert_eq!(&*leave_event.borrow(), &[1, 2]); @@ -654,7 +649,7 @@ mod tests { leave_event.borrow_mut().clear(); wnd.processes_native_event(WindowEvent::CursorMoved { device_id: MockPointerId::zero(), - position: (10, 10).into(), + position: (10., 10.).into(), }); wnd.processes_native_event(WindowEvent::CursorLeft { device_id: MockPointerId::zero() }); assert_eq!(&*leave_event.borrow(), &[1, 2]); @@ -681,7 +676,7 @@ mod tests { wnd.processes_native_event(WindowEvent::CursorMoved { device_id: MockPointerId::zero(), - position: DevicePoint::new(50, 50), + position: (50., 50.).into(), }); wnd.processes_native_event(WindowEvent::MouseInput { device_id: MockPointerId::zero(), @@ -702,7 +697,7 @@ mod tests { wnd.processes_native_event(WindowEvent::CursorMoved { device_id: MockPointerId::zero(), - position: DevicePoint::new(50, 50), + position: (50., 50.).into(), }); wnd.processes_native_event(WindowEvent::MouseInput { device_id: MockPointerId::zero(), @@ -711,7 +706,7 @@ mod tests { }); wnd.processes_native_event(WindowEvent::CursorMoved { device_id: MockPointerId::zero(), - position: DevicePoint::new(50, 150), + position: (50., 150.).into(), }); wnd.processes_native_event(WindowEvent::MouseInput { device_id: MockPointerId::zero(), @@ -744,7 +739,7 @@ mod tests { let device_id = MockPointerId::zero(); wnd.processes_native_event(WindowEvent::CursorMoved { device_id: device_id.clone(), - position: DevicePoint::new(45, 45), + position: (45., 45.).into(), }); wnd.processes_native_event(WindowEvent::MouseInput { device_id: device_id.clone(), @@ -762,7 +757,7 @@ mod tests { }); wnd.processes_native_event(WindowEvent::CursorMoved { device_id: device_id.clone(), - position: DevicePoint::new(80, 80), + position: (80., 80.).into(), }); wnd.processes_native_event(WindowEvent::MouseInput { device_id, diff --git a/core/src/events/event.rs b/core/src/events/event.rs index 303de6b71..2e20982ab 100644 --- a/core/src/events/event.rs +++ b/core/src/events/event.rs @@ -1,12 +1,13 @@ -use ribir_painter::{DeviceOffset, DevicePoint, DeviceSize}; use std::fmt::Debug; +use ribir_geometry::{Offset, Point, Size}; + use super::{ModifiersState, MouseButtons, PointerId, ScanCode, VirtualKeyCode}; #[derive(Debug)] pub enum WindowEvent { Unsupported, - Resized(DeviceSize), + Resized(Size), /// The window received a unicode character. /// @@ -39,7 +40,7 @@ pub enum WindowEvent { /// may have been transformed by the OS to implement effects such as cursor /// acceleration, it should not be used to implement non-cursor-like /// interactions such as 3D camera control. - position: DevicePoint, + position: Point, }, /// The cursor has left the window. @@ -78,7 +79,7 @@ pub enum WindowEvent { /// module. ScaleFactorChanged { scale_factor: f64, - new_inner_size: DeviceSize, + new_inner_size: Size, }, } @@ -182,7 +183,7 @@ pub enum MouseScrollDelta { /// For a 'natural scrolling' touch pad (that acts like a touch screen) /// this means moving your fingers right and down should give positive values, /// and move the content right and down (to reveal more things left and up). - PixelDelta(DeviceOffset), + PixelDelta(Offset), } /// Describes touch-screen input state. diff --git a/core/src/events/wheel.rs b/core/src/events/wheel.rs index af09be7a5..0e31779fe 100644 --- a/core/src/events/wheel.rs +++ b/core/src/events/wheel.rs @@ -75,7 +75,7 @@ mod tests { let device_id = MockPointerId::zero(); wnd.processes_native_event(WindowEvent::MouseWheel { device_id, - delta: MouseScrollDelta::PixelDelta(DeviceOffset::new(1, 1)), + delta: MouseScrollDelta::PixelDelta((1., 1.).into()), phase: TouchPhase::Started, }); diff --git a/core/src/window.rs b/core/src/window.rs index 0f2d3f674..fe9927e7e 100644 --- a/core/src/window.rs +++ b/core/src/window.rs @@ -105,18 +105,22 @@ impl Window { pub fn processes_native_event(&mut self, event: WindowEvent) { match event { WindowEvent::Resized(size) => { - self.on_resize(DeviceSize::new(size.width, size.height)); + self.on_resize( + ScaleToPhysic::new(self.raw_window.scale_factor() as f32) + .transform_size(size) + .cast(), + ); } WindowEvent::ScaleFactorChanged { new_inner_size, scale_factor } => { - self.on_resize(new_inner_size); + self.on_resize( + ScaleToPhysic::new(self.raw_window.scale_factor() as f32) + .transform_size(new_inner_size) + .cast(), + ); let factor = scale_factor as f32; self.painter.reset(Some(factor)); } - event => { - self - .dispatcher - .dispatch(event, &mut self.widget_tree, self.raw_window.scale_factor()) - } + event => self.dispatcher.dispatch(event, &mut self.widget_tree), }; if let Some(icon) = self.dispatcher.take_cursor_icon() { self.raw_window.set_cursor(icon); diff --git a/crossterm/src/from_event.rs b/crossterm/src/from_event.rs index ce59ca613..d93b78f43 100644 --- a/crossterm/src/from_event.rs +++ b/crossterm/src/from_event.rs @@ -6,7 +6,6 @@ use crossterm::event::{Event as CrosstermWindowEvent, MouseEventKind}; use ribir_core::prelude::{ ElementState, MouseScrollDelta, TouchPhase, WindowEvent as RibirWindowEvent, }; -use ribir_geometry::{DevicePoint, DeviceSize}; pub struct WrappedWindowEvent(CrosstermWindowEvent); @@ -14,10 +13,6 @@ impl From for WrappedWindowEvent { fn from(value: CrosstermWindowEvent) -> Self { WrappedWindowEvent(value) } } -impl From for CrosstermWindowEvent { - fn from(val: WrappedWindowEvent) -> Self { val.0 } -} - impl From for RibirWindowEvent { fn from(val: WrappedWindowEvent) -> Self { match val.0 { @@ -44,7 +39,7 @@ impl From for RibirWindowEvent { MouseEventKind::Drag(_) => RibirWindowEvent::Unsupported, MouseEventKind::Moved => RibirWindowEvent::CursorMoved { device_id: Box::new(CrosstermPointerId::zero()), - position: DevicePoint::new(event.column as u32, event.row as u32), + position: (event.column as f32, event.row as f32).into(), }, MouseEventKind::ScrollDown => RibirWindowEvent::MouseWheel { device_id: Box::new(CrosstermPointerId::zero()), @@ -60,56 +55,8 @@ impl From for RibirWindowEvent { #[cfg(feature = "bracketed-paste")] CrosstermWindowEvent::Paste(_data) => RibirWindowEvent::Unsupported, CrosstermWindowEvent::Resize(width, height) => { - RibirWindowEvent::Resized(DeviceSize::new(width as u32, height as u32)) - } /* CrosstermWindowEvent::ReceivedCharacter(char) => - * RibirWindowEvent::ReceivedCharacter(char), CrosstermWindowEvent::KeyboardInput - * { device_id, input, is_synthetic } => { RibirWindowEvent::KeyboardInput { - * device_id: Box::new(CrosstermPointerId::from(device_id)), - * input: WrappedKeyboardInput::from(input).into(), - * is_synthetic, - * } - * } - * CrosstermWindowEvent::ModifiersChanged(modifiers) => { - * RibirWindowEvent::ModifiersChanged(WrappedModifiersState::from(modifiers).into()) - * } - * #[allow(deprecated)] - * CrosstermWindowEvent::CursorMoved { device_id, position, modifiers: _ } => { - * RibirWindowEvent::CursorMoved { - * device_id: Box::new(CrosstermPointerId::from(device_id)), - * position, - * } - * } - * CrosstermWindowEvent::CursorLeft { device_id } => RibirWindowEvent::CursorLeft { - * device_id: Box::new(CrosstermPointerId::from(device_id)), - * }, - * #[allow(deprecated)] - * CrosstermWindowEvent::MouseWheel { - * device_id, - * delta, - * phase, - * modifiers: _, - * } => RibirWindowEvent::MouseWheel { - * device_id: Box::new(CrosstermPointerId::from(device_id)), - * delta: WrappedMouseScrollDelta::from(delta).into(), - * phase: WrappedTouchPhase::from(phase).into(), - * }, - * #[allow(deprecated)] - * CrosstermWindowEvent::MouseInput { - * device_id, - * state, - * button, - * modifiers: _, - * } => RibirWindowEvent::MouseInput { - * device_id: Box::new(CrosstermPointerId::from(device_id)), - * state: WrappedElementState::from(state).into(), - * button: WrappedMouseButton::from(button).into(), - * }, - * CrosstermWindowEvent::ScaleFactorChanged { scale_factor, new_inner_size } => { - * RibirWindowEvent::ScaleFactorChanged { - * scale_factor, - * new_inner_size: WrappedPhysicalSize::::from(new_inner_size).into(), - * } - * } */ + RibirWindowEvent::Resized((width as f32, height as f32).into()) + } } } } diff --git a/crossterm/src/from_keyboard_input.rs b/crossterm/src/from_keyboard_input.rs index 07d11983f..7aebce30c 100644 --- a/crossterm/src/from_keyboard_input.rs +++ b/crossterm/src/from_keyboard_input.rs @@ -24,20 +24,6 @@ impl From for RibirKeyboardInput { } } -// impl From for WrappedKeyboardInput { -// #[allow(deprecated)] -// fn from(value: RibirKeyboardInput) -> WrappedKeyboardInput { -// WrappedKeyboardInput::from(CrosstermKeyboardInput { -// scancode: value.scancode, -// state: WrappedElementState::from(value.state).into(), -// virtual_keycode: value -// .virtual_keycode -// .map(|v| WrappedVirtualKeyCode::from(v).into()), -// modifiers: CrosstermModifiersState::default(), -// }) -// } -// } - #[cfg(test)] mod tests { // use super::*; diff --git a/crossterm/src/from_modifiers.rs b/crossterm/src/from_modifiers.rs index 8c95cc05b..1ddd9be9b 100644 --- a/crossterm/src/from_modifiers.rs +++ b/crossterm/src/from_modifiers.rs @@ -9,10 +9,6 @@ impl From for WrappedModifiersState { fn from(value: CrosstermKeyModifiers) -> Self { WrappedModifiersState(value) } } -impl From for CrosstermKeyModifiers { - fn from(val: WrappedModifiersState) -> Self { val.0 } -} - impl From for RibirModifiersState { fn from(val: WrappedModifiersState) -> Self { let shift = if val.0.contains(CrosstermKeyModifiers::SHIFT) { diff --git a/crossterm/src/from_mouse.rs b/crossterm/src/from_mouse.rs index e4f1a7bf8..53c75eca2 100644 --- a/crossterm/src/from_mouse.rs +++ b/crossterm/src/from_mouse.rs @@ -7,10 +7,6 @@ impl From for WrappedMouseButton { fn from(value: CrosstermMouseButton) -> Self { WrappedMouseButton(value) } } -// impl From for CrosstermMouseButton { -// fn from(val: WrappedMouseButton) -> Self { val.0 } -// } - impl From for RibirMouseButton { fn from(val: WrappedMouseButton) -> Self { match val.0 { diff --git a/crossterm/src/from_window.rs b/crossterm/src/from_window.rs index 3d5647681..22456d1d1 100644 --- a/crossterm/src/from_window.rs +++ b/crossterm/src/from_window.rs @@ -21,80 +21,32 @@ impl CrosstermWindow { pub fn id(&self) -> CrosstermWindowId { self.id } } -// #[derive(PartialEq, Eq)] -// pub struct WrappedWindow(CrosstermWindow); - impl RibirRawWindow for CrosstermWindow { - fn inner_size(&self) -> Size { - // WrappedLogicalSize::::from(self.0.inner_size().to_logical(self. - // scale_factor())).into() - Size::new(100., 100.) - // let size = ScreenBuffer::current()?.info()?.terminal_size(); - } + fn inner_size(&self) -> Size { Size::new(100., 100.) } fn set_inner_size(&mut self, _size: Size) { - // self.0.set_inner_size( - // CrosstermLogicalSize::::new(size.width.cast(), size.height.cast()) - // .to_physical::(self.scale_factor()), - // ); + todo!(); } - fn outer_size(&self) -> Size { - // WrappedLogicalSize::::from(self.0.outer_size().to_logical(self. - // scale_factor())).into() - Size::new(0., 0.) - } + fn outer_size(&self) -> Size { Size::new(0., 0.) } - fn inner_position(&self) -> Point { - // WrappedLogicalPosition::::from( - // self - // .0 - // .inner_position() - // .expect(" Can only be called on the main thread") - // .to_logical(self.scale_factor()), - // ) - // .into() - Point::new(0., 0.) - } + fn inner_position(&self) -> Point { Point::new(0., 0.) } - fn outer_position(&self) -> Point { - // WrappedLogicalPosition::::from( - // self - // .0 - // .outer_position() - // .expect(" Can only be called on the main thread") - // .to_logical(self.scale_factor()), - // ) - // .into() - Point::new(0., 0.) - } + fn outer_position(&self) -> Point { Point::new(0., 0.) } fn id(&self) -> Box { Box::new(self.id()) } fn request_redraw(&self) { self.request_redraw(); } fn set_cursor(&mut self, _cursor: CursorIcon) { - // self - // .0 - // .set_cursor_icon(WrappedCursorIcon::from(cursor).into()); + todo!(); } - fn scale_factor(&self) -> f64 { - // self.0.scale_factor() - 1.0 - } + fn scale_factor(&self) -> f64 { 1.0 } fn into_any(self: Box) -> Box { self } } -// impl From for CrosstermWindow { -// fn from(value: CrosstermWindow) -> Self { WrappedWindow(value) } -// } - -// impl From for CrosstermWindow { -// fn from(val: WrappedWindow) -> Self { val.0 } -// } - impl From> for CrosstermWindow { fn from(value: Box) -> Self { *value.into_any().downcast::().unwrap() diff --git a/crossterm/src/shell_window.rs b/crossterm/src/shell_window.rs index cc75065e5..4598f443d 100644 --- a/crossterm/src/shell_window.rs +++ b/crossterm/src/shell_window.rs @@ -62,14 +62,11 @@ impl ShellWindow for PlatformShellWindow { // `poll()` waits for an `Event` for a given time period match poll(Duration::from_millis(100)) { Ok(true) => { - // println!("poll"); // It's guaranteed that the `read()` won't block when the `poll()` // function returns `true` if let Ok(event) = read() { let evt = CrosstermWindowId::from(wnd_id.clone()); - // println!("Event {evt:?}"); if let Some(wnd) = windows.get_mut(&evt) { - // println!("=== process event {event:?} ==="); wnd.processes_native_event(WrappedWindowEvent::from(event).into()); wnd.draw_frame(); } else { @@ -86,40 +83,6 @@ impl ShellWindow for PlatformShellWindow { _ => {} } } - - // event_loop.run_return(move |event, _event_loop, control: &mut - // ControlFlow| { *control = ControlFlow::Wait; - - // match event { - // Event::WindowEvent { event, window_id } => { - // if event == WindowEvent::CloseRequested { - // windows.remove(&window_id); - // } else if event == WindowEvent::Destroyed { - // if windows.is_empty() { - // *control = ControlFlow::Exit; - // } - // } else if let Some(wnd) = windows.get_mut(&window_id) { - // wnd.processes_native_event(WrappedWindowEvent::from(event). - // into()); } - // } - // Event::MainEventsCleared => windows.iter_mut().for_each(|(_, wnd)| { - // if wnd.need_draw() { - // wnd.request_redraw(); - // } - // }), - // Event::RedrawRequested(id) => { - // if let Some(wnd) = windows.get_mut(&id) { - // wnd.draw_frame(); - // } - // } - // Event::RedrawEventsCleared => { - // if windows.iter_mut().any(|(_, wnd)| wnd.need_draw()) { - // *control = ControlFlow::Poll; - // } - // } - // _ => (), - // } - // }); } fn add_window(&mut self, wnd: Window) -> Box { diff --git a/crossterm/src/window_builder.rs b/crossterm/src/window_builder.rs index f979799ea..42525bebb 100644 --- a/crossterm/src/window_builder.rs +++ b/crossterm/src/window_builder.rs @@ -94,4 +94,8 @@ impl WindowBuilder { let p_backend = CrosstermBackend::new(Box::new(stdout())); RibirWindow::new(native_wnd, p_backend, self.root, ctx) } + + pub fn build_headless(self, _shell_window: &PlatformShellWindow) -> RibirWindow { + todo!("Not supported"); + } } diff --git a/geometry/Cargo.toml b/geometry/Cargo.toml index eb2614ee7..59a0d00e6 100644 --- a/geometry/Cargo.toml +++ b/geometry/Cargo.toml @@ -1,9 +1,14 @@ [package] -name = "ribir_geometry" -version = "0.1.0" +categories = ["gui"] +description = "Ribir is a framework for building modern native/wasm cross-platform user interface applications." +documentation = "https://ribir.org/docs" edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +homepage = "https://ribir.org" +keywords = ["gui", "ui", "declarative", "compose-ui"] +license = "MIT" +name = "ribir_geometry" +repository = "https://github.com/RibirX/Ribir/geometry" +version = "0.0.0" [dependencies] euclid = "0.22.6" diff --git a/geometry/src/lib.rs b/geometry/src/lib.rs index 90cb41b03..7b6259cdf 100644 --- a/geometry/src/lib.rs +++ b/geometry/src/lib.rs @@ -11,20 +11,23 @@ pub struct LogicUnit; pub type Rect = euclid::Rect; pub type Point = euclid::Point2D; pub type Size = euclid::Size2D; -pub type Transform = euclid::Transform2D; -pub type ScaleToPhysic = euclid::Scale; -pub type ScaleToLogic = euclid::Scale; - +pub type Offset = euclid::Point2D; pub type Vector = euclid::Vector2D; -pub type Angle = euclid::Angle; pub type Box2D = euclid::Box2D; +pub type Transform = euclid::Transform2D; + pub type DeviceRect = euclid::Rect; pub type DevicePoint = euclid::Point2D; pub type DeviceSize = euclid::Size2D; +pub type DeviceOffset = euclid::Point2D; pub type DeviceVector = euclid::Vector2D; -pub type DeviceOffset = euclid::Point2D; +pub type Angle = euclid::Angle; + +pub type ScaleToPhysic = euclid::Scale; +pub type ScaleToLogic = euclid::Scale; + pub type ScaleOffsetToPhysic = euclid::Scale; pub type ScaleOffsetToLogic = euclid::Scale; diff --git a/painter/Cargo_BACKUP_877261.toml b/painter/Cargo_BACKUP_877261.toml deleted file mode 100644 index e4dd348d5..000000000 --- a/painter/Cargo_BACKUP_877261.toml +++ /dev/null @@ -1,33 +0,0 @@ -[package] -categories = ["gui"] -description = "Ribir is a framework for building modern native/wasm cross-platform user interface applications." -documentation = "https://ribir.org/docs" -edition = "2021" -homepage = "https://ribir.org" -keywords = ["gui", "ui", "declarative", "compose-ui"] -license = "MIT" -name = "ribir_painter" -readme = "README.md" -repository = "https://github.com/RibirX/Ribir/algo" -version = "0.0.0" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -bitflags = "2.0.0" -euclid = "0.22.6" -log = "0.4.17" -lyon_algorithms = "1.0.1" -lyon_tessellation = {version = "1.0.1", features = ["serialization"]} -palette = {version = "0.6.1", features = ["serializing"]} -ribir_algo = {path = "../algo", version = "0.0.0"} -ribir_geometry = {path = "../geometry"} -ribir_text = {path = "../text", version = "0.0.0"} -serde = {version = "1.0", features = ["rc"]} -serde_json = "1.0.82" -usvg = {version = "0.29.0"} -rctree ="0.5.0" -<<<<<<< HEAD -======= -bitflags-serde-legacy = "0.1.0" ->>>>>>> a0665d2f38fb666548d265846d0b59384ea22772 diff --git a/painter/Cargo_BASE_877261.toml b/painter/Cargo_BASE_877261.toml deleted file mode 100644 index fa7a5c1c8..000000000 --- a/painter/Cargo_BASE_877261.toml +++ /dev/null @@ -1,28 +0,0 @@ -[package] -categories = ["gui"] -description = "Ribir is a framework for building modern native/wasm cross-platform user interface applications." -documentation = "https://ribir.org/docs" -edition = "2021" -homepage = "https://ribir.org" -keywords = ["gui", "ui", "declarative", "compose-ui"] -license = "MIT" -name = "ribir_painter" -readme = "README.md" -repository = "https://github.com/RibirX/Ribir/algo" -version = "0.0.0" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -bitflags = "1.3.2" -euclid = "0.22.6" -log = "0.4.17" -lyon_algorithms = "1.0.1" -lyon_tessellation = {version = "1.0.1", features = ["serialization"]} -palette = {version = "0.6.1", features = ["serializing"]} -ribir_algo = {path = "../algo", version = "0.0.0"} -ribir_text = {path = "../text", version = "0.0.0"} -serde = {version = "1.0", features = ["rc"]} -serde_json = "1.0.82" -usvg = {version = "0.29.0"} -rctree ="0.5.0" \ No newline at end of file diff --git a/painter/Cargo_LOCAL_877261.toml b/painter/Cargo_LOCAL_877261.toml deleted file mode 100644 index 81403e99c..000000000 --- a/painter/Cargo_LOCAL_877261.toml +++ /dev/null @@ -1,29 +0,0 @@ -[package] -categories = ["gui"] -description = "Ribir is a framework for building modern native/wasm cross-platform user interface applications." -documentation = "https://ribir.org/docs" -edition = "2021" -homepage = "https://ribir.org" -keywords = ["gui", "ui", "declarative", "compose-ui"] -license = "MIT" -name = "ribir_painter" -readme = "README.md" -repository = "https://github.com/RibirX/Ribir/algo" -version = "0.0.0" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -bitflags = "1.3.2" -euclid = "0.22.6" -log = "0.4.17" -lyon_algorithms = "1.0.1" -lyon_tessellation = {version = "1.0.1", features = ["serialization"]} -palette = {version = "0.6.1", features = ["serializing"]} -ribir_algo = {path = "../algo", version = "0.0.0"} -ribir_geometry = {path = "../geometry"} -ribir_text = {path = "../text", version = "0.0.0"} -serde = {version = "1.0", features = ["rc"]} -serde_json = "1.0.82" -usvg = {version = "0.29.0"} -rctree ="0.5.0" diff --git a/painter/Cargo_REMOTE_877261.toml b/painter/Cargo_REMOTE_877261.toml deleted file mode 100644 index 7691bfecb..000000000 --- a/painter/Cargo_REMOTE_877261.toml +++ /dev/null @@ -1,29 +0,0 @@ -[package] -categories = ["gui"] -description = "Ribir is a framework for building modern native/wasm cross-platform user interface applications." -documentation = "https://ribir.org/docs" -edition = "2021" -homepage = "https://ribir.org" -keywords = ["gui", "ui", "declarative", "compose-ui"] -license = "MIT" -name = "ribir_painter" -readme = "README.md" -repository = "https://github.com/RibirX/Ribir/algo" -version = "0.0.0" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -bitflags = "2.0.0" -euclid = "0.22.6" -log = "0.4.17" -lyon_algorithms = "1.0.1" -lyon_tessellation = {version = "1.0.1", features = ["serialization"]} -palette = {version = "0.6.1", features = ["serializing"]} -ribir_algo = {path = "../algo", version = "0.0.0"} -ribir_text = {path = "../text", version = "0.0.0"} -serde = {version = "1.0", features = ["rc"]} -serde_json = "1.0.82" -usvg = {version = "0.29.0"} -rctree ="0.5.0" -bitflags-serde-legacy = "0.1.0" diff --git a/ribir/examples/animation_demo.rs b/ribir/examples/animation_demo.rs index 0f0b2eb10..5a0df4e81 100644 --- a/ribir/examples/animation_demo.rs +++ b/ribir/examples/animation_demo.rs @@ -1,7 +1,9 @@ -use ribir::prelude::*; -use std::time::Duration; - +#[cfg(any(feature = "crossterm", feature = "winit"))] fn main() { + use ribir::prelude::*; + use ribir::Application; + use std::time::Duration; + let style = PathStyle::Stroke(StrokeOptions::default()); let lyon_path = include_svg!("./Logo.svg"); let mut paths = vec![]; @@ -39,5 +41,17 @@ fn main() { ] } }; - app::run(w); + + let mut app = Application::new(material::purple::light()); + let window_builder = app.window_builder(w, Default::default()); + + let window_id = app.build_window(window_builder); + app.exec(window_id); +} + +#[cfg(not(any(feature = "crossterm", feature = "winit")))] +fn main() { + println!("Chose a platform to run:"); + println!(" cargo run --example animation_demo -F winit,wgpu_gl"); + println!(" cargo run --example animation_demo -F crossterm"); } diff --git a/ribir/examples/counter.rs b/ribir/examples/counter.rs index 53c7c3f62..2d4f7f8f2 100644 --- a/ribir/examples/counter.rs +++ b/ribir/examples/counter.rs @@ -1,6 +1,7 @@ -use ribir::prelude::*; - +#[cfg(any(feature = "crossterm", feature = "winit"))] fn main() { + use ribir::prelude::*; + let w = widget! { init ctx => { let ease_in = transitions::EASE_IN.of(ctx); @@ -46,5 +47,17 @@ fn main() { .subscribe(move |_| animate.run()); } }; - app::run(w); + + let mut app = Application::new(material::purple::light()); + let window_builder = app.window_builder(w, Default::default()); + + let window_id = app.build_window(window_builder); + app.exec(window_id); +} + +#[cfg(not(any(feature = "crossterm", feature = "winit")))] +fn main() { + println!("Chose a platform to run:"); + println!(" cargo run --example counter -F winit,wgpu_gl"); + println!(" cargo run --example counter -F crossterm"); } diff --git a/ribir/examples/greet.rs b/ribir/examples/greet.rs index 7a64dcad7..125c34ad9 100644 --- a/ribir/examples/greet.rs +++ b/ribir/examples/greet.rs @@ -1,9 +1,10 @@ //! This is just a `widget!` syntax teaching demo No consideration to its //! completeness and reasonableness. -use ribir::prelude::*; - +#[cfg(any(feature = "crossterm", feature = "winit"))] fn main() { + use ribir::prelude::*; + let hi = widget! { states { counter: Stateful::new(0) } init ctx => { @@ -65,5 +66,16 @@ fn main() { } }; - app::run(hi); + let mut app = Application::new(material::purple::light()); + let window_builder = app.window_builder(hi, Default::default()); + + let window_id = app.build_window(window_builder); + app.exec(window_id); +} + +#[cfg(not(any(feature = "crossterm", feature = "winit")))] +fn main() { + println!("Chose a platform to run:"); + println!(" cargo run --example counter -F winit,wgpu_gl"); + println!(" cargo run --example counter -F crossterm"); } diff --git a/ribir/examples/todo_mvp.rs b/ribir/examples/todo_mvp.rs index 2bb9d2ed5..70b9e8a3c 100644 --- a/ribir/examples/todo_mvp.rs +++ b/ribir/examples/todo_mvp.rs @@ -199,9 +199,9 @@ fn main() { app.exec(window_id); } -#[cfg(all(not(feature = "crossterm"), not(feature = "winit")))] +#[cfg(not(any(feature = "crossterm", feature = "winit")))] fn main() { - println!( - "The todo_mvp example is currently only implemented for the Winit and Crossterm platform" - ); + println!("Chose a platform to run:"); + println!(" cargo run --example todo_mvp -F winit,wgpu_gl"); + println!(" cargo run --example todo_mvp -F crossterm"); } diff --git a/ribir/examples/widget_examples.rs b/ribir/examples/widget_examples.rs index 2018636a5..855cea362 100644 --- a/ribir/examples/widget_examples.rs +++ b/ribir/examples/widget_examples.rs @@ -1,8 +1,12 @@ -use ribir::prelude::{svgs, *}; +#[cfg(any(feature = "crossterm", feature = "winit"))] +fn main() { + use ribir::Application; + use ribir_core::window::WindowConfig; -const WINDOW_SIZE: f32 = 800.; + use ribir::prelude::{svgs, *}; + + const WINDOW_SIZE: f32 = 800.; -fn main() { let widgets = widget! { init ctx => { let title_style = TypographyTheme::of(ctx).display_large.text.clone(); @@ -86,10 +90,25 @@ fn main() { } } }; - let app = Application::new(material::purple::light()); - let wnd = Window::builder(widgets) - .with_inner_size(Size::new(WINDOW_SIZE, WINDOW_SIZE)) - .with_title("StoryBook") - .build(&app); - app::run_with_window(app, wnd); + + let mut app = Application::new(material::purple::light()); + + let window_builder = app.window_builder( + widgets, + WindowConfig { + inner_size: Some((WINDOW_SIZE, WINDOW_SIZE).into()), + title: Some("StoryBook".to_owned()), + ..Default::default() + }, + ); + + let window_id = app.build_window(window_builder); + app.exec(window_id); +} + +#[cfg(not(any(feature = "crossterm", feature = "winit")))] +fn main() { + println!("Chose a platform to run:"); + println!(" cargo run --example widget_examples -F winit,wgpu_gl"); + println!(" cargo run --example widget_examples -F crossterm"); } diff --git a/tests/code_gen_test.rs b/tests/code_gen_test.rs index 2d0e7bbcb..d9d864393 100644 --- a/tests/code_gen_test.rs +++ b/tests/code_gen_test.rs @@ -30,7 +30,7 @@ fn simple_ref_bind_work() { wnd.layout(); assert_layout_result(&wnd, &[0], &ExpectRect::from_size(flex_size)); - tap_at(&mut wnd, (1, 1)); + tap_at(&mut wnd, (1., 1.)); wnd.layout(); assert_layout_result(&wnd, &[0], &ExpectRect::from_size(flex_size * 2.)); @@ -57,7 +57,7 @@ fn event_attr_sugar_work() { assert_layout_result(&wnd, &[0], &ExpectRect::from_size(BEFORE_SIZE)); assert_layout_result(&wnd, &[0, 0], &ExpectRect::from_size(BEFORE_SIZE)); - tap_at(&mut wnd, (25, 25)); + tap_at(&mut wnd, (25., 25.)); wnd.draw_frame(); assert_layout_result(&wnd, &[0], &ExpectRect::from_size(AFTER_TAP_SIZE)); @@ -85,7 +85,7 @@ fn widget_wrap_bind_work() { wnd.draw_frame(); assert_layout_result(&wnd, &[0], &ExpectRect::from_size(Size::new(104., 52.))); - tap_at(&mut wnd, (60, 1)); + tap_at(&mut wnd, (60., 1.)); wnd.draw_frame(); assert_layout_result(&wnd, &[0], &ExpectRect::from_size(Size::new(70., 60.))); @@ -116,7 +116,7 @@ fn expression_for_children() { assert_layout_result(&wnd, &[0, 3], &ExpectRect::from_size(size_one)); assert_layout_result(&wnd, &[0, 4], &ExpectRect::from_size(ZERO_SIZE)); - tap_at(&mut wnd, (0, 0)); + tap_at(&mut wnd, (0., 0.)); wnd.layout(); assert_layout_result(&wnd, &[0], &ExpectRect::from_size(Size::new(25., 5.))); assert_layout_result(&wnd, &[0, 0], &ExpectRect::from_size(size_five)); @@ -145,7 +145,7 @@ fn embed_widget_ref_outside() { wnd.layout(); assert_layout_result(&wnd, &[0], &ExpectRect::from_size(Size::new(4., 1.))); - tap_at(&mut wnd, (0, 0)); + tap_at(&mut wnd, (0., 0.)); wnd.layout(); assert_layout_result(&wnd, &[0], &ExpectRect::from_size(Size::new(8., 2.))); @@ -172,7 +172,7 @@ fn data_flow_macro() { // data flow not affect on init. assert_eq!(size, Size::new(3., 1.)); - tap_at(&mut wnd, (0, 0)); + tap_at(&mut wnd, (0., 0.)); wnd.draw_frame(); let size = layout_size_by_path(&wnd, &[0]); @@ -236,7 +236,7 @@ fn builtin_ref() { let mut wnd = Window::default_mock(w, None); wnd.draw_frame(); - tap_at(&mut wnd, (1, 1)); + tap_at(&mut wnd, (1., 1.)); wnd.draw_frame(); assert_eq!(icon_track.get(), CursorIcon::AllScroll); } @@ -264,15 +264,15 @@ fn builtin_bind_to_self() { let mut wnd = Window::default_mock(w, None); wnd.draw_frame(); - tap_at(&mut wnd, (1, 1)); + tap_at(&mut wnd, (1., 1.)); wnd.draw_frame(); assert_eq!(icon_track.get(), CursorIcon::Help); } -fn tap_at(wnd: &mut Window, pos: (u32, u32)) { +fn tap_at(wnd: &mut Window, pos: (f32, f32)) { wnd.processes_native_event(WindowEvent::CursorMoved { device_id: MockPointerId::zero(), - position: DevicePoint::new(pos.0, pos.1), + position: (pos.0, pos.1).into(), }); wnd.processes_native_event(WindowEvent::MouseInput { device_id: MockPointerId::zero(), diff --git a/winit/src/from_cursor_icon.rs b/winit/src/from_cursor_icon.rs index cfbc3f955..302e93056 100644 --- a/winit/src/from_cursor_icon.rs +++ b/winit/src/from_cursor_icon.rs @@ -96,11 +96,11 @@ impl From for WrappedCursorIcon { } } -#[cfg(test)] -mod tests { +// #[cfg(test)] +// mod tests { - use super::*; +// use super::*; - #[test] - fn from_winit() { let x = WinitCursorIcon::Alias; } -} +// #[test] +// fn from_winit() { let x = WinitCursorIcon::Alias; } +// } diff --git a/winit/src/from_element_state.rs b/winit/src/from_element_state.rs index 64f0ae20b..49f43ca23 100644 --- a/winit/src/from_element_state.rs +++ b/winit/src/from_element_state.rs @@ -7,10 +7,6 @@ impl From for WrappedElementState { fn from(value: WinitElementState) -> Self { WrappedElementState(value) } } -impl From for WinitElementState { - fn from(val: WrappedElementState) -> Self { val.0 } -} - impl From for RibirElementState { fn from(val: WrappedElementState) -> Self { match val.0 { @@ -19,13 +15,3 @@ impl From for RibirElementState { } } } - -impl From for WrappedElementState { - fn from(value: RibirElementState) -> WrappedElementState { - let es = match value { - RibirElementState::Pressed => WinitElementState::Pressed, - RibirElementState::Released => WinitElementState::Released, - }; - es.into() - } -} diff --git a/winit/src/from_event.rs b/winit/src/from_event.rs index 1c155b655..970ae6a1f 100644 --- a/winit/src/from_event.rs +++ b/winit/src/from_event.rs @@ -4,28 +4,27 @@ use crate::{ from_keyboard_input::WrappedKeyboardInput, from_modifiers::WrappedModifiersState, from_mouse::WrappedMouseButton, - from_size::{WrappedPhysicalPosition, WrappedPhysicalSize}, from_touch_phase::WrappedTouchPhase, - prelude::WrappedMouseScrollDelta, + prelude::{WrappedLogicalPosition, WrappedLogicalSize, WrappedMouseScrollDelta}, }; use ribir_core::prelude::WindowEvent as RibirWindowEvent; -use winit::event::{ModifiersState as WinitModifiersState, WindowEvent as WinitWindowEvent}; +use winit::event::WindowEvent as WinitWindowEvent; -pub struct WrappedWindowEvent<'a>(WinitWindowEvent<'a>); +pub type ScaleToLogicalFactor = f64; -impl<'a> From> for WrappedWindowEvent<'a> { - fn from(value: WinitWindowEvent<'a>) -> Self { WrappedWindowEvent(value) } -} +pub struct WrappedWindowEvent<'a>(WinitWindowEvent<'a>, ScaleToLogicalFactor); -impl<'a> From> for WinitWindowEvent<'a> { - fn from(val: WrappedWindowEvent<'a>) -> Self { val.0 } +impl<'a> From<(WinitWindowEvent<'a>, ScaleToLogicalFactor)> for WrappedWindowEvent<'a> { + fn from(value: (WinitWindowEvent<'a>, ScaleToLogicalFactor)) -> Self { + WrappedWindowEvent(value.0, value.1) + } } impl<'a> From> for RibirWindowEvent { fn from(val: WrappedWindowEvent<'a>) -> Self { match val.0 { WinitWindowEvent::Resized(size) => { - RibirWindowEvent::Resized(WrappedPhysicalSize::from(size).into()) + RibirWindowEvent::Resized(WrappedLogicalSize::::from(size.to_logical(val.1)).into()) } WinitWindowEvent::ReceivedCharacter(char) => RibirWindowEvent::ReceivedCharacter(char), WinitWindowEvent::KeyboardInput { device_id, input, is_synthetic } => { @@ -42,7 +41,7 @@ impl<'a> From> for RibirWindowEvent { WinitWindowEvent::CursorMoved { device_id, position, modifiers: _ } => { RibirWindowEvent::CursorMoved { device_id: Box::new(WrappedPointerId::from(device_id)), - position: WrappedPhysicalPosition::::from(position).into(), + position: WrappedLogicalPosition::::from(position.to_logical(val.1)).into(), } } WinitWindowEvent::CursorLeft { device_id } => RibirWindowEvent::CursorLeft { @@ -56,7 +55,7 @@ impl<'a> From> for RibirWindowEvent { modifiers: _, } => RibirWindowEvent::MouseWheel { device_id: Box::new(WrappedPointerId::from(device_id)), - delta: WrappedMouseScrollDelta::from(delta).into(), + delta: WrappedMouseScrollDelta::from((delta, val.1)).into(), phase: WrappedTouchPhase::from(phase).into(), }, #[allow(deprecated)] @@ -70,6 +69,7 @@ impl<'a> From> for RibirWindowEvent { state: WrappedElementState::from(state).into(), button: WrappedMouseButton::from(button).into(), }, + // TODO(zoech) // WinitWindowEvent::ScaleFactorChanged { scale_factor, new_inner_size } => { // RibirWindowEvent::ScaleFactorChanged { // scale_factor, @@ -81,67 +81,13 @@ impl<'a> From> for RibirWindowEvent { } } -impl<'a> From for WrappedWindowEvent<'a> { - fn from(value: RibirWindowEvent) -> WrappedWindowEvent<'a> { - let w_event = match value { - RibirWindowEvent::Resized(size) => { - WinitWindowEvent::Resized(WrappedPhysicalSize::from(size).into()) - } - RibirWindowEvent::ReceivedCharacter(char) => WinitWindowEvent::ReceivedCharacter(char), - RibirWindowEvent::KeyboardInput { device_id, input, is_synthetic } => { - WinitWindowEvent::KeyboardInput { - device_id: WrappedPointerId::from(device_id).into(), - input: WrappedKeyboardInput::from(input).into(), - is_synthetic, - } - } - RibirWindowEvent::ModifiersChanged(modifiers) => { - WinitWindowEvent::ModifiersChanged(WrappedModifiersState::from(modifiers).into()) - } - - RibirWindowEvent::CursorMoved { device_id, position } => WinitWindowEvent::CursorMoved { - device_id: WrappedPointerId::from(device_id).into(), - position: WrappedPhysicalPosition::::from(position).into(), - modifiers: WinitModifiersState::default(), - }, - RibirWindowEvent::CursorLeft { device_id } => WinitWindowEvent::CursorLeft { - device_id: WrappedPointerId::from(device_id).into(), - }, - - RibirWindowEvent::MouseWheel { device_id, delta, phase } => WinitWindowEvent::MouseWheel { - device_id: WrappedPointerId::from(device_id).into(), - delta: WrappedMouseScrollDelta::from(delta).into(), - phase: WrappedTouchPhase::from(phase).into(), - modifiers: WinitModifiersState::default(), - }, - - RibirWindowEvent::MouseInput { device_id, state, button } => WinitWindowEvent::MouseInput { - device_id: WrappedPointerId::from(device_id).into(), - state: WrappedElementState::from(state).into(), - button: WrappedMouseButton::from(button).into(), - modifiers: WinitModifiersState::default(), - }, - RibirWindowEvent::ScaleFactorChanged { scale_factor: _, new_inner_size: _ } => { - // WinitWindowEvent::ScaleFactorChanged { - // scale_factor, - // new_inner_size: WrappedPhysicalSize::::from(new_inner_size).into(), - // } - panic!("Unimplemented: \"{value:?}\" can not be converted to winit enum."); - } - other => { - panic!("Unimplemented: \"{other:?}\""); - } - }; - w_event.into() - } -} - #[cfg(test)] mod tests { - use super::*; - use crate::from_size::WinitPhysicalSize; + // use super::*; + // use crate::from_size::WinitPhysicalSize; - #[test] - fn from_winit() { WinitWindowEvent::Resized(WinitPhysicalSize:: { width: 5, height: 3 }); } + // #[test] + // fn from_winit() { WinitWindowEvent::Resized(WinitPhysicalSize:: { + // width: 5, height: 3 }); } } diff --git a/winit/src/from_keyboard_input.rs b/winit/src/from_keyboard_input.rs index ad7cb7546..444c3bf0a 100644 --- a/winit/src/from_keyboard_input.rs +++ b/winit/src/from_keyboard_input.rs @@ -1,7 +1,5 @@ use ribir_core::prelude::KeyboardInput as RibirKeyboardInput; -use winit::{ - event::KeyboardInput as WinitKeyboardInput, event::ModifiersState as WinitModifiersState, -}; +use winit::event::KeyboardInput as WinitKeyboardInput; use crate::prelude::{WrappedElementState, WrappedVirtualKeyCode}; @@ -12,10 +10,6 @@ impl From for WrappedKeyboardInput { fn from(value: WinitKeyboardInput) -> Self { WrappedKeyboardInput(value) } } -impl From for WinitKeyboardInput { - fn from(val: WrappedKeyboardInput) -> Self { val.0 } -} - impl From for RibirKeyboardInput { fn from(val: WrappedKeyboardInput) -> Self { RibirKeyboardInput { @@ -29,26 +23,12 @@ impl From for RibirKeyboardInput { } } -impl From for WrappedKeyboardInput { - #[allow(deprecated)] - fn from(value: RibirKeyboardInput) -> WrappedKeyboardInput { - WrappedKeyboardInput::from(WinitKeyboardInput { - scancode: value.scancode, - state: WrappedElementState::from(value.state).into(), - virtual_keycode: value - .virtual_keycode - .map(|v| WrappedVirtualKeyCode::from(v).into()), - modifiers: WinitModifiersState::default(), - }) - } -} - #[cfg(test)] mod tests { use super::*; use winit::{ event::ElementState as WinitElementState, event::KeyboardInput as WinitKeyboardInput, - event::VirtualKeyCode as WinitVirtualKeyCode, + event::ModifiersState as WinitModifiersState, event::VirtualKeyCode as WinitVirtualKeyCode, }; #[test] diff --git a/winit/src/from_modifiers.rs b/winit/src/from_modifiers.rs index c2a359074..58de68d99 100644 --- a/winit/src/from_modifiers.rs +++ b/winit/src/from_modifiers.rs @@ -7,10 +7,6 @@ impl From for WrappedModifiersState { fn from(value: WinitModifiersState) -> Self { WrappedModifiersState(value) } } -impl From for WinitModifiersState { - fn from(val: WrappedModifiersState) -> Self { val.0 } -} - impl From for RibirModifiersState { fn from(val: WrappedModifiersState) -> Self { let shift = if val.0.shift() { @@ -40,33 +36,3 @@ impl From for RibirModifiersState { shift | ctrl | alt | logo } } - -impl From for WrappedModifiersState { - fn from(value: RibirModifiersState) -> WrappedModifiersState { - let shift: WinitModifiersState = if value.shift() { - WinitModifiersState::SHIFT - } else { - WinitModifiersState::empty() - }; - - let ctrl: WinitModifiersState = if value.ctrl() { - WinitModifiersState::CTRL - } else { - WinitModifiersState::empty() - }; - - let alt: WinitModifiersState = if value.alt() { - WinitModifiersState::ALT - } else { - WinitModifiersState::empty() - }; - - let logo: WinitModifiersState = if value.logo() { - WinitModifiersState::LOGO - } else { - WinitModifiersState::empty() - }; - - (shift | ctrl | alt | logo).into() - } -} diff --git a/winit/src/from_mouse_scroll_delta.rs b/winit/src/from_mouse_scroll_delta.rs index b164ea139..66818af21 100644 --- a/winit/src/from_mouse_scroll_delta.rs +++ b/winit/src/from_mouse_scroll_delta.rs @@ -1,16 +1,14 @@ use ribir_core::events::MouseScrollDelta as RibirMouseScrollDelta; use winit::event::MouseScrollDelta as WinitMouseScrollDelta; -use crate::prelude::WrappedPhysicalPosition; +use crate::{from_event::ScaleToLogicalFactor, prelude::WrappedLogicalPosition}; -pub struct WrappedMouseScrollDelta(WinitMouseScrollDelta); +pub struct WrappedMouseScrollDelta(WinitMouseScrollDelta, ScaleToLogicalFactor); -impl From for WrappedMouseScrollDelta { - fn from(value: WinitMouseScrollDelta) -> Self { WrappedMouseScrollDelta(value) } -} - -impl From for WinitMouseScrollDelta { - fn from(val: WrappedMouseScrollDelta) -> Self { val.0 } +impl From<(WinitMouseScrollDelta, ScaleToLogicalFactor)> for WrappedMouseScrollDelta { + fn from(value: (WinitMouseScrollDelta, ScaleToLogicalFactor)) -> Self { + WrappedMouseScrollDelta(value.0, value.1) + } } impl From for RibirMouseScrollDelta { @@ -19,23 +17,9 @@ impl From for RibirMouseScrollDelta { WinitMouseScrollDelta::LineDelta(right, down) => { RibirMouseScrollDelta::LineDelta(right, down) } - WinitMouseScrollDelta::PixelDelta(pos) => { - RibirMouseScrollDelta::PixelDelta(WrappedPhysicalPosition::from(pos).into()) - } + WinitMouseScrollDelta::PixelDelta(pos) => RibirMouseScrollDelta::PixelDelta( + WrappedLogicalPosition::::from(pos.to_logical(val.1)).into(), + ), } } } - -impl From for WrappedMouseScrollDelta { - fn from(value: RibirMouseScrollDelta) -> WrappedMouseScrollDelta { - let es = match value { - RibirMouseScrollDelta::LineDelta(right, down) => { - WinitMouseScrollDelta::LineDelta(right, down) - } - RibirMouseScrollDelta::PixelDelta(pos) => { - WinitMouseScrollDelta::PixelDelta(WrappedPhysicalPosition::from(pos.cast()).into()) - } - }; - es.into() - } -} diff --git a/winit/src/from_touch_phase.rs b/winit/src/from_touch_phase.rs index c09f06727..eb1ee2bcc 100644 --- a/winit/src/from_touch_phase.rs +++ b/winit/src/from_touch_phase.rs @@ -7,10 +7,6 @@ impl From for WrappedTouchPhase { fn from(value: WinitTouchPhase) -> Self { WrappedTouchPhase(value) } } -impl From for WinitTouchPhase { - fn from(val: WrappedTouchPhase) -> Self { val.0 } -} - impl From for RibirTouchPhase { fn from(val: WrappedTouchPhase) -> Self { match val.0 { @@ -21,15 +17,3 @@ impl From for RibirTouchPhase { } } } - -impl From for WrappedTouchPhase { - fn from(value: RibirTouchPhase) -> WrappedTouchPhase { - let tb = match value { - RibirTouchPhase::Started => WinitTouchPhase::Started, - RibirTouchPhase::Moved => WinitTouchPhase::Moved, - RibirTouchPhase::Ended => WinitTouchPhase::Ended, - RibirTouchPhase::Cancelled => WinitTouchPhase::Cancelled, - }; - tb.into() - } -} diff --git a/winit/src/from_virtual_key_code.rs b/winit/src/from_virtual_key_code.rs index a5dc26a20..0aacbbcba 100644 --- a/winit/src/from_virtual_key_code.rs +++ b/winit/src/from_virtual_key_code.rs @@ -7,10 +7,6 @@ impl From for WrappedVirtualKeyCode { fn from(value: WinitVirtualKeyCode) -> Self { WrappedVirtualKeyCode(value) } } -impl From for WinitVirtualKeyCode { - fn from(val: WrappedVirtualKeyCode) -> Self { val.0 } -} - impl From for RibirVirtualKeyCode { fn from(val: WrappedVirtualKeyCode) -> Self { match val.0 { @@ -191,185 +187,3 @@ impl From for RibirVirtualKeyCode { } } } - -impl From for WrappedVirtualKeyCode { - fn from(value: RibirVirtualKeyCode) -> WrappedVirtualKeyCode { - let kc = match value { - RibirVirtualKeyCode::Key1 => WinitVirtualKeyCode::Key1, - RibirVirtualKeyCode::Key2 => WinitVirtualKeyCode::Key2, - RibirVirtualKeyCode::Key3 => WinitVirtualKeyCode::Key3, - RibirVirtualKeyCode::Key4 => WinitVirtualKeyCode::Key4, - RibirVirtualKeyCode::Key5 => WinitVirtualKeyCode::Key5, - RibirVirtualKeyCode::Key6 => WinitVirtualKeyCode::Key6, - RibirVirtualKeyCode::Key7 => WinitVirtualKeyCode::Key7, - RibirVirtualKeyCode::Key8 => WinitVirtualKeyCode::Key8, - RibirVirtualKeyCode::Key9 => WinitVirtualKeyCode::Key9, - RibirVirtualKeyCode::Key0 => WinitVirtualKeyCode::Key0, - - RibirVirtualKeyCode::A => WinitVirtualKeyCode::A, - RibirVirtualKeyCode::B => WinitVirtualKeyCode::B, - RibirVirtualKeyCode::C => WinitVirtualKeyCode::C, - RibirVirtualKeyCode::D => WinitVirtualKeyCode::D, - RibirVirtualKeyCode::E => WinitVirtualKeyCode::E, - RibirVirtualKeyCode::F => WinitVirtualKeyCode::F, - RibirVirtualKeyCode::G => WinitVirtualKeyCode::G, - RibirVirtualKeyCode::H => WinitVirtualKeyCode::H, - RibirVirtualKeyCode::I => WinitVirtualKeyCode::I, - RibirVirtualKeyCode::J => WinitVirtualKeyCode::J, - RibirVirtualKeyCode::K => WinitVirtualKeyCode::K, - RibirVirtualKeyCode::L => WinitVirtualKeyCode::L, - RibirVirtualKeyCode::M => WinitVirtualKeyCode::M, - RibirVirtualKeyCode::N => WinitVirtualKeyCode::N, - RibirVirtualKeyCode::O => WinitVirtualKeyCode::O, - RibirVirtualKeyCode::P => WinitVirtualKeyCode::P, - RibirVirtualKeyCode::Q => WinitVirtualKeyCode::Q, - RibirVirtualKeyCode::R => WinitVirtualKeyCode::R, - RibirVirtualKeyCode::S => WinitVirtualKeyCode::S, - RibirVirtualKeyCode::T => WinitVirtualKeyCode::T, - RibirVirtualKeyCode::U => WinitVirtualKeyCode::U, - RibirVirtualKeyCode::V => WinitVirtualKeyCode::V, - RibirVirtualKeyCode::W => WinitVirtualKeyCode::W, - RibirVirtualKeyCode::X => WinitVirtualKeyCode::X, - RibirVirtualKeyCode::Y => WinitVirtualKeyCode::Y, - RibirVirtualKeyCode::Z => WinitVirtualKeyCode::Z, - - RibirVirtualKeyCode::Escape => WinitVirtualKeyCode::Escape, - - RibirVirtualKeyCode::F1 => WinitVirtualKeyCode::F1, - RibirVirtualKeyCode::F2 => WinitVirtualKeyCode::F2, - RibirVirtualKeyCode::F3 => WinitVirtualKeyCode::F3, - RibirVirtualKeyCode::F4 => WinitVirtualKeyCode::F4, - RibirVirtualKeyCode::F5 => WinitVirtualKeyCode::F5, - RibirVirtualKeyCode::F6 => WinitVirtualKeyCode::F6, - RibirVirtualKeyCode::F7 => WinitVirtualKeyCode::F7, - RibirVirtualKeyCode::F8 => WinitVirtualKeyCode::F8, - RibirVirtualKeyCode::F9 => WinitVirtualKeyCode::F9, - RibirVirtualKeyCode::F10 => WinitVirtualKeyCode::F10, - RibirVirtualKeyCode::F11 => WinitVirtualKeyCode::F11, - RibirVirtualKeyCode::F12 => WinitVirtualKeyCode::F12, - RibirVirtualKeyCode::F13 => WinitVirtualKeyCode::F13, - RibirVirtualKeyCode::F14 => WinitVirtualKeyCode::F14, - RibirVirtualKeyCode::F15 => WinitVirtualKeyCode::F15, - RibirVirtualKeyCode::F16 => WinitVirtualKeyCode::F16, - RibirVirtualKeyCode::F17 => WinitVirtualKeyCode::F17, - RibirVirtualKeyCode::F18 => WinitVirtualKeyCode::F18, - RibirVirtualKeyCode::F19 => WinitVirtualKeyCode::F19, - RibirVirtualKeyCode::F20 => WinitVirtualKeyCode::F20, - RibirVirtualKeyCode::F21 => WinitVirtualKeyCode::F21, - RibirVirtualKeyCode::F22 => WinitVirtualKeyCode::F22, - RibirVirtualKeyCode::F23 => WinitVirtualKeyCode::F23, - RibirVirtualKeyCode::F24 => WinitVirtualKeyCode::F24, - - RibirVirtualKeyCode::Snapshot => WinitVirtualKeyCode::Snapshot, - RibirVirtualKeyCode::Scroll => WinitVirtualKeyCode::Scroll, - RibirVirtualKeyCode::Pause => WinitVirtualKeyCode::Pause, - - RibirVirtualKeyCode::Insert => WinitVirtualKeyCode::Insert, - RibirVirtualKeyCode::Home => WinitVirtualKeyCode::Home, - RibirVirtualKeyCode::Delete => WinitVirtualKeyCode::Delete, - RibirVirtualKeyCode::End => WinitVirtualKeyCode::End, - RibirVirtualKeyCode::PageDown => WinitVirtualKeyCode::PageDown, - RibirVirtualKeyCode::PageUp => WinitVirtualKeyCode::PageUp, - - RibirVirtualKeyCode::Left => WinitVirtualKeyCode::Left, - RibirVirtualKeyCode::Up => WinitVirtualKeyCode::Up, - RibirVirtualKeyCode::Right => WinitVirtualKeyCode::Right, - RibirVirtualKeyCode::Down => WinitVirtualKeyCode::Down, - - RibirVirtualKeyCode::Back => WinitVirtualKeyCode::Back, - RibirVirtualKeyCode::Return => WinitVirtualKeyCode::Return, - RibirVirtualKeyCode::Space => WinitVirtualKeyCode::Space, - - RibirVirtualKeyCode::Compose => WinitVirtualKeyCode::Compose, - - RibirVirtualKeyCode::Caret => WinitVirtualKeyCode::Caret, - - RibirVirtualKeyCode::Numlock => WinitVirtualKeyCode::Numlock, - RibirVirtualKeyCode::Numpad0 => WinitVirtualKeyCode::Numpad0, - RibirVirtualKeyCode::Numpad1 => WinitVirtualKeyCode::Numpad1, - RibirVirtualKeyCode::Numpad2 => WinitVirtualKeyCode::Numpad2, - RibirVirtualKeyCode::Numpad3 => WinitVirtualKeyCode::Numpad3, - RibirVirtualKeyCode::Numpad4 => WinitVirtualKeyCode::Numpad4, - RibirVirtualKeyCode::Numpad5 => WinitVirtualKeyCode::Numpad5, - RibirVirtualKeyCode::Numpad6 => WinitVirtualKeyCode::Numpad6, - RibirVirtualKeyCode::Numpad7 => WinitVirtualKeyCode::Numpad7, - RibirVirtualKeyCode::Numpad8 => WinitVirtualKeyCode::Numpad8, - RibirVirtualKeyCode::Numpad9 => WinitVirtualKeyCode::Numpad9, - RibirVirtualKeyCode::NumpadAdd => WinitVirtualKeyCode::NumpadAdd, - RibirVirtualKeyCode::NumpadDivide => WinitVirtualKeyCode::NumpadDivide, - RibirVirtualKeyCode::NumpadDecimal => WinitVirtualKeyCode::NumpadDecimal, - RibirVirtualKeyCode::NumpadComma => WinitVirtualKeyCode::NumpadComma, - RibirVirtualKeyCode::NumpadEnter => WinitVirtualKeyCode::NumpadEnter, - RibirVirtualKeyCode::NumpadEquals => WinitVirtualKeyCode::NumpadEquals, - RibirVirtualKeyCode::NumpadMultiply => WinitVirtualKeyCode::NumpadMultiply, - RibirVirtualKeyCode::NumpadSubtract => WinitVirtualKeyCode::NumpadSubtract, - - RibirVirtualKeyCode::AbntC1 => WinitVirtualKeyCode::AbntC1, - RibirVirtualKeyCode::AbntC2 => WinitVirtualKeyCode::AbntC2, - RibirVirtualKeyCode::Apostrophe => WinitVirtualKeyCode::Apostrophe, - RibirVirtualKeyCode::Apps => WinitVirtualKeyCode::Apps, - RibirVirtualKeyCode::Asterisk => WinitVirtualKeyCode::Asterisk, - RibirVirtualKeyCode::At => WinitVirtualKeyCode::At, - RibirVirtualKeyCode::Ax => WinitVirtualKeyCode::Ax, - RibirVirtualKeyCode::Backslash => WinitVirtualKeyCode::Backslash, - RibirVirtualKeyCode::Calculator => WinitVirtualKeyCode::Calculator, - RibirVirtualKeyCode::Capital => WinitVirtualKeyCode::Capital, - RibirVirtualKeyCode::Colon => WinitVirtualKeyCode::Colon, - RibirVirtualKeyCode::Comma => WinitVirtualKeyCode::Comma, - RibirVirtualKeyCode::Convert => WinitVirtualKeyCode::Convert, - RibirVirtualKeyCode::Equals => WinitVirtualKeyCode::Equals, - RibirVirtualKeyCode::Grave => WinitVirtualKeyCode::Grave, - RibirVirtualKeyCode::Kana => WinitVirtualKeyCode::Kana, - RibirVirtualKeyCode::Kanji => WinitVirtualKeyCode::Kanji, - RibirVirtualKeyCode::LAlt => WinitVirtualKeyCode::LAlt, - RibirVirtualKeyCode::LBracket => WinitVirtualKeyCode::LBracket, - RibirVirtualKeyCode::LControl => WinitVirtualKeyCode::LControl, - RibirVirtualKeyCode::LShift => WinitVirtualKeyCode::LShift, - RibirVirtualKeyCode::LWin => WinitVirtualKeyCode::LWin, - RibirVirtualKeyCode::Mail => WinitVirtualKeyCode::Mail, - RibirVirtualKeyCode::MediaSelect => WinitVirtualKeyCode::MediaSelect, - RibirVirtualKeyCode::MediaStop => WinitVirtualKeyCode::MediaStop, - RibirVirtualKeyCode::Minus => WinitVirtualKeyCode::Minus, - RibirVirtualKeyCode::Mute => WinitVirtualKeyCode::Mute, - RibirVirtualKeyCode::MyComputer => WinitVirtualKeyCode::MyComputer, - RibirVirtualKeyCode::NavigateForward => WinitVirtualKeyCode::NavigateForward, - RibirVirtualKeyCode::NavigateBackward => WinitVirtualKeyCode::NavigateBackward, - RibirVirtualKeyCode::NextTrack => WinitVirtualKeyCode::NextTrack, - RibirVirtualKeyCode::NoConvert => WinitVirtualKeyCode::NoConvert, - RibirVirtualKeyCode::OEM102 => WinitVirtualKeyCode::OEM102, - RibirVirtualKeyCode::Period => WinitVirtualKeyCode::Period, - RibirVirtualKeyCode::PlayPause => WinitVirtualKeyCode::PlayPause, - RibirVirtualKeyCode::Plus => WinitVirtualKeyCode::Plus, - RibirVirtualKeyCode::Power => WinitVirtualKeyCode::Power, - RibirVirtualKeyCode::PrevTrack => WinitVirtualKeyCode::PrevTrack, - RibirVirtualKeyCode::RAlt => WinitVirtualKeyCode::RAlt, - RibirVirtualKeyCode::RBracket => WinitVirtualKeyCode::RBracket, - RibirVirtualKeyCode::RControl => WinitVirtualKeyCode::RControl, - RibirVirtualKeyCode::RShift => WinitVirtualKeyCode::RShift, - RibirVirtualKeyCode::RWin => WinitVirtualKeyCode::RWin, - RibirVirtualKeyCode::Semicolon => WinitVirtualKeyCode::Semicolon, - RibirVirtualKeyCode::Slash => WinitVirtualKeyCode::Slash, - RibirVirtualKeyCode::Sleep => WinitVirtualKeyCode::Sleep, - RibirVirtualKeyCode::Stop => WinitVirtualKeyCode::Stop, - RibirVirtualKeyCode::Sysrq => WinitVirtualKeyCode::Sysrq, - RibirVirtualKeyCode::Tab => WinitVirtualKeyCode::Tab, - RibirVirtualKeyCode::Underline => WinitVirtualKeyCode::Underline, - RibirVirtualKeyCode::Unlabeled => WinitVirtualKeyCode::Unlabeled, - RibirVirtualKeyCode::VolumeDown => WinitVirtualKeyCode::VolumeDown, - RibirVirtualKeyCode::VolumeUp => WinitVirtualKeyCode::VolumeUp, - RibirVirtualKeyCode::Wake => WinitVirtualKeyCode::Wake, - RibirVirtualKeyCode::WebBack => WinitVirtualKeyCode::WebBack, - RibirVirtualKeyCode::WebFavorites => WinitVirtualKeyCode::WebFavorites, - RibirVirtualKeyCode::WebForward => WinitVirtualKeyCode::WebForward, - RibirVirtualKeyCode::WebHome => WinitVirtualKeyCode::WebHome, - RibirVirtualKeyCode::WebRefresh => WinitVirtualKeyCode::WebRefresh, - RibirVirtualKeyCode::WebSearch => WinitVirtualKeyCode::WebSearch, - RibirVirtualKeyCode::WebStop => WinitVirtualKeyCode::WebStop, - RibirVirtualKeyCode::Yen => WinitVirtualKeyCode::Yen, - RibirVirtualKeyCode::Copy => WinitVirtualKeyCode::Copy, - RibirVirtualKeyCode::Paste => WinitVirtualKeyCode::Paste, - RibirVirtualKeyCode::Cut => WinitVirtualKeyCode::Cut, - }; - kc.into() - } -} diff --git a/winit/src/from_window.rs b/winit/src/from_window.rs index d074f0ded..ee84e2477 100644 --- a/winit/src/from_window.rs +++ b/winit/src/from_window.rs @@ -71,42 +71,3 @@ impl RibirRawWindow for WrappedWindow { impl From for WrappedWindow { fn from(value: WinitWindow) -> Self { WrappedWindow(value) } } - -impl From for WinitWindow { - fn from(val: WrappedWindow) -> Self { val.0 } -} - -// impl From> for WrappedWindow { -// fn from(value: Box) -> Self { -// let core_window = value -// .as_ref() -// .as_any() -// .downcast_ref::() -// .map(|v| v) -// .unwrap(); -// (*core_window).into() -// } -// } - -// impl From<&Box> for WrappedWindow { -// fn from(value: &Box) -> Self { -// let winit_window = value -// .as_ref() -// .as_any() -// .downcast_ref::() -// .map(|v| *(v.to_owned())) -// .unwrap(); -// winit_window.into() -// } -// } - -// impl From<&dyn CoreWindow> for WrappedWindow { -// fn from(value: &dyn CoreWindow) -> Self { -// let winit_window = value -// .as_any() -// .downcast_ref::() -// .map(|v| *(v.to_owned())) -// .unwrap(); -// winit_window.into() -// } -// } diff --git a/winit/src/from_window_id.rs b/winit/src/from_window_id.rs index 26d7168aa..d3137013c 100644 --- a/winit/src/from_window_id.rs +++ b/winit/src/from_window_id.rs @@ -7,7 +7,6 @@ use winit::window::WindowId as WinitWindowId; pub struct WrappedWindowId(WinitWindowId); impl RibirWindowId for WrappedWindowId { - // fn as_any(&self) -> &dyn Any { self } fn into_any(self: Box) -> Box { self } fn equals(&self, other: &Box) -> bool { @@ -40,22 +39,6 @@ impl From for Box { fn from(value: WrappedWindowId) -> Self { Box::new(value) } } -// impl From<&Box> for WrappedWindowId { -// fn from(value: &Box) -> Self { -// // let x = *value; -// value.as_boxed_any().downcast_ref::().unwrap() -// } -// } - -// impl From> for WrappedWindowId { -// fn from(value: Box) -> Self { -// value -// .into_any() -// .downcast::() -// .unwrap() -// } -// } - #[cfg(test)] mod tests { use super::*; diff --git a/winit/src/shell_window.rs b/winit/src/shell_window.rs index b3813a7bf..3ab90751f 100644 --- a/winit/src/shell_window.rs +++ b/winit/src/shell_window.rs @@ -58,7 +58,9 @@ impl ShellWindow for PlatformShellWindow { *control = ControlFlow::Exit; } } else if let Some(wnd) = windows.get_mut(&window_id) { - wnd.processes_native_event(WrappedWindowEvent::from(event).into()); + wnd.processes_native_event( + WrappedWindowEvent::from((event, wnd.raw_window.scale_factor())).into(), + ); } } Event::MainEventsCleared => windows.iter_mut().for_each(|(_, wnd)| { diff --git a/winit/src/window_builder.rs b/winit/src/window_builder.rs index 31e60c050..0eefd10fb 100644 --- a/winit/src/window_builder.rs +++ b/winit/src/window_builder.rs @@ -14,6 +14,7 @@ use crate::{ pub struct WindowBuilder { inner_builder: winit::window::WindowBuilder, root: Widget, + config: WindowConfig, } impl WindowBuilder { @@ -46,7 +47,7 @@ impl WindowBuilder { inner_builder = inner_builder.with_resizable(resizable); } - if let Some(title) = config.title { + if let Some(title) = &config.title { inner_builder = inner_builder.with_title(title); } @@ -70,7 +71,11 @@ impl WindowBuilder { // inner_builder = inner_builder.with_window_icon(window_icon); // } - WindowBuilder { root: root_widget, inner_builder } + WindowBuilder { + root: root_widget, + inner_builder, + config, + } } pub fn build(self, shell_window: &PlatformShellWindow) -> RibirWindow { @@ -89,7 +94,12 @@ impl WindowBuilder { #[cfg(feature = "wgpu_gl")] #[inline] - pub fn build_headless(self, shell_window: &PlatformShellWindow, size: DeviceSize) -> RibirWindow { + pub fn build_headless(self, shell_window: &PlatformShellWindow) -> RibirWindow { + use ribir_geometry::{ScaleToPhysic, Size}; + + let size = self.config.inner_size.unwrap_or(Size::new(1024., 768.)); + let size: DeviceSize = ScaleToPhysic::new(1.).transform_size(size).cast(); + let native_wnd = self.inner_builder.build(shell_window.event_loop()).unwrap(); let ctx = shell_window.context().clone(); let p_backend = AppContext::wait_future(ribir_gpu::wgpu_backend_with_wnd(