From f039c80f3a940207c17f036571ad509fbacd9f42 Mon Sep 17 00:00:00 2001 From: John Nunley Date: Mon, 19 Jun 2023 11:46:38 -0700 Subject: [PATCH] Fill the windows in the examples with a solid color (cherry-pick from upstream, ignore) From https://github.com/rust-windowing/winit/pull/2812 --- Cargo.toml | 3 ++ README.md | 4 -- examples/child_window.rs | 8 +++ examples/control_flow.rs | 7 ++- examples/cursor.rs | 6 +++ examples/cursor_grab.rs | 4 ++ examples/custom_events.rs | 8 ++- examples/drag_window.rs | 10 ++++ examples/fullscreen.rs | 6 +++ examples/handling_close.rs | 8 ++- examples/ime.rs | 6 +++ examples/mouse_wheel.rs | 6 +++ examples/multiwindow.rs | 8 +++ examples/request_redraw.rs | 4 ++ examples/request_redraw_threaded.rs | 26 ++++++--- examples/resizable.rs | 6 +++ examples/theme.rs | 7 +++ examples/timer.rs | 8 ++- examples/touchpad_gestures.rs | 7 ++- examples/transparent.rs | 6 +++ examples/util/fill.rs | 81 ++++++++++++++++++++++++++++ examples/window.rs | 6 +++ examples/window_buttons.rs | 6 +++ examples/window_debug.rs | 6 +++ examples/window_drag_resize.rs | 6 +++ examples/window_icon.rs | 5 ++ examples/window_resize_increments.rs | 6 +++ examples/window_run_return.rs | 9 +++- 28 files changed, 255 insertions(+), 18 deletions(-) create mode 100644 examples/util/fill.rs diff --git a/Cargo.toml b/Cargo.toml index b6c6d6ac57..e308f127a7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -61,6 +61,9 @@ serde = { version = "1", optional = true, features = ["serde_derive"] } image = { version = "0.24.0", default-features = false, features = ["png"] } simple_logger = { version = "2.1.0", default_features = false } +[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dev-dependencies] +softbuffer = "0.3.0" + [target.'cfg(target_os = "android")'.dependencies] # Coordinate the next winit release with android-ndk-rs: https://github.com/rust-windowing/winit/issues/1995 android-activity = "0.4.0" diff --git a/README.md b/README.md index 75e2c48b44..35f64c5c70 100644 --- a/README.md +++ b/README.md @@ -73,10 +73,6 @@ Winit provides the following features, which can be enabled in your `Cargo.toml` Note that windows don't appear on Wayland until you draw/present to them. -`winit` doesn't do drawing, try the examples in [`glutin`] instead. - -[`glutin`]: https://github.com/rust-windowing/glutin - #### WebAssembly To run the web example: `cargo run-wasm --example web` diff --git a/examples/child_window.rs b/examples/child_window.rs index b1b8f95e82..c258d42a08 100644 --- a/examples/child_window.rs +++ b/examples/child_window.rs @@ -1,3 +1,7 @@ +#[cfg(any(x11_platform, macos_platform, windows_platform))] +#[path = "util/fill.rs"] +mod fill; + #[cfg(any(x11_platform, macos_platform, windows_platform))] fn main() { use std::collections::HashMap; @@ -70,6 +74,10 @@ fn main() { } _ => (), } + } else if let Event::RedrawRequested(wid) = event { + if let Some(window) = windows.get(&wid) { + fill::fill_window(window); + } } }) } diff --git a/examples/control_flow.rs b/examples/control_flow.rs index bade79d279..cf32c25dee 100644 --- a/examples/control_flow.rs +++ b/examples/control_flow.rs @@ -9,6 +9,9 @@ use winit::{ window::WindowBuilder, }; +#[path = "util/fill.rs"] +mod fill; + #[derive(Debug, Clone, Copy, PartialEq, Eq)] enum Mode { Wait, @@ -93,7 +96,9 @@ fn main() { control_flow.set_exit(); } } - Event::RedrawRequested(_window_id) => {} + Event::RedrawRequested(_window_id) => { + fill::fill_window(&window); + } Event::RedrawEventsCleared => { match mode { Mode::Wait => control_flow.set_wait(), diff --git a/examples/cursor.rs b/examples/cursor.rs index fdef7ef971..97dc75c705 100644 --- a/examples/cursor.rs +++ b/examples/cursor.rs @@ -7,6 +7,9 @@ use winit::{ window::{CursorIcon, WindowBuilder}, }; +#[path = "util/fill.rs"] +mod fill; + fn main() { SimpleLogger::new().init().unwrap(); let event_loop = EventLoop::new(); @@ -46,6 +49,9 @@ fn main() { } => { control_flow.set_exit(); } + Event::RedrawRequested(_) => { + fill::fill_window(&window); + } _ => (), } }); diff --git a/examples/cursor_grab.rs b/examples/cursor_grab.rs index 79253e106a..0476a4e4e8 100644 --- a/examples/cursor_grab.rs +++ b/examples/cursor_grab.rs @@ -7,6 +7,9 @@ use winit::{ window::{CursorGrabMode, WindowBuilder}, }; +#[path = "util/fill.rs"] +mod fill; + fn main() { SimpleLogger::new().init().unwrap(); let event_loop = EventLoop::new(); @@ -64,6 +67,7 @@ fn main() { }, _ => (), }, + Event::RedrawRequested(_) => fill::fill_window(&window), _ => (), } }); diff --git a/examples/custom_events.rs b/examples/custom_events.rs index b39353155a..b3a3d2176a 100644 --- a/examples/custom_events.rs +++ b/examples/custom_events.rs @@ -9,6 +9,9 @@ fn main() { window::WindowBuilder, }; + #[path = "util/fill.rs"] + mod fill; + #[derive(Debug, Clone, Copy)] enum CustomEvent { Timer, @@ -17,7 +20,7 @@ fn main() { SimpleLogger::new().init().unwrap(); let event_loop = EventLoopBuilder::::with_user_event().build(); - let _window = WindowBuilder::new() + let window = WindowBuilder::new() .with_title("A fantastic window!") .build(&event_loop) .unwrap(); @@ -44,6 +47,9 @@ fn main() { event: WindowEvent::CloseRequested, .. } => control_flow.set_exit(), + Event::RedrawRequested(_) => { + fill::fill_window(&window); + } _ => (), } }); diff --git a/examples/drag_window.rs b/examples/drag_window.rs index 813e9b00c9..d5d8d2f4d7 100644 --- a/examples/drag_window.rs +++ b/examples/drag_window.rs @@ -9,6 +9,9 @@ use winit::{ window::{Window, WindowBuilder, WindowId}, }; +#[path = "util/fill.rs"] +mod fill; + fn main() { SimpleLogger::new().init().unwrap(); let event_loop = EventLoop::new(); @@ -59,6 +62,13 @@ fn main() { } _ => (), }, + Event::RedrawRequested(wid) => { + if wid == window_1.id() { + fill::fill_window(&window_1); + } else if wid == window_2.id() { + fill::fill_window(&window_2); + } + } _ => (), }); } diff --git a/examples/fullscreen.rs b/examples/fullscreen.rs index a71d079f28..56849d6538 100644 --- a/examples/fullscreen.rs +++ b/examples/fullscreen.rs @@ -8,6 +8,9 @@ use winit::window::{Fullscreen, WindowBuilder}; #[cfg(target_os = "macos")] use winit::platform::macos::WindowExtMacOS; +#[path = "util/fill.rs"] +mod fill; + fn main() { SimpleLogger::new().init().unwrap(); let event_loop = EventLoop::new(); @@ -116,6 +119,9 @@ fn main() { }, _ => (), }, + Event::RedrawRequested(_) => { + fill::fill_window(&window); + } _ => {} } }); diff --git a/examples/handling_close.rs b/examples/handling_close.rs index 1fe4ad3708..689d21835e 100644 --- a/examples/handling_close.rs +++ b/examples/handling_close.rs @@ -7,11 +7,14 @@ use winit::{ window::WindowBuilder, }; +#[path = "util/fill.rs"] +mod fill; + fn main() { SimpleLogger::new().init().unwrap(); let event_loop = EventLoop::new(); - let _window = WindowBuilder::new() + let window = WindowBuilder::new() .with_title("Your faithful window") .build(&event_loop) .unwrap(); @@ -80,6 +83,9 @@ fn main() { _ => (), } } + Event::RedrawRequested(_) => { + fill::fill_window(&window); + } _ => (), } }); diff --git a/examples/ime.rs b/examples/ime.rs index 59f43d4a33..39777a65ea 100644 --- a/examples/ime.rs +++ b/examples/ime.rs @@ -9,6 +9,9 @@ use winit::{ window::{ImePurpose, WindowBuilder}, }; +#[path = "util/fill.rs"] +mod fill; + fn main() { SimpleLogger::new() .with_level(LevelFilter::Trace) @@ -106,6 +109,9 @@ fn main() { println!("\nIME purpose: {ime_purpose:?}\n"); } } + Event::RedrawRequested(_) => { + fill::fill_window(&window); + } _ => (), } }); diff --git a/examples/mouse_wheel.rs b/examples/mouse_wheel.rs index 239f5a4ec1..ea0c962bbe 100644 --- a/examples/mouse_wheel.rs +++ b/examples/mouse_wheel.rs @@ -7,6 +7,9 @@ use winit::{ window::WindowBuilder, }; +#[path = "util/fill.rs"] +mod fill; + fn main() { SimpleLogger::new().init().unwrap(); let event_loop = EventLoop::new(); @@ -56,6 +59,9 @@ In other words, the deltas indicate the direction in which to move the content ( }, _ => (), }, + Event::RedrawRequested(_) => { + fill::fill_window(&window); + } _ => (), } }); diff --git a/examples/multiwindow.rs b/examples/multiwindow.rs index 3409af5a65..84ef554a30 100644 --- a/examples/multiwindow.rs +++ b/examples/multiwindow.rs @@ -9,6 +9,9 @@ use winit::{ window::Window, }; +#[path = "util/fill.rs"] +mod fill; + fn main() { SimpleLogger::new().init().unwrap(); let event_loop = EventLoop::new(); @@ -55,6 +58,11 @@ fn main() { _ => (), } } + Event::RedrawRequested(window_id) => { + if let Some(window) = windows.get(&window_id) { + fill::fill_window(window); + } + } _ => (), } }) diff --git a/examples/request_redraw.rs b/examples/request_redraw.rs index aa53050d02..16ec6ca7c2 100644 --- a/examples/request_redraw.rs +++ b/examples/request_redraw.rs @@ -7,6 +7,9 @@ use winit::{ window::WindowBuilder, }; +#[path = "util/fill.rs"] +mod fill; + fn main() { SimpleLogger::new().init().unwrap(); let event_loop = EventLoop::new(); @@ -34,6 +37,7 @@ fn main() { }, Event::RedrawRequested(_) => { println!("\nredrawing!\n"); + fill::fill_window(&window); } _ => (), } diff --git a/examples/request_redraw_threaded.rs b/examples/request_redraw_threaded.rs index d92389c556..afe874978a 100644 --- a/examples/request_redraw_threaded.rs +++ b/examples/request_redraw_threaded.rs @@ -2,7 +2,7 @@ #[cfg(not(wasm_platform))] fn main() { - use std::{thread, time}; + use std::{sync::Arc, thread, time}; use simple_logger::SimpleLogger; use winit::{ @@ -11,17 +11,26 @@ fn main() { window::WindowBuilder, }; + #[path = "util/fill.rs"] + mod fill; + SimpleLogger::new().init().unwrap(); let event_loop = EventLoop::new(); - let window = WindowBuilder::new() - .with_title("A fantastic window!") - .build(&event_loop) - .unwrap(); + let window = { + let window = WindowBuilder::new() + .with_title("A fantastic window!") + .build(&event_loop) + .unwrap(); + Arc::new(window) + }; - thread::spawn(move || loop { - thread::sleep(time::Duration::from_secs(1)); - window.request_redraw(); + thread::spawn({ + let window = window.clone(); + move || loop { + thread::sleep(time::Duration::from_secs(1)); + window.request_redraw(); + } }); event_loop.run(move |event, _, control_flow| { @@ -36,6 +45,7 @@ fn main() { } => control_flow.set_exit(), Event::RedrawRequested(_) => { println!("\nredrawing!\n"); + fill::fill_window(&window); } _ => (), } diff --git a/examples/resizable.rs b/examples/resizable.rs index 8f16172fd7..a036759c3f 100644 --- a/examples/resizable.rs +++ b/examples/resizable.rs @@ -8,6 +8,9 @@ use winit::{ window::WindowBuilder, }; +#[path = "util/fill.rs"] +mod fill; + fn main() { SimpleLogger::new().init().unwrap(); let event_loop = EventLoop::new(); @@ -44,6 +47,9 @@ fn main() { } _ => (), }, + Event::RedrawRequested(_) => { + fill::fill_window(&window); + } _ => (), }; }); diff --git a/examples/theme.rs b/examples/theme.rs index ac8854e2e3..bdbb7adbc2 100644 --- a/examples/theme.rs +++ b/examples/theme.rs @@ -7,6 +7,9 @@ use winit::{ window::{Theme, WindowBuilder}, }; +#[path = "util/fill.rs"] +mod fill; + fn main() { SimpleLogger::new().init().unwrap(); let event_loop = EventLoop::new(); @@ -65,6 +68,10 @@ fn main() { } _ => (), }, + Event::RedrawRequested(_) => { + println!("\nredrawing!\n"); + fill::fill_window(&window); + } _ => (), } }); diff --git a/examples/timer.rs b/examples/timer.rs index 4d609bef23..d2bd2977d5 100644 --- a/examples/timer.rs +++ b/examples/timer.rs @@ -10,11 +10,14 @@ use winit::{ window::WindowBuilder, }; +#[path = "util/fill.rs"] +mod fill; + fn main() { SimpleLogger::new().init().unwrap(); let event_loop = EventLoop::new(); - let _window = WindowBuilder::new() + let window = WindowBuilder::new() .with_title("A fantastic window!") .build(&event_loop) .unwrap(); @@ -36,6 +39,9 @@ fn main() { event: WindowEvent::CloseRequested, .. } => control_flow.set_exit(), + Event::RedrawRequested(_) => { + fill::fill_window(&window); + } _ => (), } }); diff --git a/examples/touchpad_gestures.rs b/examples/touchpad_gestures.rs index 1a749a19a6..2ebe83623b 100644 --- a/examples/touchpad_gestures.rs +++ b/examples/touchpad_gestures.rs @@ -5,11 +5,14 @@ use winit::{ window::WindowBuilder, }; +#[path = "util/fill.rs"] +mod fill; + fn main() { SimpleLogger::new().init().unwrap(); let event_loop = EventLoop::new(); - let _window = WindowBuilder::new() + let window = WindowBuilder::new() .with_title("Touchpad gestures") .build(&event_loop) .unwrap(); @@ -41,6 +44,8 @@ fn main() { } _ => (), } + } else if let Event::RedrawRequested(_) = event { + fill::fill_window(&window); } }); } diff --git a/examples/transparent.rs b/examples/transparent.rs index 88c69d1b30..134be3adad 100644 --- a/examples/transparent.rs +++ b/examples/transparent.rs @@ -7,6 +7,9 @@ use winit::{ window::WindowBuilder, }; +#[path = "util/fill.rs"] +mod fill; + fn main() { SimpleLogger::new().init().unwrap(); let event_loop = EventLoop::new(); @@ -28,6 +31,9 @@ fn main() { event: WindowEvent::CloseRequested, .. } => control_flow.set_exit(), + Event::RedrawRequested(_) => { + fill::fill_window(&window); + } _ => (), } }); diff --git a/examples/util/fill.rs b/examples/util/fill.rs new file mode 100644 index 0000000000..e08f92247a --- /dev/null +++ b/examples/util/fill.rs @@ -0,0 +1,81 @@ +//! Fill the window buffer with a solid color. +//! +//! Launching a window without drawing to it has unpredictable results varying from platform to +//! platform. In order to have well-defined examples, this module provides an easy way to +//! fill the window buffer with a solid color. +//! +//! The `softbuffer` crate is used, largely because of its ease of use. `glutin` or `wgpu` could +//! also be used to fill the window buffer, but they are more complicated to use. + +use winit::window::Window; + +#[cfg(not(any(target_os = "android", target_os = "ios")))] +pub(super) fn fill_window(window: &Window) { + use softbuffer::{Context, Surface}; + use std::cell::RefCell; + use std::collections::HashMap; + use std::num::NonZeroU32; + use winit::window::WindowId; + + /// The graphics context used to draw to a window. + struct GraphicsContext { + /// The global softbuffer context. + context: Context, + + /// The hash map of window IDs to surfaces. + surfaces: HashMap, + } + + impl GraphicsContext { + fn new(w: &Window) -> Self { + Self { + context: unsafe { Context::new(w) }.expect("Failed to create a softbuffer context"), + surfaces: HashMap::new(), + } + } + + fn surface(&mut self, w: &Window) -> &mut Surface { + self.surfaces.entry(w.id()).or_insert_with(|| { + unsafe { Surface::new(&self.context, w) } + .expect("Failed to create a softbuffer surface") + }) + } + } + + thread_local! { + /// A static, thread-local map of graphics contexts to open windows. + static GC: RefCell> = RefCell::new(None); + } + + GC.with(|gc| { + // Either get the last context used or create a new one. + let mut gc = gc.borrow_mut(); + let surface = gc + .get_or_insert_with(|| GraphicsContext::new(window)) + .surface(window); + + // Fill a buffer with a solid color. + const DARK_GRAY: u32 = 0xFF181818; + let size = window.inner_size(); + + surface + .resize( + NonZeroU32::new(size.width).expect("Width must be greater than zero"), + NonZeroU32::new(size.height).expect("Height must be greater than zero"), + ) + .expect("Failed to resize the softbuffer surface"); + + let mut buffer = surface + .buffer_mut() + .expect("Failed to get the softbuffer buffer"); + buffer.fill(DARK_GRAY); + buffer + .present() + .expect("Failed to present the softbuffer buffer"); + }) +} + +#[cfg(any(target_os = "android", target_os = "ios"))] +pub(super) fn fill_window(_window: &Window) { + // No-op on mobile platforms. +} diff --git a/examples/window.rs b/examples/window.rs index e54a2f661c..4a5d8b0068 100644 --- a/examples/window.rs +++ b/examples/window.rs @@ -7,6 +7,9 @@ use winit::{ window::WindowBuilder, }; +#[path = "util/fill.rs"] +mod fill; + fn main() { SimpleLogger::new().init().unwrap(); let event_loop = EventLoop::new(); @@ -29,6 +32,9 @@ fn main() { Event::MainEventsCleared => { window.request_redraw(); } + Event::RedrawRequested(_) => { + fill::fill_window(&window); + } _ => (), } }); diff --git a/examples/window_buttons.rs b/examples/window_buttons.rs index 5d41144dbd..cab9ead49c 100644 --- a/examples/window_buttons.rs +++ b/examples/window_buttons.rs @@ -10,6 +10,9 @@ use winit::{ window::{WindowBuilder, WindowButtons}, }; +#[path = "util/fill.rs"] +mod fill; + fn main() { SimpleLogger::new().init().unwrap(); let event_loop = EventLoop::new(); @@ -62,6 +65,9 @@ fn main() { event: WindowEvent::CloseRequested, window_id, } if window_id == window.id() => control_flow.set_exit(), + Event::RedrawRequested(_) => { + fill::fill_window(&window); + } _ => (), } }); diff --git a/examples/window_debug.rs b/examples/window_debug.rs index 01077a8b6e..57f5350936 100644 --- a/examples/window_debug.rs +++ b/examples/window_debug.rs @@ -10,6 +10,9 @@ use winit::{ window::{Fullscreen, WindowBuilder}, }; +#[path = "util/fill.rs"] +mod fill; + fn main() { SimpleLogger::new().init().unwrap(); let event_loop = EventLoop::new(); @@ -126,6 +129,9 @@ fn main() { event: WindowEvent::CloseRequested, window_id, } if window_id == window.id() => control_flow.set_exit(), + Event::RedrawRequested(_) => { + fill::fill_window(&window); + } _ => (), } }); diff --git a/examples/window_drag_resize.rs b/examples/window_drag_resize.rs index 95a6737791..0c12940716 100644 --- a/examples/window_drag_resize.rs +++ b/examples/window_drag_resize.rs @@ -11,6 +11,9 @@ use winit::{ const BORDER: f64 = 8.0; +#[path = "util/fill.rs"] +mod fill; + fn main() { SimpleLogger::new().init().unwrap(); let event_loop = EventLoop::new(); @@ -66,6 +69,9 @@ fn main() { } _ => (), }, + Event::RedrawRequested(_) => { + fill::fill_window(&window); + } _ => (), }); } diff --git a/examples/window_icon.rs b/examples/window_icon.rs index ed98b3d577..e87372c208 100644 --- a/examples/window_icon.rs +++ b/examples/window_icon.rs @@ -9,6 +9,9 @@ use winit::{ window::{Icon, WindowBuilder}, }; +#[path = "util/fill.rs"] +mod fill; + fn main() { SimpleLogger::new().init().unwrap(); @@ -42,6 +45,8 @@ fn main() { } _ => (), } + } else if let Event::RedrawRequested(_) = event { + fill::fill_window(&window); } }); } diff --git a/examples/window_resize_increments.rs b/examples/window_resize_increments.rs index ce06daf22f..d2318effaf 100644 --- a/examples/window_resize_increments.rs +++ b/examples/window_resize_increments.rs @@ -7,6 +7,9 @@ use winit::{ window::WindowBuilder, }; +#[path = "util/fill.rs"] +mod fill; + fn main() { SimpleLogger::new().init().unwrap(); let event_loop = EventLoop::new(); @@ -51,6 +54,9 @@ fn main() { window.set_resize_increments(new_increments); } Event::MainEventsCleared => window.request_redraw(), + Event::RedrawRequested(_) => { + fill::fill_window(&window); + } _ => (), } }); diff --git a/examples/window_run_return.rs b/examples/window_run_return.rs index f088a51437..2a2758d0de 100644 --- a/examples/window_run_return.rs +++ b/examples/window_run_return.rs @@ -19,10 +19,14 @@ fn main() { platform::run_return::EventLoopExtRunReturn, window::WindowBuilder, }; + + #[path = "util/fill.rs"] + mod fill; + let mut event_loop = EventLoop::new(); SimpleLogger::new().init().unwrap(); - let _window = WindowBuilder::new() + let window = WindowBuilder::new() .with_title("A fantastic window!") .build(&event_loop) .unwrap(); @@ -48,6 +52,9 @@ fn main() { Event::MainEventsCleared => { control_flow.set_exit(); } + Event::RedrawRequested(_) => { + fill::fill_window(&window); + } _ => (), } });