Skip to content
This repository was archived by the owner on Jul 8, 2025. It is now read-only.

Commit 09be6be

Browse files
committed
Rewrite to support custom ApplicationHandler structs
1 parent a8c0dc1 commit 09be6be

File tree

2 files changed

+171
-108
lines changed

2 files changed

+171
-108
lines changed

src/lib.rs

Lines changed: 72 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1+
mod sb_window;
2+
13
use std::num::NonZeroU32;
4+
pub use sb_window::SoftbufferWindow;
5+
26
use std::rc::Rc;
37

48
use softbuffer::Surface;
@@ -7,9 +11,12 @@ use winit::dpi::PhysicalSize;
711
use winit::error::EventLoopError;
812
use winit::event::WindowEvent;
913
use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop};
10-
use winit::window::{Window, WindowId};
14+
use winit::window::{Window};
15+
16+
pub type RawWindow = Option<Rc<Window>>;
17+
pub type RawSurface = Option<Surface<Rc<Window>, Rc<Window>>>;
1118

12-
/// Contains a few potential properties to set for a SoftbufferWindow when it is created.
19+
/// Simple struct that holds some properties (size, title) for windows
1320
pub struct WindowProperties {
1421
/// Initial width
1522
pub width: u32,
@@ -20,6 +27,7 @@ pub struct WindowProperties {
2027
}
2128

2229
impl Default for WindowProperties {
30+
/// Creates an 800x600 window named "Softbuffer Window"
2331
fn default() -> WindowProperties {
2432
WindowProperties {
2533
width: 800,
@@ -29,118 +37,74 @@ impl Default for WindowProperties {
2937
}
3038
}
3139

32-
/// Wrapper for Softbuffer and a Winit window
33-
pub struct SoftbufferWindow {
34-
window: Option<Rc<Window>>,
35-
loop_fn: Option<Box<dyn FnMut(&mut SoftbufferWindow, WindowEvent)>>,
36-
surface: Option<Surface<Rc<Window>, Rc<Window>>>,
37-
properties: WindowProperties,
40+
/// Shorthand to run a struct that implements `ApplicationHandler`
41+
pub fn run<A: ApplicationHandler<()>>(window: &mut A) -> Result<(), EventLoopError> {
42+
let event_loop = EventLoop::new()?;
43+
event_loop.set_control_flow(ControlFlow::Poll);
44+
event_loop.run_app(window)
3845
}
3946

40-
impl ApplicationHandler for SoftbufferWindow {
41-
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
42-
let window = {
43-
let window = event_loop.create_window(
44-
Window::default_attributes()
45-
.with_title(self.properties.title)
46-
.with_inner_size(PhysicalSize::new(
47-
self.properties.width,
48-
self.properties.height,
49-
)),
50-
);
51-
Rc::new(window.unwrap())
52-
};
53-
let context = softbuffer::Context::new(window.clone()).unwrap();
54-
self.window = Some(window.clone());
55-
self.surface = Some(Surface::new(&context, window.clone()).unwrap());
56-
}
57-
58-
fn window_event(&mut self, event_loop: &ActiveEventLoop, _id: WindowId, event: WindowEvent) {
59-
// Automatic event handling
60-
match event {
61-
WindowEvent::CloseRequested => {
62-
event_loop.exit();
63-
}
64-
WindowEvent::Resized(size) => {
65-
self.surface
66-
.as_mut()
67-
.unwrap()
68-
.resize(
69-
NonZeroU32::new(size.width).unwrap(),
70-
NonZeroU32::new(size.height).unwrap(),
71-
)
72-
.unwrap();
73-
}
74-
_ => (),
75-
}
76-
77-
let is_redraw_requested = event == WindowEvent::RedrawRequested;
78-
79-
// User event handling
80-
if self.loop_fn.is_some() {
81-
let mut loop_fn = self.loop_fn.take().unwrap();
82-
loop_fn(self, event);
83-
self.loop_fn = Some(loop_fn);
84-
}
85-
86-
// Displays buffer automatically if event is RedrawRequested
87-
if is_redraw_requested {
88-
self.surface
89-
.as_mut()
90-
.unwrap()
91-
.buffer_mut()
92-
.unwrap()
93-
.present()
94-
.unwrap();
95-
self.window.as_ref().unwrap().request_redraw();
96-
}
97-
}
47+
/// Initialises and returns a new RawWindow and RawSurface given an `ActiveEventLoop` and `WindowProperties`.
48+
/// For instance, implementation within `ApplicationHandler::resumed` may look like:
49+
/// ```rust
50+
/// //...
51+
/// fn resumed(&mut self, event_loop: &ActiveEventLoop) {
52+
/// (self.window, self.surface) = init(event_loop, &self.properties);
53+
/// }
54+
/// //...
55+
/// ```
56+
pub fn init(event_loop: &ActiveEventLoop, properties: &WindowProperties) -> (RawWindow, RawSurface) {
57+
let window = {
58+
let window = event_loop.create_window(
59+
Window::default_attributes()
60+
.with_title(properties.title)
61+
.with_inner_size(PhysicalSize::new(
62+
properties.width,
63+
properties.height,
64+
)),
65+
);
66+
Rc::new(window.unwrap())
67+
};
68+
let context = softbuffer::Context::new(window.clone()).unwrap();
69+
let window : RawWindow = Some(window.clone());
70+
let surface : RawSurface = Some(Surface::new(&context, window.clone().unwrap()).unwrap());
71+
(window, surface)
9872
}
9973

100-
impl SoftbufferWindow {
101-
/// Creates a new SoftbufferWindow.
102-
/// Example usage:
103-
/// ```rust
104-
/// let window = SoftbufferWindow::new(WindowProperties::default());
105-
/// ```
106-
pub fn new(properties: WindowProperties) -> Self {
107-
SoftbufferWindow {
108-
window: None,
109-
loop_fn: None,
110-
surface: None,
111-
properties,
112-
}
113-
}
114-
115-
/// Runs a SoftbufferWindow event loop.
116-
/// To handle events, you need winit's `WindowEvent` enum.
117-
/// Example usage:
118-
/// ```rust
119-
/// window.run(move |window, event| {
120-
/// match event {
121-
/// WindowEvent::RedrawRequested => (),
122-
/// _ => ()
123-
/// }
124-
/// });
125-
/// ```
126-
pub fn run(
127-
&mut self,
128-
event_fn: impl FnMut(&mut SoftbufferWindow, WindowEvent) + 'static,
129-
) -> Result<(), EventLoopError> {
130-
self.loop_fn = Some(Box::new(event_fn));
131-
let event_loop = EventLoop::new().unwrap();
132-
event_loop.set_control_flow(ControlFlow::Poll);
133-
event_loop.run_app(self)
74+
/// Shorthand to listen for and handle WindowEvent::CloseRequested by closing windows
75+
pub fn close(event_loop: &ActiveEventLoop, event: &WindowEvent) {
76+
if let WindowEvent::CloseRequested = event {
77+
event_loop.exit();
13478
}
79+
}
13580

136-
/// Returns the size of a window as a tuple
137-
pub fn inner_size(&mut self) -> (usize, usize) {
138-
let size = self.window.clone().unwrap().inner_size();
139-
(size.width as usize, size.height as usize)
81+
/// Shorthand to listen for and handle WindowEvent::Resized by resizing a buffer
82+
pub fn resize(event: &WindowEvent, surface: &mut RawSurface) {
83+
if let WindowEvent::Resized(size) = event {
84+
surface
85+
.as_mut()
86+
.unwrap()
87+
.resize(
88+
NonZeroU32::new(size.width).unwrap(),
89+
NonZeroU32::new(size.height).unwrap(),
90+
)
91+
.unwrap();
14092
}
93+
}
14194

142-
/// Gets a mutable reference to the buffer
143-
pub fn buffer_mut(&mut self) -> softbuffer::Buffer<'_, Rc<Window>, Rc<Window>> {
144-
self.surface.as_mut().unwrap().buffer_mut().unwrap()
145-
}
95+
/// Redraws a RawSurface. Call this on `Window::RedrawRequested`.
96+
pub fn redraw(window: &mut RawWindow, surface: &mut RawSurface) {
97+
surface
98+
.as_mut()
99+
.unwrap()
100+
.buffer_mut()
101+
.unwrap()
102+
.present()
103+
.unwrap();
104+
window.as_ref().unwrap().request_redraw();
146105
}
106+
107+
/// Gets a mutable reference to a buffer from a `RawSurface`
108+
pub fn buffer_mut(surface: &mut RawSurface) -> softbuffer::Buffer<'_, Rc<Window>, Rc<Window>> {
109+
surface.as_mut().unwrap().buffer_mut().unwrap()
110+
}

src/sb_window.rs

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
use std::num::NonZeroU32;
2+
use std::rc::Rc;
3+
use softbuffer::Surface;
4+
use winit::application::ApplicationHandler;
5+
use winit::dpi::PhysicalSize;
6+
use winit::error::EventLoopError;
7+
use winit::event::WindowEvent;
8+
use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop};
9+
use winit::window::{Window, WindowId};
10+
use crate::{close, init, redraw, resize, run, RawSurface, RawWindow, WindowProperties};
11+
12+
/// Wrapper for Softbuffer and a Winit window
13+
pub struct SoftbufferWindow {
14+
window: RawWindow,
15+
surface: RawSurface,
16+
loop_fn: Option<Box<dyn FnMut(&mut SoftbufferWindow, WindowEvent)>>,
17+
properties: WindowProperties,
18+
}
19+
20+
impl ApplicationHandler for SoftbufferWindow {
21+
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
22+
(self.window, self.surface) = init(event_loop, &self.properties);
23+
}
24+
25+
fn window_event(&mut self, event_loop: &ActiveEventLoop, _id: WindowId, event: WindowEvent) {
26+
// Automatic event handling
27+
close(event_loop, &event);
28+
resize(&event, &mut self.surface);
29+
30+
31+
let is_redraw_requested = event == WindowEvent::RedrawRequested;
32+
// User event handling
33+
if self.loop_fn.is_some() {
34+
let mut loop_fn = self.loop_fn.take().unwrap();
35+
loop_fn(self, event);
36+
self.loop_fn = Some(loop_fn);
37+
}
38+
39+
// Displays buffer automatically if event is RedrawRequested
40+
if is_redraw_requested {
41+
redraw(&mut self.window, &mut self.surface);
42+
}
43+
}
44+
}
45+
46+
impl SoftbufferWindow {
47+
/// Creates a new SoftbufferWindow.
48+
/// Example usage:
49+
/// ```rust
50+
/// use softbuffer_quickstart::{SoftbufferWindow, WindowProperties};
51+
/// let window = SoftbufferWindow::new(WindowProperties::default());
52+
/// ```
53+
pub fn new(properties: WindowProperties) -> Self {
54+
SoftbufferWindow {
55+
window: None,
56+
loop_fn: None,
57+
surface: None,
58+
properties,
59+
}
60+
}
61+
62+
/// Runs a SoftbufferWindow event loop.
63+
/// To handle events, you need winit's `WindowEvent` enum.
64+
/// Example usage:
65+
/// ```rust
66+
/// use winit::event::WindowEvent;
67+
/// use softbuffer_quickstart::{SoftbufferWindow, WindowProperties};
68+
/// let mut window = SoftbufferWindow::new(WindowProperties::default());
69+
/// window.run(move |window, event| {
70+
/// match event {
71+
/// WindowEvent::RedrawRequested => (),
72+
/// _ => ()
73+
/// }
74+
/// })?;
75+
/// ```
76+
pub fn run(
77+
&mut self,
78+
event_fn: impl FnMut(&mut SoftbufferWindow, WindowEvent) + 'static,
79+
) -> Result<(), EventLoopError> {
80+
self.loop_fn = Some(Box::new(event_fn));
81+
run(self)
82+
}
83+
84+
/// Returns the size of a window as a tuple
85+
pub fn inner_size(&mut self) -> (usize, usize) {
86+
let size = self.window.clone().unwrap().inner_size();
87+
(size.width as usize, size.height as usize)
88+
}
89+
90+
/// Gets a mutable reference to the buffer
91+
pub fn buffer_mut(&mut self) -> softbuffer::Buffer<'_, Rc<Window>, Rc<Window>> {
92+
self.surface.as_mut().unwrap().buffer_mut().unwrap()
93+
}
94+
95+
/// Gets a mutable reference to the window
96+
pub fn window_mut(&mut self) -> Rc<Window> {
97+
self.window.clone().unwrap()
98+
}
99+
}

0 commit comments

Comments
 (0)