@@ -77,47 +77,111 @@ To run the Android-specific example on an Android phone: `cargo apk r --example
7777``` rust,no_run
7878use std::num::NonZeroU32;
7979use 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;
8480
85- #[path = "../examples/util/mod.rs"]
86- mod util;
81+ use softbuffer::{Context, Pixel, Surface};
82+ use winit::application::ApplicationHandler;
83+ use winit::event::{StartCause, WindowEvent};
84+ use winit::event_loop::{ActiveEventLoop, EventLoop, OwnedDisplayHandle};
85+ use winit::window::{Window, WindowId};
8786
8887fn main() {
8988 let event_loop = EventLoop::new().unwrap();
9089 let context = Context::new(event_loop.owned_display_handle()).unwrap();
90+ let mut app = App {
91+ context,
92+ state: AppState::Initial,
93+ };
94+ event_loop.run_app(&mut app).unwrap();
95+ }
9196
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() {
97+ #[derive(Debug)]
98+ struct App {
99+ context: Context<OwnedDisplayHandle>,
100+ state: AppState,
101+ }
102+
103+ #[derive(Debug)]
104+ enum AppState {
105+ Initial,
106+ Suspended {
107+ window: Rc<Window>,
108+ },
109+ Running {
110+ surface: Surface<OwnedDisplayHandle, Rc<Window>>,
111+ },
112+ }
113+
114+ impl ApplicationHandler for App {
115+ fn new_events(&mut self, event_loop: &ActiveEventLoop, cause: StartCause) {
116+ if let StartCause::Init = cause {
117+ // Create window on startup.
118+ let window_attrs = Window::default_attributes();
119+ let window = event_loop
120+ .create_window(window_attrs)
121+ .expect("failed creating window");
122+ self.state = AppState::Suspended {
123+ window: Rc::new(window),
124+ };
125+ }
126+ }
127+
128+ fn resumed(&mut self, _event_loop: &ActiveEventLoop) {
129+ // Create or re-create the surface.
130+ let AppState::Suspended { window } = &mut self.state else {
131+ unreachable!("got resumed event while not suspended");
132+ };
133+ let mut surface =
134+ Surface::new(&self.context, window.clone()).expect("failed creating surface");
135+
136+ // TODO: https://github.com/rust-windowing/softbuffer/issues/106
137+ let size = window.inner_size();
138+ if let (Some(width), Some(height)) =
139+ (NonZeroU32::new(size.width), NonZeroU32::new(size.height))
140+ {
141+ // Resize surface
142+ surface.resize(width, height).unwrap();
143+ }
144+
145+ self.state = AppState::Running { surface };
146+ }
147+
148+ fn suspended(&mut self, _event_loop: &ActiveEventLoop) {
149+ // Drop the surface.
150+ let AppState::Running { surface } = &mut self.state else {
151+ unreachable!("got resumed event while not running");
152+ };
153+ let window = surface.window().clone();
154+ self.state = AppState::Suspended { window };
155+ }
156+
157+ fn window_event(
158+ &mut self,
159+ event_loop: &ActiveEventLoop,
160+ window_id: WindowId,
161+ event: WindowEvent,
162+ ) {
163+ let AppState::Running { surface } = &mut self.state else {
164+ unreachable!("got window event while suspended");
165+ };
166+
167+ if surface.window().id() != window_id {
103168 return;
104169 }
105170
106171 match event {
172+ WindowEvent::Resized(size) => {
173+ if let (Some(width), Some(height)) =
174+ (NonZeroU32::new(size.width), NonZeroU32::new(size.height))
175+ {
176+ // Resize surface
177+ surface.resize(width, height).unwrap();
178+ }
179+ }
107180 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-
181+ // Get the next buffer.
120182 let mut buffer = surface.next_buffer().unwrap();
183+
184+ // Render into the buffer.
121185 for (x, y, pixel) in buffer.pixels_iter() {
122186 let red = (x % 255) as u8;
123187 let green = (y % 255) as u8;
@@ -126,16 +190,15 @@ fn main() {
126190 *pixel = Pixel::new_rgb(red, green, blue);
127191 }
128192
193+ // Send the buffer to the compositor.
129194 buffer.present().unwrap();
130195 }
131196 WindowEvent::CloseRequested => {
132- elwt .exit();
197+ event_loop .exit();
133198 }
134199 _ => {}
135200 }
136- });
137-
138- event_loop.run_app(&mut app).unwrap();
201+ }
139202}
140203```
141204
0 commit comments