Skip to content

Commit f6a520e

Browse files
committed
Allow specifying an initialization closure
1 parent 241b7a8 commit f6a520e

26 files changed

+469
-414
lines changed

examples/child_window.rs

+17-17
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,12 @@ fn main() -> Result<(), impl std::error::Error> {
1313
#[path = "util/fill.rs"]
1414
mod fill;
1515

16-
#[derive(Default)]
1716
struct Application {
18-
parent_window_id: Option<WindowId>,
17+
parent_window_id: WindowId,
1918
windows: HashMap<WindowId, Box<dyn Window>>,
2019
}
2120

2221
impl ApplicationHandler for Application {
23-
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
24-
let attributes = WindowAttributes::default()
25-
.with_title("parent window")
26-
.with_position(Position::Logical(LogicalPosition::new(0.0, 0.0)))
27-
.with_inner_size(LogicalSize::new(640.0f32, 480.0f32));
28-
let window = event_loop.create_window(attributes).unwrap();
29-
30-
println!("Parent window id: {:?})", window.id());
31-
self.parent_window_id = Some(window.id());
32-
33-
self.windows.insert(window.id(), window);
34-
}
35-
3622
fn window_event(
3723
&mut self,
3824
event_loop: &dyn ActiveEventLoop,
@@ -56,7 +42,7 @@ fn main() -> Result<(), impl std::error::Error> {
5642
event: KeyEvent { state: ElementState::Pressed, .. },
5743
..
5844
} => {
59-
let parent_window = self.windows.get(&self.parent_window_id.unwrap()).unwrap();
45+
let parent_window = self.windows.get(&self.parent_window_id).unwrap();
6046
let child_window = spawn_child_window(parent_window.as_ref(), event_loop);
6147
let child_id = child_window.id();
6248
println!("Child window created with id: {child_id:?}");
@@ -72,6 +58,20 @@ fn main() -> Result<(), impl std::error::Error> {
7258
}
7359
}
7460

61+
fn init(event_loop: &dyn ActiveEventLoop) -> Application {
62+
let attributes = WindowAttributes::default()
63+
.with_title("parent window")
64+
.with_position(Position::Logical(LogicalPosition::new(0.0, 0.0)))
65+
.with_inner_size(LogicalSize::new(640.0f32, 480.0f32));
66+
let window = event_loop.create_window(attributes).unwrap();
67+
68+
println!("Parent window id: {:?})", window.id());
69+
70+
let parent_window_id = window.id();
71+
let windows = HashMap::from([(window.id(), window)]);
72+
Application { parent_window_id, windows }
73+
}
74+
7575
fn spawn_child_window(
7676
parent: &dyn Window,
7777
event_loop: &dyn ActiveEventLoop,
@@ -89,7 +89,7 @@ fn main() -> Result<(), impl std::error::Error> {
8989
}
9090

9191
let event_loop = EventLoop::new().unwrap();
92-
event_loop.run_app(Application::default())
92+
event_loop.run(init)
9393
}
9494

9595
#[cfg(not(any(x11_platform, macos_platform, windows_platform)))]

examples/control_flow.rs

+21-14
Original file line numberDiff line numberDiff line change
@@ -43,16 +43,31 @@ fn main() -> Result<(), impl std::error::Error> {
4343

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

46-
event_loop.run_app(ControlFlowDemo::default())
46+
event_loop.run(ControlFlowDemo::new)
4747
}
4848

49-
#[derive(Default)]
5049
struct ControlFlowDemo {
5150
mode: Mode,
5251
request_redraw: bool,
5352
wait_cancelled: bool,
5453
close_requested: bool,
55-
window: Option<Box<dyn Window>>,
54+
window: Box<dyn Window>,
55+
}
56+
57+
impl ControlFlowDemo {
58+
fn new(event_loop: &dyn ActiveEventLoop) -> Self {
59+
let window_attributes = WindowAttributes::default().with_title(
60+
"Press 1, 2, 3 to change control flow mode. Press R to toggle redraw requests.",
61+
);
62+
let window = event_loop.create_window(window_attributes).unwrap();
63+
Self {
64+
mode: Mode::default(),
65+
request_redraw: false,
66+
wait_cancelled: false,
67+
close_requested: false,
68+
window,
69+
}
70+
}
5671
}
5772

5873
impl ApplicationHandler for ControlFlowDemo {
@@ -65,13 +80,6 @@ impl ApplicationHandler for ControlFlowDemo {
6580
}
6681
}
6782

68-
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
69-
let window_attributes = WindowAttributes::default().with_title(
70-
"Press 1, 2, 3 to change control flow mode. Press R to toggle redraw requests.",
71-
);
72-
self.window = Some(event_loop.create_window(window_attributes).unwrap());
73-
}
74-
7583
fn window_event(
7684
&mut self,
7785
_event_loop: &dyn ActiveEventLoop,
@@ -112,17 +120,16 @@ impl ApplicationHandler for ControlFlowDemo {
112120
_ => (),
113121
},
114122
WindowEvent::RedrawRequested => {
115-
let window = self.window.as_ref().unwrap();
116-
window.pre_present_notify();
117-
fill::fill_window(window.as_ref());
123+
self.window.pre_present_notify();
124+
fill::fill_window(&*self.window);
118125
},
119126
_ => (),
120127
}
121128
}
122129

123130
fn about_to_wait(&mut self, event_loop: &dyn ActiveEventLoop) {
124131
if self.request_redraw && !self.wait_cancelled && !self.close_requested {
125-
self.window.as_ref().unwrap().request_redraw();
132+
self.window.request_redraw();
126133
}
127134

128135
match self.mode {

examples/pump_events.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ fn main() -> std::process::ExitCode {
88
use std::time::Duration;
99

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

2424
impl ApplicationHandler for PumpDemo {
25-
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
26-
let window_attributes = WindowAttributes::default().with_title("A fantastic window!");
27-
self.window = Some(event_loop.create_window(window_attributes).unwrap());
25+
fn new_events(&mut self, event_loop: &dyn ActiveEventLoop, cause: StartCause) {
26+
if matches!(cause, StartCause::Init) && self.window.is_none() {
27+
let window_attributes =
28+
WindowAttributes::default().with_title("A fantastic window!");
29+
self.window = Some(event_loop.create_window(window_attributes).unwrap());
30+
}
2831
}
2932

3033
fn window_event(

examples/run_on_demand.rs

+18-10
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,23 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
2121
window: Option<Box<dyn Window>>,
2222
}
2323

24-
impl ApplicationHandler for App {
25-
fn about_to_wait(&mut self, _event_loop: &dyn ActiveEventLoop) {
26-
if let Some(window) = self.window.as_ref() {
27-
window.request_redraw();
28-
}
29-
}
30-
31-
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
24+
impl App {
25+
fn init_window(&mut self, event_loop: &dyn ActiveEventLoop) {
3226
let window_attributes = WindowAttributes::default()
3327
.with_title("Fantastic window number one!")
3428
.with_inner_size(winit::dpi::LogicalSize::new(128.0, 128.0));
3529
let window = event_loop.create_window(window_attributes).unwrap();
3630
self.window_id = Some(window.id());
3731
self.window = Some(window);
3832
}
33+
}
34+
35+
impl ApplicationHandler for App {
36+
fn about_to_wait(&mut self, _event_loop: &dyn ActiveEventLoop) {
37+
if let Some(window) = self.window.as_ref() {
38+
window.request_redraw();
39+
}
40+
}
3941

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

8385
let mut app = App { idx: 1, ..Default::default() };
84-
event_loop.run_app_on_demand(&mut app)?;
86+
event_loop.run_on_demand(|event_loop| {
87+
app.init_window(event_loop);
88+
&mut app
89+
})?;
8590

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

9095
app.idx += 1;
91-
event_loop.run_app_on_demand(&mut app)?;
96+
event_loop.run_on_demand(|event_loop| {
97+
app.init_window(event_loop);
98+
&mut app
99+
})?;
92100
println!("--------------------------------------------------------- Finished second loop");
93101
Ok(())
94102
}

examples/window.rs

+45-36
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,7 @@ fn main() -> Result<(), Box<dyn Error>> {
6666
});
6767
}
6868

69-
let app = Application::new(&event_loop, receiver, sender);
70-
Ok(event_loop.run_app(app)?)
69+
Ok(event_loop.run(|event_loop| Application::new(event_loop, receiver, sender))?)
7170
}
7271

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

9089
impl Application {
91-
fn new(event_loop: &EventLoop, receiver: Receiver<Action>, sender: Sender<Action>) -> Self {
92-
// SAFETY: we drop the context right before the event loop is stopped, thus making it safe.
90+
fn new(
91+
event_loop: &dyn ActiveEventLoop,
92+
receiver: Receiver<Action>,
93+
sender: Sender<Action>,
94+
) -> Self {
95+
// SAFETY: The context is stored in the application, which is dropped right before the event
96+
// loop is stopped, thus making it safe.
9397
#[cfg(not(any(android_platform, ios_platform)))]
94-
let context = Some(
95-
Context::new(unsafe {
96-
std::mem::transmute::<DisplayHandle<'_>, DisplayHandle<'static>>(
97-
event_loop.display_handle().unwrap(),
98-
)
99-
})
100-
.unwrap(),
101-
);
98+
let context = Context::new(unsafe {
99+
std::mem::transmute::<DisplayHandle<'_>, DisplayHandle<'static>>(
100+
event_loop.display_handle().unwrap(),
101+
)
102+
})
103+
.unwrap();
102104

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

119-
Self {
121+
let mut app = Self {
120122
receiver,
121123
sender,
122124
#[cfg(not(any(android_platform, ios_platform)))]
123125
context,
124126
custom_cursors,
125127
icon,
126128
windows: Default::default(),
127-
}
129+
};
130+
131+
app.dump_monitors(event_loop);
132+
133+
// Create initial window.
134+
app.create_window(event_loop, None).expect("failed to create initial window");
135+
136+
app.print_help();
137+
138+
app
128139
}
129140

130141
fn create_window(
@@ -528,16 +539,6 @@ impl ApplicationHandler for Application {
528539
info!("Device {device_id:?} event: {event:?}");
529540
}
530541

531-
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
532-
info!("Ready to create surfaces");
533-
self.dump_monitors(event_loop);
534-
535-
// Create initial window.
536-
self.create_window(event_loop, None).expect("failed to create initial window");
537-
538-
self.print_help();
539-
}
540-
541542
fn about_to_wait(&mut self, event_loop: &dyn ActiveEventLoop) {
542543
if self.windows.is_empty() {
543544
info!("No windows left, exiting...");
@@ -546,9 +547,17 @@ impl ApplicationHandler for Application {
546547
}
547548

548549
#[cfg(not(any(android_platform, ios_platform)))]
549-
fn exiting(&mut self, _event_loop: &dyn ActiveEventLoop) {
550-
// We must drop the context here.
551-
self.context = None;
550+
fn destroy_surfaces(&mut self, _event_loop: &dyn ActiveEventLoop) {
551+
for window in self.windows.values_mut() {
552+
window.surface = None;
553+
}
554+
}
555+
556+
#[cfg(not(any(android_platform, ios_platform)))]
557+
fn recreate_surfaces(&mut self, _event_loop: &dyn ActiveEventLoop) {
558+
for window in self.windows.values_mut() {
559+
window.surface = Some(Surface::new(&self.context, Arc::clone(&window.window)).unwrap());
560+
}
552561
}
553562
}
554563

@@ -557,10 +566,8 @@ struct WindowState {
557566
/// IME input.
558567
ime: bool,
559568
/// Render surface.
560-
///
561-
/// NOTE: This surface must be dropped before the `Window`.
562569
#[cfg(not(any(android_platform, ios_platform)))]
563-
surface: Surface<DisplayHandle<'static>, Arc<dyn Window>>,
570+
surface: Option<Surface<DisplayHandle<'static>, Arc<dyn Window>>>,
564571
/// The actual winit Window.
565572
window: Arc<dyn Window>,
566573
/// The window theme we're drawing with.
@@ -593,10 +600,8 @@ impl WindowState {
593600
fn new(app: &Application, window: Box<dyn Window>) -> Result<Self, Box<dyn Error>> {
594601
let window: Arc<dyn Window> = Arc::from(window);
595602

596-
// SAFETY: the surface is dropped before the `window` which provided it with handle, thus
597-
// it doesn't outlive it.
598603
#[cfg(not(any(android_platform, ios_platform)))]
599-
let surface = Surface::new(app.context.as_ref().unwrap(), Arc::clone(&window))?;
604+
let surface = Some(Surface::new(&app.context, Arc::clone(&window))?);
600605

601606
let theme = window.theme().unwrap_or(Theme::Dark);
602607
info!("Theme: {theme:?}");
@@ -803,7 +808,11 @@ impl WindowState {
803808
(Some(width), Some(height)) => (width, height),
804809
_ => return,
805810
};
806-
self.surface.resize(width, height).expect("failed to resize inner buffer");
811+
self.surface
812+
.as_mut()
813+
.unwrap()
814+
.resize(width, height)
815+
.expect("failed to resize inner buffer");
807816
}
808817
self.window.request_redraw();
809818
}
@@ -904,7 +913,7 @@ impl WindowState {
904913
Theme::Dark => DARK_GRAY,
905914
};
906915

907-
let mut buffer = self.surface.buffer_mut()?;
916+
let mut buffer = self.surface.as_mut().unwrap().buffer_mut()?;
908917
buffer.fill(color);
909918
self.window.pre_present_notify();
910919
buffer.present()?;

0 commit comments

Comments
 (0)