Skip to content

Commit

Permalink
api: convert Window to dyn Window
Browse files Browse the repository at this point in the history
This should allow us to make future split of backends much easier.
The `Box<dyn Window>` is a _temporary_ solution, which will be
removed with the future updates when we decide on how the Window
should be stored.
  • Loading branch information
kchibisov authored Aug 23, 2024
1 parent e716adc commit 241b7a8
Show file tree
Hide file tree
Showing 41 changed files with 2,314 additions and 2,137 deletions.
17 changes: 10 additions & 7 deletions examples/child_window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,20 @@ fn main() -> Result<(), impl std::error::Error> {
use winit::event::{ElementState, KeyEvent, WindowEvent};
use winit::event_loop::{ActiveEventLoop, EventLoop};
use winit::raw_window_handle::HasRawWindowHandle;
use winit::window::{Window, WindowId};
use winit::window::{Window, WindowAttributes, WindowId};

#[path = "util/fill.rs"]
mod fill;

#[derive(Default)]
struct Application {
parent_window_id: Option<WindowId>,
windows: HashMap<WindowId, Window>,
windows: HashMap<WindowId, Box<dyn Window>>,
}

impl ApplicationHandler for Application {
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
let attributes = Window::default_attributes()
let attributes = WindowAttributes::default()
.with_title("parent window")
.with_position(Position::Logical(LogicalPosition::new(0.0, 0.0)))
.with_inner_size(LogicalSize::new(640.0f32, 480.0f32));
Expand Down Expand Up @@ -57,24 +57,27 @@ fn main() -> Result<(), impl std::error::Error> {
..
} => {
let parent_window = self.windows.get(&self.parent_window_id.unwrap()).unwrap();
let child_window = spawn_child_window(parent_window, event_loop);
let child_window = spawn_child_window(parent_window.as_ref(), event_loop);
let child_id = child_window.id();
println!("Child window created with id: {child_id:?}");
self.windows.insert(child_id, child_window);
},
WindowEvent::RedrawRequested => {
if let Some(window) = self.windows.get(&window_id) {
fill::fill_window(window);
fill::fill_window(window.as_ref());
}
},
_ => (),
}
}
}

fn spawn_child_window(parent: &Window, event_loop: &dyn ActiveEventLoop) -> Window {
fn spawn_child_window(
parent: &dyn Window,
event_loop: &dyn ActiveEventLoop,
) -> Box<dyn Window> {
let parent = parent.raw_window_handle().unwrap();
let mut window_attributes = Window::default_attributes()
let mut window_attributes = WindowAttributes::default()
.with_title("child window")
.with_inner_size(LogicalSize::new(200.0f32, 200.0f32))
.with_position(Position::Logical(LogicalPosition::new(0.0, 0.0)))
Expand Down
8 changes: 4 additions & 4 deletions examples/control_flow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use winit::application::ApplicationHandler;
use winit::event::{ElementState, KeyEvent, StartCause, WindowEvent};
use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop};
use winit::keyboard::{Key, NamedKey};
use winit::window::{Window, WindowId};
use winit::window::{Window, WindowAttributes, WindowId};

#[path = "util/fill.rs"]
mod fill;
Expand Down Expand Up @@ -52,7 +52,7 @@ struct ControlFlowDemo {
request_redraw: bool,
wait_cancelled: bool,
close_requested: bool,
window: Option<Window>,
window: Option<Box<dyn Window>>,
}

impl ApplicationHandler for ControlFlowDemo {
Expand All @@ -66,7 +66,7 @@ impl ApplicationHandler for ControlFlowDemo {
}

fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
let window_attributes = Window::default_attributes().with_title(
let window_attributes = WindowAttributes::default().with_title(
"Press 1, 2, 3 to change control flow mode. Press R to toggle redraw requests.",
);
self.window = Some(event_loop.create_window(window_attributes).unwrap());
Expand Down Expand Up @@ -114,7 +114,7 @@ impl ApplicationHandler for ControlFlowDemo {
WindowEvent::RedrawRequested => {
let window = self.window.as_ref().unwrap();
window.pre_present_notify();
fill::fill_window(window);
fill::fill_window(window.as_ref());
},
_ => (),
}
Expand Down
8 changes: 4 additions & 4 deletions examples/pump_events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,19 @@ fn main() -> std::process::ExitCode {
use winit::event::WindowEvent;
use winit::event_loop::{ActiveEventLoop, EventLoop};
use winit::platform::pump_events::{EventLoopExtPumpEvents, PumpStatus};
use winit::window::{Window, WindowId};
use winit::window::{Window, WindowAttributes, WindowId};

#[path = "util/fill.rs"]
mod fill;

#[derive(Default)]
struct PumpDemo {
window: Option<Window>,
window: Option<Box<dyn Window>>,
}

impl ApplicationHandler for PumpDemo {
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
let window_attributes = Window::default_attributes().with_title("A fantastic window!");
let window_attributes = WindowAttributes::default().with_title("A fantastic window!");
self.window = Some(event_loop.create_window(window_attributes).unwrap());
}

Expand All @@ -43,7 +43,7 @@ fn main() -> std::process::ExitCode {
match event {
WindowEvent::CloseRequested => event_loop.exit(),
WindowEvent::RedrawRequested => {
fill::fill_window(window);
fill::fill_window(window.as_ref());
window.request_redraw();
},
_ => (),
Expand Down
10 changes: 5 additions & 5 deletions examples/run_on_demand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
use winit::event::WindowEvent;
use winit::event_loop::{ActiveEventLoop, EventLoop};
use winit::platform::run_on_demand::EventLoopExtRunOnDemand;
use winit::window::{Window, WindowId};
use winit::window::{Window, WindowAttributes, WindowId};

#[path = "util/fill.rs"]
mod fill;
Expand All @@ -18,7 +18,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
struct App {
idx: usize,
window_id: Option<WindowId>,
window: Option<Window>,
window: Option<Box<dyn Window>>,
}

impl ApplicationHandler for App {
Expand All @@ -29,7 +29,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
}

fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
let window_attributes = Window::default_attributes()
let window_attributes = WindowAttributes::default()
.with_title("Fantastic window number one!")
.with_inner_size(winit::dpi::LogicalSize::new(128.0, 128.0));
let window = event_loop.create_window(window_attributes).unwrap();
Expand Down Expand Up @@ -65,11 +65,11 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
CloseRequested",
self.idx
);
fill::cleanup_window(window);
fill::cleanup_window(window.as_ref());
self.window = None;
},
WindowEvent::RedrawRequested => {
fill::fill_window(window);
fill::fill_window(window.as_ref());
},
_ => (),
}
Expand Down
28 changes: 15 additions & 13 deletions examples/util/fill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,41 +34,43 @@ mod platform {
/// The graphics context used to draw to a window.
struct GraphicsContext {
/// The global softbuffer context.
context: RefCell<Context<&'static Window>>,
context: RefCell<Context<&'static dyn Window>>,

/// The hash map of window IDs to surfaces.
surfaces: HashMap<WindowId, Surface<&'static Window, &'static Window>>,
surfaces: HashMap<WindowId, Surface<&'static dyn Window, &'static dyn Window>>,
}

impl GraphicsContext {
fn new(w: &Window) -> Self {
fn new(w: &dyn Window) -> Self {
Self {
context: RefCell::new(
Context::new(unsafe { mem::transmute::<&'_ Window, &'static Window>(w) })
.expect("Failed to create a softbuffer context"),
Context::new(unsafe {
mem::transmute::<&'_ dyn Window, &'static dyn Window>(w)
})
.expect("Failed to create a softbuffer context"),
),
surfaces: HashMap::new(),
}
}

fn create_surface(
&mut self,
window: &Window,
) -> &mut Surface<&'static Window, &'static Window> {
window: &dyn Window,
) -> &mut Surface<&'static dyn Window, &'static dyn Window> {
self.surfaces.entry(window.id()).or_insert_with(|| {
Surface::new(&self.context.borrow(), unsafe {
mem::transmute::<&'_ Window, &'static Window>(window)
mem::transmute::<&'_ dyn Window, &'static dyn Window>(window)
})
.expect("Failed to create a softbuffer surface")
})
}

fn destroy_surface(&mut self, window: &Window) {
fn destroy_surface(&mut self, window: &dyn Window) {
self.surfaces.remove(&window.id());
}
}

pub fn fill_window(window: &Window) {
pub fn fill_window(window: &dyn Window) {
GC.with(|gc| {
let size = window.inner_size();
let (Some(width), Some(height)) =
Expand All @@ -94,7 +96,7 @@ mod platform {
}

#[allow(dead_code)]
pub fn cleanup_window(window: &Window) {
pub fn cleanup_window(window: &dyn Window) {
GC.with(|gc| {
let mut gc = gc.borrow_mut();
if let Some(context) = gc.as_mut() {
Expand All @@ -106,12 +108,12 @@ mod platform {

#[cfg(not(all(feature = "rwh_06", not(any(target_os = "android", target_os = "ios")))))]
mod platform {
pub fn fill_window(_window: &winit::window::Window) {
pub fn fill_window(_window: &dyn winit::window::Window) {
// No-op on mobile platforms.
}

#[allow(dead_code)]
pub fn cleanup_window(_window: &winit::window::Window) {
pub fn cleanup_window(_window: &dyn winit::window::Window) {
// No-op on mobile platforms.
}
}
28 changes: 14 additions & 14 deletions examples/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use winit::platform::startup_notify::{
use winit::platform::web::{ActiveEventLoopExtWeb, CustomCursorExtWeb, WindowAttributesExtWeb};
use winit::window::{
Cursor, CursorGrabMode, CustomCursor, CustomCursorSource, Fullscreen, Icon, ResizeDirection,
Theme, Window, WindowId,
Theme, Window, WindowAttributes, WindowId,
};

#[path = "util/tracing.rs"]
Expand Down Expand Up @@ -135,7 +135,7 @@ impl Application {
// TODO read-out activation token.

#[allow(unused_mut)]
let mut window_attributes = Window::default_attributes()
let mut window_attributes = WindowAttributes::default()
.with_title("Winit window")
.with_transparent(true)
.with_window_icon(Some(self.icon.clone()));
Expand Down Expand Up @@ -560,9 +560,9 @@ struct WindowState {
///
/// NOTE: This surface must be dropped before the `Window`.
#[cfg(not(any(android_platform, ios_platform)))]
surface: Surface<DisplayHandle<'static>, Arc<Window>>,
surface: Surface<DisplayHandle<'static>, Arc<dyn Window>>,
/// The actual winit Window.
window: Arc<Window>,
window: Arc<dyn Window>,
/// The window theme we're drawing with.
theme: Theme,
/// Cursor position over the window.
Expand Down Expand Up @@ -590,8 +590,8 @@ struct WindowState {
}

impl WindowState {
fn new(app: &Application, window: Window) -> Result<Self, Box<dyn Error>> {
let window = Arc::new(window);
fn new(app: &Application, window: Box<dyn Window>) -> Result<Self, Box<dyn Error>> {
let window: Arc<dyn Window> = Arc::from(window);

// SAFETY: the surface is dropped before the `window` which provided it with handle, thus
// it doesn't outlive it.
Expand All @@ -601,7 +601,7 @@ impl WindowState {
let theme = window.theme().unwrap_or(Theme::Dark);
info!("Theme: {theme:?}");
let named_idx = 0;
window.set_cursor(CURSORS[named_idx]);
window.set_cursor(CURSORS[named_idx].into());

// Allow IME out of the box.
let ime = true;
Expand Down Expand Up @@ -636,7 +636,7 @@ impl WindowState {
self.ime = !self.ime;
self.window.set_ime_allowed(self.ime);
if let Some(position) = self.ime.then_some(self.cursor_position).flatten() {
self.window.set_ime_cursor_area(position, PhysicalSize::new(20, 20));
self.window.set_ime_cursor_area(position.into(), PhysicalSize::new(20, 20).into());
}
}

Expand All @@ -647,7 +647,7 @@ impl WindowState {
pub fn cursor_moved(&mut self, position: PhysicalPosition<f64>) {
self.cursor_position = Some(position);
if self.ime {
self.window.set_ime_cursor_area(position, PhysicalSize::new(20, 20));
self.window.set_ime_cursor_area(position.into(), PhysicalSize::new(20, 20).into());
}
}

Expand Down Expand Up @@ -683,7 +683,7 @@ impl WindowState {
fn toggle_resize_increments(&mut self) {
let new_increments = match self.window.resize_increments() {
Some(_) => None,
None => Some(LogicalSize::new(25.0, 25.0)),
None => Some(LogicalSize::new(25.0, 25.0).into()),
};
info!("Had increments: {}", new_increments.is_none());
self.window.set_resize_increments(new_increments);
Expand Down Expand Up @@ -733,7 +733,7 @@ impl WindowState {
mem::swap(&mut inner_size.width, &mut inner_size.height);
info!("Requesting resize from {old_inner_size:?} to {inner_size:?}");

if let Some(new_inner_size) = self.window.request_inner_size(inner_size) {
if let Some(new_inner_size) = self.window.request_inner_size(inner_size.into()) {
if old_inner_size == new_inner_size {
info!("Inner size change got ignored");
} else {
Expand Down Expand Up @@ -766,7 +766,7 @@ impl WindowState {
) -> Result<(), Box<dyn Error>> {
let cursor = event_loop.create_custom_cursor(url_custom_cursor())?;

self.window.set_cursor(cursor);
self.window.set_cursor(cursor.into());

Ok(())
}
Expand All @@ -788,7 +788,7 @@ impl WindowState {
let cursor = CustomCursor::from_animation(Duration::from_secs(3), cursors).unwrap();
let cursor = event_loop.create_custom_cursor(cursor)?;

self.window.set_cursor(cursor);
self.window.set_cursor(cursor.into());

Ok(())
}
Expand Down Expand Up @@ -817,7 +817,7 @@ impl WindowState {
/// Show window menu.
fn show_menu(&self) {
if let Some(position) = self.cursor_position {
self.window.show_window_menu(position);
self.window.show_window_menu(position.into());
}
}

Expand Down
8 changes: 4 additions & 4 deletions examples/x11_embed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,19 @@ fn main() -> Result<(), Box<dyn Error>> {
use winit::event::WindowEvent;
use winit::event_loop::{ActiveEventLoop, EventLoop};
use winit::platform::x11::WindowAttributesExtX11;
use winit::window::{Window, WindowId};
use winit::window::{Window, WindowAttributes, WindowId};

#[path = "util/fill.rs"]
mod fill;

pub struct XEmbedDemo {
parent_window_id: u32,
window: Option<Window>,
window: Option<Box<dyn Window>>,
}

impl ApplicationHandler for XEmbedDemo {
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
let window_attributes = Window::default_attributes()
let window_attributes = WindowAttributes::default()
.with_title("An embedded window!")
.with_inner_size(winit::dpi::LogicalSize::new(128.0, 128.0))
.with_embed_parent_window(self.parent_window_id);
Expand All @@ -38,7 +38,7 @@ fn main() -> Result<(), Box<dyn Error>> {
WindowEvent::CloseRequested => event_loop.exit(),
WindowEvent::RedrawRequested => {
window.pre_present_notify();
fill::fill_window(window);
fill::fill_window(window.as_ref());
},
_ => (),
}
Expand Down
2 changes: 2 additions & 0 deletions src/changelog/unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ changelog entry.
### Changed

- Change `ActiveEventLoop` to be a trait.
- Change `Window` to be a trait.
- `ActiveEventLoop::create_window` now returns `Box<dyn Window>`.
- `ApplicationHandler` now uses `dyn ActiveEventLoop`.
- On Web, let events wake up event loop immediately when using `ControlFlow::Poll`.
- Bump MSRV from `1.70` to `1.73`.
Expand Down
Loading

0 comments on commit 241b7a8

Please sign in to comment.