mirror of
https://github.com/emilk/egui.git
synced 2026-06-28 07:23:13 -04:00
Merge branch 'master' into wgpu-0.17
This commit is contained in:
@@ -3,9 +3,9 @@ All notable changes to the `eframe` crate.
|
||||
|
||||
NOTE: [`egui-winit`](../egui-winit/CHANGELOG.md), [`egui_glium`](../egui_glium/CHANGELOG.md), [`egui_glow`](../egui_glow/CHANGELOG.md),and [`egui-wgpu`](../egui-wgpu/CHANGELOG.md) have their own changelogs!
|
||||
|
||||
This file is updated upon each release.
|
||||
Changes since the last release can be found by running the `scripts/generate_changelog.py` script.
|
||||
|
||||
## Unreleased
|
||||
* Expose raw window and display handles in `CreationContext` and `Frame`
|
||||
|
||||
## 0.22.0 - 2023-05-23
|
||||
* Fix: `request_repaint_after` works even when called from background thread [#2939](https://github.com/emilk/egui/pull/2939)
|
||||
|
||||
@@ -4,7 +4,7 @@ version = "0.22.0"
|
||||
authors = ["Emil Ernerfeldt <emil.ernerfeldt@gmail.com>"]
|
||||
description = "egui framework - write GUI apps that compiles to web and/or natively"
|
||||
edition = "2021"
|
||||
rust-version = "1.65"
|
||||
rust-version = "1.67"
|
||||
homepage = "https://github.com/emilk/egui/tree/master/crates/eframe"
|
||||
license = "MIT OR Apache-2.0"
|
||||
readme = "README.md"
|
||||
@@ -27,7 +27,14 @@ targets = ["x86_64-unknown-linux-gnu", "wasm32-unknown-unknown"]
|
||||
|
||||
|
||||
[features]
|
||||
default = ["accesskit", "default_fonts", "glow"]
|
||||
default = [
|
||||
"accesskit",
|
||||
"default_fonts",
|
||||
"glow",
|
||||
"wayland",
|
||||
"winit/default",
|
||||
"x11",
|
||||
]
|
||||
|
||||
## Enable platform accessibility API implementations through [AccessKit](https://accesskit.dev/).
|
||||
accesskit = ["egui/accesskit", "egui-winit/accesskit"]
|
||||
@@ -42,6 +49,9 @@ glow = ["dep:glow", "dep:egui_glow", "dep:glutin", "dep:glutin-winit"]
|
||||
## Enables wayland support and fixes clipboard issue.
|
||||
wayland = ["egui-winit/wayland"]
|
||||
|
||||
## Enables compiling for x11.
|
||||
x11 = ["egui-winit/x11"]
|
||||
|
||||
## Enable saving app state to disk.
|
||||
persistence = [
|
||||
"directories-next",
|
||||
@@ -109,7 +119,7 @@ image = { version = "0.24", default-features = false, features = [
|
||||
"png",
|
||||
] } # Needed for app icon
|
||||
raw-window-handle = { version = "0.5.0" }
|
||||
winit = "0.28.1"
|
||||
winit = { version = "0.28.1", default-features = false }
|
||||
|
||||
# optional native:
|
||||
directories-next = { version = "2", optional = true }
|
||||
|
||||
@@ -431,7 +431,7 @@ pub struct NativeOptions {
|
||||
/// will be used instead.
|
||||
///
|
||||
/// ### On Wayland
|
||||
/// On Wauland this sets the Application ID for the window.
|
||||
/// On Wayland this sets the Application ID for the window.
|
||||
///
|
||||
/// The application ID is used in several places of the compositor, e.g. for
|
||||
/// grouping windows of the same application. It is also important for
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
//! To learn how to set up `eframe` for web and native, go to <https://github.com/emilk/eframe_template/> and follow the instructions there!
|
||||
//!
|
||||
//! In short, you implement [`App`] (especially [`App::update`]) and then
|
||||
//! call [`crate::run_native`] from your `main.rs`, and/or call `eframe::start_web` from your `lib.rs`.
|
||||
//! call [`crate::run_native`] from your `main.rs`, and/or use `eframe::WebRunner` from your `lib.rs`.
|
||||
//!
|
||||
//! ## Usage, native:
|
||||
//! ``` no_run
|
||||
@@ -272,6 +272,7 @@ pub fn run_simple_native(
|
||||
struct SimpleApp<U> {
|
||||
update_fun: U,
|
||||
}
|
||||
|
||||
impl<U: FnMut(&egui::Context, &mut Frame)> App for SimpleApp<U> {
|
||||
fn update(&mut self, ctx: &egui::Context, frame: &mut Frame) {
|
||||
(self.update_fun)(ctx, frame);
|
||||
|
||||
@@ -121,9 +121,12 @@ pub fn window_builder<E>(
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "wayland", target_os = "linux"))]
|
||||
if let Some(app_id) = &native_options.app_id {
|
||||
{
|
||||
use winit::platform::wayland::WindowBuilderExtWayland as _;
|
||||
window_builder = window_builder.with_name(app_id, "");
|
||||
match &native_options.app_id {
|
||||
Some(app_id) => window_builder = window_builder.with_name(app_id, ""),
|
||||
None => window_builder = window_builder.with_name(title, ""),
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(min_size) = *min_window_size {
|
||||
@@ -332,8 +335,10 @@ pub struct EpiIntegration {
|
||||
pub egui_ctx: egui::Context,
|
||||
pending_full_output: egui::FullOutput,
|
||||
egui_winit: egui_winit::State,
|
||||
|
||||
/// When set, it is time to close the native window.
|
||||
close: bool,
|
||||
|
||||
can_drag_window: bool,
|
||||
window_state: WindowState,
|
||||
follow_system_theme: bool,
|
||||
@@ -562,24 +567,26 @@ impl EpiIntegration {
|
||||
pub fn maybe_autosave(&mut self, app: &mut dyn epi::App, window: &winit::window::Window) {
|
||||
let now = std::time::Instant::now();
|
||||
if now - self.last_auto_save > app.auto_save_interval() {
|
||||
self.save(app, window);
|
||||
self.save(app, Some(window));
|
||||
self.last_auto_save = now;
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::unused_self)]
|
||||
pub fn save(&mut self, _app: &mut dyn epi::App, _window: &winit::window::Window) {
|
||||
pub fn save(&mut self, _app: &mut dyn epi::App, _window: Option<&winit::window::Window>) {
|
||||
#[cfg(feature = "persistence")]
|
||||
if let Some(storage) = self.frame.storage_mut() {
|
||||
crate::profile_function!();
|
||||
|
||||
if _app.persist_native_window() {
|
||||
crate::profile_scope!("native_window");
|
||||
epi::set_value(
|
||||
storage,
|
||||
STORAGE_WINDOW_KEY,
|
||||
&WindowSettings::from_display(_window),
|
||||
);
|
||||
if let Some(window) = _window {
|
||||
if _app.persist_native_window() {
|
||||
crate::profile_scope!("native_window");
|
||||
epi::set_value(
|
||||
storage,
|
||||
STORAGE_WINDOW_KEY,
|
||||
&WindowSettings::from_display(window),
|
||||
);
|
||||
}
|
||||
}
|
||||
if _app.persist_egui_memory() {
|
||||
crate::profile_scope!("egui_memory");
|
||||
|
||||
@@ -80,14 +80,45 @@ impl crate::Storage for FileStorage {
|
||||
join_handle.join().ok();
|
||||
}
|
||||
|
||||
let join_handle = std::thread::spawn(move || {
|
||||
let file = std::fs::File::create(&file_path).unwrap();
|
||||
let config = Default::default();
|
||||
ron::ser::to_writer_pretty(file, &kv, config).unwrap();
|
||||
log::trace!("Persisted to {:?}", file_path);
|
||||
});
|
||||
match std::thread::Builder::new()
|
||||
.name("eframe_persist".to_owned())
|
||||
.spawn(move || {
|
||||
save_to_disk(&file_path, &kv);
|
||||
}) {
|
||||
Ok(join_handle) => {
|
||||
self.last_save_join_handle = Some(join_handle);
|
||||
}
|
||||
Err(err) => {
|
||||
log::warn!("Failed to spawn thread to save app state: {err}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.last_save_join_handle = Some(join_handle);
|
||||
fn save_to_disk(file_path: &PathBuf, kv: &HashMap<String, String>) {
|
||||
crate::profile_function!();
|
||||
|
||||
if let Some(parent_dir) = file_path.parent() {
|
||||
if !parent_dir.exists() {
|
||||
if let Err(err) = std::fs::create_dir_all(parent_dir) {
|
||||
log::warn!("Failed to create directory {parent_dir:?}: {err}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match std::fs::File::create(file_path) {
|
||||
Ok(file) => {
|
||||
let config = Default::default();
|
||||
|
||||
if let Err(err) = ron::ser::to_writer_pretty(file, &kv, config) {
|
||||
log::warn!("Failed to serialize app state: {err}");
|
||||
} else {
|
||||
log::trace!("Persisted to {:?}", file_path);
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
log::warn!("Failed to create file {file_path:?}: {err}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ use super::epi_integration::{self, EpiIntegration};
|
||||
pub enum UserEvent {
|
||||
RequestRepaint {
|
||||
when: Instant,
|
||||
|
||||
/// What the frame number was when the repaint was _requested_.
|
||||
frame_nr: u64,
|
||||
},
|
||||
@@ -144,11 +145,13 @@ fn run_and_return(
|
||||
// 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
|
||||
winit::event::Event::RedrawEventsCleared if cfg!(windows) => {
|
||||
#[cfg(windows)]
|
||||
winit::event::Event::RedrawEventsCleared => {
|
||||
next_repaint_time = extremely_far_future();
|
||||
winit_app.run_ui_and_paint()
|
||||
}
|
||||
winit::event::Event::RedrawRequested(_) if !cfg!(windows) => {
|
||||
#[cfg(not(windows))]
|
||||
winit::event::Event::RedrawRequested(_) => {
|
||||
next_repaint_time = extremely_far_future();
|
||||
winit_app.run_ui_and_paint()
|
||||
}
|
||||
@@ -705,7 +708,7 @@ mod glow_integration {
|
||||
|
||||
let painter =
|
||||
egui_glow::Painter::new(gl.clone(), "", self.native_options.shader_version)
|
||||
.unwrap_or_else(|error| panic!("some OpenGL error occurred {}\n", error));
|
||||
.unwrap_or_else(|err| panic!("An OpenGL error occurred: {err}\n"));
|
||||
|
||||
let system_theme = system_theme(gl_window.window(), &self.native_options);
|
||||
let mut integration = epi_integration::EpiIntegration::new(
|
||||
@@ -799,7 +802,7 @@ mod glow_integration {
|
||||
if let Some(mut running) = self.running.take() {
|
||||
running
|
||||
.integration
|
||||
.save(running.app.as_mut(), running.gl_window.window());
|
||||
.save(running.app.as_mut(), running.gl_window.window.as_ref());
|
||||
running.app.on_exit(Some(&running.gl));
|
||||
running.painter.destroy();
|
||||
}
|
||||
@@ -1258,9 +1261,9 @@ mod wgpu_integration {
|
||||
|
||||
fn save_and_destroy(&mut self) {
|
||||
if let Some(mut running) = self.running.take() {
|
||||
if let Some(window) = &self.window {
|
||||
running.integration.save(running.app.as_mut(), window);
|
||||
}
|
||||
running
|
||||
.integration
|
||||
.save(running.app.as_mut(), self.window.as_ref());
|
||||
|
||||
#[cfg(feature = "glow")]
|
||||
running.app.on_exit(None);
|
||||
|
||||
@@ -104,7 +104,7 @@ pub fn canvas_element(canvas_id: &str) -> Option<web_sys::HtmlCanvasElement> {
|
||||
|
||||
pub fn canvas_element_or_die(canvas_id: &str) -> web_sys::HtmlCanvasElement {
|
||||
canvas_element(canvas_id)
|
||||
.unwrap_or_else(|| panic!("Failed to find canvas with id {:?}", canvas_id))
|
||||
.unwrap_or_else(|| panic!("Failed to find canvas with id {canvas_id:?}"))
|
||||
}
|
||||
|
||||
fn canvas_origin(canvas_id: &str) -> egui::Pos2 {
|
||||
|
||||
@@ -104,8 +104,7 @@ pub fn install_text_agent(runner_ref: &WebRunner) -> Result<(), JsValue> {
|
||||
runner_ref.add_event_listener(&input, "focusout", move |_event: web_sys::MouseEvent, _| {
|
||||
// Delay 10 ms, and focus again.
|
||||
let func = js_sys::Function::new_no_args(&format!(
|
||||
"document.getElementById('{}').focus()",
|
||||
AGENT_ID
|
||||
"document.getElementById('{AGENT_ID}').focus()"
|
||||
));
|
||||
window
|
||||
.set_timeout_with_callback_and_timeout_and_arguments_0(&func, 10)
|
||||
@@ -221,8 +220,8 @@ pub fn move_text_cursor(cursor: Option<egui::Pos2>, canvas_id: &str) -> Option<(
|
||||
let x = (x - canvas.offset_width() as f32 / 2.0)
|
||||
.min(canvas.client_width() as f32 - bounding_rect.width() as f32);
|
||||
style.set_property("position", "absolute").ok()?;
|
||||
style.set_property("top", &format!("{}px", y)).ok()?;
|
||||
style.set_property("left", &format!("{}px", x)).ok()
|
||||
style.set_property("top", &format!("{y}px")).ok()?;
|
||||
style.set_property("left", &format!("{x}px")).ok()
|
||||
})
|
||||
} else {
|
||||
style.set_property("position", "absolute").ok()?;
|
||||
|
||||
@@ -27,7 +27,7 @@ impl WebPainterGlow {
|
||||
let gl = std::sync::Arc::new(gl);
|
||||
|
||||
let painter = egui_glow::Painter::new(gl, shader_prefix, None)
|
||||
.map_err(|error| format!("Error starting glow painter: {}", error))?;
|
||||
.map_err(|err| format!("Error starting glow painter: {err}"))?;
|
||||
|
||||
Ok(Self {
|
||||
canvas,
|
||||
|
||||
@@ -87,8 +87,7 @@ impl WebPainterWgpu {
|
||||
} else {
|
||||
// Workaround for https://github.com/gfx-rs/wgpu/issues/3710:
|
||||
// Don't use `create_surface_from_canvas`, but `create_surface` instead!
|
||||
let raw_window =
|
||||
EguiWebWindow(egui::util::hash(&format!("egui on wgpu {canvas_id}")) as u32);
|
||||
let raw_window = EguiWebWindow(egui::util::hash(("egui on wgpu", canvas_id)) as u32);
|
||||
canvas.set_attribute("data-raw-handle", &raw_window.0.to_string());
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
|
||||
Reference in New Issue
Block a user