Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update to winit 0.27. Handle new window events (IME and Occluded) #904

Closed
wants to merge 5 commits into from
Closed
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
4 changes: 4 additions & 0 deletions examples/nannou_basics/all_functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ fn model(app: &App) -> Model {
.focused(window_focused)
.unfocused(window_unfocused)
.closed(window_closed)
.occluded(occluded)
.build()
.unwrap();
Model {}
Expand Down Expand Up @@ -79,6 +80,7 @@ fn window_event(_app: &App, _model: &mut Model, event: WindowEvent) {
Focused => {}
Unfocused => {}
Closed => {}
Occluded(_val) => {}
}
}

Expand Down Expand Up @@ -119,3 +121,5 @@ fn hovered_file(_app: &App, _model: &mut Model, _path: std::path::PathBuf) {}
fn hovered_file_cancelled(_app: &App, _model: &mut Model) {}

fn dropped_file(_app: &App, _model: &mut Model, _path: std::path::PathBuf) {}

fn occluded(_app: &App, _model: &mut Model, _val: bool) {}
1 change: 1 addition & 0 deletions examples/offline/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ fn window_event(_app: &App, _model: &mut Model, event: WindowEvent) {
Focused => {}
Unfocused => {}
Closed => {}
Occluded(_val) => {}
}
}

Expand Down
1 change: 1 addition & 0 deletions examples/rust_basics/1_nannou_events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ fn event(_app: &App, _model: &mut Model, event: WindowEvent) {
Focused => {}
Unfocused => {}
Closed => {}
Occluded(_val) => {}
}
}

Expand Down
2 changes: 2 additions & 0 deletions guide/src/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ back to the origins.

# Unreleased

- Handle `winit::window::WindowEvent::Occluded` events.
- Update winit to `0.27`.
- Add GL backend to default backends for better WASM support.
- Add CI for testing the `wasm32-unknown-unknown` target.
- Enable `wgpu/webgl` when `wasm` feature is enabled.
Expand Down
2 changes: 1 addition & 1 deletion nannou/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ toml = "0.5"
walkdir = "2"
web-sys = { version = "0.3.55", optional = true }
wgpu_upstream = { version = "0.11.1", package = "wgpu" }
winit = "0.26"
winit = "0.27"

[features]
default = ["notosans"]
Expand Down
1 change: 1 addition & 0 deletions nannou/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1708,6 +1708,7 @@ where
event::WindowEvent::Focused => call_user_function!(focused),
event::WindowEvent::Unfocused => call_user_function!(unfocused),
event::WindowEvent::Closed => call_user_function!(closed),
event::WindowEvent::Occluded(val) => call_user_function!(occluded, val),
}
}
}
Expand Down
15 changes: 15 additions & 0 deletions nannou/src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,13 @@ pub enum WindowEvent {

/// The window was closed and is no longer stored in the `App`.
Closed,

/// The window has been hidden from view. This event could be used to
/// optimize rendering.
///
/// Currently supported on macOS, unsupported on iOS / Android / Web /
/// Wayland / Windows.
Occluded(bool),
}

impl WindowEvent {
Expand Down Expand Up @@ -307,6 +314,14 @@ impl WindowEvent {
| winit::event::WindowEvent::ScaleFactorChanged { .. } => {
return None;
}

// These events will never happen as long as
// `Window::set_ime_allowed` is not called.
winit::event::WindowEvent::Ime(_) => {
return None;
}

winit::event::WindowEvent::Occluded(occluded) => Occluded(*occluded),
};

Some(event)
Expand Down
131 changes: 88 additions & 43 deletions nannou/src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ pub struct Builder<'app> {
app: &'app App,
window: winit::window::WindowBuilder,
title_was_set: bool,
fullscreen: Option<Fullscreen>,
size: Option<winit::dpi::Size>,
min_size: Option<winit::dpi::Size>,
max_size: Option<winit::dpi::Size>,
surface_conf_builder: SurfaceConfigurationBuilder,
power_preference: wgpu::PowerPreference,
force_fallback_adapter: bool,
Expand Down Expand Up @@ -76,6 +80,7 @@ pub(crate) struct UserFunctions {
pub(crate) focused: Option<FocusedFnAny>,
pub(crate) unfocused: Option<UnfocusedFnAny>,
pub(crate) closed: Option<ClosedFnAny>,
pub(crate) occluded: Option<OccludedFnAny>,
}

/// The user function type for drawing their model to the surface of a single window.
Expand Down Expand Up @@ -163,6 +168,9 @@ pub type UnfocusedFn<Model> = fn(&App, &mut Model);
/// A function for processing window closed events.
pub type ClosedFn<Model> = fn(&App, &mut Model);

/// A function for processing window occluded events.
pub type OccludedFn<Model> = fn(&App, &mut Model, bool);

/// Errors that might occur while building the window.
#[derive(Debug)]
pub enum BuildError {
Expand Down Expand Up @@ -230,6 +238,7 @@ fn_any!(DroppedFileFn<M>, DroppedFileFnAny);
fn_any!(FocusedFn<M>, FocusedFnAny);
fn_any!(UnfocusedFn<M>, UnfocusedFnAny);
fn_any!(ClosedFn<M>, ClosedFnAny);
fn_any!(OccludedFn<M>, OccludedFnAny);

/// A nannou window.
///
Expand Down Expand Up @@ -355,6 +364,10 @@ impl<'app> Builder<'app> {
app,
window: winit::window::WindowBuilder::new(),
title_was_set: false,
fullscreen: None,
size: None,
min_size: None,
max_size: None,
surface_conf_builder: Default::default(),
power_preference: Self::DEFAULT_POWER_PREFERENCE,
force_fallback_adapter: Self::DEFAULT_FORCE_FALLBACK_ADAPTER,
Expand Down Expand Up @@ -691,6 +704,16 @@ impl<'app> Builder<'app> {
self
}

/// A function for processing the occluded event associated with this
/// window.
pub fn occluded<M>(mut self, f: OccludedFn<M>) -> Self
where
M: 'static,
{
self.user_functions.occluded = Some(OccludedFnAny::from_fn_ptr(f));
self
}

/// The maximum number of simultaneous capture frame jobs that can be run for this window
/// before we block and wait for the existing jobs to complete.
///
Expand Down Expand Up @@ -737,6 +760,10 @@ impl<'app> Builder<'app> {
app,
mut window,
title_was_set,
fullscreen,
size,
min_size,
max_size,
surface_conf_builder,
power_preference,
force_fallback_adapter,
Expand Down Expand Up @@ -771,39 +798,33 @@ impl<'app> Builder<'app> {
))]
{
use winit::platform::unix::WindowBuilderExtUnix;
window = window.with_class("nannou".to_string(), "nannou".to_string());
window = window.with_name("nannou".to_string(), "nannou".to_string());
}

// Set default dimensions in the case that none were given.
let initial_window_size = window
.window
.inner_size
let initial_window_size = size
.or_else(|| {
window
.window
.fullscreen
.as_ref()
.and_then(|fullscreen| match fullscreen {
Fullscreen::Exclusive(video_mode) => {
let monitor = video_mode.monitor();
Some(
video_mode
.size()
.to_logical::<f32>(monitor.scale_factor())
.into(),
)
}
Fullscreen::Borderless(monitor) => monitor.as_ref().map(|monitor| {
monitor
fullscreen.as_ref().and_then(|fullscreen| match fullscreen {
Fullscreen::Exclusive(video_mode) => {
let monitor = video_mode.monitor();
Some(
video_mode
.size()
.to_logical::<f32>(monitor.scale_factor())
.into()
}),
})
.into(),
)
}
Fullscreen::Borderless(monitor) => monitor.as_ref().map(|monitor| {
monitor
.size()
.to_logical::<f32>(monitor.scale_factor())
.into()
}),
})
})
.unwrap_or_else(|| {
let mut dim = DEFAULT_DIMENSIONS;
if let Some(min) = window.window.min_inner_size {
if let Some(min) = min_size {
match min {
winit::dpi::Size::Logical(min) => {
dim.width = dim.width.max(min.width as _);
Expand All @@ -816,7 +837,7 @@ impl<'app> Builder<'app> {
}
}
}
if let Some(max) = window.window.max_inner_size {
if let Some(max) = max_size {
match max {
winit::dpi::Size::Logical(max) => {
dim.width = dim.width.min(max.width as _);
Expand All @@ -832,24 +853,23 @@ impl<'app> Builder<'app> {
dim.into()
});

// Use the `initial_window_size` as the default dimensions for the window if none
// were specified.
if window.window.inner_size.is_none() && window.window.fullscreen.is_none() {
window.window.inner_size = Some(initial_window_size);
// Defaults dimensions are used if no size was set and not in fullscreen
// mode.
if size.is_none() && fullscreen.is_none() {
window = window.with_inner_size(initial_window_size);
}

// Set a default minimum window size for configuring the surface.
if window.window.min_inner_size.is_none() && window.window.fullscreen.is_none() {
window.window.min_inner_size = Some(winit::dpi::Size::Physical(MIN_SC_PIXELS));
if min_size.is_none() && fullscreen.is_none() {
window = window.with_min_inner_size(winit::dpi::Size::Physical(MIN_SC_PIXELS));
}

// Background must be initially cleared
let is_invalidated = true;

let clear_color = clear_color.unwrap_or_else(|| {
let mut color: wgpu::Color = Default::default();
color.a = if window.window.transparent { 0.0 } else { 1.0 };
color
let clear_color = clear_color.unwrap_or_else(|| nannou_wgpu::Color {
a: if window.transparent() { 0.0 } else { 1.0 },
..Default::default()
});

// Build the window.
Expand Down Expand Up @@ -963,6 +983,10 @@ impl<'app> Builder<'app> {
app,
window,
title_was_set,
fullscreen,
size,
min_size,
max_size,
device_desc,
power_preference,
force_fallback_adapter,
Expand All @@ -978,6 +1002,10 @@ impl<'app> Builder<'app> {
app,
window,
title_was_set,
fullscreen,
size,
min_size,
max_size,
device_desc,
power_preference,
force_fallback_adapter,
Expand All @@ -999,13 +1027,17 @@ impl<'app> Builder<'app> {
///
/// This describes to the "inner" part of the window, not including desktop decorations like the
/// title bar.
pub fn size(self, width: u32, height: u32) -> Self {
self.map_window(|w| w.with_inner_size(winit::dpi::LogicalSize { width, height }))
pub fn size(mut self, width: u32, height: u32) -> Self {
let size = winit::dpi::LogicalSize { width, height };
self.size = Some(size.into());
self.map_window(|w| w.with_inner_size(size))
}

/// Set the minimum size in points for the window.
pub fn min_size(self, width: u32, height: u32) -> Self {
self.map_window(|w| w.with_min_inner_size(winit::dpi::LogicalSize { width, height }))
pub fn min_size(mut self, width: u32, height: u32) -> Self {
let size = winit::dpi::LogicalSize { width, height };
self.min_size = Some(size.into());
self.map_window(|w| w.with_min_inner_size(size))
}

/// Set the maximum size in points for the window.
Expand All @@ -1017,8 +1049,10 @@ impl<'app> Builder<'app> {
///
/// This describes to the "inner" part of the window, not including desktop decorations like the
/// title bar.
pub fn size_pixels(self, width: u32, height: u32) -> Self {
self.map_window(|w| w.with_inner_size(winit::dpi::PhysicalSize { width, height }))
pub fn size_pixels(mut self, width: u32, height: u32) -> Self {
let size = winit::dpi::PhysicalSize { width, height };
self.size = Some(size.into());
self.map_window(|w| w.with_inner_size(size))
}

/// Whether or not the window should be resizable after creation.
Expand All @@ -1036,8 +1070,9 @@ impl<'app> Builder<'app> {
}

/// Create the window fullscreened on the current monitor.
pub fn fullscreen(self) -> Self {
pub fn fullscreen(mut self) -> Self {
let fullscreen = Fullscreen::Borderless(self.app.primary_monitor());
self.fullscreen = Some(fullscreen.clone());
self.fullscreen_with(Some(fullscreen))
}

Expand Down Expand Up @@ -1380,7 +1415,17 @@ impl Window {
/// - **iOS:** Always returns an Err.
/// - **Web:** Has no effect.
pub fn set_cursor_grab(&self, grab: bool) -> Result<(), winit::error::ExternalError> {
self.window.set_cursor_grab(grab)
if grab {
self.window
.set_cursor_grab(winit::window::CursorGrabMode::Confined)
.or_else(|_e| {
self.window
.set_cursor_grab(winit::window::CursorGrabMode::Locked)
})
} else {
self.window
.set_cursor_grab(winit::window::CursorGrabMode::None)
}
}

/// Set the cursor's visibility.
Expand Down
2 changes: 1 addition & 1 deletion nannou_egui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@ readme = "../README.md"
[dependencies]
egui_wgpu_backend = "0.14"
egui = "0.15.0"
winit = "0.26"
winit = "0.27"
nannou = { version = "0.18.1", path = "../nannou" }