Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extension via vtable with dyn #4

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions winit-core/src/application.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::any::Any;
use std::time::Instant;

use crate::dpi::PhysicalSize;
Expand Down Expand Up @@ -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 {
Expand Down
4 changes: 4 additions & 0 deletions winit-core/src/window.rs
Original file line number Diff line number Diff line change
@@ -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;

Expand Down Expand Up @@ -35,6 +37,8 @@ pub trait Window: HasWindowHandle + HasRawWindowHandle05 {
fn current_monitor(&self) -> Option<MonitorId>;

fn primary_monitor(&self) -> Option<MonitorId>;

fn as_any(&mut self) -> &mut dyn Any;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not possible?

Suggested change
fn as_any(&mut self) -> &mut dyn Any;
fn as_any(&mut self) -> &mut dyn Any {
self
}

What if we add Window: Any to the trait itself?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, it's not, because it'll require sized and it's not object safe, etc. it's not really a big issue though.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can try to pull my code and play with it, but it wasn't really working.

}

/// Attributes to use when creating a window.
Expand Down
16 changes: 16 additions & 0 deletions winit-wayland/examples/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand All @@ -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");
Expand All @@ -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();
Expand All @@ -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::<WaylandWindow>().unwrap().out_of_tree_method();
}

fn scale_factor_changed(
Expand Down Expand Up @@ -111,6 +125,8 @@ fn main() {

let proxy = EventLoopRequests::<State>::proxy(&mut event_loop);

event_loop.setup_my_cool_trait_handler::<State>();

// Test out the proxy.
std::thread::spawn(move || loop {
proxy.wakeup();
Expand Down
24 changes: 24 additions & 0 deletions winit-wayland/src/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -123,6 +125,16 @@ where
}
}

use std::any::Any;

impl EventLoop {
pub fn setup_my_cool_trait_handler<T: MyCoolTrait>(&mut self) {
self.state.vtable.foo = Some(|app: &mut dyn Application| {
app.as_any().expect("as_any not implemented").downcast_mut::<T>().unwrap().foo()
})
}
}

impl HasDisplayHandle for EventLoop {
fn display_handle(&self) -> Result<DisplayHandle<'_>, HandleError> {
self.state.winit.display_handle()
Expand All @@ -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<fn(&mut dyn Application)>,
}

impl Default for VTable {
fn default() -> Self {
Self { foo: None }
}
}

pub struct EventLoopProxy {
Expand Down
5 changes: 5 additions & 0 deletions winit-wayland/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
12 changes: 12 additions & 0 deletions winit-wayland/src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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.
Expand Down