Skip to content

Commit fa540ce

Browse files
committed
Improve README example
Don't use a utility module in the first example that users see, use the actual Winit API.
1 parent fed64dd commit fa540ce

File tree

1 file changed

+96
-33
lines changed

1 file changed

+96
-33
lines changed

README.md

Lines changed: 96 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -77,47 +77,111 @@ To run the Android-specific example on an Android phone: `cargo apk r --example
7777
```rust,no_run
7878
use std::num::NonZeroU32;
7979
use 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
8887
fn 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

Comments
 (0)