Skip to content

Commit 6d75db3

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 6d75db3

1 file changed

Lines changed: 96 additions & 34 deletions

File tree

README.md

Lines changed: 96 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -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};
7879
use std::num::NonZeroU32;
7980
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;
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
8886
fn 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

Comments
 (0)