diff --git a/crates/eframe/src/native/run.rs b/crates/eframe/src/native/run.rs index 100d18bf1..108219614 100644 --- a/crates/eframe/src/native/run.rs +++ b/crates/eframe/src/native/run.rs @@ -945,7 +945,7 @@ mod glow_integration { ); #[cfg(feature = "accesskit")] { - let window = gl_window.windows.get(&ViewportId::MAIN).unwrap(); + let window = &gl_window.windows[&ViewportId::MAIN]; let window = &mut *window.write(); integration.init_accesskit( window.egui_winit.as_mut().unwrap(), @@ -1303,7 +1303,7 @@ mod glow_integration { // This will only happen if the viewport is sync // That means that the viewport cannot be rendered by itself and needs his parent to be rendered { - let win = glutin_ctx.read().windows.get(&viewport_id).unwrap().clone(); + let win = &glutin_ctx.read().windows[&viewport_id].clone(); if win.read().render.is_none() && viewport_id != ViewportId::MAIN { if let Some(win) = glutin_ctx.read().windows.get(&win.read().parent_id) { if let Some(w) = win.read().window.as_ref() { @@ -1776,22 +1776,16 @@ mod wgpu_integration { use super::*; #[derive(Clone)] - pub struct Windows( - Arc< - RwLock< - HashMap< - ViewportId, - ( - Option>>, - Arc>>, - Option>>, - ViewportId, - ViewportBuilder, - ), - >, - >, - >, - ); + pub struct Window { + window: Option>>, + state: Arc>>, + render: Option>>, + parent_id: ViewportId, + builder: ViewportBuilder, + } + + #[derive(Clone)] + pub struct Windows(Arc>>); #[allow(unsafe_code)] unsafe impl Send for Windows {} @@ -1799,20 +1793,7 @@ mod wgpu_integration { unsafe impl Sync for Windows {} impl std::ops::Deref for Windows { - type Target = Arc< - RwLock< - HashMap< - ViewportId, - ( - Option>>, - Arc>>, - Option>>, - ViewportId, - ViewportBuilder, - ), - >, - >, - >; + type Target = Arc>>; fn deref(&self) -> &Self::Target { &self.0 @@ -1887,7 +1868,16 @@ mod wgpu_integration { fn build_windows(&mut self, event_loop: &EventLoopWindowTarget) { let Some(running) = &mut self.running else {return}; - for (id, (window, state, _, _, builder)) in running.windows.write().iter_mut() { + for ( + id, + Window { + window, + state, + builder, + .. + }, + ) in running.windows.write().iter_mut() + { if window.is_some() { continue; } @@ -1928,10 +1918,15 @@ mod wgpu_integration { fn set_window(&mut self, id: ViewportId) -> std::result::Result<(), egui_wgpu::WgpuError> { if let Some(running) = &mut self.running { - if let Some((Some(window), _, _, _, _)) = running.windows.read().get(&id) { - return pollster::block_on( - running.painter.write().set_window(id, Some(&window.read())), - ); + if let Some(Window { window, .. }) = running.windows.read().get(&id) { + let window = window.clone(); + if let Some(win) = &window { + return pollster::block_on( + running.painter.write().set_window(id, Some(&*win.read())), + ); + } else { + return pollster::block_on(running.painter.write().set_window(id, None)); + }; } } Ok(()) @@ -2036,13 +2031,13 @@ mod wgpu_integration { let windows = Windows(Arc::new(RwLock::new(HashMap::default()))); windows.write().insert( ViewportId::MAIN, - ( - Some(Arc::new(RwLock::new(window))), - Arc::new(RwLock::new(Some(state))), - None, - ViewportId::MAIN, + Window { + window: Some(Arc::new(RwLock::new(window))), + state: Arc::new(RwLock::new(Some(state))), + render: None, + parent_id: ViewportId::MAIN, builder, - ), + }, ); let _windows = windows.clone(); @@ -2057,7 +2052,7 @@ mod wgpu_integration { move |viewport_builder, viewport_id, parent_viewport_id, render| { if _windows.read().get(&viewport_id).is_none(){ let mut _windows = _windows.write(); - let (window, state, _, _, _) = _windows.entry(viewport_id).or_insert((None, Arc::new(RwLock::new(None)), None, viewport_id, viewport_builder.clone())); + let Window{window, state, ..} = _windows.entry(viewport_id).or_insert(Window{window: None, state: Arc::new(RwLock::new(None)), render: None, parent_id: viewport_id, builder: viewport_builder.clone()}); let event_loop; @@ -2072,8 +2067,8 @@ mod wgpu_integration { if let Some(window) = window { let output; { - if let Some(winit_state) = &mut *window.1.write() { - if let Some(win) = window.0.clone() { + if let Some(winit_state) = &mut *window.state.write() { + if let Some(win) = window.window { let win = win.read(); let mut input = winit_state.take_egui_input(&win); input.time = Some(time.elapsed().as_secs_f64()); @@ -2120,8 +2115,8 @@ mod wgpu_integration { viewports.retain_mut(|(id, parent, _builder, render)| { if let Some(w) = _windows.write().get_mut(id) { - w.2 = render.clone(); - w.3 = *parent; + w.render = render.clone(); + w.parent_id = *parent; active_viewports_ids.push(*id); false } else { @@ -2132,7 +2127,7 @@ mod wgpu_integration { for (id, parent, builder, render) in viewports { _windows.write().insert( id, - (None, Arc::new(RwLock::new(None)), render, parent, builder), + Window{window: None, state: Arc::new(RwLock::new(None)), render, parent_id: parent, builder}, ); active_viewports_ids.push(id); } @@ -2140,7 +2135,8 @@ mod wgpu_integration { egui_winit::process_viewports_commands( output.viewport_commands, *focused.read(), - |id| _windows.read().get(&id).and_then(|w| w.0.clone()), + |id| _windows.read().get(&id).and_then(|w| w.window.clone()) +, ); } } @@ -2188,7 +2184,7 @@ mod wgpu_integration { r.windows_id .read() .get(&window_id) - .and_then(|id| r.windows.read().get(id).map(|w| w.0.clone())) + .and_then(|id| r.windows.read().get(id).map(|w| w.window.clone())) }) .flatten() } @@ -2198,13 +2194,13 @@ mod wgpu_integration { r.windows .read() .get(&id) - .and_then(|w| w.0.as_ref().map(|w| w.read().id())) + .and_then(|w| w.window.as_ref().map(|w| w.read().id())) }) } fn save_and_destroy(&mut self) { if let Some(mut running) = self.running.take() { - if let Some((window, _, _, _, _)) = running.windows.read().get(&ViewportId::MAIN) { + if let Some(Window { window, .. }) = running.windows.read().get(&ViewportId::MAIN) { running .integration .write() @@ -2244,11 +2240,11 @@ mod wgpu_integration { viewport_commands, }; { - let Some((viewport_id, (Some(window), state, render, parent_viewport_id, _))) = windows_id.read().get(&window_id).and_then(|id|(windows.read().get(id).map(|w|(*id, w.clone())))) else{return vec![]}; + let Some((viewport_id, Window{window: Some(window), state, render, parent_id, ..})) = windows_id.read().get(&window_id).and_then(|id|(windows.read().get(id).map(|w|(*id, w.clone())))) else{return vec![]}; // This is used to not render a viewport if is sync if viewport_id != ViewportId::MAIN && render.is_none() { - if let Some(window) = running.windows.read().get(&parent_viewport_id) { - if let Some(w) = window.0.as_ref() { + if let Some(window) = running.windows.read().get(&parent_id) { + if let Some(w) = window.window.as_ref() { return vec![EventResult::RepaintNow(w.read().id())]; } } @@ -2274,7 +2270,7 @@ mod wgpu_integration { state.write().as_mut().unwrap(), &render.clone(), viewport_id, - parent_viewport_id, + parent_id, ); integration.write().handle_platform_output( @@ -2310,8 +2306,8 @@ mod wgpu_integration { viewports.retain_mut(|(id, parent, _builder, render)| { if let Some(w) = windows.write().get_mut(id) { - w.2 = render.clone(); - w.3 = *parent; + w.render = render.clone(); + w.parent_id = *parent; active_viewports_ids.push(*id); false } else { @@ -2322,7 +2318,13 @@ mod wgpu_integration { for (id, parent, builder, render) in viewports { windows.write().insert( id, - (None, Arc::new(RwLock::new(None)), render, parent, builder), + Window { + window: None, + state: Arc::new(RwLock::new(None)), + render, + parent_id: parent, + builder, + }, ); active_viewports_ids.push(id); } @@ -2330,7 +2332,12 @@ mod wgpu_integration { egui_winit::process_viewports_commands( viewport_commands, *self.is_focused.read(), - |viewport_id| windows.read().get(&viewport_id).and_then(|w| w.0.clone()), + |viewport_id| { + windows + .read() + .get(&viewport_id) + .and_then(|w| w.window.clone()) + }, ); windows @@ -2346,8 +2353,10 @@ mod wgpu_integration { control_flow.push(if integration.read().should_close() { EventResult::Exit } else if repaint_after.1.is_zero() { - if let Some((Some(window), _, _, _, _)) = - windows.read().get(&repaint_after.0) + if let Some(Window { + window: Some(window), + .. + }) = windows.read().get(&repaint_after.0) { EventResult::RepaintNext(window.read().id()) } else { @@ -2361,8 +2370,10 @@ mod wgpu_integration { // technically, this might lead to some weird corner cases where the user *WANTS* // winit to use `WaitUntil(MAX_INSTANT)` explicitly. they can roll their own // egui backend impl i guess. - if let Some((Some(window), _, _, _, _)) = - windows.read().get(&repaint_after.0) + if let Some(Window { + window: Some(window), + .. + }) = windows.read().get(&repaint_after.0) { EventResult::RepaintAt(window.read().id(), repaint_after_instant) } else { @@ -2373,7 +2384,7 @@ mod wgpu_integration { }); } - let Some((_, (Some(window), _, _, _, _))) = windows_id.read().get(&window_id).and_then(|id|(windows.read().get(id).map(|w|(*id, w.clone())))) else{return vec![]}; + let Some((_, Window{window: Some(window), ..})) = windows_id.read().get(&window_id).and_then(|id|(windows.read().get(id).map(|w|(*id, w.clone())))) else{return vec![]}; integration .write() .maybe_autosave(app.as_mut(), window.clone()); @@ -2432,7 +2443,7 @@ mod wgpu_integration { .read() .get(&ViewportId::MAIN) .unwrap() - .0 + .window .as_ref() .unwrap() .read() @@ -2510,7 +2521,7 @@ mod wgpu_integration { _ => {} }; - let event_response = if let Some((id, (_, state, _, _, _))) = + let event_response = if let Some((id, Window { state, .. })) = running.windows_id.read().get(window_id).and_then(|id| { running.windows.read().get(id).map(|w| (*id, w.clone())) }) { @@ -2552,7 +2563,7 @@ mod wgpu_integration { accesskit_winit::ActionRequestEvent { request, window_id }, )) => { if let Some(running) = &mut self.running { - if let Some((_, state, _, _, _)) = running + if let Some(Window { state, .. }) = running .windows_id .read() .get(window_id) diff --git a/crates/egui/src/context.rs b/crates/egui/src/context.rs index 7b3538677..4ff4212f6 100644 --- a/crates/egui/src/context.rs +++ b/crates/egui/src/context.rs @@ -209,19 +209,7 @@ struct ContextImpl { >, viewport_commands: Vec<(ViewportId, ViewportCommand)>, - render_sync: Option< - Arc< - Box< - dyn for<'a> Fn( - ViewportBuilder, - ViewportId, - ViewportId, - Box, - ) + Send - + Sync, - >, - >, - >, + render_sync: Option>>, viewport_counter: u64, is_desktop: bool, @@ -312,12 +300,12 @@ impl ContextImpl { self.frame_state .entry(viewport_id) .or_default() - .begin_frame(self.input.get(&viewport_id).unwrap()); + .begin_frame(&self.input[&viewport_id]); self.update_fonts_mut(); // Ensure we register the background area so panels and background ui can catch clicks: - let input = self.input.get(&viewport_id).unwrap(); + let input = &self.input[&viewport_id]; let screen_rect = input.screen_rect(); self.memory.areas.set_state( LayerId::background(), @@ -694,7 +682,7 @@ impl Context { /// Read-only access to [`FrameState`]. #[inline] pub(crate) fn frame_state(&self, reader: impl FnOnce(&FrameState) -> R) -> R { - self.read(move |ctx| reader(ctx.frame_state.get(&ctx.get_viewport_id()).unwrap())) + self.read(move |ctx| reader(&ctx.frame_state[&ctx.get_viewport_id()])) } /// Read-write access to [`FrameState`]. @@ -882,19 +870,14 @@ impl Context { .push((id, interact_rect)); if hovered { - let pointer_pos = ctx - .input - .get(&ctx.get_viewport_id()) - .unwrap() - .pointer - .interact_pos(); + let pointer_pos = &ctx.input[&ctx.get_viewport_id()].pointer.interact_pos(); if let Some(pointer_pos) = pointer_pos { if let Some(rects) = ctx.layer_rects_prev_frame.get(&layer_id) { for &(prev_id, prev_rect) in rects.iter().rev() { if prev_id == id { break; // there is no other interactive widget covering us at the pointer position. } - if prev_rect.contains(pointer_pos) { + if prev_rect.contains(*pointer_pos) { // Another interactive widget is covering us at the pointer position, // so we aren't hovered. @@ -1506,7 +1489,7 @@ impl Context { let textures_delta = self.write(|ctx| { ctx.memory.end_frame( - ctx.input.get(&ctx.get_viewport_id()).unwrap(), + &ctx.input[&ctx.get_viewport_id()], &viewports, &ctx.frame_state .entry(ctx.get_viewport_id()) @@ -1723,11 +1706,7 @@ impl Context { /// How much space is used by panels and windows. pub fn used_rect(&self) -> Rect { self.read(|ctx| { - let mut used = ctx - .frame_state - .get(&ctx.get_viewport_id()) - .unwrap() - .used_by_panels; + let mut used = ctx.frame_state[&ctx.get_viewport_id()].used_by_panels; for window in ctx.memory.areas.visible_windows() { used = used.union(window.rect()); } @@ -1905,7 +1884,7 @@ impl Context { pub fn animate_bool_with_time(&self, id: Id, target_value: bool, animation_time: f32) -> f32 { let animated_value = self.write(|ctx| { ctx.animation_manager.animate_bool( - ctx.input.get(&ctx.get_viewport_id()).unwrap(), + &ctx.input[&ctx.get_viewport_id()], animation_time, id, target_value, @@ -1925,7 +1904,7 @@ impl Context { pub fn animate_value_with_time(&self, id: Id, target_value: f32, animation_time: f32) -> f32 { let animated_value = self.write(|ctx| { ctx.animation_manager.animate_value( - ctx.input.get(&ctx.get_viewport_id()).unwrap(), + &ctx.input[&ctx.get_viewport_id()], animation_time, id, target_value, diff --git a/crates/egui/src/viewport.rs b/crates/egui/src/viewport.rs index 81632826e..2dfdae6fc 100644 --- a/crates/egui/src/viewport.rs +++ b/crates/egui/src/viewport.rs @@ -24,9 +24,14 @@ impl ViewportId { /// This is used to render an async viewport pub type ViewportRender = dyn Fn(&Context) + Sync + Send; +pub type ViewportRenderSyncCallback = dyn for<'a> Fn(ViewportBuilder, ViewportId, ViewportId, Box) + + Send + + Sync; + /// The filds in this struct should not be change directly, but is not problem tho! /// Every thing is wrapped in Option<> indicates that thing should not be changed! #[derive(PartialEq, Eq, Clone)] +#[allow(clippy::option_option)] pub struct ViewportBuilder { pub id: Id, pub title: String, diff --git a/examples/viewports/src/main.rs b/examples/viewports/src/main.rs index 807fd83ff..e0babc547 100644 --- a/examples/viewports/src/main.rs +++ b/examples/viewports/src/main.rs @@ -1,15 +1,10 @@ +use egui::mutex::RwLock; use std::sync::Arc; -use std::sync::RwLock; use eframe::egui; use eframe::egui::ViewportBuilder; use eframe::NativeOptions; -#[cfg(feature = "wgpu")] -const RENDERER: eframe::Renderer = eframe::Renderer::Wgpu; -#[cfg(not(feature = "wgpu"))] -const RENDERER: eframe::Renderer = eframe::Renderer::Glow; - #[derive(Default)] pub struct App { show_async_viewport: bool, @@ -58,10 +53,10 @@ impl eframe::App for App { ctx.create_viewport( ViewportBuilder::new("Async Viewport").with_title("Async Viewport"), move |ctx| { - let mut state = state.write().unwrap(); + let mut state = state.write(); - let mut show_async_viewport2 = show_async_viewport2.write().unwrap(); - let mut show_sync_viewport2 = show_sync_viewport2.write().unwrap(); + let mut show_async_viewport2 = show_async_viewport2.write(); + let mut show_sync_viewport2 = show_sync_viewport2.write(); let async_viewport_state2 = async_viewport_state2.clone(); let sync_viewport_state2 = sync_viewport_state2.clone(); @@ -72,7 +67,7 @@ impl eframe::App for App { ui.checkbox(&mut show_async_viewport2, "Show Async Viewport 2"); ui.checkbox(&mut show_sync_viewport2, "Show Sync Viewport 2"); - ui.label(format!("Count: {state}")); + ui.label(format!("Count: {}", *state)); if ui.button("Add").clicked() { *state += 1; } @@ -82,12 +77,12 @@ impl eframe::App for App { ViewportBuilder::new("Async Viewport in Async Viewport") .with_title("Async Viewport in Async Viewport"), move |ctx| { - let mut state = async_viewport_state2.write().unwrap(); + let mut state = async_viewport_state2.write(); let content = move |ui: &mut egui::Ui| { ui_info(ui); - ui.label(format!("Count: {state}")); + ui.label(format!("Count: {}", *state)); if ui.button("Add").clicked() { *state += 1; } @@ -107,12 +102,12 @@ impl eframe::App for App { ViewportBuilder::new("Sync Viewport in Async Viewport") .with_title("Sync Viewport in Async Viewport"), move |ctx| { - let mut state = sync_viewport_state2.write().unwrap(); + let mut state = sync_viewport_state2.write(); let content = move |ui: &mut egui::Ui| { ui_info(ui); - ui.label(format!("Count: {state}")); + ui.label(format!("Count: {}", *state)); if ui.button("Add").clicked() { *state += 1; } @@ -156,12 +151,12 @@ impl eframe::App for App { ViewportBuilder::new("Async Viewport in Sync Viewport") .with_title("Async Viewport in Sync Viewport"), move |ctx| { - let mut state = async_viewport_state3.write().unwrap(); + let mut state = async_viewport_state3.write(); let content = move |ui: &mut egui::Ui| { ui_info(ui); - ui.label(format!("Count: {state}")); + ui.label(format!("Count: {}", *state)); if ui.button("Add").clicked() { *state += 1; } @@ -186,7 +181,7 @@ impl eframe::App for App { let content = move |ui: &mut egui::Ui| { ui_info(ui); - ui.label(format!("Count: {state}")); + ui.label(format!("Count: {}", *state)); if ui.button("Add").clicked() { *state += 1; } @@ -237,7 +232,9 @@ fn main() { let _ = eframe::run_native( "Viewports", NativeOptions { - renderer: RENDERER, + #[cfg(feature = "wgpu")] + renderer: eframe::Renderer::Wgpu, + initial_window_size: Some(egui::Vec2::new(400.0, 220.0)), ..NativeOptions::default() },