Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 5 additions & 1 deletion winit/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,13 @@ winit-core.workspace = true

[dev-dependencies]
image = { workspace = true, features = ["png"] }
softbuffer.workspace = true
tracing = { workspace = true, features = ["log"] }
tracing-subscriber = { workspace = true, features = ["env-filter"] }
# Launching a window without drawing to it has unpredictable results varying from platform to
# platform. We use the `softbuffer` crate in our examples because of its ease of use to avoid
# confusion around this. `glutin` or `wgpu` could also be used to fill the window buffer, but they
# are more complicated to set up.
softbuffer.workspace = true

[target.'cfg(target_os = "android")'.dependencies]
winit-android.workspace = true
Expand Down
85 changes: 37 additions & 48 deletions winit/examples/application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ use std::time::Instant;
use std::{fmt, mem};

use cursor_icon::CursorIcon;
use rwh_06::{DisplayHandle, HasDisplayHandle};
use softbuffer::{Context, Surface};
use tracing::{error, info};
#[cfg(web_platform)]
Expand All @@ -25,7 +24,7 @@ use winit::cursor::{Cursor, CustomCursor, CustomCursorSource};
use winit::dpi::{LogicalSize, PhysicalPosition, PhysicalSize};
use winit::error::RequestError;
use winit::event::{DeviceEvent, DeviceId, MouseButton, MouseScrollDelta, WindowEvent};
use winit::event_loop::{ActiveEventLoop, EventLoop};
use winit::event_loop::{ActiveEventLoop, EventLoop, OwnedDisplayHandle};
use winit::icon::{Icon, RgbaIcon};
use winit::keyboard::{Key, ModifiersState};
use winit::monitor::Fullscreen;
Expand All @@ -45,9 +44,6 @@ use winit_core::application::macos::ApplicationHandlerExtMacOS;
#[path = "util/tracing.rs"]
mod tracing_init;

#[path = "util/fill.rs"]
mod fill;

/// The amount of points to around the window for drag resize direction calculations.
const BORDER_SIZE: f64 = 20.;

Expand Down Expand Up @@ -94,20 +90,12 @@ struct Application {
/// Drawing context.
///
/// With OpenGL it could be EGLDisplay.
context: Option<Context<DisplayHandle<'static>>>,
context: Context<OwnedDisplayHandle>,
}

impl Application {
fn new(event_loop: &EventLoop, receiver: Receiver<Action>, sender: Sender<Action>) -> Self {
// SAFETY: we drop the context right before the event loop is stopped, thus making it safe.
let context = Some(
Context::new(unsafe {
std::mem::transmute::<DisplayHandle<'_>, DisplayHandle<'static>>(
event_loop.display_handle().unwrap(),
)
})
.unwrap(),
);
let context = Context::new(event_loop.owned_display_handle()).unwrap();

// You'll have to choose an icon size at your own discretion. On X11, the desired size
// varies by WM, and on Windows, you still have to account for screen scaling. Here
Expand Down Expand Up @@ -605,9 +593,7 @@ impl ApplicationHandlerExtMacOS for Application {
/// State of the window.
struct WindowState {
/// Render surface.
///
/// NOTE: This surface must be dropped before the `Window`.
surface: Surface<DisplayHandle<'static>, Arc<dyn Window>>,
surface: Surface<OwnedDisplayHandle, Arc<dyn Window>>,
/// The actual winit Window.
window: Arc<dyn Window>,
/// The window theme we're drawing with.
Expand Down Expand Up @@ -648,9 +634,7 @@ impl WindowState {
fn new(app: &Application, window: Box<dyn Window>) -> Result<Self, Box<dyn Error>> {
let window: Arc<dyn Window> = Arc::from(window);

// SAFETY: the surface is dropped before the `window` which provided it with handle, thus
// it doesn't outlive it.
let surface = Surface::new(app.context.as_ref().unwrap(), Arc::clone(&window))?;
let surface = Surface::new(&app.context, Arc::clone(&window))?;

let theme = window.theme().unwrap_or(Theme::Dark);
info!("Theme: {theme:?}");
Expand Down Expand Up @@ -937,35 +921,40 @@ impl WindowState {
return Ok(());
}

if self.animated_fill_color {
fill::fill_window_with_animated_color(&*self.window, self.start_time);
return Ok(());
}

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

// 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
};
if self.animated_fill_color {
// Fill the entire buffer with a single color.
let time = self.start_time.elapsed().as_secs_f32() * 1.5;
let blue = (time.sin() * 255.0) as u32;
let green = ((time.cos() * 255.0) as u32) << 8;
let red = ((1.0 - time.sin() * 255.0) as u32) << 16;
let color = red | green | blue;
buffer.fill(color);
} else {
// 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
};
}
}
}
}
Expand Down
36 changes: 23 additions & 13 deletions winit/examples/child_window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
fn main() -> Result<(), impl std::error::Error> {
use std::collections::HashMap;

use softbuffer::{Context, Surface};
use tracing::info;
use winit::application::ApplicationHandler;
use winit::dpi::{LogicalPosition, LogicalSize, Position};
use winit::event::{ElementState, KeyEvent, WindowEvent};
use winit::event_loop::{ActiveEventLoop, EventLoop};
use winit::event_loop::{ActiveEventLoop, EventLoop, OwnedDisplayHandle};
use winit::raw_window_handle::HasRawWindowHandle;
use winit::window::{Window, WindowAttributes, WindowId};

Expand All @@ -16,18 +17,20 @@ fn main() -> Result<(), impl std::error::Error> {

#[derive(Debug)]
struct WindowData {
window: Box<dyn Window>,
surface: Surface<OwnedDisplayHandle, Box<dyn Window>>,
color: u32,
}

impl WindowData {
fn new(window: Box<dyn Window>, color: u32) -> Self {
Self { window, color }
fn new(context: &Context<OwnedDisplayHandle>, window: Box<dyn Window>, color: u32) -> Self {
let surface = Surface::new(context, window).unwrap();
Self { surface, color }
}
}

#[derive(Default, Debug)]
#[derive(Debug)]
struct Application {
context: Context<OwnedDisplayHandle>,
parent_window_id: Option<WindowId>,
windows: HashMap<WindowId, WindowData>,
}
Expand All @@ -42,7 +45,7 @@ fn main() -> Result<(), impl std::error::Error> {
info!("Parent window id: {:?})", window.id());
self.parent_window_id = Some(window.id());

self.windows.insert(window.id(), WindowData::new(window, 0xffbbbbbb));
self.windows.insert(window.id(), WindowData::new(&self.context, window, 0xffbbbbbb));
}

fn window_event(
Expand Down Expand Up @@ -73,18 +76,24 @@ fn main() -> Result<(), impl std::error::Error> {
0xff000000 + 3_u32.pow((child_index + 2).rem_euclid(16) as u32);

let parent_window = self.windows.get(&self.parent_window_id.unwrap()).unwrap();
let child_window =
spawn_child_window(parent_window.window.as_ref(), event_loop, child_index);
let child_window = spawn_child_window(
parent_window.surface.window().as_ref(),
event_loop,
child_index,
);
let child_id = child_window.id();
info!("Child window created with id: {child_id:?}");
self.windows.insert(child_id, WindowData::new(child_window, child_color));
self.windows.insert(
child_id,
WindowData::new(&self.context, child_window, child_color),
);
},
WindowEvent::RedrawRequested => {
if let Some(window) = self.windows.get(&window_id) {
if let Some(window) = self.windows.get_mut(&window_id) {
if window_id == self.parent_window_id.unwrap() {
fill::fill_window(window.window.as_ref());
fill::fill(&mut window.surface);
} else {
fill::fill_window_with_color(window.window.as_ref(), window.color);
fill::fill_with_color(&mut window.surface, window.color);
}
}
},
Expand Down Expand Up @@ -118,7 +127,8 @@ fn main() -> Result<(), impl std::error::Error> {
}

let event_loop = EventLoop::new().unwrap();
event_loop.run_app(Application::default())
let context = Context::new(event_loop.owned_display_handle()).unwrap();
event_loop.run_app(Application { context, parent_window_id: None, windows: HashMap::new() })
}

#[cfg(not(any(x11_platform, macos_platform, windows_platform)))]
Expand Down
18 changes: 11 additions & 7 deletions winit/examples/control_flow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ use std::thread;
#[cfg(not(web_platform))]
use std::time;

use softbuffer::{Context, Surface};
use tracing::{info, warn};
#[cfg(web_platform)]
use web_time as time;
use winit::application::ApplicationHandler;
use winit::event::{ElementState, KeyEvent, StartCause, WindowEvent};
use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop};
use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop, OwnedDisplayHandle};
use winit::keyboard::{Key, NamedKey};
use winit::window::{Window, WindowAttributes, WindowId};

Expand Down Expand Up @@ -52,7 +53,7 @@ struct ControlFlowDemo {
request_redraw: bool,
wait_cancelled: bool,
close_requested: bool,
window: Option<Box<dyn Window>>,
surface: Option<Surface<OwnedDisplayHandle, Box<dyn Window>>>,
}

impl ApplicationHandler for ControlFlowDemo {
Expand All @@ -69,7 +70,10 @@ impl ApplicationHandler for ControlFlowDemo {
let window_attributes = WindowAttributes::default().with_title(
"Press 1, 2, 3 to change control flow mode. Press R to toggle redraw requests.",
);
self.window = Some(event_loop.create_window(window_attributes).unwrap());
let window = event_loop.create_window(window_attributes).unwrap();
let context = Context::new(event_loop.owned_display_handle()).unwrap();
let surface = Surface::new(&context, window).unwrap();
self.surface = Some(surface);
}

fn window_event(
Expand Down Expand Up @@ -112,17 +116,17 @@ impl ApplicationHandler for ControlFlowDemo {
_ => (),
},
WindowEvent::RedrawRequested => {
let window = self.window.as_ref().unwrap();
window.pre_present_notify();
fill::fill_window(window.as_ref());
let surface = self.surface.as_mut().unwrap();
surface.window().pre_present_notify();
fill::fill(surface);
},
_ => (),
}
}

fn about_to_wait(&mut self, event_loop: &dyn ActiveEventLoop) {
if self.request_redraw && !self.wait_cancelled && !self.close_requested {
self.window.as_ref().unwrap().request_redraw();
self.surface.as_ref().unwrap().window().request_redraw();
}

match self.mode {
Expand Down
26 changes: 12 additions & 14 deletions winit/examples/dnd.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use std::error::Error;

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

#[path = "util/fill.rs"]
Expand All @@ -16,27 +17,24 @@ fn main() -> Result<(), Box<dyn Error>> {

let event_loop = EventLoop::new()?;

let app = Application::new();
let app = Application::default();
Ok(event_loop.run_app(app)?)
}

/// Application state and event handling.
#[derive(Debug)]
#[derive(Default, Debug)]
struct Application {
window: Option<Box<dyn Window>>,
}

impl Application {
fn new() -> Self {
Self { window: None }
}
surface: Option<Surface<OwnedDisplayHandle, Box<dyn Window>>>,
}

impl ApplicationHandler for Application {
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
let window_attributes =
WindowAttributes::default().with_title("Drag and drop files on me!");
self.window = Some(event_loop.create_window(window_attributes).unwrap());
let window = event_loop.create_window(window_attributes).unwrap();
let context = Context::new(event_loop.owned_display_handle()).unwrap();
let surface = Surface::new(&context, window).unwrap();
self.surface = Some(surface);
}

fn window_event(
Expand All @@ -53,9 +51,9 @@ impl ApplicationHandler for Application {
info!("{event:?}");
},
WindowEvent::RedrawRequested => {
let window = self.window.as_ref().unwrap();
window.pre_present_notify();
fill::fill_window(window.as_ref());
let surface = self.surface.as_mut().unwrap();
surface.window().pre_present_notify();
fill::fill(surface);
},
WindowEvent::CloseRequested => {
event_loop.exit();
Expand Down
Loading
Loading