1
0
mirror of https://github.com/emilk/egui.git synced 2026-06-26 14:49:06 -04:00

Use explicit Arc::clone to clarify when clones are cheap (#7784)

This commit is contained in:
Emil Ernerfeldt
2025-12-17 17:19:18 +01:00
committed by GitHub
parent 6157a35985
commit 986c2c0ffb
40 changed files with 80 additions and 71 deletions

View File

@@ -184,6 +184,7 @@ branches_sharing_code = "warn"
char_lit_as_u8 = "warn"
checked_conversions = "warn"
clear_with_drain = "warn"
clone_on_ref_ptr = "warn"
cloned_instead_of_copied = "warn"
dbg_macro = "warn"
debug_assert_with_mut_call = "warn"

View File

@@ -216,7 +216,7 @@ impl<'app> GlowWinitApp<'app> {
storage.as_deref(),
&mut self.native_options,
)?;
let gl = painter.gl().clone();
let gl = Arc::clone(painter.gl());
let max_texture_side = painter.max_texture_side();
glutin.max_texture_side = Some(max_texture_side);
@@ -234,9 +234,9 @@ impl<'app> GlowWinitApp<'app> {
&self.app_name,
&self.native_options,
storage,
Some(gl.clone()),
Some(Arc::clone(&gl)),
Some(Box::new({
let painter = painter.clone();
let painter = Rc::clone(&painter);
move |native| painter.borrow_mut().register_native_texture(native)
})),
#[cfg(feature = "wgpu_no_default_features")]
@@ -244,7 +244,7 @@ impl<'app> GlowWinitApp<'app> {
);
{
let event_loop_proxy = self.repaint_proxy.clone();
let event_loop_proxy = Arc::clone(&self.repaint_proxy);
integration
.egui_ctx
.set_request_repaint_callback(move |info| {

View File

@@ -219,7 +219,7 @@ impl<'app> WgpuWinitApp<'app> {
{
profiling::scope!("set_window");
pollster::block_on(painter.set_window(ViewportId::ROOT, Some(window.clone())))?;
pollster::block_on(painter.set_window(ViewportId::ROOT, Some(Arc::clone(&window))))?;
}
let wgpu_render_state = painter.render_state();
@@ -238,7 +238,7 @@ impl<'app> WgpuWinitApp<'app> {
);
{
let event_loop_proxy = self.repaint_proxy.clone();
let event_loop_proxy = Arc::clone(&self.repaint_proxy);
egui_ctx.set_request_repaint_callback(move |info| {
log::trace!("request_repaint_callback: {info:?}");
@@ -610,7 +610,7 @@ impl WgpuWinitRunning<'_> {
{
profiling::scope!("set_window");
pollster::block_on(painter.set_window(viewport_id, Some(window.clone())))?;
pollster::block_on(painter.set_window(viewport_id, Some(Arc::clone(window))))?;
}
let Some(egui_winit) = egui_winit.as_mut() else {
@@ -919,7 +919,7 @@ impl Viewport {
let window = Arc::new(window);
if let Err(err) =
pollster::block_on(painter.set_window(viewport_id, Some(window.clone())))
pollster::block_on(painter.set_window(viewport_id, Some(Arc::clone(&window))))
{
log::error!("on set_window: viewport_id {viewport_id:?} {err}");
}
@@ -1051,7 +1051,8 @@ fn render_immediate_viewport(
{
profiling::scope!("set_window");
if let Err(err) = pollster::block_on(painter.set_window(ids.this, Some(window.clone()))) {
if let Err(err) = pollster::block_on(painter.set_window(ids.this, Some(Arc::clone(window))))
{
log::error!(
"when rendering viewport_id={:?}, set_window Error {err}",
ids.this

View File

@@ -1,3 +1,5 @@
use std::sync::Arc;
use egui::{TexturesDelta, UserData, ViewportCommand};
use crate::{App, epi, web::web_painter::WebPainter};
@@ -12,7 +14,7 @@ pub struct AppRunner {
painter: Box<dyn WebPainter>,
pub(crate) input: super::WebInput,
app: Box<dyn epi::App>,
pub(crate) needs_repaint: std::sync::Arc<NeedRepaint>,
pub(crate) needs_repaint: Arc<NeedRepaint>,
last_save_time: f64,
pub(crate) text_agent: TextAgent,
@@ -63,7 +65,7 @@ impl AppRunner {
canvas,
&web_options,
)?;
gl = Some(painter.gl().clone());
gl = Some(Arc::clone(painter.gl()));
Box::new(painter) as Box<dyn WebPainter>
}
@@ -138,10 +140,9 @@ impl AppRunner {
wgpu_render_state,
};
let needs_repaint: std::sync::Arc<NeedRepaint> =
std::sync::Arc::new(NeedRepaint::new(web_options.max_fps));
let needs_repaint: Arc<NeedRepaint> = Arc::new(NeedRepaint::new(web_options.max_fps));
{
let needs_repaint = needs_repaint.clone();
let needs_repaint = Arc::clone(&needs_repaint);
egui_ctx.set_request_repaint_callback(move |info| {
needs_repaint.repaint_after(info.delay.as_secs_f64());
});

View File

@@ -91,7 +91,7 @@ impl WebPainter for WebPainterGlow {
for data in data {
events.push(Event::Screenshot {
viewport_id: ViewportId::default(),
image: image.clone(),
image: Arc::clone(&image),
user_data: data,
});
}

View File

@@ -105,7 +105,7 @@ impl WebPainterWgpu {
surface_configuration,
depth_stencil_format,
depth_texture_view: None,
on_surface_error: options.wgpu_options.on_surface_error.clone(),
on_surface_error: Arc::clone(&options.wgpu_options.on_surface_error) as _,
screen_capture_state: None,
capture_tx,
capture_rx,
@@ -336,7 +336,7 @@ impl WebPainter for WebPainterWgpu {
events.push(Event::Screenshot {
viewport_id,
user_data: data,
image: screenshot.clone(),
image: Arc::clone(&screenshot),
});
}
}

View File

@@ -188,7 +188,7 @@ impl CaptureState {
) {
#[allow(clippy::arc_with_non_send_sync, clippy::allow_attributes)] // For wasm
let buffer = Arc::new(buffer);
let buffer_clone = buffer.clone();
let buffer_clone = Arc::clone(&buffer);
let buffer_slice = buffer_clone.slice(..);
let format = self.texture.format();
let tex_extent = self.texture.size();

View File

@@ -134,7 +134,7 @@ impl Clone for WgpuSetupCreateNew {
instance_descriptor: self.instance_descriptor.clone(),
power_preference: self.power_preference,
native_adapter_selector: self.native_adapter_selector.clone(),
device_descriptor: self.device_descriptor.clone(),
device_descriptor: Arc::clone(&self.device_descriptor),
}
}
}

View File

@@ -629,7 +629,7 @@ impl Painter {
events.push(Event::Screenshot {
viewport_id,
user_data: data,
image: screenshot.clone(),
image: Arc::clone(&screenshot),
});
}
}

View File

@@ -1274,7 +1274,7 @@ impl TitleBar {
let text_pos = text_pos - self.title_galley.rect.min.to_vec2();
ui.painter().galley(
text_pos,
self.title_galley.clone(),
Arc::clone(&self.title_galley),
ui.visuals().text_color(),
);

View File

@@ -1959,7 +1959,7 @@ impl Context {
pub fn add_plugin(&self, plugin: impl plugin::Plugin + 'static) {
let handle = plugin::PluginHandle::new(plugin);
let added = self.write(|ctx| ctx.plugins.add(handle.clone()));
let added = self.write(|ctx| ctx.plugins.add(Arc::clone(&handle)));
if added {
handle.lock().dyn_plugin_mut().setup(self);
@@ -2085,13 +2085,13 @@ impl Context {
/// The currently active [`Style`] used by all subsequent popups, menus, etc.
pub fn global_style(&self) -> Arc<Style> {
self.options(|opt| opt.style().clone())
self.options(|opt| Arc::clone(opt.style()))
}
/// The currently active [`Style`] used by all subsequent popups, menus, etc.
#[deprecated = "Renamed to `global_style` to avoid confusion with `ui.style()`"]
pub fn style(&self) -> Arc<Style> {
self.options(|opt| opt.style().clone())
self.options(|opt| Arc::clone(opt.style()))
}
/// Mutate the currently active [`Style`] used by all subsequent popups, menus, etc.
@@ -2165,8 +2165,8 @@ impl Context {
/// The [`Style`] used by all subsequent popups, menus, etc.
pub fn style_of(&self, theme: Theme) -> Arc<Style> {
self.options(|opt| match theme {
Theme::Dark => opt.dark_style.clone(),
Theme::Light => opt.light_style.clone(),
Theme::Dark => Arc::clone(&opt.dark_style),
Theme::Light => Arc::clone(&opt.light_style),
})
}
@@ -2360,7 +2360,7 @@ impl Context {
///
/// You can show stats about the allocated textures using [`Self::texture_ui`].
pub fn tex_manager(&self) -> Arc<RwLock<epaint::textures::TextureManager>> {
self.read(|ctx| ctx.tex_manager.0.clone())
self.read(|ctx| Arc::clone(&ctx.tex_manager.0))
}
// ---------------------------------------------------------------------
@@ -3899,7 +3899,7 @@ impl Context {
/// The loaders of bytes, images, and textures.
pub fn loaders(&self) -> Arc<Loaders> {
self.read(|this| this.loaders.clone())
self.read(|this| Arc::clone(&this.loaders))
}
/// Returns `true` if any image is currently being loaded.

View File

@@ -97,11 +97,7 @@ impl DragAndDrop {
where
Payload: Any + Send + Sync,
{
ctx.plugin::<Self>()
.lock()
.payload
.as_ref()?
.clone()
Arc::clone(ctx.plugin::<Self>().lock().payload.as_ref()?)
.downcast()
.ok()
}

View File

@@ -1,3 +1,5 @@
use std::sync::Arc;
use emath::GuiRounding as _;
use crate::{
@@ -102,7 +104,7 @@ impl GridLayout {
Self {
ctx: ui.ctx().clone(),
style: ui.style().clone(),
style: Arc::clone(ui.style()),
id,
is_first_frame,
prev_state,

View File

@@ -609,7 +609,7 @@ impl Default for Loaders {
fn default() -> Self {
let include = Arc::new(DefaultBytesLoader::default());
Self {
bytes: Mutex::new(vec![include.clone()]),
bytes: Mutex::new(vec![Arc::clone(&include) as _]),
image: Mutex::new(Vec::new()),
// By default we only include `DefaultTextureLoader`.
texture: Mutex::new(vec![Arc::new(DefaultTextureLoader::default())]),

View File

@@ -198,7 +198,7 @@ fn menu_popup<'c, R>(
Frame::menu(ui.style())
.show(ui, |ui| {
ui.set_menu_state(Some(menu_state_arc.clone()));
ui.set_menu_state(Some(Arc::clone(menu_state_arc)));
ui.with_layout(Layout::top_down_justified(Align::LEFT), add_contents)
.inner
})

View File

@@ -202,7 +202,7 @@ impl Plugins {
return false;
}
self.plugins.insert(type_id, handle.clone());
self.plugins.insert(type_id, Arc::clone(&handle));
self.plugins_ordered.0.push(handle);
true

View File

@@ -275,7 +275,7 @@ impl Ui {
painter.set_invisible();
}
let sizing_pass = self.sizing_pass || sizing_pass;
let style = style.unwrap_or_else(|| self.style.clone());
let style = style.unwrap_or_else(|| Arc::clone(&self.style));
let sense = sense.unwrap_or_else(Sense::hover);
if sizing_pass {
@@ -305,7 +305,7 @@ impl Ui {
id: unique_id,
layout_direction: layout.main_dir,
info: ui_stack_info,
parent: Some(self.stack.clone()),
parent: Some(Arc::clone(&self.stack)),
min_rect: placer.min_rect(),
max_rect: placer.max_rect(),
};

View File

@@ -787,7 +787,7 @@ impl ViewportBuilder {
};
if is_new {
commands.push(ViewportCommand::Icon(Some(new_icon.clone())));
commands.push(ViewportCommand::Icon(Some(Arc::clone(&new_icon))));
self.icon = Some(new_icon);
}
}

View File

@@ -709,7 +709,7 @@ impl WidgetText {
default_valign,
)),
Self::LayoutJob(job) => job,
Self::Galley(galley) => galley.job.clone(),
Self::Galley(galley) => Arc::clone(&galley.job),
}
}

View File

@@ -759,7 +759,7 @@ impl TextEdit<'_> {
ui.skip_ahead_auto_ids(1);
}
painter.galley(galley_pos, galley.clone(), text_color);
painter.galley(galley_pos, Arc::clone(&galley), text_color);
if has_focus && let Some(cursor_range) = state.cursor.range(&galley) {
let primary_cursor_rect = cursor_rect(&galley, &cursor_range.primary, row_height)

View File

@@ -1,3 +1,5 @@
use std::sync::Arc;
use super::{Demo, View};
use egui::{
@@ -518,7 +520,7 @@ fn ui_stack_demo(ui: &mut Ui) {
with various information.\n\nThis is how the stack looks like here:",
);
});
let stack = ui.stack().clone();
let stack = Arc::clone(ui.stack());
egui::Frame::new()
.inner_margin(ui.spacing().menu_margin)
.stroke(ui.visuals().widgets.noninteractive.bg_stroke)

View File

@@ -52,7 +52,7 @@ impl crate::View for Screenshot {
.iter()
.filter_map(|e| {
if let egui::Event::Screenshot { image, .. } = e {
Some(image.clone())
Some(Arc::clone(image))
} else {
None
}
@@ -62,7 +62,7 @@ impl crate::View for Screenshot {
if let Some(image) = image {
self.image = Some((
image.clone(),
Arc::clone(&image),
ui.ctx()
.load_texture("screenshot_demo", image, Default::default()),
));

View File

@@ -1,3 +1,5 @@
use std::sync::Arc;
use egui::{
Color32, Pos2, Rect, Sense, StrokeKind, Vec2,
emath::{GuiRounding as _, TSTransform},
@@ -229,8 +231,8 @@ impl crate::View for TessellationTest {
TSTransform::from_translation(canvas.center().to_vec2())
* TSTransform::from_scaling(magnification_pixel_size),
);
let mesh = std::sync::Arc::new(mesh);
painter.add(epaint::Shape::mesh(mesh.clone()));
let mesh = Arc::new(mesh);
painter.add(epaint::Shape::mesh(Arc::clone(&mesh)));
if self.paint_edges {
let stroke = epaint::Stroke::new(0.5, Color32::MAGENTA);

View File

@@ -75,7 +75,7 @@ impl BytesLoader for FileLoader {
.name(format!("egui_extras::FileLoader::load({uri:?})"))
.spawn({
let ctx = ctx.clone();
let cache = self.cache.clone();
let cache = Arc::clone(&self.cache);
let uri = uri.to_owned();
move || {
let result = match std::fs::read(&path) {

View File

@@ -53,7 +53,7 @@ impl AnimatedImage {
/// Gets image at index
pub fn get_image(&self, index: usize) -> Arc<ColorImage> {
self.frames[index % self.frames.len()].clone()
Arc::clone(&self.frames[index % self.frames.len()])
}
}
type Entry = Result<Arc<AnimatedImage>, String>;

View File

@@ -84,7 +84,7 @@ impl BytesLoader for EhttpLoader {
ehttp::fetch(ehttp::Request::get(uri.clone()), {
let ctx = ctx.clone();
let cache = self.cache.clone();
let cache = Arc::clone(&self.cache);
move |response| {
let result = match response {
Ok(response) => File::from_response(&uri, response),

View File

@@ -94,7 +94,7 @@ impl ImageLoader for ImageCrateLoader {
.name(format!("egui_extras::ImageLoader::load({uri:?})"))
.spawn({
let ctx = ctx.clone();
let cache = cache.clone();
let cache = Arc::clone(cache);
let uri = uri.clone();
let bytes = bytes.clone();

View File

@@ -75,7 +75,7 @@ impl WebP {
fn get_image(&self, frame_index: usize) -> Arc<ColorImage> {
match self {
Self::Static(image) => image.clone(),
Self::Static(image) => Arc::clone(image),
Self::Animated(animation) => animation.get_image_by_index(frame_index),
}
}
@@ -108,7 +108,7 @@ impl AnimatedImage {
}
pub fn get_image_by_index(&self, index: usize) -> Arc<ColorImage> {
self.frames[index % self.frames.len()].clone()
Arc::clone(&self.frames[index % self.frames.len()])
}
}

View File

@@ -190,7 +190,7 @@ impl winit::application::ApplicationHandler<UserEvent> for GlowApp {
let gl = std::sync::Arc::new(gl);
gl_window.window().set_visible(true);
let egui_glow = egui_glow::EguiGlow::new(event_loop, gl.clone(), None, None, true);
let egui_glow = egui_glow::EguiGlow::new(event_loop, Arc::clone(&gl), None, None, true);
let event_loop_proxy = egui::mutex::Mutex::new(self.proxy.clone());
egui_glow

View File

@@ -123,7 +123,7 @@ fn adjust_color_mode(
match color_mode {
color::ColorMode::Solid(color) => adjust_color(color),
color::ColorMode::UV(callback) => {
let callback = callback.clone();
let callback = Arc::clone(callback);
*color_mode = color::ColorMode::UV(Arc::new(Box::new(move |rect, pos| {
let mut color = callback(rect, pos);
adjust_color(&mut color);

View File

@@ -880,14 +880,14 @@ impl GalleyCache {
let cached = entry.into_mut();
cached.last_used = self.generation;
let galley = cached.galley.clone();
let galley = Arc::clone(&cached.galley);
if let Some(children) = &cached.children {
// The point of `allow_split_paragraphs` is to split large jobs into paragraph,
// and then cache each paragraph individually.
// That way, if we edit a single paragraph, only that paragraph will be re-layouted.
// For that to work we need to keep all the child/paragraph
// galleys alive while the parent galley is alive:
for child_hash in children.clone().iter() {
for child_hash in Arc::clone(children).iter() {
if let Some(cached_child) = self.cache.get_mut(child_hash) {
cached_child.last_used = self.generation;
}
@@ -913,7 +913,7 @@ impl GalleyCache {
CachedGalley {
last_used: self.generation,
children: Some(child_hashes.into()),
galley: galley.clone(),
galley: Arc::clone(&galley),
},
);
galley
@@ -923,7 +923,7 @@ impl GalleyCache {
entry.insert(CachedGalley {
last_used: self.generation,
children: None,
galley: galley.clone(),
galley: Arc::clone(&galley),
});
galley
}

View File

@@ -876,7 +876,7 @@ impl Galley {
ends_with_newline |= !is_last_galley && is_last_row_in_galley;
super::PlacedRow {
pos: new_pos,
row: placed_row.row.clone(),
row: Arc::clone(&placed_row.row),
ends_with_newline,
}
}));

View File

@@ -32,7 +32,7 @@ impl Clone for TextureHandle {
fn clone(&self) -> Self {
self.tex_mngr.write().retain(self.id);
Self {
tex_mngr: self.tex_mngr.clone(),
tex_mngr: Arc::clone(&self.tex_mngr),
id: self.id,
}
}

View File

@@ -75,7 +75,7 @@ impl MyApp {
// Clone locals so we can move them into the paint callback:
let angle = self.angle;
let rotating_triangle = self.rotating_triangle.clone();
let rotating_triangle = Arc::clone(&self.rotating_triangle);
let callback = egui::PaintCallback {
rect,

View File

@@ -1,8 +1,10 @@
use eframe::{EframePumpStatus, UserEvent, egui};
use std::{cell::Cell, io, os::fd::AsRawFd as _, rc::Rc, time::Duration};
use tokio::task::LocalSet;
use winit::event_loop::{ControlFlow, EventLoop};
use eframe::{EframePumpStatus, UserEvent, egui};
pub fn run() -> io::Result<()> {
env_logger::init(); // Log to stderr (if you run with `RUST_LOG=debug`).
let options = eframe::NativeOptions {
@@ -85,7 +87,7 @@ impl eframe::App for MyApp {
self.value.set(self.value.get() + 1);
}
if ui.button("Increment Later").clicked() {
let value = self.value.clone();
let value = Rc::clone(&self.value);
let ctx = ui.ctx().clone();
tokio::task::spawn_local(async move {
tokio::time::sleep(Duration::from_secs(1)).await;

View File

@@ -86,7 +86,7 @@ impl eframe::App for MyApp {
}
if self.show_deferred_viewport.load(Ordering::Relaxed) {
let show_deferred_viewport = self.show_deferred_viewport.clone();
let show_deferred_viewport = Arc::clone(&self.show_deferred_viewport);
ui.ctx().show_viewport_deferred(
egui::ViewportId::from_hash_of("deferred_viewport"),
egui::ViewportBuilder::default()

View File

@@ -129,7 +129,7 @@ impl eframe::App for MyApp {
}
if self.show_deferred_viewport.load(Ordering::Relaxed) {
let show_deferred_viewport = self.show_deferred_viewport.clone();
let show_deferred_viewport = Arc::clone(&self.show_deferred_viewport);
ui.ctx().show_viewport_deferred(
egui::ViewportId::from_hash_of("deferred_viewport"),
egui::ViewportBuilder::default()

View File

@@ -92,7 +92,7 @@ impl eframe::App for MyApp {
.unwrap();
self.save_to_file = false;
}
self.screenshot = Some(image.clone());
self.screenshot = Some(Arc::clone(image));
}
}
});

View File

@@ -1,6 +1,8 @@
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
#![allow(rustdoc::missing_crate_level_docs)] // it's an example
use std::sync::Arc;
use eframe::egui;
use eframe::egui::{Rangef, Shape, UiKind};
use egui_extras::Column;
@@ -158,7 +160,7 @@ impl eframe::App for MyApp {
row.col(|ui| {
ui.style_mut().wrap_mode = Some(egui::TextWrapMode::Extend);
ui.label("See stack below");
cell_stack = Some(ui.stack().clone());
cell_stack = Some(Arc::clone(ui.stack()));
});
});
});
@@ -253,7 +255,7 @@ fn full_span_horizontal_range(ui_stack: &egui::UiStack) -> Rangef {
}
fn stack_ui(ui: &mut egui::Ui) {
let ui_stack = ui.stack().clone();
let ui_stack = Arc::clone(ui.stack());
ui.scope(|ui| {
stack_ui_impl(ui, &ui_stack);
});

View File

@@ -91,7 +91,7 @@ impl ViewportState {
if ui.input(|i| i.viewport().close_requested()) {
vp_state.visible = false;
}
let count = count.clone();
let count = Arc::clone(&count);
show_as_popup(ui, class, move |ui: &mut egui::Ui| {
let current_count = *count.read();
ui.label(format!("Callback has been reused {current_count} times"));
@@ -289,7 +289,7 @@ fn generic_ui(ui: &mut egui::Ui, children: &[Arc<RwLock<ViewportState>>], close_
*visible
};
if visible {
ViewportState::show(child.clone(), &ctx, close_button);
ViewportState::show(Arc::clone(child), &ctx, close_button);
}
}
}