diff --git a/eframe/CHANGELOG.md b/eframe/CHANGELOG.md index ebe4c607f75..442ec2d4fca 100644 --- a/eframe/CHANGELOG.md +++ b/eframe/CHANGELOG.md @@ -13,6 +13,7 @@ NOTE: [`egui_web`](../egui_web/CHANGELOG.md), [`egui-winit`](../egui-winit/CHANG * Added `App::on_exit_event` ([#1038](https://github.com/emilk/egui/pull/1038)) * Shift-scroll will now result in horizontal scrolling on all platforms ([#1136](https://github.com/emilk/egui/pull/1136)). * Log using the `tracing` crate. Log to stdout by adding `tracing_subscriber::fmt::init();` to your `main` ([#1192](https://github.com/emilk/egui/pull/1192)). +* `backend::RepaintSignal` no longer requires `Sync`, but now requires new method `dyn_clone` ([#1187](https://github.com/emilk/egui/pull/1187)). ## 0.16.0 - 2021-12-29 diff --git a/egui-winit/CHANGELOG.md b/egui-winit/CHANGELOG.md index 80de1eaa77b..3b5bb9dd753 100644 --- a/egui-winit/CHANGELOG.md +++ b/egui-winit/CHANGELOG.md @@ -10,6 +10,7 @@ All notable changes to the `egui-winit` integration will be noted in this file. * Shift-scroll will now result in horizontal scrolling on all platforms ([#1136](https://github.com/emilk/egui/pull/1136)). * Require knowledge about max texture side (e.g. `GL_MAX_TEXTURE_SIZE`)) ([#1154](https://github.com/emilk/egui/pull/1154)). * Fixed `enable_drag` for Windows. Now called only once just after left click ([#1108](https://github.com/emilk/egui/pull/1108)). +* Updated `EpiIntegration::new` signature ([#1187](https://github.com/emilk/egui/pull/1187)). ## 0.16.0 - 2021-12-29 diff --git a/egui-winit/src/epi.rs b/egui-winit/src/epi.rs index b4762be5d6a..47c5353f855 100644 --- a/egui-winit/src/epi.rs +++ b/egui-winit/src/epi.rs @@ -211,14 +211,17 @@ pub struct EpiIntegration { } impl EpiIntegration { - pub fn new( + pub fn new( integration_name: &'static str, max_texture_side: usize, window: &winit::window::Window, - repaint_signal: std::sync::Arc, + repaint_signal: S, persistence: crate::epi::Persistence, app: Box, - ) -> Self { + ) -> Self + where + S: epi::backend::RepaintSignal, + { let egui_ctx = egui::Context::default(); *egui_ctx.memory() = persistence.load_memory().unwrap_or_default(); diff --git a/egui_glium/src/epi_backend.rs b/egui_glium/src/epi_backend.rs index b22a507592e..c7d7952f9d9 100644 --- a/egui_glium/src/epi_backend.rs +++ b/egui_glium/src/epi_backend.rs @@ -4,13 +4,16 @@ use crate::*; struct RequestRepaintEvent; -struct GliumRepaintSignal( - std::sync::Mutex>, -); +#[derive(Clone)] +struct GliumRepaintSignal(glutin::event_loop::EventLoopProxy); impl epi::backend::RepaintSignal for GliumRepaintSignal { fn request_repaint(&self) { - self.0.lock().unwrap().send_event(RequestRepaintEvent).ok(); + self.0.send_event(RequestRepaintEvent).ok(); + } + + fn dyn_clone(&self) -> Box { + Box::new(self.clone()) } } @@ -40,9 +43,7 @@ pub fn run(app: Box, native_options: &epi::NativeOptions) -> ! { let event_loop = glutin::event_loop::EventLoop::with_user_event(); let display = create_display(window_builder, &event_loop); - let repaint_signal = std::sync::Arc::new(GliumRepaintSignal(std::sync::Mutex::new( - event_loop.create_proxy(), - ))); + let repaint_signal = GliumRepaintSignal(event_loop.create_proxy()); let mut painter = crate::Painter::new(&display); let mut integration = egui_winit::epi::EpiIntegration::new( diff --git a/egui_glow/src/epi_backend.rs b/egui_glow/src/epi_backend.rs index fef06d10684..86a3b1a195b 100644 --- a/egui_glow/src/epi_backend.rs +++ b/egui_glow/src/epi_backend.rs @@ -3,11 +3,16 @@ use egui_winit::winit; struct RequestRepaintEvent; -struct GlowRepaintSignal(std::sync::Mutex>); +#[derive(Clone)] +struct GlowRepaintSignal(winit::event_loop::EventLoopProxy); impl epi::backend::RepaintSignal for GlowRepaintSignal { fn request_repaint(&self) { - self.0.lock().unwrap().send_event(RequestRepaintEvent).ok(); + self.0.send_event(RequestRepaintEvent).ok(); + } + + fn dyn_clone(&self) -> Box { + Box::new(self.clone()) } } @@ -55,9 +60,7 @@ pub fn run(app: Box, native_options: &epi::NativeOptions) -> ! { let event_loop = winit::event_loop::EventLoop::with_user_event(); let (gl_window, gl) = create_display(window_builder, &event_loop); - let repaint_signal = std::sync::Arc::new(GlowRepaintSignal(std::sync::Mutex::new( - event_loop.create_proxy(), - ))); + let repaint_signal = GlowRepaintSignal(event_loop.create_proxy()); let mut painter = crate::Painter::new(&gl, None, "") .unwrap_or_else(|error| panic!("some OpenGL error occurred {}\n", error)); diff --git a/egui_web/CHANGELOG.md b/egui_web/CHANGELOG.md index f76bdb30905..17990ed6283 100644 --- a/egui_web/CHANGELOG.md +++ b/egui_web/CHANGELOG.md @@ -10,6 +10,7 @@ All notable changes to the `egui_web` integration will be noted in this file. * Shift-scroll will now result in horizontal scrolling ([#1136](https://github.com/emilk/egui/pull/1136)). * Updated `epi::IntegrationInfo::web_location_hash` on `hashchange` event ([#1140](https://github.com/emilk/egui/pull/1140)). * Panics will now be logged using `console.error`. +* Updated `NeedRepaint` implementation ([#1187](https://github.com/emilk/egui/pull/1187)). ## 0.16.0 - 2021-12-29 diff --git a/egui_web/src/backend.rs b/egui_web/src/backend.rs index fe4a2c28828..d61efecf7a3 100644 --- a/egui_web/src/backend.rs +++ b/egui_web/src/backend.rs @@ -55,11 +55,12 @@ impl WebInput { use std::sync::atomic::Ordering::SeqCst; -pub struct NeedRepaint(std::sync::atomic::AtomicBool); +#[derive(Clone)] +pub struct NeedRepaint(std::sync::Arc); impl Default for NeedRepaint { fn default() -> Self { - Self(true.into()) + Self(std::sync::Arc::new(true.into())) } } @@ -77,6 +78,10 @@ impl epi::backend::RepaintSignal for NeedRepaint { fn request_repaint(&self) { self.0.store(true, SeqCst); } + + fn dyn_clone(&self) -> Box { + Box::new(self.clone()) + } } // ---------------------------------------------------------------------------- @@ -87,7 +92,7 @@ pub struct AppRunner { painter: Box, pub(crate) input: WebInput, app: Box, - pub(crate) needs_repaint: std::sync::Arc, + pub(crate) needs_repaint: NeedRepaint, storage: LocalStorage, last_save_time: f64, screen_reader: crate::screen_reader::ScreenReader, @@ -102,7 +107,7 @@ impl AppRunner { let prefer_dark_mode = crate::prefer_dark_mode(); - let needs_repaint: std::sync::Arc = Default::default(); + let needs_repaint = NeedRepaint::default(); let frame = epi::Frame::new(epi::backend::FrameData { info: epi::IntegrationInfo { diff --git a/epi/src/lib.rs b/epi/src/lib.rs index 1183cc06d77..e0640296c50 100644 --- a/epi/src/lib.rs +++ b/epi/src/lib.rs @@ -290,7 +290,10 @@ pub struct Frame(pub Arc>); impl Frame { /// Create a `Frame` - called by the integration. #[doc(hidden)] - pub fn new(frame_data: backend::FrameData) -> Self { + pub fn new(frame_data: backend::FrameData) -> Self + where + S: backend::RepaintSignal, + { Self(Arc::new(Mutex::new(frame_data))) } @@ -448,23 +451,27 @@ pub mod backend { use super::*; /// How to signal the [`egui`] integration that a repaint is required. - pub trait RepaintSignal: Send + Sync { + pub trait RepaintSignal: Send + std::any::Any { /// This signals the [`egui`] integration that a repaint is required. /// /// Call this e.g. when a background process finishes in an async context and/or background thread. fn request_repaint(&self); + + /// Method to dynamically clone self. Calling [`RepaintSignal::request_repaint`] on a clone should + /// be equivalent to a call on the original value. You may use [`Box::downcast`] to get a concrete type. + fn dyn_clone(&self) -> Box; } /// The data required by [`Frame`] each frame. - pub struct FrameData { + pub struct FrameData { /// Information about the integration. pub info: IntegrationInfo, /// Where the app can issue commands back to the integration. pub output: AppOutput, - /// If you need to request a repaint from another thread, clone this and send it to that other thread. - pub repaint_signal: std::sync::Arc, + /// If you need to request a repaint from another thread, [`RepaintSignal::dyn_clone`] this and send it to that other thread. + pub repaint_signal: S, } /// Action that can be taken by the user app.