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

Allow specifying an initialization closure in EventLoop::run #3895

Open
wants to merge 1 commit into
base: master
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
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
Loading