Skip to content

Commit

Permalink
Allow specifying an initialization closure
Browse files Browse the repository at this point in the history
  • Loading branch information
madsmtm committed Sep 1, 2024
1 parent 241b7a8 commit f6a520e
Show file tree
Hide file tree
Showing 26 changed files with 469 additions and 414 deletions.
34 changes: 17 additions & 17 deletions examples/child_window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,12 @@ fn main() -> Result<(), impl std::error::Error> {
#[path = "util/fill.rs"]
mod fill;

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

impl ApplicationHandler for Application {
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
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));
let window = event_loop.create_window(attributes).unwrap();

println!("Parent window id: {:?})", window.id());
self.parent_window_id = Some(window.id());

self.windows.insert(window.id(), window);
}

fn window_event(
&mut self,
event_loop: &dyn ActiveEventLoop,
Expand All @@ -56,7 +42,7 @@ fn main() -> Result<(), impl std::error::Error> {
event: KeyEvent { state: ElementState::Pressed, .. },
..
} => {
let parent_window = self.windows.get(&self.parent_window_id.unwrap()).unwrap();
let parent_window = self.windows.get(&self.parent_window_id).unwrap();
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:?}");
Expand All @@ -72,6 +58,20 @@ fn main() -> Result<(), impl std::error::Error> {
}
}

fn init(event_loop: &dyn ActiveEventLoop) -> Application {
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));
let window = event_loop.create_window(attributes).unwrap();

println!("Parent window id: {:?})", window.id());

let parent_window_id = window.id();
let windows = HashMap::from([(window.id(), window)]);
Application { parent_window_id, windows }
}

fn spawn_child_window(
parent: &dyn Window,
event_loop: &dyn ActiveEventLoop,
Expand All @@ -89,7 +89,7 @@ fn main() -> Result<(), impl std::error::Error> {
}

let event_loop = EventLoop::new().unwrap();
event_loop.run_app(Application::default())
event_loop.run(init)
}

#[cfg(not(any(x11_platform, macos_platform, windows_platform)))]
Expand Down
35 changes: 21 additions & 14 deletions examples/control_flow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,31 @@ fn main() -> Result<(), impl std::error::Error> {

let event_loop = EventLoop::new().unwrap();

event_loop.run_app(ControlFlowDemo::default())
event_loop.run(ControlFlowDemo::new)
}

#[derive(Default)]
struct ControlFlowDemo {
mode: Mode,
request_redraw: bool,
wait_cancelled: bool,
close_requested: bool,
window: Option<Box<dyn Window>>,
window: Box<dyn Window>,
}

impl ControlFlowDemo {
fn new(event_loop: &dyn ActiveEventLoop) -> Self {
let window_attributes = WindowAttributes::default().with_title(
"Press 1, 2, 3 to change control flow mode. Press R to toggle redraw requests.",
);
let window = event_loop.create_window(window_attributes).unwrap();
Self {
mode: Mode::default(),
request_redraw: false,
wait_cancelled: false,
close_requested: false,
window,
}
}
}

impl ApplicationHandler for ControlFlowDemo {
Expand All @@ -65,13 +80,6 @@ impl ApplicationHandler for ControlFlowDemo {
}
}

fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
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());
}

fn window_event(
&mut self,
_event_loop: &dyn ActiveEventLoop,
Expand Down Expand Up @@ -112,17 +120,16 @@ impl ApplicationHandler for ControlFlowDemo {
_ => (),
},
WindowEvent::RedrawRequested => {
let window = self.window.as_ref().unwrap();
window.pre_present_notify();
fill::fill_window(window.as_ref());
self.window.pre_present_notify();
fill::fill_window(&*self.window);
},
_ => (),
}
}

fn about_to_wait(&mut self, event_loop: &dyn ActiveEventLoop) {
if self.request_redraw && !self.wait_cancelled && !self.close_requested {
self.window.as_ref().unwrap().request_redraw();
self.window.request_redraw();
}

match self.mode {
Expand Down
11 changes: 7 additions & 4 deletions examples/pump_events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ fn main() -> std::process::ExitCode {
use std::time::Duration;

use winit::application::ApplicationHandler;
use winit::event::WindowEvent;
use winit::event::{StartCause, WindowEvent};
use winit::event_loop::{ActiveEventLoop, EventLoop};
use winit::platform::pump_events::{EventLoopExtPumpEvents, PumpStatus};
use winit::window::{Window, WindowAttributes, WindowId};
Expand All @@ -22,9 +22,12 @@ fn main() -> std::process::ExitCode {
}

impl ApplicationHandler for PumpDemo {
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
let window_attributes = WindowAttributes::default().with_title("A fantastic window!");
self.window = Some(event_loop.create_window(window_attributes).unwrap());
fn new_events(&mut self, event_loop: &dyn ActiveEventLoop, cause: StartCause) {
if matches!(cause, StartCause::Init) && self.window.is_none() {
let window_attributes =
WindowAttributes::default().with_title("A fantastic window!");
self.window = Some(event_loop.create_window(window_attributes).unwrap());
}
}

fn window_event(
Expand Down
28 changes: 18 additions & 10 deletions examples/run_on_demand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,23 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
window: Option<Box<dyn Window>>,
}

impl ApplicationHandler for App {
fn about_to_wait(&mut self, _event_loop: &dyn ActiveEventLoop) {
if let Some(window) = self.window.as_ref() {
window.request_redraw();
}
}

fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
impl App {
fn init_window(&mut self, event_loop: &dyn ActiveEventLoop) {
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();
self.window_id = Some(window.id());
self.window = Some(window);
}
}

impl ApplicationHandler for App {
fn about_to_wait(&mut self, _event_loop: &dyn ActiveEventLoop) {
if let Some(window) = self.window.as_ref() {
window.request_redraw();
}
}

fn window_event(
&mut self,
Expand Down Expand Up @@ -81,14 +83,20 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut event_loop = EventLoop::new().unwrap();

let mut app = App { idx: 1, ..Default::default() };
event_loop.run_app_on_demand(&mut app)?;
event_loop.run_on_demand(|event_loop| {
app.init_window(event_loop);
&mut app
})?;

println!("--------------------------------------------------------- Finished first loop");
println!("--------------------------------------------------------- Waiting 5 seconds");
std::thread::sleep(Duration::from_secs(5));

app.idx += 1;
event_loop.run_app_on_demand(&mut app)?;
event_loop.run_on_demand(|event_loop| {
app.init_window(event_loop);
&mut app
})?;
println!("--------------------------------------------------------- Finished second loop");
Ok(())
}
Expand Down
81 changes: 45 additions & 36 deletions examples/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,7 @@ fn main() -> Result<(), Box<dyn Error>> {
});
}

let app = Application::new(&event_loop, receiver, sender);
Ok(event_loop.run_app(app)?)
Ok(event_loop.run(|event_loop| Application::new(event_loop, receiver, sender))?)
}

/// Application state and event handling.
Expand All @@ -84,21 +83,24 @@ struct Application {
///
/// With OpenGL it could be EGLDisplay.
#[cfg(not(any(android_platform, ios_platform)))]
context: Option<Context<DisplayHandle<'static>>>,
context: Context<DisplayHandle<'static>>,
}

impl Application {
fn new(event_loop: &EventLoop, receiver: Receiver<Action>, sender: Sender<Action>) -> Self {
// SAFETY: we drop the context right before the event loop is stopped, thus making it safe.
fn new(
event_loop: &dyn ActiveEventLoop,
receiver: Receiver<Action>,
sender: Sender<Action>,
) -> Self {
// SAFETY: The context is stored in the application, which is dropped right before the event
// loop is stopped, thus making it safe.
#[cfg(not(any(android_platform, ios_platform)))]
let context = Some(
Context::new(unsafe {
std::mem::transmute::<DisplayHandle<'_>, DisplayHandle<'static>>(
event_loop.display_handle().unwrap(),
)
})
.unwrap(),
);
let context = Context::new(unsafe {
std::mem::transmute::<DisplayHandle<'_>, DisplayHandle<'static>>(
event_loop.display_handle().unwrap(),
)
})
.unwrap();

// You'll have to choose an icon size at your own discretion. On X11, the desired size
// varies by WM, and on Windows, you still have to account for screen scaling. Here
Expand All @@ -116,15 +118,24 @@ impl Application {
.into_iter()
.collect();

Self {
let mut app = Self {
receiver,
sender,
#[cfg(not(any(android_platform, ios_platform)))]
context,
custom_cursors,
icon,
windows: Default::default(),
}
};

app.dump_monitors(event_loop);

// Create initial window.
app.create_window(event_loop, None).expect("failed to create initial window");

app.print_help();

app
}

fn create_window(
Expand Down Expand Up @@ -528,16 +539,6 @@ impl ApplicationHandler for Application {
info!("Device {device_id:?} event: {event:?}");
}

fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
info!("Ready to create surfaces");
self.dump_monitors(event_loop);

// Create initial window.
self.create_window(event_loop, None).expect("failed to create initial window");

self.print_help();
}

fn about_to_wait(&mut self, event_loop: &dyn ActiveEventLoop) {
if self.windows.is_empty() {
info!("No windows left, exiting...");
Expand All @@ -546,9 +547,17 @@ impl ApplicationHandler for Application {
}

#[cfg(not(any(android_platform, ios_platform)))]
fn exiting(&mut self, _event_loop: &dyn ActiveEventLoop) {
// We must drop the context here.
self.context = None;
fn destroy_surfaces(&mut self, _event_loop: &dyn ActiveEventLoop) {
for window in self.windows.values_mut() {
window.surface = None;
}
}

#[cfg(not(any(android_platform, ios_platform)))]
fn recreate_surfaces(&mut self, _event_loop: &dyn ActiveEventLoop) {
for window in self.windows.values_mut() {
window.surface = Some(Surface::new(&self.context, Arc::clone(&window.window)).unwrap());
}
}
}

Expand All @@ -557,10 +566,8 @@ struct WindowState {
/// IME input.
ime: bool,
/// Render surface.
///
/// NOTE: This surface must be dropped before the `Window`.
#[cfg(not(any(android_platform, ios_platform)))]
surface: Surface<DisplayHandle<'static>, Arc<dyn Window>>,
surface: Option<Surface<DisplayHandle<'static>, Arc<dyn Window>>>,
/// The actual winit Window.
window: Arc<dyn Window>,
/// The window theme we're drawing with.
Expand Down Expand Up @@ -593,10 +600,8 @@ impl WindowState {
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.
#[cfg(not(any(android_platform, ios_platform)))]
let surface = Surface::new(app.context.as_ref().unwrap(), Arc::clone(&window))?;
let surface = Some(Surface::new(&app.context, Arc::clone(&window))?);

let theme = window.theme().unwrap_or(Theme::Dark);
info!("Theme: {theme:?}");
Expand Down Expand Up @@ -803,7 +808,11 @@ impl WindowState {
(Some(width), Some(height)) => (width, height),
_ => return,
};
self.surface.resize(width, height).expect("failed to resize inner buffer");
self.surface
.as_mut()
.unwrap()
.resize(width, height)
.expect("failed to resize inner buffer");
}
self.window.request_redraw();
}
Expand Down Expand Up @@ -904,7 +913,7 @@ impl WindowState {
Theme::Dark => DARK_GRAY,
};

let mut buffer = self.surface.buffer_mut()?;
let mut buffer = self.surface.as_mut().unwrap().buffer_mut()?;
buffer.fill(color);
self.window.pre_present_notify();
buffer.present()?;
Expand Down
Loading

0 comments on commit f6a520e

Please sign in to comment.