@@ -75,49 +75,112 @@ To run the Android-specific example on an Android phone: `cargo apk r --example
7575## Example
7676
7777``` rust,no_run
78+ use softbuffer::{Context, Pixel, Surface};
7879use std::num::NonZeroU32;
7980use std::rc::Rc;
80- use softbuffer::{Context, Pixel, Surface};
81- use winit::event::{Event, WindowEvent};
82- use winit::event_loop::{ControlFlow, EventLoop};
83- use winit::window::Window;
84-
85- #[path = "../examples/util/mod.rs"]
86- mod util;
81+ use winit::application::ApplicationHandler;
82+ use winit::event::{StartCause, WindowEvent};
83+ use winit::event_loop::{ActiveEventLoop, EventLoop, OwnedDisplayHandle};
84+ use winit::window::{Window, WindowId};
8785
8886fn main() {
8987 let event_loop = EventLoop::new().unwrap();
9088 let context = Context::new(event_loop.owned_display_handle()).unwrap();
89+ let mut app = App {
90+ context,
91+ state: AppState::Initial,
92+ };
93+ event_loop.run_app(&mut app).unwrap();
94+ }
95+
96+ #[derive(Debug)]
97+ struct App {
98+ context: Context<OwnedDisplayHandle>,
99+ state: AppState,
100+ }
101+
102+ #[derive(Debug)]
103+ enum AppState {
104+ Initial,
105+ Suspended {
106+ window: Rc<Window>,
107+ },
108+ Running {
109+ surface: Surface<OwnedDisplayHandle, Rc<Window>>,
110+ },
111+ }
91112
92- let mut app = util::WinitAppBuilder::with_init(
93- |elwt| {
94- let window = elwt.create_window(Window::default_attributes());
95- Rc::new(window.unwrap())
96- },
97- |_elwt, window| Surface::new(&context, window.clone()).unwrap(),
98- )
99- .with_event_handler(|window, surface, window_id, event, elwt| {
100- elwt.set_control_flow(ControlFlow::Wait);
101-
102- if window_id != window.id() {
113+ impl ApplicationHandler for App {
114+ fn new_events(&mut self, event_loop: &ActiveEventLoop, cause: StartCause) {
115+ if let StartCause::Init = cause {
116+ // Create window on startup.
117+ let window_attrs = Window::default_attributes();
118+ let window = event_loop
119+ .create_window(window_attrs)
120+ .expect("failed creating window");
121+ self.state = AppState::Suspended {
122+ window: Rc::new(window),
123+ };
124+ }
125+ }
126+
127+ fn resumed(&mut self, _event_loop: &ActiveEventLoop) {
128+ // Create or re-create the surface.
129+ let AppState::Suspended { window } = &mut self.state else {
130+ unreachable!("got resumed event while not suspended");
131+ };
132+ let mut surface =
133+ Surface::new(&self.context, window.clone()).expect("failed creating surface");
134+
135+ // TODO: https://github.com/rust-windowing/softbuffer/issues/106
136+ let size = window.inner_size();
137+ if let (Some(width), Some(height)) =
138+ (NonZeroU32::new(size.width), NonZeroU32::new(size.height))
139+ {
140+ // Resize surface
141+ surface.resize(width, height).unwrap();
142+ }
143+
144+ self.state = AppState::Running { surface };
145+ }
146+
147+ fn suspended(&mut self, _event_loop: &ActiveEventLoop) {
148+ // Drop the surface.
149+ let AppState::Running { surface } = &mut self.state else {
150+ unreachable!("got resumed event while not running");
151+ };
152+ let window = surface.window().clone();
153+ self.state = AppState::Suspended { window };
154+ }
155+
156+ fn window_event(
157+ &mut self,
158+ event_loop: &ActiveEventLoop,
159+ window_id: WindowId,
160+ event: WindowEvent,
161+ ) {
162+ let AppState::Running { surface } = &mut self.state else {
163+ unreachable!("got window event while suspended");
164+ };
165+
166+ if surface.window().id() != window_id {
103167 return;
104168 }
105169
106170 match event {
171+ WindowEvent::Resized(size) => {
172+ if let (Some(width), Some(height)) =
173+ (NonZeroU32::new(size.width), NonZeroU32::new(size.height))
174+ {
175+ // Resize surface
176+ surface.resize(width, height).unwrap();
177+ }
178+ }
107179 WindowEvent::RedrawRequested => {
108- let Some(surface) = surface else {
109- tracing::error!("RedrawRequested fired before Resumed or after Suspended");
110- return;
111- };
112- let size = window.inner_size();
113- surface
114- .resize(
115- NonZeroU32::new(size.width).unwrap(),
116- NonZeroU32::new(size.height).unwrap(),
117- )
118- .unwrap();
119-
180+ // Get the next buffer.
120181 let mut buffer = surface.next_buffer().unwrap();
182+
183+ // Render into the buffer.
121184 for (x, y, pixel) in buffer.pixels_iter() {
122185 let red = (x % 255) as u8;
123186 let green = (y % 255) as u8;
@@ -126,16 +189,15 @@ fn main() {
126189 *pixel = Pixel::new_rgb(red, green, blue);
127190 }
128191
192+ // Send the buffer to the compositor.
129193 buffer.present().unwrap();
130194 }
131195 WindowEvent::CloseRequested => {
132- elwt .exit();
196+ event_loop .exit();
133197 }
134198 _ => {}
135199 }
136- });
137-
138- event_loop.run_app(&mut app).unwrap();
200+ }
139201}
140202```
141203
0 commit comments