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.29 #3606

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from 4 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
679 changes: 522 additions & 157 deletions Cargo.lock

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions crates/eframe/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ image = { version = "0.24", default-features = false, features = [
"png",
] } # Needed for app icon
raw-window-handle.workspace = true
winit = { version = "0.28.1", default-features = false }
winit = { version = "0.29", default-features = false, features = ["rwh_05"] }

# optional native:
directories-next = { version = "2", optional = true }
Expand All @@ -138,8 +138,8 @@ pollster = { version = "0.3", optional = true } # needed for wgpu

# we can expose these to user so that they can select which backends they want to enable to avoid compiling useless deps.
# this can be done at the same time we expose x11/wayland features of winit crate.
glutin = { version = "0.30", optional = true }
glutin-winit = { version = "0.3.0", optional = true }
glutin = { version = "0.31", optional = true }
glutin-winit = { version = "0.4", optional = true }
puffin = { workspace = true, optional = true }
wgpu = { workspace = true, optional = true }

Expand Down
2 changes: 1 addition & 1 deletion crates/eframe/src/native/epi_integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ impl EpiIntegration {

pub fn on_window_event(
&mut self,
event: &winit::event::WindowEvent<'_>,
event: &winit::event::WindowEvent,
egui_winit: &mut egui_winit::State,
) -> EventResponse {
crate::profile_function!(egui_winit::short_window_event_description(event));
Expand Down
23 changes: 7 additions & 16 deletions crates/eframe/src/native/glow_integration.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use std::{cell::RefCell, rc::Rc, sync::Arc, time::Instant};

use glutin::{
context::NotCurrentGlContext,
display::GetGlDisplay,
prelude::{GlDisplay, NotCurrentGlContextSurfaceAccessor, PossiblyCurrentGlContext},
prelude::{GlDisplay, PossiblyCurrentGlContext},
surface::GlSurface,
};
use raw_window_handle::{HasRawDisplayHandle as _, HasRawWindowHandle as _};
Expand Down Expand Up @@ -402,7 +403,7 @@ impl WinitApp for GlowWinitApp {
fn on_event(
&mut self,
event_loop: &EventLoopWindowTarget<UserEvent>,
event: &winit::event::Event<'_, UserEvent>,
event: &winit::event::Event<UserEvent>,
) -> Result<EventResult> {
crate::profile_function!(winit_integration::short_event_description(event));

Expand Down Expand Up @@ -434,15 +435,6 @@ impl WinitApp for GlowWinitApp {
EventResult::Wait
}

winit::event::Event::MainEventsCleared => {
if let Some(running) = &self.running {
if let Err(err) = running.glutin.borrow_mut().on_resume(event_loop) {
log::warn!("on_resume failed {err}");
}
}
EventResult::Wait
}

Copy link
Contributor Author

@fornwall fornwall Nov 22, 2023

Choose a reason for hiding this comment

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

We should be able to remove this, as winit::event::Event::Resumed is handled above.

Let's make sure to test on Android - there is a eframe using example in android-activity.

Copy link
Contributor

Choose a reason for hiding this comment

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

While you're working on glow_integration, it's probably wise to remove this stale comment entirely:

// Note: that the current Glutin API design tightly couples the GL context with
// the Window which means it's not practically possible to just destroy the
// window and re-create a new window while continuing to use the same GL context.
//
// For now this means it's not possible to support Android as well as we can with
// wgpu because we're basically forced to destroy and recreate _everything_ when
// the application suspends and resumes.
//
// There is work in progress to improve the Glutin API so it has a separate Surface
// API that would allow us to just destroy a Window/Surface when suspending, see:
// https://github.com/rust-windowing/glutin/pull/1435

The issue linked there has long been closed and fixed. Windows/Surfaces are only associated with context when/while it's made current, and it looks like eframe supports Android now with a proper Resumed/Suspended cycle?

winit::event::Event::WindowEvent { event, window_id } => {
if let Some(running) = &mut self.running {
running.on_window_event(*window_id, event)
Expand Down Expand Up @@ -664,7 +656,7 @@ impl GlowWinitRunning {
fn on_window_event(
&mut self,
window_id: WindowId,
event: &winit::event::WindowEvent<'_>,
event: &winit::event::WindowEvent,
) -> EventResult {
crate::profile_function!(egui_winit::short_window_event_description(event));

Expand Down Expand Up @@ -703,10 +695,9 @@ impl GlowWinitRunning {
}
}

winit::event::WindowEvent::ScaleFactorChanged { new_inner_size, .. } => {
if let Some(viewport_id) = viewport_id {
winit::event::WindowEvent::ScaleFactorChanged { .. } => {
if viewport_id.is_some() {
repaint_asap = true;
glutin.resize(viewport_id, **new_inner_size);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

In winit 0.29 ScaleFactorChanged does not expose the new OS suggested window size. But, a Resized event will come (recently fixed on macOS - rust-windowing/winit#3214).

}
}

Expand Down Expand Up @@ -821,7 +812,7 @@ impl GlutinWindowContext {
// Create GL display. This may probably create a window too on most platforms. Definitely on `MS windows`. Never on Android.
let display_builder = glutin_winit::DisplayBuilder::new()
// we might want to expose this option to users in the future. maybe using an env var or using native_options.
.with_preference(glutin_winit::ApiPrefence::FallbackEgl) // https://github.com/emilk/egui/issues/2520#issuecomment-1367841150
.with_preference(glutin_winit::ApiPreference::FallbackEgl) // https://github.com/emilk/egui/issues/2520#issuecomment-1367841150
.with_window_builder(Some(create_winit_window_builder(
egui_ctx,
event_loop,
Expand Down
67 changes: 43 additions & 24 deletions crates/eframe/src/native/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ fn create_event_loop(native_options: &mut epi::NativeOptions) -> EventLoop<UserE
let mut builder = create_event_loop_builder(native_options);

crate::profile_scope!("EventLoopBuilder::build");
builder.build()
Copy link
Contributor Author

Choose a reason for hiding this comment

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

TODO: Add error handling.

builder.build().unwrap()
}

/// Access a thread-local event loop.
Expand Down Expand Up @@ -67,7 +67,7 @@ fn run_and_return(
event_loop: &mut EventLoop<UserEvent>,
mut winit_app: impl WinitApp,
) -> Result<()> {
use winit::{event_loop::ControlFlow, platform::run_return::EventLoopExtRunReturn as _};
use winit::{event_loop::ControlFlow, platform::run_on_demand::EventLoopExtRunOnDemand};

log::debug!("Entering the winit event loop (run_return)…");

Expand All @@ -76,20 +76,22 @@ fn run_and_return(

let mut returned_result = Ok(());

event_loop.run_return(|event, event_loop, control_flow| {
let _ = event_loop.run_on_demand(|event, event_loop_window_target| {
emilk marked this conversation as resolved.
Show resolved Hide resolved
crate::profile_scope!("winit_event", short_event_description(&event));

let event_result = match &event {
winit::event::Event::LoopDestroyed => {
// On Mac, Cmd-Q we get here and then `run_return` doesn't return (despite its name),
winit::event::Event::LoopExiting => {
// On Mac, Cmd-Q we get here and then `run_on_demand` doesn't return (despite its name),
// so we need to save state now:
log::debug!("Received Event::LoopDestroyed - saving app state…");
log::debug!("Received Event::LoopExiting - saving app state…");
winit_app.save_and_destroy();
*control_flow = ControlFlow::Exit;
return;
}

winit::event::Event::RedrawRequested(window_id) => {
winit::event::Event::WindowEvent {
event: winit::event::WindowEvent::RedrawRequested,
window_id,
} => {
windows_next_repaint_times.remove(window_id);
winit_app.run_ui_and_paint(*window_id)
}
Expand Down Expand Up @@ -120,7 +122,7 @@ fn run_and_return(
EventResult::Wait
}

event => match winit_app.on_event(event_loop, event) {
event => match winit_app.on_event(event_loop_window_target, event) {
Ok(event_result) => event_result,
Err(err) => {
log::error!("Exiting because of error: {err} during event {event:?}");
Expand All @@ -132,7 +134,7 @@ fn run_and_return(

match event_result {
EventResult::Wait => {
control_flow.set_wait();
event_loop_window_target.set_control_flow(ControlFlow::Wait);
}
EventResult::RepaintNow(window_id) => {
log::trace!("Repaint caused by {}", short_event_description(&event));
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Cane some of this be simplified or removed for winit 0.29?

Expand Down Expand Up @@ -160,7 +162,7 @@ fn run_and_return(
EventResult::Exit => {
log::debug!("Asking to exit event loop…");
winit_app.save_and_destroy();
*control_flow = ControlFlow::Exit;
event_loop_window_target.exit();
Copy link
Contributor Author

@fornwall fornwall Nov 22, 2023

Choose a reason for hiding this comment

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

Do we still need this winit_app.save_and_destroy() - we are going to get a Event::LoopExiting event later?

return;
}
}
Expand All @@ -171,15 +173,18 @@ fn run_and_return(
use winit::event::Event;
if matches!(
event,
Event::RedrawEventsCleared | Event::RedrawRequested(_) | Event::Resumed
Event::WindowEvent {
event: winit::event::WindowEvent::RedrawRequested,
..
} | Event::Resumed
) {
windows_next_repaint_times.retain(|window_id, repaint_time| {
if Instant::now() < *repaint_time {
return true;
};

next_repaint_time = None;
control_flow.set_poll();
event_loop_window_target.set_control_flow(ControlFlow::Poll);

if let Some(window) = winit_app.window(*window_id) {
log::trace!("request_redraw for {window_id:?}");
Expand All @@ -196,7 +201,7 @@ fn run_and_return(
if time_until_next < std::time::Duration::from_secs(10_000) {
log::trace!("WaitUntil {time_until_next:?}");
}
control_flow.set_wait_until(next_repaint_time);
event_loop_window_target.set_control_flow(ControlFlow::WaitUntil(next_repaint_time));
};
});

Expand All @@ -220,21 +225,25 @@ fn run_and_return(
}

fn run_and_exit(event_loop: EventLoop<UserEvent>, mut winit_app: impl WinitApp + 'static) -> ! {
use winit::event_loop::ControlFlow;
log::debug!("Entering the winit event loop (run)…");

// When to repaint what window
let mut windows_next_repaint_times = HashMap::default();

event_loop.run(move |event, event_loop, control_flow| {
let result = event_loop.run(move |event, event_loop_window_target| {
fornwall marked this conversation as resolved.
Show resolved Hide resolved
crate::profile_scope!("winit_event", short_event_description(&event));

let event_result = match &event {
winit::event::Event::LoopDestroyed => {
log::debug!("Received Event::LoopDestroyed");
winit::event::Event::LoopExiting => {
log::debug!("Received Event::LoopExiting");
EventResult::Exit
}

winit::event::Event::RedrawRequested(window_id) => {
winit::event::Event::WindowEvent {
event: winit::event::WindowEvent::RedrawRequested,
window_id,
} => {
windows_next_repaint_times.remove(window_id);
winit_app.run_ui_and_paint(*window_id)
}
Expand Down Expand Up @@ -264,7 +273,7 @@ fn run_and_exit(event_loop: EventLoop<UserEvent>, mut winit_app: impl WinitApp +
EventResult::Wait
}

event => match winit_app.on_event(event_loop, event) {
event => match winit_app.on_event(event_loop_window_target, event) {
Ok(event_result) => event_result,
Err(err) => {
panic!("eframe encountered a fatal error: {err} during event {event:?}");
Expand All @@ -274,7 +283,7 @@ fn run_and_exit(event_loop: EventLoop<UserEvent>, mut winit_app: impl WinitApp +

match event_result {
EventResult::Wait => {
control_flow.set_wait();
event_loop_window_target.set_control_flow(ControlFlow::Wait);
}
EventResult::RepaintNow(window_id) => {
log::trace!("Repaint caused by {}", short_event_description(&event));
Expand Down Expand Up @@ -314,15 +323,18 @@ fn run_and_exit(event_loop: EventLoop<UserEvent>, mut winit_app: impl WinitApp +
use winit::event::Event;
if matches!(
event,
Event::RedrawEventsCleared | Event::RedrawRequested(_) | Event::Resumed
Event::WindowEvent {
event: winit::event::WindowEvent::RedrawRequested,
..
} | Event::Resumed
) {
windows_next_repaint_times.retain(|window_id, repaint_time| {
if Instant::now() < *repaint_time {
return true;
}

next_repaint_time = None;
control_flow.set_poll();
event_loop_window_target.set_control_flow(ControlFlow::Poll);

if let Some(window) = winit_app.window(*window_id) {
log::trace!("request_redraw for {window_id:?}");
Expand Down Expand Up @@ -350,9 +362,16 @@ fn run_and_exit(event_loop: EventLoop<UserEvent>, mut winit_app: impl WinitApp +
.map(|window| window.request_redraw())
});

control_flow.set_wait_until(next_repaint_time);
event_loop_window_target.set_control_flow(ControlFlow::WaitUntil(next_repaint_time));
};
})
});

std::process::exit(if let Err(e) = result {
log::warn!("Error from event loop: {e}");
1
} else {
0
});
emilk marked this conversation as resolved.
Show resolved Hide resolved
}

// ----------------------------------------------------------------------------
Expand Down
17 changes: 4 additions & 13 deletions crates/eframe/src/native/wgpu_integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ impl WinitApp for WgpuWinitApp {
fn on_event(
&mut self,
event_loop: &EventLoopWindowTarget<UserEvent>,
event: &winit::event::Event<'_, UserEvent>,
event: &winit::event::Event<UserEvent>,
) -> Result<EventResult> {
crate::profile_function!(winit_integration::short_event_description(event));

Expand Down Expand Up @@ -654,7 +654,7 @@ impl WgpuWinitRunning {
fn on_window_event(
&mut self,
window_id: WindowId,
event: &winit::event::WindowEvent<'_>,
event: &winit::event::WindowEvent,
) -> EventResult {
crate::profile_function!(egui_winit::short_window_event_description(event));

Expand Down Expand Up @@ -703,18 +703,9 @@ impl WgpuWinitRunning {
}
}

winit::event::WindowEvent::ScaleFactorChanged { new_inner_size, .. } => {
use std::num::NonZeroU32;
if let (Some(width), Some(height), Some(viewport_id)) = (
NonZeroU32::new(new_inner_size.width),
NonZeroU32::new(new_inner_size.height),
viewport_id,
) {
repaint_asap = true;
shared.painter.on_window_resized(viewport_id, width, height);
}
winit::event::WindowEvent::ScaleFactorChanged { .. } => {
repaint_asap = true;
}

winit::event::WindowEvent::CloseRequested => {
if viewport_id == Some(ViewportId::ROOT) && integration.should_close() {
log::debug!(
Expand Down
4 changes: 2 additions & 2 deletions crates/eframe/src/native/winit_integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ pub trait WinitApp {
fn on_event(
&mut self,
event_loop: &EventLoopWindowTarget<UserEvent>,
event: &winit::event::Event<'_, UserEvent>,
event: &winit::event::Event<UserEvent>,
) -> crate::Result<EventResult>;
}

Expand Down Expand Up @@ -117,7 +117,7 @@ pub fn system_theme(window: &Window, options: &crate::NativeOptions) -> Option<c

/// Short and fast description of an event.
/// Useful for logging and profiling.
pub fn short_event_description(event: &winit::event::Event<'_, UserEvent>) -> &'static str {
pub fn short_event_description(event: &winit::event::Event<UserEvent>) -> &'static str {
use winit::event::Event;

match event {
Expand Down
2 changes: 1 addition & 1 deletion crates/egui-wgpu/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ wgpu.workspace = true
## Enable this when generating docs.
document-features = { version = "0.2", optional = true }

winit = { version = "0.28", default-features = false, optional = true }
winit = { version = "0.29", default-features = false, optional = true, features = ["rwh_05"] }

# Native:
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
Expand Down
4 changes: 2 additions & 2 deletions crates/egui-winit/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,12 @@ egui = { version = "0.24.0", path = "../egui", default-features = false, feature
log = { version = "0.4", features = ["std"] }
raw-window-handle.workspace = true
web-time = { version = "0.2" } # We use web-time so we can (maybe) compile for web
winit = { version = "0.28", default-features = false }
winit = { version = "0.29", default-features = false, features = ["rwh_05"] }
emilk marked this conversation as resolved.
Show resolved Hide resolved
emilk marked this conversation as resolved.
Show resolved Hide resolved

#! ### Optional dependencies

# feature accesskit
accesskit_winit = { version = "0.15.0", optional = true }
accesskit_winit = { version = "0.16.0", optional = true }

## Enable this when generating docs.
document-features = { version = "0.2", optional = true }
Expand Down
Loading
Loading