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

egui_glium: run app code outside event loop to fix file dialogs #631

Merged
merged 1 commit into from
Aug 20, 2021
Merged
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
1 change: 1 addition & 0 deletions eframe/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ All notable changes to the `eframe` crate.

## Unreleased
* Improve http fetch API.
* `run_native` now returns when the app is closed.


## 0.13.1 - 2021-06-24
Expand Down
2 changes: 1 addition & 1 deletion eframe/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,6 @@ pub fn start_web(canvas_id: &str, app: Box<dyn epi::App>) -> Result<(), wasm_bin

/// Call from `fn main` like this: `eframe::run_native(Box::new(MyEguiApp::default()))`
#[cfg(not(target_arch = "wasm32"))]
pub fn run_native(app: Box<dyn epi::App>, native_options: epi::NativeOptions) -> ! {
pub fn run_native(app: Box<dyn epi::App>, native_options: epi::NativeOptions) {
egui_glium::run(app, native_options)
}
1 change: 1 addition & 0 deletions egui_glium/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ All notable changes to the `egui_glium` integration will be noted in this file.


## Unreleased
* Fix native file dialogs hanging (eg. when using [`nfd2`](https://github.com/EmbarkStudios/nfd2)
* [Fix minimize on Windows](https://github.com/emilk/egui/issues/518)
* Change `drag_and_drop_support` to `false` by default (Windows only). See <https://github.com/emilk/egui/issues/598>.
* Don't restore window position on Windows, because the position would sometimes be invalid.
Expand Down
133 changes: 80 additions & 53 deletions egui_glium/src/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,15 +172,15 @@ fn load_icon(icon_data: epi::IconData) -> Option<glutin::window::Icon> {
// ----------------------------------------------------------------------------

/// Run an egui app
pub fn run(mut app: Box<dyn epi::App>, native_options: epi::NativeOptions) -> ! {
pub fn run(mut app: Box<dyn epi::App>, native_options: epi::NativeOptions) {
#[allow(unused_mut)]
let mut storage = create_storage(app.name());

#[cfg(feature = "http")]
let http = std::sync::Arc::new(crate::http::GliumHttp {});

let window_settings = deserialize_window_settings(&storage);
let event_loop = glutin::event_loop::EventLoop::with_user_event();
let mut event_loop = glutin::event_loop::EventLoop::with_user_event();
let icon = native_options.icon_data.clone().and_then(load_icon);
let display = create_display(&*app, &native_options, window_settings, icon, &event_loop);

Expand Down Expand Up @@ -208,8 +208,6 @@ pub fn run(mut app: Box<dyn epi::App>, native_options: epi::NativeOptions) -> !

let mut previous_frame_time = None;

let mut is_focused = true;

#[cfg(feature = "persistence")]
let mut last_auto_save = Instant::now();

Expand Down Expand Up @@ -241,8 +239,67 @@ pub fn run(mut app: Box<dyn epi::App>, native_options: epi::NativeOptions) -> !
// eprintln!("Warmed up in {} ms", warm_up_start.elapsed().as_millis())
}

event_loop.run(move |event, _, control_flow| {
let mut redraw = || {
let mut is_focused = true;
let mut running = true;
let mut repaint_asap = true;

while running {
use glium::glutin::platform::run_return::EventLoopExtRunReturn as _;
event_loop.run_return(|event, _, control_flow| {
use glium::glutin::event_loop::ControlFlow;

*control_flow = ControlFlow::Wait;

match event {
// Platform-dependent event handlers to workaround a winit bug
// See: https://github.com/rust-windowing/winit/issues/987
// See: https://github.com/rust-windowing/winit/issues/1619
glutin::event::Event::RedrawEventsCleared if cfg!(windows) => {
*control_flow = ControlFlow::Exit; // Time to redraw
}
glutin::event::Event::RedrawRequested(_) if !cfg!(windows) => {
*control_flow = ControlFlow::Exit; // Time to redraw
}
glutin::event::Event::MainEventsCleared => {
if repaint_asap {
*control_flow = ControlFlow::Exit; // Time to redraw
} else {
// Winit uses up all the CPU of one core when returning ControlFlow::Wait.
// Sleeping here helps, but still uses 1-3% of CPU :(
if is_focused {
std::thread::sleep(std::time::Duration::from_millis(10));
} else {
std::thread::sleep(std::time::Duration::from_millis(100));
}
}
}
glutin::event::Event::WindowEvent { event, .. } => {
if egui.is_quit_event(&event) {
*control_flow = ControlFlow::Exit;
running = false;
}

if let glutin::event::WindowEvent::Focused(new_focused) = event {
is_focused = new_focused;
}

egui.on_event(&event);

// TODO: ask egui if the events warrants a repaint instead of repainting on each event.
display.gl_window().window().request_redraw();
}
glutin::event::Event::UserEvent(RequestRepaintEvent) => {
display.gl_window().window().request_redraw();
*control_flow = ControlFlow::Exit; // Time to redraw
}

_ => (),
}
});

repaint_asap = false;

if running {
if !is_focused {
// On Mac, a minimized Window uses up all CPU: https://github.com/emilk/egui/issues/325
// We can't know if we are minimized: https://github.com/rust-windowing/winit/issues/208
Expand Down Expand Up @@ -299,13 +356,11 @@ pub fn run(mut app: Box<dyn epi::App>, native_options: epi::NativeOptions) -> !
);
}

*control_flow = if quit {
glutin::event_loop::ControlFlow::Exit
if quit {
running = false;
} else if needs_repaint {
display.gl_window().window().request_redraw();
glutin::event_loop::ControlFlow::Poll
} else {
glutin::event_loop::ControlFlow::Wait
repaint_asap = true;
};
}

Expand All @@ -324,48 +379,20 @@ pub fn run(mut app: Box<dyn epi::App>, native_options: epi::NativeOptions) -> !
last_auto_save = now;
}
}
};

match event {
// Platform-dependent event handlers to workaround a winit bug
// See: https://github.com/rust-windowing/winit/issues/987
// See: https://github.com/rust-windowing/winit/issues/1619
glutin::event::Event::RedrawEventsCleared if cfg!(windows) => redraw(),
glutin::event::Event::RedrawRequested(_) if !cfg!(windows) => redraw(),

glutin::event::Event::WindowEvent { event, .. } => {
if egui.is_quit_event(&event) {
*control_flow = glium::glutin::event_loop::ControlFlow::Exit;
}

if let glutin::event::WindowEvent::Focused(new_focused) = event {
is_focused = new_focused;
}

egui.on_event(&event);

display.gl_window().window().request_redraw(); // TODO: ask egui if the events warrants a repaint instead
}
glutin::event::Event::LoopDestroyed => {
app.on_exit();
#[cfg(feature = "persistence")]
if let Some(storage) = &mut storage {
epi::set_value(
storage.as_mut(),
WINDOW_KEY,
&WindowSettings::from_display(&display),
);
epi::set_value(storage.as_mut(), EGUI_MEMORY_KEY, &*egui.ctx().memory());
app.save(storage.as_mut());
storage.flush();
}
}
}
}

glutin::event::Event::UserEvent(RequestRepaintEvent) => {
display.gl_window().window().request_redraw();
}
app.on_exit();

_ => (),
}
});
#[cfg(feature = "persistence")]
if let Some(storage) = &mut storage {
epi::set_value(
storage.as_mut(),
WINDOW_KEY,
&WindowSettings::from_display(&display),
);
epi::set_value(storage.as_mut(), EGUI_MEMORY_KEY, &*egui.ctx().memory());
app.save(storage.as_mut());
storage.flush();
}
}