Skip to content
Open
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
af28d87
Update fill.rs
yagizgil Mar 13, 2026
52e6428
add new example
yagizgil Mar 13, 2026
ade77e9
Update win_with_soft.rs
yagizgil Mar 14, 2026
48ded92
Update win_with_soft.rs
yagizgil Mar 14, 2026
4cfeac9
Update fill.rs
yagizgil Mar 14, 2026
ce40fe5
Update fill.rs
yagizgil Mar 14, 2026
38f85d2
Update fill.rs
yagizgil Mar 14, 2026
858e04b
Update win_with_soft.rs
yagizgil Mar 14, 2026
ecf0a0a
Update win_with_soft.rs
yagizgil Mar 14, 2026
109f1e2
Update win_with_soft.rs
yagizgil Mar 14, 2026
85de3cd
Create win_with_soft_2.rs
yagizgil Mar 14, 2026
c242f59
Update win_with_soft_2.rs
yagizgil Mar 14, 2026
1030024
Update win_with_soft_2.rs
yagizgil Mar 14, 2026
60d5848
Update win_with_soft_2.rs
yagizgil Mar 14, 2026
44c2b3f
Update win_with_soft_2.rs
yagizgil Mar 14, 2026
6310dc0
Update win_with_soft_2.rs
yagizgil Mar 14, 2026
74fabc5
Update win_with_soft_2.rs
yagizgil Mar 14, 2026
2a3a14a
complate keywrods and switch softbuffer source
yagizgil Mar 15, 2026
e2297b7
Update unreleased.md
yagizgil Mar 15, 2026
9838ef9
Update event_loop.rs
yagizgil Mar 15, 2026
e10fcb2
fix
yagizgil Mar 15, 2026
c6bd46c
fix: format
yagizgil Mar 15, 2026
909e079
fix example file named "application.rs"
yagizgil Mar 15, 2026
cfe55b4
format example named applicatio.rs
yagizgil Mar 15, 2026
284be22
remove keyboard mappings as requested
yagizgil Mar 15, 2026
bc3a2a6
Update unreleased.md
yagizgil Mar 15, 2026
d2bc9fe
Update fill.rs
yagizgil Mar 15, 2026
776f639
fmt fill.rs and exclude android for new examples
yagizgil Mar 15, 2026
5d01646
fix examples
yagizgil Mar 15, 2026
2afb39f
fmt examples
yagizgil Mar 15, 2026
6ff12eb
fix examples
yagizgil Mar 15, 2026
5feb83f
.
yagizgil Mar 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ tracing = { version = "0.1.40", default-features = false }

# Dev dependencies.
image = { version = "0.25.0", default-features = false }
softbuffer = { version = "0.4.6", default-features = false, features = [
softbuffer = { git = "https://github.com/rust-windowing/softbuffer", branch = "master", default-features = false, features = [
"x11",
"x11-dlopen",
"wayland",
Expand Down
23 changes: 23 additions & 0 deletions winit-orbital/src/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ fn convert_scancode(scancode: u8) -> (PhysicalKey, Option<NamedKey>) {
orbclient::K_LEFT => (KeyCode::ArrowLeft, Some(NamedKey::ArrowLeft)),
orbclient::K_LEFT_SHIFT => (KeyCode::ShiftLeft, Some(NamedKey::Shift)),
orbclient::K_MINUS => (KeyCode::Minus, None),

orbclient::K_NUM_0 => (KeyCode::Numpad0, None),
orbclient::K_NUM_1 => (KeyCode::Numpad1, None),
orbclient::K_NUM_2 => (KeyCode::Numpad2, None),
Expand All @@ -111,12 +112,20 @@ fn convert_scancode(scancode: u8) -> (PhysicalKey, Option<NamedKey>) {
orbclient::K_NUM_7 => (KeyCode::Numpad7, None),
orbclient::K_NUM_8 => (KeyCode::Numpad8, None),
orbclient::K_NUM_9 => (KeyCode::Numpad9, None),
orbclient::K_NUM_ASTERISK => (KeyCode::NumpadMultiply, None),
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding keyboard mappings is a simple change that should be done in another PR, in my opinion

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've removed the keyboard mappings from this PR to keep it focused. I will open a separate PR

orbclient::K_NUM_ENTER => (KeyCode::NumpadEnter, Some(NamedKey::Enter)),
orbclient::K_NUM_MINUS => (KeyCode::NumpadSubtract, None),
orbclient::K_NUM_PLUS => (KeyCode::NumpadAdd, None),
orbclient::K_NUM_SLASH => (KeyCode::NumpadDivide, None),
orbclient::K_NUM_PERIOD => (KeyCode::NumpadDecimal, None),

orbclient::K_PERIOD => (KeyCode::Period, None),
orbclient::K_PGDN => (KeyCode::PageDown, Some(NamedKey::PageDown)),
orbclient::K_PGUP => (KeyCode::PageUp, Some(NamedKey::PageUp)),
orbclient::K_QUOTE => (KeyCode::Quote, None),
orbclient::K_RIGHT => (KeyCode::ArrowRight, Some(NamedKey::ArrowRight)),
orbclient::K_RIGHT_SHIFT => (KeyCode::ShiftRight, Some(NamedKey::Shift)),
orbclient::K_RIGHT_SUPER => (KeyCode::MetaRight, Some(NamedKey::Meta)),
orbclient::K_SEMICOLON => (KeyCode::Semicolon, None),
orbclient::K_SLASH => (KeyCode::Slash, None),
orbclient::K_SPACE => (KeyCode::Space, None),
Expand All @@ -128,6 +137,20 @@ fn convert_scancode(scancode: u8) -> (PhysicalKey, Option<NamedKey>) {
orbclient::K_VOLUME_TOGGLE => (KeyCode::AudioVolumeMute, Some(NamedKey::AudioVolumeMute)),
orbclient::K_VOLUME_UP => (KeyCode::AudioVolumeUp, Some(NamedKey::AudioVolumeUp)),

orbclient::K_INS => (KeyCode::Insert, Some(NamedKey::Insert)),
orbclient::K_PRTSC => (KeyCode::PrintScreen, Some(NamedKey::PrintScreen)),
orbclient::K_NUM => (KeyCode::NumLock, Some(NamedKey::NumLock)),
orbclient::K_SCROLL => (KeyCode::ScrollLock, Some(NamedKey::ScrollLock)),
orbclient::K_APP => (KeyCode::ContextMenu, Some(NamedKey::ContextMenu)),

orbclient::K_MEDIA_FAST_FORWARD => {
(KeyCode::MediaFastForward, Some(NamedKey::MediaFastForward))
},
orbclient::K_MEDIA_REWIND => (KeyCode::MediaRewind, Some(NamedKey::MediaRewind)),
orbclient::K_MEDIA_STOP => (KeyCode::MediaStop, Some(NamedKey::MediaStop)),

orbclient::K_POWER => (KeyCode::Power, Some(NamedKey::Power)),

_ => return (PhysicalKey::Unidentified(NativeKeyCode::Unidentified), None),
};
(PhysicalKey::Code(key_code), named_key_opt)
Expand Down
46 changes: 25 additions & 21 deletions winit/examples/application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -964,32 +964,36 @@ impl WindowState {
return Ok(());
}

let mut buffer = self.surface.buffer_mut()?;
let mut buffer = self.surface.next_buffer()?;

// Draw a different color inside the safe area
let surface_size = self.window.surface_size();
let insets = self.window.safe_area();
for y in 0..surface_size.height {
for x in 0..surface_size.width {
let index = y as usize * surface_size.width as usize + x as usize;
if insets.left <= x
&& x <= (surface_size.width - insets.right)
&& insets.top <= y
&& y <= (surface_size.height - insets.bottom)
{
// In safe area
buffer[index] = match self.theme {
Theme::Light => 0xffe8e8e8, // Light gray
Theme::Dark => 0xff525252, // Medium gray
};
} else {
// Outside safe area
buffer[index] = match self.theme {
Theme::Light => 0xffffffff, // White
Theme::Dark => 0xff181818, // Dark gray
};
for (x, y, pixel) in buffer.pixels_iter() {
let is_inside_safe_area = insets.left <= x
&& x <= (surface_size.width - insets.right)
&& insets.top <= y
&& y <= (surface_size.height - insets.bottom);

let color: u32 = if is_inside_safe_area {
// In safe area
match self.theme {
Theme::Light => 0xffe8e8e8, // Light gray
Theme::Dark => 0xff525252, // Medium gray
}
}
} else {
// Outside safe area
match self.theme {
Theme::Light => 0xffffffff, // White
Theme::Dark => 0xff181818, // Dark gray
}
};

let red = ((color >> 16) & 0xff) as u8;
let green = ((color >> 8) & 0xff) as u8;
let blue = (color & 0xff) as u8;

*pixel = softbuffer::Pixel::new_rgb(red, green, blue);
}

// Present the buffer
Expand Down
14 changes: 12 additions & 2 deletions winit/examples/util/fill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,18 @@ mod platform {

surface.resize(width, height).expect("Failed to resize the softbuffer surface");

let mut buffer = surface.buffer_mut().expect("Failed to get the softbuffer buffer");
buffer.fill(color);
let mut buffer = surface.next_buffer().expect("Failed to get the softbuffer buffer");

// error[E0599]: no method named `fill` found for struct `Buffer<'surface>` in the
// current scope buffer.fill(color);

for (_, _, pixel) in buffer.pixels_iter() {
let red = ((color >> 16) & 0xff) as u8;
let green = ((color >> 8) & 0xff) as u8;
let blue = (color & 0xff) as u8;

*pixel = softbuffer::Pixel::new_rgb(red, green, blue);
}
buffer.present().expect("Failed to present the softbuffer buffer");
})
}
Expand Down
99 changes: 99 additions & 0 deletions winit/examples/win_with_soft.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
use std::error::Error;
use std::num::NonZeroU32;
use std::sync::Arc;
use std::time::{Duration, Instant};

use softbuffer::{Context, Surface};
use winit::application::ApplicationHandler;
use winit::event::WindowEvent;
use winit::event_loop::{ActiveEventLoop, EventLoop};
use winit::window::{Window, WindowAttributes, WindowId};

struct App {
window: Option<Arc<dyn Window>>,
surface: Option<Surface<Arc<dyn Window>, Arc<dyn Window>>>,
frame_count: u32,
last_fps_print: Instant,
}

impl App {
fn new() -> Self {
Self { window: None, surface: None, frame_count: 0, last_fps_print: Instant::now() }
}
}

impl ApplicationHandler for App {
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
let attributes = WindowAttributes::default().with_title("framebuffer test");
let window: Arc<dyn Window> = Arc::from(event_loop.create_window(attributes).unwrap());

let context = Context::new(window.clone()).expect("context except");
let surface = Surface::new(&context, window.clone()).expect("surface except");

self.window = Some(window);
self.surface = Some(surface);
}

fn about_to_wait(&mut self, _event_loop: &dyn ActiveEventLoop) {
if let Some(window) = self.window.as_ref() {
window.request_redraw();
}
}

fn window_event(
&mut self,
event_loop: &dyn ActiveEventLoop,
_id: WindowId,
event: WindowEvent,
) {
match event {
WindowEvent::CloseRequested => event_loop.exit(),

WindowEvent::SurfaceResized(size) => {
if let Some(surface) = self.surface.as_mut() {
let w = NonZeroU32::new(size.width.max(1)).unwrap();
let h = NonZeroU32::new(size.height.max(1)).unwrap();
surface.resize(w, h).unwrap();
}
},

WindowEvent::RedrawRequested => {
if let Some(surface) = self.surface.as_mut() {
let mut buffer = surface.next_buffer().expect("buffer except");

for (x, y, pixel) in buffer.pixels_iter() {
let red = (x % 255) as u8;
let green = (y % 255) as u8;
let blue = ((x * y) % 255) as u8;

*pixel = softbuffer::Pixel::new_rgb(red, green, blue);
}

buffer.present().unwrap();

let now = Instant::now();
self.frame_count += 1;

if now.duration_since(self.last_fps_print) >= Duration::from_secs(1) {
let fps = self.frame_count;
println!("FPS: {}", fps);

self.frame_count = 0;
self.last_fps_print = now;
}
}
},
_ => (),
}
}
}

fn main() -> Result<(), Box<dyn Error>> {
let event_loop = EventLoop::new()?;

let app = Box::leak(Box::new(App::new()));

event_loop.run_app(app)?;

Ok(())
}
115 changes: 115 additions & 0 deletions winit/examples/win_with_soft_2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
use std::error::Error;
use std::num::NonZeroU32;
use std::sync::Arc;
use std::time::{Duration, Instant};

use softbuffer::{Context, Pixel, Surface};
use winit::application::ApplicationHandler;
use winit::event::WindowEvent;
use winit::event_loop::{ActiveEventLoop, EventLoop};
use winit::window::{Window, WindowAttributes, WindowId};

struct App {
window: Option<Arc<dyn Window>>,
surface: Option<Surface<Arc<dyn Window>, Arc<dyn Window>>>,
start_time: Instant,
frame_count: u32,
last_fps_print: Instant,
total_frame_count: u64,
}

impl ApplicationHandler for App {
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
let window: Arc<dyn Window> =
Arc::from(event_loop.create_window(WindowAttributes::default()).unwrap());
self.surface =
Some(Surface::new(&Context::new(window.clone()).unwrap(), window.clone()).unwrap());
self.window = Some(window);
}

fn about_to_wait(&mut self, _: &dyn ActiveEventLoop) {
if let Some(w) = self.window.as_ref() {
w.request_redraw();
}
}

fn window_event(
&mut self,
event_loop: &dyn ActiveEventLoop,
_id: WindowId,
event: WindowEvent,
) {
match event {
WindowEvent::CloseRequested => event_loop.exit(),
WindowEvent::SurfaceResized(size) => {
if let Some(s) = self.surface.as_mut() {
s.resize(
NonZeroU32::new(size.width.max(1)).unwrap(),
NonZeroU32::new(size.height.max(1)).unwrap(),
)
.unwrap();
}
},
WindowEvent::RedrawRequested => {
if let (Some(window), Some(surface)) = (&self.window, self.surface.as_mut()) {
let mut buffer = surface.next_buffer().unwrap();
let size = window.outer_size();
let elapsed = self.start_time.elapsed();
let t = elapsed.as_secs_f32();
let total_secs = elapsed.as_secs();

let ball_x = ((t * 1.5).sin() * 0.5 + 0.5) * size.width as f32;
let ball_y = ((t * 2.1).cos() * 0.5 + 0.5) * size.height as f32;

for (x, y, pixel) in buffer.pixels_iter() {
let dx = x as f32 - ball_x;
let dy = y as f32 - ball_y;
let dist = (dx * dx + dy * dy).sqrt();

let p1 = (x as f32 * 0.01 + t).sin();
let p2 = (y as f32 * 0.01 + t * 0.5).cos();
let p3 = ((x as f32 + y as f32) * 0.005 + t).sin();
let plasma = (p1 + p2 + p3) * 0.33;

if dist < 50.0 {
*pixel = Pixel::new_rgb(255, 255, 255);
} else if (y as f32 + t * 50.0) % 20.0 < 2.0 {
*pixel = Pixel::new_rgb(0, 0, 0);
} else {
let r = ((plasma + 1.0) * 127.0) as u8;
let g = (x % 255) as u8;
let b = (y % 255).wrapping_add((t * 20.0) as u32) as u8;
*pixel = Pixel::new_rgb(r, g, b);
}
}
buffer.present().unwrap();

self.frame_count += 1;
self.total_frame_count += 1;
if self.last_fps_print.elapsed() >= Duration::from_secs(1) {
let avg = self.total_frame_count as f64 / elapsed.as_secs_f64();
window.set_title(&format!(
"FPS: {} | AVG: {:.2} | TIME: {}s | {}x{}",
self.frame_count, avg, total_secs, size.width, size.height
));
self.frame_count = 0;
self.last_fps_print = Instant::now();
}
}
},
_ => (),
}
}
}

fn main() -> Result<(), Box<dyn Error>> {
let app = App {
window: None,
surface: None,
start_time: Instant::now(),
frame_count: 0,
last_fps_print: Instant::now(),
total_frame_count: 0,
};
EventLoop::new()?.run_app(app).map_err(Into::into)
}
1 change: 1 addition & 0 deletions winit/src/changelog/unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ changelog entry.

- Add `keyboard` support for OpenHarmony.
- On iOS, add Apple Pencil support with force, altitude, and azimuth data.
- On Redox, add support for missing keyboard scancodes.

### Changed

Expand Down
Loading