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

allow RepaintSignal: ?Sync #1187

Closed
wants to merge 10 commits into from
1 change: 1 addition & 0 deletions eframe/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions egui-winit/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 6 additions & 3 deletions egui-winit/src/epi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,14 +211,17 @@ pub struct EpiIntegration {
}

impl EpiIntegration {
pub fn new(
pub fn new<S>(
integration_name: &'static str,
max_texture_side: usize,
window: &winit::window::Window,
repaint_signal: std::sync::Arc<dyn epi::backend::RepaintSignal>,
repaint_signal: S,
persistence: crate::epi::Persistence,
app: Box<dyn epi::App>,
) -> Self {
) -> Self
where
S: epi::backend::RepaintSignal,
{
let egui_ctx = egui::Context::default();

*egui_ctx.memory() = persistence.load_memory().unwrap_or_default();
Expand Down
15 changes: 8 additions & 7 deletions egui_glium/src/epi_backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@ use crate::*;

struct RequestRepaintEvent;

struct GliumRepaintSignal(
std::sync::Mutex<glutin::event_loop::EventLoopProxy<RequestRepaintEvent>>,
);
#[derive(Clone)]
struct GliumRepaintSignal(glutin::event_loop::EventLoopProxy<RequestRepaintEvent>);

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<dyn epi::backend::RepaintSignal> {
Box::new(self.clone())
}
}

Expand Down Expand Up @@ -40,9 +43,7 @@ pub fn run(app: Box<dyn epi::App>, 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(
Expand Down
13 changes: 8 additions & 5 deletions egui_glow/src/epi_backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,16 @@ use egui_winit::winit;

struct RequestRepaintEvent;

struct GlowRepaintSignal(std::sync::Mutex<winit::event_loop::EventLoopProxy<RequestRepaintEvent>>);
#[derive(Clone)]
struct GlowRepaintSignal(winit::event_loop::EventLoopProxy<RequestRepaintEvent>);

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<dyn epi::backend::RepaintSignal> {
Box::new(self.clone())
}
}

Expand Down Expand Up @@ -55,9 +60,7 @@ pub fn run(app: Box<dyn epi::App>, 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));
Expand Down
1 change: 1 addition & 0 deletions egui_web/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
13 changes: 9 additions & 4 deletions egui_web/src/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<std::sync::atomic::AtomicBool>);
zetanumbers marked this conversation as resolved.
Show resolved Hide resolved

impl Default for NeedRepaint {
fn default() -> Self {
Self(true.into())
Self(std::sync::Arc::new(true.into()))
}
}

Expand All @@ -77,6 +78,10 @@ impl epi::backend::RepaintSignal for NeedRepaint {
fn request_repaint(&self) {
self.0.store(true, SeqCst);
}

fn dyn_clone(&self) -> Box<dyn epi::backend::RepaintSignal> {
Box::new(self.clone())
}
}

// ----------------------------------------------------------------------------
Expand All @@ -87,7 +92,7 @@ pub struct AppRunner {
painter: Box<dyn Painter>,
pub(crate) input: WebInput,
app: Box<dyn epi::App>,
pub(crate) needs_repaint: std::sync::Arc<NeedRepaint>,
pub(crate) needs_repaint: NeedRepaint,
storage: LocalStorage,
last_save_time: f64,
screen_reader: crate::screen_reader::ScreenReader,
Expand All @@ -102,7 +107,7 @@ impl AppRunner {

let prefer_dark_mode = crate::prefer_dark_mode();

let needs_repaint: std::sync::Arc<NeedRepaint> = Default::default();
let needs_repaint = NeedRepaint::default();

let frame = epi::Frame::new(epi::backend::FrameData {
info: epi::IntegrationInfo {
Expand Down
17 changes: 12 additions & 5 deletions epi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,10 @@ pub struct Frame(pub Arc<Mutex<backend::FrameData>>);
impl Frame {
/// Create a `Frame` - called by the integration.
#[doc(hidden)]
pub fn new(frame_data: backend::FrameData) -> Self {
pub fn new<S>(frame_data: backend::FrameData<S>) -> Self
where
S: backend::RepaintSignal,
{
Self(Arc::new(Mutex::new(frame_data)))
}

Expand Down Expand Up @@ -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<dyn RepaintSignal>;
}

/// The data required by [`Frame`] each frame.
pub struct FrameData {
pub struct FrameData<S: ?Sized + RepaintSignal = dyn RepaintSignal> {
/// 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<dyn RepaintSignal>,
/// 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.
Expand Down