diff --git a/winit-core/src/application.rs b/winit-core/src/application.rs index fcfc311..7027914 100644 --- a/winit-core/src/application.rs +++ b/winit-core/src/application.rs @@ -1,3 +1,4 @@ +use std::any::Any; use std::time::Instant; use crate::dpi::PhysicalSize; @@ -32,6 +33,11 @@ pub trait Application: ApplicationWindow { fn device_events_handelr(&mut self) -> Option<&mut dyn DeviceEventsHandler> { None } + + #[inline(always)] + fn as_any(&mut self) -> Option<&mut dyn Any> { + None + } } pub trait ApplicationWindow { diff --git a/winit-core/src/window.rs b/winit-core/src/window.rs index 6b3fc62..814609b 100644 --- a/winit-core/src/window.rs +++ b/winit-core/src/window.rs @@ -1,5 +1,7 @@ // TODO figure out how to do WindowId. +use std::any::Any; + pub use raw_window_handle::HasWindowHandle; pub use raw_window_handle_05::HasRawWindowHandle as HasRawWindowHandle05; @@ -35,6 +37,8 @@ pub trait Window: HasWindowHandle + HasRawWindowHandle05 { fn current_monitor(&self) -> Option; fn primary_monitor(&self) -> Option; + + fn as_any(&mut self) -> &mut dyn Any; } /// Attributes to use when creating a window. diff --git a/winit-wayland/examples/window.rs b/winit-wayland/examples/window.rs index 58f0062..f8a1a4f 100644 --- a/winit-wayland/examples/window.rs +++ b/winit-wayland/examples/window.rs @@ -6,6 +6,7 @@ use winit_core::dpi::PhysicalSize; use winit_core::event_loop::{EventLoopHandle, EventLoopRequests}; use winit_core::window::WindowId; use winit_wayland::event_loop::EventLoop; +use winit_wayland::MyCoolTrait; use softbuffer::{Context, Surface}; @@ -25,6 +26,12 @@ pub struct State { // In general, a generic interface to wakeup the loop and then the user can // `poll` the sources looks more appealing. +impl MyCoolTrait for State { + fn foo(&mut self) { + println!("Hello from user trait!"); + } +} + impl Application for State { fn user_wakeup(&mut self, _: &mut dyn EventLoopHandle) { println!("Wake up"); @@ -42,8 +49,14 @@ impl Application for State { fn loop_exiting(&mut self, _: &mut dyn EventLoopHandle) { println!("Exiting the loop"); } + + fn as_any(&mut self) -> Option<&mut dyn std::any::Any> { + Some(self) + } } +use winit_wayland::window::Window as WaylandWindow; + impl ApplicationWindow for State { fn created(&mut self, loop_handle: &mut dyn EventLoopHandle, window_id: WindowId) { let window = loop_handle.get_window(window_id).unwrap(); @@ -65,6 +78,7 @@ impl ApplicationWindow for State { println!("New size {size:?}"); let window = loop_handle.get_window_mut(window_id).unwrap(); window.request_redraw(); + window.as_any().downcast_mut::().unwrap().out_of_tree_method(); } fn scale_factor_changed( @@ -111,6 +125,8 @@ fn main() { let proxy = EventLoopRequests::::proxy(&mut event_loop); + event_loop.setup_my_cool_trait_handler::(); + // Test out the proxy. std::thread::spawn(move || loop { proxy.wakeup(); diff --git a/winit-wayland/src/event_loop.rs b/winit-wayland/src/event_loop.rs index 038cd07..d26a007 100644 --- a/winit-wayland/src/event_loop.rs +++ b/winit-wayland/src/event_loop.rs @@ -23,6 +23,7 @@ use winit_core::event_loop::{EventLoopHandle, EventLoopRequests}; use winit_core::window::{Window as CoreWindow, WindowId}; use crate::state::WinitState; +use crate::MyCoolTrait; pub struct EventLoop { state: RuntimeState, @@ -55,6 +56,7 @@ where let mut state = RuntimeState { user: None, winit: WinitState::new(connection.clone(), &globals, &queue_handle, proxy).unwrap(), + vtable: Default::default(), }; let _ = event_queue.roundtrip(&mut state); @@ -123,6 +125,16 @@ where } } +use std::any::Any; + +impl EventLoop { + pub fn setup_my_cool_trait_handler(&mut self) { + self.state.vtable.foo = Some(|app: &mut dyn Application| { + app.as_any().expect("as_any not implemented").downcast_mut::().unwrap().foo() + }) + } +} + impl HasDisplayHandle for EventLoop { fn display_handle(&self) -> Result, HandleError> { self.state.winit.display_handle() @@ -142,6 +154,18 @@ pub(crate) struct RuntimeState { /// The state of the winit. pub winit: WinitState, + + pub vtable: VTable, +} + +pub struct VTable { + pub foo: Option, +} + +impl Default for VTable { + fn default() -> Self { + Self { foo: None } + } } pub struct EventLoopProxy { diff --git a/winit-wayland/src/lib.rs b/winit-wayland/src/lib.rs index c60648f..cdcd3e9 100644 --- a/winit-wayland/src/lib.rs +++ b/winit-wayland/src/lib.rs @@ -6,6 +6,7 @@ use sctk::reexports::client::protocol::wl_output::WlOutput; use sctk::reexports::client::protocol::wl_surface::WlSurface; use sctk::reexports::client::Proxy; +use winit_core::application::Application; use winit_core::dpi::{LogicalSize, PhysicalSize}; use winit_core::monitor::MonitorId; use winit_core::window::WindowId; @@ -36,3 +37,7 @@ pub(crate) fn logical_to_physical_rounded( let height = size.height as f64 * scale_factor; (width.round(), height.round()).into() } + +pub trait MyCoolTrait: Application + 'static { + fn foo(&mut self); +} diff --git a/winit-wayland/src/window.rs b/winit-wayland/src/window.rs index 28af5b6..9260fc9 100644 --- a/winit-wayland/src/window.rs +++ b/winit-wayland/src/window.rs @@ -165,6 +165,10 @@ impl Window { window } + pub fn out_of_tree_method(&mut self) { + println!("Calling out-of-tree method"); + } + /// Set the resizable state on the window. #[inline] pub fn set_resizable(&mut self, resizable: bool) { @@ -299,6 +303,10 @@ impl CoreWindow for Window { crate::make_wid(&self.window.wl_surface()) } + fn as_any(&mut self) -> &mut dyn std::any::Any { + self + } + fn request_redraw(&mut self) { self.redraw = true; } @@ -462,6 +470,10 @@ impl WindowHandler for RuntimeState { window.resize(new_size); + if let Some(foo) = self.vtable.foo { + foo(*user); + } + // NOTE: we consider window as created when its initial configure arrives, until // then it's considered as not created and attempt to get it will result in // error.